From 02d5e6ec7786e58678859c8f99c45ce72087be13 Mon Sep 17 00:00:00 2001 From: Planet-Lab Support Date: Wed, 16 Jun 2004 18:15:59 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'before-fedora-2_6_6-1_406-merge'. --- Documentation/COPYING.modules | 708 -------- Documentation/fb/pxafb.txt | 54 - Documentation/filesystems/relayfs.txt | 812 --------- Documentation/numastat.txt | 22 - Documentation/sched-domains.txt | 55 - Documentation/scsi/sym53c500_cs.txt | 23 - arch/arm/mach-ixp4xx/Kconfig | 89 - arch/arm/mach-ixp4xx/coyote-setup.c | 90 - arch/arm/mach-ixp4xx/ixdp425-setup.c | 147 -- arch/arm/mach-pxa/leds-mainstone.c | 118 -- arch/arm/mach-pxa/mainstone.c | 139 -- arch/arm/mach-pxa/pxa25x.c | 94 - arch/arm/mach-pxa/pxa27x.c | 120 -- arch/h8300/Kconfig.cpu | 183 -- arch/h8300/kernel/module.c | 122 -- arch/i386/kernel/entry_trampoline.c | 75 - arch/i386/mach-es7000/es7000plat.c | 304 ---- arch/ia64/scripts/check-serialize.S | 2 - arch/ppc/configs/bubinga_defconfig | 593 ------- arch/ppc/syslib/ibm_ocp.c | 9 - arch/um/drivers/cow.h | 41 - arch/um/drivers/cow_user.c | 375 ---- arch/um/include/irq_kern.h | 28 - arch/um/include/mem_kern.h | 30 - arch/um/kernel/physmem.c | 468 ----- arch/um/kernel/skas/uaccess.c | 219 --- arch/um/kernel/tt/uaccess.c | 73 - arch/um/os-Linux/user_syms.c | 88 - arch/x86_64/kernel/Makefile-HEAD | 38 - drivers/ide/arm/ide_arm.c | 43 - drivers/net/ibm_emac/Makefile | 12 - drivers/net/ibm_emac/ibm_emac_core.c | 1968 --------------------- drivers/net/ibm_emac/ibm_emac_phy.h | 137 -- drivers/net/wan/wanxlfw.inc_shipped | 158 -- drivers/pcmcia/pxa2xx_base.c | 333 ---- drivers/pcmcia/pxa2xx_lubbock.c | 236 --- drivers/pcmcia/pxa2xx_mainstone.c | 176 -- drivers/pcmcia/sa11xx_base.c | 242 --- drivers/pcmcia/sa11xx_base.h | 123 -- drivers/pcmcia/soc_common.c | 797 --------- drivers/pcmcia/soc_common.h | 186 -- drivers/scsi/qlogicfas408.c | 637 ------- drivers/scsi/sata_sx4.c | 1446 --------------- drivers/video/pxafb.c | 1381 --------------- fs/ext3/resize.c | 956 ---------- fs/hostfs/Makefile | 26 - fs/hostfs/hostfs.h | 79 - fs/hostfs/hostfs_kern.c | 1008 ----------- fs/hostfs/hostfs_user.c | 361 ---- fs/hppfs/Makefile | 19 - fs/hppfs/hppfs_kern.c | 811 --------- fs/rcfs/Makefile | 10 - fs/rcfs/dir.c | 336 ---- fs/rcfs/inode.c | 204 --- fs/rcfs/magic.c | 546 ------ fs/rcfs/rootdir.c | 244 --- fs/rcfs/socket_fs.c | 338 ---- fs/rcfs/super.c | 288 --- fs/rcfs/tc_magic.c | 94 - fs/reiserfs/xattr_security.c | 69 - fs/reiserfs/xattr_trusted.c | 81 - fs/reiserfs/xattr_user.c | 99 -- fs/relayfs/Makefile | 8 - fs/relayfs/inode.c | 629 ------- fs/relayfs/klog.c | 206 --- fs/relayfs/relay.c | 1911 -------------------- fs/relayfs/relay_locking.c | 322 ---- fs/relayfs/relay_locking.h | 34 - fs/relayfs/relay_lockless.c | 541 ------ fs/relayfs/relay_lockless.h | 34 - fs/relayfs/resize.c | 1091 ------------ fs/relayfs/resize.h | 51 - fs/xfs/linux-2.6/mutex.h | 53 - fs/xfs/linux-2.6/spin.h | 56 - fs/xfs/linux-2.6/time.h | 51 - fs/xfs/linux-2.6/xfs_cred.h | 50 - fs/xfs/linux-2.6/xfs_fs_subr.h | 49 - fs/xfs/linux-2.6/xfs_globals.h | 44 - fs/xfs/linux-2.6/xfs_iops.c | 710 -------- fs/xfs/linux-2.6/xfs_stats.h | 164 -- fs/xfs/linux-2.6/xfs_version.h | 44 - include/asm-alpha/8253pit.h | 10 - include/asm-alpha/relay.h | 5 - include/asm-arm/arch-ixp4xx/coyote.h | 36 - include/asm-arm/arch-ixp4xx/hardware.h | 41 - include/asm-arm/arch-ixp4xx/irqs.h | 78 - include/asm-arm/arch-ixp4xx/ixdp425.h | 38 - include/asm-arm/arch-ixp4xx/ixp4xx-regs.h | 551 ------ include/asm-arm/arch-ixp4xx/prpmc1100.h | 33 - include/asm-arm/arch-ixp4xx/timex.h | 13 - include/asm-arm/arch-ixp4xx/vmalloc.h | 17 - include/asm-arm/arch-pxa/mainstone.h | 120 -- include/asm-arm/relay.h | 5 - include/asm-arm26/relay.h | 5 - include/asm-cris/local.h | 1 - include/asm-cris/relay.h | 5 - include/asm-cris/sections.h | 7 - include/asm-generic/relay.h | 76 - include/asm-h8300/relay.h | 5 - include/asm-i386/8253pit.h | 12 - include/asm-i386/relay.h | 101 -- include/asm-ia64/cpu.h | 17 - include/asm-ia64/relay.h | 5 - include/asm-m68k/relay.h | 5 - include/asm-m68knommu/relay.h | 5 - include/asm-mips/8253pit.h | 10 - include/asm-mips/pmon.h | 22 - include/asm-mips/relay.h | 5 - include/asm-mips64/relay.h | 5 - include/asm-parisc/relay.h | 5 - include/asm-parisc/unwind.h | 72 - include/asm-ppc/ibm_ocp.h | 163 -- include/asm-ppc/relay.h | 5 - include/asm-ppc64/relay.h | 5 - include/asm-s390/relay.h | 5 - include/asm-sh/relay.h | 5 - include/asm-sparc/relay.h | 5 - include/asm-sparc64/const.h | 19 - include/asm-sparc64/relay.h | 5 - include/asm-um/cpufeature.h | 6 - include/asm-um/local.h | 6 - include/asm-um/module-generic.h | 6 - include/asm-um/sections.h | 7 - include/asm-v850/relay.h | 5 - include/asm-x86_64/8253pit.h | 10 - include/asm-x86_64/relay.h | 5 - include/linux/ckrm.h | 156 -- include/linux/ckrm_ce.h | 91 - include/linux/ckrm_net.h | 41 - include/linux/ckrm_rc.h | 367 ---- include/linux/ckrm_tc.h | 18 - include/linux/ckrm_tsk.h | 41 - include/linux/klog.h | 24 - include/linux/prio_tree.h | 64 - include/linux/rcfs.h | 98 - include/linux/relayfs_fs.h | 686 ------- include/linux/taskdelays.h | 20 - include/video/gbe.h | 317 ---- kernel/ckrm/Makefile | 14 - kernel/ckrm/ckrm.c | 1009 ----------- kernel/ckrm/ckrm_listenaq.c | 503 ------ kernel/ckrm/ckrm_sockc.c | 554 ------ kernel/ckrm/ckrm_tasks.c | 509 ------ kernel/ckrm/ckrm_tc.c | 785 -------- kernel/ckrm/ckrmutils.c | 207 --- mm/mempolicy.c | 1015 ----------- mm/prio_tree.c | 663 ------- net/bridge/br_sysfs_if.c | 269 --- scripts/reference_discarded.pl | 109 -- 149 files changed, 33738 deletions(-) delete mode 100644 Documentation/COPYING.modules delete mode 100644 Documentation/fb/pxafb.txt delete mode 100644 Documentation/filesystems/relayfs.txt delete mode 100644 Documentation/numastat.txt delete mode 100644 Documentation/sched-domains.txt delete mode 100644 Documentation/scsi/sym53c500_cs.txt delete mode 100644 arch/arm/mach-ixp4xx/Kconfig delete mode 100644 arch/arm/mach-ixp4xx/coyote-setup.c delete mode 100644 arch/arm/mach-ixp4xx/ixdp425-setup.c delete mode 100644 arch/arm/mach-pxa/leds-mainstone.c delete mode 100644 arch/arm/mach-pxa/mainstone.c delete mode 100644 arch/arm/mach-pxa/pxa25x.c delete mode 100644 arch/arm/mach-pxa/pxa27x.c delete mode 100644 arch/h8300/Kconfig.cpu delete mode 100644 arch/h8300/kernel/module.c delete mode 100644 arch/i386/kernel/entry_trampoline.c delete mode 100644 arch/i386/mach-es7000/es7000plat.c delete mode 100644 arch/ia64/scripts/check-serialize.S delete mode 100644 arch/ppc/configs/bubinga_defconfig delete mode 100644 arch/ppc/syslib/ibm_ocp.c delete mode 100644 arch/um/drivers/cow.h delete mode 100644 arch/um/drivers/cow_user.c delete mode 100644 arch/um/include/irq_kern.h delete mode 100644 arch/um/include/mem_kern.h delete mode 100644 arch/um/kernel/physmem.c delete mode 100644 arch/um/kernel/skas/uaccess.c delete mode 100644 arch/um/kernel/tt/uaccess.c delete mode 100644 arch/um/os-Linux/user_syms.c delete mode 100644 arch/x86_64/kernel/Makefile-HEAD delete mode 100644 drivers/ide/arm/ide_arm.c delete mode 100644 drivers/net/ibm_emac/Makefile delete mode 100644 drivers/net/ibm_emac/ibm_emac_core.c delete mode 100644 drivers/net/ibm_emac/ibm_emac_phy.h delete mode 100644 drivers/net/wan/wanxlfw.inc_shipped delete mode 100644 drivers/pcmcia/pxa2xx_base.c delete mode 100644 drivers/pcmcia/pxa2xx_lubbock.c delete mode 100644 drivers/pcmcia/pxa2xx_mainstone.c delete mode 100644 drivers/pcmcia/sa11xx_base.c delete mode 100644 drivers/pcmcia/sa11xx_base.h delete mode 100644 drivers/pcmcia/soc_common.c delete mode 100644 drivers/pcmcia/soc_common.h delete mode 100644 drivers/scsi/qlogicfas408.c delete mode 100644 drivers/scsi/sata_sx4.c delete mode 100644 drivers/video/pxafb.c delete mode 100644 fs/ext3/resize.c delete mode 100644 fs/hostfs/Makefile delete mode 100644 fs/hostfs/hostfs.h delete mode 100644 fs/hostfs/hostfs_kern.c delete mode 100644 fs/hostfs/hostfs_user.c delete mode 100644 fs/hppfs/Makefile delete mode 100644 fs/hppfs/hppfs_kern.c delete mode 100644 fs/rcfs/Makefile delete mode 100644 fs/rcfs/dir.c delete mode 100644 fs/rcfs/inode.c delete mode 100644 fs/rcfs/magic.c delete mode 100644 fs/rcfs/rootdir.c delete mode 100644 fs/rcfs/socket_fs.c delete mode 100644 fs/rcfs/super.c delete mode 100644 fs/rcfs/tc_magic.c delete mode 100644 fs/reiserfs/xattr_security.c delete mode 100644 fs/reiserfs/xattr_trusted.c delete mode 100644 fs/reiserfs/xattr_user.c delete mode 100644 fs/relayfs/Makefile delete mode 100644 fs/relayfs/inode.c delete mode 100644 fs/relayfs/klog.c delete mode 100644 fs/relayfs/relay.c delete mode 100644 fs/relayfs/relay_locking.c delete mode 100644 fs/relayfs/relay_locking.h delete mode 100644 fs/relayfs/relay_lockless.c delete mode 100644 fs/relayfs/relay_lockless.h delete mode 100644 fs/relayfs/resize.c delete mode 100644 fs/relayfs/resize.h delete mode 100644 fs/xfs/linux-2.6/mutex.h delete mode 100644 fs/xfs/linux-2.6/spin.h delete mode 100644 fs/xfs/linux-2.6/time.h delete mode 100644 fs/xfs/linux-2.6/xfs_cred.h delete mode 100644 fs/xfs/linux-2.6/xfs_fs_subr.h delete mode 100644 fs/xfs/linux-2.6/xfs_globals.h delete mode 100644 fs/xfs/linux-2.6/xfs_iops.c delete mode 100644 fs/xfs/linux-2.6/xfs_stats.h delete mode 100644 fs/xfs/linux-2.6/xfs_version.h delete mode 100644 include/asm-alpha/8253pit.h delete mode 100644 include/asm-alpha/relay.h delete mode 100644 include/asm-arm/arch-ixp4xx/coyote.h delete mode 100644 include/asm-arm/arch-ixp4xx/hardware.h delete mode 100644 include/asm-arm/arch-ixp4xx/irqs.h delete mode 100644 include/asm-arm/arch-ixp4xx/ixdp425.h delete mode 100644 include/asm-arm/arch-ixp4xx/ixp4xx-regs.h delete mode 100644 include/asm-arm/arch-ixp4xx/prpmc1100.h delete mode 100644 include/asm-arm/arch-ixp4xx/timex.h delete mode 100644 include/asm-arm/arch-ixp4xx/vmalloc.h delete mode 100644 include/asm-arm/arch-pxa/mainstone.h delete mode 100644 include/asm-arm/relay.h delete mode 100644 include/asm-arm26/relay.h delete mode 100644 include/asm-cris/local.h delete mode 100644 include/asm-cris/relay.h delete mode 100644 include/asm-cris/sections.h delete mode 100644 include/asm-generic/relay.h delete mode 100644 include/asm-h8300/relay.h delete mode 100644 include/asm-i386/8253pit.h delete mode 100644 include/asm-i386/relay.h delete mode 100644 include/asm-ia64/cpu.h delete mode 100644 include/asm-ia64/relay.h delete mode 100644 include/asm-m68k/relay.h delete mode 100644 include/asm-m68knommu/relay.h delete mode 100644 include/asm-mips/8253pit.h delete mode 100644 include/asm-mips/pmon.h delete mode 100644 include/asm-mips/relay.h delete mode 100644 include/asm-mips64/relay.h delete mode 100644 include/asm-parisc/relay.h delete mode 100644 include/asm-parisc/unwind.h delete mode 100644 include/asm-ppc/ibm_ocp.h delete mode 100644 include/asm-ppc/relay.h delete mode 100644 include/asm-ppc64/relay.h delete mode 100644 include/asm-s390/relay.h delete mode 100644 include/asm-sh/relay.h delete mode 100644 include/asm-sparc/relay.h delete mode 100644 include/asm-sparc64/const.h delete mode 100644 include/asm-sparc64/relay.h delete mode 100644 include/asm-um/cpufeature.h delete mode 100644 include/asm-um/local.h delete mode 100644 include/asm-um/module-generic.h delete mode 100644 include/asm-um/sections.h delete mode 100644 include/asm-v850/relay.h delete mode 100644 include/asm-x86_64/8253pit.h delete mode 100644 include/asm-x86_64/relay.h delete mode 100644 include/linux/ckrm.h delete mode 100644 include/linux/ckrm_ce.h delete mode 100644 include/linux/ckrm_net.h delete mode 100644 include/linux/ckrm_rc.h delete mode 100644 include/linux/ckrm_tc.h delete mode 100644 include/linux/ckrm_tsk.h delete mode 100644 include/linux/klog.h delete mode 100644 include/linux/prio_tree.h delete mode 100644 include/linux/rcfs.h delete mode 100644 include/linux/relayfs_fs.h delete mode 100644 include/linux/taskdelays.h delete mode 100644 include/video/gbe.h delete mode 100644 kernel/ckrm/Makefile delete mode 100644 kernel/ckrm/ckrm.c delete mode 100644 kernel/ckrm/ckrm_listenaq.c delete mode 100644 kernel/ckrm/ckrm_sockc.c delete mode 100644 kernel/ckrm/ckrm_tasks.c delete mode 100644 kernel/ckrm/ckrm_tc.c delete mode 100644 kernel/ckrm/ckrmutils.c delete mode 100644 mm/mempolicy.c delete mode 100644 mm/prio_tree.c delete mode 100644 net/bridge/br_sysfs_if.c delete mode 100644 scripts/reference_discarded.pl diff --git a/Documentation/COPYING.modules b/Documentation/COPYING.modules deleted file mode 100644 index da0266e78..000000000 --- a/Documentation/COPYING.modules +++ /dev/null @@ -1,708 +0,0 @@ -Date: Thu, 29 Apr 2004 14:10:41 -0700 (PDT) -From: Linus Torvalds -To: Giuliano Colla -cc: Linux Kernel Mailing List -Subject: Re: [hsflinux] [PATCH] Blacklist binary-only modules lying about - their license -Message-ID: - -On Thu, 29 Apr 2004, Giuliano Colla wrote: -> -> Let's try not to be ridiculous, please. - -It's not abotu being ridiculous. It's about honoring peoples copyrights. - -> As an end user, if I buy a full fledged modem, I get some amount of -> proprietary, non GPL, code which executes within the board or the -> PCMCIA card of the modem. The GPL driver may even support the -> functionality of downloading a new version of *proprietary* code into -> the flash Eprom of the device. The GPL linux driver interfaces with it, -> and all is kosher. - -Indeed. Everything is kosher, because the other piece of hardware and -software has _nothing_ to do with the kernel. It's not linked into it, it -cannot reasonably corrupt internal kernel data structures with random -pointer bugs, and in general you can think of firmware as part of the -_hardware_, not the software of the machine. - -> On the other hand, I have the misfortune of being stuck with a -> soft-modem, roughly the *same* proprietary code is provided as a binary -> file, and a linux driver (source provided) interfaces with it. In that -> case the kernel is flagged as "tainted". - -It is flagged as tainted, because your argument that it is "the same code" -is totally BOGUS AND UNTRUE! - -In the binary kernel module case, a bug in the code corrupts random data -structures, or accesses kernel internals without holding the proper locks, -or does a million other things wrong, BECAUSE A KERNEL MODULE IS VERY -INTIMATELY LINKED WITH THE KERNEL. - -A kernel module is _not_ a separate work, and can in _no_ way be seen as -"part of the hardware". It's very much a part of the _kernel_. And the -kernel developers require that such code be GPL'd so that it can be fixed, -or if there's a valid argument that it's not a derived work and not GPL'd, -then the kernel developers who have to support the end result mess most -definitely do need to know about the taint. - -You are not the first (and sadly, you likely won't be the last) person to -equate binary kernel modules with binary firmware. And I tell you that -such a comparison is ABSOLUTE CRAPOLA. There's a damn big difference -between running firmware on another chip behind a PCI bus, and linking -into the kernel directly. - -And if you don't see that difference, then you are either terminally -stupid, or you have some ulterior reason to claim that they are the same -case even though they clearly are NOT. - -> Can you honestly tell apart the two cases, if you don't make a it a case -> of "religion war"? - -It has absolutely nothing to do with religion. - - Linus - -Date: Fri, 5 Dec 2003 09:19:52 -0800 (PST) -From: Linus Torvalds -To: Peter Chubb -cc: linux-kernel@vger.kernel.org -Subject: Re: Linux GPL and binary module exception clause? -Message-ID: - -On Fri, 5 Dec 2003, Peter Chubb wrote: -> -> As I understand it, SCO is/was claiming that JFS and XFS are derived -> works of the UNIX source base, because they were developed to match -> the internal interfaces of UNIX, and with knowledge of the internals -> of UNIX -- and they hold the copyrights of and are the licensor of UNIX. - -Yes, and I'm not claiming anything like that. - -I claim that a "binary linux kernel module" is a derived work of the -kernel, and thus has to come with sources. - -But if you use those same sources (and _you_ wrote them) they do not -contain any Linux code, they are _clearly_ not derived from Linux, and you -can license and use your own code any way you want. - -You just can't make a binary module for Linux, and claim that that module -isn't derived from the kernel. Because it generally is - the binary -module not only included header files, but more importantly it clearly is -_not_ a standalone work any more. So even if you made your own prototypes -and tried hard to avoid kernel headers, it would _still_ be connected and -dependent on the kernel. - -And note that I'm very much talking about just the _binary_. Your source -code is still very much yours, and you have the right to distribute it -separately any which way you want. You wrote it, you own the copyrights to -it, and it is an independent work. - -But when you distribute it in a way that is CLEARLY tied to the GPL'd -kernel (and a binary module is just one such clear tie - a "patch" to -build it or otherwise tie it to the kernel is also such a tie, even if you -distribute it as source under some other license), you're BY DEFINITION -not an independent work any more. - -(But exactly because I'm not a black-and-white person, I reserve the right -to make a balanced decision on any particular case. I have several times -felt that the module author had a perfectly valid argument for why the -"default assumption" of being derived wasn't the case. That's why things -like the AFS module were accepted - but not liked - in the first place). - -This is why SCO's arguments are specious. IBM wrote their code, retained -their copyrights to their code AND THEY SEVERED THE CONNECTION TO SCO'S -CODE (and, arguably the connections didn't even exist in the first place, -since apparently things like JFS were written for OS/2 as well, and the -Linux port was based on that one - but that's a separate argument and -independent of my point). - -See the definition of "derivative" in USC 17.1.101: - - A "derivative work" is a work based upon one or more preexisting - works, such as a translation, musical arrangement, dramatization, - fictionalization, motion picture version, sound recording, art - reproduction, abridgment, condensation, or any other form in which - a work may be recast, transformed, or adapted. A work consisting - of editorial revisions, annotations, elaborations, or other - modifications which, as a whole, represent an original work of - authorship, is a "derivative work". - -And a binary module is an "elaboration" on the kernel. Sorry, but that is -how it IS. - -In short: your code is yours. The code you write is automatically -copyrighted by YOU, and as such you have the right to license and use it -any way you want (well, modulo _other_ laws, of course - in the US your -license can't be racist, for example, but that has nothing to do with -copyright laws, and would fall under a totally different legal framework). - -But when you use that code to create an "elaboration" to the kernel, that -makes it a derived work, and you cannot distribute it except as laid out -by the GPL. A binary module is one such case, but even just a source patch -is _also_ one such case. The lines you added are yours, but when you -distribute it as an elaboration, you are bound by the restriction on -derivative works. - -Or you had better have some other strong argument why it isn't. Which has -been my point all along. - - Linus - - -Date: Wed, 10 Dec 2003 09:10:18 -0800 (PST) -From: Linus Torvalds -To: Larry McVoy -Subject: Re: Linux GPL and binary module exception clause? - -On Wed, 10 Dec 2003, Larry McVoy wrote: -> -> Which is? How is it that you can spend a page of text saying a judge doesn't -> care about technicalities and then base the rest of your argument on the -> distinction between a "plugin" and a "kernel module"? - -I'll stop arguing, since you obviously do not get it. - -I explained the technicalities to _you_, and you are a technical person. - -But if you want to explain something to a judge, you get a real lawyer, -and you make sure that the lawyer tries to explain the issue in _non_ -technical terms. Because, quite frankly, the judge is not going to buy a -technical discussion he or she doesn't understand. - -Just as an example, how do you explain to a judge how much code the Linux -kernel contains? Do you say "it's 6 million lines of C code and header -files and documentation, for a total of about 175MB of data"? - -Yeah, maybe you'd _mention_ that, but to actually _illustrate_ the point -you'd say that if you printed it out, it would be a solid stack of papers -100 feet high. And you'd compare it to the height of the court building -you're in, or something. Maybe you'd print out _one_ file, bind it as a -book, and wave it around as one out of 15,000 files. - -But when _you_ ask me about how big the kernel is, I'd say "5 million -lines". See the difference? It would be silly for me to tell you how many -feet of paper the kernel would print out to, because we don't have those -kinds of associations. - -Similarly, if you want to explain the notion of a kernel module, you'd -compare it to maybe an extra chapter in a book. You'd make an analogy to -something that never _ever_ mentions "linking". - -Just imagine: distributing a compiled binary-only kernel module that can -be loaded into the kernel is not like distributing a new book: it's more -like distributing a extra chapter to a book that somebody else wrote, that -uses all the same characters and the plot, but more importantly it -literally can only be read _together_ with the original work. It doesn't -stand alone. - -In short, your honour, this extra chapter without any meaning on its own -is a derived work of the book. - -In contrast, maybe you can re-write your code and distribute it as a -short-story, which can be run on its own, and maybe the author has been -influenced by another book, but the short-story could be bound AS IS, and -a recipient would find it useful even without that other book. In that -case, the short story is not a derived work - it's only inspired. - -Notice? This is actually _exactly_ what I've been arguing all along, -except I've been arguing with a technical audience, so I've been using -technical examples and terminology. But my argument is that just the fact -that somebody compiled the code for Linux into a binary module that is -useless without a particular version of the kernel DOES MAKE IT A DERIVED -WORK. - -But also note how it's only the BINARY MODULE that is a derived work. Your -source code is _not_ necessarily a derived work, and if you compile it for -another operating system, I'd clearly not complain. - -This is the "stand-alone short story" vs "extra chapter without meaning -outside the book" argument. See? One is a work in its own right, the other -isn't. - - Linus - - -Please read the FAQ at http://www.tux.org/lkml/ -Date: Thu, 4 Dec 2003 22:43:42 -0800 (PST) -From: Linus Torvalds -To: David Schwartz -cc: linux-kernel@vger.kernel.org -Subject: RE: Linux GPL and binary module exception clause? - -On Thu, 4 Dec 2003, David Schwartz wrote: -> -> Yes, but they will cite the prohibition against *creating* derived -> works. - -So? - -The same prohibition exists with the GPL. You are not allowed to create -and distribute a derived work unless it is GPL'd. - -I don't see what you are arguing against. It is very clear: a kernel -module is a derived work of the kernel by default. End of story. - -You can then try to prove (through development history etc) that there -would be major reasons why it's not really derived. But your argument -seems to be that _nothing_ is derived, which is clearly totally false, as -you yourself admit when you replace "kernel" with "Harry Potter". - - Linus - -Date: Wed, 3 Dec 2003 16:00:21 -0800 (PST) -From: Linus Torvalds -To: Kendall Bennet -cc: linux-kernel@vger.kernel.org -Subject: Re: Linux GPL and binary module exception clause? - -On Wed, 3 Dec 2003, Kendall Bennett wrote: -> -> I have heard many people reference the fact that the although the Linux -> Kernel is under the GNU GPL license, that the code is licensed with an -> exception clause that says binary loadable modules do not have to be -> under the GPL. - -Nope. No such exception exists. - -There's a clarification that user-space programs that use the standard -system call interfaces aren't considered derived works, but even that -isn't an "exception" - it's just a statement of a border of what is -clearly considered a "derived work". User programs are _clearly_ not -derived works of the kernel, and as such whatever the kernel license is -just doesn't matter. - -And in fact, when it comes to modules, the GPL issue is exactly the same. -The kernel _is_ GPL. No ifs, buts and maybe's about it. As a result, -anything that is a derived work has to be GPL'd. It's that simple. - -Now, the "derived work" issue in copyright law is the only thing that -leads to any gray areas. There are areas that are not gray at all: user -space is clearly not a derived work, while kernel patches clearly _are_ -derived works. - -But one gray area in particular is something like a driver that was -originally written for another operating system (ie clearly not a derived -work of Linux in origin). At exactly what point does it become a derived -work of the kernel (and thus fall under the GPL)? - -THAT is a gray area, and _that_ is the area where I personally believe -that some modules may be considered to not be derived works simply because -they weren't designed for Linux and don't depend on any special Linux -behaviour. - -Basically: - - anything that was written with Linux in mind (whether it then _also_ - works on other operating systems or not) is clearly partially a derived - work. - - anything that has knowledge of and plays with fundamental internal - Linux behaviour is clearly a derived work. If you need to muck around - with core code, you're derived, no question about it. - -Historically, there's been things like the original Andrew filesystem -module: a standard filesystem that really wasn't written for Linux in the -first place, and just implements a UNIX filesystem. Is that derived just -because it got ported to Linux that had a reasonably similar VFS interface -to what other UNIXes did? Personally, I didn't feel that I could make that -judgment call. Maybe it was, maybe it wasn't, but it clearly is a gray -area. - -Personally, I think that case wasn't a derived work, and I was willing to -tell the AFS guys so. - -Does that mean that any kernel module is automatically not a derived work? -HELL NO! It has nothing to do with modules per se, except that non-modules -clearly are derived works (if they are so central to the kenrel that you -can't load them as a module, they are clearly derived works just by virtue -of being very intimate - and because the GPL expressly mentions linking). - -So being a module is not a sign of not being a derived work. It's just -one sign that _maybe_ it might have other arguments for why it isn't -derived. - - Linus - - -Date: Wed, 3 Dec 2003 16:23:33 -0800 (PST) -From: Linus Torvalds -To: Kendall Bennett -cc: linux-kernel@vger.kernel.org -Subject: Re: Linux GPL and binary module exception clause? - - -On Wed, 3 Dec 2003, Linus Torvalds wrote: -> -> So being a module is not a sign of not being a derived work. It's just -> one sign that _maybe_ it might have other arguments for why it isn't -> derived. - -Side note: historically, the Linux kernel module interfaces were really -quite weak, and only exported a few tens of entry-points, and really -mostly effectively only allowed character and block device drivers with -standard interfaces, and loadable filesystems. - -So historically, the fact that you could load a module using nothing but -these standard interfaces tended to be a much stronger argument for not -being very tightly coupled with the kernel. - -That has changed, and the kernel module interfaces we have today are MUCH -more extensive than they were back in '95 or so. These days modules are -used for pretty much everything, including stuff that is very much -"internal kernel" stuff and as a result the kind of historic "implied -barrier" part of modules really has weakened, and as a result there is not -avery strong argument for being an independent work from just the fact -that you're a module. - -Similarly, historically there was a much stronger argument for things like -AFS and some of the binary drivers (long forgotten now) for having been -developed totally independently of Linux: they literally were developed -before Linux even existed, by people who had zero knowledge of Linux. That -tends to strengthen the argument that they clearly aren't derived. - -In contrast, these days it would be hard to argue that a new driver or -filesystem was developed without any thought of Linux. I think the NVidia -people can probably reasonably honestly say that the code they ported had -_no_ Linux origin. But quite frankly, I'd be less inclined to believe that -for some other projects out there.. - - Linus - - - - -Date: Thu, 17 Oct 2002 10:08:19 -0700 (PDT) -From: Linus Torvalds -To: Christoph Hellwig -Cc: -Subject: Re: [PATCH] make LSM register functions GPLonly exports -In-Reply-To: <20021017175403.A32516@infradead.org> -Message-ID: - -Note that if this fight ends up being a major issue, I'm just going to -remove LSM and let the security vendors do their own thing. So far - - - I have not seen a lot of actual usage of the hooks - - seen a number of people who still worry that the hooks degrade - performance in critical areas - - the worry that people use it for non-GPL'd modules is apparently real, - considering Crispin's reply. - -I will re-iterate my stance on the GPL and kernel modules: - - There is NOTHING in the kernel license that allows modules to be - non-GPL'd. - - The _only_ thing that allows for non-GPL modules is copyright law, and - in particular the "derived work" issue. A vendor who distributes non-GPL - modules is _not_ protected by the module interface per se, and should - feel very confident that they can show in a court of law that the code - is not derived. - - The module interface has NEVER been documented or meant to be a GPL - barrier. The COPYING clearly states that the system call layer is such a - barrier, so if you do your work in user land you're not in any way - beholden to the GPL. The module interfaces are not system calls: there - are system calls used to _install_ them, but the actual interfaces are - not. - - The original binary-only modules were for things that were pre-existing - works of code, ie drivers and filesystems ported from other operating - systems, which thus could clearly be argued to not be derived works, and - the original limited export table also acted somewhat as a barrier to - show a level of distance. - -In short, Crispin: I'm going to apply the patch, and if you as a copyright -holder of that file disagree, I will simply remove all of he LSM code from -the kernel. I think it's very clear that a LSM module is a derived work, -and thus copyright law and the GPL are not in any way unclear about it. - -If people think they can avoid the GPL by using function pointers, they -are WRONG. And they have always been wrong. - - Linus - ------------------------------------------------------------------------- -Date: Fri, 19 Oct 2001 13:16:45 -0700 (PDT) -From: Linus Torvalds -To: Barnes -Subject: Re: GPL, Richard Stallman, and the Linux kernel - -[ This is not, of course, a legal document, but if you want to forward it - to anybody else, feel free to do so. And if you want to argue legal - points with me or point somehting out, I'm always interested. To a - point ;-] - -On Fri, 19 Oct 2001, Barnes wrote: -> -> I've been exchanging e-mail with Richard Stallman for a couple of -> weeks about the finer points of the GPL. - -I feel your pain. - -> I've have spent time pouring through mailing list archives, usenet, -> and web search engines to find out what's already been covered about -> your statement of allowing dynamically loaded kernel modules with -> proprietary code to co-exist with the Linux kernel. So far I've -> been unable to find anything beyond vague statements attributed to -> you. If these issues are addressed somewhere already, please refer -> me. - -Well, it really boils down to the equivalent of "_all_ derived modules -have to be GPL'd". An external module doesn't really change the GPL in -that respect. - -There are (mainly historical) examples of UNIX device drivers and some -UNIX filesystems that were pre-existing pieces of work, and which had -fairly well-defined and clear interfaces and that I personally could not -really consider any kind of "derived work" at all, and that were thus -acceptable. The clearest example of this is probably the AFS (the Andrew -Filesystem), but there have been various device drivers ported from SCO -too. - -> Issue #1 -> ======== -> Currently the GPL version 2 license is the only license covering the -> Linux kernel. I cannot find any alternative license explaining the -> loadable kernel module exception which makes your position difficult -> to legally analyze. -> -> There is a note at the top of www.kernel.org/pub/linux/kernel/COPYING, -> but that states "user programs" which would clearly not apply to -> kernel modules. -> -> Could you clarify in writing what the exception precisely states? - -Well, there really is no exception. However, copyright law obviously -hinges on the definition of "derived work", and as such anything can -always be argued on that point. - -I personally consider anything a "derived work" that needs special hooks -in the kernel to function with Linux (ie it is _not_ acceptable to make a -small piece of GPL-code as a hook for the larger piece), as that obviously -implies that the bigger module needs "help" from the main kernel. - -Similarly, I consider anything that has intimate knowledge about kernel -internals to be a derived work. - -What is left in the gray area tends to be clearly separate modules: code -that had a life outside Linux from the beginning, and that do something -self-containted that doesn't really have any impact on the rest of the -kernel. A device driver that was originally written for something else, -and that doesn't need any but the standard UNIX read/write kind of -interfaces, for example. - -> Issue #2 -> ======== -> I've found statements attributed to you that you think only 10% of -> the code in the current kernel was written by you. By not being the -> sole copyright holder of the Linux kernel, a stated exception to -> the GPL seems invalid unless all kernel copyright holders agreed on -> this exception. How does the exception cover GPL'd kernel code not -> written by you? Has everyone contributing to the kernel forfeited -> their copyright to you or agreed with the exception? - -Well, see above about the lack of exception, and about the fundamental -gray area in _any_ copyright issue. The "derived work" issue is obviously -a gray area, and I know lawyers don't like them. Crazy people (even -judges) have, as we know, claimed that even obvious spoofs of a work that -contain nothing of the original work itself, can be ruled to be "derived". - -I don't hold views that extreme, but at the same time I do consider a -module written for Linux and using kernel infrastructures to get its work -done, even if not actually copying any existing Linux code, to be a -derived work by default. You'd have to have a strong case to _not_ -consider your code a derived work.. - -> Issue #3 -> ======== -> This issue is related to issue #1. Exactly what is covered by the -> exception? For example, all code shipped with the Linux kernel -> archive and typically installed under /usr/src/linux, all code under -> /usr/src/linux except /usr/src/linux/drivers, or just the code in -> the /usr/src/linux/kernel directory? - -See above, and I think you'll see my point. - -The "user program" exception is not an exception at all, for example, it's -just a more clearly stated limitation on the "derived work" issue. If you -use standard UNIX system calls (with accepted Linux extensions), your -program obviously doesn't "derive" from the kernel itself. - -Whenever you link into the kernel, either directly or through a module, -the case is just a _lot_ more muddy. But as stated, by default it's -obviously derived - the very fact that you _need_ to do something as -fundamental as linking against the kernel very much argues that your -module is not a stand-alone thing, regardless of where the module source -code itself has come from. - -> Issue #4 -> ======== -> This last issue is not so much a issue for the Linux kernel -> exception, but a request for comment. -> -> Richard and I both agree that a "plug-in" and a "dynamically -> loaded kernel module" are effectively the same under the GPL. - -Agreed. - -The Linux kernel modules had (a long time ago), a more limited interface, -and not very many functions were actually exported. So five or six years -ago, we could believably claim that "if you only use these N interfaces -that are exported from the standard kernel, you've kind of implicitly -proven that you do not need the kernel infrastructure". - -That was never really documented either (more of a guideline for me and -others when we looked at the "derived work" issue), and as modules were -more-and-more used not for external stuff, but just for dynamic loading of -standard linux modules that were distributed as part of the kernel anyway, -the "limited interfaces" argument is no longer a very good guideline for -"derived work". - -So these days, we export many internal interfaces, not because we don't -think that they would "taint" the linker, but simply because it's useful -to do dynamic run-time loading of modules even with standard kernel -modules that _are_ supposed to know a lot about kernel internals, and are -obviously "derived works".. - -> However we disagree that a plug-in for a GPL'd program falls -> under the GPL as asserted in the GPL FAQ found in the answer: -> http://www.gnu.org/licenses/gpl-faq.html#GPLAndPlugins. - -I think you really just disagree on what is derived, and what is not. -Richard is very extreme: _anything_ that links is derived, regardless of -what the arguments against it are. I'm less extreme, and I bet you're even -less so (at least you would like to argue so for your company). - -> My assertion is that plug-ins are written to an interface, not a -> program. Since interfaces are not GPL'd, a plug-in cannot be GPL'd -> until the plug-in and program are placed together and run. That is -> done by the end user, not the plug-in creator. - -I agree, but also disrespectfully disagree ;) - -It's an issue of what a "plug-in" is - is it a way for the program to -internally load more modules as it needs them, or is it _meant_ to be a -public, published interface. - -For example, the "system call" interface could be considered a "plug-in -interface", and running a user mode program under Linux could easily be -construed as running a "plug-in" for the Linux kernel. No? - -And there, I obviously absolutely agree with you 100%: the interface is -published, and it's _meant_ for external and independent users. It's an -interface that we go to great lengths to preserve as well as we can, and -it's an interface that is designed to be independent of kernel versions. - -But maybe somebody wrote his program with the intention to dynamically -load "actors" as they were needed, as a way to maintain a good modularity, -and to try to keep the problem spaces well-defined. In that case, the -"plug-in" may technically follow all the same rules as the system call -interface, even though the author doesn't intend it that way. - -So I think it's to a large degree a matter of intent, but it could -arguably also be considered a matter of stability and documentation (ie -"require recompilation of the plug-in between version changes" would tend -to imply that it's an internal interface, while "documented binary -compatibility across many releases" implies a more stable external -interface, and less of a derived work) - -Does that make sense to you? - -> I asked Richard to comment on several scenarios involving plug-ins -> explain whether or not they were in violation of the GPL. So far he -> as only addressed one and has effectively admitted a hole. This is -> the one I asked that he's responded to: -> [A] non-GPL'd plug-in writer writes a plug-in for a non-GPL'd -> program. Another author writes a GPL'd program making the -> first author's plug-ins compatible with his program. Are now -> the plug-in author's plug-ins now retroactively required to be -> GPL'd? -> -> His response: -> No, because the plug-in was not written to extend this program. -> -> I find it suspicious that whether or not the GPL would apply to the -> plug-in depends on the mindset of the author. - -The above makes no sense if you think of it as a "plug in" issue, but it -makes sense if you think of it as a "derived work" issue, along with -taking "intent" into account. - -I know lawyers tend to not like the notion of "intent", because it brings -in another whole range of gray areas, but it's obviously a legal reality. - -Ok, enough blathering from me. I'd just like to finish off with a few -comments, just to clarify my personal stand: - - - I'm obviously not the only copyright holder of Linux, and I did so on - purpose for several reasons. One reason is just because I hate the - paperwork and other cr*p that goes along with copyright assignments. - - Another is that I don't much like copyright assignments at all: the - author is the author, and he may be bound by my requirement for GPL, - but that doesn't mean that he should give his copyright to me. - - A third reason, and the most relevant reason here, is that I want - people to _know_ that I cannot control the sources. I can write you a - note to say that "for use XXX, I do not consider module YYY to be a - derived work of my kernel", but that would not really matter that much. - Any other Linux copyright holder might still sue you. - - This third reason is what makes people who otherwise might not trust me - realize that I cannot screw people over. I am bound by the same - agreement that I require of everybody else, and the only special status - I really have is a totally non-legal issue: people trust me. - - (Yes, I realize that I probably would end up having more legal status - than most, even apart from the fact that I still am the largest single - copyright holder, if only because of appearances) - - - I don't really care about copyright law itself. What I care about is my - own morals. Whether I'd ever sue somebody or not (and quite frankly, - it's the last thing I ever want to do - if I never end up talking to - lawyers in a professional context, I'll be perfectly happy. No - disrespect intended) will be entirely up to whether I consider what - people do to me "moral" or not. Which is why intent matters to me a - lot - both the intent of the person/corporation doign the infringement, - _and_ the intent of me and others in issues like the module export - interface. - - Another way of putting this: I don't care about "legal loopholes" and - word-wrangling. - - - Finally: I don't trust the FSF. I like the GPL a lot - although not - necessarily as a legal piece of paper, but more as an intent. Which - explains why, if you've looked at the Linux COPYING file, you may have - noticed the explicit comment about "only _this_ particular version of - the GPL covers the kernel by default". - - That's because I agree with the GPL as-is, but I do not agree with the - FSF on many other matters. I don't like software patents much, for - example, but I do not want the code I write to be used as a weapon - against companies that have them. The FSF has long been discussing and - is drafting the "next generation" GPL, and they generally suggest that - people using the GPL should say "v2 or at your choice any later - version". - - Linux doesn't do that. The Linux kernel is v2 ONLY, apart from a few - files where the author put in the FSF extension (and see above about - copyright assignments why I would never remove such an extension). - -The "v2 only" issue might change some day, but only after all documented -copyright holders agree on it, and only after we've seen what the FSF -suggests. From what I've seen so far from the FSF drafts, we're not likely -to change our v2-only stance, but there might of course be legal reasons -why we'd have to do something like it (ie somebody challenging the GPLv2 -in court, and part of it to be found unenforceable or similar would -obviously mean that we'd have to reconsider the license). - - Linus - -PS. Historically, binary-only modules have not worked well under Linux, -quite regardless of any copyright issues. The kernel just develops too -quickly for binary modules to work well, and nobody really supports them. -Companies like Red Hat etc tend to refuse to have anything to do with -binary modules, because if something goes wrong there is nothing they can -do about it. So I just wanted to let you know that the _legal_ issue is -just the beginning. Even though you probably don't personally care ;) - - diff --git a/Documentation/fb/pxafb.txt b/Documentation/fb/pxafb.txt deleted file mode 100644 index db9b8500b..000000000 --- a/Documentation/fb/pxafb.txt +++ /dev/null @@ -1,54 +0,0 @@ -Driver for PXA25x LCD controller -================================ - -The driver supports the following options, either via -options= when modular or video=pxafb: when built in. - -For example: - modprobe pxafb options=mode:640x480-8,passive -or on the kernel command line - video=pxafb:mode:640x480-8,passive - -mode:XRESxYRES[-BPP] - XRES == LCCR1_PPL + 1 - YRES == LLCR2_LPP + 1 - The resolution of the display in pixels - BPP == The bit depth. Valid values are 1, 2, 4, 8 and 16. - -pixclock:PIXCLOCK - Pixel clock in picoseconds - -left:LEFT == LCCR1_BLW + 1 -right:RIGHT == LCCR1_ELW + 1 -hsynclen:HSYNC == LCCR1_HSW + 1 -upper:UPPER == LCCR2_BFW -lower:LOWER == LCCR2_EFR -vsynclen:VSYNC == LCCR2_VSW + 1 - Display margins and sync times - -color | mono => LCCR0_CMS - umm... - -active | passive => LCCR0_PAS - Active (TFT) or Passive (STN) display - -single | dual => LCCR0_SDS - Single or dual panel passive display - -4pix | 8pix => LCCR0_DPD - 4 or 8 pixel monochrome single panel data - -hsync:HSYNC -vsync:VSYNC - Horizontal and vertical sync. 0 => active low, 1 => active - high. - -dpc:DPC - Double pixel clock. 1=>true, 0=>false - -outputen:POLARITY - Output Enable Polarity. 0 => active low, 1 => active high - -pixclockpol:POLARITY - pixel clock polarity - 0 => falling edge, 1 => rising edge diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt deleted file mode 100644 index 7397bdb23..000000000 --- a/Documentation/filesystems/relayfs.txt +++ /dev/null @@ -1,812 +0,0 @@ - -relayfs - a high-speed data relay filesystem -============================================ - -relayfs is a filesystem designed to provide an efficient mechanism for -tools and facilities to relay large amounts of data from kernel space -to user space. - -The main idea behind relayfs is that every data flow is put into a -separate "channel" and each channel is a file. In practice, each -channel is a separate memory buffer allocated from within kernel space -upon channel instantiation. Software needing to relay data to user -space would open a channel or a number of channels, depending on its -needs, and would log data to that channel. All the buffering and -locking mechanics are taken care of by relayfs. The actual format and -protocol used for each channel is up to relayfs' clients. - -relayfs makes no provisions for copying the same data to more than a -single channel. This is for the clients of the relay to take care of, -and so is any form of data filtering. The purpose is to keep relayfs -as simple as possible. - - -Usage -===== - -In addition to the relayfs kernel API described below, relayfs -implements basic file operations. Here are the file operations that -are available and some comments regarding their behavior: - -open() enables user to open an _existing_ channel. A channel can be - opened in blocking or non-blocking mode, and can be opened - for reading as well as for writing. Readers will by default - be auto-consuming. - -mmap() results in channel's memory buffer being mmapped into the - caller's memory space. - -read() since we are dealing with circular buffers, the user is only - allowed to read forward. Some apps may want to loop around - read() waiting for incoming data - if there is no data - available, read will put the reader on a wait queue until - data is available (blocking mode). Non-blocking reads return - -EAGAIN if data is not available. - - -write() writing from user space operates exactly as relay_write() does - (described below). - -poll() POLLIN/POLLRDNORM/POLLOUT/POLLWRNORM/POLLERR supported. - -close() decrements the channel's refcount. When the refcount reaches - 0 i.e. when no process or kernel client has the file open - (see relay_close() below), the channel buffer is freed. - - -In order for a user application to make use of relayfs files, the -relayfs filesystem must be mounted. For example, - - mount -t relayfs relayfs /mountpoint - - -The relayfs kernel API -====================== - -relayfs channels are implemented as circular buffers subdivided into -'sub-buffers'. kernel clients write data into the channel using -relay_write(), and are notified via a set of callbacks when -significant events occur within the channel. 'Significant events' -include: - -- a sub-buffer has been filled i.e. the current write won't fit into the - current sub-buffer, and a 'buffer-switch' is triggered, after which - the data is written into the next buffer (if the next buffer is - empty). The client is notified of this condition via two callbacks, - one providing an opportunity to perform start-of-buffer tasks, the - other end-of-buffer tasks. - -- data is ready for the client to process. The client can choose to - be notified either on a per-sub-buffer basis (bulk delivery) or - per-write basis (packet delivery). - -- data has been written to the channel from user space. The client can - use this notification to accept and process 'commands' sent to the - channel via write(2). - -- the channel has been opened/closed/mapped/unmapped from user space. - The client can use this notification to trigger actions within the - kernel application, such as enabling/disabling logging to the - channel. It can also return result codes from the callback, - indicating that the operation should fail e.g. in order to restrict - more than one user space open or mmap. - -- the channel needs resizing, or needs to update its - state based on the results of the resize. Resizing the channel is - up to the kernel client to actually perform. If the channel is - configured for resizing, the client is notified when the unread data - in the channel passes a preset threshold, giving it the opportunity - to allocate a new channel buffer and replace the old one. - -Reader objects --------------- - -Channel readers use an opaque rchan_reader object to read from -channels. For VFS readers (those using read(2) to read from a -channel), these objects are automatically created and used internally; -only kernel clients that need to directly read from channels, or whose -userspace applications use mmap to access channel data, need to know -anything about rchan_readers - others may skip this section. - -A relay channel can have any number of readers, each represented by an -rchan_reader instance, which is used to encapsulate reader settings -and state. rchan_reader objects should be treated as opaque by kernel -clients. To create a reader object for directly accessing a channel -from kernel space, call the add_rchan_reader() kernel API function: - -rchan_reader *add_rchan_reader(rchan_id, auto_consume) - -This function returns an rchan_reader instance if successful, which -should then be passed to relay_read() when the kernel client is -interested in reading from the channel. - -The auto_consume parameter indicates whether a read done by this -reader will automatically 'consume' that portion of the unread channel -buffer when relay_read() is called (see below for more details). - -To close the reader, call - -remove_rchan_reader(reader) - -which will remove the reader from the list of current readers. - - -To create a reader object representing a userspace mmap reader in the -kernel application, call the add_map_reader() kernel API function: - -rchan_reader *add_map_reader(rchan_id) - -This function returns an rchan_reader instance if successful, whose -main purpose is as an argument to be passed into -relay_buffers_consumed() when the kernel client becomes aware that -data has been read by a user application using mmap to read from the -channel buffer. There is no auto_consume option in this case, since -only the kernel client/user application knows when data has been read. - -To close the map reader, call - -remove_map_reader(reader) - -which will remove the reader from the list of current readers. - -Consumed count --------------- - -A relayfs channel is a circular buffer, which means that if there is -no reader reading from it or a reader reading too slowly, at some -point the channel writer will 'lap' the reader and data will be lost. -In normal use, readers will always be able to keep up with writers and -the buffer is thus never in danger of becoming full. In many -applications, it's sufficient to ensure that this is practically -speaking always the case, by making the buffers large enough. These -types of applications can basically open the channel as -RELAY_MODE_CONTINOUS (the default anyway) and not worry about the -meaning of 'consume' and skip the rest of this section. - -If it's important for the application that a kernel client never allow -writers to overwrite unread data, the channel should be opened using -RELAY_MODE_NO_OVERWRITE and must be kept apprised of the count of -bytes actually read by the (typically) user-space channel readers. -This count is referred to as the 'consumed count'. read(2) channel -readers automatically update the channel's 'consumed count' as they -read. If the usage mode is to have only read(2) readers, which is -typically the case, the kernel client doesn't need to worry about any -of the relayfs functions having to do with 'bytes consumed' and can -skip the rest of this section. (Note that it is possible to have -multiple read(2) or auto-consuming readers, but like having multiple -readers on a pipe, these readers will race with each other i.e. it's -supported, but doesn't make much sense). - -If the kernel client cannot rely on an auto-consuming reader to keep -the 'consumed count' up-to-date, then it must do so manually, by -making the appropriate calls to relay_buffers_consumed() or -relay_bytes_consumed(). In most cases, this should only be necessary -for bulk mmap clients - almost all packet clients should be covered by -having auto-consuming read(2) readers. For mmapped bulk clients, for -instance, there are no auto-consuming VFS readers, so the kernel -client needs to make the call to relay_buffers_consumed() after -sub-buffers are read. - -Kernel API ----------- - -Here's a summary of the API relayfs provides to in-kernel clients: - -int relay_open(channel_path, bufsize, nbufs, channel_flags, - channel_callbacks, start_reserve, end_reserve, - rchan_start_reserve, resize_min, resize_max, mode, - init_buf, init_buf_size) -int relay_write(channel_id, *data_ptr, count, time_delta_offset, **wrote) -rchan_reader *add_rchan_reader(channel_id, auto_consume) -int remove_rchan_reader(rchan_reader *reader) -rchan_reader *add_map_reader(channel_id) -int remove_map_reader(rchan_reader *reader) -int relay_read(reader, buf, count, wait, *actual_read_offset) -void relay_buffers_consumed(reader, buffers_consumed) -void relay_bytes_consumed(reader, bytes_consumed, read_offset) -int relay_bytes_avail(reader) -int rchan_full(reader) -int rchan_empty(reader) -int relay_info(channel_id, *channel_info) -int relay_close(channel_id) -int relay_realloc_buffer(channel_id, nbufs, async) -int relay_replace_buffer(channel_id) -int relay_reset(int rchan_id) - ----------- -int relay_open(channel_path, bufsize, nbufs, - channel_flags, channel_callbacks, start_reserve, - end_reserve, rchan_start_reserve, resize_min, resize_max, mode) - -relay_open() is used to create a new entry in relayfs. This new entry -is created according to channel_path. channel_path contains the -absolute path to the channel file on relayfs. If, for example, the -caller sets channel_path to "/xlog/9", a "xlog/9" entry will appear -within relayfs automatically and the "xlog" directory will be created -in the filesystem's root. relayfs does not implement any policy on -its content, except to disallow the opening of two channels using the -same file. There are, nevertheless a set of guidelines for using -relayfs. Basically, each facility using relayfs should use a top-level -directory identifying it. The entry created above, for example, -presumably belongs to the "xlog" software. - -The remaining parameters for relay_open() are as follows: - -- channel_flags - an ORed combination of attribute values controlling - common channel characteristics: - - - logging scheme - relayfs use 2 mutually exclusive schemes - for logging data to a channel. The 'lockless scheme' - reserves and writes data to a channel without the need of - any type of locking on the channel. This is the preferred - scheme, but may not be available on a given architecture (it - relies on the presence of a cmpxchg instruction). It's - specified by the RELAY_SCHEME_LOCKLESS flag. The 'locking - scheme' either obtains a lock on the channel for writing or - disables interrupts, depending on whether the channel was - opened for SMP or global usage (see below). It's specified - by the RELAY_SCHEME_LOCKING flag. While a client may want - to explicitly specify a particular scheme to use, it's more - convenient to specify RELAY_SCHEME_ANY for this flag, which - will allow relayfs to choose the best available scheme i.e. - lockless if supported. - - - overwrite mode (default is RELAY_MODE_CONTINUOUS) - - If RELAY_MODE_CONTINUOUS is specified, writes to the channel - will succeed regardless of whether there are up-to-date - consumers or not. If RELAY_MODE_NO_OVERWRITE is specified, - the channel becomes 'full' when the total amount of buffer - space unconsumed by readers equals or exceeds the total - buffer size. With the buffer in this state, writes to the - buffer will fail - clients need to check the return code from - relay_write() to determine if this is the case and act - accordingly - 0 or a negative value indicate the write failed. - - - SMP usage - this applies only when the locking scheme is in - use. If RELAY_USAGE_SMP is specified, it's assumed that the - channel will be used in a per-CPU fashion and consequently, - the only locking that will be done for writes is to disable - local irqs. If RELAY_USAGE_GLOBAL is specified, it's assumed - that writes to the buffer can occur within any CPU context, - and spinlock_irq_save will be used to lock the buffer. - - - delivery mode - if RELAY_DELIVERY_BULK is specified, the - client will be notified via its deliver() callback whenever a - sub-buffer has been filled. Alternatively, - RELAY_DELIVERY_PACKET will cause delivery to occur after the - completion of each write. See the description of the channel - callbacks below for more details. - - - timestamping - if RELAY_TIMESTAMP_TSC is specified and the - architecture supports it, efficient TSC 'timestamps' can be - associated with each write, otherwise more expensive - gettimeofday() timestamping is used. At the beginning of - each sub-buffer, a gettimeofday() timestamp and the current - TSC, if supported, are read, and are passed on to the client - via the buffer_start() callback. This allows correlation of - the current time with the current TSC for subsequent writes. - Each subsequent write is associated with a 'time delta', - which is either the current TSC, if the channel is using - TSCs, or the difference between the buffer_start gettimeofday - timestamp and the gettimeofday time read for the current - write. Note that relayfs never writes either a timestamp or - time delta into the buffer unless explicitly asked to (see - the description of relay_write() for details). - -- bufsize - the size of the 'sub-buffers' making up the circular channel - buffer. For the lockless scheme, this must be a power of 2. - -- nbufs - the number of 'sub-buffers' making up the circular - channel buffer. This must be a power of 2. - - The total size of the channel buffer is bufsize * nbufs rounded up - to the next kernel page size. If the lockless scheme is used, both - bufsize and nbufs must be a power of 2. If the locking scheme is - used, the bufsize can be anything and nbufs must be a power of 2. If - RELAY_SCHEME_ANY is used, the bufsize and nbufs should be a power of 2. - - NOTE: if nbufs is 1, relayfs will bypass the normal size - checks and will allocate an rvmalloced buffer of size bufsize. - This buffer will be freed when relay_close() is called, if the channel - isn't still being referenced. - -- callbacks - a table of callback functions called when events occur - within the data relay that clients need to know about: - - - int buffer_start(channel_id, current_write_pos, buffer_id, - start_time, start_tsc, using_tsc) - - - called at the beginning of a new sub-buffer, the - buffer_start() callback gives the client an opportunity to - write data into space reserved at the beginning of a - sub-buffer. The client should only write into the buffer - if it specified a value for start_reserve and/or - channel_start_reserve (see below) when the channel was - opened. In the latter case, the client can determine - whether to write its one-time rchan_start_reserve data by - examining the value of buffer_id, which will be 0 for the - first sub-buffer. The address that the client can write - to is contained in current_write_pos (the client by - definition knows how much it can write i.e. the value it - passed to relay_open() for start_reserve/ - channel_start_reserve). start_time contains the - gettimeofday() value for the start of the buffer and start - TSC contains the TSC read at the same time. The using_tsc - param indicates whether or not start_tsc is valid (it - wouldn't be if TSC timestamping isn't being used). - - The client should return the number of bytes it wrote to - the channel, 0 if none. - - - int buffer_end(channel_id, current_write_pos, end_of_buffer, - end_time, end_tsc, using_tsc) - - called at the end of a sub-buffer, the buffer_end() - callback gives the client an opportunity to perform - end-of-buffer processing. Note that the current_write_pos - is the position where the next write would occur, but - since the current write wouldn't fit (which is the trigger - for the buffer_end event), the buffer is considered full - even though there may be unused space at the end. The - end_of_buffer param pointer value can be used to determine - exactly the size of the unused space. The client should - only write into the buffer if it specified a value for - end_reserve when the channel was opened. If the client - doesn't write anything i.e. returns 0, the unused space at - the end of the sub-buffer is available via relay_info() - - this data may be needed by the client later if it needs to - process raw sub-buffers (an alternative would be to save - the unused bytes count value in end_reserve space at the - end of each sub-buffer during buffer_end processing and - read it when needed at a later time. The other - alternative would be to use read(2), which makes the - unused count invisible to the caller). end_time contains - the gettimeofday() value for the end of the buffer and end - TSC contains the TSC read at the same time. The using_tsc - param indicates whether or not end_tsc is valid (it - wouldn't be if TSC timestamping isn't being used). - - The client should return the number of bytes it wrote to - the channel, 0 if none. - - - void deliver(channel_id, from, len) - - called when data is ready for the client. This callback - is used to notify a client when a sub-buffer is complete - (in the case of bulk delivery) or a single write is - complete (packet delivery). A bulk delivery client might - wish to then signal a daemon that a sub-buffer is ready. - A packet delivery client might wish to process the packet - or send it elsewhere. The from param is a pointer to the - delivered data and len specifies how many bytes are ready. - - - void user_deliver(channel_id, from, len) - - called when data has been written to the channel from user - space. This callback is used to notify a client when a - successful write from userspace has occurred, independent - of whether bulk or packet delivery is in use. This can be - used to allow userspace programs to communicate with the - kernel client through the channel via out-of-band write(2) - 'commands' instead of via ioctls, for instance. The from - param is a pointer to the delivered data and len specifies - how many bytes are ready. Note that this callback occurs - after the bytes have been successfully written into the - channel, which means that channel readers must be able to - deal with the 'command' data which will appear in the - channel data stream just as any other userspace or - non-userspace write would. - - - int needs_resize(channel_id, resize_type, - suggested_buf_size, suggested_n_bufs) - - called when a channel's buffers are in danger of becoming - full i.e. the number of unread bytes in the channel passes - a preset threshold, or when the current capacity of a - channel's buffer is no longer needed. Also called to - notify the client when a channel's buffer has been - replaced. If resize_type is RELAY_RESIZE_EXPAND or - RELAY_RESIZE_SHRINK, the kernel client should arrange to - call relay_realloc_buffer() with the suggested buffer size - and buffer count, which will allocate (but will not - replace the old one) a new buffer of the recommended size - for the channel. When the allocation has completed, - needs_resize() is again called, this time with a - resize_type of RELAY_RESIZE_REPLACE. The kernel client - should then arrange to call relay_replace_buffer() to - actually replace the old channel buffer with the newly - allocated buffer. Finally, once the buffer replacement - has completed, needs_resize() is again called, this time - with a resize_type of RELAY_RESIZE_REPLACED, to inform the - client that the replacement is complete and additionally - confirming the current sub-buffer size and number of - sub-buffers. Note that a resize can be canceled if - relay_realloc_buffer() is called with the async param - non-zero and the resize conditions no longer hold. In - this case, the RELAY_RESIZE_REPLACED suggested number of - sub-buffers will be the same as the number of sub-buffers - that existed before the RELAY_RESIZE_SHRINK or EXPAND i.e. - values indicating that the resize didn't actually occur. - - - int fileop_notify(channel_id, struct file *filp, enum relay_fileop) - - called when a userspace file operation has occurred or - will occur on a relayfs channel file. These notifications - can be used by the kernel client to trigger actions within - the kernel client when the corresponding event occurs, - such as enabling logging only when a userspace application - opens or mmaps a relayfs file and disabling it again when - the file is closed or unmapped. The kernel client can - also return its own return value, which can affect the - outcome of file operation - returning 0 indicates that the - operation should succeed, and returning a negative value - indicates that the operation should be failed, and that - the returned value should be returned to the ultimate - caller e.g. returning -EPERM from the open fileop will - cause the open to fail with -EPERM. Among other things, - the return value can be used to restrict a relayfs file - from being opened or mmap'ed more than once. The currently - implemented fileops are: - - RELAY_FILE_OPEN - a relayfs file is being opened. Return - 0 to allow it to succeed, negative to - have it fail. A negative return value will - be passed on unmodified to the open fileop. - RELAY_FILE_CLOSE- a relayfs file is being closed. The return - value is ignored. - RELAY_FILE_MAP - a relayfs file is being mmap'ed. Return 0 - to allow it to succeed, negative to have - it fail. A negative return value will be - passed on unmodified to the mmap fileop. - RELAY_FILE_UNMAP- a relayfs file is being unmapped. The return - value is ignored. - - - void ioctl(rchan_id, cmd, arg) - - called when an ioctl call is made using a relayfs file - descriptor. The cmd and arg are passed along to this - callback unmodified for it to do as it wishes with. The - return value from this callback is used as the return value - of the ioctl call. - - If the callbacks param passed to relay_open() is NULL, a set of - default do-nothing callbacks will be defined for the channel. - Likewise, any NULL rchan_callback function contained in a non-NULL - callbacks struct will be filled in with a default callback function - that does nothing. - -- start_reserve - the number of bytes to be reserved at the start of - each sub-buffer. The client can do what it wants with this number - of bytes when the buffer_start() callback is invoked. Typically - clients would use this to write per-sub-buffer header data. - -- end_reserve - the number of bytes to be reserved at the end of each - sub-buffer. The client can do what it wants with this number of - bytes when the buffer_end() callback is invoked. Typically clients - would use this to write per-sub-buffer footer data. - -- channel_start_reserve - the number of bytes to be reserved, in - addition to start_reserve, at the beginning of the first sub-buffer - in the channel. The client can do what it wants with this number of - bytes when the buffer_start() callback is invoked. Typically - clients would use this to write per-channel header data. - -- resize_min - if set, this signifies that the channel is - auto-resizeable. The value specifies the size that the channel will - try to maintain as a normal working size, and that it won't go - below. The client makes use of the resizing callbacks and - relay_realloc_buffer() and relay_replace_buffer() to actually effect - the resize. - -- resize_max - if set, this signifies that the channel is - auto-resizeable. The value specifies the maximum size the channel - can have as a result of resizing. - -- mode - if non-zero, specifies the file permissions that will be given - to the channel file. If 0, the default rw user perms will be used. - -- init_buf - if non-NULL, rather than allocating the channel buffer, - this buffer will be used as the initial channel buffer. The kernel - API function relay_discard_init_buf() can later be used to have - relayfs allocate a normal mmappable channel buffer and switch over - to using it after copying the init_buf contents into it. Currently, - the size of init_buf must be exactly buf_size * n_bufs. The caller - is responsible for managing the init_buf memory. This feature is - typically used for init-time channel use and should normally be - specified as NULL. - -- init_buf_size - the total size of init_buf, if init_buf is specified - as non-NULL. Currently, the size of init_buf must be exactly - buf_size * n_bufs. - -Upon successful completion, relay_open() returns a channel id -to be used for all other operations with the relay. All buffers -managed by the relay are allocated using rvmalloc/rvfree to allow -for easy mmapping to user-space. - ----------- -int relay_write(channel_id, *data_ptr, count, time_delta_offset, **wrote_pos) - -relay_write() reserves space in the channel and writes count bytes of -data pointed to by data_ptr to it. Automatically performs any -necessary locking, depending on the scheme and SMP usage in effect (no -locking is done for the lockless scheme regardless of usage). It -returns the number of bytes written, or 0/negative on failure. If -time_delta_offset is >= 0, the internal time delta, the internal time -delta calculated when the slot was reserved will be written at that -offset. This is the TSC or gettimeofday() delta between the current -write and the beginning of the buffer, whichever method is being used -by the channel. Trying to write a count larger than the bufsize -specified to relay_open() (taking into account the reserved -start-of-buffer and end-of-buffer space as well) will fail. If -wrote_pos is non-NULL, it will receive the location the data was -written to, which may be needed for some applications but is not -normally interesting. Most applications should pass in NULL for this -param. - ----------- -struct rchan_reader *add_rchan_reader(int rchan_id, int auto_consume) - -add_rchan_reader creates and initializes a reader object for a -channel. An opaque rchan_reader object is returned on success, and is -passed to relay_read() when reading the channel. If the boolean -auto_consume parameter is 1, the reader is defined to be -auto-consuming. auto-consuming reader objects are automatically -created and used for VFS read(2) readers. - ----------- -void remove_rchan_reader(struct rchan_reader *reader) - -remove_rchan_reader finds and removes the given reader from the -channel. This function is used only by non-VFS read(2) readers. VFS -read(2) readers are automatically removed when the corresponding file -object is closed. - ----------- -reader add_map_reader(int rchan_id) - -Creates and initializes an rchan_reader object for channel map -readers, and is needed for updating relay_bytes/buffers_consumed() -when kernel clients become aware of the need to do so by their mmap -user clients. - ----------- -int remove_map_reader(reader) - -Finds and removes the given map reader from the channel. This function -is useful only for map readers. - ----------- -int relay_read(reader, buf, count, wait, *actual_read_offset) - -Reads count bytes from the channel, or as much as is available within -the sub-buffer currently being read. The read offset that will be -read from is the position contained within the reader object. If the -wait flag is set, buf is non-NULL, and there is nothing available, it -will wait until there is. If the wait flag is 0 and there is nothing -available, -EAGAIN is returned. If buf is NULL, the value returned is -the number of bytes that would have been read. actual_read_offset is -the value that should be passed as the read offset to -relay_bytes_consumed, needed only if the reader is not auto-consuming -and the channel is MODE_NO_OVERWRITE, but in any case, it must not be -NULL. - ----------- - -int relay_bytes_avail(reader) - -Returns the number of bytes available relative to the reader's current -read position within the corresponding sub-buffer, 0 if there is -nothing available. Note that this doesn't return the total bytes -available in the channel buffer - this is enough though to know if -anything is available, however, or how many bytes might be returned -from the next read. - ----------- -void relay_buffers_consumed(reader, buffers_consumed) - -Adds to the channel's consumed buffer count. buffers_consumed should -be the number of buffers newly consumed, not the total number -consumed. NOTE: kernel clients don't need to call this function if -the reader is auto-consuming or the channel is MODE_CONTINUOUS. - -In order for the relay to detect the 'buffers full' condition for a -channel, it must be kept up-to-date with respect to the number of -buffers consumed by the client. If the addition of the value of the -bufs_consumed param to the current bufs_consumed count for the channel -would exceed the bufs_produced count for the channel, the channel's -bufs_consumed count will be set to the bufs_produced count for the -channel. This allows clients to 'catch up' if necessary. - ----------- -void relay_bytes_consumed(reader, bytes_consumed, read_offset) - -Adds to the channel's consumed count. bytes_consumed should be the -number of bytes actually read e.g. return value of relay_read() and -the read_offset should be the actual offset the bytes were read from -e.g. the actual_read_offset set by relay_read(). NOTE: kernel clients -don't need to call this function if the reader is auto-consuming or -the channel is MODE_CONTINUOUS. - -In order for the relay to detect the 'buffers full' condition for a -channel, it must be kept up-to-date with respect to the number of -bytes consumed by the client. For packet clients, it makes more sense -to update after each read rather than after each complete sub-buffer -read. The bytes_consumed count updates bufs_consumed when a buffer -has been consumed so this count remains consistent. - ----------- -int relay_info(channel_id, *channel_info) - -relay_info() fills in an rchan_info struct with channel status and -attribute information such as usage modes, sub-buffer size and count, -the allocated size of the entire buffer, buffers produced and -consumed, current buffer id, count of writes lost due to buffers full -condition. - -The virtual address of the channel buffer is also available here, for -those clients that need it. - -Clients may need to know how many 'unused' bytes there are at the end -of a given sub-buffer. This would only be the case if the client 1) -didn't either write this count to the end of the sub-buffer or -otherwise note it (it's available as the difference between the buffer -end and current write pos params in the buffer_end callback) (if the -client returned 0 from the buffer_end callback, it's assumed that this -is indeed the case) 2) isn't using the read() system call to read the -buffer. In other words, if the client isn't annotating the stream and -is reading the buffer by mmaping it, this information would be needed -in order for the client to 'skip over' the unused bytes at the ends of -sub-buffers. - -Additionally, for the lockless scheme, clients may need to know -whether a particular sub-buffer is actually complete. An array of -boolean values, one per sub-buffer, contains non-zero if the buffer is -complete, non-zero otherwise. - ----------- -int relay_close(channel_id) - -relay_close() is used to close the channel. It finalizes the last -sub-buffer (the one currently being written to) and marks the channel -as finalized. The channel buffer and channel data structure are then -freed automatically when the last reference to the channel is given -up. - ----------- -int relay_realloc_buffer(channel_id, nbufs, async) - -Allocates a new channel buffer using the specified sub-buffer count -(note that resizing can't change sub-buffer sizes). If async is -non-zero, the allocation is done in the background using a work queue. -When the allocation has completed, the needs_resize() callback is -called with a resize_type of RELAY_RESIZE_REPLACE. This function -doesn't replace the old buffer with the new - see -relay_replace_buffer(). - -This function is called by kernel clients in response to a -needs_resize() callback call with a resize type of RELAY_RESIZE_EXPAND -or RELAY_RESIZE_SHRINK. That callback also includes a suggested -new_bufsize and new_nbufs which should be used when calling this -function. - -Returns 0 on success, or errcode if the channel is busy or if -the allocation couldn't happen for some reason. - -NOTE: if async is not set, this function should not be called with a -lock held, as it may sleep. - ----------- -int relay_replace_buffer(channel_id) - -Replaces the current channel buffer with the new buffer allocated by -relay_realloc_buffer and contained in the channel struct. When the -replacement is complete, the needs_resize() callback is called with -RELAY_RESIZE_REPLACED. This function is called by kernel clients in -response to a needs_resize() callback having a resize type of -RELAY_RESIZE_REPLACE. - -Returns 0 on success, or errcode if the channel is busy or if the -replacement or previous allocation didn't happen for some reason. - -NOTE: This function will not sleep, so can called in any context and -with locks held. The client should, however, ensure that the channel -isn't actively being read from or written to. - ----------- -int relay_reset(rchan_id) - -relay_reset() has the effect of erasing all data from the buffer and -restarting the channel in its initial state. The buffer itself is not -freed, so any mappings are still in effect. NOTE: Care should be -taken that the channnel isn't actually being used by anything when -this call is made. - ----------- -int rchan_full(reader) - -returns 1 if the channel is full with respect to the reader, 0 if not. - ----------- -int rchan_empty(reader) - -returns 1 if the channel is empty with respect to the reader, 0 if not. - ----------- -int relay_discard_init_buf(rchan_id) - -allocates an mmappable channel buffer, copies the contents of init_buf -into it, and sets the current channel buffer to the newly allocated -buffer. This function is used only in conjunction with the init_buf -and init_buf_size params to relay_open(), and is typically used when -the ability to write into the channel at init-time is needed. The -basic usage is to specify an init_buf and init_buf_size to relay_open, -then call this function when it's safe to switch over to a normally -allocated channel buffer. 'Safe' means that the caller is in a -context that can sleep and that nothing is actively writing to the -channel. Returns 0 if successful, negative otherwise. - - -Writing directly into the channel -================================= - -Using the relay_write() API function as described above is the -preferred means of writing into a channel. In some cases, however, -in-kernel clients might want to write directly into a relay channel -rather than have relay_write() copy it into the buffer on the client's -behalf. Clients wishing to do this should follow the model used to -implement relay_write itself. The general sequence is: - -- get a pointer to the channel via rchan_get(). This increments the - channel's reference count. -- call relay_lock_channel(). This will perform the proper locking for - the channel given the scheme in use and the SMP usage. -- reserve a slot in the channel via relay_reserve() -- write directly to the reserved address -- call relay_commit() to commit the write -- call relay_unlock_channel() -- call rchan_put() to release the channel reference - -In particular, clients should make sure they call rchan_get() and -rchan_put() and not hold on to references to the channel pointer. -Also, forgetting to use relay_lock_channel()/relay_unlock_channel() -has no effect if the lockless scheme is being used, but could result -in corrupted buffer contents if the locking scheme is used. - - -Limitations -=========== - -Writes made via the write() system call are currently limited to 2 -pages worth of data. There is no such limit on the in-kernel API -function relay_write(). - -User applications can currently only mmap the complete buffer (it -doesn't really make sense to mmap only part of it, given its purpose). - - -Latest version -============== - -The latest version can be found at: - -http://www.opersys.com/relayfs - -Example relayfs clients, such as dynamic printk and the Linux Trace -Toolkit, can also be found there. - - -Credits -======= - -The ideas and specs for relayfs came about as a result of discussions -on tracing involving the following: - -Michel Dagenais -Richard Moore -Bob Wisniewski -Karim Yaghmour -Tom Zanussi - -Also thanks to Hubertus Franke for a lot of useful suggestions and bug -reports, and for contributing the klog code. diff --git a/Documentation/numastat.txt b/Documentation/numastat.txt deleted file mode 100644 index 80133ace1..000000000 --- a/Documentation/numastat.txt +++ /dev/null @@ -1,22 +0,0 @@ - -Numa policy hit/miss statistics - -/sys/devices/system/node/node*/numastat - -All units are pages. Hugepages have separate counters. - -numa_hit A process wanted to allocate memory from this node, - and succeeded. -numa_miss A process wanted to allocate memory from this node, - but ended up with memory from another. -numa_foreign A process wanted to allocate on another node, - but ended up with memory from this one. -local_node A process ran on this node and got memory from it. -other_node A process ran on this node and got memory from another node. -interleave_hit Interleaving wanted to allocate from this node - and succeeded. - -For easier reading you can use the numastat utility from the numactl package -(ftp://ftp.suse.com/pub/people/ak/numa/numactl*). Note that it only works -well right now on machines with a small number of CPUs. - diff --git a/Documentation/sched-domains.txt b/Documentation/sched-domains.txt deleted file mode 100644 index b5da811fc..000000000 --- a/Documentation/sched-domains.txt +++ /dev/null @@ -1,55 +0,0 @@ -Each CPU has a "base" scheduling domain (struct sched_domain). These are -accessed via cpu_sched_domain(i) and this_sched_domain() macros. The domain -hierarchy is built from these base domains via the ->parent pointer. ->parent -MUST be NULL terminated, and domain structures should be per-CPU as they -are locklessly updated. - -Each scheduling domain spans a number of CPUs (stored in the ->span field). -A domain's span MUST be a superset of it child's span, and a base domain -for CPU i MUST span at least i. The top domain for each CPU will generally -span all CPUs in the system although strictly it doesn't have to, but this -could lead to a case where some CPUs will never be given tasks to run unless -the CPUs allowed mask is explicitly set. A sched domain's span means "balance -process load among these CPUs". - -Each scheduling domain must have one or more CPU groups (struct sched_group) -which are organised as a circular one way linked list from the ->groups -pointer. The union of cpumasks of these groups MUST be the same as the -domain's span. The intersection of cpumasks from any two of these groups -MUST be the empty set. The group pointed to by the ->groups pointer MUST -contain the CPU to which the domain belongs. Groups may be shared among -CPUs as they contain read only data after they have been set up. - -Balancing within a sched domain occurs between groups. That is, each group -is treated as one entity. The load of a group is defined as the sum of the -load of each of its member CPUs, and only when the load of a group becomes -out of balance are tasks moved between groups. - -In kernel/sched.c, rebalance_tick is run periodically on each CPU. This -function takes its CPU's base sched domain and checks to see if has reached -its rebalance interval. If so, then it will run load_balance on that domain. -rebalance_tick then checks the parent sched_domain (if it exists), and the -parent of the parent and so forth. - -*** Implementing sched domains *** -The "base" domain will "span" the first level of the hierarchy. In the case -of SMT, you'll span all siblings of the physical CPU, with each group being -a single virtual CPU. - -In SMP, the parent of the base domain will span all physical CPUs in the -node. Each group being a single physical CPU. Then with NUMA, the parent -of the SMP domain will span the entire machine, with each group having the -cpumask of a node. Or, you could do multi-level NUMA or Opteron, for example, -might have just one domain covering its one NUMA level. - -The implementor should read comments in include/linux/sched.h: -struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of -the specifics and what to tune. - -Implementors should change the line -#undef SCHED_DOMAIN_DEBUG -to -#define SCHED_DOMAIN_DEBUG -in kernel/sched.c as this enables an error checking parse of the sched domains -which should catch most possible errors (described above). It also prints out -the domain structure in a visual format. diff --git a/Documentation/scsi/sym53c500_cs.txt b/Documentation/scsi/sym53c500_cs.txt deleted file mode 100644 index 75febcf92..000000000 --- a/Documentation/scsi/sym53c500_cs.txt +++ /dev/null @@ -1,23 +0,0 @@ -The sym53c500_cs driver originated as an add-on to David Hinds' pcmcia-cs -package, and was written by Tom Corner (tcorner@via.at). A rewrite was -long overdue, and the current version addresses the following concerns: - - (1) extensive kernel changes between 2.4 and 2.6. - (2) deprecated PCMCIA support outside the kernel. - -All the USE_BIOS code has been ripped out. It was never used, and could -not have worked anyway. The USE_DMA code is likewise gone. Many thanks -to YOKOTA Hiroshi (nsp_cs driver) and David Hinds (qlogic_cs driver) for -the code fragments I shamelessly adapted for this work. Thanks also to -Christoph Hellwig for his patient tutelage while I stumbled about. - -The Symbios Logic 53c500 chip was used in the "newer" (circa 1997) version -of the New Media Bus Toaster PCMCIA SCSI controller. Presumably there are -other products using this chip, but I've never laid eyes (much less hands) -on one. - -Through the years, there have been a number of downloads of the pcmcia-cs -version of this driver, and I guess it worked for those users. It worked -for Tom Corner, and it works for me. Your mileage will probably vary. - ---Bob Tracy (rct@frus.com) diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig deleted file mode 100644 index 3377f887b..000000000 --- a/arch/arm/mach-ixp4xx/Kconfig +++ /dev/null @@ -1,89 +0,0 @@ - -config ARCH_SUPPORTS_BIG_ENDIAN - bool - depends on ARCH_IXP4XX - default y - -menu "Intel IXP4xx Implementation Options" - -comment "IXP4xx Platforms" - -config ARCH_AVILA - bool "Avila" - depends on ARCH_IXP4XX - help - Say 'Y' here if you want your kernel to support the Gateworks - Avila Network Platform. For more information on this platform, - see Documentation/arm/IXP4xx. - -config ARCH_ADI_COYOTE - bool "Coyote" - depends on ARCH_IXP4XX - help - Say 'Y' here if you want your kernel to support the ADI - Engineering Coyote Gateway Reference Platform. For more - information on this platform, see Documentation/arm/IXP4xx. - -config ARCH_IXDP425 - bool "IXDP425" - depends on ARCH_IXP4XX - help - Say 'Y' here if you want your kernel to support Intel's - IXDP425 Development Platform (Also known as Richfield). - For more information on this platform, see Documentation/arm/IXP4xx. - -# -# IXCDP1100 is the exact same HW as IXDP425, but with a different machine -# number from the bootloader due to marketing monkeys, so we just enable it -# by default if IXDP425 is enabled. -# -config ARCH_IXCDP1100 - bool - depends on ARCH_IXDP425 - default y - -config ARCH_PRPMC1100 - bool "PrPMC1100" - depends on ARCH_IXP4XX - help - Say 'Y' here if you want your kernel to support the Motorola - PrPCM1100 Processor Mezanine Module. For more information on - this platform, see Documentation/arm/IXP4xx. - -# -# Avila and IXDP share the same source for now. Will change in future -# -config ARCH_IXDP4XX - bool - depends on ARCH_IXDP425 || ARCH_AVILA - default y - -comment "IXP4xx Options" - -config IXP4XX_INDIRECT_PCI - bool "Use indirect PCI memory access" - depends on ARCH_IXP4XX - help - IXP4xx provides two methods of accessing PCI memory space: - - 1) A direct mapped window from 0x48000000 to 0x4bffffff (64MB). - To access PCI via this space, we simply ioremap() the BAR - into the kernel and we can use the standard read[bwl]/write[bwl] - macros. This is the preffered method due to speed but it - limits the system to just 64MB of PCI memory. This can be - problamatic if using video cards and other memory-heavy devices. - - 2) If > 64MB of memory space is required, the IXP4xx can be - configured to use indirect registers to access PCI This allows - for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus. - The disadvantadge of this is that every PCI access requires - three local register accesses plus a spinlock, but in some - cases the performance hit is acceptable. In addition, you cannot - mmap() PCI devices in this case due to the indirect nature - of the PCI window. - - By default, the direct method is used. Choose this option if you - need to use the indirect method instead. If you don't know - what you need, leave this option unselected. - -endmenu diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c deleted file mode 100644 index bc6e0d042..000000000 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/coyote-setup.c - * - * ADI Engineering Coyote board-setup - * - * Copyright (C) 2003-2004 MontaVista Software, Inc. - * - * Author: Deepak Saxena - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __ARMEB__ -#define REG_OFFSET 3 -#else -#define REG_OFFSET 0 -#endif - -/* - * Only one serial port is connected on the Coyote. - */ -static struct uart_port coyote_serial_port = { - .membase = (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET), - .mapbase = (IXP4XX_UART2_BASE_PHYS), - .irq = IRQ_IXP4XX_UART2, - .flags = UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, - .line = 0, - .type = PORT_XSCALE, - .fifosize = 32 -}; - -void __init coyote_map_io(void) -{ - early_serial_setup(&coyote_serial_port); - - ixp4xx_map_io(); -} - -static struct flash_platform_data coyote_flash_data = { - .map_name = "cfi_probe", - .width = 2, -}; - -static struct resource coyote_flash_resource = { - .start = COYOTE_FLASH_BASE, - .end = COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device coyote_flash_device = { - .name = "IXP4XX-Flash", - .id = 0, - .dev = { - .platform_data = &coyote_flash_data, - }, - .num_resources = 1, - .resource = &coyote_flash_resource, -}; - -static void __init coyote_init(void) -{ - platform_add_device(&coyote_flash_device); -} - -MACHINE_START(ADI_COYOTE, "ADI Engineering IXP4XX Coyote Development Platform") - MAINTAINER("MontaVista Software, Inc.") - BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, - IXP4XX_PERIPHERAL_BASE_VIRT) - MAPIO(coyote_map_io) - INITIRQ(ixp4xx_init_irq) - BOOT_PARAMS(0x0100) - INIT_MACHINE(coyote_init) -MACHINE_END - diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c deleted file mode 100644 index 160117c67..000000000 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/ixdp425-setup.c - * - * IXDP425/IXCDP1100 board-setup - * - * Copyright (C) 2003-2004 MontaVista Software, Inc. - * - * Author: Deepak Saxena - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __ARMEB__ -#define REG_OFFSET 3 -#else -#define REG_OFFSET 0 -#endif - -/* - * IXDP425 uses both chipset serial ports - */ -static struct uart_port ixdp425_serial_ports[] = { - { - .membase = (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET), - .mapbase = (IXP4XX_UART1_BASE_PHYS), - .irq = IRQ_IXP4XX_UART1, - .flags = UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, - .line = 0, - .type = PORT_XSCALE, - .fifosize = 32 - } , { - .membase = (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET), - .mapbase = (IXP4XX_UART2_BASE_PHYS), - .irq = IRQ_IXP4XX_UART2, - .flags = UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, - .line = 1, - .type = PORT_XSCALE, - .fifosize = 32 - } -}; - -void __init ixdp425_map_io(void) -{ - early_serial_setup(&ixdp425_serial_ports[0]); - early_serial_setup(&ixdp425_serial_ports[1]); - - ixp4xx_map_io(); -} - -static struct flash_platform_data ixdp425_flash_data = { - .map_name = "cfi_probe", - .width = 2, -}; - -static struct resource ixdp425_flash_resource = { - .start = IXDP425_FLASH_BASE, - .end = IXDP425_FLASH_BASE + IXDP425_FLASH_SIZE, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device ixdp425_flash_device = { - .name = "IXP4XX-Flash", - .id = 0, - .dev = { - .platform_data = &ixdp425_flash_data, - }, - .num_resources = 1, - .resource = &ixdp425_flash_resource, -}; - -static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = { - .sda_pin = IXDP425_SDA_PIN, - .scl_pin = IXDP425_SCL_PIN, -}; - -static struct platform_device ixdp425_i2c_controller = { - .name = "IXP4XX-I2C", - .id = 0, - .dev = { - .platform_data = &ixdp425_i2c_gpio_pins, - }, - .num_resources = 0 -}; - -static void __init ixdp425_init(void) -{ - platform_add_device(&ixdp425_flash_device); - platform_add_device(&ixdp425_i2c_controller); -} - -MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") - MAINTAINER("MontaVista Software, Inc.") - BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, - IXP4XX_PERIPHERAL_BASE_VIRT) - MAPIO(ixdp425_map_io) - INITIRQ(ixp4xx_init_irq) - BOOT_PARAMS(0x0100) - INIT_MACHINE(ixdp425_init) -MACHINE_END - -MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") - MAINTAINER("MontaVista Software, Inc.") - BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, - IXP4XX_PERIPHERAL_BASE_VIRT) - MAPIO(ixdp425_map_io) - INITIRQ(ixp4xx_init_irq) - BOOT_PARAMS(0x0100) - INIT_MACHINE(ixdp425_init) -MACHINE_END - -/* - * Avila is functionally equivalent to IXDP425 except that it adds - * a CF IDE slot hanging off the expansion bus. When we have a - * driver for IXP4xx CF IDE with driver model support we'll move - * Avila to it's own setup file. - */ -#ifdef CONFIG_ARCH_AVILA -MACHINE_START(AVILA, "Gateworks Avila Network Platform") - MAINTAINER("Deepak Saxena ") - BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, - IXP4XX_PERIPHERAL_BASE_VIRT) - MAPIO(ixdp425_map_io) - INITIRQ(ixp4xx_init_irq) - BOOT_PARAMS(0x0100) - INIT_MACHINE(ixdp425_init) -MACHINE_END -#endif - diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c deleted file mode 100644 index cb6f6ddb0..000000000 --- a/arch/arm/mach-pxa/leds-mainstone.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/leds-mainstone.c - * - * Author: Nicolas Pitre - * Created: Nov 05, 2002 - * Copyright: MontaVista Software Inc. - * - * 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 "leds.h" - - -/* 8 discrete leds available for general use: */ -#define D28 (1 << 0) -#define D27 (1 << 1) -#define D26 (1 << 2) -#define D25 (1 << 3) -#define D24 (1 << 4) -#define D23 (1 << 5) -#define D22 (1 << 6) -#define D21 (1 << 7) - -#define LED_STATE_ENABLED 1 -#define LED_STATE_CLAIMED 2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -void mainstone_leds_event(led_event_t evt) -{ - unsigned long flags; - - local_irq_save(flags); - - switch (evt) { - case led_start: - hw_led_state = 0; - led_state = LED_STATE_ENABLED; - break; - - case led_stop: - led_state &= ~LED_STATE_ENABLED; - break; - - case led_claim: - led_state |= LED_STATE_CLAIMED; - hw_led_state = 0; - break; - - case led_release: - led_state &= ~LED_STATE_CLAIMED; - hw_led_state = 0; - break; - -#ifdef CONFIG_LEDS_TIMER - case led_timer: - hw_led_state ^= D26; - break; -#endif - -#ifdef CONFIG_LEDS_CPU - case led_idle_start: - hw_led_state &= ~D27; - break; - - case led_idle_end: - hw_led_state |= D27; - break; -#endif - - case led_halted: - break; - - case led_green_on: - hw_led_state |= D21;; - break; - - case led_green_off: - hw_led_state &= ~D21; - break; - - case led_amber_on: - hw_led_state |= D22;; - break; - - case led_amber_off: - hw_led_state &= ~D22; - break; - - case led_red_on: - hw_led_state |= D23;; - break; - - case led_red_off: - hw_led_state &= ~D23; - break; - - default: - break; - } - - if (led_state & LED_STATE_ENABLED) - MST_LEDCTRL = (MST_LEDCTRL | 0xff) & ~hw_led_state; - else - MST_LEDCTRL |= 0xff; - - local_irq_restore(flags); -} diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c deleted file mode 100644 index cd7da1ddf..000000000 --- a/arch/arm/mach-pxa/mainstone.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/mainstone.c - * - * Support for the Intel HCDDBBVA0 Development Platform. - * (go figure how they came up with such name...) - * - * Author: Nicolas Pitre - * Created: Nov 05, 2002 - * Copyright: MontaVista Software Inc. - * - * 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 - -#include -#include -#include - -#include "generic.h" - - -static unsigned long mainstone_irq_enabled; - -static void mainstone_mask_irq(unsigned int irq) -{ - int mainstone_irq = (irq - MAINSTONE_IRQ(0)); - MST_INTMSKENA = (mainstone_irq_enabled &= ~(1 << mainstone_irq)); -} - -static void mainstone_unmask_irq(unsigned int irq) -{ - int mainstone_irq = (irq - MAINSTONE_IRQ(0)); - /* the irq can be acknowledged only if deasserted, so it's done here */ - MST_INTSETCLR &= ~(1 << mainstone_irq); - MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq)); -} - -static struct irqchip mainstone_irq_chip = { - .ack = mainstone_mask_irq, - .mask = mainstone_mask_irq, - .unmask = mainstone_unmask_irq, -}; - - -static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc, - struct pt_regs *regs) -{ - unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled; - do { - GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ - if (likely(pending)) { - irq = MAINSTONE_IRQ(0) + __ffs(pending); - desc = irq_desc + irq; - desc->handle(irq, desc, regs); - } - pending = MST_INTSETCLR & mainstone_irq_enabled; - } while (pending); -} - -static void __init mainstone_init_irq(void) -{ - int irq; - - pxa_init_irq(); - - /* setup extra Mainstone irqs */ - for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { - set_irq_chip(irq, &mainstone_irq_chip); - set_irq_handler(irq, do_level_IRQ); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - set_irq_flags(MAINSTONE_IRQ(8), 0); - set_irq_flags(MAINSTONE_IRQ(12), 0); - - MST_INTMSKENA = 0; - MST_INTSETCLR = 0; - - set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler); - set_irq_type(IRQ_GPIO(0), IRQT_FALLING); -} - - -static struct resource smc91x_resources[] = { - [0] = { - .start = (MST_ETH_PHYS + 0x300), - .end = (MST_ETH_PHYS + 0xfffff), - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MAINSTONE_IRQ(3), - .end = MAINSTONE_IRQ(3), - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device smc91x_device = { - .name = "smc91x", - .id = 0, - .num_resources = ARRAY_SIZE(smc91x_resources), - .resource = smc91x_resources, -}; - -static void __init mainstone_init(void) -{ - platform_add_device(&smc91x_device); -} - - -static struct map_desc mainstone_io_desc[] __initdata = { - { MST_FPGA_VIRT, MST_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */ -}; - -static void __init mainstone_map_io(void) -{ - pxa_map_io(); - iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc)); -} - -MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") - MAINTAINER("MontaVista Software Inc.") - BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) - MAPIO(mainstone_map_io) - INITIRQ(mainstone_init_irq) - INIT_MACHINE(mainstone_init) -MACHINE_END diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c deleted file mode 100644 index f57c96222..000000000 --- a/arch/arm/mach-pxa/pxa25x.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/pxa25x.c - * - * Author: Nicolas Pitre - * Created: Jun 15, 2001 - * Copyright: MontaVista Software Inc. - * - * Code specific to PXA21x/25x/26x variants. - * - * 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. - * - * Since this file should be linked before any other machine specific file, - * the __initcall() here will be executed first. This serves as default - * initialization stuff for PXA machines which can be overridden later if - * need be. - */ -#include -#include -#include -#include - -#include - -#include "generic.h" - -/* - * Various clock factors driven by the CCCR register. - */ - -/* Crystal Frequency to Memory Frequency Multiplier (L) */ -static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, }; - -/* Memory Frequency to Run Mode Frequency Multiplier (M) */ -static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 }; - -/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */ -/* Note: we store the value N * 2 here. */ -static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 }; - -/* Crystal clock */ -#define BASE_CLK 3686400 - -/* - * Get the clock frequency as reflected by CCCR and the turbo flag. - * We assume these values have been applied via a fcs. - * If info is not 0 we also display the current settings. - */ -unsigned int get_clk_frequency_khz(int info) -{ - unsigned long cccr, turbo; - unsigned int l, L, m, M, n2, N; - - cccr = CCCR; - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) ); - - l = L_clk_mult[(cccr >> 0) & 0x1f]; - m = M_clk_mult[(cccr >> 5) & 0x03]; - n2 = N2_clk_mult[(cccr >> 7) & 0x07]; - - L = l * BASE_CLK; - M = m * L; - N = n2 * M / 2; - - if(info) - { - L += 5000; - printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n", - L / 1000000, (L % 1000000) / 10000, l ); - M += 5000; - printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n", - M / 1000000, (M % 1000000) / 10000, m ); - N += 5000; - printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n", - N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5, - (turbo & 1) ? "" : "in" ); - } - - return (turbo & 1) ? (N/1000) : (M/1000); -} - -EXPORT_SYMBOL(get_clk_frequency_khz); - -/* - * Return the current lclk requency in units of 10kHz - */ -unsigned int get_lclk_frequency_10khz(void) -{ - return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000; -} - -EXPORT_SYMBOL(get_lclk_frequency_10khz); - diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c deleted file mode 100644 index 1addceb0f..000000000 --- a/arch/arm/mach-pxa/pxa27x.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/pxa27x.c - * - * Author: Nicolas Pitre - * Created: Nov 05, 2002 - * Copyright: MontaVista Software Inc. - * - * Code specific to PXA27x aka Bulverde. - * - * 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 "generic.h" - -/* Crystal clock : 13-MHZ*/ -#define BASE_CLK 13000000 - -/* - * Get the clock frequency as reflected by CCSR and the turbo flag. - * We assume these values have been applied via a fcs. - * If info is not 0 we also display the current settings. - * - * For more details, refer to Bulverde Manual, section 3.8.2.1 - */ -unsigned int get_clk_frequency_khz( int info) -{ - unsigned long ccsr, turbo, b, ht; - unsigned int l, L, m, M, n2, N, S, cccra; - - ccsr = CCSR; - cccra = CCCR & (0x1 << 25); - - /* Read clkcfg register: it has turbo, b, half-turbo (and f) */ - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) ); - b = (turbo & (0x1 << 3)); - ht = (turbo & (0x1 << 2)); - - l = ccsr & 0x1f; - n2 = (ccsr>>7) & 0xf; - if (l == 31) { - /* The calculation from the Yellow Book is incorrect: - it says M=4 for L=21-30 (which is easy to calculate - by subtracting 1 and then dividing by 10, but not - with 31, so we'll do it manually */ - m = 1 << 2; - } else { - m = 1 << ((l-1)/10); - } - - L = l * BASE_CLK; - N = (n2 * L) / 2; - S = (b) ? L : (L/2); - if (cccra == 0) - M = L/m; - else - M = (b) ? L : (L/2); - - if (info) { - printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n", - L / 1000000, (L % 1000000) / 10000, l ); - printk( KERN_INFO "Memory clock: %d.%02dMHz (/%d)\n", - M / 1000000, (M % 1000000) / 10000, m ); - printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n", - N / 1000000, (N % 1000000)/10000, n2 / 2, (n2 % 2)*5, - (turbo & 1) ? "" : "in" ); - printk( KERN_INFO "System bus clock: %d.%02dMHz \n", - S / 1000000, (S % 1000000) / 10000 ); - } - - return (turbo & 1) ? (N/1000) : (L/1000); -} - -/* - * Return the current mem clock frequency in units of 10kHz as - * reflected by CCCR[A], B, and L - */ -unsigned int get_lclk_frequency_10khz(void) -{ - unsigned long ccsr, clkcfg, b; - unsigned int l, L, m, M, cccra; - - cccra = CCCR & (0x1 << 25); - - /* Read clkcfg register to obtain b */ - asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) ); - b = (clkcfg & (0x1 << 3)); - - ccsr = CCSR; - l = ccsr & 0x1f; - if (l == 31) { - /* The calculation from the Yellow Book is incorrect: - it says M=4 for L=21-30 (which is easy to calculate - by subtracting 1 and then dividing by 10, but not - with 31, so we'll do it manually */ - m = 1 << 2; - } else { - m = 1 << ((l-1)/10); - } - - L = l * BASE_CLK; - if (cccra == 0) - M = L/m; - else - M = (b) ? L : L/2; - - return (M / 10000); -} - -EXPORT_SYMBOL(get_clk_frequency_khz); -EXPORT_SYMBOL(get_lclk_frequency_10khz); - diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu deleted file mode 100644 index d9dd62a56..000000000 --- a/arch/h8300/Kconfig.cpu +++ /dev/null @@ -1,183 +0,0 @@ -menu "Processor type and features" - -choice - prompt "H8/300 platform" - default H8300H_GENERIC - -config H8300H_GENERIC - bool "H8/300H Generic" - help - H8/300H CPU Generic Hardware Support - -config H8300H_AKI3068NET - bool "AE-3068/69" - help - AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support - More Information. (Japanese Only) - - AE-3068/69 Evaluation Board Support - More Information. - - -config H8300H_H8MAX - bool "H8MAX" - help - H8MAX Evaluation Board Support - More Information. (Japanese Only) - - -config H8300H_SIM - bool "H8/300H Simulator" - help - GDB Simulator Support - More Information. - arch/h8300/Doc/simulator.txt - -config H8S_GENERIC - bool "H8S Generic" - help - H8S CPU Generic Hardware Support - -config H8S_EDOSK2674 - bool "EDOSK-2674" - help - Renesas EDOSK-2674 Evaluation Board Support - More Information. - - - -config H8S_SIM - bool "H8S Simulator" - help - GDB Simulator Support - More Information. - arch/h8300/Doc/simulator.txt - -endchoice - -if (H8300H_GENERIC || H8S_GENERIC) -menu "Detail Selection" -if (H8300H_GENERIC) -choice - prompt "CPU Selection" - -config H83002 - bool "H8/3001,3002,3003" - -config H83007 - bool "H8/3006,3007" - -config H83048 - bool "H8/3044,3045,3046,3047,3048,3052" - -config H83068 - bool "H8/3065,3066,3067,3068,3069" -endchoice -endif - -if (H8S_GENERIC) -choice - prompt "CPU Selection" - -config H8S2678 - bool "H8S/2670,2673,2674R,2675,2676" -endchoice -endif - -config CPU_CLOCK - int "CPU Clock Frequency (/1KHz)" - default "20000" - help - CPU Clock Frequency divide to 1000 -endmenu -endif - -if (H8300H_GENERIC || H8S_GENERIC || H8300H_SIM || H8S_SIM || H8S_EDOSK2674) -choice - prompt "Kernel executes from" - ---help--- - Choose the memory type that the kernel will be running in. - -config RAMKERNEL - bool "RAM" - help - The kernel will be resident in RAM when running. - -config ROMKERNEL - bool "ROM" - help - The kernel will be resident in FLASH/ROM when running. - -endchoice -endif - -if (H8300H_AKI3068NET) -config H83068 - bool - default y - -config CPU_CLOCK - int - default "20000" - -config RAMKERNEL - bool - default y -endif - -if (H8300H_H8MAX) -config H83068 - bool - default y - -config CPU_CLOCK - int - default 25000 - -config RAMKERNEL - bool - default y -endif - -if (H8300H_SIM) -config H83007 - bool - default y - -config CPU_CLOCK - int - default "16000" -endif - -if (H8S_EDOSK2674) -config H8S2678 - bool - default y -config CPU_CLOCK - int - default 33000 -endif - -if (H8S_SIM) -config H8S2678 - bool - default y -config CPU_CLOCK - int - default 33000 -endif - -config CPU_H8300H - bool - depends on (H8002 || H83007 || H83048 || H83068) - default y - -config CPU_H8S - bool - depends on H8S2678 - default y - -config PREEMPT - bool "Preemptible Kernel" - default n -endmenu diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c deleted file mode 100644 index 4fd7138a6..000000000 --- a/arch/h8300/kernel/module.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - return 0; -} - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: RELOCATION unsupported\n", - me->name); - return -ENOEXEC; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { - /* This is where to make the change */ - uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr - + rela[i].r_offset); - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rela[i].r_info); - uint32_t v = sym->st_value + rela[i].r_addend; - - switch (ELF32_R_TYPE(rela[i].r_info)) { - case R_H8_DIR24R8: - loc = (uint32_t *)((uint32_t)loc - 1); - *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); - break; - case R_H8_DIR24A8: - if (ELF32_R_SYM(rela[i].r_info)) - *loc += v; - break; - case R_H8_DIR32: - case R_H8_DIR32A16: - *loc += v; - break; - case R_H8_PCREL16: - v -= (unsigned long)loc + 2; - if ((Elf32_Sword)v > 0x7fff || - (Elf32_Sword)v < -(Elf32_Sword)0x8000) - goto overflow; - else - *(unsigned short *)loc = v; - break; - case R_H8_PCREL8: - v -= (unsigned long)loc + 1; - if ((Elf32_Sword)v > 0x7f || - (Elf32_Sword)v < -(Elf32_Sword)0x80) - goto overflow; - else - *(unsigned char *)loc = v; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rela[i].r_info)); - return -ENOEXEC; - } - } - return 0; - overflow: - printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", - me->name, rela[i].r_offset); - return -ENOEXEC; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} diff --git a/arch/i386/kernel/entry_trampoline.c b/arch/i386/kernel/entry_trampoline.c deleted file mode 100644 index 4cce52fa6..000000000 --- a/arch/i386/kernel/entry_trampoline.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * linux/arch/i386/kernel/entry_trampoline.c - * - * (C) Copyright 2003 Ingo Molnar - * - * This file contains the needed support code for 4GB userspace - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern char __entry_tramp_start, __entry_tramp_end, __start___entry_text; - -void __init init_entry_mappings(void) -{ -#ifdef CONFIG_X86_HIGH_ENTRY - - void *tramp; - int p; - - /* - * We need a high IDT and GDT for the 4G/4G split: - */ - trap_init_virtual_IDT(); - - __set_fixmap(FIX_ENTRY_TRAMPOLINE_0, __pa((unsigned long)&__entry_tramp_start), PAGE_KERNEL); - __set_fixmap(FIX_ENTRY_TRAMPOLINE_1, __pa((unsigned long)&__entry_tramp_start) + PAGE_SIZE, PAGE_KERNEL); - tramp = (void *)fix_to_virt(FIX_ENTRY_TRAMPOLINE_0); - - printk("mapped 4G/4G trampoline to %p.\n", tramp); - BUG_ON((void *)&__start___entry_text != tramp); - /* - * Virtual kernel stack: - */ - BUG_ON(__kmap_atomic_vaddr(KM_VSTACK_TOP) & (THREAD_SIZE-1)); - BUG_ON(sizeof(struct desc_struct)*NR_CPUS*GDT_ENTRIES > 2*PAGE_SIZE); - BUG_ON((unsigned int)&__entry_tramp_end - (unsigned int)&__entry_tramp_start > 2*PAGE_SIZE); - - /* - * set up the initial thread's virtual stack related - * fields: - */ - for (p = 0; p < ARRAY_SIZE(current->thread.stack_page); p++) - current->thread.stack_page[p] = virt_to_page((char *)current->thread_info + (p*PAGE_SIZE)); - - current->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK_TOP); - - for (p = 0; p < ARRAY_SIZE(current->thread.stack_page); p++) { - __kunmap_atomic_type(KM_VSTACK_TOP-p); - __kmap_atomic(current->thread.stack_page[p], KM_VSTACK_TOP-p); - } -#endif - current->thread_info->real_stack = (void *)current->thread_info; - current->thread_info->user_pgd = NULL; - current->thread.esp0 = (unsigned long)current->thread_info->real_stack + THREAD_SIZE; -} - - - -void __init entry_trampoline_setup(void) -{ - /* - * old IRQ entries set up by the boot code will still hang - * around - they are a sign of hw trouble anyway, now they'll - * produce a double fault message. - */ - trap_init_virtual_GDT(); -} diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c deleted file mode 100644 index 70db26443..000000000 --- a/arch/i386/mach-es7000/es7000plat.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Written by: Garry Forsgren, Unisys Corporation - * Natalie Protasevich, Unisys Corporation - * This file contains the code to configure and interface - * with Unisys ES7000 series hardware system manager. - * - * Copyright (c) 2003 Unisys Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Unisys Corporation, Township Line & Union Meeting - * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or: - * - * http://www.unisys.com - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "es7000.h" - -/* - * ES7000 Globals - */ - -volatile unsigned long *psai = NULL; -struct mip_reg *mip_reg; -struct mip_reg *host_reg; -int mip_port; -unsigned long mip_addr, host_addr; -extern int (*platform_rename_gsi)(); - -static int __init -es7000_rename_gsi(int ioapic, int gsi) -{ - if (ioapic) - return gsi; - else { - if (gsi == 0) - return 13; - if (gsi == 1) - return 16; - if (gsi == 4) - return 17; - if (gsi == 6) - return 18; - if (gsi == 7) - return 19; - if (gsi == 8) - return 20; - return gsi; - } -} - -/* - * Parse the OEM Table - */ - -int __init -parse_unisys_oem (char *oemptr, int oem_entries) -{ - int i; - int success = 0; - unsigned char type, size; - unsigned long val; - char *tp = NULL; - struct psai *psaip = NULL; - struct mip_reg_info *mi; - struct mip_reg *host, *mip; - - tp = oemptr; - - tp += 8; - - for (i=0; i <= oem_entries; i++) { - type = *tp++; - size = *tp++; - tp -= 2; - switch (type) { - case MIP_REG: - mi = (struct mip_reg_info *)tp; - val = MIP_RD_LO(mi->host_reg); - host_addr = val; - host = (struct mip_reg *)val; - host_reg = __va(host); - val = MIP_RD_LO(mi->mip_reg); - mip_port = MIP_PORT(mi->mip_info); - mip_addr = val; - mip = (struct mip_reg *)val; - mip_reg = __va(mip); - Dprintk("es7000_mipcfg: host_reg = 0x%lx \n", - (unsigned long)host_reg); - Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n", - (unsigned long)mip_reg); - success++; - break; - case MIP_PSAI_REG: - psaip = (struct psai *)tp; - if (tp != NULL) { - if (psaip->addr) - psai = __va(psaip->addr); - else - psai = NULL; - success++; - } - break; - default: - break; - } - if (i == 6) break; - tp += size; - } - - if (success < 2) { - printk("\nNo ES7000 found.\n"); - es7000_plat = 0; - } else { - printk("\nEnabling ES7000 specific features...\n"); - es7000_plat = 1; - platform_rename_gsi = es7000_rename_gsi; - } - return es7000_plat; -} - -int __init -find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length) -{ - struct acpi_table_rsdp *rsdp = NULL; - unsigned long rsdp_phys = 0; - struct acpi_table_header *header = NULL; - int i; - struct acpi_table_sdt sdt; - - rsdp_phys = acpi_find_rsdp(); - rsdp = __va(rsdp_phys); - if (rsdp->rsdt_address) { - struct acpi_table_rsdt *mapped_rsdt = NULL; - sdt.pa = rsdp->rsdt_address; - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); - if (!header) - return -ENODEV; - - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; - mapped_rsdt = (struct acpi_table_rsdt *) - __acpi_map_table(sdt.pa, header->length); - if (!mapped_rsdt) - return -ENODEV; - - header = &mapped_rsdt->header; - - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; - }; - for (i = 0; i < sdt.count; i++) { - - header = (struct acpi_table_header *) - __acpi_map_table(sdt.entry[i].pa, - sizeof(struct acpi_table_header)); - if (!header) - continue; - if (!strncmp((char *) &header->signature, "OEM1", 4)) { - if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) { - void *addr; - struct oem_table *t; - acpi_table_print(header, sdt.entry[i].pa); - t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length); - addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize); - *length = header->length; - *oem_addr = (unsigned long) addr; - return 0; - } - } - } - printk("ES7000: did not find Unisys ACPI OEM table!\n"); - return -1; -} - -static void -es7000_spin(int n) -{ - int i = 0; - - while (i++ < n) - rep_nop(); -} - -static int __init -es7000_mip_write(struct mip_reg *mip_reg) -{ - int status = 0; - int spin; - - spin = MIP_SPIN; - while (((unsigned long long)host_reg->off_38 & - (unsigned long long)MIP_VALID) != 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for Host Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - memcpy(host_reg, mip_reg, sizeof(struct mip_reg)); - outb(1, mip_port); - - spin = MIP_SPIN; - - while (((unsigned long long)mip_reg->off_38 & - (unsigned long long)MIP_VALID) == 0) { - if (--spin <= 0) { - printk("es7000_mip_write: Timeout waiting for MIP Valid Flag"); - return -1; - } - es7000_spin(MIP_SPIN); - } - - status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000) >> 48; - mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & - (unsigned long long)~MIP_VALID); - return status; -} - -int -es7000_start_cpu(int cpu, unsigned long eip) -{ - unsigned long vect = 0, psaival = 0; - - if (psai == NULL) - return -1; - - vect = ((unsigned long)__pa(eip)/0x1000) << 16; - psaival = (0x1000000 | vect | cpu); - - while (*psai & 0x1000000) - ; - - *psai = psaival; - - return 0; - -} - -int -es7000_stop_cpu(int cpu) -{ - int startup; - - if (psai == NULL) - return -1; - - startup= (0x1000000 | cpu); - - while ((*psai & 0xff00ffff) != startup) - ; - - startup = (*psai & 0xff0000) >> 16; - *psai &= 0xffffff; - - return 0; - -} - -void __init -es7000_sw_apic() -{ - if (es7000_plat) { - int mip_status; - struct mip_reg es7000_mip_reg; - - printk("ES7000: Enabling APIC mode.\n"); - memset(&es7000_mip_reg, 0, sizeof(struct mip_reg)); - es7000_mip_reg.off_0 = MIP_SW_APIC; - es7000_mip_reg.off_38 = (MIP_VALID); - while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) - printk("es7000_sw_apic: command failed, status = %x\n", - mip_status); - return; - } -} diff --git a/arch/ia64/scripts/check-serialize.S b/arch/ia64/scripts/check-serialize.S deleted file mode 100644 index 0400c1068..000000000 --- a/arch/ia64/scripts/check-serialize.S +++ /dev/null @@ -1,2 +0,0 @@ - .serialize.data - .serialize.instruction diff --git a/arch/ppc/configs/bubinga_defconfig b/arch/ppc/configs/bubinga_defconfig deleted file mode 100644 index ea60105b2..000000000 --- a/arch/ppc/configs/bubinga_defconfig +++ /dev/null @@ -1,593 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MMU=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_HAVE_DEC_LOCK=y -CONFIG_PPC=y -CONFIG_PPC32=y -CONFIG_GENERIC_NVRAM=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -# CONFIG_STANDALONE is not set -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -# CONFIG_IKCONFIG is not set -CONFIG_EMBEDDED=y -# CONFIG_KALLSYMS is not set -CONFIG_FUTEX=y -# CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# Processor -# -# CONFIG_6xx is not set -CONFIG_40x=y -# CONFIG_44x is not set -# CONFIG_POWER3 is not set -# CONFIG_POWER4 is not set -# CONFIG_8xx is not set -# CONFIG_MATH_EMULATION is not set -# CONFIG_CPU_FREQ is not set -CONFIG_4xx=y - -# -# IBM 4xx options -# -# CONFIG_ASH is not set -CONFIG_BUBINGA=y -# CONFIG_CPCI405 is not set -# CONFIG_EP405 is not set -# CONFIG_OAK is not set -# CONFIG_REDWOOD_5 is not set -# CONFIG_REDWOOD_6 is not set -# CONFIG_SYCAMORE is not set -# CONFIG_WALNUT is not set -CONFIG_IBM405_ERR77=y -CONFIG_IBM405_ERR51=y -CONFIG_IBM_OCP=y -CONFIG_BIOS_FIXUP=y -CONFIG_405EP=y -CONFIG_IBM_OPENBIOS=y -# CONFIG_PM is not set -CONFIG_UART0_TTYS0=y -# CONFIG_UART0_TTYS1 is not set -CONFIG_NOT_COHERENT_CACHE=y - -# -# Platform options -# -# CONFIG_PC_KEYBOARD is not set -# CONFIG_SMP is not set -# CONFIG_PREEMPT is not set -# CONFIG_HIGHMEM is not set -CONFIG_KERNEL_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_CMDLINE_BOOL is not set - -# -# Bus options -# -CONFIG_PCI=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_LEGACY_PROC=y -# CONFIG_PCI_NAMES is not set - -# -# Advanced setup -# -# CONFIG_ADVANCED_OPTIONS is not set - -# -# Default settings for advanced configuration options are used -# -CONFIG_HIGHMEM_START=0xfe000000 -CONFIG_LOWMEM_SIZE=0x30000000 -CONFIG_KERNEL_START=0xc0000000 -CONFIG_TASK_SIZE=0x80000000 -CONFIG_BOOT_LOAD=0x00400000 - -# -# Device Drivers -# - -# -# Generic Driver Options -# - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Macintosh device drivers -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -# CONFIG_OAKNET is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -CONFIG_IBM_EMAC=y -# CONFIG_IBM_EMAC_ERRMSG is not set -CONFIG_IBM_EMAC_RXB=64 -CONFIG_IBM_EMAC_TXB=8 -CONFIG_IBM_EMAC_FGAP=8 -CONFIG_IBM_EMAC_SKBRES=0 -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set -CONFIG_TMPFS=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# IBM 40x options -# - -# -# Library routines -# -CONFIG_CRC32=y - -# -# Kernel hacking -# -# CONFIG_DEBUG_KERNEL is not set -# CONFIG_SERIAL_TEXT_DEBUG is not set -CONFIG_PPC_OCP=y - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set diff --git a/arch/ppc/syslib/ibm_ocp.c b/arch/ppc/syslib/ibm_ocp.c deleted file mode 100644 index 3f6e55c79..000000000 --- a/arch/ppc/syslib/ibm_ocp.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -struct ocp_sys_info_data ocp_sys_info = { - .opb_bus_freq = 50000000, /* OPB Bus Frequency (Hz) */ - .ebc_bus_freq = 33333333, /* EBC Bus Frequency (Hz) */ -}; - -EXPORT_SYMBOL(ocp_sys_info); diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h deleted file mode 100644 index d875d0435..000000000 --- a/arch/um/drivers/cow.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __COW_H__ -#define __COW_H__ - -#include - -#if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(x) (x) -# define htonll(x) (x) -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define ntohll(x) bswap_64(x) -# define htonll(x) bswap_64(x) -#else -#error "__BYTE_ORDER not defined" -#endif - -extern int init_cow_file(int fd, char *cow_file, char *backing_file, - int sectorsize, int alignment, int *bitmap_offset_out, - unsigned long *bitmap_len_out, int *data_offset_out); - -extern int file_reader(__u64 offset, char *buf, int len, void *arg); -extern int read_cow_header(int (*reader)(__u64, char *, int, void *), - void *arg, __u32 *version_out, - char **backing_file_out, time_t *mtime_out, - __u64 *size_out, int *sectorsize_out, - __u32 *align_out, int *bitmap_offset_out); - -extern int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, int alignment, long long *size); - -extern void cow_sizes(int version, __u64 size, int sectorsize, int align, - int bitmap_offset, unsigned long *bitmap_len_out, - int *data_offset_out); - -#endif - -/* - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c deleted file mode 100644 index 014c2c853..000000000 --- a/arch/um/drivers/cow_user.c +++ /dev/null @@ -1,375 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "os.h" - -#include "cow.h" -#include "cow_sys.h" - -#define PATH_LEN_V1 256 - -struct cow_header_v1 { - int magic; - int version; - char backing_file[PATH_LEN_V1]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -#define PATH_LEN_V2 MAXPATHLEN - -struct cow_header_v2 { - unsigned long magic; - unsigned long version; - char backing_file[PATH_LEN_V2]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in - * case other systems have different values for MAXPATHLEN - */ -#define PATH_LEN_V3 4096 - -/* Changes from V2 - - * PATH_LEN_V3 as described above - * Explicitly specify field bit lengths for systems with different - * lengths for the usual C types. Not sure whether char or - * time_t should be changed, this can be changed later without - * breaking compatibility - * Add alignment field so that different alignments can be used for the - * bitmap and data - * Add cow_format field to allow for the possibility of different ways - * of specifying the COW blocks. For now, the only value is 0, - * for the traditional COW bitmap. - * Move the backing_file field to the end of the header. This allows - * for the possibility of expanding it into the padding required - * by the bitmap alignment. - * The bitmap and data portions of the file will be aligned as specified - * by the alignment field. This is to allow COW files to be - * put on devices with restrictions on access alignments, such as - * /dev/raw, with a 512 byte alignment restriction. This also - * allows the data to be more aligned more strictly than on - * sector boundaries. This is needed for ubd-mmap, which needs - * the data to be page aligned. - * Fixed (finally!) the rounding bug - */ - -struct cow_header_v3 { - __u32 magic; - __u32 version; - time_t mtime; - __u64 size; - __u32 sectorsize; - __u32 alignment; - __u32 cow_format; - char backing_file[PATH_LEN_V3]; -}; - -/* COW format definitions - for now, we have only the usual COW bitmap */ -#define COW_BITMAP 0 - -union cow_header { - struct cow_header_v1 v1; - struct cow_header_v2 v2; - struct cow_header_v3 v3; -}; - -#define COW_MAGIC 0x4f4f4f4d /* MOOO */ -#define COW_VERSION 3 - -#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) -#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) - -void cow_sizes(int version, __u64 size, int sectorsize, int align, - int bitmap_offset, unsigned long *bitmap_len_out, - int *data_offset_out) -{ - if(version < 3){ - *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); - - *data_offset_out = bitmap_offset + *bitmap_len_out; - *data_offset_out = (*data_offset_out + sectorsize - 1) / - sectorsize; - *data_offset_out *= sectorsize; - } - else { - *bitmap_len_out = DIV_ROUND(size, sectorsize); - *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); - - *data_offset_out = bitmap_offset + *bitmap_len_out; - *data_offset_out = ROUND_UP(*data_offset_out, align); - } -} - -static int absolutize(char *to, int size, char *from) -{ - char save_cwd[256], *slash; - int remaining; - - if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { - cow_printf("absolutize : unable to get cwd - errno = %d\n", - errno); - return(-1); - } - slash = strrchr(from, '/'); - if(slash != NULL){ - *slash = '\0'; - if(chdir(from)){ - *slash = '/'; - cow_printf("absolutize : Can't cd to '%s' - " - "errno = %d\n", from, errno); - return(-1); - } - *slash = '/'; - if(getcwd(to, size) == NULL){ - cow_printf("absolutize : unable to get cwd of '%s' - " - "errno = %d\n", from, errno); - return(-1); - } - remaining = size - strlen(to); - if(strlen(slash) + 1 > remaining){ - cow_printf("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcat(to, slash); - } - else { - if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ - cow_printf("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcpy(to, save_cwd); - strcat(to, "/"); - strcat(to, from); - } - chdir(save_cwd); - return(0); -} - -int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, int alignment, long long *size) -{ - struct cow_header_v3 *header; - unsigned long modtime; - int err; - - err = cow_seek_file(fd, 0); - if(err < 0){ - cow_printf("write_cow_header - lseek failed, err = %d\n", -err); - goto out; - } - - err = -ENOMEM; - header = cow_malloc(sizeof(*header)); - if(header == NULL){ - cow_printf("Failed to allocate COW V3 header\n"); - goto out; - } - header->magic = htonl(COW_MAGIC); - header->version = htonl(COW_VERSION); - - err = -EINVAL; - if(strlen(backing_file) > sizeof(header->backing_file) - 1){ - cow_printf("Backing file name \"%s\" is too long - names are " - "limited to %d characters\n", backing_file, - sizeof(header->backing_file) - 1); - goto out_free; - } - - if(absolutize(header->backing_file, sizeof(header->backing_file), - backing_file)) - goto out_free; - - err = os_file_modtime(header->backing_file, &modtime); - if(err < 0){ - cow_printf("Backing file '%s' mtime request failed, " - "err = %d\n", header->backing_file, -err); - goto out_free; - } - - err = cow_file_size(header->backing_file, size); - if(err < 0){ - cow_printf("Couldn't get size of backing file '%s', " - "err = %d\n", header->backing_file, -err); - goto out_free; - } - - header->mtime = htonl(modtime); - header->size = htonll(*size); - header->sectorsize = htonl(sectorsize); - header->alignment = htonl(alignment); - header->cow_format = COW_BITMAP; - - err = os_write_file(fd, header, sizeof(*header)); - if(err != sizeof(*header)){ - cow_printf("Write of header to new COW file '%s' failed, " - "err = %d\n", cow_file, -err); - goto out_free; - } - err = 0; - out_free: - cow_free(header); - out: - return(err); -} - -int file_reader(__u64 offset, char *buf, int len, void *arg) -{ - int fd = *((int *) arg); - - return(pread(fd, buf, len, offset)); -} - -/* XXX Need to sanity-check the values read from the header */ - -int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, - __u32 *version_out, char **backing_file_out, - time_t *mtime_out, __u64 *size_out, - int *sectorsize_out, __u32 *align_out, - int *bitmap_offset_out) -{ - union cow_header *header; - char *file; - int err, n; - unsigned long version, magic; - - header = cow_malloc(sizeof(*header)); - if(header == NULL){ - cow_printf("read_cow_header - Failed to allocate header\n"); - return(-ENOMEM); - } - err = -EINVAL; - n = (*reader)(0, (char *) header, sizeof(*header), arg); - if(n < offsetof(typeof(header->v1), backing_file)){ - cow_printf("read_cow_header - short header\n"); - goto out; - } - - magic = header->v1.magic; - if(magic == COW_MAGIC) { - version = header->v1.version; - } - else if(magic == ntohl(COW_MAGIC)){ - version = ntohl(header->v1.version); - } - /* No error printed because the non-COW case comes through here */ - else goto out; - - *version_out = version; - - if(version == 1){ - if(n < sizeof(header->v1)){ - cow_printf("read_cow_header - failed to read V1 " - "header\n"); - goto out; - } - *mtime_out = header->v1.mtime; - *size_out = header->v1.size; - *sectorsize_out = header->v1.sectorsize; - *bitmap_offset_out = sizeof(header->v1); - *align_out = *sectorsize_out; - file = header->v1.backing_file; - } - else if(version == 2){ - if(n < sizeof(header->v2)){ - cow_printf("read_cow_header - failed to read V2 " - "header\n"); - goto out; - } - *mtime_out = ntohl(header->v2.mtime); - *size_out = ntohll(header->v2.size); - *sectorsize_out = ntohl(header->v2.sectorsize); - *bitmap_offset_out = sizeof(header->v2); - *align_out = *sectorsize_out; - file = header->v2.backing_file; - } - else if(version == 3){ - if(n < sizeof(header->v3)){ - cow_printf("read_cow_header - failed to read V2 " - "header\n"); - goto out; - } - *mtime_out = ntohl(header->v3.mtime); - *size_out = ntohll(header->v3.size); - *sectorsize_out = ntohl(header->v3.sectorsize); - *align_out = ntohl(header->v3.alignment); - *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); - file = header->v3.backing_file; - } - else { - cow_printf("read_cow_header - invalid COW version\n"); - goto out; - } - err = -ENOMEM; - *backing_file_out = cow_strdup(file); - if(*backing_file_out == NULL){ - cow_printf("read_cow_header - failed to allocate backing " - "file\n"); - goto out; - } - err = 0; - out: - cow_free(header); - return(err); -} - -int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, - int alignment, int *bitmap_offset_out, - unsigned long *bitmap_len_out, int *data_offset_out) -{ - __u64 size, offset; - char zero = 0; - int err; - - err = write_cow_header(cow_file, fd, backing_file, sectorsize, - alignment, &size); - if(err) - goto out; - - *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); - cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, - bitmap_len_out, data_offset_out); - - offset = *data_offset_out + size - sizeof(zero); - err = cow_seek_file(fd, offset); - if(err < 0){ - cow_printf("cow bitmap lseek failed : err = %d\n", -err); - goto out; - } - - /* does not really matter how much we write it is just to set EOF - * this also sets the entire COW bitmap - * to zero without having to allocate it - */ - err = cow_write_file(fd, &zero, sizeof(zero)); - if(err != sizeof(zero)){ - cow_printf("Write of bitmap to new COW file '%s' failed, " - "err = %d\n", cow_file, -err); - err = -EINVAL; - goto out; - } - - return(0); - - out: - return(err); -} - -/* - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h deleted file mode 100644 index 4bcb829d7..000000000 --- a/arch/um/include/irq_kern.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __IRQ_KERN_H__ -#define __IRQ_KERN_H__ - -#include "linux/interrupt.h" - -extern int um_request_irq(unsigned int irq, int fd, int type, - irqreturn_t (*handler)(int, void *, - struct pt_regs *), - unsigned long irqflags, const char * devname, - void *dev_id); - -#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/mem_kern.h b/arch/um/include/mem_kern.h deleted file mode 100644 index b39f03d94..000000000 --- a/arch/um/include/mem_kern.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __MEM_KERN_H__ -#define __MEM_KERN_H__ - -#include "linux/list.h" -#include "linux/types.h" - -struct remapper { - struct list_head list; - int (*proc)(int, unsigned long, int, __u64); -}; - -extern void register_remapper(struct remapper *info); - -#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/physmem.c b/arch/um/kernel/physmem.c deleted file mode 100644 index d0e0f50dc..000000000 --- a/arch/um/kernel/physmem.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/mm.h" -#include "linux/ghash.h" -#include "linux/slab.h" -#include "linux/vmalloc.h" -#include "linux/bootmem.h" -#include "asm/types.h" -#include "asm/pgtable.h" -#include "kern_util.h" -#include "user_util.h" -#include "mode_kern.h" -#include "mem.h" -#include "mem_user.h" -#include "os.h" -#include "kern.h" -#include "init.h" - -#if 0 -static pgd_t physmem_pgd[PTRS_PER_PGD]; - -static struct phys_desc *lookup_mapping(void *addr) -{ - pgd = &physmem_pgd[pgd_index(addr)]; - if(pgd_none(pgd)) - return(NULL); - - pmd = pmd_offset(pgd, addr); - if(pmd_none(pmd)) - return(NULL); - - pte = pte_offset_kernel(pmd, addr); - return((struct phys_desc *) pte_val(pte)); -} - -static struct add_mapping(void *addr, struct phys_desc *new) -{ -} -#endif - -#define PHYS_HASHSIZE (8192) - -struct phys_desc; - -DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc); - -struct phys_desc { - struct virtmem_ptrs virt_ptrs; - int fd; - __u64 offset; - void *virt; - unsigned long phys; - struct list_head list; -}; - -struct virtmem_table virtmem_hash; - -static int virt_cmp(void *virt1, void *virt2) -{ - return(virt1 != virt2); -} - -static int virt_hash(void *virt) -{ - unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT; - return(addr % PHYS_HASHSIZE); -} - -DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, - virt_hash); - -LIST_HEAD(descriptor_mappings); - -struct desc_mapping { - int fd; - struct list_head list; - struct list_head pages; -}; - -static struct desc_mapping *find_mapping(int fd) -{ - struct desc_mapping *desc; - struct list_head *ele; - - list_for_each(ele, &descriptor_mappings){ - desc = list_entry(ele, struct desc_mapping, list); - if(desc->fd == fd) - return(desc); - } - - return(NULL); -} - -static struct desc_mapping *descriptor_mapping(int fd) -{ - struct desc_mapping *desc; - - desc = find_mapping(fd); - if(desc != NULL) - return(desc); - - desc = kmalloc(sizeof(*desc), GFP_ATOMIC); - if(desc == NULL) - return(NULL); - - *desc = ((struct desc_mapping) - { .fd = fd, - .list = LIST_HEAD_INIT(desc->list), - .pages = LIST_HEAD_INIT(desc->pages) }); - list_add(&desc->list, &descriptor_mappings); - - return(desc); -} - -int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) -{ - struct desc_mapping *fd_maps; - struct phys_desc *desc; - unsigned long phys; - int err; - - fd_maps = descriptor_mapping(fd); - if(fd_maps == NULL) - return(-ENOMEM); - - phys = __pa(virt); - if(find_virtmem_hash(&virtmem_hash, virt) != NULL) - panic("Address 0x%p is already substituted\n", virt); - - err = -ENOMEM; - desc = kmalloc(sizeof(*desc), GFP_ATOMIC); - if(desc == NULL) - goto out; - - *desc = ((struct phys_desc) - { .virt_ptrs = { NULL, NULL }, - .fd = fd, - .offset = offset, - .virt = virt, - .phys = __pa(virt), - .list = LIST_HEAD_INIT(desc->list) }); - insert_virtmem_hash(&virtmem_hash, desc); - - list_add(&desc->list, &fd_maps->pages); - - virt = (void *) ((unsigned long) virt & PAGE_MASK); - err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); - if(!err) - goto out; - - remove_virtmem_hash(&virtmem_hash, desc); - kfree(desc); - out: - return(err); -} - -static int physmem_fd = -1; - -static void remove_mapping(struct phys_desc *desc) -{ - void *virt = desc->virt; - int err; - - remove_virtmem_hash(&virtmem_hash, desc); - list_del(&desc->list); - kfree(desc); - - err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); - if(err) - panic("Failed to unmap block device page from physical memory, " - "errno = %d", -err); -} - -int physmem_remove_mapping(void *virt) -{ - struct phys_desc *desc; - - virt = (void *) ((unsigned long) virt & PAGE_MASK); - desc = find_virtmem_hash(&virtmem_hash, virt); - if(desc == NULL) - return(0); - - remove_mapping(desc); - return(1); -} - -void physmem_forget_descriptor(int fd) -{ - struct desc_mapping *desc; - struct phys_desc *page; - struct list_head *ele, *next; - __u64 offset; - void *addr; - int err; - - desc = find_mapping(fd); - if(desc == NULL) - return; - - list_for_each_safe(ele, next, &desc->pages){ - page = list_entry(ele, struct phys_desc, list); - offset = page->offset; - addr = page->virt; - remove_mapping(page); - err = os_seek_file(fd, offset); - if(err) - panic("physmem_forget_descriptor - failed to seek " - "to %lld in fd %d, error = %d\n", - offset, fd, -err); - err = os_read_file(fd, addr, PAGE_SIZE); - if(err < 0) - panic("physmem_forget_descriptor - failed to read " - "from fd %d to 0x%p, error = %d\n", - fd, addr, -err); - } - - list_del(&desc->list); - kfree(desc); -} - -void arch_free_page(struct page *page, int order) -{ - void *virt; - int i; - - for(i = 0; i < (1 << order); i++){ - virt = __va(page_to_phys(page + i)); - physmem_remove_mapping(virt); - } -} - -int is_remapped(void *virt) -{ - return(find_virtmem_hash(&virtmem_hash, virt) != NULL); -} - -/* Changed during early boot */ -unsigned long high_physmem; - -extern unsigned long physmem_size; - -void *to_virt(unsigned long phys) -{ - return((void *) uml_physmem + phys); -} - -unsigned long to_phys(void *virt) -{ - return(((unsigned long) virt) - uml_physmem); -} - -int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) -{ - struct page *p, *map; - unsigned long phys_len, phys_pages, highmem_len, highmem_pages; - unsigned long iomem_len, iomem_pages, total_len, total_pages; - int i; - - phys_pages = physmem >> PAGE_SHIFT; - phys_len = phys_pages * sizeof(struct page); - - iomem_pages = iomem >> PAGE_SHIFT; - iomem_len = iomem_pages * sizeof(struct page); - - highmem_pages = highmem >> PAGE_SHIFT; - highmem_len = highmem_pages * sizeof(struct page); - - total_pages = phys_pages + iomem_pages + highmem_pages; - total_len = phys_len + iomem_pages + highmem_len; - - if(kmalloc_ok){ - map = kmalloc(total_len, GFP_KERNEL); - if(map == NULL) - map = vmalloc(total_len); - } - else map = alloc_bootmem_low_pages(total_len); - - if(map == NULL) - return(-ENOMEM); - - for(i = 0; i < total_pages; i++){ - p = &map[i]; - set_page_count(p, 0); - SetPageReserved(p); - INIT_LIST_HEAD(&p->lru); - } - - mem_map = map; - max_mapnr = total_pages; - return(0); -} - -struct page *phys_to_page(const unsigned long phys) -{ - return(&mem_map[phys >> PAGE_SHIFT]); -} - -struct page *__virt_to_page(const unsigned long virt) -{ - return(&mem_map[__pa(virt) >> PAGE_SHIFT]); -} - -unsigned long page_to_phys(struct page *page) -{ - return((page - mem_map) << PAGE_SHIFT); -} - -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)); - return(pte); -} - -/* Changed during early boot */ -static unsigned long kmem_top = 0; - -unsigned long get_kmem_end(void) -{ - if(kmem_top == 0) - kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); - return(kmem_top); -} - -void map_memory(unsigned long virt, unsigned long phys, unsigned long len, - int r, int w, int x) -{ - __u64 offset; - int fd, err; - - fd = phys_mapping(phys, &offset); - err = os_map_memory((void *) virt, fd, offset, len, r, w, x); - if(err) - panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " - "err = %d\n", virt, fd, offset, len, r, w, x, err); -} - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) - -void setup_physmem(unsigned long start, unsigned long reserve_end, - unsigned long len, unsigned long highmem) -{ - unsigned long reserve = reserve_end - start; - int pfn = PFN_UP(__pa(reserve_end)); - int delta = (len - reserve) >> PAGE_SHIFT; - int err, offset, bootmap_size; - - physmem_fd = create_mem_file(len + highmem); - - offset = uml_reserved - uml_physmem; - err = os_map_memory((void *) uml_reserved, physmem_fd, offset, - len - offset, 1, 1, 0); - if(err < 0){ - os_print_error(err, "Mapping memory"); - exit(1); - } - - bootmap_size = init_bootmem(pfn, pfn + delta); - free_bootmem(__pa(reserve_end) + bootmap_size, - len - bootmap_size - reserve); -} - -int phys_mapping(unsigned long phys, __u64 *offset_out) -{ - struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, - __va(phys & PAGE_MASK)); - int fd = -1; - - if(desc != NULL){ - fd = desc->fd; - *offset_out = desc->offset; - } - else if(phys < physmem_size){ - fd = physmem_fd; - *offset_out = phys; - } - else if(phys < __pa(end_iomem)){ - struct iomem_region *region = iomem_regions; - - while(region != NULL){ - if((phys >= region->phys) && - (phys < region->phys + region->size)){ - fd = region->fd; - *offset_out = phys - region->phys; - break; - } - region = region->next; - } - } - else if(phys < __pa(end_iomem) + highmem){ - fd = physmem_fd; - *offset_out = phys - iomem_size; - } - - return(fd); -} - -static int __init uml_mem_setup(char *line, int *add) -{ - char *retptr; - physmem_size = memparse(line,&retptr); - return 0; -} -__uml_setup("mem=", uml_mem_setup, -"mem=\n" -" This controls how much \"physical\" memory the kernel allocates\n" -" for the system. The size is specified as a number followed by\n" -" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -" This is not related to the amount of memory in the host. It can\n" -" be more, and the excess, if it's ever used, will just be swapped out.\n" -" Example: mem=64M\n\n" -); - -unsigned long find_iomem(char *driver, unsigned long *len_out) -{ - struct iomem_region *region = iomem_regions; - - while(region != NULL){ - if(!strcmp(region->driver, driver)){ - *len_out = region->size; - return(region->virt); - } - } - - return(0); -} - -int setup_iomem(void) -{ - struct iomem_region *region = iomem_regions; - unsigned long iomem_start = high_physmem + PAGE_SIZE; - int err; - - while(region != NULL){ - err = os_map_memory((void *) iomem_start, region->fd, 0, - region->size, 1, 1, 0); - if(err) - printk("Mapping iomem region for driver '%s' failed, " - "errno = %d\n", region->driver, -err); - else { - region->virt = iomem_start; - region->phys = __pa(region->virt); - } - - iomem_start += region->size + PAGE_SIZE; - region = region->next; - } - - return(0); -} - -__initcall(setup_iomem); - -/* - * 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/uaccess.c b/arch/um/kernel/skas/uaccess.c deleted file mode 100644 index ea82f19b2..000000000 --- a/arch/um/kernel/skas/uaccess.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/stddef.h" -#include "linux/kernel.h" -#include "linux/string.h" -#include "linux/fs.h" -#include "linux/highmem.h" -#include "asm/page.h" -#include "asm/pgtable.h" -#include "asm/uaccess.h" -#include "kern_util.h" - -extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, - pte_t *pte_out); - -static unsigned long maybe_map(unsigned long virt, int is_write) -{ - pte_t pte; - int err; - - void *phys = um_virt_to_phys(current, virt, &pte); - int dummy_code; - - if(IS_ERR(phys) || (is_write && !pte_write(pte))){ - err = handle_page_fault(virt, 0, is_write, 0, &dummy_code); - if(err) - return(0); - phys = um_virt_to_phys(current, virt, NULL); - } - return((unsigned long) phys); -} - -static int do_op(unsigned long addr, int len, int is_write, - int (*op)(unsigned long addr, int len, void *arg), void *arg) -{ - struct page *page; - int n; - - addr = maybe_map(addr, is_write); - if(addr == -1) - return(-1); - - page = phys_to_page(addr); - addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); - n = (*op)(addr, len, arg); - kunmap(page); - - return(n); -} - -static int buffer_op(unsigned long addr, int len, int is_write, - int (*op)(unsigned long addr, int len, void *arg), - void *arg) -{ - int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); - int remain = len, n; - - n = do_op(addr, size, is_write, op, arg); - if(n != 0) - return(n < 0 ? remain : 0); - - addr += size; - remain -= size; - if(remain == 0) - return(0); - - while(addr < ((addr + remain) & PAGE_MASK)){ - n = do_op(addr, PAGE_SIZE, is_write, op, arg); - if(n != 0) - return(n < 0 ? remain : 0); - - addr += PAGE_SIZE; - remain -= PAGE_SIZE; - } - if(remain == 0) - return(0); - - n = do_op(addr, remain, is_write, op, arg); - if(n != 0) - return(n < 0 ? remain : 0); - return(0); -} - -static int copy_chunk_from_user(unsigned long from, int len, void *arg) -{ - unsigned long *to_ptr = arg, to = *to_ptr; - - memcpy((void *) to, (void *) from, len); - *to_ptr += len; - return(0); -} - -int copy_from_user_skas(void *to, const void *from, int n) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); - return(0); - } - - return(access_ok_skas(VERIFY_READ, from, n) ? - buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): - n); -} - -static int copy_chunk_to_user(unsigned long to, int len, void *arg) -{ - unsigned long *from_ptr = arg, from = *from_ptr; - - memcpy((void *) to, (void *) from, len); - *from_ptr += len; - return(0); -} - -int copy_to_user_skas(void *to, const void *from, int n) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); - return(0); - } - - return(access_ok_skas(VERIFY_WRITE, to, n) ? - buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : - n); -} - -static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) -{ - char **to_ptr = arg, *to = *to_ptr; - int n; - - strncpy(to, (void *) from, len); - n = strnlen(to, len); - *to_ptr += n; - - if(n < len) - return(1); - return(0); -} - -int strncpy_from_user_skas(char *dst, const char *src, int count) -{ - int n; - char *ptr = dst; - - if(segment_eq(get_fs(), KERNEL_DS)){ - strncpy(dst, src, count); - return(strnlen(dst, count)); - } - - if(!access_ok_skas(VERIFY_READ, src, 1)) - return(-EFAULT); - - n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, - &ptr); - if(n != 0) - return(-EFAULT); - return(strnlen(dst, count)); -} - -static int clear_chunk(unsigned long addr, int len, void *unused) -{ - memset((void *) addr, 0, len); - return(0); -} - -int __clear_user_skas(void *mem, int len) -{ - return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); -} - -int clear_user_skas(void *mem, int len) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memset(mem, 0, len); - return(0); - } - - return(access_ok_skas(VERIFY_WRITE, mem, len) ? - buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); -} - -static int strnlen_chunk(unsigned long str, int len, void *arg) -{ - int *len_ptr = arg, n; - - n = strnlen((void *) str, len); - *len_ptr += n; - - if(n < len) - return(1); - return(0); -} - -int strnlen_user_skas(const void *str, int len) -{ - int count = 0, n; - - if(segment_eq(get_fs(), KERNEL_DS)) - return(strnlen(str, len) + 1); - - n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); - if(n == 0) - return(count + 1); - return(-EFAULT); -} - -/* - * 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/uaccess.c b/arch/um/kernel/tt/uaccess.c deleted file mode 100644 index 9c8401120..000000000 --- a/arch/um/kernel/tt/uaccess.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "asm/uaccess.h" - -int copy_from_user_tt(void *to, const void *from, int n) -{ - if(!access_ok_tt(VERIFY_READ, from, n)) - return(n); - - return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int copy_to_user_tt(void *to, const void *from, int n) -{ - if(!access_ok_tt(VERIFY_WRITE, to, n)) - return(n); - - return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int strncpy_from_user_tt(char *dst, const char *src, int count) -{ - int n; - - if(!access_ok_tt(VERIFY_READ, src, 1)) - return(-EFAULT); - - n = __do_strncpy_from_user(dst, src, count, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher); - if(n < 0) return(-EFAULT); - return(n); -} - -int __clear_user_tt(void *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) -{ - if(!access_ok_tt(VERIFY_WRITE, mem, len)) - return(len); - - return(__do_clear_user(mem, len, ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -int strnlen_user_tt(const void *str, int len) -{ - return(__do_strnlen_user(str, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -/* - * 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/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c deleted file mode 100644 index ef0fb71e4..000000000 --- a/arch/um/os-Linux/user_syms.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "linux/types.h" -#include "linux/module.h" - -/* Some of this are builtin function (some are not but could in the future), - * so I *must* declare good prototypes for them and then EXPORT them. - * The kernel code uses the macro defined by include/linux/string.h, - * so I undef macros; the userspace code does not include that and I - * add an EXPORT for the glibc one.*/ - -#undef strlen -#undef strstr -#undef memcpy -#undef memset - -extern size_t strlen(const char *); -extern void *memcpy(void *, const void *, size_t); -extern void *memset(void *, int, size_t); -extern int printf(const char *, ...); - -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(printf); - -EXPORT_SYMBOL(strstr); - -/* 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 - */ -#define EXPORT_SYMBOL_PROTO(sym) \ - int sym(void); \ - EXPORT_SYMBOL(sym); - -EXPORT_SYMBOL_PROTO(__errno_location); - -EXPORT_SYMBOL_PROTO(access); -EXPORT_SYMBOL_PROTO(open); -EXPORT_SYMBOL_PROTO(open64); -EXPORT_SYMBOL_PROTO(close); -EXPORT_SYMBOL_PROTO(read); -EXPORT_SYMBOL_PROTO(write); -EXPORT_SYMBOL_PROTO(dup2); -EXPORT_SYMBOL_PROTO(__xstat); -EXPORT_SYMBOL_PROTO(__lxstat); -EXPORT_SYMBOL_PROTO(__lxstat64); -EXPORT_SYMBOL_PROTO(lseek); -EXPORT_SYMBOL_PROTO(lseek64); -EXPORT_SYMBOL_PROTO(chown); -EXPORT_SYMBOL_PROTO(truncate); -EXPORT_SYMBOL_PROTO(utime); -EXPORT_SYMBOL_PROTO(chmod); -EXPORT_SYMBOL_PROTO(rename); -EXPORT_SYMBOL_PROTO(__xmknod); - -EXPORT_SYMBOL_PROTO(symlink); -EXPORT_SYMBOL_PROTO(link); -EXPORT_SYMBOL_PROTO(unlink); -EXPORT_SYMBOL_PROTO(readlink); - -EXPORT_SYMBOL_PROTO(mkdir); -EXPORT_SYMBOL_PROTO(rmdir); -EXPORT_SYMBOL_PROTO(opendir); -EXPORT_SYMBOL_PROTO(readdir); -EXPORT_SYMBOL_PROTO(closedir); -EXPORT_SYMBOL_PROTO(seekdir); -EXPORT_SYMBOL_PROTO(telldir); - -EXPORT_SYMBOL_PROTO(ioctl); - -EXPORT_SYMBOL_PROTO(pread64); -EXPORT_SYMBOL_PROTO(pwrite64); - -EXPORT_SYMBOL_PROTO(statfs); -EXPORT_SYMBOL_PROTO(statfs64); - -EXPORT_SYMBOL_PROTO(getuid); - -/* - * 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/x86_64/kernel/Makefile-HEAD b/arch/x86_64/kernel/Makefile-HEAD deleted file mode 100644 index dc6f2695e..000000000 --- a/arch/x86_64/kernel/Makefile-HEAD +++ /dev/null @@ -1,38 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := head.o head64.o init_task.o vmlinux.lds.s -EXTRA_AFLAGS := -traditional -obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ - ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ - x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bootflag.o e820.o reboot.o warmreboot.o -obj-y += mce.o - -obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ -obj-$(CONFIG_ACPI_BOOT) += acpi/ -obj-$(CONFIG_X86_MSR) += msr.o -obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o -obj-$(CONFIG_PM) += suspend.o -obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o -obj-$(CONFIG_CPU_FREQ) += cpufreq/ -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o -obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o -obj-$(CONFIG_SWIOTLB) += swiotlb.o -obj-$(CONFIG_SCHED_SMT) += domain.o - -obj-$(CONFIG_MODULES) += module.o - -obj-y += topology.o - -bootflag-y += ../../i386/kernel/bootflag.o -cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o -topology-y += ../../i386/mach-default/topology.o -swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o -microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c deleted file mode 100644 index 23488c4d1..000000000 --- a/drivers/ide/arm/ide_arm.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ARM/ARM26 default IDE host driver - * - * Copyright (C) 2004 Bartlomiej Zolnierkiewicz - * Based on code by: Russell King, Ian Molton and Alexander Schulz. - * - * May be copied or modified under the terms of the GNU General Public License. - */ - -#include -#include -#include - -#include -#include - -#ifdef CONFIG_ARM26 -# define IDE_ARM_HOST (machine_is_a5k()) -#else -# define IDE_ARM_HOST (1) -#endif - -#ifdef CONFIG_ARCH_CLPS7500 -# include -# -# define IDE_ARM_IO (ISASLOT_IO + 0x1f0) -# define IDE_ARM_IRQ IRQ_ISA_14 -#else -# define IDE_ARM_IO 0x1f0 -# define IDE_ARM_IRQ IRQ_HARDDISK -#endif - -void __init ide_arm_init(void) -{ - if (IDE_ARM_HOST) { - hw_regs_t hw; - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); - hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, NULL); - } -} diff --git a/drivers/net/ibm_emac/Makefile b/drivers/net/ibm_emac/Makefile deleted file mode 100644 index 7f583a333..000000000 --- a/drivers/net/ibm_emac/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for the IBM PPC4xx EMAC controllers -# - -obj-$(CONFIG_IBM_EMAC) += ibm_emac.o - -ibm_emac-objs := ibm_emac_mal.o ibm_emac_core.o ibm_emac_phy.o - -# Only need this if you want to see additional debug messages -ifeq ($(CONFIG_IBM_EMAC_ERRMSG), y) -ibm_emac-objs += ibm_emac_debug.o -endif diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c deleted file mode 100644 index 0bc7f8242..000000000 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ /dev/null @@ -1,1968 +0,0 @@ -/* - * ibm_emac_core.c - * - * Ethernet driver for the built in ethernet on the IBM 4xx PowerPC - * processors. - * - * (c) 2003 Benjamin Herrenschmidt - * - * Based on original work by - * - * Armin Kuster - * Johnnie Peters - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * TODO - * - Check for races in the "remove" code path - * - Add some Power Management to the MAC and the PHY - * - Audit remaining of non-rewritten code (--BenH) - * - Cleanup message display using msglevel mecanism - * - Address all errata - * - Audit all register update paths to ensure they - * are being written post soft reset if required. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ibm_emac_core.h" - -//#define MDIO_DEBUG(fmt) printk fmt -#define MDIO_DEBUG(fmt) - -//#define LINK_DEBUG(fmt) printk fmt -#define LINK_DEBUG(fmt) - -//#define PKT_DEBUG(fmt) printk fmt -#define PKT_DEBUG(fmt) - -#define DRV_NAME "emac" -#define DRV_VERSION "2.0" -#define DRV_AUTHOR "Benjamin Herrenschmidt " -#define DRV_DESC "IBM EMAC Ethernet driver" - -/* - * When mdio_idx >= 0, contains a list of emac ocp_devs - * that have had their initialization deferred until the - * common MDIO controller has been initialized. - */ -LIST_HEAD(emac_init_list); - -MODULE_AUTHOR(DRV_AUTHOR); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_LICENSE("GPL"); - -static int skb_res = SKB_RES; -module_param(skb_res, int, 0444); -MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n" - "The 405 handles a misaligned IP header fine but\n" - "this can help if you are routing to a tunnel or a\n" - "device that needs aligned data. 0..2"); - -#define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev)) - -static unsigned int rgmii_enable[] = - { RGMII_RTBI, RGMII_RGMII, RGMII_TBI, RGMII_GMII }; - -static unsigned int rgmii_speed_mask[] = { 0, - 0, - RGMII_MII2_SPDMASK, - RGMII_MII3_SPDMASK -}; - -static unsigned int rgmii_speed100[] = { 0, - 0, - RGMII_MII2_100MB, - RGMII_MII3_100MB -}; - -static unsigned int rgmii_speed1000[] = { 0, - 0, - RGMII_MII2_1000MB, - RGMII_MII3_1000MB -}; - -#define ZMII_PRIV(ocpdev) ((struct ibm_ocp_zmii*)ocp_get_drvdata(ocpdev)) - -static unsigned int zmii_enable[][4] = { - {ZMII_SMII0, ZMII_RMII0, ZMII_MII0, - ~(ZMII_MDI1 | ZMII_MDI2 | ZMII_MDI3)}, - {ZMII_SMII1, ZMII_RMII1, ZMII_MII1, - ~(ZMII_MDI0 | ZMII_MDI2 | ZMII_MDI3)}, - {ZMII_SMII2, ZMII_RMII2, ZMII_MII2, - ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)}, - {ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)} -}; -static unsigned int mdi_enable[] = - { ZMII_MDI0, ZMII_MDI1, ZMII_MDI2, ZMII_MDI3 }; - -static unsigned int zmii_speed = 0x0; -static unsigned int zmii_speed100[] = { ZMII_MII0_100MB, ZMII_MII1_100MB }; - -/* Since multiple EMACs share MDIO lines in various ways, we need - * to avoid re-using the same PHY ID in cases where the arch didn't - * setup precise phy_map entries - */ -static u32 busy_phy_map = 0; - -/* If EMACs share a common MDIO device, this points to it */ -static struct net_device *mdio_ndev = NULL; - -struct emac_def_dev { - struct list_head link; - struct ocp_device *ocpdev; - struct ibm_ocp_mal *mal; -}; - -static struct net_device_stats *emac_stats(struct net_device *dev) -{ - struct ocp_enet_private *fep = dev->priv; - return &fep->stats; -}; - -static int -emac_init_rgmii(struct ocp_device *rgmii_dev, int input, int phy_mode) -{ - struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(rgmii_dev); - const char *mode_name[] = { "RTBI", "RGMII", "TBI", "GMII" }; - int mode = -1; - - if (!rgmii) { - rgmii = kmalloc(sizeof(struct ibm_ocp_rgmii), GFP_KERNEL); - - if (rgmii == NULL) { - printk(KERN_ERR - "rgmii%d: Out of memory allocating RGMII structure!\n", - rgmii_dev->def->index); - return -ENOMEM; - } - - memset(rgmii, 0, sizeof(*rgmii)); - - rgmii->base = - (struct rgmii_regs *)ioremap(rgmii_dev->def->paddr, - sizeof(*rgmii->base)); - if (rgmii->base == NULL) { - printk(KERN_ERR - "rgmii%d: Cannot ioremap bridge registers!\n", - rgmii_dev->def->index); - - kfree(rgmii); - return -ENOMEM; - } - ocp_set_drvdata(rgmii_dev, rgmii); - } - - if (phy_mode) { - switch (phy_mode) { - case PHY_MODE_GMII: - mode = GMII; - break; - case PHY_MODE_TBI: - mode = TBI; - break; - case PHY_MODE_RTBI: - mode = RTBI; - break; - case PHY_MODE_RGMII: - default: - mode = RGMII; - } - rgmii->base->fer &= ~RGMII_FER_MASK(input); - rgmii->base->fer |= rgmii_enable[mode] << (4 * input); - } else { - switch ((rgmii->base->fer & RGMII_FER_MASK(input)) >> (4 * - input)) { - case RGMII_RTBI: - mode = RTBI; - break; - case RGMII_RGMII: - mode = RGMII; - break; - case RGMII_TBI: - mode = TBI; - break; - case RGMII_GMII: - mode = GMII; - } - } - - /* Set mode to RGMII if nothing valid is detected */ - if (mode < 0) - mode = RGMII; - - printk(KERN_NOTICE "rgmii%d: input %d in %s mode\n", - rgmii_dev->def->index, input, mode_name[mode]); - - rgmii->mode[input] = mode; - rgmii->users++; - - return 0; -} - -static void -emac_rgmii_port_speed(struct ocp_device *ocpdev, int input, int speed) -{ - struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev); - unsigned int rgmii_speed; - - rgmii_speed = in_be32(&rgmii->base->ssr); - - rgmii_speed &= ~rgmii_speed_mask[input]; - - if (speed == 1000) - rgmii_speed |= rgmii_speed1000[input]; - else if (speed == 100) - rgmii_speed |= rgmii_speed100[input]; - - out_be32(&rgmii->base->ssr, rgmii_speed); -} - -static void emac_close_rgmii(struct ocp_device *ocpdev) -{ - struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(ocpdev); - BUG_ON(!rgmii || rgmii->users == 0); - - if (!--rgmii->users) { - ocp_set_drvdata(ocpdev, NULL); - iounmap((void *)rgmii->base); - kfree(rgmii); - } -} - -static int emac_init_zmii(struct ocp_device *zmii_dev, int input, int phy_mode) -{ - struct ibm_ocp_zmii *zmii = ZMII_PRIV(zmii_dev); - const char *mode_name[] = { "SMII", "RMII", "MII" }; - int mode = -1; - - if (!zmii) { - zmii = kmalloc(sizeof(struct ibm_ocp_zmii), GFP_KERNEL); - if (zmii == NULL) { - printk(KERN_ERR - "zmii%d: Out of memory allocating ZMII structure!\n", - zmii_dev->def->index); - return -ENOMEM; - } - memset(zmii, 0, sizeof(*zmii)); - - zmii->base = - (struct zmii_regs *)ioremap(zmii_dev->def->paddr, - sizeof(*zmii->base)); - if (zmii->base == NULL) { - printk(KERN_ERR - "zmii%d: Cannot ioremap bridge registers!\n", - zmii_dev->def->index); - - kfree(zmii); - return -ENOMEM; - } - ocp_set_drvdata(zmii_dev, zmii); - } - - if (phy_mode) { - switch (phy_mode) { - case PHY_MODE_MII: - mode = MII; - break; - case PHY_MODE_RMII: - mode = RMII; - break; - case PHY_MODE_SMII: - default: - mode = SMII; - } - zmii->base->fer &= ~ZMII_FER_MASK(input); - zmii->base->fer |= zmii_enable[input][mode]; - } else { - switch ((zmii->base->fer & ZMII_FER_MASK(input)) << (4 * input)) { - case ZMII_MII0: - mode = MII; - break; - case ZMII_RMII0: - mode = RMII; - break; - case ZMII_SMII0: - mode = SMII; - } - } - - /* Set mode to SMII if nothing valid is detected */ - if (mode < 0) - mode = SMII; - - printk(KERN_NOTICE "zmii%d: input %d in %s mode\n", - zmii_dev->def->index, input, mode_name[mode]); - - zmii->mode[input] = mode; - zmii->users++; - - return 0; -} - -static void emac_enable_zmii_port(struct ocp_device *ocpdev, int input) -{ - u32 mask; - struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev); - - mask = in_be32(&zmii->base->fer); - mask &= zmii_enable[input][MDI]; /* turn all non enabled MDI's off */ - mask |= zmii_enable[input][zmii->mode[input]] | mdi_enable[input]; - out_be32(&zmii->base->fer, mask); -} - -static void -emac_zmii_port_speed(struct ocp_device *ocpdev, int input, int speed) -{ - struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev); - - if (speed == 100) - zmii_speed |= zmii_speed100[input]; - else - zmii_speed &= ~zmii_speed100[input]; - - out_be32(&zmii->base->ssr, zmii_speed); -} - -static void emac_close_zmii(struct ocp_device *ocpdev) -{ - struct ibm_ocp_zmii *zmii = ZMII_PRIV(ocpdev); - BUG_ON(!zmii || zmii->users == 0); - - if (!--zmii->users) { - ocp_set_drvdata(ocpdev, NULL); - iounmap((void *)zmii->base); - kfree(zmii); - } -} - -int emac_phy_read(struct net_device *dev, int mii_id, int reg) -{ - uint32_t stacr; - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - - MDIO_DEBUG(("%s: phy_read, id: 0x%x, reg: 0x%x\n", dev->name, mii_id, - reg)); - - /* Enable proper ZMII port */ - if (fep->zmii_dev) - emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input); - - /* Use the EMAC that has the MDIO port */ - if (fep->mdio_dev) { - dev = fep->mdio_dev; - fep = dev->priv; - emacp = fep->emacp; - } - - udelay(MDIO_DELAY); - - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) { - printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name); - return -1; - } - - /* Clear the speed bits and make a read request to the PHY */ - stacr = ((EMAC_STACR_READ | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ); - stacr |= ((mii_id & 0x1F) << 5); - - out_be32(&emacp->em0stacr, stacr); - - udelay(MDIO_DELAY); - stacr = in_be32(&emacp->em0stacr); - - if ((stacr & EMAC_STACR_OC) == 0) { - printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name); - return -1; - } - - /* Check for a read error */ - if (stacr & EMAC_STACR_PHYE) { - MDIO_DEBUG(("EMAC MDIO PHY error !\n")); - return -1; - } - - MDIO_DEBUG((" -> 0x%x\n", stacr >> 16)); - - return (stacr >> 16); -} - -void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data) -{ - uint32_t stacr; - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - - MDIO_DEBUG(("%s phy_write, id: 0x%x, reg: 0x%x, data: 0x%x\n", - dev->name, mii_id, reg, data)); - - /* Enable proper ZMII port */ - if (fep->zmii_dev) - emac_enable_zmii_port(fep->zmii_dev, fep->zmii_input); - - /* Use the EMAC that has the MDIO port */ - if (fep->mdio_dev) { - dev = fep->mdio_dev; - fep = dev->priv; - emacp = fep->emacp; - } - - udelay(MDIO_DELAY); - - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) { - printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name); - return; - } - - /* Clear the speed bits and make a read request to the PHY */ - - stacr = ((EMAC_STACR_WRITE | (reg & 0x1f)) & ~EMAC_STACR_CLK_100MHZ); - stacr |= ((mii_id & 0x1f) << 5) | ((data & 0xffff) << 16); - - out_be32(&emacp->em0stacr, stacr); - - udelay(MDIO_DELAY); - - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) - printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name); - - /* Check for a write error */ - if ((stacr & EMAC_STACR_PHYE) != 0) { - MDIO_DEBUG(("EMAC MDIO PHY error !\n")); - } -} - -static void emac_txeob_dev(void *param, u32 chanmask) -{ - struct net_device *dev = param; - struct ocp_enet_private *fep = dev->priv; - unsigned long flags; - - spin_lock_irqsave(&fep->lock, flags); - - PKT_DEBUG(("emac_txeob_dev() entry, tx_cnt: %d\n", fep->tx_cnt)); - - while (fep->tx_cnt && - !(fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_READY)) { - - if (fep->tx_desc[fep->ack_slot].ctrl & MAL_TX_CTRL_LAST) { - /* Tell the system the transmit completed. */ - dma_unmap_single(&fep->ocpdev->dev, - fep->tx_desc[fep->ack_slot].data_ptr, - fep->tx_desc[fep->ack_slot].data_len, - DMA_TO_DEVICE); - dev_kfree_skb_irq(fep->tx_skb[fep->ack_slot]); - - if (fep->tx_desc[fep->ack_slot].ctrl & - (EMAC_TX_ST_EC | EMAC_TX_ST_MC | EMAC_TX_ST_SC)) - fep->stats.collisions++; - } - - fep->tx_skb[fep->ack_slot] = (struct sk_buff *)NULL; - if (++fep->ack_slot == NUM_TX_BUFF) - fep->ack_slot = 0; - - fep->tx_cnt--; - } - if (fep->tx_cnt < NUM_TX_BUFF) - netif_wake_queue(dev); - - PKT_DEBUG(("emac_txeob_dev() exit, tx_cnt: %d\n", fep->tx_cnt)); - - spin_unlock_irqrestore(&fep->lock, flags); -} - -/* - Fill/Re-fill the rx chain with valid ctrl/ptrs. - This function will fill from rx_slot up to the parm end. - So to completely fill the chain pre-set rx_slot to 0 and - pass in an end of 0. - */ -static void emac_rx_fill(struct net_device *dev, int end) -{ - int i; - struct ocp_enet_private *fep = dev->priv; - - i = fep->rx_slot; - do { - /* We don't want the 16 bytes skb_reserve done by dev_alloc_skb, - * it breaks our cache line alignement. However, we still allocate - * +16 so that we end up allocating the exact same size as - * dev_alloc_skb() would do. - * Also, because of the skb_res, the max DMA size we give to EMAC - * is slighly wrong, causing it to potentially DMA 2 more bytes - * from a broken/oversized packet. These 16 bytes will take care - * that we don't walk on somebody else toes with that. - */ - fep->rx_skb[i] = - alloc_skb(fep->rx_buffer_size + 16, GFP_ATOMIC); - - if (fep->rx_skb[i] == NULL) { - /* Keep rx_slot here, the next time clean/fill is called - * we will try again before the MAL wraps back here - * If the MAL tries to use this descriptor with - * the EMPTY bit off it will cause the - * rxde interrupt. That is where we will - * try again to allocate an sk_buff. - */ - break; - - } - - if (skb_res) - skb_reserve(fep->rx_skb[i], skb_res); - - /* We must NOT dma_map_single the cache line right after the - * buffer, so we must crop our sync size to account for the - * reserved space - */ - fep->rx_desc[i].data_ptr = - (unsigned char *)dma_map_single(&fep->ocpdev->dev, - (void *)fep->rx_skb[i]-> - data, - fep->rx_buffer_size - - skb_res, DMA_FROM_DEVICE); - - /* - * Some 4xx implementations use the previously - * reserved bits in data_len to encode the MS - * 4-bits of a 36-bit physical address (ERPN) - * This must be initialized. - */ - fep->rx_desc[i].data_len = 0; - fep->rx_desc[i].ctrl = MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR | - (i == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0); - - } while ((i = (i + 1) % NUM_RX_BUFF) != end); - - fep->rx_slot = i; -} - -static void -emac_rx_csum(struct net_device *dev, unsigned short ctrl, struct sk_buff *skb) -{ - struct ocp_enet_private *fep = dev->priv; - - /* Exit if interface has no TAH engine */ - if (!fep->tah_dev) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* Check for TCP/UDP/IP csum error */ - if (ctrl & EMAC_CSUM_VER_ERROR) { - /* Let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; -/* adapter->hw_csum_err++; */ - } else { - /* Csum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; -/* adapter->hw_csum_good++; */ - } -} - -static int emac_rx_clean(struct net_device *dev) -{ - int i, b, bnum, buf[6]; - int error, frame_length; - struct ocp_enet_private *fep = dev->priv; - unsigned short ctrl; - - i = fep->rx_slot; - - PKT_DEBUG(("emac_rx_clean() entry, rx_slot: %d\n", fep->rx_slot)); - - do { - if (fep->rx_skb[i] == NULL) - continue; /*we have already handled the packet but haved failed to alloc */ - /* - since rx_desc is in uncached mem we don't keep reading it directly - we pull out a local copy of ctrl and do the checks on the copy. - */ - ctrl = fep->rx_desc[i].ctrl; - if (ctrl & MAL_RX_CTRL_EMPTY) - break; /*we don't have any more ready packets */ - - if (EMAC_IS_BAD_RX_PACKET(ctrl)) { - fep->stats.rx_errors++; - fep->stats.rx_dropped++; - - if (ctrl & EMAC_RX_ST_OE) - fep->stats.rx_fifo_errors++; - if (ctrl & EMAC_RX_ST_AE) - fep->stats.rx_frame_errors++; - if (ctrl & EMAC_RX_ST_BFCS) - fep->stats.rx_crc_errors++; - if (ctrl & (EMAC_RX_ST_RP | EMAC_RX_ST_PTL | - EMAC_RX_ST_ORE | EMAC_RX_ST_IRE)) - fep->stats.rx_length_errors++; - } else { - if ((ctrl & (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) == - (MAL_RX_CTRL_FIRST | MAL_RX_CTRL_LAST)) { - /* Single descriptor packet */ - emac_rx_csum(dev, ctrl, fep->rx_skb[i]); - /* Send the skb up the chain. */ - frame_length = fep->rx_desc[i].data_len - 4; - skb_put(fep->rx_skb[i], frame_length); - fep->rx_skb[i]->dev = dev; - fep->rx_skb[i]->protocol = - eth_type_trans(fep->rx_skb[i], dev); - error = netif_rx(fep->rx_skb[i]); - - if ((error == NET_RX_DROP) || - (error == NET_RX_BAD)) { - fep->stats.rx_dropped++; - } else { - fep->stats.rx_packets++; - fep->stats.rx_bytes += frame_length; - } - fep->rx_skb[i] = NULL; - } else { - /* Multiple descriptor packet */ - if (ctrl & MAL_RX_CTRL_FIRST) { - if (fep->rx_desc[(i + 1) % NUM_RX_BUFF]. - ctrl & MAL_RX_CTRL_EMPTY) - break; - bnum = 0; - buf[bnum] = i; - ++bnum; - continue; - } - if (((ctrl & MAL_RX_CTRL_FIRST) != - MAL_RX_CTRL_FIRST) && - ((ctrl & MAL_RX_CTRL_LAST) != - MAL_RX_CTRL_LAST)) { - if (fep->rx_desc[(i + 1) % - NUM_RX_BUFF].ctrl & - MAL_RX_CTRL_EMPTY) { - i = buf[0]; - break; - } - buf[bnum] = i; - ++bnum; - continue; - } - if (ctrl & MAL_RX_CTRL_LAST) { - buf[bnum] = i; - ++bnum; - skb_put(fep->rx_skb[buf[0]], - fep->rx_desc[buf[0]].data_len); - for (b = 1; b < bnum; b++) { - /* - * MAL is braindead, we need - * to copy the remainder - * of the packet from the - * latter descriptor buffers - * to the first skb. Then - * dispose of the source - * skbs. - * - * Once the stack is fixed - * to handle frags on most - * protocols we can generate - * a fragmented skb with - * no copies. - */ - memcpy(fep->rx_skb[buf[0]]-> - data + - fep->rx_skb[buf[0]]->len, - fep->rx_skb[buf[b]]-> - data, - fep->rx_desc[buf[b]]. - data_len); - skb_put(fep->rx_skb[buf[0]], - fep->rx_desc[buf[b]]. - data_len); - dma_unmap_single(&fep->ocpdev-> - dev, - fep-> - rx_desc[buf - [b]]. - data_ptr, - fep-> - rx_desc[buf - [b]]. - data_len, - DMA_FROM_DEVICE); - dev_kfree_skb(fep-> - rx_skb[buf[b]]); - } - emac_rx_csum(dev, ctrl, - fep->rx_skb[buf[0]]); - - fep->rx_skb[buf[0]]->dev = dev; - fep->rx_skb[buf[0]]->protocol = - eth_type_trans(fep->rx_skb[buf[0]], - dev); - error = netif_rx(fep->rx_skb[buf[0]]); - - if ((error == NET_RX_DROP) - || (error == NET_RX_BAD)) { - fep->stats.rx_dropped++; - } else { - fep->stats.rx_packets++; - fep->stats.rx_bytes += - fep->rx_skb[buf[0]]->len; - } - for (b = 0; b < bnum; b++) - fep->rx_skb[buf[b]] = NULL; - } - } - } - } while ((i = (i + 1) % NUM_RX_BUFF) != fep->rx_slot); - - PKT_DEBUG(("emac_rx_clean() exit, rx_slot: %d\n", fep->rx_slot)); - - return i; -} - -static void emac_rxeob_dev(void *param, u32 chanmask) -{ - struct net_device *dev = param; - struct ocp_enet_private *fep = dev->priv; - unsigned long flags; - int n; - - spin_lock_irqsave(&fep->lock, flags); - if ((n = emac_rx_clean(dev)) != fep->rx_slot) - emac_rx_fill(dev, n); - spin_unlock_irqrestore(&fep->lock, flags); -} - -/* - * This interrupt should never occurr, we don't program - * the MAL for contiunous mode. - */ -static void emac_txde_dev(void *param, u32 chanmask) -{ - struct net_device *dev = param; - struct ocp_enet_private *fep = dev->priv; - - printk(KERN_WARNING "%s: transmit descriptor error\n", dev->name); - - emac_mac_dump(dev); - emac_mal_dump(dev); - - /* Reenable the transmit channel */ - mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask); -} - -/* - * This interrupt should be very rare at best. This occurs when - * the hardware has a problem with the receive descriptors. The manual - * states that it occurs when the hardware cannot the receive descriptor - * empty bit is not set. The recovery mechanism will be to - * traverse through the descriptors, handle any that are marked to be - * handled and reinitialize each along the way. At that point the driver - * will be restarted. - */ -static void emac_rxde_dev(void *param, u32 chanmask) -{ - struct net_device *dev = param; - struct ocp_enet_private *fep = dev->priv; - unsigned long flags; - - if (net_ratelimit()) { - printk(KERN_WARNING "%s: receive descriptor error\n", - fep->ndev->name); - - emac_mac_dump(dev); - emac_mal_dump(dev); - emac_desc_dump(dev); - } - - /* Disable RX channel */ - spin_lock_irqsave(&fep->lock, flags); - mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - - /* For now, charge the error against all emacs */ - fep->stats.rx_errors++; - - /* so do we have any good packets still? */ - emac_rx_clean(dev); - - /* When the interface is restarted it resets processing to the - * first descriptor in the table. - */ - - fep->rx_slot = 0; - emac_rx_fill(dev, 0); - - set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, fep->commac.rx_chan_mask); - set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, fep->commac.rx_chan_mask); - - /* Reenable the receive channels */ - mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - spin_unlock_irqrestore(&fep->lock, flags); -} - -static irqreturn_t -emac_mac_irq(int irq, void *dev_instance, struct pt_regs *regs) -{ - struct net_device *dev = dev_instance; - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - unsigned long tmp_em0isr; - - /* EMAC interrupt */ - tmp_em0isr = in_be32(&emacp->em0isr); - if (tmp_em0isr & (EMAC_ISR_TE0 | EMAC_ISR_TE1)) { - /* This error is a hard transmit error - could retransmit */ - fep->stats.tx_errors++; - - /* Reenable the transmit channel */ - mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask); - - } else { - fep->stats.rx_errors++; - } - - if (tmp_em0isr & EMAC_ISR_RP) - fep->stats.rx_length_errors++; - if (tmp_em0isr & EMAC_ISR_ALE) - fep->stats.rx_frame_errors++; - if (tmp_em0isr & EMAC_ISR_BFCS) - fep->stats.rx_crc_errors++; - if (tmp_em0isr & EMAC_ISR_PTLE) - fep->stats.rx_length_errors++; - if (tmp_em0isr & EMAC_ISR_ORE) - fep->stats.rx_length_errors++; - if (tmp_em0isr & EMAC_ISR_TE0) - fep->stats.tx_aborted_errors++; - - emac_err_dump(dev, tmp_em0isr); - - out_be32(&emacp->em0isr, tmp_em0isr); - - return IRQ_HANDLED; -} - -static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned short ctrl; - unsigned long flags; - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - int len = skb->len; - unsigned int offset = 0, size, f, tx_slot_first; - unsigned int nr_frags = skb_shinfo(skb)->nr_frags; - - spin_lock_irqsave(&fep->lock, flags); - - len -= skb->data_len; - - if ((fep->tx_cnt + nr_frags + len / DESC_BUF_SIZE + 1) > NUM_TX_BUFF) { - PKT_DEBUG(("emac_start_xmit() stopping queue\n")); - netif_stop_queue(dev); - spin_unlock_irqrestore(&fep->lock, flags); - restore_flags(flags); - return -EBUSY; - } - - tx_slot_first = fep->tx_slot; - - while (len) { - size = min(len, DESC_BUF_SIZE); - - fep->tx_desc[fep->tx_slot].data_len = (short)size; - fep->tx_desc[fep->tx_slot].data_ptr = - (unsigned char *)dma_map_single(&fep->ocpdev->dev, - (void *)((unsigned int)skb-> - data + offset), - size, DMA_TO_DEVICE); - - ctrl = EMAC_TX_CTRL_DFLT; - if (fep->tx_slot != tx_slot_first) - ctrl |= MAL_TX_CTRL_READY; - if ((NUM_TX_BUFF - 1) == fep->tx_slot) - ctrl |= MAL_TX_CTRL_WRAP; - if (!nr_frags && (len == size)) { - ctrl |= MAL_TX_CTRL_LAST; - fep->tx_skb[fep->tx_slot] = skb; - } - if (skb->ip_summed == CHECKSUM_HW) - ctrl |= EMAC_TX_CTRL_TAH_CSUM; - - fep->tx_desc[fep->tx_slot].ctrl = ctrl; - - len -= size; - offset += size; - - /* Bump tx count */ - if (++fep->tx_cnt == NUM_TX_BUFF) - netif_stop_queue(dev); - - /* Next descriptor */ - if (++fep->tx_slot == NUM_TX_BUFF) - fep->tx_slot = 0; - } - - for (f = 0; f < nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = frag->size; - offset = 0; - - while (len) { - size = min(len, DESC_BUF_SIZE); - - dma_map_page(&fep->ocpdev->dev, - frag->page, - frag->page_offset + offset, - size, DMA_TO_DEVICE); - - ctrl = EMAC_TX_CTRL_DFLT | MAL_TX_CTRL_READY; - if ((NUM_TX_BUFF - 1) == fep->tx_slot) - ctrl |= MAL_TX_CTRL_WRAP; - if ((f == (nr_frags - 1)) && (len == size)) { - ctrl |= MAL_TX_CTRL_LAST; - fep->tx_skb[fep->tx_slot] = skb; - } - - if (skb->ip_summed == CHECKSUM_HW) - ctrl |= EMAC_TX_CTRL_TAH_CSUM; - - fep->tx_desc[fep->tx_slot].data_len = (short)size; - fep->tx_desc[fep->tx_slot].data_ptr = - (char *)((page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset + offset); - fep->tx_desc[fep->tx_slot].ctrl = ctrl; - - len -= size; - offset += size; - - /* Bump tx count */ - if (++fep->tx_cnt == NUM_TX_BUFF) - netif_stop_queue(dev); - - /* Next descriptor */ - if (++fep->tx_slot == NUM_TX_BUFF) - fep->tx_slot = 0; - } - } - - /* - * Deferred set READY on first descriptor of packet to - * avoid TX MAL race. - */ - fep->tx_desc[tx_slot_first].ctrl |= MAL_TX_CTRL_READY; - - /* Send the packet out. */ - out_be32(&emacp->em0tmr0, EMAC_TMR0_XMIT); - - fep->stats.tx_packets++; - fep->stats.tx_bytes += skb->len; - - PKT_DEBUG(("emac_start_xmit() exitn")); - - spin_unlock_irqrestore(&fep->lock, flags); - - return 0; -} - -static int emac_adjust_to_link(struct ocp_enet_private *fep) -{ - emac_t *emacp = fep->emacp; - struct ibm_ocp_rgmii *rgmii; - unsigned long mode_reg; - int full_duplex, speed; - - full_duplex = 0; - speed = SPEED_10; - - /* set mode register 1 defaults */ - mode_reg = EMAC_M1_DEFAULT; - - /* Read link mode on PHY */ - if (fep->phy_mii.def->ops->read_link(&fep->phy_mii) == 0) { - /* If an error occurred, we don't deal with it yet */ - full_duplex = (fep->phy_mii.duplex == DUPLEX_FULL); - speed = fep->phy_mii.speed; - } - - if (fep->rgmii_dev) - rgmii = RGMII_PRIV(fep->rgmii_dev); - - /* set speed (default is 10Mb) */ - switch (speed) { - case SPEED_1000: - mode_reg |= EMAC_M1_JUMBO_ENABLE | EMAC_M1_RFS_16K; - if ((rgmii->mode[fep->rgmii_input] == RTBI) - || (rgmii->mode[fep->rgmii_input] == TBI)) - mode_reg |= EMAC_M1_MF_1000GPCS; - else - mode_reg |= EMAC_M1_MF_1000MBPS; - if (fep->rgmii_dev) - emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input, - 1000); - break; - case SPEED_100: - mode_reg |= EMAC_M1_MF_100MBPS | EMAC_M1_RFS_4K; - if (fep->rgmii_dev) - emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input, - 100); - if (fep->zmii_dev) - emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input, - 100); - break; - case SPEED_10: - default: - mode_reg = (mode_reg & ~EMAC_M1_MF_100MBPS) | EMAC_M1_RFS_4K; - if (fep->rgmii_dev) - emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input, - 10); - if (fep->zmii_dev) - emac_zmii_port_speed(fep->zmii_dev, fep->zmii_input, - 10); - } - - if (full_duplex) - mode_reg |= EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_IST; - else - mode_reg &= ~(EMAC_M1_FDE | EMAC_M1_EIFC | EMAC_M1_ILE); - - LINK_DEBUG(("%s: adjust to link, speed: %d, duplex: %d, opened: %d\n", - fep->ndev->name, speed, full_duplex, fep->opened)); - - printk(KERN_INFO "%s: Speed: %d, %s duplex.\n", - fep->ndev->name, speed, full_duplex ? "Full" : "Half"); - if (fep->opened) - out_be32(&emacp->em0mr1, mode_reg); - - return 0; -} - -static int emac_set_mac_address(struct net_device *ndev, void *p) -{ - struct ocp_enet_private *fep = ndev->priv; - emac_t *emacp = fep->emacp; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); - - /* set the high address */ - out_be32(&emacp->em0iahr, - (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]); - - /* set the low address */ - out_be32(&emacp->em0ialr, - (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16) - | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]); - - return 0; -} - -static int emac_change_mtu(struct net_device *dev, int new_mtu) -{ - struct ocp_enet_private *fep = dev->priv; - int old_mtu = dev->mtu; - emac_t *emacp = fep->emacp; - u32 em0mr0; - int i, full; - unsigned long flags; - - if ((new_mtu < EMAC_MIN_MTU) || (new_mtu > EMAC_MAX_MTU)) { - printk(KERN_ERR - "emac: Invalid MTU setting, MTU must be between %d and %d\n", - EMAC_MIN_MTU, EMAC_MAX_MTU); - return -EINVAL; - } - - if (old_mtu != new_mtu && netif_running(dev)) { - /* Stop rx engine */ - em0mr0 = in_be32(&emacp->em0mr0); - out_be32(&emacp->em0mr0, em0mr0 & ~EMAC_M0_RXE); - - /* Wait for descriptors to be empty */ - do { - full = 0; - for (i = 0; i < NUM_RX_BUFF; i++) - if (!(fep->rx_desc[i].ctrl & MAL_RX_CTRL_EMPTY)) { - printk(KERN_NOTICE - "emac: RX ring is still full\n"); - full = 1; - } - } while (full); - - spin_lock_irqsave(&fep->lock, flags); - - mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - - /* Destroy all old rx skbs */ - for (i = 0; i < NUM_RX_BUFF; i++) { - dma_unmap_single(&fep->ocpdev->dev, - fep->rx_desc[i].data_ptr, - fep->rx_desc[i].data_len, - DMA_FROM_DEVICE); - dev_kfree_skb(fep->rx_skb[i]); - fep->rx_skb[i] = NULL; - } - - /* Set new rx_buffer_size and advertise new mtu */ - fep->rx_buffer_size = - new_mtu + ENET_HEADER_SIZE + ENET_FCS_SIZE; - dev->mtu = new_mtu; - - /* Re-init rx skbs */ - fep->rx_slot = 0; - emac_rx_fill(dev, 0); - - /* Restart the rx engine */ - mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - out_be32(&emacp->em0mr0, em0mr0 | EMAC_M0_RXE); - - spin_unlock_irqrestore(&fep->lock, flags); - } - - return 0; -} - -static void __emac_set_multicast_list(struct net_device *dev) -{ - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - u32 rmr = in_be32(&emacp->em0rmr); - - /* First clear all special bits, they can be set later */ - rmr &= ~(EMAC_RMR_PME | EMAC_RMR_PMME | EMAC_RMR_MAE); - - if (dev->flags & IFF_PROMISC) { - rmr |= EMAC_RMR_PME; - } else if (dev->flags & IFF_ALLMULTI || 32 < dev->mc_count) { - /* - * Must be setting up to use multicast - * Now check for promiscuous multicast - */ - rmr |= EMAC_RMR_PMME; - } else if (dev->flags & IFF_MULTICAST && 0 < dev->mc_count) { - unsigned short em0gaht[4] = { 0, 0, 0, 0 }; - struct dev_mc_list *dmi; - - /* Need to hash on the multicast address. */ - for (dmi = dev->mc_list; dmi; dmi = dmi->next) { - unsigned long mc_crc; - unsigned int bit_number; - - mc_crc = ether_crc(6, (char *)dmi->dmi_addr); - bit_number = 63 - (mc_crc >> 26); /* MSB: 0 LSB: 63 */ - em0gaht[bit_number >> 4] |= - 0x8000 >> (bit_number & 0x0f); - } - emacp->em0gaht1 = em0gaht[0]; - emacp->em0gaht2 = em0gaht[1]; - emacp->em0gaht3 = em0gaht[2]; - emacp->em0gaht4 = em0gaht[3]; - - /* Turn on multicast addressing */ - rmr |= EMAC_RMR_MAE; - } - out_be32(&emacp->em0rmr, rmr); -} - -static int emac_init_tah(struct ocp_enet_private *fep) -{ - tah_t *tahp; - - /* Initialize TAH and enable checksum verification */ - tahp = (tah_t *) ioremap(fep->tah_dev->def->paddr, sizeof(*tahp)); - - if (tahp == NULL) { - printk(KERN_ERR "tah%d: Cannot ioremap TAH registers!\n", - fep->tah_dev->def->index); - - return -ENOMEM; - } - - out_be32(&tahp->tah_mr, TAH_MR_SR); - - /* wait for reset to complete */ - while (in_be32(&tahp->tah_mr) & TAH_MR_SR) ; - - /* 10KB TAH TX FIFO accomodates the max MTU of 9000 */ - out_be32(&tahp->tah_mr, - TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP | - TAH_MR_DIG); - - iounmap(&tahp); - - return 0; -} - -static void emac_init_rings(struct net_device *dev) -{ - struct ocp_enet_private *ep = dev->priv; - int loop; - - ep->tx_desc = (struct mal_descriptor *)((char *)ep->mal->tx_virt_addr + - (ep->mal_tx_chan * - MAL_DT_ALIGN)); - ep->rx_desc = - (struct mal_descriptor *)((char *)ep->mal->rx_virt_addr + - (ep->mal_rx_chan * MAL_DT_ALIGN)); - - /* Fill in the transmit descriptor ring. */ - for (loop = 0; loop < NUM_TX_BUFF; loop++) { - if (ep->tx_skb[loop]) { - dma_unmap_single(&ep->ocpdev->dev, - ep->tx_desc[loop].data_ptr, - ep->tx_desc[loop].data_len, - DMA_TO_DEVICE); - dev_kfree_skb_irq(ep->tx_skb[loop]); - } - ep->tx_skb[loop] = NULL; - ep->tx_desc[loop].ctrl = 0; - ep->tx_desc[loop].data_len = 0; - ep->tx_desc[loop].data_ptr = NULL; - } - ep->tx_desc[loop - 1].ctrl |= MAL_TX_CTRL_WRAP; - - /* Format the receive descriptor ring. */ - ep->rx_slot = 0; - /* Default is MTU=1500 + Ethernet overhead */ - ep->rx_buffer_size = ENET_DEF_BUF_SIZE; - emac_rx_fill(dev, 0); - if (ep->rx_slot != 0) { - printk(KERN_ERR - "%s: Not enough mem for RxChain durning Open?\n", - dev->name); - /*We couldn't fill the ring at startup? - *We could clean up and fail to open but right now we will try to - *carry on. It may be a sign of a bad NUM_RX_BUFF value - */ - } - - ep->tx_cnt = 0; - ep->tx_slot = 0; - ep->ack_slot = 0; -} - -static void emac_reset_configure(struct ocp_enet_private *fep) -{ - emac_t *emacp = fep->emacp; - int i; - - mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask); - mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - - /* - * Check for a link, some PHYs don't provide a clock if - * no link is present. Some EMACs will not come out of - * soft reset without a PHY clock present. - */ - if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) { - /* Reset the EMAC */ - out_be32(&emacp->em0mr0, EMAC_M0_SRST); - udelay(20); - for (i = 0; i < 100; i++) { - if ((in_be32(&emacp->em0mr0) & EMAC_M0_SRST) == 0) - break; - udelay(10); - } - - if (i >= 100) { - printk(KERN_ERR "%s: Cannot reset EMAC\n", - fep->ndev->name); - return; - } - } - - /* Switch IRQs off for now */ - out_be32(&emacp->em0iser, 0); - - /* Configure MAL rx channel */ - mal_set_rcbs(fep->mal, fep->mal_rx_chan, DESC_BUF_SIZE_REG); - - /* set the high address */ - out_be32(&emacp->em0iahr, - (fep->ndev->dev_addr[0] << 8) | fep->ndev->dev_addr[1]); - - /* set the low address */ - out_be32(&emacp->em0ialr, - (fep->ndev->dev_addr[2] << 24) | (fep->ndev->dev_addr[3] << 16) - | (fep->ndev->dev_addr[4] << 8) | fep->ndev->dev_addr[5]); - - /* Adjust to link */ - if (netif_carrier_ok(fep->ndev)) - emac_adjust_to_link(fep); - - /* enable broadcast/individual address and RX FIFO defaults */ - out_be32(&emacp->em0rmr, EMAC_RMR_DEFAULT); - - /* set transmit request threshold register */ - out_be32(&emacp->em0trtr, EMAC_TRTR_DEFAULT); - - /* Reconfigure multicast */ - __emac_set_multicast_list(fep->ndev); - - /* Set receiver/transmitter defaults */ - out_be32(&emacp->em0rwmr, EMAC_RWMR_DEFAULT); - out_be32(&emacp->em0tmr0, EMAC_TMR0_DEFAULT); - out_be32(&emacp->em0tmr1, EMAC_TMR1_DEFAULT); - - /* set frame gap */ - out_be32(&emacp->em0ipgvr, CONFIG_IBM_EMAC_FGAP); - - /* Init ring buffers */ - emac_init_rings(fep->ndev); -} - -static void emac_kick(struct ocp_enet_private *fep) -{ - emac_t *emacp = fep->emacp; - unsigned long emac_ier; - - emac_ier = EMAC_ISR_PP | EMAC_ISR_BP | EMAC_ISR_RP | - EMAC_ISR_SE | EMAC_ISR_PTLE | EMAC_ISR_ALE | - EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE; - - out_be32(&emacp->em0iser, emac_ier); - - /* enable all MAL transmit and receive channels */ - mal_enable_tx_channels(fep->mal, fep->commac.tx_chan_mask); - mal_enable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - - /* set transmit and receive enable */ - out_be32(&emacp->em0mr0, EMAC_M0_TXE | EMAC_M0_RXE); -} - -static void -emac_start_link(struct ocp_enet_private *fep, struct ethtool_cmd *ep) -{ - u32 advertise; - int autoneg; - int forced_speed; - int forced_duplex; - - /* Default advertise */ - advertise = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full; - autoneg = fep->want_autoneg; - forced_speed = fep->phy_mii.speed; - forced_duplex = fep->phy_mii.duplex; - - /* Setup link parameters */ - if (ep) { - if (ep->autoneg == AUTONEG_ENABLE) { - advertise = ep->advertising; - autoneg = 1; - } else { - autoneg = 0; - forced_speed = ep->speed; - forced_duplex = ep->duplex; - } - } - - /* Configure PHY & start aneg */ - fep->want_autoneg = autoneg; - if (autoneg) { - LINK_DEBUG(("%s: start link aneg, advertise: 0x%x\n", - fep->ndev->name, advertise)); - fep->phy_mii.def->ops->setup_aneg(&fep->phy_mii, advertise); - } else { - LINK_DEBUG(("%s: start link forced, speed: %d, duplex: %d\n", - fep->ndev->name, forced_speed, forced_duplex)); - fep->phy_mii.def->ops->setup_forced(&fep->phy_mii, forced_speed, - forced_duplex); - } - fep->timer_ticks = 0; - mod_timer(&fep->link_timer, jiffies + HZ); -} - -static void emac_link_timer(unsigned long data) -{ - struct ocp_enet_private *fep = (struct ocp_enet_private *)data; - int link; - - if (fep->going_away) - return; - - spin_lock_irq(&fep->lock); - - link = fep->phy_mii.def->ops->poll_link(&fep->phy_mii); - LINK_DEBUG(("%s: poll_link: %d\n", fep->ndev->name, link)); - - if (link == netif_carrier_ok(fep->ndev)) { - if (!link && fep->want_autoneg && (++fep->timer_ticks) > 10) - emac_start_link(fep, NULL); - goto out; - } - printk(KERN_INFO "%s: Link is %s\n", fep->ndev->name, - link ? "Up" : "Down"); - if (link) { - netif_carrier_on(fep->ndev); - /* Chip needs a full reset on config change. That sucks, so I - * should ultimately move that to some tasklet to limit - * latency peaks caused by this code - */ - emac_reset_configure(fep); - if (fep->opened) - emac_kick(fep); - } else { - fep->timer_ticks = 0; - netif_carrier_off(fep->ndev); - } - out: - mod_timer(&fep->link_timer, jiffies + HZ); - spin_unlock_irq(&fep->lock); -} - -static void emac_set_multicast_list(struct net_device *dev) -{ - struct ocp_enet_private *fep = dev->priv; - - spin_lock_irq(&fep->lock); - __emac_set_multicast_list(dev); - spin_unlock_irq(&fep->lock); -} - -static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) -{ - struct ocp_enet_private *fep = ndev->priv; - - cmd->supported = fep->phy_mii.def->features; - cmd->port = PORT_MII; - cmd->transceiver = XCVR_EXTERNAL; - cmd->phy_address = fep->mii_phy_addr; - spin_lock_irq(&fep->lock); - cmd->autoneg = fep->want_autoneg; - cmd->speed = fep->phy_mii.speed; - cmd->duplex = fep->phy_mii.duplex; - spin_unlock_irq(&fep->lock); - return 0; -} - -static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) -{ - struct ocp_enet_private *fep = ndev->priv; - unsigned long features = fep->phy_mii.def->features; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE) - return -EINVAL; - if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0) - return -EINVAL; - if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) - return -EINVAL; - if (cmd->autoneg == AUTONEG_DISABLE) - switch (cmd->speed) { - case SPEED_10: - if (cmd->duplex == DUPLEX_HALF && - (features & SUPPORTED_10baseT_Half) == 0) - return -EINVAL; - if (cmd->duplex == DUPLEX_FULL && - (features & SUPPORTED_10baseT_Full) == 0) - return -EINVAL; - break; - case SPEED_100: - if (cmd->duplex == DUPLEX_HALF && - (features & SUPPORTED_100baseT_Half) == 0) - return -EINVAL; - if (cmd->duplex == DUPLEX_FULL && - (features & SUPPORTED_100baseT_Full) == 0) - return -EINVAL; - break; - case SPEED_1000: - if (cmd->duplex == DUPLEX_HALF && - (features & SUPPORTED_1000baseT_Half) == 0) - return -EINVAL; - if (cmd->duplex == DUPLEX_FULL && - (features & SUPPORTED_1000baseT_Full) == 0) - return -EINVAL; - break; - default: - return -EINVAL; - } else if ((features & SUPPORTED_Autoneg) == 0) - return -EINVAL; - spin_lock_irq(&fep->lock); - emac_start_link(fep, cmd); - spin_unlock_irq(&fep->lock); - return 0; -} - -static void -emac_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) -{ - struct ocp_enet_private *fep = ndev->priv; - - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - info->fw_version[0] = '\0'; - sprintf(info->bus_info, "IBM EMAC %d", fep->ocpdev->def->index); - info->regdump_len = 0; -} - -static int emac_nway_reset(struct net_device *ndev) -{ - struct ocp_enet_private *fep = ndev->priv; - - if (!fep->want_autoneg) - return -EINVAL; - spin_lock_irq(&fep->lock); - emac_start_link(fep, NULL); - spin_unlock_irq(&fep->lock); - return 0; -} - -static u32 emac_get_link(struct net_device *ndev) -{ - return netif_carrier_ok(ndev); -} - -static struct ethtool_ops emac_ethtool_ops = { - .get_settings = emac_get_settings, - .set_settings = emac_set_settings, - .get_drvinfo = emac_get_drvinfo, - .nway_reset = emac_nway_reset, - .get_link = emac_get_link -}; - -static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct ocp_enet_private *fep = dev->priv; - uint *data = (uint *) & rq->ifr_data; - - switch (cmd) { - case SIOCGMIIPHY: - data[0] = fep->mii_phy_addr; - /* Fall through */ - case SIOCGMIIREG: - data[3] = emac_phy_read(dev, fep->mii_phy_addr, data[1]); - return 0; - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - emac_phy_write(dev, fep->mii_phy_addr, data[1], data[2]); - return 0; - default: - return -EOPNOTSUPP; - } -} - -static int emac_open(struct net_device *dev) -{ - struct ocp_enet_private *fep = dev->priv; - int rc; - - spin_lock_irq(&fep->lock); - - fep->opened = 1; - netif_carrier_off(dev); - - /* Reset & configure the chip */ - emac_reset_configure(fep); - - spin_unlock_irq(&fep->lock); - - /* Request our interrupt lines */ - rc = request_irq(dev->irq, emac_mac_irq, 0, "IBM EMAC MAC", dev); - if (rc != 0) { - printk("dev->irq %d failed\n", dev->irq); - goto bail; - } - /* Kick the chip rx & tx channels into life */ - spin_lock_irq(&fep->lock); - emac_kick(fep); - spin_unlock_irq(&fep->lock); - - netif_start_queue(dev); - bail: - return rc; -} - -static int emac_close(struct net_device *dev) -{ - struct ocp_enet_private *fep = dev->priv; - emac_t *emacp = fep->emacp; - - /* XXX Stop IRQ emitting here */ - spin_lock_irq(&fep->lock); - fep->opened = 0; - mal_disable_tx_channels(fep->mal, fep->commac.tx_chan_mask); - mal_disable_rx_channels(fep->mal, fep->commac.rx_chan_mask); - netif_carrier_off(dev); - netif_stop_queue(dev); - - /* - * Check for a link, some PHYs don't provide a clock if - * no link is present. Some EMACs will not come out of - * soft reset without a PHY clock present. - */ - if (fep->phy_mii.def->ops->poll_link(&fep->phy_mii)) { - out_be32(&emacp->em0mr0, EMAC_M0_SRST); - udelay(10); - - if (emacp->em0mr0 & EMAC_M0_SRST) { - /*not sure what to do here hopefully it clears before another open */ - printk(KERN_ERR - "%s: Phy SoftReset didn't clear, no link?\n", - dev->name); - } - } - - /* Free the irq's */ - free_irq(dev->irq, dev); - - spin_unlock_irq(&fep->lock); - - return 0; -} - -static void emac_remove(struct ocp_device *ocpdev) -{ - struct net_device *dev = ocp_get_drvdata(ocpdev); - struct ocp_enet_private *ep = dev->priv; - - /* FIXME: locking, races, ... */ - ep->going_away = 1; - ocp_set_drvdata(ocpdev, NULL); - if (ep->rgmii_dev) - emac_close_rgmii(ep->rgmii_dev); - if (ep->zmii_dev) - emac_close_zmii(ep->zmii_dev); - - unregister_netdev(dev); - del_timer_sync(&ep->link_timer); - mal_unregister_commac(ep->mal, &ep->commac); - iounmap((void *)ep->emacp); - kfree(dev); -} - -struct mal_commac_ops emac_commac_ops = { - .txeob = &emac_txeob_dev, - .txde = &emac_txde_dev, - .rxeob = &emac_rxeob_dev, - .rxde = &emac_rxde_dev, -}; - -static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal) -{ - int deferred_init = 0; - int rc = 0, i; - struct net_device *ndev; - struct ocp_enet_private *ep; - struct ocp_func_emac_data *emacdata; - int commac_reg = 0; - u32 phy_map; - - emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions; - if (!emacdata) { - printk(KERN_ERR "emac%d: Missing additional data!\n", - ocpdev->def->index); - return -ENODEV; - } - - /* Allocate our net_device structure */ - ndev = alloc_etherdev(sizeof(struct ocp_enet_private)); - if (ndev == NULL) { - printk(KERN_ERR - "emac%d: Could not allocate ethernet device.\n", - ocpdev->def->index); - return -ENOMEM; - } - ep = ndev->priv; - ep->ndev = ndev; - ep->ocpdev = ocpdev; - ndev->irq = ocpdev->def->irq; - ep->wol_irq = emacdata->wol_irq; - if (emacdata->mdio_idx >= 0) { - if (emacdata->mdio_idx == ocpdev->def->index) { - /* Set the common MDIO net_device */ - mdio_ndev = ndev; - deferred_init = 1; - } - ep->mdio_dev = mdio_ndev; - } else { - ep->mdio_dev = ndev; - } - - ocp_set_drvdata(ocpdev, ndev); - - spin_lock_init(&ep->lock); - - /* Fill out MAL informations and register commac */ - ep->mal = mal; - ep->mal_tx_chan = emacdata->mal_tx_chan; - ep->mal_rx_chan = emacdata->mal_rx_chan; - ep->commac.ops = &emac_commac_ops; - ep->commac.dev = ndev; - ep->commac.tx_chan_mask = MAL_CHAN_MASK(ep->mal_tx_chan); - ep->commac.rx_chan_mask = MAL_CHAN_MASK(ep->mal_rx_chan); - rc = mal_register_commac(ep->mal, &ep->commac); - if (rc != 0) - goto bail; - commac_reg = 1; - - /* Map our MMIOs */ - ep->emacp = (emac_t *) ioremap(ocpdev->def->paddr, sizeof(emac_t)); - - /* Check if we need to attach to a ZMII */ - if (emacdata->zmii_idx >= 0) { - ep->zmii_input = emacdata->zmii_mux; - ep->zmii_dev = - ocp_find_device(OCP_ANY_ID, OCP_FUNC_ZMII, - emacdata->zmii_idx); - if (ep->zmii_dev == NULL) - printk(KERN_WARNING - "emac%d: ZMII %d requested but not found !\n", - ocpdev->def->index, emacdata->zmii_idx); - else if ((rc = - emac_init_zmii(ep->zmii_dev, ep->zmii_input, - emacdata->phy_mode)) != 0) - goto bail; - } - - /* Check if we need to attach to a RGMII */ - if (emacdata->rgmii_idx >= 0) { - ep->rgmii_input = emacdata->rgmii_mux; - ep->rgmii_dev = - ocp_find_device(OCP_ANY_ID, OCP_FUNC_RGMII, - emacdata->rgmii_idx); - if (ep->rgmii_dev == NULL) - printk(KERN_WARNING - "emac%d: RGMII %d requested but not found !\n", - ocpdev->def->index, emacdata->rgmii_idx); - else if ((rc = - emac_init_rgmii(ep->rgmii_dev, ep->rgmii_input, - emacdata->phy_mode)) != 0) - goto bail; - } - - /* Check if we need to attach to a TAH */ - if (emacdata->tah_idx >= 0) { - ep->tah_dev = - ocp_find_device(OCP_ANY_ID, OCP_FUNC_TAH, - emacdata->tah_idx); - if (ep->tah_dev == NULL) - printk(KERN_WARNING - "emac%d: TAH %d requested but not found !\n", - ocpdev->def->index, emacdata->tah_idx); - else if ((rc = emac_init_tah(ep)) != 0) - goto bail; - } - - if (deferred_init) { - if (!list_empty(&emac_init_list)) { - struct list_head *entry; - struct emac_def_dev *ddev; - - list_for_each(entry, &emac_init_list) { - ddev = - list_entry(entry, struct emac_def_dev, - link); - emac_init_device(ddev->ocpdev, ddev->mal); - } - } - } - - /* Init link monitoring timer */ - init_timer(&ep->link_timer); - ep->link_timer.function = emac_link_timer; - ep->link_timer.data = (unsigned long)ep; - ep->timer_ticks = 0; - - /* Fill up the mii_phy structure */ - ep->phy_mii.dev = ndev; - ep->phy_mii.mdio_read = emac_phy_read; - ep->phy_mii.mdio_write = emac_phy_write; - ep->phy_mii.mode = emacdata->phy_mode; - - /* Find PHY */ - phy_map = emacdata->phy_map | busy_phy_map; - for (i = 0; i <= 0x1f; i++, phy_map >>= 1) { - if ((phy_map & 0x1) == 0) { - int val = emac_phy_read(ndev, i, MII_BMCR); - if (val != 0xffff && val != -1) - break; - } - } - if (i == 0x20) { - printk(KERN_WARNING "emac%d: Can't find PHY.\n", - ocpdev->def->index); - rc = -ENODEV; - goto bail; - } - busy_phy_map |= 1 << i; - ep->mii_phy_addr = i; - rc = mii_phy_probe(&ep->phy_mii, i); - if (rc) { - printk(KERN_WARNING "emac%d: Failed to probe PHY type.\n", - ocpdev->def->index); - rc = -ENODEV; - goto bail; - } - - /* Setup initial PHY config & startup aneg */ - if (ep->phy_mii.def->ops->init) - ep->phy_mii.def->ops->init(&ep->phy_mii); - netif_carrier_off(ndev); - if (ep->phy_mii.def->features & SUPPORTED_Autoneg) - ep->want_autoneg = 1; - emac_start_link(ep, NULL); - - /* read the MAC Address */ - for (i = 0; i < 6; i++) - ndev->dev_addr[i] = emacdata->mac_addr[i]; - - /* Fill in the driver function table */ - ndev->open = &emac_open; - ndev->hard_start_xmit = &emac_start_xmit; - ndev->stop = &emac_close; - ndev->get_stats = &emac_stats; - if (emacdata->jumbo) - ndev->change_mtu = &emac_change_mtu; - ndev->set_mac_address = &emac_set_mac_address; - ndev->set_multicast_list = &emac_set_multicast_list; - ndev->do_ioctl = &emac_ioctl; - SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops); - if (emacdata->tah_idx >= 0) - ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG; - - SET_MODULE_OWNER(ndev); - - rc = register_netdev(ndev); - if (rc != 0) - goto bail; - - printk("%s: IBM emac, MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - ndev->name, - ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2], - ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]); - printk(KERN_INFO "%s: Found %s PHY (0x%02x)\n", - ndev->name, ep->phy_mii.def->name, ep->mii_phy_addr); - - bail: - if (rc && commac_reg) - mal_unregister_commac(ep->mal, &ep->commac); - if (rc && ndev) - kfree(ndev); - - return rc; -} - -static int emac_probe(struct ocp_device *ocpdev) -{ - struct ocp_device *maldev; - struct ibm_ocp_mal *mal; - struct ocp_func_emac_data *emacdata; - - emacdata = (struct ocp_func_emac_data *)ocpdev->def->additions; - if (emacdata == NULL) { - printk(KERN_ERR "emac%d: Missing additional datas !\n", - ocpdev->def->index); - return -ENODEV; - } - - /* Get the MAL device */ - maldev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_MAL, emacdata->mal_idx); - if (maldev == NULL) { - printk("No maldev\n"); - return -ENODEV; - } - /* - * Get MAL driver data, it must be here due to link order. - * When the driver is modularized, symbol dependencies will - * ensure the MAL driver is already present if built as a - * module. - */ - mal = (struct ibm_ocp_mal *)ocp_get_drvdata(maldev); - if (mal == NULL) { - printk("No maldrv\n"); - return -ENODEV; - } - - /* If we depend on another EMAC for MDIO, wait for it to show up */ - if (emacdata->mdio_idx >= 0 && - (emacdata->mdio_idx != ocpdev->def->index) && !mdio_ndev) { - struct emac_def_dev *ddev; - /* Add this index to the deferred init table */ - ddev = kmalloc(sizeof(struct emac_def_dev), GFP_KERNEL); - ddev->ocpdev = ocpdev; - ddev->mal = mal; - list_add_tail(&ddev->link, &emac_init_list); - } else { - emac_init_device(ocpdev, mal); - } - - return 0; -} - -/* Structure for a device driver */ -static struct ocp_device_id emac_ids[] = { - {.vendor = OCP_ANY_ID,.function = OCP_FUNC_EMAC}, - {.vendor = OCP_VENDOR_INVALID} -}; - -static struct ocp_driver emac_driver = { - .name = "emac", - .id_table = emac_ids, - - .probe = emac_probe, - .remove = emac_remove, -}; - -static int __init emac_init(void) -{ - int rc; - - printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n"); - printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n"); - - if (skb_res > 2) { - printk(KERN_WARNING "Invalid skb_res: %d, cropping to 2\n", - skb_res); - skb_res = 2; - } - rc = ocp_register_driver(&emac_driver); - if (rc < 0) { - ocp_unregister_driver(&emac_driver); - return -ENODEV; - } - - return 0; -} - -static void __exit emac_exit(void) -{ - ocp_unregister_driver(&emac_driver); -} - -module_init(emac_init); -module_exit(emac_exit); diff --git a/drivers/net/ibm_emac/ibm_emac_phy.h b/drivers/net/ibm_emac/ibm_emac_phy.h deleted file mode 100644 index 61afbea96..000000000 --- a/drivers/net/ibm_emac/ibm_emac_phy.h +++ /dev/null @@ -1,137 +0,0 @@ - -/* - * ibm_emac_phy.h - * - * - * Benjamin Herrenschmidt - * February 2003 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * This file basically duplicates sungem_phy.{c,h} with different PHYs - * supported. I'm looking into merging that in a single mii layer more - * flexible than mii.c - */ - -#ifndef _IBM_EMAC_PHY_H_ -#define _IBM_EMAC_PHY_H_ - -/* - * PHY mode settings - * Used for multi-mode capable PHYs - */ -#define PHY_MODE_NA 0 -#define PHY_MODE_MII 1 -#define PHY_MODE_RMII 2 -#define PHY_MODE_SMII 3 -#define PHY_MODE_RGMII 4 -#define PHY_MODE_TBI 5 -#define PHY_MODE_GMII 6 -#define PHY_MODE_RTBI 7 -#define PHY_MODE_SGMII 8 - -/* - * PHY specific registers/values - */ - -/* CIS8201 */ -#define MII_CIS8201_EPCR 0x17 -#define EPCR_MODE_MASK 0x3000 -#define EPCR_GMII_MODE 0x0000 -#define EPCR_RGMII_MODE 0x1000 -#define EPCR_TBI_MODE 0x2000 -#define EPCR_RTBI_MODE 0x3000 - -struct mii_phy; - -/* Operations supported by any kind of PHY */ -struct mii_phy_ops { - int (*init) (struct mii_phy * phy); - int (*suspend) (struct mii_phy * phy, int wol_options); - int (*setup_aneg) (struct mii_phy * phy, u32 advertise); - int (*setup_forced) (struct mii_phy * phy, int speed, int fd); - int (*poll_link) (struct mii_phy * phy); - int (*read_link) (struct mii_phy * phy); -}; - -/* Structure used to statically define an mii/gii based PHY */ -struct mii_phy_def { - u32 phy_id; /* Concatenated ID1 << 16 | ID2 */ - u32 phy_id_mask; /* Significant bits */ - u32 features; /* Ethtool SUPPORTED_* defines */ - int magic_aneg; /* Autoneg does all speed test for us */ - const char *name; - const struct mii_phy_ops *ops; -}; - -/* An instance of a PHY, partially borrowed from mii_if_info */ -struct mii_phy { - struct mii_phy_def *def; - int advertising; - int mii_id; - - /* 1: autoneg enabled, 0: disabled */ - int autoneg; - - /* forced speed & duplex (no autoneg) - * partner speed & duplex & pause (autoneg) - */ - int speed; - int duplex; - int pause; - - /* PHY mode - if needed */ - int mode; - - /* Provided by host chip */ - struct net_device *dev; - int (*mdio_read) (struct net_device * dev, int mii_id, int reg); - void (*mdio_write) (struct net_device * dev, int mii_id, int reg, - int val); -}; - -/* Pass in a struct mii_phy with dev, mdio_read and mdio_write - * filled, the remaining fields will be filled on return - */ -extern int mii_phy_probe(struct mii_phy *phy, int mii_id); - -static inline int __phy_read(struct mii_phy *phy, int id, int reg) -{ - return phy->mdio_read(phy->dev, id, reg); -} - -static inline void __phy_write(struct mii_phy *phy, int id, int reg, int val) -{ - phy->mdio_write(phy->dev, id, reg, val); -} - -static inline int phy_read(struct mii_phy *phy, int reg) -{ - return phy->mdio_read(phy->dev, phy->mii_id, reg); -} - -static inline void phy_write(struct mii_phy *phy, int reg, int val) -{ - phy->mdio_write(phy->dev, phy->mii_id, reg, val); -} - -#endif /* _IBM_EMAC_PHY_H_ */ diff --git a/drivers/net/wan/wanxlfw.inc_shipped b/drivers/net/wan/wanxlfw.inc_shipped deleted file mode 100644 index 73da688f9..000000000 --- a/drivers/net/wan/wanxlfw.inc_shipped +++ /dev/null @@ -1,158 +0,0 @@ -static u8 firmware[]={ -0x60,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xB9,0x40,0x00,0x00,0x00,0x00,0x00, -0x10,0x14,0x42,0x80,0x4A,0xB0,0x09,0xB0,0x00,0x00,0x10,0x04,0x67,0x00,0x00,0x0E, -0x06,0xB0,0x40,0x00,0x00,0x00,0x09,0xB0,0x00,0x00,0x10,0x04,0x58,0x80,0x0C,0x80, -0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0xDE,0x21,0xFC,0x00,0x00,0x16,0xBC,0x00,0x6C, -0x21,0xFC,0x00,0x00,0x17,0x5E,0x01,0x00,0x21,0xFC,0x00,0x00,0x16,0xDE,0x01,0x78, -0x21,0xFC,0x00,0x00,0x16,0xFE,0x01,0x74,0x21,0xFC,0x00,0x00,0x17,0x1E,0x01,0x70, -0x21,0xFC,0x00,0x00,0x17,0x3E,0x01,0x6C,0x21,0xFC,0x00,0x00,0x18,0x4C,0x02,0x00, -0x23,0xFC,0x78,0x00,0x00,0x00,0xFF,0xFC,0x15,0x48,0x33,0xFC,0x04,0x80,0xFF,0xFC, -0x10,0x26,0x33,0xFC,0x01,0x10,0xFF,0xFC,0x10,0x2A,0x23,0xFC,0x00,0xD4,0x9F,0x40, -0xFF,0xFC,0x15,0x40,0x23,0xFC,0x00,0x00,0x05,0x43,0xFF,0xF9,0x01,0x00,0x23,0xFC, -0x00,0x00,0x05,0x43,0xFF,0xF9,0x01,0x14,0x23,0xFC,0x00,0x00,0x00,0x00,0xFF,0xF9, -0x01,0x10,0x23,0xFC,0x00,0x00,0x00,0x08,0xFF,0xF9,0x01,0x24,0x23,0xFC,0x00,0x00, -0x01,0x01,0xFF,0xF9,0x01,0x28,0x00,0xB9,0x00,0x0F,0x03,0x00,0xFF,0xF9,0x00,0xE8, -0x23,0xFC,0x00,0x00,0x00,0x01,0xFF,0xF9,0x00,0xD4,0x61,0x00,0x06,0x74,0x33,0xFC, -0xFF,0xFF,0xFF,0xFC,0x15,0x52,0x42,0x79,0xFF,0xFC,0x15,0x50,0x42,0x79,0xFF,0xFC, -0x15,0x64,0x2E,0x3A,0x08,0x50,0x42,0xB9,0x00,0x00,0x19,0x54,0x4A,0x87,0x66,0x00, -0x00,0x0E,0x4E,0x72,0x22,0x00,0x46,0xFC,0x27,0x00,0x60,0x00,0xFF,0xE6,0x42,0x80, -0x42,0x86,0x08,0x07,0x00,0x04,0x67,0x00,0x00,0x0A,0x08,0x87,0x00,0x00,0x61,0x00, -0x02,0xA0,0x08,0x07,0x00,0x00,0x67,0x00,0x00,0x06,0x61,0x00,0x00,0x36,0x08,0x07, -0x00,0x08,0x67,0x00,0x00,0x06,0x61,0x00,0x02,0xB8,0x08,0x07,0x00,0x0C,0x67,0x00, -0x00,0x0A,0x61,0x00,0x04,0x94,0x61,0x00,0x03,0x60,0xE2,0x8F,0x58,0x80,0x0C,0x80, -0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0xBC,0x23,0xC6,0xFF,0xF9,0x00,0xE4,0x60,0x00, -0xFF,0x92,0x20,0x70,0x09,0xB0,0x00,0x00,0x10,0x04,0x4A,0xA8,0x00,0x00,0x66,0x00, -0x02,0x4E,0x21,0x7C,0x00,0x00,0x00,0x01,0x00,0x00,0x42,0xB0,0x09,0xB0,0x00,0x00, -0x19,0x58,0x42,0xB0,0x09,0xB0,0x00,0x00,0x19,0x68,0x42,0xB0,0x09,0xB0,0x00,0x00, -0x19,0x78,0x42,0xB0,0x09,0xB0,0x00,0x00,0x19,0x88,0x22,0x39,0xFF,0xFC,0x16,0xEC, -0xC2,0xB0,0x09,0xB0,0x00,0x00,0x18,0xF2,0x0C,0xA8,0x00,0x00,0x00,0x04,0x00,0x18, -0x66,0x00,0x00,0x0E,0x82,0xB0,0x09,0xB0,0x00,0x00,0x18,0xE2,0x60,0x00,0x00,0x0A, -0x82,0xB0,0x09,0xB0,0x00,0x00,0x18,0xD2,0x23,0xC1,0xFF,0xFC,0x16,0xEC,0x00,0x70, -0x10,0x00,0x09,0xB0,0x00,0x00,0x19,0xAA,0x61,0x00,0x05,0x76,0x22,0x30,0x09,0xB0, -0x00,0x00,0x18,0x92,0x22,0x70,0x09,0xB0,0x00,0x00,0x18,0x72,0x74,0x08,0x26,0x3C, -0x18,0x00,0x00,0x00,0x0C,0xA8,0x00,0x00,0x00,0x01,0x00,0x10,0x67,0x00,0x00,0x06, -0x08,0xC3,0x00,0x1A,0x22,0xC3,0x22,0xC1,0x06,0x81,0x00,0x00,0x05,0xFC,0x51,0xCA, -0xFF,0xF4,0x08,0xC3,0x00,0x1D,0x22,0xC3,0x22,0xC1,0x74,0x1C,0x22,0xFC,0x90,0x00, -0x00,0x00,0x22,0xC1,0x06,0x81,0x00,0x00,0x05,0xFC,0x51,0xCA,0xFF,0xF0,0x22,0xFC, -0xB0,0x00,0x00,0x00,0x22,0xC1,0x22,0x70,0x09,0xB0,0x00,0x00,0x18,0x62,0x24,0x70, -0x09,0xB0,0x00,0x00,0x18,0x52,0x25,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x10,0x25,0x7C, -0x00,0x00,0x00,0x00,0x00,0x14,0x22,0x30,0x09,0xB0,0x00,0x00,0x18,0x72,0x33,0x41, -0x00,0x02,0x06,0x81,0x00,0x00,0x00,0x50,0x33,0x41,0x00,0x00,0x13,0x7C,0x00,0x08, -0x00,0x04,0x13,0x7C,0x00,0x08,0x00,0x05,0x0C,0xA8,0x00,0x00,0x00,0x05,0x00,0x10, -0x66,0x00,0x00,0x2A,0x42,0x6A,0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34, -0x23,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x38,0x33,0x7C,0x05,0xFA,0x00,0x46,0x31,0xBC, -0x00,0x02,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00,0x00,0xBC,0x0C,0xA8,0x00,0x00, -0x00,0x07,0x00,0x10,0x66,0x00,0x00,0x2C,0x35,0x7C,0x08,0x00,0x00,0x08,0x23,0x7C, -0xDE,0xBB,0x20,0xE3,0x00,0x34,0x23,0x7C,0xFF,0xFF,0xFF,0xFF,0x00,0x38,0x33,0x7C, -0x05,0xFC,0x00,0x46,0x31,0xBC,0x00,0x04,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00, -0x00,0x86,0x0C,0xA8,0x00,0x00,0x00,0x04,0x00,0x10,0x66,0x00,0x00,0x26,0x42,0x6A, -0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34,0x42,0xA9,0x00,0x38,0x33,0x7C, -0x05,0xFA,0x00,0x46,0x31,0xBC,0x00,0x02,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00, -0x00,0x56,0x0C,0xA8,0x00,0x00,0x00,0x06,0x00,0x10,0x66,0x00,0x00,0x28,0x35,0x7C, -0x08,0x00,0x00,0x08,0x23,0x7C,0xDE,0xBB,0x20,0xE3,0x00,0x34,0x42,0xA9,0x00,0x38, -0x33,0x7C,0x05,0xFC,0x00,0x46,0x31,0xBC,0x00,0x04,0x09,0xB0,0x00,0x00,0x19,0x9C, -0x60,0x00,0x00,0x24,0x42,0x6A,0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34, -0x23,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x38,0x33,0x7C,0x05,0xF8,0x00,0x46,0x42,0x70, -0x09,0xB0,0x00,0x00,0x19,0x9C,0x25,0x7C,0x00,0x00,0x00,0x03,0x00,0x04,0x0C,0xA8, -0x00,0x00,0x00,0x02,0x00,0x14,0x66,0x00,0x00,0x0E,0x25,0x7C,0x10,0x04,0x09,0x00, -0x00,0x00,0x60,0x00,0x00,0x0A,0x25,0x7C,0x10,0x04,0x00,0x00,0x00,0x00,0x33,0x7C, -0x05,0xFC,0x00,0x06,0x22,0x00,0xE9,0x89,0x00,0x81,0x00,0x00,0x00,0x01,0x33,0xC1, -0xFF,0xFC,0x15,0xC0,0x08,0x39,0x00,0x00,0xFF,0xFC,0x15,0xC0,0x66,0x00,0xFF,0xF6, -0x35,0x7C,0x00,0x1F,0x00,0x14,0x00,0xAA,0x00,0x00,0x00,0x30,0x00,0x00,0x4E,0x75, -0x20,0x70,0x09,0xB0,0x00,0x00,0x18,0x52,0x42,0x68,0x00,0x14,0x02,0xA8,0xFF,0xFF, -0xFF,0xCF,0x00,0x00,0x02,0x70,0xEF,0xFF,0x09,0xB0,0x00,0x00,0x19,0xAA,0x61,0x00, -0x03,0x70,0x22,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x42,0xB0,0x19,0x90,0x4E,0x75, -0x0C,0xB0,0x00,0x00,0x00,0x0A,0x09,0xB0,0x00,0x00,0x19,0x78,0x67,0x00,0x00,0xA8, -0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x68,0x24,0x01,0x4C,0x3C,0x20,0x00,0x00,0x00, -0x00,0x0C,0xD4,0xB0,0x09,0xB0,0x00,0x00,0x10,0x04,0x06,0x82,0x00,0x00,0x00,0x1C, -0x0C,0xB0,0x00,0x00,0x00,0x10,0x29,0x90,0x66,0x00,0x00,0x7C,0x20,0x70,0x29,0xA0, -0x00,0x04,0xE7,0x89,0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x72,0x22,0x70,0x19,0xA0, -0x00,0x04,0x24,0x30,0x29,0xA0,0x00,0x08,0x31,0x82,0x19,0xA0,0x00,0x02,0x56,0x82, -0x02,0x82,0xFF,0xFF,0xFF,0xFC,0x23,0xC8,0xFF,0xF9,0x01,0x04,0x23,0xC9,0xFF,0xF9, -0x01,0x08,0x23,0xC2,0xFF,0xF9,0x01,0x0C,0x23,0xFC,0x00,0x00,0x01,0x03,0xFF,0xF9, -0x01,0x28,0x61,0x00,0x01,0xF6,0x08,0xF0,0x00,0x1F,0x19,0x90,0x22,0x30,0x09,0xB0, -0x00,0x00,0x19,0x68,0x52,0x81,0x0C,0x81,0x00,0x00,0x00,0x0A,0x66,0x00,0x00,0x04, -0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00,0x19,0x68,0x52,0xB0,0x09,0xB0,0x00,0x00, -0x19,0x78,0x60,0x00,0xFF,0x4C,0x4E,0x75,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x88, -0xE7,0x89,0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x82,0x34,0x30,0x19,0x90,0x08,0x02, -0x00,0x0F,0x66,0x00,0x01,0x12,0x08,0x02,0x00,0x01,0x66,0x00,0x00,0xE6,0x4A,0x70, -0x09,0xB0,0x00,0x00,0x19,0x9C,0x66,0x00,0x00,0x06,0x08,0x82,0x00,0x02,0x02,0x42, -0x0C,0xBC,0x0C,0x42,0x0C,0x00,0x66,0x00,0x00,0xDC,0x42,0x83,0x36,0x30,0x19,0xA0, -0x00,0x02,0x96,0x70,0x09,0xB0,0x00,0x00,0x19,0x9C,0x0C,0x43,0x05,0xF8,0x6E,0x00, -0x00,0xC4,0x24,0x3A,0x04,0x84,0x4C,0x3C,0x20,0x00,0x00,0x00,0x00,0x0C,0xD4,0xBA, -0xFA,0xF4,0x0C,0xB0,0x00,0x00,0x00,0x00,0x29,0x90,0x66,0x00,0x00,0x96,0x21,0x83, -0x29,0xA0,0x00,0x08,0x20,0x70,0x19,0xA0,0x00,0x04,0x22,0x70,0x29,0xA0,0x00,0x04, -0x4A,0x89,0x67,0x00,0x00,0x2A,0x56,0x83,0x02,0x83,0xFF,0xFF,0xFF,0xFC,0x23,0xC8, -0xFF,0xF9,0x01,0x1C,0x23,0xC9,0xFF,0xF9,0x01,0x18,0x23,0xC3,0xFF,0xF9,0x01,0x20, -0x23,0xFC,0x00,0x00,0x03,0x01,0xFF,0xF9,0x01,0x28,0x61,0x00,0x01,0x2C,0x21,0xB0, -0x09,0xB0,0x00,0x00,0x18,0xC2,0x29,0x90,0x08,0xC6,0x00,0x04,0x24,0x3A,0x04,0x1A, -0x52,0x82,0x0C,0x82,0x00,0x00,0x00,0x28,0x66,0x00,0x00,0x04,0x42,0x82,0x23,0xC2, -0x00,0x00,0x19,0x98,0x02,0x70,0xF0,0x00,0x19,0x90,0x08,0xF0,0x00,0x1F,0x19,0x90, -0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x88,0x52,0x81,0x0C,0x81,0x00,0x00,0x00,0x1E, -0x66,0x00,0x00,0x04,0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00,0x19,0x88,0x60,0x00, -0xFE,0xF8,0x24,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x52,0xB0,0x29,0xA0,0x00,0x08, -0x60,0x00,0xFF,0xC2,0x24,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x52,0xB0,0x29,0xA0, -0x00,0x0C,0x60,0x00,0xFF,0xB0,0x4E,0x75,0x4A,0xB0,0x09,0xB0,0x00,0x00,0x19,0x78, -0x67,0x00,0x00,0x86,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x58,0x24,0x01,0xE7,0x89, -0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x72,0x36,0x30,0x19,0x90,0x08,0x03,0x00,0x0F, -0x66,0x00,0x00,0x66,0x8C,0xB0,0x09,0xB0,0x00,0x00,0x18,0xA2,0x53,0xB0,0x09,0xB0, -0x00,0x00,0x19,0x78,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x58,0x52,0x81,0x0C,0x81, -0x00,0x00,0x00,0x0A,0x66,0x00,0x00,0x04,0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00, -0x19,0x58,0x4C,0x3C,0x20,0x00,0x00,0x00,0x00,0x0C,0xD4,0xB0,0x09,0xB0,0x00,0x00, -0x10,0x04,0x06,0x82,0x00,0x00,0x00,0x1C,0x08,0x03,0x00,0x01,0x66,0x00,0x00,0x0E, -0x21,0xBC,0x00,0x00,0x00,0x20,0x29,0x90,0x60,0x00,0xFF,0x7E,0x21,0xBC,0x00,0x00, -0x00,0x30,0x29,0x90,0x60,0x00,0xFF,0x72,0x4E,0x75,0x2F,0x00,0x40,0xE7,0x20,0x39, -0xFF,0xF9,0x01,0x28,0x08,0x00,0x00,0x04,0x66,0x00,0x00,0x2C,0x4E,0x72,0x22,0x00, -0x46,0xFC,0x27,0x00,0x60,0x00,0xFF,0xE8,0x2F,0x00,0x40,0xE7,0x20,0x39,0xFF,0xF9, -0x01,0x28,0x08,0x00,0x00,0x0C,0x66,0x00,0x00,0x0E,0x4E,0x72,0x22,0x00,0x46,0xFC, -0x27,0x00,0x60,0x00,0xFF,0xE8,0x46,0xDF,0x20,0x1F,0x4E,0x75,0x2F,0x00,0x20,0x39, -0xFF,0xF9,0x00,0xE0,0x23,0xC0,0xFF,0xF9,0x00,0xE0,0x81,0xB9,0x00,0x00,0x19,0x54, -0x23,0xFC,0x00,0x00,0x09,0x09,0xFF,0xF9,0x01,0x28,0x20,0x1F,0x4E,0x73,0x00,0xB9, -0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x10,0x00,0xB9,0x00,0x00,0x10,0x00,0x00,0x00, -0x19,0x54,0x23,0xFC,0x40,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, -0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x30,0x00,0xB9,0x00,0x00,0x20,0x00,0x00,0x00, -0x19,0x54,0x23,0xFC,0x20,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, -0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x50,0x00,0xB9,0x00,0x00,0x40,0x00,0x00,0x00, -0x19,0x54,0x23,0xFC,0x10,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, -0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x70,0x00,0xB9,0x00,0x00,0x80,0x00,0x00,0x00, -0x19,0x54,0x23,0xFC,0x08,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x4E,0x73, -0x2F,0x00,0x2F,0x01,0x2F,0x02,0x2F,0x08,0x2F,0x09,0x42,0x80,0x20,0x7C,0xFF,0xFB, -0x00,0x00,0x32,0x10,0x02,0x81,0x00,0x00,0x00,0xE7,0x0C,0x41,0x00,0x42,0x66,0x00, -0x00,0x0A,0x32,0x3C,0x0E,0x08,0x60,0x00,0x00,0x3E,0x0C,0x41,0x00,0x63,0x66,0x00, -0x00,0x0A,0x32,0x3C,0x04,0x08,0x60,0x00,0x00,0x2E,0x0C,0x41,0x00,0x84,0x66,0x00, -0x00,0x0A,0x32,0x3C,0x02,0x08,0x60,0x00,0x00,0x1E,0x0C,0x41,0x00,0xA5,0x66,0x00, -0x00,0x0A,0x32,0x3C,0x0D,0x08,0x60,0x00,0x00,0x0E,0x32,0x3C,0x00,0x08,0x34,0x3C, -0x80,0xE7,0x60,0x00,0x00,0x14,0x34,0x30,0x09,0xB0,0x00,0x00,0x19,0xAA,0x02,0x42, -0x30,0x00,0x82,0x42,0x34,0x3C,0x80,0xFF,0xB2,0x70,0x09,0xB0,0x00,0x00,0x19,0xAC, -0x67,0x00,0x00,0x0C,0x31,0x81,0x09,0xB0,0x00,0x00,0x19,0xAC,0x30,0x81,0x32,0x39, -0xFF,0xFC,0x15,0x66,0xC2,0x70,0x09,0xB0,0x00,0x00,0x19,0x02,0x67,0x00,0x00,0x0C, -0x32,0x10,0x02,0x41,0xFF,0xF7,0x60,0x00,0x00,0x08,0x32,0x10,0x00,0x41,0x00,0x08, -0xC2,0x42,0x22,0x70,0x09,0xB0,0x00,0x00,0x10,0x04,0xB2,0xA9,0x00,0x04,0x67,0x00, -0x00,0x12,0x23,0x41,0x00,0x04,0x23,0xF0,0x09,0xB0,0x00,0x00,0x18,0xB2,0xFF,0xF9, -0x00,0xE4,0x54,0x88,0x58,0x80,0x0C,0x80,0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0x34, -0x22,0x5F,0x20,0x5F,0x24,0x1F,0x22,0x1F,0x20,0x1F,0x4E,0x75,0x61,0x00,0xFF,0x12, -0x4E,0x73,0xFF,0xFC,0x16,0x00,0xFF,0xFC,0x16,0x20,0xFF,0xFC,0x16,0x40,0xFF,0xFC, -0x16,0x60,0xFF,0xFC,0x0C,0x00,0xFF,0xFC,0x0D,0x00,0xFF,0xFC,0x0E,0x00,0xFF,0xFC, -0x0F,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xFC,0x01,0x40,0xFF,0xFC,0x02,0x80,0xFF,0xFC, -0x03,0xC0,0xFF,0xFC,0x00,0x50,0xFF,0xFC,0x01,0x90,0xFF,0xFC,0x02,0xD0,0xFF,0xFC, -0x04,0x10,0x00,0x00,0x40,0x00,0x00,0x01,0x2F,0x60,0x00,0x02,0x1E,0xC0,0x00,0x03, -0x0E,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00, -0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x80,0x00,0x00, -0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00, -0x00,0x13,0x00,0x00,0x00,0x2C,0x00,0x00,0x3E,0x00,0x00,0x2C,0x00,0x00,0x3E,0x00, -0x00,0x00,0x00,0x00,0x00,0x2D,0x00,0x00,0x3F,0x00,0x00,0x2D,0x00,0x00,0x3F,0x00, -0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00, -0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00, -0x77,0x61,0x6E,0x58,0x4C,0x20,0x66,0x69,0x72,0x6D,0x77,0x61,0x72,0x65,0x0A,0x43, -0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30, -0x33,0x20,0x4B,0x72,0x7A,0x79,0x73,0x7A,0x74,0x6F,0x66,0x20,0x48,0x61,0x6C,0x61, -0x73,0x61,0x20,0x3C,0x6B,0x68,0x63,0x40,0x70,0x6D,0x2E,0x77,0x61,0x77,0x2E,0x70, -0x6C,0x3E,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c deleted file mode 100644 index d595ba757..000000000 --- a/drivers/pcmcia/pxa2xx_base.c +++ /dev/null @@ -1,333 +0,0 @@ -/*====================================================================== - - Device driver for the PCMCIA control functionality of PXA2xx - microprocessors. - - The contents of this file may be used under the - terms of the GNU Public License version 2 (the "GPL") - - (c) Ian Molton (spyro@f2s.com) 2003 - (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4 - - derived from sa11xx_base.c - - Portions created by John G. Dorsey are - Copyright (C) 1999 John G. Dorsey. - - ======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "cs_internal.h" -#include "soc_common.h" -#include "pxa2xx_base.h" - - -#define MCXX_SETUP_MASK (0x7f) -#define MCXX_ASST_MASK (0x1f) -#define MCXX_HOLD_MASK (0x3f) -#define MCXX_SETUP_SHIFT (0) -#define MCXX_ASST_SHIFT (7) -#define MCXX_HOLD_SHIFT (14) - -static inline u_int pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns, - u_int mem_clk_10khz) -{ - u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 300000) + ((code % 300000) ? 1 : 0) - 1; -} - -static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns, - u_int mem_clk_10khz) -{ - u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 300000) + ((code % 300000) ? 1 : 0) - 1; -} - -static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns, - u_int mem_clk_10khz) -{ - u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 100000) + ((code % 100000) ? 1 : 0) - 1; -} - -/* This function returns the (approximate) command assertion period, in - * nanoseconds, for a given CPU clock frequency and MCXX_ASST value: - */ -static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz, - u_int pcmcia_mcxx_asst) -{ - return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz); -} - -static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock ) -{ - MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock) - & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) - | ((pxa2xx_mcxx_asst(speed, clock) - & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) - | ((pxa2xx_mcxx_hold(speed, clock) - & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); - - return 0; -} - -static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock ) -{ - MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock) - & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) - | ((pxa2xx_mcxx_asst(speed, clock) - & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) - | ((pxa2xx_mcxx_hold(speed, clock) - & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); - - return 0; -} - -static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock ) -{ - MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock) - & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) - | ((pxa2xx_mcxx_asst(speed, clock) - & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) - | ((pxa2xx_mcxx_hold(speed, clock) - & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); - - return 0; -} - -static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int lclk) -{ - struct soc_pcmcia_timing timing; - int sock = skt->nr; - - soc_common_pcmcia_get_timing(skt, &timing); - - pxa2xx_pcmcia_set_mcmem(sock, timing.mem, lclk); - pxa2xx_pcmcia_set_mcatt(sock, timing.attr, lclk); - pxa2xx_pcmcia_set_mcio(sock, timing.io, lclk); - - return 0; -} - -static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt) -{ - unsigned int lclk = get_lclk_frequency_10khz(); - return pxa2xx_pcmcia_set_mcxx(skt, lclk); -} - -int pxa2xx_drv_pcmcia_probe(struct device *dev) -{ - int ret; - struct pcmcia_low_level *ops; - int first, nr; - - if (!dev || !dev->platform_data) - return -ENODEV; - - ops = (struct pcmcia_low_level *)dev->platform_data; - first = ops->first; - nr = ops->nr; - - /* Setup GPIOs for PCMCIA/CF alternate function mode. - * - * It would be nice if set_GPIO_mode included support - * for driving GPIO outputs to default high/low state - * before programming GPIOs as outputs. Setting GPIO - * outputs to default high/low state via GPSR/GPCR - * before defining them as outputs should reduce - * the possibility of glitching outputs during GPIO - * setup. This of course assumes external terminators - * are present to hold GPIOs in a defined state. - * - * In the meantime, setup default state of GPIO - * outputs before we enable them as outputs. - */ - - GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | - GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | - GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - pxa_gpio_mode(GPIO48_nPOE_MD); - pxa_gpio_mode(GPIO49_nPWE_MD); - pxa_gpio_mode(GPIO50_nPIOR_MD); - pxa_gpio_mode(GPIO51_nPIOW_MD); - pxa_gpio_mode(GPIO52_nPCE_1_MD); - pxa_gpio_mode(GPIO53_nPCE_2_MD); - pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */ - pxa_gpio_mode(GPIO55_nPREG_MD); - pxa_gpio_mode(GPIO56_nPWAIT_MD); - pxa_gpio_mode(GPIO57_nIOIS16_MD); - - /* Provide our PXA2xx specific timing routines. */ - ops->set_timing = pxa2xx_pcmcia_set_timing; - - ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr); - - if (ret == 0) { - /* - * We have at least one socket, so set MECR:CIT - * (Card Is There) - */ - MECR |= MECR_CIT; - - /* Set MECR:NOS (Number Of Sockets) */ - if (nr > 1) - MECR |= MECR_NOS; - else - MECR &= ~MECR_NOS; - } - - return ret; -} -EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe); - -static int pxa2xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level) -{ - int ret = 0; - if (level == SUSPEND_SAVE_STATE) - ret = pcmcia_socket_dev_suspend(dev, state); - return ret; -} - -static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level) -{ - int ret = 0; - if (level == RESUME_RESTORE_STATE) - ret = pcmcia_socket_dev_resume(dev); - return ret; -} - -static struct device_driver pxa2xx_pcmcia_driver = { - .probe = pxa2xx_drv_pcmcia_probe, - .remove = soc_common_drv_pcmcia_remove, - .suspend = pxa2xx_drv_pcmcia_suspend, - .resume = pxa2xx_drv_pcmcia_resume, - .name = "pxa2xx-pcmcia", - .bus = &platform_bus_type, -}; - -#ifdef CONFIG_CPU_FREQ - -/* - * When pxa2xx_pcmcia_notifier() decides that a MC{IO,MEM,ATT} adjustment (due - * to a core clock frequency change) is needed, this routine establishes - * new values consistent with the clock speed `clock'. - */ -static void pxa2xx_pcmcia_update_mcxx(unsigned int clock) -{ - struct soc_pcmcia_socket *skt; - - down(&soc_sockets_lock); - list_for_each_entry(skt, &soc_sockets, node) { - pxa2xx_pcmcia_set_mcxx(skt, clock); - } - up(&soc_sockets_lock); -} - -/* - * When changing the processor L clock frequency, it is necessary - * to adjust the MCXX timings accordingly. We've recorded the timings - * requested by Card Services, so this is just a matter of finding - * out what our current speed is, and then recomputing the new MCXX - * values. - * - * Returns: 0 on success, -1 on error - */ -static int -pxa2xx_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data) -{ - struct cpufreq_freqs *freqs = data; - -#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock" - switch (val) { - case CPUFREQ_PRECHANGE: - if (freqs->new > freqs->old) { - debug( 2, "new frequency %u.%uMHz > %u.%uMHz, " - "pre-updating\n", - freqs->new / 1000, (freqs->new / 100) % 10, - freqs->old / 1000, (freqs->old / 100) % 10); - pxa2xx_pcmcia_update_mcxx(freqs->new); - } - break; - - case CPUFREQ_POSTCHANGE: - if (freqs->new < freqs->old) { - debug( 2, "new frequency %u.%uMHz < %u.%uMHz, " - "post-updating\n", - freqs->new / 1000, (freqs->new / 100) % 10, - freqs->old / 1000, (freqs->old / 100) % 10); - pxa2xx_pcmcia_update_mcxx(freqs->new); - } - break; - } - - return 0; -} - -static struct notifier_block pxa2xx_pcmcia_notifier_block = { - .notifier_call = pxa2xx_pcmcia_notifier -}; - -static int __init pxa2xx_pcmcia_cpufreq_init(void) -{ - int ret; - - ret = cpufreq_register_notifier(&pxa2xx_pcmcia_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - if (ret < 0) - printk(KERN_ERR "Unable to register CPU frequency change " - "notifier for PCMCIA (%d)\n", ret); - return ret; -} - -static void __exit pxa2xx_pcmcia_cpufreq_exit(void) -{ - cpufreq_unregister_notifier(&pxa2xx_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); -} - -#else -#define pxa2xx_pcmcia_cpufreq_init() -#define pxa2xx_pcmcia_cpufreq_exit() -#endif - -static int __init pxa2xx_pcmcia_init(void) -{ - int ret = driver_register(&pxa2xx_pcmcia_driver); - if (ret == 0) - pxa2xx_pcmcia_cpufreq_init(); - return ret; -} - -static void __exit pxa2xx_pcmcia_exit(void) -{ - pxa2xx_pcmcia_cpufreq_exit(); - driver_unregister(&pxa2xx_pcmcia_driver); -} - -module_init(pxa2xx_pcmcia_init); -module_exit(pxa2xx_pcmcia_exit); - -MODULE_AUTHOR("Stefan Eletzhofer and Ian Molton "); -MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA2xx core socket driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c deleted file mode 100644 index c18f28605..000000000 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * linux/drivers/pcmcia/pxa2xx_lubbock.c - * - * Author: George Davis - * Created: Jan 10, 2002 - * Copyright: MontaVista Software Inc. - * - * 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. - * - * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c - * - * Lubbock PCMCIA specific routines. - * - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "sa1111_generic.h" - -static int -lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, - const socket_state_t *state) -{ - unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; - int ret = 0; - - pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; - - /* Lubbock uses the Maxim MAX1602, with the following connections: - * - * Socket 0 (PCMCIA): - * MAX1602 Lubbock Register - * Pin Signal - * ----- ------- ---------------------- - * A0VPP S0_PWR0 SA-1111 GPIO A<0> - * A1VPP S0_PWR1 SA-1111 GPIO A<1> - * A0VCC S0_PWR2 SA-1111 GPIO A<2> - * A1VCC S0_PWR3 SA-1111 GPIO A<3> - * VX VCC - * VY +3.3V - * 12IN +12V - * CODE +3.3V Cirrus Code, CODE = High (VY) - * - * Socket 1 (CF): - * MAX1602 Lubbock Register - * Pin Signal - * ----- ------- ---------------------- - * A0VPP GND VPP is not connected - * A1VPP GND VPP is not connected - * A0VCC S1_PWR0 MISC_WR<14> - * A1VCC S1_PWR1 MISC_WR<15> - * VX VCC - * VY +3.3V - * 12IN GND VPP is not connected - * CODE +3.3V Cirrus Code, CODE = High (VY) - * - */ - - again: - switch (skt->nr) { - case 0: - pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; - - switch (state->Vcc) { - case 0: /* Hi-Z */ - break; - - case 33: /* VY */ - pa_dwr_set |= GPIO_A3; - break; - - case 50: /* VX */ - pa_dwr_set |= GPIO_A2; - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", - __FUNCTION__, state->Vcc); - ret = -1; - } - - switch (state->Vpp) { - case 0: /* Hi-Z */ - break; - - case 120: /* 12IN */ - pa_dwr_set |= GPIO_A1; - break; - - default: /* VCC */ - if (state->Vpp == state->Vcc) - pa_dwr_set |= GPIO_A0; - else { - printk(KERN_ERR "%s(): unrecognized Vpp %u\n", - __FUNCTION__, state->Vpp); - ret = -1; - break; - } - } - break; - - case 1: - misc_mask = (1 << 15) | (1 << 14); - - switch (state->Vcc) { - case 0: /* Hi-Z */ - break; - - case 33: /* VY */ - misc_set |= 1 << 15; - break; - - case 50: /* VX */ - misc_set |= 1 << 14; - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", - __FUNCTION__, state->Vcc); - ret = -1; - break; - } - - if (state->Vpp != state->Vcc && state->Vpp != 0) { - printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", - __FUNCTION__, state->Vpp); - ret = -1; - break; - } - break; - - default: - ret = -1; - } - - if (ret == 0) - ret = sa1111_pcmcia_configure_socket(skt, state); - - if (ret == 0) { - lubbock_set_misc_wr(misc_mask, misc_set); - sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); - } - -#if 1 - if (ret == 0 && state->Vcc == 33) { - struct pcmcia_state new_state; - - /* - * HACK ALERT: - * We can't sense the voltage properly on Lubbock before - * actually applying some power to the socket (catch 22). - * Resense the socket Voltage Sense pins after applying - * socket power. - * - * Note: It takes about 2.5ms for the MAX1602 VCC output - * to rise. - */ - mdelay(3); - - sa1111_pcmcia_socket_state(skt, &new_state); - - if (!new_state.vs_3v && !new_state.vs_Xv) { - /* - * Switch to 5V, Configure socket with 5V voltage - */ - lubbock_set_misc_wr(misc_mask, 0); - sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); - - /* - * It takes about 100ms to turn off Vcc. - */ - mdelay(100); - - /* - * We need to hack around the const qualifier as - * well to keep this ugly workaround localized and - * not force it to the rest of the code. Barf bags - * avaliable in the seat pocket in front of you! - */ - ((socket_state_t *)state)->Vcc = 50; - ((socket_state_t *)state)->Vpp = 50; - goto again; - } - } -#endif - - return ret; -} - -static struct pcmcia_low_level lubbock_pcmcia_ops = { - .owner = THIS_MODULE, - .hw_init = sa1111_pcmcia_hw_init, - .hw_shutdown = sa1111_pcmcia_hw_shutdown, - .socket_state = sa1111_pcmcia_socket_state, - .configure_socket = lubbock_pcmcia_configure_socket, - .socket_init = sa1111_pcmcia_socket_init, - .socket_suspend = sa1111_pcmcia_socket_suspend, - .first = 0, - .nr = 2, -}; - -#include "pxa2xx_base.h" - -int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) -{ - int ret = -ENODEV; - - if (machine_is_lubbock()) { - /* - * Set GPIO_A<3:0> to be outputs for the MAX1600, - * and switch to standby mode. - */ - sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); - sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); - sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); - - /* Set CF Socket 1 power to standby mode. */ - lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); - - sadev->dev.platform_data = &lubbock_pcmcia_ops; - ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); - } - - return ret; -} diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c deleted file mode 100644 index af85842ee..000000000 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * linux/drivers/pcmcia/pxa2xx_mainstone.c - * - * Mainstone PCMCIA specific routines. - * - * Created: May 12, 2004 - * Author: Nicolas Pitre - * Copyright: MontaVista Software Inc. - * - * 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 "soc_common.h" - - -static struct pcmcia_irqs irqs[] = { - { 0, MAINSTONE_S0_CD_IRQ, "PCMCIA0 CD" }, - { 1, MAINSTONE_S1_CD_IRQ, "PCMCIA1 CD" }, - { 0, MAINSTONE_S0_STSCHG_IRQ, "PCMCIA0 STSCHG" }, - { 1, MAINSTONE_S1_STSCHG_IRQ, "PCMCIA1 STSCHG" }, -}; - -static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) -{ - skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ; - return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static void mst_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) -{ - soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); -} - -static unsigned long mst_pcmcia_status[2]; - -static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, - struct pcmcia_state *state) -{ - unsigned long status, flip; - - status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1; - flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1; - - /* - * Workaround for STSCHG which can't be deasserted: - * We therefore disable/enable corresponding IRQs - * as needed to avoid IRQ locks. - */ - if (flip) { - mst_pcmcia_status[skt->nr] = status; - if (status & MST_PCMCIA_nSTSCHG_BVD1) - enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ - : MAINSTONE_S1_STSCHG_IRQ ); - else - disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ - : MAINSTONE_S1_STSCHG_IRQ ); - } - - state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1; - state->ready = (status & MST_PCMCIA_nIRQ) ? 1 : 0; - state->bvd1 = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0; - state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0; - state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1; - state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1; - state->wrprot = 0; /* not available */ -} - -static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, - const socket_state_t *state) -{ - unsigned long power = 0; - int ret = 0; - - switch (state->Vcc) { - case 0: power |= MST_PCMCIA_PWR_VCC_0; break; - case 33: power |= MST_PCMCIA_PWR_VCC_33; break; - case 50: power |= MST_PCMCIA_PWR_VCC_50; break; - default: - printk(KERN_ERR "%s(): bad Vcc %u\n", - __FUNCTION__, state->Vcc); - ret = -1; - } - - switch (state->Vpp) { - case 0: power |= MST_PCMCIA_PWR_VPP_0; break; - case 120: power |= MST_PCMCIA_PWR_VPP_120; break; - default: - if(state->Vpp == state->Vcc) { - power |= MST_PCMCIA_PWR_VPP_VCC; - } else { - printk(KERN_ERR "%s(): bad Vpp %u\n", - __FUNCTION__, state->Vpp); - ret = -1; - } - } - - if (state->flags & SS_RESET) - power |= MST_PCMCIA_RESET; - - switch (skt->nr) { - case 0: MST_PCMCIA0 = power; break; - case 1: MST_PCMCIA1 = power; break; - default: ret = -1; - } - - return ret; -} - -static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt) -{ -} - -static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) -{ -} - -static struct pcmcia_low_level mst_pcmcia_ops = { - .owner = THIS_MODULE, - .hw_init = mst_pcmcia_hw_init, - .hw_shutdown = mst_pcmcia_hw_shutdown, - .socket_state = mst_pcmcia_socket_state, - .configure_socket = mst_pcmcia_configure_socket, - .socket_init = mst_pcmcia_socket_init, - .socket_suspend = mst_pcmcia_socket_suspend, - .nr = 2, -}; - -static struct platform_device *mst_pcmcia_device; - -static int __init mst_pcmcia_init(void) -{ - int ret; - - mst_pcmcia_device = kmalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL); - if (!mst_pcmcia_device) - return -ENOMEM; - memset(mst_pcmcia_device, 0, sizeof(*mst_pcmcia_device)); - mst_pcmcia_device->name = "pxa2xx-pcmcia"; - mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; - - ret = platform_device_register(mst_pcmcia_device); - if (ret) - kfree(mst_pcmcia_device); - - return ret; -} - -static void __exit mst_pcmcia_exit(void) -{ - /* - * This call is supposed to free our mst_pcmcia_device. - * Unfortunately platform_device don't have a free method, and - * we can't assume it's free of any reference at this point so we - * can't free it either. - */ - platform_device_unregister(mst_pcmcia_device); -} - -module_init(mst_pcmcia_init); -module_exit(mst_pcmcia_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c deleted file mode 100644 index fb634ab5d..000000000 --- a/drivers/pcmcia/sa11xx_base.c +++ /dev/null @@ -1,242 +0,0 @@ -/*====================================================================== - - Device driver for the PCMCIA control functionality of StrongARM - SA-1100 microprocessors. - - 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 John G. Dorsey - . Portions created by John G. Dorsey are - Copyright (C) 1999 John G. Dorsey. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU 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. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "soc_common.h" -#include "sa11xx_base.h" - - -/* - * sa1100_pcmcia_default_mecr_timing - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * Calculate MECR clock wait states for given CPU clock - * speed and command wait state. This function can be over- - * written by a board specific version. - * - * The default is to simply calculate the BS values as specified in - * the INTEL SA1100 development manual - * "Expansion Memory (PCMCIA) Configuration Register (MECR)" - * that's section 10.2.5 in _my_ version of the manual ;) - */ -static unsigned int -sa1100_pcmcia_default_mecr_timing(struct soc_pcmcia_socket *skt, - unsigned int cpu_speed, - unsigned int cmd_time) -{ - return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed); -} - -/* sa1100_pcmcia_set_mecr() - * ^^^^^^^^^^^^^^^^^^^^^^^^ - * - * set MECR value for socket based on this sockets - * io, mem and attribute space access speed. - * Call board specific BS value calculation to allow boards - * to tweak the BS values. - */ -static int -sa1100_pcmcia_set_mecr(struct soc_pcmcia_socket *skt, unsigned int cpu_clock) -{ - struct soc_pcmcia_timing timing; - u32 mecr, old_mecr; - unsigned long flags; - unsigned int bs_io, bs_mem, bs_attr; - - soc_common_pcmcia_get_timing(skt, &timing); - - bs_io = skt->ops->get_timing(skt, cpu_clock, timing.io); - bs_mem = skt->ops->get_timing(skt, cpu_clock, timing.mem); - bs_attr = skt->ops->get_timing(skt, cpu_clock, timing.attr); - - local_irq_save(flags); - - old_mecr = mecr = MECR; - MECR_FAST_SET(mecr, skt->nr, 0); - MECR_BSIO_SET(mecr, skt->nr, bs_io); - MECR_BSA_SET(mecr, skt->nr, bs_attr); - MECR_BSM_SET(mecr, skt->nr, bs_mem); - if (old_mecr != mecr) - MECR = mecr; - - local_irq_restore(flags); - - debug(skt, 2, "FAST %X BSM %X BSA %X BSIO %X\n", - MECR_FAST_GET(mecr, skt->nr), - MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr), - MECR_BSIO_GET(mecr, skt->nr)); - - return 0; -} - -static int -sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt) -{ - return sa1100_pcmcia_set_mecr(skt, cpufreq_get(0)); -} - -static int -sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf) -{ - struct soc_pcmcia_timing timing; - unsigned int clock = cpufreq_get(0); - unsigned long mecr = MECR; - char *p = buf; - - soc_common_pcmcia_get_timing(skt, &timing); - - p+=sprintf(p, "I/O : %u (%u)\n", timing.io, - sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr))); - - p+=sprintf(p, "attribute: %u (%u)\n", timing.attr, - sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr))); - - p+=sprintf(p, "common : %u (%u)\n", timing.mem, - sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr))); - - return p - buf; -} - -int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, - int first, int nr) -{ - /* - * set default MECR calculation if the board specific - * code did not specify one... - */ - if (!ops->get_timing) - ops->get_timing = sa1100_pcmcia_default_mecr_timing; - - /* Provide our SA11x0 specific timing routines. */ - ops->set_timing = sa1100_pcmcia_set_timing; - ops->show_timing = sa1100_pcmcia_show_timing; - - return soc_common_drv_pcmcia_probe(dev, ops, first, nr); -} -EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); - -#ifdef CONFIG_CPU_FREQ - -/* sa1100_pcmcia_update_mecr() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * When sa1100_pcmcia_notifier() decides that a MECR adjustment (due - * to a core clock frequency change) is needed, this routine establishes - * new BS_xx values consistent with the clock speed `clock'. - */ -static void sa1100_pcmcia_update_mecr(unsigned int clock) -{ - struct soc_pcmcia_socket *skt; - - down(&soc_pcmcia_sockets_lock); - list_for_each_entry(skt, &soc_pcmcia_sockets, node) - sa1100_pcmcia_set_mecr(skt, clock); - up(&soc_pcmcia_sockets_lock); -} - -/* sa1100_pcmcia_notifier() - * ^^^^^^^^^^^^^^^^^^^^^^^^ - * When changing the processor core clock frequency, it is necessary - * to adjust the MECR timings accordingly. We've recorded the timings - * requested by Card Services, so this is just a matter of finding - * out what our current speed is, and then recomputing the new MECR - * values. - * - * Returns: 0 on success, -1 on error - */ -static int -sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freqs = data; - - switch (val) { - case CPUFREQ_PRECHANGE: - if (freqs->new > freqs->old) - sa1100_pcmcia_update_mecr(freqs->new); - break; - - case CPUFREQ_POSTCHANGE: - if (freqs->new < freqs->old) - sa1100_pcmcia_update_mecr(freqs->new); - break; - case CPUFREQ_RESUMECHANGE: - sa1100_pcmcia_update_mecr(freqs->new); - break; - } - - return 0; -} - -static struct notifier_block sa1100_pcmcia_notifier_block = { - .notifier_call = sa1100_pcmcia_notifier -}; - -static int __init sa11xx_pcmcia_init(void) -{ - int ret; - - printk(KERN_INFO "SA11xx PCMCIA\n"); - - ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - if (ret < 0) - printk(KERN_ERR "Unable to register CPU frequency change " - "notifier (%d)\n", ret); - - return ret; -} -module_init(sa11xx_pcmcia_init); - -static void __exit sa11xx_pcmcia_exit(void) -{ - cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); -} - -module_exit(sa11xx_pcmcia_exit); -#endif - -MODULE_AUTHOR("John Dorsey "); -MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver"); -MODULE_LICENSE("Dual MPL/GPL"); diff --git a/drivers/pcmcia/sa11xx_base.h b/drivers/pcmcia/sa11xx_base.h deleted file mode 100644 index 7bc208280..000000000 --- a/drivers/pcmcia/sa11xx_base.h +++ /dev/null @@ -1,123 +0,0 @@ -/*====================================================================== - - Device driver for the PCMCIA control functionality of StrongARM - SA-1100 microprocessors. - - 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 John G. Dorsey - . Portions created by John G. Dorsey are - Copyright (C) 1999 John G. Dorsey. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU 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. - -======================================================================*/ - -#if !defined(_PCMCIA_SA1100_H) -# define _PCMCIA_SA1100_H - -/* SA-1100 PCMCIA Memory and I/O timing - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * The SA-1110 Developer's Manual, section 10.2.5, says the following: - * - * "To calculate the recommended BS_xx value for each address space: - * divide the command width time (the greater of twIOWR and twIORD, - * or the greater of twWE and twOE) by processor cycle time; divide - * by 2; divide again by 3 (number of BCLK's per command assertion); - * round up to the next whole number; and subtract 1." - */ - -/* MECR: Expansion Memory Configuration Register - * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24) - * - * MECR layout is: - * - * FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0> - * - * (This layout is actually true only for the SA-1110; the FASTn bits are - * reserved on the SA-1100.) - */ - -#define MECR_SOCKET_0_SHIFT (0) -#define MECR_SOCKET_1_SHIFT (16) - -#define MECR_BS_MASK (0x1f) -#define MECR_FAST_MODE_MASK (0x01) - -#define MECR_BSIO_SHIFT (0) -#define MECR_BSA_SHIFT (5) -#define MECR_BSM_SHIFT (10) -#define MECR_FAST_SHIFT (15) - -#define MECR_SET(mecr, sock, shift, mask, bs) \ -((mecr)=((mecr)&~(((mask)<<(shift))<<\ - ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\ - (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))) - -#define MECR_GET(mecr, sock, shift, mask) \ -((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\ - (shift))&(mask)) - -#define MECR_BSIO_SET(mecr, sock, bs) \ -MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs)) - -#define MECR_BSIO_GET(mecr, sock) \ -MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK) - -#define MECR_BSA_SET(mecr, sock, bs) \ -MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs)) - -#define MECR_BSA_GET(mecr, sock) \ -MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK) - -#define MECR_BSM_SET(mecr, sock, bs) \ -MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs)) - -#define MECR_BSM_GET(mecr, sock) \ -MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK) - -#define MECR_FAST_SET(mecr, sock, fast) \ -MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast)) - -#define MECR_FAST_GET(mecr, sock) \ -MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK) - - -/* This function implements the BS value calculation for setting the MECR - * using integer arithmetic: - */ -static inline unsigned int sa1100_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns, - unsigned int cpu_clock_khz){ - unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000; - return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1); -} - -/* This function returns the (approximate) command assertion period, in - * nanoseconds, for a given CPU clock frequency and MECR BS value: - */ -static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz, - unsigned int pcmcia_mecr_bs){ - return (((10000000 * 2) / cpu_clock_khz) * (3 * (pcmcia_mecr_bs + 1))) / 10; -} - - -extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr); - -#endif /* !defined(_PCMCIA_SA1100_H) */ diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c deleted file mode 100644 index ff8b52124..000000000 --- a/drivers/pcmcia/soc_common.c +++ /dev/null @@ -1,797 +0,0 @@ -/*====================================================================== - - Common support code for the PCMCIA control functionality of - integrated SOCs like the SA-11x0 and PXA2xx microprocessors. - - 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 John G. Dorsey - . Portions created by John G. Dorsey are - Copyright (C) 1999 John G. Dorsey. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU 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. - -======================================================================*/ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "soc_common.h" - -#ifdef DEBUG - -static int pc_debug; -module_param(pc_debug, int, 0644); - -void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, - int lvl, const char *fmt, ...) -{ - va_list args; - if (pc_debug > lvl) { - printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func); - va_start(args, fmt); - printk(fmt, args); - va_end(args); - } -} - -#endif - -#define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket) - -static unsigned short -calc_speed(unsigned short *spds, int num, unsigned short dflt) -{ - unsigned short speed = 0; - int i; - - for (i = 0; i < num; i++) - if (speed < spds[i]) - speed = spds[i]; - if (speed == 0) - speed = dflt; - - return speed; -} - -void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing) -{ - timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS); - timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); - timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); -} -EXPORT_SYMBOL(soc_common_pcmcia_get_timing); - -static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) -{ - struct pcmcia_state state; - unsigned int stat; - - memset(&state, 0, sizeof(struct pcmcia_state)); - - skt->ops->socket_state(skt, &state); - - stat = state.detect ? SS_DETECT : 0; - stat |= state.ready ? SS_READY : 0; - stat |= state.wrprot ? SS_WRPROT : 0; - stat |= state.vs_3v ? SS_3VCARD : 0; - stat |= state.vs_Xv ? SS_XVCARD : 0; - - /* The power status of individual sockets is not available - * explicitly from the hardware, so we just remember the state - * and regurgitate it upon request: - */ - stat |= skt->cs_state.Vcc ? SS_POWERON : 0; - - if (skt->cs_state.flags & SS_IOCARD) - stat |= state.bvd1 ? SS_STSCHG : 0; - else { - if (state.bvd1 == 0) - stat |= SS_BATDEAD; - else if (state.bvd2 == 0) - stat |= SS_BATWARN; - } - return stat; -} - -/* - * soc_common_pcmcia_config_skt - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * Convert PCMCIA socket state to our socket configure structure. - */ -static int -soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state) -{ - int ret; - - ret = skt->ops->configure_socket(skt, state); - if (ret == 0) { - /* - * This really needs a better solution. The IRQ - * may or may not be claimed by the driver. - */ - if (skt->irq_state != 1 && state->io_irq) { - skt->irq_state = 1; - set_irq_type(skt->irq, IRQT_FALLING); - } else if (skt->irq_state == 1 && state->io_irq == 0) { - skt->irq_state = 0; - set_irq_type(skt->irq, IRQT_NOEDGE); - } - - skt->cs_state = *state; - } - - if (ret < 0) - printk(KERN_ERR "soc_common_pcmcia: unable to configure " - "socket %d\n", skt->nr); - - return ret; -} - -/* soc_common_pcmcia_sock_init() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * (Re-)Initialise the socket, turning on status interrupts - * and PCMCIA bus. This must wait for power to stabilise - * so that the card status signals report correctly. - * - * Returns: 0 - */ -static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - - debug(skt, 2, "initializing socket\n"); - - skt->ops->socket_init(skt); - return 0; -} - - -/* - * soc_common_pcmcia_suspend() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * Remove power on the socket, disable IRQs from the card. - * Turn off status interrupts, and disable the PCMCIA bus. - * - * Returns: 0 - */ -static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - int ret; - - debug(skt, 2, "suspending socket\n"); - - ret = soc_common_pcmcia_config_skt(skt, &dead_socket); - if (ret == 0) - skt->ops->socket_suspend(skt); - - return ret; -} - -static spinlock_t status_lock = SPIN_LOCK_UNLOCKED; - -static void soc_common_check_status(struct soc_pcmcia_socket *skt) -{ - unsigned int events; - - debug(skt, 4, "entering PCMCIA monitoring thread\n"); - - do { - unsigned int status; - unsigned long flags; - - status = soc_common_pcmcia_skt_state(skt); - - spin_lock_irqsave(&status_lock, flags); - events = (status ^ skt->status) & skt->cs_state.csc_mask; - skt->status = status; - spin_unlock_irqrestore(&status_lock, flags); - - debug(skt, 4, "events: %s%s%s%s%s%s\n", - events == 0 ? "" : "", - events & SS_DETECT ? "DETECT " : "", - events & SS_READY ? "READY " : "", - events & SS_BATDEAD ? "BATDEAD " : "", - events & SS_BATWARN ? "BATWARN " : "", - events & SS_STSCHG ? "STSCHG " : ""); - - if (events) - pcmcia_parse_events(&skt->socket, events); - } while (events); -} - -/* Let's poll for events in addition to IRQs since IRQ only is unreliable... */ -static void soc_common_pcmcia_poll_event(unsigned long dummy) -{ - struct soc_pcmcia_socket *skt = (struct soc_pcmcia_socket *)dummy; - debug(skt, 4, "polling for events\n"); - - mod_timer(&skt->poll_timer, jiffies + SOC_PCMCIA_POLL_PERIOD); - - soc_common_check_status(skt); -} - - -/* - * Service routine for socket driver interrupts (requested by the - * low-level PCMCIA init() operation via soc_common_pcmcia_thread()). - * The actual interrupt-servicing work is performed by - * soc_common_pcmcia_thread(), largely because the Card Services event- - * handling code performs scheduling operations which cannot be - * executed from within an interrupt context. - */ -static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) -{ - struct soc_pcmcia_socket *skt = dev; - - debug(skt, 3, "servicing IRQ %d\n", irq); - - soc_common_check_status(skt); - - return IRQ_HANDLED; -} - - -/* - * Implements the get_status() operation for the in-kernel PCMCIA - * service (formerly SS_GetStatus in Card Services). Essentially just - * fills in bits in `status' according to internal driver state or - * the value of the voltage detect chipselect register. - * - * As a debugging note, during card startup, the PCMCIA core issues - * three set_socket() commands in a row the first with RESET deasserted, - * the second with RESET asserted, and the last with RESET deasserted - * again. Following the third set_socket(), a get_status() command will - * be issued. The kernel is looking for the SS_READY flag (see - * setup_socket(), reset_socket(), and unreset_socket() in cs.c). - * - * Returns: 0 - */ -static int -soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - - skt->status = soc_common_pcmcia_skt_state(skt); - *status = skt->status; - - return 0; -} - - -/* - * Implements the get_socket() operation for the in-kernel PCMCIA - * service (formerly SS_GetSocket in Card Services). Not a very - * exciting routine. - * - * Returns: 0 - */ -static int -soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - - debug(skt, 2, "\n"); - - *state = skt->cs_state; - - return 0; -} - -/* - * Implements the set_socket() operation for the in-kernel PCMCIA - * service (formerly SS_SetSocket in Card Services). We more or - * less punt all of this work and let the kernel handle the details - * of power configuration, reset, &c. We also record the value of - * `state' in order to regurgitate it to the PCMCIA core later. - * - * Returns: 0 - */ -static int -soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - - debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n", - (state->csc_mask==0)?" ":"", - (state->csc_mask&SS_DETECT)?"DETECT ":"", - (state->csc_mask&SS_READY)?"READY ":"", - (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"", - (state->csc_mask&SS_BATWARN)?"BATWARN ":"", - (state->csc_mask&SS_STSCHG)?"STSCHG ":"", - (state->flags==0)?" ":"", - (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"", - (state->flags&SS_IOCARD)?"IOCARD ":"", - (state->flags&SS_RESET)?"RESET ":"", - (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"", - (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"", - state->Vcc, state->Vpp, state->io_irq); - - return soc_common_pcmcia_config_skt(skt, state); -} - - -/* - * Implements the set_io_map() operation for the in-kernel PCMCIA - * service (formerly SS_SetIOMap in Card Services). We configure - * the map speed as requested, but override the address ranges - * supplied by Card Services. - * - * Returns: 0 on success, -1 on error - */ -static int -soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - unsigned short speed = map->speed; - - debug(skt, 2, "map %u speed %u start 0x%08x stop 0x%08x\n", - map->map, map->speed, map->start, map->stop); - debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n", - (map->flags==0)?"":"", - (map->flags&MAP_ACTIVE)?"ACTIVE ":"", - (map->flags&MAP_16BIT)?"16BIT ":"", - (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", - (map->flags&MAP_0WS)?"0WS ":"", - (map->flags&MAP_WRPROT)?"WRPROT ":"", - (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"", - (map->flags&MAP_PREFETCH)?"PREFETCH ":""); - - if (map->map >= MAX_IO_WIN) { - printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, - map->map); - return -1; - } - - if (map->flags & MAP_ACTIVE) { - if (speed == 0) - speed = SOC_PCMCIA_IO_ACCESS; - } else { - speed = 0; - } - - skt->spd_io[map->map] = speed; - skt->ops->set_timing(skt); - - if (map->stop == 1) - map->stop = PAGE_SIZE-1; - - map->stop -= map->start; - map->stop += (unsigned long)skt->virt_io; - map->start = (unsigned long)skt->virt_io; - - return 0; -} - - -/* - * Implements the set_mem_map() operation for the in-kernel PCMCIA - * service (formerly SS_SetMemMap in Card Services). We configure - * the map speed as requested, but override the address ranges - * supplied by Card Services. - * - * Returns: 0 on success, -1 on error - */ -static int -soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - struct resource *res; - unsigned short speed = map->speed; - - debug(skt, 2, "map %u speed %u card_start %08x\n", - map->map, map->speed, map->card_start); - debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n", - (map->flags==0)?"":"", - (map->flags&MAP_ACTIVE)?"ACTIVE ":"", - (map->flags&MAP_16BIT)?"16BIT ":"", - (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", - (map->flags&MAP_0WS)?"0WS ":"", - (map->flags&MAP_WRPROT)?"WRPROT ":"", - (map->flags&MAP_ATTRIB)?"ATTRIB ":"", - (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); - - if (map->map >= MAX_WIN) - return -EINVAL; - - if (map->flags & MAP_ACTIVE) { - if (speed == 0) - speed = 300; - } else { - speed = 0; - } - - if (map->flags & MAP_ATTRIB) { - res = &skt->res_attr; - skt->spd_attr[map->map] = speed; - skt->spd_mem[map->map] = 0; - } else { - res = &skt->res_mem; - skt->spd_attr[map->map] = 0; - skt->spd_mem[map->map] = speed; - } - - skt->ops->set_timing(skt); - - map->sys_stop -= map->sys_start; - map->sys_stop += res->start + map->card_start; - map->sys_start = res->start + map->card_start; - - return 0; -} - -struct bittbl { - unsigned int mask; - const char *name; -}; - -static struct bittbl status_bits[] = { - { SS_WRPROT, "SS_WRPROT" }, - { SS_BATDEAD, "SS_BATDEAD" }, - { SS_BATWARN, "SS_BATWARN" }, - { SS_READY, "SS_READY" }, - { SS_DETECT, "SS_DETECT" }, - { SS_POWERON, "SS_POWERON" }, - { SS_STSCHG, "SS_STSCHG" }, - { SS_3VCARD, "SS_3VCARD" }, - { SS_XVCARD, "SS_XVCARD" }, -}; - -static struct bittbl conf_bits[] = { - { SS_PWR_AUTO, "SS_PWR_AUTO" }, - { SS_IOCARD, "SS_IOCARD" }, - { SS_RESET, "SS_RESET" }, - { SS_DMA_MODE, "SS_DMA_MODE" }, - { SS_SPKR_ENA, "SS_SPKR_ENA" }, - { SS_OUTPUT_ENA, "SS_OUTPUT_ENA" }, -}; - -static void -dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz) -{ - char *b = *p; - int i; - - b += sprintf(b, "%-9s:", prefix); - for (i = 0; i < sz; i++) - if (val & bits[i].mask) - b += sprintf(b, " %s", bits[i].name); - *b++ = '\n'; - *p = b; -} - -/* - * Implements the /sys/class/pcmcia_socket/??/status file. - * - * Returns: the number of characters added to the buffer - */ -static ssize_t show_status(struct class_device *class_dev, char *buf) -{ - struct soc_pcmcia_socket *skt = - container_of(class_dev, struct soc_pcmcia_socket, socket.dev); - char *p = buf; - - p+=sprintf(p, "slot : %d\n", skt->nr); - - dump_bits(&p, "status", skt->status, - status_bits, ARRAY_SIZE(status_bits)); - dump_bits(&p, "csc_mask", skt->cs_state.csc_mask, - status_bits, ARRAY_SIZE(status_bits)); - dump_bits(&p, "cs_flags", skt->cs_state.flags, - conf_bits, ARRAY_SIZE(conf_bits)); - - p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc); - p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp); - p+=sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq, skt->irq); - if (skt->ops->show_timing) - p+=skt->ops->show_timing(skt, p); - - return p-buf; -} -static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - - -static struct pccard_operations soc_common_pcmcia_operations = { - .init = soc_common_pcmcia_sock_init, - .suspend = soc_common_pcmcia_suspend, - .get_status = soc_common_pcmcia_get_status, - .get_socket = soc_common_pcmcia_get_socket, - .set_socket = soc_common_pcmcia_set_socket, - .set_io_map = soc_common_pcmcia_set_io_map, - .set_mem_map = soc_common_pcmcia_set_mem_map, -}; - - -int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i, res = 0; - - for (i = 0; i < nr; i++) { - if (irqs[i].sock != skt->nr) - continue; - res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt, - SA_INTERRUPT, irqs[i].str, skt); - if (res) - break; - set_irq_type(irqs[i].irq, IRQT_NOEDGE); - } - - if (res) { - printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n", - irqs[i].irq, res); - - while (i--) - if (irqs[i].sock == skt->nr) - free_irq(irqs[i].irq, skt); - } - return res; -} -EXPORT_SYMBOL(soc_pcmcia_request_irqs); - -void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) - free_irq(irqs[i].irq, skt); -} -EXPORT_SYMBOL(soc_pcmcia_free_irqs); - -void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) - set_irq_type(irqs[i].irq, IRQT_NOEDGE); -} -EXPORT_SYMBOL(soc_pcmcia_disable_irqs); - -void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, - struct pcmcia_irqs *irqs, int nr) -{ - int i; - - for (i = 0; i < nr; i++) - if (irqs[i].sock == skt->nr) { - set_irq_type(irqs[i].irq, IRQT_RISING); - set_irq_type(irqs[i].irq, IRQT_BOTHEDGE); - } -} -EXPORT_SYMBOL(soc_pcmcia_enable_irqs); - - -LIST_HEAD(soc_pcmcia_sockets); -DECLARE_MUTEX(soc_pcmcia_sockets_lock); - -static const char *skt_names[] = { - "PCMCIA socket 0", - "PCMCIA socket 1", -}; - -struct skt_dev_info { - int nskt; - struct soc_pcmcia_socket skt[0]; -}; - -#define SKT_DEV_INFO_SIZE(n) \ - (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) - -int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) -{ - struct skt_dev_info *sinfo; - int ret, i; - - down(&soc_pcmcia_sockets_lock); - - sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); - if (!sinfo) { - ret = -ENOMEM; - goto out; - } - - memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr)); - sinfo->nskt = nr; - - /* - * Initialise the per-socket structure. - */ - for (i = 0; i < nr; i++) { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; - - skt->socket.ops = &soc_common_pcmcia_operations; - skt->socket.owner = ops->owner; - skt->socket.dev.dev = dev; - - init_timer(&skt->poll_timer); - skt->poll_timer.function = soc_common_pcmcia_poll_event; - skt->poll_timer.data = (unsigned long)skt; - skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; - - skt->nr = first + i; - skt->irq = NO_IRQ; - skt->dev = dev; - skt->ops = ops; - - skt->res_skt.start = _PCMCIA(skt->nr); - skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; - skt->res_skt.name = skt_names[skt->nr]; - skt->res_skt.flags = IORESOURCE_MEM; - - ret = request_resource(&iomem_resource, &skt->res_skt); - if (ret) - goto out_err_1; - - skt->res_io.start = _PCMCIAIO(skt->nr); - skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; - skt->res_io.name = "io"; - skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - - ret = request_resource(&skt->res_skt, &skt->res_io); - if (ret) - goto out_err_2; - - skt->res_mem.start = _PCMCIAMem(skt->nr); - skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; - skt->res_mem.name = "memory"; - skt->res_mem.flags = IORESOURCE_MEM; - - ret = request_resource(&skt->res_skt, &skt->res_mem); - if (ret) - goto out_err_3; - - skt->res_attr.start = _PCMCIAAttr(skt->nr); - skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; - skt->res_attr.name = "attribute"; - skt->res_attr.flags = IORESOURCE_MEM; - - ret = request_resource(&skt->res_skt, &skt->res_attr); - if (ret) - goto out_err_4; - - skt->virt_io = ioremap(skt->res_io.start, 0x10000); - if (skt->virt_io == NULL) { - ret = -ENOMEM; - goto out_err_5; - } - - list_add(&skt->node, &soc_pcmcia_sockets); - - /* - * We initialize default socket timing here, because - * we are not guaranteed to see a SetIOMap operation at - * runtime. - */ - ops->set_timing(skt); - - ret = ops->hw_init(skt); - if (ret) - goto out_err_6; - - skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; - skt->socket.irq_mask = 0; - skt->socket.map_size = PAGE_SIZE; - skt->socket.pci_irq = skt->irq; - skt->socket.io_offset = (unsigned long)skt->virt_io; - - skt->status = soc_common_pcmcia_skt_state(skt); - - ret = pcmcia_register_socket(&skt->socket); - if (ret) - goto out_err_7; - - WARN_ON(skt->socket.sock != i); - - add_timer(&skt->poll_timer); - - class_device_create_file(&skt->socket.dev, &class_device_attr_status); - } - - dev_set_drvdata(dev, sinfo); - ret = 0; - goto out; - - do { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; - - del_timer_sync(&skt->poll_timer); - pcmcia_unregister_socket(&skt->socket); - - out_err_7: - flush_scheduled_work(); - - ops->hw_shutdown(skt); - out_err_6: - list_del(&skt->node); - iounmap(skt->virt_io); - out_err_5: - release_resource(&skt->res_attr); - out_err_4: - release_resource(&skt->res_mem); - out_err_3: - release_resource(&skt->res_io); - out_err_2: - release_resource(&skt->res_skt); - out_err_1: - i--; - } while (i > 0); - - kfree(sinfo); - - out: - up(&soc_pcmcia_sockets_lock); - return ret; -} - -int soc_common_drv_pcmcia_remove(struct device *dev) -{ - struct skt_dev_info *sinfo = dev_get_drvdata(dev); - int i; - - dev_set_drvdata(dev, NULL); - - down(&soc_pcmcia_sockets_lock); - for (i = 0; i < sinfo->nskt; i++) { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; - - del_timer_sync(&skt->poll_timer); - - pcmcia_unregister_socket(&skt->socket); - - flush_scheduled_work(); - - skt->ops->hw_shutdown(skt); - - soc_common_pcmcia_config_skt(skt, &dead_socket); - - list_del(&skt->node); - iounmap(skt->virt_io); - skt->virt_io = NULL; - release_resource(&skt->res_attr); - release_resource(&skt->res_mem); - release_resource(&skt->res_io); - release_resource(&skt->res_skt); - } - up(&soc_pcmcia_sockets_lock); - - kfree(sinfo); - - return 0; -} diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h deleted file mode 100644 index 60e30197b..000000000 --- a/drivers/pcmcia/soc_common.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * linux/drivers/pcmcia/soc_common.h - * - * Copyright (C) 2000 John G Dorsey - * - * This file contains definitions for the PCMCIA support code common to - * integrated SOCs like the SA-11x0 and PXA2xx microprocessors. - */ -#ifndef _ASM_ARCH_PCMCIA -#define _ASM_ARCH_PCMCIA - -/* include the world */ -#include -#include -#include -#include -#include -#include -#include "cs_internal.h" - - -struct device; -struct pcmcia_low_level; - -/* - * This structure encapsulates per-socket state which we might need to - * use when responding to a Card Services query of some kind. - */ -struct soc_pcmcia_socket { - struct pcmcia_socket socket; - - /* - * Info from low level handler - */ - struct device *dev; - unsigned int nr; - unsigned int irq; - - /* - * Core PCMCIA state - */ - struct pcmcia_low_level *ops; - - unsigned int status; - socket_state_t cs_state; - - unsigned short spd_io[MAX_IO_WIN]; - unsigned short spd_mem[MAX_WIN]; - unsigned short spd_attr[MAX_WIN]; - - struct resource res_skt; - struct resource res_io; - struct resource res_mem; - struct resource res_attr; - void *virt_io; - - unsigned int irq_state; - - struct timer_list poll_timer; - struct list_head node; -}; - -struct pcmcia_state { - unsigned detect: 1, - ready: 1, - bvd1: 1, - bvd2: 1, - wrprot: 1, - vs_3v: 1, - vs_Xv: 1; -}; - -struct pcmcia_low_level { - struct module *owner; - - /* first socket in system */ - int first; - /* nr of sockets */ - int nr; - - int (*hw_init)(struct soc_pcmcia_socket *); - void (*hw_shutdown)(struct soc_pcmcia_socket *); - - void (*socket_state)(struct soc_pcmcia_socket *, struct pcmcia_state *); - int (*configure_socket)(struct soc_pcmcia_socket *, const socket_state_t *); - - /* - * Enable card status IRQs on (re-)initialisation. This can - * be called at initialisation, power management event, or - * pcmcia event. - */ - void (*socket_init)(struct soc_pcmcia_socket *); - - /* - * Disable card status IRQs and PCMCIA bus on suspend. - */ - void (*socket_suspend)(struct soc_pcmcia_socket *); - - /* - * Hardware specific timing routines. - * If provided, the get_timing routine overrides the SOC default. - */ - unsigned int (*get_timing)(struct soc_pcmcia_socket *, unsigned int, unsigned int); - int (*set_timing)(struct soc_pcmcia_socket *); - int (*show_timing)(struct soc_pcmcia_socket *, char *); -}; - - -struct pcmcia_irqs { - int sock; - int irq; - const char *str; -}; - -struct soc_pcmcia_timing { - unsigned short io; - unsigned short mem; - unsigned short attr; -}; - -extern int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); -extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *); - - -extern struct list_head soc_pcmcia_sockets; -extern struct semaphore soc_pcmcia_sockets_lock; - -extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr); -extern int soc_common_drv_pcmcia_remove(struct device *dev); - - -#ifdef DEBUG - -extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, - int lvl, const char *fmt, ...); - -#define debug(skt, lvl, fmt, arg...) \ - soc_pcmcia_debug(skt, __func__, lvl, fmt , ## arg) - -#else -#define debug(skt, lvl, fmt, arg...) do { } while (0) -#endif - - -/* - * The PC Card Standard, Release 7, section 4.13.4, says that twIORD - * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has - * a minimum value of 165ns, as well. Section 4.7.2 (describing - * common and attribute memory write timing) says that twWE has a - * minimum value of 150ns for a 250ns cycle time (for 5V operation; - * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V - * operation, also section 4.7.4). Section 4.7.3 says that taOE - * has a maximum value of 150ns for a 300ns cycle time (for 5V - * operation), or 300ns for a 600ns cycle time (for 3.3V operation). - * - * When configuring memory maps, Card Services appears to adopt the policy - * that a memory access time of "0" means "use the default." The default - * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute - * and memory command width time is 150ns; the PCMCIA 3.3V attribute and - * memory command width time is 300ns. - */ -#define SOC_PCMCIA_IO_ACCESS (165) -#define SOC_PCMCIA_5V_MEM_ACCESS (150) -#define SOC_PCMCIA_3V_MEM_ACCESS (300) -#define SOC_PCMCIA_ATTR_MEM_ACCESS (300) - -/* - * The socket driver actually works nicely in interrupt-driven form, - * so the (relatively infrequent) polling is "just to be sure." - */ -#define SOC_PCMCIA_POLL_PERIOD (2*HZ) - - -/* I/O pins replacing memory pins - * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75) - * - * These signals change meaning when going from memory-only to - * memory-or-I/O interface: - */ -#define iostschg bvd1 -#define iospkr bvd2 - -#endif diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c deleted file mode 100644 index 5b6ce0a88..000000000 --- a/drivers/scsi/qlogicfas408.c +++ /dev/null @@ -1,637 +0,0 @@ -/*----------------------------------------------------------------*/ -/* - Qlogic linux driver - work in progress. No Warranty express or implied. - Use at your own risk. Support Tort Reform so you won't have to read all - these silly disclaimers. - - Copyright 1994, Tom Zerucha. - tz@execpc.com - - Additional Code, and much appreciated help by - Michael A. Griffith - grif@cs.ucr.edu - - Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA - help respectively, and for suffering through my foolishness during the - debugging process. - - Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 - (you can reference it, but it is incomplete and inaccurate in places) - - Version 0.46 1/30/97 - kernel 1.2.0+ - - Functions as standalone, loadable, and PCMCIA driver, the latter from - Dave Hinds' PCMCIA package. - - Cleaned up 26/10/2002 by Alan Cox as part of the 2.5 - SCSI driver cleanup and audit. This driver still needs work on the - following - - Non terminating hardware waits - - Some layering violations with its pcmcia stub - - Redistributable under terms of the GNU General Public License - - For the avoidance of doubt the "preferred form" of this code is one which - is in an open non patent encumbered format. Where cryptographic key signing - forms part of the process of creating an executable the information - including keys needed to generate an equivalently functional executable - are deemed to be part of the source code. - -*/ - -#include -#include /* to get disk capacity */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "scsi.h" -#include -#include "qlogicfas408.h" - -/*----------------------------------------------------------------*/ -static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ -static int qlcfg6 = SYNCXFRPD; -static int qlcfg7 = SYNCOFFST; -static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); -static int qlcfg9 = ((XTALFREQ + 4) / 5); -static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); - -/*----------------------------------------------------------------*/ - -/*----------------------------------------------------------------*/ -/* local functions */ -/*----------------------------------------------------------------*/ - -/* error recovery - reset everything */ - -static void ql_zap(struct qlogicfas408_priv *priv) -{ - int x; - int qbase = priv->qbase; - int int_type = priv->int_type; - - x = inb(qbase + 0xd); - REG0; - outb(3, qbase + 3); /* reset SCSI */ - outb(2, qbase + 3); /* reset chip */ - if (x & 0x80) - REG1; -} - -/* - * Do a pseudo-dma tranfer - */ - -static int ql_pdma(struct qlogicfas408_priv *priv, int phase, char *request, int reqlen) -{ - int j; - int qbase = priv->qbase; - j = 0; - if (phase & 1) { /* in */ -#if QL_TURBO_PDMA - rtrc(4) - /* empty fifo in large chunks */ - if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */ - insl(qbase + 4, request, 32); - reqlen -= 128; - request += 128; - } - while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */ - if ((j = inb(qbase + 8)) & 4) - { - insl(qbase + 4, request, 21); - reqlen -= 84; - request += 84; - } - if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */ - insl(qbase + 4, request, 11); - reqlen -= 44; - request += 44; - } -#endif - /* until both empty and int (or until reclen is 0) */ - rtrc(7) - j = 0; - while (reqlen && !((j & 0x10) && (j & 0xc0))) - { - /* while bytes to receive and not empty */ - j &= 0xc0; - while (reqlen && !((j = inb(qbase + 8)) & 0x10)) - { - *request++ = inb(qbase + 4); - reqlen--; - } - if (j & 0x10) - j = inb(qbase + 8); - - } - } else { /* out */ -#if QL_TURBO_PDMA - rtrc(4) - if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */ - outsl(qbase + 4, request, 32); - reqlen -= 128; - request += 128; - } - while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */ - if (!((j = inb(qbase + 8)) & 8)) { - outsl(qbase + 4, request, 21); - reqlen -= 84; - request += 84; - } - if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */ - outsl(qbase + 4, request, 10); - reqlen -= 40; - request += 40; - } -#endif - /* until full and int (or until reclen is 0) */ - rtrc(7) - j = 0; - while (reqlen && !((j & 2) && (j & 0xc0))) { - /* while bytes to send and not full */ - while (reqlen && !((j = inb(qbase + 8)) & 2)) - { - outb(*request++, qbase + 4); - reqlen--; - } - if (j & 2) - j = inb(qbase + 8); - } - } - /* maybe return reqlen */ - return inb(qbase + 8) & 0xc0; -} - -/* - * Wait for interrupt flag (polled - not real hardware interrupt) - */ - -static int ql_wai(struct qlogicfas408_priv *priv) -{ - int k; - int qbase = priv->qbase; - unsigned long i; - - k = 0; - i = jiffies + WATCHDOG; - while (time_before(jiffies, i) && !priv->qabort && - !((k = inb(qbase + 4)) & 0xe0)) { - barrier(); - cpu_relax(); - } - if (time_after_eq(jiffies, i)) - return (DID_TIME_OUT); - if (priv->qabort) - return (priv->qabort == 1 ? DID_ABORT : DID_RESET); - if (k & 0x60) - ql_zap(priv); - if (k & 0x20) - return (DID_PARITY); - if (k & 0x40) - return (DID_ERROR); - return 0; -} - -/* - * Initiate scsi command - queueing handler - * caller must hold host lock - */ - -static void ql_icmd(Scsi_Cmnd * cmd) -{ - struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); - int qbase = priv->qbase; - int int_type = priv->int_type; - unsigned int i; - - priv->qabort = 0; - - REG0; - /* clearing of interrupts and the fifo is needed */ - - inb(qbase + 5); /* clear interrupts */ - if (inb(qbase + 5)) /* if still interrupting */ - outb(2, qbase + 3); /* reset chip */ - else if (inb(qbase + 7) & 0x1f) - outb(1, qbase + 3); /* clear fifo */ - while (inb(qbase + 5)); /* clear ints */ - REG1; - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - outb(0, qbase + 0xb); /* disable ints */ - inb(qbase + 8); /* clear int bits */ - REG0; - outb(0x40, qbase + 0xb); /* enable features */ - - /* configurables */ - outb(qlcfgc, qbase + 0xc); - /* config: no reset interrupt, (initiator) bus id */ - outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8); - outb(qlcfg7, qbase + 7); - outb(qlcfg6, qbase + 6); - /**/ outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9 & 7, qbase + 9); /* prescaler */ -/* outb(0x99, qbase + 5); */ - outb(cmd->device->id, qbase + 4); - - for (i = 0; i < cmd->cmd_len; i++) - outb(cmd->cmnd[i], qbase + 2); - - priv->qlcmd = cmd; - outb(0x41, qbase + 3); /* select and send command */ -} - -/* - * Process scsi command - usually after interrupt - */ - -static unsigned int ql_pcmd(Scsi_Cmnd * cmd) -{ - unsigned int i, j; - unsigned long k; - unsigned int result; /* ultimate return result */ - unsigned int status; /* scsi returned status */ - unsigned int message; /* scsi returned message */ - unsigned int phase; /* recorded scsi phase */ - unsigned int reqlen; /* total length of transfer */ - struct scatterlist *sglist; /* scatter-gather list pointer */ - unsigned int sgcount; /* sg counter */ - char *buf; - struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); - int qbase = priv->qbase; - int int_type = priv->int_type; - - rtrc(1) - j = inb(qbase + 6); - i = inb(qbase + 5); - if (i == 0x20) { - return (DID_NO_CONNECT << 16); - } - i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ - if (i != 0x18) { - printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); - ql_zap(priv); - return (DID_BAD_INTR << 16); - } - j &= 7; /* j = inb( qbase + 7 ) >> 5; */ - - /* correct status is supposed to be step 4 */ - /* it sometimes returns step 3 but with 0 bytes left to send */ - /* We can try stuffing the FIFO with the max each time, but we will get a - sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ - - if (j != 3 && j != 4) { - printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", - j, i, inb(qbase + 7) & 0x1f); - ql_zap(priv); - return (DID_ERROR << 16); - } - result = DID_OK; - if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ - outb(1, qbase + 3); /* clear fifo */ - /* note that request_bufflen is the total xfer size when sg is used */ - reqlen = cmd->request_bufflen; - /* note that it won't work if transfers > 16M are requested */ - if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ - rtrc(2) - outb(reqlen, qbase); /* low-mid xfer cnt */ - outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ - outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ - outb(0x90, qbase + 3); /* command do xfer */ - /* PIO pseudo DMA to buffer or sglist */ - REG1; - if (!cmd->use_sg) - ql_pdma(priv, phase, cmd->request_buffer, - cmd->request_bufflen); - else { - sgcount = cmd->use_sg; - sglist = cmd->request_buffer; - while (sgcount--) { - if (priv->qabort) { - REG0; - return ((priv->qabort == 1 ? - DID_ABORT : DID_RESET) << 16); - } - buf = page_address(sglist->page) + sglist->offset; - if (ql_pdma(priv, phase, buf, sglist->length)) - break; - sglist++; - } - } - REG0; - rtrc(2) - /* - * Wait for irq (split into second state of irq handler - * if this can take time) - */ - if ((k = ql_wai(priv))) - return (k << 16); - k = inb(qbase + 5); /* should be 0x10, bus service */ - } - - /* - * Enter Status (and Message In) Phase - */ - - k = jiffies + WATCHDOG; - - while (time_before(jiffies, k) && !priv->qabort && - !(inb(qbase + 4) & 6)) - cpu_relax(); /* wait for status phase */ - - if (time_after_eq(jiffies, k)) { - ql_zap(priv); - return (DID_TIME_OUT << 16); - } - - /* FIXME: timeout ?? */ - while (inb(qbase + 5)) - cpu_relax(); /* clear pending ints */ - - if (priv->qabort) - return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); - - outb(0x11, qbase + 3); /* get status and message */ - if ((k = ql_wai(priv))) - return (k << 16); - i = inb(qbase + 5); /* get chip irq stat */ - j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ - status = inb(qbase + 2); - message = inb(qbase + 2); - - /* - * Should get function complete int if Status and message, else - * bus serv if only status - */ - if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { - printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); - result = DID_ERROR; - } - outb(0x12, qbase + 3); /* done, disconnect */ - rtrc(1) - if ((k = ql_wai(priv))) - return (k << 16); - - /* - * Should get bus service interrupt and disconnect interrupt - */ - - i = inb(qbase + 5); /* should be bus service */ - while (!priv->qabort && ((i & 0x20) != 0x20)) { - barrier(); - cpu_relax(); - i |= inb(qbase + 5); - } - rtrc(0) - - if (priv->qabort) - return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); - - return (result << 16) | (message << 8) | (status & STATUS_MASK); -} - -/* - * Interrupt handler - */ - -static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) -{ - Scsi_Cmnd *icmd; - struct Scsi_Host *host = (struct Scsi_Host *)dev_id; - struct qlogicfas408_priv *priv = get_priv_by_host(host); - int qbase = priv->qbase; - REG0; - - if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ - return; - - if (priv->qlcmd == NULL) { /* no command to process? */ - int i; - i = 16; - while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ - return; - } - icmd = priv->qlcmd; - icmd->result = ql_pcmd(icmd); - priv->qlcmd = NULL; - /* - * If result is CHECK CONDITION done calls qcommand to request - * sense - */ - (icmd->scsi_done) (icmd); -} - -irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *host = dev_id; - - spin_lock_irqsave(host->host_lock, flags); - ql_ihandl(irq, dev_id, regs); - spin_unlock_irqrestore(host->host_lock, flags); - return IRQ_HANDLED; -} - -/* - * Queued command - */ - -int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); - if (cmd->device->id == priv->qinitid) { - cmd->result = DID_BAD_TARGET << 16; - done(cmd); - return 0; - } - - cmd->scsi_done = done; - /* wait for the last command's interrupt to finish */ - while (priv->qlcmd != NULL) { - barrier(); - cpu_relax(); - } - ql_icmd(cmd); - return 0; -} - -/* - * Return bios parameters - */ - -int qlogicfas408_biosparam(struct scsi_device * disk, - struct block_device *dev, - sector_t capacity, int ip[]) -{ -/* This should mimic the DOS Qlogic driver's behavior exactly */ - ip[0] = 0x40; - ip[1] = 0x20; - ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); - if (ip[2] > 1024) { - ip[0] = 0xff; - ip[1] = 0x3f; - ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); -#if 0 - if (ip[2] > 1023) - ip[2] = 1023; -#endif - } - return 0; -} - -/* - * Abort a command in progress - */ - -int qlogicfas408_abort(Scsi_Cmnd * cmd) -{ - struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); - priv->qabort = 1; - ql_zap(priv); - return SUCCESS; -} - -/* - * Reset SCSI bus - * FIXME: This function is invoked with cmd = NULL directly by - * the PCMCIA qlogic_stub code. This wants fixing - */ - -int qlogicfas408_bus_reset(Scsi_Cmnd * cmd) -{ - struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); - priv->qabort = 2; - ql_zap(priv); - return SUCCESS; -} - -/* - * Reset SCSI host controller - */ - -int qlogicfas408_host_reset(Scsi_Cmnd * cmd) -{ - return FAILED; -} - -/* - * Reset SCSI device - */ - -int qlogicfas408_device_reset(Scsi_Cmnd * cmd) -{ - return FAILED; -} - -/* - * Return info string - */ - -const char *qlogicfas408_info(struct Scsi_Host *host) -{ - struct qlogicfas408_priv *priv = get_priv_by_host(host); - return priv->qinfo; -} - -/* - * Get type of chip - */ - -int qlogicfas408_get_chip_type(int qbase, int int_type) -{ - REG1; - return inb(qbase + 0xe) & 0xf8; -} - -/* - * Perform initialization tasks - */ - -void qlogicfas408_setup(int qbase, int id, int int_type) -{ - outb(1, qbase + 8); /* set for PIO pseudo DMA */ - REG0; - outb(0x40 | qlcfg8 | id, qbase + 8); /* (ini) bus id, disable scsi rst */ - outb(qlcfg5, qbase + 5); /* select timer */ - outb(qlcfg9, qbase + 9); /* prescaler */ - -#if QL_RESET_AT_START - outb(3, qbase + 3); - - REG1; - /* FIXME: timeout */ - while (inb(qbase + 0xf) & 4) - cpu_relax(); - - REG0; -#endif -} - -/* - * Checks if this is a QLogic FAS 408 - */ - -int qlogicfas408_detect(int qbase, int int_type) -{ - REG1; - return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) && - ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7)); -} - -/* - * Disable interrupts - */ - -void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv) -{ - int qbase = priv->qbase; - int int_type = priv->int_type; - - REG1; - outb(0, qbase + 0xb); /* disable ints */ -} - -/* - * Init and exit functions - */ - -static int __init qlogicfas408_init(void) -{ - return 0; -} - -static void __exit qlogicfas408_exit(void) -{ - -} - -MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); -MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); -MODULE_LICENSE("GPL"); -module_init(qlogicfas408_init); -module_exit(qlogicfas408_exit); - -EXPORT_SYMBOL(qlogicfas408_info); -EXPORT_SYMBOL(qlogicfas408_queuecommand); -EXPORT_SYMBOL(qlogicfas408_abort); -EXPORT_SYMBOL(qlogicfas408_bus_reset); -EXPORT_SYMBOL(qlogicfas408_device_reset); -EXPORT_SYMBOL(qlogicfas408_host_reset); -EXPORT_SYMBOL(qlogicfas408_biosparam); -EXPORT_SYMBOL(qlogicfas408_ihandl); -EXPORT_SYMBOL(qlogicfas408_get_chip_type); -EXPORT_SYMBOL(qlogicfas408_setup); -EXPORT_SYMBOL(qlogicfas408_detect); -EXPORT_SYMBOL(qlogicfas408_disable_ints); - diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c deleted file mode 100644 index 75013729e..000000000 --- a/drivers/scsi/sata_sx4.c +++ /dev/null @@ -1,1446 +0,0 @@ -/* - * sata_sx4.c - Promise SATA - * - * Maintained by: Jeff Garzik - * Please ALWAYS copy linux-ide@vger.kernel.org - * on emails. - * - * Copyright 2003-2004 Red Hat, Inc. - * - * The contents of this file are subject to the Open - * Software License version 1.1 that can be found at - * http://www.opensource.org/licenses/osl-1.1.txt and is included herein - * by reference. - * - * Alternatively, the contents of this file may be used under the terms - * of the GNU General Public License version 2 (the "GPL") as distributed - * in the kernel source COPYING file, 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 OSL, 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 OSL or the GPL. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsi.h" -#include -#include -#include -#include "sata_promise.h" - -#define DRV_NAME "sata_sx4" -#define DRV_VERSION "0.50" - - -enum { - PDC_PRD_TBL = 0x44, /* Direct command DMA table addr */ - - PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ - PDC_HDMA_PKT_SUBMIT = 0x100, /* Host DMA packet pointer addr */ - PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ - PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */ - - PDC_20621_SEQCTL = 0x400, - PDC_20621_SEQMASK = 0x480, - PDC_20621_GENERAL_CTL = 0x484, - PDC_20621_PAGE_SIZE = (32 * 1024), - - /* chosen, not constant, values; we design our own DIMM mem map */ - PDC_20621_DIMM_WINDOW = 0x0C, /* page# for 32K DIMM window */ - PDC_20621_DIMM_BASE = 0x00200000, - PDC_20621_DIMM_DATA = (64 * 1024), - PDC_DIMM_DATA_STEP = (256 * 1024), - PDC_DIMM_WINDOW_STEP = (8 * 1024), - PDC_DIMM_HOST_PRD = (6 * 1024), - PDC_DIMM_HOST_PKT = (128 * 0), - PDC_DIMM_HPKT_PRD = (128 * 1), - PDC_DIMM_ATA_PKT = (128 * 2), - PDC_DIMM_APKT_PRD = (128 * 3), - PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128, - PDC_PAGE_WINDOW = 0x40, - PDC_PAGE_DATA = PDC_PAGE_WINDOW + - (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE), - PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE, - - PDC_CHIP0_OFS = 0xC0000, /* offset of chip #0 */ - - PDC_20621_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | - (1<<23), - - board_20621 = 0, /* FastTrak S150 SX4 */ - - PDC_RESET = (1 << 11), /* HDMA reset */ - - PDC_MAX_HDMA = 32, - PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1), - - PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, - PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, - PDC_MAX_DIMM_MODULE = 0x02, - PDC_I2C_CONTROL_OFFSET = 0x48, - PDC_I2C_ADDR_DATA_OFFSET = 0x4C, - PDC_DIMM0_CONTROL_OFFSET = 0x80, - PDC_DIMM1_CONTROL_OFFSET = 0x84, - PDC_SDRAM_CONTROL_OFFSET = 0x88, - PDC_I2C_WRITE = 0x00000000, - PDC_I2C_READ = 0x00000040, - PDC_I2C_START = 0x00000080, - PDC_I2C_MASK_INT = 0x00000020, - PDC_I2C_COMPLETE = 0x00010000, - PDC_I2C_NO_ACK = 0x00100000, - PDC_DIMM_SPD_SUBADDRESS_START = 0x00, - PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, - PDC_DIMM_SPD_ROW_NUM = 3, - PDC_DIMM_SPD_COLUMN_NUM = 4, - PDC_DIMM_SPD_MODULE_ROW = 5, - PDC_DIMM_SPD_TYPE = 11, - PDC_DIMM_SPD_FRESH_RATE = 12, - PDC_DIMM_SPD_BANK_NUM = 17, - PDC_DIMM_SPD_CAS_LATENCY = 18, - PDC_DIMM_SPD_ATTRIBUTE = 21, - PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, - PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, - PDC_DIMM_SPD_RAS_CAS_DELAY = 29, - PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, - PDC_DIMM_SPD_SYSTEM_FREQ = 126, - PDC_CTL_STATUS = 0x08, - PDC_DIMM_WINDOW_CTLR = 0x0C, - PDC_TIME_CONTROL = 0x3C, - PDC_TIME_PERIOD = 0x40, - PDC_TIME_COUNTER = 0x44, - PDC_GENERAL_CTLR = 0x484, - PCI_PLL_INIT = 0x8A531824, - PCI_X_TCOUNT = 0xEE1E5CFF -}; - - -struct pdc_port_priv { - u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; - u8 *pkt; - dma_addr_t pkt_dma; -}; - -struct pdc_host_priv { - void *dimm_mmio; - - unsigned int doing_hdma; - unsigned int hdma_prod; - unsigned int hdma_cons; - struct { - struct ata_queued_cmd *qc; - unsigned int seq; - unsigned long pkt_ofs; - } hdma[32]; -}; - - -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc20621_dma_setup(struct ata_queued_cmd *qc); -static void pdc20621_dma_start(struct ata_queued_cmd *qc); -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static void pdc_eng_timeout(struct ata_port *ap); -static void pdc_20621_phy_reset (struct ata_port *ap); -static int pdc_port_start(struct ata_port *ap); -static void pdc_port_stop(struct ata_port *ap); -static void pdc20621_fill_sg(struct ata_queued_cmd *qc); -static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); -static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); -static void pdc20621_host_stop(struct ata_host_set *host_set); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, int have_err); -static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); -static int pdc20621_detect_dimm(struct ata_probe_ent *pe); -static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, - u32 device, u32 subaddr, u32 *pdata); -static int pdc20621_prog_dimm0(struct ata_probe_ent *pe); -static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe); -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, - void *psource, u32 offset, u32 size); -#endif -static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, - void *psource, u32 offset, u32 size); - - -static Scsi_Host_Template pdc_sata_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, -}; - -static struct ata_port_operations pdc_20621_ops = { - .port_disable = ata_port_disable, - .tf_load = pdc_tf_load_mmio, - .tf_read = ata_tf_read_mmio, - .check_status = ata_check_status_mmio, - .exec_command = pdc_exec_command_mmio, - .phy_reset = pdc_20621_phy_reset, - .bmdma_setup = pdc20621_dma_setup, - .bmdma_start = pdc20621_dma_start, - .fill_sg = pdc20621_fill_sg, - .eng_timeout = pdc_eng_timeout, - .irq_handler = pdc20621_interrupt, - .port_start = pdc_port_start, - .port_stop = pdc_port_stop, - .host_stop = pdc20621_host_stop, -}; - -static struct ata_port_info pdc_port_info[] = { - /* board_20621 */ - { - .sht = &pdc_sata_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_20621_ops, - }, - -}; - -static struct pci_device_id pdc_sata_pci_tbl[] = { - { PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_20621 }, - { } /* terminate list */ -}; - - -static struct pci_driver pdc_sata_pci_driver = { - .name = DRV_NAME, - .id_table = pdc_sata_pci_tbl, - .probe = pdc_sata_init_one, - .remove = ata_pci_remove_one, -}; - - -static void pdc20621_host_stop(struct ata_host_set *host_set) -{ - struct pdc_host_priv *hpriv = host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - iounmap(dimm_mmio); - kfree(hpriv); -} - -static int pdc_port_start(struct ata_port *ap) -{ - struct pci_dev *pdev = ap->host_set->pdev; - struct pdc_port_priv *pp; - int rc; - - rc = ata_port_start(ap); - if (rc) - return rc; - - pp = kmalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) { - rc = -ENOMEM; - goto err_out; - } - memset(pp, 0, sizeof(*pp)); - - pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); - if (!pp->pkt) { - rc = -ENOMEM; - goto err_out_kfree; - } - - ap->private_data = pp; - - return 0; - -err_out_kfree: - kfree(pp); -err_out: - ata_port_stop(ap); - return rc; -} - - -static void pdc_port_stop(struct ata_port *ap) -{ - struct pci_dev *pdev = ap->host_set->pdev; - struct pdc_port_priv *pp = ap->private_data; - - ap->private_data = NULL; - pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); - kfree(pp); - ata_port_stop(ap); -} - - -static void pdc_20621_phy_reset (struct ata_port *ap) -{ - VPRINTK("ENTER\n"); - ap->cbl = ATA_CBL_SATA; - ata_port_probe(ap); - ata_bus_reset(ap); -} - -static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, - unsigned int total_len) -{ - u32 addr; - unsigned int dw = PDC_DIMM_APKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; - - /* output ATA packet S/G table */ - addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + - (PDC_DIMM_DATA_STEP * portno); - VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr); - buf32[dw] = cpu_to_le32(addr); - buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); - - VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n", - PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_APKT_PRD, - buf32[dw], buf32[dw + 1]); -} - -static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, - unsigned int portno, - unsigned int total_len) -{ - u32 addr; - unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; - u32 *buf32 = (u32 *) buf; - - /* output Host DMA packet S/G table */ - addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA + - (PDC_DIMM_DATA_STEP * portno); - - buf32[dw] = cpu_to_le32(addr); - buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT); - - VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n", - PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HPKT_PRD, - buf32[dw], buf32[dw + 1]); -} - -static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, - unsigned int devno, u8 *buf, - unsigned int portno) -{ - unsigned int i, dw; - u32 *buf32 = (u32 *) buf; - u8 dev_reg; - - unsigned int dimm_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_APKT_PRD; - VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); - - i = PDC_DIMM_ATA_PKT; - - /* - * Set up ATA packet - */ - if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) - buf[i++] = PDC_PKT_READ; - else if (tf->protocol == ATA_PROT_NODATA) - buf[i++] = PDC_PKT_NODATA; - else - buf[i++] = 0; - buf[i++] = 0; /* reserved */ - buf[i++] = portno + 1; /* seq. id */ - buf[i++] = 0xff; /* delay seq. id */ - - /* dimm dma S/G, and next-pkt */ - dw = i >> 2; - buf32[dw] = cpu_to_le32(dimm_sg); - buf32[dw + 1] = 0; - i += 8; - - if (devno == 0) - dev_reg = ATA_DEVICE_OBS; - else - dev_reg = ATA_DEVICE_OBS | ATA_DEV1; - - /* select device */ - buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE; - buf[i++] = dev_reg; - - /* device control register */ - buf[i++] = (1 << 5) | PDC_REG_DEVCTL; - buf[i++] = tf->ctl; - - return i; -} - -static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, - unsigned int portno) -{ - unsigned int dw; - u32 tmp, *buf32 = (u32 *) buf; - - unsigned int host_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HOST_PRD; - unsigned int dimm_sg = PDC_20621_DIMM_BASE + - (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HPKT_PRD; - VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg); - VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg); - - dw = PDC_DIMM_HOST_PKT >> 2; - - /* - * Set up Host DMA packet - */ - if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE))) - tmp = PDC_PKT_READ; - else - tmp = 0; - tmp |= ((portno + 1 + 4) << 16); /* seq. id */ - tmp |= (0xff << 24); /* delay seq. id */ - buf32[dw + 0] = cpu_to_le32(tmp); - buf32[dw + 1] = cpu_to_le32(host_sg); - buf32[dw + 2] = cpu_to_le32(dimm_sg); - buf32[dw + 3] = 0; - - VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n", - PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) + - PDC_DIMM_HOST_PKT, - buf32[dw + 0], - buf32[dw + 1], - buf32[dw + 2], - buf32[dw + 3]); -} - -static void pdc20621_fill_sg(struct ata_queued_cmd *qc) -{ - struct scatterlist *sg = qc->sg; - struct ata_port *ap = qc->ap; - struct pdc_port_priv *pp = ap->private_data; - void *mmio = ap->host_set->mmio_base; - struct pdc_host_priv *hpriv = ap->host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - unsigned int portno = ap->port_no; - unsigned int i, last, idx, total_len = 0, sgt_len; - u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; - - VPRINTK("ata%u: ENTER\n", ap->id); - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - * Build S/G table - */ - last = qc->n_elem; - idx = 0; - for (i = 0; i < last; i++) { - buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); - buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); - total_len += sg[i].length; - } - buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); - sgt_len = idx * 4; - - /* - * Build ATA, host DMA packets - */ - pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); - pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno); - - pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); - i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); - - if (qc->tf.flags & ATA_TFLAG_LBA48) - i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); - else - i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); - - pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); - - /* copy three S/G tables and two packets to DIMM MMIO window */ - memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), - &pp->dimm_buf, PDC_DIMM_HEADER_SZ); - memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) + - PDC_DIMM_HOST_PRD, - &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len); - - /* force host FIFO dump */ - writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); - - readl(dimm_mmio); /* MMIO PCI posting flush */ - - VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); -} - -static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, - unsigned int seq, - u32 pkt_ofs) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - void *mmio = host_set->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ - - writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT); - readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */ -} - -static void pdc20621_push_hdma(struct ata_queued_cmd *qc, - unsigned int seq, - u32 pkt_ofs) -{ - struct ata_port *ap = qc->ap; - struct pdc_host_priv *pp = ap->host_set->private_data; - unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK; - - if (!pp->doing_hdma) { - __pdc20621_push_hdma(qc, seq, pkt_ofs); - pp->doing_hdma = 1; - return; - } - - pp->hdma[idx].qc = qc; - pp->hdma[idx].seq = seq; - pp->hdma[idx].pkt_ofs = pkt_ofs; - pp->hdma_prod++; -} - -static void pdc20621_pop_hdma(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct pdc_host_priv *pp = ap->host_set->private_data; - unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK; - - /* if nothing on queue, we're done */ - if (pp->hdma_prod == pp->hdma_cons) { - pp->doing_hdma = 0; - return; - } - - __pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq, - pp->hdma[idx].pkt_ofs); - pp->hdma_cons++; -} - -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int port_no = ap->port_no; - struct pdc_host_priv *hpriv = ap->host_set->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP); - dimm_mmio += PDC_DIMM_HOST_PKT; - - printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio)); - printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4)); - printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8)); - printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12)); -} -#else -static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } -#endif /* ATA_VERBOSE_DEBUG */ - -static void pdc20621_dma_setup(struct ata_queued_cmd *qc) -{ - /* nothing for now. later, we will call standard - * code in libata-core for ATAPI here */ -} - -static void pdc20621_dma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - unsigned int port_no = ap->port_no; - void *mmio = host_set->mmio_base; - unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 seq = (u8) (port_no + 1); - unsigned int doing_hdma = 0, port_ofs; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - VPRINTK("ata%u: ENTER\n", ap->id); - - port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); - - /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ - if (rw) { - doing_hdma = 1; - seq += 4; - } - - wmb(); /* flush PRD, pkt writes */ - - if (doing_hdma) { - pdc20621_dump_hdma(qc); - pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); - VPRINTK("queued ofs 0x%x (%u), seq %u\n", - port_ofs + PDC_DIMM_HOST_PKT, - port_ofs + PDC_DIMM_HOST_PKT, - seq); - } else { - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */ - - writel(port_ofs + PDC_DIMM_ATA_PKT, - (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - VPRINTK("submitted ofs 0x%x (%u), seq %u\n", - port_ofs + PDC_DIMM_ATA_PKT, - port_ofs + PDC_DIMM_ATA_PKT, - seq); - } -} - -static inline unsigned int pdc20621_host_intr( struct ata_port *ap, - struct ata_queued_cmd *qc, - unsigned int doing_hdma, - void *mmio) -{ - unsigned int port_no = ap->port_no; - unsigned int port_ofs = - PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); - u8 status; - unsigned int handled = 0; - - VPRINTK("ENTER\n"); - - if ((qc->tf.protocol == ATA_PROT_DMA) && /* read */ - (!(qc->tf.flags & ATA_TFLAG_WRITE))) { - - /* step two - DMA from DIMM to host */ - if (doing_hdma) { - VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); - pdc20621_pop_hdma(qc); - } - - /* step one - exec ATA command */ - else { - u8 seq = (u8) (port_no + 1 + 4); - VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - - /* submit hdma pkt */ - pdc20621_dump_hdma(qc); - pdc20621_push_hdma(qc, seq, - port_ofs + PDC_DIMM_HOST_PKT); - } - handled = 1; - - } else if (qc->tf.protocol == ATA_PROT_DMA) { /* write */ - - /* step one - DMA from host to DIMM */ - if (doing_hdma) { - u8 seq = (u8) (port_no + 1); - VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - - /* submit ata pkt */ - writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); - readl(mmio + PDC_20621_SEQCTL + (seq * 4)); - writel(port_ofs + PDC_DIMM_ATA_PKT, - (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); - } - - /* step two - execute ATA command */ - else { - VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, - readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); - pdc20621_pop_hdma(qc); - } - handled = 1; - - /* command completion, but no data xfer */ - } else if (qc->tf.protocol == ATA_PROT_NODATA) { - - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); - ata_qc_complete(qc, status); - handled = 1; - - } else { - ap->stats.idle_irq++; - } - - return handled; -} - -static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs) -{ - struct ata_host_set *host_set = dev_instance; - struct ata_port *ap; - u32 mask = 0; - unsigned int i, tmp, port_no; - unsigned int handled = 0; - void *mmio_base; - - VPRINTK("ENTER\n"); - - if (!host_set || !host_set->mmio_base) { - VPRINTK("QUICK EXIT\n"); - return IRQ_NONE; - } - - mmio_base = host_set->mmio_base; - - /* reading should also clear interrupts */ - mmio_base += PDC_CHIP0_OFS; - mask = readl(mmio_base + PDC_20621_SEQMASK); - VPRINTK("mask == 0x%x\n", mask); - - if (mask == 0xffffffff) { - VPRINTK("QUICK EXIT 2\n"); - return IRQ_NONE; - } - mask &= 0xffff; /* only 16 tags possible */ - if (!mask) { - VPRINTK("QUICK EXIT 3\n"); - return IRQ_NONE; - } - - spin_lock(&host_set->lock); - - for (i = 1; i < 9; i++) { - port_no = i - 1; - if (port_no > 3) - port_no -= 4; - if (port_no >= host_set->n_ports) - ap = NULL; - else - ap = host_set->ports[port_no]; - tmp = mask & (1 << i); - VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); - if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) - handled += pdc20621_host_intr(ap, qc, (i > 4), - mmio_base); - } - } - - spin_unlock(&host_set->lock); - - VPRINTK("mask == 0x%x\n", mask); - - VPRINTK("EXIT\n"); - - return IRQ_RETVAL(handled); -} - -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, - int have_err) -{ - u8 err_bit = have_err ? ATA_ERR : 0; - - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap) | err_bit); -} - -static void pdc_eng_timeout(struct ata_port *ap) -{ - u8 drv_stat; - struct ata_queued_cmd *qc; - - DPRINTK("ENTER\n"); - - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } - - /* hack alert! We cannot use the supplied completion - * function from inside the ->eh_strategy_handler() thread. - * libata is the only user of ->eh_strategy_handler() in - * any kernel, so the default scsi_done() assumes it is - * not being called from the SCSI EH. - */ - qc->scsidone = scsi_finish_command; - - switch (qc->tf.protocol) { - case ATA_PROT_DMA: - printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); - break; - - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); - break; - - default: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); - break; - } - -out: - DPRINTK("EXIT\n"); -} - -static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) -{ - if (tf->protocol == ATA_PROT_PIO) - ata_tf_load_mmio(ap, tf); -} - - -static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) -{ - if (tf->protocol == ATA_PROT_PIO) - ata_exec_command_mmio(ap, tf); -} - - -static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) -{ - port->cmd_addr = base; - port->data_addr = base; - port->feature_addr = - port->error_addr = base + 0x4; - port->nsect_addr = base + 0x8; - port->lbal_addr = base + 0xc; - port->lbam_addr = base + 0x10; - port->lbah_addr = base + 0x14; - port->device_addr = base + 0x18; - port->command_addr = - port->status_addr = base + 0x1c; - port->altstatus_addr = - port->ctl_addr = base + 0x38; -} - - -#ifdef ATA_VERBOSE_DEBUG -static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, - u32 offset, u32 size) -{ - u32 window_size; - u16 idx; - u8 page_mask; - long dist; - void *mmio = pe->mmio_base; - struct pdc_host_priv *hpriv = pe->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ - idx = (u16) (offset / window_size); - - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - - offset -= (idx * window_size); - idx++; - dist = ((long) (window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); - memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), - dist); - - psource += dist; - size -= dist; - for (; (long) size >= (long) window_size ;) { - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_fromio((char *) psource, (char *) (dimm_mmio), - window_size / 4); - psource += window_size; - size -= window_size; - idx ++; - } - - if (size) { - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_fromio((char *) psource, (char *) (dimm_mmio), - size / 4); - } -} -#endif - - -static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, - u32 offset, u32 size) -{ - u32 window_size; - u16 idx; - u8 page_mask; - long dist; - void *mmio = pe->mmio_base; - struct pdc_host_priv *hpriv = pe->private_data; - void *dimm_mmio = hpriv->dimm_mmio; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - page_mask = 0x00; - window_size = 0x2000 * 4; /* 32K byte uchar size */ - idx = (u16) (offset / window_size); - - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - offset -= (idx * window_size); - idx++; - dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); - memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - - psource += dist; - size -= dist; - for (; (long) size >= (long) window_size ;) { - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_toio((char *) (dimm_mmio), (char *) psource, - window_size / 4); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - psource += window_size; - size -= window_size; - idx ++; - } - - if (size) { - writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR); - readl(mmio + PDC_DIMM_WINDOW_CTLR); - memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4); - writel(0x01, mmio + PDC_GENERAL_CTLR); - readl(mmio + PDC_GENERAL_CTLR); - } -} - - -static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, - u32 subaddr, u32 *pdata) -{ - void *mmio = pe->mmio_base; - u32 i2creg = 0; - u32 status; - u32 count =0; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - i2creg |= device << 24; - i2creg |= subaddr << 16; - - /* Set the device and subaddress */ - writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET); - readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); - - /* Write Control to perform read operation, mask int */ - writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, - mmio + PDC_I2C_CONTROL_OFFSET); - - for (count = 0; count <= 1000; count ++) { - status = readl(mmio + PDC_I2C_CONTROL_OFFSET); - if (status & PDC_I2C_COMPLETE) { - status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); - break; - } else if (count == 1000) - return 0; - } - - *pdata = (status >> 8) & 0x000000ff; - return 1; -} - - -static int pdc20621_detect_dimm(struct ata_probe_ent *pe) -{ - u32 data=0 ; - if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_SYSTEM_FREQ, &data)) { - if (data == 100) - return 100; - } else - return 0; - - if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) { - if(data <= 0x75) - return 133; - } else - return 0; - - return 0; -} - - -static int pdc20621_prog_dimm0(struct ata_probe_ent *pe) -{ - u32 spd0[50]; - u32 data = 0; - int size, i; - u8 bdimmsize; - void *mmio = pe->mmio_base; - static const struct { - unsigned int reg; - unsigned int ofs; - } pdc_i2c_read_data [] = { - { PDC_DIMM_SPD_TYPE, 11 }, - { PDC_DIMM_SPD_FRESH_RATE, 12 }, - { PDC_DIMM_SPD_COLUMN_NUM, 4 }, - { PDC_DIMM_SPD_ATTRIBUTE, 21 }, - { PDC_DIMM_SPD_ROW_NUM, 3 }, - { PDC_DIMM_SPD_BANK_NUM, 17 }, - { PDC_DIMM_SPD_MODULE_ROW, 5 }, - { PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 }, - { PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 }, - { PDC_DIMM_SPD_RAS_CAS_DELAY, 29 }, - { PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 }, - { PDC_DIMM_SPD_CAS_LATENCY, 18 }, - }; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - for(i=0; i spd0[28]) - ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; - data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12; - - if (spd0[18] & 0x08) - data |= ((0x03) << 14); - else if (spd0[18] & 0x04) - data |= ((0x02) << 14); - else if (spd0[18] & 0x01) - data |= ((0x01) << 14); - else - data |= (0 << 14); - - /* - Calculate the size of bDIMMSize (power of 2) and - merge the DIMM size by program start/end address. - */ - - bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3; - size = (1 << bdimmsize) >> 20; /* size = xxx(MB) */ - data |= (((size / 16) - 1) << 16); - data |= (0 << 23); - data |= 8; - writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); - readl(mmio + PDC_DIMM0_CONTROL_OFFSET); - return size; -} - - -static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) -{ - u32 data, spd0; - int error, i; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - Set To Default : DIMM Module Global Control Register (0x022259F1) - DIMM Arbitration Disable (bit 20) - DIMM Data/Control Output Driving Selection (bit12 - bit15) - Refresh Enable (bit 17) - */ - - data = 0x022259F1; - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - - /* Turn on for ECC */ - pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_TYPE, &spd0); - if (spd0 == 0x02) { - data |= (0x01 << 16); - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - printk(KERN_ERR "Local DIMM ECC Enabled\n"); - } - - /* DIMM Initialization Select/Enable (bit 18/19) */ - data &= (~(1<<18)); - data |= (1<<19); - writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); - - error = 1; - for (i = 1; i <= 10; i++) { /* polling ~5 secs */ - data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); - if (!(data & (1<<19))) { - error = 0; - break; - } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((i * 100) * HZ / 1000 + 1); - } - return error; -} - - -static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) -{ - int speed, size, length; - u32 addr,spd0,pci_status; - u32 tmp=0; - u32 time_period=0; - u32 tcount=0; - u32 ticks=0; - u32 clock=0; - u32 fparam=0; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* Initialize PLL based upon PCI Bus Frequency */ - - /* Initialize Time Period Register */ - writel(0xffffffff, mmio + PDC_TIME_PERIOD); - time_period = readl(mmio + PDC_TIME_PERIOD); - VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); - - /* Enable timer */ - writel(0x00001a0, mmio + PDC_TIME_CONTROL); - readl(mmio + PDC_TIME_CONTROL); - - /* Wait 3 seconds */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3 * HZ); - - /* - When timer is enabled, counter is decreased every internal - clock cycle. - */ - - tcount = readl(mmio + PDC_TIME_COUNTER); - VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); - - /* - If SX4 is on PCI-X bus, after 3 seconds, the timer counter - register should be >= (0xffffffff - 3x10^8). - */ - if(tcount >= PCI_X_TCOUNT) { - ticks = (time_period - tcount); - VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); - - clock = (ticks / 300000); - VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); - - clock = (clock * 33); - VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); - - /* PLL F Param (bit 22:16) */ - fparam = (1400000 / clock) - 2; - VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); - - /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ - pci_status = (0x8a001824 | (fparam << 16)); - } else - pci_status = PCI_PLL_INIT; - - /* Initialize PLL. */ - VPRINTK("pci_status: 0x%x\n", pci_status); - writel(pci_status, mmio + PDC_CTL_STATUS); - readl(mmio + PDC_CTL_STATUS); - - /* - Read SPD of DIMM by I2C interface, - and program the DIMM Module Controller. - */ - if (!(speed = pdc20621_detect_dimm(pe))) { - printk(KERN_ERR "Detect Local DIMM Fail\n"); - return 1; /* DIMM error */ - } - VPRINTK("Local DIMM Speed = %d\n", speed); - - /* Programming DIMM0 Module Control Register (index_CID0:80h) */ - size = pdc20621_prog_dimm0(pe); - VPRINTK("Local DIMM Size = %dMB\n",size); - - /* Programming DIMM Module Global Control Register (index_CID0:88h) */ - if (pdc20621_prog_dimm_global(pe)) { - printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n"); - return 1; - } - -#ifdef ATA_VERBOSE_DEBUG - { - u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ', - 'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ', - '1','.','1','0', - '9','8','0','3','1','6','1','2',0,0}; - u8 test_parttern2[40] = {0}; - - pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40); - pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40); - - pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, - 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - - pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40); - pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40); - printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], - test_parttern2[1], &(test_parttern2[2])); - } -#endif - - /* ECC initiliazation. */ - - pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, - PDC_DIMM_SPD_TYPE, &spd0); - if (spd0 == 0x02) { - VPRINTK("Start ECC initialization\n"); - addr = 0; - length = size * 1024 * 1024; - while (addr < length) { - pdc20621_put_to_dimm(pe, (void *) &tmp, addr, - sizeof(u32)); - addr += sizeof(u32); - } - VPRINTK("Finish ECC initialization\n"); - } - return 0; -} - - -static void pdc_20621_init(struct ata_probe_ent *pe) -{ - u32 tmp; - void *mmio = pe->mmio_base; - - /* hard-code chip #0 */ - mmio += PDC_CHIP0_OFS; - - /* - * Select page 0x40 for our 32k DIMM window - */ - tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000; - tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */ - writel(tmp, mmio + PDC_20621_DIMM_WINDOW); - - /* - * Reset Host DMA - */ - tmp = readl(mmio + PDC_HDMA_CTLSTAT); - tmp |= PDC_RESET; - writel(tmp, mmio + PDC_HDMA_CTLSTAT); - readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ - - udelay(10); - - tmp = readl(mmio + PDC_HDMA_CTLSTAT); - tmp &= ~PDC_RESET; - writel(tmp, mmio + PDC_HDMA_CTLSTAT); - readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ -} - -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int printed_version; - struct ata_probe_ent *probe_ent = NULL; - unsigned long base; - void *mmio_base, *dimm_mmio = NULL; - struct pdc_host_priv *hpriv = NULL; - unsigned int board_idx = (unsigned int) ent->driver_data; - int rc; - - if (!printed_version++) - printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); - - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ - rc = pci_enable_device(pdev); - if (rc) - return rc; - - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) - goto err_out; - - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); - if (probe_ent == NULL) { - rc = -ENOMEM; - goto err_out_regions; - } - - memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; - INIT_LIST_HEAD(&probe_ent->node); - - mmio_base = ioremap(pci_resource_start(pdev, 3), - pci_resource_len(pdev, 3)); - if (mmio_base == NULL) { - rc = -ENOMEM; - goto err_out_free_ent; - } - base = (unsigned long) mmio_base; - - hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); - if (!hpriv) { - rc = -ENOMEM; - goto err_out_iounmap; - } - memset(hpriv, 0, sizeof(*hpriv)); - - dimm_mmio = ioremap(pci_resource_start(pdev, 4), - pci_resource_len(pdev, 4)); - if (!dimm_mmio) { - kfree(hpriv); - rc = -ENOMEM; - goto err_out_iounmap; - } - - hpriv->dimm_mmio = dimm_mmio; - - probe_ent->sht = pdc_port_info[board_idx].sht; - probe_ent->host_flags = pdc_port_info[board_idx].host_flags; - probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; - probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; - probe_ent->port_ops = pdc_port_info[board_idx].port_ops; - - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - probe_ent->mmio_base = mmio_base; - - probe_ent->private_data = hpriv; - base += PDC_CHIP0_OFS; - - pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); - pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); - - /* notice 4-port boards */ - switch (board_idx) { - case board_20621: - probe_ent->n_ports = 4; - - pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); - pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); - break; - default: - BUG(); - break; - } - - pci_set_master(pdev); - - /* initialize adapter */ - /* initialize local dimm */ - if (pdc20621_dimm_init(probe_ent)) { - rc = -ENOMEM; - goto err_out_iounmap_dimm; - } - pdc_20621_init(probe_ent); - - /* FIXME: check ata_device_add return value */ - ata_device_add(probe_ent); - kfree(probe_ent); - - return 0; - -err_out_iounmap_dimm: /* only get to this label if 20621 */ - kfree(hpriv); - iounmap(dimm_mmio); -err_out_iounmap: - iounmap(mmio_base); -err_out_free_ent: - kfree(probe_ent); -err_out_regions: - pci_release_regions(pdev); -err_out: - pci_disable_device(pdev); - return rc; -} - - -static int __init pdc_sata_init(void) -{ - return pci_module_init(&pdc_sata_pci_driver); -} - - -static void __exit pdc_sata_exit(void) -{ - pci_unregister_driver(&pdc_sata_pci_driver); -} - - -MODULE_AUTHOR("Jeff Garzik"); -MODULE_DESCRIPTION("Promise SATA low-level driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); - -module_init(pdc_sata_init); -module_exit(pdc_sata_exit); diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c deleted file mode 100644 index 0c86ff989..000000000 --- a/drivers/video/pxafb.c +++ /dev/null @@ -1,1381 +0,0 @@ -/* - * linux/drivers/video/pxafb.c - * - * Copyright (C) 1999 Eric A. Thomas. - * Copyright (C) 2004 Jean-Frederic Clere. - * Copyright (C) 2004 Ian Campbell. - * Copyright (C) 2004 Jeff Lackey. - * Based on sa1100fb.c Copyright (C) 1999 Eric A. Thomas - * which in turn is - * Based on acornfb.c Copyright (C) Russell King. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * Intel PXA250/210 LCD Controller Frame Buffer Driver - * - * Please direct your questions and comments on this driver to the following - * email address: - * - * linux-arm-kernel@lists.arm.linux.org.uk - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * Complain if VAR is out of range. - */ -#define DEBUG_VAR 1 - -#include "pxafb.h" - -/* Bits which should not be set in machine configuration structures */ -#define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM|LCCR0_BM|LCCR0_QDM|LCCR0_DIS|LCCR0_EFM|LCCR0_IUM|LCCR0_SFM|LCCR0_LDM|LCCR0_ENB) -#define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP) - -static void (*pxafb_backlight_power)(int); -static void (*pxafb_lcd_power)(int); - -static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *); -static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); - -#ifdef CONFIG_FB_PXA_PARAMETERS -#define PXAFB_OPTIONS_SIZE 256 -static char g_options[PXAFB_OPTIONS_SIZE] __initdata = ""; -#endif - -static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state) -{ - unsigned long flags; - - local_irq_save(flags); - /* - * We need to handle two requests being made at the same time. - * There are two important cases: - * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) - * We must perform the unblanking, which will do our REENABLE for us. - * 2. When we are blanking, but immediately unblank before we have - * blanked. We do the "REENABLE" thing here as well, just to be sure. - */ - if (fbi->task_state == C_ENABLE && state == C_REENABLE) - state = (u_int) -1; - if (fbi->task_state == C_DISABLE && state == C_ENABLE) - state = C_REENABLE; - - if (state != (u_int)-1) { - fbi->task_state = state; - schedule_work(&fbi->task); - } - local_irq_restore(flags); -} - -static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) -{ - chan &= 0xffff; - chan >>= 16 - bf->length; - return chan << bf->offset; -} - -static int -pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, - u_int trans, struct fb_info *info) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - u_int val, ret = 1; - - if (regno < fbi->palette_size) { - val = ((red >> 0) & 0xf800); - val |= ((green >> 5) & 0x07e0); - val |= ((blue >> 11) & 0x001f); - - fbi->palette_cpu[regno] = val; - ret = 0; - } - return ret; -} - -static int -pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int trans, struct fb_info *info) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - unsigned int val; - int ret = 1; - - /* - * If inverse mode was selected, invert all the colours - * rather than the register number. The register number - * is what you poke into the framebuffer to produce the - * colour you requested. - */ - if (fbi->cmap_inverse) { - red = 0xffff - red; - green = 0xffff - green; - blue = 0xffff - blue; - } - - /* - * If greyscale is true, then we convert the RGB value - * to greyscale no matter what visual we are using. - */ - if (fbi->fb.var.grayscale) - red = green = blue = (19595 * red + 38470 * green + - 7471 * blue) >> 16; - - switch (fbi->fb.fix.visual) { - case FB_VISUAL_TRUECOLOR: - /* - * 12 or 16-bit True Colour. We encode the RGB value - * according to the RGB bitfield information. - */ - if (regno < 16) { - u32 *pal = fbi->fb.pseudo_palette; - - val = chan_to_field(red, &fbi->fb.var.red); - val |= chan_to_field(green, &fbi->fb.var.green); - val |= chan_to_field(blue, &fbi->fb.var.blue); - - pal[regno] = val; - ret = 0; - } - break; - - case FB_VISUAL_STATIC_PSEUDOCOLOR: - case FB_VISUAL_PSEUDOCOLOR: - ret = pxafb_setpalettereg(regno, red, green, blue, trans, info); - break; - } - - return ret; -} - -/* - * pxafb_bpp_to_lccr3(): - * Convert a bits per pixel value to the correct bit pattern for LCCR3 - */ -static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var) -{ - int ret = 0; - switch (var->bits_per_pixel) { - case 1: ret = LCCR3_1BPP; break; - case 2: ret = LCCR3_2BPP; break; - case 4: ret = LCCR3_4BPP; break; - case 8: ret = LCCR3_8BPP; break; - case 16: ret = LCCR3_16BPP; break; - } - return ret; -} - -#ifdef CONFIG_CPU_FREQ -/* - * pxafb_display_dma_period() - * Calculate the minimum period (in picoseconds) between two DMA - * requests for the LCD controller. If we hit this, it means we're - * doing nothing but LCD DMA. - */ -static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var) -{ - /* - * Period = pixclock * bits_per_byte * bytes_per_transfer - * / memory_bits_per_pixel; - */ - return var->pixclock * 8 * 16 / var->bits_per_pixel; -} - -extern unsigned int get_clk_frequency_khz(int info); -#endif - -/* - * pxafb_check_var(): - * Get the video params out of 'var'. If a value doesn't fit, round it up, - * if it's too big, return -EINVAL. - * - * Round up in the following order: bits_per_pixel, xres, - * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, - * bitfields, horizontal timing, vertical timing. - */ -static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - - if (var->xres < MIN_XRES) - var->xres = MIN_XRES; - if (var->yres < MIN_YRES) - var->yres = MIN_YRES; - if (var->xres > fbi->max_xres) - var->xres = fbi->max_xres; - if (var->yres > fbi->max_yres) - var->yres = fbi->max_yres; - var->xres_virtual = - max(var->xres_virtual, var->xres); - var->yres_virtual = - max(var->yres_virtual, var->yres); - - /* - * Setup the RGB parameters for this display. - * - * The pixel packing format is described on page 7-11 of the - * PXA2XX Developer's Manual. - */ - if ( var->bits_per_pixel == 16 ) { - var->red.offset = 11; var->red.length = 5; - var->green.offset = 5; var->green.length = 6; - var->blue.offset = 0; var->blue.length = 5; - var->transp.offset = var->transp.length = 0; - } else { - var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - var->transp.length = 0; - } - -#ifdef CONFIG_CPU_FREQ - DPRINTK("dma period = %d ps, clock = %d kHz\n", - pxafb_display_dma_period(var), - get_clk_frequency_khz(0)); -#endif - - return 0; -} - -static inline void pxafb_set_truecolor(u_int is_true_color) -{ - DPRINTK("true_color = %d\n", is_true_color); - // do your machine-specific setup if needed -} - -/* - * pxafb_set_par(): - * Set the user defined part of the display for the specified console - */ -static int pxafb_set_par(struct fb_info *info) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - struct fb_var_screeninfo *var = &info->var; - unsigned long palette_mem_size; - - DPRINTK("set_par\n"); - - if (var->bits_per_pixel == 16) - fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; - else if (!fbi->cmap_static) - fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; - else { - /* - * Some people have weird ideas about wanting static - * pseudocolor maps. I suspect their user space - * applications are broken. - */ - fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; - } - - fbi->fb.fix.line_length = var->xres_virtual * - var->bits_per_pixel / 8; - fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; - - palette_mem_size = fbi->palette_size * sizeof(u16); - - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); - - fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); - fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; - - /* - * Set (any) board control register to handle new color depth - */ - pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); - - pxafb_activate_var(var, fbi); - - return 0; -} - -/* - * Formal definition of the VESA spec: - * On - * This refers to the state of the display when it is in full operation - * Stand-By - * This defines an optional operating state of minimal power reduction with - * the shortest recovery time - * Suspend - * This refers to a level of power management in which substantial power - * reduction is achieved by the display. The display can have a longer - * recovery time from this state than from the Stand-by state - * Off - * This indicates that the display is consuming the lowest level of power - * and is non-operational. Recovery from this state may optionally require - * the user to manually power on the monitor - * - * Now, the fbdev driver adds an additional state, (blank), where they - * turn off the video (maybe by colormap tricks), but don't mess with the - * video itself: think of it semantically between on and Stand-By. - * - * So here's what we should do in our fbdev blank routine: - * - * VESA_NO_BLANKING (mode 0) Video on, front/back light on - * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off - * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off - * VESA_POWERDOWN (mode 3) Video off, front/back light off - * - * This will match the matrox implementation. - */ - -/* - * pxafb_blank(): - * Blank the display by setting all palette values to zero. Note, the - * 12 and 16 bpp modes don't really use the palette, so this will not - * blank the display in all modes. - */ -static int pxafb_blank(int blank, struct fb_info *info) -{ - struct pxafb_info *fbi = (struct pxafb_info *)info; - int i; - - DPRINTK("pxafb_blank: blank=%d\n", blank); - - switch (blank) { - case VESA_POWERDOWN: - case VESA_VSYNC_SUSPEND: - case VESA_HSYNC_SUSPEND: - if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || - fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) - for (i = 0; i < fbi->palette_size; i++) - pxafb_setpalettereg(i, 0, 0, 0, 0, info); - - pxafb_schedule_work(fbi, C_DISABLE); - //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); - break; - - case VESA_NO_BLANKING: - //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); - if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || - fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) - fb_set_cmap(&fbi->fb.cmap, 1, info); - pxafb_schedule_work(fbi, C_ENABLE); - } - return 0; -} - -static struct fb_ops pxafb_ops = { - .owner = THIS_MODULE, - .fb_check_var = pxafb_check_var, - .fb_set_par = pxafb_set_par, - .fb_setcolreg = pxafb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_blank = pxafb_blank, - .fb_cursor = soft_cursor, -}; - -/* - * Calculate the PCD value from the clock rate (in picoseconds). - * We take account of the PPCR clock setting. - * From PXA Developer's Manual: - * - * PixelClock = LCLK - * ------------- - * 2 ( PCD + 1 ) - * - * PCD = LCLK - * ------------- - 1 - * 2(PixelClock) - * - * Where: - * LCLK = LCD/Memory Clock - * PCD = LCCR3[7:0] - * - * PixelClock here is in Hz while the pixclock argument given is the - * period in picoseconds. Hence PixelClock = 1 / ( pixclock * 10^-12 ) - * - * The function get_lclk_frequency_10khz returns LCLK in units of - * 10khz. Calling the result of this function lclk gives us the - * following - * - * PCD = (lclk * 10^4 ) * ( pixclock * 10^-12 ) - * -------------------------------------- - 1 - * 2 - * - * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below. - */ -static inline unsigned int get_pcd(unsigned int pixclock) -{ - unsigned long long pcd; - - /* FIXME: Need to take into account Double Pixel Clock mode - * (DPC) bit? or perhaps set it based on the various clock - * speeds */ - - pcd = (unsigned long long)get_lclk_frequency_10khz() * (unsigned long long)pixclock; - pcd /= 100000000 * 2; - /* no need for this, since we should subtract 1 anyway. they cancel */ - /* pcd += 1; */ /* make up for integer math truncations */ - return (unsigned int)pcd; -} - -/* - * pxafb_activate_var(): - * Configures LCD Controller based on entries in var parameter. Settings are - * only written to the controller if changes were made. - */ -static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi) -{ - struct pxafb_lcd_reg new_regs; - u_long flags; - u_int lines_per_panel, pcd = get_pcd(var->pixclock); - - DPRINTK("Configuring PXA LCD\n"); - - DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", - var->xres, var->hsync_len, - var->left_margin, var->right_margin); - DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", - var->yres, var->vsync_len, - var->upper_margin, var->lower_margin); - DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd); - -#if DEBUG_VAR - if (var->xres < 16 || var->xres > 1024) - printk(KERN_ERR "%s: invalid xres %d\n", - fbi->fb.fix.id, var->xres); - switch(var->bits_per_pixel) { - case 1: - case 2: - case 4: - case 8: - case 16: - break; - default: - printk(KERN_ERR "%s: invalid bit depth %d\n", - fbi->fb.fix.id, var->bits_per_pixel); - break; - } - if (var->hsync_len < 1 || var->hsync_len > 64) - printk(KERN_ERR "%s: invalid hsync_len %d\n", - fbi->fb.fix.id, var->hsync_len); - if (var->left_margin < 1 || var->left_margin > 255) - printk(KERN_ERR "%s: invalid left_margin %d\n", - fbi->fb.fix.id, var->left_margin); - if (var->right_margin < 1 || var->right_margin > 255) - printk(KERN_ERR "%s: invalid right_margin %d\n", - fbi->fb.fix.id, var->right_margin); - if (var->yres < 1 || var->yres > 1024) - printk(KERN_ERR "%s: invalid yres %d\n", - fbi->fb.fix.id, var->yres); - if (var->vsync_len < 1 || var->vsync_len > 64) - printk(KERN_ERR "%s: invalid vsync_len %d\n", - fbi->fb.fix.id, var->vsync_len); - if (var->upper_margin < 0 || var->upper_margin > 255) - printk(KERN_ERR "%s: invalid upper_margin %d\n", - fbi->fb.fix.id, var->upper_margin); - if (var->lower_margin < 0 || var->lower_margin > 255) - printk(KERN_ERR "%s: invalid lower_margin %d\n", - fbi->fb.fix.id, var->lower_margin); -#endif - - new_regs.lccr0 = fbi->lccr0 | - (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | - LCCR0_QDM | LCCR0_BM | LCCR0_OUM); - - new_regs.lccr1 = - LCCR1_DisWdth(var->xres) + - LCCR1_HorSnchWdth(var->hsync_len) + - LCCR1_BegLnDel(var->left_margin) + - LCCR1_EndLnDel(var->right_margin); - - /* - * If we have a dual scan LCD, we need to halve - * the YRES parameter. - */ - lines_per_panel = var->yres; - if (fbi->lccr0 & LCCR0_SDS) - lines_per_panel /= 2; - - new_regs.lccr2 = - LCCR2_DisHght(lines_per_panel) + - LCCR2_VrtSnchWdth(var->vsync_len) + - LCCR2_BegFrmDel(var->upper_margin) + - LCCR2_EndFrmDel(var->lower_margin); - - new_regs.lccr3 = fbi->lccr3 | - pxafb_bpp_to_lccr3(var) | - (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | - (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); - - if (pcd) - new_regs.lccr3 |= LCCR3_PixClkDiv(pcd); - - DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0); - DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1); - DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2); - DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3); - - /* Update shadow copy atomically */ - local_irq_save(flags); - - /* setup dma descriptors */ - fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16); - fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16); - fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16); - - fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16; - fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16; - fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16; - -#define BYTES_PER_PANEL (lines_per_panel * fbi->fb.fix.line_length) - - /* populate descriptors */ - fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma; - fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL; - fbi->dmadesc_fblow_cpu->fidr = 0; - fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL; - - fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */ - - fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma; - fbi->dmadesc_fbhigh_cpu->fidr = 0; - fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL; - - fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma; - fbi->dmadesc_palette_cpu->fidr = 0; - fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL; - - if( var->bits_per_pixel < 12) - { - /* assume any mode with <12 bpp is palette driven */ - fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma; - fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma; - fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */ - } - else - { - /* palette shouldn't be loaded in true-color mode */ - fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma; - fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */ - /* init it to something, even though we won't be using it */ - fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_palette_dma; - } - -#if 0 - DPRINTK("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu); - DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu); - DPRINTK("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu); - DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma); - DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma); - DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma); - - DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr); - DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr); - DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd); - DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd); - DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd); -#endif - - fbi->reg_lccr0 = new_regs.lccr0; - fbi->reg_lccr1 = new_regs.lccr1; - fbi->reg_lccr2 = new_regs.lccr2; - fbi->reg_lccr3 = new_regs.lccr3; - local_irq_restore(flags); - - /* - * Only update the registers if the controller is enabled - * and something has changed. - */ - if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) || - (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) || - (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1)) - pxafb_schedule_work(fbi, C_REENABLE); - - return 0; -} - -/* - * NOTE! The following functions are purely helpers for set_ctrlr_state. - * Do not call them directly; set_ctrlr_state does the correct serialisation - * to ensure that things happen in the right way 100% of time time. - * -- rmk - */ -static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) -{ - DPRINTK("backlight o%s\n", on ? "n" : "ff"); - - if (pxafb_backlight_power) - pxafb_backlight_power(on); -} - -static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on) -{ - DPRINTK("LCD power o%s\n", on ? "n" : "ff"); - - if (pxafb_lcd_power) - pxafb_lcd_power(on); -} - -static void pxafb_setup_gpio(struct pxafb_info *fbi) -{ - unsigned int lccr0 = fbi->lccr0; - - /* - * setup is based on type of panel supported - */ - - /* 4 bit interface */ - if ((lccr0 & LCCR0_CMS) == LCCR0_Mono && - (lccr0 & LCCR0_SDS) == LCCR0_Sngl && - (lccr0 & LCCR0_DPD) == LCCR0_4PixMono) - { - // bits 58-61 - GPDR1 |= (0xf << 26); - GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20); - - // bits 74-77 - GPDR2 |= (0xf << 10); - GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20); - } - - /* 8 bit interface */ - else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono && - ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) || - ((lccr0 & LCCR0_CMS) == LCCR0_Color && - (lccr0 & LCCR0_PAS) == LCCR0_Pas && (lccr0 & LCCR0_SDS) == LCCR0_Sngl)) - { - // bits 58-65 - GPDR1 |= (0x3f << 26); - GPDR2 |= (0x3); - - GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20); - GAFR2_L = (GAFR2_L & ~0xf) | (0xa); - - // bits 74-77 - GPDR2 |= (0xf << 10); - GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20); - } - - /* 16 bit interface */ - else if ((lccr0 & LCCR0_CMS) == LCCR0_Color && - ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_PAS) == LCCR0_Act)) - { - // bits 58-77 - GPDR1 |= (0x3f << 26); - GPDR2 |= 0x00003fff; - - GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20); - GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa; - } - - else { - printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n"); - } -} - -static void pxafb_enable_controller(struct pxafb_info *fbi) -{ - DPRINTK("Enabling LCD controller\n"); - DPRINTK("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); - DPRINTK("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); - DPRINTK("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0); - DPRINTK("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1); - DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); - DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); - - /* Sequence from 11.7.10 */ - LCCR3 = fbi->reg_lccr3; - LCCR2 = fbi->reg_lccr2; - LCCR1 = fbi->reg_lccr1; - LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB; - - FDADR0 = fbi->fdadr0; - FDADR1 = fbi->fdadr1; - LCCR0 |= LCCR0_ENB; - - DPRINTK("FDADR0 0x%08x\n", (unsigned int) FDADR0); - DPRINTK("FDADR1 0x%08x\n", (unsigned int) FDADR1); - DPRINTK("LCCR0 0x%08x\n", (unsigned int) LCCR0); - DPRINTK("LCCR1 0x%08x\n", (unsigned int) LCCR1); - DPRINTK("LCCR2 0x%08x\n", (unsigned int) LCCR2); - DPRINTK("LCCR3 0x%08x\n", (unsigned int) LCCR3); -} - -static void pxafb_disable_controller(struct pxafb_info *fbi) -{ - DECLARE_WAITQUEUE(wait, current); - - DPRINTK("Disabling LCD controller\n"); - - add_wait_queue(&fbi->ctrlr_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - - LCSR = 0xffffffff; /* Clear LCD Status Register */ - LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ - LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */ - - schedule_timeout(20 * HZ / 1000); - remove_wait_queue(&fbi->ctrlr_wait, &wait); -} - -/* - * pxafb_handle_irq: Handle 'LCD DONE' interrupts. - */ -static irqreturn_t pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct pxafb_info *fbi = dev_id; - unsigned int lcsr = LCSR; - - if (lcsr & LCSR_LDD) { - LCCR0 |= LCCR0_LDM; - wake_up(&fbi->ctrlr_wait); - } - - LCSR = lcsr; - return IRQ_HANDLED; -} - -/* - * This function must be called from task context only, since it will - * sleep when disabling the LCD controller, or if we get two contending - * processes trying to alter state. - */ -static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) -{ - u_int old_state; - - down(&fbi->ctrlr_sem); - - old_state = fbi->state; - - /* - * Hack around fbcon initialisation. - */ - if (old_state == C_STARTUP && state == C_REENABLE) - state = C_ENABLE; - - switch (state) { - case C_DISABLE_CLKCHANGE: - /* - * Disable controller for clock change. If the - * controller is already disabled, then do nothing. - */ - if (old_state != C_DISABLE && old_state != C_DISABLE_PM) { - fbi->state = state; - //TODO __pxafb_lcd_power(fbi, 0); - pxafb_disable_controller(fbi); - } - break; - - case C_DISABLE_PM: - case C_DISABLE: - /* - * Disable controller - */ - if (old_state != C_DISABLE) { - fbi->state = state; - __pxafb_backlight_power(fbi, 0); - __pxafb_lcd_power(fbi, 0); - if (old_state != C_DISABLE_CLKCHANGE) - pxafb_disable_controller(fbi); - } - break; - - case C_ENABLE_CLKCHANGE: - /* - * Enable the controller after clock change. Only - * do this if we were disabled for the clock change. - */ - if (old_state == C_DISABLE_CLKCHANGE) { - fbi->state = C_ENABLE; - pxafb_enable_controller(fbi); - //TODO __pxafb_lcd_power(fbi, 1); - } - break; - - case C_REENABLE: - /* - * Re-enable the controller only if it was already - * enabled. This is so we reprogram the control - * registers. - */ - if (old_state == C_ENABLE) { - pxafb_disable_controller(fbi); - pxafb_setup_gpio(fbi); - pxafb_enable_controller(fbi); - } - break; - - case C_ENABLE_PM: - /* - * Re-enable the controller after PM. This is not - * perfect - think about the case where we were doing - * a clock change, and we suspended half-way through. - */ - if (old_state != C_DISABLE_PM) - break; - /* fall through */ - - case C_ENABLE: - /* - * Power up the LCD screen, enable controller, and - * turn on the backlight. - */ - if (old_state != C_ENABLE) { - fbi->state = C_ENABLE; - pxafb_setup_gpio(fbi); - pxafb_enable_controller(fbi); - __pxafb_lcd_power(fbi, 1); - __pxafb_backlight_power(fbi, 1); - } - break; - } - up(&fbi->ctrlr_sem); -} - -/* - * Our LCD controller task (which is called when we blank or unblank) - * via keventd. - */ -static void pxafb_task(void *dummy) -{ - struct pxafb_info *fbi = dummy; - u_int state = xchg(&fbi->task_state, -1); - - set_ctrlr_state(fbi, state); -} - -#ifdef CONFIG_CPU_FREQ -/* - * CPU clock speed change handler. We need to adjust the LCD timing - * parameters when the CPU clock is adjusted by the power management - * subsystem. - * - * TODO: Determine why f->new != 10*get_lclk_frequency_10khz() - */ -static int -pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) -{ - struct pxafb_info *fbi = TO_INF(nb, freq_transition); - //TODO struct cpufreq_freqs *f = data; - u_int pcd; - - switch (val) { - case CPUFREQ_PRECHANGE: - set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); - break; - - case CPUFREQ_POSTCHANGE: - pcd = get_pcd(fbi->fb.var.pixclock); - fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); - set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); - break; - } - return 0; -} - -static int -pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data) -{ - struct pxafb_info *fbi = TO_INF(nb, freq_policy); - struct fb_var_screeninfo *var = &fbi->fb.var; - struct cpufreq_policy *policy = data; - - switch (val) { - case CPUFREQ_ADJUST: - case CPUFREQ_INCOMPATIBLE: - printk(KERN_DEBUG "min dma period: %d ps, " - "new clock %d kHz\n", pxafb_display_dma_period(var), - policy->max); - // TODO: fill in min/max values - break; -#if 0 - case CPUFREQ_NOTIFY: - printk(KERN_ERR "%s: got CPUFREQ_NOTIFY\n", __FUNCTION__); - do {} while(0); - /* todo: panic if min/max values aren't fulfilled - * [can't really happen unless there's a bug in the - * CPU policy verification process * - */ - break; -#endif - } - return 0; -} -#endif - -#ifdef CONFIG_PM -/* - * Power management hooks. Note that we won't be called from IRQ context, - * unlike the blank functions above, so we may sleep. - */ -static int pxafb_suspend(struct device *dev, u32 state, u32 level) -{ - struct pxafb_info *fbi = dev_get_drvdata(dev); - - if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) - set_ctrlr_state(fbi, C_DISABLE_PM); - return 0; -} - -static int pxafb_resume(struct device *dev, u32 level) -{ - struct pxafb_info *fbi = dev_get_drvdata(dev); - - if (level == RESUME_ENABLE) - set_ctrlr_state(fbi, C_ENABLE_PM); - return 0; -} -#else -#define pxafb_suspend NULL -#define pxafb_resume NULL -#endif - -/* - * pxafb_map_video_memory(): - * Allocates the DRAM memory for the frame buffer. This buffer is - * remapped into a non-cached, non-buffered, memory region to - * allow palette and pixel writes to occur without flushing the - * cache. Once this area is remapped, all virtual memory - * access to the video memory should occur at the new region. - */ -static int __init pxafb_map_video_memory(struct pxafb_info *fbi) -{ - u_long palette_mem_size; - - /* - * We reserve one page for the palette, plus the size - * of the framebuffer. - */ - fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE); - fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, - &fbi->map_dma, GFP_KERNEL); - - if (fbi->map_cpu) { - /* prevent initial garbage on screen */ - memset(fbi->map_cpu, 0, fbi->map_size); - fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE; - fbi->screen_dma = fbi->map_dma + PAGE_SIZE; - /* - * FIXME: this is actually the wrong thing to place in - * smem_start. But fbdev suffers from the problem that - * it needs an API which doesn't exist (in this case, - * dma_writecombine_mmap) - */ - fbi->fb.fix.smem_start = fbi->screen_dma; - - fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16; - - palette_mem_size = fbi->palette_size * sizeof(u16); - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); - - fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); - fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; - } - - return fbi->map_cpu ? 0 : -ENOMEM; -} - -static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) -{ - struct pxafb_info *fbi; - void *addr; - struct pxafb_mach_info *inf = dev->platform_data; - - /* Alloc the pxafb_info and pseudo_palette in one step */ - fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 17, GFP_KERNEL); - if (!fbi) - return NULL; - - memset(fbi, 0, sizeof(struct pxafb_info)); - fbi->dev = dev; - - strcpy(fbi->fb.fix.id, PXA_NAME); - - fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; - fbi->fb.fix.type_aux = 0; - fbi->fb.fix.xpanstep = 0; - fbi->fb.fix.ypanstep = 0; - fbi->fb.fix.ywrapstep = 0; - fbi->fb.fix.accel = FB_ACCEL_NONE; - - fbi->fb.var.nonstd = 0; - fbi->fb.var.activate = FB_ACTIVATE_NOW; - fbi->fb.var.height = -1; - fbi->fb.var.width = -1; - fbi->fb.var.accel_flags = 0; - fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; - - fbi->fb.fbops = &pxafb_ops; - fbi->fb.flags = FBINFO_FLAG_DEFAULT; - fbi->fb.node = -1; - fbi->fb.currcon = -1; - - addr = fbi; - addr = addr + sizeof(struct pxafb_info); - fbi->fb.pseudo_palette = addr; - - fbi->max_xres = inf->xres; - fbi->fb.var.xres = inf->xres; - fbi->fb.var.xres_virtual = inf->xres; - fbi->max_yres = inf->yres; - fbi->fb.var.yres = inf->yres; - fbi->fb.var.yres_virtual = inf->yres; - fbi->max_bpp = inf->bpp; - fbi->fb.var.bits_per_pixel = inf->bpp; - fbi->fb.var.pixclock = inf->pixclock; - fbi->fb.var.hsync_len = inf->hsync_len; - fbi->fb.var.left_margin = inf->left_margin; - fbi->fb.var.right_margin = inf->right_margin; - fbi->fb.var.vsync_len = inf->vsync_len; - fbi->fb.var.upper_margin = inf->upper_margin; - fbi->fb.var.lower_margin = inf->lower_margin; - fbi->fb.var.sync = inf->sync; - fbi->fb.var.grayscale = inf->cmap_greyscale; - fbi->cmap_inverse = inf->cmap_inverse; - fbi->cmap_static = inf->cmap_static; - fbi->lccr0 = inf->lccr0; - fbi->lccr3 = inf->lccr3; - fbi->state = C_STARTUP; - fbi->task_state = (u_char)-1; - fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * - fbi->max_bpp / 8; - - init_waitqueue_head(&fbi->ctrlr_wait); - INIT_WORK(&fbi->task, pxafb_task, fbi); - init_MUTEX(&fbi->ctrlr_sem); - - return fbi; -} - -#ifdef CONFIG_FB_PXA_PARAMETERS -static int __init pxafb_parse_options(struct device *dev, char *options) -{ - struct pxafb_mach_info *inf = dev->platform_data; - char *this_opt; - - if (!options || !*options) - return 0; - - dev_dbg(dev, "options are \"%s\"\n", options ? options : "null"); - - /* could be made table driven or similar?... */ - while ((this_opt = strsep(&options, ",")) != NULL) { - if (!strncmp(this_opt, "mode:", 5)) { - const char *name = this_opt+5; - unsigned int namelen = strlen(name); - int res_specified = 0, bpp_specified = 0; - unsigned int xres = 0, yres = 0, bpp = 0; - int yres_specified = 0; - int i; - for (i = namelen-1; i >= 0; i--) { - switch (name[i]) { - case '-': - namelen = i; - if (!bpp_specified && !yres_specified) { - bpp = simple_strtoul(&name[i+1], NULL, 0); - bpp_specified = 1; - } else - goto done; - break; - case 'x': - if (!yres_specified) { - yres = simple_strtoul(&name[i+1], NULL, 0); - yres_specified = 1; - } else - goto done; - break; - case '0'...'9': - break; - default: - goto done; - } - } - if (i < 0 && yres_specified) { - xres = simple_strtoul(name, NULL, 0); - res_specified = 1; - } - done: - if ( res_specified ) { - dev_info(dev, "overriding resolution: %dx%x\n", xres, yres); - inf->xres = xres; inf->yres = yres; - } - if ( bpp_specified ) - switch (bpp) { - case 1: - case 2: - case 4: - case 8: - case 16: - inf->bpp = bpp; - dev_info(dev, "overriding bit depth: %d\n", bpp); - break; - default: - dev_err(dev, "Depth %d is not valid\n", bpp); - } - } else if (!strncmp(this_opt, "pixclock:", 9)) { - inf->pixclock = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override pixclock: %u\n", inf->pixclock); - } else if (!strncmp(this_opt, "left:", 5)) { - inf->left_margin = simple_strtoul(this_opt+5, NULL, 0); - dev_info(dev, "override left: %u\n", inf->left_margin); - } else if (!strncmp(this_opt, "right:", 6)) { - inf->right_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override right: %u\n", inf->right_margin); - } else if (!strncmp(this_opt, "upper:", 6)) { - inf->upper_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override upper: %u\n", inf->upper_margin); - } else if (!strncmp(this_opt, "lower:", 6)) { - inf->lower_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override lower: %u\n", inf->lower_margin); - } else if (!strncmp(this_opt, "hsynclen:", 9)) { - inf->hsync_len = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override hsynclen: %u\n", inf->hsync_len); - } else if (!strncmp(this_opt, "vsynclen:", 9)) { - inf->vsync_len = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override vsynclen: %u\n", inf->vsync_len); - } else if (!strncmp(this_opt, "hsync:", 6)) { - if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) { - dev_info(dev, "override hsync: Active Low\n"); - inf->sync &= ~FB_SYNC_HOR_HIGH_ACT; - } else { - dev_info(dev, "override hsync: Active High\n"); - inf->sync |= FB_SYNC_HOR_HIGH_ACT; - } - } else if (!strncmp(this_opt, "vsync:", 6)) { - if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) { - dev_info(dev, "override vsync: Active Low\n"); - inf->sync &= ~FB_SYNC_VERT_HIGH_ACT; - } else { - dev_info(dev, "override vsync: Active High\n"); - inf->sync |= FB_SYNC_VERT_HIGH_ACT; - } - } else if (!strncmp(this_opt, "dpc:", 4)) { - if ( simple_strtoul(this_opt+4, NULL, 0) == 0 ) { - dev_info(dev, "override double pixel clock: false\n"); - inf->lccr3 &= ~LCCR3_DPC; - } else { - dev_info(dev, "override double pixel clock: true\n"); - inf->lccr3 |= LCCR3_DPC; - } - } else if (!strncmp(this_opt, "outputen:", 9)) { - if ( simple_strtoul(this_opt+9, NULL, 0) == 0 ) { - dev_info(dev, "override output enable: active low\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnL; - } else { - dev_info(dev, "override output enable: active high\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_OEP ) | LCCR3_OutEnH; - } - } else if (!strncmp(this_opt, "pixclockpol:", 12)) { - if ( simple_strtoul(this_opt+12, NULL, 0) == 0 ) { - dev_info(dev, "override pixel clock polarity: falling edge\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixFlEdg; - } else { - dev_info(dev, "override pixel clock polarity: rising edge\n"); - inf->lccr3 = ( inf->lccr3 & ~LCCR3_PCP ) | LCCR3_PixRsEdg; - } - } else if (!strncmp(this_opt, "color", 5)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color; - } else if (!strncmp(this_opt, "mono", 4)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono; - } else if (!strncmp(this_opt, "active", 6)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act; - } else if (!strncmp(this_opt, "passive", 7)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas; - } else if (!strncmp(this_opt, "single", 6)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl; - } else if (!strncmp(this_opt, "dual", 4)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual; - } else if (!strncmp(this_opt, "4pix", 4)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono; - } else if (!strncmp(this_opt, "8pix", 4)) { - inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono; - } else { - dev_err(dev, "unknown option: %s\n", this_opt); - return -EINVAL; - } - } - return 0; - -} -#endif - -int __init pxafb_probe(struct device *dev) -{ - struct pxafb_info *fbi; - struct pxafb_mach_info *inf; - unsigned long flags; - int ret; - - dev_dbg(dev, "pxafb_probe\n"); - - inf = dev->platform_data; - ret = -ENOMEM; - fbi = NULL; - if (!inf) - goto failed; - -#ifdef CONFIG_FB_PXA_PARAMETERS - ret = pxafb_parse_options(dev, g_options); - if ( ret < 0 ) - goto failed; -#endif - -#ifdef DEBUG_VAR - /* Check for various illegal bit-combinations. Currently only - * a warning is given. */ - - if ( inf->lccr0 & LCCR0_INVALID_CONFIG_MASK ) - dev_warn(dev, "machine LCCR0 setting contains illegal bits: %08x\n", - inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); - if ( inf->lccr3 & LCCR3_INVALID_CONFIG_MASK ) - dev_warn(dev, "machine LCCR3 setting contains illegal bits: %08x\n", - inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); - if ( inf->lccr0 & LCCR0_DPD && - ( ( inf->lccr0 & LCCR0_PAS ) != LCCR0_Pas || - ( inf->lccr0 & LCCR0_SDS ) != LCCR0_Sngl || - ( inf->lccr0 & LCCR0_CMS ) != LCCR0_Mono ) ) - dev_warn(dev, "Double Pixel Data (DPD) mode is only valid in passive mono" - " single panel mode\n"); - if ( (inf->lccr0 & LCCR0_PAS) == LCCR0_Act && - ( inf->lccr0 & LCCR0_SDS ) == LCCR0_Dual ) - dev_warn(dev, "Dual panel only valid in passive mode\n"); - if ( (inf->lccr0 & LCCR0_PAS ) == LCCR0_Pas && - (inf->upper_margin || inf->lower_margin) ) - dev_warn(dev, "Upper and lower margins must be 0 in passive mode\n"); -#endif - - dev_dbg(dev, "got a %dx%dx%d LCD\n",inf->xres, inf->yres, inf->bpp); - if (inf->xres == 0 || inf->yres == 0 || inf->bpp == 0) { - dev_err(dev, "Invalid resolution or bit depth\n"); - ret = -EINVAL; - goto failed; - } - pxafb_backlight_power = inf->pxafb_backlight_power; - pxafb_lcd_power = inf->pxafb_lcd_power; - fbi = pxafb_init_fbinfo(dev); - if (!fbi) { - dev_err(dev, "Failed to initialize framebuffer device\n"); - ret = -ENOMEM; // only reason for pxafb_init_fbinfo to fail is kmalloc - goto failed; - } - - /* Initialize video memory */ - ret = pxafb_map_video_memory(fbi); - if (ret) { - dev_err(dev, "Failed to allocate video RAM: %d\n", ret); - ret = -ENOMEM; - goto failed; - } - /* enable LCD controller clock */ - local_irq_save(flags); - CKEN |= CKEN16_LCD; - local_irq_restore(flags); - - ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); - if (ret) { - dev_err(dev, "request_irq failed: %d\n", ret); - ret = -EBUSY; - goto failed; - } - - /* - * This makes sure that our colour bitfield - * descriptors are correctly initialised. - */ - pxafb_check_var(&fbi->fb.var, &fbi->fb); - pxafb_set_par(&fbi->fb); - - dev_set_drvdata(dev, fbi); - - ret = register_framebuffer(&fbi->fb); - if (ret < 0) { - dev_err(dev, "Failed to register framebuffer device: %d\n", ret); - goto failed; - } - -#ifdef CONFIG_PM - // TODO -#endif - -#ifdef CONFIG_CPU_FREQ - fbi->freq_transition.notifier_call = pxafb_freq_transition; - fbi->freq_policy.notifier_call = pxafb_freq_policy; - cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); -#endif - - /* - * Ok, now enable the LCD controller - */ - set_ctrlr_state(fbi, C_ENABLE); - - return 0; - -failed: - dev_set_drvdata(dev, NULL); - if (fbi) - kfree(fbi); - return ret; -} - -static struct device_driver pxafb_driver = { - .name = "pxafb", - .bus = &platform_bus_type, - .probe = pxafb_probe, -#ifdef CONFIG_PM - .suspend = pxafb_suspend, - .resume = pxafb_resume, -#endif -}; - -int __devinit pxafb_init(void) -{ - return driver_register(&pxafb_driver); -} - -#ifndef MODULE -int __devinit pxafb_setup(char *options) -{ -# ifdef CONFIG_FB_PXA_PARAMETERS - strlcpy(g_options, options, sizeof(g_options)); -# endif - return 0; -} -#else -module_init(pxafb_init); -# ifdef CONFIG_FB_PXA_PARAMETERS -module_param_string(options, g_options, sizeof(g_options), 0); -MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)"); -# endif -#endif - -MODULE_DESCRIPTION("loadable framebuffer driver for PXA"); -MODULE_LICENSE("GPL"); diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c deleted file mode 100644 index d1fe21d8f..000000000 --- a/fs/ext3/resize.c +++ /dev/null @@ -1,956 +0,0 @@ -/* - * linux/fs/ext3/resize.c - * - * Support for resizing an ext3 filesystem while it is mounted. - * - * Copyright (C) 2001, 2002 Andreas Dilger - * - * This could probably be made into a module, because it is not often in use. - */ - -#include - -#define EXT3FS_DEBUG - -#include -#include -#include - -#include -#include - - -#define outside(b, first, last) ((b) < (first) || (b) >= (last)) -#define inside(b, first, last) ((b) >= (first) && (b) < (last)) - -static int verify_group_input(struct super_block *sb, - struct ext3_new_group_data *input) -{ - struct ext3_sb_info *sbi = EXT3_SB(sb); - struct ext3_super_block *es = sbi->s_es; - unsigned start = le32_to_cpu(es->s_blocks_count); - unsigned end = start + input->blocks_count; - unsigned group = input->group; - unsigned itend = input->inode_table + EXT3_SB(sb)->s_itb_per_group; - unsigned overhead = ext3_bg_has_super(sb, group) ? - (1 + ext3_bg_num_gdb(sb, group) + - le16_to_cpu(es->s_reserved_gdt_blocks)) : 0; - unsigned metaend = start + overhead; - struct buffer_head *bh; - int free_blocks_count; - int err = -EINVAL; - - input->free_blocks_count = free_blocks_count = - input->blocks_count - 2 - overhead - sbi->s_itb_per_group; - - if (test_opt(sb, DEBUG)) - printk("EXT3-fs: adding %s group %u: %u blocks " - "(%d free, %u reserved)\n", - ext3_bg_has_super(sb, input->group) ? "normal" : - "no-super", input->group, input->blocks_count, - free_blocks_count, input->reserved_blocks); - - if (group != sbi->s_groups_count) - ext3_warning(sb, __FUNCTION__, - "Cannot add at group %u (only %lu groups)", - input->group, sbi->s_groups_count); - else if ((start - le32_to_cpu(es->s_first_data_block)) % - EXT3_BLOCKS_PER_GROUP(sb)) - ext3_warning(sb, __FUNCTION__, "Last group not full"); - else if (input->reserved_blocks > input->blocks_count / 5) - ext3_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)", - input->reserved_blocks); - else if (free_blocks_count < 0) - ext3_warning(sb, __FUNCTION__, "Bad blocks count %u", - input->blocks_count); - else if (!(bh = sb_bread(sb, end - 1))) - ext3_warning(sb, __FUNCTION__, "Cannot read last block (%u)", - end - 1); - else if (outside(input->block_bitmap, start, end)) - ext3_warning(sb, __FUNCTION__, - "Block bitmap not in group (block %u)", - input->block_bitmap); - else if (outside(input->inode_bitmap, start, end)) - ext3_warning(sb, __FUNCTION__, - "Inode bitmap not in group (block %u)", - input->inode_bitmap); - else if (outside(input->inode_table, start, end) || - outside(itend - 1, start, end)) - ext3_warning(sb, __FUNCTION__, - "Inode table not in group (blocks %u-%u)", - input->inode_table, itend - 1); - else if (input->inode_bitmap == input->block_bitmap) - ext3_warning(sb, __FUNCTION__, - "Block bitmap same as inode bitmap (%u)", - input->block_bitmap); - else if (inside(input->block_bitmap, input->inode_table, itend)) - ext3_warning(sb, __FUNCTION__, - "Block bitmap (%u) in inode table (%u-%u)", - input->block_bitmap, input->inode_table, itend-1); - else if (inside(input->inode_bitmap, input->inode_table, itend)) - ext3_warning(sb, __FUNCTION__, - "Inode bitmap (%u) in inode table (%u-%u)", - input->inode_bitmap, input->inode_table, itend-1); - else if (inside(input->block_bitmap, start, metaend)) - ext3_warning(sb, __FUNCTION__, - "Block bitmap (%u) in GDT table (%u-%u)", - input->block_bitmap, start, metaend - 1); - else if (inside(input->inode_bitmap, start, metaend)) - ext3_warning(sb, __FUNCTION__, - "Inode bitmap (%u) in GDT table (%u-%u)", - input->inode_bitmap, start, metaend - 1); - else if (inside(input->inode_table, start, metaend) || - inside(itend - 1, start, metaend)) - ext3_warning(sb, __FUNCTION__, - "Inode table (%u-%u) overlaps GDT table (%u-%u)", - input->inode_table, itend - 1, start, metaend - 1); - else { - brelse(bh); - err = 0; - } - - return err; -} - -static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, - unsigned long blk) -{ - struct buffer_head *bh; - int err; - - bh = sb_getblk(sb, blk); - set_buffer_uptodate(bh); - if ((err = ext3_journal_get_write_access(handle, bh))) { - brelse(bh); - bh = ERR_PTR(err); - } else - memset(bh->b_data, 0, sb->s_blocksize); - - return bh; -} - -/* - * To avoid calling the atomic setbit hundreds or thousands of times, we only - * need to use it within a single byte (to ensure we get endianness right). - * We can use memset for the rest of the bitmap as there are no other users. - */ -static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap) -{ - int i; - - if (start_bit >= end_bit) - return; - - ext3_debug("mark end bits +%d through +%d used\n", start_bit, end_bit); - for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++) - ext3_set_bit(i, bitmap); - if (i < end_bit) - memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); -} - -/* - * Set up the block and inode bitmaps, and the inode table for the new group. - * This doesn't need to be part of the main transaction, since we are only - * changing blocks outside the actual filesystem. We still do journaling to - * ensure the recovery is correct in case of a failure just after resize. - * If any part of this fails, we simply abort the resize. - * - * We only pass inode because of the ext3 journal wrappers. - */ -static int setup_new_group_blocks(struct super_block *sb, struct inode *inode, - struct ext3_new_group_data *input) -{ - struct ext3_sb_info *sbi = EXT3_SB(sb); - unsigned long start = input->group * sbi->s_blocks_per_group + - le32_to_cpu(sbi->s_es->s_first_data_block); - int reserved_gdb = ext3_bg_has_super(sb, input->group) ? - le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0; - unsigned long gdblocks = ext3_bg_num_gdb(sb, input->group); - struct buffer_head *bh; - handle_t *handle; - unsigned long block; - int bit; - int i; - int err = 0, err2; - - handle = ext3_journal_start(inode, reserved_gdb + gdblocks + - 2 + sbi->s_itb_per_group); - if (IS_ERR(handle)) - return PTR_ERR(handle); - - lock_super(sb); - if (input->group != sbi->s_groups_count) { - err = -EBUSY; - goto exit_journal; - } - - if (IS_ERR(bh = bclean(handle, sb, input->block_bitmap))) { - err = PTR_ERR(bh); - goto exit_journal; - } - - if (ext3_bg_has_super(sb, input->group)) { - ext3_debug("mark backup superblock %#04lx (+0)\n", start); - ext3_set_bit(0, bh->b_data); - } - - /* Copy all of the GDT blocks into the backup in this group */ - for (i = 0, bit = 1, block = start + 1; - i < gdblocks; i++, block++, bit++) { - struct buffer_head *gdb; - - ext3_debug("update backup group %#04lx (+%d)\n", block, bit); - - gdb = sb_getblk(sb, block); - set_buffer_uptodate(gdb); - if ((err = ext3_journal_get_write_access(handle, gdb))) { - brelse(gdb); - goto exit_bh; - } - memcpy(gdb->b_data, sbi->s_group_desc[i], bh->b_size); - ext3_journal_dirty_metadata(handle, gdb); - ext3_set_bit(bit, bh->b_data); - brelse(gdb); - } - - /* Zero out all of the reserved backup group descriptor table blocks */ - for (i = 0, bit = gdblocks + 1, block = start + bit; - i < reserved_gdb; i++, block++, bit++) { - struct buffer_head *gdb; - - ext3_debug("clear reserved block %#04lx (+%d)\n", block, bit); - - if (IS_ERR(gdb = bclean(handle, sb, block))) { - err = PTR_ERR(bh); - goto exit_bh; - } - ext3_journal_dirty_metadata(handle, gdb); - ext3_set_bit(bit, bh->b_data); - brelse(gdb); - } - ext3_debug("mark block bitmap %#04x (+%ld)\n", input->block_bitmap, - input->block_bitmap - start); - ext3_set_bit(input->block_bitmap - start, bh->b_data); - ext3_debug("mark inode bitmap %#04x (+%ld)\n", input->inode_bitmap, - input->inode_bitmap - start); - ext3_set_bit(input->inode_bitmap - start, bh->b_data); - - /* Zero out all of the inode table blocks */ - for (i = 0, block = input->inode_table, bit = block - start; - i < sbi->s_itb_per_group; i++, bit++, block++) { - struct buffer_head *it; - - ext3_debug("clear inode block %#04x (+%ld)\n", block, bit); - if (IS_ERR(it = bclean(handle, sb, block))) { - err = PTR_ERR(it); - goto exit_bh; - } - ext3_journal_dirty_metadata(handle, it); - brelse(it); - ext3_set_bit(bit, bh->b_data); - } - mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), - bh->b_data); - ext3_journal_dirty_metadata(handle, bh); - brelse(bh); - - /* Mark unused entries in inode bitmap used */ - ext3_debug("clear inode bitmap %#04x (+%ld)\n", - input->inode_bitmap, input->inode_bitmap - start); - if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) { - err = PTR_ERR(bh); - goto exit_journal; - } - - mark_bitmap_end(EXT3_INODES_PER_GROUP(sb), EXT3_BLOCKS_PER_GROUP(sb), - bh->b_data); - ext3_journal_dirty_metadata(handle, bh); -exit_bh: - brelse(bh); - -exit_journal: - unlock_super(sb); - if ((err2 = ext3_journal_stop(handle)) && !err) - err = err2; - - return err; -} - -/* - * Iterate through the groups which hold BACKUP superblock/GDT copies in an - * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before - * calling this for the first time. In a sparse filesystem it will be the - * 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) -{ - unsigned *min = three; - int mult = 3; - unsigned ret; - - if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, - EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ret = *min; - *min += 1; - return ret; - } - - if (*five < *min) { - min = five; - mult = 5; - } - if (*seven < *min) { - min = seven; - mult = 7; - } - - ret = *min; - *min *= mult; - - return ret; -} - -/* - * Check that all of the backup GDT blocks are held in the primary GDT block. - * It is assumed that they are stored in group order. Returns the number of - * groups in current filesystem that have BACKUPS, or -ve error code. - */ -static int verify_reserved_gdb(struct super_block *sb, - struct buffer_head *primary) -{ - const unsigned long blk = primary->b_blocknr; - const unsigned long end = EXT3_SB(sb)->s_groups_count; - unsigned three = 1; - unsigned five = 5; - unsigned seven = 7; - unsigned grp; - __u32 *p = (__u32 *)primary->b_data; - int gdbackups = 0; - - while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) { - if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){ - ext3_warning(sb, __FUNCTION__, - "reserved GDT %ld missing grp %d (%ld)\n", - blk, grp, - grp * EXT3_BLOCKS_PER_GROUP(sb) + blk); - return -EINVAL; - } - if (++gdbackups > EXT3_ADDR_PER_BLOCK(sb)) - return -EFBIG; - } - - return gdbackups; -} - -/* - * Called when we need to bring a reserved group descriptor table block into - * use from the resize inode. The primary copy of the new GDT block currently - * is an indirect block (under the double indirect block in the resize inode). - * The new backup GDT blocks will be stored as leaf blocks in this indirect - * block, in group order. Even though we know all the block numbers we need, - * we check to ensure that the resize inode has actually reserved these blocks. - * - * Don't need to update the block bitmaps because the blocks are still in use. - * - * We get all of the error cases out of the way, so that we are sure to not - * fail once we start modifying the data on disk, because JBD has no rollback. - */ -static int add_new_gdb(handle_t *handle, struct inode *inode, - struct ext3_new_group_data *input, - struct buffer_head **primary) -{ - struct super_block *sb = inode->i_sb; - struct ext3_super_block *es = EXT3_SB(sb)->s_es; - unsigned long gdb_num = input->group / EXT3_DESC_PER_BLOCK(sb); - unsigned long gdb_off = input->group % EXT3_DESC_PER_BLOCK(sb); - unsigned long gdblock = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num; - struct buffer_head **o_group_desc, **n_group_desc; - struct buffer_head *dind; - int gdbackups; - struct ext3_iloc iloc; - __u32 *data; - int err; - - if (test_opt(sb, DEBUG)) - printk("EXT3-fs: ext3_add_new_gdb: adding group block %lu\n", - gdb_num); - - /* - * If we are not using the primary superblock/GDT copy don't resize, - * because the user tools have no way of handling this. Probably a - * bad time to do it anyways. - */ - if (EXT3_SB(sb)->s_sbh->b_blocknr != - le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) { - ext3_warning(sb, __FUNCTION__, - "won't resize using backup superblock at %lu\n", - EXT3_SB(sb)->s_sbh->b_blocknr); - return -EPERM; - } - - *primary = sb_bread(sb, gdblock); - if (!*primary) - return -EIO; - - if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) { - err = gdbackups; - goto exit_bh; - } - - data = EXT3_I(inode)->i_data + EXT3_DIND_BLOCK; - dind = sb_bread(sb, le32_to_cpu(*data)); - if (!dind) { - err = -EIO; - goto exit_bh; - } - - data = (__u32 *)dind->b_data; - if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) { - ext3_warning(sb, __FUNCTION__, - "new group %u GDT block %lu not reserved\n", - input->group, gdblock); - err = -EINVAL; - goto exit_dind; - } - - if ((err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh))) - goto exit_dind; - - if ((err = ext3_journal_get_write_access(handle, *primary))) - goto exit_sbh; - - if ((err = ext3_journal_get_write_access(handle, dind))) - goto exit_primary; - - /* ext3_reserve_inode_write() gets a reference on the iloc */ - if ((err = ext3_reserve_inode_write(handle, inode, &iloc))) - goto exit_dindj; - - n_group_desc = (struct buffer_head **)kmalloc((gdb_num + 1) * - sizeof(struct buffer_head *), GFP_KERNEL); - if (!n_group_desc) { - err = -ENOMEM; - ext3_warning (sb, __FUNCTION__, - "not enough memory for %lu groups", gdb_num + 1); - goto exit_inode; - } - - /* - * Finally, we have all of the possible failures behind us... - * - * Remove new GDT block from inode double-indirect block and clear out - * the new GDT block for use (which also "frees" the backup GDT blocks - * from the reserved inode). We don't need to change the bitmaps for - * these blocks, because they are marked as in-use from being in the - * reserved inode, and will become GDT blocks (primary and backup). - */ - /* - printk("removing block %d = %ld from dindir %ld[%ld]\n", - ((__u32 *)(dind->b_data))[gdb_off], gdblock, dind->b_blocknr, - gdb_num); */ - data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)] = 0; - ext3_journal_dirty_metadata(handle, dind); - brelse(dind); - inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; - ext3_mark_iloc_dirty(handle, inode, &iloc); - memset((*primary)->b_data, 0, sb->s_blocksize); - ext3_journal_dirty_metadata(handle, *primary); - - o_group_desc = EXT3_SB(sb)->s_group_desc; - memcpy(n_group_desc, o_group_desc, - EXT3_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); - n_group_desc[gdb_num] = *primary; - EXT3_SB(sb)->s_group_desc = n_group_desc; - EXT3_SB(sb)->s_gdb_count++; - kfree(o_group_desc); - - es->s_reserved_gdt_blocks = - cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1); - ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - - return 0; - -exit_inode: - //ext3_journal_release_buffer(handle, iloc.bh); - brelse(iloc.bh); -exit_dindj: - //ext3_journal_release_buffer(handle, dind); -exit_primary: - //ext3_journal_release_buffer(handle, *primary); -exit_sbh: - //ext3_journal_release_buffer(handle, *primary); -exit_dind: - brelse(dind); -exit_bh: - brelse(*primary); - - ext3_debug("leaving with error %d\n", err); - return err; -} - -/* - * Called when we are adding a new group which has a backup copy of each of - * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks. - * We need to add these reserved backup GDT blocks to the resize inode, so - * that they are kept for future resizing and not allocated to files. - * - * Each reserved backup GDT block will go into a different indirect block. - * The indirect blocks are actually the primary reserved GDT blocks, - * so we know in advance what their block numbers are. We only get the - * double-indirect block to verify it is pointing to the primary reserved - * GDT blocks so we don't overwrite a data block by accident. The reserved - * backup GDT blocks are stored in their reserved primary GDT block. - */ -static int reserve_backup_gdb(handle_t *handle, struct inode *inode, - struct ext3_new_group_data *input) -{ - struct super_block *sb = inode->i_sb; - int reserved_gdb =le16_to_cpu(EXT3_SB(sb)->s_es->s_reserved_gdt_blocks); - struct buffer_head **primary; - struct buffer_head *dind; - struct ext3_iloc iloc; - unsigned long blk; - __u32 *data, *end; - int gdbackups = 0; - int res, i; - int err; - - primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL); - if (!primary) - return -ENOMEM; - - data = EXT3_I(inode)->i_data + EXT3_DIND_BLOCK; - dind = sb_bread(sb, le32_to_cpu(*data)); - if (!dind) { - err = -EIO; - goto exit_free; - } - - blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count; - data = (__u32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count; - end = (__u32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb); - - /* Get each reserved primary GDT block and verify it holds backups */ - for (res = 0; res < reserved_gdb; res++, blk++) { - if (le32_to_cpu(*data) != blk) { - ext3_warning(sb, __FUNCTION__, - "reserved block %lu not at offset %ld\n", - blk, (long)(data - (__u32 *)dind->b_data)); - err = -EINVAL; - goto exit_bh; - } - primary[res] = sb_bread(sb, blk); - if (!primary[res]) { - err = -EIO; - goto exit_bh; - } - if ((gdbackups = verify_reserved_gdb(sb, primary[res])) < 0) { - brelse(primary[res]); - err = gdbackups; - goto exit_bh; - } - if (++data >= end) - data = (__u32 *)dind->b_data; - } - - for (i = 0; i < reserved_gdb; i++) { - if ((err = ext3_journal_get_write_access(handle, primary[i]))) { - /* - int j; - for (j = 0; j < i; j++) - ext3_journal_release_buffer(handle, primary[j]); - */ - goto exit_bh; - } - } - - if ((err = ext3_reserve_inode_write(handle, inode, &iloc))) - goto exit_bh; - - /* - * Finally we can add each of the reserved backup GDT blocks from - * the new group to its reserved primary GDT block. - */ - blk = input->group * EXT3_BLOCKS_PER_GROUP(sb); - for (i = 0; i < reserved_gdb; i++) { - int err2; - data = (__u32 *)primary[i]->b_data; - /* printk("reserving backup %lu[%u] = %lu\n", - primary[i]->b_blocknr, gdbackups, - blk + primary[i]->b_blocknr); */ - data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr); - err2 = ext3_journal_dirty_metadata(handle, primary[i]); - if (!err) - err = err2; - } - inode->i_blocks += reserved_gdb * sb->s_blocksize >> 9; - ext3_mark_iloc_dirty(handle, inode, &iloc); - -exit_bh: - while (--res >= 0) - brelse(primary[res]); - brelse(dind); - -exit_free: - kfree(primary); - - return err; -} - -/* - * Update the backup copies of the ext3 metadata. These don't need to be part - * of the main resize transaction, because e2fsck will re-write them if there - * is a problem (basically only OOM will cause a problem). However, we - * _should_ update the backups if possible, in case the primary gets trashed - * for some reason and we need to run e2fsck from a backup superblock. The - * important part is that the new block and inode counts are in the backup - * superblocks, and the location of the new group metadata in the GDT backups. - * - * We do not need lock_super() for this, because these blocks are not - * otherwise touched by the filesystem code when it is mounted. We don't - * need to worry about last changing from sbi->s_groups_count, because the - * worst that can happen is that we do not copy the full number of backups - * at this time. The resize which changed s_groups_count will backup again. - * - * We only pass inode because of the ext3 journal wrappers. - */ -static void update_backups(struct super_block *sb, struct inode *inode, - int blk_off, char *data, int size) -{ - struct ext3_sb_info *sbi = EXT3_SB(sb); - const unsigned long last = sbi->s_groups_count; - const int bpg = EXT3_BLOCKS_PER_GROUP(sb); - unsigned three = 1; - unsigned five = 5; - unsigned seven = 7; - unsigned group; - int rest = sb->s_blocksize - size; - handle_t *handle; - int err = 0, err2; - - handle = ext3_journal_start(inode, EXT3_MAX_TRANS_DATA); - if (IS_ERR(handle)) { - group = 1; - err = PTR_ERR(handle); - goto exit_err; - } - - while ((group = ext3_list_backups(sb, &three, &five, &seven)) < last) { - struct buffer_head *bh; - - /* Out of journal space, and can't get more - abort - so sad */ - if (handle->h_buffer_credits == 0 && - ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA) && - (err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA))) - break; - - bh = sb_getblk(sb, group * bpg + blk_off); - set_buffer_uptodate(bh); - ext3_debug(sb, __FUNCTION__, "update metadata backup %#04lx\n", - bh->b_blocknr); - if ((err = ext3_journal_get_write_access(handle, bh))) - break; - memcpy(bh->b_data, data, size); - if (rest) - memset(bh->b_data + size, 0, rest); - ext3_journal_dirty_metadata(handle, bh); - brelse(bh); - } - if ((err2 = ext3_journal_stop(handle)) && !err) - err = err2; - - /* - * Ugh! Need to have e2fsck write the backup copies. It is too - * late to revert the resize, we shouldn't fail just because of - * the backup copies (they are only needed in case of corruption). - * - * However, if we got here we have a journal problem too, so we - * can't really start a transaction to mark the superblock. - * Chicken out and just set the flag on the hope it will be written - * to disk, and if not - we will simply wait until next fsck. - */ -exit_err: - if (err) { - ext3_warning(sb, __FUNCTION__, - "can't update backup for group %d (err %d), " - "forcing fsck on next reboot\n", group, err); - sbi->s_mount_state &= ~EXT3_VALID_FS; - sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS); - mark_buffer_dirty(sbi->s_sbh); - } -} - -/* Add group descriptor data to an existing or new group descriptor block. - * Ensure we handle all possible error conditions _before_ we start modifying - * the filesystem, because we cannot abort the transaction and not have it - * write the data to disk. - * - * If we are on a GDT block boundary, we need to get the reserved GDT block. - * Otherwise, we may need to add backup GDT blocks for a sparse group. - * - * We only need to hold the superblock lock while we are actually adding - * in the new group's counts to the superblock. Prior to that we have - * not really "added" the group at all. We re-check that we are still - * adding in the last group in case things have changed since verifying. - */ -int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) -{ - struct ext3_sb_info *sbi = EXT3_SB(sb); - struct ext3_super_block *es = sbi->s_es; - int reserved_gdb = ext3_bg_has_super(sb, input->group) ? - le16_to_cpu(es->s_reserved_gdt_blocks) : 0; - struct buffer_head *primary = NULL; - struct ext3_group_desc *gdp; - struct inode *inode = NULL; - struct inode bogus; - handle_t *handle; - int gdb_off, gdb_num; - int err, err2; - - gdb_num = input->group / EXT3_DESC_PER_BLOCK(sb); - gdb_off = input->group % EXT3_DESC_PER_BLOCK(sb); - - if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb, - EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ext3_warning(sb, __FUNCTION__, - "Can't resize non-sparse filesystem further\n"); - return -EPERM; - } - - if (reserved_gdb || gdb_off == 0) { - if (!EXT3_HAS_COMPAT_FEATURE(sb, - EXT3_FEATURE_COMPAT_RESIZE_INODE)){ - ext3_warning(sb, __FUNCTION__, - "No reserved GDT blocks, can't resize\n"); - return -EPERM; - } - inode = iget(sb, EXT3_RESIZE_INO); - if (!inode || is_bad_inode(inode)) { - ext3_warning(sb, __FUNCTION__, - "Error opening resize inode\n"); - iput(inode); - return -ENOENT; - } - } else { - /* Used only for ext3 journal wrapper functions to get sb */ - inode = &bogus; - bogus.i_sb = sb; - } - - if ((err = verify_group_input(sb, input))) - goto exit_put; - - if ((err = setup_new_group_blocks(sb, inode, input))) - goto exit_put; - - /* - * We will always be modifying at least the superblock and a GDT - * block. If we are adding a group past the last current GDT block, - * we will also modify the inode and the dindirect block. If we - * are adding a group with superblock/GDT backups we will also - * modify each of the reserved GDT dindirect blocks. - */ - handle = ext3_journal_start(inode, ext3_bg_has_super(sb, input->group) ? - 3 + reserved_gdb : 4); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - goto exit_put; - } - - lock_super(sb); - if (input->group != EXT3_SB(sb)->s_groups_count) { - ext3_warning(sb, __FUNCTION__, - "multiple resizers run on filesystem!\n"); - goto exit_journal; - } - - if ((err = ext3_journal_get_write_access(handle, sbi->s_sbh))) - goto exit_journal; - - /* - * We will only either add reserved group blocks to a backup group - * or remove reserved blocks for the first group in a new group block. - * Doing both would be mean more complex code, and sane people don't - * use non-sparse filesystems anymore. This is already checked above. - */ - if (gdb_off) { - primary = sbi->s_group_desc[gdb_num]; - if ((err = ext3_journal_get_write_access(handle, primary))) - goto exit_journal; - - if (reserved_gdb && ext3_bg_num_gdb(sb, input->group) && - (err = reserve_backup_gdb(handle, inode, input))) - goto exit_journal; - } else if ((err = add_new_gdb(handle, inode, input, &primary))) - goto exit_journal; - - /* Finally update group descriptor block for new group */ - gdp = (struct ext3_group_desc *)primary->b_data + gdb_off; - - gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap); - gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap); - gdp->bg_inode_table = cpu_to_le32(input->inode_table); - gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count); - gdp->bg_free_inodes_count = cpu_to_le16(EXT3_INODES_PER_GROUP(sb)); - - EXT3_SB(sb)->s_groups_count++; - ext3_journal_dirty_metadata(handle, primary); - - /* Update superblock with new block counts */ - es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) + - input->blocks_count); - es->s_free_blocks_count = - cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) + - input->free_blocks_count); - es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) + - input->reserved_blocks); - es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) + - EXT3_INODES_PER_GROUP(sb)); - es->s_free_inodes_count = - cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + - EXT3_INODES_PER_GROUP(sb)); - ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - sb->s_dirt = 1; - -exit_journal: - unlock_super(sb); - handle->h_sync = 1; - if ((err2 = ext3_journal_stop(handle)) && !err) - err = err2; - if (!err) { - update_backups(sb, inode, sbi->s_sbh->b_blocknr, (char *)es, - sizeof(struct ext3_super_block)); - update_backups(sb, inode, primary->b_blocknr, primary->b_data, - primary->b_size); - } -exit_put: - if (inode != &bogus) - iput(inode); - return err; -} /* ext3_group_add */ - -/* Extend the filesystem to the new number of blocks specified. This entry - * point is only used to extend the current filesystem to the end of the last - * existing group. It can be accessed via ioctl, or by "remount,resize=" - * for emergencies (because it has no dependencies on reserved blocks). - * - * If we _really_ wanted, we could use default values to call ext3_group_add() - * allow the "remount" trick to work for arbitrary resizing, assuming enough - * GDT blocks are reserved to grow to the desired size. - */ -int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, - unsigned long n_blocks_count) -{ - unsigned long o_blocks_count; - unsigned long o_groups_count; - unsigned long last; - int add; - struct inode *inode; - struct buffer_head * bh; - handle_t *handle; - int err; - - o_blocks_count = le32_to_cpu(es->s_blocks_count); - o_groups_count = EXT3_SB(sb)->s_groups_count; - - if (test_opt(sb, DEBUG)) - printk("EXT3-fs: extending last group from %lu to %lu blocks\n", - o_blocks_count, n_blocks_count); - - if (n_blocks_count == 0 || n_blocks_count == o_blocks_count) - return 0; - - if (n_blocks_count < o_blocks_count) { - ext3_warning(sb, __FUNCTION__, - "can't shrink FS - resize aborted"); - return -EBUSY; - } - - /* Handle the remaining blocks in the last group only. */ - last = (o_blocks_count - le32_to_cpu(es->s_first_data_block)) % - EXT3_BLOCKS_PER_GROUP(sb); - - if (last == 0) { - ext3_warning(sb, __FUNCTION__, - "need to use ext2online to resize further\n"); - return -EPERM; - } - - add = EXT3_BLOCKS_PER_GROUP(sb) - last; - - if (o_blocks_count + add > n_blocks_count) - add = n_blocks_count - o_blocks_count; - - if (o_blocks_count + add < n_blocks_count) - ext3_warning(sb, __FUNCTION__, - "will only finish group (%lu blocks, %u new)", - o_blocks_count + add, add); - - /* See if the device is actually as big as what was requested */ - bh = sb_bread(sb, o_blocks_count + add -1); - if (!bh) { - ext3_warning(sb, __FUNCTION__, - "can't read last block, resize aborted"); - return -ENOSPC; - } - brelse(bh); - - /* Get a bogus inode to "free" the new blocks in this group. */ - if (!(inode = new_inode(sb))) { - ext3_warning(sb, __FUNCTION__, - "error getting dummy resize inode"); - return -ENOMEM; - } - inode->i_ino = 0; - - EXT3_I(inode)->i_state = EXT3_STATE_RESIZE; - - /* We will update the superblock, one block bitmap, and - * one group descriptor via ext3_free_blocks(). - */ - handle = ext3_journal_start(inode, 3); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - ext3_warning(sb, __FUNCTION__, "error %d on journal start",err); - goto exit_put; - } - - lock_super(sb); - if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) { - ext3_warning(sb, __FUNCTION__, - "multiple resizers run on filesystem!\n"); - err = -EBUSY; - goto exit_put; - } - - if ((err = ext3_journal_get_write_access(handle, - EXT3_SB(sb)->s_sbh))) { - ext3_warning(sb, __FUNCTION__, - "error %d on journal write access", err); - unlock_super(sb); - ext3_journal_stop(handle); - goto exit_put; - } - es->s_blocks_count = cpu_to_le32(o_blocks_count + add); - ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - sb->s_dirt = 1; - unlock_super(sb); - ext3_debug("freeing blocks %ld through %ld\n", o_blocks_count, - o_blocks_count + add); - ext3_free_blocks(handle, inode, o_blocks_count, add); - ext3_debug("freed blocks %ld through %ld\n", o_blocks_count, - o_blocks_count + add); - if ((err = ext3_journal_stop(handle))) - goto exit_put; - if (test_opt(sb, DEBUG)) - printk("EXT3-fs: extended group to %u blocks\n", - le32_to_cpu(es->s_blocks_count)); - update_backups(sb, inode, EXT3_SB(sb)->s_sbh->b_blocknr, (char *)es, - sizeof(struct ext3_super_block)); -exit_put: - iput(inode); - - return err; -} /* ext3_group_extend */ diff --git a/fs/hostfs/Makefile b/fs/hostfs/Makefile deleted file mode 100644 index 794292e0a..000000000 --- a/fs/hostfs/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -# Licensed under the GPL -# - -# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino -# to __st_ino. It stayed in the same place, so as long as the correct name -# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa. - -STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \ - echo __)st_ino - -hostfs-objs := hostfs_kern.o hostfs_user.o - -obj-y = -obj-$(CONFIG_HOSTFS) += hostfs.o - -SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) - -USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS)) -USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) - -USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD) - -$(USER_OBJS) : %.o: %.c - $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h deleted file mode 100644 index d1f6c339f..000000000 --- a/fs/hostfs/hostfs.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __UM_FS_HOSTFS -#define __UM_FS_HOSTFS - -#include "os.h" - -/* These are exactly the same definitions as in fs.h, but the names are - * changed so that this file can be included in both kernel and user files. - */ - -#define HOSTFS_ATTR_MODE 1 -#define HOSTFS_ATTR_UID 2 -#define HOSTFS_ATTR_GID 4 -#define HOSTFS_ATTR_SIZE 8 -#define HOSTFS_ATTR_ATIME 16 -#define HOSTFS_ATTR_MTIME 32 -#define HOSTFS_ATTR_CTIME 64 -#define HOSTFS_ATTR_ATIME_SET 128 -#define HOSTFS_ATTR_MTIME_SET 256 -#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */ -#define HOSTFS_ATTR_ATTR_FLAG 1024 - -struct hostfs_iattr { - unsigned int ia_valid; - mode_t ia_mode; - uid_t ia_uid; - gid_t ia_gid; - loff_t ia_size; - struct timespec ia_atime; - struct timespec ia_mtime; - struct timespec ia_ctime; - unsigned int ia_attr_flags; -}; - -extern int stat_file(const char *path, unsigned long long *inode_out, - int *mode_out, int *nlink_out, int *uid_out, int *gid_out, - unsigned long long *size_out, struct timespec *atime_out, - struct timespec *mtime_out, struct timespec *ctime_out, - int *blksize_out, unsigned long long *blocks_out); -extern int access_file(char *path, int r, int w, int x); -extern int open_file(char *path, int r, int w, int append); -extern int file_type(const char *path, int *rdev); -extern void *open_dir(char *path, int *err_out); -extern char *read_dir(void *stream, unsigned long long *pos, - unsigned long long *ino_out, int *len_out); -extern void close_file(void *stream); -extern void close_dir(void *stream); -extern int read_file(int fd, unsigned long long *offset, char *buf, int len); -extern int write_file(int fd, unsigned long long *offset, const char *buf, - int len); -extern int lseek_file(int fd, long long offset, int whence); -extern int file_create(char *name, int ur, int uw, int ux, int gr, - int gw, int gx, int or, int ow, int ox); -extern int set_attr(const char *file, struct hostfs_iattr *attrs); -extern int make_symlink(const char *from, const char *to); -extern int unlink_file(const char *file); -extern int do_mkdir(const char *file, int mode); -extern int do_rmdir(const char *file); -extern int do_mknod(const char *file, int mode, int dev); -extern int link_file(const char *from, const char *to); -extern int do_readlink(char *file, char *buf, int size); -extern int rename_file(char *from, char *to); -extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, - long long *bfree_out, long long *bavail_out, - long long *files_out, long long *ffree_out, - void *fsid_out, int fsid_size, long *namelen_out, - long *spare_out); - -#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/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c deleted file mode 100644 index ef5d5d1bf..000000000 --- a/fs/hostfs/hostfs_kern.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - * - * Ported the filesystem routines to 2.5. - * 2003-02-10 Petr Baudis - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hostfs.h" -#include "kern_util.h" -#include "kern.h" -#include "user_util.h" -#include "2_5compat.h" -#include "init.h" - -struct hostfs_inode_info { - char *host_filename; - int fd; - int mode; - struct inode vfs_inode; -}; - -static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) -{ - return(list_entry(inode, struct hostfs_inode_info, vfs_inode)); -} - -#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode) - -int hostfs_d_delete(struct dentry *dentry) -{ - return(1); -} - -struct dentry_operations hostfs_dentry_ops = { - .d_delete = hostfs_d_delete, -}; - -/* Changed in hostfs_args before the kernel starts running */ -static char *root_ino = "/"; -static int append = 0; - -#define HOSTFS_SUPER_MAGIC 0x00c0ffee - -static struct inode_operations hostfs_iops; -static struct inode_operations hostfs_dir_iops; -static struct address_space_operations hostfs_link_aops; - -static int __init hostfs_args(char *options, int *add) -{ - char *ptr; - - ptr = strchr(options, ','); - if(ptr != NULL) - *ptr++ = '\0'; - if(*options != '\0') - root_ino = options; - - options = ptr; - while(options){ - ptr = strchr(options, ','); - if(ptr != NULL) - *ptr++ = '\0'; - if(*options != '\0'){ - if(!strcmp(options, "append")) - append = 1; - else printf("hostfs_args - unsupported option - %s\n", - options); - } - options = ptr; - } - return(0); -} - -__uml_setup("hostfs=", hostfs_args, -"hostfs=,,...\n" -" This is used to set hostfs parameters. The root directory argument\n" -" is used to confine all hostfs mounts to within the specified directory\n" -" tree on the host. If this isn't specified, then a user inside UML can\n" -" mount anything on the host that's accessible to the user that's running\n" -" it.\n" -" The only flag currently supported is 'append', which specifies that all\n" -" files opened by hostfs will be opened in append mode.\n\n" -); - -static char *dentry_name(struct dentry *dentry, int extra) -{ - struct dentry *parent; - char *root, *name; - int len; - - len = 0; - parent = dentry; - while(parent->d_parent != parent){ - len += parent->d_name.len + 1; - parent = parent->d_parent; - } - - root = HOSTFS_I(parent->d_inode)->host_filename; - len += strlen(root); - name = kmalloc(len + extra + 1, GFP_KERNEL); - if(name == NULL) return(NULL); - - name[len] = '\0'; - parent = dentry; - while(parent->d_parent != parent){ - len -= parent->d_name.len + 1; - name[len] = '/'; - strncpy(&name[len + 1], parent->d_name.name, - parent->d_name.len); - parent = parent->d_parent; - } - strncpy(name, root, strlen(root)); - return(name); -} - -static char *inode_name(struct inode *ino, int extra) -{ - struct dentry *dentry; - - dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias); - return(dentry_name(dentry, extra)); -} - -static int read_name(struct inode *ino, char *name) -{ - /* The non-int inode fields are copied into ints by stat_file and - * then copied into the inode because passing the actual pointers - * in and having them treated as int * breaks on big-endian machines - */ - int err; - int i_mode, i_nlink, i_blksize; - unsigned long long i_size; - unsigned long long i_ino; - unsigned long long i_blocks; - - err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, - &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, - &ino->i_ctime, &i_blksize, &i_blocks); - if(err) - return(err); - - ino->i_ino = i_ino; - ino->i_mode = i_mode; - ino->i_nlink = i_nlink; - ino->i_size = i_size; - ino->i_blksize = i_blksize; - ino->i_blocks = i_blocks; - if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid())) - ino->i_uid = 0; - return(0); -} - -static char *follow_link(char *link) -{ - int len, n; - char *name, *resolved, *end; - - len = 64; - while(1){ - n = -ENOMEM; - name = kmalloc(len, GFP_KERNEL); - if(name == NULL) - goto out; - - n = do_readlink(link, name, len); - if(n < len) - break; - len *= 2; - kfree(name); - } - if(n < 0) - goto out_free; - - if(*name == '/') - return(name); - - end = strrchr(link, '/'); - if(end == NULL) - return(name); - - *(end + 1) = '\0'; - len = strlen(link) + strlen(name) + 1; - - resolved = kmalloc(len, GFP_KERNEL); - if(resolved == NULL){ - n = -ENOMEM; - goto out_free; - } - - sprintf(resolved, "%s%s", link, name); - kfree(name); - kfree(link); - return(resolved); - - out_free: - kfree(name); - out: - return(ERR_PTR(n)); -} - -static int read_inode(struct inode *ino) -{ - char *name; - int err = 0; - - /* Unfortunately, we are called from iget() when we don't have a dentry - * allocated yet. - */ - if(list_empty(&ino->i_dentry)) - goto out; - - err = -ENOMEM; - name = inode_name(ino, 0); - if(name == NULL) - goto out; - - if(file_type(name, NULL) == OS_TYPE_SYMLINK){ - name = follow_link(name); - if(IS_ERR(name)){ - err = PTR_ERR(name); - goto out; - } - } - - err = read_name(ino, name); - kfree(name); - out: - return(err); -} - -int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) -{ - /* do_statfs uses struct statfs64 internally, but the linux kernel - * struct statfs still has 32-bit versions for most of these fields, - * so we convert them here - */ - int err; - long long f_blocks; - long long f_bfree; - long long f_bavail; - long long f_files; - long long f_ffree; - - err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, - &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, - &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), - &sf->f_namelen, sf->f_spare); - if(err) return(err); - sf->f_blocks = f_blocks; - sf->f_bfree = f_bfree; - sf->f_bavail = f_bavail; - sf->f_files = f_files; - sf->f_ffree = f_ffree; - sf->f_type = HOSTFS_SUPER_MAGIC; - return(0); -} - -static struct inode *hostfs_alloc_inode(struct super_block *sb) -{ - struct hostfs_inode_info *hi; - - hi = kmalloc(sizeof(*hi), GFP_KERNEL); - if(hi == NULL) - return(NULL); - - *hi = ((struct hostfs_inode_info) { .host_filename = NULL, - .fd = -1, - .mode = 0 }); - inode_init_once(&hi->vfs_inode); - return(&hi->vfs_inode); -} - -static void hostfs_destroy_inode(struct inode *inode) -{ - if(HOSTFS_I(inode)->host_filename) - kfree(HOSTFS_I(inode)->host_filename); - - if(HOSTFS_I(inode)->fd != -1) - close_file(&HOSTFS_I(inode)->fd); - - kfree(HOSTFS_I(inode)); -} - -static void hostfs_read_inode(struct inode *inode) -{ - read_inode(inode); -} - -static struct super_operations hostfs_sbops = { - .alloc_inode = hostfs_alloc_inode, - .destroy_inode = hostfs_destroy_inode, - .read_inode = hostfs_read_inode, - .statfs = hostfs_statfs, -}; - -int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) -{ - void *dir; - char *name; - unsigned long long next, ino; - int error, len; - - name = dentry_name(file->f_dentry, 0); - if(name == NULL) return(-ENOMEM); - dir = open_dir(name, &error); - kfree(name); - if(dir == NULL) return(-error); - next = file->f_pos; - while((name = read_dir(dir, &next, &ino, &len)) != NULL){ - error = (*filldir)(ent, name, len, file->f_pos, - ino, DT_UNKNOWN); - if(error) break; - file->f_pos = next; - } - close_dir(dir); - return(0); -} - -int hostfs_file_open(struct inode *ino, struct file *file) -{ - char *name; - int mode = 0, r = 0, w = 0, fd; - - mode = file->f_mode & (FMODE_READ | FMODE_WRITE); - if((mode & HOSTFS_I(ino)->mode) == mode) - return(0); - - /* The file may already have been opened, but with the wrong access, - * so this resets things and reopens the file with the new access. - */ - if(HOSTFS_I(ino)->fd != -1){ - close_file(&HOSTFS_I(ino)->fd); - HOSTFS_I(ino)->fd = -1; - } - - HOSTFS_I(ino)->mode |= mode; - if(HOSTFS_I(ino)->mode & FMODE_READ) - r = 1; - if(HOSTFS_I(ino)->mode & FMODE_WRITE) - w = 1; - if(w) - r = 1; - - name = dentry_name(file->f_dentry, 0); - if(name == NULL) - return(-ENOMEM); - - fd = open_file(name, r, w, append); - kfree(name); - if(fd < 0) return(fd); - FILE_HOSTFS_I(file)->fd = fd; - - return(0); -} - -int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - return(0); -} - -static struct file_operations hostfs_file_fops = { - .llseek = generic_file_llseek, - .read = generic_file_read, - .write = generic_file_write, - .mmap = generic_file_mmap, - .open = hostfs_file_open, - .release = NULL, - .fsync = hostfs_fsync, -}; - -static struct file_operations hostfs_dir_fops = { - .readdir = hostfs_readdir, - .read = generic_read_dir, -}; - -int hostfs_writepage(struct page *page, struct writeback_control *wbc) -{ - struct address_space *mapping = page->mapping; - struct inode *inode = mapping->host; - char *buffer; - unsigned long long base; - int count = PAGE_CACHE_SIZE; - int end_index = inode->i_size >> PAGE_CACHE_SHIFT; - int err; - - if (page->index >= end_index) - count = inode->i_size & (PAGE_CACHE_SIZE-1); - - buffer = kmap(page); - base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; - - err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count); - if(err != count){ - ClearPageUptodate(page); - goto out; - } - - if (base > inode->i_size) - inode->i_size = base; - - if (PageError(page)) - ClearPageError(page); - err = 0; - - out: - kunmap(page); - - unlock_page(page); - return err; -} - -int hostfs_readpage(struct file *file, struct page *page) -{ - char *buffer; - long long start; - int err = 0; - - start = (long long) page->index << PAGE_CACHE_SHIFT; - buffer = kmap(page); - err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, - PAGE_CACHE_SIZE); - if(err < 0) goto out; - - memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); - - flush_dcache_page(page); - SetPageUptodate(page); - if (PageError(page)) ClearPageError(page); - err = 0; - out: - kunmap(page); - unlock_page(page); - return(err); -} - -int hostfs_prepare_write(struct file *file, struct page *page, - unsigned int from, unsigned int to) -{ - char *buffer; - long long start, tmp; - int err; - - start = (long long) page->index << PAGE_CACHE_SHIFT; - buffer = kmap(page); - if(from != 0){ - tmp = start; - err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer, - from); - if(err < 0) goto out; - } - if(to != PAGE_CACHE_SIZE){ - start += to; - err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to, - PAGE_CACHE_SIZE - to); - if(err < 0) goto out; - } - err = 0; - out: - kunmap(page); - return(err); -} - -int hostfs_commit_write(struct file *file, struct page *page, unsigned from, - unsigned to) -{ - struct address_space *mapping = page->mapping; - struct inode *inode = mapping->host; - char *buffer; - long long start; - int err = 0; - - start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; - buffer = kmap(page); - err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from, - to - from); - if(err > 0) err = 0; - if(!err && (start > inode->i_size)) - inode->i_size = start; - - kunmap(page); - return(err); -} - -static struct address_space_operations hostfs_aops = { - .writepage = hostfs_writepage, - .readpage = hostfs_readpage, -/* .set_page_dirty = __set_page_dirty_nobuffers, */ - .prepare_write = hostfs_prepare_write, - .commit_write = hostfs_commit_write -}; - -static int init_inode(struct inode *inode, struct dentry *dentry) -{ - char *name; - int type, err = -ENOMEM, rdev; - - if(dentry){ - name = dentry_name(dentry, 0); - if(name == NULL) - goto out; - type = file_type(name, &rdev); - kfree(name); - } - else type = OS_TYPE_DIR; - - err = 0; - if(type == OS_TYPE_SYMLINK) - inode->i_op = &page_symlink_inode_operations; - else if(type == OS_TYPE_DIR) - inode->i_op = &hostfs_dir_iops; - else inode->i_op = &hostfs_iops; - - if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops; - else inode->i_fop = &hostfs_file_fops; - - if(type == OS_TYPE_SYMLINK) - inode->i_mapping->a_ops = &hostfs_link_aops; - else inode->i_mapping->a_ops = &hostfs_aops; - - switch (type) { - case OS_TYPE_CHARDEV: - init_special_inode(inode, S_IFCHR, rdev); - break; - case OS_TYPE_BLOCKDEV: - init_special_inode(inode, S_IFBLK, rdev); - break; - case OS_TYPE_FIFO: - init_special_inode(inode, S_IFIFO, 0); - break; - case OS_TYPE_SOCK: - init_special_inode(inode, S_IFSOCK, 0); - break; - } - out: - return(err); -} - -int hostfs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) -{ - struct inode *inode; - char *name; - int error, fd; - - error = -ENOMEM; - inode = iget(dir->i_sb, 0); - if(inode == NULL) goto out; - - error = init_inode(inode, dentry); - if(error) - goto out_put; - - error = -ENOMEM; - name = dentry_name(dentry, 0); - if(name == NULL) - goto out_put; - - fd = file_create(name, - mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, - mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, - mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH); - if(fd < 0) - error = fd; - else error = read_name(inode, name); - - kfree(name); - if(error) - goto out_put; - - HOSTFS_I(inode)->fd = fd; - HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE; - d_instantiate(dentry, inode); - return(0); - - out_put: - iput(inode); - out: - return(error); -} - -struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, - struct nameidata *nd) -{ - struct inode *inode; - char *name; - int err; - - err = -ENOMEM; - inode = iget(ino->i_sb, 0); - if(inode == NULL) - goto out; - - err = init_inode(inode, dentry); - if(err) - goto out_put; - - err = -ENOMEM; - name = dentry_name(dentry, 0); - if(name == NULL) - goto out_put; - - err = read_name(inode, name); - kfree(name); - if(err == -ENOENT){ - iput(inode); - inode = NULL; - } - else if(err) - goto out_put; - - d_add(dentry, inode); - dentry->d_op = &hostfs_dentry_ops; - return(NULL); - - out_put: - iput(inode); - out: - return(ERR_PTR(err)); -} - -static char *inode_dentry_name(struct inode *ino, struct dentry *dentry) -{ - char *file; - int len; - - file = inode_name(ino, dentry->d_name.len + 1); - if(file == NULL) return(NULL); - strcat(file, "/"); - len = strlen(file); - strncat(file, dentry->d_name.name, dentry->d_name.len); - file[len + dentry->d_name.len] = '\0'; - return(file); -} - -int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) -{ - char *from_name, *to_name; - int err; - - if((from_name = inode_dentry_name(ino, from)) == NULL) - return(-ENOMEM); - to_name = dentry_name(to, 0); - if(to_name == NULL){ - kfree(from_name); - return(-ENOMEM); - } - err = link_file(to_name, from_name); - kfree(from_name); - kfree(to_name); - return(err); -} - -int hostfs_unlink(struct inode *ino, struct dentry *dentry) -{ - char *file; - int err; - - if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); - if(append) - return(-EPERM); - - err = unlink_file(file); - kfree(file); - return(err); -} - -int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) -{ - char *file; - int err; - - if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); - err = make_symlink(file, to); - kfree(file); - return(err); -} - -int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode) -{ - char *file; - int err; - - if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); - err = do_mkdir(file, mode); - kfree(file); - return(err); -} - -int hostfs_rmdir(struct inode *ino, struct dentry *dentry) -{ - char *file; - int err; - - if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); - err = do_rmdir(file); - kfree(file); - return(err); -} - -int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - struct inode *inode; - char *name; - int err = -ENOMEM; - - inode = iget(dir->i_sb, 0); - if(inode == NULL) - goto out; - - err = init_inode(inode, dentry); - if(err) - goto out_put; - - err = -ENOMEM; - name = dentry_name(dentry, 0); - if(name == NULL) - goto out_put; - - init_special_inode(inode, mode, dev); - err = do_mknod(name, mode, dev); - if(err) - goto out_free; - - err = read_name(inode, name); - kfree(name); - if(err) - goto out_put; - - d_instantiate(dentry, inode); - return(0); - - out_free: - kfree(name); - out_put: - iput(inode); - out: - return(err); -} - -int hostfs_rename(struct inode *from_ino, struct dentry *from, - struct inode *to_ino, struct dentry *to) -{ - char *from_name, *to_name; - int err; - - if((from_name = inode_dentry_name(from_ino, from)) == NULL) - return(-ENOMEM); - if((to_name = inode_dentry_name(to_ino, to)) == NULL){ - kfree(from_name); - return(-ENOMEM); - } - err = rename_file(from_name, to_name); - kfree(from_name); - kfree(to_name); - return(err); -} - -void hostfs_truncate(struct inode *ino) -{ - not_implemented(); -} - -int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) -{ - char *name; - int r = 0, w = 0, x = 0, err; - - if(desired & MAY_READ) r = 1; - if(desired & MAY_WRITE) w = 1; - if(desired & MAY_EXEC) x = 1; - name = inode_name(ino, 0); - if(name == NULL) return(-ENOMEM); - err = access_file(name, r, w, x); - kfree(name); - if(!err) err = vfs_permission(ino, desired); - return(err); -} - -int hostfs_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct hostfs_iattr attrs; - char *name; - int err; - - if(append) - attr->ia_valid &= ~ATTR_SIZE; - - attrs.ia_valid = 0; - if(attr->ia_valid & ATTR_MODE){ - attrs.ia_valid |= HOSTFS_ATTR_MODE; - attrs.ia_mode = attr->ia_mode; - } - if(attr->ia_valid & ATTR_UID){ - if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && - (attr->ia_uid == 0)) - attr->ia_uid = getuid(); - attrs.ia_valid |= HOSTFS_ATTR_UID; - attrs.ia_uid = attr->ia_uid; - } - if(attr->ia_valid & ATTR_GID){ - if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && - (attr->ia_gid == 0)) - attr->ia_gid = getuid(); - attrs.ia_valid |= HOSTFS_ATTR_GID; - attrs.ia_gid = attr->ia_gid; - } - if(attr->ia_valid & ATTR_SIZE){ - attrs.ia_valid |= HOSTFS_ATTR_SIZE; - attrs.ia_size = attr->ia_size; - } - if(attr->ia_valid & ATTR_ATIME){ - attrs.ia_valid |= HOSTFS_ATTR_ATIME; - attrs.ia_atime = attr->ia_atime; - } - if(attr->ia_valid & ATTR_MTIME){ - attrs.ia_valid |= HOSTFS_ATTR_MTIME; - attrs.ia_mtime = attr->ia_mtime; - } - if(attr->ia_valid & ATTR_CTIME){ - attrs.ia_valid |= HOSTFS_ATTR_CTIME; - attrs.ia_ctime = attr->ia_ctime; - } - if(attr->ia_valid & ATTR_ATIME_SET){ - attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET; - } - if(attr->ia_valid & ATTR_MTIME_SET){ - attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET; - } - name = dentry_name(dentry, 0); - if(name == NULL) return(-ENOMEM); - err = set_attr(name, &attrs); - kfree(name); - if(err) - return(err); - - return(inode_setattr(dentry->d_inode, attr)); -} - -int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - generic_fillattr(dentry->d_inode, stat); - return(0); -} - -static struct inode_operations hostfs_iops = { - .create = hostfs_create, - .link = hostfs_link, - .unlink = hostfs_unlink, - .symlink = hostfs_symlink, - .mkdir = hostfs_mkdir, - .rmdir = hostfs_rmdir, - .mknod = hostfs_mknod, - .rename = hostfs_rename, - .truncate = hostfs_truncate, - .permission = hostfs_permission, - .setattr = hostfs_setattr, - .getattr = hostfs_getattr, -}; - -static struct inode_operations hostfs_dir_iops = { - .create = hostfs_create, - .lookup = hostfs_lookup, - .link = hostfs_link, - .unlink = hostfs_unlink, - .symlink = hostfs_symlink, - .mkdir = hostfs_mkdir, - .rmdir = hostfs_rmdir, - .mknod = hostfs_mknod, - .rename = hostfs_rename, - .truncate = hostfs_truncate, - .permission = hostfs_permission, - .setattr = hostfs_setattr, - .getattr = hostfs_getattr, -}; - -int hostfs_link_readpage(struct file *file, struct page *page) -{ - char *buffer, *name; - long long start; - int err; - - start = page->index << PAGE_CACHE_SHIFT; - buffer = kmap(page); - name = inode_name(page->mapping->host, 0); - if(name == NULL) return(-ENOMEM); - err = do_readlink(name, buffer, PAGE_CACHE_SIZE); - kfree(name); - if(err == PAGE_CACHE_SIZE) - err = -E2BIG; - else if(err > 0){ - flush_dcache_page(page); - SetPageUptodate(page); - if (PageError(page)) ClearPageError(page); - err = 0; - } - kunmap(page); - unlock_page(page); - return(err); -} - -static struct address_space_operations hostfs_link_aops = { - .readpage = hostfs_link_readpage, -}; - -static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) -{ - struct inode *root_inode; - char *name, *data = d; - int err; - - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; - sb->s_magic = HOSTFS_SUPER_MAGIC; - sb->s_op = &hostfs_sbops; - - if((data == NULL) || (*data == '\0')) - data = root_ino; - - err = -ENOMEM; - name = kmalloc(strlen(data) + 1, GFP_KERNEL); - if(name == NULL) - goto out; - - strcpy(name, data); - - root_inode = iget(sb, 0); - if(root_inode == NULL) - goto out_free; - - err = init_inode(root_inode, NULL); - if(err) - goto out_put; - - HOSTFS_I(root_inode)->host_filename = name; - - err = -ENOMEM; - sb->s_root = d_alloc_root(root_inode); - if(sb->s_root == NULL) - goto out_put; - - err = read_inode(root_inode); - if(err) - goto out_put; - - return(0); - - out_put: - iput(root_inode); - out_free: - kfree(name); - out: - return(err); -} - -static struct super_block *hostfs_read_sb(struct file_system_type *type, - int flags, const char *dev_name, - void *data) -{ - return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); -} - -static struct file_system_type hostfs_type = { - .owner = THIS_MODULE, - .name = "hostfs", - .get_sb = hostfs_read_sb, - .kill_sb = kill_anon_super, - .fs_flags = 0, -}; - -static int __init init_hostfs(void) -{ - return(register_filesystem(&hostfs_type)); -} - -static void __exit exit_hostfs(void) -{ - unregister_filesystem(&hostfs_type); -} - -module_init(init_hostfs) -module_exit(exit_hostfs) -MODULE_LICENSE("GPL"); - -/* - * 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/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c deleted file mode 100644 index c40626609..000000000 --- a/fs/hostfs/hostfs_user.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hostfs.h" -#include "kern_util.h" -#include "user.h" - -int stat_file(const char *path, unsigned long long *inode_out, int *mode_out, - int *nlink_out, int *uid_out, int *gid_out, - unsigned long long *size_out, struct timespec *atime_out, - struct timespec *mtime_out, struct timespec *ctime_out, - int *blksize_out, unsigned long long *blocks_out) -{ - struct stat64 buf; - - if(lstat64(path, &buf) < 0) - return(-errno); - - /* See the Makefile for why STAT64_INO_FIELD is passed in - * by the build - */ - if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD; - if(mode_out != NULL) *mode_out = buf.st_mode; - if(nlink_out != NULL) *nlink_out = buf.st_nlink; - if(uid_out != NULL) *uid_out = buf.st_uid; - if(gid_out != NULL) *gid_out = buf.st_gid; - if(size_out != NULL) *size_out = buf.st_size; - if(atime_out != NULL) { - atime_out->tv_sec = buf.st_atime; - atime_out->tv_nsec = 0; - } - if(mtime_out != NULL) { - mtime_out->tv_sec = buf.st_mtime; - mtime_out->tv_nsec = 0; - } - if(ctime_out != NULL) { - ctime_out->tv_sec = buf.st_ctime; - ctime_out->tv_nsec = 0; - } - if(blksize_out != NULL) *blksize_out = buf.st_blksize; - if(blocks_out != NULL) *blocks_out = buf.st_blocks; - return(0); -} - -int file_type(const char *path, int *rdev) -{ - struct stat64 buf; - - if(lstat64(path, &buf) < 0) - return(-errno); - if(rdev != NULL) - *rdev = buf.st_rdev; - - if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); - else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); - else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); - else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); - else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO); - else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK); - else return(OS_TYPE_FILE); -} - -int access_file(char *path, int r, int w, int x) -{ - int mode = 0; - - if(r) mode = R_OK; - if(w) mode |= W_OK; - if(x) mode |= X_OK; - if(access(path, mode) != 0) return(-errno); - else return(0); -} - -int open_file(char *path, int r, int w, int append) -{ - int mode = 0, fd; - - if(r && !w) - mode = O_RDONLY; - else if(!r && w) - mode = O_WRONLY; - else if(r && w) - mode = O_RDWR; - else panic("Impossible mode in open_file"); - - if(append) - mode |= O_APPEND; - fd = open64(path, mode); - if(fd < 0) return(-errno); - else return(fd); -} - -void *open_dir(char *path, int *err_out) -{ - DIR *dir; - - dir = opendir(path); - *err_out = errno; - if(dir == NULL) return(NULL); - return(dir); -} - -char *read_dir(void *stream, unsigned long long *pos, - unsigned long long *ino_out, int *len_out) -{ - DIR *dir = stream; - struct dirent *ent; - - seekdir(dir, *pos); - ent = readdir(dir); - if(ent == NULL) return(NULL); - *len_out = strlen(ent->d_name); - *ino_out = ent->d_ino; - *pos = telldir(dir); - return(ent->d_name); -} - -int read_file(int fd, unsigned long long *offset, char *buf, int len) -{ - int n; - - n = pread64(fd, buf, len, *offset); - if(n < 0) return(-errno); - *offset += n; - return(n); -} - -int write_file(int fd, unsigned long long *offset, const char *buf, int len) -{ - int n; - - n = pwrite64(fd, buf, len, *offset); - if(n < 0) return(-errno); - *offset += n; - return(n); -} - -int lseek_file(int fd, long long offset, int whence) -{ - int ret; - - ret = lseek64(fd, offset, whence); - if(ret < 0) return(-errno); - return(0); -} - -void close_file(void *stream) -{ - close(*((int *) stream)); -} - -void close_dir(void *stream) -{ - closedir(stream); -} - -int file_create(char *name, int ur, int uw, int ux, int gr, - int gw, int gx, int or, int ow, int ox) -{ - int mode, fd; - - mode = 0; - mode |= ur ? S_IRUSR : 0; - mode |= uw ? S_IWUSR : 0; - mode |= ux ? S_IXUSR : 0; - mode |= gr ? S_IRGRP : 0; - mode |= gw ? S_IWGRP : 0; - mode |= gx ? S_IXGRP : 0; - mode |= or ? S_IROTH : 0; - mode |= ow ? S_IWOTH : 0; - mode |= ox ? S_IXOTH : 0; - fd = open64(name, O_CREAT | O_RDWR, mode); - if(fd < 0) - return(-errno); - return(fd); -} - -int set_attr(const char *file, struct hostfs_iattr *attrs) -{ - struct utimbuf buf; - int err, ma; - - if(attrs->ia_valid & HOSTFS_ATTR_MODE){ - if(chmod(file, attrs->ia_mode) != 0) return(-errno); - } - if(attrs->ia_valid & HOSTFS_ATTR_UID){ - if(chown(file, attrs->ia_uid, -1)) return(-errno); - } - if(attrs->ia_valid & HOSTFS_ATTR_GID){ - if(chown(file, -1, attrs->ia_gid)) return(-errno); - } - if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ - if(truncate(file, attrs->ia_size)) return(-errno); - } - ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; - if((attrs->ia_valid & ma) == ma){ - buf.actime = attrs->ia_atime.tv_sec; - buf.modtime = attrs->ia_mtime.tv_sec; - if(utime(file, &buf) != 0) return(-errno); - } - else { - struct timespec ts; - - if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ - err = stat_file(file, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &ts, NULL, NULL, NULL); - if(err != 0) - return(err); - buf.actime = attrs->ia_atime.tv_sec; - buf.modtime = ts.tv_sec; - if(utime(file, &buf) != 0) - return(-errno); - } - if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ - err = stat_file(file, NULL, NULL, NULL, NULL, NULL, - NULL, &ts, NULL, NULL, NULL, NULL); - if(err != 0) - return(err); - buf.actime = ts.tv_sec; - buf.modtime = attrs->ia_mtime.tv_sec; - if(utime(file, &buf) != 0) - return(-errno); - } - } - if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; - if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ - err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, - &attrs->ia_atime, &attrs->ia_mtime, NULL, - NULL, NULL); - if(err != 0) return(err); - } - return(0); -} - -int make_symlink(const char *from, const char *to) -{ - int err; - - err = symlink(to, from); - if(err) return(-errno); - return(0); -} - -int unlink_file(const char *file) -{ - int err; - - err = unlink(file); - if(err) return(-errno); - return(0); -} - -int do_mkdir(const char *file, int mode) -{ - int err; - - err = mkdir(file, mode); - if(err) return(-errno); - return(0); -} - -int do_rmdir(const char *file) -{ - int err; - - err = rmdir(file); - if(err) return(-errno); - return(0); -} - -int do_mknod(const char *file, int mode, int dev) -{ - int err; - - err = mknod(file, mode, dev); - if(err) return(-errno); - return(0); -} - -int link_file(const char *to, const char *from) -{ - int err; - - err = link(to, from); - if(err) return(-errno); - return(0); -} - -int do_readlink(char *file, char *buf, int size) -{ - int n; - - n = readlink(file, buf, size); - if(n < 0) - return(-errno); - if(n < size) - buf[n] = '\0'; - return(n); -} - -int rename_file(char *from, char *to) -{ - int err; - - err = rename(from, to); - if(err < 0) return(-errno); - return(0); -} - -int do_statfs(char *root, long *bsize_out, long long *blocks_out, - long long *bfree_out, long long *bavail_out, - long long *files_out, long long *ffree_out, - void *fsid_out, int fsid_size, long *namelen_out, - long *spare_out) -{ - struct statfs64 buf; - int err; - - err = statfs64(root, &buf); - if(err < 0) return(-errno); - *bsize_out = buf.f_bsize; - *blocks_out = buf.f_blocks; - *bfree_out = buf.f_bfree; - *bavail_out = buf.f_bavail; - *files_out = buf.f_files; - *ffree_out = buf.f_ffree; - memcpy(fsid_out, &buf.f_fsid, - sizeof(buf.f_fsid) > fsid_size ? fsid_size : - sizeof(buf.f_fsid)); - *namelen_out = buf.f_namelen; - spare_out[0] = buf.f_spare[0]; - spare_out[1] = buf.f_spare[1]; - spare_out[2] = buf.f_spare[2]; - spare_out[3] = buf.f_spare[3]; - spare_out[4] = buf.f_spare[4]; - spare_out[5] = buf.f_spare[5]; - 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/fs/hppfs/Makefile b/fs/hppfs/Makefile deleted file mode 100644 index e67f03848..000000000 --- a/fs/hppfs/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com) -# Licensed under the GPL -# - -hppfs-objs := hppfs_kern.o - -obj-y = -obj-$(CONFIG_HPPFS) += hppfs.o - -clean: - -modules: - -fastdep: - -dep: - -archmrproper: clean diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c deleted file mode 100644 index ebf08cb55..000000000 --- a/fs/hppfs/hppfs_kern.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "os.h" - -static int init_inode(struct inode *inode, struct dentry *dentry); - -struct hppfs_data { - struct list_head list; - char contents[PAGE_SIZE - sizeof(struct list_head)]; -}; - -struct hppfs_private { - struct file proc_file; - int host_fd; - loff_t len; - struct hppfs_data *contents; -}; - -struct hppfs_inode_info { - struct dentry *proc_dentry; - struct inode vfs_inode; -}; - -static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) -{ - return(list_entry(inode, struct hppfs_inode_info, vfs_inode)); -} - -#define HPPFS_SUPER_MAGIC 0xb00000ee - -static struct super_operations hppfs_sbops; - -static int is_pid(struct dentry *dentry) -{ - struct super_block *sb; - int i; - - sb = dentry->d_sb; - if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) - return(0); - - for(i = 0; i < dentry->d_name.len; i++){ - if(!isdigit(dentry->d_name.name[i])) - return(0); - } - return(1); -} - -static char *dentry_name(struct dentry *dentry, int extra) -{ - struct dentry *parent; - char *root, *name; - const char *seg_name; - int len, seg_len; - - len = 0; - parent = dentry; - while(parent->d_parent != parent){ - if(is_pid(parent)) - len += strlen("pid") + 1; - else len += parent->d_name.len + 1; - parent = parent->d_parent; - } - - root = "proc"; - len += strlen(root); - name = kmalloc(len + extra + 1, GFP_KERNEL); - if(name == NULL) return(NULL); - - name[len] = '\0'; - parent = dentry; - while(parent->d_parent != parent){ - if(is_pid(parent)){ - seg_name = "pid"; - seg_len = strlen("pid"); - } - else { - seg_name = parent->d_name.name; - seg_len = parent->d_name.len; - } - - len -= seg_len + 1; - name[len] = '/'; - strncpy(&name[len + 1], seg_name, seg_len); - parent = parent->d_parent; - } - strncpy(name, root, strlen(root)); - return(name); -} - -struct dentry_operations hppfs_dentry_ops = { -}; - -static int file_removed(struct dentry *dentry, const char *file) -{ - char *host_file; - int extra, fd; - - extra = 0; - if(file != NULL) extra += strlen(file) + 1; - - host_file = dentry_name(dentry, extra + strlen("/remove")); - if(host_file == NULL){ - printk("file_removed : allocation failed\n"); - return(-ENOMEM); - } - - if(file != NULL){ - strcat(host_file, "/"); - strcat(host_file, file); - } - strcat(host_file, "/remove"); - - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); - kfree(host_file); - if(fd > 0){ - os_close_file(fd); - return(1); - } - return(0); -} - -static void hppfs_read_inode(struct inode *ino) -{ - struct inode *proc_ino; - - if(HPPFS_I(ino)->proc_dentry == NULL) - return; - - proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; - ino->i_uid = proc_ino->i_uid; - ino->i_gid = proc_ino->i_gid; - ino->i_atime = proc_ino->i_atime; - ino->i_mtime = proc_ino->i_mtime; - ino->i_ctime = proc_ino->i_ctime; - ino->i_ino = proc_ino->i_ino; - ino->i_mode = proc_ino->i_mode; - ino->i_nlink = proc_ino->i_nlink; - ino->i_size = proc_ino->i_size; - ino->i_blksize = proc_ino->i_blksize; - ino->i_blocks = proc_ino->i_blocks; -} - -static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, - struct nameidata *nd) -{ - struct dentry *proc_dentry, *new, *parent; - struct inode *inode; - int err, deleted; - - deleted = file_removed(dentry, NULL); - if(deleted < 0) - return(ERR_PTR(deleted)); - else if(deleted) - return(ERR_PTR(-ENOENT)); - - err = -ENOMEM; - parent = HPPFS_I(ino)->proc_dentry; - down(&parent->d_inode->i_sem); - proc_dentry = d_lookup(parent, &dentry->d_name); - if(proc_dentry == NULL){ - proc_dentry = d_alloc(parent, &dentry->d_name); - if(proc_dentry == NULL){ - up(&parent->d_inode->i_sem); - goto out; - } - new = (*parent->d_inode->i_op->lookup)(parent->d_inode, - proc_dentry, NULL); - if(new){ - dput(proc_dentry); - proc_dentry = new; - } - } - up(&parent->d_inode->i_sem); - - if(IS_ERR(proc_dentry)) - return(proc_dentry); - - inode = iget(ino->i_sb, 0); - if(inode == NULL) - goto out_dput; - - err = init_inode(inode, proc_dentry); - if(err) - goto out_put; - - hppfs_read_inode(inode); - - d_add(dentry, inode); - dentry->d_op = &hppfs_dentry_ops; - return(NULL); - - out_put: - iput(inode); - out_dput: - dput(proc_dentry); - out: - return(ERR_PTR(err)); -} - -static struct inode_operations hppfs_file_iops = { -}; - -static ssize_t read_proc(struct file *file, char *buf, ssize_t count, - loff_t *ppos, int is_user) -{ - ssize_t (*read)(struct file *, char *, size_t, loff_t *); - ssize_t n; - - read = file->f_dentry->d_inode->i_fop->read; - - if(!is_user) - set_fs(KERNEL_DS); - - n = (*read)(file, buf, count, &file->f_pos); - - if(!is_user) - set_fs(USER_DS); - - if(ppos) *ppos = file->f_pos; - return(n); -} - -static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) -{ - ssize_t n; - int cur, err; - char *new_buf; - - n = -ENOMEM; - new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if(new_buf == NULL){ - printk("hppfs_read_file : kmalloc failed\n"); - goto out; - } - n = 0; - while(count > 0){ - cur = min_t(ssize_t, count, PAGE_SIZE); - err = os_read_file(fd, new_buf, cur); - if(err < 0){ - printk("hppfs_read : read failed, errno = %d\n", - count); - n = err; - goto out_free; - } - else if(err == 0) - break; - - if(copy_to_user(buf, new_buf, err)){ - n = -EFAULT; - goto out_free; - } - n += err; - count -= err; - } - out_free: - kfree(new_buf); - out: - return(n); -} - -static ssize_t hppfs_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - struct hppfs_private *hppfs = file->private_data; - struct hppfs_data *data; - loff_t off; - int err; - - if(hppfs->contents != NULL){ - if(*ppos >= hppfs->len) return(0); - - data = hppfs->contents; - off = *ppos; - while(off >= sizeof(data->contents)){ - data = list_entry(data->list.next, struct hppfs_data, - list); - off -= sizeof(data->contents); - } - - if(off + count > hppfs->len) - count = hppfs->len - off; - copy_to_user(buf, &data->contents[off], count); - *ppos += count; - } - else if(hppfs->host_fd != -1){ - err = os_seek_file(hppfs->host_fd, *ppos); - if(err){ - printk("hppfs_read : seek failed, errno = %d\n", err); - return(err); - } - count = hppfs_read_file(hppfs->host_fd, buf, count); - if(count > 0) - *ppos += count; - } - else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1); - - return(count); -} - -static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, - loff_t *ppos) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = &data->proc_file; - ssize_t (*write)(struct file *, const char *, size_t, loff_t *); - int err; - - write = proc_file->f_dentry->d_inode->i_fop->write; - - proc_file->f_pos = file->f_pos; - err = (*write)(proc_file, buf, len, &proc_file->f_pos); - file->f_pos = proc_file->f_pos; - - return(err); -} - -static int open_host_sock(char *host_file, int *filter_out) -{ - char *end; - int fd; - - end = &host_file[strlen(host_file)]; - strcpy(end, "/rw"); - *filter_out = 1; - fd = os_connect_socket(host_file); - if(fd > 0) - return(fd); - - strcpy(end, "/r"); - *filter_out = 0; - fd = os_connect_socket(host_file); - return(fd); -} - -static void free_contents(struct hppfs_data *head) -{ - struct hppfs_data *data; - struct list_head *ele, *next; - - if(head == NULL) return; - - list_for_each_safe(ele, next, &head->list){ - data = list_entry(ele, struct hppfs_data, list); - kfree(data); - } - kfree(head); -} - -static struct hppfs_data *hppfs_get_data(int fd, int filter, - struct file *proc_file, - struct file *hppfs_file, - loff_t *size_out) -{ - struct hppfs_data *data, *new, *head; - int n, err; - - err = -ENOMEM; - data = kmalloc(sizeof(*data), GFP_KERNEL); - if(data == NULL){ - printk("hppfs_get_data : head allocation failed\n"); - goto failed; - } - - INIT_LIST_HEAD(&data->list); - - head = data; - *size_out = 0; - - if(filter){ - while((n = read_proc(proc_file, data->contents, - sizeof(data->contents), NULL, 0)) > 0) - os_write_file(fd, data->contents, n); - err = os_shutdown_socket(fd, 0, 1); - if(err){ - printk("hppfs_get_data : failed to shut down " - "socket\n"); - goto failed_free; - } - } - while(1){ - n = os_read_file(fd, data->contents, sizeof(data->contents)); - if(n < 0){ - err = n; - printk("hppfs_get_data : read failed, errno = %d\n", - err); - goto failed_free; - } - else if(n == 0) - break; - - *size_out += n; - - if(n < sizeof(data->contents)) - break; - - new = kmalloc(sizeof(*data), GFP_KERNEL); - if(new == 0){ - printk("hppfs_get_data : data allocation failed\n"); - err = -ENOMEM; - goto failed_free; - } - - INIT_LIST_HEAD(&new->list); - list_add(&new->list, &data->list); - data = new; - } - return(head); - - failed_free: - free_contents(head); - failed: - return(ERR_PTR(err)); -} - -static struct hppfs_private *hppfs_data(void) -{ - struct hppfs_private *data; - - data = kmalloc(sizeof(*data), GFP_KERNEL); - if(data == NULL) - return(data); - - *data = ((struct hppfs_private ) { .host_fd = -1, - .len = -1, - .contents = NULL } ); - return(data); -} - -static int file_mode(int fmode) -{ - if(fmode == (FMODE_READ | FMODE_WRITE)) - return(O_RDWR); - if(fmode == FMODE_READ) - return(O_RDONLY); - if(fmode == FMODE_WRITE) - return(O_WRONLY); - return(0); -} - -static int hppfs_open(struct inode *inode, struct file *file) -{ - struct hppfs_private *data; - struct dentry *proc_dentry; - char *host_file; - int err, fd, type, filter; - - err = -ENOMEM; - data = hppfs_data(); - if(data == NULL) - goto out; - - host_file = dentry_name(file->f_dentry, strlen("/rw")); - if(host_file == NULL) - goto out_free2; - - proc_dentry = HPPFS_I(inode)->proc_dentry; - - /* XXX This isn't closed anywhere */ - err = open_private_file(&data->proc_file, proc_dentry, - file_mode(file->f_mode)); - if(err) - goto out_free1; - - type = os_file_type(host_file); - if(type == OS_TYPE_FILE){ - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); - if(fd >= 0) - data->host_fd = fd; - else printk("hppfs_open : failed to open '%s', errno = %d\n", - host_file, -fd); - - data->contents = NULL; - } - else if(type == OS_TYPE_DIR){ - fd = open_host_sock(host_file, &filter); - if(fd > 0){ - data->contents = hppfs_get_data(fd, filter, - &data->proc_file, - file, &data->len); - if(!IS_ERR(data->contents)) - data->host_fd = fd; - } - else printk("hppfs_open : failed to open a socket in " - "'%s', errno = %d\n", host_file, -fd); - } - kfree(host_file); - - file->private_data = data; - return(0); - - out_free1: - kfree(host_file); - out_free2: - free_contents(data->contents); - kfree(data); - out: - return(err); -} - -static int hppfs_dir_open(struct inode *inode, struct file *file) -{ - struct hppfs_private *data; - struct dentry *proc_dentry; - int err; - - err = -ENOMEM; - data = hppfs_data(); - if(data == NULL) - goto out; - - proc_dentry = HPPFS_I(inode)->proc_dentry; - err = open_private_file(&data->proc_file, proc_dentry, - file_mode(file->f_mode)); - if(err) - goto out_free; - - file->private_data = data; - return(0); - - out_free: - kfree(data); - out: - return(err); -} - -static loff_t hppfs_llseek(struct file *file, loff_t off, int where) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = &data->proc_file; - loff_t (*llseek)(struct file *, loff_t, int); - loff_t ret; - - llseek = proc_file->f_dentry->d_inode->i_fop->llseek; - if(llseek != NULL){ - ret = (*llseek)(proc_file, off, where); - if(ret < 0) - return(ret); - } - - return(default_llseek(file, off, where)); -} - -static struct file_operations hppfs_file_fops = { - .owner = NULL, - .llseek = hppfs_llseek, - .read = hppfs_read, - .write = hppfs_write, - .open = hppfs_open, -}; - -struct hppfs_dirent { - void *vfs_dirent; - filldir_t filldir; - struct dentry *dentry; -}; - -static int hppfs_filldir(void *d, const char *name, int size, - loff_t offset, ino_t inode, unsigned int type) -{ - struct hppfs_dirent *dirent = d; - - if(file_removed(dirent->dentry, name)) - return(0); - - return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, - inode, type)); -} - -static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = &data->proc_file; - int (*readdir)(struct file *, void *, filldir_t); - struct hppfs_dirent dirent = ((struct hppfs_dirent) - { .vfs_dirent = ent, - .filldir = filldir, - .dentry = file->f_dentry } ); - int err; - - readdir = proc_file->f_dentry->d_inode->i_fop->readdir; - - proc_file->f_pos = file->f_pos; - err = (*readdir)(proc_file, &dirent, hppfs_filldir); - file->f_pos = proc_file->f_pos; - - return(err); -} - -static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - return(0); -} - -static struct file_operations hppfs_dir_fops = { - .owner = NULL, - .readdir = hppfs_readdir, - .open = hppfs_dir_open, - .fsync = hppfs_fsync, -}; - -static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) -{ - sf->f_blocks = 0; - sf->f_bfree = 0; - sf->f_bavail = 0; - sf->f_files = 0; - sf->f_ffree = 0; - sf->f_type = HPPFS_SUPER_MAGIC; - return(0); -} - -static struct inode *hppfs_alloc_inode(struct super_block *sb) -{ - struct hppfs_inode_info *hi; - - hi = kmalloc(sizeof(*hi), GFP_KERNEL); - if(hi == NULL) - return(NULL); - - *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); - inode_init_once(&hi->vfs_inode); - return(&hi->vfs_inode); -} - -void hppfs_delete_inode(struct inode *ino) -{ - clear_inode(ino); -} - -static void hppfs_destroy_inode(struct inode *inode) -{ - kfree(HPPFS_I(inode)); -} - -static struct super_operations hppfs_sbops = { - .alloc_inode = hppfs_alloc_inode, - .destroy_inode = hppfs_destroy_inode, - .read_inode = hppfs_read_inode, - .delete_inode = hppfs_delete_inode, - .statfs = hppfs_statfs, -}; - -static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen) -{ - struct file proc_file; - struct dentry *proc_dentry; - int (*readlink)(struct dentry *, char *, int); - int err, n; - - proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - err = open_private_file(&proc_file, proc_dentry, O_RDONLY); - if(err) - return(err); - - readlink = proc_dentry->d_inode->i_op->readlink; - n = (*readlink)(proc_dentry, buffer, buflen); - - close_private_file(&proc_file); - - return(n); -} - -static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - struct file proc_file; - struct dentry *proc_dentry; - int (*follow_link)(struct dentry *, struct nameidata *); - int err, n; - - proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - err = open_private_file(&proc_file, proc_dentry, O_RDONLY); - if(err) - return(err); - - follow_link = proc_dentry->d_inode->i_op->follow_link; - n = (*follow_link)(proc_dentry, nd); - - close_private_file(&proc_file); - - return(n); -} - -static struct inode_operations hppfs_dir_iops = { - .lookup = hppfs_lookup, -}; - -static struct inode_operations hppfs_link_iops = { - .readlink = hppfs_readlink, - .follow_link = hppfs_follow_link, -}; - -static int init_inode(struct inode *inode, struct dentry *dentry) -{ - if(S_ISDIR(dentry->d_inode->i_mode)){ - inode->i_op = &hppfs_dir_iops; - inode->i_fop = &hppfs_dir_fops; - } - else if(S_ISLNK(dentry->d_inode->i_mode)){ - inode->i_op = &hppfs_link_iops; - inode->i_fop = &hppfs_file_fops; - } - else { - inode->i_op = &hppfs_file_iops; - inode->i_fop = &hppfs_file_fops; - } - - HPPFS_I(inode)->proc_dentry = dentry; - - return(0); -} - -static int hppfs_fill_super(struct super_block *sb, void *d, int silent) -{ - struct inode *root_inode; - struct file_system_type *procfs; - struct super_block *proc_sb; - int err; - - err = -ENOENT; - procfs = get_fs_type("proc"); - if(procfs == NULL) - goto out; - - if(list_empty(&procfs->fs_supers)) - goto out; - - proc_sb = list_entry(procfs->fs_supers.next, struct super_block, - s_instances); - - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; - sb->s_magic = HPPFS_SUPER_MAGIC; - sb->s_op = &hppfs_sbops; - - root_inode = iget(sb, 0); - if(root_inode == NULL) - goto out; - - err = init_inode(root_inode, proc_sb->s_root); - if(err) - goto out_put; - - err = -ENOMEM; - sb->s_root = d_alloc_root(root_inode); - if(sb->s_root == NULL) - goto out_put; - - hppfs_read_inode(root_inode); - - return(0); - - out_put: - iput(root_inode); - out: - return(err); -} - -static struct super_block *hppfs_read_super(struct file_system_type *type, - int flags, const char *dev_name, - void *data) -{ - return(get_sb_nodev(type, flags, data, hppfs_fill_super)); -} - -static struct file_system_type hppfs_type = { - .owner = THIS_MODULE, - .name = "hppfs", - .get_sb = hppfs_read_super, - .kill_sb = kill_anon_super, - .fs_flags = 0, -}; - -static int __init init_hppfs(void) -{ - return(register_filesystem(&hppfs_type)); -} - -static void __exit exit_hppfs(void) -{ - unregister_filesystem(&hppfs_type); -} - -module_init(init_hppfs) -module_exit(exit_hppfs) -MODULE_LICENSE("GPL"); - -/* - * 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/fs/rcfs/Makefile b/fs/rcfs/Makefile deleted file mode 100644 index 29575223e..000000000 --- a/fs/rcfs/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for rcfs routines. -# - -obj-$(CONFIG_RCFS_FS) += rcfs.o - -rcfs-objs := super.o inode.o dir.o rootdir.o magic.o tc_magic.o socket_fs.o - -rcfs-objs-$(CONFIG_CKRM_TYPE_TASKCLASS) += tc_magic.o -rcfs-objs-$(CONFIG_CKRM_TYPE_SOCKETCLASS) += socket_fs.o diff --git a/fs/rcfs/dir.c b/fs/rcfs/dir.c deleted file mode 100644 index 048fe09bd..000000000 --- a/fs/rcfs/dir.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * fs/rcfs/dir.c - * - * Copyright (C) Shailabh Nagar, IBM Corp. 2004 - * Vivek Kashyap, IBM Corp. 2004 - * - * - * Directory operations for rcfs - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 08 Mar 2004 - * Created. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - - - -#define rcfs_positive(dentry) ((dentry)->d_inode && !d_unhashed((dentry))) - -int rcfs_empty(struct dentry *dentry) -{ - struct dentry *child; - int ret = 0; - - spin_lock(&dcache_lock); - list_for_each_entry(child, &dentry->d_subdirs, d_child) - if (!rcfs_is_magic(child) && rcfs_positive(child)) - goto out; - ret = 1; -out: - spin_unlock(&dcache_lock); - return ret; -} - - - - -/* Directory inode operations */ - - -int -rcfs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) -{ - return rcfs_mknod(dir, dentry, mode | S_IFREG, 0); -} -EXPORT_SYMBOL(rcfs_create); - - -/* Symlinks permitted ?? */ -int -rcfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) -{ - struct inode *inode; - int error = -ENOSPC; - - inode = rcfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); - if (inode) { - int l = strlen(symname)+1; - error = page_symlink(inode, symname, l); - if (!error) { - if (dir->i_mode & S_ISGID) - inode->i_gid = dir->i_gid; - d_instantiate(dentry, inode); - dget(dentry); - } else - iput(inode); - } - return error; -} -EXPORT_SYMBOL(rcfs_symlink); - -int -rcfs_create_coredir(struct inode *dir, struct dentry *dentry) -{ - - struct rcfs_inode_info *ripar, *ridir; - int sz; - - ripar = RCFS_I(dir); - ridir = RCFS_I(dentry->d_inode); - - // Inform RC's - do Core operations - if (ckrm_is_core_valid(ripar->core)) { - sz = strlen(ripar->name) + strlen(dentry->d_name.name) + 2 ; - ridir->name = kmalloc(sz, GFP_KERNEL); - if (!ridir->name) { - return -ENOMEM; - } - snprintf(ridir->name, sz,"%s/%s", ripar->name, - dentry->d_name.name); - ridir->core = (*(ripar->core->classtype->alloc)) - (ripar->core,ridir->name); - } - else { - printk(KERN_ERR "rcfs_mkdir: Invalid parent core %p\n", - ripar->core); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL(rcfs_create_coredir); - - -int -rcfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - - int retval = 0; - ckrm_classtype_t *clstype; - -#if 0 - struct dentry *pd = list_entry(dir->i_dentry.next, struct dentry, - d_alias); - if ((!strcmp(pd->d_name.name, "/") && - !strcmp(dentry->d_name.name, "ce"))) { - // Call CE's mkdir if it has registered, else fail. - if (rcfs_eng_callbacks.mkdir) { - return (*rcfs_eng_callbacks.mkdir)(dir, dentry, mode); - } else { - return -EINVAL; - } - } -#endif - - if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) { - printk(KERN_ERR "rcfs_mkdir: error in _rcfs_mknod\n"); - return retval; - } - - dir->i_nlink++; - - // Inherit parent's ops since _rcfs_mknod assigns noperm ops - dentry->d_inode->i_op = dir->i_op; - dentry->d_inode->i_fop = dir->i_fop; - - - retval = rcfs_create_coredir(dir, dentry); - if (retval) { - simple_rmdir(dir,dentry); - return retval; - // goto mkdir_err; - } - - // create the default set of magic files - clstype = (RCFS_I(dentry->d_inode))->core->classtype; - rcfs_create_magic(dentry, &(((struct rcfs_magf*)clstype->mfdesc)[1]), - clstype->mfcount-1); - - return retval; - -//mkdir_err: - dir->i_nlink--; - return retval; -} -EXPORT_SYMBOL(rcfs_mkdir); - - -int -rcfs_rmdir(struct inode * dir, struct dentry * dentry) -{ - struct rcfs_inode_info *ri = RCFS_I(dentry->d_inode); - -#if 0 - struct dentry *pd = list_entry(dir->i_dentry.next, - struct dentry, d_alias); - if ((!strcmp(pd->d_name.name, "/") && - !strcmp(dentry->d_name.name, "ce"))) { - // Call CE's mkdir if it has registered, else fail. - if (rcfs_eng_callbacks.rmdir) { - return (*rcfs_eng_callbacks.rmdir)(dir, dentry); - } else { - return simple_rmdir(dir, dentry); - } - } - else if ((!strcmp(pd->d_name.name, "/") && - !strcmp(dentry->d_name.name, "network"))) { - return -EPERM; - } -#endif - - if (!rcfs_empty(dentry)) { - printk(KERN_ERR "rcfs_rmdir: directory not empty\n"); - goto out; - } - - // Core class removal - - if (ri->core == NULL) { - printk(KERN_ERR "rcfs_rmdir: core==NULL\n"); - // likely a race condition - return 0; - } - - if ((*(ri->core->classtype->free))(ri->core)) { - printk(KERN_ERR "rcfs_rmdir: ckrm_free_core_class failed\n"); - goto out; - } - ri->core = NULL ; // just to be safe - - // Clear magic files only after core successfully removed - rcfs_clear_magic(dentry); - - return simple_rmdir(dir, dentry); - -out: - return -EBUSY; -} -EXPORT_SYMBOL(rcfs_rmdir); - - -int -rcfs_unlink(struct inode *dir, struct dentry *dentry) -{ - // -ENOENT and not -ENOPERM to allow rm -rf to work despite - // magic files being present - return -ENOENT; -} -EXPORT_SYMBOL(rcfs_unlink); - -// rename is allowed on directories only -int -rcfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - if (S_ISDIR(old_dentry->d_inode->i_mode)) - return simple_rename(old_dir, old_dentry, new_dir, new_dentry); - else - return -EINVAL; -} -EXPORT_SYMBOL(rcfs_rename); - - -struct inode_operations rcfs_dir_inode_operations = { - .create = rcfs_create, - .lookup = simple_lookup, - .link = simple_link, - .unlink = rcfs_unlink, - .symlink = rcfs_symlink, - .mkdir = rcfs_mkdir, - .rmdir = rcfs_rmdir, - .mknod = rcfs_mknod, - .rename = rcfs_rename, -}; - - - - - -int -rcfs_root_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) -{ - return -EPERM; -} - - -int -rcfs_root_symlink(struct inode * dir, struct dentry *dentry, - const char * symname) -{ - return -EPERM; -} - -int -rcfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - return -EPERM; -} - -int -rcfs_root_rmdir(struct inode * dir, struct dentry * dentry) -{ - return -EPERM; -} - -int -rcfs_root_unlink(struct inode *dir, struct dentry *dentry) -{ - return -EPERM; -} - -int -rcfs_root_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - return -EPERM; -} - -int -rcfs_root_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - return -EPERM; -} - -struct inode_operations rcfs_rootdir_inode_operations = { - .create = rcfs_root_create, - .lookup = simple_lookup, - .link = simple_link, - .unlink = rcfs_root_unlink, - .symlink = rcfs_root_symlink, - .mkdir = rcfs_root_mkdir, - .rmdir = rcfs_root_rmdir, - .mknod = rcfs_root_mknod, - .rename = rcfs_root_rename, -}; diff --git a/fs/rcfs/inode.c b/fs/rcfs/inode.c deleted file mode 100644 index d9be67394..000000000 --- a/fs/rcfs/inode.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * fs/rcfs/inode.c - * - * Copyright (C) Shailabh Nagar, IBM Corp. 2004 - * Vivek Kashyap, IBM Corp. 2004 - * - * - * Resource class filesystem (rcfs) forming the - * user interface to Class-based Kernel Resource Management (CKRM). - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 05 Mar 2004 - * Created. - * 06 Mar 2004 - * Parsing for shares added - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - - -// Address of variable used as flag to indicate a magic file, -// ; value unimportant -int RCFS_IS_MAGIC; - - -struct inode *rcfs_get_inode(struct super_block *sb, int mode, dev_t dev) -{ - struct inode * inode = new_inode(sb); - - if (inode) { - inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - default: - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - // Treat as default assignment */ - inode->i_op = &rcfs_file_inode_operations; - // inode->i_fop = &rcfs_file_operations; - break; - case S_IFDIR: - // inode->i_op = &rcfs_dir_inode_operations; - inode->i_op = &rcfs_rootdir_inode_operations; - inode->i_fop = &simple_dir_operations; - - // directory inodes start off with i_nlink == 2 - // (for "." entry) - - inode->i_nlink++; - break; - case S_IFLNK: - inode->i_op = &page_symlink_inode_operations; - break; - } - } - return inode; -} - - - -int -_rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - struct inode *inode; - int error = -EPERM; - - if (dentry->d_inode) - return -EEXIST; - - inode = rcfs_get_inode(dir->i_sb, mode, dev); - if (inode) { - if (dir->i_mode & S_ISGID) { - inode->i_gid = dir->i_gid; - if (S_ISDIR(mode)) - inode->i_mode |= S_ISGID; - } - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - - return error; -} -EXPORT_SYMBOL(_rcfs_mknod); - - -int -rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - // User can only create directories, not files - if ((mode & S_IFMT) != S_IFDIR) - return -EINVAL; - - return dir->i_op->mkdir(dir, dentry, mode); -} -EXPORT_SYMBOL(rcfs_mknod); - - -struct dentry * -rcfs_create_internal(struct dentry *parent, struct rcfs_magf *magf, int magic) -{ - struct qstr qstr; - struct dentry *mfdentry ; - - // Get new dentry for name - qstr.name = magf->name; - qstr.len = strlen(magf->name); - qstr.hash = full_name_hash(magf->name,qstr.len); - mfdentry = lookup_hash(&qstr,parent); - - if (!IS_ERR(mfdentry)) { - int err; - - down(&parent->d_inode->i_sem); - if (magic && (magf->mode & S_IFDIR)) - err = parent->d_inode->i_op->mkdir(parent->d_inode, - mfdentry, magf->mode); - else { - err =_rcfs_mknod(parent->d_inode,mfdentry, - magf->mode,0); - // _rcfs_mknod doesn't increment parent's link count, - // i_op->mkdir does. - parent->d_inode->i_nlink++; - } - up(&parent->d_inode->i_sem); - - if (err) { - dput(mfdentry); - return mfdentry; - } - } - return mfdentry ; -} -EXPORT_SYMBOL(rcfs_create_internal); - -int -rcfs_delete_internal(struct dentry *mfdentry) -{ - struct dentry *parent ; - - if (!mfdentry || !mfdentry->d_parent) - return -EINVAL; - - parent = mfdentry->d_parent; - - if (!mfdentry->d_inode) { - return 0; - } - down(&mfdentry->d_inode->i_sem); - if (S_ISDIR(mfdentry->d_inode->i_mode)) - simple_rmdir(parent->d_inode, mfdentry); - else - simple_unlink(parent->d_inode, mfdentry); - up(&mfdentry->d_inode->i_sem); - - d_delete(mfdentry); - - return 0; -} -EXPORT_SYMBOL(rcfs_delete_internal); - -struct inode_operations rcfs_file_inode_operations = { - .getattr = simple_getattr, -}; - - - - - - diff --git a/fs/rcfs/magic.c b/fs/rcfs/magic.c deleted file mode 100644 index ad92a07a8..000000000 --- a/fs/rcfs/magic.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * fs/rcfs/magic.c - * - * Copyright (C) Shailabh Nagar, IBM Corp. 2004 - * (C) Vivek Kashyap, IBM Corp. 2004 - * (C) Chandra Seetharaman, IBM Corp. 2004 - * (C) Hubertus Franke, IBM Corp. 2004 - * - * File operations for common magic files in rcfs, - * the user interface for CKRM. - * - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 23 Apr 2004 - * Created from code kept earlier in fs/rcfs/magic_*.c - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - - - -/****************************************************** - * Macros - * - * generic macros to assist in writing magic fileops - * - *****************************************************/ - - -#define MAGIC_SHOW(FUNC) \ -static int \ -FUNC ## _show(struct seq_file *s, void *v) \ -{ \ - int rc=0; \ - ckrm_core_class_t *core ; \ - \ - core = (ckrm_core_class_t *) \ - (((struct rcfs_inode_info *)s->private)->core); \ - \ - if (!ckrm_is_core_valid(core)) { \ - return -EINVAL; \ - } \ - \ - if (core->classtype->show_ ## FUNC) \ - rc = (* core->classtype->show_ ## FUNC)(core, s); \ - \ - return rc; \ -}; - - -#define MAGIC_OPEN(FUNC) \ -static int \ -FUNC ## _open(struct inode *inode, struct file *file) \ -{ \ - struct rcfs_inode_info *ri; \ - int ret=-EINVAL; \ - \ - if (file->f_dentry && file->f_dentry->d_parent) { \ - \ - ri = RCFS_I(file->f_dentry->d_parent->d_inode); \ - ret = single_open(file,FUNC ## _show, (void *)ri); \ - } \ - return ret; \ -} - -#define MAGIC_CLOSE(FUNC) \ -static int \ -FUNC ## _close(struct inode *inode, struct file *file) \ -{ \ - return single_release(inode,file); \ -} - - - -#define MAGIC_PARSE(FUNC) \ -static int \ -FUNC ## _parse(char *options, char **resstr, char **otherstr) \ -{ \ - char *p; \ - \ - if (!options) \ - return 1; \ - \ - while ((p = strsep(&options, ",")) != NULL) { \ - substring_t args[MAX_OPT_ARGS]; \ - int token; \ - \ - if (!*p) \ - continue; \ - \ - token = match_token(p, FUNC##_tokens, args); \ - switch (token) { \ - case FUNC ## _res_type: \ - *resstr = match_strdup(args); \ - break; \ - case FUNC ## _str: \ - *otherstr = match_strdup(args); \ - break; \ - default: \ - return 0; \ - } \ - } \ - return 1; \ -} - -#define MAGIC_WRITE(FUNC,CLSTYPEFUN) \ -static ssize_t \ -FUNC ## _write(struct file *file, const char __user *buf, \ - size_t count, loff_t *ppos) \ -{ \ - struct rcfs_inode_info *ri = \ - RCFS_I(file->f_dentry->d_parent->d_inode); \ - char *optbuf, *otherstr=NULL, *resname=NULL; \ - int done, rc = 0; \ - ckrm_core_class_t *core ; \ - \ - core = ri->core; \ - if (!ckrm_is_core_valid(core)) \ - return -EINVAL; \ - \ - if ((ssize_t) count < 0 \ - || (ssize_t) count > FUNC ## _max_input_size) \ - return -EINVAL; \ - \ - if (!access_ok(VERIFY_READ, buf, count)) \ - return -EFAULT; \ - \ - down(&(ri->vfs_inode.i_sem)); \ - \ - optbuf = kmalloc(FUNC ## _max_input_size, GFP_KERNEL); \ - __copy_from_user(optbuf, buf, count); \ - if (optbuf[count-1] == '\n') \ - optbuf[count-1]='\0'; \ - \ - done = FUNC ## _parse(optbuf, &resname, &otherstr); \ - \ - if (!done) { \ - printk(KERN_ERR "Error parsing FUNC \n"); \ - goto FUNC ## _write_out; \ - } \ - \ - if (core->classtype-> CLSTYPEFUN) { \ - rc = (*core->classtype->CLSTYPEFUN) \ - (core, resname, otherstr); \ - if (rc) { \ - printk(KERN_ERR "FUNC_write: CLSTYPEFUN error\n"); \ - goto FUNC ## _write_out; \ - } \ - } \ - \ -FUNC ## _write_out: \ - up(&(ri->vfs_inode.i_sem)); \ - kfree(optbuf); \ - kfree(otherstr); \ - kfree(resname); \ - return rc ? rc : count; \ -} - - -#define MAGIC_RD_FILEOPS(FUNC) \ -struct file_operations FUNC ## _fileops = { \ - .open = FUNC ## _open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = FUNC ## _close, \ -}; \ -EXPORT_SYMBOL(FUNC ## _fileops); - - -#define MAGIC_RDWR_FILEOPS(FUNC) \ -struct file_operations FUNC ## _fileops = { \ - .open = FUNC ## _open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = FUNC ## _close, \ - .write = FUNC ## _write, \ -}; \ -EXPORT_SYMBOL(FUNC ## _fileops); - - -/******************************************************************************** - * Target - * - * pseudo file for manually reclassifying members to a class - * - *******************************************************************************/ - -#define TARGET_MAX_INPUT_SIZE 100 - -static ssize_t -target_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct rcfs_inode_info *ri= RCFS_I(file->f_dentry->d_inode); - char *optbuf; - int rc = -EINVAL; - ckrm_classtype_t *clstype; - - - if ((ssize_t) count < 0 || (ssize_t) count > TARGET_MAX_INPUT_SIZE) - return -EINVAL; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - - down(&(ri->vfs_inode.i_sem)); - - optbuf = kmalloc(TARGET_MAX_INPUT_SIZE, GFP_KERNEL); - __copy_from_user(optbuf, buf, count); - if (optbuf[count-1] == '\n') - optbuf[count-1]='\0'; - - clstype = ri->core->classtype; - if (clstype->forced_reclassify) - rc = (* clstype->forced_reclassify)(ri->core,optbuf); - - up(&(ri->vfs_inode.i_sem)); - kfree(optbuf); - return !rc ? count : rc; - -} - -struct file_operations target_fileops = { - .write = target_write, -}; -EXPORT_SYMBOL(target_fileops); - - - -/******************************************************************************** - * Config - * - * Set/get configuration parameters of a class. - * - *******************************************************************************/ - -/* Currently there are no per-class config parameters defined. - * Use existing code as a template - */ - -#define config_max_input_size 300 - -enum config_token_t { - config_str, config_res_type, config_err -}; - -static match_table_t config_tokens = { - {config_res_type,"res=%s"}, - {config_str, "config=%s"}, - {config_err, NULL}, -}; - - -MAGIC_PARSE(config); -MAGIC_WRITE(config,set_config); -MAGIC_SHOW(config); -MAGIC_OPEN(config); -MAGIC_CLOSE(config); - -MAGIC_RDWR_FILEOPS(config); - - -/******************************************************************************** - * Members - * - * List members of a class - * - *******************************************************************************/ - -MAGIC_SHOW(members); -MAGIC_OPEN(members); -MAGIC_CLOSE(members); - -MAGIC_RD_FILEOPS(members); - - -/******************************************************************************** - * Stats - * - * Get/reset class statistics - * No standard set of stats defined. Each resource controller chooses - * its own set of statistics to maintain and export. - * - *******************************************************************************/ - -#define stats_max_input_size 50 - -enum stats_token_t { - stats_res_type, stats_str,stats_err -}; - -static match_table_t stats_tokens = { - {stats_res_type,"res=%s"}, - {stats_str, NULL}, - {stats_err, NULL}, -}; - - -MAGIC_PARSE(stats); -MAGIC_WRITE(stats,reset_stats); -MAGIC_SHOW(stats); -MAGIC_OPEN(stats); -MAGIC_CLOSE(stats); - -MAGIC_RDWR_FILEOPS(stats); - - -/******************************************************************************** - * Shares - * - * Set/get shares of a taskclass. - * Share types and semantics are defined by rcfs and ckrm core - * - *******************************************************************************/ - - -#define SHARES_MAX_INPUT_SIZE 300 - -/* The enums for the share types should match the indices expected by - array parameter to ckrm_set_resshare */ - -/* Note only the first NUM_SHAREVAL enums correspond to share types, - the remaining ones are for token matching purposes */ - -enum share_token_t { - MY_GUAR, MY_LIM, TOT_GUAR, MAX_LIM, SHARE_RES_TYPE, SHARE_ERR -}; - -/* Token matching for parsing input to this magic file */ -static match_table_t shares_tokens = { - {SHARE_RES_TYPE, "res=%s"}, - {MY_GUAR, "guarantee=%d"}, - {MY_LIM, "limit=%d"}, - {TOT_GUAR,"total_guarantee=%d"}, - {MAX_LIM, "max_limit=%d"}, - {SHARE_ERR, NULL} -}; - - -static int -shares_parse(char *options, char **resstr, struct ckrm_shares *shares) -{ - char *p; - int option; - - if (!options) - return 1; - - while ((p = strsep(&options, ",")) != NULL) { - - substring_t args[MAX_OPT_ARGS]; - int token; - - if (!*p) - continue; - - token = match_token(p, shares_tokens, args); - switch (token) { - case SHARE_RES_TYPE: - *resstr = match_strdup(args); - break; - case MY_GUAR: - if (match_int(args, &option)) - return 0; - shares->my_guarantee = option; - break; - case MY_LIM: - if (match_int(args, &option)) - return 0; - shares->my_limit = option; - break; - case TOT_GUAR: - if (match_int(args, &option)) - return 0; - shares->total_guarantee = option; - break; - case MAX_LIM: - if (match_int(args, &option)) - return 0; - shares->max_limit = option; - break; - default: - return 0; - } - - } - return 1; -} - - -static ssize_t -shares_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - struct rcfs_inode_info *ri; - char *optbuf; - int rc = 0; - struct ckrm_core_class *core; - int done; - char *resname; - - struct ckrm_shares newshares = { - CKRM_SHARE_UNCHANGED, - CKRM_SHARE_UNCHANGED, - CKRM_SHARE_UNCHANGED, - CKRM_SHARE_UNCHANGED, - CKRM_SHARE_UNCHANGED, - CKRM_SHARE_UNCHANGED - }; - - if ((ssize_t) count < 0 || (ssize_t) count > SHARES_MAX_INPUT_SIZE) - return -EINVAL; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - - ri = RCFS_I(file->f_dentry->d_parent->d_inode); - - if (!ri || !ckrm_is_core_valid((ckrm_core_class_t *)(ri->core))) { - printk(KERN_ERR "shares_write: Error accessing core class\n"); - return -EFAULT; - } - - down(&inode->i_sem); - - core = ri->core; - optbuf = kmalloc(SHARES_MAX_INPUT_SIZE, GFP_KERNEL); - __copy_from_user(optbuf, buf, count); - if (optbuf[count-1] == '\n') - optbuf[count-1]='\0'; - - done = shares_parse(optbuf, &resname, &newshares); - if (!done) { - printk(KERN_ERR "Error parsing shares\n"); - rc = -EINVAL; - goto write_out; - } - - if (core->classtype->set_shares) { - rc = (*core->classtype->set_shares)(core,resname,&newshares); - if (rc) { - printk(KERN_ERR "shares_write: resctlr share set error\n"); - goto write_out; - } - } - - printk(KERN_ERR "Set %s shares to %d %d %d %d\n", - resname, - newshares.my_guarantee, - newshares.my_limit, - newshares.total_guarantee, - newshares.max_limit); - - rc = count ; - -write_out: - - up(&inode->i_sem); - kfree(optbuf); - kfree(resname); - return rc; -} - - -MAGIC_SHOW(shares); -MAGIC_OPEN(shares); -MAGIC_CLOSE(shares); - -MAGIC_RDWR_FILEOPS(shares); - - - -/* - * magic file creation/deletion - * - */ - - -int -rcfs_clear_magic(struct dentry *parent) -{ - struct dentry *mftmp, *mfdentry ; - - list_for_each_entry_safe(mfdentry, mftmp, &parent->d_subdirs, d_child) { - - if (!rcfs_is_magic(mfdentry)) - continue ; - - if (rcfs_delete_internal(mfdentry)) - printk(KERN_ERR "rcfs_clear_magic: error deleting one\n"); - } - - return 0; - -} -EXPORT_SYMBOL(rcfs_clear_magic); - - -int -rcfs_create_magic(struct dentry *parent, struct rcfs_magf magf[], int count) -{ - int i; - struct dentry *mfdentry; - - for (i=0; id_inode)->core = RCFS_I(parent->d_inode)->core; - mfdentry->d_fsdata = &RCFS_IS_MAGIC; - if (magf[i].i_fop) - mfdentry->d_inode->i_fop = magf[i].i_fop; - if (magf[i].i_op) - mfdentry->d_inode->i_op = magf[i].i_op; - } - return 0; -} -EXPORT_SYMBOL(rcfs_create_magic); diff --git a/fs/rcfs/rootdir.c b/fs/rcfs/rootdir.c deleted file mode 100644 index fe3415d8d..000000000 --- a/fs/rcfs/rootdir.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * fs/rcfs/rootdir.c - * - * Copyright (C) Vivek Kashyap, IBM Corp. 2004 - * - * - * Functions for creating root directories and magic files - * for classtypes and classification engines under rcfs - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 08 April 2004 - * Created. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - - - -rbce_eng_callback_t rcfs_eng_callbacks = { - NULL, NULL -}; - -int -rcfs_register_engine(rbce_eng_callback_t *rcbs) -{ - if (!rcbs->mkdir || rcfs_eng_callbacks.mkdir) { - return -EINVAL; - } - rcfs_eng_callbacks = *rcbs; - return 0; -} -EXPORT_SYMBOL(rcfs_register_engine); - - - -int -rcfs_unregister_engine(rbce_eng_callback_t *rcbs) -{ - if (!rcbs->mkdir || !rcfs_eng_callbacks.mkdir || - (rcbs->mkdir != rcfs_eng_callbacks.mkdir)) { - return -EINVAL; - } - rcfs_eng_callbacks.mkdir = NULL; - rcfs_eng_callbacks.rmdir = NULL; - return 0; -} -EXPORT_SYMBOL(rcfs_unregister_engine); - - - - -/* rcfs_mkroot - * Create and return a "root" dentry under /rcfs. Also create associated magic files - * - * @mfdesc: array of rcfs_magf describing root dir and its magic files - * @count: number of entries in mfdesc - * @core: core class to be associated with root - * @rootde: output parameter to return the newly created root dentry - */ - -int -rcfs_mkroot(struct rcfs_magf *mfdesc, int mfcount, struct dentry **rootde) -{ - int sz; - struct rcfs_magf *rootdesc = &mfdesc[0]; - struct dentry *dentry ; - struct rcfs_inode_info *rootri; - - if ((mfcount < 0) || (!mfdesc)) - return -EINVAL; - - rootdesc = &mfdesc[0]; - printk("allocating classtype root <%s>\n",rootdesc->name); - dentry = rcfs_create_internal(rcfs_rootde, rootdesc,0); - - if (!dentry) { - printk(KERN_ERR "Could not create %s\n",rootdesc->name); - return -ENOMEM; - } - - rootri = RCFS_I(dentry->d_inode); - sz = strlen(rootdesc->name) + strlen(RCFS_ROOT) + 2; - rootri->name = kmalloc(sz, GFP_KERNEL); - if (!rootri->name) { - printk(KERN_ERR "Error allocating name for %s\n", - rootdesc->name); - rcfs_delete_internal(dentry); - return -ENOMEM; - } - snprintf(rootri->name,sz,"%s/%s",RCFS_ROOT,rootdesc->name); - - if (rootdesc->i_fop) - dentry->d_inode->i_fop = rootdesc->i_fop; - if (rootdesc->i_op) - dentry->d_inode->i_op = rootdesc->i_op; - - // set output parameters - *rootde = dentry; - - return 0; -} -EXPORT_SYMBOL(rcfs_mkroot); - - -int -rcfs_rmroot(struct dentry *rootde) -{ - if (!rootde) - return -EINVAL; - - rcfs_clear_magic(rootde); - kfree(RCFS_I(rootde->d_inode)->name); - rcfs_delete_internal(rootde); - return 0; -} -EXPORT_SYMBOL(rcfs_rmroot); - - -int -rcfs_register_classtype(ckrm_classtype_t *clstype) -{ - int rc ; - struct rcfs_inode_info *rootri; - struct rcfs_magf *mfdesc; - - // Initialize mfdesc, mfcount - clstype->mfdesc = (void *) genmfdesc[clstype->mfidx]->rootmf; - clstype->mfcount = genmfdesc[clstype->mfidx]->rootmflen; - - mfdesc = (struct rcfs_magf *)clstype->mfdesc; - - /* rcfs root entry has the same name as the classtype */ - strncpy(mfdesc[0].name,clstype->name,RCFS_MAGF_NAMELEN) ; - - rc = rcfs_mkroot(mfdesc,clstype->mfcount, - (struct dentry **)&(clstype->rootde)); - if (rc) - return rc; - - rootri = RCFS_I(((struct dentry *)(clstype->rootde))->d_inode); - rootri->core = clstype->default_class; - clstype->default_class->name = rootri->name; - ckrm_core_grab(clstype->default_class); - - // Create magic files under root - if ((rc = rcfs_create_magic(clstype->rootde, &mfdesc[1], - clstype->mfcount-1))) { - kfree(rootri->name); - rcfs_delete_internal(clstype->rootde); - return rc; - } - - return rc; -} -EXPORT_SYMBOL(rcfs_register_classtype); - - -int -rcfs_deregister_classtype(ckrm_classtype_t *clstype) -{ - int rc; - - rc = rcfs_rmroot((struct dentry *)clstype->rootde); - if (!rc) { - clstype->default_class->name = NULL ; - ckrm_core_drop(clstype->default_class); - } - return rc; -} -EXPORT_SYMBOL(rcfs_deregister_classtype); - - - -// Common root and magic file entries. -// root name, root permissions, magic file names and magic file permissions are needed by -// all entities (classtypes and classification engines) existing under the rcfs mount point - -// The common sets of these attributes are listed here as a table. Individual classtypes and -// classification engines can simple specify the index into the table to initialize their -// magf entries. -// - -#ifdef CONFIG_CKRM_TYPE_TASKCLASS -extern struct rcfs_mfdesc tc_mfdesc; -#endif - -#ifdef CONFIG_CKRM_TYPE_TASKCLASS -extern struct rcfs_mfdesc sock_mfdesc; -#endif - -// extern struct rcfs_magf rbce_mfdesc; - - -struct rcfs_mfdesc *genmfdesc[]={ -#ifdef CONFIG_CKRM_TYPE_TASKCLASS - &tc_mfdesc, -#else - NULL, -#endif -#ifdef CONFIG_CKRM_TYPE_SOCKETCLASS - &sock_mfdesc, -#else - NULL, -#endif -// Create similar entry for RBCE ? -//#ifdef CONFIG_CKRM_CE -// &rbce_mfdesc, -//#else -// NULL, -//#endif - -}; - - - - diff --git a/fs/rcfs/socket_fs.c b/fs/rcfs/socket_fs.c deleted file mode 100644 index 492fb092c..000000000 --- a/fs/rcfs/socket_fs.c +++ /dev/null @@ -1,338 +0,0 @@ -/* ckrm_socketaq.c - * - * Copyright (C) Vivek Kashyap, IBM Corp. 2004 - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * Initial version - */ - -/******************************************************************************* - * Socket class type - * - * Defines the root structure for socket based classes. Currently only inbound - * connection control is supported based on prioritized accept queues. - ******************************************************************************/ - - -#include -#include - -extern int rcfs_create(struct inode *,struct dentry *, int, struct nameidata *); -extern int rcfs_unlink(struct inode *, struct dentry *); -extern int rcfs_symlink(struct inode *, struct dentry *, const char *); -extern int rcfs_mknod(struct inode *, struct dentry *, int mode, dev_t); -extern int rcfs_mkdir(struct inode *, struct dentry *, int); -extern int rcfs_rmdir(struct inode *, struct dentry *); -extern int rcfs_rename(struct inode *, struct dentry *, struct inode *, - struct dentry *); - -extern int rcfs_create_coredir(struct inode *, struct dentry *); -int sock_mkdir(struct inode *, struct dentry *, int mode); -int sock_rmdir(struct inode *, struct dentry *); - - -int sock_create_noperm(struct inode *, struct dentry *,int, struct nameidata *); -int sock_unlink_noperm(struct inode *,struct dentry *); -int sock_mkdir_noperm(struct inode *,struct dentry *,int); -int sock_rmdir_noperm(struct inode *,struct dentry *); -int sock_mknod_noperm(struct inode *,struct dentry *,int, dev_t); - -void sock_set_directory(void); - -extern struct file_operations config_fileops, - members_fileops, - shares_fileops, - stats_fileops, - target_fileops; - - -struct inode_operations my_iops = { - .create = rcfs_create, - .lookup = simple_lookup, - .link = simple_link, - .unlink = rcfs_unlink, - .symlink = rcfs_symlink, - .mkdir = sock_mkdir, - .rmdir = sock_rmdir, - .mknod = rcfs_mknod, - .rename = rcfs_rename, -}; - -struct inode_operations class_iops = { - .create = sock_create_noperm, - .lookup = simple_lookup, - .link = simple_link, - .unlink = sock_unlink_noperm, - .symlink = rcfs_symlink, - .mkdir = sock_mkdir_noperm, - .rmdir = sock_rmdir_noperm, - .mknod = sock_mknod_noperm, - .rename = rcfs_rename, -}; - -struct inode_operations sub_iops = { - .create = sock_create_noperm, - .lookup = simple_lookup, - .link = simple_link, - .unlink = sock_unlink_noperm, - .symlink = rcfs_symlink, - .mkdir = sock_mkdir_noperm, - .rmdir = sock_rmdir_noperm, - .mknod = sock_mknod_noperm, - .rename = rcfs_rename, -}; - -struct rcfs_magf def_magf = { - .mode = RCFS_DEFAULT_DIR_MODE, - .i_op = &sub_iops, - .i_fop = NULL, -}; - -struct rcfs_magf sock_rootdesc[] = { - { - // .name = should not be set, copy from classtype name, - .mode = RCFS_DEFAULT_DIR_MODE, - .i_op = &my_iops, - //.i_fop = &simple_dir_operations, - .i_fop = NULL, - }, - { - .name = "members", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &members_fileops, - }, - { - .name = "target", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &target_fileops, - }, -}; - -struct rcfs_magf sock_magf[] = { - { - .name = "config", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &config_fileops, - }, - { - .name = "members", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop =&members_fileops, - }, - { - .name = "shares", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &shares_fileops, - }, - { - .name = "stats", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &stats_fileops, - }, - { - .name = "target", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &target_fileops, - }, -}; - -struct rcfs_magf sub_magf[] = { - { - .name = "config", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &config_fileops, - }, - { - .name = "shares", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &shares_fileops, - }, - { - .name = "stats", - .mode = RCFS_DEFAULT_FILE_MODE, - .i_op = &my_iops, - .i_fop = &stats_fileops, - }, -}; - -struct rcfs_mfdesc sock_mfdesc = { - .rootmf = sock_rootdesc, - .rootmflen = (sizeof(sock_rootdesc)/sizeof(struct rcfs_magf)), -}; - - -#define SOCK_MAX_MAGF (sizeof(sock_magf)/sizeof(struct rcfs_magf)) -#define LAQ_MAX_SUBMAGF (sizeof(sub_magf)/sizeof(struct rcfs_magf)) - -int -sock_rmdir(struct inode *p, struct dentry *me) -{ - struct dentry *mftmp, *mfdentry ; - - // delete all magic sub directories - list_for_each_entry_safe(mfdentry, mftmp, &me->d_subdirs, d_child) { - if (S_ISDIR(mfdentry->d_inode->i_mode)) - rcfs_rmdir(me->d_inode, mfdentry); - } - // delete ourselves - rcfs_rmdir(p,me); - - return 0; -} - -#ifdef NUM_ACCEPT_QUEUES -#define LAQ_NUM_ACCEPT_QUEUES NUM_ACCEPT_QUEUES -#else -#define LAQ_NUM_ACCEPT_QUEUES 0 -#endif - -int -sock_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - int retval = 0; - int i,j; - struct dentry *pentry, *mfdentry; - - if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) { - printk(KERN_ERR "rcfs_mkdir: error reaching parent\n"); - return retval; - } - - // Needed if only _rcfs_mknod is used instead of i_op->mkdir - dir->i_nlink++; - - retval = rcfs_create_coredir(dir, dentry); - if (retval) - goto mkdir_err; - - /* create the default set of magic files */ - for (i =0; i < SOCK_MAX_MAGF; i++) { - mfdentry = rcfs_create_internal(dentry, &sock_magf[i],0); - mfdentry->d_fsdata = &RCFS_IS_MAGIC; - RCFS_I(mfdentry->d_inode)->core = - RCFS_I(dentry->d_inode)->core; - if (sock_magf[i].i_fop) - mfdentry->d_inode->i_fop = sock_magf[i].i_fop; - if (sock_magf[i].i_op) - mfdentry->d_inode->i_op = sock_magf[i].i_op; - } - - for (i=1; i < LAQ_NUM_ACCEPT_QUEUES; i++) { - j = sprintf(def_magf.name, "%d",i); - def_magf.name[j] = '\0'; - - pentry = rcfs_create_internal(dentry, &def_magf,0); - retval = rcfs_create_coredir(dentry->d_inode, pentry); - if (retval) - goto mkdir_err; - for (j=0; j < LAQ_MAX_SUBMAGF; j++) { - mfdentry = rcfs_create_internal(pentry, &sub_magf[j],0); - mfdentry->d_fsdata = &RCFS_IS_MAGIC; - RCFS_I(mfdentry->d_inode)->core = - RCFS_I(pentry->d_inode)->core; - if (sub_magf[j].i_fop) - mfdentry->d_inode->i_fop = sub_magf[j].i_fop; - if (sub_magf[j].i_op) - mfdentry->d_inode->i_op = sub_magf[j].i_op; - } - pentry->d_inode->i_op = &sub_iops; - } - dentry->d_inode->i_op = &class_iops; - return 0; - -mkdir_err: - // Needed - dir->i_nlink--; - return retval; -} -#ifndef NUM_ACCEPT_QUEUES -#define NUM_ACCEPT_QUEUES 0 -#endif - -char * -sock_get_name(struct ckrm_core_class *c) -{ - char *p = (char *)c->name; - - while(*p) - p++; - while( *p != '/' && p != c->name) - p--; - - return ++p; -} - -int -sock_create_noperm(struct inode *dir,struct dentry *dentry,int mode, struct nameidata *nd) -{ - return -EPERM; -} - -int -sock_unlink_noperm(struct inode *dir,struct dentry *dentry) -{ - return -EPERM; -} - -int -sock_mkdir_noperm(struct inode *dir,struct dentry *dentry, int mode) -{ - return -EPERM; -} - -int -sock_rmdir_noperm(struct inode *dir,struct dentry *dentry) -{ - return -EPERM; -} - -int -sock_mknod_noperm(struct inode *dir,struct dentry *dentry,int mode, dev_t dev) -{ - return -EPERM; -} - -#if 0 -void -sock_set_directory() -{ - struct dentry *pentry, *dentry; - - pentry = rcfs_set_magf_byname("listen_aq", (void *)&my_dir_magf[0]); - if (pentry) { - dentry = rcfs_create_internal(pentry, &my_dir_magf[1],0); - if (my_dir_magf[1].i_fop) - dentry->d_inode->i_fop = my_dir_magf[1].i_fop; - RCFS_I(dentry->d_inode)->core = - RCFS_I(pentry->d_inode)->core; - dentry = rcfs_create_internal(pentry, &my_dir_magf[2],0); - if (my_dir_magf[2].i_fop) - dentry->d_inode->i_fop = my_dir_magf[2].i_fop; - RCFS_I(dentry->d_inode)->core = - RCFS_I(pentry->d_inode)->core; - } - else { - printk(KERN_ERR "Could not create /rcfs/listen_aq\n" - "Perhaps /rcfs needs to be mounted\n"); - } -} -#endif - diff --git a/fs/rcfs/super.c b/fs/rcfs/super.c deleted file mode 100644 index d0e78c447..000000000 --- a/fs/rcfs/super.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * fs/rcfs/super.c - * - * Copyright (C) Shailabh Nagar, IBM Corp. 2004 - * Vivek Kashyap, IBM Corp. 2004 - * - * Super block operations for rcfs - * - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 08 Mar 2004 - * Created. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - - -static kmem_cache_t *rcfs_inode_cachep; - - -inline struct rcfs_inode_info *RCFS_I(struct inode *inode) -{ - return container_of(inode, struct rcfs_inode_info, vfs_inode); -} -EXPORT_SYMBOL(RCFS_I); - - - -static struct inode * -rcfs_alloc_inode(struct super_block *sb) -{ - struct rcfs_inode_info *ri; - ri = (struct rcfs_inode_info *) kmem_cache_alloc(rcfs_inode_cachep, - SLAB_KERNEL); - if (!ri) - return NULL; - ri->name = NULL; - return &ri->vfs_inode; -} - -static void -rcfs_destroy_inode(struct inode *inode) -{ - struct rcfs_inode_info *ri = RCFS_I(inode); - - kfree(ri->name); - kmem_cache_free(rcfs_inode_cachep, RCFS_I(inode)); -} - -static void -rcfs_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) -{ - struct rcfs_inode_info *ri = (struct rcfs_inode_info *) foo; - - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ri->vfs_inode); -} - -int -rcfs_init_inodecache(void) -{ - rcfs_inode_cachep = kmem_cache_create("rcfs_inode_cache", - sizeof(struct rcfs_inode_info), - 0, SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT, - rcfs_init_once, NULL); - if (rcfs_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -void rcfs_destroy_inodecache(void) -{ - printk(KERN_WARNING "destroy inodecache was called\n"); - if (kmem_cache_destroy(rcfs_inode_cachep)) - printk(KERN_INFO "rcfs_inode_cache: not all structures were freed\n"); -} - -struct super_operations rcfs_super_ops = -{ - .alloc_inode = rcfs_alloc_inode, - .destroy_inode = rcfs_destroy_inode, - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, -}; - - -struct dentry *rcfs_rootde; /* redundant since one can also get it from sb */ -static struct inode *rcfs_root; -static struct rcfs_inode_info *rcfs_rootri; - -static int rcfs_mounted; - -static int rcfs_fill_super(struct super_block * sb, void * data, int silent) -{ - struct inode * inode; - struct dentry * root; - struct rcfs_inode_info *rootri; - struct ckrm_classtype *clstype; - int i,rc; - - sb->s_fs_info = NULL; - if (rcfs_mounted) { - return -EPERM; - } - rcfs_mounted++; - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = RCFS_MAGIC; - sb->s_op = &rcfs_super_ops; - inode = rcfs_get_inode(sb, S_IFDIR | 0755, 0); - if (!inode) - return -ENOMEM; - inode->i_op = &rcfs_rootdir_inode_operations; - - root = d_alloc_root(inode); - if (!root) { - iput(inode); - return -ENOMEM; - } - sb->s_root = root; - - - // Link inode and core class - rootri = RCFS_I(inode); - rootri->name = kmalloc(strlen(RCFS_ROOT) + 1, GFP_KERNEL); - if (!rootri->name) { - d_delete(root); - iput(inode); - return -ENOMEM; - } - strcpy(rootri->name, RCFS_ROOT); - rootri->core = NULL; - - rcfs_root = inode; - sb->s_fs_info = rcfs_root = inode; - rcfs_rootde = root ; - rcfs_rootri = rootri ; - - // register metatypes - for ( i=0; is_fs_info != rcfs_root) { - generic_shutdown_super(sb); - return; - } - rcfs_mounted--; - - for ( i=0; i < CKRM_MAX_CLASSTYPES; i++) { - - clstype = ckrm_classtypes[i]; - if (clstype == NULL || clstype->rootde == NULL) - continue; - - if ((rc = rcfs_deregister_classtype(clstype))) { - printk(KERN_ERR "Error removing classtype %s\n", - clstype->name); - // return ; // can also choose to stop here - } - } - - // do not remove comment block until ce directory issue resolved - // deregister CE with rcfs - // Check if loaded - // if ce is in one directory /rcfs/ce, - // rcfs_deregister_engine for all classtypes within above - // codebase - // followed by - // rcfs_rmroot here - // if ce in multiple (per-classtype) directories - // call rbce_deregister_engine within ckrm_deregister_classtype - - // following will automatically clear rcfs root entry including its - // rcfs_inode_info - - generic_shutdown_super(sb); - - // printk(KERN_ERR "Removed all entries\n"); -} - - -static struct file_system_type rcfs_fs_type = { - .name = "rcfs", - .get_sb = rcfs_get_sb, - .kill_sb = rcfs_kill_sb, -}; - -struct rcfs_functions my_rcfs_fn = { - .mkroot = rcfs_mkroot, - .rmroot = rcfs_rmroot, - .register_classtype = rcfs_register_classtype, - .deregister_classtype = rcfs_deregister_classtype, -}; - -extern struct rcfs_functions rcfs_fn ; - -static int __init init_rcfs_fs(void) -{ - int ret; - - ret = register_filesystem(&rcfs_fs_type); - if (ret) - goto init_register_err; - - ret = rcfs_init_inodecache(); - if (ret) - goto init_cache_err; - - rcfs_fn = my_rcfs_fn ; - - return ret; - -init_cache_err: - unregister_filesystem(&rcfs_fs_type); -init_register_err: - return ret; -} - -static void __exit exit_rcfs_fs(void) -{ - rcfs_destroy_inodecache(); - unregister_filesystem(&rcfs_fs_type); -} - -module_init(init_rcfs_fs) -module_exit(exit_rcfs_fs) - -MODULE_LICENSE("GPL"); diff --git a/fs/rcfs/tc_magic.c b/fs/rcfs/tc_magic.c deleted file mode 100644 index 16864094c..000000000 --- a/fs/rcfs/tc_magic.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * fs/rcfs/tc_magic.c - * - * Copyright (C) Shailabh Nagar, IBM Corp. 2004 - * (C) Vivek Kashyap, IBM Corp. 2004 - * (C) Chandra Seetharaman, IBM Corp. 2004 - * (C) Hubertus Franke, IBM Corp. 2004 - * - * - * define magic fileops for taskclass classtype - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 23 Apr 2004 - * Created. - * - */ - -#include -#include - - -/******************************************************************************* - * Taskclass general - * - * Define structures for taskclass root directory and its magic files - * In taskclasses, there is one set of magic files, created automatically under - * the taskclass root (upon classtype registration) and each directory (class) - * created subsequently. However, classtypes can also choose to have different - * sets of magic files created under their root and other directories under root - * using their mkdir function. RCFS only provides helper functions for creating - * the root directory and its magic files - * - *******************************************************************************/ - -#define TC_FILE_MODE (S_IFREG | S_IRUGO | S_IWUSR) - -#define NR_TCROOTMF 6 -struct rcfs_magf tc_rootdesc[NR_TCROOTMF] = { - /* First entry must be root */ - { -// .name = should not be set, copy from classtype name - .mode = RCFS_DEFAULT_DIR_MODE, - .i_op = &rcfs_dir_inode_operations, - .i_fop = &simple_dir_operations, - }, - /* Rest are root's magic files */ - { - .name = "target", - .mode = TC_FILE_MODE, - .i_fop = &target_fileops, - .i_op = &rcfs_file_inode_operations, - }, - { - .name = "config", - .mode = TC_FILE_MODE, - .i_fop = &config_fileops, - .i_op = &rcfs_file_inode_operations, - }, - { - .name = "members", - .mode = TC_FILE_MODE, - .i_fop = &members_fileops, - .i_op = &rcfs_file_inode_operations, - }, - { - .name = "stats", - .mode = TC_FILE_MODE, - .i_fop = &stats_fileops, - .i_op = &rcfs_file_inode_operations, - }, - { - .name = "shares", - .mode = TC_FILE_MODE, - .i_fop = &shares_fileops, - .i_op = &rcfs_file_inode_operations, - }, -}; - -struct rcfs_mfdesc tc_mfdesc = { - .rootmf = tc_rootdesc, - .rootmflen = NR_TCROOTMF, -}; - - diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c deleted file mode 100644 index eacbdca43..000000000 --- a/fs/reiserfs/xattr_security.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define XATTR_SECURITY_PREFIX "security." - -static int -security_get (struct inode *inode, const char *name, void *buffer, size_t size) -{ - if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX)) - return -EINVAL; - - if (is_reiserfs_priv_object(inode)) - return -EPERM; - - return reiserfs_xattr_get (inode, name, buffer, size); -} - -static int -security_set (struct inode *inode, const char *name, const void *buffer, - size_t size, int flags) -{ - if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX)) - return -EINVAL; - - if (is_reiserfs_priv_object(inode)) - return -EPERM; - - return reiserfs_xattr_set (inode, name, buffer, size, flags); -} - -static int -security_del (struct inode *inode, const char *name) -{ - if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX)) - return -EINVAL; - - if (is_reiserfs_priv_object(inode)) - return -EPERM; - - return 0; -} - -static int -security_list (struct inode *inode, const char *name, int namelen, char *out) -{ - int len = namelen; - - if (is_reiserfs_priv_object(inode)) - return 0; - - if (out) - memcpy (out, name, len); - - return len; -} - - -struct reiserfs_xattr_handler security_handler = { - prefix: XATTR_SECURITY_PREFIX, - get: security_get, - set: security_set, - del: security_del, - list: security_list, -}; diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c deleted file mode 100644 index 39a10ec8c..000000000 --- a/fs/reiserfs/xattr_trusted.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define XATTR_TRUSTED_PREFIX "trusted." - -static int -trusted_get (struct inode *inode, const char *name, void *buffer, size_t size) -{ - if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs (inode->i_sb)) - return -EOPNOTSUPP; - - if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) - return -EPERM; - - return reiserfs_xattr_get (inode, name, buffer, size); -} - -static int -trusted_set (struct inode *inode, const char *name, const void *buffer, - size_t size, int flags) -{ - if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs (inode->i_sb)) - return -EOPNOTSUPP; - - if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) - return -EPERM; - - return reiserfs_xattr_set (inode, name, buffer, size, flags); -} - -static int -trusted_del (struct inode *inode, const char *name) -{ - if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs (inode->i_sb)) - return -EOPNOTSUPP; - - if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) - return -EPERM; - - return 0; -} - -static int -trusted_list (struct inode *inode, const char *name, int namelen, char *out) -{ - int len = namelen; - - if (!reiserfs_xattrs (inode->i_sb)) - return 0; - - if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode))) - return 0; - - if (out) - memcpy (out, name, len); - - return len; -} - - -struct reiserfs_xattr_handler trusted_handler = { - prefix: XATTR_TRUSTED_PREFIX, - get: trusted_get, - set: trusted_set, - del: trusted_del, - list: trusted_list, -}; diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c deleted file mode 100644 index 38779f3fd..000000000 --- a/fs/reiserfs/xattr_user.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_REISERFS_FS_POSIX_ACL -# include -#endif - -#define XATTR_USER_PREFIX "user." - -static int -user_get (struct inode *inode, const char *name, void *buffer, size_t size) -{ - - int error; - - if (strlen(name) < sizeof(XATTR_USER_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs_user (inode->i_sb)) - return -EOPNOTSUPP; - - error = reiserfs_permission_locked (inode, MAY_READ, NULL); - if (error) - return error; - - return reiserfs_xattr_get (inode, name, buffer, size); -} - -static int -user_set (struct inode *inode, const char *name, const void *buffer, - size_t size, int flags) -{ - - int error; - - if (strlen(name) < sizeof(XATTR_USER_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs_user (inode->i_sb)) - return -EOPNOTSUPP; - - if (!S_ISREG (inode->i_mode) && - (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) - return -EPERM; - - error = reiserfs_permission_locked (inode, MAY_WRITE, NULL); - if (error) - return error; - - return reiserfs_xattr_set (inode, name, buffer, size, flags); -} - -static int -user_del (struct inode *inode, const char *name) -{ - int error; - - if (strlen(name) < sizeof(XATTR_USER_PREFIX)) - return -EINVAL; - - if (!reiserfs_xattrs_user (inode->i_sb)) - return -EOPNOTSUPP; - - if (!S_ISREG (inode->i_mode) && - (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) - return -EPERM; - - error = reiserfs_permission_locked (inode, MAY_WRITE, NULL); - if (error) - return error; - - return 0; -} - -static int -user_list (struct inode *inode, const char *name, int namelen, char *out) -{ - int len = namelen; - if (!reiserfs_xattrs_user (inode->i_sb)) - return 0; - - if (out) - memcpy (out, name, len); - - return len; -} - -struct reiserfs_xattr_handler user_handler = { - prefix: XATTR_USER_PREFIX, - get: user_get, - set: user_set, - del: user_del, - list: user_list, -}; diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile deleted file mode 100644 index 09f098a10..000000000 --- a/fs/relayfs/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# relayfs Makefile -# - -obj-$(CONFIG_RELAYFS_FS) += relayfs.o - -relayfs-y := relay.o relay_lockless.o relay_locking.o inode.o resize.o -relayfs-$(CONFIG_KLOG_CHANNEL) += klog.o diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c deleted file mode 100644 index 6e8736015..000000000 --- a/fs/relayfs/inode.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - * VFS-related code for RelayFS, a high-speed data relay filesystem. - * - * Copyright (C) 2003 - Tom Zanussi , IBM Corp - * Copyright (C) 2003 - Karim Yaghmour - * - * Based on ramfs, Copyright (C) 2002 - Linus Torvalds - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RELAYFS_MAGIC 0x26F82121 - -static struct super_operations relayfs_ops; -static struct address_space_operations relayfs_aops; -static struct inode_operations relayfs_file_inode_operations; -static struct file_operations relayfs_file_operations; -static struct inode_operations relayfs_dir_inode_operations; - -static struct vfsmount * relayfs_mount; -static int relayfs_mount_count; - -static struct backing_dev_info relayfs_backing_dev_info = { - .ra_pages = 0, /* No readahead */ - .memory_backed = 1, /* Does not contribute to dirty memory */ -}; - -static struct inode * -relayfs_get_inode(struct super_block *sb, int mode, dev_t dev) -{ - struct inode * inode; - - inode = new_inode(sb); - - if (inode) { - inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_mapping->a_ops = &relayfs_aops; - inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - default: - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - inode->i_op = &relayfs_file_inode_operations; - inode->i_fop = &relayfs_file_operations; - break; - case S_IFDIR: - inode->i_op = &relayfs_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inode->i_nlink++; - break; - case S_IFLNK: - inode->i_op = &page_symlink_inode_operations; - break; - } - } - return inode; -} - -/* - * File creation. Allocate an inode, and we're done.. - */ -/* SMP-safe */ -static int -relayfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - struct inode * inode; - int error = -ENOSPC; - - inode = relayfs_get_inode(dir->i_sb, mode, dev); - - if (inode) { - d_instantiate(dentry, inode); - dget(dentry); /* Extra count - pin the dentry in core */ - error = 0; - } - return error; -} - -static int -relayfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) -{ - int retval; - - retval = relayfs_mknod(dir, dentry, mode | S_IFDIR, 0); - - if (!retval) - dir->i_nlink++; - return retval; -} - -static int -relayfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) -{ - return relayfs_mknod(dir, dentry, mode | S_IFREG, 0); -} - -static int -relayfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) -{ - struct inode *inode; - int error = -ENOSPC; - - inode = relayfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); - - if (inode) { - int l = strlen(symname)+1; - error = page_symlink(inode, symname, l); - if (!error) { - d_instantiate(dentry, inode); - dget(dentry); - } else - iput(inode); - } - return error; -} - -/** - * relayfs_create_entry - create a relayfs directory or file - * @name: the name of the file to create - * @parent: parent directory - * @dentry: result dentry - * @entry_type: type of file to create (S_IFREG, S_IFDIR) - * @mode: mode - * @data: data to associate with the file - * - * Creates a file or directory with the specifed permissions. - */ -static int -relayfs_create_entry(const char * name, struct dentry * parent, struct dentry **dentry, int entry_type, int mode, void * data) -{ - struct qstr qname; - struct dentry * d; - - int error = 0; - - error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count); - if (error) { - printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error); - return error; - } - - qname.name = name; - qname.len = strlen(name); - qname.hash = full_name_hash(name, qname.len); - - if (parent == NULL) - if (relayfs_mount && relayfs_mount->mnt_sb) - parent = relayfs_mount->mnt_sb->s_root; - - if (parent == NULL) { - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - return -EINVAL; - } - - parent = dget(parent); - down(&parent->d_inode->i_sem); - d = lookup_hash(&qname, parent); - if (IS_ERR(d)) { - error = PTR_ERR(d); - goto release_mount; - } - - if (d->d_inode) { - error = -EEXIST; - goto release_mount; - } - - if (entry_type == S_IFREG) - error = relayfs_create(parent->d_inode, d, entry_type | mode, NULL); - else - error = relayfs_mkdir(parent->d_inode, d, entry_type | mode); - if (error) - goto release_mount; - - if ((entry_type == S_IFREG) && data) { - d->d_inode->u.generic_ip = data; - goto exit; /* don't release mount for regular files */ - } - -release_mount: - simple_release_fs(&relayfs_mount, &relayfs_mount_count); -exit: - *dentry = d; - up(&parent->d_inode->i_sem); - dput(parent); - - return error; -} - -/** - * relayfs_create_file - create a file in the relay filesystem - * @name: the name of the file to create - * @parent: parent directory - * @dentry: result dentry - * @data: data to associate with the file - * @mode: mode, if not specied the default perms are used - * - * The file will be created user rw on behalf of current user. - */ -int -relayfs_create_file(const char * name, struct dentry * parent, struct dentry **dentry, void * data, int mode) -{ - if (!mode) - mode = S_IRUSR | S_IWUSR; - - return relayfs_create_entry(name, parent, dentry, S_IFREG, - mode, data); -} - -/** - * relayfs_create_dir - create a directory in the relay filesystem - * @name: the name of the directory to create - * @parent: parent directory - * @dentry: result dentry - * - * The directory will be created world rwx on behalf of current user. - */ -int -relayfs_create_dir(const char * name, struct dentry * parent, struct dentry **dentry) -{ - return relayfs_create_entry(name, parent, dentry, S_IFDIR, - S_IRWXU | S_IRUGO | S_IXUGO, NULL); -} - -/** - * relayfs_remove_file - remove a file in the relay filesystem - * @dentry: file dentry - * - * Remove a file previously created by relayfs_create_file. - */ -int -relayfs_remove_file(struct dentry *dentry) -{ - struct dentry *parent; - int is_reg; - - parent = dentry->d_parent; - if (parent == NULL) - return -EINVAL; - - is_reg = S_ISREG(dentry->d_inode->i_mode); - - parent = dget(parent); - down(&parent->d_inode->i_sem); - if (dentry->d_inode) { - simple_unlink(parent->d_inode, dentry); - d_delete(dentry); - } - dput(dentry); - up(&parent->d_inode->i_sem); - dput(parent); - - if(is_reg) - simple_release_fs(&relayfs_mount, &relayfs_mount_count); - - return 0; -} - -/** - * relayfs_open - open file op for relayfs files - * @inode: the inode - * @filp: the file - * - * Associates the channel with the file, and increments the - * channel refcount. Reads will be 'auto-consuming'. - */ -int -relayfs_open(struct inode *inode, struct file *filp) -{ - struct rchan *rchan; - struct rchan_reader *reader; - int retval = 0; - - if (inode->u.generic_ip) { - rchan = (struct rchan *)inode->u.generic_ip; - if (rchan == NULL) - return -EACCES; - reader = __add_rchan_reader(rchan, filp, 1, 0); - if (reader == NULL) - return -ENOMEM; - filp->private_data = reader; - retval = rchan->callbacks->fileop_notify(rchan->id, filp, - RELAY_FILE_OPEN); - if (retval == 0) - /* Inc relay channel refcount for file */ - rchan_get(rchan->id); - else { - __remove_rchan_reader(reader); - retval = -EPERM; - } - } - - return retval; -} - -/** - * relayfs_mmap - mmap file op for relayfs files - * @filp: the file - * @vma: the vma describing what to map - * - * Calls upon relay_mmap_buffer to map the file into user space. - */ -int -relayfs_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct rchan *rchan; - - rchan = ((struct rchan_reader *)filp->private_data)->rchan; - - return __relay_mmap_buffer(rchan, vma); -} - -/** - * relayfs_file_read - read file op for relayfs files - * @filp: the file - * @buf: user buf to read into - * @count: bytes requested - * @offset: offset into file - * - * Reads count bytes from the channel, or as much as is available within - * the sub-buffer currently being read. Reads are 'auto-consuming'. - * See relay_read() for details. - * - * Returns bytes read on success, 0 or -EAGAIN if nothing available, - * negative otherwise. - */ -ssize_t -relayfs_file_read(struct file *filp, char * buf, size_t count, loff_t *offset) -{ - size_t read_count; - struct rchan_reader *reader; - u32 dummy; /* all VFS readers are auto-consuming */ - - if (offset != &filp->f_pos) /* pread, seeking not supported */ - return -ESPIPE; - - if (count == 0) - return 0; - - reader = (struct rchan_reader *)filp->private_data; - read_count = relay_read(reader, buf, count, - filp->f_flags & (O_NDELAY | O_NONBLOCK) ? 0 : 1, &dummy); - - return read_count; -} - -/** - * relayfs_file_write - write file op for relayfs files - * @filp: the file - * @buf: user buf to write from - * @count: bytes to write - * @offset: offset into file - * - * Reserves a slot in the relay buffer and writes count bytes - * into it. The current limit for a single write is 2 pages - * worth. The user_deliver() channel callback will be invoked on - * - * Returns bytes written on success, 0 or -EAGAIN if nothing available, - * negative otherwise. - */ -ssize_t -relayfs_file_write(struct file *filp, const char *buf, size_t count, loff_t *offset) -{ - int write_count; - char * write_buf; - struct rchan *rchan; - int err = 0; - void *wrote_pos; - struct rchan_reader *reader; - - reader = (struct rchan_reader *)filp->private_data; - if (reader == NULL) - return -EPERM; - - rchan = reader->rchan; - if (rchan == NULL) - return -EPERM; - - if (count == 0) - return 0; - - /* Change this if need to write more than 2 pages at once */ - if (count > 2 * PAGE_SIZE) - return -EINVAL; - - write_buf = (char *)__get_free_pages(GFP_KERNEL, 1); - if (write_buf == NULL) - return -ENOMEM; - - if (copy_from_user(write_buf, buf, count)) - return -EFAULT; - - if (filp->f_flags & (O_NDELAY | O_NONBLOCK)) { - write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos); - if (write_count == 0) - return -EAGAIN; - } else { - err = wait_event_interruptible(rchan->write_wait, - (write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos))); - if (err) - return err; - } - - free_pages((unsigned long)write_buf, 1); - - rchan->callbacks->user_deliver(rchan->id, wrote_pos, write_count); - - return write_count; -} - -/** - * relayfs_ioctl - ioctl file op for relayfs files - * @inode: the inode - * @filp: the file - * @cmd: the command - * @arg: command arg - * - * Passes the specified cmd/arg to the kernel client. arg may be a - * pointer to user-space data, in which case the kernel client is - * responsible for copying the data to/from user space appropriately. - * The kernel client is also responsible for returning a meaningful - * return value for ioctl calls. - * - * Returns result of relay channel callback, -EPERM if unsuccessful. - */ -int -relayfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct rchan *rchan; - struct rchan_reader *reader; - - reader = (struct rchan_reader *)filp->private_data; - if (reader == NULL) - return -EPERM; - - rchan = reader->rchan; - if (rchan == NULL) - return -EPERM; - - return rchan->callbacks->ioctl(rchan->id, cmd, arg); -} - -/** - * relayfs_poll - poll file op for relayfs files - * @filp: the file - * @wait: poll table - * - * Poll implemention. - */ -static unsigned int -relayfs_poll(struct file *filp, poll_table *wait) -{ - struct rchan_reader *reader; - unsigned int mask = 0; - - reader = (struct rchan_reader *)filp->private_data; - - if (reader->rchan->finalized) - return POLLERR; - - if (filp->f_mode & FMODE_READ) { - poll_wait(filp, &reader->rchan->read_wait, wait); - if (!rchan_empty(reader)) - mask |= POLLIN | POLLRDNORM; - } - - if (filp->f_mode & FMODE_WRITE) { - poll_wait(filp, &reader->rchan->write_wait, wait); - if (!rchan_full(reader)) - mask |= POLLOUT | POLLWRNORM; - } - - return mask; -} - -/** - * relayfs_release - release file op for relayfs files - * @inode: the inode - * @filp: the file - * - * Decrements the channel refcount, as the filesystem is - * no longer using it. - */ -int -relayfs_release(struct inode *inode, struct file *filp) -{ - struct rchan_reader *reader; - struct rchan *rchan; - - reader = (struct rchan_reader *)filp->private_data; - if (reader == NULL || reader->rchan == NULL) - return 0; - rchan = reader->rchan; - - rchan->callbacks->fileop_notify(reader->rchan->id, filp, - RELAY_FILE_CLOSE); - __remove_rchan_reader(reader); - /* The channel is no longer in use as far as this file is concerned */ - rchan_put(rchan); - - return 0; -} - -static struct address_space_operations relayfs_aops = { - .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write -}; - -static struct file_operations relayfs_file_operations = { - .open = relayfs_open, - .read = relayfs_file_read, - .write = relayfs_file_write, - .ioctl = relayfs_ioctl, - .poll = relayfs_poll, - .mmap = relayfs_mmap, - .fsync = simple_sync_file, - .release = relayfs_release, -}; - -static struct inode_operations relayfs_file_inode_operations = { - .getattr = simple_getattr, -}; - -static struct inode_operations relayfs_dir_inode_operations = { - .create = relayfs_create, - .lookup = simple_lookup, - .link = simple_link, - .unlink = simple_unlink, - .symlink = relayfs_symlink, - .mkdir = relayfs_mkdir, - .rmdir = simple_rmdir, - .mknod = relayfs_mknod, - .rename = simple_rename, -}; - -static struct super_operations relayfs_ops = { - .statfs = simple_statfs, - .drop_inode = generic_delete_inode, -}; - -static int -relayfs_fill_super(struct super_block * sb, void * data, int silent) -{ - struct inode * inode; - struct dentry * root; - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - sb->s_magic = RELAYFS_MAGIC; - sb->s_op = &relayfs_ops; - inode = relayfs_get_inode(sb, S_IFDIR | 0755, 0); - - if (!inode) - return -ENOMEM; - - root = d_alloc_root(inode); - if (!root) { - iput(inode); - return -ENOMEM; - } - sb->s_root = root; - - return 0; -} - -static struct super_block * -relayfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) -{ - return get_sb_single(fs_type, flags, data, relayfs_fill_super); -} - -static struct file_system_type relayfs_fs_type = { - .owner = THIS_MODULE, - .name = "relayfs", - .get_sb = relayfs_get_sb, - .kill_sb = kill_litter_super, -}; - -static int __init -init_relayfs_fs(void) -{ - int err = register_filesystem(&relayfs_fs_type); -#ifdef CONFIG_KLOG_CHANNEL - if (!err) - create_klog_channel(); -#endif - return err; -} - -static void __exit -exit_relayfs_fs(void) -{ -#ifdef CONFIG_KLOG_CHANNEL - remove_klog_channel(); -#endif - unregister_filesystem(&relayfs_fs_type); -} - -module_init(init_relayfs_fs) -module_exit(exit_relayfs_fs) - -MODULE_AUTHOR("Tom Zanussi and Karim Yaghmour "); -MODULE_DESCRIPTION("Relay Filesystem"); -MODULE_LICENSE("GPL"); - diff --git a/fs/relayfs/klog.c b/fs/relayfs/klog.c deleted file mode 100644 index 3f2d31da4..000000000 --- a/fs/relayfs/klog.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * KLOG Generic Logging facility built upon the relayfs infrastructure - * - * Authors: Hubertus Franke (frankeh@us.ibm.com) - * Tom Zanussi (zanussi@us.ibm.com) - * - * Please direct all questions/comments to zanussi@us.ibm.com - * - * Copyright (C) 2003, IBM Corp - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* klog channel id */ -static int klog_channel = -1; - -/* maximum size of klog formatting buffer beyond which truncation will occur */ -#define KLOG_BUF_SIZE (512) -/* per-cpu klog formatting buffer */ -static char buf[NR_CPUS][KLOG_BUF_SIZE]; - -/* - * klog_enabled determines whether klog()/klog_raw() actually do write - * to the klog channel at any given time. If klog_enabled == 1 they do, - * otherwise they don't. Settable using sysctl fs.relayfs.klog_enabled. - */ -#ifdef CONFIG_KLOG_CHANNEL_AUTOENABLE -static int klog_enabled = 1; -#else -static int klog_enabled = 0; -#endif - -/** - * klog - write a formatted string into the klog channel - * @fmt: format string - * - * Returns number of bytes written, negative number on failure. - */ -int klog(const char *fmt, ...) -{ - va_list args; - int len, err; - char *cbuf; - unsigned long flags; - - if (!klog_enabled || klog_channel < 0) - return 0; - - local_irq_save(flags); - cbuf = buf[smp_processor_id()]; - - va_start(args, fmt); - len = vsnprintf(cbuf, KLOG_BUF_SIZE, fmt, args); - va_end(args); - - err = relay_write(klog_channel, cbuf, len, -1, NULL); - local_irq_restore(flags); - - return err; -} - -/** - * klog_raw - directly write into the klog channel - * @buf: buffer containing data to write - * @len: # bytes to write - * - * Returns number of bytes written, negative number on failure. - */ -int klog_raw(const char *buf,int len) -{ - int err = 0; - - if (klog_enabled && klog_channel >= 0) - err = relay_write(klog_channel, buf, len, -1, NULL); - - return err; -} - -/** - * relayfs sysctl data - * - * Only sys/fs/relayfs/klog_enabled for now. - */ -#define CTL_ENABLE_KLOG 100 -#define CTL_RELAYFS 100 - -static struct ctl_table_header *relayfs_ctl_table_header; - -static struct ctl_table relayfs_table[] = -{ - { - .ctl_name = CTL_ENABLE_KLOG, - .procname = "klog_enabled", - .data = &klog_enabled, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - 0 - } -}; - -static struct ctl_table relayfs_dir_table[] = -{ - { - .ctl_name = CTL_RELAYFS, - .procname = "relayfs", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = relayfs_table, - }, - { - 0 - } -}; - -static struct ctl_table relayfs_root_table[] = -{ - { - .ctl_name = CTL_FS, - .procname = "fs", - .data = NULL, - .maxlen = 0, - .mode = 0555, - .child = relayfs_dir_table, - }, - { - 0 - } -}; - -/** - * create_klog_channel - creates channel /mnt/relay/klog - * - * Returns channel id on success, negative otherwise. - */ -int -create_klog_channel(void) -{ - u32 bufsize, nbufs; - u32 channel_flags; - - channel_flags = RELAY_DELIVERY_PACKET | RELAY_USAGE_GLOBAL; - channel_flags |= RELAY_SCHEME_ANY | RELAY_TIMESTAMP_ANY; - - bufsize = 1 << (CONFIG_KLOG_CHANNEL_SHIFT - 2); - nbufs = 4; - - klog_channel = relay_open("klog", - bufsize, - nbufs, - channel_flags, - NULL, - 0, - 0, - 0, - 0, - 0, - 0, - NULL, - 0); - - if (klog_channel < 0) - printk("klog channel creation failed, errcode: %d\n", klog_channel); - else { - printk("klog channel created (%u bytes)\n", 1 << CONFIG_KLOG_CHANNEL_SHIFT); - relayfs_ctl_table_header = register_sysctl_table(relayfs_root_table, 1); - } - - return klog_channel; -} - -/** - * remove_klog_channel - destroys channel /mnt/relay/klog - * - * Returns 0, negative otherwise. - */ -int -remove_klog_channel(void) -{ - if (relayfs_ctl_table_header) - unregister_sysctl_table(relayfs_ctl_table_header); - - return relay_close(klog_channel); -} - -EXPORT_SYMBOL(klog); -EXPORT_SYMBOL(klog_raw); - diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c deleted file mode 100644 index 11f4636ce..000000000 --- a/fs/relayfs/relay.c +++ /dev/null @@ -1,1911 +0,0 @@ -/* - * Public API and common code for RelayFS. - * - * Please see Documentation/filesystems/relayfs.txt for API description. - * - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "relay_lockless.h" -#include "relay_locking.h" -#include "resize.h" - -/* Relay channel table, indexed by channel id */ -static struct rchan * rchan_table[RELAY_MAX_CHANNELS]; -static rwlock_t rchan_table_lock = RW_LOCK_UNLOCKED; - -/* Relay operation structs, one per scheme */ -static struct relay_ops lockless_ops = { - .reserve = lockless_reserve, - .commit = lockless_commit, - .get_offset = lockless_get_offset, - .finalize = lockless_finalize, - .reset = lockless_reset, - .reset_index = lockless_reset_index -}; - -static struct relay_ops locking_ops = { - .reserve = locking_reserve, - .commit = locking_commit, - .get_offset = locking_get_offset, - .finalize = locking_finalize, - .reset = locking_reset, - .reset_index = locking_reset_index -}; - -/* - * Low-level relayfs kernel API. These functions should not normally be - * used by clients. See high-level kernel API below. - */ - -/** - * rchan_get - get channel associated with id, incrementing refcount - * @rchan_id: the channel id - * - * Returns channel if successful, NULL otherwise. - */ -struct rchan * -rchan_get(int rchan_id) -{ - struct rchan *rchan; - - if ((rchan_id < 0) || (rchan_id >= RELAY_MAX_CHANNELS)) - return NULL; - - read_lock(&rchan_table_lock); - rchan = rchan_table[rchan_id]; - if (rchan) - atomic_inc(&rchan->refcount); - read_unlock(&rchan_table_lock); - - return rchan; -} - -/** - * clear_readers - clear non-VFS readers - * @rchan: the channel - * - * Clear the channel pointers of all non-VFS readers open on the channel. - */ -static inline void -clear_readers(struct rchan *rchan) -{ - struct list_head *p; - struct rchan_reader *reader; - - read_lock(&rchan->open_readers_lock); - list_for_each(p, &rchan->open_readers) { - reader = list_entry(p, struct rchan_reader, list); - if (!reader->vfs_reader) - reader->rchan = NULL; - } - read_unlock(&rchan->open_readers_lock); -} - -/** - * rchan_alloc_id - reserve a channel id and store associated channel - * @rchan: the channel - * - * Returns channel id if successful, -1 otherwise. - */ -static inline int -rchan_alloc_id(struct rchan *rchan) -{ - int i; - int rchan_id = -1; - - if (rchan == NULL) - return -1; - - write_lock(&rchan_table_lock); - for (i = 0; i < RELAY_MAX_CHANNELS; i++) { - if (rchan_table[i] == NULL) { - rchan_table[i] = rchan; - rchan_id = rchan->id = i; - break; - } - } - if (rchan_id != -1) - atomic_inc(&rchan->refcount); - write_unlock(&rchan_table_lock); - - return rchan_id; -} - -/** - * rchan_free_id - revoke a channel id and remove associated channel - * @rchan_id: the channel id - */ -static inline void -rchan_free_id(int rchan_id) -{ - struct rchan *rchan; - - if ((rchan_id < 0) || (rchan_id >= RELAY_MAX_CHANNELS)) - return; - - write_lock(&rchan_table_lock); - rchan = rchan_table[rchan_id]; - rchan_table[rchan_id] = NULL; - write_unlock(&rchan_table_lock); -} - -/** - * rchan_destroy_buf - destroy the current channel buffer - * @rchan: the channel - */ -static inline void -rchan_destroy_buf(struct rchan *rchan) -{ - if (rchan->buf && !rchan->init_buf) - free_rchan_buf(rchan->buf, - rchan->buf_page_array, - rchan->buf_page_count); -} - -/** - * relay_release - perform end-of-buffer processing for last buffer - * @rchan: the channel - * - * Returns 0 if successful, negative otherwise. - * - * Releases the channel buffer, destroys the channel, and removes the - * relay file from the relayfs filesystem. Should only be called from - * rchan_put(). If we're here, it means by definition refcount is 0. - */ -static int -relay_release(struct rchan *rchan) -{ - if (rchan == NULL) - return -EBADF; - - rchan_destroy_buf(rchan); - rchan_free_id(rchan->id); - relayfs_remove_file(rchan->dentry); - clear_readers(rchan); - kfree(rchan); - - return 0; -} - -/** - * rchan_get - decrement channel refcount, releasing it if 0 - * @rchan: the channel - * - * If the refcount reaches 0, the channel will be destroyed. - */ -void -rchan_put(struct rchan *rchan) -{ - if (atomic_dec_and_test(&rchan->refcount)) - relay_release(rchan); -} - -/** - * relay_reserve - reserve a slot in the channel buffer - * @rchan: the channel - * @len: the length of the slot to reserve - * @td: the time delta between buffer start and current write, or TSC - * @err: receives the result flags - * @interrupting: 1 if interrupting previous, used only in locking scheme - * - * Returns pointer to the beginning of the reserved slot, NULL if error. - * - * The errcode value contains the result flags and is an ORed combination - * of the following: - * - * RELAY_BUFFER_SWITCH_NONE - no buffer switch occurred - * RELAY_EVENT_DISCARD_NONE - event should not be discarded - * RELAY_BUFFER_SWITCH - buffer switch occurred - * RELAY_EVENT_DISCARD - event should be discarded (all buffers are full) - * RELAY_EVENT_TOO_LONG - event won't fit into even an empty buffer - * - * buffer_start and buffer_end callbacks are triggered at this point - * if applicable. - */ -char * -relay_reserve(struct rchan *rchan, - u32 len, - struct timeval *ts, - u32 *td, - int *err, - int *interrupting) -{ - if (rchan == NULL) - return NULL; - - *interrupting = 0; - - return rchan->relay_ops->reserve(rchan, len, ts, td, err, interrupting); -} - - -/** - * wakeup_readers - wake up VFS readers waiting on a channel - * @private: the channel - * - * This is the work function used to defer reader waking. The - * reason waking is deferred is that calling directly from commit - * causes problems if you're writing from say the scheduler. - */ -static void -wakeup_readers(void *private) -{ - struct rchan *rchan = (struct rchan *)private; - - wake_up_interruptible(&rchan->read_wait); -} - - -/** - * relay_commit - commit a reserved slot in the buffer - * @rchan: the channel - * @from: commit the length starting here - * @len: length committed - * @interrupting: 1 if interrupting previous, used only in locking scheme - * - * After the write into the reserved buffer has been complted, this - * function must be called in order for the relay to determine whether - * buffers are complete and to wake up VFS readers. - * - * delivery callback is triggered at this point if applicable. - */ -void -relay_commit(struct rchan *rchan, - char *from, - u32 len, - int reserve_code, - int interrupting) -{ - int deliver; - - if (rchan == NULL) - return; - - deliver = packet_delivery(rchan) || - (reserve_code & RELAY_BUFFER_SWITCH); - - rchan->relay_ops->commit(rchan, from, len, deliver, interrupting); - - /* The params are always the same, so no worry about re-queuing */ - if (deliver && waitqueue_active(&rchan->read_wait)) { - PREPARE_WORK(&rchan->wake_readers, wakeup_readers, rchan); - schedule_delayed_work(&rchan->wake_readers, 1); - } -} - -/** - * relay_get_offset - get current and max channel buffer offsets - * @rchan: the channel - * @max_offset: maximum channel offset - * - * Returns the current and maximum channel buffer offsets. - */ -u32 -relay_get_offset(struct rchan *rchan, u32 *max_offset) -{ - return rchan->relay_ops->get_offset(rchan, max_offset); -} - -/** - * reset_index - try once to reset the current channel index - * @rchan: the channel - * @old_index: the index read before reset - * - * Attempts to reset the channel index to 0. It tries once, and - * if it fails, returns negative, 0 otherwise. - */ -int -reset_index(struct rchan *rchan, u32 old_index) -{ - return rchan->relay_ops->reset_index(rchan, old_index); -} - -/* - * close() vm_op implementation for relayfs file mapping. - */ -static void -relay_file_mmap_close(struct vm_area_struct *vma) -{ - struct file *filp = vma->vm_file; - struct rchan_reader *reader; - struct rchan *rchan; - - reader = (struct rchan_reader *)filp->private_data; - rchan = reader->rchan; - - atomic_dec(&rchan->mapped); - - rchan->callbacks->fileop_notify(reader->rchan->id, filp, - RELAY_FILE_UNMAP); -} - -/* - * vm_ops for relay file mappings. - */ -static struct vm_operations_struct relay_file_mmap_ops = { - .close = relay_file_mmap_close -}; - -/* \begin{Code inspired from BTTV driver} */ -static inline unsigned long -kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *) adr)); - kva |= adr & (PAGE_SIZE - 1); - ret = __pa(kva); - return ret; -} - -static int -relay_mmap_region(struct vm_area_struct *vma, - const char *adr, - const char *start_pos, - unsigned long size) -{ - unsigned long start = (unsigned long) adr; - unsigned long page, pos; - - pos = (unsigned long) start_pos; - - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return 0; -} -/* \end{Code inspired from BTTV driver} */ - -/** - * relay_mmap_buffer: - mmap buffer to process address space - * @rchan_id: relay channel id - * @vma: vm_area_struct describing memory to be mapped - * - * Returns: - * 0 if ok - * -EAGAIN, when remap failed - * -EINVAL, invalid requested length - * - * Caller should already have grabbed mmap_sem. - */ -int -__relay_mmap_buffer(struct rchan *rchan, - struct vm_area_struct *vma) -{ - int err = 0; - unsigned long length = vma->vm_end - vma->vm_start; - struct file *filp = vma->vm_file; - - if (rchan == NULL) { - err = -EBADF; - goto exit; - } - - if (rchan->init_buf) { - err = -EPERM; - goto exit; - } - - if (length != (unsigned long)rchan->alloc_size) { - err = -EINVAL; - goto exit; - } - - err = relay_mmap_region(vma, - (char *)vma->vm_start, - rchan->buf, - rchan->alloc_size); - - if (err == 0) { - vma->vm_ops = &relay_file_mmap_ops; - err = rchan->callbacks->fileop_notify(rchan->id, filp, - RELAY_FILE_MAP); - if (err == 0) - atomic_inc(&rchan->mapped); - } -exit: - return err; -} - -/* - * High-level relayfs kernel API. See Documentation/filesystems/relafys.txt. - */ - -/* - * rchan_callback implementations defining default channel behavior. Used - * in place of corresponding NULL values in client callback struct. - */ - -/* - * buffer_end() default callback. Does nothing. - */ -static int -buffer_end_default_callback(int rchan_id, - char *current_write_pos, - char *end_of_buffer, - struct timeval end_time, - u32 end_tsc, - int using_tsc) -{ - return 0; -} - -/* - * buffer_start() default callback. Does nothing. - */ -static int -buffer_start_default_callback(int rchan_id, - char *current_write_pos, - u32 buffer_id, - struct timeval start_time, - u32 start_tsc, - int using_tsc) -{ - return 0; -} - -/* - * deliver() default callback. Does nothing. - */ -static void -deliver_default_callback(int rchan_id, char *from, u32 len) -{ -} - -/* - * user_deliver() default callback. Does nothing. - */ -static void -user_deliver_default_callback(int rchan_id, char *from, u32 len) -{ -} - -/* - * needs_resize() default callback. Does nothing. - */ -static void -needs_resize_default_callback(int rchan_id, - int resize_type, - u32 suggested_buf_size, - u32 suggested_n_bufs) -{ -} - -/* - * fileop_notify() default callback. Does nothing. - */ -static int -fileop_notify_default_callback(int rchan_id, - struct file *filp, - enum relay_fileop fileop) -{ - return 0; -} - -/* - * ioctl() default callback. Does nothing. - */ -static int -ioctl_default_callback(int rchan_id, - unsigned int cmd, - unsigned long arg) -{ - return 0; -} - -/* relay channel default callbacks */ -static struct rchan_callbacks default_channel_callbacks = { - .buffer_start = buffer_start_default_callback, - .buffer_end = buffer_end_default_callback, - .deliver = deliver_default_callback, - .user_deliver = user_deliver_default_callback, - .needs_resize = needs_resize_default_callback, - .fileop_notify = fileop_notify_default_callback, - .ioctl = ioctl_default_callback, -}; - -/** - * check_attribute_flags - check sanity of channel attributes - * @flags: channel attributes - * @resizeable: 1 if true - * - * Returns 0 if successful, negative otherwise. - */ -static int -check_attribute_flags(u32 *attribute_flags, int resizeable) -{ - u32 flags = *attribute_flags; - - if (!(flags & RELAY_DELIVERY_BULK) && !(flags & RELAY_DELIVERY_PACKET)) - return -EINVAL; /* Delivery mode must be specified */ - - if (!(flags & RELAY_USAGE_SMP) && !(flags & RELAY_USAGE_GLOBAL)) - return -EINVAL; /* Usage must be specified */ - - if (resizeable) { /* Resizeable can never be continuous */ - *attribute_flags &= ~RELAY_MODE_CONTINUOUS; - *attribute_flags |= RELAY_MODE_NO_OVERWRITE; - } - - if ((flags & RELAY_MODE_CONTINUOUS) && - (flags & RELAY_MODE_NO_OVERWRITE)) - return -EINVAL; /* Can't have it both ways */ - - if (!(flags & RELAY_MODE_CONTINUOUS) && - !(flags & RELAY_MODE_NO_OVERWRITE)) - *attribute_flags |= RELAY_MODE_CONTINUOUS; /* Default to continuous */ - - if (!(flags & RELAY_SCHEME_ANY)) - return -EINVAL; /* One or both must be specified */ - else if (flags & RELAY_SCHEME_LOCKLESS) { - if (have_cmpxchg()) - *attribute_flags &= ~RELAY_SCHEME_LOCKING; - else if (flags & RELAY_SCHEME_LOCKING) - *attribute_flags &= ~RELAY_SCHEME_LOCKLESS; - else - return -EINVAL; /* Locking scheme not an alternative */ - } - - if (!(flags & RELAY_TIMESTAMP_ANY)) - return -EINVAL; /* One or both must be specified */ - else if (flags & RELAY_TIMESTAMP_TSC) { - if (have_tsc()) - *attribute_flags &= ~RELAY_TIMESTAMP_GETTIMEOFDAY; - else if (flags & RELAY_TIMESTAMP_GETTIMEOFDAY) - *attribute_flags &= ~RELAY_TIMESTAMP_TSC; - else - return -EINVAL; /* gettimeofday not an alternative */ - } - - return 0; -} - -/* - * High-level API functions. - */ - -/** - * __relay_reset - internal reset function - * @rchan: the channel - * @init: 1 if this is a first-time channel initialization - * - * See relay_reset for description of effect. - */ -void -__relay_reset(struct rchan *rchan, int init) -{ - int i; - - if (init) { - rchan->version = RELAYFS_CHANNEL_VERSION; - init_MUTEX(&rchan->resize_sem); - init_waitqueue_head(&rchan->read_wait); - init_waitqueue_head(&rchan->write_wait); - atomic_set(&rchan->refcount, 0); - INIT_LIST_HEAD(&rchan->open_readers); - rchan->open_readers_lock = RW_LOCK_UNLOCKED; - } - - rchan->buf_id = rchan->buf_idx = 0; - atomic_set(&rchan->suspended, 0); - atomic_set(&rchan->mapped, 0); - rchan->half_switch = 0; - rchan->bufs_produced = 0; - rchan->bufs_consumed = 0; - rchan->bytes_consumed = 0; - rchan->initialized = 0; - rchan->finalized = 0; - rchan->resize_min = rchan->resize_max = 0; - rchan->resizing = 0; - rchan->replace_buffer = 0; - rchan->resize_buf = NULL; - rchan->resize_buf_size = 0; - rchan->resize_alloc_size = 0; - rchan->resize_n_bufs = 0; - rchan->resize_err = 0; - rchan->resize_failures = 0; - rchan->resize_order = 0; - - rchan->expand_page_array = NULL; - rchan->expand_page_count = 0; - rchan->shrink_page_array = NULL; - rchan->shrink_page_count = 0; - rchan->resize_page_array = NULL; - rchan->resize_page_count = 0; - rchan->old_buf_page_array = NULL; - rchan->expand_buf_id = 0; - - INIT_WORK(&rchan->wake_readers, NULL, NULL); - INIT_WORK(&rchan->wake_writers, NULL, NULL); - - for (i = 0; i < RELAY_MAX_BUFS; i++) - rchan->unused_bytes[i] = 0; - - rchan->relay_ops->reset(rchan, init); -} - -/** - * relay_reset - reset the channel - * @rchan: the channel - * - * Returns 0 if successful, negative if not. - * - * This has the effect of erasing all data from the buffer and - * restarting the channel in its initial state. The buffer itself - * is not freed, so any mappings are still in effect. - * - * NOTE: Care should be taken that the channnel isn't actually - * being used by anything when this call is made. - */ -int -relay_reset(int rchan_id) -{ - struct rchan *rchan; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - __relay_reset(rchan, 0); - update_readers_consumed(rchan, 0, 0); - - rchan_put(rchan); - - return 0; -} - -/** - * check_init_buf - check the sanity of init_buf, if present - * @init_buf: the initbuf - * @init_buf_size: the total initbuf size - * @bufsize: the channel's sub-buffer size - * @nbufs: the number of sub-buffers in the channel - * - * Returns 0 if ok, negative otherwise. - */ -static int -check_init_buf(char *init_buf, u32 init_buf_size, u32 bufsize, u32 nbufs) -{ - int err = 0; - - if (init_buf && nbufs == 1) /* 1 sub-buffer makes no sense */ - err = -EINVAL; - - if (init_buf && (bufsize * nbufs != init_buf_size)) - err = -EINVAL; - - return err; -} - -/** - * rchan_create_buf - allocate the initial channel buffer - * @rchan: the channel - * @size_alloc: the total size of the channel buffer - * - * Returns 0 if successful, negative otherwise. - */ -static inline int -rchan_create_buf(struct rchan *rchan, int size_alloc) -{ - struct page **page_array; - int page_count; - - if ((rchan->buf = (char *)alloc_rchan_buf(size_alloc, &page_array, &page_count)) == NULL) { - rchan->buf_page_array = NULL; - rchan->buf_page_count = 0; - return -ENOMEM; - } - - rchan->buf_page_array = page_array; - rchan->buf_page_count = page_count; - - return 0; -} - -/** - * rchan_create - allocate and initialize a channel, including buffer - * @chanpath: path specifying the relayfs channel file to create - * @bufsize: the size of the sub-buffers within the channel buffer - * @nbufs: the number of sub-buffers within the channel buffer - * @rchan_flags: flags specifying buffer attributes - * @err: err code - * - * Returns channel if successful, NULL otherwise, err receives errcode. - * - * Allocates a struct rchan representing a relay channel, according - * to the attributes passed in via rchan_flags. Does some basic sanity - * checking but doesn't try to do anything smart. In particular, the - * number of buffers must be a power of 2, and if the lockless scheme - * is being used, the sub-buffer size must also be a power of 2. The - * locking scheme can use buffers of any size. - */ -static struct rchan * -rchan_create(const char *chanpath, - int bufsize, - int nbufs, - u32 rchan_flags, - char *init_buf, - u32 init_buf_size, - int *err) -{ - int size_alloc; - struct rchan *rchan = NULL; - - *err = 0; - - rchan = (struct rchan *)kmalloc(sizeof(struct rchan), GFP_KERNEL); - if (rchan == NULL) { - *err = -ENOMEM; - return NULL; - } - rchan->buf = rchan->init_buf = NULL; - - *err = check_init_buf(init_buf, init_buf_size, bufsize, nbufs); - if (*err) - goto exit; - - if (nbufs == 1 && bufsize) { - rchan->n_bufs = nbufs; - rchan->buf_size = bufsize; - size_alloc = bufsize; - goto alloc; - } - - if (bufsize <= 0 || - (rchan_flags & RELAY_SCHEME_LOCKLESS && hweight32(bufsize) != 1) || - hweight32(nbufs) != 1 || - nbufs < RELAY_MIN_BUFS || - nbufs > RELAY_MAX_BUFS) { - *err = -EINVAL; - goto exit; - } - - size_alloc = FIX_SIZE(bufsize * nbufs); - if (size_alloc > RELAY_MAX_BUF_SIZE) { - *err = -EINVAL; - goto exit; - } - rchan->n_bufs = nbufs; - rchan->buf_size = bufsize; - - if (rchan_flags & RELAY_SCHEME_LOCKLESS) { - offset_bits(rchan) = ffs(bufsize) - 1; - offset_mask(rchan) = RELAY_BUF_OFFSET_MASK(offset_bits(rchan)); - bufno_bits(rchan) = ffs(nbufs) - 1; - } -alloc: - if (rchan_alloc_id(rchan) == -1) { - *err = -ENOMEM; - goto exit; - } - - if (init_buf == NULL) { - *err = rchan_create_buf(rchan, size_alloc); - if (*err) { - rchan_free_id(rchan->id); - goto exit; - } - } else - rchan->buf = rchan->init_buf = init_buf; - - rchan->alloc_size = size_alloc; - - if (rchan_flags & RELAY_SCHEME_LOCKLESS) - rchan->relay_ops = &lockless_ops; - else - rchan->relay_ops = &locking_ops; - -exit: - if (*err) { - kfree(rchan); - rchan = NULL; - } - - return rchan; -} - - -static char tmpname[NAME_MAX]; - -/** - * rchan_create_dir - create directory for file - * @chanpath: path to file, including filename - * @residual: filename remaining after parse - * @topdir: the directory filename should be created in - * - * Returns 0 if successful, negative otherwise. - * - * Inspired by xlate_proc_name() in procfs. Given a file path which - * includes the filename, creates any and all directories necessary - * to create the file. - */ -static int -rchan_create_dir(const char * chanpath, - const char **residual, - struct dentry **topdir) -{ - const char *cp = chanpath, *next; - struct dentry *parent = NULL; - int len, err = 0; - - while (1) { - next = strchr(cp, '/'); - if (!next) - break; - - len = next - cp; - - strncpy(tmpname, cp, len); - tmpname[len] = '\0'; - err = relayfs_create_dir(tmpname, parent, &parent); - if (err && (err != -EEXIST)) - return err; - cp += len + 1; - } - - *residual = cp; - *topdir = parent; - - return err; -} - -/** - * rchan_create_file - create file, including parent directories - * @chanpath: path to file, including filename - * @dentry: result dentry - * @data: data to associate with the file - * - * Returns 0 if successful, negative otherwise. - */ -static int -rchan_create_file(const char * chanpath, - struct dentry **dentry, - struct rchan * data, - int mode) -{ - int err; - const char * fname; - struct dentry *topdir; - - err = rchan_create_dir(chanpath, &fname, &topdir); - if (err && (err != -EEXIST)) - return err; - - err = relayfs_create_file(fname, topdir, dentry, (void *)data, mode); - - return err; -} - -/** - * relay_open - create a new file/channel buffer in relayfs - * @chanpath: name of file to create, including path - * @bufsize: size of sub-buffers - * @nbufs: number of sub-buffers - * @flags: channel attributes - * @callbacks: client callback functions - * @start_reserve: number of bytes to reserve at start of each sub-buffer - * @end_reserve: number of bytes to reserve at end of each sub-buffer - * @rchan_start_reserve: additional reserve at start of first sub-buffer - * @resize_min: minimum total buffer size, if set - * @resize_max: maximum total buffer size, if set - * @mode: the perms to be given to the relayfs file, 0 to accept defaults - * @init_buf: initial memory buffer to start out with, NULL if N/A - * @init_buf_size: initial memory buffer size to start out with, 0 if N/A - * - * Returns channel id if successful, negative otherwise. - * - * Creates a relay channel using the sizes and attributes specified. - * The default permissions, used if mode == 0 are S_IRUSR | S_IWUSR. See - * Documentation/filesystems/relayfs.txt for details. - */ -int -relay_open(const char *chanpath, - int bufsize, - int nbufs, - u32 flags, - struct rchan_callbacks *channel_callbacks, - u32 start_reserve, - u32 end_reserve, - u32 rchan_start_reserve, - u32 resize_min, - u32 resize_max, - int mode, - char *init_buf, - u32 init_buf_size) -{ - int err; - struct rchan *rchan; - struct dentry *dentry; - struct rchan_callbacks *callbacks = NULL; - - if (chanpath == NULL) - return -EINVAL; - - if (nbufs != 1) { - err = check_attribute_flags(&flags, resize_min ? 1 : 0); - if (err) - return err; - } - - rchan = rchan_create(chanpath, bufsize, nbufs, flags, init_buf, init_buf_size, &err); - - if (err < 0) - return err; - - /* Create file in fs */ - if ((err = rchan_create_file(chanpath, &dentry, rchan, mode)) < 0) { - rchan_destroy_buf(rchan); - rchan_free_id(rchan->id); - kfree(rchan); - return err; - } - - rchan->dentry = dentry; - - if (channel_callbacks == NULL) - callbacks = &default_channel_callbacks; - else - callbacks = channel_callbacks; - - if (callbacks->buffer_end == NULL) - callbacks->buffer_end = buffer_end_default_callback; - if (callbacks->buffer_start == NULL) - callbacks->buffer_start = buffer_start_default_callback; - if (callbacks->deliver == NULL) - callbacks->deliver = deliver_default_callback; - if (callbacks->user_deliver == NULL) - callbacks->user_deliver = user_deliver_default_callback; - if (callbacks->needs_resize == NULL) - callbacks->needs_resize = needs_resize_default_callback; - if (callbacks->fileop_notify == NULL) - callbacks->fileop_notify = fileop_notify_default_callback; - if (callbacks->ioctl == NULL) - callbacks->ioctl = ioctl_default_callback; - rchan->callbacks = callbacks; - - /* Just to let the client know the sizes used */ - rchan->callbacks->needs_resize(rchan->id, - RELAY_RESIZE_REPLACED, - rchan->buf_size, - rchan->n_bufs); - - rchan->flags = flags; - rchan->start_reserve = start_reserve; - rchan->end_reserve = end_reserve; - rchan->rchan_start_reserve = rchan_start_reserve; - - __relay_reset(rchan, 1); - - if (resize_min > 0 && resize_max > 0 && - resize_max < RELAY_MAX_TOTAL_BUF_SIZE) { - rchan->resize_min = resize_min; - rchan->resize_max = resize_max; - init_shrink_timer(rchan); - } - - rchan_get(rchan->id); - - return rchan->id; -} - -/** - * relay_discard_init_buf - alloc channel buffer and copy init_buf into it - * @rchan_id: the channel id - * - * Returns 0 if successful, negative otherwise. - * - * NOTE: May sleep. Should also be called only when the channel isn't - * actively being written into. - */ -int -relay_discard_init_buf(int rchan_id) -{ - struct rchan *rchan; - int err = 0; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - if (rchan->init_buf == NULL) { - err = -EINVAL; - goto out; - } - - err = rchan_create_buf(rchan, rchan->alloc_size); - if (err) - goto out; - - memcpy(rchan->buf, rchan->init_buf, rchan->n_bufs * rchan->buf_size); - rchan->init_buf = NULL; -out: - rchan_put(rchan); - - return err; -} - -/** - * relay_finalize - perform end-of-buffer processing for last buffer - * @rchan_id: the channel id - * @releasing: true if called when releasing file - * - * Returns 0 if successful, negative otherwise. - */ -static int -relay_finalize(int rchan_id) -{ - struct rchan *rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - if (rchan->finalized == 0) { - rchan->relay_ops->finalize(rchan); - rchan->finalized = 1; - } - - if (waitqueue_active(&rchan->read_wait)) { - PREPARE_WORK(&rchan->wake_readers, wakeup_readers, rchan); - schedule_delayed_work(&rchan->wake_readers, 1); - } - - rchan_put(rchan); - - return 0; -} - -/** - * restore_callbacks - restore default channel callbacks - * @rchan: the channel - * - * Restore callbacks to the default versions. - */ -static inline void -restore_callbacks(struct rchan *rchan) -{ - if (rchan->callbacks != &default_channel_callbacks) - rchan->callbacks = &default_channel_callbacks; -} - -/** - * relay_close - close the channel - * @rchan_id: relay channel id - * - * Finalizes the last sub-buffer and marks the channel as finalized. - * The channel buffer and channel data structure are then freed - * automatically when the last reference to the channel is given up. - */ -int -relay_close(int rchan_id) -{ - int err; - struct rchan *rchan; - - if ((rchan_id < 0) || (rchan_id >= RELAY_MAX_CHANNELS)) - return -EBADF; - - err = relay_finalize(rchan_id); - - if (!err) { - read_lock(&rchan_table_lock); - rchan = rchan_table[rchan_id]; - read_unlock(&rchan_table_lock); - - if (rchan) { - restore_callbacks(rchan); - if (rchan->resize_min) - del_timer(&rchan->shrink_timer); - rchan_put(rchan); - } - } - - return err; -} - -/** - * relay_write - reserve a slot in the channel and write data into it - * @rchan_id: relay channel id - * @data_ptr: data to be written into reserved slot - * @count: number of bytes to write - * @td_offset: optional offset where time delta should be written - * @wrote_pos: optional ptr returning buf pos written to, ignored if NULL - * - * Returns the number of bytes written, 0 or negative on failure. - * - * Reserves space in the channel and writes count bytes of data_ptr - * to it. Automatically performs any necessary locking, depending - * on the scheme and SMP usage in effect (no locking is done for the - * lockless scheme regardless of usage). - * - * If td_offset is >= 0, the internal time delta calculated when - * slot was reserved will be written at that offset. - * - * If wrote_pos is non-NULL, it will receive the location the data - * was written to, which may be needed for some applications but is not - * normally interesting. - */ -int -relay_write(int rchan_id, - const void *data_ptr, - size_t count, - int td_offset, - void **wrote_pos) -{ - unsigned long flags; - char *reserved, *write_pos; - int bytes_written = 0; - int reserve_code, interrupting; - struct timeval ts; - u32 td; - struct rchan *rchan; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - relay_lock_channel(rchan, flags); /* nop for lockless */ - - write_pos = reserved = relay_reserve(rchan, count, &ts, &td, - &reserve_code, &interrupting); - - if (reserved != NULL) { - relay_write_direct(write_pos, data_ptr, count); - if ((td_offset >= 0) && (td_offset < count - sizeof(td))) - *((u32 *)(reserved + td_offset)) = td; - bytes_written = count; - } else if (reserve_code == RELAY_WRITE_TOO_LONG) - bytes_written = -EINVAL; - - if (bytes_written > 0) - relay_commit(rchan, reserved, bytes_written, reserve_code, interrupting); - - relay_unlock_channel(rchan, flags); /* nop for lockless */ - - rchan_put(rchan); - - if (wrote_pos) - *wrote_pos = reserved; - - return bytes_written; -} - -/** - * wakeup_writers - wake up VFS writers waiting on a channel - * @private: the channel - * - * This is the work function used to defer writer waking. The - * reason waking is deferred is that calling directly from - * buffers_consumed causes problems if you're writing from say - * the scheduler. - */ -static void -wakeup_writers(void *private) -{ - struct rchan *rchan = (struct rchan *)private; - - wake_up_interruptible(&rchan->write_wait); -} - - -/** - * __relay_buffers_consumed - internal version of relay_buffers_consumed - * @rchan: the relay channel - * @bufs_consumed: number of buffers to add to current count for channel - * - * Internal - updates the channel's consumed buffer count. - */ -static void -__relay_buffers_consumed(struct rchan *rchan, u32 bufs_consumed) -{ - rchan->bufs_consumed += bufs_consumed; - - if (rchan->bufs_consumed > rchan->bufs_produced) - rchan->bufs_consumed = rchan->bufs_produced; - - atomic_set(&rchan->suspended, 0); - - PREPARE_WORK(&rchan->wake_writers, wakeup_writers, rchan); - schedule_delayed_work(&rchan->wake_writers, 1); -} - -/** - * __reader_buffers_consumed - update reader/channel consumed buffer count - * @reader: channel reader - * @bufs_consumed: number of buffers to add to current count for channel - * - * Internal - updates the reader's consumed buffer count. If the reader's - * resulting total is greater than the channel's, update the channel's. -*/ -static void -__reader_buffers_consumed(struct rchan_reader *reader, u32 bufs_consumed) -{ - reader->bufs_consumed += bufs_consumed; - - if (reader->bufs_consumed > reader->rchan->bufs_consumed) - __relay_buffers_consumed(reader->rchan, bufs_consumed); -} - -/** - * relay_buffers_consumed - add to the # buffers consumed for the channel - * @reader: channel reader - * @bufs_consumed: number of buffers to add to current count for channel - * - * Adds to the channel's consumed buffer count. buffers_consumed should - * be the number of buffers newly consumed, not the total number consumed. - * - * NOTE: kernel clients don't need to call this function if the reader - * is auto-consuming or the channel is MODE_CONTINUOUS. - */ -void -relay_buffers_consumed(struct rchan_reader *reader, u32 bufs_consumed) -{ - if (reader && reader->rchan) - __reader_buffers_consumed(reader, bufs_consumed); -} - -/** - * __relay_bytes_consumed - internal version of relay_bytes_consumed - * @rchan: the relay channel - * @bytes_consumed: number of bytes to add to current count for channel - * @read_offset: where the bytes were consumed from - * - * Internal - updates the channel's consumed count. -*/ -static void -__relay_bytes_consumed(struct rchan *rchan, u32 bytes_consumed, u32 read_offset) -{ - u32 consuming_idx; - u32 unused; - - consuming_idx = read_offset / rchan->buf_size; - - if (consuming_idx >= rchan->n_bufs) - consuming_idx = rchan->n_bufs - 1; - rchan->bytes_consumed += bytes_consumed; - - unused = rchan->unused_bytes[consuming_idx]; - - if (rchan->bytes_consumed + unused >= rchan->buf_size) { - __relay_buffers_consumed(rchan, 1); - rchan->bytes_consumed = 0; - } -} - -/** - * __reader_bytes_consumed - update reader/channel consumed count - * @reader: channel reader - * @bytes_consumed: number of bytes to add to current count for channel - * @read_offset: where the bytes were consumed from - * - * Internal - updates the reader's consumed count. If the reader's - * resulting total is greater than the channel's, update the channel's. -*/ -static void -__reader_bytes_consumed(struct rchan_reader *reader, u32 bytes_consumed, u32 read_offset) -{ - u32 consuming_idx; - u32 unused; - - consuming_idx = read_offset / reader->rchan->buf_size; - - if (consuming_idx >= reader->rchan->n_bufs) - consuming_idx = reader->rchan->n_bufs - 1; - - reader->bytes_consumed += bytes_consumed; - - unused = reader->rchan->unused_bytes[consuming_idx]; - - if (reader->bytes_consumed + unused >= reader->rchan->buf_size) { - reader->bufs_consumed++; - reader->bytes_consumed = 0; - } - - if ((reader->bufs_consumed > reader->rchan->bufs_consumed) || - ((reader->bufs_consumed == reader->rchan->bufs_consumed) && - (reader->bytes_consumed > reader->rchan->bytes_consumed))) - __relay_bytes_consumed(reader->rchan, bytes_consumed, read_offset); -} - -/** - * relay_bytes_consumed - add to the # bytes consumed for the channel - * @reader: channel reader - * @bytes_consumed: number of bytes to add to current count for channel - * @read_offset: where the bytes were consumed from - * - * Adds to the channel's consumed count. bytes_consumed should be the - * number of bytes actually read e.g. return value of relay_read() and - * the read_offset should be the actual offset the bytes were read from - * e.g. the actual_read_offset set by relay_read(). See - * Documentation/filesystems/relayfs.txt for more details. - * - * NOTE: kernel clients don't need to call this function if the reader - * is auto-consuming or the channel is MODE_CONTINUOUS. - */ -void -relay_bytes_consumed(struct rchan_reader *reader, u32 bytes_consumed, u32 read_offset) -{ - if (reader && reader->rchan) - __reader_bytes_consumed(reader, bytes_consumed, read_offset); -} - -/** - * update_readers_consumed - apply offset change to reader - * @rchan: the channel - * - * Apply the consumed counts to all readers open on the channel. - */ -void -update_readers_consumed(struct rchan *rchan, u32 bufs_consumed, u32 bytes_consumed) -{ - struct list_head *p; - struct rchan_reader *reader; - - read_lock(&rchan->open_readers_lock); - list_for_each(p, &rchan->open_readers) { - reader = list_entry(p, struct rchan_reader, list); - reader->bufs_consumed = bufs_consumed; - reader->bytes_consumed = bytes_consumed; - if (reader->vfs_reader) - reader->pos.file->f_pos = 0; - else - reader->pos.f_pos = 0; - reader->offset_changed = 1; - } - read_unlock(&rchan->open_readers_lock); -} - -/** - * do_read - utility function to do the actual read to user - * @rchan: the channel - * @buf: user buf to read into, NULL if just getting info - * @count: bytes requested - * @read_offset: offset into channel - * @new_offset: new offset into channel after read - * @actual_read_offset: read offset actually used - * - * Returns the number of bytes read, 0 if none. - */ -static ssize_t -do_read(struct rchan *rchan, char *buf, size_t count, u32 read_offset, u32 *new_offset, u32 *actual_read_offset) -{ - u32 read_bufno, cur_bufno; - u32 avail_offset, cur_idx, max_offset, buf_end_offset; - u32 avail_count, buf_size; - int unused_bytes = 0; - size_t read_count = 0; - u32 last_buf_byte_offset; - - *actual_read_offset = read_offset; - - buf_size = rchan->buf_size; - if (unlikely(!buf_size)) BUG(); - - read_bufno = read_offset / buf_size; - if (unlikely(read_bufno >= RELAY_MAX_BUFS)) BUG(); - unused_bytes = rchan->unused_bytes[read_bufno]; - - avail_offset = cur_idx = relay_get_offset(rchan, &max_offset); - - if (cur_idx == read_offset) { - if (atomic_read(&rchan->suspended) == 1) { - read_offset += 1; - if (read_offset >= max_offset) - read_offset = 0; - *actual_read_offset = read_offset; - } else { - *new_offset = read_offset; - return 0; - } - } else { - last_buf_byte_offset = (read_bufno + 1) * buf_size - 1; - if (read_offset == last_buf_byte_offset) { - if (unused_bytes != 1) { - read_offset += 1; - if (read_offset >= max_offset) - read_offset = 0; - *actual_read_offset = read_offset; - } - } - } - - read_bufno = read_offset / buf_size; - if (unlikely(read_bufno >= RELAY_MAX_BUFS)) BUG(); - unused_bytes = rchan->unused_bytes[read_bufno]; - - cur_bufno = cur_idx / buf_size; - - buf_end_offset = (read_bufno + 1) * buf_size - unused_bytes; - if (avail_offset > buf_end_offset) - avail_offset = buf_end_offset; - else if (avail_offset < read_offset) - avail_offset = buf_end_offset; - avail_count = avail_offset - read_offset; - read_count = avail_count >= count ? count : avail_count; - - if (read_count && buf != NULL) - if (copy_to_user(buf, rchan->buf + read_offset, read_count)) - return -EFAULT; - - if (read_bufno == cur_bufno) - if (read_count && (read_offset + read_count >= buf_end_offset) && (read_offset + read_count <= cur_idx)) { - *new_offset = cur_idx; - return read_count; - } - - if (read_offset + read_count + unused_bytes > max_offset) - *new_offset = 0; - else if (read_offset + read_count >= buf_end_offset) - *new_offset = read_offset + read_count + unused_bytes; - else - *new_offset = read_offset + read_count; - - return read_count; -} - -/** - * __relay_read - read bytes from channel, relative to current reader pos - * @reader: channel reader - * @buf: user buf to read into, NULL if just getting info - * @count: bytes requested - * @read_offset: offset into channel - * @new_offset: new offset into channel after read - * @actual_read_offset: read offset actually used - * @wait: if non-zero, wait for something to read - * - * Internal - see relay_read() for details. - * - * Returns the number of bytes read, 0 if none, negative on failure. - */ -static ssize_t -__relay_read(struct rchan_reader *reader, char *buf, size_t count, u32 read_offset, u32 *new_offset, u32 *actual_read_offset, int wait) -{ - int err = 0; - size_t read_count = 0; - struct rchan *rchan = reader->rchan; - - if (!wait && !rchan->initialized) - return -EAGAIN; - - if (using_lockless(rchan)) - read_offset &= idx_mask(rchan); - - if (read_offset >= rchan->n_bufs * rchan->buf_size) { - *new_offset = 0; - if (!wait) - return -EAGAIN; - else - return -EINTR; - } - - if (buf != NULL && wait) { - err = wait_event_interruptible(rchan->read_wait, - ((rchan->finalized == 1) || - (atomic_read(&rchan->suspended) == 1) || - (relay_get_offset(rchan, NULL) != read_offset))); - - if (rchan->finalized) - return 0; - - if (reader->offset_changed) { - reader->offset_changed = 0; - return -EINTR; - } - - if (err) - return err; - } - - read_count = do_read(rchan, buf, count, read_offset, new_offset, actual_read_offset); - - if (read_count < 0) - err = read_count; - - if (err) - return err; - else - return read_count; -} - -/** - * relay_read - read bytes from channel, relative to current reader pos - * @reader: channel reader - * @buf: user buf to read into, NULL if just getting info - * @count: bytes requested - * @wait: if non-zero, wait for something to read - * @actual_read_offset: set read offset actually used, must not be NULL - * - * Reads count bytes from the channel, or as much as is available within - * the sub-buffer currently being read. The read offset that will be - * read from is the position contained within the reader object. If the - * wait flag is set, buf is non-NULL, and there is nothing available, - * it will wait until there is. If the wait flag is 0 and there is - * nothing available, -EAGAIN is returned. If buf is NULL, the value - * returned is the number of bytes that would have been read. - * actual_read_offset is the value that should be passed as the read - * offset to relay_bytes_consumed, needed only if the reader is not - * auto-consuming and the channel is MODE_NO_OVERWRITE, but in any case, - * it must not be NULL. See Documentation/filesystems/relayfs.txt for - * more details. - */ -ssize_t -relay_read(struct rchan_reader *reader, char *buf, size_t count, int wait, u32 *actual_read_offset) -{ - u32 new_offset; - u32 read_offset; - ssize_t read_count; - - if (reader == NULL || reader->rchan == NULL) - return -EBADF; - - if (actual_read_offset == NULL) - return -EINVAL; - - if (reader->vfs_reader) - read_offset = (u32)(reader->pos.file->f_pos); - else - read_offset = reader->pos.f_pos; - *actual_read_offset = read_offset; - - read_count = __relay_read(reader, buf, count, read_offset, - &new_offset, actual_read_offset, wait); - - if (read_count < 0) - return read_count; - - if (reader->vfs_reader) - reader->pos.file->f_pos = new_offset; - else - reader->pos.f_pos = new_offset; - - if (reader->auto_consume && ((read_count) || (new_offset != read_offset))) - __reader_bytes_consumed(reader, read_count, *actual_read_offset); - - if (read_count == 0 && !wait) - return -EAGAIN; - - return read_count; -} - -/** - * relay_bytes_avail - number of bytes available in current sub-buffer - * @reader: channel reader - * - * Returns the number of bytes available relative to the reader's - * current read position within the corresponding sub-buffer, 0 if - * there is nothing available. See Documentation/filesystems/relayfs.txt - * for more details. - */ -ssize_t -relay_bytes_avail(struct rchan_reader *reader) -{ - u32 f_pos; - u32 new_offset; - u32 actual_read_offset; - ssize_t bytes_read; - - if (reader == NULL || reader->rchan == NULL) - return -EBADF; - - if (reader->vfs_reader) - f_pos = (u32)reader->pos.file->f_pos; - else - f_pos = reader->pos.f_pos; - new_offset = f_pos; - - bytes_read = __relay_read(reader, NULL, reader->rchan->buf_size, - f_pos, &new_offset, &actual_read_offset, 0); - - if ((new_offset != f_pos) && - ((bytes_read == -EINTR) || (bytes_read == 0))) - bytes_read = -EAGAIN; - else if ((bytes_read < 0) && (bytes_read != -EAGAIN)) - bytes_read = 0; - - return bytes_read; -} - -/** - * rchan_empty - boolean, is the channel empty wrt reader? - * @reader: channel reader - * - * Returns 1 if the channel is empty, 0 otherwise. - */ -int -rchan_empty(struct rchan_reader *reader) -{ - ssize_t avail_count; - u32 buffers_ready; - struct rchan *rchan = reader->rchan; - u32 cur_idx, curbuf_bytes; - int mapped; - - if (atomic_read(&rchan->suspended) == 1) - return 0; - - mapped = atomic_read(&rchan->mapped); - - if (mapped && bulk_delivery(rchan)) { - buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; - return buffers_ready ? 0 : 1; - } - - if (mapped && packet_delivery(rchan)) { - buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; - if (buffers_ready) - return 0; - else { - cur_idx = relay_get_offset(rchan, NULL); - curbuf_bytes = cur_idx % rchan->buf_size; - return curbuf_bytes == rchan->bytes_consumed ? 1 : 0; - } - } - - avail_count = relay_bytes_avail(reader); - - return avail_count ? 0 : 1; -} - -/** - * rchan_full - boolean, is the channel full wrt consuming reader? - * @reader: channel reader - * - * Returns 1 if the channel is full, 0 otherwise. - */ -int -rchan_full(struct rchan_reader *reader) -{ - u32 buffers_ready; - struct rchan *rchan = reader->rchan; - - if (mode_continuous(rchan)) - return 0; - - buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; - - return buffers_ready > reader->rchan->n_bufs - 1 ? 1 : 0; -} - -/** - * relay_info - get status and other information about a relay channel - * @rchan_id: relay channel id - * @rchan_info: pointer to the rchan_info struct to be filled in - * - * Fills in an rchan_info struct with channel status and attribute - * information. See Documentation/filesystems/relayfs.txt for details. - * - * Returns 0 if successful, negative otherwise. - */ -int -relay_info(int rchan_id, struct rchan_info *rchan_info) -{ - int i; - struct rchan *rchan; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - rchan_info->flags = rchan->flags; - rchan_info->buf_size = rchan->buf_size; - rchan_info->buf_addr = rchan->buf; - rchan_info->alloc_size = rchan->alloc_size; - rchan_info->n_bufs = rchan->n_bufs; - rchan_info->cur_idx = relay_get_offset(rchan, NULL); - rchan_info->bufs_produced = rchan->bufs_produced; - rchan_info->bufs_consumed = rchan->bufs_consumed; - rchan_info->buf_id = rchan->buf_id; - - for (i = 0; i < rchan->n_bufs; i++) { - rchan_info->unused_bytes[i] = rchan->unused_bytes[i]; - if (using_lockless(rchan)) - rchan_info->buffer_complete[i] = (atomic_read(&fill_count(rchan, i)) == rchan->buf_size); - else - rchan_info->buffer_complete[i] = 0; - } - - rchan_put(rchan); - - return 0; -} - -/** - * __add_rchan_reader - creates and adds a reader to a channel - * @rchan: relay channel - * @filp: the file associated with rchan, if applicable - * @auto_consume: boolean, whether reader's reads automatically consume - * @map_reader: boolean, whether reader's reading via a channel mapping - * - * Returns a pointer to the reader object create, NULL if unsuccessful - * - * Creates and initializes an rchan_reader object for reading the channel. - * If filp is non-NULL, the reader is a VFS reader, otherwise not. - * - * If the reader is a map reader, it isn't considered a VFS reader for - * our purposes. Also, map_readers can't be auto-consuming. - */ -struct rchan_reader * -__add_rchan_reader(struct rchan *rchan, struct file *filp, int auto_consume, int map_reader) -{ - struct rchan_reader *reader; - u32 will_read; - - reader = kmalloc(sizeof(struct rchan_reader), GFP_KERNEL); - - if (reader) { - write_lock(&rchan->open_readers_lock); - reader->rchan = rchan; - if (filp) { - reader->vfs_reader = 1; - reader->pos.file = filp; - } else { - reader->vfs_reader = 0; - reader->pos.f_pos = 0; - } - reader->map_reader = map_reader; - reader->auto_consume = auto_consume; - - if (!map_reader) { - will_read = rchan->bufs_produced % rchan->n_bufs; - if (!will_read && atomic_read(&rchan->suspended)) - will_read = rchan->n_bufs; - reader->bufs_consumed = rchan->bufs_produced - will_read; - rchan->bufs_consumed = reader->bufs_consumed; - rchan->bytes_consumed = reader->bytes_consumed = 0; - reader->offset_changed = 0; - } - - list_add(&reader->list, &rchan->open_readers); - write_unlock(&rchan->open_readers_lock); - } - - return reader; -} - -/** - * add_rchan_reader - create a reader for a channel - * @rchan_id: relay channel handle - * @auto_consume: boolean, whether reader's reads automatically consume - * - * Returns a pointer to the reader object created, NULL if unsuccessful - * - * Creates and initializes an rchan_reader object for reading the channel. - * This function is useful only for non-VFS readers. - */ -struct rchan_reader * -add_rchan_reader(int rchan_id, int auto_consume) -{ - struct rchan *rchan = rchan_get(rchan_id); - if (rchan == NULL) - return NULL; - - return __add_rchan_reader(rchan, NULL, auto_consume, 0); -} - -/** - * add_map_reader - create a map reader for a channel - * @rchan_id: relay channel handle - * - * Returns a pointer to the reader object created, NULL if unsuccessful - * - * Creates and initializes an rchan_reader object for reading the channel. - * This function is useful only for map readers. - */ -struct rchan_reader * -add_map_reader(int rchan_id) -{ - struct rchan *rchan = rchan_get(rchan_id); - if (rchan == NULL) - return NULL; - - return __add_rchan_reader(rchan, NULL, 0, 1); -} - -/** - * __remove_rchan_reader - destroy a channel reader - * @reader: channel reader - * - * Internal - removes reader from the open readers list, and frees it. - */ -void -__remove_rchan_reader(struct rchan_reader *reader) -{ - struct list_head *p; - struct rchan_reader *found_reader = NULL; - - write_lock(&reader->rchan->open_readers_lock); - list_for_each(p, &reader->rchan->open_readers) { - found_reader = list_entry(p, struct rchan_reader, list); - if (found_reader == reader) { - list_del(&found_reader->list); - break; - } - } - write_unlock(&reader->rchan->open_readers_lock); - - if (found_reader) - kfree(found_reader); -} - -/** - * remove_rchan_reader - destroy a channel reader - * @reader: channel reader - * - * Finds and removes the given reader from the channel. This function - * is useful only for non-VFS readers. - * - * Returns 0 if successful, negative otherwise. - */ -int -remove_rchan_reader(struct rchan_reader *reader) -{ - int err = 0; - - if (reader) { - rchan_put(reader->rchan); - __remove_rchan_reader(reader); - } else - err = -EINVAL; - - return err; -} - -/** - * remove_map_reader - destroy a map reader - * @reader: channel reader - * - * Finds and removes the given map reader from the channel. This function - * is useful only for map readers. - * - * Returns 0 if successful, negative otherwise. - */ -int -remove_map_reader(struct rchan_reader *reader) -{ - return remove_rchan_reader(reader); -} - -EXPORT_SYMBOL(relay_open); -EXPORT_SYMBOL(relay_close); -EXPORT_SYMBOL(relay_reset); -EXPORT_SYMBOL(relay_reserve); -EXPORT_SYMBOL(relay_commit); -EXPORT_SYMBOL(relay_read); -EXPORT_SYMBOL(relay_write); -EXPORT_SYMBOL(relay_bytes_avail); -EXPORT_SYMBOL(relay_buffers_consumed); -EXPORT_SYMBOL(relay_bytes_consumed); -EXPORT_SYMBOL(relay_info); -EXPORT_SYMBOL(relay_discard_init_buf); - - diff --git a/fs/relayfs/relay_locking.c b/fs/relayfs/relay_locking.c deleted file mode 100644 index 718f14967..000000000 --- a/fs/relayfs/relay_locking.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * RelayFS locking scheme implementation. - * - * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * - * This file is released under the GPL. - */ - -#include -#include "relay_locking.h" -#include "resize.h" - -/** - * switch_buffers - switches between read and write buffers. - * @cur_time: current time. - * @cur_tsc: the TSC associated with current_time, if applicable - * @rchan: the channel - * @finalizing: if true, don't start a new buffer - * @resetting: if true, - * - * This should be called from with interrupts disabled. - */ -static void -switch_buffers(struct timeval cur_time, - u32 cur_tsc, - struct rchan *rchan, - int finalizing, - int resetting, - int finalize_buffer_only) -{ - char *chan_buf_end; - int bytes_written; - - if (!rchan->half_switch) { - bytes_written = rchan->callbacks->buffer_end(rchan->id, - cur_write_pos(rchan), write_buf_end(rchan), - cur_time, cur_tsc, using_tsc(rchan)); - if (bytes_written == 0) - rchan->unused_bytes[rchan->buf_idx % rchan->n_bufs] = - write_buf_end(rchan) - cur_write_pos(rchan); - } - - if (finalize_buffer_only) { - rchan->bufs_produced++; - return; - } - - chan_buf_end = rchan->buf + rchan->n_bufs * rchan->buf_size; - if((write_buf(rchan) + rchan->buf_size >= chan_buf_end) || resetting) - write_buf(rchan) = rchan->buf; - else - write_buf(rchan) += rchan->buf_size; - write_buf_end(rchan) = write_buf(rchan) + rchan->buf_size; - write_limit(rchan) = write_buf_end(rchan) - rchan->end_reserve; - cur_write_pos(rchan) = write_buf(rchan); - - rchan->buf_start_time = cur_time; - rchan->buf_start_tsc = cur_tsc; - - if (resetting) - rchan->buf_idx = 0; - else - rchan->buf_idx++; - rchan->buf_id++; - - if (!packet_delivery(rchan)) - rchan->unused_bytes[rchan->buf_idx % rchan->n_bufs] = 0; - - if (resetting) { - rchan->bufs_produced = rchan->bufs_produced + rchan->n_bufs; - rchan->bufs_produced -= rchan->bufs_produced % rchan->n_bufs; - rchan->bufs_consumed = rchan->bufs_produced; - rchan->bytes_consumed = 0; - update_readers_consumed(rchan, rchan->bufs_consumed, rchan->bytes_consumed); - } else if (!rchan->half_switch) - rchan->bufs_produced++; - - rchan->half_switch = 0; - - if (!finalizing) { - bytes_written = rchan->callbacks->buffer_start(rchan->id, cur_write_pos(rchan), rchan->buf_id, cur_time, cur_tsc, using_tsc(rchan)); - cur_write_pos(rchan) += bytes_written; - } -} - -/** - * locking_reserve - reserve a slot in the buffer for an event. - * @rchan: the channel - * @slot_len: the length of the slot to reserve - * @ts: variable that will receive the time the slot was reserved - * @tsc: the timestamp counter associated with time - * @err: receives the result flags - * @interrupting: if this write is interrupting another, set to non-zero - * - * Returns pointer to the beginning of the reserved slot, NULL if error. - * - * The err value contains the result flags and is an ORed combination - * of the following: - * - * RELAY_BUFFER_SWITCH_NONE - no buffer switch occurred - * RELAY_EVENT_DISCARD_NONE - event should not be discarded - * RELAY_BUFFER_SWITCH - buffer switch occurred - * RELAY_EVENT_DISCARD - event should be discarded (all buffers are full) - * RELAY_EVENT_TOO_LONG - event won't fit into even an empty buffer - */ -inline char * -locking_reserve(struct rchan *rchan, - u32 slot_len, - struct timeval *ts, - u32 *tsc, - int *err, - int *interrupting) -{ - u32 buffers_ready; - int bytes_written; - - *err = RELAY_BUFFER_SWITCH_NONE; - - if (slot_len >= rchan->buf_size) { - *err = RELAY_WRITE_DISCARD | RELAY_WRITE_TOO_LONG; - return NULL; - } - - if (rchan->initialized == 0) { - rchan->initialized = 1; - get_timestamp(&rchan->buf_start_time, - &rchan->buf_start_tsc, rchan); - rchan->unused_bytes[0] = 0; - bytes_written = rchan->callbacks->buffer_start( - rchan->id, cur_write_pos(rchan), - rchan->buf_id, rchan->buf_start_time, - rchan->buf_start_tsc, using_tsc(rchan)); - cur_write_pos(rchan) += bytes_written; - *tsc = get_time_delta(ts, rchan); - return cur_write_pos(rchan); - } - - *tsc = get_time_delta(ts, rchan); - - if (in_progress_event_size(rchan)) { - interrupted_pos(rchan) = cur_write_pos(rchan); - cur_write_pos(rchan) = in_progress_event_pos(rchan) - + in_progress_event_size(rchan) - + interrupting_size(rchan); - *interrupting = 1; - } else { - in_progress_event_pos(rchan) = cur_write_pos(rchan); - in_progress_event_size(rchan) = slot_len; - interrupting_size(rchan) = 0; - } - - if (cur_write_pos(rchan) + slot_len > write_limit(rchan)) { - if (atomic_read(&rchan->suspended) == 1) { - in_progress_event_pos(rchan) = NULL; - in_progress_event_size(rchan) = 0; - interrupting_size(rchan) = 0; - *err = RELAY_WRITE_DISCARD; - return NULL; - } - - buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; - if (buffers_ready == rchan->n_bufs - 1) { - if (!mode_continuous(rchan)) { - atomic_set(&rchan->suspended, 1); - in_progress_event_pos(rchan) = NULL; - in_progress_event_size(rchan) = 0; - interrupting_size(rchan) = 0; - get_timestamp(ts, tsc, rchan); - switch_buffers(*ts, *tsc, rchan, 0, 0, 1); - recalc_time_delta(ts, tsc, rchan); - rchan->half_switch = 1; - - cur_write_pos(rchan) = write_buf_end(rchan) - 1; - *err = RELAY_BUFFER_SWITCH | RELAY_WRITE_DISCARD; - return NULL; - } - } - - get_timestamp(ts, tsc, rchan); - switch_buffers(*ts, *tsc, rchan, 0, 0, 0); - recalc_time_delta(ts, tsc, rchan); - *err = RELAY_BUFFER_SWITCH; - } - - return cur_write_pos(rchan); -} - -/** - * locking_commit - commit a reserved slot in the buffer - * @rchan: the channel - * @from: commit the length starting here - * @len: length committed - * @deliver: length committed - * @interrupting: not used - * - * Commits len bytes and calls deliver callback if applicable. - */ -inline void -locking_commit(struct rchan *rchan, - char *from, - u32 len, - int deliver, - int interrupting) -{ - cur_write_pos(rchan) += len; - - if (interrupting) { - cur_write_pos(rchan) = interrupted_pos(rchan); - interrupting_size(rchan) += len; - } else { - in_progress_event_size(rchan) = 0; - if (interrupting_size(rchan)) { - cur_write_pos(rchan) += interrupting_size(rchan); - interrupting_size(rchan) = 0; - } - } - - if (deliver) { - if (bulk_delivery(rchan)) { - u32 cur_idx = cur_write_pos(rchan) - rchan->buf; - u32 cur_bufno = cur_idx / rchan->buf_size; - from = rchan->buf + cur_bufno * rchan->buf_size; - len = cur_idx - cur_bufno * rchan->buf_size; - } - rchan->callbacks->deliver(rchan->id, from, len); - expand_check(rchan); - } -} - -/** - * locking_finalize: - finalize last buffer at end of channel use - * @rchan: the channel - */ -inline void -locking_finalize(struct rchan *rchan) -{ - unsigned long int flags; - struct timeval time; - u32 tsc; - - local_irq_save(flags); - get_timestamp(&time, &tsc, rchan); - switch_buffers(time, tsc, rchan, 1, 0, 0); - local_irq_restore(flags); -} - -/** - * locking_get_offset - get current and max 'file' offsets for VFS - * @rchan: the channel - * @max_offset: maximum channel offset - * - * Returns the current and maximum buffer offsets in VFS terms. - */ -u32 -locking_get_offset(struct rchan *rchan, - u32 *max_offset) -{ - if (max_offset) - *max_offset = rchan->buf_size * rchan->n_bufs - 1; - - return cur_write_pos(rchan) - rchan->buf; -} - -/** - * locking_reset - reset the channel - * @rchan: the channel - * @init: 1 if this is a first-time channel initialization - */ -void locking_reset(struct rchan *rchan, int init) -{ - if (init) - channel_lock(rchan) = SPIN_LOCK_UNLOCKED; - write_buf(rchan) = rchan->buf; - write_buf_end(rchan) = write_buf(rchan) + rchan->buf_size; - cur_write_pos(rchan) = write_buf(rchan); - write_limit(rchan) = write_buf_end(rchan) - rchan->end_reserve; - in_progress_event_pos(rchan) = NULL; - in_progress_event_size(rchan) = 0; - interrupted_pos(rchan) = NULL; - interrupting_size(rchan) = 0; -} - -/** - * locking_reset_index - atomically set channel index to the beginning - * @rchan: the channel - * - * If this fails, it means that something else just logged something - * and therefore we probably no longer want to do this. It's up to the - * caller anyway... - * - * Returns 0 if the index was successfully set, negative otherwise - */ -int -locking_reset_index(struct rchan *rchan, u32 old_idx) -{ - unsigned long flags; - struct timeval time; - u32 tsc; - u32 cur_idx; - - relay_lock_channel(rchan, flags); - cur_idx = locking_get_offset(rchan, NULL); - if (cur_idx != old_idx) { - relay_unlock_channel(rchan, flags); - return -1; - } - - get_timestamp(&time, &tsc, rchan); - switch_buffers(time, tsc, rchan, 0, 1, 0); - - relay_unlock_channel(rchan, flags); - - return 0; -} - - - - - - - diff --git a/fs/relayfs/relay_locking.h b/fs/relayfs/relay_locking.h deleted file mode 100644 index 3dde7df52..000000000 --- a/fs/relayfs/relay_locking.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _RELAY_LOCKING_H -#define _RELAY_LOCKING_H - -extern char * -locking_reserve(struct rchan *rchan, - u32 slot_len, - struct timeval *time_stamp, - u32 *tsc, - int *err, - int *interrupting); - -extern void -locking_commit(struct rchan *rchan, - char *from, - u32 len, - int deliver, - int interrupting); - -extern void -locking_resume(struct rchan *rchan); - -extern void -locking_finalize(struct rchan *rchan); - -extern u32 -locking_get_offset(struct rchan *rchan, u32 *max_offset); - -extern void -locking_reset(struct rchan *rchan, int init); - -extern int -locking_reset_index(struct rchan *rchan, u32 old_idx); - -#endif /* _RELAY_LOCKING_H */ diff --git a/fs/relayfs/relay_lockless.c b/fs/relayfs/relay_lockless.c deleted file mode 100644 index 98524bf61..000000000 --- a/fs/relayfs/relay_lockless.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * RelayFS lockless scheme implementation. - * - * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 2002, 2003 - Bob Wisniewski (bob@watson.ibm.com), IBM Corp - * - * This file is released under the GPL. - */ - -#include -#include "relay_lockless.h" -#include "resize.h" - -/** - * compare_and_store_volatile - self-explicit - * @ptr: ptr to the word that will receive the new value - * @oval: the value we think is currently in *ptr - * @nval: the value *ptr will get if we were right - */ -inline int -compare_and_store_volatile(volatile u32 *ptr, - u32 oval, - u32 nval) -{ - u32 prev; - - barrier(); - prev = cmpxchg(ptr, oval, nval); - barrier(); - - return (prev == oval); -} - -/** - * atomic_set_volatile - atomically set the value in ptr to nval. - * @ptr: ptr to the word that will receive the new value - * @nval: the new value - */ -inline void -atomic_set_volatile(atomic_t *ptr, - u32 nval) -{ - barrier(); - atomic_set(ptr, (int)nval); - barrier(); -} - -/** - * atomic_add_volatile - atomically add val to the value at ptr. - * @ptr: ptr to the word that will receive the addition - * @val: the value to add to *ptr - */ -inline void -atomic_add_volatile(atomic_t *ptr, u32 val) -{ - barrier(); - atomic_add((int)val, ptr); - barrier(); -} - -/** - * atomic_sub_volatile - atomically substract val from the value at ptr. - * @ptr: ptr to the word that will receive the subtraction - * @val: the value to subtract from *ptr - */ -inline void -atomic_sub_volatile(atomic_t *ptr, s32 val) -{ - barrier(); - atomic_sub((int)val, ptr); - barrier(); -} - -/** - * lockless_commit - commit a reserved slot in the buffer - * @rchan: the channel - * @from: commit the length starting here - * @len: length committed - * @deliver: length committed - * @interrupting: not used - * - * Commits len bytes and calls deliver callback if applicable. - */ -inline void -lockless_commit(struct rchan *rchan, - char *from, - u32 len, - int deliver, - int interrupting) -{ - u32 bufno, idx; - - idx = from - rchan->buf; - - if (len > 0) { - bufno = RELAY_BUFNO_GET(idx, offset_bits(rchan)); - atomic_add_volatile(&fill_count(rchan, bufno), len); - } - - if (deliver) { - u32 mask = offset_mask(rchan); - if (bulk_delivery(rchan)) { - from = rchan->buf + RELAY_BUF_OFFSET_CLEAR(idx, mask); - len += RELAY_BUF_OFFSET_GET(idx, mask); - } - rchan->callbacks->deliver(rchan->id, from, len); - expand_check(rchan); - } -} - -/** - * get_buffer_end - get the address of the end of buffer - * @rchan: the channel - * @buf_idx: index into channel corresponding to address - */ -static inline char * -get_buffer_end(struct rchan *rchan, u32 buf_idx) -{ - return rchan->buf - + RELAY_BUF_OFFSET_CLEAR(buf_idx, offset_mask(rchan)) - + RELAY_BUF_SIZE(offset_bits(rchan)); -} - - -/** - * finalize_buffer - utility function consolidating end-of-buffer tasks. - * @rchan: the channel - * @end_idx: index into buffer to write the end-buffer event at - * @size_lost: number of unused bytes at the end of the buffer - * @time_stamp: the time of the end-buffer event - * @tsc: the timestamp counter associated with time - * @resetting: are we resetting the channel? - * - * This function must be called with local irqs disabled. - */ -static inline void -finalize_buffer(struct rchan *rchan, - u32 end_idx, - u32 size_lost, - struct timeval *time_stamp, - u32 *tsc, - int resetting) -{ - char* cur_write_pos; - char* write_buf_end; - u32 bufno; - int bytes_written; - - cur_write_pos = rchan->buf + end_idx; - write_buf_end = get_buffer_end(rchan, end_idx - 1); - - bytes_written = rchan->callbacks->buffer_end(rchan->id, cur_write_pos, - write_buf_end, *time_stamp, *tsc, using_tsc(rchan)); - if (bytes_written == 0) - rchan->unused_bytes[rchan->buf_idx % rchan->n_bufs] = size_lost; - - bufno = RELAY_BUFNO_GET(end_idx, offset_bits(rchan)); - atomic_add_volatile(&fill_count(rchan, bufno), size_lost); - if (resetting) { - rchan->bufs_produced = rchan->bufs_produced + rchan->n_bufs; - rchan->bufs_produced -= rchan->bufs_produced % rchan->n_bufs; - rchan->bufs_consumed = rchan->bufs_produced; - rchan->bytes_consumed = 0; - update_readers_consumed(rchan, rchan->bufs_consumed, rchan->bytes_consumed); - } else - rchan->bufs_produced++; -} - -/** - * lockless_finalize: - finalize last buffer at end of channel use - * @rchan: the channel - */ -inline void -lockless_finalize(struct rchan *rchan) -{ - u32 event_end_idx; - u32 size_lost; - unsigned long int flags; - struct timeval time; - u32 tsc; - - event_end_idx = RELAY_BUF_OFFSET_GET(idx(rchan), offset_mask(rchan)); - size_lost = RELAY_BUF_SIZE(offset_bits(rchan)) - event_end_idx; - - local_irq_save(flags); - get_timestamp(&time, &tsc, rchan); - finalize_buffer(rchan, idx(rchan) & idx_mask(rchan), size_lost, - &time, &tsc, 0); - local_irq_restore(flags); -} - -/** - * discard_check: - determine whether a write should be discarded - * @rchan: the channel - * @old_idx: index into buffer where check for space should begin - * @write_len: the length of the write to check - * @time_stamp: the time of the end-buffer event - * @tsc: the timestamp counter associated with time - * - * The return value contains the result flags and is an ORed combination - * of the following: - * - * RELAY_WRITE_DISCARD_NONE - write should not be discarded - * RELAY_BUFFER_SWITCH - buffer switch occurred - * RELAY_WRITE_DISCARD - write should be discarded (all buffers are full) - * RELAY_WRITE_TOO_LONG - write won't fit into even an empty buffer - */ -static inline int -discard_check(struct rchan *rchan, - u32 old_idx, - u32 write_len, - struct timeval *time_stamp, - u32 *tsc) -{ - u32 buffers_ready; - u32 offset_mask = offset_mask(rchan); - u8 offset_bits = offset_bits(rchan); - u32 idx_mask = idx_mask(rchan); - u32 size_lost; - unsigned long int flags; - - if (write_len > RELAY_BUF_SIZE(offset_bits)) - return RELAY_WRITE_DISCARD | RELAY_WRITE_TOO_LONG; - - if (mode_continuous(rchan)) - return RELAY_WRITE_DISCARD_NONE; - - local_irq_save(flags); - if (atomic_read(&rchan->suspended) == 1) { - local_irq_restore(flags); - return RELAY_WRITE_DISCARD; - } - if (rchan->half_switch) { - local_irq_restore(flags); - return RELAY_WRITE_DISCARD_NONE; - } - buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; - if (buffers_ready == rchan->n_bufs - 1) { - atomic_set(&rchan->suspended, 1); - size_lost = RELAY_BUF_SIZE(offset_bits) - - RELAY_BUF_OFFSET_GET(old_idx, offset_mask); - finalize_buffer(rchan, old_idx & idx_mask, size_lost, - time_stamp, tsc, 0); - rchan->half_switch = 1; - idx(rchan) = RELAY_BUF_OFFSET_CLEAR((old_idx & idx_mask), offset_mask(rchan)) + RELAY_BUF_SIZE(offset_bits) - 1; - local_irq_restore(flags); - - return RELAY_BUFFER_SWITCH | RELAY_WRITE_DISCARD; - } - local_irq_restore(flags); - - return RELAY_WRITE_DISCARD_NONE; -} - -/** - * switch_buffers - switch over to a new sub-buffer - * @rchan: the channel - * @slot_len: the length of the slot needed for the current write - * @offset: the offset calculated for the new index - * @ts: timestamp - * @tsc: the timestamp counter associated with time - * @old_idx: the value of the buffer control index when we were called - * @old_idx: the new calculated value of the buffer control index - * @resetting: are we resetting the channel? - */ -static inline void -switch_buffers(struct rchan *rchan, - u32 slot_len, - u32 offset, - struct timeval *ts, - u32 *tsc, - u32 new_idx, - u32 old_idx, - int resetting) -{ - u32 size_lost = rchan->end_reserve; - unsigned long int flags; - u32 idx_mask = idx_mask(rchan); - u8 offset_bits = offset_bits(rchan); - char *cur_write_pos; - u32 new_buf_no; - u32 start_reserve = rchan->start_reserve; - - if (resetting) - size_lost = RELAY_BUF_SIZE(offset_bits(rchan)) - old_idx % rchan->buf_size; - - if (offset > 0) - size_lost += slot_len - offset; - else - old_idx += slot_len; - - local_irq_save(flags); - if (!rchan->half_switch) - finalize_buffer(rchan, old_idx & idx_mask, size_lost, - ts, tsc, resetting); - rchan->half_switch = 0; - rchan->buf_start_time = *ts; - rchan->buf_start_tsc = *tsc; - local_irq_restore(flags); - - cur_write_pos = rchan->buf + RELAY_BUF_OFFSET_CLEAR((new_idx - & idx_mask), offset_mask(rchan)); - if (resetting) - rchan->buf_idx = 0; - else - rchan->buf_idx++; - rchan->buf_id++; - - rchan->unused_bytes[rchan->buf_idx % rchan->n_bufs] = 0; - - rchan->callbacks->buffer_start(rchan->id, cur_write_pos, - rchan->buf_id, *ts, *tsc, using_tsc(rchan)); - new_buf_no = RELAY_BUFNO_GET(new_idx & idx_mask, offset_bits); - atomic_sub_volatile(&fill_count(rchan, new_buf_no), - RELAY_BUF_SIZE(offset_bits) - start_reserve); - if (atomic_read(&fill_count(rchan, new_buf_no)) < start_reserve) - atomic_set_volatile(&fill_count(rchan, new_buf_no), - start_reserve); -} - -/** - * lockless_reserve_slow - the slow reserve path in the lockless scheme - * @rchan: the channel - * @slot_len: the length of the slot to reserve - * @ts: variable that will receive the time the slot was reserved - * @tsc: the timestamp counter associated with time - * @old_idx: the value of the buffer control index when we were called - * @err: receives the result flags - * - * Returns pointer to the beginning of the reserved slot, NULL if error. - - * err values same as for lockless_reserve. - */ -static inline char * -lockless_reserve_slow(struct rchan *rchan, - u32 slot_len, - struct timeval *ts, - u32 *tsc, - u32 old_idx, - int *err) -{ - u32 new_idx, offset; - unsigned long int flags; - u32 offset_mask = offset_mask(rchan); - u32 idx_mask = idx_mask(rchan); - u32 start_reserve = rchan->start_reserve; - u32 end_reserve = rchan->end_reserve; - int discard_event; - u32 reserved_idx; - char *cur_write_pos; - int initializing = 0; - - *err = RELAY_BUFFER_SWITCH_NONE; - - discard_event = discard_check(rchan, old_idx, slot_len, ts, tsc); - if (discard_event != RELAY_WRITE_DISCARD_NONE) { - *err = discard_event; - return NULL; - } - - local_irq_save(flags); - if (rchan->initialized == 0) { - rchan->initialized = initializing = 1; - idx(rchan) = rchan->start_reserve + rchan->rchan_start_reserve; - } - local_irq_restore(flags); - - do { - old_idx = idx(rchan); - new_idx = old_idx + slot_len; - - offset = RELAY_BUF_OFFSET_GET(new_idx + end_reserve, - offset_mask); - if ((offset < slot_len) && (offset > 0)) { - reserved_idx = RELAY_BUF_OFFSET_CLEAR(new_idx - + end_reserve, offset_mask) + start_reserve; - new_idx = reserved_idx + slot_len; - } else if (offset < slot_len) { - reserved_idx = old_idx; - new_idx = RELAY_BUF_OFFSET_CLEAR(new_idx - + end_reserve, offset_mask) + start_reserve; - } else - reserved_idx = old_idx; - get_timestamp(ts, tsc, rchan); - } while (!compare_and_store_volatile(&idx(rchan), old_idx, new_idx)); - - reserved_idx &= idx_mask; - - if (initializing == 1) { - cur_write_pos = rchan->buf - + RELAY_BUF_OFFSET_CLEAR((old_idx & idx_mask), - offset_mask(rchan)); - rchan->buf_start_time = *ts; - rchan->buf_start_tsc = *tsc; - rchan->unused_bytes[0] = 0; - - rchan->callbacks->buffer_start(rchan->id, cur_write_pos, - rchan->buf_id, *ts, *tsc, using_tsc(rchan)); - } - - if (offset < slot_len) { - switch_buffers(rchan, slot_len, offset, ts, tsc, new_idx, - old_idx, 0); - *err = RELAY_BUFFER_SWITCH; - } - - /* If not using TSC, need to calc time delta */ - recalc_time_delta(ts, tsc, rchan); - - return rchan->buf + reserved_idx; -} - -/** - * lockless_reserve - reserve a slot in the buffer for an event. - * @rchan: the channel - * @slot_len: the length of the slot to reserve - * @ts: variable that will receive the time the slot was reserved - * @tsc: the timestamp counter associated with time - * @err: receives the result flags - * @interrupting: not used - * - * Returns pointer to the beginning of the reserved slot, NULL if error. - * - * The err value contains the result flags and is an ORed combination - * of the following: - * - * RELAY_BUFFER_SWITCH_NONE - no buffer switch occurred - * RELAY_EVENT_DISCARD_NONE - event should not be discarded - * RELAY_BUFFER_SWITCH - buffer switch occurred - * RELAY_EVENT_DISCARD - event should be discarded (all buffers are full) - * RELAY_EVENT_TOO_LONG - event won't fit into even an empty buffer - */ -inline char * -lockless_reserve(struct rchan *rchan, - u32 slot_len, - struct timeval *ts, - u32 *tsc, - int *err, - int *interrupting) -{ - u32 old_idx, new_idx, offset; - u32 offset_mask = offset_mask(rchan); - - do { - old_idx = idx(rchan); - new_idx = old_idx + slot_len; - - offset = RELAY_BUF_OFFSET_GET(new_idx + rchan->end_reserve, - offset_mask); - if (offset < slot_len) - return lockless_reserve_slow(rchan, slot_len, - ts, tsc, old_idx, err); - get_time_or_tsc(ts, tsc, rchan); - } while (!compare_and_store_volatile(&idx(rchan), old_idx, new_idx)); - - /* If not using TSC, need to calc time delta */ - recalc_time_delta(ts, tsc, rchan); - - *err = RELAY_BUFFER_SWITCH_NONE; - - return rchan->buf + (old_idx & idx_mask(rchan)); -} - -/** - * lockless_get_offset - get current and max channel offsets - * @rchan: the channel - * @max_offset: maximum channel offset - * - * Returns the current and maximum channel offsets. - */ -u32 -lockless_get_offset(struct rchan *rchan, - u32 *max_offset) -{ - if (max_offset) - *max_offset = rchan->buf_size * rchan->n_bufs - 1; - - return rchan->initialized ? idx(rchan) & idx_mask(rchan) : 0; -} - -/** - * lockless_reset - reset the channel - * @rchan: the channel - * @init: 1 if this is a first-time channel initialization - */ -void lockless_reset(struct rchan *rchan, int init) -{ - int i; - - /* Start first buffer at 0 - (end_reserve + 1) so that it - gets initialized via buffer_start callback as well. */ - idx(rchan) = 0UL - (rchan->end_reserve + 1); - idx_mask(rchan) = - (1UL << (bufno_bits(rchan) + offset_bits(rchan))) - 1; - atomic_set(&fill_count(rchan, 0), - (int)rchan->start_reserve + - (int)rchan->rchan_start_reserve); - for (i = 1; i < rchan->n_bufs; i++) - atomic_set(&fill_count(rchan, i), - (int)RELAY_BUF_SIZE(offset_bits(rchan))); -} - -/** - * lockless_reset_index - atomically set channel index to the beginning - * @rchan: the channel - * @old_idx: the current index - * - * If this fails, it means that something else just logged something - * and therefore we probably no longer want to do this. It's up to the - * caller anyway... - * - * Returns 0 if the index was successfully set, negative otherwise - */ -int -lockless_reset_index(struct rchan *rchan, u32 old_idx) -{ - struct timeval ts; - u32 tsc; - u32 new_idx; - - if (compare_and_store_volatile(&idx(rchan), old_idx, 0)) { - new_idx = rchan->start_reserve; - switch_buffers(rchan, 0, 0, &ts, &tsc, new_idx, old_idx, 1); - return 0; - } else - return -1; -} - - - - - - - - - - - - - diff --git a/fs/relayfs/relay_lockless.h b/fs/relayfs/relay_lockless.h deleted file mode 100644 index 8d4189e8c..000000000 --- a/fs/relayfs/relay_lockless.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _RELAY_LOCKLESS_H -#define _RELAY_LOCKLESS_H - -extern char * -lockless_reserve(struct rchan *rchan, - u32 slot_len, - struct timeval *time_stamp, - u32 *tsc, - int * interrupting, - int * errcode); - -extern void -lockless_commit(struct rchan *rchan, - char * from, - u32 len, - int deliver, - int interrupting); - -extern void -lockless_resume(struct rchan *rchan); - -extern void -lockless_finalize(struct rchan *rchan); - -extern u32 -lockless_get_offset(struct rchan *rchan, u32 *max_offset); - -extern void -lockless_reset(struct rchan *rchan, int init); - -extern int -lockless_reset_index(struct rchan *rchan, u32 old_idx); - -#endif/* _RELAY_LOCKLESS_H */ diff --git a/fs/relayfs/resize.c b/fs/relayfs/resize.c deleted file mode 100644 index 25f00bfa6..000000000 --- a/fs/relayfs/resize.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * RelayFS buffer management and resizing code. - * - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include "resize.h" - -/** - * alloc_page_array - alloc array to hold pages, but not pages - * @size: the total size of the memory represented by the page array - * @page_count: the number of pages the array can hold - * @err: 0 on success, negative otherwise - * - * Returns a pointer to the page array if successful, NULL otherwise. - */ -static struct page ** -alloc_page_array(int size, int *page_count, int *err) -{ - int n_pages; - struct page **page_array; - int page_array_size; - - *err = 0; - - size = PAGE_ALIGN(size); - n_pages = size >> PAGE_SHIFT; - page_array_size = n_pages * sizeof(struct page *); - page_array = kmalloc(page_array_size, GFP_KERNEL); - if (page_array == NULL) { - *err = -ENOMEM; - return NULL; - } - *page_count = n_pages; - memset(page_array, 0, page_array_size); - - return page_array; -} - -/** - * free_page_array - free array to hold pages, but not pages - * @page_array: pointer to the page array - */ -static inline void -free_page_array(struct page **page_array) -{ - kfree(page_array); -} - -/** - * depopulate_page_array - free and unreserve all pages in the array - * @page_array: pointer to the page array - * @page_count: number of pages to free - */ -static void -depopulate_page_array(struct page **page_array, int page_count) -{ - int i; - - for (i = 0; i < page_count; i++) { - ClearPageReserved(page_array[i]); - __free_page(page_array[i]); - } -} - -/** - * populate_page_array - allocate and reserve pages - * @page_array: pointer to the page array - * @page_count: number of pages to allocate - * - * Returns 0 if successful, negative otherwise. - */ -static int -populate_page_array(struct page **page_array, int page_count) -{ - int i; - - for (i = 0; i < page_count; i++) { - page_array[i] = alloc_page(GFP_KERNEL); - if (unlikely(!page_array[i])) { - depopulate_page_array(page_array, i); - return -ENOMEM; - } - SetPageReserved(page_array[i]); - } - return 0; -} - -/** - * alloc_rchan_buf - allocate the initial channel buffer - * @size: total size of the buffer - * @page_array: receives a pointer to the buffer's page array - * @page_count: receives the number of pages allocated - * - * Returns a pointer to the resulting buffer, NULL if unsuccessful - */ -void * -alloc_rchan_buf(unsigned long size, struct page ***page_array, int *page_count) -{ - void *mem; - int err; - - *page_array = alloc_page_array(size, page_count, &err); - if (!*page_array) - return NULL; - - err = populate_page_array(*page_array, *page_count); - if (err) { - free_page_array(*page_array); - *page_array = NULL; - return NULL; - } - - mem = vmap(*page_array, *page_count, GFP_KERNEL, PAGE_KERNEL); - if (!mem) { - depopulate_page_array(*page_array, *page_count); - free_page_array(*page_array); - *page_array = NULL; - return NULL; - } - memset(mem, 0, size); - - return mem; -} - -/** - * free_rchan_buf - free a channel buffer - * @buf: pointer to the buffer to free - * @page_array: pointer to the buffer's page array - * @page_count: number of pages in page array - */ -void -free_rchan_buf(void *buf, struct page **page_array, int page_count) -{ - vunmap(buf); - depopulate_page_array(page_array, page_count); - free_page_array(page_array); -} - -/** - * expand_check - check whether the channel needs expanding - * @rchan: the channel - * - * If the channel needs expanding, the needs_resize callback is - * called with RELAY_RESIZE_EXPAND. - * - * Returns the suggested number of sub-buffers for the new - * buffer. - */ -void -expand_check(struct rchan *rchan) -{ - u32 active_bufs; - u32 new_n_bufs = 0; - u32 threshold = rchan->n_bufs * RESIZE_THRESHOLD; - - if (rchan->init_buf) - return; - - if (rchan->resize_min == 0) - return; - - if (rchan->resizing || rchan->replace_buffer) - return; - - active_bufs = rchan->bufs_produced - rchan->bufs_consumed + 1; - - if (rchan->resize_max && active_bufs == threshold) { - new_n_bufs = rchan->n_bufs * 2; - } - - if (new_n_bufs && (new_n_bufs * rchan->buf_size <= rchan->resize_max)) - rchan->callbacks->needs_resize(rchan->id, - RELAY_RESIZE_EXPAND, - rchan->buf_size, - new_n_bufs); -} - -/** - * can_shrink - check whether the channel can shrink - * @rchan: the channel - * @cur_idx: the current channel index - * - * Returns the suggested number of sub-buffers for the new - * buffer, 0 if the buffer is not shrinkable. - */ -static inline u32 -can_shrink(struct rchan *rchan, u32 cur_idx) -{ - u32 active_bufs = rchan->bufs_produced - rchan->bufs_consumed + 1; - u32 new_n_bufs = 0; - u32 cur_bufno_bytes = cur_idx % rchan->buf_size; - - if (rchan->resize_min == 0 || - rchan->resize_min >= rchan->n_bufs * rchan->buf_size) - goto out; - - if (active_bufs > 1) - goto out; - - if (cur_bufno_bytes != rchan->bytes_consumed) - goto out; - - new_n_bufs = rchan->resize_min / rchan->buf_size; -out: - return new_n_bufs; -} - -/** - * shrink_check: - timer function checking whether the channel can shrink - * @data: unused - * - * Every SHRINK_TIMER_SECS, check whether the channel is shrinkable. - * If so, we attempt to atomically reset the channel to the beginning. - * The needs_resize callback is then called with RELAY_RESIZE_SHRINK. - * If the reset fails, it means we really shouldn't be shrinking now - * and need to wait until the next time around. - */ -static void -shrink_check(unsigned long data) -{ - struct rchan *rchan = (struct rchan *)data; - u32 shrink_to_nbufs, cur_idx; - - del_timer(&rchan->shrink_timer); - rchan->shrink_timer.expires = jiffies + SHRINK_TIMER_SECS * HZ; - add_timer(&rchan->shrink_timer); - - if (rchan->init_buf) - return; - - if (rchan->resizing || rchan->replace_buffer) - return; - - if (using_lockless(rchan)) - cur_idx = idx(rchan); - else - cur_idx = relay_get_offset(rchan, NULL); - - shrink_to_nbufs = can_shrink(rchan, cur_idx); - if (shrink_to_nbufs != 0 && reset_index(rchan, cur_idx) == 0) { - update_readers_consumed(rchan, rchan->bufs_consumed, 0); - rchan->callbacks->needs_resize(rchan->id, - RELAY_RESIZE_SHRINK, - rchan->buf_size, - shrink_to_nbufs); - } -} - -/** - * init_shrink_timer: - Start timer used to check shrinkability. - * @rchan: the channel - */ -void -init_shrink_timer(struct rchan *rchan) -{ - if (rchan->resize_min) { - init_timer(&rchan->shrink_timer); - rchan->shrink_timer.function = shrink_check; - rchan->shrink_timer.data = (unsigned long)rchan; - rchan->shrink_timer.expires = jiffies + SHRINK_TIMER_SECS * HZ; - add_timer(&rchan->shrink_timer); - } -} - - -/** - * alloc_new_pages - allocate new pages for expanding buffer - * @rchan: the channel - * - * Returns 0 on success, negative otherwise. - */ -static int -alloc_new_pages(struct rchan *rchan) -{ - int new_pages_size, err; - - if (unlikely(rchan->expand_page_array)) BUG(); - - new_pages_size = rchan->resize_alloc_size - rchan->alloc_size; - rchan->expand_page_array = alloc_page_array(new_pages_size, - &rchan->expand_page_count, &err); - if (rchan->expand_page_array == NULL) { - rchan->resize_err = -ENOMEM; - return -ENOMEM; - } - - err = populate_page_array(rchan->expand_page_array, - rchan->expand_page_count); - if (err) { - rchan->resize_err = -ENOMEM; - free_page_array(rchan->expand_page_array); - rchan->expand_page_array = NULL; - } - - return err; -} - -/** - * clear_resize_offset - helper function for buffer resizing - * @rchan: the channel - * - * Clear the saved offset change. - */ -static inline void -clear_resize_offset(struct rchan *rchan) -{ - rchan->resize_offset.ge = 0UL; - rchan->resize_offset.le = 0UL; - rchan->resize_offset.delta = 0; -} - -/** - * save_resize_offset - helper function for buffer resizing - * @rchan: the channel - * @ge: affected region ge this - * @le: affected region le this - * @delta: apply this delta - * - * Save a resize offset. - */ -static inline void -save_resize_offset(struct rchan *rchan, u32 ge, u32 le, int delta) -{ - rchan->resize_offset.ge = ge; - rchan->resize_offset.le = le; - rchan->resize_offset.delta = delta; -} - -/** - * update_file_offset - apply offset change to reader - * @reader: the channel reader - * @change_idx: the offset index into the offsets array - * - * Returns non-zero if the offset was applied. - * - * Apply the offset delta saved in change_idx to the reader's - * current read position. - */ -static inline int -update_file_offset(struct rchan_reader *reader) -{ - int applied = 0; - struct rchan *rchan = reader->rchan; - u32 f_pos; - int delta = reader->rchan->resize_offset.delta; - - if (reader->vfs_reader) - f_pos = (u32)reader->pos.file->f_pos; - else - f_pos = reader->pos.f_pos; - - if (f_pos == relay_get_offset(rchan, NULL)) - return 0; - - if ((f_pos >= rchan->resize_offset.ge - 1) && - (f_pos <= rchan->resize_offset.le)) { - if (reader->vfs_reader) - reader->pos.file->f_pos += delta; - else - reader->pos.f_pos += delta; - applied = 1; - } - - return applied; -} - -/** - * update_file_offsets - apply offset change to readers - * @rchan: the channel - * - * Apply the saved offset deltas to all files open on the channel. - */ -static inline void -update_file_offsets(struct rchan *rchan) -{ - struct list_head *p; - struct rchan_reader *reader; - - read_lock(&rchan->open_readers_lock); - list_for_each(p, &rchan->open_readers) { - reader = list_entry(p, struct rchan_reader, list); - if (update_file_offset(reader)) - reader->offset_changed = 1; - } - read_unlock(&rchan->open_readers_lock); -} - -/** - * setup_expand_buf - setup expand buffer for replacement - * @rchan: the channel - * @newsize: the size of the new buffer - * @oldsize: the size of the old buffer - * @old_n_bufs: the number of sub-buffers in the old buffer - * - * Inserts new pages into the old buffer to create a larger - * new channel buffer, splitting them at old_cur_idx, the bottom - * half of the old buffer going to the bottom of the new, likewise - * for the top half. - */ -static void -setup_expand_buf(struct rchan *rchan, int newsize, int oldsize, u32 old_n_bufs) -{ - u32 cur_idx; - int cur_bufno, delta, i, j; - u32 ge, le; - int cur_pageno; - u32 free_bufs, free_pages; - u32 free_pages_in_cur_buf; - u32 free_bufs_to_end; - u32 cur_pages = rchan->alloc_size >> PAGE_SHIFT; - u32 pages_per_buf = cur_pages / rchan->n_bufs; - u32 bufs_ready = rchan->bufs_produced - rchan->bufs_consumed; - - if (!rchan->resize_page_array || !rchan->expand_page_array || - !rchan->buf_page_array) - return; - - if (bufs_ready >= rchan->n_bufs) { - bufs_ready = rchan->n_bufs; - free_bufs = 0; - } else - free_bufs = rchan->n_bufs - bufs_ready - 1; - - cur_idx = relay_get_offset(rchan, NULL); - cur_pageno = cur_idx / PAGE_SIZE; - cur_bufno = cur_idx / rchan->buf_size; - - free_pages_in_cur_buf = (pages_per_buf - 1) - (cur_pageno % pages_per_buf); - free_pages = free_bufs * pages_per_buf + free_pages_in_cur_buf; - free_bufs_to_end = (rchan->n_bufs - 1) - cur_bufno; - if (free_bufs >= free_bufs_to_end) { - free_pages = free_bufs_to_end * pages_per_buf + free_pages_in_cur_buf; - free_bufs = free_bufs_to_end; - } - - for (i = 0, j = 0; i <= cur_pageno + free_pages; i++, j++) - rchan->resize_page_array[j] = rchan->buf_page_array[i]; - for (i = 0; i < rchan->expand_page_count; i++, j++) - rchan->resize_page_array[j] = rchan->expand_page_array[i]; - for (i = cur_pageno + free_pages + 1; i < rchan->buf_page_count; i++, j++) - rchan->resize_page_array[j] = rchan->buf_page_array[i]; - - delta = newsize - oldsize; - ge = (cur_pageno + 1 + free_pages) * PAGE_SIZE; - le = oldsize; - save_resize_offset(rchan, ge, le, delta); - - rchan->expand_buf_id = rchan->buf_id + 1 + free_bufs; -} - -/** - * setup_shrink_buf - setup shrink buffer for replacement - * @rchan: the channel - * - * Removes pages from the old buffer to create a smaller - * new channel buffer. - */ -static void -setup_shrink_buf(struct rchan *rchan) -{ - int i; - int copy_end_page; - - if (!rchan->resize_page_array || !rchan->shrink_page_array || - !rchan->buf_page_array) - return; - - copy_end_page = rchan->resize_alloc_size / PAGE_SIZE; - - for (i = 0; i < copy_end_page; i++) - rchan->resize_page_array[i] = rchan->buf_page_array[i]; -} - -/** - * cleanup_failed_alloc - relaybuf_alloc helper - */ -static void -cleanup_failed_alloc(struct rchan *rchan) -{ - if (rchan->expand_page_array) { - depopulate_page_array(rchan->expand_page_array, - rchan->expand_page_count); - free_page_array(rchan->expand_page_array); - rchan->expand_page_array = NULL; - rchan->expand_page_count = 0; - } else if (rchan->shrink_page_array) { - free_page_array(rchan->shrink_page_array); - rchan->shrink_page_array = NULL; - rchan->shrink_page_count = 0; - } - - if (rchan->resize_page_array) { - free_page_array(rchan->resize_page_array); - rchan->resize_page_array = NULL; - rchan->resize_page_count = 0; - } -} - -/** - * relaybuf_alloc - allocate a new resized channel buffer - * @private: pointer to the channel struct - * - * Internal - manages the allocation and remapping of new channel - * buffers. - */ -static void -relaybuf_alloc(void *private) -{ - struct rchan *rchan = (struct rchan *)private; - int i, j, err; - u32 old_cur_idx; - int free_size; - int free_start_page, free_end_page; - u32 newsize, oldsize; - - if (rchan->resize_alloc_size > rchan->alloc_size) { - err = alloc_new_pages(rchan); - if (err) goto cleanup; - } else { - free_size = rchan->alloc_size - rchan->resize_alloc_size; - BUG_ON(free_size <= 0); - rchan->shrink_page_array = alloc_page_array(free_size, - &rchan->shrink_page_count, &err); - if (rchan->shrink_page_array == NULL) - goto cleanup; - free_start_page = rchan->resize_alloc_size / PAGE_SIZE; - free_end_page = rchan->alloc_size / PAGE_SIZE; - for (i = 0, j = free_start_page; j < free_end_page; i++, j++) - rchan->shrink_page_array[i] = rchan->buf_page_array[j]; - } - - rchan->resize_page_array = alloc_page_array(rchan->resize_alloc_size, - &rchan->resize_page_count, &err); - if (rchan->resize_page_array == NULL) - goto cleanup; - - old_cur_idx = relay_get_offset(rchan, NULL); - clear_resize_offset(rchan); - newsize = rchan->resize_alloc_size; - oldsize = rchan->alloc_size; - if (newsize > oldsize) - setup_expand_buf(rchan, newsize, oldsize, rchan->n_bufs); - else - setup_shrink_buf(rchan); - - rchan->resize_buf = vmap(rchan->resize_page_array, rchan->resize_page_count, GFP_KERNEL, PAGE_KERNEL); - - if (rchan->resize_buf == NULL) - goto cleanup; - - rchan->replace_buffer = 1; - rchan->resizing = 0; - - rchan->callbacks->needs_resize(rchan->id, RELAY_RESIZE_REPLACE, 0, 0); - return; - -cleanup: - cleanup_failed_alloc(rchan); - rchan->resize_err = -ENOMEM; - return; -} - -/** - * relaybuf_free - free a resized channel buffer - * @private: pointer to the channel struct - * - * Internal - manages the de-allocation and unmapping of old channel - * buffers. - */ -static void -relaybuf_free(void *private) -{ - struct free_rchan_buf *free_buf = (struct free_rchan_buf *)private; - int i; - - if (free_buf->unmap_buf) - vunmap(free_buf->unmap_buf); - - for (i = 0; i < 3; i++) { - if (!free_buf->page_array[i].array) - continue; - if (free_buf->page_array[i].count) - depopulate_page_array(free_buf->page_array[i].array, - free_buf->page_array[i].count); - free_page_array(free_buf->page_array[i].array); - } - - kfree(free_buf); -} - -/** - * calc_order - determine the power-of-2 order of a resize - * @high: the larger size - * @low: the smaller size - * - * Returns order - */ -static inline int -calc_order(u32 high, u32 low) -{ - int order = 0; - - if (!high || !low || high <= low) - return 0; - - while (high > low) { - order++; - high /= 2; - } - - return order; -} - -/** - * check_size - check the sanity of the requested channel size - * @rchan: the channel - * @nbufs: the new number of sub-buffers - * @err: return code - * - * Returns the non-zero total buffer size if ok, otherwise 0 and - * sets errcode if not. - */ -static inline u32 -check_size(struct rchan *rchan, u32 nbufs, int *err) -{ - u32 new_channel_size = 0; - - *err = 0; - - if (nbufs > rchan->n_bufs) { - rchan->resize_order = calc_order(nbufs, rchan->n_bufs); - if (!rchan->resize_order) { - *err = -EINVAL; - goto out; - } - - new_channel_size = rchan->buf_size * nbufs; - if (new_channel_size > rchan->resize_max) { - *err = -EINVAL; - goto out; - } - } else if (nbufs < rchan->n_bufs) { - if (rchan->n_bufs < 2) { - *err = -EINVAL; - goto out; - } - rchan->resize_order = -calc_order(rchan->n_bufs, nbufs); - if (!rchan->resize_order) { - *err = -EINVAL; - goto out; - } - - new_channel_size = rchan->buf_size * nbufs; - if (new_channel_size < rchan->resize_min) { - *err = -EINVAL; - goto out; - } - } else - *err = -EINVAL; -out: - return new_channel_size; -} - -/** - * __relay_realloc_buffer - allocate a new channel buffer - * @rchan: the channel - * @new_nbufs: the new number of sub-buffers - * @async: do the allocation using a work queue - * - * Internal - see relay_realloc_buffer() for details. - */ -static int -__relay_realloc_buffer(struct rchan *rchan, u32 new_nbufs, int async) -{ - u32 new_channel_size; - int err = 0; - - if (new_nbufs == rchan->n_bufs) - return -EINVAL; - - if (down_trylock(&rchan->resize_sem)) - return -EBUSY; - - if (rchan->init_buf) { - err = -EPERM; - goto out; - } - - if (rchan->replace_buffer) { - err = -EBUSY; - goto out; - } - - if (rchan->resizing) { - err = -EBUSY; - goto out; - } else - rchan->resizing = 1; - - if (rchan->resize_failures > MAX_RESIZE_FAILURES) { - err = -ENOMEM; - goto out; - } - - new_channel_size = check_size(rchan, new_nbufs, &err); - if (err) - goto out; - - rchan->resize_n_bufs = new_nbufs; - rchan->resize_buf_size = rchan->buf_size; - rchan->resize_alloc_size = FIX_SIZE(new_channel_size); - - if (async) { - INIT_WORK(&rchan->work, relaybuf_alloc, rchan); - schedule_delayed_work(&rchan->work, 1); - } else - relaybuf_alloc((void *)rchan); -out: - up(&rchan->resize_sem); - - return err; -} - -/** - * relay_realloc_buffer - allocate a new channel buffer - * @rchan_id: the channel id - * @bufsize: the new sub-buffer size - * @nbufs: the new number of sub-buffers - * - * Allocates a new channel buffer using the specified sub-buffer size - * and count. If async is non-zero, the allocation is done in the - * background using a work queue. When the allocation has completed, - * the needs_resize() callback is called with a resize_type of - * RELAY_RESIZE_REPLACE. This function doesn't replace the old buffer - * with the new - see relay_replace_buffer(). See - * Documentation/filesystems/relayfs.txt for more details. - * - * Returns 0 on success, or errcode if the channel is busy or if - * the allocation couldn't happen for some reason. - */ -int -relay_realloc_buffer(int rchan_id, u32 new_nbufs, int async) -{ - int err; - - struct rchan *rchan; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - err = __relay_realloc_buffer(rchan, new_nbufs, async); - - rchan_put(rchan); - - return err; -} - -/** - * expand_cancel_check - check whether the current expand needs canceling - * @rchan: the channel - * - * Returns 1 if the expand should be canceled, 0 otherwise. - */ -static int -expand_cancel_check(struct rchan *rchan) -{ - if (rchan->buf_id >= rchan->expand_buf_id) - return 1; - else - return 0; -} - -/** - * shrink_cancel_check - check whether the current shrink needs canceling - * @rchan: the channel - * - * Returns 1 if the shrink should be canceled, 0 otherwise. - */ -static int -shrink_cancel_check(struct rchan *rchan, u32 newsize) -{ - u32 active_bufs = rchan->bufs_produced - rchan->bufs_consumed + 1; - u32 cur_idx = relay_get_offset(rchan, NULL); - - if (cur_idx >= newsize) - return 1; - - if (active_bufs > 1) - return 1; - - return 0; -} - -/** - * switch_rchan_buf - do_replace_buffer helper - */ -static void -switch_rchan_buf(struct rchan *rchan, - int newsize, - int oldsize, - u32 old_nbufs, - u32 cur_idx) -{ - u32 newbufs, cur_bufno; - int i; - - cur_bufno = cur_idx / rchan->buf_size; - - rchan->buf = rchan->resize_buf; - rchan->alloc_size = rchan->resize_alloc_size; - rchan->n_bufs = rchan->resize_n_bufs; - - if (newsize > oldsize) { - u32 ge = rchan->resize_offset.ge; - u32 moved_buf = ge / rchan->buf_size; - - newbufs = (newsize - oldsize) / rchan->buf_size; - for (i = moved_buf; i < old_nbufs; i++) { - if (using_lockless(rchan)) - atomic_set(&fill_count(rchan, i + newbufs), - atomic_read(&fill_count(rchan, i))); - rchan->unused_bytes[i + newbufs] = rchan->unused_bytes[i]; - } - for (i = moved_buf; i < moved_buf + newbufs; i++) { - if (using_lockless(rchan)) - atomic_set(&fill_count(rchan, i), - (int)RELAY_BUF_SIZE(offset_bits(rchan))); - rchan->unused_bytes[i] = 0; - } - } - - rchan->buf_idx = cur_bufno; - - if (!using_lockless(rchan)) { - cur_write_pos(rchan) = rchan->buf + cur_idx; - write_buf(rchan) = rchan->buf + cur_bufno * rchan->buf_size; - write_buf_end(rchan) = write_buf(rchan) + rchan->buf_size; - write_limit(rchan) = write_buf_end(rchan) - rchan->end_reserve; - } else { - idx(rchan) &= idx_mask(rchan); - bufno_bits(rchan) += rchan->resize_order; - idx_mask(rchan) = - (1UL << (bufno_bits(rchan) + offset_bits(rchan))) - 1; - } -} - -/** - * do_replace_buffer - does the work of channel buffer replacement - * @rchan: the channel - * @newsize: new channel buffer size - * @oldsize: old channel buffer size - * @old_n_bufs: old channel sub-buffer count - * - * Returns 0 if replacement happened, 1 if canceled - * - * Does the work of switching buffers and fixing everything up - * so the channel can continue with a new size. - */ -static int -do_replace_buffer(struct rchan *rchan, - int newsize, - int oldsize, - u32 old_nbufs) -{ - u32 cur_idx; - int err = 0; - int canceled; - - cur_idx = relay_get_offset(rchan, NULL); - - if (newsize > oldsize) - canceled = expand_cancel_check(rchan); - else - canceled = shrink_cancel_check(rchan, newsize); - - if (canceled) { - err = -EAGAIN; - goto out; - } - - switch_rchan_buf(rchan, newsize, oldsize, old_nbufs, cur_idx); - - if (rchan->resize_offset.delta) - update_file_offsets(rchan); - - atomic_set(&rchan->suspended, 0); - - rchan->old_buf_page_array = rchan->buf_page_array; - rchan->buf_page_array = rchan->resize_page_array; - rchan->buf_page_count = rchan->resize_page_count; - rchan->resize_page_array = NULL; - rchan->resize_page_count = 0; - rchan->resize_buf = NULL; - rchan->resize_buf_size = 0; - rchan->resize_alloc_size = 0; - rchan->resize_n_bufs = 0; - rchan->resize_err = 0; - rchan->resize_order = 0; -out: - rchan->callbacks->needs_resize(rchan->id, - RELAY_RESIZE_REPLACED, - rchan->buf_size, - rchan->n_bufs); - return err; -} - -/** - * add_free_page_array - add a page_array to be freed - * @free_rchan_buf: the free_rchan_buf struct - * @page_array: the page array to free - * @page_count: the number of pages to free, 0 to free the array only - * - * Internal - Used add page_arrays to be freed asynchronously. - */ -static inline void -add_free_page_array(struct free_rchan_buf *free_rchan_buf, - struct page **page_array, int page_count) -{ - int cur = free_rchan_buf->cur++; - - free_rchan_buf->page_array[cur].array = page_array; - free_rchan_buf->page_array[cur].count = page_count; -} - -/** - * free_replaced_buffer - free a channel's old buffer - * @rchan: the channel - * @oldbuf: the old buffer - * @oldsize: old buffer size - * - * Frees a channel buffer via work queue. - */ -static int -free_replaced_buffer(struct rchan *rchan, char *oldbuf, int oldsize) -{ - struct free_rchan_buf *free_buf; - - free_buf = kmalloc(sizeof(struct free_rchan_buf), GFP_ATOMIC); - if (!free_buf) - return -ENOMEM; - memset(free_buf, 0, sizeof(struct free_rchan_buf)); - - free_buf->unmap_buf = oldbuf; - add_free_page_array(free_buf, rchan->old_buf_page_array, 0); - rchan->old_buf_page_array = NULL; - add_free_page_array(free_buf, rchan->expand_page_array, 0); - add_free_page_array(free_buf, rchan->shrink_page_array, rchan->shrink_page_count); - - rchan->expand_page_array = NULL; - rchan->expand_page_count = 0; - rchan->shrink_page_array = NULL; - rchan->shrink_page_count = 0; - - INIT_WORK(&free_buf->work, relaybuf_free, free_buf); - schedule_delayed_work(&free_buf->work, 1); - - return 0; -} - -/** - * free_canceled_resize - free buffers allocated for a canceled resize - * @rchan: the channel - * - * Frees canceled buffers via work queue. - */ -static int -free_canceled_resize(struct rchan *rchan) -{ - struct free_rchan_buf *free_buf; - - free_buf = kmalloc(sizeof(struct free_rchan_buf), GFP_ATOMIC); - if (!free_buf) - return -ENOMEM; - memset(free_buf, 0, sizeof(struct free_rchan_buf)); - - if (rchan->resize_alloc_size > rchan->alloc_size) - add_free_page_array(free_buf, rchan->expand_page_array, rchan->expand_page_count); - else - add_free_page_array(free_buf, rchan->shrink_page_array, 0); - - add_free_page_array(free_buf, rchan->resize_page_array, 0); - free_buf->unmap_buf = rchan->resize_buf; - - rchan->expand_page_array = NULL; - rchan->expand_page_count = 0; - rchan->shrink_page_array = NULL; - rchan->shrink_page_count = 0; - rchan->resize_page_array = NULL; - rchan->resize_page_count = 0; - rchan->resize_buf = NULL; - - INIT_WORK(&free_buf->work, relaybuf_free, free_buf); - schedule_delayed_work(&free_buf->work, 1); - - return 0; -} - -/** - * __relay_replace_buffer - replace channel buffer with new buffer - * @rchan: the channel - * - * Internal - see relay_replace_buffer() for details. - * - * Returns 0 if successful, negative otherwise. - */ -static int -__relay_replace_buffer(struct rchan *rchan) -{ - int oldsize; - int err = 0; - char *oldbuf; - - if (down_trylock(&rchan->resize_sem)) - return -EBUSY; - - if (rchan->init_buf) { - err = -EPERM; - goto out; - } - - if (!rchan->replace_buffer) - goto out; - - if (rchan->resizing) { - err = -EBUSY; - goto out; - } - - if (rchan->resize_buf == NULL) { - err = -EINVAL; - goto out; - } - - oldbuf = rchan->buf; - oldsize = rchan->alloc_size; - - err = do_replace_buffer(rchan, rchan->resize_alloc_size, - oldsize, rchan->n_bufs); - if (err == 0) - err = free_replaced_buffer(rchan, oldbuf, oldsize); - else - err = free_canceled_resize(rchan); -out: - rchan->replace_buffer = 0; - up(&rchan->resize_sem); - - return err; -} - -/** - * relay_replace_buffer - replace channel buffer with new buffer - * @rchan_id: the channel id - * - * Replaces the current channel buffer with the new buffer allocated - * by relay_alloc_buffer and contained in the channel struct. When the - * replacement is complete, the needs_resize() callback is called with - * RELAY_RESIZE_REPLACED. - * - * Returns 0 on success, or errcode if the channel is busy or if - * the replacement or previous allocation didn't happen for some reason. - */ -int -relay_replace_buffer(int rchan_id) -{ - int err; - - struct rchan *rchan; - - rchan = rchan_get(rchan_id); - if (rchan == NULL) - return -EBADF; - - err = __relay_replace_buffer(rchan); - - rchan_put(rchan); - - return err; -} - -EXPORT_SYMBOL(relay_realloc_buffer); -EXPORT_SYMBOL(relay_replace_buffer); - diff --git a/fs/relayfs/resize.h b/fs/relayfs/resize.h deleted file mode 100644 index 6f06d221d..000000000 --- a/fs/relayfs/resize.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _RELAY_RESIZE_H -#define _RELAY_RESIZE_H - -/* - * If the channel usage has been below the low water mark for more than - * this amount of time, we can shrink the buffer if necessary. - */ -#define SHRINK_TIMER_SECS 60 - -/* This inspired by rtai/shmem */ -#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE - -/* Don't attempt resizing again after this many failures */ -#define MAX_RESIZE_FAILURES 1 - -/* Trigger resizing if a resizable channel is this full */ -#define RESIZE_THRESHOLD 3 / 4 - -/* - * Used for deferring resized channel free - */ -struct free_rchan_buf -{ - char *unmap_buf; - struct - { - struct page **array; - int count; - } page_array[3]; - - int cur; - struct work_struct work; /* resize de-allocation work struct */ -}; - -extern void * -alloc_rchan_buf(unsigned long size, - struct page ***page_array, - int *page_count); - -extern void -free_rchan_buf(void *buf, - struct page **page_array, - int page_count); - -extern void -expand_check(struct rchan *rchan); - -extern void -init_shrink_timer(struct rchan *rchan); - -#endif/* _RELAY_RESIZE_H */ diff --git a/fs/xfs/linux-2.6/mutex.h b/fs/xfs/linux-2.6/mutex.h deleted file mode 100644 index 0b296bb94..000000000 --- a/fs/xfs/linux-2.6/mutex.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_MUTEX_H__ -#define __XFS_SUPPORT_MUTEX_H__ - -#include -#include - -/* - * Map the mutex'es from IRIX to Linux semaphores. - * - * Destroy just simply initializes to -99 which should block all other - * callers. - */ -#define MUTEX_DEFAULT 0x0 -typedef struct semaphore mutex_t; - -#define mutex_init(lock, type, name) sema_init(lock, 1) -#define mutex_destroy(lock) sema_init(lock, -99) -#define mutex_lock(lock, num) down(lock) -#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1) -#define mutex_unlock(lock) up(lock) - -#endif /* __XFS_SUPPORT_MUTEX_H__ */ diff --git a/fs/xfs/linux-2.6/spin.h b/fs/xfs/linux-2.6/spin.h deleted file mode 100644 index bcf60a0b8..000000000 --- a/fs/xfs/linux-2.6/spin.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_SPIN_H__ -#define __XFS_SUPPORT_SPIN_H__ - -#include /* preempt needs this */ -#include - -/* - * Map lock_t from IRIX to Linux spinlocks. - * - * We do not make use of lock_t from interrupt context, so we do not - * have to worry about disabling interrupts at all (unlike IRIX). - */ - -typedef spinlock_t lock_t; - -#define SPLDECL(s) unsigned long s - -#define spinlock_init(lock, name) spin_lock_init(lock) -#define spinlock_destroy(lock) -#define mutex_spinlock(lock) ({ spin_lock(lock); 0; }) -#define mutex_spinunlock(lock, s) do { spin_unlock(lock); (void)s; } while (0) -#define nested_spinlock(lock) spin_lock(lock) -#define nested_spinunlock(lock) spin_unlock(lock) - -#endif /* __XFS_SUPPORT_SPIN_H__ */ diff --git a/fs/xfs/linux-2.6/time.h b/fs/xfs/linux-2.6/time.h deleted file mode 100644 index 6c6fd0faa..000000000 --- a/fs/xfs/linux-2.6/time.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUPPORT_TIME_H__ -#define __XFS_SUPPORT_TIME_H__ - -#include -#include - -typedef struct timespec timespec_t; - -static inline void delay(long ticks) -{ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(ticks); -} - -static inline void nanotime(struct timespec *tvp) -{ - *tvp = CURRENT_TIME; -} - -#endif /* __XFS_SUPPORT_TIME_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h deleted file mode 100644 index 00c45849d..000000000 --- a/fs/xfs/linux-2.6/xfs_cred.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_CRED_H__ -#define __XFS_CRED_H__ - -/* - * Credentials - */ -typedef struct cred { - /* EMPTY */ -} cred_t; - -extern struct cred *sys_cred; - -/* this is a hack.. (assums sys_cred is the only cred_t in the system) */ -static __inline int capable_cred(cred_t *cr, int cid) -{ - return (cr == sys_cred) ? 1 : capable(cid); -} - -#endif /* __XFS_CRED_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h deleted file mode 100644 index 198b8dd78..000000000 --- a/fs/xfs/linux-2.6/xfs_fs_subr.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SUBR_H__ -#define __XFS_SUBR_H__ - -/* - * Utilities shared among file system implementations. - */ - -struct cred; - -extern int fs_noerr(void); -extern int fs_nosys(void); -extern int fs_nodev(void); -extern void fs_noval(void); -extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); -extern void fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); -extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int); - -#endif /* __XFS_FS_SUBR_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h deleted file mode 100644 index e81e2f38a..000000000 --- a/fs/xfs/linux-2.6/xfs_globals.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_GLOBALS_H__ -#define __XFS_GLOBALS_H__ - -/* - * This file declares globals needed by XFS that were normally defined - * somewhere else in IRIX. - */ - -extern uint64_t xfs_panic_mask; /* set to cause more panics */ -extern unsigned long xfs_physmem; -extern struct cred *sys_cred; - -#endif /* __XFS_GLOBALS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c deleted file mode 100644 index e7d4eba4c..000000000 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include "xfs.h" -#include "xfs_fs.h" -#include "xfs_inum.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_sb.h" -#include "xfs_ag.h" -#include "xfs_dir.h" -#include "xfs_dir2.h" -#include "xfs_alloc.h" -#include "xfs_dmapi.h" -#include "xfs_quota.h" -#include "xfs_mount.h" -#include "xfs_alloc_btree.h" -#include "xfs_bmap_btree.h" -#include "xfs_ialloc_btree.h" -#include "xfs_btree.h" -#include "xfs_ialloc.h" -#include "xfs_attr_sf.h" -#include "xfs_dir_sf.h" -#include "xfs_dir2_sf.h" -#include "xfs_dinode.h" -#include "xfs_inode.h" -#include "xfs_bmap.h" -#include "xfs_bit.h" -#include "xfs_rtalloc.h" -#include "xfs_error.h" -#include "xfs_itable.h" -#include "xfs_rw.h" -#include "xfs_acl.h" -#include "xfs_cap.h" -#include "xfs_mac.h" -#include "xfs_attr.h" -#include "xfs_buf_item.h" -#include "xfs_utils.h" - -#include - - -/* - * Pull the link count and size up from the xfs inode to the linux inode - */ -STATIC void -validate_fields( - struct inode *ip) -{ - vnode_t *vp = LINVFS_GET_VP(ip); - vattr_t va; - int error; - - va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; - VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error); - if (likely(!error)) { - ip->i_nlink = va.va_nlink; - ip->i_blocks = va.va_nblocks; - - /* we're under i_sem so i_size can't change under us */ - if (i_size_read(ip) != va.va_size) - i_size_write(ip, va.va_size); - } -} - -/* - * Determine whether a process has a valid fs_struct (kernel daemons - * like knfsd don't have an fs_struct). - * - * XXX(hch): nfsd is broken, better fix it instead. - */ -STATIC inline int -has_fs_struct(struct task_struct *task) -{ - return (task->fs != init_task.fs); -} - -STATIC int -linvfs_mknod( - struct inode *dir, - struct dentry *dentry, - int mode, - dev_t rdev) -{ - struct inode *ip; - vattr_t va; - vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); - xfs_acl_t *default_acl = NULL; - attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; - int error; - - /* - * Irix uses Missed'em'V split, but doesn't want to see - * the upper 5 bits of (14bit) major. - */ - if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) - return -EINVAL; - - if (test_default_acl && test_default_acl(dvp)) { - if (!_ACL_ALLOC(default_acl)) - return -ENOMEM; - if (!_ACL_GET_DEFAULT(dvp, default_acl)) { - _ACL_FREE(default_acl); - default_acl = NULL; - } - } - - if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) - mode &= ~current->fs->umask; - - memset(&va, 0, sizeof(va)); - va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - va.va_type = IFTOVT(mode); - va.va_mode = mode; - - switch (mode & S_IFMT) { - case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - va.va_rdev = sysv_encode_dev(rdev); - va.va_mask |= XFS_AT_RDEV; - /*FALLTHROUGH*/ - case S_IFREG: - VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); - break; - case S_IFDIR: - VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); - break; - default: - error = EINVAL; - break; - } - - if (default_acl) { - if (!error) { - error = _ACL_INHERIT(vp, &va, default_acl); - if (!error) { - VMODIFY(vp); - } else { - struct dentry teardown = {}; - int err2; - - /* Oh, the horror. - * If we can't add the ACL we must back out. - * ENOSPC can hit here, among other things. - */ - teardown.d_inode = ip = LINVFS_GET_IP(vp); - teardown.d_name = dentry->d_name; - remove_inode_hash(ip); - make_bad_inode(ip); - if (S_ISDIR(mode)) - VOP_RMDIR(dvp, &teardown, NULL, err2); - else - VOP_REMOVE(dvp, &teardown, NULL, err2); - VN_RELE(vp); - } - } - _ACL_FREE(default_acl); - } - - if (!error) { - ASSERT(vp); - ip = LINVFS_GET_IP(vp); - - if (S_ISCHR(mode) || S_ISBLK(mode)) - ip->i_rdev = rdev; - else if (S_ISDIR(mode)) - validate_fields(ip); - d_instantiate(dentry, ip); - validate_fields(dir); - } - return -error; -} - -STATIC int -linvfs_create( - struct inode *dir, - struct dentry *dentry, - int mode, - struct nameidata *nd) -{ - return linvfs_mknod(dir, dentry, mode, 0); -} - -STATIC int -linvfs_mkdir( - struct inode *dir, - struct dentry *dentry, - int mode) -{ - return linvfs_mknod(dir, dentry, mode|S_IFDIR, 0); -} - -STATIC struct dentry * -linvfs_lookup( - struct inode *dir, - struct dentry *dentry, - struct nameidata *nd) -{ - struct inode *ip = NULL; - vnode_t *vp, *cvp = NULL; - int error; - - if (dentry->d_name.len >= MAXNAMELEN) - return ERR_PTR(-ENAMETOOLONG); - - vp = LINVFS_GET_VP(dir); - VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error); - if (!error) { - ASSERT(cvp); - ip = LINVFS_GET_IP(cvp); - if (!ip) { - VN_RELE(cvp); - return ERR_PTR(-EACCES); - } - } - if (error && (error != ENOENT)) - return ERR_PTR(-error); - return d_splice_alias(ip, dentry); -} - -STATIC int -linvfs_link( - struct dentry *old_dentry, - struct inode *dir, - struct dentry *dentry) -{ - struct inode *ip; /* inode of guy being linked to */ - vnode_t *tdvp; /* target directory for new name/link */ - vnode_t *vp; /* vp of name being linked */ - int error; - - ip = old_dentry->d_inode; /* inode being linked to */ - if (S_ISDIR(ip->i_mode)) - return -EPERM; - - tdvp = LINVFS_GET_VP(dir); - vp = LINVFS_GET_VP(ip); - - VOP_LINK(tdvp, vp, dentry, NULL, error); - if (!error) { - VMODIFY(tdvp); - VN_HOLD(vp); - validate_fields(ip); - d_instantiate(dentry, ip); - } - return -error; -} - -STATIC int -linvfs_unlink( - struct inode *dir, - struct dentry *dentry) -{ - struct inode *inode; - vnode_t *dvp; /* directory containing name to remove */ - int error; - - inode = dentry->d_inode; - dvp = LINVFS_GET_VP(dir); - - VOP_REMOVE(dvp, dentry, NULL, error); - if (!error) { - validate_fields(dir); /* For size only */ - validate_fields(inode); - } - - return -error; -} - -STATIC int -linvfs_symlink( - struct inode *dir, - struct dentry *dentry, - const char *symname) -{ - struct inode *ip; - vattr_t va; - vnode_t *dvp; /* directory containing name to remove */ - vnode_t *cvp; /* used to lookup symlink to put in dentry */ - int error; - - dvp = LINVFS_GET_VP(dir); - cvp = NULL; - - memset(&va, 0, sizeof(va)); - va.va_type = VLNK; - va.va_mode = irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO; - va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - - error = 0; - VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); - if (!error && cvp) { - ASSERT(cvp->v_type == VLNK); - ip = LINVFS_GET_IP(cvp); - d_instantiate(dentry, ip); - validate_fields(dir); - validate_fields(ip); /* size needs update */ - } - return -error; -} - -STATIC int -linvfs_rmdir( - struct inode *dir, - struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - vnode_t *dvp = LINVFS_GET_VP(dir); - int error; - - VOP_RMDIR(dvp, dentry, NULL, error); - if (!error) { - validate_fields(inode); - validate_fields(dir); - } - return -error; -} - -STATIC int -linvfs_rename( - struct inode *odir, - struct dentry *odentry, - struct inode *ndir, - struct dentry *ndentry) -{ - struct inode *new_inode = ndentry->d_inode; - vnode_t *fvp; /* from directory */ - vnode_t *tvp; /* target directory */ - int error; - - fvp = LINVFS_GET_VP(odir); - tvp = LINVFS_GET_VP(ndir); - - VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); - if (error) - return -error; - - if (new_inode) - validate_fields(new_inode); - - validate_fields(odir); - if (ndir != odir) - validate_fields(ndir); - return 0; -} - -STATIC int -linvfs_readlink( - struct dentry *dentry, - char *buf, - int size) -{ - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); - uio_t uio; - iovec_t iov; - int error; - - iov.iov_base = buf; - iov.iov_len = size; - - uio.uio_iov = &iov; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_resid = size; - uio.uio_iovcnt = 1; - - VOP_READLINK(vp, &uio, 0, NULL, error); - if (error) - return -error; - - return (size - uio.uio_resid); -} - -/* - * careful here - this function can get called recursively, so - * we need to be very careful about how much stack we use. - * uio is kmalloced for this reason... - */ -STATIC int -linvfs_follow_link( - struct dentry *dentry, - struct nameidata *nd) -{ - vnode_t *vp; - uio_t *uio; - iovec_t iov; - int error; - char *link; - - ASSERT(dentry); - ASSERT(nd); - - link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); - if (!link) { - nd_set_link(nd, ERR_PTR(-ENOMEM)); - return 0; - } - - uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL); - if (!uio) { - kfree(link); - nd_set_link(nd, ERR_PTR(-ENOMEM)); - return 0; - } - - vp = LINVFS_GET_VP(dentry->d_inode); - - iov.iov_base = link; - iov.iov_len = MAXNAMELEN; - - uio->uio_iov = &iov; - uio->uio_offset = 0; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_resid = MAXNAMELEN; - uio->uio_iovcnt = 1; - - VOP_READLINK(vp, uio, 0, NULL, error); - if (error) { - kfree(link); - link = ERR_PTR(-error); - } else { - link[MAXNAMELEN - uio->uio_resid] = '\0'; - } - kfree(uio); - - nd_set_link(nd, link); - return 0; -} - -static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd) -{ - char *s = nd_get_link(nd); - if (!IS_ERR(s)) - kfree(s); -} - -#ifdef CONFIG_XFS_POSIX_ACL -STATIC int -linvfs_permission( - struct inode *inode, - int mode, - struct nameidata *nd) -{ - vnode_t *vp = LINVFS_GET_VP(inode); - int error; - - mode <<= 6; /* convert from linux to vnode access bits */ - VOP_ACCESS(vp, mode, NULL, error); - return -error; -} -#else -#define linvfs_permission NULL -#endif - -STATIC int -linvfs_getattr( - struct vfsmount *mnt, - struct dentry *dentry, - struct kstat *stat) -{ - struct inode *inode = dentry->d_inode; - vnode_t *vp = LINVFS_GET_VP(inode); - int error = 0; - - if (unlikely(vp->v_flag & VMODIFIED)) - error = vn_revalidate(vp); - if (!error) - generic_fillattr(inode, stat); - return 0; -} - -STATIC int -linvfs_setattr( - struct dentry *dentry, - struct iattr *attr) -{ - struct inode *inode = dentry->d_inode; - unsigned int ia_valid = attr->ia_valid; - vnode_t *vp = LINVFS_GET_VP(inode); - vattr_t vattr; - int flags = 0; - int error; - - memset(&vattr, 0, sizeof(vattr_t)); - if (ia_valid & ATTR_UID) { - vattr.va_mask |= XFS_AT_UID; - vattr.va_uid = attr->ia_uid; - } - if (ia_valid & ATTR_GID) { - vattr.va_mask |= XFS_AT_GID; - vattr.va_gid = attr->ia_gid; - } - if (ia_valid & ATTR_SIZE) { - vattr.va_mask |= XFS_AT_SIZE; - vattr.va_size = attr->ia_size; - } - if (ia_valid & ATTR_ATIME) { - vattr.va_mask |= XFS_AT_ATIME; - vattr.va_atime = attr->ia_atime; - } - if (ia_valid & ATTR_MTIME) { - vattr.va_mask |= XFS_AT_MTIME; - vattr.va_mtime = attr->ia_mtime; - } - if (ia_valid & ATTR_CTIME) { - vattr.va_mask |= XFS_AT_CTIME; - vattr.va_ctime = attr->ia_ctime; - } - if (ia_valid & ATTR_MODE) { - vattr.va_mask |= XFS_AT_MODE; - vattr.va_mode = attr->ia_mode; - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - inode->i_mode &= ~S_ISGID; - } - - if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) - flags |= ATTR_UTIME; -#ifdef ATTR_NO_BLOCK - if ((ia_valid & ATTR_NO_BLOCK)) - flags |= ATTR_NONBLOCK; -#endif - - VOP_SETATTR(vp, &vattr, flags, NULL, error); - if (error) - return -error; - vn_revalidate(vp); - return error; -} - -STATIC void -linvfs_truncate( - struct inode *inode) -{ - block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block); -} - -STATIC int -linvfs_setxattr( - struct dentry *dentry, - const char *name, - const void *data, - size_t size, - int flags) -{ - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); - char *attr = (char *)name; - attrnames_t *namesp; - int xflags = 0; - int error; - - namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT); - if (!namesp) - return -EOPNOTSUPP; - attr += namesp->attr_namelen; - error = namesp->attr_capable(vp, NULL); - if (error) - return error; - - /* Convert Linux syscall to XFS internal ATTR flags */ - if (flags & XATTR_CREATE) - xflags |= ATTR_CREATE; - if (flags & XATTR_REPLACE) - xflags |= ATTR_REPLACE; - xflags |= namesp->attr_flag; - return namesp->attr_set(vp, attr, (void *)data, size, xflags); -} - -STATIC ssize_t -linvfs_getxattr( - struct dentry *dentry, - const char *name, - void *data, - size_t size) -{ - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); - char *attr = (char *)name; - attrnames_t *namesp; - int xflags = 0; - ssize_t error; - - namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT); - if (!namesp) - return -EOPNOTSUPP; - attr += namesp->attr_namelen; - error = namesp->attr_capable(vp, NULL); - if (error) - return error; - - /* Convert Linux syscall to XFS internal ATTR flags */ - if (!size) { - xflags |= ATTR_KERNOVAL; - data = NULL; - } - xflags |= namesp->attr_flag; - return namesp->attr_get(vp, attr, (void *)data, size, xflags); -} - -STATIC ssize_t -linvfs_listxattr( - struct dentry *dentry, - char *data, - size_t size) -{ - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); - int error, xflags = ATTR_KERNAMELS; - ssize_t result; - - if (!size) - xflags |= ATTR_KERNOVAL; - xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS; - - error = attr_generic_list(vp, data, size, xflags, &result); - if (error < 0) - return error; - return result; -} - -STATIC int -linvfs_removexattr( - struct dentry *dentry, - const char *name) -{ - vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); - char *attr = (char *)name; - attrnames_t *namesp; - int xflags = 0; - int error; - - namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT); - if (!namesp) - return -EOPNOTSUPP; - attr += namesp->attr_namelen; - error = namesp->attr_capable(vp, NULL); - if (error) - return error; - xflags |= namesp->attr_flag; - return namesp->attr_remove(vp, attr, xflags); -} - - -struct inode_operations linvfs_file_inode_operations = { - .permission = linvfs_permission, - .truncate = linvfs_truncate, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, -}; - -struct inode_operations linvfs_dir_inode_operations = { - .create = linvfs_create, - .lookup = linvfs_lookup, - .link = linvfs_link, - .unlink = linvfs_unlink, - .symlink = linvfs_symlink, - .mkdir = linvfs_mkdir, - .rmdir = linvfs_rmdir, - .mknod = linvfs_mknod, - .rename = linvfs_rename, - .permission = linvfs_permission, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, -}; - -struct inode_operations linvfs_symlink_inode_operations = { - .readlink = linvfs_readlink, - .follow_link = linvfs_follow_link, - .put_link = linvfs_put_link, - .permission = linvfs_permission, - .getattr = linvfs_getattr, - .setattr = linvfs_setattr, - .setxattr = linvfs_setxattr, - .getxattr = linvfs_getxattr, - .listxattr = linvfs_listxattr, - .removexattr = linvfs_removexattr, -}; diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h deleted file mode 100644 index 04566006f..000000000 --- a/fs/xfs/linux-2.6/xfs_stats.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_STATS_H__ -#define __XFS_STATS_H__ - - -#if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF) - -#include - -/* - * XFS global statistics - */ -struct xfsstats { -# define XFSSTAT_END_EXTENT_ALLOC 4 - __uint32_t xs_allocx; - __uint32_t xs_allocb; - __uint32_t xs_freex; - __uint32_t xs_freeb; -# define XFSSTAT_END_ALLOC_BTREE (XFSSTAT_END_EXTENT_ALLOC+4) - __uint32_t xs_abt_lookup; - __uint32_t xs_abt_compare; - __uint32_t xs_abt_insrec; - __uint32_t xs_abt_delrec; -# define XFSSTAT_END_BLOCK_MAPPING (XFSSTAT_END_ALLOC_BTREE+7) - __uint32_t xs_blk_mapr; - __uint32_t xs_blk_mapw; - __uint32_t xs_blk_unmap; - __uint32_t xs_add_exlist; - __uint32_t xs_del_exlist; - __uint32_t xs_look_exlist; - __uint32_t xs_cmp_exlist; -# define XFSSTAT_END_BLOCK_MAP_BTREE (XFSSTAT_END_BLOCK_MAPPING+4) - __uint32_t xs_bmbt_lookup; - __uint32_t xs_bmbt_compare; - __uint32_t xs_bmbt_insrec; - __uint32_t xs_bmbt_delrec; -# define XFSSTAT_END_DIRECTORY_OPS (XFSSTAT_END_BLOCK_MAP_BTREE+4) - __uint32_t xs_dir_lookup; - __uint32_t xs_dir_create; - __uint32_t xs_dir_remove; - __uint32_t xs_dir_getdents; -# define XFSSTAT_END_TRANSACTIONS (XFSSTAT_END_DIRECTORY_OPS+3) - __uint32_t xs_trans_sync; - __uint32_t xs_trans_async; - __uint32_t xs_trans_empty; -# define XFSSTAT_END_INODE_OPS (XFSSTAT_END_TRANSACTIONS+7) - __uint32_t xs_ig_attempts; - __uint32_t xs_ig_found; - __uint32_t xs_ig_frecycle; - __uint32_t xs_ig_missed; - __uint32_t xs_ig_dup; - __uint32_t xs_ig_reclaims; - __uint32_t xs_ig_attrchg; -# define XFSSTAT_END_LOG_OPS (XFSSTAT_END_INODE_OPS+5) - __uint32_t xs_log_writes; - __uint32_t xs_log_blocks; - __uint32_t xs_log_noiclogs; - __uint32_t xs_log_force; - __uint32_t xs_log_force_sleep; -# define XFSSTAT_END_TAIL_PUSHING (XFSSTAT_END_LOG_OPS+10) - __uint32_t xs_try_logspace; - __uint32_t xs_sleep_logspace; - __uint32_t xs_push_ail; - __uint32_t xs_push_ail_success; - __uint32_t xs_push_ail_pushbuf; - __uint32_t xs_push_ail_pinned; - __uint32_t xs_push_ail_locked; - __uint32_t xs_push_ail_flushing; - __uint32_t xs_push_ail_restarts; - __uint32_t xs_push_ail_flush; -# define XFSSTAT_END_WRITE_CONVERT (XFSSTAT_END_TAIL_PUSHING+2) - __uint32_t xs_xstrat_quick; - __uint32_t xs_xstrat_split; -# define XFSSTAT_END_READ_WRITE_OPS (XFSSTAT_END_WRITE_CONVERT+2) - __uint32_t xs_write_calls; - __uint32_t xs_read_calls; -# define XFSSTAT_END_ATTRIBUTE_OPS (XFSSTAT_END_READ_WRITE_OPS+4) - __uint32_t xs_attr_get; - __uint32_t xs_attr_set; - __uint32_t xs_attr_remove; - __uint32_t xs_attr_list; -# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_ATTRIBUTE_OPS+3) - __uint32_t xs_iflush_count; - __uint32_t xs_icluster_flushcnt; - __uint32_t xs_icluster_flushinode; -# define XFSSTAT_END_VNODE_OPS (XFSSTAT_END_INODE_CLUSTER+8) - __uint32_t vn_active; /* # vnodes not on free lists */ - __uint32_t vn_alloc; /* # times vn_alloc called */ - __uint32_t vn_get; /* # times vn_get called */ - __uint32_t vn_hold; /* # times vn_hold called */ - __uint32_t vn_rele; /* # times vn_rele called */ - __uint32_t vn_reclaim; /* # times vn_reclaim called */ - __uint32_t vn_remove; /* # times vn_remove called */ - __uint32_t vn_free; /* # times vn_free called */ -#define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9) - __uint32_t pb_get; - __uint32_t pb_create; - __uint32_t pb_get_locked; - __uint32_t pb_get_locked_waited; - __uint32_t pb_busy_locked; - __uint32_t pb_miss_locked; - __uint32_t pb_page_retries; - __uint32_t pb_page_found; - __uint32_t pb_get_read; -/* Extra precision counters */ - __uint64_t xs_xstrat_bytes; - __uint64_t xs_write_bytes; - __uint64_t xs_read_bytes; -}; - -DECLARE_PER_CPU(struct xfsstats, xfsstats); - -/* We don't disable preempt, not too worried about poking the - * wrong cpu's stat for now */ -#define XFS_STATS_INC(count) (__get_cpu_var(xfsstats).count++) -#define XFS_STATS_DEC(count) (__get_cpu_var(xfsstats).count--) -#define XFS_STATS_ADD(count, inc) (__get_cpu_var(xfsstats).count += (inc)) - -extern void xfs_init_procfs(void); -extern void xfs_cleanup_procfs(void); - - -#else /* !CONFIG_PROC_FS */ - -# define XFS_STATS_INC(count) -# define XFS_STATS_DEC(count) -# define XFS_STATS_ADD(count, inc) - -static __inline void xfs_init_procfs(void) { }; -static __inline void xfs_cleanup_procfs(void) { }; - -#endif /* !CONFIG_PROC_FS */ - -#endif /* __XFS_STATS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_version.h b/fs/xfs/linux-2.6/xfs_version.h deleted file mode 100644 index 96f963944..000000000 --- a/fs/xfs/linux-2.6/xfs_version.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -/* - * Dummy file that can contain a timestamp to put into the - * XFS init string, to help users keep track of what they're - * running - */ - -#ifndef __XFS_VERSION_H__ -#define __XFS_VERSION_H__ - -#define XFS_VERSION_STRING "SGI XFS" - -#endif /* __XFS_VERSION_H__ */ diff --git a/include/asm-alpha/8253pit.h b/include/asm-alpha/8253pit.h deleted file mode 100644 index fef5c1450..000000000 --- a/include/asm-alpha/8253pit.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 8253/8254 Programmable Interval Timer - */ - -#ifndef _8253PIT_H -#define _8253PIT_H - -#define PIT_TICK_RATE 1193180UL - -#endif diff --git a/include/asm-alpha/relay.h b/include/asm-alpha/relay.h deleted file mode 100644 index 104091f06..000000000 --- a/include/asm-alpha/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_ALPHA_RELAY_H -#define _ASM_ALPHA_RELAY_H - -#include -#endif diff --git a/include/asm-arm/arch-ixp4xx/coyote.h b/include/asm-arm/arch-ixp4xx/coyote.h deleted file mode 100644 index dd0c2d2d8..000000000 --- a/include/asm-arm/arch-ixp4xx/coyote.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/coyote.h - * - * ADI Engineering platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (c) MontaVista, Software, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define COYOTE_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS -#define COYOTE_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE * 2 - -/* PCI controller GPIO to IRQ pin mappings */ -#define COYOTE_PCI_SLOT0_PIN 6 -#define COYOTE_PCI_SLOT1_PIN 11 - -#define COYOTE_PCI_SLOT0_DEVID 14 -#define COYOTE_PCI_SLOT1_DEVID 15 - -#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_CS3_BASE_PHYS -#define COYOTE_IDE_BASE_VIRT 0xFFFE1000 -#define COYOTE_IDE_REGION_SIZE 0x1000 - -#define COYOTE_IDE_DATA_PORT 0xFFFE10E0 -#define COYOTE_IDE_CTRL_PORT 0xFFFE10FC -#define COYOTE_IDE_ERROR_PORT 0xFFFE10E2 - diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h deleted file mode 100644 index a048cbc58..000000000 --- a/include/asm-arm/arch-ixp4xx/hardware.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/hardware.h - * - * Copyright (C) 2002 Intel Corporation. - * Copyright (C) 2003-2004 MontaVista Software, Inc. - * - * 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. - * - */ - -/* - * Hardware definitions for IXP4xx based systems - */ - -#ifndef __ASM_ARCH_HARDWARE_H__ -#define __ASM_ARCH_HARDWARE_H__ - -#define PCIBIOS_MIN_IO 0x00001000 -#define PCIBIOS_MIN_MEM 0x48000000 - -/* - * We override the standard dma-mask routines for bouncing. - */ -#define HAVE_ARCH_PCI_SET_DMA_MASK - -#define pcibios_assign_all_busses() 1 - -/* Register locations and bits */ -#include "ixp4xx-regs.h" - -/* Platform helper functions and definitions */ -#include "platform.h" - -/* Platform specific details */ -#include "ixdp425.h" -#include "coyote.h" -#include "prpmc1100.h" - -#endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h deleted file mode 100644 index c782b560c..000000000 --- a/include/asm-arm/arch-ixp4xx/irqs.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/irqs.h - * - * IRQ definitions for IXP4XX based systems - * - * Copyright (C) 2002 Intel Corporation. - * Copyright (C) 2003 MontaVista Software, Inc. - * - * 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. - * - */ - -#ifndef _ARCH_IXP4XX_IRQS_H_ -#define _ARCH_IXP4XX_IRQS_H_ - -#define NR_IRQS 32 - -#define IRQ_IXP4XX_NPEA 0 -#define IRQ_IXP4XX_NPEB 1 -#define IRQ_IXP4XX_NPEC 2 -#define IRQ_IXP4XX_QM1 3 -#define IRQ_IXP4XX_QM2 4 -#define IRQ_IXP4XX_TIMER1 5 -#define IRQ_IXP4XX_GPIO0 6 -#define IRQ_IXP4XX_GPIO1 7 -#define IRQ_IXP4XX_PCI_INT 8 -#define IRQ_IXP4XX_PCI_DMA1 9 -#define IRQ_IXP4XX_PCI_DMA2 10 -#define IRQ_IXP4XX_TIMER2 11 -#define IRQ_IXP4XX_USB 12 -#define IRQ_IXP4XX_UART2 13 -#define IRQ_IXP4XX_TIMESTAMP 14 -#define IRQ_IXP4XX_UART1 15 -#define IRQ_IXP4XX_WDOG 16 -#define IRQ_IXP4XX_AHB_PMU 17 -#define IRQ_IXP4XX_XSCALE_PMU 18 -#define IRQ_IXP4XX_GPIO2 19 -#define IRQ_IXP4XX_GPIO3 20 -#define IRQ_IXP4XX_GPIO4 21 -#define IRQ_IXP4XX_GPIO5 22 -#define IRQ_IXP4XX_GPIO6 23 -#define IRQ_IXP4XX_GPIO7 24 -#define IRQ_IXP4XX_GPIO8 25 -#define IRQ_IXP4XX_GPIO9 26 -#define IRQ_IXP4XX_GPIO10 27 -#define IRQ_IXP4XX_GPIO11 28 -#define IRQ_IXP4XX_GPIO12 29 -#define IRQ_IXP4XX_SW_INT1 30 -#define IRQ_IXP4XX_SW_INT2 31 - -#define XSCALE_PMU_IRQ (IRQ_IXP4XX_XSCALE_PMU) - -/* - * IXDP425 board IRQs - */ -#define IRQ_IXDP425_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_IXDP425_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_IXDP425_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_IXDP425_PCI_INTD IRQ_IXP4XX_GPIO8 - -/* - * PrPMC1100 Board IRQs - */ -#define IRQ_PRPMC1100_PCI_INTA IRQ_IXP4XX_GPIO11 -#define IRQ_PRPMC1100_PCI_INTB IRQ_IXP4XX_GPIO10 -#define IRQ_PRPMC1100_PCI_INTC IRQ_IXP4XX_GPIO9 -#define IRQ_PRPMC1100_PCI_INTD IRQ_IXP4XX_GPIO8 - -/* - * ADI Coyote Board IRQs - */ -#define IRQ_COYOTE_PCI_SLOT0 IRQ_IXP4XX_GPIO6 -#define IRQ_COYOTE_PCI_SLOT1 IRQ_IXP4XX_GPIO11 -#define IRQ_COYOTE_IDE IRQ_IXP4XX_GPIO5 - -#endif diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h deleted file mode 100644 index 7d21bf941..000000000 --- a/include/asm-arm/arch-ixp4xx/ixdp425.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/ixdp425.h - * - * IXDP425 platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (c) MontaVista, Software, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define IXDP425_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS -#define IXDP425_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE - -#define IXDP425_SDA_PIN 7 -#define IXDP425_SCL_PIN 6 - -/* - * IXDP425 PCI IRQs - */ -#define IXDP425_PCI_MAX_DEV 4 -#define IXDP425_PCI_IRQ_LINES 4 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define IXDP425_PCI_INTA_PIN 11 -#define IXDP425_PCI_INTB_PIN 10 -#define IXDP425_PCI_INTC_PIN 9 -#define IXDP425_PCI_INTD_PIN 8 - - diff --git a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h deleted file mode 100644 index b5810b254..000000000 --- a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h +++ /dev/null @@ -1,551 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/ixp4xx-regs.h - * - * Register definitions for IXP4xx chipset. This file contains - * register location and bit definitions only. Platform specific - * definitions and helper function declarations are in platform.h - * and machine-name.h. - * - * Copyright (C) 2002 Intel Corporation. - * Copyright (C) 2003-2004 MontaVista Software, Inc. - * - * 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. - * - */ - -#ifndef __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#ifndef _ASM_ARM_IXP4XX_H_ -#define _ASM_ARM_IXP4XX_H_ - -/* - * IXP4xx Linux Memory Map: - * - * Phy Size Virt Description - * ========================================================================= - * - * 0x00000000 0x10000000(max) PAGE_OFFSET System RAM - * - * 0x48000000 0x04000000 ioremap'd PCI Memory Space - * - * 0x50000000 0x10000000 ioremap'd EXP BUS - * - * 0x6000000 0x00004000 ioremap'd QMgr - * - * 0xC0000000 0x00001000 0xffbfe000 PCI CFG - * - * 0xC4000000 0x00001000 0xffbfd000 EXP CFG - * - * 0xC8000000 0x0000C000 0xffbf2000 On-Chip Peripherals - */ - - -/* - * Expansion BUS Configuration registers - */ -#define IXP4XX_EXP_CFG_BASE_PHYS (0xC4000000) -#define IXP4XX_EXP_CFG_BASE_VIRT (0xFFBFD000) -#define IXP4XX_EXP_CFG_REGION_SIZE (0x00001000) - -/* - * PCI Config registers - */ -#define IXP4XX_PCI_CFG_BASE_PHYS (0xC0000000) -#define IXP4XX_PCI_CFG_BASE_VIRT (0xFFBFD000) -#define IXP4XX_PCI_CFG_REGION_SIZE (0x00001000) - -/* - * Peripheral space - */ -#define IXP4XX_PERIPHERAL_BASE_PHYS (0xC8000000) -#define IXP4XX_PERIPHERAL_BASE_VIRT (0xFFBF2000) -#define IXP4XX_PERIPHERAL_REGION_SIZE (0x0000C000) - -#define IXP4XX_EXP_CS0_OFFSET 0x00 -#define IXP4XX_EXP_CS1_OFFSET 0x04 -#define IXP4XX_EXP_CS2_OFFSET 0x08 -#define IXP4XX_EXP_CS3_OFFSET 0x0C -#define IXP4XX_EXP_CS4_OFFSET 0x10 -#define IXP4XX_EXP_CS5_OFFSET 0x14 -#define IXP4XX_EXP_CS6_OFFSET 0x18 -#define IXP4XX_EXP_CS7_OFFSET 0x1C -#define IXP4XX_EXP_CFG0_OFFSET 0x20 -#define IXP4XX_EXP_CFG1_OFFSET 0x24 -#define IXP4XX_EXP_CFG2_OFFSET 0x28 -#define IXP4XX_EXP_CFG3_OFFSET 0x2C - -/* - * Expansion Bus Controller registers. - */ -#define IXP4XX_EXP_REG(x) ((volatile u32 *)(IXP4XX_EXP_CFG_BASE_VIRT+(x))) - -#define IXP4XX_EXP_CS0 IXP4XX_EXP_REG(IXP4XX_EXP_CS0_OFFSET) -#define IXP4XX_EXP_CS1 IXP4XX_EXP_REG(IXP4XX_EXP_CS1_OFFSET) -#define IXP4XX_EXP_CS2 IXP4XX_EXP_REG(IXP4XX_EXP_CS2_OFFSET) -#define IXP4XX_EXP_CS3 IXP4XX_EXP_REG(IXP4XX_EXP_CS3_OFFSET) -#define IXP4XX_EXP_CS4 IXP4XX_EXP_REG(IXP4XX_EXP_CS4_OFFSET) -#define IXP4XX_EXP_CS5 IXP4XX_EXP_REG(IXP4XX_EXP_CS5_OFFSET) -#define IXP4XX_EXP_CS6 IXP4XX_EXP_REG(IXP4XX_EXP_CS6_OFFSET) -#define IXP4XX_EXP_CS7 IXP4XX_EXP_REG(IXP4XX_EXP_CS7_OFFSET) - -#define IXP4XX_EXP_CFG0 IXP4XX_EXP_REG(IXP4XX_EXP_CFG0_OFFSET) -#define IXP4XX_EXP_CFG1 IXP4XX_EXP_REG(IXP4XX_EXP_CFG1_OFFSET) -#define IXP4XX_EXP_CFG2 IXP4XX_EXP_REG(IXP4XX_EXP_CFG2_OFFSET) -#define IXP4XX_EXP_CFG3 IXP4XX_EXP_REG(IXP4XX_EXP_CFG3_OFFSET) - - -/* - * Peripheral Space Register Region Base Addresses - */ -#define IXP4XX_UART1_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x0000) -#define IXP4XX_UART2_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x1000) -#define IXP4XX_PMU_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x2000) -#define IXP4XX_INTC_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x3000) -#define IXP4XX_GPIO_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x4000) -#define IXP4XX_TIMER_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x5000) -#define IXP4XX_USB_BASE_PHYS (IXP4XX_PERIPHERAL_BASE_PHYS + 0x5000) - -#define IXP4XX_UART1_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000) -#define IXP4XX_UART2_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000) -#define IXP4XX_PMU_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000) -#define IXP4XX_INTC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000) -#define IXP4XX_GPIO_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000) -#define IXP4XX_TIMER_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000) -#define IXP4XX_USB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000) - -/* - * Constants to make it easy to access Interrupt Controller registers - */ -#define IXP4XX_ICPR_OFFSET 0x00 /* Interrupt Status */ -#define IXP4XX_ICMR_OFFSET 0x04 /* Interrupt Enable */ -#define IXP4XX_ICLR_OFFSET 0x08 /* Interrupt IRQ/FIQ Select */ -#define IXP4XX_ICIP_OFFSET 0x0C /* IRQ Status */ -#define IXP4XX_ICFP_OFFSET 0x10 /* FIQ Status */ -#define IXP4XX_ICHR_OFFSET 0x14 /* Interrupt Priority */ -#define IXP4XX_ICIH_OFFSET 0x18 /* IRQ Highest Pri Int */ -#define IXP4XX_ICFH_OFFSET 0x1C /* FIQ Highest Pri Int */ - -/* - * Interrupt Controller Register Definitions. - */ - -#define IXP4XX_INTC_REG(x) ((volatile u32 *)(IXP4XX_INTC_BASE_VIRT+(x))) - -#define IXP4XX_ICPR IXP4XX_INTC_REG(IXP4XX_ICPR_OFFSET) -#define IXP4XX_ICMR IXP4XX_INTC_REG(IXP4XX_ICMR_OFFSET) -#define IXP4XX_ICLR IXP4XX_INTC_REG(IXP4XX_ICLR_OFFSET) -#define IXP4XX_ICIP IXP4XX_INTC_REG(IXP4XX_ICIP_OFFSET) -#define IXP4XX_ICFP IXP4XX_INTC_REG(IXP4XX_ICFP_OFFSET) -#define IXP4XX_ICHR IXP4XX_INTC_REG(IXP4XX_ICHR_OFFSET) -#define IXP4XX_ICIH IXP4XX_INTC_REG(IXP4XX_ICIH_OFFSET) -#define IXP4XX_ICFH IXP4XX_INTC_REG(IXP4XX_ICFH_OFFSET) - -/* - * Constants to make it easy to access GPIO registers - */ -#define IXP4XX_GPIO_GPOUTR_OFFSET 0x00 -#define IXP4XX_GPIO_GPOER_OFFSET 0x04 -#define IXP4XX_GPIO_GPINR_OFFSET 0x08 -#define IXP4XX_GPIO_GPISR_OFFSET 0x0C -#define IXP4XX_GPIO_GPIT1R_OFFSET 0x10 -#define IXP4XX_GPIO_GPIT2R_OFFSET 0x14 -#define IXP4XX_GPIO_GPCLKR_OFFSET 0x18 -#define IXP4XX_GPIO_GPDBSELR_OFFSET 0x1C - -/* - * GPIO Register Definitions. - * [Only perform 32bit reads/writes] - */ -#define IXP4XX_GPIO_REG(x) ((volatile u32 *)(IXP4XX_GPIO_BASE_VIRT+(x))) - -#define IXP4XX_GPIO_GPOUTR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOUTR_OFFSET) -#define IXP4XX_GPIO_GPOER IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOER_OFFSET) -#define IXP4XX_GPIO_GPINR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPINR_OFFSET) -#define IXP4XX_GPIO_GPISR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPISR_OFFSET) -#define IXP4XX_GPIO_GPIT1R IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT1R_OFFSET) -#define IXP4XX_GPIO_GPIT2R IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT2R_OFFSET) -#define IXP4XX_GPIO_GPCLKR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPCLKR_OFFSET) -#define IXP4XX_GPIO_GPDBSELR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPDBSELR_OFFSET) - -/* - * GPIO register bit definitions - */ - -/* Interrupt styles - */ -#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH 0x0 -#define IXP4XX_GPIO_STYLE_ACTIVE_LOW 0x1 -#define IXP4XX_GPIO_STYLE_RISING_EDGE 0x2 -#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3 -#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4 - -/* - * Mask used to clear interrupt styles - */ -#define IXP4XX_GPIO_STYLE_CLEAR 0x7 -#define IXP4XX_GPIO_STYLE_SIZE 3 - -/* - * Constants to make it easy to access Timer Control/Status registers - */ -#define IXP4XX_OSTS_OFFSET 0x00 /* Continious TimeStamp */ -#define IXP4XX_OST1_OFFSET 0x04 /* Timer 1 Timestamp */ -#define IXP4XX_OSRT1_OFFSET 0x08 /* Timer 1 Reload */ -#define IXP4XX_OST2_OFFSET 0x0C /* Timer 2 Timestamp */ -#define IXP4XX_OSRT2_OFFSET 0x10 /* Timer 2 Reload */ -#define IXP4XX_OSWT_OFFSET 0x14 /* Watchdog Timer */ -#define IXP4XX_OSWE_OFFSET 0x18 /* Watchdog Enable */ -#define IXP4XX_OSWK_OFFSET 0x1C /* Watchdog Key */ -#define IXP4XX_OSST_OFFSET 0x20 /* Timer Status */ - -/* - * Operating System Timer Register Definitions. - */ - -#define IXP4XX_TIMER_REG(x) ((volatile u32 *)(IXP4XX_TIMER_BASE_VIRT+(x))) - -#define IXP4XX_OSTS IXP4XX_TIMER_REG(IXP4XX_OSTS_OFFSET) -#define IXP4XX_OST1 IXP4XX_TIMER_REG(IXP4XX_OST1_OFFSET) -#define IXP4XX_OSRT1 IXP4XX_TIMER_REG(IXP4XX_OSRT1_OFFSET) -#define IXP4XX_OST2 IXP4XX_TIMER_REG(IXP4XX_OST2_OFFSET) -#define IXP4XX_OSRT2 IXP4XX_TIMER_REG(IXP4XX_OSRT2_OFFSET) -#define IXP4XX_OSWT IXP4XX_TIMER_REG(IXP4XX_OSWT_OFFSET) -#define IXP4XX_OSWE IXP4XX_TIMER_REG(IXP4XX_OSWE_OFFSET) -#define IXP4XX_OSWK IXP4XX_TIMER_REG(IXP4XX_OSWK_OFFSET) -#define IXP4XX_OSST IXP4XX_TIMER_REG(IXP4XX_OSST_OFFSET) - -/* - * Timer register values and bit definitions - */ -#define IXP4XX_OST_ENABLE 0x00000001 -#define IXP4XX_OST_ONE_SHOT 0x00000002 -/* Low order bits of reload value ignored */ -#define IXP4XX_OST_RELOAD_MASK 0x00000003 -#define IXP4XX_OST_DISABLED 0x00000000 -#define IXP4XX_OSST_TIMER_1_PEND 0x00000001 -#define IXP4XX_OSST_TIMER_2_PEND 0x00000002 -#define IXP4XX_OSST_TIMER_TS_PEND 0x00000004 -#define IXP4XX_OSST_TIMER_WDOG_PEND 0x00000008 -#define IXP4XX_OSST_TIMER_WARM_RESET 0x00000010 - -#define IXP4XX_WDT_KEY 0x0000482E - -#define IXP4XX_WDT_RESET_ENABLE 0x00000001 -#define IXP4XX_WDT_IRQ_ENABLE 0x00000002 -#define IXP4XX_WDT_COUNT_ENABLE 0x00000004 - - -/* - * Constants to make it easy to access PCI Control/Status registers - */ -#define PCI_NP_AD_OFFSET 0x00 -#define PCI_NP_CBE_OFFSET 0x04 -#define PCI_NP_WDATA_OFFSET 0x08 -#define PCI_NP_RDATA_OFFSET 0x0c -#define PCI_CRP_AD_CBE_OFFSET 0x10 -#define PCI_CRP_WDATA_OFFSET 0x14 -#define PCI_CRP_RDATA_OFFSET 0x18 -#define PCI_CSR_OFFSET 0x1c -#define PCI_ISR_OFFSET 0x20 -#define PCI_INTEN_OFFSET 0x24 -#define PCI_DMACTRL_OFFSET 0x28 -#define PCI_AHBMEMBASE_OFFSET 0x2c -#define PCI_AHBIOBASE_OFFSET 0x30 -#define PCI_PCIMEMBASE_OFFSET 0x34 -#define PCI_AHBDOORBELL_OFFSET 0x38 -#define PCI_PCIDOORBELL_OFFSET 0x3C -#define PCI_ATPDMA0_AHBADDR_OFFSET 0x40 -#define PCI_ATPDMA0_PCIADDR_OFFSET 0x44 -#define PCI_ATPDMA0_LENADDR_OFFSET 0x48 -#define PCI_ATPDMA1_AHBADDR_OFFSET 0x4C -#define PCI_ATPDMA1_PCIADDR_OFFSET 0x50 -#define PCI_ATPDMA1_LENADDR_OFFSET 0x54 - -/* - * PCI Control/Status Registers - */ -#define IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x))) - -#define PCI_NP_AD IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET) -#define PCI_NP_CBE IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET) -#define PCI_NP_WDATA IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET) -#define PCI_NP_RDATA IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET) -#define PCI_CRP_AD_CBE IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET) -#define PCI_CRP_WDATA IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET) -#define PCI_CRP_RDATA IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET) -#define PCI_CSR IXP4XX_PCI_CSR(PCI_CSR_OFFSET) -#define PCI_ISR IXP4XX_PCI_CSR(PCI_ISR_OFFSET) -#define PCI_INTEN IXP4XX_PCI_CSR(PCI_INTEN_OFFSET) -#define PCI_DMACTRL IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET) -#define PCI_AHBMEMBASE IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET) -#define PCI_AHBIOBASE IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET) -#define PCI_PCIMEMBASE IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET) -#define PCI_AHBDOORBELL IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET) -#define PCI_PCIDOORBELL IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET) -#define PCI_ATPDMA0_AHBADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET) -#define PCI_ATPDMA0_PCIADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET) -#define PCI_ATPDMA0_LENADDR IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET) -#define PCI_ATPDMA1_AHBADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET) -#define PCI_ATPDMA1_PCIADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET) -#define PCI_ATPDMA1_LENADDR IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET) - -/* - * PCI register values and bit definitions - */ - -/* CSR bit definitions */ -#define PCI_CSR_HOST 0x00000001 -#define PCI_CSR_ARBEN 0x00000002 -#define PCI_CSR_ADS 0x00000004 -#define PCI_CSR_PDS 0x00000008 -#define PCI_CSR_ABE 0x00000010 -#define PCI_CSR_DBT 0x00000020 -#define PCI_CSR_ASE 0x00000100 -#define PCI_CSR_IC 0x00008000 - -/* ISR (Interrupt status) Register bit definitions */ -#define PCI_ISR_PSE 0x00000001 -#define PCI_ISR_PFE 0x00000002 -#define PCI_ISR_PPE 0x00000004 -#define PCI_ISR_AHBE 0x00000008 -#define PCI_ISR_APDC 0x00000010 -#define PCI_ISR_PADC 0x00000020 -#define PCI_ISR_ADB 0x00000040 -#define PCI_ISR_PDB 0x00000080 - -/* INTEN (Interrupt Enable) Register bit definitions */ -#define PCI_INTEN_PSE 0x00000001 -#define PCI_INTEN_PFE 0x00000002 -#define PCI_INTEN_PPE 0x00000004 -#define PCI_INTEN_AHBE 0x00000008 -#define PCI_INTEN_APDC 0x00000010 -#define PCI_INTEN_PADC 0x00000020 -#define PCI_INTEN_ADB 0x00000040 -#define PCI_INTEN_PDB 0x00000080 - -/* - * Shift value for byte enable on NP cmd/byte enable register - */ -#define IXP4XX_PCI_NP_CBE_BESL 4 - -/* - * PCI commands supported by NP access unit - */ -#define NP_CMD_IOREAD 0x2 -#define NP_CMD_IOWRITE 0x3 -#define NP_CMD_CONFIGREAD 0xa -#define NP_CMD_CONFIGWRITE 0xb -#define NP_CMD_MEMREAD 0x6 -#define NP_CMD_MEMWRITE 0x7 - -/* - * Constants for CRP access into local config space - */ -#define CRP_AD_CBE_BESL 20 -#define CRP_AD_CBE_WRITE 0x00010000 - - -/* - * USB Device Controller - * - * These are used by the USB gadget driver, so they don't follow the - * IXP4XX_ naming convetions. - * - */ -# define IXP4XX_USB_REG(x) (*((volatile u32 *)(x))) - -/* UDC Undocumented - Reserved1 */ -#define UDC_RES1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0004) -/* UDC Undocumented - Reserved2 */ -#define UDC_RES2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0008) -/* UDC Undocumented - Reserved3 */ -#define UDC_RES3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x000C) -/* UDC Control Register */ -#define UDCCR IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0000) -/* UDC Endpoint 0 Control/Status Register */ -#define UDCCS0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0010) -/* UDC Endpoint 1 (IN) Control/Status Register */ -#define UDCCS1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0014) -/* UDC Endpoint 2 (OUT) Control/Status Register */ -#define UDCCS2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0018) -/* UDC Endpoint 3 (IN) Control/Status Register */ -#define UDCCS3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x001C) -/* UDC Endpoint 4 (OUT) Control/Status Register */ -#define UDCCS4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0020) -/* UDC Endpoint 5 (Interrupt) Control/Status Register */ -#define UDCCS5 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0024) -/* UDC Endpoint 6 (IN) Control/Status Register */ -#define UDCCS6 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0028) -/* UDC Endpoint 7 (OUT) Control/Status Register */ -#define UDCCS7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x002C) -/* UDC Endpoint 8 (IN) Control/Status Register */ -#define UDCCS8 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0030) -/* UDC Endpoint 9 (OUT) Control/Status Register */ -#define UDCCS9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0034) -/* UDC Endpoint 10 (Interrupt) Control/Status Register */ -#define UDCCS10 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0038) -/* UDC Endpoint 11 (IN) Control/Status Register */ -#define UDCCS11 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x003C) -/* UDC Endpoint 12 (OUT) Control/Status Register */ -#define UDCCS12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0040) -/* UDC Endpoint 13 (IN) Control/Status Register */ -#define UDCCS13 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0044) -/* UDC Endpoint 14 (OUT) Control/Status Register */ -#define UDCCS14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0048) -/* UDC Endpoint 15 (Interrupt) Control/Status Register */ -#define UDCCS15 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x004C) -/* UDC Frame Number Register High */ -#define UFNRH IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0060) -/* UDC Frame Number Register Low */ -#define UFNRL IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0064) -/* UDC Byte Count Reg 2 */ -#define UBCR2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0068) -/* UDC Byte Count Reg 4 */ -#define UBCR4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x006c) -/* UDC Byte Count Reg 7 */ -#define UBCR7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0070) -/* UDC Byte Count Reg 9 */ -#define UBCR9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0074) -/* UDC Byte Count Reg 12 */ -#define UBCR12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0078) -/* UDC Byte Count Reg 14 */ -#define UBCR14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x007c) -/* UDC Endpoint 0 Data Register */ -#define UDDR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0080) -/* UDC Endpoint 1 Data Register */ -#define UDDR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0100) -/* UDC Endpoint 2 Data Register */ -#define UDDR2 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0180) -/* UDC Endpoint 3 Data Register */ -#define UDDR3 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0200) -/* UDC Endpoint 4 Data Register */ -#define UDDR4 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0400) -/* UDC Endpoint 5 Data Register */ -#define UDDR5 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00A0) -/* UDC Endpoint 6 Data Register */ -#define UDDR6 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0600) -/* UDC Endpoint 7 Data Register */ -#define UDDR7 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0680) -/* UDC Endpoint 8 Data Register */ -#define UDDR8 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0700) -/* UDC Endpoint 9 Data Register */ -#define UDDR9 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0900) -/* UDC Endpoint 10 Data Register */ -#define UDDR10 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00C0) -/* UDC Endpoint 11 Data Register */ -#define UDDR11 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0B00) -/* UDC Endpoint 12 Data Register */ -#define UDDR12 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0B80) -/* UDC Endpoint 13 Data Register */ -#define UDDR13 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0C00) -/* UDC Endpoint 14 Data Register */ -#define UDDR14 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0E00) -/* UDC Endpoint 15 Data Register */ -#define UDDR15 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x00E0) -/* UDC Interrupt Control Register 0 */ -#define UICR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0050) -/* UDC Interrupt Control Register 1 */ -#define UICR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0054) -/* UDC Status Interrupt Register 0 */ -#define USIR0 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x0058) -/* UDC Status Interrupt Register 1 */ -#define USIR1 IXP4XX_USB_REG(IXP4XX_USB_BASE_VIRT+0x005C) - -#define UDCCR_UDE (1 << 0) /* UDC enable */ -#define UDCCR_UDA (1 << 1) /* UDC active */ -#define UDCCR_RSM (1 << 2) /* Device resume */ -#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */ -#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */ -#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */ -#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */ -#define UDCCR_REM (1 << 7) /* Reset interrupt mask */ - -#define UDCCS0_OPR (1 << 0) /* OUT packet ready */ -#define UDCCS0_IPR (1 << 1) /* IN packet ready */ -#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */ -#define UDCCS0_SST (1 << 4) /* Sent stall */ -#define UDCCS0_FST (1 << 5) /* Force stall */ -#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */ -#define UDCCS0_SA (1 << 7) /* Setup active */ - -#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_BI_SST (1 << 4) /* Sent stall */ -#define UDCCS_BI_FST (1 << 5) /* Force stall */ -#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */ - -#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_BO_DME (1 << 3) /* DMA enable */ -#define UDCCS_BO_SST (1 << 4) /* Sent stall */ -#define UDCCS_BO_FST (1 << 5) /* Force stall */ -#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */ - -#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */ - -#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ -#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */ -#define UDCCS_IO_DME (1 << 3) /* DMA enable */ -#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ -#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ - -#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */ -#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */ -#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */ -#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */ -#define UDCCS_INT_SST (1 << 4) /* Sent stall */ -#define UDCCS_INT_FST (1 << 5) /* Force stall */ -#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */ - -#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */ -#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */ -#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */ -#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */ -#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */ -#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */ -#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */ -#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */ - -#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */ -#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */ -#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */ -#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */ -#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */ -#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */ -#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */ -#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */ - -#define USIR0_IR0 (1 << 0) /* Interrup request ep 0 */ -#define USIR0_IR1 (1 << 1) /* Interrup request ep 1 */ -#define USIR0_IR2 (1 << 2) /* Interrup request ep 2 */ -#define USIR0_IR3 (1 << 3) /* Interrup request ep 3 */ -#define USIR0_IR4 (1 << 4) /* Interrup request ep 4 */ -#define USIR0_IR5 (1 << 5) /* Interrup request ep 5 */ -#define USIR0_IR6 (1 << 6) /* Interrup request ep 6 */ -#define USIR0_IR7 (1 << 7) /* Interrup request ep 7 */ - -#define USIR1_IR8 (1 << 0) /* Interrup request ep 8 */ -#define USIR1_IR9 (1 << 1) /* Interrup request ep 9 */ -#define USIR1_IR10 (1 << 2) /* Interrup request ep 10 */ -#define USIR1_IR11 (1 << 3) /* Interrup request ep 11 */ -#define USIR1_IR12 (1 << 4) /* Interrup request ep 12 */ -#define USIR1_IR13 (1 << 5) /* Interrup request ep 13 */ -#define USIR1_IR14 (1 << 6) /* Interrup request ep 14 */ -#define USIR1_IR15 (1 << 7) /* Interrup request ep 15 */ - -#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ - -#endif diff --git a/include/asm-arm/arch-ixp4xx/prpmc1100.h b/include/asm-arm/arch-ixp4xx/prpmc1100.h deleted file mode 100644 index e2532ab7f..000000000 --- a/include/asm-arm/arch-ixp4xx/prpmc1100.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * include/asm-arm/arch-ixp4xx/prpmc1100.h - * - * Motorolla PrPMC1100 platform specific definitions - * - * Author: Deepak Saxena - * - * Copyright 2004 (c) MontaVista, Software, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __ASM_ARCH_HARDWARE_H__ -#error "Do not include this directly, instead #include " -#endif - -#define PRPMC1100_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS -#define PRPMC1100_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE - -#define PRPMC1100_PCI_MIN_DEVID 10 -#define PRPMC1100_PCI_MAX_DEVID 16 -#define PRPMC1100_PCI_IRQ_LINES 4 - - -/* PCI controller GPIO to IRQ pin mappings */ -#define PRPMC1100_PCI_INTA_PIN 11 -#define PRPMC1100_PCI_INTB_PIN 10 -#define PRPMC1100_PCI_INTC_PIN 9 -#define PRPMC1100_PCI_INTD_PIN 8 - - diff --git a/include/asm-arm/arch-ixp4xx/timex.h b/include/asm-arm/arch-ixp4xx/timex.h deleted file mode 100644 index 38c9d77d3..000000000 --- a/include/asm-arm/arch-ixp4xx/timex.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp4xx/timex.h - * - */ - -#include - -/* - * We use IXP425 General purpose timer for our timer needs, it runs at - * 66.66... MHz - */ -#define CLOCK_TICK_RATE (66666666) - diff --git a/include/asm-arm/arch-ixp4xx/vmalloc.h b/include/asm-arm/arch-ixp4xx/vmalloc.h deleted file mode 100644 index da46e560a..000000000 --- a/include/asm-arm/arch-ixp4xx/vmalloc.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * linux/include/asm-arm/arch-ixp4xx/vmalloc.h - */ - -/* - * Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -#define VMALLOC_END (0xFF000000) - diff --git a/include/asm-arm/arch-pxa/mainstone.h b/include/asm-arm/arch-pxa/mainstone.h deleted file mode 100644 index 14c862adc..000000000 --- a/include/asm-arm/arch-pxa/mainstone.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * linux/include/asm-arm/arch-pxa/mainstone.h - * - * Author: Nicolas Pitre - * Created: Nov 14, 2002 - * Copyright: MontaVista Software Inc. - * - * 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. - */ - -#ifndef ASM_ARCH_MAINSTONE_H -#define ASM_ARCH_MAINSTONE_H - -#define MST_ETH_PHYS PXA_CS4_PHYS - -#define MST_FPGA_PHYS PXA_CS2_PHYS -#define MST_FPGA_VIRT (0xf0000000) -#define MST_P2V(x) ((x) - MST_FPGA_PHYS + MST_FPGA_VIRT) -#define MST_V2P(x) ((x) - MST_FPGA_VIRT + MST_FPGA_PHYS) - -#ifndef __ASSEMBLY__ -# define __MST_REG(x) (*((volatile unsigned long *)MST_P2V(x))) -#else -# define __MST_REG(x) MST_P2V(x) -#endif - -/* board level registers in the FPGA */ - -#define MST_LEDDAT1 __MST_REG(0x08000010) -#define MST_LEDDAT2 __MST_REG(0x08000014) -#define MST_LEDCTRL __MST_REG(0x08000040) -#define MST_GPSWR __MST_REG(0x08000060) -#define MST_MSCWR1 __MST_REG(0x08000080) -#define MST_MSCWR2 __MST_REG(0x08000084) -#define MST_MSCWR3 __MST_REG(0x08000088) -#define MST_MSCRD __MST_REG(0x08000090) -#define MST_INTMSKENA __MST_REG(0x080000c0) -#define MST_INTSETCLR __MST_REG(0x080000d0) -#define MST_PCMCIA0 __MST_REG(0x080000e0) -#define MST_PCMCIA1 __MST_REG(0x080000e4) - -#define MST_MSCWR1_CAMERA_ON (1 << 15) /* Camera interface power control */ -#define MST_MSCWR1_CAMERA_SEL (1 << 14) /* Camera interface mux control */ -#define MST_MSCWR1_LCD_CTL (1 << 13) /* General-purpose LCD control */ -#define MST_MSCWR1_MS_ON (1 << 12) /* Memory Stick power control */ -#define MST_MSCWR1_MMC_ON (1 << 11) /* MultiMediaCard* power control */ -#define MST_MSCWR1_MS_SEL (1 << 10) /* SD/MS multiplexer control */ -#define MST_MSCWR1_BB_SEL (1 << 9) /* PCMCIA/Baseband multiplexer */ -#define MST_MSCWR1_BT_ON (1 << 8) /* Bluetooth UART transceiver */ -#define MST_MSCWR1_BTDTR (1 << 7) /* Bluetooth UART DTR */ - -#define MST_MSCWR1_IRDA_MASK (3 << 5) /* IrDA transceiver mode */ -#define MST_MSCWR1_IRDA_FULL (0 << 5) /* full distance power */ -#define MST_MSCWR1_IRDA_OFF (1 << 5) /* shutdown */ -#define MST_MSCWR1_IRDA_MED (2 << 5) /* 2/3 distance power */ -#define MST_MSCWR1_IRDA_LOW (3 << 5) /* 1/3 distance power */ - -#define MST_MSCWR1_IRDA_FIR (1 << 4) /* IrDA transceiver SIR/FIR */ -#define MST_MSCWR1_GREENLED (1 << 3) /* LED D1 control */ -#define MST_MSCWR1_PDC_CTL (1 << 2) /* reserved */ -#define MST_MSCWR1_MTR_ON (1 << 1) /* Silent alert motor */ -#define MST_MSCWR1_SYSRESET (1 << 0) /* System reset */ - -#define MST_MSCWR2_USB_OTG_RST (1 << 6) /* USB On The Go reset */ -#define MST_MSCWR2_USB_OTG_SEL (1 << 5) /* USB On The Go control */ -#define MST_MSCWR2_nUSBC_SC (1 << 4) /* USB client soft connect control */ -#define MST_MSCWR2_I2S_SPKROFF (1 << 3) /* I2S CODEC amplifier control */ -#define MST_MSCWR2_AC97_SPKROFF (1 << 2) /* AC97 CODEC amplifier control */ -#define MST_MSCWR2_RADIO_PWR (1 << 1) /* Radio module power control */ -#define MST_MSCWR2_RADIO_WAKE (1 << 0) /* Radio module wake-up signal */ - -#define MST_MSCWR3_GPIO_RESET_EN (1 << 2) /* Enable GPIO Reset */ -#define MST_MSCWR3_GPIO_RESET (1 << 1) /* Initiate a GPIO Reset */ -#define MST_MSCWR3_COMMS_SW_RESET (1 << 0) /* Communications Processor Reset Control */ - -#define MST_MSCRD_nPENIRQ (1 << 9) /* ADI7873* nPENIRQ signal */ -#define MST_MSCRD_nMEMSTK_CD (1 << 8) /* Memory Stick detection signal */ -#define MST_MSCRD_nMMC_CD (1 << 7) /* SD/MMC card detection signal */ -#define MST_MSCRD_nUSIM_CD (1 << 6) /* USIM card detection signal */ -#define MST_MSCRD_USB_CBL (1 << 5) /* USB client cable status */ -#define MST_MSCRD_TS_BUSY (1 << 4) /* ADI7873 busy */ -#define MST_MSCRD_BTDSR (1 << 3) /* Bluetooth UART DSR */ -#define MST_MSCRD_BTRI (1 << 2) /* Bluetooth UART Ring Indicator */ -#define MST_MSCRD_BTDCD (1 << 1) /* Bluetooth UART DCD */ -#define MST_MSCRD_nMMC_WP (1 << 0) /* SD/MMC write-protect status */ - -#define MST_INT_S1_IRQ (1 << 15) /* PCMCIA socket 1 IRQ */ -#define MST_INT_S1_STSCHG (1 << 14) /* PCMCIA socket 1 status changed */ -#define MST_INT_S1_CD (1 << 13) /* PCMCIA socket 1 card detection */ -#define MST_INT_S0_IRQ (1 << 11) /* PCMCIA socket 0 IRQ */ -#define MST_INT_S0_STSCHG (1 << 10) /* PCMCIA socket 0 status changed */ -#define MST_INT_S0_CD (1 << 9) /* PCMCIA socket 0 card detection */ -#define MST_INT_nEXBRD_INT (1 << 7) /* Expansion board IRQ */ -#define MST_INT_MSINS (1 << 6) /* Memory Stick* detection */ -#define MST_INT_PENIRQ (1 << 5) /* ADI7873* touch-screen IRQ */ -#define MST_INT_AC97 (1 << 4) /* AC'97 CODEC IRQ */ -#define MST_INT_ETHERNET (1 << 3) /* Ethernet controller IRQ */ -#define MST_INT_USBC (1 << 2) /* USB client cable detection IRQ */ -#define MST_INT_USIM (1 << 1) /* USIM card detection IRQ */ -#define MST_INT_MMC (1 << 0) /* MMC/SD card detection IRQ */ - -#define MST_PCMCIA_nIRQ (1 << 10) /* IRQ / ready signal */ -#define MST_PCMCIA_nSPKR_BVD2 (1 << 9) /* VDD sense / digital speaker */ -#define MST_PCMCIA_nSTSCHG_BVD1 (1 << 8) /* VDD sense / card status changed */ -#define MST_PCMCIA_nVS2 (1 << 7) /* VSS voltage sense */ -#define MST_PCMCIA_nVS1 (1 << 6) /* VSS voltage sense */ -#define MST_PCMCIA_nCD (1 << 5) /* Card detection signal */ -#define MST_PCMCIA_RESET (1 << 4) /* Card reset signal */ -#define MST_PCMCIA_PWR_MASK (0x000f) /* MAX1602 power-supply controls */ - -#define MST_PCMCIA_PWR_VPP_0 0x0 /* voltage VPP = 0V */ -#define MST_PCMCIA_PWR_VPP_120 0x2 /* voltage VPP = 12V*/ -#define MST_PCMCIA_PWR_VPP_VCC 0x1 /* voltage VPP = VCC */ -#define MST_PCMCIA_PWR_VCC_0 0x0 /* voltage VCC = 0V */ -#define MST_PCMCIA_PWR_VCC_33 0x8 /* voltage VCC = 3.3V */ -#define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */ - -#endif diff --git a/include/asm-arm/relay.h b/include/asm-arm/relay.h deleted file mode 100644 index f9913f1b1..000000000 --- a/include/asm-arm/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_ARM_RELAY_H -#define _ASM_ARM_RELAY_H - -#include -#endif diff --git a/include/asm-arm26/relay.h b/include/asm-arm26/relay.h deleted file mode 100644 index f9913f1b1..000000000 --- a/include/asm-arm26/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_ARM_RELAY_H -#define _ASM_ARM_RELAY_H - -#include -#endif diff --git a/include/asm-cris/local.h b/include/asm-cris/local.h deleted file mode 100644 index c11c530f7..000000000 --- a/include/asm-cris/local.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/asm-cris/relay.h b/include/asm-cris/relay.h deleted file mode 100644 index 30ee42c13..000000000 --- a/include/asm-cris/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_CRIS_RELAY_H -#define _ASM_CRIS_RELAY_H - -#include -#endif diff --git a/include/asm-cris/sections.h b/include/asm-cris/sections.h deleted file mode 100644 index 2c998ce89..000000000 --- a/include/asm-cris/sections.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _CRIS_SECTIONS_H -#define _CRIS_SECTIONS_H - -/* nothing to see, move along */ -#include - -#endif diff --git a/include/asm-generic/relay.h b/include/asm-generic/relay.h deleted file mode 100644 index c6d8dead8..000000000 --- a/include/asm-generic/relay.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _ASM_GENERIC_RELAY_H -#define _ASM_GENERIC_RELAY_H -/* - * linux/include/asm-generic/relay.h - * - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 2002 - Karim Yaghmour (karim@opersys.com) - * - * Architecture-independent definitions for relayfs - */ - -#include - -/** - * get_time_delta - utility function for getting time delta - * @now: pointer to a timeval struct that may be given current time - * @rchan: the channel - * - * Returns the time difference between the current time and the buffer - * start time. - */ -static inline u32 -get_time_delta(struct timeval *now, struct rchan *rchan) -{ - u32 time_delta; - - do_gettimeofday(now); - time_delta = calc_time_delta(now, &rchan->buf_start_time); - - return time_delta; -} - -/** - * get_timestamp - utility function for getting a time and TSC pair - * @now: current time - * @tsc: the TSC associated with now - * @rchan: the channel - * - * Sets the value pointed to by now to the current time. Value pointed to - * by tsc is not set since there is no generic TSC support. - */ -static inline void -get_timestamp(struct timeval *now, - u32 *tsc, - struct rchan *rchan) -{ - do_gettimeofday(now); -} - -/** - * get_time_or_tsc: - Utility function for getting a time or a TSC. - * @now: current time - * @tsc: current TSC - * @rchan: the channel - * - * Sets the value pointed to by now to the current time. - */ -static inline void -get_time_or_tsc(struct timeval *now, - u32 *tsc, - struct rchan *rchan) -{ - do_gettimeofday(now); -} - -/** - * have_tsc - does this platform have a useable TSC? - * - * Returns 0. - */ -static inline int -have_tsc(void) -{ - return 0; -} -#endif diff --git a/include/asm-h8300/relay.h b/include/asm-h8300/relay.h deleted file mode 100644 index 34ebfdd2f..000000000 --- a/include/asm-h8300/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_H8300_RELAY_H -#define _ASM_H8300_RELAY_H - -#include -#endif diff --git a/include/asm-i386/8253pit.h b/include/asm-i386/8253pit.h deleted file mode 100644 index 96c7c3592..000000000 --- a/include/asm-i386/8253pit.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 8253/8254 Programmable Interval Timer - */ - -#ifndef _8253PIT_H -#define _8253PIT_H - -#include - -#define PIT_TICK_RATE CLOCK_TICK_RATE - -#endif diff --git a/include/asm-i386/relay.h b/include/asm-i386/relay.h deleted file mode 100644 index 98e5b7246..000000000 --- a/include/asm-i386/relay.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef _ASM_I386_RELAY_H -#define _ASM_I386_RELAY_H -/* - * linux/include/asm-i386/relay.h - * - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 2002 - Karim Yaghmour (karim@opersys.com) - * - * i386 definitions for relayfs - */ - -#include - -#ifdef CONFIG_X86_TSC -#include - -/** - * get_time_delta - utility function for getting time delta - * @now: pointer to a timeval struct that may be given current time - * @rchan: the channel - * - * Returns either the TSC if TSCs are being used, or the time and the - * time difference between the current time and the buffer start time - * if TSCs are not being used. - */ -static inline u32 -get_time_delta(struct timeval *now, struct rchan *rchan) -{ - u32 time_delta; - - if ((using_tsc(rchan) == 1) && cpu_has_tsc) - rdtscl(time_delta); - else { - do_gettimeofday(now); - time_delta = calc_time_delta(now, &rchan->buf_start_time); - } - - return time_delta; -} - -/** - * get_timestamp - utility function for getting a time and TSC pair - * @now: current time - * @tsc: the TSC associated with now - * @rchan: the channel - * - * Sets the value pointed to by now to the current time and the value - * pointed to by tsc to the tsc associated with that time, if the - * platform supports TSC. - */ -static inline void -get_timestamp(struct timeval *now, - u32 *tsc, - struct rchan *rchan) -{ - do_gettimeofday(now); - - if ((using_tsc(rchan) == 1) && cpu_has_tsc) - rdtscl(*tsc); -} - -/** - * get_time_or_tsc - utility function for getting a time or a TSC - * @now: current time - * @tsc: current TSC - * @rchan: the channel - * - * Sets the value pointed to by now to the current time or the value - * pointed to by tsc to the current tsc, depending on whether we're - * using TSCs or not. - */ -static inline void -get_time_or_tsc(struct timeval *now, - u32 *tsc, - struct rchan *rchan) -{ - if ((using_tsc(rchan) == 1) && cpu_has_tsc) - rdtscl(*tsc); - else - do_gettimeofday(now); -} - -/** - * have_tsc - does this platform have a useable TSC? - * - * Returns 1 if this platform has a useable TSC counter for - * timestamping purposes, 0 otherwise. - */ -static inline int -have_tsc(void) -{ - if (cpu_has_tsc) - return 1; - else - return 0; -} - -#else /* No TSC support (#ifdef CONFIG_X86_TSC) */ -#include -#endif /* #ifdef CONFIG_X86_TSC */ -#endif diff --git a/include/asm-ia64/cpu.h b/include/asm-ia64/cpu.h deleted file mode 100644 index 33c5d0fe9..000000000 --- a/include/asm-ia64/cpu.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ASM_IA64_CPU_H_ -#define _ASM_IA64_CPU_H_ - -#include -#include -#include -#include - -struct ia64_cpu { - struct cpu cpu; -}; - -DECLARE_PER_CPU(struct ia64_cpu, cpu_devices); - -DECLARE_PER_CPU(int, cpu_state); - -#endif /* _ASM_IA64_CPU_H_ */ diff --git a/include/asm-ia64/relay.h b/include/asm-ia64/relay.h deleted file mode 100644 index 1d7628ec6..000000000 --- a/include/asm-ia64/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_IA64_RELAY_H -#define _ASM_IA64_RELAY_H - -#include -#endif diff --git a/include/asm-m68k/relay.h b/include/asm-m68k/relay.h deleted file mode 100644 index ec637ffb8..000000000 --- a/include/asm-m68k/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_M68K_RELAY_H -#define _ASM_M68K_RELAY_H - -#include -#endif diff --git a/include/asm-m68knommu/relay.h b/include/asm-m68knommu/relay.h deleted file mode 100644 index ef1afa6b2..000000000 --- a/include/asm-m68knommu/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_M68KNOMMU_RELAY_H -#define _ASM_M68KNOMMU_RELAY_H - -#include -#endif diff --git a/include/asm-mips/8253pit.h b/include/asm-mips/8253pit.h deleted file mode 100644 index 285f78488..000000000 --- a/include/asm-mips/8253pit.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 8253/8254 Programmable Interval Timer - */ - -#ifndef _8253PIT_H -#define _8253PIT_H - -#define PIT_TICK_RATE 1193182UL - -#endif diff --git a/include/asm-mips/pmon.h b/include/asm-mips/pmon.h deleted file mode 100644 index 016251785..000000000 --- a/include/asm-mips/pmon.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2004 by Ralf Baechle - */ -#ifndef _ASM_PMON_H -#define _ASM_PMON_H - -struct callvectors { - int (*open) (char*, int, int); /* 0 */ - int (*close) (int); /* 4 */ - int (*read) (int, void*, int); /* 8 */ - int (*write) (int, void*, int); /* 12 */ - off_t (*lseek) (int, off_t, int); /* 16 */ - int (*printf) (const char*, ...); /* 20 */ - void (*cacheflush) (void); /* 24 */ - char* (*gets) (char*); /* 28 */ -}; - -#endif /* _ASM_PMON_H */ diff --git a/include/asm-mips/relay.h b/include/asm-mips/relay.h deleted file mode 100644 index 37304bd30..000000000 --- a/include/asm-mips/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_RELAY_H -#define _ASM_RELAY_H - -#include -#endif diff --git a/include/asm-mips64/relay.h b/include/asm-mips64/relay.h deleted file mode 100644 index 37304bd30..000000000 --- a/include/asm-mips64/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_RELAY_H -#define _ASM_RELAY_H - -#include -#endif diff --git a/include/asm-parisc/relay.h b/include/asm-parisc/relay.h deleted file mode 100644 index cea0c777f..000000000 --- a/include/asm-parisc/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_PARISC_RELAY_H -#define _ASM_PARISC_RELAY_H - -#include -#endif diff --git a/include/asm-parisc/unwind.h b/include/asm-parisc/unwind.h deleted file mode 100644 index 5a52cb1f1..000000000 --- a/include/asm-parisc/unwind.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _UNWIND_H_ -#define _UNWIND_H_ - -/* From ABI specifications */ -struct unwind_table_entry { - unsigned int region_start; - unsigned int region_end; - unsigned int Cannot_unwind:1; /* 0 */ - unsigned int Millicode:1; /* 1 */ - unsigned int Millicode_save_sr0:1; /* 2 */ - unsigned int Region_description:2; /* 3..4 */ - unsigned int reserved1:1; /* 5 */ - unsigned int Entry_SR:1; /* 6 */ - unsigned int Entry_FR:4; /* number saved *//* 7..10 */ - unsigned int Entry_GR:5; /* number saved *//* 11..15 */ - unsigned int Args_stored:1; /* 16 */ - unsigned int Variable_Frame:1; /* 17 */ - unsigned int Separate_Package_Body:1; /* 18 */ - unsigned int Frame_Extension_Millicode:1; /* 19 */ - unsigned int Stack_Overflow_Check:1; /* 20 */ - unsigned int Two_Instruction_SP_Increment:1; /* 21 */ - unsigned int Ada_Region:1; /* 22 */ - unsigned int cxx_info:1; /* 23 */ - unsigned int cxx_try_catch:1; /* 24 */ - unsigned int sched_entry_seq:1; /* 25 */ - unsigned int reserved2:1; /* 26 */ - unsigned int Save_SP:1; /* 27 */ - unsigned int Save_RP:1; /* 28 */ - unsigned int Save_MRP_in_frame:1; /* 29 */ - unsigned int extn_ptr_defined:1; /* 30 */ - unsigned int Cleanup_defined:1; /* 31 */ - - unsigned int MPE_XL_interrupt_marker:1; /* 0 */ - unsigned int HP_UX_interrupt_marker:1; /* 1 */ - unsigned int Large_frame:1; /* 2 */ - unsigned int Pseudo_SP_Set:1; /* 3 */ - unsigned int reserved4:1; /* 4 */ - unsigned int Total_frame_size:27; /* 5..31 */ -}; - -struct unwind_table { - struct unwind_table *next; - const char *name; - unsigned long gp; - unsigned long base_addr; - unsigned long start; - unsigned long end; - const struct unwind_table_entry *table; - unsigned long length; -}; - -struct unwind_frame_info { - unsigned long sp; - unsigned long ip; - struct task_struct *t; - /* Eventually we would like to be able to get at any of the registers - available; but for now we only try to get the sp and ip for each - frame */ - /* struct pt_regs regs; */ - unsigned long prev_sp, prev_ip; -}; - -void * unwind_table_add(const char *name, unsigned long base_addr, - unsigned long gp, - const void *start, const void *end); -void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, - struct pt_regs *regs); -void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t); -int unwind_once(struct unwind_frame_info *info); -int unwind_to_user(struct unwind_frame_info *info); - -#endif diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h deleted file mode 100644 index 8c61d9304..000000000 --- a/include/asm-ppc/ibm_ocp.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * ibm_ocp.h - * - * (c) Benjamin Herrenschmidt (benh@kernel.crashing.org) - * Mipsys - France - * - * Derived from work (c) Armin Kuster akuster@pacbell.net - * - * Additional support and port to 2.6 LDM/sysfs by - * Matt Porter - * Copyright 2003-2004 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#ifdef __KERNEL__ -#ifndef __IBM_OCP_H__ -#define __IBM_OCP_H__ - -#include - -/* - * IBM 4xx OCP system information - */ -struct ocp_sys_info_data { - int opb_bus_freq; /* OPB Bus Frequency (Hz) */ - int ebc_bus_freq; /* EBC Bus Frequency (Hz) */ -}; - -extern struct ocp_sys_info_data ocp_sys_info; - -/* - * EMAC additional data and sysfs support - * - * Note about mdio_idx: When you have a zmii, it's usually - * not necessary, it covers the case of the 405EP which has - * the MDIO lines on EMAC0 only - * - * Note about phy_map: Per EMAC map of PHY ids which should - * be probed by emac_probe. Different EMACs can have - * overlapping maps. - * - * Note, this map uses inverse logic for bits: - * 0 - id should be probed - * 1 - id should be ignored - * - * Default value of 0x00000000 - will result in usual - * auto-detection logic. - * - */ - -struct ocp_func_emac_data { - int rgmii_idx; /* RGMII device index or -1 */ - int rgmii_mux; /* RGMII input of this EMAC */ - int zmii_idx; /* ZMII device index or -1 */ - int zmii_mux; /* ZMII input of this EMAC */ - int mal_idx; /* MAL device index */ - int mal_rx_chan; /* MAL rx channel number */ - int mal_tx_chan; /* MAL tx channel number */ - int wol_irq; /* WOL interrupt */ - int mdio_idx; /* EMAC idx of MDIO master or -1 */ - int tah_idx; /* TAH device index or -1 */ - int jumbo; /* Jumbo frames capable flag */ - int phy_mode; /* PHY type or configurable mode */ - u8 mac_addr[6]; /* EMAC mac address */ - u32 phy_map; /* EMAC phy map */ -}; - -/* Sysfs support */ -#define OCP_SYSFS_EMAC_DATA() \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_idx) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_mux) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_idx) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_rx_chan) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_tx_chan) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, wol_irq) \ -OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx) \ - \ -void ocp_show_emac_data(struct device *dev) \ -{ \ - device_create_file(dev, &dev_attr_emac_zmii_idx); \ - device_create_file(dev, &dev_attr_emac_zmii_mux); \ - device_create_file(dev, &dev_attr_emac_mal_idx); \ - device_create_file(dev, &dev_attr_emac_mal_rx_chan); \ - device_create_file(dev, &dev_attr_emac_mal_tx_chan); \ - device_create_file(dev, &dev_attr_emac_wol_irq); \ - device_create_file(dev, &dev_attr_emac_mdio_idx); \ -} - -#ifdef CONFIG_40x -/* - * Helper function to copy MAC addresses from the bd_t to OCP EMAC - * additions. - * - * The range of EMAC indices (inclusive) to be copied are the arguments. - */ -static inline void ibm_ocp_set_emac(int start, int end) -{ - int i; - struct ocp_def *def; - - /* Copy MAC addresses to EMAC additions */ - for (i=start; i<=end; i++) { - def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); - memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, - &__res.bi_enetaddr[i], - 6); - } -} -#endif - -/* - * MAL additional data and sysfs support - */ -struct ocp_func_mal_data { - int num_tx_chans; /* Number of TX channels */ - int num_rx_chans; /* Number of RX channels */ - int txeob_irq; /* TX End Of Buffer IRQ */ - int rxeob_irq; /* RX End Of Buffer IRQ */ - int txde_irq; /* TX Descriptor Error IRQ */ - int rxde_irq; /* RX Descriptor Error IRQ */ - int serr_irq; /* MAL System Error IRQ */ -}; - -#define OCP_SYSFS_MAL_DATA() \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, num_tx_chans) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, num_rx_chans) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, txeob_irq) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, rxeob_irq) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, txde_irq) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, rxde_irq) \ -OCP_SYSFS_ADDTL(struct ocp_func_mal_data, "%d\n", mal, serr_irq) \ - \ -void ocp_show_mal_data(struct device *dev) \ -{ \ - device_create_file(dev, &dev_attr_mal_num_tx_chans); \ - device_create_file(dev, &dev_attr_mal_num_rx_chans); \ - device_create_file(dev, &dev_attr_mal_txeob_irq); \ - device_create_file(dev, &dev_attr_mal_rxeob_irq); \ - device_create_file(dev, &dev_attr_mal_txde_irq); \ - device_create_file(dev, &dev_attr_mal_rxde_irq); \ - device_create_file(dev, &dev_attr_mal_serr_irq); \ -} - -/* - * IIC additional data and sysfs support - */ -struct ocp_func_iic_data { - int fast_mode; /* IIC fast mode enabled */ -}; - -#define OCP_SYSFS_IIC_DATA() \ -OCP_SYSFS_ADDTL(struct ocp_func_iic_data, "%d\n", iic, fast_mode) \ - \ -void ocp_show_iic_data(struct device *dev) \ -{ \ - device_create_file(dev, &dev_attr_iic_fast_mode); \ -} -#endif /* __IBM_OCP_H__ */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/relay.h b/include/asm-ppc/relay.h deleted file mode 100644 index c5b8526a7..000000000 --- a/include/asm-ppc/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_PPC_RELAY_H -#define _ASM_PPC_RELAY_H - -#include -#endif diff --git a/include/asm-ppc64/relay.h b/include/asm-ppc64/relay.h deleted file mode 100644 index 3c428ef02..000000000 --- a/include/asm-ppc64/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_PPC64_RELAY_H -#define _ASM_PPC64_RELAY_H - -#include -#endif diff --git a/include/asm-s390/relay.h b/include/asm-s390/relay.h deleted file mode 100644 index 502eb3b58..000000000 --- a/include/asm-s390/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_S390_RELAY_H -#define _ASM_S390_RELAY_H - -#include -#endif diff --git a/include/asm-sh/relay.h b/include/asm-sh/relay.h deleted file mode 100644 index fd8b76416..000000000 --- a/include/asm-sh/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_SH_RELAY_H -#define _ASM_SH_RELAY_H - -#include -#endif diff --git a/include/asm-sparc/relay.h b/include/asm-sparc/relay.h deleted file mode 100644 index 2141eac01..000000000 --- a/include/asm-sparc/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_SPARC_RELAY_H -#define _ASM_SPARC_RELAY_H - -#include -#endif diff --git a/include/asm-sparc64/const.h b/include/asm-sparc64/const.h deleted file mode 100644 index 8ad902b2c..000000000 --- a/include/asm-sparc64/const.h +++ /dev/null @@ -1,19 +0,0 @@ -/* const.h: Macros for dealing with constants. */ - -#ifndef _SPARC64_CONST_H -#define _SPARC64_CONST_H - -/* Some constant macros are used in both assembler and - * C code. Therefore we cannot annotate them always with - * 'UL' and other type specificers unilaterally. We - * use the following macros to deal with this. - */ - -#ifdef __ASSEMBLY__ -#define _AC(X,Y) X -#else -#define _AC(X,Y) (X##Y) -#endif - - -#endif /* !(_SPARC64_CONST_H) */ diff --git a/include/asm-sparc64/relay.h b/include/asm-sparc64/relay.h deleted file mode 100644 index 72ea16410..000000000 --- a/include/asm-sparc64/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_SPARC64_RELAY_H -#define _ASM_SPARC64_RELAY_H - -#include -#endif diff --git a/include/asm-um/cpufeature.h b/include/asm-um/cpufeature.h deleted file mode 100644 index fb7bd42a4..000000000 --- a/include/asm-um/cpufeature.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_CPUFEATURE_H -#define __UM_CPUFEATURE_H - -#include "asm/arch/cpufeature.h" - -#endif diff --git a/include/asm-um/local.h b/include/asm-um/local.h deleted file mode 100644 index 9a280c5bb..000000000 --- a/include/asm-um/local.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_LOCAL_H -#define __UM_LOCAL_H - -#include "asm/arch/local.h" - -#endif diff --git a/include/asm-um/module-generic.h b/include/asm-um/module-generic.h deleted file mode 100644 index 5a265f56b..000000000 --- a/include/asm-um/module-generic.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_MODULE_GENERIC_H -#define __UM_MODULE_GENERIC_H - -#include "asm/arch/module.h" - -#endif diff --git a/include/asm-um/sections.h b/include/asm-um/sections.h deleted file mode 100644 index 6b0231eef..000000000 --- a/include/asm-um/sections.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _UM_SECTIONS_H -#define _UM_SECTIONS_H - -/* nothing to see, move along */ -#include - -#endif diff --git a/include/asm-v850/relay.h b/include/asm-v850/relay.h deleted file mode 100644 index 869a53890..000000000 --- a/include/asm-v850/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __V850_RELAY_H -#define __V850_RELAY_H - -#include -#endif diff --git a/include/asm-x86_64/8253pit.h b/include/asm-x86_64/8253pit.h deleted file mode 100644 index 285f78488..000000000 --- a/include/asm-x86_64/8253pit.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 8253/8254 Programmable Interval Timer - */ - -#ifndef _8253PIT_H -#define _8253PIT_H - -#define PIT_TICK_RATE 1193182UL - -#endif diff --git a/include/asm-x86_64/relay.h b/include/asm-x86_64/relay.h deleted file mode 100644 index d8b1b8859..000000000 --- a/include/asm-x86_64/relay.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ASM_X86_64_RELAY_H -#define _ASM_X86_64_RELAY_H - -#include -#endif diff --git a/include/linux/ckrm.h b/include/linux/ckrm.h deleted file mode 100644 index 99ab97e3a..000000000 --- a/include/linux/ckrm.h +++ /dev/null @@ -1,156 +0,0 @@ -/* ckrm.h - Class-based Kernel Resource Management (CKRM) - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004 - * (C) Shailabh Nagar, IBM Corp. 2003 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * - * - * Provides a base header file including macros and basic data structures. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 28 Aug 2003 - * Created. - * 06 Nov 2003 - * Made modifications to suit the new RBCE module. - * 10 Nov 2003 - * Added callbacks_active and surrounding logic. Added task paramter - * for all CE callbacks. - * 19 Nov 2004 - * New Event callback structure - */ - -#ifndef _LINUX_CKRM_H -#define _LINUX_CKRM_H - -#ifdef CONFIG_CKRM - -// Data structure and function to get the list of registered -// resource controllers. - -// #include - -/* CKRM defines a set of events at particular points in the kernel - * at which callbacks registered by various class types are called - */ - -enum ckrm_event { - /* we distinguish various events types - * - * (a) CKRM_LATCHABLE_EVENTS - * events can be latched for event callbacks by classtypes - * - * (b) CKRM_NONLATACHBLE_EVENTS - * events can not be latched but can be used to call classification - * - * (c) event that are used for notification purposes - * range: [ CKRM_EVENT_CANNOT_CLASSIFY .. ) - */ - - /* events (a) */ - - CKRM_LATCHABLE_EVENTS, - - CKRM_EVENT_NEWTASK = CKRM_LATCHABLE_EVENTS, - CKRM_EVENT_FORK, - CKRM_EVENT_EXIT, - CKRM_EVENT_EXEC, - CKRM_EVENT_UID, - CKRM_EVENT_GID, - CKRM_EVENT_LOGIN, - CKRM_EVENT_USERADD, - CKRM_EVENT_USERDEL, - CKRM_EVENT_LISTEN_START, - CKRM_EVENT_LISTEN_STOP, - CKRM_EVENT_APPTAG, - - /* events (b) */ - - CKRM_NONLATCHABLE_EVENTS, - - CKRM_EVENT_RECLASSIFY = CKRM_NONLATCHABLE_EVENTS, - - /* events (c) */ - CKRM_NOTCLASSIFY_EVENTS, - - CKRM_EVENT_MANUAL = CKRM_NOTCLASSIFY_EVENTS, - - CKRM_NUM_EVENTS -}; -#endif - -#ifdef __KERNEL__ -#ifdef CONFIG_CKRM - -extern void ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg); - -typedef void (*ckrm_event_cb)(void *arg); - -struct ckrm_hook_cb { - ckrm_event_cb fct; - struct ckrm_hook_cb *next; -}; - -#define CKRM_DEF_CB(EV,fct) \ -static inline void ckrm_cb_##fct(void) \ -{ \ - ckrm_invoke_event_cb_chain(CKRM_EVENT_##EV,NULL); \ -} - -#define CKRM_DEF_CB_ARG(EV,fct,argtp) \ -static inline void ckrm_cb_##fct(argtp arg) \ -{ \ - ckrm_invoke_event_cb_chain(CKRM_EVENT_##EV,(void*)arg); \ -} - -#else // !CONFIG_CKRM - -#define CKRM_DEF_CB(EV,fct) \ -static inline void ckrm_cb_##fct(void) { } - -#define CKRM_DEF_CB_ARG(EV,fct,argtp) \ -static inline void ckrm_cb_##fct(argtp arg) { } - -#endif // CONFIG_CKRM - -/*----------------------------------------------------------------- - * define the CKRM event functions - * EVENT FCT ARG - *-----------------------------------------------------------------*/ - -// types we refer at -struct task_struct; -struct sock; -struct user_struct; - -CKRM_DEF_CB_ARG( FORK , fork, struct task_struct *); -CKRM_DEF_CB_ARG( EXEC , exec, const char* ); -CKRM_DEF_CB ( UID , uid ); -CKRM_DEF_CB ( GID , gid ); -CKRM_DEF_CB ( APPTAG , apptag ); -CKRM_DEF_CB ( LOGIN , login ); -CKRM_DEF_CB_ARG( USERADD , useradd, struct user_struct *); -CKRM_DEF_CB_ARG( USERDEL , userdel, struct user_struct *); -CKRM_DEF_CB_ARG( LISTEN_START , listen_start, struct sock * ); -CKRM_DEF_CB_ARG( LISTEN_STOP , listen_stop, struct sock * ); - -// and a few special one's -void ckrm_cb_newtask(struct task_struct *); -void ckrm_cb_exit(struct task_struct *); - -// some other functions required -extern void ckrm_init(void); -extern int get_exe_path_name(struct task_struct *, char *, int); - -#endif // __KERNEL__ - -#endif // _LINUX_CKRM_H diff --git a/include/linux/ckrm_ce.h b/include/linux/ckrm_ce.h deleted file mode 100644 index 0bde15dd3..000000000 --- a/include/linux/ckrm_ce.h +++ /dev/null @@ -1,91 +0,0 @@ -/* ckrm_ce.h - Header file to be used by Classification Engine of CKRM - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003 - * (C) Shailabh Nagar, IBM Corp. 2003 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * - * Provides data structures, macros and kernel API of CKRM for - * classification engine. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 12 Nov 2003 - * Created. - * 22 Apr 2004 - * Adopted to classtypes - */ - -#ifndef _LINUX_CKRM_CE_H -#define _LINUX_CKRM_CE_H - -#ifdef CONFIG_CKRM - -#include "ckrm.h" // getting the event names - -/* Action parameters identifying the cause of a task<->class notify callback - * these can perculate up to user daemon consuming records send by the classification - * engine - */ - -#ifdef __KERNEL__ - -typedef void* (*ce_classify_fct_t)(enum ckrm_event event, void *obj, ... ); -typedef void (*ce_notify_fct_t) (enum ckrm_event event, void *classobj, void *obj); - -typedef struct ckrm_eng_callback { - /* general state information */ - int always_callback; /* set if CE should always be called back regardless of numclasses */ - - /* callbacks which are called without holding locks */ - - unsigned long c_interest; /* set of classification events CE is interested in */ - ce_classify_fct_t classify; /* generic classify */ - - void (*class_add) (const char *name, void *core); /* class added */ - void (*class_delete)(const char *name, void *core); /* class deleted */ - - /* callback which are called while holding task_lock(tsk) */ - unsigned long n_interest; /* set of notification events CE is interested in */ - ce_notify_fct_t notify; /* notify on class switch */ - -} ckrm_eng_callback_t; - -struct inode; -struct dentry; - -typedef struct rbce_eng_callback { - int (*mkdir)(struct inode *, struct dentry *, int); // mkdir - int (*rmdir)(struct inode *, struct dentry *); // rmdir -} rbce_eng_callback_t; - -extern int ckrm_register_engine (const char *name, ckrm_eng_callback_t *); -extern int ckrm_unregister_engine(const char *name); - -extern void *ckrm_classobj(char *, int *classtype); -extern int get_exe_path_name(struct task_struct *t, char *filename, int max_size); - -extern int rcfs_register_engine(rbce_eng_callback_t *); -extern int rcfs_unregister_engine(rbce_eng_callback_t *); - -extern int ckrm_reclassify(int pid); - -#ifndef _LINUX_CKRM_RC_H -// ckrm kernel has inlined functions for this which are exported -extern void ckrm_core_grab(void *); -extern void ckrm_core_drop(void *); -#endif - -#endif // CONFIG_CKRM - -#endif // __KERNEL__ - -#endif // _LINUX_CKRM_CE_H diff --git a/include/linux/ckrm_net.h b/include/linux/ckrm_net.h deleted file mode 100644 index 0cbf784bb..000000000 --- a/include/linux/ckrm_net.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ckrm_rc.h - Header file to be used by Resource controllers of CKRM - * - * Copyright (C) Vivek Kashyap , IBM Corp. 2004 - * - * Provides data structures, macros and kernel API of CKRM for - * resource controllers. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef _LINUX_CKRM_NET_H -#define _LINUX_CKRM_NET_H - -struct ckrm_sock_class; - -struct ckrm_net_struct { - int ns_type; // type of net class - struct sock *ns_sk; // pointer to socket - pid_t ns_tgid; // real process id - pid_t ns_pid; // calling thread's pid - int ns_family; // IPPROTO_IPV4 || IPPROTO_IPV6 - // Currently only IPV4 is supported - union { - __u32 ns_dipv4; // V4 listener's address - } ns_daddr; - __u16 ns_dport; // listener's port - __u16 ns_sport; // sender's port - atomic_t ns_refcnt; - struct ckrm_sock_class *core; - struct list_head ckrm_link; -}; - -#define ns_daddrv4 ns_daddr.ns_dipv4 - -#endif diff --git a/include/linux/ckrm_rc.h b/include/linux/ckrm_rc.h deleted file mode 100644 index e514f1c72..000000000 --- a/include/linux/ckrm_rc.h +++ /dev/null @@ -1,367 +0,0 @@ -/* ckrm_rc.h - Header file to be used by Resource controllers of CKRM - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003 - * (C) Shailabh Nagar, IBM Corp. 2003 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * (C) Vivek Kashyap , IBM Corp. 2004 - * - * Provides data structures, macros and kernel API of CKRM for - * resource controllers. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 12 Nov 2003 - * Created. - */ - -#ifndef _LINUX_CKRM_RC_H -#define _LINUX_CKRM_RC_H - -#ifdef __KERNEL__ - -#ifdef CONFIG_CKRM - -#include -#include -#include -#include - - -/* maximum number of class types */ -#define CKRM_MAX_CLASSTYPES 32 -/* maximum classtype name length */ -#define CKRM_MAX_CLASSTYPE_NAME 32 - -/* maximum resource controllers per classtype */ -#define CKRM_MAX_RES_CTLRS 8 -/* maximum resource controller name length */ -#define CKRM_MAX_RES_NAME 128 - - -struct ckrm_core_class; -struct ckrm_classtype; - -/******************************************************************************** - * Share specifications - *******************************************************************************/ - -typedef struct ckrm_shares { - int my_guarantee; - int my_limit; - int total_guarantee; - int max_limit; - int unused_guarantee; // not used as parameters - int cur_max_limit; // not used as parameters -} ckrm_shares_t; - -#define CKRM_SHARE_UNCHANGED (-1) // value to indicate no change -#define CKRM_SHARE_DONTCARE (-2) // value to indicate don't care. -#define CKRM_SHARE_DFLT_TOTAL_GUARANTEE (100) // Start off with these values -#define CKRM_SHARE_DFLT_MAX_LIMIT (100) // to simplify set_res_shares logic - - -/******************************************************************************** - * RESOURCE CONTROLLERS - *******************************************************************************/ - -/* resource controller callback structure */ - -typedef struct ckrm_res_ctlr { - char res_name[CKRM_MAX_RES_NAME]; - int res_hdepth; // maximum hierarchy - int resid; // (for now) same as the enum resid - struct ckrm_classtype *classtype; // classtype owning this resource controller - - /* allocate/free new resource class object for resource controller */ - void *(*res_alloc) (struct ckrm_core_class *this, struct ckrm_core_class *parent); - void (*res_free) (void *); - - /* set/get limits/guarantees for a resource controller class */ - int (*set_share_values) (void* , struct ckrm_shares *shares); - int (*get_share_values) (void* , struct ckrm_shares *shares); - - /* statistics and configuration access */ - int (*get_stats) (void* , struct seq_file *); - int (*reset_stats) (void *); - int (*show_config) (void* , struct seq_file *); - int (*set_config) (void* , const char *cfgstr); - - void (*change_resclass)(void *, void *, void *); - -} ckrm_res_ctlr_t; - -/*************************************************************************************** - * CKRM_CLASSTYPE - * - * A object describes a dimension for CKRM to classify - * along. I needs to provide methods to create and manipulate class objects in - * this dimension - ***************************************************************************************/ - -/* list of predefined class types, we always recognize */ -#define CKRM_CLASSTYPE_TASK_CLASS 0 -#define CKRM_CLASSTYPE_SOCKET_CLASS 1 -#define CKRM_RESV_CLASSTYPES 2 /* always +1 of last known type */ - -#define CKRM_MAX_TYPENAME_LEN 32 - - -typedef struct ckrm_classtype { - /* Hubertus: Rearrange slots so that they are more cache friendly during access */ - - /* resource controllers */ - spinlock_t res_ctlrs_lock; /* protect data below (other than atomics) */ - int max_res_ctlrs; /* maximum number of resource controller allowed */ - int max_resid; /* maximum resid used */ - int resid_reserved; /* maximum number of reserved controllers */ - long bit_res_ctlrs; /* bitmap of resource ID used */ - atomic_t nr_resusers[CKRM_MAX_RES_CTLRS]; - ckrm_res_ctlr_t* res_ctlrs[CKRM_MAX_RES_CTLRS]; - - /* state about my classes */ - - struct ckrm_core_class *default_class; // pointer to default class - struct list_head classes; // listhead to link up all classes of this classtype - int num_classes; // how many classes do exist - - /* state about my ce interaction */ - int ce_regd; // Has a CE been registered for this classtype - int ce_cb_active; // are callbacks active - atomic_t ce_nr_users; // how many transient calls active - struct ckrm_eng_callback ce_callbacks; // callback engine - - // Begin classtype-rcfs private data. No rcfs/fs specific types used. - int mfidx; // Index into genmfdesc array used to initialize - // mfdesc and mfcount - void *mfdesc; // Array of descriptors of root and magic files - int mfcount; // length of above array - void *rootde; // root dentry created by rcfs - // End rcfs private data - - char name[CKRM_MAX_TYPENAME_LEN]; // currently same as mfdesc[0]->name but could be different - int typeID; /* unique TypeID */ - int maxdepth; /* maximum depth supported */ - - /* functions to be called on any class type by external API's */ - struct ckrm_core_class* (*alloc)(struct ckrm_core_class *parent, const char *name); /* alloc class instance */ - int (*free) (struct ckrm_core_class *cls); /* free class instance */ - - int (*show_members)(struct ckrm_core_class *, struct seq_file *); - int (*show_stats) (struct ckrm_core_class *, struct seq_file *); - int (*show_config) (struct ckrm_core_class *, struct seq_file *); - int (*show_shares) (struct ckrm_core_class *, struct seq_file *); - - int (*reset_stats) (struct ckrm_core_class *, const char *resname, - const char *); - int (*set_config) (struct ckrm_core_class *, const char *resname, - const char *cfgstr); - int (*set_shares) (struct ckrm_core_class *, const char *resname, - struct ckrm_shares *shares); - int (*forced_reclassify)(struct ckrm_core_class *, const char *); - - - /* functions to be called on a class type by ckrm internals */ - void (*add_resctrl)(struct ckrm_core_class *, int resid); // class initialization for new RC - -} ckrm_classtype_t; - -/****************************************************************************************** - * CKRM CORE CLASS - * common part to any class structure (i.e. instance of a classtype) - ******************************************************************************************/ - -/* basic definition of a hierarchy that is to be used by the the CORE classes - * and can be used by the resource class objects - */ - -#define CKRM_CORE_MAGIC 0xBADCAFFE - -typedef struct ckrm_hnode { - struct ckrm_core_class *parent; - struct list_head siblings; /* linked list of siblings */ - struct list_head children; /* anchor for children */ -} ckrm_hnode_t; - -typedef struct ckrm_core_class { - struct ckrm_classtype *classtype; // what type does this core class belong to - void* res_class[CKRM_MAX_RES_CTLRS]; // pointer to array of resource classes - spinlock_t class_lock; // to protect the list and the array above - struct list_head objlist; // generic list for any object list to be maintained by class - struct list_head clslist; // to link up all classes in a single list type wrt to type - struct dentry *dentry; // dentry of inode in the RCFS - int magic; - struct ckrm_hnode hnode; // hierarchy - rwlock_t hnode_rwlock; // rw_clock protecting the hnode above. - atomic_t refcnt; - const char *name; - int delayed; // core deletion delayed because of race conditions -} ckrm_core_class_t; - -/* type coerce between derived class types and ckrm core class type */ -#define class_type(type,coreptr) container_of(coreptr,type,core) -#define class_core(clsptr) (&(clsptr)->core) -/* locking classes */ -#define class_lock(coreptr) spin_lock(&(coreptr)->class_lock) -#define class_unlock(coreptr) spin_unlock(&(coreptr)->class_lock) -/* what type is a class of ISA */ -#define class_isa(clsptr) (class_core(clsptr)->classtype) - - -/****************************************************************************************** - * OTHER - ******************************************************************************************/ - -#define ckrm_get_res_class(rescls,resid,type) ((type*)((rescls)->res_class[resid])) - -extern int ckrm_register_res_ctlr (struct ckrm_classtype *, ckrm_res_ctlr_t *); -extern int ckrm_unregister_res_ctlr (ckrm_res_ctlr_t *); - -extern int ckrm_validate_and_grab_core(struct ckrm_core_class *core); -extern int ckrm_init_core_class(struct ckrm_classtype *clstype,struct ckrm_core_class *dcore, - struct ckrm_core_class *parent, const char *name); -extern int ckrm_release_core_class(struct ckrm_core_class *); // Hubertus .. can disappear after cls del debugging -extern struct ckrm_res_ctlr *ckrm_resctlr_lookup(struct ckrm_classtype *type, const char *resname); - -#if 0 - -// Hubertus ... need to straighten out all these I don't think we will even call thsie ore are we - -/* interface to the RCFS filesystem */ -extern struct ckrm_core_class *ckrm_alloc_core_class(struct ckrm_core_class *, const char *, int); - -// Reclassify the given pid to the given core class by force -extern void ckrm_forced_reclassify_pid(int, struct ckrm_core_class *); - -// Reclassify the given net_struct to the given core class by force -extern void ckrm_forced_reclassify_laq(struct ckrm_net_struct *, - struct ckrm_core_class *); - -#endif - -extern void ckrm_lock_hier(struct ckrm_core_class *); -extern void ckrm_unlock_hier(struct ckrm_core_class *); -extern struct ckrm_core_class * ckrm_get_next_child(struct ckrm_core_class *, - struct ckrm_core_class *); - -extern void child_guarantee_changed(struct ckrm_shares *, int, int); -extern void child_maxlimit_changed(struct ckrm_shares *, int); -extern int set_shares(struct ckrm_shares *, struct ckrm_shares *, struct ckrm_shares *); - -/* classtype registration and lookup */ -extern int ckrm_register_classtype (struct ckrm_classtype *clstype); -extern int ckrm_unregister_classtype(struct ckrm_classtype *clstype); -extern struct ckrm_classtype* ckrm_find_classtype_by_name(const char *name); - -/* default functions that can be used in classtypes's function table */ -extern int ckrm_class_show_shares(struct ckrm_core_class *core, struct seq_file *seq); -extern int ckrm_class_show_stats(struct ckrm_core_class *core, struct seq_file *seq); -extern int ckrm_class_show_config(struct ckrm_core_class *core, struct seq_file *seq); -extern int ckrm_class_set_config(struct ckrm_core_class *core, const char *resname, const char *cfgstr); -extern int ckrm_class_set_shares(struct ckrm_core_class *core, const char *resname, struct ckrm_shares *shares); -extern int ckrm_class_reset_stats(struct ckrm_core_class *core, const char *resname, const char *unused); - -#if 0 -extern void ckrm_ns_hold(struct ckrm_net_struct *); -extern void ckrm_ns_put(struct ckrm_net_struct *); -extern void *ckrm_set_rootcore_byname(char *, void *); -#endif - -static inline void ckrm_core_grab(struct ckrm_core_class *core) -{ - if (core) atomic_inc(&core->refcnt); -} - -static inline void ckrm_core_drop(struct ckrm_core_class *core) -{ - // only make definition available in this context - extern void ckrm_free_core_class(struct ckrm_core_class *core); - if (core && (atomic_dec_and_test(&core->refcnt))) - ckrm_free_core_class(core); -} - -static inline unsigned int -ckrm_is_core_valid(ckrm_core_class_t *core) -{ - return (core && (core->magic == CKRM_CORE_MAGIC)); -} - -// iterate through all associate resource controllers: -// requires following arguments (ckrm_core_class *cls, -// ckrm_res_ctrl *ctlr, -// void *robj, -// int bmap) -#define forall_class_resobjs(cls,rcbs,robj,bmap) \ - for ( bmap=((cls->classtype)->bit_res_ctlrs) ; \ - ({ int rid; ((rid=ffs(bmap)-1) >= 0) && \ - (bmap&=~(1<classtype->res_ctlrs[rid]) && (robj=cls->res_class[rid]))); }) ; \ - ) - -extern struct ckrm_classtype* ckrm_classtypes[]; /* should provide a different interface */ - - -/*----------------------------------------------------------------------------- - * CKRM event callback specification for the classtypes or resource controllers - * typically an array is specified using CKRM_EVENT_SPEC terminated with - * CKRM_EVENT_SPEC_LAST and then that array is registered using - * ckrm_register_event_set. - * Individual registration of event_cb is also possible - *-----------------------------------------------------------------------------*/ - -struct ckrm_event_spec { - enum ckrm_event ev; - struct ckrm_hook_cb cb; -}; -#define CKRM_EVENT_SPEC(EV,FCT) { CKRM_EVENT_##EV, { (ckrm_event_cb)FCT, NULL } } - -int ckrm_register_event_set(struct ckrm_event_spec especs[]); -int ckrm_unregister_event_set(struct ckrm_event_spec especs[]); -int ckrm_register_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb); -int ckrm_unregister_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb); - -/****************************************************************************************** - * CE Invocation interface - ******************************************************************************************/ - -#define ce_protect(ctype) (atomic_inc(&((ctype)->ce_nr_users))) -#define ce_release(ctype) (atomic_dec(&((ctype)->ce_nr_users))) - -// CE Classification callbacks with - -#define CE_CLASSIFY_NORET(ctype, event, objs_to_classify...) \ -do { \ - if ((ctype)->ce_cb_active && (test_bit(event,&(ctype)->ce_callbacks.c_interest))) \ - (*(ctype)->ce_callbacks.classify)(event, objs_to_classify); \ -} while (0) - -#define CE_CLASSIFY_RET(ret, ctype, event, objs_to_classify...) \ -do { \ - if ((ctype)->ce_cb_active && (test_bit(event,&(ctype)->ce_callbacks.c_interest))) \ - ret = (*(ctype)->ce_callbacks.classify)(event, objs_to_classify); \ -} while (0) - -#define CE_NOTIFY(ctype, event, cls, objs_to_classify) \ -do { \ - if ((ctype)->ce_cb_active && (test_bit(event,&(ctype)->ce_callbacks.n_interest))) \ - (*(ctype)->ce_callbacks.notify)(event,cls,objs_to_classify); \ -} while (0) - - -#endif // CONFIG_CKRM - -#endif // __KERNEL__ - -#endif // _LINUX_CKRM_RC_H - - - - - diff --git a/include/linux/ckrm_tc.h b/include/linux/ckrm_tc.h deleted file mode 100644 index 6a570252b..000000000 --- a/include/linux/ckrm_tc.h +++ /dev/null @@ -1,18 +0,0 @@ -#include - - - -#define TASK_CLASS_TYPE_NAME "taskclass" - -typedef struct ckrm_task_class { - struct ckrm_core_class core; -} ckrm_task_class_t; - - -// Index into genmfdesc array, defined in rcfs/dir_modules.c, -// which has the mfdesc entry that taskclass wants to use -#define TC_MF_IDX 0 - - -extern int ckrm_forced_reclassify_pid(int pid, struct ckrm_task_class *cls); - diff --git a/include/linux/ckrm_tsk.h b/include/linux/ckrm_tsk.h deleted file mode 100644 index 64d20dd27..000000000 --- a/include/linux/ckrm_tsk.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ckrm_tsk.h - No. of tasks resource controller for CKRM - * - * Copyright (C) Chandra Seetharaman, IBM Corp. 2003 - * - * Provides No. of tasks resource controller for CKRM - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 31 Mar 2004 - * Created. - */ - -#ifndef _LINUX_CKRM_TSK_H -#define _LINUX_CKRM_TSK_H - -#include - -#ifdef CONFIG_CKRM_RES_NUMTASKS - -extern int numtasks_get_ref(void *, int); -extern int numtasks_get_ref_resid(void *, int, int); -extern void numtasks_put_ref(void *); - -#else - -#define numtasks_get_ref(a, b) 1 -#define numtasks_get_ref_resid(a, b, c) 1 -#define numtasks_put_ref(a) - -#endif - -#endif // _LINUX_CKRM_RES_H diff --git a/include/linux/klog.h b/include/linux/klog.h deleted file mode 100644 index cb79beaa5..000000000 --- a/include/linux/klog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * KLOG Generic Logging facility built upon the relayfs infrastructure - * - * Authors: Hubertus Frankeh (frankeh@us.ibm.com) - * Tom Zanussi (zanussi@us.ibm.com) - * - * Please direct all questions/comments to zanussi@us.ibm.com - * - * Copyright (C) 2003, IBM Corp - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _LINUX_KLOG_H -#define _LINUX_KLOG_H - -extern int klog(const char *fmt, ...); -extern int klog_raw(const char *buf,int len); - -#endif /* _LINUX_KLOG_H */ diff --git a/include/linux/prio_tree.h b/include/linux/prio_tree.h deleted file mode 100644 index 4ac5c6269..000000000 --- a/include/linux/prio_tree.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _LINUX_PRIO_TREE_H -#define _LINUX_PRIO_TREE_H - -struct prio_tree_node { - struct prio_tree_node *left; - struct prio_tree_node *right; - struct prio_tree_node *parent; -}; - -struct prio_tree_root { - struct prio_tree_node *prio_tree_node; - unsigned int index_bits; -}; - -struct prio_tree_iter { - struct prio_tree_node *cur; - unsigned long mask; - unsigned long value; - int size_level; -}; - -#define INIT_PRIO_TREE_ROOT(ptr) \ -do { \ - (ptr)->prio_tree_node = NULL; \ - (ptr)->index_bits = 1; \ -} while (0) - -#define INIT_PRIO_TREE_NODE(ptr) \ -do { \ - (ptr)->left = (ptr)->right = (ptr)->parent = (ptr); \ -} while (0) - -#define INIT_PRIO_TREE_ITER(ptr) \ -do { \ - (ptr)->cur = NULL; \ - (ptr)->mask = 0UL; \ - (ptr)->value = 0UL; \ - (ptr)->size_level = 0; \ -} while (0) - -#define prio_tree_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -static inline int prio_tree_empty(const struct prio_tree_root *root) -{ - return root->prio_tree_node == NULL; -} - -static inline int prio_tree_root(const struct prio_tree_node *node) -{ - return node->parent == node; -} - -static inline int prio_tree_left_empty(const struct prio_tree_node *node) -{ - return node->left == node; -} - -static inline int prio_tree_right_empty(const struct prio_tree_node *node) -{ - return node->right == node; -} - -#endif /* _LINUX_PRIO_TREE_H */ diff --git a/include/linux/rcfs.h b/include/linux/rcfs.h deleted file mode 100644 index a2a65e8a6..000000000 --- a/include/linux/rcfs.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _LINUX_RCFS_H -#define _LINUX_RCFS_H - -#include -#include -#include -#include -#include - - - -/* The following declarations cannot be included in any of ckrm*.h files without - jumping hoops. Remove later when rearrangements done */ - -// Hubertus .. taken out -//extern ckrm_res_callback_t ckrm_res_ctlrs[CKRM_MAX_RES_CTLRS]; - -#define RCFS_MAGIC 0x4feedbac -#define RCFS_MAGF_NAMELEN 20 -extern int RCFS_IS_MAGIC; - -#define rcfs_is_magic(dentry) ((dentry)->d_fsdata == &RCFS_IS_MAGIC) - -typedef struct rcfs_inode_info { - ckrm_core_class_t *core; - char *name; - struct inode vfs_inode; -} rcfs_inode_info_t; - -#define RCFS_DEFAULT_DIR_MODE (S_IFDIR | S_IRUGO | S_IXUGO) -#define RCFS_DEFAULT_FILE_MODE (S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH) - - -struct rcfs_magf { - char name[RCFS_MAGF_NAMELEN]; - int mode; - struct inode_operations *i_op; - struct file_operations *i_fop; -}; - -struct rcfs_mfdesc { - struct rcfs_magf *rootmf; // Root directory and its magic files - int rootmflen; // length of above array - // Can have a different magf describing magic files for non-root entries too -}; - -extern struct rcfs_mfdesc *genmfdesc[]; - -inline struct rcfs_inode_info *RCFS_I(struct inode *inode); - -int rcfs_empty(struct dentry *); -struct inode *rcfs_get_inode(struct super_block *, int, dev_t); -int rcfs_mknod(struct inode *, struct dentry *, int, dev_t); -int _rcfs_mknod(struct inode *, struct dentry *, int , dev_t); -int rcfs_mkdir(struct inode *, struct dentry *, int); -ckrm_core_class_t *rcfs_make_core(struct dentry *, struct ckrm_core_class *); -struct dentry *rcfs_set_magf_byname(char *, void *); - -struct dentry * rcfs_create_internal(struct dentry *, struct rcfs_magf *, int); -int rcfs_delete_internal(struct dentry *); -int rcfs_create_magic(struct dentry *, struct rcfs_magf *, int); -int rcfs_clear_magic(struct dentry *); - - -extern struct super_operations rcfs_super_ops; -extern struct address_space_operations rcfs_aops; - -extern struct inode_operations rcfs_dir_inode_operations; -extern struct inode_operations rcfs_rootdir_inode_operations; -extern struct inode_operations rcfs_file_inode_operations; - - -extern struct file_operations target_fileops; -extern struct file_operations shares_fileops; -extern struct file_operations stats_fileops; -extern struct file_operations config_fileops; -extern struct file_operations members_fileops; -extern struct file_operations rcfs_file_operations; - -// Callbacks into rcfs from ckrm - -typedef struct rcfs_functions { - int (* mkroot)(struct rcfs_magf *,int, struct dentry **); - int (* rmroot)(struct dentry *); - int (* register_classtype)(ckrm_classtype_t *); - int (* deregister_classtype)(ckrm_classtype_t *); -} rcfs_fn_t; - -int rcfs_register_classtype(ckrm_classtype_t *); -int rcfs_deregister_classtype(ckrm_classtype_t *); -int rcfs_mkroot(struct rcfs_magf *, int , struct dentry **); -int rcfs_rmroot(struct dentry *); - -#define RCFS_ROOT "/rcfs" // Hubertus .. we should use the mount point instead of hardcoded -extern struct dentry *rcfs_rootde; - - -#endif /* _LINUX_RCFS_H */ diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h deleted file mode 100644 index 2c52874ab..000000000 --- a/include/linux/relayfs_fs.h +++ /dev/null @@ -1,686 +0,0 @@ -/* - * linux/include/linux/relayfs_fs.h - * - * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp - * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) - * - * RelayFS definitions and declarations - * - * Please see Documentation/filesystems/relayfs.txt for more info. - */ - -#ifndef _LINUX_RELAYFS_FS_H -#define _LINUX_RELAYFS_FS_H - -#include -#include -#include -#include -#include -#include - -/* - * Tracks changes to rchan struct - */ -#define RELAYFS_CHANNEL_VERSION 1 - -/* - * Maximum number of simultaneously open channels - */ -#define RELAY_MAX_CHANNELS 256 - -/* - * Relay properties - */ -#define RELAY_MIN_BUFS 2 -#define RELAY_MIN_BUFSIZE 4096 -#define RELAY_MAX_BUFS 256 -#define RELAY_MAX_BUF_SIZE 0x1000000 -#define RELAY_MAX_TOTAL_BUF_SIZE 0x8000000 - -/* - * Lockless scheme utility macros - */ -#define RELAY_MAX_BUFNO(bufno_bits) (1UL << (bufno_bits)) -#define RELAY_BUF_SIZE(offset_bits) (1UL << (offset_bits)) -#define RELAY_BUF_OFFSET_MASK(offset_bits) (RELAY_BUF_SIZE(offset_bits) - 1) -#define RELAY_BUFNO_GET(index, offset_bits) ((index) >> (offset_bits)) -#define RELAY_BUF_OFFSET_GET(index, mask) ((index) & (mask)) -#define RELAY_BUF_OFFSET_CLEAR(index, mask) ((index) & ~(mask)) - -/* - * Flags returned by relay_reserve() - */ -#define RELAY_BUFFER_SWITCH_NONE 0x0 -#define RELAY_WRITE_DISCARD_NONE 0x0 -#define RELAY_BUFFER_SWITCH 0x1 -#define RELAY_WRITE_DISCARD 0x2 -#define RELAY_WRITE_TOO_LONG 0x4 - -/* - * Relay attribute flags - */ -#define RELAY_DELIVERY_BULK 0x1 -#define RELAY_DELIVERY_PACKET 0x2 -#define RELAY_SCHEME_LOCKLESS 0x4 -#define RELAY_SCHEME_LOCKING 0x8 -#define RELAY_SCHEME_ANY 0xC -#define RELAY_TIMESTAMP_TSC 0x10 -#define RELAY_TIMESTAMP_GETTIMEOFDAY 0x20 -#define RELAY_TIMESTAMP_ANY 0x30 -#define RELAY_USAGE_SMP 0x40 -#define RELAY_USAGE_GLOBAL 0x80 -#define RELAY_MODE_CONTINUOUS 0x100 -#define RELAY_MODE_NO_OVERWRITE 0x200 - -/* - * Flags for needs_resize() callback - */ -#define RELAY_RESIZE_NONE 0x0 -#define RELAY_RESIZE_EXPAND 0x1 -#define RELAY_RESIZE_SHRINK 0x2 -#define RELAY_RESIZE_REPLACE 0x4 -#define RELAY_RESIZE_REPLACED 0x8 - -/* - * Values for fileop_notify() callback - */ -enum relay_fileop -{ - RELAY_FILE_OPEN, - RELAY_FILE_CLOSE, - RELAY_FILE_MAP, - RELAY_FILE_UNMAP -}; - -/* - * Data structure returned by relay_info() - */ -struct rchan_info -{ - u32 flags; /* relay attribute flags for channel */ - u32 buf_size; /* channel's sub-buffer size */ - char *buf_addr; /* address of channel start */ - u32 alloc_size; /* total buffer size actually allocated */ - u32 n_bufs; /* number of sub-buffers in channel */ - u32 cur_idx; /* current write index into channel */ - u32 bufs_produced; /* current count of sub-buffers produced */ - u32 bufs_consumed; /* current count of sub-buffers consumed */ - u32 buf_id; /* buf_id of current sub-buffer */ - int buffer_complete[RELAY_MAX_BUFS]; /* boolean per sub-buffer */ - int unused_bytes[RELAY_MAX_BUFS]; /* count per sub-buffer */ -}; - -/* - * Relay channel client callbacks - */ -struct rchan_callbacks -{ - /* - * buffer_start - called at the beginning of a new sub-buffer - * @rchan_id: the channel id - * @current_write_pos: position in sub-buffer client should write to - * @buffer_id: the id of the new sub-buffer - * @start_time: the timestamp associated with the start of sub-buffer - * @start_tsc: the TSC associated with the timestamp, if using_tsc - * @using_tsc: boolean, indicates whether start_tsc is valid - * - * Return value should be the number of bytes written by the client. - * - * See Documentation/filesystems/relayfs.txt for details. - */ - int (*buffer_start) (int rchan_id, - char *current_write_pos, - u32 buffer_id, - struct timeval start_time, - u32 start_tsc, - int using_tsc); - - /* - * buffer_end - called at the end of a sub-buffer - * @rchan_id: the channel id - * @current_write_pos: position in sub-buffer of end of data - * @end_of_buffer: the position of the end of the sub-buffer - * @end_time: the timestamp associated with the end of the sub-buffer - * @end_tsc: the TSC associated with the end_time, if using_tsc - * @using_tsc: boolean, indicates whether end_tsc is valid - * - * Return value should be the number of bytes written by the client. - * - * See Documentation/filesystems/relayfs.txt for details. - */ - int (*buffer_end) (int rchan_id, - char *current_write_pos, - char *end_of_buffer, - struct timeval end_time, - u32 end_tsc, - int using_tsc); - - /* - * deliver - called when data is ready for the client - * @rchan_id: the channel id - * @from: the start of the delivered data - * @len: the length of the delivered data - * - * See Documentation/filesystems/relayfs.txt for details. - */ - void (*deliver) (int rchan_id, char *from, u32 len); - - /* - * user_deliver - called when data has been written from userspace - * @rchan_id: the channel id - * @from: the start of the delivered data - * @len: the length of the delivered data - * - * See Documentation/filesystems/relayfs.txt for details. - */ - void (*user_deliver) (int rchan_id, char *from, u32 len); - - /* - * needs_resize - called when a resizing event occurs - * @rchan_id: the channel id - * @resize_type: the type of resizing event - * @suggested_buf_size: the suggested new sub-buffer size - * @suggested_buf_size: the suggested new number of sub-buffers - * - * See Documentation/filesystems/relayfs.txt for details. - */ - void (*needs_resize)(int rchan_id, - int resize_type, - u32 suggested_buf_size, - u32 suggested_n_bufs); - - /* - * fileop_notify - called on open/close/mmap/munmap of a relayfs file - * @rchan_id: the channel id - * @filp: relayfs file pointer - * @fileop: which file operation is in progress - * - * The return value can direct the outcome of the operation. - * - * See Documentation/filesystems/relayfs.txt for details. - */ - int (*fileop_notify)(int rchan_id, - struct file *filp, - enum relay_fileop fileop); - - /* - * ioctl - called in ioctl context from userspace - * @rchan_id: the channel id - * @cmd: ioctl cmd - * @arg: ioctl cmd arg - * - * The return value is returned as the value from the ioctl call. - * - * See Documentation/filesystems/relayfs.txt for details. - */ - int (*ioctl) (int rchan_id, unsigned int cmd, unsigned long arg); -}; - -/* - * Lockless scheme-specific data - */ -struct lockless_rchan -{ - u8 bufno_bits; /* # bits used for sub-buffer id */ - u8 offset_bits; /* # bits used for offset within sub-buffer */ - u32 index; /* current index = sub-buffer id and offset */ - u32 offset_mask; /* used to obtain offset portion of index */ - u32 index_mask; /* used to mask off unused bits index */ - atomic_t fill_count[RELAY_MAX_BUFS]; /* fill count per sub-buffer */ -}; - -/* - * Locking scheme-specific data - */ -struct locking_rchan -{ - char *write_buf; /* start of write sub-buffer */ - char *write_buf_end; /* end of write sub-buffer */ - char *current_write_pos; /* current write pointer */ - char *write_limit; /* takes reserves into account */ - char *in_progress_event_pos; /* used for interrupted writes */ - u16 in_progress_event_size; /* used for interrupted writes */ - char *interrupted_pos; /* used for interrupted writes */ - u16 interrupting_size; /* used for interrupted writes */ - spinlock_t lock; /* channel lock for locking scheme */ -}; - -struct relay_ops; - -/* - * Offset resizing data structure - */ -struct resize_offset -{ - u32 ge; - u32 le; - int delta; -}; - -/* - * Relay channel data structure - */ -struct rchan -{ - u32 version; /* the version of this struct */ - char *buf; /* the channel buffer */ - union - { - struct lockless_rchan lockless; - struct locking_rchan locking; - } scheme; /* scheme-specific channel data */ - - int id; /* the channel id */ - struct rchan_callbacks *callbacks; /* client callbacks */ - u32 flags; /* relay channel attributes */ - u32 buf_id; /* current sub-buffer id */ - u32 buf_idx; /* current sub-buffer index */ - - atomic_t mapped; /* map count */ - - atomic_t suspended; /* channel suspended i.e full? */ - int half_switch; /* used internally for suspend */ - - struct timeval buf_start_time; /* current sub-buffer start time */ - u32 buf_start_tsc; /* current sub-buffer start TSC */ - - u32 buf_size; /* sub-buffer size */ - u32 alloc_size; /* total buffer size allocated */ - u32 n_bufs; /* number of sub-buffers */ - - u32 bufs_produced; /* count of sub-buffers produced */ - u32 bufs_consumed; /* count of sub-buffers consumed */ - u32 bytes_consumed; /* bytes consumed in cur sub-buffer */ - - int initialized; /* first buffer initialized? */ - int finalized; /* channel finalized? */ - - u32 start_reserve; /* reserve at start of sub-buffers */ - u32 end_reserve; /* reserve at end of sub-buffers */ - u32 rchan_start_reserve; /* additional reserve sub-buffer 0 */ - - struct dentry *dentry; /* channel file dentry */ - - wait_queue_head_t read_wait; /* VFS read wait queue */ - wait_queue_head_t write_wait; /* VFS write wait queue */ - struct work_struct wake_readers; /* reader wake-up work struct */ - struct work_struct wake_writers; /* reader wake-up work struct */ - atomic_t refcount; /* channel refcount */ - - struct relay_ops *relay_ops; /* scheme-specific channel ops */ - - int unused_bytes[RELAY_MAX_BUFS]; /* unused count per sub-buffer */ - - struct semaphore resize_sem; /* serializes alloc/repace */ - struct work_struct work; /* resize allocation work struct */ - - struct list_head open_readers; /* open readers for this channel */ - rwlock_t open_readers_lock; /* protection for open_readers list */ - - char *init_buf; /* init channel buffer, if non-NULL */ - - u32 resize_min; /* minimum resized total buffer size */ - u32 resize_max; /* maximum resized total buffer size */ - char *resize_buf; /* for autosize alloc/free */ - u32 resize_buf_size; /* resized sub-buffer size */ - u32 resize_n_bufs; /* resized number of sub-buffers */ - u32 resize_alloc_size; /* resized actual total size */ - int resizing; /* is resizing in progress? */ - int resize_err; /* resizing err code */ - int resize_failures; /* number of resize failures */ - int replace_buffer; /* is the alloced buffer ready? */ - struct resize_offset resize_offset; /* offset change */ - struct timer_list shrink_timer; /* timer used for shrinking */ - int resize_order; /* size of last resize */ - u32 expand_buf_id; /* subbuf id expand will occur at */ - - struct page **buf_page_array; /* array of current buffer pages */ - int buf_page_count; /* number of current buffer pages */ - struct page **expand_page_array;/* new pages to be inserted */ - int expand_page_count; /* number of new pages */ - struct page **shrink_page_array;/* old pages to be freed */ - int shrink_page_count; /* number of old pages */ - struct page **resize_page_array;/* will become current pages */ - int resize_page_count; /* number of resize pages */ - struct page **old_buf_page_array; /* hold for freeing */ -} ____cacheline_aligned; - -/* - * Relay channel reader struct - */ -struct rchan_reader -{ - struct list_head list; /* for list inclusion */ - struct rchan *rchan; /* the channel we're reading from */ - int auto_consume; /* does this reader auto-consume? */ - u32 bufs_consumed; /* buffers this reader has consumed */ - u32 bytes_consumed; /* bytes consumed in cur sub-buffer */ - int offset_changed; /* have channel offsets changed? */ - int vfs_reader; /* are we a VFS reader? */ - int map_reader; /* are we an mmap reader? */ - - union - { - struct file *file; - u32 f_pos; - } pos; /* current read offset */ -}; - -/* - * These help make union member access less tedious - */ -#define channel_buffer(rchan) ((rchan)->buf) -#define idx(rchan) ((rchan)->scheme.lockless.index) -#define bufno_bits(rchan) ((rchan)->scheme.lockless.bufno_bits) -#define offset_bits(rchan) ((rchan)->scheme.lockless.offset_bits) -#define offset_mask(rchan) ((rchan)->scheme.lockless.offset_mask) -#define idx_mask(rchan) ((rchan)->scheme.lockless.index_mask) -#define bulk_delivery(rchan) (((rchan)->flags & RELAY_DELIVERY_BULK) ? 1 : 0) -#define packet_delivery(rchan) (((rchan)->flags & RELAY_DELIVERY_PACKET) ? 1 : 0) -#define using_lockless(rchan) (((rchan)->flags & RELAY_SCHEME_LOCKLESS) ? 1 : 0) -#define using_locking(rchan) (((rchan)->flags & RELAY_SCHEME_LOCKING) ? 1 : 0) -#define using_tsc(rchan) (((rchan)->flags & RELAY_TIMESTAMP_TSC) ? 1 : 0) -#define using_gettimeofday(rchan) (((rchan)->flags & RELAY_TIMESTAMP_GETTIMEOFDAY) ? 1 : 0) -#define usage_smp(rchan) (((rchan)->flags & RELAY_USAGE_SMP) ? 1 : 0) -#define usage_global(rchan) (((rchan)->flags & RELAY_USAGE_GLOBAL) ? 1 : 0) -#define mode_continuous(rchan) (((rchan)->flags & RELAY_MODE_CONTINUOUS) ? 1 : 0) -#define fill_count(rchan, i) ((rchan)->scheme.lockless.fill_count[(i)]) -#define write_buf(rchan) ((rchan)->scheme.locking.write_buf) -#define read_buf(rchan) ((rchan)->scheme.locking.read_buf) -#define write_buf_end(rchan) ((rchan)->scheme.locking.write_buf_end) -#define read_buf_end(rchan) ((rchan)->scheme.locking.read_buf_end) -#define cur_write_pos(rchan) ((rchan)->scheme.locking.current_write_pos) -#define read_limit(rchan) ((rchan)->scheme.locking.read_limit) -#define write_limit(rchan) ((rchan)->scheme.locking.write_limit) -#define in_progress_event_pos(rchan) ((rchan)->scheme.locking.in_progress_event_pos) -#define in_progress_event_size(rchan) ((rchan)->scheme.locking.in_progress_event_size) -#define interrupted_pos(rchan) ((rchan)->scheme.locking.interrupted_pos) -#define interrupting_size(rchan) ((rchan)->scheme.locking.interrupting_size) -#define channel_lock(rchan) ((rchan)->scheme.locking.lock) - - -/** - * calc_time_delta - utility function for time delta calculation - * @now: current time - * @start: start time - * - * Returns the time delta produced by subtracting start time from now. - */ -static inline u32 -calc_time_delta(struct timeval *now, - struct timeval *start) -{ - return (now->tv_sec - start->tv_sec) * 1000000 - + (now->tv_usec - start->tv_usec); -} - -/** - * recalc_time_delta - utility function for time delta recalculation - * @now: current time - * @new_delta: the new time delta calculated - * @cpu: the associated CPU id - */ -static inline void -recalc_time_delta(struct timeval *now, - u32 *new_delta, - struct rchan *rchan) -{ - if (using_tsc(rchan) == 0) - *new_delta = calc_time_delta(now, &rchan->buf_start_time); -} - -/** - * have_cmpxchg - does this architecture have a cmpxchg? - * - * Returns 1 if this architecture has a cmpxchg useable by - * the lockless scheme, 0 otherwise. - */ -static inline int -have_cmpxchg(void) -{ -#if defined(__HAVE_ARCH_CMPXCHG) - return 1; -#else - return 0; -#endif -} - -/** - * relay_write_direct - write data directly into destination buffer - */ -#define relay_write_direct(DEST, SRC, SIZE) \ -do\ -{\ - memcpy(DEST, SRC, SIZE);\ - DEST += SIZE;\ -} while (0); - -/** - * relay_lock_channel - lock the relay channel if applicable - * - * This macro only affects the locking scheme. If the locking scheme - * is in use and the channel usage is SMP, does a local_irq_save. If the - * locking sheme is in use and the channel usage is GLOBAL, uses - * spin_lock_irqsave. FLAGS is initialized to 0 since we know that - * it is being initialized prior to use and we avoid the compiler warning. - */ -#define relay_lock_channel(RCHAN, FLAGS) \ -do\ -{\ - FLAGS = 0;\ - if (using_locking(RCHAN)) {\ - if (usage_smp(RCHAN)) {\ - local_irq_save(FLAGS); \ - } else {\ - spin_lock_irqsave(&(RCHAN)->scheme.locking.lock, FLAGS); \ - }\ - }\ -} while (0); - -/** - * relay_unlock_channel - unlock the relay channel if applicable - * - * This macro only affects the locking scheme. See relay_lock_channel. - */ -#define relay_unlock_channel(RCHAN, FLAGS) \ -do\ -{\ - if (using_locking(RCHAN)) {\ - if (usage_smp(RCHAN)) {\ - local_irq_restore(FLAGS); \ - } else {\ - spin_unlock_irqrestore(&(RCHAN)->scheme.locking.lock, FLAGS); \ - }\ - }\ -} while (0); - -/* - * Define cmpxchg if we don't have it - */ -#ifndef __HAVE_ARCH_CMPXCHG -#define cmpxchg(p,o,n) 0 -#endif - -/* - * High-level relayfs kernel API, fs/relayfs/relay.c - */ -extern int -relay_open(const char *chanpath, - int bufsize, - int nbufs, - u32 flags, - struct rchan_callbacks *channel_callbacks, - u32 start_reserve, - u32 end_reserve, - u32 rchan_start_reserve, - u32 resize_min, - u32 resize_max, - int mode, - char *init_buf, - u32 init_buf_size); - -extern int -relay_close(int rchan_id); - -extern int -relay_write(int rchan_id, - const void *data_ptr, - size_t count, - int td_offset, - void **wrote_pos); - -extern ssize_t -relay_read(struct rchan_reader *reader, - char *buf, - size_t count, - int wait, - u32 *actual_read_offset); - -extern int -relay_discard_init_buf(int rchan_id); - -extern struct rchan_reader * -add_rchan_reader(int rchan_id, int autoconsume); - -extern int -remove_rchan_reader(struct rchan_reader *reader); - -extern struct rchan_reader * -add_map_reader(int rchan_id); - -extern int -remove_map_reader(struct rchan_reader *reader); - -extern int -relay_info(int rchan_id, struct rchan_info *rchan_info); - -extern void -relay_buffers_consumed(struct rchan_reader *reader, u32 buffers_consumed); - -extern void -relay_bytes_consumed(struct rchan_reader *reader, u32 bytes_consumed, u32 read_offset); - -extern ssize_t -relay_bytes_avail(struct rchan_reader *reader); - -extern int -relay_realloc_buffer(int rchan_id, u32 new_nbufs, int in_background); - -extern int -relay_replace_buffer(int rchan_id); - -extern int -rchan_empty(struct rchan_reader *reader); - -extern int -rchan_full(struct rchan_reader *reader); - -extern void -update_readers_consumed(struct rchan *rchan, u32 bufs_consumed, u32 bytes_consumed); - -extern int -__relay_mmap_buffer(struct rchan *rchan, struct vm_area_struct *vma); - -extern struct rchan_reader * -__add_rchan_reader(struct rchan *rchan, struct file *filp, int auto_consume, int map_reader); - -extern void -__remove_rchan_reader(struct rchan_reader *reader); - -/* - * Low-level relayfs kernel API, fs/relayfs/relay.c - */ -extern struct rchan * -rchan_get(int rchan_id); - -extern void -rchan_put(struct rchan *rchan); - -extern char * -relay_reserve(struct rchan *rchan, - u32 data_len, - struct timeval *time_stamp, - u32 *time_delta, - int *errcode, - int *interrupting); - -extern void -relay_commit(struct rchan *rchan, - char *from, - u32 len, - int reserve_code, - int interrupting); - -extern u32 -relay_get_offset(struct rchan *rchan, u32 *max_offset); - -extern int -relay_reset(int rchan_id); - -/* - * VFS functions, fs/relayfs/inode.c - */ -extern int -relayfs_create_dir(const char *name, - struct dentry *parent, - struct dentry **dentry); - -extern int -relayfs_create_file(const char * name, - struct dentry *parent, - struct dentry **dentry, - void * data, - int mode); - -extern int -relayfs_remove_file(struct dentry *dentry); - -extern int -reset_index(struct rchan *rchan, u32 old_index); - - -/* - * klog functions, fs/relayfs/klog.c - */ -extern int -create_klog_channel(void); - -extern int -remove_klog_channel(void); - -/* - * Scheme-specific channel ops - */ -struct relay_ops -{ - char * (*reserve) (struct rchan *rchan, - u32 slot_len, - struct timeval *time_stamp, - u32 *tsc, - int * errcode, - int * interrupting); - - void (*commit) (struct rchan *rchan, - char *from, - u32 len, - int deliver, - int interrupting); - - u32 (*get_offset) (struct rchan *rchan, - u32 *max_offset); - - void (*resume) (struct rchan *rchan); - void (*finalize) (struct rchan *rchan); - void (*reset) (struct rchan *rchan, - int init); - int (*reset_index) (struct rchan *rchan, - u32 old_index); -}; - -#endif /* _LINUX_RELAYFS_FS_H */ - - - - - diff --git a/include/linux/taskdelays.h b/include/linux/taskdelays.h deleted file mode 100644 index 698b23b61..000000000 --- a/include/linux/taskdelays.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _LINUX_TASKDELAYS_H -#define _LINUX_TASKDELAYS_H - -#include - -struct task_delay_info { -#ifdef CONFIG_DELAY_ACCT - /* delay statistics in usecs */ - unsigned long runs; - unsigned long waitcpu_total; - unsigned long runcpu_total; - unsigned long iowait_total; - unsigned long mem_iowait_total; - unsigned long num_iowaits; - unsigned long num_memwaits; -#endif -}; - -#endif // _LINUX_TASKDELAYS_H - diff --git a/include/video/gbe.h b/include/video/gbe.h deleted file mode 100644 index ad510284f..000000000 --- a/include/video/gbe.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * include/video/gbe.h -- SGI GBE (Graphics Back End) - * - * Copyright (C) 1999 Silicon Graphics, Inc. (Jeffrey Newquist) - * - * This file is subject to the terms and conditions of the GNU General Public - * License version 2 as published by the Free Software Foundation. - */ - -#ifndef __GBE_H__ -#define __GBE_H__ - -struct sgi_gbe { - volatile uint32_t ctrlstat; /* general control */ - volatile uint32_t dotclock; /* dot clock PLL control */ - volatile uint32_t i2c; /* crt I2C control */ - volatile uint32_t sysclk; /* system clock PLL control */ - volatile uint32_t i2cfp; /* flat panel I2C control */ - volatile uint32_t id; /* device id/chip revision */ - volatile uint32_t config; /* power on configuration [1] */ - volatile uint32_t bist; /* internal bist status [1] */ - uint32_t _pad0[0x010000/4 - 8]; - volatile uint32_t vt_xy; /* current dot coords */ - volatile uint32_t vt_xymax; /* maximum dot coords */ - volatile uint32_t vt_vsync; /* vsync on/off */ - volatile uint32_t vt_hsync; /* hsync on/off */ - volatile uint32_t vt_vblank; /* vblank on/off */ - volatile uint32_t vt_hblank; /* hblank on/off */ - volatile uint32_t vt_flags; /* polarity of vt signals */ - volatile uint32_t vt_f2rf_lock; /* f2rf & framelck y coord */ - volatile uint32_t vt_intr01; /* intr 0,1 y coords */ - volatile uint32_t vt_intr23; /* intr 2,3 y coords */ - volatile uint32_t fp_hdrv; /* flat panel hdrv on/off */ - volatile uint32_t fp_vdrv; /* flat panel vdrv on/off */ - volatile uint32_t fp_de; /* flat panel de on/off */ - volatile uint32_t vt_hpixen; /* intrnl horiz pixel on/off */ - volatile uint32_t vt_vpixen; /* intrnl vert pixel on/off */ - volatile uint32_t vt_hcmap; /* cmap write (horiz) */ - volatile uint32_t vt_vcmap; /* cmap write (vert) */ - volatile uint32_t did_start_xy; /* eol/f did/xy reset val */ - volatile uint32_t crs_start_xy; /* eol/f crs/xy reset val */ - volatile uint32_t vc_start_xy; /* eol/f vc/xy reset val */ - uint32_t _pad1[0xffb0/4]; - volatile uint32_t ovr_width_tile;/*overlay plane ctrl 0 */ - volatile uint32_t ovr_inhwctrl; /* overlay plane ctrl 1 */ - volatile uint32_t ovr_control; /* overlay plane ctrl 1 */ - uint32_t _pad2[0xfff4/4]; - volatile uint32_t frm_size_tile;/* normal plane ctrl 0 */ - volatile uint32_t frm_size_pixel;/*normal plane ctrl 1 */ - volatile uint32_t frm_inhwctrl; /* normal plane ctrl 2 */ - volatile uint32_t frm_control; /* normal plane ctrl 3 */ - uint32_t _pad3[0xfff0/4]; - volatile uint32_t did_inhwctrl; /* DID control */ - volatile uint32_t did_control; /* DID shadow */ - uint32_t _pad4[0x7ff8/4]; - volatile uint32_t mode_regs[32];/* WID table */ - uint32_t _pad5[0x7f80/4]; - volatile uint32_t cmap[6144]; /* color map */ - uint32_t _pad6[0x2000/4]; - volatile uint32_t cm_fifo; /* color map fifo status */ - uint32_t _pad7[0x7ffc/4]; - volatile uint32_t gmap[256]; /* gamma map */ - uint32_t _pad8[0x7c00/4]; - volatile uint32_t gmap10[1024]; /* gamma map */ - uint32_t _pad9[0x7000/4]; - volatile uint32_t crs_pos; /* cusror control 0 */ - volatile uint32_t crs_ctl; /* cusror control 1 */ - volatile uint32_t crs_cmap[3]; /* crs cmap */ - uint32_t _pad10[0x7fec/4]; - volatile uint32_t crs_glyph[64];/* crs glyph */ - uint32_t _pad11[0x7f00/4]; - volatile uint32_t vc_0; /* video capture crtl 0 */ - volatile uint32_t vc_1; /* video capture crtl 1 */ - volatile uint32_t vc_2; /* video capture crtl 2 */ - volatile uint32_t vc_3; /* video capture crtl 3 */ - volatile uint32_t vc_4; /* video capture crtl 4 */ - volatile uint32_t vc_5; /* video capture crtl 5 */ - volatile uint32_t vc_6; /* video capture crtl 6 */ - volatile uint32_t vc_7; /* video capture crtl 7 */ - volatile uint32_t vc_8; /* video capture crtl 8 */ -}; - -#define MASK(msb, lsb) \ - ( (((u32)1<<((msb)-(lsb)+1))-1) << (lsb) ) -#define GET(v, msb, lsb) \ - ( ((u32)(v) & MASK(msb,lsb)) >> (lsb) ) -#define SET(v, f, msb, lsb) \ - ( (v) = ((v)&~MASK(msb,lsb)) | (( (u32)(f)<<(lsb) ) & MASK(msb,lsb)) ) - -#define GET_GBE_FIELD(reg, field, v) \ - GET((v), GBE_##reg##_##field##_MSB, GBE_##reg##_##field##_LSB) -#define SET_GBE_FIELD(reg, field, v, f) \ - SET((v), (f), GBE_##reg##_##field##_MSB, GBE_##reg##_##field##_LSB) - -/* - * Bit mask information - */ -#define GBE_CTRLSTAT_CHIPID_MSB 3 -#define GBE_CTRLSTAT_CHIPID_LSB 0 -#define GBE_CTRLSTAT_SENSE_N_MSB 4 -#define GBE_CTRLSTAT_SENSE_N_LSB 4 -#define GBE_CTRLSTAT_PCLKSEL_MSB 29 -#define GBE_CTRLSTAT_PCLKSEL_LSB 28 - -#define GBE_DOTCLK_M_MSB 7 -#define GBE_DOTCLK_M_LSB 0 -#define GBE_DOTCLK_N_MSB 13 -#define GBE_DOTCLK_N_LSB 8 -#define GBE_DOTCLK_P_MSB 15 -#define GBE_DOTCLK_P_LSB 14 -#define GBE_DOTCLK_RUN_MSB 20 -#define GBE_DOTCLK_RUN_LSB 20 - -#define GBE_VT_XY_Y_MSB 23 -#define GBE_VT_XY_Y_LSB 12 -#define GBE_VT_XY_X_MSB 11 -#define GBE_VT_XY_X_LSB 0 -#define GBE_VT_XY_FREEZE_MSB 31 -#define GBE_VT_XY_FREEZE_LSB 31 - -#define GBE_FP_VDRV_ON_MSB 23 -#define GBE_FP_VDRV_ON_LSB 12 -#define GBE_FP_VDRV_OFF_MSB 11 -#define GBE_FP_VDRV_OFF_LSB 0 - -#define GBE_FP_HDRV_ON_MSB 23 -#define GBE_FP_HDRV_ON_LSB 12 -#define GBE_FP_HDRV_OFF_MSB 11 -#define GBE_FP_HDRV_OFF_LSB 0 - -#define GBE_FP_DE_ON_MSB 23 -#define GBE_FP_DE_ON_LSB 12 -#define GBE_FP_DE_OFF_MSB 11 -#define GBE_FP_DE_OFF_LSB 0 - -#define GBE_VT_VSYNC_VSYNC_ON_MSB 23 -#define GBE_VT_VSYNC_VSYNC_ON_LSB 12 -#define GBE_VT_VSYNC_VSYNC_OFF_MSB 11 -#define GBE_VT_VSYNC_VSYNC_OFF_LSB 0 - -#define GBE_VT_HSYNC_HSYNC_ON_MSB 23 -#define GBE_VT_HSYNC_HSYNC_ON_LSB 12 -#define GBE_VT_HSYNC_HSYNC_OFF_MSB 11 -#define GBE_VT_HSYNC_HSYNC_OFF_LSB 0 - -#define GBE_VT_VBLANK_VBLANK_ON_MSB 23 -#define GBE_VT_VBLANK_VBLANK_ON_LSB 12 -#define GBE_VT_VBLANK_VBLANK_OFF_MSB 11 -#define GBE_VT_VBLANK_VBLANK_OFF_LSB 0 - -#define GBE_VT_HBLANK_HBLANK_ON_MSB 23 -#define GBE_VT_HBLANK_HBLANK_ON_LSB 12 -#define GBE_VT_HBLANK_HBLANK_OFF_MSB 11 -#define GBE_VT_HBLANK_HBLANK_OFF_LSB 0 - -#define GBE_VT_FLAGS_F2RF_HIGH_MSB 6 -#define GBE_VT_FLAGS_F2RF_HIGH_LSB 6 -#define GBE_VT_FLAGS_SYNC_LOW_MSB 5 -#define GBE_VT_FLAGS_SYNC_LOW_LSB 5 -#define GBE_VT_FLAGS_SYNC_HIGH_MSB 4 -#define GBE_VT_FLAGS_SYNC_HIGH_LSB 4 -#define GBE_VT_FLAGS_HDRV_LOW_MSB 3 -#define GBE_VT_FLAGS_HDRV_LOW_LSB 3 -#define GBE_VT_FLAGS_HDRV_INVERT_MSB 2 -#define GBE_VT_FLAGS_HDRV_INVERT_LSB 2 -#define GBE_VT_FLAGS_VDRV_LOW_MSB 1 -#define GBE_VT_FLAGS_VDRV_LOW_LSB 1 -#define GBE_VT_FLAGS_VDRV_INVERT_MSB 0 -#define GBE_VT_FLAGS_VDRV_INVERT_LSB 0 - -#define GBE_VT_VCMAP_VCMAP_ON_MSB 23 -#define GBE_VT_VCMAP_VCMAP_ON_LSB 12 -#define GBE_VT_VCMAP_VCMAP_OFF_MSB 11 -#define GBE_VT_VCMAP_VCMAP_OFF_LSB 0 - -#define GBE_VT_HCMAP_HCMAP_ON_MSB 23 -#define GBE_VT_HCMAP_HCMAP_ON_LSB 12 -#define GBE_VT_HCMAP_HCMAP_OFF_MSB 11 -#define GBE_VT_HCMAP_HCMAP_OFF_LSB 0 - -#define GBE_VT_XYMAX_MAXX_MSB 11 -#define GBE_VT_XYMAX_MAXX_LSB 0 -#define GBE_VT_XYMAX_MAXY_MSB 23 -#define GBE_VT_XYMAX_MAXY_LSB 12 - -#define GBE_VT_HPIXEN_HPIXEN_ON_MSB 23 -#define GBE_VT_HPIXEN_HPIXEN_ON_LSB 12 -#define GBE_VT_HPIXEN_HPIXEN_OFF_MSB 11 -#define GBE_VT_HPIXEN_HPIXEN_OFF_LSB 0 - -#define GBE_VT_VPIXEN_VPIXEN_ON_MSB 23 -#define GBE_VT_VPIXEN_VPIXEN_ON_LSB 12 -#define GBE_VT_VPIXEN_VPIXEN_OFF_MSB 11 -#define GBE_VT_VPIXEN_VPIXEN_OFF_LSB 0 - -#define GBE_OVR_CONTROL_OVR_DMA_ENABLE_MSB 0 -#define GBE_OVR_CONTROL_OVR_DMA_ENABLE_LSB 0 - -#define GBE_OVR_INHWCTRL_OVR_DMA_ENABLE_MSB 0 -#define GBE_OVR_INHWCTRL_OVR_DMA_ENABLE_LSB 0 - -#define GBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_MSB 13 -#define GBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_LSB 13 - -#define GBE_FRM_CONTROL_FRM_DMA_ENABLE_MSB 0 -#define GBE_FRM_CONTROL_FRM_DMA_ENABLE_LSB 0 -#define GBE_FRM_CONTROL_FRM_TILE_PTR_MSB 31 -#define GBE_FRM_CONTROL_FRM_TILE_PTR_LSB 9 -#define GBE_FRM_CONTROL_FRM_LINEAR_MSB 1 -#define GBE_FRM_CONTROL_FRM_LINEAR_LSB 1 - -#define GBE_FRM_INHWCTRL_FRM_DMA_ENABLE_MSB 0 -#define GBE_FRM_INHWCTRL_FRM_DMA_ENABLE_LSB 0 - -#define GBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_MSB 12 -#define GBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_LSB 5 -#define GBE_FRM_SIZE_TILE_FRM_RHS_MSB 4 -#define GBE_FRM_SIZE_TILE_FRM_RHS_LSB 0 -#define GBE_FRM_SIZE_TILE_FRM_DEPTH_MSB 14 -#define GBE_FRM_SIZE_TILE_FRM_DEPTH_LSB 13 -#define GBE_FRM_SIZE_TILE_FRM_FIFO_RESET_MSB 15 -#define GBE_FRM_SIZE_TILE_FRM_FIFO_RESET_LSB 15 - -#define GBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_MSB 31 -#define GBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_LSB 16 - -#define GBE_DID_CONTROL_DID_DMA_ENABLE_MSB 0 -#define GBE_DID_CONTROL_DID_DMA_ENABLE_LSB 0 -#define GBE_DID_INHWCTRL_DID_DMA_ENABLE_MSB 0 -#define GBE_DID_INHWCTRL_DID_DMA_ENABLE_LSB 0 - -#define GBE_DID_START_XY_DID_STARTY_MSB 23 -#define GBE_DID_START_XY_DID_STARTY_LSB 12 -#define GBE_DID_START_XY_DID_STARTX_MSB 11 -#define GBE_DID_START_XY_DID_STARTX_LSB 0 - -#define GBE_CRS_START_XY_CRS_STARTY_MSB 23 -#define GBE_CRS_START_XY_CRS_STARTY_LSB 12 -#define GBE_CRS_START_XY_CRS_STARTX_MSB 11 -#define GBE_CRS_START_XY_CRS_STARTX_LSB 0 - -#define GBE_WID_AUX_MSB 12 -#define GBE_WID_AUX_LSB 11 -#define GBE_WID_GAMMA_MSB 10 -#define GBE_WID_GAMMA_LSB 10 -#define GBE_WID_CM_MSB 9 -#define GBE_WID_CM_LSB 5 -#define GBE_WID_TYP_MSB 4 -#define GBE_WID_TYP_LSB 2 -#define GBE_WID_BUF_MSB 1 -#define GBE_WID_BUF_LSB 0 - -#define GBE_VC_START_XY_VC_STARTY_MSB 23 -#define GBE_VC_START_XY_VC_STARTY_LSB 12 -#define GBE_VC_START_XY_VC_STARTX_MSB 11 -#define GBE_VC_START_XY_VC_STARTX_LSB 0 - -/* Constants */ - -#define GBE_FRM_DEPTH_8 0 -#define GBE_FRM_DEPTH_16 1 -#define GBE_FRM_DEPTH_32 2 - -#define GBE_CMODE_I8 0 -#define GBE_CMODE_I12 1 -#define GBE_CMODE_RG3B2 2 -#define GBE_CMODE_RGB4 3 -#define GBE_CMODE_ARGB5 4 -#define GBE_CMODE_RGB8 5 -#define GBE_CMODE_RGBA5 6 -#define GBE_CMODE_RGB10 7 - -#define GBE_BMODE_BOTH 3 - -#define GBE_CRS_MAGIC 54 -#define GBE_PIXEN_MAGIC_ON 19 -#define GBE_PIXEN_MAGIC_OFF 2 - -#define GBE_TLB_SIZE 128 - -/* [1] - only GBE revision 2 and later */ - -/* - * Video Timing Data Structure - */ - -struct gbe_timing_info { - int flags; - short width; /* Monitor resolution */ - short height; - int fields_sec; /* fields/sec (Hz -3 dec. places */ - int cfreq; /* pixel clock frequency (MHz -3 dec. places) */ - short htotal; /* Horizontal total pixels */ - short hblank_start; /* Horizontal blank start */ - short hblank_end; /* Horizontal blank end */ - short hsync_start; /* Horizontal sync start */ - short hsync_end; /* Horizontal sync end */ - short vtotal; /* Vertical total lines */ - short vblank_start; /* Vertical blank start */ - short vblank_end; /* Vertical blank end */ - short vsync_start; /* Vertical sync start */ - short vsync_end; /* Vertical sync end */ - short pll_m; /* PLL M parameter */ - short pll_n; /* PLL P parameter */ - short pll_p; /* PLL N parameter */ -}; - -/* Defines for gbe_vof_info_t flags */ - -#define GBE_VOF_UNKNOWNMON 1 -#define GBE_VOF_STEREO 2 -#define GBE_VOF_DO_GENSYNC 4 /* enable incoming sync */ -#define GBE_VOF_SYNC_ON_GREEN 8 /* sync on green */ -#define GBE_VOF_FLATPANEL 0x1000 /* FLATPANEL Timing */ -#define GBE_VOF_MAGICKEY 0x2000 /* Backdoor key */ - -#endif /* ! __GBE_H__ */ diff --git a/kernel/ckrm/Makefile b/kernel/ckrm/Makefile deleted file mode 100644 index 58b9aad74..000000000 --- a/kernel/ckrm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile for CKRM -# - -ifeq ($(CONFIG_CKRM),y) - obj-y = ckrm.o ckrmutils.o -endif - -obj-$(CONFIG_CKRM_TYPE_TASKCLASS) += ckrm_tc.o -obj-$(CONFIG_CKRM_RES_NUMTASKS) += ckrm_tasks.o - -obj-$(CONFIG_CKRM_TYPE_SOCKETCLASS) += ckrm_sockc.o -obj-$(CONFIG_CKRM_RES_LISTENAQ) += ckrm_listenaq.o - diff --git a/kernel/ckrm/ckrm.c b/kernel/ckrm/ckrm.c deleted file mode 100644 index 43d14a8a9..000000000 --- a/kernel/ckrm/ckrm.c +++ /dev/null @@ -1,1009 +0,0 @@ -/* ckrm.c - Class-based Kernel Resource Management (CKRM) - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003, 2004 - * (C) Shailabh Nagar, IBM Corp. 2003, 2004 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * (C) Vivek Kashyap, IBM Corp. 2004 - * - * - * Provides kernel API of CKRM for in-kernel,per-resource controllers - * (one each for cpu, memory, io, network) and callbacks for - * classification modules. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 28 Aug 2003 - * Created. - * 06 Nov 2003 - * Made modifications to suit the new RBCE module. - * 10 Nov 2003 - * Fixed a bug in fork and exit callbacks. Added callbacks_active and - * surrounding logic. Added task paramter for all CE callbacks. - * 23 Mar 2004 - * moved to referenced counted class objects and correct locking - * 19 Apr 2004 - * Integrated ckrm hooks, classtypes, ... - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -rwlock_t ckrm_class_lock = RW_LOCK_UNLOCKED; // protect classlists - -struct rcfs_functions rcfs_fn ; -EXPORT_SYMBOL(rcfs_fn); - - -/************************************************************************** - * Helper Functions * - **************************************************************************/ - -/* - * Return TRUE if the given core class pointer is valid. - */ - -/* - * Return TRUE if the given resource is registered. - */ -inline unsigned int -is_res_regd(struct ckrm_classtype *clstype, int resid) -{ - return ( (resid>=0) && (resid < clstype->max_resid) && - test_bit(resid, &clstype->bit_res_ctlrs) - ); -} - -struct ckrm_res_ctlr* -ckrm_resctlr_lookup(struct ckrm_classtype *clstype, const char *resname) -{ - int resid = -1; - - for (resid=0; resid < clstype->max_resid; resid++) { - if (test_bit(resid, &clstype->bit_res_ctlrs)) { - struct ckrm_res_ctlr *rctrl = clstype->res_ctlrs[resid]; - if (!strncmp(resname, rctrl->res_name,CKRM_MAX_RES_NAME)) - return rctrl; - } - } - return NULL; -} -EXPORT_SYMBOL(ckrm_resctlr_lookup); - -/* given a classname return the class handle and its classtype*/ -void * -ckrm_classobj(char *classname, int *classTypeID) -{ - int i; - - *classTypeID = -1; - if (!classname || !*classname) { - return NULL; - } - - read_lock(&ckrm_class_lock); - for ( i=0 ; iclasses, clslist) { - if (core->name && !strcmp(core->name, classname)) { - // FIXME: should grep reference.. - read_unlock(&ckrm_class_lock); - *classTypeID = ctype->typeID; - return core; - } - } - } - read_unlock(&ckrm_class_lock); - return NULL; -} - -EXPORT_SYMBOL(is_res_regd); -EXPORT_SYMBOL(ckrm_classobj); - -/************************************************************************** - * Internal Functions/macros * - **************************************************************************/ - -static inline void -set_callbacks_active(struct ckrm_classtype *ctype) -{ - ctype->ce_cb_active = ((atomic_read(&ctype->ce_nr_users) > 0) && - (ctype->ce_callbacks.always_callback || (ctype->num_classes > 1))); -} - -int -ckrm_validate_and_grab_core(struct ckrm_core_class *core) -{ - int rc = 0; - read_lock(&ckrm_class_lock); - if (likely(ckrm_is_core_valid(core))) { - ckrm_core_grab(core); - rc = 1; - } - read_unlock(&ckrm_class_lock); - return rc; -} - -/**************************************************************************** - * Interfaces for classification engine * - ****************************************************************************/ - -/* - * Registering a callback structure by the classification engine. - * - * Returns typeId of class on success -errno for failure. - */ -int -ckrm_register_engine(const char *typename, ckrm_eng_callback_t *ecbs) -{ - struct ckrm_classtype *ctype; - - ctype = ckrm_find_classtype_by_name(typename); - if (ctype == NULL) - return (-ENOENT); - - ce_protect(ctype); - if (atomic_read(&ctype->ce_nr_users) != 1) { - // Some engine is acive, deregister it first. - ce_release(ctype); - return (-EBUSY); - } - - /* we require that either classify and class_delete are set (due to object reference) - * or that notify is set (in case no real classification is supported only notification - * also require that the function pointer be set the momement the mask is non-null - */ - if ( ! (((ecbs->classify) && (ecbs->class_delete)) || (ecbs->notify)) || - (ecbs->c_interest && ecbs->classify == NULL) || - (ecbs->n_interest && ecbs->notify == NULL) ) - { - ce_release(ctype); - return (-EINVAL); - } - - - /* Is any other engine registered for this classtype ? */ - if (ctype->ce_regd) { - ce_release(ctype); - return (-EINVAL); - } - - ctype->ce_regd = 1; - ctype->ce_callbacks = *ecbs; - set_callbacks_active(ctype); - if (ctype->ce_callbacks.class_add) - (*ctype->ce_callbacks.class_add)(ctype->default_class->name,ctype->default_class); - return ctype->typeID; -} - -/* - * Unregistering a callback structure by the classification engine. - * - * Returns 0 on success -errno for failure. - */ -int -ckrm_unregister_engine(const char *typename) -{ - struct ckrm_classtype *ctype; - - ctype = ckrm_find_classtype_by_name(typename); - if (ctype == NULL) - return (-ENOENT); - - ctype->ce_cb_active = 0; - - if (atomic_dec_and_test(&ctype->ce_nr_users) != 1) { - // Somebody is currently using the engine, cannot deregister. - atomic_inc(&ctype->ce_nr_users); - return (-EBUSY); - } - - ctype->ce_regd = 0; - memset(&ctype->ce_callbacks, 0, sizeof(ckrm_eng_callback_t)); - return 0; -} - -/**************************************************************************** - * Interfaces to manipulate class (core or resource) hierarchies - ****************************************************************************/ - -/* - */ -static void -ckrm_add_child(struct ckrm_core_class *parent, struct ckrm_core_class *child) -{ - struct ckrm_hnode *cnode = &child->hnode; - - if (!ckrm_is_core_valid(child)) { - printk(KERN_ERR "Invalid child %p given in ckrm_add_child\n", child); - return; - } - - class_lock(child); - INIT_LIST_HEAD(&cnode->children); - INIT_LIST_HEAD(&cnode->siblings); - - if (parent) { - struct ckrm_hnode *pnode; - - if (!ckrm_is_core_valid(parent)) { - printk(KERN_ERR "Invalid parent %p given in ckrm_add_child\n", - parent); - parent = NULL; - } else { - pnode = &parent->hnode; - write_lock(&parent->hnode_rwlock); - list_add(&cnode->siblings, &pnode->children); - write_unlock(&parent->hnode_rwlock); - } - } - cnode->parent = parent; - class_unlock(child); - return; -} - -/* - */ -static int -ckrm_remove_child(struct ckrm_core_class *child) -{ - struct ckrm_hnode *cnode, *pnode; - struct ckrm_core_class *parent; - - if (!ckrm_is_core_valid(child)) { - printk(KERN_ERR "Invalid child %p given in ckrm_remove_child\n", child); - return 0; - } - - cnode = &child->hnode; - parent = cnode->parent; - if (!ckrm_is_core_valid(parent)) { - printk(KERN_ERR "Invalid parent %p in ckrm_remove_child\n", parent); - return 0; - } - - pnode = &parent->hnode; - - class_lock(child); - /* ensure that the node does not have children */ - if (!list_empty(&cnode->children)) { - class_unlock(child); - return 0; - } - write_lock(&parent->hnode_rwlock); - list_del(&cnode->siblings); - write_unlock(&parent->hnode_rwlock); - cnode->parent = NULL; - class_unlock(child); - return 1; -} - -void -ckrm_lock_hier(struct ckrm_core_class *parent) -{ - if (ckrm_is_core_valid(parent)) { - read_lock(&parent->hnode_rwlock); - } -} - -void -ckrm_unlock_hier(struct ckrm_core_class *parent) -{ - if (ckrm_is_core_valid(parent)) { - read_unlock(&parent->hnode_rwlock); - } -} - -/* - * hnode_rwlock of the parent core class must held in read mode. - * external callers should 've called ckrm_lock_hier before calling this - * function. - */ -#define hnode_2_core(ptr) ((ptr) ? container_of(ptr, struct ckrm_core_class, hnode) : NULL) - -struct ckrm_core_class * -ckrm_get_next_child(struct ckrm_core_class *parent, - struct ckrm_core_class *child) -{ - struct list_head *cnode; - struct ckrm_hnode *next_cnode; - struct ckrm_core_class *next_childcore; - - if (!ckrm_is_core_valid(parent)) { - printk(KERN_ERR "Invalid parent %p in ckrm_get_next_child\n", parent); - return NULL; - } - if (list_empty(&parent->hnode.children)) { - return NULL; - } - - if (child) { - if (!ckrm_is_core_valid(child)) { - printk(KERN_ERR "Invalid child %p in ckrm_get_next_child\n", child); - return NULL; - } - cnode = child->hnode.siblings.next; - } else { - cnode = parent->hnode.children.next; - } - - if (cnode == &parent->hnode.children) { // back at the anchor - return NULL; - } - - next_cnode = container_of(cnode, struct ckrm_hnode, siblings); - next_childcore = hnode_2_core(next_cnode); - - if (!ckrm_is_core_valid(next_childcore)) { - printk(KERN_ERR "Invalid next child %p in ckrm_get_next_child\n", - next_childcore); - return NULL; - } - return next_childcore; -} - -EXPORT_SYMBOL(ckrm_lock_hier); -EXPORT_SYMBOL(ckrm_unlock_hier); -EXPORT_SYMBOL(ckrm_get_next_child); - -static void -ckrm_alloc_res_class(struct ckrm_core_class *core, - struct ckrm_core_class *parent, - int resid) -{ - - struct ckrm_classtype *clstype; - - /* - * Allocate a resource class only if the resource controller has - * registered with core and the engine requests for the class. - */ - - if (!ckrm_is_core_valid(core)) - return ; - - clstype = core->classtype; - core->res_class[resid] = NULL; - - if (test_bit(resid, &clstype->bit_res_ctlrs)) { - ckrm_res_ctlr_t *rcbs; - - atomic_inc(&clstype->nr_resusers[resid]); - rcbs = clstype->res_ctlrs[resid]; - - if (rcbs && rcbs->res_alloc) { - core->res_class[resid] =(*rcbs->res_alloc)(core,parent); - if (core->res_class[resid]) - return; - printk(KERN_ERR "Error creating res class\n"); - } - atomic_dec(&clstype->nr_resusers[resid]); - } -} - -/* - * Initialize a core class - * - */ - -#define CLS_DEBUG(fmt, args...) do { /* printk("%s: " fmt, __FUNCTION__ , ## args); */ } while (0) - - -int -ckrm_init_core_class(struct ckrm_classtype *clstype, - struct ckrm_core_class *dcore, - struct ckrm_core_class *parent, - const char *name) -{ - // Hubertus ... should replace name with dentry or add dentry ? - int i; - - // Hubertus .. how is this used in initialization - - CLS_DEBUG("name %s => %p\n", name?name:"default",dcore); - - if ((dcore != clstype->default_class) && ( !ckrm_is_core_valid(parent))) { - printk("error not a valid parent %p\n", parent); - return -EINVAL; - } -#if 0 // Hubertus .. dynamic allocation still breaks when RCs registers. See def in ckrm_rc.h - dcore->res_class = NULL; - if (clstype->max_resid > 0) { - dcore->res_class = (void**)kmalloc(clstype->max_resid * sizeof(void*) , GFP_KERNEL); - if (dcore->res_class == NULL) { - printk("error no mem\n"); - return -ENOMEM; - } - } -#endif - - dcore->classtype = clstype; - dcore->magic = CKRM_CORE_MAGIC; - dcore->name = name; - dcore->class_lock = SPIN_LOCK_UNLOCKED; - dcore->hnode_rwlock = RW_LOCK_UNLOCKED; - dcore->delayed = 0; - - atomic_set(&dcore->refcnt, 0); - write_lock(&ckrm_class_lock); - - INIT_LIST_HEAD(&dcore->objlist); - list_add(&dcore->clslist,&clstype->classes); - - clstype->num_classes++; - set_callbacks_active(clstype); - - write_unlock(&ckrm_class_lock); - ckrm_add_child(parent, dcore); - - for (i = 0; i < clstype->max_resid; i++) - ckrm_alloc_res_class(dcore,parent,i); - - // fix for race condition seen in stress with numtasks - if (parent) - ckrm_core_grab(parent); - - ckrm_core_grab( dcore ); - return 0; -} - - -static void -ckrm_free_res_class(struct ckrm_core_class *core, int resid) -{ - /* - * Free a resource class only if the resource controller has - * registered with core - */ - - if (core->res_class[resid]) { - ckrm_res_ctlr_t *rcbs; - struct ckrm_classtype *clstype = core->classtype; - - atomic_inc(&clstype->nr_resusers[resid]); - rcbs = clstype->res_ctlrs[resid]; - - if (rcbs->res_free) { - (*rcbs->res_free)(core->res_class[resid]); - atomic_dec(&clstype->nr_resusers[resid]); // for inc in alloc - core->res_class[resid] = NULL; - } - atomic_dec(&clstype->nr_resusers[resid]); - } -} - - -/* - * Free a core class - * requires that all tasks were previously reassigned to another class - * - * Returns 0 on success -errno on failure. - */ - -void -ckrm_free_core_class(struct ckrm_core_class *core) -{ - int i; - struct ckrm_classtype *clstype = core->classtype; - struct ckrm_core_class *parent = core->hnode.parent; - - CLS_DEBUG("core=%p:%s parent=%p:%s\n",core,core->name,parent,parent->name); - if (core->delayed) { - /* this core was marked as late */ - printk("class <%s> finally deleted %lu\n",core->name,jiffies); - } - if (ckrm_remove_child(core) == 0) { - printk("Core class removal failed. Chilren present\n"); - } - - for (i = 0; i < clstype->max_resid; i++) { - ckrm_free_res_class(core,i); - } - - write_lock(&ckrm_class_lock); - - // Clear the magic, so we would know if this core is reused. - core->magic = 0; -#if 0 // Dynamic not yet enabled - core->res_class = NULL; -#endif - // Remove this core class from its linked list. - list_del(&core->clslist); - clstype->num_classes--; - set_callbacks_active(clstype); - write_unlock(&ckrm_class_lock); - - // fix for race condition seen in stress with numtasks - if (parent) - ckrm_core_drop(parent); - - kfree(core); -} - -int -ckrm_release_core_class(struct ckrm_core_class *core) -{ - if (!ckrm_is_core_valid(core)) { - // Invalid core - return (-EINVAL); - } - - if (core == core->classtype->default_class) - return 0; - - /* need to make sure that the classgot really dropped */ - if (atomic_read(&core->refcnt) != 1) { - CLS_DEBUG("class <%s> deletion delayed refcnt=%d jif=%ld\n", - core->name,atomic_read(&core->refcnt),jiffies); - core->delayed = 1; /* just so we have a ref point */ - } - ckrm_core_drop(core); - return 0; -} - -/**************************************************************************** - * Interfaces for the resource controller * - ****************************************************************************/ -/* - * Registering a callback structure by the resource controller. - * - * Returns the resource id(0 or +ve) on success, -errno for failure. - */ -static int -ckrm_register_res_ctlr_intern(struct ckrm_classtype *clstype, ckrm_res_ctlr_t *rcbs) -{ - int resid, ret,i; - - if (!rcbs) - return -EINVAL; - - resid = rcbs->resid; - - spin_lock(&clstype->res_ctlrs_lock); - - printk(KERN_WARNING "resid is %d name is %s %s\n", - resid, rcbs->res_name,clstype->res_ctlrs[resid]->res_name); - - if (resid >= 0) { - if ((resid < CKRM_MAX_RES_CTLRS) && (clstype->res_ctlrs[resid] == NULL)) { - clstype->res_ctlrs[resid] = rcbs; - atomic_set(&clstype->nr_resusers[resid], 0); - set_bit(resid, &clstype->bit_res_ctlrs); - ret = resid; - if (resid >= clstype->max_resid) { - clstype->max_resid = resid + 1; - } - } else { - ret = -EBUSY; - } - spin_unlock(&clstype->res_ctlrs_lock); - return ret; - } - - for (i = clstype->resid_reserved; i < clstype->max_res_ctlrs; i++) { - if (clstype->res_ctlrs[i] == NULL) { - clstype->res_ctlrs[i] = rcbs; - rcbs->resid = i; - atomic_set(&clstype->nr_resusers[i], 0); - set_bit(i, &clstype->bit_res_ctlrs); - if (i >= clstype->max_resid) { - clstype->max_resid = i + 1; - } - spin_unlock(&clstype->res_ctlrs_lock); - return i; - } - } - - spin_unlock(&clstype->res_ctlrs_lock); - return (-ENOMEM); -} - -int -ckrm_register_res_ctlr(struct ckrm_classtype *clstype, ckrm_res_ctlr_t *rcbs) -{ - struct ckrm_core_class *core; - int resid; - - resid = ckrm_register_res_ctlr_intern(clstype,rcbs); - - if (resid >= 0) { - /* run through all classes and create the resource class object and - * if necessary "initialize" class in context of this resource - */ - read_lock(&ckrm_class_lock); - list_for_each_entry(core, &clstype->classes, clslist) { - printk("CKRM .. create res clsobj for resouce <%s> class <%s> par=%p\n", - rcbs->res_name, core->name, core->hnode.parent); - ckrm_alloc_res_class(core, core->hnode.parent, resid); - if (clstype->add_resctrl) // FIXME: this should be mandatory - (*clstype->add_resctrl)(core,resid); - } - read_unlock(&ckrm_class_lock); - } - return resid; -} - -/* - * Unregistering a callback structure by the resource controller. - * - * Returns 0 on success -errno for failure. - */ -int -ckrm_unregister_res_ctlr(struct ckrm_res_ctlr *rcbs) -{ - struct ckrm_classtype *clstype = rcbs->classtype; - int resid = rcbs->resid; - - if ((clstype == NULL) || (resid < 0)) - return -EINVAL; - - if (atomic_read(&clstype->nr_resusers[resid])) - return -EBUSY; - - // FIXME: probably need to also call deregistration function - - spin_lock(&clstype->res_ctlrs_lock); - clstype->res_ctlrs[resid] = NULL; - clear_bit(resid, &clstype->bit_res_ctlrs); - clstype->max_resid = fls(clstype->bit_res_ctlrs); - rcbs->resid = -1; - spin_unlock(&clstype->res_ctlrs_lock); - - return 0; -} - -/******************************************************************* - * Class Type Registration - *******************************************************************/ - -/* Hubertus ... we got to do some locking here */ - -struct ckrm_classtype* ckrm_classtypes[CKRM_MAX_CLASSTYPES]; -EXPORT_SYMBOL(ckrm_classtypes); // really should build a better interface for this - -int -ckrm_register_classtype(struct ckrm_classtype *clstype) -{ - int tid = clstype->typeID; - - if (tid != -1) { - if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES) || (ckrm_classtypes[tid])) - return -EINVAL; - } else { - int i; - for ( i=CKRM_RESV_CLASSTYPES ; itypeID = tid; - ckrm_classtypes[tid] = clstype; - - /* Hubertus .. we need to call the callbacks of the RCFS client */ - if (rcfs_fn.register_classtype) { - (* rcfs_fn.register_classtype)(clstype); - // No error return for now ; - } - - return tid; -} - -int -ckrm_unregister_classtype(struct ckrm_classtype *clstype) -{ - int tid = clstype->typeID; - - if ((tid < 0) || (tid > CKRM_MAX_CLASSTYPES) || (ckrm_classtypes[tid] != clstype)) - return -EINVAL; - - if (rcfs_fn.deregister_classtype) { - (* rcfs_fn.deregister_classtype)(clstype); - // No error return for now - } - - ckrm_classtypes[tid] = NULL; - clstype->typeID = -1; - return 0; -} - -struct ckrm_classtype* -ckrm_find_classtype_by_name(const char *name) -{ - int i; - for ( i=0 ; iname,name,CKRM_MAX_TYPENAME_LEN)) - return ctype; - } - return NULL; -} - - -/******************************************************************* - * Event callback invocation - *******************************************************************/ - -struct ckrm_hook_cb* ckrm_event_callbacks[CKRM_NONLATCHABLE_EVENTS]; - -/* Registration / Deregistration / Invocation functions */ - -int -ckrm_register_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb) -{ - struct ckrm_hook_cb **cbptr; - - if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS)) - return 1; - cbptr = &ckrm_event_callbacks[ev]; - while (*cbptr != NULL) - cbptr = &((*cbptr)->next); - *cbptr = cb; - return 0; -} - -int -ckrm_unregister_event_cb(enum ckrm_event ev, struct ckrm_hook_cb *cb) -{ - struct ckrm_hook_cb **cbptr; - - if ((ev < CKRM_LATCHABLE_EVENTS) || (ev >= CKRM_NONLATCHABLE_EVENTS)) - return -1; - cbptr = &ckrm_event_callbacks[ev]; - while ((*cbptr != NULL) && (*cbptr != cb)) - cbptr = &((*cbptr)->next); - if (*cbptr) - (*cbptr)->next = cb->next; - return (*cbptr == NULL); -} - -int -ckrm_register_event_set(struct ckrm_event_spec especs[]) -{ - struct ckrm_event_spec *espec = especs; - - for ( espec = especs ; espec->ev != -1 ; espec++ ) - ckrm_register_event_cb(espec->ev,&espec->cb); - return 0; -} - -int -ckrm_unregister_event_set(struct ckrm_event_spec especs[]) -{ - struct ckrm_event_spec *espec = especs; - - for ( espec = especs ; espec->ev != -1 ; espec++ ) - ckrm_unregister_event_cb(espec->ev,&espec->cb); - return 0; -} - -#define ECC_PRINTK(fmt, args...) // printk("%s: " fmt, __FUNCTION__ , ## args) - -void -ckrm_invoke_event_cb_chain(enum ckrm_event ev, void *arg) -{ - struct ckrm_hook_cb *cb, *anchor; - - ECC_PRINTK("%d %x\n",current,ev,arg); - if ((anchor = ckrm_event_callbacks[ev]) != NULL) { - for ( cb = anchor ; cb ; cb = cb->next ) - (*cb->fct)(arg); - } -} - -/******************************************************************* - * Generic Functions that can be used as default functions - * in almost all classtypes - * (a) function iterator over all resource classes of a class - * (b) function invoker on a named resource - *******************************************************************/ - -int -ckrm_class_show_shares(struct ckrm_core_class *core, struct seq_file *seq) -{ - int i; - struct ckrm_res_ctlr *rcbs; - struct ckrm_classtype *clstype = core->classtype; - struct ckrm_shares shares; - - for (i = 0; i < clstype->max_resid; i++) { - atomic_inc(&clstype->nr_resusers[i]); - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->get_share_values) { - (*rcbs->get_share_values)(core->res_class[i], &shares); - seq_printf(seq,"res=%s,guarantee=%d,limit=%d,total_guarantee=%d,max_limit=%d\n", - rcbs->res_name, - shares.my_guarantee, - shares.my_limit, - shares.total_guarantee, - shares.max_limit); - } - atomic_dec(&clstype->nr_resusers[i]); - } - return 0; -} - -int -ckrm_class_show_stats(struct ckrm_core_class *core, struct seq_file *seq) -{ - int i; - struct ckrm_res_ctlr *rcbs; - struct ckrm_classtype *clstype = core->classtype; - - for (i = 0; i < clstype->max_resid; i++) { - atomic_inc(&clstype->nr_resusers[i]); - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->get_stats) - (*rcbs->get_stats)(core->res_class[i], seq); - atomic_dec(&clstype->nr_resusers[i]); - } - return 0; -} - -int -ckrm_class_show_config(struct ckrm_core_class *core, struct seq_file *seq) -{ - int i; - struct ckrm_res_ctlr *rcbs; - struct ckrm_classtype *clstype = core->classtype; - - for (i = 0; i < clstype->max_resid; i++) { - atomic_inc(&clstype->nr_resusers[i]); - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->show_config) - (*rcbs->show_config)(core->res_class[i], seq); - atomic_dec(&clstype->nr_resusers[i]); - } - return 0; -} - -int -ckrm_class_set_config(struct ckrm_core_class *core, const char *resname, const char *cfgstr) -{ - struct ckrm_classtype *clstype = core->classtype; - struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype,resname); - int rc; - - if (rcbs == NULL || rcbs->set_config == NULL) - return -EINVAL; - rc = (*rcbs->set_config)(core->res_class[rcbs->resid],cfgstr); - return rc; -} - -int -ckrm_class_set_shares(struct ckrm_core_class *core, const char *resname, - struct ckrm_shares *shares) -{ - struct ckrm_classtype *clstype = core->classtype; - struct ckrm_res_ctlr *rcbs; - int rc; - - printk("ckrm_class_set_shares(%s,%s)\n",core->name,resname); - rcbs = ckrm_resctlr_lookup(clstype,resname); - if (rcbs == NULL || rcbs->set_share_values == NULL) - return -EINVAL; - rc = (*rcbs->set_share_values)(core->res_class[rcbs->resid],shares); - return rc; -} - -int -ckrm_class_reset_stats(struct ckrm_core_class *core, const char *resname, const char *unused) -{ - struct ckrm_classtype *clstype = core->classtype; - struct ckrm_res_ctlr *rcbs = ckrm_resctlr_lookup(clstype,resname); - int rc; - - if (rcbs == NULL || rcbs->reset_stats == NULL) - return -EINVAL; - rc = (*rcbs->reset_stats)(core->res_class[rcbs->resid]); - return rc; -} - -/******************************************************************* - * Initialization - *******************************************************************/ - -void -ckrm_cb_newtask(struct task_struct *tsk) -{ - tsk->ce_data = NULL; - spin_lock_init(&tsk->ckrm_tsklock); - ckrm_invoke_event_cb_chain(CKRM_EVENT_NEWTASK,tsk); -} - -void -ckrm_cb_exit(struct task_struct *tsk) -{ - ckrm_invoke_event_cb_chain(CKRM_EVENT_EXIT,tsk); - tsk->ce_data = NULL; -} - -void __init -ckrm_init(void) -{ - printk("CKRM Initialization\n"); - - // register/initialize the Metatypes - -#ifdef CONFIG_CKRM_TYPE_TASKCLASS - { - extern void ckrm_meta_init_taskclass(void); - ckrm_meta_init_taskclass(); - } -#endif -#ifdef CONFIG_CKRM_TYPE_SOCKETCLASS - { - extern void ckrm_meta_init_sockclass(void); - ckrm_meta_init_sockclass(); - } -#endif - // prepare init_task and then rely on inheritance of properties - ckrm_cb_newtask(&init_task); - printk("CKRM Initialization done\n"); -} - -EXPORT_SYMBOL(ckrm_register_engine); -EXPORT_SYMBOL(ckrm_unregister_engine); - -EXPORT_SYMBOL(ckrm_register_res_ctlr); -EXPORT_SYMBOL(ckrm_unregister_res_ctlr); - -EXPORT_SYMBOL(ckrm_init_core_class); -EXPORT_SYMBOL(ckrm_free_core_class); -EXPORT_SYMBOL(ckrm_release_core_class); - -EXPORT_SYMBOL(ckrm_register_classtype); -EXPORT_SYMBOL(ckrm_unregister_classtype); -EXPORT_SYMBOL(ckrm_find_classtype_by_name); - -EXPORT_SYMBOL(ckrm_core_grab); -EXPORT_SYMBOL(ckrm_core_drop); -EXPORT_SYMBOL(ckrm_is_core_valid); -EXPORT_SYMBOL(ckrm_validate_and_grab_core); - -EXPORT_SYMBOL(ckrm_register_event_set); -EXPORT_SYMBOL(ckrm_unregister_event_set); -EXPORT_SYMBOL(ckrm_register_event_cb); -EXPORT_SYMBOL(ckrm_unregister_event_cb); - -EXPORT_SYMBOL(ckrm_class_show_stats); -EXPORT_SYMBOL(ckrm_class_show_config); -EXPORT_SYMBOL(ckrm_class_show_shares); - -EXPORT_SYMBOL(ckrm_class_set_config); -EXPORT_SYMBOL(ckrm_class_set_shares); - -EXPORT_SYMBOL(ckrm_class_reset_stats); - - diff --git a/kernel/ckrm/ckrm_listenaq.c b/kernel/ckrm/ckrm_listenaq.c deleted file mode 100644 index 235ac0699..000000000 --- a/kernel/ckrm/ckrm_listenaq.c +++ /dev/null @@ -1,503 +0,0 @@ -/* ckrm_socketaq.c - accept queue resource controller - * - * Copyright (C) Vivek Kashyap, IBM Corp. 2004 - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * Initial version - */ - -/* Code Description: TBD - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define hnode_2_core(ptr) \ - ((ptr) ? container_of(ptr, struct ckrm_core_class, hnode) : NULL) - - -#define CKRM_SAQ_MAX_DEPTH 3 // 0 => /rcfs - // 1 => socket_aq - // 2 => socket_aq/listen_class - // 3 => socket_aq/listen_class/accept_queues - // 4 => Not allowed - -typedef struct ckrm_laq_res { - spinlock_t reslock; - atomic_t refcnt; - struct ckrm_shares shares; - struct ckrm_core_class *core; - struct ckrm_core_class *pcore; - int my_depth; - int my_id; -} ckrm_laq_res_t; - -static int my_resid = -1; - -extern struct ckrm_core_class *rcfs_create_under_netroot(char *, int, int); -extern struct ckrm_core_class *rcfs_make_core(struct dentry *, - struct ckrm_core_class * ) ; - -void -laq_res_hold(struct ckrm_laq_res *res) -{ - atomic_inc(&res->refcnt); - return; -} - -void -laq_res_put(struct ckrm_laq_res *res) -{ - if (atomic_dec_and_test(&res->refcnt)) - kfree(res); - return; -} - -/* Initialize rescls values - */ -static void -laq_res_initcls(void *my_res) -{ - ckrm_laq_res_t *res = my_res; - - res->shares.my_guarantee = CKRM_SHARE_DONTCARE; - res->shares.my_limit = CKRM_SHARE_DONTCARE; - res->shares.total_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE; - res->shares.max_limit = CKRM_SHARE_DFLT_MAX_LIMIT; - res->shares.unused_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE; - res->shares.cur_max_limit = 0; -} - -static int -atoi(char *s) -{ - int k = 0; - while(*s) - k = *s++ - '0' + (k * 10); - return k; -} - -static char * -laq_get_name(struct ckrm_core_class *c) -{ - char *p = (char *)c->name; - - while(*p) - p++; - while( *p != '/' && p != c->name) - p--; - - return ++p; -} - -static void * -laq_res_alloc(struct ckrm_core_class *core, struct ckrm_core_class *parent) -{ - ckrm_laq_res_t *res, *pres; - int pdepth; - - if (parent) - pres = ckrm_get_res_class(parent, my_resid, ckrm_laq_res_t); - else - pres = NULL; - - if (core == core->classtype->default_class) - pdepth = 1; - else { - if (!parent) - return NULL; - pdepth = 1 + pres->my_depth; - } - - res = kmalloc(sizeof(ckrm_laq_res_t), GFP_ATOMIC); - if (res) { - memset(res, 0, sizeof(res)); - spin_lock_init(&res->reslock); - laq_res_hold(res); - res->my_depth = pdepth; - if (pdepth == 2) // listen class - res->my_id = 0; - else if (pdepth == 3) - res->my_id = atoi(laq_get_name(core)); - res->core = core; - res->pcore = parent; - - // rescls in place, now initialize contents other than - // hierarchy pointers - laq_res_initcls(res); // acts as initialising value - } - - return res; -} - -static void -laq_res_free(void *my_res) -{ - ckrm_laq_res_t *res = (ckrm_laq_res_t *)my_res; - ckrm_laq_res_t *parent; - - if (!res) - return; - - if (res->my_depth != 3) { - kfree(res); - return; - } - - parent = ckrm_get_res_class(res->pcore, my_resid, ckrm_laq_res_t); - if (!parent) // Should never happen - return; - - spin_lock(&parent->reslock); - spin_lock(&res->reslock); - - // return child's guarantee to parent node - // Limits have no meaning for accept queue control - child_guarantee_changed(&parent->shares, res->shares.my_guarantee, 0); - - spin_unlock(&res->reslock); - laq_res_put(res); - spin_unlock(&parent->reslock); - return; -} - -/************************************************************************** - * SHARES *** - **************************************************************************/ - -void -laq_set_aq_values(ckrm_laq_res_t *my_res, ckrm_laq_res_t *parent, int updatep) -{ - - struct ckrm_net_struct *ns; - struct ckrm_core_class *core = parent->core; - struct tcp_opt *tp; - - if (my_res->my_depth < 2) - return; - - // XXX Instead of holding a class_lock introduce a rw - // lock to be write locked by listen callbacks and read locked here. - // - VK - class_lock(core); - list_for_each_entry(ns, &core->objlist,ckrm_link) { - tp = tcp_sk(ns->ns_sk); - if (updatep) - tp->acceptq[0].aq_ratio = - parent->shares.total_guarantee/ - parent->shares.unused_guarantee; - - tp->acceptq[my_res->my_id].aq_ratio = - my_res->shares.total_guarantee/ - parent->shares.my_guarantee; - } - class_unlock(core); - return; -} - -static int -laq_set_share_values(void *my_res, struct ckrm_shares *shares) -{ - ckrm_laq_res_t *res = my_res; - ckrm_laq_res_t *parent, *child; - struct ckrm_hnode *chnode; - int rc = 0; - - if (!res) - return -EINVAL; - - if (!res->pcore) { - // something is badly wrong - printk(KERN_ERR "socketaq internal inconsistency\n"); - return -EBADF; - } - - parent = ckrm_get_res_class(res->pcore, my_resid, ckrm_laq_res_t); - if (!parent) // socket_class does not have a share interface - return -EINVAL; - - // Ensure that we ignore limit values - shares->my_limit = shares->max_limit = CKRM_SHARE_UNCHANGED; - - switch (res->my_depth) { - - case 0: printk(KERN_ERR "socketaq bad entry\n"); - rc = -EBADF; - break; - - case 1: // can't be written to. this is internal default. - // return -EINVAL - rc = -EINVAL; - break; - - case 2: // nothing to inherit - if (!shares->total_guarantee) { - rc = -EINVAL; - break; - } - - ckrm_lock_hier(res->pcore); - spin_lock(&res->reslock); - rc = set_shares(shares, &res->shares, NULL); - if (!rc) { - list_for_each_entry(chnode, - &res->core->hnode.children,siblings){ - child=hnode_2_core(chnode)->res_class[my_resid]; - laq_set_aq_values(child,res,(child->my_id==1)); - } - } - spin_unlock(&res->reslock); - ckrm_unlock_hier(res->pcore); - break; - - case 3: // accept queue itself. Check against parent. - ckrm_lock_hier(parent->pcore); - spin_lock(&parent->reslock); - rc = set_shares(shares, &res->shares, &parent->shares); - if (!rc) { - laq_set_aq_values(res,parent,1); - } - spin_unlock(&parent->reslock); - ckrm_unlock_hier(parent->pcore); - break; - } - - return rc; -} - -static int -laq_get_share_values(void *my_res, struct ckrm_shares *shares) -{ - ckrm_laq_res_t *res = my_res; - - if (!res) - return -EINVAL; - *shares = res->shares; - return 0; -} - -/************************************************************************** - * STATS *** - **************************************************************************/ - -void -laq_print_aq_stats(struct seq_file *sfile, struct tcp_acceptq_info *taq, int i) -{ - seq_printf(sfile, "Class %d connections:\n\taccepted: %u\n\t" - "queued: %u\n\twait_time: %lu\n\t", - i, taq->acceptq_count, taq->acceptq_qcount, - taq->acceptq_wait_time); - - if (i) - return; - - for (i = 1; i < NUM_ACCEPT_QUEUES; i++) { - taq[0].acceptq_wait_time += taq[i].acceptq_wait_time; - taq[0].acceptq_qcount += taq[i].acceptq_qcount; - taq[0].acceptq_count += taq[i].acceptq_count; - } - - seq_printf(sfile, "Totals :\n\taccepted: %u\n\t" - "queued: %u\n\twait_time: %lu\n", - taq->acceptq_count, taq->acceptq_qcount, - taq->acceptq_wait_time); - - return; -} - -void -laq_get_aq_stats(ckrm_laq_res_t *pres, ckrm_laq_res_t *mres, - struct tcp_acceptq_info *taq) -{ - struct ckrm_net_struct *ns; - struct ckrm_core_class *core = pres->core; - struct tcp_opt *tp; - int a = mres->my_id; - int z; - - if (a == 0) - z = NUM_ACCEPT_QUEUES; - else - z = a+1; - - // XXX Instead of holding a class_lock introduce a rw - // lock to be write locked by listen callbacks and read locked here. - // - VK - class_lock(pres->core); - list_for_each_entry(ns, &core->objlist,ckrm_link) { - tp = tcp_sk(ns->ns_sk); - for (; a< z; a++) { - taq->acceptq_wait_time += tp->acceptq[a].aq_wait_time; - taq->acceptq_qcount += tp->acceptq[a].aq_qcount; - taq->acceptq_count += tp->acceptq[a].aq_count; - taq++; - } - } - class_unlock(pres->core); -} - - -static int -laq_get_stats(void *my_res, struct seq_file *sfile) -{ - ckrm_laq_res_t *res = my_res; - ckrm_laq_res_t *parent; - struct tcp_acceptq_info taq[NUM_ACCEPT_QUEUES]; - int rc = 0; - - if (!res) - return -EINVAL; - - if (!res->pcore) { - // something is badly wrong - printk(KERN_ERR "socketaq internal inconsistency\n"); - return -EBADF; - } - - parent = ckrm_get_res_class(res->pcore, my_resid, ckrm_laq_res_t); - if (!parent) { // socket_class does not have a stat interface - printk(KERN_ERR "socketaq internal fs inconsistency\n"); - return -EINVAL; - } - - memset(taq, 0, sizeof(struct tcp_acceptq_info) * NUM_ACCEPT_QUEUES); - - switch (res->my_depth) { - - default: - case 0: printk(KERN_ERR "socket class bad entry\n"); - rc = -EBADF; - break; - - case 1: // can't be read from. this is internal default. - // return -EINVAL - rc = -EINVAL; - break; - - case 2: // return the default and total - ckrm_lock_hier(res->core); // block any deletes - laq_get_aq_stats(res, res, &taq[0]); - laq_print_aq_stats(sfile, &taq[0], 0); - ckrm_unlock_hier(res->core); // block any deletes - break; - - case 3: - ckrm_lock_hier(parent->core); // block any deletes - laq_get_aq_stats(parent, res, &taq[res->my_id]); - laq_print_aq_stats(sfile, &taq[res->my_id], res->my_id); - ckrm_unlock_hier(parent->core); // block any deletes - break; - } - - return rc; -} - -/* - * The network connection is reclassified to this class. Update its shares. - * The socket lock is held. - */ -static void -laq_change_resclass(void *n, void *old, void *r) -{ - struct ckrm_net_struct *ns = (struct ckrm_net_struct *)n; - struct ckrm_laq_res *res = (struct ckrm_laq_res *)r; - struct ckrm_hnode *chnode = NULL; - - - if (res->my_depth != 2) - return; - - // a change to my_depth == 3 ie. the accept classes cannot happen. - // there is no target file - if (res->my_depth == 2) { // it is one of the socket classes - struct ckrm_laq_res *reschild; - struct sock *sk = ns->ns_sk; - struct tcp_opt *tp = tcp_sk(sk); - - // share rule: hold parent resource lock. then self. - // However, since my_depth == 1 is a generic class it is not - // needed here. Self lock is enough. - spin_lock(&res->reslock); - tp->acceptq[0].aq_ratio = res->shares.total_guarantee/ - res->shares.unused_guarantee; - list_for_each_entry(chnode,&res->core->hnode.children,siblings){ - reschild = hnode_2_core(chnode)->res_class[my_resid]; - - spin_lock(&reschild->reslock); - tp->acceptq[reschild->my_id].aq_ratio= - reschild->shares.total_guarantee/ - res->shares.my_guarantee; - spin_unlock(&reschild->reslock); - } - spin_unlock(&res->reslock); - } - - return; -} - -struct ckrm_res_ctlr laq_rcbs = { - .res_name = "laq", - .resid = -1 , // dynamically assigned - .res_alloc = laq_res_alloc, - .res_free = laq_res_free, - .set_share_values = laq_set_share_values, - .get_share_values = laq_get_share_values, - .get_stats = laq_get_stats, - .change_resclass = laq_change_resclass, - // .res_initcls = laq_res_initcls, // LAQ_HUBERTUS: no need for this !! -}; - -int __init -init_ckrm_laq_res(void) -{ - struct ckrm_classtype *clstype; - int resid; - - clstype = ckrm_find_classtype_by_name("socket_class"); - if (clstype == NULL) { - printk(KERN_INFO " Unknown ckrm classtype"); - return -ENOENT; - } - - if (my_resid == -1) { - resid = ckrm_register_res_ctlr(clstype,&laq_rcbs); - if (resid >= 0) - my_resid = resid; - printk("........init_ckrm_listen_aq_res -> %d\n",my_resid); - } - return 0; - -} - -void __exit -exit_ckrm_laq_res(void) -{ - ckrm_unregister_res_ctlr(&laq_rcbs); - my_resid = -1; -} - - -module_init(init_ckrm_laq_res) -module_exit(exit_ckrm_laq_res) - -MODULE_LICENSE("GPL"); - diff --git a/kernel/ckrm/ckrm_sockc.c b/kernel/ckrm/ckrm_sockc.c deleted file mode 100644 index 26731bb20..000000000 --- a/kernel/ckrm/ckrm_sockc.c +++ /dev/null @@ -1,554 +0,0 @@ -/* ckrm_sock.c - Class-based Kernel Resource Management (CKRM) - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004 - * (C) Shailabh Nagar, IBM Corp. 2003 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * (C) Vivek Kashyap, IBM Corp. 2004 - * - * - * Provides kernel API of CKRM for in-kernel,per-resource controllers - * (one each for cpu, memory, io, network) and callbacks for - * classification modules. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 28 Aug 2003 - * Created. - * 06 Nov 2003 - * Made modifications to suit the new RBCE module. - * 10 Nov 2003 - * Fixed a bug in fork and exit callbacks. Added callbacks_active and - * surrounding logic. Added task paramter for all CE callbacks. - * 23 Mar 2004 - * moved to referenced counted class objects and correct locking - * 12 Apr 2004 - * introduced adopted to emerging classtype interface - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct ckrm_sock_class { - struct ckrm_core_class core; -}; - -static struct ckrm_sock_class sockclass_dflt_class = { -}; - -#define SOCKET_CLASS_TYPE_NAME "socket_class" - -const char *dflt_sockclass_name = SOCKET_CLASS_TYPE_NAME; - -static struct ckrm_core_class *sock_alloc_class(struct ckrm_core_class *parent, const char *name); -static int sock_free_class(struct ckrm_core_class *core); - -static int sock_forced_reclassify(ckrm_core_class_t *target, const char *resname); -static int sock_show_members(struct ckrm_core_class *core, struct seq_file *seq); -static void sock_add_resctrl(struct ckrm_core_class *core, int resid); -static void sock_reclassify_class(struct ckrm_sock_class *cls); - -struct ckrm_classtype CT_sockclass = { - .mfidx = 1, - .name = SOCKET_CLASS_TYPE_NAME, - .typeID = CKRM_CLASSTYPE_SOCKET_CLASS, - .maxdepth = 3, - .resid_reserved = 0, - .max_res_ctlrs = CKRM_MAX_RES_CTLRS, - .max_resid = 0, - .bit_res_ctlrs = 0L, - .res_ctlrs_lock = SPIN_LOCK_UNLOCKED, - .classes = LIST_HEAD_INIT(CT_sockclass.classes), - - .default_class = &sockclass_dflt_class.core, - - // private version of functions - .alloc = &sock_alloc_class, - .free = &sock_free_class, - .show_members = &sock_show_members, - .forced_reclassify = &sock_forced_reclassify, - - // use of default functions - .show_shares = &ckrm_class_show_shares, - .show_stats = &ckrm_class_show_stats, - .show_config = &ckrm_class_show_config, - .set_config = &ckrm_class_set_config, - .set_shares = &ckrm_class_set_shares, - .reset_stats = &ckrm_class_reset_stats, - - // mandatory private version .. no dflt available - .add_resctrl = &sock_add_resctrl, -}; - -/* helper functions */ - -void -ckrm_ns_hold(struct ckrm_net_struct *ns) -{ - atomic_inc(&ns->ns_refcnt); - return; -} - -void -ckrm_ns_put(struct ckrm_net_struct *ns) -{ - if (atomic_dec_and_test(&ns->ns_refcnt)) - kfree(ns); - - return; -} -/* - * Change the class of a netstruct - * - * Change the task's task class to "newcls" if the task's current - * class (task->taskclass) is same as given "oldcls", if it is non-NULL. - * - */ - -static void -sock_set_class(struct ckrm_net_struct *ns, struct ckrm_sock_class *newcls, - struct ckrm_sock_class *oldcls, enum ckrm_event event) -{ - int i; - struct ckrm_res_ctlr *rcbs; - struct ckrm_classtype *clstype; - void *old_res_class, *new_res_class; - - if ((newcls == oldcls) || (newcls == NULL)) { - ns->core = (void *)oldcls; - return; - } - - class_lock(class_core(newcls)); - ns->core = newcls; - list_add(&ns->ckrm_link, &class_core(newcls)->objlist); - class_unlock(class_core(newcls)); - - clstype = class_isa(newcls); - for (i = 0; i < clstype->max_resid; i++) { - atomic_inc(&clstype->nr_resusers[i]); - old_res_class = oldcls ? class_core(oldcls)->res_class[i] : NULL; - new_res_class = newcls ? class_core(newcls)->res_class[i] : NULL; - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->change_resclass && (old_res_class != new_res_class)) - (*rcbs->change_resclass)(ns, old_res_class, new_res_class); - atomic_dec(&clstype->nr_resusers[i]); - } - return; -} - -static void -sock_add_resctrl(struct ckrm_core_class *core, int resid) -{ - struct ckrm_net_struct *ns; - struct ckrm_res_ctlr *rcbs; - - if ((resid < 0) || (resid >= CKRM_MAX_RES_CTLRS) || ((rcbs = core->classtype->res_ctlrs[resid]) == NULL)) - return; - - class_lock(core); - list_for_each_entry(ns, &core->objlist, ckrm_link) { - if (rcbs->change_resclass) - (*rcbs->change_resclass)(ns, NULL, core->res_class[resid]); - } - class_unlock(core); -} - - -/************************************************************************** - * Functions called from classification points * - **************************************************************************/ - -static void -cb_sockclass_listen_start(struct sock *sk) -{ - struct ckrm_net_struct *ns = NULL; - struct ckrm_sock_class *newcls = NULL; - struct ckrm_res_ctlr *rcbs; - struct ckrm_classtype *clstype; - int i = 0; - - // XXX - TBD ipv6 - if (sk->sk_family == IPPROTO_IPV6) - return; - - // to store the socket address - ns = (struct ckrm_net_struct *) - kmalloc(sizeof(struct ckrm_net_struct), GFP_ATOMIC); - if (!ns) - return; - - memset(ns,0, sizeof(ns)); - INIT_LIST_HEAD(&ns->ckrm_link); - - ns->ns_family = sk->sk_family; - if (ns->ns_family == IPPROTO_IPV6) // IPv6 not supported yet. - return; - - ns->ns_daddrv4 = inet_sk(sk)->rcv_saddr; - ns->ns_dport = inet_sk(sk)->num; - - ns->ns_pid = current->pid; - ns->ns_tgid = current->tgid; - - ce_protect(&CT_sockclass); - CE_CLASSIFY_RET(newcls,&CT_sockclass,CKRM_EVENT_LISTEN_START,ns,current); - ce_release(&CT_sockclass); - - if (newcls == NULL) { - newcls = &sockclass_dflt_class; - ckrm_core_grab(class_core(newcls)); - } - - class_lock(class_core(newcls)); - list_add(&ns->ckrm_link, &class_core(newcls)->objlist); - ckrm_ns_put(ns); - ns->core = newcls; - class_unlock(class_core(newcls)); - - - // the socket is already locked - // take a reference on socket on our behalf - sock_hold(sk); - sk->sk_ns = (void *)ns; - ns->ns_sk = sk; - - // modify its shares - clstype = class_isa(newcls); - for (i = 0; i < clstype->max_resid; i++) { - atomic_inc(&clstype->nr_resusers[i]); - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->change_resclass) { - (*rcbs->change_resclass)((void *)ns, - NULL,class_core(newcls)->res_class[i]); - } - atomic_dec(&clstype->nr_resusers[i]); - } - return; -} - -static void -cb_sockclass_listen_stop(struct sock *sk) -{ - struct ckrm_net_struct *ns = NULL; - struct ckrm_sock_class *newcls = NULL; - - // XXX - TBD ipv6 - if (sk->sk_family == IPPROTO_IPV6) - return; - - ns = (struct ckrm_net_struct *)sk->sk_ns; - if (!ns) // listen_start called before socket_aq was loaded - return; - - newcls = ns->core; - if (newcls) { - class_lock(class_core(newcls)); - list_del(&ns->ckrm_link); - INIT_LIST_HEAD(&ns->ckrm_link); - class_unlock(class_core(newcls)); - ckrm_core_drop(class_core(newcls)); - } - - // the socket is already locked - sk->sk_ns = NULL; - sock_put(sk); - - // Should be the last count and free it - ckrm_ns_put(ns); - return; -} - -static struct ckrm_event_spec sock_events_callbacks[] = { - CKRM_EVENT_SPEC( LISTEN_START, cb_sockclass_listen_start ), - CKRM_EVENT_SPEC( LISTEN_STOP, cb_sockclass_listen_stop ), - { -1 } -}; - -/************************************************************************** - * Class Object Creation / Destruction - **************************************************************************/ - -static struct ckrm_core_class * -sock_alloc_class(struct ckrm_core_class *parent, const char *name) -{ - struct ckrm_sock_class *sockcls; - sockcls = kmalloc(sizeof(struct ckrm_sock_class), GFP_KERNEL); - if (sockcls == NULL) - return NULL; - - ckrm_init_core_class(&CT_sockclass,class_core(sockcls),parent,name); - - ce_protect(&CT_sockclass); - if (CT_sockclass.ce_cb_active && CT_sockclass.ce_callbacks.class_add) - (*CT_sockclass.ce_callbacks.class_add)(name,sockcls); - ce_release(&CT_sockclass); - - return class_core(sockcls); -} - -static int -sock_free_class(struct ckrm_core_class *core) -{ - struct ckrm_sock_class *sockcls; - - if (!ckrm_is_core_valid(core)) { - // Invalid core - return (-EINVAL); - } - if (core == core->classtype->default_class) { - // reset the name tag - core->name = dflt_sockclass_name; - return 0; - } - - sockcls = class_type(struct ckrm_sock_class, core); - - ce_protect(&CT_sockclass); - - if (CT_sockclass.ce_cb_active && CT_sockclass.ce_callbacks.class_delete) - (*CT_sockclass.ce_callbacks.class_delete)(core->name,sockcls); - - sock_reclassify_class ( sockcls ); - - ce_release(&CT_sockclass); - - ckrm_release_core_class(core); // Hubertus .... could just drop the class .. error message - return 0; -} - - -static int -sock_show_members(struct ckrm_core_class *core, struct seq_file *seq) -{ - struct list_head *lh; - struct ckrm_net_struct *ns = NULL; - - class_lock(core); - list_for_each(lh, &core->objlist) { - ns = container_of(lh, struct ckrm_net_struct,ckrm_link); - seq_printf(seq, "%d.%d.%d.%d\\%d\n", - NIPQUAD(ns->ns_daddrv4),ns->ns_dport); - } - class_unlock(core); - - return 0; -} - -static int -sock_forced_reclassify_ns(struct ckrm_net_struct *tns, struct ckrm_core_class *core) -{ - struct ckrm_net_struct *ns = NULL; - struct sock *sk = NULL; - struct ckrm_sock_class *oldcls, *newcls; - int rc = -EINVAL; - - if (!ckrm_is_core_valid(core)) { - return rc; - } - - newcls = class_type(struct ckrm_sock_class, core); - // lookup the listening sockets - // returns with a reference count set on socket - sk = tcp_v4_lookup_listener(tns->ns_daddrv4,tns->ns_dport,0); - if (!sk) { - printk(KERN_INFO "No such listener 0x%x:%d\n", - tns->ns_daddrv4, tns->ns_dport); - return rc; - } - lock_sock(sk); - if (!sk->sk_ns) { - goto out; - } - ns = sk->sk_ns; - ckrm_ns_hold(ns); - oldcls = ns->core; - if ((oldcls == NULL) || (oldcls == newcls)) { - ckrm_ns_put(ns); - goto out; - } - - // remove the net_struct from the current class - class_lock(class_core(oldcls)); - list_del(&ns->ckrm_link); - INIT_LIST_HEAD(&ns->ckrm_link); - ns->core = NULL; - class_unlock(class_core(oldcls)); - - sock_set_class(ns, newcls, oldcls, CKRM_EVENT_MANUAL); - ckrm_ns_put(ns); - rc = 0; -out: - release_sock(sk); - sock_put(sk); - - return rc; - -} - -enum sock_target_token_t { - IPV4, IPV6, SOCKC_TARGET_ERR -}; - -static match_table_t sock_target_tokens = { - {IPV4, "ipv4=%s"}, - {IPV6, "ipv6=%s"}, - {SOCKC_TARGET_ERR, NULL}, -}; - -char * -v4toi(char *s, char c, __u32 *v) -{ - unsigned int k = 0, n = 0; - - while(*s && (*s != c)) { - if (*s == '.') { - n <<= 8; - n |= k; - k = 0; - } - else - k = k *10 + *s - '0'; - s++; - } - - n <<= 8; - *v = n | k; - - return s; -} - -static int -sock_forced_reclassify(struct ckrm_core_class *target,const char *options) -{ - char *p,*p2; - struct ckrm_net_struct ns; - __u32 v4addr, tmp; - - if (!options) - return 1; - - while ((p = strsep((char**)&options, ",")) != NULL) { - substring_t args[MAX_OPT_ARGS]; - int token; - - if (!*p) - continue; - token = match_token(p, sock_target_tokens, args); - switch (token) { - - case IPV4: - - p2 = p; - while(*p2 && (*p2 != '=')) - ++p2; - p2++; - p2 = v4toi(p2, '\\',&(v4addr)); - ns.ns_daddrv4 = htonl(v4addr); - ns.ns_family = 4; //IPPROTO_IPV4 - p2 = v4toi(++p2, ':',&tmp); ns.ns_dport = (__u16)tmp; - p2 = v4toi(++p2,'\0',&ns.ns_pid); - - sock_forced_reclassify_ns(&ns,target); - break; - - case IPV6: - printk(KERN_INFO "rcfs: IPV6 not supported yet\n"); - return 0; - default: - return 0; - } - } - return 1; -} - -/* - * Listen_aq reclassification. - */ -static void -sock_reclassify_class(struct ckrm_sock_class *cls) -{ - struct ckrm_net_struct *ns, *tns; - struct ckrm_core_class *core = class_core(cls); - LIST_HEAD(local_list); - - if (!cls) - return; - - if (!ckrm_validate_and_grab_core(core)) - return; - - class_lock(core); - // we have the core refcnt - if (list_empty(&core->objlist)) { - class_unlock(core); - ckrm_core_drop(core); - return; - } - - INIT_LIST_HEAD(&local_list); - list_splice_init(&core->objlist, &local_list); - class_unlock(core); - ckrm_core_drop(core); - - list_for_each_entry_safe(ns, tns, &local_list, ckrm_link) { - ckrm_ns_hold(ns); - list_del(&ns->ckrm_link); - if (ns->ns_sk) { - lock_sock(ns->ns_sk); - sock_set_class(ns, &sockclass_dflt_class, NULL, CKRM_EVENT_MANUAL); - release_sock(ns->ns_sk); - } - ckrm_ns_put(ns); - } - return ; -} - -void __init -ckrm_meta_init_sockclass(void) -{ - printk("...... Initializing ClassType<%s> ........\n",CT_sockclass.name); - // intialize the default class - ckrm_init_core_class(&CT_sockclass, class_core(&sockclass_dflt_class), - NULL,dflt_sockclass_name); - - // register classtype and initialize default task class - ckrm_register_classtype(&CT_sockclass); - ckrm_register_event_set(sock_events_callbacks); - - // note registeration of all resource controllers will be done later dynamically - // as these are specified as modules -} - - - -#if 1 - -/*************************************************************************************** - * Debugging Network Classes: Utility functions - **************************************************************************************/ - -#endif diff --git a/kernel/ckrm/ckrm_tasks.c b/kernel/ckrm/ckrm_tasks.c deleted file mode 100644 index dcc7ee341..000000000 --- a/kernel/ckrm/ckrm_tasks.c +++ /dev/null @@ -1,509 +0,0 @@ -/* ckrm_numtasks.c - "Number of tasks" resource controller for CKRM - * - * Copyright (C) Chandra Seetharaman, IBM Corp. 2003 - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 31 Mar 2004: Created - * - */ - -/* - * Code Description: TBD - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TOTAL_NUM_TASKS (131072) // 128 K -#define NUMTASKS_DEBUG -#define NUMTASKS_NAME "numtasks" - -typedef struct ckrm_numtasks { - struct ckrm_core_class *core; // the core i am part of... - struct ckrm_core_class *parent; // parent of the core above. - struct ckrm_shares shares; - spinlock_t cnt_lock; // always grab parent's lock first and then child's - int cnt_guarantee; // num_tasks guarantee in local units - int cnt_unused; // has to borrow if more than this is needed - int cnt_limit; // no tasks over this limit. - atomic_t cnt_cur_alloc; // current alloc from self - atomic_t cnt_borrowed; // borrowed from the parent - - int over_guarantee; //turn on/off when cur_alloc goes over/under guarantee - - // internally maintained statictics to compare with max numbers - int limit_failures; // no. of failures 'cause the request was over the limit - int borrow_sucesses; // no. of successful borrows - int borrow_failures; // no. of borrow faileures - - // Maximum the specific statictics has reached. - int max_limit_failures; - int max_borrow_sucesses; - int max_borrow_failures; - - // Total number of specific statistics - int tot_limit_failures; - int tot_borrow_sucesses; - int tot_borrow_failures; -} ckrm_numtasks_t; - -struct ckrm_res_ctlr numtasks_rcbs; - -/* Initialize rescls values - * May be called on each rcfs unmount or as part of error recovery - * to make share values sane. - * Does not traverse hierarchy reinitializing children. - */ -static void -numtasks_res_initcls_one(ckrm_numtasks_t *res) -{ - res->shares.my_guarantee = CKRM_SHARE_DONTCARE; - res->shares.my_limit = CKRM_SHARE_DONTCARE; - res->shares.total_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE; - res->shares.max_limit = CKRM_SHARE_DFLT_MAX_LIMIT; - res->shares.unused_guarantee = CKRM_SHARE_DFLT_TOTAL_GUARANTEE; - res->shares.cur_max_limit = 0; - - res->cnt_guarantee = CKRM_SHARE_DONTCARE; - res->cnt_unused = CKRM_SHARE_DONTCARE; - res->cnt_limit = CKRM_SHARE_DONTCARE; - - res->over_guarantee = 0; - - res->limit_failures = 0; - res->borrow_sucesses = 0; - res->borrow_failures = 0; - - res->max_limit_failures = 0; - res->max_borrow_sucesses = 0; - res->max_borrow_failures = 0; - - res->tot_limit_failures = 0; - res->tot_borrow_sucesses = 0; - res->tot_borrow_failures = 0; - - atomic_set(&res->cnt_cur_alloc, 0); - atomic_set(&res->cnt_borrowed, 0); - return; -} - -#if 0 -static void -numtasks_res_initcls(void *my_res) -{ - ckrm_numtasks_t *res = my_res; - - /* Write a version which propagates values all the way down - and replace rcbs callback with that version */ - -} -#endif - -int -numtasks_get_ref(void *arg, int force) -{ - int rc, resid = numtasks_rcbs.resid; - ckrm_numtasks_t *res; - ckrm_core_class_t *core = arg; - - if ((resid < 0) || (core == NULL)) - return 1; - - res = ckrm_get_res_class(core, resid, ckrm_numtasks_t); - if (res == NULL) - return 1; - - atomic_inc(&res->cnt_cur_alloc); - - rc = 1; - if (((res->parent) && (res->cnt_unused == CKRM_SHARE_DONTCARE)) || - (atomic_read(&res->cnt_cur_alloc) > res->cnt_unused)) { - - rc = 0; - if (!force && (res->cnt_limit != CKRM_SHARE_DONTCARE) && - (atomic_read(&res->cnt_cur_alloc) > res->cnt_limit)) { - res->limit_failures++; - res->tot_limit_failures++; - } else if (res->parent != NULL) { - if ((rc = numtasks_get_ref(res->parent, force)) == 1) { - atomic_inc(&res->cnt_borrowed); - res->borrow_sucesses++; - res->tot_borrow_sucesses++; - res->over_guarantee = 1; - } else { - res->borrow_failures++; - res->tot_borrow_failures++; - } - } else { - rc = force; - } - } else if (res->over_guarantee) { - res->over_guarantee = 0; - - if (res->max_limit_failures < res->limit_failures) { - res->max_limit_failures = res->limit_failures; - } - if (res->max_borrow_sucesses < res->borrow_sucesses) { - res->max_borrow_sucesses = res->borrow_sucesses; - } - if (res->max_borrow_failures < res->borrow_failures) { - res->max_borrow_failures = res->borrow_failures; - } - res->limit_failures = 0; - res->borrow_sucesses = 0; - res->borrow_failures = 0; - } - - if (!rc) { - atomic_dec(&res->cnt_cur_alloc); - } - return rc; -} - -void -numtasks_put_ref(void *arg) -{ - int resid = numtasks_rcbs.resid; - ckrm_numtasks_t *res; - ckrm_core_class_t *core = arg; - - if ((resid == -1) || (core == NULL)) { - return; - } - - res = ckrm_get_res_class(core, resid, ckrm_numtasks_t); - if (res == NULL) - return; - atomic_dec(&res->cnt_cur_alloc); - if (atomic_read(&res->cnt_borrowed) > 0) { - atomic_dec(&res->cnt_borrowed); - numtasks_put_ref(res->parent); - } - return; -} - -static void * -numtasks_res_alloc(struct ckrm_core_class *core, struct ckrm_core_class *parent) -{ - ckrm_numtasks_t *res; - - res = kmalloc(sizeof(ckrm_numtasks_t), GFP_ATOMIC); - - if (res) { - res->core = core; - res->parent = parent; - numtasks_res_initcls_one(res); - res->cnt_lock = SPIN_LOCK_UNLOCKED; - if (parent == NULL) { - // I am part of root class. so set the max tasks to available - // default - res->cnt_guarantee = TOTAL_NUM_TASKS; - res->cnt_unused = TOTAL_NUM_TASKS; - res->cnt_limit = TOTAL_NUM_TASKS; - } - } else { - printk(KERN_ERR "numtasks_res_alloc: failed GFP_ATOMIC alloc\n"); - } - return res; -} - -/* - * No locking of this resource class object necessary as we are not - * supposed to be assigned (or used) when/after this function is called. - */ -static void -numtasks_res_free(void *my_res) -{ - ckrm_numtasks_t *res = my_res, *parres, *childres; - ckrm_core_class_t *child = NULL; - int i, borrowed, maxlimit, resid = numtasks_rcbs.resid; - - if (!res) - return; - - // Assuming there will be no children when this function is called - - parres = ckrm_get_res_class(res->parent, resid, ckrm_numtasks_t); - - if (unlikely(atomic_read(&res->cnt_cur_alloc) != 0 || - atomic_read(&res->cnt_borrowed))) { - printk(KERN_ERR "numtasks_res_free: resource still alloc'd %p\n", res); - if ((borrowed = atomic_read(&res->cnt_borrowed)) > 0) { - for (i = 0; i < borrowed; i++) { - numtasks_put_ref(parres->core); - } - } - } - - // return child's limit/guarantee to parent node - spin_lock(&parres->cnt_lock); - child_guarantee_changed(&parres->shares, res->shares.my_guarantee, 0); - - // run thru parent's children and get the new max_limit of the parent - ckrm_lock_hier(parres->core); - maxlimit = 0; - while ((child = ckrm_get_next_child(parres->core, child)) != NULL) { - childres = ckrm_get_res_class(child, resid, ckrm_numtasks_t); - if (maxlimit < childres->shares.my_limit) { - maxlimit = childres->shares.my_limit; - } - } - ckrm_unlock_hier(parres->core); - if (parres->shares.cur_max_limit < maxlimit) { - parres->shares.cur_max_limit = maxlimit; - } - - spin_unlock(&parres->cnt_lock); - kfree(res); - return; -} -/* - * Recalculate the guarantee and limit in real units... and propagate the - * same to children. - * Caller is responsible for protecting res and for the integrity of parres - */ -static void -recalc_and_propagate(ckrm_numtasks_t *res, ckrm_numtasks_t *parres) -{ - ckrm_core_class_t *child = NULL; - ckrm_numtasks_t *childres; - int resid = numtasks_rcbs.resid; - - if (parres) { - struct ckrm_shares *par = &parres->shares; - struct ckrm_shares *self = &res->shares; - - // calculate cnt_guarantee and cnt_limit - // - if (parres->cnt_guarantee == CKRM_SHARE_DONTCARE) { - res->cnt_guarantee = CKRM_SHARE_DONTCARE; - } else { - res->cnt_guarantee = (self->my_guarantee * parres->cnt_guarantee) - / par->total_guarantee; - } - if (parres->cnt_limit == CKRM_SHARE_DONTCARE) { - res->cnt_limit = CKRM_SHARE_DONTCARE; - } else { - res->cnt_limit = (self->my_limit * parres->cnt_limit) - / par->max_limit; - } - - // Calculate unused units - if (res->cnt_guarantee == CKRM_SHARE_DONTCARE) { - res->cnt_unused = CKRM_SHARE_DONTCARE; - } else { - res->cnt_unused = (self->unused_guarantee * - res->cnt_guarantee) / self->total_guarantee; - } - } - - // propagate to children - ckrm_lock_hier(res->core); - while ((child = ckrm_get_next_child(res->core, child)) != NULL) { - childres = ckrm_get_res_class(child, resid, ckrm_numtasks_t); - - spin_lock(&childres->cnt_lock); - recalc_and_propagate(childres, res); - spin_unlock(&childres->cnt_lock); - } - ckrm_unlock_hier(res->core); - return; -} - -static int -numtasks_set_share_values(void *my_res, struct ckrm_shares *new) -{ - ckrm_numtasks_t *parres, *res = my_res; - struct ckrm_shares *cur = &res->shares, *par; - int rc = -EINVAL, resid = numtasks_rcbs.resid; - - if (!res) - return rc; - - if (res->parent) { - parres = ckrm_get_res_class(res->parent, resid, ckrm_numtasks_t); - spin_lock(&parres->cnt_lock); - spin_lock(&res->cnt_lock); - par = &parres->shares; - } else { - spin_lock(&res->cnt_lock); - par = NULL; - parres = NULL; - } - - rc = set_shares(new, cur, par); - - if ((rc == 0) && parres) { - // Calculate parent's unused units - if (parres->cnt_guarantee == CKRM_SHARE_DONTCARE) { - parres->cnt_unused = CKRM_SHARE_DONTCARE; - } else { - parres->cnt_unused = (par->unused_guarantee * - parres->cnt_guarantee) / par->total_guarantee; - } - - recalc_and_propagate(res, parres); - } - spin_unlock(&res->cnt_lock); - if (res->parent) { - spin_unlock(&parres->cnt_lock); - } - return rc; -} - - -static int -numtasks_get_share_values(void *my_res, struct ckrm_shares *shares) -{ - ckrm_numtasks_t *res = my_res; - - if (!res) - return -EINVAL; - *shares = res->shares; - return 0; -} - -static int -numtasks_get_stats(void *my_res, struct seq_file *sfile) -{ - ckrm_numtasks_t *res = my_res; - - if (!res) - return -EINVAL; - - seq_printf(sfile, "Number of tasks resource:\n"); - seq_printf(sfile, "Total Over limit failures: %d\n", - res->tot_limit_failures); - seq_printf(sfile, "Total Over guarantee sucesses: %d\n", - res->tot_borrow_sucesses); - seq_printf(sfile, "Total Over guarantee failures: %d\n", - res->tot_borrow_failures); - - seq_printf(sfile, "Maximum Over limit failures: %d\n", - res->max_limit_failures); - seq_printf(sfile, "Maximum Over guarantee sucesses: %d\n", - res->max_borrow_sucesses); - seq_printf(sfile, "Maximum Over guarantee failures: %d\n", - res->max_borrow_failures); -#ifdef NUMTASKS_DEBUG - seq_printf(sfile, "cur_alloc %d; borrowed %d; cnt_guar %d; cnt_limit %d " - "unused_guarantee %d, cur_max_limit %d\n", - atomic_read(&res->cnt_cur_alloc), - atomic_read(&res->cnt_borrowed), - res->cnt_guarantee, - res->cnt_limit, - res->shares.unused_guarantee, - res->shares.cur_max_limit); -#endif - - return 0; -} - -static int -numtasks_show_config(void *my_res, struct seq_file *sfile) -{ - ckrm_numtasks_t *res = my_res; - - if (!res) - return -EINVAL; - - seq_printf(sfile, "res=%s,parameter=somevalue\n",NUMTASKS_NAME); - return 0; -} - -static int -numtasks_set_config(void *my_res, const char *cfgstr) -{ - ckrm_numtasks_t *res = my_res; - - if (!res) - return -EINVAL; - printk("numtasks config='%s'\n",cfgstr); - return 0; -} - -static void -numtasks_change_resclass(void *task, void *old, void *new) -{ - ckrm_numtasks_t *oldres = old; - ckrm_numtasks_t *newres = new; - - if (oldres != (void *) -1) { - struct task_struct *tsk = task; - if (!oldres) { - struct ckrm_core_class *old_core = &(tsk->parent->taskclass->core); - oldres = ckrm_get_res_class(old_core, numtasks_rcbs.resid, - ckrm_numtasks_t); - } - numtasks_put_ref(oldres->core); - } - if (newres) { - (void) numtasks_get_ref(newres->core, 1); - } -} - -struct ckrm_res_ctlr numtasks_rcbs = { - .res_name = NUMTASKS_NAME, - .res_hdepth = 1, - .resid = -1, - .res_alloc = numtasks_res_alloc, - .res_free = numtasks_res_free, - .set_share_values = numtasks_set_share_values, - .get_share_values = numtasks_get_share_values, - .get_stats = numtasks_get_stats, - .show_config = numtasks_show_config, - .set_config = numtasks_set_config, - .change_resclass = numtasks_change_resclass, -}; - -int __init -init_ckrm_numtasks_res(void) -{ - struct ckrm_classtype *clstype; - int resid = numtasks_rcbs.resid; - - clstype = ckrm_find_classtype_by_name("taskclass"); - if (clstype == NULL) { - printk(KERN_INFO " Unknown ckrm classtype"); - return -ENOENT; - } - - if (resid == -1) { - resid = ckrm_register_res_ctlr(clstype,&numtasks_rcbs); - printk("........init_ckrm_numtasks_res -> %d\n",resid); - } - return 0; -} - -void __exit -exit_ckrm_numtasks_res(void) -{ - ckrm_unregister_res_ctlr(&numtasks_rcbs); - numtasks_rcbs.resid = -1; -} - -module_init(init_ckrm_numtasks_res) -module_exit(exit_ckrm_numtasks_res) - -EXPORT_SYMBOL(numtasks_get_ref); -EXPORT_SYMBOL(numtasks_put_ref); - -MODULE_LICENSE("GPL"); - diff --git a/kernel/ckrm/ckrm_tc.c b/kernel/ckrm/ckrm_tc.c deleted file mode 100644 index cc0377887..000000000 --- a/kernel/ckrm/ckrm_tc.c +++ /dev/null @@ -1,785 +0,0 @@ -/* ckrm_tc.c - Class-based Kernel Resource Management (CKRM) - * - * Copyright (C) Hubertus Franke, IBM Corp. 2003,2004 - * (C) Shailabh Nagar, IBM Corp. 2003 - * (C) Chandra Seetharaman, IBM Corp. 2003 - * (C) Vivek Kashyap, IBM Corp. 2004 - * - * - * Provides kernel API of CKRM for in-kernel,per-resource controllers - * (one each for cpu, memory, io, network) and callbacks for - * classification modules. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 28 Aug 2003 - * Created. - * 06 Nov 2003 - * Made modifications to suit the new RBCE module. - * 10 Nov 2003 - * Fixed a bug in fork and exit callbacks. Added callbacks_active and - * surrounding logic. Added task paramter for all CE callbacks. - * 23 Mar 2004 - * moved to referenced counted class objects and correct locking - * 12 Apr 2004 - * introduced adopted to emerging classtype interface - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - - -#define TC_DEBUG(fmt, args...) do { /* printk("%s: " fmt, __FUNCTION__ , ## args); */ } while (0) - - -static struct ckrm_task_class taskclass_dflt_class = { -}; - -const char *dflt_taskclass_name = TASK_CLASS_TYPE_NAME; - -static struct ckrm_core_class *ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name); -static int ckrm_free_task_class(struct ckrm_core_class *core); - -static int tc_forced_reclassify(ckrm_core_class_t *target, const char *resname); -static int tc_show_members(struct ckrm_core_class *core, struct seq_file *seq); -static void tc_add_resctrl(struct ckrm_core_class *core, int resid); - -struct ckrm_classtype CT_taskclass = { - .mfidx = TC_MF_IDX, - .name = TASK_CLASS_TYPE_NAME, - .typeID = CKRM_CLASSTYPE_TASK_CLASS, - .maxdepth = 3, // Hubertus .. just to start - .resid_reserved = 4, // Hubertus .. reservation - .max_res_ctlrs = CKRM_MAX_RES_CTLRS, - .max_resid = 0, - .bit_res_ctlrs = 0L, - .res_ctlrs_lock = SPIN_LOCK_UNLOCKED, - .classes = LIST_HEAD_INIT(CT_taskclass.classes), - - .default_class = &taskclass_dflt_class.core, - - // private version of functions - .alloc = &ckrm_alloc_task_class, - .free = &ckrm_free_task_class, - .show_members = &tc_show_members, - .forced_reclassify = &tc_forced_reclassify, - - // use of default functions - .show_shares = &ckrm_class_show_shares, - .show_stats = &ckrm_class_show_stats, - .show_config = &ckrm_class_show_config, - .set_config = &ckrm_class_set_config, - .set_shares = &ckrm_class_set_shares, - .reset_stats = &ckrm_class_reset_stats, - - // mandatory private version .. no dflt available - .add_resctrl = &tc_add_resctrl, -}; - -/************************************************************************** - * Helper Functions * - **************************************************************************/ - -static inline void -ckrm_init_task_lock(struct task_struct *tsk) -{ - tsk->ckrm_tsklock = SPIN_LOCK_UNLOCKED; -} - -// Hubertus .. following functions should move to ckrm_rc.h - -static inline void -ckrm_task_lock(struct task_struct *tsk) -{ - spin_lock(&tsk->ckrm_tsklock); -} - -static inline void -ckrm_task_unlock(struct task_struct *tsk) -{ - spin_unlock(&tsk->ckrm_tsklock); -} - -/* - * Change the task class of the given task. - * - * Change the task's task class to "newcls" if the task's current - * class (task->taskclass) is same as given "oldcls", if it is non-NULL. - * - * Caller is responsible to make sure the task structure stays put through - * this function. - * - * This function should be called with the following locks NOT held - * - tsk->ckrm_task_lock - * - core->ckrm_lock, if core is NULL then ckrm_dflt_class.ckrm_lock - * - tsk->taskclass->ckrm_lock - * - * Function is also called with a ckrm_core_grab on the new core, hence - * it needs to be dropped if no assignment takes place. - */ - -static void -ckrm_set_taskclass(struct task_struct *tsk, ckrm_task_class_t *newcls, - ckrm_task_class_t *oldcls, enum ckrm_event event) -{ - int i; - ckrm_classtype_t *clstype; - ckrm_res_ctlr_t *rcbs; - ckrm_task_class_t *curcls; - void *old_res_class, *new_res_class; - int drop_old_cls; - - ckrm_task_lock(tsk); - curcls = tsk->taskclass; - - // check whether compare_and_exchange should - if (oldcls && (oldcls != curcls)) { - ckrm_task_unlock(tsk); - if (newcls) { - /* compensate for previous grab */ - TC_DEBUG("(%s:%d): Race-condition caught <%s> %d\n", - tsk->comm,tsk->pid,class_core(newcls)->name,event); - ckrm_core_drop(class_core(newcls)); - } - return; - } - - // make sure we have a real destination core - if (!newcls) { - newcls = &taskclass_dflt_class; - ckrm_core_grab(class_core(newcls)); - } - - // take out of old class - // remember that we need to drop the oldcore - if ((drop_old_cls = (curcls != NULL))) { - class_lock(class_core(curcls)); - if (newcls == curcls) { - // we are already in the destination class. - // we still need to drop oldcore - class_unlock(class_core(curcls)); - ckrm_task_unlock(tsk); - goto out; - } - list_del(&tsk->taskclass_link); - INIT_LIST_HEAD(&tsk->taskclass_link); - tsk->taskclass = NULL; - class_unlock(class_core(curcls)); - } - - // put into new class - class_lock(class_core(newcls)); - tsk->taskclass = newcls; - list_add(&tsk->taskclass_link, &class_core(newcls)->objlist); - class_unlock(class_core(newcls)); - - if (newcls == curcls) { - ckrm_task_unlock(tsk); - goto out; - } - - CE_NOTIFY(&CT_taskclass,event,newcls,tsk); - - ckrm_task_unlock(tsk); - - clstype = class_isa(newcls); // Hubertus .. can hardcode ckrm_CT_taskclass - if (clstype->bit_res_ctlrs) { // avoid running through the entire list if non is registered - for (i = 0; i < clstype->max_resid; i++) { - if (clstype->res_ctlrs[i] == NULL) - continue; - atomic_inc(&clstype->nr_resusers[i]); - old_res_class = curcls ? class_core(curcls)->res_class[i] : NULL; - new_res_class = newcls ? class_core(newcls)->res_class[i] : NULL; - rcbs = clstype->res_ctlrs[i]; - if (rcbs && rcbs->change_resclass && (old_res_class != new_res_class)) - (*rcbs->change_resclass)(tsk, old_res_class, new_res_class); - atomic_dec(&clstype->nr_resusers[i]); - } - } - - out: - if (drop_old_cls) - ckrm_core_drop(class_core(curcls)); - return; -} - -// HF SUGGEST: we could macro-tize this for other types DEF_FUNC_ADD_RESCTRL(funcname,link) -// would DEF_FUNC_ADD_RESCTRL(tc_add_resctrl,taskclass_link) - -static void -tc_add_resctrl(struct ckrm_core_class *core, int resid) -{ - struct task_struct *tsk; - struct ckrm_res_ctlr *rcbs; - - if ((resid < 0) || (resid >= CKRM_MAX_RES_CTLRS) || ((rcbs = core->classtype->res_ctlrs[resid]) == NULL)) - return; - - class_lock(core); - list_for_each_entry(tsk, &core->objlist, taskclass_link) { - if (rcbs->change_resclass) - (*rcbs->change_resclass)(tsk, (void *) -1, core->res_class[resid]); - } - class_unlock(core); -} - - -/************************************************************************** - * Functions called from classification points * - **************************************************************************/ - -#define ECB_PRINTK(fmt, args...) // do { if (CT_taskclass.ce_regd) printk("%s: " fmt, __FUNCTION__ , ## args); } while (0) - -#define CE_CLASSIFY_TASK(event, tsk) \ -do { \ - struct ckrm_task_class *newcls = NULL, *oldcls = tsk->taskclass; \ - \ - CE_CLASSIFY_RET(newcls,&CT_taskclass,event,tsk); \ - if (newcls) { \ - /* called synchrously. no need to get task struct */ \ - ckrm_set_taskclass(tsk, newcls, oldcls, event); \ - } \ -} while (0) - -#define CE_CLASSIFY_TASK_PROTECT(event, tsk) \ -do { \ - ce_protect(&CT_taskclass); \ - CE_CLASSIFY_TASK(event,tsk); \ - ce_release(&CT_taskclass); \ -} while (0) - - - - -static void -cb_taskclass_newtask(struct task_struct *tsk) -{ - tsk->taskclass = NULL; - INIT_LIST_HEAD(&tsk->taskclass_link); -} - - -static void -cb_taskclass_fork(struct task_struct *tsk) -{ - struct ckrm_task_class *cls = NULL; - - ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm); - - ce_protect(&CT_taskclass); - CE_CLASSIFY_RET(cls,&CT_taskclass,CKRM_EVENT_FORK,tsk); - if (cls == NULL) { - ckrm_task_lock(tsk->parent); - cls = tsk->parent->taskclass; - ckrm_core_grab(class_core(cls)); - ckrm_task_unlock(tsk->parent); - } - if (!list_empty(&tsk->taskclass_link)) - printk("BUG in cb_fork.. tsk (%s:%d> already linked\n", - tsk->comm,tsk->pid); - - ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_FORK); - ce_release(&CT_taskclass); -} - -static void -cb_taskclass_exit(struct task_struct *tsk) -{ - ckrm_task_class_t *cls; - - // Remove the task from the current core class - - ECB_PRINTK("%p:%d:%s\n",tsk,tsk->pid,tsk->comm); - ckrm_task_lock(tsk); - - CE_CLASSIFY_NORET( &CT_taskclass, CKRM_EVENT_EXIT, tsk); - - if ((cls = tsk->taskclass) != NULL) { - class_lock(class_core(cls)); - tsk->taskclass = NULL; - list_del(&tsk->taskclass_link); - class_unlock(class_core(cls)); - ckrm_core_drop(class_core(cls)); - } else { - INIT_LIST_HEAD(&tsk->taskclass_link); - } - ckrm_task_unlock(tsk); -} - -static void -cb_taskclass_exec(const char *filename) -{ - ECB_PRINTK("%p:%d:%s <%s>\n",current,current->pid,current->comm,filename); - CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_EXEC, current); -} - -static void -cb_taskclass_uid(void) -{ - ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm); - CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_UID, current); -} - -static void -cb_taskclass_gid(void) -{ - ECB_PRINTK("%p:%d:%s\n",current,current->pid,current->comm); - CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_GID, current); -} - -static struct ckrm_event_spec taskclass_events_callbacks[] = { - CKRM_EVENT_SPEC( NEWTASK, cb_taskclass_newtask ), - CKRM_EVENT_SPEC( EXEC , cb_taskclass_exec ), - CKRM_EVENT_SPEC( FORK , cb_taskclass_fork ), - CKRM_EVENT_SPEC( EXIT , cb_taskclass_exit ), - CKRM_EVENT_SPEC( UID , cb_taskclass_uid ), - CKRM_EVENT_SPEC( GID , cb_taskclass_gid ), - { -1 } -}; - -/*********************************************************************** - * - * Asynchronous callback functions (driven by RCFS) - * - * Async functions force a setting of the task structure - * synchronous callbacks are protected against race conditions - * by using a cmpxchg on the core before setting it. - * Async calls need to be serialized to ensure they can't - * race against each other - * - ***********************************************************************/ - -DECLARE_MUTEX(async_serializer); // serialize all async functions - - -/* - * Go through the task list and reclassify all tasks according to the current - * classification rules. - * - * We have the problem that we can not hold any lock (including the - * tasklist_lock) while classifying. Two methods possible - * - * (a) go through entire pidrange (0..pidmax) and if a task exists at - * that pid then reclassify it - * (b) go several time through task list and build a bitmap for a particular - * subrange of pid otherwise the memory requirements ight be too much. - * - * We use a hybrid by comparing ratio nr_threads/pidmax - */ - -static void -ckrm_reclassify_all_tasks(void) -{ - extern int pid_max; - - struct task_struct *proc, *thread; - int i; - int curpidmax = pid_max; - int ratio; - int use_bitmap; - - - ratio = curpidmax / nr_threads; - if (curpidmax <= PID_MAX_DEFAULT) { - use_bitmap = 1; - } else { - use_bitmap = (ratio >= 2); - } - - ce_protect(&CT_taskclass); - - retry: - if (use_bitmap == 0) { - // go through it in one walk - read_lock(&tasklist_lock); - for ( i=0 ; ipid; - if ((pid < pid_start) || (pid >= pid_end)) { - if (pid >= pid_end) { - do_next = 1; - } - continue; - } - pid -= pid_start; - set_bit(pid, bitmap); - num_found++; - } while_each_thread(proc, thread); - read_unlock(&tasklist_lock); - - if (num_found == 0) - continue; - - pos = 0; - for ( ; num_found-- ; ) { - pos = find_next_bit(bitmap, bitmapsize, pos); - pid = pos + pid_start; - - read_lock(&tasklist_lock); - if ((thread = find_task_by_pid(pid)) != NULL) { - get_task_struct(thread); - read_unlock(&tasklist_lock); - CE_CLASSIFY_TASK(CKRM_EVENT_RECLASSIFY, thread); - put_task_struct(thread); - } else { - read_unlock(&tasklist_lock); - } - } - } - - } - ce_release(&CT_taskclass); -} - -int -ckrm_reclassify(int pid) -{ - struct task_struct *tsk; - int rc = 0; - - down(&async_serializer); // protect again race condition - if (pid < 0) { - // do we want to treat this as process group .. should YES ToDo - rc = -EINVAL; - } else if (pid == 0) { - // reclassify all tasks in the system - ckrm_reclassify_all_tasks(); - } else { - // reclassify particular pid - read_lock(&tasklist_lock); - if ((tsk = find_task_by_pid(pid)) != NULL) { - get_task_struct(tsk); - read_unlock(&tasklist_lock); - CE_CLASSIFY_TASK_PROTECT(CKRM_EVENT_RECLASSIFY, tsk); - put_task_struct(tsk); - } else { - read_unlock(&tasklist_lock); - rc = -EINVAL; - } - } - up(&async_serializer); - return rc; -} - -/* - * Reclassify all tasks in the given core class. - */ - -static void -ckrm_reclassify_class_tasks(struct ckrm_task_class *cls) -{ - int ce_regd; - struct ckrm_hnode *cnode; - struct ckrm_task_class *parcls; - int num = 0; - - if (!ckrm_validate_and_grab_core(&cls->core)) - return; - - down(&async_serializer); // protect again race condition - - - TC_DEBUG("start %p:%s:%d:%d\n",cls,cls->core.name, - atomic_read(&cls->core.refcnt),atomic_read(&cls->core.hnode.parent->refcnt)); - // If no CE registered for this classtype, following will be needed repeatedly; - ce_regd = class_core(cls)->classtype->ce_regd; - cnode = &(class_core(cls)->hnode); - parcls = class_type(ckrm_task_class_t, cnode->parent); - -next_task: - class_lock(class_core(cls)); - if (!list_empty(&class_core(cls)->objlist)) { - struct ckrm_task_class *newcls = NULL; - struct task_struct *tsk = - list_entry(class_core(cls)->objlist.next, - struct task_struct, taskclass_link); - - get_task_struct(tsk); - class_unlock(class_core(cls)); - - if (ce_regd) { - CE_CLASSIFY_RET(newcls,&CT_taskclass,CKRM_EVENT_RECLASSIFY,tsk); - if (cls == newcls) { - // don't allow reclassifying to the same class - // as we are in the process of cleaning up this class - ckrm_core_drop(class_core(newcls)); // to compensate CE's grab - newcls = NULL; - } - } - if (newcls == NULL) { - newcls = parcls; - ckrm_core_grab(class_core(newcls)); - } - ckrm_set_taskclass(tsk, newcls, cls, CKRM_EVENT_RECLASSIFY); - put_task_struct(tsk); - num++; - goto next_task; - } - TC_DEBUG("stop %p:%s:%d:%d %d\n",cls,cls->core.name, - atomic_read(&cls->core.refcnt),atomic_read(&cls->core.hnode.parent->refcnt),num); - class_unlock(class_core(cls)); - ckrm_core_drop(class_core(cls)); - - up(&async_serializer); - - return ; -} - -/* - * Change the core class of the given task. - */ - -int -ckrm_forced_reclassify_pid(pid_t pid, struct ckrm_task_class *cls) -{ - struct task_struct *tsk; - - if (!ckrm_validate_and_grab_core(class_core(cls))) - return - EINVAL; - - read_lock(&tasklist_lock); - if ((tsk = find_task_by_pid(pid)) == NULL) { - read_unlock(&tasklist_lock); - ckrm_core_drop(class_core(cls)); - return -EINVAL; - } - get_task_struct(tsk); - read_unlock(&tasklist_lock); - - down(&async_serializer); // protect again race condition - - ce_protect(&CT_taskclass); - ckrm_set_taskclass(tsk, cls, NULL, CKRM_EVENT_MANUAL); - ce_release(&CT_taskclass); - put_task_struct(tsk); - - up(&async_serializer); - return 0; -} - -static struct ckrm_core_class * -ckrm_alloc_task_class(struct ckrm_core_class *parent, const char *name) -{ - struct ckrm_task_class *taskcls; - taskcls = kmalloc(sizeof(struct ckrm_task_class), GFP_KERNEL); - if (taskcls == NULL) - return NULL; - - ckrm_init_core_class(&CT_taskclass, - class_core(taskcls),parent,name); - - ce_protect(&CT_taskclass); - if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_add) - (*CT_taskclass.ce_callbacks.class_add)(name,taskcls); - ce_release(&CT_taskclass); - - return class_core(taskcls); -} - -static int -ckrm_free_task_class(struct ckrm_core_class *core) -{ - struct ckrm_task_class *taskcls; - - if (!ckrm_is_core_valid(core)) { - // Invalid core - return (-EINVAL); - } - if (core == core->classtype->default_class) { - // reset the name tag - core->name = dflt_taskclass_name; - return 0; - } - - TC_DEBUG("%p:%s:%d\n",core,core->name,atomic_read(&core->refcnt)); - - taskcls = class_type(struct ckrm_task_class, core); - - ce_protect(&CT_taskclass); - - if (CT_taskclass.ce_cb_active && CT_taskclass.ce_callbacks.class_delete) - (*CT_taskclass.ce_callbacks.class_delete)(core->name,taskcls); - ckrm_reclassify_class_tasks( taskcls ); - - ce_release(&CT_taskclass); - - ckrm_release_core_class(core); // Hubertus .... could just drop the class .. error message - return 0; -} - - -void __init -ckrm_meta_init_taskclass(void) -{ - printk("...... Initializing ClassType<%s> ........\n",CT_taskclass.name); - // intialize the default class - ckrm_init_core_class(&CT_taskclass, class_core(&taskclass_dflt_class), - NULL,dflt_taskclass_name); - - // register classtype and initialize default task class - ckrm_register_classtype(&CT_taskclass); - ckrm_register_event_set(taskclass_events_callbacks); - - // note registeration of all resource controllers will be done later dynamically - // as these are specified as modules -} - - - -static int -tc_show_members(struct ckrm_core_class *core, struct seq_file *seq) -{ - struct list_head *lh; - struct task_struct *tsk; - - class_lock(core); - list_for_each(lh, &core->objlist) { - tsk = container_of(lh, struct task_struct, taskclass_link); - seq_printf(seq,"%ld\n", (long)tsk->pid); - } - class_unlock(core); - - return 0; -} - -static int -tc_forced_reclassify(struct ckrm_core_class *target,const char *obj) -{ - pid_t pid; - int rc = -EINVAL; - - pid = (pid_t) simple_strtoul(obj,NULL,10); - if (pid > 0) { - rc = ckrm_forced_reclassify_pid(pid, - class_type(ckrm_task_class_t,target)); - } - return rc; -} - -#if 1 - -/*************************************************************************************** - * Debugging Task Classes: Utility functions - **************************************************************************************/ - -void -check_tasklist_sanity(struct ckrm_task_class *cls) -{ - struct ckrm_core_class *core = class_core(cls); - struct list_head *lh1, *lh2; - int count = 0; - - if (core) { - class_lock(core); - if (list_empty(&core->objlist)) { - class_lock(core); - printk("check_tasklist_sanity: class %s empty list\n", - core->name); - return; - } - list_for_each_safe(lh1, lh2, &core->objlist) { - struct task_struct *tsk = container_of(lh1, struct task_struct, taskclass_link); - if (count++ > 20000) { - printk("list is CORRUPTED\n"); - break; - } - if (tsk->taskclass != cls) { - const char *tclsname; - tclsname = (tsk->taskclass) ? class_core(tsk->taskclass)->name - : "NULL"; - printk("sanity: task %s:%d has ckrm_core |%s| but in list |%s|\n", - tsk->comm,tsk->pid,tclsname,core->name); - } - } - class_unlock(core); - } -} - -void -ckrm_debug_free_task_class(struct ckrm_task_class *tskcls) -{ - struct task_struct *proc, *thread; - int count = 0; - - printk("Analyze Error <%s> %d\n", - class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt))); - - read_lock(&tasklist_lock); - class_lock(class_core(tskcls)); - do_each_thread(proc, thread) { - count += (tskcls == thread->taskclass); - if ((thread->taskclass == tskcls) || (tskcls == NULL)) { - const char *tclsname; - tclsname = (thread->taskclass) ? class_core(thread->taskclass)->name : "NULL"; - printk("%d thread=<%s:%d> -> <%s> <%lx>\n", - count,thread->comm,thread->pid,tclsname, thread->flags & PF_EXITING); - } - } while_each_thread(proc, thread); - class_unlock(class_core(tskcls)); - read_unlock(&tasklist_lock); - - printk("End Analyze Error <%s> %d\n", - class_core(tskcls)->name,atomic_read(&(class_core(tskcls)->refcnt))); -} - -#endif diff --git a/kernel/ckrm/ckrmutils.c b/kernel/ckrm/ckrmutils.c deleted file mode 100644 index c0d873cb4..000000000 --- a/kernel/ckrm/ckrmutils.c +++ /dev/null @@ -1,207 +0,0 @@ -/* ckrmutils.c - Utility functions for CKRM - * - * Copyright (C) Chandra Seetharaman, IBM Corp. 2003 - * (C) Hubertus Franke , IBM Corp. 2004 - * - * Provides simple utility functions for the core module, CE and resource - * controllers. - * - * Latest version, more details at http://ckrm.sf.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/* Changes - * - * 13 Nov 2003 - * Created - */ - -#include -#include -#include -#include -#include - -int -get_exe_path_name(struct task_struct *tsk, char *buf, int buflen) -{ - struct vm_area_struct * vma; - struct vfsmount *mnt; - struct mm_struct * mm = get_task_mm(tsk); - struct dentry *dentry; - char *lname; - int rc = 0; - - *buf = '\0'; - if (!mm) { - return -EINVAL; - } - - down_read(&mm->mmap_sem); - vma = mm->mmap; - while (vma) { - if ((vma->vm_flags & VM_EXECUTABLE) && - vma->vm_file) { - dentry = dget(vma->vm_file->f_dentry); - mnt = mntget(vma->vm_file->f_vfsmnt); - lname = d_path(dentry, mnt, buf, buflen); - if (! IS_ERR(lname)) { - strncpy(buf, lname, strlen(lname) + 1); - } else { - rc = (int) PTR_ERR(lname); - } - mntput(mnt); - dput(dentry); - break; - } - vma = vma->vm_next; - } - up_read(&mm->mmap_sem); - mmput(mm); - return rc; -} - - -/* - * must be called with cnt_lock of parres held - * Caller is responsible for making sure that the new guarantee doesn't - * overflow parent's total guarantee. - */ -void -child_guarantee_changed(struct ckrm_shares *parent, int cur, int new) -{ - if (new == cur || !parent) { - return; - } - if (new != CKRM_SHARE_DONTCARE) { - parent->unused_guarantee -= new; - } - if (cur != CKRM_SHARE_DONTCARE) { - parent->unused_guarantee += cur; - } - return; -} - -/* - * must be called with cnt_lock of parres held - * Caller is responsible for making sure that the new limit is not more - * than parent's max_limit - */ -void -child_maxlimit_changed(struct ckrm_shares *parent, int new_limit) -{ - if (parent && parent->cur_max_limit < new_limit) { - parent->cur_max_limit = new_limit; - } - return; -} - -/* - * Caller is responsible for holding any lock to protect the data - * structures passed to this function - */ -int -set_shares(struct ckrm_shares *new, struct ckrm_shares *cur, - struct ckrm_shares *par) -{ - int rc = -EINVAL; - int cur_usage_guar = cur->total_guarantee - cur->unused_guarantee; - int increase_by = new->my_guarantee - cur->my_guarantee; - - // Check total_guarantee for correctness - if (new->total_guarantee <= CKRM_SHARE_DONTCARE) { - goto set_share_err; - } else if (new->total_guarantee == CKRM_SHARE_UNCHANGED) { - ;// do nothing - } else if (cur_usage_guar > new->total_guarantee) { - goto set_share_err; - } - - // Check max_limit for correctness - if (new->max_limit <= CKRM_SHARE_DONTCARE) { - goto set_share_err; - } else if (new->max_limit == CKRM_SHARE_UNCHANGED) { - ; // do nothing - } else if (cur->cur_max_limit > new->max_limit) { - goto set_share_err; - } - - // Check my_guarantee for correctness - if (new->my_guarantee == CKRM_SHARE_UNCHANGED) { - ; // do nothing - } else if (new->my_guarantee == CKRM_SHARE_DONTCARE) { - ; // do nothing - } else if (par && increase_by > par->unused_guarantee) { - goto set_share_err; - } - - // Check my_limit for correctness - if (new->my_limit == CKRM_SHARE_UNCHANGED) { - ; // do nothing - } else if (new->my_limit == CKRM_SHARE_DONTCARE) { - ; // do nothing - } else if (par && new->my_limit > par->max_limit) { - // I can't get more limit than my parent's limit - goto set_share_err; - - } - - // make sure guarantee is lesser than limit - if (new->my_limit == CKRM_SHARE_DONTCARE) { - ; // do nothing - } else if (new->my_limit == CKRM_SHARE_UNCHANGED) { - if (new->my_guarantee == CKRM_SHARE_DONTCARE) { - ; // do nothing - } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) { - ; // do nothing earlier setting would 've taken care of it - } else if (new->my_guarantee > cur->my_limit) { - goto set_share_err; - } - } else { // new->my_limit has a valid value - if (new->my_guarantee == CKRM_SHARE_DONTCARE) { - ; // do nothing - } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) { - if (cur->my_guarantee > new->my_limit) { - goto set_share_err; - } - } else if (new->my_guarantee > new->my_limit) { - goto set_share_err; - } - } - - if (new->my_guarantee != CKRM_SHARE_UNCHANGED) { - child_guarantee_changed(par, cur->my_guarantee, - new->my_guarantee); - cur->my_guarantee = new->my_guarantee; - } - - if (new->my_limit != CKRM_SHARE_UNCHANGED) { - child_maxlimit_changed(par, new->my_limit); - cur->my_limit = new->my_limit; - } - - if (new->total_guarantee != CKRM_SHARE_UNCHANGED) { - cur->unused_guarantee = new->total_guarantee - cur_usage_guar; - cur->total_guarantee = new->total_guarantee; - } - - if (new->max_limit != CKRM_SHARE_UNCHANGED) { - cur->max_limit = new->max_limit; - } - - rc = 0; -set_share_err: - return rc; -} - -EXPORT_SYMBOL(get_exe_path_name); -EXPORT_SYMBOL(child_guarantee_changed); -EXPORT_SYMBOL(child_maxlimit_changed); -EXPORT_SYMBOL(set_shares); - - diff --git a/mm/mempolicy.c b/mm/mempolicy.c deleted file mode 100644 index a62a65c2e..000000000 --- a/mm/mempolicy.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Simple NUMA memory policy for the Linux kernel. - * - * Copyright 2003,2004 Andi Kleen, SuSE Labs. - * Subject to the GNU Public License, version 2. - * - * NUMA policy allows the user to give hints in which node(s) memory should - * be allocated. - * - * Support four policies per VMA and per process: - * - * The VMA policy has priority over the process policy for a page fault. - * - * interleave Allocate memory interleaved over a set of nodes, - * with normal fallback if it fails. - * For VMA based allocations this interleaves based on the - * offset into the backing object or offset into the mapping - * for anonymous memory. For process policy an process counter - * is used. - * bind Only allocate memory on a specific set of nodes, - * no fallback. - * preferred Try a specific node first before normal fallback. - * As a special case node -1 here means do the allocation - * on the local CPU. This is normally identical to default, - * but useful to set in a VMA when you have a non default - * process policy. - * default Allocate on the local node first, or when on a VMA - * use the process policy. This is what Linux always did - * in a NUMA aware kernel and still does by, ahem, default. - * - * The process policy is applied for most non interrupt memory allocations - * in that process' context. Interrupts ignore the policies and always - * try to allocate on the local CPU. The VMA policy is only applied for memory - * allocations for a VMA in the VM. - * - * Currently there are a few corner cases in swapping where the policy - * is not applied, but the majority should be handled. When process policy - * is used it is not remembered over swap outs/swap ins. - * - * Only the highest zone in the zone hierarchy gets policied. Allocations - * requesting a lower zone just use default policy. This implies that - * on systems with highmem kernel lowmem allocation don't get policied. - * Same with GFP_DMA allocations. - * - * For shmfs/tmpfs/hugetlbfs shared memory the policy is shared between - * all users and remembered even when nobody has memory mapped. - */ - -/* Notebook: - fix mmap readahead to honour policy and enable policy for any page cache - object - statistics for bigpages - global policy for page cache? currently it uses process policy. Requires - first item above. - handle mremap for shared memory (currently ignored for the policy) - grows down? - make bind policy root only? It can trigger oom much faster and the - kernel is not always grateful with that. - could replace all the switch()es with a mempolicy_ops structure. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static kmem_cache_t *policy_cache; -static kmem_cache_t *sn_cache; - -#define PDprintk(fmt...) - -/* Highest zone. An specific allocation for a zone below that is not - policied. */ -static int policy_zone; - -static struct mempolicy default_policy = { - .refcnt = ATOMIC_INIT(1), /* never free it */ - .policy = MPOL_DEFAULT, -}; - -/* Check if all specified nodes are online */ -static int nodes_online(unsigned long *nodes) -{ - DECLARE_BITMAP(offline, MAX_NUMNODES); - - bitmap_copy(offline, node_online_map, MAX_NUMNODES); - if (bitmap_empty(offline, MAX_NUMNODES)) - set_bit(0, offline); - bitmap_complement(offline, MAX_NUMNODES); - bitmap_and(offline, offline, nodes, MAX_NUMNODES); - if (!bitmap_empty(offline, MAX_NUMNODES)) - return -EINVAL; - return 0; -} - -/* Do sanity checking on a policy */ -static int mpol_check_policy(int mode, unsigned long *nodes) -{ - int empty = bitmap_empty(nodes, MAX_NUMNODES); - - switch (mode) { - case MPOL_DEFAULT: - if (!empty) - return -EINVAL; - break; - case MPOL_BIND: - case MPOL_INTERLEAVE: - /* Preferred will only use the first bit, but allow - more for now. */ - if (empty) - return -EINVAL; - break; - } - return nodes_online(nodes); -} - -/* Copy a node mask from user space. */ -static int get_nodes(unsigned long *nodes, unsigned long __user *nmask, - unsigned long maxnode, int mode) -{ - unsigned long k; - unsigned long nlongs; - unsigned long endmask; - - --maxnode; - nlongs = BITS_TO_LONGS(maxnode); - if ((maxnode % BITS_PER_LONG) == 0) - endmask = ~0UL; - else - endmask = (1UL << (maxnode % BITS_PER_LONG)) - 1; - - /* When the user specified more nodes than supported just check - if the non supported part is all zero. */ - if (nmask && nlongs > BITS_TO_LONGS(MAX_NUMNODES)) { - for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) { - unsigned long t; - if (get_user(t, nmask + k)) - return -EFAULT; - if (k == nlongs - 1) { - if (t & endmask) - return -EINVAL; - } else if (t) - return -EINVAL; - } - nlongs = BITS_TO_LONGS(MAX_NUMNODES); - endmask = ~0UL; - } - - bitmap_zero(nodes, MAX_NUMNODES); - if (nmask && copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) - return -EFAULT; - nodes[nlongs-1] &= endmask; - return mpol_check_policy(mode, nodes); -} - -/* Generate a custom zonelist for the BIND policy. */ -static struct zonelist *bind_zonelist(unsigned long *nodes) -{ - struct zonelist *zl; - int num, max, nd; - - max = 1 + MAX_NR_ZONES * bitmap_weight(nodes, MAX_NUMNODES); - zl = kmalloc(sizeof(void *) * max, GFP_KERNEL); - if (!zl) - return NULL; - num = 0; - for (nd = find_first_bit(nodes, MAX_NUMNODES); - nd < MAX_NUMNODES; - nd = find_next_bit(nodes, MAX_NUMNODES, 1+nd)) { - int k; - for (k = MAX_NR_ZONES-1; k >= 0; k--) { - struct zone *z = &NODE_DATA(nd)->node_zones[k]; - if (!z->present_pages) - continue; - zl->zones[num++] = z; - if (k > policy_zone) - policy_zone = k; - } - } - BUG_ON(num >= max); - zl->zones[num] = NULL; - return zl; -} - -/* Create a new policy */ -static struct mempolicy *mpol_new(int mode, unsigned long *nodes) -{ - struct mempolicy *policy; - - PDprintk("setting mode %d nodes[0] %lx\n", mode, nodes[0]); - if (mode == MPOL_DEFAULT) - return NULL; - policy = kmem_cache_alloc(policy_cache, GFP_KERNEL); - if (!policy) - return ERR_PTR(-ENOMEM); - atomic_set(&policy->refcnt, 1); - switch (mode) { - case MPOL_INTERLEAVE: - bitmap_copy(policy->v.nodes, nodes, MAX_NUMNODES); - break; - case MPOL_PREFERRED: - policy->v.preferred_node = find_first_bit(nodes, MAX_NUMNODES); - if (policy->v.preferred_node >= MAX_NUMNODES) - policy->v.preferred_node = -1; - break; - case MPOL_BIND: - policy->v.zonelist = bind_zonelist(nodes); - if (policy->v.zonelist == NULL) { - kmem_cache_free(policy_cache, policy); - return ERR_PTR(-ENOMEM); - } - break; - } - policy->policy = mode; - return policy; -} - -/* Ensure all existing pages follow the policy. */ -static int -verify_pages(unsigned long addr, unsigned long end, unsigned long *nodes) -{ - while (addr < end) { - struct page *p; - pte_t *pte; - pmd_t *pmd; - pgd_t *pgd = pgd_offset_k(addr); - if (pgd_none(*pgd)) { - addr = (addr + PGDIR_SIZE) & PGDIR_MASK; - continue; - } - pmd = pmd_offset(pgd, addr); - if (pmd_none(*pmd)) { - addr = (addr + PMD_SIZE) & PMD_MASK; - continue; - } - p = NULL; - pte = pte_offset_map(pmd, addr); - if (pte_present(*pte)) - p = pte_page(*pte); - pte_unmap(pte); - if (p) { - unsigned nid = page_to_nid(p); - if (!test_bit(nid, nodes)) - return -EIO; - } - addr += PAGE_SIZE; - } - return 0; -} - -/* Step 1: check the range */ -static struct vm_area_struct * -check_range(struct mm_struct *mm, unsigned long start, unsigned long end, - unsigned long *nodes, unsigned long flags) -{ - int err; - struct vm_area_struct *first, *vma, *prev; - - first = find_vma(mm, start); - if (!first) - return ERR_PTR(-EFAULT); - prev = NULL; - for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) { - if (!vma->vm_next && vma->vm_end < end) - return ERR_PTR(-EFAULT); - if (prev && prev->vm_end < vma->vm_start) - return ERR_PTR(-EFAULT); - if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) { - err = verify_pages(vma->vm_start, vma->vm_end, nodes); - if (err) { - first = ERR_PTR(err); - break; - } - } - prev = vma; - } - return first; -} - -/* Apply policy to a single VMA */ -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) -{ - int err = 0; - struct mempolicy *old = vma->vm_policy; - - PDprintk("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff, - vma->vm_ops, vma->vm_file, - vma->vm_ops ? vma->vm_ops->set_policy : NULL); - - if (vma->vm_ops && vma->vm_ops->set_policy) - err = vma->vm_ops->set_policy(vma, new); - if (!err) { - mpol_get(new); - vma->vm_policy = new; - mpol_free(old); - } - return err; -} - -/* Step 2: apply policy to a range and do splits. */ -static int mbind_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end, struct mempolicy *new) -{ - struct vm_area_struct *next; - int err; - - err = 0; - for (; vma && vma->vm_start < end; vma = next) { - next = vma->vm_next; - if (vma->vm_start < start) - err = split_vma(vma->vm_mm, vma, start, 1); - if (!err && vma->vm_end > end) - err = split_vma(vma->vm_mm, vma, end, 0); - if (!err) - err = policy_vma(vma, new); - if (err) - break; - } - return err; -} - -/* Change policy for a memory range */ -asmlinkage long sys_mbind(unsigned long start, unsigned long len, - unsigned long mode, - unsigned long __user *nmask, unsigned long maxnode, - unsigned flags) -{ - struct vm_area_struct *vma; - struct mm_struct *mm = current->mm; - struct mempolicy *new; - unsigned long end; - DECLARE_BITMAP(nodes, MAX_NUMNODES); - int err; - - if ((flags & ~(unsigned long)(MPOL_MF_STRICT)) || mode > MPOL_MAX) - return -EINVAL; - if (start & ~PAGE_MASK) - return -EINVAL; - if (mode == MPOL_DEFAULT) - flags &= ~MPOL_MF_STRICT; - len = (len + PAGE_SIZE - 1) & PAGE_MASK; - end = start + len; - if (end < start) - return -EINVAL; - if (end == start) - return 0; - - err = get_nodes(nodes, nmask, maxnode, mode); - if (err) - return err; - - new = mpol_new(mode, nodes); - if (IS_ERR(new)) - return PTR_ERR(new); - - PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len, - mode,nodes[0]); - - down_write(&mm->mmap_sem); - vma = check_range(mm, start, end, nodes, flags); - err = PTR_ERR(vma); - if (!IS_ERR(vma)) - err = mbind_range(vma, start, end, new); - up_write(&mm->mmap_sem); - mpol_free(new); - return err; -} - -/* Set the process memory policy */ -asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, - unsigned long maxnode) -{ - int err; - struct mempolicy *new; - DECLARE_BITMAP(nodes, MAX_NUMNODES); - - if (mode > MPOL_MAX) - return -EINVAL; - err = get_nodes(nodes, nmask, maxnode, mode); - if (err) - return err; - new = mpol_new(mode, nodes); - if (IS_ERR(new)) - return PTR_ERR(new); - mpol_free(current->mempolicy); - current->mempolicy = new; - if (new && new->policy == MPOL_INTERLEAVE) - current->il_next = find_first_bit(new->v.nodes, MAX_NUMNODES); - return 0; -} - -/* Fill a zone bitmap for a policy */ -static void get_zonemask(struct mempolicy *p, unsigned long *nodes) -{ - int i; - - bitmap_zero(nodes, MAX_NUMNODES); - switch (p->policy) { - case MPOL_BIND: - for (i = 0; p->v.zonelist->zones[i]; i++) - __set_bit(p->v.zonelist->zones[i]->zone_pgdat->node_id, nodes); - break; - case MPOL_DEFAULT: - break; - case MPOL_INTERLEAVE: - bitmap_copy(nodes, p->v.nodes, MAX_NUMNODES); - break; - case MPOL_PREFERRED: - /* or use current node instead of online map? */ - if (p->v.preferred_node < 0) - bitmap_copy(nodes, node_online_map, MAX_NUMNODES); - else - __set_bit(p->v.preferred_node, nodes); - break; - default: - BUG(); - } -} - -static int lookup_node(struct mm_struct *mm, unsigned long addr) -{ - struct page *p; - int err; - - err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, 0, &p, NULL); - if (err >= 0) { - err = page_zone(p)->zone_pgdat->node_id; - put_page(p); - } - return err; -} - -/* Copy a kernel node mask to user space */ -static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode, - void *nodes, unsigned nbytes) -{ - unsigned long copy = ALIGN(maxnode-1, 64) / 8; - - if (copy > nbytes) { - if (copy > PAGE_SIZE) - return -EINVAL; - if (clear_user((char __user *)mask + nbytes, copy - nbytes)) - return -EFAULT; - copy = nbytes; - } - return copy_to_user(mask, nodes, copy) ? -EFAULT : 0; -} - -/* Retrieve NUMA policy */ -asmlinkage long sys_get_mempolicy(int __user *policy, - unsigned long __user *nmask, - unsigned long maxnode, - unsigned long addr, unsigned long flags) -{ - int err, pval; - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma = NULL; - struct mempolicy *pol = current->mempolicy; - - if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) - return -EINVAL; - if (nmask != NULL && maxnode < numnodes) - return -EINVAL; - if (flags & MPOL_F_ADDR) { - down_read(&mm->mmap_sem); - vma = find_vma_intersection(mm, addr, addr+1); - if (!vma) { - up_read(&mm->mmap_sem); - return -EFAULT; - } - if (vma->vm_ops && vma->vm_ops->get_policy) - pol = vma->vm_ops->get_policy(vma, addr); - else - pol = vma->vm_policy; - } else if (addr) - return -EINVAL; - - if (!pol) - pol = &default_policy; - - if (flags & MPOL_F_NODE) { - if (flags & MPOL_F_ADDR) { - err = lookup_node(mm, addr); - if (err < 0) - goto out; - pval = err; - } else if (pol == current->mempolicy && - pol->policy == MPOL_INTERLEAVE) { - pval = current->il_next; - } else { - err = -EINVAL; - goto out; - } - } else - pval = pol->policy; - - err = -EFAULT; - if (policy && put_user(pval, policy)) - goto out; - - err = 0; - if (nmask) { - DECLARE_BITMAP(nodes, MAX_NUMNODES); - get_zonemask(pol, nodes); - err = copy_nodes_to_user(nmask, maxnode, nodes, sizeof(nodes)); - } - - out: - if (vma) - up_read(¤t->mm->mmap_sem); - return err; -} - -#ifdef CONFIG_COMPAT -/* The other functions are compatible */ -asmlinkage long compat_get_mempolicy(int __user *policy, - unsigned __user *nmask, unsigned maxnode, - unsigned addr, unsigned flags) -{ - long err; - unsigned long __user *nm = NULL; - if (nmask) - nm = compat_alloc_user_space(ALIGN(maxnode-1, 64) / 8); - err = sys_get_mempolicy(policy, nm, maxnode, addr, flags); - if (!err && copy_in_user(nmask, nm, ALIGN(maxnode-1, 32)/8)) - err = -EFAULT; - return err; -} -#endif - -/* Return effective policy for a VMA */ -static struct mempolicy * -get_vma_policy(struct vm_area_struct *vma, unsigned long addr) -{ - struct mempolicy *pol = current->mempolicy; - - if (vma) { - if (vma->vm_ops && vma->vm_ops->get_policy) - pol = vma->vm_ops->get_policy(vma, addr); - else if (vma->vm_policy && - vma->vm_policy->policy != MPOL_DEFAULT) - pol = vma->vm_policy; - } - if (!pol) - pol = &default_policy; - return pol; -} - -/* Return a zonelist representing a mempolicy */ -static struct zonelist *zonelist_policy(unsigned gfp, struct mempolicy *policy) -{ - int nd; - - switch (policy->policy) { - case MPOL_PREFERRED: - nd = policy->v.preferred_node; - if (nd < 0) - nd = numa_node_id(); - break; - case MPOL_BIND: - /* Lower zones don't get a policy applied */ - if (gfp >= policy_zone) - return policy->v.zonelist; - /*FALL THROUGH*/ - case MPOL_INTERLEAVE: /* should not happen */ - case MPOL_DEFAULT: - nd = numa_node_id(); - break; - default: - nd = 0; - BUG(); - } - return NODE_DATA(nd)->node_zonelists + (gfp & GFP_ZONEMASK); -} - -/* Do dynamic interleaving for a process */ -static unsigned interleave_nodes(struct mempolicy *policy) -{ - unsigned nid, next; - struct task_struct *me = current; - - nid = me->il_next; - BUG_ON(nid >= MAX_NUMNODES); - next = find_next_bit(policy->v.nodes, MAX_NUMNODES, 1+nid); - if (next >= MAX_NUMNODES) - next = find_first_bit(policy->v.nodes, MAX_NUMNODES); - me->il_next = next; - return nid; -} - -/* Do static interleaving for a VMA with known offset. */ -static unsigned offset_il_node(struct mempolicy *pol, - struct vm_area_struct *vma, unsigned long off) -{ - unsigned nnodes = bitmap_weight(pol->v.nodes, MAX_NUMNODES); - unsigned target = (unsigned)off % nnodes; - int c; - int nid = -1; - - c = 0; - do { - nid = find_next_bit(pol->v.nodes, MAX_NUMNODES, nid+1); - c++; - } while (c <= target); - BUG_ON(nid >= MAX_NUMNODES); - BUG_ON(!test_bit(nid, pol->v.nodes)); - return nid; -} - -/* Allocate a page in interleaved policy. - Own path because it needs to do special accounting. */ -static struct page *alloc_page_interleave(unsigned gfp, unsigned nid) -{ - struct zonelist *zl; - struct page *page; - - BUG_ON(!test_bit(nid, node_online_map)); - zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK); - page = __alloc_pages(gfp, 0, zl); - if (page && page_zone(page) == zl->zones[0]) { - zl->zones[0]->pageset[get_cpu()].interleave_hit++; - put_cpu(); - } - return page; -} - -/** - * alloc_page_vma - Allocate a page for a VMA. - * - * @gfp: - * %GFP_USER user allocation. - * %GFP_KERNEL kernel allocations, - * %GFP_HIGHMEM highmem/user allocations, - * %GFP_FS allocation should not call back into a file system. - * %GFP_ATOMIC don't sleep. - * - * @vma: Pointer to VMA or NULL if not available. - * @addr: Virtual Address of the allocation. Must be inside the VMA. - * - * This function allocates a page from the kernel page pool and applies - * a NUMA policy associated with the VMA or the current process. - * When VMA is not NULL caller must hold down_read on the mmap_sem of the - * mm_struct of the VMA to prevent it from going away. Should be used for - * all allocations for pages that will be mapped into - * user space. Returns NULL when no page can be allocated. - * - * Should be called with the mm_sem of the vma hold. - */ -struct page * -alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr) -{ - struct mempolicy *pol = get_vma_policy(vma, addr); - - if (unlikely(pol->policy == MPOL_INTERLEAVE)) { - unsigned nid; - if (vma) { - unsigned long off; - BUG_ON(addr >= vma->vm_end); - BUG_ON(addr < vma->vm_start); - off = vma->vm_pgoff; - off += (addr - vma->vm_start) >> PAGE_SHIFT; - nid = offset_il_node(pol, vma, off); - } else { - /* fall back to process interleaving */ - nid = interleave_nodes(pol); - } - return alloc_page_interleave(gfp, nid); - } - return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); -} - -/** - * alloc_pages_current - Allocate pages. - * - * @gfp: - * %GFP_USER user allocation, - * %GFP_KERNEL kernel allocation, - * %GFP_HIGHMEM highmem allocation, - * %GFP_FS don't call back into a file system. - * %GFP_ATOMIC don't sleep. - * @order: Power of two of allocation size in pages. 0 is a single page. - * - * Allocate a page from the kernel page pool. When not in - * interrupt context and apply the current process NUMA policy. - * Returns NULL when no page can be allocated. - */ -struct page *alloc_pages_current(unsigned gfp, unsigned order) -{ - struct mempolicy *pol = current->mempolicy; - - if (!pol || in_interrupt()) - pol = &default_policy; - if (pol->policy == MPOL_INTERLEAVE && order == 0) - return alloc_page_interleave(gfp, interleave_nodes(pol)); - return __alloc_pages(gfp, order, zonelist_policy(gfp, pol)); -} -EXPORT_SYMBOL(alloc_pages_current); - -/* Slow path of a mempolicy copy */ -struct mempolicy *__mpol_copy(struct mempolicy *old) -{ - struct mempolicy *new = kmem_cache_alloc(policy_cache, GFP_KERNEL); - - if (!new) - return ERR_PTR(-ENOMEM); - *new = *old; - atomic_set(&new->refcnt, 1); - if (new->policy == MPOL_BIND) { - int sz = ksize(old->v.zonelist); - new->v.zonelist = kmalloc(sz, SLAB_KERNEL); - if (!new->v.zonelist) { - kmem_cache_free(policy_cache, new); - return ERR_PTR(-ENOMEM); - } - memcpy(new->v.zonelist, old->v.zonelist, sz); - } - return new; -} - -/* Slow path of a mempolicy comparison */ -int __mpol_equal(struct mempolicy *a, struct mempolicy *b) -{ - if (!a || !b) - return 0; - if (a->policy != b->policy) - return 0; - switch (a->policy) { - case MPOL_DEFAULT: - return 1; - case MPOL_INTERLEAVE: - return bitmap_equal(a->v.nodes, b->v.nodes, MAX_NUMNODES); - case MPOL_PREFERRED: - return a->v.preferred_node == b->v.preferred_node; - case MPOL_BIND: { - int i; - for (i = 0; a->v.zonelist->zones[i]; i++) - if (a->v.zonelist->zones[i] != b->v.zonelist->zones[i]) - return 0; - return b->v.zonelist->zones[i] == NULL; - } - default: - BUG(); - return 0; - } -} - -/* Slow path of a mpol destructor. */ -void __mpol_free(struct mempolicy *p) -{ - if (!atomic_dec_and_test(&p->refcnt)) - return; - if (p->policy == MPOL_BIND) - kfree(p->v.zonelist); - p->policy = MPOL_DEFAULT; - kmem_cache_free(policy_cache, p); -} - -/* - * Hugetlb policy. Same as above, just works with node numbers instead of - * zonelists. - */ - -/* Find first node suitable for an allocation */ -int mpol_first_node(struct vm_area_struct *vma, unsigned long addr) -{ - struct mempolicy *pol = get_vma_policy(vma, addr); - - switch (pol->policy) { - case MPOL_DEFAULT: - return numa_node_id(); - case MPOL_BIND: - return pol->v.zonelist->zones[0]->zone_pgdat->node_id; - case MPOL_INTERLEAVE: - return interleave_nodes(pol); - case MPOL_PREFERRED: - return pol->v.preferred_node >= 0 ? - pol->v.preferred_node : numa_node_id(); - } - BUG(); - return 0; -} - -/* Find secondary valid nodes for an allocation */ -int mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long addr) -{ - struct mempolicy *pol = get_vma_policy(vma, addr); - - switch (pol->policy) { - case MPOL_PREFERRED: - case MPOL_DEFAULT: - case MPOL_INTERLEAVE: - return 1; - case MPOL_BIND: { - struct zone **z; - for (z = pol->v.zonelist->zones; *z; z++) - if ((*z)->zone_pgdat->node_id == nid) - return 1; - return 0; - } - default: - BUG(); - return 0; - } -} - -/* - * Shared memory backing store policy support. - * - * Remember policies even when nobody has shared memory mapped. - * The policies are kept in Red-Black tree linked from the inode. - * They are protected by the sp->sem semaphore, which should be held - * for any accesses to the tree. - */ - -/* lookup first element intersecting start-end */ -/* Caller holds sp->sem */ -static struct sp_node * -sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end) -{ - struct rb_node *n = sp->root.rb_node; - - while (n) { - struct sp_node *p = rb_entry(n, struct sp_node, nd); - if (start >= p->end) { - n = n->rb_right; - } else if (end < p->start) { - n = n->rb_left; - } else { - break; - } - } - if (!n) - return NULL; - for (;;) { - struct sp_node *w = NULL; - struct rb_node *prev = rb_prev(n); - if (!prev) - break; - w = rb_entry(prev, struct sp_node, nd); - if (w->end <= start) - break; - n = prev; - } - return rb_entry(n, struct sp_node, nd); -} - -/* Insert a new shared policy into the list. */ -/* Caller holds sp->sem */ -static void sp_insert(struct shared_policy *sp, struct sp_node *new) -{ - struct rb_node **p = &sp->root.rb_node; - struct rb_node *parent = NULL; - struct sp_node *nd; - - while (*p) { - parent = *p; - nd = rb_entry(parent, struct sp_node, nd); - if (new->start < nd->start) - p = &(*p)->rb_left; - else if (new->end > nd->end) - p = &(*p)->rb_right; - else - BUG(); - } - rb_link_node(&new->nd, parent, p); - rb_insert_color(&new->nd, &sp->root); - PDprintk("inserting %lx-%lx: %d\n", new->start, new->end, - new->policy ? new->policy->policy : 0); -} - -/* Find shared policy intersecting idx */ -struct mempolicy * -mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) -{ - struct mempolicy *pol = NULL; - struct sp_node *sn; - - down(&sp->sem); - sn = sp_lookup(sp, idx, idx+1); - if (sn) { - mpol_get(sn->policy); - pol = sn->policy; - } - up(&sp->sem); - return pol; -} - -static void sp_delete(struct shared_policy *sp, struct sp_node *n) -{ - PDprintk("deleting %lx-l%x\n", n->start, n->end); - rb_erase(&n->nd, &sp->root); - mpol_free(n->policy); - kmem_cache_free(sn_cache, n); -} - -struct sp_node * -sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol) -{ - struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL); - - if (!n) - return NULL; - n->start = start; - n->end = end; - mpol_get(pol); - n->policy = pol; - return n; -} - -/* Replace a policy range. */ -static int shared_policy_replace(struct shared_policy *sp, unsigned long start, - unsigned long end, struct sp_node *new) -{ - struct sp_node *n, *new2; - - down(&sp->sem); - n = sp_lookup(sp, start, end); - /* Take care of old policies in the same range. */ - while (n && n->start < end) { - struct rb_node *next = rb_next(&n->nd); - if (n->start >= start) { - if (n->end <= end) - sp_delete(sp, n); - else - n->start = end; - } else { - /* Old policy spanning whole new range. */ - if (n->end > end) { - new2 = sp_alloc(end, n->end, n->policy); - if (!new2) { - up(&sp->sem); - return -ENOMEM; - } - n->end = end; - sp_insert(sp, new2); - } - /* Old crossing beginning, but not end (easy) */ - if (n->start < start && n->end > start) - n->end = start; - } - if (!next) - break; - n = rb_entry(next, struct sp_node, nd); - } - if (new) - sp_insert(sp, new); - up(&sp->sem); - return 0; -} - -int mpol_set_shared_policy(struct shared_policy *info, - struct vm_area_struct *vma, struct mempolicy *npol) -{ - int err; - struct sp_node *new = NULL; - unsigned long sz = vma_pages(vma); - - PDprintk("set_shared_policy %lx sz %lu %d %lx\n", - vma->vm_pgoff, - sz, npol? npol->policy : -1, - npol ? npol->v.nodes[0] : -1); - - if (npol) { - new = sp_alloc(vma->vm_pgoff, vma->vm_pgoff + sz, npol); - if (!new) - return -ENOMEM; - } - err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); - if (err && new) - kmem_cache_free(sn_cache, new); - return err; -} - -/* Free a backing policy store on inode delete. */ -void mpol_free_shared_policy(struct shared_policy *p) -{ - struct sp_node *n; - struct rb_node *next; - - down(&p->sem); - next = rb_first(&p->root); - while (next) { - n = rb_entry(next, struct sp_node, nd); - next = rb_next(&n->nd); - rb_erase(&n->nd, &p->root); - mpol_free(n->policy); - kmem_cache_free(sn_cache, n); - } - up(&p->sem); -} - -static __init int numa_policy_init(void) -{ - policy_cache = kmem_cache_create("numa_policy", - sizeof(struct mempolicy), - 0, SLAB_PANIC, NULL, NULL); - - sn_cache = kmem_cache_create("shared_policy_node", - sizeof(struct sp_node), - 0, SLAB_PANIC, NULL, NULL); - return 0; -} -module_init(numa_policy_init); diff --git a/mm/prio_tree.c b/mm/prio_tree.c deleted file mode 100644 index 6cd41a831..000000000 --- a/mm/prio_tree.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - * mm/prio_tree.c - priority search tree for mapping->i_mmap - * - * Copyright (C) 2004, Rajesh Venkatasubramanian - * - * This file is released under the GPL v2. - * - * Based on the radix priority search tree proposed by Edward M. McCreight - * SIAM Journal of Computing, vol. 14, no.2, pages 257-276, May 1985 - * - * 02Feb2004 Initial version - */ - -#include -#include -#include -#include - -/* - * A clever mix of heap and radix trees forms a radix priority search tree (PST) - * which is useful for storing intervals, e.g, we can consider a vma as a closed - * interval of file pages [offset_begin, offset_end], and store all vmas that - * map a file in a PST. Then, using the PST, we can answer a stabbing query, - * i.e., selecting a set of stored intervals (vmas) that overlap with (map) a - * given input interval X (a set of consecutive file pages), in "O(log n + m)" - * time where 'log n' is the height of the PST, and 'm' is the number of stored - * intervals (vmas) that overlap (map) with the input interval X (the set of - * consecutive file pages). - * - * In our implementation, we store closed intervals of the form [radix_index, - * heap_index]. We assume that always radix_index <= heap_index. McCreight's PST - * is designed for storing intervals with unique radix indices, i.e., each - * interval have different radix_index. However, this limitation can be easily - * overcome by using the size, i.e., heap_index - radix_index, as part of the - * index, so we index the tree using [(radix_index,size), heap_index]. - * - * When the above-mentioned indexing scheme is used, theoretically, in a 32 bit - * machine, the maximum height of a PST can be 64. We can use a balanced version - * of the priority search tree to optimize the tree height, but the balanced - * tree proposed by McCreight is too complex and memory-hungry for our purpose. - */ - -/* - * The following macros are used for implementing prio_tree for i_mmap - */ - -#define RADIX_INDEX(vma) ((vma)->vm_pgoff) -#define VMA_SIZE(vma) (((vma)->vm_end - (vma)->vm_start) >> PAGE_SHIFT) -/* avoid overflow */ -#define HEAP_INDEX(vma) ((vma)->vm_pgoff + (VMA_SIZE(vma) - 1)) - -#define GET_INDEX_VMA(vma, radix, heap) \ -do { \ - radix = RADIX_INDEX(vma); \ - heap = HEAP_INDEX(vma); \ -} while (0) - -#define GET_INDEX(node, radix, heap) \ -do { \ - struct vm_area_struct *__tmp = \ - prio_tree_entry(node, struct vm_area_struct, shared.prio_tree_node);\ - GET_INDEX_VMA(__tmp, radix, heap); \ -} while (0) - -static unsigned long index_bits_to_maxindex[BITS_PER_LONG]; - -void __init prio_tree_init(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(index_bits_to_maxindex) - 1; i++) - index_bits_to_maxindex[i] = (1UL << (i + 1)) - 1; - index_bits_to_maxindex[ARRAY_SIZE(index_bits_to_maxindex) - 1] = ~0UL; -} - -/* - * Maximum heap_index that can be stored in a PST with index_bits bits - */ -static inline unsigned long prio_tree_maxindex(unsigned int bits) -{ - return index_bits_to_maxindex[bits - 1]; -} - -/* - * Extend a priority search tree so that it can store a node with heap_index - * max_heap_index. In the worst case, this algorithm takes O((log n)^2). - * However, this function is used rarely and the common case performance is - * not bad. - */ -static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root, - struct prio_tree_node *node, unsigned long max_heap_index) -{ - static void prio_tree_remove(struct prio_tree_root *, - struct prio_tree_node *); - struct prio_tree_node *first = NULL, *prev, *last = NULL; - - if (max_heap_index > prio_tree_maxindex(root->index_bits)) - root->index_bits++; - - while (max_heap_index > prio_tree_maxindex(root->index_bits)) { - root->index_bits++; - - if (prio_tree_empty(root)) - continue; - - if (first == NULL) { - first = root->prio_tree_node; - prio_tree_remove(root, root->prio_tree_node); - INIT_PRIO_TREE_NODE(first); - last = first; - } else { - prev = last; - last = root->prio_tree_node; - prio_tree_remove(root, root->prio_tree_node); - INIT_PRIO_TREE_NODE(last); - prev->left = last; - last->parent = prev; - } - } - - INIT_PRIO_TREE_NODE(node); - - if (first) { - node->left = first; - first->parent = node; - } else - last = node; - - if (!prio_tree_empty(root)) { - last->left = root->prio_tree_node; - last->left->parent = last; - } - - root->prio_tree_node = node; - return node; -} - -/* - * Replace a prio_tree_node with a new node and return the old node - */ -static struct prio_tree_node *prio_tree_replace(struct prio_tree_root *root, - struct prio_tree_node *old, struct prio_tree_node *node) -{ - INIT_PRIO_TREE_NODE(node); - - if (prio_tree_root(old)) { - BUG_ON(root->prio_tree_node != old); - /* - * We can reduce root->index_bits here. However, it is complex - * and does not help much to improve performance (IMO). - */ - node->parent = node; - root->prio_tree_node = node; - } else { - node->parent = old->parent; - if (old->parent->left == old) - old->parent->left = node; - else - old->parent->right = node; - } - - if (!prio_tree_left_empty(old)) { - node->left = old->left; - old->left->parent = node; - } - - if (!prio_tree_right_empty(old)) { - node->right = old->right; - old->right->parent = node; - } - - return old; -} - -/* - * Insert a prio_tree_node @node into a radix priority search tree @root. The - * algorithm typically takes O(log n) time where 'log n' is the number of bits - * required to represent the maximum heap_index. In the worst case, the algo - * can take O((log n)^2) - check prio_tree_expand. - * - * If a prior node with same radix_index and heap_index is already found in - * the tree, then returns the address of the prior node. Otherwise, inserts - * @node into the tree and returns @node. - */ -static struct prio_tree_node *prio_tree_insert(struct prio_tree_root *root, - struct prio_tree_node *node) -{ - struct prio_tree_node *cur, *res = node; - unsigned long radix_index, heap_index; - unsigned long r_index, h_index, index, mask; - int size_flag = 0; - - GET_INDEX(node, radix_index, heap_index); - - if (prio_tree_empty(root) || - heap_index > prio_tree_maxindex(root->index_bits)) - return prio_tree_expand(root, node, heap_index); - - cur = root->prio_tree_node; - mask = 1UL << (root->index_bits - 1); - - while (mask) { - GET_INDEX(cur, r_index, h_index); - - if (r_index == radix_index && h_index == heap_index) - return cur; - - if (h_index < heap_index || - (h_index == heap_index && r_index > radix_index)) { - struct prio_tree_node *tmp = node; - node = prio_tree_replace(root, cur, node); - cur = tmp; - /* swap indices */ - index = r_index; - r_index = radix_index; - radix_index = index; - index = h_index; - h_index = heap_index; - heap_index = index; - } - - if (size_flag) - index = heap_index - radix_index; - else - index = radix_index; - - if (index & mask) { - if (prio_tree_right_empty(cur)) { - INIT_PRIO_TREE_NODE(node); - cur->right = node; - node->parent = cur; - return res; - } else - cur = cur->right; - } else { - if (prio_tree_left_empty(cur)) { - INIT_PRIO_TREE_NODE(node); - cur->left = node; - node->parent = cur; - return res; - } else - cur = cur->left; - } - - mask >>= 1; - - if (!mask) { - mask = 1UL << (root->index_bits - 1); - size_flag = 1; - } - } - /* Should not reach here */ - BUG(); - return NULL; -} - -/* - * Remove a prio_tree_node @node from a radix priority search tree @root. The - * algorithm takes O(log n) time where 'log n' is the number of bits required - * to represent the maximum heap_index. - */ -static void prio_tree_remove(struct prio_tree_root *root, - struct prio_tree_node *node) -{ - struct prio_tree_node *cur; - unsigned long r_index, h_index_right, h_index_left; - - cur = node; - - while (!prio_tree_left_empty(cur) || !prio_tree_right_empty(cur)) { - if (!prio_tree_left_empty(cur)) - GET_INDEX(cur->left, r_index, h_index_left); - else { - cur = cur->right; - continue; - } - - if (!prio_tree_right_empty(cur)) - GET_INDEX(cur->right, r_index, h_index_right); - else { - cur = cur->left; - continue; - } - - /* both h_index_left and h_index_right cannot be 0 */ - if (h_index_left >= h_index_right) - cur = cur->left; - else - cur = cur->right; - } - - if (prio_tree_root(cur)) { - BUG_ON(root->prio_tree_node != cur); - INIT_PRIO_TREE_ROOT(root); - return; - } - - if (cur->parent->right == cur) - cur->parent->right = cur->parent; - else - cur->parent->left = cur->parent; - - while (cur != node) - cur = prio_tree_replace(root, cur->parent, cur); -} - -/* - * Following functions help to enumerate all prio_tree_nodes in the tree that - * overlap with the input interval X [radix_index, heap_index]. The enumeration - * takes O(log n + m) time where 'log n' is the height of the tree (which is - * proportional to # of bits required to represent the maximum heap_index) and - * 'm' is the number of prio_tree_nodes that overlap the interval X. - */ - -static struct prio_tree_node *prio_tree_left( - struct prio_tree_root *root, struct prio_tree_iter *iter, - unsigned long radix_index, unsigned long heap_index, - unsigned long *r_index, unsigned long *h_index) -{ - if (prio_tree_left_empty(iter->cur)) - return NULL; - - GET_INDEX(iter->cur->left, *r_index, *h_index); - - if (radix_index <= *h_index) { - iter->cur = iter->cur->left; - iter->mask >>= 1; - if (iter->mask) { - if (iter->size_level) - iter->size_level++; - } else { - if (iter->size_level) { - BUG_ON(!prio_tree_left_empty(iter->cur)); - BUG_ON(!prio_tree_right_empty(iter->cur)); - iter->size_level++; - iter->mask = ULONG_MAX; - } else { - iter->size_level = 1; - iter->mask = 1UL << (root->index_bits - 1); - } - } - return iter->cur; - } - - return NULL; -} - -static struct prio_tree_node *prio_tree_right( - struct prio_tree_root *root, struct prio_tree_iter *iter, - unsigned long radix_index, unsigned long heap_index, - unsigned long *r_index, unsigned long *h_index) -{ - unsigned long value; - - if (prio_tree_right_empty(iter->cur)) - return NULL; - - if (iter->size_level) - value = iter->value; - else - value = iter->value | iter->mask; - - if (heap_index < value) - return NULL; - - GET_INDEX(iter->cur->right, *r_index, *h_index); - - if (radix_index <= *h_index) { - iter->cur = iter->cur->right; - iter->mask >>= 1; - iter->value = value; - if (iter->mask) { - if (iter->size_level) - iter->size_level++; - } else { - if (iter->size_level) { - BUG_ON(!prio_tree_left_empty(iter->cur)); - BUG_ON(!prio_tree_right_empty(iter->cur)); - iter->size_level++; - iter->mask = ULONG_MAX; - } else { - iter->size_level = 1; - iter->mask = 1UL << (root->index_bits - 1); - } - } - return iter->cur; - } - - return NULL; -} - -static struct prio_tree_node *prio_tree_parent(struct prio_tree_iter *iter) -{ - iter->cur = iter->cur->parent; - if (iter->mask == ULONG_MAX) - iter->mask = 1UL; - else if (iter->size_level == 1) - iter->mask = 1UL; - else - iter->mask <<= 1; - if (iter->size_level) - iter->size_level--; - if (!iter->size_level && (iter->value & iter->mask)) - iter->value ^= iter->mask; - return iter->cur; -} - -static inline int overlap(unsigned long radix_index, unsigned long heap_index, - unsigned long r_index, unsigned long h_index) -{ - return heap_index >= r_index && radix_index <= h_index; -} - -/* - * prio_tree_first: - * - * Get the first prio_tree_node that overlaps with the interval [radix_index, - * heap_index]. Note that always radix_index <= heap_index. We do a pre-order - * traversal of the tree. - */ -static struct prio_tree_node *prio_tree_first(struct prio_tree_root *root, - struct prio_tree_iter *iter, unsigned long radix_index, - unsigned long heap_index) -{ - unsigned long r_index, h_index; - - INIT_PRIO_TREE_ITER(iter); - - if (prio_tree_empty(root)) - return NULL; - - GET_INDEX(root->prio_tree_node, r_index, h_index); - - if (radix_index > h_index) - return NULL; - - iter->mask = 1UL << (root->index_bits - 1); - iter->cur = root->prio_tree_node; - - while (1) { - if (overlap(radix_index, heap_index, r_index, h_index)) - return iter->cur; - - if (prio_tree_left(root, iter, radix_index, heap_index, - &r_index, &h_index)) - continue; - - if (prio_tree_right(root, iter, radix_index, heap_index, - &r_index, &h_index)) - continue; - - break; - } - return NULL; -} - -/* - * prio_tree_next: - * - * Get the next prio_tree_node that overlaps with the input interval in iter - */ -static struct prio_tree_node *prio_tree_next(struct prio_tree_root *root, - struct prio_tree_iter *iter, unsigned long radix_index, - unsigned long heap_index) -{ - unsigned long r_index, h_index; - -repeat: - while (prio_tree_left(root, iter, radix_index, - heap_index, &r_index, &h_index)) { - if (overlap(radix_index, heap_index, r_index, h_index)) - return iter->cur; - } - - while (!prio_tree_right(root, iter, radix_index, - heap_index, &r_index, &h_index)) { - while (!prio_tree_root(iter->cur) && - iter->cur->parent->right == iter->cur) - prio_tree_parent(iter); - - if (prio_tree_root(iter->cur)) - return NULL; - - prio_tree_parent(iter); - } - - if (overlap(radix_index, heap_index, r_index, h_index)) - return iter->cur; - - goto repeat; -} - -/* - * Radix priority search tree for address_space->i_mmap - * - * For each vma that map a unique set of file pages i.e., unique [radix_index, - * heap_index] value, we have a corresponing priority search tree node. If - * multiple vmas have identical [radix_index, heap_index] value, then one of - * them is used as a tree node and others are stored in a vm_set list. The tree - * node points to the first vma (head) of the list using vm_set.head. - * - * prio_tree_root - * | - * A vm_set.head - * / \ / - * L R -> H-I-J-K-M-N-O-P-Q-S - * ^ ^ <-- vm_set.list --> - * tree nodes - * - * We need some way to identify whether a vma is a tree node, head of a vm_set - * list, or just a member of a vm_set list. We cannot use vm_flags to store - * such information. The reason is, in the above figure, it is possible that - * vm_flags' of R and H are covered by the different mmap_sems. When R is - * removed under R->mmap_sem, H replaces R as a tree node. Since we do not hold - * H->mmap_sem, we cannot use H->vm_flags for marking that H is a tree node now. - * That's why some trick involving shared.vm_set.parent is used for identifying - * tree nodes and list head nodes. - * - * vma radix priority search tree node rules: - * - * vma->shared.vm_set.parent != NULL ==> a tree node - * vma->shared.vm_set.head != NULL ==> list of others mapping same range - * vma->shared.vm_set.head == NULL ==> no others map the same range - * - * vma->shared.vm_set.parent == NULL - * vma->shared.vm_set.head != NULL ==> list head of vmas mapping same range - * vma->shared.vm_set.head == NULL ==> a list node - */ - -/* - * Add a new vma known to map the same set of pages as the old vma: - * useful for fork's dup_mmap as well as vma_prio_tree_insert below. - * Note that it just happens to work correctly on i_mmap_nonlinear too. - */ -void vma_prio_tree_add(struct vm_area_struct *vma, struct vm_area_struct *old) -{ - /* Leave these BUG_ONs till prio_tree patch stabilizes */ - BUG_ON(RADIX_INDEX(vma) != RADIX_INDEX(old)); - BUG_ON(HEAP_INDEX(vma) != HEAP_INDEX(old)); - - if (!old->shared.vm_set.parent) - list_add(&vma->shared.vm_set.list, - &old->shared.vm_set.list); - else if (old->shared.vm_set.head) - list_add_tail(&vma->shared.vm_set.list, - &old->shared.vm_set.head->shared.vm_set.list); - else { - INIT_LIST_HEAD(&vma->shared.vm_set.list); - vma->shared.vm_set.head = old; - old->shared.vm_set.head = vma; - } -} - -void vma_prio_tree_insert(struct vm_area_struct *vma, - struct prio_tree_root *root) -{ - struct prio_tree_node *ptr; - struct vm_area_struct *old; - - ptr = prio_tree_insert(root, &vma->shared.prio_tree_node); - if (ptr != &vma->shared.prio_tree_node) { - old = prio_tree_entry(ptr, struct vm_area_struct, - shared.prio_tree_node); - vma_prio_tree_add(vma, old); - } -} - -void vma_prio_tree_remove(struct vm_area_struct *vma, - struct prio_tree_root *root) -{ - struct vm_area_struct *node, *head, *new_head; - - if (!vma->shared.vm_set.head) { - if (!vma->shared.vm_set.parent) - list_del_init(&vma->shared.vm_set.list); - else - prio_tree_remove(root, &vma->shared.prio_tree_node); - } else { - /* Leave this BUG_ON till prio_tree patch stabilizes */ - BUG_ON(vma->shared.vm_set.head->shared.vm_set.head != vma); - if (vma->shared.vm_set.parent) { - head = vma->shared.vm_set.head; - if (!list_empty(&head->shared.vm_set.list)) { - new_head = list_entry( - head->shared.vm_set.list.next, - struct vm_area_struct, - shared.vm_set.list); - list_del_init(&head->shared.vm_set.list); - } else - new_head = NULL; - - prio_tree_replace(root, &vma->shared.prio_tree_node, - &head->shared.prio_tree_node); - head->shared.vm_set.head = new_head; - if (new_head) - new_head->shared.vm_set.head = head; - - } else { - node = vma->shared.vm_set.head; - if (!list_empty(&vma->shared.vm_set.list)) { - new_head = list_entry( - vma->shared.vm_set.list.next, - struct vm_area_struct, - shared.vm_set.list); - list_del_init(&vma->shared.vm_set.list); - node->shared.vm_set.head = new_head; - new_head->shared.vm_set.head = node; - } else - node->shared.vm_set.head = NULL; - } - } -} - -/* - * Helper function to enumerate vmas that map a given file page or a set of - * contiguous file pages. The function returns vmas that at least map a single - * page in the given range of contiguous file pages. - */ -struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma, - struct prio_tree_root *root, struct prio_tree_iter *iter, - pgoff_t begin, pgoff_t end) -{ - struct prio_tree_node *ptr; - struct vm_area_struct *next; - - if (!vma) { - /* - * First call is with NULL vma - */ - ptr = prio_tree_first(root, iter, begin, end); - if (ptr) { - next = prio_tree_entry(ptr, struct vm_area_struct, - shared.prio_tree_node); - prefetch(next->shared.vm_set.head); - return next; - } else - return NULL; - } - - if (vma->shared.vm_set.parent) { - if (vma->shared.vm_set.head) { - next = vma->shared.vm_set.head; - prefetch(next->shared.vm_set.list.next); - return next; - } - } else { - next = list_entry(vma->shared.vm_set.list.next, - struct vm_area_struct, shared.vm_set.list); - if (!next->shared.vm_set.head) { - prefetch(next->shared.vm_set.list.next); - return next; - } - } - - ptr = prio_tree_next(root, iter, begin, end); - if (ptr) { - next = prio_tree_entry(ptr, struct vm_area_struct, - shared.prio_tree_node); - prefetch(next->shared.vm_set.head); - return next; - } else - return NULL; -} diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c deleted file mode 100644 index 178822116..000000000 --- a/net/bridge/br_sysfs_if.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Sysfs attributes of bridge ports - * Linux ethernet bridge - * - * Authors: - * Stephen Hemminger - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include "br_private.h" - -struct brport_attribute { - struct attribute attr; - ssize_t (*show)(struct net_bridge_port *, char *); - ssize_t (*store)(struct net_bridge_port *, unsigned long); -}; - -#define BRPORT_ATTR(_name,_mode,_show,_store) \ -struct brport_attribute brport_attr_##_name = { \ - .attr = {.name = __stringify(_name), \ - .mode = _mode, \ - .owner = THIS_MODULE, }, \ - .show = _show, \ - .store = _store, \ -}; - -static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->path_cost); -} -static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v) -{ - br_stp_set_path_cost(p, v); - return 0; -} -static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, - show_path_cost, store_path_cost); - -static ssize_t show_priority(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->priority); -} -static ssize_t store_priority(struct net_bridge_port *p, unsigned long v) -{ - if (v >= (1<<(16-BR_PORT_BITS))) - return -ERANGE; - br_stp_set_port_priority(p, v); - return 0; -} -static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, - show_priority, store_priority); - -static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) -{ - return br_show_bridge_id(buf, &p->designated_root); -} -static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL); - -static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf) -{ - return br_show_bridge_id(buf, &p->designated_bridge); -} -static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL); - -static ssize_t show_designated_port(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->designated_port); -} -static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL); - -static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->designated_cost); -} -static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL); - -static ssize_t show_port_id(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "0x%x\n", p->port_id); -} -static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL); - -static ssize_t show_port_no(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "0x%x\n", p->port_no); -} - -static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL); - -static ssize_t show_change_ack(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->topology_change_ack); -} -static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL); - -static ssize_t show_config_pending(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->config_pending); -} -static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL); - -static ssize_t show_port_state(struct net_bridge_port *p, char *buf) -{ - return sprintf(buf, "%d\n", p->state); -} -static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL); - -static ssize_t show_message_age_timer(struct net_bridge_port *p, - char *buf) -{ - return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer)); -} -static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL); - -static ssize_t show_forward_delay_timer(struct net_bridge_port *p, - char *buf) -{ - return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer)); -} -static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL); - -static ssize_t show_hold_timer(struct net_bridge_port *p, - char *buf) -{ - return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer)); -} -static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); - -static struct brport_attribute *brport_attrs[] = { - &brport_attr_path_cost, - &brport_attr_priority, - &brport_attr_port_id, - &brport_attr_port_no, - &brport_attr_designated_root, - &brport_attr_designated_bridge, - &brport_attr_designated_port, - &brport_attr_designated_cost, - &brport_attr_state, - &brport_attr_change_ack, - &brport_attr_config_pending, - &brport_attr_message_age_timer, - &brport_attr_forward_delay_timer, - &brport_attr_hold_timer, - NULL -}; - -#define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr) -#define to_brport(obj) container_of(obj, struct net_bridge_port, kobj) - -static ssize_t brport_show(struct kobject * kobj, - struct attribute * attr, char * buf) -{ - struct brport_attribute * brport_attr = to_brport_attr(attr); - struct net_bridge_port * p = to_brport(kobj); - - return brport_attr->show(p, buf); -} - -static ssize_t brport_store(struct kobject * kobj, - struct attribute * attr, - const char * buf, size_t count) -{ - struct brport_attribute * brport_attr = to_brport_attr(attr); - struct net_bridge_port * p = to_brport(kobj); - ssize_t ret = -EINVAL; - char *endp; - unsigned long val; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - val = simple_strtoul(buf, &endp, 0); - if (endp != buf) { - rtnl_lock(); - if (p->dev && p->br && brport_attr->store) { - spin_lock_bh(&p->br->lock); - ret = brport_attr->store(p, val); - spin_unlock_bh(&p->br->lock); - if (ret == 0) - ret = count; - } - rtnl_unlock(); - } - return ret; -} - -/* called from kobject_put when port ref count goes to zero. */ -static void brport_release(struct kobject *kobj) -{ - kfree(container_of(kobj, struct net_bridge_port, kobj)); -} - -static struct sysfs_ops brport_sysfs_ops = { - .show = brport_show, - .store = brport_store, -}; - -static struct kobj_type brport_ktype = { - .sysfs_ops = &brport_sysfs_ops, - .release = brport_release, -}; - - -/* - * Add sysfs entries to ethernet device added to a bridge. - * Creates a brport subdirectory with bridge attributes. - * Puts symlink in bridge's brport subdirectory - */ -int br_sysfs_addif(struct net_bridge_port *p) -{ - struct net_bridge *br = p->br; - struct brport_attribute **a; - int err; - - ASSERT_RTNL(); - - kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); - p->kobj.ktype = &brport_ktype; - p->kobj.parent = &(p->dev->class_dev.kobj); - p->kobj.kset = &bridge_subsys.kset; - - err = kobject_add(&p->kobj); - if(err) - goto out1; - - err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, - SYSFS_BRIDGE_PORT_LINK); - if (err) - goto out2; - - for (a = brport_attrs; *a; ++a) { - err = sysfs_create_file(&p->kobj, &((*a)->attr)); - if (err) - goto out2; - } - - err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name); - if (err) - goto out2; - - return 0; - out2: - kobject_del(&p->kobj); - out1: - return err; -} - -void br_sysfs_removeif(struct net_bridge_port *p) -{ - pr_debug("br_sysfs_removeif\n"); - sysfs_remove_link(&p->br->ifobj, p->dev->name); - kobject_del(&p->kobj); -} - -void br_sysfs_freeif(struct net_bridge_port *p) -{ - pr_debug("br_sysfs_freeif\n"); - kobject_put(&p->kobj); -} diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl deleted file mode 100644 index 9d01ec5f3..000000000 --- a/scripts/reference_discarded.pl +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/perl -w -# -# reference_discarded.pl (C) Keith Owens 2001 -# -# Released under GPL V2. -# -# List dangling references to vmlinux discarded sections. - -use strict; -die($0 . " takes no arguments\n") if($#ARGV >= 0); - -my %object; -my $object; -my $line; -my $ignore; -my $errorcount; - -$| = 1; - -# printf("Finding objects, "); -open(OBJDUMP_LIST, "find . -name '*.o' | xargs objdump -h |") || die "getting objdump list failed"; -while (defined($line = )) { - chomp($line); - if ($line =~ /:\s+file format/) { - ($object = $line) =~ s/:.*//; - $object{$object}->{'module'} = 0; - $object{$object}->{'size'} = 0; - $object{$object}->{'off'} = 0; - } - if ($line =~ /^\s*\d+\s+\.modinfo\s+/) { - $object{$object}->{'module'} = 1; - } - if ($line =~ /^\s*\d+\s+\.comment\s+/) { - ($object{$object}->{'size'}, $object{$object}->{'off'}) = (split(' ', $line))[2,5]; - } -} -close(OBJDUMP_LIST); -# printf("%d objects, ", scalar keys(%object)); -$ignore = 0; -foreach $object (keys(%object)) { - if ($object{$object}->{'module'}) { - ++$ignore; - delete($object{$object}); - } -} -# printf("ignoring %d module(s)\n", $ignore); - -# Ignore conglomerate objects, they have been built from multiple objects and we -# only care about the individual objects. If an object has more than one GCC: -# string in the comment section then it is conglomerate. This does not filter -# out conglomerates that consist of exactly one object, can't be helped. - -# printf("Finding conglomerates, "); -$ignore = 0; -foreach $object (keys(%object)) { - if (exists($object{$object}->{'off'})) { - my ($off, $size, $comment, $l); - $off = hex($object{$object}->{'off'}); - $size = hex($object{$object}->{'size'}); - open(OBJECT, "<$object") || die "cannot read $object"; - seek(OBJECT, $off, 0) || die "seek to $off in $object failed"; - $l = read(OBJECT, $comment, $size); - die "read $size bytes from $object .comment failed" if ($l != $size); - close(OBJECT); - if ($comment =~ /GCC\:.*GCC\:/m) { - ++$ignore; - delete($object{$object}); - } - } -} -# printf("ignoring %d conglomerate(s)\n", $ignore); - -# printf("Scanning objects\n"); -$errorcount = 0; -foreach $object (keys(%object)) { - my $from; - open(OBJDUMP, "objdump -r $object|") || die "cannot objdump -r $object"; - while (defined($line = )) { - chomp($line); - if ($line =~ /RELOCATION RECORDS FOR /) { - ($from = $line) =~ s/.*\[([^]]*).*/$1/; - } - if (($line =~ /\.text\.exit$/ || - $line =~ /\.exit\.text$/ || - $line =~ /\.data\.exit$/ || - $line =~ /\.exit\.data$/ || - $line =~ /\.exitcall\.exit$/) && - ($from !~ /\.text\.exit$/ && - $from !~ /\.exit\.text$/ && - $from !~ /\.data\.exit$/ && - $from !~ /\.exit\.data$/ && - $from !~ /\.altinstructions$/ && - $from !~ /\.debug_info$/ && - $from !~ /\.debug_aranges$/ && - $from !~ /\.debug_ranges$/ && - $from !~ /\.debug_line$/ && - $from !~ /\.debug_frame$/ && - $from !~ /\.exitcall\.exit$/ && - $from !~ /\.eh_frame$/ && - $from !~ /\.stab$/)) { - printf("Error: %s %s refers to %s\n", $object, $from, $line); - $errorcount = $errorcount + 1; - } - } - close(OBJDUMP); -} -# printf("Done\n"); - -exit($errorcount); -- 2.43.0