N: Jesper Juhl
E: jesper.juhl@gmail.com
-D: Various fixes, cleanups and minor features.
+D: Various fixes, cleanups and minor features all over the tree.
+D: Wrote initial version of the hdaps driver (since passed on to others).
S: Lemnosvej 1, 3.tv
S: 2300 Copenhagen S.
S: Denmark
S: United Kingdom
N: Ian S. Nelson
-E: ian.nelson@echostar.com
+E: nelsonis@earthlink.net
+P: 1024D/00D3D983 3EFD 7B86 B888 D7E2 29B6 9E97 576F 1B97 00D3 D983
D: Minor mmap and ide hacks
S: 1370 Atlantis Ave.
S: Lafayette CO, 80026
something it would have done anyway.
+ Chapter 16: Function return values and names
+
+Functions can return values of many different kinds, and one of the
+most common is a value indicating whether the function succeeded or
+failed. Such a value can be represented as an error-code integer
+(-Exxx = failure, 0 = success) or a "succeeded" boolean (0 = failure,
+non-zero = success).
+
+Mixing up these two sorts of representations is a fertile source of
+difficult-to-find bugs. If the C language included a strong distinction
+between integers and booleans then the compiler would find these mistakes
+for us... but it doesn't. To help prevent such bugs, always follow this
+convention:
+
+ If the name of a function is an action or an imperative command,
+ the function should return an error-code integer. If the name
+ is a predicate, the function should return a "succeeded" boolean.
+
+For example, "add work" is a command, and the add_work() function returns 0
+for success or -EBUSY for failure. In the same way, "PCI device present" is
+a predicate, and the pci_dev_present() function returns 1 if it succeeds in
+finding a matching device or 0 if it doesn't.
+
+All EXPORTed functions must respect this convention, and so should all
+public functions. Private (static) functions need not, but it is
+recommended that they do.
+
+Functions whose return value is the actual result of a computation, rather
+than an indication of whether the computation succeeded, are not subject to
+this rule. Generally they indicate failure by returning some out-of-range
+result. Typical examples would be functions that return pointers; they use
+NULL or the ERR_PTR mechanism to report failure.
+
+
Appendix I: References
</sect1>
</chapter>
- <chapter id="proc">
- <title>The proc filesystem</title>
-
- <sect1><title>sysctl interface</title>
-!Ekernel/sysctl.c
- </sect1>
-
- <sect1><title>proc filesystem interface</title>
-!Ifs/proc/base.c
- </sect1>
- </chapter>
-
- <chapter id="debugfs">
- <title>The debugfs filesystem</title>
-
- <sect1><title>debugfs interface</title>
-!Efs/debugfs/inode.c
-!Efs/debugfs/file.c
- </sect1>
- </chapter>
-
<chapter id="vfs">
<title>The Linux VFS</title>
<sect1><title>The Filesystem types</title>
</sect1>
</chapter>
+ <chapter id="proc">
+ <title>The proc filesystem</title>
+
+ <sect1><title>sysctl interface</title>
+!Ekernel/sysctl.c
+ </sect1>
+
+ <sect1><title>proc filesystem interface</title>
+!Ifs/proc/base.c
+ </sect1>
+ </chapter>
+
+ <chapter id="sysfs">
+ <title>The Filesystem for Exporting Kernel Objects</title>
+!Efs/sysfs/file.c
+!Efs/sysfs/symlink.c
+!Efs/sysfs/bin.c
+ </chapter>
+
+ <chapter id="debugfs">
+ <title>The debugfs filesystem</title>
+
+ <sect1><title>debugfs interface</title>
+!Efs/debugfs/inode.c
+!Efs/debugfs/file.c
+ </sect1>
+ </chapter>
+
+ <chapter id="relayfs">
+ <title>relay interface support</title>
+
+ <para>
+ Relay interface support
+ is designed to provide an efficient mechanism for tools and
+ facilities to relay large amounts of data from kernel space to
+ user space.
+ </para>
+
+ <sect1><title>relay interface</title>
+!Ekernel/relay.c
+!Ikernel/relay.c
+ </sect1>
+ </chapter>
+
<chapter id="netcore">
<title>Linux Networking</title>
<sect1><title>Networking Base Types</title>
</sect1>
</chapter>
- <chapter id="sysfs">
- <title>The Filesystem for Exporting Kernel Objects</title>
-!Efs/sysfs/file.c
-!Efs/sysfs/symlink.c
-!Efs/sysfs/bin.c
- </chapter>
-
<chapter id="security">
<title>Security Framework</title>
!Esecurity/security.c
-->
!Edrivers/base/driver.c
!Edrivers/base/core.c
+!Edrivers/base/class.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
!Edrivers/base/dmapool.c
!Eblock/ll_rw_blk.c
</chapter>
+ <chapter id="chrdev">
+ <title>Char devices</title>
+!Efs/char_dev.c
+ </chapter>
+
<chapter id="miscdev">
<title>Miscellaneous Devices</title>
!Edrivers/char/misc.c
Documentation/kernel-parameters.txt.
18: All new module parameters are documented with MODULE_PARM_DESC()
+
+19: All new userspace interfaces are documented in Documentation/ABI/.
+ See Documentation/ABI/README for more information.
are the same person/entity. If not, the name of
the person/entity authorizing use of GPL should be
listed in case it's necessary to verify the will of
- the copright owner.
+ the copyright owner.
Interfaces: If your driver uses existing interfaces and behaves like
other drivers in the same class it will be much more likely
- to be accepted than if it invents gratuitous new ones.
+ to be accepted than if it invents gratuitous new ones.
If you need to implement a common API over Linux and NT
drivers do it in userspace.
it will go in the bitbucket.
Control: In general if there is active maintainance of a driver by
- the author then patches will be redirected to them unless
+ the author then patches will be redirected to them unless
they are totally obvious and without need of checking.
If you want to be the contact and update point for the
driver it is a good idea to state this in the comments,
Vendor: Being the hardware vendor and maintaining the driver is
often a good thing. If there is a stable working driver from
other people already in the tree don't expect 'we are the
- vendor' to get your driver chosen. Ideally work with the
+ vendor' to get your driver chosen. Ideally work with the
existing driver author to build a single perfect driver.
Author: It doesn't matter if a large Linux company wrote the driver,
ftp.??.kernel.org:/pub/linux/kernel/...
?? == your country code, such as "us", "uk", "fr", etc.
-Linux kernel mailing list:
+Linux kernel mailing list:
linux-kernel@vger.kernel.org
[mail majordomo@vger.kernel.org to subscribe]
Linux Device Drivers, Third Edition (covers 2.6.10):
http://lwn.net/Kernel/LDD3/ (free version)
-Kernel traffic:
- Weekly summary of kernel list activity (much easier to read)
- http://www.kerneltraffic.org/kernel-traffic/
-
LWN.net:
Weekly summary of kernel development activity - http://lwn.net/
2.6 API changes:
Linux USB project:
http://www.linux-usb.org/
-How to NOT write kernel driver by arjanv@redhat.com
- http://people.redhat.com/arjanv/olspaper.pdf
+How to NOT write kernel driver by Arjan van de Ven:
+ http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
Kernel Janitor:
http://janitor.kernelnewbies.org/
-
---
-Last updated on 17 Nov 2005.
trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
patches. Trivial patches must qualify for one of the following rules:
Spelling fixes in documentation
- Spelling fixes which could break grep(1).
+ Spelling fixes which could break grep(1)
Warning fixes (cluttering with useless warnings is bad)
Compilation fixes (only if they are actually correct)
Runtime fixes (only if they actually fix things)
- Removing use of deprecated functions/macros (eg. check_region).
+ Removing use of deprecated functions/macros (eg. check_region)
Contact detail and documentation fixes
Non-portable code replaced by portable code (even in arch-specific,
since people copy, as long as it's trivial)
- Any fix by the author/maintainer of the file. (ie. patch monkey
+ Any fix by the author/maintainer of the file (ie. patch monkey
in re-transmission mode)
URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
you to re-send them using MIME.
+WARNING: Some mailers like Mozilla send your messages with
+---- message header ----
+Content-Type: text/plain; charset=us-ascii; format=flowed
+---- message header ----
+The problem is that "format=flowed" makes some of the mailers
+on receiving side to replace TABs with spaces and do similar
+changes. Thus the patches from you can look corrupted.
+
+To fix this just make your mozilla defaults/pref/mailnews.js file to look like:
+pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+pref("mailnews.display.disable_format_flowed_support", true);
+
+
7) E-mail size.
It is quite common for Linus to "drop" your patch without comment.
That's the nature of the system. If he drops your patch, it could be
due to
-* Your patch did not apply cleanly to the latest kernel version
+* Your patch did not apply cleanly to the latest kernel version.
* Your patch was not sufficiently discussed on linux-kernel.
-* A style issue (see section 2),
-* An e-mail formatting issue (re-read this section)
-* A technical problem with your change
-* He gets tons of e-mail, and yours got lost in the shuffle
-* You are being annoying (See Figure 1)
+* A style issue (see section 2).
+* An e-mail formatting issue (re-read this section).
+* A technical problem with your change.
+* He gets tons of e-mail, and yours got lost in the shuffle.
+* You are being annoying.
When in doubt, solicit comments on linux-kernel mailing list.
Andrew Morton, "The perfect patch" (tpp).
<http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
-Jeff Garzik, "Linux kernel patch submission format."
+Jeff Garzik, "Linux kernel patch submission format".
<http://linux.yyz.us/patch-format.html>
-Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
<http://www.kroah.com/log/2005/03/31/>
<http://www.kroah.com/log/2005/07/08/>
<http://www.kroah.com/log/2005/10/19/>
NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
<http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
-Kernel Documentation/CodingStyle
+Kernel Documentation/CodingStyle:
<http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
-Linus Torvald's mail on the canonical patch format:
+Linus Torvalds's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
--
to represent the cpuset hierarchy provides for a familiar permission
and name space for cpusets, with a minimum of additional kernel code.
-The cpus file in the root (top_cpuset) cpuset is read-only.
-It automatically tracks the value of cpu_online_map, using a CPU
-hotplug notifier. If and when memory nodes can be hotplugged,
-we expect to make the mems file in the root cpuset read-only
-as well, and have it track the value of node_online_map.
+The cpus and mems files in the root (top_cpuset) cpuset are
+read-only. The cpus file automatically tracks the value of
+cpu_online_map using a CPU hotplug notifier, and the mems file
+automatically tracks the value of node_online_map using the
+cpuset_track_online_nodes() hook.
1.4 What are exclusive cpusets ?
2.9 Appletalk
2.10 IPX
2.11 /proc/sys/fs/mqueue - POSIX message queues filesystem
+ 2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
+ 2.13 /proc/<pid>/oom_score - Display current oom-killer score
------------------------------------------------------------------------------
Preface
maximum message size value (it is every message queue's attribute set during
its creation).
+2.12 /proc/<pid>/oom_adj - Adjust the oom-killer score
+------------------------------------------------------
+
+This file can be used to adjust the score used to select which processes
+should be killed in an out-of-memory situation. Giving it a high score will
+increase the likelihood of this process being killed by the oom-killer. Valid
+values are in the range -16 to +15, plus the special value -17, which disables
+oom-killing altogether for this process.
+
+2.13 /proc/<pid>/oom_score - Display current oom-killer score
+-------------------------------------------------------------
+
+------------------------------------------------------------------------------
+This file can be used to check the current score used by the oom-killer is for
+any given <pid>. Use it together with /proc/<pid>/oom_adj to tune which
+process should be killed in an out-of-memory situation.
------------------------------------------------------------------------------
Summary
it will appear as a kernel argument readable via /proc/cmdline by programs
running once the system is up.
+The number of kernel parameters is not limited, but the length of the
+complete command line (parameters including spaces etc.) is limited to
+a fixed number of characters. This limit depends on the architecture
+and is between 256 and 4096 characters. It is defined in the file
+./include/asm/setup.h as COMMAND_LINE_SIZE.
+
+
53c7xx= [HW,SCSI] Amiga SCSI controllers
See header of drivers/scsi/53c7xx.c.
See also Documentation/scsi/ncr53c7xx.txt.
pt. [PARIDE]
See Documentation/paride.txt.
- quiet= [KNL] Disable log messages
+ quiet [KNL] Disable most log messages
r128= [HW,DRM]
are: IPSRC_RND #IP Source is random (between min/max),
IPDST_RND, UDPSRC_RND,
UDPDST_RND, MACSRC_RND, MACDST_RND
+ MPLS_RND, VID_RND, SVID_RND
pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then
cycle through the port range.
pgset "mpls 0" turn off mpls (or any invalid argument works too!)
+ pgset "vlan_id 77" set VLAN ID 0-4095
+ pgset "vlan_p 3" set priority bit 0-7 (default 0)
+ pgset "vlan_cfi 0" set canonical format identifier 0-1 (default 0)
+
+ pgset "svlan_id 22" set SVLAN ID 0-4095
+ pgset "svlan_p 3" set priority bit 0-7 (default 0)
+ pgset "svlan_cfi 0" set canonical format identifier 0-1 (default 0)
+
+ pgset "vlan_id 9999" > 4095 remove vlan and svlan tags
+ pgset "svlan 9999" > 4095 remove svlan tag
+
+
+ pgset "tos XX" set former IPv4 TOS field (e.g. "tos 28" for AF11 no ECN, default 00)
+ pgset "traffic_class XX" set former IPv6 TRAFFIC CLASS (e.g. "traffic_class B8" for EF no ECN, default 00)
+
pgset stop aborts injection. Also, ^C aborts generator.
+++ /dev/null
-BSD Secure Levels Linux Security Module
-Michael A. Halcrow <mike@halcrow.us>
-
-
-Introduction
-
-Under the BSD Secure Levels security model, sets of policies are
-associated with levels. Levels range from -1 to 2, with -1 being the
-weakest and 2 being the strongest. These security policies are
-enforced at the kernel level, so not even the superuser is able to
-disable or circumvent them. This hardens the machine against attackers
-who gain root access to the system.
-
-
-Levels and Policies
-
-Level -1 (Permanently Insecure):
- - Cannot increase the secure level
-
-Level 0 (Insecure):
- - Cannot ptrace the init process
-
-Level 1 (Default):
- - /dev/mem and /dev/kmem are read-only
- - IMMUTABLE and APPEND extended attributes, if set, may not be unset
- - Cannot load or unload kernel modules
- - Cannot write directly to a mounted block device
- - Cannot perform raw I/O operations
- - Cannot perform network administrative tasks
- - Cannot setuid any file
-
-Level 2 (Secure):
- - Cannot decrement the system time
- - Cannot write to any block device, whether mounted or not
- - Cannot unmount any mounted filesystems
-
-
-Compilation
-
-To compile the BSD Secure Levels LSM, seclvl.ko, enable the
-SECURITY_SECLVL configuration option. This is found under Security
-options -> BSD Secure Levels in the kernel configuration menu.
-
-
-Basic Usage
-
-Once the machine is in a running state, with all the necessary modules
-loaded and all the filesystems mounted, you can load the seclvl.ko
-module:
-
-# insmod seclvl.ko
-
-The module defaults to secure level 1, except when compiled directly
-into the kernel, in which case it defaults to secure level 0. To raise
-the secure level to 2, the administrator writes ``2'' to the
-seclvl/seclvl file under the sysfs mount point (assumed to be /sys in
-these examples):
-
-# echo -n "2" > /sys/seclvl/seclvl
-
-Alternatively, you can initialize the module at secure level 2 with
-the initlvl module parameter:
-
-# insmod seclvl.ko initlvl=2
-
-At this point, it is impossible to remove the module or reduce the
-secure level. If the administrator wishes to have the option of doing
-so, he must provide a module parameter, sha1_passwd, that specifies
-the SHA1 hash of the password that can be used to reduce the secure
-level to 0.
-
-To generate this SHA1 hash, the administrator can use OpenSSL:
-
-# echo -n "boogabooga" | openssl sha1
-abeda4e0f33defa51741217592bf595efb8d289c
-
-In order to use password-instigated secure level reduction, the SHA1
-crypto module must be loaded or compiled into the kernel:
-
-# insmod sha1.ko
-
-The administrator can then insmod the seclvl module, including the
-SHA1 hash of the password:
-
-# insmod seclvl.ko
- sha1_passwd=abeda4e0f33defa51741217592bf595efb8d289c
-
-To reduce the secure level, write the password to seclvl/passwd under
-your sysfs mount point:
-
-# echo -n "boogabooga" > /sys/seclvl/passwd
-
-The September 2004 edition of Sys Admin Magazine has an article about
-the BSD Secure Levels LSM. I encourage you to refer to that article
-for a more in-depth treatment of this security module:
-
-http://www.samag.com/documents/s=9304/sam0409a/0409a.htm
M: Douglas_Warzecha@dell.com
S: Maintained
-DEVICE-MAPPER
+DEVICE-MAPPER (LVM)
P: Alasdair Kergon
L: dm-devel@redhat.com
W: http://sources.redhat.com/dm
W: http://www.linux-ax25.org/
S: Maintained
-NETWORK BLOCK DEVICE
+NETWORK BLOCK DEVICE (NBD)
P: Paul Clements
M: Paul.Clements@steeleye.com
S: Maintained
L: linux-kernel@vger.kernel.org ?
S: Supported
+SPIDERNET NETWORK DRIVER for CELL
+P: Jim Lewis
+M: jim@jklewis.com
+L: netdev@vger.kernel.org
+S: Supported
+
SRM (Alpha) environment access
P: Jan-Benedict Glaw
M: jbglaw@lug-owl.de
SUPERH (sh)
P: Paul Mundt
M: lethal@linux-sh.org
-P: Kazumoto Kojima
-M: kkojima@rr.iij4u.or.jp
-L: linuxsh-dev@lists.sourceforge.net
+L: linuxsh-dev@lists.sourceforge.net (subscribers-only)
W: http://www.linux-sh.org
W: http://www.m17n.org/linux-sh/
-W: http://www.rr.iij4u.or.jp/~kkojima/linux-sh4.html
S: Maintained
SUPERH64 (sh64)
nticks = delta >> FIX_SHIFT;
while (nticks > 0) {
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
/* We ran out of memory, or some other thing happened to us that
made us unable to handle the page fault gracefully. */
out_of_memory:
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
profile_tick(CPU_PROFILING, regs);
do_leds();
do_set_rtc();
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
};
static struct omap_kp_platform_data kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = fsample_keymap,
+ .rows = 8,
+ .cols = 8,
+ .keymap = fsample_keymap,
+ .keymapsize = ARRAY_SIZE(fsample_keymap),
+ .delay = 4,
};
static struct platform_device kp_device = {
};
static struct omap_kp_platform_data h2_kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = h2_keymap,
- .rep = 1,
+ .rows = 8,
+ .cols = 8,
+ .keymap = h2_keymap,
+ .keymapsize = ARRAY_SIZE(h2_keymap),
+ .rep = 1,
+ .delay = 9,
+ .dbounce = 1,
};
static struct platform_device h2_kp_device = {
};
static struct omap_kp_platform_data h3_kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = h3_keymap,
- .rep = 1,
+ .rows = 8,
+ .cols = 8,
+ .keymap = h3_keymap,
+ .keymapsize = ARRAY_SIZE(h3_keymap),
+ .rep = 1,
+ .delay = 9,
+ .dbounce = 1,
};
static struct platform_device h3_kp_device = {
};
static struct omap_kp_platform_data innovator_kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = innovator_keymap,
+ .rows = 8,
+ .cols = 8,
+ .keymap = innovator_keymap,
+ .keymapsize = ARRAY_SIZE(innovator_keymap),
+ .delay = 4,
};
static struct platform_device innovator_kp_device = {
};
static struct omap_kp_platform_data nokia770_kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = nokia770_keymap
+ .rows = 8,
+ .cols = 8,
+ .keymap = nokia770_keymap,
+ .keymapsize = ARRAY_SIZE(nokia770_keymap)
+ .delay = 4,
};
static struct platform_device nokia770_kp_device = {
};
static struct omap_kp_platform_data osk_kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = (int *) osk_keymap,
+ .rows = 8,
+ .cols = 8,
+ .keymap = (int *) osk_keymap,
+ .keymapsize = ARRAY_SIZE(osk_keymap),
+ .delay = 9,
};
static struct resource osk5912_kp_resources[] = {
};
static struct omap_kp_platform_data kp_data = {
- .rows = 8,
- .cols = 8,
- .keymap = p2_keymap,
+ .rows = 8,
+ .cols = 8,
+ .keymap = p2_keymap,
+ .keymapsize = ARRAY_SIZE(p2_keymap),
+ .delay = 4,
+ .dbounce = 1,
};
static struct platform_device kp_device = {
.rows = 6,
.cols = 7,
.keymap = h4_keymap,
+ .keymapsize = ARRAY_SIZE(h4_keymap),
.rep = 1,
.row_gpios = row_gpios,
.col_gpios = col_gpios,
if (fsr & (1 << 11)) /* write? */
mask = VM_WRITE;
else
- mask = VM_READ|VM_EXEC;
+ mask = VM_READ|VM_EXEC|VM_WRITE;
fault = VM_FAULT_BADACCESS;
if (!(vma->vm_flags & mask))
return fault;
}
- if (tsk->pid != 1)
+ if (!is_init(tsk))
goto out;
/*
static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
*/
good_area:
if (READ_FAULT(fsr)) /* read? */
- mask = VM_READ|VM_EXEC;
+ mask = VM_READ|VM_EXEC|VM_WRITE;
else
mask = VM_WRITE;
}
fault = -3; /* out of memory */
- if (tsk->pid != 1)
+ if (!is_init(tsk))
goto out;
/*
* Call the generic timer interrupt handler
*/
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
write_sequnlock(&xtime_lock);
/*
/* call the real timer interrupt handler */
- do_timer(regs);
+ do_timer(1);
cris_do_profile(regs); /* Save profiling information */
return IRQ_HANDLED;
/* call the real timer interrupt handler */
- do_timer(regs);
+ do_timer(1);
/*
* If we have an externally synchronized Linux clock, then update
*/
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
update_process_times(user_mode(regs));
profile_tick(CPU_PROFILING, regs);
/* may need to kick the hardware timer */
platform_timer_eoi();
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
#include <linux/smp_lock.h>
#include <linux/dmi.h>
#include <linux/suspend.h>
+#include <linux/kthread.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#else
static int realmode_power_off;
#endif
-static int exit_kapmd __read_mostly;
-static int kapmd_running __read_mostly;
#ifdef CONFIG_APM_ALLOW_INTS
static int allow_ints = 1;
#else
static const char driver_version[] = "1.16ac"; /* no spaces */
+static struct task_struct *kapmd_task;
+
/*
* APM event names taken from the APM 1.2 specification. These are
* the message codes that the BIOS uses to tell us about events
set_current_state(TASK_INTERRUPTIBLE);
for (;;) {
schedule_timeout(APM_CHECK_TIMEOUT);
- if (exit_kapmd)
+ if (kthread_should_stop())
break;
/*
* Ok, check all events, check for idle (and mark us sleeping
char * power_stat;
char * bat_stat;
- kapmd_running = 1;
-
- daemonize("kapmd");
-
- current->flags |= PF_NOFREEZE;
-
#ifdef CONFIG_SMP
/* 2002/08/01 - WT
* This is to avoid random crashes at boot time during initialization
console_blank_hook = NULL;
#endif
}
- kapmd_running = 0;
return 0;
}
{
struct proc_dir_entry *apm_proc;
struct desc_struct *gdt;
- int ret;
+ int err;
dmi_check_system(apm_dmi_table);
if (apm_proc)
apm_proc->owner = THIS_MODULE;
- ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
- if (ret < 0) {
- printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
+ kapmd_task = kthread_create(apm, NULL, "kapmd");
+ if (IS_ERR(kapmd_task)) {
+ printk(KERN_ERR "apm: disabled - Unable to start kernel "
+ "thread.\n");
+ err = PTR_ERR(kapmd_task);
+ kapmd_task = NULL;
remove_proc_entry("apm", NULL);
- return -ENOMEM;
+ return err;
}
+ kapmd_task->flags |= PF_NOFREEZE;
+ wake_up_process(kapmd_task);
if (num_online_cpus() > 1 && !smp ) {
printk(KERN_NOTICE
remove_proc_entry("apm", NULL);
if (power_off)
pm_power_off = NULL;
- exit_kapmd = 1;
- while (kapmd_running)
- schedule();
+ if (kapmd_task) {
+ kthread_stop(kapmd_task);
+ kapmd_task = NULL;
+ }
#ifdef CONFIG_PM_LEGACY
pm_active = 0;
#endif
static DEFINE_SPINLOCK(efi_rt_lock);
static pgd_t efi_bak_pg_dir_pointer[2];
-static void efi_call_phys_prelog(void)
+static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
{
unsigned long cr4;
unsigned long temp;
load_gdt(cpu_gdt_descr);
}
-static void efi_call_phys_epilog(void)
+static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
{
unsigned long cr4;
struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
{ [0 ... NR_CPUS-1] = 0xff };
EXPORT_SYMBOL(x86_cpu_to_apicid);
+u8 apicid_2_node[MAX_APICID];
+
/*
* Trampoline 80x86 program as an array.
*/
{
int cpu = smp_processor_id();
int apicid = logical_smp_processor_id();
- int node = apicid_to_node(apicid);
+ int node = apicid_to_node(hard_smp_processor_id());
if (!node_online(node))
node = first_online_node;
irq_ctx_init(cpu);
+ x86_cpu_to_apicid[cpu] = apicid;
/*
* This grunge runs the startup process for
* the targeted processor.
#include <linux/nodemask.h>
#include <asm/srat.h>
#include <asm/topology.h>
+#include <asm/smp.h>
/*
* proximity macros and definitions
static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
static int num_memory_chunks; /* total number of memory chunks */
+static u8 __initdata apicid_to_pxm[MAX_APICID];
extern void * boot_ioremap(unsigned long, unsigned long);
/* mark this node as "seen" in node bitmap */
BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain);
+ apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain;
+
printk("CPU 0x%02X in proximity domain 0x%02X\n",
cpu_affinity->apic_id, cpu_affinity->proximity_domain);
}
printk("Number of logical nodes in system = %d\n", num_online_nodes());
printk("Number of memory chunks in system = %d\n", num_memory_chunks);
+ for (i = 0; i < MAX_APICID; i++)
+ apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+
for (j = 0; j < num_memory_chunks; j++){
struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
retval = get_user_pages(current, current->mm,
(unsigned long )to, 1, 1, 0, &pg, NULL);
- if (retval == -ENOMEM && current->pid == 1) {
+ if (retval == -ENOMEM && is_init(current)) {
up_read(¤t->mm->mmap_sem);
blk_congestion_wait(WRITE, HZ/50);
goto survive;
case 1: /* read, present */
goto bad_area;
case 0: /* read, not present */
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto bad_area;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
static void ppro_start(struct op_msrs const * const msrs)
{
unsigned int low,high;
+ int i;
- if (reset_value[0]) {
- CTRL_READ(low, high, msrs, 0);
- CTRL_SET_ACTIVE(low);
- CTRL_WRITE(low, high, msrs, 0);
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (reset_value[i]) {
+ CTRL_READ(low, high, msrs, i);
+ CTRL_SET_ACTIVE(low);
+ CTRL_WRITE(low, high, msrs, i);
+ }
}
}
static void ppro_stop(struct op_msrs const * const msrs)
{
unsigned int low,high;
+ int i;
- if (reset_value[0]) {
- CTRL_READ(low, high, msrs, 0);
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (!reset_value[i])
+ continue;
+ CTRL_READ(low, high, msrs, i);
CTRL_SET_INACTIVE(low);
- CTRL_WRITE(low, high, msrs, 0);
+ CTRL_WRITE(low, high, msrs, i);
}
}
}
printk(KERN_INFO "simeth_device_event: %s ipaddr=0x%x\n",
- dev->name, htonl(ifa->ifa_local));
+ dev->name, ntohl(ifa->ifa_local));
/*
* XXX Fix me
local = dev->priv;
/* now do it for real */
r = event == NETDEV_UP ?
- netdev_attach(local->simfd, dev->irq, htonl(ifa->ifa_local)):
+ netdev_attach(local->simfd, dev->irq, ntohl(ifa->ifa_local)):
netdev_detach(local->simfd);
printk(KERN_INFO "simeth: netdev_attach/detach: event=%s ->%d\n",
* xtime_lock.
*/
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
local_cpu_data->itm_next = new_itm;
write_sequnlock(&xtime_lock);
} else
# error File is out of sync with <linux/mm.h>. Please update.
# endif
+ if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE))))
+ goto bad_area;
+
mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
- | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
- | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
+ | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
if ((vma->vm_flags & mask) != mask)
goto bad_area;
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
#ifndef CONFIG_SMP
profile_tick(CPU_PROFILING, regs);
#endif
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
*/
static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
{
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
case 1: /* read, present */
goto acc_err;
case 0: /* read, not present */
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto acc_err;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
#ifdef CONFIG_SUN3
intersil_clear();
#endif
- do_timer(fp);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(fp));
#endif
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
timerlo = count;
kstat_this_cpu.irqs[irq]++;
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
}
while (time_elapsed > 0) {
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
if (jiffie_drift >= 999) {
jiffie_drift -= 999;
- do_timer(regs); /* increment jiffies by one */
+ do_timer(1); /* increment jiffies by one */
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
if (irq_src & 0x00000800) { /* Check for timer interrupt */
handled = 1;
irq_src &= ~0x00000800;
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
/*
* call the generic timer interrupt handling
*/
- do_timer(regs);
+ do_timer(1);
/*
* If we have an externally synchronized Linux clock, then update
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
/* handle the timer call */
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */
if (cpu == 0)
- do_timer(regs);
+ do_timer(1);
update_process_times(user_mode(regs));
* - SEGREL32 handling
* We are not doing SEGREL32 handling correctly. According to the ABI, we
* should do a value offset, like this:
- * if (is_init(me, (void *)val))
+ * if (in_init(me, (void *)val))
* val -= (uint32_t)me->module_init;
* else
* val -= (uint32_t)me->module_core;
/* three functions to determine where in the module core
* or init pieces the location is */
-static inline int is_init(struct module *me, void *loc)
+static inline int in_init(struct module *me, void *loc)
{
return (loc >= me->module_init &&
loc <= (me->module_init + me->init_size));
}
-static inline int is_core(struct module *me, void *loc)
+static inline int in_core(struct module *me, void *loc)
{
return (loc >= me->module_core &&
loc <= (me->module_core + me->core_size));
}
-static inline int is_local(struct module *me, void *loc)
+static inline int in_local(struct module *me, void *loc)
{
- return is_init(me, loc) || is_core(me, loc);
+ return in_init(me, loc) || in_core(me, loc);
}
-static inline int is_local_section(struct module *me, void *loc, void *dot)
+static inline int in_local_section(struct module *me, void *loc, void *dot)
{
- return (is_init(me, loc) && is_init(me, dot)) ||
- (is_core(me, loc) && is_core(me, dot));
+ return (in_init(me, loc) && in_init(me, dot)) ||
+ (in_core(me, loc) && in_core(me, dot));
}
break;
case R_PARISC_PCREL17F:
/* 17-bit PC relative address */
- val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
val = (val - dot - 8)/4;
CHECK_RELOC(val, 17)
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break;
case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */
- val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
+ val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
strtab + sym->st_name, (unsigned long)loc, addend,
val)
strtab + sym->st_name,
loc, val);
/* can we reach it locally? */
- if(!is_local_section(me, (void *)val, (void *)dot)) {
+ if(!in_local_section(me, (void *)val, (void *)dot)) {
- if (is_local(me, (void *)val))
+ if (in_local(me, (void *)val))
/* this is the case where the
* symbol is local to the
* module, but in a different
* in case it's more than 22
* bits away */
val = get_stub(me, val, addend, ELF_STUB_DIRECT,
- is_init(me, loc));
+ in_init(me, loc));
else if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, ELF_STUB_MILLI,
- is_init(me, loc));
+ in_init(me, loc));
else
val = get_stub(me, val, addend, ELF_STUB_GOT,
- is_init(me, loc));
+ in_init(me, loc));
}
DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
strtab + sym->st_name, loc, sym->st_value,
break;
case R_PARISC_FPTR64:
/* 64-bit function address */
- if(is_local(me, (void *)(val + addend))) {
+ if(in_local(me, (void *)(val + addend))) {
*loc64 = get_fdesc(me, val+addend);
DEBUGP("FDESC for %s at %p points to %lx\n",
strtab + sym->st_name, *loc64,
#endif
if (cpu == 0) {
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
write_sequnlock(&xtime_lock);
}
}
tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
tb_last_jiffy = tb_next_jiffy;
- do_timer(regs);
+ do_timer(1);
timer_recalc_offset(tb_last_jiffy);
timer_check_rtc();
}
/* protection fault */
if (error_code & 0x08000000)
goto bad_area;
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto bad_area;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
err->disposition == RTAS_DISP_NOT_RECOVERED &&
err->target == RTAS_TARGET_MEMORY &&
err->type == RTAS_TYPE_ECC_UNCORR &&
- !(current->pid == 0 || current->pid == 1)) {
+ !(current->pid == 0 || is_init(current))) {
/* Kill off a user process with an ECC error */
printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
current->pid);
/* We are in an interrupt, no need to save/restore flags */
write_seqlock(&xtime_lock);
tb_last_stamp = jiffy_stamp;
- do_timer(regs);
+ do_timer(1);
/*
* update the rtc when needed, this should be performed on the
* generate the same exception over and over again and we get
* nowhere. Better to kill it and let the kernel panic.
*/
- if (current->pid == 1) {
+ if (is_init(current)) {
__sighandler_t handler;
spin_lock_irq(¤t->sighand->siglock);
/* protection fault */
if (error_code & 0x08000000)
goto bad_area;
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto bad_area;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
-#include <linux/page-flags.h>
+#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
#include <linux/sysctl.h>
void account_ticks(struct pt_regs *regs)
{
__u64 tmp;
- __u32 ticks, xticks;
+ __u32 ticks;
/* Calculate how many ticks have passed. */
if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
*/
write_seqlock(&xtime_lock);
if (S390_lowcore.jiffy_timer > xtime_cc) {
+ __u32 xticks;
tmp = S390_lowcore.jiffy_timer - xtime_cc;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
xticks = 1;
xtime_cc += CLK_TICKS_PER_JIFFY;
}
- while (xticks--)
- do_timer(regs);
+ do_timer(xticks);
}
write_sequnlock(&xtime_lock);
#else
- for (xticks = ticks; xticks > 0; xticks--)
- do_timer(regs);
+ do_timer(ticks);
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
*/
void handle_timer_tick(struct pt_regs *regs)
{
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
} else {
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto bad_area;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
asm ("getcon cr62, %0" : "=r" (current_ctc));
ctc_last_interrupt = (unsigned long) current_ctc;
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
show_regs(regs);
#endif
}
- if (tsk->pid == 1) {
+ if (is_init(tsk)) {
panic("INIT had user mode bad_area\n");
}
tsk->thread.address = address;
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (current->pid == 1) {
+ if (is_init(current)) {
panic("INIT out of memory\n");
yield();
goto survive;
}
printk("fault:Out of memory\n");
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
{
write_seqlock(&xtime_lock); /* Dummy, to show that we remember */
pcic_clear_clock_irq();
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
#endif
clear_clock_irq();
- do_timer(regs);
+ do_timer(1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
profile_tick(CPU_PROFILING, regs);
update_process_times(user_mode(regs));
#endif
- do_timer(regs);
+ do_timer(1);
/* Guarantee that the following sequences execute
* uninterrupted.
{
write_seqlock(&xtime_lock);
- do_timer(regs);
+ do_timer(1);
timer_check_rtc();
#include <linux/limits.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/tty.h>
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/timex.h>
Solaris setpgrp and setsid? */
ret = sys_setpgid(0, 0);
if (ret) return ret;
+ mutex_lock(&tty_mutex);
current->signal->tty = NULL;
+ mutex_unlock(&tty_mutex);
return process_group(current);
}
case 2: /* getsid */
mconsole_reply(req, err_msg, err, 0);
}
+struct mconsole_output {
+ struct list_head list;
+ struct mc_request *req;
+};
+
static DEFINE_SPINLOCK(console_lock);
static LIST_HEAD(clients);
static char console_buf[MCONSOLE_MAX_DATA];
return;
list_for_each(ele, &clients){
- struct mconsole_entry *entry;
+ struct mconsole_output *entry;
- entry = list_entry(ele, struct mconsole_entry, list);
- mconsole_reply_len(&entry->request, console_buf,
+ entry = list_entry(ele, struct mconsole_output, list);
+ mconsole_reply_len(entry->req, console_buf,
console_index, 0, 1);
}
static void with_console(struct mc_request *req, void (*proc)(void *),
void *arg)
{
- struct mconsole_entry entry;
+ struct mconsole_output entry;
unsigned long flags;
- entry.request = *req;
+ entry.req = req;
list_add(&entry.list, &clients);
spin_lock_irqsave(&console_lock, flags);
int mconsole_reply_len(struct mc_request *req, const char *str, int total,
int err, int more)
{
+ /* XXX This is a stack consumption problem. It'd be nice to
+ * make it global and serialize access to it, but there are a
+ * ton of callers to this function.
+ */
struct mconsole_reply reply;
int len, n;
goto out;
}
- if(!lp->have_mac){
- dev_ip_addr(dev, &lp->mac[2]);
- set_ether_mac(dev, lp->mac);
- }
-
lp->fd = (*lp->open)(&lp->user);
if(lp->fd < 0){
err = lp->fd;
#endif
}
+static void setup_etheraddr(char *str, unsigned char *addr)
+{
+ char *end;
+ int i;
+
+ if(str == NULL)
+ goto random;
+
+ for(i=0;i<6;i++){
+ addr[i] = simple_strtoul(str, &end, 16);
+ if((end == str) ||
+ ((*end != ':') && (*end != ',') && (*end != '\0'))){
+ printk(KERN_ERR
+ "setup_etheraddr: failed to parse '%s' "
+ "as an ethernet address\n", str);
+ goto random;
+ }
+ str = end + 1;
+ }
+ if(addr[0] & 1){
+ printk(KERN_ERR
+ "Attempt to assign a broadcast ethernet address to a "
+ "device disallowed\n");
+ goto random;
+ }
+ return;
+
+random:
+ random_ether_addr(addr)
+}
+
static DEFINE_SPINLOCK(devices_lock);
static LIST_HEAD(devices);
list_add(&device->list, &devices);
spin_unlock(&devices_lock);
- if (setup_etheraddr(mac, device->mac))
- device->have_mac = 1;
+ setup_etheraddr(mac, device->mac);
printk(KERN_INFO "Netdevice %d ", n);
- if (device->have_mac)
- printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
- device->mac[0], device->mac[1],
- device->mac[2], device->mac[3],
- device->mac[4], device->mac[5]);
+ printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+ device->mac[0], device->mac[1],
+ device->mac[2], device->mac[3],
+ device->mac[4], device->mac[5]);
printk(": ");
dev = alloc_etherdev(size);
if (dev == NULL) {
.dev = dev,
.fd = -1,
.mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
- .have_mac = device->have_mac,
.protocol = transport->kern->protocol,
.open = transport->user->open,
.close = transport->user->close,
init_timer(&lp->tl);
spin_lock_init(&lp->lock);
lp->tl.function = uml_net_user_timer_expire;
- if (lp->have_mac)
- memcpy(lp->mac, device->mac, sizeof(lp->mac));
+ memcpy(lp->mac, device->mac, sizeof(lp->mac));
if (transport->user->init)
(*transport->user->init)(&lp->user, dev);
- if (device->have_mac)
- set_ether_mac(dev, device->mac);
+ set_ether_mac(dev, device->mac);
return 0;
}
__uml_exitcall(close_devices);
-int setup_etheraddr(char *str, unsigned char *addr)
-{
- char *end;
- int i;
-
- if(str == NULL)
- return(0);
- for(i=0;i<6;i++){
- addr[i] = simple_strtoul(str, &end, 16);
- if((end == str) ||
- ((*end != ':') && (*end != ',') && (*end != '\0'))){
- printk(KERN_ERR
- "setup_etheraddr: failed to parse '%s' "
- "as an ethernet address\n", str);
- return(0);
- }
- str = end + 1;
- }
- if(addr[0] & 1){
- printk(KERN_ERR
- "Attempt to assign a broadcast ethernet address to a "
- "device disallowed\n");
- return(0);
- }
- return(1);
-}
-
-void dev_ip_addr(void *d, unsigned char *bin_buf)
-{
- struct net_device *dev = d;
- struct in_device *ip = dev->ip_ptr;
- struct in_ifaddr *in;
-
- if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
- printk(KERN_WARNING "dev_ip_addr - device not assigned an "
- "IP address\n");
- return;
- }
- memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
-}
-
struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
{
if((skb != NULL) && (skb_tailroom(skb) < extra)){
struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in;
- __u32 *mask_out = m;
+ __be32 *mask_out = m;
if(ip == NULL)
return(1);
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/time.h>
#include "user.h"
#include "user_util.h"
#include "kern_util.h"
#include "chan_user.h"
#include "os.h"
+/* This address is used only as a unique identifer */
static int null_chan;
static void *null_init(char *str, int device, const struct chan_opts *opts)
#define RNG_MISCDEV_MINOR 183 /* official */
+/* Changed at init time, in the non-modular case, and at module load
+ * time, in the module case. Presumably, the module subsystem
+ * protects against a module being loaded twice at the same time.
+ */
static int random_fd = -1;
static int rng_dev_open (struct inode *inode, struct file *filp)
/*
* Don't register by default -- as this registeres very early in the
* boot process it becomes the default console.
+ *
+ * Initialized at init time.
*/
static int use_stderr_console = 0;
return line_open(vts, tty);
}
+/* Set in an initcall, checked in an exitcall */
static int con_init_done = 0;
static const struct tty_operations console_ops = {
if(dev->file == NULL)
goto out;
- if (ubd_open_dev(dev))
- goto out;
-
err = ubd_file_size(dev, &dev->size);
if(err < 0)
- goto out_close;
+ goto out;
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
if(err)
- goto out_close;
+ goto out;
if(fake_major != MAJOR_NR)
ubd_new_disk(fake_major, dev->size, n,
make_ide_entries(ubd_gendisk[n]->disk_name);
err = 0;
-out_close:
- ubd_close(dev);
out:
return err;
}
struct platform_device pdev;
int index;
unsigned char mac[ETH_ALEN];
- int have_mac;
};
struct uml_net_private {
struct net_device_stats stats;
int fd;
unsigned char mac[ETH_ALEN];
- int have_mac;
unsigned short (*protocol)(struct sk_buff *);
int (*open)(void *);
void (*close)(int, void *);
extern struct net_device *ether_init(int);
extern unsigned short ether_protocol(struct sk_buff *);
-extern int setup_etheraddr(char *str, unsigned char *addr);
extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
extern int tap_setup_common(char *str, char *type, char **dev_name,
char **mac_out, char **gate_addr);
extern unsigned short eth_protocol(struct sk_buff *skb);
#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:
- */
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
};
extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, unsigned char *bin_buf);
-extern void iter_addresses(void *d, void (*cb)(unsigned char *,
- unsigned char *, void *),
+extern void iter_addresses(void *d, void (*cb)(unsigned char *,
+ unsigned char *, void *),
void *arg);
extern void *get_output_buffer(int *len_out);
extern int dev_netmask(void *d, void *m);
#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:
- */
static int read_proc_exitcode(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- int len;
+ int len, val;
- len = sprintf(page, "%d\n", uml_exitcode);
+ /* Save uml_exitcode in a local so that we don't need to guarantee
+ * that sprintf accesses it atomically.
+ */
+ val = uml_exitcode;
+ len = sprintf(page, "%d\n", val);
len -= off;
if(len <= off+count) *eof = 1;
*start = page + off;
#endif
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
- *pte = pte_mkexec(*pte);
- *pte = pte_wrprotect(*pte);
+ /* This is wrong for the code page, but it doesn't matter since the
+ * stub is mapped by hand with the correct permissions.
+ */
+ *pte = pte_mkwrite(*pte);
return(0);
out_pmd:
+++ /dev/null
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/config.h"
-#include "linux/kernel.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/string.h"
-#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/utsname.h"
-#include "linux/fs.h"
-#include "linux/utime.h"
-#include "linux/smp_lock.h"
-#include "linux/module.h"
-#include "linux/init.h"
-#include "linux/capability.h"
-#include "linux/vmalloc.h"
-#include "linux/spinlock.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/personality.h"
-#include "asm/unistd.h"
-#include "asm/mman.h"
-#include "asm/segment.h"
-#include "asm/stat.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "asm/user.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "signal_kern.h"
-#include "init.h"
-#include "irq_user.h"
-#include "mem_user.h"
-#include "tlb.h"
-#include "frame_kern.h"
-#include "sigcontext.h"
-#include "os.h"
-#include "mode.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
-
-/* This is a per-cpu array. A processor only modifies its entry and it only
- * cares about its entry, so it's OK if another processor is modifying its
- * entry.
- */
-struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-
-int external_pid(void *t)
-{
- struct task_struct *task = t ? t : current;
-
- return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
-}
-
-int pid_to_processor_id(int pid)
-{
- int i;
-
- for(i = 0; i < ncpus; i++){
- if(cpu_tasks[i].pid == pid) return(i);
- }
- return(-1);
-}
-
-void free_stack(unsigned long stack, int order)
-{
- free_pages(stack, order);
-}
-
-unsigned long alloc_stack(int order, int atomic)
-{
- unsigned long page;
- gfp_t flags = GFP_KERNEL;
-
- if (atomic)
- flags = GFP_ATOMIC;
- page = __get_free_pages(flags, order);
- if(page == 0)
- return(0);
- stack_protections(page);
- return(page);
-}
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
- int pid;
-
- current->thread.request.u.thread.proc = fn;
- current->thread.request.u.thread.arg = arg;
- pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
- ¤t->thread.regs, 0, NULL, NULL);
- if(pid < 0)
- panic("do_fork failed in kernel_thread, errno = %d", pid);
- return(pid);
-}
-
-void set_current(void *t)
-{
- struct task_struct *task = t;
-
- cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
- { external_pid(task), task });
-}
-
-void *_switch_to(void *prev, void *next, void *last)
-{
- struct task_struct *from = prev;
- struct task_struct *to= next;
-
- to->thread.prev_sched = from;
- set_current(to);
-
- do {
- current->thread.saved_task = NULL ;
- CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
- if(current->thread.saved_task)
- show_regs(&(current->thread.regs));
- next= current->thread.saved_task;
- prev= current;
- } while(current->thread.saved_task);
-
- return(current->thread.prev_sched);
-
-}
-
-void interrupt_end(void)
-{
- if(need_resched()) schedule();
- if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
-}
-
-void release_thread(struct task_struct *task)
-{
- CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-}
-
-void exit_thread(void)
-{
- unprotect_stack((unsigned long) current_thread);
-}
-
-void *get_current(void)
-{
- return(current);
-}
-
-int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
- struct pt_regs *regs)
-{
- int ret;
-
- p->thread = (struct thread_struct) INIT_THREAD;
- ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
- clone_flags, sp, stack_top, p, regs);
-
- if (ret || !current->thread.forking)
- goto out;
-
- clear_flushed_tls(p);
-
- /*
- * Set a new TLS for the child thread?
- */
- if (clone_flags & CLONE_SETTLS)
- ret = arch_copy_tls(p);
-
-out:
- return ret;
-}
-
-void initial_thread_cb(void (*proc)(void *), void *arg)
-{
- int save_kmalloc_ok = kmalloc_ok;
-
- kmalloc_ok = 0;
- CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
- arg);
- kmalloc_ok = save_kmalloc_ok;
-}
-
-unsigned long stack_sp(unsigned long page)
-{
- return(page + PAGE_SIZE - sizeof(void *));
-}
-
-int current_pid(void)
-{
- return(current->pid);
-}
-
-void default_idle(void)
-{
- CHOOSE_MODE(uml_idle_timer(), (void) 0);
-
- while(1){
- /* endless idle loop with no priority at all */
-
- /*
- * although we are an idle CPU, we do not want to
- * get into the scheduler unnecessarily.
- */
- if(need_resched())
- schedule();
-
- idle_sleep(10);
- }
-}
-
-void cpu_idle(void)
-{
- CHOOSE_MODE(init_idle_tt(), init_idle_skas());
-}
-
-int page_size(void)
-{
- return(PAGE_SIZE);
-}
-
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t ptent;
-
- if(task->mm == NULL)
- return(ERR_PTR(-EINVAL));
- pgd = pgd_offset(task->mm, addr);
- if(!pgd_present(*pgd))
- return(ERR_PTR(-EINVAL));
-
- pud = pud_offset(pgd, addr);
- if(!pud_present(*pud))
- return(ERR_PTR(-EINVAL));
-
- pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd))
- return(ERR_PTR(-EINVAL));
-
- pte = pte_offset_kernel(pmd, addr);
- ptent = *pte;
- if(!pte_present(ptent))
- return(ERR_PTR(-EINVAL));
-
- if(pte_out != NULL)
- *pte_out = ptent;
- return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
- return("(Unknown)");
-#else
- void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
- return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
-void force_sigbus(void)
-{
- printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
- current->pid);
- lock_kernel();
- sigaddset(¤t->pending.signal, SIGBUS);
- recalc_sigpending();
- current->flags |= PF_SIGNALED;
- do_exit(SIGBUS | 0x80);
-}
-
-void dump_thread(struct pt_regs *regs, struct user *u)
-{
-}
-
-void enable_hlt(void)
-{
- panic("enable_hlt");
-}
-
-EXPORT_SYMBOL(enable_hlt);
-
-void disable_hlt(void)
-{
- panic("disable_hlt");
-}
-
-EXPORT_SYMBOL(disable_hlt);
-
-void *um_kmalloc(int size)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-void *um_kmalloc_atomic(int size)
-{
- return kmalloc(size, GFP_ATOMIC);
-}
-
-void *um_vmalloc(int size)
-{
- return vmalloc(size);
-}
-
-void *um_vmalloc_atomic(int size)
-{
- return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
-}
-
-int __cant_sleep(void) {
- return in_atomic() || irqs_disabled() || in_interrupt();
- /* Is in_interrupt() really needed? */
-}
-
-unsigned long get_fault_addr(void)
-{
- return((unsigned long) current->thread.fault_addr);
-}
-
-EXPORT_SYMBOL(get_fault_addr);
-
-void not_implemented(void)
-{
- printk(KERN_DEBUG "Something isn't implemented in here\n");
-}
-
-EXPORT_SYMBOL(not_implemented);
-
-int user_context(unsigned long sp)
-{
- unsigned long stack;
-
- stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
- return(stack != (unsigned long) current_thread);
-}
-
-extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
-
-void do_uml_exitcalls(void)
-{
- exitcall_t *call;
-
- call = &__uml_exitcall_end;
- while (--call >= &__uml_exitcall_begin)
- (*call)();
-}
-
-char *uml_strdup(char *string)
-{
- return kstrdup(string, GFP_KERNEL);
-}
-
-int copy_to_user_proc(void __user *to, void *from, int size)
-{
- return(copy_to_user(to, from, size));
-}
-
-int copy_from_user_proc(void *to, void __user *from, int size)
-{
- return(copy_from_user(to, from, size));
-}
-
-int clear_user_proc(void __user *buf, int size)
-{
- return(clear_user(buf, size));
-}
-
-int strlen_user_proc(char __user *str)
-{
- return(strlen_user(str));
-}
-
-int smp_sigio_handler(void)
-{
-#ifdef CONFIG_SMP
- int cpu = current_thread->cpu;
- IPI_handler(cpu);
- if(cpu != 0)
- return(1);
-#endif
- return(0);
-}
-
-int cpu(void)
-{
- return(current_thread->cpu);
-}
-
-static atomic_t using_sysemu = ATOMIC_INIT(0);
-int sysemu_supported;
-
-void set_using_sysemu(int value)
-{
- if (value > sysemu_supported)
- return;
- atomic_set(&using_sysemu, value);
-}
-
-int get_using_sysemu(void)
-{
- return atomic_read(&using_sysemu);
-}
-
-static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
-{
- if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
- *eof = 1;
-
- return strlen(buf);
-}
-
-static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
-{
- char tmp[2];
-
- if (copy_from_user(tmp, buf, 1))
- return -EFAULT;
-
- if (tmp[0] >= '0' && tmp[0] <= '2')
- set_using_sysemu(tmp[0] - '0');
- return count; /*We use the first char, but pretend to write everything*/
-}
-
-int __init make_proc_sysemu(void)
-{
- struct proc_dir_entry *ent;
- if (!sysemu_supported)
- return 0;
-
- ent = create_proc_entry("sysemu", 0600, &proc_root);
-
- if (ent == NULL)
- {
- printk(KERN_WARNING "Failed to register /proc/sysemu\n");
- return(0);
- }
-
- ent->read_proc = proc_read_sysemu;
- ent->write_proc = proc_write_sysemu;
-
- return 0;
-}
-
-late_initcall(make_proc_sysemu);
-
-int singlestepping(void * t)
-{
- struct task_struct *task = t ? t : current;
-
- if ( ! (task->ptrace & PT_DTRACE) )
- return(0);
-
- if (task->thread.singlestep_syscall)
- return(1);
-
- return 2;
-}
-
-/*
- * Only x86 and x86_64 have an arch_align_stack().
- * All other arches have "#define arch_align_stack(x) (x)"
- * in their asm/system.h
- * As this is included in UML from asm-um/system-generic.h,
- * we can use it to behave as the subarch does.
- */
-#ifndef arch_align_stack
-unsigned long arch_align_stack(unsigned long sp)
-{
- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= get_random_int() % 8192;
- return sp & ~0xf;
-}
-#endif
write_seqlock_irqsave(&xtime_lock, flags);
- do_timer(regs);
+ do_timer(1);
nsecs = get_time();
xtime.tv_sec = nsecs / NSEC_PER_SEC;
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (current->pid == 1) {
+ if (is_init(current)) {
up_read(&mm->mmap_sem);
yield();
down_read(&mm->mmap_sem);
else if(found < 0)
printf("read returned errno %d\n", -found);
+out:
+ close(fd);
+
return;
found:
if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
printf("not tmpfs\n");
- return;
+ goto out;
}
printf("OK\n");
default_tmpdir = "/dev/shm";
+ goto out;
}
/*
if (mach_tick)
mach_tick ();
- do_timer (regs);
+ do_timer (1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
#include <linux/pci.h>
#include <linux/cache.h>
#include <linux/module.h>
-#include <asm/dma-mapping.h>
+#include <linux/dma-mapping.h>
+
#include <asm/proto.h>
#include <asm/swiotlb.h>
#include <asm/dma.h>
(((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
}
- if (lost > 0) {
+ if (lost > 0)
handle_lost_ticks(lost, regs);
- jiffies += lost;
- }
+ else
+ lost = 0;
/*
* Do the timer stuff.
*/
- do_timer(regs);
+ do_timer(lost + 1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
int unhandled_signal(struct task_struct *tsk, int sig)
{
- if (tsk->pid == 1)
+ if (is_init(tsk))
return 1;
if (tsk->ptrace & PT_PTRACED)
return 0;
case PF_PROT: /* read, present */
goto bad_area;
case 0: /* read, not present */
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
goto bad_area;
}
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
goto again;
}
last_ccount_stamp = next;
next += CCOUNT_PER_JIFFY;
- do_timer (regs); /* Linux handler in kernel/timer.c */
+ do_timer (1); /* Linux handler in kernel/timer.c */
if (ntp_synced() &&
xtime.tv_sec - last_rtc_update >= 659 &&
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (current->pid == 1) {
+ if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in;
- u32 addr;
+ __be32 addr;
if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
printk(KERN_WARNING "Device not assigned an IP address!\n");
**/
void blk_trace_shutdown(request_queue_t *q)
{
- blk_trace_startstop(q, 0);
- blk_trace_remove(q);
+ if (q->blk_trace) {
+ blk_trace_startstop(q, 0);
+ blk_trace_remove(q);
+ }
}
/*
static int __init genhd_device_init(void)
{
+ int err;
+
bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
blk_dev_init();
- subsystem_register(&block_subsys);
- return 0;
+ err = subsystem_register(&block_subsys);
+ if (err < 0)
+ printk(KERN_WARNING "%s: subsystem_register error: %d\n",
+ __FUNCTION__, err);
+ return err;
}
subsys_initcall(genhd_device_init);
if (q->queue_tags)
__blk_queue_free_tags(q);
- if (q->blk_trace)
- blk_trace_shutdown(q);
+ blk_trace_shutdown(q);
kmem_cache_free(requestq_cachep, q);
}
/**
* class_destroy - destroys a struct class structure
- * @cs: pointer to the struct class that is to be destroyed
+ * @cls: pointer to the struct class that is to be destroyed
*
* Note, the pointer to be destroyed must have been created with a call
* to class_create().
/**
* class_device_create - creates a class device and registers it with sysfs
- * @cs: pointer to the struct class that this device should be registered to.
+ * @cls: pointer to the struct class that this device should be registered to.
* @parent: pointer to the parent struct class_device of this new device, if any.
- * @dev: the dev_t for the char device to be added.
+ * @devt: the dev_t for the char device to be added.
* @device: a pointer to a struct device that is assiociated with this class device.
* @fmt: string for the class device's name
*
/**
* class_device_destroy - removes a class device that was created with class_device_create()
* @cls: the pointer to the struct class that this device was registered * with.
- * @dev: the dev_t of the device that was previously registered.
+ * @devt: the dev_t of the device that was previously registered.
*
* This call unregisters and cleans up a class device that was created with a
* call to class_device_create()
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/kthread.h>
#include <linux/firmware.h>
#include "base.h"
WARN_ON(1);
return 0;
}
- daemonize("%s/%s", "firmware", fw_work->name);
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
fw_work->uevent);
if (ret < 0)
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
+ struct task_struct *task;
struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
GFP_ATOMIC);
- int ret;
if (!fw_work)
return -ENOMEM;
.uevent = uevent,
};
- ret = kernel_thread(request_firmware_work_func, fw_work,
- CLONE_FS | CLONE_FILES);
+ task = kthread_run(request_firmware_work_func, fw_work,
+ "firmware/%s", name);
- if (ret < 0) {
+ if (IS_ERR(task)) {
fw_work->cont(NULL, fw_work->context);
module_put(fw_work->module);
kfree(fw_work);
- return ret;
+ return PTR_ERR(task);
}
return 0;
}
#include <linux/completion.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
goto out;
if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
goto out;
- lo->lo_pending++;
loop_add_bio(lo, old_bio);
+ wake_up(&lo->lo_event);
spin_unlock_irq(&lo->lo_lock);
- complete(&lo->lo_bh_done);
return 0;
out:
- if (lo->lo_pending == 0)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
* to avoid blocking in our make_request_fn. it also does loop decrypting
* on reads for block backed loop, as that is too heavy to do from
* b_end_io context where irqs may be disabled.
+ *
+ * Loop explanation: loop_clr_fd() sets lo_state to Lo_rundown before
+ * calling kthread_stop(). Therefore once kthread_should_stop() is
+ * true, make_request will not place any more requests. Therefore
+ * once kthread_should_stop() is true and lo_bio is NULL, we are
+ * done with the loop.
*/
static int loop_thread(void *data)
{
struct loop_device *lo = data;
struct bio *bio;
- daemonize("loop%d", lo->lo_number);
-
/*
* loop can be used in an encrypted device,
* hence, it mustn't be stopped at all
set_user_nice(current, -20);
- lo->lo_state = Lo_bound;
- lo->lo_pending = 1;
+ while (!kthread_should_stop() || lo->lo_bio) {
- /*
- * complete it, we are running
- */
- complete(&lo->lo_done);
-
- for (;;) {
- int pending;
+ wait_event_interruptible(lo->lo_event,
+ lo->lo_bio || kthread_should_stop());
- if (wait_for_completion_interruptible(&lo->lo_bh_done))
+ if (!lo->lo_bio)
continue;
-
spin_lock_irq(&lo->lo_lock);
-
- /*
- * could be completed because of tear-down, not pending work
- */
- if (unlikely(!lo->lo_pending)) {
- spin_unlock_irq(&lo->lo_lock);
- break;
- }
-
bio = loop_get_bio(lo);
- lo->lo_pending--;
- pending = lo->lo_pending;
spin_unlock_irq(&lo->lo_lock);
BUG_ON(!bio);
loop_handle_bio(lo, bio);
-
- /*
- * upped both for pending work and tear-down, lo_pending
- * will hit zero then
- */
- if (unlikely(!pending))
- break;
}
- complete(&lo->lo_done);
return 0;
}
set_blocksize(bdev, lo_blocksize);
- error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
- if (error < 0)
- goto out_putf;
- wait_for_completion(&lo->lo_done);
+ lo->lo_thread = kthread_create(loop_thread, lo, "loop%d",
+ lo->lo_number);
+ if (IS_ERR(lo->lo_thread)) {
+ error = PTR_ERR(lo->lo_thread);
+ goto out_clr;
+ }
+ lo->lo_state = Lo_bound;
+ wake_up_process(lo->lo_thread);
return 0;
+out_clr:
+ lo->lo_thread = NULL;
+ lo->lo_device = NULL;
+ lo->lo_backing_file = NULL;
+ lo->lo_flags = 0;
+ set_capacity(disks[lo->lo_number], 0);
+ invalidate_bdev(bdev, 0);
+ bd_set_size(bdev, 0);
+ mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
+ lo->lo_state = Lo_unbound;
out_putf:
fput(file);
out:
spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_rundown;
- lo->lo_pending--;
- if (!lo->lo_pending)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- wait_for_completion(&lo->lo_done);
+ kthread_stop(lo->lo_thread);
lo->lo_backing_file = NULL;
lo->lo_sizelimit = 0;
lo->lo_encrypt_key_size = 0;
lo->lo_flags = 0;
+ lo->lo_thread = NULL;
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
if (!lo->lo_queue)
goto out_mem4;
mutex_init(&lo->lo_ctl_mutex);
- init_completion(&lo->lo_done);
- init_completion(&lo->lo_bh_done);
lo->lo_number = i;
+ lo->lo_thread = NULL;
+ init_waitqueue_head(&lo->lo_event);
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
disk->first_minor = i;
*
* AVM BlueFRITZ! USB driver
*
- * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2003-2006 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
MODULE_DEVICE_TABLE(usb, bfusb_table);
-
#define BFUSB_MAX_BLOCK_SIZE 256
#define BFUSB_BLOCK_TIMEOUT 3000
#define BFUSB_MAX_BULK_TX 2
#define BFUSB_MAX_BULK_RX 2
-struct bfusb {
+struct bfusb_data {
struct hci_dev *hdev;
unsigned long state;
struct sk_buff_head completed_q;
};
-struct bfusb_scb {
+struct bfusb_data_scb {
struct urb *urb;
};
static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs);
static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs);
-static struct urb *bfusb_get_completed(struct bfusb *bfusb)
+static struct urb *bfusb_get_completed(struct bfusb_data *data)
{
struct sk_buff *skb;
struct urb *urb = NULL;
- BT_DBG("bfusb %p", bfusb);
+ BT_DBG("bfusb %p", data);
- skb = skb_dequeue(&bfusb->completed_q);
+ skb = skb_dequeue(&data->completed_q);
if (skb) {
- urb = ((struct bfusb_scb *) skb->cb)->urb;
+ urb = ((struct bfusb_data_scb *) skb->cb)->urb;
kfree_skb(skb);
}
return urb;
}
-static void bfusb_unlink_urbs(struct bfusb *bfusb)
+static void bfusb_unlink_urbs(struct bfusb_data *data)
{
struct sk_buff *skb;
struct urb *urb;
- BT_DBG("bfusb %p", bfusb);
+ BT_DBG("bfusb %p", data);
- while ((skb = skb_dequeue(&bfusb->pending_q))) {
- urb = ((struct bfusb_scb *) skb->cb)->urb;
+ while ((skb = skb_dequeue(&data->pending_q))) {
+ urb = ((struct bfusb_data_scb *) skb->cb)->urb;
usb_kill_urb(urb);
- skb_queue_tail(&bfusb->completed_q, skb);
+ skb_queue_tail(&data->completed_q, skb);
}
- while ((urb = bfusb_get_completed(bfusb)))
+ while ((urb = bfusb_get_completed(data)))
usb_free_urb(urb);
}
-
-static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
+static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
{
- struct bfusb_scb *scb = (void *) skb->cb;
- struct urb *urb = bfusb_get_completed(bfusb);
+ struct bfusb_data_scb *scb = (void *) skb->cb;
+ struct urb *urb = bfusb_get_completed(data);
int err, pipe;
- BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len);
+ BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
return -ENOMEM;
- pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+ pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
- usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, skb->len,
+ usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
bfusb_tx_complete, skb);
scb->urb = urb;
- skb_queue_tail(&bfusb->pending_q, skb);
+ skb_queue_tail(&data->pending_q, skb);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
BT_ERR("%s bulk tx submit failed urb %p err %d",
- bfusb->hdev->name, urb, err);
- skb_unlink(skb, &bfusb->pending_q);
+ data->hdev->name, urb, err);
+ skb_unlink(skb, &data->pending_q);
usb_free_urb(urb);
} else
- atomic_inc(&bfusb->pending_tx);
+ atomic_inc(&data->pending_tx);
return err;
}
-static void bfusb_tx_wakeup(struct bfusb *bfusb)
+static void bfusb_tx_wakeup(struct bfusb_data *data)
{
struct sk_buff *skb;
- BT_DBG("bfusb %p", bfusb);
+ BT_DBG("bfusb %p", data);
- if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) {
- set_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+ if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
+ set_bit(BFUSB_TX_WAKEUP, &data->state);
return;
}
do {
- clear_bit(BFUSB_TX_WAKEUP, &bfusb->state);
+ clear_bit(BFUSB_TX_WAKEUP, &data->state);
- while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) &&
- (skb = skb_dequeue(&bfusb->transmit_q))) {
- if (bfusb_send_bulk(bfusb, skb) < 0) {
- skb_queue_head(&bfusb->transmit_q, skb);
+ while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) &&
+ (skb = skb_dequeue(&data->transmit_q))) {
+ if (bfusb_send_bulk(data, skb) < 0) {
+ skb_queue_head(&data->transmit_q, skb);
break;
}
}
- } while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state));
+ } while (test_bit(BFUSB_TX_WAKEUP, &data->state));
- clear_bit(BFUSB_TX_PROCESS, &bfusb->state);
+ clear_bit(BFUSB_TX_PROCESS, &data->state);
}
static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
- struct bfusb *bfusb = (struct bfusb *) skb->dev;
+ struct bfusb_data *data = (struct bfusb_data *) skb->dev;
- BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
+ BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
- atomic_dec(&bfusb->pending_tx);
+ atomic_dec(&data->pending_tx);
- if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+ if (!test_bit(HCI_RUNNING, &data->hdev->flags))
return;
if (!urb->status)
- bfusb->hdev->stat.byte_tx += skb->len;
+ data->hdev->stat.byte_tx += skb->len;
else
- bfusb->hdev->stat.err_tx++;
+ data->hdev->stat.err_tx++;
- read_lock(&bfusb->lock);
+ read_lock(&data->lock);
- skb_unlink(skb, &bfusb->pending_q);
- skb_queue_tail(&bfusb->completed_q, skb);
+ skb_unlink(skb, &data->pending_q);
+ skb_queue_tail(&data->completed_q, skb);
- bfusb_tx_wakeup(bfusb);
+ bfusb_tx_wakeup(data);
- read_unlock(&bfusb->lock);
+ read_unlock(&data->lock);
}
-static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
+static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
{
- struct bfusb_scb *scb;
+ struct bfusb_data_scb *scb;
struct sk_buff *skb;
int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
return -ENOMEM;
- if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) {
+ skb = bt_skb_alloc(size, GFP_ATOMIC);
+ if (!skb) {
usb_free_urb(urb);
return -ENOMEM;
}
- skb->dev = (void *) bfusb;
+ skb->dev = (void *) data;
- scb = (struct bfusb_scb *) skb->cb;
+ scb = (struct bfusb_data_scb *) skb->cb;
scb->urb = urb;
- pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep);
+ pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
- usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, size,
+ usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
bfusb_rx_complete, skb);
- skb_queue_tail(&bfusb->pending_q, skb);
+ skb_queue_tail(&data->pending_q, skb);
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
BT_ERR("%s bulk rx submit failed urb %p err %d",
- bfusb->hdev->name, urb, err);
- skb_unlink(skb, &bfusb->pending_q);
+ data->hdev->name, urb, err);
+ skb_unlink(skb, &data->pending_q);
kfree_skb(skb);
usb_free_urb(urb);
}
return err;
}
-static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len)
+static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
{
- BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len);
+ BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
if (hdr & 0x10) {
- BT_ERR("%s error in block", bfusb->hdev->name);
- if (bfusb->reassembly)
- kfree_skb(bfusb->reassembly);
- bfusb->reassembly = NULL;
+ BT_ERR("%s error in block", data->hdev->name);
+ if (data->reassembly)
+ kfree_skb(data->reassembly);
+ data->reassembly = NULL;
return -EIO;
}
unsigned char pkt_type;
int pkt_len = 0;
- if (bfusb->reassembly) {
- BT_ERR("%s unexpected start block", bfusb->hdev->name);
- kfree_skb(bfusb->reassembly);
- bfusb->reassembly = NULL;
+ if (data->reassembly) {
+ BT_ERR("%s unexpected start block", data->hdev->name);
+ kfree_skb(data->reassembly);
+ data->reassembly = NULL;
}
if (len < 1) {
- BT_ERR("%s no packet type found", bfusb->hdev->name);
+ BT_ERR("%s no packet type found", data->hdev->name);
return -EPROTO;
}
- pkt_type = *data++; len--;
+ pkt_type = *buf++; len--;
switch (pkt_type) {
case HCI_EVENT_PKT:
if (len >= HCI_EVENT_HDR_SIZE) {
- struct hci_event_hdr *hdr = (struct hci_event_hdr *) data;
+ struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
} else {
- BT_ERR("%s event block is too short", bfusb->hdev->name);
+ BT_ERR("%s event block is too short", data->hdev->name);
return -EILSEQ;
}
break;
case HCI_ACLDATA_PKT:
if (len >= HCI_ACL_HDR_SIZE) {
- struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data;
+ struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
} else {
- BT_ERR("%s data block is too short", bfusb->hdev->name);
+ BT_ERR("%s data block is too short", data->hdev->name);
return -EILSEQ;
}
break;
case HCI_SCODATA_PKT:
if (len >= HCI_SCO_HDR_SIZE) {
- struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data;
+ struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
} else {
- BT_ERR("%s audio block is too short", bfusb->hdev->name);
+ BT_ERR("%s audio block is too short", data->hdev->name);
return -EILSEQ;
}
break;
skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
if (!skb) {
- BT_ERR("%s no memory for the packet", bfusb->hdev->name);
+ BT_ERR("%s no memory for the packet", data->hdev->name);
return -ENOMEM;
}
- skb->dev = (void *) bfusb->hdev;
+ skb->dev = (void *) data->hdev;
bt_cb(skb)->pkt_type = pkt_type;
- bfusb->reassembly = skb;
+ data->reassembly = skb;
} else {
- if (!bfusb->reassembly) {
- BT_ERR("%s unexpected continuation block", bfusb->hdev->name);
+ if (!data->reassembly) {
+ BT_ERR("%s unexpected continuation block", data->hdev->name);
return -EIO;
}
}
if (len > 0)
- memcpy(skb_put(bfusb->reassembly, len), data, len);
+ memcpy(skb_put(data->reassembly, len), buf, len);
if (hdr & 0x08) {
- hci_recv_frame(bfusb->reassembly);
- bfusb->reassembly = NULL;
+ hci_recv_frame(data->reassembly);
+ data->reassembly = NULL;
}
return 0;
static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
- struct bfusb *bfusb = (struct bfusb *) skb->dev;
+ struct bfusb_data *data = (struct bfusb_data *) skb->dev;
unsigned char *buf = urb->transfer_buffer;
int count = urb->actual_length;
int err, hdr, len;
BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
- read_lock(&bfusb->lock);
+ read_lock(&data->lock);
- if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
+ if (!test_bit(HCI_RUNNING, &data->hdev->flags))
goto unlock;
if (urb->status || !count)
goto resubmit;
- bfusb->hdev->stat.byte_rx += count;
+ data->hdev->stat.byte_rx += count;
skb_put(skb, count);
if (count < len) {
BT_ERR("%s block extends over URB buffer ranges",
- bfusb->hdev->name);
+ data->hdev->name);
}
if ((hdr & 0xe1) == 0xc1)
- bfusb_recv_block(bfusb, hdr, buf, len);
+ bfusb_recv_block(data, hdr, buf, len);
count -= len;
buf += len;
}
- skb_unlink(skb, &bfusb->pending_q);
+ skb_unlink(skb, &data->pending_q);
kfree_skb(skb);
- bfusb_rx_submit(bfusb, urb);
+ bfusb_rx_submit(data, urb);
- read_unlock(&bfusb->lock);
+ read_unlock(&data->lock);
return;
resubmit:
- urb->dev = bfusb->udev;
+ urb->dev = data->udev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
BT_ERR("%s bulk resubmit failed urb %p err %d",
- bfusb->hdev->name, urb, err);
+ data->hdev->name, urb, err);
}
unlock:
- read_unlock(&bfusb->lock);
+ read_unlock(&data->lock);
}
-
static int bfusb_open(struct hci_dev *hdev)
{
- struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+ struct bfusb_data *data = hdev->driver_data;
unsigned long flags;
int i, err;
- BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+ BT_DBG("hdev %p bfusb %p", hdev, data);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
- write_lock_irqsave(&bfusb->lock, flags);
+ write_lock_irqsave(&data->lock, flags);
- err = bfusb_rx_submit(bfusb, NULL);
+ err = bfusb_rx_submit(data, NULL);
if (!err) {
for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
- bfusb_rx_submit(bfusb, NULL);
+ bfusb_rx_submit(data, NULL);
} else {
clear_bit(HCI_RUNNING, &hdev->flags);
}
- write_unlock_irqrestore(&bfusb->lock, flags);
+ write_unlock_irqrestore(&data->lock, flags);
return err;
}
static int bfusb_flush(struct hci_dev *hdev)
{
- struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+ struct bfusb_data *data = hdev->driver_data;
- BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+ BT_DBG("hdev %p bfusb %p", hdev, data);
- skb_queue_purge(&bfusb->transmit_q);
+ skb_queue_purge(&data->transmit_q);
return 0;
}
static int bfusb_close(struct hci_dev *hdev)
{
- struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+ struct bfusb_data *data = hdev->driver_data;
unsigned long flags;
- BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+ BT_DBG("hdev %p bfusb %p", hdev, data);
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
- write_lock_irqsave(&bfusb->lock, flags);
- write_unlock_irqrestore(&bfusb->lock, flags);
+ write_lock_irqsave(&data->lock, flags);
+ write_unlock_irqrestore(&data->lock, flags);
- bfusb_unlink_urbs(bfusb);
+ bfusb_unlink_urbs(data);
bfusb_flush(hdev);
return 0;
static int bfusb_send_frame(struct sk_buff *skb)
{
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
- struct bfusb *bfusb;
+ struct bfusb_data *data;
struct sk_buff *nskb;
unsigned char buf[3];
int sent = 0, size, count;
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- bfusb = (struct bfusb *) hdev->driver_data;
+ data = hdev->driver_data;
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
count = skb->len;
/* Max HCI frame size seems to be 1511 + 1 */
- if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) {
+ nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
+ if (!nskb) {
BT_ERR("Can't allocate memory for new packet");
return -ENOMEM;
}
- nskb->dev = (void *) bfusb;
+ nskb->dev = (void *) data;
while (count) {
size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE);
}
/* Don't send frame with multiple size of bulk max packet */
- if ((nskb->len % bfusb->bulk_pkt_size) == 0) {
+ if ((nskb->len % data->bulk_pkt_size) == 0) {
buf[0] = 0xdd;
buf[1] = 0x00;
memcpy(skb_put(nskb, 2), buf, 2);
}
- read_lock(&bfusb->lock);
+ read_lock(&data->lock);
- skb_queue_tail(&bfusb->transmit_q, nskb);
- bfusb_tx_wakeup(bfusb);
+ skb_queue_tail(&data->transmit_q, nskb);
+ bfusb_tx_wakeup(data);
- read_unlock(&bfusb->lock);
+ read_unlock(&data->lock);
kfree_skb(skb);
static void bfusb_destruct(struct hci_dev *hdev)
{
- struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
+ struct bfusb_data *data = hdev->driver_data;
- BT_DBG("hdev %p bfusb %p", hdev, bfusb);
+ BT_DBG("hdev %p bfusb %p", hdev, data);
- kfree(bfusb);
+ kfree(data);
}
static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
return -ENOIOCTLCMD;
}
-
-static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count)
+static int bfusb_load_firmware(struct bfusb_data *data, unsigned char *firmware, int count)
{
unsigned char *buf;
int err, pipe, len, size, sent = 0;
- BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev);
+ BT_DBG("bfusb %p udev %p", data, data->udev);
BT_INFO("BlueFRITZ! USB loading firmware");
- pipe = usb_sndctrlpipe(bfusb->udev, 0);
+ pipe = usb_sndctrlpipe(data->udev, 0);
- if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+ if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
BT_ERR("Can't change to loading configuration");
return -EBUSY;
}
- bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+ data->udev->toggle[0] = data->udev->toggle[1] = 0;
buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
if (!buf) {
return -ENOMEM;
}
- pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
+ pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
while (count) {
size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);
memcpy(buf, firmware + sent, size);
- err = usb_bulk_msg(bfusb->udev, pipe, buf, size,
+ err = usb_bulk_msg(data->udev, pipe, buf, size,
&len, BFUSB_BLOCK_TIMEOUT);
if (err || (len != size)) {
count -= size;
}
- if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0,
- &len, BFUSB_BLOCK_TIMEOUT)) < 0) {
+ err = usb_bulk_msg(data->udev, pipe, NULL, 0,
+ &len, BFUSB_BLOCK_TIMEOUT);
+ if (err < 0) {
BT_ERR("Error in null packet request");
goto error;
}
- pipe = usb_sndctrlpipe(bfusb->udev, 0);
+ pipe = usb_sndctrlpipe(data->udev, 0);
- if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
- 0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+ err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
+ 0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (err < 0) {
BT_ERR("Can't change to running configuration");
goto error;
}
- bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
+ data->udev->toggle[0] = data->udev->toggle[1] = 0;
BT_INFO("BlueFRITZ! USB device ready");
error:
kfree(buf);
- pipe = usb_sndctrlpipe(bfusb->udev, 0);
+ pipe = usb_sndctrlpipe(data->udev, 0);
- usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+ usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
return err;
struct usb_host_endpoint *bulk_out_ep;
struct usb_host_endpoint *bulk_in_ep;
struct hci_dev *hdev;
- struct bfusb *bfusb;
+ struct bfusb_data *data;
BT_DBG("intf %p id %p", intf, id);
}
/* Initialize control structure and load firmware */
- if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) {
+ data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
+ if (!data) {
BT_ERR("Can't allocate memory for control structure");
goto done;
}
- bfusb->udev = udev;
- bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress;
- bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress;
- bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
+ data->udev = udev;
+ data->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress;
+ data->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress;
+ data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
- rwlock_init(&bfusb->lock);
+ rwlock_init(&data->lock);
- bfusb->reassembly = NULL;
+ data->reassembly = NULL;
- skb_queue_head_init(&bfusb->transmit_q);
- skb_queue_head_init(&bfusb->pending_q);
- skb_queue_head_init(&bfusb->completed_q);
+ skb_queue_head_init(&data->transmit_q);
+ skb_queue_head_init(&data->pending_q);
+ skb_queue_head_init(&data->completed_q);
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
BT_ERR("Firmware request failed");
BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
- if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) {
+ if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
BT_ERR("Firmware loading failed");
goto release;
}
goto error;
}
- bfusb->hdev = hdev;
+ data->hdev = hdev;
hdev->type = HCI_USB;
- hdev->driver_data = bfusb;
+ hdev->driver_data = data;
SET_HCIDEV_DEV(hdev, &intf->dev);
hdev->open = bfusb_open;
goto error;
}
- usb_set_intfdata(intf, bfusb);
+ usb_set_intfdata(intf, data);
return 0;
release_firmware(firmware);
error:
- kfree(bfusb);
+ kfree(data);
done:
return -EIO;
static void bfusb_disconnect(struct usb_interface *intf)
{
- struct bfusb *bfusb = usb_get_intfdata(intf);
- struct hci_dev *hdev = bfusb->hdev;
+ struct bfusb_data *data = usb_get_intfdata(intf);
+ struct hci_dev *hdev = data->hdev;
BT_DBG("intf %p", intf);
BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
- if ((err = usb_register(&bfusb_driver)) < 0)
+ err = usb_register(&bfusb_driver);
+ if (err < 0)
BT_ERR("Failed to register BlueFRITZ! USB driver");
return err;
static void hci_uart_destruct(struct hci_dev *hdev)
{
- struct hci_uart *hu;
-
if (!hdev)
return;
BT_DBG("%s", hdev->name);
-
- hu = (struct hci_uart *) hdev->driver_data;
- kfree(hu);
+ kfree(hdev->driver_data);
}
/* ------ LDISC part ------ */
return -EEXIST;
if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
- BT_ERR("Can't allocate controll structure");
+ BT_ERR("Can't allocate control structure");
return -ENFILE;
}
*
* Return Value: None
*/
-static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
+static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
{
struct hci_uart *hu = (void *)tty->disc_data;
hu->hdev->stat.byte_rx += count;
spin_unlock(&hu->rx_lock);
- if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle)
+ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+ tty->driver->unthrottle)
tty->driver->unthrottle(tty);
}
/* Ericsson with non-standard id */
{ USB_DEVICE(0x0bdb, 0x1002) },
+ /* Canyon CN-BTU1 with HID interfaces */
+ { USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
+
{ } /* Terminating entry */
};
*
* Bluetooth virtual HCI driver
*
- * Copyright (C) 2000-2001 Qualcomm Incorporated
- * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
- * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
static int vhci_close_dev(struct hci_dev *hdev)
{
- struct vhci_data *vhci = hdev->driver_data;
+ struct vhci_data *data = hdev->driver_data;
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
- skb_queue_purge(&vhci->readq);
+ skb_queue_purge(&data->readq);
return 0;
}
static int vhci_flush(struct hci_dev *hdev)
{
- struct vhci_data *vhci = hdev->driver_data;
+ struct vhci_data *data = hdev->driver_data;
- skb_queue_purge(&vhci->readq);
+ skb_queue_purge(&data->readq);
return 0;
}
static int vhci_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
- struct vhci_data *vhci;
+ struct vhci_data *data;
if (!hdev) {
BT_ERR("Frame for unknown HCI device (hdev=NULL)");
if (!test_bit(HCI_RUNNING, &hdev->flags))
return -EBUSY;
- vhci = hdev->driver_data;
+ data = hdev->driver_data;
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
- skb_queue_tail(&vhci->readq, skb);
+ skb_queue_tail(&data->readq, skb);
- if (vhci->flags & VHCI_FASYNC)
- kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
+ if (data->flags & VHCI_FASYNC)
+ kill_fasync(&data->fasync, SIGIO, POLL_IN);
- wake_up_interruptible(&vhci->read_wait);
+ wake_up_interruptible(&data->read_wait);
return 0;
}
kfree(hdev->driver_data);
}
-static inline ssize_t vhci_get_user(struct vhci_data *vhci,
+static inline ssize_t vhci_get_user(struct vhci_data *data,
const char __user *buf, size_t count)
{
struct sk_buff *skb;
return -EFAULT;
}
- skb->dev = (void *) vhci->hdev;
+ skb->dev = (void *) data->hdev;
bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
return count;
}
-static inline ssize_t vhci_put_user(struct vhci_data *vhci,
+static inline ssize_t vhci_put_user(struct vhci_data *data,
struct sk_buff *skb, char __user *buf, int count)
{
char __user *ptr = buf;
total += len;
- vhci->hdev->stat.byte_tx += len;
+ data->hdev->stat.byte_tx += len;
switch (bt_cb(skb)->pkt_type) {
case HCI_COMMAND_PKT:
- vhci->hdev->stat.cmd_tx++;
+ data->hdev->stat.cmd_tx++;
break;
case HCI_ACLDATA_PKT:
- vhci->hdev->stat.acl_tx++;
+ &nbs