diff -Nru a/Makefile b/Makefile --- a/Makefile Sat Sep 21 21:25:45 2002 +++ b/Makefile Sat Sep 21 21:25:45 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 37 +SUBLEVEL = 38 EXTRAVERSION = # *DOCUMENTATION* diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Sat Sep 21 21:25:45 2002 +++ b/arch/i386/kernel/vm86.c Sat Sep 21 21:25:45 2002 @@ -261,7 +261,7 @@ "movl %0,%%esp\n\t" "jmp resume_userspace" : /* no outputs */ - :"r" (&info->regs), "b" (tsk) : "ax"); + :"r" (&info->regs), "b" (tsk->thread_info) : "ax"); /* we never return here */ } @@ -273,7 +273,7 @@ regs32->eax = retval; __asm__ __volatile__("movl %0,%%esp\n\t" "jmp resume_userspace" - : : "r" (regs32), "b" (current)); + : : "r" (regs32), "b" (current_thread_info())); } static inline void set_IF(struct kernel_vm86_regs * regs) diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Sat Sep 21 21:25:43 2002 +++ b/arch/ia64/Makefile Sat Sep 21 21:25:45 2002 @@ -86,11 +86,10 @@ HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o -SUBDIRS := arch/$(ARCH)/tools arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib $(SUBDIRS) -CORE_FILES := arch/$(ARCH)/kernel/kernel.o arch/$(ARCH)/mm/mm.o $(CORE_FILES) - -LIBS := $(TOPDIR)/arch/$(ARCH)/lib/lib.a $(LIBS) \ - $(TOPDIR)/arch/$(ARCH)/lib/lib.a +libs-y += arch/$(ARCH)/lib/ +core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ +drivers-$(CONFIG_PCI) += arch/$(ARCH)/pci/ +drivers-$(CONFIG_IA64_HP_ZX1) += arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot @@ -102,30 +101,14 @@ rawboot: @$(MAKEBOOT) rawboot -# -# My boot writes directly to a specific disk partition, I doubt most -# people will want to do that without changes.. -# -msb my-special-boot: - @$(MAKEBOOT) msb - -bootimage: - @$(MAKEBOOT) bootimage - -srmboot: - @$(MAKEBOOT) srmboot - archclean: @$(MAKEBOOT) clean archmrproper: @$(MAKE) -C arch/$(ARCH)/tools mrproper -bootpfile: - @$(MAKEBOOT) bootpfile - prepare: $(TOPDIR)/include/asm-ia64/offsets.h $(TOPDIR)/include/asm-ia64/offsets.h: include/asm include/linux/version.h \ include/config/MARKER - @$(MAKE) -C arch/$(ARCH)/tools $@ \ No newline at end of file + @$(MAKE) -C arch/$(ARCH)/tools $@ diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in --- a/arch/ia64/config.in Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/config.in Sat Sep 21 21:25:48 2002 @@ -68,6 +68,7 @@ then bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA define_bool CONFIG_PM y + define_bool CONFIG_IOSAPIC y fi if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then @@ -85,6 +86,31 @@ fi define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore. + +define_int CONFIG_FORCE_MAX_ZONEORDER 18 + +bool 'IA-64 Huge TLB Page Support' CONFIG_HUGETLB_PAGE + +if [ "$CONFIG_HUGETLB_PAGE" = "y" ]; then + if [ "$CONFIG_MCKINLEY" = "y" ]; then + choice ' IA-64 Huge TLB Page Size' \ + "4GB CONFIG_HUGETLB_PAGE_SIZE_4GB \ + 256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \ + 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \ + 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \ + 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \ + 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \ + 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB + else + choice ' IA-64 Huge TLB Page Size' \ + "256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \ + 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \ + 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \ + 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \ + 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \ + 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB + fi +fi bool 'SMP support' CONFIG_SMP bool 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT diff -Nru a/arch/ia64/hp/Makefile b/arch/ia64/hp/Makefile --- a/arch/ia64/hp/Makefile Sat Sep 21 21:25:46 2002 +++ b/arch/ia64/hp/Makefile Sat Sep 21 21:25:46 2002 @@ -7,7 +7,6 @@ subdir-$(CONFIG_IA64_GENERIC) += $(ALL_SUB_DIRS) subdir-$(CONFIG_IA64_HP_SIM) += sim -subdir-$(CONFIG_IA64_HP_ZX1) += zx1 common SUB_DIRS := $(subdir-y) obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) diff -Nru a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile --- a/arch/ia64/hp/common/Makefile Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/hp/common/Makefile Sat Sep 21 21:25:48 2002 @@ -5,8 +5,6 @@ # Copyright (C) Alex Williamson (alex_williamson@hp.com) # -O_TARGET := common.o - export-objs := sba_iommu.o obj-y := sba_iommu.o diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c --- a/arch/ia64/hp/common/sba_iommu.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/hp/common/sba_iommu.c Sat Sep 21 21:25:45 2002 @@ -39,9 +39,7 @@ #define DRIVER_NAME "SBA" -#ifndef CONFIG_IA64_HP_PROTO #define ALLOW_IOV_BYPASS -#endif #define ENABLE_MARK_CLEAN /* ** The number of debug flags is a clue - this code is fragile. @@ -740,6 +738,9 @@ unsigned long phys_addr = virt_to_phys(addr); #endif + if (!sba_list) + panic("sba_map_single: no SBA found!\n"); + ioc = GET_IOC(dev); ASSERT(ioc); @@ -828,6 +829,9 @@ unsigned long flags; dma_addr_t offset; + if (!sba_list) + panic("sba_map_single: no SBA found!\n"); + ioc = GET_IOC(dev); ASSERT(ioc); @@ -1094,6 +1098,9 @@ DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist)); + if (!sba_list) + panic("sba_map_single: no SBA found!\n"); + ioc = GET_IOC(dev); ASSERT(ioc); @@ -1183,6 +1190,9 @@ DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist)); + if (!sba_list) + panic("sba_map_single: no SBA found!\n"); + ioc = GET_IOC(dev); ASSERT(ioc); @@ -1252,10 +1262,6 @@ ** Firmware programs the maximum IOV space size into the imask reg */ iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; -#ifdef CONFIG_IA64_HP_PROTO - if (!iova_space_size) - iova_space_size = GB(1); -#endif /* ** iov_order is always based on a 1GB IOVA space since we want to @@ -1484,66 +1490,65 @@ #ifdef CONFIG_PROC_FS static int sba_proc_info(char *buf, char **start, off_t offset, int len) { - struct sba_device *sba_dev = sba_list; - struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ - int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ + struct sba_device *sba_dev; + struct ioc *ioc; + int total_pages; unsigned long i = 0, avg = 0, min, max; - sprintf(buf, "%s rev %d.%d\n", - "Hewlett Packard zx1 SBA", - ((sba_dev->hw_rev >> 4) & 0xF), - (sba_dev->hw_rev & 0xF) - ); - sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", - buf, - (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ - total_pages); - - sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, - total_pages - ioc->used_pages, ioc->used_pages, - (int) (ioc->used_pages * 100 / total_pages)); - - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ - - min = max = ioc->avg_search[0]; - for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { - avg += ioc->avg_search[i]; - if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; - if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; - } - avg /= SBA_SEARCH_SAMPLE; - sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - buf, min, avg, max); - - sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msingle_calls, ioc->msingle_pages, - (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); + for (sba_dev = sba_list; sba_dev; sba_dev = sba_dev->next) { + ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ + total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ + + sprintf(buf, "%s rev %d.%d\n", "Hewlett Packard zx1 SBA", + ((sba_dev->hw_rev >> 4) & 0xF), (sba_dev->hw_rev & 0xF)); + sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", buf, + (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); + + sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, + total_pages - ioc->used_pages, ioc->used_pages, + (int) (ioc->used_pages * 100 / total_pages)); + + sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", + buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + + min = max = ioc->avg_search[0]; + for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { + avg += ioc->avg_search[i]; + if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; + if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; + } + avg /= SBA_SEARCH_SAMPLE; + sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + buf, min, avg, max); + + sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", + buf, ioc->msingle_calls, ioc->msingle_pages, + (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_single(): %12ld bypasses\n", - buf, ioc->msingle_bypass); + sprintf(buf, "%spci_map_single(): %12ld bypasses\n", + buf, ioc->msingle_bypass); #endif - sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usingle_calls, ioc->usingle_pages, - (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); + sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", + buf, ioc->usingle_calls, ioc->usingle_pages, + (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_unmap_single: %12ld bypasses\n", - buf, ioc->usingle_bypass); + sprintf(buf, "%spci_unmap_single: %12ld bypasses\n", + buf, ioc->usingle_bypass); #endif - sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msg_calls, ioc->msg_pages, - (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); + sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + buf, ioc->msg_calls, ioc->msg_pages, + (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_sg() : %12ld bypasses\n", - buf, ioc->msg_bypass); + sprintf(buf, "%spci_map_sg() : %12ld bypasses\n", + buf, ioc->msg_bypass); #endif - sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usg_calls, ioc->usg_pages, - (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); - + sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + buf, ioc->usg_calls, ioc->usg_pages, + (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); + } return strlen(buf); } @@ -1551,9 +1556,13 @@ sba_resource_map(char *buf, char **start, off_t offset, int len) { struct ioc *ioc = sba_list->ioc; /* FIXME: Multi-IOC support! */ - unsigned int *res_ptr = (unsigned int *)ioc->res_map; + unsigned int *res_ptr; int i; + if (!ioc) + return 0; + + res_ptr = (unsigned int *)ioc->res_map; buf[0] = '\0'; for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { if ((i & 7) == 0) @@ -1593,13 +1602,11 @@ } func_id = READ_REG(hpa + SBA_FUNC_ID); - - if (func_id == ZX1_FUNC_ID_VALUE) { - strcpy(sba_rev, "zx1"); - func_offset = zx1_func_offsets; - } else { + if (func_id != ZX1_FUNC_ID_VALUE) return; - } + + strcpy(sba_rev, "zx1"); + func_offset = zx1_func_offsets; /* Read HW Rev First */ hw_rev = READ_REG(hpa + SBA_FCLASS) & 0xFFUL; @@ -1625,10 +1632,8 @@ device->slot_name, hpa); if ((hw_rev & 0xFF) < 0x20) { - printk(KERN_INFO "%s WARNING rev 2.0 or greater will be required for IO MMU support in the future\n", DRIVER_NAME); -#ifndef CONFIG_IA64_HP_PROTO - panic("%s: CONFIG_IA64_HP_PROTO MUST be enabled to support SBA rev less than 2.0", DRIVER_NAME); -#endif + printk("%s: SBA rev less than 2.0 not supported", DRIVER_NAME); + return; } sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); diff -Nru a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile --- a/arch/ia64/hp/zx1/Makefile Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/hp/zx1/Makefile Sat Sep 21 21:25:48 2002 @@ -1,11 +1,9 @@ # -# ia64/platform/hp/zx1/Makefile +# ia64/hp/zx1/Makefile # # Copyright (C) 2002 Hewlett Packard # Copyright (C) Alex Williamson (alex_williamson@hp.com) # - -O_TARGET := zx1.o obj-y := hpzx1_misc.o obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o diff -Nru a/arch/ia64/hp/zx1/hpzx1_misc.c b/arch/ia64/hp/zx1/hpzx1_misc.c --- a/arch/ia64/hp/zx1/hpzx1_misc.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/hp/zx1/hpzx1_misc.c Sat Sep 21 21:25:45 2002 @@ -25,68 +25,84 @@ static int hpzx1_devices; struct fake_pci_dev { + struct fake_pci_dev *next; + struct pci_dev *pci_dev; unsigned long csr_base; unsigned long csr_size; unsigned long mapped_csrs; // ioremapped int sizing; // in middle of BAR sizing operation? -}; +} *fake_pci_dev_list; static struct pci_ops *orig_pci_ops; -#define HP_CFG_RD(sz, bits, name) \ -static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) \ -{ \ - struct fake_pci_dev *fake_dev; \ - if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata)) \ - return orig_pci_ops->name(dev, where, value); \ - \ - if (where == PCI_BASE_ADDRESS_0) { \ - if (fake_dev->sizing) \ - *value = ~(fake_dev->csr_size - 1); \ - else \ - *value = (fake_dev->csr_base & \ - PCI_BASE_ADDRESS_MEM_MASK) | \ - PCI_BASE_ADDRESS_SPACE_MEMORY; \ - fake_dev->sizing = 0; \ - return PCIBIOS_SUCCESSFUL; \ - } \ - *value = read##sz(fake_dev->mapped_csrs + where); \ - if (where == PCI_COMMAND) \ - *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ \ - return PCIBIOS_SUCCESSFUL; \ +struct fake_pci_dev * +lookup_fake_dev (struct pci_bus *bus, unsigned int devfn) +{ + struct fake_pci_dev *fake_dev; + + for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next) + if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn) + return fake_dev; + return NULL; } -#define HP_CFG_WR(sz, bits, name) \ -static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value) \ -{ \ - struct fake_pci_dev *fake_dev; \ - \ - if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata)) \ - return orig_pci_ops->name(dev, where, value); \ - \ - if (where == PCI_BASE_ADDRESS_0) { \ - if (value == (u##bits) ~0) \ - fake_dev->sizing = 1; \ - return PCIBIOS_SUCCESSFUL; \ - } else \ - write##sz(value, fake_dev->mapped_csrs + where); \ - return PCIBIOS_SUCCESSFUL; \ +static int +hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) +{ + struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); + + if (!fake_dev) + return (*orig_pci_ops->read)(bus, devfn, where, size, value); + + if (where == PCI_BASE_ADDRESS_0) { + if (fake_dev->sizing) + *value = ~(fake_dev->csr_size - 1); + else + *value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK) + | PCI_BASE_ADDRESS_SPACE_MEMORY); + fake_dev->sizing = 0; + return PCIBIOS_SUCCESSFUL; + } + switch (size) { + case 1: *value = readb(fake_dev->mapped_csrs + where); break; + case 2: *value = readw(fake_dev->mapped_csrs + where); break; + case 4: *value = readl(fake_dev->mapped_csrs + where); break; + default: + printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size); + break; + } + if (where == PCI_COMMAND) + *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ + return PCIBIOS_SUCCESSFUL; } -HP_CFG_RD(b, 8, read_byte) -HP_CFG_RD(w, 16, read_word) -HP_CFG_RD(l, 32, read_dword) -HP_CFG_WR(b, 8, write_byte) -HP_CFG_WR(w, 16, write_word) -HP_CFG_WR(l, 32, write_dword) +static int +hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +{ + struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); + + if (!fake_dev) + return (*orig_pci_ops->write)(bus, devfn, where, size, value); + + if (where == PCI_BASE_ADDRESS_0) { + if (value == ((1UL << 8*size) - 1)) + fake_dev->sizing = 1; + return PCIBIOS_SUCCESSFUL; + } + switch (size) { + case 1: writeb(value, fake_dev->mapped_csrs + where); break; + case 2: writew(value, fake_dev->mapped_csrs + where); break; + case 4: writel(value, fake_dev->mapped_csrs + where); break; + default: + printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size); + break; + } + return PCIBIOS_SUCCESSFUL; +} static struct pci_ops hp_pci_conf = { - hp_cfg_readb, - hp_cfg_readw, - hp_cfg_readl, - hp_cfg_writeb, - hp_cfg_writew, - hp_cfg_writel, + .read = hp_cfg_read, + .write = hp_cfg_write }; static void @@ -143,6 +159,10 @@ bus->ops = &hp_pci_conf; // replace pci ops for this bus + fake->pci_dev = dev; + fake->next = fake_pci_dev_list; + fake_pci_dev_list = fake; + memset(dev, 0, sizeof(*dev)); dev->bus = bus; dev->sysdata = fake; @@ -309,57 +329,20 @@ * HWP0003: AGP LBA device */ acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL); -#ifdef CONFIG_IA64_HP_PROTO - if (hpzx1_devices) { -#endif acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL); acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL); - -#ifdef CONFIG_IA64_HP_PROTO - } - -#define ZX1_FUNC_ID_VALUE (PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP - /* - * Early protos don't have bridges in the ACPI namespace, so - * if we didn't find anything, add the things we know are - * there. - */ - if (hpzx1_devices == 0) { - u64 hpa, csr_base; - - csr_base = 0xfed00000UL; - hpa = (u64) ioremap(csr_base, 0x2000); - if (__raw_readl(hpa) == ZX1_FUNC_ID_VALUE) { - hpzx1_fake_pci_dev("HWP0001 SBA", 0, csr_base, 0x1000); - hpzx1_fake_pci_dev("HWP0001 IOC", 0, csr_base + 0x1000, - 0x1000); - - csr_base = 0xfed24000UL; - iounmap(hpa); - hpa = (u64) ioremap(csr_base, 0x1000); - hpzx1_fake_pci_dev("HWP0003 AGP LBA", 0x40, csr_base, - 0x1000); - } - iounmap(hpa); - } -#endif } extern void sba_init(void); -void -hpzx1_pci_fixup (int phase) +static void +hpzx1_init (void) { - iosapic_pci_fixup(phase); - switch (phase) { - case 0: - /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */ - MAX_DMA_ADDRESS = ~0UL; - break; + /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */ + MAX_DMA_ADDRESS = ~0UL; - case 1: - hpzx1_acpi_dev_init(); - sba_init(); - break; - } + hpzx1_acpi_dev_init(); + sba_init(); } + +subsys_initcall(hpzx1_init); diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Sat Sep 21 21:25:46 2002 +++ b/arch/ia64/ia32/sys_ia32.c Sat Sep 21 21:25:46 2002 @@ -2111,8 +2111,8 @@ }; struct ipc_kludge { - struct msgbuf *msgp; - long msgtyp; + u32 msgp; + s32 msgtyp; }; #define SEMOP 1 diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/Makefile Sat Sep 21 21:25:45 2002 @@ -2,7 +2,6 @@ # Makefile for the linux kernel. # -O_TARGET := kernel.o EXTRA_TARGETS := head.o init_task.o export-objs := ia64_ksyms.o @@ -10,12 +9,9 @@ obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \ machvec.o pal.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \ signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o -obj-$(CONFIG_IA64_GENERIC) += iosapic.o -obj-$(CONFIG_IA64_HP_ZX1) += iosapic.o -obj-$(CONFIG_IA64_DIG) += iosapic.o +obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_EFI_VARS) += efivars.o -obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/acpi.c Sat Sep 21 21:25:45 2002 @@ -58,6 +58,8 @@ unsigned char acpi_kbd_controller_present = 1; +int acpi_disabled __initdata; /* XXX this shouldn't be needed---we can't boot without ACPI! */ + const char * acpi_get_sysname (void) { @@ -608,7 +610,7 @@ * gets interrupts such as power and sleep buttons. If it's not * on a Legacy interrupt, it needs to be setup. */ - if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1) + if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1) printk(KERN_ERR PREFIX "Can't find FADT\n"); #ifdef CONFIG_SERIAL_8250_ACPI diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/efi.c Sat Sep 21 21:25:45 2002 @@ -33,6 +33,15 @@ #define EFI_DEBUG 0 +#ifdef CONFIG_HUGETLB_PAGE + +/* By default at total of 512MB is reserved huge pages. */ +#define HTLBZONE_SIZE_DEFAULT 0x20000000 + +unsigned long htlbzone_pages = (HTLBZONE_SIZE_DEFAULT >> HPAGE_SHIFT); + +#endif + extern efi_status_t efi_call_phys (void *, ...); struct efi efi; @@ -399,6 +408,25 @@ ++cp; } } +#ifdef CONFIG_HUGETLB_PAGE + /* Just duplicating the above algo for lpzone start */ + for (cp = saved_command_line; *cp; ) { + if (memcmp(cp, "lpmem=", 6) == 0) { + cp += 6; + htlbzone_pages = memparse(cp, &end); + htlbzone_pages = (htlbzone_pages >> HPAGE_SHIFT); + if (end != cp) + break; + cp = end; + } else { + while (*cp != ' ' && *cp) + ++cp; + while (*cp == ' ') + ++cp; + } + } + printk("Total HugeTLB_Page memory pages requested 0x%lx \n", htlbzone_pages); +#endif if (mem_limit != ~0UL) printk("Ignoring memory above %luMB\n", mem_limit >> 20); diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/entry.S Sat Sep 21 21:25:45 2002 @@ -90,15 +90,23 @@ br.ret.sptk.many rp END(ia64_execve) +/* + * sys_clone2(u64 flags, u64 ustack_base, u64 ustack_size, u64 user_tid, u64 tls) + */ GLOBAL_ENTRY(sys_clone2) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) - alloc r16=ar.pfs,3,2,4,0 + alloc r16=ar.pfs,5,2,5,0 DO_SAVE_SWITCH_STACK + adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp mov loc0=rp mov loc1=r16 // save ar.pfs across do_fork .body mov out1=in1 mov out3=in2 + tbit.nz p6,p0=in0,CLONE_SETTLS_BIT + mov out4=in3 // valid only w/CLONE_SETTID and/or CLONE_CLEARTID + ;; +(p6) st8 [r2]=in4 // store TLS in r13 (tp) adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK br.call.sptk.many rp=do_fork @@ -115,15 +123,24 @@ br.ret.sptk.many rp END(sys_clone2) +/* + * sys_clone(u64 flags, u64 ustack_base, u64 user_tid, u64 tls) + * Deprecated. Use sys_clone2() instead. + */ GLOBAL_ENTRY(sys_clone) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) - alloc r16=ar.pfs,2,2,4,0 + alloc r16=ar.pfs,4,2,5,0 DO_SAVE_SWITCH_STACK + adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp mov loc0=rp mov loc1=r16 // save ar.pfs across do_fork .body mov out1=in1 mov out3=16 // stacksize (compensates for 16-byte scratch area) + tbit.nz p6,p0=in0,CLONE_SETTLS_BIT + mov out4=in2 // out4 = user_tid (optional) + ;; +(p6) st8 [r2]=in3 // store TLS in r13 (tp) adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK br.call.sptk.many rp=do_fork @@ -521,7 +538,7 @@ #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) /* * We need to call schedule_tail() to complete the scheduling process. - * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the + * Called by ia64_switch_to() after do_fork()->copy_thread(). r8 contains the * address of the previously executing task. */ br.call.sptk.many rp=ia64_invoke_schedule_tail @@ -872,7 +889,7 @@ #endif /* __GNUC__ < 3 */ /* - * Setup stack and call ia64_do_signal. Note that pSys and pNonSys need to + * Setup stack and call do_notify_resume_user(). Note that pSys and pNonSys need to * be set up by the caller. We declare 8 input registers so the system call * args get preserved, in case we need to restart a system call. */ @@ -900,7 +917,7 @@ mov ar.unat=r9 mov ar.pfs=loc1 br.ret.sptk.many rp -END(do_notify_resume_user) +END(notify_resume_user) GLOBAL_ENTRY(sys_rt_sigsuspend) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) @@ -1224,10 +1241,10 @@ data8 sys_futex // 1230 data8 sys_sched_setaffinity data8 sys_sched_getaffinity - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall // 1235 - data8 ia64_ni_syscall + data8 sys_security + data8 sys_alloc_hugepages + data8 sys_free_hugepages // 1235 + data8 sys_exit_group data8 ia64_ni_syscall data8 sys_io_setup data8 sys_io_destroy diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/kernel/gate.S Sat Sep 21 21:25:48 2002 @@ -2,7 +2,7 @@ * This file contains the code that gets mapped at the upper end of each task's text * region. For now, it contains the signal trampoline code only. * - * Copyright (C) 1999-2001 Hewlett-Packard Co + * Copyright (C) 1999-2002 Hewlett-Packard Co * David Mosberger-Tang */ @@ -135,7 +135,7 @@ ;; 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 restore_rbs // yup -> (clobbers r14 and r16) +(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) ;; back_from_restore_rbs: adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp @@ -189,20 +189,69 @@ .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF .body restore_rbs: + // On input: + // r14 = bsp1 (bsp at the time of return from signal handler) + // r15 = bsp0 (bsp at the time the signal occurred) + // + // Here, we need to calculate bspstore0, the value that ar.bspstore needs + // to be set to, based on bsp0 and the size of the dirty partition on + // the alternate stack (sc_loadrs >> 16). This can be done with the + // following algorithm: + // + // bspstore0 = rse_skip_regs(bsp0, -rse_num_regs(bsp1 - (loadrs >> 19), bsp1)); + // + // This is what the code below does. + // alloc r2=ar.pfs,0,0,0,0 // alloc null frame adds r16=(LOADRS_OFF+SIGCONTEXT_OFF),sp + adds r18=(RNAT_OFF+SIGCONTEXT_OFF),sp ;; - ld8 r14=[r16] - adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp + ld8 r17=[r16] + ld8 r16=[r18] // get new rnat + extr.u r18=r15,3,6 // r18 <- rse_slot_num(bsp0) ;; - mov ar.rsc=r14 // put RSE into enforced lazy mode - ld8 r14=[r16] // get new rnat + mov ar.rsc=r17 // put RSE into enforced lazy mode + shr.u r17=r17,16 ;; - loadrs // restore dirty partition + sub r14=r14,r17 // r14 (bspstore1) <- bsp1 - (sc_loadrs >> 16) + shr.u r17=r17,3 // r17 <- (sc_loadrs >> 19) + ;; + loadrs // restore dirty partition + extr.u r14=r14,3,6 // r14 <- rse_slot_num(bspstore1) + ;; + add r14=r14,r17 // r14 <- rse_slot_num(bspstore1) + (sc_loadrs >> 19) + ;; + shr.u r14=r14,6 // r14 <- (rse_slot_num(bspstore1) + (sc_loadrs >> 19))/0x40 + ;; + sub r14=r14,r17 // r14 <- -rse_num_regs(bspstore1, bsp1) + movl r17=0x8208208208208209 + ;; + add r18=r18,r14 // r18 (delta) <- rse_slot_num(bsp0) - rse_num_regs(bspstore1,bsp1) + setf.sig f7=r17 + cmp.lt p7,p0=r14,r0 // p7 <- (r14 < 0)? + ;; +(p7) adds r18=-62,r18 // delta -= 62 + ;; + setf.sig f6=r18 + ;; + xmpy.h f6=f6,f7 + ;; + getf.sig r17=f6 + ;; + add r17=r17,r18 + shr r18=r18,63 + ;; + shr r17=r17,5 + ;; + sub r17=r17,r18 // r17 = delta/63 + ;; + add r17=r14,r17 // r17 <- delta/63 - rse_num_regs(bspstore1, bsp1) + ;; + shladd r15=r17,3,r15 // r15 <- bsp0 + 8*(delta/63 - rse_num_regs(bspstore1, bsp1)) ;; mov ar.bspstore=r15 // switch back to old register backing store area ;; - mov ar.rnat=r14 // restore RNaT + mov ar.rnat=r16 // restore RNaT mov ar.rsc=0xf // (will be restored later on from sc_ar_rsc) // invala not necessary as that will happen when returning to user-mode br.cond.sptk back_from_restore_rbs diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Sat Sep 21 21:25:46 2002 +++ b/arch/ia64/kernel/head.S Sat Sep 21 21:25:46 2002 @@ -13,6 +13,8 @@ * Copyright (C) 1999 Intel Corp. * Copyright (C) 1999 Asit Mallick * Copyright (C) 1999 Don Dugger + * Copyright (C) 2002 Fenghua Yu + * -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2. */ #include @@ -260,302 +262,297 @@ END(ia64_load_debug_regs) GLOBAL_ENTRY(__ia64_save_fpu) - alloc r2=ar.pfs,1,0,0,0 - adds r3=16,in0 + alloc r2=ar.pfs,1,4,0,0 + adds loc0=96*16-16,in0 + adds loc1=96*16-16-128,in0 ;; - stf.spill.nta [in0]=f32,32 - stf.spill.nta [ r3]=f33,32 + stf.spill.nta [loc0]=f127,-256 + stf.spill.nta [loc1]=f119,-256 ;; - stf.spill.nta [in0]=f34,32 - stf.spill.nta [ r3]=f35,32 + stf.spill.nta [loc0]=f111,-256 + stf.spill.nta [loc1]=f103,-256 ;; - stf.spill.nta [in0]=f36,32 - stf.spill.nta [ r3]=f37,32 + stf.spill.nta [loc0]=f95,-256 + stf.spill.nta [loc1]=f87,-256 ;; - stf.spill.nta [in0]=f38,32 - stf.spill.nta [ r3]=f39,32 + stf.spill.nta [loc0]=f79,-256 + stf.spill.nta [loc1]=f71,-256 ;; - stf.spill.nta [in0]=f40,32 - stf.spill.nta [ r3]=f41,32 + stf.spill.nta [loc0]=f63,-256 + stf.spill.nta [loc1]=f55,-256 + adds loc2=96*16-32,in0 ;; - stf.spill.nta [in0]=f42,32 - stf.spill.nta [ r3]=f43,32 + stf.spill.nta [loc0]=f47,-256 + stf.spill.nta [loc1]=f39,-256 + adds loc3=96*16-32-128,in0 ;; - stf.spill.nta [in0]=f44,32 - stf.spill.nta [ r3]=f45,32 + stf.spill.nta [loc2]=f126,-256 + stf.spill.nta [loc3]=f118,-256 ;; - stf.spill.nta [in0]=f46,32 - stf.spill.nta [ r3]=f47,32 + stf.spill.nta [loc2]=f110,-256 + stf.spill.nta [loc3]=f102,-256 ;; - stf.spill.nta [in0]=f48,32 - stf.spill.nta [ r3]=f49,32 + stf.spill.nta [loc2]=f94,-256 + stf.spill.nta [loc3]=f86,-256 ;; - stf.spill.nta [in0]=f50,32 - stf.spill.nta [ r3]=f51,32 + stf.spill.nta [loc2]=f78,-256 + stf.spill.nta [loc3]=f70,-256 ;; - stf.spill.nta [in0]=f52,32 - stf.spill.nta [ r3]=f53,32 + stf.spill.nta [loc2]=f62,-256 + stf.spill.nta [loc3]=f54,-256 + adds loc0=96*16-48,in0 ;; - stf.spill.nta [in0]=f54,32 - stf.spill.nta [ r3]=f55,32 + stf.spill.nta [loc2]=f46,-256 + stf.spill.nta [loc3]=f38,-256 + adds loc1=96*16-48-128,in0 ;; - stf.spill.nta [in0]=f56,32 - stf.spill.nta [ r3]=f57,32 + stf.spill.nta [loc0]=f125,-256 + stf.spill.nta [loc1]=f117,-256 ;; - stf.spill.nta [in0]=f58,32 - stf.spill.nta [ r3]=f59,32 + stf.spill.nta [loc0]=f109,-256 + stf.spill.nta [loc1]=f101,-256 ;; - stf.spill.nta [in0]=f60,32 - stf.spill.nta [ r3]=f61,32 + stf.spill.nta [loc0]=f93,-256 + stf.spill.nta [loc1]=f85,-256 ;; - stf.spill.nta [in0]=f62,32 - stf.spill.nta [ r3]=f63,32 + stf.spill.nta [loc0]=f77,-256 + stf.spill.nta [loc1]=f69,-256 ;; - stf.spill.nta [in0]=f64,32 - stf.spill.nta [ r3]=f65,32 + stf.spill.nta [loc0]=f61,-256 + stf.spill.nta [loc1]=f53,-256 + adds loc2=96*16-64,in0 ;; - stf.spill.nta [in0]=f66,32 - stf.spill.nta [ r3]=f67,32 + stf.spill.nta [loc0]=f45,-256 + stf.spill.nta [loc1]=f37,-256 + adds loc3=96*16-64-128,in0 ;; - stf.spill.nta [in0]=f68,32 - stf.spill.nta [ r3]=f69,32 + stf.spill.nta [loc2]=f124,-256 + stf.spill.nta [loc3]=f116,-256 ;; - stf.spill.nta [in0]=f70,32 - stf.spill.nta [ r3]=f71,32 + stf.spill.nta [loc2]=f108,-256 + stf.spill.nta [loc3]=f100,-256 ;; - stf.spill.nta [in0]=f72,32 - stf.spill.nta [ r3]=f73,32 + stf.spill.nta [loc2]=f92,-256 + stf.spill.nta [loc3]=f84,-256 ;; - stf.spill.nta [in0]=f74,32 - stf.spill.nta [ r3]=f75,32 + stf.spill.nta [loc2]=f76,-256 + stf.spill.nta [loc3]=f68,-256 ;; - stf.spill.nta [in0]=f76,32 - stf.spill.nta [ r3]=f77,32 + stf.spill.nta [loc2]=f60,-256 + stf.spill.nta [loc3]=f52,-256 + adds loc0=96*16-80,in0 ;; - stf.spill.nta [in0]=f78,32 - stf.spill.nta [ r3]=f79,32 + stf.spill.nta [loc2]=f44,-256 + stf.spill.nta [loc3]=f36,-256 + adds loc1=96*16-80-128,in0 ;; - stf.spill.nta [in0]=f80,32 - stf.spill.nta [ r3]=f81,32 + stf.spill.nta [loc0]=f123,-256 + stf.spill.nta [loc1]=f115,-256 ;; - stf.spill.nta [in0]=f82,32 - stf.spill.nta [ r3]=f83,32 + stf.spill.nta [loc0]=f107,-256 + stf.spill.nta [loc1]=f99,-256 ;; - stf.spill.nta [in0]=f84,32 - stf.spill.nta [ r3]=f85,32 + stf.spill.nta [loc0]=f91,-256 + stf.spill.nta [loc1]=f83,-256 ;; - stf.spill.nta [in0]=f86,32 - stf.spill.nta [ r3]=f87,32 + stf.spill.nta [loc0]=f75,-256 + stf.spill.nta [loc1]=f67,-256 ;; - stf.spill.nta [in0]=f88,32 - stf.spill.nta [ r3]=f89,32 + stf.spill.nta [loc0]=f59,-256 + stf.spill.nta [loc1]=f51,-256 + adds loc2=96*16-96,in0 ;; - stf.spill.nta [in0]=f90,32 - stf.spill.nta [ r3]=f91,32 + stf.spill.nta [loc0]=f43,-256 + stf.spill.nta [loc1]=f35,-256 + adds loc3=96*16-96-128,in0 ;; - stf.spill.nta [in0]=f92,32 - stf.spill.nta [ r3]=f93,32 + stf.spill.nta [loc2]=f122,-256 + stf.spill.nta [loc3]=f114,-256 ;; - stf.spill.nta [in0]=f94,32 - stf.spill.nta [ r3]=f95,32 + stf.spill.nta [loc2]=f106,-256 + stf.spill.nta [loc3]=f98,-256 ;; - stf.spill.nta [in0]=f96,32 - stf.spill.nta [ r3]=f97,32 + stf.spill.nta [loc2]=f90,-256 + stf.spill.nta [loc3]=f82,-256 ;; - stf.spill.nta [in0]=f98,32 - stf.spill.nta [ r3]=f99,32 + stf.spill.nta [loc2]=f74,-256 + stf.spill.nta [loc3]=f66,-256 ;; - stf.spill.nta [in0]=f100,32 - stf.spill.nta [ r3]=f101,32 + stf.spill.nta [loc2]=f58,-256 + stf.spill.nta [loc3]=f50,-256 + adds loc0=96*16-112,in0 ;; - stf.spill.nta [in0]=f102,32 - stf.spill.nta [ r3]=f103,32 + stf.spill.nta [loc2]=f42,-256 + stf.spill.nta [loc3]=f34,-256 + adds loc1=96*16-112-128,in0 ;; - stf.spill.nta [in0]=f104,32 - stf.spill.nta [ r3]=f105,32 + stf.spill.nta [loc0]=f121,-256 + stf.spill.nta [loc1]=f113,-256 ;; - stf.spill.nta [in0]=f106,32 - stf.spill.nta [ r3]=f107,32 + stf.spill.nta [loc0]=f105,-256 + stf.spill.nta [loc1]=f97,-256 ;; - stf.spill.nta [in0]=f108,32 - stf.spill.nta [ r3]=f109,32 + stf.spill.nta [loc0]=f89,-256 + stf.spill.nta [loc1]=f81,-256 ;; - stf.spill.nta [in0]=f110,32 - stf.spill.nta [ r3]=f111,32 + stf.spill.nta [loc0]=f73,-256 + stf.spill.nta [loc1]=f65,-256 ;; - stf.spill.nta [in0]=f112,32 - stf.spill.nta [ r3]=f113,32 + stf.spill.nta [loc0]=f57,-256 + stf.spill.nta [loc1]=f49,-256 + adds loc2=96*16-128,in0 ;; - stf.spill.nta [in0]=f114,32 - stf.spill.nta [ r3]=f115,32 + stf.spill.nta [loc0]=f41,-256 + stf.spill.nta [loc1]=f33,-256 + adds loc3=96*16-128-128,in0 ;; - stf.spill.nta [in0]=f116,32 - stf.spill.nta [ r3]=f117,32 + stf.spill.nta [loc2]=f120,-256 + stf.spill.nta [loc3]=f112,-256 ;; - stf.spill.nta [in0]=f118,32 - stf.spill.nta [ r3]=f119,32 + stf.spill.nta [loc2]=f104,-256 + stf.spill.nta [loc3]=f96,-256 ;; - stf.spill.nta [in0]=f120,32 - stf.spill.nta [ r3]=f121,32 + stf.spill.nta [loc2]=f88,-256 + stf.spill.nta [loc3]=f80,-256 ;; - stf.spill.nta [in0]=f122,32 - stf.spill.nta [ r3]=f123,32 + stf.spill.nta [loc2]=f72,-256 + stf.spill.nta [loc3]=f64,-256 ;; - stf.spill.nta [in0]=f124,32 - stf.spill.nta [ r3]=f125,32 + stf.spill.nta [loc2]=f56,-256 + stf.spill.nta [loc3]=f48,-256 ;; - stf.spill.nta [in0]=f126,32 - stf.spill.nta [ r3]=f127,32 + stf.spill.nta [loc2]=f40 + stf.spill.nta [loc3]=f32 br.ret.sptk.many rp END(__ia64_save_fpu) GLOBAL_ENTRY(__ia64_load_fpu) - alloc r2=ar.pfs,1,0,0,0 - adds r3=16,in0 - ;; - ldf.fill.nta f32=[in0],32 - ldf.fill.nta f33=[ r3],32 - ;; - ldf.fill.nta f34=[in0],32 - ldf.fill.nta f35=[ r3],32 - ;; - ldf.fill.nta f36=[in0],32 - ldf.fill.nta f37=[ r3],32 - ;; - ldf.fill.nta f38=[in0],32 - ldf.fill.nta f39=[ r3],32 - ;; - ldf.fill.nta f40=[in0],32 - ldf.fill.nta f41=[ r3],32 - ;; - ldf.fill.nta f42=[in0],32 - ldf.fill.nta f43=[ r3],32 - ;; - ldf.fill.nta f44=[in0],32 - ldf.fill.nta f45=[ r3],32 - ;; - ldf.fill.nta f46=[in0],32 - ldf.fill.nta f47=[ r3],32 - ;; - ldf.fill.nta f48=[in0],32 - ldf.fill.nta f49=[ r3],32 - ;; - ldf.fill.nta f50=[in0],32 - ldf.fill.nta f51=[ r3],32 - ;; - ldf.fill.nta f52=[in0],32 - ldf.fill.nta f53=[ r3],32 - ;; - ldf.fill.nta f54=[in0],32 - ldf.fill.nta f55=[ r3],32 - ;; - ldf.fill.nta f56=[in0],32 - ldf.fill.nta f57=[ r3],32 - ;; - ldf.fill.nta f58=[in0],32 - ldf.fill.nta f59=[ r3],32 - ;; - ldf.fill.nta f60=[in0],32 - ldf.fill.nta f61=[ r3],32 - ;; - ldf.fill.nta f62=[in0],32 - ldf.fill.nta f63=[ r3],32 - ;; - ldf.fill.nta f64=[in0],32 - ldf.fill.nta f65=[ r3],32 - ;; - ldf.fill.nta f66=[in0],32 - ldf.fill.nta f67=[ r3],32 - ;; - ldf.fill.nta f68=[in0],32 - ldf.fill.nta f69=[ r3],32 - ;; - ldf.fill.nta f70=[in0],32 - ldf.fill.nta f71=[ r3],32 - ;; - ldf.fill.nta f72=[in0],32 - ldf.fill.nta f73=[ r3],32 - ;; - ldf.fill.nta f74=[in0],32 - ldf.fill.nta f75=[ r3],32 - ;; - ldf.fill.nta f76=[in0],32 - ldf.fill.nta f77=[ r3],32 - ;; - ldf.fill.nta f78=[in0],32 - ldf.fill.nta f79=[ r3],32 - ;; - ldf.fill.nta f80=[in0],32 - ldf.fill.nta f81=[ r3],32 - ;; - ldf.fill.nta f82=[in0],32 - ldf.fill.nta f83=[ r3],32 - ;; - ldf.fill.nta f84=[in0],32 - ldf.fill.nta f85=[ r3],32 - ;; - ldf.fill.nta f86=[in0],32 - ldf.fill.nta f87=[ r3],32 - ;; - ldf.fill.nta f88=[in0],32 - ldf.fill.nta f89=[ r3],32 - ;; - ldf.fill.nta f90=[in0],32 - ldf.fill.nta f91=[ r3],32 - ;; - ldf.fill.nta f92=[in0],32 - ldf.fill.nta f93=[ r3],32 - ;; - ldf.fill.nta f94=[in0],32 - ldf.fill.nta f95=[ r3],32 - ;; - ldf.fill.nta f96=[in0],32 - ldf.fill.nta f97=[ r3],32 - ;; - ldf.fill.nta f98=[in0],32 - ldf.fill.nta f99=[ r3],32 - ;; - ldf.fill.nta f100=[in0],32 - ldf.fill.nta f101=[ r3],32 - ;; - ldf.fill.nta f102=[in0],32 - ldf.fill.nta f103=[ r3],32 - ;; - ldf.fill.nta f104=[in0],32 - ldf.fill.nta f105=[ r3],32 - ;; - ldf.fill.nta f106=[in0],32 - ldf.fill.nta f107=[ r3],32 - ;; - ldf.fill.nta f108=[in0],32 - ldf.fill.nta f109=[ r3],32 - ;; - ldf.fill.nta f110=[in0],32 - ldf.fill.nta f111=[ r3],32 - ;; - ldf.fill.nta f112=[in0],32 - ldf.fill.nta f113=[ r3],32 - ;; - ldf.fill.nta f114=[in0],32 - ldf.fill.nta f115=[ r3],32 - ;; - ldf.fill.nta f116=[in0],32 - ldf.fill.nta f117=[ r3],32 - ;; - ldf.fill.nta f118=[in0],32 - ldf.fill.nta f119=[ r3],32 - ;; - ldf.fill.nta f120=[in0],32 - ldf.fill.nta f121=[ r3],32 - ;; - ldf.fill.nta f122=[in0],32 - ldf.fill.nta f123=[ r3],32 - ;; - ldf.fill.nta f124=[in0],32 - ldf.fill.nta f125=[ r3],32 - ;; - ldf.fill.nta f126=[in0],32 - ldf.fill.nta f127=[ r3],32 + alloc r2=ar.pfs,1,2,0,0 + adds r3=128,in0 + adds r14=256,in0 + adds r15=384,in0 + mov loc0=512 + mov loc1=-1024+16 + ;; + ldf.fill.nta f32=[in0],loc0 + ldf.fill.nta f40=[ r3],loc0 + ldf.fill.nta f48=[r14],loc0 + ldf.fill.nta f56=[r15],loc0 + ;; + ldf.fill.nta f64=[in0],loc0 + ldf.fill.nta f72=[ r3],loc0 + ldf.fill.nta f80=[r14],loc0 + ldf.fill.nta f88=[r15],loc0 + ;; + ldf.fill.nta f96=[in0],loc1 + ldf.fill.nta f104=[ r3],loc1 + ldf.fill.nta f112=[r14],loc1 + ldf.fill.nta f120=[r15],loc1 + ;; + ldf.fill.nta f33=[in0],loc0 + ldf.fill.nta f41=[ r3],loc0 + ldf.fill.nta f49=[r14],loc0 + ldf.fill.nta f57=[r15],loc0 + ;; + ldf.fill.nta f65=[in0],loc0 + ldf.fill.nta f73=[ r3],loc0 + ldf.fill.nta f81=[r14],loc0 + ldf.fill.nta f89=[r15],loc0 + ;; + ldf.fill.nta f97=[in0],loc1 + ldf.fill.nta f105=[ r3],loc1 + ldf.fill.nta f113=[r14],loc1 + ldf.fill.nta f121=[r15],loc1 + ;; + ldf.fill.nta f34=[in0],loc0 + ldf.fill.nta f42=[ r3],loc0 + ldf.fill.nta f50=[r14],loc0 + ldf.fill.nta f58=[r15],loc0 + ;; + ldf.fill.nta f66=[in0],loc0 + ldf.fill.nta f74=[ r3],loc0 + ldf.fill.nta f82=[r14],loc0 + ldf.fill.nta f90=[r15],loc0 + ;; + ldf.fill.nta f98=[in0],loc1 + ldf.fill.nta f106=[ r3],loc1 + ldf.fill.nta f114=[r14],loc1 + ldf.fill.nta f122=[r15],loc1 + ;; + ldf.fill.nta f35=[in0],loc0 + ldf.fill.nta f43=[ r3],loc0 + ldf.fill.nta f51=[r14],loc0 + ldf.fill.nta f59=[r15],loc0 + ;; + ldf.fill.nta f67=[in0],loc0 + ldf.fill.nta f75=[ r3],loc0 + ldf.fill.nta f83=[r14],loc0 + ldf.fill.nta f91=[r15],loc0 + ;; + ldf.fill.nta f99=[in0],loc1 + ldf.fill.nta f107=[ r3],loc1 + ldf.fill.nta f115=[r14],loc1 + ldf.fill.nta f123=[r15],loc1 + ;; + ldf.fill.nta f36=[in0],loc0 + ldf.fill.nta f44=[ r3],loc0 + ldf.fill.nta f52=[r14],loc0 + ldf.fill.nta f60=[r15],loc0 + ;; + ldf.fill.nta f68=[in0],loc0 + ldf.fill.nta f76=[ r3],loc0 + ldf.fill.nta f84=[r14],loc0 + ldf.fill.nta f92=[r15],loc0 + ;; + ldf.fill.nta f100=[in0],loc1 + ldf.fill.nta f108=[ r3],loc1 + ldf.fill.nta f116=[r14],loc1 + ldf.fill.nta f124=[r15],loc1 + ;; + ldf.fill.nta f37=[in0],loc0 + ldf.fill.nta f45=[ r3],loc0 + ldf.fill.nta f53=[r14],loc0 + ldf.fill.nta f61=[r15],loc0 + ;; + ldf.fill.nta f69=[in0],loc0 + ldf.fill.nta f77=[ r3],loc0 + ldf.fill.nta f85=[r14],loc0 + ldf.fill.nta f93=[r15],loc0 + ;; + ldf.fill.nta f101=[in0],loc1 + ldf.fill.nta f109=[ r3],loc1 + ldf.fill.nta f117=[r14],loc1 + ldf.fill.nta f125=[r15],loc1 + ;; + ldf.fill.nta f38 =[in0],loc0 + ldf.fill.nta f46 =[ r3],loc0 + ldf.fill.nta f54 =[r14],loc0 + ldf.fill.nta f62 =[r15],loc0 + ;; + ldf.fill.nta f70 =[in0],loc0 + ldf.fill.nta f78 =[ r3],loc0 + ldf.fill.nta f86 =[r14],loc0 + ldf.fill.nta f94 =[r15],loc0 + ;; + ldf.fill.nta f102=[in0],loc1 + ldf.fill.nta f110=[ r3],loc1 + ldf.fill.nta f118=[r14],loc1 + ldf.fill.nta f126=[r15],loc1 + ;; + ldf.fill.nta f39 =[in0],loc0 + ldf.fill.nta f47 =[ r3],loc0 + ldf.fill.nta f55 =[r14],loc0 + ldf.fill.nta f63 =[r15],loc0 + ;; + ldf.fill.nta f71 =[in0],loc0 + ldf.fill.nta f79 =[ r3],loc0 + ldf.fill.nta f87 =[r14],loc0 + ldf.fill.nta f95 =[r15],loc0 + ;; + ldf.fill.nta f103=[in0] + ldf.fill.nta f111=[ r3] + ldf.fill.nta f119=[r14] + ldf.fill.nta f127=[r15] br.ret.sptk.many rp END(__ia64_load_fpu) diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c --- a/arch/ia64/kernel/ia64_ksyms.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/ia64_ksyms.c Sat Sep 21 21:25:45 2002 @@ -127,6 +127,8 @@ EXPORT_SYMBOL(ia64_pal_call_phys_static); EXPORT_SYMBOL(ia64_pal_call_stacked); EXPORT_SYMBOL(ia64_pal_call_static); +EXPORT_SYMBOL(ia64_load_scratch_fpregs); +EXPORT_SYMBOL(ia64_save_scratch_fpregs); extern struct efi efi; EXPORT_SYMBOL(efi); diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/kernel/init_task.c Sat Sep 21 21:25:48 2002 @@ -16,7 +16,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); struct mm_struct init_mm = INIT_MM(init_mm); /* diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/iosapic.c Sat Sep 21 21:25:45 2002 @@ -27,8 +27,8 @@ * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping * error * 02/07/29 T. Kochi Allocate interrupt vectors dynamically - * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, - * etc.) + * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) + * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code. */ /* * Here is what the interrupt logic between a PCI device and the kernel looks like: @@ -51,7 +51,7 @@ * architecture-independent interrupt handling mechanism in Linux. As an * IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number * mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and - * IRQ. A platform can implemnent platform_irq_to_vector(irq) and + * IRQ. A platform can implement platform_irq_to_vector(irq) and * platform_local_vector_to_irq(vector) APIs to differentiate the mapping. * Please see also include/asm-ia64/hw_irq.h for those APIs. * @@ -65,14 +65,15 @@ */ #include -#include +#include #include +#include +#include +#include #include #include #include #include -#include -#include #include #include @@ -95,13 +96,6 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; -/* PCI pin to GSI routing information. This info typically comes from ACPI. */ - -static struct { - int num_routes; - struct pci_vector_struct *route; -} pci_irq; - /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ static struct iosapic_intr_info { @@ -146,11 +140,11 @@ int gsi_to_vector (unsigned int gsi) { - int vector; + struct iosapic_intr_info *info; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) - if (iosapic_intr_info[vector].gsi_base + iosapic_intr_info[vector].rte_index == gsi) - return vector; + for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info) + if (info->gsi_base + info->rte_index == gsi) + return info - iosapic_intr_info; return -1; } @@ -163,7 +157,7 @@ int rte_index; char redir; - DBG(KERN_DEBUG "%s: routing vector %d to %x\n", __FUNCTION__, vector, dest); + DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest); rte_index = iosapic_intr_info[vector].rte_index; if (rte_index < 0) @@ -584,7 +578,8 @@ index = find_iosapic(gsi); if (index < 0) { - printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi); + printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", + isa_irq, gsi); return; } @@ -604,75 +599,6 @@ set_rte(vector, dest); } -/* - * Map PCI pin to the corresponding GSI. - * If no such mapping exists, return -1. - */ -static int -pci_pin_to_gsi (int bus, int slot, int pci_pin, unsigned int *gsi) -{ - struct pci_vector_struct *r; - - for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r) - if (r->bus == bus && - (r->pci_id >> 16) == slot && r->pin == pci_pin) { - *gsi = r->irq; - return 0; - } - - return -1; -} - -/* - * Map PCI pin to the corresponding IA-64 interrupt vector. If no such mapping exists, - * try to allocate a new vector. If it fails, return -1. - */ -static int -pci_pin_to_vector (int bus, int slot, int pci_pin) -{ - int index, vector; - int gsi_base, pcat_compat; - char *addr; - unsigned int gsi; - - if (pci_pin_to_gsi(bus, slot, pci_pin, &gsi) < 0) { - printk("PCI: no interrupt route for %02x:%02x pin %c\n", bus, slot, 'A' + pci_pin); - return -1; - } - - vector = gsi_to_vector(gsi); - - if (vector < 0) { - /* we should allocate a vector for this interrupt line */ - - index = find_iosapic(gsi); - - if (index < 0) { - printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi); - return -1; - } - - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - pcat_compat = iosapic_lists[index].pcat_compat; - - if (pcat_compat && (gsi < 16)) - vector = isa_irq_to_vector(gsi); - else { - /* new GSI; allocate a vector for it */ - vector = ia64_alloc_vector(); - } - - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - 0, 0, gsi_base, addr); - - DBG("PCI: (%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n", - bus, slot, 'A' + pci_pin, gsi, vector); - } - - return vector; -} - void __devinit iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat) { @@ -713,7 +639,7 @@ iosapic_lists[num_iosapic].num_rte = num_rte; num_iosapic++; - printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n", + printk(KERN_INFO" IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n", (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { @@ -740,122 +666,93 @@ } } - -/* - * Set allocated interrupt vector to dev->irq and - * program IOSAPIC to deliver interrupts - */ -void -iosapic_fixup_pci_interrupt (struct pci_dev *dev) +static void +fixup_vector (int vector, unsigned int gsi, const char *pci_id) { - unsigned char pci_pin; - int vector; - unsigned int dest; - struct hw_interrupt_type *irq_type; + struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; irq_desc_t *idesc; + unsigned int dest; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pci_pin); - if (pci_pin) { - pci_pin--; /* interrupt pins are numberd starting from 1 */ - - vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pci_pin); - - if (vector < 0 && dev->bus->parent) { - /* go back to the bridge */ - struct pci_dev *bridge = dev->bus->self; - - if (bridge) { - /* allow for multiple bridges on an adapter */ - do { - /* do the bridge swizzle... */ - pci_pin = (pci_pin + PCI_SLOT(dev->devfn)) % 4; - vector = pci_pin_to_vector(bridge->bus->number, - PCI_SLOT(bridge->devfn), - pci_pin); - } while (vector < 0 && (bridge = bridge->bus->self)); - } - if (vector >= 0) - printk(KERN_WARNING - "PCI: using PPB (%s INT%c) to get vector %d\n", - dev->slot_name, 'A' + pci_pin, - vector); - else - printk(KERN_WARNING - "PCI: Couldn't map irq for (%s INT%c)\n", - dev->slot_name, 'A' + pci_pin); - } + idesc = irq_desc(vector); + if (idesc->handler != irq_type) { + if (idesc->handler != &no_irq_type) + printk("IOSAPIC: changing vector %d from %s to %s\n", + vector, idesc->handler->typename, irq_type->typename); + idesc->handler = irq_type; + } +#ifdef CONFIG_SMP + /* + * For platforms that do not support interrupt redirect via the XTP interface, we + * can round-robin the PCI device interrupts to the processors + */ + if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) { + static int cpu_index = -1; - if (vector >= 0) { - dev->irq = vector; + do + if (++cpu_index >= NR_CPUS) + cpu_index = 0; + while (!cpu_online(cpu_index)); - irq_type = &irq_type_iosapic_level; - idesc = irq_desc(vector); - if (idesc->handler != irq_type) { - if (idesc->handler != &no_irq_type) - printk("%s: changing vector %d from %s to %s\n", - __FUNCTION__, vector, - idesc->handler->typename, - irq_type->typename); - idesc->handler = irq_type; - } -#ifdef CONFIG_SMP - /* - * For platforms that do not support interrupt redirect - * via the XTP interface, we can round-robin the PCI - * device interrupts to the processors - */ - if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) { - static int cpu_index = 0; - - while (!cpu_online(cpu_index)) - if (++cpu_index >= NR_CPUS) - cpu_index = 0; - - dest = cpu_physical_id(cpu_index) & 0xffff; - } else { - /* - * Direct the interrupt vector to the current cpu, - * platform redirection will distribute them. - */ - dest = (ia64_get_lid() >> 16) & 0xffff; - } + dest = cpu_physical_id(cpu_index) & 0xffff; + } else { + /* + * Direct the interrupt vector to the current cpu, platform redirection + * will distribute them. + */ + dest = (ia64_get_lid() >> 16) & 0xffff; + } #else - /* direct the interrupt vector to the running cpu id */ - dest = (ia64_get_lid() >> 16) & 0xffff; + /* direct the interrupt vector to the running cpu id */ + dest = (ia64_get_lid() >> 16) & 0xffff; #endif + set_rte(vector, dest); - printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n", - dev->slot_name, 'A' + pci_pin, dest, vector); - set_rte(vector, dest); - } - } + printk("IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n", pci_id, gsi, dest, vector); } - -void -iosapic_pci_fixup (int phase) +void __init +iosapic_parse_prt (void) { - struct pci_dev *dev; + struct acpi_prt_entry *entry; + struct list_head *node; + unsigned int gsi, gsi_base; + int index, vector, pcat_compat; + char pci_id[16]; + char *addr; - if (phase == 0) { - if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) { - printk("%s: acpi_get_prt failed\n", __FILE__); - } - return; - } + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); - if (phase != 1) - return; + /* We're only interested in static (non-link) entries. */ + if (entry->link.handle) + continue; + + gsi = entry->link.index; + + vector = gsi_to_vector(gsi); + if (vector < 0) { + /* allocate a vector for this interrupt line */ + index = find_iosapic(gsi); + + if (index < 0) { + printk(KERN_WARNING"IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi); + return; + } + addr = iosapic_lists[index].addr; + gsi_base = iosapic_lists[index].gsi_base; + pcat_compat = iosapic_lists[index].pcat_compat; - pci_for_each_dev(dev) { - /* fixup dev->irq and program IOSAPIC */ - iosapic_fixup_pci_interrupt(dev); + if (pcat_compat && (gsi < 16)) + vector = isa_irq_to_vector(gsi); + else + /* new GSI; allocate a vector for it */ + vector = ia64_alloc_vector(); - /* - * Nothing to fixup - * Fix out-of-range IRQ numbers - */ - if (dev->irq >= IA64_NUM_VECTORS) - dev->irq = 15; /* Spurious interrupts */ + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr); + } + snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", + entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); + + fixup_vector(vector, gsi, pci_id); } } diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/irq.c Sat Sep 21 21:25:45 2002 @@ -403,8 +403,8 @@ break; desc->status &= ~IRQ_PENDING; } - out: desc->status &= ~IRQ_INPROGRESS; + out: /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. @@ -788,7 +788,7 @@ if (!shared) { desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); desc->handler->startup(irq); } spin_unlock_irqrestore(&desc->lock,flags); diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/ivt.S Sat Sep 21 21:25:45 2002 @@ -70,24 +70,6 @@ mov r19=n;; /* prepare to save predicates */ \ br.sptk.many dispatch_to_fault_handler -/* - * As we don't (hopefully) use the space available, we need to fill it with - * nops. the parameter may be used for debugging and is representing the entry - * number - */ -#define BREAK_BUNDLE(a) break.m (a); \ - break.i (a); \ - break.i (a) -/* - * 4 breaks bundles all together - */ -#define BREAK_BUNDLE4(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a) - -/* - * 8 bundles all together (too lazy to use only 4 at a time !) - */ -#define BREAK_BUNDLE8(a); BREAK_BUNDLE4(a); BREAK_BUNDLE4(a) - .section .text.ivt,"ax" .align 32768 // align on 32KB boundary @@ -115,6 +97,10 @@ * - the faulting virtual address has no L1, L2, or L3 mapping */ mov r16=cr.ifa // get address that caused the TLB miss +#ifdef CONFIG_HUGETLB_PAGE + movl r18=PAGE_SHIFT + mov r25=cr.itir +#endif ;; rsm psr.dt // use physical addressing for data mov r31=pr // save the predicate registers @@ -122,8 +108,18 @@ shl r21=r16,3 // shift bit 60 into sign bit shr.u r17=r16,61 // get the region number into r17 ;; + shr r22=r21,3 +#ifdef CONFIG_HUGETLB_PAGE + extr.u r26=r25,2,6 + ;; + cmp.eq p8,p0=HPAGE_SHIFT,r26 + ;; +(p8) dep r25=r18,r25,2,6 +(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT + ;; +#endif cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? - shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of the faulting address + shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address ;; (p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d // ensure "rsm psr.dt" has taken effect @@ -134,7 +130,7 @@ (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 (p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) cmp.eq p7,p6=0,r21 // unused address bits all zeroes? - shr.u r18=r16,PMD_SHIFT // shift L2 index into position + shr.u r18=r22,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; @@ -142,7 +138,7 @@ dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry ;; (p7) ld8 r20=[r17] // fetch the L2 entry (may be 0) - shr.u r19=r16,PAGE_SHIFT // shift L3 index into position + shr.u r19=r22,PAGE_SHIFT // shift L3 index into position ;; (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL? dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry @@ -160,6 +156,10 @@ (p11) itc.d r18 // insert the data TLB entry (p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) mov cr.ifa=r22 + +#ifdef CONFIG_HUGETLB_PAGE +(p8) mov cr.itir=r25 // change to default page-size for VHPT +#endif /* * Now compute and insert the TLB entry for the virtual page table. We never diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/mca.c Sat Sep 21 21:25:45 2002 @@ -208,6 +208,8 @@ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); } +device_initcall(ia64_mca_check_errors); + /* * ia64_mca_register_cpev * diff -Nru a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S --- a/arch/ia64/kernel/pal.S Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/kernel/pal.S Sat Sep 21 21:25:48 2002 @@ -245,3 +245,48 @@ br.ret.sptk.many b0 END(ia64_pal_call_phys_stacked) +/* + * Save scratch fp scratch regs which aren't saved in pt_regs already (fp10-fp15). + * + * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch + * regs fp-low partition. + * + * Inputs: + * in0 Address of stack storage for fp regs + */ +GLOBAL_ENTRY(ia64_save_scratch_fpregs) + alloc r3=ar.pfs,1,0,0,0 + add r2=16,in0 + ;; + stf.spill [in0] = f10,32 + stf.spill [r2] = f11,32 + ;; + stf.spill [in0] = f12,32 + stf.spill [r2] = f13,32 + ;; + stf.spill [in0] = f14,32 + stf.spill [r2] = f15,32 + br.ret.sptk.many rp +END(ia64_save_scratch_fpregs) + +/* + * Load scratch fp scratch regs (fp10-fp15) + * + * Inputs: + * in0 Address of stack storage for fp regs + */ + +GLOBAL_ENTRY(ia64_load_scratch_fpregs) + alloc r3=ar.pfs,1,0,0,0 + add r2=16,in0 + ;; + ldf.fill f10 = [in0],32 + ldf.fill f11 = [r2],32 + ;; + ldf.fill f12 = [in0],32 + ldf.fill f13 = [r2],32 + ;; + ldf.fill f14 = [in0],32 + ldf.fill f15 = [r2],32 + br.ret.sptk.many rp +END(ia64_load_scratch_fpregs) diff -Nru a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c --- a/arch/ia64/kernel/pci.c Sat Sep 21 21:25:45 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,290 +0,0 @@ -/* - * pci.c - Low-Level PCI Access in IA-64 - * - * Derived from bios32.c of i386 tree. - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - - -#ifdef CONFIG_SMP -# include -#endif -#include - - -#undef DEBUG -#define DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#ifdef CONFIG_IA64_MCA -extern void ia64_mca_check_errors( void ); -#endif - -struct pci_fixup pcibios_fixups[1]; - -struct pci_ops *pci_root_ops; - - -/* - * Low-level SAL-based PCI configuration access functions. Note that SAL - * calls are already serialized (via sal_lock), so we don't need another - * synchronization mechanism here. Not using segment number (yet). - */ - -#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \ - ((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg)) - -static int -__pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) -{ - int result = 0; - u64 data = 0; - - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data); - - *value = (u32) data; - - return result; -} - -static int -__pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) -{ - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) - return -EINVAL; - - return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value); -} - - -static int -pci_sal_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - return __pci_sal_read(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -static int -pci_sal_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - return __pci_sal_write(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); -} - -struct pci_ops pci_sal_ops = { - .read = pci_sal_read, - .write = pci_sal_write, -}; - - -/* - * Initialization. Uses the SAL interface - */ - -struct pci_bus * -pcibios_scan_root(int bus) -{ - struct list_head *list = NULL; - struct pci_bus *pci_bus = NULL; - - list_for_each(list, &pci_root_buses) { - pci_bus = pci_bus_b(list); - if (pci_bus->number == bus) { - /* Already scanned */ - printk("PCI: Bus (%02x) already probed\n", bus); - return pci_bus; - } - } - - printk("PCI: Probing PCI hardware on bus (%02x)\n", bus); - - return pci_scan_bus(bus, pci_root_ops, NULL); -} - -void __init -pcibios_config_init (void) -{ - if (pci_root_ops) - return; - - printk("PCI: Using SAL to access configuration space\n"); - - pci_root_ops = &pci_sal_ops; - - return; -} - -static int __init -pcibios_init (void) -{ -# define PCI_BUSES_TO_SCAN 255 - int i = 0; - -#ifdef CONFIG_IA64_MCA - ia64_mca_check_errors(); /* For post-failure MCA error logging */ -#endif - - pcibios_config_init(); - - platform_pci_fixup(0); /* phase 0 fixups (before buses scanned) */ - - printk("PCI: Probing PCI hardware\n"); - for (i = 0; i < PCI_BUSES_TO_SCAN; i++) - pci_scan_bus(i, pci_root_ops, NULL); - - platform_pci_fixup(1); /* phase 1 fixups (after buses scanned) */ - return 0; -} - -subsys_initcall(pcibios_init); - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __init -pcibios_fixup_bus (struct pci_bus *b) -{ - return; -} - -void __init -pcibios_update_resource (struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - unsigned long where, size; - u32 reg; - - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); - - /* ??? FIXME -- record old value for shutdown. */ -} - -void __init -pcibios_update_irq (struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - - /* ??? FIXME -- record old value for shutdown. */ -} - -void __init -pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges) -{ -} - -int -pcibios_enable_device (struct pci_dev *dev) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - if (!dev) - return -EINVAL; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because of resource collisions\n", - dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - - printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name); - - return 0; -} - -void -pcibios_align_resource (void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -/* - * PCI BIOS setup, always defaults to SAL interface - */ -char * __init -pcibios_setup (char *str) -{ - return NULL; -} - -int -pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - /* - * I/O space cannot be accessed via normal processor loads and stores on this - * platform. - */ - if (mmap_state == pci_mmap_io) - /* - * XXX we could relax this for I/O spaces for which ACPI indicates that - * the space is 1-to-1 mapped. But at the moment, we don't support - * multiple PCI address spaces and the legacy I/O space is not 1-to-1 - * mapped, so this is moot. - */ - return -EINVAL; - - /* - * Leave vm_pgoff as-is, the PCI space address is the physical address on this - * platform. - */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); - - if (write_combine) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - else - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - - return 0; -} diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/kernel/perfmon.c Sat Sep 21 21:25:48 2002 @@ -76,7 +76,7 @@ /* XXX: these three assume that register i is implemented */ #define PMD_IS_COUNTING(i) (pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING) #define PMC_IS_COUNTING(i) (pmu_conf.pmc_desc[i].type == PFM_REG_COUNTING) -#define PMC_IS_MONITOR(c) (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR) +#define PMC_IS_MONITOR(i) (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR) /* k assume unsigned */ #define IBR_IS_IMPL(k) (kpid) { - ctx->ctx_notify_task = task = current; - current->thread.pfm_context = ctx; + ctx->ctx_notify_task = current; + task->thread.pfm_context = ctx; } else if (notify_pid!=0) { struct task_struct *notify_task; @@ -1034,7 +1041,10 @@ /* * check if we can send this task a signal */ - if (pfm_bad_permissions(notify_task)) goto buffer_error; + if (pfm_bad_permissions(notify_task)) { + read_unlock(&tasklist_lock); + goto buffer_error; + } /* * make visible @@ -1044,7 +1054,7 @@ * okay because child will do the scan for nothing which * won't hurt. */ - current->thread.pfm_context = ctx; + task->thread.pfm_context = ctx; /* * will cause task to check on exit for monitored @@ -1101,7 +1111,7 @@ sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */ - if (copy_to_user(req, &tmp, sizeof(tmp))) { + if (__copy_to_user(req, &tmp, sizeof(tmp))) { ret = -EFAULT; goto buffer_error; } @@ -1147,16 +1157,38 @@ abort: UNLOCK_PFS(); + /* make sure we don't leave anything behind */ + task->thread.pfm_context = NULL; + return ret; } +static inline unsigned long +pfm_new_counter_value (pfm_counter_t *reg, int is_long_reset) +{ + unsigned long val = is_long_reset ? reg->long_reset : reg->short_reset; + unsigned long new_seed, old_seed = reg->seed, mask = reg->mask; + extern unsigned long carta_random32 (unsigned long seed); + + if (reg->flags & PFM_REGFL_RANDOM) { + new_seed = carta_random32(old_seed); + val -= (old_seed & mask); /* counter values are negative numbers! */ + if ((mask >> 32) != 0) + /* construct a full 64-bit random value: */ + new_seed |= carta_random32(old_seed >> 32) << 32; + reg->seed = new_seed; + } + reg->lval = val; + return val; +} + static void pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag) { unsigned long mask = ovfl_regs[0]; unsigned long reset_others = 0UL; unsigned long val; - int i; + int i, is_long_reset = (flag & PFM_RELOAD_LONG_RESET); DBprintk(("masks=0x%lx\n", mask)); @@ -1166,15 +1198,11 @@ mask >>= PMU_FIRST_COUNTER; for(i = PMU_FIRST_COUNTER; mask; i++, mask >>= 1) { if (mask & 0x1) { - val = flag == PFM_RELOAD_LONG_RESET ? - ctx->ctx_soft_pmds[i].long_reset: - ctx->ctx_soft_pmds[i].short_reset; - + val = pfm_new_counter_value(ctx->ctx_soft_pmds + i, is_long_reset); reset_others |= ctx->ctx_soft_pmds[i].reset_pmds[0]; - DBprintk(("[%d] %s reset soft_pmd[%d]=%lx\n", - current->pid, - flag == PFM_RELOAD_LONG_RESET ? "long" : "short", i, val)); + DBprintk(("[%d] %s reset soft_pmd[%d]=%lx\n", current->pid, + is_long_reset ? "long" : "short", i, val)); /* upper part is ignored on rval */ pfm_write_soft_counter(ctx, i, val); @@ -1188,23 +1216,17 @@ if ((reset_others & 0x1) == 0) continue; - val = flag == PFM_RELOAD_LONG_RESET ? - ctx->ctx_soft_pmds[i].long_reset: - ctx->ctx_soft_pmds[i].short_reset; + val = pfm_new_counter_value(ctx->ctx_soft_pmds + i, is_long_reset); if (PMD_IS_COUNTING(i)) { pfm_write_soft_counter(ctx, i, val); } else { ia64_set_pmd(i, val); } - - DBprintk(("[%d] %s reset_others pmd[%d]=%lx\n", - current->pid, - flag == PFM_RELOAD_LONG_RESET ? "long" : "short", i, val)); + DBprintk(("[%d] %s reset_others pmd[%d]=%lx\n", current->pid, + is_long_reset ? "long" : "short", i, val)); } ia64_srlz_d(); - /* just in case ! */ - ctx->ctx_ovfl_regs[0] = 0UL; } static int @@ -1212,9 +1234,10 @@ { struct thread_struct *th = &task->thread; pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; - unsigned int cnum; + unsigned long value; + unsigned int cnum, reg_flags, flags; int i; - int ret = 0, reg_retval = 0; + int ret = -EINVAL; /* we don't quite support this right now */ if (task != current) return -EINVAL; @@ -1225,10 +1248,12 @@ for (i = 0; i < count; i++, req++) { + if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; - if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; - - cnum = tmp.reg_num; + cnum = tmp.reg_num; + reg_flags = tmp.reg_flags; + value = tmp.reg_value; + flags = 0; /* * we reject all non implemented PMC as well @@ -1237,8 +1262,7 @@ */ if (!PMC_IS_IMPL(cnum) || cnum < 4) { DBprintk(("pmc[%u] is unimplemented or invalid\n", cnum)); - ret = -EINVAL; - goto abort_mission; + goto error; } /* * A PMC used to configure monitors must be: @@ -1247,73 +1271,79 @@ * any other configuration is rejected. */ if (PMC_IS_MONITOR(cnum) || PMC_IS_COUNTING(cnum)) { - DBprintk(("pmc[%u].pm=%ld\n", cnum, PMC_PM(cnum, tmp.reg_value))); - - if (ctx->ctx_fl_system ^ PMC_PM(cnum, tmp.reg_value)) { - DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, tmp.reg_value), ctx->ctx_fl_system)); - ret = -EINVAL; - goto abort_mission; + if (ctx->ctx_fl_system ^ PMC_PM(cnum, value)) { + DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, value), ctx->ctx_fl_system)); + goto error; } } if (PMC_IS_COUNTING(cnum)) { - pfm_monitor_t *p = (pfm_monitor_t *)&tmp.reg_value; + pfm_monitor_t *p = (pfm_monitor_t *)&value; /* * enforce generation of overflow interrupt. Necessary on all * CPUs. */ p->pmc_oi = 1; - if (tmp.reg_flags & PFM_REGFL_OVFL_NOTIFY) { + if (reg_flags & PFM_REGFL_OVFL_NOTIFY) { /* - * must have a target for the signal - */ + * must have a target for the signal + */ if (ctx->ctx_notify_task == NULL) { - DBprintk(("no notify_task && PFM_REGFL_OVFL_NOTIFY\n")); - ret = -EINVAL; - goto abort_mission; + DBprintk(("cannot set ovfl_notify: no notify_task\n")); + goto error; } - - ctx->ctx_soft_pmds[cnum].flags |= PFM_REGFL_OVFL_NOTIFY; + flags |= PFM_REGFL_OVFL_NOTIFY; } - /* - * copy reset vector - */ - ctx->ctx_soft_pmds[cnum].reset_pmds[0] = tmp.reg_reset_pmds[0]; - ctx->ctx_soft_pmds[cnum].reset_pmds[1] = tmp.reg_reset_pmds[1]; - ctx->ctx_soft_pmds[cnum].reset_pmds[2] = tmp.reg_reset_pmds[2]; - ctx->ctx_soft_pmds[cnum].reset_pmds[3] = tmp.reg_reset_pmds[3]; + + if (reg_flags & PFM_REGFL_RANDOM) flags |= PFM_REGFL_RANDOM; + + } else if (reg_flags & (PFM_REGFL_OVFL_NOTIFY|PFM_REGFL_RANDOM)) { + DBprintk(("cannot set ovfl_notify or random on pmc%u\n", cnum)); + goto error; } + /* * execute write checker, if any */ - if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs); -abort_mission: - if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL; + if (PMC_WR_FUNC(cnum)) { + ret = PMC_WR_FUNC(cnum)(task, cnum, &value, regs); + if (ret) goto error; + ret = -EINVAL; + } - PFM_REG_RETFLAG_SET(tmp.reg_flags, reg_retval); + /* + * no error on this register + */ + PFM_REG_RETFLAG_SET(tmp.reg_flags, 0); /* * update register return value, abort all if problem during copy. + * we only modify the reg_flags field. no check mode is fine because + * access has been verified upfront in sys_perfmonctl(). + * + * If this fails, then the software state is not modified */ - if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; + if (__put_user(tmp.reg_flags, &req->reg_flags)) return -EFAULT; /* - * if there was something wrong on this register, don't touch - * the hardware at all and abort write request for others. - * - * On error, the user mut sequentially scan the table and the first - * entry which has a return flag set is the one that caused the error. + * Now we commit the changes to the software state */ - if (ret != 0) { - DBprintk(("[%d] pmc[%u]=0x%lx error %d\n", - task->pid, cnum, tmp.reg_value, reg_retval)); - break; - } /* - * We can proceed with this register! + * full flag update each time a register is programmed */ + ctx->ctx_soft_pmds[cnum].flags = flags; + + if (PMC_IS_COUNTING(cnum)) { + /* + * copy reset vector + */ + ctx->ctx_soft_pmds[cnum].reset_pmds[0] = tmp.reg_reset_pmds[0]; + ctx->ctx_soft_pmds[cnum].reset_pmds[1] = tmp.reg_reset_pmds[1]; + ctx->ctx_soft_pmds[cnum].reset_pmds[2] = tmp.reg_reset_pmds[2]; + ctx->ctx_soft_pmds[cnum].reset_pmds[3] = tmp.reg_reset_pmds[3]; + } /* * Needed in case the user does not initialize the equivalent @@ -1325,16 +1355,26 @@ /* * keep copy the pmc, used for register reload */ - th->pmc[cnum] = tmp.reg_value; + th->pmc[cnum] = value; - ia64_set_pmc(cnum, tmp.reg_value); + ia64_set_pmc(cnum, value); DBprintk(("[%d] pmc[%u]=0x%lx flags=0x%x used_pmds=0x%lx\n", - task->pid, cnum, tmp.reg_value, + task->pid, cnum, value, ctx->ctx_soft_pmds[cnum].flags, ctx->ctx_used_pmds[0])); } + + return 0; + +error: + PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL); + + if (__put_user(tmp.reg_flags, &req->reg_flags)) ret = -EFAULT; + + DBprintk(("[%d] pmc[%u]=0x%lx error %d\n", task->pid, cnum, value, ret)); + return ret; } @@ -1342,9 +1382,10 @@ pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; + unsigned long value, hw_value; unsigned int cnum; int i; - int ret = 0, reg_retval = 0; + int ret; /* we don't quite support this right now */ if (task != current) return -EINVAL; @@ -1354,65 +1395,74 @@ */ if (!CTX_IS_ENABLED(ctx)) return -EINVAL; - /* XXX: ctx locking may be required here */ + ret = -EINVAL; + for (i = 0; i < count; i++, req++) { - if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; + if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; + + cnum = tmp.reg_num; + value = tmp.reg_value; - cnum = tmp.reg_num; if (!PMD_IS_IMPL(cnum)) { - ret = -EINVAL; + DBprintk(("pmd[%u] is unimplemented or invalid\n", cnum)); goto abort_mission; } - /* update virtualized (64bits) counter */ - if (PMD_IS_COUNTING(cnum)) { - ctx->ctx_soft_pmds[cnum].ival = tmp.reg_value; - ctx->ctx_soft_pmds[cnum].val = tmp.reg_value & ~pmu_conf.perf_ovfl_val; - ctx->ctx_soft_pmds[cnum].long_reset = tmp.reg_long_reset; - ctx->ctx_soft_pmds[cnum].short_reset = tmp.reg_short_reset; - - } /* * execute write checker, if any */ - if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs); -abort_mission: - if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL; - - PFM_REG_RETFLAG_SET(tmp.reg_flags, reg_retval); + if (PMD_WR_FUNC(cnum)) { + unsigned long v = value; + ret = PMD_WR_FUNC(cnum)(task, cnum, &v, regs); + if (ret) goto abort_mission; + value = v; + ret = -EINVAL; + } + hw_value = value; + /* + * no error on this register + */ + PFM_REG_RETFLAG_SET(tmp.reg_flags, 0); - if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; + if (__put_user(tmp.reg_flags, &req->reg_flags)) return -EFAULT; /* - * if there was something wrong on this register, don't touch - * the hardware at all and abort write request for others. - * - * On error, the user mut sequentially scan the table and the first - * entry which has a return flag set is the one that caused the error. + * now commit changes to software state */ - if (ret != 0) { - DBprintk(("[%d] pmc[%u]=0x%lx error %d\n", - task->pid, cnum, tmp.reg_value, reg_retval)); - break; + + /* update virtualized (64bits) counter */ + if (PMD_IS_COUNTING(cnum)) { + ctx->ctx_soft_pmds[cnum].lval = value; + ctx->ctx_soft_pmds[cnum].val = value & ~pmu_conf.perf_ovfl_val; + + hw_value = value & pmu_conf.perf_ovfl_val; + + ctx->ctx_soft_pmds[cnum].long_reset = tmp.reg_long_reset; + ctx->ctx_soft_pmds[cnum].short_reset = tmp.reg_short_reset; + + ctx->ctx_soft_pmds[cnum].seed = tmp.reg_random_seed; + ctx->ctx_soft_pmds[cnum].mask = tmp.reg_random_mask; } /* keep track of what we use */ CTX_USED_PMD(ctx, pmu_conf.pmd_desc[(cnum)].dep_pmd[0]); + /* mark this register as used as well */ CTX_USED_PMD(ctx, RDEP(cnum)); /* writes to unimplemented part is ignored, so this is safe */ - ia64_set_pmd(cnum, tmp.reg_value & pmu_conf.perf_ovfl_val); + ia64_set_pmd(cnum, hw_value); /* to go away */ ia64_srlz_d(); - DBprintk(("[%d] pmd[%u]: soft_pmd=0x%lx short_reset=0x%lx " + DBprintk(("[%d] pmd[%u]: value=0x%lx hw_value=0x%lx soft_pmd=0x%lx short_reset=0x%lx " "long_reset=0x%lx hw_pmd=%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx\n", task->pid, cnum, + value, hw_value, ctx->ctx_soft_pmds[cnum].val, ctx->ctx_soft_pmds[cnum].short_reset, ctx->ctx_soft_pmds[cnum].long_reset, @@ -1421,17 +1471,36 @@ ctx->ctx_used_pmds[0], ctx->ctx_soft_pmds[cnum].reset_pmds[0])); } + + return 0; + +abort_mission: + /* + * for now, we have only one possibility for error + */ + PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL); + + /* + * we change the return value to EFAULT in case we cannot write register return code. + * The caller first must correct this error, then a resubmission of the request will + * eventually yield the EINVAL. + */ + if (__put_user(tmp.reg_flags, &req->reg_flags)) ret = -EFAULT; + + DBprintk(("[%d] pmc[%u]=0x%lx ret %d\n", task->pid, cnum, value, ret)); + return ret; } + static int pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *th = &task->thread; - unsigned long val=0; - pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; - unsigned int cnum; - int i, ret = 0; + unsigned long val = 0UL; + pfarg_reg_t *req = (pfarg_reg_t *)arg; + unsigned int cnum, reg_flags = 0; + int i, ret = -EINVAL; if (!CTX_IS_ENABLED(ctx)) return -EINVAL; @@ -1447,11 +1516,9 @@ DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); for (i = 0; i < count; i++, req++) { - unsigned long ctx_val = ~0UL; - if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; - - cnum = tmp.reg_num; + if (__get_user(cnum, &req->reg_num)) return -EFAULT; + if (__get_user(reg_flags, &req->reg_flags)) return -EFAULT; if (!PMD_IS_IMPL(cnum)) goto abort_mission; /* @@ -1501,34 +1568,40 @@ */ val &= pmu_conf.perf_ovfl_val; - val += ctx_val = ctx->ctx_soft_pmds[cnum].val; + val += ctx->ctx_soft_pmds[cnum].val; } - tmp.reg_value = val; - /* * execute read checker, if any */ if (PMD_RD_FUNC(cnum)) { - ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value, regs); + unsigned long v = val; + ret = PMD_RD_FUNC(cnum)(task, cnum, &v, regs); + val = v; } - PFM_REG_RETFLAG_SET(tmp.reg_flags, ret); + PFM_REG_RETFLAG_SET(reg_flags, 0); DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", - cnum, ret, val, ia64_get_pmc(cnum))); - - if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; + cnum, ret, val, ia64_get_pmc(cnum))); + /* + * update register return value, abort all if problem during copy. + * we only modify the reg_flags field. no check mode is fine because + * access has been verified upfront in sys_perfmonctl(). + */ + if (__put_user(cnum, &req->reg_num)) return -EFAULT; + if (__put_user(val, &req->reg_value)) return -EFAULT; + if (__put_user(reg_flags, &req->reg_flags)) return -EFAULT; } + return 0; + abort_mission: - PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL); - /* - * XXX: if this fails, we stick with the original failure, flag not updated! - */ - copy_to_user(req, &tmp, sizeof(tmp)); - return -EINVAL; + PFM_REG_RETFLAG_SET(reg_flags, PFM_REG_RETFL_EINVAL); + if (__put_user(reg_flags, &req->reg_flags)) ret = -EFAULT; + + return ret; } #ifdef PFM_PMU_USES_DBR @@ -1697,44 +1770,6 @@ return 0; } -#ifndef CONFIG_SMP -/* - * On UP kernels, we do not need to constantly set the psr.pp bit - * when a task is scheduled. The psr.pp bit can only be changed in - * the kernel because of a user request. Given we are on a UP non preeemptive - * kernel we know that no other task is running, so we cna simply update their - * psr.pp from their saved state. There is this no impact on the context switch - * code compared to the SMP case. - */ -static void -pfm_tasklist_toggle_pp(unsigned int val) -{ - struct task_struct *p; - struct pt_regs *regs; - - DBprintk(("invoked by [%d] pp=%u\n", current->pid, val)); - - read_lock(&tasklist_lock); - - for_each_task(p) { - regs = (struct pt_regs *)((unsigned long) p + IA64_STK_OFFSET); - - /* - * position on pt_regs saved on stack on 1st entry into the kernel - */ - regs--; - - /* - * update psr.pp - */ - ia64_psr(regs)->pp = val; - } - read_unlock(&tasklist_lock); -} -#endif - - - static int pfm_stop(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) @@ -1763,11 +1798,8 @@ ia64_srlz_i(); -#ifdef CONFIG_SMP __get_cpu_var(pfm_dcr_pp) = 0; -#else - pfm_tasklist_toggle_pp(0); -#endif + ia64_psr(regs)->pp = 0; } else { @@ -2013,7 +2045,7 @@ for (i = 0; i < count; i++, req++) { - if (copy_from_user(&tmp, req, sizeof(tmp))) goto abort_mission; + if (__copy_from_user(&tmp, req, sizeof(tmp))) goto abort_mission; rnum = tmp.dbreg_num; dbreg.val = tmp.dbreg_value; @@ -2046,7 +2078,7 @@ PFM_REG_RETFLAG_SET(tmp.dbreg_flags, 0); - if (copy_to_user(req, &tmp, sizeof(tmp))) goto abort_mission; + if (__copy_to_user(req, &tmp, sizeof(tmp))) goto abort_mission; /* * Debug registers, just like PMC, can only be modified @@ -2101,7 +2133,7 @@ * XXX: for now we can only come here on EINVAL */ PFM_REG_RETFLAG_SET(tmp.dbreg_flags, PFM_REG_RETFL_EINVAL); - copy_to_user(req, &tmp, sizeof(tmp)); + __put_user(tmp.dbreg_flags, &req->dbreg_flags); } return ret; } @@ -2142,7 +2174,7 @@ tmp.ft_version = PFM_VERSION; tmp.ft_smpl_version = PFM_SMPL_VERSION; - if (copy_to_user(arg, &tmp, sizeof(tmp))) return -EFAULT; + if (__copy_to_user(arg, &tmp, sizeof(tmp))) return -EFAULT; return 0; } @@ -2171,11 +2203,8 @@ if (ctx->ctx_fl_system) { -#ifdef CONFIG_SMP __get_cpu_var(pfm_dcr_pp) = 1; -#else - pfm_tasklist_toggle_pp(1); -#endif + /* set user level psr.pp */ ia64_psr(regs)->pp = 1; @@ -2226,10 +2255,8 @@ __asm__ __volatile__ ("rsm psr.pp;;"::: "memory"); ia64_srlz_i(); -#ifdef CONFIG_SMP - __get_cpu_var(pfm_syst_wide) = 1; __get_cpu_var(pfm_dcr_pp) = 0; -#endif + __get_cpu_var(pfm_syst_wide) = 1; } else { /* * needed in case the task was a passive task during @@ -2270,11 +2297,11 @@ { pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; unsigned int cnum; - int i; + int i, ret = -EINVAL; for (i = 0; i < count; i++, req++) { - if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; + if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT; cnum = tmp.reg_num; @@ -2286,16 +2313,13 @@ DBprintk(("pmc_reset_val pmc[%u]=0x%lx\n", cnum, tmp.reg_value)); - if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; + if (__copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT; } return 0; abort_mission: PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL); - /* - * XXX: if this fails, we stick with the original failure, flag not updated! - */ - copy_to_user(req, &tmp, sizeof(tmp)); - return -EINVAL; + if (__copy_to_user(req, &tmp, sizeof(tmp))) ret = -EFAULT; + return ret; } /* @@ -2303,21 +2327,21 @@ */ static pfm_cmd_desc_t pfm_cmd_tab[]={ /* 0 */{ NULL, 0, 0, 0}, /* not used */ -/* 1 */{ pfm_write_pmcs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, -/* 2 */{ pfm_write_pmds, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, -/* 3 */{ pfm_read_pmds,PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, +/* 1 */{ pfm_write_pmcs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, +/* 2 */{ pfm_write_pmds, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, +/* 3 */{ pfm_read_pmds,PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, /* 4 */{ pfm_stop, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, /* 5 */{ pfm_start, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, /* 6 */{ pfm_enable, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, /* 7 */{ pfm_disable, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, -/* 8 */{ pfm_context_create, PFM_CMD_PID|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, 1, sizeof(pfarg_context_t)}, +/* 8 */{ pfm_context_create, PFM_CMD_PID|PFM_CMD_ARG_RW, 1, sizeof(pfarg_context_t)}, /* 9 */{ pfm_context_destroy, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, /* 10 */{ pfm_restart, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_NOCHK, 0, 0}, /* 11 */{ pfm_protect_context, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, -/* 12 */{ pfm_get_features, PFM_CMD_ARG_WRITE, 0, 0}, +/* 12 */{ pfm_get_features, PFM_CMD_ARG_RW, 0, 0}, /* 13 */{ pfm_debug, 0, 1, sizeof(unsigned int)}, /* 14 */{ pfm_context_unprotect, PFM_CMD_PID|PFM_CMD_CTX, 0, 0}, -/* 15 */{ pfm_get_pmc_reset, PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, +/* 15 */{ pfm_get_pmc_reset, PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, /* 16 */{ NULL, 0, 0, 0}, /* not used */ /* 17 */{ NULL, 0, 0, 0}, /* not used */ /* 18 */{ NULL, 0, 0, 0}, /* not used */ @@ -2335,8 +2359,8 @@ /* 30 */{ NULL, 0, 0, 0}, /* not used */ /* 31 */{ NULL, 0, 0, 0}, /* not used */ #ifdef PFM_PMU_USES_DBR -/* 32 */{ pfm_write_ibrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)}, -/* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)} +/* 32 */{ pfm_write_ibrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)}, +/* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)} #endif }; #define PFM_CMD_COUNT (sizeof(pfm_cmd_tab)/sizeof(pfm_cmd_desc_t)) @@ -2345,19 +2369,22 @@ check_task_state(struct task_struct *task) { int ret = 0; - +#ifdef CONFIG_SMP /* We must wait until the state has been completely * saved. There can be situations where the reader arrives before * after the task is marked as STOPPED but before pfm_save_regs() * is completed. */ + if (task->state != TASK_ZOMBIE && task->state != TASK_STOPPED) return -EBUSY; + DBprintk(("before wait_task_inactive [%d] state %ld\n", task->pid, task->state)); + wait_task_inactive(task); + DBprintk(("after wait_task_inactive [%d] state %ld\n", task->pid, task->state)); +#else if (task->state != TASK_ZOMBIE && task->state != TASK_STOPPED) { DBprintk(("warning [%d] not in stable state %ld\n", task->pid, task->state)); ret = -EBUSY; } - DBprintk(("before wait_task_inactive [%d] state %ld\n", task->pid, task->state)); - wait_task_inactive(task); - DBprintk(("after wait_task_inactive [%d] state %ld\n", task->pid, task->state)); +#endif return ret; } @@ -2389,7 +2416,7 @@ if (PFM_CMD_READ_ARG(cmd) && !access_ok(VERIFY_READ, arg, sz*count)) return -EFAULT; - if (PFM_CMD_WRITE_ARG(cmd) && !access_ok(VERIFY_WRITE, arg, sz*count)) return -EFAULT; + if (PFM_CMD_RW_ARG(cmd) && !access_ok(VERIFY_WRITE, arg, sz*count)) return -EFAULT; if (PFM_CMD_USE_PID(cmd)) { /* @@ -2551,9 +2578,16 @@ */ h->pid = current->pid; h->cpu = smp_processor_id(); - h->rate = 0; /* XXX: add the sampling rate used here */ - h->ip = regs ? regs->cr_iip : 0x0; /* where did the fault happened */ - h->regs = ovfl_mask; /* which registers overflowed */ + h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL; + /* + * where did the fault happen + */ + h->ip = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL; + + /* + * which registers overflowed + */ + h->regs = ovfl_mask; /* guaranteed to monotonically increase on each cpu */ h->stamp = pfm_get_stamp(); @@ -2572,15 +2606,13 @@ if (PMD_IS_COUNTING(j)) { *e = pfm_read_soft_counter(ctx, j); - /* check if this pmd overflowed as well */ - *e += ovfl_mask & (1UL<ctx_soft_pmds[i].val)); /* - * Because we sometimes (EARS/BTB) reset to a specific value, we cannot simply use - * val to count the number of times we overflowed. Otherwise we would loose the - * current value in the PMD (which can be >0). So to make sure we don't loose - * the residual counts we set val to contain full 64bits value of the counter. + * Note that the pmd is not necessarily 0 at this point as qualified events + * may have happened before the PMU was frozen. The residual count is not + * taken into consideration here but will be with any read of the pmd via + * pfm_read_pmds(). */ old_val = ctx->ctx_soft_pmds[i].val; - ctx->ctx_soft_pmds[i].val = 1 + pmu_conf.perf_ovfl_val + pfm_read_soft_counter(ctx, i); - - DBprintk_ovfl(("soft_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx\n", - i, ctx->ctx_soft_pmds[i].val, old_val, - ia64_get_pmd(i) & pmu_conf.perf_ovfl_val)); - - /* - * now that we have extracted the hardware counter, we can clear it to ensure - * that a subsequent PFM_READ_PMDS will not include it again. - */ - ia64_set_pmd(i, 0UL); + ctx->ctx_soft_pmds[i].val += 1 + pmu_conf.perf_ovfl_val; /* * check for overflow condition @@ -2699,12 +2721,15 @@ ovfl_pmds |= 1UL << i; - DBprintk_ovfl(("soft_pmd[%d] overflowed flags=0x%x, ovfl=0x%lx\n", i, ctx->ctx_soft_pmds[i].flags, ovfl_pmds)); - if (PMC_OVFL_NOTIFY(ctx, i)) { ovfl_notify |= 1UL << i; } } + DBprintk_ovfl(("soft_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n", + i, ctx->ctx_soft_pmds[i].val, old_val, + ia64_get_pmd(i) & pmu_conf.perf_ovfl_val, ovfl_pmds, ovfl_notify)); + + } /* @@ -2893,7 +2918,7 @@ struct task_struct *task; pfm_context_t *ctx; - pfm_stats.pfm_ovfl_intr_count++; + pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++; /* * srlz.d done before arriving here @@ -2951,10 +2976,7 @@ atomic_set(&ctx->ctx_is_busy, 0); #endif } else { - pfm_stats.pfm_spurious_ovfl_intr_count++; - - printk("perfmon: Spurious PMU overflow interrupt on CPU%d: pmc0=0x%lx owner=%p\n", - smp_processor_id(), pmc0, (void *)PMU_OWNER()); + pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } } @@ -2965,28 +2987,24 @@ char *p = page; int i; - p += sprintf(p, "enabled : %s\n", pmu_conf.pfm_is_disabled ? "No": "Yes"); - p += sprintf(p, "fastctxsw : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No"); - p += sprintf(p, "ovfl_mask : 0x%lx\n", pmu_conf.perf_ovfl_val); - p += sprintf(p, "overflow intrs : %lu\n", pfm_stats.pfm_ovfl_intr_count); - p += sprintf(p, "spurious intrs : %lu\n", pfm_stats.pfm_spurious_ovfl_intr_count); - p += sprintf(p, "recorded samples : %lu\n", pfm_stats.pfm_recorded_samples_count); - p += sprintf(p, "smpl buffer full : %lu\n", pfm_stats.pfm_full_smpl_buffer_count); + p += sprintf(p, "enabled : %s\n", pmu_conf.pfm_is_disabled ? "No": "Yes"); + p += sprintf(p, "fastctxsw : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No"); + p += sprintf(p, "ovfl_mask : 0x%lx\n", pmu_conf.perf_ovfl_val); -#ifdef CONFIG_SMP - p += sprintf(p, "CPU%d syst_wide : %d\n" - "CPU%d dcr_pp : %d\n", - smp_processor_id(), - __get_cpu_var(pfm_syst_wide), - smp_processor_id(), - __get_cpu_var(pfm_dcr_pp)); -#endif + for(i=0; i < NR_CPUS; i++) { + if (cpu_is_online(i) == 0) continue; + p += sprintf(p, "CPU%-2d overflow intrs : %lu\n", i, pfm_stats[i].pfm_ovfl_intr_count); + p += sprintf(p, "CPU%-2d spurious intrs : %lu\n", i, pfm_stats[i].pfm_spurious_ovfl_intr_count); + p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count); + p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count); + p += sprintf(p, "CPU%-2d owner : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1); + } LOCK_PFS(); - p += sprintf(p, "proc_sessions : %lu\n" - "sys_sessions : %lu\n" - "sys_use_dbregs : %lu\n" - "ptrace_use_dbregs: %lu\n", + p += sprintf(p, "proc_sessions : %lu\n" + "sys_sessions : %lu\n" + "sys_use_dbregs : %lu\n" + "ptrace_use_dbregs : %lu\n", pfm_sessions.pfs_task_sessions, pfm_sessions.pfs_sys_sessions, pfm_sessions.pfs_sys_use_dbregs, @@ -2994,30 +3012,6 @@ UNLOCK_PFS(); - for(i=0; i < NR_CPUS; i++) { - if (cpu_is_online(i)) { - p += sprintf(p, "CPU%d owner : %-6d\n", - i, - pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1); - } - } - - for(i=0; pmd_desc[i].type != PFM_REG_NONE; i++) { - p += sprintf(p, "PMD%-2d: %d 0x%lx 0x%lx\n", - i, - pmd_desc[i].type, - pmd_desc[i].dep_pmd[0], - pmd_desc[i].dep_pmc[0]); - } - - for(i=0; pmc_desc[i].type != PFM_REG_NONE; i++) { - p += sprintf(p, "PMC%-2d: %d 0x%lx 0x%lx\n", - i, - pmc_desc[i].type, - pmc_desc[i].dep_pmd[0], - pmc_desc[i].dep_pmc[0]); - } - return p - page; } @@ -3038,7 +3032,6 @@ return len; } -#ifdef CONFIG_SMP void pfm_syst_wide_update_task(struct task_struct *task, int mode) { @@ -3051,8 +3044,6 @@ */ ia64_psr(regs)->pp = mode ? __get_cpu_var(pfm_dcr_pp) : 0; } -#endif - void pfm_save_regs (struct task_struct *task) @@ -3292,6 +3283,30 @@ owner = PMU_OWNER(); ctx = task->thread.pfm_context; + t = &task->thread; + + /* + * we restore ALL the debug registers to avoid picking up + * stale state. + * + * This must be done even when the task is still the owner + * as the registers may have been modified via ptrace() + * (not perfmon) by the previous task. + * + * XXX: dealing with this in a lazy fashion requires modifications + * to the way the the debug registers are managed. This is will done + * in the next version of perfmon. + */ + if (ctx->ctx_fl_using_dbreg) { + for (i=0; i < pmu_conf.num_ibrs; i++) { + ia64_set_ibr(i, t->ibr[i]); + } + ia64_srlz_i(); + for (i=0; i < pmu_conf.num_dbrs; i++) { + ia64_set_dbr(i, t->dbr[i]); + } + ia64_srlz_d(); + } /* * if we were the last user, then nothing to do except restore psr @@ -3327,7 +3342,6 @@ pfm_fetch_regs(cpu, task, ctx); } #endif - t = &task->thread; /* * To avoid leaking information to the user level when psr.sp=0, @@ -3357,21 +3371,6 @@ if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]); } - /* - * we restore ALL the debug registers to avoid picking up - * stale state. - */ - if (ctx->ctx_fl_using_dbreg) { - for (i=0; i < pmu_conf.num_ibrs; i++) { - ia64_set_ibr(i, t->ibr[i]); - } - ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { - ia64_set_dbr(i, t->dbr[i]); - } - } - ia64_srlz_d(); - if (t->pmc[0] & ~0x1) { pfm_overflow_handler(task, ctx, t->pmc[0], NULL); } @@ -3542,12 +3541,8 @@ ia64_srlz_i(); -#ifdef CONFIG_SMP __get_cpu_var(pfm_syst_wide) = 0; __get_cpu_var(pfm_dcr_pp) = 0; -#else - pfm_tasklist_toggle_pp(0); -#endif } else { /* stop monitoring */ @@ -3766,18 +3761,12 @@ m = nctx->ctx_used_pmds[0] >> PMU_FIRST_COUNTER; for(i = PMU_FIRST_COUNTER ; m ; m>>=1, i++) { if ((m & 0x1) && pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING) { - nctx->ctx_soft_pmds[i].val = nctx->ctx_soft_pmds[i].ival & ~pmu_conf.perf_ovfl_val; - thread->pmd[i] = nctx->ctx_soft_pmds[i].ival & pmu_conf.perf_ovfl_val; + nctx->ctx_soft_pmds[i].val = nctx->ctx_soft_pmds[i].lval & ~pmu_conf.perf_ovfl_val; + thread->pmd[i] = nctx->ctx_soft_pmds[i].lval & pmu_conf.perf_ovfl_val; + } else { + thread->pmd[i] = 0UL; /* reset to initial state */ } - /* what about the other pmds? zero or keep as is */ - } - /* - * clear BTB index register - * XXX: CPU-model specific knowledge! - */ - thread->pmd[16] = 0; - nctx->ctx_fl_frozen = 0; nctx->ctx_ovfl_regs[0] = 0UL; @@ -3947,7 +3936,8 @@ pfm_sessions.pfs_sys_session[ctx->ctx_cpu] = NULL; pfm_sessions.pfs_sys_sessions--; DBprintk(("freeing syswide session on CPU%ld\n", ctx->ctx_cpu)); - /* update perfmon debug register counter */ + + /* update perfmon debug register usage counter */ if (ctx->ctx_fl_using_dbreg) { if (pfm_sessions.pfs_sys_use_dbregs == 0) { printk("perfmon: invalid release for [%d] sys_use_dbregs=0\n", task->pid); @@ -3990,7 +3980,8 @@ * Walk through the list and free the sampling buffer and psb */ while (psb) { - DBprintk(("[%d] freeing smpl @%p size %ld\n", current->pid, psb->psb_hdr, psb->psb_size)); + DBprintk(("[%d] freeing smpl @%p size %ld\n", + current->pid, psb->psb_hdr, psb->psb_size)); pfm_rvfree(psb->psb_hdr, psb->psb_size); tmp = psb->psb_next; @@ -4011,14 +4002,14 @@ void pfm_cleanup_owners(struct task_struct *task) { - struct task_struct *p; + struct task_struct *g, *p; pfm_context_t *ctx; DBprintk(("called by [%d] for [%d]\n", current->pid, task->pid)); read_lock(&tasklist_lock); - for_each_task(p) { + do_each_thread(g, p) { /* * It is safe to do the 2-step test here, because thread.ctx * is cleaned up only in release_thread() and at that point @@ -4056,7 +4047,8 @@ DBprintk(("done for notifier [%d] in [%d]\n", task->pid, p->pid)); } - } + } while_each_thread(g, p); + read_unlock(&tasklist_lock); atomic_set(&task->thread.pfm_owners_check, 0); @@ -4070,23 +4062,21 @@ void pfm_cleanup_notifiers(struct task_struct *task) { - struct task_struct *p; + struct task_struct *g, *p; pfm_context_t *ctx; DBprintk(("called by [%d] for [%d]\n", current->pid, task->pid)); read_lock(&tasklist_lock); - for_each_task(p) { + do_each_thread(g, p) { /* - * It is safe to do the 2-step test here, because thread.ctx - * is cleaned up only in release_thread() and at that point - * the task has been detached from the tasklist which is an - * operation which uses the write_lock() on the tasklist_lock - * so it cannot run concurrently to this loop. So we have the - * guarantee that if we find p and it has a perfmon ctx then - * it is going to stay like this for the entire execution of this - * loop. + * It is safe to do the 2-step test here, because thread.ctx is cleaned up + * only in release_thread() and at that point the task has been detached + * from the tasklist which is an operation which uses the write_lock() on + * the tasklist_lock so it cannot run concurrently to this loop. So we + * have the guarantee that if we find p and it has a perfmon ctx then it + * is going to stay like this for the entire execution of this loop. */ ctx = p->thread.pfm_context; @@ -4095,16 +4085,16 @@ if (ctx && ctx->ctx_notify_task == task) { DBprintk(("trying for notifier [%d] in [%d]\n", task->pid, p->pid)); /* - * the spinlock is required to take care of a race condition - * with the send_sig_info() call. We must make sure that - * either the send_sig_info() completes using a valid task, - * or the notify_task is cleared before the send_sig_info() - * can pick up a stale value. Note that by the time this - * function is executed the 'task' is already detached from the - * tasklist. The problem is that the notifiers have a direct - * pointer to it. It is okay to send a signal to a task in this - * stage, it simply will have no effect. But it is better than sending - * to a completely destroyed task or worse to a new task using the same + * the spinlock is required to take care of a race condition with + * the send_sig_info() call. We must make sure that either the + * send_sig_info() completes using a valid task, or the + * notify_task is cleared before the send_sig_info() can pick up a + * stale value. Note that by the time this function is executed + * the 'task' is already detached from the tasklist. The problem + * is that the notifiers have a direct pointer to it. It is okay + * to send a signal to a task in this stage, it simply will have + * no effect. But it is better than sending to a completely + * destroyed task or worse to a new task using the same * task_struct address. */ LOCK_CTX(ctx); @@ -4115,7 +4105,8 @@ DBprintk(("done for notifier [%d] in [%d]\n", task->pid, p->pid)); } - } + } while_each_thread(g, p); + read_unlock(&tasklist_lock); atomic_set(&task->thread.pfm_notifiers_check, 0); diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/process.c Sat Sep 21 21:25:45 2002 @@ -81,6 +81,12 @@ } void +dump_stack (void) +{ + show_stack(NULL); +} + +void show_regs (struct pt_regs *regs) { unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri; @@ -248,18 +254,15 @@ * | | <-- sp (lowest addr) * +---------------------+ * - * Note: if we get called through kernel_thread() then the memory - * above "(highest addr)" is valid kernel stack memory that needs to - * be copied as well. - * - * Observe that we copy the unat values that are in pt_regs and - * switch_stack. Spilling an integer to address X causes bit N in - * ar.unat to be set to the NaT bit of the register, with N=(X & - * 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY - * if the pt_regs structure in the parent is congruent to that of the - * child, modulo 512. Since the stack is page aligned and the page - * size is at least 4KB, this is always the case, so there is nothing - * to worry about. + * Note: if we get called through kernel_thread() then the memory above "(highest addr)" + * is valid kernel stack memory that needs to be copied as well. + * + * Observe that we copy the unat values that are in pt_regs and switch_stack. Spilling an + * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register, + * with N=(X & 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY if the + * pt_regs structure in the parent is congruent to that of the child, modulo 512. Since + * the stack is page aligned and the page size is at least 4KB, this is always the case, + * so there is nothing to worry about. */ int copy_thread (int nr, unsigned long clone_flags, @@ -300,6 +303,8 @@ memcpy((void *) child_rbs, (void *) rbs, rbs_size); if (user_mode(child_ptregs)) { + if (clone_flags & CLONE_SETTLS) + child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ if (user_stack_base) { child_ptregs->r12 = user_stack_base + user_stack_size - 16; child_ptregs->ar_bspstore = user_stack_base; diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/kernel/ptrace.c Sat Sep 21 21:25:48 2002 @@ -474,7 +474,7 @@ { struct switch_stack *sw; unsigned long urbs_end; - struct task_struct *p; + struct task_struct *g, *p; struct mm_struct *mm; struct pt_regs *pt; long multi_threaded; @@ -495,7 +495,7 @@ } else { read_lock(&tasklist_lock); { - for_each_task(p) { + do_each_thread(g, p) { if (p->mm == mm && p->state != TASK_RUNNING) { sw = (struct switch_stack *) (p->thread.ksp + 16); pt = ia64_task_regs(p); @@ -504,7 +504,7 @@ if (make_writable) user_flushrs(p, pt); } - } + } while_each_thread(g, p); } read_unlock(&tasklist_lock); } diff -Nru a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c --- a/arch/ia64/kernel/semaphore.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/semaphore.c Sat Sep 21 21:25:45 2002 @@ -15,8 +15,8 @@ * test if they need to do any extra work (up needs to do something * only if count was negative before the increment operation. * - * "sleepers" and the contention routine ordering is protected by the - * semaphore spinlock. + * "sleeping" and the contention routine ordering is protected + * by the spinlock in the semaphore's waitqueue head. * * Note that these functions are only called when there is contention * on the lock, and as such all this is the "non-critical" part of the @@ -44,40 +44,42 @@ wake_up(&sem->wait); } -static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; - void __down (struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); + unsigned long flags; + tsk->state = TASK_UNINTERRUPTIBLE; - add_wait_queue_exclusive(&sem->wait, &wait); + spin_lock_irqsave(&sem->wait.lock, flags); + add_wait_queue_exclusive_locked(&sem->wait, &wait); - spin_lock_irq(&semaphore_lock); sem->sleepers++; for (;;) { int sleepers = sem->sleepers; /* * Add "everybody else" into it. They aren't - * playing, because we own the spinlock. + * playing, because we own the spinlock in + * the wait_queue_head. */ if (!atomic_add_negative(sleepers - 1, &sem->count)) { sem->sleepers = 0; break; } sem->sleepers = 1; /* us - see -1 above */ - spin_unlock_irq(&semaphore_lock); + spin_unlock_irqrestore(&sem->wait.lock, flags); schedule(); + + spin_lock_irqsave(&sem->wait.lock, flags); tsk->state = TASK_UNINTERRUPTIBLE; - spin_lock_irq(&semaphore_lock); } - spin_unlock_irq(&semaphore_lock); - remove_wait_queue(&sem->wait, &wait); + remove_wait_queue_locked(&sem->wait, &wait); + wake_up_locked(&sem->wait); + spin_unlock_irqrestore(&sem->wait.lock, flags); tsk->state = TASK_RUNNING; - wake_up(&sem->wait); } int @@ -86,10 +88,12 @@ int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); + unsigned long flags; + tsk->state = TASK_INTERRUPTIBLE; - add_wait_queue_exclusive(&sem->wait, &wait); + spin_lock_irqsave(&sem->wait.lock, flags); + add_wait_queue_exclusive_locked(&sem->wait, &wait); - spin_lock_irq(&semaphore_lock); sem->sleepers ++; for (;;) { int sleepers = sem->sleepers; @@ -110,25 +114,27 @@ /* * Add "everybody else" into it. They aren't - * playing, because we own the spinlock. The - * "-1" is because we're still hoping to get - * the lock. + * playing, because we own the spinlock in + * wait_queue_head. The "-1" is because we're + * still hoping to get the semaphore. */ if (!atomic_add_negative(sleepers - 1, &sem->count)) { sem->sleepers = 0; break; } sem->sleepers = 1; /* us - see -1 above */ - spin_unlock_irq(&semaphore_lock); + spin_unlock_irqrestore(&sem->wait.lock, flags); schedule(); + + spin_lock_irqsave(&sem->wait.lock, flags); tsk->state = TASK_INTERRUPTIBLE; - spin_lock_irq(&semaphore_lock); } - spin_unlock_irq(&semaphore_lock); + remove_wait_queue_locked(&sem->wait, &wait); + wake_up_locked(&sem->wait); + spin_unlock_irqrestore(&sem->wait.lock, flags); + tsk->state = TASK_RUNNING; - remove_wait_queue(&sem->wait, &wait); - wake_up(&sem->wait); return retval; } @@ -142,17 +148,19 @@ unsigned long flags; int sleepers; - spin_lock_irqsave(&semaphore_lock, flags); + spin_lock_irqsave(&sem->wait.lock, flags); sleepers = sem->sleepers + 1; sem->sleepers = 0; /* * Add "everybody else" and us into it. They aren't - * playing, because we own the spinlock. + * playing, because we own the spinlock in the + * wait_queue_head. */ - if (!atomic_add_negative(sleepers, &sem->count)) - wake_up(&sem->wait); + if (!atomic_add_negative(sleepers, &sem->count)) { + wake_up_locked(&sem->wait); + } - spin_unlock_irqrestore(&semaphore_lock, flags); + spin_unlock_irqrestore(&sem->wait.lock, flags); return 1; } diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/signal.c Sat Sep 21 21:25:45 2002 @@ -354,6 +354,15 @@ return err; } +/* + * Check whether the register-backing store is already on the signal stack. + */ +static inline int +rbs_on_sig_stack (unsigned long bsp) +{ + return (bsp - current->sas_ss_sp < current->sas_ss_size); +} + static long setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr) @@ -366,10 +375,17 @@ frame = (void *) scr->pt.r12; tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section); - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack((unsigned long) frame)) { - new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); - frame = (void *) ((current->sas_ss_sp + current->sas_ss_size) - & ~(STACK_ALIGN - 1)); + if (ka->sa.sa_flags & SA_ONSTACK) { + /* + * We need to check the memory and register stacks separately, because + * they're switched separately (memory stack is switched in the kernel, + * register stack is switched in the signal trampoline). + */ + if (!on_sig_stack((unsigned long) frame)) + frame = (void *) ((current->sas_ss_sp + current->sas_ss_size) + & ~(STACK_ALIGN - 1)); + if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) + new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); } frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); @@ -460,7 +476,6 @@ long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { - struct signal_struct *sig; struct k_sigaction *ka; siginfo_t info; long restart = in_syscall; @@ -487,7 +502,7 @@ } } else #endif - if (scr->pt.r10 != -1) { + if (scr->pt.r10 != -1) /* * A system calls has to be restarted only if one of the error codes * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 @@ -495,101 +510,14 @@ * restart the syscall, so we can clear the "restart" flag here. */ restart = 0; - } - - for (;;) { - unsigned long signr; - spin_lock_irq(¤t->sigmask_lock); - signr = dequeue_signal(¤t->blocked, &info); - spin_unlock_irq(¤t->sigmask_lock); + while (1) { + int signr = get_signal_to_deliver(&info, &scr->pt); - if (!signr) + if (signr <= 0) break; - if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { - /* Let the debugger run. */ - current->exit_code = signr; - current->thread.siginfo = &info; - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); - - signr = current->exit_code; - current->thread.siginfo = 0; - - /* We're back. Did the debugger cancel the sig? */ - if (!signr) - continue; - current->exit_code = 0; - - /* The debugger continued. Ignore SIGSTOP. */ - if (signr == SIGSTOP) - continue; - - /* Update the siginfo structure. Is this good? */ - if (signr != info.si_signo) { - info.si_signo = signr; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->parent->pid; - info.si_uid = current->parent->uid; - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(¤t->blocked, signr)) { - send_sig_info(signr, &info, current); - continue; - } - } - ka = ¤t->sig->action[signr - 1]; - if (ka->sa.sa_handler == SIG_IGN) { - if (signr != SIGCHLD) - continue; - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; - continue; - } - - if (ka->sa.sa_handler == SIG_DFL) { - int exit_code = signr; - - /* Init gets no signals it doesn't want. */ - if (current->pid == 1) - continue; - - switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: - continue; - - case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) - continue; - /* FALLTHRU */ - - case SIGSTOP: - current->state = TASK_STOPPED; - current->exit_code = signr; - sig = current->parent->sig; - if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) - notify_parent(current, SIGCHLD); - schedule(); - continue; - - case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGABRT: case SIGFPE: case SIGSEGV: - case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: - if (do_coredump(signr, &scr->pt)) - exit_code |= 0x80; - /* FALLTHRU */ - - default: - sig_exit(signr, exit_code, &info); - /* NOTREACHED */ - } - } if (restart) { switch (errno) { @@ -601,7 +529,7 @@ scr->pt.r8 = -EINTR; else #endif - scr->pt.r8 = EINTR; + scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; } @@ -612,13 +540,14 @@ scr->pt.cr_iip -= 2; } else #endif - ia64_decrement_ip(&scr->pt); + ia64_decrement_ip(&scr->pt); } } - /* Whee! Actually deliver the signal. If the - delivery failed, we need to continue to iterate in - this loop so we can deliver the SIGSEGV... */ + /* + * Whee! Actually deliver the signal. If the delivery failed, we need to + * continue to iterate in this loop so we can deliver the SIGSEGV... + */ if (handle_signal(signr, ka, &info, oldset, scr)) return 1; } @@ -634,9 +563,8 @@ } else #endif /* - * Note: the syscall number is in r15 which is - * saved in pt_regs so all we need to do here - * is adjust ip so that the "break" + * Note: the syscall number is in r15 which is saved in pt_regs so + * all we need to do here is adjust ip so that the "break" * instruction gets re-executed. */ ia64_decrement_ip(&scr->pt); diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/smpboot.c Sat Sep 21 21:25:45 2002 @@ -257,31 +257,6 @@ local_cpu_data->prof_multiplier = 1; } -/* - * Architecture specific routine called by the kernel just before init is - * fired off. This allows the BP to have everything in order [we hope]. - * At the end of this all the APs will hit the system scheduling and off - * we go. Each AP will jump through the kernel - * init into idle(). At this point the scheduler will one day take over - * and give them jobs to do. smp_callin is a standard routine - * we use to track CPUs as they power up. - */ - -static volatile atomic_t smp_commenced = ATOMIC_INIT(0); - -static void __init -smp_commence (void) -{ - /* - * Lets the callins below out of their loop. - */ - Dprintk("Setting commenced=1, go go go\n"); - - wmb(); - atomic_set(&smp_commenced, 1); -} - - static void __init smp_callin (void) { @@ -361,7 +336,7 @@ * don't care about the eip and regs settings since we'll never reschedule the * forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0); + return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL); } static int __init diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c --- a/arch/ia64/kernel/sys_ia64.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/sys_ia64.c Sat Sep 21 21:25:45 2002 @@ -19,6 +19,12 @@ #include #include +#ifdef CONFIG_HUGETLB_PAGE +# define SHMLBA_HPAGE HPAGE_SIZE +# define COLOR_HALIGN(addr) (((addr) + SHMLBA_HPAGE - 1) & ~(SHMLBA_HPAGE - 1)) +# define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE) +#endif + unsigned long arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -56,16 +62,14 @@ } asmlinkage long -ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6, - long arg7, long stack) +ia64_getpriority (int which, int who) { - struct pt_regs *regs = (struct pt_regs *) &stack; extern long sys_getpriority (int, int); long prio; prio = sys_getpriority(which, who); if (prio >= 0) { - regs->r8 = 0; /* ensure negative priority is not mistaken as error code */ + force_successful_syscall_return(); prio = 20 - prio; } return prio; @@ -79,10 +83,8 @@ } asmlinkage unsigned long -ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6, - long arg7, long stack) +ia64_shmat (int shmid, void *shmaddr, int shmflg) { - struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long raddr; int retval; @@ -90,16 +92,14 @@ if (retval < 0) return retval; - regs->r8 = 0; /* ensure negative addresses are not mistaken as an error code */ + force_successful_syscall_return(); return raddr; } asmlinkage unsigned long -ia64_brk (unsigned long brk, long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6, long arg7, long stack) +ia64_brk (unsigned long brk) { extern int vm_enough_memory (long pages); - struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long rlim, retval, newbrk, oldbrk; struct mm_struct *mm = current->mm; @@ -145,7 +145,7 @@ out: retval = mm->brk; up_write(&mm->mmap_sem); - regs->r8 = 0; /* ensure large retval isn't mistaken as error code */ + force_successful_syscall_return(); return retval; } @@ -222,32 +222,98 @@ * of) files that are larger than the address space of the CPU. */ asmlinkage unsigned long -sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff, - long arg6, long arg7, long stack) +sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) { - struct pt_regs *regs = (struct pt_regs *) &stack; - addr = do_mmap2(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) - regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ + force_successful_syscall_return(); return addr; } asmlinkage unsigned long -sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, - int fd, long off, long arg6, long arg7, long stack) +sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off) { - struct pt_regs *regs = (struct pt_regs *) &stack; - if ((off & ~PAGE_MASK) != 0) return -EINVAL; addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); if (!IS_ERR((void *) addr)) - regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ + force_successful_syscall_return(); return addr; } +#ifdef CONFIG_HUGETLB_PAGE + +asmlinkage unsigned long +sys_alloc_hugepages (int key, unsigned long addr, size_t len, int prot, int flag) +{ + struct mm_struct *mm = current->mm; + long retval; + extern int alloc_hugetlb_pages (int, unsigned long, unsigned long, int, int); + + if ((key < 0) || (len & (HPAGE_SIZE - 1))) + return -EINVAL; + + if (addr && ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))) + addr = TASK_HPAGE_BASE; + + if (!addr) + addr = TASK_HPAGE_BASE; + down_write(&mm->mmap_sem); + { + retval = arch_get_unmapped_area(NULL, COLOR_HALIGN(addr), len, 0, 0); + if (retval != -ENOMEM) + retval = alloc_hugetlb_pages(key, retval, len, prot, flag); + } + up_write(&mm->mmap_sem); + + if (IS_ERR((void *) retval)) + return retval; + + force_successful_syscall_return(); + return retval; +} + +asmlinkage int +sys_free_hugepages (unsigned long addr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + extern int free_hugepages(struct vm_area_struct *); + int retval; + + vma = find_vma(mm, addr); + if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr)) + return -EINVAL; + + down_write(&mm->mmap_sem); + { + spin_lock(&mm->page_table_lock); + { + retval = free_hugepages(vma); + } + spin_unlock(&mm->page_table_lock); + } + up_write(&mm->mmap_sem); + return retval; +} + +#else /* !CONFIG_HUGETLB_PAGE */ + +asmlinkage unsigned long +sys_alloc_hugepages (int key, size_t addr, unsigned long len, int prot, int flag) +{ + return -ENOSYS; +} + +asmlinkage unsigned long +sys_free_hugepages (unsigned long addr) +{ + return -ENOSYS; +} + +#endif /* !CONFIG_HUGETLB_PAGE */ + asmlinkage long sys_vm86 (long arg0, long arg1, long arg2, long arg3) { @@ -256,16 +322,14 @@ } asmlinkage unsigned long -ia64_create_module (const char *name_user, size_t size, long arg2, long arg3, - long arg4, long arg5, long arg6, long arg7, long stack) +ia64_create_module (const char *name_user, size_t size) { extern unsigned long sys_create_module (const char *, size_t); - struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long addr; addr = sys_create_module (name_user, size); if (!IS_ERR((void *) addr)) - regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ + force_successful_syscall_return(); return addr; } diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/kernel/time.c Sat Sep 21 21:25:45 2002 @@ -104,7 +104,8 @@ tv->tv_sec--; } - xtime = *tv; + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = 1000 * tv->tv_usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -135,7 +136,7 @@ } while (cmpxchg(&last_time_offset, old, usec) != old); sec = xtime.tv_sec; - usec += xtime.tv_usec; + usec += xtime.tv_nsec / 1000; } read_unlock_irqrestore(&xtime_lock, flags); diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile --- a/arch/ia64/lib/Makefile Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/lib/Makefile Sat Sep 21 21:25:48 2002 @@ -15,6 +15,7 @@ obj-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o obj-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o +obj-$(CONFIG_PERFMON) += carta_random.o IGNORE_FLAGS_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o diff -Nru a/arch/ia64/lib/carta_random.S b/arch/ia64/lib/carta_random.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/lib/carta_random.S Sat Sep 21 21:25:48 2002 @@ -0,0 +1,54 @@ +/* + * Fast, simple, yet decent quality random number generator based on + * a paper by David G. Carta ("Two Fast Implementations of the + * `Minimal Standard' Random Number Generator," Communications of the + * ACM, January, 1990). + * + * Copyright (C) 2002 Hewlett-Packard Co + * David Mosberger-Tang + */ + +#include + +#define a r2 +#define m r3 +#define lo r8 +#define hi r9 +#define t0 r16 +#define t1 r17 +#define seed r32 + +GLOBAL_ENTRY(carta_random32) + movl a = (16807 << 16) | 16807 + ;; + pmpyshr2.u t0 = a, seed, 0 + pmpyshr2.u t1 = a, seed, 16 + ;; + unpack2.l t0 = t1, t0 + dep m = -1, r0, 0, 31 + ;; + zxt4 lo = t0 + shr.u hi = t0, 32 + ;; + dep t0 = 0, hi, 15, 49 // t0 = (hi & 0x7fff) + ;; + shl t0 = t0, 16 // t0 = (hi & 0x7fff) << 16 + shr t1 = hi, 15 // t1 = (hi >> 15) + ;; + add lo = lo, t0 + ;; + cmp.gtu p6, p0 = lo, m + ;; +(p6) and lo = lo, m + ;; +(p6) add lo = 1, lo + ;; + add lo = lo, t1 + ;; + cmp.gtu p6, p0 = lo, m + ;; +(p6) and lo = lo, m + ;; +(p6) add lo = 1, lo + br.ret.sptk.many rp +END(carta_random32) diff -Nru a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile --- a/arch/ia64/mm/Makefile Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/mm/Makefile Sat Sep 21 21:25:45 2002 @@ -7,8 +7,7 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -O_TARGET := mm.o - obj-y := init.o fault.o tlb.o extable.o +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o include $(TOPDIR)/Rules.make diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/mm/hugetlbpage.c Sat Sep 21 21:25:48 2002 @@ -0,0 +1,546 @@ +/* + * IA-64 Huge TLB Page Support for Kernel. + * + * Copyright (C) 2002, Rohit Seth + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct vm_operations_struct hugetlb_vm_ops; +struct list_head htlbpage_freelist; +spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; +extern long htlbpagemem; + +static void zap_hugetlb_resources (struct vm_area_struct *); + +#define MAX_ID 32 +struct htlbpagekey { + struct inode *in; + int key; +} htlbpagek[MAX_ID]; + +static struct inode * +find_key_inode(int key) +{ + int i; + + for (i = 0; i < MAX_ID; i++) { + if (htlbpagek[i].key == key) + return (htlbpagek[i].in); + } + return NULL; +} + +static struct page * +alloc_hugetlb_page (void) +{ + struct list_head *curr, *head; + struct page *page; + + spin_lock(&htlbpage_lock); + + head = &htlbpage_freelist; + curr = head->next; + + if (curr == head) { + spin_unlock(&htlbpage_lock); + return NULL; + } + page = list_entry(curr, struct page, list); + list_del(curr); + htlbpagemem--; + spin_unlock(&htlbpage_lock); + set_page_count(page, 1); + memset(page_address(page), 0, HPAGE_SIZE); + return page; +} + +static void +free_hugetlb_page (struct page *page) +{ + spin_lock(&htlbpage_lock); + if ((page->mapping != NULL) && (page_count(page) == 2)) { + struct inode *inode = page->mapping->host; + int i; + + ClearPageDirty(page); + remove_from_page_cache(page); + set_page_count(page, 1); + if ((inode->i_size -= HPAGE_SIZE) == 0) { + for (i = 0; i < MAX_ID; i++) + if (htlbpagek[i].key == inode->i_ino) { + htlbpagek[i].key = 0; + htlbpagek[i].in = NULL; + break; + } + kfree(inode); + } + } + if (put_page_testzero(page)) { + list_add(&page->list, &htlbpage_freelist); + htlbpagemem++; + } + spin_unlock(&htlbpage_lock); +} + +static pte_t * +huge_pte_alloc (struct mm_struct *mm, unsigned long addr) +{ + unsigned long taddr = htlbpage_to_page(addr); + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte = NULL; + + pgd = pgd_offset(mm, taddr); + pmd = pmd_alloc(mm, pgd, taddr); + if (pmd) + pte = pte_alloc_map(mm, pmd, taddr); + return pte; +} + +static pte_t * +huge_pte_offset (struct mm_struct *mm, unsigned long addr) +{ + unsigned long taddr = htlbpage_to_page(addr); + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte = NULL; + + pgd = pgd_offset(mm, taddr); + pmd = pmd_offset(pgd, taddr); + pte = pte_offset_map(pmd, taddr); + return pte; +} + +#define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; } + +static void +set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma, + struct page *page, pte_t * page_table, int write_access) +{ + pte_t entry; + + mm->rss += (HPAGE_SIZE / PAGE_SIZE); + if (write_access) { + entry = + pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); + } else + entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot)); + entry = pte_mkyoung(entry); + mk_pte_huge(entry); + set_pte(page_table, entry); + return; +} + +static int +anon_get_hugetlb_page (struct mm_struct *mm, struct vm_area_struct *vma, + int write_access, pte_t * page_table) +{ + struct page *page; + + page = alloc_hugetlb_page(); + if (page == NULL) + return -1; + set_huge_pte(mm, vma, page, page_table, write_access); + return 1; +} + +static int +make_hugetlb_pages_present (unsigned long addr, unsigned long end, int flags) +{ + int write; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + pte_t *pte; + + vma = find_vma(mm, addr); + if (!vma) + goto out_error1; + + write = (vma->vm_flags & VM_WRITE) != 0; + if ((vma->vm_end - vma->vm_start) & (HPAGE_SIZE - 1)) + goto out_error1; + spin_lock(&mm->page_table_lock); + do { + pte = huge_pte_alloc(mm, addr); + if ((pte) && (pte_none(*pte))) { + if (anon_get_hugetlb_page(mm, vma, write ? VM_WRITE : VM_READ, pte) == -1) + goto out_error; + } else + goto out_error; + addr += HPAGE_SIZE; + } while (addr < end); + spin_unlock(&mm->page_table_lock); + vma->vm_flags |= (VM_HUGETLB | VM_RESERVED); + if (flags & MAP_PRIVATE) + vma->vm_flags |= VM_DONTCOPY; + vma->vm_ops = &hugetlb_vm_ops; + return 0; +out_error: + if (addr > vma->vm_start) { + vma->vm_end = addr; + zap_hugetlb_resources(vma); + vma->vm_end = end; + } + spin_unlock(&mm->page_table_lock); +out_error1: + return -1; +} + +int +copy_hugetlb_page_range (struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) +{ + pte_t *src_pte, *dst_pte, entry; + struct page *ptepage; + unsigned long addr = vma->vm_start; + unsigned long end = vma->vm_end; + + while (addr < end) { + dst_pte = huge_pte_alloc(dst, addr); + if (!dst_pte) + goto nomem; + src_pte = huge_pte_offset(src, addr); + entry = *src_pte; + ptepage = pte_page(entry); + get_page(ptepage); + set_pte(dst_pte, entry); + dst->rss += (HPAGE_SIZE / PAGE_SIZE); + addr += HPAGE_SIZE; + } + return 0; + + nomem: + return -ENOMEM; +} + +int +follow_hugetlb_page (struct mm_struct *mm, struct vm_area_struct *vma, + struct page **pages, struct vm_area_struct **vmas, + unsigned long *st, int *length, int i) +{ + pte_t *ptep, pte; + unsigned long start = *st; + unsigned long pstart; + int len = *length; + struct page *page; + + do { + pstart = start & HPAGE_MASK; + ptep = huge_pte_offset(mm, start); + pte = *ptep; + +back1: + page = pte_page(pte); + if (pages) { + page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); + pages[i] = page; + } + if (vmas) + vmas[i] = vma; + i++; + len--; + start += PAGE_SIZE; + if (((start & HPAGE_MASK) == pstart) && len + && (start < vma->vm_end)) + goto back1; + } while (len && start < vma->vm_end); + *length = len; + *st = start; + return i; +} + +static void +zap_hugetlb_resources (struct vm_area_struct *mpnt) +{ + struct mm_struct *mm = mpnt->vm_mm; + unsigned long len, addr, end; + pte_t *ptep; + struct page *page; + + addr = mpnt->vm_start; + end = mpnt->vm_end; + len = end - addr; + do { + ptep = huge_pte_offset(mm, addr); + page = pte_page(*ptep); + pte_clear(ptep); + free_hugetlb_page(page); + addr += HPAGE_SIZE; + } while (addr < end); + mm->rss -= (len >> PAGE_SHIFT); + mpnt->vm_ops = NULL; + flush_tlb_range(mpnt, end - len, end); +} + +static void +unlink_vma (struct vm_area_struct *mpnt) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + + vma = mm->mmap; + if (vma == mpnt) { + mm->mmap = vma->vm_next; + } else { + while (vma->vm_next != mpnt) { + vma = vma->vm_next; + } + vma->vm_next = mpnt->vm_next; + } + rb_erase(&mpnt->vm_rb, &mm->mm_rb); + mm->mmap_cache = NULL; + mm->map_count--; +} + +int +free_hugepages (struct vm_area_struct *mpnt) +{ + unlink_vma(mpnt); + zap_hugetlb_resources(mpnt); + kmem_cache_free(vm_area_cachep, mpnt); + return 1; +} + +static struct inode * +set_new_inode (unsigned long len, int prot, int flag, int key) +{ + struct inode *inode; + int i; + + for (i = 0; i < MAX_ID; i++) { + if (htlbpagek[i].key == 0) + break; + } + if (i == MAX_ID) + return NULL; + inode = kmalloc(sizeof (struct inode), GFP_ATOMIC); + if (inode == NULL) + return NULL; + + inode_init_once(inode); + atomic_inc(&inode->i_writecount); + inode->i_mapping = &inode->i_data; + inode->i_mapping->host = inode; + inode->i_ino = (unsigned long) key; + + htlbpagek[i].key = key; + htlbpagek[i].in = inode; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_mode = prot; + inode->i_size = len; + return inode; +} + +static int +check_size_prot (struct inode *inode, unsigned long len, int prot, int flag) +{ + if (inode->i_uid != current->fsuid) + return -1; + if (inode->i_gid != current->fsgid) + return -1; + if (inode->i_size != len) + return -1; + return 0; +} + +int +alloc_shared_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + struct inode *inode; + struct address_space *mapping; + struct page *page; + int idx; + int retval = -ENOMEM; + int newalloc = 0; + +try_again: + spin_lock(&htlbpage_lock); + inode = find_key_inode(key); + if (inode == NULL) { + if (!capable(CAP_SYS_ADMIN)) { + if (!in_group_p(0)) { + retval = -EPERM; + goto out_err; + } + } + if (!(flag & IPC_CREAT)) { + retval = -ENOENT; + goto out_err; + } + inode = set_new_inode(len, prot, flag, key); + if (inode == NULL) + goto out_err; + newalloc = 1; + } else { + if (check_size_prot(inode, len, prot, flag) < 0) { + retval = -EINVAL; + goto out_err; + } + else if (atomic_read(&inode->i_writecount)) { + spin_unlock(&htlbpage_lock); + goto try_again; + } + } + spin_unlock(&htlbpage_lock); + mapping = inode->i_mapping; + + addr = do_mmap_pgoff(NULL, addr, len, (unsigned long) prot, + MAP_NORESERVE|MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0); + if (IS_ERR((void *) addr)) + goto freeinode; + + vma = find_vma(mm, addr); + if (!vma) { + retval = -EINVAL; + goto freeinode; + } + + spin_lock(&mm->page_table_lock); + do { + pte_t *pte = huge_pte_alloc(mm, addr); + if ((pte) && (pte_none(*pte))) { + idx = (addr - vma->vm_start) >> HPAGE_SHIFT; + page = find_get_page(mapping, idx); + if (page == NULL) { + page = alloc_hugetlb_page(); + if (page == NULL) + goto out; + add_to_page_cache(page, mapping, idx); + } + set_huge_pte(mm, vma, page, pte, + (vma->vm_flags & VM_WRITE)); + } else + goto out; + addr += HPAGE_SIZE; + } while (addr < vma->vm_end); + retval = 0; + vma->vm_flags |= (VM_HUGETLB | VM_RESERVED); + vma->vm_ops = &hugetlb_vm_ops; + spin_unlock(&mm->page_table_lock); + spin_lock(&htlbpage_lock); + atomic_set(&inode->i_writecount, 0); + spin_unlock(&htlbpage_lock); + return retval; +out: + if (addr > vma->vm_start) { + unsigned long raddr = vma->vm_end; + vma->vm_end = addr; + zap_hugetlb_resources(vma); + vma->vm_end = raddr; + } + spin_unlock(&mm->page_table_lock); + do_munmap(mm, vma->vm_start, len); + if (newalloc) + goto freeinode; + return retval; + +out_err: + spin_unlock(&htlbpage_lock); +freeinode: + if (newalloc) { + for (idx = 0; idx < MAX_ID; idx++) + if (htlbpagek[idx].key == inode->i_ino) { + htlbpagek[idx].key = 0; + htlbpagek[idx].in = NULL; + break; + } + kfree(inode); + } + return retval; +} + +static int +alloc_private_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag) +{ + if (!capable(CAP_SYS_ADMIN)) { + if (!in_group_p(0)) + return -EPERM; + } + addr = do_mmap_pgoff(NULL, addr, len, prot, + MAP_NORESERVE | MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0); + if (IS_ERR((void *) addr)) + return -ENOMEM; + if (make_hugetlb_pages_present(addr, (addr + len), flag) < 0) { + do_munmap(current->mm, addr, len); + return -ENOMEM; + } + return 0; +} + +int +alloc_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag) +{ + if (key > 0) + return alloc_shared_hugetlb_pages(key, addr, len, prot, flag); + else + return alloc_private_hugetlb_pages(key, addr, len, prot, flag); +} + +int +set_hugetlb_mem_size (int count) +{ + int j, lcount; + struct page *page, *map; + extern long htlbzone_pages; + extern struct list_head htlbpage_freelist; + + if (count < 0) + lcount = count; + else + lcount = count - htlbzone_pages; + if (lcount > 0) { /*Increase the mem size. */ + while (lcount--) { + page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + if (page == NULL) + break; + map = page; + for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) { + SetPageReserved(map); + map++; + } + spin_lock(&htlbpage_lock); + list_add(&page->list, &htlbpage_freelist); + htlbpagemem++; + htlbzone_pages++; + spin_unlock(&htlbpage_lock); + } + return (int) htlbzone_pages; + } + /*Shrink the memory size. */ + while (lcount++) { + page = alloc_hugetlb_page(); + if (page == NULL) + break; + spin_lock(&htlbpage_lock); + htlbzone_pages--; + spin_unlock(&htlbpage_lock); + map = page; + for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) { + map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | + 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved | + 1 << PG_private | 1<< PG_writeback); + map++; + } + set_page_count(page, 1); + __free_pages(page, HUGETLB_PAGE_ORDER); + } + return (int) htlbzone_pages; +} + +static struct vm_operations_struct hugetlb_vm_ops = { + .close = zap_hugetlb_resources +}; diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/mm/init.c Sat Sep 21 21:25:45 2002 @@ -78,7 +78,7 @@ vma->vm_mm = current->mm; vma->vm_start = IA64_RBS_BOT; vma->vm_end = vma->vm_start + PAGE_SIZE; - vma->vm_page_prot = PAGE_COPY; + vma->vm_page_prot = protection_map[VM_READ | VM_WRITE]; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP; vma->vm_ops = NULL; vma->vm_pgoff = 0; @@ -339,6 +339,14 @@ /* * Set up the page tables. */ + +#ifdef CONFIG_HUGETLB_PAGE +long htlbpagemem; +int htlbpage_max; +extern long htlbzone_pages; +extern struct list_head htlbpage_freelist; +#endif + void paging_init (void) { @@ -438,5 +446,30 @@ #ifdef CONFIG_IA32_SUPPORT ia32_gdt_init(); +#endif +#ifdef CONFIG_HUGETLB_PAGE + { + long i; + int j; + struct page *page, *map; + + if ((htlbzone_pages << (HPAGE_SHIFT - PAGE_SHIFT)) >= max_low_pfn) + htlbzone_pages = (max_low_pfn >> ((HPAGE_SHIFT - PAGE_SHIFT) + 1)); + INIT_LIST_HEAD(&htlbpage_freelist); + for (i = 0; i < htlbzone_pages; i++) { + page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER); + if (!page) + break; + map = page; + for (j = 0; j < (HPAGE_SIZE/PAGE_SIZE); j++) { + SetPageReserved(map); + map++; + } + list_add(&page->list, &htlbpage_freelist); + } + printk("Total Huge_TLB_Page memory pages allocated %ld \n", i); + htlbzone_pages = htlbpagemem = i; + htlbpage_max = (int)i; + } #endif } diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c --- a/arch/ia64/mm/tlb.c Sat Sep 21 21:25:46 2002 +++ b/arch/ia64/mm/tlb.c Sat Sep 21 21:25:46 2002 @@ -63,7 +63,7 @@ read_lock(&tasklist_lock); repeat: - for_each_task(tsk) { + for_each_process(tsk) { if (!tsk->mm) continue; tsk_context = tsk->mm->context; diff -Nru a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/pci/Makefile Sat Sep 21 21:25:48 2002 @@ -0,0 +1,3 @@ +obj-y := pci.o + +include $(TOPDIR)/Rules.make diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/pci/pci.c Sat Sep 21 21:25:45 2002 @@ -0,0 +1,278 @@ +/* + * pci.c - Low-Level PCI Access in IA-64 + * + * Derived from bios32.c of i386 tree. + * + * Copyright (C) 2002 Hewlett-Packard Co + * David Mosberger-Tang + * + * Note: Above list of copyright holders is incomplete... + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +#ifdef CONFIG_SMP +# include +#endif +#include + + +#undef DEBUG +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#ifdef CONFIG_IA64_MCA +extern void ia64_mca_check_errors( void ); +#endif + +struct pci_fixup pcibios_fixups[1]; + +/* + * Low-level SAL-based PCI configuration access functions. Note that SAL + * calls are already serialized (via sal_lock), so we don't need another + * synchronization mechanism here. Not using segment number (yet). + */ + +#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \ + ((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg)) + +static int +__pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +{ + int result = 0; + u64 data = 0; + + if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data); + + *value = (u32) data; + + return result; +} + +static int +__pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +{ + if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + return -EINVAL; + + return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value); +} + + +static int +pci_sal_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) +{ + return __pci_sal_read(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), + where, size, value); +} + +static int +pci_sal_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +{ + return __pci_sal_write(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), + where, size, value); +} + +struct pci_ops pci_sal_ops = { + .read = pci_sal_read, + .write = pci_sal_write +}; + +struct pci_ops *pci_root_ops = &pci_sal_ops; /* default to SAL */ + +static int __init +pci_acpi_init (void) +{ + if (!acpi_pci_irq_init()) + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + else + printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); + return 0; +} + +subsys_initcall(pci_acpi_init); + +/* Called by ACPI when it finds a new root bus. */ +struct pci_bus * +pcibios_scan_root (int bus) +{ + struct list_head *list; + struct pci_bus *pci_bus; + + list_for_each(list, &pci_root_buses) { + pci_bus = pci_bus_b(list); + if (pci_bus->number == bus) { + /* Already scanned */ + printk("PCI: Bus (%02x) already probed\n", bus); + return pci_bus; + } + } + + printk("PCI: Probing PCI hardware on bus (%02x)\n", bus); + return pci_scan_bus(bus, pci_root_ops, NULL); +} + +/* + * Called after each bus is probed, but before its children are examined. + */ +void __init +pcibios_fixup_bus (struct pci_bus *b) +{ + return; +} + +void __init +pcibios_update_resource (struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + unsigned long where, size; + u32 reg; + + where = PCI_BASE_ADDRESS_0 + (resource * 4); + size = res->end - res->start; + pci_read_config_dword(dev, where, ®); + reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); + pci_write_config_dword(dev, where, reg); + + /* ??? FIXME -- record old value for shutdown. */ +} + +void __init +pcibios_update_irq (struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + + /* ??? FIXME -- record old value for shutdown. */ +} + +void __init +pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges) +{ +} + +static inline int +pcibios_enable_resources (struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + if (!dev) + return -EINVAL; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + /* Only set up the desired resources. */ + if (!(mask & (1 << idx))) + continue; + + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +int +pcibios_enable_device (struct pci_dev *dev, int mask) +{ + int ret; + + ret = pcibios_enable_resources(dev, mask); + if (ret < 0) + return ret; + + printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name); + return acpi_pci_irq_enable(dev); +} + +void +pcibios_align_resource (void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +/* + * PCI BIOS setup, always defaults to SAL interface + */ +char * __init +pcibios_setup (char *str) +{ + return NULL; +} + +int +pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine) +{ + /* + * I/O space cannot be accessed via normal processor loads and stores on this + * platform. + */ + if (mmap_state == pci_mmap_io) + /* + * XXX we could relax this for I/O spaces for which ACPI indicates that + * the space is 1-to-1 mapped. But at the moment, we don't support + * multiple PCI address spaces and the legacy I/O space is not 1-to-1 + * mapped, so this is moot. + */ + return -EINVAL; + + /* + * Leave vm_pgoff as-is, the PCI space address is the physical address on this + * platform. + */ + vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); + + if (write_combine) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + else + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} diff -Nru a/arch/ia64/tools/print_offsets.awk b/arch/ia64/tools/print_offsets.awk --- a/arch/ia64/tools/print_offsets.awk Sat Sep 21 21:25:45 2002 +++ b/arch/ia64/tools/print_offsets.awk Sat Sep 21 21:25:45 2002 @@ -9,6 +9,7 @@ print " */" print "" print "#define CLONE_IDLETASK_BIT 12" + print "#define CLONE_SETTLS_BIT 19" } # look for .tab: diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c --- a/arch/ia64/tools/print_offsets.c Sat Sep 21 21:25:48 2002 +++ b/arch/ia64/tools/print_offsets.c Sat Sep 21 21:25:48 2002 @@ -202,6 +202,7 @@ } printf ("\n#define CLONE_IDLETASK_BIT %ld\n", ia64_fls (CLONE_IDLETASK)); + printf ("\n#define CLONE_SETTLS_BIT %ld\n", ia64_fls (CLONE_SETTLS)); printf ("\n#endif /* _ASM_IA64_OFFSETS_H */\n"); return 0; diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Sat Sep 21 21:25:45 2002 +++ b/arch/m68k/atari/stram.c Sat Sep 21 21:25:45 2002 @@ -974,8 +974,6 @@ /* ST-RAM device */ /* ------------------------------------------------------------------------ */ -static int stram_sizes[14] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static int refcnt = 0; static void do_stram_request(request_queue_t *q) @@ -1048,28 +1046,33 @@ .release = stram_release, }; +static struct gendisk stram_disk = { + .major = STRAM_MAJOR, + .first_minor = STRAM_MINOR, + .minor_shift = 0, + .fops = &stram_fops, + .major_name = "stram" +}; + int __init stram_device_init(void) { + if (!MACH_IS_ATARI) + /* no point in initializing this, I hope */ + return -ENXIO; + + if (!max_swap_size) + /* swapping not enabled */ + return -ENXIO; + + if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { + printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR); + return -ENXIO; + } - if (!MACH_IS_ATARI) - /* no point in initializing this, I hope */ - return( -ENXIO ); - - if (!max_swap_size) - /* swapping not enabled */ - return( -ENXIO ); - - if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { - printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR ); - return( -ENXIO ); - } - - blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request); - stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024; - blk_size[STRAM_MAJOR] = stram_sizes; - register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops, - (swap_end-swap_start)>>9); - return( 0 ); + blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request); + set_capacity(&stram_disk, (swap_end - swap_start)/512); + add_disk(&stram_disk); + return 0; } diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acorn/block/fd1772.c Sat Sep 21 21:25:45 2002 @@ -203,7 +203,8 @@ */ #define MAX_DISK_SIZE 720 -static int floppy_sizes[256]; +static struct gendisk disks[FD_MAX_UNIT]; +static char names[FD_MAX_UNIT][4]; /* current info on each unit */ static struct archy_floppy_struct { @@ -962,16 +963,16 @@ if (unit[SelectedDrive].disktype > disk_type) { /* try another disk type */ unit[SelectedDrive].disktype--; - floppy_sizes[SelectedDrive] - = unit[SelectedDrive].disktype->blocks >> 1; + set_capacity(&disks[SelectedDrive], + unit[SelectedDrive].disktype->blocks); } else Probing = 0; } else { /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ if (unit[SelectedDrive].autoprobe) { unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1; - floppy_sizes[SelectedDrive] - = unit[SelectedDrive].disktype->blocks >> 1; + set_capacity(&disks[SelectedDrive], + unit[SelectedDrive].disktype->blocks); Probing = 1; } } @@ -1243,7 +1244,7 @@ if (!floppy->disktype) { Probing = 1; floppy->disktype = disk_type + NUM_DISK_TYPES - 1; - floppy_sizes[drive] = floppy->disktype->blocks >> 1; + set_capacity(&disks[drive], floppy->disktype->blocks); floppy->autoprobe = 1; } } else { @@ -1255,7 +1256,7 @@ goto repeat; } floppy->disktype = &disk_type[type]; - floppy_sizes[drive] = disk_type[type].blocks >> 1; + set_capacity(&disks[drive], floppy->disktype->blocks); floppy->autoprobe = 0; } @@ -1474,14 +1475,9 @@ static int floppy_open(struct inode *inode, struct file *filp) { - int drive; + int drive = minor(inode->i_rdev) & 3; int old_dev; - if (!filp) { - DPRINT(("Weird, open called with filp=0\n")); - return -EIO; - } - drive = minor(inode->i_rdev) & 3; if ((minor(inode->i_rdev) >> 2) > NUM_DISK_TYPES) return -ENXIO; @@ -1543,6 +1539,13 @@ .revalidate = floppy_revalidate, }; +static struct gendisk *floppy_find(int minor) +{ + int drive = minor & 3; + if ((minor>> 2) > NUM_DISK_TYPES || minor >= FD_MAX_UNITS) + return NULL; + return &disks[drive]; +} int fd1772_init(void) { @@ -1580,19 +1583,20 @@ out of some special memory... */ DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */ #endif - + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request); for (i = 0; i < FD_MAX_UNITS; i++) { unit[i].track = -1; + disks[i].major = MAJOR_NR; + disks[i].first_minor = 0; + disks[i].fops = &floppy_fops; + sprintf(names[i], "fd%d", i); + disks[i].major_name = names[i]; + set_capacity(&disks[i], MAX_DISK_SIZE * 2); } + blk_set_probe(MAJOR_NR, floppy_find); - for (i = 0; i < 256; i++) - if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES) - floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1; - else - floppy_sizes[i] = MAX_DISK_SIZE; - - blk_size[MAJOR_NR] = floppy_sizes; - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request); + for (i = 0; i < FD_MAX_UNITS; i++) + add_disk(disks + i); config_types(); diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acorn/block/mfmhd.c Sat Sep 21 21:25:45 2002 @@ -1014,13 +1014,17 @@ /* * Tell the user about the drive if we decided it exists. */ -static void mfm_geometry (int drive) +static void mfm_geometry(int drive) { - if (mfm_info[drive].cylinders) - printk ("mfm%c: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", 'a' + drive, - mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096, - mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors, - mfm_info[drive].lowcurrent, mfm_info[drive].precomp); + struct mfm_info *p = mfm_info + drive; + struct gendisk *disk = mfm_gendisk + drive; + if (p->cylinders) + printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", + disk->major_name, + p->cylinders * p->heads * p->sectors / 4096, + p->cylinders, p->heads, p->sectors, + p->lowcurrent, p->precomp); + set_capacity(disk, p->cylinders * p->heads * p->sectors / 2); } #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT @@ -1241,7 +1245,6 @@ if (raw_cmd.dev == drive) mfm_specify (); mfm_geometry (drive); - set_capacity(&mfm_gendisk[drive], mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2); } } @@ -1267,12 +1270,8 @@ outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */ for (i = 0; i < mfm_drives; i++) { - add_gendisk(mfm_gendisk + i); - mfm_geometry (i); - register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6, - &mfm_fops, - mfm_info[i].cylinders * mfm_info[i].heads * - mfm_info[i].sectors / 2); + mfm_geometry(i); + add_disk(mfm_gendisk + i); } } diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c --- a/drivers/acpi/ac.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/ac.c Sat Sep 21 21:25:45 2002 @@ -33,13 +33,6 @@ #include "acpi_drivers.h" -#define _COMPONENT ACPI_AC_COMPONENT -ACPI_MODULE_NAME ("acpi_ac") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); -MODULE_LICENSE("GPL"); - #define ACPI_AC_COMPONENT 0x00020000 #define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_HID "ACPI0003" @@ -50,6 +43,13 @@ #define ACPI_AC_STATUS_OFFLINE 0x00 #define ACPI_AC_STATUS_ONLINE 0x01 #define ACPI_AC_STATUS_UNKNOWN 0xFF + +#define _COMPONENT ACPI_AC_COMPONENT +ACPI_MODULE_NAME ("acpi_ac") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); +MODULE_LICENSE("GPL"); int acpi_ac_add (struct acpi_device *device); int acpi_ac_remove (struct acpi_device *device, int type); diff -Nru a/drivers/acpi/battery.c b/drivers/acpi/battery.c --- a/drivers/acpi/battery.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/battery.c Sat Sep 21 21:25:45 2002 @@ -33,14 +33,6 @@ #include "acpi_drivers.h" -#define _COMPONENT ACPI_BATTERY_COMPONENT -ACPI_MODULE_NAME ("acpi_battery") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); -MODULE_LICENSE("GPL"); - - #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" @@ -58,6 +50,14 @@ #define ACPI_BATTERY_NOTIFY_INFO 0x81 #define ACPI_BATTERY_UNITS_WATTS "mW" #define ACPI_BATTERY_UNITS_AMPS "mA" + + +#define _COMPONENT ACPI_BATTERY_COMPONENT +ACPI_MODULE_NAME ("acpi_battery") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); +MODULE_LICENSE("GPL"); static int acpi_battery_add (struct acpi_device *device); static int acpi_battery_remove (struct acpi_device *device, int type); diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c --- a/drivers/acpi/button.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/button.c Sat Sep 21 21:25:45 2002 @@ -33,13 +33,6 @@ #include "acpi_drivers.h" -#define _COMPONENT ACPI_BUTTON_COMPONENT -ACPI_MODULE_NAME ("acpi_button") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); -MODULE_LICENSE("GPL"); - #define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" @@ -65,6 +58,13 @@ #define ACPI_BUTTON_HID_LID "PNP0C0D" #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" #define ACPI_BUTTON_TYPE_LID 0x05 + +#define _COMPONENT ACPI_BUTTON_COMPONENT +ACPI_MODULE_NAME ("acpi_button") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME); +MODULE_LICENSE("GPL"); int acpi_button_add (struct acpi_device *device); diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c --- a/drivers/acpi/fan.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/fan.c Sat Sep 21 21:25:45 2002 @@ -33,13 +33,6 @@ #include "acpi_drivers.h" -#define _COMPONENT ACPI_FAN_COMPONENT -ACPI_MODULE_NAME ("acpi_fan") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); -MODULE_LICENSE("GPL"); - #define ACPI_FAN_COMPONENT 0x00200000 #define ACPI_FAN_CLASS "fan" #define ACPI_FAN_HID "PNP0C0B" @@ -47,6 +40,13 @@ #define ACPI_FAN_DEVICE_NAME "Fan" #define ACPI_FAN_FILE_STATE "state" #define ACPI_FAN_NOTIFY_STATUS 0x80 + +#define _COMPONENT ACPI_FAN_COMPONENT +ACPI_MODULE_NAME ("acpi_fan") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME); +MODULE_LICENSE("GPL"); int acpi_fan_add (struct acpi_device *device); int acpi_fan_remove (struct acpi_device *device, int type); diff -Nru a/drivers/acpi/numa.c b/drivers/acpi/numa.c --- a/drivers/acpi/numa.c Sat Sep 21 21:25:48 2002 +++ b/drivers/acpi/numa.c Sat Sep 21 21:25:48 2002 @@ -29,6 +29,7 @@ #include #include #include +#include "acpi_bus.h" extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler); diff -Nru a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c --- a/drivers/acpi/pci_bind.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/pci_bind.c Sat Sep 21 21:25:45 2002 @@ -185,7 +185,7 @@ */ data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c Sat Sep 21 21:25:46 2002 +++ b/drivers/acpi/processor.c Sat Sep 21 21:25:46 2002 @@ -43,14 +43,6 @@ #include "acpi_bus.h" #include "acpi_drivers.h" - -#define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME ("acpi_processor") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); -MODULE_LICENSE("GPL"); - #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" @@ -83,6 +75,14 @@ #define ACPI_PROCESSOR_LIMIT_USER 0 #define ACPI_PROCESSOR_LIMIT_THERMAL 1 + +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME ("acpi_processor") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); +MODULE_LICENSE("GPL"); + static int acpi_processor_add (struct acpi_device *device); static int acpi_processor_remove (struct acpi_device *device, int type); diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c Sat Sep 21 21:25:45 2002 +++ b/drivers/acpi/thermal.c Sat Sep 21 21:25:45 2002 @@ -42,18 +42,6 @@ #include "acpi_bus.h" #include "acpi_drivers.h" - -#define _COMPONENT ACPI_THERMAL_COMPONENT -ACPI_MODULE_NAME ("acpi_thermal") - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -static int tzp = 0; -MODULE_PARM(tzp, "i"); -MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); - #define ACPI_THERMAL_COMPONENT 0x04000000 #define ACPI_THERMAL_CLASS "thermal_zone" #define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" @@ -75,6 +63,18 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define KELVIN_TO_CELSIUS(t) ((t-2732+5)/10) + +#define _COMPONENT ACPI_THERMAL_COMPONENT +ACPI_MODULE_NAME ("acpi_thermal") + +MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +static int tzp = 0; +MODULE_PARM(tzp, "i"); +MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); + static int acpi_thermal_add (struct acpi_device *device); static int acpi_thermal_remove (struct acpi_device *device, int type); diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Sat Sep 21 21:25:48 2002 +++ b/drivers/block/DAC960.c Sat Sep 21 21:25:48 2002 @@ -1973,7 +1973,6 @@ disk->major_name = names + 9 * n; disk->minor_shift = DAC960_MaxPartitionsBits; disk->fops = &DAC960_BlockDeviceOperations; - add_gendisk(disk); } /* Indicate the Block Device Registration completed successfully, @@ -2622,10 +2621,8 @@ if (Controller == NULL) continue; DAC960_InitializeController(Controller); for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) { - long size = disk_size(Controller, disk); - register_disk(&Controller->disks[disk], - DAC960_KernelDevice(Controller->ControllerNumber, disk, 0), - DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size); + set_capacity(&Controller->disks[disk], disk_size(Controller, disk)); + add_disk(&Controller->disks[disk]); } } DAC960_CreateProcEntries(); @@ -5268,9 +5265,8 @@ Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; size = disk_size(Controller, LogicalDriveNumber); /* BROKEN, same as modular ide-floppy/ide-disk; same fix - ->probe() */ - register_disk(&Controller->disks[LogicalDriveNumber], - DAC960_KernelDevice(Controller->ControllerNumber, LogicalDriveNumber, 0), - DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size); + set_capacity(&Controller->disks[LogicalDriveNumber], size); + add_disk(&Controller->disks[LogicalDriveNumber]); } if (!get_capacity(&Controller->disks[LogicalDriveNumber])) return -ENXIO; diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/acsi.c Sat Sep 21 21:25:45 2002 @@ -1698,11 +1698,8 @@ disk->major_name = acsi_names + 4*i; disk->minor_shift = (acsi_info[i].type==HARDDISK)?4:0; disk->fops = &acsi_fops; - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, - disk->fops, - acsi_info[i].size); + set_capacity(disk, acsi_info[i].size); + add_disk(disk); } } diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Sat Sep 21 21:25:48 2002 +++ b/drivers/block/cciss.c Sat Sep 21 21:25:48 2002 @@ -769,11 +769,8 @@ continue; (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size; disk->major_name = hba[ctlr]->names + 12 * i; - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, - drv->nr_blocks); + set_capacity(disk, drv->nr_blocks); + add_disk(disk); } hba[ctlr]->usage_count--; return 0; @@ -1241,12 +1238,8 @@ /* setup partitions per disk */ disk = &hba[ctlr]->gendisk[logvol]; disk->major_name = hba[ctlr]->names + 12 * logvol; - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, - disk->fops, - hba[ctlr]->drv[logvol].nr_blocks); + set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks); + add_disk(disk); kfree(ld_buff); kfree(size_buff); @@ -2449,11 +2442,8 @@ continue; (BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size; disk->major_name = hba[i]->names + 12 * j; - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, - drv->nr_blocks); + set_capacity(disk, drv->nr_blocks); + add_disk(disk); } cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */ diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/cpqarray.c Sat Sep 21 21:25:45 2002 @@ -449,11 +449,8 @@ continue; disk->major_name = ida_names + (i*NWD+j)*10; (BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->blk_size; - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major,disk->first_minor), - 1<minor_shift, disk->fops, - drv->nr_blks); + set_capacity(disk, drv->nr_blks); + add_disk(disk); } } /* done ! */ @@ -1475,11 +1472,8 @@ continue; (BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size; disk->major_name = ida_names + (ctlr*NWD+i)*10; - add_gendisk(disk); - register_disk(disk, - mk_kdev(disk->major,disk->first_minor), - 1<minor_shift, disk->fops, - drv->nr_blks); + set_capacity(disk, drv->nr_blks); + add_disk(disk); } hba[ctlr]->usage_count--; diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/floppy.c Sat Sep 21 21:25:45 2002 @@ -416,6 +416,8 @@ static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE]; +static struct gendisk disks[N_DRIVE]; +static char names[N_DRIVE][4]; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; /* @@ -3775,6 +3777,7 @@ } UDRS->fd_device = minor(inode->i_rdev); + set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]); if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (buffer_drive == drive) buffer_track = -1; @@ -3952,6 +3955,7 @@ poll_drive(0, FD_RAW_NEED_DISK); process_fd_request(); } + set_capacity(&disks[drive], floppy_sizes[minor(dev)]); return 0; } @@ -4219,6 +4223,16 @@ bus_id: "03?0", }; +static struct gendisk *floppy_find(int minor) +{ + int drive = (minor&3) | ((minor&0x80) >> 5); + if (drive >= N_DRIVE || + !(allowed_drive_mask & (1 << drive)) || + fdc_state[FDC(drive)].version == FDC_NONE) + return NULL; + return &disks[drive]; +} + int __init floppy_init(void) { int i,unit,drive; @@ -4231,13 +4245,22 @@ return -EBUSY; } + for (i=0; i> 1; else floppy_sizes[i] = MAX_DISK_SIZE; - blk_size[MAJOR_NR] = floppy_sizes; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock); reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); config_types(); @@ -4262,6 +4285,7 @@ unregister_blkdev(MAJOR_NR,"fd"); del_timer(&fd_timeout); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + blk_set_probe(MAJOR_NR, NULL); return -ENODEV; } #if N_FDC > 1 @@ -4273,6 +4297,7 @@ del_timer(&fd_timeout); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); unregister_blkdev(MAJOR_NR,"fd"); + blk_set_probe(MAJOR_NR, NULL); return -EBUSY; } @@ -4336,6 +4361,7 @@ floppy_release_irq_and_dma(); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); unregister_blkdev(MAJOR_NR,"fd"); + blk_set_probe(MAJOR_NR, NULL); } for (drive = 0; drive < N_DRIVE; drive++) { @@ -4345,9 +4371,7 @@ continue; if (fdc_state[FDC(drive)].version == FDC_NONE) continue; - for (i = 0; iminor_shift) { @@ -59,28 +74,20 @@ gp->part = p; write_lock(&gendisk_lock); - - /* - * In 2.5 this will go away. Fix the drivers who rely on - * old behaviour. - */ - - for (sgp = gendisk_head; sgp; sgp = sgp->next) - { - if (sgp == gp) - { - printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n", - sgp->major); - goto out; - } - } + list_add(&gp->list, &gendisks[gp->major].list); gp->next = gendisk_head; gendisk_head = gp; -out: write_unlock(&gendisk_lock); } -EXPORT_SYMBOL(add_gendisk); +void add_disk(struct gendisk *disk) +{ + add_gendisk(disk); + register_disk(disk, mk_kdev(disk->major, disk->first_minor), + 1<minor_shift, disk->fops, get_capacity(disk)); +} + +EXPORT_SYMBOL(add_disk); EXPORT_SYMBOL(del_gendisk); void unlink_gendisk(struct gendisk *disk) @@ -92,6 +99,7 @@ break; if (*p) *p = (*p)->next; + list_del_init(&disk->list); write_unlock(&gendisk_lock); } @@ -105,20 +113,25 @@ struct gendisk * get_gendisk(kdev_t dev) { - struct gendisk *gp = NULL; + struct gendisk *disk; + struct list_head *p; int major = major(dev); int minor = minor(dev); read_lock(&gendisk_lock); - for (gp = gendisk_head; gp; gp = gp->next) { - if (gp->major != major) - continue; - if (gp->first_minor > minor) + if (gendisks[major].get) { + disk = gendisks[major].get(minor); + read_unlock(&gendisk_lock); + return disk; + } + list_for_each(p, &gendisks[major].list) { + disk = list_entry(p, struct gendisk, list); + if (disk->first_minor > minor) continue; - if (gp->first_minor + (1<minor_shift) <= minor) + if (disk->first_minor + (1<minor_shift) <= minor) continue; read_unlock(&gendisk_lock); - return gp; + return disk; } read_unlock(&gendisk_lock); return NULL; @@ -161,6 +174,10 @@ if (sgp == gendisk_head) seq_puts(part, "major minor #blocks name\n\n"); + /* Don't show non-partitionable devices or empty devices */ + if (!sgp->minor_shift || !get_capacity(sgp)) + return 0; + /* show the full disk and all non-0 size partitions of it */ seq_printf(part, "%4d %4d %10ld %s\n", sgp->major, sgp->first_minor, @@ -194,7 +211,10 @@ int __init device_init(void) { + int i; rwlock_init(&gendisk_lock); + for (i = 0; i < MAX_BLKDEV; i++) + INIT_LIST_HEAD(&gendisks[i].list); blk_dev_init(); #ifdef CONFIG_FC4_SOC /* This has to be done before scsi_dev_init */ diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/loop.c Sat Sep 21 21:25:45 2002 @@ -83,7 +83,8 @@ static int max_loop = 8; static struct loop_device *loop_dev; -static int *loop_sizes; +static struct gendisk *disks; +static char *names; static devfs_handle_t devfs_handle; /* For the directory */ /* @@ -165,8 +166,8 @@ static void figure_loop_size(struct loop_device *lo) { - loop_sizes[lo->lo_number] = compute_loop_size(lo, - lo->lo_backing_file->f_dentry); + set_capacity(disks + lo->lo_number, compute_loop_size(lo, + lo->lo_backing_file->f_dentry)); } @@ -792,8 +793,8 @@ lo->lo_flags = 0; memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_name, 0, LO_NAME_SIZE); - loop_sizes[lo->lo_number] = 0; invalidate_bdev(bdev, 0); + set_capacity(disks + lo->lo_number, 0); filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; lo->lo_state = Lo_unbound; fput(filp); @@ -906,20 +907,6 @@ case LOOP_GET_STATUS: err = loop_get_status(lo, (struct loop_info *) arg); break; - case BLKGETSIZE: - if (lo->lo_state != Lo_bound) { - err = -ENXIO; - break; - } - err = put_user((unsigned long) loop_sizes[lo->lo_number] << 1, (unsigned long *) arg); - break; - case BLKGETSIZE64: - if (lo->lo_state != Lo_bound) { - err = -ENXIO; - break; - } - err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)arg); - break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } @@ -932,18 +919,11 @@ struct loop_device *lo; int dev, type; - if (!inode) - return -EINVAL; - if (major(inode->i_rdev) != MAJOR_NR) { - printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR); - return -ENODEV; - } dev = minor(inode->i_rdev); if (dev >= max_loop) return -ENODEV; lo = &loop_dev[dev]; - MOD_INC_USE_COUNT; down(&lo->lo_ctl_mutex); type = lo->lo_encrypt_type; @@ -959,13 +939,6 @@ struct loop_device *lo; int dev, type; - if (!inode) - return 0; - if (major(inode->i_rdev) != MAJOR_NR) { - printk(KERN_WARNING "lo_release: pseudo-major != %d\n", - MAJOR_NR); - return 0; - } dev = minor(inode->i_rdev); if (dev >= max_loop) return 0; @@ -978,7 +951,6 @@ xfer_funcs[type]->unlock(lo); up(&lo->lo_ctl_mutex); - MOD_DEC_USE_COUNT; return 0; } @@ -1051,46 +1023,56 @@ if (!loop_dev) return -ENOMEM; - loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL); - if (!loop_sizes) + disks = kmalloc(max_loop * sizeof(struct gendisk), GFP_KERNEL); + if (!disks) goto out_mem; + names = kmalloc(max_loop * 8, GFP_KERNEL); + blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), loop_make_request); blk_queue_bounce_limit(BLK_DEFAULT_QUEUE(MAJOR_NR), BLK_BOUNCE_HIGH); for (i = 0; i < max_loop; i++) { struct loop_device *lo = &loop_dev[i]; + struct gendisk *disk = disks + i; memset(lo, 0, sizeof(struct loop_device)); init_MUTEX(&lo->lo_ctl_mutex); init_MUTEX_LOCKED(&lo->lo_sem); init_MUTEX_LOCKED(&lo->lo_bh_mutex); lo->lo_number = i; spin_lock_init(&lo->lo_lock); + memset(disk, 0, sizeof(struct gendisk)); + disk->major = LOOP_MAJOR; + disk->first_minor = i; + disk->fops = &lo_fops; + sprintf(names + 8*i, "loop%d", i); + disk->major_name = names + 8 * i; + add_disk(disk); } - memset(loop_sizes, 0, max_loop * sizeof(int)); - blk_size[MAJOR_NR] = loop_sizes; - for (i = 0; i < max_loop; i++) - register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &lo_fops, 0); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; out_mem: + kfree(names); + kfree(disks); kfree(loop_dev); - kfree(loop_sizes); printk(KERN_ERR "loop: ran out of memory\n"); return -ENOMEM; } void loop_exit(void) { + int i; + for (i = 0; i < max_loop; i++) + del_gendisk(disks + i); devfs_unregister(devfs_handle); if (unregister_blkdev(MAJOR_NR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); + kfree(names); + kfree(disks); kfree(loop_dev); - kfree(loop_sizes); } module_init(loop_init); diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/nbd.c Sat Sep 21 21:25:45 2002 @@ -59,8 +59,8 @@ static int nbd_blksizes[MAX_NBD]; static int nbd_blksize_bits[MAX_NBD]; -static int nbd_sizes[MAX_NBD]; static u64 nbd_bytesizes[MAX_NBD]; +static char nbd_names[MAX_NBD][7]; static struct nbd_device nbd_dev[MAX_NBD]; static devfs_handle_t devfs_handle; @@ -78,11 +78,7 @@ static int nbd_open(struct inode *inode, struct file *file) { - int dev; - - if (!inode) - return -EINVAL; - dev = minor(inode->i_rdev); + int dev = minor(inode->i_rdev); if (dev >= MAX_NBD) return -ENODEV; @@ -387,21 +383,15 @@ static int nbd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct nbd_device *lo; - int dev, error, temp; + int dev = minor(inode->i_rdev); + struct nbd_device *lo = &nbd_dev[dev]; + int error, temp; struct request sreq ; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!inode) - return -EINVAL; - dev = minor(inode->i_rdev); - if (dev >= MAX_NBD) - return -ENODEV; - - lo = &nbd_dev[dev]; switch (cmd) { case NBD_DISCONNECT: printk(KERN_INFO "NBD_DISCONNECT\n"); @@ -455,15 +445,15 @@ temp >>= 1; } nbd_bytesizes[dev] &= ~(nbd_blksizes[dev]-1); - nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS; + set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9); return 0; case NBD_SET_SIZE: nbd_bytesizes[dev] = arg & ~(nbd_blksizes[dev]-1); - nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS; + set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9); return 0; case NBD_SET_SIZE_BLOCKS: nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev]; - nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS; + set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9); return 0; case NBD_DO_IT: if (!lo->file) @@ -479,25 +469,14 @@ dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out); return 0; #endif - case BLKGETSIZE: - return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg); - case BLKGETSIZE64: - return put_user((u64)nbd_bytesizes[dev], (u64 *) arg); } return -EINVAL; } static int nbd_release(struct inode *inode, struct file *file) { - struct nbd_device *lo; - int dev; - - if (!inode) - return -ENODEV; - dev = minor(inode->i_rdev); - if (dev >= MAX_NBD) - return -ENODEV; - lo = &nbd_dev[dev]; + int dev = minor(inode->i_rdev); + struct nbd_device *lo = &nbd_dev[dev]; if (lo->refcnt <= 0) printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt); lo->refcnt--; @@ -535,9 +514,9 @@ #ifdef MODULE printk("nbd: registered device at major %d\n", MAJOR_NR); #endif - blk_size[MAJOR_NR] = nbd_sizes; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request, &nbd_lock); for (i = 0; i < MAX_NBD; i++) { + struct gendisk *disk = &nbd_dev[i].disk; nbd_dev[i].refcnt = 0; nbd_dev[i].file = NULL; nbd_dev[i].magic = LO_MAGIC; @@ -548,9 +527,14 @@ nbd_blksizes[i] = 1024; nbd_blksize_bits[i] = 10; nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */ - nbd_sizes[i] = nbd_bytesizes[i] >> BLOCK_SIZE_BITS; - register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &nbd_fops, - nbd_bytesizes[i]>>9); + disk->major = MAJOR_NR; + disk->first_minor = i; + disk->minor_shift = 0; + disk->fops = &nbd_fops; + sprintf(nbd_names[i], "nbd%d", i); + disk->major_name = nbd_names[i]; + set_capacity(disk, 0x3ffffe); + add_disk(disk); } devfs_handle = devfs_mk_dir (NULL, "nbd", NULL); devfs_register_series (devfs_handle, "%u", MAX_NBD, @@ -563,6 +547,9 @@ static void __exit nbd_cleanup(void) { + int i; + for (i = 0; i < MAX_NBD; i++) + del_gendisk(&nbd_dev[i].disk); devfs_unregister (devfs_handle); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c --- a/drivers/block/paride/pcd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/paride/pcd.c Sat Sep 21 21:25:45 2002 @@ -176,8 +176,6 @@ /* set up defines for blk.h, why don't all drivers do it this way ? */ #define MAJOR_NR major -#define DEVICE_NR(device) (minor(device)) -#define DEVICE_OFF(device) #include @@ -224,6 +222,7 @@ int present; /* does this unit exist ? */ char *name; /* pcd0, pcd1, etc */ struct cdrom_device_info info; /* uniform cdrom interface */ + struct gendisk disk; }; struct pcd_unit pcd[PCD_UNITS]; @@ -282,6 +281,7 @@ pcd_drive_count = 0; for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { + struct gendisk *disk = &cd->disk; cd->pi = &cd->pia; cd->present = 0; cd->last_sense = 0; @@ -298,6 +298,11 @@ cd->info.speed = 0; cd->info.capacity = 1; cd->info.mask = 0; + disk->major = major; + disk->first_minor = unit; + disk->minor_shift = 0; + disk->major_name = cd->name; + disk->fops = &pcd_bdops; } } @@ -925,8 +930,9 @@ for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { if (cd->present) { + struct gendisk *disk = &cd->disk; register_cdrom(&cd->info); - devfs_plain_cdrom(&cd->info, &pcd_bdops); + add_disk(disk); } } @@ -942,6 +948,7 @@ for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { if (cd->present) { + del_gendisk(&cd->disk); pi_release(cd->pi); unregister_cdrom(&cd->info); } diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c --- a/drivers/block/paride/pd.c Sat Sep 21 21:25:48 2002 +++ b/drivers/block/paride/pd.c Sat Sep 21 21:25:48 2002 @@ -687,10 +687,8 @@ PD.gd.fops = &pd_fops; PD.gd.major = major; PD.gd.first_minor = unit << PD_BITS; - add_gendisk(&PD.gd); - register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit< #include #include @@ -168,30 +159,32 @@ #include "setup.h" -static STT pf_stt[7] = {{"drive0",7,drive0}, - {"drive1",7,drive1}, - {"drive2",7,drive2}, - {"drive3",7,drive3}, - {"disable",1,&disable}, - {"cluster",1,&cluster}, - {"nice",1,&nice}}; - -void pf_setup( char *str, int *ints) +static STT pf_stt[7] = { + {"drive0", 7, drive0}, + {"drive1", 7, drive1}, + {"drive2", 7, drive2}, + {"drive3", 7, drive3}, + {"disable", 1, &disable}, + {"cluster", 1, &cluster}, + {"nice", 1, &nice} +}; -{ generic_setup(pf_stt,7,str); +void pf_setup(char *str, int *ints) +{ + generic_setup(pf_stt, 7, str); } #endif -MODULE_PARM(verbose,"i"); -MODULE_PARM(major,"i"); -MODULE_PARM(name,"s"); -MODULE_PARM(cluster,"i"); -MODULE_PARM(nice,"i"); -MODULE_PARM(drive0,"1-7i"); -MODULE_PARM(drive1,"1-7i"); -MODULE_PARM(drive2,"1-7i"); -MODULE_PARM(drive3,"1-7i"); +MODULE_PARM(verbose, "i"); +MODULE_PARM(major, "i"); +MODULE_PARM(name, "s"); +MODULE_PARM(cluster, "i"); +MODULE_PARM(nice, "i"); +MODULE_PARM(drive0, "1-7i"); +MODULE_PARM(drive1, "1-7i"); +MODULE_PARM(drive2, "1-7i"); +MODULE_PARM(drive3, "1-7i"); #include "paride.h" @@ -199,7 +192,6 @@ #define MAJOR_NR major #define DEVICE_NR(device) minor(device) -#define DEVICE_OFF(device) #include #include @@ -208,15 +200,15 @@ /* constants for faking geometry numbers */ -#define PF_FD_MAX 8192 /* use FD geometry under this size */ +#define PF_FD_MAX 8192 /* use FD geometry under this size */ #define PF_FD_HDS 2 #define PF_FD_SPT 18 #define PF_HD_HDS 64 #define PF_HD_SPT 32 #define PF_MAX_RETRIES 5 -#define PF_TMO 800 /* interrupt timeout in jiffies */ -#define PF_SPIN_DEL 50 /* spin delay in micro-seconds */ +#define PF_TMO 800 /* interrupt timeout in jiffies */ +#define PF_SPIN_DEL 50 /* spin delay in micro-seconds */ #define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL) @@ -239,27 +231,22 @@ #define ATAPI_WRITE_10 0x2a #ifdef MODULE -void cleanup_module( void ); +void cleanup_module(void); #endif static int pf_open(struct inode *inode, struct file *file); static void do_pf_request(request_queue_t * q); -static int pf_ioctl(struct inode *inode,struct file *file, - unsigned int cmd, unsigned long arg); +static int pf_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); -static int pf_release (struct inode *inode, struct file *file); +static int pf_release(struct inode *inode, struct file *file); static int pf_detect(void); static void do_pf_read(void); static void do_pf_read_start(void); static void do_pf_write(void); static void do_pf_write_start(void); -static void do_pf_read_drq( void ); -static void do_pf_write_done( void ); - -static int pf_identify (int unit); -static void pf_lock(int unit, int func); -static void pf_eject(int unit); -static int pf_check_media(kdev_t dev); +static void do_pf_read_drq(void); +static void do_pf_write_done(void); #define PF_NM 0 #define PF_RO 1 @@ -268,714 +255,715 @@ #define PF_NAMELEN 8 struct pf_unit { - struct pi_adapter pia; /* interface to paride layer */ + struct pi_adapter pia; /* interface to paride layer */ struct pi_adapter *pi; - int removable; /* removable media device ? */ - int media_status; /* media present ? WP ? */ - int drive; /* drive */ + int removable; /* removable media device ? */ + int media_status; /* media present ? WP ? */ + int drive; /* drive */ int lun; - int access; /* count of active opens ... */ - int capacity; /* Size of this volume in sectors */ - int present; /* device present ? */ - char name[PF_NAMELEN]; /* pf0, pf1, ... */ - }; - -struct pf_unit pf[PF_UNITS]; + int access; /* count of active opens ... */ + int present; /* device present ? */ + char name[PF_NAMELEN]; /* pf0, pf1, ... */ + struct gendisk disk; +}; -/* 'unit' must be defined in all functions - either as a local or a param */ +struct pf_unit units[PF_UNITS]; -#define PF pf[unit] -#define PI PF.pi +static int pf_identify(struct pf_unit *pf); +static void pf_lock(struct pf_unit *pf, int func); +static void pf_eject(struct pf_unit *pf); +static int pf_check_media(kdev_t dev); -static char pf_scratch[512]; /* scratch block buffer */ +static char pf_scratch[512]; /* scratch block buffer */ /* the variables below are used mainly in the I/O request engine, which processes only one request at a time. */ -static int pf_retries = 0; /* i/o error retry count */ -static int pf_busy = 0; /* request being processed ? */ -static int pf_block; /* address of next requested block */ -static int pf_count; /* number of blocks still to do */ -static int pf_run; /* sectors in current cluster */ -static int pf_cmd; /* current command READ/WRITE */ -static int pf_unit; /* unit of current request */ -static int pf_mask; /* stopper for pseudo-int */ -static char * pf_buf; /* buffer for request in progress */ +static int pf_retries = 0; /* i/o error retry count */ +static int pf_busy = 0; /* request being processed ? */ +static struct request *pf_req; /* current request */ +static int pf_block; /* address of next requested block */ +static int pf_count; /* number of blocks still to do */ +static int pf_run; /* sectors in current cluster */ +static int pf_cmd; /* current command READ/WRITE */ +static struct pf_unit *pf_current;/* unit of current request */ +static int pf_mask; /* stopper for pseudo-int */ +static char *pf_buf; /* buffer for request in progress */ /* kernel glue structures */ static struct block_device_operations pf_fops = { - owner: THIS_MODULE, - open: pf_open, - release: pf_release, - ioctl: pf_ioctl, - check_media_change: pf_check_media, + .owner = THIS_MODULE, + .open = pf_open, + .release = pf_release, + .ioctl = pf_ioctl, + .check_media_change = pf_check_media, }; -void pf_init_units( void ) - -{ int unit, j; +void pf_init_units(void) +{ + struct pf_unit *pf; + int unit; - pf_drive_count = 0; - for (unit=0;unitdisk; + pf->pi = &pf->pia; + pf->media_status = PF_NM; + pf->drive = (*drives[unit])[D_SLV]; + pf->lun = (*drives[unit])[D_LUN]; + snprintf(pf->name, PF_NAMELEN, "%s%d", name, unit); + disk->major = MAJOR_NR; + disk->first_minor = unit; + disk->major_name = pf->name; + disk->minor_shift = 0; + disk->fops = &pf_fops; + if (!(*drives[unit])[D_PRT]) + pf_drive_count++; + } +} -{ int unit = DEVICE_NR(inode->i_rdev); +static int pf_open(struct inode *inode, struct file *file) +{ + int unit = DEVICE_NR(inode->i_rdev); + struct pf_unit *pf = units + unit; - if ((unit >= PF_UNITS) || (!PF.present)) return -ENODEV; + if ((unit >= PF_UNITS) || (!pf->present)) + return -ENODEV; - pf_identify(unit); + pf_identify(pf); - if (PF.media_status == PF_NM) + if (pf->media_status == PF_NM) return -ENODEV; - if ((PF.media_status == PF_RO) && (file ->f_mode & 2)) + if ((pf->media_status == PF_RO) && (file->f_mode & 2)) return -EROFS; - PF.access++; - if (PF.removable) pf_lock(unit,1); + pf->access++; + if (pf->removable) + pf_lock(pf, 1); - return 0; + return 0; } -static int pf_ioctl(struct inode *inode,struct file *file, - unsigned int cmd, unsigned long arg) - -{ int err, unit; +static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int unit = DEVICE_NR(inode->i_rdev); struct hd_geometry *geo = (struct hd_geometry *) arg; + struct hd_geometry g; + struct pf_unit *pf = units + unit; + sector_t capacity; + + if (unit >= PF_UNITS) + return -EINVAL; + if (!pf->present) + return -ENODEV; - if ((!inode) || kdev_none(inode->i_rdev)) return -EINVAL; - unit = DEVICE_NR(inode->i_rdev); - if (unit >= PF_UNITS) return -EINVAL; - if (!PF.present) return -ENODEV; - - switch (cmd) { - case CDROMEJECT: - if (PF.access == 1) { - pf_eject(unit); + if (cmd == CDROMEJECT) { + if (pf->access == 1) { + pf_eject(pf); return 0; } - case HDIO_GETGEO: - if (!geo) return -EINVAL; - err = verify_area(VERIFY_WRITE,geo,sizeof(*geo)); - if (err) return err; - if (PF.capacity < PF_FD_MAX) { - put_user(PF.capacity/(PF_FD_HDS*PF_FD_SPT), - (short *) &geo->cylinders); - put_user(PF_FD_HDS, (char *) &geo->heads); - put_user(PF_FD_SPT, (char *) &geo->sectors); - } else { - put_user(PF.capacity/(PF_HD_HDS*PF_HD_SPT), - (short *) &geo->cylinders); - put_user(PF_HD_HDS, (char *) &geo->heads); - put_user(PF_HD_SPT, (char *) &geo->sectors); - } - put_user(0,(long *)&geo->start); - return 0; - case BLKGETSIZE: - return put_user(PF.capacity,(long *) arg); - case BLKGETSIZE64: - return put_user((u64)PF.capacity << 9,(u64 *)arg); - default: - return -EINVAL; - } + return -EBUSY; + } + if (cmd != HDIO_GETGEO) + return -EINVAL; + capacity = get_capacity(&pf->disk); + if (capacity < PF_FD_MAX) { + g.cylinders = capacity / (PF_FD_HDS * PF_FD_SPT); + g.heads = PF_FD_HDS; + g.sectors = PF_FD_SPT; + } else { + g.cylinders = capacity / (PF_HD_HDS * PF_HD_SPT); + g.heads = PF_HD_HDS; + g.sectors = PF_HD_SPT; + } + if (copy_to_user(geo, &g, sizeof(g))) + return -EFAULT; + return 0; } +static int pf_release(struct inode *inode, struct file *file) +{ + int unit = DEVICE_NR(inode->i_rdev); + struct pf_unit *pf = units + unit; -static int pf_release (struct inode *inode, struct file *file) - -{ kdev_t devp; - int unit; - - devp = inode->i_rdev; - unit = DEVICE_NR(devp); - - if ((unit >= PF_UNITS) || (PF.access <= 0)) - return -EINVAL; + if ((unit >= PF_UNITS) || (pf->access <= 0)) + return -EINVAL; - PF.access--; + pf->access--; - if (!PF.access && PF.removable) - pf_lock(unit,0); + if (!pf->access && pf->removable) + pf_lock(pf, 0); return 0; } -static int pf_check_media( kdev_t dev) - -{ return 1; +static int pf_check_media(kdev_t dev) +{ + return 1; } -#define WR(c,r,v) pi_write_regr(PI,c,r,v) -#define RR(c,r) (pi_read_regr(PI,c,r)) - -#define LUN (0x20*PF.lun) -#define DRIVE (0xa0+0x10*PF.drive) +static inline int status_reg(struct pf_unit *pf) +{ + return pi_read_regr(pf->pi, 1, 6); +} -static int pf_wait( int unit, int go, int stop, char * fun, char * msg ) +static inline int read_reg(struct pf_unit *pf, int reg) +{ + return pi_read_regr(pf->pi, 0, reg); +} -{ int j, r, e, s, p; +static inline void write_reg(struct pf_unit *pf, int reg, int val) +{ + pi_write_regr(pf->pi, 0, reg, val); +} - j = 0; - while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++=PF_SPIN)) { - s = RR(0,7); - e = RR(0,1); - p = RR(0,2); - if (j >= PF_SPIN) e |= 0x100; - if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" - " loop=%d phase=%d\n", - PF.name,fun,msg,r,s,e,j,p); - return (e<<8)+s; - } - return 0; + j = 0; + while ((((r = status_reg(pf)) & go) || (stop && (!(r & stop)))) + && (j++ < PF_SPIN)) + udelay(PF_SPIN_DEL); + + if ((r & (STAT_ERR & stop)) || (j >= PF_SPIN)) { + s = read_reg(pf, 7); + e = read_reg(pf, 1); + p = read_reg(pf, 2); + if (j >= PF_SPIN) + e |= 0x100; + if (fun) + printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" + " loop=%d phase=%d\n", + pf->name, fun, msg, r, s, e, j, p); + return (e << 8) + s; + } + return 0; } -static int pf_command( int unit, char * cmd, int dlen, char * fun ) - -{ pi_connect(PI); +static int pf_command(struct pf_unit *pf, char *cmd, int dlen, char *fun) +{ + pi_connect(pf->pi); - WR(0,6,DRIVE); + write_reg(pf, 6, 0xa0+0x10*pf->drive); - if (pf_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) { - pi_disconnect(PI); - return -1; - } + if (pf_wait(pf, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { + pi_disconnect(pf->pi); + return -1; + } - WR(0,4,dlen % 256); - WR(0,5,dlen / 256); - WR(0,7,0xa0); /* ATAPI packet command */ + write_reg(pf, 4, dlen % 256); + write_reg(pf, 5, dlen / 256); + write_reg(pf, 7, 0xa0); /* ATAPI packet command */ - if (pf_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) { - pi_disconnect(PI); - return -1; - } + if (pf_wait(pf, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { + pi_disconnect(pf->pi); + return -1; + } - if (RR(0,2) != 1) { - printk("%s: %s: command phase error\n",PF.name,fun); - pi_disconnect(PI); - return -1; - } + if (read_reg(pf, 2) != 1) { + printk("%s: %s: command phase error\n", pf->name, fun); + pi_disconnect(pf->pi); + return -1; + } - pi_write_block(PI,cmd,12); + pi_write_block(pf->pi, cmd, 12); - return 0; + return 0; } -static int pf_completion( int unit, char * buf, char * fun ) - -{ int r, s, n; +static int pf_completion(struct pf_unit *pf, char *buf, char *fun) +{ + int r, s, n; - r = pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, - fun,"completion"); + r = pf_wait(pf, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, + fun, "completion"); - if ((RR(0,2)&2) && (RR(0,7)&STAT_DRQ)) { - n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc); - pi_read_block(PI,buf,n); - } + if ((read_reg(pf, 2) & 2) && (read_reg(pf, 7) & STAT_DRQ)) { + n = (((read_reg(pf, 4) + 256 * read_reg(pf, 5)) + + 3) & 0xfffc); + pi_read_block(pf->pi, buf, n); + } - s = pf_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done"); + s = pf_wait(pf, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); - pi_disconnect(PI); + pi_disconnect(pf->pi); - return (r?r:s); + return (r ? r : s); } -static void pf_req_sense( int unit, int quiet ) - -{ char rs_cmd[12] = { ATAPI_REQ_SENSE,LUN,0,0,16,0,0,0,0,0,0,0 }; - char buf[16]; - int r; - - r = pf_command(unit,rs_cmd,16,"Request sense"); - mdelay(1); - if (!r) pf_completion(unit,buf,"Request sense"); - - if ((!r)&&(!quiet)) - printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - PF.name,buf[2]&0xf,buf[12],buf[13]); +static void pf_req_sense(struct pf_unit *pf, int quiet) +{ + char rs_cmd[12] = + { ATAPI_REQ_SENSE, pf->lun << 5, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; + char buf[16]; + int r; + + r = pf_command(pf, rs_cmd, 16, "Request sense"); + mdelay(1); + if (!r) + pf_completion(pf, buf, "Request sense"); + + if ((!r) && (!quiet)) + printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", + pf->name, buf[2] & 0xf, buf[12], buf[13]); } -static int pf_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) +static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fun) +{ + int r; -{ int r; + r = pf_command(pf, cmd, dlen, fun); + mdelay(1); + if (!r) + r = pf_completion(pf, buf, fun); + if (r) + pf_req_sense(pf, !fun); - r = pf_command(unit,cmd,dlen,fun); - mdelay(1); - if (!r) r = pf_completion(unit,buf,fun); - if (r) pf_req_sense(unit,!fun); - - return r; + return r; } #define DBMSG(msg) ((verbose>1)?(msg):NULL) -static void pf_lock(int unit, int func) - -{ char lo_cmd[12] = { ATAPI_LOCK,LUN,0,0,func,0,0,0,0,0,0,0 }; +static void pf_lock(struct pf_unit *pf, int func) +{ + char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 }; - pf_atapi(unit,lo_cmd,0,pf_scratch,func?"unlock":"lock"); + pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock"); } +static void pf_eject(struct pf_unit *pf) +{ + char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; -static void pf_eject( int unit ) - -{ char ej_cmd[12] = { ATAPI_DOOR,LUN,0,0,2,0,0,0,0,0,0,0 }; - - pf_lock(unit,0); - pf_atapi(unit,ej_cmd,0,pf_scratch,"eject"); + pf_lock(pf, 0); + pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject"); } -#define PF_RESET_TMO 30 /* in tenths of a second */ - -static void pf_sleep( int cs ) +#define PF_RESET_TMO 30 /* in tenths of a second */ -{ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(cs); +static void pf_sleep(int cs) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(cs); } - -static int pf_reset( int unit ) - /* the ATAPI standard actually specifies the contents of all 7 registers after a reset, but the specification is ambiguous concerning the last two bytes, and different drives interpret the standard differently. -*/ + */ + +static int pf_reset(struct pf_unit *pf) +{ + int i, k, flg; + int expect[5] = { 1, 1, 1, 0x14, 0xeb }; -{ int i, k, flg; - int expect[5] = {1,1,1,0x14,0xeb}; + pi_connect(pf->pi); + write_reg(pf, 6, 0xa0+0x10*pf->drive); + write_reg(pf, 7, 8); - pi_connect(PI); - WR(0,6,DRIVE); - WR(0,7,8); - - pf_sleep(20*HZ/1000); - - k = 0; - while ((k++ < PF_RESET_TMO) && (RR(1,6)&STAT_BUSY)) - pf_sleep(HZ/10); + pf_sleep(20 * HZ / 1000); + + k = 0; + while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY)) + pf_sleep(HZ / 10); flg = 1; - for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); + for (i = 0; i < 5; i++) + flg &= (read_reg(pf, i + 1) == expect[i]); if (verbose) { - printk("%s: Reset (%d) signature = ",PF.name,k); - for (i=0;i<5;i++) printk("%3x",RR(0,i+1)); - if (!flg) printk(" (incorrect)"); + printk("%s: Reset (%d) signature = ", pf->name, k); + for (i = 0; i < 5; i++) + printk("%3x", read_reg(pf, i + 1)); + if (!flg) + printk(" (incorrect)"); printk("\n"); } - - pi_disconnect(PI); - return flg-1; -} -static void pf_mode_sense( int unit ) + pi_disconnect(pf->pi); + return flg - 1; +} -{ char ms_cmd[12] = { ATAPI_MODE_SENSE,LUN,0,0,0,0,0,0,8,0,0,0}; - char buf[8]; +static void pf_mode_sense(struct pf_unit *pf) +{ + char ms_cmd[12] = + { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 }; + char buf[8]; - pf_atapi(unit,ms_cmd,8,buf,DBMSG("mode sense")); - PF.media_status = PF_RW; - if (buf[3] & 0x80) PF.media_status = PF_RO; + pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense")); + pf->media_status = PF_RW; + if (buf[3] & 0x80) + pf->media_status = PF_RO; } -static void xs( char *buf, char *targ, int offs, int len ) - -{ int j,k,l; +static void xs(char *buf, char *targ, int offs, int len) +{ + int j, k, l; - j=0; l=0; - for (k=0;klun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char buf[8]; + int bs; - if (pf_atapi(unit,rc_cmd,8,buf,DBMSG("get capacity"))) { - PF.media_status = PF_NM; + if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) { + pf->media_status = PF_NM; return; } - PF.capacity = xl(buf,0) + 1; - bs = xl(buf,4); + set_capacity(&pf->disk, xl(buf, 0) + 1); + bs = xl(buf, 4); if (bs != 512) { - PF.capacity = 0; - if (verbose) printk("%s: Drive %d, LUN %d," - " unsupported block size %d\n", - PF.name,PF.drive,PF.lun,bs); - } + set_capacity(&pf->disk, 0); + if (verbose) + printk("%s: Drive %d, LUN %d," + " unsupported block size %d\n", + pf->name, pf->drive, pf->lun, bs); + } } -static int pf_identify( int unit ) - -{ int dt, s; - char *ms[2] = {"master","slave"}; - char mf[10], id[18]; - char id_cmd[12] = { ATAPI_IDENTIFY,LUN,0,0,36,0,0,0,0,0,0,0}; - char buf[36]; +static int pf_identify(struct pf_unit *pf) +{ + int dt, s; + char *ms[2] = { "master", "slave" }; + char mf[10], id[18]; + char id_cmd[12] = + { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; + char buf[36]; - s = pf_atapi(unit,id_cmd,36,buf,"identify"); - if (s) return -1; + s = pf_atapi(pf, id_cmd, 36, buf, "identify"); + if (s) + return -1; dt = buf[0] & 0x1f; if ((dt != 0) && (dt != 7)) { - if (verbose) - printk("%s: Drive %d, LUN %d, unsupported type %d\n", - PF.name,PF.drive,PF.lun,dt); - return -1; - } - - xs(buf,mf,8,8); - xs(buf,id,16,16); - - PF.removable = (buf[1] & 0x80); - - pf_mode_sense(unit); - pf_mode_sense(unit); - pf_mode_sense(unit); - - pf_get_capacity(unit); - - printk("%s: %s %s, %s LUN %d, type %d", - PF.name,mf,id,ms[PF.drive],PF.lun,dt); - if (PF.removable) printk(", removable"); - if (PF.media_status == PF_NM) - printk(", no media\n"); - else { if (PF.media_status == PF_RO) printk(", RO"); - printk(", %d blocks\n",PF.capacity); - } + if (verbose) + printk("%s: Drive %d, LUN %d, unsupported type %d\n", + pf->name, pf->drive, pf->lun, dt); + return -1; + } + + xs(buf, mf, 8, 8); + xs(buf, id, 16, 16); + pf->removable = (buf[1] & 0x80); + + pf_mode_sense(pf); + pf_mode_sense(pf); + pf_mode_sense(pf); + + pf_get_capacity(pf); + + printk("%s: %s %s, %s LUN %d, type %d", + pf->name, mf, id, ms[pf->drive], pf->lun, dt); + if (pf->removable) + printk(", removable"); + if (pf->media_status == PF_NM) + printk(", no media\n"); + else { + if (pf->media_status == PF_RO) + printk(", RO"); + printk(", %ld blocks\n", get_capacity(&pf->disk)); + } return 0; } -static int pf_probe( int unit ) - /* returns 0, with id set if drive is detected -1, if drive detection failed */ - -{ if (PF.drive == -1) { - for (PF.drive=0;PF.drive<=1;PF.drive++) - if (!pf_reset(unit)) { - if (PF.lun != -1) return pf_identify(unit); - else for (PF.lun=0;PF.lun<8;PF.lun++) - if (!pf_identify(unit)) return 0; - } +static int pf_probe(struct pf_unit *pf) +{ + if (pf->drive == -1) { + for (pf->drive = 0; pf->drive <= 1; pf->drive++) + if (!pf_reset(pf)) { + if (pf->lun != -1) + return pf_identify(pf); + else + for (pf->lun = 0; pf->lun < 8; pf->lun++) + if (!pf_identify(pf)) + return 0; + } } else { - if (pf_reset(unit)) return -1; - if (PF.lun != -1) return pf_identify(unit); - for (PF.lun=0;PF.lun<8;PF.lun++) - if (!pf_identify(unit)) return 0; + if (pf_reset(pf)) + return -1; + if (pf->lun != -1) + return pf_identify(pf); + for (pf->lun = 0; pf->lun < 8; pf->lun++) + if (!pf_identify(pf)) + return 0; } - return -1; + return -1; } -static int pf_detect( void ) - -{ int k, unit; +static int pf_detect(void) +{ + struct pf_unit *pf = units; + int k, unit; printk("%s: %s version %s, major %d, cluster %d, nice %d\n", - name,name,PF_VERSION,major,cluster,nice); + name, name, PF_VERSION, major, cluster, nice); k = 0; if (pf_drive_count == 0) { - unit = 0; - if (pi_init(PI,1,-1,-1,-1,-1,-1,pf_scratch, - PI_PF,verbose,PF.name)) { - if (!pf_probe(unit)) { - PF.present = 1; - k++; - } else pi_release(PI); - } - - } else for (unit=0;unitpi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF, + verbose, pf->name)) { + if (!pf_probe(pf)) { + pf->present = 1; + k++; + } else + pi_release(pf->pi); + } - if (k) return 0; + } else + for (unit = 0; unit < PF_UNITS; unit++, pf++) { + int *conf = *drives[unit]; + if (!conf[D_PRT]) + continue; + if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD], + conf[D_UNI], conf[D_PRO], conf[D_DLY], + pf_scratch, PI_PF, verbose, pf->name)) { + if (!pf_probe(pf)) { + pf->present = 1; + k++; + } else + pi_release(pf->pi); + } + } + if (k) + return 0; - printk("%s: No ATAPI disk detected\n",name); + printk("%s: No ATAPI disk detected\n", name); return -1; } /* The i/o request engine */ -static int pf_start( int unit, int cmd, int b, int c ) - -{ int i; - char io_cmd[12] = {cmd,LUN,0,0,0,0,0,0,0,0,0,0}; +static int pf_start(struct pf_unit *pf, int cmd, int b, int c) +{ + int i; + char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - for(i=0;i<4;i++) { - io_cmd[5-i] = b & 0xff; - b = b >> 8; + for (i = 0; i < 4; i++) { + io_cmd[5 - i] = b & 0xff; + b = b >> 8; } - + io_cmd[8] = c & 0xff; io_cmd[7] = (c >> 8) & 0xff; - i = pf_command(unit,io_cmd,c*512,"start i/o"); + i = pf_command(pf, io_cmd, c * 512, "start i/o"); - mdelay(1); + mdelay(1); - return i; + return i; } -static int pf_ready( void ) - -{ int unit = pf_unit; - - return (((RR(1,6)&(STAT_BUSY|pf_mask)) == pf_mask)); +static int pf_ready(void) +{ + return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask)); } -static void do_pf_request (request_queue_t * q) +static void do_pf_request(request_queue_t * q) { int unit; - if (pf_busy) return; -repeat: - if (blk_queue_empty(QUEUE)) + if (pf_busy) + return; + repeat: + if (elv_queue_empty(QUEUE)) return; - pf_unit = unit = DEVICE_NR(CURRENT->rq_dev); - pf_block = CURRENT->sector; - pf_run = CURRENT->nr_sectors; - pf_count = CURRENT->current_nr_sectors; - - if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) { - end_request(CURRENT, 0); - goto repeat; - } - - pf_cmd = rq_data_dir(CURRENT); - pf_buf = CURRENT->buffer; - pf_retries = 0; - - pf_busy = 1; - if (pf_cmd == READ) pi_do_claimed(PI,do_pf_read); - else if (pf_cmd == WRITE) pi_do_claimed(PI,do_pf_write); - else { pf_busy = 0; - end_request(CURRENT, 0); - goto repeat; - } -} - -static void pf_next_buf( int unit ) + pf_req = elv_next_request(QUEUE); + unit = DEVICE_NR(pf_req->rq_dev); + pf_current = units + unit; + pf_block = pf_req->sector; + pf_run = pf_req->nr_sectors; + pf_count = pf_req->current_nr_sectors; + + if ((unit >= PF_UNITS) || + (pf_block + pf_count > get_capacity(&pf_current->disk))) { + end_request(pf_req, 0); + goto repeat; + } -{ long saved_flags; + pf_cmd = rq_data_dir(pf_req); + pf_buf = pf_req->buffer; + pf_retries = 0; - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 1); - if (!pf_run) { spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; + pf_busy = 1; + if (pf_cmd == READ) + pi_do_claimed(pf_current->pi, do_pf_read); + else if (pf_cmd == WRITE) + pi_do_claimed(pf_current->pi, do_pf_write); + else { + pf_busy = 0; + end_request(pf_req, 0); + goto repeat; } - -/* paranoia */ +} - if (blk_queue_empty(QUEUE) || - (rq_data_dir(CURRENT) != pf_cmd) || - (DEVICE_NR(CURRENT->rq_dev) != pf_unit) || - (CURRENT->sector != pf_block)) - printk("%s: OUCH: request list changed unexpectedly\n", - PF.name); +static int pf_next_buf(void) +{ + long saved_flags; - pf_count = CURRENT->current_nr_sectors; - pf_buf = CURRENT->buffer; - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); + pf_count--; + pf_run--; + pf_buf += 512; + pf_block++; + if (!pf_run) + return 0; + if (!pf_count) + return 1; + spin_lock_irqsave(&pf_spin_lock, saved_flags); + end_request(pf_req, 1); + pf_count = pf_req->current_nr_sectors; + pf_buf = pf_req->buffer; + spin_unlock_irqrestore(&pf_spin_lock, saved_flags); + return 1; } -static void do_pf_read( void ) +static inline void next_request(int success) +{ + long saved_flags; + spin_lock_irqsave(&pf_spin_lock, saved_flags); + end_request(pf_req, success); + pf_busy = 0; + do_pf_request(NULL); + spin_unlock_irqrestore(&pf_spin_lock, saved_flags); +} /* detach from the calling context - in case the spinlock is held */ - -{ ps_set_intr(do_pf_read_start,0,0,nice); +static void do_pf_read(void) +{ + ps_set_intr(do_pf_read_start, 0, 0, nice); } -static void do_pf_read_start( void ) - -{ int unit = pf_unit; - long saved_flags; - +static void do_pf_read_start(void) +{ pf_busy = 1; - if (pf_start(unit,ATAPI_READ_10,pf_block,pf_run)) { - pi_disconnect(PI); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(PI,do_pf_read_start); + if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) { + pi_disconnect(pf_current->pi); + if (pf_retries < PF_MAX_RETRIES) { + pf_retries++; + pi_do_claimed(pf_current->pi, do_pf_read_start); return; - } - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 0); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; - } + } + next_request(0); + return; + } pf_mask = STAT_DRQ; - ps_set_intr(do_pf_read_drq,pf_ready,PF_TMO,nice); + ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice); } -static void do_pf_read_drq( void ) - -{ int unit = pf_unit; - long saved_flags; - +static void do_pf_read_drq(void) +{ while (1) { - if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR, - "read block","completion") & STAT_ERR) { - pi_disconnect(PI); - if (pf_retries < PF_MAX_RETRIES) { - pf_req_sense(unit,0); - pf_retries++; - pi_do_claimed(PI,do_pf_read_start); - return; - } - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 0); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; - } - pi_read_block(PI,pf_buf,512); - pf_count--; pf_run--; - pf_buf += 512; - pf_block++; - if (!pf_run) break; - if (!pf_count) pf_next_buf(unit); - } - pi_disconnect(PI); - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 1); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); + if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR, + "read block", "completion") & STAT_ERR) { + pi_disconnect(pf_current->pi); + if (pf_retries < PF_MAX_RETRIES) { + pf_req_sense(pf_current, 0); + pf_retries++; + pi_do_claimed(pf_current->pi, do_pf_read_start); + return; + } + next_request(0); + return; + } + pi_read_block(pf_current->pi, pf_buf, 512); + if (pf_next_buf()) + break; + } + pi_disconnect(pf_current->pi); + next_request(1); } -static void do_pf_write( void ) - -{ ps_set_intr(do_pf_write_start,0,0,nice); +static void do_pf_write(void) +{ + ps_set_intr(do_pf_write_start, 0, 0, nice); } -static void do_pf_write_start( void ) - -{ int unit = pf_unit; - long saved_flags; - +static void do_pf_write_start(void) +{ pf_busy = 1; - if (pf_start(unit,ATAPI_WRITE_10,pf_block,pf_run)) { - pi_disconnect(PI); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(PI,do_pf_write_start); + if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) { + pi_disconnect(pf_current->pi); + if (pf_retries < PF_MAX_RETRIES) { + pf_retries++; + pi_do_claimed(pf_current->pi, do_pf_write_start); return; - } - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 0); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; - } + } + next_request(0); + return; + } while (1) { - if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR, - "write block","data wait") & STAT_ERR) { - pi_disconnect(PI); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(PI,do_pf_write_start); - return; - } - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 0); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; - } - pi_write_block(PI,pf_buf,512); - pf_count--; pf_run--; - pf_buf += 512; - pf_block++; - if (!pf_run) break; - if (!pf_count) pf_next_buf(unit); + if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR, + "write block", "data wait") & STAT_ERR) { + pi_disconnect(pf_current->pi); + if (pf_retries < PF_MAX_RETRIES) { + pf_retries++; + pi_do_claimed(pf_current->pi, do_pf_write_start); + return; + } + next_request(0); + return; + } + pi_write_block(pf_current->pi, pf_buf, 512); + if (pf_next_buf()) + break; } pf_mask = 0; - ps_set_intr(do_pf_write_done,pf_ready,PF_TMO,nice); + ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice); } -static void do_pf_write_done( void ) - -{ int unit = pf_unit; - long saved_flags; - - if (pf_wait(unit,STAT_BUSY,0,"write block","done") & STAT_ERR) { - pi_disconnect(PI); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(PI,do_pf_write_start); - return; - } - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 0); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); - return; - } - pi_disconnect(PI); - spin_lock_irqsave(&pf_spin_lock,saved_flags); - end_request(CURRENT, 1); - pf_busy = 0; - do_pf_request(NULL); - spin_unlock_irqrestore(&pf_spin_lock,saved_flags); +static void do_pf_write_done(void) +{ + if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) { + pi_disconnect(pf_current->pi); + if (pf_retries < PF_MAX_RETRIES) { + pf_retries++; + pi_do_claimed(pf_current->pi, do_pf_write_start); + return; + } + next_request(0); + return; + } + pi_disconnect(pf_current->pi); + next_request(1); } -static int __init pf_init(void) /* preliminary initialisation */ -{ - int i; - request_queue_t * q; +static int __init pf_init(void) +{ /* preliminary initialisation */ + struct pf_unit *pf; + int unit; + request_queue_t *q; if (disable) return -1; @@ -986,7 +974,7 @@ return -1; pf_busy = 0; - if (register_blkdev(MAJOR_NR,name,&pf_fops)) { + if (register_blkdev(MAJOR_NR, name, &pf_fops)) { printk("pf_init: unable to get major number %d\n", major); return -1; } @@ -995,21 +983,28 @@ blk_queue_max_phys_segments(q, cluster); blk_queue_max_hw_segments(q, cluster); - for (i=0;idisk; + if (!pf->present) + continue; + add_disk(disk); + } return 0; } static void __exit pf_exit(void) { + struct pf_unit *pf; int unit; - unregister_blkdev(MAJOR_NR,name); - for (unit=0;unitpresent) + continue; + del_gendisk(&pf->disk); + pi_release(pf->pi); + } } - + MODULE_LICENSE("GPL"); module_init(pf_init) module_exit(pf_exit) diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Sat Sep 21 21:25:43 2002 +++ b/drivers/block/ps2esdi.c Sat Sep 21 21:25:43 2002 @@ -435,11 +435,9 @@ for (i = 0; i < ps2esdi_drives; i++) { struct gendisk *disk = ps2esdi_gendisk + i; - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major,disk->first_minor), - 1<minor_shift, disk->fops, - ps2esdi_info[i].head * ps2esdi_info[i].sect * + set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * ps2esdi_info[i].cyl); + add_disk(disk); } return 0; diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Sat Sep 21 21:25:46 2002 +++ b/drivers/block/rd.c Sat Sep 21 21:25:46 2002 @@ -77,7 +77,8 @@ */ static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */ -static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ +static struct gendisk rd_disks[NUM_RAMDISKS]; +static char rd_names[NUM_RAMDISKS][5]; static devfs_handle_t devfs_handle; static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ @@ -286,37 +287,38 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int error = -EINVAL; - unsigned int minor; - - if (!inode || kdev_none(inode->i_rdev)) - goto out; + int error; - minor = minor(inode->i_rdev); + if (cmd != BLKFLSBUF) + return -EINVAL; - switch (cmd) { - case BLKFLSBUF: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - /* special: we want to release the ramdisk memory, - it's not like with the other blockdevices where - this ioctl only flushes away the buffer cache. */ - error = -EBUSY; - down(&inode->i_bdev->bd_sem); - if (inode->i_bdev->bd_openers <= 2) { - truncate_inode_pages(inode->i_mapping, 0); - error = 0; - } - up(&inode->i_bdev->bd_sem); - break; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + /* special: we want to release the ramdisk memory, + it's not like with the other blockdevices where + this ioctl only flushes away the buffer cache. */ + error = -EBUSY; + down(&inode->i_bdev->bd_sem); + if (inode->i_bdev->bd_openers <= 2) { + truncate_inode_pages(inode->i_mapping, 0); + error = 0; } -out: + up(&inode->i_bdev->bd_sem); return error; } #ifdef CONFIG_BLK_DEV_INITRD +static struct block_device_operations rd_bd_op; +static struct gendisk initrd_disk = { + .major = MAJOR_NR, + .first_minor = INITRD_MINOR, + .minor_shift = 0, + .fops = &rd_bd_op, + .major_name = "initrd" +}; + static ssize_t initrd_read(struct file *file, char *buf, size_t count, loff_t *ppos) { @@ -339,6 +341,7 @@ spin_lock(&initrd_users_lock); if (!--initrd_users) { spin_unlock(&initrd_users_lock); + del_gendisk(&initrd_disk); free_initrd_mem(initrd_start, initrd_end); initrd_start = 0; } else { @@ -410,6 +413,7 @@ invalidate_bdev(bdev, 1); blkdev_put(bdev, BDEV_FILE); } + del_gendisk(rd_disks + i); } devfs_unregister (devfs_handle); @@ -437,9 +441,16 @@ blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request); for (i = 0; i < NUM_RAMDISKS; i++) { + struct gendisk *disk = rd_disks + i; /* rd_size is given in kB */ rd_length[i] = rd_size << 10; - rd_kbsize[i] = rd_size; + disk->major = MAJOR_NR; + disk->first_minor = 0; + disk->minor_shift = 0; + disk->fops = &rd_bd_op; + sprintf(rd_names[i], "rd%d", i); + disk->major_name = rd_names[i]; + set_capacity(disk, rd_size * 2); } devfs_handle = devfs_mk_dir (NULL, "rd", NULL); devfs_register_series (devfs_handle, "%u", NUM_RAMDISKS, @@ -448,17 +459,14 @@ &rd_bd_op, NULL); for (i = 0; i < NUM_RAMDISKS; i++) - register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, - rd_size<<1); + add_disk(rd_disks + i); #ifdef CONFIG_BLK_DEV_INITRD /* We ought to separate initrd operations here */ - register_disk(NULL, mk_kdev(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1); + add_disk(&initrd_disk); devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR, INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL); #endif - - blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */ /* rd_size is given in kB */ printk("RAMDISK driver initialized: " diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Sat Sep 21 21:25:45 2002 +++ b/drivers/block/swim3.c Sat Sep 21 21:25:45 2002 @@ -38,8 +38,8 @@ #include #include -static int floppy_blocksizes[2] = {512,512}; -static int floppy_sizes[2] = {1440,1440}; +static struct gendisk disks[2]; +static char names[2][4]; #define MAX_FLOPPIES 2 @@ -1015,6 +1015,7 @@ int swim3_init(void) { struct device_node *swim; + int i; floppy_devfs_handle = devfs_mk_dir(NULL, "floppy", NULL); @@ -1039,9 +1040,17 @@ MAJOR_NR); return -EBUSY; } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,&swim3_lock); - blksize_size[MAJOR_NR] = floppy_blocksizes; - blk_size[MAJOR_NR] = floppy_sizes; + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &swim3_lock); + for (i = 0; i < floppy_count; i++) { + struct gendisk *disk = disks + i; + disk->major = MAJOR_NR; + disk->first_minor = i; + disk->fops = &floppy_fops; + sprintf(names[i], "fd%d", i); + disk->major_name = names[i]; + set_capacity(disk, 2880); + add_disk(disk); + } } return 0; diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c --- a/drivers/block/swim_iop.c Sat Sep 21 21:25:43 2002 +++ b/drivers/block/swim_iop.c Sat Sep 21 21:25:43 2002 @@ -83,7 +83,8 @@ static struct floppy_state floppy_states[MAX_FLOPPIES]; -static int floppy_sizes[2] = {2880,2880}; +static struct gendisk disks[2]; +static char names[2][4]; static spinlock_t swim_iop_lock = SPIN_LOCK_UNLOCKED; @@ -152,8 +153,6 @@ } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &swim_iop_lock); - blk_size[MAJOR_NR] = floppy_sizes; - printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n", DRIVER_VERSION); @@ -193,6 +192,16 @@ printk("SWIM-IOP: detected %d installed drives.\n", floppy_count); do_floppy = NULL; + for (i = 0; i < floppy_count; i++) { + struct gendisk *disk = disks + i; + disk->major = MAJOR_NR; + disk->first_minor = i; + disk->fops = &floppy_fops; + sprintf(names[i], "fd%d", i); + disk->major_name = names[i]; + set_capacity(disk, 2880 * 2); + add_disk(disk); + } return 0; } diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Sat Sep 21 21:25:48 2002 +++ b/drivers/block/umem.c Sat Sep 21 21:25:48 2002 @@ -1199,11 +1199,8 @@ disk->major_name = mm_names + i*6; disk->minor_shift = MM_SHIFT; disk->fops = &mm_fops; - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, - disk->fops, - cards[i].mm_size << 1); + set_capacity(disk, cards[i].mm_size << 1); + add_disk(disk); } init_battery_timer(); diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Sat Sep 21 21:25:48 2002 +++ b/drivers/block/xd.c Sat Sep 21 21:25:48 2002 @@ -222,12 +222,9 @@ for (i = 0; i < xd_drives; i++) { struct gendisk *disk = xd_gendisk + i; - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major,disk->first_minor), - 1<minor_shift, - disk->fops, - xd_info[i].heads * xd_info[i].cylinders * + set_capacity(disk, xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors); + add_disk(disk); } return 0; diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Sat Sep 21 21:25:48 2002 +++ b/drivers/cdrom/aztcd.c Sat Sep 21 21:25:48 2002 @@ -319,27 +319,9 @@ ########################################################################### */ /* CDROM Drive Low Level I/O Functions */ -void op_ok(void); -void pa_ok(void); -void sten_low(void); -void dten_low(void); -void statusAzt(void); static void aztStatTimer(void); /* CDROM Drive Command Functions */ -static int aztSendCmd(int cmd); -static int sendAztCmd(int cmd, struct azt_Play_msf *params); -static int aztSeek(struct azt_Play_msf *params); -static int aztSetDiskType(int type); -static int aztStatus(void); -static int getAztStatus(void); -static int aztPlay(struct azt_Play_msf *arg); -static void aztCloseDoor(void); -static void aztLockDoor(void); -static void aztUnlockDoor(void); -static int aztGetValue(unsigned char *result); -static int aztGetQChannelInfo(struct azt_Toc *qp); -static int aztUpdateToc(void); static int aztGetDiskInfo(void); #if AZT_MULTISESSION static int aztGetMultiDiskInfo(void); @@ -350,21 +332,15 @@ static int check_aztcd_media_change(kdev_t full_dev); static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static void azt_transfer(void); -static void do_aztcd_request(request_queue_t *); -static void azt_invalidate_buffers(void); -int aztcd_open(struct inode *ip, struct file *fp); - +static int aztcd_open(struct inode *ip, struct file *fp); static int aztcd_release(struct inode *inode, struct file *file); -int aztcd_init(void); - static struct block_device_operations azt_fops = { - owner:THIS_MODULE, - open:aztcd_open, - release:aztcd_release, - ioctl:aztcd_ioctl, - check_media_change:check_aztcd_media_change, + .owner = THIS_MODULE, + .open = aztcd_open, + .release = aztcd_release, + .ioctl = aztcd_ioctl, + .check_media_change = check_aztcd_media_change, }; /* Aztcd State Machine: Controls Drive Operating State */ @@ -384,7 +360,7 @@ busy waiting */ /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/ # define OP_OK op_ok() -void op_ok(void) +static void op_ok(void) { aztTimeOutCount = 0; do { @@ -399,7 +375,7 @@ /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/ # define PA_OK pa_ok() -void pa_ok(void) +static void pa_ok(void) { aztTimeOutCount = 0; do { @@ -414,7 +390,7 @@ /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/ # define STEN_LOW sten_low() -void sten_low(void) +static void sten_low(void) { aztTimeOutCount = 0; do { @@ -432,7 +408,7 @@ /* Wait for DTEN=Low = handshake signal 'Data available'*/ # define DTEN_LOW dten_low() -void dten_low(void) +static void dten_low(void) { aztTimeOutCount = 0; do { @@ -450,7 +426,7 @@ * may cause kernel panic when used in the wrong place */ #define STEN_LOW_WAIT statusAzt() -void statusAzt(void) +static void statusAzt(void) { AztTimeout = AZT_STATUS_DELAY; SET_TIMER(aztStatTimer, HZ / 100); @@ -757,7 +733,7 @@ * Read the current Q-channel info. Also used for reading the * table of contents. */ -int aztGetQChannelInfo(struct azt_Toc *qp) +static int aztGetQChannelInfo(struct azt_Toc *qp) { unsigned char notUsed; int st; @@ -1648,7 +1624,7 @@ /* * Open the device special file. Check that a disk is in. */ -int aztcd_open(struct inode *ip, struct file *fp) +static int aztcd_open(struct inode *ip, struct file *fp) { int st; @@ -1714,13 +1690,19 @@ return 0; } - +static struct gendisk azt_disk = { + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .fops = &azt_fops, + .major_name = "aztcd" +}; /* * Test for presence of drive and initialize it. Called at boot time. */ -int __init aztcd_init(void) +static int __init aztcd_init(void) { long int count, max_count; unsigned char result[50]; @@ -1939,7 +1921,7 @@ } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); - register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &azt_fops, 0); + add_disk(&azt_disk); azt_invalidate_buffers(); aztPresent = 1; @@ -1955,9 +1937,10 @@ } -void __exit aztcd_exit(void) +static void __exit aztcd_exit(void) { devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0); + del_gendisk(&azt_disk); if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { printk("What's that: can't unregister aztcd\n"); return; @@ -1971,9 +1954,7 @@ printk(KERN_INFO "aztcd module released.\n"); } -#ifdef MODULE module_init(aztcd_init); -#endif module_exit(aztcd_exit); /*########################################################################## diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/cdrom.c Sat Sep 21 21:25:45 2002 @@ -327,8 +327,6 @@ static void cdrom_sysctl_register(void); #endif /* CONFIG_SYSCTL */ static struct cdrom_device_info *topCdromPtr; -static devfs_handle_t devfs_handle; -static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER; /* This macro makes sure we don't have to check on cdrom_device_ops * existence in the run-time routines below. Change_capability is a @@ -381,26 +379,6 @@ if (check_media_type==1) cdi->options |= (int) CDO_CHECK_TYPE; - if (!devfs_handle) - devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL); - cdi->number = devfs_alloc_unique_number (&cdrom_numspace); - if (cdi->de) { - int pos; - devfs_handle_t slave; - char rname[64]; - - pos = devfs_generate_path (cdi->de, rname + 3, - sizeof rname - 3); - if (pos >= 0) { - char vname[16]; - sprintf (vname, "cdrom%d", cdi->number); - strncpy (rname + pos, "../", 3); - devfs_mk_symlink (devfs_handle, vname, - DEVFS_FL_DEFAULT, - rname + pos, &slave, NULL); - devfs_auto_unregister (cdi->de, slave); - } - } cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); cdi->next = topCdromPtr; topCdromPtr = cdi; @@ -432,8 +410,6 @@ else topCdromPtr = cdi->next; cdi->ops->n_minors--; - devfs_unregister (cdi->de); - devfs_dealloc_unique_number (&cdrom_numspace, cdi->number); cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); return 0; } @@ -2618,8 +2594,6 @@ #ifdef CONFIG_SYSCTL cdrom_sysctl_register(); #endif - if (!devfs_handle) - devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL); return 0; } @@ -2629,7 +2603,6 @@ #ifdef CONFIG_SYSCTL cdrom_sysctl_unregister(); #endif - devfs_unregister(devfs_handle); } module_init(cdrom_init); diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c --- a/drivers/cdrom/cdu31a.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/cdu31a.c Sat Sep 21 21:25:45 2002 @@ -3154,41 +3154,50 @@ struct block_device_operations scd_bdops = { - owner: THIS_MODULE, - open: cdrom_open, - release: cdrom_release, - ioctl: cdrom_ioctl, - check_media_change: cdrom_media_changed, + .owner = THIS_MODULE, + .open = cdrom_open, + .release = cdrom_release, + .ioctl = cdrom_ioctl, + .check_media_change = cdrom_media_changed, }; static struct cdrom_device_ops scd_dops = { - open:scd_open, - release:scd_release, - drive_status:scd_drive_status, - media_changed:scd_media_changed, - tray_move:scd_tray_move, - lock_door:scd_lock_door, - select_speed:scd_select_speed, - get_last_session:scd_get_last_session, - get_mcn:scd_get_mcn, - reset:scd_reset, - audio_ioctl:scd_audio_ioctl, - dev_ioctl:scd_dev_ioctl, - capability:CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | - CDC_SELECT_SPEED | CDC_MULTI_SESSION | - CDC_MULTI_SESSION | CDC_MCN | - CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, - n_minors:1, + .open = scd_open, + .release = scd_release, + .drive_status = scd_drive_status, + .media_changed = scd_media_changed, + .tray_move = scd_tray_move, + .lock_door = scd_lock_door, + .select_speed = scd_select_speed, + .get_last_session = scd_get_last_session, + .get_mcn = scd_get_mcn, + .reset = scd_reset, + .audio_ioctl = scd_audio_ioctl, + .dev_ioctl = scd_dev_ioctl, + .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | + CDC_SELECT_SPEED | CDC_MULTI_SESSION | + CDC_MULTI_SESSION | CDC_MCN | + CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | + CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, + .n_minors = 1, }; static struct cdrom_device_info scd_info = { - ops:&scd_dops, - speed:2, - capacity:1, - name:"cdu31a" + .ops = &scd_dops, + .speed = 2, + .capacity = 1, + .name = "cdu31a" }; +static struct gendisk scd_gendisk = { + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .major_name = "cdu31a" + .fops = &scd_bdops, + .flags = GENHD_FL_CD, +} + /* The different types of disc loading mechanisms supported */ static char *load_mech[] __initdata = { "caddy", "tray", "pop-up", "unknown" }; @@ -3291,6 +3300,7 @@ int __init cdu31a_init(void) { struct s_sony_drive_config drive_config; + struct gendisk *disk = &scd_gendisk; unsigned int res_size; char msg[255]; char buf[40]; @@ -3431,12 +3441,9 @@ scd_info.dev = mk_kdev(MAJOR_NR, 0); scd_info.mask = deficiency; - strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name)); - - if (register_cdrom(&scd_info)) { + if (register_cdrom(&scd_info)) goto errout0; - } - devfs_plain_cdrom(&scd_info, &scd_bdops); + add_disk(disk); } @@ -3462,6 +3469,7 @@ void __exit cdu31a_exit(void) { + del_gendisk(&scd_gendisk); if (unregister_cdrom(&scd_info)) { printk ("Can't unregister cdu31a from Uniform cdrom driver\n"); diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c --- a/drivers/cdrom/cm206.c Sat Sep 21 21:25:48 2002 +++ b/drivers/cdrom/cm206.c Sat Sep 21 21:25:48 2002 @@ -772,11 +772,11 @@ struct block_device_operations cm206_bdops = { - owner: THIS_MODULE, - open: cdrom_open, - release: cdrom_release, - ioctl: cdrom_ioctl, - check_media_change: cdrom_media_changed, + .owner = THIS_MODULE, + .open = cdrom_open, + .release = cdrom_release, + .ioctl = cdrom_ioctl, + .check_media_change = cdrom_media_changed, }; /* The new open. The real opening strategy is defined in cdrom.c. */ @@ -1330,57 +1330,41 @@ } static struct cdrom_device_ops cm206_dops = { - open:cm206_open, - release:cm206_release, - drive_status:cm206_drive_status, - media_changed:cm206_media_changed, - tray_move:cm206_tray_move, - lock_door:cm206_lock_door, - select_speed:cm206_select_speed, - get_last_session:cm206_get_last_session, - get_mcn:cm206_get_upc, - reset:cm206_reset, - audio_ioctl:cm206_audio_ioctl, - dev_ioctl:cm206_ioctl, - capability:CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | - CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | - CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | - CDC_IOCTLS | CDC_DRIVE_STATUS, - n_minors:1, + .open = cm206_open, + .release = cm206_release, + .drive_status = cm206_drive_status, + .media_changed = cm206_media_changed, + .tray_move = cm206_tray_move, + .lock_door = cm206_lock_door, + .select_speed = cm206_select_speed, + .get_last_session = cm206_get_last_session, + .get_mcn = cm206_get_upc, + .reset = cm206_reset, + .audio_ioctl = cm206_audio_ioctl, + .dev_ioctl = cm206_ioctl, + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | + CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | + CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | + CDC_IOCTLS | CDC_DRIVE_STATUS, + .n_minors = 1, }; static struct cdrom_device_info cm206_info = { - ops:&cm206_dops, - speed:2, - capacity:1, - name:"cm206", + .ops = &cm206_dops, + .speed = 2, + .capacity = 1, + .name = "cm206", }; -/* This routine gets called during initialization if things go wrong, - * can be used in cleanup_module as well. */ -static void cleanup(int level) -{ - switch (level) { - case 4: - if (unregister_cdrom(&cm206_info)) { - printk("Can't unregister cdrom cm206\n"); - return; - } - if (unregister_blkdev(MAJOR_NR, "cm206")) { - printk("Can't unregister major cm206\n"); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - case 3: - free_irq(cm206_irq, NULL); - case 2: - case 1: - kfree(cd); - release_region(cm206_base, 16); - default:; - } -} +static struct gendisk cm206_gendisk = { + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .major_name = "cm206", + .fops = &cm206_bdops, + .flags = GENHD_FL_CD, +}; /* This function probes for the adapter card. It returns the base address if it has found the adapter card. One can specify a base @@ -1435,6 +1419,7 @@ { uch e = 0; long int size = sizeof(struct cm206_struct); + struct gendisk *disk = &cm206_gendisk; printk(KERN_INFO "cm206 cdrom driver " REVISION); cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); @@ -1454,7 +1439,7 @@ cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq); if (cm206_irq <= 0) { printk("can't find IRQ!\n"); - cleanup(1); + goto out_probe; return -EIO; } else printk(" IRQ %d found\n", cm206_irq); @@ -1472,8 +1457,7 @@ if (send_receive_polled(c_drive_configuration) != c_drive_configuration) { printk(KERN_INFO " drive not there\n"); - cleanup(1); - return -EIO; + goto out_probe; } e = send_receive_polled(c_gimme); printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code); @@ -1486,24 +1470,19 @@ printk(", motorized tray"); if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) { printk("\nUnable to reserve IRQ---aborted\n"); - cleanup(2); - return -EIO; + goto out_probe; } printk(".\n"); if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) { - printk(KERN_INFO "Cannot register for major %d!\n", - MAJOR_NR); - cleanup(3); - return -EIO; + printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); + goto out_blkdev; } cm206_info.dev = mk_kdev(MAJOR_NR, 0); if (register_cdrom(&cm206_info) != 0) { - printk(KERN_INFO "Cannot register for cdrom %d!\n", - MAJOR_NR); - cleanup(3); - return -EIO; + printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR); + goto out_cdrom; } - devfs_plain_cdrom(&cm206_info, &cm206_bdops); + add_disk(disk); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cm206_request, &cm206_lock); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); @@ -1517,6 +1496,15 @@ " %ld bytes kernel memory used.\n", cd->max_sectors * 2, size); return 0; + +out_cdrom: + unregister_blkdev(MAJOR_NR, "cm206"); +out_blkdev: + free_irq(cm206_irq, NULL); +out_probe: + kfree(cd); + release_region(cm206_base, 16); + return -EIO; } #ifdef MODULE @@ -1548,7 +1536,19 @@ void __exit cm206_exit(void) { - cleanup(4); + del_gendisk(&cm206_gendisk); + if (unregister_cdrom(&cm206_info)) { + printk("Can't unregister cdrom cm206\n"); + return; + } + if (unregister_blkdev(MAJOR_NR, "cm206")) { + printk("Can't unregister major cm206\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + free_irq(cm206_irq, NULL); + kfree(cd); + release_region(cm206_base, 16); printk(KERN_INFO "cm206 removed\n"); } diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Sat Sep 21 21:25:43 2002 +++ b/drivers/cdrom/gscd.c Sat Sep 21 21:25:43 2002 @@ -86,14 +86,12 @@ * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq); */ -static void gscd_transfer(void); static void gscd_read_cmd(void); static void gscd_hsg2msf(long hsg, struct msf *msf); static void gscd_bin2bcd(unsigned char *p); /* Schnittstellen zum Kern/FS */ -static void do_gscd_request(request_queue_t *); static void __do_gscd_request(unsigned long dummy); static int gscd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); @@ -103,13 +101,8 @@ /* GoldStar Funktionen */ -static void cc_Reset(void); -static int wait_drv_ready(void); -static int find_drives(void); static void cmd_out(int, char *, char *, int); static void cmd_status(void); -static void cc_Ident(char *); -static void cc_SetSpeed(void); static void init_cd_drive(int); static int get_status(void); @@ -123,10 +116,6 @@ static int gscd_bcd2bin(unsigned char bcd); #endif -/* common GoldStar Initialization */ - -static int my_gscd_init(void); - /* lo-level cmd-Funktionen */ @@ -164,11 +153,11 @@ static spinlock_t gscd_lock = SPIN_LOCK_UNLOCKED; static struct block_device_operations gscd_fops = { - owner:THIS_MODULE, - open:gscd_open, - release:gscd_release, - ioctl:gscd_ioctl, - check_media_change:check_gscd_med_chg, + .owner = THIS_MODULE, + .open = gscd_open, + .release = gscd_release, + .ioctl = gscd_ioctl, + .check_media_change = check_gscd_med_chg, }; /* @@ -414,7 +403,7 @@ } -int get_status(void) +static int get_status(void) { int status; @@ -430,7 +419,7 @@ } -void cc_invalidate(void) +static void cc_invalidate(void) { drv_num_read = 0xFF; f_dsk_valid = 0xFF; @@ -441,7 +430,7 @@ } -void clear_Audio(void) +static void clear_Audio(void) { f_AudioPlay = 0; @@ -457,7 +446,7 @@ * waiting ? */ -int wait_drv_ready(void) +static int wait_drv_ready(void) { int found, read; @@ -475,7 +464,7 @@ return read; } -void cc_Ident(char *respons) +static void cc_Ident(char *respons) { char to_do[] = { CMD_IDENT, 0, 0 }; @@ -483,7 +472,7 @@ } -void cc_SetSpeed(void) +static void cc_SetSpeed(void) { char to_do[] = { CMD_SETSPEED, 0, 0 }; char dummy; @@ -494,8 +483,7 @@ } } - -void cc_Reset(void) +static void cc_Reset(void) { char to_do[] = { CMD_RESET, 0 }; char dummy; @@ -503,9 +491,7 @@ cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0); } - - -void cmd_status(void) +static void cmd_status(void) { char to_do[] = { CMD_STATUS, 0 }; char dummy; @@ -518,7 +504,7 @@ } -void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count) +static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count) { int result; @@ -817,7 +803,7 @@ return; } -int __init find_drives(void) +static int __init find_drives(void) { int *pdrv; int drvnum; @@ -861,7 +847,7 @@ return drvnum; } -void __init init_cd_drive(int num) +static void __init init_cd_drive(int num) { char resp[50]; int i; @@ -912,28 +898,20 @@ } #endif -/* Init for the Module-Version */ -int init_gscd(void) -{ - long err; - - - /* call the GoldStar-init */ - err = my_gscd_init(); - - if (err < 0) { - return err; - } else { - printk(KERN_INFO "Happy GoldStar !\n"); - return 0; - } -} +static struct gendisk gscd_disk = { + .major = MAJOR_NR, + .first_minor = 0, + ,minor_shift = 0, + .fops = &gscd_fops, + .major_name = "gscd" +}; -void __exit exit_gscd(void) +static void __exit gscd_exit(void) { CLEAR_TIMER; devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0); + del_gendisk(&gscd_disk); if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { printk("What's that: can't unregister GoldStar-module\n"); return; @@ -943,22 +921,9 @@ printk(KERN_INFO "GoldStar-module released.\n"); } -#ifdef MODULE -module_init(init_gscd); -#endif -module_exit(exit_gscd); - - -/* Test for presence of drive and initialize it. Called only at boot time. */ -int __init gscd_init(void) -{ - return my_gscd_init(); -} - - /* This is the common initialisation for the GoldStar drive. */ /* It is called at boot time AND for module init. */ -int __init my_gscd_init(void) +static int __init gscd_init(void) { int i; int result; @@ -1026,7 +991,7 @@ disk_state = 0; gscdPresent = 1; - register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &gscd_fops, 0); + add_disk(&gscd_disk); printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); return 0; @@ -1075,3 +1040,5 @@ MODULE_AUTHOR("Oliver Raupach "); MODULE_LICENSE("GPL"); +module_init(gscd_init); +module_exit(gscd_exit); diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c --- a/drivers/cdrom/mcd.c Sat Sep 21 21:25:46 2002 +++ b/drivers/cdrom/mcd.c Sat Sep 21 21:25:46 2002 @@ -194,31 +194,40 @@ struct block_device_operations mcd_bdops = { - owner: THIS_MODULE, - open: cdrom_open, - release: cdrom_release, - ioctl: cdrom_ioctl, - check_media_change: cdrom_media_changed, + .owner = THIS_MODULE, + .open = cdrom_open, + .release = cdrom_release, + .ioctl = cdrom_ioctl, + .check_media_change = cdrom_media_changed, }; static struct timer_list mcd_timer; static struct cdrom_device_ops mcd_dops = { - open:mcd_open, - release:mcd_release, - drive_status:mcd_drive_status, - media_changed:mcd_media_changed, - tray_move:mcd_tray_move, - audio_ioctl:mcd_audio_ioctl, - capability:CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | - CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, + .open = mcd_open, + .release = mcd_release, + .drive_status = mcd_drive_status, + .media_changed = mcd_media_changed, + .tray_move = mcd_tray_move, + .audio_ioctl = mcd_audio_ioctl, + .capability = CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | + CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, }; static struct cdrom_device_info mcd_info = { - ops:&mcd_dops, - speed:2, - capacity:1, - name:"mcd", + .ops = &mcd_dops, + .speed = 2, + .capacity = 1, + .name = "mcd", +}; + +static struct gendisk mcd_gendisk = { + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .major_name = "mcd", + .fops = &mcd_bdops, + .flags = GENHD_FL_CD; }; #ifndef MODULE @@ -1023,39 +1032,13 @@ } } - - -/* This routine gets called during initialization if things go wrong, - * and is used in mcd_exit as well. */ -static void cleanup(int level) -{ - switch (level) { - case 3: - if (unregister_cdrom(&mcd_info)) { - printk(KERN_WARNING "Can't unregister cdrom mcd\n"); - return; - } - free_irq(mcd_irq, NULL); - case 2: - release_region(mcd_port, 4); - case 1: - if (unregister_blkdev(MAJOR_NR, "mcd")) { - printk(KERN_WARNING "Can't unregister major mcd\n"); - return; - } - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - default:; - } -} - - - /* * Test for presence of drive and initialize it. Called at boot time. */ int __init mcd_init(void) { + struct gendisk *disk = &mcd_gendisk; int count; unsigned char result[3]; char msg[80]; @@ -1070,9 +1053,8 @@ return -EIO; } if (!request_region(mcd_port, 4, "mcd")) { - cleanup(1); printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port); - return -EIO; + goto out_region; } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcd_request, @@ -1092,8 +1074,7 @@ if (count >= 2000000) { printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n", mcd_port, mcd_irq); - cleanup(2); - return -EIO; + goto out_probe; } count = inb(MCDPORT(0)); /* pick up the status */ @@ -1102,14 +1083,11 @@ if (getValue(result + count)) { printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n", mcd_port); - cleanup(2); - return -EIO; + goto out_probe; } - if (result[0] == result[1] && result[1] == result[2]) { - cleanup(2); - return -EIO; - } + if (result[0] == result[1] && result[1] == result[2]) + goto out_probe; mcdVersion = result[2]; @@ -1120,8 +1098,7 @@ if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) { printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq); - cleanup(2); - return -EIO; + goto out_probe; } if (result[1] == 'D') { @@ -1151,13 +1128,20 @@ if (register_cdrom(&mcd_info) != 0) { printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n"); - cleanup(3); - return -EIO; + goto out_cdrom; } - devfs_plain_cdrom(&mcd_info, &mcd_bdops); + add_disk(disk); printk(msg); - return 0; + +out_cdrom: + free_irq(mcd_irq, NULL); +out_probe: + release_region(mcd_port, 4); +out_region: + unregister_blkdev(MAJOR_NR, "mcd"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + return -EIO; } @@ -1522,7 +1506,18 @@ void __exit mcd_exit(void) { - cleanup(3); + del_gendisk(&mcd_gendisk); + if (unregister_cdrom(&mcd_info)) { + printk(KERN_WARNING "Can't unregister cdrom mcd\n"); + return; + } + free_irq(mcd_irq, NULL); + release_region(mcd_port, 4); + if (unregister_blkdev(MAJOR_NR, "mcd")) { + printk(KERN_WARNING "Can't unregister major mcd\n"); + return; + } + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); del_timer_sync(&mcd_timer); } diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/mcdx.c Sat Sep 21 21:25:45 2002 @@ -206,6 +206,7 @@ int status; /* last operation's error / status */ int readerrs; /* # of blocks read w/o error */ struct cdrom_device_info info; + struct gendisk disk; }; @@ -1020,6 +1021,7 @@ struct s_drive_stuff *stuffp = mcdx_stuffp[i]; if (!stuffp) continue; + del_gendisk(&stuffp->disk); if (unregister_cdrom(&stuffp->info)) { printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); return; @@ -1059,6 +1061,7 @@ int __init mcdx_init_drive(int drive) { struct s_version version; + struct gendisk *disk; struct s_drive_stuff *stuffp; int size = sizeof(*stuffp); char msg[80]; @@ -1203,6 +1206,13 @@ stuffp->info.handle = stuffp; sprintf(stuffp->info.name, "mcdx%d", drive); stuffp->info.dev = mk_kdev(MAJOR_NR, drive); + disk = &stuffp->disk; + disk->major = MAJOR_NR; + disk->first_minor = drive; + disk->minor_shift = 0; + disk->major_name = stuffp->info.name; + disk->fops = &mcdx_bdops; + disk->flags = GENHD_FL_CD; sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d." " (Firmware version %c %x)\n", @@ -1220,7 +1230,7 @@ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); return 2; } - devfs_plain_cdrom(&stuffp->info, &mcdx_bdops); + add_disk(disk); printk(msg); return 0; } diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/optcd.c Sat Sep 21 21:25:45 2002 @@ -742,7 +742,7 @@ #if DEBUG_TOC -void toc_debug_info(int i) +static void toc_debug_info(int i) { printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d" " %2d:%02d.%02d %2d:%02d.%02d\n", @@ -1973,11 +1973,11 @@ static struct block_device_operations opt_fops = { - owner: THIS_MODULE, - open: opt_open, - release: opt_release, - ioctl: opt_ioctl, - check_media_change: opt_media_change, + .owner = THIS_MODULE, + .open = opt_open, + .release = opt_release, + .ioctl = opt_ioctl, + .check_media_change = opt_media_change, }; #ifndef MODULE @@ -1997,9 +1997,17 @@ #endif /* MODULE */ +static struct gendisk optcd_disk = { + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .fops = &opt_fops, + .major_name = "optcd" +}; + /* Test for presence of drive and initialize it. Called at boot time or during module initialisation. */ -int __init optcd_init(void) +static int __init optcd_init(void) { int status; @@ -2041,16 +2049,17 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request, &optcd_lock); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); - register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &opt_fops, 0); + add_disk(&optcd_disk); printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port); return 0; } -void __exit optcd_exit(void) +static void __exit optcd_exit(void) { devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0); + del_gendisk(&optcd_disk); if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { printk(KERN_ERR "optcd: what's that: can't unregister\n"); return; @@ -2060,10 +2069,7 @@ printk(KERN_INFO "optcd: module released.\n"); } -#ifdef MODULE module_init(optcd_init); -#endif module_exit(optcd_exit); - MODULE_LICENSE("GPL"); diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/sbpcd.c Sat Sep 21 21:25:45 2002 @@ -722,7 +722,7 @@ u_char mode_xb_8; u_char delay; struct cdrom_device_info *sbpcd_infop; - + struct gendisk disk; } D_S[NR_SBPCD]; static struct sbpcd_drive *current_drive = D_S; @@ -5777,6 +5777,7 @@ for (j=0;jdrv_id==-1) continue; @@ -5829,15 +5830,20 @@ sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); sbpcd_infop->handle = p; p->sbpcd_infop = sbpcd_infop; - sprintf(nbuff, "c0t%d/cd", p->drv_id); - sbpcd_infop->de = - devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT, - MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO, - &sbpcd_bdops, NULL); + disk = &p->disk; + disk->major = MAJOR_NR; + disk->first_minor = j; + disk->minor_shift = 0; + disk->fops = &sbpcd_bdops; + disk->major_name = sbpcd_infop->name; + disk->flags = GENHD_FL_CD; + sprintf(nbuff, "c0t%d", p->drv_id); + disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL); if (register_cdrom(sbpcd_infop)) { printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); } + add_disk(disk); } blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE); @@ -5863,8 +5869,10 @@ for (j=0;j0) vfree(D_S[j].aud_buf); + devfs_unregister(D_S[j].disk.de); if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL)) { msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name); diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Sat Sep 21 21:25:46 2002 +++ b/drivers/cdrom/sjcd.c Sat Sep 21 21:25:46 2002 @@ -1528,7 +1528,7 @@ /* * Open the device special file. Check disk is in. */ -int sjcd_open(struct inode *ip, struct file *fp) +static int sjcd_open(struct inode *ip, struct file *fp) { /* * Check the presence of device. @@ -1647,11 +1647,11 @@ * A list of file operations allowed for this cdrom. */ static struct block_device_operations sjcd_fops = { - owner:THIS_MODULE, - open:sjcd_open, - release:sjcd_release, - ioctl:sjcd_ioctl, - check_media_change:sjcd_disk_change, + .owner = THIS_MODULE, + .open = sjcd_open, + .release = sjcd_release, + .ioctl = sjcd_ioctl, + .check_media_change = sjcd_disk_change, }; /* @@ -1664,11 +1664,20 @@ unsigned char major, minor; } sjcd_version; +static struct gendisk sjcd_disk = +{ + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .fops = &sjcd_fops, + .major_name = "sjcd" +}; + /* * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */ -int __init sjcd_init(void) +static int __init sjcd_init(void) { int i; @@ -1688,7 +1697,6 @@ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); - register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &sjcd_fops, 0); if (check_region(sjcd_base, 4)) { printk @@ -1782,6 +1790,7 @@ printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); + add_disk(&sjcd_disk); sjcd_present++; return (0); @@ -1800,19 +1809,17 @@ } -void __exit sjcd_exit(void) +static void __exit sjcd_exit(void) { devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0); + del_gendisk(&sjcd_disk); if (sjcd_cleanup()) printk("SJCD: module: cannot be removed.\n"); else printk(KERN_INFO "SJCD: module: removed.\n"); } -#ifdef MODULE module_init(sjcd_init); -#endif module_exit(sjcd_exit); - MODULE_LICENSE("GPL"); diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Sat Sep 21 21:25:45 2002 +++ b/drivers/cdrom/sonycd535.c Sat Sep 21 21:25:45 2002 @@ -1448,18 +1448,25 @@ static struct block_device_operations cdu_fops = { - owner: THIS_MODULE, - open: cdu_open, - release: cdu_release, - ioctl: cdu_ioctl, - check_media_change: cdu535_check_media_change, + .owner = THIS_MODULE, + .open = cdu_open, + .release = cdu_release, + .ioctl = cdu_ioctl, + .check_media_change = cdu535_check_media_change, }; +static struct gendisk cdu_disk = +{ + .major = MAJOR_NR, + .first_minor = 0, + .minor_shift = 0, + .fops = &cdu_fops, + .major_name = "cdu" + /* * Initialize the driver. */ -int __init -sony535_init(void) +static int __init sony535_init(void) { struct s535_sony_drive_config drive_config; Byte cmd_buff[3]; @@ -1648,7 +1655,7 @@ return -EIO; } - register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &cdu_fops, 0); + add_disk(&cdu_disk); return 0; } @@ -1688,7 +1695,7 @@ #endif /* MODULE */ void __exit -sony535_exit(void) +static sony535_exit(void) { int i; @@ -1700,15 +1707,14 @@ kfree(sony_toc); devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0, DEVFS_SPECIAL_BLK, 0); + del_gendisk(&cdu_disk); if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); else printk(KERN_INFO CDU535_HANDLE " module released\n"); } -#ifdef MODULE module_init(sony535_init); -#endif module_exit(sony535_exit); diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/ide-cd.c Sat Sep 21 21:25:45 2002 @@ -2611,12 +2611,6 @@ if (!CDROM_CONFIG_FLAGS(drive)->close_tray) devinfo->mask |= CDC_CLOSE_TRAY; - devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, - drive->disk->major, - drive->disk->first_minor, - S_IFBLK | S_IRUGO | S_IWUGO, - ide_fops, NULL); - return register_cdrom(devinfo); } @@ -3127,6 +3121,9 @@ memset(info, 0, sizeof (struct cdrom_info)); drive->driver_data = info; DRIVER(drive)->busy++; + g->minor_shift = 0; + g->de = drive->de; + g->flags = GENHD_FL_CD; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; DRIVER(drive)->busy--; @@ -3146,14 +3143,7 @@ DRIVER(drive)->busy--; cdrom_read_toc(drive, &sense); - g->minor_shift = 0; - /* probably bogus, but that's the old behaviour */ - g->de = NULL; - g->flags = GENHD_FL_DEVFS; - add_gendisk(g); - register_disk(g, mk_kdev(g->major,g->first_minor), - 1<minor_shift, ide_fops, - get_capacity(g)); + add_disk(g); return 0; failed: return 1; diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/ide-disk.c Sat Sep 21 21:25:45 2002 @@ -1706,10 +1706,8 @@ g->de = drive->de; g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; g->flags |= GENHD_FL_DEVFS; - add_gendisk(g); - register_disk(g, mk_kdev(g->major,g->first_minor), - 1<minor_shift, ide_fops, - current_capacity(drive)); + set_capacity(g, current_capacity(drive)); + add_disk(g); return 0; failed: return 1; diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/ide-floppy.c Sat Sep 21 21:25:45 2002 @@ -2111,10 +2111,7 @@ g->de = drive->de; g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; g->flags |= GENHD_FL_DEVFS; - add_gendisk(g); - register_disk(g, mk_kdev(g->major,g->first_minor), - 1<minor_shift, ide_fops, - get_capacity(g)); + add_disk(g); return 0; failed: return 1; diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/ide-probe.c Sat Sep 21 21:25:45 2002 @@ -563,6 +563,11 @@ { u32 i = 0; + /* register with global device tree */ + strncpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); + snprintf(hwif->gendev.name,DEVICE_NAME_SIZE,"IDE Controller"); + device_register(&hwif->gendev); + if (hwif->mmio == 2) return; if (hwif->io_ports[IDE_CONTROL_OFFSET]) @@ -715,8 +720,9 @@ u16 unit = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) + if (drive->present) { ata_attach(drive); + } } } #endif @@ -973,6 +979,15 @@ gd[unit].major_name = names + 4*unit; gd[unit].minor_shift = PARTN_BITS; gd[unit].fops = ide_fops; + + snprintf(gd[unit].disk_dev.bus_id,BUS_ID_SIZE,"%u.%u", + hwif->index,unit); + snprintf(gd[unit].disk_dev.name,DEVICE_NAME_SIZE, + "%s","IDE Drive"); + gd[unit].disk_dev.parent = &hwif->gendev; + gd[unit].disk_dev.bus = &ide_bus_type; + device_register(&gd[unit].disk_dev); + hwif->drives[unit].disk = gd + unit; } diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/ide.c Sat Sep 21 21:25:45 2002 @@ -152,6 +152,7 @@ #include #include #include +#include #include #include @@ -3524,6 +3525,10 @@ 5 }; +struct bus_type ide_bus_type = { + .name = "ide", +}; + /* * This is gets invoked once during initialization, to set *everything* up */ @@ -3537,6 +3542,8 @@ banner_printed = 1; } + bus_register(&ide_bus_type); + init_ide_data(); initializing = 1; @@ -3591,6 +3598,8 @@ proc_ide_destroy(); #endif devfs_unregister (ide_devfs_handle); + + bus_unregister(&ide_bus_type); } #else /* !MODULE */ diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c --- a/drivers/ide/legacy/hd.c Sat Sep 21 21:25:43 2002 +++ b/drivers/ide/legacy/hd.c Sat Sep 21 21:25:43 2002 @@ -838,11 +838,9 @@ } for(drive=0; drive < NR_HD; drive++) { - add_gendisk(hd_gendisk + drive); - register_disk(hd_gendisk + drive, - mk_kdev(MAJOR_NR,drive<<6), 1<<6, - &hd_fops, hd_info[drive].head * hd_info[drive].sect * - hd_info[drive].cyl); + struct hd_i_struct *p = hd_info + drive; + set_capacity(hd_gendisk + drive, p->head * p->sect * p->cyl); + add_disk(hd_gendisk + drive); } } diff -Nru a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c --- a/drivers/ide/pci/cy82c693.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/pci/cy82c693.c Sat Sep 21 21:25:45 2002 @@ -429,7 +429,7 @@ } static struct pci_device_id cy82c693_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Sat Sep 21 21:25:45 2002 +++ b/drivers/ide/setup-pci.c Sat Sep 21 21:25:45 2002 @@ -389,7 +389,7 @@ ulong flags = pci_resource_flags(dev, bar); /* Unconfigured ? */ - if(pci_resource_len(dev, bar) == 0) + if (!flags || pci_resource_len(dev, bar) == 0) return 0; /* I/O space */ @@ -422,10 +422,8 @@ unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || - ((dev->class & ~(0xfa))) || - (dev->class & (port ? 4 : 1)) != 0) - { + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + { /* Possibly we should fail if these checks report true */ ide_pci_check_iomem(dev, d, 2*port); ide_pci_check_iomem(dev, d, 2*port+1); @@ -667,6 +665,9 @@ if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL) continue; + + /* setup proper ancestral information */ + hwif->gendev.parent = &dev->dev; if (hwif->channel) { index.b.high = hwif->index; diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Sat Sep 21 21:25:45 2002 +++ b/drivers/md/md.c Sat Sep 21 21:25:45 2002 @@ -243,43 +243,6 @@ return NULL; } -static LIST_HEAD(device_names); - -char * partition_name(kdev_t dev) -{ - struct gendisk *hd; - static char nomem [] = ""; - dev_name_t *dname; - struct list_head *tmp; - - list_for_each(tmp, &device_names) { - dname = list_entry(tmp, dev_name_t, list); - if (kdev_same(dname->dev, dev)) - return dname->name; - } - - dname = (dev_name_t *) kmalloc(sizeof(*dname), GFP_KERNEL); - - if (!dname) - return nomem; - /* - * ok, add this new device name to the list - */ - hd = get_gendisk (dev); - dname->name = NULL; - if (hd) - dname->name = disk_name(hd, minor(dev)-hd->first_minor, dname->namebuf); - if (!dname->name) { - sprintf (dname->namebuf, "[dev %s]", kdevname(dev)); - dname->name = dname->namebuf; - } - - dname->dev = dev; - list_add(&dname->list, &device_names); - - return dname->name; -} - static unsigned int calc_dev_sboffset(struct block_device *bdev) { unsigned int size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; @@ -613,7 +576,7 @@ static void print_desc(mdp_disk_t *desc) { printk(" DISK\n", desc->number, - partition_name(mk_kdev(desc->major,desc->minor)), + partition_name(MKDEV(desc->major,desc->minor)), desc->major,desc->minor,desc->raid_disk,desc->state); } @@ -970,7 +933,7 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { - printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(to_kdev_t(newdev))); + printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(newdev)); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -981,7 +944,7 @@ err = lock_rdev(rdev, newdev); if (err) { printk(KERN_ERR "md: could not lock %s.\n", - partition_name(to_kdev_t(newdev))); + partition_name(newdev)); goto abort_free; } rdev->desc_nr = -1; @@ -1466,9 +1429,8 @@ mddev->state &= ~(1 << MD_SB_CLEAN); md_update_sb(mddev); md_recover_arrays(); - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major,disk->first_minor), - 1, &md_fops, md_size[mdidx(mddev)]<<1); + set_capacity(disk, md_size[mdidx(mddev)]<<1); + add_disk(disk); disks[mdidx(mddev)] = disk; return (0); @@ -1754,7 +1716,7 @@ start_rdev = md_import_device(startdev, 1); if (IS_ERR(start_rdev)) { - printk(KERN_WARNING "md: could not import %s!\n", partition_name(to_kdev_t(startdev))); + printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev)); goto abort; } @@ -1789,7 +1751,7 @@ rdev = md_import_device(dev, 1); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n", - partition_name(to_kdev_t(dev))); + partition_name(dev)); continue; } list_add(&rdev->same_set, &pending_raid_disks); @@ -1994,7 +1956,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to generate %s error in md%d ... \n", - partition_name(to_kdev_t(dev)), mdidx(mddev)); + partition_name(dev), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) { @@ -2028,7 +1990,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to remove %s from md%d ... \n", - partition_name(to_kdev_t(dev)), mdidx(mddev)); + partition_name(dev), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) @@ -2057,7 +2019,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", - partition_name(to_kdev_t(dev)), mdidx(mddev)); + partition_name(dev), mdidx(mddev)); if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING "md%d: personality does not support diskops!\n", @@ -2232,7 +2194,7 @@ err = autostart_array(arg); if (err) { printk(KERN_WARNING "md: autostart %s failed!\n", - partition_name(val_to_kdev(arg))); + partition_name(arg)); goto abort; } goto done; @@ -3231,7 +3193,7 @@ rdev = md_import_device(dev,1); if (IS_ERR(rdev)) { printk(KERN_ALERT "md: could not import %s!\n", - partition_name(to_kdev_t(dev))); + partition_name(dev)); continue; } if (rdev->faulty) { @@ -3499,17 +3461,6 @@ return md_init(); } -static void free_device_names(void) -{ - while (!list_empty(&device_names)) { - dev_name_t *tmp = list_entry(device_names.next, - dev_name_t, list); - list_del(&tmp->list); - kfree(tmp); - } -} - - void cleanup_module(void) { md_unregister_thread(md_recovery_thread); @@ -3524,15 +3475,12 @@ blk_dev[MAJOR_NR].queue = NULL; blk_clear(MAJOR_NR); - - free_device_names(); } #endif EXPORT_SYMBOL(md_size); EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); -EXPORT_SYMBOL(partition_name); EXPORT_SYMBOL(md_error); EXPORT_SYMBOL(md_sync_acct); EXPORT_SYMBOL(md_done_sync); diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Sat Sep 21 21:25:47 2002 +++ b/drivers/message/i2o/i2o_block.c Sat Sep 21 21:25:48 2002 @@ -719,11 +719,7 @@ struct gendisk *p = &i2o_disk[unit>>4]; i2ob_install_device(i2ob_dev[unit].i2odev->controller, i2ob_dev[unit].i2odev, unit); - add_gendisk(p); - register_disk(p, - mk_kdev(p->major, p->first_minor), - 1<minor_shift, p->fops, - get_capacity(p)); + add_disk(p); break; } @@ -1465,12 +1461,7 @@ printk(KERN_WARNING "Could not install I2O block device\n"); else { - struct gendisk *p = &i2o_disk[scan_unit>>4]; - add_gendisk(p); - register_disk(p, - mk_kdev(p->major, p->first_minor), - 1<minor_shift, p->fops, - get_capacity(p)); + add_disk(&i2o_disk[scan_unit>>4]); scan_unit+=16; i2ob_dev_count++; @@ -1558,12 +1549,7 @@ printk(KERN_ERR "i2o_block: Could not install new device\n"); else { - struct gendisk *p = &i2o_disk[unit>>4]; - add_gendisk(p); - register_disk(p, - mk_kdev(p->major, p->first_minor), - 1<minor_shift, p->fops, - get_capacity(p)); + add_disk(&i2o_disk[unit>>4]); i2ob_dev_count++; i2o_device_notify_on(d, &i2o_block_handler); } diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Sat Sep 21 21:25:45 2002 +++ b/drivers/mtd/ftl.c Sat Sep 21 21:25:45 2002 @@ -94,12 +94,6 @@ /* Funky stuff for setting up a block device */ #define MAJOR_NR FTL_MAJOR -#define DEVICE_OFF(device) - -#define DEVICE_NR(minor) ((minor)>>5) -#define REGION_NR(minor) (((minor)>>3)&3) -#define PART_NR(minor) ((minor)&7) -#define MINOR_NR(dev,reg,part) (((dev)<<5)+((reg)<<3)+(part)) #include @@ -1258,10 +1252,8 @@ partition->state = FTL_FORMATTED; atomic_set(&partition->open, 0); myparts[device] = partition; - add_gendisk(disk); - register_disk(disk, mk_kdev(MAJOR_NR, device << 4), - MAX_PART, &ftl_blk_fops, - le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE); + set_capacity(disk, le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE); + add_disk(disk); #ifdef PCMCIA_DEBUG printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", le32_to_cpu(partition->header.FormattedSize) >> 10); diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Sat Sep 21 21:25:45 2002 +++ b/drivers/mtd/mtdblock.c Sat Sep 21 21:25:45 2002 @@ -490,13 +490,7 @@ return 0; } -#if LINUX_VERSION_CODE < 0x20300 -#define RQFUNC_ARG void -#else -#define RQFUNC_ARG request_queue_t *q -#endif - -static void mtdblock_request(RQFUNC_ARG) +static void mtdblock_request(request_queue *q) { /* Don't do anything, except wake the thread if necessary */ wake_up(&thr_wq); @@ -522,10 +516,8 @@ return put_user((u64)mtdblk->mtd->size, (u64 *)arg); case BLKFLSBUF: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) if(!capable(CAP_SYS_ADMIN)) return -EACCES; -#endif fsync_bdev(inode->i_bdev); invalidate_bdev(inode->i_bdev, 0); down(&mtdblk->cache_sem); @@ -540,16 +532,6 @@ } } -#if LINUX_VERSION_CODE < 0x20326 -static struct file_operations mtd_fops = -{ - open: mtdblock_open, - ioctl: mtdblock_ioctl, - release: mtdblock_release, - read: block_read, - write: block_write -}; -#else static struct block_device_operations mtd_fops = { owner: THIS_MODULE, @@ -557,7 +539,6 @@ release: mtdblock_release, ioctl: mtdblock_ioctl }; -#endif #ifdef CONFIG_DEVFS_FS /* Notification that a new device has been added. Create the devfs entry for diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c --- a/drivers/mtd/mtdblock_ro.c Sat Sep 21 21:25:45 2002 +++ b/drivers/mtd/mtdblock_ro.c Sat Sep 21 21:25:45 2002 @@ -22,35 +22,24 @@ #define DEVICE_NR(device) (device) #include -#if LINUX_VERSION_CODE < 0x20300 -#define RQFUNC_ARG void -#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) -#else #define RQFUNC_ARG request_queue_t *q -#endif #ifdef MTDBLOCK_DEBUG static int debug = MTDBLOCK_DEBUG; MODULE_PARM(debug, "i"); #endif - -static int mtd_sizes[MAX_MTD_DEVICES]; - +static struct gendisk mtd_disks[MAX_MTD_DEVICES]; +static char names names[MAX_MTD_DEVICES][11]; static int mtdblock_open(struct inode *inode, struct file *file) { struct mtd_info *mtd = NULL; - - int dev; + int dev = minor(inode->i_rdev); + struct gendisk *disk = mtd_disks + dev; DEBUG(1,"mtdblock_open\n"); - - if (inode == 0) - return -EINVAL; - - dev = minor(inode->i_rdev); - + mtd = get_mtd_device(NULL, dev); if (!mtd) return -EINVAL; @@ -59,7 +48,8 @@ return -EINVAL; } - mtd_sizes[dev] = mtd->size>>9; + set_capacit(disk, mtd->size>>9); + add_disk(disk); DEBUG(1, "ok\n"); @@ -83,6 +73,8 @@ printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); release_return(-ENODEV); } + + del_gendisk(mtd_disks + dev); if (mtd->sync) mtd->sync(mtd); @@ -143,12 +135,10 @@ /* Remove the request we are handling from the request list so nobody messes with it */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) /* Now drop the lock that the ll_rw_blk functions grabbed for us and process the request. This is necessary due to the extreme time we spend processing it. */ spin_unlock_irq(&io_request_lock); -#endif // Handle the request switch (current_request->cmd) @@ -193,9 +183,7 @@ } // Grab the lock and re-thread the item onto the linked list -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) spin_lock_irq(&io_request_lock); -#endif mtdblock_end_request(current_request, res); } } @@ -209,47 +197,25 @@ mtd = __get_mtd_device(NULL, minor(inode->i_rdev)); - if (!mtd) return -EINVAL; - - switch (cmd) { - case BLKGETSIZE: /* Return device size */ - return put_user((mtd->size >> 9), (unsigned long *) arg); - case BLKGETSIZE64: - return put_user((u64)mtd->size, (u64 *)arg); - - case BLKFLSBUF: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - if(!capable(CAP_SYS_ADMIN)) return -EACCES; -#endif - fsync_bdev(inode->i_bdev); - invalidate_bdev(inode->i_bdev, 0); - if (mtd->sync) - mtd->sync(mtd); - return 0; + if (!mtd || cmd != BLKFLSBUF) + return -EINVAL; - default: - return -ENOTTY; - } + if(!capable(CAP_SYS_ADMIN)) + return -EACCES; + fsync_bdev(inode->i_bdev); + invalidate_bdev(inode->i_bdev, 0); + if (mtd->sync) + mtd->sync(mtd); + return 0; } -#if LINUX_VERSION_CODE < 0x20326 -static struct file_operations mtd_fops = -{ - open: mtdblock_open, - ioctl: mtdblock_ioctl, - release: mtdblock_release, - read: block_read, - write: block_write -}; -#else static struct block_device_operations mtd_fops = { - owner: THIS_MODULE, - open: mtdblock_open, - release: mtdblock_release, - ioctl: mtdblock_ioctl + .owner = THIS_MODULE, + .open = mtdblock_open, + .release = mtdblock_release, + .ioctl = mtdblock_ioctl }; -#endif int __init init_mtdblock(void) { @@ -260,16 +226,17 @@ MTD_BLOCK_MAJOR); return -EAGAIN; } - - /* We fill it in at open() time. */ - for (i=0; i< MAX_MTD_DEVICES; i++) { - mtd_sizes[i] = 0; - } - - /* Allow the block size to default to BLOCK_SIZE. */ - blk_size[MAJOR_NR] = mtd_sizes; - + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); + + for (i = 0; i < MAX_MTD_DEVICES; i++) { + struct gendisk *disk = mtd_disks + i; + disk->major = MAJOR_NR; + disk->first_minor = i; + sprintf(names[i], "mtdblock%d", i); + disk->major_name = names[i]; + disk->fops = &mtd_fops; + } return 0; } diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Sat Sep 21 21:25:43 2002 +++ b/drivers/mtd/nftlcore.c Sat Sep 21 21:25:43 2002 @@ -41,8 +41,6 @@ /* NFTL block device stuff */ #define MAJOR_NR NFTL_MAJOR -#define DEVICE_OFF(device) - #include #include @@ -141,10 +139,9 @@ gd->first_minor = firstfree << NFTL_PARTN_BITS; gd->minor_shift = NFTL_PARTN_BITS; gd->major_name = name; + set_capacity(gd, nftl->nr_sects); nftl->disk = gd; - add_gendisk(gd); - register_disk(gd, mk_kdev(MAJOR_NR,firstfree<nr_sects); + add_disk(gd); } static void NFTL_unsetup(int i) diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c --- a/drivers/net/8139cp.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/8139cp.c Sat Sep 21 21:25:45 2002 @@ -22,11 +22,11 @@ Wake-on-LAN support - Felipe Damasio PCI suspend/resume - Felipe Damasio + LinkChg interrupt - Felipe Damasio TODO, in rough priority order: * Test Tx checksumming thoroughly * dev->tx_timeout - * LinkChg interrupt * Support forcing media type with a module parameter, like dl2k.c/sundance.c * Constants (module parms?) for Rx work limit @@ -677,6 +677,8 @@ cp_rx(cp); if (status & (TxOK | TxErr | TxEmpty | SWInt)) cp_tx(cp); + if (status & LinkChg) + mii_check_media(&cp->mii_if, netif_msg_link(cp)); if (status & PciErr) { u16 pci_status; @@ -1192,6 +1194,8 @@ if (rc) goto err_out_hw; + netif_carrier_off(dev); + mii_check_media(&cp->mii_if, netif_msg_link(cp)); netif_start_queue(dev); return 0; @@ -1210,6 +1214,7 @@ printk(KERN_DEBUG "%s: disabling interface\n", dev->name); netif_stop_queue(dev); + netif_carrier_off(dev); spin_lock_irq(&cp->lock); cp_stop_hw(cp); @@ -1649,14 +1654,27 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { struct cp_private *cp = dev->priv; + struct mii_ioctl_data *mii; int rc = 0; + mii = (struct mii_ioctl_data *) &rq->ifr_data; if (!netif_running(dev)) return -EINVAL; + if (cmd != SIOCETHTOOL) + mii->reg_num &= 0x1f; + switch (cmd) { case SIOCETHTOOL: return cp_ethtool_ioctl(cp, (void *) rq->ifr_data); + + case SIOCGMIIPHY: /* Get the address of the PHY in use. */ + mii->phy_id = CP_INTERNAL_PHY; + /* Fall Through */ + + case SIOCGMIIREG: /* Read the specified MII register. */ + mii->val_out = mdio_read (dev, CP_INTERNAL_PHY, mii->reg_num); + break; default: rc = -EOPNOTSUPP; diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile --- a/drivers/net/Makefile Sat Sep 21 21:25:45 2002 +++ b/drivers/net/Makefile Sat Sep 21 21:25:45 2002 @@ -41,7 +41,7 @@ obj-$(CONFIG_VORTEX) += 3c59x.o obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o obj-$(CONFIG_PCNET32) += pcnet32.o mii.o -obj-$(CONFIG_EEPRO100) += eepro100.o +obj-$(CONFIG_EEPRO100) += eepro100.o mii.o obj-$(CONFIG_TLAN) += tlan.o obj-$(CONFIG_EPIC100) += epic100.o mii.o obj-$(CONFIG_SIS900) += sis900.o diff -Nru a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c --- a/drivers/net/irda/actisys.c Sat Sep 21 21:25:48 2002 +++ b/drivers/net/irda/actisys.c Sat Sep 21 21:25:48 2002 @@ -165,7 +165,7 @@ int ret = 0; int i = 0; - IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed, + IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __FUNCTION__, speed, self->speed); /* Go to a known state by reseting the dongle */ diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c --- a/drivers/net/irda/irda-usb.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/irda/irda-usb.c Sat Sep 21 21:25:45 2002 @@ -156,12 +156,12 @@ (!force) && (self->speed != -1)) { /* No speed and xbofs change here * (we'll do it later in the write callback) */ - IRDA_DEBUG(2, __FUNCTION__ "(), not changing speed yet\n"); + IRDA_DEBUG(2, "%s(), not changing speed yet\n", __FUNCTION__); *header = 0; return; } - IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed); + IRDA_DEBUG(2, "%s(), changing speed to %d\n", __FUNCTION__, self->new_speed); self->speed = self->new_speed; /* We will do ` self->new_speed = -1; ' in the completion * handler just in case the current URB fail - Jean II */ @@ -203,7 +203,7 @@ /* Set the negotiated additional XBOFS */ if (self->new_xbofs != -1) { - IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs); + IRDA_DEBUG(2, "%s(), changing xbofs to %d\n", __FUNCTION__, self->new_xbofs); self->xbofs = self->new_xbofs; /* We will do ` self->new_xbofs = -1; ' in the completion * handler just in case the current URB fail - Jean II */ @@ -251,13 +251,13 @@ struct urb *urb; int ret; - IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n", + IRDA_DEBUG(2, "%s(), speed=%d, xbofs=%d\n", __FUNCTION__, self->new_speed, self->new_xbofs); /* Grab the speed URB */ urb = self->speed_urb; if (urb->status != 0) { - WARNING(__FUNCTION__ "(), URB still in use!\n"); + WARNING("%s(), URB still in use!\n", __FUNCTION__); return; } @@ -278,7 +278,7 @@ /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { - WARNING(__FUNCTION__ "(), failed Speed URB\n"); + WARNING("%s(), failed Speed URB\n", __FUNCTION__); } } @@ -291,7 +291,7 @@ { struct irda_usb_cb *self = urb->context; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); /* We should always have a context */ ASSERT(self != NULL, return;); @@ -301,7 +301,7 @@ /* Check for timeout and other USB nasties */ if (urb->status != 0) { /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags); + IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __FUNCTION__, urb->status, urb->transfer_flags); /* Don't do anything here, that might confuse the USB layer. * Instead, we will wait for irda_usb_net_timeout(), the @@ -336,7 +336,7 @@ int res, mtt; int err = 1; /* Failed */ - IRDA_DEBUG(4, __FUNCTION__ "() on %s\n", netdev->name); + IRDA_DEBUG(4, "%s() on %s\n", __FUNCTION__, netdev->name); netif_stop_queue(netdev); @@ -347,7 +347,7 @@ * We need to check self->present under the spinlock because * of irda_usb_disconnect() is synchronous - Jean II */ if (!self->present) { - IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n"); + IRDA_DEBUG(0, "%s(), Device is gone...\n", __FUNCTION__); goto drop; } @@ -381,7 +381,7 @@ } if (urb->status != 0) { - WARNING(__FUNCTION__ "(), URB still in use!\n"); + WARNING("%s(), URB still in use!\n", __FUNCTION__); goto drop; } @@ -390,9 +390,9 @@ * Also, we don't use directly skb_cow(), because it require * headroom >= 16, which force unnecessary copies - Jean II */ if (skb_headroom(skb) < USB_IRDA_HEADER) { - IRDA_DEBUG(0, __FUNCTION__ "(), Insuficient skb headroom.\n"); + IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); if (skb_cow(skb, USB_IRDA_HEADER)) { - WARNING(__FUNCTION__ "(), failed skb_cow() !!!\n"); + WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); goto drop; } } @@ -463,7 +463,7 @@ /* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */ if ((res = usb_submit_urb(urb, GFP_ATOMIC))) { - WARNING(__FUNCTION__ "(), failed Tx URB\n"); + WARNING("%s(), failed Tx URB\n", __FUNCTION__); self->stats.tx_errors++; /* Let USB recover : We will catch that in the watchdog */ /*netif_start_queue(netdev);*/ @@ -495,7 +495,7 @@ struct sk_buff *skb = urb->context; struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); /* We should always have a context */ ASSERT(self != NULL, return;); @@ -509,7 +509,7 @@ /* Check for timeout and other USB nasties */ if (urb->status != 0) { /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags); + IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __FUNCTION__, urb->status, urb->transfer_flags); /* Don't do anything here, that might confuse the USB layer, * and we could go in recursion and blow the kernel stack... @@ -528,7 +528,7 @@ /* If the network is closed, stop everything */ if ((!self->netopen) || (!self->present)) { - IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n"); + IRDA_DEBUG(0, "%s(), Network is gone...\n", __FUNCTION__); spin_unlock_irqrestore(&self->lock, flags); return; } @@ -539,7 +539,7 @@ (self->new_xbofs != self->xbofs)) { /* We haven't changed speed yet (because of * IUC_SPEED_BUG), so do it now - Jean II */ - IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n"); + IRDA_DEBUG(1, "%s(), Changing speed now...\n", __FUNCTION__); irda_usb_change_speed_xbofs(self); } else { /* New speed and xbof is now commited in hardware */ @@ -571,7 +571,7 @@ struct urb *urb; int done = 0; /* If we have made any progress */ - IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n"); + IRDA_DEBUG(0, "%s(), Network layer thinks we timed out!\n", __FUNCTION__); ASSERT(self != NULL, return;); /* Protect us from USB callbacks, net Tx and else. */ @@ -579,7 +579,7 @@ /* self->present *MUST* be read under spinlock */ if (!self->present) { - WARNING(__FUNCTION__ "(), device not present!\n"); + WARNING("%s(), device not present!\n", __FUNCTION__); netif_stop_queue(netdev); spin_unlock_irqrestore(&self->lock, flags); return; @@ -702,11 +702,11 @@ struct irda_skb_cb *cb; int ret; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); /* Check that we have an urb */ if (!urb) { - WARNING(__FUNCTION__ "(), Bug : urb == NULL\n"); + WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__); return; } @@ -716,7 +716,7 @@ if (!skb) { /* If this ever happen, we are in deep s***. * Basically, the Rx path will stop... */ - WARNING(__FUNCTION__ "(), Failed to allocate Rx skb\n"); + WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__); return; } } else { @@ -745,7 +745,7 @@ if (ret) { /* If this ever happen, we are in deep s***. * Basically, the Rx path will stop... */ - WARNING(__FUNCTION__ "(), Failed to submit Rx URB %d\n", ret); + WARNING("%s(), Failed to submit Rx URB %d\n", __FUNCTION__, ret); } } @@ -763,7 +763,7 @@ struct irda_skb_cb *cb; struct sk_buff *new; - IRDA_DEBUG(2, __FUNCTION__ "(), len=%d\n", urb->actual_length); + IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length); /* Find ourselves */ cb = (struct irda_skb_cb *) skb->cb; @@ -773,7 +773,7 @@ /* If the network is closed or the device gone, stop everything */ if ((!self->netopen) || (!self->present)) { - IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone!\n"); + IRDA_DEBUG(0, "%s(), Network is gone!\n", __FUNCTION__); /* Don't re-submit the URB : will stall the Rx path */ return; } @@ -786,13 +786,13 @@ self->stats.rx_crc_errors++; break; case -ECONNRESET: /* -104 */ - IRDA_DEBUG(0, __FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", urb->transfer_flags); + IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags); /* uhci_cleanup_unlink() is going to kill the Rx * URB just after we return. No problem, at this * point the URB will be idle ;-) - Jean II */ break; default: - IRDA_DEBUG(0, __FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", urb->status, urb->transfer_flags); + IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags); break; } goto done; @@ -800,7 +800,7 @@ /* Check for empty frames */ if (urb->actual_length <= USB_IRDA_HEADER) { - WARNING(__FUNCTION__ "(), empty frame!\n"); + WARNING("%s(), empty frame!\n", __FUNCTION__); goto done; } @@ -905,7 +905,7 @@ */ static int irda_usb_net_init(struct net_device *dev) { - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); /* Set up to be a normal IrDA network device driver */ irda_device_setup(dev); @@ -929,7 +929,7 @@ char hwname[16]; int i; - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); ASSERT(netdev != NULL, return -1;); self = (struct irda_usb_cb *) netdev->priv; @@ -937,7 +937,7 @@ /* Can only open the device if it's there */ if(!self->present) { - WARNING(__FUNCTION__ "(), device not present!\n"); + WARNING("%s(), device not present!\n", __FUNCTION__); return -1; } @@ -993,7 +993,7 @@ struct irda_usb_cb *self; int i; - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); ASSERT(netdev != NULL, return -1;); self = (struct irda_usb_cb *) netdev->priv; @@ -1049,7 +1049,7 @@ self = dev->priv; ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ @@ -1107,7 +1107,7 @@ { struct irda_class_desc *desc; - IRDA_DEBUG(3, __FUNCTION__ "()\n"); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); desc = self->irda_desc; @@ -1120,7 +1120,8 @@ self->qos.window_size.bits = desc->bmWindowSize; self->qos.data_size.bits = desc->bmDataSize; - IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); + IRDA_DEBUG(0, "%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", + __FUNCTION__, self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); /* Don't always trust what the dongle tell us */ if(self->capability & IUC_SIR_ONLY) @@ -1164,7 +1165,7 @@ struct net_device *netdev; int err; - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); spin_lock_init(&self->lock); @@ -1184,7 +1185,7 @@ /* Create a network device for us */ if (!(netdev = dev_alloc("irda%d", &err))) { - ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__); return -1; } self->netdev = netdev; @@ -1204,7 +1205,7 @@ err = register_netdevice(netdev); rtnl_unlock(); if (err) { - ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + ERROR("%s(), register_netdev() failed!\n", __FUNCTION__); return -1; } MESSAGE("IrDA: Registered device %s\n", netdev->name); @@ -1219,7 +1220,7 @@ */ static inline int irda_usb_close(struct irda_usb_cb *self) { - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); ASSERT(self != NULL, return -1;); @@ -1301,12 +1302,13 @@ /* This is our interrupt endpoint */ self->bulk_int_ep = ep; } else { - ERROR(__FUNCTION__ "(), Unrecognised endpoint %02X.\n", ep); + ERROR("%s(), Unrecognised endpoint %02X.\n", __FUNCTION__, ep); } } } - IRDA_DEBUG(0, __FUNCTION__ "(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep); + IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", + __FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep); /* Should be 8, 16, 32 or 64 bytes */ ASSERT(self->bulk_out_mtu == 64, ;); @@ -1368,7 +1370,7 @@ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500)); - IRDA_DEBUG(1, __FUNCTION__ "(), ret=%d\n", ret); + IRDA_DEBUG(1, "%s(), ret=%d\n", __FUNCTION__, ret); if (ret < sizeof(*desc)) { WARNING("usb-irda: class_descriptor read %s (%d)\n", (ret<0) ? "failed" : "too short", ret); @@ -1427,7 +1429,7 @@ if((irda->usbdev != NULL) && (irda->present == 0) && (irda->netopen == 0)) { - IRDA_DEBUG(0, __FUNCTION__ "(), found a zombie instance !!!\n"); + IRDA_DEBUG(0, "%s(), found a zombie instance !!!\n", __FUNCTION__); irda_usb_disconnect(irda->usbdev, (void *) irda); } } @@ -1491,10 +1493,10 @@ break; case -EPIPE: /* -EPIPE = -32 */ usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); - IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" ); + IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__); break; default: - IRDA_DEBUG(0, __FUNCTION__ "(), Unknown error %d\n", ret); + IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret); return NULL; break; } @@ -1503,7 +1505,7 @@ interface = &dev->actconfig->interface[ifnum].altsetting[0]; if(!irda_usb_parse_endpoints(self, interface->endpoint, interface->bNumEndpoints)) { - ERROR(__FUNCTION__ "(), Bogus endpoints...\n"); + ERROR("%s(), Bogus endpoints...\n", __FUNCTION__); return NULL; } @@ -1542,7 +1544,7 @@ struct irda_usb_cb *self = (struct irda_usb_cb *) ptr; int i; - IRDA_DEBUG(1, __FUNCTION__ "()\n"); + IRDA_DEBUG(1, "%s()\n", __FUNCTION__); /* Make sure that the Tx path is not executing. - Jean II */ spin_lock_irqsave(&self->lock, flags); @@ -1583,7 +1585,7 @@ usb_free_urb(self->tx_urb); usb_free_urb(self->speed_urb); - IRDA_DEBUG(0, __FUNCTION__ "(), USB IrDA Disconnected\n"); + IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__); } /*------------------------------------------------------------------*/ @@ -1632,7 +1634,7 @@ irda = &irda_instance[i]; /* If the Device is zombie */ if((irda->usbdev != NULL) && (irda->present == 0)) { - IRDA_DEBUG(0, __FUNCTION__ "(), disconnect zombie now !\n"); + IRDA_DEBUG(0, "%s(), disconnect zombie now !\n", __FUNCTION__); irda_usb_disconnect(irda->usbdev, (void *) irda); } } diff -Nru a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c --- a/drivers/net/irda/irtty.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/irda/irtty.c Sat Sep 21 21:25:45 2002 @@ -356,7 +356,7 @@ cflag &= ~CBAUD; - IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to %d\n", speed); + IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed); switch (speed) { case 1200: @@ -406,7 +406,7 @@ __u32 speed = (__u32) task->param; int ret = 0; - IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); + IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies); self = (struct irtty_cb *) task->instance; ASSERT(self != NULL, return -1;); @@ -416,7 +416,7 @@ /* Check if busy */ if (self->task && self->task != task) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); spin_unlock_irqrestore(&self->lock, flags); return MSECS_TO_JIFFIES(10); } else @@ -571,7 +571,7 @@ struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; if (!self || !self->netdev) { - IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n"); + IRDA_DEBUG(0, "%s(), not ready yet!\n", __FUNCTION__); return; } @@ -621,7 +621,7 @@ { struct irtty_cb *self; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); self = (struct irtty_cb *) task->instance; @@ -707,7 +707,7 @@ */ static int irtty_receive_room(struct tty_struct *tty) { - IRDA_DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, "%s()\n", __FUNCTION__); return 65536; /* We can handle an infinite amount of data. :-) */ } @@ -749,7 +749,7 @@ * Now serial buffer is almost free & we can start * transmission of another packet */ - IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n"); + IRDA_DEBUG(5, "%s(), finished with frame!\n", __FUNCTION__); self->stats.tx_packets++; @@ -759,7 +759,7 @@ spin_unlock_irqrestore(&self->lock, flags); if (self->new_speed) { - IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n"); + IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__); irda_task_execute(self, irtty_change_speed, irtty_change_speed_complete, NULL, (void *) self->new_speed); @@ -824,7 +824,7 @@ /* This is probably unsafe, but currently under discussion - Jean II */ if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { - IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n"); + IRDA_DEBUG(2, "%s(), error doing ioctl!\n", __FUNCTION__); } set_fs(fs); @@ -850,7 +850,7 @@ ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]); + IRDA_DEBUG(2, "%s(), mode=%s\n", __FUNCTION__, infrared_mode[mode]); /* Protect access to self->rx_buff - Jean II */ spin_lock_irqsave(&self->lock, flags); @@ -948,7 +948,7 @@ ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRTTY_MAGIC, return -1;); - IRDA_DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, "%s()\n", __FUNCTION__); /* Ready to play! */ netif_start_queue(dev); @@ -1015,7 +1015,7 @@ ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRTTY_MAGIC, return -1;); - IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); /* Locking : * irda_device_dongle_init() can't be locked. diff -Nru a/drivers/net/irda/ma600.c b/drivers/net/irda/ma600.c --- a/drivers/net/irda/ma600.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/irda/ma600.c Sat Sep 21 21:25:45 2002 @@ -48,7 +48,7 @@ #undef IRDA_DEBUG #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args)) - #undef ASSERT(expr, func) + #undef ASSERT #define ASSERT(expr, func) \ if(!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n",\ @@ -86,13 +86,13 @@ int __init ma600_init(void) { - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); return irda_device_register_dongle(&dongle); } void __exit ma600_cleanup(void) { - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); irda_device_unregister_dongle(&dongle); } @@ -105,7 +105,7 @@ */ static void ma600_open(dongle_t *self, struct qos_info *qos) { - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400 |IR_57600|IR_115200; @@ -123,7 +123,7 @@ static void ma600_close(dongle_t *self) { - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); /* Power off dongle */ self->set_dtr_rts(self->dev, FALSE, FALSE); @@ -184,12 +184,12 @@ __u8 byte_echo; int ret = 0; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); ASSERT(task != NULL, return -1;); if (self->speed_task && self->speed_task != task) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); return MSECS_TO_JIFFIES(10); } else { self->speed_task = task; @@ -215,7 +215,7 @@ break; case IRDA_TASK_CHILD_WAIT: - WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); + WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__); ret = -1; break; @@ -246,7 +246,7 @@ if(byte != byte_echo) { /* if control byte != echo, I don't know what to do */ - printk(KERN_WARNING __FUNCTION__ "() control byte written != read!\n"); + printk(KERN_WARNING "%s() control byte written != read!\n", __FUNCTION__); printk(KERN_WARNING "control byte = 0x%c%c\n", hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]); printk(KERN_WARNING "byte echo = 0x%c%c\n", @@ -254,7 +254,7 @@ hexTbl[byte_echo & 0x0f]); #ifndef NDEBUG } else { - IRDA_DEBUG(2, __FUNCTION__ "() control byte write read OK\n"); + IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__); #endif } @@ -273,7 +273,7 @@ break; default: - ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state); irda_task_next_state(task, IRDA_TASK_DONE); self->speed_task = NULL; ret = -1; @@ -298,12 +298,12 @@ dongle_t *self = (dongle_t *) task->instance; int ret = 0; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); ASSERT(task != NULL, return -1;); if (self->reset_task && self->reset_task != task) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__); return MSECS_TO_JIFFIES(10); } else self->reset_task = task; @@ -326,7 +326,7 @@ self->reset_task = NULL; break; default: - ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state); irda_task_next_state(task, IRDA_TASK_DONE); self->reset_task = NULL; ret = -1; diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c --- a/drivers/net/irda/nsc-ircc.c Sat Sep 21 21:25:43 2002 +++ b/drivers/net/irda/nsc-ircc.c Sat Sep 21 21:25:43 2002 @@ -130,7 +130,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev); static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size); static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase); -static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud); +static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud); static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self); static int nsc_ircc_read_dongle_id (int iobase); @@ -921,8 +921,8 @@ break; case 0x0A: /* same as */ case 0x0B: /* Reserved */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", - dongle_types[dongle_id]); + IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n", + __FUNCTION__, dongle_types[dongle_id]); break; case 0x0C: /* same as */ case 0x0D: /* HP HSDL-1100/HSDL-2100 */ @@ -930,14 +930,14 @@ case 0x0E: /* Supports SIR Mode only */ break; case 0x0F: /* No dongle connected */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", - dongle_types[dongle_id]); + IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n", + __FUNCTION__, dongle_types[dongle_id]); switch_bank(iobase, BANK0); outb(0x62, iobase+MCR); break; default: - IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n"); + IRDA_DEBUG(0, "%s(), invalid data_rate\n", __FUNCTION__); } /* Restore bank register */ outb(bank, iobase+BSR); @@ -948,17 +948,19 @@ * * Change the speed of the device * + * This function *must* be called with irq off and spin-lock. */ -static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) +static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) { struct net_device *dev = self->netdev; __u8 mcr = MCR_SIR; int iobase; __u8 bank; + __u8 ier; /* Interrupt enable register */ - IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed); + IRDA_DEBUG(2, "%s(), speed=%d\n", __FUNCTION__, speed); - ASSERT(self != NULL, return;); + ASSERT(self != NULL, return 0;); iobase = self->io.fir_base; @@ -989,20 +991,20 @@ outb(inb(iobase+4) | 0x04, iobase+4); mcr = MCR_MIR; - IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__); break; case 1152000: mcr = MCR_MIR; - IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __FUNCTION__); break; case 4000000: mcr = MCR_FIR; - IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __FUNCTION__); break; default: mcr = MCR_FIR; - IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", - speed); + IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", + __FUNCTION__, speed); break; } @@ -1033,18 +1035,21 @@ if (speed > 115200) { /* Install FIR xmit handler */ dev->hard_start_xmit = nsc_ircc_hard_xmit_fir; - outb(IER_SFIF_IE, iobase+IER); + ier = IER_SFIF_IE; nsc_ircc_dma_receive(self); } else { /* Install SIR xmit handler */ dev->hard_start_xmit = nsc_ircc_hard_xmit_sir; - outb(IER_RXHDL_IE, iobase+IER); + ier = IER_RXHDL_IE; } + /* Set our current interrupt mask */ + outb(ier, iobase+IER); /* Restore BSR */ outb(bank, iobase+BSR); - netif_wake_queue(dev); - + + /* Make sure interrupt handlers keep the proper interrupt mask */ + return(ier); } /* @@ -1069,20 +1074,36 @@ netif_stop_queue(dev); + /* Make sure tests *& speed change are atomic */ + spin_lock_irqsave(&self->lock, flags); + /* Check if we need to change the speed */ speed = irda_get_next_speed(skb); if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ + /* Check for empty frame. */ if (!skb->len) { - nsc_ircc_change_speed(self, speed); + /* If we just sent a frame, we get called before + * the last bytes get out (because of the SIR FIFO). + * If this is the case, let interrupt handler change + * the speed itself... Jean II */ + if (self->io.direction == IO_RECV) { + nsc_ircc_change_speed(self, speed); + /* TODO : For SIR->SIR, the next packet + * may get corrupted - Jean II */ + netif_wake_queue(dev); + } else { + self->new_speed = speed; + /* Queue will be restarted after speed change + * to make sure packets gets through the + * proper xmit handler - Jean II */ + } + spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); return 0; } else self->new_speed = speed; } - spin_lock_irqsave(&self->lock, flags); - /* Save current bank */ bank = inb(iobase+BSR); @@ -1121,20 +1142,38 @@ netif_stop_queue(dev); + /* Make sure tests *& speed change are atomic */ + spin_lock_irqsave(&self->lock, flags); + /* Check if we need to change the speed */ speed = irda_get_next_speed(skb); if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ + /* Check for empty frame. */ if (!skb->len) { - nsc_ircc_change_speed(self, speed); + /* If we are currently transmitting, defer to + * interrupt handler. - Jean II */ + if(self->tx_fifo.len == 0) { + nsc_ircc_change_speed(self, speed); + netif_wake_queue(dev); + } else { + self->new_speed = speed; + /* Keep queue stopped : + * the speed change operation may change the + * xmit handler, and we want to make sure + * the next packet get through the proper + * Tx path, so block the Tx queue until + * the speed change has been done. + * Jean II */ + } + spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); return 0; - } else + } else { + /* Change speed after current frame */ self->new_speed = speed; + } } - spin_lock_irqsave(&self->lock, flags); - /* Save current bank */ bank = inb(iobase+BSR); @@ -1204,8 +1243,9 @@ nsc_ircc_dma_xmit(self, iobase); } out: - /* Not busy transmitting anymore if window is not full */ - if (self->tx_fifo.free < MAX_TX_WINDOW) + /* Not busy transmitting anymore if window is not full, + * and if we don't need to change speed */ + if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) netif_wake_queue(self->netdev); /* Restore bank register */ @@ -1265,15 +1305,15 @@ int actual = 0; __u8 bank; - IRDA_DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, "%s()\n", __FUNCTION__); /* Save current bank */ bank = inb(iobase+BSR); switch_bank(iobase, BANK0); if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { - IRDA_DEBUG(4, __FUNCTION__ - "(), warning, FIFO not empty yet!\n"); + IRDA_DEBUG(4, "%s(), warning, FIFO not empty yet!\n", + __FUNCTION__); /* FIFO may still be filled to the Tx interrupt threshold */ fifo_size -= 17; @@ -1285,8 +1325,8 @@ outb(buf[actual++], iobase+TXD); } - IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); + IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", + __FUNCTION__, fifo_size, actual, len); /* Restore bank */ outb(bank, iobase+BSR); @@ -1307,7 +1347,7 @@ __u8 bank; int ret = TRUE; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); iobase = self->io.fir_base; @@ -1329,12 +1369,6 @@ self->stats.tx_packets++; } - /* Check if we need to change the speed */ - if (self->new_speed) { - nsc_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - } - /* Finished with this frame, so prepare for next */ self->tx_fifo.ptr++; self->tx_fifo.len--; @@ -1351,8 +1385,9 @@ self->tx_fifo.tail = self->tx_buff.head; } - /* Make sure we have room for more frames */ - if (self->tx_fifo.free < MAX_TX_WINDOW) { + /* Make sure we have room for more frames and + * that we don't need to change speed */ + if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) { /* Not busy transmitting anymore */ /* Tell the network layer, that we can accept more frames */ netif_wake_queue(self->netdev); @@ -1443,7 +1478,7 @@ len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8); if (st_fifo->tail >= MAX_RX_WINDOW) { - IRDA_DEBUG(0, __FUNCTION__ "(), window is full!\n"); + IRDA_DEBUG(0, "%s(), window is full!\n", __FUNCTION__); continue; } @@ -1629,24 +1664,25 @@ } /* Check if transmission has completed */ if (eir & EIR_TXEMP_EV) { - /* Check if we need to change the speed? */ + /* Turn around and get ready to receive some data */ + self->io.direction = IO_RECV; + self->ier = IER_RXHDL_IE; + /* Check if we need to change the speed? + * Need to be after self->io.direction to avoid race with + * nsc_ircc_hard_xmit_sir() - Jean II */ if (self->new_speed) { - IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n"); - nsc_ircc_change_speed(self, self->new_speed); + IRDA_DEBUG(2, "%s(), Changing speed!\n", __FUNCTION__); + self->ier = nsc_ircc_change_speed(self, + self->new_speed); self->new_speed = 0; + netif_wake_queue(self->netdev); /* Check if we are going to FIR */ if (self->io.speed > 115200) { - /* Should wait for status FIFO interrupt */ - self->ier = IER_SFIF_IE; - /* No need to do anymore SIR stuff */ return; } } - /* Turn around and get ready to receive some data */ - self->io.direction = IO_RECV; - self->ier = IER_RXHDL_IE; } /* Rx FIFO threshold or timeout */ @@ -1705,19 +1741,37 @@ } } else if (eir & EIR_DMA_EV) { /* Finished with all transmissions? */ - if (nsc_ircc_dma_xmit_complete(self)) { - /* Check if there are more frames to be transmitted */ - if (irda_device_txqueue_empty(self->netdev)) { - /* Prepare for receive */ - nsc_ircc_dma_receive(self); - - self->ier = IER_SFIF_IE; + if (nsc_ircc_dma_xmit_complete(self)) { + if(self->new_speed != 0) { + /* As we stop the Tx queue, the speed change + * need to be done when the Tx fifo is + * empty. Ask for a Tx done interrupt */ + self->ier = IER_TXEMP_IE; + } else { + /* Check if there are more frames to be + * transmitted */ + if (irda_device_txqueue_empty(self->netdev)) { + /* Prepare for receive */ + nsc_ircc_dma_receive(self); + self->ier = IER_SFIF_IE; + } else + WARNING("%s(), potential " + "Tx queue lockup !\n", + __FUNCTION__); } } else { /* Not finished yet, so interrupt on DMA again */ self->ier = IER_DMA_IE; } + } else if (eir & EIR_TXEMP_EV) { + /* The Tx FIFO has totally drained out, so now we can change + * the speed... - Jean II */ + self->ier = nsc_ircc_change_speed(self, self->new_speed); + self->new_speed = 0; + netif_wake_queue(self->netdev); + /* Note : nsc_ircc_change_speed() restarted Rx fifo */ } + outb(bank, iobase+BSR); } @@ -1810,7 +1864,7 @@ */ static int nsc_ircc_net_init(struct net_device *dev) { - IRDA_DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, "%s()\n", __FUNCTION__); /* Setup to be a normal IrDA network device driver */ irda_device_setup(dev); @@ -1833,7 +1887,7 @@ char hwname[32]; __u8 bank; - IRDA_DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = (struct nsc_ircc_cb *) dev->priv; @@ -1897,7 +1951,7 @@ int iobase; __u8 bank; - IRDA_DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); @@ -1953,7 +2007,7 @@ ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c --- a/drivers/net/mii.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/mii.c Sat Sep 21 21:25:45 2002 @@ -170,6 +170,75 @@ return r; } +void mii_check_link (struct mii_if_info *mii) +{ + if (mii_link_ok(mii)) + netif_carrier_on(mii->dev); + else + netif_carrier_off(mii->dev); +} + +unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print) +{ + unsigned int old_carrier, new_carrier; + int advertise, lpa, media, duplex; + + /* if forced media, go no further */ + if (mii->duplex_lock) + return 0; /* duplex did not change */ + + /* check current and old link status */ + old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; + new_carrier = (unsigned int) mii_link_ok(mii); + + /* if carrier state did not change, this is a "bounce", + * just exit as everything is already set correctly + */ + if (old_carrier == new_carrier) + return 0; /* duplex did not change */ + + /* no carrier, nothing much to do */ + if (!new_carrier) { + netif_carrier_off(mii->dev); + if (ok_to_print) + printk(KERN_INFO "%s: link down\n", mii->dev->name); + return 0; /* duplex did not change */ + } + + /* + * we have carrier, see who's on the other end + */ + netif_carrier_on(mii->dev); + + /* get MII advertise and LPA values */ + if (mii->advertising) + advertise = mii->advertising; + else { + advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); + mii->advertising = advertise; + } + lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); + + /* figure out media and duplex from advertise and LPA values */ + media = mii_nway_result(lpa & advertise); + duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0; + + if (ok_to_print) + printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", + mii->dev->name, + media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? + "100" : "10", + duplex ? "full" : "half", + lpa); + + if (mii->full_duplex != duplex) { + mii->full_duplex = duplex; + return 1; /* duplex changed */ + } + + return 0; /* duplex did not change */ +} + MODULE_AUTHOR ("Jeff Garzik "); MODULE_DESCRIPTION ("MII hardware support library"); MODULE_LICENSE("GPL"); @@ -178,3 +247,6 @@ EXPORT_SYMBOL(mii_nway_restart); EXPORT_SYMBOL(mii_ethtool_gset); EXPORT_SYMBOL(mii_ethtool_sset); +EXPORT_SYMBOL(mii_check_link); +EXPORT_SYMBOL(mii_check_media); + diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c --- a/drivers/net/wireless/wavelan_cs.c Sat Sep 21 21:25:45 2002 +++ b/drivers/net/wireless/wavelan_cs.c Sat Sep 21 21:25:45 2002 @@ -56,8 +56,7 @@ * */ -#include -#include +/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */ #include "wavelan_cs.p.h" /* Private header */ /************************* MISC SUBROUTINES **************************/ @@ -2890,8 +2889,8 @@ .private = (iw_handler *) wavelan_private_handler, .private_args = (struct iw_priv_args *) wavelan_private_args, }; +#endif /* WIRELESS_EXT > 12 */ -#else /* WIRELESS_EXT > 12 */ /*------------------------------------------------------------------*/ /* * Perform ioctl : config & info stuff @@ -2916,8 +2915,9 @@ ret = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); break; +#if WIRELESS_EXT <= 12 /* --------------- WIRELESS EXTENSIONS --------------- */ - + /* Now done as iw_handler - Jean II */ case SIOCGIWNAME: wavelan_get_name(dev, NULL, &(wrq->u), NULL); break; @@ -3191,6 +3191,7 @@ } break; #endif /* HISTOGRAM */ +#endif /* WIRELESS_EXT <= 12 */ /* ------------------- OTHER IOCTL ------------------- */ @@ -3203,7 +3204,6 @@ #endif return ret; } -#endif /* WIRELESS_EXT > 12 */ /*------------------------------------------------------------------*/ /* @@ -5199,9 +5199,8 @@ #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ #if WIRELESS_EXT > 12 dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; -#else /* WIRELESS_EXT > 12 */ - dev->do_ioctl = wavelan_ioctl; /* wireless extensions */ #endif /* WIRELESS_EXT > 12 */ + dev->do_ioctl = wavelan_ioctl; /* old wireless extensions */ dev->get_wireless_stats = wavelan_get_wireless_stats; #endif diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h --- a/drivers/net/wireless/wavelan_cs.p.h Sat Sep 21 21:25:45 2002 +++ b/drivers/net/wireless/wavelan_cs.p.h Sat Sep 21 21:25:45 2002 @@ -439,6 +439,7 @@ #include #include #include +#include #ifdef CONFIG_NET_RADIO #include /* Wireless extensions */ diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Sat Sep 21 21:25:47 2002 +++ b/drivers/pci/pci-driver.c Sat Sep 21 21:25:47 2002 @@ -44,7 +44,7 @@ drv = to_pci_driver(dev->driver); pci_dev = to_pci_dev(dev); - if (drv->probe) { + if (!pci_dev->driver && drv->probe) { const struct pci_device_id *id; id = pci_match_device(drv->id_table, pci_dev); diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Sat Sep 21 21:25:48 2002 +++ b/drivers/s390/block/dasd_genhd.c Sat Sep 21 21:25:48 2002 @@ -259,10 +259,8 @@ struct gendisk *disk = dasd_gendisk_by_dev(device->kdev); if (disk == NULL) return; - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, - device->blocks << device->s2b_shift); + set_capacity(disk, device->blocks << device->s2b_shift); + add_disk(disk); } /* diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Sat Sep 21 21:25:48 2002 +++ b/drivers/s390/block/xpram.c Sat Sep 21 21:25:48 2002 @@ -59,6 +59,8 @@ static xpram_device_t xpram_devices[XPRAM_MAX_DEVS]; static int xpram_sizes[XPRAM_MAX_DEVS]; +static struct gendisk xpram_disks[XPRAM_MAX_DEVS]; +static char xpram_names[XPRAM_MAX_DEV][8]; static unsigned long xpram_pages; static int xpram_devs; static devfs_handle_t xpram_devfs_handle; @@ -459,16 +461,24 @@ q = BLK_DEFAULT_QUEUE(XPRAM_MAJOR); blk_queue_make_request(q,xpram_make_request); blk_queue_hardsect_size(q, 4096); - blk_size[XPRAM_MAJOR] = xpram_sizes; /* * Setup device structures. */ offset = 0; for (i = 0; i < xpram_devs; i++) { + struct gendisk *disk = xpram_disks + i; xpram_devices[i].size = xpram_sizes[i] / 4; xpram_devices[i].offset = offset; offset += xpram_devices[i].size; + disk->major = XPRAM_MAJOR; + disk->first_minor = i; + disk->minor_shift = 0; + disk->fops = &xpram_devops; + sprintf(xpram_names[i], "slram%d", i); + disk->major_name = xpram_names[i]; + set_capacity(disk, xpram_sizes[i] << 1); + add_disk(disk); } return 0; @@ -479,6 +489,9 @@ */ static void __exit xpram_exit(void) { + int i; + for (i = 0; i < xpram_devs; i++) + del_gendisk(xpram_disks + i); blk_clear(XPRAM_MAJOR); unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); devfs_unregister(xpram_devfs_handle); diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c --- a/drivers/sbus/char/jsflash.c Sat Sep 21 21:25:45 2002 +++ b/drivers/sbus/char/jsflash.c Sat Sep 21 21:25:45 2002 @@ -36,21 +36,14 @@ #include #include #include +#include /* * is controlled from the outside with these definitions. */ #define MAJOR_NR JSFD_MAJOR -#define DEVICE_REQUEST jsfd_do_request -#define DEVICE_NR(device) (MINOR(device)) -#define DEVICE_ON(device) -#define DEVICE_OFF(device) -#define DEVICE_NO_RANDOM - #include - - #include #include #include @@ -134,8 +127,8 @@ /* */ -static int jsfd_sizes[JSF_MAX]; -static u64 jsfd_bytesizes[JSF_MAX]; +static struct gendisk jsfd_disk[JSF_MAX]; +static char names[JSF_MAX][6]; /* * Let's pretend we may have several of these... @@ -447,28 +440,6 @@ return error; } -static int jsfd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int dev; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!inode) - return -EINVAL; - if ((dev = MINOR(inode->i_rdev)) >= JSF_MAX) return -ENODEV; - - switch (cmd) { - case BLKGETSIZE: - return put_user(jsfd_bytesizes[dev] >> 9, (unsigned long *) arg); - case BLKGETSIZE64: - return put_user(jsfd_bytesizes[dev], (u64 *) arg); - - default: ; - } - return -ENOTTY; -} - static int jsf_mmap(struct file * file, struct vm_area_struct * vma) { return -ENXIO; @@ -549,10 +520,9 @@ .owner = THIS_MODULE, .open = jsfd_open, .release = jsfd_release, - .ioctl = jsfd_ioctl, }; -int jsflash_init(void) +static int jsflash_init(void) { int rc; struct jsflash *jsf; @@ -640,14 +610,15 @@ return 0; } -int jsfd_init(void) { +static int jsfd_init(void) +{ + static spinlock_t lock = SPIN_LOCK_UNLOCKED; struct jsflash *jsf; struct jsfd_part *jdp; int i; - if (jsf0.base == 0) { + if (jsf0.base == 0) return -ENXIO; - } if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) { printk("jsfd_init: unable to get major number %d\n", @@ -655,20 +626,23 @@ return -EIO; } - blk_size[JSFD_MAJOR] = jsfd_sizes; - - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), jsfd_do_request, &lock); for (i = 0; i < JSF_MAX; i++) { + struct gendisk *disk = jsfd_disk + i; if ((i & JSF_PART_MASK) >= JSF_NPART) continue; jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */ jdp = &jsf->dv[i&JSF_PART_MASK]; jdp->refcnt = 0; - jsfd_bytesizes[i] = jdp->dsize; - jsfd_sizes[i] = jsfd_bytesizes[i] >> 10; - register_disk(NULL, MKDEV(JSFD_MAJOR, i), 1, &jsfd_fops, - jsfd_bytesizes[i] >> 9); + disk->major = JSFD_MAJOR; + disk->first_minor = i; + sprintf(names[i], "jsfd%d", i); + disk->major_name = names[i]; + disk->fops = &jsfd_fops; + disk->minor_shift = 0; + set_capacity(disk, jdp->dsize >> 9); + add_disk(disk); set_device_ro(MKDEV(JSFD_MAJOR, i), 1); } return 0; @@ -686,9 +660,14 @@ return rc; } -static void __exit jsflash_cleanup_module(void) { +static void __exit jsflash_cleanup_module(void) +{ + int i; - /* for (all probed units) { } */ + for (i = 0; i < JSF_MAX; i++) { + if ((i & JSF_PART_MASK) >= JSF_NPART) continue; + del_gendisk(jsfd_disk + i); + } if (jsf0.busy) printk("jsf0: cleaning busy unit\n"); jsf0.base = 0; diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Sat Sep 21 21:25:45 2002 +++ b/drivers/scsi/sd.c Sat Sep 21 21:25:45 2002 @@ -1250,10 +1250,8 @@ if (sdkp && (0 == sdkp->capacity) && sdkp->device) { sd_init_onedisk(sdkp, k); if (!sdkp->has_been_registered) { - add_gendisk(sd_disks[k]); - register_disk(sd_disks[k], MKDEV_SD(k), - 1<<4, &sd_fops, - sdkp->capacity); + set_capacity(sd_disks[k], sdkp->capacity); + add_disk(sd_disks[k]); sdkp->has_been_registered = 1; } } diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Sat Sep 21 21:25:45 2002 +++ b/drivers/scsi/sr.c Sat Sep 21 21:25:45 2002 @@ -762,6 +762,7 @@ disk->minor_shift = 0; disk->major_name = cd->cdi.name; disk->fops = &sr_bdops; + disk->flags = GENHD_FL_CD; cd->disk = disk; cd->capacity = 0x1fffff; cd->device->sector_size = 2048;/* A guess, just in case */ @@ -805,14 +806,10 @@ &dev_attr_type); device_create_file(&cd->cdi.cdrom_driverfs_dev, &dev_attr_kdev); - cd->cdi.de = devfs_register(cd->device->de, "cd", - DEVFS_FL_DEFAULT, MAJOR_NR, i, - S_IFBLK | S_IRUGO | S_IWUGO, - &sr_bdops, NULL); + disk->de = cd->device->de; register_cdrom(&cd->cdi); - add_gendisk(disk); - register_disk(disk, mk_kdev(disk->major, disk->first_minor), - 1<minor_shift, disk->fops, cd->capacity); + set_capacity(disk, cd->capacity); + add_disk(disk); } } diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c --- a/drivers/scsi/sr_ioctl.c Sat Sep 21 21:25:46 2002 +++ b/drivers/scsi/sr_ioctl.c Sat Sep 21 21:25:46 2002 @@ -545,16 +545,7 @@ unsigned int cmd, unsigned long arg) { Scsi_CD *cd = cdi->handle; - - switch (cmd) { - case BLKGETSIZE: - return put_user(cd->capacity, (unsigned long *) arg); - case BLKGETSIZE64: - return put_user((u64)cd->capacity << 9, (u64 *)arg); - - default: - return scsi_ioctl(cd->device, cmd, (void *)arg); - } + return scsi_ioctl(cd->device, cmd, (void *)arg); } /* diff -Nru a/fs/block_dev.c b/fs/block_dev.c --- a/fs/block_dev.c Sat Sep 21 21:25:48 2002 +++ b/fs/block_dev.c Sat Sep 21 21:25:48 2002 @@ -843,6 +843,9 @@ case BLKPG: ret = blk_ioctl(bdev, cmd, arg); break; + case BLKRRPART: + ret = blkdev_reread_part(bdev); + break; default: if (bdev->bd_op->ioctl) ret =bdev->bd_op->ioctl(inode, file, cmd, arg); @@ -854,8 +857,6 @@ case BLKROSET: ret = blk_ioctl(bdev,cmd,arg); break; - case BLKRRPART: - ret = blkdev_reread_part(bdev); } } } diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c --- a/fs/jfs/file.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/file.c Sat Sep 21 21:25:45 2002 @@ -19,6 +19,7 @@ #include #include "jfs_incore.h" +#include "jfs_dmap.h" #include "jfs_txnmgr.h" #include "jfs_xattr.h" #include "jfs_debug.h" @@ -94,6 +95,47 @@ IWRITE_UNLOCK(ip); } +static int jfs_open(struct inode *inode, struct file *file) +{ + int rc; + + if ((rc = generic_file_open(inode, file))) + return rc; + + /* + * We attempt to allow only one "active" file open per aggregate + * group. Otherwise, appending to files in parallel can cause + * fragmentation within the files. + * + * If the file is empty, it was probably just created and going + * to be written to. If it has a size, we'll hold off until the + * file is actually grown. + */ + if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE && + (inode->i_size == 0)) { + struct jfs_inode_info *ji = JFS_IP(inode); + if (ji->active_ag == -1) { + ji->active_ag = ji->agno; + atomic_inc( + &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]); + } + } + + return 0; +} +static int jfs_release(struct inode *inode, struct file *file) +{ + struct jfs_inode_info *ji = JFS_IP(inode); + + if (ji->active_ag != -1) { + struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; + atomic_dec(&bmap->db_active[ji->active_ag]); + ji->active_ag = -1; + } + + return 0; +} + struct inode_operations jfs_file_inode_operations = { .truncate = jfs_truncate, .setxattr = jfs_setxattr, @@ -103,7 +145,7 @@ }; struct file_operations jfs_file_operations = { - .open = generic_file_open, + .open = jfs_open, .llseek = generic_file_llseek, .write = generic_file_write, .read = generic_file_read, @@ -112,4 +154,5 @@ .writev = generic_file_writev, .sendfile = generic_file_sendfile, .fsync = jfs_fsync, + .release = jfs_release, }; diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c --- a/fs/jfs/jfs_dmap.c Sat Sep 21 21:25:48 2002 +++ b/fs/jfs/jfs_dmap.c Sat Sep 21 21:25:48 2002 @@ -241,6 +241,7 @@ bmp->db_ipbmap = ipbmap; JFS_SBI(ipbmap->i_sb)->bmap = bmp; + memset(bmp->db_active, 0, sizeof(bmp->db_active)); DBINITMAP(bmp->db_mapsize, ipbmap, &bmp->db_DBmap); /* @@ -271,6 +272,7 @@ int dbUnmount(struct inode *ipbmap, int mounterror) { struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap; + int i; if (!(mounterror || isReadOnly(ipbmap))) dbSync(ipbmap); @@ -280,6 +282,14 @@ */ truncate_inode_pages(ipbmap->i_mapping, 0); + /* + * Sanity Check + */ + for (i = 0; i < bmp->db_numag; i++) + if (atomic_read(&bmp->db_active[i])) + printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n", + i, atomic_read(&bmp->db_active[i])); + /* free the memory for the in-memory bmap. */ kfree(bmp); @@ -598,102 +608,77 @@ * * FUNCTION: find the preferred allocation group for new allocations. * - * we try to keep the trailing (rightmost) allocation groups - * free for large allocations. we try to do this by targeting - * new inode allocations towards the leftmost or 'active' - * allocation groups while keeping the rightmost or 'inactive' - * allocation groups free. once the active allocation groups - * have dropped to a certain percentage of free space, we add - * the leftmost inactive allocation group to the active set. - * - * within the active allocation groups, we maintain a preferred + * Within the allocation groups, we maintain a preferred * allocation group which consists of a group with at least - * average free space over the active set. it is the preferred - * group that we target new inode allocation towards. the - * tie-in between inode allocation and block allocation occurs - * as we allocate the first (data) block of an inode and specify - * the inode (block) as the allocation hint for this block. + * average free space. It is the preferred group that we target + * new inode allocation towards. The tie-in between inode + * allocation and block allocation occurs as we allocate the + * first (data) block of an inode and specify the inode (block) + * as the allocation hint for this block. + * + * We try to avoid having more than one open file growing in + * an allocation group, as this will lead to fragmentation. + * This differs from the old OS/2 method of trying to keep + * empty ags around for large allocations. * * PARAMETERS: * ipbmap - pointer to in-core inode for the block map. * * RETURN VALUES: * the preferred allocation group number. - * - * note: only called by dbAlloc(); */ int dbNextAG(struct inode *ipbmap) { - s64 avgfree, inactfree, actfree, rem; - int actags, inactags, l2agsize; + s64 avgfree; + int agpref; + s64 hwm = 0; + int i; + int next_best = -1; struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap; BMAP_LOCK(bmp); - /* determine the number of active allocation groups (i.e. - * the number of allocation groups up to and including - * the rightmost allocation group with blocks allocated - * in it. - */ - actags = bmp->db_maxag + 1; - assert(actags <= bmp->db_numag); - - /* get the number of inactive allocation groups (i.e. the - * number of allocation group following the rightmost group - * with allocation in it. - */ - inactags = bmp->db_numag - actags; - - /* determine how many blocks are in the inactive allocation - * groups. in doing this, we must account for the fact that - * the rightmost group might be a partial group (i.e. file - * system size is not a multiple of the group size). - */ - l2agsize = bmp->db_agl2size; - rem = bmp->db_mapsize & (bmp->db_agsize - 1); - inactfree = (inactags - && rem) ? ((inactags - 1) << l2agsize) + - rem : inactags << l2agsize; - - /* now determine how many free blocks are in the active - * allocation groups plus the average number of free blocks - * within the active ags. - */ - actfree = bmp->db_nfree - inactfree; - avgfree = (u32) actfree / (u32) actags; - - /* check if not all of the allocation groups are active. - */ - if (actags < bmp->db_numag) { - /* not all of the allocation groups are active. determine - * if we should extend the active set by 1 (i.e. add the - * group following the current active set). we do so if - * the number of free blocks within the active set is less - * than the allocation group set and average free within - * the active set is less than 60%. we activate a new group - * by setting the allocation group preference to the new - * group. - */ - if (actfree < bmp->db_agsize && - ((avgfree * 100) >> l2agsize) < 60) - bmp->db_agpref = actags; - } else { - /* all allocation groups are in the active set. check if - * the preferred allocation group has average free space. - * if not, re-establish the preferred group as the leftmost - * group with average free space. - */ - if (bmp->db_agfree[bmp->db_agpref] < avgfree) { - for (bmp->db_agpref = 0; bmp->db_agpref < actags; - bmp->db_agpref++) { - if (bmp->db_agfree[bmp->db_agpref] <= - avgfree) - break; - } - assert(bmp->db_agpref < bmp->db_numag); + /* determine the average number of free blocks within the ags. */ + avgfree = (u32)bmp->db_nfree / bmp->db_numag; + + /* + * if the current preferred ag does not have an active allocator + * and has at least average freespace, return it + */ + agpref = bmp->db_agpref; + if ((atomic_read(&bmp->db_active[agpref]) == 0) && + (bmp->db_agfree[agpref] >= avgfree)) + goto found; + + /* From the last preferred ag, find the next one with at least + * average free space. + */ + for (i = 0 ; i < bmp->db_numag; i++, agpref++) { + if (agpref == bmp->db_numag) + agpref = 0; + + if (atomic_read(&bmp->db_active[agpref])) + /* open file is currently growing in this ag */ + continue; + if (bmp->db_agfree[agpref] >= avgfree) + goto found; + else if (bmp->db_agfree[agpref] > hwm) { + hwm = bmp->db_agfree[agpref]; + next_best = agpref; } } + /* + * If no inactive ag was found with average freespace, use the + * next best + */ + if (next_best != -1) + agpref = next_best; + + /* else agpref should be back to its original value */ + +found: + bmp->db_agpref = agpref; BMAP_UNLOCK(bmp); /* return the preferred group. @@ -701,7 +686,6 @@ return (bmp->db_agpref); } - /* * NAME: dbAlloc() * @@ -750,6 +734,7 @@ struct dmap *dp; int l2nb; s64 mapSize; + int writers; /* assert that nblocks is valid */ assert(nblocks > 0); @@ -774,11 +759,10 @@ /* the hint should be within the map */ assert(hint < mapSize); - /* if no hint was specified or the number of blocks to be - * allocated is greater than the allocation group size, try - * to allocate anywhere. + /* if the number of blocks to be allocated is greater than the + * allocation group size, try to allocate anywhere. */ - if (hint == 0 || l2nb > bmp->db_agl2size) { + if (l2nb > bmp->db_agl2size) { IWRITE_LOCK(ipbmap); rc = dbAllocAny(bmp, nblocks, l2nb, results); @@ -790,39 +774,34 @@ goto write_unlock; } + /* + * If no hint, let dbNextAG recommend an allocation group + */ + if (hint == 0) + goto pref_ag; + /* we would like to allocate close to the hint. adjust the * hint to the block following the hint since the allocators * will start looking for free space starting at this point. - * if the hint was the last block of the file system, try to - * allocate in the same allocation group as the hint. */ blkno = hint + 1; - if (blkno >= bmp->db_mapsize) { - blkno--; - goto tryag; - } + + if (blkno >= bmp->db_mapsize) + goto pref_ag; + + agno = blkno >> bmp->db_agl2size; /* check if blkno crosses over into a new allocation group. * if so, check if we should allow allocations within this - * allocation group. we try to keep the trailing (rightmost) - * allocation groups of the file system free for large - * allocations and may want to prevent this allocation from - * spilling over into this space. - */ - if ((blkno & (bmp->db_agsize - 1)) == 0) { - /* check if the AG is beyond the rightmost AG with - * allocations in it. if so, call dbNextAG() to - * determine if the allocation should be allowed - * to proceed within this AG or should be targeted - * to another AG. - */ - agno = blkno >> bmp->db_agl2size; - if (agno > bmp->db_maxag) { - agno = dbNextAG(ipbmap); - blkno = (s64) agno << bmp->db_agl2size; - goto tryag; - } - } + * allocation group. + */ + if ((blkno & (bmp->db_agsize - 1)) == 0) + /* check if the AG is currenly being written to. + * if so, call dbNextAG() to find a non-busy + * AG with sufficient free space. + */ + if (atomic_read(&bmp->db_active[agno])) + goto pref_ag; /* check if the allocation request size can be satisfied from a * single dmap. if so, try to allocate from the dmap containing @@ -844,9 +823,8 @@ /* first, try to satisfy the allocation request with the * blocks beginning at the hint. */ - if ((rc = - dbAllocNext(bmp, dp, blkno, - (int) nblocks)) != ENOSPC) { + if ((rc = dbAllocNext(bmp, dp, blkno, (int) nblocks)) + != ENOSPC) { if (rc == 0) { *results = blkno; DBALLOC(bmp->db_DBmap, bmp->db_mapsize, @@ -858,12 +836,23 @@ goto read_unlock; } + writers = atomic_read(&bmp->db_active[agno]); + if ((writers > 1) || + ((writers == 1) && (JFS_IP(ip)->active_ag != agno))) { + /* + * Someone else is writing in this allocation + * group. To avoid fragmenting, try another ag + */ + release_metapage(mp); + IREAD_UNLOCK(ipbmap); + goto pref_ag; + } + /* next, try to satisfy the allocation request with blocks * near the hint. */ if ((rc = - dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, - results)) + dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, results)) != ENOSPC) { if (rc == 0) { DBALLOC(bmp->db_DBmap, bmp->db_mapsize, @@ -876,10 +865,9 @@ } /* try to satisfy the allocation request with blocks within - * the same allocation group as the hint. + * the same dmap as the hint. */ - if ((rc = - dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results)) + if ((rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results)) != ENOSPC) { if (rc == 0) { DBALLOC(bmp->db_DBmap, bmp->db_mapsize, @@ -895,14 +883,30 @@ IREAD_UNLOCK(ipbmap); } - tryag: + /* try to satisfy the allocation request with blocks within + * the same allocation group as the hint. + */ + IWRITE_LOCK(ipbmap); + if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) + != ENOSPC) { + if (rc == 0) + DBALLOC(bmp->db_DBmap, bmp->db_mapsize, + *results, nblocks); + goto write_unlock; + } + IWRITE_UNLOCK(ipbmap); + + + pref_ag: + /* + * Let dbNextAG recommend a preferred allocation group + */ + agno = dbNextAG(ipbmap); IWRITE_LOCK(ipbmap); - /* determine the allocation group number of the hint and try to - * allocate within this allocation group. if that fails, try to + /* Try to allocate within this allocation group. if that fails, try to * allocate anywhere in the map. */ - agno = blkno >> bmp->db_agl2size; if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) == ENOSPC) rc = dbAllocAny(bmp, nblocks, l2nb, results); if (rc == 0) { @@ -2314,11 +2318,9 @@ * if so, establish the new maximum allocation group number by * searching left for the first allocation group with allocation. */ - if ((bmp->db_agfree[agno] == bmp->db_agsize - && agno == bmp->db_maxag) || (agno == bmp->db_numag - 1 - && bmp->db_agfree[agno] == - (bmp-> db_mapsize & - (BPERDMAP - 1)))) { + if ((bmp->db_agfree[agno] == bmp->db_agsize && agno == bmp->db_maxag) || + (agno == bmp->db_numag - 1 && + bmp->db_agfree[agno] == (bmp-> db_mapsize & (BPERDMAP - 1)))) { while (bmp->db_maxag > 0) { bmp->db_maxag -= 1; if (bmp->db_agfree[bmp->db_maxag] != diff -Nru a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h --- a/fs/jfs/jfs_dmap.h Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_dmap.h Sat Sep 21 21:25:45 2002 @@ -227,6 +227,7 @@ struct dbmap db_bmap; /* on-disk aggregate map descriptor */ struct inode *db_ipbmap; /* ptr to aggregate map incore inode */ struct semaphore db_bmaplock; /* aggregate map lock */ + atomic_t db_active[MAXAG]; /* count of active, open files in AG */ u32 *db_DBmap; }; diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c --- a/fs/jfs/jfs_extent.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_extent.c Sat Sep 21 21:25:45 2002 @@ -514,9 +514,12 @@ static int extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) { + struct jfs_inode_info *ji = JFS_IP(ip); + struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); s64 nb, nblks, daddr, max; - int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage; - struct bmap *mp = JFS_SBI(ip->i_sb)->bmap; + int rc, nbperpage = sbi->nbperpage; + struct bmap *bmp = sbi->bmap; + int ag; /* get the number of blocks to initially attempt to allocate. * we'll first try the number of blocks requested unless this @@ -524,7 +527,7 @@ * blocks in the map. in that case, we'll start off with the * maximum free. */ - max = (s64) 1 << mp->db_maxfreebud; + max = (s64) 1 << bmp->db_maxfreebud; if (*nblocks >= max && *nblocks > nbperpage) nb = nblks = (max > nbperpage) ? max : nbperpage; else @@ -548,6 +551,18 @@ *nblocks = nb; *blkno = daddr; + + if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) { + ag = BLKTOAG(daddr, sbi); + if (ji->active_ag == -1) { + atomic_inc(&bmp->db_active[ag]); + ji->active_ag = ag; + } else if (ji->active_ag != ag) { + atomic_dec(&bmp->db_active[ji->active_ag]); + atomic_inc(&bmp->db_active[ag]); + ji->active_ag = ag; + } + } return (0); } diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c --- a/fs/jfs/jfs_imap.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_imap.c Sat Sep 21 21:25:45 2002 @@ -429,6 +429,7 @@ /* set the ag for the inode */ JFS_IP(ip)->agno = BLKTOAG(agstart, sbi); + JFS_IP(ip)->active_ag = -1; return (rc); } @@ -1358,6 +1359,7 @@ DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino); jfs_ip->ixpxd = iagp->inoext[extno]; jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); + jfs_ip->active_ag = -1; } @@ -1413,15 +1415,27 @@ * moving backward on the disk.) compute the hint within the * file system and the iag. */ + + /* get the ag number of this iag */ + agno = JFS_IP(pip)->agno; + + if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { + /* + * There is an open file actively growing. We want to + * allocate new inodes from a different ag to avoid + * fragmentation problems. + */ + agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap); + AG_LOCK(imap, agno); + goto tryag; + } + inum = pip->i_ino + 1; ino = inum & (INOSPERIAG - 1); /* back off the the hint if it is outside of the iag */ if (ino == 0) inum = pip->i_ino; - - /* get the ag number of this iag */ - agno = JFS_IP(pip)->agno; /* lock the AG inode map information */ AG_LOCK(imap, agno); diff -Nru a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h --- a/fs/jfs/jfs_incore.h Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_incore.h Sat Sep 21 21:25:45 2002 @@ -49,7 +49,7 @@ long cflag; /* commit flags */ u16 bxflag; /* xflag of pseudo buffer? */ unchar agno; /* ag number */ - unchar pad; /* pad */ + signed char active_ag; /* ag currently allocating from */ lid_t blid; /* lid of pseudo buffer? */ lid_t atlhead; /* anonymous tlock list head */ lid_t atltail; /* anonymous tlock list tail */ diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c --- a/fs/jfs/jfs_logmgr.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_logmgr.c Sat Sep 21 21:25:45 2002 @@ -66,6 +66,7 @@ #include #include /* for sync_blockdev() */ #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" #include "jfs_metapage.h" @@ -2146,12 +2147,17 @@ lbmStartIO(bp); spin_lock_irq(&log_redrive_lock); } - add_wait_queue(&jfs_IO_thread_wait, &wq); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&log_redrive_lock); - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&jfs_IO_thread_wait, &wq); + if (current->flags & PF_FREEZE) { + spin_unlock_irq(&log_redrive_lock); + refrigerator(PF_IOTHREAD); + } else { + add_wait_queue(&jfs_IO_thread_wait, &wq); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&log_redrive_lock); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&jfs_IO_thread_wait, &wq); + } } while (!jfs_stop_threads); jFYI(1,("jfsIOWait being killed!\n")); diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c --- a/fs/jfs/jfs_txnmgr.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/jfs_txnmgr.c Sat Sep 21 21:25:46 2002 @@ -47,6 +47,7 @@ #include #include #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" #include "jfs_metapage.h" @@ -2789,8 +2790,6 @@ complete(&jfsIOwait); do { - DECLARE_WAITQUEUE(wq, current); - LAZY_LOCK(flags); restart: WorkDone = 0; @@ -2825,12 +2824,19 @@ if (WorkDone) goto restart; - add_wait_queue(&jfs_commit_thread_wait, &wq); - set_current_state(TASK_INTERRUPTIBLE); - LAZY_UNLOCK(flags); - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&jfs_commit_thread_wait, &wq); + if (current->flags & PF_FREEZE) { + LAZY_UNLOCK(flags); + refrigerator(PF_IOTHREAD); + } else { + DECLARE_WAITQUEUE(wq, current); + + add_wait_queue(&jfs_commit_thread_wait, &wq); + set_current_state(TASK_INTERRUPTIBLE); + LAZY_UNLOCK(flags); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&jfs_commit_thread_wait, &wq); + } } while (!jfs_stop_threads); if (TxAnchor.unlock_queue) @@ -2981,7 +2987,6 @@ complete(&jfsIOwait); do { - DECLARE_WAITQUEUE(wq, current); /* * write each inode on the anonymous inode list */ @@ -3030,12 +3035,20 @@ } /* Add anon_list2 back to anon_list */ list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list); - add_wait_queue(&jfs_sync_thread_wait, &wq); - set_current_state(TASK_INTERRUPTIBLE); - TXN_UNLOCK(); - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&jfs_sync_thread_wait, &wq); + + if (current->flags & PF_FREEZE) { + TXN_UNLOCK(); + refrigerator(PF_IOTHREAD); + } else { + DECLARE_WAITQUEUE(wq, current); + + add_wait_queue(&jfs_sync_thread_wait, &wq); + set_current_state(TASK_INTERRUPTIBLE); + TXN_UNLOCK(); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&jfs_sync_thread_wait, &wq); + } } while (!jfs_stop_threads); jFYI(1, ("jfs_sync being killed\n")); diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c --- a/fs/jfs/super.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/super.c Sat Sep 21 21:25:45 2002 @@ -406,6 +406,7 @@ init_rwsem(&jfs_ip->rdwrlock); init_MUTEX(&jfs_ip->commit_sem); jfs_ip->atlhead = 0; + jfs_ip->active_ag = -1; inode_init_once(&jfs_ip->vfs_inode); } } diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c --- a/fs/jfs/xattr.c Sat Sep 21 21:25:45 2002 +++ b/fs/jfs/xattr.c Sat Sep 21 21:25:45 2002 @@ -78,6 +78,68 @@ #define EA_NEW 0x0004 #define EA_MALLOC 0x0008 +/* Namespaces */ +#define XATTR_SYSTEM_PREFIX "system." +#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) + +#define XATTR_USER_PREFIX "user." +#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) + +#define XATTR_OS2_PREFIX "os2." +#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) + +/* + * These three routines are used to recognize on-disk extended attributes + * that are in a recognized namespace. If the attribute is not recognized, + * "os2." is prepended to the name + */ +static inline int is_os2_xattr(struct jfs_ea *ea) +{ + /* + * Check for "system." + */ + if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) && + !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return FALSE; + /* + * Check for "user." + */ + if ((ea->namelen >= XATTR_USER_PREFIX_LEN) && + !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) + return FALSE; + /* + * Add any other valid namespace prefixes here + */ + + /* + * We assume it's OS/2's flat namespace + */ + return TRUE; +} + +static inline int name_size(struct jfs_ea *ea) +{ + if (is_os2_xattr(ea)) + return ea->namelen + XATTR_OS2_PREFIX_LEN; + else + return ea->namelen; +} + +static inline int copy_name(char *buffer, struct jfs_ea *ea) +{ + int len = ea->namelen; + + if (is_os2_xattr(ea)) { + memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN); + buffer += XATTR_OS2_PREFIX_LEN; + len += XATTR_OS2_PREFIX_LEN; + } + memcpy(buffer, ea->name, ea->namelen); + buffer[ea->namelen] = 0; + + return len; +} + /* Forward references */ static void ea_release(struct inode *inode, struct ea_buffer *ea_buf); @@ -577,7 +639,8 @@ return rc; } -static int can_set_xattr(struct inode *inode, const char *name) +static int can_set_xattr(struct inode *inode, const char *name, + void *value, size_t value_len) { if (IS_RDONLY(inode)) return -EROFS; @@ -585,6 +648,10 @@ if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode)) return -EPERM; + if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) && + (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0)) + return -EOPNOTSUPP; + if (!S_ISREG(inode->i_mode) && (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX)) return -EPERM; @@ -602,13 +669,24 @@ int xattr_size; int new_size; int namelen = strlen(name); + char *os2name = NULL; int found = 0; int rc; int length; - if ((rc = can_set_xattr(inode, name))) + if ((rc = can_set_xattr(inode, name, value, value_len))) return rc; + if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { + os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, + GFP_KERNEL); + if (!os2name) + return -ENOMEM; + strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); + name = os2name; + namelen -= XATTR_OS2_PREFIX_LEN; + } + xattr_size = ea_get(inode, &ea_buf, 0); if (xattr_size < 0) { rc = xattr_size; @@ -714,6 +792,9 @@ release: ea_release(inode, &ea_buf); out: + if (os2name) + kfree(os2name); + return rc; } @@ -728,7 +809,7 @@ return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags); } -static int can_get_xattr(struct inode *inode, const char *name) +static inline int can_get_xattr(struct inode *inode, const char *name) { return permission(inode, MAY_READ); } @@ -742,12 +823,23 @@ int xattr_size; ssize_t size; int namelen = strlen(name); + char *os2name = NULL; int rc; char *value; if ((rc = can_get_xattr(inode, name))) return rc; + if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { + os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, + GFP_KERNEL); + if (!os2name) + return -ENOMEM; + strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); + name = os2name; + namelen -= XATTR_OS2_PREFIX_LEN; + } + xattr_size = ea_get(inode, &ea_buf, 0); if (xattr_size < 0) { size = xattr_size; @@ -780,6 +872,8 @@ release: ea_release(inode, &ea_buf); out: + if (os2name) + kfree(os2name); return size; } @@ -813,7 +907,7 @@ /* compute required size of list */ for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) - size += ea->namelen + 1; + size += name_size(ea) + 1; if (!data) goto release; @@ -826,9 +920,8 @@ /* Copy attribute names to buffer */ buffer = data; for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { - memcpy(buffer, ea->name, ea->namelen); - buffer[ea->namelen] = 0; - buffer += ea->namelen + 1; + int namelen = copy_name(buffer, ea); + buffer += namelen + 1; } release: diff -Nru a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile --- a/fs/ncpfs/Makefile Sat Sep 21 21:25:48 2002 +++ b/fs/ncpfs/Makefile Sat Sep 21 21:25:48 2002 @@ -5,7 +5,7 @@ obj-$(CONFIG_NCP_FS) += ncpfs.o ncpfs-objs := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ - ncpsign_kernel.o + ncpsign_kernel.o getopt.o ifeq ($(CONFIG_NCPFS_EXTRAS),y) ncpfs-objs += symlink.o endif diff -Nru a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ncpfs/getopt.c Sat Sep 21 21:25:48 2002 @@ -0,0 +1,75 @@ +/* + * getopt.c + */ + +#include +#include + +#include + +#include "getopt.h" + +/** + * ncp_getopt - option parser + * @caller: name of the caller, for error messages + * @options: the options string + * @opts: an array of &struct option entries controlling parser operations + * @optopt: output; will contain the current option + * @optarg: output; will contain the value (if one exists) + * @flag: output; may be NULL; should point to a long for or'ing flags + * @value: output; may be NULL; will be overwritten with the integer value + * of the current argument. + * + * Helper to parse options on the format used by mount ("a=b,c=d,e,f"). + * Returns opts->val if a matching entry in the 'opts' array is found, + * 0 when no more tokens are found, -1 if an error is encountered. + */ +int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value) +{ + char *token; + char *val; + + do { + if ((token = strsep(options, ",")) == NULL) + return 0; + } while (*token == '\0'); + if (optopt) + *optopt = token; + + if ((val = strchr (token, '=')) != NULL) { + *val++ = 0; + } + *optarg = val; + for (; opts->name; opts++) { + if (!strcmp(opts->name, token)) { + if (!val) { + if (opts->has_arg & OPT_NOPARAM) { + return opts->val; + } + printk(KERN_INFO "%s: the %s option requires an argument\n", + caller, token); + return -EINVAL; + } + if (opts->has_arg & OPT_INT) { + char* v; + + *value = simple_strtoul(val, &v, 0); + if (!*v) { + return opts->val; + } + printk(KERN_INFO "%s: invalid numeric value in %s=%s\n", + caller, token, val); + return -EDOM; + } + if (opts->has_arg & OPT_STRING) { + return opts->val; + } + printk(KERN_INFO "%s: unexpected argument %s to the %s option\n", + caller, val, token); + return -EINVAL; + } + } + printk(KERN_INFO "%s: Unrecognized mount option %s\n", caller, token); + return -EOPNOTSUPP; +} diff -Nru a/fs/ncpfs/getopt.h b/fs/ncpfs/getopt.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ncpfs/getopt.h Sat Sep 21 21:25:48 2002 @@ -0,0 +1,16 @@ +#ifndef _LINUX_GETOPT_H +#define _LINUX_GETOPT_H + +#define OPT_NOPARAM 1 +#define OPT_INT 2 +#define OPT_STRING 4 +struct ncp_option { + const char *name; + unsigned int has_arg; + int val; +}; + +extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value); + +#endif /* _LINUX_GETOPT_H */ diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c --- a/fs/ncpfs/inode.c Sat Sep 21 21:25:45 2002 +++ b/fs/ncpfs/inode.c Sat Sep 21 21:25:45 2002 @@ -31,7 +31,10 @@ #include +#include + #include "ncplib_kernel.h" +#include "getopt.h" static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); @@ -283,6 +286,103 @@ clear_inode(inode); } +static void ncp_stop_tasks(struct ncp_server *server) { + struct sock* sk = server->ncp_sock->sk; + + sk->error_report = server->error_report; + sk->data_ready = server->data_ready; + sk->write_space = server->write_space; + del_timer_sync(&server->timeout_tm); + flush_scheduled_tasks(); +} + +static const struct ncp_option ncp_opts[] = { + { "uid", OPT_INT, 'u' }, + { "gid", OPT_INT, 'g' }, + { "owner", OPT_INT, 'o' }, + { "mode", OPT_INT, 'm' }, + { "dirmode", OPT_INT, 'd' }, + { "timeout", OPT_INT, 't' }, + { "retry", OPT_INT, 'r' }, + { "flags", OPT_INT, 'f' }, + { "wdogpid", OPT_INT, 'w' }, + { "ncpfd", OPT_INT, 'n' }, + { "infofd", OPT_INT, 'i' }, /* v5 */ + { "version", OPT_INT, 'v' }, + { NULL, 0, 0 } }; + +static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { + int optval; + char *optarg; + unsigned long optint; + int version = 0; + + data->flags = 0; + data->int_flags = 0; + data->mounted_uid = 0; + data->wdog_pid = -1; + data->ncp_fd = ~0; + data->time_out = 10; + data->retry_count = 20; + data->uid = 0; + data->gid = 0; + data->file_mode = 0600; + data->dir_mode = 0700; + data->info_fd = -1; + data->mounted_vol[0] = 0; + + while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { + if (optval < 0) + return optval; + switch (optval) { + case 'u': + data->uid = optint; + break; + case 'g': + data->gid = optint; + break; + case 'o': + data->mounted_uid = optint; + break; + case 'm': + data->file_mode = optint; + break; + case 'd': + data->dir_mode = optint; + break; + case 't': + data->time_out = optint; + break; + case 'r': + data->retry_count = optint; + break; + case 'f': + data->flags = optint; + break; + case 'w': + data->wdog_pid = optint; + break; + case 'n': + data->ncp_fd = optint; + break; + case 'i': + data->info_fd = optint; + break; + case 'v': + if (optint < NCP_MOUNT_VERSION_V4) { + return -ECHRNG; + } + if (optint > NCP_MOUNT_VERSION_V5) { + return -ECHRNG; + } + version = optint; + break; + + } + } + return 0; +} + static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; @@ -323,6 +423,7 @@ data.gid = md->gid; data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; + data.info_fd = -1; memcpy(data.mounted_vol, md->mounted_vol, NCP_VOLNAME_LEN+1); } @@ -342,12 +443,18 @@ data.gid = md->gid; data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; + data.info_fd = -1; data.mounted_vol[0] = 0; } break; default: error = -ECHRNG; - goto out; + if (*(__u32*)raw_data == cpu_to_be32(0x76657273)) { + error = ncp_parse_options(&data, raw_data); + } + if (error) + goto out; + break; } error = -EBADF; ncp_filp = fget(data.ncp_fd); @@ -376,6 +483,28 @@ memset(server, 0, sizeof(*server)); server->ncp_filp = ncp_filp; + server->ncp_sock = sock; + + if (data.info_fd != -1) { + struct socket *info_sock; + + error = -EBADF; + server->info_filp = fget(data.info_fd); + if (!server->info_filp) + goto out_fput; + error = -ENOTSOCK; + sock_inode = server->info_filp->f_dentry->d_inode; + if (!S_ISSOCK(sock_inode->i_mode)) + goto out_fput2; + info_sock = SOCKET_I(sock_inode); + if (!info_sock) + goto out_fput2; + error = -EBADFD; + if (info_sock->type != SOCK_STREAM) + goto out_fput2; + server->info_sock = info_sock; + } + /* server->lock = 0; */ init_MUTEX(&server->sem); server->packet = NULL; @@ -413,6 +542,16 @@ server->dentry_ttl = 0; /* no caching */ + INIT_LIST_HEAD(&server->tx.requests); + init_MUTEX(&server->rcv.creq_sem); + server->tx.creq = NULL; + server->rcv.creq = NULL; + server->data_ready = sock->sk->data_ready; + server->write_space = sock->sk->write_space; + server->error_report = sock->sk->error_report; + sock->sk->user_data = server; + + init_timer(&server->timeout_tm); #undef NCP_PACKET_SIZE #define NCP_PACKET_SIZE 131072 error = -ENOMEM; @@ -421,6 +560,22 @@ if (server->packet == NULL) goto out_nls; + sock->sk->data_ready = ncp_tcp_data_ready; + sock->sk->error_report = ncp_tcp_error_report; + if (sock->type == SOCK_STREAM) { + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + INIT_TQUEUE(&server->rcv.tq, ncp_tcp_rcv_proc, server); + INIT_TQUEUE(&server->tx.tq, ncp_tcp_tx_proc, server); + sock->sk->write_space = ncp_tcp_write_space; + } else { + INIT_TQUEUE(&server->rcv.tq, ncpdgram_rcv_proc, server); + INIT_TQUEUE(&server->timeout_tq, ncpdgram_timeout_proc, server); + server->timeout_tm.data = (unsigned long)server; + server->timeout_tm.function = ncpdgram_timeout_call; + } + ncp_lock_server(server); error = ncp_connect(server); ncp_unlock_server(server); @@ -495,12 +650,16 @@ ncp_disconnect(server); ncp_unlock_server(server); out_packet: + ncp_stop_tasks(server); vfree(server->packet); out_nls: #ifdef CONFIG_NCPFS_NLS unload_nls(server->nls_io); unload_nls(server->nls_vol); #endif +out_fput2: + if (server->info_filp) + fput(server->info_filp); out_fput: /* 23/12/1998 Marcin Dalecki : * @@ -522,6 +681,8 @@ ncp_disconnect(server); ncp_unlock_server(server); + ncp_stop_tasks(server); + #ifdef CONFIG_NCPFS_NLS /* unload the NLS charsets */ if (server->nls_vol) @@ -536,6 +697,8 @@ } #endif /* CONFIG_NCPFS_NLS */ + if (server->info_filp) + fput(server->info_filp); fput(server->ncp_filp); kill_proc(server->m.wdog_pid, SIGTERM, 1); diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c --- a/fs/ncpfs/ioctl.c Sat Sep 21 21:25:43 2002 +++ b/fs/ncpfs/ioctl.c Sat Sep 21 21:25:43 2002 @@ -424,7 +424,7 @@ if (user.object_name_len) { newname = ncp_kmalloc(user.object_name_len, GFP_USER); if (!newname) return -ENOMEM; - if (copy_from_user(newname, user.object_name, sizeof(user))) { + if (copy_from_user(newname, user.object_name, user.object_name_len)) { ncp_kfree_s(newname, user.object_name_len); return -EFAULT; } diff -Nru a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c --- a/fs/ncpfs/ncplib_kernel.c Sat Sep 21 21:25:45 2002 +++ b/fs/ncpfs/ncplib_kernel.c Sat Sep 21 21:25:45 2002 @@ -341,6 +341,7 @@ target->nameLen = *name_len; memcpy(target->entryName, name_len + 1, *name_len); target->entryName[*name_len] = '\0'; + target->volNumber = le32_to_cpu(target->volNumber); return; } @@ -475,7 +476,7 @@ } result = NW_NS_DOS; - no_namespaces = ncp_reply_word(server, 0); + no_namespaces = le16_to_cpu(ncp_reply_word(server, 0)); namespace = ncp_reply_data(server, 2); while (no_namespaces > 0) { diff -Nru a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c --- a/fs/ncpfs/ncpsign_kernel.c Sat Sep 21 21:25:45 2002 +++ b/fs/ncpfs/ncpsign_kernel.c Sat Sep 21 21:25:45 2002 @@ -93,19 +93,35 @@ /* Make a signature for the current packet and add it at the end of the */ /* packet. */ -void sign_packet(struct ncp_server *server, int *size) { - char data[64]; +void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) { + unsigned char data[64]; - memset(data,0,64); - memcpy(data,server->sign_root,8); - PUT_LE32(data+8,(*size)); - memcpy(data+12,server->packet+sizeof(struct ncp_request_header)-1, - min_t(unsigned int,(*size)-sizeof(struct ncp_request_header)+1,52)); + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, server->sign_last); + memcpy(sign_buff, server->sign_last, 8); +} - nwsign(server->sign_last,data,server->sign_last); +int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) { + unsigned char data[64]; + unsigned char hash[16]; - memcpy(server->packet+(*size),server->sign_last,8); - (*size)+=8; + memcpy(data, server->sign_root, 8); + *(__u32*)(data + 8) = totalsize; + if (size < 52) { + memcpy(data + 12, packet, size); + memset(data + 12 + size, 0, 52 - size); + } else { + memcpy(data + 12, packet, 52); + } + nwsign(server->sign_last, data, hash); + return memcmp(sign_buff, hash, 8); } #endif /* CONFIG_NCPFS_PACKET_SIGNING */ diff -Nru a/fs/ncpfs/ncpsign_kernel.h b/fs/ncpfs/ncpsign_kernel.h --- a/fs/ncpfs/ncpsign_kernel.h Sat Sep 21 21:25:48 2002 +++ b/fs/ncpfs/ncpsign_kernel.h Sat Sep 21 21:25:48 2002 @@ -10,6 +10,19 @@ #include -void sign_packet(struct ncp_server *server, int *size); +#ifdef CONFIG_NCPFS_PACKET_SIGNING +void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff); +int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff); +#endif + +static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) { +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + __sign_packet(server, data, size, totalsize, sign_buff); + return 8; + } +#endif + return 0; +} #endif diff -Nru a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c --- a/fs/ncpfs/sock.c Sat Sep 21 21:25:45 2002 +++ b/fs/ncpfs/sock.c Sat Sep 21 21:25:45 2002 @@ -29,18 +29,13 @@ #include -#ifdef CONFIG_NCPFS_PACKET_SIGNING #include "ncpsign_kernel.h" -#endif static int _recv(struct socket *sock, unsigned char *ubuf, int size, unsigned flags) { struct iovec iov; struct msghdr msg; - struct scm_cookie scm; - - memset(&scm, 0, sizeof(scm)); iov.iov_base = ubuf; iov.iov_len = size; @@ -50,15 +45,14 @@ msg.msg_control = NULL; msg.msg_iov = &iov; msg.msg_iovlen = 1; - return sock->ops->recvmsg(sock, &msg, size, flags, &scm); + + return sock_recvmsg(sock, &msg, size, flags); } -static int _send(struct socket *sock, const void *buff, int len) +static inline int _send(struct socket *sock, const void *buff, int len) { struct iovec iov; struct msghdr msg; - struct scm_cookie scm; - int err; iov.iov_base = (void *) buff; iov.iov_len = len; @@ -70,353 +64,661 @@ msg.msg_iovlen = 1; msg.msg_flags = 0; - err = scm_send(sock, &msg, &scm); - if (err < 0) { - return err; - } - err = sock->ops->sendmsg(sock, &msg, len, &scm); - scm_destroy(&scm); - return err; + return sock_sendmsg(sock, &msg, len); } -static int do_ncp_rpc_call(struct ncp_server *server, int size, - struct ncp_reply_header* reply_buf, int max_reply_size) -{ - struct file *file; - struct socket *sock; +struct ncp_request_reply { + struct list_head req; + wait_queue_head_t wq; + struct ncp_reply_header* reply_buf; + size_t datalen; int result; - char *start = server->packet; - poll_table wait_table; - int init_timeout, max_timeout; - int timeout; - int retrans; - int major_timeout_seen; - int acknowledge_seen; - int n; + enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status; + struct iovec* tx_ciov; + size_t tx_totallen; + size_t tx_iovlen; + struct iovec tx_iov[3]; + u_int16_t tx_type; + u_int32_t sign[6]; +}; - /* We have to check the result, so store the complete header */ - struct ncp_request_header request = - *((struct ncp_request_header *) (server->packet)); +void ncp_tcp_data_ready(struct sock *sk, int len) { + struct ncp_server *server = sk->user_data; + + server->data_ready(sk, len); + schedule_task(&server->rcv.tq); +} + +void ncp_tcp_error_report(struct sock *sk) { + struct ncp_server *server = sk->user_data; + + server->error_report(sk); + schedule_task(&server->rcv.tq); +} + +void ncp_tcp_write_space(struct sock *sk) { + struct ncp_server *server = sk->user_data; + + /* We do not need any locking: we first set tx.creq, and then we do sendmsg, + not vice versa... */ + server->write_space(sk); + if (server->tx.creq) { + schedule_task(&server->tx.tq); + } +} + +void ncpdgram_timeout_call(unsigned long v) { + struct ncp_server *server = (void*)v; + + schedule_task(&server->timeout_tq); +} + +static inline void ncp_finish_request(struct ncp_request_reply *req, int result) { + req->result = result; + req->status = RQ_DONE; + wake_up_all(&req->wq); +} + +static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err) { + struct ncp_request_reply *req; + + ncp_invalidate_conn(server); + del_timer(&server->timeout_tm); + while (!list_empty(&server->tx.requests)) { + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + + list_del_init(&req->req); + if (req == aborted) { + ncp_finish_request(req, err); + } else { + ncp_finish_request(req, -EIO); + } + } + req = server->rcv.creq; + if (req) { + server->rcv.creq = NULL; + if (req == aborted) { + ncp_finish_request(req, err); + } else { + ncp_finish_request(req, -EIO); + } + server->rcv.ptr = NULL; + server->rcv.state = 0; + } + req = server->tx.creq; + if (req) { + server->tx.creq = NULL; + if (req == aborted) { + ncp_finish_request(req, err); + } else { + ncp_finish_request(req, -EIO); + } + } +} + +static inline int get_conn_number(struct ncp_reply_header *rp) { + return rp->conn_low | (rp->conn_high << 8); +} + +static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) { + /* If req is done, we got signal, but we also received answer... */ + switch (req->status) { + case RQ_IDLE: + case RQ_DONE: + break; + case RQ_QUEUED: + list_del_init(&req->req); + ncp_finish_request(req, err); + break; + case RQ_INPROGRESS: + __abort_ncp_connection(server, req, err); + break; + } +} + +static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) { + down(&server->rcv.creq_sem); + __ncp_abort_request(server, req, err); + up(&server->rcv.creq_sem); +} + +static inline void __ncptcp_abort(struct ncp_server *server) { + __abort_ncp_connection(server, NULL, 0); +} + +static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) { + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_iov = req->tx_ciov; + msg.msg_iovlen = req->tx_iovlen; + msg.msg_flags = MSG_DONTWAIT; + return sock_sendmsg(sock, &msg, req->tx_totallen); +} + +static void __ncptcp_try_send(struct ncp_server *server) { + struct ncp_request_reply *rq; + struct msghdr msg; + struct iovec* iov; + int result; + + rq = server->tx.creq; + if (!rq) { + return; + } + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_iov = rq->tx_ciov; + msg.msg_iovlen = rq->tx_iovlen; + msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT; + result = sock_sendmsg(server->ncp_sock, &msg, rq->tx_totallen); + if (result == -EAGAIN) { + return; + } + if (result < 0) { + printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result); + __ncp_abort_request(server, rq, result); + return; + } + if (result >= rq->tx_totallen) { + server->rcv.creq = rq; + server->tx.creq = NULL; + return; + } + rq->tx_totallen -= result; + iov = rq->tx_ciov; + while (iov->iov_len <= result) { + result -= iov->iov_len; + iov++; + rq->tx_iovlen--; + } + iov->iov_len -= result; + rq->tx_ciov = iov; +} - struct ncp_reply_header reply; +static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) { + req->status = RQ_INPROGRESS; + h->conn_low = server->connection; + h->conn_high = server->connection >> 8; + h->sequence = ++server->sequence; +} + +static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) { + size_t signlen; + struct ncp_request_header* h; + + req->tx_ciov = req->tx_iov + 1; + + h = req->tx_iov[1].iov_base; + ncp_init_header(server, req, h); + signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, + cpu_to_le32(req->tx_totallen), req->sign); + if (signlen) { + req->tx_ciov[1].iov_base = req->sign; + req->tx_ciov[1].iov_len = signlen; + req->tx_iovlen += 1; + req->tx_totallen += signlen; + } + server->rcv.creq = req; + server->timeout_last = server->m.time_out; + server->timeout_retries = server->m.retry_count; + ncpdgram_send(server->ncp_sock, req); + mod_timer(&server->timeout_tm, jiffies + server->m.time_out); +} + +#define NCP_TCP_XMIT_MAGIC (0x446D6454) +#define NCP_TCP_XMIT_VERSION (1) +#define NCP_TCP_RCVD_MAGIC (0x744E6350) - file = server->ncp_filp; - sock = SOCKET_I(file->f_dentry->d_inode); +static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) { + size_t signlen; + struct ncp_request_header* h; + + req->tx_ciov = req->tx_iov; + h = req->tx_iov[1].iov_base; + ncp_init_header(server, req, h); + signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, + req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, + cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16; + + req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); + req->sign[1] = htonl(req->tx_totallen + signlen); + req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); + req->sign[3] = htonl(req->datalen + 8); + req->tx_iov[0].iov_base = req->sign; + req->tx_iov[0].iov_len = signlen; + req->tx_iovlen += 1; + req->tx_totallen += signlen; - init_timeout = server->m.time_out; - max_timeout = NCP_MAX_RPC_TIMEOUT; - retrans = server->m.retry_count; - major_timeout_seen = 0; - acknowledge_seen = 0; - - for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) { - /* - DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", - htonl(server->m.serv_addr.sipx_network), - server->m.serv_addr.sipx_node[0], - server->m.serv_addr.sipx_node[1], - server->m.serv_addr.sipx_node[2], - server->m.serv_addr.sipx_node[3], - server->m.serv_addr.sipx_node[4], - server->m.serv_addr.sipx_node[5], - ntohs(server->m.serv_addr.sipx_port)); - */ - DDPRINTK("ncpfs: req.typ: %04X, con: %d, " - "seq: %d", - request.type, - (request.conn_high << 8) + request.conn_low, - request.sequence); - DDPRINTK(" func: %d\n", - request.function); + server->tx.creq = req; + __ncptcp_try_send(server); +} - result = _send(sock, (void *) start, size); +static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) { + if (server->ncp_sock->type == SOCK_STREAM) + ncptcp_start_request(server, req); + else + ncpdgram_start_request(server, req); +} + +static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) { + down(&server->rcv.creq_sem); + if (!ncp_conn_valid(server)) { + up(&server->rcv.creq_sem); + printk(KERN_ERR "ncpfs: tcp: Server died\n"); + return -EIO; + } + if (server->tx.creq || server->rcv.creq) { + req->status = RQ_QUEUED; + list_add_tail(&req->req, &server->tx.requests); + up(&server->rcv.creq_sem); + return 0; + } + __ncp_start_request(server, req); + up(&server->rcv.creq_sem); + return 0; +} + +static void __ncp_next_request(struct ncp_server *server) { + struct ncp_request_reply *req; + + server->rcv.creq = NULL; + if (list_empty(&server->tx.requests)) { + return; + } + req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); + list_del_init(&req->req); + __ncp_start_request(server, req); +} + +static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) { + if (server->info_sock) { + struct iovec iov[2]; + struct msghdr msg; + __u32 hdr[2]; + + hdr[0] = cpu_to_be32(len + 8); + hdr[1] = cpu_to_be32(id); + + iov[0].iov_base = hdr; + iov[0].iov_len = 8; + iov[1].iov_base = (void *) data; + iov[1].iov_len = len; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + msg.msg_flags = MSG_NOSIGNAL; + + sock_sendmsg(server->info_sock, &msg, len + 8); + } +} + +static void __ncpdgram_rcv_proc(void *s) { + struct ncp_server *server = s; + struct socket* sock; + + sock = server->ncp_sock; + + while (1) { + struct ncp_reply_header reply; + int result; + + result = _recv(sock, (void*)&reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); if (result < 0) { - printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result); - return result; + break; } - re_select: - poll_initwait(&wait_table); - /* mb() is not necessary because ->poll() will serialize - instructions adding the wait_table waitqueues in the - waitqueue-head before going to calculate the mask-retval. */ - __set_current_state(TASK_INTERRUPTIBLE); - if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) { - int timed_out; - if (timeout > max_timeout) { - /* JEJB/JSP 2/7/94 - * This is useful to see if the system is - * hanging */ - if (acknowledge_seen == 0) { - printk(KERN_WARNING "NCP max timeout\n"); + if (result >= sizeof(reply)) { + struct ncp_request_reply *req; + + if (reply.type == NCP_WATCHDOG) { + unsigned char buf[10]; + + if (server->connection != get_conn_number(&reply)) { + goto drop; } - timeout = max_timeout; - } - timed_out = !schedule_timeout(timeout); - poll_freewait(&wait_table); - current->state = TASK_RUNNING; - if (signal_pending(current)) { - result = -ERESTARTSYS; - break; - } - if(wait_table.error) { - result = wait_table.error; - break; - } - if (timed_out) { - if (n < retrans) + result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); + if (result < 0) { + DPRINTK("recv failed with %d\n", result); + continue; + } + if (result < 10) { + DPRINTK("too short (%u) watchdog packet\n", result); continue; - if (server->m.flags & NCP_MOUNT_SOFT) { - printk(KERN_WARNING "NCP server not responding\n"); - result = -EIO; - break; } - n = 0; - timeout = init_timeout; - if (init_timeout < max_timeout) - init_timeout <<= 1; - if (!major_timeout_seen) { - printk(KERN_WARNING "NCP server not responding\n"); + if (buf[9] != '?') { + DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]); + continue; } - major_timeout_seen = 1; + buf[9] = 'Y'; + _send(sock, buf, sizeof(buf)); continue; } - } else { - poll_freewait(&wait_table); + if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) { + result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT); + if (result < 0) { + continue; + } + info_server(server, 0, server->unexpected_packet.data, result); + continue; + } + down(&server->rcv.creq_sem); + req = server->rcv.creq; + if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && + server->connection == get_conn_number(&reply)))) { + if (reply.type == NCP_POSITIVE_ACK) { + server->timeout_retries = server->m.retry_count; + server->timeout_last = NCP_MAX_RPC_TIMEOUT; + mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); + } else if (reply.type == NCP_REPLY) { + result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT); +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (result < 8 + 8) { + result = -EIO; + } else { + unsigned int hdrl; + + result -= 8; + hdrl = sock->sk->family == AF_INET ? 8 : 6; + if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) { + printk(KERN_INFO "ncpfs: Signature violation\n"); + result = -EIO; + } + } + } +#endif + del_timer(&server->timeout_tm); + server->rcv.creq = NULL; + ncp_finish_request(req, result); + __ncp_next_request(server); + up(&server->rcv.creq_sem); + continue; + } + } + up(&server->rcv.creq_sem); } - current->state = TASK_RUNNING; +drop:; + _recv(sock, (void*)&reply, sizeof(reply), MSG_DONTWAIT); + } +} - /* Get the header from the next packet using a peek, so keep it - * on the recv queue. If it is wrong, it will be some reply - * we don't now need, so discard it */ - result = _recv(sock, (void *) &reply, sizeof(reply), - MSG_PEEK | MSG_DONTWAIT); - if (result < 0) { - if (result == -EAGAIN) { - DDPRINTK("ncp_rpc_call: bad select ready\n"); - goto re_select; - } - if (result == -ECONNREFUSED) { - DPRINTK("ncp_rpc_call: server playing coy\n"); - goto re_select; +void ncpdgram_rcv_proc(void *s) { + mm_segment_t fs; + struct ncp_server *server = s; + + fs = get_fs(); + set_fs(get_ds()); + __ncpdgram_rcv_proc(server); + set_fs(fs); +} + +static void __ncpdgram_timeout_proc(struct ncp_server *server) { + /* If timer is pending, we are processing another request... */ + if (!timer_pending(&server->timeout_tm)) { + struct ncp_request_reply* req; + + req = server->rcv.creq; + if (req) { + int timeout; + + if (server->m.flags & NCP_MOUNT_SOFT) { + if (server->timeout_retries-- == 0) { + __ncp_abort_request(server, req, -ETIMEDOUT); + return; + } } - if (result != -ERESTARTSYS) { - printk(KERN_ERR "ncp_rpc_call: recv error = %d\n", - -result); + /* Ignore errors */ + ncpdgram_send(server->ncp_sock, req); + timeout = server->timeout_last << 1; + if (timeout > NCP_MAX_RPC_TIMEOUT) { + timeout = NCP_MAX_RPC_TIMEOUT; } - break; + server->timeout_last = timeout; + mod_timer(&server->timeout_tm, jiffies + timeout); } - if ((result == sizeof(reply)) - && (reply.type == NCP_POSITIVE_ACK)) { - /* Throw away the packet */ - DPRINTK("ncp_rpc_call: got positive acknowledge\n"); - _recv(sock, (void *) &reply, sizeof(reply), - MSG_DONTWAIT); - n = 0; - timeout = max_timeout; - acknowledge_seen = 1; - goto re_select; - } - DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d," - "seq: %d\n", - reply.type, - (reply.conn_high << 8) + reply.conn_low, - reply.task, - reply.sequence); - - if ((result >= sizeof(reply)) - && (reply.type == NCP_REPLY) - && ((request.type == NCP_ALLOC_SLOT_REQUEST) - || ((reply.sequence == request.sequence) - && (reply.conn_low == request.conn_low) -/* seem to get wrong task from NW311 && (reply.task == request.task) */ - && (reply.conn_high == request.conn_high)))) { - if (major_timeout_seen) - printk(KERN_NOTICE "NCP server OK\n"); - break; - } - /* JEJB/JSP 2/7/94 - * we have xid mismatch, so discard the packet and start - * again. What a hack! but I can't call recvfrom with - * a null buffer yet. */ - _recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT); - - DPRINTK("ncp_rpc_call: reply mismatch\n"); - goto re_select; - } - /* - * we have the correct reply, so read into the correct place and - * return it - */ - result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT); - if (result < 0) { - printk(KERN_WARNING "NCP: notice message: result=%d\n", result); - } else if (result < sizeof(struct ncp_reply_header)) { - printk(KERN_ERR "NCP: just caught a too small read memory size..., " - "email to NET channel\n"); - printk(KERN_ERR "NCP: result=%d\n", result); - result = -EIO; } +} - return result; +void ncpdgram_timeout_proc(void *s) { + mm_segment_t fs; + struct ncp_server *server = s; + + fs = get_fs(); + set_fs(get_ds()); + down(&server->rcv.creq_sem); + __ncpdgram_timeout_proc(server); + up(&server->rcv.creq_sem); + set_fs(fs); +} + +static inline void ncp_init_req(struct ncp_request_reply* req) { + init_waitqueue_head(&req->wq); + req->status = RQ_IDLE; } static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) { - poll_table wait_table; - struct file *file; - struct socket *sock; - int init_timeout; - size_t dataread; - int result = 0; - - file = server->ncp_filp; - sock = SOCKET_I(file->f_dentry->d_inode); - - dataread = 0; - - init_timeout = server->m.time_out * 20; - - /* hard-mounted volumes have no timeout, except connection close... */ - if (!(server->m.flags & NCP_MOUNT_SOFT)) - init_timeout = 0x7FFF0000; - - while (len) { - poll_initwait(&wait_table); - /* mb() is not necessary because ->poll() will serialize - instructions adding the wait_table waitqueues in the - waitqueue-head before going to calculate the mask-retval. */ - __set_current_state(TASK_INTERRUPTIBLE); - if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) { - init_timeout = schedule_timeout(init_timeout); - poll_freewait(&wait_table); - current->state = TASK_RUNNING; - if (signal_pending(current)) { - return -ERESTARTSYS; - } - if (!init_timeout) { - return -EIO; - } - if(wait_table.error) { - return wait_table.error; - } - } else { - poll_freewait(&wait_table); + int result; + + if (buffer) { + result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT); + } else { + static unsigned char dummy[1024]; + + if (len > sizeof(dummy)) { + len = sizeof(dummy); } - current->state = TASK_RUNNING; + result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT); + } + if (result < 0) { + return result; + } + if (result > len) { + printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %u)\n", result, len); + return -EIO; + } + return result; +} - result = _recv(sock, buffer, len, MSG_DONTWAIT); - if (result < 0) { +static int __ncptcp_rcv_proc(struct ncp_server *server) { + /* We have to check the result, so store the complete header */ + while (1) { + int result; + struct ncp_request_reply *req; + int datalen; + int type; + + while (server->rcv.len) { + result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len); if (result == -EAGAIN) { - DDPRINTK("ncpfs: tcp: bad select ready\n"); - continue; + return 0; } - return result; - } - if (result == 0) { - printk(KERN_ERR "ncpfs: tcp: EOF on socket\n"); - return -EIO; + if (result <= 0) { + req = server->rcv.creq; + if (req) { + __ncp_abort_request(server, req, -EIO); + } else { + __ncptcp_abort(server); + } + if (result < 0) { + printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result); + } else { + DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n"); + } + return -EIO; + } + if (server->rcv.ptr) { + server->rcv.ptr += result; + } + server->rcv.len -= result; } - if (result > len) { - printk(KERN_ERR "ncpfs: tcp: bug in recvmsg\n"); - return -EIO; + switch (server->rcv.state) { + case 0: + if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { + printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); + __ncptcp_abort(server); + return -EIO; + } + datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; + if (datalen < 10) { + printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active) { + if (datalen < 18) { + printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); + __ncptcp_abort(server); + return -EIO; + } + server->rcv.buf.len = datalen - 8; + server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1; + server->rcv.len = 8; + server->rcv.state = 4; + break; + } +#endif + type = ntohs(server->rcv.buf.type); +cont:; + if (type != NCP_REPLY) { + if (datalen - 8 <= sizeof(server->unexpected_packet.data)) { + *(__u16*)(server->unexpected_packet.data) = htons(type); + server->unexpected_packet.len = datalen - 8; + + server->rcv.state = 5; + server->rcv.ptr = server->unexpected_packet.data + 2; + server->rcv.len = datalen - 10; + break; + } + DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type); +skipdata2:; + server->rcv.state = 2; +skipdata:; + server->rcv.ptr = NULL; + server->rcv.len = datalen - 10; + break; + } + req = server->rcv.creq; + if (!req) { + DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n"); + goto skipdata2; + } + if (datalen > req->datalen + 8) { + printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %d)\n", datalen, req->datalen + 8); + server->rcv.state = 3; + goto skipdata; + } + req->datalen = datalen - 8; + req->reply_buf->type = NCP_REPLY; + server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2; + server->rcv.len = datalen - 10; + server->rcv.state = 1; + break; +#ifdef CONFIG_NCPFS_PACKET_SIGNING + case 4: + datalen = server->rcv.buf.len; + type = ntohs(server->rcv.buf.type2); + goto cont; +#endif + case 1: + req = server->rcv.creq; + if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { + if (req->reply_buf->sequence != server->sequence) { + printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) { + printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#ifdef CONFIG_NCPFS_PACKET_SIGNING + if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { + if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { + printk(KERN_ERR "ncpfs: tcp: Signature violation\n"); + __ncp_abort_request(server, req, -EIO); + return -EIO; + } + } +#endif + ncp_finish_request(req, req->datalen); + nextreq:; + __ncp_next_request(server); + case 2: + next:; + server->rcv.ptr = (unsigned char*)&server->rcv.buf; + server->rcv.len = 10; + server->rcv.state = 0; + break; + case 3: + ncp_finish_request(server->rcv.creq, -EIO); + goto nextreq; + case 5: + info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); + goto next; } - dataread += result; - buffer += result; - len -= result; } - return 0; -} +} -#define NCP_TCP_XMIT_MAGIC (0x446D6454) -#define NCP_TCP_XMIT_VERSION (1) -#define NCP_TCP_RCVD_MAGIC (0x744E6350) +void ncp_tcp_rcv_proc(void *s) { + mm_segment_t fs; + struct ncp_server *server = s; + + fs = get_fs(); + set_fs(get_ds()); + down(&server->rcv.creq_sem); + __ncptcp_rcv_proc(server); + up(&server->rcv.creq_sem); + set_fs(fs); + return; +} -static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size, +void ncp_tcp_tx_proc(void *s) { + mm_segment_t fs; + struct ncp_server *server = s; + + fs = get_fs(); + set_fs(get_ds()); + down(&server->rcv.creq_sem); + __ncptcp_try_send(server); + up(&server->rcv.creq_sem); + set_fs(fs); + return; +} + +static int do_ncp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header* reply_buf, int max_reply_size) { - struct file *file; - struct socket *sock; int result; - struct iovec iov[2]; - struct msghdr msg; - struct scm_cookie scm; - __u32 ncptcp_rcvd_hdr[2]; - __u32 ncptcp_xmit_hdr[4]; - int datalen; + struct ncp_request_reply req; - /* We have to check the result, so store the complete header */ - struct ncp_request_header request = - *((struct ncp_request_header *) (server->packet)); + ncp_init_req(&req); + req.reply_buf = reply_buf; + req.datalen = max_reply_size; + req.tx_iov[1].iov_base = (void *) server->packet; + req.tx_iov[1].iov_len = size; + req.tx_iovlen = 1; + req.tx_totallen = size; + req.tx_type = *(u_int16_t*)server->packet; - file = server->ncp_filp; - sock = SOCKET_I(file->f_dentry->d_inode); - - ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC); - ncptcp_xmit_hdr[1] = htonl(size + 16); - ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION); - ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8); - - DDPRINTK("ncpfs: req.typ: %04X, con: %d, " - "seq: %d", - request.type, - (request.conn_high << 8) + request.conn_low, - request.sequence); - DDPRINTK(" func: %d\n", - request.function); - - iov[1].iov_base = (void *) server->packet; - iov[1].iov_len = size; - iov[0].iov_base = ncptcp_xmit_hdr; - iov[0].iov_len = 16; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_iov = iov; - msg.msg_iovlen = 2; - msg.msg_flags = MSG_NOSIGNAL; - - result = scm_send(sock, &msg, &scm); - if (result < 0) { - return result; - } - result = sock->ops->sendmsg(sock, &msg, size + 16, &scm); - scm_destroy(&scm); + result = ncp_add_request(server, &req); if (result < 0) { - printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result); return result; } -rstrcv: - result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8); - if (result) - return result; - if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) { - printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0])); - return -EIO; - } - datalen = ntohl(ncptcp_rcvd_hdr[1]); - if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) { - printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); - return -EIO; + if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) { + ncp_abort_request(server, &req, -EIO); } - datalen -= 8; - result = do_tcp_rcv(server, reply_buf, datalen); - if (result) - return result; - if (reply_buf->type != NCP_REPLY) { - DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type); - goto rstrcv; - } - if (request.type == NCP_ALLOC_SLOT_REQUEST) - return datalen; - if (reply_buf->sequence != request.sequence) { - printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); - return -EIO; - } - if ((reply_buf->conn_low != request.conn_low) || - (reply_buf->conn_high != request.conn_high)) { - printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); - return -EIO; - } - return datalen; + return req.result; } /* @@ -426,8 +728,6 @@ static int ncp_do_request(struct ncp_server *server, int size, void* reply, int max_reply_size) { - struct file *file; - struct socket *sock; int result; if (server->lock == 0) { @@ -435,21 +735,10 @@ return -EIO; } if (!ncp_conn_valid(server)) { + printk(KERN_ERR "ncpfs: Connection invalid!\n"); return -EIO; } -#ifdef CONFIG_NCPFS_PACKET_SIGNING - if (server->sign_active) { - sign_packet(server, &size); - } -#endif /* CONFIG_NCPFS_PACKET_SIGNING */ - file = server->ncp_filp; - sock = SOCKET_I(file->f_dentry->d_inode); - /* N.B. this isn't needed ... check socket type? */ - if (!sock) { - printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n"); - result = -EBADF; - } else { mm_segment_t fs; sigset_t old_set; unsigned long mask, flags; @@ -478,10 +767,7 @@ fs = get_fs(); set_fs(get_ds()); - if (sock->type == SOCK_STREAM) - result = do_ncp_tcp_rpc_call(server, size, reply, max_reply_size); - else - result = do_ncp_rpc_call(server, size, reply, max_reply_size); + result = do_ncp_rpc_call(server, size, reply, max_reply_size); set_fs(fs); @@ -510,20 +796,13 @@ { struct ncp_request_header *h; struct ncp_reply_header* reply = rpl; - int request_size = server->current_size - - sizeof(struct ncp_request_header); int result; h = (struct ncp_request_header *) (server->packet); if (server->has_subfunction != 0) { - *(__u16 *) & (h->data[0]) = htons(request_size - 2); + *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2); } h->type = NCP_REQUEST; - - server->sequence += 1; - h->sequence = server->sequence; - h->conn_low = (server->connection) & 0xff; - h->conn_high = ((server->connection) & 0xff00) >> 8; /* * The server shouldn't know or care what task is making a * request, so we always use the same task number. @@ -531,7 +810,7 @@ h->task = 2; /* (current->pid) & 0xff; */ h->function = function; - result = ncp_do_request(server, request_size + sizeof(*h), reply, size); + result = ncp_do_request(server, server->current_size, reply, size); if (result < 0) { DPRINTK("ncp_request_error: %d\n", result); goto out; @@ -554,20 +833,17 @@ struct ncp_request_header *h; int result; + server->connection = 0xFFFF; + server->sequence = 255; + h = (struct ncp_request_header *) (server->packet); h->type = NCP_ALLOC_SLOT_REQUEST; - - server->sequence = 0; - h->sequence = server->sequence; - h->conn_low = 0xff; - h->conn_high = 0xff; h->task = 2; /* see above */ h->function = 0; result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); if (result < 0) goto out; - server->sequence = 0; server->connection = h->conn_low + (h->conn_high * 256); result = 0; out: @@ -580,11 +856,6 @@ h = (struct ncp_request_header *) (server->packet); h->type = NCP_DEALLOC_SLOT_REQUEST; - - server->sequence += 1; - h->sequence = server->sequence; - h->conn_low = (server->connection) & 0xff; - h->conn_high = ((server->connection) & 0xff00) >> 8; h->task = 2; /* see above */ h->function = 0; diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c --- a/fs/partitions/check.c Sat Sep 21 21:25:45 2002 +++ b/fs/partitions/check.c Sat Sep 21 21:25:45 2002 @@ -286,6 +286,8 @@ #ifdef CONFIG_DEVFS_FS static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER; +static devfs_handle_t cdroms; +static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER; #endif static void devfs_create_partitions(struct gendisk *dev) @@ -333,6 +335,47 @@ #endif } +static void devfs_create_cdrom(struct gendisk *dev) +{ +#ifdef CONFIG_DEVFS_FS + int pos = 0; + devfs_handle_t dir, slave; + unsigned int devfs_flags = DEVFS_FL_DEFAULT; + char dirname[64], symlink[16]; + char vname[23]; + + if (!cdroms) + cdroms = devfs_mk_dir (NULL, "cdroms", NULL); + + dev->number = devfs_alloc_unique_number(&cdrom_numspace); + sprintf(vname, "cdroms/cdrom%d", dev->number); + if (dev->de) { + int pos; + devfs_handle_t slave; + char rname[64]; + + dev->disk_de = devfs_register(dev->de, "cd", DEVFS_FL_DEFAULT, + dev->major, dev->first_minor, + S_IFBLK | S_IRUGO | S_IWUGO, + dev->fops, NULL); + + pos = devfs_generate_path(dev->disk_de, rname+3, sizeof(rname)-3); + if (pos >= 0) { + strncpy(rname + pos, "../", 3); + devfs_mk_symlink(devfs_handle, vname, + DEVFS_FL_DEFAULT, + rname + pos, &slave, NULL); + devfs_auto_unregister(dev->de, slave); + } + } else { + dev->disk_de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT, + dev->major, dev->first_minor, + S_IFBLK | S_IRUGO | S_IWUGO, + dev->fops, NULL); + } +#endif +} + static void devfs_remove_partitions(struct gendisk *dev) { #ifdef CONFIG_DEVFS_FS @@ -343,7 +386,10 @@ } devfs_unregister(dev->disk_de); dev->disk_de = NULL; - devfs_dealloc_unique_number(&disc_numspace, dev->number); + if (dev->flags & GENHD_FL_CD) + devfs_dealloc_unique_number(&cdrom_numspace, dev->number); + else + devfs_dealloc_unique_number(&disc_numspace, dev->number); #endif } @@ -367,6 +413,9 @@ set_capacity(disk, size); + if (disk->flags & GENHD_FL_CD) + devfs_create_cdrom(disk); + /* No minors to use for partitions */ if (!disk->minor_shift) return; @@ -503,4 +552,48 @@ kfree(disk->part); disk->part = NULL; } +} + +struct dev_name { + struct list_head list; + dev_t dev; + char namebuf[64]; + char *name; +}; + +static LIST_HEAD(device_names); + +char *partition_name(dev_t dev) +{ + struct gendisk *hd; + static char nomem [] = ""; + struct dev_name *dname; + struct list_head *tmp; + + list_for_each(tmp, &device_names) { + dname = list_entry(tmp, struct dev_name, list); + if (dname->dev == dev) + return dname->name; + } + + dname = kmalloc(sizeof(*dname), GFP_KERNEL); + + if (!dname) + return nomem; + /* + * ok, add this new device name to the list + */ + hd = get_gendisk(to_kdev_t(dev)); + dname->name = NULL; + if (hd) + dname->name = disk_name(hd, MINOR(dev)-hd->first_minor, dname->namebuf); + if (!dname->name) { + sprintf(dname->namebuf, "[dev %s]", kdevname(to_kdev_t(dev))); + dname->name = dname->namebuf; + } + + dname->dev = dev; + list_add(&dname->list, &device_names); + + return dname->name; } diff -Nru a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c --- a/fs/udf/lowlevel.c Sat Sep 21 21:25:46 2002 +++ b/fs/udf/lowlevel.c Sat Sep 21 21:25:46 2002 @@ -78,13 +78,10 @@ if (ret) /* Hard Disk */ { - ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock); - - if (!ret && lblock != 0x7FFFFFFF) - lblock = ((512 * lblock) / sb->s_blocksize); + lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits; } - if (!ret && lblock) + if (lblock) return lblock - 1; else return 0; diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h --- a/include/asm-ia64/hardirq.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/hardirq.h Sat Sep 21 21:25:45 2002 @@ -83,6 +83,7 @@ #define hardirq_trylock() (!in_interrupt()) #define hardirq_endlock() do { } while (0) +#define in_atomic() (preempt_count() != 0) #define irq_enter() (preempt_count() += HARDIRQ_OFFSET) #if CONFIG_PREEMPT diff -Nru a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h --- a/include/asm-ia64/ide.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/ide.h Sat Sep 21 21:25:45 2002 @@ -90,20 +90,6 @@ #endif } -#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) -#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) -#define ide_check_region(from,extent) check_region((from), (extent)) -#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) -#define ide_release_region(from,extent) release_region((from), (extent)) - -/* - * The following are not needed for the non-m68k ports - */ -#define ide_ack_intr(hwif) (1) -#define ide_fix_driveid(id) do {} while (0) -#define ide_release_lock(lock) do {} while (0) -#define ide_get_lock(lock, hdlr, data) do {} while (0) - #endif /* __KERNEL__ */ #endif /* __ASM_IA64_IDE_H */ diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h --- a/include/asm-ia64/machvec.h Sat Sep 21 21:25:43 2002 +++ b/include/asm-ia64/machvec.h Sat Sep 21 21:25:43 2002 @@ -86,12 +86,10 @@ # define platform_setup ia64_mv.setup # define platform_cpu_init ia64_mv.cpu_init # define platform_irq_init ia64_mv.irq_init -# define platform_map_nr ia64_mv.map_nr # define platform_mca_init ia64_mv.mca_init # define platform_mca_handler ia64_mv.mca_handler # define platform_cmci_handler ia64_mv.cmci_handler # define platform_log_print ia64_mv.log_print -# define platform_pci_fixup ia64_mv.pci_fixup # define platform_send_ipi ia64_mv.send_ipi # define platform_global_tlb_purge ia64_mv.global_tlb_purge # define platform_pci_dma_init ia64_mv.dma_init @@ -159,8 +157,6 @@ platform_setup, \ platform_cpu_init, \ platform_irq_init, \ - platform_pci_fixup, \ - platform_map_nr, \ platform_mca_init, \ platform_mca_handler, \ platform_cmci_handler, \ @@ -236,9 +232,6 @@ #endif #ifndef platform_log_print # define platform_log_print ((ia64_mv_log_print_t *) machvec_noop) -#endif -#ifndef platform_pci_fixup -# define platform_pci_fixup ((ia64_mv_pci_fixup_t *) machvec_noop) #endif #ifndef platform_send_ipi # define platform_send_ipi ia64_send_ipi /* default to architected version */ diff -Nru a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h --- a/include/asm-ia64/machvec_dig.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/machvec_dig.h Sat Sep 21 21:25:45 2002 @@ -16,7 +16,5 @@ #define platform_name "dig" #define platform_setup dig_setup #define platform_irq_init dig_irq_init -#define platform_pci_fixup iosapic_pci_fixup -#define platform_map_nr map_nr_dense #endif /* _ASM_IA64_MACHVEC_DIG_h */ diff -Nru a/include/asm-ia64/machvec_hpsim.h b/include/asm-ia64/machvec_hpsim.h --- a/include/asm-ia64/machvec_hpsim.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/machvec_hpsim.h Sat Sep 21 21:25:45 2002 @@ -15,6 +15,5 @@ #define platform_name "hpsim" #define platform_setup hpsim_setup #define platform_irq_init hpsim_irq_init -#define platform_map_nr map_nr_dense #endif /* _ASM_IA64_MACHVEC_HPSIM_h */ diff -Nru a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h --- a/include/asm-ia64/machvec_hpzx1.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/machvec_hpzx1.h Sat Sep 21 21:25:45 2002 @@ -22,8 +22,6 @@ */ #define platform_name "hpzx1" #define platform_setup dig_setup -#define platform_pci_fixup hpzx1_pci_fixup -#define platform_map_nr map_nr_dense #define platform_pci_dma_init ((ia64_mv_pci_dma_init *) machvec_noop) #define platform_pci_alloc_consistent sba_alloc_consistent #define platform_pci_free_consistent sba_free_consistent diff -Nru a/include/asm-ia64/machvec_sn1.h b/include/asm-ia64/machvec_sn1.h --- a/include/asm-ia64/machvec_sn1.h Sat Sep 21 21:25:46 2002 +++ b/include/asm-ia64/machvec_sn1.h Sat Sep 21 21:25:46 2002 @@ -68,10 +68,8 @@ #define platform_setup sn1_setup #define platform_cpu_init sn_cpu_init #define platform_irq_init sn1_irq_init -#define platform_map_nr sn1_map_nr #define platform_send_ipi sn1_send_IPI #define platform_global_tlb_purge sn1_global_tlb_purge -#define platform_pci_fixup sn1_pci_fixup #define platform_inb sn1_inb #define platform_inw sn1_inw #define platform_inl sn1_inl diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h --- a/include/asm-ia64/machvec_sn2.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/machvec_sn2.h Sat Sep 21 21:25:45 2002 @@ -73,10 +73,8 @@ #define platform_setup sn1_setup #define platform_cpu_init sn_cpu_init #define platform_irq_init sn1_irq_init -#define platform_map_nr sn2_map_nr #define platform_send_ipi sn2_send_IPI #define platform_global_tlb_purge sn2_global_tlb_purge -#define platform_pci_fixup sn1_pci_fixup #ifdef Colin /* We are using the same is Generic IA64 calls defined in io.h */ #define platform_inb sn1_inb #define platform_inw sn1_inw diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h --- a/include/asm-ia64/mmu_context.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/mmu_context.h Sat Sep 21 21:25:45 2002 @@ -110,6 +110,10 @@ rr2 = rr0 + 2*rid_incr; rr3 = rr0 + 3*rid_incr; rr4 = rr0 + 4*rid_incr; +#ifdef CONFIG_HUGETLB_PAGE + rr4 = (rr4 & (~(0xfcUL))) | (HPAGE_SHIFT << 2); +#endif + ia64_set_rr(0x0000000000000000, rr0); ia64_set_rr(0x2000000000000000, rr1); ia64_set_rr(0x4000000000000000, rr2); diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h --- a/include/asm-ia64/page.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/page.h Sat Sep 21 21:25:45 2002 @@ -30,6 +30,32 @@ #define PAGE_MASK (~(PAGE_SIZE - 1)) #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) +#ifdef CONFIG_HUGETLB_PAGE + +# if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB) +# define HPAGE_SHIFT 32 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB) +# define HPAGE_SHIFT 28 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +# define HPAGE_SHIFT 26 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_16MB) +# define HPAGE_SHIFT 24 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +# define HPAGE_SHIFT 22 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define HPAGE_SHIFT 20 +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256KB) +# define HPAGE_SHIFT 18 +# else +# error Unsupported IA-64 HugeTLB Page Size! +# endif + +# define REGION_HPAGE (4UL) /* note: this is hardcoded in mmu_context.h:reload_context()!*/ +# define REGION_SHIFT 61 +# define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT) +# define HPAGE_MASK (~(HPAGE_SIZE - 1)) +#endif /* CONFIG_HUGETLB_PAGE */ + #ifdef __ASSEMBLY__ # define __pa(x) ((x) - PAGE_OFFSET) # define __va(x) ((x) + PAGE_OFFSET) @@ -86,6 +112,12 @@ #define REGION_SIZE REGION_NUMBER(1) #define REGION_KERNEL 7 + +#ifdef CONFIG_HUGETLB_PAGE +# define htlbpage_to_page(x) ((REGION_NUMBER(x) << 61) \ + | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT))) +# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#endif #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) # define ia64_abort() __builtin_trap() diff -Nru a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h --- a/include/asm-ia64/pal.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/pal.h Sat Sep 21 21:25:45 2002 @@ -78,6 +78,7 @@ #ifndef __ASSEMBLY__ #include +#include /* * Data types needed to pass information into PAL procedures and @@ -649,12 +650,43 @@ extern struct ia64_pal_retval ia64_pal_call_stacked (u64, u64, u64, u64); extern struct ia64_pal_retval ia64_pal_call_phys_static (u64, u64, u64, u64); extern struct ia64_pal_retval ia64_pal_call_phys_stacked (u64, u64, u64, u64); +extern void ia64_save_scratch_fpregs (struct ia64_fpreg *); +extern void ia64_load_scratch_fpregs (struct ia64_fpreg *); -#define PAL_CALL(iprv,a0,a1,a2,a3) iprv = ia64_pal_call_static(a0, a1, a2, a3, 0) -#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) iprv = ia64_pal_call_static(a0, a1, a2, a3, 1) -#define PAL_CALL_STK(iprv,a0,a1,a2,a3) iprv = ia64_pal_call_stacked(a0, a1, a2, a3) -#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3) iprv = ia64_pal_call_phys_static(a0, a1, a2, a3) -#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3) iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3) +#define PAL_CALL(iprv,a0,a1,a2,a3) do { \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ + iprv = ia64_pal_call_static(a0, a1, a2, a3, 0); \ + ia64_load_scratch_fpregs(fr); \ +} while (0) + +#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) do { \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ + iprv = ia64_pal_call_static(a0, a1, a2, a3, 1); \ + ia64_load_scratch_fpregs(fr); \ +} while (0) + +#define PAL_CALL_STK(iprv,a0,a1,a2,a3) do { \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ + iprv = ia64_pal_call_stacked(a0, a1, a2, a3); \ + ia64_load_scratch_fpregs(fr); \ +} while (0) + +#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3) do { \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ + iprv = ia64_pal_call_phys_static(a0, a1, a2, a3); \ + ia64_load_scratch_fpregs(fr); \ +} while (0) + +#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3) do { \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ + iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3); \ + ia64_load_scratch_fpregs(fr); \ +} while (0) typedef int (*ia64_pal_handler) (u64, ...); extern ia64_pal_handler ia64_pal; diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h --- a/include/asm-ia64/perfmon.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/perfmon.h Sat Sep 21 21:25:45 2002 @@ -45,6 +45,7 @@ * PMC flags */ #define PFM_REGFL_OVFL_NOTIFY 0x1 /* send notification on overflow */ +#define PFM_REGFL_RANDOM 0x2 /* randomize sampling periods */ /* * PMD/PMC/IBR/DBR return flags (ignored on input) @@ -86,8 +87,10 @@ unsigned long reg_short_reset;/* reset after counter overflow (small) */ unsigned long reg_reset_pmds[4]; /* which other counters to reset on overflow */ + unsigned long reg_random_seed; /* seed value when randomization is used */ + unsigned long reg_random_mask; /* bitmask used to limit random value */ - unsigned long reserved[16]; /* for future use */ + unsigned long reserved[14]; /* for future use */ } pfarg_reg_t; typedef struct { @@ -132,28 +135,28 @@ #define PFM_VERSION_MINOR(x) ((x) & 0xffff) /* - * Entry header in the sampling buffer. - * The header is directly followed with the PMDS saved in increasing index - * order: PMD4, PMD5, .... How many PMDs are present is determined by the - * user program during context creation. + * Entry header in the sampling buffer. The header is directly followed + * with the PMDs saved in increasing index order: PMD4, PMD5, .... How + * many PMDs are present is determined by the user program during + * context creation. * - * XXX: in this version of the entry, only up to 64 registers can be recorded - * This should be enough for quite some time. Always check sampling format - * before parsing entries! + * XXX: in this version of the entry, only up to 64 registers can be + * recorded. This should be enough for quite some time. Always check + * sampling format before parsing entries! * - * Inn the case where multiple counters have overflowed at the same time, the - * rate field indicate the initial value of the first PMD, based on the index. - * For instance, if PMD2 and PMD5 have ovewrflowed for this entry, the rate field - * will show the initial value of PMD2. + * In the case where multiple counters overflow at the same time, the + * last_reset_value member indicates the initial value of the PMD with + * the smallest index. For instance, if PMD2 and PMD5 have overflowed, + * the last_reset_value member contains the initial value of PMD2. */ typedef struct { - int pid; /* identification of process */ - int cpu; /* which cpu was used */ - unsigned long rate; /* initial value of overflowed counter */ - unsigned long stamp; /* timestamp */ - unsigned long ip; /* where did the overflow interrupt happened */ - unsigned long regs; /* bitmask of which registers overflowed */ - unsigned long period; /* sampling period used by overflowed counter (smallest pmd index) */ + int pid; /* identification of process */ + int cpu; /* which cpu was used */ + unsigned long last_reset_value; /* initial value of counter that overflowed */ + unsigned long stamp; /* timestamp */ + unsigned long ip; /* where did the overflow interrupt happened */ + unsigned long regs; /* bitmask of which registers overflowed */ + unsigned long period; /* unused */ } perfmon_smpl_entry_t; extern int perfmonctl(pid_t pid, int cmd, void *arg, int narg); diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h --- a/include/asm-ia64/processor.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/processor.h Sat Sep 21 21:25:45 2002 @@ -236,7 +236,15 @@ __u64 ssd; /* IA32 stack selector descriptor */ __u64 old_k1; /* old value of ar.k1 */ __u64 old_iob; /* old IOBase value */ -# define INIT_THREAD_IA32 0, 0, 0x17800000037fULL, 0, 0, 0, 0, 0, 0, +# define INIT_THREAD_IA32 .eflag = 0, \ + .fsr = 0, \ + .fcr = 0x17800000037fULL, \ + .fir = 0, \ + .fdr = 0, \ + .csd = 0, \ + .ssd = 0, \ + .old_k1 = 0, \ + .old_iob = 0, #else # define INIT_THREAD_IA32 #endif /* CONFIG_IA32_SUPPORT */ @@ -248,7 +256,13 @@ atomic_t pfm_notifiers_check; /* when >0, will cleanup ctx_notify_task in tasklist */ atomic_t pfm_owners_check; /* when >0, will cleanup ctx_owner in tasklist */ void *pfm_smpl_buf_list; /* list of sampling buffers to vfree */ -# define INIT_THREAD_PM {0, }, {0, }, 0, NULL, {0}, {0}, NULL, +# define INIT_THREAD_PM .pmc = {0, }, \ + .pmd = {0, }, \ + .pfm_ovfl_block_reset = 0, \ + .pfm_context = NULL, \ + .pfm_notifiers_check = { 0 }, \ + .pfm_owners_check = { 0 }, \ + .pfm_smpl_buf_list = NULL, #else # define INIT_THREAD_PM #endif @@ -258,16 +272,17 @@ }; #define INIT_THREAD { \ - flags: 0, \ - ksp: 0, \ - map_base: DEFAULT_MAP_BASE, \ - task_size: DEFAULT_TASK_SIZE, \ - siginfo: 0, \ + .flags = 0, \ + .ksp = 0, \ + .map_base = DEFAULT_MAP_BASE, \ + .task_size = DEFAULT_TASK_SIZE, \ + .siginfo = 0, \ + .last_fph_cpu = 0, \ INIT_THREAD_IA32 \ INIT_THREAD_PM \ - dbr: {0, }, \ - ibr: {0, }, \ - fph: {{{{0}}}, } \ + .dbr = {0, }, \ + .ibr = {0, }, \ + .fph = {{{{0}}}, } \ } #define start_thread(regs,new_ip,new_sp) do { \ diff -Nru a/include/asm-ia64/rse.h b/include/asm-ia64/rse.h --- a/include/asm-ia64/rse.h Sat Sep 21 21:25:48 2002 +++ b/include/asm-ia64/rse.h Sat Sep 21 21:25:48 2002 @@ -37,9 +37,9 @@ } /* - * Calcuate the number of registers in the dirty partition starting at - * BSPSTORE with a size of DIRTY bytes. This isn't simply DIRTY - * divided by eight because the 64th slot is used to store ar.rnat. + * Calculate the number of registers in the dirty partition starting at BSPSTORE and + * ending at BSP. This isn't simply (BSP-BSPSTORE)/8 because every 64th slot stores + * ar.rnat. */ static __inline__ unsigned long ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp) diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h --- a/include/asm-ia64/sal.h Sat Sep 21 21:25:48 2002 +++ b/include/asm-ia64/sal.h Sat Sep 21 21:25:48 2002 @@ -38,9 +38,12 @@ # define SAL_CALL(result,args...) do { \ unsigned long flags; \ + struct ia64_fpreg fr[6]; \ + ia64_save_scratch_fpregs(fr); \ spin_lock_irqsave(&sal_lock, flags); \ __SAL_CALL(result,args); \ spin_unlock_irqrestore(&sal_lock, flags); \ + ia64_load_scratch_fpregs(fr); \ } while (0) #define SAL_SET_VECTORS 0x01000000 diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h --- a/include/asm-ia64/siginfo.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/siginfo.h Sat Sep 21 21:25:45 2002 @@ -66,6 +66,7 @@ long _band; /* POLL_IN, POLL_OUT, POLL_MSG (XPG requires a "long") */ int _fd; } _sigpoll; + /* SIGPROF */ struct { pid_t _pid; /* which child */ diff -Nru a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h --- a/include/asm-ia64/signal.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/signal.h Sat Sep 21 21:25:45 2002 @@ -166,7 +166,6 @@ # include -#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER #define HAVE_ARCH_SYS_PAUSE #endif /* __KERNEL__ */ diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h --- a/include/asm-ia64/spinlock.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/spinlock.h Sat Sep 21 21:25:45 2002 @@ -108,7 +108,8 @@ } rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } -#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) +#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) +#define rwlock_is_locked(x) (*(volatile int *) (x) != 0) #define _raw_read_lock(rw) \ do { \ diff -Nru a/include/asm-ia64/suspend.h b/include/asm-ia64/suspend.h --- a/include/asm-ia64/suspend.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/suspend.h Sat Sep 21 21:25:45 2002 @@ -0,0 +1 @@ +/* dummy (must be non-empty to prevent prejudicial removal...) */ diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h --- a/include/asm-ia64/system.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/system.h Sat Sep 21 21:25:45 2002 @@ -148,8 +148,8 @@ "cmp.ne p6,p7=%1,r0;;" \ "(p6) ssm psr.i;" \ "(p7) rsm psr.i;;" \ - "srlz.d" \ - : "=&r" (old_psr) : "r"((psr) & IA64_PSR_I) \ + "(p6) srlz.d" \ + : "=r" (old_psr) : "r"((psr) & IA64_PSR_I) \ : "p6", "p7", "memory"); \ if ((old_psr & IA64_PSR_I) && !(psr & IA64_PSR_I)) { \ __asm__ ("mov %0=ip" : "=r"(ip)); \ @@ -174,6 +174,13 @@ #define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") #define local_save_flags(flags) __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory") +#define irqs_disabled() \ +({ \ + unsigned long flags; \ + local_save_flags(flags); \ + (flags & IA64_PSR_I) == 0; \ +}) + /* * Force an unresolved reference if someone tries to use * ia64_fetch_and_add() with a bad value. @@ -367,14 +374,14 @@ extern void ia64_save_extra (struct task_struct *task); extern void ia64_load_extra (struct task_struct *task); -#if defined(CONFIG_SMP) && defined(CONFIG_PERFMON) +#ifdef CONFIG_PERFMON DECLARE_PER_CPU(int, pfm_syst_wide); # define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_wide) != 0) #else # define PERFMON_IS_SYSWIDE() (0) #endif -#define __switch_to(prev,next,last) do { \ +#define __switch_to(prev,next,last) do { \ if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)) \ || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE()) \ ia64_save_extra(prev); \ diff -Nru a/include/asm-ia64/timex.h b/include/asm-ia64/timex.h --- a/include/asm-ia64/timex.h Sat Sep 21 21:25:48 2002 +++ b/include/asm-ia64/timex.h Sat Sep 21 21:25:48 2002 @@ -3,14 +3,18 @@ /* * Copyright (C) 1998-2001 Hewlett-Packard Co - * Copyright (C) 1998-2001 David Mosberger-Tang + * David Mosberger-Tang */ /* * 2001/01/18 davidm Removed CLOCK_TICK_RATE. It makes no sense on IA-64. * Also removed cacheflush_time as it's entirely unused. */ +#include + typedef unsigned long cycles_t; + +#define CLOCK_TICK_RATE 100000000 static inline cycles_t get_cycles (void) diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h --- a/include/asm-ia64/tlb.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/tlb.h Sat Sep 21 21:25:45 2002 @@ -81,7 +81,7 @@ */ flush_tlb_mm(tlb->mm); } else if (unlikely (end - start >= 1024*1024*1024*1024UL - || REGION_NUMBER(start) != REGION_NUMBER(end - 1))) + || REGION_NUMBER(start) != REGION_NUMBER(end - 1))) { /* * If we flush more than a tera-byte or across regions, we're probably @@ -198,5 +198,9 @@ #define tlb_start_vma(tlb, vma) do { } while (0) #define tlb_end_vma(tlb, vma) do { } while (0) + +#define tlb_remove_tlb_entry(tlb, ptep, addr) __tlb_remove_tlb_entry(tlb, ptep, addr) +#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep) +#define pmd_free_tlb(tlb, ptep) __pmd_free_tlb(tlb, ptep) #endif /* _ASM_IA64_TLB_H */ diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h --- a/include/asm-ia64/unistd.h Sat Sep 21 21:25:45 2002 +++ b/include/asm-ia64/unistd.h Sat Sep 21 21:25:45 2002 @@ -225,7 +225,7 @@ #define __NR_security 1233 #define __NR_alloc_hugepages 1234 #define __NR_free_hugepages 1235 -/* 1236 currently unused */ +#define __NR_exit_group 1236 /* 1237 currently unused */ #define __NR_io_setup 1238 #define __NR_io_destroy 1239 diff -Nru a/include/linux/blkpg.h b/include/linux/blkpg.h --- a/include/linux/blkpg.h Sat Sep 21 21:25:45 2002 +++ b/include/linux/blkpg.h Sat Sep 21 21:25:45 2002 @@ -56,7 +56,7 @@ #ifdef __KERNEL__ -extern char * partition_name(kdev_t dev); +extern char * partition_name(dev_t dev); extern int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg); #endif /* __KERNEL__ */ diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h --- a/include/linux/cdrom.h Sat Sep 21 21:25:43 2002 +++ b/include/linux/cdrom.h Sat Sep 21 21:25:43 2002 @@ -730,9 +730,7 @@ struct cdrom_device_ops *ops; /* link to device_ops */ struct cdrom_device_info *next; /* next device_info for this major */ void *handle; /* driver-dependent data */ - devfs_handle_t de; /* real driver should create this */ struct device cdrom_driverfs_dev; /* driverfs implementation */ - int number; /* generic driver updates this */ /* specifications */ kdev_t dev; /* device number */ int mask; /* mask of capability: disables them */ @@ -786,18 +784,6 @@ extern int register_cdrom(struct cdrom_device_info *cdi); extern int unregister_cdrom(struct cdrom_device_info *cdi); - -static inline void devfs_plain_cdrom(struct cdrom_device_info *cdi, - struct block_device_operations *ops) -{ - char vname[23]; - - sprintf (vname, "cdroms/cdrom%d", cdi->number); - cdi->de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT, - major(cdi->dev), minor(cdi->dev), - S_IFBLK | S_IRUGO | S_IWUGO, - ops, NULL); -} typedef struct { int data; diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h --- a/include/linux/genhd.h Sat Sep 21 21:25:45 2002 +++ b/include/linux/genhd.h Sat Sep 21 21:25:45 2002 @@ -68,6 +68,7 @@ #define GENHD_FL_REMOVABLE 1 #define GENHD_FL_DRIVERFS 2 #define GENHD_FL_DEVFS 4 +#define GENHD_FL_CD 8 struct gendisk { int major; /* major number of driver */ @@ -80,6 +81,7 @@ struct gendisk *next; struct block_device_operations *fops; sector_t capacity; + struct list_head list; int flags; int number; /* devfs crap */ @@ -90,7 +92,7 @@ }; /* drivers/block/genhd.c */ -extern void add_gendisk(struct gendisk *gp); +extern void add_disk(struct gendisk *disk); extern void del_gendisk(struct gendisk *gp); extern void unlink_gendisk(struct gendisk *gp); extern struct gendisk *get_gendisk(kdev_t dev); @@ -258,6 +260,9 @@ extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern void update_partition(struct gendisk *disk, int part); + +/* will go away */ +extern void blk_set_probe(int major, struct gendisk *(p)(int)); static inline unsigned int disk_index (kdev_t dev) { diff -Nru a/include/linux/ide.h b/include/linux/ide.h --- a/include/linux/ide.h Sat Sep 21 21:25:45 2002 +++ b/include/linux/ide.h Sat Sep 21 21:25:45 2002 @@ -1072,6 +1072,8 @@ unsigned highmem : 1; /* can do full 32-bit dma */ unsigned no_dsc : 1; /* 0 default, 1 dsc_overlap disabled */ + struct device gendev; + void *hwif_data; /* extra hwif data */ } ide_hwif_t; @@ -1758,5 +1760,7 @@ extern spinlock_t ide_lock; #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable(); } while (0) + +extern struct bus_type ide_bus_type; #endif /* _IDE_H */ diff -Nru a/include/linux/mii.h b/include/linux/mii.h --- a/include/linux/mii.h Sat Sep 21 21:25:43 2002 +++ b/include/linux/mii.h Sat Sep 21 21:25:43 2002 @@ -118,10 +118,12 @@ struct ethtool_cmd; -int mii_link_ok (struct mii_if_info *mii); -int mii_nway_restart (struct mii_if_info *mii); -int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); -int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); +extern int mii_link_ok (struct mii_if_info *mii); +extern int mii_nway_restart (struct mii_if_info *mii); +extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); +extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); +extern void mii_check_link (struct mii_if_info *mii); +extern unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print); /* This structure is used in all SIOCxMIIxxx ioctl calls */ diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h --- a/include/linux/nbd.h Sat Sep 21 21:25:48 2002 +++ b/include/linux/nbd.h Sat Sep 21 21:25:48 2002 @@ -79,6 +79,7 @@ spinlock_t queue_lock; struct list_head queue_head; /* Requests are added here... */ struct semaphore tx_lock; + struct gendisk disk; }; #endif diff -Nru a/include/linux/ncp.h b/include/linux/ncp.h --- a/include/linux/ncp.h Sat Sep 21 21:25:43 2002 +++ b/include/linux/ncp.h Sat Sep 21 21:25:43 2002 @@ -30,6 +30,7 @@ }; #define NCP_REPLY (0x3333) +#define NCP_WATCHDOG (0x3E3E) #define NCP_POSITIVE_ACK (0x9999) struct ncp_reply_header { diff -Nru a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h --- a/include/linux/ncp_fs_sb.h Sat Sep 21 21:25:43 2002 +++ b/include/linux/ncp_fs_sb.h Sat Sep 21 21:25:43 2002 @@ -13,6 +13,8 @@ #ifdef __KERNEL__ +#include + #define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ struct ncp_server { @@ -24,6 +26,9 @@ __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; struct file *ncp_filp; /* File pointer to ncp socket */ + struct socket *ncp_sock;/* ncp socket */ + struct file *info_filp; + struct socket *info_sock; u8 sequence; u8 task; @@ -79,7 +84,53 @@ /* miscellaneous */ unsigned int flags; + + spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ + + void (*data_ready)(struct sock* sk, int len); + void (*error_report)(struct sock* sk); + void (*write_space)(struct sock* sk); /* STREAM mode only */ + struct { + struct tq_struct tq; /* STREAM/DGRAM: data/error ready */ + struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ + struct semaphore creq_sem; /* DGRAM only: lock accesses to rcv.creq */ + + unsigned int state; /* STREAM only: receiver state */ + struct { + __u32 magic __attribute__((packed)); + __u32 len __attribute__((packed)); + __u16 type __attribute__((packed)); + __u16 p1 __attribute__((packed)); + __u16 p2 __attribute__((packed)); + __u16 p3 __attribute__((packed)); + __u16 type2 __attribute__((packed)); + } buf; /* STREAM only: temporary buffer */ + unsigned char* ptr; /* STREAM only: pointer to data */ + size_t len; /* STREAM only: length of data to receive */ + } rcv; + struct { + struct list_head requests; /* STREAM only: queued requests */ + struct tq_struct tq; /* STREAM only: transmitter ready */ + struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */ + } tx; + struct timer_list timeout_tm; /* DGRAM only: timeout timer */ + struct tq_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ + int timeout_last; /* DGRAM only: current timeout length */ + int timeout_retries; /* DGRAM only: retries left */ + struct { + size_t len; + __u8 data[128]; + } unexpected_packet; }; + +extern void ncp_tcp_rcv_proc(void *server); +extern void ncp_tcp_tx_proc(void *server); +extern void ncpdgram_rcv_proc(void *server); +extern void ncpdgram_timeout_proc(void *server); +extern void ncpdgram_timeout_call(unsigned long server); +extern void ncp_tcp_data_ready(struct sock* sk, int len); +extern void ncp_tcp_write_space(struct sock* sk); +extern void ncp_tcp_error_report(struct sock* sk); #define NCP_FLAG_UTF8 1 diff -Nru a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h --- a/include/linux/ncp_mount.h Sat Sep 21 21:25:48 2002 +++ b/include/linux/ncp_mount.h Sat Sep 21 21:25:48 2002 @@ -11,7 +11,7 @@ #include #include -#define NCP_MOUNT_VERSION 3 +#define NCP_MOUNT_VERSION 3 /* Binary */ /* Values for flags */ #define NCP_MOUNT_SOFT 0x0001 @@ -41,7 +41,7 @@ __kernel_mode_t dir_mode; }; -#define NCP_MOUNT_VERSION_V4 (4) +#define NCP_MOUNT_VERSION_V4 (4) /* Binary or text */ struct ncp_mount_data_v4 { int version; @@ -66,6 +66,8 @@ unsigned long dir_mode; }; +#define NCP_MOUNT_VERSION_V5 (5) /* Text only */ + #ifdef __KERNEL__ struct ncp_mount_data_kernel { @@ -83,6 +85,7 @@ __kernel_gid32_t gid; __kernel_mode_t file_mode; __kernel_mode_t dir_mode; + int info_fd; }; #endif /* __KERNEL__ */ diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h --- a/include/linux/raid/md.h Sat Sep 21 21:25:45 2002 +++ b/include/linux/raid/md.h Sat Sep 21 21:25:45 2002 @@ -62,10 +62,9 @@ extern int md_size[MAX_MD_DEVS]; -extern char * partition_name (kdev_t dev); extern inline char * bdev_partition_name (struct block_device *bdev) { - return partition_name(bdev ? to_kdev_t(bdev->bd_dev) : NODEV); + return partition_name(bdev ? bdev->bd_dev : 0); } extern int register_md_personality (int p_num, mdk_personality_t *p); extern int unregister_md_personality (int p_num); diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h --- a/include/linux/raid/md_k.h Sat Sep 21 21:25:45 2002 +++ b/include/linux/raid/md_k.h Sat Sep 21 21:25:45 2002 @@ -299,16 +299,6 @@ #define THREAD_WAKEUP 0 -#define MAX_DISKNAME_LEN 64 - -typedef struct dev_name_s { - struct list_head list; - kdev_t dev; - char namebuf [MAX_DISKNAME_LEN]; - char *name; -} dev_name_t; - - #define __wait_event_lock_irq(wq, condition, lock) \ do { \ wait_queue_t __wait; \ diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Sat Sep 21 21:25:43 2002 +++ b/kernel/ksyms.c Sat Sep 21 21:25:43 2002 @@ -576,7 +576,7 @@ EXPORT_SYMBOL(fasync_helper); EXPORT_SYMBOL(kill_fasync); -EXPORT_SYMBOL(disk_name); /* for md.c */ +EXPORT_SYMBOL(partition_name); /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Sat Sep 21 21:25:48 2002 +++ b/kernel/sched.c Sat Sep 21 21:25:48 2002 @@ -940,8 +940,17 @@ struct list_head *queue; int idx; - if (unlikely(in_atomic())) - BUG(); + /* + * Test if we are atomic. Since do_exit() needs to call into + * schedule() atomically, we ignore that path for now. + * Otherwise, whine if we are scheduling when we should not be. + */ + if (likely(current->state != TASK_ZOMBIE)) { + if (unlikely(in_atomic())) { + printk(KERN_ERR "bad: scheduling while atomic!\n"); + dump_stack(); + } + } #if CONFIG_DEBUG_HIGHMEM check_highmem_ptes(); diff -Nru a/kernel/sys.c b/kernel/sys.c --- a/kernel/sys.c Sat Sep 21 21:25:45 2002 +++ b/kernel/sys.c Sat Sep 21 21:25:45 2002 @@ -412,9 +412,10 @@ #ifdef CONFIG_SOFTWARE_SUSPEND case LINUX_REBOOT_CMD_SW_SUSPEND: - if(!software_suspend_enabled) + if (!software_suspend_enabled) { + unlock_kernel(); return -EAGAIN; - + } software_suspend(); do_exit(0); break; diff -Nru a/mm/numa.c b/mm/numa.c --- a/mm/numa.c Sat Sep 21 21:25:48 2002 +++ b/mm/numa.c Sat Sep 21 21:25:48 2002 @@ -27,6 +27,7 @@ { unsigned long size; + pgdat = &contig_page_data; contig_page_data.node_id = 0; contig_page_data.node_start_pfn = node_start_pfn; calculate_totalpages (&contig_page_data, zones_size, zholes_size); diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c --- a/net/irda/af_irda.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/af_irda.c Sat Sep 21 21:25:45 2002 @@ -509,7 +509,7 @@ notify_t notify; if (self->lsap) { - WARNING(__FUNCTION__ "(), busy!\n"); + WARNING("%s(), busy!\n", __FUNCTION__); return -EBUSY; } @@ -521,7 +521,7 @@ self->lsap = irlmp_open_lsap(LSAP_CONNLESS, ¬ify, pid); if (self->lsap == NULL) { - IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate LSAP!\n"); + IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __FUNCTION__); return -ENOMEM; } @@ -542,12 +542,12 @@ */ static int irda_find_lsap_sel(struct irda_sock *self, char *name) { - IRDA_DEBUG(2, __FUNCTION__ "(%p, %s)\n", self, name); + IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name); ASSERT(self != NULL, return -1;); if (self->iriap) { - WARNING("%s: busy with a previous query\n", __FUNCTION__); + WARNING("%s(): busy with a previous query\n", __FUNCTION__); return -EBUSY; } @@ -582,8 +582,8 @@ /* Get the remote TSAP selector */ switch (self->ias_result->type) { case IAS_INTEGER: - IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n", - self->ias_result->t.integer); + IRDA_DEBUG(4, "%s() int=%d\n", + __FUNCTION__, self->ias_result->t.integer); if (self->ias_result->t.integer != -1) self->dtsap_sel = self->ias_result->t.integer; @@ -592,7 +592,7 @@ break; default: self->dtsap_sel = 0; - IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n"); + IRDA_DEBUG(0, "%s(), bad type!\n", __FUNCTION__); break; } if (self->ias_result) @@ -630,7 +630,7 @@ __u32 daddr = DEV_ADDR_ANY; /* Address we found the service on */ __u8 dtsap_sel = 0x0; /* TSAP associated with it */ - IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name); + IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name); ASSERT(self != NULL, return -1;); @@ -652,8 +652,8 @@ /* Try the address in the log */ self->daddr = discoveries[i].daddr; self->saddr = 0x0; - IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n", - self->daddr); + IRDA_DEBUG(1, "%s(), trying daddr = %08x\n", + __FUNCTION__, self->daddr); /* Query remote LM-IAS for this service */ err = irda_find_lsap_sel(self, name); @@ -661,9 +661,8 @@ case 0: /* We found the requested service */ if(daddr != DEV_ADDR_ANY) { - IRDA_DEBUG(1, __FUNCTION__ - "(), discovered service ''%s'' in two different devices !!!\n", - name); + IRDA_DEBUG(1, "%s(), discovered service ''%s'' in two different devices !!!\n", + __FUNCTION__, name); self->daddr = DEV_ADDR_ANY; kfree(discoveries); return(-ENOTUNIQ); @@ -677,8 +676,7 @@ break; default: /* Something bad did happen :-( */ - IRDA_DEBUG(0, __FUNCTION__ - "(), unexpected IAS query failure\n"); + IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __FUNCTION__); self->daddr = DEV_ADDR_ANY; kfree(discoveries); return(-EHOSTUNREACH); @@ -690,9 +688,8 @@ /* Check out what we found */ if(daddr == DEV_ADDR_ANY) { - IRDA_DEBUG(1, __FUNCTION__ - "(), cannot discover service ''%s'' in any device !!!\n", - name); + IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n", + __FUNCTION__, name); self->daddr = DEV_ADDR_ANY; return(-EADDRNOTAVAIL); } @@ -702,9 +699,8 @@ self->saddr = 0x0; self->dtsap_sel = dtsap_sel; - IRDA_DEBUG(1, __FUNCTION__ - "(), discovered requested service ''%s'' at address %08x\n", - name, self->daddr); + IRDA_DEBUG(1, "%s(), discovered requested service ''%s'' at address %08x\n", + __FUNCTION__, name, self->daddr); return 0; } @@ -735,8 +731,8 @@ saddr.sir_addr = self->saddr; } - IRDA_DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel); - IRDA_DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr); + IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __FUNCTION__, saddr.sir_lsap_sel); + IRDA_DEBUG(1, "%s(), addr = %08x\n", __FUNCTION__, saddr.sir_addr); /* uaddr_len come to us uninitialised */ *uaddr_len = sizeof (struct sockaddr_irda); @@ -755,7 +751,7 @@ { struct sock *sk = sock->sk; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) && (sk->type != SOCK_DGRAM)) @@ -786,7 +782,7 @@ ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); + IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self); if (addr_len != sizeof(struct sockaddr_irda)) return -EINVAL; @@ -796,8 +792,7 @@ if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA)) { self->pid = addr->sir_lsap_sel; if (self->pid & 0x80) { - IRDA_DEBUG(0, __FUNCTION__ - "(), extension in PID not supp!\n"); + IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__); return -EOPNOTSUPP; } err = irda_open_lsap(self, self->pid); @@ -842,7 +837,7 @@ struct sk_buff *skb; int err; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, "%s()\n", __FUNCTION__); ASSERT(self != NULL, return -1;); @@ -918,7 +913,7 @@ /* Now attach up the new socket */ new->tsap = irttp_dup(self->tsap, new); if (!new->tsap) { - IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n"); + IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__); return -1; } @@ -977,7 +972,7 @@ struct irda_sock *self = irda_sk(sk); int err; - IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self); + IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self); /* Don't allow connect for Ultra sockets */ if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA)) @@ -1007,19 +1002,18 @@ /* Try to find one suitable */ err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); if (err) { - IRDA_DEBUG(0, __FUNCTION__ - "(), auto-connect failed!\n"); + IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __FUNCTION__); return err; } } else { /* Use the one provided by the user */ self->daddr = addr->sir_addr; - IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr); + IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr); /* Query remote LM-IAS */ err = irda_find_lsap_sel(self, addr->sir_name); if (err) { - IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n"); + IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__); return err; } } @@ -1037,7 +1031,7 @@ self->saddr, self->daddr, NULL, self->max_sdu_size_rx, NULL); if (err) { - IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n"); + IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__); return err; } diff -Nru a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c --- a/net/irda/ircomm/ircomm_core.c Sat Sep 21 21:25:43 2002 +++ b/net/irda/ircomm/ircomm_core.c Sat Sep 21 21:25:43 2002 @@ -63,7 +63,7 @@ { ircomm = hashbin_new(HB_LOCK); if (ircomm == NULL) { - ERROR(__FUNCTION__ "(), can't allocate hashbin!\n"); + ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__); return -ENOMEM; } diff -Nru a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c --- a/net/irda/ircomm/ircomm_lmp.c Sat Sep 21 21:25:43 2002 +++ b/net/irda/ircomm/ircomm_lmp.c Sat Sep 21 21:25:43 2002 @@ -228,7 +228,7 @@ } ret = irlmp_data_request(self->lsap, skb); if (ret) { - ERROR(__FUNCTION__ "(), failed\n"); + ERROR("%s(), failed\n", __FUNCTION__); dev_kfree_skb(skb); } diff -Nru a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c --- a/net/irda/ircomm/ircomm_param.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/ircomm/ircomm_param.c Sat Sep 21 21:25:45 2002 @@ -154,7 +154,7 @@ count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb), &ircomm_param_info); if (count < 0) { - WARNING(__FUNCTION__ "(), no room for parameter!\n"); + WARNING("%s(), no room for parameter!\n", __FUNCTION__); spin_unlock_irqrestore(&self->spinlock, flags); return -1; } diff -Nru a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c --- a/net/irda/ircomm/ircomm_ttp.c Sat Sep 21 21:25:48 2002 +++ b/net/irda/ircomm/ircomm_ttp.c Sat Sep 21 21:25:48 2002 @@ -146,7 +146,7 @@ ret = irttp_data_request(self->tsap, skb); if (ret) { - ERROR(__FUNCTION__ "(), failed\n"); + ERROR("%s(), failed\n", __FUNCTION__); dev_kfree_skb(skb); } @@ -192,7 +192,7 @@ ASSERT(qos != NULL, return;); if (max_sdu_size != TTP_SAR_DISABLE) { - ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n"); + ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__); dev_kfree_skb(skb); return; } @@ -229,7 +229,7 @@ ASSERT(qos != NULL, return;); if (max_sdu_size != TTP_SAR_DISABLE) { - ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n"); + ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__); dev_kfree_skb(skb); return; } diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c --- a/net/irda/ircomm/ircomm_tty.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/ircomm/ircomm_tty.c Sat Sep 21 21:25:45 2002 @@ -92,7 +92,7 @@ { ircomm_tty = hashbin_new(HB_LOCK); if (ircomm_tty == NULL) { - ERROR(__FUNCTION__ "(), can't allocate hashbin!\n"); + ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__); return -ENOMEM; } @@ -135,7 +135,7 @@ driver.read_proc = ircomm_tty_read_proc; #endif /* CONFIG_PROC_FS */ if (tty_register_driver(&driver)) { - ERROR(__FUNCTION__ "Couldn't register serial driver\n"); + ERROR("%s(): Couldn't register serial driver\n", __FUNCTION__); return -1; } return 0; @@ -168,7 +168,7 @@ ret = tty_unregister_driver(&driver); if (ret) { - ERROR(__FUNCTION__ "(), failed to unregister driver\n"); + ERROR("%s(), failed to unregister driver\n", __FUNCTION__); return; } @@ -223,7 +223,7 @@ /* Connect IrCOMM link with remote device */ ret = ircomm_tty_attach_cable(self); if (ret < 0) { - ERROR(__FUNCTION__ "(), error attaching cable!\n"); + ERROR("%s(), error attaching cable!\n", __FUNCTION__); return ret; } @@ -410,7 +410,7 @@ /* No, so make new instance */ self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL); if (self == NULL) { - ERROR(__FUNCTION__"(), kmalloc failed!\n"); + ERROR("%s(), kmalloc failed!\n", __FUNCTION__); MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -563,9 +563,8 @@ } if (--self->open_count < 0) { - ERROR(__FUNCTION__ - "(), bad serial port count for ttys%d: %d\n", - self->line, self->open_count); + ERROR("%s(), bad serial port count for ttys%d: %d\n", + __FUNCTION__, self->line, self->open_count); self->open_count = 0; } if (self->open_count) { diff -Nru a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c --- a/net/irda/ircomm/ircomm_tty_attach.c Sat Sep 21 21:25:48 2002 +++ b/net/irda/ircomm/ircomm_tty_attach.c Sat Sep 21 21:25:48 2002 @@ -601,8 +601,7 @@ self->saddr = info->saddr; if (self->iriap) { - WARNING(__FUNCTION__ - "(), busy with a previous query\n"); + WARNING("%s(), busy with a previous query\n", __FUNCTION__); return -EBUSY; } @@ -659,8 +658,7 @@ self->saddr = info->saddr; if (self->iriap) { - WARNING(__FUNCTION__ - "(), busy with a previous query\n"); + WARNING("%s(), busy with a previous query\n", __FUNCTION__); return -EBUSY; } @@ -728,8 +726,7 @@ switch (event) { case IRCOMM_TTY_GOT_PARAMETERS: if (self->iriap) { - WARNING(__FUNCTION__ - "(), busy with a previous query\n"); + WARNING("%s(), busy with a previous query\n", __FUNCTION__); return -EBUSY; } diff -Nru a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c --- a/net/irda/ircomm/ircomm_tty_ioctl.c Sat Sep 21 21:25:43 2002 +++ b/net/irda/ircomm/ircomm_tty_ioctl.c Sat Sep 21 21:25:43 2002 @@ -95,7 +95,7 @@ self->settings.flow_control |= IRCOMM_RTS_CTS_IN; /* This got me. Bummer. Jean II */ if (self->service_type == IRCOMM_3_WIRE_RAW) - WARNING(__FUNCTION__ "(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n"); + WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__); } else { self->flags &= ~ASYNC_CTS_FLOW; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; diff -Nru a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c --- a/net/irda/irlan/irlan_client.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/irlan/irlan_client.c Sat Sep 21 21:25:45 2002 @@ -367,7 +367,7 @@ ASSERT(self->magic == IRLAN_MAGIC, return;); if (!skb) { - ERROR( __FUNCTION__ "(), Got NULL skb!\n"); + ERROR("%s(), Got NULL skb!\n", __FUNCTION__); return; } frame = skb->data; diff -Nru a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c --- a/net/irda/irlan/irlan_client_event.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/irlan/irlan_client_event.c Sat Sep 21 21:25:45 2002 @@ -100,8 +100,7 @@ switch (event) { case IRLAN_DISCOVERY_INDICATION: if (self->client.iriap) { - WARNING(__FUNCTION__ - "(), busy with a previous query\n"); + WARNING("%s(), busy with a previous query\n", __FUNCTION__); return -EBUSY; } diff -Nru a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c --- a/net/irda/irlan/irlan_common.c Sat Sep 21 21:25:45 2002 +++ b/net/irda/irlan/irlan_common.c Sat Sep 21 21:25:45 2002 @@ -424,7 +424,7 @@ IRDA_DEBUG(2, __FUNCTION__ "(), IrLMP connect failed\n"); break; default: - ERROR(__FUNCTION__ "(), Unknown disconnect reason\n"); + ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__); break; }