From ed092cbc837297e6826734760d8aacc15ea0b1f0 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 6 Jan 2005 05:57:16 -0500 Subject: [PATCH] export print_sense_internal Currently, we have scsi_print_sense and scsi_print_req_sense, but the linux-iscsi driver receives async messages from a target that may contain SCSI sense data and these messages are not tied to any specific command. So that we can use the scsi-ml sense printing capabilities the attached patch exports exports print_sense_internal and renames it to __scsi_print_sense. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- include/scsi/scsi_dbg.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 38fbb68c9b87..12e90934a7a8 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -8,6 +8,9 @@ extern void scsi_print_command(struct scsi_cmnd *); extern void __scsi_print_command(unsigned char *); extern void scsi_print_sense(const char *, struct scsi_cmnd *); extern void scsi_print_req_sense(const char *, struct scsi_request *); +extern void __scsi_print_sense(const char *name, + const unsigned char *sense_buffer, + int sense_len); extern void scsi_print_driverbyte(int); extern void scsi_print_hostbyte(int); extern void scsi_print_status(unsigned char); -- cgit v1.2.3 From b733ce2121acfea01efbd9af7adfc9cd3953e349 Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Fri, 7 Jan 2005 00:17:45 -0800 Subject: [IA64] add hpzx1_swiotlb machine-vector I was in need of a 3.3V/dual-voltage-capable PCI sound-card and, as luck would have it, the only card of that sort in the local computer store was one that _still_ has a DMA engine that cannot even DMA to all 32 bits (it's limited to 28 bits). Hard to believe, but true (the card in question is a "SoundBlaster Live! 24-bit" with a CA0106 chip; stay away from that one if you can...). Anyhow, since I don't like it when PCI cards don't work in my machine, I created the attached patch which adds a new machine-vector to enable support of such broken cards. With the patch applied, you can either configure the kernel for "HP-zx1/sx1000+swiotlb" or configure for "generic" and boot with option "machvec=hpzx1_swiotlb" to enable support for broken PCI devices. The patch works as follows: the new machvec implements a I/O MMU which will use the hardware I/O MMU whenever possible but fall back on the software I/O TLB when encountering a device that can't be supported by the hardware I/O MMU. Fortunately, we don't have to mess with MAX_DMA_ADDRESS or create a new zone: the software I/O TLB allocates its memory as low as possible and early in the boot-process, so on any machine with low memory, we're pretty much guaranteed that we'll get a reasonable amount of low memory, which is all we need to properly support broken PCI cards. Note that I made a small change to swiotlb.c: I added a swiotlb_init_with_default_size() function to let the new I/O MMU initialize the software I/O TLB with less than 64MB (which is way too much for the limited uses we'll see for the broken PCI devices; for example, the CA0106 chip allocates only coherent buffers of about 128KB). The patch has been tested on a zx1 machine in the generic, hpzx1, and hpzx1_swiotlb configuration. Thanks to Alex Williamson for the suggestion of doing this via a completely separate machvec. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- Documentation/kernel-parameters.txt | 6 +++++- arch/ia64/Kconfig | 24 +++++++++++++++++------- arch/ia64/Kconfig.debug | 2 +- arch/ia64/Makefile | 2 ++ arch/ia64/hp/common/Makefile | 2 ++ arch/ia64/hp/zx1/Makefile | 2 +- arch/ia64/kernel/Makefile | 1 + arch/ia64/kernel/acpi.c | 2 ++ arch/ia64/kernel/setup.c | 25 +++++++++++++++++++++++-- arch/ia64/lib/swiotlb.c | 16 +++++++++++++--- drivers/char/agp/Kconfig | 2 +- include/asm-ia64/machvec.h | 2 ++ include/asm-ia64/numnodes.h | 2 +- 13 files changed, 71 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 46f59e879f54..01f874edd532 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -673,7 +673,11 @@ running once the system is up. mac53c9x= [HW,SCSI] Format: ,,,,,,, - + + machvec= [IA64] + Force the use of a particular machine-vector (machvec) in a generic + kernel. Example: machvec=hpzx1_swiotlb + mad16= [HW,OSS] Format: ,,,,,, diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 480ab214db61..4a51bf17c058 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -61,11 +61,12 @@ config IA64_GENERIC will run on any supported IA-64 system. However, if you configure a kernel for your specific system, it will be faster and smaller. - generic For any supported IA-64 system - DIG-compliant For DIG ("Developer's Interface Guide") compliant systems - HP-zx1/sx1000 For HP systems - SGI-SN2 For SGI Altix systems - Ski-simulator For the HP simulator + generic For any supported IA-64 system + DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + HP-zx1/sx1000 For HP systems + HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. + SGI-SN2 For SGI Altix systems + Ski-simulator For the HP simulator If you don't know what to do, choose "generic". @@ -78,6 +79,15 @@ config IA64_HP_ZX1 Build a kernel that runs on HP zx1 and sx1000 systems. This adds support for the HP I/O MMU. +config IA64_HP_ZX1_SWIOTLB + bool "HP-zx1/sx1000 with software I/O TLB" + help + Build a kernel that runs on HP zx1 and sx1000 systems even when they + have broken PCI devices which cannot DMA to full 32 bits. Apart + from support for the HP I/O MMU, this includes support for the software + I/O TLB, which allows supporting the broken devices at the expense of + wasting some kernel memory (about 2MB by default). + config IA64_SGI_SN2 bool "SGI-SN2" help @@ -184,7 +194,7 @@ config VIRTUAL_MEM_MAP config DISCONTIGMEM bool "Discontiguous memory support" - depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1) && NUMA && VIRTUAL_MEM_MAP + depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory, @@ -321,7 +331,7 @@ menu "Power management and ACPI" config PM bool "Power Management support" - depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 + depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB default y help "Power Management" means that parts of your computer are shut diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug index 19edc8b2c61d..de9d507ba0fd 100644 --- a/arch/ia64/Kconfig.debug +++ b/arch/ia64/Kconfig.debug @@ -16,7 +16,7 @@ config IA64_GRANULE_16MB config IA64_GRANULE_64MB bool "64MB" - depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2) + depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_SGI_SN2) endchoice diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 2932ac71bd0b..c0b3d95d0f81 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -57,11 +57,13 @@ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ +core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ +drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile index e7c7133c7ca7..f61a60057ff7 100644 --- a/arch/ia64/hp/common/Makefile +++ b/arch/ia64/hp/common/Makefile @@ -6,3 +6,5 @@ # obj-y := sba_iommu.o +obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += hwsw_iommu.o +obj-$(CONFIG_IA64_GENERIC) += hwsw_iommu.o diff --git a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile index 64e39aa82a3f..61e878729d1e 100644 --- a/arch/ia64/hp/zx1/Makefile +++ b/arch/ia64/hp/zx1/Makefile @@ -5,4 +5,4 @@ # Copyright (C) Alex Williamson (alex_williamson@hp.com) # -obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o +obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o hpzx1_swiotlb_machvec.o diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 12d8bf976cc2..c1a02bbc252c 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -12,6 +12,7 @@ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o i obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o +obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index d9f35a76c3fd..4c7f1be5ef3b 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -113,6 +113,8 @@ acpi_get_sysname (void) return "hpsim"; # elif defined (CONFIG_IA64_HP_ZX1) return "hpzx1"; +# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB) + return "hpzx1_swiotlb"; # elif defined (CONFIG_IA64_SGI_SN2) return "sn2"; # elif defined (CONFIG_IA64_DIG) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 7b2033bf0954..d35bda31d238 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -1,7 +1,7 @@ /* * Architecture-specific setup. * - * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co + * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co * David Mosberger-Tang * Stephane Eranian * Copyright (C) 2000, Rohit Seth @@ -312,7 +312,28 @@ setup_arch (char **cmdline_p) io_port_init(); #ifdef CONFIG_IA64_GENERIC - machvec_init(acpi_get_sysname()); + { + const char *mvec_name = strstr (*cmdline_p, "machvec="); + char str[64]; + + if (mvec_name) { + const char *end; + size_t len; + + mvec_name += 8; + end = strchr (mvec_name, ' '); + if (end) + len = end - mvec_name; + else + len = strlen (mvec_name); + len = min(len, sizeof (str) - 1); + strncpy (str, mvec_name, len); + str[len] = '\0'; + mvec_name = str; + } else + mvec_name = acpi_get_sysname(); + machvec_init(mvec_name); + } #endif if (early_console_setup(*cmdline_p) == 0) diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c index e4770828db59..d38b01538184 100644 --- a/arch/ia64/lib/swiotlb.c +++ b/arch/ia64/lib/swiotlb.c @@ -61,9 +61,8 @@ static char *io_tlb_start, *io_tlb_end; /* * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and * io_tlb_end. This is command line adjustable via setup_io_tlb_npages. - * Default to 64MB. */ -static unsigned long io_tlb_nslabs = 32768; +static unsigned long io_tlb_nslabs; /* * When the IOMMU overflows we return a fallback buffer. This sets the size. @@ -113,10 +112,15 @@ __setup("swiotlb=", setup_io_tlb_npages); * structures for the software IO TLB used to implement the PCI DMA API. */ void -swiotlb_init(void) +swiotlb_init_with_default_size (size_t default_size) { unsigned long i; + if (!io_tlb_nslabs) { + io_tlb_nslabs = (default_size >> PAGE_SHIFT); + io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); + } + /* * Get IO TLB memory from the low pages */ @@ -145,6 +149,12 @@ swiotlb_init(void) virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); } +void +swiotlb_init (void) +{ + swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ +} + static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr) { diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index d9b4a6e7fb94..fe0cb7bf529e 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -144,7 +144,7 @@ config AGP_I460 config AGP_HP_ZX1 tristate "HP ZX1 chipset AGP support" - depends on AGP && (IA64_HP_ZX1 || IA64_GENERIC) + depends on AGP && (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC) help This option gives you AGP GART support for the HP ZX1 chipset for IA64 processors. diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index 0749f1a1454e..f21fbed79643 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -94,6 +94,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include # elif defined (CONFIG_IA64_HP_ZX1) # include +# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB) +# include # elif defined (CONFIG_IA64_SGI_SN2) # include # elif defined (CONFIG_IA64_GENERIC) diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h index 4fed3ac3c442..21cff4da5485 100644 --- a/include/asm-ia64/numnodes.h +++ b/include/asm-ia64/numnodes.h @@ -4,7 +4,7 @@ #ifdef CONFIG_IA64_DIG /* Max 8 Nodes */ #define NODES_SHIFT 3 -#elif defined(CONFIG_IA64_HP_ZX1) +#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB) /* Max 32 Nodes */ #define NODES_SHIFT 5 #elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) -- cgit v1.2.3 From 9521392a2fbb55db92f12741ae329efd121b0d81 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Sun, 9 Jan 2005 22:56:57 -0600 Subject: [PATCH] cciss update to version 2.6.4 This patch removes support for 2 controllers that were recently cancelled and it adds support for the P600, a cciss based SAS controller due to ship in late March/early April '05. Neither of these controllers have made it to the field. Signed-off-by: Mike Miller Signed-off-by: James Bottomley --- Documentation/cciss.txt | 3 +-- drivers/block/cciss.c | 17 +++++++---------- include/linux/pci_ids.h | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index 7d8f67e5c837..5bbc54667aa3 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt @@ -14,8 +14,7 @@ This driver is known to work with the following cards: * SA 6400 * SA 6400 U320 Expansion Module * SA 6i - * SA 6422 - * SA V100 + * SA P600 If nodes are not already created in the /dev/cciss directory diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 97bf2d4b9207..30ae21daa7ba 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -46,14 +46,14 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.6.2)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2) +#define DRIVER_NAME "HP CISS Driver (v 2.6.4)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,4) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2"); +MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.4"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i V100"); + " SA6i P600"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -80,10 +80,8 @@ const struct pci_device_id cciss_pci_device_id[] = { 0x0E11, 0x409D, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x4091, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409E, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS, - 0x103C, 0x3211, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, + 0x103C, 0x3225, 0, 0, 0}, {0,} }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); @@ -104,8 +102,7 @@ static struct board_type products[] = { { 0x409C0E11, "Smart Array 6400", &SA5_access}, { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, { 0x40910E11, "Smart Array 6i", &SA5_access}, - { 0x409E0E11, "Smart Array 6422", &SA5_access}, - { 0x3211103C, "Smart Array V100", &SA5_access}, + { 0x3225103C, "Smart Array P600", &SA5_access}, }; /* How long to wait (in millesconds) for board to go into simple mode */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d607c59b3851..6c55342f5865 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -690,7 +690,7 @@ #define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c #define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 #define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 -#define PCI_DEVICE_ID_HP_CISS 0x3210 +#define PCI_DEVICE_ID_HP_CISSA 0x3220 #define PCI_VENDOR_ID_PCTECH 0x1042 #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 -- cgit v1.2.3 From 872a9465d098476c5cf2e21c53deb70be31b3270 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Sun, 9 Jan 2005 22:23:32 -0800 Subject: [IA64] implements the features required for the HAVE_PCI_LEGACY code in sysfs This patch implements the features required for the HAVE_PCI_LEGACY code in sysfs. It allows userspace applications to access legacy I/O ports an memory space using files in sysfs on a per-bus basis. Tested on sn2, but it *should* work on other ia64 platforms as well (though zx1 will probably need machine vectors to do routing of non-base busses). Signed-off-by: Jesse Barnes Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 114 +++++++++++++++++++++++++++++++++++++++- arch/ia64/sn/pci/pci_dma.c | 64 ++++++++++++++++++++++ include/asm-ia64/machvec.h | 24 +++++++++ include/asm-ia64/machvec_init.h | 3 ++ include/asm-ia64/machvec_sn2.h | 6 +++ include/asm-ia64/pci.h | 14 +++++ include/asm-ia64/sn/sn_sal.h | 46 ++++++++++++++++ 7 files changed, 270 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 01f8eabf3636..edc8915bb415 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -6,6 +6,7 @@ * Copyright (C) 2002 Hewlett-Packard Co * David Mosberger-Tang * Bjorn Helgaas + * Copyright (C) 2004 Silicon Graphics, Inc. * * Note: Above list of copyright holders is incomplete... */ @@ -526,7 +527,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, * 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); + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); if (write_combine) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -540,6 +541,117 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, return 0; } +/** + * pci_mmap_legacy_page_range - map legacy memory space to userland + * @bus: bus whose legacy space we're mapping + * @vma: vma passed in by mmap + * + * Map legacy memory space for this device back to userspace using a machine + * vector to get the base address. + */ +int +pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) +{ + char *addr; + + addr = pci_get_legacy_mem(bus); + if (IS_ERR(addr)) + return PTR_ERR(addr); + + vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); + + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +/** + * ia64_pci_get_legacy_mem - generic legacy mem routine + * @bus: bus to get legacy memory base address for + * + * Find the base of legacy memory for @bus. This is typically the first + * megabyte of bus address space for @bus or is simply 0 on platforms whose + * chipsets support legacy I/O and memory routing. Returns the base address + * or an error pointer if an error occurred. + * + * This is the ia64 generic version of this routine. Other platforms + * are free to override it with a machine vector. + */ +char *ia64_pci_get_legacy_mem(struct pci_bus *bus) +{ + return (char *)__IA64_UNCACHED_OFFSET; +} + +/** + * ia64_pci_legacy_read - read from legacy I/O space + * @bus: bus to read + * @port: legacy port value + * @val: caller allocated storage for returned value + * @size: number of bytes to read + * + * Simply reads @size bytes from @port and puts the result in @val. + * + * Again, this (and the write routine) are generic versions that can be + * overridden by the platform. This is necessary on platforms that don't + * support legacy I/O routing or that hard fail on legacy I/O timeouts. + */ +int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) +{ + int ret = size; + + switch (size) { + case 1: + *val = inb(port); + break; + case 2: + *val = inw(port); + break; + case 4: + *val = inl(port); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * ia64_pci_legacy_write - perform a legacy I/O write + * @bus: bus pointer + * @port: port to write + * @val: value to write + * @size: number of bytes to write from @val + * + * Simply writes @size bytes of @val to @port. + */ +int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size) +{ + int ret = 0; + + switch (size) { + case 1: + outb(val, port); + break; + case 2: + outw(val, port); + break; + case 4: + outl(val, port); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + /** * pci_cacheline_size - determine cacheline size for PCI devices * @dev: void diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 71f311dc04c3..4187f920d26d 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -475,3 +475,67 @@ EXPORT_SYMBOL(sn_pci_alloc_consistent); EXPORT_SYMBOL(sn_pci_free_consistent); EXPORT_SYMBOL(sn_pci_dma_supported); EXPORT_SYMBOL(sn_dma_mapping_error); + +char *sn_pci_get_legacy_mem(struct pci_bus *bus) +{ + if (!SN_PCIBUS_BUSSOFT(bus)) + return ERR_PTR(-ENODEV); + + return (char *)(SN_PCIBUS_BUSSOFT(bus)->bs_legacy_mem | __IA64_UNCACHED_OFFSET); +} + +int sn_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size) +{ + unsigned long addr; + int ret; + + if (!SN_PCIBUS_BUSSOFT(bus)) + return -ENODEV; + + addr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET; + addr += port; + + ret = ia64_sn_probe_mem(addr, (long)size, (void *)val); + + if (ret == 2) + return -EINVAL; + + if (ret == 1) + *val = -1; + + return size; +} + +int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size) +{ + int ret = size; + unsigned long paddr; + unsigned long *addr; + + if (!SN_PCIBUS_BUSSOFT(bus)) { + ret = -ENODEV; + goto out; + } + + /* Put the phys addr in uncached space */ + paddr = SN_PCIBUS_BUSSOFT(bus)->bs_legacy_io | __IA64_UNCACHED_OFFSET; + paddr += port; + addr = (unsigned long *)paddr; + + switch (size) { + case 1: + *(volatile u8 *)(addr) = (u8)(val); + break; + case 2: + *(volatile u16 *)(addr) = (u16)(val); + break; + case 4: + *(volatile u32 *)(addr) = (u32)(val); + break; + default: + ret = -EINVAL; + break; + } + out: + return ret; +} diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index f21fbed79643..8ef0f02635d4 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -20,6 +20,7 @@ struct scatterlist; struct irq_desc; struct page; struct mm_struct; +struct pci_bus; typedef void ia64_mv_setup_t (char **); typedef void ia64_mv_cpu_init_t (void); @@ -31,6 +32,11 @@ typedef void ia64_mv_tlb_migrate_finish_t (struct mm_struct *); typedef struct irq_desc *ia64_mv_irq_desc (unsigned int); typedef u8 ia64_mv_irq_to_vector (unsigned int); typedef unsigned int ia64_mv_local_vector_to_irq (u8); +typedef char *ia64_mv_pci_get_legacy_mem_t (struct pci_bus *); +typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val, + u8 size); +typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val, + u8 size); /* DMA-mapping interface: */ typedef void ia64_mv_dma_init (void); @@ -127,6 +133,9 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # define platform_irq_desc ia64_mv.irq_desc # define platform_irq_to_vector ia64_mv.irq_to_vector # define platform_local_vector_to_irq ia64_mv.local_vector_to_irq +# define platform_pci_get_legacy_mem ia64_mv.pci_get_legacy_mem +# define platform_pci_legacy_read ia64_mv.pci_legacy_read +# define platform_pci_legacy_write ia64_mv.pci_legacy_write # define platform_inb ia64_mv.inb # define platform_inw ia64_mv.inw # define platform_inl ia64_mv.inl @@ -174,6 +183,9 @@ struct ia64_machine_vector { ia64_mv_irq_desc *irq_desc; ia64_mv_irq_to_vector *irq_to_vector; ia64_mv_local_vector_to_irq *local_vector_to_irq; + ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem; + ia64_mv_pci_legacy_read_t *pci_legacy_read; + ia64_mv_pci_legacy_write_t *pci_legacy_write; ia64_mv_inb_t *inb; ia64_mv_inw_t *inw; ia64_mv_inl_t *inl; @@ -217,6 +229,9 @@ struct ia64_machine_vector { platform_irq_desc, \ platform_irq_to_vector, \ platform_local_vector_to_irq, \ + platform_pci_get_legacy_mem, \ + platform_pci_legacy_read, \ + platform_pci_legacy_write, \ platform_inb, \ platform_inw, \ platform_inl, \ @@ -332,6 +347,15 @@ extern ia64_mv_dma_supported swiotlb_dma_supported; #ifndef platform_local_vector_to_irq # define platform_local_vector_to_irq __ia64_local_vector_to_irq #endif +#ifndef platform_pci_get_legacy_mem +# define platform_pci_get_legacy_mem ia64_pci_get_legacy_mem +#endif +#ifndef platform_pci_legacy_read +# define platform_pci_legacy_read ia64_pci_legacy_read +#endif +#ifndef platform_pci_legacy_write +# define platform_pci_legacy_write ia64_pci_legacy_write +#endif #ifndef platform_inb # define platform_inb __ia64_inb #endif diff --git a/include/asm-ia64/machvec_init.h b/include/asm-ia64/machvec_init.h index 0d7386a13422..cb19becd3937 100644 --- a/include/asm-ia64/machvec_init.h +++ b/include/asm-ia64/machvec_init.h @@ -5,6 +5,9 @@ extern ia64_mv_global_tlb_purge_t ia64_global_tlb_purge; extern ia64_mv_irq_desc __ia64_irq_desc; extern ia64_mv_irq_to_vector __ia64_irq_to_vector; extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq; +extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem; +extern ia64_mv_pci_legacy_read_t ia64_pci_legacy_read; +extern ia64_mv_pci_legacy_write_t ia64_pci_legacy_write; extern ia64_mv_inb_t __ia64_inb; extern ia64_mv_inw_t __ia64_inw; diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index 299a57f83f29..bd0ed509a4cc 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h @@ -43,6 +43,9 @@ extern ia64_mv_tlb_migrate_finish_t sn_tlb_migrate_finish; extern ia64_mv_irq_desc sn_irq_desc; extern ia64_mv_irq_to_vector sn_irq_to_vector; extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq; +extern ia64_mv_pci_get_legacy_mem_t sn_pci_get_legacy_mem; +extern ia64_mv_pci_legacy_read_t sn_pci_legacy_read; +extern ia64_mv_pci_legacy_write_t sn_pci_legacy_write; extern ia64_mv_inb_t __sn_inb; extern ia64_mv_inw_t __sn_inw; extern ia64_mv_inl_t __sn_inl; @@ -105,6 +108,9 @@ extern ia64_mv_dma_supported sn_dma_supported; #define platform_irq_desc sn_irq_desc #define platform_irq_to_vector sn_irq_to_vector #define platform_local_vector_to_irq sn_local_vector_to_irq +#define platform_pci_get_legacy_mem sn_pci_get_legacy_mem +#define platform_pci_legacy_read sn_pci_legacy_read +#define platform_pci_legacy_write sn_pci_legacy_write #define platform_dma_init machvec_noop #define platform_dma_alloc_coherent sn_dma_alloc_coherent #define platform_dma_free_coherent sn_dma_free_coherent diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h index 898f4eca65b5..48e565fb5e0f 100644 --- a/include/asm-ia64/pci.h +++ b/include/asm-ia64/pci.h @@ -85,6 +85,20 @@ extern int pcibios_prep_mwi (struct pci_dev *); #define HAVE_PCI_MMAP extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); +#define HAVE_PCI_LEGACY +extern int pci_mmap_legacy_page_range(struct pci_bus *bus, + struct vm_area_struct *vma); +extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, + size_t count); +extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, + size_t count); +extern int pci_mmap_legacy_mem(struct kobject *kobj, + struct bin_attribute *attr, + struct vm_area_struct *vma); + +#define pci_get_legacy_mem platform_pci_get_legacy_mem +#define pci_legacy_read platform_pci_legacy_read +#define pci_legacy_write platform_pci_legacy_write struct pci_window { struct resource resource; diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 51485f7d66a8..0d65837b8b03 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -474,6 +474,52 @@ ia64_sn_pod_mode(void) return isrv.v0; } +/** + * ia64_sn_probe_mem - read from memory safely + * @addr: address to probe + * @size: number bytes to read (1,2,4,8) + * @data_ptr: address to store value read by probe (-1 returned if probe fails) + * + * Call into the SAL to do a memory read. If the read generates a machine + * check, this routine will recover gracefully and return -1 to the caller. + * @addr is usually a kernel virtual address in uncached space (i.e. the + * address starts with 0xc), but if called in physical mode, @addr should + * be a physical address. + * + * Return values: + * 0 - probe successful + * 1 - probe failed (generated MCA) + * 2 - Bad arg + * <0 - PAL error + */ +static inline u64 +ia64_sn_probe_mem(long addr, long size, void *data_ptr) +{ + struct ia64_sal_retval isrv; + + SAL_CALL(isrv, SN_SAL_PROBE, addr, size, 0, 0, 0, 0, 0); + + if (data_ptr) { + switch (size) { + case 1: + *((u8*)data_ptr) = (u8)isrv.v0; + break; + case 2: + *((u16*)data_ptr) = (u16)isrv.v0; + break; + case 4: + *((u32*)data_ptr) = (u32)isrv.v0; + break; + case 8: + *((u64*)data_ptr) = (u64)isrv.v0; + break; + default: + isrv.status = 2; + } + } + return isrv.status; +} + /* * Retrieve the system serial number as an ASCII string. */ -- cgit v1.2.3 From 4cc329ec856b828bb5dc306d9d0574619b8815a0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Jan 2005 12:58:17 -0500 Subject: [PATCH] mark arcdev_setup static It's only used in arcnet.c, and following the model of the other link layers it doesn't make sense to use it outside alloc_arcdev() either. --- drivers/net/arcnet/arcnet.c | 3 +-- include/linux/arcdevice.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 282a678007b3..9fd21724f61f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -93,7 +93,6 @@ EXPORT_SYMBOL(arc_raw_proto); EXPORT_SYMBOL(arc_proto_null); EXPORT_SYMBOL(arcnet_unregister_proto); EXPORT_SYMBOL(arcnet_debug); -EXPORT_SYMBOL(arcdev_setup); EXPORT_SYMBOL(alloc_arcdev); EXPORT_SYMBOL(arcnet_interrupt); @@ -317,7 +316,7 @@ static int choose_mtu(void) /* Setup a struct device for ARCnet. */ -void arcdev_setup(struct net_device *dev) +static void arcdev_setup(struct net_device *dev) { dev->type = ARPHRD_ARCNET; dev->hard_header_len = sizeof(struct archdr); diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index bd4364daf948..7198f129e135 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -343,7 +343,6 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, void arcnet_unregister_proto(struct ArcProto *proto); irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs); -void arcdev_setup(struct net_device *dev); struct net_device *alloc_arcdev(char *name); void arcnet_rx(struct net_device *dev, int bufnum); -- cgit v1.2.3 From 357bdf2ac6f6f2c57bce76d819b4605e92897a58 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 10 Jan 2005 16:57:45 -0800 Subject: [PATCH] quota: make some code static The patch below makes some needlessly global code static. The most interesting part is that dquot_cachep can become static, since it isn't used outside of dquot.c . Signed-off-by: Adrian Bunk Acked-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/dquot.c | 8 ++++---- fs/quota.c | 2 +- include/linux/slab.h | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/dquot.c b/fs/dquot.c index ce53e60bd227..8455855e751a 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -128,6 +128,9 @@ static char *quotatypes[] = INITQFNAMES; static struct quota_format_type *quota_formats; /* List of registered formats */ static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES; +/* SLAB cache for dquot structures */ +static kmem_cache_t *dquot_cachep; + int register_quota_format(struct quota_format_type *fmt) { spin_lock(&dq_list_lock); @@ -199,7 +202,7 @@ static void put_quota_format(struct quota_format_type *fmt) static LIST_HEAD(inuse_list); static LIST_HEAD(free_dquots); -unsigned int dq_hash_bits, dq_hash_mask; +static unsigned int dq_hash_bits, dq_hash_mask; static struct hlist_head *dquot_hash; struct dqstats dqstats; @@ -1781,9 +1784,6 @@ static ctl_table sys_table[] = { { .ctl_name = 0 }, }; -/* SLAB cache for dquot structures */ -kmem_cache_t *dquot_cachep; - static int __init dquot_init(void) { int i; diff --git a/fs/quota.c b/fs/quota.c index e69e8d1ada84..d59ccf2358b5 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -136,7 +136,7 @@ restart: return NULL; } -void quota_sync_sb(struct super_block *sb, int type) +static void quota_sync_sb(struct super_block *sb, int type) { int cnt; struct inode *discard[MAXQUOTAS]; diff --git a/include/linux/slab.h b/include/linux/slab.h index 93c8264fe67b..0c7ae4f678a2 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -118,7 +118,6 @@ extern kmem_cache_t *mm_cachep; extern kmem_cache_t *names_cachep; extern kmem_cache_t *files_cachep; extern kmem_cache_t *filp_cachep; -extern kmem_cache_t *dquot_cachep; extern kmem_cache_t *fs_cachep; extern kmem_cache_t *signal_cachep; extern kmem_cache_t *sighand_cachep; -- cgit v1.2.3 From 7f01bafbc7463ed7b02bf1c0187cac1c01c922c8 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Mon, 10 Jan 2005 17:10:38 -0800 Subject: [PATCH] split bprm_apply_creds into two functions The following patch splits bprm_apply_creds into two functions, bprm_apply_creds and bprm_post_apply_creds. The latter is called after the task_lock has been dropped. Without this patch, SELinux must drop the task_lock and re-acquire it during apply_creds, making the 'unsafe' flag meaningless to any later security modules. Please apply. Signed-off-by: Serge Hallyn Signed-off-by: Stephen Smalley Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 1 + include/linux/security.h | 25 +++++-- security/dummy.c | 6 ++ security/selinux/hooks.c | 148 ++++++++++++++++++++------------------ security/selinux/include/objsec.h | 6 ++ 5 files changed, 112 insertions(+), 74 deletions(-) (limited to 'include') diff --git a/fs/exec.c b/fs/exec.c index c401dc74226e..ffe22877ca94 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -963,6 +963,7 @@ void compute_creds(struct linux_binprm *bprm) unsafe = unsafe_exec(current); security_bprm_apply_creds(bprm, unsafe); task_unlock(current); + security_bprm_post_apply_creds(bprm); } EXPORT_SYMBOL(compute_creds); diff --git a/include/linux/security.h b/include/linux/security.h index 4e0795b5a276..2b048ec62e9c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -109,13 +109,20 @@ struct swap_info_struct; * and the information saved in @bprm->security by the set_security hook. * Since this hook function (and its caller) are void, this hook can not * return an error. However, it can leave the security attributes of the - * process unchanged if an access failure occurs at this point. It can - * also perform other state changes on the process (e.g. closing open - * file descriptors to which access is no longer granted if the attributes - * were changed). + * process unchanged if an access failure occurs at this point. * bprm_apply_creds is called under task_lock. @unsafe indicates various * reasons why it may be unsafe to change security state. * @bprm contains the linux_binprm structure. + * @bprm_post_apply_creds: + * Runs after bprm_apply_creds with the task_lock dropped, so that + * functions which cannot be called safely under the task_lock can + * be used. This hook is a good place to perform state changes on + * the process such as closing open file descriptors to which access + * is no longer granted if the attributes were changed. + * Note that a security module might need to save state between + * bprm_apply_creds and bprm_post_apply_creds to store the decision + * on whether the process may proceed. + * @bprm contains the linux_binprm structure. * @bprm_set_security: * Save security information in the bprm->security field, typically based * on information about the bprm->file, for later use by the apply_creds @@ -1042,6 +1049,7 @@ struct security_operations { int (*bprm_alloc_security) (struct linux_binprm * bprm); void (*bprm_free_security) (struct linux_binprm * bprm); void (*bprm_apply_creds) (struct linux_binprm * bprm, int unsafe); + void (*bprm_post_apply_creds) (struct linux_binprm * bprm); int (*bprm_set_security) (struct linux_binprm * bprm); int (*bprm_check_security) (struct linux_binprm * bprm); int (*bprm_secureexec) (struct linux_binprm * bprm); @@ -1314,6 +1322,10 @@ static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int uns { security_ops->bprm_apply_creds (bprm, unsafe); } +static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm) +{ + security_ops->bprm_post_apply_creds (bprm); +} static inline int security_bprm_set (struct linux_binprm *bprm) { return security_ops->bprm_set_security (bprm); @@ -1992,6 +2004,11 @@ static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int uns cap_bprm_apply_creds (bprm, unsafe); } +static inline void security_bprm_post_apply_creds (struct linux_binprm *bprm) +{ + return; +} + static inline int security_bprm_set (struct linux_binprm *bprm) { return cap_bprm_set_security (bprm); diff --git a/security/dummy.c b/security/dummy.c index ce3deb72a87f..16d48b15ca1b 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -200,6 +200,11 @@ static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) dummy_capget(current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted); } +static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm) +{ + return; +} + static int dummy_bprm_set_security (struct linux_binprm *bprm) { return 0; @@ -916,6 +921,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security); set_to_dummy_if_null(ops, bprm_apply_creds); + set_to_dummy_if_null(ops, bprm_post_apply_creds); set_to_dummy_if_null(ops, bprm_set_security); set_to_dummy_if_null(ops, bprm_check_security); set_to_dummy_if_null(ops, bprm_secureexec); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a480aa47a9d3..2cbabb33c2a9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1795,10 +1795,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) struct task_security_struct *tsec; struct bprm_security_struct *bsec; u32 sid; - struct av_decision avd; - struct itimerval itimer; - struct rlimit *rlim, *initrlim; - int rc, i; + int rc; secondary_ops->bprm_apply_creds(bprm, unsafe); @@ -1808,91 +1805,101 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) sid = bsec->sid; tsec->osid = tsec->sid; + bsec->unsafe = 0; if (tsec->sid != sid) { /* Check for shared state. If not ok, leave SID unchanged and kill. */ if (unsafe & LSM_UNSAFE_SHARE) { - rc = avc_has_perm_noaudit(tsec->sid, sid, - SECCLASS_PROCESS, PROCESS__SHARE, &avd); + rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, + PROCESS__SHARE, NULL); if (rc) { - task_unlock(current); - avc_audit(tsec->sid, sid, SECCLASS_PROCESS, - PROCESS__SHARE, &avd, rc, NULL); - force_sig_specific(SIGKILL, current); - goto lock_out; + bsec->unsafe = 1; + return; } } /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and kill. */ if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { - rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid, - SECCLASS_PROCESS, PROCESS__PTRACE, &avd); - if (!rc) - tsec->sid = sid; - task_unlock(current); - avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, - PROCESS__PTRACE, &avd, rc, NULL); + rc = avc_has_perm(tsec->ptrace_sid, sid, + SECCLASS_PROCESS, PROCESS__PTRACE, + NULL); if (rc) { - force_sig_specific(SIGKILL, current); - goto lock_out; + bsec->unsafe = 1; + return; } - } else { - tsec->sid = sid; - task_unlock(current); - } - - /* Close files for which the new task SID is not authorized. */ - flush_unauthorized_files(current->files); - - /* Check whether the new SID can inherit signal state - from the old SID. If not, clear itimers to avoid - subsequent signal generation and flush and unblock - signals. This must occur _after_ the task SID has - been updated so that any kill done after the flush - will be checked against the new SID. */ - rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, - PROCESS__SIGINH, NULL); - if (rc) { - memset(&itimer, 0, sizeof itimer); - for (i = 0; i < 3; i++) - do_setitimer(i, &itimer, NULL); - flush_signals(current); - spin_lock_irq(¤t->sighand->siglock); - flush_signal_handlers(current, 1); - sigemptyset(¤t->blocked); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); } + tsec->sid = sid; + } +} - /* Check whether the new SID can inherit resource limits - from the old SID. If not, reset all soft limits to - the lower of the current task's hard limit and the init - task's soft limit. Note that the setting of hard limits - (even to lower them) can be controlled by the setrlimit - check. The inclusion of the init task's soft limit into - the computation is to avoid resetting soft limits higher - than the default soft limit for cases where the default - is lower than the hard limit, e.g. RLIMIT_CORE or - RLIMIT_STACK.*/ - rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, - PROCESS__RLIMITINH, NULL); - if (rc) { - for (i = 0; i < RLIM_NLIMITS; i++) { - rlim = current->signal->rlim + i; - initrlim = init_task.signal->rlim+i; - rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); - } - } +/* + * called after apply_creds without the task lock held + */ +static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) +{ + struct task_security_struct *tsec; + struct rlimit *rlim, *initrlim; + struct itimerval itimer; + struct bprm_security_struct *bsec; + int rc, i; - /* Wake up the parent if it is waiting so that it can - recheck wait permission to the new task SID. */ - wake_up_interruptible(¤t->parent->signal->wait_chldexit); + tsec = current->security; + bsec = bprm->security; -lock_out: - task_lock(current); + if (bsec->unsafe) { + force_sig_specific(SIGKILL, current); return; } + if (tsec->osid == tsec->sid) + return; + + /* Close files for which the new task SID is not authorized. */ + flush_unauthorized_files(current->files); + + /* Check whether the new SID can inherit signal state + from the old SID. If not, clear itimers to avoid + subsequent signal generation and flush and unblock + signals. This must occur _after_ the task SID has + been updated so that any kill done after the flush + will be checked against the new SID. */ + rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, + PROCESS__SIGINH, NULL); + if (rc) { + memset(&itimer, 0, sizeof itimer); + for (i = 0; i < 3; i++) + do_setitimer(i, &itimer, NULL); + flush_signals(current); + spin_lock_irq(¤t->sighand->siglock); + flush_signal_handlers(current, 1); + sigemptyset(¤t->blocked); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + /* Check whether the new SID can inherit resource limits + from the old SID. If not, reset all soft limits to + the lower of the current task's hard limit and the init + task's soft limit. Note that the setting of hard limits + (even to lower them) can be controlled by the setrlimit + check. The inclusion of the init task's soft limit into + the computation is to avoid resetting soft limits higher + than the default soft limit for cases where the default + is lower than the hard limit, e.g. RLIMIT_CORE or + RLIMIT_STACK.*/ + rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, + PROCESS__RLIMITINH, NULL); + if (rc) { + for (i = 0; i < RLIM_NLIMITS; i++) { + rlim = current->signal->rlim + i; + initrlim = init_task.signal->rlim+i; + rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); + } + } + + /* Wake up the parent if it is waiting so that it can + recheck wait permission to the new task SID. */ + wake_up_interruptible(¤t->parent->signal->wait_chldexit); } /* superblock security operations */ @@ -4212,6 +4219,7 @@ struct security_operations selinux_ops = { .bprm_alloc_security = selinux_bprm_alloc_security, .bprm_free_security = selinux_bprm_free_security, .bprm_apply_creds = selinux_bprm_apply_creds, + .bprm_post_apply_creds = selinux_bprm_post_apply_creds, .bprm_set_security = selinux_bprm_set_security, .bprm_check_security = selinux_bprm_check_security, .bprm_secureexec = selinux_bprm_secureexec, diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index d1516e47e421..30a0abc9c778 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -87,6 +87,12 @@ struct bprm_security_struct { struct linux_binprm *bprm; /* back pointer to bprm object */ u32 sid; /* SID for transformed process */ unsigned char set; + + /* + * unsafe is used to share failure information from bprm_apply_creds() + * to bprm_post_apply_creds(). + */ + char unsafe; }; struct netif_security_struct { -- cgit v1.2.3 From b6dfc3f2d6cb1a1d0c1ad4506712c1557566b419 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Mon, 10 Jan 2005 17:10:53 -0800 Subject: [PATCH] merge *_vm_enough_memory()s into a common helper The vm_enough_memory functionality was replicated in three separate places, and not always kept in sync. It also used capable() for authorization checks. This caused any process which ends up checking for this permission to have PF_SUPERPRIV set (inappropriately), and caused poor dependencies between stacked modules, since each LSM was generically asked to moderate capable(CAP_SYS_ADMIN) without knowing why. Signed-off-by: Serge Hallyn Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/mmap.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ security/commoncap.c | 81 +++----------------------------------------- security/dummy.c | 64 +++-------------------------------- security/selinux/hooks.c | 70 +++++++++----------------------------- 5 files changed, 112 insertions(+), 192 deletions(-) (limited to 'include') diff --git a/include/linux/mm.h b/include/linux/mm.h index ee9817135376..75f5b8ed7231 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -711,6 +711,7 @@ static inline void vma_nonlinear_insert(struct vm_area_struct *vma, } /* mmap.c */ +extern int __vm_enough_memory(long pages, int cap_sys_admin); extern void vma_adjust(struct vm_area_struct *vma, unsigned long start, unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert); extern struct vm_area_struct *vma_merge(struct mm_struct *, diff --git a/mm/mmap.c b/mm/mmap.c index ca45a0e92e3b..f0d1f464ee00 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -61,10 +61,98 @@ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; atomic_t vm_committed_space = ATOMIC_INIT(0); +/* + * Check that a process has enough memory to allocate a new virtual + * mapping. 0 means there is enough memory for the allocation to + * succeed and -ENOMEM implies there is not. + * + * We currently support three overcommit policies, which are set via the + * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting + * + * Strict overcommit modes added 2002 Feb 26 by Alan Cox. + * Additional code 2002 Jul 20 by Robert Love. + * + * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise. + * + * Note this is a helper function intended to be used by LSMs which + * wish to use this logic. + */ +int __vm_enough_memory(long pages, int cap_sys_admin) +{ + unsigned long free, allowed; + + vm_acct_memory(pages); + + /* + * Sometimes we want to use more memory than we have + */ + if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) + return 0; + + if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { + unsigned long n; + + free = get_page_cache_size(); + free += nr_swap_pages; + + /* + * Any slabs which are created with the + * SLAB_RECLAIM_ACCOUNT flag claim to have contents + * which are reclaimable, under pressure. The dentry + * cache and most inode caches should fall into this + */ + free += atomic_read(&slab_reclaim_pages); + + /* + * Leave the last 3% for root + */ + if (!cap_sys_admin) + free -= free / 32; + + if (free > pages) + return 0; + + /* + * nr_free_pages() is very expensive on large systems, + * only call if we're about to fail. + */ + n = nr_free_pages(); + if (!cap_sys_admin) + n -= n / 32; + free += n; + + if (free > pages) + return 0; + vm_unacct_memory(pages); + return -ENOMEM; + } + + allowed = (totalram_pages - hugetlb_total_pages()) + * sysctl_overcommit_ratio / 100; + /* + * Leave the last 3% for root + */ + if (!cap_sys_admin) + allowed -= allowed / 32; + allowed += total_swap_pages; + + /* Don't let a single process grow too big: + leave 3% of the size of this process for other processes */ + allowed -= current->mm->total_vm / 32; + + if (atomic_read(&vm_committed_space) < allowed) + return 0; + + vm_unacct_memory(pages); + + return -ENOMEM; +} + EXPORT_SYMBOL(sysctl_overcommit_memory); EXPORT_SYMBOL(sysctl_overcommit_ratio); EXPORT_SYMBOL(sysctl_max_map_count); EXPORT_SYMBOL(vm_committed_space); +EXPORT_SYMBOL(__vm_enough_memory); /* * Requires inode->i_mapping->i_mmap_lock diff --git a/security/commoncap.c b/security/commoncap.c index 0fdbcfd40a98..849b8c338ee8 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -316,86 +316,13 @@ int cap_syslog (int type) return 0; } -/* - * Check that a process has enough memory to allocate a new virtual - * mapping. 0 means there is enough memory for the allocation to - * succeed and -ENOMEM implies there is not. - * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting - * - * Strict overcommit modes added 2002 Feb 26 by Alan Cox. - * Additional code 2002 Jul 20 by Robert Love. - */ int cap_vm_enough_memory(long pages) { - unsigned long free, allowed; - - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - unsigned long n; - - free = get_page_cache_size(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for root - */ - if (!capable(CAP_SYS_ADMIN)) - free -= free / 32; - - if (free > pages) - return 0; - - /* - * nr_free_pages() is very expensive on large systems, - * only call if we're about to fail. - */ - n = nr_free_pages(); - if (!capable(CAP_SYS_ADMIN)) - n -= n / 32; - free += n; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } - - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - /* - * Leave the last 3% for root - */ - if (!capable(CAP_SYS_ADMIN)) - allowed -= allowed / 32; - allowed += total_swap_pages; - - /* Don't let a single process grow too big: - leave 3% of the size of this process for other processes */ - allowed -= current->mm->total_vm / 32; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; - - vm_unacct_memory(pages); + int cap_sys_admin = 0; - return -ENOMEM; + if (cap_capable(current, CAP_SYS_ADMIN) == 0) + cap_sys_admin = 1; + return __vm_enough_memory(pages, cap_sys_admin); } EXPORT_SYMBOL(cap_capable); diff --git a/security/dummy.c b/security/dummy.c index 16d48b15ca1b..72e6d71a79aa 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -108,69 +108,13 @@ static int dummy_settime(struct timespec *ts, struct timezone *tz) return 0; } -/* - * Check that a process has enough memory to allocate a new virtual - * mapping. 0 means there is enough memory for the allocation to - * succeed and -ENOMEM implies there is not. - * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting - */ static int dummy_vm_enough_memory(long pages) { - unsigned long free, allowed; - - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - free = get_page_cache_size(); - free += nr_free_pages(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for root - */ - if (current->euid) - free -= free / 32; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } - - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - allowed += total_swap_pages; - - /* Leave the last 3% for root */ - if (current->euid) - allowed -= allowed / 32; - - /* Don't let a single process grow too big: - leave 3% of the size of this process for other processes */ - allowed -= current->mm->total_vm / 32; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; - - vm_unacct_memory(pages); + int cap_sys_admin = 0; - return -ENOMEM; + if (dummy_capable(current, CAP_SYS_ADMIN) == 0) + cap_sys_admin = 1; + return __vm_enough_memory(pages, cap_sys_admin); } static int dummy_bprm_alloc_security (struct linux_binprm *bprm) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2cbabb33c2a9..ea244b769d99 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1515,69 +1515,29 @@ static int selinux_syslog(int type) * mapping. 0 means there is enough memory for the allocation to * succeed and -ENOMEM implies there is not. * - * We currently support three overcommit policies, which are set via the - * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting + * Note that secondary_ops->capable and task_has_perm_noaudit return 0 + * if the capability is granted, but __vm_enough_memory requires 1 if + * the capability is granted. * - * Strict overcommit modes added 2002 Feb 26 by Alan Cox. - * Additional code 2002 Jul 20 by Robert Love. + * Do not audit the selinux permission check, as this is applied to all + * processes that allocate mappings. */ static int selinux_vm_enough_memory(long pages) { - unsigned long free, allowed; - int rc; + int rc, cap_sys_admin = 0; struct task_security_struct *tsec = current->security; - vm_acct_memory(pages); - - /* - * Sometimes we want to use more memory than we have - */ - if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) - return 0; - - if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { - free = get_page_cache_size(); - free += nr_free_pages(); - free += nr_swap_pages; - - /* - * Any slabs which are created with the - * SLAB_RECLAIM_ACCOUNT flag claim to have contents - * which are reclaimable, under pressure. The dentry - * cache and most inode caches should fall into this - */ - free += atomic_read(&slab_reclaim_pages); - - /* - * Leave the last 3% for privileged processes. - * Don't audit the check, as it is applied to all processes - * that allocate mappings. - */ - rc = secondary_ops->capable(current, CAP_SYS_ADMIN); - if (!rc) { - rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, - SECCLASS_CAPABILITY, - CAP_TO_MASK(CAP_SYS_ADMIN), NULL); - } - if (rc) - free -= free / 32; - - if (free > pages) - return 0; - vm_unacct_memory(pages); - return -ENOMEM; - } - - allowed = (totalram_pages - hugetlb_total_pages()) - * sysctl_overcommit_ratio / 100; - allowed += total_swap_pages; - - if (atomic_read(&vm_committed_space) < allowed) - return 0; + rc = secondary_ops->capable(current, CAP_SYS_ADMIN); + if (rc == 0) + rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, + SECCLASS_CAPABILITY, + CAP_TO_MASK(CAP_SYS_ADMIN), + NULL); - vm_unacct_memory(pages); + if (rc == 0) + cap_sys_admin = 1; - return -ENOMEM; + return __vm_enough_memory(pages, cap_sys_admin); } /* binprm security operations */ -- cgit v1.2.3 From bced89beb5f1982c93b0d504ffd3279c174d7801 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 10 Jan 2005 17:11:19 -0800 Subject: [PATCH] ppc64: rename perf counter register #defines This patch makes some cleanups to the #defines for various fields in the MMCR0 performance monitor control register. Specifically, the names of a couple of bits are changed so that: a) they are a bit less cumbersomely long and b) they match the names used in the hardware documentation. Signed-off-by: David Gibson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/oprofile/op_model_power4.c | 2 +- arch/ppc64/oprofile/op_model_rs64.c | 2 +- include/asm-ppc64/processor.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c index c0f7a151c764..b1ca798f4c29 100644 --- a/arch/ppc64/oprofile/op_model_power4.c +++ b/arch/ppc64/oprofile/op_model_power4.c @@ -97,7 +97,7 @@ static void power4_cpu_setup(void *unused) mtspr(SPRN_MMCR0, mmcr0); mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; - mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL; + mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; mtspr(SPRN_MMCR0, mmcr0); mtspr(SPRN_MMCR1, mmcr1_val); diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c index b34ea586440a..b3cddb7e03d0 100644 --- a/arch/ppc64/oprofile/op_model_rs64.c +++ b/arch/ppc64/oprofile/op_model_rs64.c @@ -119,7 +119,7 @@ static void rs64_cpu_setup(void *unused) mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; /* Only applies to POWER3, but should be safe on RS64 */ - mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL; + mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; mtspr(SPRN_MMCR0, mmcr0); dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index d5b23b426efa..1cf388538595 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h @@ -331,8 +331,8 @@ #define MMCR0_FCECE 0x02000000UL /* freeze counters on enabled condition or event */ /* time base exception enable */ #define MMCR0_TBEE 0x00400000UL /* time base exception enable */ -#define MMCR0_PMC1INTCONTROL 0x00008000UL /* PMC1 count enable*/ -#define MMCR0_PMCNINTCONTROL 0x00004000UL /* PMCn count enable*/ +#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/ +#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/ #define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */ #define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */ #define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */ -- cgit v1.2.3 From 3f3078b6fd65b26f1fbfca470d5e85479b48a64e Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 10 Jan 2005 17:12:03 -0800 Subject: [PATCH] pm: introduce pm_message_t This introduces pm_message_t. For now, it is only good for type-safety and sparse checking, but plan is to turn pm_message_t into structure soon. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/power/devices.txt | 88 +++++++++++++++++++++++++++++++++++++++++ arch/arm/common/amba.c | 2 +- arch/arm/common/locomo.c | 2 +- arch/arm/common/sa1111.c | 2 +- drivers/base/platform.c | 2 +- drivers/base/power/power.h | 6 +-- drivers/base/power/runtime.c | 4 +- drivers/base/power/suspend.c | 8 ++-- drivers/ide/ide.c | 2 +- drivers/pci/pci-driver.c | 2 +- include/linux/device.h | 2 +- include/linux/pm.h | 32 +++++++++++++-- 12 files changed, 132 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 435ea29bb676..2b2a3a6f96e2 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -118,6 +118,94 @@ will fail. There is currently no way to know what states a device or driver supports a priori. This will change in the future. +pm_message_t meaning + +pm_message_t has two fields. event ("major"), and flags. If driver +does not know event code, it aborts the request, returning error. Some +drivers may need to deal with special cases based on the actual type +of suspend operation being done at the system level. This is why +there are flags. + +Event codes are: + +ON -- no need to do anything except special cases like broken +HW. + +# NOTIFICATION -- pretty much same as ON? + +FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from +scratch. That probably means stop accepting upstream requests, the +actual policy of what to do with them beeing specific to a given +driver. It's acceptable for a network driver to just drop packets +while a block driver is expected to block the queue so no request is +lost. (Use IDE as an example on how to do that). FREEZE requires no +power state change, and it's expected for drivers to be able to +quickly transition back to operating state. + +SUSPEND -- like FREEZE, but also put hardware into low-power state. If +there's need to distinguish several levels of sleep, additional flag +is probably best way to do that. + +Transitions are only from a resumed state to a suspended state, never +between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen, +FREEZE -> SUSPEND or SUSPEND -> FREEZE can not). + +All events are: + +[NOTE NOTE NOTE: If you are driver author, you should not care; you +should only look at event, and ignore flags.] + +#Prepare for suspend -- userland is still running but we are going to +#enter suspend state. This gives drivers chance to load firmware from +#disk and store it in memory, or do other activities taht require +#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these +#are forbiden once the suspend dance is started.. event = ON, flags = +#PREPARE_TO_SUSPEND + +Apm standby -- prepare for APM event. Quiesce devices to make life +easier for APM BIOS. event = FREEZE, flags = APM_STANDBY + +Apm suspend -- same as APM_STANDBY, but it we should probably avoid +spinning down disks. event = FREEZE, flags = APM_SUSPEND + +System halt, reboot -- quiesce devices to make life easier for BIOS. event += FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT + +System shutdown -- at least disks need to be spun down, or data may be +lost. Quiesce devices, just to make life easier for BIOS. event = +FREEZE, flags = SYSTEM_SHUTDOWN + +Kexec -- turn off DMAs and put hardware into some state where new +kernel can take over. event = FREEZE, flags = KEXEC + +Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake +may need to be enabled on some devices. This actually has at least 3 +subtypes, system can reboot, enter S4 and enter S5 at the end of +swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT, +SYSTEM_SHUTDOWN, SYSTEM_S4 + +Suspend to ram -- put devices into low power state. event = SUSPEND, +flags = SUSPEND_TO_RAM + +Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put +devices into low power mode, but you must be able to reinitialize +device from scratch in resume method. This has two flavors, its done +once on suspending kernel, once on resuming kernel. event = FREEZE, +flags = DURING_SUSPEND or DURING_RESUME + +Device detach requested from /sys -- deinitialize device; proably same as +SYSTEM_SHUTDOWN, I do not understand this one too much. probably event += FREEZE, flags = DEV_DETACH. + +#These are not really events sent: +# +#System fully on -- device is working normally; this is probably never +#passed to suspend() method... event = ON, flags = 0 +# +#Ready after resume -- userland is now running, again. Time to free any +#memory you ate during prepare to suspend... event = ON, flags = +#READY_AFTER_RESUME +# Driver Detach Power Management diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c index b5f5c6d2cb62..a0507f8c33fe 100644 --- a/arch/arm/common/amba.c +++ b/arch/arm/common/amba.c @@ -59,7 +59,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, #define amba_hotplug NULL #endif -static int amba_suspend(struct device *dev, u32 state) +static int amba_suspend(struct device *dev, pm_message_t state) { struct amba_driver *drv = to_amba_driver(dev->driver); int ret = 0; diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index b86e288c678c..34c8cf33ad9a 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -668,7 +668,7 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv) return dev->devid == drv->devid; } -static int locomo_bus_suspend(struct device *dev, u32 state) +static int locomo_bus_suspend(struct device *dev, pm_message_t state) { struct locomo_dev *ldev = LOCOMO_DEV(dev); struct locomo_driver *drv = LOCOMO_DRV(dev->driver); diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 32839b819c34..c90939341db1 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -1193,7 +1193,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv) return dev->devid == drv->devid; } -static int sa1111_bus_suspend(struct device *dev, u32 state) +static int sa1111_bus_suspend(struct device *dev, pm_message_t state) { struct sa1111_dev *sadev = SA1111_DEV(dev); struct sa1111_driver *drv = SA1111_DRV(dev->driver); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 81251fde2516..c8c87cebcbc1 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -276,7 +276,7 @@ static int platform_match(struct device * dev, struct device_driver * drv) return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } -static int platform_suspend(struct device * dev, u32 state) +static int platform_suspend(struct device * dev, pm_message_t state) { int ret = 0; diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 66cb431b1433..e5eda746f2a6 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -71,14 +71,14 @@ extern int resume_device(struct device *); /* * suspend.c */ -extern int suspend_device(struct device *, u32); +extern int suspend_device(struct device *, pm_message_t); /* * runtime.c */ -extern int dpm_runtime_suspend(struct device *, u32); +extern int dpm_runtime_suspend(struct device *, pm_message_t); extern void dpm_runtime_resume(struct device *); #else /* CONFIG_PM */ @@ -93,7 +93,7 @@ static inline void device_pm_remove(struct device * dev) } -static inline int dpm_runtime_suspend(struct device * dev, u32 state) +static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state) { return 0; } diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 5e58f68363af..325962d80191 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -44,7 +44,7 @@ void dpm_runtime_resume(struct device * dev) * @state: State to enter. */ -int dpm_runtime_suspend(struct device * dev, u32 state) +int dpm_runtime_suspend(struct device * dev, pm_message_t state) { int error = 0; @@ -73,7 +73,7 @@ int dpm_runtime_suspend(struct device * dev, u32 state) * always be able to tell, but we need accurate information to * work reliably. */ -void dpm_set_power_state(struct device * dev, u32 state) +void dpm_set_power_state(struct device * dev, pm_message_t state) { down(&dpm_sem); dev->power.power_state = state; diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 94c1311ee26b..8e1ace2d817e 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -11,7 +11,7 @@ #include #include "power.h" -extern int sysdev_suspend(u32 state); +extern int sysdev_suspend(pm_message_t state); /* * The entries in the dpm_active list are in a depth first order, simply @@ -35,7 +35,7 @@ extern int sysdev_suspend(u32 state); * @state: Power state device is entering. */ -int suspend_device(struct device * dev, u32 state) +int suspend_device(struct device * dev, pm_message_t state) { int error = 0; @@ -65,7 +65,7 @@ int suspend_device(struct device * dev, u32 state) * */ -int device_suspend(u32 state) +int device_suspend(pm_message_t state) { int error = 0; @@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(device_suspend); * done, power down system devices. */ -int device_power_down(u32 state) +int device_power_down(pm_message_t state) { int error = 0; struct device * dev; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 2e50f8597b83..7f867df01a56 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1380,7 +1380,7 @@ int ata_attach(ide_drive_t *drive) return 1; } -static int generic_ide_suspend(struct device *dev, u32 state) +static int generic_ide_suspend(struct device *dev, pm_message_t state) { ide_drive_t *drive = dev->driver_data; struct request rq; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7ce952cd99f6..7371987cf183 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -284,7 +284,7 @@ static int pci_device_remove(struct device * dev) return 0; } -static int pci_device_suspend(struct device * dev, u32 state) +static int pci_device_suspend(struct device * dev, pm_message_t state) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; diff --git a/include/linux/device.h b/include/linux/device.h index 2c5d57283d5a..786e1591102b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -61,7 +61,7 @@ struct bus_type { int (*match)(struct device * dev, struct device_driver * drv); int (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); - int (*suspend)(struct device * dev, u32 state); + int (*suspend)(struct device * dev, pm_message_t state); int (*resume)(struct device * dev); }; diff --git a/include/linux/pm.h b/include/linux/pm.h index 68da2eae8547..22c7aeb6419e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -222,10 +222,34 @@ extern int pm_suspend(suspend_state_t state); struct device; +typedef u32 __bitwise pm_message_t; + +/* + * There are 4 important states driver can be in: + * ON -- driver is working + * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver + * of that class, freeze queues for block like IDE does, drop packets for + * ethernet, etc... stop DMA engine too etc... so a consistent image can be + * saved; but do not power any hardware down. + * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly + * pci D3. + * + * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND). + * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional, + * and will go away as soon as drivers are fixed. Also note that typedef is neccessary, + * we'll probably want to switch to + * typedef struct pm_message_t { int event; int flags; } pm_message_t + * or something similar soon. + */ + +#define PMSG_FREEZE ((__force pm_message_t) 3) +#define PMSG_SUSPEND ((__force pm_message_t) 3) +#define PMSG_ON ((__force pm_message_t) 0) + struct dev_pm_info { - u32 power_state; + pm_message_t power_state; #ifdef CONFIG_PM - u32 prev_state; + pm_message_t prev_state; void * saved_state; atomic_t pm_users; struct device * pm_parent; @@ -235,8 +259,8 @@ struct dev_pm_info { extern void device_pm_set_parent(struct device * dev, struct device * parent); -extern int device_suspend(u32 state); -extern int device_power_down(u32 state); +extern int device_suspend(pm_message_t state); +extern int device_power_down(pm_message_t state); extern void device_power_up(void); extern void device_resume(void); -- cgit v1.2.3 From bf17b0cb528a4ccafbd969bfbcef85a2fa2006bf Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 10 Jan 2005 17:12:19 -0800 Subject: [PATCH] mark older power managment as deprecated Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pm.h | 71 +++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 49 deletions(-) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 22c7aeb6419e..1d106a3edad5 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -28,44 +28,28 @@ #include /* - * Power management requests + * Power management requests... these are passed to pm_send_all() and friends. + * + * these functions are old and deprecated, see below. */ -enum -{ - PM_SUSPEND, /* enter D1-D3 */ - PM_RESUME, /* enter D0 */ - - PM_SAVE_STATE, /* save device's state */ +typedef int __bitwise pm_request_t; - /* enable wake-on */ - PM_SET_WAKEUP, +#define PM_SUSPEND ((__force pm_request_t) 1) /* enter D1-D3 */ +#define PM_RESUME ((__force pm_request_t) 2) /* enter D0 */ - /* bus resource management */ - PM_GET_RESOURCES, - PM_SET_RESOURCES, - - /* base station management */ - PM_EJECT, - PM_LOCK, -}; - -typedef int pm_request_t; /* - * Device types + * Device types... these are passed to pm_register */ -enum -{ - PM_UNKNOWN_DEV = 0, /* generic */ - PM_SYS_DEV, /* system device (fan, KB controller, ...) */ - PM_PCI_DEV, /* PCI device */ - PM_USB_DEV, /* USB device */ - PM_SCSI_DEV, /* SCSI device */ - PM_ISA_DEV, /* ISA device */ - PM_MTD_DEV, /* Memory Technology Device */ -}; +typedef int __bitwise pm_dev_t; -typedef int pm_dev_t; +#define PM_UNKNOWN_DEV ((__force pm_dev_t) 0) /* generic */ +#define PM_SYS_DEV ((__force pm_dev_t) 1) /* system device (fan, KB controller, ...) */ +#define PM_PCI_DEV ((__force pm_dev_t) 2) /* PCI device */ +#define PM_USB_DEV ((__force pm_dev_t) 3) /* USB device */ +#define PM_SCSI_DEV ((__force pm_dev_t) 4) /* SCSI device */ +#define PM_ISA_DEV ((__force pm_dev_t) 5) /* ISA device */ +#define PM_MTD_DEV ((__force pm_dev_t) 6) /* Memory Technology Device */ /* * System device hardware ID (PnP) values @@ -119,32 +103,27 @@ extern int pm_active; /* * Register a device with power management */ -struct pm_dev *pm_register(pm_dev_t type, - unsigned long id, - pm_callback callback); +struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback); /* * Unregister a device with power management */ -void pm_unregister(struct pm_dev *dev); +void __deprecated pm_unregister(struct pm_dev *dev); /* * Unregister all devices with matching callback */ -void pm_unregister_all(pm_callback callback); +void __deprecated pm_unregister_all(pm_callback callback); /* * Send a request to a single device */ -int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data); +int __deprecated pm_send(struct pm_dev *dev, pm_request_t rqst, void *data); /* * Send a request to all devices */ -int pm_send_all(pm_request_t rqst, void *data); - -static inline void pm_access(struct pm_dev *dev) {} -static inline void pm_dev_idle(struct pm_dev *dev) {} +int __deprecated pm_send_all(pm_request_t rqst, void *data); #else /* CONFIG_PM */ @@ -171,16 +150,10 @@ static inline int pm_send_all(pm_request_t rqst, void *data) return 0; } -static inline struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from) -{ - return 0; -} - -static inline void pm_access(struct pm_dev *dev) {} -static inline void pm_dev_idle(struct pm_dev *dev) {} - #endif /* CONFIG_PM */ +/* Functions above this comment are list-based old-style power + * managment. Please avoid using them. */ /* * Callbacks for platform drivers to implement. -- cgit v1.2.3 From 681569acbf2f96e8bcfc7655736b0223feade423 Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Mon, 10 Jan 2005 17:13:02 -0800 Subject: [PATCH] m32r: employ new kernel API/ABI We, Linux/M32R project members, decided to change the kernel API/ABI. This modification is not small, but if we don't change it now, perhaps we have no chance to change them hereafter. * Why change the m32r kernel API/ABI? - The m32r port has many old-style syscall interfaces, because we made m32r port refering to the other traditional archs. Some old syscalls are no longer used or can be safely removed by upgrading the GNU C library. - To make the m32r kernel more secure, it is preferable to prevent stack region from being executed. (e.g. stack overflow) * API/ABI changes - include/asm-m32r/unistd.h: Upgrade to the new kernel API. - arch/m32r/entry.S: Minimum update to the new ABI. - Don't use UID16 syscalls. - To make stack noexecutable: 1) Don't use trampoline for signal handlers for kernel space (cf. sparc64): sys_signal: remove. sys_sigaction, sys_rt_sigaction: use glibc's restorer. 2) Don't generate trampoline code by GCC in userspace: Support non-executable stack by the m32r gcc. --> done (for gcc-3.4.3/gcc-4.0) * New userland - This modification does *not* keep backward compatibility. So we have been prepared new userland, based on the new API/ABI. Already, more than 200 new Debian deb binary packages are available on the Linux/M32R site: http://debian.linux-m32r.org/dists/04_ordovician/ (for this new ABI) Signed-off-by: NIIBE Yutaka Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/Kconfig | 2 +- arch/m32r/kernel/entry.S | 90 ++++++++--------- arch/m32r/kernel/signal.c | 187 +---------------------------------- include/asm-m32r/unistd.h | 241 ++++++++++++++++++++++------------------------ 4 files changed, 164 insertions(+), 356 deletions(-) (limited to 'include') diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 3ad33ed06091..0d90ea58a0cb 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -14,7 +14,7 @@ config SBUS config UID16 bool - default y + default n config GENERIC_ISA_DMA bool diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 29b0d8d0c68e..e71801637083 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -725,25 +725,25 @@ ENTRY(sys_call_table) .long sys_time .long sys_mknod .long sys_chmod /* 15 */ - .long sys_lchown + .long sys_ni_syscall /* lchown16 syscall holder */ .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat + .long sys_ni_syscall /* old stat syscall holder */ .long sys_lseek .long sys_getpid /* 20 */ .long sys_mount .long sys_oldumount - .long sys_setuid - .long sys_getuid + .long sys_ni_syscall /* setuid16 syscall holder */ + .long sys_ni_syscall /* getuid16 syscall holder */ .long sys_stime /* 25 */ .long sys_ptrace .long sys_alarm - .long sys_fstat + .long sys_ni_syscall /* old fstat syscall holder */ .long sys_pause .long sys_utime /* 30 */ - .long sys_cacheflush /* for M32R */ /* old stty syscall holder */ + .long sys_ni_syscall /* old stty syscall holder */ .long sys_cachectl /* for M32R */ /* old gtty syscall holder */ .long sys_access - .long sys_nice + .long sys_ni_syscall /* nice syscall holder */ .long sys_ni_syscall /* 35 - old ftime syscall holder */ .long sys_sync .long sys_kill @@ -755,17 +755,17 @@ ENTRY(sys_call_table) .long sys_times .long sys_ni_syscall /* old prof syscall holder */ .long sys_brk /* 45 */ - .long sys_setgid - .long sys_getgid - .long sys_signal - .long sys_geteuid - .long sys_getegid /* 50 */ + .long sys_ni_syscall /* setgid16 syscall holder */ + .long sys_getgid /* will be unused */ + .long sys_ni_syscall /* signal syscall holder */ + .long sys_ni_syscall /* geteuid16 syscall holder */ + .long sys_ni_syscall /* 50 - getegid16 syscall holder */ .long sys_acct .long sys_umount /* recycled never used phys() */ .long sys_ni_syscall /* old lock syscall holder */ .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_fcntl /* 55 - will be unused */ + .long sys_ni_syscall /* mpx syscall holder */ .long sys_setpgid .long sys_ni_syscall /* old ulimit syscall holder */ .long sys_ni_syscall /* sys_olduname */ @@ -776,41 +776,41 @@ ENTRY(sys_call_table) .long sys_getppid .long sys_getpgrp /* 65 */ .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid /* 70 */ - .long sys_setregid - .long sys_sigsuspend - .long sys_sigpending + .long sys_ni_syscall /* sigaction syscall holder */ + .long sys_ni_syscall /* sgetmask syscall holder */ + .long sys_ni_syscall /* ssetmask syscall holder */ + .long sys_ni_syscall /* 70 - setreuid16 syscall holder */ + .long sys_ni_syscall /* setregid16 syscall holder */ + .long sys_ni_syscall /* sigsuspend syscall holder */ + .long sys_ni_syscall /* sigpending syscall holder */ .long sys_sethostname .long sys_setrlimit /* 75 */ - .long sys_getrlimit + .long sys_getrlimit/*will be unused*/ .long sys_getrusage .long sys_gettimeofday .long sys_settimeofday - .long sys_getgroups /* 80 */ - .long sys_setgroups + .long sys_ni_syscall /* 80 - getgroups16 syscall holder */ + .long sys_ni_syscall /* setgroups16 syscall holder */ .long sys_ni_syscall /* sys_oldselect */ .long sys_symlink - .long sys_lstat + .long sys_ni_syscall /* old lstat syscall holder */ .long sys_readlink /* 85 */ .long sys_uselib .long sys_swapon .long sys_reboot - .long old_readdir + .long sys_ni_syscall /* readdir syscall holder */ .long sys_ni_syscall /* 90 - old_mmap syscall holder */ .long sys_munmap .long sys_truncate .long sys_ftruncate .long sys_fchmod - .long sys_fchown /* 95 */ + .long sys_ni_syscall /* 95 - fchwon16 syscall holder */ .long sys_getpriority .long sys_setpriority .long sys_ni_syscall /* old profil syscall holder */ .long sys_statfs .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* ioperm */ + .long sys_ni_syscall /* ioperm syscall holder */ .long sys_socketcall .long sys_syslog .long sys_setitimer @@ -818,37 +818,37 @@ ENTRY(sys_call_table) .long sys_newstat .long sys_newlstat .long sys_newfstat - .long sys_uname - .long sys_ni_syscall /* 110 - iopl */ + .long sys_ni_syscall /* old uname syscall holder */ + .long sys_ni_syscall /* 110 - iopl syscall holder */ .long sys_vhangup - .long sys_ni_syscall /* for idle */ - .long sys_ni_syscall /* for vm86old */ + .long sys_ni_syscall /* idle syscall holder */ + .long sys_ni_syscall /* vm86old syscall holder */ .long sys_wait4 .long sys_swapoff /* 115 */ .long sys_sysinfo .long sys_ipc .long sys_fsync - .long sys_sigreturn + .long sys_ni_syscall /* sigreturn syscall holder */ .long sys_clone /* 120 */ .long sys_setdomainname .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ + .long sys_ni_syscall /* modify_ldt syscall holder */ .long sys_adjtimex .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* sys_create_module */ + .long sys_ni_syscall /* sigprocmask syscall holder */ + .long sys_ni_syscall /* create_module syscall holder */ .long sys_init_module .long sys_delete_module - .long sys_ni_syscall /* 130 sys_get_kernel_syms */ + .long sys_ni_syscall /* 130 - get_kernel_syms */ .long sys_quotactl .long sys_getpgid .long sys_fchdir .long sys_bdflush .long sys_sysfs /* 135 */ .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid - .long sys_setfsgid + .long sys_ni_syscall /* afs_syscall syscall holder */ + .long sys_ni_syscall /* setfsuid16 syscall holder */ + .long sys_ni_syscall /* setfsgid16 syscall holder */ .long sys_llseek /* 140 */ .long sys_getdents .long sys_select @@ -873,10 +873,10 @@ ENTRY(sys_call_table) .long sys_sched_rr_get_interval .long sys_nanosleep .long sys_mremap - .long sys_setresuid - .long sys_getresuid /* 165 */ - .long sys_tas /* vm86 */ - .long sys_ni_syscall /* sys_query_module */ + .long sys_ni_syscall /* setresuid16 syscall holder */ + .long sys_ni_syscall /* 165 - getresuid16 syscall holder */ + .long sys_tas /* vm86 syscall holder */ + .long sys_ni_syscall /* query_module syscall holder */ .long sys_poll .long sys_nfsservctl .long sys_setresgid /* 170 */ @@ -891,7 +891,7 @@ ENTRY(sys_call_table) .long sys_rt_sigsuspend .long sys_pread64 /* 180 */ .long sys_pwrite64 - .long sys_chown + .long sys_ni_syscall /* chown16 syscall holder */ .long sys_getcwd .long sys_capget .long sys_capset /* 185 */ diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index cbfa6748e4ab..d1f782517ad5 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -33,32 +33,6 @@ int do_signal(struct pt_regs *, sigset_t *); -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(old_sigset_t mask, unsigned long r1, - unsigned long r2, unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, struct pt_regs regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs.r0 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(®s, &saveset)) - return regs.r0; - } -} - asmlinkage int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, unsigned long r2, unsigned long r3, unsigned long r4, @@ -89,38 +63,6 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, } } -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r2, unsigned long r3, unsigned long r4, @@ -134,26 +76,14 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, * Do a signal return; undo the signal stack. */ -struct sigframe -{ -// char *pretcode; - int sig; - struct sigcontext sc; -// struct _fpstate fpstate; - unsigned long extramask[_NSIG_WORDS-1]; - char retcode[4]; -}; - struct rt_sigframe { -// char *pretcode; int sig; struct siginfo *pinfo; void *puc; struct siginfo info; struct ucontext uc; // struct _fpstate fpstate; - char retcode[8]; }; static int @@ -207,38 +137,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, return err; } -asmlinkage int -sys_sigreturn(unsigned long r0, unsigned long r1, - unsigned long r2, unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, struct pt_regs regs) -{ - struct sigframe __user *frame = (struct sigframe __user *)regs.spu; - sigset_t set; - int result; - - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(®s, &frame->sc, &result)) - goto badframe; - return result; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - asmlinkage int sys_rt_sigreturn(unsigned long r0, unsigned long r1, unsigned long r2, unsigned long r3, unsigned long r4, @@ -342,71 +240,6 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) return (void __user *)((sp - frame_size) & -8ul); } -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->spu, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(signal, &frame->sig); - if (err) - goto give_sigsegv; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - if (err) - goto give_sigsegv; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - if (err) - goto give_sigsegv; - } - - if (ka->sa.sa_flags & SA_RESTORER) - regs->lr = (unsigned long)ka->sa.sa_restorer; - else { - /* This is : ldi r7, #__NR_sigreturn ; trap #2 */ - unsigned long code = 0x670010f2 | (__NR_sigreturn << 16); - - regs->lr = (unsigned long)frame->retcode; - err |= __put_user(code, (long __user *)(frame->retcode+0)); - if (err) - goto give_sigsegv; - flush_cache_sigtramp((unsigned long)frame->retcode); - } - - /* Set up registers for signal handler */ - regs->spu = (unsigned long)frame; - regs->r0 = signal; /* Arg for signal handler */ - regs->r1 = (unsigned long)&frame->sc; - regs->bpc = (unsigned long)ka->sa.sa_handler; - - set_fs(USER_DS); - -#if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=%p pc=%p\n", - current->comm, current->pid, frame, regs->pc); -#endif - - return; - -give_sigsegv: - force_sigsegv(sig, current); -} - static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { @@ -448,20 +281,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Set up to return from userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->lr = (unsigned long)ka->sa.sa_restorer; - else { - /* This is : ldi r7, #__NR_rt_sigreturn ; trap #2 */ - unsigned long code1 = 0x97f00000 | (__NR_rt_sigreturn); - unsigned long code2 = 0x10f2f000; - - regs->lr = (unsigned long)frame->retcode; - err |= __put_user(code1, (long __user *)(frame->retcode+0)); - err |= __put_user(code2, (long __user *)(frame->retcode+4)); - if (err) - goto give_sigsegv; - flush_cache_sigtramp((unsigned long)frame->retcode); - } + regs->lr = (unsigned long)ka->sa.sa_restorer; /* Set up registers for signal handler */ regs->spu = (unsigned long)frame; @@ -519,10 +339,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); - else - setup_frame(sig, ka, oldset, regs); + setup_rt_frame(sig, ka, info, oldset, regs); if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h index a506573b7b69..f71dfa15db74 100644 --- a/include/asm-m32r/unistd.h +++ b/include/asm-m32r/unistd.h @@ -25,26 +25,26 @@ #define __NR_time 13 #define __NR_mknod 14 #define __NR_chmod 15 -#define __NR_lchown 16 -#define __NR_break 17 -#define __NR_oldstat 18 +/* 16 is unused */ +/* 17 is unused */ +/* 18 is unused */ #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 #define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 +/* 23 is unused */ +/* 24 is unused */ #define __NR_stime 25 #define __NR_ptrace 26 #define __NR_alarm 27 -#define __NR_oldfstat 28 +/* 28 is unused */ #define __NR_pause 29 #define __NR_utime 30 -#define __NR_cacheflush 31 /* old #define __NR_stty 31*/ +/* 31 is unused */ #define __NR_cachectl 32 /* old #define __NR_gtty 32*/ #define __NR_access 33 -#define __NR_nice 34 -#define __NR_ftime 35 +/* 34 is unused */ +/* 35 is unused */ #define __NR_sync 36 #define __NR_kill 37 #define __NR_rename 38 @@ -53,22 +53,22 @@ #define __NR_dup 41 #define __NR_pipe 42 #define __NR_times 43 -#define __NR_prof 44 +/* 44 is unused */ #define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 +/* 46 is unused */ +/* 47 is unused (getgid16) */ +/* 48 is unused */ +/* 49 is unused */ +/* 50 is unused */ #define __NR_acct 51 #define __NR_umount2 52 -#define __NR_lock 53 +/* 53 is unused */ #define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_mpx 56 +/* 55 is unused (fcntl) */ +/* 56 is unused */ #define __NR_setpgid 57 -#define __NR_ulimit 58 -#define __NR_oldolduname 59 +/* 58 is unused */ +/* 59 is unused */ #define __NR_umask 60 #define __NR_chroot 61 #define __NR_ustat 62 @@ -76,41 +76,41 @@ #define __NR_getppid 64 #define __NR_getpgrp 65 #define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 +/* 67 is unused */ +/* 68 is unused*/ +/* 69 is unused*/ +/* 70 is unused */ +/* 71 is unused */ +/* 72 is unused */ +/* 73 is unused */ #define __NR_sethostname 74 #define __NR_setrlimit 75 -#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ +/* 76 is unused (old getrlimit) */ #define __NR_getrusage 77 #define __NR_gettimeofday 78 #define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 +/* 80 is unused */ +/* 81 is unused */ +/* 82 is unused */ #define __NR_symlink 83 -#define __NR_oldlstat 84 +/* 84 is unused */ #define __NR_readlink 85 #define __NR_uselib 86 #define __NR_swapon 87 #define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 +/* 89 is unused */ +/* 90 is unused */ #define __NR_munmap 91 #define __NR_truncate 92 #define __NR_ftruncate 93 #define __NR_fchmod 94 -#define __NR_fchown 95 +/* 95 is unused */ #define __NR_getpriority 96 #define __NR_setpriority 97 -#define __NR_profil 98 +/* 98 is unused */ #define __NR_statfs 99 #define __NR_fstatfs 100 -#define __NR_ioperm 101 +/* 101 is unused */ #define __NR_socketcall 102 #define __NR_syslog 103 #define __NR_setitimer 104 @@ -118,37 +118,37 @@ #define __NR_stat 106 #define __NR_lstat 107 #define __NR_fstat 108 -#define __NR_olduname 109 -#define __NR_iopl 110 +/* 109 is unused */ +/* 110 is unused */ #define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86old 113 +/* 112 is unused */ +/* 113 is unused */ #define __NR_wait4 114 #define __NR_swapoff 115 #define __NR_sysinfo 116 #define __NR_ipc 117 #define __NR_fsync 118 -#define __NR_sigreturn 119 +/* 119 is unused */ #define __NR_clone 120 #define __NR_setdomainname 121 #define __NR_uname 122 -#define __NR_modify_ldt 123 +/* 123 is unused */ #define __NR_adjtimex 124 #define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 +/* 126 is unused */ +/* 127 is unused */ #define __NR_init_module 128 #define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 +/* 130 is unused */ #define __NR_quotactl 131 #define __NR_getpgid 132 #define __NR_fchdir 133 #define __NR_bdflush 134 #define __NR_sysfs 135 #define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 +/* 137 is unused */ +/* 138 is unused */ +/* 139 is unused */ #define __NR__llseek 140 #define __NR_getdents 141 #define __NR__newselect 142 @@ -173,14 +173,14 @@ #define __NR_sched_rr_get_interval 161 #define __NR_nanosleep 162 #define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 +/* 164 is unused */ +/* 165 is unused */ #define __NR_tas 166 -#define __NR_query_module 167 +/* 167 is unused */ #define __NR_poll 168 #define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 +/* 170 is unused */ +/* 171 is unused */ #define __NR_prctl 172 #define __NR_rt_sigreturn 173 #define __NR_rt_sigaction 174 @@ -191,14 +191,14 @@ #define __NR_rt_sigsuspend 179 #define __NR_pread64 180 #define __NR_pwrite64 181 -#define __NR_chown 182 +/* 182 is unused */ #define __NR_getcwd 183 #define __NR_capget 184 #define __NR_capset 185 #define __NR_sigaltstack 186 #define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ +/* 188 is unused */ +/* 189 is unused */ #define __NR_vfork 190 #define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ #define __NR_mmap2 192 @@ -229,71 +229,71 @@ #define __NR_pivot_root 217 #define __NR_mincore 218 #define __NR_madvise 219 -#define __NR_madvise1 219 /* delete when C lib stub is removed */ #define __NR_getdents64 220 #define __NR_fcntl64 221 -#define __NR_security 223 /* syscall for security modules */ -#define __NR_gettid 224 -#define __NR_readahead 225 -#define __NR_setxattr 226 -#define __NR_lsetxattr 227 -#define __NR_fsetxattr 228 -#define __NR_getxattr 229 -#define __NR_lgetxattr 230 -#define __NR_fgetxattr 231 -#define __NR_listxattr 232 -#define __NR_llistxattr 233 -#define __NR_flistxattr 234 -#define __NR_removexattr 235 -#define __NR_lremovexattr 236 -#define __NR_fremovexattr 237 +/* 222 is unused */ +/* 223 is unused */ +#define __NR_gettid 224 +#define __NR_readahead 225 +#define __NR_setxattr 226 +#define __NR_lsetxattr 227 +#define __NR_fsetxattr 228 +#define __NR_getxattr 229 +#define __NR_lgetxattr 230 +#define __NR_fgetxattr 231 +#define __NR_listxattr 232 +#define __NR_llistxattr 233 +#define __NR_flistxattr 234 +#define __NR_removexattr 235 +#define __NR_lremovexattr 236 +#define __NR_fremovexattr 237 #define __NR_tkill 238 #define __NR_sendfile64 239 #define __NR_futex 240 #define __NR_sched_setaffinity 241 #define __NR_sched_getaffinity 242 -#define __NR_set_thread_area 243 -#define __NR_get_thread_area 244 -#define __NR_io_setup 245 -#define __NR_io_destroy 246 -#define __NR_io_getevents 247 -#define __NR_io_submit 248 -#define __NR_io_cancel 249 -#define __NR_fadvise64 250 - -#define __NR_exit_group 252 -#define __NR_lookup_dcookie 253 -#define __NR_epoll_create 254 -#define __NR_epoll_ctl 255 -#define __NR_epoll_wait 256 -#define __NR_remap_file_pages 257 -#define __NR_set_tid_address 258 -#define __NR_timer_create 259 -#define __NR_timer_settime (__NR_timer_create+1) -#define __NR_timer_gettime (__NR_timer_create+2) -#define __NR_timer_getoverrun (__NR_timer_create+3) -#define __NR_timer_delete (__NR_timer_create+4) -#define __NR_clock_settime (__NR_timer_create+5) -#define __NR_clock_gettime (__NR_timer_create+6) -#define __NR_clock_getres (__NR_timer_create+7) -#define __NR_clock_nanosleep (__NR_timer_create+8) -#define __NR_statfs64 268 -#define __NR_fstatfs64 269 -#define __NR_tgkill 270 -#define __NR_utimes 271 -#define __NR_fadvise64_64 272 -#define __NR_vserver 273 -#define __NR_mbind 274 -#define __NR_get_mempolicy 275 -#define __NR_set_mempolicy 276 -#define __NR_mq_open 277 -#define __NR_mq_unlink (__NR_mq_open+1) -#define __NR_mq_timedsend (__NR_mq_open+2) -#define __NR_mq_timedreceive (__NR_mq_open+3) -#define __NR_mq_notify (__NR_mq_open+4) -#define __NR_mq_getsetattr (__NR_mq_open+5) -#define __NR_sys_kexec_load 283 -#define __NR_waitid 284 +#define __NR_set_thread_area 243 +#define __NR_get_thread_area 244 +#define __NR_io_setup 245 +#define __NR_io_destroy 246 +#define __NR_io_getevents 247 +#define __NR_io_submit 248 +#define __NR_io_cancel 249 +#define __NR_fadvise64 250 +/* 251 is unused */ +#define __NR_exit_group 252 +#define __NR_lookup_dcookie 253 +#define __NR_epoll_create 254 +#define __NR_epoll_ctl 255 +#define __NR_epoll_wait 256 +#define __NR_remap_file_pages 257 +#define __NR_set_tid_address 258 +#define __NR_timer_create 259 +#define __NR_timer_settime (__NR_timer_create+1) +#define __NR_timer_gettime (__NR_timer_create+2) +#define __NR_timer_getoverrun (__NR_timer_create+3) +#define __NR_timer_delete (__NR_timer_create+4) +#define __NR_clock_settime (__NR_timer_create+5) +#define __NR_clock_gettime (__NR_timer_create+6) +#define __NR_clock_getres (__NR_timer_create+7) +#define __NR_clock_nanosleep (__NR_timer_create+8) +#define __NR_statfs64 268 +#define __NR_fstatfs64 269 +#define __NR_tgkill 270 +#define __NR_utimes 271 +#define __NR_fadvise64_64 272 +#define __NR_vserver 273 +#define __NR_mbind 274 +#define __NR_get_mempolicy 275 +#define __NR_set_mempolicy 276 +#define __NR_mq_open 277 +#define __NR_mq_unlink (__NR_mq_open+1) +#define __NR_mq_timedsend (__NR_mq_open+2) +#define __NR_mq_timedreceive (__NR_mq_open+3) +#define __NR_mq_notify (__NR_mq_open+4) +#define __NR_mq_getsetattr (__NR_mq_open+5) +#define __NR_sys_kexec_load 283 +#define __NR_waitid 284 #define NR_syscalls 285 @@ -407,14 +407,10 @@ __syscall_return(type,__res); \ #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR -#define __ARCH_WANT_OLD_STAT #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#define __ARCH_WANT_SYS_SIGNAL #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_WAITPID @@ -422,11 +418,8 @@ __syscall_return(type,__res); \ #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK -#define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/ #define __ARCH_WANT_SYS_OLDUMOUNT -#define __ARCH_WANT_SYS_SIGPENDING -#define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION #endif @@ -451,7 +444,6 @@ __syscall_return(type,__res); \ */ static __inline__ _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount); asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); @@ -461,7 +453,6 @@ asmlinkage int sys_fork(struct pt_regs regs); asmlinkage int sys_vfork(struct pt_regs regs); asmlinkage int sys_pipe(unsigned long __user *fildes); asmlinkage int sys_ptrace(long request, long pid, long addr, long data); -asmlinkage long sys_iopl(unsigned long unused); struct sigaction; asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, -- cgit v1.2.3 From d88971f9f74f63f3b2d998289c50b243bc1c4bfc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Jan 2005 17:13:44 -0800 Subject: [PATCH] M68k: Remove nowhere referenced files M68k: Remove nowhere referenced files Signed-off-by: Domen Puncer Signed-off-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m68k/apollo/dn_debug.c | 22 ------------- arch/m68k/sun3x/sun3x_ksyms.c | 13 -------- include/asm-m68k/atari_SCCserial.h | 67 -------------------------------------- 3 files changed, 102 deletions(-) delete mode 100644 arch/m68k/apollo/dn_debug.c delete mode 100644 arch/m68k/sun3x/sun3x_ksyms.c delete mode 100644 include/asm-m68k/atari_SCCserial.h (limited to 'include') diff --git a/arch/m68k/apollo/dn_debug.c b/arch/m68k/apollo/dn_debug.c deleted file mode 100644 index b106969bd8fe..000000000000 --- a/arch/m68k/apollo/dn_debug.c +++ /dev/null @@ -1,22 +0,0 @@ - -#define DN_DEBUG_BUFFER_BASE 0x82800000 -#define DN_DEBUG_BUFFER_SIZE 8*1024*1024 - -static char *current_dbg_ptr=DN_DEBUG_BUFFER_BASE; - -int dn_deb_printf(const char *fmt, ...) { - - va_list args; - int i; - - if(current_dbg_ptr<(DN_DEBUG_BUFFER_BASE + DN_DEBUG_BUFFER_SIZE)) { - va_start(args,fmt); - i=vsprintf(current_dbg_ptr,fmt,args); - va_end(args); - current_dbg_ptr+=i; - - return i; - } - else - return 0; -} diff --git a/arch/m68k/sun3x/sun3x_ksyms.c b/arch/m68k/sun3x/sun3x_ksyms.c deleted file mode 100644 index 43e5a9af8abd..000000000000 --- a/arch/m68k/sun3x/sun3x_ksyms.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include -#include -#include - -/* - * Add things here when you find the need for it. - */ -EXPORT_SYMBOL(dvma_map_align); -EXPORT_SYMBOL(dvma_unmap); -EXPORT_SYMBOL(dvma_malloc_align); -EXPORT_SYMBOL(dvma_free); -EXPORT_SYMBOL(idprom); diff --git a/include/asm-m68k/atari_SCCserial.h b/include/asm-m68k/atari_SCCserial.h deleted file mode 100644 index de3af56c6874..000000000000 --- a/include/asm-m68k/atari_SCCserial.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _ATARI_SCCSERIAL_H -#define _ATARI_SCCSERIAL_H - -/* Special configuration ioctls for the Atari SCC5380 Serial - * Communications Controller - */ - -/* ioctl command codes */ - -#define TIOCGATSCC 0x54c0 /* get SCC configuration */ -#define TIOCSATSCC 0x54c1 /* set SCC configuration */ -#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */ - -/* Clock sources */ - -#define CLK_RTxC 0 -#define CLK_TRxC 1 -#define CLK_PCLK 2 - -/* baud_bases for the common clocks in the Atari. These are the real - * frequencies divided by 16. - */ - -#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */ -#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */ -#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */ -#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */ -#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused - * clock sources */ - -#define SCC_BAUD_BASE_M147_PCLK 312500 /* 5 MHz */ -#define SCC_BAUD_BASE_M147 312500 /* 5 MHz */ -#define SCC_BAUD_BASE_MVME_PCLK 781250 /* 12.5 MHz */ -#define SCC_BAUD_BASE_MVME 625000 /* 10.000 MHz */ -#define SCC_BAUD_BASE_BVME_PCLK 781250 /* 12.5 MHz */ /* XXX ??? */ -#define SCC_BAUD_BASE_BVME 460800 /* 7.3728 MHz */ - -/* The SCC configuration structure */ - -struct atari_SCCserial { - unsigned RTxC_base; /* base_baud of RTxC */ - unsigned TRxC_base; /* base_baud of TRxC */ - unsigned PCLK_base; /* base_baud of PCLK, for both channels! */ - struct { - unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */ - unsigned divisor; /* divisor for base baud, valid values: - * see below */ - } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300, - * 600, 1200, 1800, 2400, 4800, 9600, - * 19200, 38400, 57600 and 115200 bps. The - * last two could be replaced by other - * rates > 38400 if they're not possible. - */ -}; - -/* The following divisors are valid: - * - * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use - * the BRG) - * - * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible) - * - * - CLK_PCLK: >= 4 and even (no direct modes, only BRG) - * - */ - -#endif /* _ATARI_SCCSERIAL_H */ -- cgit v1.2.3 From a4a2d10db6c1e1ba2fe5077bc263b8d0254e6933 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Mon, 10 Jan 2005 17:14:45 -0800 Subject: [PATCH] cciss update to version 2.6.4 This patch removes support for 2 controllers that were recently cancelled and it adds support for the P600, a cciss based SAS controller due to ship in late March/early April '05. Neither of these controllers have made it to the field. Signed-off-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cciss.txt | 3 +-- drivers/block/cciss.c | 17 +++++++---------- include/linux/pci_ids.h | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index aadd46fc3001..74589c53a0c4 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt @@ -14,8 +14,7 @@ This driver is known to work with the following cards: * SA 6400 * SA 6400 U320 Expansion Module * SA 6i - * SA 6422 - * SA V100 + * SA P600 If nodes are not already created in the /dev/cciss directory, run as root: diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index f747fb3d13db..2f30018d3387 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -46,14 +46,14 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 2.6.2)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2) +#define DRIVER_NAME "HP CISS Driver (v 2.6.4)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,4) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2"); +MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.4"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i V100"); + " SA6i P600"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -80,10 +80,8 @@ const struct pci_device_id cciss_pci_device_id[] = { 0x0E11, 0x409D, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x4091, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409E, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS, - 0x103C, 0x3211, 0, 0, 0}, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, + 0x103C, 0x3225, 0, 0, 0}, {0,} }; MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); @@ -104,8 +102,7 @@ static struct board_type products[] = { { 0x409C0E11, "Smart Array 6400", &SA5_access}, { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, { 0x40910E11, "Smart Array 6i", &SA5_access}, - { 0x409E0E11, "Smart Array 6422", &SA5_access}, - { 0x3211103C, "Smart Array V100", &SA5_access}, + { 0x3225103C, "Smart Array P600", &SA5_access}, }; /* How long to wait (in millesconds) for board to go into simple mode */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f36775e68710..791a795862c2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -693,7 +693,7 @@ #define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c #define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 #define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 -#define PCI_DEVICE_ID_HP_CISS 0x3210 +#define PCI_DEVICE_ID_HP_CISSA 0x3220 #define PCI_VENDOR_ID_PCTECH 0x1042 #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 -- cgit v1.2.3 From 67547e35e2802ad9e2ad8c5e7fccb61ac12ce4e7 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 10 Jan 2005 17:18:41 -0800 Subject: [PATCH] optimize prefetch() usage in list_for_each_xxx This patch changes list_for_each_xxx iterators from: for (pos = (head)->next, prefetch(pos->next); pos != (head); pos = pos->next, prefetch(pos->next)) to: for (pos = (head)->next; prefetch(pos->next), pos != (head); pos = pos->next) Reduces my vmlinux .text size by 4401 bytes. Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/list.h | 48 ++++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/include/linux/list.h b/include/linux/list.h index 7cad5322077c..dd7cd54fa831 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -326,8 +326,8 @@ static inline void list_splice_init(struct list_head *list, * @head: the head for your list. */ #define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) + for (pos = (head)->next; prefetch(pos->next), pos != (head); \ + pos = pos->next) /** * __list_for_each - iterate over a list @@ -348,8 +348,8 @@ static inline void list_splice_init(struct list_head *list, * @head: the head for your list. */ #define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) + for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ + pos = pos->prev) /** * list_for_each_safe - iterate over a list safe against removal of list entry @@ -368,11 +368,9 @@ static inline void list_splice_init(struct list_head *list, * @member: the name of the list_struct within the struct. */ #define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) + for (pos = list_entry((head)->next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_reverse - iterate backwards over list of given type. @@ -381,11 +379,9 @@ static inline void list_splice_init(struct list_head *list, * @member: the name of the list_struct within the struct. */ #define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) /** * list_prepare_entry - prepare a pos entry for use as a start point in @@ -405,11 +401,9 @@ static inline void list_splice_init(struct list_head *list, * @member: the name of the list_struct within the struct. */ #define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry @@ -434,8 +428,8 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_rcu(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = rcu_dereference(pos->next), prefetch(pos->next)) + for (pos = (head)->next; prefetch(pos->next), pos != (head); \ + pos = rcu_dereference(pos->next)) #define __list_for_each_rcu(pos, head) \ for (pos = (head)->next; pos != (head); \ @@ -467,12 +461,10 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ pos = rcu_dereference(list_entry(pos->member.next, \ - typeof(*pos), member)), \ - prefetch(pos->member.next)) + typeof(*pos), member))) /** @@ -486,8 +478,8 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ - (pos) = rcu_dereference((pos)->next), prefetch((pos)->next)) + for ((pos) = (pos)->next; prefetch((pos)->next), (pos) != (head); \ + (pos) = rcu_dereference((pos)->next)) /* * Double linked lists with a single pointer list head. -- cgit v1.2.3 From 77aa6cbfb03f4bc3a3e9676efcd24879946438c4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Jan 2005 17:20:37 -0800 Subject: [PATCH] cleanup virtual console <-> selection.c interface Pass around pointers instead of indices into a global array between various files of the virtual console implementation and stop using obsfucting macros that expect certain variables to be in scope. This is a first step to get rid of the various global arrays in the VC code. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/selection.c | 44 +++-- drivers/char/vc_screen.c | 60 +++--- drivers/char/vt.c | 428 +++++++++++++++++++++-------------------- drivers/char/vt_ioctl.c | 2 +- include/linux/console_struct.h | 3 + include/linux/selection.h | 23 +-- 6 files changed, 284 insertions(+), 276 deletions(-) (limited to 'include') diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 0c265fe6713a..791b1fc1f4a0 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -33,7 +33,7 @@ extern void poke_blanked_console(void); /* Variables for selection control. */ /* Use a dynamic buffer, instead of static (Dec 1994) */ - int sel_cons; /* must not be disallocated */ +struct vc_data *sel_cons; /* must not be disallocated */ static volatile int sel_start = -1; /* cleared by clear_selection */ static int sel_end; static int sel_buffer_lth; @@ -44,20 +44,22 @@ static char *sel_buffer; /* set reverse video on characters s-e of console with selection. */ inline static void -highlight(const int s, const int e) { +highlight(const int s, const int e) +{ invert_screen(sel_cons, s, e-s+2, 1); } /* use complementary color to show the pointer */ inline static void -highlight_pointer(const int where) { +highlight_pointer(const int where) +{ complement_pos(sel_cons, where); } static unsigned char sel_pos(int n) { - return inverse_translate(vc_cons[sel_cons].d, screen_glyph(sel_cons, n)); + return inverse_translate(sel_cons, screen_glyph(sel_cons, n)); } /* remove the current selection highlight, if any, @@ -111,10 +113,10 @@ static inline unsigned short limit(const unsigned short v, const unsigned short /* set the current selection. Invoked by ioctl() or by kernel code. */ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) { + struct vc_data *vc = vc_cons[fg_console].d; int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; int i, ps, pe; - unsigned int currcons = fg_console; poke_blanked_console(); @@ -128,12 +130,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t __get_user(ye, &sel->ye); __get_user(sel_mode, &sel->sel_mode); xs--; ys--; xe--; ye--; - xs = limit(xs, video_num_columns - 1); - ys = limit(ys, video_num_lines - 1); - xe = limit(xe, video_num_columns - 1); - ye = limit(ye, video_num_lines - 1); - ps = ys * video_size_row + (xs << 1); - pe = ye * video_size_row + (xe << 1); + xs = limit(xs, vc->vc_cols - 1); + ys = limit(ys, vc->vc_rows - 1); + xe = limit(xe, vc->vc_cols - 1); + ye = limit(ye, vc->vc_rows - 1); + ps = ys * vc->vc_size_row + (xs << 1); + pe = ye * vc->vc_size_row + (xe << 1); if (sel_mode == TIOCL_SELCLEAR) { /* useful for screendump without selection highlights */ @@ -154,9 +156,9 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t pe = tmp; } - if (sel_cons != fg_console) { + if (sel_cons != vc_cons[fg_console].d) { clear_selection(); - sel_cons = fg_console; + sel_cons = vc_cons[fg_console].d; } switch (sel_mode) @@ -173,7 +175,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t (!spc && !inword(sel_pos(ps)))) break; new_sel_start = ps; - if (!(ps % video_size_row)) + if (!(ps % vc->vc_size_row)) break; } spc = isspace(sel_pos(pe)); @@ -183,14 +185,14 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t (!spc && !inword(sel_pos(pe)))) break; new_sel_end = pe; - if (!((pe + 2) % video_size_row)) + if (!((pe + 2) % vc->vc_size_row)) break; } break; case TIOCL_SELLINE: /* line-by-line selection */ - new_sel_start = ps - ps % video_size_row; - new_sel_end = pe + video_size_row - - pe % video_size_row - 2; + new_sel_start = ps - ps % vc->vc_size_row; + new_sel_end = pe + vc->vc_size_row + - pe % vc->vc_size_row - 2; break; case TIOCL_SELPOINTER: highlight_pointer(pe); @@ -204,11 +206,11 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t /* select to end of line if on trailing space */ if (new_sel_end > new_sel_start && - !atedge(new_sel_end, video_size_row) && + !atedge(new_sel_end, vc->vc_size_row) && isspace(sel_pos(new_sel_end))) { for (pe = new_sel_end + 2; ; pe += 2) if (!isspace(sel_pos(pe)) || - atedge(pe, video_size_row)) + atedge(pe, vc->vc_size_row)) break; if (isspace(sel_pos(pe))) new_sel_end = pe; @@ -255,7 +257,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t *bp = sel_pos(i); if (!isspace(*bp++)) obp = bp; - if (! ((i + 2) % video_size_row)) { + if (! ((i + 2) % vc->vc_size_row)) { /* strip trailing blanks from line and add newline, unless non-space at end of line. */ if (obp != bp) { diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c5c6b5e26850..55971a272ead 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -59,7 +59,7 @@ vcs_size(struct inode *inode) if (!vc_cons_allocated(currcons)) return -ENXIO; - size = video_num_lines * video_num_columns; + size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_cols; if (minor & 128) size = 2*size + HEADER_SIZE; @@ -99,6 +99,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); + struct vc_data *vc; long pos; long viewed, attr, read; int col, maxcol; @@ -126,6 +127,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ret = -ENXIO; if (!vc_cons_allocated(currcons)) goto unlock_out; + vc = vc_cons[currcons].d; ret = -EINVAL; if (pos < 0) @@ -159,15 +161,15 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) con_buf_start = con_buf0 = con_buf; orig_count = this_round; - maxcol = video_num_columns; + maxcol = vc->vc_cols; if (!attr) { - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); col = p % maxcol; p += maxcol - col; while (this_round-- > 0) { - *con_buf0++ = (vcs_scr_readw(currcons, org++) & 0xff); + *con_buf0++ = (vcs_scr_readw(vc, org++) & 0xff); if (++col == maxcol) { - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); col = 0; p += maxcol; } @@ -176,9 +178,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) if (p < HEADER_SIZE) { size_t tmp_count; - con_buf0[0] = (char) video_num_lines; - con_buf0[1] = (char) video_num_columns; - getconsxy(currcons, con_buf0 + 2); + con_buf0[0] = (char)vc->vc_rows; + con_buf0[1] = (char)vc->vc_cols; + getconsxy(vc, con_buf0 + 2); con_buf_start += p; this_round += p; @@ -214,7 +216,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) p /= 2; col = p % maxcol; - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); p += maxcol - col; /* Buffer has even length, so we can always copy @@ -224,10 +226,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) this_round = (this_round + 1) >> 1; while (this_round) { - *tmp_buf++ = vcs_scr_readw(currcons, org++); + *tmp_buf++ = vcs_scr_readw(vc, org++); this_round --; if (++col == maxcol) { - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); col = 0; p += maxcol; } @@ -270,6 +272,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); + struct vc_data *vc; long pos; long viewed, attr, size, written; char *con_buf0; @@ -299,6 +302,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) ret = -ENXIO; if (!vc_cons_allocated(currcons)) goto unlock_out; + vc = vc_cons[currcons].d; size = vcs_size(inode); ret = -EINVAL; @@ -351,10 +355,10 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) con_buf0 = con_buf; orig_count = this_round; - maxcol = video_num_columns; + maxcol = vc->vc_cols; p = pos; if (!attr) { - org0 = org = screen_pos(currcons, p, viewed); + org0 = org = screen_pos(vc, p, viewed); col = p % maxcol; p += maxcol - col; @@ -362,11 +366,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) unsigned char c = *con_buf0++; this_round--; - vcs_scr_writew(currcons, - (vcs_scr_readw(currcons, org) & 0xff00) | c, org); + vcs_scr_writew(vc, + (vcs_scr_readw(vc, org) & 0xff00) | c, org); org++; if (++col == maxcol) { - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); col = 0; p += maxcol; } @@ -375,34 +379,34 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) if (p < HEADER_SIZE) { char header[HEADER_SIZE]; - getconsxy(currcons, header + 2); + getconsxy(vc, header + 2); while (p < HEADER_SIZE && this_round > 0) { this_round--; header[p++] = *con_buf0++; } if (!viewed) - putconsxy(currcons, header + 2); + putconsxy(vc, header + 2); } p -= HEADER_SIZE; col = (p/2) % maxcol; if (this_round > 0) { - org0 = org = screen_pos(currcons, p/2, viewed); + org0 = org = screen_pos(vc, p/2, viewed); if ((p & 1) && this_round > 0) { char c; this_round--; c = *con_buf0++; #ifdef __BIG_ENDIAN - vcs_scr_writew(currcons, c | - (vcs_scr_readw(currcons, org) & 0xff00), org); + vcs_scr_writew(vc, c | + (vcs_scr_readw(vc, org) & 0xff00), org); #else - vcs_scr_writew(currcons, (c << 8) | - (vcs_scr_readw(currcons, org) & 0xff), org); + vcs_scr_writew(vc, (c << 8) | + (vcs_scr_readw(vc, org) & 0xff), org); #endif org++; p++; if (++col == maxcol) { - org = screen_pos(currcons, p/2, viewed); + org = screen_pos(vc, p/2, viewed); col = 0; } } @@ -413,11 +417,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) unsigned short w; w = get_unaligned(((const unsigned short *)con_buf0)); - vcs_scr_writew(currcons, w, org++); + vcs_scr_writew(vc, w, org++); con_buf0 += 2; this_round -= 2; if (++col == maxcol) { - org = screen_pos(currcons, p, viewed); + org = screen_pos(vc, p, viewed); col = 0; p += maxcol; } @@ -427,9 +431,9 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) c = *con_buf0++; #ifdef __BIG_ENDIAN - vcs_scr_writew(currcons, (vcs_scr_readw(currcons, org) & 0xff) | (c << 8), org); + vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff) | (c << 8), org); #else - vcs_scr_writew(currcons, (vcs_scr_readw(currcons, org) & 0xff00) | c, org); + vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff00) | c, org); #endif } } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7ef949fbceb5..261599fd095a 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -40,15 +40,6 @@ * - Arno Griffioen * - David Carter * - * Note that the abstract console driver allows all consoles to be of - * potentially different sizes, so the following variables depend on the - * current console (currcons): - * - * - video_num_columns - * - video_num_lines - * - video_size_row - * - can_do_color - * * The abstract console driver provides a generic interface for a text * console. It supports VGA text mode, frame buffer based graphical consoles * and special graphics processors that are only accessible through some @@ -146,13 +137,13 @@ static const struct consw *con_driver_map[MAX_NR_CONSOLES]; static int con_open(struct tty_struct *, struct file *); static void vc_init(unsigned int console, unsigned int rows, unsigned int cols, int do_clear); -static void gotoxy(int currcons, int new_x, int new_y); +static void gotoxy(struct vc_data *vc, int new_x, int new_y); static void save_cur(int currcons); static void reset_terminal(int currcons, int do_clear); static void con_flush_chars(struct tty_struct *tty); static void set_vesa_blanking(char __user *p); -static void set_cursor(int currcons); -static void hide_cursor(int currcons); +static void set_cursor(struct vc_data *vc); +static void hide_cursor(struct vc_data *vc); static void console_callback(void *ignored); static void blank_screen_t(unsigned long dummy); @@ -223,28 +214,32 @@ enum { * Low-Level Functions */ -#define IS_FG (currcons == fg_console) +#define IS_FG (currcons == fg_console) +#define IS_FG_VC(vc) (vc == vc_cons[fg_console].d) + #define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d) #ifdef VT_BUF_VRAM_ONLY -#define DO_UPDATE 0 +#define DO_UPDATE 0 +#define DO_UPDATE_VC(vc) 0 #else -#define DO_UPDATE IS_VISIBLE +#define DO_UPDATE IS_VISIBLE +#define DO_UPDATE_VC(vc) CON_IS_VISIBLE(vc) #endif static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data); static struct pm_dev *pm_con; -static inline unsigned short *screenpos(int currcons, int offset, int viewed) +static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed) { unsigned short *p; if (!viewed) - p = (unsigned short *)(origin + offset); - else if (!sw->con_screen_pos) - p = (unsigned short *)(visible_origin + offset); + p = (unsigned short *)(vc->vc_origin + offset); + else if (!vc->vc_sw->con_screen_pos) + p = (unsigned short *)(vc->vc_visible_origin + offset); else - p = sw->con_screen_pos(vc_cons[currcons].d, offset); + p = vc->vc_sw->con_screen_pos(vc, offset); return p; } @@ -265,14 +260,15 @@ static void scrup(int currcons, unsigned int t, unsigned int b, int nr) if (t+nr >= b) nr = b - t - 1; - if (b > video_num_lines || t >= b || nr < 1) + if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1) return; if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr)) return; - d = (unsigned short *) (origin+video_size_row*t); - s = (unsigned short *) (origin+video_size_row*(t+nr)); - scr_memmovew(d, s, (b-t-nr) * video_size_row); - scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr); + d = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t); + s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*(t+nr)); + scr_memmovew(d, s, (b-t-nr) * vc_cons[currcons].d->vc_size_row); + scr_memsetw(d + (b-t-nr) * vc_cons[currcons].d->vc_cols, video_erase_char, + vc_cons[currcons].d->vc_size_row * nr); } static void @@ -283,40 +279,40 @@ scrdown(int currcons, unsigned int t, unsigned int b, int nr) if (t+nr >= b) nr = b - t - 1; - if (b > video_num_lines || t >= b || nr < 1) + if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1) return; if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr)) return; - s = (unsigned short *) (origin+video_size_row*t); - step = video_num_columns * nr; - scr_memmovew(s + step, s, (b-t-nr)*video_size_row); + s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t); + step = vc_cons[currcons].d->vc_cols * nr; + scr_memmovew(s + step, s, (b-t-nr)*vc_cons[currcons].d->vc_size_row); scr_memsetw(s, video_erase_char, 2*step); } -static void do_update_region(int currcons, unsigned long start, int count) +static void do_update_region(struct vc_data *vc, unsigned long start, int count) { #ifndef VT_BUF_VRAM_ONLY unsigned int xx, yy, offset; u16 *p; p = (u16 *) start; - if (!sw->con_getxy) { - offset = (start - origin) / 2; - xx = offset % video_num_columns; - yy = offset / video_num_columns; + if (!vc->vc_sw->con_getxy) { + offset = (start - vc->vc_origin) / 2; + xx = offset % vc->vc_cols; + yy = offset / vc->vc_cols; } else { int nxx, nyy; - start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy); + start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy); xx = nxx; yy = nyy; } for(;;) { u16 attrib = scr_readw(p) & 0xff00; int startx = xx; u16 *q = p; - while (xx < video_num_columns && count) { + while (xx < vc->vc_cols && count) { if (attrib != (scr_readw(p) & 0xff00)) { if (p > q) - sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx); + vc->vc_sw->con_putcs(vc, q, p-q, yy, startx); startx = xx; q = p; attrib = scr_readw(p) & 0xff00; @@ -326,14 +322,14 @@ static void do_update_region(int currcons, unsigned long start, int count) count--; } if (p > q) - sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx); + vc->vc_sw->con_putcs(vc, q, p-q, yy, startx); if (!count) break; xx = 0; yy++; - if (sw->con_getxy) { + if (vc->vc_sw->con_getxy) { p = (u16 *)start; - start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL); + start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); } } #endif @@ -344,9 +340,9 @@ void update_region(int currcons, unsigned long start, int count) WARN_CONSOLE_UNLOCKED(); if (DO_UPDATE) { - hide_cursor(currcons); - do_update_region(currcons, start, count); - set_cursor(currcons); + hide_cursor(vc_cons[currcons].d); + do_update_region(vc_cons[currcons].d, start, count); + set_cursor(vc_cons[currcons].d); } } @@ -370,7 +366,7 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde */ { u8 a = color; - if (!can_do_color) + if (!vc_cons[currcons].d->vc_can_do_color) return _intensity | (_underline ? 4 : 0) | (_reverse ? 8 : 0) | @@ -401,31 +397,30 @@ static void update_attr(int currcons) } /* Note: inverting the screen twice should revert to the original state */ - -void invert_screen(int currcons, int offset, int count, int viewed) +void invert_screen(struct vc_data *vc, int offset, int count, int viewed) { unsigned short *p; WARN_CONSOLE_UNLOCKED(); count /= 2; - p = screenpos(currcons, offset, viewed); - if (sw->con_invert_region) - sw->con_invert_region(vc_cons[currcons].d, p, count); + p = screenpos(vc, offset, viewed); + if (vc->vc_sw->con_invert_region) + vc->vc_sw->con_invert_region(vc, p, count); #ifndef VT_BUF_VRAM_ONLY else { u16 *q = p; int cnt = count; u16 a; - if (!can_do_color) { + if (!vc->vc_can_do_color) { while (cnt--) { a = scr_readw(q); a ^= 0x0800; scr_writew(a, q); q++; } - } else if (hi_font_mask == 0x100) { + } else if (vc->vc_hi_font_mask == 0x100) { while (cnt--) { a = scr_readw(q); a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4); @@ -442,12 +437,12 @@ void invert_screen(int currcons, int offset, int count, int viewed) } } #endif - if (DO_UPDATE) - do_update_region(currcons, (unsigned long) p, count); + if (DO_UPDATE_VC(vc)) + do_update_region(vc, (unsigned long) p, count); } /* used by selection: complement pointer position */ -void complement_pos(int currcons, int offset) +void complement_pos(struct vc_data *vc, int offset) { static unsigned short *p; static unsigned short old; @@ -457,21 +452,21 @@ void complement_pos(int currcons, int offset) if (p) { scr_writew(old, p); - if (DO_UPDATE) - sw->con_putc(vc_cons[currcons].d, old, oldy, oldx); + if (DO_UPDATE_VC(vc)) + vc->vc_sw->con_putc(vc, old, oldy, oldx); } if (offset == -1) p = NULL; else { unsigned short new; - p = screenpos(currcons, offset, 1); + p = screenpos(vc, offset, 1); old = scr_readw(p); - new = old ^ complement_mask; + new = old ^ vc->vc_complement_mask; scr_writew(new, p); - if (DO_UPDATE) { - oldx = (offset >> 1) % video_num_columns; - oldy = (offset >> 1) / video_num_columns; - sw->con_putc(vc_cons[currcons].d, new, oldy, oldx); + if (DO_UPDATE_VC(vc)) { + oldx = (offset >> 1) % vc->vc_cols; + oldy = (offset >> 1) / vc->vc_cols; + vc->vc_sw->con_putc(vc, new, oldy, oldx); } } } @@ -480,7 +475,7 @@ static void insert_char(int currcons, unsigned int nr) { unsigned short *p, *q = (unsigned short *) pos; - p = q + video_num_columns - nr - x; + p = q + vc_cons[currcons].d->vc_cols - nr - x; while (--p >= q) scr_writew(scr_readw(p), p + nr); scr_memsetw(q, video_erase_char, nr*2); @@ -488,7 +483,7 @@ static void insert_char(int currcons, unsigned int nr) if (DO_UPDATE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1, - video_num_columns-x-nr); + vc_cons[currcons].d->vc_cols-x-nr); attr = video_erase_char >> 8; while (nr--) sw->con_putc(vc_cons[currcons].d, @@ -502,7 +497,7 @@ static void delete_char(int currcons, unsigned int nr) unsigned int i = x; unsigned short *p = (unsigned short *) pos; - while (++i <= video_num_columns - nr) { + while (++i <= vc_cons[currcons].d->vc_cols - nr) { scr_writew(scr_readw(p+nr), p); p++; } @@ -511,22 +506,22 @@ static void delete_char(int currcons, unsigned int nr) if (DO_UPDATE) { unsigned short oldattr = attr; sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1, - video_num_columns-x-nr); + vc_cons[currcons].d->vc_cols-x-nr); attr = video_erase_char >> 8; while (nr--) sw->con_putc(vc_cons[currcons].d, video_erase_char, y, - video_num_columns-1-nr); + vc_cons[currcons].d->vc_cols-1-nr); attr = oldattr; } } static int softcursor_original; -static void add_softcursor(int currcons) +static void add_softcursor(struct vc_data *vc) { - int i = scr_readw((u16 *) pos); - u32 type = cursor_type; + int i = scr_readw((u16 *) vc->vc_pos); + u32 type = vc->vc_cursor_type; if (! (type & 0x10)) return; if (softcursor_original != -1) return; @@ -535,41 +530,43 @@ static void add_softcursor(int currcons) i ^= ((type) & 0xff00 ); if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; - scr_writew(i, (u16 *) pos); - if (DO_UPDATE) - sw->con_putc(vc_cons[currcons].d, i, y, x); + scr_writew(i, (u16 *) vc->vc_pos); + if (DO_UPDATE_VC(vc)) + vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x); } -static void hide_softcursor(int currcons) +static void hide_softcursor(struct vc_data *vc) { if (softcursor_original != -1) { - scr_writew(softcursor_original,(u16 *) pos); - if (DO_UPDATE) - sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x); + scr_writew(softcursor_original, (u16 *)vc->vc_pos); + if (DO_UPDATE_VC(vc)) + vc->vc_sw->con_putc(vc, softcursor_original, + vc->vc_y, vc->vc_x); softcursor_original = -1; } } -static void hide_cursor(int currcons) +static void hide_cursor(struct vc_data *vc) { - if (currcons == sel_cons) + if (vc == sel_cons) clear_selection(); - sw->con_cursor(vc_cons[currcons].d,CM_ERASE); - hide_softcursor(currcons); + vc->vc_sw->con_cursor(vc, CM_ERASE); + hide_softcursor(vc); } -static void set_cursor(int currcons) +static void set_cursor(struct vc_data *vc) { - if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS) - return; - if (deccm) { - if (currcons == sel_cons) - clear_selection(); - add_softcursor(currcons); - if ((cursor_type & 0x0f) != 1) - sw->con_cursor(vc_cons[currcons].d,CM_DRAW); - } else - hide_cursor(currcons); + if (!IS_FG_VC(vc) || console_blanked || + vc->vc_vt->vc_mode == KD_GRAPHICS) + return; + if (vc->vc_deccm) { + if (vc == sel_cons) + clear_selection(); + add_softcursor(vc); + if ((vc->vc_cursor_type & 0x0f) != 1) + vc->vc_sw->con_cursor(vc, CM_DRAW); + } else + hide_cursor(vc); } static void set_origin(int currcons) @@ -582,7 +579,7 @@ static void set_origin(int currcons) origin = (unsigned long) screenbuf; visible_origin = origin; scr_end = origin + screenbuf_size; - pos = origin + video_size_row*y + 2*x; + pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x; } static inline void save_screen(int currcons) @@ -623,7 +620,7 @@ void redraw_screen(int new_console, int is_switch) if (is_switch) { currcons = fg_console; - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); if (fg_console != new_console) { struct vc_data **display = vc_cons[new_console].d->vc_display_fg; old_console = (*display) ? (*display)->vc_num : fg_console; @@ -640,7 +637,7 @@ void redraw_screen(int new_console, int is_switch) } } else { currcons = new_console; - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); } if (redraw) { @@ -661,9 +658,9 @@ void redraw_screen(int new_console, int is_switch) clear_buffer_attributes(currcons); } if (update && vcmode != KD_GRAPHICS) - do_update_region(currcons, origin, screenbuf_size/2); + do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2); } - set_cursor(currcons); + set_cursor(vc_cons[currcons].d); if (is_switch) { set_leds(); compute_shiftstate(); @@ -696,13 +693,14 @@ static void visual_init(int currcons, int init) vc_cons[currcons].d->vc_uni_pagedir = 0; hi_font_mask = 0; complement_mask = 0; - can_do_color = 0; + vc_cons[currcons].d->vc_can_do_color = 0; sw->con_init(vc_cons[currcons].d, init); if (!complement_mask) - complement_mask = can_do_color ? 0x7700 : 0x0800; + complement_mask = + vc_cons[currcons].d->vc_can_do_color ? 0x7700 : 0x0800; s_complement_mask = complement_mask; - video_size_row = video_num_columns<<1; - screenbuf_size = video_num_lines*video_size_row; + vc_cons[currcons].d->vc_size_row = vc_cons[currcons].d->vc_cols<<1; + screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row; } int vc_allocate(unsigned int currcons) /* return 0 on success */ @@ -730,6 +728,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ memset((void *)p, 0, structsize); vc_cons[currcons].d = (struct vc_data *)p; vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data)); + vc_cons[currcons].d->vc_vt = vt_cons[currcons]; visual_init(currcons, 1); if (!*vc_cons[currcons].d->vc_uni_pagedir_loc) con_set_default_unimap(currcons); @@ -742,7 +741,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ } screenbuf = (unsigned short *) q; kmalloced = 1; - vc_init(currcons, video_num_lines, video_num_columns, 1); + vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols, 1); if (!pm_con) { pm_con = pm_register(PM_SYS_DEV, @@ -785,21 +784,21 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW) return -EINVAL; - new_cols = (cols ? cols : video_num_columns); - new_rows = (lines ? lines : video_num_lines); + new_cols = (cols ? cols : vc_cons[currcons].d->vc_cols); + new_rows = (lines ? lines : vc_cons[currcons].d->vc_rows); new_row_size = new_cols << 1; new_screen_size = new_row_size * new_rows; - if (new_cols == video_num_columns && new_rows == video_num_lines) + if (new_cols == vc_cons[currcons].d->vc_cols && new_rows == vc_cons[currcons].d->vc_rows) return 0; newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER); if (!newscreen) return -ENOMEM; - old_rows = video_num_lines; - old_cols = video_num_columns; - old_row_size = video_size_row; + old_rows = vc_cons[currcons].d->vc_rows; + old_cols = vc_cons[currcons].d->vc_cols; + old_row_size = vc_cons[currcons].d->vc_size_row; old_screen_size = screenbuf_size; err = resize_screen(currcons, new_cols, new_rows); @@ -808,9 +807,9 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) return err; } - video_num_lines = new_rows; - video_num_columns = new_cols; - video_size_row = new_row_size; + vc_cons[currcons].d->vc_rows = new_rows; + vc_cons[currcons].d->vc_cols = new_cols; + vc_cons[currcons].d->vc_size_row = new_row_size; screenbuf_size = new_screen_size; rlth = min(old_row_size, new_row_size); @@ -841,16 +840,16 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) /* do part of a reset_terminal() */ top = 0; - bottom = video_num_lines; - gotoxy(currcons, x, y); + bottom = vc_cons[currcons].d->vc_rows; + gotoxy(vc_cons[currcons].d, x, y); save_cur(currcons); if (vc_cons[currcons].d->vc_tty) { struct winsize ws, *cws = &vc_cons[currcons].d->vc_tty->winsize; memset(&ws, 0, sizeof(ws)); - ws.ws_row = video_num_lines; - ws.ws_col = video_num_columns; + ws.ws_row = vc_cons[currcons].d->vc_rows; + ws.ws_col = vc_cons[currcons].d->vc_cols; ws.ws_ypixel = video_scan_lines; if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && vc_cons[currcons].d->vc_tty->pgrp > 0) @@ -913,38 +912,40 @@ int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, * might also be negative. If the given position is out of * bounds, the cursor is placed at the nearest margin. */ -static void gotoxy(int currcons, int new_x, int new_y) +static void gotoxy(struct vc_data *vc, int new_x, int new_y) { int min_y, max_y; if (new_x < 0) - x = 0; - else - if (new_x >= video_num_columns) - x = video_num_columns - 1; + vc->vc_x = 0; + else { + if (new_x >= vc->vc_cols) + vc->vc_x = vc->vc_cols - 1; else - x = new_x; - if (decom) { - min_y = top; - max_y = bottom; + vc->vc_x = new_x; + } + + if (vc->vc_decom) { + min_y = vc->vc_top; + max_y = vc->vc_bottom; } else { min_y = 0; - max_y = video_num_lines; + max_y = vc->vc_rows; } if (new_y < min_y) - y = min_y; + vc->vc_y = min_y; else if (new_y >= max_y) - y = max_y - 1; + vc->vc_y = max_y - 1; else - y = new_y; - pos = origin + y*video_size_row + (x<<1); - need_wrap = 0; + vc->vc_y = new_y; + vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1); + vc->vc_need_wrap = 0; } /* for absolute user moves, when decom is set */ static void gotoxay(int currcons, int new_x, int new_y) { - gotoxy(currcons, new_x, decom ? (top+new_y) : new_y); + gotoxy(vc_cons[currcons].d, new_x, decom ? (top+new_y) : new_y); } void scrollback(int lines) @@ -952,7 +953,7 @@ void scrollback(int lines) int currcons = fg_console; if (!lines) - lines = video_num_lines/2; + lines = vc_cons[currcons].d->vc_rows/2; scrolldelta(-lines); } @@ -961,7 +962,7 @@ void scrollfront(int lines) int currcons = fg_console; if (!lines) - lines = video_num_lines/2; + lines = vc_cons[currcons].d->vc_rows/2; scrolldelta(lines); } @@ -972,9 +973,9 @@ static void lf(int currcons) */ if (y+1 == bottom) scrup(currcons,top,bottom,1); - else if (y < video_num_lines-1) { + else if (y < vc_cons[currcons].d->vc_rows-1) { y++; - pos += video_size_row; + pos += vc_cons[currcons].d->vc_size_row; } need_wrap = 0; } @@ -988,7 +989,7 @@ static void ri(int currcons) scrdown(currcons,top,bottom,1); else if (y > 0) { y--; - pos -= video_size_row; + pos -= vc_cons[currcons].d->vc_size_row; } need_wrap = 0; } @@ -1025,10 +1026,10 @@ static void csi_J(int currcons, int vpar) if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, y, x, 1, - video_num_columns-x); + vc_cons[currcons].d->vc_cols-x); sw->con_clear(vc_cons[currcons].d, y+1, 0, - video_num_lines-y-1, - video_num_columns); + vc_cons[currcons].d->vc_rows-y-1, + vc_cons[currcons].d->vc_cols); } break; case 1: /* erase from start to cursor */ @@ -1037,18 +1038,18 @@ static void csi_J(int currcons, int vpar) if (DO_UPDATE) { /* do in two stages */ sw->con_clear(vc_cons[currcons].d, 0, 0, y, - video_num_columns); + vc_cons[currcons].d->vc_cols); sw->con_clear(vc_cons[currcons].d, y, 0, 1, x + 1); } break; case 2: /* erase whole display */ - count = video_num_columns * video_num_lines; + count = vc_cons[currcons].d->vc_cols * vc_cons[currcons].d->vc_rows; start = (unsigned short *) origin; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, 0, 0, - video_num_lines, - video_num_columns); + vc_cons[currcons].d->vc_rows, + vc_cons[currcons].d->vc_cols); break; default: return; @@ -1064,11 +1065,11 @@ static void csi_K(int currcons, int vpar) switch (vpar) { case 0: /* erase from cursor to end of line */ - count = video_num_columns-x; + count = vc_cons[currcons].d->vc_cols-x; start = (unsigned short *) pos; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, x, 1, - video_num_columns-x); + vc_cons[currcons].d->vc_cols-x); break; case 1: /* erase from start of line to cursor */ start = (unsigned short *) (pos - (x<<1)); @@ -1079,10 +1080,10 @@ static void csi_K(int currcons, int vpar) break; case 2: /* erase whole line */ start = (unsigned short *) (pos - (x<<1)); - count = video_num_columns; + count = vc_cons[currcons].d->vc_cols; if (DO_UPDATE) sw->con_clear(vc_cons[currcons].d, y, 0, 1, - video_num_columns); + vc_cons[currcons].d->vc_cols); break; default: return; @@ -1097,7 +1098,7 @@ static void csi_X(int currcons, int vpar) /* erase the following vpar positions if (!vpar) vpar++; - count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; + count = (vpar > vc_cons[currcons].d->vc_cols-x) ? (vc_cons[currcons].d->vc_cols-x) : vpar; scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count); if (DO_UPDATE) @@ -1270,7 +1271,7 @@ static void set_mode(int currcons, int on_off) case 3: /* 80/132 mode switch unimplemented */ deccolm = on_off; #if 0 - (void) vc_resize(deccolm ? 132 : 80, video_num_lines); + (void) vc_resize(deccolm ? 132 : 80, vc_cons[currcons].d->vc_rows); /* this alone does not suffice; some user mode utility has to change the hardware regs */ #endif @@ -1278,7 +1279,7 @@ static void set_mode(int currcons, int on_off) case 5: /* Inverted screen on/off */ if (decscnm != on_off) { decscnm = on_off; - invert_screen(currcons, 0, screenbuf_size, 0); + invert_screen(vc_cons[currcons].d, 0, screenbuf_size, 0); update_attr(currcons); } break; @@ -1325,14 +1326,16 @@ static void setterm_command(int currcons) { switch(par[0]) { case 1: /* set color for underline mode */ - if (can_do_color && par[1] < 16) { + if (vc_cons[currcons].d->vc_can_do_color && + par[1] < 16) { ulcolor = color_table[par[1]]; if (underline) update_attr(currcons); } break; case 2: /* set color for half intensity mode */ - if (can_do_color && par[1] < 16) { + if (vc_cons[currcons].d->vc_can_do_color && + par[1] < 16) { halfcolor = color_table[par[1]]; if (intensity == 0) update_attr(currcons); @@ -1381,8 +1384,8 @@ static void setterm_command(int currcons) /* console_sem is held */ static void csi_at(int currcons, unsigned int nr) { - if (nr > video_num_columns - x) - nr = video_num_columns - x; + if (nr > vc_cons[currcons].d->vc_cols - x) + nr = vc_cons[currcons].d->vc_cols - x; else if (!nr) nr = 1; insert_char(currcons, nr); @@ -1391,8 +1394,8 @@ static void csi_at(int currcons, unsigned int nr) /* console_sem is held */ static void csi_L(int currcons, unsigned int nr) { - if (nr > video_num_lines - y) - nr = video_num_lines - y; + if (nr > vc_cons[currcons].d->vc_rows - y) + nr = vc_cons[currcons].d->vc_rows - y; else if (!nr) nr = 1; scrdown(currcons,y,bottom,nr); @@ -1402,8 +1405,8 @@ static void csi_L(int currcons, unsigned int nr) /* console_sem is held */ static void csi_P(int currcons, unsigned int nr) { - if (nr > video_num_columns - x) - nr = video_num_columns - x; + if (nr > vc_cons[currcons].d->vc_cols - x) + nr = vc_cons[currcons].d->vc_cols - x; else if (!nr) nr = 1; delete_char(currcons, nr); @@ -1412,8 +1415,8 @@ static void csi_P(int currcons, unsigned int nr) /* console_sem is held */ static void csi_M(int currcons, unsigned int nr) { - if (nr > video_num_lines - y) - nr = video_num_lines - y; + if (nr > vc_cons[currcons].d->vc_rows - y) + nr = vc_cons[currcons].d->vc_rows - y; else if (!nr) nr=1; scrup(currcons,y,bottom,nr); @@ -1438,7 +1441,7 @@ static void save_cur(int currcons) /* console_sem is held */ static void restore_cur(int currcons) { - gotoxy(currcons,saved_x,saved_y); + gotoxy(vc_cons[currcons].d,saved_x,saved_y); intensity = s_intensity; underline = s_underline; blink = s_blink; @@ -1460,7 +1463,7 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, static void reset_terminal(int currcons, int do_clear) { top = 0; - bottom = video_num_lines; + bottom = vc_cons[currcons].d->vc_rows; vc_state = ESnormal; ques = 0; translate = set_translate(LAT1_MAP,currcons); @@ -1507,7 +1510,7 @@ static void reset_terminal(int currcons, int do_clear) bell_pitch = DEFAULT_BELL_PITCH; bell_duration = DEFAULT_BELL_DURATION; - gotoxy(currcons,0,0); + gotoxy(vc_cons[currcons].d, 0, 0); save_cur(currcons); if (do_clear) csi_J(currcons,2); @@ -1532,7 +1535,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) return; case 9: pos -= (x << 1); - while (x < video_num_columns - 1) { + while (x < vc_cons[currcons].d->vc_cols - 1) { x++; if (tab_stop[x >> 5] & (1 << (x & 31))) break; @@ -1719,31 +1722,31 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) switch(c) { case 'G': case '`': if (par[0]) par[0]--; - gotoxy(currcons,par[0],y); + gotoxy(vc_cons[currcons].d, par[0], y); return; case 'A': if (!par[0]) par[0]++; - gotoxy(currcons,x,y-par[0]); + gotoxy(vc_cons[currcons].d, x, y-par[0]); return; case 'B': case 'e': if (!par[0]) par[0]++; - gotoxy(currcons,x,y+par[0]); + gotoxy(vc_cons[currcons].d, x, y+par[0]); return; case 'C': case 'a': if (!par[0]) par[0]++; - gotoxy(currcons,x+par[0],y); + gotoxy(vc_cons[currcons].d, x+par[0], y); return; case 'D': if (!par[0]) par[0]++; - gotoxy(currcons,x-par[0],y); + gotoxy(vc_cons[currcons].d, x-par[0], y); return; case 'E': if (!par[0]) par[0]++; - gotoxy(currcons,0,y+par[0]); + gotoxy(vc_cons[currcons].d, 0, y+par[0]); return; case 'F': if (!par[0]) par[0]++; - gotoxy(currcons,0,y-par[0]); + gotoxy(vc_cons[currcons].d, 0, y-par[0]); return; case 'd': if (par[0]) par[0]--; @@ -1797,10 +1800,10 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) if (!par[0]) par[0]++; if (!par[1]) - par[1] = video_num_lines; + par[1] = vc_cons[currcons].d->vc_rows; /* Minimum allowed region is 2 lines */ if (par[0] < par[1] && - par[1] <= video_num_lines) { + par[1] <= vc_cons[currcons].d->vc_rows) { top=par[0]-1; bottom=par[1]; gotoxay(currcons,0,0); @@ -1847,7 +1850,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) csi_J(currcons, 2); video_erase_char = (video_erase_char & 0xff00) | ' '; - do_update_region(currcons, origin, screenbuf_size/2); + do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2); } return; case ESsetG0: @@ -1963,7 +1966,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co /* undraw cursor first */ if (IS_FG) - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); while (!tty->stopped && count) { int orig = *buf; @@ -2065,7 +2068,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co draw_x = x; draw_from = pos; } - if (x == video_num_columns - 1) { + if (x == vc_cons[currcons].d->vc_cols - 1) { need_wrap = decawm; draw_to = pos+2; } else { @@ -2102,7 +2105,7 @@ static void console_callback(void *ignored) if (want_console >= 0) { if (want_console != fg_console && vc_cons_allocated(want_console)) { - hide_cursor(fg_console); + hide_cursor(vc_cons[fg_console].d); change_console(want_console); /* we only changed when the console had already been allocated - a new console is not created @@ -2176,7 +2179,7 @@ void vt_console_print(struct console *co, const char *b, unsigned count) /* undraw cursor first */ if (IS_FG) - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); start = (ushort *)pos; @@ -2209,7 +2212,7 @@ void vt_console_print(struct console *co, const char *b, unsigned count) } scr_writew((attr << 8) + c, (unsigned short *) pos); cnt++; - if (myx == video_num_columns - 1) { + if (myx == vc_cons[currcons].d->vc_cols - 1) { need_wrap = 1; continue; } @@ -2220,12 +2223,12 @@ void vt_console_print(struct console *co, const char *b, unsigned count) if (IS_VISIBLE) sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x); x += cnt; - if (x == video_num_columns) { + if (x == vc_cons[currcons].d->vc_cols) { x--; need_wrap = 1; } } - set_cursor(currcons); + set_cursor(vc_cons[currcons].d); if (!oops_in_progress) poke_blanked_console(); @@ -2438,7 +2441,7 @@ static void con_flush_chars(struct tty_struct *tty) acquire_console_sem(); vt = tty->driver_data; if (vt) - set_cursor(vt->vc_num); + set_cursor(vc_cons[vt->vc_num].d); release_console_sem(); } @@ -2459,8 +2462,8 @@ static int con_open(struct tty_struct *tty, struct file *filp) vc_cons[currcons].d->vc_tty = tty; if (!tty->winsize.ws_row && !tty->winsize.ws_col) { - tty->winsize.ws_row = video_num_lines; - tty->winsize.ws_col = video_num_columns; + tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; + tty->winsize.ws_col = vc_cons[currcons].d->vc_cols; } release_console_sem(); vcs_make_devfs(tty); @@ -2507,10 +2510,10 @@ static void vc_init(unsigned int currcons, unsigned int rows, { int j, k ; - video_num_columns = cols; - video_num_lines = rows; - video_size_row = cols<<1; - screenbuf_size = video_num_lines * video_size_row; + vc_cons[currcons].d->vc_cols = cols; + vc_cons[currcons].d->vc_rows = rows; + vc_cons[currcons].d->vc_size_row = cols<<1; + screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row; set_origin(currcons); pos = origin; @@ -2563,22 +2566,23 @@ static int __init con_init(void) alloc_bootmem(sizeof(struct vc_data)); vt_cons[currcons] = (struct vt_struct *) alloc_bootmem(sizeof(struct vt_struct)); + vc_cons[currcons].d->vc_vt = vt_cons[currcons]; visual_init(currcons, 1); screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size); kmalloced = 0; - vc_init(currcons, video_num_lines, video_num_columns, + vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols, currcons || !sw->con_save_screen); } currcons = fg_console = 0; master_display_fg = vc_cons[currcons].d; set_origin(currcons); save_screen(currcons); - gotoxy(currcons,x,y); + gotoxy(vc_cons[currcons].d, x, y); csi_J(currcons, 0); update_screen(fg_console); printk("Console: %s %s %dx%d", - can_do_color ? "colour" : "mono", - display_desc, video_num_columns, video_num_lines); + vc_cons[currcons].d->vc_can_do_color ? "colour" : "mono", + display_desc, vc_cons[currcons].d->vc_cols, vc_cons[currcons].d->vc_rows); printable = 1; printk("\n"); @@ -2690,7 +2694,7 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt) origin = (unsigned long) screenbuf; visible_origin = origin; scr_end = origin + screenbuf_size; - pos = origin + video_size_row*y + 2*x; + pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x; visual_init(i, 0); update_attr(i); @@ -2788,7 +2792,7 @@ void do_blank_screen(int entering_gfx) /* entering graphics mode? */ if (entering_gfx) { - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); save_screen(currcons); sw->con_blank(vc_cons[currcons].d, -1, 1); console_blanked = fg_console + 1; @@ -2802,7 +2806,7 @@ void do_blank_screen(int entering_gfx) return; } - hide_cursor(currcons); + hide_cursor(vc_cons[currcons].d); del_timer_sync(&console_timer); blank_timer_expired = 0; @@ -2859,7 +2863,7 @@ void do_unblank_screen(int leaving_gfx) if (console_blank_hook) console_blank_hook(0); set_palette(currcons); - set_cursor(fg_console); + set_cursor(vc_cons[fg_console].d); } EXPORT_SYMBOL(do_unblank_screen); @@ -3185,47 +3189,47 @@ int con_font_op(int currcons, struct console_font_op *op) */ /* used by selection */ -u16 screen_glyph(int currcons, int offset) +u16 screen_glyph(struct vc_data *vc, int offset) { - u16 w = scr_readw(screenpos(currcons, offset, 1)); + u16 w = scr_readw(screenpos(vc, offset, 1)); u16 c = w & 0xff; - if (w & hi_font_mask) + if (w & vc->vc_hi_font_mask) c |= 0x100; return c; } /* used by vcs - note the word offset */ -unsigned short *screen_pos(int currcons, int w_offset, int viewed) +unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) { - return screenpos(currcons, 2 * w_offset, viewed); + return screenpos(vc, 2 * w_offset, viewed); } -void getconsxy(int currcons, unsigned char *p) +void getconsxy(struct vc_data *vc, unsigned char *p) { - p[0] = x; - p[1] = y; + p[0] = vc->vc_x; + p[1] = vc->vc_y; } -void putconsxy(int currcons, unsigned char *p) +void putconsxy(struct vc_data *vc, unsigned char *p) { - gotoxy(currcons, p[0], p[1]); - set_cursor(currcons); + gotoxy(vc, p[0], p[1]); + set_cursor(vc); } -u16 vcs_scr_readw(int currcons, const u16 *org) +u16 vcs_scr_readw(struct vc_data *vc, const u16 *org) { - if ((unsigned long)org == pos && softcursor_original != -1) + if ((unsigned long)org == vc->vc_pos && softcursor_original != -1) return softcursor_original; return scr_readw(org); } -void vcs_scr_writew(int currcons, u16 val, u16 *org) +void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org) { scr_writew(val, org); - if ((unsigned long)org == pos) { + if ((unsigned long)org == vc->vc_pos) { softcursor_original = -1; - add_softcursor(currcons); + add_softcursor(vc); } } diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index dd8e2f7817f5..ad3a5d3d394c 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -37,7 +37,7 @@ char vt_dont_switch; extern struct tty_driver *console_driver; #define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) -#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons) +#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) /* * Console (vt and kd) routines, as defined by USL SVR4 manual, and by diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index a9a2a486234c..062049ca5c44 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -9,6 +9,8 @@ * to achieve effects such as fast scrolling by changing the origin. */ +struct vt_struct; + #define NPAR 16 struct vc_data { @@ -87,6 +89,7 @@ struct vc_data { struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ unsigned long vc_uni_pagedir; unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ + struct vt_struct *vc_vt; /* additional information is in vt_kern.h */ }; diff --git a/include/linux/selection.h b/include/linux/selection.h index 059c958951f3..ed3408b400f1 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -10,7 +10,7 @@ #include #include -extern int sel_cons; +extern struct vc_data *sel_cons; extern void clear_selection(void); extern int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty); @@ -19,11 +19,6 @@ extern int sel_loadlut(char __user *p); extern int mouse_reporting(void); extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); -#define video_num_columns (vc_cons[currcons].d->vc_cols) -#define video_num_lines (vc_cons[currcons].d->vc_rows) -#define video_size_row (vc_cons[currcons].d->vc_size_row) -#define can_do_color (vc_cons[currcons].d->vc_can_do_color) - extern int console_blanked; extern unsigned char color_table[]; @@ -31,15 +26,15 @@ extern int default_red[]; extern int default_grn[]; extern int default_blu[]; -extern unsigned short *screen_pos(int currcons, int w_offset, int viewed); -extern u16 screen_glyph(int currcons, int offset); -extern void complement_pos(int currcons, int offset); -extern void invert_screen(int currcons, int offset, int count, int shift); +extern unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed); +extern u16 screen_glyph(struct vc_data *vc, int offset); +extern void complement_pos(struct vc_data *vc, int offset); +extern void invert_screen(struct vc_data *vc, int offset, int count, int shift); -extern void getconsxy(int currcons, unsigned char *p); -extern void putconsxy(int currcons, unsigned char *p); +extern void getconsxy(struct vc_data *vc, unsigned char *p); +extern void putconsxy(struct vc_data *vc, unsigned char *p); -extern u16 vcs_scr_readw(int currcons, const u16 *org); -extern void vcs_scr_writew(int currcons, u16 val, u16 *org); +extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org); +extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); #endif -- cgit v1.2.3 From f5dbb2b796763f47bd81ccf7e12f26e67243e7d1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Jan 2005 17:20:52 -0800 Subject: [PATCH] warn about cli, sti & co uses even on UP These don't exist on SMP at all, at least warn on compiling for UP. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/interrupt.h | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 991831cff1da..d99e7aeb7d33 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -61,12 +61,30 @@ extern void enable_irq(unsigned int irq); * Temporary defines for UP kernels, until all code gets fixed. */ #ifndef CONFIG_SMP -# define cli() local_irq_disable() -# define sti() local_irq_enable() -# define save_flags(x) local_save_flags(x) -# define restore_flags(x) local_irq_restore(x) -# define save_and_cli(x) local_irq_save(x) -#endif +static inline void __deprecated cli(void) +{ + local_irq_disable(); +} +static inline void __deprecated sti(void) +{ + local_irq_enable(); +} +static inline void __deprecated save_flags(unsigned long *x) +{ + local_save_flags(*x); +} +#define save_flags(x) save_flags(&x); +static inline void __deprecated restore_flags(unsigned long x) +{ + local_irq_restore(x); +} + +static inline void __deprecated save_and_cli(unsigned long *x) +{ + local_irq_save(*x); +} +#define save_and_cli(x) save_and_cli(&x) +#endif /* CONFIG_SMP */ /* SoftIRQ primitives. */ #define local_bh_disable() \ -- cgit v1.2.3 From 9f6142d7d1f6fbe7c240e1a6fe067feef570634b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 10 Jan 2005 17:21:11 -0800 Subject: [PATCH] remove umsdos from tree UMSDOS has been non-function since early 2.5 and would need a major rewrite to be resurrected (which I don't hope anyone plans as it's a really horrible hack) From: Adrian Bunk With umsdos gone, there's no longer a MAINTAINERS entry required. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/00-INDEX | 2 - Documentation/filesystems/umsdos.txt | 100 --- MAINTAINERS | 7 - fs/Kconfig | 46 +- fs/Makefile | 1 - fs/umsdos/Makefile | 13 - fs/umsdos/README-WIP.txt | 114 ---- fs/umsdos/dir.c | 810 ------------------------ fs/umsdos/emd.c | 660 -------------------- fs/umsdos/inode.c | 483 --------------- fs/umsdos/ioctl.c | 446 -------------- fs/umsdos/mangle.c | 522 ---------------- fs/umsdos/namei.c | 1124 ---------------------------------- fs/umsdos/rdir.c | 248 -------- fs/umsdos/specs | 289 --------- include/linux/umsdos_fs.h | 182 ------ include/linux/umsdos_fs.p | 100 --- include/linux/umsdos_fs_i.h | 58 -- 18 files changed, 2 insertions(+), 5203 deletions(-) delete mode 100644 Documentation/filesystems/umsdos.txt delete mode 100644 fs/umsdos/Makefile delete mode 100644 fs/umsdos/README-WIP.txt delete mode 100644 fs/umsdos/dir.c delete mode 100644 fs/umsdos/emd.c delete mode 100644 fs/umsdos/inode.c delete mode 100644 fs/umsdos/ioctl.c delete mode 100644 fs/umsdos/mangle.c delete mode 100644 fs/umsdos/namei.c delete mode 100644 fs/umsdos/rdir.c delete mode 100644 fs/umsdos/specs delete mode 100644 include/linux/umsdos_fs.h delete mode 100644 include/linux/umsdos_fs.p delete mode 100644 include/linux/umsdos_fs_i.h (limited to 'include') diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 6cf8082f605b..bcfbab899b37 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -42,8 +42,6 @@ udf.txt - info and mount options for the UDF filesystem. ufs.txt - info on the ufs filesystem. -umsdos.txt - - info on the umsdos extensions to the msdos filesystem. vfat.txt - info on using the VFAT filesystem used in Windows NT and Windows 95 vfs.txt diff --git a/Documentation/filesystems/umsdos.txt b/Documentation/filesystems/umsdos.txt deleted file mode 100644 index c253708f3466..000000000000 --- a/Documentation/filesystems/umsdos.txt +++ /dev/null @@ -1,100 +0,0 @@ -Firstly, let me say that UMSDOS is going through some major code changes, -and has some KNOWN BUGS (and quite a few unknown :-). Please read -fs/umsdos/README-WIP.txt for more information on current status. Thanks. - ----------------------------------------------------------------------------- -Very short explanation for the impatient! - -Umsdos is a file system driver that run on top the MSDOS fs driver. -It is written by Jacques Gelinas (jacques@solucorp.qc.ca) -and is currently maintained by Matija Nalis (mnalis@jagor.srce.hr) - -Umsdos is not a file system per se, but a twist to make a boring -one into a useful one. - -It gives you: - - long file names - Permissions and owners - Links - Special files (devices, pipes...) - All that is needed to be a linux root fs. - -There is plenty of documentation on it in the source. A formatted document -made from those comments is available from -sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos. - -You mount a DOS partition like this: - -mount -t umsdos /dev/hda3 /mnt - ^ ----------| - -All options are passed to the msdos drivers. Option like uid,gid etc are -given to msdos. - -The default behavior of Umsdos is to do the same thing as the msdos driver -mostly passing commands to it without much processing. Again, this is -the default. After doing the mount on a DOS partition, nothing special -happens. This is why all mount options are passed to the msdos fs driver. - -Umsdos uses a special DOS file --linux-.--- to store the information -which can't be handled by the normal MS-DOS filesystem. This is the trick. - ---linux-.--- is optional. There is one per directory. - -**** If --linux-.--- is missing, then Umsdos process the directory the - same way the msdos driver does. Short file names, no goodies, default - owner and permissions. So each directory may have or not this - --linux-.--- - -Now, how to get those --linux-.---. - -\begin joke_section - - Well send me a directory content - and I will send you one customised for you. - $5 per directory. Add any applicable taxes. -\end joke_section - -A utility umssync creates those. The kernel maintains them. It is available -from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz. -A compiled version is available in umsdos_progs-0.7.bin.tar.gz. - -So in our example, after mounting mnt, we do - - umssync . - -This will promote this directory (a recursive option is available) to full -umsdos capabilities (long name, etc.). However, an "ls -l" before and after -won't show much difference. The files which were there are still there, but -now you can do all this: - - chmod 644 * - chown you.your_group * - ls >THIS_IS.A.VERY.LONG.NAME - ln -s toto tata - ls -l - -Once a directory is promoted, all subdirectories created will inherit that -promotion. - -What happens if you boot DOS and create files in those promoted directories ? -Umsdos won't notice new files, but will signal removed files (it won't crash). -Using umssync in /etc/rc will make sure the DOS directory is in sync with -the --linux-.---. - -It is a good idea to put the following command in your RC file just -after the "mount -a": - - mount -a - /sbin/umssync -i+ -c+ -r99 /umsdos_mount_point - - (You put one for each umsdos mount point in the fstab) - -This will ensure nice operation. A umsdos.fsck is in the making, -so you will be allowed to manage umsdos partitions in the same way -other filesystems are, using the generic fsck front end. - -Hope this helps! - diff --git a/MAINTAINERS b/MAINTAINERS index df0d9e0b30e4..502b6bf95c5e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2244,13 +2244,6 @@ L: linux_udf@hpesjro.fc.hp.com W: http://linux-udf.sourceforge.net S: Maintained -UMSDOS FILESYSTEM -P: Matija Nalis -M: Matija Nalis -L: linux-kernel@vger.kernel.org -W: http://linux.voyager.hr/umsdos/ -S: Maintained - UNIFORM CDROM DRIVER P: Jens Axboe M: axboe@suse.de diff --git a/fs/Kconfig b/fs/Kconfig index e2661f504c5d..17e4eb1b97a8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -578,9 +578,8 @@ config FAT_FS tristate select NLS help - If you want to use one of the FAT-based file systems (the MS-DOS, - VFAT (Windows 95) and UMSDOS (used to run Linux on top of an - ordinary DOS partition) file systems), then you must say Y or M here + If you want to use one of the FAT-based file systems (the MS-DOS and + VFAT (Windows 95) file systems), then you must say Y or M here to include FAT support. You will then be able to mount partitions or diskettes with FAT-based file systems and transparently access the files on them, i.e. MSDOS files will look and behave just like all @@ -612,9 +611,6 @@ config FAT_FS fat. Note that if you compile the FAT support as a module, you cannot compile any of the FAT-based file systems into the kernel -- they will have to be modules as well. - The file system of your root partition (the one containing the - directory /) cannot be a module, so don't say M here if you intend - to use UMSDOS as your root file system. config MSDOS_FS tristate "MSDOS fs support" @@ -631,10 +627,6 @@ config MSDOS_FS transparent, i.e. the MSDOS files look and behave just like all other Unix files. - If you want to use UMSDOS, the Unix-like file system on top of a - DOS file system, which allows you to run Linux from within a DOS - partition without repartitioning, you'll have to say Y or M here. - If you have Windows 95 or Windows NT installed on your MSDOS partitions, you should use the VFAT file system (say Y to "VFAT fs support" below), or you will not be able to see the long filenames @@ -654,11 +646,6 @@ config VFAT_FS used by Windows 95, Windows 98, Windows NT 4.0, and the Unix programs from the mtools package. - You cannot use the VFAT file system for your Linux root partition - (the one containing the directory /); use UMSDOS instead if you - want to run Linux from within a DOS partition (i.e. say Y to - "Unix like fs on top of std MSDOS fs", below). - The VFAT support enlarges your kernel by about 10 KB and it only works if you said Y to the "DOS FAT fs support" above. Please read the file for details. If @@ -689,35 +676,6 @@ config FAT_DEFAULT_IOCHARSET If unsure, you shouldn't set "utf8" here. See for more information. -config UMSDOS_FS -#dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS -# UMSDOS is temprory broken - bool - help - Say Y here if you want to run Linux from within an existing DOS - partition of your hard drive. The advantage of this is that you can - get away without repartitioning your hard drive (which often implies - backing everything up and restoring afterwards) and hence you're - able to quickly try out Linux or show it to your friends; the - disadvantage is that Linux becomes susceptible to DOS viruses and - that UMSDOS is somewhat slower than ext2fs. Another use of UMSDOS - is to write files with long unix filenames to MSDOS floppies; it - also allows Unix-style soft-links and owner/permissions of files on - MSDOS floppies. You will need a program called umssync in order to - make use of UMSDOS; read - . - - To get utilities for initializing/checking UMSDOS file system, or - latest patches and/or information, visit the UMSDOS home page at - . - - This option enlarges your kernel by about 28 KB and it only works if - you said Y to both "DOS FAT fs support" and "MSDOS fs support" - above. To compile this as a module, choose M here: the module will be - called umsdos. Note that the file system of your root partition - (the one containing the directory /) cannot be a module, so saying M - could be dangerous. If unsure, say N. - config NTFS_FS tristate "NTFS file system support" select NLS diff --git a/fs/Makefile b/fs/Makefile index 82dbf96892fa..443f2bc56ccf 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ obj-$(CONFIG_MINIX_FS) += minix/ obj-$(CONFIG_FAT_FS) += fat/ -obj-$(CONFIG_UMSDOS_FS) += umsdos/ obj-$(CONFIG_MSDOS_FS) += msdos/ obj-$(CONFIG_VFAT_FS) += vfat/ obj-$(CONFIG_BFS_FS) += bfs/ diff --git a/fs/umsdos/Makefile b/fs/umsdos/Makefile deleted file mode 100644 index 7de26124539a..000000000000 --- a/fs/umsdos/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the umsdos Unix-like filesystem routines. -# - -obj-$(CONFIG_UMSDOS) += umsdos.o - -umsdos-objs := dir.o inode.o ioctl.o mangle.o namei.o rdir.o emd.o - -p: - proto *.c >/usr/include/linux/umsdos_fs.p - -doc: - nadoc -i -p umsdos.doc - /tmp/umsdos.mpg diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt deleted file mode 100644 index 14643c738f6e..000000000000 --- a/fs/umsdos/README-WIP.txt +++ /dev/null @@ -1,114 +0,0 @@ -Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing -(started by Peter T. Waltenberg ) -(Final conversion to dentries Bill Hawes ) - -There is no warning any more. -Both read-only and read-write stuff is fixed, both in -msdos-compatibile mode, and in umsdos EMD mode, and it seems stable. - -Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that -will compile and work on 2.2.x+ kernels and glibc based systems, as well as -kernel patches and other umsdos related information may be found at -http://linux.voyager.hr/umsdos/ - -Information below is getting outdated slowly -- I'll fix it one day when I -get enough time - there are more important things to fix right now. - -Legend: those lines marked with '+' on the beggining of line indicates it -passed all of my tests, and performed perfect in all of them. - -Current status (010125) - UMSDOS 0.86j: - -(1) pure MSDOS (no --linux-.--- EMD file): - -READ: -+ readdir - works -+ lookup - works -+ read file - works - -WRITE: -+ creat file - works -+ unlink file - works -+ write file - works -+ rename file (same dir) - works -+ rename file (dif. dir) - works -+ rename dir (same dir) - works -+ rename dir (dif. dir) - works -+ mkdir - works -+ rmdir - works - - -(2) umsdos (with --linux-.--- EMD file): - -READ: -+ readdir - works -+ lookup - works -+ permissions/owners stuff - works -+ long file names - works -+ read file - works -+ switching MSDOS/UMSDOS - works -+ switching UMSDOS/MSDOS - works -- pseudo root things - works mostly. See notes below. -+ resolve symlink - works -+ dereference symlink - works -+ dangling symlink - works -+ hard links - works -+ special files (block/char devices, FIFOs, sockets...) - works -+ various umsdos ioctls - works - - -WRITE: -+ create symlink - works -+ create hardlink - works -+ create file - works -+ create special file - works -+ write to file - works -+ rename file (same dir) - works -+ rename file (dif. dir) - works -+ rename hardlink (same dir) - works -- rename hardlink (dif. dir) - works, but see notes below. -+ rename symlink (same dir) - works -+ rename symlink (dif. dir) - works -+ rename dir (same dir) - works -+ rename dir (dif. dir) - works -+ unlink file - works -+ notify_change (chown,perms) - works -+ notify_change for hardlinks - works -+ unlink hardlink - works -+ mkdir - works -+ rmdir - works -+ umssyncing (many ioctls) - works - - -- CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank - Gockel to use it even under umsdosfs, but I - have no way of testing it -- please let me know if there are problems specific - to umsdos (for instance, it works under msdosfs, but not under umsdosfs). - - -Some current notes: - -Note: creating and using pseudo-hardlinks is always non-perfect, especially -in filesystems that might be externally modified like umsdos. There is -example is specs file about it. Specifically, moving directory which -contains hardlinks will break them. - -Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in -pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice -versa. Thanks to Sorin Iordachescu for providing fix. -See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade -procedure if you used broken versions... - ------------------------------------------------------------------------------- - -Some general notes: - -Good idea when running development kernels is to have SysRq support compiled -in kernel, and use Sync/Emergency-remount-RO if you bump into problems (like -not being able to umount(2) umsdosfs, and because of it root partition also, -or panics which force you to reboot etc.) - -I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do -check for messages having "UMSDOS" in the subject, and read them. I might -miss some in all that volume, though. I should reply to any direct e-mail -in few days. If I don't, probably I never got your message. diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c deleted file mode 100644 index 775f02021128..000000000000 --- a/fs/umsdos/dir.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - * linux/fs/umsdos/dir.c - * - * Written 1993 by Jacques Gelinas - * Inspired from linux/fs/msdos/... : Werner Almesberger - * - * Extended MS-DOS directory handling functions - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define UMSDOS_SPECIAL_DIRFPOS 3 -extern struct dentry *saved_root; -extern struct inode *pseudo_root; - -/* #define UMSDOS_DEBUG_VERBOSE 1 */ - -/* - * Dentry operations routines - */ - -/* nothing for now ... */ -static int umsdos_dentry_validate(struct dentry *dentry, struct nameidata *nd) -{ - return 1; -} - -/* for now, drop everything to force lookups ... */ -/* ITYM s/everything/& positive/... */ -static int umsdos_dentry_dput(struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - if (inode) { - return 1; - } - return 0; -} - -struct dentry_operations umsdos_dentry_operations = -{ - .d_revalidate = umsdos_dentry_validate, - .d_delete = umsdos_dentry_dput, -}; - -struct UMSDOS_DIR_ONCE { - void *dirbuf; - filldir_t filldir; - int count; - int stop; -}; - -/* - * Record a single entry the first call. - * Return -EINVAL the next one. - * NOTE: filldir DOES NOT use a dentry - */ - -static int umsdos_dir_once ( void *buf, - const char *name, - int len, - loff_t offset, - ino_t ino, - unsigned type) -{ - int ret = -EINVAL; - struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf; - - if (d->count == 0) { - PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", - len, name, offset)); - ret = d->filldir (d->dirbuf, name, len, offset, ino, DT_UNKNOWN); - d->stop = ret < 0; - d->count = 1; - } - return ret; -} - - -/* - * Read count directory entries from directory filp - * Return a negative value from linux/errno.h. - * Return > 0 if success (the number of bytes written by filldir). - * - * This function is used by the normal readdir VFS entry point, - * and in order to get the directory entry from a file's dentry. - * See umsdos_dentry_to_entry() below. - */ - -static int umsdos_readdir_x (struct inode *dir, struct file *filp, - void *dirbuf, struct umsdos_dirent *u_entry, - filldir_t filldir) -{ - struct dentry *demd; - off_t start_fpos; - int ret = 0; - loff_t pos; - - umsdos_startlookup (dir); - - if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root) { - - /* - * We don't need to simulate this pseudo directory - * when umsdos_readdir_x is called for internal operation - * of umsdos. This is why dirent_in_fs is tested - */ - /* #Specification: pseudo root / directory /DOS - * When umsdos operates in pseudo root mode (C:\linux is the - * linux root), it simulate a directory /DOS which points to - * the real root of the file system. - */ - - Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n")); - if (filldir (dirbuf, "DOS", 3, - UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO, DT_DIR) == 0) { - filp->f_pos++; - } - goto out_end; - } - - if (filp->f_pos < 2 || - (dir->i_ino != UMSDOS_ROOT_INO && filp->f_pos == 32)) { - - int last_f_pos = filp->f_pos; - struct UMSDOS_DIR_ONCE bufk; - - Printk (("umsdos_readdir_x: . or .. /mn/?\n")); - - bufk.dirbuf = dirbuf; - bufk.filldir = filldir; - bufk.count = 0; - - ret = fat_readdir (filp, &bufk, umsdos_dir_once); - if (last_f_pos > 0 && filp->f_pos > last_f_pos) - filp->f_pos = UMSDOS_SPECIAL_DIRFPOS; - if (u_entry != NULL) - u_entry->flags = 0; - goto out_end; - } - - Printk (("umsdos_readdir_x: normal file /mn/?\n")); - - /* get the EMD dentry */ - demd = umsdos_get_emd_dentry(filp->f_dentry); - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out_end; - ret = -EIO; - if (!demd->d_inode) { - printk(KERN_WARNING - "umsdos_readir_x: EMD file %s/%s not found\n", - demd->d_parent->d_name.name, demd->d_name.name); - goto out_dput; - } - - pos = filp->f_pos; - start_fpos = filp->f_pos; - - if (pos <= UMSDOS_SPECIAL_DIRFPOS + 1) - pos = 0; - ret = 0; - while (pos < demd->d_inode->i_size) { - off_t cur_f_pos = pos; - struct dentry *dret; - struct inode *inode; - struct umsdos_dirent entry; - struct umsdos_info info; - - ret = -EIO; - if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0) - break; - if (entry.name_len == 0) - continue; -#ifdef UMSDOS_DEBUG_VERBOSE -if (entry.flags & UMSDOS_HLINK) -printk("umsdos_readdir_x: %s/%s is hardlink\n", -filp->f_dentry->d_name.name, entry.name); -#endif - - umsdos_parse (entry.name, entry.name_len, &info); - info.f_pos = cur_f_pos; - umsdos_manglename (&info); - /* - * Do a real lookup on the short name. - */ - dret = umsdos_covered(filp->f_dentry, info.fake.fname, - info.fake.len); - ret = PTR_ERR(dret); - if (IS_ERR(dret)) - break; - /* - * If the file wasn't found, remove it from the EMD. - */ - inode = dret->d_inode; - if (!inode) - goto remove_name; -#ifdef UMSDOS_DEBUG_VERBOSE -if (UMSDOS_I(inode)->i_is_hlink) -printk("umsdos_readdir_x: %s/%s already resolved, ino=%ld\n", -dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino); -#endif - -Printk (("Found %s/%s, ino=%ld, flags=%x\n", -dret->d_parent->d_name.name, info.fake.fname, dret->d_inode->i_ino, -entry.flags)); - /* check whether to resolve a hard-link */ - if ((entry.flags & UMSDOS_HLINK) && - !UMSDOS_I(inode)->i_is_hlink) { - dret = umsdos_solve_hlink (dret); - ret = PTR_ERR(dret); - if (IS_ERR(dret)) - break; - inode = dret->d_inode; - if (!inode) { -printk("umsdos_readdir_x: %s/%s negative after link\n", -dret->d_parent->d_name.name, dret->d_name.name); - goto clean_up; - } - } - - /* #Specification: pseudo root / reading real root - * The pseudo root (/linux) is logically - * erased from the real root. This means that - * ls /DOS, won't show "linux". This avoids - * infinite recursion (/DOS/linux/DOS/linux/...) while - * walking the file system. - */ - if (inode != pseudo_root && !(entry.flags & UMSDOS_HIDDEN)) { - if (filldir (dirbuf, entry.name, entry.name_len, - cur_f_pos, inode->i_ino, DT_UNKNOWN) < 0) { - pos = cur_f_pos; - } -Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n", -dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino)); - if (u_entry != NULL) - *u_entry = entry; - dput(dret); - ret = 0; - break; - } - clean_up: - dput(dret); - continue; - - remove_name: - /* #Specification: umsdos / readdir / not in MSDOS - * During a readdir operation, if the file is not - * in the MS-DOS directory any more, the entry is - * removed from the EMD file silently. - */ -#ifdef UMSDOS_PARANOIA -printk("umsdos_readdir_x: %s/%s out of sync, erasing\n", -filp->f_dentry->d_name.name, info.entry.name); -#endif - ret = umsdos_delentry(filp->f_dentry, &info, - S_ISDIR(info.entry.mode)); - if (ret) - printk(KERN_WARNING - "umsdos_readdir_x: delentry %s, err=%d\n", - info.entry.name, ret); - goto clean_up; - } - /* - * If the fillbuf has failed, f_pos is back to 0. - * To avoid getting back into the . and .. state - * (see comments at the beginning), we put back - * the special offset. - */ - filp->f_pos = pos; - if (filp->f_pos == 0) - filp->f_pos = start_fpos; -out_dput: - dput(demd); - -out_end: - umsdos_endlookup (dir); - - Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n", - dir, filp->f_pos, ret)); - return ret; -} - - -/* - * Read count directory entries from directory filp. - * Return a negative value from linux/errno.h. - * Return 0 or positive if successful. - */ - -static int UMSDOS_readdir (struct file *filp, void *dirbuf, filldir_t filldir) -{ - struct inode *dir = filp->f_dentry->d_inode; - int ret = 0, count = 0; - struct UMSDOS_DIR_ONCE bufk; - - lock_kernel(); - - bufk.dirbuf = dirbuf; - bufk.filldir = filldir; - bufk.stop = 0; - - Printk (("UMSDOS_readdir in\n")); - while (ret == 0 && bufk.stop == 0) { - struct umsdos_dirent entry; - - bufk.count = 0; - ret = umsdos_readdir_x (dir, filp, &bufk, &entry, - umsdos_dir_once); - if (bufk.count == 0) - break; - count += bufk.count; - } - unlock_kernel(); - Printk (("UMSDOS_readdir out %d count %d pos %Ld\n", - ret, count, filp->f_pos)); - return count ? : ret; -} - - -/* - * Complete the inode content with info from the EMD file. - * - * This function modifies the state of a dir inode. It decides - * whether the dir is a UMSDOS or DOS directory. This is done - * deeper in umsdos_patch_inode() called at the end of this function. - * - * Because it is does disk access, umsdos_patch_inode() may block. - * At the same time, another process may get here to initialise - * the same directory inode. There are three cases. - * - * 1) The inode is already initialised. We do nothing. - * 2) The inode is not initialised. We lock access and do it. - * 3) Like 2 but another process has locked the inode, so we try - * to lock it and check right afterward check whether - * initialisation is still needed. - * - * - * Thanks to the "mem" option of the kernel command line, it was - * possible to consistently reproduce this problem by limiting - * my memory to 4 MB and running X. - * - * Do this only if the inode is freshly read, because we will lose - * the current (updated) content. - * - * A lookup of a mount point directory yield the inode into - * the other fs, so we don't care about initialising it. iget() - * does this automatically. - */ - -void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info) -{ - struct inode *inode = dentry->d_inode; - struct umsdos_dirent *entry = &info->entry; - - /* - * This part of the initialization depends only on i_patched. - */ - if (UMSDOS_I(inode)->i_patched) - goto out; - UMSDOS_I(inode)->i_patched = 1; - if (S_ISREG (entry->mode)) - entry->mtime = inode->i_mtime; - inode->i_mode = entry->mode; - inode->i_rdev = to_kdev_t (entry->rdev); - inode->i_atime = entry->atime; - inode->i_ctime = entry->ctime; - inode->i_mtime = entry->mtime; - inode->i_uid = entry->uid; - inode->i_gid = entry->gid; - - /* #Specification: umsdos / i_nlink - * The nlink field of an inode is maintained by the MSDOS file system - * for directory and by UMSDOS for other files. The logic is that - * MSDOS is already figuring out what to do for directories and - * does nothing for other files. For MSDOS, there are no hard links - * so all file carry nlink==1. UMSDOS use some info in the - * EMD file to plug the correct value. - */ - if (!S_ISDIR (entry->mode)) { - if (entry->nlink > 0) { - inode->i_nlink = entry->nlink; - } else { - printk (KERN_ERR - "UMSDOS: lookup_patch entry->nlink < 1 ???\n"); - } - } - /* - * The mode may have changed, so patch the inode again. - */ - umsdos_patch_dentry_inode(dentry, info->f_pos); - umsdos_set_dirinfo_new(dentry, info->f_pos); - -out: - return; -} - - -/* - * Return != 0 if an entry is the pseudo DOS entry in the pseudo root. - */ - -int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry) -{ - /* #Specification: pseudo root / DOS hard coded - * The pseudo sub-directory DOS in the pseudo root is hard coded. - * The name is DOS. This is done this way to help standardised - * the umsdos layout. The idea is that from now on /DOS is - * a reserved path and nobody will think of using such a path - * for a package. - */ - return dir == pseudo_root - && dentry->d_name.len == 3 - && dentry->d_name.name[0] == 'D' - && dentry->d_name.name[1] == 'O' - && dentry->d_name.name[2] == 'S'; -} - - -/* - * Check whether a file exists in the current directory. - * Return 0 if OK, negative error code if not (ex: -ENOENT). - * - * fills dentry->d_inode with found inode, and increments its count. - * if not found, return -ENOENT. - */ -/* #Specification: umsdos / lookup - * A lookup for a file is done in two steps. First, we - * locate the file in the EMD file. If not present, we - * return an error code (-ENOENT). If it is there, we - * repeat the operation on the msdos file system. If - * this fails, it means that the file system is not in - * sync with the EMD file. We silently remove this - * entry from the EMD file, and return ENOENT. - */ - -struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo) -{ - struct dentry *dret = NULL; - struct inode *inode; - int ret = -ENOENT; - struct umsdos_info info; - -#ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_lookup_x: looking for %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name); -#endif - - umsdos_startlookup (dir); - if (umsdos_is_pseudodos (dir, dentry)) { - /* #Specification: pseudo root / lookup(DOS) - * A lookup of DOS in the pseudo root will always succeed - * and return the inode of the real root. - */ - Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n")); - inode = saved_root->d_inode; - goto out_add; - } - - ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); - if (ret) { -printk("umsdos_lookup_x: %s/%s parse failed, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret); - goto out; - } - - ret = umsdos_findentry (dentry->d_parent, &info, 0); - if (ret) { -if (ret != -ENOENT) -printk("umsdos_lookup_x: %s/%s findentry failed, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret); - goto out; - } -Printk (("lookup %.*s pos %lu ret %d len %d ", -info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len)); - - /* do a real lookup to get the short name ... */ - dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); - ret = PTR_ERR(dret); - if (IS_ERR(dret)) { -printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret); - goto out; - } - inode = dret->d_inode; - if (!inode) - goto out_remove; - umsdos_lookup_patch_new(dret, &info); -#ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_lookup_x: found %s/%s, ino=%ld\n", -dret->d_parent->d_name.name, dret->d_name.name, dret->d_inode->i_ino); -#endif - - /* Check for a hard link */ - if ((info.entry.flags & UMSDOS_HLINK) && - !UMSDOS_I(inode)->i_is_hlink) { - dret = umsdos_solve_hlink (dret); - ret = PTR_ERR(dret); - if (IS_ERR(dret)) - goto out; - ret = -ENOENT; - inode = dret->d_inode; - if (!inode) { -printk("umsdos_lookup_x: %s/%s negative after link\n", -dret->d_parent->d_name.name, dret->d_name.name); - goto out_dput; - } - } - - if (inode == pseudo_root && !nopseudo) { - /* #Specification: pseudo root / dir lookup - * For the same reason as readdir, a lookup in /DOS for - * the pseudo root directory (linux) will fail. - */ - /* - * This has to be allowed for resolving hard links - * which are recorded independently of the pseudo-root - * mode. - */ -printk("umsdos_lookup_x: skipping DOS/linux\n"); - ret = -ENOENT; - goto out_dput; - } - - /* - * We've found it OK. Now hash the dentry with the inode. - */ -out_add: - atomic_inc(&inode->i_count); - d_add (dentry, inode); - dentry->d_op = &umsdos_dentry_operations; - ret = 0; - -out_dput: - if (dret && dret != dentry) - d_drop(dret); - dput(dret); -out: - umsdos_endlookup (dir); - return ERR_PTR(ret); - -out_remove: - printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n", - dentry->d_parent->d_name.name, dentry->d_name.name); - umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode)); - ret = -ENOENT; - goto out_dput; -} - - -/* - * Check whether a file exists in the current directory. - * Return 0 if OK, negative error code if not (ex: -ENOENT). - * - * Called by VFS; should fill dentry->d_inode via d_add. - */ - -struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd) -{ - struct dentry *ret; - - ret = umsdos_lookup_x (dir, dentry, 0); - - /* Create negative dentry if not found. */ - if (ret == ERR_PTR(-ENOENT)) { - Printk ((KERN_DEBUG - "UMSDOS_lookup: converting -ENOENT to negative\n")); - d_add (dentry, NULL); - dentry->d_op = &umsdos_dentry_operations; - ret = NULL; - } - return ret; -} - -struct dentry *umsdos_covered(struct dentry *parent, char *name, int len) -{ - struct dentry *result, *dentry; - struct qstr qstr; - - qstr.name = name; - qstr.len = len; - qstr.hash = full_name_hash(name, len); - result = ERR_PTR(-ENOMEM); - dentry = d_alloc(parent, &qstr); - if (dentry) { - /* XXXXXXXXXXXXXXXXXXX Race alert! */ - result = UMSDOS_rlookup(parent->d_inode, dentry); - d_drop(dentry); - if (result) - goto out_fail; - return dentry; - } -out: - return result; - -out_fail: - dput(dentry); - goto out; -} - -/* - * Lookup or create a dentry from within the filesystem. - * - * We need to use this instead of lookup_dentry, as the - * directory semaphore lock is already held. - */ -struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len, - int real) -{ - struct dentry *result, *dentry; - struct qstr qstr; - - qstr.name = name; - qstr.len = len; - qstr.hash = full_name_hash(name, len); - result = d_lookup(parent, &qstr); - if (!result) { - result = ERR_PTR(-ENOMEM); - dentry = d_alloc(parent, &qstr); - if (dentry) { - result = real ? - UMSDOS_rlookup(parent->d_inode, dentry) : - UMSDOS_lookup(parent->d_inode, dentry); - if (result) - goto out_fail; - return dentry; - } - } -out: - return result; - -out_fail: - dput(dentry); - goto out; -} - -/* - * Return a path relative to our root. - */ -char * umsdos_d_path(struct dentry *dentry, char * buffer, int len) -{ - struct dentry * old_root; - char * path; - - read_lock(¤t->fs->lock); - old_root = dget(current->fs->root); - read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); - path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */ - spin_unlock(&dcache_lock); - - if (*path == '/') - path++; /* skip leading '/' */ - - if (current->fs->root->d_inode == pseudo_root) - { - *(path-1) = '/'; - path -= (UMSDOS_PSDROOT_LEN+1); - memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN); - } - dput(old_root); - - return path; -} - -/* - * Return the dentry which points to a pseudo-hardlink. - * - * it should try to find file it points to - * if file is found, return new dentry/inode - * The resolved inode will have i_is_hlink set. - * - * Note: the original dentry is always dput(), even if an error occurs. - */ - -struct dentry *umsdos_solve_hlink (struct dentry *hlink) -{ - /* root is our root for resolving pseudo-hardlink */ - struct dentry *base = hlink->d_sb->s_root; - struct dentry *dentry_dst; - char *path, *pt; - int len; - struct address_space *mapping = hlink->d_inode->i_mapping; - struct page *page; - - page=read_cache_page(mapping,0,(filler_t *)mapping->a_ops->readpage,NULL); - dentry_dst=(struct dentry *)page; - if (IS_ERR(page)) - goto out; - wait_on_page_locked(page); - if (!PageUptodate(page)) - goto async_fail; - - dentry_dst = ERR_PTR(-ENOMEM); - path = (char *) kmalloc (PATH_MAX, GFP_KERNEL); - if (path == NULL) - goto out_release; - memcpy(path, kmap(page), hlink->d_inode->i_size); - kunmap(page); - page_cache_release(page); - - len = hlink->d_inode->i_size; - - /* start at root dentry */ - dentry_dst = dget(base); - path[len] = '\0'; - - pt = path; - if (*path == '/') - pt++; /* skip leading '/' */ - - if (base->d_inode == pseudo_root) - pt += (UMSDOS_PSDROOT_LEN + 1); - - while (1) { - struct dentry *dir = dentry_dst, *demd; - char *start = pt; - int real; - - while (*pt != '\0' && *pt != '/') pt++; - len = (int) (pt - start); - if (*pt == '/') *pt++ = '\0'; - - real = 1; - demd = umsdos_get_emd_dentry(dir); - if (!IS_ERR(demd)) { - if (demd->d_inode) - real = 0; - dput(demd); - } - -#ifdef UMSDOS_DEBUG_VERBOSE -printk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n", -dir->d_parent->d_name.name, dir->d_name.name, start, real); -#endif - dentry_dst = umsdos_lookup_dentry(dir, start, len, real); -/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ - if (real) - d_drop(dir); - dput (dir); - if (IS_ERR(dentry_dst)) - break; - /* not found? stop search ... */ - if (!dentry_dst->d_inode) { - break; - } - if (*pt == '\0') /* we're finished! */ - break; - } /* end while */ - - if (!IS_ERR(dentry_dst)) { - struct inode *inode = dentry_dst->d_inode; - if (inode) { - UMSDOS_I(inode)->i_is_hlink = 1; -#ifdef UMSDOS_DEBUG_VERBOSE -printk ("umsdos_solve_hlink: resolved link %s/%s, ino=%ld\n", -dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name, inode->i_ino); -#endif - } else { -#ifdef UMSDOS_DEBUG_VERBOSE -printk ("umsdos_solve_hlink: resolved link %s/%s negative!\n", -dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name); -#endif - } - } else - printk(KERN_WARNING - "umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst)); - kfree (path); - -out: - dput(hlink); /* original hlink no longer needed */ - return dentry_dst; - -async_fail: - dentry_dst = ERR_PTR(-EIO); -out_release: - page_cache_release(page); - goto out; -} - - -struct file_operations umsdos_dir_operations = -{ - .read = generic_read_dir, - .readdir = UMSDOS_readdir, - .ioctl = UMSDOS_ioctl_dir, -}; - -struct inode_operations umsdos_dir_inode_operations = -{ - .create = UMSDOS_create, - .lookup = UMSDOS_lookup, - .link = UMSDOS_link, - .unlink = UMSDOS_unlink, - .symlink = UMSDOS_symlink, - .mkdir = UMSDOS_mkdir, - .rmdir = UMSDOS_rmdir, - .mknod = UMSDOS_mknod, - .rename = UMSDOS_rename, - .setattr = UMSDOS_notify_change, -}; diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c deleted file mode 100644 index 16a15d75dcd7..000000000000 --- a/fs/umsdos/emd.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * linux/fs/umsdos/emd.c - * - * Written 1993 by Jacques Gelinas - * - * Extended MS-DOS directory handling functions - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q) -{ - p->name_len = q->name_len; - p->flags = q->flags; - p->nlink = cpu_to_le16(q->nlink); - p->uid = cpu_to_le16(q->uid); - p->gid = cpu_to_le16(q->gid); - p->atime = cpu_to_le32(q->atime); - p->mtime = cpu_to_le32(q->mtime); - p->ctime = cpu_to_le32(q->ctime); - p->rdev = cpu_to_le16(q->rdev); - p->mode = cpu_to_le16(q->mode); -} - -static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q) -{ - p->name_len = q->name_len; - p->name[p->name_len]='\0'; - p->flags = q->flags; - p->nlink = le16_to_cpu (q->nlink); - /* FIXME -- 32bit UID/GID issues */ - p->uid = le16_to_cpu (q->uid); - p->gid = le16_to_cpu (q->gid); - p->atime = le32_to_cpu (q->atime); - p->mtime = le32_to_cpu (q->mtime); - p->ctime = le32_to_cpu (q->ctime); - p->rdev = le16_to_cpu (q->rdev); - p->mode = le16_to_cpu (q->mode); -} - -/* - * Lookup the EMD dentry for a directory. - * - * Note: the caller must hold a lock on the parent directory. - */ -struct dentry *umsdos_get_emd_dentry(struct dentry *parent) -{ - struct dentry *demd; - - demd = umsdos_lookup_dentry(parent, UMSDOS_EMD_FILE, - UMSDOS_EMD_NAMELEN, 1); - return demd; -} - -/* - * Check whether a directory has an EMD file. - * - * Note: the caller must hold a lock on the parent directory. - */ -int umsdos_have_emd(struct dentry *dir) -{ - struct dentry *demd = umsdos_get_emd_dentry (dir); - int found = 0; - - if (!IS_ERR(demd)) { - if (demd->d_inode) - found = 1; - dput(demd); - } - return found; -} - -/* - * Create the EMD file for a directory if it doesn't - * already exist. Returns 0 or an error code. - * - * Note: the caller must hold a lock on the parent directory. - */ -int umsdos_make_emd(struct dentry *parent) -{ - struct dentry *demd = umsdos_get_emd_dentry(parent); - int err = PTR_ERR(demd); - - if (IS_ERR(demd)) { - printk("umsdos_make_emd: can't get dentry in %s, err=%d\n", - parent->d_name.name, err); - goto out; - } - - /* already created? */ - err = 0; - if (demd->d_inode) - goto out_set; - -Printk(("umsdos_make_emd: creating EMD %s/%s\n", -parent->d_name.name, demd->d_name.name)); - - err = msdos_create(parent->d_inode, demd, S_IFREG | 0777, NULL); - if (err) { - printk (KERN_WARNING - "umsdos_make_emd: create %s/%s failed, err=%d\n", - parent->d_name.name, demd->d_name.name, err); - } -out_set: - dput(demd); -out: - return err; -} - - -/* - * Read an entry from the EMD file. - * Support variable length record. - * Return -EIO if error, 0 if OK. - * - * does not change {d,i}_count - */ - -int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_dirent *entry) -{ - struct address_space *mapping = demd->d_inode->i_mapping; - struct page *page; - struct umsdos_dirent *p; - int offs = *pos & ~PAGE_CACHE_MASK; - int recsize; - int ret = 0; - - page = read_cache_page(mapping, *pos>>PAGE_CACHE_SHIFT, - (filler_t*)mapping->a_ops->readpage, NULL); - if (IS_ERR(page)) - goto sync_fail; - wait_on_page_locked(page); - if (!PageUptodate(page)) - goto async_fail; - p = (struct umsdos_dirent*)(kmap(page)+offs); - - /* if this is an invalid entry (invalid name length), ignore it */ - if( p->name_len > UMSDOS_MAXNAME ) - { - printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len); - p->name_len = 0; - ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */ - /* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */ - } - - recsize = umsdos_evalrecsize(p->name_len); - if (offs + recsize > PAGE_CACHE_SIZE) { - struct page *page2; - int part = (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare; - page2 = read_cache_page(mapping, 1+(*pos>>PAGE_CACHE_SHIFT), - (filler_t*)mapping->a_ops->readpage, NULL); - if (IS_ERR(page2)) { - kunmap(page); - page_cache_release(page); - page = page2; - goto sync_fail; - } - wait_on_page_locked(page2); - if (!PageUptodate(page2)) { - kunmap(page); - page_cache_release(page2); - goto async_fail; - } - memcpy(entry->spare,p->spare,part); - memcpy(entry->spare+part,kmap(page2), - recsize+offs-PAGE_CACHE_SIZE); - kunmap(page2); - page_cache_release(page2); - } else - memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare); - get_entry(entry, p); - kunmap(page); - page_cache_release(page); - *pos += recsize; - return ret; -async_fail: - page_cache_release(page); - page = ERR_PTR(-EIO); -sync_fail: - return PTR_ERR(page); -} - - -/* - * Write an entry in the EMD file. - * Return 0 if OK, -EIO if some error. - * - * Note: the caller must hold a lock on the parent directory. - */ -int umsdos_writeentry (struct dentry *parent, struct umsdos_info *info, - int free_entry) -{ - struct inode *dir = parent->d_inode; - struct umsdos_dirent *entry = &info->entry; - struct dentry *emd_dentry; - int ret; - struct umsdos_dirent entry0,*p; - struct address_space *mapping; - struct page *page, *page2 = NULL; - int offs; - - emd_dentry = umsdos_get_emd_dentry(parent); - ret = PTR_ERR(emd_dentry); - if (IS_ERR(emd_dentry)) - goto out; - /* make sure there's an EMD file */ - ret = -EIO; - if (!emd_dentry->d_inode) { - printk(KERN_WARNING - "umsdos_writeentry: no EMD file in %s/%s\n", - parent->d_parent->d_name.name, parent->d_name.name); - goto out_dput; - } - - if (free_entry) { - /* #Specification: EMD file / empty entries - * Unused entries in the EMD file are identified - * by the name_len field equal to 0. However to - * help future extension (or bug correction :-( ), - * empty entries are filled with 0. - */ - memset (&entry0, 0, sizeof (entry0)); - entry = &entry0; - } else if (entry->name_len > 0) { - memset (entry->name + entry->name_len, '\0', - sizeof (entry->name) - entry->name_len); - /* #Specification: EMD file / spare bytes - * 10 bytes are unused in each record of the EMD. They - * are set to 0 all the time, so it will be possible - * to do new stuff and rely on the state of those - * bytes in old EMD files. - */ - memset (entry->spare, 0, sizeof (entry->spare)); - } - - /* write the entry and update the parent timestamps */ - mapping = emd_dentry->d_inode->i_mapping; - offs = info->f_pos & ~PAGE_CACHE_MASK; - ret = -ENOMEM; - page = grab_cache_page(mapping, info->f_pos>>PAGE_CACHE_SHIFT); - if (!page) - goto out_dput; - p = (struct umsdos_dirent *) (page_address(page) + offs); - if (offs + info->recsize > PAGE_CACHE_SIZE) { - ret = mapping->a_ops->prepare_write(NULL,page,offs, - PAGE_CACHE_SIZE); - if (ret) - goto out_unlock; - page2 = grab_cache_page(mapping, - (info->f_pos>>PAGE_CACHE_SHIFT)+1); - if (!page2) - goto out_unlock2; - ret = mapping->a_ops->prepare_write(NULL,page2,0, - offs+info->recsize-PAGE_CACHE_SIZE); - if (ret) - goto out_unlock3; - put_entry (p, entry); - memcpy(p->spare,entry->spare, - (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare); - memcpy(page_address(page2), - ((char*)entry)+PAGE_CACHE_SIZE-offs, - offs+info->recsize-PAGE_CACHE_SIZE); - ret = mapping->a_ops->commit_write(NULL,page2,0, - offs+info->recsize-PAGE_CACHE_SIZE); - if (ret) - goto out_unlock3; - ret = mapping->a_ops->commit_write(NULL,page,offs, - PAGE_CACHE_SIZE); - unlock_page(page2); - page_cache_release(page2); - if (ret) - goto out_unlock; - } else { - ret = mapping->a_ops->prepare_write(NULL,page,offs, - offs + info->recsize); - if (ret) - goto out_unlock; - put_entry (p, entry); - memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare); - ret = mapping->a_ops->commit_write(NULL,page,offs, - offs + info->recsize); - if (ret) - goto out_unlock; - } - unlock_page(page); - page_cache_release(page); - - dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; - mark_inode_dirty(dir); - -out_dput: - dput(emd_dentry); -out: - Printk (("umsdos_writeentry /mn/: returning %d...\n", ret)); - return ret; -out_unlock3: - unlock_page(page2); - page_cache_release(page2); -out_unlock2: - ClearPageUptodate(page); - kunmap(page); -out_unlock: - unlock_page(page); - page_cache_release(page); - printk ("UMSDOS: problem with EMD file: can't write\n"); - goto out_dput; -} - -/* - * General search, locate a name in the EMD file or an empty slot to - * store it. if info->entry.name_len == 0, search the first empty - * slot (of the proper size). - * - * Return 0 if found, -ENOENT if not found, another error code if - * other problem. - * - * So this routine is used to either find an existing entry or to - * create a new one, while making sure it is a new one. After you - * get -ENOENT, you make sure the entry is stuffed correctly and - * call umsdos_writeentry(). - * - * To delete an entry, you find it, zero out the entry (memset) - * and call umsdos_writeentry(). - * - * All this to say that umsdos_writeentry must be called after this - * function since it relies on the f_pos field of info. - * - * Note: the caller must hold a lock on the parent directory. - */ -/* #Specification: EMD file structure - * The EMD file uses a fairly simple layout. It is made of records - * (UMSDOS_REC_SIZE == 64). When a name can't be written in a single - * record, multiple contiguous records are allocated. - */ - -static int umsdos_find (struct dentry *demd, struct umsdos_info *info) -{ - struct umsdos_dirent *entry = &info->entry; - int recsize = info->recsize; - struct inode *emd_dir; - int ret = -ENOENT; - struct { - off_t posok; /* Position available to store the entry */ - off_t one; /* One empty position -> maybe <- large enough */ - } empty; - int found = 0; - int empty_size = 0; - struct address_space *mapping; - filler_t *readpage; - struct page *page = NULL; - int index = -1; - int offs = PAGE_CACHE_SIZE,max_offs = PAGE_CACHE_SIZE; - char *p = NULL; - loff_t pos = 0; - - /* make sure there's an EMD file ... */ - ret = -ENOENT; - emd_dir = demd->d_inode; - if (!emd_dir) - goto out_dput; - mapping = emd_dir->i_mapping; - readpage = (filler_t*)mapping->a_ops->readpage; - - empty.posok = emd_dir->i_size; - while (1) { - struct umsdos_dirent *rentry; - int entry_size; - - if (offs >= max_offs) { - if (page) { - kunmap(page); - page_cache_release(page); - page = NULL; - } - if (pos >= emd_dir->i_size) { - info->f_pos = empty.posok; - break; - } - if (++index == (emd_dir->i_size>>PAGE_CACHE_SHIFT)) - max_offs = emd_dir->i_size & ~PAGE_CACHE_MASK; - offs -= PAGE_CACHE_SIZE; - page = read_cache_page(mapping,index,readpage,NULL); - if (IS_ERR(page)) - goto sync_fail; - wait_on_page_locked(page); - if (!PageUptodate(page)) - goto async_fail; - p = kmap(page); - } - - rentry = (struct umsdos_dirent *)(p+offs); - - if (rentry->name_len == 0) { - /* We are looking for an empty section at least */ - /* as large as recsize. */ - if (entry->name_len == 0) { - info->f_pos = pos; - ret = 0; - break; - } - offs += UMSDOS_REC_SIZE; - pos += UMSDOS_REC_SIZE; - if (found) - continue; - if (!empty_size) - empty.one = pos-UMSDOS_REC_SIZE; - empty_size += UMSDOS_REC_SIZE; - if (empty_size == recsize) { - /* Here is a large enough section. */ - empty.posok = empty.one; - found = 1; - } - continue; - } - - entry_size = umsdos_evalrecsize(rentry->name_len); - if (entry_size > PAGE_CACHE_SIZE) - goto async_fail; - empty_size = 0; - if (entry->name_len != rentry->name_len) - goto skip_it; - - if (entry_size + offs > PAGE_CACHE_SIZE) { - /* Sucker spans the page boundary */ - int len = (p+PAGE_CACHE_SIZE)-rentry->name; - struct page *next_page; - char *q; - next_page = read_cache_page(mapping,index+1,readpage,NULL); - if (IS_ERR(next_page)) { - page_cache_release(page); - page = next_page; - goto sync_fail; - } - wait_on_page_locked(next_page); - if (!PageUptodate(next_page)) { - page_cache_release(page); - page = next_page; - goto async_fail; - } - q = kmap(next_page); - if (memcmp(entry->name, rentry->name, len) || - memcmp(entry->name+len, q, entry->name_len-len)) { - kunmap(next_page); - page_cache_release(next_page); - goto skip_it; - } - kunmap(next_page); - page_cache_release(next_page); - } else if (memcmp (entry->name, rentry->name, entry->name_len)) - goto skip_it; - - info->f_pos = pos; - get_entry(entry, rentry); - ret = 0; - break; -skip_it: - offs+=entry_size; - pos+=entry_size; - } - if (page) { - kunmap(page); - page_cache_release(page); - } - umsdos_manglename (info); - -out_dput: - dput(demd); - return ret; - -async_fail: - page_cache_release(page); - page = ERR_PTR(-EIO); -sync_fail: - return PTR_ERR(page); -} - - -/* - * Add a new entry in the EMD file. - * Return 0 if OK or a negative error code. - * Return -EEXIST if the entry already exists. - * - * Complete the information missing in info. - * - * N.B. What if the EMD file doesn't exist? - */ - -int umsdos_newentry (struct dentry *parent, struct umsdos_info *info) -{ - int err, ret = -EEXIST; - struct dentry *demd = umsdos_get_emd_dentry(parent); - - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - err = umsdos_find (demd, info); - if (err && err == -ENOENT) { - ret = umsdos_writeentry (parent, info, 0); - Printk (("umsdos_writeentry EMD ret = %d\n", ret)); - } -out: - return ret; -} - - -/* - * Create a new hidden link. - * Return 0 if OK, an error code if not. - */ - -/* #Specification: hard link / hidden name - * When a hard link is created, the original file is renamed - * to a hidden name. The name is "..LINKNNN" where NNN is a - * number define from the entry offset in the EMD file. - */ -int umsdos_newhidden (struct dentry *parent, struct umsdos_info *info) -{ - int ret; - struct dentry *demd = umsdos_get_emd_dentry(parent); - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - - umsdos_parse ("..LINK", 6, info); - info->entry.name_len = 0; - ret = umsdos_find (demd, info); - if (ret == -ENOENT || ret == 0) { - info->entry.name_len = sprintf (info->entry.name, - "..LINK%ld", info->f_pos); - ret = 0; - } -out: - return ret; -} - - -/* - * Remove an entry from the EMD file. - * Return 0 if OK, a negative error code otherwise. - * - * Complete the information missing in info. - */ - -int umsdos_delentry (struct dentry *parent, struct umsdos_info *info, int isdir) -{ - int ret; - struct dentry *demd = umsdos_get_emd_dentry(parent); - - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - ret = umsdos_find (demd, info); - if (ret) - goto out; - if (info->entry.name_len == 0) - goto out; - - if ((isdir != 0) != (S_ISDIR (info->entry.mode) != 0)) { - if (S_ISDIR (info->entry.mode)) { - ret = -EISDIR; - } else { - ret = -ENOTDIR; - } - goto out; - } - ret = umsdos_writeentry (parent, info, 1); - -out: - return ret; -} - - -/* - * Verify that an EMD directory is empty. - * Return: - * 0 if not empty, - * 1 if empty (except for EMD file), - * 2 if empty or no EMD file. - */ - -int umsdos_isempty (struct dentry *dentry) -{ - struct dentry *demd; - int ret = 2; - loff_t pos = 0; - - demd = umsdos_get_emd_dentry(dentry); - if (IS_ERR(demd)) - goto out; - /* If the EMD file does not exist, it is certainly empty. :-) */ - if (!demd->d_inode) - goto out_dput; - - ret = 1; - while (pos < demd->d_inode->i_size) { - struct umsdos_dirent entry; - - if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0) { - ret = 0; - break; - } - if (entry.name_len != 0) { - ret = 0; - break; - } - } - -out_dput: - dput(demd); -out: - return ret; -} - -/* - * Locate an entry in a EMD directory. - * Return 0 if OK, error code if not, generally -ENOENT. - * - * expect argument: - * 0: anything - * 1: file - * 2: directory - */ - -int umsdos_findentry (struct dentry *parent, struct umsdos_info *info, - int expect) -{ - int ret; - struct dentry *demd = umsdos_get_emd_dentry(parent); - - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - ret = umsdos_find (demd, info); - if (ret) - goto out; - - switch (expect) { - case 1: - if (S_ISDIR (info->entry.mode)) - ret = -EISDIR; - break; - case 2: - if (!S_ISDIR (info->entry.mode)) - ret = -ENOTDIR; - } - -out: - Printk (("umsdos_findentry: returning %d\n", ret)); - return ret; -} diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c deleted file mode 100644 index 778feedf4642..000000000000 --- a/fs/umsdos/inode.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * linux/fs/umsdos/inode.c - * - * Written 1993 by Jacques Gelinas - * Inspired from linux/fs/msdos/... by Werner Almesberger - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct dentry_operations umsdos_dentry_operations; - -struct dentry *saved_root; /* Original root if changed */ -struct inode *pseudo_root; /* Useful to simulate the pseudo DOS */ - /* directory. See UMSDOS_readdir_x() */ - -static struct dentry *check_pseudo_root(struct super_block *); - - -void UMSDOS_put_inode (struct inode *inode) -{ - PRINTK ((KERN_DEBUG - "put inode %p (%lu) pos %lu count=%d\n" - ,inode, inode->i_ino - ,UMSDOS_I(inode)->pos - ,atomic_read(&inode->i_count))); - - if (inode == pseudo_root) { - Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count))); - } - - if (atomic_read(&inode->i_count) == 1) - UMSDOS_I(inode)->i_patched = 0; -} - - -void UMSDOS_put_super (struct super_block *sb) -{ - Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n")); - if (saved_root && pseudo_root && kdev_same(sb->s_dev, ROOT_DEV)) { - shrink_dcache_parent(saved_root); - dput(saved_root); - saved_root = NULL; - pseudo_root = NULL; - } - fat_put_super (sb); -} - - -/* - * Complete the setup of a directory dentry based on its - * EMD/non-EMD status. If it has an EMD, then plug the - * umsdos function table. If not, use the msdos one. - */ -void umsdos_setup_dir(struct dentry *dir) -{ - struct inode *inode = dir->d_inode; - struct umsdos_inode_info *ui = UMSDOS_I(inode); - - if (!S_ISDIR(inode->i_mode)) - printk(KERN_ERR "umsdos_setup_dir: %s/%s not a dir!\n", - dir->d_parent->d_name.name, dir->d_name.name); - - init_waitqueue_head (&ui->dir_info.p); - ui->dir_info.looking = 0; - ui->dir_info.creating = 0; - ui->dir_info.pid = 0; - - inode->i_op = &umsdos_rdir_inode_operations; - inode->i_fop = &umsdos_rdir_operations; - if (umsdos_have_emd(dir)) { -Printk((KERN_DEBUG "umsdos_setup_dir: %s/%s using EMD\n", -dir->d_parent->d_name.name, dir->d_name.name)); - inode->i_op = &umsdos_dir_inode_operations; - inode->i_fop = &umsdos_dir_operations; - } -} - - -/* - * Add some info into an inode so it can find its owner quickly - */ -void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos) -{ - struct inode *inode = dentry->d_inode; - struct dentry *demd; - - UMSDOS_I(inode)->pos = f_pos; - - /* now check the EMD file */ - demd = umsdos_get_emd_dentry(dentry->d_parent); - if (!IS_ERR(demd)) { - dput(demd); - } - return; -} - -static struct inode_operations umsdos_file_inode_operations = { - .truncate = fat_truncate, - .setattr = UMSDOS_notify_change, -}; - -static struct inode_operations umsdos_symlink_inode_operations = { - .readlink = page_readlink, - .follow_link = page_follow_link, - .setattr = UMSDOS_notify_change, -}; - -/* - * Connect the proper tables in the inode and add some info. - */ -/* #Specification: inode / umsdos info - * The first time an inode is seen (inode->i_count == 1), - * the inode number of the EMD file which controls this inode - * is tagged to this inode. It allows operations such as - * notify_change to be handled. - */ -void umsdos_patch_dentry_inode(struct dentry *dentry, off_t f_pos) -{ - struct inode *inode = dentry->d_inode; - -PRINTK (("umsdos_patch_dentry_inode: inode=%lu\n", inode->i_ino)); - - /* - * Classify the inode based on EMD/non-EMD status. - */ -PRINTK (("umsdos_patch_inode: call umsdos_set_dirinfo_new(%p,%lu)\n", -dentry, f_pos)); - umsdos_set_dirinfo_new(dentry, f_pos); - - inode->i_op = &umsdos_file_inode_operations; - if (S_ISREG (inode->i_mode)) { - /* address_space operations already set */ - } else if (S_ISDIR (inode->i_mode)) { - umsdos_setup_dir(dentry); - } else if (S_ISLNK (inode->i_mode)) { - /* address_space operations already set */ - inode->i_op = &umsdos_symlink_inode_operations; - } else - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); -} - - -/* - * lock the parent dir before starting ... - * also handles hardlink converting - */ -int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr) -{ - struct inode *dir, *inode; - struct umsdos_info info; - struct dentry *temp, *old_dentry = NULL; - int ret; - - lock_kernel(); - - ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, - &info); - if (ret) - goto out; - ret = umsdos_findentry (dentry->d_parent, &info, 0); - if (ret) { -printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret); - goto out; - } - - if (info.entry.flags & UMSDOS_HLINK) { - /* - * In order to get the correct (real) inode, we just drop - * the original dentry. - */ - d_drop(dentry); -Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname)); - - /* Do a real lookup to get the short name dentry */ - temp = umsdos_covered(dentry->d_parent, info.fake.fname, - info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out; - - /* now resolve the link ... */ - temp = umsdos_solve_hlink(temp); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out; - old_dentry = dentry; - dentry = temp; /* so umsdos_notify_change_locked will operate on that */ - } - - dir = dentry->d_parent->d_inode; - inode = dentry->d_inode; - - ret = inode_change_ok (inode, attr); - if (ret) - goto out; - - ret = umsdos_notify_change_locked(dentry, attr); - if (ret == 0) - ret = inode_setattr (inode, attr); -out: - if (old_dentry) - dput (dentry); /* if we had to use fake dentry for hardlinks, dput() it now */ - unlock_kernel(); - return ret; -} - - -/* - * Must be called with the parent lock held. - */ -int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode = dentry->d_inode; - struct dentry *demd; - struct address_space *mapping; - struct page *page; - int ret = 0; - struct umsdos_dirent *entry; - int offs; - -Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n", -dentry->d_parent->d_name.name, dentry->d_name.name, UMSDOS_I(inode)->i_patched)); - - if (inode->i_nlink == 0) - goto out; - if (inode->i_ino == UMSDOS_ROOT_INO) - goto out; - - /* get the EMD file dentry */ - demd = umsdos_get_emd_dentry(dentry->d_parent); - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - ret = 0; - /* don't do anything if directory is not promoted to umsdos yet */ - if (!demd->d_inode) { - Printk((KERN_DEBUG - "UMSDOS_notify_change: no EMD file %s/%s\n", - demd->d_parent->d_name.name, demd->d_name.name)); - goto out_dput; - } - - /* don't do anything if this is the EMD itself */ - if (inode == demd->d_inode) - goto out_dput; - - /* This inode is not a EMD file nor an inode used internally - * by MSDOS, so we can update its status. - * See emd.c - */ - - /* Read only the start of the entry since we don't touch the name */ - mapping = demd->d_inode->i_mapping; - offs = UMSDOS_I(inode)->pos & ~PAGE_CACHE_MASK; - ret = -ENOMEM; - page=grab_cache_page(mapping,UMSDOS_I(inode)->pos>>PAGE_CACHE_SHIFT); - if (!page) - goto out_dput; - ret=mapping->a_ops->prepare_write(NULL,page,offs,offs+UMSDOS_REC_SIZE); - if (ret) - goto out_unlock; - entry = (struct umsdos_dirent *) (page_address(page) + offs); - if (attr->ia_valid & ATTR_UID) - entry->uid = cpu_to_le16(attr->ia_uid); - if (attr->ia_valid & ATTR_GID) - entry->gid = cpu_to_le16(attr->ia_gid); - if (attr->ia_valid & ATTR_MODE) - entry->mode = cpu_to_le16(attr->ia_mode); - if (attr->ia_valid & ATTR_ATIME) - entry->atime = cpu_to_le32(attr->ia_atime); - if (attr->ia_valid & ATTR_MTIME) - entry->mtime = cpu_to_le32(attr->ia_mtime); - if (attr->ia_valid & ATTR_CTIME) - entry->ctime = cpu_to_le32(attr->ia_ctime); - entry->nlink = cpu_to_le16(inode->i_nlink); - ret=mapping->a_ops->commit_write(NULL,page,offs,offs+UMSDOS_REC_SIZE); - if (ret) - printk(KERN_WARNING - "umsdos_notify_change: %s/%s EMD write error, ret=%d\n", - dentry->d_parent->d_name.name, dentry->d_name.name,ret); - - /* #Specification: notify_change / msdos fs - * notify_change operation are done only on the - * EMD file. The msdos fs is not even called. - */ -out_unlock: - unlock_page(page); - page_cache_release(page); -out_dput: - dput(demd); -out: - return ret; -} - - -/* - * Update the disk with the inode content - */ -int UMSDOS_write_inode (struct inode *inode, int wait) -{ - struct iattr newattrs; - int ret; - - ret = fat_write_inode (inode, wait); - newattrs.ia_mtime = inode->i_mtime; - newattrs.ia_atime = inode->i_atime; - newattrs.ia_ctime = inode->i_ctime; - newattrs.ia_valid = ATTR_MTIME | ATTR_ATIME | ATTR_CTIME; - /* - * UMSDOS_notify_change is convenient to call here - * to update the EMD entry associated with this inode. - * But it has the side effect to re"dirt" the inode. - */ -/* - * UMSDOS_notify_change (inode, &newattrs); - - * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work. We need to remove ourselves from list on dirty inodes. /mn/ */ - return ret; -} - - -static struct super_operations umsdos_sops = -{ - .write_inode = UMSDOS_write_inode, - .put_inode = UMSDOS_put_inode, - .delete_inode = fat_delete_inode, - .put_super = UMSDOS_put_super, - .statfs = UMSDOS_statfs, - .clear_inode = fat_clear_inode, -}; - -int UMSDOS_statfs(struct super_block *sb,struct statfs *buf) -{ - int ret; - ret = fat_statfs (sb, buf); - if (!ret) - buf->f_namelen = UMSDOS_MAXNAME; - return ret; -} - -/* - * Read the super block of an Extended MS-DOS FS. - */ -struct super_block *UMSDOS_read_super (struct super_block *sb, void *data, - int silent) -{ - struct super_block *res; - struct dentry *new_root; - - /* - * Call msdos-fs to mount the disk. - * Note: this returns res == sb or NULL - */ - MSDOS_SB(sb)->options.isvfat = 0; - res = fat_read_super(sb, data, silent, &umsdos_rdir_inode_operations); - - if (IS_ERR(res)) - return NULL; - if (res == NULL) { - if (!silent) - printk(KERN_INFO "VFS: Can't find a valid " - "UMSDOS filesystem on dev %s.\n", sb->s_id); - return NULL; - } - - printk (KERN_INFO "UMSDOS 0.86k " - "(compatibility level %d.%d, fast msdos)\n", - UMSDOS_VERSION, UMSDOS_RELEASE); - - sb->s_op = &umsdos_sops; - MSDOS_SB(sb)->options.dotsOK = 0; /* disable hidden==dotfile */ - - /* install our dentry operations ... */ - sb->s_root->d_op = &umsdos_dentry_operations; - - umsdos_patch_dentry_inode(sb->s_root, 0); - - /* Check whether to change to the /linux root */ - new_root = check_pseudo_root(sb); - - if (new_root) { - /* sanity check */ - if (new_root->d_op != &umsdos_dentry_operations) - printk("umsdos_read_super: pseudo-root wrong ops!\n"); - - pseudo_root = new_root->d_inode; - saved_root = sb->s_root; - printk(KERN_INFO "UMSDOS: changed to alternate root\n"); - dget (sb->s_root); sb->s_root = dget(new_root); - } - return sb; -} - -/* - * Check for an alternate root if we're the root device. - */ - -extern kdev_t ROOT_DEV; -static struct dentry *check_pseudo_root(struct super_block *sb) -{ - struct dentry *root, *sbin, *init; - - /* - * Check whether we're mounted as the root device. - * must check like this, because we can be used with initrd - */ - - if (!kdev_same(sb->s_dev, ROOT_DEV)) - goto out_noroot; - - /* - * lookup_dentry needs a (so far non-existent) root. - */ - printk(KERN_INFO "check_pseudo_root: mounted as root\n"); - root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN); - if (IS_ERR(root)) - goto out_noroot; - - if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode)) - goto out_dput; - -printk(KERN_INFO "check_pseudo_root: found %s/%s\n", -root->d_parent->d_name.name, root->d_name.name); - - /* look for /sbin/init */ - sbin = lookup_one_len("sbin", root, 4); - if (IS_ERR(sbin)) - goto out_dput; - if (!sbin->d_inode || !S_ISDIR(sbin->d_inode->i_mode)) - goto out_dput_sbin; - init = lookup_one_len("init", sbin, 4); - if (IS_ERR(init)) - goto out_dput_sbin; - if (!init->d_inode) - goto out_dput_init; - printk(KERN_INFO "check_pseudo_root: found %s/%s, enabling pseudo-root\n", init->d_parent->d_name.name, init->d_name.name); - dput(sbin); - dput(init); - return root; - - /* Alternate root not found ... */ -out_dput_init: - dput(init); -out_dput_sbin: - dput(sbin); -out_dput: - dput(root); -out_noroot: - return NULL; -} - - -static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super); - -static int __init init_umsdos_fs (void) -{ - return register_filesystem (&umsdos_fs_type); -} - -static void __exit exit_umsdos_fs (void) -{ - unregister_filesystem (&umsdos_fs_type); -} - -module_init(init_umsdos_fs) -module_exit(exit_umsdos_fs) -MODULE_LICENSE("GPL"); diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c deleted file mode 100644 index fc300030afd1..000000000000 --- a/fs/umsdos/ioctl.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * linux/fs/umsdos/ioctl.c - * - * Written 1993 by Jacques Gelinas - * - * Extended MS-DOS ioctl directory handling functions - * - * Changes: - * 11/07/2003 Daniele Bellucci - * - audit copy_to_user/put_user in umsdos_ioctl_fill. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct UMSDOS_DIR_ONCE { - struct dirent *ent; - int count; -}; - -/* - * Record a single entry the first call. - * Return -EINVAL the next one. - */ -static int umsdos_ioctl_fill ( - void *buf, - const char *name, - int name_len, - loff_t offset, - ino_t ino, - unsigned type) -{ - int ret = -EINVAL; - struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf; - - if (d->count == 0) { - if (copy_to_user (d->ent->d_name, name, name_len) || - put_user ('\0', d->ent->d_name + name_len) || - put_user (name_len, &d->ent->d_reclen) || - put_user (ino, &d->ent->d_ino) || - put_user (offset, &d->ent->d_off)) - return -EFAULT; - d->count = 1; - ret = 0; - } - return ret; -} - - -/* - * Perform special function on a directory - */ -/* #Specification: ioctl / prototypes - * The official prototype for the umsdos ioctl on directory - * is: - * - * int ioctl ( - * int fd, // File handle of the directory - * int cmd, // command - * struct umsdos_ioctl *data) - * - * The struct and the commands are defined in linux/umsdos_fs.h. - * - * umsdos_progs/umsdosio.c provide an interface in C++ to all - * these ioctl. umsdos_progs/udosctl is a small utility showing - * all this. - * - * These ioctl generally allow one to work on the EMD or the - * DOS directory independently. These are essential to implement - * the synchronise. - */ -int UMSDOS_ioctl_dir(struct inode *dir, struct file *filp, unsigned int cmd, - unsigned long data_ptr) -{ - struct dentry *dentry = filp->f_dentry; - struct umsdos_ioctl *idata = (struct umsdos_ioctl *) data_ptr; - int ret; - struct umsdos_ioctl data; - -Printk(("UMSDOS_ioctl_dir: %s/%s, cmd=%d, data=%08lx\n", -dentry->d_parent->d_name.name, dentry->d_name.name, cmd, data_ptr)); - - /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */ - if (cmd != UMSDOS_GETVERSION - && cmd != UMSDOS_READDIR_DOS - && cmd != UMSDOS_READDIR_EMD - && cmd != UMSDOS_INIT_EMD - && cmd != UMSDOS_CREAT_EMD - && cmd != UMSDOS_RENAME_DOS - && cmd != UMSDOS_UNLINK_EMD - && cmd != UMSDOS_UNLINK_DOS - && cmd != UMSDOS_RMDIR_DOS - && cmd != UMSDOS_STAT_DOS - && cmd != UMSDOS_DOS_SETUP) - return fat_dir_ioctl (dir, filp, cmd, data_ptr); - - /* #Specification: ioctl / access - * Only root (effective id) is allowed to do IOCTL on directory - * in UMSDOS. EPERM is returned for other user. - */ - /* - * Well, not all cases require write access, but it simplifies - * the code, and let's face it, there is only one client (umssync) - * for all this. - */ - ret = verify_area (VERIFY_WRITE, (void *) data_ptr, - sizeof (struct umsdos_ioctl)); - if (ret < 0) - goto out; - - ret = -EPERM; - if (current->euid != 0 && cmd != UMSDOS_GETVERSION) - goto out; - - ret = -EINVAL; - if (cmd == UMSDOS_GETVERSION) { - /* #Specification: ioctl / UMSDOS_GETVERSION - * The field version and release of the structure - * umsdos_ioctl are filled with the version and release - * number of the fs code in the kernel. This will allow - * some form of checking. Users won't be able to run - * incompatible utility such as the synchroniser (umssync). - * umsdos_progs/umsdosio.c enforce this checking. - * - * Return always 0. - */ - put_user (UMSDOS_VERSION, &idata->version); - put_user (UMSDOS_RELEASE, &idata->release); - ret = 0; - goto out; - } - if (cmd == UMSDOS_READDIR_DOS) { - /* #Specification: ioctl / UMSDOS_READDIR_DOS - * One entry is read from the DOS directory at the current - * file position. The entry is put as is in the dos_dirent - * field of struct umsdos_ioctl. - * - * Return > 0 if success. - */ - struct UMSDOS_DIR_ONCE bufk; - - bufk.count = 0; - bufk.ent = &idata->dos_dirent; - - fat_readdir (filp, &bufk, umsdos_ioctl_fill); - - ret = bufk.count == 1 ? 1 : 0; - goto out; - } - if (cmd == UMSDOS_READDIR_EMD) { - /* #Specification: ioctl / UMSDOS_READDIR_EMD - * One entry is read from the EMD at the current - * file position. The entry is put as is in the umsdos_dirent - * field of struct umsdos_ioctl. The corresponding mangled - * DOS entry name is put in the dos_dirent field. - * - * All entries are read including hidden links. Blank - * entries are skipped. - * - * Return > 0 if success. - */ - struct dentry *demd; - loff_t pos = filp->f_pos; - - /* The absence of the EMD is simply seen as an EOF */ - demd = umsdos_get_emd_dentry(dentry); - ret = PTR_ERR(demd); - if (IS_ERR(demd)) - goto out; - ret = 0; - if (!demd->d_inode) - goto read_dput; - - while (pos < demd->d_inode->i_size) { - off_t f_pos = pos; - struct umsdos_dirent entry; - struct umsdos_info info; - - ret = umsdos_emd_dir_readentry (demd, &pos, &entry); - - if (ret == -ENAMETOOLONG) { - printk (KERN_INFO "Fixing EMD entry with invalid size -- zeroing out\n"); - memset (&info, 0, sizeof (info)); - info.f_pos = f_pos; - info.recsize = UMSDOS_REC_SIZE; - ret = umsdos_writeentry (dentry, &info, 1); - continue; - } - - if (ret) - break; - if (entry.name_len <= 0) - continue; - - umsdos_parse (entry.name, entry.name_len, &info); - info.f_pos = f_pos; - umsdos_manglename (&info); - ret = -EFAULT; - if (copy_to_user (&idata->umsdos_dirent, &entry, - sizeof (entry))) - break; - if (copy_to_user (&idata->dos_dirent.d_name, - info.fake.fname, - info.fake.len + 1)) - break; - ret = entry.name_len; - break; - } - /* update the original f_pos */ - filp->f_pos = pos; - read_dput: - d_drop(demd); - dput(demd); - goto out; - } - if (cmd == UMSDOS_INIT_EMD) { - /* #Specification: ioctl / UMSDOS_INIT_EMD - * The UMSDOS_INIT_EMD command makes sure the EMD - * exists for a directory. If it does not, it is - * created. Also, it makes sure the directory function - * table (struct inode_operations) is set to the UMSDOS - * semantic. This mean that umssync may be applied to - * an "opened" msdos directory, and it will change behavior - * on the fly. - * - * Return 0 if success. - */ - - ret = umsdos_make_emd(dentry); -Printk(("UMSDOS_ioctl_dir: INIT_EMD %s/%s, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret)); - umsdos_setup_dir (dentry); - goto out; - } - - ret = -EFAULT; - if (copy_from_user (&data, idata, sizeof (data))) - goto out; - - if (cmd == UMSDOS_CREAT_EMD) { - /* #Specification: ioctl / UMSDOS_CREAT_EMD - * The umsdos_dirent field of the struct umsdos_ioctl is used - * as is to create a new entry in the EMD of the directory. - * The DOS directory is not modified. - * No validation is done (yet). - * - * Return 0 if success. - */ - struct umsdos_info info; - - /* This makes sure info.entry and info in general - * is correctly initialised - */ - memcpy (&info.entry, &data.umsdos_dirent, - sizeof (data.umsdos_dirent)); - umsdos_parse (data.umsdos_dirent.name - ,data.umsdos_dirent.name_len, &info); - ret = umsdos_newentry (dentry, &info); - goto out; - } - else if (cmd == UMSDOS_RENAME_DOS) { - struct dentry *old_dentry, *new_dentry; /* FIXME */ - - /* #Specification: ioctl / UMSDOS_RENAME_DOS - * A file or directory is renamed in a DOS directory - * (not moved across directory). The source name - * is in the dos_dirent.name field and the destination - * is in umsdos_dirent.name field. - * - * This ioctl allows umssync to rename a mangled file - * name before syncing it back in the EMD. - */ - old_dentry = umsdos_lookup_dentry (dentry, - data.dos_dirent.d_name, - data.dos_dirent.d_reclen ,1); - ret = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto out; - new_dentry = umsdos_lookup_dentry (dentry, - data.umsdos_dirent.name, - data.umsdos_dirent.name_len, 1); - ret = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { -printk("umsdos_ioctl: renaming %s/%s to %s/%s\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name, -new_dentry->d_parent->d_name.name, new_dentry->d_name.name); - ret = msdos_rename (dir, old_dentry, dir, new_dentry); - d_drop(new_dentry); - d_drop(old_dentry); - dput(new_dentry); - } - dput(old_dentry); - goto out; - } - else if (cmd == UMSDOS_UNLINK_EMD) { - /* #Specification: ioctl / UMSDOS_UNLINK_EMD - * The umsdos_dirent field of the struct umsdos_ioctl is used - * as is to remove an entry from the EMD of the directory. - * No validation is done (yet). The mode field is used - * to validate S_ISDIR or S_ISREG. - * - * Return 0 if success. - */ - struct umsdos_info info; - - /* This makes sure info.entry and info in general - * is correctly initialised - */ - memcpy (&info.entry, &data.umsdos_dirent, - sizeof (data.umsdos_dirent)); - umsdos_parse (data.umsdos_dirent.name, - data.umsdos_dirent.name_len, &info); - ret = umsdos_delentry (dentry, &info, - S_ISDIR (data.umsdos_dirent.mode)); - if (ret) { - printk(KERN_WARNING - "umsdos_ioctl: delentry %s/%s failed, ret=%d\n", - dentry->d_name.name, info.entry.name, ret); - } - goto out; - } - else if (cmd == UMSDOS_UNLINK_DOS) { - struct dentry *temp; - - /* #Specification: ioctl / UMSDOS_UNLINK_DOS - * The dos_dirent field of the struct umsdos_ioctl is used to - * execute a msdos_unlink operation. The d_name and d_reclen - * fields are used. - * - * Return 0 if success. - */ - temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name, - data.dos_dirent.d_reclen, 1); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out; - ret = -ENOENT; - if (temp->d_inode) { - ret = -EISDIR; - if (!S_ISDIR(temp->d_inode->i_mode)) - ret = msdos_unlink (dir, temp); - if (!ret) - d_delete(temp); - } - dput (temp); - goto out; - } - else if (cmd == UMSDOS_RMDIR_DOS) { - struct dentry *temp; - - /* #Specification: ioctl / UMSDOS_RMDIR_DOS - * The dos_dirent field of the struct umsdos_ioctl is used to - * execute a msdos_rmdir operation. The d_name and d_reclen - * fields are used. - * - * Return 0 if success. - */ - temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name, - data.dos_dirent.d_reclen, 1); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out; - ret = -ENOENT; - if (temp->d_inode) { - ret = -ENOTDIR; - if (S_ISDIR(temp->d_inode->i_mode)) - ret = msdos_rmdir (dir, temp); - if (!ret) - d_delete(temp); - } - dput (temp); - goto out; - - } else if (cmd == UMSDOS_STAT_DOS) { - /* #Specification: ioctl / UMSDOS_STAT_DOS - * The dos_dirent field of the struct umsdos_ioctl is - * used to execute a stat operation in the DOS directory. - * The d_name and d_reclen fields are used. - * - * The following field of umsdos_ioctl.stat are filled. - * - * st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime, - * Return 0 if success. - */ - struct dentry *dret; - struct inode *inode; - - dret = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name, - data.dos_dirent.d_reclen, 1); - ret = PTR_ERR(dret); - if (IS_ERR(dret)) - goto out; - ret = -ENOENT; - inode = dret->d_inode; - if (inode) { - data.stat.st_ino = inode->i_ino; - data.stat.st_mode = inode->i_mode; - data.stat.st_size = inode->i_size; - data.stat.st_atime = inode->i_atime; - data.stat.st_ctime = inode->i_ctime; - data.stat.st_mtime = inode->i_mtime; - ret = -EFAULT; - if (!copy_to_user (&idata->stat, &data.stat, - sizeof (data.stat))) - ret = 0; - } - dput(dret); - goto out; - } - else if (cmd == UMSDOS_DOS_SETUP) { - /* #Specification: ioctl / UMSDOS_DOS_SETUP - * The UMSDOS_DOS_SETUP ioctl allow changing the - * default permission of the MS-DOS filesystem driver - * on the fly. The MS-DOS driver applies global permissions - * to every file and directory. Normally these permissions - * are controlled by a mount option. This is not - * available for root partition, so a special utility - * (umssetup) is provided to do this, normally in - * /etc/rc.local. - * - * Be aware that this applies ONLY to MS-DOS directories - * (those without EMD --linux-.---). Umsdos directory - * have independent (standard) permission for each - * and every file. - * - * The field umsdos_dirent provide the information needed. - * umsdos_dirent.uid and gid sets the owner and group. - * umsdos_dirent.mode set the permissions flags. - */ - dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid; - dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid; - dir->i_sb->u.msdos_sb.options.fs_fmask = - dir->i_sb->u.msdos_sb.options.fs_dmask = - data.umsdos_dirent.mode; - ret = 0; - } -out: - Printk (("ioctl %d, returning %d\n", cmd, ret)); - return ret; -} diff --git a/fs/umsdos/mangle.c b/fs/umsdos/mangle.c deleted file mode 100644 index 0451123594d9..000000000000 --- a/fs/umsdos/mangle.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * linux/fs/umsdos/mangle.c - * - * Written 1993 by Jacques Gelinas - * - * Control the mangling of file name to fit msdos name space. - * Many optimisations by GLU == dglaude@is1.vub.ac.be (Glaude David) - */ - -#include -#include -#include -#include - -/* (This file is used outside of the kernel) */ -#ifndef __KERNEL__ -#define KERN_WARNING -#endif - -/* - * Complete the mangling of the MSDOS fake name - * based on the position of the entry in the EMD file. - * - * Simply complete the job of umsdos_parse; fill the extension. - * - * Beware that info->f_pos must be set. - */ -void umsdos_manglename (struct umsdos_info *info) -{ - if (info->msdos_reject) { - /* #Specification: file name / non MSDOS conforming / mangling - * Each non MSDOS conforming file has a special extension - * build from the entry position in the EMD file. - * - * This number is then transform in a base 32 number, where - * each digit is expressed like hexadecimal number, using - * digit and letter, except it uses 22 letters from 'a' to 'v'. - * The number 32 comes from 2**5. It is faster to split a binary - * number using a base which is a power of two. And I was 32 - * when I started this project. Pick your answer :-) . - * - * If the result is '0', it is replace with '_', simply - * to make it odd. - * - * This is true for the first two character of the extension. - * The last one is taken from a list of odd character, which - * are: - * - * { } ( ) ! ` ^ & @ - * - * With this scheme, we can produce 9216 ( 9* 32 * 32) - * different extensions which should not clash with any useful - * extension already popular or meaningful. Since most directory - * have much less than 32 * 32 files in it, the first character - * of the extension of any mangled name will be {. - * - * Here are the reason to do this (this kind of mangling). - * - * -The mangling is deterministic. Just by the extension, we - * are able to locate the entry in the EMD file. - * - * -By keeping to beginning of the file name almost unchanged, - * we are helping the MSDOS user. - * - * -The mangling produces names not too ugly, so an msdos user - * may live with it (remember it, type it, etc...). - * - * -The mangling produces names ugly enough so no one will - * ever think of using such a name in real life. This is not - * fool proof. I don't think there is a total solution to this. - */ - int entry_num; - char *pt = info->fake.fname + info->fake.len; - /* lookup for encoding the last character of the extension - * It contains valid character after the ugly one to make sure - * even if someone overflows the 32 * 32 * 9 limit, it still - * does something - */ -#define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@' - static char lookup3[] = - { - SPECIAL_MANGLING, - /* This is the start of lookup12 */ - '_', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v' - }; - -#define lookup12 (lookup3+9) - entry_num = info->f_pos / UMSDOS_REC_SIZE; - if (entry_num > (9* 32 * 32)){ - printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n" - "This may break the mangling strategy.\n" - "Not a killer problem. See doc.\n"); - } - *pt++ = '.'; - *pt++ = lookup3 [(entry_num >> 10) & 31]; - *pt++ = lookup12[(entry_num >> 5) & 31]; - *pt++ = lookup12[entry_num & 31]; - *pt = '\0'; /* help doing printk */ - info->fake.len += 4; - info->msdos_reject = 0; /* Avoid mangling twice */ - } -} - -/* - * Evaluate the record size needed to store of name of len character. - * The value returned is a multiple of UMSDOS_REC_SIZE. - */ -int umsdos_evalrecsize (int len) -{ - struct umsdos_dirent dirent; - int nbrec = 1 + ((len - 1 + (dirent.name - (char *) &dirent)) - / UMSDOS_REC_SIZE); - - return nbrec * UMSDOS_REC_SIZE; - /* - * GLU This should be inlined or something to speed it up to the max. - * GLU nbrec is absolutely not needed to return the value. - */ -} -#ifdef TEST -int umsdos_evalrecsize_old (int len) -{ - struct umsdos_dirent dirent; - int size = len + (dirent.name - (char *) &dirent); - int nbrec = size / UMSDOS_REC_SIZE; - int extra = size % UMSDOS_REC_SIZE; - - if (extra > 0) - nbrec++; - return nbrec * UMSDOS_REC_SIZE; -} -#endif - - -/* - * Fill the struct info with the full and msdos name of a file - * Return 0 if all is OK, a negative error code otherwise. - */ -int umsdos_parse ( - const char *fname, - int len, - struct umsdos_info *info) -{ - int ret = -ENAMETOOLONG; - - /* #Specification: file name / too long - * If a file name exceed UMSDOS maxima, the file name is silently - * truncated. This makes it conformant with the other file system - * of Linux (minix and ext2 at least). - */ - if (len > UMSDOS_MAXNAME) - len = UMSDOS_MAXNAME; - { - const char *firstpt = NULL; /* First place we saw a "." in fname */ - - /* #Specification: file name / non MSDOS conforming / base length 0 - * file names beginning with a period '.' are invalid for MS-DOS. - * It needs absolutely a base name. So the file name is mangled - */ - int ivldchar = fname[0] == '.'; /* At least one invalid character */ - int msdos_len = len; - int base_len; - - /* - * cardinal_per_size tells if there exists at least one - * DOS pseudo device on length n. See the test below. - */ - static const char cardinal_per_size[9] = - { - 0, 0, 0, 1, 1, 0, 1, 0, 1 - }; - - /* - * lkp translate all character to acceptable character (for DOS). - * When lkp[n] == n, it means also it is an acceptable one. - * So it serves both as a flag and as a translator. - */ - static char lkp[256]; - static char is_init; - - if (!is_init) { - /* - * Initialisation of the array is easier and less error - * prone like this. - */ - int i; - static const char *spc = "\"*+,/:;<=>?[\\]|~"; - - is_init = 1; - for (i = 0; i <= 32; i++) - lkp[i] = '#'; - for (i = 33; i < 'A'; i++) - lkp[i] = (char) i; - for (i = 'A'; i <= 'Z'; i++) - lkp[i] = (char) (i + ('a' - 'A')); - for (i = 'Z' + 1; i < 127; i++) - lkp[i] = (char) i; - for (i = 128; i < 256; i++) - lkp[i] = '#'; - - lkp['.'] = '_'; - while (*spc != '\0') - lkp[(unsigned char) (*spc++)] = '#'; - } - /* GLU - * File names longer than 8+'.'+3 are invalid for MS-DOS, - * so the file name is to be mangled--no further test is needed. - * This speeds up handling of long names. - * The position of the last point is no more necessary anyway. - */ - if (len <= (8 + 1 + 3)) { - const char *pt = fname; - const char *endpt = fname + len; - - while (pt < endpt) { - if (*pt == '.') { - if (firstpt != NULL) { - /* 2 . in a file name. Reject */ - ivldchar = 1; - break; - } else { - int extlen = (int) (endpt - pt); - - firstpt = pt; - if (firstpt - fname > 8) { - /* base name longer than 8: reject */ - ivldchar = 1; - break; - } else if (extlen > 4) { - /* Extension longer than 4 (including .): reject */ - ivldchar = 1; - break; - } else if (extlen == 1) { - /* #Specification: file name / non MSDOS conforming / last char == . - * If the last character of a file name is - * a period, mangling is applied. MS-DOS does - * not support those file names. - */ - ivldchar = 1; - break; - } else if (extlen == 4) { - /* #Specification: file name / non MSDOS conforming / mangling clash - * To avoid clash with the umsdos mangling, any file - * with a special character as the first character - * of the extension will be mangled. This solves the - * following problem: - * - * # - * touch FILE - * # FILE is invalid for DOS, so mangling is applied - * # file.{_1 is created in the DOS directory - * touch file.{_1 - * # To UMSDOS file point to a single DOS entry. - * # So file.{_1 has to be mangled. - * # - */ - static char special[] = - { - SPECIAL_MANGLING, '\0' - }; - - if (strchr (special, firstpt[1]) != NULL) { - ivldchar = 1; - break; - } - } - } - } else if (lkp[(unsigned char) (*pt)] != *pt) { - ivldchar = 1; - break; - } - pt++; - } - } else { - ivldchar = 1; - } - if (ivldchar - || (firstpt == NULL && len > 8) - || (len == UMSDOS_EMD_NAMELEN - && memcmp (fname, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN) == 0)) { - /* #Specification: file name / --linux-.--- - * The name of the EMD file --linux-.--- is map to a mangled - * name. So UMSDOS does not restrict its use. - */ - /* #Specification: file name / non MSDOS conforming / mangling - * Non MSDOS conforming file names must use some alias to fit - * in the MSDOS name space. - * - * The strategy is simple. The name is simply truncated to - * 8 char. points are replace with underscore and a - * number is given as an extension. This number correspond - * to the entry number in the EMD file. The EMD file - * only need to carry the real name. - * - * Upper case is also converted to lower case. - * Control character are converted to #. - * Spaces are converted to #. - * The following characters are also converted to #. - * # - * " * + , / : ; < = > ? [ \ ] | ~ - * # - * - * Sometimes the problem is not in MS-DOS itself but in - * command.com. - */ - int i; - char *pt = info->fake.fname; - - base_len = msdos_len = (msdos_len > 8) ? 8 : msdos_len; - /* - * There is no '.' any more so we know for a fact that - * the base length is the length. - */ - memcpy (info->fake.fname, fname, msdos_len); - for (i = 0; i < msdos_len; i++, pt++) - *pt = lkp[(unsigned char) (*pt)]; - *pt = '\0'; /* GLU We force null termination. */ - info->msdos_reject = 1; - /* - * The numeric extension is added only when we know - * the position in the EMD file, in umsdos_newentry(), - * umsdos_delentry(), and umsdos_findentry(). - * See umsdos_manglename(). - */ - } else { - /* Conforming MSDOS file name */ - strncpy (info->fake.fname, fname, len); - info->msdos_reject = 0; - base_len = firstpt != NULL ? (int) (firstpt - fname) : len; - } - if (cardinal_per_size[base_len]) { - /* #Specification: file name / MSDOS devices / mangling - * To avoid unreachable file from MS-DOS, any MS-DOS conforming - * file with a basename equal to one of the MS-DOS pseudo - * devices will be mangled. - * - * If a file such as "prn" was created, it would be unreachable - * under MS-DOS because "prn" is assumed to be the printer, even - * if the file does have an extension. - * - * Since the extension is unimportant to MS-DOS, we must patch - * the basename also. We simply insert a minus '-'. To avoid - * conflict with valid file with a minus in front (such as - * "-prn"), we add an mangled extension like any other - * mangled file name. - * - * Here is the list of DOS pseudo devices: - * - * # - * "prn","con","aux","nul", - * "lpt1","lpt2","lpt3","lpt4", - * "com1","com2","com3","com4", - * "clock$" - * # - * - * and some standard ones for common DOS programs - * - * "emmxxxx0","xmsxxxx0","setverxx" - * - * (Thanks to Chris Hall - * for pointing these out to me). - * - * Is there one missing? - */ - /* This table must be ordered by length */ - static const char *tbdev[] = - { - "prn", "con", "aux", "nul", - "lpt1", "lpt2", "lpt3", "lpt4", - "com1", "com2", "com3", "com4", - "clock$", - "emmxxxx0", "xmsxxxx0", "setverxx" - }; - - /* Tell where to find in tbdev[], the first name of */ - /* a certain length */ - static const char start_ind_dev[9] = - { - 0, 0, 0, 4, 12, 12, 13, 13, 16 - }; - char basen[9]; - int i; - - for (i = start_ind_dev[base_len - 1]; i < start_ind_dev[base_len]; i++) { - if (memcmp (info->fake.fname, tbdev[i], base_len) == 0) { - memcpy (basen, info->fake.fname, base_len); - basen[base_len] = '\0'; /* GLU We force null termination. */ - /* - * GLU We do that only if necessary; we try to do the - * GLU simple thing in the usual circumstance. - */ - info->fake.fname[0] = '-'; - strcpy (info->fake.fname + 1, basen); /* GLU We already guaranteed a null would be at the end. */ - msdos_len = (base_len == 8) ? 8 : base_len + 1; - info->msdos_reject = 1; - break; - } - } - } - info->fake.fname[msdos_len] = '\0'; /* Help doing printk */ - /* GLU This zero should (always?) be there already. */ - info->fake.len = msdos_len; - /* Why not use info->fake.len everywhere? Is it longer? - */ - memcpy (info->entry.name, fname, len); - info->entry.name[len] = '\0'; /* for printk */ - info->entry.name_len = len; - ret = 0; - } - /* - * Evaluate how many records are needed to store this entry. - */ - info->recsize = umsdos_evalrecsize (len); - return ret; -} - -#ifdef TEST - -struct MANG_TEST { - char *fname; /* Name to validate */ - int msdos_reject; /* Expected msdos_reject flag */ - char *msname; /* Expected msdos name */ -}; - -struct MANG_TEST tb[] = -{ - "hello", 0, "hello", - "hello.1", 0, "hello.1", - "hello.1_", 0, "hello.1_", - "prm", 0, "prm", - -#ifdef PROPOSITION - "HELLO", 1, "hello", - "Hello.1", 1, "hello.1", - "Hello.c", 1, "hello.c", -#else -/* - * I find the three examples below very unfortunate. I propose to - * convert them to lower case in a quick preliminary pass, then test - * whether there are other troublesome characters. I have not made - * this change, because it is not easy, but I wanted to mention the - * principle. Obviously something like that would increase the chance - * of collisions, for example between "HELLO" and "Hello", but these - * can be treated elsewhere along with the other collisions. - */ - - "HELLO", 1, "hello", - "Hello.1", 1, "hello_1", - "Hello.c", 1, "hello_c", -#endif - - "hello.{_1", 1, "hello_{_", - "hello\t", 1, "hello#", - "hello.1.1", 1, "hello_1_", - "hel,lo", 1, "hel#lo", - "Salut.Tu.vas.bien?", 1, "salut_tu", - ".profile", 1, "_profile", - ".xv", 1, "_xv", - "toto.", 1, "toto_", - "clock$.x", 1, "-clock$", - "emmxxxx0", 1, "-emmxxxx", - "emmxxxx0.abcd", 1, "-emmxxxx", - "aux", 1, "-aux", - "prn", 1, "-prn", - "prn.abc", 1, "-prn", - "PRN", 1, "-prn", - /* - * GLU WARNING: the results of these are different with my version - * GLU of mangling compared to the original one. - * GLU CAUSE: the manner of calculating the baselen variable. - * GLU For you they are always 3. - * GLU For me they are respectively 7, 8, and 8. - - */ - "PRN.abc", 1, "prn_abc", - "Prn.abcd", 1, "prn_abcd", - "prn.abcd", 1, "prn_abcd", - "Prn.abcdefghij", 1, "prn_abcd" -}; - -int main (int argc, char *argv[]) -{ - int i, rold, rnew; - - printf ("Testing the umsdos_parse.\n"); - for (i = 0; i < sizeof (tb) / sizeof (tb[0]); i++) { - struct MANG_TEST *pttb = tb + i; - struct umsdos_info info; - int ok = umsdos_parse (pttb->fname, strlen (pttb->fname), &info); - - if (strcmp (info.fake.fname, pttb->msname) != 0) { - printf ("**** %s -> ", pttb->fname); - printf ("%s <> %s\n", info.fake.fname, pttb->msname); - } else if (info.msdos_reject != pttb->msdos_reject) { - printf ("**** %s -> %s ", pttb->fname, pttb->msname); - printf ("%d <> %d\n", info.msdos_reject, pttb->msdos_reject); - } else { - printf (" %s -> %s %d\n", pttb->fname, pttb->msname - ,pttb->msdos_reject); - } - } - printf ("Testing the new umsdos_evalrecsize."); - for (i = 0; i < UMSDOS_MAXNAME; i++) { - rnew = umsdos_evalrecsize (i); - rold = umsdos_evalrecsize_old (i); - if (!(i % UMSDOS_REC_SIZE)) { - printf ("\n%d:\t", i); - } - if (rnew != rold) { - printf ("**** %d newres: %d != %d \n", i, rnew, rold); - } else { - printf ("."); - } - } - printf ("\nEnd of Testing.\n"); - - return 0; -} - -#endif diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c deleted file mode 100644 index 2d8a64af1aed..000000000000 --- a/fs/umsdos/namei.c +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * linux/fs/umsdos/namei.c - * - * Written 1993 by Jacques Gelinas - * Inspired from linux/fs/msdos/... by Werner Almesberger - * - * Maintain and access the --linux alternate directory file. - */ - /* - * You are in the maze of twisted functions - half of them shouldn't - * be here... - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define UMSDOS_DIR_LOCK - -#ifdef UMSDOS_DIR_LOCK - -static inline void u_sleep_on (struct inode *dir) -{ - sleep_on (&UMSDOS_I(dir)->dir_info.p); -} - -static inline void u_wake_up (struct inode *dir) -{ - wake_up (&UMSDOS_I(dir)->dir_info.p); -} - -/* - * Wait for creation exclusivity. - * Return 0 if the dir was already available. - * Return 1 if a wait was necessary. - * When 1 is return, it means a wait was done. It does not - * mean the directory is available. - */ -static int umsdos_waitcreate (struct inode *dir) -{ - int ret = 0; - - if (UMSDOS_I(dir)->dir_info.creating - && UMSDOS_I(dir)->dir_info.pid != current->pid) { - PRINTK (("creating && dir_info.pid=%lu, current->pid=%u\n", UMSDOS_I(dir)->dir_info.pid, current->pid)); - u_sleep_on (dir); - ret = 1; - } - return ret; -} - -/* - * Wait for any lookup process to finish - */ -static void umsdos_waitlookup (struct inode *dir) -{ - while (UMSDOS_I(dir)->dir_info.looking) { - u_sleep_on (dir); - } -} - -/* - * Lock all other process out of this directory. - */ -/* #Specification: file creation / not atomic - * File creation is a two step process. First we create (allocate) - * an entry in the EMD file and then (using the entry offset) we - * build a unique name for MSDOS. We create this name in the msdos - * space. - * - * We have to use semaphore (sleep_on/wake_up) to prevent lookup - * into a directory when we create a file or directory and to - * prevent creation while a lookup is going on. Since many lookup - * may happen at the same time, the semaphore is a counter. - * - * Only one creation is allowed at the same time. This protection - * may not be necessary. The problem arise mainly when a lookup - * or a readdir is done while a file is partially created. The - * lookup process see that as a "normal" problem and silently - * erase the file from the EMD file. Normal because a file - * may be erased during a MSDOS session, but not removed from - * the EMD file. - * - * The locking is done on a directory per directory basis. Each - * directory inode has its wait_queue. - * - * For some operation like hard link, things even get worse. Many - * creation must occur at once (atomic). To simplify the design - * a process is allowed to recursively lock the directory for - * creation. The pid of the locking process is kept along with - * a counter so a second level of locking is granted or not. - */ -void umsdos_lockcreate (struct inode *dir) -{ - /* - * Wait for any creation process to finish except - * if we (the process) own the lock - */ - while (umsdos_waitcreate (dir) != 0); - UMSDOS_I(dir)->dir_info.creating++; - UMSDOS_I(dir)->dir_info.pid = current->pid; - umsdos_waitlookup (dir); -} - -/* - * Lock all other process out of those two directories. - */ -static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2) -{ - /* - * We must check that both directory are available before - * locking anyone of them. This is to avoid some deadlock. - * Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing - * this to me. - */ - while (1) { - if (umsdos_waitcreate (dir1) == 0 - && umsdos_waitcreate (dir2) == 0) { - /* We own both now */ - UMSDOS_I(dir1)->dir_info.creating++; - UMSDOS_I(dir1)->dir_info.pid = current->pid; - UMSDOS_I(dir2)->dir_info.creating++; - UMSDOS_I(dir2)->dir_info.pid = current->pid; - break; - } - } - umsdos_waitlookup (dir1); - umsdos_waitlookup (dir2); -} - -/* - * Wait until creation is finish in this directory. - */ -void umsdos_startlookup (struct inode *dir) -{ - while (umsdos_waitcreate (dir) != 0); - UMSDOS_I(dir)->dir_info.looking++; -} - -/* - * Unlock the directory. - */ -void umsdos_unlockcreate (struct inode *dir) -{ - UMSDOS_I(dir)->dir_info.creating--; - if (UMSDOS_I(dir)->dir_info.creating < 0) { - printk ("UMSDOS: UMSDOS_I(dir)->dir_info.creating < 0: %d" - ,UMSDOS_I(dir)->dir_info.creating); - } - u_wake_up (dir); -} - -/* - * Tell directory lookup is over. - */ -void umsdos_endlookup (struct inode *dir) -{ - UMSDOS_I(dir)->dir_info.looking--; - if (UMSDOS_I(dir)->dir_info.looking < 0) { - printk ("UMSDOS: UMSDOS_I(dir)->dir_info.looking < 0: %d" - ,UMSDOS_I(dir)->dir_info.looking); - } - u_wake_up (dir); -} - -#else -static void umsdos_lockcreate (struct inode *dir) -{ -} -static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2) -{ -} -void umsdos_startlookup (struct inode *dir) -{ -} -static void umsdos_unlockcreate (struct inode *dir) -{ -} -void umsdos_endlookup (struct inode *dir) -{ -} - -#endif - -static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry, - int errcod) -{ - int ret = 0; - - if (umsdos_is_pseudodos (dir, dentry)) { - /* #Specification: pseudo root / any file creation /DOS - * The pseudo sub-directory /DOS can't be created! - * EEXIST is returned. - * - * The pseudo sub-directory /DOS can't be removed! - * EPERM is returned. - */ - ret = errcod; - } - return ret; -} - -/* - * Add a new file (ordinary or special) into the alternate directory. - * The file is added to the real MSDOS directory. If successful, it - * is then added to the EMD file. - * - * Return the status of the operation. 0 mean success. - * - * #Specification: create / file exists in DOS - * Here is a situation: we are trying to create a file with - * UMSDOS. The file is unknown to UMSDOS but already - * exists in the DOS directory. - * - * Here is what we are NOT doing: - * - * We could silently assume that everything is fine - * and allows the creation to succeed. - * - * It is possible not all files in the partition - * are meant to be visible from linux. By trying to create - * those file in some directory, one user may get access - * to those file without proper permissions. Looks like - * a security hole to me. Off course sharing a file system - * with DOS is some kind of security hole :-) - * - * So ? - * - * We return EEXIST in this case. - * The same is true for directory creation. - */ -static int umsdos_create_any (struct inode *dir, struct dentry *dentry, - int mode, dev_t rdev, char flags) -{ - struct dentry *fake; - struct inode *inode; - int ret; - struct umsdos_info info; - - ret = umsdos_nevercreat (dir, dentry, -EEXIST); - if (ret) - goto out; - - ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); - if (ret) - goto out; - - info.entry.mode = mode; - info.entry.rdev = rdev; - info.entry.flags = flags; - info.entry.uid = current->fsuid; - info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds(); - info.entry.nlink = 1; - ret = umsdos_newentry (dentry->d_parent, &info); - if (ret) - goto out; - - /* do a real lookup to get the short name dentry */ - fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); - ret = PTR_ERR(fake); - if (IS_ERR(fake)) - goto out_remove; - - /* should not exist yet ... */ - ret = -EEXIST; - if (fake->d_inode) - goto out_remove_dput; - - ret = msdos_create (dir, fake, S_IFREG | 0777, NULL); - if (ret) - goto out_remove_dput; - - inode = fake->d_inode; - atomic_inc(&inode->i_count); - d_instantiate (dentry, inode); - dput(fake); - if (atomic_read(&inode->i_count) > 1) { - printk(KERN_WARNING - "umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - inode->i_ino, atomic_read(&inode->i_count)); - } - umsdos_lookup_patch_new(dentry, &info); - -out: - return ret; - - /* Creation failed ... remove the EMD entry */ -out_remove_dput: - dput(fake); -out_remove: - if (ret == -EEXIST) - printk(KERN_WARNING "UMSDOS: out of sync, deleting %s/%s\n", - dentry->d_parent->d_name.name, info.fake.fname); - umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode)); - goto out; -} - -/* - * Add a new file into the alternate directory. - * The file is added to the real MSDOS directory. If successful, it - * is then added to the EMD file. - * - * Return the status of the operation. 0 mean success. - */ -int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) -{ - return umsdos_create_any (dir, dentry, mode, 0, 0); -} - - -/* - * Initialise the new_entry from the old for a rename operation. - * (Only useful for umsdos_rename_f() below). - */ -static void umsdos_ren_init (struct umsdos_info *new_info, - struct umsdos_info *old_info) -{ - new_info->entry.mode = old_info->entry.mode; - new_info->entry.rdev = old_info->entry.rdev; - new_info->entry.uid = old_info->entry.uid; - new_info->entry.gid = old_info->entry.gid; - new_info->entry.ctime = old_info->entry.ctime; - new_info->entry.atime = old_info->entry.atime; - new_info->entry.mtime = old_info->entry.mtime; - new_info->entry.flags = old_info->entry.flags; - new_info->entry.nlink = old_info->entry.nlink; -} - -/* - * Rename a file (move) in the file system. - */ - -static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - int flags) -{ - struct inode *old_inode = old_dentry->d_inode; - struct dentry *old, *new, *old_emd; - int err, ret; - struct umsdos_info old_info; - struct umsdos_info new_info; - - ret = -EPERM; - err = umsdos_parse (old_dentry->d_name.name, - old_dentry->d_name.len, &old_info); - if (err) - goto out; - err = umsdos_parse (new_dentry->d_name.name, - new_dentry->d_name.len, &new_info); - if (err) - goto out; - - /* Get the EMD dentry for the old parent */ - old_emd = umsdos_get_emd_dentry(old_dentry->d_parent); - ret = PTR_ERR(old_emd); - if (IS_ERR(old_emd)) - goto out; - - umsdos_lockcreate2 (old_dir, new_dir); - - ret = umsdos_findentry(old_emd->d_parent, &old_info, 0); - if (ret) - goto out_unlock; - - err = umsdos_findentry(new_dentry->d_parent, &new_info, 0); - if (err == 0) { - /* check whether it _really_ exists ... */ - ret = -EEXIST; - if (new_dentry->d_inode) - goto out_unlock; - - /* bogus lookup? complain and fix up the EMD ... */ - printk(KERN_WARNING - "umsdos_rename_f: entry %s/%s exists, inode NULL??\n", - new_dentry->d_parent->d_name.name, new_info.entry.name); - err = umsdos_delentry(new_dentry->d_parent, &new_info, - S_ISDIR(new_info.entry.mode)); - } - - umsdos_ren_init (&new_info, &old_info); - if (flags) - new_info.entry.flags = flags; - ret = umsdos_newentry (new_dentry->d_parent, &new_info); - if (ret) - goto out_unlock; - - /* If we're moving a hardlink, drop it first */ - if (old_info.entry.flags & UMSDOS_HLINK) { - d_drop(old_dentry); - } - - old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname, - old_info.fake.len); - ret = PTR_ERR(old); - if (IS_ERR(old)) - goto out_unlock; - /* make sure it's the same inode! */ - ret = -ENOENT; - /* - * note: for hardlinks they will be different! - * old_inode will contain inode of .LINKxxx file containing data, and - * old->d_inode will contain inode of file containing path to .LINKxxx file - */ - if (!(old_info.entry.flags & UMSDOS_HLINK)) { - if (old->d_inode != old_inode) - goto out_dput; - } - - new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, - new_info.fake.len); - ret = PTR_ERR(new); - if (IS_ERR(new)) - goto out_dput; - - /* Do the msdos-level rename */ - ret = msdos_rename (old_dir, old, new_dir, new); - - dput(new); - - /* If the rename failed, remove the new EMD entry */ - if (ret != 0) { - umsdos_delentry (new_dentry->d_parent, &new_info, - S_ISDIR (new_info.entry.mode)); - goto out_dput; - } - - /* - * Rename successful ... remove the old name from the EMD. - * Note that we use the EMD parent here, as the old dentry - * may have moved to a new parent ... - */ - err = umsdos_delentry (old_emd->d_parent, &old_info, - S_ISDIR (old_info.entry.mode)); - if (err) { - /* Failed? Complain a bit, but don't fail the operation */ - printk(KERN_WARNING - "umsdos_rename_f: delentry %s/%s failed, error=%d\n", - old_emd->d_parent->d_name.name, old_info.entry.name, - err); - } - - /* - * Update f_pos so notify_change will succeed - * if the file was already in use. - */ - umsdos_set_dirinfo_new(old_dentry, new_info.f_pos); - - /* dput() the dentry if we haven't already */ -out_dput: - dput(old); - -out_unlock: - dput(old_emd); - umsdos_unlockcreate (old_dir); - umsdos_unlockcreate (new_dir); - -out: - Printk ((" _ret=%d\n", ret)); - return ret; -} - -/* - * Setup a Symbolic link or a (pseudo) hard link - * Return a negative error code or 0 if OK. - */ -/* #Specification: symbolic links / strategy - * A symbolic link is simply a file which holds a path. It is - * implemented as a normal MSDOS file (not very space efficient :-() - * - * I see two different ways to do this: One is to place the link data - * in unused entries of the EMD file; the other is to have a separate - * file dedicated to hold all symbolic links data. - * - * Let's go for simplicity... - */ - -/* - * AV. Should be called with dir->i_sem down. - */ -static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry, - const char *symname, int mode, char flags) -{ - int ret, len; - - ret = umsdos_create_any (dir, dentry, mode, 0, flags); - if (ret) { - printk(KERN_WARNING - "umsdos_symlink: create failed, ret=%d\n", ret); - goto out; - } - - len = strlen (symname) + 1; - ret = page_symlink(dentry->d_inode, symname, len); - if (ret < 0) - goto out_unlink; -out: - return ret; - -out_unlink: - printk(KERN_WARNING "umsdos_symlink: write failed, unlinking\n"); - UMSDOS_unlink (dir, dentry); - d_drop(dentry); - goto out; -} - -/* - * Setup a Symbolic link. - * Return a negative error code or 0 if OK. - */ -int UMSDOS_symlink ( struct inode *dir, struct dentry *dentry, - const char *symname) -{ - return umsdos_symlink_x (dir, dentry, symname, S_IFLNK | 0777, 0); -} - -/* - * Add a link to an inode in a directory - */ -int UMSDOS_link (struct dentry *olddentry, struct inode *dir, - struct dentry *dentry) -{ - struct inode *oldinode = olddentry->d_inode; - struct inode *olddir = olddentry->d_parent->d_inode; - struct dentry *temp; - char *path; - unsigned long buffer; - int ret; - struct umsdos_info old_info; - struct umsdos_info hid_info; - -#ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_link: new %s/%s -> %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name, -olddentry->d_parent->d_name.name, olddentry->d_name.name); -#endif - - ret = -EPERM; - if (S_ISDIR (oldinode->i_mode)) - goto out; - - ret = umsdos_nevercreat (dir, dentry, -EPERM); - if (ret) - goto out; - - ret = -ENOMEM; - buffer = get_zeroed_page(GFP_KERNEL); - if (!buffer) - goto out; - - /* - * Lock the link parent if it's not the same directory. - */ - ret = -EDEADLOCK; - if (olddir != dir) { - if (atomic_read(&olddir->i_sem.count) < 1) - goto out_free; - down(&olddir->i_sem); - } - - /* - * Parse the name and get the visible directory entry. - */ - ret = umsdos_parse (olddentry->d_name.name, olddentry->d_name.len, - &old_info); - if (ret) - goto out_unlock; - ret = umsdos_findentry (olddentry->d_parent, &old_info, 1); - if (ret) { -printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name, ret); - goto out_unlock; - } - - /* - * If the visible dentry is a pseudo-hardlink, the original - * file must be already hidden. - */ - if (!(old_info.entry.flags & UMSDOS_HLINK)) { - int err; - - /* create a hidden link name */ - ret = umsdos_newhidden (olddentry->d_parent, &hid_info); - if (ret) { -printk("umsdos_link: can't make hidden %s/%s, ret=%d\n", -olddentry->d_parent->d_name.name, hid_info.entry.name, ret); - goto out_unlock; - } - - /* - * Make a dentry and rename the original file ... - */ - temp = umsdos_lookup_dentry(olddentry->d_parent, - hid_info.entry.name, - hid_info.entry.name_len, 0); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) { -printk("umsdos_link: lookup %s/%s failed, ret=%d\n", -dentry->d_parent->d_name.name, hid_info.entry.name, ret); - goto cleanup; - } - /* rename the link to the hidden location ... */ - ret = umsdos_rename_f(olddir, olddentry, olddir, temp, - UMSDOS_HIDDEN); - d_move(olddentry, temp); - dput(temp); - if (ret) { -printk("umsdos_link: rename to %s/%s failed, ret=%d\n", -temp->d_parent->d_name.name, temp->d_name.name, ret); - goto cleanup; - } - /* mark the inode as a hardlink */ - UMSDOS_I(oldinode)->i_is_hlink = 1; - - /* - * Capture the path to the hidden link. - */ - path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE); -Printk(("umsdos_link: hidden link path=%s\n", path)); - - /* - * Recreate a dentry for the original name and symlink it, - * then symlink the new dentry. Don't give up if one fails, - * or we'll lose the file completely! - * - * Note: this counts as the "original" reference, so we - * don't increment i_nlink for this one. - */ - temp = umsdos_lookup_dentry(olddentry->d_parent, - old_info.entry.name, - old_info.entry.name_len, 0); - ret = PTR_ERR(temp); - if (!IS_ERR(temp)) { - ret = umsdos_symlink_x (olddir, temp, path, - S_IFREG | 0777, UMSDOS_HLINK); - dput(temp); - } - - /* This symlink increments i_nlink (see below.) */ - err = umsdos_symlink_x (dir, dentry, path, - S_IFREG | 0777, UMSDOS_HLINK); - /* fold the two errors */ - if (!ret) - ret = err; - goto out_unlock; - - /* creation failed ... remove the link entry */ - cleanup: -printk("umsdos_link: link failed, ret=%d, removing %s/%s\n", -ret, olddentry->d_parent->d_name.name, hid_info.entry.name); - err = umsdos_delentry(olddentry->d_parent, &hid_info, 0); - goto out_unlock; - } - -Printk(("UMSDOS_link: %s/%s already hidden\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name)); - /* - * The original file is already hidden, and we need to get - * the dentry for its real name, not the visible name. - * N.B. make sure it's the hidden inode ... - */ - if (!UMSDOS_I(oldinode)->i_is_hlink) - printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n", - olddentry->d_parent->d_name.name, - olddentry->d_name.name, oldinode->i_ino); - - /* - * In order to get the correct (real) inode, we just drop - * the original dentry. - */ - d_drop(olddentry); -Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname)); - - /* Do a real lookup to get the short name dentry */ - temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, - old_info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_unlock; - - /* now resolve the link ... */ - temp = umsdos_solve_hlink(temp); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_unlock; - path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE); - dput(temp); -Printk(("umsdos_link: %s/%s already hidden, path=%s\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name, path)); - - /* finally we can symlink it ... */ - ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK); - -out_unlock: - /* remain locked for the call to notify_change ... */ - if (ret == 0) { - struct iattr newattrs; - - /* Do a real lookup to get the short name dentry */ - temp = umsdos_covered(olddentry->d_parent, - old_info.fake.fname, - old_info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_unlock2; - - /* now resolve the link ... */ - temp = umsdos_solve_hlink(temp); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_unlock2; - - -#ifdef UMSDOS_PARANOIA -if (!UMSDOS_I(oldinode)->i_is_hlink) -printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino); -#endif - temp->d_inode->i_nlink++; -Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n", -olddentry->d_parent->d_name.name, olddentry->d_name.name, -oldinode->i_ino, oldinode->i_nlink)); - newattrs.ia_valid = 0; - ret = umsdos_notify_change_locked(temp, &newattrs); - if (ret == 0) - mark_inode_dirty(temp->d_inode); - dput(temp); -out_unlock2: - if (ret == 0) - mark_inode_dirty(olddentry->d_inode); - } - if (olddir != dir) - up(&olddir->i_sem); - -out_free: - free_page(buffer); -out: - Printk (("umsdos_link %d\n", ret)); - return ret; -} - - -/* - * Add a sub-directory in a directory - */ -/* #Specification: mkdir / Directory already exist in DOS - * We do the same thing as for file creation. - * For all user it is an error. - */ -/* #Specification: mkdir / umsdos directory / create EMD - * When we created a new sub-directory in a UMSDOS - * directory (one with full UMSDOS semantics), we - * create immediately an EMD file in the new - * sub-directory so it inherits UMSDOS semantics. - */ -int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode) -{ - struct dentry *temp; - struct inode *inode; - int ret, err; - struct umsdos_info info; - - ret = umsdos_nevercreat (dir, dentry, -EEXIST); - if (ret) - goto out; - - ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); - if (ret) - goto out; - - info.entry.mode = mode | S_IFDIR; - info.entry.rdev = 0; - info.entry.uid = current->fsuid; - info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - info.entry.ctime = info.entry.atime = info.entry.mtime = get_seconds(); - info.entry.flags = 0; - info.entry.nlink = 1; - ret = umsdos_newentry (dentry->d_parent, &info); - if (ret) - goto out; - - /* lookup the short name dentry */ - temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_remove; - - /* Make sure the short name doesn't exist */ - ret = -EEXIST; - if (temp->d_inode) { -printk("umsdos_mkdir: short name %s/%s exists\n", -dentry->d_parent->d_name.name, info.fake.fname); - goto out_remove_dput; - } - - ret = msdos_mkdir (dir, temp, mode); - if (ret) - goto out_remove_dput; - - /* - * Lock the inode to protect the EMD creation ... - */ - inode = temp->d_inode; - down(&inode->i_sem); - - atomic_inc(&inode->i_count); - d_instantiate(dentry, inode); - - /* N.B. this should have an option to create the EMD ... */ - umsdos_lookup_patch_new(dentry, &info); - - /* - * Create the EMD file, and set up the dir so it is - * promoted to EMD with the EMD file invisible. - * - * N.B. error return if EMD fails? - */ - err = umsdos_make_emd(dentry); - umsdos_setup_dir(dentry); - - up(&inode->i_sem); - dput(temp); - -out: - Printk(("umsdos_mkdir: %s/%s, ret=%d\n", - dentry->d_parent->d_name.name, dentry->d_name.name, ret)); - return ret; - - /* an error occurred ... remove EMD entry. */ -out_remove_dput: - dput(temp); -out_remove: - umsdos_delentry (dentry->d_parent, &info, 1); - goto out; -} - -/* - * Add a new device special file into a directory. - * - * #Specification: Special files / strategy - * Device special file, pipes, etc ... are created like normal - * file in the msdos file system. Of course they remain empty. - * - * One strategy was to create those files only in the EMD file - * since they were not important for MSDOS. The problem with - * that, is that there were not getting inode number allocated. - * The MSDOS filesystems is playing a nice game to fake inode - * number, so why not use it. - * - * The absence of inode number compatible with those allocated - * for ordinary files was causing major trouble with hard link - * in particular and other parts of the kernel I guess. - */ -int UMSDOS_mknod (struct inode *dir, struct dentry *dentry, - int mode, dev_t rdev) -{ - return umsdos_create_any (dir, dentry, mode, rdev, 0); -} - -/* - * Remove a sub-directory. - */ -int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry) -{ - struct dentry *temp; - int ret, err, empty; - struct umsdos_info info; - - ret = umsdos_nevercreat (dir, dentry, -EPERM); - if (ret) - goto out; - - ret = -EBUSY; - if (!d_unhashed(dentry)) - goto out; - - /* check whether the EMD is empty */ - ret = -ENOTEMPTY; - empty = umsdos_isempty (dentry); - - /* Have to remove the EMD file? */ - if (empty == 1) { - struct dentry *demd; - - demd = umsdos_get_emd_dentry(dentry); - if (!IS_ERR(demd)) { - err = -ENOENT; - if (demd->d_inode) - err = msdos_unlink (dentry->d_inode, demd); -Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err)); -#ifdef UMSDOS_PARANOIA -if (err) -printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n", -demd->d_parent->d_name.name, demd->d_name.name, err); -#endif - if (!err) { - d_delete(demd); - ret = 0; - } - dput(demd); - } - } else if (empty == 2) - ret = 0; - if (ret) - goto out; - - umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); - /* Call findentry to complete the mangling */ - umsdos_findentry (dentry->d_parent, &info, 2); - temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out; - /* - * Attempt to remove the msdos name. - */ - ret = msdos_rmdir (dir, temp); - if (ret && ret != -ENOENT) - goto out_dput; - - d_delete(temp); - /* OK so far ... remove the name from the EMD */ - ret = umsdos_delentry (dentry->d_parent, &info, 1); -#ifdef UMSDOS_PARANOIA -if (ret) -printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret); -#endif - - /* dput() temp if we didn't do it above */ -out_dput: - dput(temp); - -out: - Printk (("umsdos_rmdir %d\n", ret)); - return ret; -} - - -/* - * Remove a file from the directory. - * - * #Specification: hard link / deleting a link - * When we delete a file and this file is a link, - * we must subtract 1 from the nlink field of the - * hidden link. - * - * If the count goes to 0, we delete this hidden - * link too. - */ -int UMSDOS_unlink (struct inode *dir, struct dentry *dentry) -{ - struct dentry *temp, *link = NULL; - struct inode *inode; - int ret; - struct umsdos_info info; - -Printk(("UMSDOS_unlink: entering %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name)); - - ret = umsdos_nevercreat (dir, dentry, -EPERM); - if (ret) - goto out; - - ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); - if (ret) - goto out; - - umsdos_lockcreate (dir); - ret = umsdos_findentry (dentry->d_parent, &info, 1); - if (ret) { -printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, ret); - goto out_unlock; - } - -Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname)); - - /* - * Note! If this is a hardlink and the names are aliased, - * the short-name lookup will return the hardlink dentry. - * In order to get the correct (real) inode, we just drop - * the original dentry. - */ - if (info.entry.flags & UMSDOS_HLINK) { - d_drop(dentry); - } - - /* Do a real lookup to get the short name dentry */ - temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); - ret = PTR_ERR(temp); - if (IS_ERR(temp)) - goto out_unlock; - - /* - * Resolve hardlinks now, but defer processing until later. - */ - if (info.entry.flags & UMSDOS_HLINK) { - link = umsdos_solve_hlink(dget(temp)); - } - - /* Delete the EMD entry */ - ret = umsdos_delentry (dentry->d_parent, &info, 0); - if (ret && ret != -ENOENT) { - printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n", - info.entry.name, ret); - goto out_dput; - } - - ret = msdos_unlink(dir, temp); - if (!ret) - d_delete(temp); -#ifdef UMSDOS_PARANOIA -if (ret) -printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n", -temp->d_parent->d_name.name, temp->d_name.name, ret); -#endif - - /* dput() temp if we didn't do it above */ -out_dput: - dput(temp); - -out_unlock: - umsdos_unlockcreate (dir); - - /* - * Now check for deferred handling of a hardlink. - */ - if (!link) - goto out; - - if (IS_ERR(link)) { -printk("umsdos_unlink: failed to resolve %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name); - if (!ret) - ret = PTR_ERR(link); - goto out; - } - -Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n", -link->d_parent->d_name.name, link->d_name.name, ret)); - - /* already have an error? */ - if (ret) - goto out_cleanup; - - /* make sure the link exists ... */ - inode = link->d_inode; - if (!inode) { - printk(KERN_WARNING "umsdos_unlink: hard link not found\n"); - goto out_cleanup; - } - - /* - * If this was the last linked reference, delete it now. - * - * N.B. Deadlock problem? We should be holding the lock - * for the hardlink's parent, but another process might - * be holding that lock waiting for us to finish ... - */ - if (inode->i_nlink <= 1) { - ret = UMSDOS_unlink (link->d_parent->d_inode, link); - if (ret) { - printk(KERN_WARNING - "umsdos_unlink: link removal failed, ret=%d\n", - ret); - } else - d_delete(link); - } else { - struct iattr newattrs; - inode->i_nlink--; - newattrs.ia_valid = 0; - ret = umsdos_notify_change_locked(link, &newattrs); - if (!ret) - mark_inode_dirty(link->d_inode); - } - -out_cleanup: - d_drop(link); - dput(link); - -out: - Printk (("umsdos_unlink %d\n", ret)); - return ret; -} - -/* - * Rename (move) a file. - */ -int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int ret; - - ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST); - if (ret) - return ret; - - /* - * If the target already exists, delete it first. - */ - if (new_dentry->d_inode) { - dget(new_dentry); - if (S_ISDIR(old_dentry->d_inode->i_mode)) - ret = UMSDOS_rmdir (new_dir, new_dentry); - else - ret = UMSDOS_unlink (new_dir, new_dentry); - if (!ret) - d_drop(new_dentry); - dput(new_dentry); - if (ret) - return ret; - } - ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0); - return ret; -} diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c deleted file mode 100644 index 2f32539b1a37..000000000000 --- a/fs/umsdos/rdir.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * linux/fs/umsdos/rdir.c - * - * Written 1994 by Jacques Gelinas - * - * Extended MS-DOS directory pure MS-DOS handling functions - * (For directory without EMD file). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -extern struct dentry *saved_root; -extern struct inode *pseudo_root; -extern struct dentry_operations umsdos_dentry_operations; - -struct RDIR_FILLDIR { - void *dirbuf; - filldir_t filldir; - int real_root; -}; - -static int rdir_filldir ( void *buf, - const char *name, - int name_len, - loff_t offset, - ino_t ino, - unsigned int d_type) -{ - int ret = 0; - struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf; - - if (d->real_root) { - PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n")); - /* real root of a pseudo_rooted partition */ - if (name_len != UMSDOS_PSDROOT_LEN - || memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) { - /* So it is not the /linux directory */ - if (name_len == 2 && name[0] == '.' && name[1] == '.') { - /* Make sure the .. entry points back to the pseudo_root */ - ino = pseudo_root->i_ino; - } - ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN); - } - } else { - /* Any DOS directory */ - ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN); - } - return ret; -} - - -static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir) -{ - struct inode *dir = filp->f_dentry->d_inode; - struct RDIR_FILLDIR bufk; - int ret; - - lock_kernel(); - bufk.filldir = filldir; - bufk.dirbuf = dirbuf; - bufk.real_root = pseudo_root && (dir == saved_root->d_inode); - ret = fat_readdir (filp, &bufk, rdir_filldir); - unlock_kernel(); - return ret; -} - - -/* - * Lookup into a non promoted directory. - * If the result is a directory, make sure we find out if it is - * a promoted one or not (calling umsdos_setup_dir_inode(inode)). - */ -/* #Specification: pseudo root / DOS/.. - * In the real root directory (c:\), the directory .. - * is the pseudo root (c:\linux). - */ -struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) -{ - struct dentry *ret; - - if (saved_root && dir == saved_root->d_inode && !nopseudo && - dentry->d_name.len == UMSDOS_PSDROOT_LEN && - memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) { - /* #Specification: pseudo root / DOS/linux - * Even in the real root directory (c:\), the directory - * /linux won't show - */ - - ret = ERR_PTR(-ENOENT); - goto out; - } - - ret = msdos_lookup (dir, dentry, NULL); - if (ret) { - printk(KERN_WARNING - "umsdos_rlookup_x: %s/%s failed, ret=%ld\n", - dentry->d_parent->d_name.name, dentry->d_name.name, - PTR_ERR(ret)); - goto out; - } - if (dentry->d_inode) { - /* We must install the proper function table - * depending on whether this is an MS-DOS or - * a UMSDOS directory - */ -Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n", -dentry->d_parent->d_name.name, dentry->d_name.name)); -/* only patch if needed (because we get called even for lookup - (not only rlookup) stuff sometimes, like in umsdos_covered() */ - if (UMSDOS_I(dentry->d_inode)->i_patched == 0) - umsdos_patch_dentry_inode(dentry, 0); - - } -out: - /* always install our dentry ops ... */ - dentry->d_op = &umsdos_dentry_operations; - return ret; -} - - -struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry, struct nameidata *nd) -{ - return umsdos_rlookup_x (dir, dentry, 0); -} - - -/* #Specification: dual mode / rmdir in a DOS directory - * In a DOS (not EMD in it) directory, we use a reverse strategy - * compared with a UMSDOS directory. We assume that a subdirectory - * of a DOS directory is also a DOS directory. This is not always - * true (umssync may be used anywhere), but makes sense. - * - * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY - * then we check if it is a Umsdos directory. We check if it is - * really empty (only . .. and --linux-.--- in it). If it is true - * we remove the EMD and do a msdos_rmdir() again. - * - * In a Umsdos directory, we assume all subdirectories are also - * Umsdos directories, so we check the EMD file first. - */ -/* #Specification: pseudo root / rmdir /DOS - * The pseudo sub-directory /DOS can't be removed! - * This is done even if the pseudo root is not a Umsdos - * directory anymore (very unlikely), but an accident (under - * MS-DOS) is always possible. - * - * EPERM is returned. - */ -static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry) -{ - int ret, empty; - - ret = -EPERM; - if (umsdos_is_pseudodos (dir, dentry)) - goto out; - - ret = -EBUSY; - if (!d_unhashed(dentry)) - goto out; - - ret = msdos_rmdir (dir, dentry); - if (ret != -ENOTEMPTY) - goto out; - - empty = umsdos_isempty (dentry); - if (empty == 1) { - struct dentry *demd; - /* We have to remove the EMD file. */ - demd = umsdos_get_emd_dentry(dentry); - ret = PTR_ERR(demd); - if (!IS_ERR(demd)) { - ret = 0; - if (demd->d_inode) - ret = msdos_unlink (dentry->d_inode, demd); - if (!ret) - d_delete(demd); - dput(demd); - } - } - if (ret) - goto out; - - /* now retry the original ... */ - ret = msdos_rmdir (dir, dentry); - -out: - return ret; -} - -/* #Specification: dual mode / introduction - * One goal of UMSDOS is to allow a practical and simple coexistence - * between MS-DOS and Linux in a single partition. Using the EMD file - * in each directory, UMSDOS adds Unix semantics and capabilities to - * a normal DOS filesystem. To help and simplify coexistence, here is - * the logic related to the EMD file. - * - * If it is missing, then the directory is managed by the MS-DOS driver. - * The names are limited to DOS limits (8.3). No links, no device special - * and pipe and so on. - * - * If it is there, it is the directory. If it is there but empty, then - * the directory looks empty. The utility umssync allows synchronisation - * of the real DOS directory and the EMD. - * - * Whenever umssync is applied to a directory without EMD, one is - * created on the fly. The directory is promoted to full Unix semantics. - * Of course, the ls command will show exactly the same content as before - * the umssync session. - * - * It is believed that the user/admin will promote directories to Unix - * semantics as needed. - * - * The strategy to implement this is to use two function table (struct - * inode_operations). One for true UMSDOS directory and one for directory - * with missing EMD. - * - * Functions related to the DOS semantic (but aware of UMSDOS) generally - * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate - * from the one with full UMSDOS semantics. - */ -struct file_operations umsdos_rdir_operations = -{ - .read = generic_read_dir, - .readdir = UMSDOS_rreaddir, - .ioctl = UMSDOS_ioctl_dir, -}; - -struct inode_operations umsdos_rdir_inode_operations = -{ - .create = msdos_create, - .lookup = UMSDOS_rlookup, - .unlink = msdos_unlink, - .mkdir = msdos_mkdir, - .rmdir = UMSDOS_rrmdir, - .rename = msdos_rename, - .setattr = UMSDOS_notify_change, -}; diff --git a/fs/umsdos/specs b/fs/umsdos/specs deleted file mode 100644 index 0f7d68c0aef6..000000000000 --- a/fs/umsdos/specs +++ /dev/null @@ -1,289 +0,0 @@ -/* #Specification: umsdos / readdir - * umsdos_readdir() should fill a struct dirent with - * an inode number. The cheap way to get it is to - * do a lookup in the MSDOS directory for each - * entry processed by the readdir() function. - * This is not very efficient, but very simple. The - * other way around is to maintain a copy of the inode - * number in the EMD file. This is a problem because - * this has to be maintained in sync using tricks. - * Remember that MSDOS (the OS) does not update the - * modification time (mtime) of a directory. There is - * no easy way to tell that a directory was modified - * during a DOS session and synchronise the EMD file. - */ - /* #Specification: readdir / . and .. - * The msdos filesystem manages the . and .. entry properly - * so the EMD file won't hold any info about it. - * - * In readdir, we assume that for the root directory - * the read position will be 0 for ".", 1 for "..". For - * a non root directory, the read position will be 0 for "." - * and 32 for "..". - */ - /* - * This is a trick used by the msdos file system (fs/msdos/dir.c) - * to manage . and .. for the root directory of a file system. - * Since there is no such entry in the root, fs/msdos/dir.c - * use the following: - * - * if f_pos == 0, return ".". - * if f_pos == 1, return "..". - * - * So let msdos handle it - * - * Since umsdos entries are much larger, we share the same f_pos. - * if f_pos is 0 or 1 or 32, we are clearly looking at . and - * .. - * - * As soon as we get f_pos == 2 or f_pos == 64, then back to - * 0, but this time we are reading the EMD file. - * - * Well, not so true. The problem, is that UMSDOS_REC_SIZE is - * also 64, so as soon as we read the first record in the - * EMD, we are back at offset 64. So we set the offset - * to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the - * .. entry from msdos. - * - * Now (linux 1.3), umsdos_readdir can read more than one - * entry even if we limit (umsdos_dir_once) to only one: - * It skips over hidden file. So we switch to - * UMSDOS_SPECIAL_DIRFPOS as soon as we have read successfully - * the .. entry. - */ - /* #Specification: umsdos / lookup / inode info - * After successfully reading an inode from the MSDOS - * filesystem, we use the EMD file to complete it. - * We update the following field. - * - * uid, gid, atime, ctime, mtime, mode. - * - * We rely on MSDOS for mtime. If the file - * was modified during an MSDOS session, at least - * mtime will be meaningful. We do this only for regular - * file. - * - * We don't rely on MS-DOS for mtime for directories - * because the MS-DOS date on a directory is its - * creation time (strange MSDOS behavior) which - * corresponds to none of the three Unix time stamps. - */ - /* #Specification: umsdos / conversion mode - * The msdos filesystem can do some inline conversion - * of the data of a file. It can translate silently - * from the MS-DOS text file format to the Unix one - * (CRLF -> LF) while reading, and the reverse - * while writing. This is activated using the mount - * option conv=.... - * - * This is not useful for Linux files in a promoted - * directory. It can even be harmful. For this - * reason, the binary (no conversion) mode is - * always activated. - */ - /* #Specification: umsdos / conversion mode / todo - * A flag could be added to file and directories - * forcing an automatic conversion mode (as - * done with the msdos filesystem). - * - * This flag could be setup on a directory basis - * (instead of file) and all files in it would - * logically inherit it. If the conversion mode - * is active (conv=) then the i_binary flag would - * be left untouched in those directories. - * - * It was proposed that the sticky bit be used to set - * this. A problem with that is that new files would - * be written incorrectly. The other problem is that - * the sticky bit has a meaning for directories. So - * another bit should be used (there is some space - * in the EMD file for it) and a special utility - * would be used to assign the flag to a directory). - * I don't think it is useful to assign this flag - * on a single file. - */ - * #Specification: weakness / rename - * There is a case where UMSDOS rename has a different behavior - * than a normal Unix file system. Renaming an open file across - * directory boundary does not work. Renaming an open file within - * a directory does work, however. - * - * The problem may is in Linux VFS driver for msdos. - * I believe this is not a bug but a design feature, because - * an inode number represents some sort of directory address - * in the MSDOS directory structure, so moving the file into - * another directory does not preserve the inode number. - */ -/* #Specification: rename / new name exist - * If the destination name already exists, it will - * silently be removed. EXT2 does it this way - * and this is the spec of SunOS. So does UMSDOS. - * - * If the destination is an empty directory it will - * also be removed. - */ -/* #Specification: rename / new name exist / possible flaw - * The code to handle the deletion of the target (file - * and directory) use to be in umsdos_rename_f, surrounded - * by proper directory locking. This was ensuring that only - * one process could achieve a rename (modification) operation - * in the source and destination directory. This was also - * ensuring the operation was "atomic". - * - * This has been changed because this was creating a - * stack overflow (the stack is only 4 kB) in the kernel. To avoid - * the code doing the deletion of the target (if exist) has - * been moved to a upper layer. umsdos_rename_f is tried - * once and if it fails with EEXIST, the target is removed - * and umsdos_rename_f is done again. - * - * This makes the code cleaner and may solve a - * deadlock problem one tester was experiencing. - * - * The point is to mention that possibly, the semantic of - * "rename" may be wrong. Anyone dare to check that :-) - * Be aware that IF it is wrong, to produce the problem you - * will need two process trying to rename a file to the - * same target at the same time. Again, I am not sure it - * is a problem at all. - */ - -/* #Specification: hard link / strategy - * Hard links are difficult to implement on top of an MS-DOS FAT file - * system. Unlike Unix file systems, there are no inodes. A directory - * entry holds the functionality of the inode and the entry. - * - * We will used the same strategy as a normal Unix file system - * (with inodes) except we will do it symbolically (using paths). - * - * Because anything can happen during a DOS session (defragment, - * directory sorting, etc.), we can't rely on an MS-DOS pseudo - * inode number to record the link. For this reason, the link - * will be done using hidden symbolic links. The following - * scenario illustrates how it works. - * - * Given a file /foo/file - * - * # - * ln /foo/file /tmp/file2 - * - * become internally - * - * mv /foo/file /foo/-LINK1 - * ln -s /foo/-LINK1 /foo/file - * ln -s /foo/-LINK1 /tmp/file2 - * # - * - * Using this strategy, we can operate on /foo/file or /foo/file2. - * We can remove one and keep the other, like a normal Unix hard link. - * We can rename /foo/file or /tmp/file2 independently. - * - * The entry -LINK1 will be hidden. It will hold a link count. - * When all link are erased, the hidden file is erased too. - */ - -/* #Specification: weakness / hard link - * The strategy for hard link introduces a side effect that - * may or may not be acceptable. Here is the sequence - * - * # - * mkdir subdir1 - * touch subdir1/file - * mkdir subdir2 - * ln subdir1/file subdir2/file - * rm subdir1/file - * rmdir subdir1 - * rmdir: subdir1: Directory not empty - * # - * - * This happen because there is an invisible file (--link) in - * subdir1 which is referenced by subdir2/file. - * - * Any idea ? - */ -/* #Specification: weakness / hard link / rename directory - * Another weakness of hard link come from the fact that - * it is based on hidden symbolic links. Here is an example. - * - * # - * mkdir /subdir1 - * touch /subdir1/file - * mkdir /subdir2 - * ln /subdir1/file subdir2/file - * mv /subdir1 subdir3 - * ls -l /subdir2/file - * # - * - * Since /subdir2/file is a hidden symbolic link - * to /subdir1/..hlinkNNN, accessing it will fail since - * /subdir1 does not exist anymore (has been renamed). - */ -/* #Specification: hard link / directory - * A hard link can't be made on a directory. EPERM is returned - * in this case. - */ -/* #Specification: hard link / first hard link - * The first time a hard link is done on a file, this - * file must be renamed and hidden. Then an internal - * symbolic link must be done on the hidden file. - * - * The second link is done after on this hidden file. - * - * It is expected that the Linux MSDOS file system - * keeps the same pseudo inode when a rename operation - * is done on a file in the same directory. - */ -/* #Specification: function name / convention - * A simple convention for function names has been used in - * the UMSDOS filesystem. First, all functions use the prefix - * umsdos_ to avoid name clashes with other parts of the kernel. - * - * Standard VFS entry points use the prefix UMSDOS (upper case) - * so it's easier to tell them apart. - * N.B. (FIXME) PTW, the order and contents of this struct changed. - */ - -/* #Specification: mount / options - * Umsdos run on top of msdos. Currently, it supports no - * mount option, but happily pass all option received to - * the msdos driver. I am not sure if all msdos mount option - * make sense with Umsdos. Here are at least those who - * are useful. - * uid= - * gid= - * - * These options affect the operation of umsdos in directories - * which do not have an EMD file. They behave like normal - * msdos directory, with all limitation of msdos. - */ - -/* #Specification: pseudo root / mount - * When a umsdos fs is mounted, a special handling is done - * if it is the root partition. We check for the presence - * of the file /linux/etc/init or /linux/etc/rc or - * /linux/sbin/init. If one is there, we do a chroot("/linux"). - * - * We check both because (see init/main.c) the kernel - * try to exec init at different place and if it fails - * it tries /bin/sh /etc/rc. To be consistent with - * init/main.c, many more test would have to be done - * to locate init. Any complain ? - * - * The chroot is done manually in init/main.c but the - * info (the inode) is located at mount time and store - * in a global variable (pseudo_root) which is used at - * different place in the umsdos driver. There is no - * need to store this variable elsewhere because it - * will always be one, not one per mount. - * - * This feature allows the installation - * of a linux system within a DOS system in a subdirectory. - * - * A user may install its linux stuff in c:\linux - * avoiding any clash with existing DOS file and subdirectory. - * When linux boots, it hides this fact, showing a normal - * root directory with /etc /bin /tmp ... - * - * The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h - * in the macro UMSDOS_PSDROOT_NAME. - */ diff --git a/include/linux/umsdos_fs.h b/include/linux/umsdos_fs.h deleted file mode 100644 index 67c25693db66..000000000000 --- a/include/linux/umsdos_fs.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef LINUX_UMSDOS_FS_H -#define LINUX_UMSDOS_FS_H - - -/*#define UMS_DEBUG 1 // define for check_* functions */ -/*#define UMSDOS_DEBUG 1*/ -#define UMSDOS_PARANOIA 1 - -#define UMSDOS_VERSION 0 -#define UMSDOS_RELEASE 4 - -#define UMSDOS_ROOT_INO 1 - -/* This is the file acting as a directory extension */ -#define UMSDOS_EMD_FILE "--linux-.---" -#define UMSDOS_EMD_NAMELEN 12 -#define UMSDOS_PSDROOT_NAME "linux" -#define UMSDOS_PSDROOT_LEN 5 - -#ifndef _LINUX_TYPES_H -#include -#endif -#ifndef _LINUX_LIMITS_H -#include -#endif -#ifndef _LINUX_DIRENT_H -#include -#endif -#ifndef _LINUX_IOCTL_H -#include -#endif - - -#ifdef __KERNEL__ -/* #Specification: convention / PRINTK Printk and printk - * Here is the convention for the use of printk inside fs/umsdos - * - * printk carry important message (error or status). - * Printk is for debugging (it is a macro defined at the beginning of - * most source. - * PRINTK is a nulled Printk macro. - * - * This convention makes the source easier to read, and Printk easier - * to shut off. - */ -# define PRINTK(x) -# ifdef UMSDOS_DEBUG -# define Printk(x) printk x -# else -# define Printk(x) -# endif -#endif /* __KERNEL__ */ - - -struct umsdos_fake_info { - char fname[13]; - int len; -}; - -#define UMSDOS_MAXNAME 220 -/* This structure is 256 bytes large, depending on the name, only part */ -/* of it is written to disk */ -/* nice though it would be, I can't change this and preserve backward compatibility */ -struct umsdos_dirent { - unsigned char name_len; /* if == 0, then this entry is not used */ - unsigned char flags; /* UMSDOS_xxxx */ - unsigned short nlink; /* How many hard links point to this entry */ - __kernel_uid_t uid; /* Owner user id */ - __kernel_gid_t gid; /* Group id */ - time_t atime; /* Access time */ - time_t mtime; /* Last modification time */ - time_t ctime; /* Creation time */ - unsigned short rdev; /* major and minor of a device special file */ - umode_t mode; /* Standard UNIX permissions bits + type of */ - char spare[12]; /* unused bytes for future extensions */ - /* file, see linux/stat.h */ - char name[UMSDOS_MAXNAME]; /* Not '\0' terminated */ - /* but '\0' padded, so it will allow */ - /* for adding news fields in this record */ - /* by reducing the size of name[] */ -}; - -#define UMSDOS_HIDDEN 1 /* Never show this entry in directory search */ -#define UMSDOS_HLINK 2 /* It is a (pseudo) hard link */ - -/* #Specification: EMD file / record size - * Entry are 64 bytes wide in the EMD file. It allows for a 30 characters - * name. If a name is longer, contiguous entries are allocated. So a - * umsdos_dirent may span multiple records. - */ - -#define UMSDOS_REC_SIZE 64 - -/* Translation between MSDOS name and UMSDOS name */ - -struct umsdos_info { - int msdos_reject; /* Tell if the file name is invalid for MSDOS */ - /* See umsdos_parse */ - struct umsdos_fake_info fake; - struct umsdos_dirent entry; - off_t f_pos; /* offset of the entry in the EMD file - * or offset where the entry may be store - * if it is a new entry - */ - int recsize; /* Record size needed to store entry */ -}; - -/* Definitions for ioctl (number randomly chosen) - * The next ioctl commands operate only on the DOS directory - * The file umsdos_progs/umsdosio.c contain a string table - * based on the order of those definition. Keep it in sync - */ -#define UMSDOS_READDIR_DOS _IO(0x04,210) /* Do a readdir of the DOS directory */ -#define UMSDOS_UNLINK_DOS _IO(0x04,211) /* Erase in the DOS directory only */ -#define UMSDOS_RMDIR_DOS _IO(0x04,212) /* rmdir in the DOS directory only */ -#define UMSDOS_STAT_DOS _IO(0x04,213) /* Get info about a file */ - -/* The next ioctl commands operate only on the EMD file */ -#define UMSDOS_CREAT_EMD _IO(0x04,214) /* Create a file */ -#define UMSDOS_UNLINK_EMD _IO(0x04,215) /* unlink (rmdir) a file */ -#define UMSDOS_READDIR_EMD _IO(0x04,216) /* read the EMD file only. */ -#define UMSDOS_GETVERSION _IO(0x04,217) /* Get the release number of UMSDOS */ -#define UMSDOS_INIT_EMD _IO(0x04,218) /* Create the EMD file if not there */ -#define UMSDOS_DOS_SETUP _IO(0x04,219) /* Set the defaults of the MS-DOS driver. */ - -#define UMSDOS_RENAME_DOS _IO(0x04,220) /* rename a file/directory in the DOS - * directory only */ -struct umsdos_ioctl { - struct dirent dos_dirent; - struct umsdos_dirent umsdos_dirent; - /* The following structure is used to exchange some data with - * utilities (umsdos_progs/util/umsdosio.c). The first releases - * were using struct stat from "sys/stat.h". This was causing - * some problem for cross compilation of the kernel. - * Since I am not really using the structure stat, but only - * some fields of it, I have decided to replicate the structure - * here for compatibility with the binaries out there. - * FIXME PTW 1998, this has probably changed - */ - - struct { - unsigned long st_dev; - ino_t st_ino; /* used */ - umode_t st_mode; /* used */ - nlink_t st_nlink; - __kernel_uid_t st_uid; - __kernel_gid_t st_gid; - unsigned long st_rdev; - off_t st_size; /* used */ - unsigned long st_blksize; - unsigned long st_blocks; - time_t st_atime; /* used */ - unsigned long __unused1; - time_t st_mtime; /* used */ - unsigned long __unused2; - time_t st_ctime; /* used */ - unsigned long __unused3; - uid_t st_uid32; - gid_t st_gid32; - } stat; - char version, release; -}; - -/* Different macros to access struct umsdos_dirent */ -#define EDM_ENTRY_ISUSED(e) ((e)->name_len!=0) - -#ifdef __KERNEL__ - -#ifndef LINUX_FS_H -#include -#endif - -extern struct inode_operations umsdos_dir_inode_operations; -extern struct inode_operations umsdos_rdir_inode_operations; -extern struct file_operations umsdos_dir_operations; -extern struct file_operations umsdos_rdir_operations; - -#include - -#endif /* __KERNEL__ */ - -#endif diff --git a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p deleted file mode 100644 index 1c284c5a7aec..000000000000 --- a/include/linux/umsdos_fs.p +++ /dev/null @@ -1,100 +0,0 @@ -/* check.c 23/01/95 03.38.30 */ -void check_page_tables (void); - -/* dir.c 22/06/95 00.22.12 */ -int dummy_dir_read ( struct file *filp, - char *buf, - size_t size, - loff_t *count); -char * umsdos_d_path(struct dentry *, char *, int); -void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *); -int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry); -struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo); -struct dentry *UMSDOS_lookup(struct inode *, struct dentry *, struct nameidata *); -struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int); -struct dentry *umsdos_covered(struct dentry *, char *, int); - -struct dentry *umsdos_solve_hlink (struct dentry *hlink); - -/* emd.c 22/06/95 00.22.04 */ -struct dentry *umsdos_get_emd_dentry(struct dentry *); -int umsdos_have_emd(struct dentry *); -int umsdos_make_emd(struct dentry *); -int umsdos_emd_dir_readentry (struct dentry *, loff_t *, struct umsdos_dirent *); -int umsdos_newentry (struct dentry *, struct umsdos_info *); -int umsdos_newhidden (struct dentry *, struct umsdos_info *); -int umsdos_delentry (struct dentry *, struct umsdos_info *, int); -int umsdos_findentry (struct dentry *, struct umsdos_info *, int); -int umsdos_isempty (struct dentry *); -int umsdos_writeentry (struct dentry *, struct umsdos_info *, int); - -/* file.c 25/01/95 02.25.38 */ - -/* inode.c 12/06/95 09.49.40 */ -void fill_new_filp (struct file *filp, struct dentry *dentry); -void UMSDOS_read_inode (struct inode *); -void UMSDOS_write_inode (struct inode *, int); -int UMSDOS_notify_change (struct dentry *, struct iattr *attr); -int umsdos_notify_change_locked(struct dentry *, struct iattr *attr); -void UMSDOS_put_inode (struct inode *); -int UMSDOS_statfs (struct super_block *, struct statfs *); -struct super_block *UMSDOS_read_super (struct super_block *, void *, int); -void UMSDOS_put_super (struct super_block *); - -void umsdos_setup_dir(struct dentry *); -void umsdos_set_dirinfo_new(struct dentry *, off_t); -void umsdos_patch_dentry_inode (struct dentry *, off_t); -int umsdos_get_dirowner (struct inode *inode, struct inode **result); - -/* ioctl.c 22/06/95 00.22.08 */ -int UMSDOS_ioctl_dir (struct inode *dir, - struct file *filp, - unsigned int cmd, - unsigned long data); - -/* mangle.c 25/01/95 02.25.38 */ -void umsdos_manglename (struct umsdos_info *info); -int umsdos_evalrecsize (int len); -int umsdos_parse (const char *name,int len, struct umsdos_info *info); - -/* namei.c 25/01/95 02.25.38 */ -void umsdos_lockcreate (struct inode *dir); -void umsdos_startlookup (struct inode *dir); -void umsdos_unlockcreate (struct inode *dir); -void umsdos_endlookup (struct inode *dir); - -int umsdos_readlink_x ( struct dentry *dentry, - char *buffer, - int bufsiz); -int UMSDOS_symlink (struct inode *dir, - struct dentry *dentry, - const char *symname); -int UMSDOS_link (struct dentry *olddentry, - struct inode *dir, - struct dentry *dentry); -int UMSDOS_create (struct inode *dir, - struct dentry *dentry, - int mode); - -int UMSDOS_mkdir (struct inode *dir, - struct dentry *dentry, - int mode); -int UMSDOS_mknod (struct inode *dir, - struct dentry *dentry, - int mode, - dev_t rdev); -int UMSDOS_rmdir (struct inode *dir,struct dentry *dentry); -int UMSDOS_unlink (struct inode *dir, struct dentry *dentry); -int UMSDOS_rename (struct inode *old_dir, - struct dentry *old_dentry, - struct inode *new_dir, - struct dentry *new_dentry); - -/* rdir.c 22/03/95 03.31.42 */ -struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo); -struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd); - -static inline struct umsdos_inode_info *UMSDOS_I(struct inode *inode) -{ - return &inode->u.umsdos_i; -} diff --git a/include/linux/umsdos_fs_i.h b/include/linux/umsdos_fs_i.h deleted file mode 100644 index f4c992b44cd2..000000000000 --- a/include/linux/umsdos_fs_i.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef UMSDOS_FS_I_H -#define UMSDOS_FS_I_H - -#ifndef _LINUX_TYPES_H -#include -#endif - -#include -#include - -/* #Specification: strategy / in memory inode - * Here is the information specific to the inode of the UMSDOS file - * system. This information is added to the end of the standard struct - * inode. Each file system has its own extension to struct inode, - * so do the umsdos file system. - * - * The strategy is to have the umsdos_inode_info as a superset of - * the msdos_inode_info, since most of the time the job is done - * by the msdos fs code. - * - * So we duplicate the msdos_inode_info, and add our own info at the - * end. - * - * The offset in this EMD file of the entry: pos - * - * For directory, we have dir_locking_info to help synchronise - * file creation and file lookup. See also msdos_fs_i.h for more - * information about msdos_inode_info. - * - * Special file and fifo do have an inode which correspond to an - * empty MSDOS file. - * - * symlink are processed mostly like regular file. The content is the - * link. - * - * The UMSDOS specific extension is placed after the union. - */ - -struct dir_locking_info { - wait_queue_head_t p; - short int looking; /* How many process doing a lookup */ - short int creating; /* Is there any creation going on here - * Only one at a time, although one - * may recursively lock, so it is a counter - */ - long pid; /* pid of the process owning the creation - * lock */ -}; - -struct umsdos_inode_info { - struct msdos_inode_info msdos_info; - struct dir_locking_info dir_info; - int i_patched; /* Inode has been patched */ - int i_is_hlink; /* Resolved hardlink inode? */ - off_t pos; /* Entry offset in the emd_owner file */ -}; - -#endif -- cgit v1.2.3 From eefe1116eb1798bfc2e92dcbc190df0392197bd9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 10 Jan 2005 17:22:40 -0800 Subject: [PATCH] drivers/char/: misc cleanups below are as requested my drivers/char/ cleanups in one big patch for better merging. Each of the patches included was already sent three times without any objections to linux-kernel. The n_tty.c patch is Approved-by: Alan Cox The patch below makes changes under drivers/char/ including the following: - make needlessly global code static - remove completely unused code Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/esp.c | 2 +- drivers/char/genrtc.c | 2 +- drivers/char/ip2/fip_firm.h | 2 +- drivers/char/ip2/i2cmd.c | 59 +------- drivers/char/ip2/i2cmd.h | 17 --- drivers/char/ip2/i2lib.c | 2 +- drivers/char/ip2main.c | 5 +- drivers/char/keyboard.c | 20 +-- drivers/char/lp.c | 4 +- drivers/char/n_tty.c | 4 +- drivers/char/pcmcia/synclink_cs.c | 24 +-- drivers/char/pty.c | 2 +- drivers/char/synclink.c | 311 ++++++++++++++++++-------------------- drivers/char/tipar.c | 4 +- drivers/char/toshiba.c | 2 +- drivers/char/tty_io.c | 28 +--- drivers/char/tty_ioctl.c | 2 +- include/linux/lp.h | 6 - 18 files changed, 187 insertions(+), 309 deletions(-) (limited to 'include') diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 62f8e3087fe6..fb681990a84d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -2401,7 +2401,7 @@ static struct tty_operations esp_ops = { /* * The serial driver boot-time initialization code! */ -int __init espserial_init(void) +static int __init espserial_init(void) { int i, offset; struct esp_struct * info; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index fc02f72f013b..d3a2bc36129b 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -83,7 +83,7 @@ static unsigned char days_in_mo[] = static int irq_active; #ifdef CONFIG_GEN_RTC_X -struct work_struct genrtc_task; +static struct work_struct genrtc_task; static struct timer_list timer_task; static unsigned int oldsecs; diff --git a/drivers/char/ip2/fip_firm.h b/drivers/char/ip2/fip_firm.h index f118123ea912..4c525fa4929f 100644 --- a/drivers/char/ip2/fip_firm.h +++ b/drivers/char/ip2/fip_firm.h @@ -1,7 +1,7 @@ /* fip_firm.h - Intelliport II loadware */ /* -31232 bytes read from ff.lod */ -unsigned char fip_firm[] __initdata = { +static unsigned char fip_firm[] __initdata = { 0x3C,0x42,0x37,0x18,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x57,0x65,0x64,0x20,0x44,0x65,0x63,0x20,0x30,0x31,0x20,0x31,0x32,0x3A,0x32,0x34, 0x3A,0x33,0x30,0x20,0x31,0x39,0x39,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c index 77fd8543efc3..fd299d6c42ac 100644 --- a/drivers/char/ip2/i2cmd.c +++ b/drivers/char/ip2/i2cmd.c @@ -88,7 +88,7 @@ static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE //static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET // Back to normal -static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ +//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ //static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON //static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME @@ -103,7 +103,7 @@ static UCHAR ct47[] = { 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS //static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB //static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB //static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET -static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP +//static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1 static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2 static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE @@ -151,40 +151,6 @@ static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW //* Code * //******** -//****************************************************************************** -// Function: i2cmdSetSeq(type, size, string) -// Parameters: type - sequence number -// size - length of sequence -// string - substitution string -// -// Returns: Pointer to command structure -// -// Description: -// -// This routine sets the parameters of command 38 Define Hot Key sequence (alias -// "special receive sequence"). Returns a pointer to the structure. Endeavours -// to be bullet-proof in that the sequence number is forced in range, and any -// out-of-range sizes are forced to zero. -//****************************************************************************** -cmdSyntaxPtr -i2cmdSetSeq(unsigned char type, unsigned char size, unsigned char *string) -{ - cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct38; - unsigned char *pc; - - pCM->cmd[1] = ((type > 0xf) ? 0xf : type); // Sequence number - size = ((size > 0x8) ? 0 : size); // size - pCM->cmd[2] = size; - pCM->length = 3 + size; // UPDATES THE LENGTH! - - pc = &(pCM->cmd[3]); - - while(size--) { - *pc++ = *string++; - } - return pCM; -} - //****************************************************************************** // Function: i2cmdUnixFlags(iflag, cflag, lflag) // Parameters: Unix tty flags @@ -210,27 +176,6 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) return pCM; } -//****************************************************************************** -// Function: i2cmdBaudRemap(dest,src) -// Parameters: ? -// -// Returns: Pointer to command structure -// -// Description: -// -// This routine sets the parameters of command 53 and returns a pointer to the -// appropriate structure. -//****************************************************************************** -cmdSyntaxPtr -i2cmdBaudRemap(unsigned char dest, unsigned char src) -{ - cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct53; - - pCM->cmd[1] = dest; - pCM->cmd[2] = src; - return pCM; -} - //****************************************************************************** // Function: i2cmdBaudDef(which, rate) // Parameters: ? diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h index 83475167f491..c41728a85710 100644 --- a/drivers/char/ip2/i2cmd.h +++ b/drivers/char/ip2/i2cmd.h @@ -71,9 +71,7 @@ typedef struct _cmdSyntax // there is more than one parameter to assign, we must use a function rather // than a macro (used usually). // -extern cmdSyntaxPtr i2cmdSetSeq(UCHAR seqno, UCHAR size, UCHAR *string); extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag); -extern cmdSyntaxPtr i2cmdBaudRemap(UCHAR dest, UCHAR src); extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate); // Declarations for the global arrays used to bear the commands and their @@ -397,14 +395,6 @@ static UCHAR cc02[]; // library code in response to data movement and shouldn't ever be sent by the // user code. See i2pack.h and the body of i2lib.c for details. -// COMMAND 38: Define the hot-key sequence -// seqno: sequence number 0-15 -// size: number of characters in sequence (1-8) -// string: pointer to the characters -// (if size == 0, "undefines" this sequence -// -#define CMD_SET_SEQ(seqno,size,string) i2cmdSetSeq(seqno,size,string) - // Enable on-board post-processing, using options given in oflag argument. // Formerly, this command was automatically preceded by a CMD_OPOST_OFF command // because the loadware does not permit sending back-to-back CMD_OPOST_ON @@ -458,13 +448,6 @@ static UCHAR cc02[]; #define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control #define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table -// COMMAND 53: Remap baud rate table -// dest = index of table entry to be changed -// src = index value to substitute. -// at default mapping table is f(x) = x -// -#define CMD_BAUD_REMAP(dest,src) i2cmdBaudRemap(dest,src) - // COMMAND 54: Define custom rate #1 // rate = (short) 1/10 of the desired baud rate // diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index a886e954cae9..82c5f30375ac 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c @@ -141,7 +141,7 @@ fatality(i2eBordStrPtr pB ) //* Code * //******** -inline int +static inline int i2Validate ( i2ChanStrPtr pCh ) { //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 3d3ae6856bbd..fca9a978fb73 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -138,7 +138,7 @@ #include static int ip2_read_procmem(char *, char **, off_t, int); -int ip2_read_proc(char *, char **, off_t, int, int *, void * ); +static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); /********************/ /* Type Definitions */ @@ -202,7 +202,6 @@ static void do_status(void *p); static void ip2_wait_until_sent(PTTY,int); static void set_params (i2ChanStrPtr, struct termios *); -static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *); static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); @@ -3097,7 +3096,7 @@ ip2_read_procmem(char *buf, char **start, off_t offset, int len) * different sources including ip2mkdev.c and a couple of other drivers. * The bugs are all mine. :-) =mhw= */ -int ip2_read_proc(char *page, char **start, off_t off, +static int ip2_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int i, j, box; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7c943edc7dcc..fae2ab6d9dc3 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -330,7 +330,7 @@ static void applkey(struct vc_data *vc, int key, char mode) * in utf-8 already. UTF-8 is defined for words of up to 31 bits, * but we need only 16 bits here */ -void to_utf8(struct vc_data *vc, ushort c) +static void to_utf8(struct vc_data *vc, ushort c) { if (c < 0x80) /* 0******* */ @@ -392,7 +392,7 @@ void compute_shiftstate(void) * Otherwise, conclude that DIACR was not combining after all, * queue it and return CH. */ -unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) +static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch) { int d = diacr; int i; @@ -853,18 +853,6 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) set_leds(); } -void register_leds(struct kbd_struct *kbd, unsigned int led, - unsigned int *addr, unsigned int mask) -{ - if (led < 3) { - ledptrs[led].addr = addr; - ledptrs[led].mask = mask; - ledptrs[led].valid = 1; - kbd->ledmode = LED_SHOW_MEM; - } else - kbd->ledmode = LED_SHOW_FLAGS; -} - static inline unsigned char getleds(void) { struct kbd_struct *kbd = kbd_table + fg_console; @@ -925,7 +913,7 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); /* * This allows a newly plugged keyboard to pick the LED state. */ -void kbd_refresh_leds(struct input_handle *handle) +static void kbd_refresh_leds(struct input_handle *handle) { unsigned char leds = ledstate; @@ -1027,7 +1015,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u } #endif -void kbd_rawcode(unsigned char data) +static void kbd_rawcode(unsigned char data) { struct vc_data *vc = vc_cons[fg_console].d; kbd = kbd_table + fg_console; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 093f79828fca..92a54cb659d6 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -142,7 +142,7 @@ /* ROUND_UP macro from fs/select.c */ #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) -struct lp_struct lp_table[LP_NO]; +static struct lp_struct lp_table[LP_NO]; static unsigned int lp_count = 0; static struct class_simple *lp_class; @@ -867,7 +867,7 @@ static struct parport_driver lp_driver = { .detach = lp_detach, }; -int __init lp_init (void) +static int __init lp_init (void) { int i, err = 0; diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index a29dffd9408e..4280394442f7 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -152,7 +152,7 @@ static void reset_buffer_flags(struct tty_struct *tty) * lock_kernel() still. */ -void n_tty_flush_buffer(struct tty_struct * tty) +static void n_tty_flush_buffer(struct tty_struct * tty) { /* clear everything and unthrottle the driver */ reset_buffer_flags(tty); @@ -174,7 +174,7 @@ void n_tty_flush_buffer(struct tty_struct * tty) * at this instant in time. */ -ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) +static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; ssize_t n = 0; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index e331fc0ce3c5..234af616f220 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -923,7 +923,7 @@ static void tx_release(struct tty_struct *tty) /* Return next bottom half action to perform. * or 0 if nothing to do. */ -int bh_action(MGSLPC_INFO *info) +static int bh_action(MGSLPC_INFO *info) { unsigned long flags; int rc = 0; @@ -1017,7 +1017,7 @@ void bh_status(MGSLPC_INFO *info) } /* eom: non-zero = end of frame */ -void rx_ready_hdlc(MGSLPC_INFO *info, int eom) +static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) { unsigned char data[2]; unsigned char fifo_count, read_count, i; @@ -1079,7 +1079,7 @@ void rx_ready_hdlc(MGSLPC_INFO *info, int eom) issue_command(info, CHA, CMD_RXFIFO); } -void rx_ready_async(MGSLPC_INFO *info, int tcd) +static void rx_ready_async(MGSLPC_INFO *info, int tcd) { unsigned char data, status; int fifo_count; @@ -1153,7 +1153,7 @@ void rx_ready_async(MGSLPC_INFO *info, int tcd) } -void tx_done(MGSLPC_INFO *info) +static void tx_done(MGSLPC_INFO *info) { if (!info->tx_active) return; @@ -1190,7 +1190,7 @@ void tx_done(MGSLPC_INFO *info) } } -void tx_ready(MGSLPC_INFO *info) +static void tx_ready(MGSLPC_INFO *info) { unsigned char fifo_count = 32; int c; @@ -1239,7 +1239,7 @@ void tx_ready(MGSLPC_INFO *info) } } -void cts_change(MGSLPC_INFO *info) +static void cts_change(MGSLPC_INFO *info) { get_signals(info); if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) @@ -1276,7 +1276,7 @@ void cts_change(MGSLPC_INFO *info) info->pending_bh |= BH_STATUS; } -void dcd_change(MGSLPC_INFO *info) +static void dcd_change(MGSLPC_INFO *info) { get_signals(info); if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) @@ -1310,7 +1310,7 @@ void dcd_change(MGSLPC_INFO *info) info->pending_bh |= BH_STATUS; } -void dsr_change(MGSLPC_INFO *info) +static void dsr_change(MGSLPC_INFO *info) { get_signals(info); if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) @@ -1325,7 +1325,7 @@ void dsr_change(MGSLPC_INFO *info) info->pending_bh |= BH_STATUS; } -void ri_change(MGSLPC_INFO *info) +static void ri_change(MGSLPC_INFO *info) { get_signals(info); if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) @@ -2955,7 +2955,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info) /* Called to print information about devices */ -int mgslpc_read_proc(char *page, char **start, off_t off, int count, +static int mgslpc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0, l; @@ -3218,7 +3218,7 @@ static void __exit synclink_cs_exit(void) module_init(synclink_cs_init); module_exit(synclink_cs_exit); -void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate) +static void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate) { unsigned int M, N; unsigned char val; @@ -3254,7 +3254,7 @@ void mgslpc_set_rate(MGSLPC_INFO *info, unsigned char channel, unsigned int rate /* Enabled the AUX clock output at the specified frequency. */ -void enable_auxclk(MGSLPC_INFO *info) +static void enable_auxclk(MGSLPC_INFO *info) { unsigned char val; diff --git a/drivers/char/pty.c b/drivers/char/pty.c index a47386427eb2..22e6caadcddf 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -35,7 +35,7 @@ /* These are global because they are accessed in tty_io.c */ #ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver; -struct tty_driver *pts_driver; +static struct tty_driver *pts_driver; #endif static void pty_close(struct tty_struct * tty, struct file * filp) diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index a23342724582..37c8bea8e2b0 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -53,7 +53,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) #if defined(__i386__) # define BREAKPOINT() asm(" int $3"); #else @@ -118,7 +117,7 @@ #define RCLRVALUE 0xffff -MGSL_PARAMS default_params = { +static MGSL_PARAMS default_params = { MGSL_MODE_HDLC, /* unsigned long mode */ 0, /* unsigned char loopback; */ HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */ @@ -679,13 +678,13 @@ void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask ); #define usc_EnableReceiver(a,b) \ usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) ) -u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port ); -void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value ); -void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ); +static u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port ); +static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value ); +static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ); -u16 usc_InReg( struct mgsl_struct *info, u16 Port ); -void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value ); -void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ); +static u16 usc_InReg( struct mgsl_struct *info, u16 Port ); +static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value ); +static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ); void usc_RCmd( struct mgsl_struct *info, u16 Cmd ); void usc_TCmd( struct mgsl_struct *info, u16 Cmd ); @@ -694,40 +693,39 @@ void usc_TCmd( struct mgsl_struct *info, u16 Cmd ); #define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1)) -void usc_process_rxoverrun_sync( struct mgsl_struct *info ); -void usc_start_receiver( struct mgsl_struct *info ); -void usc_stop_receiver( struct mgsl_struct *info ); +static void usc_process_rxoverrun_sync( struct mgsl_struct *info ); +static void usc_start_receiver( struct mgsl_struct *info ); +static void usc_stop_receiver( struct mgsl_struct *info ); -void usc_start_transmitter( struct mgsl_struct *info ); -void usc_stop_transmitter( struct mgsl_struct *info ); -void usc_set_txidle( struct mgsl_struct *info ); -void usc_load_txfifo( struct mgsl_struct *info ); +static void usc_start_transmitter( struct mgsl_struct *info ); +static void usc_stop_transmitter( struct mgsl_struct *info ); +static void usc_set_txidle( struct mgsl_struct *info ); +static void usc_load_txfifo( struct mgsl_struct *info ); -void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate ); -void usc_enable_loopback( struct mgsl_struct *info, int enable ); +static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate ); +static void usc_enable_loopback( struct mgsl_struct *info, int enable ); -void usc_get_serial_signals( struct mgsl_struct *info ); -void usc_set_serial_signals( struct mgsl_struct *info ); +static void usc_get_serial_signals( struct mgsl_struct *info ); +static void usc_set_serial_signals( struct mgsl_struct *info ); -void usc_reset( struct mgsl_struct *info ); +static void usc_reset( struct mgsl_struct *info ); -void usc_set_sync_mode( struct mgsl_struct *info ); -void usc_set_sdlc_mode( struct mgsl_struct *info ); -void usc_set_async_mode( struct mgsl_struct *info ); -void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate ); +static void usc_set_sync_mode( struct mgsl_struct *info ); +static void usc_set_sdlc_mode( struct mgsl_struct *info ); +static void usc_set_async_mode( struct mgsl_struct *info ); +static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate ); -void usc_loopback_frame( struct mgsl_struct *info ); +static void usc_loopback_frame( struct mgsl_struct *info ); -void mgsl_tx_timeout(unsigned long context); +static void mgsl_tx_timeout(unsigned long context); -void usc_loopmode_cancel_transmit( struct mgsl_struct * info ); -void usc_loopmode_insert_request( struct mgsl_struct * info ); -int usc_loopmode_active( struct mgsl_struct * info); -void usc_loopmode_send_done( struct mgsl_struct * info ); -int usc_loopmode_send_active( struct mgsl_struct * info ); +static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ); +static void usc_loopmode_insert_request( struct mgsl_struct * info ); +static int usc_loopmode_active( struct mgsl_struct * info); +static void usc_loopmode_send_done( struct mgsl_struct * info ); -int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); +static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); #ifdef CONFIG_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) @@ -753,77 +751,77 @@ static void hdlcdev_exit(struct mgsl_struct *info); ((Nrdd) << 11) + \ ((Nrad) << 6) ) -void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit); +static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit); /* * Adapter diagnostic routines */ -BOOLEAN mgsl_register_test( struct mgsl_struct *info ); -BOOLEAN mgsl_irq_test( struct mgsl_struct *info ); -BOOLEAN mgsl_dma_test( struct mgsl_struct *info ); -BOOLEAN mgsl_memory_test( struct mgsl_struct *info ); -int mgsl_adapter_test( struct mgsl_struct *info ); +static BOOLEAN mgsl_register_test( struct mgsl_struct *info ); +static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ); +static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ); +static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ); +static int mgsl_adapter_test( struct mgsl_struct *info ); /* * device and resource management routines */ -int mgsl_claim_resources(struct mgsl_struct *info); -void mgsl_release_resources(struct mgsl_struct *info); -void mgsl_add_device(struct mgsl_struct *info); -struct mgsl_struct* mgsl_allocate_device(void); +static int mgsl_claim_resources(struct mgsl_struct *info); +static void mgsl_release_resources(struct mgsl_struct *info); +static void mgsl_add_device(struct mgsl_struct *info); +static struct mgsl_struct* mgsl_allocate_device(void); /* * DMA buffer manupulation functions. */ -void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ); -int mgsl_get_rx_frame( struct mgsl_struct *info ); -int mgsl_get_raw_rx_frame( struct mgsl_struct *info ); -void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ); -void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ); -int num_free_tx_dma_buffers(struct mgsl_struct *info); -void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize); -void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count); +static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ); +static int mgsl_get_rx_frame( struct mgsl_struct *info ); +static int mgsl_get_raw_rx_frame( struct mgsl_struct *info ); +static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ); +static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ); +static int num_free_tx_dma_buffers(struct mgsl_struct *info); +static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize); +static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count); /* * DMA and Shared Memory buffer allocation and formatting */ -int mgsl_allocate_dma_buffers(struct mgsl_struct *info); -void mgsl_free_dma_buffers(struct mgsl_struct *info); -int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); -void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); -int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info); -void mgsl_free_buffer_list_memory(struct mgsl_struct *info); -int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info); -void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info); -int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info); -void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info); -int load_next_tx_holding_buffer(struct mgsl_struct *info); -int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize); +static int mgsl_allocate_dma_buffers(struct mgsl_struct *info); +static void mgsl_free_dma_buffers(struct mgsl_struct *info); +static int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); +static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount); +static int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info); +static void mgsl_free_buffer_list_memory(struct mgsl_struct *info); +static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info); +static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info); +static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info); +static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info); +static int load_next_tx_holding_buffer(struct mgsl_struct *info); +static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize); /* * Bottom half interrupt handlers */ -void mgsl_bh_handler(void* Context); -void mgsl_bh_receive(struct mgsl_struct *info); -void mgsl_bh_transmit(struct mgsl_struct *info); -void mgsl_bh_status(struct mgsl_struct *info); +static void mgsl_bh_handler(void* Context); +static void mgsl_bh_receive(struct mgsl_struct *info); +static void mgsl_bh_transmit(struct mgsl_struct *info); +static void mgsl_bh_status(struct mgsl_struct *info); /* * Interrupt handler routines and dispatch table. */ -void mgsl_isr_null( struct mgsl_struct *info ); -void mgsl_isr_transmit_data( struct mgsl_struct *info ); -void mgsl_isr_receive_data( struct mgsl_struct *info ); -void mgsl_isr_receive_status( struct mgsl_struct *info ); -void mgsl_isr_transmit_status( struct mgsl_struct *info ); -void mgsl_isr_io_pin( struct mgsl_struct *info ); -void mgsl_isr_misc( struct mgsl_struct *info ); -void mgsl_isr_receive_dma( struct mgsl_struct *info ); -void mgsl_isr_transmit_dma( struct mgsl_struct *info ); +static void mgsl_isr_null( struct mgsl_struct *info ); +static void mgsl_isr_transmit_data( struct mgsl_struct *info ); +static void mgsl_isr_receive_data( struct mgsl_struct *info ); +static void mgsl_isr_receive_status( struct mgsl_struct *info ); +static void mgsl_isr_transmit_status( struct mgsl_struct *info ); +static void mgsl_isr_io_pin( struct mgsl_struct *info ); +static void mgsl_isr_misc( struct mgsl_struct *info ); +static void mgsl_isr_receive_dma( struct mgsl_struct *info ); +static void mgsl_isr_transmit_dma( struct mgsl_struct *info ); typedef void (*isr_dispatch_func)(struct mgsl_struct *); -isr_dispatch_func UscIsrTable[7] = +static isr_dispatch_func UscIsrTable[7] = { mgsl_isr_null, mgsl_isr_misc, @@ -858,7 +856,7 @@ static int pci_registered; /* * Global linked list of SyncLink devices */ -struct mgsl_struct *mgsl_device_list; +static struct mgsl_struct *mgsl_device_list; static int mgsl_device_count; /* @@ -935,7 +933,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); * (gdb) to get the .text address for the add-symbol-file command. * This allows remote debugging of dynamically loadable modules. */ -void* mgsl_get_text_ptr(void) +static void* mgsl_get_text_ptr(void) { return mgsl_get_text_ptr; } @@ -1052,7 +1050,7 @@ static void mgsl_start(struct tty_struct *tty) /* mgsl_bh_action() Return next bottom half action to perform. * Return Value: BH action code or 0 if nothing to do. */ -int mgsl_bh_action(struct mgsl_struct *info) +static int mgsl_bh_action(struct mgsl_struct *info) { unsigned long flags; int rc = 0; @@ -1084,7 +1082,7 @@ int mgsl_bh_action(struct mgsl_struct *info) /* * Perform bottom half processing of work items queued by ISR. */ -void mgsl_bh_handler(void* Context) +static void mgsl_bh_handler(void* Context) { struct mgsl_struct *info = (struct mgsl_struct*)Context; int action; @@ -1128,7 +1126,7 @@ void mgsl_bh_handler(void* Context) __FILE__,__LINE__,info->device_name); } -void mgsl_bh_receive(struct mgsl_struct *info) +static void mgsl_bh_receive(struct mgsl_struct *info) { int (*get_rx_frame)(struct mgsl_struct *info) = (info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame); @@ -1149,7 +1147,7 @@ void mgsl_bh_receive(struct mgsl_struct *info) } while(get_rx_frame(info)); } -void mgsl_bh_transmit(struct mgsl_struct *info) +static void mgsl_bh_transmit(struct mgsl_struct *info) { struct tty_struct *tty = info->tty; unsigned long flags; @@ -1172,7 +1170,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info) spin_unlock_irqrestore(&info->irq_spinlock,flags); } -void mgsl_bh_status(struct mgsl_struct *info) +static void mgsl_bh_status(struct mgsl_struct *info) { if ( debug_level >= DEBUG_LEVEL_BH ) printk( "%s(%d):mgsl_bh_status() entry on %s\n", @@ -1193,7 +1191,7 @@ void mgsl_bh_status(struct mgsl_struct *info) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_receive_status( struct mgsl_struct *info ) +static void mgsl_isr_receive_status( struct mgsl_struct *info ) { u16 status = usc_InReg( info, RCSR ); @@ -1245,7 +1243,7 @@ void mgsl_isr_receive_status( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_transmit_status( struct mgsl_struct *info ) +static void mgsl_isr_transmit_status( struct mgsl_struct *info ) { u16 status = usc_InReg( info, TCSR ); @@ -1312,7 +1310,7 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_io_pin( struct mgsl_struct *info ) +static void mgsl_isr_io_pin( struct mgsl_struct *info ) { struct mgsl_icount *icount; u16 status = usc_InReg( info, MISR ); @@ -1430,7 +1428,7 @@ void mgsl_isr_io_pin( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_transmit_data( struct mgsl_struct *info ) +static void mgsl_isr_transmit_data( struct mgsl_struct *info ) { if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n", @@ -1462,7 +1460,7 @@ void mgsl_isr_transmit_data( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_receive_data( struct mgsl_struct *info ) +static void mgsl_isr_receive_data( struct mgsl_struct *info ) { int Fifocount; u16 status; @@ -1574,7 +1572,7 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) * Arguments: info pointer to device extension (instance data) * Return Value: None */ -void mgsl_isr_misc( struct mgsl_struct *info ) +static void mgsl_isr_misc( struct mgsl_struct *info ) { u16 status = usc_InReg( info, MISR ); @@ -1610,7 +1608,7 @@ void mgsl_isr_misc( struct mgsl_struct *info ) * Arguments: info pointer to device extension (instance data) * Return Value: None */ -void mgsl_isr_null( struct mgsl_struct *info ) +static void mgsl_isr_null( struct mgsl_struct *info ) { } /* end of mgsl_isr_null() */ @@ -1634,7 +1632,7 @@ void mgsl_isr_null( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_receive_dma( struct mgsl_struct *info ) +static void mgsl_isr_receive_dma( struct mgsl_struct *info ) { u16 status; @@ -1678,7 +1676,7 @@ void mgsl_isr_receive_dma( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_isr_transmit_dma( struct mgsl_struct *info ) +static void mgsl_isr_transmit_dma( struct mgsl_struct *info ) { u16 status; @@ -2990,7 +2988,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, return mgsl_ioctl_common(info, cmd, arg); } -int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) +static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) { int error; struct mgsl_icount cnow; /* kernel counter temps */ @@ -3649,7 +3647,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info) * * Return Value: */ -int mgsl_read_proc(char *page, char **start, off_t off, int count, +static int mgsl_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0, l; @@ -3688,7 +3686,7 @@ done: * Arguments: info pointer to device instance data * Return Value: 0 if success, otherwise error */ -int mgsl_allocate_dma_buffers(struct mgsl_struct *info) +static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) { unsigned short BuffersPerFrame; @@ -3795,7 +3793,7 @@ int mgsl_allocate_dma_buffers(struct mgsl_struct *info) * Arguments: info pointer to device instance data * Return Value: 0 if success, otherwise error */ -int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) +static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) { unsigned int i; @@ -3880,7 +3878,7 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) * the buffer list contains the information necessary to free * the individual buffers! */ -void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) +static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) { if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI ) kfree(info->buffer_list); @@ -3907,7 +3905,7 @@ void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) * * Return Value: 0 if success, otherwise -ENOMEM */ -int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) +static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) { int i; unsigned long phys_addr; @@ -3949,7 +3947,7 @@ int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList, * * Return Value: None */ -void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount) +static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount) { int i; @@ -3972,7 +3970,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_free_dma_buffers( struct mgsl_struct *info ) +static void mgsl_free_dma_buffers( struct mgsl_struct *info ) { mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count ); mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count ); @@ -3993,7 +3991,7 @@ void mgsl_free_dma_buffers( struct mgsl_struct *info ) * * Return Value: 0 if success, otherwise -ENOMEM */ -int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) +static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) { info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA); if ( info->intermediate_rxbuffer == NULL ) @@ -4013,7 +4011,7 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) * * Return Value: None */ -void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) +static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) { if ( info->intermediate_rxbuffer ) kfree(info->intermediate_rxbuffer); @@ -4035,7 +4033,7 @@ void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) * * Return Value: 0 if success, otherwise -ENOMEM */ -int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) +static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) { int i; @@ -4066,7 +4064,7 @@ int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) * * Return Value: None */ -void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) +static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) { int i; @@ -4098,7 +4096,7 @@ void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) * into adapter's tx dma buffer, * 0 otherwise */ -int load_next_tx_holding_buffer(struct mgsl_struct *info) +static int load_next_tx_holding_buffer(struct mgsl_struct *info) { int ret = 0; @@ -4144,7 +4142,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info) * * Return Value: 1 if able to store, 0 otherwise */ -int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize) +static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize) { struct tx_holding_buffer *ptx; @@ -4163,7 +4161,7 @@ int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned return 1; } -int mgsl_claim_resources(struct mgsl_struct *info) +static int mgsl_claim_resources(struct mgsl_struct *info) { if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) { printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n", @@ -4243,7 +4241,7 @@ errout: } /* end of mgsl_claim_resources() */ -void mgsl_release_resources(struct mgsl_struct *info) +static void mgsl_release_resources(struct mgsl_struct *info) { if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):mgsl_release_resources(%s) entry\n", @@ -4297,7 +4295,7 @@ void mgsl_release_resources(struct mgsl_struct *info) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_add_device( struct mgsl_struct *info ) +static void mgsl_add_device( struct mgsl_struct *info ) { info->next_device = NULL; info->line = mgsl_device_count; @@ -4363,7 +4361,7 @@ void mgsl_add_device( struct mgsl_struct *info ) * Arguments: none * Return Value: pointer to mgsl_struct if success, otherwise NULL */ -struct mgsl_struct* mgsl_allocate_device(void) +static struct mgsl_struct* mgsl_allocate_device(void) { struct mgsl_struct *info; @@ -4582,7 +4580,7 @@ module_exit(synclink_exit); * * None */ -void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) +static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) { /* output command to CCAR in bits <15..11> */ /* preserve bits <10..7>, bits <6..0> must be zero */ @@ -4609,7 +4607,7 @@ void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) * * None */ -void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) +static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) { /* write command mask to DCAR */ outw( Cmd + info->mbre_bit, info->io_base ); @@ -4636,7 +4634,7 @@ void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) * None * */ -void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) +static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) { /* Note: The DCAR is located at the adapter base address */ /* Note: must preserve state of BIT8 in DCAR */ @@ -4665,7 +4663,7 @@ void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) * The 16-bit value read from register * */ -u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) +static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) { /* Note: The DCAR is located at the adapter base address */ /* Note: must preserve state of BIT8 in DCAR */ @@ -4692,7 +4690,7 @@ u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr ) * None * */ -void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) +static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) { outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); outw( RegValue, info->io_base + CCAR ); @@ -4717,7 +4715,7 @@ void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) * * 16-bit value read from register */ -u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) +static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) { outw( RegAddr + info->loopback_bits, info->io_base + CCAR ); return inw( info->io_base + CCAR ); @@ -4731,7 +4729,7 @@ u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr ) * Arguments: info pointer to device instance data * Return Value: NONE */ -void usc_set_sdlc_mode( struct mgsl_struct *info ) +static void usc_set_sdlc_mode( struct mgsl_struct *info ) { u16 RegValue; int PreSL1660; @@ -5311,7 +5309,7 @@ void usc_set_sdlc_mode( struct mgsl_struct *info ) * enable 1 = enable loopback, 0 = disable * Return Value: None */ -void usc_enable_loopback(struct mgsl_struct *info, int enable) +static void usc_enable_loopback(struct mgsl_struct *info, int enable) { if (enable) { /* blank external TXD output */ @@ -5375,7 +5373,7 @@ void usc_enable_loopback(struct mgsl_struct *info, int enable) * * Return Value: None */ -void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) +static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) { u32 XtalSpeed; u16 Tc; @@ -5432,7 +5430,7 @@ void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) * * Return Value: None */ -void usc_process_rxoverrun_sync( struct mgsl_struct *info ) +static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) { int start_index; int end_index; @@ -5571,7 +5569,7 @@ void usc_process_rxoverrun_sync( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_stop_receiver( struct mgsl_struct *info ) +static void usc_stop_receiver( struct mgsl_struct *info ) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):usc_stop_receiver(%s)\n", @@ -5604,7 +5602,7 @@ void usc_stop_receiver( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_start_receiver( struct mgsl_struct *info ) +static void usc_start_receiver( struct mgsl_struct *info ) { u32 phys_addr; @@ -5668,7 +5666,7 @@ void usc_start_receiver( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_start_transmitter( struct mgsl_struct *info ) +static void usc_start_transmitter( struct mgsl_struct *info ) { u32 phys_addr; unsigned int FrameSize; @@ -5774,7 +5772,7 @@ void usc_start_transmitter( struct mgsl_struct *info ) * Arguments: info pointer to device isntance data * Return Value: None */ -void usc_stop_transmitter( struct mgsl_struct *info ) +static void usc_stop_transmitter( struct mgsl_struct *info ) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):usc_stop_transmitter(%s)\n", @@ -5803,7 +5801,7 @@ void usc_stop_transmitter( struct mgsl_struct *info ) * Arguments: info pointer to device extension (instance data) * Return Value: None */ -void usc_load_txfifo( struct mgsl_struct *info ) +static void usc_load_txfifo( struct mgsl_struct *info ) { int Fifocount; u8 TwoBytes[2]; @@ -5860,7 +5858,7 @@ void usc_load_txfifo( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_reset( struct mgsl_struct *info ) +static void usc_reset( struct mgsl_struct *info ) { if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { int i; @@ -5974,7 +5972,7 @@ void usc_reset( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_set_async_mode( struct mgsl_struct *info ) +static void usc_set_async_mode( struct mgsl_struct *info ) { u16 RegValue; @@ -6167,7 +6165,7 @@ void usc_set_async_mode( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_loopback_frame( struct mgsl_struct *info ) +static void usc_loopback_frame( struct mgsl_struct *info ) { int i; unsigned long oldmode = info->params.mode; @@ -6235,7 +6233,7 @@ void usc_loopback_frame( struct mgsl_struct *info ) * Arguments: info pointer to adapter info structure * Return Value: None */ -void usc_set_sync_mode( struct mgsl_struct *info ) +static void usc_set_sync_mode( struct mgsl_struct *info ) { usc_loopback_frame( info ); usc_set_sdlc_mode( info ); @@ -6258,7 +6256,7 @@ void usc_set_sync_mode( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_set_txidle( struct mgsl_struct *info ) +static void usc_set_txidle( struct mgsl_struct *info ) { u16 usc_idle_mode = IDLEMODE_FLAGS; @@ -6321,7 +6319,7 @@ void usc_set_txidle( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_get_serial_signals( struct mgsl_struct *info ) +static void usc_get_serial_signals( struct mgsl_struct *info ) { u16 status; @@ -6357,7 +6355,7 @@ void usc_get_serial_signals( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: None */ -void usc_set_serial_signals( struct mgsl_struct *info ) +static void usc_set_serial_signals( struct mgsl_struct *info ) { u16 Control; unsigned char V24Out = info->serial_signals; @@ -6389,7 +6387,7 @@ void usc_set_serial_signals( struct mgsl_struct *info ) * 0 disables the AUX clock. * Return Value: None */ -void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) +static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) { if ( data_rate ) { /* @@ -6499,7 +6497,7 @@ void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) +static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) { unsigned int i; @@ -6525,7 +6523,7 @@ void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: number of free tx dma buffers */ -int num_free_tx_dma_buffers(struct mgsl_struct *info) +static int num_free_tx_dma_buffers(struct mgsl_struct *info) { return info->tx_buffer_count - info->tx_dma_buffers_used; } @@ -6540,7 +6538,7 @@ int num_free_tx_dma_buffers(struct mgsl_struct *info) * Arguments: info pointer to device instance data * Return Value: None */ -void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) +static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) { unsigned int i; @@ -6568,7 +6566,7 @@ void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info ) * * Return Value: None */ -void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ) +static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex ) { int Done = 0; DMABUFFERENTRY *pBufEntry; @@ -6611,7 +6609,7 @@ void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartInd * Arguments: info pointer to device extension * Return Value: 1 if frame returned, otherwise 0 */ -int mgsl_get_rx_frame(struct mgsl_struct *info) +static int mgsl_get_rx_frame(struct mgsl_struct *info) { unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */ unsigned short status; @@ -6810,7 +6808,7 @@ Cleanup: * Arguments: info pointer to device extension * Return Value: 1 if frame returned, otherwise 0 */ -int mgsl_get_raw_rx_frame(struct mgsl_struct *info) +static int mgsl_get_raw_rx_frame(struct mgsl_struct *info) { unsigned int CurrentIndex, NextIndex; unsigned short status; @@ -6975,8 +6973,8 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) * * Return Value: None */ -void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer, - unsigned int BufferSize) +static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, + const char *Buffer, unsigned int BufferSize) { unsigned short Copycount; unsigned int i = 0; @@ -7052,7 +7050,7 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer, * Arguments: info pointer to device instance data * Return Value: TRUE if test passed, otherwise FALSE */ -BOOLEAN mgsl_register_test( struct mgsl_struct *info ) +static BOOLEAN mgsl_register_test( struct mgsl_struct *info ) { static unsigned short BitPatterns[] = { 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f }; @@ -7108,7 +7106,7 @@ BOOLEAN mgsl_register_test( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: TRUE if test passed, otherwise FALSE */ -BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) +static BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) { unsigned long EndTime; unsigned long flags; @@ -7163,7 +7161,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: TRUE if test passed, otherwise FALSE */ -BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) +static BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) { unsigned short FifoLevel; unsigned long phys_addr; @@ -7455,7 +7453,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: 0 if success, otherwise -ENODEV */ -int mgsl_adapter_test( struct mgsl_struct *info ) +static int mgsl_adapter_test( struct mgsl_struct *info ) { if ( debug_level >= DEBUG_LEVEL_INFO ) printk( "%s(%d):Testing device %s\n", @@ -7497,7 +7495,7 @@ int mgsl_adapter_test( struct mgsl_struct *info ) * Arguments: info pointer to device instance data * Return Value: TRUE if test passed, otherwise FALSE */ -BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) +static BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) { static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 }; @@ -7578,7 +7576,7 @@ BOOLEAN mgsl_memory_test( struct mgsl_struct *info ) * * Return Value: None */ -void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, +static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, unsigned short count ) { /* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */ @@ -7600,7 +7598,7 @@ void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr, } /* End Of mgsl_load_pci_memory() */ -void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit) +static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit) { int i; int linecount; @@ -7640,7 +7638,7 @@ void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int * Arguments: context pointer to device instance data * Return Value: None */ -void mgsl_tx_timeout(unsigned long context) +static void mgsl_tx_timeout(unsigned long context) { struct mgsl_struct *info = (struct mgsl_struct*)context; unsigned long flags; @@ -7694,7 +7692,7 @@ static int mgsl_loopmode_send_done( struct mgsl_struct * info ) /* release the line by echoing RxD to TxD * upon completion of a transmit frame */ -void usc_loopmode_send_done( struct mgsl_struct * info ) +static void usc_loopmode_send_done( struct mgsl_struct * info ) { info->loopmode_send_done_requested = FALSE; /* clear CMR:13 to 0 to start echoing RxData to TxData */ @@ -7704,7 +7702,7 @@ void usc_loopmode_send_done( struct mgsl_struct * info ) /* abort a transmit in progress while in HDLC LoopMode */ -void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) +static void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) { /* reset tx dma channel and purge TxFifo */ usc_RTCmd( info, RTCmd_PurgeTxFifo ); @@ -7716,7 +7714,7 @@ void usc_loopmode_cancel_transmit( struct mgsl_struct * info ) * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort) * we must clear CMR:13 to begin repeating TxData to RxData */ -void usc_loopmode_insert_request( struct mgsl_struct * info ) +static void usc_loopmode_insert_request( struct mgsl_struct * info ) { info->loopmode_insert_requested = TRUE; @@ -7733,18 +7731,11 @@ void usc_loopmode_insert_request( struct mgsl_struct * info ) /* return 1 if station is inserted into the loop, otherwise 0 */ -int usc_loopmode_active( struct mgsl_struct * info) +static int usc_loopmode_active( struct mgsl_struct * info) { return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ; } -/* return 1 if USC is in loop send mode, otherwise 0 - */ -int usc_loopmode_send_active( struct mgsl_struct * info ) -{ - return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ; -} - #ifdef CONFIG_HDLC /** diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 7696ead16862..0c5ba9dc9063 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -488,7 +488,7 @@ static struct parport_driver tipar_driver = { .detach = tipar_detach, }; -int __init +static int __init tipar_init_module(void) { int err = 0; @@ -525,7 +525,7 @@ out: return err; } -void __exit +static void __exit tipar_cleanup_module(void) { unsigned int i; diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index baf65901ab41..58e21fe44262 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -407,7 +407,7 @@ static int tosh_get_machine_id(void) * laptop, otherwise zero and determines the Machine ID, BIOS version and * date, and SCI version. */ -int tosh_probe(void) +static int tosh_probe(void) { int i,major,minor,day,year,month,flag; unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 }; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index ffc82ee87b37..0edec4f95c30 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -327,7 +327,7 @@ void tty_ldisc_put(int disc) EXPORT_SYMBOL_GPL(tty_ldisc_put); -void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) +static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) { tty->ldisc = *ld; tty->ldisc.refcount = 0; @@ -583,7 +583,7 @@ restart: /* * This routine returns a tty driver structure, given a device number */ -struct tty_driver *get_tty_driver(dev_t device, int *index) +static struct tty_driver *get_tty_driver(dev_t device, int *index) { struct tty_driver *p; @@ -744,7 +744,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * but doesn't hold any locks, so we need to make sure we have the appropriate * locks for what we're doing.. */ -void do_tty_hangup(void *data) +static void do_tty_hangup(void *data) { struct tty_struct *tty = (struct tty_struct *) data; struct file * cons_filp = NULL; @@ -2523,28 +2523,6 @@ out: tty_ldisc_deref(disc); } -/* - * Call the ldisc flush directly from a driver. This function may - * return an error and need retrying by the user. - */ - -int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count) -{ - int ret = 0; - struct tty_ldisc *disc; - - disc = tty_ldisc_ref(tty); - if(test_bit(TTY_DONT_FLIP, &tty->flags)) - ret = -EAGAIN; - else if(disc == NULL) - ret = -EIO; - else - disc->receive_buf(tty, cp, fp, count); - tty_ldisc_deref(disc); - return ret; - -} - /* * Routine which returns the baud rate of the tty * diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 7145057e0a48..58597993954f 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -372,7 +372,7 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) /* * Send a high priority character to the tty. */ -void send_prio_char(struct tty_struct *tty, char ch) +static void send_prio_char(struct tty_struct *tty, char ch) { int was_stopped = tty->stopped; diff --git a/include/linux/lp.h b/include/linux/lp.h index 521bcd2fecb1..7059b6b9878a 100644 --- a/include/linux/lp.h +++ b/include/linux/lp.h @@ -186,12 +186,6 @@ struct lp_struct { */ #define LP_DELAY 50 -/* - * function prototypes - */ - -extern int lp_init(void); - #endif #endif -- cgit v1.2.3 From b69ae6c23849111524f3f89cc0a45ee1742689d4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 10 Jan 2005 17:24:52 -0800 Subject: [PATCH] efs: make a struct static (fwd) The patch below makes a needessly global struct in the efs code static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/efs/super.c | 20 ++++++++++++++++++++ include/linux/efs_vh.h | 17 ----------------- 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/fs/efs/super.c b/fs/efs/super.c index af4d01e2730a..d8d5ea9a9997 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -32,6 +32,26 @@ static struct file_system_type efs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; +static struct pt_types sgi_pt_types[] = { + {0x00, "SGI vh"}, + {0x01, "SGI trkrepl"}, + {0x02, "SGI secrepl"}, + {0x03, "SGI raw"}, + {0x04, "SGI bsd"}, + {SGI_SYSV, "SGI sysv"}, + {0x06, "SGI vol"}, + {SGI_EFS, "SGI efs"}, + {0x08, "SGI lv"}, + {0x09, "SGI rlv"}, + {0x0A, "SGI xfs"}, + {0x0B, "SGI xfslog"}, + {0x0C, "SGI xlv"}, + {0x82, "Linux swap"}, + {0x83, "Linux native"}, + {0, NULL} +}; + + static kmem_cache_t * efs_inode_cachep; static struct inode *efs_alloc_inode(struct super_block *sb) diff --git a/include/linux/efs_vh.h b/include/linux/efs_vh.h index b3df61ef2eb2..8a11150c61fe 100644 --- a/include/linux/efs_vh.h +++ b/include/linux/efs_vh.h @@ -47,23 +47,6 @@ struct volume_header { struct pt_types { int pt_type; char *pt_name; -} sgi_pt_types[] = { - {0x00, "SGI vh"}, - {0x01, "SGI trkrepl"}, - {0x02, "SGI secrepl"}, - {0x03, "SGI raw"}, - {0x04, "SGI bsd"}, - {SGI_SYSV, "SGI sysv"}, - {0x06, "SGI vol"}, - {SGI_EFS, "SGI efs"}, - {0x08, "SGI lv"}, - {0x09, "SGI rlv"}, - {0x0A, "SGI xfs"}, - {0x0B, "SGI xfslog"}, - {0x0C, "SGI xlv"}, - {0x82, "Linux swap"}, - {0x83, "Linux native"}, - {0, NULL} }; #endif /* __EFS_VH_H__ */ -- cgit v1.2.3 From 823986199ffd2928bcff8b6ab3c0dede78d19253 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 10 Jan 2005 17:25:07 -0800 Subject: [PATCH] ext3 cleanups - make some needlessly global code static - super.c: remove the unused global function ext3_panic Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/balloc.c | 2 +- fs/ext3/dir.c | 2 +- fs/ext3/inode.c | 4 +- fs/ext3/resize.c | 4 +- fs/ext3/super.c | 45 +++------ fs/ext3/xattr.c | 242 +++++++++++++++++++++++------------------------ fs/ext3/xattr.h | 8 -- include/linux/ext3_fs.h | 10 -- include/linux/ext3_jbd.h | 2 - 9 files changed, 143 insertions(+), 176 deletions(-) (limited to 'include') diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 4631ae139bf7..3f1b811ef2ad 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1451,7 +1451,7 @@ static inline int test_root(int a, int b) } } -int ext3_group_sparse(int group) +static int ext3_group_sparse(int group) { return (test_root(group, 3) || test_root(group, 5) || test_root(group, 7)); diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index b2bb90817371..832867aef3dc 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -306,7 +306,7 @@ static void free_rb_tree_fname(struct rb_root *root) } -struct dir_private_info *create_dir_info(loff_t pos) +static struct dir_private_info *create_dir_info(loff_t pos) { struct dir_private_info *p; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 1132ad886f5a..0a92408946a9 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -39,6 +39,8 @@ #include "xattr.h" #include "acl.h" +static int ext3_writepage_trans_blocks(struct inode *inode); + /* * Test whether an inode is a fast symlink. */ @@ -2807,7 +2809,7 @@ err_out: * block and work out the exact number of indirects which are touched. Pah. */ -int ext3_writepage_trans_blocks(struct inode *inode) +static int ext3_writepage_trans_blocks(struct inode *inode) { int bpp = ext3_journal_blocks_per_page(inode); int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3; diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index b2786fac330d..2c9f81278d5d 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -285,8 +285,8 @@ exit_journal: * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... */ -unsigned ext3_list_backups(struct super_block *sb, unsigned *three, - unsigned *five, unsigned *seven) +static unsigned ext3_list_backups(struct super_block *sb, unsigned *three, + unsigned *five, unsigned *seven) { unsigned *min = three; int mult = 3; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 9b654f7f29d7..d962d89e9ce1 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -50,6 +50,13 @@ static void ext3_mark_recovery_complete(struct super_block * sb, static void ext3_clear_journal_err(struct super_block * sb, struct ext3_super_block * es); static int ext3_sync_fs(struct super_block *sb, int wait); +static const char *ext3_decode_error(struct super_block * sb, int errno, + char nbuf[16]); +static int ext3_remount (struct super_block * sb, int * flags, char * data); +static int ext3_statfs (struct super_block * sb, struct kstatfs * buf); +static void ext3_unlockfs(struct super_block *sb); +static void ext3_write_super (struct super_block * sb); +static void ext3_write_super_lockfs(struct super_block *sb); /* * Wrappers for journal_start/end. @@ -178,7 +185,8 @@ void ext3_error (struct super_block * sb, const char * function, ext3_handle_error(sb); } -const char *ext3_decode_error(struct super_block * sb, int errno, char nbuf[16]) +static const char *ext3_decode_error(struct super_block * sb, int errno, + char nbuf[16]) { char *errstr = NULL; @@ -261,29 +269,6 @@ void ext3_abort (struct super_block * sb, const char * function, journal_abort(EXT3_SB(sb)->s_journal, -EIO); } -/* Deal with the reporting of failure conditions while running, such as - * inconsistencies in operation or invalid system states. - * - * Use ext3_error() for cases of invalid filesystem states, as that will - * record an error on disk and force a filesystem check on the next boot. - */ -NORET_TYPE void ext3_panic (struct super_block * sb, const char * function, - const char * fmt, ...) -{ - va_list args; - - va_start(args, fmt); - printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function); - vprintk(fmt, args); - printk("\n"); - va_end(args); - - /* this is to prevent panic from syncing this filesystem */ - /* AKPM: is this sufficient? */ - sb->s_flags |= MS_RDONLY; - panic ("EXT3-fs panic forced\n"); -} - void ext3_warning (struct super_block * sb, const char * function, const char * fmt, ...) { @@ -386,7 +371,7 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi) } } -void ext3_put_super (struct super_block * sb) +static void ext3_put_super (struct super_block * sb) { struct ext3_sb_info *sbi = EXT3_SB(sb); struct ext3_super_block *es = sbi->s_es; @@ -2018,7 +2003,7 @@ int ext3_force_commit(struct super_block *sb) * This implicitly triggers the writebehind on sync(). */ -void ext3_write_super (struct super_block * sb) +static void ext3_write_super (struct super_block * sb) { if (down_trylock(&sb->s_lock) == 0) BUG(); @@ -2041,7 +2026,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait) * LVM calls this function before a (read-only) snapshot is created. This * gives us a chance to flush the journal completely and mark the fs clean. */ -void ext3_write_super_lockfs(struct super_block *sb) +static void ext3_write_super_lockfs(struct super_block *sb) { sb->s_dirt = 0; @@ -2062,7 +2047,7 @@ void ext3_write_super_lockfs(struct super_block *sb) * Called by LVM after the snapshot is done. We need to reset the RECOVER * flag here, even though the filesystem is not technically dirty yet. */ -void ext3_unlockfs(struct super_block *sb) +static void ext3_unlockfs(struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) { lock_super(sb); @@ -2074,7 +2059,7 @@ void ext3_unlockfs(struct super_block *sb) } } -int ext3_remount (struct super_block * sb, int * flags, char * data) +static int ext3_remount (struct super_block * sb, int * flags, char * data) { struct ext3_super_block * es; struct ext3_sb_info *sbi = EXT3_SB(sb); @@ -2146,7 +2131,7 @@ int ext3_remount (struct super_block * sb, int * flags, char * data) return 0; } -int ext3_statfs (struct super_block * sb, struct kstatfs * buf) +static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) { struct ext3_super_block *es = EXT3_SB(sb)->s_es; unsigned long overhead; diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 935778cc834f..31ef0eef09a3 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -138,23 +138,12 @@ ext3_xattr_handler(int name_index) return handler; } -/* - * Inode operation listxattr() - * - * dentry->d_inode->i_sem: don't care - */ -ssize_t -ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) -{ - return ext3_xattr_list(dentry->d_inode, buffer, size); -} - /* * ext3_xattr_block_get() * * routine looks for attribute in EA block and returns it's value and size */ -int +static int ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { @@ -250,7 +239,7 @@ cleanup: * * routine looks for attribute in inode body and returns it's value and size */ -int +static int ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { @@ -352,7 +341,7 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name, * * generate list of attributes stored in EA block */ -int +static int ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) { struct buffer_head *bh = NULL; @@ -428,7 +417,7 @@ cleanup: * * generate list of attributes stored in inode body */ -int +static int ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) { struct ext3_xattr_entry *last; @@ -507,7 +496,7 @@ cleanup: * Returns a negative error number on failure, or the number of bytes * used / required on success. */ -int +static int ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) { int size = buffer_size; @@ -545,6 +534,17 @@ cleanup: return error + size; } +/* + * Inode operation listxattr() + * + * dentry->d_inode->i_sem: don't care + */ +ssize_t +ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + return ext3_xattr_list(dentry->d_inode, buffer, size); +} + /* * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is * not set, set it. @@ -571,7 +571,7 @@ static void ext3_xattr_update_super_block(handle_t *handle, * search attribute and calculate free space in inode body * NOTE: free space includes space our attribute hold */ -int +static int ext3_xattr_ibody_find(struct inode *inode, int name_index, const char *name, int *free) { @@ -638,7 +638,7 @@ ext3_xattr_ibody_find(struct inode *inode, int name_index, * search attribute and calculate free space in EA block (if it allocated) * NOTE: free space includes space our attribute hold */ -int +static int ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, int *free) { @@ -698,7 +698,7 @@ bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", * * this routine add/remove/replace attribute in inode body */ -int +static int ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, const char *name, const void *value, size_t value_len, int flags) @@ -845,113 +845,12 @@ done: return 0; } -/* - * ext3_xattr_set_handle() - * - * Create, replace or remove an extended attribute for this inode. Buffer - * is NULL to remove an existing extended attribute, and non-NULL to - * either replace an existing extended attribute, or create a new extended - * attribute. The flags XATTR_REPLACE and XATTR_CREATE - * specify that an extended attribute must exist and must not exist - * previous to the call, respectively. - * - * Returns 0, or a negative error number on failure. - */ -int -ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, - int flags) -{ - int free1 = -1, free2 = -1; - int err, where = 0, total; - int name_len; - - ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", - name_index, name, value, (long)value_len); - - if (IS_RDONLY(inode)) - return -EROFS; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - return -EPERM; - if (value == NULL) - value_len = 0; - if (name == NULL) - return -EINVAL; - name_len = strlen(name); - if (name_len > 255 || value_len > inode->i_sb->s_blocksize) - return -ERANGE; - down_write(&EXT3_I(inode)->xattr_sem); - -#define EX_FOUND_IN_IBODY 1 -#define EX_FOUND_IN_BLOCK 2 - - /* try to find attribute in inode body */ - err = ext3_xattr_ibody_find(inode, name_index, name, &free1); - if (err == 0) { - /* found EA in inode */ - where = EX_FOUND_IN_IBODY; - } else if (err == -ENOENT) { - /* there is no such attribute in inode body */ - /* try to find attribute in dedicated block */ - err = ext3_xattr_block_find(inode, name_index, name, &free2); - if (err != 0 && err != -ENOENT) { - /* not found EA in block */ - goto finish; - } else if (err == 0) { - /* found EA in block */ - where = EX_FOUND_IN_BLOCK; - } - } else - goto finish; - - /* check flags: may replace? may create ? */ - if (where && (flags & XATTR_CREATE)) { - err = -EEXIST; - goto finish; - } else if (!where && (flags & XATTR_REPLACE)) { - err = -ENODATA; - goto finish; - } - - /* check if we have enough space to store attribute */ - total = EXT3_XATTR_LEN(strlen(name)) + value_len; - if (total > free1 && free2 > 0 && total > free2) { - /* have no enough space */ - err = -ENOSPC; - goto finish; - } - - /* there are two cases when we want to remove EA from original storage: - * a) EA is stored in the inode, but new value doesn't fit - * b) EA is stored in the block, but new value fit in inode - */ - if (where == EX_FOUND_IN_IBODY && total > free1) - ext3_xattr_ibody_set(handle, inode, name_index, name, - NULL, 0, flags); - else if (where == EX_FOUND_IN_BLOCK && total <= free1) - ext3_xattr_block_set(handle, inode, name_index, - name, NULL, 0, flags); - - /* try to store EA in inode body */ - err = ext3_xattr_ibody_set(handle, inode, name_index, name, - value, value_len, flags); - if (err) { - /* can't store EA in inode body: try to store in block */ - err = ext3_xattr_block_set(handle, inode, name_index, name, - value, value_len, flags); - } - -finish: - up_write(&EXT3_I(inode)->xattr_sem); - return err; -} - /* * ext3_xattr_block_set() * * this routine add/remove/replace attribute in EA block */ -int +static int ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, const char *name, const void *value, size_t value_len, int flags) @@ -1205,6 +1104,107 @@ cleanup: return error; } +/* + * ext3_xattr_set_handle() + * + * Create, replace or remove an extended attribute for this inode. Buffer + * is NULL to remove an existing extended attribute, and non-NULL to + * either replace an existing extended attribute, or create a new extended + * attribute. The flags XATTR_REPLACE and XATTR_CREATE + * specify that an extended attribute must exist and must not exist + * previous to the call, respectively. + * + * Returns 0, or a negative error number on failure. + */ +int +ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, + const char *name, const void *value, size_t value_len, + int flags) +{ + int free1 = -1, free2 = -1; + int err, where = 0, total; + int name_len; + + ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", + name_index, name, value, (long)value_len); + + if (IS_RDONLY(inode)) + return -EROFS; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + return -EPERM; + if (value == NULL) + value_len = 0; + if (name == NULL) + return -EINVAL; + name_len = strlen(name); + if (name_len > 255 || value_len > inode->i_sb->s_blocksize) + return -ERANGE; + down_write(&EXT3_I(inode)->xattr_sem); + +#define EX_FOUND_IN_IBODY 1 +#define EX_FOUND_IN_BLOCK 2 + + /* try to find attribute in inode body */ + err = ext3_xattr_ibody_find(inode, name_index, name, &free1); + if (err == 0) { + /* found EA in inode */ + where = EX_FOUND_IN_IBODY; + } else if (err == -ENOENT) { + /* there is no such attribute in inode body */ + /* try to find attribute in dedicated block */ + err = ext3_xattr_block_find(inode, name_index, name, &free2); + if (err != 0 && err != -ENOENT) { + /* not found EA in block */ + goto finish; + } else if (err == 0) { + /* found EA in block */ + where = EX_FOUND_IN_BLOCK; + } + } else + goto finish; + + /* check flags: may replace? may create ? */ + if (where && (flags & XATTR_CREATE)) { + err = -EEXIST; + goto finish; + } else if (!where && (flags & XATTR_REPLACE)) { + err = -ENODATA; + goto finish; + } + + /* check if we have enough space to store attribute */ + total = EXT3_XATTR_LEN(strlen(name)) + value_len; + if (total > free1 && free2 > 0 && total > free2) { + /* have no enough space */ + err = -ENOSPC; + goto finish; + } + + /* there are two cases when we want to remove EA from original storage: + * a) EA is stored in the inode, but new value doesn't fit + * b) EA is stored in the block, but new value fit in inode + */ + if (where == EX_FOUND_IN_IBODY && total > free1) + ext3_xattr_ibody_set(handle, inode, name_index, name, + NULL, 0, flags); + else if (where == EX_FOUND_IN_BLOCK && total <= free1) + ext3_xattr_block_set(handle, inode, name_index, + name, NULL, 0, flags); + + /* try to store EA in inode body */ + err = ext3_xattr_ibody_set(handle, inode, name_index, name, + value, value_len, flags); + if (err) { + /* can't store EA in inode body: try to store in block */ + err = ext3_xattr_block_set(handle, inode, name_index, name, + value, value_len, flags); + } + +finish: + up_write(&EXT3_I(inode)->xattr_sem); + return err; +} + /* * Second half of ext3_xattr_set_handle(): Update the file system. */ diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index b677cf7ac568..b2b25ad82451 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -65,10 +65,8 @@ extern struct xattr_handler ext3_xattr_security_handler; extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -extern int ext3_xattr_list(struct inode *, char *, size_t); extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *,const void *,size_t,int); -extern int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,const void *,size_t,int); extern void ext3_xattr_delete_inode(handle_t *, struct inode *); extern void ext3_xattr_put_super(struct super_block *); @@ -87,12 +85,6 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name, return -EOPNOTSUPP; } -static inline int -ext3_xattr_list(struct inode *inode, void *buffer, size_t size) -{ - return -EOPNOTSUPP; -} - static inline int ext3_xattr_set(struct inode *inode, int name_index, const char *name, const void *value, size_t size, int flags) diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index a45400d0a2f4..2789be67fbe9 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -793,25 +793,15 @@ extern void ext3_error (struct super_block *, const char *, const char *, ...) extern void __ext3_std_error (struct super_block *, const char *, int); extern void ext3_abort (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); -extern NORET_TYPE void ext3_panic (struct super_block *, const char *, - const char *, ...) - __attribute__ ((NORET_AND format (printf, 3, 4))); extern void ext3_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); extern void ext3_update_dynamic_rev (struct super_block *sb); -extern void ext3_put_super (struct super_block *); -extern void ext3_write_super (struct super_block *); -extern void ext3_write_super_lockfs (struct super_block *); -extern void ext3_unlockfs (struct super_block *); -extern int ext3_remount (struct super_block *, int *, char *); -extern int ext3_statfs (struct super_block *, struct kstatfs *); #define ext3_std_error(sb, errno) \ do { \ if ((errno)) \ __ext3_std_error((sb), __FUNCTION__, (errno)); \ } while (0) -extern const char *ext3_decode_error(struct super_block *sb, int errno, char nbuf[16]); /* * Inodes and files operations diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h index 0380c1fbdab0..47445f93d4f7 100644 --- a/include/linux/ext3_jbd.h +++ b/include/linux/ext3_jbd.h @@ -46,8 +46,6 @@ EXT3_XATTR_TRANS_BLOCKS - 2 + \ 2*EXT3_QUOTA_TRANS_BLOCKS) -extern int ext3_writepage_trans_blocks(struct inode *inode); - /* Delete operations potentially hit one directory's namespace plus an * entire inode, plus arbitrary amounts of bitmap/indirection data. Be * generous. We can grow the delete transaction later if necessary. */ -- cgit v1.2.3 From 111b88bf399406586f780f53c4b5e6d142a30bc4 Mon Sep 17 00:00:00 2001 From: "Andries E. Brouwer" Date: Mon, 10 Jan 2005 17:25:53 -0800 Subject: [PATCH] remove NR_SUPER define Last month I removed the "or too many mounted filesystems" part from an error message in mount(8) - NR_SUPER has not been used in a very long time. Also NR_RESERVED_FILES is unused today. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index 31391d59ddc2..aa7abb112dbc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -68,8 +68,6 @@ extern int dir_notify_enable; #endif #define NR_FILE 8192 /* this can well be larger on a larger system */ -#define NR_RESERVED_FILES 10 /* reserved for root */ -#define NR_SUPER 256 #define MAY_EXEC 1 #define MAY_WRITE 2 -- cgit v1.2.3 From e926095b7dd6e715d931486f16a85250807dae64 Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Mon, 10 Jan 2005 17:26:36 -0800 Subject: [PATCH] coda: bounds checking This patch adds bounds checks for tainted scalars (reported by Brian Fulton and Ted Unangst, Coverity Inc.). Signed-off-by: Jan Harkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/coda/upcall.c | 26 +++++++++++++++++++------- include/linux/coda.h | 4 ++-- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 569e144c661a..5ac4985bfe05 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -555,6 +555,11 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid, goto exit; } + if (data->vi.out_size > VC_MAXDATASIZE) { + error = -EINVAL; + goto exit; + } + inp->coda_ioctl.VFid = *fid; /* the cmd field was mutated by increasing its size field to @@ -583,19 +588,26 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid, error, coda_f2s(fid)); goto exit; } + + if (outsize < (long)outp->coda_ioctl.data + outp->coda_ioctl.len) { + error = -EINVAL; + goto exit; + } /* Copy out the OUT buffer. */ if (outp->coda_ioctl.len > data->vi.out_size) { error = -EINVAL; - } else { - if (copy_to_user(data->vi.out, - (char *)outp + (long)outp->coda_ioctl.data, - data->vi.out_size)) { - error = -EFAULT; - goto exit; - } + goto exit; } + /* Copy out the OUT buffer. */ + if (copy_to_user(data->vi.out, + (char *)outp + (long)outp->coda_ioctl.data, + outp->coda_ioctl.len)) { + error = -EFAULT; + goto exit; + } + exit: CODA_FREE(inp, insize); return error; diff --git a/include/linux/coda.h b/include/linux/coda.h index 309cbbe35e67..bbc5afcd7db6 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h @@ -761,8 +761,8 @@ union coda_downcalls { struct ViceIoctl { void __user *in; /* Data to be transferred in */ void __user *out; /* Data to be transferred out */ - short in_size; /* Size of input buffer <= 2K */ - short out_size; /* Maximum size of output buffer, <= 2K */ + u_short in_size; /* Size of input buffer <= 2K */ + u_short out_size; /* Maximum size of output buffer, <= 2K */ }; struct PioctlData { -- cgit v1.2.3 From fa34aea6ccc56aea96b2a531436508f2790d17e7 Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Mon, 10 Jan 2005 17:27:05 -0800 Subject: [PATCH] coda: make global code static The patch below makes some needlessly global code static. Signed-off-by: Adrian Bunk Signed-off-by: Jan Harkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/coda/cnode.c | 2 +- fs/coda/dir.c | 2 +- fs/coda/file.c | 2 +- fs/coda/inode.c | 2 +- fs/coda/sysctl.c | 56 ++++++++++++++++++++++++----------------------- include/linux/coda_proc.h | 21 ------------------ 6 files changed, 33 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 6bf72ebb1c57..23aeef5aa814 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -11,7 +11,7 @@ #include #include -inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) +static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) { return memcmp(fid1, fid2, sizeof(*fid1)) == 0; } diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 7397d7c93bd4..5e84f907cb73 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -55,7 +55,7 @@ int coda_fsync(struct file *, struct dentry *dentry, int datasync); int coda_hasmknod; -struct dentry_operations coda_dentry_operations = +static struct dentry_operations coda_dentry_operations = { .d_revalidate = coda_dentry_revalidate, .d_delete = coda_dentry_delete, diff --git a/fs/coda/file.c b/fs/coda/file.c index 960bda823d58..e6bc022568f3 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -26,7 +26,7 @@ /* if CODA_STORE fails with EOPNOTSUPP, venus clearly doesn't support * CODA_STORE/CODA_RELEASE and we fall back on using the CODA_CLOSE upcall */ -int use_coda_close; +static int use_coda_close; static ssize_t coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *ppos) diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 6a891bfc01de..04a73fb4848f 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -89,7 +89,7 @@ static int coda_remount(struct super_block *sb, int *flags, char *data) } /* exported operations */ -struct super_operations coda_super_operations = +static struct super_operations coda_super_operations = { .alloc_inode = coda_alloc_inode, .destroy_inode = coda_destroy_inode, diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 5b71f47e27dd..f0b10757288f 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -41,35 +41,22 @@ static struct ctl_table_header *fs_table_header; #define CODA_CACHE_INV 9 /* cache invalidation statistics */ #define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */ -static ctl_table coda_table[] = { - {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, - {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, - {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, - {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, - {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec}, - { 0 } -}; - -static ctl_table fs_table[] = { - {FS_CODA, "coda", NULL, 0, 0555, coda_table}, - {0} -}; - struct coda_vfs_stats coda_vfs_stat; -struct coda_cache_inv_stats coda_cache_inv_stat; +static struct coda_cache_inv_stats coda_cache_inv_stat; -void reset_coda_vfs_stats( void ) +static void reset_coda_vfs_stats( void ) { memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) ); } -void reset_coda_cache_inv_stats( void ) +static void reset_coda_cache_inv_stats( void ) { memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) ); } -int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, - void __user * buffer, size_t * lenp, loff_t * ppos ) +static int do_reset_coda_vfs_stats( ctl_table * table, int write, + struct file * filp, void __user * buffer, + size_t * lenp, loff_t * ppos ) { if ( write ) { reset_coda_vfs_stats(); @@ -82,9 +69,10 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, return 0; } -int do_reset_coda_cache_inv_stats( ctl_table * table, int write, - struct file * filp, void __user * buffer, - size_t * lenp, loff_t * ppos ) +static int do_reset_coda_cache_inv_stats( ctl_table * table, int write, + struct file * filp, + void __user * buffer, + size_t * lenp, loff_t * ppos ) { if ( write ) { reset_coda_cache_inv_stats(); @@ -97,8 +85,8 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write, return 0; } -int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, - int length) +static int coda_vfs_stats_get_info( char * buffer, char ** start, + off_t offset, int length) { int len=0; off_t begin; @@ -158,8 +146,8 @@ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, return len; } -int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, - int length) +static int coda_cache_inv_stats_get_info( char * buffer, char ** start, + off_t offset, int length) { int len=0; off_t begin; @@ -196,6 +184,20 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, return len; } +static ctl_table coda_table[] = { + {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, + {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, + {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, + {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, + {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec}, + { 0 } +}; + +static ctl_table fs_table[] = { + {FS_CODA, "coda", NULL, 0, 0555, coda_table}, + {0} +}; + #ifdef CONFIG_PROC_FS @@ -207,7 +209,7 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, */ -struct proc_dir_entry* proc_fs_coda; +static struct proc_dir_entry* proc_fs_coda; #endif diff --git a/include/linux/coda_proc.h b/include/linux/coda_proc.h index c061a22ed86d..0dc1b0458e75 100644 --- a/include/linux/coda_proc.h +++ b/include/linux/coda_proc.h @@ -72,26 +72,5 @@ struct coda_cache_inv_stats /* these global variables hold the actual statistics data */ extern struct coda_vfs_stats coda_vfs_stat; -extern struct coda_cache_inv_stats coda_cache_inv_stat; - -/* reset statistics to 0 */ -void reset_coda_vfs_stats( void ); -void reset_coda_cache_inv_stats( void ); - -/* like coda_dointvec, these functions are to be registered in the ctl_table - * data structure for /proc/sys/... files - */ -int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, - void __user * buffer, size_t * lenp, loff_t * ppos ); -int do_reset_coda_cache_inv_stats( ctl_table * table, int write, - struct file * filp, void __user * buffer, - size_t * lenp, loff_t * ppos ); - -/* these functions are called to form the content of /proc/fs/coda/... files */ -int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, - int length); -int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, - int length); - #endif /* _CODA_PROC_H */ -- cgit v1.2.3 From ffd4550426f416fa430ddf5e303c66d504ccf9e4 Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Mon, 10 Jan 2005 17:27:21 -0800 Subject: [PATCH] coda: remove unused coda_mknod Remove coda_mknod as the code was never used, coda_hasmknod was always 0. (reported by Adrian Bunk) Signed-off-by: Jan Harkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/coda/dir.c | 58 +++++++--------------------------------------- fs/coda/upcall.c | 3 +-- include/linux/coda_psdev.h | 2 +- 3 files changed, 10 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 5e84f907cb73..2391766e9c7c 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -29,7 +29,6 @@ /* dir inode-ops */ static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd); -static int coda_mknod(struct inode *dir, struct dentry *new, int mode, dev_t rdev); static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd); static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, struct dentry *entry); @@ -53,7 +52,12 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir, void *dirent, struct dentry *dir); int coda_fsync(struct file *, struct dentry *dentry, int datasync); -int coda_hasmknod; +/* same as fs/bad_inode.c */ +static int coda_return_EIO(void) +{ + return -EIO; +} +#define CODA_EIO_ERROR ((void *) (coda_return_EIO)) static struct dentry_operations coda_dentry_operations = { @@ -70,7 +74,7 @@ struct inode_operations coda_dir_inode_operations = .symlink = coda_symlink, .mkdir = coda_mkdir, .rmdir = coda_rmdir, - .mknod = coda_mknod, + .mknod = CODA_EIO_ERROR, .rename = coda_rename, .permission = coda_permission, .getattr = coda_getattr, @@ -208,7 +212,7 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na } error = venus_create(dir->i_sb, coda_i2f(dir), name, length, - 0, mode, 0, &newfid, &attrs); + 0, mode, &newfid, &attrs); if ( error ) { unlock_kernel(); @@ -230,52 +234,6 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode, struct na return 0; } -static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev) -{ - int error=0; - const char *name=de->d_name.name; - int length=de->d_name.len; - struct inode *inode; - struct CodaFid newfid; - struct coda_vattr attrs; - - if ( coda_hasmknod == 0 ) - return -EIO; - - if (!old_valid_dev(rdev)) - return -EINVAL; - - lock_kernel(); - coda_vfs_stat.create++; - - if (coda_isroot(dir) && coda_iscontrol(name, length)) { - unlock_kernel(); - return -EPERM; - } - - error = venus_create(dir->i_sb, coda_i2f(dir), name, length, - 0, mode, rdev, &newfid, &attrs); - - if ( error ) { - unlock_kernel(); - d_drop(de); - return error; - } - - inode = coda_iget(dir->i_sb, &newfid, &attrs); - if ( IS_ERR(inode) ) { - unlock_kernel(); - d_drop(de); - return PTR_ERR(inode); - } - - /* invalidate the directory cnode's attributes */ - coda_dir_changed(dir, 0); - unlock_kernel(); - d_instantiate(de, inode); - return 0; -} - static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) { struct inode *inode; diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 5ac4985bfe05..107dbfae7d13 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -331,7 +331,7 @@ int venus_rename(struct super_block *sb, struct CodaFid *old_fid, } int venus_create(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length, int excl, int mode, dev_t rdev, + const char *name, int length, int excl, int mode, struct CodaFid *newfid, struct coda_vattr *attrs) { union inputArgs *inp; @@ -345,7 +345,6 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid, inp->coda_create.VFid = *dirfid; inp->coda_create.attr.va_mode = mode; - inp->coda_create.attr.va_rdev = huge_encode_dev(rdev); inp->coda_create.excl = excl; inp->coda_create.mode = mode; inp->coda_create.name = offset; diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h index 0c767ffd6a0d..d539262a8f89 100644 --- a/include/linux/coda_psdev.h +++ b/include/linux/coda_psdev.h @@ -49,7 +49,7 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length, struct CodaFid *newfid, struct coda_vattr *attrs); int venus_create(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length, int excl, int mode, dev_t rdev, + const char *name, int length, int excl, int mode, struct CodaFid *newfid, struct coda_vattr *attrs) ; int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length); -- cgit v1.2.3 From 5e2a73373ab4ad14fec0a8a5e2e2c175b10d732d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 10 Jan 2005 23:49:52 -0800 Subject: [IA64-SGI] fix bogus address dereference in sn/setup.c Some code in sn/setup.c was trying to dereference a physical address, which usually doesn't work (esp. not with the region register init patch I posted). This patch converts the function used to find the klconfig to return virtual char * instead of a physical address and updates the caller to deal with it. Signed-off-by: Jesse Barnes Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/setup.c | 8 ++++---- include/asm-ia64/sn/sn_sal.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 92171c00fbce..aa87b33c9d2e 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -505,15 +505,15 @@ static void __init scan_for_ionodes(void) /* Setup ionodes with memory */ for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { - u64 klgraph_header; + char *klgraph_header; cnodeid_t cnodeid; if (physical_node_map[nasid] == -1) continue; - klgraph_header = cnodeid = -1; - klgraph_header = ia64_sn_get_klconfig_addr(nasid); - if (klgraph_header <= 0) { + cnodeid = -1; + klgraph_header = __va(ia64_sn_get_klconfig_addr(nasid)); + if (!klgraph_header) { if (IS_RUNNING_ON_SIMULATOR()) continue; BUG(); /* All nodes must have klconfig tables! */ diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 0d65837b8b03..347bbe6a0af0 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -203,7 +203,7 @@ ia64_sn_get_master_baseio_nasid(void) return ret_stuff.v0; } -static inline u64 +static inline char * ia64_sn_get_klconfig_addr(nasid_t nasid) { struct ia64_sal_retval ret_stuff; @@ -223,7 +223,7 @@ ia64_sn_get_klconfig_addr(nasid_t nasid) if (ret_stuff.status != 0) { panic("ia64_sn_get_klconfig_addr: Returned error %lx\n", ret_stuff.status); } - return(ret_stuff.v0); + return ret_stuff.v0 ? __va(ret_stuff.v0) : NULL; } /* -- cgit v1.2.3 From 0a71336b6a8858a525007c5b4e0d14ba57f9f315 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 11 Jan 2005 01:40:38 -0800 Subject: [PATCH] cputime: introduce cputime This patch introduces the concept of (virtual) cputime. Each architecture can define its method to measure cputime. The main idea is to define a cputime_t type and a set of operations on it (see asm-generic/cputime.h). Then use the type for utime, stime, cutime, cstime, it_virt_value, it_virt_incr, it_prof_value and it_prof_incr and use the cputime operations for each access to these variables. The default implementation is jiffies based and the effect of this patch for architectures which use the default implementation should be neglectible. There is a second type cputime64_t which is necessary for the kernel_stat cpu statistics. The default cputime_t is 32 bit and based on HZ, this will overflow after 49.7 days. This is not enough for kernel_stat (ihmo not enough for a processes too), so it is necessary to have a 64 bit type. The third thing that gets introduced by this patch is an additional field for the /proc/stat interface: cpu steal time. An architecture can account cpu steal time by calls to the account_stealtime function. The cpu which backs a virtual processor doesn't spent all of its time for the virtual cpu. To get meaningful cpu usage numbers this involuntary wait time needs to be accounted and exported to user space. From: Hugh Dickins The p->signal check in account_system_time is insufficient. If the timer interrupt hits near the end of exit_notify, after EXIT_ZOMBIE has been set, another cpu may release_task (NULLifying p->signal) in between account_system_time's check and check_rlimit's dereference. Nor should account_it_prof risk send_sig. But surely account_user_time is safe? Signed-off-by: Hugh Dickins Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/parisc/kernel/binfmt_elf32.c | 6 +- arch/ppc64/kernel/binfmt_elf32.c | 6 +- arch/s390/kernel/binfmt_elf32.c | 6 +- arch/sparc64/kernel/binfmt_elf32.c | 6 +- fs/binfmt_elf.c | 12 +-- fs/proc/array.c | 22 ++--- fs/proc/proc_misc.c | 60 +++++++------ include/asm-alpha/cputime.h | 6 ++ include/asm-arm/cputime.h | 6 ++ include/asm-arm26/cputime.h | 6 ++ include/asm-cris/cputime.h | 6 ++ include/asm-generic/cputime.h | 64 ++++++++++++++ include/asm-h8300/cputime.h | 6 ++ include/asm-i386/cputime.h | 6 ++ include/asm-ia64/cputime.h | 6 ++ include/asm-m32r/cputime.h | 6 ++ include/asm-m68k/cputime.h | 6 ++ include/asm-m68knommu/cputime.h | 6 ++ include/asm-mips/cputime.h | 6 ++ include/asm-parisc/cputime.h | 6 ++ include/asm-ppc/cputime.h | 6 ++ include/asm-ppc64/cputime.h | 6 ++ include/asm-s390/cputime.h | 6 ++ include/asm-sh/cputime.h | 6 ++ include/asm-sh64/cputime.h | 6 ++ include/asm-sparc/cputime.h | 6 ++ include/asm-sparc64/cputime.h | 6 ++ include/asm-um/cputime.h | 6 ++ include/asm-v850/cputime.h | 6 ++ include/asm-x86_64/cputime.h | 6 ++ include/linux/kernel_stat.h | 20 +++-- include/linux/sched.h | 12 +-- kernel/compat.c | 14 ++-- kernel/cpu.c | 4 +- kernel/exit.c | 18 ++-- kernel/fork.c | 14 ++-- kernel/itimer.c | 57 +++++++------ kernel/sched.c | 168 +++++++++++++++++++++++++++++++------ kernel/signal.c | 14 ++-- kernel/sys.c | 34 ++++---- kernel/timer.c | 65 ++------------ mm/oom_kill.c | 3 +- 42 files changed, 523 insertions(+), 214 deletions(-) create mode 100644 include/asm-alpha/cputime.h create mode 100644 include/asm-arm/cputime.h create mode 100644 include/asm-arm26/cputime.h create mode 100644 include/asm-cris/cputime.h create mode 100644 include/asm-generic/cputime.h create mode 100644 include/asm-h8300/cputime.h create mode 100644 include/asm-i386/cputime.h create mode 100644 include/asm-ia64/cputime.h create mode 100644 include/asm-m32r/cputime.h create mode 100644 include/asm-m68k/cputime.h create mode 100644 include/asm-m68knommu/cputime.h create mode 100644 include/asm-mips/cputime.h create mode 100644 include/asm-parisc/cputime.h create mode 100644 include/asm-ppc/cputime.h create mode 100644 include/asm-ppc64/cputime.h create mode 100644 include/asm-s390/cputime.h create mode 100644 include/asm-sh/cputime.h create mode 100644 include/asm-sh64/cputime.h create mode 100644 include/asm-sparc/cputime.h create mode 100644 include/asm-sparc64/cputime.h create mode 100644 include/asm-um/cputime.h create mode 100644 include/asm-v850/cputime.h create mode 100644 include/asm-x86_64/cputime.h (limited to 'include') diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c index 4486a745b0ef..6fd07e90aad7 100644 --- a/arch/parisc/kernel/binfmt_elf32.c +++ b/arch/parisc/kernel/binfmt_elf32.c @@ -92,10 +92,12 @@ struct elf_prpsinfo32 current->thread.map_base = DEFAULT_MAP_BASE32; \ current->thread.task_size = DEFAULT_TASK_SIZE32 \ -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c index 478e5fce6be1..fadc699a0497 100644 --- a/arch/ppc64/kernel/binfmt_elf32.c +++ b/arch/ppc64/kernel/binfmt_elf32.c @@ -60,10 +60,12 @@ struct elf_prpsinfo32 #include -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 1100c409b5bb..ed234bf06d1c 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -197,10 +197,12 @@ MODULE_AUTHOR("Gerhard Tonn "); #undef MODULE_DESCRIPTION #undef MODULE_AUTHOR -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index c13eaf030758..a1a12d2aa353 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -132,10 +132,12 @@ struct elf_prpsinfo32 #include -#define jiffies_to_timeval jiffies_to_compat_timeval +#undef cputime_to_timeval +#define cputime_to_timeval cputime_to_compat_timeval static __inline__ void -jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { + unsigned long jiffies = cputime_to_jiffies(cputime); value->tv_usec = (jiffies % HZ) * (1000000L / HZ); value->tv_sec = jiffies / HZ; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 0ecc44fb0551..eaa2c7026e60 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1215,16 +1215,16 @@ static void fill_prstatus(struct elf_prstatus *prstatus, * this and each other thread to finish dying after the * core dump synchronization phase. */ - jiffies_to_timeval(p->utime + p->signal->utime, + cputime_to_timeval(cputime_add(p->utime, p->signal->utime), &prstatus->pr_utime); - jiffies_to_timeval(p->stime + p->signal->stime, + cputime_to_timeval(cputime_add(p->stime, p->signal->stime), &prstatus->pr_stime); } else { - jiffies_to_timeval(p->utime, &prstatus->pr_utime); - jiffies_to_timeval(p->stime, &prstatus->pr_stime); + cputime_to_timeval(p->utime, &prstatus->pr_utime); + cputime_to_timeval(p->stime, &prstatus->pr_stime); } - jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime); - jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime); + cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime); + cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime); } static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, diff --git a/fs/proc/array.c b/fs/proc/array.c index e4bd14aa005d..eb5c084ede4a 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -313,8 +313,9 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) int num_threads = 0; struct mm_struct *mm; unsigned long long start_time; - unsigned long cmin_flt = 0, cmaj_flt = 0, cutime = 0, cstime = 0; - unsigned long min_flt = 0, maj_flt = 0, utime = 0, stime = 0; + unsigned long cmin_flt = 0, cmaj_flt = 0; + unsigned long min_flt = 0, maj_flt = 0; + cputime_t cutime, cstime, utime, stime; unsigned long rsslim = 0; struct task_struct *t; char tcomm[sizeof(task->comm)]; @@ -332,6 +333,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) sigemptyset(&sigign); sigemptyset(&sigcatch); + cutime = cstime = utime = stime = cputime_zero; read_lock(&tasklist_lock); if (task->sighand) { spin_lock_irq(&task->sighand->siglock); @@ -344,8 +346,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) do { min_flt += t->min_flt; maj_flt += t->maj_flt; - utime += t->utime; - stime += t->stime; + utime = cputime_add(utime, t->utime); + stime = cputime_add(stime, t->stime); t = next_thread(t); } while (t != task); } @@ -367,8 +369,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) if (whole) { min_flt += task->signal->min_flt; maj_flt += task->signal->maj_flt; - utime += task->signal->utime; - stime += task->signal->stime; + utime = cputime_add(utime, task->signal->utime); + stime = cputime_add(stime, task->signal->stime); } } ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; @@ -411,10 +413,10 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) cmin_flt, maj_flt, cmaj_flt, - jiffies_to_clock_t(utime), - jiffies_to_clock_t(stime), - jiffies_to_clock_t(cutime), - jiffies_to_clock_t(cstime), + cputime_to_clock_t(utime), + cputime_to_clock_t(stime), + cputime_to_clock_t(cutime), + cputime_to_clock_t(cstime), priority, nice, num_threads, diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index c7322cfefe13..89d09007df5d 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -101,10 +101,10 @@ static int uptime_read_proc(char *page, char **start, off_t off, struct timespec uptime; struct timespec idle; int len; - u64 idle_jiffies = init_task.utime + init_task.stime; + cputime_t idletime = cputime_add(init_task.utime, init_task.stime); do_posix_clock_monotonic_gettime(&uptime); - jiffies_to_timespec(idle_jiffies, &idle); + cputime_to_timespec(idletime, &idle); len = sprintf(page,"%lu.%02lu %lu.%02lu\n", (unsigned long) uptime.tv_sec, (uptime.tv_nsec / (NSEC_PER_SEC / 100)), @@ -322,9 +322,11 @@ static int show_stat(struct seq_file *p, void *v) { int i; unsigned long jif; - u64 sum = 0, user = 0, nice = 0, system = 0, - idle = 0, iowait = 0, irq = 0, softirq = 0; + cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; + u64 sum = 0; + user = nice = system = idle = iowait = + irq = softirq = steal = cputime64_zero; jif = - wall_to_monotonic.tv_sec; if (wall_to_monotonic.tv_nsec) --jif; @@ -332,25 +334,27 @@ static int show_stat(struct seq_file *p, void *v) for_each_cpu(i) { int j; - user += kstat_cpu(i).cpustat.user; - nice += kstat_cpu(i).cpustat.nice; - system += kstat_cpu(i).cpustat.system; - idle += kstat_cpu(i).cpustat.idle; - iowait += kstat_cpu(i).cpustat.iowait; - irq += kstat_cpu(i).cpustat.irq; - softirq += kstat_cpu(i).cpustat.softirq; + user = cputime64_add(user, kstat_cpu(i).cpustat.user); + nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice); + system = cputime64_add(system, kstat_cpu(i).cpustat.system); + idle = cputime64_add(idle, kstat_cpu(i).cpustat.idle); + iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait); + irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq); + softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); + steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); for (j = 0 ; j < NR_IRQS ; j++) sum += kstat_cpu(i).irqs[j]; } - seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu\n", - (unsigned long long)jiffies_64_to_clock_t(user), - (unsigned long long)jiffies_64_to_clock_t(nice), - (unsigned long long)jiffies_64_to_clock_t(system), - (unsigned long long)jiffies_64_to_clock_t(idle), - (unsigned long long)jiffies_64_to_clock_t(iowait), - (unsigned long long)jiffies_64_to_clock_t(irq), - (unsigned long long)jiffies_64_to_clock_t(softirq)); + seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n", + (unsigned long long)cputime64_to_clock_t(user), + (unsigned long long)cputime64_to_clock_t(nice), + (unsigned long long)cputime64_to_clock_t(system), + (unsigned long long)cputime64_to_clock_t(idle), + (unsigned long long)cputime64_to_clock_t(iowait), + (unsigned long long)cputime64_to_clock_t(irq), + (unsigned long long)cputime64_to_clock_t(softirq), + (unsigned long long)cputime64_to_clock_t(steal)); for_each_online_cpu(i) { /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ @@ -361,15 +365,17 @@ static int show_stat(struct seq_file *p, void *v) iowait = kstat_cpu(i).cpustat.iowait; irq = kstat_cpu(i).cpustat.irq; softirq = kstat_cpu(i).cpustat.softirq; - seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu\n", + steal = kstat_cpu(i).cpustat.steal; + seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu\n", i, - (unsigned long long)jiffies_64_to_clock_t(user), - (unsigned long long)jiffies_64_to_clock_t(nice), - (unsigned long long)jiffies_64_to_clock_t(system), - (unsigned long long)jiffies_64_to_clock_t(idle), - (unsigned long long)jiffies_64_to_clock_t(iowait), - (unsigned long long)jiffies_64_to_clock_t(irq), - (unsigned long long)jiffies_64_to_clock_t(softirq)); + (unsigned long long)cputime64_to_clock_t(user), + (unsigned long long)cputime64_to_clock_t(nice), + (unsigned long long)cputime64_to_clock_t(system), + (unsigned long long)cputime64_to_clock_t(idle), + (unsigned long long)cputime64_to_clock_t(iowait), + (unsigned long long)cputime64_to_clock_t(irq), + (unsigned long long)cputime64_to_clock_t(softirq), + (unsigned long long)cputime64_to_clock_t(steal)); } seq_printf(p, "intr %llu", (unsigned long long)sum); diff --git a/include/asm-alpha/cputime.h b/include/asm-alpha/cputime.h new file mode 100644 index 000000000000..19577fd93230 --- /dev/null +++ b/include/asm-alpha/cputime.h @@ -0,0 +1,6 @@ +#ifndef __ALPHA_CPUTIME_H +#define __ALPHA_CPUTIME_H + +#include + +#endif /* __ALPHA_CPUTIME_H */ diff --git a/include/asm-arm/cputime.h b/include/asm-arm/cputime.h new file mode 100644 index 000000000000..3a8002a5fec7 --- /dev/null +++ b/include/asm-arm/cputime.h @@ -0,0 +1,6 @@ +#ifndef __ARM_CPUTIME_H +#define __ARM_CPUTIME_H + +#include + +#endif /* __ARM_CPUTIME_H */ diff --git a/include/asm-arm26/cputime.h b/include/asm-arm26/cputime.h new file mode 100644 index 000000000000..d2783a9e47b3 --- /dev/null +++ b/include/asm-arm26/cputime.h @@ -0,0 +1,6 @@ +#ifndef __ARM26_CPUTIME_H +#define __ARM26_CPUTIME_H + +#include + +#endif /* __ARM26_CPUTIME_H */ diff --git a/include/asm-cris/cputime.h b/include/asm-cris/cputime.h new file mode 100644 index 000000000000..4446a65656fa --- /dev/null +++ b/include/asm-cris/cputime.h @@ -0,0 +1,6 @@ +#ifndef __CRIS_CPUTIME_H +#define __CRIS_CPUTIME_H + +#include + +#endif /* __CRIS_CPUTIME_H */ diff --git a/include/asm-generic/cputime.h b/include/asm-generic/cputime.h new file mode 100644 index 000000000000..c9968a09f8ab --- /dev/null +++ b/include/asm-generic/cputime.h @@ -0,0 +1,64 @@ +#ifndef _ASM_GENERIC_CPUTIME_H +#define _ASM_GENERIC_CPUTIME_H + +#include +#include + +typedef unsigned long cputime_t; + +#define cputime_zero (0UL) +#define cputime_max ((~0UL >> 1) - 1) +#define cputime_add(__a, __b) ((__a) + (__b)) +#define cputime_sub(__a, __b) ((__a) - (__b)) +#define cputime_eq(__a, __b) ((__a) == (__b)) +#define cputime_gt(__a, __b) ((__a) > (__b)) +#define cputime_ge(__a, __b) ((__a) >= (__b)) +#define cputime_lt(__a, __b) ((__a) < (__b)) +#define cputime_le(__a, __b) ((__a) <= (__b)) +#define cputime_to_jiffies(__ct) (__ct) +#define jiffies_to_cputime(__hz) (__hz) + +typedef u64 cputime64_t; + +#define cputime64_zero (0ULL) +#define cputime64_add(__a, __b) ((__a) + (__b)) +#define cputime64_to_jiffies64(__ct) (__ct) +#define cputime_to_cputime64(__ct) ((u64) __ct) + + +/* + * Convert cputime to milliseconds and back. + */ +#define cputime_to_msecs(__ct) jiffies_to_msecs(__ct) +#define msecs_to_cputime(__msecs) msecs_to_jiffies(__msecs) + +/* + * Convert cputime to seconds and back. + */ +#define cputime_to_secs(__ct) (jiffies_to_msecs(__ct) / HZ) +#define secs_to_cputime(__secs) (msecs_to_jiffies(__secs * HZ)) + +/* + * Convert cputime to timespec and back. + */ +#define timespec_to_cputime(__val) timespec_to_jiffies(__val) +#define cputime_to_timespec(__ct,__val) jiffies_to_timespec(__ct,__val) + +/* + * Convert cputime to timeval and back. + */ +#define timeval_to_cputime(__val) timeval_to_jiffies(__val) +#define cputime_to_timeval(__ct,__val) jiffies_to_timeval(__ct,__val) + +/* + * Convert cputime to clock and back. + */ +#define cputime_to_clock_t(__ct) jiffies_to_clock_t(__ct) +#define clock_t_to_cputime(__x) clock_t_to_jiffies(__x) + +/* + * Convert cputime64 to clock. + */ +#define cputime64_to_clock_t(__ct) jiffies_64_to_clock_t(__ct) + +#endif diff --git a/include/asm-h8300/cputime.h b/include/asm-h8300/cputime.h new file mode 100644 index 000000000000..092e187c7b08 --- /dev/null +++ b/include/asm-h8300/cputime.h @@ -0,0 +1,6 @@ +#ifndef __H8300_CPUTIME_H +#define __H8300_CPUTIME_H + +#include + +#endif /* __H8300_CPUTIME_H */ diff --git a/include/asm-i386/cputime.h b/include/asm-i386/cputime.h new file mode 100644 index 000000000000..398ed7cd171d --- /dev/null +++ b/include/asm-i386/cputime.h @@ -0,0 +1,6 @@ +#ifndef __I386_CPUTIME_H +#define __I386_CPUTIME_H + +#include + +#endif /* __I386_CPUTIME_H */ diff --git a/include/asm-ia64/cputime.h b/include/asm-ia64/cputime.h new file mode 100644 index 000000000000..72400a78002a --- /dev/null +++ b/include/asm-ia64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __IA64_CPUTIME_H +#define __IA64_CPUTIME_H + +#include + +#endif /* __IA64_CPUTIME_H */ diff --git a/include/asm-m32r/cputime.h b/include/asm-m32r/cputime.h new file mode 100644 index 000000000000..0a47550df2b7 --- /dev/null +++ b/include/asm-m32r/cputime.h @@ -0,0 +1,6 @@ +#ifndef __M32R_CPUTIME_H +#define __M32R_CPUTIME_H + +#include + +#endif /* __M32R_CPUTIME_H */ diff --git a/include/asm-m68k/cputime.h b/include/asm-m68k/cputime.h new file mode 100644 index 000000000000..c79c5e892305 --- /dev/null +++ b/include/asm-m68k/cputime.h @@ -0,0 +1,6 @@ +#ifndef __M68K_CPUTIME_H +#define __M68K_CPUTIME_H + +#include + +#endif /* __M68K_CPUTIME_H */ diff --git a/include/asm-m68knommu/cputime.h b/include/asm-m68knommu/cputime.h new file mode 100644 index 000000000000..a0c4a660878d --- /dev/null +++ b/include/asm-m68knommu/cputime.h @@ -0,0 +1,6 @@ +#ifndef __M68KNOMMU_CPUTIME_H +#define __M68KNOMMU_CPUTIME_H + +#include + +#endif /* __M68KNOMMU_CPUTIME_H */ diff --git a/include/asm-mips/cputime.h b/include/asm-mips/cputime.h new file mode 100644 index 000000000000..c00eacbdd979 --- /dev/null +++ b/include/asm-mips/cputime.h @@ -0,0 +1,6 @@ +#ifndef __MIPS_CPUTIME_H +#define __MIPS_CPUTIME_H + +#include + +#endif /* __MIPS_CPUTIME_H */ diff --git a/include/asm-parisc/cputime.h b/include/asm-parisc/cputime.h new file mode 100644 index 000000000000..dcdf2fbd7e72 --- /dev/null +++ b/include/asm-parisc/cputime.h @@ -0,0 +1,6 @@ +#ifndef __PARISC_CPUTIME_H +#define __PARISC_CPUTIME_H + +#include + +#endif /* __PARISC_CPUTIME_H */ diff --git a/include/asm-ppc/cputime.h b/include/asm-ppc/cputime.h new file mode 100644 index 000000000000..8e9faf5ce720 --- /dev/null +++ b/include/asm-ppc/cputime.h @@ -0,0 +1,6 @@ +#ifndef __PPC_CPUTIME_H +#define __PPC_CPUTIME_H + +#include + +#endif /* __PPC_CPUTIME_H */ diff --git a/include/asm-ppc64/cputime.h b/include/asm-ppc64/cputime.h new file mode 100644 index 000000000000..8e9faf5ce720 --- /dev/null +++ b/include/asm-ppc64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __PPC_CPUTIME_H +#define __PPC_CPUTIME_H + +#include + +#endif /* __PPC_CPUTIME_H */ diff --git a/include/asm-s390/cputime.h b/include/asm-s390/cputime.h new file mode 100644 index 000000000000..ad989e5d369c --- /dev/null +++ b/include/asm-s390/cputime.h @@ -0,0 +1,6 @@ +#ifndef __S390_CPUTIME_H +#define __S390_CPUTIME_H + +#include + +#endif /* __S390_CPUTIME_H */ diff --git a/include/asm-sh/cputime.h b/include/asm-sh/cputime.h new file mode 100644 index 000000000000..6ca395d1393e --- /dev/null +++ b/include/asm-sh/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SH_CPUTIME_H +#define __SH_CPUTIME_H + +#include + +#endif /* __SH_CPUTIME_H */ diff --git a/include/asm-sh64/cputime.h b/include/asm-sh64/cputime.h new file mode 100644 index 000000000000..0fd89da2aa86 --- /dev/null +++ b/include/asm-sh64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SH64_CPUTIME_H +#define __SH64_CPUTIME_H + +#include + +#endif /* __SH64_CPUTIME_H */ diff --git a/include/asm-sparc/cputime.h b/include/asm-sparc/cputime.h new file mode 100644 index 000000000000..1a642b81e019 --- /dev/null +++ b/include/asm-sparc/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SPARC_CPUTIME_H +#define __SPARC_CPUTIME_H + +#include + +#endif /* __SPARC_CPUTIME_H */ diff --git a/include/asm-sparc64/cputime.h b/include/asm-sparc64/cputime.h new file mode 100644 index 000000000000..dec2fc7a36f8 --- /dev/null +++ b/include/asm-sparc64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SPARC64_CPUTIME_H +#define __SPARC64_CPUTIME_H + +#include + +#endif /* __SPARC64_CPUTIME_H */ diff --git a/include/asm-um/cputime.h b/include/asm-um/cputime.h new file mode 100644 index 000000000000..c84acbadfa2f --- /dev/null +++ b/include/asm-um/cputime.h @@ -0,0 +1,6 @@ +#ifndef __UM_CPUTIME_H +#define __UM_CPUTIME_H + +#include + +#endif /* __UM_CPUTIME_H */ diff --git a/include/asm-v850/cputime.h b/include/asm-v850/cputime.h new file mode 100644 index 000000000000..7c799c33b8a9 --- /dev/null +++ b/include/asm-v850/cputime.h @@ -0,0 +1,6 @@ +#ifndef __V850_CPUTIME_H +#define __V850_CPUTIME_H + +#include + +#endif /* __V850_CPUTIME_H */ diff --git a/include/asm-x86_64/cputime.h b/include/asm-x86_64/cputime.h new file mode 100644 index 000000000000..a07012dc5a3c --- /dev/null +++ b/include/asm-x86_64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __X86_64_CPUTIME_H +#define __X86_64_CPUTIME_H + +#include + +#endif /* __X86_64_CPUTIME_H */ diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 4594ccc4a7c1..dba27749b428 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -6,6 +6,7 @@ #include #include #include +#include /* * 'kernel_stat.h' contains the definitions needed for doing @@ -14,13 +15,14 @@ */ struct cpu_usage_stat { - u64 user; - u64 nice; - u64 system; - u64 softirq; - u64 irq; - u64 idle; - u64 iowait; + cputime64_t user; + cputime64_t nice; + cputime64_t system; + cputime64_t softirq; + cputime64_t irq; + cputime64_t idle; + cputime64_t iowait; + cputime64_t steal; }; struct kernel_stat { @@ -50,4 +52,8 @@ static inline int kstat_irqs(int irq) return sum; } +extern void account_user_time(struct task_struct *, cputime_t); +extern void account_system_time(struct task_struct *, int, cputime_t); +extern void account_steal_time(struct task_struct *, cputime_t); + #endif /* _LINUX_KERNEL_STAT_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c2c63f23a4a..dcc1814f97e8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -168,7 +169,7 @@ long io_schedule_timeout(long timeout); extern void cpu_init (void); extern void trap_init(void); extern void update_process_times(int user); -extern void scheduler_tick(int user_tick, int system); +extern void scheduler_tick(void); extern unsigned long cache_decay_ticks; /* Attach to any functions which should be ignored in wchan output. */ @@ -311,7 +312,7 @@ struct signal_struct { * Live threads maintain their own counters and add to these * in __exit_signal, except for the group leader. */ - unsigned long utime, stime, cutime, cstime; + cputime_t utime, stime, cutime, cstime; unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; @@ -589,10 +590,11 @@ struct task_struct { int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ unsigned long rt_priority; - unsigned long it_real_value, it_prof_value, it_virt_value; - unsigned long it_real_incr, it_prof_incr, it_virt_incr; + unsigned long it_real_value, it_real_incr; + cputime_t it_virt_value, it_virt_incr; + cputime_t it_prof_value, it_prof_incr; struct timer_list real_timer; - unsigned long utime, stime; + cputime_t utime, stime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ diff --git a/kernel/compat.c b/kernel/compat.c index 48ee147c1343..d1b1d4dd019a 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -163,15 +163,15 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) struct compat_tms tmp; struct task_struct *tsk = current; struct task_struct *t; - unsigned long utime, stime, cutime, cstime; + cputime_t utime, stime, cutime, cstime; read_lock(&tasklist_lock); utime = tsk->signal->utime; stime = tsk->signal->stime; t = tsk; do { - utime += t->utime; - stime += t->stime; + utime = cputime_add(utime, t->utime); + stime = cputime_add(stime, t->stime); t = next_thread(t); } while (t != tsk); @@ -190,10 +190,10 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) spin_unlock_irq(&tsk->sighand->siglock); read_unlock(&tasklist_lock); - tmp.tms_utime = compat_jiffies_to_clock_t(utime); - tmp.tms_stime = compat_jiffies_to_clock_t(stime); - tmp.tms_cutime = compat_jiffies_to_clock_t(cutime); - tmp.tms_cstime = compat_jiffies_to_clock_t(cstime); + tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime)); + tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime)); + tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime)); + tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime)); if (copy_to_user(tbuf, &tmp, sizeof(tmp))) return -EFAULT; } diff --git a/kernel/cpu.c b/kernel/cpu.c index b97f7f91ec6d..628f4ccda127 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -48,7 +48,9 @@ static inline void check_for_tasks(int cpu) write_lock_irq(&tasklist_lock); for_each_process(p) { - if (task_cpu(p) == cpu && (p->utime != 0 || p->stime != 0)) + if (task_cpu(p) == cpu && + (!cputime_eq(p->utime, cputime_zero) || + !cputime_eq(p->stime, cputime_zero))) printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\ (state = %ld, flags = %lx) \n", p->comm, p->pid, cpu, p->state, p->flags); diff --git a/kernel/exit.c b/kernel/exit.c index 02f0a95cb557..e0df301a4553 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -755,8 +755,8 @@ static void exit_notify(struct task_struct *tsk) * Clear these here so that update_process_times() won't try to deliver * itimer, profile or rlimit signals to this task while it is in late exit. */ - tsk->it_virt_value = 0; - tsk->it_prof_value = 0; + tsk->it_virt_value = cputime_zero; + tsk->it_prof_value = cputime_zero; write_unlock_irq(&tasklist_lock); @@ -1046,10 +1046,16 @@ static int wait_task_zombie(task_t *p, int noreap, * here reaping other children at the same time. */ spin_lock_irq(&p->parent->sighand->siglock); - p->parent->signal->cutime += - p->utime + p->signal->utime + p->signal->cutime; - p->parent->signal->cstime += - p->stime + p->signal->stime + p->signal->cstime; + p->parent->signal->cutime = + cputime_add(p->parent->signal->cutime, + cputime_add(p->utime, + cputime_add(p->signal->utime, + p->signal->cutime))); + p->parent->signal->cstime = + cputime_add(p->parent->signal->cstime, + cputime_add(p->stime, + cputime_add(p->signal->stime, + p->signal->cstime))); p->parent->signal->cmin_flt += p->min_flt + p->signal->min_flt + p->signal->cmin_flt; p->parent->signal->cmaj_flt += diff --git a/kernel/fork.c b/kernel/fork.c index 6d9412937d37..be1ff8ddbb9c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -749,7 +749,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts sig->leader = 0; /* session leadership doesn't inherit */ sig->tty_old_pgrp = 0; - sig->utime = sig->stime = sig->cutime = sig->cstime = 0; + sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; @@ -871,15 +871,15 @@ static task_t *copy_process(unsigned long clone_flags, p->it_real_value = 0; p->it_real_incr = 0; - p->it_virt_value = 0; - p->it_virt_incr = 0; - p->it_prof_value = 0; - p->it_prof_incr = 0; + p->it_virt_value = cputime_zero; + p->it_virt_incr = cputime_zero; + p->it_prof_value = cputime_zero; + p->it_prof_incr = cputime_zero; init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; - p->utime = 0; - p->stime = 0; + p->utime = cputime_zero; + p->stime = cputime_zero; p->rchar = 0; /* I/O counter: bytes read */ p->wchar = 0; /* I/O counter: bytes written */ p->syscr = 0; /* I/O counter: read syscalls */ diff --git a/kernel/itimer.c b/kernel/itimer.c index 95fbf1c6becf..e1743c563206 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -16,11 +16,10 @@ int do_getitimer(int which, struct itimerval *value) { - register unsigned long val, interval; + register unsigned long val; switch (which) { case ITIMER_REAL: - interval = current->it_real_incr; val = 0; /* * FIXME! This needs to be atomic, in case the kernel timer happens! @@ -32,20 +31,20 @@ int do_getitimer(int which, struct itimerval *value) if ((long) val <= 0) val = 1; } + jiffies_to_timeval(val, &value->it_value); + jiffies_to_timeval(current->it_real_incr, &value->it_interval); break; case ITIMER_VIRTUAL: - val = current->it_virt_value; - interval = current->it_virt_incr; + cputime_to_timeval(current->it_virt_value, &value->it_value); + cputime_to_timeval(current->it_virt_incr, &value->it_interval); break; case ITIMER_PROF: - val = current->it_prof_value; - interval = current->it_prof_incr; + cputime_to_timeval(current->it_prof_value, &value->it_value); + cputime_to_timeval(current->it_prof_incr, &value->it_interval); break; default: return(-EINVAL); } - jiffies_to_timeval(val, &value->it_value); - jiffies_to_timeval(interval, &value->it_interval); return 0; } @@ -81,37 +80,43 @@ void it_real_fn(unsigned long __data) int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) { - register unsigned long i, j; + unsigned long expire; + cputime_t cputime; int k; - i = timeval_to_jiffies(&value->it_interval); - j = timeval_to_jiffies(&value->it_value); if (ovalue && (k = do_getitimer(which, ovalue)) < 0) return k; switch (which) { case ITIMER_REAL: del_timer_sync(¤t->real_timer); - current->it_real_value = j; - current->it_real_incr = i; - if (!j) + expire = timeval_to_jiffies(&value->it_value); + current->it_real_value = expire; + current->it_real_incr = + timeval_to_jiffies(&value->it_interval); + if (!expire) break; - if (j > (unsigned long) LONG_MAX) - j = LONG_MAX; - i = j + jiffies; - current->real_timer.expires = i; + if (expire > (unsigned long) LONG_MAX) + expire = LONG_MAX; + current->real_timer.expires = jiffies + expire; add_timer(¤t->real_timer); break; case ITIMER_VIRTUAL: - if (j) - j++; - current->it_virt_value = j; - current->it_virt_incr = i; + cputime = timeval_to_cputime(&value->it_value); + if (cputime_gt(cputime, cputime_zero)) + cputime = cputime_add(cputime, + jiffies_to_cputime(1)); + current->it_virt_value = cputime; + cputime = timeval_to_cputime(&value->it_interval); + current->it_virt_incr = cputime; break; case ITIMER_PROF: - if (j) - j++; - current->it_prof_value = j; - current->it_prof_incr = i; + cputime = timeval_to_cputime(&value->it_value); + if (cputime_gt(cputime, cputime_zero)) + cputime = cputime_add(cputime, + jiffies_to_cputime(1)); + current->it_prof_value = cputime; + cputime = timeval_to_cputime(&value->it_interval); + current->it_prof_incr = cputime; break; default: return -EINVAL; diff --git a/kernel/sched.c b/kernel/sched.c index 1c523337bc61..9e1fbc42bd01 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1182,7 +1182,7 @@ void fastcall sched_fork(task_t *p) */ current->time_slice = 1; preempt_disable(); - scheduler_tick(0, 0); + scheduler_tick(); local_irq_enable(); preempt_enable(); } else @@ -2250,6 +2250,148 @@ EXPORT_PER_CPU_SYMBOL(kstat); STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \ ((rq)->curr->static_prio > (rq)->best_expired_prio)) +/* + * Do the virtual cpu time signal calculations. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in user space since the last update + */ +static inline void account_it_virt(struct task_struct * p, cputime_t cputime) +{ + cputime_t it_virt = p->it_virt_value; + + if (cputime_gt(it_virt, cputime_zero) && + cputime_gt(cputime, cputime_zero)) { + if (cputime_ge(cputime, it_virt)) { + it_virt = cputime_add(it_virt, p->it_virt_incr); + send_sig(SIGVTALRM, p, 1); + } + it_virt = cputime_sub(it_virt, cputime); + p->it_virt_value = it_virt; + } +} + +/* + * Do the virtual profiling signal calculations. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in user and kernel space since the last update + */ +static void account_it_prof(struct task_struct *p, cputime_t cputime) +{ + cputime_t it_prof = p->it_prof_value; + + if (cputime_gt(it_prof, cputime_zero) && + cputime_gt(cputime, cputime_zero)) { + if (cputime_ge(cputime, it_prof)) { + it_prof = cputime_add(it_prof, p->it_prof_incr); + send_sig(SIGPROF, p, 1); + } + it_prof = cputime_sub(it_prof, cputime); + p->it_prof_value = it_prof; + } +} + +/* + * Check if the process went over its cputime resource limit after + * some cpu time got added to utime/stime. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in user and kernel space since the last update + */ +static void check_rlimit(struct task_struct *p, cputime_t cputime) +{ + cputime_t total, tmp; + + total = cputime_add(p->utime, p->stime); + tmp = jiffies_to_cputime(p->signal->rlim[RLIMIT_CPU].rlim_cur); + if (unlikely(cputime_gt(total, tmp))) { + /* Send SIGXCPU every second. */ + tmp = cputime_sub(total, cputime); + if (cputime_to_secs(tmp) < cputime_to_secs(total)) + send_sig(SIGXCPU, p, 1); + /* and SIGKILL when we go over max.. */ + tmp = jiffies_to_cputime(p->signal->rlim[RLIMIT_CPU].rlim_max); + if (cputime_gt(total, tmp)) + send_sig(SIGKILL, p, 1); + } +} + +/* + * Account user cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @hardirq_offset: the offset to subtract from hardirq_count() + * @cputime: the cpu time spent in user space since the last update + */ +void account_user_time(struct task_struct *p, cputime_t cputime) +{ + struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; + cputime64_t tmp; + + p->utime = cputime_add(p->utime, cputime); + + /* Check for signals (SIGVTALRM, SIGPROF, SIGXCPU & SIGKILL). */ + check_rlimit(p, cputime); + account_it_virt(p, cputime); + account_it_prof(p, cputime); + + /* Add user time to cpustat. */ + tmp = cputime_to_cputime64(cputime); + if (TASK_NICE(p) > 0) + cpustat->nice = cputime64_add(cpustat->nice, tmp); + else + cpustat->user = cputime64_add(cpustat->user, tmp); +} + +/* + * Account system cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @hardirq_offset: the offset to subtract from hardirq_count() + * @cputime: the cpu time spent in kernel space since the last update + */ +void account_system_time(struct task_struct *p, int hardirq_offset, + cputime_t cputime) +{ + struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; + runqueue_t *rq = this_rq(); + cputime64_t tmp; + + p->stime = cputime_add(p->stime, cputime); + + /* Check for signals (SIGPROF, SIGXCPU & SIGKILL). */ + if (likely(p->signal && p->exit_state < EXIT_ZOMBIE)) { + check_rlimit(p, cputime); + account_it_prof(p, cputime); + } + + /* Add system time to cpustat. */ + tmp = cputime_to_cputime64(cputime); + if (hardirq_count() - hardirq_offset) + cpustat->irq = cputime64_add(cpustat->irq, tmp); + else if (softirq_count()) + cpustat->softirq = cputime64_add(cpustat->softirq, tmp); + else if (p != rq->idle) + cpustat->system = cputime64_add(cpustat->system, tmp); + else if (atomic_read(&rq->nr_iowait) > 0) + cpustat->iowait = cputime64_add(cpustat->iowait, tmp); + else + cpustat->idle = cputime64_add(cpustat->idle, tmp); +} + +/* + * Account for involuntary wait time. + * @p: the process from which the cpu time has been stolen + * @steal: the cpu time spent in involuntary wait + */ +void account_steal_time(struct task_struct *p, cputime_t steal) +{ + struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; + cputime64_t steal64 = cputime_to_cputime64(steal); + runqueue_t *rq = this_rq(); + + if (p == rq->idle) + cpustat->system = cputime64_add(cpustat->system, steal64); + else + cpustat->steal = cputime64_add(cpustat->steal, steal64); +} + /* * This function gets called by the timer code, with HZ frequency. * We call it with interrupts disabled. @@ -2257,42 +2399,20 @@ EXPORT_PER_CPU_SYMBOL(kstat); * It also gets called by the fork code, when changing the parent's * timeslices. */ -void scheduler_tick(int user_ticks, int sys_ticks) +void scheduler_tick(void) { int cpu = smp_processor_id(); - struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; runqueue_t *rq = this_rq(); task_t *p = current; rq->timestamp_last_tick = sched_clock(); - if (rcu_pending(cpu)) - rcu_check_callbacks(cpu, user_ticks); - - /* note: this timer irq context must be accounted for as well */ - if (hardirq_count() - HARDIRQ_OFFSET) { - cpustat->irq += sys_ticks; - sys_ticks = 0; - } else if (softirq_count()) { - cpustat->softirq += sys_ticks; - sys_ticks = 0; - } - if (p == rq->idle) { - if (atomic_read(&rq->nr_iowait) > 0) - cpustat->iowait += sys_ticks; - else - cpustat->idle += sys_ticks; if (wake_priority_sleeper(rq)) goto out; rebalance_tick(cpu, rq, SCHED_IDLE); return; } - if (TASK_NICE(p) > 0) - cpustat->nice += user_ticks; - else - cpustat->user += user_ticks; - cpustat->system += sys_ticks; /* Task might have expired already, but not scheduled off yet */ if (p->array != rq->active) { diff --git a/kernel/signal.c b/kernel/signal.c index d800b3f97323..6d0a3bd948ab 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -375,8 +375,8 @@ void __exit_signal(struct task_struct *tsk) * We won't ever get here for the group leader, since it * will have been the last reference on the signal_struct. */ - sig->utime += tsk->utime; - sig->stime += tsk->stime; + sig->utime = cputime_add(sig->utime, tsk->utime); + sig->stime = cputime_add(sig->stime, tsk->stime); sig->min_flt += tsk->min_flt; sig->maj_flt += tsk->maj_flt; sig->nvcsw += tsk->nvcsw; @@ -1470,8 +1470,10 @@ void do_notify_parent(struct task_struct *tsk, int sig) info.si_uid = tsk->uid; /* FIXME: find out whether or not this is supposed to be c*time. */ - info.si_utime = tsk->utime + tsk->signal->utime; - info.si_stime = tsk->stime + tsk->signal->stime; + info.si_utime = cputime_to_jiffies(cputime_add(tsk->utime, + tsk->signal->utime)); + info.si_stime = cputime_to_jiffies(cputime_add(tsk->stime, + tsk->signal->stime)); info.si_status = tsk->exit_code & 0x7f; if (tsk->exit_code & 0x80) @@ -1527,8 +1529,8 @@ do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent, info.si_uid = tsk->uid; /* FIXME: find out whether or not this is supposed to be c*time. */ - info.si_utime = tsk->utime; - info.si_stime = tsk->stime; + info.si_utime = cputime_to_jiffies(tsk->utime); + info.si_stime = cputime_to_jiffies(tsk->stime); info.si_code = why; switch (why) { diff --git a/kernel/sys.c b/kernel/sys.c index 20080da0c3de..6e354fd380e7 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -893,15 +893,15 @@ asmlinkage long sys_times(struct tms __user * tbuf) struct tms tmp; struct task_struct *tsk = current; struct task_struct *t; - unsigned long utime, stime, cutime, cstime; + cputime_t utime, stime, cutime, cstime; read_lock(&tasklist_lock); utime = tsk->signal->utime; stime = tsk->signal->stime; t = tsk; do { - utime += t->utime; - stime += t->stime; + utime = cputime_add(utime, t->utime); + stime = cputime_add(stime, t->stime); t = next_thread(t); } while (t != tsk); @@ -920,10 +920,10 @@ asmlinkage long sys_times(struct tms __user * tbuf) spin_unlock_irq(&tsk->sighand->siglock); read_unlock(&tasklist_lock); - tmp.tms_utime = jiffies_to_clock_t(utime); - tmp.tms_stime = jiffies_to_clock_t(stime); - tmp.tms_cutime = jiffies_to_clock_t(cutime); - tmp.tms_cstime = jiffies_to_clock_t(cstime); + tmp.tms_utime = cputime_to_clock_t(utime); + tmp.tms_stime = cputime_to_clock_t(stime); + tmp.tms_cutime = cputime_to_clock_t(cutime); + tmp.tms_cstime = cputime_to_clock_t(cstime); if (copy_to_user(tbuf, &tmp, sizeof(struct tms))) return -EFAULT; } @@ -1528,7 +1528,7 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r) { struct task_struct *t; unsigned long flags; - unsigned long utime, stime; + cputime_t utime, stime; memset((char *) r, 0, sizeof *r); @@ -1545,12 +1545,12 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_minflt = p->signal->cmin_flt; r->ru_majflt = p->signal->cmaj_flt; spin_unlock_irqrestore(&p->sighand->siglock, flags); - jiffies_to_timeval(utime, &r->ru_utime); - jiffies_to_timeval(stime, &r->ru_stime); + cputime_to_timeval(utime, &r->ru_utime); + cputime_to_timeval(stime, &r->ru_stime); break; case RUSAGE_SELF: spin_lock_irqsave(&p->sighand->siglock, flags); - utime = stime = 0; + utime = stime = cputime_zero; goto sum_group; case RUSAGE_BOTH: spin_lock_irqsave(&p->sighand->siglock, flags); @@ -1561,16 +1561,16 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r) r->ru_minflt = p->signal->cmin_flt; r->ru_majflt = p->signal->cmaj_flt; sum_group: - utime += p->signal->utime; - stime += p->signal->stime; + utime = cputime_add(utime, p->signal->utime); + stime = cputime_add(stime, p->signal->stime); r->ru_nvcsw += p->signal->nvcsw; r->ru_nivcsw += p->signal->nivcsw; r->ru_minflt += p->signal->min_flt; r->ru_majflt += p->signal->maj_flt; t = p; do { - utime += t->utime; - stime += t->stime; + utime = cputime_add(utime, t->utime); + stime = cputime_add(stime, t->stime); r->ru_nvcsw += t->nvcsw; r->ru_nivcsw += t->nivcsw; r->ru_minflt += t->min_flt; @@ -1578,8 +1578,8 @@ void k_getrusage(struct task_struct *p, int who, struct rusage *r) t = next_thread(t); } while (t != p); spin_unlock_irqrestore(&p->sighand->siglock, flags); - jiffies_to_timeval(utime, &r->ru_utime); - jiffies_to_timeval(stime, &r->ru_stime); + cputime_to_timeval(utime, &r->ru_utime); + cputime_to_timeval(stime, &r->ru_stime); break; default: BUG(); diff --git a/kernel/timer.c b/kernel/timer.c index ec35a6e801a8..6bb47b0e4983 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -806,59 +806,6 @@ static void update_wall_time(unsigned long ticks) } while (ticks); } -static inline void do_process_times(struct task_struct *p, - unsigned long user, unsigned long system) -{ - unsigned long psecs; - - psecs = (p->utime += user); - psecs += (p->stime += system); - if (p->signal && !unlikely(p->exit_state) && - psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_cur) { - /* Send SIGXCPU every second.. */ - if (!(psecs % HZ)) - send_sig(SIGXCPU, p, 1); - /* and SIGKILL when we go over max.. */ - if (psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_max) - send_sig(SIGKILL, p, 1); - } -} - -static inline void do_it_virt(struct task_struct * p, unsigned long ticks) -{ - unsigned long it_virt = p->it_virt_value; - - if (it_virt) { - it_virt -= ticks; - if (!it_virt) { - it_virt = p->it_virt_incr; - send_sig(SIGVTALRM, p, 1); - } - p->it_virt_value = it_virt; - } -} - -static inline void do_it_prof(struct task_struct *p) -{ - unsigned long it_prof = p->it_prof_value; - - if (it_prof) { - if (--it_prof == 0) { - it_prof = p->it_prof_incr; - send_sig(SIGPROF, p, 1); - } - p->it_prof_value = it_prof; - } -} - -static void update_one_process(struct task_struct *p, unsigned long user, - unsigned long system, int cpu) -{ - do_process_times(p, user, system); - do_it_virt(p, user); - do_it_prof(p); -} - /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. @@ -866,11 +813,17 @@ static void update_one_process(struct task_struct *p, unsigned long user, void update_process_times(int user_tick) { struct task_struct *p = current; - int cpu = smp_processor_id(), system = user_tick ^ 1; + int cpu = smp_processor_id(); - update_one_process(p, user_tick, system, cpu); + /* Note: this timer irq context must be accounted for as well. */ + if (user_tick) + account_user_time(p, jiffies_to_cputime(1)); + else + account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); run_local_timers(); - scheduler_tick(user_tick, system); + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_tick); + scheduler_tick(); } /* diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 967958c7fae1..7f2951f4ddca 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -61,7 +61,8 @@ static unsigned long badness(struct task_struct *p, unsigned long uptime) * of seconds. There is no particular reason for this other than * that it turned out to work very well in practice. */ - cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3); + cpu_time = (cputime_to_jiffies(p->utime) + cputime_to_jiffies(p->stime)) + >> (SHIFT_HZ + 3); if (uptime >= p->start_time.tv_sec) run_time = (uptime - p->start_time.tv_sec) >> 10; -- cgit v1.2.3 From a6ab0c16edd9bf13db04afc7cd88cb137fe770aa Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 11 Jan 2005 01:40:53 -0800 Subject: [PATCH] cputime: microsecond based cputime for s390 This patch adds the architecture magic to replace the jiffies based cputime with microsecond based cputime and it adds code to calculate involuntary wait time. With this patch the numbers reported by top and ps when running on LPAR or z/VM are finally not junk anymore. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/Kconfig | 7 ++ arch/s390/kernel/binfmt_elf32.c | 5 +- arch/s390/kernel/entry.S | 135 +++++++++++++++++++++++++++++-- arch/s390/kernel/entry64.S | 128 ++++++++++++++++++++++++++++-- arch/s390/kernel/irq.c | 8 ++ arch/s390/kernel/time.c | 42 +++------- arch/s390/kernel/vtime.c | 111 ++++++++++++++++++++++---- include/asm-s390/cputime.h | 170 +++++++++++++++++++++++++++++++++++++++- include/asm-s390/hardirq.h | 1 + include/asm-s390/lowcore.h | 47 +++++++++-- include/asm-s390/system.h | 18 +++++ include/asm-s390/timer.h | 2 - include/linux/hardirq.h | 18 ++++- kernel/softirq.c | 1 + 14 files changed, 620 insertions(+), 73 deletions(-) (limited to 'include') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 85ecab32be89..8394c4e51073 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -367,6 +367,13 @@ config VIRT_TIMER This provides a kernel interface for virtual CPU timers. Default is disabled. +config VIRT_CPU_ACCOUNTING + bool "Base user process accounting on virtual cpu timer" + depends on VIRT_TIMER + help + Select this option to use CPU timer deltas to do user + process accounting. + config APPLDATA_BASE bool "Linux - VM Monitor Stream, base infrastructure" depends on PROC_FS && VIRT_TIMER=y diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index ed234bf06d1c..03ba5893f17b 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -202,9 +202,8 @@ MODULE_AUTHOR("Gerhard Tonn "); static __inline__ void cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) { - unsigned long jiffies = cputime_to_jiffies(cputime); - value->tv_usec = (jiffies % HZ) * (1000000L / HZ); - value->tv_sec = jiffies / HZ; + value->tv_usec = cputime % 1000000; + value->tv_sec = cputime / 1000000; } #include "../../../fs/binfmt_elf.c" diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index f72f9ec9be55..c0e09b33febe 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -66,6 +66,27 @@ STACK_SIZE = 1 << STACK_SHIFT * R15 - kernel stack pointer */ + .macro STORE_TIMER lc_offset +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + stpt \lc_offset +#endif + .endm + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .macro UPDATE_VTIME lc_from,lc_to,lc_sum + lm %r10,%r11,\lc_from + sl %r10,\lc_to + sl %r11,\lc_to+4 + bc 3,BASED(0f) + sl %r10,BASED(.Lc_1) +0: al %r10,\lc_sum + al %r11,\lc_sum+4 + bc 12,BASED(1f) + al %r10,BASED(.Lc_1) +1: stm %r10,%r11,\lc_sum + .endm +#endif + .macro SAVE_ALL_BASE savearea stm %r12,%r15,\savearea l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 @@ -118,6 +139,7 @@ STACK_SIZE = 1 << STACK_SHIFT ni __LC_RETURN_PSW+1,0xfd # clear wait state bit .endif lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user + STORE_TIMER __LC_EXIT_TIMER lpsw __LC_RETURN_PSW # back to caller .endm @@ -159,9 +181,21 @@ __critical_start: .globl system_call system_call: + STORE_TIMER __LC_SYNC_ENTER_TIMER +sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 lh %r7,0x8a # get svc number from lowcore +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +sysc_vtime: + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(sysc_do_svc) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +sysc_stime: + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +sysc_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +#endif sysc_do_svc: l %r9,__LC_THREAD_INFO # load pointer to thread_info struct sla %r7,2 # *4 and test for svc 0 @@ -391,10 +425,19 @@ pgm_check_handler: * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ + STORE_TIMER __LC_SYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception bnz BASED(pgm_per) # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f @@ -425,6 +468,14 @@ pgm_per: # pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime2) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime2: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID @@ -442,6 +493,14 @@ pgm_per_std: # pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(pgm_no_vtime3) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime3: +#endif lh %r7,0x8a # get svc number from lowcore l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,__TI_task(%r9) @@ -458,9 +517,18 @@ pgm_svcper: .globl io_int_handler io_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(io_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +io_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area @@ -549,9 +617,18 @@ io_sigpending: .globl ext_int_handler ext_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+16 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(ext_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +ext_no_vtime: +#endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # get interruption code @@ -565,8 +642,17 @@ ext_int_handler: .globl mcck_int_handler mcck_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(mcck_no_vtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +mcck_no_vtime: +#endif l %r1,BASED(.Ls390_mcck) basr %r14,%r1 # call machine check handler mcck_return: @@ -661,17 +747,47 @@ cleanup_critical: br %r14 cleanup_system_call: - mvc __LC_RETURN_PSW(4),0(%r12) - clc 4(4,%r12),BASED(cleanup_table_system_call) - bne BASED(0f) + mvc __LC_RETURN_PSW(8),0(%r12) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) + bh BASED(0f) + mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) + bhe BASED(cleanup_vtime) +#endif + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) + bh BASED(0f) mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 0: st %r13,__LC_SAVE_AREA+20 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 st %r15,__LC_SAVE_AREA+28 lh %r7,0x8a +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +cleanup_vtime: + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) + bhe BASED(cleanup_stime) + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + bz BASED(cleanup_novtime) + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +cleanup_stime: + clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) + bh BASED(cleanup_update) + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +cleanup_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +cleanup_novtime: +#endif mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) la %r12,__LC_RETURN_PSW br %r14 +cleanup_system_call_insn: + .long sysc_saveall + 0x80000000 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .long system_call + 0x80000000 + .long sysc_vtime + 0x80000000 + .long sysc_stime + 0x80000000 + .long sysc_update + 0x80000000 +#endif cleanup_sysc_return: mvc __LC_RETURN_PSW(4),0(%r12) @@ -680,15 +796,23 @@ cleanup_sysc_return: br %r14 cleanup_sysc_leave: - clc 4(4,%r12),BASED(cleanup_sysc_leave_lpsw) + clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) + be BASED(0f) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) be BASED(0f) +#endif mvc __LC_RETURN_PSW(8),SP_PSW(%r15) mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) lm %r0,%r11,SP_R0(%r15) l %r15,SP_R15(%r15) 0: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_lpsw: +cleanup_sysc_leave_insn: +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .long sysc_leave + 14 + 0x80000000 +#endif .long sysc_leave + 10 + 0x80000000 /* @@ -704,6 +828,7 @@ cleanup_sysc_leave_lpsw: .L0x028: .short 0x028 .L0x030: .short 0x030 .L0x038: .short 0x038 +.Lc_1: .long 1 /* * Symbol constants diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index adbe2a5f5f72..51527ab8c8f9 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -58,6 +58,21 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) #define BASED(name) name-system_call(%r13) + .macro STORE_TIMER lc_offset +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + stpt \lc_offset +#endif + .endm + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .macro UPDATE_VTIME lc_from,lc_to,lc_sum + lg %r10,\lc_from + slg %r10,\lc_to + alg %r10,\lc_sum + stg %r10,\lc_sum + .endm +#endif + /* * Register usage in interrupt handlers: * R9 - pointer to current task structure @@ -117,6 +132,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) ni __LC_RETURN_PSW+1,0xfd # clear wait state bit .endif lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user + STORE_TIMER __LC_EXIT_TIMER lpswe __LC_RETURN_PSW # back to caller .endm @@ -156,9 +172,21 @@ __critical_start: .globl system_call system_call: + STORE_TIMER __LC_SYNC_ENTER_TIMER +sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +sysc_vtime: + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz sysc_do_svc + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +sysc_stime: + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +sysc_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +#endif sysc_do_svc: lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct slag %r7,%r7,2 # *4 and test for svc 0 @@ -441,10 +469,19 @@ pgm_check_handler: * we just ignore the PER event (FIXME: is there anything we have to do * for LPSW?). */ + STORE_TIMER __LC_SYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception jnz pgm_per # got per exception -> special case SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f @@ -475,6 +512,14 @@ pgm_per: # pgm_per_std: SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime2 + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime2: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID @@ -492,6 +537,14 @@ pgm_per_std: # pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz pgm_no_vtime3 + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +pgm_no_vtime3: +#endif llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) @@ -507,9 +560,18 @@ pgm_svcper: */ .globl io_int_handler io_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz io_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +io_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler @@ -595,9 +657,18 @@ io_sigpending: */ .globl ext_int_handler ext_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER stck __LC_INT_CLOCK SAVE_ALL_BASE __LC_SAVE_AREA+32 SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz ext_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +ext_no_vtime: +#endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code @@ -609,8 +680,17 @@ ext_int_handler: */ .globl mcck_int_handler mcck_int_handler: + STORE_TIMER __LC_ASYNC_ENTER_TIMER SAVE_ALL_BASE __LC_SAVE_AREA+64 SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz mcck_no_vtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER +mcck_no_vtime: +#endif brasl %r14,s390_do_machine_check mcck_return: RESTORE_ALL 0 @@ -700,17 +780,47 @@ cleanup_critical: br %r14 cleanup_system_call: - mvc __LC_RETURN_PSW(8),0(%r12) - clc 8(8,%r12),BASED(cleanup_table_system_call) - jne 0f + mvc __LC_RETURN_PSW(16),0(%r12) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) + jh 0f + mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) + jhe cleanup_vtime +#endif + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) + jh 0f mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 0: stg %r13,__LC_SAVE_AREA+40 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 stg %r15,__LC_SAVE_AREA+56 llgh %r7,__LC_SVC_INT_CODE +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +cleanup_vtime: + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) + jhe cleanup_stime + tm SP_PSW+1(%r15),0x01 # interrupting from user ? + jz cleanup_novtime + UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER +cleanup_stime: + clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32) + jh cleanup_update + UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER +cleanup_update: + mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER +cleanup_novtime: +#endif mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) la %r12,__LC_RETURN_PSW br %r14 +cleanup_system_call_insn: + .quad sysc_saveall +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .quad system_call + .quad sysc_vtime + .quad sysc_stime + .quad sysc_update +#endif cleanup_sysc_return: mvc __LC_RETURN_PSW(8),0(%r12) @@ -719,15 +829,23 @@ cleanup_sysc_return: br %r14 cleanup_sysc_leave: - clc 8(8,%r12),BASED(cleanup_sysc_leave_lpsw) + clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) + je 0f +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) je 0f +#endif mvc __LC_RETURN_PSW(16),SP_PSW(%r15) mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) lmg %r0,%r11,SP_R0(%r15) lg %r15,SP_R15(%r15) 0: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_lpsw: +cleanup_sysc_leave_insn: +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + .quad sysc_leave + 16 +#endif .quad sysc_leave + 12 /* diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 75275fe905b1..59bfceabaebe 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -71,6 +71,10 @@ asmlinkage void do_softirq(void) local_irq_save(flags); + account_system_vtime(current); + + local_bh_disable(); + if (local_softirq_pending()) { /* Get current stack pointer. */ asm volatile("la %0,0(15)" : "=a" (old)); @@ -93,6 +97,10 @@ asmlinkage void do_softirq(void) __do_softirq(); } + account_system_vtime(current); + + __local_bh_enable(); + local_irq_restore(flags); } diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 2fea300f4b47..995e2cd38e77 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -150,28 +150,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); -#ifndef CONFIG_ARCH_S390X - -static inline __u32 -__calculate_ticks(__u64 elapsed) -{ - register_pair rp; - - rp.pair = elapsed >> 1; - asm ("dr %0,%1" : "+d" (rp) : "d" (CLK_TICKS_PER_JIFFY >> 1)); - return rp.subreg.odd; -} - -#else /* CONFIG_ARCH_S390X */ - -static inline __u32 -__calculate_ticks(__u64 elapsed) -{ - return elapsed / CLK_TICKS_PER_JIFFY; -} - -#endif /* CONFIG_ARCH_S390X */ - #ifdef CONFIG_PROFILING #define s390_do_profile(regs) profile_tick(CPU_PROFILING, regs) @@ -187,14 +165,14 @@ __calculate_ticks(__u64 elapsed) void account_ticks(struct pt_regs *regs) { __u64 tmp; - __u32 ticks; + __u32 ticks, xticks; /* Calculate how many ticks have passed. */ if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) return; tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */ - ticks = __calculate_ticks(tmp) + 1; + ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1; S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY * (__u64) ticks; } else if (tmp >= CLK_TICKS_PER_JIFFY) { @@ -216,11 +194,9 @@ void account_ticks(struct pt_regs *regs) */ write_seqlock(&xtime_lock); if (S390_lowcore.jiffy_timer > xtime_cc) { - __u32 xticks; - tmp = S390_lowcore.jiffy_timer - xtime_cc; if (tmp >= 2*CLK_TICKS_PER_JIFFY) { - xticks = __calculate_ticks(tmp); + xticks = __div(tmp, CLK_TICKS_PER_JIFFY); xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY; } else { xticks = 1; @@ -230,14 +206,18 @@ void account_ticks(struct pt_regs *regs) do_timer(regs); } write_sequnlock(&xtime_lock); - while (ticks--) - update_process_times(user_mode(regs)); #else - while (ticks--) { + for (xticks = ticks; xticks > 0; xticks--) do_timer(regs); +#endif + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING + account_user_vtime(current); +#else + while (ticks--) update_process_times(user_mode(regs)); - } #endif + s390_do_profile(regs); } diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 02d2179e4082..63cdfec3ba99 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -25,7 +27,95 @@ static ext_int_info_t ext_int_info_timer; DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); -void start_cpu_timer(void) +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +/* + * Update process times based on virtual cpu times stored by entry.S + * to the lowcore fields user_timer, system_timer & steal_clock. + */ +void account_user_vtime(struct task_struct *tsk) +{ + cputime_t cputime; + __u64 timer, clock; + int rcu_user_flag; + + timer = S390_lowcore.last_update_timer; + clock = S390_lowcore.last_update_clock; + asm volatile (" STPT %0\n" /* Store current cpu timer value */ + " STCK %1" /* Store current tod clock value */ + : "=m" (S390_lowcore.last_update_timer), + "=m" (S390_lowcore.last_update_clock) ); + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; + S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock; + + cputime = S390_lowcore.user_timer >> 12; + rcu_user_flag = cputime != 0; + S390_lowcore.user_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_user_time(tsk, cputime); + + cputime = S390_lowcore.system_timer >> 12; + S390_lowcore.system_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_system_time(tsk, HARDIRQ_OFFSET, cputime); + + cputime = S390_lowcore.steal_clock; + if ((__s64) cputime > 0) { + cputime >>= 12; + S390_lowcore.steal_clock -= cputime << 12; + account_steal_time(tsk, cputime); + } + + run_local_timers(); + if (rcu_pending(smp_processor_id())) + rcu_check_callbacks(smp_processor_id(), rcu_user_flag); + scheduler_tick(); +} + +/* + * Update process times based on virtual cpu times stored by entry.S + * to the lowcore fields user_timer, system_timer & steal_clock. + */ +void account_system_vtime(struct task_struct *tsk) +{ + cputime_t cputime; + __u64 timer; + + timer = S390_lowcore.last_update_timer; + asm volatile (" STPT %0" /* Store current cpu timer value */ + : "=m" (S390_lowcore.last_update_timer) ); + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; + + cputime = S390_lowcore.system_timer >> 12; + S390_lowcore.system_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_system_time(tsk, 0, cputime); +} + +static inline void set_vtimer(__u64 expires) +{ + __u64 timer; + + asm volatile (" STPT %0\n" /* Store current cpu timer value */ + " SPT %1" /* Set new value immediatly afterwards */ + : "=m" (timer) : "m" (expires) ); + S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; + S390_lowcore.last_update_timer = expires; + + /* store expire time for this CPU timer */ + per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; +} +#else +static inline void set_vtimer(__u64 expires) +{ + S390_lowcore.last_update_timer = expires; + asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); + + /* store expire time for this CPU timer */ + per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; +} +#endif + +static void start_cpu_timer(void) { struct vtimer_queue *vt_list; @@ -33,7 +123,7 @@ void start_cpu_timer(void) set_vtimer(vt_list->idle); } -void stop_cpu_timer(void) +static void stop_cpu_timer(void) { __u64 done; struct vtimer_queue *vt_list; @@ -71,19 +161,11 @@ void stop_cpu_timer(void) set_vtimer(VTIMER_MAX_SLICE); } -void set_vtimer(__u64 expires) -{ - asm volatile ("SPT %0" : : "m" (expires)); - - /* store expire time for this CPU timer */ - per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; -} - /* * Sorted add to a list. List is linear searched until first bigger * element is found. */ -void list_add_sorted(struct vtimer_list *timer, struct list_head *head) +static void list_add_sorted(struct vtimer_list *timer, struct list_head *head) { struct vtimer_list *event; @@ -429,11 +511,12 @@ void init_cpu_vtimer(void) { struct vtimer_queue *vt_list; unsigned long cr0; - __u64 timer; /* kick the virtual timer */ - timer = VTIMER_MAX_SLICE; - asm volatile ("SPT %0" : : "m" (timer)); + S390_lowcore.exit_timer = VTIMER_MAX_SLICE; + S390_lowcore.last_update_timer = VTIMER_MAX_SLICE; + asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); + asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); __ctl_store(cr0, 0, 0); cr0 |= 0x400; __ctl_load(cr0, 0, 0); diff --git a/include/asm-s390/cputime.h b/include/asm-s390/cputime.h index ad989e5d369c..216d861337e6 100644 --- a/include/asm-s390/cputime.h +++ b/include/asm-s390/cputime.h @@ -1,6 +1,168 @@ -#ifndef __S390_CPUTIME_H -#define __S390_CPUTIME_H +/* + * include/asm-s390/cputime.h + * + * (C) Copyright IBM Corp. 2004 + * + * Author: Martin Schwidefsky + */ -#include +#ifndef _S390_CPUTIME_H +#define _S390_CPUTIME_H -#endif /* __S390_CPUTIME_H */ +/* We want to use micro-second resolution. */ + +typedef unsigned long long cputime_t; +typedef unsigned long long cputime64_t; + +#ifndef __s390x__ + +static inline unsigned int +__div(unsigned long long n, unsigned int base) +{ + register_pair rp; + + rp.pair = n >> 1; + asm ("dr %0,%1" : "+d" (rp) : "d" (base >> 1)); + return rp.subreg.odd; +} + +#else /* __s390x__ */ + +static inline unsigned int +__div(unsigned long long n, unsigned int base) +{ + return n / base; +} + +#endif /* __s390x__ */ + +#define cputime_zero (0ULL) +#define cputime_max ((~0UL >> 1) - 1) +#define cputime_add(__a, __b) ((__a) + (__b)) +#define cputime_sub(__a, __b) ((__a) - (__b)) +#define cputime_eq(__a, __b) ((__a) == (__b)) +#define cputime_gt(__a, __b) ((__a) > (__b)) +#define cputime_ge(__a, __b) ((__a) >= (__b)) +#define cputime_lt(__a, __b) ((__a) < (__b)) +#define cputime_le(__a, __b) ((__a) <= (__b)) +#define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ)) +#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ)) + +#define cputime64_zero (0ULL) +#define cputime64_add(__a, __b) ((__a) + (__b)) +#define cputime_to_cputime64(__ct) (__ct) + +static inline u64 +cputime64_to_jiffies64(cputime64_t cputime) +{ + do_div(cputime, 1000000 / HZ); + return cputime; +} + +/* + * Convert cputime to milliseconds and back. + */ +static inline unsigned int +cputime_to_msecs(const cputime_t cputime) +{ + return __div(cputime, 1000); +} + +static inline cputime_t +msecs_to_cputime(const unsigned int m) +{ + return (cputime_t) m * 1000; +} + +/* + * Convert cputime to milliseconds and back. + */ +static inline unsigned int +cputime_to_secs(const cputime_t cputime) +{ + return __div(cputime, 1000000); +} + +static inline cputime_t +secs_to_cputime(const unsigned int s) +{ + return (cputime_t) s * 1000000; +} + +/* + * Convert cputime to timespec and back. + */ +static inline cputime_t +timespec_to_cputime(const struct timespec *value) +{ + return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000; +} + +static inline void +cputime_to_timespec(const cputime_t cputime, struct timespec *value) +{ +#ifndef __s390x__ + register_pair rp; + + rp.pair = cputime >> 1; + asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1)); + value->tv_nsec = rp.subreg.even * 1000; + value->tv_sec = rp.subreg.odd; +#else + value->tv_nsec = (cputime % 1000000) * 1000; + value->tv_sec = cputime / 1000000; +#endif +} + +/* + * Convert cputime to timeval and back. + * Since cputime and timeval have the same resolution (microseconds) + * this is easy. + */ +static inline cputime_t +timeval_to_cputime(const struct timeval *value) +{ + return value->tv_usec + (u64) value->tv_sec * 1000000; +} + +static inline void +cputime_to_timeval(const cputime_t cputime, struct timeval *value) +{ +#ifndef __s390x__ + register_pair rp; + + rp.pair = cputime >> 1; + asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1)); + value->tv_usec = rp.subreg.even; + value->tv_sec = rp.subreg.odd; +#else + value->tv_usec = cputime % 1000000; + value->tv_sec = cputime / 1000000; +#endif +} + +/* + * Convert cputime to clock and back. + */ +static inline clock_t +cputime_to_clock_t(cputime_t cputime) +{ + return __div(cputime, 1000000 / USER_HZ); +} + +static inline cputime_t +clock_t_to_cputime(unsigned long x) +{ + return (cputime_t) x * (1000000 / USER_HZ); +} + +/* + * Convert cputime64 to clock. + */ +static inline clock_t +cputime64_to_clock_t(cputime64_t cputime) +{ + return __div(cputime, 1000000 / USER_HZ); +} + +#endif /* _S390_CPUTIME_H */ diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h index 1580b7b2b05e..53e59b4760c5 100644 --- a/include/asm-s390/hardirq.h +++ b/include/asm-s390/hardirq.h @@ -16,6 +16,7 @@ #include #include #include +#include #include /* irq_cpustat_t is unused currently, but could be converted diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index 0aa1c0f1e705..df5172fc589d 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h @@ -56,13 +56,18 @@ #define __LC_RETURN_PSW 0x200 -#define __LC_IRB 0x210 - -#define __LC_DIAG44_OPCODE 0x250 - #define __LC_SAVE_AREA 0xC00 #ifndef __s390x__ +#define __LC_IRB 0x208 +#define __LC_SYNC_ENTER_TIMER 0x248 +#define __LC_ASYNC_ENTER_TIMER 0x250 +#define __LC_EXIT_TIMER 0x258 +#define __LC_LAST_UPDATE_TIMER 0x260 +#define __LC_USER_TIMER 0x268 +#define __LC_SYSTEM_TIMER 0x270 +#define __LC_LAST_UPDATE_CLOCK 0x278 +#define __LC_STEAL_CLOCK 0x280 #define __LC_KERNEL_STACK 0xC40 #define __LC_THREAD_INFO 0xC44 #define __LC_ASYNC_STACK 0xC48 @@ -76,6 +81,16 @@ #define __LC_CURRENT 0xC90 #define __LC_INT_CLOCK 0xC98 #else /* __s390x__ */ +#define __LC_IRB 0x210 +#define __LC_SYNC_ENTER_TIMER 0x250 +#define __LC_ASYNC_ENTER_TIMER 0x258 +#define __LC_EXIT_TIMER 0x260 +#define __LC_LAST_UPDATE_TIMER 0x268 +#define __LC_USER_TIMER 0x270 +#define __LC_SYSTEM_TIMER 0x278 +#define __LC_LAST_UPDATE_CLOCK 0x280 +#define __LC_STEAL_CLOCK 0x288 +#define __LC_DIAG44_OPCODE 0x290 #define __LC_KERNEL_STACK 0xD40 #define __LC_THREAD_INFO 0xD48 #define __LC_ASYNC_STACK 0xD50 @@ -87,7 +102,7 @@ #define __LC_IPLDEV 0xDB8 #define __LC_JIFFY_TIMER 0xDC0 #define __LC_CURRENT 0xDD8 -#define __LC_INT_CLOCK 0xDe8 +#define __LC_INT_CLOCK 0xDE8 #endif /* __s390x__ */ #define __LC_PANIC_MAGIC 0xE00 @@ -169,7 +184,15 @@ struct _lowcore psw_t return_psw; /* 0x200 */ __u8 irb[64]; /* 0x208 */ - __u8 pad8[0xc00-0x248]; /* 0x248 */ + __u64 sync_enter_timer; /* 0x248 */ + __u64 async_enter_timer; /* 0x250 */ + __u64 exit_timer; /* 0x258 */ + __u64 last_update_timer; /* 0x260 */ + __u64 user_timer; /* 0x268 */ + __u64 system_timer; /* 0x270 */ + __u64 last_update_clock; /* 0x278 */ + __u64 steal_clock; /* 0x280 */ + __u8 pad8[0xc00-0x288]; /* 0x288 */ /* System info area */ __u32 save_area[16]; /* 0xc00 */ @@ -250,8 +273,16 @@ struct _lowcore psw_t io_new_psw; /* 0x1f0 */ psw_t return_psw; /* 0x200 */ __u8 irb[64]; /* 0x210 */ - __u32 diag44_opcode; /* 0x250 */ - __u8 pad8[0xc00-0x254]; /* 0x254 */ + __u64 sync_enter_timer; /* 0x250 */ + __u64 async_enter_timer; /* 0x258 */ + __u64 exit_timer; /* 0x260 */ + __u64 last_update_timer; /* 0x268 */ + __u64 user_timer; /* 0x270 */ + __u64 system_timer; /* 0x278 */ + __u64 last_update_clock; /* 0x280 */ + __u64 steal_clock; /* 0x288 */ + __u32 diag44_opcode; /* 0x290 */ + __u8 pad8[0xc00-0x294]; /* 0x294 */ /* System info area */ __u64 save_area[16]; /* 0xc00 */ __u8 pad9[0xd40-0xc80]; /* 0xc80 */ diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index d9f3498136e1..e8596077e057 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h @@ -105,11 +105,29 @@ static inline void restore_access_regs(unsigned int *acrs) #define prepare_arch_switch(rq, next) do { } while(0) #define task_running(rq, p) ((rq)->curr == (p)) + +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +extern void account_user_vtime(struct task_struct *); +extern void account_system_vtime(struct task_struct *); + +#define finish_arch_switch(rq, prev) do { \ + set_fs(current->thread.mm_segment); \ + spin_unlock(&(rq)->lock); \ + account_system_vtime(prev); \ + local_irq_enable(); \ +} while (0) + +#else + +#define account_system_vtime(prev) + #define finish_arch_switch(rq, prev) do { \ set_fs(current->thread.mm_segment); \ spin_unlock_irq(&(rq)->lock); \ } while (0) +#endif + #define nop() __asm__ __volatile__ ("nop") #define xchg(ptr,x) \ diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h index 454d1ea85c54..ea0788967c51 100644 --- a/include/asm-s390/timer.h +++ b/include/asm-s390/timer.h @@ -37,8 +37,6 @@ struct vtimer_queue { __u64 idle; /* temp var for idle */ }; -void set_vtimer(__u64 expires); - extern void init_virt_timer(struct vtimer_list *timer); extern void add_virt_timer(void *new); extern void add_virt_timer_periodic(void *new); diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index ba0fcb34c8cd..ebc712e91066 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -4,6 +4,7 @@ #include #include #include +#include /* * We put the hardirq and softirq counter into the preemption @@ -84,7 +85,22 @@ extern void synchronize_irq(unsigned int irq); #define nmi_enter() irq_enter() #define nmi_exit() sub_preempt_count(HARDIRQ_OFFSET) -#define irq_enter() add_preempt_count(HARDIRQ_OFFSET) +#ifndef CONFIG_VIRT_CPU_ACCOUNTING +static inline void account_user_vtime(struct task_struct *tsk) +{ +} + +static inline void account_system_vtime(struct task_struct *tsk) +{ +} +#endif + +#define irq_enter() \ + do { \ + account_system_vtime(current); \ + add_preempt_count(HARDIRQ_OFFSET); \ + } while (0) + extern void irq_exit(void); #endif /* LINUX_HARDIRQ_H */ diff --git a/kernel/softirq.c b/kernel/softirq.c index 9e2d204da364..582a1e8091bc 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -163,6 +163,7 @@ EXPORT_SYMBOL(local_bh_enable); */ void irq_exit(void) { + account_system_vtime(current); sub_preempt_count(IRQ_EXIT_OFFSET); if (!in_interrupt() && local_softirq_pending()) invoke_softirq(); -- cgit v1.2.3 From a1996f881869fc68b2ff8d164190cb258831aca5 Mon Sep 17 00:00:00 2001 From: Zwane Mwaikambo Date: Tue, 11 Jan 2005 01:42:00 -0800 Subject: [PATCH] ppc64: Move hotplug cpu functions to smp_ops This should allow for easier adding of hotplug cpu support for other PPC64 subarchs. The patch is untested but does compile with and without hotplug cpu on pSeries and G5 configs. What can get slightly confusing is the fact that both ppc_md and smp_ops have cpu_die members. Signed-off-by: Zwane Mwaikambo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/pSeries_smp.c | 9 +++++++-- arch/ppc64/kernel/smp.c | 16 ++++++++++++++++ include/asm-ppc64/machdep.h | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index d03c47164001..12da1cdf854e 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c @@ -87,7 +87,7 @@ static int query_cpu_stopped(unsigned int pcpu) #ifdef CONFIG_HOTPLUG_CPU -int __cpu_disable(void) +int pSeries_cpu_disable(void) { /* FIXME: go put this in a header somewhere */ extern void xics_migrate_irqs_away(void); @@ -103,7 +103,7 @@ int __cpu_disable(void) return 0; } -void __cpu_die(unsigned int cpu) +void pSeries_cpu_die(unsigned int cpu) { int tries; int cpu_status; @@ -352,6 +352,11 @@ void __init smp_init_pSeries(void) else smp_ops = &pSeries_xics_smp_ops; +#ifdef CONFIG_HOTPLUG_CPU + smp_ops->cpu_disable = pSeries_cpu_disable; + smp_ops->cpu_die = pSeries_cpu_die; +#endif + /* Start secondary threads on SMT systems; primary threads * are already in the running state. */ diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index db78b2f03884..808bb3d906c6 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -551,3 +551,19 @@ void __init smp_cpus_done(unsigned int max_cpus) */ cpu_present_map = cpu_possible_map; } + +#ifdef CONFIG_HOTPLUG_CPU +int __cpu_disable(void) +{ + if (smp_ops->cpu_disable) + return smp_ops->cpu_disable(); + + return -ENOSYS; +} + +void __cpu_die(unsigned int cpu) +{ + if (smp_ops->cpu_die) + smp_ops->cpu_die(cpu); +} +#endif diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h index ae1c4fd4a7cf..a21a944d326f 100644 --- a/include/asm-ppc64/machdep.h +++ b/include/asm-ppc64/machdep.h @@ -31,6 +31,8 @@ struct smp_ops_t { void (*late_setup_cpu)(int nr); void (*take_timebase)(void); void (*give_timebase)(void); + int (*cpu_disable)(void); + void (*cpu_die)(unsigned int nr); }; #endif -- cgit v1.2.3 From 9aaf64a0f7cfd94cac1d0be99d2943e1302c0608 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Jan 2005 01:43:28 -0800 Subject: [PATCH] ppc64: make xmon print BUG() warnings I've had to explain to a number of people that a 0x700 exception is often a BUG(). Make this crystal clear by printing the BUG information in the xmon exception printout. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/traps.c | 4 ++-- arch/ppc64/xmon/xmon.c | 24 ++++++++++++++++++++++++ include/asm-ppc64/bug.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index c37af43a7a62..418aff49933e 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -344,7 +344,7 @@ extern struct bug_entry __start___bug_table[], __stop___bug_table[]; #define module_find_bug(x) NULL #endif -static struct bug_entry *find_bug(unsigned long bugaddr) +struct bug_entry *find_bug(unsigned long bugaddr) { struct bug_entry *bug; @@ -354,7 +354,7 @@ static struct bug_entry *find_bug(unsigned long bugaddr) return module_find_bug(bugaddr); } -int +static int check_bug_trap(struct pt_regs *regs) { struct bug_entry *bug; diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index c53046d52e6c..2be270592fb3 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "nonstdio.h" #include "privinst.h" @@ -1319,6 +1320,26 @@ static void backtrace(struct pt_regs *excp) scannl(); } +static void print_bug_trap(struct pt_regs *regs) +{ + struct bug_entry *bug; + unsigned long addr; + + if (regs->msr & MSR_PR) + return; /* not in kernel */ + addr = regs->nip; /* address of trap instruction */ + if (addr < PAGE_OFFSET) + return; + bug = find_bug(regs->nip); + if (bug == NULL) + return; + if (bug->line & BUG_WARNING_TRAP) + return; + + printf("kernel BUG in %s at %s:%d!\n", + bug->function, bug->file, (unsigned int)bug->line); +} + void excprint(struct pt_regs *fp) { unsigned long trap; @@ -1350,6 +1371,9 @@ void excprint(struct pt_regs *fp) printf(" pid = %ld, comm = %s\n", current->pid, current->comm); } + + if (trap == 0x700) + print_bug_trap(fp); } void prregs(struct pt_regs *fp) diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h index 790bc56091d6..db31dd22233c 100644 --- a/include/asm-ppc64/bug.h +++ b/include/asm-ppc64/bug.h @@ -18,6 +18,8 @@ struct bug_entry { const char *function; }; +struct bug_entry *find_bug(unsigned long bugaddr); + /* * If this bit is set in the line number it means that the trap * is for WARN_ON rather than BUG or BUG_ON. -- cgit v1.2.3 From 0ca63a2ac3a68acd98b2af1bf1972a61bfcfa63f Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Jan 2005 01:43:55 -0800 Subject: [PATCH] ppc64: PCI cleanup - remove pci_fix_bus_sysdata. We required it for the old pci dma subsystem, but now it is useless. - remove PCI_GET_PHB_PTR and use pci_bus_to_host instead - remove pci_find_hose_for_OF_device - remove some unused fields in struct pci_controller - remove pci_device_loc stale prototype - remove an old mask of pci bus number that was left around from the pre PCI domains days Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/maple_pci.c | 3 --- arch/ppc64/kernel/pSeries_pci.c | 1 - arch/ppc64/kernel/pci.c | 33 ++++++++------------------------- arch/ppc64/kernel/pci.h | 4 ---- arch/ppc64/kernel/pci_dn.c | 33 --------------------------------- arch/ppc64/kernel/pmac_pci.c | 2 -- include/asm-ppc64/pci-bridge.h | 23 +++-------------------- 7 files changed, 11 insertions(+), 88 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c index f8cd5b495d6b..53993999b265 100644 --- a/arch/ppc64/kernel/maple_pci.c +++ b/arch/ppc64/kernel/maple_pci.c @@ -382,9 +382,6 @@ void __init maple_pcibios_fixup(void) /* Do the mapping of the IO space */ phbs_remap_io(); - /* Fixup the pci_bus sysdata pointers */ - pci_fix_bus_sysdata(); - DBG(" <- maple_pcibios_fixup\n"); } diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index 2b9a00951f20..8953e94889ba 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -552,7 +552,6 @@ void __init pSeries_final_fixup(void) phbs_remap_io(); pSeries_request_regions(); - pci_fix_bus_sysdata(); pci_addr_cache_build(); } diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 25822272542e..a7bf62655601 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -91,7 +91,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region struct resource *res) { unsigned long offset = 0; - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); if (!hose) return; @@ -127,7 +127,7 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { struct pci_dev *dev = data; - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); unsigned long start = res->start; unsigned long alignto; @@ -292,7 +292,7 @@ int pci_domain_nr(struct pci_bus *bus) #ifdef CONFIG_PPC_ISERIES return 0; #else - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); return hose->global_number; #endif @@ -304,7 +304,7 @@ EXPORT_SYMBOL(pci_domain_nr); int pci_name_bus(char *name, struct pci_bus *bus) { #ifndef CONFIG_PPC_ISERIES - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); if (hose->buid) sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); @@ -336,7 +336,7 @@ static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - struct pci_controller *hose = PCI_GET_PHB_PTR(dev); + struct pci_controller *hose = pci_bus_to_host(dev->bus); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long io_offset = 0; int i, res_bit; @@ -643,7 +643,7 @@ void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose) static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, unsigned long *start_virt, unsigned long *size) { - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); struct pci_bus_region region; struct resource *res; @@ -728,23 +728,6 @@ void phbs_remap_io(void) remap_bus_range(hose->bus); } - -/* - * This function finds the PHB that matching device_node in the - * OpenFirmware by scanning all the pci_controllers. - */ -struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node) -{ - while (node) { - struct pci_controller *hose, *tmp; - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) - if (hose->arch_data == node) - return hose; - node=node->parent; - } - return NULL; -} - /* * ppc64 can have multifunction devices that do not respond to function 0. * In this case we must scan all functions. @@ -778,7 +761,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) { /* Update device resources. */ - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -814,7 +797,7 @@ EXPORT_SYMBOL(pcibios_fixup_device_resources); void __devinit pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_controller *hose = pci_bus_to_host(bus); struct pci_dev *dev = bus->self; struct resource *res; int i; diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index 2ed6b674bbca..28517c14015b 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -17,7 +17,6 @@ extern unsigned long isa_io_base; extern void pci_setup_pci_controller(struct pci_controller *hose); extern void pci_setup_phb_io(struct pci_controller *hose, int primary); -extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); extern void pci_setup_phb_io_dynamic(struct pci_controller *hose); @@ -36,11 +35,8 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); -void pci_fix_bus_sysdata(void); struct device_node *fetch_dev_dn(struct pci_dev *dev); -#define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb) - /* PCI address cache management routines */ void pci_addr_cache_insert_device(struct pci_dev *dev); void pci_addr_cache_remove_device(struct pci_dev *dev); diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 962394708ece..280b744fe64e 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -21,19 +21,12 @@ */ #include #include -#include #include #include -#include #include -#include -#include #include -#include #include -#include -#include #include "pci.h" @@ -178,29 +171,3 @@ void __init pci_devs_phb_init(void) list_for_each_entry_safe(phb, tmp, &hose_list, list_node) pci_devs_phb_init_dynamic(phb); } - - -static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list) -{ - struct pci_bus *bus; - - list_for_each_entry(bus, bus_list, node) { - if (bus->self) - bus->sysdata = bus->self->sysdata; - pci_fixup_bus_sysdata_list(&bus->children); - } -} - -/* - * Fixup the bus->sysdata ptrs to point to the bus' device_node. - * This is done late in pcibios_init(). We do this mostly for - * sanity, but pci_dma.c uses these at DMA time so they must be - * correct. - * To do this we recurse down the bus hierarchy. Note that PHB's - * have bus->self == NULL, but fortunately bus->sysdata is already - * correct in this case. - */ -void __init pci_fix_bus_sysdata(void) -{ - pci_fixup_bus_sysdata_list(&pci_root_buses); -} diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c index 32634216ad78..00a831df6d9f 100644 --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -664,8 +664,6 @@ void __init pmac_pcibios_fixup(void) for_each_pci_dev(dev) pci_read_irq_line(dev); - - pci_fix_bus_sysdata(); } static void __init pmac_fixup_phb_resources(void) diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h index 51cfa8b72812..c4f9023ea5ed 100644 --- a/include/asm-ppc64/pci-bridge.h +++ b/include/asm-ppc64/pci-bridge.h @@ -11,18 +11,10 @@ * 2 of the License, or (at your option) any later version. */ -struct device_node; -struct pci_controller; - -/* Get the PCI host controller for an OF device */ -extern struct pci_controller* -pci_find_hose_for_OF_device(struct device_node* node); - /* * Structure of a PCI controller (host bridge) */ struct pci_controller { - char what[8]; /* Eye catcher */ struct pci_bus *bus; char is_dynamic; void *arch_data; @@ -49,7 +41,6 @@ struct pci_controller { */ struct resource io_resource; struct resource mem_resources[3]; - int mem_resource_count; int global_number; int local_number; unsigned long buid; @@ -57,14 +48,6 @@ struct pci_controller { unsigned long dma_window_size; }; -/* - * pci_device_loc returns the bus number and device/function number - * for a device on a PCI bus, given its device_node struct. - * It returns 0 if OK, -1 on error. - */ -extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, - unsigned char *devfn_ptr); - struct device_node *fetch_dev_dn(struct pci_dev *dev); /* Get a device_node from a pci_dev. This code must be fast except in the case @@ -72,8 +55,9 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev); */ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev) { - struct device_node *dn = (struct device_node *)(dev->sysdata); - if (dn->devfn == dev->devfn && dn->busno == (dev->bus->number&0xff)) + struct device_node *dn = dev->sysdata; + + if (dn->devfn == dev->devfn && dn->busno == dev->bus->number) return dn; /* fast path. sysdata is good */ else return fetch_dev_dn(dev); @@ -102,6 +86,5 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) return busdn->phb; } - #endif #endif /* __KERNEL__ */ -- cgit v1.2.3 From f52cf14bfd2b0e6cff9aba14dbafb96547fbeb7c Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Jan 2005 01:44:09 -0800 Subject: [PATCH] ppc64: Remove flush_instruction_cache Remove flush_instruction_cache, we cant touch HID bits on LPAR machines. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/misc.S | 20 -------------------- arch/ppc64/kernel/ppc_ksyms.c | 1 - include/asm-ppc64/system.h | 1 - 3 files changed, 22 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index a795ae320b37..1502b814a558 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -167,27 +167,7 @@ _GLOBAL(call_with_mmu_off) xori r0,r0,MSR_IR|MSR_DR mtspr SPRN_SRR1,r0 rfid - -/* - * Flush instruction cache. - */ -_GLOBAL(flush_instruction_cache) -/* - * This is called by kgdb code - * and should probably go away - * to be replaced by invalidating - * the cache lines that are actually - * modified - */ - /* use invalidate-all bit in HID0 - * - is this consistent across all 64-bit cpus? -- paulus */ - mfspr r3,HID0 - ori r3,r3,HID0_ICFI - mtspr HID0,r3 - sync - isync - blr .section ".toc","aw" PPC64_CACHES: diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index 7efdaabf5b7b..38c0398d823c 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -114,7 +114,6 @@ EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(flush_instruction_cache); EXPORT_SYMBOL(giveup_fpu); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(giveup_altivec); diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index dc3153fa414e..6785e69e8b9e 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -108,7 +108,6 @@ extern void show_regs(struct pt_regs * regs); extern void low_hash_fault(struct pt_regs *regs, unsigned long address); extern int die(const char *str, struct pt_regs *regs, long err); -extern void flush_instruction_cache(void); extern int _get_PVR(void); extern void giveup_fpu(struct task_struct *); extern void disable_kernel_fp(void); -- cgit v1.2.3 From d00da3f86a633fa1a767a406e52aa3201717f33a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Jan 2005 01:44:23 -0800 Subject: [PATCH] ppc64: interrupt code cleanup - Move some function prototypes into header files. - Remove late_setup_cpu, put the set indicator and vpa init into xics probe instead - rtas-proc was doing weird stuff with the 9005 indicator. Get rid of it. - Dont open code the set_indicator call in the hotplug code Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/pSeries_smp.c | 46 ++++++++++++----------------------------- arch/ppc64/kernel/rtas-proc.c | 12 ----------- arch/ppc64/kernel/smp.c | 12 ----------- arch/ppc64/kernel/xics.c | 10 +++------ include/asm-ppc64/machdep.h | 1 - include/asm-ppc64/rtas.h | 2 ++ include/asm-ppc64/xics.h | 4 ++++ 7 files changed, 22 insertions(+), 65 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index 12da1cdf854e..da4b63fbb7ae 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c @@ -19,9 +19,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -40,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -89,9 +86,6 @@ static int query_cpu_stopped(unsigned int pcpu) int pSeries_cpu_disable(void) { - /* FIXME: go put this in a header somewhere */ - extern void xics_migrate_irqs_away(void); - systemcfg->processorCount--; /*fix boot_cpuid here*/ @@ -250,8 +244,6 @@ static void smp_xics_message_pass(int target, int msg) } } -extern void xics_request_IPIs(void); - static int __init smp_xics_probe(void) { xics_request_IPIs(); @@ -263,6 +255,18 @@ static void __devinit smp_xics_setup_cpu(int cpu) { if (cpu != boot_cpuid) xics_setup_cpu(); + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) + vpa_init(cpu); + +#ifdef CONFIG_IRQ_ALL_CPUS + /* + * Put the calling processor into the GIQ. This is really only + * necessary from a secondary thread as the OF start-cpu interface + * performs this function for us on primary threads. + */ + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, default_distrib_server, 1); +#endif } static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; @@ -290,26 +294,7 @@ static void __devinit pSeries_take_timebase(void) spin_unlock(&timebase_lock); } -static void __devinit pSeries_late_setup_cpu(int cpu) -{ - extern unsigned int default_distrib_server; - - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - vpa_init(cpu); - } - -#ifdef CONFIG_IRQ_ALL_CPUS - /* Put the calling processor into the GIQ. This is really only - * necessary from a secondary thread as the OF start-cpu interface - * performs this function for us on primary threads. - */ - /* TODO: 9005 is #defined in rtas-proc.c -- move to a header */ - rtas_set_indicator(9005, default_distrib_server, 1); -#endif -} - - -void __devinit smp_pSeries_kick_cpu(int nr) +static void __devinit smp_pSeries_kick_cpu(int nr) { BUG_ON(nr < 0 || nr >= NR_CPUS); @@ -329,7 +314,6 @@ static struct smp_ops_t pSeries_mpic_smp_ops = { .probe = smp_mpic_probe, .kick_cpu = smp_pSeries_kick_cpu, .setup_cpu = smp_mpic_setup_cpu, - .late_setup_cpu = pSeries_late_setup_cpu, }; static struct smp_ops_t pSeries_xics_smp_ops = { @@ -337,7 +321,6 @@ static struct smp_ops_t pSeries_xics_smp_ops = { .probe = smp_xics_probe, .kick_cpu = smp_pSeries_kick_cpu, .setup_cpu = smp_xics_setup_cpu, - .late_setup_cpu = pSeries_late_setup_cpu, }; /* This is called very early */ @@ -372,9 +355,6 @@ void __init smp_init_pSeries(void) } } - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) - vpa_init(boot_cpuid); - /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { smp_ops->give_timebase = pSeries_give_timebase; diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c index ed07210b9917..28b1f1521f21 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/ppc64/kernel/rtas-proc.c @@ -52,7 +52,6 @@ #define IBM_VOLTAGE 0x232a /* 9002 */ #define IBM_DRCONNECTOR 0x232b /* 9003 */ #define IBM_POWERSUPPLY 0x232c /* 9004 */ -#define IBM_INTQUEUE 0x232d /* 9005 */ /* Status return values */ #define SENSOR_CRITICAL_HIGH 13 @@ -107,7 +106,6 @@ #define DR_ACTION 0x2329 /* 9001 */ #define DR_INDICATOR 0x232a /* 9002 */ /* 9003 - 9004: Vendor specific */ -#define GLOBAL_INTERRUPT_QUEUE 0x232d /* 9005 */ /* 9006 - 9999: Vendor specific */ /* other */ @@ -553,7 +551,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m, "No current flow" }; const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", "Exchange" }; - const char * ibm_intqueue[] = { "Disabled", "Enabled" }; int have_strings = 0; int num_states = 0; @@ -665,15 +662,6 @@ static void ppc_rtas_process_sensor(struct seq_file *m, case IBM_POWERSUPPLY: seq_printf(m, "Powersupply:\t"); break; - case IBM_INTQUEUE: - seq_printf(m, "Interrupt queue:\t"); - num_states = sizeof(ibm_intqueue) / sizeof(char *); - if (state < num_states) { - seq_printf(m, "%s\t", - ibm_intqueue[state]); - have_strings = 1; - } - break; default: seq_printf(m, "Unknown sensor (type %d), ignoring it\n", s->token); diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 808bb3d906c6..f5b4a8f29581 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -38,12 +36,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -58,7 +54,6 @@ #endif int smp_threads_ready; -unsigned long cache_decay_ticks; cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; @@ -77,10 +72,6 @@ void smp_call_function_interrupt(void); int smt_enabled_at_boot = 1; -/* Low level assembly function used to backup CPU 0 state */ -extern void __save_cpu_setup(void); - - #ifdef CONFIG_PPC_MULTIPLATFORM void smp_mpic_message_pass(int target, int msg) { @@ -507,9 +498,6 @@ int __devinit start_secondary(void *unused) if (smp_ops->take_timebase) smp_ops->take_timebase(); - if (smp_ops->late_setup_cpu) - smp_ops->late_setup_cpu(cpu); - spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); spin_unlock(&call_lock); diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index b9fdcc60d6e8..dd88142ebf39 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -643,20 +643,16 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) /* Interrupts are disabled. */ void xics_migrate_irqs_away(void) { - int set_indicator = rtas_token("set-indicator"); - const unsigned int giqs = 9005UL; /* Global Interrupt Queue Server */ - int status = 0; + int status; unsigned int irq, virq, cpu = smp_processor_id(); - BUG_ON(set_indicator == RTAS_UNKNOWN_SERVICE); - /* Reject any interrupt that was queued to us... */ ops->cppr_info(cpu, 0); iosync(); /* Refuse any new interrupts... */ - rtas_call(set_indicator, 3, 1, &status, giqs, - hard_smp_processor_id(), 0); + status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + hard_smp_processor_id(), 0); WARN_ON(status != 0); /* Allow IPIs again... */ diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h index a21a944d326f..476d2185ffd1 100644 --- a/include/asm-ppc64/machdep.h +++ b/include/asm-ppc64/machdep.h @@ -28,7 +28,6 @@ struct smp_ops_t { int (*probe)(void); void (*kick_cpu)(int nr); void (*setup_cpu)(int nr); - void (*late_setup_cpu)(int nr); void (*take_timebase)(void); void (*give_timebase)(void); int (*cpu_disable)(void); diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h index a405a871919e..dc2879cc4981 100644 --- a/include/asm-ppc64/rtas.h +++ b/include/asm-ppc64/rtas.h @@ -241,4 +241,6 @@ extern void rtas_stop_self(void); /* RMO buffer reserved for user-space RTAS use */ extern unsigned long rtas_rmo_buf; +#define GLOBAL_INTERRUPT_QUEUE 9005 + #endif /* _PPC64_RTAS_H */ diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h index 560f4fd99e21..6b9aedc6eadb 100644 --- a/include/asm-ppc64/xics.h +++ b/include/asm-ppc64/xics.h @@ -18,6 +18,8 @@ void xics_init_IRQ(void); int xics_get_irq(struct pt_regs *); void xics_setup_cpu(void); void xics_cause_IPI(int cpu); +void xics_request_IPIs(void); +void xics_migrate_irqs_away(void); /* first argument is ignored for now*/ void pSeriesLP_cppr_info(int n_cpu, u8 value); @@ -28,4 +30,6 @@ struct xics_ipi_struct { extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; +extern unsigned int default_distrib_server; + #endif /* _PPC64_KERNEL_XICS_H */ -- cgit v1.2.3 From 3d311cb2e0c88fa555aff6ce67635028241b7440 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Jan 2005 01:44:36 -0800 Subject: [PATCH] ppc64: Fix rtas_set_indicator(9005) It turns out we were passing in the wrong thing to the rtas_set_indicator call. Luckily we got away with it because it looks like firmware does not check arguments and just inserts or removes the current cpu from the global server group. Fix it. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/pSeries_smp.c | 3 ++- arch/ppc64/kernel/xics.c | 9 +++++++-- include/asm-ppc64/xics.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c index da4b63fbb7ae..f8f2007b8885 100644 --- a/arch/ppc64/kernel/pSeries_smp.c +++ b/arch/ppc64/kernel/pSeries_smp.c @@ -265,7 +265,8 @@ static void __devinit smp_xics_setup_cpu(int cpu) * necessary from a secondary thread as the OF start-cpu interface * performs this function for us on primary threads. */ - rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, default_distrib_server, 1); + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); #endif } diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index dd88142ebf39..eca025abe098 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -91,6 +91,7 @@ static int xics_irq_8259_cascade_real = 0; static unsigned int default_server = 0xFF; /* also referenced in smp.c... */ unsigned int default_distrib_server = 0; +unsigned int interrupt_server_size = 8; /* * XICS only has a single IPI, so encode the messages per CPU @@ -511,6 +512,10 @@ nextnode: default_server = ireg[0]; default_distrib_server = ireg[i-1]; /* take last element */ } + ireg = (uint *)get_property(np, + "ibm,interrupt-server#-size", NULL); + if (ireg) + interrupt_server_size = *ireg; break; } } @@ -650,9 +655,9 @@ void xics_migrate_irqs_away(void) ops->cppr_info(cpu, 0); iosync(); - /* Refuse any new interrupts... */ + /* remove ourselves from the global interrupt queue */ status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, - hard_smp_processor_id(), 0); + (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); WARN_ON(status != 0); /* Allow IPIs again... */ diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h index 6b9aedc6eadb..0027da4364ac 100644 --- a/include/asm-ppc64/xics.h +++ b/include/asm-ppc64/xics.h @@ -31,5 +31,6 @@ struct xics_ipi_struct { extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; extern unsigned int default_distrib_server; +extern unsigned int interrupt_server_size; #endif /* _PPC64_KERNEL_XICS_H */ -- cgit v1.2.3 From a46596def4cc4beb3f850dee0f2643fa3cc88ce0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:47:21 -0800 Subject: [PATCH] x86_64: Fix sparse warnings Fix sparse warnings warning: cast removes address space of expression for uses of put_user() on x86_64 caused by doing __m(addr) in __put_user_asm() with addr a __user pointer. Signed-off-by: Roland Dreier Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h index 406102dbf298..926e614e60d6 100644 --- a/include/asm-x86_64/uaccess.h +++ b/include/asm-x86_64/uaccess.h @@ -172,7 +172,7 @@ do { \ /* FIXME: this hack is definitely wrong -AK */ struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct *)(x)) +#define __m(x) (*(struct __large_struct __user *)(x)) /* * Tell gcc we read from memory instead of writing: this is because -- cgit v1.2.3 From 6d925f6d2b0c955ee1185f9923b5aa2f02a3d7fd Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:47:35 -0800 Subject: [PATCH] x86_64: Fix some gcc 4 warnings in arch/x86_64 Fix some gcc 4 warnings in arch/x86_64 There are tons more outside though. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/head64.c | 13 +++++++------ arch/x86_64/kernel/setup.c | 8 ++++---- arch/x86_64/kernel/signal.c | 2 +- include/asm-x86_64/msr.h | 3 ++- include/asm-x86_64/unistd.h | 2 +- 5 files changed, 15 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 5254e90a8113..6cad46c98a23 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -61,16 +61,17 @@ static void __init copy_bootdata(char *real_mode_data) static void __init setup_boot_cpu_data(void) { - int dummy, eax; + unsigned int dummy, eax; /* get vendor info */ - cpuid(0, &boot_cpu_data.cpuid_level, - (int *)&boot_cpu_data.x86_vendor_id[0], - (int *)&boot_cpu_data.x86_vendor_id[8], - (int *)&boot_cpu_data.x86_vendor_id[4]); + cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level, + (unsigned int *)&boot_cpu_data.x86_vendor_id[0], + (unsigned int *)&boot_cpu_data.x86_vendor_id[8], + (unsigned int *)&boot_cpu_data.x86_vendor_id[4]); /* get cpu type */ - cpuid(1, &eax, &dummy, &dummy, (int *) &boot_cpu_data.x86_capability); + cpuid(1, &eax, &dummy, &dummy, + (unsigned int *) &boot_cpu_data.x86_capability); boot_cpu_data.x86 = (eax >> 8) & 0xf; boot_cpu_data.x86_model = (eax >> 4) & 0xf; boot_cpu_data.x86_mask = eax & 0xf; diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 1bf8d4e95e92..7a7be426f5af 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -849,10 +849,10 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) memset(&c->x86_capability, 0, sizeof c->x86_capability); /* Get vendor name */ - cpuid(0x00000000, &c->cpuid_level, - (int *)&c->x86_vendor_id[0], - (int *)&c->x86_vendor_id[8], - (int *)&c->x86_vendor_id[4]); + cpuid(0x00000000, (unsigned int *)&c->cpuid_level, + (unsigned int *)&c->x86_vendor_id[0], + (unsigned int *)&c->x86_vendor_id[8], + (unsigned int *)&c->x86_vendor_id[4]); get_cpu_vendor(c); diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index e9aa2ca0b55d..df01c50b7177 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -139,7 +139,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; - long eax; + unsigned long eax; frame = (struct rt_sigframe __user *)(regs->rsp - 8); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index ed94245a5d4f..850695678419 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h @@ -67,7 +67,8 @@ : "=a" (low), "=d" (high) \ : "c" (counter)) -extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) +extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) { __asm__("cpuid" : "=a" (*eax), diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index 506ec8d12e75..f1a510a9b195 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -724,7 +724,7 @@ static inline long dup(unsigned int fd) } /* implemented in asm in arch/x86_64/kernel/entry.S */ -extern long execve(char *, char **, char **); +extern int execve(const char *, char * const *, char * const *); static inline long open(const char * filename, int flags, int mode) { -- cgit v1.2.3 From e77da0004873c55d33962075b2625e728f1568eb Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:47:47 -0800 Subject: [PATCH] i386: Port missing cpuid bits from x86-64 to i386 Port missing cpuid bits from x86-64 to i386 Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 4 +++- arch/i386/kernel/cpu/proc.c | 10 ++++++++-- include/asm-i386/cpufeature.h | 6 +++++- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index aef962cac862..35f37a3d3954 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -274,8 +274,10 @@ void __init generic_identify(struct cpuinfo_x86 * c) /* AMD-defined flags: level 0x80000001 */ xlvl = cpuid_eax(0x80000000); if ( (xlvl & 0xffff0000) == 0x80000000 ) { - if ( xlvl >= 0x80000001 ) + if ( xlvl >= 0x80000001 ) { c->x86_capability[1] = cpuid_edx(0x80000001); + c->x86_capability[6] = cpuid_ecx(0x80000001); + } if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 4ba834c44ea5..8c179a948131 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -28,7 +28,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, - NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -45,7 +45,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", - "tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL, + "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -54,6 +54,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* AMD-defined (#2) */ + "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; struct cpuinfo_x86 *c = v; int i, n = c - cpu_data; diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index fdbd65ca669e..e147cabd3bfe 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -9,7 +9,7 @@ #include -#define NCAPINTS 6 /* Currently we have 6 32-bit words worth of info */ +#define NCAPINTS 7 /* N 32-bit words worth of info */ /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ @@ -77,6 +77,7 @@ #define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ #define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ #define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ @@ -85,6 +86,9 @@ #define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ #define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (5*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (5*32+ 1) /* If yes HyperThreading not valid */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) -- cgit v1.2.3 From b9662b21dd274ff9c9d1ddbc85b90f7cebf38d03 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:48:01 -0800 Subject: [PATCH] i386: AMD dual core support for i386 AMD dual core support for i386 Run HT initialization on AMD dual core CPUs on i386. They fake being HT CPUs. This patch makes the HT detection run on AMD CPUs too. I moved the HT detection code into a common file from intel.c for that. It would be actually better to run HT detection always on all CPUs but this would need a second callback afterwards to AMD code, which I avoided for now. It adds a cpuinfo->x86_num_cores field. This sets up the phys_proc_id[] array. This overloads this array with HT, but when smp_num_siblings is 1 It is currently only used for /proc/cpuinfo printing. The reason we want to behave this like SMT is that there are some license managers in user space that license according to number of physical CPUs, and when they handle HT they should handle CMP with this hack too. Another reason we need this is that the powernow k8 driver needs this information to properly manage dual core CPUs. When there are ever dual core HT CPUs this will need small changes in smpboot.c. I didn't do this for now to keep the patch simple. Then we set smp_num_siblings to 1 on these systems again to prevent the scheduler from setting up HT scheduling (which is not a very good match for dual core). This is a port of the CMP support code from x86-64 (minus the NUMA bits) Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/amd.c | 17 +++++++++++++++ arch/i386/kernel/cpu/common.c | 48 +++++++++++++++++++++++++++++++++++++++++++ arch/i386/kernel/cpu/intel.c | 43 +------------------------------------- include/asm-i386/processor.h | 3 +++ 4 files changed, 69 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 091b98ae93b6..ae94585d0445 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -188,6 +188,23 @@ static void __init init_amd(struct cpuinfo_x86 *c) } display_cacheinfo(c); + detect_ht(c); + +#ifdef CONFIG_X86_HT + /* AMD dual core looks like HT but isn't really. Hide it from the + scheduler. This works around problems with the domain scheduler. + Also probably gives slightly better scheduling and disables + SMT nice which is harmful on dual core. + TBD tune the domain scheduler for dual core. */ + if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) + smp_num_siblings = 1; +#endif + + if (cpuid_eax(0x80000000) >= 0x80000008) { + c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; + if (c->x86_num_cores & (c->x86_num_cores - 1)) + c->x86_num_cores = 1; + } } static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 35f37a3d3954..5761150d84e0 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -10,6 +10,11 @@ #include #include #include +#ifdef CONFIG_X86_LOCAL_APIC +#include +#include +#include +#endif #include "cpu.h" @@ -323,6 +328,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) c->x86_model = c->x86_mask = 0; /* So far unknown... */ c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ + c->x86_num_cores = 1; memset(&c->x86_capability, 0, sizeof c->x86_capability); if (!have_cpuid_p()) { @@ -431,6 +437,48 @@ void __init dodgy_tsc(void) cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); } +void __init detect_ht(struct cpuinfo_x86 *c) +{ + u32 eax, ebx, ecx, edx; + int index_lsb, index_msb, tmp; + int cpu = smp_processor_id(); + + if (!cpu_has(c, X86_FEATURE_HT)) + return; + + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; + + if (smp_num_siblings == 1) { + printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + } else if (smp_num_siblings > 1 ) { + index_lsb = 0; + index_msb = 31; + + if (smp_num_siblings > NR_CPUS) { + printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); + smp_num_siblings = 1; + return; + } + tmp = smp_num_siblings; + while ((tmp & 1) == 0) { + tmp >>=1 ; + index_lsb++; + } + tmp = smp_num_siblings; + while ((tmp & 0x80000000 ) == 0) { + tmp <<=1 ; + index_msb--; + } + if (index_lsb != index_msb ) + index_msb++; + phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + phys_proc_id[cpu]); + } +} + void __init print_cpu_info(struct cpuinfo_x86 *c) { char *vendor = NULL; diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index eb145ed88d6a..ec3858cf4c5a 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -140,48 +140,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) strcpy(c->x86_model_id, p); #ifdef CONFIG_X86_HT - if (cpu_has(c, X86_FEATURE_HT)) { - extern int phys_proc_id[NR_CPUS]; - - u32 eax, ebx, ecx, edx; - int index_lsb, index_msb, tmp; - int cpu = smp_processor_id(); - - cpuid(1, &eax, &ebx, &ecx, &edx); - smp_num_siblings = (ebx & 0xff0000) >> 16; - - if (smp_num_siblings == 1) { - printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); - } else if (smp_num_siblings > 1 ) { - index_lsb = 0; - index_msb = 31; - - if (smp_num_siblings > NR_CPUS) { - printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); - smp_num_siblings = 1; - goto too_many_siblings; - } - tmp = smp_num_siblings; - while ((tmp & 1) == 0) { - tmp >>=1 ; - index_lsb++; - } - tmp = smp_num_siblings; - while ((tmp & 0x80000000 ) == 0) { - tmp <<=1 ; - index_msb--; - } - if (index_lsb != index_msb ) - index_msb++; - phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); - - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - phys_proc_id[cpu]); - } - - } -too_many_siblings: - + detect_ht(c); #endif /* Work around errata */ diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 0d4e4acc3b12..b97d274521b2 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -65,6 +65,7 @@ struct cpuinfo_x86 { int f00f_bug; int coma_bug; unsigned long loops_per_jiffy; + unsigned char x86_num_cores; } __attribute__((__aligned__(SMP_CACHE_BYTES))); #define X86_VENDOR_INTEL 0 @@ -96,12 +97,14 @@ extern struct cpuinfo_x86 cpu_data[]; #define current_cpu_data boot_cpu_data #endif +extern int phys_proc_id[NR_CPUS]; extern char ignore_fpu_irq; extern void identify_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); extern void dodgy_tsc(void); +extern void detect_ht(struct cpuinfo_x86 *c); /* * EFLAGS bits -- cgit v1.2.3 From 42382d56082e4a545f0d0851f9b57d4ba30faab0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:48:14 -0800 Subject: [PATCH] i386: Count both multi cores and SMP siblings in /proc/cpuinfo siblings. Count both multi cores and SMP siblings in /proc/cpuinfo siblings. This avoids breaking user space licensing managers who license by CPU on dual core systems. Port of the equivalent code on x86-64. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 2 ++ arch/i386/kernel/cpu/intel.c | 2 -- arch/i386/kernel/cpu/proc.c | 7 ++----- include/asm-i386/processor.h | 5 +++++ 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 5761150d84e0..b619be984d5a 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -437,6 +437,7 @@ void __init dodgy_tsc(void) cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); } +#ifdef CONFIG_X86_HT void __init detect_ht(struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx; @@ -478,6 +479,7 @@ void __init detect_ht(struct cpuinfo_x86 *c) phys_proc_id[cpu]); } } +#endif void __init print_cpu_info(struct cpuinfo_x86 *c) { diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index ec3858cf4c5a..b8d847b850dc 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -139,9 +139,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) if ( p ) strcpy(c->x86_model_id, p); -#ifdef CONFIG_X86_HT detect_ht(c); -#endif /* Work around errata */ Intel_errata_workarounds(c); diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 8c179a948131..c8d83fdc237a 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -94,11 +94,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_X86_HT - if (smp_num_siblings > 1) { - extern int phys_proc_id[NR_CPUS]; - seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); - seq_printf(m, "siblings\t: %d\n", smp_num_siblings); - } + seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); + seq_printf(m, "siblings\t: %d\n", c->x86_num_cores * smp_num_siblings); #endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index b97d274521b2..70a48f509d24 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -104,7 +104,12 @@ extern void identify_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); extern void dodgy_tsc(void); + +#ifdef CONFIG_X86_HT extern void detect_ht(struct cpuinfo_x86 *c); +#else +static inline void detect_ht(struct cpuinfo_x86 *c) {} +#endif /* * EFLAGS bits -- cgit v1.2.3 From 82a7151979b57d1ca84792ddf19efccc247c9558 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:48:40 -0800 Subject: [PATCH] x86_64: Move memset_io out of line to avoid warnings. Move memset_io out of line to avoid warnings. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/lib/io.c | 8 ++++++++ include/asm-x86_64/io.h | 6 ++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/x86_64/lib/io.c b/arch/x86_64/lib/io.c index df68a2623736..87b4a4e18039 100644 --- a/arch/x86_64/lib/io.c +++ b/arch/x86_64/lib/io.c @@ -13,3 +13,11 @@ void __memcpy_fromio(void *dst,unsigned long src,unsigned len) __inline_memcpy(dst,(const void *) src,len); } EXPORT_SYMBOL(__memcpy_fromio); + +void memset_io(volatile void __iomem *a, int b, size_t c) +{ + /* XXX: memset can mangle the IO patterns quite a bit. + perhaps it would be better to use a dumb one */ + memset((void *)a,b,c); +} +EXPORT_SYMBOL(memset_io); diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h index ce379aee7355..734db492e889 100644 --- a/include/asm-x86_64/io.h +++ b/include/asm-x86_64/io.h @@ -260,10 +260,8 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, unsi { __memcpy_toio((unsigned long)to,from,len); } -static inline void memset_io(volatile void __iomem *a, int b, size_t c) -{ - memset((__force void *)a,b,c); -} + +void memset_io(volatile void __iomem *a, int b, size_t c); /* * ISA space is 'always mapped' on a typical x86 system, no need to -- cgit v1.2.3 From 54465502760ca40444639dcb8114860dda8a5453 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:48:53 -0800 Subject: [PATCH] x86_64: Fix ioremap attribute restoration on i386 and x86-64 We need to save the access flags to properly restore the direct mapping on unmap. For that we use some upper bits in vm_flags Also add a comment for that to the header file. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/ioremap.c | 6 +++--- arch/x86_64/mm/ioremap.c | 10 +++++----- include/linux/vmalloc.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index 1aa488b7f999..58ff04eeb9db 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c @@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr) if (!p) { printk("__iounmap: bad address %p\n", addr); return; - } + } - if (p->flags && p->phys_addr < virt_to_phys(high_memory) - 1) { + if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, PAGE_KERNEL); diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index 1a166779eeba..12363e69b0c3 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l if (phys_addr >= 0xA0000 && last_addr < 0x100000) return (__force void __iomem *)phys_to_virt(phys_addr); +#ifndef CONFIG_DISCONTIGMEM /* * Don't allow anybody to remap normal RAM that we're using.. */ - if (phys_addr < virt_to_phys(high_memory)) { -#ifndef CONFIG_DISCONTIGMEM + if (last_addr < virt_to_phys(high_memory)) { char *t_addr, *t_end; struct page *page; @@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; -#endif } +#endif /* * Mappings have to be page-aligned @@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP | (flags << 24)); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr) } *pprev = p->next; unmap_vm_area(p); - if ((p->flags >> 24) && + if ((p->flags >> 20) && p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 8c68717810c3..9af7ad38c08d 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -8,6 +8,7 @@ #define VM_IOREMAP 0x00000001 /* ioremap() and friends */ #define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_MAP 0x00000004 /* vmap()ed pages */ +/* bits [20..32] reserved for arch specific ioremap internals */ struct vm_struct { void *addr; -- cgit v1.2.3 From 46e801e5ad461e6c17cb83bd72d1d84c0cb25626 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:49:46 -0800 Subject: [PATCH] x86_64: Add new key syscalls. Add new key syscalls. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ia32entry.S | 4 ++++ include/asm-x86_64/ia32_unistd.h | 6 +++++- include/asm-x86_64/unistd.h | 10 ++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 4210fa0e6918..270f8ca873ae 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -587,6 +587,10 @@ ia32_sys_call_table: .quad compat_sys_mq_getsetattr .quad quiet_ni_syscall /* reserved for kexec */ .quad sys32_waitid + .quad quiet_ni_syscall /* sys_altroot */ + .quad sys_add_key + .quad sys_request_key + .quad sys_keyctl /* don't forget to change IA32_NR_syscalls */ ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h index 26e56c27fe18..f3b7111cf33d 100644 --- a/include/asm-x86_64/ia32_unistd.h +++ b/include/asm-x86_64/ia32_unistd.h @@ -290,7 +290,11 @@ #define __NR_ia32_mq_getsetattr (__NR_ia32_mq_open+5) #define __NR_ia32_kexec 283 #define __NR_ia32_waitid 284 +/* #define __NR_sys_setaltroot 285 */ +#define __NR_ia32_add_key 286 +#define __NR_ia32_request_key 287 +#define __NR_ia32_keyctl 288 -#define IA32_NR_syscalls 285 /* must be > than biggest syscall! */ +#define IA32_NR_syscalls 290 /* must be > than biggest syscall! */ #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index f1a510a9b195..d9182e600b69 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -556,8 +556,14 @@ __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr) __SYSCALL(__NR_kexec_load, sys_ni_syscall) #define __NR_waitid 247 __SYSCALL(__NR_waitid, sys_waitid) - -#define __NR_syscall_max __NR_waitid +#define __NR_add_key 248 +__SYSCALL(__NR_add_key, sys_add_key) +#define __NR_request_key 249 +__SYSCALL(__NR_request_key, sys_request_key) +#define __NR_keyctl 250 +__SYSCALL(__NR_keyctl, sys_keyctl) + +#define __NR_syscall_max __NR_keyctl #ifndef __NO_STUBS /* user-visible error numbers are in the range -1 - -4095 */ -- cgit v1.2.3 From 9156123ff70b756a4d2385a4bd546e71cf7a9be8 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:50:51 -0800 Subject: [PATCH] x86_64: Cleanups preparing for memory hotplug From: Matt Tolentino Some cleanup work in early page table init preparing for memory hotplug. Hacked up by AK Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/setup.c | 2 +- arch/x86_64/mm/init.c | 48 +++++++++++++++++++++++++--------------------- include/asm-x86_64/proto.h | 2 +- 3 files changed, 28 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 6b0b38c71608..7a8711a03294 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -493,7 +493,7 @@ void __init setup_arch(char **cmdline_p) check_efer(); - init_memory_mapping(); + init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); #ifdef CONFIG_ACPI_BOOT /* diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index c2ac2b4b7842..e4c8d2dc190c 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -252,51 +252,55 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon __flush_tlb(); } +static void __init find_early_table_space(unsigned long end) +{ + unsigned long puds, pmds, tables; + + puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; + pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; + tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + + round_up(pmds * sizeof(pmd_t), PAGE_SIZE); + + table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables); + if (table_start == -1UL) + panic("Cannot find space for the kernel page tables"); + + table_start >>= PAGE_SHIFT; + table_end = table_start; +} + /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __init init_memory_mapping(void) +void __init init_memory_mapping(unsigned long start, unsigned long end) { - unsigned long adr; - unsigned long end; unsigned long next; - unsigned long puds, pmds, tables; Dprintk("init_memory_mapping\n"); - end = end_pfn_map << PAGE_SHIFT; - /* * Find space for the kernel direct mapping tables. * Later we should allocate these tables in the local node of the memory * mapped. Unfortunately this is done currently before the nodes are * discovered. */ + find_early_table_space(end); - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - tables = round_up(puds*8, PAGE_SIZE) + round_up(pmds * 8, PAGE_SIZE); - - table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables); - if (table_start == -1UL) - panic("Cannot find space for the kernel page tables"); + start = (unsigned long)__va(start); + end = (unsigned long)__va(end); - table_start >>= PAGE_SHIFT; - table_end = table_start; - - end += __PAGE_OFFSET; /* turn virtual */ - - for (adr = PAGE_OFFSET; adr < end; adr = next) { + for (; start < end; start = next) { int map; unsigned long pud_phys; pud_t *pud = alloc_low_page(&map, &pud_phys); - next = adr + PGDIR_SIZE; + next = start + PGDIR_SIZE; if (next > end) next = end; - phys_pud_init(pud, adr-PAGE_OFFSET, next-PAGE_OFFSET); - set_pgd(init_level4_pgt + pgd_index(adr), mk_kernel_pgd(pud_phys)); + phys_pud_init(pud, __pa(start), __pa(next)); + set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(map); } + asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); __flush_tlb_all(); early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index e942ca5957e4..3bee3482389a 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h @@ -15,7 +15,7 @@ extern void pda_init(int); extern void early_idt_handler(void); extern void mcheck_init(struct cpuinfo_x86 *c); -extern void init_memory_mapping(void); +extern void init_memory_mapping(unsigned long start, unsigned long end); extern void system_call(void); extern int kernel_syscall(void); -- cgit v1.2.3 From 1d563ebcaf796f4bcf2903336899dcd7c48db429 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 01:51:05 -0800 Subject: [PATCH] x86_64: Remove unused prototypes. Pointed out by Matthew Wilcox. Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86_64/hw_irq.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index 767e11abd5c5..2b5cb2865d21 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h @@ -87,8 +87,6 @@ extern u8 irq_vector[NR_IRQ_VECTORS]; * Interrupt entry/exit code at both C and assembly level */ -extern void mask_irq(unsigned int irq); -extern void unmask_irq(unsigned int irq); extern void disable_8259A_irq(unsigned int irq); extern void enable_8259A_irq(unsigned int irq); extern int i8259A_irq_pending(unsigned int irq); -- cgit v1.2.3 From 1821c54f2a37b7ef2b53dc6cbd3c5da450e182ac Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 01:52:11 -0800 Subject: [PATCH] UML: add some pudding This adds pud_t support to UML. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/mem.c | 3 ++- arch/um/kernel/process_kern.c | 12 +++++++++++- arch/um/kernel/skas/tlb.c | 7 +++++-- arch/um/kernel/tlb.c | 16 ++++++++++++---- arch/um/kernel/trap_kern.c | 7 +++++-- arch/um/kernel/tt/tlb.c | 12 +++++++++--- include/asm-um/pgalloc.h | 14 ++++++++------ include/asm-um/pgtable.h | 35 +++++++++++++++++++++-------------- 8 files changed, 73 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 4279161c8849..77d063d5407f 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -135,7 +135,8 @@ pte_t *kmap_pte; pgprot_t kmap_prot; #define kmap_get_fixmap_pte(vaddr) \ - pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\ + (vaddr)), (vaddr)) void __init kmap_init(void) { diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 2af5a343cf1c..62e6c8ef2e67 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; if(task->mm == NULL) return(ERR_PTR(-EINVAL)); pgd = pgd_offset(task->mm, addr); - pmd = pmd_offset(pgd, addr); + if(!pgd_present(*pgd)) + return(ERR_PTR(-EINVAL)); + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)) + return(ERR_PTR(-EINVAL)); + + pmd = pmd_offset(pud, addr); if(!pmd_present(*pmd)) return(ERR_PTR(-EINVAL)); + pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte)) return(ERR_PTR(-EINVAL)); + if(pte_out != NULL) *pte_out = *pte; return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 02e3e06bb033..3b0d8da430c1 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -18,6 +18,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { pgd_t *npgd; + pmd_t *npud; pmd_t *npmd; pte_t *npte; unsigned long addr; @@ -27,7 +28,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, fd = mm->context.skas.mm_fd; for(addr = start_addr; addr < end_addr;){ npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); + npud = pud_offset(npgd, addr); + npmd = pmd_offset(npud, addr); if(pmd_present(*npmd)){ npte = pte_offset_kernel(npmd, addr); r = pte_read(*npte); @@ -79,7 +81,8 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte) || pte_newpage(*pte)){ diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index c42053140e2b..26f5d12d81f3 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) return(pgd_offset(mm, address)); } -pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) +pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) { - return(pmd_offset(pgd, address)); + return(pud_offset(pgd, address)); +} + +pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) +{ + return(pmd_offset(pud, address)); } pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) @@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) pte_t *addr_pte(struct task_struct *task, unsigned long addr) { - return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr), - addr)); + pgd_t *pgd = pgd_offset(task->mm, addr); + pud_t *pud = pud_offset(pgd, addr); + pmd_t *pmd = pmd_offset(pud, addr); + + return(pte_offset_map(pmd, addr)); } /* diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index cba33ef6da5d..9385a1aefaba 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -13,6 +13,7 @@ #include "linux/ptrace.h" #include "asm/semaphore.h" #include "asm/pgtable.h" +#include "asm/pgalloc.h" #include "asm/tlbflush.h" #include "asm/a.out.h" #include "asm/current.h" @@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long page; @@ -54,8 +56,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; page = address & PAGE_MASK; - pgd = pgd_offset(mm, page); - pmd = pmd_offset(pgd, page); + pgd = pgd_offset(mm); + pud = pud_offset(pgd, page); + pmd = pmd_offset(pud, page); do { survive: switch (handle_mm_fault(mm, vma, address, is_write)){ diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index d8ad334cfac9..ce057e3c1fb4 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -19,6 +19,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { pgd_t *npgd; + pud_t *npud; pmd_t *npmd; pte_t *npte; unsigned long addr; @@ -42,7 +43,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, continue; } npgd = pgd_offset(mm, addr); - npmd = pmd_offset(npgd, addr); + npud = pud_offset(npgd, addr); + npmd = pmd_offset(npud, addr); if(pmd_present(*npmd)){ npte = pte_offset_kernel(npmd, addr); r = pte_read(*npte); @@ -90,6 +92,7 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, { struct mm_struct *mm; pgd_t *pgd; + pud_t *pmd; pmd_t *pmd; pte_t *pte; unsigned long addr; @@ -98,7 +101,8 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(!pte_present(*pte) || pte_newpage(*pte)){ @@ -155,6 +159,7 @@ void mprotect_kernel_vm(int w) { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned long addr; @@ -162,7 +167,8 @@ void mprotect_kernel_vm(int w) mm = &init_mm; for(addr = start_vm; addr < end_vm;){ pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); if(pmd_present(*pmd)){ pte = pte_offset_kernel(pmd, addr); if(pte_present(*pte)) protect_vm_page(addr, w, 0); diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h index 73973aeaf482..d22a15573d83 100644 --- a/include/asm-um/pgalloc.h +++ b/include/asm-um/pgalloc.h @@ -13,12 +13,14 @@ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) -static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, - struct page *pte) -{ - set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); -} +#define pmd_populate(mm, pmd, pte) \ + set_pmd(pmd, __pmd(_PAGE_TABLE + \ + ((unsigned long long)page_to_pfn(pte) << \ + (unsigned long long) PAGE_SHIFT))) +/* + * Allocate and free page tables. + */ extern pgd_t *pgd_alloc(struct mm_struct *); extern void pgd_free(pgd_t *pgd); @@ -45,7 +47,7 @@ static inline void pte_free(struct page *pte) #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_free(x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0) -#define pgd_populate(mm, pmd, pte) BUG() +#define pud_populate(mm, pmd, pte) BUG() #define check_pgt_cache() do { } while (0) diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h index a747f7dd4ff4..e16ea2a3ecd7 100644 --- a/include/asm-um/pgtable.h +++ b/include/asm-um/pgtable.h @@ -7,8 +7,6 @@ #ifndef __UM_PGTABLE_H #define __UM_PGTABLE_H -#include - #include "linux/sched.h" #include "asm/processor.h" #include "asm/page.h" @@ -23,7 +21,6 @@ extern unsigned long *empty_zero_page; #define pgtable_cache_init() do ; while (0) /* PMD_SHIFT determines the size of the area a second-level page table can map */ -#define PMD_SHIFT 22 #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) @@ -39,7 +36,6 @@ extern unsigned long *empty_zero_page; #define PTRS_PER_PTE 1024 #define PTRS_PER_PMD 1 #define PTRS_PER_PGD 1024 -#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_PGD_NR 0 #define pte_ERROR(e) \ @@ -176,6 +172,15 @@ extern pte_t * __bad_pagetable(void); #define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) #define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) +#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE) +#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE) + +static inline pud_t *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr) +{ + BUG(); +} + /* * The "pgd_xxx()" functions here are trivial for a folded two-level * setup: the pgd is never bad, and a pmd always exists (as it's folded @@ -374,15 +379,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * this macro returns the index of the entry in the pgd page which would * control the given virtual address */ -#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) + +#define pgd_index_k(addr) pgd_index(addr) /* * pgd_offset() returns a (pgd_t *) * pgd_index() is used get the offset into the pgd page's array of pgd_t's; */ -#define pgd_offset(mm, address) \ -((mm)->pgd + ((address) >> PGDIR_SHIFT)) - +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* * a shortcut which implies the use of the kernel's pgd, instead @@ -390,15 +395,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) +/* + * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] + * + * this macro returns the index of the entry in the pmd page which would + * control the given virtual address + */ #define pmd_index(address) \ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -/* Find an entry in the second-level page table.. */ -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - /* * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] * @@ -430,6 +435,8 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) #include +#include + #endif #endif -- cgit v1.2.3 From 7d35ecabf698b47a613a2fbc9035d859d331767c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 01:52:52 -0800 Subject: [PATCH] UML: Three-level page table support This is the three-level page table support from the x86_64 patch. It can be enabled on x86, although it's not particularly needed at this point. However, it can be used to implement very large physical memory (with almost all of it in highmem) on UML. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig | 2 + arch/um/Kconfig_i386 | 8 ++ arch/um/Makefile | 2 +- arch/um/defconfig | 1 + arch/um/kernel/mem.c | 5 +- arch/um/kernel/physmem.c | 7 +- arch/um/kernel/skas/tlb.c | 149 ++++++++++++++++++++-------- arch/um/kernel/trap_kern.c | 5 +- arch/um/kernel/tt/tlb.c | 156 +++++++++++++++++++++-------- include/asm-um/page.h | 106 +++++++++++++++++--- include/asm-um/pgalloc.h | 12 +-- include/asm-um/pgtable-2level.h | 83 ++++++++++++++++ include/asm-um/pgtable-3level.h | 172 ++++++++++++++++++++++++++++++++ include/asm-um/pgtable.h | 209 ++++++++++++++------------------------- include/asm-um/vm-flags-i386.h | 14 +++ include/asm-um/vm-flags-x86_64.h | 27 +++++ 16 files changed, 714 insertions(+), 244 deletions(-) create mode 100644 arch/um/Kconfig_i386 create mode 100644 include/asm-um/pgtable-2level.h create mode 100644 include/asm-um/pgtable-3level.h create mode 100644 include/asm-um/vm-flags-i386.h create mode 100644 include/asm-um/vm-flags-x86_64.h (limited to 'include') diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 06ba2aca73a5..633e8a54fde2 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -68,6 +68,8 @@ config MODE_SKAS to CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this option will shrink the UML binary slightly. +source "arch/um/Kconfig_arch" + config NET bool "Networking support" help diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386 new file mode 100644 index 000000000000..e2a5f6692cd6 --- /dev/null +++ b/arch/um/Kconfig_i386 @@ -0,0 +1,8 @@ +config 3_LEVEL_PGTABLES + bool "Three-level pagetables" + default n + help + Three-level pagetables will let UML have more than 4G of physical + memory. All the memory that can't be mapped directly will be treated + as high memory. + diff --git a/arch/um/Makefile b/arch/um/Makefile index b8371a95849a..288a375b9c3b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -17,7 +17,7 @@ core-y += $(ARCH_DIR)/kernel/ \ # Have to precede the include because the included Makefiles reference them. SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ - arch-signal.h module.h + arch-signal.h module.h vm-flags.h SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ diff --git a/arch/um/defconfig b/arch/um/defconfig index 708878e397a9..515581109029 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -17,6 +17,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_MODE_TT=y CONFIG_MODE_SKAS=y +# CONFIG_3_LEVEL_PGTABLES is not set CONFIG_NET=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 77d063d5407f..e8a2c9c5716b 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -25,7 +25,7 @@ extern char __binary_start; /* Changed during early boot */ unsigned long *empty_zero_page = NULL; unsigned long *empty_bad_page = NULL; -pgd_t swapper_pg_dir[1024]; +pgd_t swapper_pg_dir[PTRS_PER_PGD]; unsigned long highmem; int kmalloc_ok = 0; @@ -242,6 +242,7 @@ struct page *arch_validate(struct page *page, int mask, int order) } addr += PAGE_SIZE; } + if(i == (1 << order)) return(page); page = alloc_pages(mask, order); goto again; @@ -336,7 +337,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *pte; - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); + pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 3253bc0e3a5c..2853028657b3 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -309,7 +309,7 @@ struct page *__virt_to_page(const unsigned long virt) return(&mem_map[__pa(virt) >> PAGE_SHIFT]); } -unsigned long page_to_phys(struct page *page) +phys_t page_to_phys(struct page *page) { return((page - mem_map) << PAGE_SHIFT); } @@ -318,8 +318,9 @@ pte_t mk_pte(struct page *page, pgprot_t pgprot) { pte_t pte; - pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot); - if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte)); + pte_set_val(pte, page_to_phys(page), pgprot); + if(pte_present(pte)) + pte_mknewprot(pte_mknewpage(pte)); return(pte); } diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index 3b0d8da430c1..956fb0102a1e 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -18,54 +19,86 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, unsigned long end_addr, int force) { pgd_t *npgd; - pmd_t *npud; + pud_t *npud; pmd_t *npmd; pte_t *npte; - unsigned long addr; + unsigned long addr, end; int r, w, x, err, fd; if(mm == NULL) return; fd = mm->context.skas.mm_fd; for(addr = start_addr; addr < end_addr;){ npgd = pgd_offset(mm, addr); - npud = pud_offset(npgd, addr); - npmd = pmd_offset(npud, addr); - if(pmd_present(*npmd)){ - npte = pte_offset_kernel(npmd, addr); - r = pte_read(*npte); - w = pte_write(*npte); - x = pte_exec(*npte); - if(!pte_dirty(*npte)) w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } - if(force || pte_newpage(*npte)){ - err = unmap(fd, (void *) addr, PAGE_SIZE); + if(!pgd_present(*npgd)){ + if(force || pgd_newpage(*npgd)){ + end = addr + PGDIR_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*npte)) - map(fd, addr, - pte_val(*npte) & PAGE_MASK, - PAGE_SIZE, r, w, x); + pgd_mkuptodate(*npgd); } - else if(pte_newprot(*npte)){ - protect(fd, addr, PAGE_SIZE, r, w, x, 1); + addr += PGDIR_SIZE; + continue; + } + + npud = pud_offset(npgd, addr); + if(!pud_present(*npud)){ + if(force || pud_newpage(*npud)){ + end = addr + PUD_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + pud_mkuptodate(*npud); } - *npte = pte_mkuptodate(*npte); - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + npmd = pmd_offset(npud, addr); + if(!pmd_present(*npmd)){ if(force || pmd_newpage(*npmd)){ - err = unmap(fd, (void *) addr, PMD_SIZE); + end = addr + PMD_SIZE; + if(end > end_addr) + end = end_addr; + err = unmap(fd, (void *) addr, end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); pmd_mkuptodate(*npmd); } addr += PMD_SIZE; + continue; + } + + npte = pte_offset_kernel(npmd, addr); + r = pte_read(*npte); + w = pte_write(*npte); + x = pte_exec(*npte); + if(!pte_dirty(*npte)) + w = 0; + if(!pte_young(*npte)){ + r = 0; + w = 0; } + if(force || pte_newpage(*npte)){ + err = unmap(fd, (void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*npte)) + map(fd, addr, pte_val(*npte) & PAGE_MASK, + PAGE_SIZE, r, w, x); + } + else if(pte_newprot(*npte)) + protect(fd, addr, PAGE_SIZE, r, w, x, 1); + + *npte = pte_mkuptodate(*npte); + addr += PAGE_SIZE; } } @@ -73,9 +106,10 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) { struct mm_struct *mm; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned long addr; + unsigned long addr, last; int updated = 0, err; mm = &init_mm; @@ -83,36 +117,71 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) pgd = pgd_offset(mm, addr); pud = pud_offset(pgd, addr); pmd = pmd_offset(pud, addr); - if(pmd_present(*pmd)){ - pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte) || pte_newpage(*pte)){ + if(!pgd_present(*pgd)){ + if(pgd_newpage(*pgd)){ updated = 1; + last = addr + PGDIR_SIZE; + if(last > end) + last = end; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*pte)) - map_memory(addr, - pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, 1, 1, 1); } - else if(pte_newprot(*pte)){ + addr += PGDIR_SIZE; + continue; + } + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)){ + if(pud_newpage(*pud)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + last = addr + PUD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); } - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + pmd = pmd_offset(pud, addr); + if(!pmd_present(*pmd)){ if(pmd_newpage(*pmd)){ updated = 1; - err = os_unmap_memory((void *) addr, PMD_SIZE); + last = addr + PMD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } addr += PMD_SIZE; + continue; + } + + pte = pte_offset_kernel(pmd, addr); + if(!pte_present(*pte) || pte_newpage(*pte)){ + updated = 1; + err = os_unmap_memory((void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*pte)) + map_memory(addr, pte_val(*pte) & PAGE_MASK, + PAGE_SIZE, 1, 1, 1); } + else if(pte_newprot(*pte)){ + updated = 1; + protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + } + addr += PAGE_SIZE; } } diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 9385a1aefaba..80d07fe6b979 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -56,7 +56,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; page = address & PAGE_MASK; - pgd = pgd_offset(mm); + pgd = pgd_offset(mm, page); pud = pud_offset(pgd, page); pmd = pmd_offset(pud, page); do { @@ -77,6 +77,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, default: BUG(); } + pgd = pgd_offset(mm, page); + pud = pud_offset(pgd, page); + pmd = pmd_offset(pud, page); pte = pte_offset_kernel(pmd, page); } while(!pte_present(*pte)); err = 0; diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index ce057e3c1fb4..3bc35eea1da4 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -22,7 +23,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, pud_t *npud; pmd_t *npmd; pte_t *npte; - unsigned long addr; + unsigned long addr, end; int r, w, x, err; if((current->thread.mode.tt.extern_pid != -1) && @@ -42,46 +43,81 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, addr = STACK_TOP - ABOVE_KMEM; continue; } + npgd = pgd_offset(mm, addr); + if(!pgd_present(*npgd)){ + if(force || pgd_newpage(*npgd)){ + end = addr + PGDIR_SIZE; + if(end > end_addr) + end = end_addr; + err = os_unmap_memory((void *) addr, + end - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + pgd_mkuptodate(*npgd); + } + addr += PGDIR_SIZE; + continue; + } + npud = pud_offset(npgd, addr); - npmd = pmd_offset(npud, addr); - if(pmd_present(*npmd)){ - npte = pte_offset_kernel(npmd, addr); - r = pte_read(*npte); - w = pte_write(*npte); - x = pte_exec(*npte); - if(!pte_dirty(*npte)) w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } - if(force || pte_newpage(*npte)){ + if(!pud_present(*npud)){ + if(force || pud_newpage(*npud)){ + end = addr + PUD_SIZE; + if(end > end_addr) + end = end_addr; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*npte)) - map_memory(addr, - pte_val(*npte) & PAGE_MASK, - PAGE_SIZE, r, w, x); - } - else if(pte_newprot(*npte)){ - protect_memory(addr, PAGE_SIZE, r, w, x, 1); + pud_mkuptodate(*npud); } - *npte = pte_mkuptodate(*npte); - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + npmd = pmd_offset(npud, addr); + if(!pmd_present(*npmd)){ if(force || pmd_newpage(*npmd)){ - err = os_unmap_memory((void *) addr, PMD_SIZE); + end = addr + PMD_SIZE; + if(end > end_addr) + end = end_addr; + err = os_unmap_memory((void *) addr, + end - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); pmd_mkuptodate(*npmd); } addr += PMD_SIZE; + continue; } + + npte = pte_offset_kernel(npmd, addr); + r = pte_read(*npte); + w = pte_write(*npte); + x = pte_exec(*npte); + if(!pte_dirty(*npte)) + w = 0; + if(!pte_young(*npte)){ + r = 0; + w = 0; + } + if(force || pte_newpage(*npte)){ + err = os_unmap_memory((void *) addr, PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", -err); + if(pte_present(*npte)) + map_memory(addr, pte_val(*npte) & PAGE_MASK, + PAGE_SIZE, r, w, x); + } + else if(pte_newprot(*npte)) + protect_memory(addr, PAGE_SIZE, r, w, x, 1); + + *npte = pte_mkuptodate(*npte); + addr += PAGE_SIZE; } } @@ -92,47 +128,83 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, { struct mm_struct *mm; pgd_t *pgd; - pud_t *pmd; + pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned long addr; + unsigned long addr, last; int updated = 0, err; mm = &init_mm; for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); - pud = pud_offset(pgd, addr); - pmd = pmd_offset(pud, addr); - if(pmd_present(*pmd)){ - pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte) || pte_newpage(*pte)){ + if(!pgd_present(*pgd)){ + if(pgd_newpage(*pgd)){ updated = 1; + last = addr + PGDIR_SIZE; + if(last > end) + last = end; err = os_unmap_memory((void *) addr, - PAGE_SIZE); + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); - if(pte_present(*pte)) - map_memory(addr, - pte_val(*pte) & PAGE_MASK, - PAGE_SIZE, 1, 1, 1); } - else if(pte_newprot(*pte)){ + addr += PGDIR_SIZE; + continue; + } + + pud = pud_offset(pgd, addr); + if(!pud_present(*pud)){ + if(pud_newpage(*pud)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + last = addr + PUD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); } - addr += PAGE_SIZE; + addr += PUD_SIZE; + continue; } - else { + + pmd = pmd_offset(pud, addr); + if(!pmd_present(*pmd)){ if(pmd_newpage(*pmd)){ updated = 1; - err = os_unmap_memory((void *) addr, PMD_SIZE); + last = addr + PMD_SIZE; + if(last > end) + last = end; + err = os_unmap_memory((void *) addr, + last - addr); if(err < 0) panic("munmap failed, errno = %d\n", -err); } addr += PMD_SIZE; + continue; + } + + pte = pte_offset_kernel(pmd, addr); + if(!pte_present(*pte) || pte_newpage(*pte)){ + updated = 1; + err = os_unmap_memory((void *) addr, + PAGE_SIZE); + if(err < 0) + panic("munmap failed, errno = %d\n", + -err); + if(pte_present(*pte)) + map_memory(addr, + pte_val(*pte) & PAGE_MASK, + PAGE_SIZE, 1, 1, 1); + } + else if(pte_newprot(*pte)){ + updated = 1; + protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); } + addr += PAGE_SIZE; } if(updated && update_seq) atomic_inc(&vmchange_seq); } diff --git a/include/asm-um/page.h b/include/asm-um/page.h index f69b0f1c270e..3620a08dc9f3 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -8,18 +9,82 @@ struct page; -#include "asm/arch/page.h" +#include +#include -#undef __pa -#undef __va -#undef pfn_to_page -#undef page_to_pfn -#undef virt_to_page -#undef pfn_valid -#undef virt_addr_valid -#undef VALID_PAGE -#undef PAGE_OFFSET -#undef KERNELBASE +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* + * These are used to make use of C type-checking.. + */ + +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) + +#define clear_user_page(page, vaddr, pg) clear_page(page) +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) + +#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64_BIT) + +typedef struct { unsigned long pte_low, pte_high; } pte_t; +typedef struct { unsigned long long pmd; } pmd_t; +typedef struct { unsigned long pgd; } pgd_t; +#define pte_val(x) ((x).pte_low | ((unsigned long long) (x).pte_high << 32)) + +#define pte_get_bits(pte, bits) ((pte).pte_low & (bits)) +#define pte_set_bits(pte, bits) ((pte).pte_low |= (bits)) +#define pte_clear_bits(pte, bits) ((pte).pte_low &= ~(bits)) +#define pte_copy(to, from) ({ (to).pte_high = (from).pte_high; \ + smp_wmb(); \ + (to).pte_low = (from).pte_low; }) +#define pte_is_zero(pte) (!((pte).pte_low & ~_PAGE_NEWPAGE) && !(pte).pte_high) +#define pte_set_val(pte, phys, prot) \ + ({ (pte).pte_high = (phys) >> 32; \ + (pte).pte_low = (phys) | pgprot_val(prot); }) + +typedef unsigned long long pfn_t; +typedef unsigned long long phys_t; + +#else + +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pgd; } pgd_t; + +#ifdef CONFIG_3_LEVEL_PGTABLES +typedef struct { unsigned long pmd; } pmd_t; +#define pmd_val(x) ((x).pmd) +#define __pmd(x) ((pmd_t) { (x) } ) +#endif + +#define pte_val(x) ((x).pte) + + +#define pte_get_bits(p, bits) ((p).pte & (bits)) +#define pte_set_bits(p, bits) ((p).pte |= (bits)) +#define pte_clear_bits(p, bits) ((p).pte &= ~(bits)) +#define pte_copy(to, from) ((to).pte = (from).pte) +#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE)) +#define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot)) + +typedef unsigned long pfn_t; +typedef unsigned long phys_t; + +#endif + +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) extern unsigned long uml_physmem; @@ -30,7 +95,6 @@ extern unsigned long uml_physmem; extern unsigned long to_phys(void *virt); extern void *to_virt(unsigned long phys); - #define __pa(virt) to_phys((void *) virt) #define __va(phys) to_virt((unsigned long) phys) @@ -42,7 +106,21 @@ extern void *to_virt(unsigned long phys); #define pfn_valid(pfn) ((pfn) < max_mapnr) #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v))) - + +/* Pure 2^n version of get_order */ +static __inline__ int get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} + extern struct page *arch_validate(struct page *page, int mask, int order); #define HAVE_ARCH_VALIDATE diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h index d22a15573d83..8fcb2fc0a892 100644 --- a/include/asm-um/pgalloc.h +++ b/include/asm-um/pgalloc.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h * Licensed under the GPL */ @@ -7,11 +8,12 @@ #ifndef __UM_PGALLOC_H #define __UM_PGALLOC_H +#include "linux/config.h" #include "linux/mm.h" #include "asm/fixmap.h" #define pmd_populate_kernel(mm, pmd, pte) \ - set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) + set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) #define pmd_populate(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + \ @@ -39,15 +41,13 @@ static inline void pte_free(struct page *pte) #define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) +#ifdef CONFIG_3_LEVEL_PGTABLES /* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. + * In the 3-level case we free the pmds as part of the pgd. */ - -#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_free(x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0) -#define pud_populate(mm, pmd, pte) BUG() +#endif #define check_pgt_cache() do { } while (0) diff --git a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h new file mode 100644 index 000000000000..f6263d11f205 --- /dev/null +++ b/include/asm-um/pgtable-2level.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. + * Derived from include/asm-i386/pgtable.h + * Licensed under the GPL + */ + +#ifndef __UM_PGTABLE_2LEVEL_H +#define __UM_PGTABLE_2LEVEL_H + +#include + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ + +#define PGDIR_SHIFT 22 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the i386 is two-level, so + * we don't really have any PMD directory physically. + */ +#define PTRS_PER_PTE 1024 +#define PTRS_PER_PMD 1 +#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE) +#define PTRS_PER_PGD 1024 +#define FIRST_USER_PGD_NR 0 + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), \ + pte_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \ + pgd_val(e)) + +static inline int pgd_newpage(pgd_t pgd) { return 0; } +static inline void pgd_mkuptodate(pgd_t pgd) { } + +#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) + +static inline pte_t pte_mknewprot(pte_t pte) +{ + pte_val(pte) |= _PAGE_NEWPROT; + return(pte); +} + +static inline pte_t pte_mknewpage(pte_t pte) +{ + pte_val(pte) |= _PAGE_NEWPAGE; + return(pte); +} + +static inline void set_pte(pte_t *pteptr, pte_t pteval) +{ + /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so + * fix_range knows to unmap it. _PAGE_NEWPROT is specific to + * mapped pages. + */ + *pteptr = pte_mknewpage(pteval); + if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); +} + +#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval)) + +#define pte_page(x) pfn_to_page(pte_pfn(x)) +#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE) +#define pte_pfn(x) phys_to_pfn(pte_val(x)) +#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot)) + +#define pmd_page_kernel(pmd) \ + ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) + +/* + * Bits 0 through 3 are taken + */ +#define PTE_FILE_MAX_BITS 28 + +#define pte_to_pgoff(pte) (pte_val(pte) >> 4) + +#define pgoff_to_pte(off) ((pte_t) { ((off) << 4) + _PAGE_FILE }) + +#endif diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h new file mode 100644 index 000000000000..acebb593cfd6 --- /dev/null +++ b/include/asm-um/pgtable-3level.h @@ -0,0 +1,172 @@ +/* + * Copyright 2003 PathScale Inc + * Derived from include/asm-i386/pgtable.h + * Licensed under the GPL + */ + +#ifndef __UM_PGTABLE_3LEVEL_H +#define __UM_PGTABLE_3LEVEL_H + +#include + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ + +#define PGDIR_SHIFT 30 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* PMD_SHIFT determines the size of the area a second-level page table can + * map + */ + +#define PMD_SHIFT 21 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* + * entries per page directory level + */ + +#define PTRS_PER_PTE 512 +#define PTRS_PER_PMD 512 +#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE) +#define PTRS_PER_PGD 512 +#define FIRST_USER_PGD_NR 0 + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), \ + pte_val(e)) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \ + pmd_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \ + pgd_val(e)) + +#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE)) +#define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) +#define pud_present(x) (pud_val(x) & _PAGE_PRESENT) +#define pud_populate(mm, pud, pmd) \ + set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd))) + +#define set_pud(pudptr, pudval) set_64bit((phys_t *) (pudptr), pud_val(pudval)) +static inline int pgd_newpage(pgd_t pgd) +{ + return(pgd_val(pgd) & _PAGE_NEWPAGE); +} + +static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; } + + +#define pte_present(x) pte_get_bits(x, (_PAGE_PRESENT | _PAGE_PROTNONE)) + +static inline pte_t pte_mknewprot(pte_t pte) +{ + pte_set_bits(pte, _PAGE_NEWPROT); + return(pte); +} + +static inline pte_t pte_mknewpage(pte_t pte) +{ + pte_set_bits(pte, _PAGE_NEWPAGE); + return(pte); +} + +static inline void set_pte(pte_t *pteptr, pte_t pteval) +{ + pte_copy(*pteptr, pteval); + + /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so + * fix_range knows to unmap it. _PAGE_NEWPROT is specific to + * mapped pages. + */ + + *pteptr = pte_mknewpage(*pteptr); + if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); +} + +#define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval)) + +static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL); + + if(pmd) + memset(pmd, 0, PAGE_SIZE); + + return pmd; +} + +static inline void pmd_free(pmd_t *pmd){ + free_page((unsigned long) pmd); +} + +#define __pmd_free_tlb(tlb,x) do { } while (0) + +static inline void pud_clear (pud_t * pud) { } + +#define pud_page(pud) \ + ((struct page *) __va(pud_val(pud) & PAGE_MASK)) + +/* Find an entry in the second-level page table.. */ +#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \ + pmd_index(address)) + +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +static inline int pte_none(pte_t pte) +{ + return pte_is_zero(pte); +} + +static inline unsigned long pte_pfn(pte_t pte) +{ + return phys_to_pfn(pte_val(pte)); +} + +static inline pte_t pfn_pte(pfn_t page_nr, pgprot_t pgprot) +{ + pte_t pte; + phys_t phys = pfn_to_phys(page_nr); + + pte_set_val(pte, phys, pgprot); + return pte; +} + +static inline pmd_t pfn_pmd(pfn_t page_nr, pgprot_t pgprot) +{ + return __pmd((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)); +} + +/* + * Bits 0 through 3 are taken in the low part of the pte, + * put the 32 bits of offset into the high part. + */ +#define PTE_FILE_MAX_BITS 32 + +#ifdef CONFIG_64_BIT + +#define pte_to_pgoff(p) ((p).pte >> 32) + +#define pgoff_to_pte(off) ((pte_t) { ((off) < 32) | _PAGE_FILE }) + +#else + +#define pte_to_pgoff(pte) ((pte).pte_high) + +#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) }) + +#endif + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h index e16ea2a3ecd7..7f980a262334 100644 --- a/include/asm-um/pgtable.h +++ b/include/asm-um/pgtable.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Derived from include/asm-i386/pgtable.h * Licensed under the GPL */ @@ -12,6 +13,24 @@ #include "asm/page.h" #include "asm/fixmap.h" +#define _PAGE_PRESENT 0x001 +#define _PAGE_NEWPAGE 0x002 +#define _PAGE_NEWPROT 0x004 +#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */ +#define _PAGE_PROTNONE 0x010 /* If not present */ +#define _PAGE_RW 0x020 +#define _PAGE_USER 0x040 +#define _PAGE_ACCESSED 0x080 +#define _PAGE_DIRTY 0x100 + +#ifdef CONFIG_3_LEVEL_PGTABLES +#include "asm/pgtable-3level.h" +#else +#include "asm/pgtable-2level.h" +#endif + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt, pte_t *pte_out); @@ -20,33 +39,6 @@ extern unsigned long *empty_zero_page; #define pgtable_cache_init() do ; while (0) -/* PMD_SHIFT determines the size of the area a second-level page table can map */ -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* PGDIR_SHIFT determines what a third-level page table entry can map */ -#define PGDIR_SHIFT 22 -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) - -/* - * entries per page directory level: the i386 is two-level, so - * we don't really have any PMD directory physically. - */ -#define PTRS_PER_PTE 1024 -#define PTRS_PER_PMD 1 -#define PTRS_PER_PGD 1024 -#define FIRST_USER_PGD_NR 0 - -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -#define pmd_ERROR(e) \ - printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) - -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; - /* * pgd entries used up by user/kernel: */ @@ -66,7 +58,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern unsigned long end_iomem; #define VMALLOC_OFFSET (__va_space) -#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) +#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #ifdef CONFIG_HIGHMEM # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) @@ -74,18 +66,8 @@ extern unsigned long end_iomem; # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) #endif -#define _PAGE_PRESENT 0x001 -#define _PAGE_NEWPAGE 0x002 -#define _PAGE_NEWPROT 0x004 -#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */ -#define _PAGE_PROTNONE 0x010 /* If not present */ -#define _PAGE_RW 0x020 -#define _PAGE_USER 0x040 -#define _PAGE_ACCESSED 0x080 -#define _PAGE_DIRTY 0x100 - -#define REGION_MASK 0xf0000000 -#define REGION_SHIFT 28 +#define REGION_SHIFT (sizeof(pte_t) * 8 - 4) +#define REGION_MASK (((unsigned long) 0xf) << REGION_SHIFT) #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) @@ -153,16 +135,13 @@ extern pte_t * __bad_pagetable(void); /* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE) -#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) - -#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0) +#define pte_clear(xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE)) #define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE)) #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) @@ -181,67 +160,13 @@ static inline pud_t *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, BUG(); } -/* - * The "pgd_xxx()" functions here are trivial for a folded two-level - * setup: the pgd is never bad, and a pmd always exists (as it's folded - * into the pgd entry) - */ -static inline int pgd_none(pgd_t pgd) { return 0; } -static inline int pgd_bad(pgd_t pgd) { return 0; } -static inline int pgd_present(pgd_t pgd) { return 1; } -static inline void pgd_clear(pgd_t * pgdp) { } - - #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -#define pte_page(pte) phys_to_page(pte_val(pte)) #define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK) -#define pte_pfn(x) phys_to_pfn(pte_val(x)) -#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot)) - -extern struct page *phys_to_page(const unsigned long phys); -extern struct page *__virt_to_page(const unsigned long virt); -#define virt_to_page(addr) __virt_to_page((const unsigned long) addr) - -/* - * Bits 0 through 3 are taken - */ -#define PTE_FILE_MAX_BITS 28 - -#define pte_to_pgoff(pte) ((pte).pte_low >> 4) - -#define pgoff_to_pte(off) \ - ((pte_t) { ((off) << 4) + _PAGE_FILE }) - -static inline pte_t pte_mknewprot(pte_t pte) -{ - pte_val(pte) |= _PAGE_NEWPROT; - return(pte); -} - -static inline pte_t pte_mknewpage(pte_t pte) -{ - pte_val(pte) |= _PAGE_NEWPAGE; - return(pte); -} - -static inline void set_pte(pte_t *pteptr, pte_t pteval) -{ - /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so - * fix_range knows to unmap it. _PAGE_NEWPROT is specific to - * mapped pages. - */ - *pteptr = pte_mknewpage(pteval); - if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); -} - -/* - * (pmds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ -#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) +#define pte_address(x) (__va(pte_val(x) & PAGE_MASK)) +#define mk_phys(a, r) ((a) + (((unsigned long) r) << REGION_SHIFT)) +#define phys_addr(p) ((p) & ~REGION_MASK) /* * The following only work if pte_present() is true. @@ -249,25 +174,25 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) */ static inline int pte_user(pte_t pte) { - return((pte_val(pte) & _PAGE_USER) && - !(pte_val(pte) & _PAGE_PROTNONE)); + return((pte_get_bits(pte, _PAGE_USER)) && + !(pte_get_bits(pte, _PAGE_PROTNONE))); } static inline int pte_read(pte_t pte) { - return((pte_val(pte) & _PAGE_USER) && - !(pte_val(pte) & _PAGE_PROTNONE)); + return((pte_get_bits(pte, _PAGE_USER)) && + !(pte_get_bits(pte, _PAGE_PROTNONE))); } static inline int pte_exec(pte_t pte){ - return((pte_val(pte) & _PAGE_USER) && - !(pte_val(pte) & _PAGE_PROTNONE)); + return((pte_get_bits(pte, _PAGE_USER)) && + !(pte_get_bits(pte, _PAGE_PROTNONE))); } static inline int pte_write(pte_t pte) { - return((pte_val(pte) & _PAGE_RW) && - !(pte_val(pte) & _PAGE_PROTNONE)); + return((pte_get_bits(pte, _PAGE_RW)) && + !(pte_get_bits(pte, _PAGE_PROTNONE))); } /* @@ -275,85 +200,98 @@ static inline int pte_write(pte_t pte) */ static inline int pte_file(pte_t pte) { - return (pte).pte_low & _PAGE_FILE; + return pte_get_bits(pte, _PAGE_FILE); +} + +static inline int pte_dirty(pte_t pte) +{ + return pte_get_bits(pte, _PAGE_DIRTY); +} + +static inline int pte_young(pte_t pte) +{ + return pte_get_bits(pte, _PAGE_ACCESSED); +} + +static inline int pte_newpage(pte_t pte) +{ + return pte_get_bits(pte, _PAGE_NEWPAGE); } -static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; } static inline int pte_newprot(pte_t pte) { - return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT)); + return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT))); } static inline pte_t pte_rdprotect(pte_t pte) { - pte_val(pte) &= ~_PAGE_USER; + pte_clear_bits(pte, _PAGE_USER); return(pte_mknewprot(pte)); } static inline pte_t pte_exprotect(pte_t pte) { - pte_val(pte) &= ~_PAGE_USER; + pte_clear_bits(pte, _PAGE_USER); return(pte_mknewprot(pte)); } static inline pte_t pte_mkclean(pte_t pte) { - pte_val(pte) &= ~_PAGE_DIRTY; + pte_clear_bits(pte, _PAGE_DIRTY); return(pte); } static inline pte_t pte_mkold(pte_t pte) { - pte_val(pte) &= ~_PAGE_ACCESSED; + pte_clear_bits(pte, _PAGE_ACCESSED); return(pte); } static inline pte_t pte_wrprotect(pte_t pte) { - pte_val(pte) &= ~_PAGE_RW; + pte_clear_bits(pte, _PAGE_RW); return(pte_mknewprot(pte)); } static inline pte_t pte_mkread(pte_t pte) { - pte_val(pte) |= _PAGE_USER; + pte_set_bits(pte, _PAGE_RW); return(pte_mknewprot(pte)); } static inline pte_t pte_mkexec(pte_t pte) { - pte_val(pte) |= _PAGE_USER; + pte_set_bits(pte, _PAGE_USER); return(pte_mknewprot(pte)); } static inline pte_t pte_mkdirty(pte_t pte) { - pte_val(pte) |= _PAGE_DIRTY; + pte_set_bits(pte, _PAGE_DIRTY); return(pte); } static inline pte_t pte_mkyoung(pte_t pte) { - pte_val(pte) |= _PAGE_ACCESSED; + pte_set_bits(pte, _PAGE_ACCESSED); return(pte); } static inline pte_t pte_mkwrite(pte_t pte) { - pte_val(pte) |= _PAGE_RW; + pte_set_bits(pte, _PAGE_RW); return(pte_mknewprot(pte)); } static inline pte_t pte_mkuptodate(pte_t pte) { - pte_val(pte) &= ~_PAGE_NEWPAGE; - if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT; + pte_clear_bits(pte, _PAGE_NEWPAGE); + if(pte_present(pte)) + pte_clear_bits(pte, _PAGE_NEWPROT); return(pte); } -extern unsigned long page_to_phys(struct page *page); +extern phys_t page_to_phys(struct page *page); /* * Conversion functions: convert a page and protection to a page entry, @@ -362,11 +300,9 @@ extern unsigned long page_to_phys(struct page *page); extern pte_t mk_pte(struct page *page, pgprot_t pgprot); -#define pte_set_val(p, phys, prot) pte_val(p) = (phys | pgprot_val(prot)) - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); + pte_set_val(pte, (pte_val(pte) & _PAGE_CHG_MASK), newprot); if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte)); return pte; } @@ -401,8 +337,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * this macro returns the index of the entry in the pmd page which would * control the given virtual address */ -#define pmd_index(address) \ - (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) /* * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] @@ -435,11 +370,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #include -#include +#include #endif - #endif + +extern struct page *phys_to_page(const unsigned long phys); +extern struct page *__virt_to_page(const unsigned long virt); +#define virt_to_page(addr) __virt_to_page((const unsigned long) addr) + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/include/asm-um/vm-flags-i386.h b/include/asm-um/vm-flags-i386.h new file mode 100644 index 000000000000..e0d24c568dbc --- /dev/null +++ b/include/asm-um/vm-flags-i386.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#ifndef __VM_FLAGS_I386_H +#define __VM_FLAGS_I386_H + +#define VM_DATA_DEFAULT_FLAGS \ + (VM_READ | VM_WRITE | \ + ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#endif diff --git a/include/asm-um/vm-flags-x86_64.h b/include/asm-um/vm-flags-x86_64.h new file mode 100644 index 000000000000..e04e92d64858 --- /dev/null +++ b/include/asm-um/vm-flags-x86_64.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * Copyright 2003 PathScale, Inc. + * Licensed under the GPL + */ + +#ifndef __VM_FLAGS_X86_64_H +#define __VM_FLAGS_X86_64_H + +#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \ + VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \ + VM_MAYEXEC) + +extern unsigned long vm_stack_flags, vm_stack_flags32; +extern unsigned long vm_data_default_flags, vm_data_default_flags32; +extern unsigned long vm_force_exec32; + +#define VM_DATA_DEFAULT_FLAGS \ + (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \ + vm_data_default_flags) + +#define VM_STACK_DEFAULT_FLAGS \ + (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) + +#endif -- cgit v1.2.3 From df69f7acb11b7bd78fd5ec8bcb216e0d70728e03 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 01:53:06 -0800 Subject: [PATCH] UML: x86-64 core support This adds the new files from the x86_64 port which just drop in and don't require any work anywhere else. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile | 6 +- arch/um/Makefile-i386 | 2 + arch/um/Makefile-x86_64 | 35 ++++ arch/um/include/sysdep-x86_64/checksum.h | 151 ++++++++++++++++ arch/um/include/sysdep-x86_64/sigcontext.h | 49 +++++ arch/um/kernel/tt/Makefile | 5 +- arch/um/sys-x86_64/Makefile | 39 ++++ arch/um/sys-x86_64/bugs.c | 122 +++++++++++++ arch/um/sys-x86_64/fault.c | 23 +++ arch/um/sys-x86_64/mem.c | 25 +++ arch/um/sys-x86_64/sigcontext.c | 39 ++++ arch/um/sys-x86_64/signal.c | 276 +++++++++++++++++++++++++++++ arch/um/sys-x86_64/sysrq.c | 49 +++++ arch/um/sys-x86_64/util/Makefile | 10 ++ arch/um/sys-x86_64/util/mk_sc.c | 58 ++++++ arch/um/sys-x86_64/util/mk_thread_kern.c | 21 +++ arch/um/sys-x86_64/util/mk_thread_user.c | 30 ++++ include/asm-um/apic.h | 4 + include/asm-um/module-x86_64.h | 30 ++++ include/asm-um/pda.h | 31 ++++ include/asm-um/prctl.h | 6 + include/asm-um/processor-x86_64.h | 33 ++++ include/asm-um/sigcontext-x86_64.h | 22 +++ include/asm-um/system-x86_64.h | 23 +++ include/asm-um/vm-flags-x86_64.h | 6 + 25 files changed, 1092 insertions(+), 3 deletions(-) create mode 100644 arch/um/include/sysdep-x86_64/checksum.h create mode 100644 arch/um/include/sysdep-x86_64/sigcontext.h create mode 100644 arch/um/sys-x86_64/Makefile create mode 100644 arch/um/sys-x86_64/bugs.c create mode 100644 arch/um/sys-x86_64/fault.c create mode 100644 arch/um/sys-x86_64/mem.c create mode 100644 arch/um/sys-x86_64/sigcontext.c create mode 100644 arch/um/sys-x86_64/signal.c create mode 100644 arch/um/sys-x86_64/sysrq.c create mode 100644 arch/um/sys-x86_64/util/Makefile create mode 100644 arch/um/sys-x86_64/util/mk_sc.c create mode 100644 arch/um/sys-x86_64/util/mk_thread_kern.c create mode 100644 arch/um/sys-x86_64/util/mk_thread_user.c create mode 100644 include/asm-um/apic.h create mode 100644 include/asm-um/module-x86_64.h create mode 100644 include/asm-um/pda.h create mode 100644 include/asm-um/prctl.h create mode 100644 include/asm-um/processor-x86_64.h create mode 100644 include/asm-um/sigcontext-x86_64.h create mode 100644 include/asm-um/system-x86_64.h (limited to 'include') diff --git a/arch/um/Makefile b/arch/um/Makefile index 288a375b9c3b..62e78418b1ea 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -12,8 +12,7 @@ SHELL := /bin/bash filechk_gen_header = $< core-y += $(ARCH_DIR)/kernel/ \ - $(ARCH_DIR)/drivers/ \ - $(ARCH_DIR)/sys-$(SUBARCH)/ + $(ARCH_DIR)/drivers/ # Have to precede the include because the included Makefiles reference them. SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ @@ -38,6 +37,9 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) +core-y += $(SUBARCH_CORE) +libs-y += $(SUBARCH_LIBS) + # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common # in CFLAGS. Otherwise, it would cause ld to complain about the two different diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 7c7d008478b6..43991d9e3437 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -1,3 +1,5 @@ +SUBARCH_CORE := arch/um/sys-i386/ + ifeq ($(CONFIG_HOST_2G_2G), y) TOP_ADDR := 0x80000000 else diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 705df73454c8..9638cac93165 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -1 +1,36 @@ +# Copyright 2003 - 2004 Pathscale, Inc +# Released under the GPL + +SUBARCH_LIBS := arch/um/sys-x86_64/ +START := 0x60000000 + +CFLAGS += -U__$(SUBARCH)__ -fno-builtin ARCH_USER_CFLAGS := -D__x86_64__ + +ELF_ARCH := i386:x86-64 +ELF_FORMAT := elf64-x86-64 + +SYS_UTIL_DIR := $(ARCH_DIR)/sys-x86_64/util +SYS_DIR := $(ARCH_DIR)/include/sysdep-x86_64 + +SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h + +prepare: $(SYS_HEADERS) + +$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc + $(call filechk,gen_header) + +$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread + $(call filechk,gen_header) + +$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +CLEAN_FILES += $(SYS_HEADERS) + +LIBC_DIR := /usr/lib64 + +export LIBC_DIR diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h new file mode 100644 index 000000000000..d57aa7f3130e --- /dev/null +++ b/arch/um/include/sysdep-x86_64/checksum.h @@ -0,0 +1,151 @@ +/* + * Licensed under the GPL + */ + +#ifndef __UM_SYSDEP_CHECKSUM_H +#define __UM_SYSDEP_CHECKSUM_H + +#include "linux/string.h" +#include "linux/in6.h" +#include "asm/uaccess.h" + +extern unsigned int csum_partial_copy_from(const char *src, char *dst, int len, + int sum, int *err_ptr); +extern unsigned csum_partial(const unsigned char *buff, unsigned len, + unsigned sum); + +/* + * Note: when you get a NULL pointer exception here this means someone + * passed in an incorrect kernel address to one of these functions. + * + * If you use these functions directly please don't forget the + * verify_area(). + */ + +static __inline__ +unsigned int csum_partial_copy_nocheck(const char *src, char *dst, + int len, int sum) +{ + memcpy(dst, src, len); + return(csum_partial(dst, len, sum)); +} + +static __inline__ +unsigned int csum_partial_copy_from_user(const char *src, char *dst, + int len, int sum, int *err_ptr) +{ + return csum_partial_copy_from(src, dst, len, sum, err_ptr); +} + +/** + * csum_fold - Fold and invert a 32bit checksum. + * sum: 32bit unfolded sum + * + * Fold a 32bit running checksum to 16bit and invert it. This is usually + * the last step before putting a checksum into a packet. + * Make sure not to mix with 64bit checksums. + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + __asm__( + " addl %1,%0\n" + " adcl $0xffff,%0" + : "=r" (sum) + : "r" (sum << 16), "0" (sum & 0xffff0000) + ); + return (~sum) >> 16; +} + +/** + * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum. + * @saddr: source address + * @daddr: destination address + * @len: length of packet + * @proto: ip protocol of packet + * @sum: initial sum to be added in (32bit unfolded) + * + * Returns the pseudo header checksum the input data. Result is + * 32bit unfolded. + */ +static inline unsigned long +csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len, + unsigned short proto, unsigned int sum) +{ + asm(" addl %1, %0\n" + " adcl %2, %0\n" + " adcl %3, %0\n" + " adcl $0, %0\n" + : "=r" (sum) + : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum)); + return sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/** + * ip_fast_csum - Compute the IPv4 header checksum efficiently. + * iph: ipv4 header + * ihl: length of header / 4 + */ +static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) +{ + unsigned int sum; + + asm( " movl (%1), %0\n" + " subl $4, %2\n" + " jbe 2f\n" + " addl 4(%1), %0\n" + " adcl 8(%1), %0\n" + " adcl 12(%1), %0\n" + "1: adcl 16(%1), %0\n" + " lea 4(%1), %1\n" + " decl %2\n" + " jne 1b\n" + " adcl $0, %0\n" + " movl %0, %2\n" + " shrl $16, %0\n" + " addw %w2, %w0\n" + " adcl $0, %0\n" + " notl %0\n" + "2:" + /* Since the input registers which are loaded with iph and ipl + are modified, we must also specify them as outputs, or gcc + will assume they contain their original values. */ + : "=r" (sum), "=r" (iph), "=r" (ihl) + : "1" (iph), "2" (ihl) + : "memory"); + return(sum); +} + +static inline unsigned add32_with_carry(unsigned a, unsigned b) +{ + asm("addl %2,%0\n\t" + "adcl $0,%0" + : "=r" (a) + : "0" (a), "r" (b)); + return a; +} + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h new file mode 100644 index 000000000000..6a0c346b6404 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/sigcontext.h @@ -0,0 +1,49 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_SIGCONTEXT_H +#define __SYSDEP_X86_64_SIGCONTEXT_H + +#include "sc.h" + +#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) + +#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) +#define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result) + +#define SC_FAULT_ADDR(sc) SC_CR2(sc) +#define SC_FAULT_TYPE(sc) SC_ERR(sc) + +#define FAULT_WRITE(err) ((err) & 2) + +#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc)) + +#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) + +/* ptrace expects that, at the start of a system call, %eax contains + * -ENOSYS, so this makes it so. + */ + +#define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) + +#define SEGV_IS_FIXABLE(trap) ((trap) == 14) +#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc)) + +extern unsigned long *sc_sigmask(void *sc_ptr); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ + diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile index 17f4594dc231..7c9eec5fded5 100644 --- a/arch/um/kernel/tt/Makefile +++ b/arch/um/kernel/tt/Makefile @@ -24,6 +24,9 @@ $(USER_OBJS) : %.o: %.c $(obj)/unmap.o: $(src)/unmap.c $(CC) $(UNMAP_CFLAGS) -c -o $@ $< +LIBC_DIR ?= /usr/lib + $(obj)/unmap_fin.o : $(obj)/unmap.o - ld -r -o $(obj)/unmap_tmp.o $< -lc -L/usr/lib + ld -r -o $(obj)/unmap_tmp.o $< -lc -L$(LIBC_DIR) objcopy $(obj)/unmap_tmp.o $@ -G switcheroo + diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile new file mode 100644 index 000000000000..0859685f511a --- /dev/null +++ b/arch/um/sys-x86_64/Makefile @@ -0,0 +1,39 @@ +# +# Copyright 2003 PathScale, Inc. +# +# Licensed under the GPL +# + +lib-y = bitops.o bugs.o csum-partial.o fault.o mem.o memcpy.o \ + ptrace.o semaphore.o sigcontext.o signal.o syscalls.o \ + sysrq.o thunk.o + +USER_OBJS := sigcontext.o +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) + +SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ + semaphore.c thunk.S +SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f) + +clean-files := $(SYMLINKS) + +bitops.c-dir = lib +csum-copy.S-dir = lib +csum-partial.c-dir = lib +csum-wrappers.c-dir = lib +memcpy.S-dir = lib +semaphore.c-dir = kernel +thunk.S-dir = lib + +define make_link + -rm -f $1 + ln -sf $(TOPDIR)/arch/x86_64/$($(notdir $1)-dir)/$(notdir $1) $1 +endef + +$(SYMLINKS): + $(call make_link,$@) + +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< + +CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c new file mode 100644 index 000000000000..fdce7ea98ca7 --- /dev/null +++ b/arch/um/sys-x86_64/bugs.c @@ -0,0 +1,122 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "linux/errno.h" +#include "asm/system.h" +#include "asm/pda.h" +#include "sysdep/ptrace.h" +#include "os.h" + +void arch_init_thread(void) +{ +} + +void arch_check_bugs(void) +{ +} + +int arch_handle_signal(int sig, union uml_pt_regs *regs) +{ + return(0); +} + +#define MAXTOKEN 64 + +/* Set during early boot */ +int host_has_cmov = 1; +int host_has_xmm = 0; + +static char token(int fd, char *buf, int len, char stop) +{ + int n; + char *ptr, *end, c; + + ptr = buf; + end = &buf[len]; + do { + n = os_read_file(fd, ptr, sizeof(*ptr)); + c = *ptr++; + if(n != sizeof(*ptr)){ + if(n == 0) return(0); + printk("Reading /proc/cpuinfo failed, err = %d\n", -n); + if(n < 0) + return(n); + else + return(-EIO); + } + } while((c != '\n') && (c != stop) && (ptr < end)); + + if(ptr == end){ + printk("Failed to find '%c' in /proc/cpuinfo\n", stop); + return(-1); + } + *(ptr - 1) = '\0'; + return(c); +} + +static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) +{ + int n; + char c; + + scratch[len - 1] = '\0'; + while(1){ + c = token(fd, scratch, len - 1, ':'); + if(c <= 0) + return(0); + else if(c != ':'){ + printk("Failed to find ':' in /proc/cpuinfo\n"); + return(0); + } + + if(!strncmp(scratch, key, strlen(key))) + return(1); + + do { + n = os_read_file(fd, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("Failed to find newline in " + "/proc/cpuinfo, err = %d\n", -n); + return(0); + } + } while(c != '\n'); + } + return(0); +} + +int cpu_feature(char *what, char *buf, int len) +{ + int fd, ret = 0; + + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + if(!find_cpuinfo_line(fd, what, buf, len)){ + printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); + goto out_close; + } + + token(fd, buf, len, '\n'); + ret = 1; + + out_close: + os_close_file(fd); + return(ret); +} + +/* Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c new file mode 100644 index 000000000000..cee1513c5c31 --- /dev/null +++ b/arch/um/sys-x86_64/fault.c @@ -0,0 +1,23 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "user.h" + +int arch_fixup(unsigned long address, void *sc_ptr) +{ + /* XXX search_exception_tables() */ + return(0); +} + +/* Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c new file mode 100644 index 000000000000..3f59a0a4f156 --- /dev/null +++ b/arch/um/sys-x86_64/mem.c @@ -0,0 +1,25 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/mm.h" +#include "asm/page.h" +#include "asm/mman.h" + +unsigned long vm_stack_flags = __VM_STACK_FLAGS; +unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; +unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_force_exec32 = PROT_EXEC; + +/* Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c new file mode 100644 index 000000000000..c88e64def6f2 --- /dev/null +++ b/arch/um/sys-x86_64/sigcontext.c @@ -0,0 +1,39 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include +#include +#include +#include "user.h" + +void sc_to_sc(void *to_ptr, void *from_ptr) +{ + struct sigcontext *to = to_ptr, *from = from_ptr; + int size = sizeof(*to); /* + sizeof(struct _fpstate); */ + + memcpy(to, from, size); + if(from->fpstate != NULL) + to->fpstate = (struct _fpstate *) (to + 1); + + to->fpstate = NULL; +} + +unsigned long *sc_sigmask(void *sc_ptr) +{ + struct sigcontext *sc = sc_ptr; + + return(&sc->oldmask); +} + +/* Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c new file mode 100644 index 000000000000..4864c0605972 --- /dev/null +++ b/arch/um/sys-x86_64/signal.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2003 PathScale, Inc. + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/errno.h" +#include "linux/personality.h" +#include "linux/ptrace.h" +#include "asm/current.h" +#include "asm/uaccess.h" +#include "asm/sigcontext.h" +#include "asm/ptrace.h" +#include "asm/arch/ucontext.h" +#include "choose-mode.h" +#include "sysdep/ptrace.h" +#include "frame_kern.h" + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" + +static int copy_sc_from_user_skas(struct pt_regs *regs, + struct sigcontext *from) +{ + int err = 0; + +#define GETREG(regs, regno, sc, regname) \ + __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= GETREG(regs, R8, from, r8); + err |= GETREG(regs, R9, from, r9); + err |= GETREG(regs, R10, from, r10); + err |= GETREG(regs, R11, from, r11); + err |= GETREG(regs, R12, from, r12); + err |= GETREG(regs, R13, from, r13); + err |= GETREG(regs, R14, from, r14); + err |= GETREG(regs, R15, from, r15); + err |= GETREG(regs, RDI, from, rdi); + err |= GETREG(regs, RSI, from, rsi); + err |= GETREG(regs, RBP, from, rbp); + err |= GETREG(regs, RBX, from, rbx); + err |= GETREG(regs, RDX, from, rdx); + err |= GETREG(regs, RAX, from, rax); + err |= GETREG(regs, RCX, from, rcx); + err |= GETREG(regs, RSP, from, rsp); + err |= GETREG(regs, RIP, from, rip); + err |= GETREG(regs, EFLAGS, from, eflags); + err |= GETREG(regs, CS, from, cs); + +#undef GETREG + + return(err); +} + +int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, + struct pt_regs *regs, unsigned long mask) +{ + unsigned long eflags; + int err = 0; + + err |= __put_user(0, &to->gs); + err |= __put_user(0, &to->fs); + +#define PUTREG(regs, regno, sc, regname) \ + __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ + &(sc)->regname) + + err |= PUTREG(regs, RDI, to, rdi); + err |= PUTREG(regs, RSI, to, rsi); + err |= PUTREG(regs, RBP, to, rbp); + err |= PUTREG(regs, RSP, to, rsp); + err |= PUTREG(regs, RBX, to, rbx); + err |= PUTREG(regs, RDX, to, rdx); + err |= PUTREG(regs, RCX, to, rcx); + err |= PUTREG(regs, RAX, to, rax); + err |= PUTREG(regs, R8, to, r8); + err |= PUTREG(regs, R9, to, r9); + err |= PUTREG(regs, R10, to, r10); + err |= PUTREG(regs, R11, to, r11); + err |= PUTREG(regs, R12, to, r12); + err |= PUTREG(regs, R13, to, r13); + err |= PUTREG(regs, R14, to, r14); + err |= PUTREG(regs, R15, to, r15); + err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ + err |= __put_user(current->thread.err, &to->err); + err |= __put_user(current->thread.trap_no, &to->trapno); + err |= PUTREG(regs, RIP, to, rip); + err |= PUTREG(regs, EFLAGS, to, eflags); +#undef PUTREG + + err |= __put_user(mask, &to->oldmask); + err |= __put_user(current->thread.cr2, &to->cr2); + + return(err); +} + +#endif + +#ifdef CONFIG_MODE_TT +int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, + int fpsize) +{ + struct _fpstate *to_fp, *from_fp; + unsigned long sigs; + int err; + + to_fp = to->fpstate; + from_fp = from->fpstate; + sigs = to->oldmask; + err = copy_from_user(to, from, sizeof(*to)); + to->oldmask = sigs; + return(err); +} + +int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, + struct sigcontext *from, int fpsize) +{ + struct _fpstate *to_fp, *from_fp; + int err; + + to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); + from_fp = from->fpstate; + err = copy_to_user(to, from, sizeof(*to)); + return(err); +} + +#endif + +static int copy_sc_from_user(struct pt_regs *to, void *from) +{ + int ret; + + ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, + sizeof(struct _fpstate)), + copy_sc_from_user_skas(to, from)); + return(ret); +} + +static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, + struct pt_regs *from, unsigned long mask) +{ + return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), + sizeof(*fp)), + copy_sc_to_user_skas(to, fp, from, mask))); +} + +struct rt_sigframe +{ + char *pretcode; + struct ucontext uc; + struct siginfo info; +}; + +#define round_down(m, n) (((m) / (n)) * (n)) + +int setup_signal_stack_si(unsigned long stack_top, int sig, + struct k_sigaction *ka, struct pt_regs * regs, + siginfo_t *info, sigset_t *set) +{ + struct rt_sigframe __user *frame; + struct _fpstate __user *fp = NULL; + int err = 0; + struct task_struct *me = current; + + frame = (struct rt_sigframe __user *) + round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; + frame -= 128; + + if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) + goto out; + +#if 0 /* XXX */ + if (save_i387(fp) < 0) + err |= -1; +#endif + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto out; + + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto out; + } + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); + err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); + if (sizeof(*set) == 16) { + __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); + __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + } + else + err |= __copy_to_user(&frame->uc.uc_sigmask, set, + sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + /* x86-64 should always use SA_RESTORER. */ + if (ka->sa.sa_flags & SA_RESTORER) + err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); + else + /* could use a vstub here */ + goto out; + + if (err) + goto out; + + /* Set up registers for signal handler */ + { + struct exec_domain *ed = current_thread_info()->exec_domain; + if (unlikely(ed && ed->signal_invmap && sig < 32)) + sig = ed->signal_invmap[sig]; + } + + PT_REGS_RDI(regs) = sig; + /* In case the signal handler was declared without prototypes */ + PT_REGS_RAX(regs) = 0; + + /* This also works for non SA_SIGINFO handlers because they expect the + next argument after the signal number on the stack. */ + PT_REGS_RSI(regs) = (unsigned long) &frame->info; + PT_REGS_RDX(regs) = (unsigned long) &frame->uc; + PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; + + PT_REGS_RSP(regs) = (unsigned long) frame; + out: + return(err); +} + +long sys_rt_sigreturn(struct pt_regs *regs) +{ + unsigned long __user sp = PT_REGS_SP(¤t->thread.regs); + struct rt_sigframe __user *frame = + (struct rt_sigframe __user *)(sp - 8); + struct ucontext __user *uc = &frame->uc; + sigset_t set; + + if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto segfault; + + sigdelsetmask(&set, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) + goto segfault; + + /* Avoid ERESTART handling */ + PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; + return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); + + segfault: + force_sig(SIGSEGV, current); + return 0; +} +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c new file mode 100644 index 000000000000..c33f85f9e8bb --- /dev/null +++ b/arch/um/sys-x86_64/sysrq.c @@ -0,0 +1,49 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/version.h" +#include "linux/module.h" +#include "asm/current.h" +#include "asm/ptrace.h" +#include "sysrq.h" + +void __show_regs(struct pt_regs * regs) +{ + printk("\n"); + print_modules(); + printk("Pid: %d, comm: %.20s %s %s\n", + current->pid, current->comm, print_tainted(), UTS_RELEASE); + printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff, + PT_REGS_RIP(regs)); + printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), + PT_REGS_EFLAGS(regs)); + printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); + printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); + printk("RBP: %016lx R08: %016lx R09: %016lx\n", + PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); + printk("R10: %016lx R11: %016lx R12: %016lx\n", + PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); + printk("R13: %016lx R14: %016lx R15: %016lx\n", + PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); +} + +void show_regs(struct pt_regs *regs) +{ + __show_regs(regs); + show_trace((unsigned long *) ®s); +} + +/* Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile new file mode 100644 index 000000000000..002607980864 --- /dev/null +++ b/arch/um/sys-x86_64/util/Makefile @@ -0,0 +1,10 @@ +# Copyright 2003 - 2004 Pathscale, Inc +# Released under the GPL + +hostprogs-y := mk_sc mk_thread +always := $(hostprogs-y) + +mk_thread-objs := mk_thread_kern.o mk_thread_user.o + +HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS) diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c new file mode 100644 index 000000000000..c236e213918d --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_sc.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 - 2004 PathScale, Inc + * Released under the GPL + */ + +#include +#include +#include + +#define SC_OFFSET(name, field) \ + printf("#define " name \ + "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\ + offsetof(struct sigcontext, field)) + +#define SC_FP_OFFSET(name, field) \ + printf("#define " name \ + "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\ + offsetof(struct _fpstate, field)) + +#define SC_FP_OFFSET_PTR(name, field, type) \ + printf("#define " name \ + "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ + offsetof(struct _fpstate, field)) + +int main(int argc, char **argv) +{ + SC_OFFSET("SC_RBX", rbx); + SC_OFFSET("SC_RCX", rcx); + SC_OFFSET("SC_RDX", rdx); + SC_OFFSET("SC_RSI", rsi); + SC_OFFSET("SC_RDI", rdi); + SC_OFFSET("SC_RBP", rbp); + SC_OFFSET("SC_RAX", rax); + SC_OFFSET("SC_R8", r8); + SC_OFFSET("SC_R9", r9); + SC_OFFSET("SC_R10", r10); + SC_OFFSET("SC_R11", r11); + SC_OFFSET("SC_R12", r12); + SC_OFFSET("SC_R13", r13); + SC_OFFSET("SC_R14", r14); + SC_OFFSET("SC_R15", r15); + SC_OFFSET("SC_IP", rip); + SC_OFFSET("SC_SP", rsp); + SC_OFFSET("SC_CR2", cr2); + SC_OFFSET("SC_ERR", err); + SC_OFFSET("SC_TRAPNO", trapno); + SC_OFFSET("SC_CS", cs); + SC_OFFSET("SC_FS", fs); + SC_OFFSET("SC_GS", gs); + SC_OFFSET("SC_EFLAGS", eflags); + SC_OFFSET("SC_SIGMASK", oldmask); +#if 0 + SC_OFFSET("SC_ORIG_RAX", orig_rax); + SC_OFFSET("SC_DS", ds); + SC_OFFSET("SC_ES", es); + SC_OFFSET("SC_SS", ss); +#endif + return(0); +} diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c new file mode 100644 index 000000000000..a281673f02b2 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_kern.c @@ -0,0 +1,21 @@ +#include "linux/config.h" +#include "linux/stddef.h" +#include "linux/sched.h" + +extern void print_head(void); +extern void print_constant_ptr(char *name, int value); +extern void print_constant(char *name, char *type, int value); +extern void print_tail(void); + +#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) + +int main(int argc, char **argv) +{ + print_head(); +#ifdef CONFIG_MODE_TT + print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); +#endif + print_tail(); + return(0); +} + diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c new file mode 100644 index 000000000000..7989725568b8 --- /dev/null +++ b/arch/um/sys-x86_64/util/mk_thread_user.c @@ -0,0 +1,30 @@ +#include + +void print_head(void) +{ + printf("/*\n"); + printf(" * Generated by mk_thread\n"); + printf(" */\n"); + printf("\n"); + printf("#ifndef __UM_THREAD_H\n"); + printf("#define __UM_THREAD_H\n"); + printf("\n"); +} + +void print_constant_ptr(char *name, int value) +{ + printf("#define %s(task) ((unsigned long *) " + "&(((char *) (task))[%d]))\n", name, value); +} + +void print_constant(char *name, char *type, int value) +{ + printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, + value); +} + +void print_tail(void) +{ + printf("\n"); + printf("#endif\n"); +} diff --git a/include/asm-um/apic.h b/include/asm-um/apic.h new file mode 100644 index 000000000000..876dee84ab11 --- /dev/null +++ b/include/asm-um/apic.h @@ -0,0 +1,4 @@ +#ifndef __UM_APIC_H +#define __UM_APIC_H + +#endif diff --git a/include/asm-um/module-x86_64.h b/include/asm-um/module-x86_64.h new file mode 100644 index 000000000000..35b5491d3e96 --- /dev/null +++ b/include/asm-um/module-x86_64.h @@ -0,0 +1,30 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_MODULE_X86_64_H +#define __UM_MODULE_X86_64_H + +/* UML is simple */ +struct mod_arch_specific +{ +}; + +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Ehdr Elf64_Ehdr + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/pda.h b/include/asm-um/pda.h new file mode 100644 index 000000000000..0d8bf33ffd42 --- /dev/null +++ b/include/asm-um/pda.h @@ -0,0 +1,31 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_PDA_X86_64_H +#define __UM_PDA_X86_64_H + +/* XXX */ +struct foo { + unsigned int __softirq_pending; + unsigned int __nmi_count; +}; + +extern struct foo me; + +#define read_pda(me) (&me) + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/prctl.h b/include/asm-um/prctl.h new file mode 100644 index 000000000000..64b6d099bdd5 --- /dev/null +++ b/include/asm-um/prctl.h @@ -0,0 +1,6 @@ +#ifndef __UM_PRCTL_H +#define __UM_PRCTL_H + +#include "asm/arch/prctl.h" + +#endif diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h new file mode 100644 index 000000000000..0b8d4e2d8efc --- /dev/null +++ b/include/asm-um/processor-x86_64.h @@ -0,0 +1,33 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_PROCESSOR_X86_64_H +#define __UM_PROCESSOR_X86_64_H + +#include "asm/arch/user.h" + +struct arch_thread { +}; + +#define INIT_ARCH_THREAD { } + +#define current_text_addr() \ + ({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; }) + +#include "asm/processor-generic.h" + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/sigcontext-x86_64.h b/include/asm-um/sigcontext-x86_64.h new file mode 100644 index 000000000000..b600e0b01e48 --- /dev/null +++ b/include/asm-um/sigcontext-x86_64.h @@ -0,0 +1,22 @@ +/* Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_SIGCONTEXT_X86_64_H +#define __UM_SIGCONTEXT_X86_64_H + +#include "asm/sigcontext-generic.h" + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/system-x86_64.h b/include/asm-um/system-x86_64.h new file mode 100644 index 000000000000..e1b61b580734 --- /dev/null +++ b/include/asm-um/system-x86_64.h @@ -0,0 +1,23 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_SYSTEM_X86_64_H +#define __UM_SYSTEM_X86_64_H + +#include "asm/system-generic.h" + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/vm-flags-x86_64.h b/include/asm-um/vm-flags-x86_64.h index e04e92d64858..3213edfa7888 100644 --- a/include/asm-um/vm-flags-x86_64.h +++ b/include/asm-um/vm-flags-x86_64.h @@ -17,11 +17,17 @@ extern unsigned long vm_stack_flags, vm_stack_flags32; extern unsigned long vm_data_default_flags, vm_data_default_flags32; extern unsigned long vm_force_exec32; +#ifdef TIF_IA32 #define VM_DATA_DEFAULT_FLAGS \ (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \ vm_data_default_flags) #define VM_STACK_DEFAULT_FLAGS \ (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) +#endif + +#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags + +#define VM_STACK_DEFAULT_FLAGS vm_stack_flags #endif -- cgit v1.2.3 From 104d88dfb8ab4ea3ff022873281abaca28e6bc04 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 03:13:00 -0800 Subject: [PATCH] UML: x86_64 ptrace support This adds the x86_64 ptrace support. It also cleans up the existing code somewhat, eliminating a couple of simple header files, and generalizing the mk_ptregs buils to accomodate multiple architectures. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysdep-i386/ptrace.h | 45 ++++- arch/um/include/sysdep-x86_64/ptrace.h | 260 ++++++++++++++++++++++++++++ arch/um/include/sysdep-x86_64/ptrace_user.h | 69 ++++++++ arch/um/kernel/ptrace.c | 1 + arch/um/kernel/skas/Makefile | 2 - arch/um/kernel/skas/include/ptrace-skas.h | 57 ------ arch/um/kernel/skas/util/Makefile | 2 + arch/um/kernel/skas/util/mk_ptregs-i386.c | 51 ++++++ arch/um/kernel/skas/util/mk_ptregs-x86_64.c | 68 ++++++++ arch/um/kernel/skas/util/mk_ptregs.c | 51 ------ arch/um/kernel/tt/include/ptrace-tt.h | 26 --- arch/um/sys-i386/ldt.c | 2 + arch/um/sys-x86_64/Makefile | 6 +- arch/um/sys-x86_64/ptrace.c | 138 +++++++++++++++ arch/um/sys-x86_64/ptrace_user.c | 64 +++++++ include/asm-um/ptrace-generic.h | 1 - include/asm-um/ptrace-x86_64.h | 75 ++++++++ 17 files changed, 776 insertions(+), 142 deletions(-) create mode 100644 arch/um/include/sysdep-x86_64/ptrace.h create mode 100644 arch/um/include/sysdep-x86_64/ptrace_user.h delete mode 100644 arch/um/kernel/skas/include/ptrace-skas.h create mode 100644 arch/um/kernel/skas/util/mk_ptregs-i386.c create mode 100644 arch/um/kernel/skas/util/mk_ptregs-x86_64.c delete mode 100644 arch/um/kernel/skas/util/mk_ptregs.c delete mode 100644 arch/um/kernel/tt/include/ptrace-tt.h create mode 100644 arch/um/sys-x86_64/ptrace.c create mode 100644 arch/um/sys-x86_64/ptrace_user.c create mode 100644 include/asm-um/ptrace-x86_64.h (limited to 'include') diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h index fc8e4f314ca6..dc126e5e25ac 100644 --- a/arch/um/include/sysdep-i386/ptrace.h +++ b/arch/um/include/sysdep-i386/ptrace.h @@ -9,11 +9,52 @@ #include "uml-config.h" #ifdef UML_CONFIG_MODE_TT -#include "ptrace-tt.h" +#include "sysdep/sc.h" #endif #ifdef UML_CONFIG_MODE_SKAS -#include "ptrace-skas.h" + +/* syscall emulation path in ptrace */ + +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif + +void set_using_sysemu(int value); +int get_using_sysemu(void); +extern int sysemu_supported; + +#include "skas_ptregs.h" + +#define HOST_FRAME_SIZE 17 + +#define REGS_IP(r) ((r)[HOST_IP]) +#define REGS_SP(r) ((r)[HOST_SP]) +#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) +#define REGS_EAX(r) ((r)[HOST_EAX]) +#define REGS_EBX(r) ((r)[HOST_EBX]) +#define REGS_ECX(r) ((r)[HOST_ECX]) +#define REGS_EDX(r) ((r)[HOST_EDX]) +#define REGS_ESI(r) ((r)[HOST_ESI]) +#define REGS_EDI(r) ((r)[HOST_EDI]) +#define REGS_EBP(r) ((r)[HOST_EBP]) +#define REGS_CS(r) ((r)[HOST_CS]) +#define REGS_SS(r) ((r)[HOST_SS]) +#define REGS_DS(r) ((r)[HOST_DS]) +#define REGS_ES(r) ((r)[HOST_ES]) +#define REGS_FS(r) ((r)[HOST_FS]) +#define REGS_GS(r) ((r)[HOST_GS]) + +#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) + +#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) + +#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) + +#define REGS_FAULT_ADDR(r) ((r)->fault_addr) + +#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) + #endif #ifndef PTRACE_SYSEMU_SINGLESTEP #define PTRACE_SYSEMU_SINGLESTEP 32 diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h new file mode 100644 index 000000000000..64b1cc16752d --- /dev/null +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -0,0 +1,260 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_PTRACE_H +#define __SYSDEP_X86_64_PTRACE_H + +#include "uml-config.h" + +#ifdef UML_CONFIG_MODE_TT +#include "sysdep/sc.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS +#include "skas_ptregs.h" + +#define REGS_IP(r) ((r)[HOST_IP]) +#define REGS_SP(r) ((r)[HOST_SP]) + +#define REGS_RBX(r) ((r)[HOST_RBX]) +#define REGS_RCX(r) ((r)[HOST_RCX]) +#define REGS_RDX(r) ((r)[HOST_RDX]) +#define REGS_RSI(r) ((r)[HOST_RSI]) +#define REGS_RDI(r) ((r)[HOST_RDI]) +#define REGS_RBP(r) ((r)[HOST_RBP]) +#define REGS_RAX(r) ((r)[HOST_RAX]) +#define REGS_R8(r) ((r)[HOST_R8]) +#define REGS_R9(r) ((r)[HOST_R9]) +#define REGS_R10(r) ((r)[HOST_R10]) +#define REGS_R11(r) ((r)[HOST_R11]) +#define REGS_R12(r) ((r)[HOST_R12]) +#define REGS_R13(r) ((r)[HOST_R13]) +#define REGS_R14(r) ((r)[HOST_R14]) +#define REGS_R15(r) ((r)[HOST_R15]) +#define REGS_CS(r) ((r)[HOST_CS]) +#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) +#define REGS_SS(r) ((r)[HOST_SS]) + +#define HOST_FS_BASE 21 +#define HOST_GS_BASE 22 +#define HOST_DS 23 +#define HOST_ES 24 +#define HOST_FS 25 +#define HOST_GS 26 + +#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE]) +#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE]) +#define REGS_DS(r) ((r)[HOST_DS]) +#define REGS_ES(r) ((r)[HOST_ES]) +#define REGS_FS(r) ((r)[HOST_FS]) +#define REGS_GS(r) ((r)[HOST_GS]) + +#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX]) + +#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res) + +#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) + +#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) + +#define REGS_FAULT_ADDR(r) ((r)->fault_addr) + +#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) + +#define REGS_TRAP(r) ((r)->trap_type) + +#define REGS_ERR(r) ((r)->fault_type) + +#endif + +#include "choose-mode.h" + +/* XXX */ +union uml_pt_regs { +#ifdef UML_CONFIG_MODE_TT + struct tt_regs { + long syscall; + unsigned long orig_rax; + void *sc; + } tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { + /* XXX */ + unsigned long regs[27]; + unsigned long fp[65]; + unsigned long fault_addr; + unsigned long fault_type; + unsigned long trap_type; + long syscall; + int is_user; + } skas; +#endif +}; + +#define EMPTY_UML_PT_REGS { } + +/* XXX */ +extern int mode_tt; + +#define UPT_RBX(r) CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs)) +#define UPT_RCX(r) CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs)) +#define UPT_RDX(r) CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs)) +#define UPT_RSI(r) CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs)) +#define UPT_RDI(r) CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs)) +#define UPT_RBP(r) CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs)) +#define UPT_RAX(r) CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs)) +#define UPT_R8(r) CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs)) +#define UPT_R9(r) CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs)) +#define UPT_R10(r) CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs)) +#define UPT_R11(r) CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs)) +#define UPT_R12(r) CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs)) +#define UPT_R13(r) CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs)) +#define UPT_R14(r) CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) +#define UPT_R15(r) CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) +#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_FS(r) CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) +#define UPT_GS(r) CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) +#define UPT_DS(r) CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) +#define UPT_ES(r) CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) +#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) +#define UPT_ORIG_RAX(r) \ + CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) + +#define UPT_IP(r) CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) +#define UPT_SP(r) CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) + +#define UPT_EFLAGS(r) \ + CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) +#define UPT_SC(r) ((r)->tt.sc) +#define UPT_SYSCALL_NR(r) CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) + +extern int user_context(unsigned long sp); + +#define UPT_IS_USER(r) \ + CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) + +#define UPT_SYSCALL_ARG1(r) UPT_RDI(r) +#define UPT_SYSCALL_ARG2(r) UPT_RSI(r) +#define UPT_SYSCALL_ARG3(r) UPT_RDX(r) +#define UPT_SYSCALL_ARG4(r) UPT_R10(r) +#define UPT_SYSCALL_ARG5(r) UPT_R8(r) +#define UPT_SYSCALL_ARG6(r) UPT_R9(r) + +struct syscall_args { + unsigned long args[6]; +}; + +#define SYSCALL_ARGS(r) ((struct syscall_args) \ + { .args = { UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) } } ) + +#define UPT_REG(regs, reg) \ + ({ unsigned long val; \ + switch(reg){ \ + case R8: val = UPT_R8(regs); break; \ + case R9: val = UPT_R9(regs); break; \ + case R10: val = UPT_R10(regs); break; \ + case R11: val = UPT_R11(regs); break; \ + case R12: val = UPT_R12(regs); break; \ + case R13: val = UPT_R13(regs); break; \ + case R14: val = UPT_R14(regs); break; \ + case R15: val = UPT_R15(regs); break; \ + case RIP: val = UPT_IP(regs); break; \ + case RSP: val = UPT_SP(regs); break; \ + case RAX: val = UPT_RAX(regs); break; \ + case RBX: val = UPT_RBX(regs); break; \ + case RCX: val = UPT_RCX(regs); break; \ + case RDX: val = UPT_RDX(regs); break; \ + case RSI: val = UPT_RSI(regs); break; \ + case RDI: val = UPT_RDI(regs); break; \ + case RBP: val = UPT_RBP(regs); break; \ + case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ + case CS: val = UPT_CS(regs); break; \ + case DS: val = UPT_DS(regs); break; \ + case ES: val = UPT_ES(regs); break; \ + case FS: val = UPT_FS(regs); break; \ + case GS: val = UPT_GS(regs); break; \ + case EFLAGS: val = UPT_EFLAGS(regs); break; \ + default : \ + panic("Bad register in UPT_REG : %d\n", reg); \ + val = -1; \ + } \ + val; \ + }) + + +#define UPT_SET(regs, reg, val) \ + ({ unsigned long val; \ + switch(reg){ \ + case R8: UPT_R8(regs) = val; break; \ + case R9: UPT_R9(regs) = val; break; \ + case R10: UPT_R10(regs) = val; break; \ + case R11: UPT_R11(regs) = val; break; \ + case R12: UPT_R12(regs) = val; break; \ + case R13: UPT_R13(regs) = val; break; \ + case R14: UPT_R14(regs) = val; break; \ + case R15: UPT_R15(regs) = val; break; \ + case RIP: UPT_IP(regs) = val; break; \ + case RSP: UPT_SP(regs) = val; break; \ + case RAX: UPT_RAX(regs) = val; break; \ + case RBX: UPT_RBX(regs) = val; break; \ + case RCX: UPT_RCX(regs) = val; break; \ + case RDX: UPT_RDX(regs) = val; break; \ + case RSI: UPT_RSI(regs) = val; break; \ + case RDI: UPT_RDI(regs) = val; break; \ + case RBP: UPT_RBP(regs) = val; break; \ + case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \ + case CS: UPT_CS(regs) = val; break; \ + case DS: UPT_DS(regs) = val; break; \ + case ES: UPT_ES(regs) = val; break; \ + case FS: UPT_FS(regs) = val; break; \ + case GS: UPT_GS(regs) = val; break; \ + case EFLAGS: UPT_EFLAGS(regs) = val; break; \ + default : \ + panic("Bad register in UPT_SET : %d\n", reg); \ + break; \ + } \ + val; \ + }) + +#define UPT_SET_SYSCALL_RETURN(r, res) \ + CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ + REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) + +#define UPT_RESTART_SYSCALL(r) \ + CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ + REGS_RESTART_SYSCALL((r)->skas.regs)) + +#define UPT_SEGV_IS_FIXABLE(r) \ + CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ + REGS_SEGV_IS_FIXABLE(&r->skas)) + +#define UPT_FAULT_ADDR(r) \ + CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) + +#define UPT_FAULT_WRITE(r) \ + CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas)) + +#define UPT_TRAP(r) CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas)) +#define UPT_ERR(r) CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas)) + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h new file mode 100644 index 000000000000..a7bb52bbe624 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -0,0 +1,69 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_X86_64_PTRACE_USER_H__ +#define __SYSDEP_X86_64_PTRACE_USER_H__ + +#define __FRAME_OFFSETS +#include +#undef __FRAME_OFFSETS + +#define PT_INDEX(off) ((off) / sizeof(unsigned long)) + +#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)]) +#define PT_SYSCALL_NR_OFFSET (ORIG_RAX) + +#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)]) +#define PT_SYSCALL_ARG1_OFFSET (RDI) + +#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)]) +#define PT_SYSCALL_ARG2_OFFSET (RSI) + +#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)]) +#define PT_SYSCALL_ARG3_OFFSET (RDX) + +#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)]) +#define PT_SYSCALL_ARG4_OFFSET (RCX) + +#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)]) +#define PT_SYSCALL_ARG5_OFFSET (R8) + +#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)]) +#define PT_SYSCALL_ARG6_OFFSET (R9) + +#define PT_SYSCALL_RET_OFFSET (RAX) + +#define PT_IP_OFFSET (RIP) +#define PT_IP(regs) ((regs)[PT_INDEX(RIP)]) + +#define PT_SP_OFFSET (RSP) +#define PT_SP(regs) ((regs)[PT_INDEX(RSP)]) + +#define PT_ORIG_RAX_OFFSET (ORIG_RAX) +#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)]) + +#define MAX_REG_OFFSET (FRAME_SIZE) +#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) + +/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though + * it's defined in the kernel's include/linux/ptrace.h + */ +#ifndef PTRACE_SETOPTIONS +#define PTRACE_SETOPTIONS 0x4200 +#endif + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index daf1cb54d023..be56a8f103d7 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -16,6 +16,7 @@ #include "asm/uaccess.h" #include "kern_util.h" #include "ptrace_user.h" +#include "skas_ptrace.h" /* * Called by kernel/ptrace.c when detaching.. diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index d7b61cba9448..c340c9cbf19b 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -6,8 +6,6 @@ obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \ -subdir-y := util - USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h deleted file mode 100644 index f5c5268cc492..000000000000 --- a/arch/um/kernel/skas/include/ptrace-skas.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __PTRACE_SKAS_H -#define __PTRACE_SKAS_H - -#include "uml-config.h" - -#ifdef UML_CONFIG_MODE_SKAS - -#include "skas_ptregs.h" - -#define HOST_FRAME_SIZE 17 - -#define REGS_IP(r) ((r)[HOST_IP]) -#define REGS_SP(r) ((r)[HOST_SP]) -#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -#define REGS_EAX(r) ((r)[HOST_EAX]) -#define REGS_EBX(r) ((r)[HOST_EBX]) -#define REGS_ECX(r) ((r)[HOST_ECX]) -#define REGS_EDX(r) ((r)[HOST_EDX]) -#define REGS_ESI(r) ((r)[HOST_ESI]) -#define REGS_EDI(r) ((r)[HOST_EDI]) -#define REGS_EBP(r) ((r)[HOST_EBP]) -#define REGS_CS(r) ((r)[HOST_CS]) -#define REGS_SS(r) ((r)[HOST_SS]) -#define REGS_DS(r) ((r)[HOST_DS]) -#define REGS_ES(r) ((r)[HOST_ES]) -#define REGS_FS(r) ((r)[HOST_FS]) -#define REGS_GS(r) ((r)[HOST_GS]) - -#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) - -#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) - -#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) - -#define REGS_FAULT_ADDR(r) ((r)->fault_addr) - -#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) - -#endif - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile index a26e0c34a762..17f5909d60f7 100644 --- a/arch/um/kernel/skas/util/Makefile +++ b/arch/um/kernel/skas/util/Makefile @@ -1,2 +1,4 @@ hostprogs-y := mk_ptregs always := $(hostprogs-y) + +mk_ptregs-objs := mk_ptregs-$(SUBARCH).o diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c new file mode 100644 index 000000000000..0788dd05bcac --- /dev/null +++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) + +int main(int argc, char **argv) +{ + printf("/* Automatically generated by " + "arch/um/kernel/skas/util/mk_ptregs */\n"); + printf("\n"); + printf("#ifndef __SKAS_PT_REGS_\n"); + printf("#define __SKAS_PT_REGS_\n"); + printf("\n"); + printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); + printf("#define HOST_FP_SIZE %d\n", + sizeof(struct user_i387_struct) / sizeof(unsigned long)); + printf("#define HOST_XFP_SIZE %d\n", + sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); + + PRINT_REG("IP", EIP); + PRINT_REG("SP", UESP); + PRINT_REG("EFLAGS", EFL); + PRINT_REG("EAX", EAX); + PRINT_REG("EBX", EBX); + PRINT_REG("ECX", ECX); + PRINT_REG("EDX", EDX); + PRINT_REG("ESI", ESI); + PRINT_REG("EDI", EDI); + PRINT_REG("EBP", EBP); + PRINT_REG("CS", CS); + PRINT_REG("SS", SS); + PRINT_REG("DS", DS); + PRINT_REG("FS", FS); + PRINT_REG("ES", ES); + PRINT_REG("GS", GS); + printf("\n"); + printf("#endif\n"); + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c new file mode 100644 index 000000000000..67aee92a70ef --- /dev/null +++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c @@ -0,0 +1,68 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include +#define __FRAME_OFFSETS +#include + +#define PRINT_REG(name, val) \ + printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val)) + +int main(int argc, char **argv) +{ + printf("/* Automatically generated by " + "arch/um/kernel/skas/util/mk_ptregs */\n"); + printf("\n"); + printf("#ifndef __SKAS_PT_REGS_\n"); + printf("#define __SKAS_PT_REGS_\n"); + printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n", + FRAME_SIZE); + PRINT_REG("RBX", RBX); + PRINT_REG("RCX", RCX); + PRINT_REG("RDI", RDI); + PRINT_REG("RSI", RSI); + PRINT_REG("RDX", RDX); + PRINT_REG("RBP", RBP); + PRINT_REG("RAX", RAX); + PRINT_REG("R8", R8); + PRINT_REG("R9", R9); + PRINT_REG("R10", R10); + PRINT_REG("R11", R11); + PRINT_REG("R12", R12); + PRINT_REG("R13", R13); + PRINT_REG("R14", R14); + PRINT_REG("R15", R15); + PRINT_REG("ORIG_RAX", ORIG_RAX); + PRINT_REG("CS", CS); + PRINT_REG("SS", SS); + PRINT_REG("EFLAGS", EFLAGS); +#if 0 + PRINT_REG("FS", FS); + PRINT_REG("GS", GS); + PRINT_REG("DS", DS); + PRINT_REG("ES", ES); +#endif + + PRINT_REG("IP", RIP); + PRINT_REG("SP", RSP); + printf("#define HOST_FP_SIZE 0\n"); + printf("#define HOST_XFP_SIZE 0\n"); + printf("\n"); + printf("\n"); + printf("#endif\n"); + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c deleted file mode 100644 index 116f74d2c334..000000000000 --- a/arch/um/kernel/skas/util/mk_ptregs.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include - -#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) - -int main(int argc, char **argv) -{ - printf("/* Automatically generated by " - "arch/um/kernel/skas/util/mk_ptregs */\n"); - printf("\n"); - printf("#ifndef __SKAS_PT_REGS_\n"); - printf("#define __SKAS_PT_REGS_\n"); - printf("\n"); - printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); - printf("#define HOST_FP_SIZE %d\n", - sizeof(struct user_i387_struct) / sizeof(unsigned long)); - printf("#define HOST_XFP_SIZE %d\n", - sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); - - PRINT_REG("IP", EIP); - PRINT_REG("SP", UESP); - PRINT_REG("EFLAGS", EFL); - PRINT_REG("EAX", EAX); - PRINT_REG("EBX", EBX); - PRINT_REG("ECX", ECX); - PRINT_REG("EDX", EDX); - PRINT_REG("ESI", ESI); - PRINT_REG("EDI", EDI); - PRINT_REG("EBP", EBP); - PRINT_REG("CS", CS); - PRINT_REG("SS", SS); - PRINT_REG("DS", DS); - PRINT_REG("FS", FS); - PRINT_REG("ES", ES); - PRINT_REG("GS", GS); - printf("\n"); - printf("#endif\n"); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tt/include/ptrace-tt.h b/arch/um/kernel/tt/include/ptrace-tt.h deleted file mode 100644 index 3084c1db8678..000000000000 --- a/arch/um/kernel/tt/include/ptrace-tt.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __PTRACE_TT_H -#define __PTRACE_TT_H - -#include "uml-config.h" - -#ifdef UML_CONFIG_MODE_TT -#include "sysdep/sc.h" -#endif - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index ba77ccaa8361..98d7691980b2 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -25,6 +25,8 @@ int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) #ifdef CONFIG_MODE_SKAS extern int userspace_pid; +#include "skas_ptrace.h" + int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) { struct ptrace_ldt ldt; diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 0859685f511a..81e165903570 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -5,10 +5,10 @@ # lib-y = bitops.o bugs.o csum-partial.o fault.o mem.o memcpy.o \ - ptrace.o semaphore.o sigcontext.o signal.o syscalls.o \ - sysrq.o thunk.o + ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \ + syscalls.o sysrq.o thunk.o -USER_OBJS := sigcontext.o +USER_OBJS := ptrace_user.o sigcontext.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c new file mode 100644 index 000000000000..8c146b2a1e00 --- /dev/null +++ b/arch/um/sys-x86_64/ptrace.c @@ -0,0 +1,138 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#define __FRAME_OFFSETS +#include "asm/ptrace.h" +#include "linux/sched.h" +#include "linux/errno.h" +#include "asm/elf.h" + +/* XXX x86_64 */ +unsigned long not_ss; +unsigned long not_ds; +unsigned long not_es; + +#define SC_SS(r) (not_ss) +#define SC_DS(r) (not_ds) +#define SC_ES(r) (not_es) + +/* determines which flags the user has access to. */ +/* 1 = access 0 = no access */ +#define FLAG_MASK 0x44dd5UL + +int putreg(struct task_struct *child, int regno, unsigned long value) +{ + unsigned long tmp; + +#ifdef TIF_IA32 + /* Some code in the 64bit emulation may not be 64bit clean. + Don't take any chances. */ + if (test_tsk_thread_flag(child, TIF_IA32)) + value &= 0xffffffff; +#endif + switch (regno){ + case FS: + case GS: + case DS: + case ES: + case SS: + case CS: + if (value && (value & 3) != 3) + return -EIO; + value &= 0xffff; + break; + + case FS_BASE: + case GS_BASE: + if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) + return -EIO; + break; + + case EFLAGS: + value &= FLAG_MASK; + tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK; + value |= tmp; + break; + } + + PT_REGS_SET(&child->thread.regs, regno, value); + return 0; +} + +unsigned long getreg(struct task_struct *child, int regno) +{ + unsigned long retval = ~0UL; + switch (regno) { + case FS: + case GS: + case DS: + case ES: + case SS: + case CS: + retval = 0xffff; + /* fall through */ + default: + retval &= PT_REG(&child->thread.regs, regno); +#ifdef TIF_IA32 + if (test_tsk_thread_flag(child, TIF_IA32)) + retval &= 0xffffffff; +#endif + } + return retval; +} + +void arch_switch(void) +{ +/* XXX + printk("arch_switch\n"); +*/ +} + +int is_syscall(unsigned long addr) +{ + panic("is_syscall"); +} + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) +{ + panic("dump_fpu"); + return(1); +} + +int get_fpregs(unsigned long buf, struct task_struct *child) +{ + panic("get_fpregs"); + return(0); +} + +int set_fpregs(unsigned long buf, struct task_struct *child) +{ + panic("set_fpregs"); + return(0); +} + +int get_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + panic("get_fpxregs"); + return(0); +} + +int set_fpxregs(unsigned long buf, struct task_struct *tsk) +{ + panic("set_fxpregs"); + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c new file mode 100644 index 000000000000..e1f8bacc5f1a --- /dev/null +++ b/arch/um/sys-x86_64/ptrace_user.c @@ -0,0 +1,64 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#include +#include +#define __FRAME_OFFSETS +#include +#include +#include "user.h" +#include "kern_constants.h" + +int ptrace_getregs(long pid, unsigned long *regs_out) +{ + if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) + return(-errno); + return(0); +} + +int ptrace_setregs(long pid, unsigned long *regs) +{ + if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) + return(-errno); + return(0); +} + +void ptrace_pokeuser(unsigned long addr, unsigned long data) +{ + panic("ptrace_pokeuser"); +} + +#define DS 184 +#define ES 192 +#define __USER_DS 0x2b + +void arch_enter_kernel(void *task, int pid) +{ +} + +void arch_leave_kernel(void *task, int pid) +{ +#ifdef UM_USER_CS + if(ptrace(PTRACE_POKEUSER, pid, CS, UM_USER_CS) < 0) + tracer_panic("POKEUSER CS failed"); +#endif + + if(ptrace(PTRACE_POKEUSER, pid, DS, __USER_DS) < 0) + tracer_panic("POKEUSER DS failed"); + if(ptrace(PTRACE_POKEUSER, pid, ES, __USER_DS) < 0) + tracer_panic("POKEUSER ES failed"); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h index a1bb25f8e85b..0e187165cf02 100644 --- a/include/asm-um/ptrace-generic.h +++ b/include/asm-um/ptrace-generic.h @@ -21,7 +21,6 @@ #undef instruction_pointer #include "sysdep/ptrace.h" -#include "skas_ptrace.h" struct pt_regs { union uml_pt_regs regs; diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h new file mode 100644 index 000000000000..c34be39b78b2 --- /dev/null +++ b/include/asm-um/ptrace-x86_64.h @@ -0,0 +1,75 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_PTRACE_X86_64_H +#define __UM_PTRACE_X86_64_H + +#include "linux/compiler.h" + +#define signal_fault signal_fault_x86_64 +#define __FRAME_OFFSETS /* Needed to get the R* macros */ +#include "asm/ptrace-generic.h" +#undef signal_fault + +void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where); + +#define FS_BASE (21 * sizeof(unsigned long)) +#define GS_BASE (22 * sizeof(unsigned long)) +#define DS (23 * sizeof(unsigned long)) +#define ES (24 * sizeof(unsigned long)) +#define FS (25 * sizeof(unsigned long)) +#define GS (26 * sizeof(unsigned long)) + +#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs) +#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs) +#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs) +#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs) +#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs) +#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs) +#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs) +#define PT_REGS_R8(r) UPT_R8(&(r)->regs) +#define PT_REGS_R9(r) UPT_R9(&(r)->regs) +#define PT_REGS_R10(r) UPT_R10(&(r)->regs) +#define PT_REGS_R11(r) UPT_R11(&(r)->regs) +#define PT_REGS_R12(r) UPT_R12(&(r)->regs) +#define PT_REGS_R13(r) UPT_R13(&(r)->regs) +#define PT_REGS_R14(r) UPT_R14(&(r)->regs) +#define PT_REGS_R15(r) UPT_R15(&(r)->regs) + +#define PT_REGS_FS(r) UPT_FS(&(r)->regs) +#define PT_REGS_GS(r) UPT_GS(&(r)->regs) +#define PT_REGS_DS(r) UPT_DS(&(r)->regs) +#define PT_REGS_ES(r) UPT_ES(&(r)->regs) +#define PT_REGS_SS(r) UPT_SS(&(r)->regs) +#define PT_REGS_CS(r) UPT_CS(&(r)->regs) + +#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs) +#define PT_REGS_RIP(r) UPT_IP(&(r)->regs) +#define PT_REGS_RSP(r) UPT_SP(&(r)->regs) + +#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) + +/* XXX */ +#define user_mode(r) UPT_IS_USER(&(r)->regs) +#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r) +#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r) + +#define PT_FIX_EXEC_STACK(sp) do ; while(0) + +#define profile_pc(regs) PT_REGS_IP(regs) + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ -- cgit v1.2.3 From e08d84a7687bab59c762cca3a9008a4f1e18b591 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 03:13:41 -0800 Subject: [PATCH] UML: Separate out the time code Move the i386 __delay to sys-i386 and add an implementation for x86_64. Also get rid of the definition of um_udelay_t. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/time_kern.c | 19 ++----------------- arch/um/sys-i386/Makefile | 2 +- arch/um/sys-i386/delay.c | 14 ++++++++++++++ arch/um/sys-x86_64/Makefile | 2 +- arch/um/sys-x86_64/delay.c | 26 ++++++++++++++++++++++++++ include/asm-um/archparam-i386.h | 4 ---- include/asm-um/archparam-ppc.h | 4 ---- 7 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 arch/um/sys-i386/delay.c create mode 100644 arch/um/sys-x86_64/delay.c (limited to 'include') diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 498344110eee..3b538f6cc3ae 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -136,22 +136,7 @@ long um_stime(int * tptr) return 0; } -/* XXX Needs to be moved under sys-i386 */ -void __delay(um_udelay_t time) -{ - /* Stolen from the i386 __loop_delay */ - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (time)); -} - -void __udelay(um_udelay_t usecs) +void __udelay(unsigned long usecs) { int i, n; @@ -159,7 +144,7 @@ void __udelay(um_udelay_t usecs) for(i=0;i Date: Tue, 11 Jan 2005 03:13:55 -0800 Subject: [PATCH] UML: x86-64 headers Add a bunch of headers to include/asm-um to support x86_64. Also move some arch-specific things from generic files to x86-specific ones. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/archparam-i386.h | 7 +++++ include/asm-um/archparam-x86_64.h | 62 +++++++++++++++++++++++++++++++++++++++ include/asm-um/calling.h | 9 ++++++ include/asm-um/dwarf2.h | 11 +++++++ include/asm-um/elf.h | 5 ++++ include/asm-um/fixmap.h | 7 ----- 6 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 include/asm-um/archparam-x86_64.h create mode 100644 include/asm-um/calling.h create mode 100644 include/asm-um/dwarf2.h (limited to 'include') diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h index 61de0d440cdc..5b5df118d9a5 100644 --- a/include/asm-um/archparam-i386.h +++ b/include/asm-um/archparam-i386.h @@ -65,6 +65,13 @@ extern unsigned long __kernel_vsyscall; #define VSYSCALL_BASE vsyscall_ehdr #define VSYSCALL_END vsyscall_end +/* + * This is the range that is readable by user mode, and things + * acting like user mode such as get_user_pages. + */ +#define FIXADDR_USER_START VSYSCALL_BASE +#define FIXADDR_USER_END VSYSCALL_END + /* * Architecture-neutral AT_ values in 0-17, leave some room * for more of them, start the x86-specific ones at 32. diff --git a/include/asm-um/archparam-x86_64.h b/include/asm-um/archparam-x86_64.h new file mode 100644 index 000000000000..96321c4892f1 --- /dev/null +++ b/include/asm-um/archparam-x86_64.h @@ -0,0 +1,62 @@ +/* + * Copyright 2003 PathScale, Inc. + * + * Licensed under the GPL + */ + +#ifndef __UM_ARCHPARAM_X86_64_H +#define __UM_ARCHPARAM_X86_64_H + +#include + +#define ELF_PLATFORM "x86_64" + +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) + +typedef unsigned long elf_greg_t; +typedef struct { } elf_fpregset_t; + +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 + +#define ELF_PLAT_INIT(regs, load_addr) do { \ + PT_REGS_RBX(regs) = 0; \ + PT_REGS_RCX(regs) = 0; \ + PT_REGS_RDX(regs) = 0; \ + PT_REGS_RSI(regs) = 0; \ + PT_REGS_RDI(regs) = 0; \ + PT_REGS_RBP(regs) = 0; \ + PT_REGS_RAX(regs) = 0; \ + PT_REGS_R8(regs) = 0; \ + PT_REGS_R9(regs) = 0; \ + PT_REGS_R10(regs) = 0; \ + PT_REGS_R11(regs) = 0; \ + PT_REGS_R12(regs) = 0; \ + PT_REGS_R13(regs) = 0; \ + PT_REGS_R14(regs) = 0; \ + PT_REGS_R15(regs) = 0; \ +} while (0) + +#ifdef TIF_IA32 /* XXX */ + clear_thread_flag(TIF_IA32); +#endif + +/* No user-accessible fixmap addresses, i.e. vsyscall */ +#define FIXADDR_USER_START 0 +#define FIXADDR_USER_END 0 + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/include/asm-um/calling.h b/include/asm-um/calling.h new file mode 100644 index 000000000000..0b2384cc99fd --- /dev/null +++ b/include/asm-um/calling.h @@ -0,0 +1,9 @@ +# Copyright 2003 - 2004 Pathscale, Inc +# Released under the GPL + +#ifndef __UM_CALLING_H /* XXX x86_64 */ +#define __UM_CALLING_H + +#include "asm/arch/calling.h" + +#endif diff --git a/include/asm-um/dwarf2.h b/include/asm-um/dwarf2.h new file mode 100644 index 000000000000..d1a02e762931 --- /dev/null +++ b/include/asm-um/dwarf2.h @@ -0,0 +1,11 @@ +/* Copyright 2003 - 2004 Pathscale, Inc + * Released under the GPL + */ + +/* Needed on x86_64 by thunk.S */ +#ifndef __UM_DWARF2_H +#define __UM_DWARF2_H + +#include "asm/arch/dwarf2.h" + +#endif diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h index b689a770a83f..b3a7258f9971 100644 --- a/include/asm-um/elf.h +++ b/include/asm-um/elf.h @@ -1,6 +1,7 @@ #ifndef __UM_ELF_H #define __UM_ELF_H +#include "linux/config.h" #include "asm/archparam.h" extern long elf_aux_hwcap; @@ -12,7 +13,11 @@ extern long elf_aux_hwcap; #define elf_check_arch(x) (1) +#ifdef CONFIG_64_BIT +#define ELF_CLASS ELFCLASS64 +#else #define ELF_CLASS ELFCLASS32 +#endif #define USE_ELF_CORE_DUMP diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h index 0fb5779088b0..900f3fbb9fab 100644 --- a/include/asm-um/fixmap.h +++ b/include/asm-um/fixmap.h @@ -64,13 +64,6 @@ extern unsigned long get_kmem_end(void); #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) -/* - * This is the range that is readable by user mode, and things - * acting like user mode such as get_user_pages. - */ -#define FIXADDR_USER_START VSYSCALL_BASE -#define FIXADDR_USER_END VSYSCALL_END - extern void __this_fixmap_does_not_exist(void); /* -- cgit v1.2.3 From 986edf120fbe724b49b7127328641ab57d0e2d05 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 03:14:48 -0800 Subject: [PATCH] UML: code tidying Some small cleanups that resulted from the x86_64 merge: Some unneeded includes were removed Some overlong lines were shortened current_thread_info was replaced by a generic version. Some warnings were fixed Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/process.h | 2 +- arch/um/kernel/mem.c | 2 ++ arch/um/kernel/mem_user.c | 4 +--- arch/um/kernel/process.c | 7 ++----- arch/um/kernel/skas/process.c | 3 ++- arch/um/kernel/skas/trap_user.c | 1 - arch/um/kernel/tt/ptproxy/sysdep.c | 1 - arch/um/kernel/tt/ptproxy/wait.c | 1 - arch/um/kernel/tt/trap_user.c | 1 - arch/um/kernel/um_arch.c | 5 +++++ arch/um/os-Linux/Makefile | 2 ++ arch/um/os-Linux/elf_aux.c | 1 - arch/um/os-Linux/user_syms.c | 8 +++++--- include/asm-um/processor-i386.h | 3 ++- include/asm-um/thread_info.h | 2 +- 15 files changed, 23 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 07af218574fd..5af9157ff54f 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -6,7 +6,7 @@ #ifndef __PROCESS_H__ #define __PROCESS_H__ -#include +#include extern void sig_handler(int sig, struct sigcontext sc); extern void alarm_handler(int sig, struct sigcontext sc); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index e8a2c9c5716b..f95e90ae9c88 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -173,6 +173,7 @@ static void init_highmem(void) static void __init fixaddr_user_init( void) { +#if FIXADDR_USER_START != 0 long size = FIXADDR_USER_END - FIXADDR_USER_START; pgd_t *pgd; pmd_t *pmd; @@ -192,6 +193,7 @@ static void __init fixaddr_user_init( void) pte = pte_offset_kernel(pmd, vaddr); pte_set_val( (*pte), paddr, PAGE_READONLY); } +#endif } void paging_init(void) diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c index 33f71e764951..4a663fd434bb 100644 --- a/arch/um/kernel/mem_user.c +++ b/arch/um/kernel/mem_user.c @@ -48,8 +48,6 @@ #include "tempfile.h" #include "kern_constants.h" -extern struct mem_region physmem_region; - #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" static int create_tmp_file(unsigned long len) @@ -135,7 +133,7 @@ static int create_anon_file(unsigned long len) addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if(addr == MAP_FAILED){ - os_print_error((int) addr, "mapping physmem file"); + perror("mapping physmem file"); exit(1); } munmap(addr, len); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 0fca3f073c86..1e638b813199 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -13,14 +13,10 @@ #include #include #include -#include #include #include -#include -#include #include #include -#include #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -28,6 +24,7 @@ #include "signal_kern.h" #include "signal_user.h" #include "sysdep/ptrace.h" +#include "sysdep/ptrace_user.h" #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" @@ -331,7 +328,7 @@ void __init check_ptrace(void) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); - if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80))) + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP + 0x80)) panic("check_ptrace : expected SIGTRAP + 0x80, " "got status = %d", status); diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 4b368908e5a4..2fc18a123dae 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -73,7 +73,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu "errno = %d\n", errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); - if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80))) + if((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)) panic("handle_trap - failed to wait at end of syscall, " "errno = %d, status = %d\n", errno, status); } diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c index 96593709a6e1..09248772de60 100644 --- a/arch/um/kernel/skas/trap_user.c +++ b/arch/um/kernel/skas/trap_user.c @@ -5,7 +5,6 @@ #include #include -#include #include "sysdep/ptrace.h" #include "signal_user.h" #include "user_util.h" diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index c42855aeda60..4545ea4f27e1 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -12,7 +12,6 @@ terms and conditions. #include #include #include -#include #include #include "ptrace_user.h" #include "user_util.h" diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c index 86ef67653e72..fcb7ea50fc7e 100644 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ b/arch/um/kernel/tt/ptproxy/wait.c @@ -10,7 +10,6 @@ terms and conditions. #include #include #include -#include #include "ptproxy.h" #include "sysdep.h" diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index 00bacacfcc35..67fdef69d54e 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "sysdep/ptrace.h" #include "signal_user.h" #include "user_util.h" diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 1ce25f89f8ac..8096843e4d4c 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -17,6 +17,7 @@ #include "linux/sysrq.h" #include "linux/seq_file.h" #include "linux/delay.h" +#include "linux/module.h" #include "asm/page.h" #include "asm/pgtable.h" #include "asm/ptrace.h" @@ -156,6 +157,8 @@ static int __init uml_version_setup(char *line, int *add) { printf("%s\n", system_utsname.release); exit(0); + + return 0; } __uml_setup("--version", uml_version_setup, @@ -256,6 +259,8 @@ static int __init Usage(char *line, int *add) p++; } exit(0); + + return 0; } __uml_setup("--help", Usage, diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 9d88f68977df..f8378124be13 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -11,3 +11,5 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< + +CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 36575ff8bfac..9aee0b62ebca 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -26,7 +26,6 @@ unsigned long vsyscall_end; unsigned long __kernel_vsyscall; - __init void scan_elf_aux( char **envp) { long page_size = 0; diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 383ac7b52beb..75d7af9ae1d2 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -26,9 +26,6 @@ EXPORT_SYMBOL(printf); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(vsyscall_ehdr); -EXPORT_SYMBOL(vsyscall_end); - /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. * However, the modules will use the CRC defined *here*, no matter if it is * good; so the versions of these symbols will always match @@ -37,6 +34,11 @@ EXPORT_SYMBOL(vsyscall_end); int sym(void); \ EXPORT_SYMBOL(sym); +#ifdef SUBARCH_i386 +EXPORT_SYMBOL(vsyscall_ehdr); +EXPORT_SYMBOL(vsyscall_end); +#endif + EXPORT_SYMBOL_PROTO(__errno_location); EXPORT_SYMBOL_PROTO(access); diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h index b276481cc6cb..cb44bb56836f 100644 --- a/include/asm-um/processor-i386.h +++ b/include/asm-um/processor-i386.h @@ -24,7 +24,8 @@ struct arch_thread { * instruction pointer ("program counter"). Stolen * from asm-i386/processor.h */ -#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; }) +#define current_text_addr() \ + ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; }) #include "asm/processor-generic.h" diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h index 6550ed4355c2..7797873890c2 100644 --- a/include/asm-um/thread_info.h +++ b/include/asm-um/thread_info.h @@ -47,7 +47,7 @@ static inline struct thread_info *current_thread_info(void) struct thread_info *ti; unsigned long mask = PAGE_SIZE * (1 << CONFIG_KERNEL_STACK_ORDER) - 1; - __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask)); + ti = (struct thread_info *) (((unsigned long) &ti) & ~mask); return ti; } -- cgit v1.2.3 From 757c4d2fc71af260c8112ce7ae7816e4ac6fad40 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 03:15:14 -0800 Subject: [PATCH] UML: 2.6.10 ptrace updates Add some of the 2.6.10 ptrace updates. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/ptrace.c | 28 ++++++++++++++++++++++++++-- include/asm-um/ptrace-generic.h | 5 +++++ 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index be56a8f103d7..23c11c426ab2 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -307,6 +307,25 @@ long sys_ptrace(long request, long pid, long addr, long data) return ret; } +void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, + int error_code) +{ + struct siginfo info; + + memset(&info, 0, sizeof(info)); + info.si_signo = SIGTRAP; + info.si_code = TRAP_BRKPT; + + /* User-mode eip? */ + info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL; + + /* Send us the fakey SIGTRAP */ + force_sig_info(SIGTRAP, &info, tsk); +} + +/* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and + * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check + */ void syscall_trace(union uml_pt_regs *regs, int entryexit) { int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; @@ -321,14 +340,19 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) audit_syscall_exit(current, regs->eax); } - if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep) + /* Fake a debug trap */ + if (is_singlestep) + send_sigtrap(current, regs, 0); + + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; + if (!(current->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep; + tracesysgood = (current->ptrace & PT_TRACESYSGOOD); ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); if (entryexit) /* force do_signal() --> is_syscall() */ diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h index 0e187165cf02..46599ac44037 100644 --- a/include/asm-um/ptrace-generic.h +++ b/include/asm-um/ptrace-generic.h @@ -12,11 +12,13 @@ #define pt_regs pt_regs_subarch #define show_regs show_regs_subarch +#define send_sigtrap send_sigtrap_subarch #include "asm/arch/ptrace.h" #undef pt_regs #undef show_regs +#undef send_sigtrap #undef user_mode #undef instruction_pointer @@ -55,6 +57,9 @@ extern int set_fpxregs(unsigned long buf, struct task_struct *tsk); extern void show_regs(struct pt_regs *regs); +extern void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, + int error_code); + #endif #endif -- cgit v1.2.3 From 7ab79f6551b8fc72895def06dc17b80bf91d5dd4 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 11 Jan 2005 03:16:34 -0800 Subject: [PATCH] UML: sparse annotations Lots of sparse annotations from Chris Wright. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/mconsole_kern.c | 2 +- arch/um/drivers/ubd_kern.c | 10 +++++----- arch/um/include/um_uaccess.h | 14 +++++++------- arch/um/include/uml_uaccess.h | 2 +- arch/um/kernel/checksum.c | 12 ++++++------ arch/um/kernel/exec_kern.c | 10 ++++++---- arch/um/kernel/exitcode.c | 2 +- arch/um/kernel/irq.c | 4 ++-- arch/um/kernel/mem.c | 4 ++-- arch/um/kernel/process_kern.c | 8 ++++---- arch/um/kernel/ptrace.c | 15 ++++++++------- arch/um/kernel/signal_kern.c | 2 +- arch/um/kernel/skas/uaccess.c | 22 +++++++++++----------- arch/um/kernel/syscall_kern.c | 7 +++---- arch/um/kernel/time_kern.c | 6 +++--- arch/um/kernel/tt/uaccess.c | 12 ++++++------ arch/um/sys-i386/ldt.c | 12 +++++++----- arch/um/sys-i386/ptrace.c | 24 +++++++++++++----------- arch/um/sys-i386/sigcontext.c | 3 +-- arch/um/sys-i386/signal.c | 2 +- arch/um/sys-i386/syscalls.c | 16 +++++++++------- arch/um/sys-x86_64/signal.c | 2 +- include/asm-um/uaccess.h | 4 ++-- 23 files changed, 101 insertions(+), 94 deletions(-) (limited to 'include') diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index cb8c1ee24fc7..ecbabd351c6d 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -499,7 +499,7 @@ int mconsole_init(void) __initcall(mconsole_init); -static int write_proc_mconsole(struct file *file, const char *buffer, +static int write_proc_mconsole(struct file *file, const char __user *buffer, unsigned long count, void *data) { char *buf; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index f05c2b7514f2..17d85730086b 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -172,7 +172,7 @@ static struct proc_dir_entry *proc_ide = NULL; static void make_proc_ide(void) { - proc_ide_root = proc_mkdir("ide", 0); + proc_ide_root = proc_mkdir("ide", NULL); proc_ide = proc_mkdir("ide0", proc_ide_root); } @@ -1087,7 +1087,7 @@ static void do_ubd_request(request_queue_t *q) static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct hd_geometry *loc = (struct hd_geometry *) arg; + struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; struct ubd *dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, @@ -1108,19 +1108,19 @@ static int ubd_ioctl(struct inode * inode, struct file * file, case HDIO_GET_IDENTITY: ubd_id.cyls = dev->size / (128 * 32 * 512); - if(copy_to_user((char *) arg, (char *) &ubd_id, + if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); return(0); case CDROMVOLREAD: - if(copy_from_user(&volume, (char *) arg, sizeof(volume))) + if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) return(-EFAULT); volume.channel0 = 255; volume.channel1 = 255; volume.channel2 = 255; volume.channel3 = 255; - if(copy_to_user((char *) arg, &volume, sizeof(volume))) + if(copy_to_user((char __user *) arg, &volume, sizeof(volume))) return(-EFAULT); return(0); } diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index c72024219f23..4eb302cbf865 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -20,19 +20,19 @@ #define access_ok(type, addr, size) \ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) -static inline int verify_area(int type, const void * addr, unsigned long size) +static inline int verify_area(int type, const void __user *addr, unsigned long size) { - return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, + return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, size)); } -static inline int copy_from_user(void *to, const void *from, int n) +static inline int copy_from_user(void *to, const void __user *from, int n) { return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, from, n)); } -static inline int copy_to_user(void *to, const void *from, int n) +static inline int copy_to_user(void __user *to, const void *from, int n) { return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, from, n)); @@ -57,7 +57,7 @@ static inline int copy_to_user(void *to, const void *from, int n) * and returns @count. */ -static inline int strncpy_from_user(char *dst, const char *src, int count) +static inline int strncpy_from_user(char *dst, const char __user *src, int count) { return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, dst, src, count)); @@ -89,7 +89,7 @@ static inline int __clear_user(void *mem, int len) * Returns number of bytes that could not be cleared. * On success, this will be zero. */ -static inline int clear_user(void *mem, int len) +static inline int clear_user(void __user *mem, int len) { return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); } @@ -105,7 +105,7 @@ static inline int clear_user(void *mem, int len) * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -static inline int strnlen_user(const void *str, long len) +static inline int strnlen_user(const void __user *str, long len) { return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); } diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h index 785ccd51bbf5..f77eb6428453 100644 --- a/arch/um/include/uml_uaccess.h +++ b/arch/um/include/uml_uaccess.h @@ -7,7 +7,7 @@ #define __UML_UACCESS_H__ extern int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher); + void **fault_addr, void **fault_catcher); extern unsigned long __do_user_copy(void *to, const void *from, int n, void **fault_addr, void **fault_catcher, void (*op)(void *to, const void *from, diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c index fa50a9b81ca2..669783580fe5 100644 --- a/arch/um/kernel/checksum.c +++ b/arch/um/kernel/checksum.c @@ -2,16 +2,16 @@ #include "linux/errno.h" #include "linux/module.h" -extern unsigned int arch_csum_partial(const char *buff, int len, int sum); +unsigned int arch_csum_partial(const char *buff, int len, int sum); -extern unsigned int csum_partial(char *buff, int len, int sum) +unsigned int csum_partial(char *buff, int len, int sum) { - return(arch_csum_partial(buff, len, sum)); + return arch_csum_partial(buff, len, sum); } EXPORT_SYMBOL(csum_partial); -unsigned int csum_partial_copy_to(const char *src, char *dst, int len, +unsigned int csum_partial_copy_to(const char *src, char __user *dst, int len, int sum, int *err_ptr) { if(copy_to_user(dst, src, len)){ @@ -22,7 +22,7 @@ unsigned int csum_partial_copy_to(const char *src, char *dst, int len, return(arch_csum_partial(src, len, sum)); } -unsigned int csum_partial_copy_from(const char *src, char *dst, int len, +unsigned int csum_partial_copy_from(const char __user *src, char *dst, int len, int sum, int *err_ptr) { if(copy_from_user(dst, src, len)){ @@ -30,7 +30,7 @@ unsigned int csum_partial_copy_from(const char *src, char *dst, int len, return(-1); } - return(arch_csum_partial(dst, len, sum)); + return arch_csum_partial(dst, len, sum); } /* diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index 4336240c179a..49ddabe69be7 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -34,7 +34,8 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) extern void log_exec(char **argv, void *tty); -static long execve1(char *file, char **argv, char **env) +static long execve1(char *file, char __user * __user *argv, + char *__user __user *env) { long error; @@ -51,7 +52,7 @@ static long execve1(char *file, char **argv, char **env) return(error); } -long um_execve(char *file, char **argv, char **env) +long um_execve(char *file, char __user *__user *argv, char __user *__user *env) { long err; @@ -61,13 +62,14 @@ long um_execve(char *file, char **argv, char **env) return(err); } -long sys_execve(char *file, char **argv, char **env) +long sys_execve(char *file, char __user *__user *argv, + char __user *__user *env) { long error; char *filename; lock_kernel(); - filename = getname((char *) file); + filename = getname((char __user *) file); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = execve1(filename, argv, env); diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 14a748e2e25a..0ea87f24b36f 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -27,7 +27,7 @@ static int read_proc_exitcode(char *page, char **start, off_t off, return(len); } -static int write_proc_exitcode(struct file *file, const char *buffer, +static int write_proc_exitcode(struct file *file, const char __user *buffer, unsigned long count, void *data) { char *end, buf[sizeof("nnnnn\0")]; diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 6d53b5987d62..ab7417b78c87 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -152,13 +152,13 @@ void __init init_IRQ(void) int i; irq_desc[TIMER_IRQ].status = IRQ_DISABLED; - irq_desc[TIMER_IRQ].action = 0; + irq_desc[TIMER_IRQ].action = NULL; irq_desc[TIMER_IRQ].depth = 1; irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; enable_irq(TIMER_IRQ); for(i=1;ithread.fault_addr = (void *) addr; - if(__do_copy_to_user((void *) addr, &zero, + if(__do_copy_to_user((void __user *) addr, &zero, sizeof(zero), ¤t->thread.fault_addr, ¤t->thread.fault_catcher)){ diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 62e6c8ef2e67..8d003f351eb3 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -368,22 +368,22 @@ void *get_init_task(void) return(&init_thread_union.thread_info.task); } -int copy_to_user_proc(void *to, void *from, int size) +int copy_to_user_proc(void __user *to, void *from, int size) { return(copy_to_user(to, from, size)); } -int copy_from_user_proc(void *to, void *from, int size) +int copy_from_user_proc(void *to, void __user *from, int size) { return(copy_from_user(to, from, size)); } -int clear_user_proc(void *buf, int size) +int clear_user_proc(void __user *buf, int size) { return(clear_user(buf, size)); } -int strlen_user_proc(char *str) +int strlen_user_proc(char __user *str) { return(strlen_user(str)); } diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 23c11c426ab2..0d8e76969600 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -81,7 +81,7 @@ long sys_ptrace(long request, long pid, long addr, long data) copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp, (unsigned long __user *) data); break; } @@ -103,7 +103,7 @@ long sys_ptrace(long request, long pid, long addr, long data) addr = addr >> 2; tmp = child->thread.arch.debugregs[addr]; } - ret = put_user(tmp, (unsigned long *) data); + ret = put_user(tmp, (unsigned long __user *) data); break; } @@ -201,7 +201,8 @@ long sys_ptrace(long request, long pid, long addr, long data) break; } for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { - __put_user(getreg(child, i), (unsigned long *) data); + __put_user(getreg(child, i), + (unsigned long __user *) data); data += sizeof(long); } ret = 0; @@ -217,7 +218,7 @@ long sys_ptrace(long request, long pid, long addr, long data) break; } for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { - __get_user(tmp, (unsigned long *) data); + __get_user(tmp, (unsigned long __user *) data); putreg(child, i, tmp); data += sizeof(long); } @@ -251,14 +252,14 @@ long sys_ptrace(long request, long pid, long addr, long data) fault = ((struct ptrace_faultinfo) { .is_write = child->thread.err, .addr = child->thread.cr2 }); - ret = copy_to_user((unsigned long *) data, &fault, + ret = copy_to_user((unsigned long __user *) data, &fault, sizeof(fault)); if(ret) break; break; } case PTRACE_SIGPENDING: - ret = copy_to_user((unsigned long *) data, + ret = copy_to_user((unsigned long __user *) data, &child->pending.signal, sizeof(child->pending.signal)); break; @@ -266,7 +267,7 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_LDT: { struct ptrace_ldt ldt; - if(copy_from_user(&ldt, (unsigned long *) data, + if(copy_from_user(&ldt, (unsigned long __user *) data, sizeof(ldt))){ ret = -EIO; break; diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 44c05e5690b8..7807a3e8c426 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -196,7 +196,7 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) } } -long sys_sigaltstack(const stack_t *uss, stack_t *uoss) +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 6d559db8f865..c8e5fe49583a 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -132,10 +132,10 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) return(0); } -int copy_from_user_skas(void *to, const void *from, int n) +int copy_from_user_skas(void *to, const void __user *from, int n) { if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); + memcpy(to, (__force void*)from, n); return(0); } @@ -153,10 +153,10 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) return(0); } -int copy_to_user_skas(void *to, const void *from, int n) +int copy_to_user_skas(void __user *to, const void *from, int n) { if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); + memcpy((__force void*)to, from, n); return(0); } @@ -179,13 +179,13 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) return(0); } -int strncpy_from_user_skas(char *dst, const char *src, int count) +int strncpy_from_user_skas(char *dst, const char __user *src, int count) { int n; char *ptr = dst; if(segment_eq(get_fs(), KERNEL_DS)){ - strncpy(dst, src, count); + strncpy(dst, (__force void*)src, count); return(strnlen(dst, count)); } @@ -205,15 +205,15 @@ static int clear_chunk(unsigned long addr, int len, void *unused) return(0); } -int __clear_user_skas(void *mem, int len) +int __clear_user_skas(void __user *mem, int len) { return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); } -int clear_user_skas(void *mem, int len) +int clear_user_skas(void __user *mem, int len) { if(segment_eq(get_fs(), KERNEL_DS)){ - memset(mem, 0, len); + memset((__force void*)mem, 0, len); return(0); } @@ -233,12 +233,12 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) return(0); } -int strnlen_user_skas(const void *str, int len) +int strnlen_user_skas(const void __user *str, int len) { int count = 0, n; if(segment_eq(get_fs(), KERNEL_DS)) - return(strnlen(str, len) + 1); + return(strnlen((__force char*)str, len) + 1); n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); if(n == 0) diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c index b620e7c17aa2..a294e5071fe8 100644 --- a/arch/um/kernel/syscall_kern.c +++ b/arch/um/kernel/syscall_kern.c @@ -27,10 +27,9 @@ /* Unlocked, I don't care if this is a bit off */ int nsyscalls = 0; -long um_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void * data) +long um_mount(char __user * dev_name, char __user * dir_name, + char __user * type, unsigned long new_flags, void __user * data) { - if(type == NULL) type = ""; return(sys_mount(dev_name, dir_name, type, new_flags, data)); } @@ -96,7 +95,7 @@ long old_mmap(unsigned long addr, unsigned long len, * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -long sys_pipe(unsigned long * fildes) +long sys_pipe(unsigned long __user * fildes) { int fd[2]; long error; diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 3b538f6cc3ae..df21b0529ae6 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -111,19 +111,19 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) return(IRQ_HANDLED); } -long um_time(int * tloc) +long um_time(int __user *tloc) { struct timeval now; do_gettimeofday(&now); if (tloc) { - if (put_user(now.tv_sec,tloc)) + if (put_user(now.tv_sec, tloc)) now.tv_sec = -EFAULT; } return now.tv_sec; } -long um_stime(int * tptr) +long um_stime(int __user *tptr) { int value; struct timespec new; diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index 0409718935f7..a72aa632972f 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c @@ -6,7 +6,7 @@ #include "linux/sched.h" #include "asm/uaccess.h" -int copy_from_user_tt(void *to, const void *from, int n) +int copy_from_user_tt(void *to, const void __user *from, int n) { if(!access_ok_tt(VERIFY_READ, from, n)) return(n); @@ -15,7 +15,7 @@ int copy_from_user_tt(void *to, const void *from, int n) ¤t->thread.fault_catcher)); } -int copy_to_user_tt(void *to, const void *from, int n) +int copy_to_user_tt(void __user *to, const void *from, int n) { if(!access_ok_tt(VERIFY_WRITE, to, n)) return(n); @@ -24,7 +24,7 @@ int copy_to_user_tt(void *to, const void *from, int n) ¤t->thread.fault_catcher)); } -int strncpy_from_user_tt(char *dst, const char *src, int count) +int strncpy_from_user_tt(char *dst, const char __user *src, int count) { int n; @@ -38,14 +38,14 @@ int strncpy_from_user_tt(char *dst, const char *src, int count) return(n); } -int __clear_user_tt(void *mem, int len) +int __clear_user_tt(void __user *mem, int len) { return(__do_clear_user(mem, len, ¤t->thread.fault_addr, ¤t->thread.fault_catcher)); } -int clear_user_tt(void *mem, int len) +int clear_user_tt(void __user *mem, int len) { if(!access_ok_tt(VERIFY_WRITE, mem, len)) return(len); @@ -54,7 +54,7 @@ int clear_user_tt(void *mem, int len) ¤t->thread.fault_catcher)); } -int strnlen_user_tt(const void *str, int len) +int strnlen_user_tt(const void __user *str, int len) { return(__do_strnlen_user(str, len, ¤t->thread.fault_addr, diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 98d7691980b2..e97b98806af7 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -15,10 +15,12 @@ extern int modify_ldt(int func, void *ptr, unsigned long bytecount); /* XXX this needs copy_to_user and copy_from_user */ -int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) +int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount) { - if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); - return(modify_ldt(func, ptr, bytecount)); + if (verify_area(VERIFY_READ, ptr, bytecount)) + return -EFAULT; + + return modify_ldt(func, ptr, bytecount); } #endif @@ -27,7 +29,7 @@ extern int userspace_pid; #include "skas_ptrace.h" -int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) +int sys_modify_ldt_skas(int func, void __user *ptr, unsigned long bytecount) { struct ptrace_ldt ldt; void *buf; @@ -76,7 +78,7 @@ int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) } #endif -int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) +int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, ptr, bytecount)); diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 42322d888503..c6a1bba337ea 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -3,6 +3,8 @@ * Licensed under the GPL */ +#include +#include #include "linux/sched.h" #include "asm/elf.h" #include "asm/ptrace.h" @@ -22,7 +24,7 @@ int is_syscall(unsigned long addr) unsigned short instr; int n; - n = copy_from_user(&instr, (void *) addr, sizeof(instr)); + n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); if(n){ printk("is_syscall : failed to read instruction from 0x%lx\n", addr); @@ -175,12 +177,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave */ #ifdef CONFIG_MODE_TT -static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, +static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, struct pt_regs *regs) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; - struct _fpreg *to; + struct _fpreg __user *to; struct _fpxreg *from; int i; @@ -205,7 +207,7 @@ static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, } #endif -static inline int convert_fxsr_to_user(struct _fpstate *buf, +static inline int convert_fxsr_to_user(struct _fpstate __user *buf, struct pt_regs *regs) { return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); @@ -213,12 +215,12 @@ static inline int convert_fxsr_to_user(struct _fpstate *buf, #ifdef CONFIG_MODE_TT static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; struct _fpxreg *to; - struct _fpreg *from; + struct _fpreg __user *from; int i; if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) @@ -244,7 +246,7 @@ static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, #endif static inline int convert_fxsr_from_user(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); } @@ -253,7 +255,7 @@ int get_fpregs(unsigned long buf, struct task_struct *child) { int err; - err = convert_fxsr_to_user((struct _fpstate *) buf, + err = convert_fxsr_to_user((struct _fpstate __user *) buf, &child->thread.regs); if(err) return(-EFAULT); else return(0); @@ -264,7 +266,7 @@ int set_fpregs(unsigned long buf, struct task_struct *child) int err; err = convert_fxsr_from_user(&child->thread.regs, - (struct _fpstate *) buf); + (struct _fpstate __user *) buf); if(err) return(-EFAULT); else return(0); } @@ -276,7 +278,7 @@ int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_to_user((void *) buf, fxsave, + err = __copy_to_user((void __user *) buf, fxsave, sizeof(struct user_fxsr_struct)); if(err) return -EFAULT; else return 0; @@ -295,7 +297,7 @@ int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_from_user(fxsave, (void *) buf, + err = __copy_from_user(fxsave, (void __user *) buf, sizeof(struct user_fxsr_struct) ); if(err) return -EFAULT; else return 0; diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c index a30140331cf7..467d489c31cd 100644 --- a/arch/um/sys-i386/sigcontext.c +++ b/arch/um/sys-i386/sigcontext.c @@ -22,8 +22,7 @@ void sc_to_sc(void *to_ptr, void *from_ptr) unsigned long *sc_sigmask(void *sc_ptr) { struct sigcontext *sc = sc_ptr; - - return(&sc->oldmask); + return &sc->oldmask; } int sc_get_fpregs(unsigned long buf, void *sc_ptr) diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 6794671be7a3..0cb4c86b5c2b 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -146,7 +146,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, } #endif -static int copy_sc_from_user(struct pt_regs *to, void *from) +static int copy_sc_from_user(struct pt_regs *to, void __user *from) { int ret; diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index 14f1434374ee..dd58b5511e9b 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c @@ -30,7 +30,7 @@ extern int old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset); -long old_mmap_i386(struct mmap_arg_struct *arg) +long old_mmap_i386(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int err = -EFAULT; @@ -45,11 +45,13 @@ long old_mmap_i386(struct mmap_arg_struct *arg) struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp; + fd_set __user *outp; + fd_set __user *exp; + struct timeval __user *tvp; }; -long old_select(struct sel_arg_struct *arg) +long old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -62,8 +64,8 @@ long old_select(struct sel_arg_struct *arg) /* The i386 version skips reading from %esi, the fourth argument. So we must do * this, too. */ -long sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, - int unused, int *child_tid) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int __user *parent_tid, int unused, int __user *child_tid) { long ret; @@ -86,7 +88,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, * This is really horribly ugly. */ long sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void *__user ptr, long fifth) { int version, ret; diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index 4864c0605972..a5682f1d020d 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c @@ -128,7 +128,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, #endif -static int copy_sc_from_user(struct pt_regs *to, void *from) +static int copy_sc_from_user(struct pt_regs *to, void __user *from) { int ret; diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h index d42d5f8dcdfd..801710d00a40 100644 --- a/include/asm-um/uaccess.h +++ b/include/asm-um/uaccess.h @@ -55,7 +55,7 @@ #define get_user(x, ptr) \ ({ \ - const __typeof__((*(ptr))) *private_ptr = (ptr); \ + const __typeof__((*(ptr))) __user *private_ptr = (ptr); \ (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \ }) @@ -75,7 +75,7 @@ #define put_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) *private_ptr = (ptr); \ + __typeof__(*(ptr)) __user *private_ptr = (ptr); \ (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ __put_user(x, private_ptr) : -EFAULT); \ }) -- cgit v1.2.3 From bf36f91f08100b758a4f12811da05b9c1ce09c90 Mon Sep 17 00:00:00 2001 From: Prasanna Meda Date: Tue, 11 Jan 2005 03:18:08 -0800 Subject: [PATCH] easily tweakable comm length This change still keeps the comm length at 16, but allows easier patching for local modifications, and also introduces a macro to use instead of magic 16, where sizeof(comm) is not preferable to use. Not able to use killall, pidof etc. effectively, when long process names are used for scripts. Just changing the command length from 16 to 32 breaks a.out coredump logic. Deamonise and get_task_comm helped in other places in 2.6.10. Signed-off-by: Prasanna Meda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc64/kernel/binfmt_aout32.c | 2 +- fs/binfmt_aout.c | 2 +- include/linux/sched.h | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index 64d547853b48..c54d806e13d2 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -95,7 +95,7 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file) set_fs(KERNEL_DS); has_dumped = 1; current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(current->comm)); + strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm)); dump.signal = signr; dump_thread(regs, &dump); diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index acdd53848566..8075fdff2364 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -112,7 +112,7 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file) set_fs(KERNEL_DS); has_dumped = 1; current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(current->comm)); + strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm)); #ifndef __sparc__ dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index dcc1814f97e8..96f69aaa0534 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -121,6 +121,9 @@ extern unsigned long nr_iowait(void); #define set_current_state(state_value) \ set_mb(current->state, (state_value)) +/* Task command name length */ +#define TASK_COMM_LEN 16 + /* * Scheduling policies */ @@ -612,7 +615,7 @@ struct task_struct { struct key *thread_keyring; /* keyring private to this thread */ #endif unsigned short used_math; - char comm[16]; + char comm[TASK_COMM_LEN]; /* file system info */ int link_count, total_link_count; /* ipc stuff */ -- cgit v1.2.3 From f1395ea3c1fbf67824ff83e5d4fd7aefb5346e90 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:19:00 -0800 Subject: [PATCH] pcmcia: new ds - cs interface Add a new registration function to register the PCMCIA 16-bit subsystem (ds a.k.a. pcmcia) with the PCMICA core (cs a.k.a. pcmcia_core). As send_event is only called with skt->sem held, we can use that to safeguard skt->callback(), too. Note that the class_device_register() call by pccardd() is done _before_ skt->sem() is held, and the pcmcia_socket_register() doesn't hold skt->sem() as well, so there is no chance for a deadlock. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 55 ++++++++++++++++++++++++++++++++++++++++++-- drivers/pcmcia/cs_internal.h | 8 +++++++ drivers/pcmcia/ds.c | 51 ++++++++++++---------------------------- include/pcmcia/ss.h | 2 ++ 4 files changed, 78 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 4e4c964f7e01..7a522f0eed88 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -349,8 +349,6 @@ static void free_regions(memory_handle_t *list) } } -static int send_event(struct pcmcia_socket *s, event_t event, int priority); - static void shutdown_socket(struct pcmcia_socket *s) { client_t **c; @@ -402,6 +400,26 @@ static void shutdown_socket(struct pcmcia_socket *s) ======================================================================*/ + +static int pcmcia_send_event(struct pcmcia_socket *s, event_t event, int priority) +{ + int ret; + + if (!s->callback) + return 0; + if (!try_module_get(s->callback->owner)) + return 0; + + ret = s->callback->event(s, event, priority); + + module_put(s->callback->owner); + + return ret; +} + + +/* NOTE: send_event needs to be called with skt->sem held. */ + static int send_event(struct pcmcia_socket *s, event_t event, int priority) { client_t *client = s->clients; @@ -411,6 +429,11 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority) ret = 0; if (s->state & SOCKET_CARDBUS) return 0; + + ret = pcmcia_send_event(s, event, priority); + if (ret) + return (ret); + for (; client; client = client->next) { if (client->state & (CLIENT_UNBOUND|CLIENT_STALE)) continue; @@ -1363,6 +1386,34 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) return CS_OUT_OF_RESOURCE; } /* register_client */ +/* register pcmcia_callback */ +int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) +{ + int ret = 0; + + /* s->skt_sem also protects s->callback */ + down(&s->skt_sem); + + if (c) { + /* registration */ + if (s->callback) { + ret = -EBUSY; + goto err; + } + + s->callback = c; + + if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) + pcmcia_send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); + } else + s->callback = NULL; + err: + up(&s->skt_sem); + + return ret; +} +EXPORT_SYMBOL(pccard_register_pcmcia); + /*====================================================================*/ int pcmcia_release_configuration(client_handle_t handle) diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index fbce6b67988b..dcb1c651724f 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -173,6 +173,14 @@ int pccard_reset_card(struct pcmcia_socket *skt); int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status); int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg); + +struct pcmcia_callback{ + struct module *owner; + int (*event) (struct pcmcia_socket *s, event_t event, int priority); +}; + +int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); + #define cs_socket_name(skt) ((skt)->dev.class_id) #ifdef DEBUG diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 639c5acf22f1..536dccc5bff1 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -112,7 +112,7 @@ typedef struct user_info_t { /* Socket state information */ struct pcmcia_bus_socket { atomic_t refcount; - client_handle_t handle; + struct pcmcia_callback callback; int state; user_info_t *user; int req_pending, req_result; @@ -484,14 +484,12 @@ static void handle_removal(void *data) ======================================================================*/ -static int ds_event(event_t event, int priority, - event_callback_args_t *args) +static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) { - struct pcmcia_bus_socket *s; + struct pcmcia_bus_socket *s = skt->pcmcia; ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", - event, priority, args->client_handle); - s = args->client_data; + event, priority, s); switch (event) { @@ -1082,8 +1080,6 @@ static struct file_operations ds_fops = { static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_dev->class_data; - client_reg_t client_reg; - bind_req_t bind; struct pcmcia_bus_socket *s; int ret; @@ -1107,35 +1103,18 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) s->parent = socket; /* Set up hotline to Card Services */ - client_reg.dev_info = bind.dev_info = &dev_info; - - bind.Socket = socket; - bind.Function = BIND_FN_ALL; - ret = pcmcia_bind_device(&bind); - if (ret != CS_SUCCESS) { - cs_error(NULL, BindDevice, ret); - kfree(s); - return -EINVAL; - } + s->callback.owner = THIS_MODULE; + s->callback.event = &ds_event; + socket->pcmcia = s; - client_reg.Attributes = INFO_MASTER_CLIENT; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_EJECTION_REQUEST | CS_EVENT_INSERTION_REQUEST | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &ds_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = s; - ret = pcmcia_register_client(&s->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(NULL, RegisterClient, ret); - kfree(s); - return -EINVAL; + ret = pccard_register_pcmcia(socket, &s->callback); + if (ret) { + printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); + pcmcia_put_bus_socket(s); + socket->pcmcia = NULL; + return (ret); } - socket->pcmcia = s; - return 0; } @@ -1147,9 +1126,9 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev) if (!socket || !socket->pcmcia) return; - flush_scheduled_work(); + pccard_register_pcmcia(socket, NULL); - pcmcia_deregister_client(socket->pcmcia->handle); + flush_scheduled_work(); socket->pcmcia->state |= DS_SOCKET_DEAD; pcmcia_put_bus_socket(socket->pcmcia); diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 1958cda29889..c8c53fc0ef07 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -159,6 +159,7 @@ typedef struct window_t { struct config_t; struct region_t; +struct pcmcia_callback; struct pcmcia_socket { struct module *owner; @@ -215,6 +216,7 @@ struct pcmcia_socket { /* pcmcia (16-bit) */ struct pcmcia_bus_socket *pcmcia; + struct pcmcia_callback *callback; /* cardbus (32-bit) */ #ifdef CONFIG_CARDBUS -- cgit v1.2.3 From 32363bfb234d9514f6f278eb84e53401de7734f8 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:19:27 -0800 Subject: [PATCH] pcmcia: unify bind_mtd and pcmcia_bind_mtd Unify the pcmcia_bind_mtd and bind_mtd functions. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 73 +++++++++++++---------------------------------------- include/pcmcia/cs.h | 7 ----- 2 files changed, 18 insertions(+), 62 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index fee02e131d85..f8fc17b0d92b 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -171,46 +171,6 @@ static int pcmcia_bind_device(bind_req_t *req) return CS_SUCCESS; } /* bind_device */ - -/*====================================================================== - - Bind_mtd() associates a device driver with a particular memory - region. It is normally called by Driver Services after it has - identified a memory device type. An instance of the corresponding - driver will then be able to register to control this region. - -======================================================================*/ - -static int pcmcia_bind_mtd(mtd_bind_t *req) -{ - struct pcmcia_socket *s; - memory_handle_t region; - - s = req->Socket; - if (!s) - return CS_BAD_SOCKET; - - if (req->Attributes & REGION_TYPE_AM) - region = s->a_region; - else - region = s->c_region; - - while (region) { - if (region->info.CardOffset == req->CardOffset) - break; - region = region->info.next; - } - if (!region || (region->mtd != NULL)) - return CS_BAD_OFFSET; - strlcpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN); - - ds_dbg(1, "%s: bind_mtd: attr 0x%x, offset 0x%x, dev %s\n", - cs_socket_name(s), req->Attributes, req->CardOffset, - (char *)req->dev_info); - return CS_SUCCESS; -} /* bind_mtd */ - - /* String tables for error messages */ typedef struct lookup_t { @@ -545,22 +505,25 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) { - mtd_bind_t bind_req; - int ret; + struct pcmcia_socket *s = bus_sock->parent; + memory_handle_t region; - bind_req.dev_info = &mtd_info->dev_info; - bind_req.Attributes = mtd_info->Attributes; - bind_req.Socket = bus_sock->parent; - bind_req.CardOffset = mtd_info->CardOffset; - ret = pcmcia_bind_mtd(&bind_req); - if (ret != CS_SUCCESS) { - cs_error(NULL, BindMTD, ret); - printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d" - " offset 0x%x\n", - (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset); - return -ENODEV; - } - return 0; + if (mtd_info->Attributes & REGION_TYPE_AM) + region = s->a_region; + else + region = s->c_region; + + while (region) { + if (region->info.CardOffset == mtd_info->CardOffset) + break; + region = region->info.next; + } + if (!region || (region->mtd != NULL)) + return -ENODEV; + + strlcpy(region->dev_info, mtd_info->dev_info, DEV_NAME_LEN); + + return 0; } /* bind_mtd */ /*====================================================================== diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 48eddee1e554..6c518d10d8d5 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -325,13 +325,6 @@ typedef struct bind_req_t { /* Flag to bind to all functions */ #define BIND_FN_ALL 0xff -typedef struct mtd_bind_t { - struct pcmcia_socket *Socket; - u_int Attributes; - u_int CardOffset; - dev_info_t *dev_info; -} mtd_bind_t; - /* Events */ #define CS_EVENT_PRI_LOW 0 #define CS_EVENT_PRI_HIGH 1 -- cgit v1.2.3 From 26432027dec4d2c887a742a619331e6b82de34f3 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:19:40 -0800 Subject: [PATCH] pcmcia: unfiy bind_device and pcmcia_bind_device Unify bind_device and pcmcia_bind_device. Also, change bind_device so that it conforms to CodingStyle. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 161 ++++++++++++++++++++++------------------------------ include/pcmcia/cs.h | 9 +-- 2 files changed, 69 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index f8fc17b0d92b..a9d572ec8bc0 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -128,49 +128,12 @@ struct pcmcia_bus_socket { /*====================================================================*/ -/* Device driver ID passed to Card Services */ -static dev_info_t dev_info = "Driver Services"; - static int major_dev = -1; /*====================================================================*/ /* code which was in cs.c before */ -/*====================================================================== - - Bind_device() associates a device driver with a particular socket. - It is normally called by Driver Services after it has identified - a newly inserted card. An instance of that driver will then be - eligible to register as a client of this socket. - -======================================================================*/ - -static int pcmcia_bind_device(bind_req_t *req) -{ - client_t *client; - struct pcmcia_socket *s; - - s = req->Socket; - if (!s) - return CS_BAD_SOCKET; - - client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL); - if (!client) - return CS_OUT_OF_RESOURCE; - memset(client, '\0', sizeof(client_t)); - client->client_magic = CLIENT_MAGIC; - strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN); - client->Socket = s; - client->Function = req->Function; - client->state = CLIENT_UNBOUND; - client->next = s->clients; - s->clients = client; - ds_dbg(1, "%s: bind_device(): client 0x%p, dev %s\n", - cs_socket_name(client->Socket), client, client->dev_info); - return CS_SUCCESS; -} /* bind_device */ - /* String tables for error messages */ typedef struct lookup_t { @@ -528,79 +491,89 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) /*====================================================================== + bind_request() and bind_device() are merged by now. Individual + descriptions: + bind_request() connects a socket to a particular client driver. It looks up the specified device ID in the list of registered drivers, binds it to the socket, and tries to create an instance of the device. unbind_request() deletes a driver instance. + Bind_device() associates a device driver with a particular socket. + It is normally called by Driver Services after it has identified + a newly inserted card. An instance of that driver will then be + eligible to register as a client of this socket. + ======================================================================*/ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { - struct pcmcia_driver *driver; - socket_bind_t *b; - bind_req_t bind_req; - int ret; + struct pcmcia_driver *driver; + socket_bind_t *b; + client_t *client; - if (!s) - return -EINVAL; + if (!s) + return -EINVAL; - ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, - (char *)bind_info->dev_info); - driver = get_pcmcia_driver(&bind_info->dev_info); - if (!driver) - return -EINVAL; + ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, + (char *)bind_info->dev_info); + driver = get_pcmcia_driver(&bind_info->dev_info); + if (!driver) + return -EINVAL; - for (b = s->bind; b; b = b->next) - if ((driver == b->driver) && - (bind_info->function == b->function)) - break; - if (b != NULL) { - bind_info->instance = b->instance; - return -EBUSY; - } + for (b = s->bind; b; b = b->next) + if ((driver == b->driver) && + (bind_info->function == b->function)) + break; + if (b != NULL) { + bind_info->instance = b->instance; + return -EBUSY; + } - if (!try_module_get(driver->owner)) - return -EINVAL; - - bind_req.Socket = s->parent; - bind_req.Function = bind_info->function; - bind_req.dev_info = (dev_info_t *) driver->drv.name; - ret = pcmcia_bind_device(&bind_req); - if (ret != CS_SUCCESS) { - cs_error(NULL, BindDevice, ret); - printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n", - (char *)dev_info, s->parent->sock); - module_put(driver->owner); - return -ENODEV; - } + if (!try_module_get(driver->owner)) + return -EINVAL; - /* Add binding to list for this socket */ - driver->use_count++; - b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); - if (!b) - { - driver->use_count--; - module_put(driver->owner); - return -ENOMEM; - } - b->driver = driver; - b->function = bind_info->function; - b->instance = NULL; - b->next = s->bind; - s->bind = b; - - if (driver->attach) { - b->instance = driver->attach(); - if (b->instance == NULL) { - printk(KERN_NOTICE "ds: unable to create instance " - "of '%s'!\n", (char *)bind_info->dev_info); - module_put(driver->owner); - return -ENODEV; + client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL); + if (!client) { + module_put(driver->owner); + return -ENOMEM; + } + memset(client, 0, sizeof(client_t)); + + client->client_magic = CLIENT_MAGIC; + client->Socket = s->parent; + client->Function = bind_info->function; + client->state = CLIENT_UNBOUND; + client->next = s->parent->clients; + strlcpy(client->dev_info, driver->drv.name, DEV_NAME_LEN); + s->parent->clients = client; + + /* Add binding to list for this socket */ + b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); + if (!b) + { + module_put(driver->owner); + return -ENOMEM; + } + b->driver = driver; + b->function = bind_info->function; + b->instance = NULL; + b->next = s->bind; + s->bind = b; + + driver->use_count++; + if (driver->attach) { + b->instance = driver->attach(); + if (b->instance == NULL) { + printk(KERN_NOTICE "ds: unable to create instance " + "of '%s'!\n", (char *)bind_info->dev_info); + module_put(driver->owner); + /* FIXME: client isn't freed here */ + return -ENODEV; + } } - } - return 0; + return 0; } /* bind_request */ /*====================================================================*/ diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 6c518d10d8d5..4a82490a1e45 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -315,13 +315,6 @@ typedef struct error_info_t { int retcode; } error_info_t; -/* Special stuff for binding drivers to sockets */ -typedef struct bind_req_t { - struct pcmcia_socket *Socket; - u_char Function; - dev_info_t *dev_info; -} bind_req_t; - /* Flag to bind to all functions */ #define BIND_FN_ALL 0xff @@ -413,6 +406,8 @@ enum service { GetFirstWindow, GetNextWindow, GetMemPage }; +struct pcmcia_socket; + int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg); int pcmcia_deregister_client(client_handle_t handle); int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config); -- cgit v1.2.3 From 632a82e01b23d22667117e035a2b81455e7f9335 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:19:53 -0800 Subject: [PATCH] pcmcia: device model integration can only be submitted under GPL As discussed previously, my integration of ds.c with the driver model can and will only be available under the GPL, as it's too much derived of other buses' implementation of integration with the driver model. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 48 +++++++++++++++--------------------------------- include/pcmcia/ds.h | 26 ++++++-------------------- 2 files changed, 21 insertions(+), 53 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a9d572ec8bc0..b2f42d04503d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1,35 +1,17 @@ -/*====================================================================== - - PC Card Driver Services - - ds.c 1.112 2001/10/13 00:08:28 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in - which case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * ds.c -- 16-bit PCMCIA core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + * (C) 2003 - 2004 Dominik Brodowski + */ #include #include @@ -72,7 +54,7 @@ MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("PCMCIA Driver Services"); -MODULE_LICENSE("Dual MPL/GPL"); +MODULE_LICENSE("GPL"); #ifdef DEBUG int ds_pc_debug; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 8a22fecf1cbd..ec0c0b9c1a06 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -1,30 +1,16 @@ /* - * ds.h 1.56 2000/06/12 21:55:40 + * ds.h -- 16-bit PCMCIA core support * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds + * (C) 2003 - 2004 Dominik Brodowski */ #ifndef _LINUX_DS_H -- cgit v1.2.3 From eac81ddc89a8a15f7ac4a0e44d8225c4a8e88a5f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:20:06 -0800 Subject: [PATCH] pcmcia: add pcmcia_device(s) Add pcmcia_device(s). Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/pcmcia/ds.h | 22 ++++++++++++++++ 2 files changed, 95 insertions(+) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index b2f42d04503d..a37746187881 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -101,7 +101,15 @@ struct pcmcia_bus_socket { wait_queue_head_t queue, request; socket_bind_t *bind; struct pcmcia_socket *parent; + + /* the PCMCIA devices connected to this socket (normally one, more + * for multifunction devices: */ + struct list_head devices_list; + u8 device_count; /* the number of devices, used + * only internally and subject + * to incorrectness and change */ }; +static spinlock_t pcmcia_dev_list_lock; #define DS_SOCKET_PRESENT 0x01 #define DS_SOCKET_BUSY 0x02 @@ -328,6 +336,16 @@ static int proc_read_drivers(char *buf, char **start, off_t pos, } #endif +/* pcmcia_device handling */ + +static void pcmcia_release_dev(struct device *dev) +{ + struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + p_dev->socket->pcmcia->device_count = 0; + kfree(p_dev); +} + + /*====================================================================== These manage a ring buffer of events pending for one user process @@ -491,8 +509,10 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { struct pcmcia_driver *driver; + struct pcmcia_device *p_dev; socket_bind_t *b; client_t *client; + unsigned long flags; if (!s) return -EINVAL; @@ -543,6 +563,38 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) b->next = s->bind; s->bind = b; + /* Currently, the userspace pcmcia cardmgr detects pcmcia devices. + * Here this information is translated into a kernel + * struct pcmcia_device. + */ + + p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); + if (!p_dev) { + /* FIXME: client isn't freed here */ + goto no_p_dev; + } + memset(p_dev, 0, sizeof(struct pcmcia_device)); + + p_dev->socket = s->parent; + p_dev->device_no = (s->device_count++); + p_dev->func = bind_info->function; + + p_dev->dev.bus = &pcmcia_bus_type; + p_dev->dev.parent = s->parent->dev.dev; + p_dev->dev.release = pcmcia_release_dev; + sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->device_no); + p_dev->dev.driver = &driver->drv; + if (device_register(&p_dev->dev)) { + /* FIXME: client isn't freed here */ + kfree(p_dev); + goto no_p_dev; + } + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_add_tail(&p_dev->socket_device_list, &s->devices_list); + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + no_p_dev: + driver->use_count++; if (driver->attach) { b->instance = driver->attach(); @@ -632,6 +684,8 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { socket_bind_t **b, *c; + struct pcmcia_device *p_dev; + unsigned long flags; ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock, (char *)bind_info->dev_info); @@ -652,6 +706,22 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) module_put(c->driver->owner); *b = c->next; kfree(c); + + restart: + /* unregister the pcmcia_device */ + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == bind_info->function) { + list_del(&p_dev->socket_device_list); + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + device_unregister(&p_dev->dev); + + /* multiple devices may be registered to this "function" */ + goto restart; + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); return 0; } /* unbind_request */ @@ -1034,6 +1104,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); + INIT_LIST_HEAD(&s->devices_list); /* initialize data */ s->parent = socket; @@ -1090,6 +1161,8 @@ static int __init init_pcmcia_bus(void) { int i; + spin_lock_init(&pcmcia_dev_list_lock); + bus_register(&pcmcia_bus_type); class_interface_register(&pcmcia_bus_interface); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index ec0c0b9c1a06..35437bc8303b 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -127,6 +127,8 @@ typedef struct dev_link_t { ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT))) +struct pcmcia_socket; + extern struct bus_type pcmcia_bus_type; struct pcmcia_driver { @@ -141,6 +143,26 @@ struct pcmcia_driver { int pcmcia_register_driver(struct pcmcia_driver *driver); void pcmcia_unregister_driver(struct pcmcia_driver *driver); +struct pcmcia_device { + /* the socket and the device_no [for multifunction devices] + uniquely define a pcmcia_device */ + struct pcmcia_socket *socket; + + u8 device_no; + + /* the hardware "function" device; certain subdevices can + * share one hardware "function" device. */ + u8 func; + + struct list_head socket_device_list; + + struct device dev; +}; + +#define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev) +#define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) + + /* error reporting */ void cs_error(client_handle_t handle, int func, int ret); -- cgit v1.2.3 From daca1b3686b00cfad0281d016d5517610345c85f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:20:20 -0800 Subject: [PATCH] pcmcia: remove socket_bind_t, use pcmcia_devices instead Remove struct socket_bind_t by moving "dev_link_t *instance" to struct pcmcia_device, and transforming all users of socket_bind_t to use struct pcmcia_device instead. Also, CodingStyle updates for get_device_info and unbind_request. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 310 +++++++++++++++++++++++++++------------------------- include/pcmcia/ds.h | 4 + 2 files changed, 168 insertions(+), 146 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a37746187881..1fe37b8ad12b 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -71,13 +71,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644); /*====================================================================*/ -typedef struct socket_bind_t { - struct pcmcia_driver *driver; - u_char function; - dev_link_t *instance; - struct socket_bind_t *next; -} socket_bind_t; - /* Device user information */ #define MAX_EVENTS 32 #define USER_MAGIC 0x7ea4 @@ -99,7 +92,6 @@ struct pcmcia_bus_socket { user_info_t *user; int req_pending, req_result; wait_queue_head_t queue, request; - socket_bind_t *bind; struct pcmcia_socket *parent; /* the PCMCIA devices connected to this socket (normally one, more @@ -338,6 +330,20 @@ static int proc_read_drivers(char *buf, char **start, off_t pos, /* pcmcia_device handling */ +static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) +{ + struct device *tmp_dev; + tmp_dev = get_device(&p_dev->dev); + if (!tmp_dev) + return NULL; + return to_pcmcia_dev(tmp_dev); +} + +static void pcmcia_put_dev(struct pcmcia_device *p_dev) +{ + put_device(&p_dev->dev); +} + static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); @@ -508,37 +514,29 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { - struct pcmcia_driver *driver; - struct pcmcia_device *p_dev; - socket_bind_t *b; + struct pcmcia_driver *p_drv; + struct pcmcia_device *p_dev, *tmp_dev; client_t *client; unsigned long flags; + int ret = 0; if (!s) return -EINVAL; ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, (char *)bind_info->dev_info); - driver = get_pcmcia_driver(&bind_info->dev_info); - if (!driver) - return -EINVAL; - for (b = s->bind; b; b = b->next) - if ((driver == b->driver) && - (bind_info->function == b->function)) - break; - if (b != NULL) { - bind_info->instance = b->instance; - return -EBUSY; - } + p_drv = get_pcmcia_driver(&bind_info->dev_info); + if (!p_drv) + return -EINVAL; - if (!try_module_get(driver->owner)) + if (!try_module_get(p_drv->owner)) return -EINVAL; client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL); if (!client) { - module_put(driver->owner); - return -ENOMEM; + ret = -ENOMEM; + goto err_put; } memset(client, 0, sizeof(client_t)); @@ -547,21 +545,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) client->Function = bind_info->function; client->state = CLIENT_UNBOUND; client->next = s->parent->clients; - strlcpy(client->dev_info, driver->drv.name, DEV_NAME_LEN); - s->parent->clients = client; - - /* Add binding to list for this socket */ - b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL); - if (!b) - { - module_put(driver->owner); - return -ENOMEM; - } - b->driver = driver; - b->function = bind_info->function; - b->instance = NULL; - b->next = s->bind; - s->bind = b; + strlcpy(client->dev_info, p_drv->drv.name, DEV_NAME_LEN); /* Currently, the userspace pcmcia cardmgr detects pcmcia devices. * Here this information is translated into a kernel @@ -570,8 +554,8 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); if (!p_dev) { - /* FIXME: client isn't freed here */ - goto no_p_dev; + ret = -ENOMEM; + goto err_free_client; } memset(p_dev, 0, sizeof(struct pcmcia_device)); @@ -583,31 +567,53 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) p_dev->dev.parent = s->parent->dev.dev; p_dev->dev.release = pcmcia_release_dev; sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->device_no); - p_dev->dev.driver = &driver->drv; - if (device_register(&p_dev->dev)) { - /* FIXME: client isn't freed here */ + p_dev->dev.driver = &p_drv->drv; + + ret = device_register(&p_dev->dev); + if (ret) { kfree(p_dev); - goto no_p_dev; + goto err_free_client; } + + /* Add to the list in pcmcia_bus_socket, but only if no device + * with the same func _and_ driver exists */ spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) { + if ((tmp_dev->func == bind_info->function) && + (tmp_dev->dev.driver == p_dev->dev.driver)){ + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + bind_info->instance = tmp_dev->instance; + ret = -EBUSY; + goto err_unregister; + } + } list_add_tail(&p_dev->socket_device_list, &s->devices_list); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - no_p_dev: + /* finally here the parent client is registered */ + s->parent->clients = client; - driver->use_count++; - if (driver->attach) { - b->instance = driver->attach(); - if (b->instance == NULL) { + p_drv->use_count++; + if (p_drv->attach) { + p_dev->instance = p_drv->attach(); + if (!p_dev->instance) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", (char *)bind_info->dev_info); - module_put(driver->owner); /* FIXME: client isn't freed here */ - return -ENODEV; + ret = -ENODEV; + goto err_unregister; } } - + return 0; + + err_unregister: + device_unregister(&p_dev->dev); + err_free_client: + kfree(client); + err_put: + module_put(p_drv->owner); + return (ret); } /* bind_request */ /*====================================================================*/ @@ -616,113 +622,125 @@ extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s); static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) { - socket_bind_t *b; - dev_node_t *node; + dev_node_t *node; + struct pcmcia_device *p_dev; + unsigned long flags; + int ret = 0; #ifdef CONFIG_CARDBUS - /* - * Some unbelievably ugly code to associate the PCI cardbus - * device and its driver with the PCMCIA "bind" information. - */ - { - struct pci_bus *bus; - - bus = pcmcia_lookup_bus(s->parent); - if (bus) { - struct list_head *list; - struct pci_dev *dev = NULL; - - list = bus->devices.next; - while (list != &bus->devices) { - struct pci_dev *pdev = pci_dev_b(list); - list = list->next; - - if (first) { - dev = pdev; - break; - } + /* + * Some unbelievably ugly code to associate the PCI cardbus + * device and its driver with the PCMCIA "bind" information. + */ + { + struct pci_bus *bus; - /* Try to handle "next" here some way? */ - } - if (dev && dev->driver) { - strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); - bind_info->major = 0; - bind_info->minor = 0; - bind_info->next = NULL; - return 0; + bus = pcmcia_lookup_bus(s->parent); + if (bus) { + struct list_head *list; + struct pci_dev *dev = NULL; + + list = bus->devices.next; + while (list != &bus->devices) { + struct pci_dev *pdev = pci_dev_b(list); + list = list->next; + + if (first) { + dev = pdev; + break; + } + + /* Try to handle "next" here some way? */ + } + if (dev && dev->driver) { + strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); + bind_info->major = 0; + bind_info->minor = 0; + bind_info->next = NULL; + return 0; + } } } - } #endif - for (b = s->bind; b; b = b->next) - if ((strcmp((char *)b->driver->drv.name, - (char *)bind_info->dev_info) == 0) && - (b->function == bind_info->function)) - break; - if (b == NULL) return -ENODEV; - if ((b->instance == NULL) || - (b->instance->state & DEV_CONFIG_PENDING)) - return -EAGAIN; - if (first) - node = b->instance->dev; - else - for (node = b->instance->dev; node; node = node->next) - if (node == bind_info->next) break; - if (node == NULL) return -ENODEV; - - strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); - bind_info->major = node->major; - bind_info->minor = node->minor; - bind_info->next = node->next; - - return 0; + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == bind_info->function) { + p_dev = pcmcia_get_dev(p_dev); + if (!p_dev) + continue; + goto found; + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return -ENODEV; + + found: + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + if ((!p_dev->instance) || + (p_dev->instance->state & DEV_CONFIG_PENDING)) { + ret = -EAGAIN; + goto err_put; + } + + if (first) + node = p_dev->instance->dev; + else + for (node = p_dev->instance->dev; node; node = node->next) + if (node == bind_info->next) + break; + if (!node) { + ret = -ENODEV; + goto err_put; + } + + strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); + bind_info->major = node->major; + bind_info->minor = node->minor; + bind_info->next = node->next; + + err_put: + pcmcia_put_dev(p_dev); + return (ret); } /* get_device_info */ /*====================================================================*/ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { - socket_bind_t **b, *c; - struct pcmcia_device *p_dev; - unsigned long flags; - - ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock, - (char *)bind_info->dev_info); - for (b = &s->bind; *b; b = &(*b)->next) - if ((strcmp((char *)(*b)->driver->drv.name, - (char *)bind_info->dev_info) == 0) && - ((*b)->function == bind_info->function)) - break; - if (*b == NULL) - return -ENODEV; - - c = *b; - c->driver->use_count--; - if (c->driver->detach) { - if (c->instance) - c->driver->detach(c->instance); - } - module_put(c->driver->owner); - *b = c->next; - kfree(c); + struct pcmcia_device *p_dev; + struct pcmcia_driver *p_drv; + unsigned long flags; + + ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock, + (char *)bind_info->dev_info); restart: - /* unregister the pcmcia_device */ - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { - if (p_dev->func == bind_info->function) { - list_del(&p_dev->socket_device_list); - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - device_unregister(&p_dev->dev); - - /* multiple devices may be registered to this "function" */ - goto restart; - } - } - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - return 0; + /* unregister the pcmcia_device */ + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == bind_info->function) { + list_del(&p_dev->socket_device_list); + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + /* detach the "instance" */ + p_drv = to_pcmcia_drv(p_dev->dev.driver); + if (p_drv) { + p_drv->use_count--; + if ((p_drv->detach) && (p_dev->instance)) + p_drv->detach(p_dev->instance); + module_put(p_drv->owner); + } + + device_unregister(&p_dev->dev); + + /* multiple devices may be registered to this "function" */ + goto restart; + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return 0; } /* unbind_request */ /*====================================================================== diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 35437bc8303b..9a25e32eca9b 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -156,6 +156,10 @@ struct pcmcia_device { struct list_head socket_device_list; + /* deprecated, a cleaned up version will be moved into this + struct soon */ + dev_link_t *instance; + struct device dev; }; -- cgit v1.2.3 From ef3571cc1e8902902430ccf85b45510a97fc5ba8 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:20:33 -0800 Subject: [PATCH] pcmcia: remove internal module use count, use module_refcount instead Remove the internal driver use_count in ds.c, as the reference counting is done in the module core anyways, and that reference count is available for cardmgr's usage by a call to module_refcount. And if !CONFIG_MODULE_UNLOAD, rmmod is useless anyways, so avoid that call by cardmgr at all. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 13 ++++++++----- include/pcmcia/ds.h | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 1fe37b8ad12b..24dd95e238a9 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -285,7 +285,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) if (!driver) return -EINVAL; - driver->use_count = 0; driver->drv.bus = &pcmcia_bus_type; return driver_register(&driver->drv); @@ -307,10 +306,16 @@ static struct proc_dir_entry *proc_pccard = NULL; static int proc_read_drivers_callback(struct device_driver *driver, void *d) { char **p = d; - struct pcmcia_driver *p_dev = container_of(driver, + struct pcmcia_driver *p_drv = container_of(driver, struct pcmcia_driver, drv); - *p += sprintf(*p, "%-24.24s 1 %d\n", driver->name, p_dev->use_count); + *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name, +#ifdef CONFIG_MODULE_UNLOAD + (p_drv->owner) ? module_refcount(p_drv->owner) : 1 +#else + 1 +#endif + ); d = (void *) p; return 0; @@ -593,7 +598,6 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) /* finally here the parent client is registered */ s->parent->clients = client; - p_drv->use_count++; if (p_drv->attach) { p_dev->instance = p_drv->attach(); if (!p_dev->instance) { @@ -727,7 +731,6 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) /* detach the "instance" */ p_drv = to_pcmcia_drv(p_dev->dev.driver); if (p_drv) { - p_drv->use_count--; if ((p_drv->detach) && (p_dev->instance)) p_drv->detach(p_dev->instance); module_put(p_drv->owner); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 9a25e32eca9b..3f1e4ccbb31f 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -132,7 +132,6 @@ struct pcmcia_socket; extern struct bus_type pcmcia_bus_type; struct pcmcia_driver { - int use_count; dev_link_t *(*attach)(void); void (*detach)(dev_link_t *); struct module *owner; -- cgit v1.2.3 From 249b2be4f41cd018f89238a5e03dbb16b4bff496 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:21:13 -0800 Subject: [PATCH] pcmcia: device model integration can only be submitted under GPL, part 2 As discussed previously, my integration of ds.c and cs.c with the driver model can and will only be available under the GPL, as it's too much derived of other buses' implementation of integration with the driver model. cs_internal.h did only contain the MPL header before - I contacted Dave Hinds because of this, and as far as he can tell, it was just an oversight that this was not marked as dual-licensed as the other files are. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/bulkmem.c | 45 ++++++++++++------------------------------ drivers/pcmcia/cardbus.c | 45 ++++++++++++------------------------------ drivers/pcmcia/cistpl.c | 45 ++++++++++++------------------------------ drivers/pcmcia/cs.c | 47 +++++++++++++------------------------------- drivers/pcmcia/cs_internal.h | 18 +++++++---------- drivers/pcmcia/rsrc_mgr.c | 45 ++++++++++++------------------------------ include/pcmcia/bulkmem.h | 28 +++++--------------------- include/pcmcia/ciscode.h | 25 +++++------------------ include/pcmcia/cisreg.h | 25 +++++------------------ include/pcmcia/cistpl.h | 25 +++++------------------ include/pcmcia/cs.h | 25 +++++------------------ include/pcmcia/cs_types.h | 25 +++++------------------ include/pcmcia/mem_op.h | 25 +++++------------------ include/pcmcia/ss.h | 25 +++++------------------ 14 files changed, 113 insertions(+), 335 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 855c1f76c5dd..1be40034acd4 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -1,35 +1,16 @@ -/*====================================================================== - - PCMCIA Bulk Memory Services - - bulkmem.c 1.38 2000/09/25 19:29:51 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * bulkmem.c -- 16-bit PCMCIA Bulk Memory Services + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ #include #include diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 1b86c6d3a572..3ccb5247ec50 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -1,35 +1,16 @@ -/*====================================================================== - - Cardbus device configuration - - cardbus.c 1.87 2002/10/24 06:11:41 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * cardbus.c -- 16-bit PCMCIA core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ /* * Cardbus handling has been re-written to be more of a PCI bridge thing, diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 8cf0623397f7..9dbc73df87ee 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1,35 +1,16 @@ -/*====================================================================== - - PCMCIA Card Information Structure parser - - cistpl.c 1.99 2002/10/24 06:11:48 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in - which case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * cistpl.c -- 16-bit PCMCIA Card Information Structure parser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ #include #include diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index c8de9491938c..192ffc4540cf 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -1,35 +1,16 @@ -/*====================================================================== - - Kernel Card Services -- core services - - cs.c 1.271 2000/10/02 20:27:49 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * cs.c -- Kernel Card Services - core services + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ #include #include @@ -92,7 +73,7 @@ static const char *options = "options: " OPTIONS; MODULE_AUTHOR("David Hinds "); MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS); -MODULE_LICENSE("Dual MPL/GPL"); +MODULE_LICENSE("GPL"); #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index dcb1c651724f..67f85f56fe9d 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -1,19 +1,15 @@ /* - * cs_internal.h 1.57 2002/10/24 06:11:43 + * cs_internal.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CS_INTERNAL_H diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 4e0ca166dade..481758277a4d 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -1,35 +1,16 @@ -/*====================================================================== - - Resource management routines - - rsrc_mgr.c 1.79 2000/08/30 20:23:58 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ +/* + * rsrc_mgr.c -- Resource management routines + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ #include #include diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h index f6954220f419..b53b78d497ba 100644 --- a/include/pcmcia/bulkmem.h +++ b/include/pcmcia/bulkmem.h @@ -1,33 +1,15 @@ /* - * Definitions for bulk memory services + * bulkmem.h -- Definitions for bulk memory services * - * bulkmem.h 1.12 2000/06/12 21:55:41 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - * bulkmem.h 1.3 1995/05/27 04:49:49 + * (C) 1999 David A. Hinds */ #ifndef _LINUX_BULKMEM_H diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h index 0d84b163d055..2000b43ece91 100644 --- a/include/pcmcia/ciscode.h +++ b/include/pcmcia/ciscode.h @@ -1,30 +1,15 @@ /* - * ciscode.h 1.56 2002/10/25 06:37:30 + * ciscode.h -- Definitions for bulk memory services * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CISCODE_H diff --git a/include/pcmcia/cisreg.h b/include/pcmcia/cisreg.h index 803d2c369a4b..ddaad465502e 100644 --- a/include/pcmcia/cisreg.h +++ b/include/pcmcia/cisreg.h @@ -1,30 +1,15 @@ /* - * cisreg.h 1.17 2000/06/12 21:55:41 + * cisreg.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CISREG_H diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index 499f748c0028..c6a069554fd7 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -1,30 +1,15 @@ /* - * cistpl.h 1.34 2000/06/19 23:18:12 + * cistpl.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CISTPL_H diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 4a82490a1e45..8bd6081c5f8f 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -1,30 +1,15 @@ /* - * cs.h 1.71 2000/08/29 00:54:20 + * cs.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CS_H diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index 3a4aec08549e..b57c921998f0 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -1,30 +1,15 @@ /* - * cs_types.h 1.18 2000/06/12 21:55:40 + * cs_types.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_CS_TYPES_H diff --git a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h index 261dd5bbbdf2..8d19b9401a5b 100644 --- a/include/pcmcia/mem_op.h +++ b/include/pcmcia/mem_op.h @@ -1,30 +1,15 @@ /* - * mem_op.h 1.13 2000/06/12 21:55:40 + * mem_op.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_MEM_OP_H diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index c8c53fc0ef07..cc679ac74891 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -1,30 +1,15 @@ /* - * ss.h 1.28 2000/06/12 21:55:40 + * ss.h * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * (C) 1999 David A. Hinds */ #ifndef _LINUX_SS_H -- cgit v1.2.3 From b504f217c32be942c0634c415e668d11726ef7e4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:21:40 -0800 Subject: [PATCH] pcmcia: add pcmcia_(put,get)_socket Add pcmcia_{put,get}_socket Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 23 +++++++++++++++++++++++ include/pcmcia/cs.h | 3 +++ 2 files changed, 26 insertions(+) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 192ffc4540cf..c7827c26db94 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -172,6 +172,29 @@ int pcmcia_socket_dev_resume(struct device *dev) EXPORT_SYMBOL(pcmcia_socket_dev_resume); +struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt) +{ + struct class_device *cl_dev = class_device_get(&skt->dev); + if (!cl_dev) + return NULL; + skt = class_get_devdata(cl_dev); + if (!try_module_get(skt->owner)) { + class_device_put(&skt->dev); + return NULL; + } + return (skt); +} +EXPORT_SYMBOL(pcmcia_get_socket); + + +void pcmcia_put_socket(struct pcmcia_socket *skt) +{ + module_put(skt->owner); + class_device_put(&skt->dev); +} +EXPORT_SYMBOL(pcmcia_put_socket); + + static void pcmcia_release_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_get_devdata(class_dev); diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 8bd6081c5f8f..bcc0abee07eb 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -426,6 +426,9 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req); int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask); #endif +struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt); +void pcmcia_put_socket(struct pcmcia_socket *skt); + #endif /* __KERNEL__ */ #endif /* _LINUX_CS_H */ -- cgit v1.2.3 From 00bfce19fba26c176381ddde535e5d85efdeea19 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:22:20 -0800 Subject: [PATCH] pcmcia: add a pointer to client in struct pcmcia_device Add a pointer to the "client" structure to struct pcmcia_device. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 1 + include/pcmcia/ds.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 77adb5f06185..107a48ba4ac8 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -704,6 +704,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) p_dev->socket = s->parent; p_dev->device_no = (s->device_count++); p_dev->func = bind_info->function; + p_dev->client = client; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->parent->dev.dev; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 3f1e4ccbb31f..ba49e8bc7abd 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -128,6 +128,7 @@ typedef struct dev_link_t { struct pcmcia_socket; +struct client_t; extern struct bus_type pcmcia_bus_type; @@ -158,6 +159,7 @@ struct pcmcia_device { /* deprecated, a cleaned up version will be moved into this struct soon */ dev_link_t *instance; + struct client_t *client; struct device dev; }; -- cgit v1.2.3 From d56666b522432b244f38f52f89a3ccf275c4e41d Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:24:11 -0800 Subject: [PATCH] pcmcia: move struct client_t inside struct pcmcia_device Move the struct client_t inside struct pcmcia_device. This means it gets proper reference counting as well. The clients list inside struct pcmcia_socket can be removed now. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/bulkmem.c | 1 + drivers/pcmcia/cs.c | 4 +- drivers/pcmcia/cs_internal.h | 14 +------ drivers/pcmcia/ds.c | 88 +++++++++++++++----------------------------- include/pcmcia/ds.h | 15 +++++++- include/pcmcia/ss.h | 1 - 6 files changed, 46 insertions(+), 77 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 1be40034acd4..8997b5c04a9e 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef DEBUG diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index b93ec422c78a..e875cb399ffb 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef CONFIG_PCI @@ -199,8 +200,6 @@ static void pcmcia_release_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_get_devdata(class_dev); - BUG_ON(socket->clients); - complete(&socket->socket_released); } @@ -369,7 +368,6 @@ static void shutdown_socket(struct pcmcia_socket *s) kfree(s->config); s->config = NULL; } - BUG_ON(s->clients); free_regions(&s->a_region); free_regions(&s->c_region); diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 67f85f56fe9d..6d441e178f63 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -18,19 +18,7 @@ #include #define CLIENT_MAGIC 0x51E6 -typedef struct client_t { - u_short client_magic; - struct pcmcia_socket *Socket; - u_char Function; - dev_info_t dev_info; - u_int Attributes; - u_int state; - event_t EventMask, PendingEvents; - int (*event_handler)(event_t event, int priority, - event_callback_args_t *); - event_callback_args_t event_callback_args; - struct client_t *next; -} client_t; +typedef struct client_t client_t; /* Flags in client state */ #define CLIENT_CONFIG_LOCKED 0x0001 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 059f02471b62..f6609d8f4639 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -356,6 +356,7 @@ static void pcmcia_put_dev(struct pcmcia_device *p_dev) static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + ds_dbg(1, "releasing dev %p\n", p_dev); pcmcia_put_bus_socket(p_dev->socket->pcmcia); kfree(p_dev); } @@ -430,11 +431,11 @@ static int send_event_callback(struct device *dev, void * _data) if (p_dev->socket != data->skt) return 0; - if (p_dev->client->state & (CLIENT_UNBOUND|CLIENT_STALE)) + if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE)) return 0; - if (p_dev->client->EventMask & data->event) - return EVENT(p_dev->client, data->event, data->priority); + if (p_dev->client.EventMask & data->event) + return EVENT(&p_dev->client, data->event, data->priority); return 0; } @@ -559,10 +560,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { struct pcmcia_driver *p_drv; struct pcmcia_device *p_dev, *tmp_dev; - client_t *client; unsigned long flags; int ret = 0; + s = pcmcia_get_bus_socket(s); if (!s) return -EINVAL; @@ -570,25 +571,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) (char *)bind_info->dev_info); p_drv = get_pcmcia_driver(&bind_info->dev_info); - if (!p_drv) - return -EINVAL; - - if (!try_module_get(p_drv->owner)) - return -EINVAL; - - client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL); - if (!client) { - ret = -ENOMEM; + if ((!p_drv) || (!try_module_get(p_drv->owner))) { + ret = -EINVAL; goto err_put; } - memset(client, 0, sizeof(client_t)); - - client->client_magic = CLIENT_MAGIC; - client->Socket = s->parent; - client->Function = bind_info->function; - client->state = CLIENT_UNBOUND; - client->next = s->parent->clients; - strlcpy(client->dev_info, p_drv->drv.name, DEV_NAME_LEN); /* Currently, the userspace pcmcia cardmgr detects pcmcia devices. * Here this information is translated into a kernel @@ -598,21 +584,13 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); if (!p_dev) { ret = -ENOMEM; - goto err_free_client; + goto err_put_module; } memset(p_dev, 0, sizeof(struct pcmcia_device)); - s = pcmcia_get_bus_socket(s); - if (!s) { - ret = -ENODEV; - kfree(p_dev); - goto err_free_client; - } - p_dev->socket = s->parent; p_dev->device_no = (s->device_count++); p_dev->func = bind_info->function; - p_dev->client = client; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->parent->dev.dev; @@ -620,11 +598,17 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->device_no); p_dev->dev.driver = &p_drv->drv; + /* compat */ + p_dev->client.client_magic = CLIENT_MAGIC; + p_dev->client.Socket = s->parent; + p_dev->client.Function = bind_info->function; + p_dev->client.state = CLIENT_UNBOUND; + strlcpy(p_dev->client.dev_info, p_drv->drv.name, DEV_NAME_LEN); + ret = device_register(&p_dev->dev); if (ret) { kfree(p_dev); - pcmcia_put_bus_socket(s); - goto err_free_client; + goto err_put_module; } /* Add to the list in pcmcia_bus_socket, but only if no device @@ -642,15 +626,11 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) list_add_tail(&p_dev->socket_device_list, &s->devices_list); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - /* finally here the parent client is registered */ - s->parent->clients = client; - if (p_drv->attach) { p_dev->instance = p_drv->attach(); - if (!p_dev->instance) { + if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", (char *)bind_info->dev_info); - /* FIXME: client isn't freed here */ ret = -ENODEV; goto err_unregister; } @@ -660,11 +640,14 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) err_unregister: device_unregister(&p_dev->dev); - err_free_client: - kfree(client); - err_put: module_put(p_drv->owner); return (ret); + + err_put_module: + module_put(p_drv->owner); + err_put: + pcmcia_put_bus_socket(s); + return (ret); } /* bind_request */ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) @@ -690,11 +673,11 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) continue; spin_lock_irqsave(&pcmcia_dev_list_lock, flags); list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { - if ((p_dev->client->state & CLIENT_UNBOUND) && - (!strcmp(p_dev->client->dev_info, (char *)req->dev_info))) { + if ((p_dev->client.state & CLIENT_UNBOUND) && + (!strcmp(p_dev->client.dev_info, (char *)req->dev_info))) { p_dev = pcmcia_get_dev(p_dev); if (p_dev) - client = p_dev->client; + client = &p_dev->client; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); goto found; } @@ -753,7 +736,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } up(&s->skt_sem); - pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */ return CS_SUCCESS; out_no_resource: @@ -877,7 +859,7 @@ static int unbind_request(struct pcmcia_bus_socket *s) } p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); list_del(&p_dev->socket_device_list); - p_dev->client->state |= CLIENT_STALE; + p_dev->client.state |= CLIENT_STALE; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); /* detach the "instance" */ @@ -896,10 +878,9 @@ static int unbind_request(struct pcmcia_bus_socket *s) int pcmcia_deregister_client(client_handle_t handle) { - client_t **client; struct pcmcia_socket *s; - u_long flags; int i; + struct pcmcia_device *p_dev = handle_to_pdev(handle); if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; @@ -914,18 +895,9 @@ int pcmcia_deregister_client(client_handle_t handle) goto warn_out; if (handle->state & CLIENT_STALE) { - spin_lock_irqsave(&s->lock, flags); - client = &s->clients; - while ((*client) && ((*client) != handle)) - client = &(*client)->next; - if (*client == NULL) { - spin_unlock_irqrestore(&s->lock, flags); - return CS_BAD_HANDLE; - } - *client = handle->next; handle->client_magic = 0; - kfree(handle); - spin_unlock_irqrestore(&s->lock, flags); + handle->state &= ~CLIENT_STALE; + pcmcia_put_dev(p_dev); } else { handle->state = CLIENT_UNBOUND; handle->event_handler = NULL; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index ba49e8bc7abd..c8223b32742e 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -128,7 +128,6 @@ typedef struct dev_link_t { struct pcmcia_socket; -struct client_t; extern struct bus_type pcmcia_bus_type; @@ -159,7 +158,18 @@ struct pcmcia_device { /* deprecated, a cleaned up version will be moved into this struct soon */ dev_link_t *instance; - struct client_t *client; + struct client_t { + u_short client_magic; + struct pcmcia_socket *Socket; + u_char Function; + dev_info_t dev_info; + u_int Attributes; + u_int state; + event_t EventMask, PendingEvents; + int (*event_handler) (event_t event, int priority, + event_callback_args_t *); + event_callback_args_t event_callback_args; + } client; struct device dev; }; @@ -167,6 +177,7 @@ struct pcmcia_device { #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev) #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) +#define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client); /* error reporting */ void cs_error(client_handle_t handle, int func, int ret); diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index cc679ac74891..fc8080f2b691 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -153,7 +153,6 @@ struct pcmcia_socket { u_int state; u_short functions; u_short lock_count; - client_handle_t clients; pccard_mem_map cis_mem; void __iomem *cis_virt; struct config_t *config; -- cgit v1.2.3 From 301d0dc6bc4b1d148f23da8ac006247a6f7bb719 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:24:39 -0800 Subject: [PATCH] pcmcia: SET_NETDEV for network devices This patch updates pcmcia network drivers so that their class devices are linked to the correct physical device. Based on an patch by Adam Belay, but adapted to a different pcmcia driver model implementation. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/pcmcia/3c574_cs.c | 1 + drivers/net/pcmcia/3c589_cs.c | 1 + drivers/net/pcmcia/axnet_cs.c | 1 + drivers/net/pcmcia/com20020_cs.c | 1 + drivers/net/pcmcia/fmvj18x_cs.c | 1 + drivers/net/pcmcia/ibmtr_cs.c | 1 + drivers/net/pcmcia/nmclan_cs.c | 1 + drivers/net/pcmcia/pcnet_cs.c | 1 + drivers/net/pcmcia/smc91c92_cs.c | 1 + drivers/net/pcmcia/xirc2ps_cs.c | 1 + include/pcmcia/ds.h | 1 + 11 files changed, 11 insertions(+) (limited to 'include') diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 1154fbbc0dc4..f29d4f88e874 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -519,6 +519,7 @@ static void tc574_config(dev_link_t *link) link->state &= ~DEV_CONFIG_PENDING; link->dev = &lp->node; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 2dd8f774dc5a..108d67066d4c 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -391,6 +391,7 @@ static void tc589_config(dev_link_t *link) link->dev = &lp->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 91be6752dd39..a01842d09324 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -458,6 +458,7 @@ static void axnet_config(dev_link_t *link) info->phy_id = (i < 32) ? i : -1; link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 1cf038aa604a..c39124e79b76 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -394,6 +394,7 @@ static void com20020_config(dev_link_t *link) link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = com20020_found(dev, 0); /* calls register_netdev */ diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index d5b1bb63936b..e077d1510a3a 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -591,6 +591,7 @@ static void fmvj18x_config(dev_link_t *link) lp->cardtype = cardtype; link->dev = &lp->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 886398f1d15c..ca1efb928c41 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -366,6 +366,7 @@ static void ibmtr_config(dev_link_t *link) link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = ibmtr_probe_card(dev); if (i != 0) { diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 8e616d4dccd8..7410230d69c8 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -775,6 +775,7 @@ static void nmclan_config(dev_link_t *link) link->dev = &lp->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = register_netdev(dev); if (i != 0) { diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index b9ca8347f9e6..0aa0ec3f3113 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -722,6 +722,7 @@ static void pcnet_config(dev_link_t *link) link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = ei_poll; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 8a381612fef7..99ce9a2bbfcd 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1024,6 +1024,7 @@ static void smc91c92_config(dev_link_t *link) link->dev = &smc->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 0f5a664841b7..cbf072b06d2b 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1121,6 +1121,7 @@ xirc2ps_config(dev_link_t * link) link->dev = &local->node; link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index c8223b32742e..eeb118ceced1 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -178,6 +178,7 @@ struct pcmcia_device { #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) #define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client); +#define handle_to_dev(handle) ((container_of(handle, struct pcmcia_device, client))->dev) /* error reporting */ void cs_error(client_handle_t handle, int func, int ret); -- cgit v1.2.3 From ff274f25ca7dc5decce21db4411d2aa5655fe8e4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:26:22 -0800 Subject: [PATCH] pcmcia: remove obsolete code Remove the code marked as obsolete -- nobody complained. Signed-off-by: Dominik Broodwski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/Kconfig | 12 --------- drivers/pcmcia/bulkmem.c | 46 -------------------------------- drivers/pcmcia/cs.c | 60 ------------------------------------------ drivers/pcmcia/pcmcia_compat.c | 20 -------------- include/pcmcia/cs.h | 7 ----- 5 files changed, 145 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 37b643d24825..22f3c9a0841e 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -39,18 +39,6 @@ config PCMCIA_DEBUG In all the above examples, N is the debugging verbosity level. -config PCMCIA_OBSOLETE - bool "Enable obsolete PCCARD code" - depends on PCCARD != n - help - Say Y here to enable some code found in the PCCARD subsystem - which has no in-kernel usage, but might be needed for certain - external PCMCIA drivers. If you do need to say Y here so that - one such driver compiles and/or works correctly, please report - this to linux-pcmcia lists.infradead.org - - If unsure, say N - config PCMCIA tristate "16-bit PCMCIA support" depends on PCCARD diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 8997b5c04a9e..1ce023699a96 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -152,49 +152,3 @@ int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn) return pccard_match_region(rgn->next, rgn); } /* get_next_region */ - -#ifdef CONFIG_PCMCIA_OBSOLETE - -static int match_region(client_handle_t handle, memory_handle_t list, - region_info_t *match) -{ - while (list != NULL) { - if (!(handle->Attributes & INFO_MTD_CLIENT) || - (strcmp(handle->dev_info, list->dev_info) == 0)) { - *match = list->info; - return CS_SUCCESS; - } - list = list->info.next; - } - return CS_NO_MORE_ITEMS; -} /* match_region */ - -int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn) -{ - struct pcmcia_socket *s = SOCKET(handle); - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - - if ((handle->Attributes & INFO_MASTER_CLIENT) && - (!(s->state & SOCKET_REGION_INFO))) { - setup_regions(s, handle->Function, 0, &s->c_region); - setup_regions(s, handle->Function, 1, &s->a_region); - s->state |= SOCKET_REGION_INFO; - } - - if (rgn->Attributes & REGION_TYPE_AM) - return match_region(handle, s->a_region, rgn); - else - return match_region(handle, s->c_region, rgn); -} /* get_first_region */ -EXPORT_SYMBOL(pcmcia_get_first_region); - -int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn) -{ - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - return match_region(handle, rgn->next, rgn); -} /* get_next_region */ -EXPORT_SYMBOL(pcmcia_get_next_region); - -#endif diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index e875cb399ffb..298bd4689897 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -1147,37 +1147,6 @@ int pcmcia_modify_configuration(client_handle_t handle, return CS_SUCCESS; } /* modify_configuration */ -#ifdef CONFIG_PCMCIA_OBSOLETE - -/*====================================================================== - - Modify the attributes of a window returned by RequestWindow. - -======================================================================*/ - -int pcmcia_modify_window(window_handle_t win, modwin_t *req) -{ - if ((win == NULL) || (win->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - - win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE); - if (req->Attributes & WIN_MEMORY_TYPE) - win->ctl.flags |= MAP_ATTRIB; - if (req->Attributes & WIN_ENABLE) - win->ctl.flags |= MAP_ACTIVE; - if (req->Attributes & WIN_DATA_WIDTH_16) - win->ctl.flags |= MAP_16BIT; - if (req->Attributes & WIN_USE_WAIT) - win->ctl.flags |= MAP_USE_WAIT; - win->ctl.speed = req->AccessSpeed; - win->sock->ops->set_mem_map(win->sock, &win->ctl); - - return CS_SUCCESS; -} /* modify_window */ -EXPORT_SYMBOL(pcmcia_modify_window); - -#endif /* CONFIG_PCMCIA_OBSOLETE */ - /* register pcmcia_callback */ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) { @@ -1863,35 +1832,6 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) return ret; } /* insert_card */ -/*====================================================================== - - Maybe this should send a CS_EVENT_CARD_INSERTION event if we - haven't sent one to this client yet? - -======================================================================*/ - -#ifdef CONFIG_PCMCIA_OBSOLETE -int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask) -{ - u_int events, bit; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - if (handle->Attributes & CONF_EVENT_MASK_VALID) - return CS_BAD_SOCKET; - handle->EventMask = mask->EventMask; - events = handle->PendingEvents & handle->EventMask; - handle->PendingEvents -= events; - while (events != 0) { - bit = ((events ^ (events-1)) + 1) >> 1; - EVENT(handle, bit, CS_EVENT_PRI_LOW); - events -= bit; - } - return CS_SUCCESS; -} /* set_event_mask */ -EXPORT_SYMBOL(pcmcia_set_event_mask); - -#endif /* CONFIG_PCMCIA_OBSOLETE */ - /*====================================================================== OS-specific module glue goes here diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c index 673d34576d3b..68b80084f83f 100644 --- a/drivers/pcmcia/pcmcia_compat.c +++ b/drivers/pcmcia/pcmcia_compat.c @@ -123,23 +123,3 @@ int pcmcia_access_configuration_register(client_handle_t handle, } EXPORT_SYMBOL(pcmcia_access_configuration_register); -#ifdef CONFIG_PCMCIA_OBSOLETE - -int pcmcia_get_first_window(window_handle_t *win, win_req_t *req) -{ - if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - - return pcmcia_get_window(((client_handle_t)*win)->Socket, win, 0, req); -} -EXPORT_SYMBOL(pcmcia_get_first_window); - -int pcmcia_get_next_window(window_handle_t *win, win_req_t *req) -{ - if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - return pcmcia_get_window((*win)->sock, win, (*win)->index+1, req); -} -EXPORT_SYMBOL(pcmcia_get_next_window); - -#endif diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index bcc0abee07eb..dfc7ede3c0fb 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -419,13 +419,6 @@ int pcmcia_eject_card(struct pcmcia_socket *skt); int pcmcia_insert_card(struct pcmcia_socket *skt); int pcmcia_report_error(client_handle_t handle, error_info_t *err); -#ifdef CONFIG_PCMCIA_OBSOLETE -int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req); -int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req); -int pcmcia_modify_window(window_handle_t win, modwin_t *req); -int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask); -#endif - struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt); void pcmcia_put_socket(struct pcmcia_socket *skt); -- cgit v1.2.3 From bbdedd8fb89e19647576019a5f34d9108dd184c1 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:26:35 -0800 Subject: [PATCH] pcmcia: remove pending_events PendingEvents is unused, so remove it Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 2 -- include/pcmcia/ds.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 78857f9f0cac..ee08e945e1fb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -741,8 +741,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { if (client->EventMask & CS_EVENT_CARD_INSERTION) EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); - else - client->PendingEvents |= CS_EVENT_CARD_INSERTION; } up(&s->skt_sem); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index eeb118ceced1..c579df808e5b 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -165,7 +165,7 @@ struct pcmcia_device { dev_info_t dev_info; u_int Attributes; u_int state; - event_t EventMask, PendingEvents; + event_t EventMask; int (*event_handler) (event_t event, int priority, event_callback_args_t *); event_callback_args_t event_callback_args; -- cgit v1.2.3 From b1b3650d7652a786bfe85f53c09378d06ad2a13f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:26:51 -0800 Subject: [PATCH] pcmcia: remove client_attributes Remove the "Attributes" entry of struct client_t -- _all_ in-kernel drivers did set it to INFO_IO_CLIENT | INFO_CARD_SHARE anyway, and the pcmcia core didn't care at all what this value was set to. Also, remove the setting of the respective request field in all in-kernel drivers -- the request structure is kept the same, though, to keep external drivers compiling. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/bluetooth/bluecard_cs.c | 1 - drivers/bluetooth/bt3c_cs.c | 1 - drivers/bluetooth/btuart_cs.c | 1 - drivers/bluetooth/dtl1_cs.c | 1 - drivers/char/pcmcia/synclink_cs.c | 1 - drivers/ide/legacy/ide-cs.c | 1 - drivers/isdn/hardware/avm/avm_cs.c | 1 - drivers/isdn/hisax/avma1_cs.c | 1 - drivers/isdn/hisax/elsa_cs.c | 1 - drivers/isdn/hisax/sedlbauer_cs.c | 1 - drivers/isdn/hisax/teles_cs.c | 1 - drivers/mtd/maps/pcmciamtd.c | 1 - drivers/net/pcmcia/3c574_cs.c | 1 - drivers/net/pcmcia/3c589_cs.c | 1 - drivers/net/pcmcia/axnet_cs.c | 1 - drivers/net/pcmcia/com20020_cs.c | 1 - drivers/net/pcmcia/fmvj18x_cs.c | 1 - drivers/net/pcmcia/ibmtr_cs.c | 1 - drivers/net/pcmcia/nmclan_cs.c | 1 - drivers/net/pcmcia/pcnet_cs.c | 1 - drivers/net/pcmcia/smc91c92_cs.c | 1 - drivers/net/pcmcia/xirc2ps_cs.c | 1 - drivers/net/wireless/airo_cs.c | 1 - drivers/net/wireless/atmel_cs.c | 1 - drivers/net/wireless/netwave_cs.c | 1 - drivers/net/wireless/orinoco_cs.c | 1 - drivers/net/wireless/ray_cs.c | 1 - drivers/net/wireless/wavelan_cs.c | 1 - drivers/net/wireless/wl3501_cs.c | 1 - drivers/parport/parport_cs.c | 1 - drivers/pcmcia/ds.c | 1 - drivers/scsi/pcmcia/aha152x_stub.c | 1 - drivers/scsi/pcmcia/fdomain_stub.c | 1 - drivers/scsi/pcmcia/nsp_cs.c | 1 - drivers/scsi/pcmcia/qlogic_stub.c | 1 - drivers/scsi/pcmcia/sym53c500_cs.c | 1 - drivers/serial/serial_cs.c | 1 - drivers/telephony/ixj_pcmcia.c | 1 - include/pcmcia/cs.h | 4 ++-- include/pcmcia/ds.h | 1 - sound/pcmcia/pdaudiocf/pdaudiocf.c | 1 - sound/pcmcia/vx/vx_entry.c | 1 - 42 files changed, 2 insertions(+), 43 deletions(-) (limited to 'include') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 9a75536afb8d..325ab5d76786 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -904,7 +904,6 @@ static dev_link_t *bluecard_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 227e3e5a9d36..84977a0605e5 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -709,7 +709,6 @@ static dev_link_t *bt3c_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 4ba1dfa62911..38dbac8db507 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -628,7 +628,6 @@ static dev_link_t *btuart_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 2ea43e748695..9fcc8e4d2159 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -607,7 +607,6 @@ static dev_link_t *dtl1_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d732bdcbfc45..c6accb1ab6ac 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -608,7 +608,6 @@ static dev_link_t *mgslpc_attach(void) dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 0e0047ef5760..b114113b0acb 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -144,7 +144,6 @@ static dev_link_t *ide_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index d1d615fc9e12..fbbfb9cfbc4e 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -178,7 +178,6 @@ static dev_link_t *avmcs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index b30a1e330f77..784df60d1a1f 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -193,7 +193,6 @@ static dev_link_t *avma1cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 14f0f0fe246d..92349814990f 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -227,7 +227,6 @@ static dev_link_t *elsa_cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 3802923e8b27..ab4f78a33def 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -240,7 +240,6 @@ static dev_link_t *sedlbauer_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 0f789f3b8df5..c17c25fd4713 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -208,7 +208,6 @@ static dev_link_t *teles_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 9c17b52fe5a7..e37b4c1976e5 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -800,7 +800,6 @@ static dev_link_t *pcmciamtd_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index f29d4f88e874..3e05fd774128 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -322,7 +322,6 @@ static dev_link_t *tc574_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 108d67066d4c..00c82eafb21b 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -236,7 +236,6 @@ static dev_link_t *tc589_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index a01842d09324..c61fba0ea898 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -191,7 +191,6 @@ static dev_link_t *axnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index c39124e79b76..211fdac0a6eb 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -211,7 +211,6 @@ static dev_link_t *com20020_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index e077d1510a3a..850f1d94c5d6 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -299,7 +299,6 @@ static dev_link_t *fmvj18x_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index ca1efb928c41..c3ca9fb65912 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -204,7 +204,6 @@ static dev_link_t *ibmtr_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 7410230d69c8..35e66f0f9e42 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -512,7 +512,6 @@ static dev_link_t *nmclan_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 0aa0ec3f3113..ddaf72136c2d 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -286,7 +286,6 @@ static dev_link_t *pcnet_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 99ce9a2bbfcd..78f84e1f9fc8 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -374,7 +374,6 @@ static dev_link_t *smc91c92_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index cbf072b06d2b..aadbb787982c 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -627,7 +627,6 @@ xirc2ps_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index cee7eab30b22..16a973141091 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -225,7 +225,6 @@ static dev_link_t *airo_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 5ceec62a57af..3fe780d128d9 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -237,7 +237,6 @@ static dev_link_t *atmel_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index d19e7981863d..e2685634c2d5 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -503,7 +503,6 @@ static dev_link_t *netwave_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index ba2f3b50a65d..2c8618098602 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -197,7 +197,6 @@ orinoco_cs_attach(void) dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index c7c5c22c7ae2..e220781b03ae 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -398,7 +398,6 @@ static dev_link_t *ray_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 1509c5dadd50..a2b95854f4fc 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4689,7 +4689,6 @@ wavelan_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_REGISTRATION_COMPLETE | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 5d4f4c32efb9..b0186c8398be 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -2015,7 +2015,6 @@ static dev_link_t *wl3501_attach(void) link->next = wl3501_dev_list; wl3501_dev_list = link; client_reg.dev_info = &wl3501_dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index f828b97ce9e7..d497877ef11c 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -143,7 +143,6 @@ static dev_link_t *parport_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index ee08e945e1fb..8ab0615c786b 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -709,7 +709,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = s; - client->Attributes = req->Attributes; client->EventMask = req->EventMask; client->event_handler = req->event_handler; client->event_callback_args = req->event_callback_args; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index b82c0df05b9f..97d69da43825 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -145,7 +145,6 @@ static dev_link_t *aha152x_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &aha152x_event; client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 67d98b20650f..343b67578706 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -131,7 +131,6 @@ static dev_link_t *fdomain_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &fdomain_event; client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index b6d615a6b447..8aae1ae9fa9b 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1672,7 +1672,6 @@ static dev_link_t *nsp_cs_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 23ac561c849b..4b66969ace4a 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -212,7 +212,6 @@ static dev_link_t *qlogic_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &qlogic_event; client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; client_reg.Version = 0x0210; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 84d06345614e..be3d3369cae6 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -995,7 +995,6 @@ SYM53C500_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &SYM53C500_event; client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 6b592a0d2fac..59dd5560fa1f 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -237,7 +237,6 @@ static dev_link_t *serial_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 789c17c65b03..e1ef0d7ee8d1 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -69,7 +69,6 @@ static dev_link_t *ixj_attach(void) link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index dfc7ede3c0fb..311682a7fef0 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -124,7 +124,7 @@ typedef struct client_req_t { /* For RegisterClient */ typedef struct client_reg_t { dev_info_t *dev_info; - u_int Attributes; + u_int Attributes; /* UNUSED */ u_int EventMask; int (*event_handler)(event_t event, int priority, event_callback_args_t *); @@ -279,7 +279,7 @@ typedef struct win_req_t { #define WIN_BAR_MASK 0xe000 #define WIN_BAR_SHIFT 13 -/* Attributes for RegisterClient */ +/* Attributes for RegisterClient -- UNUSED -- */ #define INFO_MASTER_CLIENT 0x01 #define INFO_IO_CLIENT 0x02 #define INFO_MTD_CLIENT 0x04 diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index c579df808e5b..e46ae96e867b 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -163,7 +163,6 @@ struct pcmcia_device { struct pcmcia_socket *Socket; u_char Function; dev_info_t dev_info; - u_int Attributes; u_int state; event_t EventMask; int (*event_handler) (event_t event, int priority, diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 1276b3652601..299bbf228358 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -183,7 +183,6 @@ static dev_link_t *snd_pdacf_attach(void) /* Register with Card Services */ client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL #ifdef CONFIG_PM diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c index ad2917e4e69f..8f59818fef8a 100644 --- a/sound/pcmcia/vx/vx_entry.c +++ b/sound/pcmcia/vx/vx_entry.c @@ -175,7 +175,6 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw) /* Register with Card Services */ memset(&client_reg, 0, sizeof(client_reg)); client_reg.dev_info = hw->dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL #ifdef CONFIG_PM -- cgit v1.2.3 From cfe963fa06f43cb8d97a230c9a3ecd632766d992 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:27:18 -0800 Subject: [PATCH] pcmcia: remove dev_info from client Remove the dev_info - contained name from struct client_t Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 3 ++- drivers/pcmcia/ds.c | 27 ++++++++++++++++++--------- include/pcmcia/ds.h | 1 - 3 files changed, 20 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 30b2980f0176..4f8cf5cdd904 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -1530,6 +1530,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) struct pcmcia_socket *s; config_t *c; int ret = CS_IN_USE, irq = 0; + struct pcmcia_device *p_dev = handle_to_pdev(handle); if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; @@ -1579,7 +1580,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || (s->functions > 1) || (irq == s->pci_irq)) ? SA_SHIRQ : 0, - handle->dev_info, req->Instance)) + p_dev->dev.bus_id, req->Instance)) return CS_IN_USE; } diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 8ab0615c786b..db18d56c825f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -221,8 +221,10 @@ int pcmcia_report_error(client_handle_t handle, error_info_t *err) if (CHECK_HANDLE(handle)) printk(KERN_NOTICE); - else - printk(KERN_NOTICE "%s: ", handle->dev_info); + else { + struct pcmcia_device *p_dev = handle_to_pdev(handle); + printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id); + } for (i = 0; i < ARRAY_SIZE(service_table); i++) if (service_table[i].key == err->func) @@ -608,7 +610,6 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) p_dev->client.Socket = s->parent; p_dev->client.Function = bind_info->function; p_dev->client.state = CLIENT_UNBOUND; - strlcpy(p_dev->client.dev_info, p_drv->drv.name, DEV_NAME_LEN); ret = device_register(&p_dev->dev); if (ret) { @@ -683,14 +684,22 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) continue; spin_lock_irqsave(&pcmcia_dev_list_lock, flags); list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { - if ((p_dev->client.state & CLIENT_UNBOUND) && - (!strcmp(p_dev->client.dev_info, (char *)req->dev_info))) { - p_dev = pcmcia_get_dev(p_dev); - if (p_dev) - client = &p_dev->client; + struct pcmcia_driver *p_drv; + p_dev = pcmcia_get_dev(p_dev); + if (!p_dev) + continue; + if ((!p_dev->client.state & CLIENT_UNBOUND) || + (!p_dev->dev.driver)) { + pcmcia_put_dev(p_dev); + continue; + } + p_drv = to_pcmcia_drv(p_dev->dev.driver); + if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) { + client = &p_dev->client; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); goto found; } + pcmcia_put_dev(p_dev); } spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); pcmcia_put_bus_socket(skt); @@ -733,7 +742,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } ds_dbg(1, "register_client(): client 0x%p, dev %s\n", - client, client->dev_info); + client, p_dev->dev.bus_id); if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index e46ae96e867b..1a7a03d8623a 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -162,7 +162,6 @@ struct pcmcia_device { u_short client_magic; struct pcmcia_socket *Socket; u_char Function; - dev_info_t dev_info; u_int state; event_t EventMask; int (*event_handler) (event_t event, int priority, -- cgit v1.2.3 From dd9b77563baf01b205b2016dc1caf473b9222831 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:27:45 -0800 Subject: [PATCH] pcmcia: per-socket resource database Make the io and mem db per-socket, as different sockets may have different requirements or may not even need the resource db at all (SS_CAP_STATIC_MAP). Updated to make rsrc_mem_probe per-socket and to remove unnecessary and even broken check for empty list as per Russell King's suggestions. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 6 ++- drivers/pcmcia/cs_internal.h | 2 +- drivers/pcmcia/rsrc_mgr.c | 99 +++++++++++++++++++++----------------------- include/pcmcia/ss.h | 10 +++++ 4 files changed, 63 insertions(+), 54 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 4f8cf5cdd904..9c21a58f835e 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -250,6 +250,10 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) socket->cis_mem.flags = 0; socket->cis_mem.speed = cis_speed; + /* init resource database */ + socket->mem_db.next = &socket->mem_db; + socket->io_db.next = &socket->io_db; + INIT_LIST_HEAD(&socket->cis_cache); spin_lock_init(&socket->lock); @@ -305,6 +309,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) up_write(&pcmcia_socket_list_rwsem); /* wait for sysfs to drop all references */ + release_resource_db(socket); wait_for_completion(&socket->socket_released); } /* pcmcia_unregister_socket */ EXPORT_SYMBOL(pcmcia_unregister_socket); @@ -1879,7 +1884,6 @@ static int __init init_pcmcia_cs(void) static void __exit exit_pcmcia_cs(void) { printk(KERN_INFO "unloading Kernel Card Services\n"); - release_resource_db(); class_interface_unregister(&pccard_sysfs_interface); class_unregister(&pcmcia_socket_class); } diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index e53886be55fe..f64ca5663f3c 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -143,7 +143,7 @@ struct resource *find_mem_region(u_long base, u_long num, u_long align, int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); -void release_resource_db(void); +void release_resource_db(struct pcmcia_socket *s); /* In socket_sysfs.c */ extern struct class_interface pccard_sysfs_interface; diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index a487cafb1903..d2aa1aabe219 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -53,23 +53,10 @@ INT_MODULE_PARM(mem_limit, 0x10000); ======================================================================*/ -typedef struct resource_map_t { - u_long base, num; - struct resource_map_t *next; -} resource_map_t; - -/* Memory resource database */ -static resource_map_t mem_db = { - .next = &mem_db, -}; - -/* IO port resource database */ -static resource_map_t io_db = { - .next = &io_db, -}; +typedef struct resource_map_t resource_map_t; static DECLARE_MUTEX(rsrc_sem); -static unsigned int rsrc_mem_probe; + #define MEM_PROBE_LOW (1 << 0) #define MEM_PROBE_HIGH (1 << 1) @@ -208,7 +195,7 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num) ======================================================================*/ #ifdef CONFIG_PCMCIA_PROBE -static void do_io_probe(ioaddr_t base, ioaddr_t num) +static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num) { struct resource *res; ioaddr_t i, j, bad, any; @@ -253,7 +240,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) bad = any = i; } else { if (bad) { - sub_interval(&io_db, bad, i-bad); + sub_interval(&s->io_db, bad, i-bad); printk(" %#04x-%#04x", bad, i-1); bad = 0; } @@ -264,7 +251,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) printk(" nothing: probe failed.\n"); return; } else { - sub_interval(&io_db, bad, i-bad); + sub_interval(&s->io_db, bad, i-bad); printk(" %#04x-%#04x", bad, i-1); } } @@ -409,7 +396,7 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) if (i != j) { if (!bad) printk(" excluding"); printk(" %#05lx-%#05lx", i, j-1); - sub_interval(&mem_db, i, j-i); + sub_interval(&s->mem_db, i, j-i); bad += j-i; } } @@ -422,12 +409,12 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) { u_long ok; - if (m == &mem_db) + if (m == &s->mem_db) return 0; ok = inv_probe(m->next, s); if (ok) { if (m->base >= 0x100000) - sub_interval(&mem_db, m->base, m->num); + sub_interval(&s->mem_db, m->base, m->num); return ok; } if (m->base < 0x100000) @@ -443,14 +430,14 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) /* We do up to four passes through the list */ if (probe_mask & MEM_PROBE_HIGH) { - if (inv_probe(mem_db.next, s) > 0) + if (inv_probe(s->mem_db.next, s) > 0) return; printk(KERN_NOTICE "cs: warning: no high memory space " "available!\n"); } if ((probe_mask & MEM_PROBE_LOW) == 0) return; - for (m = mem_db.next; m != &mem_db; m = mm.next) { + for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) { mm = *m; /* Only probe < 1 MB */ if (mm.base >= 0x100000) continue; @@ -463,7 +450,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) b = order[i] << 12; if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { if (ok >= mem_limit) - sub_interval(&mem_db, b, 0x10000); + sub_interval(&s->mem_db, b, 0x10000); else ok += do_mem_probe(b, 0x10000, s); } @@ -477,7 +464,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) { resource_map_t *m, mm; - for (m = mem_db.next; m != &mem_db; m = mm.next) { + for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) { mm = *m; if (do_mem_probe(mm.base, mm.num, s)) break; @@ -501,8 +488,8 @@ void pcmcia_validate_mem(struct pcmcia_socket *s) if (s->features & SS_CAP_PAGE_REGS) probe_mask = MEM_PROBE_HIGH; - if (probe_mask & ~rsrc_mem_probe) { - rsrc_mem_probe |= probe_mask; + if (probe_mask & ~s->rsrc_mem_probe) { + s->rsrc_mem_probe |= probe_mask; down(&s->skt_sem); @@ -591,7 +578,7 @@ int adjust_io_region(struct resource *res, unsigned long r_start, int ret = -ENOMEM; down(&rsrc_sem); - for (m = io_db.next; m != &io_db; m = m->next) { + for (m = s->io_db.next; m != &s->io_db; m = m->next) { unsigned long start = m->base; unsigned long end = m->base + m->num - 1; @@ -632,7 +619,7 @@ struct resource *find_io_region(unsigned long base, int num, data.mask = align - 1; data.offset = base & data.mask; - data.map = &io_db; + data.map = &s->io_db; down(&rsrc_sem); #ifdef CONFIG_PCI @@ -664,7 +651,7 @@ struct resource *find_mem_region(u_long base, u_long num, u_long align, data.mask = align - 1; data.offset = base & data.mask; - data.map = &mem_db; + data.map = &s->mem_db; for (i = 0; i < 2; i++) { if (low) { @@ -830,7 +817,7 @@ void undo_irq(u_int Attributes, int irq) ======================================================================*/ -static int adjust_memory(adjust_t *adj) +static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) { u_long base, num; int ret; @@ -845,10 +832,10 @@ static int adjust_memory(adjust_t *adj) down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - ret = add_interval(&mem_db, base, num); + ret = add_interval(&s->mem_db, base, num); break; case REMOVE_MANAGED_RESOURCE: - ret = sub_interval(&mem_db, base, num); + ret = sub_interval(&s->mem_db, base, num); if (ret == CS_SUCCESS) { struct pcmcia_socket *socket; down_read(&pcmcia_socket_list_rwsem); @@ -867,7 +854,7 @@ static int adjust_memory(adjust_t *adj) /*====================================================================*/ -static int adjust_io(adjust_t *adj) +static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) { int base, num, ret = CS_SUCCESS; @@ -881,17 +868,17 @@ static int adjust_io(adjust_t *adj) down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&io_db, base, num) != 0) { + if (add_interval(&s->io_db, base, num) != 0) { ret = CS_IN_USE; break; } #ifdef CONFIG_PCMCIA_PROBE if (probe_io) - do_io_probe(base, num); + do_io_probe(s, base, num); #endif break; case REMOVE_MANAGED_RESOURCE: - sub_interval(&io_db, base, num); + sub_interval(&s->io_db, base, num); break; default: ret = CS_UNSUPPORTED_FUNCTION; @@ -956,32 +943,40 @@ static int adjust_irq(adjust_t *adj) int pcmcia_adjust_resource_info(adjust_t *adj) { - switch (adj->Resource) { - case RES_MEMORY_RANGE: - return adjust_memory(adj); - break; - case RES_IO_RANGE: - return adjust_io(adj); - break; - case RES_IRQ: - return adjust_irq(adj); - break; - } - return CS_UNSUPPORTED_FUNCTION; + struct pcmcia_socket *s; + int ret = CS_UNSUPPORTED_FUNCTION; + + if (adj->Resource == RES_IRQ) + return adjust_irq(adj); + + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(s, &pcmcia_socket_list, socket_list) { + switch (adj->Resource) { + case RES_MEMORY_RANGE: + ret = adjust_memory(s, adj); + break; + case RES_IO_RANGE: + ret = adjust_io(s, adj); + break; + } + } + up_read(&pcmcia_socket_list_rwsem); + + return (ret); } EXPORT_SYMBOL(pcmcia_adjust_resource_info); /*====================================================================*/ -void release_resource_db(void) +void release_resource_db(struct pcmcia_socket *s) { resource_map_t *p, *q; - for (p = mem_db.next; p != &mem_db; p = q) { + for (p = s->mem_db.next; p != &s->mem_db; p = q) { q = p->next; kfree(p); } - for (p = io_db.next; p != &io_db; p = q) { + for (p = s->io_db.next; p != &s->io_db; p = q) { q = p->next; kfree(p); } diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index fc8080f2b691..fe5bdada22f7 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -146,6 +146,12 @@ struct config_t; struct region_t; struct pcmcia_callback; +/* for io_db and mem_db */ +struct resource_map_t { + u_long base, num; + struct resource_map_t *next; +}; + struct pcmcia_socket { struct module *owner; spinlock_t lock; @@ -170,6 +176,10 @@ struct pcmcia_socket { struct list_head socket_list; struct completion socket_released; + struct resource_map_t mem_db; + struct resource_map_t io_db; + unsigned int rsrc_mem_probe; + /* deprecated */ unsigned int sock; /* socket number */ -- cgit v1.2.3 From 23d2f5dbc2b457b2f7f486f343ee8feece9eba8a Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:27:58 -0800 Subject: [PATCH] pcmcia: validate_mem only for non-statically mapped sockets validate_mem() does only make sense for !SS_CAP_STATIC_MAP sockets. Therefore, re-direct validate_mem() calls only for those. The newly added redirection layer will allow for a "library" module named "rsrc_nonstatic" which contains the resource database handling code, and it will only need to be loaded for the drivers which need it. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 6 +++++- drivers/pcmcia/cs_internal.h | 2 ++ drivers/pcmcia/rsrc_mgr.c | 17 ++++++++++++++++- include/pcmcia/ss.h | 5 +++++ 4 files changed, 28 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 9c21a58f835e..590b2a561890 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -250,7 +250,11 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) socket->cis_mem.flags = 0; socket->cis_mem.speed = cis_speed; - /* init resource database */ + /* init resource handling */ + if (socket->features & SS_CAP_STATIC_MAP) + socket->resource_ops = &pccard_static_ops; + else + socket->resource_ops = &pccard_nonstatic_ops; socket->mem_db.next = &socket->mem_db; socket->io_db.next = &socket->io_db; diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index f64ca5663f3c..764e71bcecab 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -144,6 +144,8 @@ int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); void release_resource_db(struct pcmcia_socket *s); +extern struct pccard_resource_ops pccard_static_ops; +extern struct pccard_resource_ops pccard_nonstatic_ops; /* In socket_sysfs.c */ extern struct class_interface pccard_sysfs_interface; diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index d2aa1aabe219..1bc69b669477 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -473,11 +473,12 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) #endif /* CONFIG_PCMCIA_PROBE */ + /* * Locking note: this is the only place where we take * both rsrc_sem and skt_sem. */ -void pcmcia_validate_mem(struct pcmcia_socket *s) +static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) { if (probe_mem) { unsigned int probe_mask; @@ -503,6 +504,11 @@ void pcmcia_validate_mem(struct pcmcia_socket *s) } } +void pcmcia_validate_mem(struct pcmcia_socket *s) +{ + if (s->resource_ops->validate_mem) + s->resource_ops->validate_mem(s); +} EXPORT_SYMBOL(pcmcia_validate_mem); struct pcmcia_align_data { @@ -981,3 +987,12 @@ void release_resource_db(struct pcmcia_socket *s) kfree(p); } } + + +struct pccard_resource_ops pccard_static_ops = { + .validate_mem = NULL, +}; + +struct pccard_resource_ops pccard_nonstatic_ops = { + .validate_mem = pcmcia_nonstatic_validate_mem, +}; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index fe5bdada22f7..d872a714fa28 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -115,6 +115,10 @@ struct pccard_operations { int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem); }; +struct pccard_resource_ops { + void (*validate_mem) (struct pcmcia_socket *s); +}; + /* * Calls to set up low-level "Socket Services" drivers */ @@ -194,6 +198,7 @@ struct pcmcia_socket { /* socket operations */ struct pccard_operations * ops; + struct pccard_resource_ops * resource_ops; /* Zoom video behaviour is so chip specific its not worth adding this to _ops */ -- cgit v1.2.3 From aa4cb19247959d6c3ee9f0274f1d299155791aae Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:28:10 -0800 Subject: [PATCH] pcmcia: adjust_io_region only for non-statically mapped sockets Calls to adjust_io_region only happen if !SS_CAP_STATIC_MAP. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_mgr.c | 14 ++++++++++++-- include/pcmcia/ss.h | 6 +++++- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 1bc69b669477..a97c971ad805 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -577,8 +577,8 @@ pcmcia_align(void *align_data, struct resource *res, * Adjust an existing IO region allocation, but making sure that we don't * encroach outside the resources which the user supplied. */ -int adjust_io_region(struct resource *res, unsigned long r_start, - unsigned long r_end, struct pcmcia_socket *s) +static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start, + unsigned long r_end, struct pcmcia_socket *s) { resource_map_t *m; int ret = -ENOMEM; @@ -599,6 +599,14 @@ int adjust_io_region(struct resource *res, unsigned long r_start, return ret; } +int adjust_io_region(struct resource *res, unsigned long r_start, + unsigned long r_end, struct pcmcia_socket *s) +{ + if (s->resource_ops->adjust_io_region) + return s->resource_ops->adjust_io_region(res, r_start, r_end, s); + return -ENOMEM; +} + /*====================================================================== These find ranges of I/O ports or memory addresses that are not @@ -991,8 +999,10 @@ void release_resource_db(struct pcmcia_socket *s) struct pccard_resource_ops pccard_static_ops = { .validate_mem = NULL, + .adjust_io_region = NULL, }; struct pccard_resource_ops pccard_nonstatic_ops = { .validate_mem = pcmcia_nonstatic_validate_mem, + .adjust_io_region = nonstatic_adjust_io_region, }; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index d872a714fa28..63eba592e00c 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -116,7 +116,11 @@ struct pccard_operations { }; struct pccard_resource_ops { - void (*validate_mem) (struct pcmcia_socket *s); + void (*validate_mem) (struct pcmcia_socket *s); + int (*adjust_io_region) (struct resource *res, + unsigned long r_start, + unsigned long r_end, + struct pcmcia_socket *s); }; /* -- cgit v1.2.3 From 1b71fababfefb7b4477826789eaaad961e423b06 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:28:24 -0800 Subject: [PATCH] pcmcia: find_io_region only for non-statically mapped sockets Calls to find_io_region only happen if !SS_CAP_STATIC_MAP. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_mgr.c | 43 +++++++++++++++++++++++++++---------------- include/pcmcia/ss.h | 3 +++ 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index a97c971ad805..de488824dbe6 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -504,13 +504,6 @@ static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) } } -void pcmcia_validate_mem(struct pcmcia_socket *s) -{ - if (s->resource_ops->validate_mem) - s->resource_ops->validate_mem(s); -} -EXPORT_SYMBOL(pcmcia_validate_mem); - struct pcmcia_align_data { unsigned long mask; unsigned long offset; @@ -599,14 +592,6 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star return ret; } -int adjust_io_region(struct resource *res, unsigned long r_start, - unsigned long r_end, struct pcmcia_socket *s) -{ - if (s->resource_ops->adjust_io_region) - return s->resource_ops->adjust_io_region(res, r_start, r_end, s); - return -ENOMEM; -} - /*====================================================================== These find ranges of I/O ports or memory addresses that are not @@ -620,7 +605,7 @@ int adjust_io_region(struct resource *res, unsigned long r_start, ======================================================================*/ -struct resource *find_io_region(unsigned long base, int num, +struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); @@ -997,12 +982,38 @@ void release_resource_db(struct pcmcia_socket *s) } +void pcmcia_validate_mem(struct pcmcia_socket *s) +{ + if (s->resource_ops->validate_mem) + s->resource_ops->validate_mem(s); +} +EXPORT_SYMBOL(pcmcia_validate_mem); + +int adjust_io_region(struct resource *res, unsigned long r_start, + unsigned long r_end, struct pcmcia_socket *s) +{ + if (s->resource_ops->adjust_io_region) + return s->resource_ops->adjust_io_region(res, r_start, r_end, s); + return -ENOMEM; +} + +struct resource *find_io_region(unsigned long base, int num, + unsigned long align, struct pcmcia_socket *s) +{ + if (s->resource_ops->find_io) + return s->resource_ops->find_io(base, num, align, s); + return NULL; +} + + struct pccard_resource_ops pccard_static_ops = { .validate_mem = NULL, .adjust_io_region = NULL, + .find_io = NULL, }; struct pccard_resource_ops pccard_nonstatic_ops = { .validate_mem = pcmcia_nonstatic_validate_mem, .adjust_io_region = nonstatic_adjust_io_region, + .find_io = nonstatic_find_io_region, }; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 63eba592e00c..02fd88e83e32 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -121,6 +121,9 @@ struct pccard_resource_ops { unsigned long r_start, unsigned long r_end, struct pcmcia_socket *s); + struct resource* (*find_io) (unsigned long base, int num, + unsigned long align, + struct pcmcia_socket *s); }; /* -- cgit v1.2.3 From 1b55e603e08a16ed866a91433fc1b44eb9a1e16d Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:28:37 -0800 Subject: [PATCH] pcmcia: find_mem_region only for non-statically mapped sockets Calls to adjust_mem_region only happen if !SS_CAP_STATIC_MAP. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_mgr.c | 12 +++++++++++- include/pcmcia/ss.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index de488824dbe6..ea52d03e9f4b 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -638,7 +638,7 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num, return res; } -struct resource *find_mem_region(u_long base, u_long num, u_long align, +struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); @@ -1005,15 +1005,25 @@ struct resource *find_io_region(unsigned long base, int num, return NULL; } +struct resource *find_mem_region(u_long base, u_long num, u_long align, + int low, struct pcmcia_socket *s) +{ + if (s->resource_ops->find_mem) + return s->resource_ops->find_mem(base, num, align, low, s); + return NULL; +} + struct pccard_resource_ops pccard_static_ops = { .validate_mem = NULL, .adjust_io_region = NULL, .find_io = NULL, + .find_mem = NULL, }; struct pccard_resource_ops pccard_nonstatic_ops = { .validate_mem = pcmcia_nonstatic_validate_mem, .adjust_io_region = nonstatic_adjust_io_region, .find_io = nonstatic_find_io_region, + .find_mem = nonstatic_find_mem_region, }; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 02fd88e83e32..bd22d0c69975 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -124,6 +124,9 @@ struct pccard_resource_ops { struct resource* (*find_io) (unsigned long base, int num, unsigned long align, struct pcmcia_socket *s); + struct resource* (*find_mem) (unsigned long base, unsigned long num, + unsigned long align, int low, + struct pcmcia_socket *s); }; /* -- cgit v1.2.3 From 83b52fe651c487d60a3e7e55770bbde73a16a10c Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:28:50 -0800 Subject: [PATCH] pcmcia: adjust_ and release_resources only for non-statically mapped sockets re-direct calls to adjust_resource_info for MEM and IO. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_mgr.c | 34 +++++++++++++++++++++++++--------- include/pcmcia/ss.h | 3 +++ 2 files changed, 28 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index ea52d03e9f4b..ff67766d0a07 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -940,6 +940,17 @@ static int adjust_irq(adjust_t *adj) /*====================================================================*/ +static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj) +{ + switch (adj->Resource) { + case RES_MEMORY_RANGE: + return adjust_memory(s, adj); + case RES_IO_RANGE: + return adjust_io(s, adj); + } + return CS_UNSUPPORTED_FUNCTION; +} + int pcmcia_adjust_resource_info(adjust_t *adj) { struct pcmcia_socket *s; @@ -950,14 +961,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj) down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(s, &pcmcia_socket_list, socket_list) { - switch (adj->Resource) { - case RES_MEMORY_RANGE: - ret = adjust_memory(s, adj); - break; - case RES_IO_RANGE: - ret = adjust_io(s, adj); - break; - } + if (s->resource_ops->adjust_resource) + ret = s->resource_ops->adjust_resource(s, adj); } up_read(&pcmcia_socket_list_rwsem); @@ -967,7 +972,7 @@ EXPORT_SYMBOL(pcmcia_adjust_resource_info); /*====================================================================*/ -void release_resource_db(struct pcmcia_socket *s) +static void nonstatic_release_resource_db(struct pcmcia_socket *s) { resource_map_t *p, *q; @@ -982,6 +987,7 @@ void release_resource_db(struct pcmcia_socket *s) } + void pcmcia_validate_mem(struct pcmcia_socket *s) { if (s->resource_ops->validate_mem) @@ -1013,12 +1019,20 @@ struct resource *find_mem_region(u_long base, u_long num, u_long align, return NULL; } +void release_resource_db(struct pcmcia_socket *s) +{ + if (s->resource_ops->exit) + s->resource_ops->exit(s); +} + struct pccard_resource_ops pccard_static_ops = { .validate_mem = NULL, .adjust_io_region = NULL, .find_io = NULL, .find_mem = NULL, + .adjust_resource = NULL, + .exit = NULL, }; struct pccard_resource_ops pccard_nonstatic_ops = { @@ -1026,4 +1040,6 @@ struct pccard_resource_ops pccard_nonstatic_ops = { .adjust_io_region = nonstatic_adjust_io_region, .find_io = nonstatic_find_io_region, .find_mem = nonstatic_find_mem_region, + .adjust_resource = nonstatic_adjust_resource_info, + .exit = nonstatic_release_resource_db, }; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index bd22d0c69975..3b4b3cfea12d 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -127,6 +127,9 @@ struct pccard_resource_ops { struct resource* (*find_mem) (unsigned long base, unsigned long num, unsigned long align, int low, struct pcmcia_socket *s); + int (*adjust_resource) (struct pcmcia_socket *s, + adjust_t *adj); + void (*exit) (struct pcmcia_socket *s); }; /* -- cgit v1.2.3 From 6238b318f00f14924f07e1d5aa18d067d80f9fbd Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:29:18 -0800 Subject: [PATCH] pcmcia: make rsrc_nonstatic an independend module Make rsrc_nonstatic an independent module. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/Kconfig | 9 +++++++++ drivers/pcmcia/Makefile | 4 +++- drivers/pcmcia/cistpl.c | 2 ++ drivers/pcmcia/cs.c | 8 ++------ drivers/pcmcia/cs_internal.h | 2 -- drivers/pcmcia/hd64465_ss.c | 1 + drivers/pcmcia/i82092.c | 1 + drivers/pcmcia/i82365.c | 1 + drivers/pcmcia/m32r_cfc.c | 1 + drivers/pcmcia/m32r_pcc.c | 1 + drivers/pcmcia/pd6729.c | 1 + drivers/pcmcia/rsrc_mgr.c | 1 + drivers/pcmcia/rsrc_nonstatic.c | 4 ++++ drivers/pcmcia/soc_common.c | 1 + drivers/pcmcia/tcic.c | 3 ++- drivers/pcmcia/yenta_socket.c | 1 + include/pcmcia/ss.h | 4 ++++ 17 files changed, 35 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 22f3c9a0841e..ca14e721502d 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -80,6 +80,7 @@ config YENTA depends on PCCARD && PCI #fixme: remove dependendcy on CARDBUS depends on CARDBUS + select PCCARD_NONSTATIC ---help--- This option enables support for CardBus host bridges. Virtually all modern PCMCIA bridges are CardBus compatible. A "bridge" is @@ -94,6 +95,7 @@ config YENTA config PD6729 tristate "Cirrus PD6729 compatible bridge support" depends on PCMCIA && PCI + select PCCARD_NONSTATIC help This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge device, found in some older laptops and PCMCIA card readers. @@ -101,6 +103,7 @@ config PD6729 config I82092 tristate "i82092 compatible bridge support" depends on PCMCIA && PCI + select PCCARD_NONSTATIC help This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device, found in some older laptops and more commonly in evaluation boards for the @@ -109,6 +112,7 @@ config I82092 config I82365 tristate "i82365 compatible bridge support" depends on PCMCIA && ISA + select PCCARD_NONSTATIC help Say Y here to include support for ISA-bus PCMCIA host bridges that are register compatible with the Intel i82365. These are found on @@ -119,6 +123,7 @@ config I82365 config TCIC tristate "Databook TCIC host bridge support" depends on PCMCIA + select PCCARD_NONSTATIC help Say Y here to include support for the Databook TCIC family of PCMCIA host bridges. These are only found on a handful of old systems. @@ -178,4 +183,8 @@ config M32R_CFC_NUM help Set the number of M32R CF slots. +config PCCARD_NONSTATIC + tristate + depends on PCCARD + endmenu diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 1d26c873b6f6..3d5eb4984a7f 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -6,13 +6,15 @@ ifeq ($(CONFIG_PCMCIA_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif -pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o rsrc_nonstatic.o +pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o obj-$(CONFIG_PCCARD) += pcmcia_core.o pcmcia-y += ds.o pcmcia_compat.o obj-$(CONFIG_PCMCIA) += pcmcia.o +obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o + # socket drivers diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 99b90c2334f7..e29a6ddf2fd7 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -78,6 +78,7 @@ void release_cis_mem(struct pcmcia_socket *s) s->cis_virt = NULL; } } +EXPORT_SYMBOL(release_cis_mem); /* * Map the card memory at "card_offset" into virtual space. @@ -320,6 +321,7 @@ void destroy_cis_cache(struct pcmcia_socket *s) s->fake_cis = NULL; } } +EXPORT_SYMBOL(destroy_cis_cache); /*====================================================================== diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 590b2a561890..ecf3afff5dce 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -212,7 +212,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) { int ret; - if (!socket || !socket->ops || !socket->dev.dev) + if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops) return -EINVAL; cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops); @@ -250,11 +250,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) socket->cis_mem.flags = 0; socket->cis_mem.speed = cis_speed; - /* init resource handling */ - if (socket->features & SS_CAP_STATIC_MAP) - socket->resource_ops = &pccard_static_ops; - else - socket->resource_ops = &pccard_nonstatic_ops; + socket->mem_db.next = &socket->mem_db; socket->io_db.next = &socket->io_db; diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 764e71bcecab..f64ca5663f3c 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -144,8 +144,6 @@ int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); void release_resource_db(struct pcmcia_socket *s); -extern struct pccard_resource_ops pccard_static_ops; -extern struct pccard_resource_ops pccard_nonstatic_ops; /* In socket_sysfs.c */ extern struct class_interface pccard_sysfs_interface; diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c index 875c9cfaea3f..36d85f04e276 100644 --- a/drivers/pcmcia/hd64465_ss.c +++ b/drivers/pcmcia/hd64465_ss.c @@ -922,6 +922,7 @@ static int __init init_hs(void) hs_set_voltages(&hs_sockets[i], 0, 0); hs_sockets[i].socket.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP; /* mappings are fixed in host memory */ + hs_sockets[i].socket.resource_ops = &pccard_static_ops; hs_sockets[i].socket.irq_mask = 0xffde;/*0xffff*/ /* IRQs mapped in s/w so can do any, really */ hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW; /* 16MB fixed window size */ diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index eb255238aef8..aa8ed192d21a 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -162,6 +162,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de for (i = 0; idev; sockets[i].socket.ops = &i82092aa_operations; + sockets[i].socket.resource_ops = &pccard_nonstatic_ops; ret = pcmcia_register_socket(&sockets[i].socket); if (ret) { goto err_out_free_sockets; diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 56ced25d993c..0d9bb1505c2e 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1400,6 +1400,7 @@ static int __init init_i82365(void) for (i = 0; i < sockets; i++) { socket[i].socket.dev.dev = &i82365_device.dev; socket[i].socket.ops = &pcic_operations; + socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.owner = THIS_MODULE; socket[i].number = i; ret = pcmcia_register_socket(&socket[i].socket); diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 836058dfa2c0..023013d3e263 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -831,6 +831,7 @@ static int __init init_m32r_pcc(void) for (i = 0 ; i < pcc_sockets ; i++) { socket[i].socket.dev.dev = &pcc_device.dev; socket[i].socket.ops = &pcc_operations; + socket[i].socket.resource_ops = &pccard_static_ops; socket[i].socket.owner = THIS_MODULE; socket[i].number = i; ret = pcmcia_register_socket(&socket[i].socket); diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index aae7a16a1815..8c881ae73287 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -768,6 +768,7 @@ static int __init init_m32r_pcc(void) for (i = 0 ; i < pcc_sockets ; i++) { socket[i].socket.dev.dev = &pcc_device.dev; socket[i].socket.ops = &pcc_operations; + socket[i].socket.resource_ops = &pccard_static_ops; socket[i].socket.owner = THIS_MODULE; socket[i].number = i; ret = pcmcia_register_socket(&socket[i].socket); diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index ded56ce22d17..1347f94260c7 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -759,6 +759,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, socket[i].number = i; socket[i].socket.ops = &pd6729_operations; + socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.dev.dev = &dev->dev; socket[i].socket.driver_data = &socket[i]; } diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 7483249d09fe..b3f1fe0b02ca 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -290,3 +290,4 @@ struct pccard_resource_ops pccard_static_ops = { .adjust_resource = NULL, .exit = NULL, }; +EXPORT_SYMBOL(pccard_static_ops); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 088bbb1d2949..025dca06b8d4 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -34,6 +34,9 @@ #include #include "cs_internal.h" +MODULE_AUTHOR("David A. Hinds, Dominik Brodowski"); +MODULE_LICENSE("GPL"); + /* Parameters that can be set with 'insmod' */ #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) @@ -769,3 +772,4 @@ struct pccard_resource_ops pccard_nonstatic_ops = { .adjust_resource = nonstatic_adjust_resource_info, .exit = nonstatic_release_resource_db, }; +EXPORT_SYMBOL(pccard_nonstatic_ops); diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index a45fee3f4355..20dd66b245bc 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -758,6 +758,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops goto out_err_6; skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; + skt->socket.resource_ops = &pccard_static_ops; skt->socket.irq_mask = 0; skt->socket.map_size = PAGE_SIZE; skt->socket.pci_irq = skt->irq; diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index a651309eb84f..e20438a7408f 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -531,8 +531,9 @@ static int __init init_tcic(void) for (i = 0; i < sockets; i++) { socket_table[i].socket.ops = &tcic_operations; + socket_table[i].socket.resource_ops = &pccard_nonstatic_ops; socket_table[i].socket.dev.dev = &tcic_device.dev; - ret = pcmcia_register_socket(&socket_table[i].socket); + ret = pcmcia_register_socket(&socket_table[i].socket); if (ret && i) pcmcia_unregister_socket(&socket_table[0].socket); } diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 8b76f7d6a37e..91b7b133989a 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -917,6 +917,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i /* prepare pcmcia_socket */ socket->socket.ops = ¥ta_socket_operations; + socket->socket.resource_ops = &pccard_nonstatic_ops; socket->socket.dev.dev = &dev->dev; socket->socket.driver_data = socket; socket->socket.owner = THIS_MODULE; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 3b4b3cfea12d..281689320506 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -131,6 +131,10 @@ struct pccard_resource_ops { adjust_t *adj); void (*exit) (struct pcmcia_socket *s); }; +/* SS_CAP_STATIC_MAP */ +extern struct pccard_resource_ops pccard_static_ops; +/* !SS_CAP_STATIC_MAP */ +extern struct pccard_resource_ops pccard_nonstatic_ops; /* * Calls to set up low-level "Socket Services" drivers -- cgit v1.2.3 From 6ca65becb8ced63d016e438792f84b99e5499c51 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 11 Jan 2005 03:29:31 -0800 Subject: [PATCH] pcmcia: allocate resource database per-socket Move the resource databases and the "mem_probe" flag into a struct specific to rsrc_nonstatic, as it is not needed for the SS_CAP_STATIC_MAP case. Saves a few bytes, and makes code clearer (in my opinion) Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cs.c | 10 +++-- drivers/pcmcia/rsrc_nonstatic.c | 81 +++++++++++++++++++++++++++++++---------- include/pcmcia/ss.h | 11 +----- 3 files changed, 69 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index ecf3afff5dce..edfc17a30687 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -217,6 +217,12 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops); + if (socket->resource_ops->init) { + ret = socket->resource_ops->init(socket); + if (ret) + return (ret); + } + /* try to obtain a socket number [yes, it gets ugly if we * register more than 2^sizeof(unsigned int) pcmcia * sockets... but the socket number is deprecated @@ -250,10 +256,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) socket->cis_mem.flags = 0; socket->cis_mem.speed = cis_speed; - - socket->mem_db.next = &socket->mem_db; - socket->io_db.next = &socket->io_db; - INIT_LIST_HEAD(&socket->cis_cache); spin_lock_init(&socket->lock); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 025dca06b8d4..72eeac72609f 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -47,8 +47,20 @@ INT_MODULE_PARM(probe_io, 1); /* IO port probe? */ INT_MODULE_PARM(mem_limit, 0x10000); #endif +/* for io_db and mem_db */ +struct resource_map_t { + u_long base, num; + struct resource_map_t *next; +}; + typedef struct resource_map_t resource_map_t; +struct socket_data { + struct resource_map_t mem_db; + struct resource_map_t io_db; + unsigned int rsrc_mem_probe; +}; + static DECLARE_MUTEX(rsrc_sem); #define MEM_PROBE_LOW (1 << 0) #define MEM_PROBE_HIGH (1 << 1) @@ -179,6 +191,7 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num) static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num) { struct resource *res; + struct socket_data *s_data = s->resource_data; ioaddr_t i, j, bad, any; u_char *b, hole, most; @@ -221,7 +234,7 @@ static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num) bad = any = i; } else { if (bad) { - sub_interval(&s->io_db, bad, i-bad); + sub_interval(&s_data->io_db, bad, i-bad); printk(" %#04x-%#04x", bad, i-1); bad = 0; } @@ -232,7 +245,7 @@ static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num) printk(" nothing: probe failed.\n"); return; } else { - sub_interval(&s->io_db, bad, i-bad); + sub_interval(&s_data->io_db, bad, i-bad); printk(" %#04x-%#04x", bad, i-1); } } @@ -351,6 +364,7 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size) static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) { + struct socket_data *s_data = s->resource_data; u_long i, j, bad, fail, step; printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:", @@ -377,7 +391,7 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) if (i != j) { if (!bad) printk(" excluding"); printk(" %#05lx-%#05lx", i, j-1); - sub_interval(&s->mem_db, i, j-i); + sub_interval(&s_data->mem_db, i, j-i); bad += j-i; } } @@ -389,13 +403,14 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) { + struct socket_data *s_data = s->resource_data; u_long ok; - if (m == &s->mem_db) + if (m == &s_data->mem_db) return 0; ok = inv_probe(m->next, s); if (ok) { if (m->base >= 0x100000) - sub_interval(&s->mem_db, m->base, m->num); + sub_interval(&s_data->mem_db, m->base, m->num); return ok; } if (m->base < 0x100000) @@ -408,17 +423,18 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) resource_map_t *m, mm; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; u_long b, i, ok = 0; + struct socket_data *s_data = s->resource_data; /* We do up to four passes through the list */ if (probe_mask & MEM_PROBE_HIGH) { - if (inv_probe(s->mem_db.next, s) > 0) + if (inv_probe(s_data->mem_db.next, s) > 0) return; printk(KERN_NOTICE "cs: warning: no high memory space " "available!\n"); } if ((probe_mask & MEM_PROBE_LOW) == 0) return; - for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) { + for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { mm = *m; /* Only probe < 1 MB */ if (mm.base >= 0x100000) continue; @@ -431,7 +447,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) b = order[i] << 12; if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { if (ok >= mem_limit) - sub_interval(&s->mem_db, b, 0x10000); + sub_interval(&s_data->mem_db, b, 0x10000); else ok += do_mem_probe(b, 0x10000, s); } @@ -444,8 +460,9 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) { resource_map_t *m, mm; + struct socket_data *s_data = s->resource_data; - for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) { + for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { mm = *m; if (do_mem_probe(mm.base, mm.num, s)) break; @@ -461,6 +478,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) */ static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) { + struct socket_data *s_data = s->resource_data; if (probe_mem) { unsigned int probe_mask; @@ -470,8 +488,8 @@ static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) if (s->features & SS_CAP_PAGE_REGS) probe_mask = MEM_PROBE_HIGH; - if (probe_mask & ~s->rsrc_mem_probe) { - s->rsrc_mem_probe |= probe_mask; + if (probe_mask & ~s_data->rsrc_mem_probe) { + s_data->rsrc_mem_probe |= probe_mask; down(&s->skt_sem); @@ -555,10 +573,11 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star unsigned long r_end, struct pcmcia_socket *s) { resource_map_t *m; + struct socket_data *s_data = s->resource_data; int ret = -ENOMEM; down(&rsrc_sem); - for (m = s->io_db.next; m != &s->io_db; m = m->next) { + for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) { unsigned long start = m->base; unsigned long end = m->base + m->num - 1; @@ -590,6 +609,7 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); + struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min = base; int ret; @@ -599,7 +619,7 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num, data.mask = align - 1; data.offset = base & data.mask; - data.map = &s->io_db; + data.map = &s_data->io_db; down(&rsrc_sem); #ifdef CONFIG_PCI @@ -623,6 +643,7 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig int low, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); + struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min, max; int ret, i; @@ -631,7 +652,7 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig data.mask = align - 1; data.offset = base & data.mask; - data.map = &s->mem_db; + data.map = &s_data->mem_db; for (i = 0; i < 2; i++) { if (low) { @@ -669,6 +690,7 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) { u_long base, num; + struct socket_data *data = s->resource_data; int ret; base = adj->resource.memory.Base; @@ -681,10 +703,10 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - ret = add_interval(&s->mem_db, base, num); + ret = add_interval(&data->mem_db, base, num); break; case REMOVE_MANAGED_RESOURCE: - ret = sub_interval(&s->mem_db, base, num); + ret = sub_interval(&data->mem_db, base, num); if (ret == CS_SUCCESS) { struct pcmcia_socket *socket; down_read(&pcmcia_socket_list_rwsem); @@ -704,6 +726,7 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) { + struct socket_data *data = s->resource_data; int base, num, ret = CS_SUCCESS; base = adj->resource.io.BasePort; @@ -716,7 +739,7 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) down(&rsrc_sem); switch (adj->Action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&s->io_db, base, num) != 0) { + if (add_interval(&data->io_db, base, num) != 0) { ret = CS_IN_USE; break; } @@ -726,7 +749,7 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) #endif break; case REMOVE_MANAGED_RESOURCE: - sub_interval(&s->io_db, base, num); + sub_interval(&data->io_db, base, num); break; default: ret = CS_UNSUPPORTED_FUNCTION; @@ -749,15 +772,32 @@ static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj return CS_UNSUPPORTED_FUNCTION; } +static int nonstatic_init(struct pcmcia_socket *s) +{ + struct socket_data *data; + + data = kmalloc(sizeof(struct socket_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->mem_db.next = &data->mem_db; + data->io_db.next = &data->io_db; + + s->resource_data = (void *) data; + + return 0; +} + static void nonstatic_release_resource_db(struct pcmcia_socket *s) { + struct socket_data *data = s->resource_data; resource_map_t *p, *q; - for (p = s->mem_db.next; p != &s->mem_db; p = q) { + for (p = data->mem_db.next; p != &data->mem_db; p = q) { q = p->next; kfree(p); } - for (p = s->io_db.next; p != &s->io_db; p = q) { + for (p = data->io_db.next; p != &data->io_db; p = q) { q = p->next; kfree(p); } @@ -770,6 +810,7 @@ struct pccard_resource_ops pccard_nonstatic_ops = { .find_io = nonstatic_find_io_region, .find_mem = nonstatic_find_mem_region, .adjust_resource = nonstatic_adjust_resource_info, + .init = nonstatic_init, .exit = nonstatic_release_resource_db, }; EXPORT_SYMBOL(pccard_nonstatic_ops); diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 281689320506..70cbca2638c5 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -129,6 +129,7 @@ struct pccard_resource_ops { struct pcmcia_socket *s); int (*adjust_resource) (struct pcmcia_socket *s, adjust_t *adj); + int (*init) (struct pcmcia_socket *s); void (*exit) (struct pcmcia_socket *s); }; /* SS_CAP_STATIC_MAP */ @@ -167,11 +168,6 @@ struct config_t; struct region_t; struct pcmcia_callback; -/* for io_db and mem_db */ -struct resource_map_t { - u_long base, num; - struct resource_map_t *next; -}; struct pcmcia_socket { struct module *owner; @@ -197,10 +193,6 @@ struct pcmcia_socket { struct list_head socket_list; struct completion socket_released; - struct resource_map_t mem_db; - struct resource_map_t io_db; - unsigned int rsrc_mem_probe; - /* deprecated */ unsigned int sock; /* socket number */ @@ -216,6 +208,7 @@ struct pcmcia_socket { /* socket operations */ struct pccard_operations * ops; struct pccard_resource_ops * resource_ops; + void * resource_data; /* Zoom video behaviour is so chip specific its not worth adding this to _ops */ -- cgit v1.2.3 From 66d272434a1b009b94bab07bae98dec39e0a9706 Mon Sep 17 00:00:00 2001 From: Hisashi Hifumi Date: Tue, 11 Jan 2005 03:30:37 -0800 Subject: [PATCH] BUG on error handlings in Ext3 under I/O failure condition I found bugs on error handlings in the functions arround the ext3 file system, which cause inadequate completions of synchronous write I/O operations when disk I/O failures occur. Both 2.4 and 2.6 have this problem. I carried out following experiment: 1. Mount a ext3 file system on a SCSI disk with ordered mode. 2. Open a file on the file system with O_SYNC|O_RDWR|O_TRUNC|O_CREAT flag. 3. Write 512 bytes data to the file by calling write() every 5 seconds, and examine return values from the syscall. from write(). 4. Disconnect the SCSI cable, and examine messages from the kernel. After the SCSI cable is disconnected, write() must fail. But the result was different: write() succeeded for a while even though messages of the kernel notified SCSI I/O error. By applying following modifications, the above problem was solved. Signed-off-by: Hisashi Hifumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 8 +++++--- fs/fs-writeback.c | 15 ++++++++++----- fs/jbd/commit.c | 3 +++ include/linux/fs.h | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index 7a31850892cb..341ba4c58a18 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -311,10 +311,10 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) { struct inode * inode = dentry->d_inode; struct super_block * sb; - int ret; + int ret, err; /* sync the inode to buffers */ - write_inode_now(inode, 0); + ret = write_inode_now(inode, 0); /* sync the superblock to buffers */ sb = inode->i_sb; @@ -324,7 +324,9 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync) unlock_super(sb); /* .. finally sync the buffers to disk */ - ret = sync_blockdev(sb->s_bdev); + err = sync_blockdev(sb->s_bdev); + if (!ret) + ret = err; return ret; } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 26f234a0da93..6d0e70efd399 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -558,22 +558,24 @@ void sync_inodes(int wait) * dirty. This is primarily needed by knfsd. */ -void write_inode_now(struct inode *inode, int sync) +int write_inode_now(struct inode *inode, int sync) { + int ret; struct writeback_control wbc = { .nr_to_write = LONG_MAX, .sync_mode = WB_SYNC_ALL, }; if (inode->i_mapping->backing_dev_info->memory_backed) - return; + return 0; might_sleep(); spin_lock(&inode_lock); - __writeback_single_inode(inode, &wbc); + ret = __writeback_single_inode(inode, &wbc); spin_unlock(&inode_lock); if (sync) wait_on_inode(inode); + return ret; } EXPORT_SYMBOL(write_inode_now); @@ -642,8 +644,11 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int need_write_inode_now = 1; spin_unlock(&inode_lock); - if (need_write_inode_now) - write_inode_now(inode, 1); + if (need_write_inode_now) { + err2 = write_inode_now(inode, 1); + if (!err) + err = err2; + } else wait_on_inode(inode); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index c5c9983e3a60..aa5f22435d0c 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -337,6 +337,9 @@ write_out_data: } spin_unlock(&journal->j_list_lock); + if (err) + __journal_abort_hard(journal); + journal_write_revoke_records(journal, commit_transaction); jbd_debug(3, "JBD: commit phase 2\n"); diff --git a/include/linux/fs.h b/include/linux/fs.h index aa7abb112dbc..4d26f55c1299 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1344,7 +1344,7 @@ static inline void invalidate_remote_inode(struct inode *inode) invalidate_inode_pages(inode->i_mapping); } extern int invalidate_inode_pages2(struct address_space *mapping); -extern void write_inode_now(struct inode *, int); +extern int write_inode_now(struct inode *, int); extern int filemap_fdatawrite(struct address_space *); extern int filemap_flush(struct address_space *); extern int filemap_fdatawait(struct address_space *); -- cgit v1.2.3 From 5a1b817d2e63ba23f8b5649ed60ea4a46706306d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2005 16:59:26 +0000 Subject: [ARM] Add show_ipi_list() call. --- arch/arm/kernel/irq.c | 3 +++ include/asm-arm/smp.h | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'include') diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 5b35e76c3ce4..3ec2c1223aa0 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -231,6 +231,9 @@ unlock: } else if (i == NR_IRQS) { #ifdef CONFIG_ARCH_ACORN show_fiq_list(p, v); +#endif +#ifdef CONFIG_SMP + show_ipi_list(p); #endif seq_printf(p, "Err: %10lu\n", irq_err_count); } diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 0b012dfc098a..8375e904d562 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -32,6 +32,13 @@ extern cpumask_t cpu_present_mask; */ #define PROC_CHANGE_PENALTY 15 +struct seq_file; + +/* + * generate IPI list text + */ +extern void show_ipi_list(struct seq_file *p); + /* * Move global data into per-processor storage. */ -- cgit v1.2.3 From 902e60c56b03d5b70df72b2269223eb60e0aeedd Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2005 23:26:57 +0000 Subject: [ARM] Add SMP IRQ affinity and routing support. Provide /proc/irq/*/smp_affinity support, and add necessary methods to allow a machine to route the interrupt to the desired CPU. --- arch/arm/kernel/irq.c | 101 +++++++++++++++++++++++++++++++++++++++++++-- include/asm-arm/mach/irq.h | 14 +++++++ 2 files changed, 112 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index ed245c7a45d7..5e0656e88918 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -349,7 +350,7 @@ void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -374,7 +375,7 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -438,7 +439,7 @@ void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -906,8 +907,97 @@ out: EXPORT_SYMBOL(probe_irq_off); +#ifdef CONFIG_SMP +static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +{ + pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); + + spin_lock_irq(&irq_controller_lock); + desc->cpu = cpu; + desc->chip->set_cpu(desc, irq, cpu); + spin_unlock_irq(&irq_controller_lock); +} + +#ifdef CONFIG_PROC_FS +static int +irq_affinity_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct irqdesc *desc = irq_desc + ((int)data); + int len = cpumask_scnprintf(page, count, desc->affinity); + + if (count - len < 2) + return -EINVAL; + page[len++] = '\n'; + page[len] = '\0'; + + return len; +} + +static int +irq_affinity_write_proc(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + unsigned int irq = (unsigned int)data; + struct irqdesc *desc = irq_desc + irq; + cpumask_t affinity, tmp; + int ret = -EIO; + + if (!desc->chip->set_cpu) + goto out; + + ret = cpumask_parse(buffer, count, affinity); + if (ret) + goto out; + + cpus_and(tmp, affinity, cpu_online_map); + if (cpus_empty(tmp)) { + ret = -EINVAL; + goto out; + } + + desc->affinity = affinity; + route_irq(desc, irq, first_cpu(tmp)); + ret = count; + + out: + return ret; +} +#endif +#endif + void __init init_irq_proc(void) { +#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) + struct proc_dir_entry *dir; + int irq; + + dir = proc_mkdir("irq", 0); + if (!dir) + return; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct proc_dir_entry *entry; + struct irqdesc *desc; + char name[16]; + + desc = irq_desc + irq; + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name) - 1, "%u", irq); + + desc->procdir = proc_mkdir(name, dir); + if (!desc->procdir) + continue; + + entry = create_proc_entry("smp_affinity", 0600, desc->procdir); + if (entry) { + entry->nlink = 1; + entry->data = (void *)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + } +#endif } void __init init_IRQ(void) @@ -916,6 +1006,11 @@ void __init init_IRQ(void) extern void init_dma(void); int irq; +#ifdef CONFIG_SMP + bad_irq_desc.affinity = CPU_MASK_ALL; + bad_irq_desc.cpu = smp_processor_id(); +#endif + for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { *desc = bad_irq_desc; INIT_LIST_HEAD(&desc->pend); diff --git a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h index c6ae545e4237..a43a353f6c7b 100644 --- a/include/asm-arm/mach/irq.h +++ b/include/asm-arm/mach/irq.h @@ -47,6 +47,13 @@ struct irqchip { * Set wakeup-enable on the selected IRQ */ int (*wake)(unsigned int, unsigned int); + +#ifdef CONFIG_SMP + /* + * Route an interrupt to a CPU + */ + void (*set_cpu)(struct irqdesc *desc, unsigned int irq, unsigned int cpu); +#endif }; struct irqdesc { @@ -67,6 +74,13 @@ struct irqdesc { unsigned int noautoenable : 1; /* don't automatically enable IRQ */ unsigned int unused :25; + struct proc_dir_entry *procdir; + +#ifdef CONFIG_SMP + cpumask_t affinity; + unsigned int cpu; +#endif + /* * IRQ lock detection */ -- cgit v1.2.3 From 8f13ed2fa0cc179e1462f8d7c81dd4a62b7e0c88 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 15:35:48 -0800 Subject: [PATCH] x86_64: Fix ACPI SRAT NUMA parsing Fix fallout from the recent nodemask_t changes. The node ids assigned in the SRAT parser were off by one. I added a new first_unset_node() function to nodemask.h to allocate IDs sanely. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/mm/srat.c | 17 ++++++++++------- include/linux/nodemask.h | 9 +++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 1db7483a0564..aaf329373367 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -20,17 +20,20 @@ static struct acpi_table_slit *acpi_slit; -static DECLARE_BITMAP(nodes_parsed, MAX_NUMNODES) __initdata; +static nodemask_t nodes_parsed __initdata; +static nodemask_t nodes_found __initdata; static struct node nodes[MAX_NUMNODES] __initdata; static __u8 pxm2node[256] __initdata = { [0 ... 255] = 0xff }; static __init int setup_node(int pxm) { - if (pxm2node[pxm] == 0xff) { - if (num_online_nodes() >= MAX_NUMNODES) + unsigned node = pxm2node[pxm]; + if (node == 0xff) { + if (nodes_weight(nodes_found) >= MAX_NUMNODES) return -1; - pxm2node[pxm] = num_online_nodes(); - node_set_online(num_online_nodes()); + node = first_unset_node(nodes_found); + node_set(node, nodes_found); + pxm2node[pxm] = node; } return pxm2node[pxm]; } @@ -140,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) return; } nd = &nodes[node]; - if (!test_and_set_bit(node, &nodes_parsed)) { + if (!node_test_and_set(node, nodes_parsed)) { nd->start = start; nd->end = end; } else { @@ -171,7 +174,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) return -1; } for (i = 0; i < MAX_NUMNODES; i++) { - if (!test_bit(i, &nodes_parsed)) + if (!node_isset(i, nodes_parsed)) continue; cutoff_node(i, start, end); if (nodes[i].start == nodes[i].end) diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 4de843d94147..16475a23efa7 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -38,6 +38,8 @@ * * int first_node(mask) Number lowest set bit, or MAX_NUMNODES * int next_node(node, mask) Next node past 'node', or MAX_NUMNODES + * int first_unset_node(mask) First node not set in mask, or + * MAX_NUMNODES. * * nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set * NODE_MASK_ALL Initializer - all bits set @@ -235,6 +237,13 @@ static inline int __next_node(int n, const nodemask_t *srcp, int nbits) m; \ }) +#define first_unset_node(mask) __first_unset_node(&(mask)) +static inline int __first_unset_node(const nodemask_t *maskp) +{ + return min_t(int,MAX_NUMNODES, + find_first_zero_bit(maskp->bits, MAX_NUMNODES)); +} + #define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES) #if MAX_NUMNODES <= BITS_PER_LONG -- cgit v1.2.3 From c0e289599d4ad6b448b7a3fb52a086dc294da88f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Jan 2005 15:36:17 -0800 Subject: [PATCH] [3/4] x86_64: Fix NUMA hash setup Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/mm/k8topology.c | 2 +- arch/x86_64/mm/numa.c | 8 +++----- arch/x86_64/mm/srat.c | 2 +- include/asm-x86_64/numa.h | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 0622ad3016f2..55a2e67e32a6 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -148,7 +148,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) if (!found) return -1; - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, numnodes); if (memnode_shift < 0) { printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n"); return -1; diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index b1a7db4f4d6d..72b16f3d5e87 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -34,9 +34,7 @@ cpumask_t node_to_cpumask[MAX_NUMNODES]; int numa_off __initdata; -unsigned long nodes_present; - -int __init compute_hash_shift(struct node *nodes) +int __init compute_hash_shift(struct node *nodes, int numnodes) { int i; int shift = 24; @@ -45,7 +43,7 @@ int __init compute_hash_shift(struct node *nodes) /* When in doubt use brute force. */ while (shift < 48) { memset(memnodemap,0xff,sizeof(*memnodemap) * NODEMAPSIZE); - for_each_online_node(i) { + for (i = 0; i < numnodes; i++) { if (nodes[i].start == nodes[i].end) continue; for (addr = nodes[i].start; @@ -197,7 +195,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) (nodes[i].end - nodes[i].start) >> 20); node_set_online(i); } - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, numa_fake); if (memnode_shift < 0) { memnode_shift = 0; printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index aaf329373367..3bd04832f041 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -166,7 +166,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) int i; if (acpi_numa <= 0) return -1; - memnode_shift = compute_hash_shift(nodes); + memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed)); if (memnode_shift < 0) { printk(KERN_ERR "SRAT: No NUMA node hash function found. Contact maintainer\n"); diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index 21843b35ef18..3574f604542b 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h @@ -8,7 +8,7 @@ struct node { u64 start,end; }; -extern int compute_hash_shift(struct node *nodes); +extern int compute_hash_shift(struct node *nodes, int numnodes); #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) -- cgit v1.2.3 From 3a7cccbdbd3013f19fad3b8c2acd2af851165137 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 11 Jan 2005 23:37:59 +0000 Subject: [ARM] Relocate ipi_count into ipi data structures. This removes ipi_count from the globally visible per-cpu cpu data structure. --- arch/arm/kernel/smp.c | 12 ++++++------ include/asm-arm/cpu.h | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 9c7874cebb43..abd3a8133eef 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -42,6 +42,7 @@ cpumask_t cpu_online_map; */ struct ipi_data { spinlock_t lock; + unsigned long ipi_count; unsigned long bits; }; @@ -242,12 +243,12 @@ int smp_call_function(void (*func)(void *info), void *info, int retry, void show_ipi_list(struct seq_file *p) { - int cpu; + unsigned int cpu; - seq_printf(p, "IPI: "); + seq_puts(p, "IPI:"); for_each_online_cpu(cpu) - seq_printf(p, "%10lu ", per_cpu(cpu_data, cpu).ipi_count); + seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); seq_putc(p, '\n'); } @@ -316,12 +317,11 @@ static void ipi_cpu_stop(unsigned int cpu) void do_IPI(unsigned int ipimask, struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); + struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - per_cpu(cpu_data, cpu).ipi_count++; + ipi->ipi_count++; if (ipimask & (1 << 0)) { - struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - for (;;) { unsigned long msgs; diff --git a/include/asm-arm/cpu.h b/include/asm-arm/cpu.h index 0f99a8881a8b..fcbdd40cb667 100644 --- a/include/asm-arm/cpu.h +++ b/include/asm-arm/cpu.h @@ -17,7 +17,6 @@ struct cpuinfo_arm { struct cpu cpu; #ifdef CONFIG_SMP unsigned int loops_per_jiffy; - unsigned long ipi_count; #endif }; -- cgit v1.2.3 From d2bca7baf9666c0ba382f39b8b1ca9a04b88798a Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Tue, 11 Jan 2005 16:48:35 -0800 Subject: [PATCH] Alpha: typos in io_trivial.h This apparently explains some weird IO failures reported in last two months. Only non-bwx (including generic) kernels were affected. Acked-by: Richard Henderson Signed-off-by: Linus Torvalds --- include/asm-alpha/io_trivial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/io_trivial.h b/include/asm-alpha/io_trivial.h index cfe1f86c33db..b10d1aa4cdd1 100644 --- a/include/asm-alpha/io_trivial.h +++ b/include/asm-alpha/io_trivial.h @@ -26,7 +26,7 @@ IO_CONCAT(__IO_PREFIX,iowrite8)(u8 b, void __iomem *a) __EXTERN_INLINE void IO_CONCAT(__IO_PREFIX,iowrite16)(u16 b, void __iomem *a) { - __kernel_stb(b, *(volatile u16 __force *)a); + __kernel_stw(b, *(volatile u16 __force *)a); } #endif @@ -66,7 +66,7 @@ IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a) __EXTERN_INLINE void IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a) { - __kernel_stb(b, *(volatile u16 __force *)a); + __kernel_stw(b, *(volatile u16 __force *)a); } #elif IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 2 __EXTERN_INLINE u8 -- cgit v1.2.3 From 8de4d36f31299effc7c2c4ba05262de4e3d69b4d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 11 Jan 2005 16:50:53 -0800 Subject: [PATCH] PPC64 had _raw_read_trylock already Ingo presumably didn't notice that ppc64 already had a functional _raw_read_trylock when he added the #define to use the generic version. This just removes the #define so we use the ppc64-specific version again. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- include/asm-ppc64/spinlock.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h index 58e5dc61d9d8..e194599dbe50 100644 --- a/include/asm-ppc64/spinlock.h +++ b/include/asm-ppc64/spinlock.h @@ -222,8 +222,6 @@ static void __inline__ _raw_read_unlock(rwlock_t *rw) : "cr0", "memory"); } -#define _raw_read_trylock(lock) generic_raw_read_trylock(lock) - /* * This returns the old value in the lock, * so we got the write lock if the return value is 0. -- cgit v1.2.3 From 8d3f522381071d2847aea15f0ef5ac66c9a3c93a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 11 Jan 2005 17:02:21 -0800 Subject: [PATCH] ppc: fix removed MMCR0_PMXE define In ChangeSet 1.2370, 2005/01/11 17:41:32-08:00, tglx@linutronix.de wrote: > > [PATCH] ppc: remove duplicate define > > The MMCR0_PMXE is already defined in reg.h... Er, no it's not. But perhaps it should be... --- include/asm-ppc/reg.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h index 73eab4528eb9..48c0706466ca 100644 --- a/include/asm-ppc/reg.h +++ b/include/asm-ppc/reg.h @@ -329,6 +329,7 @@ #define MMCR0_PMC2_CYCLES 0x1 #define MMCR0_PMC2_ITLB 0x7 #define MMCR0_PMC2_LOADMISSTIME 0x5 +#define MMCR0_PMXE (1 << 26) /* Short-hand versions for a number of the above SPRNs */ #define CTR SPRN_CTR /* Counter Register */ -- cgit v1.2.3 From f741676a0eea898c7fd2169df9cfcf65a3f76bd1 Mon Sep 17 00:00:00 2001 From: David Mosberger Date: Tue, 11 Jan 2005 17:14:26 -0800 Subject: [IA64] add hpzx1_swiotlb machine-vector (new files) This is really part of the earlier changeset from David to add the new machine vector to support certain limited range DMA cards on zx1. I just forgot to run "bk new" before the commit, so the newly added files weren't checked into BK. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/hp/common/hwsw_iommu.c | 185 +++++++++++++++++++++++++++++++ arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c | 3 + include/asm-ia64/machvec_hpzx1_swiotlb.h | 43 +++++++ 3 files changed, 231 insertions(+) create mode 100644 arch/ia64/hp/common/hwsw_iommu.c create mode 100644 arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c create mode 100644 include/asm-ia64/machvec_hpzx1_swiotlb.h (limited to 'include') diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c new file mode 100644 index 000000000000..80f8ef013939 --- /dev/null +++ b/arch/ia64/hp/common/hwsw_iommu.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2004 Hewlett-Packard Development Company, L.P. + * Contributed by David Mosberger-Tang + * + * This is a pseudo I/O MMU which dispatches to the hardware I/O MMU + * whenever possible. We assume that the hardware I/O MMU requires + * full 32-bit addressability, as is the case, e.g., for HP zx1-based + * systems (there, the I/O MMU window is mapped at 3-4GB). If a + * device doesn't provide full 32-bit addressability, we fall back on + * the sw I/O TLB. This is good enough to let us support broken + * hardware such as soundcards which have a DMA engine that can + * address only 28 bits. + */ + +#include + +#include + +/* swiotlb declarations & definitions: */ +extern void swiotlb_init_with_default_size (size_t size); +extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent; +extern ia64_mv_dma_free_coherent swiotlb_free_coherent; +extern ia64_mv_dma_map_single swiotlb_map_single; +extern ia64_mv_dma_unmap_single swiotlb_unmap_single; +extern ia64_mv_dma_map_sg swiotlb_map_sg; +extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg; +extern ia64_mv_dma_supported swiotlb_dma_supported; +extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error; + +/* hwiommu declarations & definitions: */ + +extern ia64_mv_dma_alloc_coherent sba_alloc_coherent; +extern ia64_mv_dma_free_coherent sba_free_coherent; +extern ia64_mv_dma_map_single sba_map_single; +extern ia64_mv_dma_unmap_single sba_unmap_single; +extern ia64_mv_dma_map_sg sba_map_sg; +extern ia64_mv_dma_unmap_sg sba_unmap_sg; +extern ia64_mv_dma_supported sba_dma_supported; +extern ia64_mv_dma_mapping_error sba_dma_mapping_error; + +#define hwiommu_alloc_coherent sba_alloc_coherent +#define hwiommu_free_coherent sba_free_coherent +#define hwiommu_map_single sba_map_single +#define hwiommu_unmap_single sba_unmap_single +#define hwiommu_map_sg sba_map_sg +#define hwiommu_unmap_sg sba_unmap_sg +#define hwiommu_dma_supported sba_dma_supported +#define hwiommu_dma_mapping_error sba_dma_mapping_error +#define hwiommu_sync_single_for_cpu machvec_dma_sync_single +#define hwiommu_sync_sg_for_cpu machvec_dma_sync_sg +#define hwiommu_sync_single_for_device machvec_dma_sync_single +#define hwiommu_sync_sg_for_device machvec_dma_sync_sg + + +/* + * Note: we need to make the determination of whether or not to use + * the sw I/O TLB based purely on the device structure. Anything else + * would be unreliable or would be too intrusive. + */ +static inline int +use_swiotlb (struct device *dev) +{ + return dev && dev->dma_mask && !hwiommu_dma_supported(dev, *dev->dma_mask); +} + +void +hwsw_init (void) +{ + /* default to a smallish 2MB sw I/O TLB */ + swiotlb_init_with_default_size (2 * (1<<20)); +} + +void * +hwsw_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int flags) +{ + if (use_swiotlb(dev)) + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); + else + return hwiommu_alloc_coherent(dev, size, dma_handle, flags); +} + +void +hwsw_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) +{ + if (use_swiotlb(dev)) + swiotlb_free_coherent(dev, size, vaddr, dma_handle); + else + hwiommu_free_coherent(dev, size, vaddr, dma_handle); +} + +dma_addr_t +hwsw_map_single (struct device *dev, void *addr, size_t size, int dir) +{ + if (use_swiotlb(dev)) + return swiotlb_map_single(dev, addr, size, dir); + else + return hwiommu_map_single(dev, addr, size, dir); +} + +void +hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir) +{ + if (use_swiotlb(dev)) + return swiotlb_unmap_single(dev, iova, size, dir); + else + return hwiommu_unmap_single(dev, iova, size, dir); +} + + +int +hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) +{ + if (use_swiotlb(dev)) + return swiotlb_map_sg(dev, sglist, nents, dir); + else + return hwiommu_map_sg(dev, sglist, nents, dir); +} + +void +hwsw_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) +{ + if (use_swiotlb(dev)) + return swiotlb_unmap_sg(dev, sglist, nents, dir); + else + return hwiommu_unmap_sg(dev, sglist, nents, dir); +} + +void +hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir) +{ + if (use_swiotlb(dev)) + swiotlb_sync_single_for_cpu(dev, addr, size, dir); + else + hwiommu_sync_single_for_cpu(dev, addr, size, dir); +} + +void +hwsw_sync_sg_for_cpu (struct device *dev, struct scatterlist *sg, int nelems, int dir) +{ + if (use_swiotlb(dev)) + swiotlb_sync_sg_for_cpu(dev, sg, nelems, dir); + else + hwiommu_sync_sg_for_cpu(dev, sg, nelems, dir); +} + +void +hwsw_sync_single_for_device (struct device *dev, dma_addr_t addr, size_t size, int dir) +{ + if (use_swiotlb(dev)) + swiotlb_sync_single_for_device(dev, addr, size, dir); + else + hwiommu_sync_single_for_device(dev, addr, size, dir); +} + +void +hwsw_sync_sg_for_device (struct device *dev, struct scatterlist *sg, int nelems, int dir) +{ + if (use_swiotlb(dev)) + swiotlb_sync_sg_for_device(dev, sg, nelems, dir); + else + hwiommu_sync_sg_for_device(dev, sg, nelems, dir); +} + +int +hwsw_dma_supported (struct device *dev, u64 mask) +{ + if (hwiommu_dma_supported(dev, mask)) + return 1; + return swiotlb_dma_supported(dev, mask); +} + +int +hwsw_dma_mapping_error (dma_addr_t dma_addr) +{ + return hwiommu_dma_mapping_error (dma_addr) || swiotlb_dma_mapping_error(dma_addr); +} + +EXPORT_SYMBOL(hwsw_dma_mapping_error); +EXPORT_SYMBOL(hwsw_map_single); +EXPORT_SYMBOL(hwsw_unmap_single); +EXPORT_SYMBOL(hwsw_map_sg); +EXPORT_SYMBOL(hwsw_unmap_sg); +EXPORT_SYMBOL(hwsw_dma_supported); +EXPORT_SYMBOL(hwsw_alloc_coherent); +EXPORT_SYMBOL(hwsw_free_coherent); diff --git a/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c b/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c new file mode 100644 index 000000000000..4392a96b3c58 --- /dev/null +++ b/arch/ia64/hp/zx1/hpzx1_swiotlb_machvec.c @@ -0,0 +1,3 @@ +#define MACHVEC_PLATFORM_NAME hpzx1_swiotlb +#define MACHVEC_PLATFORM_HEADER +#include diff --git a/include/asm-ia64/machvec_hpzx1_swiotlb.h b/include/asm-ia64/machvec_hpzx1_swiotlb.h new file mode 100644 index 000000000000..9924b1b00a6c --- /dev/null +++ b/include/asm-ia64/machvec_hpzx1_swiotlb.h @@ -0,0 +1,43 @@ +#ifndef _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h +#define _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h + +extern ia64_mv_setup_t dig_setup; +extern ia64_mv_dma_init hwsw_init; +extern ia64_mv_dma_alloc_coherent hwsw_alloc_coherent; +extern ia64_mv_dma_free_coherent hwsw_free_coherent; +extern ia64_mv_dma_map_single hwsw_map_single; +extern ia64_mv_dma_unmap_single hwsw_unmap_single; +extern ia64_mv_dma_map_sg hwsw_map_sg; +extern ia64_mv_dma_unmap_sg hwsw_unmap_sg; +extern ia64_mv_dma_supported hwsw_dma_supported; +extern ia64_mv_dma_mapping_error hwsw_dma_mapping_error; +extern ia64_mv_dma_sync_single_for_cpu hwsw_sync_single_for_cpu; +extern ia64_mv_dma_sync_sg_for_cpu hwsw_sync_sg_for_cpu; +extern ia64_mv_dma_sync_single_for_device hwsw_sync_single_for_device; +extern ia64_mv_dma_sync_sg_for_device hwsw_sync_sg_for_device; + +/* + * This stuff has dual use! + * + * For a generic kernel, the macros are used to initialize the + * platform's machvec structure. When compiling a non-generic kernel, + * the macros are used directly. + */ +#define platform_name "hpzx1_swiotlb" + +#define platform_setup dig_setup +#define platform_dma_init hwsw_init +#define platform_dma_alloc_coherent hwsw_alloc_coherent +#define platform_dma_free_coherent hwsw_free_coherent +#define platform_dma_map_single hwsw_map_single +#define platform_dma_unmap_single hwsw_unmap_single +#define platform_dma_map_sg hwsw_map_sg +#define platform_dma_unmap_sg hwsw_unmap_sg +#define platform_dma_supported hwsw_dma_supported +#define platform_dma_mapping_error hwsw_dma_mapping_error +#define platform_dma_sync_single_for_cpu hwsw_sync_single_for_cpu +#define platform_dma_sync_sg_for_cpu hwsw_sync_sg_for_cpu +#define platform_dma_sync_single_for_device hwsw_sync_single_for_device +#define platform_dma_sync_sg_for_device hwsw_sync_sg_for_device + +#endif /* _ASM_IA64_MACHVEC_HPZX1_SWIOTLB_h */ -- cgit v1.2.3 From 65c333c9425f7914ec3cf8fa5e18b1f08abb812a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 11 Jan 2005 22:06:41 -0600 Subject: SCSI: add starget_for_each_device From: James.Smart@Emulex.Com This patch deprecates the use of device_for_each_child() with stargets. The reasoning behind this is due to issues regarding: Semaphores that device_for_each_child() takes Implicit assumptions that each child is an sdev device. The patch adds a new helper function, starget_for_each_device(), and replaces all previous uses of device_for_each_child(). Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 22 ++++++++++++++++++++++ drivers/scsi/scsi_lib.c | 18 ++++++++---------- drivers/scsi/scsi_transport_fc.c | 16 +++++++--------- include/scsi/scsi_device.h | 2 ++ 4 files changed, 39 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 82c7b0ab4047..63e5224eee0a 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1082,6 +1082,28 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost, } EXPORT_SYMBOL(__scsi_iterate_devices); +/** + * starget_for_each_device - helper to walk all devices of a target + * @starget: target whose devices we want to iterate over. + * + * This traverses over each devices of @shost. The devices have + * a reference that must be released by scsi_host_put when breaking + * out of the loop. + */ +void starget_for_each_device(struct scsi_target *starget, void * data, + void (*fn)(struct scsi_device *, void *)) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct scsi_device *sdev; + + shost_for_each_device(sdev, shost) { + if ((sdev->channel == starget->channel) && + (sdev->id == starget->id)) + fn(sdev, data); + } +} +EXPORT_SYMBOL(starget_for_each_device); + /** * scsi_device_lookup - find a device given the host (UNLOCKED) * @shost: SCSI host pointer diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 73660628b520..38f165070c94 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1782,31 +1782,29 @@ scsi_device_resume(struct scsi_device *sdev) } EXPORT_SYMBOL(scsi_device_resume); -static int -device_quiesce_fn(struct device *dev, void *data) +static void +device_quiesce_fn(struct scsi_device *sdev, void *data) { - scsi_device_quiesce(to_scsi_device(dev)); - return 0; + scsi_device_quiesce(sdev); } void scsi_target_quiesce(struct scsi_target *starget) { - device_for_each_child(&starget->dev, NULL, device_quiesce_fn); + starget_for_each_device(starget, NULL, device_quiesce_fn); } EXPORT_SYMBOL(scsi_target_quiesce); -static int -device_resume_fn(struct device *dev, void *data) +static void +device_resume_fn(struct scsi_device *sdev, void *data) { - scsi_device_resume(to_scsi_device(dev)); - return 0; + scsi_device_resume(sdev); } void scsi_target_resume(struct scsi_target *starget) { - device_for_each_child(&starget->dev, NULL, device_resume_fn); + starget_for_each_device(starget, NULL, device_resume_fn); } EXPORT_SYMBOL(scsi_target_resume); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 926cec15e5f2..2fddf2c24b67 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -808,10 +808,9 @@ EXPORT_SYMBOL(fc_release_transport); * @dev: scsi device * @data: unused **/ -static int fc_device_block(struct device *dev, void *data) +static void fc_device_block(struct scsi_device *sdev, void *data) { - scsi_internal_device_block(to_scsi_device(dev)); - return 0; + scsi_internal_device_block(sdev); } /** @@ -819,10 +818,9 @@ static int fc_device_block(struct device *dev, void *data) * @dev: scsi device * @data: unused **/ -static int fc_device_unblock(struct device *dev, void *data) +static void fc_device_unblock(struct scsi_device *sdev, void *data) { - scsi_internal_device_unblock(to_scsi_device(dev)); - return 0; + scsi_internal_device_unblock(sdev); } /** @@ -842,7 +840,7 @@ static void fc_timeout_blocked_tgt(void *data) * unblock this device, then IO errors will probably * result if the host still isn't ready. */ - device_for_each_child(&starget->dev, NULL, fc_device_unblock); + starget_for_each_device(starget, NULL, fc_device_unblock); } /** @@ -870,7 +868,7 @@ fc_target_block(struct scsi_target *starget) if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) return -EINVAL; - device_for_each_child(&starget->dev, NULL, fc_device_block); + starget_for_each_device(starget, NULL, fc_device_block); /* The scsi lld blocks this target for the timeout period only. */ schedule_delayed_work(work, timeout * HZ); @@ -901,7 +899,7 @@ fc_target_unblock(struct scsi_target *starget) if (cancel_delayed_work(&fc_starget_dev_loss_work(starget))) flush_scheduled_work(); - device_for_each_child(&starget->dev, NULL, fc_device_unblock); + starget_for_each_device(starget, NULL, fc_device_unblock); } EXPORT_SYMBOL(fc_target_unblock); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 6afc72fba7dc..8678132e3947 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -172,6 +172,8 @@ extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *, uint, uint, uint); extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *, uint, uint, uint); +extern void starget_for_each_device(struct scsi_target *, void *, + void (*fn)(struct scsi_device *, void *)); /* only exposed to implement shost_for_each_device */ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, -- cgit v1.2.3 From e47da19362bec6bc9d7e17a599cc9eb6fd144eed Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 11 Jan 2005 22:09:46 -0600 Subject: FC Transport updates - additional fc host attributes From: James.Smart@Emulex.Com This patch adds 5 more FC transport host attributes in support of HBAAPI. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 20 ++++++++++++++++++++ include/scsi/scsi_transport_fc.h | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2fddf2c24b67..1aca210eabd1 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -270,6 +270,16 @@ static int fc_setup_host_transport_attrs(struct Scsi_Host *shost) sizeof(fc_host_symbolic_name(shost))); fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN; fc_host_maxframe_size(shost) = -1; + memset(fc_host_hardware_version(shost), 0, + sizeof(fc_host_hardware_version(shost))); + memset(fc_host_firmware_version(shost), 0, + sizeof(fc_host_firmware_version(shost))); + memset(fc_host_serial_number(shost), 0, + sizeof(fc_host_serial_number(shost))); + memset(fc_host_opt_rom_version(shost), 0, + sizeof(fc_host_opt_rom_version(shost))); + memset(fc_host_driver_version(shost), 0, + sizeof(fc_host_driver_version(shost))); fc_host_port_id(shost) = -1; fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; @@ -536,6 +546,11 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); +fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); +fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); +fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); +fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); +fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1)); /* Dynamic Host Attributes */ @@ -772,6 +787,11 @@ fc_attach_transport(struct fc_function_template *ft) SETUP_HOST_ATTRIBUTE_RD(symbolic_name); SETUP_HOST_ATTRIBUTE_RD(supported_speeds); SETUP_HOST_ATTRIBUTE_RD(maxframe_size); + SETUP_HOST_ATTRIBUTE_RD(hardware_version); + SETUP_HOST_ATTRIBUTE_RD(firmware_version); + SETUP_HOST_ATTRIBUTE_RD(serial_number); + SETUP_HOST_ATTRIBUTE_RD(opt_rom_version); + SETUP_HOST_ATTRIBUTE_RD(driver_version); SETUP_HOST_ATTRIBUTE_RD(port_id); SETUP_HOST_ATTRIBUTE_RD(port_type); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 3b7128327791..1d4adfd6d3e9 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -185,6 +185,8 @@ struct fc_host_statistics { #define FC_FC4_LIST_SIZE 32 #define FC_SYMBOLIC_NAME_SIZE 256 +#define FC_VERSION_STRING_SIZE 64 +#define FC_SERIAL_NUMBER_SIZE 80 struct fc_host_attrs { /* Fixed Attributes */ @@ -195,6 +197,11 @@ struct fc_host_attrs { char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; u32 supported_speeds; u32 maxframe_size; + char hardware_version[FC_VERSION_STRING_SIZE]; + char firmware_version[FC_VERSION_STRING_SIZE]; + char serial_number[FC_SERIAL_NUMBER_SIZE]; + char opt_rom_version[FC_VERSION_STRING_SIZE]; + char driver_version[FC_VERSION_STRING_SIZE]; /* Dynamic Attributes */ u32 port_id; @@ -226,6 +233,16 @@ struct fc_host_attrs { (((struct fc_host_attrs *)(x)->shost_data)->supported_speeds) #define fc_host_maxframe_size(x) \ (((struct fc_host_attrs *)(x)->shost_data)->maxframe_size) +#define fc_host_hardware_version(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->hardware_version) +#define fc_host_firmware_version(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->firmware_version) +#define fc_host_serial_number(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->serial_number) +#define fc_host_opt_rom_version(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->opt_rom_version) +#define fc_host_driver_version(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->driver_version) #define fc_host_port_id(x) \ (((struct fc_host_attrs *)(x)->shost_data)->port_id) #define fc_host_port_type(x) \ @@ -285,6 +302,11 @@ struct fc_function_template { unsigned long show_host_symbolic_name:1; unsigned long show_host_supported_speeds:1; unsigned long show_host_maxframe_size:1; + unsigned long show_host_hardware_version:1; + unsigned long show_host_firmware_version:1; + unsigned long show_host_serial_number:1; + unsigned long show_host_opt_rom_version:1; + unsigned long show_host_driver_version:1; /* host dynamic attributes */ unsigned long show_host_port_id:1; unsigned long show_host_port_type:1; -- cgit v1.2.3 From 7c896bbf8aa0a194f63332aeb1f52021b32b53cd Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 12 Jan 2005 13:49:34 +0000 Subject: [ARM] Don't use __init for function prototypes. --- include/asm-arm/smp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 8375e904d562..f21fd8f6bcdd 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -53,6 +53,6 @@ extern void smp_cross_call(cpumask_t callmap); * Boot a secondary CPU, and assign it the specified idle task. * This also gives us the initial stack to use for this CPU. */ -extern int __init boot_secondary(unsigned int cpu, struct task_struct *); +extern int boot_secondary(unsigned int cpu, struct task_struct *); #endif /* ifndef __ASM_ARM_SMP_H */ -- cgit v1.2.3 From 209a0f3b1ad61e34c6fe3b912449db8c85ca5d0a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 12 Jan 2005 14:01:58 +0000 Subject: [ARM] Remove include. asm/processor.h doesn't use atomic operations nor types, so there's no need to include asm/atomic.h. Signed-off-by: Russell King --- include/asm-arm/processor.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 06ab5f106a0f..4a9845997a75 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -19,7 +19,6 @@ #ifdef __KERNEL__ -#include #include #include #include -- cgit v1.2.3 From d56169c76f3692896274e56c3a090015e304c1ec Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Wed, 12 Jan 2005 15:14:51 +0000 Subject: [ARM PATCH] 2388/1: Add SSP control code for Sharp SL-C7xx Series (Corgi) Patch from Richard Purdie The Sharp SL-C7xx Series (Corgi) has 3 devices connected to the SSP interface each needing different configurations of the port. This code provides the necessary access and locking so drivers can access these components. It uses the functions provided by the PXA SSP driver to access the port. It also adds some machine specific GPIO definitions used by this code and adds some comments to existing definitions. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/Makefile | 2 +- arch/arm/mach-pxa/corgi.c | 6 + arch/arm/mach-pxa/corgi_ssp.c | 247 +++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/corgi.h | 22 ++-- 4 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 arch/arm/mach-pxa/corgi_ssp.c (limited to 'include') diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 0464f512de95..d480bd54c95d 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o -obj-$(CONFIG_PXA_SHARPSL) += corgi.o +obj-$(CONFIG_PXA_SHARPSL) += corgi.o corgi_ssp.o ssp.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 8173808121f7..716643c7df2a 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -68,8 +68,14 @@ static struct platform_device corgiscoop_device = { .resource = corgi_scoop_resources, }; +static struct platform_device corgissp_device = { + .name = "corgi-ssp", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &corgiscoop_device, + &corgissp_device, }; static struct sharpsl_flash_param_info sharpsl_flash_param; diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c new file mode 100644 index 000000000000..1d2a881f3b7e --- /dev/null +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -0,0 +1,247 @@ +/* + * SSP control code for Sharp Corgi devices + * + * Copyright (c) 2004 Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED; +static struct ssp_dev corgi_ssp_dev; +static struct ssp_state corgi_ssp_state; + +/* + * There are three devices connected to the SSP interface: + * 1. A touchscreen controller (TI ADS7846 compatible) + * 2. An LCD contoller (with some Backlight functionality) + * 3. A battery moinitoring IC (Maxim MAX1111) + * + * Each device uses a different speed/mode of communication. + * + * The touchscreen is very sensitive and the most frequently used + * so the port is left configured for this. + * + * Devices are selected using Chip Selects on GPIOs. + */ + +/* + * ADS7846 Routines + */ +unsigned long corgi_ssp_ads7846_putget(ulong data) +{ + unsigned long ret,flag; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + + ssp_write_word(&corgi_ssp_dev,data); + ret = ssp_read_word(&corgi_ssp_dev); + + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + return ret; +} + +/* + * NOTE: These functions should always be called in interrupt context + * and use the _lock and _unlock functions. They are very time sensitive. + */ +void corgi_ssp_ads7846_lock(void) +{ + spin_lock(&corgi_ssp_lock); + GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); +} + +void corgi_ssp_ads7846_unlock(void) +{ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + spin_unlock(&corgi_ssp_lock); +} + +void corgi_ssp_ads7846_put(ulong data) +{ + ssp_write_word(&corgi_ssp_dev,data); +} + +unsigned long corgi_ssp_ads7846_get(void) +{ + return ssp_read_word(&corgi_ssp_dev); +} + +EXPORT_SYMBOL(corgi_ssp_ads7846_putget); +EXPORT_SYMBOL(corgi_ssp_ads7846_lock); +EXPORT_SYMBOL(corgi_ssp_ads7846_unlock); +EXPORT_SYMBOL(corgi_ssp_ads7846_put); +EXPORT_SYMBOL(corgi_ssp_ads7846_get); + + +/* + * LCD/Backlight Routines + */ +unsigned long corgi_ssp_dac_put(ulong data) +{ + unsigned long flag; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76)); + ssp_enable(&corgi_ssp_dev); + + ssp_write_word(&corgi_ssp_dev,data); + /* Read null data back from device to prevent SSP overflow */ + ssp_read_word(&corgi_ssp_dev); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + return 0; +} + +void corgi_ssp_lcdtg_send(u8 adrs, u8 data) +{ + corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f)); +} + +void corgi_ssp_blduty_set(int duty) +{ + corgi_ssp_lcdtg_send(0x02,duty); +} + +EXPORT_SYMBOL(corgi_ssp_lcdtg_send); +EXPORT_SYMBOL(corgi_ssp_blduty_set); + +/* + * Max1111 Routines + */ +int corgi_ssp_max1111_get(ulong data) +{ + unsigned long flag; + int voltage,voltage1,voltage2; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8)); + ssp_enable(&corgi_ssp_dev); + + udelay(1); + + /* TB1/RB1 */ + ssp_write_word(&corgi_ssp_dev,data); + ssp_read_word(&corgi_ssp_dev); /* null read */ + + /* TB12/RB2 */ + ssp_write_word(&corgi_ssp_dev,0); + voltage1=ssp_read_word(&corgi_ssp_dev); + + /* TB13/RB3*/ + ssp_write_word(&corgi_ssp_dev,0); + voltage2=ssp_read_word(&corgi_ssp_dev); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + if (voltage1 & 0xc0 || voltage2 & 0x3f) + voltage = -1; + else + voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03); + + return voltage; +} + +EXPORT_SYMBOL(corgi_ssp_max1111_get); + +/* + * Support Routines + */ +int __init corgi_ssp_probe(struct device *dev) +{ + int ret; + + /* Chip Select - Disable All */ + GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */ + GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/ + GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/ + + ret=ssp_init(&corgi_ssp_dev,1); + + if (ret) + printk(KERN_ERR "Unable to register SSP handler!\n"); + else { + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + } + + return ret; +} + +static int corgi_ssp_remove(struct device *dev) +{ + ssp_exit(&corgi_ssp_dev); + return 0; +} + +static int corgi_ssp_suspend(struct device *dev, u32 state, u32 level) +{ + if (level == SUSPEND_POWER_DOWN) { + ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state); + } + return 0; +} + +static int corgi_ssp_resume(struct device *dev, u32 level) +{ + if (level == RESUME_POWER_ON) { + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */ + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/ + ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); + ssp_enable(&corgi_ssp_dev); + } + return 0; +} + +static struct device_driver corgissp_driver = { + .name = "corgi-ssp", + .bus = &platform_bus_type, + .probe = corgi_ssp_probe, + .remove = corgi_ssp_remove, + .suspend = corgi_ssp_suspend, + .resume = corgi_ssp_resume, +}; + +int __init corgi_ssp_init(void) +{ + return driver_register(&corgissp_driver); +} + +arch_initcall(corgi_ssp_init); diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h index 9cfd9c47b366..9de52f035ba6 100644 --- a/include/asm-arm/arch-pxa/corgi.h +++ b/include/asm-arm/arch-pxa/corgi.h @@ -15,29 +15,31 @@ /* - * Corgi GPIO definitions + * Corgi (Non Standard) GPIO Definitions */ -#define CORGI_GPIO_KEY_INT (0) /* key interrupt */ +#define CORGI_GPIO_KEY_INT (0) /* Keyboard Interrupt */ #define CORGI_GPIO_AC_IN (1) #define CORGI_GPIO_WAKEUP (3) -#define CORGI_GPIO_AK_INT (4) // Remote Controller -#define CORGI_GPIO_TP_INT (5) /* Touch Panel interrupt */ -#define CORGI_GPIO_nSD_CLK (6) +#define CORGI_GPIO_AK_INT (4) /* IR Controller Interrupt */ +#define CORGI_GPIO_TP_INT (5) /* Touch Panel Interrupt */ #define CORGI_GPIO_nSD_WP (7) -#define CORGI_GPIO_nSD_DETECT (9) +#define CORGI_GPIO_nSD_DETECT (9) /* MMC/SD Card Detect */ #define CORGI_GPIO_nSD_INT (10) #define CORGI_GPIO_MAIN_BAT_LOW (11) #define CORGI_GPIO_BAT_COVER (11) #define CORGI_GPIO_LED_ORANGE (13) -#define CORGI_GPIO_CF_CD (14) +#define CORGI_GPIO_CF_CD (14) /* Compact Flash Card Detect */ #define CORGI_GPIO_CHRG_FULL (16) -#define CORGI_GPIO_CF_IRQ (17) +#define CORGI_GPIO_CF_IRQ (17) /* Compact Flash Interrupt */ +#define CORGI_GPIO_LCDCON_CS (19) /* LCD Control Chip Select */ +#define CORGI_GPIO_MAX1111_CS (20) /* MAX111 Chip Select */ #define CORGI_GPIO_ADC_TEMP_ON (21) #define CORGI_GPIO_IR_ON (22) -#define CORGI_GPIO_SD_PWR (33) +#define CORGI_GPIO_ADS7846_CS (24) /* ADS7846 Chip Select */ +#define CORGI_GPIO_SD_PWR (33) /* MMC/SD Power */ #define CORGI_GPIO_CHRG_ON (38) #define CORGI_GPIO_DISCHARGE_ON (42) -#define CORGI_GPIO_HSYNC (44) +#define CORGI_GPIO_HSYNC (44) /* LCD HSync Pulse */ #define CORGI_GPIO_USB_PULLUP (45) -- cgit v1.2.3 From bfc52a39f05cf3c661d9b0ca5a98aef6e6a97f50 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 12 Jan 2005 19:52:49 +0000 Subject: [ARM] Add missing tlb_migrate_finish() Signed-off-by: Russell King --- include/asm-arm/tlb.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h index ab3cad4fb53d..0843a876b3ce 100644 --- a/include/asm-arm/tlb.h +++ b/include/asm-arm/tlb.h @@ -91,4 +91,6 @@ tlb_is_full_mm(struct mmu_gather *tlb) #define pte_free_tlb(tlb,ptep) pte_free(ptep) #define pmd_free_tlb(tlb,pmdp) pmd_free(pmdp) +#define tlb_migrate_finish(mm) do { } while (0) + #endif -- cgit v1.2.3 From 80ce63d3a9a3ca3bcd0232caeb3bfb127af5ad35 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 12 Jan 2005 17:00:45 -0800 Subject: [PATCH] possible rq starvation on oom I stumbled across this the other day. The block layer only uses a single memory pool for request allocation, so it's very possible for eg writes to have allocated them all at any point in time. If that is the case and the machine is low on memory, a reader attempting to allocate a request and failing in blk_alloc_request() can get stuck for a long time since no one is there to wake it up. The solution is either to add the extra mempool so both reads and writes have one, or attempt to handle the situation. I chose the latter, to save the extra memory required for the additional mempool with BLKDEV_MIN_RQ statically allocated requests per-queue. If a read allocation fails and we have no readers in flight for this queue, mark us rq-starved so that the next write being freed will wake up the sleeping reader(s). Same situation would happen for writes as well of course, it's just a lot more unlikely. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 51 +++++++++++++++++++++++++++++++++++++---------- include/linux/blkdev.h | 1 + 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 98db1776ba31..3994af7e555b 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1438,6 +1438,7 @@ static int blk_init_free_list(request_queue_t *q) struct request_list *rl = &q->rq; rl->count[READ] = rl->count[WRITE] = 0; + rl->starved[READ] = rl->starved[WRITE] = 0; init_waitqueue_head(&rl->wait[READ]); init_waitqueue_head(&rl->wait[WRITE]); init_waitqueue_head(&rl->drain); @@ -1618,6 +1619,22 @@ void ioc_set_batching(request_queue_t *q, struct io_context *ioc) ioc->last_waited = jiffies; } +static void __freed_request(request_queue_t *q, int rw) +{ + struct request_list *rl = &q->rq; + + if (rl->count[rw] < queue_congestion_off_threshold(q)) + clear_queue_congested(q, rw); + + if (rl->count[rw] + 1 <= q->nr_requests) { + smp_mb(); + if (waitqueue_active(&rl->wait[rw])) + wake_up(&rl->wait[rw]); + + blk_clear_queue_full(q, rw); + } +} + /* * A request has just been released. Account for it, update the full and * congestion status, wake up any waiters. Called under q->queue_lock. @@ -1627,17 +1644,17 @@ static void freed_request(request_queue_t *q, int rw) struct request_list *rl = &q->rq; rl->count[rw]--; - if (rl->count[rw] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, rw); - if (rl->count[rw]+1 <= q->nr_requests) { + + __freed_request(q, rw); + + if (unlikely(rl->starved[rw ^ 1])) + __freed_request(q, rw ^ 1); + + if (!rl->count[READ] && !rl->count[WRITE]) { smp_mb(); - if (waitqueue_active(&rl->wait[rw])) - wake_up(&rl->wait[rw]); - blk_clear_queue_full(q, rw); + if (unlikely(waitqueue_active(&rl->drain))) + wake_up(&rl->drain); } - if (unlikely(waitqueue_active(&rl->drain)) && - !rl->count[READ] && !rl->count[WRITE]) - wake_up(&rl->drain); } #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) @@ -1669,8 +1686,7 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) switch (elv_may_queue(q, rw)) { case ELV_MQUEUE_NO: - spin_unlock_irq(q->queue_lock); - goto out; + goto rq_starved; case ELV_MQUEUE_MAY: break; case ELV_MQUEUE_MUST: @@ -1688,6 +1704,7 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) get_rq: rl->count[rw]++; + rl->starved[rw] = 0; if (rl->count[rw] >= queue_congestion_on_threshold(q)) set_queue_congested(q, rw); spin_unlock_irq(q->queue_lock); @@ -1703,6 +1720,18 @@ get_rq: */ spin_lock_irq(q->queue_lock); freed_request(q, rw); + + /* + * in the very unlikely event that allocation failed and no + * requests for this direction was pending, mark us starved + * so that freeing of a request in the other direction will + * notice us. another possible fix would be to split the + * rq mempool into READ and WRITE + */ +rq_starved: + if (unlikely(rl->count[rw] == 0)) + rl->starved[rw] = 1; + spin_unlock_irq(q->queue_lock); goto out; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 1b7dc44bf3c1..5615a3c9e410 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -95,6 +95,7 @@ void swap_io_context(struct io_context **ioc1, struct io_context **ioc2); struct request_list { int count[2]; + int starved[2]; mempool_t *rq_pool; wait_queue_head_t wait[2]; wait_queue_head_t drain; -- cgit v1.2.3 From ec72859c7038f7d037509ee6ae851dbe80af2343 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 12 Jan 2005 17:00:59 -0800 Subject: [PATCH] PPC64 Disable preemption in flush_tlb_pending The preempt debug stuff found a place where we were using smp_processor_id() without having preemption disabled, in flush_tlb_pending. This patch fixes it by using get_cpu_var and put_cpu_var instead of the __get_cpu_var variant. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- include/asm-ppc64/tlbflush.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h index 183bdfba9f0c..45411a67e082 100644 --- a/include/asm-ppc64/tlbflush.h +++ b/include/asm-ppc64/tlbflush.h @@ -32,10 +32,11 @@ extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); static inline void flush_tlb_pending(void) { - struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); if (batch->index) __flush_tlb_pending(batch); + put_cpu_var(ppc64_tlb_batch); } #define flush_tlb_mm(mm) flush_tlb_pending() -- cgit v1.2.3 From 44462c19a68f0b93c8c8503d6c2afa673994ad4a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 12 Jan 2005 17:01:24 -0800 Subject: [PATCH] PPC64 can do preempt debug too This patch enables the DEBUG_PREEMPT config option for PPC64. I have this turned on on my desktop G5 and it isn't finding any problems. (It did find one problem, in flush_tlb_pending(), that I have just sent a patch for.) BTW, do we really need to restrict which architectures the config option is available on? Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- include/asm-ppc64/smp.h | 2 +- lib/Kconfig.debug | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h index 6121d21355bc..965980bbbb57 100644 --- a/include/asm-ppc64/smp.h +++ b/include/asm-ppc64/smp.h @@ -38,7 +38,7 @@ struct pt_regs; extern void smp_message_recv(int, struct pt_regs *); -#define smp_processor_id() (get_paca()->paca_index) +#define __smp_processor_id() (get_paca()->paca_index) #define hard_smp_processor_id() (get_paca()->hw_cpu_id) extern cpumask_t cpu_sibling_map[NR_CPUS]; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index aba7f11a25ac..d2e2d705585e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -50,7 +50,7 @@ config DEBUG_SLAB config DEBUG_PREEMPT bool "Debug preemptible kernel" - depends on PREEMPT && X86 + depends on PREEMPT && (X86 || PPC64) default y help If you say Y here then the kernel will use a debug variant of the -- cgit v1.2.3 From de10f9d45f6836709d77629cda7ad4e743e32cbe Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 12 Jan 2005 17:01:51 -0800 Subject: [PATCH] PPC64 Move thread_info flags to its own cache line This patch fixes a problem I have been seeing since all the preempt changes went in, which is that ppc64 SMP systems would livelock randomly if preempt was enabled. It turns out that what was happening was that one cpu was spinning in spin_lock_irq (the version at line 215 of kernel/spinlock.c) madly doing preempt_enable() and preempt_disable() calls. The other cpu had the lock and was trying to set the TIF_NEED_RESCHED flag for the task running on the first cpu. That is an atomic operation which has to be retried if another cpu writes to the same cacheline between the load and the store, which the other cpu was doing every time it did preempt_enable() or preempt_disable(). I decided to move the thread_info flags field into the next cache line, since it is the only field that would regularly be modified by cpus other than the one running the task that owns the thread_info. (OK possibly the `cpu' field would be on a rebalance; I don't know the rebalancing code, but that should be pretty infrequent.) Thus, moving the flags field seems like a good idea generally as well as solving the immediate problem. For the record I am pretty unhappy with the code we use for spin_lock et al. with preemption turned on (the BUILD_LOCK_OPS stuff in spinlock.c). For a start we do the atomic op (_raw_spin_trylock) each time around the loop. That is going to be generating a lot of unnecessary bus (or fabric) traffic. Instead, after we fail to get the lock we should poll it with simple loads until we see that it is clear and then retry the atomic op. Assuming a reasonable cache design, the loads won't generate any bus traffic until another cpu writes to the cacheline containing the lock. Secondly we have lost the __spin_yield call that we had on ppc64, which is an important optimization when we are running under the hypervisor. I can't just put that in cpu_relax because I need to know which (virtual) cpu is holding the lock, so that I can tell the hypervisor which virtual cpu to give my time slice to. That information is stored in the lock variable, which is why __spin_yield needs the address of the lock. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- include/asm-ppc64/thread_info.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h index 595d67ef4b6f..e823d119ffcf 100644 --- a/include/asm-ppc64/thread_info.h +++ b/include/asm-ppc64/thread_info.h @@ -12,6 +12,7 @@ #ifndef __ASSEMBLY__ #include +#include #include #include #include @@ -22,12 +23,13 @@ struct thread_info { struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ - unsigned long flags; /* low level flags */ int cpu; /* cpu we're on */ int preempt_count; struct restart_block restart_block; /* set by force_successful_syscall_return */ unsigned char syscall_noerror; + /* low level flags - has atomic operations done on it */ + unsigned long flags ____cacheline_aligned_in_smp; }; /* @@ -39,12 +41,12 @@ struct thread_info { { \ .task = &tsk, \ .exec_domain = &default_exec_domain, \ - .flags = 0, \ .cpu = 0, \ .preempt_count = 1, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ + .flags = 0, \ } #define init_thread_info (init_thread_union.thread_info) -- cgit v1.2.3