diff options
263 files changed, 8223 insertions, 7539 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc index a0d18dbeb7a9..6a5fd072849d 100644 --- a/Documentation/ABI/testing/sysfs-class-uwb_rc +++ b/Documentation/ABI/testing/sysfs-class-uwb_rc | |||
@@ -32,14 +32,16 @@ Contact: linux-usb@vger.kernel.org | |||
32 | Description: | 32 | Description: |
33 | Write: | 33 | Write: |
34 | 34 | ||
35 | <channel> [<bpst offset>] | 35 | <channel> |
36 | 36 | ||
37 | to start beaconing on a specific channel, or stop | 37 | to force a specific channel to be used when beaconing, |
38 | beaconing if <channel> is -1. Valid channels depends | 38 | or, if <channel> is -1, to prohibit beaconing. If |
39 | on the radio controller's supported band groups. | 39 | <channel> is 0, then the default channel selection |
40 | algorithm will be used. Valid channels depends on the | ||
41 | radio controller's supported band groups. | ||
40 | 42 | ||
41 | <bpst offset> may be used to try and join a specific | 43 | Reading returns the currently active channel, or -1 if |
42 | beacon group if more than one was found during a scan. | 44 | the radio controller is not beaconing. |
43 | 45 | ||
44 | What: /sys/class/uwb_rc/uwbN/scan | 46 | What: /sys/class/uwb_rc/uwbN/scan |
45 | Date: July 2008 | 47 | Date: July 2008 |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index dc7c681e532c..df18d87c4837 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -310,15 +310,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl> | |||
310 | 310 | ||
311 | --------------------------- | 311 | --------------------------- |
312 | 312 | ||
313 | What: ide-scsi (BLK_DEV_IDESCSI) | ||
314 | When: 2.6.29 | ||
315 | Why: The 2.6 kernel supports direct writing to ide CD drives, which | ||
316 | eliminates the need for ide-scsi. The new method is more | ||
317 | efficient in every way. | ||
318 | Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | ||
319 | |||
320 | --------------------------- | ||
321 | |||
322 | What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client() | 313 | What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client() |
323 | When: 2.6.29 (ideally) or 2.6.30 (more likely) | 314 | When: 2.6.29 (ideally) or 2.6.30 (more likely) |
324 | Why: Deprecated by the new (standard) device driver binding model. Use | 315 | Why: Deprecated by the new (standard) device driver binding model. Use |
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 23d2f4460deb..ccec55394380 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -394,7 +394,6 @@ prototypes: | |||
394 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, | 394 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, |
395 | unsigned long, unsigned long, unsigned long); | 395 | unsigned long, unsigned long, unsigned long); |
396 | int (*check_flags)(int); | 396 | int (*check_flags)(int); |
397 | int (*dir_notify)(struct file *, unsigned long); | ||
398 | }; | 397 | }; |
399 | 398 | ||
400 | locking rules: | 399 | locking rules: |
@@ -424,7 +423,6 @@ sendfile: no | |||
424 | sendpage: no | 423 | sendpage: no |
425 | get_unmapped_area: no | 424 | get_unmapped_area: no |
426 | check_flags: no | 425 | check_flags: no |
427 | dir_notify: no | ||
428 | 426 | ||
429 | ->llseek() locking has moved from llseek to the individual llseek | 427 | ->llseek() locking has moved from llseek to the individual llseek |
430 | implementations. If your fs is not using generic_file_llseek, you | 428 | implementations. If your fs is not using generic_file_llseek, you |
diff --git a/Documentation/filesystems/devpts.txt b/Documentation/filesystems/devpts.txt new file mode 100644 index 000000000000..68dffd87f9b7 --- /dev/null +++ b/Documentation/filesystems/devpts.txt | |||
@@ -0,0 +1,132 @@ | |||
1 | |||
2 | To support containers, we now allow multiple instances of devpts filesystem, | ||
3 | such that indices of ptys allocated in one instance are independent of indices | ||
4 | allocated in other instances of devpts. | ||
5 | |||
6 | To preserve backward compatibility, this support for multiple instances is | ||
7 | enabled only if: | ||
8 | |||
9 | - CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and | ||
10 | - '-o newinstance' mount option is specified while mounting devpts | ||
11 | |||
12 | IOW, devpts now supports both single-instance and multi-instance semantics. | ||
13 | |||
14 | If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and | ||
15 | this referred to as the "legacy" mode. In this mode, the new mount options | ||
16 | (-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message | ||
17 | on console. | ||
18 | |||
19 | If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the | ||
20 | 'newinstance' option (as in current start-up scripts) the new mount binds | ||
21 | to the initial kernel mount of devpts. This mode is referred to as the | ||
22 | 'single-instance' mode and the current, single-instance semantics are | ||
23 | preserved, i.e PTYs are common across the system. | ||
24 | |||
25 | The only difference between this single-instance mode and the legacy mode | ||
26 | is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which | ||
27 | can safely be ignored. | ||
28 | |||
29 | If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified, | ||
30 | the mount is considered to be in the multi-instance mode and a new instance | ||
31 | of the devpts fs is created. Any ptys created in this instance are independent | ||
32 | of ptys in other instances of devpts. Like in the single-instance mode, the | ||
33 | /dev/pts/ptmx node is present. To effectively use the multi-instance mode, | ||
34 | open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or | ||
35 | bind-mount. | ||
36 | |||
37 | Eg: A container startup script could do the following: | ||
38 | |||
39 | $ chmod 0666 /dev/pts/ptmx | ||
40 | $ rm /dev/ptmx | ||
41 | $ ln -s pts/ptmx /dev/ptmx | ||
42 | $ ns_exec -cm /bin/bash | ||
43 | |||
44 | # We are now in new container | ||
45 | |||
46 | $ umount /dev/pts | ||
47 | $ mount -t devpts -o newinstance lxcpts /dev/pts | ||
48 | $ sshd -p 1234 | ||
49 | |||
50 | where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs | ||
51 | /bin/bash in the child process. A pty created by the sshd is not visible in | ||
52 | the original mount of /dev/pts. | ||
53 | |||
54 | User-space changes | ||
55 | ------------------ | ||
56 | |||
57 | In multi-instance mode (i.e '-o newinstance' mount option is specified at least | ||
58 | once), following user-space issues should be noted. | ||
59 | |||
60 | 1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored | ||
61 | and no change is needed to system-startup scripts. | ||
62 | |||
63 | 2. To effectively use multi-instance mode (i.e -o newinstance is specified) | ||
64 | administrators or startup scripts should "redirect" open of /dev/ptmx to | ||
65 | /dev/pts/ptmx using either a bind mount or symlink. | ||
66 | |||
67 | $ mount -t devpts -o newinstance devpts /dev/pts | ||
68 | |||
69 | followed by either | ||
70 | |||
71 | $ rm /dev/ptmx | ||
72 | $ ln -s pts/ptmx /dev/ptmx | ||
73 | $ chmod 666 /dev/pts/ptmx | ||
74 | or | ||
75 | $ mount -o bind /dev/pts/ptmx /dev/ptmx | ||
76 | |||
77 | 3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it | ||
78 | enables better error-reporting and treats both single-instance and | ||
79 | multi-instance mounts similarly. | ||
80 | |||
81 | But this method requires that system-startup scripts set the mode of | ||
82 | /dev/pts/ptmx correctly (default mode is 0000). The scripts can set the | ||
83 | mode by, either | ||
84 | |||
85 | - adding ptmxmode mount option to devpts entry in /etc/fstab, or | ||
86 | - using 'chmod 0666 /dev/pts/ptmx' | ||
87 | |||
88 | 4. If multi-instance mode mount is needed for containers, but the system | ||
89 | startup scripts have not yet been updated, container-startup scripts | ||
90 | should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single- | ||
91 | instance mounts. | ||
92 | |||
93 | Or, in general, container-startup scripts should use: | ||
94 | |||
95 | mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts | ||
96 | if [ ! -L /dev/ptmx ]; then | ||
97 | mount -o bind /dev/pts/ptmx /dev/ptmx | ||
98 | fi | ||
99 | |||
100 | When all devpts mounts are multi-instance, /dev/ptmx can permanently be | ||
101 | a symlink to pts/ptmx and the bind mount can be ignored. | ||
102 | |||
103 | 5. A multi-instance mount that is not accompanied by the /dev/ptmx to | ||
104 | /dev/pts/ptmx redirection would result in an unusable/unreachable pty. | ||
105 | |||
106 | mount -t devpts -o newinstance lxcpts /dev/pts | ||
107 | |||
108 | immediately followed by: | ||
109 | |||
110 | open("/dev/ptmx") | ||
111 | |||
112 | would create a pty, say /dev/pts/7, in the initial kernel mount. | ||
113 | But /dev/pts/7 would be invisible in the new mount. | ||
114 | |||
115 | 6. The permissions for /dev/pts/ptmx node should be specified when mounting | ||
116 | /dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000). | ||
117 | |||
118 | mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts | ||
119 | |||
120 | The permissions can be later be changed as usual with 'chmod'. | ||
121 | |||
122 | chmod 666 /dev/pts/ptmx | ||
123 | |||
124 | 7. A mount of devpts without the 'newinstance' option results in binding to | ||
125 | initial kernel mount. This behavior while preserving legacy semantics, | ||
126 | does not provide strict isolation in a container environment. i.e by | ||
127 | mounting devpts without the 'newinstance' option, a container could | ||
128 | get visibility into the 'host' or root container's devpts. | ||
129 | |||
130 | To workaround this and have strict isolation, all mounts of devpts, | ||
131 | including the mount in the root container, should use the newinstance | ||
132 | option. | ||
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt index bb0142f61084..ac2facc50d2a 100644 --- a/Documentation/filesystems/files.txt +++ b/Documentation/filesystems/files.txt | |||
@@ -76,13 +76,13 @@ the fdtable structure - | |||
76 | 5. Handling of the file structures is special. Since the look-up | 76 | 5. Handling of the file structures is special. Since the look-up |
77 | of the fd (fget()/fget_light()) are lock-free, it is possible | 77 | of the fd (fget()/fget_light()) are lock-free, it is possible |
78 | that look-up may race with the last put() operation on the | 78 | that look-up may race with the last put() operation on the |
79 | file structure. This is avoided using atomic_inc_not_zero() | 79 | file structure. This is avoided using atomic_long_inc_not_zero() |
80 | on ->f_count : | 80 | on ->f_count : |
81 | 81 | ||
82 | rcu_read_lock(); | 82 | rcu_read_lock(); |
83 | file = fcheck_files(files, fd); | 83 | file = fcheck_files(files, fd); |
84 | if (file) { | 84 | if (file) { |
85 | if (atomic_inc_not_zero(&file->f_count)) | 85 | if (atomic_long_inc_not_zero(&file->f_count)) |
86 | *fput_needed = 1; | 86 | *fput_needed = 1; |
87 | else | 87 | else |
88 | /* Didn't get the reference, someone's freed */ | 88 | /* Didn't get the reference, someone's freed */ |
@@ -92,7 +92,7 @@ the fdtable structure - | |||
92 | .... | 92 | .... |
93 | return file; | 93 | return file; |
94 | 94 | ||
95 | atomic_inc_not_zero() detects if refcounts is already zero or | 95 | atomic_long_inc_not_zero() detects if refcounts is already zero or |
96 | goes to zero during increment. If it does, we fail | 96 | goes to zero during increment. If it does, we fail |
97 | fget()/fget_light(). | 97 | fget()/fget_light(). |
98 | 98 | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 5579bda58a6d..ef19afa186a9 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -733,7 +733,6 @@ struct file_operations { | |||
733 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 733 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
734 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 734 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
735 | int (*check_flags)(int); | 735 | int (*check_flags)(int); |
736 | int (*dir_notify)(struct file *filp, unsigned long arg); | ||
737 | int (*flock) (struct file *, int, struct file_lock *); | 736 | int (*flock) (struct file *, int, struct file_lock *); |
738 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); | 737 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); |
739 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); | 738 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); |
@@ -800,8 +799,6 @@ otherwise noted. | |||
800 | 799 | ||
801 | check_flags: called by the fcntl(2) system call for F_SETFL command | 800 | check_flags: called by the fcntl(2) system call for F_SETFL command |
802 | 801 | ||
803 | dir_notify: called by the fcntl(2) system call for F_NOTIFY command | ||
804 | |||
805 | flock: called by the flock(2) system call | 802 | flock: called by the flock(2) system call |
806 | 803 | ||
807 | splice_write: called by the VFS to splice data from a pipe to a file. This | 804 | splice_write: called by the VFS to splice data from a pipe to a file. This |
@@ -931,7 +928,7 @@ manipulate dentries: | |||
931 | d_lookup: look up a dentry given its parent and path name component | 928 | d_lookup: look up a dentry given its parent and path name component |
932 | It looks up the child of that given name from the dcache | 929 | It looks up the child of that given name from the dcache |
933 | hash table. If it is found, the reference count is incremented | 930 | hash table. If it is found, the reference count is incremented |
934 | and the dentry is returned. The caller must use d_put() | 931 | and the dentry is returned. The caller must use dput() |
935 | to free the dentry when it finishes using it. | 932 | to free the dentry when it finishes using it. |
936 | 933 | ||
937 | For further information on dentry locking, please refer to the document | 934 | For further information on dentry locking, please refer to the document |
diff --git a/Documentation/usb/wusb-cbaf b/Documentation/usb/wusb-cbaf index 2e78b70f3adc..426ddaaef96f 100644 --- a/Documentation/usb/wusb-cbaf +++ b/Documentation/usb/wusb-cbaf | |||
@@ -80,12 +80,6 @@ case $1 in | |||
80 | start) | 80 | start) |
81 | for dev in ${2:-$hdevs} | 81 | for dev in ${2:-$hdevs} |
82 | do | 82 | do |
83 | uwb_rc=$(readlink -f $dev/uwb_rc) | ||
84 | if cat $uwb_rc/beacon | grep -q -- "-1" | ||
85 | then | ||
86 | echo 13 0 > $uwb_rc/beacon | ||
87 | echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2 | ||
88 | fi | ||
89 | echo $host_CHID > $dev/wusb_chid | 83 | echo $host_CHID > $dev/wusb_chid |
90 | echo I: started host $(basename $dev) >&2 | 84 | echo I: started host $(basename $dev) >&2 |
91 | done | 85 | done |
@@ -95,9 +89,6 @@ case $1 in | |||
95 | do | 89 | do |
96 | echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid | 90 | echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid |
97 | echo I: stopped host $(basename $dev) >&2 | 91 | echo I: stopped host $(basename $dev) >&2 |
98 | uwb_rc=$(readlink -f $dev/uwb_rc) | ||
99 | echo -1 | cat > $uwb_rc/beacon | ||
100 | echo I: stopped beaconing on $(basename $uwb_rc) >&2 | ||
101 | done | 92 | done |
102 | ;; | 93 | ;; |
103 | set-chid) | 94 | set-chid) |
diff --git a/MAINTAINERS b/MAINTAINERS index 4209b7148758..befacf07729f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2049,6 +2049,12 @@ M: mikulas@artax.karlin.mff.cuni.cz | |||
2049 | W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi | 2049 | W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi |
2050 | S: Maintained | 2050 | S: Maintained |
2051 | 2051 | ||
2052 | HSO 3G Modem Driver (hso.c) | ||
2053 | P: Denis Joseph Barrow | ||
2054 | M: d.barow@option.com | ||
2055 | W: http://www.pharscape.org | ||
2056 | S: Maintained | ||
2057 | |||
2052 | HTCPEN TOUCHSCREEN DRIVER | 2058 | HTCPEN TOUCHSCREEN DRIVER |
2053 | P: Pau Oliva Fora | 2059 | P: Pau Oliva Fora |
2054 | M: pof@eslack.org | 2060 | M: pof@eslack.org |
@@ -2146,11 +2152,6 @@ M: Gadi Oxman <gadio@netvision.net.il> | |||
2146 | L: linux-kernel@vger.kernel.org | 2152 | L: linux-kernel@vger.kernel.org |
2147 | S: Maintained | 2153 | S: Maintained |
2148 | 2154 | ||
2149 | IDE-SCSI DRIVER | ||
2150 | L: linux-ide@vger.kernel.org | ||
2151 | L: linux-scsi@vger.kernel.org | ||
2152 | S: Orphan | ||
2153 | |||
2154 | IDLE-I7300 | 2155 | IDLE-I7300 |
2155 | P: Andy Henroid | 2156 | P: Andy Henroid |
2156 | M: andrew.d.henroid@intel.com | 2157 | M: andrew.d.henroid@intel.com |
@@ -2633,13 +2634,13 @@ W: http://www.hansenpartnership.com/voyager | |||
2633 | S: Maintained | 2634 | S: Maintained |
2634 | 2635 | ||
2635 | LINUX FOR POWERPC (32-BIT AND 64-BIT) | 2636 | LINUX FOR POWERPC (32-BIT AND 64-BIT) |
2636 | P: Paul Mackerras | ||
2637 | M: paulus@samba.org | ||
2638 | P: Benjamin Herrenschmidt | 2637 | P: Benjamin Herrenschmidt |
2639 | M: benh@kernel.crashing.org | 2638 | M: benh@kernel.crashing.org |
2639 | P: Paul Mackerras | ||
2640 | M: paulus@samba.org | ||
2640 | W: http://www.penguinppc.org/ | 2641 | W: http://www.penguinppc.org/ |
2641 | L: linuxppc-dev@ozlabs.org | 2642 | L: linuxppc-dev@ozlabs.org |
2642 | T: git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git | 2643 | T: git kernel.org:/pub/scm/linux/kernel/git/benh/powerpc.git |
2643 | S: Supported | 2644 | S: Supported |
2644 | 2645 | ||
2645 | LINUX FOR POWER MACINTOSH | 2646 | LINUX FOR POWER MACINTOSH |
diff --git a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c index 1f762189fa64..c2938e574a40 100644 --- a/arch/alpha/kernel/init_task.c +++ b/arch/alpha/kernel/init_task.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
9 | 9 | ||
10 | 10 | ||
11 | static struct fs_struct init_fs = INIT_FS; | ||
12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index 0bbf80625395..e859af349467 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
14 | 14 | ||
15 | static struct fs_struct init_fs = INIT_FS; | ||
16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c index 44058469c6ec..993d56ee3cf3 100644 --- a/arch/avr32/kernel/init_task.c +++ b/arch/avr32/kernel/init_task.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
15 | 15 | ||
16 | static struct fs_struct init_fs = INIT_FS; | ||
17 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
18 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
19 | struct mm_struct init_mm = INIT_MM(init_mm); | 18 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c index 6bdba7b21109..2c228c020978 100644 --- a/arch/blackfin/kernel/init_task.c +++ b/arch/blackfin/kernel/init_task.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/mqueue.h> | 33 | #include <linux/mqueue.h> |
34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
35 | 35 | ||
36 | static struct fs_struct init_fs = INIT_FS; | ||
37 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 36 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
38 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 37 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
39 | 38 | ||
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 5933656db5a2..60816e876455 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c | |||
@@ -37,7 +37,6 @@ | |||
37 | * setup. | 37 | * setup. |
38 | */ | 38 | */ |
39 | 39 | ||
40 | static struct fs_struct init_fs = INIT_FS; | ||
41 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 40 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
42 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 41 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
43 | struct mm_struct init_mm = INIT_MM(init_mm); | 42 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c index e2198815b630..29429a8b7f6a 100644 --- a/arch/frv/kernel/init_task.c +++ b/arch/frv/kernel/init_task.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | 11 | ||
12 | 12 | ||
13 | static struct fs_struct init_fs = INIT_FS; | ||
14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
16 | struct mm_struct init_mm = INIT_MM(init_mm); | 15 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c index 93a4899e46c2..cb5dc552da97 100644 --- a/arch/h8300/kernel/init_task.c +++ b/arch/h8300/kernel/init_task.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
14 | 14 | ||
15 | static struct fs_struct init_fs = INIT_FS; | ||
16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c index 9d7e1c66faf4..5b0e830c6f33 100644 --- a/arch/ia64/kernel/init_task.c +++ b/arch/ia64/kernel/init_task.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
19 | 19 | ||
20 | static struct fs_struct init_fs = INIT_FS; | ||
21 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 20 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
22 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 21 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
23 | struct mm_struct init_mm = INIT_MM(init_mm); | 22 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c index 0d658dbb6766..016885c6f260 100644 --- a/arch/m32r/kernel/init_task.c +++ b/arch/m32r/kernel/init_task.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
12 | #include <asm/pgtable.h> | 12 | #include <asm/pgtable.h> |
13 | 13 | ||
14 | static struct fs_struct init_fs = INIT_FS; | ||
15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
17 | struct mm_struct init_mm = INIT_MM(init_mm); | 16 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 3042c2bc8c58..632ce016014d 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -40,7 +40,6 @@ | |||
40 | * alignment requirements and potentially different initial | 40 | * alignment requirements and potentially different initial |
41 | * setup. | 41 | * setup. |
42 | */ | 42 | */ |
43 | static struct fs_struct init_fs = INIT_FS; | ||
44 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 43 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
45 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 44 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
46 | struct mm_struct init_mm = INIT_MM(init_mm); | 45 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c index 344c01aede08..fe282de1d596 100644 --- a/arch/m68knommu/kernel/init_task.c +++ b/arch/m68knommu/kernel/init_task.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
14 | 14 | ||
15 | static struct fs_struct init_fs = INIT_FS; | ||
16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c index d72487ad7c15..149cd914526e 100644 --- a/arch/mips/kernel/init_task.c +++ b/arch/mips/kernel/init_task.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | 11 | ||
12 | static struct fs_struct init_fs = INIT_FS; | ||
13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
15 | struct mm_struct init_mm = INIT_MM(init_mm); | 14 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c index af16f6e5c918..5ac3566f8c98 100644 --- a/arch/mn10300/kernel/init_task.c +++ b/arch/mn10300/kernel/init_task.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
20 | 20 | ||
21 | static struct fs_struct init_fs = INIT_FS; | ||
22 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 21 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
23 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 22 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
24 | struct mm_struct init_mm = INIT_MM(init_mm); | 23 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c index f5941c086551..1e25a45d64c1 100644 --- a/arch/parisc/kernel/init_task.c +++ b/arch/parisc/kernel/init_task.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
35 | #include <asm/pgalloc.h> | 35 | #include <asm/pgalloc.h> |
36 | 36 | ||
37 | static struct fs_struct init_fs = INIT_FS; | ||
38 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 37 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
39 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 38 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
40 | struct mm_struct init_mm = INIT_MM(init_mm); | 39 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c index 4c85b8d56478..688b329800bd 100644 --- a/arch/powerpc/kernel/init_task.c +++ b/arch/powerpc/kernel/init_task.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/mqueue.h> | 7 | #include <linux/mqueue.h> |
8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
9 | 9 | ||
10 | static struct fs_struct init_fs = INIT_FS; | ||
11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 10 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 11 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
13 | struct mm_struct init_mm = INIT_MM(init_mm); | 12 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c index 2949126d28d1..6b793aeda72e 100644 --- a/arch/powerpc/oprofile/cell/spu_task_sync.c +++ b/arch/powerpc/oprofile/cell/spu_task_sync.c | |||
@@ -297,7 +297,7 @@ static inline unsigned long fast_get_dcookie(struct path *path) | |||
297 | { | 297 | { |
298 | unsigned long cookie; | 298 | unsigned long cookie; |
299 | 299 | ||
300 | if (path->dentry->d_cookie) | 300 | if (path->dentry->d_flags & DCACHE_COOKIE) |
301 | return (unsigned long)path->dentry; | 301 | return (unsigned long)path->dentry; |
302 | get_dcookie(path, &cookie); | 302 | get_dcookie(path, &cookie); |
303 | return cookie; | 303 | return cookie; |
diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c index e80716843619..7db95c0b8693 100644 --- a/arch/s390/kernel/init_task.c +++ b/arch/s390/kernel/init_task.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
18 | 18 | ||
19 | static struct fs_struct init_fs = INIT_FS; | ||
20 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 19 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
21 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 20 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
22 | struct mm_struct init_mm = INIT_MM(init_mm); | 21 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c index b151a25cb14d..80c35ff71d56 100644 --- a/arch/sh/kernel/init_task.c +++ b/arch/sh/kernel/init_task.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
8 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
9 | 9 | ||
10 | static struct fs_struct init_fs = INIT_FS; | ||
11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 10 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 11 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
13 | struct pt_regs fake_swapper_regs; | 12 | struct pt_regs fake_swapper_regs; |
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index 62126e4cec54..f28cb8278e98 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
10 | 10 | ||
11 | static struct fs_struct init_fs = INIT_FS; | ||
12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index 910eda8fca18..806d381947bf 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include "linux/mqueue.h" | 10 | #include "linux/mqueue.h" |
11 | #include "asm/uaccess.h" | 11 | #include "asm/uaccess.h" |
12 | 12 | ||
13 | static struct fs_struct init_fs = INIT_FS; | ||
14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c index d39918076bb4..df3bf269beab 100644 --- a/arch/x86/kernel/init_task.c +++ b/arch/x86/kernel/init_task.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | #include <asm/desc.h> | 11 | #include <asm/desc.h> |
12 | 12 | ||
13 | static struct fs_struct init_fs = INIT_FS; | ||
14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
16 | struct mm_struct init_mm = INIT_MM(init_mm); | 15 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index f6ea94b74da1..74917658b004 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -170,7 +170,7 @@ static struct irq_cfg irq_cfgx[NR_IRQS] = { | |||
170 | [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, | 170 | [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, }, |
171 | }; | 171 | }; |
172 | 172 | ||
173 | void __init arch_early_irq_init(void) | 173 | int __init arch_early_irq_init(void) |
174 | { | 174 | { |
175 | struct irq_cfg *cfg; | 175 | struct irq_cfg *cfg; |
176 | struct irq_desc *desc; | 176 | struct irq_desc *desc; |
@@ -184,6 +184,8 @@ void __init arch_early_irq_init(void) | |||
184 | desc = irq_to_desc(i); | 184 | desc = irq_to_desc(i); |
185 | desc->chip_data = &cfg[i]; | 185 | desc->chip_data = &cfg[i]; |
186 | } | 186 | } |
187 | |||
188 | return 0; | ||
187 | } | 189 | } |
188 | 190 | ||
189 | #ifdef CONFIG_SPARSE_IRQ | 191 | #ifdef CONFIG_SPARSE_IRQ |
@@ -212,7 +214,7 @@ static struct irq_cfg *get_one_free_irq_cfg(int cpu) | |||
212 | return cfg; | 214 | return cfg; |
213 | } | 215 | } |
214 | 216 | ||
215 | void arch_init_chip_data(struct irq_desc *desc, int cpu) | 217 | int arch_init_chip_data(struct irq_desc *desc, int cpu) |
216 | { | 218 | { |
217 | struct irq_cfg *cfg; | 219 | struct irq_cfg *cfg; |
218 | 220 | ||
@@ -224,6 +226,8 @@ void arch_init_chip_data(struct irq_desc *desc, int cpu) | |||
224 | BUG_ON(1); | 226 | BUG_ON(1); |
225 | } | 227 | } |
226 | } | 228 | } |
229 | |||
230 | return 0; | ||
227 | } | 231 | } |
228 | 232 | ||
229 | #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC | 233 | #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC |
@@ -1345,8 +1349,6 @@ void __setup_vector_irq(int cpu) | |||
1345 | 1349 | ||
1346 | /* Mark the inuse vectors */ | 1350 | /* Mark the inuse vectors */ |
1347 | for_each_irq_desc(irq, desc) { | 1351 | for_each_irq_desc(irq, desc) { |
1348 | if (!desc) | ||
1349 | continue; | ||
1350 | cfg = desc->chip_data; | 1352 | cfg = desc->chip_data; |
1351 | if (!cpu_isset(cpu, cfg->domain)) | 1353 | if (!cpu_isset(cpu, cfg->domain)) |
1352 | continue; | 1354 | continue; |
@@ -1730,8 +1732,6 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1730 | for_each_irq_desc(irq, desc) { | 1732 | for_each_irq_desc(irq, desc) { |
1731 | struct irq_pin_list *entry; | 1733 | struct irq_pin_list *entry; |
1732 | 1734 | ||
1733 | if (!desc) | ||
1734 | continue; | ||
1735 | cfg = desc->chip_data; | 1735 | cfg = desc->chip_data; |
1736 | entry = cfg->irq_2_pin; | 1736 | entry = cfg->irq_2_pin; |
1737 | if (!entry) | 1737 | if (!entry) |
@@ -2378,9 +2378,6 @@ static void ir_irq_migration(struct work_struct *work) | |||
2378 | struct irq_desc *desc; | 2378 | struct irq_desc *desc; |
2379 | 2379 | ||
2380 | for_each_irq_desc(irq, desc) { | 2380 | for_each_irq_desc(irq, desc) { |
2381 | if (!desc) | ||
2382 | continue; | ||
2383 | |||
2384 | if (desc->status & IRQ_MOVE_PENDING) { | 2381 | if (desc->status & IRQ_MOVE_PENDING) { |
2385 | unsigned long flags; | 2382 | unsigned long flags; |
2386 | 2383 | ||
@@ -2670,9 +2667,6 @@ static inline void init_IO_APIC_traps(void) | |||
2670 | * 0x80, because int 0x80 is hm, kind of importantish. ;) | 2667 | * 0x80, because int 0x80 is hm, kind of importantish. ;) |
2671 | */ | 2668 | */ |
2672 | for_each_irq_desc(irq, desc) { | 2669 | for_each_irq_desc(irq, desc) { |
2673 | if (!desc) | ||
2674 | continue; | ||
2675 | |||
2676 | cfg = desc->chip_data; | 2670 | cfg = desc->chip_data; |
2677 | if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { | 2671 | if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { |
2678 | /* | 2672 | /* |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 8655b5bb0963..f99a6c6c432e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -435,8 +435,12 @@ static void __init set_highmem_pages_init(void) | |||
435 | #endif /* !CONFIG_NUMA */ | 435 | #endif /* !CONFIG_NUMA */ |
436 | 436 | ||
437 | #else | 437 | #else |
438 | # define permanent_kmaps_init(pgd_base) do { } while (0) | 438 | static inline void permanent_kmaps_init(pgd_t *pgd_base) |
439 | # define set_highmem_pages_init() do { } while (0) | 439 | { |
440 | } | ||
441 | static inline void set_highmem_pages_init(void) | ||
442 | { | ||
443 | } | ||
440 | #endif /* CONFIG_HIGHMEM */ | 444 | #endif /* CONFIG_HIGHMEM */ |
441 | 445 | ||
442 | void __init native_pagetable_setup_start(pgd_t *base) | 446 | void __init native_pagetable_setup_start(pgd_t *base) |
diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c index 3df469dbe814..e07f5c9fcd35 100644 --- a/arch/xtensa/kernel/init_task.c +++ b/arch/xtensa/kernel/init_task.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | 23 | ||
24 | static struct fs_struct init_fs = INIT_FS; | ||
25 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 24 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
26 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 25 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
27 | struct mm_struct init_mm = INIT_MM(init_mm); | 26 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index c602b547cc6e..1697043119bd 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -190,7 +190,7 @@ config DIGIEPCA | |||
190 | 190 | ||
191 | config ESPSERIAL | 191 | config ESPSERIAL |
192 | tristate "Hayes ESP serial port support" | 192 | tristate "Hayes ESP serial port support" |
193 | depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API | 193 | depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN |
194 | help | 194 | help |
195 | This is a driver which supports Hayes ESP serial ports. Both single | 195 | This is a driver which supports Hayes ESP serial ports. Both single |
196 | port cards and multiport cards are supported. Make sure to read | 196 | port cards and multiport cards are supported. Make sure to read |
@@ -443,6 +443,17 @@ config UNIX98_PTYS | |||
443 | All modern Linux systems use the Unix98 ptys. Say Y unless | 443 | All modern Linux systems use the Unix98 ptys. Say Y unless |
444 | you're on an embedded system and want to conserve memory. | 444 | you're on an embedded system and want to conserve memory. |
445 | 445 | ||
446 | config DEVPTS_MULTIPLE_INSTANCES | ||
447 | bool "Support multiple instances of devpts" | ||
448 | depends on UNIX98_PTYS | ||
449 | default n | ||
450 | ---help--- | ||
451 | Enable support for multiple instances of devpts filesystem. | ||
452 | If you want to have isolated PTY namespaces (eg: in containers), | ||
453 | say Y here. Otherwise, say N. If enabled, each mount of devpts | ||
454 | filesystem with the '-o newinstance' option will create an | ||
455 | independent PTY namespace. | ||
456 | |||
446 | config LEGACY_PTYS | 457 | config LEGACY_PTYS |
447 | bool "Legacy (BSD) PTY support" | 458 | bool "Legacy (BSD) PTY support" |
448 | default y | 459 | default y |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index b97aebd7aeb8..4e0cfdeab146 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -170,7 +170,7 @@ static __inline__ void rtsdtr_ctrl(int bits) | |||
170 | */ | 170 | */ |
171 | static void rs_stop(struct tty_struct *tty) | 171 | static void rs_stop(struct tty_struct *tty) |
172 | { | 172 | { |
173 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 173 | struct async_struct *info = tty->driver_data; |
174 | unsigned long flags; | 174 | unsigned long flags; |
175 | 175 | ||
176 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | 176 | if (serial_paranoia_check(info, tty->name, "rs_stop")) |
@@ -190,7 +190,7 @@ static void rs_stop(struct tty_struct *tty) | |||
190 | 190 | ||
191 | static void rs_start(struct tty_struct *tty) | 191 | static void rs_start(struct tty_struct *tty) |
192 | { | 192 | { |
193 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 193 | struct async_struct *info = tty->driver_data; |
194 | unsigned long flags; | 194 | unsigned long flags; |
195 | 195 | ||
196 | if (serial_paranoia_check(info, tty->name, "rs_start")) | 196 | if (serial_paranoia_check(info, tty->name, "rs_start")) |
@@ -861,7 +861,7 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) | |||
861 | 861 | ||
862 | static void rs_flush_chars(struct tty_struct *tty) | 862 | static void rs_flush_chars(struct tty_struct *tty) |
863 | { | 863 | { |
864 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 864 | struct async_struct *info = tty->driver_data; |
865 | unsigned long flags; | 865 | unsigned long flags; |
866 | 866 | ||
867 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) | 867 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) |
@@ -934,7 +934,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count | |||
934 | 934 | ||
935 | static int rs_write_room(struct tty_struct *tty) | 935 | static int rs_write_room(struct tty_struct *tty) |
936 | { | 936 | { |
937 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 937 | struct async_struct *info = tty->driver_data; |
938 | 938 | ||
939 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) | 939 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) |
940 | return 0; | 940 | return 0; |
@@ -943,7 +943,7 @@ static int rs_write_room(struct tty_struct *tty) | |||
943 | 943 | ||
944 | static int rs_chars_in_buffer(struct tty_struct *tty) | 944 | static int rs_chars_in_buffer(struct tty_struct *tty) |
945 | { | 945 | { |
946 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 946 | struct async_struct *info = tty->driver_data; |
947 | 947 | ||
948 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) | 948 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) |
949 | return 0; | 949 | return 0; |
@@ -952,7 +952,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty) | |||
952 | 952 | ||
953 | static void rs_flush_buffer(struct tty_struct *tty) | 953 | static void rs_flush_buffer(struct tty_struct *tty) |
954 | { | 954 | { |
955 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 955 | struct async_struct *info = tty->driver_data; |
956 | unsigned long flags; | 956 | unsigned long flags; |
957 | 957 | ||
958 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | 958 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) |
@@ -969,7 +969,7 @@ static void rs_flush_buffer(struct tty_struct *tty) | |||
969 | */ | 969 | */ |
970 | static void rs_send_xchar(struct tty_struct *tty, char ch) | 970 | static void rs_send_xchar(struct tty_struct *tty, char ch) |
971 | { | 971 | { |
972 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 972 | struct async_struct *info = tty->driver_data; |
973 | unsigned long flags; | 973 | unsigned long flags; |
974 | 974 | ||
975 | if (serial_paranoia_check(info, tty->name, "rs_send_char")) | 975 | if (serial_paranoia_check(info, tty->name, "rs_send_char")) |
@@ -1004,7 +1004,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) | |||
1004 | */ | 1004 | */ |
1005 | static void rs_throttle(struct tty_struct * tty) | 1005 | static void rs_throttle(struct tty_struct * tty) |
1006 | { | 1006 | { |
1007 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 1007 | struct async_struct *info = tty->driver_data; |
1008 | unsigned long flags; | 1008 | unsigned long flags; |
1009 | #ifdef SERIAL_DEBUG_THROTTLE | 1009 | #ifdef SERIAL_DEBUG_THROTTLE |
1010 | char buf[64]; | 1010 | char buf[64]; |
@@ -1029,7 +1029,7 @@ static void rs_throttle(struct tty_struct * tty) | |||
1029 | 1029 | ||
1030 | static void rs_unthrottle(struct tty_struct * tty) | 1030 | static void rs_unthrottle(struct tty_struct * tty) |
1031 | { | 1031 | { |
1032 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 1032 | struct async_struct *info = tty->driver_data; |
1033 | unsigned long flags; | 1033 | unsigned long flags; |
1034 | #ifdef SERIAL_DEBUG_THROTTLE | 1034 | #ifdef SERIAL_DEBUG_THROTTLE |
1035 | char buf[64]; | 1035 | char buf[64]; |
@@ -1194,7 +1194,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int __user *value) | |||
1194 | 1194 | ||
1195 | static int rs_tiocmget(struct tty_struct *tty, struct file *file) | 1195 | static int rs_tiocmget(struct tty_struct *tty, struct file *file) |
1196 | { | 1196 | { |
1197 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1197 | struct async_struct * info = tty->driver_data; |
1198 | unsigned char control, status; | 1198 | unsigned char control, status; |
1199 | unsigned long flags; | 1199 | unsigned long flags; |
1200 | 1200 | ||
@@ -1217,7 +1217,7 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file) | |||
1217 | static int rs_tiocmset(struct tty_struct *tty, struct file *file, | 1217 | static int rs_tiocmset(struct tty_struct *tty, struct file *file, |
1218 | unsigned int set, unsigned int clear) | 1218 | unsigned int set, unsigned int clear) |
1219 | { | 1219 | { |
1220 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1220 | struct async_struct * info = tty->driver_data; |
1221 | unsigned long flags; | 1221 | unsigned long flags; |
1222 | 1222 | ||
1223 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | 1223 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
@@ -1244,7 +1244,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
1244 | */ | 1244 | */ |
1245 | static int rs_break(struct tty_struct *tty, int break_state) | 1245 | static int rs_break(struct tty_struct *tty, int break_state) |
1246 | { | 1246 | { |
1247 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1247 | struct async_struct * info = tty->driver_data; |
1248 | unsigned long flags; | 1248 | unsigned long flags; |
1249 | 1249 | ||
1250 | if (serial_paranoia_check(info, tty->name, "rs_break")) | 1250 | if (serial_paranoia_check(info, tty->name, "rs_break")) |
@@ -1264,7 +1264,7 @@ static int rs_break(struct tty_struct *tty, int break_state) | |||
1264 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 1264 | static int rs_ioctl(struct tty_struct *tty, struct file * file, |
1265 | unsigned int cmd, unsigned long arg) | 1265 | unsigned int cmd, unsigned long arg) |
1266 | { | 1266 | { |
1267 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1267 | struct async_struct * info = tty->driver_data; |
1268 | struct async_icount cprev, cnow; /* kernel counter temps */ | 1268 | struct async_icount cprev, cnow; /* kernel counter temps */ |
1269 | struct serial_icounter_struct icount; | 1269 | struct serial_icounter_struct icount; |
1270 | void __user *argp = (void __user *)arg; | 1270 | void __user *argp = (void __user *)arg; |
@@ -1368,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1368 | 1368 | ||
1369 | static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 1369 | static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
1370 | { | 1370 | { |
1371 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 1371 | struct async_struct *info = tty->driver_data; |
1372 | unsigned long flags; | 1372 | unsigned long flags; |
1373 | unsigned int cflag = tty->termios->c_cflag; | 1373 | unsigned int cflag = tty->termios->c_cflag; |
1374 | 1374 | ||
@@ -1428,7 +1428,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
1428 | */ | 1428 | */ |
1429 | static void rs_close(struct tty_struct *tty, struct file * filp) | 1429 | static void rs_close(struct tty_struct *tty, struct file * filp) |
1430 | { | 1430 | { |
1431 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1431 | struct async_struct * info = tty->driver_data; |
1432 | struct serial_state *state; | 1432 | struct serial_state *state; |
1433 | unsigned long flags; | 1433 | unsigned long flags; |
1434 | 1434 | ||
@@ -1523,7 +1523,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1523 | */ | 1523 | */ |
1524 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | 1524 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) |
1525 | { | 1525 | { |
1526 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1526 | struct async_struct * info = tty->driver_data; |
1527 | unsigned long orig_jiffies, char_time; | 1527 | unsigned long orig_jiffies, char_time; |
1528 | int lsr; | 1528 | int lsr; |
1529 | 1529 | ||
@@ -1587,7 +1587,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1587 | */ | 1587 | */ |
1588 | static void rs_hangup(struct tty_struct *tty) | 1588 | static void rs_hangup(struct tty_struct *tty) |
1589 | { | 1589 | { |
1590 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1590 | struct async_struct * info = tty->driver_data; |
1591 | struct serial_state *state = info->state; | 1591 | struct serial_state *state = info->state; |
1592 | 1592 | ||
1593 | if (serial_paranoia_check(info, tty->name, "rs_hangup")) | 1593 | if (serial_paranoia_check(info, tty->name, "rs_hangup")) |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 5e5b1dc1a0a7..6a59f72a9c21 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -5010,7 +5010,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5010 | if (nchan == 0) { | 5010 | if (nchan == 0) { |
5011 | dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " | 5011 | dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " |
5012 | "Serial-Modules\n"); | 5012 | "Serial-Modules\n"); |
5013 | return -EIO; | 5013 | goto err_unmap; |
5014 | } | 5014 | } |
5015 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { | 5015 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { |
5016 | struct RUNTIME_9060 __iomem *ctl_addr; | 5016 | struct RUNTIME_9060 __iomem *ctl_addr; |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index cf2461d34e5f..39ad820b2350 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -69,7 +69,9 @@ static int invalid_lilo_config; | |||
69 | 69 | ||
70 | /* | 70 | /* |
71 | * The ISA boards do window flipping into the same spaces so its only sane with | 71 | * The ISA boards do window flipping into the same spaces so its only sane with |
72 | * a single lock. It's still pretty efficient. | 72 | * a single lock. It's still pretty efficient. This lock guards the hardware |
73 | * and the tty_port lock guards the kernel side stuff like use counts. Take | ||
74 | * this lock inside the port lock if you must take both. | ||
73 | */ | 75 | */ |
74 | static DEFINE_SPINLOCK(epca_lock); | 76 | static DEFINE_SPINLOCK(epca_lock); |
75 | 77 | ||
@@ -156,14 +158,12 @@ static struct channel *verifyChannel(struct tty_struct *); | |||
156 | static void pc_sched_event(struct channel *, int); | 158 | static void pc_sched_event(struct channel *, int); |
157 | static void epca_error(int, char *); | 159 | static void epca_error(int, char *); |
158 | static void pc_close(struct tty_struct *, struct file *); | 160 | static void pc_close(struct tty_struct *, struct file *); |
159 | static void shutdown(struct channel *); | 161 | static void shutdown(struct channel *, struct tty_struct *tty); |
160 | static void pc_hangup(struct tty_struct *); | 162 | static void pc_hangup(struct tty_struct *); |
161 | static int pc_write_room(struct tty_struct *); | 163 | static int pc_write_room(struct tty_struct *); |
162 | static int pc_chars_in_buffer(struct tty_struct *); | 164 | static int pc_chars_in_buffer(struct tty_struct *); |
163 | static void pc_flush_buffer(struct tty_struct *); | 165 | static void pc_flush_buffer(struct tty_struct *); |
164 | static void pc_flush_chars(struct tty_struct *); | 166 | static void pc_flush_chars(struct tty_struct *); |
165 | static int block_til_ready(struct tty_struct *, struct file *, | ||
166 | struct channel *); | ||
167 | static int pc_open(struct tty_struct *, struct file *); | 167 | static int pc_open(struct tty_struct *, struct file *); |
168 | static void post_fep_init(unsigned int crd); | 168 | static void post_fep_init(unsigned int crd); |
169 | static void epcapoll(unsigned long); | 169 | static void epcapoll(unsigned long); |
@@ -173,7 +173,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned); | |||
173 | static unsigned termios2digi_i(struct channel *ch, unsigned); | 173 | static unsigned termios2digi_i(struct channel *ch, unsigned); |
174 | static unsigned termios2digi_c(struct channel *ch, unsigned); | 174 | static unsigned termios2digi_c(struct channel *ch, unsigned); |
175 | static void epcaparam(struct tty_struct *, struct channel *); | 175 | static void epcaparam(struct tty_struct *, struct channel *); |
176 | static void receive_data(struct channel *); | 176 | static void receive_data(struct channel *, struct tty_struct *tty); |
177 | static int pc_ioctl(struct tty_struct *, struct file *, | 177 | static int pc_ioctl(struct tty_struct *, struct file *, |
178 | unsigned int, unsigned long); | 178 | unsigned int, unsigned long); |
179 | static int info_ioctl(struct tty_struct *, struct file *, | 179 | static int info_ioctl(struct tty_struct *, struct file *, |
@@ -392,7 +392,7 @@ static struct channel *verifyChannel(struct tty_struct *tty) | |||
392 | * through tty->driver_data this should catch it. | 392 | * through tty->driver_data this should catch it. |
393 | */ | 393 | */ |
394 | if (tty) { | 394 | if (tty) { |
395 | struct channel *ch = (struct channel *)tty->driver_data; | 395 | struct channel *ch = tty->driver_data; |
396 | if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { | 396 | if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { |
397 | if (ch->magic == EPCA_MAGIC) | 397 | if (ch->magic == EPCA_MAGIC) |
398 | return ch; | 398 | return ch; |
@@ -419,76 +419,34 @@ static void epca_error(int line, char *msg) | |||
419 | static void pc_close(struct tty_struct *tty, struct file *filp) | 419 | static void pc_close(struct tty_struct *tty, struct file *filp) |
420 | { | 420 | { |
421 | struct channel *ch; | 421 | struct channel *ch; |
422 | unsigned long flags; | 422 | struct tty_port *port; |
423 | /* | 423 | /* |
424 | * verifyChannel returns the channel from the tty struct if it is | 424 | * verifyChannel returns the channel from the tty struct if it is |
425 | * valid. This serves as a sanity check. | 425 | * valid. This serves as a sanity check. |
426 | */ | 426 | */ |
427 | ch = verifyChannel(tty); | 427 | ch = verifyChannel(tty); |
428 | if (ch != NULL) { | 428 | if (ch == NULL) |
429 | spin_lock_irqsave(&epca_lock, flags); | 429 | return; |
430 | if (tty_hung_up_p(filp)) { | 430 | port = &ch->port; |
431 | spin_unlock_irqrestore(&epca_lock, flags); | ||
432 | return; | ||
433 | } | ||
434 | if (ch->port.count-- > 1) { | ||
435 | /* Begin channel is open more than once */ | ||
436 | /* | ||
437 | * Return without doing anything. Someone might still | ||
438 | * be using the channel. | ||
439 | */ | ||
440 | spin_unlock_irqrestore(&epca_lock, flags); | ||
441 | return; | ||
442 | } | ||
443 | /* Port open only once go ahead with shutdown & reset */ | ||
444 | BUG_ON(ch->port.count < 0); | ||
445 | |||
446 | /* | ||
447 | * Let the rest of the driver know the channel is being closed. | ||
448 | * This becomes important if an open is attempted before close | ||
449 | * is finished. | ||
450 | */ | ||
451 | ch->port.flags |= ASYNC_CLOSING; | ||
452 | tty->closing = 1; | ||
453 | |||
454 | spin_unlock_irqrestore(&epca_lock, flags); | ||
455 | |||
456 | if (ch->port.flags & ASYNC_INITIALIZED) { | ||
457 | /* Setup an event to indicate when the | ||
458 | transmit buffer empties */ | ||
459 | setup_empty_event(tty, ch); | ||
460 | /* 30 seconds timeout */ | ||
461 | tty_wait_until_sent(tty, 3000); | ||
462 | } | ||
463 | pc_flush_buffer(tty); | ||
464 | 431 | ||
465 | tty_ldisc_flush(tty); | 432 | if (tty_port_close_start(port, tty, filp) == 0) |
466 | shutdown(ch); | 433 | return; |
467 | 434 | ||
468 | spin_lock_irqsave(&epca_lock, flags); | 435 | pc_flush_buffer(tty); |
469 | tty->closing = 0; | 436 | shutdown(ch, tty); |
470 | ch->event = 0; | ||
471 | ch->port.tty = NULL; | ||
472 | spin_unlock_irqrestore(&epca_lock, flags); | ||
473 | 437 | ||
474 | if (ch->port.blocked_open) { | 438 | tty_port_close_end(port, tty); |
475 | if (ch->close_delay) | 439 | ch->event = 0; /* FIXME: review ch->event locking */ |
476 | msleep_interruptible(jiffies_to_msecs(ch->close_delay)); | 440 | tty_port_tty_set(port, NULL); |
477 | wake_up_interruptible(&ch->port.open_wait); | ||
478 | } | ||
479 | ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | | ||
480 | ASYNC_CLOSING); | ||
481 | wake_up_interruptible(&ch->port.close_wait); | ||
482 | } | ||
483 | } | 441 | } |
484 | 442 | ||
485 | static void shutdown(struct channel *ch) | 443 | static void shutdown(struct channel *ch, struct tty_struct *tty) |
486 | { | 444 | { |
487 | unsigned long flags; | 445 | unsigned long flags; |
488 | struct tty_struct *tty; | ||
489 | struct board_chan __iomem *bc; | 446 | struct board_chan __iomem *bc; |
447 | struct tty_port *port = &ch->port; | ||
490 | 448 | ||
491 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | 449 | if (!(port->flags & ASYNC_INITIALIZED)) |
492 | return; | 450 | return; |
493 | 451 | ||
494 | spin_lock_irqsave(&epca_lock, flags); | 452 | spin_lock_irqsave(&epca_lock, flags); |
@@ -503,7 +461,6 @@ static void shutdown(struct channel *ch) | |||
503 | */ | 461 | */ |
504 | if (bc) | 462 | if (bc) |
505 | writeb(0, &bc->idata); | 463 | writeb(0, &bc->idata); |
506 | tty = ch->port.tty; | ||
507 | 464 | ||
508 | /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ | 465 | /* If we're a modem control device and HUPCL is on, drop RTS & DTR. */ |
509 | if (tty->termios->c_cflag & HUPCL) { | 466 | if (tty->termios->c_cflag & HUPCL) { |
@@ -517,32 +474,26 @@ static void shutdown(struct channel *ch) | |||
517 | * will have to reinitialized. Set a flag to indicate this. | 474 | * will have to reinitialized. Set a flag to indicate this. |
518 | */ | 475 | */ |
519 | /* Prevent future Digi programmed interrupts from coming active */ | 476 | /* Prevent future Digi programmed interrupts from coming active */ |
520 | ch->port.flags &= ~ASYNC_INITIALIZED; | 477 | port->flags &= ~ASYNC_INITIALIZED; |
521 | spin_unlock_irqrestore(&epca_lock, flags); | 478 | spin_unlock_irqrestore(&epca_lock, flags); |
522 | } | 479 | } |
523 | 480 | ||
524 | static void pc_hangup(struct tty_struct *tty) | 481 | static void pc_hangup(struct tty_struct *tty) |
525 | { | 482 | { |
526 | struct channel *ch; | 483 | struct channel *ch; |
484 | |||
527 | /* | 485 | /* |
528 | * verifyChannel returns the channel from the tty struct if it is | 486 | * verifyChannel returns the channel from the tty struct if it is |
529 | * valid. This serves as a sanity check. | 487 | * valid. This serves as a sanity check. |
530 | */ | 488 | */ |
531 | ch = verifyChannel(tty); | 489 | ch = verifyChannel(tty); |
532 | if (ch != NULL) { | 490 | if (ch != NULL) { |
533 | unsigned long flags; | ||
534 | |||
535 | pc_flush_buffer(tty); | 491 | pc_flush_buffer(tty); |
536 | tty_ldisc_flush(tty); | 492 | tty_ldisc_flush(tty); |
537 | shutdown(ch); | 493 | shutdown(ch, tty); |
538 | 494 | ||
539 | spin_lock_irqsave(&epca_lock, flags); | 495 | ch->event = 0; /* FIXME: review locking of ch->event */ |
540 | ch->port.tty = NULL; | 496 | tty_port_hangup(&ch->port); |
541 | ch->event = 0; | ||
542 | ch->port.count = 0; | ||
543 | ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); | ||
544 | spin_unlock_irqrestore(&epca_lock, flags); | ||
545 | wake_up_interruptible(&ch->port.open_wait); | ||
546 | } | 497 | } |
547 | } | 498 | } |
548 | 499 | ||
@@ -786,100 +737,22 @@ static void pc_flush_chars(struct tty_struct *tty) | |||
786 | } | 737 | } |
787 | } | 738 | } |
788 | 739 | ||
789 | static int block_til_ready(struct tty_struct *tty, | 740 | static int epca_carrier_raised(struct tty_port *port) |
790 | struct file *filp, struct channel *ch) | ||
791 | { | 741 | { |
792 | DECLARE_WAITQUEUE(wait, current); | 742 | struct channel *ch = container_of(port, struct channel, port); |
793 | int retval, do_clocal = 0; | 743 | if (ch->imodem & ch->dcd) |
794 | unsigned long flags; | 744 | return 1; |
795 | |||
796 | if (tty_hung_up_p(filp)) { | ||
797 | if (ch->port.flags & ASYNC_HUP_NOTIFY) | ||
798 | retval = -EAGAIN; | ||
799 | else | ||
800 | retval = -ERESTARTSYS; | ||
801 | return retval; | ||
802 | } | ||
803 | |||
804 | /* | ||
805 | * If the device is in the middle of being closed, then block until | ||
806 | * it's done, and then try again. | ||
807 | */ | ||
808 | if (ch->port.flags & ASYNC_CLOSING) { | ||
809 | interruptible_sleep_on(&ch->port.close_wait); | ||
810 | |||
811 | if (ch->port.flags & ASYNC_HUP_NOTIFY) | ||
812 | return -EAGAIN; | ||
813 | else | ||
814 | return -ERESTARTSYS; | ||
815 | } | ||
816 | |||
817 | if (filp->f_flags & O_NONBLOCK) { | ||
818 | /* | ||
819 | * If non-blocking mode is set, then make the check up front | ||
820 | * and then exit. | ||
821 | */ | ||
822 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
823 | return 0; | ||
824 | } | ||
825 | if (tty->termios->c_cflag & CLOCAL) | ||
826 | do_clocal = 1; | ||
827 | /* Block waiting for the carrier detect and the line to become free */ | ||
828 | |||
829 | retval = 0; | ||
830 | add_wait_queue(&ch->port.open_wait, &wait); | ||
831 | |||
832 | spin_lock_irqsave(&epca_lock, flags); | ||
833 | /* We dec count so that pc_close will know when to free things */ | ||
834 | if (!tty_hung_up_p(filp)) | ||
835 | ch->port.count--; | ||
836 | ch->port.blocked_open++; | ||
837 | while (1) { | ||
838 | set_current_state(TASK_INTERRUPTIBLE); | ||
839 | if (tty_hung_up_p(filp) || | ||
840 | !(ch->port.flags & ASYNC_INITIALIZED)) { | ||
841 | if (ch->port.flags & ASYNC_HUP_NOTIFY) | ||
842 | retval = -EAGAIN; | ||
843 | else | ||
844 | retval = -ERESTARTSYS; | ||
845 | break; | ||
846 | } | ||
847 | if (!(ch->port.flags & ASYNC_CLOSING) && | ||
848 | (do_clocal || (ch->imodem & ch->dcd))) | ||
849 | break; | ||
850 | if (signal_pending(current)) { | ||
851 | retval = -ERESTARTSYS; | ||
852 | break; | ||
853 | } | ||
854 | spin_unlock_irqrestore(&epca_lock, flags); | ||
855 | /* | ||
856 | * Allow someone else to be scheduled. We will occasionally go | ||
857 | * through this loop until one of the above conditions change. | ||
858 | * The below schedule call will allow other processes to enter | ||
859 | * and prevent this loop from hogging the cpu. | ||
860 | */ | ||
861 | schedule(); | ||
862 | spin_lock_irqsave(&epca_lock, flags); | ||
863 | } | ||
864 | |||
865 | __set_current_state(TASK_RUNNING); | ||
866 | remove_wait_queue(&ch->port.open_wait, &wait); | ||
867 | if (!tty_hung_up_p(filp)) | ||
868 | ch->port.count++; | ||
869 | ch->port.blocked_open--; | ||
870 | |||
871 | spin_unlock_irqrestore(&epca_lock, flags); | ||
872 | |||
873 | if (retval) | ||
874 | return retval; | ||
875 | |||
876 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
877 | return 0; | 745 | return 0; |
878 | } | 746 | } |
879 | 747 | ||
748 | static void epca_raise_dtr_rts(struct tty_port *port) | ||
749 | { | ||
750 | } | ||
751 | |||
880 | static int pc_open(struct tty_struct *tty, struct file *filp) | 752 | static int pc_open(struct tty_struct *tty, struct file *filp) |
881 | { | 753 | { |
882 | struct channel *ch; | 754 | struct channel *ch; |
755 | struct tty_port *port; | ||
883 | unsigned long flags; | 756 | unsigned long flags; |
884 | int line, retval, boardnum; | 757 | int line, retval, boardnum; |
885 | struct board_chan __iomem *bc; | 758 | struct board_chan __iomem *bc; |
@@ -890,6 +763,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
890 | return -ENODEV; | 763 | return -ENODEV; |
891 | 764 | ||
892 | ch = &digi_channels[line]; | 765 | ch = &digi_channels[line]; |
766 | port = &ch->port; | ||
893 | boardnum = ch->boardnum; | 767 | boardnum = ch->boardnum; |
894 | 768 | ||
895 | /* Check status of board configured in system. */ | 769 | /* Check status of board configured in system. */ |
@@ -926,22 +800,24 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
926 | return -ENODEV; | 800 | return -ENODEV; |
927 | } | 801 | } |
928 | 802 | ||
929 | spin_lock_irqsave(&epca_lock, flags); | 803 | spin_lock_irqsave(&port->lock, flags); |
930 | /* | 804 | /* |
931 | * Every time a channel is opened, increment a counter. This is | 805 | * Every time a channel is opened, increment a counter. This is |
932 | * necessary because we do not wish to flush and shutdown the channel | 806 | * necessary because we do not wish to flush and shutdown the channel |
933 | * until the last app holding the channel open, closes it. | 807 | * until the last app holding the channel open, closes it. |
934 | */ | 808 | */ |
935 | ch->port.count++; | 809 | port->count++; |
936 | /* | 810 | /* |
937 | * Set a kernel structures pointer to our local channel structure. This | 811 | * Set a kernel structures pointer to our local channel structure. This |
938 | * way we can get to it when passed only a tty struct. | 812 | * way we can get to it when passed only a tty struct. |
939 | */ | 813 | */ |
940 | tty->driver_data = ch; | 814 | tty->driver_data = ch; |
815 | port->tty = tty; | ||
941 | /* | 816 | /* |
942 | * If this is the first time the channel has been opened, initialize | 817 | * If this is the first time the channel has been opened, initialize |
943 | * the tty->termios struct otherwise let pc_close handle it. | 818 | * the tty->termios struct otherwise let pc_close handle it. |
944 | */ | 819 | */ |
820 | spin_lock(&epca_lock); | ||
945 | globalwinon(ch); | 821 | globalwinon(ch); |
946 | ch->statusflags = 0; | 822 | ch->statusflags = 0; |
947 | 823 | ||
@@ -956,31 +832,33 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
956 | writew(head, &bc->rout); | 832 | writew(head, &bc->rout); |
957 | 833 | ||
958 | /* Set the channels associated tty structure */ | 834 | /* Set the channels associated tty structure */ |
959 | ch->port.tty = tty; | ||
960 | 835 | ||
961 | /* | 836 | /* |
962 | * The below routine generally sets up parity, baud, flow control | 837 | * The below routine generally sets up parity, baud, flow control |
963 | * issues, etc.... It effect both control flags and input flags. | 838 | * issues, etc.... It effect both control flags and input flags. |
964 | */ | 839 | */ |
965 | epcaparam(tty, ch); | 840 | epcaparam(tty, ch); |
966 | ch->port.flags |= ASYNC_INITIALIZED; | ||
967 | memoff(ch); | 841 | memoff(ch); |
968 | spin_unlock_irqrestore(&epca_lock, flags); | 842 | spin_unlock(&epca_lock); |
843 | port->flags |= ASYNC_INITIALIZED; | ||
844 | spin_unlock_irqrestore(&port->lock, flags); | ||
969 | 845 | ||
970 | retval = block_til_ready(tty, filp, ch); | 846 | retval = tty_port_block_til_ready(port, tty, filp); |
971 | if (retval) | 847 | if (retval) |
972 | return retval; | 848 | return retval; |
973 | /* | 849 | /* |
974 | * Set this again in case a hangup set it to zero while this open() was | 850 | * Set this again in case a hangup set it to zero while this open() was |
975 | * waiting for the line... | 851 | * waiting for the line... |
976 | */ | 852 | */ |
977 | spin_lock_irqsave(&epca_lock, flags); | 853 | spin_lock_irqsave(&port->lock, flags); |
978 | ch->port.tty = tty; | 854 | port->tty = tty; |
855 | spin_lock(&epca_lock); | ||
979 | globalwinon(ch); | 856 | globalwinon(ch); |
980 | /* Enable Digi Data events */ | 857 | /* Enable Digi Data events */ |
981 | writeb(1, &bc->idata); | 858 | writeb(1, &bc->idata); |
982 | memoff(ch); | 859 | memoff(ch); |
983 | spin_unlock_irqrestore(&epca_lock, flags); | 860 | spin_unlock(&epca_lock); |
861 | spin_unlock_irqrestore(&port->lock, flags); | ||
984 | return 0; | 862 | return 0; |
985 | } | 863 | } |
986 | 864 | ||
@@ -1016,8 +894,11 @@ static void __exit epca_module_exit(void) | |||
1016 | } | 894 | } |
1017 | ch = card_ptr[crd]; | 895 | ch = card_ptr[crd]; |
1018 | for (count = 0; count < bd->numports; count++, ch++) { | 896 | for (count = 0; count < bd->numports; count++, ch++) { |
1019 | if (ch && ch->port.tty) | 897 | struct tty_struct *tty = tty_port_tty_get(&ch->port); |
1020 | tty_hangup(ch->port.tty); | 898 | if (tty) { |
899 | tty_hangup(tty); | ||
900 | tty_kref_put(tty); | ||
901 | } | ||
1021 | } | 902 | } |
1022 | } | 903 | } |
1023 | pci_unregister_driver(&epca_driver); | 904 | pci_unregister_driver(&epca_driver); |
@@ -1042,6 +923,11 @@ static const struct tty_operations pc_ops = { | |||
1042 | .break_ctl = pc_send_break | 923 | .break_ctl = pc_send_break |
1043 | }; | 924 | }; |
1044 | 925 | ||
926 | static const struct tty_port_operations epca_port_ops = { | ||
927 | .carrier_raised = epca_carrier_raised, | ||
928 | .raise_dtr_rts = epca_raise_dtr_rts, | ||
929 | }; | ||
930 | |||
1045 | static int info_open(struct tty_struct *tty, struct file *filp) | 931 | static int info_open(struct tty_struct *tty, struct file *filp) |
1046 | { | 932 | { |
1047 | return 0; | 933 | return 0; |
@@ -1377,6 +1263,7 @@ static void post_fep_init(unsigned int crd) | |||
1377 | u16 tseg, rseg; | 1263 | u16 tseg, rseg; |
1378 | 1264 | ||
1379 | tty_port_init(&ch->port); | 1265 | tty_port_init(&ch->port); |
1266 | ch->port.ops = &epca_port_ops; | ||
1380 | ch->brdchan = bc; | 1267 | ch->brdchan = bc; |
1381 | ch->mailbox = gd; | 1268 | ch->mailbox = gd; |
1382 | INIT_WORK(&ch->tqueue, do_softint); | 1269 | INIT_WORK(&ch->tqueue, do_softint); |
@@ -1428,7 +1315,7 @@ static void post_fep_init(unsigned int crd) | |||
1428 | ch->boardnum = crd; | 1315 | ch->boardnum = crd; |
1429 | ch->channelnum = i; | 1316 | ch->channelnum = i; |
1430 | ch->magic = EPCA_MAGIC; | 1317 | ch->magic = EPCA_MAGIC; |
1431 | ch->port.tty = NULL; | 1318 | tty_port_tty_set(&ch->port, NULL); |
1432 | 1319 | ||
1433 | if (shrinkmem) { | 1320 | if (shrinkmem) { |
1434 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); | 1321 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); |
@@ -1510,7 +1397,7 @@ static void post_fep_init(unsigned int crd) | |||
1510 | ch->fepstartca = 0; | 1397 | ch->fepstartca = 0; |
1511 | ch->fepstopca = 0; | 1398 | ch->fepstopca = 0; |
1512 | 1399 | ||
1513 | ch->close_delay = 50; | 1400 | ch->port.close_delay = 50; |
1514 | 1401 | ||
1515 | spin_unlock_irqrestore(&epca_lock, flags); | 1402 | spin_unlock_irqrestore(&epca_lock, flags); |
1516 | } | 1403 | } |
@@ -1622,15 +1509,16 @@ static void doevent(int crd) | |||
1622 | if (bc == NULL) | 1509 | if (bc == NULL) |
1623 | goto next; | 1510 | goto next; |
1624 | 1511 | ||
1512 | tty = tty_port_tty_get(&ch->port); | ||
1625 | if (event & DATA_IND) { /* Begin DATA_IND */ | 1513 | if (event & DATA_IND) { /* Begin DATA_IND */ |
1626 | receive_data(ch); | 1514 | receive_data(ch, tty); |
1627 | assertgwinon(ch); | 1515 | assertgwinon(ch); |
1628 | } /* End DATA_IND */ | 1516 | } /* End DATA_IND */ |
1629 | /* else *//* Fix for DCD transition missed bug */ | 1517 | /* else *//* Fix for DCD transition missed bug */ |
1630 | if (event & MODEMCHG_IND) { | 1518 | if (event & MODEMCHG_IND) { |
1631 | /* A modem signal change has been indicated */ | 1519 | /* A modem signal change has been indicated */ |
1632 | ch->imodem = mstat; | 1520 | ch->imodem = mstat; |
1633 | if (ch->port.flags & ASYNC_CHECK_CD) { | 1521 | if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { |
1634 | /* We are now receiving dcd */ | 1522 | /* We are now receiving dcd */ |
1635 | if (mstat & ch->dcd) | 1523 | if (mstat & ch->dcd) |
1636 | wake_up_interruptible(&ch->port.open_wait); | 1524 | wake_up_interruptible(&ch->port.open_wait); |
@@ -1638,7 +1526,6 @@ static void doevent(int crd) | |||
1638 | pc_sched_event(ch, EPCA_EVENT_HANGUP); | 1526 | pc_sched_event(ch, EPCA_EVENT_HANGUP); |
1639 | } | 1527 | } |
1640 | } | 1528 | } |
1641 | tty = ch->port.tty; | ||
1642 | if (tty) { | 1529 | if (tty) { |
1643 | if (event & BREAK_IND) { | 1530 | if (event & BREAK_IND) { |
1644 | /* A break has been indicated */ | 1531 | /* A break has been indicated */ |
@@ -1658,6 +1545,7 @@ static void doevent(int crd) | |||
1658 | tty_wakeup(tty); | 1545 | tty_wakeup(tty); |
1659 | } | 1546 | } |
1660 | } | 1547 | } |
1548 | tty_kref_put(tty); | ||
1661 | } | 1549 | } |
1662 | next: | 1550 | next: |
1663 | globalwinon(ch); | 1551 | globalwinon(ch); |
@@ -1877,9 +1765,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
1877 | * that the driver will wait on carrier detect. | 1765 | * that the driver will wait on carrier detect. |
1878 | */ | 1766 | */ |
1879 | if (ts->c_cflag & CLOCAL) | 1767 | if (ts->c_cflag & CLOCAL) |
1880 | ch->port.flags &= ~ASYNC_CHECK_CD; | 1768 | clear_bit(ASYNC_CHECK_CD, &ch->port.flags); |
1881 | else | 1769 | else |
1882 | ch->port.flags |= ASYNC_CHECK_CD; | 1770 | set_bit(ASYNC_CHECK_CD, &ch->port.flags); |
1883 | mval = ch->m_dtr | ch->m_rts; | 1771 | mval = ch->m_dtr | ch->m_rts; |
1884 | } /* End CBAUD not detected */ | 1772 | } /* End CBAUD not detected */ |
1885 | iflag = termios2digi_i(ch, ts->c_iflag); | 1773 | iflag = termios2digi_i(ch, ts->c_iflag); |
@@ -1952,11 +1840,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
1952 | } | 1840 | } |
1953 | 1841 | ||
1954 | /* Caller holds lock */ | 1842 | /* Caller holds lock */ |
1955 | static void receive_data(struct channel *ch) | 1843 | static void receive_data(struct channel *ch, struct tty_struct *tty) |
1956 | { | 1844 | { |
1957 | unchar *rptr; | 1845 | unchar *rptr; |
1958 | struct ktermios *ts = NULL; | 1846 | struct ktermios *ts = NULL; |
1959 | struct tty_struct *tty; | ||
1960 | struct board_chan __iomem *bc; | 1847 | struct board_chan __iomem *bc; |
1961 | int dataToRead, wrapgap, bytesAvailable; | 1848 | int dataToRead, wrapgap, bytesAvailable; |
1962 | unsigned int tail, head; | 1849 | unsigned int tail, head; |
@@ -1969,7 +1856,6 @@ static void receive_data(struct channel *ch) | |||
1969 | globalwinon(ch); | 1856 | globalwinon(ch); |
1970 | if (ch->statusflags & RXSTOPPED) | 1857 | if (ch->statusflags & RXSTOPPED) |
1971 | return; | 1858 | return; |
1972 | tty = ch->port.tty; | ||
1973 | if (tty) | 1859 | if (tty) |
1974 | ts = tty->termios; | 1860 | ts = tty->termios; |
1975 | bc = ch->brdchan; | 1861 | bc = ch->brdchan; |
@@ -2029,7 +1915,7 @@ static void receive_data(struct channel *ch) | |||
2029 | globalwinon(ch); | 1915 | globalwinon(ch); |
2030 | writew(tail, &bc->rout); | 1916 | writew(tail, &bc->rout); |
2031 | /* Must be called with global data */ | 1917 | /* Must be called with global data */ |
2032 | tty_schedule_flip(ch->port.tty); | 1918 | tty_schedule_flip(tty); |
2033 | } | 1919 | } |
2034 | 1920 | ||
2035 | static int info_ioctl(struct tty_struct *tty, struct file *file, | 1921 | static int info_ioctl(struct tty_struct *tty, struct file *file, |
@@ -2097,7 +1983,7 @@ static int info_ioctl(struct tty_struct *tty, struct file *file, | |||
2097 | 1983 | ||
2098 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) | 1984 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) |
2099 | { | 1985 | { |
2100 | struct channel *ch = (struct channel *) tty->driver_data; | 1986 | struct channel *ch = tty->driver_data; |
2101 | struct board_chan __iomem *bc; | 1987 | struct board_chan __iomem *bc; |
2102 | unsigned int mstat, mflag = 0; | 1988 | unsigned int mstat, mflag = 0; |
2103 | unsigned long flags; | 1989 | unsigned long flags; |
@@ -2131,7 +2017,7 @@ static int pc_tiocmget(struct tty_struct *tty, struct file *file) | |||
2131 | static int pc_tiocmset(struct tty_struct *tty, struct file *file, | 2017 | static int pc_tiocmset(struct tty_struct *tty, struct file *file, |
2132 | unsigned int set, unsigned int clear) | 2018 | unsigned int set, unsigned int clear) |
2133 | { | 2019 | { |
2134 | struct channel *ch = (struct channel *) tty->driver_data; | 2020 | struct channel *ch = tty->driver_data; |
2135 | unsigned long flags; | 2021 | unsigned long flags; |
2136 | 2022 | ||
2137 | if (!ch) | 2023 | if (!ch) |
@@ -2178,7 +2064,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2178 | unsigned int mflag, mstat; | 2064 | unsigned int mflag, mstat; |
2179 | unsigned char startc, stopc; | 2065 | unsigned char startc, stopc; |
2180 | struct board_chan __iomem *bc; | 2066 | struct board_chan __iomem *bc; |
2181 | struct channel *ch = (struct channel *) tty->driver_data; | 2067 | struct channel *ch = tty->driver_data; |
2182 | void __user *argp = (void __user *)arg; | 2068 | void __user *argp = (void __user *)arg; |
2183 | 2069 | ||
2184 | if (ch) | 2070 | if (ch) |
@@ -2352,15 +2238,16 @@ static void do_softint(struct work_struct *work) | |||
2352 | struct channel *ch = container_of(work, struct channel, tqueue); | 2238 | struct channel *ch = container_of(work, struct channel, tqueue); |
2353 | /* Called in response to a modem change event */ | 2239 | /* Called in response to a modem change event */ |
2354 | if (ch && ch->magic == EPCA_MAGIC) { | 2240 | if (ch && ch->magic == EPCA_MAGIC) { |
2355 | struct tty_struct *tty = ch->port.tty; | 2241 | struct tty_struct *tty = tty_port_tty_get(&ch->port);; |
2356 | 2242 | ||
2357 | if (tty && tty->driver_data) { | 2243 | if (tty && tty->driver_data) { |
2358 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | 2244 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { |
2359 | tty_hangup(tty); | 2245 | tty_hangup(tty); |
2360 | wake_up_interruptible(&ch->port.open_wait); | 2246 | wake_up_interruptible(&ch->port.open_wait); |
2361 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 2247 | clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); |
2362 | } | 2248 | } |
2363 | } | 2249 | } |
2250 | tty_kref_put(tty); | ||
2364 | } | 2251 | } |
2365 | } | 2252 | } |
2366 | 2253 | ||
@@ -2473,7 +2360,7 @@ static void pc_unthrottle(struct tty_struct *tty) | |||
2473 | 2360 | ||
2474 | static int pc_send_break(struct tty_struct *tty, int msec) | 2361 | static int pc_send_break(struct tty_struct *tty, int msec) |
2475 | { | 2362 | { |
2476 | struct channel *ch = (struct channel *) tty->driver_data; | 2363 | struct channel *ch = tty->driver_data; |
2477 | unsigned long flags; | 2364 | unsigned long flags; |
2478 | 2365 | ||
2479 | if (msec == -1) | 2366 | if (msec == -1) |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 7f077c0097f6..45ec263ec012 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -2054,6 +2054,15 @@ static void esp_hangup(struct tty_struct *tty) | |||
2054 | wake_up_interruptible(&info->port.open_wait); | 2054 | wake_up_interruptible(&info->port.open_wait); |
2055 | } | 2055 | } |
2056 | 2056 | ||
2057 | static int esp_carrier_raised(struct tty_port *port) | ||
2058 | { | ||
2059 | struct esp_struct *info = container_of(port, struct esp_struct, port); | ||
2060 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
2061 | if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD) | ||
2062 | return 1; | ||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2057 | /* | 2066 | /* |
2058 | * ------------------------------------------------------------ | 2067 | * ------------------------------------------------------------ |
2059 | * esp_open() and friends | 2068 | * esp_open() and friends |
@@ -2066,17 +2075,19 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2066 | int retval; | 2075 | int retval; |
2067 | int do_clocal = 0; | 2076 | int do_clocal = 0; |
2068 | unsigned long flags; | 2077 | unsigned long flags; |
2078 | int cd; | ||
2079 | struct tty_port *port = &info->port; | ||
2069 | 2080 | ||
2070 | /* | 2081 | /* |
2071 | * If the device is in the middle of being closed, then block | 2082 | * If the device is in the middle of being closed, then block |
2072 | * until it's done, and then try again. | 2083 | * until it's done, and then try again. |
2073 | */ | 2084 | */ |
2074 | if (tty_hung_up_p(filp) || | 2085 | if (tty_hung_up_p(filp) || |
2075 | (info->port.flags & ASYNC_CLOSING)) { | 2086 | (port->flags & ASYNC_CLOSING)) { |
2076 | if (info->port.flags & ASYNC_CLOSING) | 2087 | if (port->flags & ASYNC_CLOSING) |
2077 | interruptible_sleep_on(&info->port.close_wait); | 2088 | interruptible_sleep_on(&port->close_wait); |
2078 | #ifdef SERIAL_DO_RESTART | 2089 | #ifdef SERIAL_DO_RESTART |
2079 | if (info->port.flags & ASYNC_HUP_NOTIFY) | 2090 | if (port->flags & ASYNC_HUP_NOTIFY) |
2080 | return -EAGAIN; | 2091 | return -EAGAIN; |
2081 | else | 2092 | else |
2082 | return -ERESTARTSYS; | 2093 | return -ERESTARTSYS; |
@@ -2091,7 +2102,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2091 | */ | 2102 | */ |
2092 | if ((filp->f_flags & O_NONBLOCK) || | 2103 | if ((filp->f_flags & O_NONBLOCK) || |
2093 | (tty->flags & (1 << TTY_IO_ERROR))) { | 2104 | (tty->flags & (1 << TTY_IO_ERROR))) { |
2094 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 2105 | port->flags |= ASYNC_NORMAL_ACTIVE; |
2095 | return 0; | 2106 | return 0; |
2096 | } | 2107 | } |
2097 | 2108 | ||
@@ -2101,20 +2112,20 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2101 | /* | 2112 | /* |
2102 | * Block waiting for the carrier detect and the line to become | 2113 | * Block waiting for the carrier detect and the line to become |
2103 | * free (i.e., not in use by the callout). While we are in | 2114 | * free (i.e., not in use by the callout). While we are in |
2104 | * this loop, info->port.count is dropped by one, so that | 2115 | * this loop, port->count is dropped by one, so that |
2105 | * rs_close() knows when to free things. We restore it upon | 2116 | * rs_close() knows when to free things. We restore it upon |
2106 | * exit, either normal or abnormal. | 2117 | * exit, either normal or abnormal. |
2107 | */ | 2118 | */ |
2108 | retval = 0; | 2119 | retval = 0; |
2109 | add_wait_queue(&info->port.open_wait, &wait); | 2120 | add_wait_queue(&port->open_wait, &wait); |
2110 | #ifdef SERIAL_DEBUG_OPEN | 2121 | #ifdef SERIAL_DEBUG_OPEN |
2111 | printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", | 2122 | printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", |
2112 | info->line, info->port.count); | 2123 | info->line, port->count); |
2113 | #endif | 2124 | #endif |
2114 | spin_lock_irqsave(&info->lock, flags); | 2125 | spin_lock_irqsave(&info->lock, flags); |
2115 | if (!tty_hung_up_p(filp)) | 2126 | if (!tty_hung_up_p(filp)) |
2116 | info->port.count--; | 2127 | port->count--; |
2117 | info->port.blocked_open++; | 2128 | port->blocked_open++; |
2118 | while (1) { | 2129 | while (1) { |
2119 | if ((tty->termios->c_cflag & CBAUD)) { | 2130 | if ((tty->termios->c_cflag & CBAUD)) { |
2120 | unsigned int scratch; | 2131 | unsigned int scratch; |
@@ -2129,9 +2140,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2129 | } | 2140 | } |
2130 | set_current_state(TASK_INTERRUPTIBLE); | 2141 | set_current_state(TASK_INTERRUPTIBLE); |
2131 | if (tty_hung_up_p(filp) || | 2142 | if (tty_hung_up_p(filp) || |
2132 | !(info->port.flags & ASYNC_INITIALIZED)) { | 2143 | !(port->flags & ASYNC_INITIALIZED)) { |
2133 | #ifdef SERIAL_DO_RESTART | 2144 | #ifdef SERIAL_DO_RESTART |
2134 | if (info->port.flags & ASYNC_HUP_NOTIFY) | 2145 | if (port->flags & ASYNC_HUP_NOTIFY) |
2135 | retval = -EAGAIN; | 2146 | retval = -EAGAIN; |
2136 | else | 2147 | else |
2137 | retval = -ERESTARTSYS; | 2148 | retval = -ERESTARTSYS; |
@@ -2141,11 +2152,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2141 | break; | 2152 | break; |
2142 | } | 2153 | } |
2143 | 2154 | ||
2144 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | 2155 | cd = tty_port_carrier_raised(port); |
2145 | if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD) | ||
2146 | do_clocal = 1; | ||
2147 | 2156 | ||
2148 | if (!(info->port.flags & ASYNC_CLOSING) && | 2157 | if (!(port->flags & ASYNC_CLOSING) && |
2149 | (do_clocal)) | 2158 | (do_clocal)) |
2150 | break; | 2159 | break; |
2151 | if (signal_pending(current)) { | 2160 | if (signal_pending(current)) { |
@@ -2154,25 +2163,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2154 | } | 2163 | } |
2155 | #ifdef SERIAL_DEBUG_OPEN | 2164 | #ifdef SERIAL_DEBUG_OPEN |
2156 | printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", | 2165 | printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", |
2157 | info->line, info->port.count); | 2166 | info->line, port->count); |
2158 | #endif | 2167 | #endif |
2159 | spin_unlock_irqrestore(&info->lock, flags); | 2168 | spin_unlock_irqrestore(&info->lock, flags); |
2160 | schedule(); | 2169 | schedule(); |
2161 | spin_lock_irqsave(&info->lock, flags); | 2170 | spin_lock_irqsave(&info->lock, flags); |
2162 | } | 2171 | } |
2163 | set_current_state(TASK_RUNNING); | 2172 | set_current_state(TASK_RUNNING); |
2164 | remove_wait_queue(&info->port.open_wait, &wait); | 2173 | remove_wait_queue(&port->open_wait, &wait); |
2165 | if (!tty_hung_up_p(filp)) | 2174 | if (!tty_hung_up_p(filp)) |
2166 | info->port.count++; | 2175 | port->count++; |
2167 | info->port.blocked_open--; | 2176 | port->blocked_open--; |
2168 | spin_unlock_irqrestore(&info->lock, flags); | 2177 | spin_unlock_irqrestore(&info->lock, flags); |
2169 | #ifdef SERIAL_DEBUG_OPEN | 2178 | #ifdef SERIAL_DEBUG_OPEN |
2170 | printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", | 2179 | printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", |
2171 | info->line, info->port.count); | 2180 | info->line, port->count); |
2172 | #endif | 2181 | #endif |
2173 | if (retval) | 2182 | if (retval) |
2174 | return retval; | 2183 | return retval; |
2175 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 2184 | port->flags |= ASYNC_NORMAL_ACTIVE; |
2176 | return 0; | 2185 | return 0; |
2177 | } | 2186 | } |
2178 | 2187 | ||
@@ -2329,6 +2338,10 @@ static const struct tty_operations esp_ops = { | |||
2329 | .tiocmset = esp_tiocmset, | 2338 | .tiocmset = esp_tiocmset, |
2330 | }; | 2339 | }; |
2331 | 2340 | ||
2341 | static const struct tty_port_operations esp_port_ops = { | ||
2342 | .esp_carrier_raised, | ||
2343 | }; | ||
2344 | |||
2332 | /* | 2345 | /* |
2333 | * The serial driver boot-time initialization code! | 2346 | * The serial driver boot-time initialization code! |
2334 | */ | 2347 | */ |
@@ -2415,6 +2428,8 @@ static int __init espserial_init(void) | |||
2415 | offset = 0; | 2428 | offset = 0; |
2416 | 2429 | ||
2417 | do { | 2430 | do { |
2431 | tty_port_init(&info->port); | ||
2432 | info->port.ops = &esp_port_ops; | ||
2418 | info->io_port = esp[i] + offset; | 2433 | info->io_port = esp[i] + offset; |
2419 | info->irq = irq[i]; | 2434 | info->irq = irq[i]; |
2420 | info->line = (i * 8) + (offset / 8); | 2435 | info->line = (i * 8) + (offset / 8); |
@@ -2437,8 +2452,6 @@ static int __init espserial_init(void) | |||
2437 | info->config.flow_off = flow_off; | 2452 | info->config.flow_off = flow_off; |
2438 | info->config.pio_threshold = pio_threshold; | 2453 | info->config.pio_threshold = pio_threshold; |
2439 | info->next_port = ports; | 2454 | info->next_port = ports; |
2440 | init_waitqueue_head(&info->port.open_wait); | ||
2441 | init_waitqueue_head(&info->port.close_wait); | ||
2442 | init_waitqueue_head(&info->delta_msr_wait); | 2455 | init_waitqueue_head(&info->delta_msr_wait); |
2443 | init_waitqueue_head(&info->break_wait); | 2456 | init_waitqueue_head(&info->break_wait); |
2444 | ports = info; | 2457 | ports = info; |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index c6090f84a2e4..9e4e569dc00d 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port) | |||
376 | 376 | ||
377 | void gs_hangup(struct tty_struct *tty) | 377 | void gs_hangup(struct tty_struct *tty) |
378 | { | 378 | { |
379 | struct gs_port *port; | 379 | struct gs_port *port; |
380 | unsigned long flags; | ||
380 | 381 | ||
381 | func_enter (); | 382 | func_enter (); |
382 | 383 | ||
@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty) | |||
386 | return; | 387 | return; |
387 | 388 | ||
388 | gs_shutdown_port (port); | 389 | gs_shutdown_port (port); |
390 | spin_lock_irqsave(&port->port.lock, flags); | ||
389 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); | 391 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE); |
390 | port->port.tty = NULL; | 392 | port->port.tty = NULL; |
391 | port->port.count = 0; | 393 | port->port.count = 0; |
394 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
392 | 395 | ||
393 | wake_up_interruptible(&port->port.open_wait); | 396 | wake_up_interruptible(&port->port.open_wait); |
394 | func_exit (); | 397 | func_exit (); |
@@ -397,7 +400,8 @@ void gs_hangup(struct tty_struct *tty) | |||
397 | 400 | ||
398 | int gs_block_til_ready(void *port_, struct file * filp) | 401 | int gs_block_til_ready(void *port_, struct file * filp) |
399 | { | 402 | { |
400 | struct gs_port *port = port_; | 403 | struct gs_port *gp = port_; |
404 | struct tty_port *port = &gp->port; | ||
401 | DECLARE_WAITQUEUE(wait, current); | 405 | DECLARE_WAITQUEUE(wait, current); |
402 | int retval; | 406 | int retval; |
403 | int do_clocal = 0; | 407 | int do_clocal = 0; |
@@ -409,16 +413,16 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
409 | 413 | ||
410 | if (!port) return 0; | 414 | if (!port) return 0; |
411 | 415 | ||
412 | tty = port->port.tty; | 416 | tty = port->tty; |
413 | 417 | ||
414 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); | 418 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); |
415 | /* | 419 | /* |
416 | * If the device is in the middle of being closed, then block | 420 | * If the device is in the middle of being closed, then block |
417 | * until it's done, and then try again. | 421 | * until it's done, and then try again. |
418 | */ | 422 | */ |
419 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | 423 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
420 | interruptible_sleep_on(&port->port.close_wait); | 424 | interruptible_sleep_on(&port->close_wait); |
421 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 425 | if (port->flags & ASYNC_HUP_NOTIFY) |
422 | return -EAGAIN; | 426 | return -EAGAIN; |
423 | else | 427 | else |
424 | return -ERESTARTSYS; | 428 | return -ERESTARTSYS; |
@@ -432,7 +436,7 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
432 | */ | 436 | */ |
433 | if ((filp->f_flags & O_NONBLOCK) || | 437 | if ((filp->f_flags & O_NONBLOCK) || |
434 | (tty->flags & (1 << TTY_IO_ERROR))) { | 438 | (tty->flags & (1 << TTY_IO_ERROR))) { |
435 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 439 | port->flags |= ASYNC_NORMAL_ACTIVE; |
436 | return 0; | 440 | return 0; |
437 | } | 441 | } |
438 | 442 | ||
@@ -444,34 +448,34 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
444 | /* | 448 | /* |
445 | * Block waiting for the carrier detect and the line to become | 449 | * Block waiting for the carrier detect and the line to become |
446 | * free (i.e., not in use by the callout). While we are in | 450 | * free (i.e., not in use by the callout). While we are in |
447 | * this loop, port->port.count is dropped by one, so that | 451 | * this loop, port->count is dropped by one, so that |
448 | * rs_close() knows when to free things. We restore it upon | 452 | * rs_close() knows when to free things. We restore it upon |
449 | * exit, either normal or abnormal. | 453 | * exit, either normal or abnormal. |
450 | */ | 454 | */ |
451 | retval = 0; | 455 | retval = 0; |
452 | 456 | ||
453 | add_wait_queue(&port->port.open_wait, &wait); | 457 | add_wait_queue(&port->open_wait, &wait); |
454 | 458 | ||
455 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); | 459 | gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); |
456 | spin_lock_irqsave(&port->driver_lock, flags); | 460 | spin_lock_irqsave(&port->lock, flags); |
457 | if (!tty_hung_up_p(filp)) { | 461 | if (!tty_hung_up_p(filp)) { |
458 | port->port.count--; | 462 | port->count--; |
459 | } | 463 | } |
460 | spin_unlock_irqrestore(&port->driver_lock, flags); | 464 | port->blocked_open++; |
461 | port->port.blocked_open++; | 465 | spin_unlock_irqrestore(&port->lock, flags); |
462 | while (1) { | 466 | while (1) { |
463 | CD = port->rd->get_CD (port); | 467 | CD = tty_port_carrier_raised(port); |
464 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); | 468 | gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); |
465 | set_current_state (TASK_INTERRUPTIBLE); | 469 | set_current_state (TASK_INTERRUPTIBLE); |
466 | if (tty_hung_up_p(filp) || | 470 | if (tty_hung_up_p(filp) || |
467 | !(port->port.flags & ASYNC_INITIALIZED)) { | 471 | !(port->flags & ASYNC_INITIALIZED)) { |
468 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 472 | if (port->flags & ASYNC_HUP_NOTIFY) |
469 | retval = -EAGAIN; | 473 | retval = -EAGAIN; |
470 | else | 474 | else |
471 | retval = -ERESTARTSYS; | 475 | retval = -ERESTARTSYS; |
472 | break; | 476 | break; |
473 | } | 477 | } |
474 | if (!(port->port.flags & ASYNC_CLOSING) && | 478 | if (!(port->flags & ASYNC_CLOSING) && |
475 | (do_clocal || CD)) | 479 | (do_clocal || CD)) |
476 | break; | 480 | break; |
477 | gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", | 481 | gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", |
@@ -483,19 +487,20 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
483 | schedule(); | 487 | schedule(); |
484 | } | 488 | } |
485 | gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", | 489 | gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", |
486 | port->port.blocked_open); | 490 | port->blocked_open); |
487 | set_current_state (TASK_RUNNING); | 491 | set_current_state (TASK_RUNNING); |
488 | remove_wait_queue(&port->port.open_wait, &wait); | 492 | remove_wait_queue(&port->open_wait, &wait); |
493 | |||
494 | spin_lock_irqsave(&port->lock, flags); | ||
489 | if (!tty_hung_up_p(filp)) { | 495 | if (!tty_hung_up_p(filp)) { |
490 | port->port.count++; | 496 | port->count++; |
491 | } | 497 | } |
492 | port->port.blocked_open--; | 498 | port->blocked_open--; |
493 | if (retval) | 499 | if (retval == 0) |
494 | return retval; | 500 | port->flags |= ASYNC_NORMAL_ACTIVE; |
495 | 501 | spin_unlock_irqrestore(&port->lock, flags); | |
496 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
497 | func_exit (); | 502 | func_exit (); |
498 | return 0; | 503 | return retval; |
499 | } | 504 | } |
500 | 505 | ||
501 | 506 | ||
@@ -506,7 +511,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
506 | 511 | ||
507 | func_enter (); | 512 | func_enter (); |
508 | 513 | ||
509 | port = (struct gs_port *) tty->driver_data; | 514 | port = tty->driver_data; |
510 | 515 | ||
511 | if (!port) return; | 516 | if (!port) return; |
512 | 517 | ||
@@ -516,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
516 | port->port.tty = tty; | 521 | port->port.tty = tty; |
517 | } | 522 | } |
518 | 523 | ||
519 | spin_lock_irqsave(&port->driver_lock, flags); | 524 | spin_lock_irqsave(&port->port.lock, flags); |
520 | 525 | ||
521 | if (tty_hung_up_p(filp)) { | 526 | if (tty_hung_up_p(filp)) { |
522 | spin_unlock_irqrestore(&port->driver_lock, flags); | 527 | spin_unlock_irqrestore(&port->port.lock, flags); |
523 | if (port->rd->hungup) | 528 | if (port->rd->hungup) |
524 | port->rd->hungup (port); | 529 | port->rd->hungup (port); |
525 | func_exit (); | 530 | func_exit (); |
@@ -538,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
538 | 543 | ||
539 | if (port->port.count) { | 544 | if (port->port.count) { |
540 | gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); | 545 | gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count); |
541 | spin_unlock_irqrestore(&port->driver_lock, flags); | 546 | spin_unlock_irqrestore(&port->port.lock, flags); |
542 | func_exit (); | 547 | func_exit (); |
543 | return; | 548 | return; |
544 | } | 549 | } |
@@ -559,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
559 | * line status register. | 564 | * line status register. |
560 | */ | 565 | */ |
561 | 566 | ||
567 | spin_lock_irqsave(&port->driver_lock, flags); | ||
562 | port->rd->disable_rx_interrupts (port); | 568 | port->rd->disable_rx_interrupts (port); |
563 | spin_unlock_irqrestore(&port->driver_lock, flags); | 569 | spin_unlock_irqrestore(&port->driver_lock, flags); |
570 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
564 | 571 | ||
565 | /* close has no way of returning "EINTR", so discard return value */ | 572 | /* close has no way of returning "EINTR", so discard return value */ |
566 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 573 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
@@ -573,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
573 | tty_ldisc_flush(tty); | 580 | tty_ldisc_flush(tty); |
574 | tty->closing = 0; | 581 | tty->closing = 0; |
575 | 582 | ||
583 | spin_lock_irqsave(&port->driver_lock, flags); | ||
576 | port->event = 0; | 584 | port->event = 0; |
577 | port->rd->close (port); | 585 | port->rd->close (port); |
578 | port->rd->shutdown_port (port); | 586 | port->rd->shutdown_port (port); |
587 | spin_unlock_irqrestore(&port->driver_lock, flags); | ||
588 | |||
589 | spin_lock_irqsave(&port->port.lock, flags); | ||
579 | port->port.tty = NULL; | 590 | port->port.tty = NULL; |
580 | 591 | ||
581 | if (port->port.blocked_open) { | 592 | if (port->port.blocked_open) { |
582 | if (port->close_delay) { | 593 | if (port->close_delay) { |
583 | spin_unlock_irqrestore(&port->driver_lock, flags); | 594 | spin_unlock_irqrestore(&port->port.lock, flags); |
584 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); | 595 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); |
585 | spin_lock_irqsave(&port->driver_lock, flags); | 596 | spin_lock_irqsave(&port->port.lock, flags); |
586 | } | 597 | } |
587 | wake_up_interruptible(&port->port.open_wait); | 598 | wake_up_interruptible(&port->port.open_wait); |
588 | } | 599 | } |
589 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); | 600 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED); |
601 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
590 | wake_up_interruptible(&port->port.close_wait); | 602 | wake_up_interruptible(&port->port.close_wait); |
591 | 603 | ||
592 | func_exit (); | 604 | func_exit (); |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 0587b66d6fc7..5a8a4c28c867 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -529,7 +529,7 @@ static void hvc_set_winsz(struct work_struct *work) | |||
529 | tty = tty_kref_get(hp->tty); | 529 | tty = tty_kref_get(hp->tty); |
530 | spin_unlock_irqrestore(&hp->lock, hvc_flags); | 530 | spin_unlock_irqrestore(&hp->lock, hvc_flags); |
531 | 531 | ||
532 | tty_do_resize(tty, tty, &ws); | 532 | tty_do_resize(tty, &ws); |
533 | tty_kref_put(tty); | 533 | tty_kref_put(tty); |
534 | } | 534 | } |
535 | 535 | ||
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index af055287271a..406f8742a260 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c | |||
@@ -997,14 +997,14 @@ out: | |||
997 | 997 | ||
998 | static int hvsi_write_room(struct tty_struct *tty) | 998 | static int hvsi_write_room(struct tty_struct *tty) |
999 | { | 999 | { |
1000 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1000 | struct hvsi_struct *hp = tty->driver_data; |
1001 | 1001 | ||
1002 | return N_OUTBUF - hp->n_outbuf; | 1002 | return N_OUTBUF - hp->n_outbuf; |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static int hvsi_chars_in_buffer(struct tty_struct *tty) | 1005 | static int hvsi_chars_in_buffer(struct tty_struct *tty) |
1006 | { | 1006 | { |
1007 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1007 | struct hvsi_struct *hp = tty->driver_data; |
1008 | 1008 | ||
1009 | return hp->n_outbuf; | 1009 | return hp->n_outbuf; |
1010 | } | 1010 | } |
@@ -1070,7 +1070,7 @@ out: | |||
1070 | */ | 1070 | */ |
1071 | static void hvsi_throttle(struct tty_struct *tty) | 1071 | static void hvsi_throttle(struct tty_struct *tty) |
1072 | { | 1072 | { |
1073 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1073 | struct hvsi_struct *hp = tty->driver_data; |
1074 | 1074 | ||
1075 | pr_debug("%s\n", __func__); | 1075 | pr_debug("%s\n", __func__); |
1076 | 1076 | ||
@@ -1079,7 +1079,7 @@ static void hvsi_throttle(struct tty_struct *tty) | |||
1079 | 1079 | ||
1080 | static void hvsi_unthrottle(struct tty_struct *tty) | 1080 | static void hvsi_unthrottle(struct tty_struct *tty) |
1081 | { | 1081 | { |
1082 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1082 | struct hvsi_struct *hp = tty->driver_data; |
1083 | unsigned long flags; | 1083 | unsigned long flags; |
1084 | int shouldflip = 0; | 1084 | int shouldflip = 0; |
1085 | 1085 | ||
@@ -1100,7 +1100,7 @@ static void hvsi_unthrottle(struct tty_struct *tty) | |||
1100 | 1100 | ||
1101 | static int hvsi_tiocmget(struct tty_struct *tty, struct file *file) | 1101 | static int hvsi_tiocmget(struct tty_struct *tty, struct file *file) |
1102 | { | 1102 | { |
1103 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1103 | struct hvsi_struct *hp = tty->driver_data; |
1104 | 1104 | ||
1105 | hvsi_get_mctrl(hp); | 1105 | hvsi_get_mctrl(hp); |
1106 | return hp->mctrl; | 1106 | return hp->mctrl; |
@@ -1109,7 +1109,7 @@ static int hvsi_tiocmget(struct tty_struct *tty, struct file *file) | |||
1109 | static int hvsi_tiocmset(struct tty_struct *tty, struct file *file, | 1109 | static int hvsi_tiocmset(struct tty_struct *tty, struct file *file, |
1110 | unsigned int set, unsigned int clear) | 1110 | unsigned int set, unsigned int clear) |
1111 | { | 1111 | { |
1112 | struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data; | 1112 | struct hvsi_struct *hp = tty->driver_data; |
1113 | unsigned long flags; | 1113 | unsigned long flags; |
1114 | uint16_t new_mctrl; | 1114 | uint16_t new_mctrl; |
1115 | 1115 | ||
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index b60d425ce8d1..fc8cf7ac7f2b 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -485,7 +485,21 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { | |||
485 | DMI_MATCH(DMI_PRODUCT_NAME, "MP061"), | 485 | DMI_MATCH(DMI_PRODUCT_NAME, "MP061"), |
486 | }, | 486 | }, |
487 | }, | 487 | }, |
488 | { } | 488 | { |
489 | .ident = "Dell Precision", | ||
490 | .matches = { | ||
491 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
492 | DMI_MATCH(DMI_PRODUCT_NAME, "Precision"), | ||
493 | }, | ||
494 | }, | ||
495 | { | ||
496 | .ident = "Dell Vostro", | ||
497 | .matches = { | ||
498 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
499 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"), | ||
500 | }, | ||
501 | }, | ||
502 | { } | ||
489 | }; | 503 | }; |
490 | 504 | ||
491 | /* | 505 | /* |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 04e4549299ba..24aa6e88e223 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -328,11 +328,13 @@ static inline void drop_rts(struct isi_port *port) | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /* card->lock MUST NOT be held */ | 330 | /* card->lock MUST NOT be held */ |
331 | static inline void raise_dtr_rts(struct isi_port *port) | 331 | |
332 | static void isicom_raise_dtr_rts(struct tty_port *port) | ||
332 | { | 333 | { |
333 | struct isi_board *card = port->card; | 334 | struct isi_port *ip = container_of(port, struct isi_port, port); |
335 | struct isi_board *card = ip->card; | ||
334 | unsigned long base = card->base; | 336 | unsigned long base = card->base; |
335 | u16 channel = port->channel; | 337 | u16 channel = ip->channel; |
336 | 338 | ||
337 | if (!lock_card(card)) | 339 | if (!lock_card(card)) |
338 | return; | 340 | return; |
@@ -340,7 +342,7 @@ static inline void raise_dtr_rts(struct isi_port *port) | |||
340 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 342 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
341 | outw(0x0f04, base); | 343 | outw(0x0f04, base); |
342 | InterruptTheCard(base); | 344 | InterruptTheCard(base); |
343 | port->status |= (ISI_DTR | ISI_RTS); | 345 | ip->status |= (ISI_DTR | ISI_RTS); |
344 | unlock_card(card); | 346 | unlock_card(card); |
345 | } | 347 | } |
346 | 348 | ||
@@ -830,80 +832,10 @@ static int isicom_setup_port(struct tty_struct *tty) | |||
830 | return 0; | 832 | return 0; |
831 | } | 833 | } |
832 | 834 | ||
833 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 835 | static int isicom_carrier_raised(struct tty_port *port) |
834 | struct isi_port *port) | ||
835 | { | 836 | { |
836 | struct isi_board *card = port->card; | 837 | struct isi_port *ip = container_of(port, struct isi_port, port); |
837 | int do_clocal = 0, retval; | 838 | return (ip->status & ISI_DCD)?1 : 0; |
838 | unsigned long flags; | ||
839 | DECLARE_WAITQUEUE(wait, current); | ||
840 | |||
841 | /* block if port is in the process of being closed */ | ||
842 | |||
843 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | ||
844 | pr_dbg("block_til_ready: close in progress.\n"); | ||
845 | interruptible_sleep_on(&port->port.close_wait); | ||
846 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
847 | return -EAGAIN; | ||
848 | else | ||
849 | return -ERESTARTSYS; | ||
850 | } | ||
851 | |||
852 | /* if non-blocking mode is set ... */ | ||
853 | |||
854 | if ((filp->f_flags & O_NONBLOCK) || | ||
855 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
856 | pr_dbg("block_til_ready: non-block mode.\n"); | ||
857 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | if (C_CLOCAL(tty)) | ||
862 | do_clocal = 1; | ||
863 | |||
864 | /* block waiting for DCD to be asserted, and while | ||
865 | callout dev is busy */ | ||
866 | retval = 0; | ||
867 | add_wait_queue(&port->port.open_wait, &wait); | ||
868 | |||
869 | spin_lock_irqsave(&card->card_lock, flags); | ||
870 | if (!tty_hung_up_p(filp)) | ||
871 | port->port.count--; | ||
872 | port->port.blocked_open++; | ||
873 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
874 | |||
875 | while (1) { | ||
876 | raise_dtr_rts(port); | ||
877 | |||
878 | set_current_state(TASK_INTERRUPTIBLE); | ||
879 | if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { | ||
880 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
881 | retval = -EAGAIN; | ||
882 | else | ||
883 | retval = -ERESTARTSYS; | ||
884 | break; | ||
885 | } | ||
886 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
887 | (do_clocal || (port->status & ISI_DCD))) { | ||
888 | break; | ||
889 | } | ||
890 | if (signal_pending(current)) { | ||
891 | retval = -ERESTARTSYS; | ||
892 | break; | ||
893 | } | ||
894 | schedule(); | ||
895 | } | ||
896 | set_current_state(TASK_RUNNING); | ||
897 | remove_wait_queue(&port->port.open_wait, &wait); | ||
898 | spin_lock_irqsave(&card->card_lock, flags); | ||
899 | if (!tty_hung_up_p(filp)) | ||
900 | port->port.count++; | ||
901 | port->port.blocked_open--; | ||
902 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
903 | if (retval) | ||
904 | return retval; | ||
905 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
906 | return 0; | ||
907 | } | 839 | } |
908 | 840 | ||
909 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 841 | static int isicom_open(struct tty_struct *tty, struct file *filp) |
@@ -932,12 +864,13 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) | |||
932 | 864 | ||
933 | isicom_setup_board(card); | 865 | isicom_setup_board(card); |
934 | 866 | ||
867 | /* FIXME: locking on port.count etc */ | ||
935 | port->port.count++; | 868 | port->port.count++; |
936 | tty->driver_data = port; | 869 | tty->driver_data = port; |
937 | tty_port_tty_set(&port->port, tty); | 870 | tty_port_tty_set(&port->port, tty); |
938 | error = isicom_setup_port(tty); | 871 | error = isicom_setup_port(tty); |
939 | if (error == 0) | 872 | if (error == 0) |
940 | error = block_til_ready(tty, filp, port); | 873 | error = tty_port_block_til_ready(&port->port, tty, filp); |
941 | return error; | 874 | return error; |
942 | } | 875 | } |
943 | 876 | ||
@@ -1012,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
1012 | 945 | ||
1013 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 946 | static void isicom_close(struct tty_struct *tty, struct file *filp) |
1014 | { | 947 | { |
1015 | struct isi_port *port = tty->driver_data; | 948 | struct isi_port *ip = tty->driver_data; |
949 | struct tty_port *port = &ip->port; | ||
1016 | struct isi_board *card; | 950 | struct isi_board *card; |
1017 | unsigned long flags; | 951 | unsigned long flags; |
1018 | 952 | ||
1019 | if (!port) | 953 | BUG_ON(!ip); |
1020 | return; | ||
1021 | card = port->card; | ||
1022 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) | ||
1023 | return; | ||
1024 | |||
1025 | pr_dbg("Close start!!!.\n"); | ||
1026 | |||
1027 | spin_lock_irqsave(&card->card_lock, flags); | ||
1028 | if (tty_hung_up_p(filp)) { | ||
1029 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1030 | return; | ||
1031 | } | ||
1032 | |||
1033 | if (tty->count == 1 && port->port.count != 1) { | ||
1034 | printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " | ||
1035 | "count tty->count = 1 port count = %d.\n", | ||
1036 | card->base, port->port.count); | ||
1037 | port->port.count = 1; | ||
1038 | } | ||
1039 | if (--port->port.count < 0) { | ||
1040 | printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " | ||
1041 | "count for channel%d = %d", card->base, port->channel, | ||
1042 | port->port.count); | ||
1043 | port->port.count = 0; | ||
1044 | } | ||
1045 | 954 | ||
1046 | if (port->port.count) { | 955 | card = ip->card; |
1047 | spin_unlock_irqrestore(&card->card_lock, flags); | 956 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) |
1048 | return; | 957 | return; |
1049 | } | ||
1050 | port->port.flags |= ASYNC_CLOSING; | ||
1051 | tty->closing = 1; | ||
1052 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1053 | 958 | ||
1054 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1055 | tty_wait_until_sent(tty, port->port.closing_wait); | ||
1056 | /* indicate to the card that no more data can be received | 959 | /* indicate to the card that no more data can be received |
1057 | on this port */ | 960 | on this port */ |
1058 | spin_lock_irqsave(&card->card_lock, flags); | 961 | spin_lock_irqsave(&card->card_lock, flags); |
1059 | if (port->port.flags & ASYNC_INITIALIZED) { | 962 | if (port->flags & ASYNC_INITIALIZED) { |
1060 | card->port_status &= ~(1 << port->channel); | 963 | card->port_status &= ~(1 << ip->channel); |
1061 | outw(card->port_status, card->base + 0x02); | 964 | outw(card->port_status, card->base + 0x02); |
1062 | } | 965 | } |
1063 | isicom_shutdown_port(port); | 966 | isicom_shutdown_port(ip); |
1064 | spin_unlock_irqrestore(&card->card_lock, flags); | 967 | spin_unlock_irqrestore(&card->card_lock, flags); |
1065 | 968 | ||
1066 | isicom_flush_buffer(tty); | 969 | isicom_flush_buffer(tty); |
1067 | tty_ldisc_flush(tty); | 970 | |
1068 | 971 | tty_port_close_end(port, tty); | |
1069 | spin_lock_irqsave(&card->card_lock, flags); | ||
1070 | tty->closing = 0; | ||
1071 | |||
1072 | if (port->port.blocked_open) { | ||
1073 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1074 | if (port->port.close_delay) { | ||
1075 | pr_dbg("scheduling until time out.\n"); | ||
1076 | msleep_interruptible( | ||
1077 | jiffies_to_msecs(port->port.close_delay)); | ||
1078 | } | ||
1079 | spin_lock_irqsave(&card->card_lock, flags); | ||
1080 | wake_up_interruptible(&port->port.open_wait); | ||
1081 | } | ||
1082 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
1083 | wake_up_interruptible(&port->port.close_wait); | ||
1084 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1085 | } | 972 | } |
1086 | 973 | ||
1087 | /* write et all */ | 974 | /* write et all */ |
@@ -1420,10 +1307,7 @@ static void isicom_hangup(struct tty_struct *tty) | |||
1420 | isicom_shutdown_port(port); | 1307 | isicom_shutdown_port(port); |
1421 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1308 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1422 | 1309 | ||
1423 | port->port.count = 0; | 1310 | tty_port_hangup(&port->port); |
1424 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1425 | tty_port_tty_set(&port->port, NULL); | ||
1426 | wake_up_interruptible(&port->port.open_wait); | ||
1427 | } | 1311 | } |
1428 | 1312 | ||
1429 | 1313 | ||
@@ -1452,6 +1336,11 @@ static const struct tty_operations isicom_ops = { | |||
1452 | .break_ctl = isicom_send_break, | 1336 | .break_ctl = isicom_send_break, |
1453 | }; | 1337 | }; |
1454 | 1338 | ||
1339 | static const struct tty_port_operations isicom_port_ops = { | ||
1340 | .carrier_raised = isicom_carrier_raised, | ||
1341 | .raise_dtr_rts = isicom_raise_dtr_rts, | ||
1342 | }; | ||
1343 | |||
1455 | static int __devinit reset_card(struct pci_dev *pdev, | 1344 | static int __devinit reset_card(struct pci_dev *pdev, |
1456 | const unsigned int card, unsigned int *signature) | 1345 | const unsigned int card, unsigned int *signature) |
1457 | { | 1346 | { |
@@ -1794,6 +1683,7 @@ static int __init isicom_init(void) | |||
1794 | spin_lock_init(&isi_card[idx].card_lock); | 1683 | spin_lock_init(&isi_card[idx].card_lock); |
1795 | for (channel = 0; channel < 16; channel++, port++) { | 1684 | for (channel = 0; channel < 16; channel++, port++) { |
1796 | tty_port_init(&port->port); | 1685 | tty_port_init(&port->port); |
1686 | port->port.ops = &isicom_port_ops; | ||
1797 | port->magic = ISICOM_MAGIC; | 1687 | port->magic = ISICOM_MAGIC; |
1798 | port->card = &isi_card[idx]; | 1688 | port->card = &isi_card[idx]; |
1799 | port->channel = channel; | 1689 | port->channel = channel; |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4b10770fa937..5c3dc6b8411c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -151,7 +151,7 @@ static char *stli_drvversion = "5.6.0"; | |||
151 | static char *stli_serialname = "ttyE"; | 151 | static char *stli_serialname = "ttyE"; |
152 | 152 | ||
153 | static struct tty_driver *stli_serial; | 153 | static struct tty_driver *stli_serial; |
154 | 154 | static const struct tty_port_operations stli_port_ops; | |
155 | 155 | ||
156 | #define STLI_TXBUFSIZE 4096 | 156 | #define STLI_TXBUFSIZE 4096 |
157 | 157 | ||
@@ -626,8 +626,6 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | |||
626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); |
627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
629 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, | ||
630 | struct stliport *portp, struct file *filp); | ||
631 | static int stli_setport(struct tty_struct *tty); | 629 | static int stli_setport(struct tty_struct *tty); |
632 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 630 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
633 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 631 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
@@ -769,7 +767,7 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) | |||
769 | break; | 767 | break; |
770 | } | 768 | } |
771 | if (i == ARRAY_SIZE(stli_brdstr)) { | 769 | if (i == ARRAY_SIZE(stli_brdstr)) { |
772 | printk("STALLION: unknown board name, %s?\n", argp[0]); | 770 | printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]); |
773 | return 0; | 771 | return 0; |
774 | } | 772 | } |
775 | 773 | ||
@@ -787,6 +785,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
787 | { | 785 | { |
788 | struct stlibrd *brdp; | 786 | struct stlibrd *brdp; |
789 | struct stliport *portp; | 787 | struct stliport *portp; |
788 | struct tty_port *port; | ||
790 | unsigned int minordev, brdnr, portnr; | 789 | unsigned int minordev, brdnr, portnr; |
791 | int rc; | 790 | int rc; |
792 | 791 | ||
@@ -808,30 +807,19 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
808 | return -ENODEV; | 807 | return -ENODEV; |
809 | if (portp->devnr < 1) | 808 | if (portp->devnr < 1) |
810 | return -ENODEV; | 809 | return -ENODEV; |
811 | 810 | port = &portp->port; | |
812 | |||
813 | /* | ||
814 | * Check if this port is in the middle of closing. If so then wait | ||
815 | * until it is closed then return error status based on flag settings. | ||
816 | * The sleep here does not need interrupt protection since the wakeup | ||
817 | * for it is done with the same context. | ||
818 | */ | ||
819 | if (portp->port.flags & ASYNC_CLOSING) { | ||
820 | interruptible_sleep_on(&portp->port.close_wait); | ||
821 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
822 | return -EAGAIN; | ||
823 | return -ERESTARTSYS; | ||
824 | } | ||
825 | 811 | ||
826 | /* | 812 | /* |
827 | * On the first open of the device setup the port hardware, and | 813 | * On the first open of the device setup the port hardware, and |
828 | * initialize the per port data structure. Since initializing the port | 814 | * initialize the per port data structure. Since initializing the port |
829 | * requires several commands to the board we will need to wait for any | 815 | * requires several commands to the board we will need to wait for any |
830 | * other open that is already initializing the port. | 816 | * other open that is already initializing the port. |
817 | * | ||
818 | * Review - locking | ||
831 | */ | 819 | */ |
832 | tty_port_tty_set(&portp->port, tty); | 820 | tty_port_tty_set(port, tty); |
833 | tty->driver_data = portp; | 821 | tty->driver_data = portp; |
834 | portp->port.count++; | 822 | port->count++; |
835 | 823 | ||
836 | wait_event_interruptible(portp->raw_wait, | 824 | wait_event_interruptible(portp->raw_wait, |
837 | !test_bit(ST_INITIALIZING, &portp->state)); | 825 | !test_bit(ST_INITIALIZING, &portp->state)); |
@@ -841,7 +829,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
841 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | 829 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { |
842 | set_bit(ST_INITIALIZING, &portp->state); | 830 | set_bit(ST_INITIALIZING, &portp->state); |
843 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { | 831 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { |
844 | portp->port.flags |= ASYNC_INITIALIZED; | 832 | /* Locking */ |
833 | port->flags |= ASYNC_INITIALIZED; | ||
845 | clear_bit(TTY_IO_ERROR, &tty->flags); | 834 | clear_bit(TTY_IO_ERROR, &tty->flags); |
846 | } | 835 | } |
847 | clear_bit(ST_INITIALIZING, &portp->state); | 836 | clear_bit(ST_INITIALIZING, &portp->state); |
@@ -849,31 +838,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
849 | if (rc < 0) | 838 | if (rc < 0) |
850 | return rc; | 839 | return rc; |
851 | } | 840 | } |
852 | 841 | return tty_port_block_til_ready(&portp->port, tty, filp); | |
853 | /* | ||
854 | * Check if this port is in the middle of closing. If so then wait | ||
855 | * until it is closed then return error status, based on flag settings. | ||
856 | * The sleep here does not need interrupt protection since the wakeup | ||
857 | * for it is done with the same context. | ||
858 | */ | ||
859 | if (portp->port.flags & ASYNC_CLOSING) { | ||
860 | interruptible_sleep_on(&portp->port.close_wait); | ||
861 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
862 | return -EAGAIN; | ||
863 | return -ERESTARTSYS; | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Based on type of open being done check if it can overlap with any | ||
868 | * previous opens still in effect. If we are a normal serial device | ||
869 | * then also we might have to wait for carrier. | ||
870 | */ | ||
871 | if (!(filp->f_flags & O_NONBLOCK)) { | ||
872 | if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0) | ||
873 | return rc; | ||
874 | } | ||
875 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
876 | return 0; | ||
877 | } | 842 | } |
878 | 843 | ||
879 | /*****************************************************************************/ | 844 | /*****************************************************************************/ |
@@ -882,25 +847,16 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
882 | { | 847 | { |
883 | struct stlibrd *brdp; | 848 | struct stlibrd *brdp; |
884 | struct stliport *portp; | 849 | struct stliport *portp; |
850 | struct tty_port *port; | ||
885 | unsigned long flags; | 851 | unsigned long flags; |
886 | 852 | ||
887 | portp = tty->driver_data; | 853 | portp = tty->driver_data; |
888 | if (portp == NULL) | 854 | if (portp == NULL) |
889 | return; | 855 | return; |
856 | port = &portp->port; | ||
890 | 857 | ||
891 | spin_lock_irqsave(&stli_lock, flags); | 858 | if (tty_port_close_start(port, tty, filp) == 0) |
892 | if (tty_hung_up_p(filp)) { | ||
893 | spin_unlock_irqrestore(&stli_lock, flags); | ||
894 | return; | ||
895 | } | ||
896 | if ((tty->count == 1) && (portp->port.count != 1)) | ||
897 | portp->port.count = 1; | ||
898 | if (portp->port.count-- > 1) { | ||
899 | spin_unlock_irqrestore(&stli_lock, flags); | ||
900 | return; | 859 | return; |
901 | } | ||
902 | |||
903 | portp->port.flags |= ASYNC_CLOSING; | ||
904 | 860 | ||
905 | /* | 861 | /* |
906 | * May want to wait for data to drain before closing. The BUSY flag | 862 | * May want to wait for data to drain before closing. The BUSY flag |
@@ -908,15 +864,19 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
908 | * updated by messages from the slave - indicating when all chars | 864 | * updated by messages from the slave - indicating when all chars |
909 | * really have drained. | 865 | * really have drained. |
910 | */ | 866 | */ |
867 | spin_lock_irqsave(&stli_lock, flags); | ||
911 | if (tty == stli_txcooktty) | 868 | if (tty == stli_txcooktty) |
912 | stli_flushchars(tty); | 869 | stli_flushchars(tty); |
913 | tty->closing = 1; | ||
914 | spin_unlock_irqrestore(&stli_lock, flags); | 870 | spin_unlock_irqrestore(&stli_lock, flags); |
915 | 871 | ||
872 | /* We end up doing this twice for the moment. This needs looking at | ||
873 | eventually. Note we still use portp->closing_wait as a result */ | ||
916 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 874 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
917 | tty_wait_until_sent(tty, portp->closing_wait); | 875 | tty_wait_until_sent(tty, portp->closing_wait); |
918 | 876 | ||
919 | portp->port.flags &= ~ASYNC_INITIALIZED; | 877 | /* FIXME: port locking here needs attending to */ |
878 | port->flags &= ~ASYNC_INITIALIZED; | ||
879 | |||
920 | brdp = stli_brds[portp->brdnr]; | 880 | brdp = stli_brds[portp->brdnr]; |
921 | stli_rawclose(brdp, portp, 0, 0); | 881 | stli_rawclose(brdp, portp, 0, 0); |
922 | if (tty->termios->c_cflag & HUPCL) { | 882 | if (tty->termios->c_cflag & HUPCL) { |
@@ -934,17 +894,8 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
934 | set_bit(ST_DOFLUSHRX, &portp->state); | 894 | set_bit(ST_DOFLUSHRX, &portp->state); |
935 | stli_flushbuffer(tty); | 895 | stli_flushbuffer(tty); |
936 | 896 | ||
937 | tty->closing = 0; | 897 | tty_port_close_end(port, tty); |
938 | tty_port_tty_set(&portp->port, NULL); | 898 | tty_port_tty_set(port, NULL); |
939 | |||
940 | if (portp->openwaitcnt) { | ||
941 | if (portp->close_delay) | ||
942 | msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | ||
943 | wake_up_interruptible(&portp->port.open_wait); | ||
944 | } | ||
945 | |||
946 | portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
947 | wake_up_interruptible(&portp->port.close_wait); | ||
948 | } | 899 | } |
949 | 900 | ||
950 | /*****************************************************************************/ | 901 | /*****************************************************************************/ |
@@ -1183,62 +1134,23 @@ static int stli_setport(struct tty_struct *tty) | |||
1183 | 1134 | ||
1184 | /*****************************************************************************/ | 1135 | /*****************************************************************************/ |
1185 | 1136 | ||
1186 | /* | 1137 | static int stli_carrier_raised(struct tty_port *port) |
1187 | * Possibly need to wait for carrier (DCD signal) to come high. Say | ||
1188 | * maybe because if we are clocal then we don't need to wait... | ||
1189 | */ | ||
1190 | |||
1191 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, | ||
1192 | struct stliport *portp, struct file *filp) | ||
1193 | { | 1138 | { |
1194 | unsigned long flags; | 1139 | struct stliport *portp = container_of(port, struct stliport, port); |
1195 | int rc, doclocal; | 1140 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
1196 | 1141 | } | |
1197 | rc = 0; | ||
1198 | doclocal = 0; | ||
1199 | |||
1200 | if (tty->termios->c_cflag & CLOCAL) | ||
1201 | doclocal++; | ||
1202 | |||
1203 | spin_lock_irqsave(&stli_lock, flags); | ||
1204 | portp->openwaitcnt++; | ||
1205 | if (! tty_hung_up_p(filp)) | ||
1206 | portp->port.count--; | ||
1207 | spin_unlock_irqrestore(&stli_lock, flags); | ||
1208 | |||
1209 | for (;;) { | ||
1210 | stli_mkasysigs(&portp->asig, 1, 1); | ||
1211 | if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, | ||
1212 | &portp->asig, sizeof(asysigs_t), 0)) < 0) | ||
1213 | break; | ||
1214 | if (tty_hung_up_p(filp) || | ||
1215 | ((portp->port.flags & ASYNC_INITIALIZED) == 0)) { | ||
1216 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
1217 | rc = -EBUSY; | ||
1218 | else | ||
1219 | rc = -ERESTARTSYS; | ||
1220 | break; | ||
1221 | } | ||
1222 | if (((portp->port.flags & ASYNC_CLOSING) == 0) && | ||
1223 | (doclocal || (portp->sigs & TIOCM_CD))) { | ||
1224 | break; | ||
1225 | } | ||
1226 | if (signal_pending(current)) { | ||
1227 | rc = -ERESTARTSYS; | ||
1228 | break; | ||
1229 | } | ||
1230 | interruptible_sleep_on(&portp->port.open_wait); | ||
1231 | } | ||
1232 | |||
1233 | spin_lock_irqsave(&stli_lock, flags); | ||
1234 | if (! tty_hung_up_p(filp)) | ||
1235 | portp->port.count++; | ||
1236 | portp->openwaitcnt--; | ||
1237 | spin_unlock_irqrestore(&stli_lock, flags); | ||
1238 | 1142 | ||
1239 | return rc; | 1143 | static void stli_raise_dtr_rts(struct tty_port *port) |
1144 | { | ||
1145 | struct stliport *portp = container_of(port, struct stliport, port); | ||
1146 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
1147 | stli_mkasysigs(&portp->asig, 1, 1); | ||
1148 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
1149 | sizeof(asysigs_t), 0) < 0) | ||
1150 | printk(KERN_WARNING "istallion: dtr raise failed.\n"); | ||
1240 | } | 1151 | } |
1241 | 1152 | ||
1153 | |||
1242 | /*****************************************************************************/ | 1154 | /*****************************************************************************/ |
1243 | 1155 | ||
1244 | /* | 1156 | /* |
@@ -1550,7 +1462,7 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s | |||
1550 | sio.irq = 0; | 1462 | sio.irq = 0; |
1551 | sio.flags = portp->port.flags; | 1463 | sio.flags = portp->port.flags; |
1552 | sio.baud_base = portp->baud_base; | 1464 | sio.baud_base = portp->baud_base; |
1553 | sio.close_delay = portp->close_delay; | 1465 | sio.close_delay = portp->port.close_delay; |
1554 | sio.closing_wait = portp->closing_wait; | 1466 | sio.closing_wait = portp->closing_wait; |
1555 | sio.custom_divisor = portp->custom_divisor; | 1467 | sio.custom_divisor = portp->custom_divisor; |
1556 | sio.xmit_fifo_size = 0; | 1468 | sio.xmit_fifo_size = 0; |
@@ -1582,7 +1494,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s | |||
1582 | return -EFAULT; | 1494 | return -EFAULT; |
1583 | if (!capable(CAP_SYS_ADMIN)) { | 1495 | if (!capable(CAP_SYS_ADMIN)) { |
1584 | if ((sio.baud_base != portp->baud_base) || | 1496 | if ((sio.baud_base != portp->baud_base) || |
1585 | (sio.close_delay != portp->close_delay) || | 1497 | (sio.close_delay != portp->port.close_delay) || |
1586 | ((sio.flags & ~ASYNC_USR_MASK) != | 1498 | ((sio.flags & ~ASYNC_USR_MASK) != |
1587 | (portp->port.flags & ~ASYNC_USR_MASK))) | 1499 | (portp->port.flags & ~ASYNC_USR_MASK))) |
1588 | return -EPERM; | 1500 | return -EPERM; |
@@ -1591,7 +1503,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s | |||
1591 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | 1503 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
1592 | (sio.flags & ASYNC_USR_MASK); | 1504 | (sio.flags & ASYNC_USR_MASK); |
1593 | portp->baud_base = sio.baud_base; | 1505 | portp->baud_base = sio.baud_base; |
1594 | portp->close_delay = sio.close_delay; | 1506 | portp->port.close_delay = sio.close_delay; |
1595 | portp->closing_wait = sio.closing_wait; | 1507 | portp->closing_wait = sio.closing_wait; |
1596 | portp->custom_divisor = sio.custom_divisor; | 1508 | portp->custom_divisor = sio.custom_divisor; |
1597 | 1509 | ||
@@ -1821,6 +1733,7 @@ static void stli_hangup(struct tty_struct *tty) | |||
1821 | { | 1733 | { |
1822 | struct stliport *portp; | 1734 | struct stliport *portp; |
1823 | struct stlibrd *brdp; | 1735 | struct stlibrd *brdp; |
1736 | struct tty_port *port; | ||
1824 | unsigned long flags; | 1737 | unsigned long flags; |
1825 | 1738 | ||
1826 | portp = tty->driver_data; | 1739 | portp = tty->driver_data; |
@@ -1831,8 +1744,11 @@ static void stli_hangup(struct tty_struct *tty) | |||
1831 | brdp = stli_brds[portp->brdnr]; | 1744 | brdp = stli_brds[portp->brdnr]; |
1832 | if (brdp == NULL) | 1745 | if (brdp == NULL) |
1833 | return; | 1746 | return; |
1747 | port = &portp->port; | ||
1834 | 1748 | ||
1835 | portp->port.flags &= ~ASYNC_INITIALIZED; | 1749 | spin_lock_irqsave(&port->lock, flags); |
1750 | port->flags &= ~ASYNC_INITIALIZED; | ||
1751 | spin_unlock_irqrestore(&port->lock, flags); | ||
1836 | 1752 | ||
1837 | if (!test_bit(ST_CLOSING, &portp->state)) | 1753 | if (!test_bit(ST_CLOSING, &portp->state)) |
1838 | stli_rawclose(brdp, portp, 0, 0); | 1754 | stli_rawclose(brdp, portp, 0, 0); |
@@ -1853,12 +1769,9 @@ static void stli_hangup(struct tty_struct *tty) | |||
1853 | clear_bit(ST_TXBUSY, &portp->state); | 1769 | clear_bit(ST_TXBUSY, &portp->state); |
1854 | clear_bit(ST_RXSTOP, &portp->state); | 1770 | clear_bit(ST_RXSTOP, &portp->state); |
1855 | set_bit(TTY_IO_ERROR, &tty->flags); | 1771 | set_bit(TTY_IO_ERROR, &tty->flags); |
1856 | tty_port_tty_set(&portp->port, NULL); | ||
1857 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1858 | portp->port.count = 0; | ||
1859 | spin_unlock_irqrestore(&stli_lock, flags); | 1772 | spin_unlock_irqrestore(&stli_lock, flags); |
1860 | 1773 | ||
1861 | wake_up_interruptible(&portp->port.open_wait); | 1774 | tty_port_hangup(port); |
1862 | } | 1775 | } |
1863 | 1776 | ||
1864 | /*****************************************************************************/ | 1777 | /*****************************************************************************/ |
@@ -2132,7 +2045,7 @@ static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigne | |||
2132 | unsigned char __iomem *bits; | 2045 | unsigned char __iomem *bits; |
2133 | 2046 | ||
2134 | if (test_bit(ST_CMDING, &portp->state)) { | 2047 | if (test_bit(ST_CMDING, &portp->state)) { |
2135 | printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n", | 2048 | printk(KERN_ERR "istallion: command already busy, cmd=%x!\n", |
2136 | (int) cmd); | 2049 | (int) cmd); |
2137 | return; | 2050 | return; |
2138 | } | 2051 | } |
@@ -2692,16 +2605,17 @@ static int stli_initports(struct stlibrd *brdp) | |||
2692 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { | 2605 | for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { |
2693 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); | 2606 | portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); |
2694 | if (!portp) { | 2607 | if (!portp) { |
2695 | printk("STALLION: failed to allocate port structure\n"); | 2608 | printk(KERN_WARNING "istallion: failed to allocate port structure\n"); |
2696 | continue; | 2609 | continue; |
2697 | } | 2610 | } |
2698 | tty_port_init(&portp->port); | 2611 | tty_port_init(&portp->port); |
2612 | portp->port.ops = &stli_port_ops; | ||
2699 | portp->magic = STLI_PORTMAGIC; | 2613 | portp->magic = STLI_PORTMAGIC; |
2700 | portp->portnr = i; | 2614 | portp->portnr = i; |
2701 | portp->brdnr = brdp->brdnr; | 2615 | portp->brdnr = brdp->brdnr; |
2702 | portp->panelnr = panelnr; | 2616 | portp->panelnr = panelnr; |
2703 | portp->baud_base = STL_BAUDBASE; | 2617 | portp->baud_base = STL_BAUDBASE; |
2704 | portp->close_delay = STL_CLOSEDELAY; | 2618 | portp->port.close_delay = STL_CLOSEDELAY; |
2705 | portp->closing_wait = 30 * HZ; | 2619 | portp->closing_wait = 30 * HZ; |
2706 | init_waitqueue_head(&portp->port.open_wait); | 2620 | init_waitqueue_head(&portp->port.open_wait); |
2707 | init_waitqueue_head(&portp->port.close_wait); | 2621 | init_waitqueue_head(&portp->port.close_wait); |
@@ -2758,7 +2672,7 @@ static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offse | |||
2758 | unsigned char val; | 2672 | unsigned char val; |
2759 | 2673 | ||
2760 | if (offset > brdp->memsize) { | 2674 | if (offset > brdp->memsize) { |
2761 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2675 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
2762 | "range at line=%d(%d), brd=%d\n", | 2676 | "range at line=%d(%d), brd=%d\n", |
2763 | (int) offset, line, __LINE__, brdp->brdnr); | 2677 | (int) offset, line, __LINE__, brdp->brdnr); |
2764 | ptr = NULL; | 2678 | ptr = NULL; |
@@ -2832,7 +2746,7 @@ static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long off | |||
2832 | unsigned char val; | 2746 | unsigned char val; |
2833 | 2747 | ||
2834 | if (offset > brdp->memsize) { | 2748 | if (offset > brdp->memsize) { |
2835 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2749 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
2836 | "range at line=%d(%d), brd=%d\n", | 2750 | "range at line=%d(%d), brd=%d\n", |
2837 | (int) offset, line, __LINE__, brdp->brdnr); | 2751 | (int) offset, line, __LINE__, brdp->brdnr); |
2838 | ptr = NULL; | 2752 | ptr = NULL; |
@@ -2884,7 +2798,7 @@ static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long off | |||
2884 | unsigned char val; | 2798 | unsigned char val; |
2885 | 2799 | ||
2886 | if (offset > brdp->memsize) { | 2800 | if (offset > brdp->memsize) { |
2887 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2801 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
2888 | "range at line=%d(%d), brd=%d\n", | 2802 | "range at line=%d(%d), brd=%d\n", |
2889 | (int) offset, line, __LINE__, brdp->brdnr); | 2803 | (int) offset, line, __LINE__, brdp->brdnr); |
2890 | ptr = NULL; | 2804 | ptr = NULL; |
@@ -2929,7 +2843,7 @@ static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long of | |||
2929 | unsigned char val; | 2843 | unsigned char val; |
2930 | 2844 | ||
2931 | if (offset > brdp->memsize) { | 2845 | if (offset > brdp->memsize) { |
2932 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2846 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
2933 | "range at line=%d(%d), board=%d\n", | 2847 | "range at line=%d(%d), board=%d\n", |
2934 | (int) offset, line, __LINE__, brdp->brdnr); | 2848 | (int) offset, line, __LINE__, brdp->brdnr); |
2935 | ptr = NULL; | 2849 | ptr = NULL; |
@@ -2994,7 +2908,7 @@ static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offse | |||
2994 | void __iomem *ptr; | 2908 | void __iomem *ptr; |
2995 | 2909 | ||
2996 | if (offset > brdp->memsize) { | 2910 | if (offset > brdp->memsize) { |
2997 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2911 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
2998 | "range at line=%d(%d), brd=%d\n", | 2912 | "range at line=%d(%d), brd=%d\n", |
2999 | (int) offset, line, __LINE__, brdp->brdnr); | 2913 | (int) offset, line, __LINE__, brdp->brdnr); |
3000 | ptr = NULL; | 2914 | ptr = NULL; |
@@ -3060,7 +2974,7 @@ static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offs | |||
3060 | unsigned char val; | 2974 | unsigned char val; |
3061 | 2975 | ||
3062 | if (offset > brdp->memsize) { | 2976 | if (offset > brdp->memsize) { |
3063 | printk(KERN_ERR "STALLION: shared memory pointer=%x out of " | 2977 | printk(KERN_ERR "istallion: shared memory pointer=%x out of " |
3064 | "range at line=%d(%d), brd=%d\n", | 2978 | "range at line=%d(%d), brd=%d\n", |
3065 | (int) offset, line, __LINE__, brdp->brdnr); | 2979 | (int) offset, line, __LINE__, brdp->brdnr); |
3066 | ptr = NULL; | 2980 | ptr = NULL; |
@@ -3499,7 +3413,7 @@ static int stli_startbrd(struct stlibrd *brdp) | |||
3499 | #endif | 3413 | #endif |
3500 | 3414 | ||
3501 | if (nrdevs < (brdp->nrports + 1)) { | 3415 | if (nrdevs < (brdp->nrports + 1)) { |
3502 | printk(KERN_ERR "STALLION: slave failed to allocate memory for " | 3416 | printk(KERN_ERR "istallion: slave failed to allocate memory for " |
3503 | "all devices, devices=%d\n", nrdevs); | 3417 | "all devices, devices=%d\n", nrdevs); |
3504 | brdp->nrports = nrdevs - 1; | 3418 | brdp->nrports = nrdevs - 1; |
3505 | } | 3419 | } |
@@ -3509,13 +3423,13 @@ static int stli_startbrd(struct stlibrd *brdp) | |||
3509 | brdp->bitsize = (nrdevs + 7) / 8; | 3423 | brdp->bitsize = (nrdevs + 7) / 8; |
3510 | memoff = readl(&hdrp->memp); | 3424 | memoff = readl(&hdrp->memp); |
3511 | if (memoff > brdp->memsize) { | 3425 | if (memoff > brdp->memsize) { |
3512 | printk(KERN_ERR "STALLION: corrupted shared memory region?\n"); | 3426 | printk(KERN_ERR "istallion: corrupted shared memory region?\n"); |
3513 | rc = -EIO; | 3427 | rc = -EIO; |
3514 | goto stli_donestartup; | 3428 | goto stli_donestartup; |
3515 | } | 3429 | } |
3516 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); | 3430 | memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff); |
3517 | if (readw(&memp->dtype) != TYP_ASYNCTRL) { | 3431 | if (readw(&memp->dtype) != TYP_ASYNCTRL) { |
3518 | printk(KERN_ERR "STALLION: no slave control device found\n"); | 3432 | printk(KERN_ERR "istallion: no slave control device found\n"); |
3519 | goto stli_donestartup; | 3433 | goto stli_donestartup; |
3520 | } | 3434 | } |
3521 | memp++; | 3435 | memp++; |
@@ -3600,7 +3514,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp) | |||
3600 | retval = stli_initonb(brdp); | 3514 | retval = stli_initonb(brdp); |
3601 | break; | 3515 | break; |
3602 | default: | 3516 | default: |
3603 | printk(KERN_ERR "STALLION: board=%d is unknown board " | 3517 | printk(KERN_ERR "istallion: board=%d is unknown board " |
3604 | "type=%d\n", brdp->brdnr, brdp->brdtype); | 3518 | "type=%d\n", brdp->brdnr, brdp->brdtype); |
3605 | retval = -ENODEV; | 3519 | retval = -ENODEV; |
3606 | } | 3520 | } |
@@ -3609,7 +3523,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp) | |||
3609 | return retval; | 3523 | return retval; |
3610 | 3524 | ||
3611 | stli_initports(brdp); | 3525 | stli_initports(brdp); |
3612 | printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x " | 3526 | printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x " |
3613 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], | 3527 | "nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype], |
3614 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, | 3528 | brdp->brdnr, brdp->iobase, (int) brdp->memaddr, |
3615 | brdp->nrpanels, brdp->nrports); | 3529 | brdp->nrpanels, brdp->nrports); |
@@ -3703,7 +3617,7 @@ static int stli_eisamemprobe(struct stlibrd *brdp) | |||
3703 | if (! foundit) { | 3617 | if (! foundit) { |
3704 | brdp->memaddr = 0; | 3618 | brdp->memaddr = 0; |
3705 | brdp->membase = NULL; | 3619 | brdp->membase = NULL; |
3706 | printk(KERN_ERR "STALLION: failed to probe shared memory " | 3620 | printk(KERN_ERR "istallion: failed to probe shared memory " |
3707 | "region for %s in EISA slot=%d\n", | 3621 | "region for %s in EISA slot=%d\n", |
3708 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); | 3622 | stli_brdnames[brdp->brdtype], (brdp->iobase >> 12)); |
3709 | return -ENODEV; | 3623 | return -ENODEV; |
@@ -3848,7 +3762,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev, | |||
3848 | mutex_lock(&stli_brdslock); | 3762 | mutex_lock(&stli_brdslock); |
3849 | brdnr = stli_getbrdnr(); | 3763 | brdnr = stli_getbrdnr(); |
3850 | if (brdnr < 0) { | 3764 | if (brdnr < 0) { |
3851 | printk(KERN_INFO "STALLION: too many boards found, " | 3765 | printk(KERN_INFO "istallion: too many boards found, " |
3852 | "maximum supported %d\n", STL_MAXBRDS); | 3766 | "maximum supported %d\n", STL_MAXBRDS); |
3853 | mutex_unlock(&stli_brdslock); | 3767 | mutex_unlock(&stli_brdslock); |
3854 | retval = -EIO; | 3768 | retval = -EIO; |
@@ -3920,7 +3834,7 @@ static struct stlibrd *stli_allocbrd(void) | |||
3920 | 3834 | ||
3921 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); | 3835 | brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); |
3922 | if (!brdp) { | 3836 | if (!brdp) { |
3923 | printk(KERN_ERR "STALLION: failed to allocate memory " | 3837 | printk(KERN_ERR "istallion: failed to allocate memory " |
3924 | "(size=%Zd)\n", sizeof(struct stlibrd)); | 3838 | "(size=%Zd)\n", sizeof(struct stlibrd)); |
3925 | return NULL; | 3839 | return NULL; |
3926 | } | 3840 | } |
@@ -4518,6 +4432,11 @@ static const struct tty_operations stli_ops = { | |||
4518 | .tiocmset = stli_tiocmset, | 4432 | .tiocmset = stli_tiocmset, |
4519 | }; | 4433 | }; |
4520 | 4434 | ||
4435 | static const struct tty_port_operations stli_port_ops = { | ||
4436 | .carrier_raised = stli_carrier_raised, | ||
4437 | .raise_dtr_rts = stli_raise_dtr_rts, | ||
4438 | }; | ||
4439 | |||
4521 | /*****************************************************************************/ | 4440 | /*****************************************************************************/ |
4522 | /* | 4441 | /* |
4523 | * Loadable module initialization stuff. | 4442 | * Loadable module initialization stuff. |
@@ -4554,7 +4473,7 @@ static int __init istallion_module_init(void) | |||
4554 | 4473 | ||
4555 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); | 4474 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
4556 | if (!stli_txcookbuf) { | 4475 | if (!stli_txcookbuf) { |
4557 | printk(KERN_ERR "STALLION: failed to allocate memory " | 4476 | printk(KERN_ERR "istallion: failed to allocate memory " |
4558 | "(size=%d)\n", STLI_TXBUFSIZE); | 4477 | "(size=%d)\n", STLI_TXBUFSIZE); |
4559 | retval = -ENOMEM; | 4478 | retval = -ENOMEM; |
4560 | goto err; | 4479 | goto err; |
@@ -4579,7 +4498,7 @@ static int __init istallion_module_init(void) | |||
4579 | 4498 | ||
4580 | retval = tty_register_driver(stli_serial); | 4499 | retval = tty_register_driver(stli_serial); |
4581 | if (retval) { | 4500 | if (retval) { |
4582 | printk(KERN_ERR "STALLION: failed to register serial driver\n"); | 4501 | printk(KERN_ERR "istallion: failed to register serial driver\n"); |
4583 | goto err_ttyput; | 4502 | goto err_ttyput; |
4584 | } | 4503 | } |
4585 | 4504 | ||
@@ -4593,7 +4512,7 @@ static int __init istallion_module_init(void) | |||
4593 | */ | 4512 | */ |
4594 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); | 4513 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); |
4595 | if (retval) { | 4514 | if (retval) { |
4596 | printk(KERN_ERR "STALLION: failed to register serial memory " | 4515 | printk(KERN_ERR "istallion: failed to register serial memory " |
4597 | "device\n"); | 4516 | "device\n"); |
4598 | goto err_deinit; | 4517 | goto err_deinit; |
4599 | } | 4518 | } |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 12d327a2c9ba..8b0da97d5293 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -206,6 +206,7 @@ static void moxa_poll(unsigned long); | |||
206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); |
207 | static void moxa_setup_empty_event(struct tty_struct *); | 207 | static void moxa_setup_empty_event(struct tty_struct *); |
208 | static void moxa_shut_down(struct tty_struct *); | 208 | static void moxa_shut_down(struct tty_struct *); |
209 | static int moxa_carrier_raised(struct tty_port *); | ||
209 | /* | 210 | /* |
210 | * moxa board interface functions: | 211 | * moxa board interface functions: |
211 | */ | 212 | */ |
@@ -405,6 +406,10 @@ static const struct tty_operations moxa_ops = { | |||
405 | .tiocmset = moxa_tiocmset, | 406 | .tiocmset = moxa_tiocmset, |
406 | }; | 407 | }; |
407 | 408 | ||
409 | static const struct tty_port_operations moxa_port_ops = { | ||
410 | .carrier_raised = moxa_carrier_raised, | ||
411 | }; | ||
412 | |||
408 | static struct tty_driver *moxaDriver; | 413 | static struct tty_driver *moxaDriver; |
409 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 414 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); |
410 | static DEFINE_SPINLOCK(moxa_lock); | 415 | static DEFINE_SPINLOCK(moxa_lock); |
@@ -826,6 +831,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) | |||
826 | 831 | ||
827 | for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { | 832 | for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) { |
828 | tty_port_init(&p->port); | 833 | tty_port_init(&p->port); |
834 | p->port.ops = &moxa_port_ops; | ||
829 | p->type = PORT_16550A; | 835 | p->type = PORT_16550A; |
830 | p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; | 836 | p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; |
831 | } | 837 | } |
@@ -1115,15 +1121,27 @@ static void moxa_close_port(struct tty_struct *tty) | |||
1115 | tty_port_tty_set(&ch->port, NULL); | 1121 | tty_port_tty_set(&ch->port, NULL); |
1116 | } | 1122 | } |
1117 | 1123 | ||
1124 | static int moxa_carrier_raised(struct tty_port *port) | ||
1125 | { | ||
1126 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | ||
1127 | int dcd; | ||
1128 | |||
1129 | spin_lock_bh(&moxa_lock); | ||
1130 | dcd = ch->DCDState; | ||
1131 | spin_unlock_bh(&moxa_lock); | ||
1132 | return dcd; | ||
1133 | } | ||
1134 | |||
1118 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1135 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, |
1119 | struct moxa_port *ch) | 1136 | struct moxa_port *ch) |
1120 | { | 1137 | { |
1138 | struct tty_port *port = &ch->port; | ||
1121 | DEFINE_WAIT(wait); | 1139 | DEFINE_WAIT(wait); |
1122 | int retval = 0; | 1140 | int retval = 0; |
1123 | u8 dcd; | 1141 | u8 dcd; |
1124 | 1142 | ||
1125 | while (1) { | 1143 | while (1) { |
1126 | prepare_to_wait(&ch->port.open_wait, &wait, TASK_INTERRUPTIBLE); | 1144 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); |
1127 | if (tty_hung_up_p(filp)) { | 1145 | if (tty_hung_up_p(filp)) { |
1128 | #ifdef SERIAL_DO_RESTART | 1146 | #ifdef SERIAL_DO_RESTART |
1129 | retval = -ERESTARTSYS; | 1147 | retval = -ERESTARTSYS; |
@@ -1132,9 +1150,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | |||
1132 | #endif | 1150 | #endif |
1133 | break; | 1151 | break; |
1134 | } | 1152 | } |
1135 | spin_lock_bh(&moxa_lock); | 1153 | dcd = tty_port_carrier_raised(port); |
1136 | dcd = ch->DCDState; | ||
1137 | spin_unlock_bh(&moxa_lock); | ||
1138 | if (dcd) | 1154 | if (dcd) |
1139 | break; | 1155 | break; |
1140 | 1156 | ||
@@ -1144,7 +1160,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | |||
1144 | } | 1160 | } |
1145 | schedule(); | 1161 | schedule(); |
1146 | } | 1162 | } |
1147 | finish_wait(&ch->port.open_wait, &wait); | 1163 | finish_wait(&port->open_wait, &wait); |
1148 | 1164 | ||
1149 | return retval; | 1165 | return retval; |
1150 | } | 1166 | } |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 047766915411..402c9f217f83 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -541,74 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | |||
541 | return status; | 541 | return status; |
542 | } | 542 | } |
543 | 543 | ||
544 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | 544 | static int mxser_carrier_raised(struct tty_port *port) |
545 | struct mxser_port *port) | ||
546 | { | 545 | { |
547 | DECLARE_WAITQUEUE(wait, current); | 546 | struct mxser_port *mp = container_of(port, struct mxser_port, port); |
548 | int retval; | 547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; |
549 | int do_clocal = 0; | 548 | } |
550 | unsigned long flags; | ||
551 | |||
552 | /* | ||
553 | * If non-blocking mode is set, or the port is not enabled, | ||
554 | * then make the check up front and then exit. | ||
555 | */ | ||
556 | if ((filp->f_flags & O_NONBLOCK) || | ||
557 | test_bit(TTY_IO_ERROR, &tty->flags)) { | ||
558 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
559 | return 0; | ||
560 | } | ||
561 | 549 | ||
562 | if (tty->termios->c_cflag & CLOCAL) | 550 | static void mxser_raise_dtr_rts(struct tty_port *port) |
563 | do_clocal = 1; | 551 | { |
552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); | ||
553 | unsigned long flags; | ||
564 | 554 | ||
565 | /* | 555 | spin_lock_irqsave(&mp->slock, flags); |
566 | * Block waiting for the carrier detect and the line to become | 556 | outb(inb(mp->ioaddr + UART_MCR) | |
567 | * free (i.e., not in use by the callout). While we are in | 557 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); |
568 | * this loop, port->port.count is dropped by one, so that | 558 | spin_unlock_irqrestore(&mp->slock, flags); |
569 | * mxser_close() knows when to free things. We restore it upon | ||
570 | * exit, either normal or abnormal. | ||
571 | */ | ||
572 | retval = 0; | ||
573 | add_wait_queue(&port->port.open_wait, &wait); | ||
574 | |||
575 | spin_lock_irqsave(&port->slock, flags); | ||
576 | if (!tty_hung_up_p(filp)) | ||
577 | port->port.count--; | ||
578 | spin_unlock_irqrestore(&port->slock, flags); | ||
579 | port->port.blocked_open++; | ||
580 | while (1) { | ||
581 | spin_lock_irqsave(&port->slock, flags); | ||
582 | outb(inb(port->ioaddr + UART_MCR) | | ||
583 | UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); | ||
584 | spin_unlock_irqrestore(&port->slock, flags); | ||
585 | set_current_state(TASK_INTERRUPTIBLE); | ||
586 | if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { | ||
587 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
588 | retval = -EAGAIN; | ||
589 | else | ||
590 | retval = -ERESTARTSYS; | ||
591 | break; | ||
592 | } | ||
593 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
594 | (do_clocal || | ||
595 | (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) | ||
596 | break; | ||
597 | if (signal_pending(current)) { | ||
598 | retval = -ERESTARTSYS; | ||
599 | break; | ||
600 | } | ||
601 | schedule(); | ||
602 | } | ||
603 | set_current_state(TASK_RUNNING); | ||
604 | remove_wait_queue(&port->port.open_wait, &wait); | ||
605 | if (!tty_hung_up_p(filp)) | ||
606 | port->port.count++; | ||
607 | port->port.blocked_open--; | ||
608 | if (retval) | ||
609 | return retval; | ||
610 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
611 | return 0; | ||
612 | } | 559 | } |
613 | 560 | ||
614 | static int mxser_set_baud(struct tty_struct *tty, long newspd) | 561 | static int mxser_set_baud(struct tty_struct *tty, long newspd) |
@@ -1087,14 +1034,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1087 | /* | 1034 | /* |
1088 | * Start up serial port | 1035 | * Start up serial port |
1089 | */ | 1036 | */ |
1090 | spin_lock_irqsave(&info->slock, flags); | 1037 | spin_lock_irqsave(&info->port.lock, flags); |
1091 | info->port.count++; | 1038 | info->port.count++; |
1092 | spin_unlock_irqrestore(&info->slock, flags); | 1039 | spin_unlock_irqrestore(&info->port.lock, flags); |
1093 | retval = mxser_startup(tty); | 1040 | retval = mxser_startup(tty); |
1094 | if (retval) | 1041 | if (retval) |
1095 | return retval; | 1042 | return retval; |
1096 | 1043 | ||
1097 | retval = mxser_block_til_ready(tty, filp, info); | 1044 | retval = tty_port_block_til_ready(&info->port, tty, filp); |
1098 | if (retval) | 1045 | if (retval) |
1099 | return retval; | 1046 | return retval; |
1100 | 1047 | ||
@@ -1133,58 +1080,27 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1133 | static void mxser_close(struct tty_struct *tty, struct file *filp) | 1080 | static void mxser_close(struct tty_struct *tty, struct file *filp) |
1134 | { | 1081 | { |
1135 | struct mxser_port *info = tty->driver_data; | 1082 | struct mxser_port *info = tty->driver_data; |
1083 | struct tty_port *port = &info->port; | ||
1136 | 1084 | ||
1137 | unsigned long timeout; | 1085 | unsigned long timeout; |
1138 | unsigned long flags; | ||
1139 | 1086 | ||
1140 | if (tty->index == MXSER_PORTS) | 1087 | if (tty->index == MXSER_PORTS) |
1141 | return; | 1088 | return; |
1142 | if (!info) | 1089 | if (!info) |
1143 | return; | 1090 | return; |
1144 | 1091 | ||
1145 | spin_lock_irqsave(&info->slock, flags); | 1092 | if (tty_port_close_start(port, tty, filp) == 0) |
1146 | |||
1147 | if (tty_hung_up_p(filp)) { | ||
1148 | spin_unlock_irqrestore(&info->slock, flags); | ||
1149 | return; | ||
1150 | } | ||
1151 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
1152 | /* | ||
1153 | * Uh, oh. tty->count is 1, which means that the tty | ||
1154 | * structure will be freed. Info->port.count should always | ||
1155 | * be one in these conditions. If it's greater than | ||
1156 | * one, we've got real problems, since it means the | ||
1157 | * serial port won't be shutdown. | ||
1158 | */ | ||
1159 | printk(KERN_ERR "mxser_close: bad serial port count; " | ||
1160 | "tty->count is 1, info->port.count is %d\n", info->port.count); | ||
1161 | info->port.count = 1; | ||
1162 | } | ||
1163 | if (--info->port.count < 0) { | ||
1164 | printk(KERN_ERR "mxser_close: bad serial port count for " | ||
1165 | "ttys%d: %d\n", tty->index, info->port.count); | ||
1166 | info->port.count = 0; | ||
1167 | } | ||
1168 | if (info->port.count) { | ||
1169 | spin_unlock_irqrestore(&info->slock, flags); | ||
1170 | return; | 1093 | return; |
1171 | } | 1094 | |
1172 | info->port.flags |= ASYNC_CLOSING; | ||
1173 | spin_unlock_irqrestore(&info->slock, flags); | ||
1174 | /* | 1095 | /* |
1175 | * Save the termios structure, since this port may have | 1096 | * Save the termios structure, since this port may have |
1176 | * separate termios for callout and dialin. | 1097 | * separate termios for callout and dialin. |
1098 | * | ||
1099 | * FIXME: Can this go ? | ||
1177 | */ | 1100 | */ |
1178 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) | 1101 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) |
1179 | info->normal_termios = *tty->termios; | 1102 | info->normal_termios = *tty->termios; |
1180 | /* | 1103 | /* |
1181 | * Now we wait for the transmit buffer to clear; and we notify | ||
1182 | * the line discipline to only process XON/XOFF characters. | ||
1183 | */ | ||
1184 | tty->closing = 1; | ||
1185 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1186 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
1187 | /* | ||
1188 | * At this point we stop accepting input. To do this, we | 1104 | * At this point we stop accepting input. To do this, we |
1189 | * disable the receive line status interrupts, and tell the | 1105 | * disable the receive line status interrupts, and tell the |
1190 | * interrupt driver to stop checking the data ready bit in the | 1106 | * interrupt driver to stop checking the data ready bit in the |
@@ -1209,19 +1125,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1209 | } | 1125 | } |
1210 | } | 1126 | } |
1211 | mxser_shutdown(tty); | 1127 | mxser_shutdown(tty); |
1212 | |||
1213 | mxser_flush_buffer(tty); | 1128 | mxser_flush_buffer(tty); |
1214 | tty_ldisc_flush(tty); | ||
1215 | |||
1216 | tty->closing = 0; | ||
1217 | tty_port_tty_set(&info->port, NULL); | ||
1218 | if (info->port.blocked_open) { | ||
1219 | if (info->port.close_delay) | ||
1220 | schedule_timeout_interruptible(info->port.close_delay); | ||
1221 | wake_up_interruptible(&info->port.open_wait); | ||
1222 | } | ||
1223 | 1129 | ||
1224 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | 1130 | /* Right now the tty_port set is done outside of the close_end helper |
1131 | as we don't yet have everyone using refcounts */ | ||
1132 | tty_port_close_end(port, tty); | ||
1133 | tty_port_tty_set(port, NULL); | ||
1225 | } | 1134 | } |
1226 | 1135 | ||
1227 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1136 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -2146,10 +2055,7 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2146 | 2055 | ||
2147 | mxser_flush_buffer(tty); | 2056 | mxser_flush_buffer(tty); |
2148 | mxser_shutdown(tty); | 2057 | mxser_shutdown(tty); |
2149 | info->port.count = 0; | 2058 | tty_port_hangup(&info->port); |
2150 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2151 | tty_port_tty_set(&info->port, NULL); | ||
2152 | wake_up_interruptible(&info->port.open_wait); | ||
2153 | } | 2059 | } |
2154 | 2060 | ||
2155 | /* | 2061 | /* |
@@ -2449,6 +2355,11 @@ static const struct tty_operations mxser_ops = { | |||
2449 | .tiocmset = mxser_tiocmset, | 2355 | .tiocmset = mxser_tiocmset, |
2450 | }; | 2356 | }; |
2451 | 2357 | ||
2358 | struct tty_port_operations mxser_port_ops = { | ||
2359 | .carrier_raised = mxser_carrier_raised, | ||
2360 | .raise_dtr_rts = mxser_raise_dtr_rts, | ||
2361 | }; | ||
2362 | |||
2452 | /* | 2363 | /* |
2453 | * The MOXA Smartio/Industio serial driver boot-time initialization code! | 2364 | * The MOXA Smartio/Industio serial driver boot-time initialization code! |
2454 | */ | 2365 | */ |
@@ -2482,6 +2393,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2482 | for (i = 0; i < brd->info->nports; i++) { | 2393 | for (i = 0; i < brd->info->nports; i++) { |
2483 | info = &brd->ports[i]; | 2394 | info = &brd->ports[i]; |
2484 | tty_port_init(&info->port); | 2395 | tty_port_init(&info->port); |
2396 | info->port.ops = &mxser_port_ops; | ||
2485 | info->board = brd; | 2397 | info->board = brd; |
2486 | info->stop_rx = 0; | 2398 | info->stop_rx = 0; |
2487 | info->ldisc_stop_rx = 0; | 2399 | info->ldisc_stop_rx = 0; |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 4a8215a89ad3..d2e93e343226 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1003,7 +1003,7 @@ static int r3964_open(struct tty_struct *tty) | |||
1003 | 1003 | ||
1004 | static void r3964_close(struct tty_struct *tty) | 1004 | static void r3964_close(struct tty_struct *tty) |
1005 | { | 1005 | { |
1006 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1006 | struct r3964_info *pInfo = tty->disc_data; |
1007 | struct r3964_client_info *pClient, *pNext; | 1007 | struct r3964_client_info *pClient, *pNext; |
1008 | struct r3964_message *pMsg; | 1008 | struct r3964_message *pMsg; |
1009 | struct r3964_block_header *pHeader, *pNextHeader; | 1009 | struct r3964_block_header *pHeader, *pNextHeader; |
@@ -1058,7 +1058,7 @@ static void r3964_close(struct tty_struct *tty) | |||
1058 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 1058 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
1059 | unsigned char __user * buf, size_t nr) | 1059 | unsigned char __user * buf, size_t nr) |
1060 | { | 1060 | { |
1061 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1061 | struct r3964_info *pInfo = tty->disc_data; |
1062 | struct r3964_client_info *pClient; | 1062 | struct r3964_client_info *pClient; |
1063 | struct r3964_message *pMsg; | 1063 | struct r3964_message *pMsg; |
1064 | struct r3964_client_message theMsg; | 1064 | struct r3964_client_message theMsg; |
@@ -1113,7 +1113,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1113 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | 1113 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
1114 | const unsigned char *data, size_t count) | 1114 | const unsigned char *data, size_t count) |
1115 | { | 1115 | { |
1116 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1116 | struct r3964_info *pInfo = tty->disc_data; |
1117 | struct r3964_block_header *pHeader; | 1117 | struct r3964_block_header *pHeader; |
1118 | struct r3964_client_info *pClient; | 1118 | struct r3964_client_info *pClient; |
1119 | unsigned char *new_data; | 1119 | unsigned char *new_data; |
@@ -1182,7 +1182,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1182 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, | 1182 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
1183 | unsigned int cmd, unsigned long arg) | 1183 | unsigned int cmd, unsigned long arg) |
1184 | { | 1184 | { |
1185 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1185 | struct r3964_info *pInfo = tty->disc_data; |
1186 | if (pInfo == NULL) | 1186 | if (pInfo == NULL) |
1187 | return -EINVAL; | 1187 | return -EINVAL; |
1188 | switch (cmd) { | 1188 | switch (cmd) { |
@@ -1216,7 +1216,7 @@ static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1216 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, | 1216 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
1217 | struct poll_table_struct *wait) | 1217 | struct poll_table_struct *wait) |
1218 | { | 1218 | { |
1219 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1219 | struct r3964_info *pInfo = tty->disc_data; |
1220 | struct r3964_client_info *pClient; | 1220 | struct r3964_client_info *pClient; |
1221 | struct r3964_message *pMsg = NULL; | 1221 | struct r3964_message *pMsg = NULL; |
1222 | unsigned long flags; | 1222 | unsigned long flags; |
@@ -1241,7 +1241,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, | |||
1241 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1241 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
1242 | char *fp, int count) | 1242 | char *fp, int count) |
1243 | { | 1243 | { |
1244 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; | 1244 | struct r3964_info *pInfo = tty->disc_data; |
1245 | const unsigned char *p; | 1245 | const unsigned char *p; |
1246 | char *f, flags = 0; | 1246 | char *f, flags = 0; |
1247 | int i; | 1247 | int i; |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index efbfe9612658..f6f0e4ec2b51 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -47,8 +47,8 @@ | |||
47 | #include <linux/bitops.h> | 47 | #include <linux/bitops.h> |
48 | #include <linux/audit.h> | 48 | #include <linux/audit.h> |
49 | #include <linux/file.h> | 49 | #include <linux/file.h> |
50 | #include <linux/uaccess.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | ||
52 | #include <asm/system.h> | 52 | #include <asm/system.h> |
53 | 53 | ||
54 | /* number of characters left in xmit buffer before select has we have room */ | 54 | /* number of characters left in xmit buffer before select has we have room */ |
@@ -62,6 +62,17 @@ | |||
62 | #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ | 62 | #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ |
63 | #define TTY_THRESHOLD_UNTHROTTLE 128 | 63 | #define TTY_THRESHOLD_UNTHROTTLE 128 |
64 | 64 | ||
65 | /* | ||
66 | * Special byte codes used in the echo buffer to represent operations | ||
67 | * or special handling of characters. Bytes in the echo buffer that | ||
68 | * are not part of such special blocks are treated as normal character | ||
69 | * codes. | ||
70 | */ | ||
71 | #define ECHO_OP_START 0xff | ||
72 | #define ECHO_OP_MOVE_BACK_COL 0x80 | ||
73 | #define ECHO_OP_SET_CANON_COL 0x81 | ||
74 | #define ECHO_OP_ERASE_TAB 0x82 | ||
75 | |||
65 | static inline unsigned char *alloc_buf(void) | 76 | static inline unsigned char *alloc_buf(void) |
66 | { | 77 | { |
67 | gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; | 78 | gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; |
@@ -169,6 +180,7 @@ static void check_unthrottle(struct tty_struct *tty) | |||
169 | * | 180 | * |
170 | * Locking: tty_read_lock for read fields. | 181 | * Locking: tty_read_lock for read fields. |
171 | */ | 182 | */ |
183 | |||
172 | static void reset_buffer_flags(struct tty_struct *tty) | 184 | static void reset_buffer_flags(struct tty_struct *tty) |
173 | { | 185 | { |
174 | unsigned long flags; | 186 | unsigned long flags; |
@@ -176,6 +188,11 @@ static void reset_buffer_flags(struct tty_struct *tty) | |||
176 | spin_lock_irqsave(&tty->read_lock, flags); | 188 | spin_lock_irqsave(&tty->read_lock, flags); |
177 | tty->read_head = tty->read_tail = tty->read_cnt = 0; | 189 | tty->read_head = tty->read_tail = tty->read_cnt = 0; |
178 | spin_unlock_irqrestore(&tty->read_lock, flags); | 190 | spin_unlock_irqrestore(&tty->read_lock, flags); |
191 | |||
192 | mutex_lock(&tty->echo_lock); | ||
193 | tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0; | ||
194 | mutex_unlock(&tty->echo_lock); | ||
195 | |||
179 | tty->canon_head = tty->canon_data = tty->erasing = 0; | 196 | tty->canon_head = tty->canon_data = tty->erasing = 0; |
180 | memset(&tty->read_flags, 0, sizeof tty->read_flags); | 197 | memset(&tty->read_flags, 0, sizeof tty->read_flags); |
181 | n_tty_set_room(tty); | 198 | n_tty_set_room(tty); |
@@ -266,89 +283,118 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty) | |||
266 | } | 283 | } |
267 | 284 | ||
268 | /** | 285 | /** |
269 | * opost - output post processor | 286 | * do_output_char - output one character |
270 | * @c: character (or partial unicode symbol) | 287 | * @c: character (or partial unicode symbol) |
271 | * @tty: terminal device | 288 | * @tty: terminal device |
289 | * @space: space available in tty driver write buffer | ||
272 | * | 290 | * |
273 | * Perform OPOST processing. Returns -1 when the output device is | 291 | * This is a helper function that handles one output character |
274 | * full and the character must be retried. Note that Linux currently | 292 | * (including special characters like TAB, CR, LF, etc.), |
275 | * ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't | 293 | * putting the results in the tty driver's write buffer. |
276 | * relevant in the world today. If you ever need them, add them here. | 294 | * |
295 | * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY | ||
296 | * and NLDLY. They simply aren't relevant in the world today. | ||
297 | * If you ever need them, add them here. | ||
298 | * | ||
299 | * Returns the number of bytes of buffer space used or -1 if | ||
300 | * no space left. | ||
277 | * | 301 | * |
278 | * Called from both the receive and transmit sides and can be called | 302 | * Locking: should be called under the output_lock to protect |
279 | * re-entrantly. Relies on lock_kernel() for tty->column state. | 303 | * the column state and space left in the buffer |
280 | */ | 304 | */ |
281 | 305 | ||
282 | static int opost(unsigned char c, struct tty_struct *tty) | 306 | static int do_output_char(unsigned char c, struct tty_struct *tty, int space) |
283 | { | 307 | { |
284 | int space, spaces; | 308 | int spaces; |
285 | 309 | ||
286 | space = tty_write_room(tty); | ||
287 | if (!space) | 310 | if (!space) |
288 | return -1; | 311 | return -1; |
289 | 312 | ||
290 | lock_kernel(); | 313 | switch (c) { |
291 | if (O_OPOST(tty)) { | 314 | case '\n': |
292 | switch (c) { | 315 | if (O_ONLRET(tty)) |
293 | case '\n': | 316 | tty->column = 0; |
294 | if (O_ONLRET(tty)) | 317 | if (O_ONLCR(tty)) { |
295 | tty->column = 0; | 318 | if (space < 2) |
296 | if (O_ONLCR(tty)) { | 319 | return -1; |
297 | if (space < 2) { | ||
298 | unlock_kernel(); | ||
299 | return -1; | ||
300 | } | ||
301 | tty_put_char(tty, '\r'); | ||
302 | tty->column = 0; | ||
303 | } | ||
304 | tty->canon_column = tty->column; | ||
305 | break; | ||
306 | case '\r': | ||
307 | if (O_ONOCR(tty) && tty->column == 0) { | ||
308 | unlock_kernel(); | ||
309 | return 0; | ||
310 | } | ||
311 | if (O_OCRNL(tty)) { | ||
312 | c = '\n'; | ||
313 | if (O_ONLRET(tty)) | ||
314 | tty->canon_column = tty->column = 0; | ||
315 | break; | ||
316 | } | ||
317 | tty->canon_column = tty->column = 0; | 320 | tty->canon_column = tty->column = 0; |
321 | tty_put_char(tty, '\r'); | ||
322 | tty_put_char(tty, c); | ||
323 | return 2; | ||
324 | } | ||
325 | tty->canon_column = tty->column; | ||
326 | break; | ||
327 | case '\r': | ||
328 | if (O_ONOCR(tty) && tty->column == 0) | ||
329 | return 0; | ||
330 | if (O_OCRNL(tty)) { | ||
331 | c = '\n'; | ||
332 | if (O_ONLRET(tty)) | ||
333 | tty->canon_column = tty->column = 0; | ||
318 | break; | 334 | break; |
319 | case '\t': | 335 | } |
320 | spaces = 8 - (tty->column & 7); | 336 | tty->canon_column = tty->column = 0; |
321 | if (O_TABDLY(tty) == XTABS) { | 337 | break; |
322 | if (space < spaces) { | 338 | case '\t': |
323 | unlock_kernel(); | 339 | spaces = 8 - (tty->column & 7); |
324 | return -1; | 340 | if (O_TABDLY(tty) == XTABS) { |
325 | } | 341 | if (space < spaces) |
326 | tty->column += spaces; | 342 | return -1; |
327 | tty->ops->write(tty, " ", spaces); | ||
328 | unlock_kernel(); | ||
329 | return 0; | ||
330 | } | ||
331 | tty->column += spaces; | 343 | tty->column += spaces; |
332 | break; | 344 | tty->ops->write(tty, " ", spaces); |
333 | case '\b': | 345 | return spaces; |
334 | if (tty->column > 0) | 346 | } |
335 | tty->column--; | 347 | tty->column += spaces; |
336 | break; | 348 | break; |
337 | default: | 349 | case '\b': |
350 | if (tty->column > 0) | ||
351 | tty->column--; | ||
352 | break; | ||
353 | default: | ||
354 | if (!iscntrl(c)) { | ||
338 | if (O_OLCUC(tty)) | 355 | if (O_OLCUC(tty)) |
339 | c = toupper(c); | 356 | c = toupper(c); |
340 | if (!iscntrl(c) && !is_continuation(c, tty)) | 357 | if (!is_continuation(c, tty)) |
341 | tty->column++; | 358 | tty->column++; |
342 | break; | ||
343 | } | 359 | } |
360 | break; | ||
344 | } | 361 | } |
362 | |||
345 | tty_put_char(tty, c); | 363 | tty_put_char(tty, c); |
346 | unlock_kernel(); | 364 | return 1; |
347 | return 0; | ||
348 | } | 365 | } |
349 | 366 | ||
350 | /** | 367 | /** |
351 | * opost_block - block postprocess | 368 | * process_output - output post processor |
369 | * @c: character (or partial unicode symbol) | ||
370 | * @tty: terminal device | ||
371 | * | ||
372 | * Perform OPOST processing. Returns -1 when the output device is | ||
373 | * full and the character must be retried. | ||
374 | * | ||
375 | * Locking: output_lock to protect column state and space left | ||
376 | * (also, this is called from n_tty_write under the | ||
377 | * tty layer write lock) | ||
378 | */ | ||
379 | |||
380 | static int process_output(unsigned char c, struct tty_struct *tty) | ||
381 | { | ||
382 | int space, retval; | ||
383 | |||
384 | mutex_lock(&tty->output_lock); | ||
385 | |||
386 | space = tty_write_room(tty); | ||
387 | retval = do_output_char(c, tty, space); | ||
388 | |||
389 | mutex_unlock(&tty->output_lock); | ||
390 | if (retval < 0) | ||
391 | return -1; | ||
392 | else | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * process_output_block - block post processor | ||
352 | * @tty: terminal device | 398 | * @tty: terminal device |
353 | * @inbuf: user buffer | 399 | * @inbuf: user buffer |
354 | * @nr: number of bytes | 400 | * @nr: number of bytes |
@@ -358,26 +404,32 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
358 | * the simple cases normally found and helps to generate blocks of | 404 | * the simple cases normally found and helps to generate blocks of |
359 | * symbols for the console driver and thus improve performance. | 405 | * symbols for the console driver and thus improve performance. |
360 | * | 406 | * |
361 | * Called from n_tty_write under the tty layer write lock. Relies | 407 | * Locking: output_lock to protect column state and space left |
362 | * on lock_kernel for the tty->column state. | 408 | * (also, this is called from n_tty_write under the |
409 | * tty layer write lock) | ||
363 | */ | 410 | */ |
364 | 411 | ||
365 | static ssize_t opost_block(struct tty_struct *tty, | 412 | static ssize_t process_output_block(struct tty_struct *tty, |
366 | const unsigned char *buf, unsigned int nr) | 413 | const unsigned char *buf, unsigned int nr) |
367 | { | 414 | { |
368 | int space; | 415 | int space; |
369 | int i; | 416 | int i; |
370 | const unsigned char *cp; | 417 | const unsigned char *cp; |
371 | 418 | ||
419 | mutex_lock(&tty->output_lock); | ||
420 | |||
372 | space = tty_write_room(tty); | 421 | space = tty_write_room(tty); |
373 | if (!space) | 422 | if (!space) { |
423 | mutex_unlock(&tty->output_lock); | ||
374 | return 0; | 424 | return 0; |
425 | } | ||
375 | if (nr > space) | 426 | if (nr > space) |
376 | nr = space; | 427 | nr = space; |
377 | 428 | ||
378 | lock_kernel(); | ||
379 | for (i = 0, cp = buf; i < nr; i++, cp++) { | 429 | for (i = 0, cp = buf; i < nr; i++, cp++) { |
380 | switch (*cp) { | 430 | unsigned char c = *cp; |
431 | |||
432 | switch (c) { | ||
381 | case '\n': | 433 | case '\n': |
382 | if (O_ONLRET(tty)) | 434 | if (O_ONLRET(tty)) |
383 | tty->column = 0; | 435 | tty->column = 0; |
@@ -399,54 +451,403 @@ static ssize_t opost_block(struct tty_struct *tty, | |||
399 | tty->column--; | 451 | tty->column--; |
400 | break; | 452 | break; |
401 | default: | 453 | default: |
402 | if (O_OLCUC(tty)) | 454 | if (!iscntrl(c)) { |
403 | goto break_out; | 455 | if (O_OLCUC(tty)) |
404 | if (!iscntrl(*cp)) | 456 | goto break_out; |
405 | tty->column++; | 457 | if (!is_continuation(c, tty)) |
458 | tty->column++; | ||
459 | } | ||
406 | break; | 460 | break; |
407 | } | 461 | } |
408 | } | 462 | } |
409 | break_out: | 463 | break_out: |
410 | if (tty->ops->flush_chars) | ||
411 | tty->ops->flush_chars(tty); | ||
412 | i = tty->ops->write(tty, buf, i); | 464 | i = tty->ops->write(tty, buf, i); |
413 | unlock_kernel(); | 465 | |
466 | mutex_unlock(&tty->output_lock); | ||
414 | return i; | 467 | return i; |
415 | } | 468 | } |
416 | 469 | ||
470 | /** | ||
471 | * process_echoes - write pending echo characters | ||
472 | * @tty: terminal device | ||
473 | * | ||
474 | * Write previously buffered echo (and other ldisc-generated) | ||
475 | * characters to the tty. | ||
476 | * | ||
477 | * Characters generated by the ldisc (including echoes) need to | ||
478 | * be buffered because the driver's write buffer can fill during | ||
479 | * heavy program output. Echoing straight to the driver will | ||
480 | * often fail under these conditions, causing lost characters and | ||
481 | * resulting mismatches of ldisc state information. | ||
482 | * | ||
483 | * Since the ldisc state must represent the characters actually sent | ||
484 | * to the driver at the time of the write, operations like certain | ||
485 | * changes in column state are also saved in the buffer and executed | ||
486 | * here. | ||
487 | * | ||
488 | * A circular fifo buffer is used so that the most recent characters | ||
489 | * are prioritized. Also, when control characters are echoed with a | ||
490 | * prefixed "^", the pair is treated atomically and thus not separated. | ||
491 | * | ||
492 | * Locking: output_lock to protect column state and space left, | ||
493 | * echo_lock to protect the echo buffer | ||
494 | */ | ||
495 | |||
496 | static void process_echoes(struct tty_struct *tty) | ||
497 | { | ||
498 | int space, nr; | ||
499 | unsigned char c; | ||
500 | unsigned char *cp, *buf_end; | ||
501 | |||
502 | if (!tty->echo_cnt) | ||
503 | return; | ||
504 | |||
505 | mutex_lock(&tty->output_lock); | ||
506 | mutex_lock(&tty->echo_lock); | ||
507 | |||
508 | space = tty_write_room(tty); | ||
509 | |||
510 | buf_end = tty->echo_buf + N_TTY_BUF_SIZE; | ||
511 | cp = tty->echo_buf + tty->echo_pos; | ||
512 | nr = tty->echo_cnt; | ||
513 | while (nr > 0) { | ||
514 | c = *cp; | ||
515 | if (c == ECHO_OP_START) { | ||
516 | unsigned char op; | ||
517 | unsigned char *opp; | ||
518 | int no_space_left = 0; | ||
519 | |||
520 | /* | ||
521 | * If the buffer byte is the start of a multi-byte | ||
522 | * operation, get the next byte, which is either the | ||
523 | * op code or a control character value. | ||
524 | */ | ||
525 | opp = cp + 1; | ||
526 | if (opp == buf_end) | ||
527 | opp -= N_TTY_BUF_SIZE; | ||
528 | op = *opp; | ||
529 | |||
530 | switch (op) { | ||
531 | unsigned int num_chars, num_bs; | ||
532 | |||
533 | case ECHO_OP_ERASE_TAB: | ||
534 | if (++opp == buf_end) | ||
535 | opp -= N_TTY_BUF_SIZE; | ||
536 | num_chars = *opp; | ||
537 | |||
538 | /* | ||
539 | * Determine how many columns to go back | ||
540 | * in order to erase the tab. | ||
541 | * This depends on the number of columns | ||
542 | * used by other characters within the tab | ||
543 | * area. If this (modulo 8) count is from | ||
544 | * the start of input rather than from a | ||
545 | * previous tab, we offset by canon column. | ||
546 | * Otherwise, tab spacing is normal. | ||
547 | */ | ||
548 | if (!(num_chars & 0x80)) | ||
549 | num_chars += tty->canon_column; | ||
550 | num_bs = 8 - (num_chars & 7); | ||
551 | |||
552 | if (num_bs > space) { | ||
553 | no_space_left = 1; | ||
554 | break; | ||
555 | } | ||
556 | space -= num_bs; | ||
557 | while (num_bs--) { | ||
558 | tty_put_char(tty, '\b'); | ||
559 | if (tty->column > 0) | ||
560 | tty->column--; | ||
561 | } | ||
562 | cp += 3; | ||
563 | nr -= 3; | ||
564 | break; | ||
565 | |||
566 | case ECHO_OP_SET_CANON_COL: | ||
567 | tty->canon_column = tty->column; | ||
568 | cp += 2; | ||
569 | nr -= 2; | ||
570 | break; | ||
571 | |||
572 | case ECHO_OP_MOVE_BACK_COL: | ||
573 | if (tty->column > 0) | ||
574 | tty->column--; | ||
575 | cp += 2; | ||
576 | nr -= 2; | ||
577 | break; | ||
578 | |||
579 | case ECHO_OP_START: | ||
580 | /* This is an escaped echo op start code */ | ||
581 | if (!space) { | ||
582 | no_space_left = 1; | ||
583 | break; | ||
584 | } | ||
585 | tty_put_char(tty, ECHO_OP_START); | ||
586 | tty->column++; | ||
587 | space--; | ||
588 | cp += 2; | ||
589 | nr -= 2; | ||
590 | break; | ||
591 | |||
592 | default: | ||
593 | if (iscntrl(op)) { | ||
594 | if (L_ECHOCTL(tty)) { | ||
595 | /* | ||
596 | * Ensure there is enough space | ||
597 | * for the whole ctrl pair. | ||
598 | */ | ||
599 | if (space < 2) { | ||
600 | no_space_left = 1; | ||
601 | break; | ||
602 | } | ||
603 | tty_put_char(tty, '^'); | ||
604 | tty_put_char(tty, op ^ 0100); | ||
605 | tty->column += 2; | ||
606 | space -= 2; | ||
607 | } else { | ||
608 | if (!space) { | ||
609 | no_space_left = 1; | ||
610 | break; | ||
611 | } | ||
612 | tty_put_char(tty, op); | ||
613 | space--; | ||
614 | } | ||
615 | } | ||
616 | /* | ||
617 | * If above falls through, this was an | ||
618 | * undefined op. | ||
619 | */ | ||
620 | cp += 2; | ||
621 | nr -= 2; | ||
622 | } | ||
623 | |||
624 | if (no_space_left) | ||
625 | break; | ||
626 | } else { | ||
627 | int retval; | ||
628 | |||
629 | retval = do_output_char(c, tty, space); | ||
630 | if (retval < 0) | ||
631 | break; | ||
632 | space -= retval; | ||
633 | cp += 1; | ||
634 | nr -= 1; | ||
635 | } | ||
636 | |||
637 | /* When end of circular buffer reached, wrap around */ | ||
638 | if (cp >= buf_end) | ||
639 | cp -= N_TTY_BUF_SIZE; | ||
640 | } | ||
641 | |||
642 | if (nr == 0) { | ||
643 | tty->echo_pos = 0; | ||
644 | tty->echo_cnt = 0; | ||
645 | tty->echo_overrun = 0; | ||
646 | } else { | ||
647 | int num_processed = tty->echo_cnt - nr; | ||
648 | tty->echo_pos += num_processed; | ||
649 | tty->echo_pos &= N_TTY_BUF_SIZE - 1; | ||
650 | tty->echo_cnt = nr; | ||
651 | if (num_processed > 0) | ||
652 | tty->echo_overrun = 0; | ||
653 | } | ||
654 | |||
655 | mutex_unlock(&tty->echo_lock); | ||
656 | mutex_unlock(&tty->output_lock); | ||
657 | |||
658 | if (tty->ops->flush_chars) | ||
659 | tty->ops->flush_chars(tty); | ||
660 | } | ||
417 | 661 | ||
418 | /** | 662 | /** |
419 | * echo_char - echo characters | 663 | * add_echo_byte - add a byte to the echo buffer |
664 | * @c: unicode byte to echo | ||
665 | * @tty: terminal device | ||
666 | * | ||
667 | * Add a character or operation byte to the echo buffer. | ||
668 | * | ||
669 | * Should be called under the echo lock to protect the echo buffer. | ||
670 | */ | ||
671 | |||
672 | static void add_echo_byte(unsigned char c, struct tty_struct *tty) | ||
673 | { | ||
674 | int new_byte_pos; | ||
675 | |||
676 | if (tty->echo_cnt == N_TTY_BUF_SIZE) { | ||
677 | /* Circular buffer is already at capacity */ | ||
678 | new_byte_pos = tty->echo_pos; | ||
679 | |||
680 | /* | ||
681 | * Since the buffer start position needs to be advanced, | ||
682 | * be sure to step by a whole operation byte group. | ||
683 | */ | ||
684 | if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) { | ||
685 | if (tty->echo_buf[(tty->echo_pos + 1) & | ||
686 | (N_TTY_BUF_SIZE - 1)] == | ||
687 | ECHO_OP_ERASE_TAB) { | ||
688 | tty->echo_pos += 3; | ||
689 | tty->echo_cnt -= 2; | ||
690 | } else { | ||
691 | tty->echo_pos += 2; | ||
692 | tty->echo_cnt -= 1; | ||
693 | } | ||
694 | } else { | ||
695 | tty->echo_pos++; | ||
696 | } | ||
697 | tty->echo_pos &= N_TTY_BUF_SIZE - 1; | ||
698 | |||
699 | tty->echo_overrun = 1; | ||
700 | } else { | ||
701 | new_byte_pos = tty->echo_pos + tty->echo_cnt; | ||
702 | new_byte_pos &= N_TTY_BUF_SIZE - 1; | ||
703 | tty->echo_cnt++; | ||
704 | } | ||
705 | |||
706 | tty->echo_buf[new_byte_pos] = c; | ||
707 | } | ||
708 | |||
709 | /** | ||
710 | * echo_move_back_col - add operation to move back a column | ||
711 | * @tty: terminal device | ||
712 | * | ||
713 | * Add an operation to the echo buffer to move back one column. | ||
714 | * | ||
715 | * Locking: echo_lock to protect the echo buffer | ||
716 | */ | ||
717 | |||
718 | static void echo_move_back_col(struct tty_struct *tty) | ||
719 | { | ||
720 | mutex_lock(&tty->echo_lock); | ||
721 | |||
722 | add_echo_byte(ECHO_OP_START, tty); | ||
723 | add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty); | ||
724 | |||
725 | mutex_unlock(&tty->echo_lock); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * echo_set_canon_col - add operation to set the canon column | ||
730 | * @tty: terminal device | ||
731 | * | ||
732 | * Add an operation to the echo buffer to set the canon column | ||
733 | * to the current column. | ||
734 | * | ||
735 | * Locking: echo_lock to protect the echo buffer | ||
736 | */ | ||
737 | |||
738 | static void echo_set_canon_col(struct tty_struct *tty) | ||
739 | { | ||
740 | mutex_lock(&tty->echo_lock); | ||
741 | |||
742 | add_echo_byte(ECHO_OP_START, tty); | ||
743 | add_echo_byte(ECHO_OP_SET_CANON_COL, tty); | ||
744 | |||
745 | mutex_unlock(&tty->echo_lock); | ||
746 | } | ||
747 | |||
748 | /** | ||
749 | * echo_erase_tab - add operation to erase a tab | ||
750 | * @num_chars: number of character columns already used | ||
751 | * @after_tab: true if num_chars starts after a previous tab | ||
752 | * @tty: terminal device | ||
753 | * | ||
754 | * Add an operation to the echo buffer to erase a tab. | ||
755 | * | ||
756 | * Called by the eraser function, which knows how many character | ||
757 | * columns have been used since either a previous tab or the start | ||
758 | * of input. This information will be used later, along with | ||
759 | * canon column (if applicable), to go back the correct number | ||
760 | * of columns. | ||
761 | * | ||
762 | * Locking: echo_lock to protect the echo buffer | ||
763 | */ | ||
764 | |||
765 | static void echo_erase_tab(unsigned int num_chars, int after_tab, | ||
766 | struct tty_struct *tty) | ||
767 | { | ||
768 | mutex_lock(&tty->echo_lock); | ||
769 | |||
770 | add_echo_byte(ECHO_OP_START, tty); | ||
771 | add_echo_byte(ECHO_OP_ERASE_TAB, tty); | ||
772 | |||
773 | /* We only need to know this modulo 8 (tab spacing) */ | ||
774 | num_chars &= 7; | ||
775 | |||
776 | /* Set the high bit as a flag if num_chars is after a previous tab */ | ||
777 | if (after_tab) | ||
778 | num_chars |= 0x80; | ||
779 | |||
780 | add_echo_byte(num_chars, tty); | ||
781 | |||
782 | mutex_unlock(&tty->echo_lock); | ||
783 | } | ||
784 | |||
785 | /** | ||
786 | * echo_char_raw - echo a character raw | ||
420 | * @c: unicode byte to echo | 787 | * @c: unicode byte to echo |
421 | * @tty: terminal device | 788 | * @tty: terminal device |
422 | * | 789 | * |
423 | * Echo user input back onto the screen. This must be called only when | 790 | * Echo user input back onto the screen. This must be called only when |
424 | * L_ECHO(tty) is true. Called from the driver receive_buf path. | 791 | * L_ECHO(tty) is true. Called from the driver receive_buf path. |
425 | * | 792 | * |
426 | * Relies on BKL for tty column locking | 793 | * This variant does not treat control characters specially. |
794 | * | ||
795 | * Locking: echo_lock to protect the echo buffer | ||
796 | */ | ||
797 | |||
798 | static void echo_char_raw(unsigned char c, struct tty_struct *tty) | ||
799 | { | ||
800 | mutex_lock(&tty->echo_lock); | ||
801 | |||
802 | if (c == ECHO_OP_START) { | ||
803 | add_echo_byte(ECHO_OP_START, tty); | ||
804 | add_echo_byte(ECHO_OP_START, tty); | ||
805 | } else { | ||
806 | add_echo_byte(c, tty); | ||
807 | } | ||
808 | |||
809 | mutex_unlock(&tty->echo_lock); | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * echo_char - echo a character | ||
814 | * @c: unicode byte to echo | ||
815 | * @tty: terminal device | ||
816 | * | ||
817 | * Echo user input back onto the screen. This must be called only when | ||
818 | * L_ECHO(tty) is true. Called from the driver receive_buf path. | ||
819 | * | ||
820 | * This variant tags control characters to be possibly echoed as | ||
821 | * as "^X" (where X is the letter representing the control char). | ||
822 | * | ||
823 | * Locking: echo_lock to protect the echo buffer | ||
427 | */ | 824 | */ |
428 | 825 | ||
429 | static void echo_char(unsigned char c, struct tty_struct *tty) | 826 | static void echo_char(unsigned char c, struct tty_struct *tty) |
430 | { | 827 | { |
431 | if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { | 828 | mutex_lock(&tty->echo_lock); |
432 | tty_put_char(tty, '^'); | 829 | |
433 | tty_put_char(tty, c ^ 0100); | 830 | if (c == ECHO_OP_START) { |
434 | tty->column += 2; | 831 | add_echo_byte(ECHO_OP_START, tty); |
435 | } else | 832 | add_echo_byte(ECHO_OP_START, tty); |
436 | opost(c, tty); | 833 | } else { |
834 | if (iscntrl(c) && c != '\t') | ||
835 | add_echo_byte(ECHO_OP_START, tty); | ||
836 | add_echo_byte(c, tty); | ||
837 | } | ||
838 | |||
839 | mutex_unlock(&tty->echo_lock); | ||
437 | } | 840 | } |
438 | 841 | ||
439 | /** | 842 | /** |
440 | * finsh_erasing - complete erase | 843 | * finish_erasing - complete erase |
441 | * @tty: tty doing the erase | 844 | * @tty: tty doing the erase |
442 | * | ||
443 | * Relies on BKL for tty column locking | ||
444 | */ | 845 | */ |
846 | |||
445 | static inline void finish_erasing(struct tty_struct *tty) | 847 | static inline void finish_erasing(struct tty_struct *tty) |
446 | { | 848 | { |
447 | if (tty->erasing) { | 849 | if (tty->erasing) { |
448 | tty_put_char(tty, '/'); | 850 | echo_char_raw('/', tty); |
449 | tty->column++; | ||
450 | tty->erasing = 0; | 851 | tty->erasing = 0; |
451 | } | 852 | } |
452 | } | 853 | } |
@@ -460,7 +861,7 @@ static inline void finish_erasing(struct tty_struct *tty) | |||
460 | * present in the stream from the driver layer. Handles the complexities | 861 | * present in the stream from the driver layer. Handles the complexities |
461 | * of UTF-8 multibyte symbols. | 862 | * of UTF-8 multibyte symbols. |
462 | * | 863 | * |
463 | * Locking: read_lock for tty buffers, BKL for column/erasing state | 864 | * Locking: read_lock for tty buffers |
464 | */ | 865 | */ |
465 | 866 | ||
466 | static void eraser(unsigned char c, struct tty_struct *tty) | 867 | static void eraser(unsigned char c, struct tty_struct *tty) |
@@ -471,7 +872,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
471 | 872 | ||
472 | /* FIXME: locking needed ? */ | 873 | /* FIXME: locking needed ? */ |
473 | if (tty->read_head == tty->canon_head) { | 874 | if (tty->read_head == tty->canon_head) { |
474 | /* opost('\a', tty); */ /* what do you think? */ | 875 | /* process_output('\a', tty); */ /* what do you think? */ |
475 | return; | 876 | return; |
476 | } | 877 | } |
477 | if (c == ERASE_CHAR(tty)) | 878 | if (c == ERASE_CHAR(tty)) |
@@ -497,7 +898,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
497 | echo_char(KILL_CHAR(tty), tty); | 898 | echo_char(KILL_CHAR(tty), tty); |
498 | /* Add a newline if ECHOK is on and ECHOKE is off. */ | 899 | /* Add a newline if ECHOK is on and ECHOKE is off. */ |
499 | if (L_ECHOK(tty)) | 900 | if (L_ECHOK(tty)) |
500 | opost('\n', tty); | 901 | echo_char_raw('\n', tty); |
501 | return; | 902 | return; |
502 | } | 903 | } |
503 | kill_type = KILL; | 904 | kill_type = KILL; |
@@ -533,67 +934,61 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
533 | if (L_ECHO(tty)) { | 934 | if (L_ECHO(tty)) { |
534 | if (L_ECHOPRT(tty)) { | 935 | if (L_ECHOPRT(tty)) { |
535 | if (!tty->erasing) { | 936 | if (!tty->erasing) { |
536 | tty_put_char(tty, '\\'); | 937 | echo_char_raw('\\', tty); |
537 | tty->column++; | ||
538 | tty->erasing = 1; | 938 | tty->erasing = 1; |
539 | } | 939 | } |
540 | /* if cnt > 1, output a multi-byte character */ | 940 | /* if cnt > 1, output a multi-byte character */ |
541 | echo_char(c, tty); | 941 | echo_char(c, tty); |
542 | while (--cnt > 0) { | 942 | while (--cnt > 0) { |
543 | head = (head+1) & (N_TTY_BUF_SIZE-1); | 943 | head = (head+1) & (N_TTY_BUF_SIZE-1); |
544 | tty_put_char(tty, tty->read_buf[head]); | 944 | echo_char_raw(tty->read_buf[head], tty); |
945 | echo_move_back_col(tty); | ||
545 | } | 946 | } |
546 | } else if (kill_type == ERASE && !L_ECHOE(tty)) { | 947 | } else if (kill_type == ERASE && !L_ECHOE(tty)) { |
547 | echo_char(ERASE_CHAR(tty), tty); | 948 | echo_char(ERASE_CHAR(tty), tty); |
548 | } else if (c == '\t') { | 949 | } else if (c == '\t') { |
549 | unsigned int col = tty->canon_column; | 950 | unsigned int num_chars = 0; |
550 | unsigned long tail = tty->canon_head; | 951 | int after_tab = 0; |
551 | 952 | unsigned long tail = tty->read_head; | |
552 | /* Find the column of the last char. */ | 953 | |
553 | while (tail != tty->read_head) { | 954 | /* |
955 | * Count the columns used for characters | ||
956 | * since the start of input or after a | ||
957 | * previous tab. | ||
958 | * This info is used to go back the correct | ||
959 | * number of columns. | ||
960 | */ | ||
961 | while (tail != tty->canon_head) { | ||
962 | tail = (tail-1) & (N_TTY_BUF_SIZE-1); | ||
554 | c = tty->read_buf[tail]; | 963 | c = tty->read_buf[tail]; |
555 | if (c == '\t') | 964 | if (c == '\t') { |
556 | col = (col | 7) + 1; | 965 | after_tab = 1; |
557 | else if (iscntrl(c)) { | 966 | break; |
967 | } else if (iscntrl(c)) { | ||
558 | if (L_ECHOCTL(tty)) | 968 | if (L_ECHOCTL(tty)) |
559 | col += 2; | 969 | num_chars += 2; |
560 | } else if (!is_continuation(c, tty)) | 970 | } else if (!is_continuation(c, tty)) { |
561 | col++; | 971 | num_chars++; |
562 | tail = (tail+1) & (N_TTY_BUF_SIZE-1); | 972 | } |
563 | } | ||
564 | |||
565 | /* should never happen */ | ||
566 | if (tty->column > 0x80000000) | ||
567 | tty->column = 0; | ||
568 | |||
569 | /* Now backup to that column. */ | ||
570 | while (tty->column > col) { | ||
571 | /* Can't use opost here. */ | ||
572 | tty_put_char(tty, '\b'); | ||
573 | if (tty->column > 0) | ||
574 | tty->column--; | ||
575 | } | 973 | } |
974 | echo_erase_tab(num_chars, after_tab, tty); | ||
576 | } else { | 975 | } else { |
577 | if (iscntrl(c) && L_ECHOCTL(tty)) { | 976 | if (iscntrl(c) && L_ECHOCTL(tty)) { |
578 | tty_put_char(tty, '\b'); | 977 | echo_char_raw('\b', tty); |
579 | tty_put_char(tty, ' '); | 978 | echo_char_raw(' ', tty); |
580 | tty_put_char(tty, '\b'); | 979 | echo_char_raw('\b', tty); |
581 | if (tty->column > 0) | ||
582 | tty->column--; | ||
583 | } | 980 | } |
584 | if (!iscntrl(c) || L_ECHOCTL(tty)) { | 981 | if (!iscntrl(c) || L_ECHOCTL(tty)) { |
585 | tty_put_char(tty, '\b'); | 982 | echo_char_raw('\b', tty); |
586 | tty_put_char(tty, ' '); | 983 | echo_char_raw(' ', tty); |
587 | tty_put_char(tty, '\b'); | 984 | echo_char_raw('\b', tty); |
588 | if (tty->column > 0) | ||
589 | tty->column--; | ||
590 | } | 985 | } |
591 | } | 986 | } |
592 | } | 987 | } |
593 | if (kill_type == ERASE) | 988 | if (kill_type == ERASE) |
594 | break; | 989 | break; |
595 | } | 990 | } |
596 | if (tty->read_head == tty->canon_head) | 991 | if (tty->read_head == tty->canon_head && L_ECHO(tty)) |
597 | finish_erasing(tty); | 992 | finish_erasing(tty); |
598 | } | 993 | } |
599 | 994 | ||
@@ -712,6 +1107,7 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty, | |||
712 | static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | 1107 | static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) |
713 | { | 1108 | { |
714 | unsigned long flags; | 1109 | unsigned long flags; |
1110 | int parmrk; | ||
715 | 1111 | ||
716 | if (tty->raw) { | 1112 | if (tty->raw) { |
717 | put_tty_queue(c, tty); | 1113 | put_tty_queue(c, tty); |
@@ -721,18 +1117,21 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
721 | if (I_ISTRIP(tty)) | 1117 | if (I_ISTRIP(tty)) |
722 | c &= 0x7f; | 1118 | c &= 0x7f; |
723 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 1119 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
724 | c=tolower(c); | 1120 | c = tolower(c); |
725 | 1121 | ||
726 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | 1122 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && |
727 | ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) || | 1123 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && |
728 | c == INTR_CHAR(tty) || c == QUIT_CHAR(tty) || c == SUSP_CHAR(tty))) | 1124 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { |
729 | start_tty(tty); | 1125 | start_tty(tty); |
1126 | process_echoes(tty); | ||
1127 | } | ||
730 | 1128 | ||
731 | if (tty->closing) { | 1129 | if (tty->closing) { |
732 | if (I_IXON(tty)) { | 1130 | if (I_IXON(tty)) { |
733 | if (c == START_CHAR(tty)) | 1131 | if (c == START_CHAR(tty)) { |
734 | start_tty(tty); | 1132 | start_tty(tty); |
735 | else if (c == STOP_CHAR(tty)) | 1133 | process_echoes(tty); |
1134 | } else if (c == STOP_CHAR(tty)) | ||
736 | stop_tty(tty); | 1135 | stop_tty(tty); |
737 | } | 1136 | } |
738 | return; | 1137 | return; |
@@ -745,19 +1144,23 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
745 | * up. | 1144 | * up. |
746 | */ | 1145 | */ |
747 | if (!test_bit(c, tty->process_char_map) || tty->lnext) { | 1146 | if (!test_bit(c, tty->process_char_map) || tty->lnext) { |
748 | finish_erasing(tty); | ||
749 | tty->lnext = 0; | 1147 | tty->lnext = 0; |
1148 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; | ||
1149 | if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { | ||
1150 | /* beep if no space */ | ||
1151 | if (L_ECHO(tty)) | ||
1152 | process_output('\a', tty); | ||
1153 | return; | ||
1154 | } | ||
750 | if (L_ECHO(tty)) { | 1155 | if (L_ECHO(tty)) { |
751 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { | 1156 | finish_erasing(tty); |
752 | tty_put_char(tty, '\a'); /* beep if no space */ | ||
753 | return; | ||
754 | } | ||
755 | /* Record the column of first canon char. */ | 1157 | /* Record the column of first canon char. */ |
756 | if (tty->canon_head == tty->read_head) | 1158 | if (tty->canon_head == tty->read_head) |
757 | tty->canon_column = tty->column; | 1159 | echo_set_canon_col(tty); |
758 | echo_char(c, tty); | 1160 | echo_char(c, tty); |
1161 | process_echoes(tty); | ||
759 | } | 1162 | } |
760 | if (I_PARMRK(tty) && c == (unsigned char) '\377') | 1163 | if (parmrk) |
761 | put_tty_queue(c, tty); | 1164 | put_tty_queue(c, tty); |
762 | put_tty_queue(c, tty); | 1165 | put_tty_queue(c, tty); |
763 | return; | 1166 | return; |
@@ -766,6 +1169,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
766 | if (I_IXON(tty)) { | 1169 | if (I_IXON(tty)) { |
767 | if (c == START_CHAR(tty)) { | 1170 | if (c == START_CHAR(tty)) { |
768 | start_tty(tty); | 1171 | start_tty(tty); |
1172 | process_echoes(tty); | ||
769 | return; | 1173 | return; |
770 | } | 1174 | } |
771 | if (c == STOP_CHAR(tty)) { | 1175 | if (c == STOP_CHAR(tty)) { |
@@ -786,7 +1190,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
786 | if (c == SUSP_CHAR(tty)) { | 1190 | if (c == SUSP_CHAR(tty)) { |
787 | send_signal: | 1191 | send_signal: |
788 | /* | 1192 | /* |
789 | * Echo character, and then send the signal. | ||
790 | * Note that we do not use isig() here because we want | 1193 | * Note that we do not use isig() here because we want |
791 | * the order to be: | 1194 | * the order to be: |
792 | * 1) flush, 2) echo, 3) signal | 1195 | * 1) flush, 2) echo, 3) signal |
@@ -795,8 +1198,12 @@ send_signal: | |||
795 | n_tty_flush_buffer(tty); | 1198 | n_tty_flush_buffer(tty); |
796 | tty_driver_flush_buffer(tty); | 1199 | tty_driver_flush_buffer(tty); |
797 | } | 1200 | } |
798 | if (L_ECHO(tty)) | 1201 | if (I_IXON(tty)) |
1202 | start_tty(tty); | ||
1203 | if (L_ECHO(tty)) { | ||
799 | echo_char(c, tty); | 1204 | echo_char(c, tty); |
1205 | process_echoes(tty); | ||
1206 | } | ||
800 | if (tty->pgrp) | 1207 | if (tty->pgrp) |
801 | kill_pgrp(tty->pgrp, signal, 1); | 1208 | kill_pgrp(tty->pgrp, signal, 1); |
802 | return; | 1209 | return; |
@@ -815,6 +1222,7 @@ send_signal: | |||
815 | if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || | 1222 | if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || |
816 | (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { | 1223 | (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { |
817 | eraser(c, tty); | 1224 | eraser(c, tty); |
1225 | process_echoes(tty); | ||
818 | return; | 1226 | return; |
819 | } | 1227 | } |
820 | if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { | 1228 | if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { |
@@ -822,8 +1230,9 @@ send_signal: | |||
822 | if (L_ECHO(tty)) { | 1230 | if (L_ECHO(tty)) { |
823 | finish_erasing(tty); | 1231 | finish_erasing(tty); |
824 | if (L_ECHOCTL(tty)) { | 1232 | if (L_ECHOCTL(tty)) { |
825 | tty_put_char(tty, '^'); | 1233 | echo_char_raw('^', tty); |
826 | tty_put_char(tty, '\b'); | 1234 | echo_char_raw('\b', tty); |
1235 | process_echoes(tty); | ||
827 | } | 1236 | } |
828 | } | 1237 | } |
829 | return; | 1238 | return; |
@@ -834,22 +1243,29 @@ send_signal: | |||
834 | 1243 | ||
835 | finish_erasing(tty); | 1244 | finish_erasing(tty); |
836 | echo_char(c, tty); | 1245 | echo_char(c, tty); |
837 | opost('\n', tty); | 1246 | echo_char_raw('\n', tty); |
838 | while (tail != tty->read_head) { | 1247 | while (tail != tty->read_head) { |
839 | echo_char(tty->read_buf[tail], tty); | 1248 | echo_char(tty->read_buf[tail], tty); |
840 | tail = (tail+1) & (N_TTY_BUF_SIZE-1); | 1249 | tail = (tail+1) & (N_TTY_BUF_SIZE-1); |
841 | } | 1250 | } |
1251 | process_echoes(tty); | ||
842 | return; | 1252 | return; |
843 | } | 1253 | } |
844 | if (c == '\n') { | 1254 | if (c == '\n') { |
1255 | if (tty->read_cnt >= N_TTY_BUF_SIZE) { | ||
1256 | if (L_ECHO(tty)) | ||
1257 | process_output('\a', tty); | ||
1258 | return; | ||
1259 | } | ||
845 | if (L_ECHO(tty) || L_ECHONL(tty)) { | 1260 | if (L_ECHO(tty) || L_ECHONL(tty)) { |
846 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) | 1261 | echo_char_raw('\n', tty); |
847 | tty_put_char(tty, '\a'); | 1262 | process_echoes(tty); |
848 | opost('\n', tty); | ||
849 | } | 1263 | } |
850 | goto handle_newline; | 1264 | goto handle_newline; |
851 | } | 1265 | } |
852 | if (c == EOF_CHAR(tty)) { | 1266 | if (c == EOF_CHAR(tty)) { |
1267 | if (tty->read_cnt >= N_TTY_BUF_SIZE) | ||
1268 | return; | ||
853 | if (tty->canon_head != tty->read_head) | 1269 | if (tty->canon_head != tty->read_head) |
854 | set_bit(TTY_PUSH, &tty->flags); | 1270 | set_bit(TTY_PUSH, &tty->flags); |
855 | c = __DISABLED_CHAR; | 1271 | c = __DISABLED_CHAR; |
@@ -857,22 +1273,28 @@ send_signal: | |||
857 | } | 1273 | } |
858 | if ((c == EOL_CHAR(tty)) || | 1274 | if ((c == EOL_CHAR(tty)) || |
859 | (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { | 1275 | (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { |
1276 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) | ||
1277 | ? 1 : 0; | ||
1278 | if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) { | ||
1279 | if (L_ECHO(tty)) | ||
1280 | process_output('\a', tty); | ||
1281 | return; | ||
1282 | } | ||
860 | /* | 1283 | /* |
861 | * XXX are EOL_CHAR and EOL2_CHAR echoed?!? | 1284 | * XXX are EOL_CHAR and EOL2_CHAR echoed?!? |
862 | */ | 1285 | */ |
863 | if (L_ECHO(tty)) { | 1286 | if (L_ECHO(tty)) { |
864 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) | ||
865 | tty_put_char(tty, '\a'); | ||
866 | /* Record the column of first canon char. */ | 1287 | /* Record the column of first canon char. */ |
867 | if (tty->canon_head == tty->read_head) | 1288 | if (tty->canon_head == tty->read_head) |
868 | tty->canon_column = tty->column; | 1289 | echo_set_canon_col(tty); |
869 | echo_char(c, tty); | 1290 | echo_char(c, tty); |
1291 | process_echoes(tty); | ||
870 | } | 1292 | } |
871 | /* | 1293 | /* |
872 | * XXX does PARMRK doubling happen for | 1294 | * XXX does PARMRK doubling happen for |
873 | * EOL_CHAR and EOL2_CHAR? | 1295 | * EOL_CHAR and EOL2_CHAR? |
874 | */ | 1296 | */ |
875 | if (I_PARMRK(tty) && c == (unsigned char) '\377') | 1297 | if (parmrk) |
876 | put_tty_queue(c, tty); | 1298 | put_tty_queue(c, tty); |
877 | 1299 | ||
878 | handle_newline: | 1300 | handle_newline: |
@@ -889,23 +1311,27 @@ handle_newline: | |||
889 | } | 1311 | } |
890 | } | 1312 | } |
891 | 1313 | ||
892 | finish_erasing(tty); | 1314 | parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; |
1315 | if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { | ||
1316 | /* beep if no space */ | ||
1317 | if (L_ECHO(tty)) | ||
1318 | process_output('\a', tty); | ||
1319 | return; | ||
1320 | } | ||
893 | if (L_ECHO(tty)) { | 1321 | if (L_ECHO(tty)) { |
894 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { | 1322 | finish_erasing(tty); |
895 | tty_put_char(tty, '\a'); /* beep if no space */ | ||
896 | return; | ||
897 | } | ||
898 | if (c == '\n') | 1323 | if (c == '\n') |
899 | opost('\n', tty); | 1324 | echo_char_raw('\n', tty); |
900 | else { | 1325 | else { |
901 | /* Record the column of first canon char. */ | 1326 | /* Record the column of first canon char. */ |
902 | if (tty->canon_head == tty->read_head) | 1327 | if (tty->canon_head == tty->read_head) |
903 | tty->canon_column = tty->column; | 1328 | echo_set_canon_col(tty); |
904 | echo_char(c, tty); | 1329 | echo_char(c, tty); |
905 | } | 1330 | } |
1331 | process_echoes(tty); | ||
906 | } | 1332 | } |
907 | 1333 | ||
908 | if (I_PARMRK(tty) && c == (unsigned char) '\377') | 1334 | if (parmrk) |
909 | put_tty_queue(c, tty); | 1335 | put_tty_queue(c, tty); |
910 | 1336 | ||
911 | put_tty_queue(c, tty); | 1337 | put_tty_queue(c, tty); |
@@ -923,10 +1349,11 @@ handle_newline: | |||
923 | 1349 | ||
924 | static void n_tty_write_wakeup(struct tty_struct *tty) | 1350 | static void n_tty_write_wakeup(struct tty_struct *tty) |
925 | { | 1351 | { |
926 | if (tty->fasync) { | 1352 | /* Write out any echoed characters that are still pending */ |
927 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | 1353 | process_echoes(tty); |
1354 | |||
1355 | if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) | ||
928 | kill_fasync(&tty->fasync, SIGIO, POLL_OUT); | 1356 | kill_fasync(&tty->fasync, SIGIO, POLL_OUT); |
929 | } | ||
930 | } | 1357 | } |
931 | 1358 | ||
932 | /** | 1359 | /** |
@@ -1134,6 +1561,10 @@ static void n_tty_close(struct tty_struct *tty) | |||
1134 | free_buf(tty->read_buf); | 1561 | free_buf(tty->read_buf); |
1135 | tty->read_buf = NULL; | 1562 | tty->read_buf = NULL; |
1136 | } | 1563 | } |
1564 | if (tty->echo_buf) { | ||
1565 | free_buf(tty->echo_buf); | ||
1566 | tty->echo_buf = NULL; | ||
1567 | } | ||
1137 | } | 1568 | } |
1138 | 1569 | ||
1139 | /** | 1570 | /** |
@@ -1151,13 +1582,19 @@ static int n_tty_open(struct tty_struct *tty) | |||
1151 | if (!tty) | 1582 | if (!tty) |
1152 | return -EINVAL; | 1583 | return -EINVAL; |
1153 | 1584 | ||
1154 | /* This one is ugly. Currently a malloc failure here can panic */ | 1585 | /* These are ugly. Currently a malloc failure here can panic */ |
1155 | if (!tty->read_buf) { | 1586 | if (!tty->read_buf) { |
1156 | tty->read_buf = alloc_buf(); | 1587 | tty->read_buf = alloc_buf(); |
1157 | if (!tty->read_buf) | 1588 | if (!tty->read_buf) |
1158 | return -ENOMEM; | 1589 | return -ENOMEM; |
1159 | } | 1590 | } |
1591 | if (!tty->echo_buf) { | ||
1592 | tty->echo_buf = alloc_buf(); | ||
1593 | if (!tty->echo_buf) | ||
1594 | return -ENOMEM; | ||
1595 | } | ||
1160 | memset(tty->read_buf, 0, N_TTY_BUF_SIZE); | 1596 | memset(tty->read_buf, 0, N_TTY_BUF_SIZE); |
1597 | memset(tty->echo_buf, 0, N_TTY_BUF_SIZE); | ||
1161 | reset_buffer_flags(tty); | 1598 | reset_buffer_flags(tty); |
1162 | tty->column = 0; | 1599 | tty->column = 0; |
1163 | n_tty_set_termios(tty, NULL); | 1600 | n_tty_set_termios(tty, NULL); |
@@ -1487,16 +1924,23 @@ do_it_again: | |||
1487 | * @buf: userspace buffer pointer | 1924 | * @buf: userspace buffer pointer |
1488 | * @nr: size of I/O | 1925 | * @nr: size of I/O |
1489 | * | 1926 | * |
1490 | * Write function of the terminal device. This is serialized with | 1927 | * Write function of the terminal device. This is serialized with |
1491 | * respect to other write callers but not to termios changes, reads | 1928 | * respect to other write callers but not to termios changes, reads |
1492 | * and other such events. We must be careful with N_TTY as the receive | 1929 | * and other such events. Since the receive code will echo characters, |
1493 | * code will echo characters, thus calling driver write methods. | 1930 | * thus calling driver write methods, the output_lock is used in |
1931 | * the output processing functions called here as well as in the | ||
1932 | * echo processing function to protect the column state and space | ||
1933 | * left in the buffer. | ||
1494 | * | 1934 | * |
1495 | * This code must be sure never to sleep through a hangup. | 1935 | * This code must be sure never to sleep through a hangup. |
1936 | * | ||
1937 | * Locking: output_lock to protect column state and space left | ||
1938 | * (note that the process_output*() functions take this | ||
1939 | * lock themselves) | ||
1496 | */ | 1940 | */ |
1497 | 1941 | ||
1498 | static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | 1942 | static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, |
1499 | const unsigned char *buf, size_t nr) | 1943 | const unsigned char *buf, size_t nr) |
1500 | { | 1944 | { |
1501 | const unsigned char *b = buf; | 1945 | const unsigned char *b = buf; |
1502 | DECLARE_WAITQUEUE(wait, current); | 1946 | DECLARE_WAITQUEUE(wait, current); |
@@ -1510,6 +1954,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
1510 | return retval; | 1954 | return retval; |
1511 | } | 1955 | } |
1512 | 1956 | ||
1957 | /* Write out any echoed characters that are still pending */ | ||
1958 | process_echoes(tty); | ||
1959 | |||
1513 | add_wait_queue(&tty->write_wait, &wait); | 1960 | add_wait_queue(&tty->write_wait, &wait); |
1514 | while (1) { | 1961 | while (1) { |
1515 | set_current_state(TASK_INTERRUPTIBLE); | 1962 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -1523,7 +1970,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
1523 | } | 1970 | } |
1524 | if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { | 1971 | if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { |
1525 | while (nr > 0) { | 1972 | while (nr > 0) { |
1526 | ssize_t num = opost_block(tty, b, nr); | 1973 | ssize_t num = process_output_block(tty, b, nr); |
1527 | if (num < 0) { | 1974 | if (num < 0) { |
1528 | if (num == -EAGAIN) | 1975 | if (num == -EAGAIN) |
1529 | break; | 1976 | break; |
@@ -1535,7 +1982,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
1535 | if (nr == 0) | 1982 | if (nr == 0) |
1536 | break; | 1983 | break; |
1537 | c = *b; | 1984 | c = *b; |
1538 | if (opost(c, tty) < 0) | 1985 | if (process_output(c, tty) < 0) |
1539 | break; | 1986 | break; |
1540 | b++; nr--; | 1987 | b++; nr--; |
1541 | } | 1988 | } |
@@ -1565,6 +2012,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, | |||
1565 | break_out: | 2012 | break_out: |
1566 | __set_current_state(TASK_RUNNING); | 2013 | __set_current_state(TASK_RUNNING); |
1567 | remove_wait_queue(&tty->write_wait, &wait); | 2014 | remove_wait_queue(&tty->write_wait, &wait); |
2015 | if (b - buf != nr && tty->fasync) | ||
2016 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
1568 | return (b - buf) ? b - buf : retval; | 2017 | return (b - buf) ? b - buf : retval; |
1569 | } | 2018 | } |
1570 | 2019 | ||
@@ -1663,4 +2112,3 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
1663 | .receive_buf = n_tty_receive_buf, | 2112 | .receive_buf = n_tty_receive_buf, |
1664 | .write_wakeup = n_tty_write_wakeup | 2113 | .write_wakeup = n_tty_write_wakeup |
1665 | }; | 2114 | }; |
1666 | |||
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 9a34a1935283..d6102b644b55 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -353,6 +353,7 @@ struct ctrl_ul { | |||
353 | 353 | ||
354 | /* This holds all information that is needed regarding a port */ | 354 | /* This holds all information that is needed regarding a port */ |
355 | struct port { | 355 | struct port { |
356 | struct tty_port port; | ||
356 | u8 update_flow_control; | 357 | u8 update_flow_control; |
357 | struct ctrl_ul ctrl_ul; | 358 | struct ctrl_ul ctrl_ul; |
358 | struct ctrl_dl ctrl_dl; | 359 | struct ctrl_dl ctrl_dl; |
@@ -365,8 +366,6 @@ struct port { | |||
365 | u8 toggle_ul; | 366 | u8 toggle_ul; |
366 | u16 token_dl; | 367 | u16 token_dl; |
367 | 368 | ||
368 | struct tty_struct *tty; | ||
369 | int tty_open_count; | ||
370 | /* mutex to ensure one access patch to this port */ | 369 | /* mutex to ensure one access patch to this port */ |
371 | struct mutex tty_sem; | 370 | struct mutex tty_sem; |
372 | wait_queue_head_t tty_wait; | 371 | wait_queue_head_t tty_wait; |
@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc) | |||
788 | * Return 1 - send buffer to card and ack. | 787 | * Return 1 - send buffer to card and ack. |
789 | * Return 0 - don't ack, don't send buffer to card. | 788 | * Return 0 - don't ack, don't send buffer to card. |
790 | */ | 789 | */ |
791 | static int send_data(enum port_type index, const struct nozomi *dc) | 790 | static int send_data(enum port_type index, struct nozomi *dc) |
792 | { | 791 | { |
793 | u32 size = 0; | 792 | u32 size = 0; |
794 | const struct port *port = &dc->port[index]; | 793 | struct port *port = &dc->port[index]; |
795 | const u8 toggle = port->toggle_ul; | 794 | const u8 toggle = port->toggle_ul; |
796 | void __iomem *addr = port->ul_addr[toggle]; | 795 | void __iomem *addr = port->ul_addr[toggle]; |
797 | const u32 ul_size = port->ul_size[toggle]; | 796 | const u32 ul_size = port->ul_size[toggle]; |
798 | struct tty_struct *tty = port->tty; | 797 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
799 | 798 | ||
800 | /* Get data from tty and place in buf for now */ | 799 | /* Get data from tty and place in buf for now */ |
801 | size = __kfifo_get(port->fifo_ul, dc->send_buf, | 800 | size = __kfifo_get(port->fifo_ul, dc->send_buf, |
@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) | |||
803 | 802 | ||
804 | if (size == 0) { | 803 | if (size == 0) { |
805 | DBG4("No more data to send, disable link:"); | 804 | DBG4("No more data to send, disable link:"); |
805 | tty_kref_put(tty); | ||
806 | return 0; | 806 | return 0; |
807 | } | 807 | } |
808 | 808 | ||
@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) | |||
815 | if (tty) | 815 | if (tty) |
816 | tty_wakeup(tty); | 816 | tty_wakeup(tty); |
817 | 817 | ||
818 | tty_kref_put(tty); | ||
818 | return 1; | 819 | return 1; |
819 | } | 820 | } |
820 | 821 | ||
@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
826 | u32 offset = 4; | 827 | u32 offset = 4; |
827 | struct port *port = &dc->port[index]; | 828 | struct port *port = &dc->port[index]; |
828 | void __iomem *addr = port->dl_addr[port->toggle_dl]; | 829 | void __iomem *addr = port->dl_addr[port->toggle_dl]; |
829 | struct tty_struct *tty = port->tty; | 830 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
830 | int i; | 831 | int i; |
831 | 832 | ||
832 | if (unlikely(!tty)) { | 833 | if (unlikely(!tty)) { |
@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) | |||
870 | } | 871 | } |
871 | 872 | ||
872 | set_bit(index, &dc->flip); | 873 | set_bit(index, &dc->flip); |
873 | 874 | tty_kref_put(tty); | |
874 | return 1; | 875 | return 1; |
875 | } | 876 | } |
876 | 877 | ||
@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) | |||
1276 | 1277 | ||
1277 | exit_handler: | 1278 | exit_handler: |
1278 | spin_unlock(&dc->spin_mutex); | 1279 | spin_unlock(&dc->spin_mutex); |
1279 | for (a = 0; a < NOZOMI_MAX_PORTS; a++) | 1280 | for (a = 0; a < NOZOMI_MAX_PORTS; a++) { |
1280 | if (test_and_clear_bit(a, &dc->flip)) | 1281 | struct tty_struct *tty; |
1281 | tty_flip_buffer_push(dc->port[a].tty); | 1282 | if (test_and_clear_bit(a, &dc->flip)) { |
1283 | tty = tty_port_tty_get(&dc->port[a].port); | ||
1284 | if (tty) | ||
1285 | tty_flip_buffer_push(tty); | ||
1286 | tty_kref_put(tty); | ||
1287 | } | ||
1288 | } | ||
1282 | return IRQ_HANDLED; | 1289 | return IRQ_HANDLED; |
1283 | none: | 1290 | none: |
1284 | spin_unlock(&dc->spin_mutex); | 1291 | spin_unlock(&dc->spin_mutex); |
@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1453 | 1460 | ||
1454 | for (i = 0; i < MAX_PORT; i++) { | 1461 | for (i = 0; i < MAX_PORT; i++) { |
1455 | mutex_init(&dc->port[i].tty_sem); | 1462 | mutex_init(&dc->port[i].tty_sem); |
1456 | dc->port[i].tty_open_count = 0; | 1463 | tty_port_init(&dc->port[i].port); |
1457 | dc->port[i].tty = NULL; | ||
1458 | tty_register_device(ntty_driver, dc->index_start + i, | 1464 | tty_register_device(ntty_driver, dc->index_start + i, |
1459 | &pdev->dev); | 1465 | &pdev->dev); |
1460 | } | 1466 | } |
1461 | |||
1462 | return 0; | 1467 | return 0; |
1463 | 1468 | ||
1464 | err_free_sbuf: | 1469 | err_free_sbuf: |
@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc) | |||
1482 | 1487 | ||
1483 | flush_scheduled_work(); | 1488 | flush_scheduled_work(); |
1484 | 1489 | ||
1485 | for (i = 0; i < MAX_PORT; ++i) | 1490 | for (i = 0; i < MAX_PORT; ++i) { |
1486 | if (dc->port[i].tty && \ | 1491 | struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); |
1487 | list_empty(&dc->port[i].tty->hangup_work.entry)) | 1492 | if (tty && list_empty(&tty->hangup_work.entry)) |
1488 | tty_hangup(dc->port[i].tty); | 1493 | tty_hangup(tty); |
1489 | 1494 | tty_kref_put(tty); | |
1495 | } | ||
1496 | /* Racy below - surely should wait for scheduled work to be done or | ||
1497 | complete off a hangup method ? */ | ||
1490 | while (dc->open_ttys) | 1498 | while (dc->open_ttys) |
1491 | msleep(1); | 1499 | msleep(1); |
1492 | |||
1493 | for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) | 1500 | for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) |
1494 | tty_unregister_device(ntty_driver, i); | 1501 | tty_unregister_device(ntty_driver, i); |
1495 | } | 1502 | } |
@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
1579 | if (mutex_lock_interruptible(&port->tty_sem)) | 1586 | if (mutex_lock_interruptible(&port->tty_sem)) |
1580 | return -ERESTARTSYS; | 1587 | return -ERESTARTSYS; |
1581 | 1588 | ||
1582 | port->tty_open_count++; | 1589 | port->port.count++; |
1583 | dc->open_ttys++; | 1590 | dc->open_ttys++; |
1584 | 1591 | ||
1585 | /* Enable interrupt downlink for channel */ | 1592 | /* Enable interrupt downlink for channel */ |
1586 | if (port->tty_open_count == 1) { | 1593 | if (port->port.count == 1) { |
1594 | /* FIXME: is this needed now ? */ | ||
1587 | tty->low_latency = 1; | 1595 | tty->low_latency = 1; |
1588 | tty->driver_data = port; | 1596 | tty->driver_data = port; |
1589 | port->tty = tty; | 1597 | tty_port_tty_set(&port->port, tty); |
1590 | DBG1("open: %d", port->token_dl); | 1598 | DBG1("open: %d", port->token_dl); |
1591 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1599 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1592 | dc->last_ier = dc->last_ier | port->token_dl; | 1600 | dc->last_ier = dc->last_ier | port->token_dl; |
1593 | writew(dc->last_ier, dc->reg_ier); | 1601 | writew(dc->last_ier, dc->reg_ier); |
1594 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1602 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1595 | } | 1603 | } |
1596 | |||
1597 | mutex_unlock(&port->tty_sem); | 1604 | mutex_unlock(&port->tty_sem); |
1598 | |||
1599 | return 0; | 1605 | return 0; |
1600 | } | 1606 | } |
1601 | 1607 | ||
@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
1606 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1612 | static void ntty_close(struct tty_struct *tty, struct file *file) |
1607 | { | 1613 | { |
1608 | struct nozomi *dc = get_dc_by_tty(tty); | 1614 | struct nozomi *dc = get_dc_by_tty(tty); |
1609 | struct port *port = tty->driver_data; | 1615 | struct port *nport = tty->driver_data; |
1616 | struct tty_port *port = &nport->port; | ||
1610 | unsigned long flags; | 1617 | unsigned long flags; |
1611 | 1618 | ||
1612 | if (!dc || !port) | 1619 | if (!dc || !nport) |
1613 | return; | 1620 | return; |
1614 | 1621 | ||
1615 | if (mutex_lock_interruptible(&port->tty_sem)) | 1622 | /* Users cannot interrupt a close */ |
1616 | return; | 1623 | mutex_lock(&nport->tty_sem); |
1617 | 1624 | ||
1618 | if (!port->tty_open_count) | 1625 | WARN_ON(!port->count); |
1619 | goto exit; | ||
1620 | 1626 | ||
1621 | dc->open_ttys--; | 1627 | dc->open_ttys--; |
1622 | port->tty_open_count--; | 1628 | port->count--; |
1629 | tty_port_tty_set(port, NULL); | ||
1623 | 1630 | ||
1624 | if (port->tty_open_count == 0) { | 1631 | if (port->count == 0) { |
1625 | DBG1("close: %d", port->token_dl); | 1632 | DBG1("close: %d", nport->token_dl); |
1626 | spin_lock_irqsave(&dc->spin_mutex, flags); | 1633 | spin_lock_irqsave(&dc->spin_mutex, flags); |
1627 | dc->last_ier &= ~(port->token_dl); | 1634 | dc->last_ier &= ~(nport->token_dl); |
1628 | writew(dc->last_ier, dc->reg_ier); | 1635 | writew(dc->last_ier, dc->reg_ier); |
1629 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1636 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1630 | } | 1637 | } |
1631 | 1638 | mutex_unlock(&nport->tty_sem); | |
1632 | exit: | ||
1633 | mutex_unlock(&port->tty_sem); | ||
1634 | } | 1639 | } |
1635 | 1640 | ||
1636 | /* | 1641 | /* |
@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1660 | return -EAGAIN; | 1665 | return -EAGAIN; |
1661 | } | 1666 | } |
1662 | 1667 | ||
1663 | if (unlikely(!port->tty_open_count)) { | 1668 | if (unlikely(!port->port.count)) { |
1664 | DBG1(" "); | 1669 | DBG1(" "); |
1665 | goto exit; | 1670 | goto exit; |
1666 | } | 1671 | } |
@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty) | |||
1710 | if (!mutex_trylock(&port->tty_sem)) | 1715 | if (!mutex_trylock(&port->tty_sem)) |
1711 | return 0; | 1716 | return 0; |
1712 | 1717 | ||
1713 | if (!port->tty_open_count) | 1718 | if (!port->port.count) |
1714 | goto exit; | 1719 | goto exit; |
1715 | 1720 | ||
1716 | room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); | 1721 | room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); |
@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) | |||
1866 | goto exit_in_buffer; | 1871 | goto exit_in_buffer; |
1867 | } | 1872 | } |
1868 | 1873 | ||
1869 | if (unlikely(!port->tty_open_count)) { | 1874 | if (unlikely(!port->port.count)) { |
1870 | dev_err(&dc->pdev->dev, "No tty open?\n"); | 1875 | dev_err(&dc->pdev->dev, "No tty open?\n"); |
1871 | rval = -ENODEV; | 1876 | rval = -ENODEV; |
1872 | goto exit_in_buffer; | 1877 | goto exit_in_buffer; |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 4d64a02612a4..dc073e167abc 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -138,20 +138,15 @@ struct _input_signal_events { | |||
138 | */ | 138 | */ |
139 | 139 | ||
140 | typedef struct _mgslpc_info { | 140 | typedef struct _mgslpc_info { |
141 | struct tty_port port; | ||
141 | void *if_ptr; /* General purpose pointer (used by SPPP) */ | 142 | void *if_ptr; /* General purpose pointer (used by SPPP) */ |
142 | int magic; | 143 | int magic; |
143 | int flags; | ||
144 | int count; /* count of opens */ | ||
145 | int line; | 144 | int line; |
146 | unsigned short close_delay; | ||
147 | unsigned short closing_wait; /* time to wait before closing */ | ||
148 | 145 | ||
149 | struct mgsl_icount icount; | 146 | struct mgsl_icount icount; |
150 | 147 | ||
151 | struct tty_struct *tty; | ||
152 | int timeout; | 148 | int timeout; |
153 | int x_char; /* xon/xoff character */ | 149 | int x_char; /* xon/xoff character */ |
154 | int blocked_open; /* # of blocked opens */ | ||
155 | unsigned char read_status_mask; | 150 | unsigned char read_status_mask; |
156 | unsigned char ignore_status_mask; | 151 | unsigned char ignore_status_mask; |
157 | 152 | ||
@@ -170,9 +165,6 @@ typedef struct _mgslpc_info { | |||
170 | int rx_buf_count; /* total number of rx buffers */ | 165 | int rx_buf_count; /* total number of rx buffers */ |
171 | int rx_frame_count; /* number of full rx buffers */ | 166 | int rx_frame_count; /* number of full rx buffers */ |
172 | 167 | ||
173 | wait_queue_head_t open_wait; | ||
174 | wait_queue_head_t close_wait; | ||
175 | |||
176 | wait_queue_head_t status_event_wait_q; | 168 | wait_queue_head_t status_event_wait_q; |
177 | wait_queue_head_t event_wait_q; | 169 | wait_queue_head_t event_wait_q; |
178 | struct timer_list tx_timer; /* HDLC transmit timeout timer */ | 170 | struct timer_list tx_timer; /* HDLC transmit timeout timer */ |
@@ -375,7 +367,7 @@ static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short | |||
375 | static void rx_start(MGSLPC_INFO *info); | 367 | static void rx_start(MGSLPC_INFO *info); |
376 | static void rx_stop(MGSLPC_INFO *info); | 368 | static void rx_stop(MGSLPC_INFO *info); |
377 | 369 | ||
378 | static void tx_start(MGSLPC_INFO *info); | 370 | static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty); |
379 | static void tx_stop(MGSLPC_INFO *info); | 371 | static void tx_stop(MGSLPC_INFO *info); |
380 | static void tx_set_idle(MGSLPC_INFO *info); | 372 | static void tx_set_idle(MGSLPC_INFO *info); |
381 | 373 | ||
@@ -389,7 +381,8 @@ static void async_mode(MGSLPC_INFO *info); | |||
389 | 381 | ||
390 | static void tx_timeout(unsigned long context); | 382 | static void tx_timeout(unsigned long context); |
391 | 383 | ||
392 | static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); | 384 | static int carrier_raised(struct tty_port *port); |
385 | static void raise_dtr_rts(struct tty_port *port); | ||
393 | 386 | ||
394 | #if SYNCLINK_GENERIC_HDLC | 387 | #if SYNCLINK_GENERIC_HDLC |
395 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | 388 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) |
@@ -410,7 +403,7 @@ static void release_resources(MGSLPC_INFO *info); | |||
410 | static void mgslpc_add_device(MGSLPC_INFO *info); | 403 | static void mgslpc_add_device(MGSLPC_INFO *info); |
411 | static void mgslpc_remove_device(MGSLPC_INFO *info); | 404 | static void mgslpc_remove_device(MGSLPC_INFO *info); |
412 | 405 | ||
413 | static bool rx_get_frame(MGSLPC_INFO *info); | 406 | static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty); |
414 | static void rx_reset_buffers(MGSLPC_INFO *info); | 407 | static void rx_reset_buffers(MGSLPC_INFO *info); |
415 | static int rx_alloc_buffers(MGSLPC_INFO *info); | 408 | static int rx_alloc_buffers(MGSLPC_INFO *info); |
416 | static void rx_free_buffers(MGSLPC_INFO *info); | 409 | static void rx_free_buffers(MGSLPC_INFO *info); |
@@ -421,7 +414,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id); | |||
421 | * Bottom half interrupt handlers | 414 | * Bottom half interrupt handlers |
422 | */ | 415 | */ |
423 | static void bh_handler(struct work_struct *work); | 416 | static void bh_handler(struct work_struct *work); |
424 | static void bh_transmit(MGSLPC_INFO *info); | 417 | static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty); |
425 | static void bh_status(MGSLPC_INFO *info); | 418 | static void bh_status(MGSLPC_INFO *info); |
426 | 419 | ||
427 | /* | 420 | /* |
@@ -432,10 +425,10 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
432 | unsigned int set, unsigned int clear); | 425 | unsigned int set, unsigned int clear); |
433 | static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); | 426 | static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); |
434 | static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params); | 427 | static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params); |
435 | static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params); | 428 | static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty); |
436 | static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode); | 429 | static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode); |
437 | static int set_txidle(MGSLPC_INFO *info, int idle_mode); | 430 | static int set_txidle(MGSLPC_INFO *info, int idle_mode); |
438 | static int set_txenable(MGSLPC_INFO *info, int enable); | 431 | static int set_txenable(MGSLPC_INFO *info, int enable, struct tty_struct *tty); |
439 | static int tx_abort(MGSLPC_INFO *info); | 432 | static int tx_abort(MGSLPC_INFO *info); |
440 | static int set_rxenable(MGSLPC_INFO *info, int enable); | 433 | static int set_rxenable(MGSLPC_INFO *info, int enable); |
441 | static int wait_events(MGSLPC_INFO *info, int __user *mask); | 434 | static int wait_events(MGSLPC_INFO *info, int __user *mask); |
@@ -474,7 +467,7 @@ static struct tty_driver *serial_driver; | |||
474 | /* number of characters left in xmit buffer before we ask for more */ | 467 | /* number of characters left in xmit buffer before we ask for more */ |
475 | #define WAKEUP_CHARS 256 | 468 | #define WAKEUP_CHARS 256 |
476 | 469 | ||
477 | static void mgslpc_change_params(MGSLPC_INFO *info); | 470 | static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty); |
478 | static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); | 471 | static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); |
479 | 472 | ||
480 | /* PCMCIA prototypes */ | 473 | /* PCMCIA prototypes */ |
@@ -517,6 +510,11 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
517 | } | 510 | } |
518 | } | 511 | } |
519 | 512 | ||
513 | static const struct tty_port_operations mgslpc_port_ops = { | ||
514 | .carrier_raised = carrier_raised, | ||
515 | .raise_dtr_rts = raise_dtr_rts | ||
516 | }; | ||
517 | |||
520 | static int mgslpc_probe(struct pcmcia_device *link) | 518 | static int mgslpc_probe(struct pcmcia_device *link) |
521 | { | 519 | { |
522 | MGSLPC_INFO *info; | 520 | MGSLPC_INFO *info; |
@@ -532,12 +530,12 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
532 | } | 530 | } |
533 | 531 | ||
534 | info->magic = MGSLPC_MAGIC; | 532 | info->magic = MGSLPC_MAGIC; |
533 | tty_port_init(&info->port); | ||
534 | info->port.ops = &mgslpc_port_ops; | ||
535 | INIT_WORK(&info->task, bh_handler); | 535 | INIT_WORK(&info->task, bh_handler); |
536 | info->max_frame_size = 4096; | 536 | info->max_frame_size = 4096; |
537 | info->close_delay = 5*HZ/10; | 537 | info->port.close_delay = 5*HZ/10; |
538 | info->closing_wait = 30*HZ; | 538 | info->port.closing_wait = 30*HZ; |
539 | init_waitqueue_head(&info->open_wait); | ||
540 | init_waitqueue_head(&info->close_wait); | ||
541 | init_waitqueue_head(&info->status_event_wait_q); | 539 | init_waitqueue_head(&info->status_event_wait_q); |
542 | init_waitqueue_head(&info->event_wait_q); | 540 | init_waitqueue_head(&info->event_wait_q); |
543 | spin_lock_init(&info->lock); | 541 | spin_lock_init(&info->lock); |
@@ -784,7 +782,7 @@ static void tx_release(struct tty_struct *tty) | |||
784 | 782 | ||
785 | spin_lock_irqsave(&info->lock,flags); | 783 | spin_lock_irqsave(&info->lock,flags); |
786 | if (!info->tx_enabled) | 784 | if (!info->tx_enabled) |
787 | tx_start(info); | 785 | tx_start(info, tty); |
788 | spin_unlock_irqrestore(&info->lock,flags); | 786 | spin_unlock_irqrestore(&info->lock,flags); |
789 | } | 787 | } |
790 | 788 | ||
@@ -823,6 +821,7 @@ static int bh_action(MGSLPC_INFO *info) | |||
823 | static void bh_handler(struct work_struct *work) | 821 | static void bh_handler(struct work_struct *work) |
824 | { | 822 | { |
825 | MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); | 823 | MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); |
824 | struct tty_struct *tty; | ||
826 | int action; | 825 | int action; |
827 | 826 | ||
828 | if (!info) | 827 | if (!info) |
@@ -833,6 +832,7 @@ static void bh_handler(struct work_struct *work) | |||
833 | __FILE__,__LINE__,info->device_name); | 832 | __FILE__,__LINE__,info->device_name); |
834 | 833 | ||
835 | info->bh_running = true; | 834 | info->bh_running = true; |
835 | tty = tty_port_tty_get(&info->port); | ||
836 | 836 | ||
837 | while((action = bh_action(info)) != 0) { | 837 | while((action = bh_action(info)) != 0) { |
838 | 838 | ||
@@ -844,10 +844,10 @@ static void bh_handler(struct work_struct *work) | |||
844 | switch (action) { | 844 | switch (action) { |
845 | 845 | ||
846 | case BH_RECEIVE: | 846 | case BH_RECEIVE: |
847 | while(rx_get_frame(info)); | 847 | while(rx_get_frame(info, tty)); |
848 | break; | 848 | break; |
849 | case BH_TRANSMIT: | 849 | case BH_TRANSMIT: |
850 | bh_transmit(info); | 850 | bh_transmit(info, tty); |
851 | break; | 851 | break; |
852 | case BH_STATUS: | 852 | case BH_STATUS: |
853 | bh_status(info); | 853 | bh_status(info); |
@@ -859,14 +859,14 @@ static void bh_handler(struct work_struct *work) | |||
859 | } | 859 | } |
860 | } | 860 | } |
861 | 861 | ||
862 | tty_kref_put(tty); | ||
862 | if (debug_level >= DEBUG_LEVEL_BH) | 863 | if (debug_level >= DEBUG_LEVEL_BH) |
863 | printk( "%s(%d):bh_handler(%s) exit\n", | 864 | printk( "%s(%d):bh_handler(%s) exit\n", |
864 | __FILE__,__LINE__,info->device_name); | 865 | __FILE__,__LINE__,info->device_name); |
865 | } | 866 | } |
866 | 867 | ||
867 | static void bh_transmit(MGSLPC_INFO *info) | 868 | static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty) |
868 | { | 869 | { |
869 | struct tty_struct *tty = info->tty; | ||
870 | if (debug_level >= DEBUG_LEVEL_BH) | 870 | if (debug_level >= DEBUG_LEVEL_BH) |
871 | printk("bh_transmit() entry on %s\n", info->device_name); | 871 | printk("bh_transmit() entry on %s\n", info->device_name); |
872 | 872 | ||
@@ -945,12 +945,11 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) | |||
945 | issue_command(info, CHA, CMD_RXFIFO); | 945 | issue_command(info, CHA, CMD_RXFIFO); |
946 | } | 946 | } |
947 | 947 | ||
948 | static void rx_ready_async(MGSLPC_INFO *info, int tcd) | 948 | static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) |
949 | { | 949 | { |
950 | unsigned char data, status, flag; | 950 | unsigned char data, status, flag; |
951 | int fifo_count; | 951 | int fifo_count; |
952 | int work = 0; | 952 | int work = 0; |
953 | struct tty_struct *tty = info->tty; | ||
954 | struct mgsl_icount *icount = &info->icount; | 953 | struct mgsl_icount *icount = &info->icount; |
955 | 954 | ||
956 | if (tcd) { | 955 | if (tcd) { |
@@ -1013,7 +1012,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd) | |||
1013 | } | 1012 | } |
1014 | 1013 | ||
1015 | 1014 | ||
1016 | static void tx_done(MGSLPC_INFO *info) | 1015 | static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty) |
1017 | { | 1016 | { |
1018 | if (!info->tx_active) | 1017 | if (!info->tx_active) |
1019 | return; | 1018 | return; |
@@ -1042,7 +1041,7 @@ static void tx_done(MGSLPC_INFO *info) | |||
1042 | else | 1041 | else |
1043 | #endif | 1042 | #endif |
1044 | { | 1043 | { |
1045 | if (info->tty->stopped || info->tty->hw_stopped) { | 1044 | if (tty->stopped || tty->hw_stopped) { |
1046 | tx_stop(info); | 1045 | tx_stop(info); |
1047 | return; | 1046 | return; |
1048 | } | 1047 | } |
@@ -1050,7 +1049,7 @@ static void tx_done(MGSLPC_INFO *info) | |||
1050 | } | 1049 | } |
1051 | } | 1050 | } |
1052 | 1051 | ||
1053 | static void tx_ready(MGSLPC_INFO *info) | 1052 | static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) |
1054 | { | 1053 | { |
1055 | unsigned char fifo_count = 32; | 1054 | unsigned char fifo_count = 32; |
1056 | int c; | 1055 | int c; |
@@ -1062,7 +1061,7 @@ static void tx_ready(MGSLPC_INFO *info) | |||
1062 | if (!info->tx_active) | 1061 | if (!info->tx_active) |
1063 | return; | 1062 | return; |
1064 | } else { | 1063 | } else { |
1065 | if (info->tty->stopped || info->tty->hw_stopped) { | 1064 | if (tty->stopped || tty->hw_stopped) { |
1066 | tx_stop(info); | 1065 | tx_stop(info); |
1067 | return; | 1066 | return; |
1068 | } | 1067 | } |
@@ -1099,7 +1098,7 @@ static void tx_ready(MGSLPC_INFO *info) | |||
1099 | } | 1098 | } |
1100 | } | 1099 | } |
1101 | 1100 | ||
1102 | static void cts_change(MGSLPC_INFO *info) | 1101 | static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) |
1103 | { | 1102 | { |
1104 | get_signals(info); | 1103 | get_signals(info); |
1105 | if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) | 1104 | if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) |
@@ -1112,14 +1111,14 @@ static void cts_change(MGSLPC_INFO *info) | |||
1112 | wake_up_interruptible(&info->status_event_wait_q); | 1111 | wake_up_interruptible(&info->status_event_wait_q); |
1113 | wake_up_interruptible(&info->event_wait_q); | 1112 | wake_up_interruptible(&info->event_wait_q); |
1114 | 1113 | ||
1115 | if (info->flags & ASYNC_CTS_FLOW) { | 1114 | if (info->port.flags & ASYNC_CTS_FLOW) { |
1116 | if (info->tty->hw_stopped) { | 1115 | if (tty->hw_stopped) { |
1117 | if (info->serial_signals & SerialSignal_CTS) { | 1116 | if (info->serial_signals & SerialSignal_CTS) { |
1118 | if (debug_level >= DEBUG_LEVEL_ISR) | 1117 | if (debug_level >= DEBUG_LEVEL_ISR) |
1119 | printk("CTS tx start..."); | 1118 | printk("CTS tx start..."); |
1120 | if (info->tty) | 1119 | if (tty) |
1121 | info->tty->hw_stopped = 0; | 1120 | tty->hw_stopped = 0; |
1122 | tx_start(info); | 1121 | tx_start(info, tty); |
1123 | info->pending_bh |= BH_TRANSMIT; | 1122 | info->pending_bh |= BH_TRANSMIT; |
1124 | return; | 1123 | return; |
1125 | } | 1124 | } |
@@ -1127,8 +1126,8 @@ static void cts_change(MGSLPC_INFO *info) | |||
1127 | if (!(info->serial_signals & SerialSignal_CTS)) { | 1126 | if (!(info->serial_signals & SerialSignal_CTS)) { |
1128 | if (debug_level >= DEBUG_LEVEL_ISR) | 1127 | if (debug_level >= DEBUG_LEVEL_ISR) |
1129 | printk("CTS tx stop..."); | 1128 | printk("CTS tx stop..."); |
1130 | if (info->tty) | 1129 | if (tty) |
1131 | info->tty->hw_stopped = 1; | 1130 | tty->hw_stopped = 1; |
1132 | tx_stop(info); | 1131 | tx_stop(info); |
1133 | } | 1132 | } |
1134 | } | 1133 | } |
@@ -1136,7 +1135,7 @@ static void cts_change(MGSLPC_INFO *info) | |||
1136 | info->pending_bh |= BH_STATUS; | 1135 | info->pending_bh |= BH_STATUS; |
1137 | } | 1136 | } |
1138 | 1137 | ||
1139 | static void dcd_change(MGSLPC_INFO *info) | 1138 | static void dcd_change(MGSLPC_INFO *info, struct tty_struct *tty) |
1140 | { | 1139 | { |
1141 | get_signals(info); | 1140 | get_signals(info); |
1142 | if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) | 1141 | if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) |
@@ -1158,17 +1157,17 @@ static void dcd_change(MGSLPC_INFO *info) | |||
1158 | wake_up_interruptible(&info->status_event_wait_q); | 1157 | wake_up_interruptible(&info->status_event_wait_q); |
1159 | wake_up_interruptible(&info->event_wait_q); | 1158 | wake_up_interruptible(&info->event_wait_q); |
1160 | 1159 | ||
1161 | if (info->flags & ASYNC_CHECK_CD) { | 1160 | if (info->port.flags & ASYNC_CHECK_CD) { |
1162 | if (debug_level >= DEBUG_LEVEL_ISR) | 1161 | if (debug_level >= DEBUG_LEVEL_ISR) |
1163 | printk("%s CD now %s...", info->device_name, | 1162 | printk("%s CD now %s...", info->device_name, |
1164 | (info->serial_signals & SerialSignal_DCD) ? "on" : "off"); | 1163 | (info->serial_signals & SerialSignal_DCD) ? "on" : "off"); |
1165 | if (info->serial_signals & SerialSignal_DCD) | 1164 | if (info->serial_signals & SerialSignal_DCD) |
1166 | wake_up_interruptible(&info->open_wait); | 1165 | wake_up_interruptible(&info->port.open_wait); |
1167 | else { | 1166 | else { |
1168 | if (debug_level >= DEBUG_LEVEL_ISR) | 1167 | if (debug_level >= DEBUG_LEVEL_ISR) |
1169 | printk("doing serial hangup..."); | 1168 | printk("doing serial hangup..."); |
1170 | if (info->tty) | 1169 | if (tty) |
1171 | tty_hangup(info->tty); | 1170 | tty_hangup(tty); |
1172 | } | 1171 | } |
1173 | } | 1172 | } |
1174 | info->pending_bh |= BH_STATUS; | 1173 | info->pending_bh |= BH_STATUS; |
@@ -1214,6 +1213,7 @@ static void ri_change(MGSLPC_INFO *info) | |||
1214 | static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | 1213 | static irqreturn_t mgslpc_isr(int dummy, void *dev_id) |
1215 | { | 1214 | { |
1216 | MGSLPC_INFO *info = dev_id; | 1215 | MGSLPC_INFO *info = dev_id; |
1216 | struct tty_struct *tty; | ||
1217 | unsigned short isr; | 1217 | unsigned short isr; |
1218 | unsigned char gis, pis; | 1218 | unsigned char gis, pis; |
1219 | int count=0; | 1219 | int count=0; |
@@ -1224,6 +1224,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1224 | if (!(info->p_dev->_locked)) | 1224 | if (!(info->p_dev->_locked)) |
1225 | return IRQ_HANDLED; | 1225 | return IRQ_HANDLED; |
1226 | 1226 | ||
1227 | tty = tty_port_tty_get(&info->port); | ||
1228 | |||
1227 | spin_lock(&info->lock); | 1229 | spin_lock(&info->lock); |
1228 | 1230 | ||
1229 | while ((gis = read_reg(info, CHA + GIS))) { | 1231 | while ((gis = read_reg(info, CHA + GIS))) { |
@@ -1239,9 +1241,9 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1239 | if (gis & (BIT1 + BIT0)) { | 1241 | if (gis & (BIT1 + BIT0)) { |
1240 | isr = read_reg16(info, CHB + ISR); | 1242 | isr = read_reg16(info, CHB + ISR); |
1241 | if (isr & IRQ_DCD) | 1243 | if (isr & IRQ_DCD) |
1242 | dcd_change(info); | 1244 | dcd_change(info, tty); |
1243 | if (isr & IRQ_CTS) | 1245 | if (isr & IRQ_CTS) |
1244 | cts_change(info); | 1246 | cts_change(info, tty); |
1245 | } | 1247 | } |
1246 | if (gis & (BIT3 + BIT2)) | 1248 | if (gis & (BIT3 + BIT2)) |
1247 | { | 1249 | { |
@@ -1258,8 +1260,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1258 | } | 1260 | } |
1259 | if (isr & IRQ_BREAK_ON) { | 1261 | if (isr & IRQ_BREAK_ON) { |
1260 | info->icount.brk++; | 1262 | info->icount.brk++; |
1261 | if (info->flags & ASYNC_SAK) | 1263 | if (info->port.flags & ASYNC_SAK) |
1262 | do_SAK(info->tty); | 1264 | do_SAK(tty); |
1263 | } | 1265 | } |
1264 | if (isr & IRQ_RXTIME) { | 1266 | if (isr & IRQ_RXTIME) { |
1265 | issue_command(info, CHA, CMD_RXFIFO_READ); | 1267 | issue_command(info, CHA, CMD_RXFIFO_READ); |
@@ -1268,7 +1270,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1268 | if (info->params.mode == MGSL_MODE_HDLC) | 1270 | if (info->params.mode == MGSL_MODE_HDLC) |
1269 | rx_ready_hdlc(info, isr & IRQ_RXEOM); | 1271 | rx_ready_hdlc(info, isr & IRQ_RXEOM); |
1270 | else | 1272 | else |
1271 | rx_ready_async(info, isr & IRQ_RXEOM); | 1273 | rx_ready_async(info, isr & IRQ_RXEOM, tty); |
1272 | } | 1274 | } |
1273 | 1275 | ||
1274 | /* transmit IRQs */ | 1276 | /* transmit IRQs */ |
@@ -1277,14 +1279,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1277 | info->icount.txabort++; | 1279 | info->icount.txabort++; |
1278 | else | 1280 | else |
1279 | info->icount.txunder++; | 1281 | info->icount.txunder++; |
1280 | tx_done(info); | 1282 | tx_done(info, tty); |
1281 | } | 1283 | } |
1282 | else if (isr & IRQ_ALLSENT) { | 1284 | else if (isr & IRQ_ALLSENT) { |
1283 | info->icount.txok++; | 1285 | info->icount.txok++; |
1284 | tx_done(info); | 1286 | tx_done(info, tty); |
1285 | } | 1287 | } |
1286 | else if (isr & IRQ_TXFIFO) | 1288 | else if (isr & IRQ_TXFIFO) |
1287 | tx_ready(info); | 1289 | tx_ready(info, tty); |
1288 | } | 1290 | } |
1289 | if (gis & BIT7) { | 1291 | if (gis & BIT7) { |
1290 | pis = read_reg(info, CHA + PIS); | 1292 | pis = read_reg(info, CHA + PIS); |
@@ -1308,6 +1310,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1308 | } | 1310 | } |
1309 | 1311 | ||
1310 | spin_unlock(&info->lock); | 1312 | spin_unlock(&info->lock); |
1313 | tty_kref_put(tty); | ||
1311 | 1314 | ||
1312 | if (debug_level >= DEBUG_LEVEL_ISR) | 1315 | if (debug_level >= DEBUG_LEVEL_ISR) |
1313 | printk("%s(%d):mgslpc_isr(%d)exit.\n", | 1316 | printk("%s(%d):mgslpc_isr(%d)exit.\n", |
@@ -1318,14 +1321,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1318 | 1321 | ||
1319 | /* Initialize and start device. | 1322 | /* Initialize and start device. |
1320 | */ | 1323 | */ |
1321 | static int startup(MGSLPC_INFO * info) | 1324 | static int startup(MGSLPC_INFO * info, struct tty_struct *tty) |
1322 | { | 1325 | { |
1323 | int retval = 0; | 1326 | int retval = 0; |
1324 | 1327 | ||
1325 | if (debug_level >= DEBUG_LEVEL_INFO) | 1328 | if (debug_level >= DEBUG_LEVEL_INFO) |
1326 | printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); | 1329 | printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); |
1327 | 1330 | ||
1328 | if (info->flags & ASYNC_INITIALIZED) | 1331 | if (info->port.flags & ASYNC_INITIALIZED) |
1329 | return 0; | 1332 | return 0; |
1330 | 1333 | ||
1331 | if (!info->tx_buf) { | 1334 | if (!info->tx_buf) { |
@@ -1352,30 +1355,30 @@ static int startup(MGSLPC_INFO * info) | |||
1352 | retval = adapter_test(info); | 1355 | retval = adapter_test(info); |
1353 | 1356 | ||
1354 | if ( retval ) { | 1357 | if ( retval ) { |
1355 | if (capable(CAP_SYS_ADMIN) && info->tty) | 1358 | if (capable(CAP_SYS_ADMIN) && tty) |
1356 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1359 | set_bit(TTY_IO_ERROR, &tty->flags); |
1357 | release_resources(info); | 1360 | release_resources(info); |
1358 | return retval; | 1361 | return retval; |
1359 | } | 1362 | } |
1360 | 1363 | ||
1361 | /* program hardware for current parameters */ | 1364 | /* program hardware for current parameters */ |
1362 | mgslpc_change_params(info); | 1365 | mgslpc_change_params(info, tty); |
1363 | 1366 | ||
1364 | if (info->tty) | 1367 | if (tty) |
1365 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 1368 | clear_bit(TTY_IO_ERROR, &tty->flags); |
1366 | 1369 | ||
1367 | info->flags |= ASYNC_INITIALIZED; | 1370 | info->port.flags |= ASYNC_INITIALIZED; |
1368 | 1371 | ||
1369 | return 0; | 1372 | return 0; |
1370 | } | 1373 | } |
1371 | 1374 | ||
1372 | /* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware | 1375 | /* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware |
1373 | */ | 1376 | */ |
1374 | static void shutdown(MGSLPC_INFO * info) | 1377 | static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) |
1375 | { | 1378 | { |
1376 | unsigned long flags; | 1379 | unsigned long flags; |
1377 | 1380 | ||
1378 | if (!(info->flags & ASYNC_INITIALIZED)) | 1381 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
1379 | return; | 1382 | return; |
1380 | 1383 | ||
1381 | if (debug_level >= DEBUG_LEVEL_INFO) | 1384 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1402,7 +1405,7 @@ static void shutdown(MGSLPC_INFO * info) | |||
1402 | /* TODO:disable interrupts instead of reset to preserve signal states */ | 1405 | /* TODO:disable interrupts instead of reset to preserve signal states */ |
1403 | reset_device(info); | 1406 | reset_device(info); |
1404 | 1407 | ||
1405 | if (!info->tty || info->tty->termios->c_cflag & HUPCL) { | 1408 | if (!tty || tty->termios->c_cflag & HUPCL) { |
1406 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); | 1409 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); |
1407 | set_signals(info); | 1410 | set_signals(info); |
1408 | } | 1411 | } |
@@ -1411,13 +1414,13 @@ static void shutdown(MGSLPC_INFO * info) | |||
1411 | 1414 | ||
1412 | release_resources(info); | 1415 | release_resources(info); |
1413 | 1416 | ||
1414 | if (info->tty) | 1417 | if (tty) |
1415 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1418 | set_bit(TTY_IO_ERROR, &tty->flags); |
1416 | 1419 | ||
1417 | info->flags &= ~ASYNC_INITIALIZED; | 1420 | info->port.flags &= ~ASYNC_INITIALIZED; |
1418 | } | 1421 | } |
1419 | 1422 | ||
1420 | static void mgslpc_program_hw(MGSLPC_INFO *info) | 1423 | static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) |
1421 | { | 1424 | { |
1422 | unsigned long flags; | 1425 | unsigned long flags; |
1423 | 1426 | ||
@@ -1443,7 +1446,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info) | |||
1443 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); | 1446 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); |
1444 | get_signals(info); | 1447 | get_signals(info); |
1445 | 1448 | ||
1446 | if (info->netcount || info->tty->termios->c_cflag & CREAD) | 1449 | if (info->netcount || (tty && (tty->termios->c_cflag & CREAD))) |
1447 | rx_start(info); | 1450 | rx_start(info); |
1448 | 1451 | ||
1449 | spin_unlock_irqrestore(&info->lock,flags); | 1452 | spin_unlock_irqrestore(&info->lock,flags); |
@@ -1451,19 +1454,19 @@ static void mgslpc_program_hw(MGSLPC_INFO *info) | |||
1451 | 1454 | ||
1452 | /* Reconfigure adapter based on new parameters | 1455 | /* Reconfigure adapter based on new parameters |
1453 | */ | 1456 | */ |
1454 | static void mgslpc_change_params(MGSLPC_INFO *info) | 1457 | static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) |
1455 | { | 1458 | { |
1456 | unsigned cflag; | 1459 | unsigned cflag; |
1457 | int bits_per_char; | 1460 | int bits_per_char; |
1458 | 1461 | ||
1459 | if (!info->tty || !info->tty->termios) | 1462 | if (!tty || !tty->termios) |
1460 | return; | 1463 | return; |
1461 | 1464 | ||
1462 | if (debug_level >= DEBUG_LEVEL_INFO) | 1465 | if (debug_level >= DEBUG_LEVEL_INFO) |
1463 | printk("%s(%d):mgslpc_change_params(%s)\n", | 1466 | printk("%s(%d):mgslpc_change_params(%s)\n", |
1464 | __FILE__,__LINE__, info->device_name ); | 1467 | __FILE__,__LINE__, info->device_name ); |
1465 | 1468 | ||
1466 | cflag = info->tty->termios->c_cflag; | 1469 | cflag = tty->termios->c_cflag; |
1467 | 1470 | ||
1468 | /* if B0 rate (hangup) specified then negate DTR and RTS */ | 1471 | /* if B0 rate (hangup) specified then negate DTR and RTS */ |
1469 | /* otherwise assert DTR and RTS */ | 1472 | /* otherwise assert DTR and RTS */ |
@@ -1510,7 +1513,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info) | |||
1510 | * current data rate. | 1513 | * current data rate. |
1511 | */ | 1514 | */ |
1512 | if (info->params.data_rate <= 460800) { | 1515 | if (info->params.data_rate <= 460800) { |
1513 | info->params.data_rate = tty_get_baud_rate(info->tty); | 1516 | info->params.data_rate = tty_get_baud_rate(tty); |
1514 | } | 1517 | } |
1515 | 1518 | ||
1516 | if ( info->params.data_rate ) { | 1519 | if ( info->params.data_rate ) { |
@@ -1520,24 +1523,24 @@ static void mgslpc_change_params(MGSLPC_INFO *info) | |||
1520 | info->timeout += HZ/50; /* Add .02 seconds of slop */ | 1523 | info->timeout += HZ/50; /* Add .02 seconds of slop */ |
1521 | 1524 | ||
1522 | if (cflag & CRTSCTS) | 1525 | if (cflag & CRTSCTS) |
1523 | info->flags |= ASYNC_CTS_FLOW; | 1526 | info->port.flags |= ASYNC_CTS_FLOW; |
1524 | else | 1527 | else |
1525 | info->flags &= ~ASYNC_CTS_FLOW; | 1528 | info->port.flags &= ~ASYNC_CTS_FLOW; |
1526 | 1529 | ||
1527 | if (cflag & CLOCAL) | 1530 | if (cflag & CLOCAL) |
1528 | info->flags &= ~ASYNC_CHECK_CD; | 1531 | info->port.flags &= ~ASYNC_CHECK_CD; |
1529 | else | 1532 | else |
1530 | info->flags |= ASYNC_CHECK_CD; | 1533 | info->port.flags |= ASYNC_CHECK_CD; |
1531 | 1534 | ||
1532 | /* process tty input control flags */ | 1535 | /* process tty input control flags */ |
1533 | 1536 | ||
1534 | info->read_status_mask = 0; | 1537 | info->read_status_mask = 0; |
1535 | if (I_INPCK(info->tty)) | 1538 | if (I_INPCK(tty)) |
1536 | info->read_status_mask |= BIT7 | BIT6; | 1539 | info->read_status_mask |= BIT7 | BIT6; |
1537 | if (I_IGNPAR(info->tty)) | 1540 | if (I_IGNPAR(tty)) |
1538 | info->ignore_status_mask |= BIT7 | BIT6; | 1541 | info->ignore_status_mask |= BIT7 | BIT6; |
1539 | 1542 | ||
1540 | mgslpc_program_hw(info); | 1543 | mgslpc_program_hw(info, tty); |
1541 | } | 1544 | } |
1542 | 1545 | ||
1543 | /* Add a character to the transmit buffer | 1546 | /* Add a character to the transmit buffer |
@@ -1597,7 +1600,7 @@ static void mgslpc_flush_chars(struct tty_struct *tty) | |||
1597 | 1600 | ||
1598 | spin_lock_irqsave(&info->lock,flags); | 1601 | spin_lock_irqsave(&info->lock,flags); |
1599 | if (!info->tx_active) | 1602 | if (!info->tx_active) |
1600 | tx_start(info); | 1603 | tx_start(info, tty); |
1601 | spin_unlock_irqrestore(&info->lock,flags); | 1604 | spin_unlock_irqrestore(&info->lock,flags); |
1602 | } | 1605 | } |
1603 | 1606 | ||
@@ -1659,7 +1662,7 @@ start: | |||
1659 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { | 1662 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { |
1660 | spin_lock_irqsave(&info->lock,flags); | 1663 | spin_lock_irqsave(&info->lock,flags); |
1661 | if (!info->tx_active) | 1664 | if (!info->tx_active) |
1662 | tx_start(info); | 1665 | tx_start(info, tty); |
1663 | spin_unlock_irqrestore(&info->lock,flags); | 1666 | spin_unlock_irqrestore(&info->lock,flags); |
1664 | } | 1667 | } |
1665 | cleanup: | 1668 | cleanup: |
@@ -1764,7 +1767,7 @@ static void mgslpc_send_xchar(struct tty_struct *tty, char ch) | |||
1764 | if (ch) { | 1767 | if (ch) { |
1765 | spin_lock_irqsave(&info->lock,flags); | 1768 | spin_lock_irqsave(&info->lock,flags); |
1766 | if (!info->tx_enabled) | 1769 | if (!info->tx_enabled) |
1767 | tx_start(info); | 1770 | tx_start(info, tty); |
1768 | spin_unlock_irqrestore(&info->lock,flags); | 1771 | spin_unlock_irqrestore(&info->lock,flags); |
1769 | } | 1772 | } |
1770 | } | 1773 | } |
@@ -1862,7 +1865,7 @@ static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params) | |||
1862 | * | 1865 | * |
1863 | * Returns: 0 if success, otherwise error code | 1866 | * Returns: 0 if success, otherwise error code |
1864 | */ | 1867 | */ |
1865 | static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params) | 1868 | static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params, struct tty_struct *tty) |
1866 | { | 1869 | { |
1867 | unsigned long flags; | 1870 | unsigned long flags; |
1868 | MGSL_PARAMS tmp_params; | 1871 | MGSL_PARAMS tmp_params; |
@@ -1883,7 +1886,7 @@ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params) | |||
1883 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 1886 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
1884 | spin_unlock_irqrestore(&info->lock,flags); | 1887 | spin_unlock_irqrestore(&info->lock,flags); |
1885 | 1888 | ||
1886 | mgslpc_change_params(info); | 1889 | mgslpc_change_params(info, tty); |
1887 | 1890 | ||
1888 | return 0; | 1891 | return 0; |
1889 | } | 1892 | } |
@@ -1944,7 +1947,7 @@ static int set_interface(MGSLPC_INFO * info, int if_mode) | |||
1944 | return 0; | 1947 | return 0; |
1945 | } | 1948 | } |
1946 | 1949 | ||
1947 | static int set_txenable(MGSLPC_INFO * info, int enable) | 1950 | static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty) |
1948 | { | 1951 | { |
1949 | unsigned long flags; | 1952 | unsigned long flags; |
1950 | 1953 | ||
@@ -1954,7 +1957,7 @@ static int set_txenable(MGSLPC_INFO * info, int enable) | |||
1954 | spin_lock_irqsave(&info->lock,flags); | 1957 | spin_lock_irqsave(&info->lock,flags); |
1955 | if (enable) { | 1958 | if (enable) { |
1956 | if (!info->tx_enabled) | 1959 | if (!info->tx_enabled) |
1957 | tx_start(info); | 1960 | tx_start(info, tty); |
1958 | } else { | 1961 | } else { |
1959 | if (info->tx_enabled) | 1962 | if (info->tx_enabled) |
1960 | tx_stop(info); | 1963 | tx_stop(info); |
@@ -2263,6 +2266,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2263 | unsigned int cmd, unsigned long arg) | 2266 | unsigned int cmd, unsigned long arg) |
2264 | { | 2267 | { |
2265 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2268 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2269 | int error; | ||
2270 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2271 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2272 | void __user *argp = (void __user *)arg; | ||
2273 | unsigned long flags; | ||
2266 | 2274 | ||
2267 | if (debug_level >= DEBUG_LEVEL_INFO) | 2275 | if (debug_level >= DEBUG_LEVEL_INFO) |
2268 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2276 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2277,22 +2285,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2277 | return -EIO; | 2285 | return -EIO; |
2278 | } | 2286 | } |
2279 | 2287 | ||
2280 | return ioctl_common(info, cmd, arg); | ||
2281 | } | ||
2282 | |||
2283 | static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) | ||
2284 | { | ||
2285 | int error; | ||
2286 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2287 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2288 | void __user *argp = (void __user *)arg; | ||
2289 | unsigned long flags; | ||
2290 | |||
2291 | switch (cmd) { | 2288 | switch (cmd) { |
2292 | case MGSL_IOCGPARAMS: | 2289 | case MGSL_IOCGPARAMS: |
2293 | return get_params(info, argp); | 2290 | return get_params(info, argp); |
2294 | case MGSL_IOCSPARAMS: | 2291 | case MGSL_IOCSPARAMS: |
2295 | return set_params(info, argp); | 2292 | return set_params(info, argp, tty); |
2296 | case MGSL_IOCGTXIDLE: | 2293 | case MGSL_IOCGTXIDLE: |
2297 | return get_txidle(info, argp); | 2294 | return get_txidle(info, argp); |
2298 | case MGSL_IOCSTXIDLE: | 2295 | case MGSL_IOCSTXIDLE: |
@@ -2302,7 +2299,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) | |||
2302 | case MGSL_IOCSIF: | 2299 | case MGSL_IOCSIF: |
2303 | return set_interface(info,(int)arg); | 2300 | return set_interface(info,(int)arg); |
2304 | case MGSL_IOCTXENABLE: | 2301 | case MGSL_IOCTXENABLE: |
2305 | return set_txenable(info,(int)arg); | 2302 | return set_txenable(info,(int)arg, tty); |
2306 | case MGSL_IOCRXENABLE: | 2303 | case MGSL_IOCRXENABLE: |
2307 | return set_rxenable(info,(int)arg); | 2304 | return set_rxenable(info,(int)arg); |
2308 | case MGSL_IOCTXABORT: | 2305 | case MGSL_IOCTXABORT: |
@@ -2369,7 +2366,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
2369 | == RELEVANT_IFLAG(old_termios->c_iflag))) | 2366 | == RELEVANT_IFLAG(old_termios->c_iflag))) |
2370 | return; | 2367 | return; |
2371 | 2368 | ||
2372 | mgslpc_change_params(info); | 2369 | mgslpc_change_params(info, tty); |
2373 | 2370 | ||
2374 | /* Handle transition to B0 status */ | 2371 | /* Handle transition to B0 status */ |
2375 | if (old_termios->c_cflag & CBAUD && | 2372 | if (old_termios->c_cflag & CBAUD && |
@@ -2404,81 +2401,34 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
2404 | static void mgslpc_close(struct tty_struct *tty, struct file * filp) | 2401 | static void mgslpc_close(struct tty_struct *tty, struct file * filp) |
2405 | { | 2402 | { |
2406 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2403 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2404 | struct tty_port *port = &info->port; | ||
2407 | 2405 | ||
2408 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close")) | 2406 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close")) |
2409 | return; | 2407 | return; |
2410 | 2408 | ||
2411 | if (debug_level >= DEBUG_LEVEL_INFO) | 2409 | if (debug_level >= DEBUG_LEVEL_INFO) |
2412 | printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", | 2410 | printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", |
2413 | __FILE__,__LINE__, info->device_name, info->count); | 2411 | __FILE__,__LINE__, info->device_name, port->count); |
2414 | |||
2415 | if (!info->count) | ||
2416 | return; | ||
2417 | 2412 | ||
2418 | if (tty_hung_up_p(filp)) | 2413 | WARN_ON(!port->count); |
2419 | goto cleanup; | ||
2420 | |||
2421 | if ((tty->count == 1) && (info->count != 1)) { | ||
2422 | /* | ||
2423 | * tty->count is 1 and the tty structure will be freed. | ||
2424 | * info->count should be one in this case. | ||
2425 | * if it's not, correct it so that the port is shutdown. | ||
2426 | */ | ||
2427 | printk("mgslpc_close: bad refcount; tty->count is 1, " | ||
2428 | "info->count is %d\n", info->count); | ||
2429 | info->count = 1; | ||
2430 | } | ||
2431 | 2414 | ||
2432 | info->count--; | 2415 | if (tty_port_close_start(port, tty, filp) == 0) |
2433 | |||
2434 | /* if at least one open remaining, leave hardware active */ | ||
2435 | if (info->count) | ||
2436 | goto cleanup; | 2416 | goto cleanup; |
2437 | 2417 | ||
2438 | info->flags |= ASYNC_CLOSING; | 2418 | if (port->flags & ASYNC_INITIALIZED) |
2439 | |||
2440 | /* set tty->closing to notify line discipline to | ||
2441 | * only process XON/XOFF characters. Only the N_TTY | ||
2442 | * discipline appears to use this (ppp does not). | ||
2443 | */ | ||
2444 | tty->closing = 1; | ||
2445 | |||
2446 | /* wait for transmit data to clear all layers */ | ||
2447 | |||
2448 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
2449 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2450 | printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n", | ||
2451 | __FILE__,__LINE__, info->device_name ); | ||
2452 | tty_wait_until_sent(tty, info->closing_wait); | ||
2453 | } | ||
2454 | |||
2455 | if (info->flags & ASYNC_INITIALIZED) | ||
2456 | mgslpc_wait_until_sent(tty, info->timeout); | 2419 | mgslpc_wait_until_sent(tty, info->timeout); |
2457 | 2420 | ||
2458 | mgslpc_flush_buffer(tty); | 2421 | mgslpc_flush_buffer(tty); |
2459 | 2422 | ||
2460 | tty_ldisc_flush(tty); | 2423 | tty_ldisc_flush(tty); |
2461 | 2424 | shutdown(info, tty); | |
2462 | shutdown(info); | 2425 | |
2463 | 2426 | tty_port_close_end(port, tty); | |
2464 | tty->closing = 0; | 2427 | tty_port_tty_set(port, NULL); |
2465 | info->tty = NULL; | ||
2466 | |||
2467 | if (info->blocked_open) { | ||
2468 | if (info->close_delay) { | ||
2469 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
2470 | } | ||
2471 | wake_up_interruptible(&info->open_wait); | ||
2472 | } | ||
2473 | |||
2474 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
2475 | |||
2476 | wake_up_interruptible(&info->close_wait); | ||
2477 | |||
2478 | cleanup: | 2428 | cleanup: |
2479 | if (debug_level >= DEBUG_LEVEL_INFO) | 2429 | if (debug_level >= DEBUG_LEVEL_INFO) |
2480 | printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, | 2430 | printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, |
2481 | tty->driver->name, info->count); | 2431 | tty->driver->name, port->count); |
2482 | } | 2432 | } |
2483 | 2433 | ||
2484 | /* Wait until the transmitter is empty. | 2434 | /* Wait until the transmitter is empty. |
@@ -2498,7 +2448,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2498 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent")) | 2448 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent")) |
2499 | return; | 2449 | return; |
2500 | 2450 | ||
2501 | if (!(info->flags & ASYNC_INITIALIZED)) | 2451 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
2502 | goto exit; | 2452 | goto exit; |
2503 | 2453 | ||
2504 | orig_jiffies = jiffies; | 2454 | orig_jiffies = jiffies; |
@@ -2559,120 +2509,40 @@ static void mgslpc_hangup(struct tty_struct *tty) | |||
2559 | return; | 2509 | return; |
2560 | 2510 | ||
2561 | mgslpc_flush_buffer(tty); | 2511 | mgslpc_flush_buffer(tty); |
2562 | shutdown(info); | 2512 | shutdown(info, tty); |
2563 | 2513 | tty_port_hangup(&info->port); | |
2564 | info->count = 0; | ||
2565 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2566 | info->tty = NULL; | ||
2567 | |||
2568 | wake_up_interruptible(&info->open_wait); | ||
2569 | } | 2514 | } |
2570 | 2515 | ||
2571 | /* Block the current process until the specified port | 2516 | static int carrier_raised(struct tty_port *port) |
2572 | * is ready to be opened. | ||
2573 | */ | ||
2574 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
2575 | MGSLPC_INFO *info) | ||
2576 | { | 2517 | { |
2577 | DECLARE_WAITQUEUE(wait, current); | 2518 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); |
2578 | int retval; | 2519 | unsigned long flags; |
2579 | bool do_clocal = false; | ||
2580 | bool extra_count = false; | ||
2581 | unsigned long flags; | ||
2582 | |||
2583 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2584 | printk("%s(%d):block_til_ready on %s\n", | ||
2585 | __FILE__,__LINE__, tty->driver->name ); | ||
2586 | |||
2587 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | ||
2588 | /* nonblock mode is set or port is not enabled */ | ||
2589 | /* just verify that callout device is not active */ | ||
2590 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2591 | return 0; | ||
2592 | } | ||
2593 | |||
2594 | if (tty->termios->c_cflag & CLOCAL) | ||
2595 | do_clocal = true; | ||
2596 | |||
2597 | /* Wait for carrier detect and the line to become | ||
2598 | * free (i.e., not in use by the callout). While we are in | ||
2599 | * this loop, info->count is dropped by one, so that | ||
2600 | * mgslpc_close() knows when to free things. We restore it upon | ||
2601 | * exit, either normal or abnormal. | ||
2602 | */ | ||
2603 | |||
2604 | retval = 0; | ||
2605 | add_wait_queue(&info->open_wait, &wait); | ||
2606 | |||
2607 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2608 | printk("%s(%d):block_til_ready before block on %s count=%d\n", | ||
2609 | __FILE__,__LINE__, tty->driver->name, info->count ); | ||
2610 | |||
2611 | spin_lock_irqsave(&info->lock, flags); | ||
2612 | if (!tty_hung_up_p(filp)) { | ||
2613 | extra_count = true; | ||
2614 | info->count--; | ||
2615 | } | ||
2616 | spin_unlock_irqrestore(&info->lock, flags); | ||
2617 | info->blocked_open++; | ||
2618 | |||
2619 | while (1) { | ||
2620 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2621 | spin_lock_irqsave(&info->lock,flags); | ||
2622 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2623 | set_signals(info); | ||
2624 | spin_unlock_irqrestore(&info->lock,flags); | ||
2625 | } | ||
2626 | |||
2627 | set_current_state(TASK_INTERRUPTIBLE); | ||
2628 | |||
2629 | if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){ | ||
2630 | retval = (info->flags & ASYNC_HUP_NOTIFY) ? | ||
2631 | -EAGAIN : -ERESTARTSYS; | ||
2632 | break; | ||
2633 | } | ||
2634 | |||
2635 | spin_lock_irqsave(&info->lock,flags); | ||
2636 | get_signals(info); | ||
2637 | spin_unlock_irqrestore(&info->lock,flags); | ||
2638 | |||
2639 | if (!(info->flags & ASYNC_CLOSING) && | ||
2640 | (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { | ||
2641 | break; | ||
2642 | } | ||
2643 | |||
2644 | if (signal_pending(current)) { | ||
2645 | retval = -ERESTARTSYS; | ||
2646 | break; | ||
2647 | } | ||
2648 | |||
2649 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2650 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | ||
2651 | __FILE__,__LINE__, tty->driver->name, info->count ); | ||
2652 | |||
2653 | schedule(); | ||
2654 | } | ||
2655 | |||
2656 | set_current_state(TASK_RUNNING); | ||
2657 | remove_wait_queue(&info->open_wait, &wait); | ||
2658 | 2520 | ||
2659 | if (extra_count) | 2521 | spin_lock_irqsave(&info->lock,flags); |
2660 | info->count++; | 2522 | get_signals(info); |
2661 | info->blocked_open--; | 2523 | spin_unlock_irqrestore(&info->lock,flags); |
2662 | 2524 | ||
2663 | if (debug_level >= DEBUG_LEVEL_INFO) | 2525 | if (info->serial_signals & SerialSignal_DCD) |
2664 | printk("%s(%d):block_til_ready after blocking on %s count=%d\n", | 2526 | return 1; |
2665 | __FILE__,__LINE__, tty->driver->name, info->count ); | 2527 | return 0; |
2528 | } | ||
2666 | 2529 | ||
2667 | if (!retval) | 2530 | static void raise_dtr_rts(struct tty_port *port) |
2668 | info->flags |= ASYNC_NORMAL_ACTIVE; | 2531 | { |
2532 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); | ||
2533 | unsigned long flags; | ||
2669 | 2534 | ||
2670 | return retval; | 2535 | spin_lock_irqsave(&info->lock,flags); |
2536 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2537 | set_signals(info); | ||
2538 | spin_unlock_irqrestore(&info->lock,flags); | ||
2671 | } | 2539 | } |
2672 | 2540 | ||
2541 | |||
2673 | static int mgslpc_open(struct tty_struct *tty, struct file * filp) | 2542 | static int mgslpc_open(struct tty_struct *tty, struct file * filp) |
2674 | { | 2543 | { |
2675 | MGSLPC_INFO *info; | 2544 | MGSLPC_INFO *info; |
2545 | struct tty_port *port; | ||
2676 | int retval, line; | 2546 | int retval, line; |
2677 | unsigned long flags; | 2547 | unsigned long flags; |
2678 | 2548 | ||
@@ -2691,23 +2561,24 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2691 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open")) | 2561 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open")) |
2692 | return -ENODEV; | 2562 | return -ENODEV; |
2693 | 2563 | ||
2564 | port = &info->port; | ||
2694 | tty->driver_data = info; | 2565 | tty->driver_data = info; |
2695 | info->tty = tty; | 2566 | tty_port_tty_set(port, tty); |
2696 | 2567 | ||
2697 | if (debug_level >= DEBUG_LEVEL_INFO) | 2568 | if (debug_level >= DEBUG_LEVEL_INFO) |
2698 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", | 2569 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", |
2699 | __FILE__,__LINE__,tty->driver->name, info->count); | 2570 | __FILE__,__LINE__,tty->driver->name, port->count); |
2700 | 2571 | ||
2701 | /* If port is closing, signal caller to try again */ | 2572 | /* If port is closing, signal caller to try again */ |
2702 | if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){ | 2573 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ |
2703 | if (info->flags & ASYNC_CLOSING) | 2574 | if (port->flags & ASYNC_CLOSING) |
2704 | interruptible_sleep_on(&info->close_wait); | 2575 | interruptible_sleep_on(&port->close_wait); |
2705 | retval = ((info->flags & ASYNC_HUP_NOTIFY) ? | 2576 | retval = ((port->flags & ASYNC_HUP_NOTIFY) ? |
2706 | -EAGAIN : -ERESTARTSYS); | 2577 | -EAGAIN : -ERESTARTSYS); |
2707 | goto cleanup; | 2578 | goto cleanup; |
2708 | } | 2579 | } |
2709 | 2580 | ||
2710 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 2581 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
2711 | 2582 | ||
2712 | spin_lock_irqsave(&info->netlock, flags); | 2583 | spin_lock_irqsave(&info->netlock, flags); |
2713 | if (info->netcount) { | 2584 | if (info->netcount) { |
@@ -2715,17 +2586,19 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2715 | spin_unlock_irqrestore(&info->netlock, flags); | 2586 | spin_unlock_irqrestore(&info->netlock, flags); |
2716 | goto cleanup; | 2587 | goto cleanup; |
2717 | } | 2588 | } |
2718 | info->count++; | 2589 | spin_lock(&port->lock); |
2590 | port->count++; | ||
2591 | spin_unlock(&port->lock); | ||
2719 | spin_unlock_irqrestore(&info->netlock, flags); | 2592 | spin_unlock_irqrestore(&info->netlock, flags); |
2720 | 2593 | ||
2721 | if (info->count == 1) { | 2594 | if (port->count == 1) { |
2722 | /* 1st open on this device, init hardware */ | 2595 | /* 1st open on this device, init hardware */ |
2723 | retval = startup(info); | 2596 | retval = startup(info, tty); |
2724 | if (retval < 0) | 2597 | if (retval < 0) |
2725 | goto cleanup; | 2598 | goto cleanup; |
2726 | } | 2599 | } |
2727 | 2600 | ||
2728 | retval = block_til_ready(tty, filp, info); | 2601 | retval = tty_port_block_til_ready(&info->port, tty, filp); |
2729 | if (retval) { | 2602 | if (retval) { |
2730 | if (debug_level >= DEBUG_LEVEL_INFO) | 2603 | if (debug_level >= DEBUG_LEVEL_INFO) |
2731 | printk("%s(%d):block_til_ready(%s) returned %d\n", | 2604 | printk("%s(%d):block_til_ready(%s) returned %d\n", |
@@ -2739,13 +2612,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2739 | retval = 0; | 2612 | retval = 0; |
2740 | 2613 | ||
2741 | cleanup: | 2614 | cleanup: |
2742 | if (retval) { | ||
2743 | if (tty->count == 1) | ||
2744 | info->tty = NULL; /* tty layer will release tty struct */ | ||
2745 | if(info->count) | ||
2746 | info->count--; | ||
2747 | } | ||
2748 | |||
2749 | return retval; | 2615 | return retval; |
2750 | } | 2616 | } |
2751 | 2617 | ||
@@ -3500,7 +3366,7 @@ static void rx_start(MGSLPC_INFO *info) | |||
3500 | info->rx_enabled = true; | 3366 | info->rx_enabled = true; |
3501 | } | 3367 | } |
3502 | 3368 | ||
3503 | static void tx_start(MGSLPC_INFO *info) | 3369 | static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty) |
3504 | { | 3370 | { |
3505 | if (debug_level >= DEBUG_LEVEL_ISR) | 3371 | if (debug_level >= DEBUG_LEVEL_ISR) |
3506 | printk("%s(%d):tx_start(%s)\n", | 3372 | printk("%s(%d):tx_start(%s)\n", |
@@ -3524,11 +3390,11 @@ static void tx_start(MGSLPC_INFO *info) | |||
3524 | if (info->params.mode == MGSL_MODE_ASYNC) { | 3390 | if (info->params.mode == MGSL_MODE_ASYNC) { |
3525 | if (!info->tx_active) { | 3391 | if (!info->tx_active) { |
3526 | info->tx_active = true; | 3392 | info->tx_active = true; |
3527 | tx_ready(info); | 3393 | tx_ready(info, tty); |
3528 | } | 3394 | } |
3529 | } else { | 3395 | } else { |
3530 | info->tx_active = true; | 3396 | info->tx_active = true; |
3531 | tx_ready(info); | 3397 | tx_ready(info, tty); |
3532 | mod_timer(&info->tx_timer, jiffies + | 3398 | mod_timer(&info->tx_timer, jiffies + |
3533 | msecs_to_jiffies(5000)); | 3399 | msecs_to_jiffies(5000)); |
3534 | } | 3400 | } |
@@ -3849,13 +3715,12 @@ static void rx_reset_buffers(MGSLPC_INFO *info) | |||
3849 | * | 3715 | * |
3850 | * Returns true if frame returned, otherwise false | 3716 | * Returns true if frame returned, otherwise false |
3851 | */ | 3717 | */ |
3852 | static bool rx_get_frame(MGSLPC_INFO *info) | 3718 | static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty) |
3853 | { | 3719 | { |
3854 | unsigned short status; | 3720 | unsigned short status; |
3855 | RXBUF *buf; | 3721 | RXBUF *buf; |
3856 | unsigned int framesize = 0; | 3722 | unsigned int framesize = 0; |
3857 | unsigned long flags; | 3723 | unsigned long flags; |
3858 | struct tty_struct *tty = info->tty; | ||
3859 | bool return_frame = false; | 3724 | bool return_frame = false; |
3860 | 3725 | ||
3861 | if (info->rx_frame_count == 0) | 3726 | if (info->rx_frame_count == 0) |
@@ -4075,7 +3940,11 @@ static void tx_timeout(unsigned long context) | |||
4075 | hdlcdev_tx_done(info); | 3940 | hdlcdev_tx_done(info); |
4076 | else | 3941 | else |
4077 | #endif | 3942 | #endif |
4078 | bh_transmit(info); | 3943 | { |
3944 | struct tty_struct *tty = tty_port_tty_get(&info->port); | ||
3945 | bh_transmit(info, tty); | ||
3946 | tty_kref_put(tty); | ||
3947 | } | ||
4079 | } | 3948 | } |
4080 | 3949 | ||
4081 | #if SYNCLINK_GENERIC_HDLC | 3950 | #if SYNCLINK_GENERIC_HDLC |
@@ -4094,11 +3963,12 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, | |||
4094 | unsigned short parity) | 3963 | unsigned short parity) |
4095 | { | 3964 | { |
4096 | MGSLPC_INFO *info = dev_to_port(dev); | 3965 | MGSLPC_INFO *info = dev_to_port(dev); |
3966 | struct tty_struct *tty; | ||
4097 | unsigned char new_encoding; | 3967 | unsigned char new_encoding; |
4098 | unsigned short new_crctype; | 3968 | unsigned short new_crctype; |
4099 | 3969 | ||
4100 | /* return error if TTY interface open */ | 3970 | /* return error if TTY interface open */ |
4101 | if (info->count) | 3971 | if (info->port.count) |
4102 | return -EBUSY; | 3972 | return -EBUSY; |
4103 | 3973 | ||
4104 | switch (encoding) | 3974 | switch (encoding) |
@@ -4123,8 +3993,11 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, | |||
4123 | info->params.crc_type = new_crctype; | 3993 | info->params.crc_type = new_crctype; |
4124 | 3994 | ||
4125 | /* if network interface up, reprogram hardware */ | 3995 | /* if network interface up, reprogram hardware */ |
4126 | if (info->netcount) | 3996 | if (info->netcount) { |
4127 | mgslpc_program_hw(info); | 3997 | tty = tty_port_tty_get(&info->port); |
3998 | mgslpc_program_hw(info, tty); | ||
3999 | tty_kref_put(tty); | ||
4000 | } | ||
4128 | 4001 | ||
4129 | return 0; | 4002 | return 0; |
4130 | } | 4003 | } |
@@ -4165,8 +4038,11 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4165 | 4038 | ||
4166 | /* start hardware transmitter if necessary */ | 4039 | /* start hardware transmitter if necessary */ |
4167 | spin_lock_irqsave(&info->lock,flags); | 4040 | spin_lock_irqsave(&info->lock,flags); |
4168 | if (!info->tx_active) | 4041 | if (!info->tx_active) { |
4169 | tx_start(info); | 4042 | struct tty_struct *tty = tty_port_tty_get(&info->port); |
4043 | tx_start(info, tty); | ||
4044 | tty_kref_put(tty); | ||
4045 | } | ||
4170 | spin_unlock_irqrestore(&info->lock,flags); | 4046 | spin_unlock_irqrestore(&info->lock,flags); |
4171 | 4047 | ||
4172 | return 0; | 4048 | return 0; |
@@ -4183,6 +4059,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4183 | static int hdlcdev_open(struct net_device *dev) | 4059 | static int hdlcdev_open(struct net_device *dev) |
4184 | { | 4060 | { |
4185 | MGSLPC_INFO *info = dev_to_port(dev); | 4061 | MGSLPC_INFO *info = dev_to_port(dev); |
4062 | struct tty_struct *tty; | ||
4186 | int rc; | 4063 | int rc; |
4187 | unsigned long flags; | 4064 | unsigned long flags; |
4188 | 4065 | ||
@@ -4195,7 +4072,7 @@ static int hdlcdev_open(struct net_device *dev) | |||
4195 | 4072 | ||
4196 | /* arbitrate between network and tty opens */ | 4073 | /* arbitrate between network and tty opens */ |
4197 | spin_lock_irqsave(&info->netlock, flags); | 4074 | spin_lock_irqsave(&info->netlock, flags); |
4198 | if (info->count != 0 || info->netcount != 0) { | 4075 | if (info->port.count != 0 || info->netcount != 0) { |
4199 | printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); | 4076 | printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); |
4200 | spin_unlock_irqrestore(&info->netlock, flags); | 4077 | spin_unlock_irqrestore(&info->netlock, flags); |
4201 | return -EBUSY; | 4078 | return -EBUSY; |
@@ -4203,17 +4080,19 @@ static int hdlcdev_open(struct net_device *dev) | |||
4203 | info->netcount=1; | 4080 | info->netcount=1; |
4204 | spin_unlock_irqrestore(&info->netlock, flags); | 4081 | spin_unlock_irqrestore(&info->netlock, flags); |
4205 | 4082 | ||
4083 | tty = tty_port_tty_get(&info->port); | ||
4206 | /* claim resources and init adapter */ | 4084 | /* claim resources and init adapter */ |
4207 | if ((rc = startup(info)) != 0) { | 4085 | if ((rc = startup(info, tty)) != 0) { |
4086 | tty_kref_put(tty); | ||
4208 | spin_lock_irqsave(&info->netlock, flags); | 4087 | spin_lock_irqsave(&info->netlock, flags); |
4209 | info->netcount=0; | 4088 | info->netcount=0; |
4210 | spin_unlock_irqrestore(&info->netlock, flags); | 4089 | spin_unlock_irqrestore(&info->netlock, flags); |
4211 | return rc; | 4090 | return rc; |
4212 | } | 4091 | } |
4213 | |||
4214 | /* assert DTR and RTS, apply hardware settings */ | 4092 | /* assert DTR and RTS, apply hardware settings */ |
4215 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 4093 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; |
4216 | mgslpc_program_hw(info); | 4094 | mgslpc_program_hw(info, tty); |
4095 | tty_kref_put(tty); | ||
4217 | 4096 | ||
4218 | /* enable network layer transmit */ | 4097 | /* enable network layer transmit */ |
4219 | dev->trans_start = jiffies; | 4098 | dev->trans_start = jiffies; |
@@ -4241,6 +4120,7 @@ static int hdlcdev_open(struct net_device *dev) | |||
4241 | static int hdlcdev_close(struct net_device *dev) | 4120 | static int hdlcdev_close(struct net_device *dev) |
4242 | { | 4121 | { |
4243 | MGSLPC_INFO *info = dev_to_port(dev); | 4122 | MGSLPC_INFO *info = dev_to_port(dev); |
4123 | struct tty_struct *tty = tty_port_tty_get(&info->port); | ||
4244 | unsigned long flags; | 4124 | unsigned long flags; |
4245 | 4125 | ||
4246 | if (debug_level >= DEBUG_LEVEL_INFO) | 4126 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -4249,8 +4129,8 @@ static int hdlcdev_close(struct net_device *dev) | |||
4249 | netif_stop_queue(dev); | 4129 | netif_stop_queue(dev); |
4250 | 4130 | ||
4251 | /* shutdown adapter and release resources */ | 4131 | /* shutdown adapter and release resources */ |
4252 | shutdown(info); | 4132 | shutdown(info, tty); |
4253 | 4133 | tty_kref_put(tty); | |
4254 | hdlc_close(dev); | 4134 | hdlc_close(dev); |
4255 | 4135 | ||
4256 | spin_lock_irqsave(&info->netlock, flags); | 4136 | spin_lock_irqsave(&info->netlock, flags); |
@@ -4281,7 +4161,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4281 | printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); | 4161 | printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); |
4282 | 4162 | ||
4283 | /* return error if TTY interface open */ | 4163 | /* return error if TTY interface open */ |
4284 | if (info->count) | 4164 | if (info->port.count) |
4285 | return -EBUSY; | 4165 | return -EBUSY; |
4286 | 4166 | ||
4287 | if (cmd != SIOCWANDEV) | 4167 | if (cmd != SIOCWANDEV) |
@@ -4354,8 +4234,11 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4354 | info->params.clock_speed = 0; | 4234 | info->params.clock_speed = 0; |
4355 | 4235 | ||
4356 | /* if network interface up, reprogram hardware */ | 4236 | /* if network interface up, reprogram hardware */ |
4357 | if (info->netcount) | 4237 | if (info->netcount) { |
4358 | mgslpc_program_hw(info); | 4238 | struct tty_struct *tty = tty_port_tty_get(&info->port); |
4239 | mgslpc_program_hw(info, tty); | ||
4240 | tty_kref_put(tty); | ||
4241 | } | ||
4359 | return 0; | 4242 | return 0; |
4360 | 4243 | ||
4361 | default: | 4244 | default: |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 6d4582712b1f..112a6ba9a96f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Added support for a Unix98-style ptmx device. | 6 | * Added support for a Unix98-style ptmx device. |
7 | * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 | 7 | * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 |
8 | * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to | ||
9 | * waiting writers -- Sapan Bhatia <sapan@corewars.org> | ||
10 | * | 8 | * |
11 | * When reading this code see also fs/devpts. In particular note that the | 9 | * When reading this code see also fs/devpts. In particular note that the |
12 | * driver_data field is used by the devpts side as a binding to the devpts | 10 | * driver_data field is used by the devpts side as a binding to the devpts |
@@ -217,7 +215,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp) | |||
217 | 215 | ||
218 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); | 216 | clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); |
219 | set_bit(TTY_THROTTLED, &tty->flags); | 217 | set_bit(TTY_THROTTLED, &tty->flags); |
220 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
221 | retval = 0; | 218 | retval = 0; |
222 | out: | 219 | out: |
223 | return retval; | 220 | return retval; |
@@ -230,6 +227,55 @@ static void pty_set_termios(struct tty_struct *tty, | |||
230 | tty->termios->c_cflag |= (CS8 | CREAD); | 227 | tty->termios->c_cflag |= (CS8 | CREAD); |
231 | } | 228 | } |
232 | 229 | ||
230 | /** | ||
231 | * pty_do_resize - resize event | ||
232 | * @tty: tty being resized | ||
233 | * @real_tty: real tty (not the same as tty if using a pty/tty pair) | ||
234 | * @rows: rows (character) | ||
235 | * @cols: cols (character) | ||
236 | * | ||
237 | * Update the termios variables and send the neccessary signals to | ||
238 | * peform a terminal resize correctly | ||
239 | */ | ||
240 | |||
241 | int pty_resize(struct tty_struct *tty, struct winsize *ws) | ||
242 | { | ||
243 | struct pid *pgrp, *rpgrp; | ||
244 | unsigned long flags; | ||
245 | struct tty_struct *pty = tty->link; | ||
246 | |||
247 | /* For a PTY we need to lock the tty side */ | ||
248 | mutex_lock(&tty->termios_mutex); | ||
249 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) | ||
250 | goto done; | ||
251 | |||
252 | /* Get the PID values and reference them so we can | ||
253 | avoid holding the tty ctrl lock while sending signals. | ||
254 | We need to lock these individually however. */ | ||
255 | |||
256 | spin_lock_irqsave(&tty->ctrl_lock, flags); | ||
257 | pgrp = get_pid(tty->pgrp); | ||
258 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | ||
259 | |||
260 | spin_lock_irqsave(&pty->ctrl_lock, flags); | ||
261 | rpgrp = get_pid(pty->pgrp); | ||
262 | spin_unlock_irqrestore(&pty->ctrl_lock, flags); | ||
263 | |||
264 | if (pgrp) | ||
265 | kill_pgrp(pgrp, SIGWINCH, 1); | ||
266 | if (rpgrp != pgrp && rpgrp) | ||
267 | kill_pgrp(rpgrp, SIGWINCH, 1); | ||
268 | |||
269 | put_pid(pgrp); | ||
270 | put_pid(rpgrp); | ||
271 | |||
272 | tty->winsize = *ws; | ||
273 | pty->winsize = *ws; /* Never used so will go away soon */ | ||
274 | done: | ||
275 | mutex_unlock(&tty->termios_mutex); | ||
276 | return 0; | ||
277 | } | ||
278 | |||
233 | static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | 279 | static int pty_install(struct tty_driver *driver, struct tty_struct *tty) |
234 | { | 280 | { |
235 | struct tty_struct *o_tty; | 281 | struct tty_struct *o_tty; |
@@ -290,6 +336,7 @@ static const struct tty_operations pty_ops = { | |||
290 | .chars_in_buffer = pty_chars_in_buffer, | 336 | .chars_in_buffer = pty_chars_in_buffer, |
291 | .unthrottle = pty_unthrottle, | 337 | .unthrottle = pty_unthrottle, |
292 | .set_termios = pty_set_termios, | 338 | .set_termios = pty_set_termios, |
339 | .resize = pty_resize | ||
293 | }; | 340 | }; |
294 | 341 | ||
295 | /* Traditional BSD devices */ | 342 | /* Traditional BSD devices */ |
@@ -319,6 +366,7 @@ static const struct tty_operations pty_ops_bsd = { | |||
319 | .unthrottle = pty_unthrottle, | 366 | .unthrottle = pty_unthrottle, |
320 | .set_termios = pty_set_termios, | 367 | .set_termios = pty_set_termios, |
321 | .ioctl = pty_bsd_ioctl, | 368 | .ioctl = pty_bsd_ioctl, |
369 | .resize = pty_resize | ||
322 | }; | 370 | }; |
323 | 371 | ||
324 | static void __init legacy_pty_init(void) | 372 | static void __init legacy_pty_init(void) |
@@ -561,7 +609,8 @@ static const struct tty_operations ptm_unix98_ops = { | |||
561 | .unthrottle = pty_unthrottle, | 609 | .unthrottle = pty_unthrottle, |
562 | .set_termios = pty_set_termios, | 610 | .set_termios = pty_set_termios, |
563 | .ioctl = pty_unix98_ioctl, | 611 | .ioctl = pty_unix98_ioctl, |
564 | .shutdown = pty_unix98_shutdown | 612 | .shutdown = pty_unix98_shutdown, |
613 | .resize = pty_resize | ||
565 | }; | 614 | }; |
566 | 615 | ||
567 | static const struct tty_operations pty_unix98_ops = { | 616 | static const struct tty_operations pty_unix98_ops = { |
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index a8f68a3f14dd..2e8a6eed34be 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c | |||
@@ -173,7 +173,7 @@ static void rio_disable_tx_interrupts(void *ptr); | |||
173 | static void rio_enable_tx_interrupts(void *ptr); | 173 | static void rio_enable_tx_interrupts(void *ptr); |
174 | static void rio_disable_rx_interrupts(void *ptr); | 174 | static void rio_disable_rx_interrupts(void *ptr); |
175 | static void rio_enable_rx_interrupts(void *ptr); | 175 | static void rio_enable_rx_interrupts(void *ptr); |
176 | static int rio_get_CD(void *ptr); | 176 | static int rio_carrier_raised(struct tty_port *port); |
177 | static void rio_shutdown_port(void *ptr); | 177 | static void rio_shutdown_port(void *ptr); |
178 | static int rio_set_real_termios(void *ptr); | 178 | static int rio_set_real_termios(void *ptr); |
179 | static void rio_hungup(void *ptr); | 179 | static void rio_hungup(void *ptr); |
@@ -224,7 +224,6 @@ static struct real_driver rio_real_driver = { | |||
224 | rio_enable_tx_interrupts, | 224 | rio_enable_tx_interrupts, |
225 | rio_disable_rx_interrupts, | 225 | rio_disable_rx_interrupts, |
226 | rio_enable_rx_interrupts, | 226 | rio_enable_rx_interrupts, |
227 | rio_get_CD, | ||
228 | rio_shutdown_port, | 227 | rio_shutdown_port, |
229 | rio_set_real_termios, | 228 | rio_set_real_termios, |
230 | rio_chars_in_buffer, | 229 | rio_chars_in_buffer, |
@@ -476,9 +475,9 @@ static void rio_enable_rx_interrupts(void *ptr) | |||
476 | 475 | ||
477 | 476 | ||
478 | /* Jeez. Isn't this simple? */ | 477 | /* Jeez. Isn't this simple? */ |
479 | static int rio_get_CD(void *ptr) | 478 | static int rio_carrier_raised(struct tty_port *port) |
480 | { | 479 | { |
481 | struct Port *PortP = ptr; | 480 | struct Port *PortP = container_of(port, struct Port, gs.port); |
482 | int rv; | 481 | int rv; |
483 | 482 | ||
484 | func_enter(); | 483 | func_enter(); |
@@ -797,16 +796,9 @@ static int rio_init_drivers(void) | |||
797 | return 1; | 796 | return 1; |
798 | } | 797 | } |
799 | 798 | ||
800 | 799 | static const struct tty_port_operations rio_port_ops = { | |
801 | static void *ckmalloc(int size) | 800 | .carrier_raised = rio_carrier_raised, |
802 | { | 801 | }; |
803 | void *p; | ||
804 | |||
805 | p = kzalloc(size, GFP_KERNEL); | ||
806 | return p; | ||
807 | } | ||
808 | |||
809 | |||
810 | 802 | ||
811 | static int rio_init_datastructures(void) | 803 | static int rio_init_datastructures(void) |
812 | { | 804 | { |
@@ -826,33 +818,30 @@ static int rio_init_datastructures(void) | |||
826 | #define TMIO_SZ sizeof(struct termios *) | 818 | #define TMIO_SZ sizeof(struct termios *) |
827 | rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); | 819 | rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); |
828 | 820 | ||
829 | if (!(p = ckmalloc(RI_SZ))) | 821 | if (!(p = kzalloc(RI_SZ, GFP_KERNEL))) |
830 | goto free0; | 822 | goto free0; |
831 | if (!(p->RIOHosts = ckmalloc(RIO_HOSTS * HOST_SZ))) | 823 | if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL))) |
832 | goto free1; | 824 | goto free1; |
833 | if (!(p->RIOPortp = ckmalloc(RIO_PORTS * PORT_SZ))) | 825 | if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL))) |
834 | goto free2; | 826 | goto free2; |
835 | p->RIOConf = RIOConf; | 827 | p->RIOConf = RIOConf; |
836 | rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp); | 828 | rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp); |
837 | 829 | ||
838 | #if 1 | 830 | #if 1 |
839 | for (i = 0; i < RIO_PORTS; i++) { | 831 | for (i = 0; i < RIO_PORTS; i++) { |
840 | port = p->RIOPortp[i] = ckmalloc(sizeof(struct Port)); | 832 | port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL); |
841 | if (!port) { | 833 | if (!port) { |
842 | goto free6; | 834 | goto free6; |
843 | } | 835 | } |
844 | rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); | 836 | rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); |
837 | tty_port_init(&port->gs.port); | ||
838 | port->gs.port.ops = &rio_port_ops; | ||
845 | port->PortNum = i; | 839 | port->PortNum = i; |
846 | port->gs.magic = RIO_MAGIC; | 840 | port->gs.magic = RIO_MAGIC; |
847 | port->gs.close_delay = HZ / 2; | 841 | port->gs.close_delay = HZ / 2; |
848 | port->gs.closing_wait = 30 * HZ; | 842 | port->gs.closing_wait = 30 * HZ; |
849 | port->gs.rd = &rio_real_driver; | 843 | port->gs.rd = &rio_real_driver; |
850 | spin_lock_init(&port->portSem); | 844 | spin_lock_init(&port->portSem); |
851 | /* | ||
852 | * Initializing wait queue | ||
853 | */ | ||
854 | init_waitqueue_head(&port->gs.port.open_wait); | ||
855 | init_waitqueue_head(&port->gs.port.close_wait); | ||
856 | } | 845 | } |
857 | #else | 846 | #else |
858 | /* We could postpone initializing them to when they are configured. */ | 847 | /* We could postpone initializing them to when they are configured. */ |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 2c6c8f33d6b4..9af8d74875bc 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -857,98 +857,21 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
857 | rc_shutdown_board(bp); | 857 | rc_shutdown_board(bp); |
858 | } | 858 | } |
859 | 859 | ||
860 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 860 | static int carrier_raised(struct tty_port *port) |
861 | struct riscom_port *port) | ||
862 | { | 861 | { |
863 | DECLARE_WAITQUEUE(wait, current); | 862 | struct riscom_port *p = container_of(port, struct riscom_port, port); |
864 | struct riscom_board *bp = port_Board(port); | 863 | struct riscom_board *bp = port_Board(p); |
865 | int retval; | ||
866 | int do_clocal = 0; | ||
867 | int CD; | ||
868 | unsigned long flags; | 864 | unsigned long flags; |
869 | 865 | int CD; | |
870 | /* | 866 | |
871 | * If the device is in the middle of being closed, then block | ||
872 | * until it's done, and then try again. | ||
873 | */ | ||
874 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | ||
875 | interruptible_sleep_on(&port->port.close_wait); | ||
876 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
877 | return -EAGAIN; | ||
878 | else | ||
879 | return -ERESTARTSYS; | ||
880 | } | ||
881 | |||
882 | /* | ||
883 | * If non-blocking mode is set, or the port is not enabled, | ||
884 | * then make the check up front and then exit. | ||
885 | */ | ||
886 | if ((filp->f_flags & O_NONBLOCK) || | ||
887 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
888 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | if (C_CLOCAL(tty)) | ||
893 | do_clocal = 1; | ||
894 | |||
895 | /* | ||
896 | * Block waiting for the carrier detect and the line to become | ||
897 | * free (i.e., not in use by the callout). While we are in | ||
898 | * this loop, info->count is dropped by one, so that | ||
899 | * rs_close() knows when to free things. We restore it upon | ||
900 | * exit, either normal or abnormal. | ||
901 | */ | ||
902 | retval = 0; | ||
903 | add_wait_queue(&port->port.open_wait, &wait); | ||
904 | |||
905 | spin_lock_irqsave(&riscom_lock, flags); | 867 | spin_lock_irqsave(&riscom_lock, flags); |
906 | 868 | rc_out(bp, CD180_CAR, port_No(p)); | |
907 | if (!tty_hung_up_p(filp)) | 869 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; |
908 | port->port.count--; | 870 | rc_out(bp, CD180_MSVR, MSVR_RTS); |
909 | 871 | bp->DTR &= ~(1u << port_No(p)); | |
872 | rc_out(bp, RC_DTR, bp->DTR); | ||
910 | spin_unlock_irqrestore(&riscom_lock, flags); | 873 | spin_unlock_irqrestore(&riscom_lock, flags); |
911 | 874 | return CD; | |
912 | port->port.blocked_open++; | ||
913 | while (1) { | ||
914 | spin_lock_irqsave(&riscom_lock, flags); | ||
915 | |||
916 | rc_out(bp, CD180_CAR, port_No(port)); | ||
917 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | ||
918 | rc_out(bp, CD180_MSVR, MSVR_RTS); | ||
919 | bp->DTR &= ~(1u << port_No(port)); | ||
920 | rc_out(bp, RC_DTR, bp->DTR); | ||
921 | |||
922 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
923 | |||
924 | set_current_state(TASK_INTERRUPTIBLE); | ||
925 | if (tty_hung_up_p(filp) || | ||
926 | !(port->port.flags & ASYNC_INITIALIZED)) { | ||
927 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
928 | retval = -EAGAIN; | ||
929 | else | ||
930 | retval = -ERESTARTSYS; | ||
931 | break; | ||
932 | } | ||
933 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
934 | (do_clocal || CD)) | ||
935 | break; | ||
936 | if (signal_pending(current)) { | ||
937 | retval = -ERESTARTSYS; | ||
938 | break; | ||
939 | } | ||
940 | schedule(); | ||
941 | } | ||
942 | __set_current_state(TASK_RUNNING); | ||
943 | remove_wait_queue(&port->port.open_wait, &wait); | ||
944 | if (!tty_hung_up_p(filp)) | ||
945 | port->port.count++; | ||
946 | port->port.blocked_open--; | ||
947 | if (retval) | ||
948 | return retval; | ||
949 | |||
950 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
951 | return 0; | ||
952 | } | 875 | } |
953 | 876 | ||
954 | static int rc_open(struct tty_struct *tty, struct file *filp) | 877 | static int rc_open(struct tty_struct *tty, struct file *filp) |
@@ -977,13 +900,13 @@ static int rc_open(struct tty_struct *tty, struct file *filp) | |||
977 | 900 | ||
978 | error = rc_setup_port(bp, port); | 901 | error = rc_setup_port(bp, port); |
979 | if (error == 0) | 902 | if (error == 0) |
980 | error = block_til_ready(tty, filp, port); | 903 | error = tty_port_block_til_ready(&port->port, tty, filp); |
981 | return error; | 904 | return error; |
982 | } | 905 | } |
983 | 906 | ||
984 | static void rc_flush_buffer(struct tty_struct *tty) | 907 | static void rc_flush_buffer(struct tty_struct *tty) |
985 | { | 908 | { |
986 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 909 | struct riscom_port *port = tty->driver_data; |
987 | unsigned long flags; | 910 | unsigned long flags; |
988 | 911 | ||
989 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) | 912 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) |
@@ -998,7 +921,7 @@ static void rc_flush_buffer(struct tty_struct *tty) | |||
998 | 921 | ||
999 | static void rc_close(struct tty_struct *tty, struct file *filp) | 922 | static void rc_close(struct tty_struct *tty, struct file *filp) |
1000 | { | 923 | { |
1001 | struct riscom_port *port = (struct riscom_port *) tty->driver_data; | 924 | struct riscom_port *port = tty->driver_data; |
1002 | struct riscom_board *bp; | 925 | struct riscom_board *bp; |
1003 | unsigned long flags; | 926 | unsigned long flags; |
1004 | unsigned long timeout; | 927 | unsigned long timeout; |
@@ -1006,40 +929,19 @@ static void rc_close(struct tty_struct *tty, struct file *filp) | |||
1006 | if (!port || rc_paranoia_check(port, tty->name, "close")) | 929 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
1007 | return; | 930 | return; |
1008 | 931 | ||
1009 | spin_lock_irqsave(&riscom_lock, flags); | ||
1010 | |||
1011 | if (tty_hung_up_p(filp)) | ||
1012 | goto out; | ||
1013 | |||
1014 | bp = port_Board(port); | 932 | bp = port_Board(port); |
1015 | if ((tty->count == 1) && (port->port.count != 1)) { | 933 | |
1016 | printk(KERN_INFO "rc%d: rc_close: bad port count;" | 934 | if (tty_port_close_start(&port->port, tty, filp) == 0) |
1017 | " tty->count is 1, port count is %d\n", | 935 | return; |
1018 | board_No(bp), port->port.count); | 936 | |
1019 | port->port.count = 1; | ||
1020 | } | ||
1021 | if (--port->port.count < 0) { | ||
1022 | printk(KERN_INFO "rc%d: rc_close: bad port count " | ||
1023 | "for tty%d: %d\n", | ||
1024 | board_No(bp), port_No(port), port->port.count); | ||
1025 | port->port.count = 0; | ||
1026 | } | ||
1027 | if (port->port.count) | ||
1028 | goto out; | ||
1029 | port->port.flags |= ASYNC_CLOSING; | ||
1030 | /* | ||
1031 | * Now we wait for the transmit buffer to clear; and we notify | ||
1032 | * the line discipline to only process XON/XOFF characters. | ||
1033 | */ | ||
1034 | tty->closing = 1; | ||
1035 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1036 | tty_wait_until_sent(tty, port->port.closing_wait); | ||
1037 | /* | 937 | /* |
1038 | * At this point we stop accepting input. To do this, we | 938 | * At this point we stop accepting input. To do this, we |
1039 | * disable the receive line status interrupts, and tell the | 939 | * disable the receive line status interrupts, and tell the |
1040 | * interrupt driver to stop checking the data ready bit in the | 940 | * interrupt driver to stop checking the data ready bit in the |
1041 | * line status register. | 941 | * line status register. |
1042 | */ | 942 | */ |
943 | |||
944 | spin_lock_irqsave(&riscom_lock, flags); | ||
1043 | port->IER &= ~IER_RXD; | 945 | port->IER &= ~IER_RXD; |
1044 | if (port->port.flags & ASYNC_INITIALIZED) { | 946 | if (port->port.flags & ASYNC_INITIALIZED) { |
1045 | port->IER &= ~IER_TXRDY; | 947 | port->IER &= ~IER_TXRDY; |
@@ -1053,33 +955,24 @@ static void rc_close(struct tty_struct *tty, struct file *filp) | |||
1053 | */ | 955 | */ |
1054 | timeout = jiffies + HZ; | 956 | timeout = jiffies + HZ; |
1055 | while (port->IER & IER_TXEMPTY) { | 957 | while (port->IER & IER_TXEMPTY) { |
958 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1056 | msleep_interruptible(jiffies_to_msecs(port->timeout)); | 959 | msleep_interruptible(jiffies_to_msecs(port->timeout)); |
960 | spin_lock_irqsave(&riscom_lock, flags); | ||
1057 | if (time_after(jiffies, timeout)) | 961 | if (time_after(jiffies, timeout)) |
1058 | break; | 962 | break; |
1059 | } | 963 | } |
1060 | } | 964 | } |
1061 | rc_shutdown_port(tty, bp, port); | 965 | rc_shutdown_port(tty, bp, port); |
1062 | rc_flush_buffer(tty); | 966 | rc_flush_buffer(tty); |
1063 | tty_ldisc_flush(tty); | ||
1064 | |||
1065 | tty->closing = 0; | ||
1066 | port->port.tty = NULL; | ||
1067 | if (port->port.blocked_open) { | ||
1068 | if (port->port.close_delay) | ||
1069 | msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); | ||
1070 | wake_up_interruptible(&port->port.open_wait); | ||
1071 | } | ||
1072 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1073 | wake_up_interruptible(&port->port.close_wait); | ||
1074 | |||
1075 | out: | ||
1076 | spin_unlock_irqrestore(&riscom_lock, flags); | 967 | spin_unlock_irqrestore(&riscom_lock, flags); |
968 | |||
969 | tty_port_close_end(&port->port, tty); | ||
1077 | } | 970 | } |
1078 | 971 | ||
1079 | static int rc_write(struct tty_struct *tty, | 972 | static int rc_write(struct tty_struct *tty, |
1080 | const unsigned char *buf, int count) | 973 | const unsigned char *buf, int count) |
1081 | { | 974 | { |
1082 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 975 | struct riscom_port *port = tty->driver_data; |
1083 | struct riscom_board *bp; | 976 | struct riscom_board *bp; |
1084 | int c, total = 0; | 977 | int c, total = 0; |
1085 | unsigned long flags; | 978 | unsigned long flags; |
@@ -1122,7 +1015,7 @@ static int rc_write(struct tty_struct *tty, | |||
1122 | 1015 | ||
1123 | static int rc_put_char(struct tty_struct *tty, unsigned char ch) | 1016 | static int rc_put_char(struct tty_struct *tty, unsigned char ch) |
1124 | { | 1017 | { |
1125 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1018 | struct riscom_port *port = tty->driver_data; |
1126 | unsigned long flags; | 1019 | unsigned long flags; |
1127 | int ret = 0; | 1020 | int ret = 0; |
1128 | 1021 | ||
@@ -1146,7 +1039,7 @@ out: | |||
1146 | 1039 | ||
1147 | static void rc_flush_chars(struct tty_struct *tty) | 1040 | static void rc_flush_chars(struct tty_struct *tty) |
1148 | { | 1041 | { |
1149 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1042 | struct riscom_port *port = tty->driver_data; |
1150 | unsigned long flags; | 1043 | unsigned long flags; |
1151 | 1044 | ||
1152 | if (rc_paranoia_check(port, tty->name, "rc_flush_chars")) | 1045 | if (rc_paranoia_check(port, tty->name, "rc_flush_chars")) |
@@ -1166,7 +1059,7 @@ static void rc_flush_chars(struct tty_struct *tty) | |||
1166 | 1059 | ||
1167 | static int rc_write_room(struct tty_struct *tty) | 1060 | static int rc_write_room(struct tty_struct *tty) |
1168 | { | 1061 | { |
1169 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1062 | struct riscom_port *port = tty->driver_data; |
1170 | int ret; | 1063 | int ret; |
1171 | 1064 | ||
1172 | if (rc_paranoia_check(port, tty->name, "rc_write_room")) | 1065 | if (rc_paranoia_check(port, tty->name, "rc_write_room")) |
@@ -1180,7 +1073,7 @@ static int rc_write_room(struct tty_struct *tty) | |||
1180 | 1073 | ||
1181 | static int rc_chars_in_buffer(struct tty_struct *tty) | 1074 | static int rc_chars_in_buffer(struct tty_struct *tty) |
1182 | { | 1075 | { |
1183 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1076 | struct riscom_port *port = tty->driver_data; |
1184 | 1077 | ||
1185 | if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer")) | 1078 | if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer")) |
1186 | return 0; | 1079 | return 0; |
@@ -1190,7 +1083,7 @@ static int rc_chars_in_buffer(struct tty_struct *tty) | |||
1190 | 1083 | ||
1191 | static int rc_tiocmget(struct tty_struct *tty, struct file *file) | 1084 | static int rc_tiocmget(struct tty_struct *tty, struct file *file) |
1192 | { | 1085 | { |
1193 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1086 | struct riscom_port *port = tty->driver_data; |
1194 | struct riscom_board *bp; | 1087 | struct riscom_board *bp; |
1195 | unsigned char status; | 1088 | unsigned char status; |
1196 | unsigned int result; | 1089 | unsigned int result; |
@@ -1220,7 +1113,7 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file) | |||
1220 | static int rc_tiocmset(struct tty_struct *tty, struct file *file, | 1113 | static int rc_tiocmset(struct tty_struct *tty, struct file *file, |
1221 | unsigned int set, unsigned int clear) | 1114 | unsigned int set, unsigned int clear) |
1222 | { | 1115 | { |
1223 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1116 | struct riscom_port *port = tty->driver_data; |
1224 | unsigned long flags; | 1117 | unsigned long flags; |
1225 | struct riscom_board *bp; | 1118 | struct riscom_board *bp; |
1226 | 1119 | ||
@@ -1252,7 +1145,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1252 | 1145 | ||
1253 | static int rc_send_break(struct tty_struct *tty, int length) | 1146 | static int rc_send_break(struct tty_struct *tty, int length) |
1254 | { | 1147 | { |
1255 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1148 | struct riscom_port *port = tty->driver_data; |
1256 | struct riscom_board *bp = port_Board(port); | 1149 | struct riscom_board *bp = port_Board(port); |
1257 | unsigned long flags; | 1150 | unsigned long flags; |
1258 | 1151 | ||
@@ -1345,7 +1238,7 @@ static int rc_get_serial_info(struct riscom_port *port, | |||
1345 | static int rc_ioctl(struct tty_struct *tty, struct file *filp, | 1238 | static int rc_ioctl(struct tty_struct *tty, struct file *filp, |
1346 | unsigned int cmd, unsigned long arg) | 1239 | unsigned int cmd, unsigned long arg) |
1347 | { | 1240 | { |
1348 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1241 | struct riscom_port *port = tty->driver_data; |
1349 | void __user *argp = (void __user *)arg; | 1242 | void __user *argp = (void __user *)arg; |
1350 | int retval; | 1243 | int retval; |
1351 | 1244 | ||
@@ -1371,7 +1264,7 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, | |||
1371 | 1264 | ||
1372 | static void rc_throttle(struct tty_struct *tty) | 1265 | static void rc_throttle(struct tty_struct *tty) |
1373 | { | 1266 | { |
1374 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1267 | struct riscom_port *port = tty->driver_data; |
1375 | struct riscom_board *bp; | 1268 | struct riscom_board *bp; |
1376 | unsigned long flags; | 1269 | unsigned long flags; |
1377 | 1270 | ||
@@ -1393,7 +1286,7 @@ static void rc_throttle(struct tty_struct *tty) | |||
1393 | 1286 | ||
1394 | static void rc_unthrottle(struct tty_struct *tty) | 1287 | static void rc_unthrottle(struct tty_struct *tty) |
1395 | { | 1288 | { |
1396 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1289 | struct riscom_port *port = tty->driver_data; |
1397 | struct riscom_board *bp; | 1290 | struct riscom_board *bp; |
1398 | unsigned long flags; | 1291 | unsigned long flags; |
1399 | 1292 | ||
@@ -1415,7 +1308,7 @@ static void rc_unthrottle(struct tty_struct *tty) | |||
1415 | 1308 | ||
1416 | static void rc_stop(struct tty_struct *tty) | 1309 | static void rc_stop(struct tty_struct *tty) |
1417 | { | 1310 | { |
1418 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1311 | struct riscom_port *port = tty->driver_data; |
1419 | struct riscom_board *bp; | 1312 | struct riscom_board *bp; |
1420 | unsigned long flags; | 1313 | unsigned long flags; |
1421 | 1314 | ||
@@ -1433,7 +1326,7 @@ static void rc_stop(struct tty_struct *tty) | |||
1433 | 1326 | ||
1434 | static void rc_start(struct tty_struct *tty) | 1327 | static void rc_start(struct tty_struct *tty) |
1435 | { | 1328 | { |
1436 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1329 | struct riscom_port *port = tty->driver_data; |
1437 | struct riscom_board *bp; | 1330 | struct riscom_board *bp; |
1438 | unsigned long flags; | 1331 | unsigned long flags; |
1439 | 1332 | ||
@@ -1454,8 +1347,9 @@ static void rc_start(struct tty_struct *tty) | |||
1454 | 1347 | ||
1455 | static void rc_hangup(struct tty_struct *tty) | 1348 | static void rc_hangup(struct tty_struct *tty) |
1456 | { | 1349 | { |
1457 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1350 | struct riscom_port *port = tty->driver_data; |
1458 | struct riscom_board *bp; | 1351 | struct riscom_board *bp; |
1352 | unsigned long flags; | ||
1459 | 1353 | ||
1460 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) | 1354 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) |
1461 | return; | 1355 | return; |
@@ -1463,16 +1357,18 @@ static void rc_hangup(struct tty_struct *tty) | |||
1463 | bp = port_Board(port); | 1357 | bp = port_Board(port); |
1464 | 1358 | ||
1465 | rc_shutdown_port(tty, bp, port); | 1359 | rc_shutdown_port(tty, bp, port); |
1360 | spin_lock_irqsave(&port->port.lock, flags); | ||
1466 | port->port.count = 0; | 1361 | port->port.count = 0; |
1467 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1362 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1468 | port->port.tty = NULL; | 1363 | port->port.tty = NULL; |
1469 | wake_up_interruptible(&port->port.open_wait); | 1364 | wake_up_interruptible(&port->port.open_wait); |
1365 | spin_unlock_irqrestore(&port->port.lock, flags); | ||
1470 | } | 1366 | } |
1471 | 1367 | ||
1472 | static void rc_set_termios(struct tty_struct *tty, | 1368 | static void rc_set_termios(struct tty_struct *tty, |
1473 | struct ktermios *old_termios) | 1369 | struct ktermios *old_termios) |
1474 | { | 1370 | { |
1475 | struct riscom_port *port = (struct riscom_port *)tty->driver_data; | 1371 | struct riscom_port *port = tty->driver_data; |
1476 | unsigned long flags; | 1372 | unsigned long flags; |
1477 | 1373 | ||
1478 | if (rc_paranoia_check(port, tty->name, "rc_set_termios")) | 1374 | if (rc_paranoia_check(port, tty->name, "rc_set_termios")) |
@@ -1510,6 +1406,11 @@ static const struct tty_operations riscom_ops = { | |||
1510 | .break_ctl = rc_send_break, | 1406 | .break_ctl = rc_send_break, |
1511 | }; | 1407 | }; |
1512 | 1408 | ||
1409 | static const struct tty_port_operations riscom_port_ops = { | ||
1410 | .carrier_raised = carrier_raised, | ||
1411 | }; | ||
1412 | |||
1413 | |||
1513 | static int __init rc_init_drivers(void) | 1414 | static int __init rc_init_drivers(void) |
1514 | { | 1415 | { |
1515 | int error; | 1416 | int error; |
@@ -1541,6 +1442,7 @@ static int __init rc_init_drivers(void) | |||
1541 | memset(rc_port, 0, sizeof(rc_port)); | 1442 | memset(rc_port, 0, sizeof(rc_port)); |
1542 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { | 1443 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { |
1543 | tty_port_init(&rc_port[i].port); | 1444 | tty_port_init(&rc_port[i].port); |
1445 | rc_port[i].port.ops = &riscom_port_ops; | ||
1544 | rc_port[i].magic = RISCOM8_MAGIC; | 1446 | rc_port[i].magic = RISCOM8_MAGIC; |
1545 | } | 1447 | } |
1546 | return 0; | 1448 | return 0; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 584d791e84a6..f59fc5cea067 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -135,6 +135,7 @@ static int rcktpt_type[NUM_BOARDS]; | |||
135 | static int is_PCI[NUM_BOARDS]; | 135 | static int is_PCI[NUM_BOARDS]; |
136 | static rocketModel_t rocketModel[NUM_BOARDS]; | 136 | static rocketModel_t rocketModel[NUM_BOARDS]; |
137 | static int max_board; | 137 | static int max_board; |
138 | static const struct tty_port_operations rocket_port_ops; | ||
138 | 139 | ||
139 | /* | 140 | /* |
140 | * The following arrays define the interrupt bits corresponding to each AIOP. | 141 | * The following arrays define the interrupt bits corresponding to each AIOP. |
@@ -435,15 +436,15 @@ static void rp_do_transmit(struct r_port *info) | |||
435 | #endif | 436 | #endif |
436 | if (!info) | 437 | if (!info) |
437 | return; | 438 | return; |
438 | if (!info->port.tty) { | 439 | tty = tty_port_tty_get(&info->port); |
439 | printk(KERN_WARNING "rp: WARNING %s called with " | 440 | |
440 | "info->port.tty==NULL\n", __func__); | 441 | if (tty == NULL) { |
442 | printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__); | ||
441 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 443 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
442 | return; | 444 | return; |
443 | } | 445 | } |
444 | 446 | ||
445 | spin_lock_irqsave(&info->slock, flags); | 447 | spin_lock_irqsave(&info->slock, flags); |
446 | tty = info->port.tty; | ||
447 | info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); | 448 | info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); |
448 | 449 | ||
449 | /* Loop sending data to FIFO until done or FIFO full */ | 450 | /* Loop sending data to FIFO until done or FIFO full */ |
@@ -477,6 +478,7 @@ static void rp_do_transmit(struct r_port *info) | |||
477 | } | 478 | } |
478 | 479 | ||
479 | spin_unlock_irqrestore(&info->slock, flags); | 480 | spin_unlock_irqrestore(&info->slock, flags); |
481 | tty_kref_put(tty); | ||
480 | 482 | ||
481 | #ifdef ROCKET_DEBUG_INTR | 483 | #ifdef ROCKET_DEBUG_INTR |
482 | printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, | 484 | printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, |
@@ -498,18 +500,18 @@ static void rp_handle_port(struct r_port *info) | |||
498 | if (!info) | 500 | if (!info) |
499 | return; | 501 | return; |
500 | 502 | ||
501 | if ((info->flags & ROCKET_INITIALIZED) == 0) { | 503 | if ((info->port.flags & ASYNC_INITIALIZED) == 0) { |
502 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " | 504 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " |
503 | "info->flags & NOT_INIT\n"); | 505 | "info->flags & NOT_INIT\n"); |
504 | return; | 506 | return; |
505 | } | 507 | } |
506 | if (!info->port.tty) { | 508 | tty = tty_port_tty_get(&info->port); |
509 | if (!tty) { | ||
507 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " | 510 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " |
508 | "info->port.tty==NULL\n"); | 511 | "tty==NULL\n"); |
509 | return; | 512 | return; |
510 | } | 513 | } |
511 | cp = &info->channel; | 514 | cp = &info->channel; |
512 | tty = info->port.tty; | ||
513 | 515 | ||
514 | IntMask = sGetChanIntID(cp) & info->intmask; | 516 | IntMask = sGetChanIntID(cp) & info->intmask; |
515 | #ifdef ROCKET_DEBUG_INTR | 517 | #ifdef ROCKET_DEBUG_INTR |
@@ -541,6 +543,7 @@ static void rp_handle_port(struct r_port *info) | |||
541 | printk(KERN_INFO "DSR change...\n"); | 543 | printk(KERN_INFO "DSR change...\n"); |
542 | } | 544 | } |
543 | #endif | 545 | #endif |
546 | tty_kref_put(tty); | ||
544 | } | 547 | } |
545 | 548 | ||
546 | /* | 549 | /* |
@@ -649,9 +652,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
649 | info->board = board; | 652 | info->board = board; |
650 | info->aiop = aiop; | 653 | info->aiop = aiop; |
651 | info->chan = chan; | 654 | info->chan = chan; |
652 | info->port.closing_wait = 3000; | 655 | tty_port_init(&info->port); |
653 | info->port.close_delay = 50; | 656 | info->port.ops = &rocket_port_ops; |
654 | init_waitqueue_head(&info->port.open_wait); | ||
655 | init_completion(&info->close_wait); | 657 | init_completion(&info->close_wait); |
656 | info->flags &= ~ROCKET_MODE_MASK; | 658 | info->flags &= ~ROCKET_MODE_MASK; |
657 | switch (pc104[board][line]) { | 659 | switch (pc104[board][line]) { |
@@ -710,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
710 | * Configures a rocketport port according to its termio settings. Called from | 712 | * Configures a rocketport port according to its termio settings. Called from |
711 | * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. | 713 | * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. |
712 | */ | 714 | */ |
713 | static void configure_r_port(struct r_port *info, | 715 | static void configure_r_port(struct tty_struct *tty, struct r_port *info, |
714 | struct ktermios *old_termios) | 716 | struct ktermios *old_termios) |
715 | { | 717 | { |
716 | unsigned cflag; | 718 | unsigned cflag; |
@@ -718,7 +720,7 @@ static void configure_r_port(struct r_port *info, | |||
718 | unsigned rocketMode; | 720 | unsigned rocketMode; |
719 | int bits, baud, divisor; | 721 | int bits, baud, divisor; |
720 | CHANNEL_t *cp; | 722 | CHANNEL_t *cp; |
721 | struct ktermios *t = info->port.tty->termios; | 723 | struct ktermios *t = tty->termios; |
722 | 724 | ||
723 | cp = &info->channel; | 725 | cp = &info->channel; |
724 | cflag = t->c_cflag; | 726 | cflag = t->c_cflag; |
@@ -751,7 +753,7 @@ static void configure_r_port(struct r_port *info, | |||
751 | } | 753 | } |
752 | 754 | ||
753 | /* baud rate */ | 755 | /* baud rate */ |
754 | baud = tty_get_baud_rate(info->port.tty); | 756 | baud = tty_get_baud_rate(tty); |
755 | if (!baud) | 757 | if (!baud) |
756 | baud = 9600; | 758 | baud = 9600; |
757 | divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; | 759 | divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; |
@@ -769,7 +771,7 @@ static void configure_r_port(struct r_port *info, | |||
769 | sSetBaud(cp, divisor); | 771 | sSetBaud(cp, divisor); |
770 | 772 | ||
771 | /* FIXME: Should really back compute a baud rate from the divisor */ | 773 | /* FIXME: Should really back compute a baud rate from the divisor */ |
772 | tty_encode_baud_rate(info->port.tty, baud, baud); | 774 | tty_encode_baud_rate(tty, baud, baud); |
773 | 775 | ||
774 | if (cflag & CRTSCTS) { | 776 | if (cflag & CRTSCTS) { |
775 | info->intmask |= DELTA_CTS; | 777 | info->intmask |= DELTA_CTS; |
@@ -794,15 +796,15 @@ static void configure_r_port(struct r_port *info, | |||
794 | * Handle software flow control in the board | 796 | * Handle software flow control in the board |
795 | */ | 797 | */ |
796 | #ifdef ROCKET_SOFT_FLOW | 798 | #ifdef ROCKET_SOFT_FLOW |
797 | if (I_IXON(info->port.tty)) { | 799 | if (I_IXON(tty)) { |
798 | sEnTxSoftFlowCtl(cp); | 800 | sEnTxSoftFlowCtl(cp); |
799 | if (I_IXANY(info->port.tty)) { | 801 | if (I_IXANY(tty)) { |
800 | sEnIXANY(cp); | 802 | sEnIXANY(cp); |
801 | } else { | 803 | } else { |
802 | sDisIXANY(cp); | 804 | sDisIXANY(cp); |
803 | } | 805 | } |
804 | sSetTxXONChar(cp, START_CHAR(info->port.tty)); | 806 | sSetTxXONChar(cp, START_CHAR(tty)); |
805 | sSetTxXOFFChar(cp, STOP_CHAR(info->port.tty)); | 807 | sSetTxXOFFChar(cp, STOP_CHAR(tty)); |
806 | } else { | 808 | } else { |
807 | sDisTxSoftFlowCtl(cp); | 809 | sDisTxSoftFlowCtl(cp); |
808 | sDisIXANY(cp); | 810 | sDisIXANY(cp); |
@@ -814,24 +816,24 @@ static void configure_r_port(struct r_port *info, | |||
814 | * Set up ignore/read mask words | 816 | * Set up ignore/read mask words |
815 | */ | 817 | */ |
816 | info->read_status_mask = STMRCVROVRH | 0xFF; | 818 | info->read_status_mask = STMRCVROVRH | 0xFF; |
817 | if (I_INPCK(info->port.tty)) | 819 | if (I_INPCK(tty)) |
818 | info->read_status_mask |= STMFRAMEH | STMPARITYH; | 820 | info->read_status_mask |= STMFRAMEH | STMPARITYH; |
819 | if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) | 821 | if (I_BRKINT(tty) || I_PARMRK(tty)) |
820 | info->read_status_mask |= STMBREAKH; | 822 | info->read_status_mask |= STMBREAKH; |
821 | 823 | ||
822 | /* | 824 | /* |
823 | * Characters to ignore | 825 | * Characters to ignore |
824 | */ | 826 | */ |
825 | info->ignore_status_mask = 0; | 827 | info->ignore_status_mask = 0; |
826 | if (I_IGNPAR(info->port.tty)) | 828 | if (I_IGNPAR(tty)) |
827 | info->ignore_status_mask |= STMFRAMEH | STMPARITYH; | 829 | info->ignore_status_mask |= STMFRAMEH | STMPARITYH; |
828 | if (I_IGNBRK(info->port.tty)) { | 830 | if (I_IGNBRK(tty)) { |
829 | info->ignore_status_mask |= STMBREAKH; | 831 | info->ignore_status_mask |= STMBREAKH; |
830 | /* | 832 | /* |
831 | * If we're ignoring parity and break indicators, | 833 | * If we're ignoring parity and break indicators, |
832 | * ignore overruns too. (For real raw support). | 834 | * ignore overruns too. (For real raw support). |
833 | */ | 835 | */ |
834 | if (I_IGNPAR(info->port.tty)) | 836 | if (I_IGNPAR(tty)) |
835 | info->ignore_status_mask |= STMRCVROVRH; | 837 | info->ignore_status_mask |= STMRCVROVRH; |
836 | } | 838 | } |
837 | 839 | ||
@@ -864,106 +866,17 @@ static void configure_r_port(struct r_port *info, | |||
864 | } | 866 | } |
865 | } | 867 | } |
866 | 868 | ||
867 | /* info->port.count is considered critical, protected by spinlocks. */ | 869 | static int carrier_raised(struct tty_port *port) |
868 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
869 | struct r_port *info) | ||
870 | { | 870 | { |
871 | DECLARE_WAITQUEUE(wait, current); | 871 | struct r_port *info = container_of(port, struct r_port, port); |
872 | int retval; | 872 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; |
873 | int do_clocal = 0, extra_count = 0; | 873 | } |
874 | unsigned long flags; | ||
875 | |||
876 | /* | ||
877 | * If the device is in the middle of being closed, then block | ||
878 | * until it's done, and then try again. | ||
879 | */ | ||
880 | if (tty_hung_up_p(filp)) | ||
881 | return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | ||
882 | if (info->flags & ROCKET_CLOSING) { | ||
883 | if (wait_for_completion_interruptible(&info->close_wait)) | ||
884 | return -ERESTARTSYS; | ||
885 | return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | ||
886 | } | ||
887 | |||
888 | /* | ||
889 | * If non-blocking mode is set, or the port is not enabled, | ||
890 | * then make the check up front and then exit. | ||
891 | */ | ||
892 | if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { | ||
893 | info->flags |= ROCKET_NORMAL_ACTIVE; | ||
894 | return 0; | ||
895 | } | ||
896 | if (tty->termios->c_cflag & CLOCAL) | ||
897 | do_clocal = 1; | ||
898 | |||
899 | /* | ||
900 | * Block waiting for the carrier detect and the line to become free. While we are in | ||
901 | * this loop, info->port.count is dropped by one, so that rp_close() knows when to free things. | ||
902 | * We restore it upon exit, either normal or abnormal. | ||
903 | */ | ||
904 | retval = 0; | ||
905 | add_wait_queue(&info->port.open_wait, &wait); | ||
906 | #ifdef ROCKET_DEBUG_OPEN | ||
907 | printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->port.count); | ||
908 | #endif | ||
909 | spin_lock_irqsave(&info->slock, flags); | ||
910 | |||
911 | #ifdef ROCKET_DISABLE_SIMUSAGE | ||
912 | info->flags |= ROCKET_NORMAL_ACTIVE; | ||
913 | #else | ||
914 | if (!tty_hung_up_p(filp)) { | ||
915 | extra_count = 1; | ||
916 | info->port.count--; | ||
917 | } | ||
918 | #endif | ||
919 | info->port.blocked_open++; | ||
920 | |||
921 | spin_unlock_irqrestore(&info->slock, flags); | ||
922 | |||
923 | while (1) { | ||
924 | if (tty->termios->c_cflag & CBAUD) { | ||
925 | sSetDTR(&info->channel); | ||
926 | sSetRTS(&info->channel); | ||
927 | } | ||
928 | set_current_state(TASK_INTERRUPTIBLE); | ||
929 | if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) { | ||
930 | if (info->flags & ROCKET_HUP_NOTIFY) | ||
931 | retval = -EAGAIN; | ||
932 | else | ||
933 | retval = -ERESTARTSYS; | ||
934 | break; | ||
935 | } | ||
936 | if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT))) | ||
937 | break; | ||
938 | if (signal_pending(current)) { | ||
939 | retval = -ERESTARTSYS; | ||
940 | break; | ||
941 | } | ||
942 | #ifdef ROCKET_DEBUG_OPEN | ||
943 | printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n", | ||
944 | info->line, info->port.count, info->flags); | ||
945 | #endif | ||
946 | schedule(); /* Don't hold spinlock here, will hang PC */ | ||
947 | } | ||
948 | __set_current_state(TASK_RUNNING); | ||
949 | remove_wait_queue(&info->port.open_wait, &wait); | ||
950 | |||
951 | spin_lock_irqsave(&info->slock, flags); | ||
952 | |||
953 | if (extra_count) | ||
954 | info->port.count++; | ||
955 | info->port.blocked_open--; | ||
956 | |||
957 | spin_unlock_irqrestore(&info->slock, flags); | ||
958 | 874 | ||
959 | #ifdef ROCKET_DEBUG_OPEN | 875 | static void raise_dtr_rts(struct tty_port *port) |
960 | printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n", | 876 | { |
961 | info->line, info->port.count); | 877 | struct r_port *info = container_of(port, struct r_port, port); |
962 | #endif | 878 | sSetDTR(&info->channel); |
963 | if (retval) | 879 | sSetRTS(&info->channel); |
964 | return retval; | ||
965 | info->flags |= ROCKET_NORMAL_ACTIVE; | ||
966 | return 0; | ||
967 | } | 880 | } |
968 | 881 | ||
969 | /* | 882 | /* |
@@ -973,24 +886,26 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
973 | static int rp_open(struct tty_struct *tty, struct file *filp) | 886 | static int rp_open(struct tty_struct *tty, struct file *filp) |
974 | { | 887 | { |
975 | struct r_port *info; | 888 | struct r_port *info; |
889 | struct tty_port *port; | ||
976 | int line = 0, retval; | 890 | int line = 0, retval; |
977 | CHANNEL_t *cp; | 891 | CHANNEL_t *cp; |
978 | unsigned long page; | 892 | unsigned long page; |
979 | 893 | ||
980 | line = tty->index; | 894 | line = tty->index; |
981 | if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL)) | 895 | if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) |
982 | return -ENXIO; | 896 | return -ENXIO; |
983 | 897 | port = &info->port; | |
898 | |||
984 | page = __get_free_page(GFP_KERNEL); | 899 | page = __get_free_page(GFP_KERNEL); |
985 | if (!page) | 900 | if (!page) |
986 | return -ENOMEM; | 901 | return -ENOMEM; |
987 | 902 | ||
988 | if (info->flags & ROCKET_CLOSING) { | 903 | if (port->flags & ASYNC_CLOSING) { |
989 | retval = wait_for_completion_interruptible(&info->close_wait); | 904 | retval = wait_for_completion_interruptible(&info->close_wait); |
990 | free_page(page); | 905 | free_page(page); |
991 | if (retval) | 906 | if (retval) |
992 | return retval; | 907 | return retval; |
993 | return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); | 908 | return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); |
994 | } | 909 | } |
995 | 910 | ||
996 | /* | 911 | /* |
@@ -1002,9 +917,9 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1002 | info->xmit_buf = (unsigned char *) page; | 917 | info->xmit_buf = (unsigned char *) page; |
1003 | 918 | ||
1004 | tty->driver_data = info; | 919 | tty->driver_data = info; |
1005 | info->port.tty = tty; | 920 | tty_port_tty_set(port, tty); |
1006 | 921 | ||
1007 | if (info->port.count++ == 0) { | 922 | if (port->count++ == 0) { |
1008 | atomic_inc(&rp_num_ports_open); | 923 | atomic_inc(&rp_num_ports_open); |
1009 | 924 | ||
1010 | #ifdef ROCKET_DEBUG_OPEN | 925 | #ifdef ROCKET_DEBUG_OPEN |
@@ -1019,7 +934,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1019 | /* | 934 | /* |
1020 | * Info->count is now 1; so it's safe to sleep now. | 935 | * Info->count is now 1; so it's safe to sleep now. |
1021 | */ | 936 | */ |
1022 | if ((info->flags & ROCKET_INITIALIZED) == 0) { | 937 | if (!test_bit(ASYNC_INITIALIZED, &port->flags)) { |
1023 | cp = &info->channel; | 938 | cp = &info->channel; |
1024 | sSetRxTrigger(cp, TRIG_1); | 939 | sSetRxTrigger(cp, TRIG_1); |
1025 | if (sGetChanStatus(cp) & CD_ACT) | 940 | if (sGetChanStatus(cp) & CD_ACT) |
@@ -1043,21 +958,21 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1043 | sEnRxFIFO(cp); | 958 | sEnRxFIFO(cp); |
1044 | sEnTransmit(cp); | 959 | sEnTransmit(cp); |
1045 | 960 | ||
1046 | info->flags |= ROCKET_INITIALIZED; | 961 | set_bit(ASYNC_INITIALIZED, &info->port.flags); |
1047 | 962 | ||
1048 | /* | 963 | /* |
1049 | * Set up the tty->alt_speed kludge | 964 | * Set up the tty->alt_speed kludge |
1050 | */ | 965 | */ |
1051 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) | 966 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) |
1052 | info->port.tty->alt_speed = 57600; | 967 | tty->alt_speed = 57600; |
1053 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) | 968 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) |
1054 | info->port.tty->alt_speed = 115200; | 969 | tty->alt_speed = 115200; |
1055 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) | 970 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) |
1056 | info->port.tty->alt_speed = 230400; | 971 | tty->alt_speed = 230400; |
1057 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 972 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1058 | info->port.tty->alt_speed = 460800; | 973 | tty->alt_speed = 460800; |
1059 | 974 | ||
1060 | configure_r_port(info, NULL); | 975 | configure_r_port(tty, info, NULL); |
1061 | if (tty->termios->c_cflag & CBAUD) { | 976 | if (tty->termios->c_cflag & CBAUD) { |
1062 | sSetDTR(cp); | 977 | sSetDTR(cp); |
1063 | sSetRTS(cp); | 978 | sSetRTS(cp); |
@@ -1066,7 +981,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1066 | /* Starts (or resets) the maint polling loop */ | 981 | /* Starts (or resets) the maint polling loop */ |
1067 | mod_timer(&rocket_timer, jiffies + POLL_PERIOD); | 982 | mod_timer(&rocket_timer, jiffies + POLL_PERIOD); |
1068 | 983 | ||
1069 | retval = block_til_ready(tty, filp, info); | 984 | retval = tty_port_block_til_ready(port, tty, filp); |
1070 | if (retval) { | 985 | if (retval) { |
1071 | #ifdef ROCKET_DEBUG_OPEN | 986 | #ifdef ROCKET_DEBUG_OPEN |
1072 | printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); | 987 | printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval); |
@@ -1081,8 +996,8 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1081 | */ | 996 | */ |
1082 | static void rp_close(struct tty_struct *tty, struct file *filp) | 997 | static void rp_close(struct tty_struct *tty, struct file *filp) |
1083 | { | 998 | { |
1084 | struct r_port *info = (struct r_port *) tty->driver_data; | 999 | struct r_port *info = tty->driver_data; |
1085 | unsigned long flags; | 1000 | struct tty_port *port = &info->port; |
1086 | int timeout; | 1001 | int timeout; |
1087 | CHANNEL_t *cp; | 1002 | CHANNEL_t *cp; |
1088 | 1003 | ||
@@ -1093,53 +1008,10 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1093 | printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); | 1008 | printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count); |
1094 | #endif | 1009 | #endif |
1095 | 1010 | ||
1096 | if (tty_hung_up_p(filp)) | 1011 | if (tty_port_close_start(port, tty, filp) == 0) |
1097 | return; | ||
1098 | spin_lock_irqsave(&info->slock, flags); | ||
1099 | |||
1100 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
1101 | /* | ||
1102 | * Uh, oh. tty->count is 1, which means that the tty | ||
1103 | * structure will be freed. Info->count should always | ||
1104 | * be one in these conditions. If it's greater than | ||
1105 | * one, we've got real problems, since it means the | ||
1106 | * serial port won't be shutdown. | ||
1107 | */ | ||
1108 | printk(KERN_WARNING "rp_close: bad serial port count; " | ||
1109 | "tty->count is 1, info->port.count is %d\n", info->port.count); | ||
1110 | info->port.count = 1; | ||
1111 | } | ||
1112 | if (--info->port.count < 0) { | ||
1113 | printk(KERN_WARNING "rp_close: bad serial port count for " | ||
1114 | "ttyR%d: %d\n", info->line, info->port.count); | ||
1115 | info->port.count = 0; | ||
1116 | } | ||
1117 | if (info->port.count) { | ||
1118 | spin_unlock_irqrestore(&info->slock, flags); | ||
1119 | return; | 1012 | return; |
1120 | } | ||
1121 | info->flags |= ROCKET_CLOSING; | ||
1122 | spin_unlock_irqrestore(&info->slock, flags); | ||
1123 | 1013 | ||
1124 | cp = &info->channel; | 1014 | cp = &info->channel; |
1125 | |||
1126 | /* | ||
1127 | * Notify the line discpline to only process XON/XOFF characters | ||
1128 | */ | ||
1129 | tty->closing = 1; | ||
1130 | |||
1131 | /* | ||
1132 | * If transmission was throttled by the application request, | ||
1133 | * just flush the xmit buffer. | ||
1134 | */ | ||
1135 | if (tty->flow_stopped) | ||
1136 | rp_flush_buffer(tty); | ||
1137 | |||
1138 | /* | ||
1139 | * Wait for the transmit buffer to clear | ||
1140 | */ | ||
1141 | if (info->port.closing_wait != ROCKET_CLOSING_WAIT_NONE) | ||
1142 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
1143 | /* | 1015 | /* |
1144 | * Before we drop DTR, make sure the UART transmitter | 1016 | * Before we drop DTR, make sure the UART transmitter |
1145 | * has completely drained; this is especially | 1017 | * has completely drained; this is especially |
@@ -1168,19 +1040,24 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1168 | 1040 | ||
1169 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1041 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1170 | 1042 | ||
1171 | if (info->port.blocked_open) { | 1043 | /* We can't yet use tty_port_close_end as the buffer handling in this |
1172 | if (info->port.close_delay) { | 1044 | driver is a bit different to the usual */ |
1173 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | 1045 | |
1046 | if (port->blocked_open) { | ||
1047 | if (port->close_delay) { | ||
1048 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); | ||
1174 | } | 1049 | } |
1175 | wake_up_interruptible(&info->port.open_wait); | 1050 | wake_up_interruptible(&port->open_wait); |
1176 | } else { | 1051 | } else { |
1177 | if (info->xmit_buf) { | 1052 | if (info->xmit_buf) { |
1178 | free_page((unsigned long) info->xmit_buf); | 1053 | free_page((unsigned long) info->xmit_buf); |
1179 | info->xmit_buf = NULL; | 1054 | info->xmit_buf = NULL; |
1180 | } | 1055 | } |
1181 | } | 1056 | } |
1182 | info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE); | 1057 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1183 | tty->closing = 0; | 1058 | tty->closing = 0; |
1059 | tty_port_tty_set(port, NULL); | ||
1060 | wake_up_interruptible(&port->close_wait); | ||
1184 | complete_all(&info->close_wait); | 1061 | complete_all(&info->close_wait); |
1185 | atomic_dec(&rp_num_ports_open); | 1062 | atomic_dec(&rp_num_ports_open); |
1186 | 1063 | ||
@@ -1195,7 +1072,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1195 | static void rp_set_termios(struct tty_struct *tty, | 1072 | static void rp_set_termios(struct tty_struct *tty, |
1196 | struct ktermios *old_termios) | 1073 | struct ktermios *old_termios) |
1197 | { | 1074 | { |
1198 | struct r_port *info = (struct r_port *) tty->driver_data; | 1075 | struct r_port *info = tty->driver_data; |
1199 | CHANNEL_t *cp; | 1076 | CHANNEL_t *cp; |
1200 | unsigned cflag; | 1077 | unsigned cflag; |
1201 | 1078 | ||
@@ -1213,7 +1090,7 @@ static void rp_set_termios(struct tty_struct *tty, | |||
1213 | /* Or CMSPAR */ | 1090 | /* Or CMSPAR */ |
1214 | tty->termios->c_cflag &= ~CMSPAR; | 1091 | tty->termios->c_cflag &= ~CMSPAR; |
1215 | 1092 | ||
1216 | configure_r_port(info, old_termios); | 1093 | configure_r_port(tty, info, old_termios); |
1217 | 1094 | ||
1218 | cp = &info->channel; | 1095 | cp = &info->channel; |
1219 | 1096 | ||
@@ -1238,7 +1115,7 @@ static void rp_set_termios(struct tty_struct *tty, | |||
1238 | 1115 | ||
1239 | static int rp_break(struct tty_struct *tty, int break_state) | 1116 | static int rp_break(struct tty_struct *tty, int break_state) |
1240 | { | 1117 | { |
1241 | struct r_port *info = (struct r_port *) tty->driver_data; | 1118 | struct r_port *info = tty->driver_data; |
1242 | unsigned long flags; | 1119 | unsigned long flags; |
1243 | 1120 | ||
1244 | if (rocket_paranoia_check(info, "rp_break")) | 1121 | if (rocket_paranoia_check(info, "rp_break")) |
@@ -1284,7 +1161,7 @@ static int sGetChanRI(CHANNEL_T * ChP) | |||
1284 | */ | 1161 | */ |
1285 | static int rp_tiocmget(struct tty_struct *tty, struct file *file) | 1162 | static int rp_tiocmget(struct tty_struct *tty, struct file *file) |
1286 | { | 1163 | { |
1287 | struct r_port *info = (struct r_port *)tty->driver_data; | 1164 | struct r_port *info = tty->driver_data; |
1288 | unsigned int control, result, ChanStatus; | 1165 | unsigned int control, result, ChanStatus; |
1289 | 1166 | ||
1290 | ChanStatus = sGetChanStatusLo(&info->channel); | 1167 | ChanStatus = sGetChanStatusLo(&info->channel); |
@@ -1305,7 +1182,7 @@ static int rp_tiocmget(struct tty_struct *tty, struct file *file) | |||
1305 | static int rp_tiocmset(struct tty_struct *tty, struct file *file, | 1182 | static int rp_tiocmset(struct tty_struct *tty, struct file *file, |
1306 | unsigned int set, unsigned int clear) | 1183 | unsigned int set, unsigned int clear) |
1307 | { | 1184 | { |
1308 | struct r_port *info = (struct r_port *)tty->driver_data; | 1185 | struct r_port *info = tty->driver_data; |
1309 | 1186 | ||
1310 | if (set & TIOCM_RTS) | 1187 | if (set & TIOCM_RTS) |
1311 | info->channel.TxControl[3] |= SET_RTS; | 1188 | info->channel.TxControl[3] |= SET_RTS; |
@@ -1338,7 +1215,8 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1338 | return 0; | 1215 | return 0; |
1339 | } | 1216 | } |
1340 | 1217 | ||
1341 | static int set_config(struct r_port *info, struct rocket_config __user *new_info) | 1218 | static int set_config(struct tty_struct *tty, struct r_port *info, |
1219 | struct rocket_config __user *new_info) | ||
1342 | { | 1220 | { |
1343 | struct rocket_config new_serial; | 1221 | struct rocket_config new_serial; |
1344 | 1222 | ||
@@ -1350,7 +1228,7 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info | |||
1350 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1228 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) |
1351 | return -EPERM; | 1229 | return -EPERM; |
1352 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1230 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1353 | configure_r_port(info, NULL); | 1231 | configure_r_port(tty, info, NULL); |
1354 | return 0; | 1232 | return 0; |
1355 | } | 1233 | } |
1356 | 1234 | ||
@@ -1359,15 +1237,15 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info | |||
1359 | info->port.closing_wait = new_serial.closing_wait; | 1237 | info->port.closing_wait = new_serial.closing_wait; |
1360 | 1238 | ||
1361 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) | 1239 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) |
1362 | info->port.tty->alt_speed = 57600; | 1240 | tty->alt_speed = 57600; |
1363 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) | 1241 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) |
1364 | info->port.tty->alt_speed = 115200; | 1242 | tty->alt_speed = 115200; |
1365 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) | 1243 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) |
1366 | info->port.tty->alt_speed = 230400; | 1244 | tty->alt_speed = 230400; |
1367 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1245 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1368 | info->port.tty->alt_speed = 460800; | 1246 | tty->alt_speed = 460800; |
1369 | 1247 | ||
1370 | configure_r_port(info, NULL); | 1248 | configure_r_port(tty, info, NULL); |
1371 | return 0; | 1249 | return 0; |
1372 | } | 1250 | } |
1373 | 1251 | ||
@@ -1434,7 +1312,7 @@ static int get_version(struct r_port *info, struct rocket_version __user *retver | |||
1434 | static int rp_ioctl(struct tty_struct *tty, struct file *file, | 1312 | static int rp_ioctl(struct tty_struct *tty, struct file *file, |
1435 | unsigned int cmd, unsigned long arg) | 1313 | unsigned int cmd, unsigned long arg) |
1436 | { | 1314 | { |
1437 | struct r_port *info = (struct r_port *) tty->driver_data; | 1315 | struct r_port *info = tty->driver_data; |
1438 | void __user *argp = (void __user *)arg; | 1316 | void __user *argp = (void __user *)arg; |
1439 | int ret = 0; | 1317 | int ret = 0; |
1440 | 1318 | ||
@@ -1452,7 +1330,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1452 | ret = get_config(info, argp); | 1330 | ret = get_config(info, argp); |
1453 | break; | 1331 | break; |
1454 | case RCKP_SET_CONFIG: | 1332 | case RCKP_SET_CONFIG: |
1455 | ret = set_config(info, argp); | 1333 | ret = set_config(tty, info, argp); |
1456 | break; | 1334 | break; |
1457 | case RCKP_GET_PORTS: | 1335 | case RCKP_GET_PORTS: |
1458 | ret = get_ports(info, argp); | 1336 | ret = get_ports(info, argp); |
@@ -1472,7 +1350,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1472 | 1350 | ||
1473 | static void rp_send_xchar(struct tty_struct *tty, char ch) | 1351 | static void rp_send_xchar(struct tty_struct *tty, char ch) |
1474 | { | 1352 | { |
1475 | struct r_port *info = (struct r_port *) tty->driver_data; | 1353 | struct r_port *info = tty->driver_data; |
1476 | CHANNEL_t *cp; | 1354 | CHANNEL_t *cp; |
1477 | 1355 | ||
1478 | if (rocket_paranoia_check(info, "rp_send_xchar")) | 1356 | if (rocket_paranoia_check(info, "rp_send_xchar")) |
@@ -1487,7 +1365,7 @@ static void rp_send_xchar(struct tty_struct *tty, char ch) | |||
1487 | 1365 | ||
1488 | static void rp_throttle(struct tty_struct *tty) | 1366 | static void rp_throttle(struct tty_struct *tty) |
1489 | { | 1367 | { |
1490 | struct r_port *info = (struct r_port *) tty->driver_data; | 1368 | struct r_port *info = tty->driver_data; |
1491 | CHANNEL_t *cp; | 1369 | CHANNEL_t *cp; |
1492 | 1370 | ||
1493 | #ifdef ROCKET_DEBUG_THROTTLE | 1371 | #ifdef ROCKET_DEBUG_THROTTLE |
@@ -1507,7 +1385,7 @@ static void rp_throttle(struct tty_struct *tty) | |||
1507 | 1385 | ||
1508 | static void rp_unthrottle(struct tty_struct *tty) | 1386 | static void rp_unthrottle(struct tty_struct *tty) |
1509 | { | 1387 | { |
1510 | struct r_port *info = (struct r_port *) tty->driver_data; | 1388 | struct r_port *info = tty->driver_data; |
1511 | CHANNEL_t *cp; | 1389 | CHANNEL_t *cp; |
1512 | #ifdef ROCKET_DEBUG_THROTTLE | 1390 | #ifdef ROCKET_DEBUG_THROTTLE |
1513 | printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, | 1391 | printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, |
@@ -1534,7 +1412,7 @@ static void rp_unthrottle(struct tty_struct *tty) | |||
1534 | */ | 1412 | */ |
1535 | static void rp_stop(struct tty_struct *tty) | 1413 | static void rp_stop(struct tty_struct *tty) |
1536 | { | 1414 | { |
1537 | struct r_port *info = (struct r_port *) tty->driver_data; | 1415 | struct r_port *info = tty->driver_data; |
1538 | 1416 | ||
1539 | #ifdef ROCKET_DEBUG_FLOW | 1417 | #ifdef ROCKET_DEBUG_FLOW |
1540 | printk(KERN_INFO "stop %s: %d %d....\n", tty->name, | 1418 | printk(KERN_INFO "stop %s: %d %d....\n", tty->name, |
@@ -1550,7 +1428,7 @@ static void rp_stop(struct tty_struct *tty) | |||
1550 | 1428 | ||
1551 | static void rp_start(struct tty_struct *tty) | 1429 | static void rp_start(struct tty_struct *tty) |
1552 | { | 1430 | { |
1553 | struct r_port *info = (struct r_port *) tty->driver_data; | 1431 | struct r_port *info = tty->driver_data; |
1554 | 1432 | ||
1555 | #ifdef ROCKET_DEBUG_FLOW | 1433 | #ifdef ROCKET_DEBUG_FLOW |
1556 | printk(KERN_INFO "start %s: %d %d....\n", tty->name, | 1434 | printk(KERN_INFO "start %s: %d %d....\n", tty->name, |
@@ -1570,7 +1448,7 @@ static void rp_start(struct tty_struct *tty) | |||
1570 | */ | 1448 | */ |
1571 | static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | 1449 | static void rp_wait_until_sent(struct tty_struct *tty, int timeout) |
1572 | { | 1450 | { |
1573 | struct r_port *info = (struct r_port *) tty->driver_data; | 1451 | struct r_port *info = tty->driver_data; |
1574 | CHANNEL_t *cp; | 1452 | CHANNEL_t *cp; |
1575 | unsigned long orig_jiffies; | 1453 | unsigned long orig_jiffies; |
1576 | int check_time, exit_time; | 1454 | int check_time, exit_time; |
@@ -1627,7 +1505,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1627 | static void rp_hangup(struct tty_struct *tty) | 1505 | static void rp_hangup(struct tty_struct *tty) |
1628 | { | 1506 | { |
1629 | CHANNEL_t *cp; | 1507 | CHANNEL_t *cp; |
1630 | struct r_port *info = (struct r_port *) tty->driver_data; | 1508 | struct r_port *info = tty->driver_data; |
1631 | 1509 | ||
1632 | if (rocket_paranoia_check(info, "rp_hangup")) | 1510 | if (rocket_paranoia_check(info, "rp_hangup")) |
1633 | return; | 1511 | return; |
@@ -1636,15 +1514,13 @@ static void rp_hangup(struct tty_struct *tty) | |||
1636 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); | 1514 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1637 | #endif | 1515 | #endif |
1638 | rp_flush_buffer(tty); | 1516 | rp_flush_buffer(tty); |
1639 | if (info->flags & ROCKET_CLOSING) | 1517 | if (info->port.flags & ASYNC_CLOSING) |
1640 | return; | 1518 | return; |
1641 | if (info->port.count) | 1519 | if (info->port.count) |
1642 | atomic_dec(&rp_num_ports_open); | 1520 | atomic_dec(&rp_num_ports_open); |
1643 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1521 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1644 | 1522 | ||
1645 | info->port.count = 0; | 1523 | tty_port_hangup(&info->port); |
1646 | info->flags &= ~ROCKET_NORMAL_ACTIVE; | ||
1647 | info->port.tty = NULL; | ||
1648 | 1524 | ||
1649 | cp = &info->channel; | 1525 | cp = &info->channel; |
1650 | sDisRxFIFO(cp); | 1526 | sDisRxFIFO(cp); |
@@ -1653,7 +1529,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1653 | sDisCTSFlowCtl(cp); | 1529 | sDisCTSFlowCtl(cp); |
1654 | sDisTxSoftFlowCtl(cp); | 1530 | sDisTxSoftFlowCtl(cp); |
1655 | sClrTxXOFF(cp); | 1531 | sClrTxXOFF(cp); |
1656 | info->flags &= ~ROCKET_INITIALIZED; | 1532 | info->port.flags &= ~ASYNC_INITIALIZED; |
1657 | 1533 | ||
1658 | wake_up_interruptible(&info->port.open_wait); | 1534 | wake_up_interruptible(&info->port.open_wait); |
1659 | } | 1535 | } |
@@ -1667,7 +1543,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1667 | */ | 1543 | */ |
1668 | static int rp_put_char(struct tty_struct *tty, unsigned char ch) | 1544 | static int rp_put_char(struct tty_struct *tty, unsigned char ch) |
1669 | { | 1545 | { |
1670 | struct r_port *info = (struct r_port *) tty->driver_data; | 1546 | struct r_port *info = tty->driver_data; |
1671 | CHANNEL_t *cp; | 1547 | CHANNEL_t *cp; |
1672 | unsigned long flags; | 1548 | unsigned long flags; |
1673 | 1549 | ||
@@ -1714,7 +1590,7 @@ static int rp_put_char(struct tty_struct *tty, unsigned char ch) | |||
1714 | static int rp_write(struct tty_struct *tty, | 1590 | static int rp_write(struct tty_struct *tty, |
1715 | const unsigned char *buf, int count) | 1591 | const unsigned char *buf, int count) |
1716 | { | 1592 | { |
1717 | struct r_port *info = (struct r_port *) tty->driver_data; | 1593 | struct r_port *info = tty->driver_data; |
1718 | CHANNEL_t *cp; | 1594 | CHANNEL_t *cp; |
1719 | const unsigned char *b; | 1595 | const unsigned char *b; |
1720 | int c, retval = 0; | 1596 | int c, retval = 0; |
@@ -1764,7 +1640,8 @@ static int rp_write(struct tty_struct *tty, | |||
1764 | 1640 | ||
1765 | /* Write remaining data into the port's xmit_buf */ | 1641 | /* Write remaining data into the port's xmit_buf */ |
1766 | while (1) { | 1642 | while (1) { |
1767 | if (!info->port.tty) /* Seemingly obligatory check... */ | 1643 | /* Hung up ? */ |
1644 | if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags)) | ||
1768 | goto end; | 1645 | goto end; |
1769 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); | 1646 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); |
1770 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); | 1647 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); |
@@ -1806,7 +1683,7 @@ end: | |||
1806 | */ | 1683 | */ |
1807 | static int rp_write_room(struct tty_struct *tty) | 1684 | static int rp_write_room(struct tty_struct *tty) |
1808 | { | 1685 | { |
1809 | struct r_port *info = (struct r_port *) tty->driver_data; | 1686 | struct r_port *info = tty->driver_data; |
1810 | int ret; | 1687 | int ret; |
1811 | 1688 | ||
1812 | if (rocket_paranoia_check(info, "rp_write_room")) | 1689 | if (rocket_paranoia_check(info, "rp_write_room")) |
@@ -1827,7 +1704,7 @@ static int rp_write_room(struct tty_struct *tty) | |||
1827 | */ | 1704 | */ |
1828 | static int rp_chars_in_buffer(struct tty_struct *tty) | 1705 | static int rp_chars_in_buffer(struct tty_struct *tty) |
1829 | { | 1706 | { |
1830 | struct r_port *info = (struct r_port *) tty->driver_data; | 1707 | struct r_port *info = tty->driver_data; |
1831 | CHANNEL_t *cp; | 1708 | CHANNEL_t *cp; |
1832 | 1709 | ||
1833 | if (rocket_paranoia_check(info, "rp_chars_in_buffer")) | 1710 | if (rocket_paranoia_check(info, "rp_chars_in_buffer")) |
@@ -1848,7 +1725,7 @@ static int rp_chars_in_buffer(struct tty_struct *tty) | |||
1848 | */ | 1725 | */ |
1849 | static void rp_flush_buffer(struct tty_struct *tty) | 1726 | static void rp_flush_buffer(struct tty_struct *tty) |
1850 | { | 1727 | { |
1851 | struct r_port *info = (struct r_port *) tty->driver_data; | 1728 | struct r_port *info = tty->driver_data; |
1852 | CHANNEL_t *cp; | 1729 | CHANNEL_t *cp; |
1853 | unsigned long flags; | 1730 | unsigned long flags; |
1854 | 1731 | ||
@@ -2371,6 +2248,11 @@ static const struct tty_operations rocket_ops = { | |||
2371 | .tiocmset = rp_tiocmset, | 2248 | .tiocmset = rp_tiocmset, |
2372 | }; | 2249 | }; |
2373 | 2250 | ||
2251 | static const struct tty_port_operations rocket_port_ops = { | ||
2252 | .carrier_raised = carrier_raised, | ||
2253 | .raise_dtr_rts = raise_dtr_rts, | ||
2254 | }; | ||
2255 | |||
2374 | /* | 2256 | /* |
2375 | * The module "startup" routine; it's run when the module is loaded. | 2257 | * The module "startup" routine; it's run when the module is loaded. |
2376 | */ | 2258 | */ |
diff --git a/drivers/char/rocket.h b/drivers/char/rocket.h index a8b09195ebba..ec863f35f1a9 100644 --- a/drivers/char/rocket.h +++ b/drivers/char/rocket.h | |||
@@ -39,7 +39,7 @@ struct rocket_version { | |||
39 | /* | 39 | /* |
40 | * Rocketport flags | 40 | * Rocketport flags |
41 | */ | 41 | */ |
42 | #define ROCKET_CALLOUT_NOHUP 0x00000001 | 42 | /*#define ROCKET_CALLOUT_NOHUP 0x00000001 */ |
43 | #define ROCKET_FORCE_CD 0x00000002 | 43 | #define ROCKET_FORCE_CD 0x00000002 |
44 | #define ROCKET_HUP_NOTIFY 0x00000004 | 44 | #define ROCKET_HUP_NOTIFY 0x00000004 |
45 | #define ROCKET_SPLIT_TERMIOS 0x00000008 | 45 | #define ROCKET_SPLIT_TERMIOS 0x00000008 |
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 21f3ff53ba32..67e0f1e778a2 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h | |||
@@ -1162,11 +1162,6 @@ struct r_port { | |||
1162 | /* number of characters left in xmit buffer before we ask for more */ | 1162 | /* number of characters left in xmit buffer before we ask for more */ |
1163 | #define WAKEUP_CHARS 256 | 1163 | #define WAKEUP_CHARS 256 |
1164 | 1164 | ||
1165 | /* Internal flags used only by the rocketport driver */ | ||
1166 | #define ROCKET_INITIALIZED 0x80000000 /* Port is active */ | ||
1167 | #define ROCKET_CLOSING 0x40000000 /* Serial port is closing */ | ||
1168 | #define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */ | ||
1169 | |||
1170 | /* | 1165 | /* |
1171 | * Assigned major numbers for the Comtrol Rocketport | 1166 | * Assigned major numbers for the Comtrol Rocketport |
1172 | */ | 1167 | */ |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 2978a49a172b..f29fbe9b8ed7 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -306,7 +306,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
306 | */ | 306 | */ |
307 | int paste_selection(struct tty_struct *tty) | 307 | int paste_selection(struct tty_struct *tty) |
308 | { | 308 | { |
309 | struct vc_data *vc = (struct vc_data *)tty->driver_data; | 309 | struct vc_data *vc = tty->driver_data; |
310 | int pasted = 0; | 310 | int pasted = 0; |
311 | unsigned int count; | 311 | unsigned int count; |
312 | struct tty_ldisc *ld; | 312 | struct tty_ldisc *ld; |
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 7b0c35207d9b..33872a219df6 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c | |||
@@ -122,7 +122,7 @@ static void a2232_disable_tx_interrupts(void *ptr); | |||
122 | static void a2232_enable_tx_interrupts(void *ptr); | 122 | static void a2232_enable_tx_interrupts(void *ptr); |
123 | static void a2232_disable_rx_interrupts(void *ptr); | 123 | static void a2232_disable_rx_interrupts(void *ptr); |
124 | static void a2232_enable_rx_interrupts(void *ptr); | 124 | static void a2232_enable_rx_interrupts(void *ptr); |
125 | static int a2232_get_CD(void *ptr); | 125 | static int a2232_carrier_raised(struct tty_port *port); |
126 | static void a2232_shutdown_port(void *ptr); | 126 | static void a2232_shutdown_port(void *ptr); |
127 | static int a2232_set_real_termios(void *ptr); | 127 | static int a2232_set_real_termios(void *ptr); |
128 | static int a2232_chars_in_buffer(void *ptr); | 128 | static int a2232_chars_in_buffer(void *ptr); |
@@ -148,7 +148,6 @@ static struct real_driver a2232_real_driver = { | |||
148 | a2232_enable_tx_interrupts, | 148 | a2232_enable_tx_interrupts, |
149 | a2232_disable_rx_interrupts, | 149 | a2232_disable_rx_interrupts, |
150 | a2232_enable_rx_interrupts, | 150 | a2232_enable_rx_interrupts, |
151 | a2232_get_CD, | ||
152 | a2232_shutdown_port, | 151 | a2232_shutdown_port, |
153 | a2232_set_real_termios, | 152 | a2232_set_real_termios, |
154 | a2232_chars_in_buffer, | 153 | a2232_chars_in_buffer, |
@@ -260,9 +259,10 @@ static void a2232_enable_rx_interrupts(void *ptr) | |||
260 | port->disable_rx = 0; | 259 | port->disable_rx = 0; |
261 | } | 260 | } |
262 | 261 | ||
263 | static int a2232_get_CD(void *ptr) | 262 | static int a2232_carrier_raised(struct tty_port *port) |
264 | { | 263 | { |
265 | return ((struct a2232_port *) ptr)->cd_status; | 264 | struct a2232_port *ap = container_of(port, struct a2232_port, gs.port); |
265 | return ap->cd_status; | ||
266 | } | 266 | } |
267 | 267 | ||
268 | static void a2232_shutdown_port(void *ptr) | 268 | static void a2232_shutdown_port(void *ptr) |
@@ -460,14 +460,14 @@ static void a2232_throttle(struct tty_struct *tty) | |||
460 | if switched on. So the only thing we can do at this | 460 | if switched on. So the only thing we can do at this |
461 | layer here is not taking any characters out of the | 461 | layer here is not taking any characters out of the |
462 | A2232 buffer any more. */ | 462 | A2232 buffer any more. */ |
463 | struct a2232_port *port = (struct a2232_port *) tty->driver_data; | 463 | struct a2232_port *port = tty->driver_data; |
464 | port->throttle_input = -1; | 464 | port->throttle_input = -1; |
465 | } | 465 | } |
466 | 466 | ||
467 | static void a2232_unthrottle(struct tty_struct *tty) | 467 | static void a2232_unthrottle(struct tty_struct *tty) |
468 | { | 468 | { |
469 | /* Unthrottle: dual to "throttle()" above. */ | 469 | /* Unthrottle: dual to "throttle()" above. */ |
470 | struct a2232_port *port = (struct a2232_port *) tty->driver_data; | 470 | struct a2232_port *port = tty->driver_data; |
471 | port->throttle_input = 0; | 471 | port->throttle_input = 0; |
472 | } | 472 | } |
473 | 473 | ||
@@ -638,6 +638,10 @@ int ch, err, n, p; | |||
638 | return IRQ_HANDLED; | 638 | return IRQ_HANDLED; |
639 | } | 639 | } |
640 | 640 | ||
641 | static const struct tty_port_operations a2232_port_ops = { | ||
642 | .carrier_raised = a2232_carrier_raised, | ||
643 | }; | ||
644 | |||
641 | static void a2232_init_portstructs(void) | 645 | static void a2232_init_portstructs(void) |
642 | { | 646 | { |
643 | struct a2232_port *port; | 647 | struct a2232_port *port; |
@@ -645,6 +649,8 @@ static void a2232_init_portstructs(void) | |||
645 | 649 | ||
646 | for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) { | 650 | for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) { |
647 | port = a2232_ports + i; | 651 | port = a2232_ports + i; |
652 | tty_port_init(&port->gs.port); | ||
653 | port->gs.port.ops = &a2232_port_ops; | ||
648 | port->which_a2232 = i/NUMLINES; | 654 | port->which_a2232 = i/NUMLINES; |
649 | port->which_port_on_a2232 = i%NUMLINES; | 655 | port->which_port_on_a2232 = i%NUMLINES; |
650 | port->disable_rx = port->throttle_input = port->cd_status = 0; | 656 | port->disable_rx = port->throttle_input = port->cd_status = 0; |
@@ -652,11 +658,6 @@ static void a2232_init_portstructs(void) | |||
652 | port->gs.close_delay = HZ/2; | 658 | port->gs.close_delay = HZ/2; |
653 | port->gs.closing_wait = 30 * HZ; | 659 | port->gs.closing_wait = 30 * HZ; |
654 | port->gs.rd = &a2232_real_driver; | 660 | port->gs.rd = &a2232_real_driver; |
655 | #ifdef NEW_WRITE_LOCKING | ||
656 | mutex_init(&(port->gs.port_write_mutex)); | ||
657 | #endif | ||
658 | init_waitqueue_head(&port->gs.port.open_wait); | ||
659 | init_waitqueue_head(&port->gs.port.close_wait); | ||
660 | } | 661 | } |
661 | } | 662 | } |
662 | 663 | ||
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index a8f15e6be594..f1f24f0ee26f 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -315,7 +315,7 @@ u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd) | |||
315 | 315 | ||
316 | static void cy_stop(struct tty_struct *tty) | 316 | static void cy_stop(struct tty_struct *tty) |
317 | { | 317 | { |
318 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 318 | struct cyclades_port *info = tty->driver_data; |
319 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 319 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
320 | int channel; | 320 | int channel; |
321 | unsigned long flags; | 321 | unsigned long flags; |
@@ -337,7 +337,7 @@ static void cy_stop(struct tty_struct *tty) | |||
337 | 337 | ||
338 | static void cy_start(struct tty_struct *tty) | 338 | static void cy_start(struct tty_struct *tty) |
339 | { | 339 | { |
340 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 340 | struct cyclades_port *info = tty->driver_data; |
341 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; | 341 | volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR; |
342 | int channel; | 342 | int channel; |
343 | unsigned long flags; | 343 | unsigned long flags; |
@@ -1062,7 +1062,7 @@ static void config_setup(struct cyclades_port *info) | |||
1062 | 1062 | ||
1063 | static int cy_put_char(struct tty_struct *tty, unsigned char ch) | 1063 | static int cy_put_char(struct tty_struct *tty, unsigned char ch) |
1064 | { | 1064 | { |
1065 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1065 | struct cyclades_port *info = tty->driver_data; |
1066 | unsigned long flags; | 1066 | unsigned long flags; |
1067 | 1067 | ||
1068 | #ifdef SERIAL_DEBUG_IO | 1068 | #ifdef SERIAL_DEBUG_IO |
@@ -1090,7 +1090,7 @@ static int cy_put_char(struct tty_struct *tty, unsigned char ch) | |||
1090 | 1090 | ||
1091 | static void cy_flush_chars(struct tty_struct *tty) | 1091 | static void cy_flush_chars(struct tty_struct *tty) |
1092 | { | 1092 | { |
1093 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1093 | struct cyclades_port *info = tty->driver_data; |
1094 | unsigned long flags; | 1094 | unsigned long flags; |
1095 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | 1095 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1096 | int channel; | 1096 | int channel; |
@@ -1122,7 +1122,7 @@ static void cy_flush_chars(struct tty_struct *tty) | |||
1122 | */ | 1122 | */ |
1123 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1123 | static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) |
1124 | { | 1124 | { |
1125 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1125 | struct cyclades_port *info = tty->driver_data; |
1126 | unsigned long flags; | 1126 | unsigned long flags; |
1127 | int c, total = 0; | 1127 | int c, total = 0; |
1128 | 1128 | ||
@@ -1166,7 +1166,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
1166 | 1166 | ||
1167 | static int cy_write_room(struct tty_struct *tty) | 1167 | static int cy_write_room(struct tty_struct *tty) |
1168 | { | 1168 | { |
1169 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1169 | struct cyclades_port *info = tty->driver_data; |
1170 | int ret; | 1170 | int ret; |
1171 | 1171 | ||
1172 | #ifdef SERIAL_DEBUG_IO | 1172 | #ifdef SERIAL_DEBUG_IO |
@@ -1183,7 +1183,7 @@ static int cy_write_room(struct tty_struct *tty) | |||
1183 | 1183 | ||
1184 | static int cy_chars_in_buffer(struct tty_struct *tty) | 1184 | static int cy_chars_in_buffer(struct tty_struct *tty) |
1185 | { | 1185 | { |
1186 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1186 | struct cyclades_port *info = tty->driver_data; |
1187 | 1187 | ||
1188 | #ifdef SERIAL_DEBUG_IO | 1188 | #ifdef SERIAL_DEBUG_IO |
1189 | printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ | 1189 | printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */ |
@@ -1197,7 +1197,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1197 | 1197 | ||
1198 | static void cy_flush_buffer(struct tty_struct *tty) | 1198 | static void cy_flush_buffer(struct tty_struct *tty) |
1199 | { | 1199 | { |
1200 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1200 | struct cyclades_port *info = tty->driver_data; |
1201 | unsigned long flags; | 1201 | unsigned long flags; |
1202 | 1202 | ||
1203 | #ifdef SERIAL_DEBUG_IO | 1203 | #ifdef SERIAL_DEBUG_IO |
@@ -1218,7 +1218,7 @@ static void cy_flush_buffer(struct tty_struct *tty) | |||
1218 | */ | 1218 | */ |
1219 | static void cy_throttle(struct tty_struct *tty) | 1219 | static void cy_throttle(struct tty_struct *tty) |
1220 | { | 1220 | { |
1221 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1221 | struct cyclades_port *info = tty->driver_data; |
1222 | unsigned long flags; | 1222 | unsigned long flags; |
1223 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | 1223 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1224 | int channel; | 1224 | int channel; |
@@ -1250,7 +1250,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
1250 | 1250 | ||
1251 | static void cy_unthrottle(struct tty_struct *tty) | 1251 | static void cy_unthrottle(struct tty_struct *tty) |
1252 | { | 1252 | { |
1253 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1253 | struct cyclades_port *info = tty->driver_data; |
1254 | unsigned long flags; | 1254 | unsigned long flags; |
1255 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | 1255 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1256 | int channel; | 1256 | int channel; |
@@ -1345,7 +1345,7 @@ check_and_exit: | |||
1345 | 1345 | ||
1346 | static int cy_tiocmget(struct tty_struct *tty, struct file *file) | 1346 | static int cy_tiocmget(struct tty_struct *tty, struct file *file) |
1347 | { | 1347 | { |
1348 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1348 | struct cyclades_port *info = tty->driver_data; |
1349 | int channel; | 1349 | int channel; |
1350 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | 1350 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1351 | unsigned long flags; | 1351 | unsigned long flags; |
@@ -1369,7 +1369,7 @@ static int | |||
1369 | cy_tiocmset(struct tty_struct *tty, struct file *file, | 1369 | cy_tiocmset(struct tty_struct *tty, struct file *file, |
1370 | unsigned int set, unsigned int clear) | 1370 | unsigned int set, unsigned int clear) |
1371 | { | 1371 | { |
1372 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1372 | struct cyclades_port *info = tty->driver_data; |
1373 | int channel; | 1373 | int channel; |
1374 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; | 1374 | volatile unsigned char *base_addr = (u_char *) BASE_ADDR; |
1375 | unsigned long flags; | 1375 | unsigned long flags; |
@@ -1532,7 +1532,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1532 | unsigned int cmd, unsigned long arg) | 1532 | unsigned int cmd, unsigned long arg) |
1533 | { | 1533 | { |
1534 | unsigned long val; | 1534 | unsigned long val; |
1535 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1535 | struct cyclades_port *info = tty->driver_data; |
1536 | int ret_val = 0; | 1536 | int ret_val = 0; |
1537 | void __user *argp = (void __user *)arg; | 1537 | void __user *argp = (void __user *)arg; |
1538 | 1538 | ||
@@ -1607,7 +1607,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1607 | 1607 | ||
1608 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 1608 | static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
1609 | { | 1609 | { |
1610 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1610 | struct cyclades_port *info = tty->driver_data; |
1611 | 1611 | ||
1612 | #ifdef SERIAL_DEBUG_OTHER | 1612 | #ifdef SERIAL_DEBUG_OTHER |
1613 | printk("cy_set_termios %s\n", tty->name); | 1613 | printk("cy_set_termios %s\n", tty->name); |
@@ -1631,7 +1631,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
1631 | 1631 | ||
1632 | static void cy_close(struct tty_struct *tty, struct file *filp) | 1632 | static void cy_close(struct tty_struct *tty, struct file *filp) |
1633 | { | 1633 | { |
1634 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1634 | struct cyclades_port *info = tty->driver_data; |
1635 | 1635 | ||
1636 | /* CP('C'); */ | 1636 | /* CP('C'); */ |
1637 | #ifdef SERIAL_DEBUG_OTHER | 1637 | #ifdef SERIAL_DEBUG_OTHER |
@@ -1698,7 +1698,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
1698 | */ | 1698 | */ |
1699 | void cy_hangup(struct tty_struct *tty) | 1699 | void cy_hangup(struct tty_struct *tty) |
1700 | { | 1700 | { |
1701 | struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; | 1701 | struct cyclades_port *info = tty->driver_data; |
1702 | 1702 | ||
1703 | #ifdef SERIAL_DEBUG_OTHER | 1703 | #ifdef SERIAL_DEBUG_OTHER |
1704 | printk("cy_hangup %s\n", tty->name); /* */ | 1704 | printk("cy_hangup %s\n", tty->name); /* */ |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index a16b94f12eb2..3c67c3d83de9 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -1450,7 +1450,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp) | |||
1450 | 1450 | ||
1451 | static void sx_flush_buffer(struct tty_struct *tty) | 1451 | static void sx_flush_buffer(struct tty_struct *tty) |
1452 | { | 1452 | { |
1453 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1453 | struct specialix_port *port = tty->driver_data; |
1454 | unsigned long flags; | 1454 | unsigned long flags; |
1455 | struct specialix_board *bp; | 1455 | struct specialix_board *bp; |
1456 | 1456 | ||
@@ -1472,7 +1472,7 @@ static void sx_flush_buffer(struct tty_struct *tty) | |||
1472 | 1472 | ||
1473 | static void sx_close(struct tty_struct *tty, struct file *filp) | 1473 | static void sx_close(struct tty_struct *tty, struct file *filp) |
1474 | { | 1474 | { |
1475 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1475 | struct specialix_port *port = tty->driver_data; |
1476 | struct specialix_board *bp; | 1476 | struct specialix_board *bp; |
1477 | unsigned long flags; | 1477 | unsigned long flags; |
1478 | unsigned long timeout; | 1478 | unsigned long timeout; |
@@ -1585,7 +1585,7 @@ static void sx_close(struct tty_struct *tty, struct file *filp) | |||
1585 | static int sx_write(struct tty_struct *tty, | 1585 | static int sx_write(struct tty_struct *tty, |
1586 | const unsigned char *buf, int count) | 1586 | const unsigned char *buf, int count) |
1587 | { | 1587 | { |
1588 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1588 | struct specialix_port *port = tty->driver_data; |
1589 | struct specialix_board *bp; | 1589 | struct specialix_board *bp; |
1590 | int c, total = 0; | 1590 | int c, total = 0; |
1591 | unsigned long flags; | 1591 | unsigned long flags; |
@@ -1637,7 +1637,7 @@ static int sx_write(struct tty_struct *tty, | |||
1637 | 1637 | ||
1638 | static int sx_put_char(struct tty_struct *tty, unsigned char ch) | 1638 | static int sx_put_char(struct tty_struct *tty, unsigned char ch) |
1639 | { | 1639 | { |
1640 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1640 | struct specialix_port *port = tty->driver_data; |
1641 | unsigned long flags; | 1641 | unsigned long flags; |
1642 | struct specialix_board *bp; | 1642 | struct specialix_board *bp; |
1643 | 1643 | ||
@@ -1676,7 +1676,7 @@ static int sx_put_char(struct tty_struct *tty, unsigned char ch) | |||
1676 | 1676 | ||
1677 | static void sx_flush_chars(struct tty_struct *tty) | 1677 | static void sx_flush_chars(struct tty_struct *tty) |
1678 | { | 1678 | { |
1679 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1679 | struct specialix_port *port = tty->driver_data; |
1680 | unsigned long flags; | 1680 | unsigned long flags; |
1681 | struct specialix_board *bp = port_Board(port); | 1681 | struct specialix_board *bp = port_Board(port); |
1682 | 1682 | ||
@@ -1703,7 +1703,7 @@ static void sx_flush_chars(struct tty_struct *tty) | |||
1703 | 1703 | ||
1704 | static int sx_write_room(struct tty_struct *tty) | 1704 | static int sx_write_room(struct tty_struct *tty) |
1705 | { | 1705 | { |
1706 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1706 | struct specialix_port *port = tty->driver_data; |
1707 | int ret; | 1707 | int ret; |
1708 | 1708 | ||
1709 | func_enter(); | 1709 | func_enter(); |
@@ -1724,7 +1724,7 @@ static int sx_write_room(struct tty_struct *tty) | |||
1724 | 1724 | ||
1725 | static int sx_chars_in_buffer(struct tty_struct *tty) | 1725 | static int sx_chars_in_buffer(struct tty_struct *tty) |
1726 | { | 1726 | { |
1727 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1727 | struct specialix_port *port = tty->driver_data; |
1728 | 1728 | ||
1729 | func_enter(); | 1729 | func_enter(); |
1730 | 1730 | ||
@@ -1738,7 +1738,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty) | |||
1738 | 1738 | ||
1739 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) | 1739 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) |
1740 | { | 1740 | { |
1741 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1741 | struct specialix_port *port = tty->driver_data; |
1742 | struct specialix_board *bp; | 1742 | struct specialix_board *bp; |
1743 | unsigned char status; | 1743 | unsigned char status; |
1744 | unsigned int result; | 1744 | unsigned int result; |
@@ -1780,7 +1780,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) | |||
1780 | static int sx_tiocmset(struct tty_struct *tty, struct file *file, | 1780 | static int sx_tiocmset(struct tty_struct *tty, struct file *file, |
1781 | unsigned int set, unsigned int clear) | 1781 | unsigned int set, unsigned int clear) |
1782 | { | 1782 | { |
1783 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1783 | struct specialix_port *port = tty->driver_data; |
1784 | unsigned long flags; | 1784 | unsigned long flags; |
1785 | struct specialix_board *bp; | 1785 | struct specialix_board *bp; |
1786 | 1786 | ||
@@ -1820,7 +1820,7 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, | |||
1820 | 1820 | ||
1821 | static int sx_send_break(struct tty_struct *tty, int length) | 1821 | static int sx_send_break(struct tty_struct *tty, int length) |
1822 | { | 1822 | { |
1823 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1823 | struct specialix_port *port = tty->driver_data; |
1824 | struct specialix_board *bp = port_Board(port); | 1824 | struct specialix_board *bp = port_Board(port); |
1825 | unsigned long flags; | 1825 | unsigned long flags; |
1826 | 1826 | ||
@@ -1931,7 +1931,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1931 | static int sx_ioctl(struct tty_struct *tty, struct file *filp, | 1931 | static int sx_ioctl(struct tty_struct *tty, struct file *filp, |
1932 | unsigned int cmd, unsigned long arg) | 1932 | unsigned int cmd, unsigned long arg) |
1933 | { | 1933 | { |
1934 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1934 | struct specialix_port *port = tty->driver_data; |
1935 | void __user *argp = (void __user *)arg; | 1935 | void __user *argp = (void __user *)arg; |
1936 | 1936 | ||
1937 | func_enter(); | 1937 | func_enter(); |
@@ -1959,7 +1959,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1959 | 1959 | ||
1960 | static void sx_throttle(struct tty_struct *tty) | 1960 | static void sx_throttle(struct tty_struct *tty) |
1961 | { | 1961 | { |
1962 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1962 | struct specialix_port *port = tty->driver_data; |
1963 | struct specialix_board *bp; | 1963 | struct specialix_board *bp; |
1964 | unsigned long flags; | 1964 | unsigned long flags; |
1965 | 1965 | ||
@@ -2004,7 +2004,7 @@ static void sx_throttle(struct tty_struct *tty) | |||
2004 | 2004 | ||
2005 | static void sx_unthrottle(struct tty_struct *tty) | 2005 | static void sx_unthrottle(struct tty_struct *tty) |
2006 | { | 2006 | { |
2007 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2007 | struct specialix_port *port = tty->driver_data; |
2008 | struct specialix_board *bp; | 2008 | struct specialix_board *bp; |
2009 | unsigned long flags; | 2009 | unsigned long flags; |
2010 | 2010 | ||
@@ -2045,7 +2045,7 @@ static void sx_unthrottle(struct tty_struct *tty) | |||
2045 | 2045 | ||
2046 | static void sx_stop(struct tty_struct *tty) | 2046 | static void sx_stop(struct tty_struct *tty) |
2047 | { | 2047 | { |
2048 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2048 | struct specialix_port *port = tty->driver_data; |
2049 | struct specialix_board *bp; | 2049 | struct specialix_board *bp; |
2050 | unsigned long flags; | 2050 | unsigned long flags; |
2051 | 2051 | ||
@@ -2072,7 +2072,7 @@ static void sx_stop(struct tty_struct *tty) | |||
2072 | 2072 | ||
2073 | static void sx_start(struct tty_struct *tty) | 2073 | static void sx_start(struct tty_struct *tty) |
2074 | { | 2074 | { |
2075 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2075 | struct specialix_port *port = tty->driver_data; |
2076 | struct specialix_board *bp; | 2076 | struct specialix_board *bp; |
2077 | unsigned long flags; | 2077 | unsigned long flags; |
2078 | 2078 | ||
@@ -2100,7 +2100,7 @@ static void sx_start(struct tty_struct *tty) | |||
2100 | 2100 | ||
2101 | static void sx_hangup(struct tty_struct *tty) | 2101 | static void sx_hangup(struct tty_struct *tty) |
2102 | { | 2102 | { |
2103 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2103 | struct specialix_port *port = tty->driver_data; |
2104 | struct specialix_board *bp; | 2104 | struct specialix_board *bp; |
2105 | unsigned long flags; | 2105 | unsigned long flags; |
2106 | 2106 | ||
@@ -2135,7 +2135,7 @@ static void sx_hangup(struct tty_struct *tty) | |||
2135 | static void sx_set_termios(struct tty_struct *tty, | 2135 | static void sx_set_termios(struct tty_struct *tty, |
2136 | struct ktermios *old_termios) | 2136 | struct ktermios *old_termios) |
2137 | { | 2137 | { |
2138 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2138 | struct specialix_port *port = tty->driver_data; |
2139 | unsigned long flags; | 2139 | unsigned long flags; |
2140 | struct specialix_board *bp; | 2140 | struct specialix_board *bp; |
2141 | 2141 | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 963b03fb29e5..e1e0dd89ac9a 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -130,6 +130,8 @@ static char stl_unwanted[SC26198_RXFIFOSIZE]; | |||
130 | static DEFINE_MUTEX(stl_brdslock); | 130 | static DEFINE_MUTEX(stl_brdslock); |
131 | static struct stlbrd *stl_brds[STL_MAXBRDS]; | 131 | static struct stlbrd *stl_brds[STL_MAXBRDS]; |
132 | 132 | ||
133 | static const struct tty_port_operations stl_port_ops; | ||
134 | |||
133 | /* | 135 | /* |
134 | * Per board state flags. Used with the state field of the board struct. | 136 | * Per board state flags. Used with the state field of the board struct. |
135 | * Not really much here! | 137 | * Not really much here! |
@@ -407,7 +409,6 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
407 | static int stl_brdinit(struct stlbrd *brdp); | 409 | static int stl_brdinit(struct stlbrd *brdp); |
408 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 410 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); |
409 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 411 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); |
410 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp); | ||
411 | 412 | ||
412 | /* | 413 | /* |
413 | * CD1400 uart specific handling functions. | 414 | * CD1400 uart specific handling functions. |
@@ -703,8 +704,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
703 | { | 704 | { |
704 | struct stlport *portp; | 705 | struct stlport *portp; |
705 | struct stlbrd *brdp; | 706 | struct stlbrd *brdp; |
707 | struct tty_port *port; | ||
706 | unsigned int minordev, brdnr, panelnr; | 708 | unsigned int minordev, brdnr, panelnr; |
707 | int portnr, rc; | 709 | int portnr; |
708 | 710 | ||
709 | pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); | 711 | pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); |
710 | 712 | ||
@@ -715,6 +717,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
715 | brdp = stl_brds[brdnr]; | 717 | brdp = stl_brds[brdnr]; |
716 | if (brdp == NULL) | 718 | if (brdp == NULL) |
717 | return -ENODEV; | 719 | return -ENODEV; |
720 | |||
718 | minordev = MINOR2PORT(minordev); | 721 | minordev = MINOR2PORT(minordev); |
719 | for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { | 722 | for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { |
720 | if (brdp->panels[panelnr] == NULL) | 723 | if (brdp->panels[panelnr] == NULL) |
@@ -731,16 +734,17 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
731 | portp = brdp->panels[panelnr]->ports[portnr]; | 734 | portp = brdp->panels[panelnr]->ports[portnr]; |
732 | if (portp == NULL) | 735 | if (portp == NULL) |
733 | return -ENODEV; | 736 | return -ENODEV; |
737 | port = &portp->port; | ||
734 | 738 | ||
735 | /* | 739 | /* |
736 | * On the first open of the device setup the port hardware, and | 740 | * On the first open of the device setup the port hardware, and |
737 | * initialize the per port data structure. | 741 | * initialize the per port data structure. |
738 | */ | 742 | */ |
739 | tty_port_tty_set(&portp->port, tty); | 743 | tty_port_tty_set(port, tty); |
740 | tty->driver_data = portp; | 744 | tty->driver_data = portp; |
741 | portp->port.count++; | 745 | port->count++; |
742 | 746 | ||
743 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | 747 | if ((port->flags & ASYNC_INITIALIZED) == 0) { |
744 | if (!portp->tx.buf) { | 748 | if (!portp->tx.buf) { |
745 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | 749 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); |
746 | if (!portp->tx.buf) | 750 | if (!portp->tx.buf) |
@@ -754,91 +758,24 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
754 | stl_enablerxtx(portp, 1, 1); | 758 | stl_enablerxtx(portp, 1, 1); |
755 | stl_startrxtx(portp, 1, 0); | 759 | stl_startrxtx(portp, 1, 0); |
756 | clear_bit(TTY_IO_ERROR, &tty->flags); | 760 | clear_bit(TTY_IO_ERROR, &tty->flags); |
757 | portp->port.flags |= ASYNC_INITIALIZED; | 761 | port->flags |= ASYNC_INITIALIZED; |
758 | } | ||
759 | |||
760 | /* | ||
761 | * Check if this port is in the middle of closing. If so then wait | ||
762 | * until it is closed then return error status, based on flag settings. | ||
763 | * The sleep here does not need interrupt protection since the wakeup | ||
764 | * for it is done with the same context. | ||
765 | */ | ||
766 | if (portp->port.flags & ASYNC_CLOSING) { | ||
767 | interruptible_sleep_on(&portp->port.close_wait); | ||
768 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
769 | return -EAGAIN; | ||
770 | return -ERESTARTSYS; | ||
771 | } | 762 | } |
772 | 763 | return tty_port_block_til_ready(port, tty, filp); | |
773 | /* | ||
774 | * Based on type of open being done check if it can overlap with any | ||
775 | * previous opens still in effect. If we are a normal serial device | ||
776 | * then also we might have to wait for carrier. | ||
777 | */ | ||
778 | if (!(filp->f_flags & O_NONBLOCK)) | ||
779 | if ((rc = stl_waitcarrier(tty, portp, filp)) != 0) | ||
780 | return rc; | ||
781 | |||
782 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
783 | |||
784 | return 0; | ||
785 | } | 764 | } |
786 | 765 | ||
787 | /*****************************************************************************/ | 766 | /*****************************************************************************/ |
788 | 767 | ||
789 | /* | 768 | static int stl_carrier_raised(struct tty_port *port) |
790 | * Possibly need to wait for carrier (DCD signal) to come high. Say | ||
791 | * maybe because if we are clocal then we don't need to wait... | ||
792 | */ | ||
793 | |||
794 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, | ||
795 | struct file *filp) | ||
796 | { | 769 | { |
797 | unsigned long flags; | 770 | struct stlport *portp = container_of(port, struct stlport, port); |
798 | int rc, doclocal; | 771 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
799 | 772 | } | |
800 | pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp); | ||
801 | |||
802 | rc = 0; | ||
803 | doclocal = 0; | ||
804 | |||
805 | spin_lock_irqsave(&stallion_lock, flags); | ||
806 | |||
807 | if (tty->termios->c_cflag & CLOCAL) | ||
808 | doclocal++; | ||
809 | |||
810 | portp->openwaitcnt++; | ||
811 | if (! tty_hung_up_p(filp)) | ||
812 | portp->port.count--; | ||
813 | |||
814 | for (;;) { | ||
815 | /* Takes brd_lock internally */ | ||
816 | stl_setsignals(portp, 1, 1); | ||
817 | if (tty_hung_up_p(filp) || | ||
818 | ((portp->port.flags & ASYNC_INITIALIZED) == 0)) { | ||
819 | if (portp->port.flags & ASYNC_HUP_NOTIFY) | ||
820 | rc = -EBUSY; | ||
821 | else | ||
822 | rc = -ERESTARTSYS; | ||
823 | break; | ||
824 | } | ||
825 | if (((portp->port.flags & ASYNC_CLOSING) == 0) && | ||
826 | (doclocal || (portp->sigs & TIOCM_CD))) | ||
827 | break; | ||
828 | if (signal_pending(current)) { | ||
829 | rc = -ERESTARTSYS; | ||
830 | break; | ||
831 | } | ||
832 | /* FIXME */ | ||
833 | interruptible_sleep_on(&portp->port.open_wait); | ||
834 | } | ||
835 | |||
836 | if (! tty_hung_up_p(filp)) | ||
837 | portp->port.count++; | ||
838 | portp->openwaitcnt--; | ||
839 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
840 | 773 | ||
841 | return rc; | 774 | static void stl_raise_dtr_rts(struct tty_port *port) |
775 | { | ||
776 | struct stlport *portp = container_of(port, struct stlport, port); | ||
777 | /* Takes brd_lock internally */ | ||
778 | stl_setsignals(portp, 1, 1); | ||
842 | } | 779 | } |
843 | 780 | ||
844 | /*****************************************************************************/ | 781 | /*****************************************************************************/ |
@@ -890,47 +827,29 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
890 | static void stl_close(struct tty_struct *tty, struct file *filp) | 827 | static void stl_close(struct tty_struct *tty, struct file *filp) |
891 | { | 828 | { |
892 | struct stlport *portp; | 829 | struct stlport *portp; |
830 | struct tty_port *port; | ||
893 | unsigned long flags; | 831 | unsigned long flags; |
894 | 832 | ||
895 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | 833 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); |
896 | 834 | ||
897 | portp = tty->driver_data; | 835 | portp = tty->driver_data; |
898 | if (portp == NULL) | 836 | BUG_ON(portp == NULL); |
899 | return; | ||
900 | 837 | ||
901 | spin_lock_irqsave(&stallion_lock, flags); | 838 | port = &portp->port; |
902 | if (tty_hung_up_p(filp)) { | ||
903 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
904 | return; | ||
905 | } | ||
906 | if ((tty->count == 1) && (portp->port.count != 1)) | ||
907 | portp->port.count = 1; | ||
908 | if (portp->port.count-- > 1) { | ||
909 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
910 | return; | ||
911 | } | ||
912 | |||
913 | portp->port.count = 0; | ||
914 | portp->port.flags |= ASYNC_CLOSING; | ||
915 | 839 | ||
840 | if (tty_port_close_start(port, tty, filp) == 0) | ||
841 | return; | ||
916 | /* | 842 | /* |
917 | * May want to wait for any data to drain before closing. The BUSY | 843 | * May want to wait for any data to drain before closing. The BUSY |
918 | * flag keeps track of whether we are still sending or not - it is | 844 | * flag keeps track of whether we are still sending or not - it is |
919 | * very accurate for the cd1400, not quite so for the sc26198. | 845 | * very accurate for the cd1400, not quite so for the sc26198. |
920 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | 846 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) |
921 | */ | 847 | */ |
922 | tty->closing = 1; | ||
923 | |||
924 | spin_unlock_irqrestore(&stallion_lock, flags); | ||
925 | |||
926 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
927 | tty_wait_until_sent(tty, portp->closing_wait); | ||
928 | stl_waituntilsent(tty, (HZ / 2)); | 848 | stl_waituntilsent(tty, (HZ / 2)); |
929 | 849 | ||
930 | 850 | spin_lock_irqsave(&port->lock, flags); | |
931 | spin_lock_irqsave(&stallion_lock, flags); | ||
932 | portp->port.flags &= ~ASYNC_INITIALIZED; | 851 | portp->port.flags &= ~ASYNC_INITIALIZED; |
933 | spin_unlock_irqrestore(&stallion_lock, flags); | 852 | spin_unlock_irqrestore(&port->lock, flags); |
934 | 853 | ||
935 | stl_disableintrs(portp); | 854 | stl_disableintrs(portp); |
936 | if (tty->termios->c_cflag & HUPCL) | 855 | if (tty->termios->c_cflag & HUPCL) |
@@ -944,20 +863,9 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
944 | portp->tx.head = NULL; | 863 | portp->tx.head = NULL; |
945 | portp->tx.tail = NULL; | 864 | portp->tx.tail = NULL; |
946 | } | 865 | } |
947 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
948 | tty_ldisc_flush(tty); | ||
949 | 866 | ||
950 | tty->closing = 0; | 867 | tty_port_close_end(port, tty); |
951 | tty_port_tty_set(&portp->port, NULL); | 868 | tty_port_tty_set(port, NULL); |
952 | |||
953 | if (portp->openwaitcnt) { | ||
954 | if (portp->close_delay) | ||
955 | msleep_interruptible(jiffies_to_msecs(portp->close_delay)); | ||
956 | wake_up_interruptible(&portp->port.open_wait); | ||
957 | } | ||
958 | |||
959 | portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
960 | wake_up_interruptible(&portp->port.close_wait); | ||
961 | } | 869 | } |
962 | 870 | ||
963 | /*****************************************************************************/ | 871 | /*****************************************************************************/ |
@@ -1405,14 +1313,20 @@ static void stl_stop(struct tty_struct *tty) | |||
1405 | static void stl_hangup(struct tty_struct *tty) | 1313 | static void stl_hangup(struct tty_struct *tty) |
1406 | { | 1314 | { |
1407 | struct stlport *portp; | 1315 | struct stlport *portp; |
1316 | struct tty_port *port; | ||
1317 | unsigned long flags; | ||
1408 | 1318 | ||
1409 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1319 | pr_debug("stl_hangup(tty=%p)\n", tty); |
1410 | 1320 | ||
1411 | portp = tty->driver_data; | 1321 | portp = tty->driver_data; |
1412 | if (portp == NULL) | 1322 | if (portp == NULL) |
1413 | return; | 1323 | return; |
1324 | port = &portp->port; | ||
1325 | |||
1326 | spin_lock_irqsave(&port->lock, flags); | ||
1327 | port->flags &= ~ASYNC_INITIALIZED; | ||
1328 | spin_unlock_irqrestore(&port->lock, flags); | ||
1414 | 1329 | ||
1415 | portp->port.flags &= ~ASYNC_INITIALIZED; | ||
1416 | stl_disableintrs(portp); | 1330 | stl_disableintrs(portp); |
1417 | if (tty->termios->c_cflag & HUPCL) | 1331 | if (tty->termios->c_cflag & HUPCL) |
1418 | stl_setsignals(portp, 0, 0); | 1332 | stl_setsignals(portp, 0, 0); |
@@ -1426,10 +1340,7 @@ static void stl_hangup(struct tty_struct *tty) | |||
1426 | portp->tx.head = NULL; | 1340 | portp->tx.head = NULL; |
1427 | portp->tx.tail = NULL; | 1341 | portp->tx.tail = NULL; |
1428 | } | 1342 | } |
1429 | tty_port_tty_set(&portp->port, NULL); | 1343 | tty_port_hangup(port); |
1430 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1431 | portp->port.count = 0; | ||
1432 | wake_up_interruptible(&portp->port.open_wait); | ||
1433 | } | 1344 | } |
1434 | 1345 | ||
1435 | /*****************************************************************************/ | 1346 | /*****************************************************************************/ |
@@ -1776,6 +1687,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | |||
1776 | break; | 1687 | break; |
1777 | } | 1688 | } |
1778 | tty_port_init(&portp->port); | 1689 | tty_port_init(&portp->port); |
1690 | portp->port.ops = &stl_port_ops; | ||
1779 | portp->magic = STL_PORTMAGIC; | 1691 | portp->magic = STL_PORTMAGIC; |
1780 | portp->portnr = i; | 1692 | portp->portnr = i; |
1781 | portp->brdnr = panelp->brdnr; | 1693 | portp->brdnr = panelp->brdnr; |
@@ -2659,6 +2571,11 @@ static const struct tty_operations stl_ops = { | |||
2659 | .tiocmset = stl_tiocmset, | 2571 | .tiocmset = stl_tiocmset, |
2660 | }; | 2572 | }; |
2661 | 2573 | ||
2574 | static const struct tty_port_operations stl_port_ops = { | ||
2575 | .carrier_raised = stl_carrier_raised, | ||
2576 | .raise_dtr_rts = stl_raise_dtr_rts, | ||
2577 | }; | ||
2578 | |||
2662 | /*****************************************************************************/ | 2579 | /*****************************************************************************/ |
2663 | /* CD1400 HARDWARE FUNCTIONS */ | 2580 | /* CD1400 HARDWARE FUNCTIONS */ |
2664 | /*****************************************************************************/ | 2581 | /*****************************************************************************/ |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index ba4e86281fbf..b60be7b0decf 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -279,7 +279,7 @@ static void sx_disable_tx_interrupts(void *ptr); | |||
279 | static void sx_enable_tx_interrupts(void *ptr); | 279 | static void sx_enable_tx_interrupts(void *ptr); |
280 | static void sx_disable_rx_interrupts(void *ptr); | 280 | static void sx_disable_rx_interrupts(void *ptr); |
281 | static void sx_enable_rx_interrupts(void *ptr); | 281 | static void sx_enable_rx_interrupts(void *ptr); |
282 | static int sx_get_CD(void *ptr); | 282 | static int sx_carrier_raised(struct tty_port *port); |
283 | static void sx_shutdown_port(void *ptr); | 283 | static void sx_shutdown_port(void *ptr); |
284 | static int sx_set_real_termios(void *ptr); | 284 | static int sx_set_real_termios(void *ptr); |
285 | static void sx_close(void *ptr); | 285 | static void sx_close(void *ptr); |
@@ -360,7 +360,6 @@ static struct real_driver sx_real_driver = { | |||
360 | sx_enable_tx_interrupts, | 360 | sx_enable_tx_interrupts, |
361 | sx_disable_rx_interrupts, | 361 | sx_disable_rx_interrupts, |
362 | sx_enable_rx_interrupts, | 362 | sx_enable_rx_interrupts, |
363 | sx_get_CD, | ||
364 | sx_shutdown_port, | 363 | sx_shutdown_port, |
365 | sx_set_real_termios, | 364 | sx_set_real_termios, |
366 | sx_chars_in_buffer, | 365 | sx_chars_in_buffer, |
@@ -791,7 +790,7 @@ static int sx_getsignals(struct sx_port *port) | |||
791 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " | 790 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " |
792 | "%02x/%02x\n", | 791 | "%02x/%02x\n", |
793 | (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, | 792 | (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, |
794 | port->c_dcd, sx_get_CD(port), | 793 | port->c_dcd, tty_port_carrier_raised(&port->gs.port), |
795 | sx_read_channel_byte(port, hi_ip), | 794 | sx_read_channel_byte(port, hi_ip), |
796 | sx_read_channel_byte(port, hi_state)); | 795 | sx_read_channel_byte(port, hi_state)); |
797 | 796 | ||
@@ -1190,7 +1189,7 @@ static inline void sx_check_modem_signals(struct sx_port *port) | |||
1190 | 1189 | ||
1191 | hi_state = sx_read_channel_byte(port, hi_state); | 1190 | hi_state = sx_read_channel_byte(port, hi_state); |
1192 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", | 1191 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", |
1193 | port->c_dcd, sx_get_CD(port)); | 1192 | port->c_dcd, tty_port_carrier_raised(&port->gs.port)); |
1194 | 1193 | ||
1195 | if (hi_state & ST_BREAK) { | 1194 | if (hi_state & ST_BREAK) { |
1196 | hi_state &= ~ST_BREAK; | 1195 | hi_state &= ~ST_BREAK; |
@@ -1202,11 +1201,11 @@ static inline void sx_check_modem_signals(struct sx_port *port) | |||
1202 | hi_state &= ~ST_DCD; | 1201 | hi_state &= ~ST_DCD; |
1203 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); | 1202 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); |
1204 | sx_write_channel_byte(port, hi_state, hi_state); | 1203 | sx_write_channel_byte(port, hi_state, hi_state); |
1205 | c_dcd = sx_get_CD(port); | 1204 | c_dcd = tty_port_carrier_raised(&port->gs.port); |
1206 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); | 1205 | sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); |
1207 | if (c_dcd != port->c_dcd) { | 1206 | if (c_dcd != port->c_dcd) { |
1208 | port->c_dcd = c_dcd; | 1207 | port->c_dcd = c_dcd; |
1209 | if (sx_get_CD(port)) { | 1208 | if (tty_port_carrier_raised(&port->gs.port)) { |
1210 | /* DCD went UP */ | 1209 | /* DCD went UP */ |
1211 | if ((sx_read_channel_byte(port, hi_hstat) != | 1210 | if ((sx_read_channel_byte(port, hi_hstat) != |
1212 | HS_IDLE_CLOSED) && | 1211 | HS_IDLE_CLOSED) && |
@@ -1415,13 +1414,10 @@ static void sx_enable_rx_interrupts(void *ptr) | |||
1415 | } | 1414 | } |
1416 | 1415 | ||
1417 | /* Jeez. Isn't this simple? */ | 1416 | /* Jeez. Isn't this simple? */ |
1418 | static int sx_get_CD(void *ptr) | 1417 | static int sx_carrier_raised(struct tty_port *port) |
1419 | { | 1418 | { |
1420 | struct sx_port *port = ptr; | 1419 | struct sx_port *sp = container_of(port, struct sx_port, gs.port); |
1421 | func_enter2(); | 1420 | return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0); |
1422 | |||
1423 | func_exit(); | ||
1424 | return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0); | ||
1425 | } | 1421 | } |
1426 | 1422 | ||
1427 | /* Jeez. Isn't this simple? */ | 1423 | /* Jeez. Isn't this simple? */ |
@@ -1536,7 +1532,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp) | |||
1536 | } | 1532 | } |
1537 | /* tty->low_latency = 1; */ | 1533 | /* tty->low_latency = 1; */ |
1538 | 1534 | ||
1539 | port->c_dcd = sx_get_CD(port); | 1535 | port->c_dcd = sx_carrier_raised(&port->gs.port); |
1540 | sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); | 1536 | sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); |
1541 | 1537 | ||
1542 | func_exit(); | 1538 | func_exit(); |
@@ -1945,7 +1941,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1945 | 1941 | ||
1946 | static void sx_throttle(struct tty_struct *tty) | 1942 | static void sx_throttle(struct tty_struct *tty) |
1947 | { | 1943 | { |
1948 | struct sx_port *port = (struct sx_port *)tty->driver_data; | 1944 | struct sx_port *port = tty->driver_data; |
1949 | 1945 | ||
1950 | func_enter2(); | 1946 | func_enter2(); |
1951 | /* If the port is using any type of input flow | 1947 | /* If the port is using any type of input flow |
@@ -1959,7 +1955,7 @@ static void sx_throttle(struct tty_struct *tty) | |||
1959 | 1955 | ||
1960 | static void sx_unthrottle(struct tty_struct *tty) | 1956 | static void sx_unthrottle(struct tty_struct *tty) |
1961 | { | 1957 | { |
1962 | struct sx_port *port = (struct sx_port *)tty->driver_data; | 1958 | struct sx_port *port = tty->driver_data; |
1963 | 1959 | ||
1964 | func_enter2(); | 1960 | func_enter2(); |
1965 | /* Always unthrottle even if flow control is not enabled on | 1961 | /* Always unthrottle even if flow control is not enabled on |
@@ -2354,6 +2350,10 @@ static const struct tty_operations sx_ops = { | |||
2354 | .tiocmset = sx_tiocmset, | 2350 | .tiocmset = sx_tiocmset, |
2355 | }; | 2351 | }; |
2356 | 2352 | ||
2353 | static const struct tty_port_operations sx_port_ops = { | ||
2354 | .carrier_raised = sx_carrier_raised, | ||
2355 | }; | ||
2356 | |||
2357 | static int sx_init_drivers(void) | 2357 | static int sx_init_drivers(void) |
2358 | { | 2358 | { |
2359 | int error; | 2359 | int error; |
@@ -2410,6 +2410,7 @@ static int sx_init_portstructs(int nboards, int nports) | |||
2410 | for (j = 0; j < boards[i].nports; j++) { | 2410 | for (j = 0; j < boards[i].nports; j++) { |
2411 | sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); | 2411 | sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); |
2412 | tty_port_init(&port->gs.port); | 2412 | tty_port_init(&port->gs.port); |
2413 | port->gs.port.ops = &sx_port_ops; | ||
2413 | port->gs.magic = SX_MAGIC; | 2414 | port->gs.magic = SX_MAGIC; |
2414 | port->gs.close_delay = HZ / 2; | 2415 | port->gs.close_delay = HZ / 2; |
2415 | port->gs.closing_wait = 30 * HZ; | 2416 | port->gs.closing_wait = 30 * HZ; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 500f5176b6ba..b8063d4cad32 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -977,7 +977,7 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
977 | */ | 977 | */ |
978 | static void mgsl_stop(struct tty_struct *tty) | 978 | static void mgsl_stop(struct tty_struct *tty) |
979 | { | 979 | { |
980 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 980 | struct mgsl_struct *info = tty->driver_data; |
981 | unsigned long flags; | 981 | unsigned long flags; |
982 | 982 | ||
983 | if (mgsl_paranoia_check(info, tty->name, "mgsl_stop")) | 983 | if (mgsl_paranoia_check(info, tty->name, "mgsl_stop")) |
@@ -1000,7 +1000,7 @@ static void mgsl_stop(struct tty_struct *tty) | |||
1000 | */ | 1000 | */ |
1001 | static void mgsl_start(struct tty_struct *tty) | 1001 | static void mgsl_start(struct tty_struct *tty) |
1002 | { | 1002 | { |
1003 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 1003 | struct mgsl_struct *info = tty->driver_data; |
1004 | unsigned long flags; | 1004 | unsigned long flags; |
1005 | 1005 | ||
1006 | if (mgsl_paranoia_check(info, tty->name, "mgsl_start")) | 1006 | if (mgsl_paranoia_check(info, tty->name, "mgsl_start")) |
@@ -2057,7 +2057,7 @@ static int mgsl_put_char(struct tty_struct *tty, unsigned char ch) | |||
2057 | */ | 2057 | */ |
2058 | static void mgsl_flush_chars(struct tty_struct *tty) | 2058 | static void mgsl_flush_chars(struct tty_struct *tty) |
2059 | { | 2059 | { |
2060 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2060 | struct mgsl_struct *info = tty->driver_data; |
2061 | unsigned long flags; | 2061 | unsigned long flags; |
2062 | 2062 | ||
2063 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2063 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
@@ -2109,7 +2109,7 @@ static int mgsl_write(struct tty_struct * tty, | |||
2109 | const unsigned char *buf, int count) | 2109 | const unsigned char *buf, int count) |
2110 | { | 2110 | { |
2111 | int c, ret = 0; | 2111 | int c, ret = 0; |
2112 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2112 | struct mgsl_struct *info = tty->driver_data; |
2113 | unsigned long flags; | 2113 | unsigned long flags; |
2114 | 2114 | ||
2115 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2115 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
@@ -2232,7 +2232,7 @@ cleanup: | |||
2232 | */ | 2232 | */ |
2233 | static int mgsl_write_room(struct tty_struct *tty) | 2233 | static int mgsl_write_room(struct tty_struct *tty) |
2234 | { | 2234 | { |
2235 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2235 | struct mgsl_struct *info = tty->driver_data; |
2236 | int ret; | 2236 | int ret; |
2237 | 2237 | ||
2238 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room")) | 2238 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room")) |
@@ -2267,7 +2267,7 @@ static int mgsl_write_room(struct tty_struct *tty) | |||
2267 | */ | 2267 | */ |
2268 | static int mgsl_chars_in_buffer(struct tty_struct *tty) | 2268 | static int mgsl_chars_in_buffer(struct tty_struct *tty) |
2269 | { | 2269 | { |
2270 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2270 | struct mgsl_struct *info = tty->driver_data; |
2271 | 2271 | ||
2272 | if (debug_level >= DEBUG_LEVEL_INFO) | 2272 | if (debug_level >= DEBUG_LEVEL_INFO) |
2273 | printk("%s(%d):mgsl_chars_in_buffer(%s)\n", | 2273 | printk("%s(%d):mgsl_chars_in_buffer(%s)\n", |
@@ -2301,7 +2301,7 @@ static int mgsl_chars_in_buffer(struct tty_struct *tty) | |||
2301 | */ | 2301 | */ |
2302 | static void mgsl_flush_buffer(struct tty_struct *tty) | 2302 | static void mgsl_flush_buffer(struct tty_struct *tty) |
2303 | { | 2303 | { |
2304 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2304 | struct mgsl_struct *info = tty->driver_data; |
2305 | unsigned long flags; | 2305 | unsigned long flags; |
2306 | 2306 | ||
2307 | if (debug_level >= DEBUG_LEVEL_INFO) | 2307 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2329,7 +2329,7 @@ static void mgsl_flush_buffer(struct tty_struct *tty) | |||
2329 | */ | 2329 | */ |
2330 | static void mgsl_send_xchar(struct tty_struct *tty, char ch) | 2330 | static void mgsl_send_xchar(struct tty_struct *tty, char ch) |
2331 | { | 2331 | { |
2332 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2332 | struct mgsl_struct *info = tty->driver_data; |
2333 | unsigned long flags; | 2333 | unsigned long flags; |
2334 | 2334 | ||
2335 | if (debug_level >= DEBUG_LEVEL_INFO) | 2335 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2358,7 +2358,7 @@ static void mgsl_send_xchar(struct tty_struct *tty, char ch) | |||
2358 | */ | 2358 | */ |
2359 | static void mgsl_throttle(struct tty_struct * tty) | 2359 | static void mgsl_throttle(struct tty_struct * tty) |
2360 | { | 2360 | { |
2361 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2361 | struct mgsl_struct *info = tty->driver_data; |
2362 | unsigned long flags; | 2362 | unsigned long flags; |
2363 | 2363 | ||
2364 | if (debug_level >= DEBUG_LEVEL_INFO) | 2364 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2388,7 +2388,7 @@ static void mgsl_throttle(struct tty_struct * tty) | |||
2388 | */ | 2388 | */ |
2389 | static void mgsl_unthrottle(struct tty_struct * tty) | 2389 | static void mgsl_unthrottle(struct tty_struct * tty) |
2390 | { | 2390 | { |
2391 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2391 | struct mgsl_struct *info = tty->driver_data; |
2392 | unsigned long flags; | 2392 | unsigned long flags; |
2393 | 2393 | ||
2394 | if (debug_level >= DEBUG_LEVEL_INFO) | 2394 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2841,7 +2841,7 @@ static int modem_input_wait(struct mgsl_struct *info,int arg) | |||
2841 | */ | 2841 | */ |
2842 | static int tiocmget(struct tty_struct *tty, struct file *file) | 2842 | static int tiocmget(struct tty_struct *tty, struct file *file) |
2843 | { | 2843 | { |
2844 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2844 | struct mgsl_struct *info = tty->driver_data; |
2845 | unsigned int result; | 2845 | unsigned int result; |
2846 | unsigned long flags; | 2846 | unsigned long flags; |
2847 | 2847 | ||
@@ -2867,7 +2867,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file) | |||
2867 | static int tiocmset(struct tty_struct *tty, struct file *file, | 2867 | static int tiocmset(struct tty_struct *tty, struct file *file, |
2868 | unsigned int set, unsigned int clear) | 2868 | unsigned int set, unsigned int clear) |
2869 | { | 2869 | { |
2870 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 2870 | struct mgsl_struct *info = tty->driver_data; |
2871 | unsigned long flags; | 2871 | unsigned long flags; |
2872 | 2872 | ||
2873 | if (debug_level >= DEBUG_LEVEL_INFO) | 2873 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2898,7 +2898,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
2898 | */ | 2898 | */ |
2899 | static int mgsl_break(struct tty_struct *tty, int break_state) | 2899 | static int mgsl_break(struct tty_struct *tty, int break_state) |
2900 | { | 2900 | { |
2901 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 2901 | struct mgsl_struct * info = tty->driver_data; |
2902 | unsigned long flags; | 2902 | unsigned long flags; |
2903 | 2903 | ||
2904 | if (debug_level >= DEBUG_LEVEL_INFO) | 2904 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -2932,7 +2932,7 @@ static int mgsl_break(struct tty_struct *tty, int break_state) | |||
2932 | static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | 2932 | static int mgsl_ioctl(struct tty_struct *tty, struct file * file, |
2933 | unsigned int cmd, unsigned long arg) | 2933 | unsigned int cmd, unsigned long arg) |
2934 | { | 2934 | { |
2935 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 2935 | struct mgsl_struct * info = tty->driver_data; |
2936 | int ret; | 2936 | int ret; |
2937 | 2937 | ||
2938 | if (debug_level >= DEBUG_LEVEL_INFO) | 2938 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3042,7 +3042,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne | |||
3042 | */ | 3042 | */ |
3043 | static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 3043 | static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
3044 | { | 3044 | { |
3045 | struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; | 3045 | struct mgsl_struct *info = tty->driver_data; |
3046 | unsigned long flags; | 3046 | unsigned long flags; |
3047 | 3047 | ||
3048 | if (debug_level >= DEBUG_LEVEL_INFO) | 3048 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3096,7 +3096,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio | |||
3096 | */ | 3096 | */ |
3097 | static void mgsl_close(struct tty_struct *tty, struct file * filp) | 3097 | static void mgsl_close(struct tty_struct *tty, struct file * filp) |
3098 | { | 3098 | { |
3099 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 3099 | struct mgsl_struct * info = tty->driver_data; |
3100 | 3100 | ||
3101 | if (mgsl_paranoia_check(info, tty->name, "mgsl_close")) | 3101 | if (mgsl_paranoia_check(info, tty->name, "mgsl_close")) |
3102 | return; | 3102 | return; |
@@ -3104,70 +3104,18 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) | |||
3104 | if (debug_level >= DEBUG_LEVEL_INFO) | 3104 | if (debug_level >= DEBUG_LEVEL_INFO) |
3105 | printk("%s(%d):mgsl_close(%s) entry, count=%d\n", | 3105 | printk("%s(%d):mgsl_close(%s) entry, count=%d\n", |
3106 | __FILE__,__LINE__, info->device_name, info->port.count); | 3106 | __FILE__,__LINE__, info->device_name, info->port.count); |
3107 | |||
3108 | if (!info->port.count) | ||
3109 | return; | ||
3110 | 3107 | ||
3111 | if (tty_hung_up_p(filp)) | 3108 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
3112 | goto cleanup; | 3109 | goto cleanup; |
3113 | 3110 | ||
3114 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
3115 | /* | ||
3116 | * tty->count is 1 and the tty structure will be freed. | ||
3117 | * info->port.count should be one in this case. | ||
3118 | * if it's not, correct it so that the port is shutdown. | ||
3119 | */ | ||
3120 | printk("mgsl_close: bad refcount; tty->count is 1, " | ||
3121 | "info->port.count is %d\n", info->port.count); | ||
3122 | info->port.count = 1; | ||
3123 | } | ||
3124 | |||
3125 | info->port.count--; | ||
3126 | |||
3127 | /* if at least one open remaining, leave hardware active */ | ||
3128 | if (info->port.count) | ||
3129 | goto cleanup; | ||
3130 | |||
3131 | info->port.flags |= ASYNC_CLOSING; | ||
3132 | |||
3133 | /* set tty->closing to notify line discipline to | ||
3134 | * only process XON/XOFF characters. Only the N_TTY | ||
3135 | * discipline appears to use this (ppp does not). | ||
3136 | */ | ||
3137 | tty->closing = 1; | ||
3138 | |||
3139 | /* wait for transmit data to clear all layers */ | ||
3140 | |||
3141 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
3142 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
3143 | printk("%s(%d):mgsl_close(%s) calling tty_wait_until_sent\n", | ||
3144 | __FILE__,__LINE__, info->device_name ); | ||
3145 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
3146 | } | ||
3147 | |||
3148 | if (info->port.flags & ASYNC_INITIALIZED) | 3111 | if (info->port.flags & ASYNC_INITIALIZED) |
3149 | mgsl_wait_until_sent(tty, info->timeout); | 3112 | mgsl_wait_until_sent(tty, info->timeout); |
3150 | |||
3151 | mgsl_flush_buffer(tty); | 3113 | mgsl_flush_buffer(tty); |
3152 | |||
3153 | tty_ldisc_flush(tty); | 3114 | tty_ldisc_flush(tty); |
3154 | |||
3155 | shutdown(info); | 3115 | shutdown(info); |
3156 | 3116 | ||
3157 | tty->closing = 0; | 3117 | tty_port_close_end(&info->port, tty); |
3158 | info->port.tty = NULL; | 3118 | info->port.tty = NULL; |
3159 | |||
3160 | if (info->port.blocked_open) { | ||
3161 | if (info->port.close_delay) { | ||
3162 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | ||
3163 | } | ||
3164 | wake_up_interruptible(&info->port.open_wait); | ||
3165 | } | ||
3166 | |||
3167 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
3168 | |||
3169 | wake_up_interruptible(&info->port.close_wait); | ||
3170 | |||
3171 | cleanup: | 3119 | cleanup: |
3172 | if (debug_level >= DEBUG_LEVEL_INFO) | 3120 | if (debug_level >= DEBUG_LEVEL_INFO) |
3173 | printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, | 3121 | printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, |
@@ -3188,7 +3136,7 @@ cleanup: | |||
3188 | */ | 3136 | */ |
3189 | static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | 3137 | static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) |
3190 | { | 3138 | { |
3191 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 3139 | struct mgsl_struct * info = tty->driver_data; |
3192 | unsigned long orig_jiffies, char_time; | 3140 | unsigned long orig_jiffies, char_time; |
3193 | 3141 | ||
3194 | if (!info ) | 3142 | if (!info ) |
@@ -3261,7 +3209,7 @@ exit: | |||
3261 | */ | 3209 | */ |
3262 | static void mgsl_hangup(struct tty_struct *tty) | 3210 | static void mgsl_hangup(struct tty_struct *tty) |
3263 | { | 3211 | { |
3264 | struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; | 3212 | struct mgsl_struct * info = tty->driver_data; |
3265 | 3213 | ||
3266 | if (debug_level >= DEBUG_LEVEL_INFO) | 3214 | if (debug_level >= DEBUG_LEVEL_INFO) |
3267 | printk("%s(%d):mgsl_hangup(%s)\n", | 3215 | printk("%s(%d):mgsl_hangup(%s)\n", |
@@ -3281,6 +3229,35 @@ static void mgsl_hangup(struct tty_struct *tty) | |||
3281 | 3229 | ||
3282 | } /* end of mgsl_hangup() */ | 3230 | } /* end of mgsl_hangup() */ |
3283 | 3231 | ||
3232 | /* | ||
3233 | * carrier_raised() | ||
3234 | * | ||
3235 | * Return true if carrier is raised | ||
3236 | */ | ||
3237 | |||
3238 | static int carrier_raised(struct tty_port *port) | ||
3239 | { | ||
3240 | unsigned long flags; | ||
3241 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); | ||
3242 | |||
3243 | spin_lock_irqsave(&info->irq_spinlock, flags); | ||
3244 | usc_get_serial_signals(info); | ||
3245 | spin_unlock_irqrestore(&info->irq_spinlock, flags); | ||
3246 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | ||
3247 | } | ||
3248 | |||
3249 | static void raise_dtr_rts(struct tty_port *port) | ||
3250 | { | ||
3251 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); | ||
3252 | unsigned long flags; | ||
3253 | |||
3254 | spin_lock_irqsave(&info->irq_spinlock,flags); | ||
3255 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3256 | usc_set_serial_signals(info); | ||
3257 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | ||
3258 | } | ||
3259 | |||
3260 | |||
3284 | /* block_til_ready() | 3261 | /* block_til_ready() |
3285 | * | 3262 | * |
3286 | * Block the current process until the specified port | 3263 | * Block the current process until the specified port |
@@ -3302,6 +3279,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3302 | bool do_clocal = false; | 3279 | bool do_clocal = false; |
3303 | bool extra_count = false; | 3280 | bool extra_count = false; |
3304 | unsigned long flags; | 3281 | unsigned long flags; |
3282 | int dcd; | ||
3283 | struct tty_port *port = &info->port; | ||
3305 | 3284 | ||
3306 | if (debug_level >= DEBUG_LEVEL_INFO) | 3285 | if (debug_level >= DEBUG_LEVEL_INFO) |
3307 | printk("%s(%d):block_til_ready on %s\n", | 3286 | printk("%s(%d):block_til_ready on %s\n", |
@@ -3309,7 +3288,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3309 | 3288 | ||
3310 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3289 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3311 | /* nonblock mode is set or port is not enabled */ | 3290 | /* nonblock mode is set or port is not enabled */ |
3312 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3291 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3313 | return 0; | 3292 | return 0; |
3314 | } | 3293 | } |
3315 | 3294 | ||
@@ -3318,50 +3297,42 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3318 | 3297 | ||
3319 | /* Wait for carrier detect and the line to become | 3298 | /* Wait for carrier detect and the line to become |
3320 | * free (i.e., not in use by the callout). While we are in | 3299 | * free (i.e., not in use by the callout). While we are in |
3321 | * this loop, info->port.count is dropped by one, so that | 3300 | * this loop, port->count is dropped by one, so that |
3322 | * mgsl_close() knows when to free things. We restore it upon | 3301 | * mgsl_close() knows when to free things. We restore it upon |
3323 | * exit, either normal or abnormal. | 3302 | * exit, either normal or abnormal. |
3324 | */ | 3303 | */ |
3325 | 3304 | ||
3326 | retval = 0; | 3305 | retval = 0; |
3327 | add_wait_queue(&info->port.open_wait, &wait); | 3306 | add_wait_queue(&port->open_wait, &wait); |
3328 | 3307 | ||
3329 | if (debug_level >= DEBUG_LEVEL_INFO) | 3308 | if (debug_level >= DEBUG_LEVEL_INFO) |
3330 | printk("%s(%d):block_til_ready before block on %s count=%d\n", | 3309 | printk("%s(%d):block_til_ready before block on %s count=%d\n", |
3331 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3310 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3332 | 3311 | ||
3333 | spin_lock_irqsave(&info->irq_spinlock, flags); | 3312 | spin_lock_irqsave(&info->irq_spinlock, flags); |
3334 | if (!tty_hung_up_p(filp)) { | 3313 | if (!tty_hung_up_p(filp)) { |
3335 | extra_count = true; | 3314 | extra_count = true; |
3336 | info->port.count--; | 3315 | port->count--; |
3337 | } | 3316 | } |
3338 | spin_unlock_irqrestore(&info->irq_spinlock, flags); | 3317 | spin_unlock_irqrestore(&info->irq_spinlock, flags); |
3339 | info->port.blocked_open++; | 3318 | port->blocked_open++; |
3340 | 3319 | ||
3341 | while (1) { | 3320 | while (1) { |
3342 | if (tty->termios->c_cflag & CBAUD) { | 3321 | if (tty->termios->c_cflag & CBAUD) |
3343 | spin_lock_irqsave(&info->irq_spinlock,flags); | 3322 | tty_port_raise_dtr_rts(port); |
3344 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3345 | usc_set_serial_signals(info); | ||
3346 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | ||
3347 | } | ||
3348 | 3323 | ||
3349 | set_current_state(TASK_INTERRUPTIBLE); | 3324 | set_current_state(TASK_INTERRUPTIBLE); |
3350 | 3325 | ||
3351 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3326 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3352 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3327 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3353 | -EAGAIN : -ERESTARTSYS; | 3328 | -EAGAIN : -ERESTARTSYS; |
3354 | break; | 3329 | break; |
3355 | } | 3330 | } |
3356 | 3331 | ||
3357 | spin_lock_irqsave(&info->irq_spinlock,flags); | 3332 | dcd = tty_port_carrier_raised(&info->port); |
3358 | usc_get_serial_signals(info); | ||
3359 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | ||
3360 | 3333 | ||
3361 | if (!(info->port.flags & ASYNC_CLOSING) && | 3334 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd)) |
3362 | (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { | ||
3363 | break; | 3335 | break; |
3364 | } | ||
3365 | 3336 | ||
3366 | if (signal_pending(current)) { | 3337 | if (signal_pending(current)) { |
3367 | retval = -ERESTARTSYS; | 3338 | retval = -ERESTARTSYS; |
@@ -3370,24 +3341,25 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3370 | 3341 | ||
3371 | if (debug_level >= DEBUG_LEVEL_INFO) | 3342 | if (debug_level >= DEBUG_LEVEL_INFO) |
3372 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | 3343 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", |
3373 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3344 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3374 | 3345 | ||
3375 | schedule(); | 3346 | schedule(); |
3376 | } | 3347 | } |
3377 | 3348 | ||
3378 | set_current_state(TASK_RUNNING); | 3349 | set_current_state(TASK_RUNNING); |
3379 | remove_wait_queue(&info->port.open_wait, &wait); | 3350 | remove_wait_queue(&port->open_wait, &wait); |
3380 | 3351 | ||
3352 | /* FIXME: Racy on hangup during close wait */ | ||
3381 | if (extra_count) | 3353 | if (extra_count) |
3382 | info->port.count++; | 3354 | port->count++; |
3383 | info->port.blocked_open--; | 3355 | port->blocked_open--; |
3384 | 3356 | ||
3385 | if (debug_level >= DEBUG_LEVEL_INFO) | 3357 | if (debug_level >= DEBUG_LEVEL_INFO) |
3386 | printk("%s(%d):block_til_ready after blocking on %s count=%d\n", | 3358 | printk("%s(%d):block_til_ready after blocking on %s count=%d\n", |
3387 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3359 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3388 | 3360 | ||
3389 | if (!retval) | 3361 | if (!retval) |
3390 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3362 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3391 | 3363 | ||
3392 | return retval; | 3364 | return retval; |
3393 | 3365 | ||
@@ -4304,6 +4276,12 @@ static void mgsl_add_device( struct mgsl_struct *info ) | |||
4304 | 4276 | ||
4305 | } /* end of mgsl_add_device() */ | 4277 | } /* end of mgsl_add_device() */ |
4306 | 4278 | ||
4279 | static const struct tty_port_operations mgsl_port_ops = { | ||
4280 | .carrier_raised = carrier_raised, | ||
4281 | .raise_dtr_rts = raise_dtr_rts, | ||
4282 | }; | ||
4283 | |||
4284 | |||
4307 | /* mgsl_allocate_device() | 4285 | /* mgsl_allocate_device() |
4308 | * | 4286 | * |
4309 | * Allocate and initialize a device instance structure | 4287 | * Allocate and initialize a device instance structure |
@@ -4322,6 +4300,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) | |||
4322 | printk("Error can't allocate device instance data\n"); | 4300 | printk("Error can't allocate device instance data\n"); |
4323 | } else { | 4301 | } else { |
4324 | tty_port_init(&info->port); | 4302 | tty_port_init(&info->port); |
4303 | info->port.ops = &mgsl_port_ops; | ||
4325 | info->magic = MGSL_MAGIC; | 4304 | info->magic = MGSL_MAGIC; |
4326 | INIT_WORK(&info->task, mgsl_bh_handler); | 4305 | INIT_WORK(&info->task, mgsl_bh_handler); |
4327 | info->max_frame_size = 4096; | 4306 | info->max_frame_size = 4096; |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 08911ed66494..53544e21f191 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -720,44 +720,9 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
720 | return; | 720 | return; |
721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); | 721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); |
722 | 722 | ||
723 | if (!info->port.count) | 723 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
724 | return; | ||
725 | |||
726 | if (tty_hung_up_p(filp)) | ||
727 | goto cleanup; | ||
728 | |||
729 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
730 | /* | ||
731 | * tty->count is 1 and the tty structure will be freed. | ||
732 | * info->port.count should be one in this case. | ||
733 | * if it's not, correct it so that the port is shutdown. | ||
734 | */ | ||
735 | DBGERR(("%s close: bad refcount; tty->count=1, " | ||
736 | "info->port.count=%d\n", info->device_name, info->port.count)); | ||
737 | info->port.count = 1; | ||
738 | } | ||
739 | |||
740 | info->port.count--; | ||
741 | |||
742 | /* if at least one open remaining, leave hardware active */ | ||
743 | if (info->port.count) | ||
744 | goto cleanup; | 724 | goto cleanup; |
745 | 725 | ||
746 | info->port.flags |= ASYNC_CLOSING; | ||
747 | |||
748 | /* set tty->closing to notify line discipline to | ||
749 | * only process XON/XOFF characters. Only the N_TTY | ||
750 | * discipline appears to use this (ppp does not). | ||
751 | */ | ||
752 | tty->closing = 1; | ||
753 | |||
754 | /* wait for transmit data to clear all layers */ | ||
755 | |||
756 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
757 | DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); | ||
758 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
759 | } | ||
760 | |||
761 | if (info->port.flags & ASYNC_INITIALIZED) | 726 | if (info->port.flags & ASYNC_INITIALIZED) |
762 | wait_until_sent(tty, info->timeout); | 727 | wait_until_sent(tty, info->timeout); |
763 | flush_buffer(tty); | 728 | flush_buffer(tty); |
@@ -765,20 +730,8 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
765 | 730 | ||
766 | shutdown(info); | 731 | shutdown(info); |
767 | 732 | ||
768 | tty->closing = 0; | 733 | tty_port_close_end(&info->port, tty); |
769 | info->port.tty = NULL; | 734 | info->port.tty = NULL; |
770 | |||
771 | if (info->port.blocked_open) { | ||
772 | if (info->port.close_delay) { | ||
773 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | ||
774 | } | ||
775 | wake_up_interruptible(&info->port.open_wait); | ||
776 | } | ||
777 | |||
778 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
779 | |||
780 | wake_up_interruptible(&info->port.close_wait); | ||
781 | |||
782 | cleanup: | 735 | cleanup: |
783 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); | 736 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); |
784 | } | 737 | } |
@@ -3132,6 +3085,29 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
3132 | return 0; | 3085 | return 0; |
3133 | } | 3086 | } |
3134 | 3087 | ||
3088 | static int carrier_raised(struct tty_port *port) | ||
3089 | { | ||
3090 | unsigned long flags; | ||
3091 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3092 | |||
3093 | spin_lock_irqsave(&info->lock,flags); | ||
3094 | get_signals(info); | ||
3095 | spin_unlock_irqrestore(&info->lock,flags); | ||
3096 | return (info->signals & SerialSignal_DCD) ? 1 : 0; | ||
3097 | } | ||
3098 | |||
3099 | static void raise_dtr_rts(struct tty_port *port) | ||
3100 | { | ||
3101 | unsigned long flags; | ||
3102 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3103 | |||
3104 | spin_lock_irqsave(&info->lock,flags); | ||
3105 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3106 | set_signals(info); | ||
3107 | spin_unlock_irqrestore(&info->lock,flags); | ||
3108 | } | ||
3109 | |||
3110 | |||
3135 | /* | 3111 | /* |
3136 | * block current process until the device is ready to open | 3112 | * block current process until the device is ready to open |
3137 | */ | 3113 | */ |
@@ -3143,12 +3119,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3143 | bool do_clocal = false; | 3119 | bool do_clocal = false; |
3144 | bool extra_count = false; | 3120 | bool extra_count = false; |
3145 | unsigned long flags; | 3121 | unsigned long flags; |
3122 | int cd; | ||
3123 | struct tty_port *port = &info->port; | ||
3146 | 3124 | ||
3147 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); | 3125 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); |
3148 | 3126 | ||
3149 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3127 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3150 | /* nonblock mode is set or port is not enabled */ | 3128 | /* nonblock mode is set or port is not enabled */ |
3151 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3129 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3152 | return 0; | 3130 | return 0; |
3153 | } | 3131 | } |
3154 | 3132 | ||
@@ -3157,46 +3135,38 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3157 | 3135 | ||
3158 | /* Wait for carrier detect and the line to become | 3136 | /* Wait for carrier detect and the line to become |
3159 | * free (i.e., not in use by the callout). While we are in | 3137 | * free (i.e., not in use by the callout). While we are in |
3160 | * this loop, info->port.count is dropped by one, so that | 3138 | * this loop, port->count is dropped by one, so that |
3161 | * close() knows when to free things. We restore it upon | 3139 | * close() knows when to free things. We restore it upon |
3162 | * exit, either normal or abnormal. | 3140 | * exit, either normal or abnormal. |
3163 | */ | 3141 | */ |
3164 | 3142 | ||
3165 | retval = 0; | 3143 | retval = 0; |
3166 | add_wait_queue(&info->port.open_wait, &wait); | 3144 | add_wait_queue(&port->open_wait, &wait); |
3167 | 3145 | ||
3168 | spin_lock_irqsave(&info->lock, flags); | 3146 | spin_lock_irqsave(&info->lock, flags); |
3169 | if (!tty_hung_up_p(filp)) { | 3147 | if (!tty_hung_up_p(filp)) { |
3170 | extra_count = true; | 3148 | extra_count = true; |
3171 | info->port.count--; | 3149 | port->count--; |
3172 | } | 3150 | } |
3173 | spin_unlock_irqrestore(&info->lock, flags); | 3151 | spin_unlock_irqrestore(&info->lock, flags); |
3174 | info->port.blocked_open++; | 3152 | port->blocked_open++; |
3175 | 3153 | ||
3176 | while (1) { | 3154 | while (1) { |
3177 | if ((tty->termios->c_cflag & CBAUD)) { | 3155 | if ((tty->termios->c_cflag & CBAUD)) |
3178 | spin_lock_irqsave(&info->lock,flags); | 3156 | tty_port_raise_dtr_rts(port); |
3179 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3180 | set_signals(info); | ||
3181 | spin_unlock_irqrestore(&info->lock,flags); | ||
3182 | } | ||
3183 | 3157 | ||
3184 | set_current_state(TASK_INTERRUPTIBLE); | 3158 | set_current_state(TASK_INTERRUPTIBLE); |
3185 | 3159 | ||
3186 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3160 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3187 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3161 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3188 | -EAGAIN : -ERESTARTSYS; | 3162 | -EAGAIN : -ERESTARTSYS; |
3189 | break; | 3163 | break; |
3190 | } | 3164 | } |
3191 | 3165 | ||
3192 | spin_lock_irqsave(&info->lock,flags); | 3166 | cd = tty_port_carrier_raised(port); |
3193 | get_signals(info); | ||
3194 | spin_unlock_irqrestore(&info->lock,flags); | ||
3195 | 3167 | ||
3196 | if (!(info->port.flags & ASYNC_CLOSING) && | 3168 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd )) |
3197 | (do_clocal || (info->signals & SerialSignal_DCD)) ) { | ||
3198 | break; | 3169 | break; |
3199 | } | ||
3200 | 3170 | ||
3201 | if (signal_pending(current)) { | 3171 | if (signal_pending(current)) { |
3202 | retval = -ERESTARTSYS; | 3172 | retval = -ERESTARTSYS; |
@@ -3208,14 +3178,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3208 | } | 3178 | } |
3209 | 3179 | ||
3210 | set_current_state(TASK_RUNNING); | 3180 | set_current_state(TASK_RUNNING); |
3211 | remove_wait_queue(&info->port.open_wait, &wait); | 3181 | remove_wait_queue(&port->open_wait, &wait); |
3212 | 3182 | ||
3213 | if (extra_count) | 3183 | if (extra_count) |
3214 | info->port.count++; | 3184 | port->count++; |
3215 | info->port.blocked_open--; | 3185 | port->blocked_open--; |
3216 | 3186 | ||
3217 | if (!retval) | 3187 | if (!retval) |
3218 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3188 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3219 | 3189 | ||
3220 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); | 3190 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); |
3221 | return retval; | 3191 | return retval; |
@@ -3444,6 +3414,11 @@ static void add_device(struct slgt_info *info) | |||
3444 | #endif | 3414 | #endif |
3445 | } | 3415 | } |
3446 | 3416 | ||
3417 | static const struct tty_port_operations slgt_port_ops = { | ||
3418 | .carrier_raised = carrier_raised, | ||
3419 | .raise_dtr_rts = raise_dtr_rts, | ||
3420 | }; | ||
3421 | |||
3447 | /* | 3422 | /* |
3448 | * allocate device instance structure, return NULL on failure | 3423 | * allocate device instance structure, return NULL on failure |
3449 | */ | 3424 | */ |
@@ -3458,6 +3433,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3458 | driver_name, adapter_num, port_num)); | 3433 | driver_name, adapter_num, port_num)); |
3459 | } else { | 3434 | } else { |
3460 | tty_port_init(&info->port); | 3435 | tty_port_init(&info->port); |
3436 | info->port.ops = &slgt_port_ops; | ||
3461 | info->magic = MGSL_MAGIC; | 3437 | info->magic = MGSL_MAGIC; |
3462 | INIT_WORK(&info->task, bh_handler); | 3438 | INIT_WORK(&info->task, bh_handler); |
3463 | info->max_frame_size = 4096; | 3439 | info->max_frame_size = 4096; |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 6bdb44f7bec2..7b0c5b2dd263 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info); | |||
558 | 558 | ||
559 | static int startup(SLMP_INFO *info); | 559 | static int startup(SLMP_INFO *info); |
560 | static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); | 560 | static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); |
561 | static int carrier_raised(struct tty_port *port); | ||
561 | static void shutdown(SLMP_INFO *info); | 562 | static void shutdown(SLMP_INFO *info); |
562 | static void program_hw(SLMP_INFO *info); | 563 | static void program_hw(SLMP_INFO *info); |
563 | static void change_params(SLMP_INFO *info); | 564 | static void change_params(SLMP_INFO *info); |
@@ -800,7 +801,7 @@ cleanup: | |||
800 | */ | 801 | */ |
801 | static void close(struct tty_struct *tty, struct file *filp) | 802 | static void close(struct tty_struct *tty, struct file *filp) |
802 | { | 803 | { |
803 | SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; | 804 | SLMP_INFO * info = tty->driver_data; |
804 | 805 | ||
805 | if (sanity_check(info, tty->name, "close")) | 806 | if (sanity_check(info, tty->name, "close")) |
806 | return; | 807 | return; |
@@ -809,70 +810,18 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
809 | printk("%s(%d):%s close() entry, count=%d\n", | 810 | printk("%s(%d):%s close() entry, count=%d\n", |
810 | __FILE__,__LINE__, info->device_name, info->port.count); | 811 | __FILE__,__LINE__, info->device_name, info->port.count); |
811 | 812 | ||
812 | if (!info->port.count) | 813 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
813 | return; | ||
814 | |||
815 | if (tty_hung_up_p(filp)) | ||
816 | goto cleanup; | ||
817 | |||
818 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
819 | /* | ||
820 | * tty->count is 1 and the tty structure will be freed. | ||
821 | * info->port.count should be one in this case. | ||
822 | * if it's not, correct it so that the port is shutdown. | ||
823 | */ | ||
824 | printk("%s(%d):%s close: bad refcount; tty->count is 1, " | ||
825 | "info->port.count is %d\n", | ||
826 | __FILE__,__LINE__, info->device_name, info->port.count); | ||
827 | info->port.count = 1; | ||
828 | } | ||
829 | |||
830 | info->port.count--; | ||
831 | |||
832 | /* if at least one open remaining, leave hardware active */ | ||
833 | if (info->port.count) | ||
834 | goto cleanup; | 814 | goto cleanup; |
835 | 815 | ||
836 | info->port.flags |= ASYNC_CLOSING; | ||
837 | |||
838 | /* set tty->closing to notify line discipline to | ||
839 | * only process XON/XOFF characters. Only the N_TTY | ||
840 | * discipline appears to use this (ppp does not). | ||
841 | */ | ||
842 | tty->closing = 1; | ||
843 | |||
844 | /* wait for transmit data to clear all layers */ | ||
845 | |||
846 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
847 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
848 | printk("%s(%d):%s close() calling tty_wait_until_sent\n", | ||
849 | __FILE__,__LINE__, info->device_name ); | ||
850 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
851 | } | ||
852 | |||
853 | if (info->port.flags & ASYNC_INITIALIZED) | 816 | if (info->port.flags & ASYNC_INITIALIZED) |
854 | wait_until_sent(tty, info->timeout); | 817 | wait_until_sent(tty, info->timeout); |
855 | 818 | ||
856 | flush_buffer(tty); | 819 | flush_buffer(tty); |
857 | |||
858 | tty_ldisc_flush(tty); | 820 | tty_ldisc_flush(tty); |
859 | |||
860 | shutdown(info); | 821 | shutdown(info); |
861 | 822 | ||
862 | tty->closing = 0; | 823 | tty_port_close_end(&info->port, tty); |
863 | info->port.tty = NULL; | 824 | info->port.tty = NULL; |
864 | |||
865 | if (info->port.blocked_open) { | ||
866 | if (info->port.close_delay) { | ||
867 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | ||
868 | } | ||
869 | wake_up_interruptible(&info->port.open_wait); | ||
870 | } | ||
871 | |||
872 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
873 | |||
874 | wake_up_interruptible(&info->port.close_wait); | ||
875 | |||
876 | cleanup: | 825 | cleanup: |
877 | if (debug_level >= DEBUG_LEVEL_INFO) | 826 | if (debug_level >= DEBUG_LEVEL_INFO) |
878 | printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, | 827 | printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, |
@@ -884,7 +833,7 @@ cleanup: | |||
884 | */ | 833 | */ |
885 | static void hangup(struct tty_struct *tty) | 834 | static void hangup(struct tty_struct *tty) |
886 | { | 835 | { |
887 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 836 | SLMP_INFO *info = tty->driver_data; |
888 | 837 | ||
889 | if (debug_level >= DEBUG_LEVEL_INFO) | 838 | if (debug_level >= DEBUG_LEVEL_INFO) |
890 | printk("%s(%d):%s hangup()\n", | 839 | printk("%s(%d):%s hangup()\n", |
@@ -907,7 +856,7 @@ static void hangup(struct tty_struct *tty) | |||
907 | */ | 856 | */ |
908 | static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 857 | static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
909 | { | 858 | { |
910 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 859 | SLMP_INFO *info = tty->driver_data; |
911 | unsigned long flags; | 860 | unsigned long flags; |
912 | 861 | ||
913 | if (debug_level >= DEBUG_LEVEL_INFO) | 862 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -960,7 +909,7 @@ static int write(struct tty_struct *tty, | |||
960 | const unsigned char *buf, int count) | 909 | const unsigned char *buf, int count) |
961 | { | 910 | { |
962 | int c, ret = 0; | 911 | int c, ret = 0; |
963 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 912 | SLMP_INFO *info = tty->driver_data; |
964 | unsigned long flags; | 913 | unsigned long flags; |
965 | 914 | ||
966 | if (debug_level >= DEBUG_LEVEL_INFO) | 915 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1038,7 +987,7 @@ cleanup: | |||
1038 | */ | 987 | */ |
1039 | static int put_char(struct tty_struct *tty, unsigned char ch) | 988 | static int put_char(struct tty_struct *tty, unsigned char ch) |
1040 | { | 989 | { |
1041 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 990 | SLMP_INFO *info = tty->driver_data; |
1042 | unsigned long flags; | 991 | unsigned long flags; |
1043 | int ret = 0; | 992 | int ret = 0; |
1044 | 993 | ||
@@ -1075,7 +1024,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch) | |||
1075 | */ | 1024 | */ |
1076 | static void send_xchar(struct tty_struct *tty, char ch) | 1025 | static void send_xchar(struct tty_struct *tty, char ch) |
1077 | { | 1026 | { |
1078 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1027 | SLMP_INFO *info = tty->driver_data; |
1079 | unsigned long flags; | 1028 | unsigned long flags; |
1080 | 1029 | ||
1081 | if (debug_level >= DEBUG_LEVEL_INFO) | 1030 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1099,7 +1048,7 @@ static void send_xchar(struct tty_struct *tty, char ch) | |||
1099 | */ | 1048 | */ |
1100 | static void wait_until_sent(struct tty_struct *tty, int timeout) | 1049 | static void wait_until_sent(struct tty_struct *tty, int timeout) |
1101 | { | 1050 | { |
1102 | SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; | 1051 | SLMP_INFO * info = tty->driver_data; |
1103 | unsigned long orig_jiffies, char_time; | 1052 | unsigned long orig_jiffies, char_time; |
1104 | 1053 | ||
1105 | if (!info ) | 1054 | if (!info ) |
@@ -1166,7 +1115,7 @@ exit: | |||
1166 | */ | 1115 | */ |
1167 | static int write_room(struct tty_struct *tty) | 1116 | static int write_room(struct tty_struct *tty) |
1168 | { | 1117 | { |
1169 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1118 | SLMP_INFO *info = tty->driver_data; |
1170 | int ret; | 1119 | int ret; |
1171 | 1120 | ||
1172 | if (sanity_check(info, tty->name, "write_room")) | 1121 | if (sanity_check(info, tty->name, "write_room")) |
@@ -1193,7 +1142,7 @@ static int write_room(struct tty_struct *tty) | |||
1193 | */ | 1142 | */ |
1194 | static void flush_chars(struct tty_struct *tty) | 1143 | static void flush_chars(struct tty_struct *tty) |
1195 | { | 1144 | { |
1196 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1145 | SLMP_INFO *info = tty->driver_data; |
1197 | unsigned long flags; | 1146 | unsigned long flags; |
1198 | 1147 | ||
1199 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 1148 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
@@ -1232,7 +1181,7 @@ static void flush_chars(struct tty_struct *tty) | |||
1232 | */ | 1181 | */ |
1233 | static void flush_buffer(struct tty_struct *tty) | 1182 | static void flush_buffer(struct tty_struct *tty) |
1234 | { | 1183 | { |
1235 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1184 | SLMP_INFO *info = tty->driver_data; |
1236 | unsigned long flags; | 1185 | unsigned long flags; |
1237 | 1186 | ||
1238 | if (debug_level >= DEBUG_LEVEL_INFO) | 1187 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1254,7 +1203,7 @@ static void flush_buffer(struct tty_struct *tty) | |||
1254 | */ | 1203 | */ |
1255 | static void tx_hold(struct tty_struct *tty) | 1204 | static void tx_hold(struct tty_struct *tty) |
1256 | { | 1205 | { |
1257 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1206 | SLMP_INFO *info = tty->driver_data; |
1258 | unsigned long flags; | 1207 | unsigned long flags; |
1259 | 1208 | ||
1260 | if (sanity_check(info, tty->name, "tx_hold")) | 1209 | if (sanity_check(info, tty->name, "tx_hold")) |
@@ -1274,7 +1223,7 @@ static void tx_hold(struct tty_struct *tty) | |||
1274 | */ | 1223 | */ |
1275 | static void tx_release(struct tty_struct *tty) | 1224 | static void tx_release(struct tty_struct *tty) |
1276 | { | 1225 | { |
1277 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1226 | SLMP_INFO *info = tty->driver_data; |
1278 | unsigned long flags; | 1227 | unsigned long flags; |
1279 | 1228 | ||
1280 | if (sanity_check(info, tty->name, "tx_release")) | 1229 | if (sanity_check(info, tty->name, "tx_release")) |
@@ -1304,7 +1253,7 @@ static void tx_release(struct tty_struct *tty) | |||
1304 | static int do_ioctl(struct tty_struct *tty, struct file *file, | 1253 | static int do_ioctl(struct tty_struct *tty, struct file *file, |
1305 | unsigned int cmd, unsigned long arg) | 1254 | unsigned int cmd, unsigned long arg) |
1306 | { | 1255 | { |
1307 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1256 | SLMP_INFO *info = tty->driver_data; |
1308 | int error; | 1257 | int error; |
1309 | struct mgsl_icount cnow; /* kernel counter temps */ | 1258 | struct mgsl_icount cnow; /* kernel counter temps */ |
1310 | struct serial_icounter_struct __user *p_cuser; /* user space */ | 1259 | struct serial_icounter_struct __user *p_cuser; /* user space */ |
@@ -1515,7 +1464,7 @@ done: | |||
1515 | */ | 1464 | */ |
1516 | static int chars_in_buffer(struct tty_struct *tty) | 1465 | static int chars_in_buffer(struct tty_struct *tty) |
1517 | { | 1466 | { |
1518 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1467 | SLMP_INFO *info = tty->driver_data; |
1519 | 1468 | ||
1520 | if (sanity_check(info, tty->name, "chars_in_buffer")) | 1469 | if (sanity_check(info, tty->name, "chars_in_buffer")) |
1521 | return 0; | 1470 | return 0; |
@@ -1531,7 +1480,7 @@ static int chars_in_buffer(struct tty_struct *tty) | |||
1531 | */ | 1480 | */ |
1532 | static void throttle(struct tty_struct * tty) | 1481 | static void throttle(struct tty_struct * tty) |
1533 | { | 1482 | { |
1534 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1483 | SLMP_INFO *info = tty->driver_data; |
1535 | unsigned long flags; | 1484 | unsigned long flags; |
1536 | 1485 | ||
1537 | if (debug_level >= DEBUG_LEVEL_INFO) | 1486 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1556,7 +1505,7 @@ static void throttle(struct tty_struct * tty) | |||
1556 | */ | 1505 | */ |
1557 | static void unthrottle(struct tty_struct * tty) | 1506 | static void unthrottle(struct tty_struct * tty) |
1558 | { | 1507 | { |
1559 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 1508 | SLMP_INFO *info = tty->driver_data; |
1560 | unsigned long flags; | 1509 | unsigned long flags; |
1561 | 1510 | ||
1562 | if (debug_level >= DEBUG_LEVEL_INFO) | 1511 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1587,7 +1536,7 @@ static void unthrottle(struct tty_struct * tty) | |||
1587 | static int set_break(struct tty_struct *tty, int break_state) | 1536 | static int set_break(struct tty_struct *tty, int break_state) |
1588 | { | 1537 | { |
1589 | unsigned char RegValue; | 1538 | unsigned char RegValue; |
1590 | SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; | 1539 | SLMP_INFO * info = tty->driver_data; |
1591 | unsigned long flags; | 1540 | unsigned long flags; |
1592 | 1541 | ||
1593 | if (debug_level >= DEBUG_LEVEL_INFO) | 1542 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3269,7 +3218,7 @@ static int modem_input_wait(SLMP_INFO *info,int arg) | |||
3269 | */ | 3218 | */ |
3270 | static int tiocmget(struct tty_struct *tty, struct file *file) | 3219 | static int tiocmget(struct tty_struct *tty, struct file *file) |
3271 | { | 3220 | { |
3272 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 3221 | SLMP_INFO *info = tty->driver_data; |
3273 | unsigned int result; | 3222 | unsigned int result; |
3274 | unsigned long flags; | 3223 | unsigned long flags; |
3275 | 3224 | ||
@@ -3295,7 +3244,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file) | |||
3295 | static int tiocmset(struct tty_struct *tty, struct file *file, | 3244 | static int tiocmset(struct tty_struct *tty, struct file *file, |
3296 | unsigned int set, unsigned int clear) | 3245 | unsigned int set, unsigned int clear) |
3297 | { | 3246 | { |
3298 | SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; | 3247 | SLMP_INFO *info = tty->driver_data; |
3299 | unsigned long flags; | 3248 | unsigned long flags; |
3300 | 3249 | ||
3301 | if (debug_level >= DEBUG_LEVEL_INFO) | 3250 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3318,7 +3267,28 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
3318 | return 0; | 3267 | return 0; |
3319 | } | 3268 | } |
3320 | 3269 | ||
3270 | static int carrier_raised(struct tty_port *port) | ||
3271 | { | ||
3272 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); | ||
3273 | unsigned long flags; | ||
3274 | |||
3275 | spin_lock_irqsave(&info->lock,flags); | ||
3276 | get_signals(info); | ||
3277 | spin_unlock_irqrestore(&info->lock,flags); | ||
3321 | 3278 | ||
3279 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | ||
3280 | } | ||
3281 | |||
3282 | static void raise_dtr_rts(struct tty_port *port) | ||
3283 | { | ||
3284 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); | ||
3285 | unsigned long flags; | ||
3286 | |||
3287 | spin_lock_irqsave(&info->lock,flags); | ||
3288 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3289 | set_signals(info); | ||
3290 | spin_unlock_irqrestore(&info->lock,flags); | ||
3291 | } | ||
3322 | 3292 | ||
3323 | /* Block the current process until the specified port is ready to open. | 3293 | /* Block the current process until the specified port is ready to open. |
3324 | */ | 3294 | */ |
@@ -3330,6 +3300,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3330 | bool do_clocal = false; | 3300 | bool do_clocal = false; |
3331 | bool extra_count = false; | 3301 | bool extra_count = false; |
3332 | unsigned long flags; | 3302 | unsigned long flags; |
3303 | int cd; | ||
3304 | struct tty_port *port = &info->port; | ||
3333 | 3305 | ||
3334 | if (debug_level >= DEBUG_LEVEL_INFO) | 3306 | if (debug_level >= DEBUG_LEVEL_INFO) |
3335 | printk("%s(%d):%s block_til_ready()\n", | 3307 | printk("%s(%d):%s block_til_ready()\n", |
@@ -3338,7 +3310,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3338 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3310 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3339 | /* nonblock mode is set or port is not enabled */ | 3311 | /* nonblock mode is set or port is not enabled */ |
3340 | /* just verify that callout device is not active */ | 3312 | /* just verify that callout device is not active */ |
3341 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3313 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3342 | return 0; | 3314 | return 0; |
3343 | } | 3315 | } |
3344 | 3316 | ||
@@ -3347,50 +3319,42 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3347 | 3319 | ||
3348 | /* Wait for carrier detect and the line to become | 3320 | /* Wait for carrier detect and the line to become |
3349 | * free (i.e., not in use by the callout). While we are in | 3321 | * free (i.e., not in use by the callout). While we are in |
3350 | * this loop, info->port.count is dropped by one, so that | 3322 | * this loop, port->count is dropped by one, so that |
3351 | * close() knows when to free things. We restore it upon | 3323 | * close() knows when to free things. We restore it upon |
3352 | * exit, either normal or abnormal. | 3324 | * exit, either normal or abnormal. |
3353 | */ | 3325 | */ |
3354 | 3326 | ||
3355 | retval = 0; | 3327 | retval = 0; |
3356 | add_wait_queue(&info->port.open_wait, &wait); | 3328 | add_wait_queue(&port->open_wait, &wait); |
3357 | 3329 | ||
3358 | if (debug_level >= DEBUG_LEVEL_INFO) | 3330 | if (debug_level >= DEBUG_LEVEL_INFO) |
3359 | printk("%s(%d):%s block_til_ready() before block, count=%d\n", | 3331 | printk("%s(%d):%s block_til_ready() before block, count=%d\n", |
3360 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3332 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3361 | 3333 | ||
3362 | spin_lock_irqsave(&info->lock, flags); | 3334 | spin_lock_irqsave(&info->lock, flags); |
3363 | if (!tty_hung_up_p(filp)) { | 3335 | if (!tty_hung_up_p(filp)) { |
3364 | extra_count = true; | 3336 | extra_count = true; |
3365 | info->port.count--; | 3337 | port->count--; |
3366 | } | 3338 | } |
3367 | spin_unlock_irqrestore(&info->lock, flags); | 3339 | spin_unlock_irqrestore(&info->lock, flags); |
3368 | info->port.blocked_open++; | 3340 | port->blocked_open++; |
3369 | 3341 | ||
3370 | while (1) { | 3342 | while (1) { |
3371 | if ((tty->termios->c_cflag & CBAUD)) { | 3343 | if (tty->termios->c_cflag & CBAUD) |
3372 | spin_lock_irqsave(&info->lock,flags); | 3344 | tty_port_raise_dtr_rts(port); |
3373 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3374 | set_signals(info); | ||
3375 | spin_unlock_irqrestore(&info->lock,flags); | ||
3376 | } | ||
3377 | 3345 | ||
3378 | set_current_state(TASK_INTERRUPTIBLE); | 3346 | set_current_state(TASK_INTERRUPTIBLE); |
3379 | 3347 | ||
3380 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3348 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3381 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3349 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3382 | -EAGAIN : -ERESTARTSYS; | 3350 | -EAGAIN : -ERESTARTSYS; |
3383 | break; | 3351 | break; |
3384 | } | 3352 | } |
3385 | 3353 | ||
3386 | spin_lock_irqsave(&info->lock,flags); | 3354 | cd = tty_port_carrier_raised(port); |
3387 | get_signals(info); | ||
3388 | spin_unlock_irqrestore(&info->lock,flags); | ||
3389 | 3355 | ||
3390 | if (!(info->port.flags & ASYNC_CLOSING) && | 3356 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) |
3391 | (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { | ||
3392 | break; | 3357 | break; |
3393 | } | ||
3394 | 3358 | ||
3395 | if (signal_pending(current)) { | 3359 | if (signal_pending(current)) { |
3396 | retval = -ERESTARTSYS; | 3360 | retval = -ERESTARTSYS; |
@@ -3399,24 +3363,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3399 | 3363 | ||
3400 | if (debug_level >= DEBUG_LEVEL_INFO) | 3364 | if (debug_level >= DEBUG_LEVEL_INFO) |
3401 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3365 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3402 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3366 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3403 | 3367 | ||
3404 | schedule(); | 3368 | schedule(); |
3405 | } | 3369 | } |
3406 | 3370 | ||
3407 | set_current_state(TASK_RUNNING); | 3371 | set_current_state(TASK_RUNNING); |
3408 | remove_wait_queue(&info->port.open_wait, &wait); | 3372 | remove_wait_queue(&port->open_wait, &wait); |
3409 | 3373 | ||
3410 | if (extra_count) | 3374 | if (extra_count) |
3411 | info->port.count++; | 3375 | port->count++; |
3412 | info->port.blocked_open--; | 3376 | port->blocked_open--; |
3413 | 3377 | ||
3414 | if (debug_level >= DEBUG_LEVEL_INFO) | 3378 | if (debug_level >= DEBUG_LEVEL_INFO) |
3415 | printk("%s(%d):%s block_til_ready() after, count=%d\n", | 3379 | printk("%s(%d):%s block_til_ready() after, count=%d\n", |
3416 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3380 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3417 | 3381 | ||
3418 | if (!retval) | 3382 | if (!retval) |
3419 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3383 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3420 | 3384 | ||
3421 | return retval; | 3385 | return retval; |
3422 | } | 3386 | } |
@@ -3782,6 +3746,11 @@ static void add_device(SLMP_INFO *info) | |||
3782 | #endif | 3746 | #endif |
3783 | } | 3747 | } |
3784 | 3748 | ||
3749 | static const struct tty_port_operations port_ops = { | ||
3750 | .carrier_raised = carrier_raised, | ||
3751 | .raise_dtr_rts = raise_dtr_rts, | ||
3752 | }; | ||
3753 | |||
3785 | /* Allocate and initialize a device instance structure | 3754 | /* Allocate and initialize a device instance structure |
3786 | * | 3755 | * |
3787 | * Return Value: pointer to SLMP_INFO if success, otherwise NULL | 3756 | * Return Value: pointer to SLMP_INFO if success, otherwise NULL |
@@ -3798,6 +3767,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) | |||
3798 | __FILE__,__LINE__, adapter_num, port_num); | 3767 | __FILE__,__LINE__, adapter_num, port_num); |
3799 | } else { | 3768 | } else { |
3800 | tty_port_init(&info->port); | 3769 | tty_port_init(&info->port); |
3770 | info->port.ops = &port_ops; | ||
3801 | info->magic = MGSL_MAGIC; | 3771 | info->magic = MGSL_MAGIC; |
3802 | INIT_WORK(&info->task, bh_handler); | 3772 | INIT_WORK(&info->task, bh_handler); |
3803 | info->max_frame_size = 4096; | 3773 | info->max_frame_size = 4096; |
@@ -3940,6 +3910,7 @@ static const struct tty_operations ops = { | |||
3940 | .tiocmset = tiocmset, | 3910 | .tiocmset = tiocmset, |
3941 | }; | 3911 | }; |
3942 | 3912 | ||
3913 | |||
3943 | static void synclinkmp_cleanup(void) | 3914 | static void synclinkmp_cleanup(void) |
3944 | { | 3915 | { |
3945 | int rc; | 3916 | int rc; |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index db15f9ba7c0b..d33e5ab06177 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1111,9 +1111,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
1111 | * Locks the line discipline as required | 1111 | * Locks the line discipline as required |
1112 | * Writes to the tty driver are serialized by the atomic_write_lock | 1112 | * Writes to the tty driver are serialized by the atomic_write_lock |
1113 | * and are then processed in chunks to the device. The line discipline | 1113 | * and are then processed in chunks to the device. The line discipline |
1114 | * write method will not be involked in parallel for each device | 1114 | * write method will not be invoked in parallel for each device. |
1115 | * The line discipline write method is called under the big | ||
1116 | * kernel lock for historical reasons. New code should not rely on this. | ||
1117 | */ | 1115 | */ |
1118 | 1116 | ||
1119 | static ssize_t tty_write(struct file *file, const char __user *buf, | 1117 | static ssize_t tty_write(struct file *file, const char __user *buf, |
@@ -1213,7 +1211,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p) | |||
1213 | * be held until the 'fast-open' is also done. Will change once we | 1211 | * be held until the 'fast-open' is also done. Will change once we |
1214 | * have refcounting in the driver and per driver locking | 1212 | * have refcounting in the driver and per driver locking |
1215 | */ | 1213 | */ |
1216 | struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, | 1214 | static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, |
1217 | struct inode *inode, int idx) | 1215 | struct inode *inode, int idx) |
1218 | { | 1216 | { |
1219 | struct tty_struct *tty; | 1217 | struct tty_struct *tty; |
@@ -2050,7 +2048,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2050 | /** | 2048 | /** |
2051 | * tty_do_resize - resize event | 2049 | * tty_do_resize - resize event |
2052 | * @tty: tty being resized | 2050 | * @tty: tty being resized |
2053 | * @real_tty: real tty (not the same as tty if using a pty/tty pair) | ||
2054 | * @rows: rows (character) | 2051 | * @rows: rows (character) |
2055 | * @cols: cols (character) | 2052 | * @cols: cols (character) |
2056 | * | 2053 | * |
@@ -2058,41 +2055,34 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) | |||
2058 | * peform a terminal resize correctly | 2055 | * peform a terminal resize correctly |
2059 | */ | 2056 | */ |
2060 | 2057 | ||
2061 | int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 2058 | int tty_do_resize(struct tty_struct *tty, struct winsize *ws) |
2062 | struct winsize *ws) | ||
2063 | { | 2059 | { |
2064 | struct pid *pgrp, *rpgrp; | 2060 | struct pid *pgrp; |
2065 | unsigned long flags; | 2061 | unsigned long flags; |
2066 | 2062 | ||
2067 | /* For a PTY we need to lock the tty side */ | 2063 | /* Lock the tty */ |
2068 | mutex_lock(&real_tty->termios_mutex); | 2064 | mutex_lock(&tty->termios_mutex); |
2069 | if (!memcmp(ws, &real_tty->winsize, sizeof(*ws))) | 2065 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) |
2070 | goto done; | 2066 | goto done; |
2071 | /* Get the PID values and reference them so we can | 2067 | /* Get the PID values and reference them so we can |
2072 | avoid holding the tty ctrl lock while sending signals */ | 2068 | avoid holding the tty ctrl lock while sending signals */ |
2073 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 2069 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
2074 | pgrp = get_pid(tty->pgrp); | 2070 | pgrp = get_pid(tty->pgrp); |
2075 | rpgrp = get_pid(real_tty->pgrp); | ||
2076 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 2071 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
2077 | 2072 | ||
2078 | if (pgrp) | 2073 | if (pgrp) |
2079 | kill_pgrp(pgrp, SIGWINCH, 1); | 2074 | kill_pgrp(pgrp, SIGWINCH, 1); |
2080 | if (rpgrp != pgrp && rpgrp) | ||
2081 | kill_pgrp(rpgrp, SIGWINCH, 1); | ||
2082 | |||
2083 | put_pid(pgrp); | 2075 | put_pid(pgrp); |
2084 | put_pid(rpgrp); | ||
2085 | 2076 | ||
2086 | tty->winsize = *ws; | 2077 | tty->winsize = *ws; |
2087 | real_tty->winsize = *ws; | ||
2088 | done: | 2078 | done: |
2089 | mutex_unlock(&real_tty->termios_mutex); | 2079 | mutex_unlock(&tty->termios_mutex); |
2090 | return 0; | 2080 | return 0; |
2091 | } | 2081 | } |
2092 | 2082 | ||
2093 | /** | 2083 | /** |
2094 | * tiocswinsz - implement window size set ioctl | 2084 | * tiocswinsz - implement window size set ioctl |
2095 | * @tty; tty | 2085 | * @tty; tty side of tty |
2096 | * @arg: user buffer for result | 2086 | * @arg: user buffer for result |
2097 | * | 2087 | * |
2098 | * Copies the user idea of the window size to the kernel. Traditionally | 2088 | * Copies the user idea of the window size to the kernel. Traditionally |
@@ -2105,17 +2095,16 @@ done: | |||
2105 | * then calls into the default method. | 2095 | * then calls into the default method. |
2106 | */ | 2096 | */ |
2107 | 2097 | ||
2108 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2098 | static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) |
2109 | struct winsize __user *arg) | ||
2110 | { | 2099 | { |
2111 | struct winsize tmp_ws; | 2100 | struct winsize tmp_ws; |
2112 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | 2101 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) |
2113 | return -EFAULT; | 2102 | return -EFAULT; |
2114 | 2103 | ||
2115 | if (tty->ops->resize) | 2104 | if (tty->ops->resize) |
2116 | return tty->ops->resize(tty, real_tty, &tmp_ws); | 2105 | return tty->ops->resize(tty, &tmp_ws); |
2117 | else | 2106 | else |
2118 | return tty_do_resize(tty, real_tty, &tmp_ws); | 2107 | return tty_do_resize(tty, &tmp_ws); |
2119 | } | 2108 | } |
2120 | 2109 | ||
2121 | /** | 2110 | /** |
@@ -2540,7 +2529,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2540 | case TIOCGWINSZ: | 2529 | case TIOCGWINSZ: |
2541 | return tiocgwinsz(real_tty, p); | 2530 | return tiocgwinsz(real_tty, p); |
2542 | case TIOCSWINSZ: | 2531 | case TIOCSWINSZ: |
2543 | return tiocswinsz(tty, real_tty, p); | 2532 | return tiocswinsz(real_tty, p); |
2544 | case TIOCCONS: | 2533 | case TIOCCONS: |
2545 | return real_tty != tty ? -EINVAL : tioccons(file); | 2534 | return real_tty != tty ? -EINVAL : tioccons(file); |
2546 | case FIONBIO: | 2535 | case FIONBIO: |
@@ -2785,6 +2774,8 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2785 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 2774 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
2786 | mutex_init(&tty->atomic_read_lock); | 2775 | mutex_init(&tty->atomic_read_lock); |
2787 | mutex_init(&tty->atomic_write_lock); | 2776 | mutex_init(&tty->atomic_write_lock); |
2777 | mutex_init(&tty->output_lock); | ||
2778 | mutex_init(&tty->echo_lock); | ||
2788 | spin_lock_init(&tty->read_lock); | 2779 | spin_lock_init(&tty->read_lock); |
2789 | spin_lock_init(&tty->ctrl_lock); | 2780 | spin_lock_init(&tty->ctrl_lock); |
2790 | INIT_LIST_HEAD(&tty->tty_files); | 2781 | INIT_LIST_HEAD(&tty->tty_files); |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index f307f135cbfb..7a84b406a952 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -316,8 +316,7 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | |||
316 | { | 316 | { |
317 | /* wait_event is a macro */ | 317 | /* wait_event is a macro */ |
318 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | 318 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); |
319 | if (tty->ldisc.refcount == 0) | 319 | WARN_ON(tty->ldisc.refcount == 0); |
320 | printk(KERN_ERR "tty_ldisc_ref_wait\n"); | ||
321 | return &tty->ldisc; | 320 | return &tty->ldisc; |
322 | } | 321 | } |
323 | 322 | ||
@@ -376,15 +375,17 @@ EXPORT_SYMBOL_GPL(tty_ldisc_deref); | |||
376 | * @tty: terminal to activate ldisc on | 375 | * @tty: terminal to activate ldisc on |
377 | * | 376 | * |
378 | * Set the TTY_LDISC flag when the line discipline can be called | 377 | * Set the TTY_LDISC flag when the line discipline can be called |
379 | * again. Do necessary wakeups for existing sleepers. | 378 | * again. Do necessary wakeups for existing sleepers. Clear the LDISC |
379 | * changing flag to indicate any ldisc change is now over. | ||
380 | * | 380 | * |
381 | * Note: nobody should set this bit except via this function. Clearing | 381 | * Note: nobody should set the TTY_LDISC bit except via this function. |
382 | * directly is allowed. | 382 | * Clearing directly is allowed. |
383 | */ | 383 | */ |
384 | 384 | ||
385 | void tty_ldisc_enable(struct tty_struct *tty) | 385 | void tty_ldisc_enable(struct tty_struct *tty) |
386 | { | 386 | { |
387 | set_bit(TTY_LDISC, &tty->flags); | 387 | set_bit(TTY_LDISC, &tty->flags); |
388 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
388 | wake_up(&tty_ldisc_wait); | 389 | wake_up(&tty_ldisc_wait); |
389 | } | 390 | } |
390 | 391 | ||
@@ -496,7 +497,14 @@ restart: | |||
496 | * reference to the line discipline. The TTY_LDISC bit | 497 | * reference to the line discipline. The TTY_LDISC bit |
497 | * prevents anyone taking a reference once it is clear. | 498 | * prevents anyone taking a reference once it is clear. |
498 | * We need the lock to avoid racing reference takers. | 499 | * We need the lock to avoid racing reference takers. |
500 | * | ||
501 | * We must clear the TTY_LDISC bit here to avoid a livelock | ||
502 | * with a userspace app continually trying to use the tty in | ||
503 | * parallel to the change and re-referencing the tty. | ||
499 | */ | 504 | */ |
505 | clear_bit(TTY_LDISC, &tty->flags); | ||
506 | if (o_tty) | ||
507 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
500 | 508 | ||
501 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 509 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
502 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | 510 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { |
@@ -528,7 +536,7 @@ restart: | |||
528 | * If the TTY_LDISC bit is set, then we are racing against | 536 | * If the TTY_LDISC bit is set, then we are racing against |
529 | * another ldisc change | 537 | * another ldisc change |
530 | */ | 538 | */ |
531 | if (!test_bit(TTY_LDISC, &tty->flags)) { | 539 | if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
532 | struct tty_ldisc *ld; | 540 | struct tty_ldisc *ld; |
533 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 541 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
534 | tty_ldisc_put(new_ldisc.ops); | 542 | tty_ldisc_put(new_ldisc.ops); |
@@ -536,10 +544,14 @@ restart: | |||
536 | tty_ldisc_deref(ld); | 544 | tty_ldisc_deref(ld); |
537 | goto restart; | 545 | goto restart; |
538 | } | 546 | } |
539 | 547 | /* | |
540 | clear_bit(TTY_LDISC, &tty->flags); | 548 | * This flag is used to avoid two parallel ldisc changes. Once |
549 | * open and close are fine grained locked this may work better | ||
550 | * as a mutex shared with the open/close/hup paths | ||
551 | */ | ||
552 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
541 | if (o_tty) | 553 | if (o_tty) |
542 | clear_bit(TTY_LDISC, &o_tty->flags); | 554 | set_bit(TTY_LDISC_CHANGING, &o_tty->flags); |
543 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 555 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
544 | 556 | ||
545 | /* | 557 | /* |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index c8f8024cb40e..9b8004c72686 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/tty.h> | 7 | #include <linux/tty.h> |
8 | #include <linux/tty_driver.h> | 8 | #include <linux/tty_driver.h> |
9 | #include <linux/tty_flip.h> | 9 | #include <linux/tty_flip.h> |
10 | #include <linux/serial.h> | ||
10 | #include <linux/timer.h> | 11 | #include <linux/timer.h> |
11 | #include <linux/string.h> | 12 | #include <linux/string.h> |
12 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
@@ -94,3 +95,227 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) | |||
94 | spin_unlock_irqrestore(&port->lock, flags); | 95 | spin_unlock_irqrestore(&port->lock, flags); |
95 | } | 96 | } |
96 | EXPORT_SYMBOL(tty_port_tty_set); | 97 | EXPORT_SYMBOL(tty_port_tty_set); |
98 | |||
99 | /** | ||
100 | * tty_port_hangup - hangup helper | ||
101 | * @port: tty port | ||
102 | * | ||
103 | * Perform port level tty hangup flag and count changes. Drop the tty | ||
104 | * reference. | ||
105 | */ | ||
106 | |||
107 | void tty_port_hangup(struct tty_port *port) | ||
108 | { | ||
109 | unsigned long flags; | ||
110 | |||
111 | spin_lock_irqsave(&port->lock, flags); | ||
112 | port->count = 0; | ||
113 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
114 | if (port->tty) | ||
115 | tty_kref_put(port->tty); | ||
116 | port->tty = NULL; | ||
117 | spin_unlock_irqrestore(&port->lock, flags); | ||
118 | wake_up_interruptible(&port->open_wait); | ||
119 | } | ||
120 | EXPORT_SYMBOL(tty_port_hangup); | ||
121 | |||
122 | /** | ||
123 | * tty_port_carrier_raised - carrier raised check | ||
124 | * @port: tty port | ||
125 | * | ||
126 | * Wrapper for the carrier detect logic. For the moment this is used | ||
127 | * to hide some internal details. This will eventually become entirely | ||
128 | * internal to the tty port. | ||
129 | */ | ||
130 | |||
131 | int tty_port_carrier_raised(struct tty_port *port) | ||
132 | { | ||
133 | if (port->ops->carrier_raised == NULL) | ||
134 | return 1; | ||
135 | return port->ops->carrier_raised(port); | ||
136 | } | ||
137 | EXPORT_SYMBOL(tty_port_carrier_raised); | ||
138 | |||
139 | /** | ||
140 | * tty_port_raise_dtr_rts - Riase DTR/RTS | ||
141 | * @port: tty port | ||
142 | * | ||
143 | * Wrapper for the DTR/RTS raise logic. For the moment this is used | ||
144 | * to hide some internal details. This will eventually become entirely | ||
145 | * internal to the tty port. | ||
146 | */ | ||
147 | |||
148 | void tty_port_raise_dtr_rts(struct tty_port *port) | ||
149 | { | ||
150 | if (port->ops->raise_dtr_rts) | ||
151 | port->ops->raise_dtr_rts(port); | ||
152 | } | ||
153 | EXPORT_SYMBOL(tty_port_raise_dtr_rts); | ||
154 | |||
155 | /** | ||
156 | * tty_port_block_til_ready - Waiting logic for tty open | ||
157 | * @port: the tty port being opened | ||
158 | * @tty: the tty device being bound | ||
159 | * @filp: the file pointer of the opener | ||
160 | * | ||
161 | * Implement the core POSIX/SuS tty behaviour when opening a tty device. | ||
162 | * Handles: | ||
163 | * - hangup (both before and during) | ||
164 | * - non blocking open | ||
165 | * - rts/dtr/dcd | ||
166 | * - signals | ||
167 | * - port flags and counts | ||
168 | * | ||
169 | * The passed tty_port must implement the carrier_raised method if it can | ||
170 | * do carrier detect and the raise_dtr_rts method if it supports software | ||
171 | * management of these lines. Note that the dtr/rts raise is done each | ||
172 | * iteration as a hangup may have previously dropped them while we wait. | ||
173 | */ | ||
174 | |||
175 | int tty_port_block_til_ready(struct tty_port *port, | ||
176 | struct tty_struct *tty, struct file *filp) | ||
177 | { | ||
178 | int do_clocal = 0, retval; | ||
179 | unsigned long flags; | ||
180 | DECLARE_WAITQUEUE(wait, current); | ||
181 | int cd; | ||
182 | |||
183 | /* block if port is in the process of being closed */ | ||
184 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | ||
185 | interruptible_sleep_on(&port->close_wait); | ||
186 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
187 | return -EAGAIN; | ||
188 | else | ||
189 | return -ERESTARTSYS; | ||
190 | } | ||
191 | |||
192 | /* if non-blocking mode is set we can pass directly to open unless | ||
193 | the port has just hung up or is in another error state */ | ||
194 | if ((filp->f_flags & O_NONBLOCK) || | ||
195 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
196 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | if (C_CLOCAL(tty)) | ||
201 | do_clocal = 1; | ||
202 | |||
203 | /* Block waiting until we can proceed. We may need to wait for the | ||
204 | carrier, but we must also wait for any close that is in progress | ||
205 | before the next open may complete */ | ||
206 | |||
207 | retval = 0; | ||
208 | add_wait_queue(&port->open_wait, &wait); | ||
209 | |||
210 | /* The port lock protects the port counts */ | ||
211 | spin_lock_irqsave(&port->lock, flags); | ||
212 | if (!tty_hung_up_p(filp)) | ||
213 | port->count--; | ||
214 | port->blocked_open++; | ||
215 | spin_unlock_irqrestore(&port->lock, flags); | ||
216 | |||
217 | while (1) { | ||
218 | /* Indicate we are open */ | ||
219 | if (tty->termios->c_cflag & CBAUD) | ||
220 | tty_port_raise_dtr_rts(port); | ||
221 | |||
222 | set_current_state(TASK_INTERRUPTIBLE); | ||
223 | /* Check for a hangup or uninitialised port. Return accordingly */ | ||
224 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | ||
225 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
226 | retval = -EAGAIN; | ||
227 | else | ||
228 | retval = -ERESTARTSYS; | ||
229 | break; | ||
230 | } | ||
231 | /* Probe the carrier. For devices with no carrier detect this | ||
232 | will always return true */ | ||
233 | cd = tty_port_carrier_raised(port); | ||
234 | if (!(port->flags & ASYNC_CLOSING) && | ||
235 | (do_clocal || cd)) | ||
236 | break; | ||
237 | if (signal_pending(current)) { | ||
238 | retval = -ERESTARTSYS; | ||
239 | break; | ||
240 | } | ||
241 | schedule(); | ||
242 | } | ||
243 | set_current_state(TASK_RUNNING); | ||
244 | remove_wait_queue(&port->open_wait, &wait); | ||
245 | |||
246 | /* Update counts. A parallel hangup will have set count to zero and | ||
247 | we must not mess that up further */ | ||
248 | spin_lock_irqsave(&port->lock, flags); | ||
249 | if (!tty_hung_up_p(filp)) | ||
250 | port->count++; | ||
251 | port->blocked_open--; | ||
252 | if (retval == 0) | ||
253 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
254 | spin_unlock_irqrestore(&port->lock, flags); | ||
255 | return 0; | ||
256 | |||
257 | } | ||
258 | EXPORT_SYMBOL(tty_port_block_til_ready); | ||
259 | |||
260 | int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) | ||
261 | { | ||
262 | unsigned long flags; | ||
263 | |||
264 | spin_lock_irqsave(&port->lock, flags); | ||
265 | if (tty_hung_up_p(filp)) { | ||
266 | spin_unlock_irqrestore(&port->lock, flags); | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | if( tty->count == 1 && port->count != 1) { | ||
271 | printk(KERN_WARNING | ||
272 | "tty_port_close_start: tty->count = 1 port count = %d.\n", | ||
273 | port->count); | ||
274 | port->count = 1; | ||
275 | } | ||
276 | if (--port->count < 0) { | ||
277 | printk(KERN_WARNING "tty_port_close_start: count = %d\n", | ||
278 | port->count); | ||
279 | port->count = 0; | ||
280 | } | ||
281 | |||
282 | if (port->count) { | ||
283 | spin_unlock_irqrestore(&port->lock, flags); | ||
284 | return 0; | ||
285 | } | ||
286 | port->flags |= ASYNC_CLOSING; | ||
287 | tty->closing = 1; | ||
288 | spin_unlock_irqrestore(&port->lock, flags); | ||
289 | /* Don't block on a stalled port, just pull the chain */ | ||
290 | if (tty->flow_stopped) | ||
291 | tty_driver_flush_buffer(tty); | ||
292 | if (port->flags & ASYNC_INITIALIZED && | ||
293 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
294 | tty_wait_until_sent(tty, port->closing_wait); | ||
295 | return 1; | ||
296 | } | ||
297 | EXPORT_SYMBOL(tty_port_close_start); | ||
298 | |||
299 | void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) | ||
300 | { | ||
301 | unsigned long flags; | ||
302 | |||
303 | tty_ldisc_flush(tty); | ||
304 | |||
305 | spin_lock_irqsave(&port->lock, flags); | ||
306 | tty->closing = 0; | ||
307 | |||
308 | if (port->blocked_open) { | ||
309 | spin_unlock_irqrestore(&port->lock, flags); | ||
310 | if (port->close_delay) { | ||
311 | msleep_interruptible( | ||
312 | jiffies_to_msecs(port->close_delay)); | ||
313 | } | ||
314 | spin_lock_irqsave(&port->lock, flags); | ||
315 | wake_up_interruptible(&port->open_wait); | ||
316 | } | ||
317 | port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
318 | wake_up_interruptible(&port->close_wait); | ||
319 | spin_unlock_irqrestore(&port->lock, flags); | ||
320 | } | ||
321 | EXPORT_SYMBOL(tty_port_close_end); | ||
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 1718b3c481db..0e8234bd0e19 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c | |||
@@ -69,7 +69,7 @@ static void scc_disable_tx_interrupts(void * ptr); | |||
69 | static void scc_enable_tx_interrupts(void * ptr); | 69 | static void scc_enable_tx_interrupts(void * ptr); |
70 | static void scc_disable_rx_interrupts(void * ptr); | 70 | static void scc_disable_rx_interrupts(void * ptr); |
71 | static void scc_enable_rx_interrupts(void * ptr); | 71 | static void scc_enable_rx_interrupts(void * ptr); |
72 | static int scc_get_CD(void * ptr); | 72 | static int scc_carrier_raised(struct tty_port *port); |
73 | static void scc_shutdown_port(void * ptr); | 73 | static void scc_shutdown_port(void * ptr); |
74 | static int scc_set_real_termios(void *ptr); | 74 | static int scc_set_real_termios(void *ptr); |
75 | static void scc_hungup(void *ptr); | 75 | static void scc_hungup(void *ptr); |
@@ -100,7 +100,6 @@ static struct real_driver scc_real_driver = { | |||
100 | scc_enable_tx_interrupts, | 100 | scc_enable_tx_interrupts, |
101 | scc_disable_rx_interrupts, | 101 | scc_disable_rx_interrupts, |
102 | scc_enable_rx_interrupts, | 102 | scc_enable_rx_interrupts, |
103 | scc_get_CD, | ||
104 | scc_shutdown_port, | 103 | scc_shutdown_port, |
105 | scc_set_real_termios, | 104 | scc_set_real_termios, |
106 | scc_chars_in_buffer, | 105 | scc_chars_in_buffer, |
@@ -129,6 +128,10 @@ static const struct tty_operations scc_ops = { | |||
129 | .break_ctl = scc_break_ctl, | 128 | .break_ctl = scc_break_ctl, |
130 | }; | 129 | }; |
131 | 130 | ||
131 | static const struct tty_port_operations scc_port_ops = { | ||
132 | .carrier_raised = scc_carrier_raised, | ||
133 | }; | ||
134 | |||
132 | /*---------------------------------------------------------------------------- | 135 | /*---------------------------------------------------------------------------- |
133 | * vme_scc_init() and support functions | 136 | * vme_scc_init() and support functions |
134 | *---------------------------------------------------------------------------*/ | 137 | *---------------------------------------------------------------------------*/ |
@@ -176,6 +179,8 @@ static void scc_init_portstructs(void) | |||
176 | 179 | ||
177 | for (i = 0; i < 2; i++) { | 180 | for (i = 0; i < 2; i++) { |
178 | port = scc_ports + i; | 181 | port = scc_ports + i; |
182 | tty_port_init(&port->gs.port); | ||
183 | port->gs.port.ops = &scc_port_ops; | ||
179 | port->gs.magic = SCC_MAGIC; | 184 | port->gs.magic = SCC_MAGIC; |
180 | port->gs.close_delay = HZ/2; | 185 | port->gs.close_delay = HZ/2; |
181 | port->gs.closing_wait = 30 * HZ; | 186 | port->gs.closing_wait = 30 * HZ; |
@@ -624,10 +629,10 @@ static void scc_enable_rx_interrupts(void *ptr) | |||
624 | } | 629 | } |
625 | 630 | ||
626 | 631 | ||
627 | static int scc_get_CD(void *ptr) | 632 | static int scc_carrier_raised(struct tty_port *port) |
628 | { | 633 | { |
629 | struct scc_port *port = ptr; | 634 | struct scc_port *sc = container_of(port, struct scc_port, gs.port); |
630 | unsigned channel = port->channel; | 635 | unsigned channel = sc->channel; |
631 | 636 | ||
632 | return !!(scc_last_status_reg[channel] & SR_DCD); | 637 | return !!(scc_last_status_reg[channel] & SR_DCD); |
633 | } | 638 | } |
@@ -638,7 +643,7 @@ static void scc_shutdown_port(void *ptr) | |||
638 | struct scc_port *port = ptr; | 643 | struct scc_port *port = ptr; |
639 | 644 | ||
640 | port->gs.port.flags &= ~ GS_ACTIVE; | 645 | port->gs.port.flags &= ~ GS_ACTIVE; |
641 | if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { | 646 | if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) { |
642 | scc_setsignals (port, 0, 0); | 647 | scc_setsignals (port, 0, 0); |
643 | } | 648 | } |
644 | } | 649 | } |
@@ -779,7 +784,7 @@ static void scc_setsignals(struct scc_port *port, int dtr, int rts) | |||
779 | 784 | ||
780 | static void scc_send_xchar(struct tty_struct *tty, char ch) | 785 | static void scc_send_xchar(struct tty_struct *tty, char ch) |
781 | { | 786 | { |
782 | struct scc_port *port = (struct scc_port *)tty->driver_data; | 787 | struct scc_port *port = tty->driver_data; |
783 | 788 | ||
784 | port->x_char = ch; | 789 | port->x_char = ch; |
785 | if (ch) | 790 | if (ch) |
@@ -896,7 +901,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) | |||
896 | return retval; | 901 | return retval; |
897 | } | 902 | } |
898 | 903 | ||
899 | port->c_dcd = scc_get_CD (port); | 904 | port->c_dcd = tty_port_carrier_raised(&port->gs.port); |
900 | 905 | ||
901 | scc_enable_rx_interrupts(port); | 906 | scc_enable_rx_interrupts(port); |
902 | 907 | ||
@@ -906,7 +911,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) | |||
906 | 911 | ||
907 | static void scc_throttle (struct tty_struct * tty) | 912 | static void scc_throttle (struct tty_struct * tty) |
908 | { | 913 | { |
909 | struct scc_port *port = (struct scc_port *)tty->driver_data; | 914 | struct scc_port *port = tty->driver_data; |
910 | unsigned long flags; | 915 | unsigned long flags; |
911 | SCC_ACCESS_INIT(port); | 916 | SCC_ACCESS_INIT(port); |
912 | 917 | ||
@@ -922,7 +927,7 @@ static void scc_throttle (struct tty_struct * tty) | |||
922 | 927 | ||
923 | static void scc_unthrottle (struct tty_struct * tty) | 928 | static void scc_unthrottle (struct tty_struct * tty) |
924 | { | 929 | { |
925 | struct scc_port *port = (struct scc_port *)tty->driver_data; | 930 | struct scc_port *port = tty->driver_data; |
926 | unsigned long flags; | 931 | unsigned long flags; |
927 | SCC_ACCESS_INIT(port); | 932 | SCC_ACCESS_INIT(port); |
928 | 933 | ||
@@ -945,7 +950,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file, | |||
945 | 950 | ||
946 | static int scc_break_ctl(struct tty_struct *tty, int break_state) | 951 | static int scc_break_ctl(struct tty_struct *tty, int break_state) |
947 | { | 952 | { |
948 | struct scc_port *port = (struct scc_port *)tty->driver_data; | 953 | struct scc_port *port = tty->driver_data; |
949 | unsigned long flags; | 954 | unsigned long flags; |
950 | SCC_ACCESS_INIT(port); | 955 | SCC_ACCESS_INIT(port); |
951 | 956 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 008176edbd64..80014213fb53 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -819,8 +819,8 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, | |||
819 | * ctrl_lock of the tty IFF a tty is passed. | 819 | * ctrl_lock of the tty IFF a tty is passed. |
820 | */ | 820 | */ |
821 | 821 | ||
822 | static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 822 | static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, |
823 | struct vc_data *vc, unsigned int cols, unsigned int lines) | 823 | unsigned int cols, unsigned int lines) |
824 | { | 824 | { |
825 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 825 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
826 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 826 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; |
@@ -932,7 +932,7 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | |||
932 | ws.ws_row = vc->vc_rows; | 932 | ws.ws_row = vc->vc_rows; |
933 | ws.ws_col = vc->vc_cols; | 933 | ws.ws_col = vc->vc_cols; |
934 | ws.ws_ypixel = vc->vc_scan_lines; | 934 | ws.ws_ypixel = vc->vc_scan_lines; |
935 | tty_do_resize(tty, real_tty, &ws); | 935 | tty_do_resize(tty, &ws); |
936 | } | 936 | } |
937 | 937 | ||
938 | if (CON_IS_VISIBLE(vc)) | 938 | if (CON_IS_VISIBLE(vc)) |
@@ -954,13 +954,12 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | |||
954 | 954 | ||
955 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | 955 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) |
956 | { | 956 | { |
957 | return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows); | 957 | return vc_do_resize(vc->vc_tty, vc, cols, rows); |
958 | } | 958 | } |
959 | 959 | ||
960 | /** | 960 | /** |
961 | * vt_resize - resize a VT | 961 | * vt_resize - resize a VT |
962 | * @tty: tty to resize | 962 | * @tty: tty to resize |
963 | * @real_tty: tty if a pty/tty pair | ||
964 | * @ws: winsize attributes | 963 | * @ws: winsize attributes |
965 | * | 964 | * |
966 | * Resize a virtual terminal. This is called by the tty layer as we | 965 | * Resize a virtual terminal. This is called by the tty layer as we |
@@ -971,14 +970,13 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | |||
971 | * termios_mutex and the tty ctrl_lock in that order. | 970 | * termios_mutex and the tty ctrl_lock in that order. |
972 | */ | 971 | */ |
973 | 972 | ||
974 | int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 973 | int vt_resize(struct tty_struct *tty, struct winsize *ws) |
975 | struct winsize *ws) | ||
976 | { | 974 | { |
977 | struct vc_data *vc = tty->driver_data; | 975 | struct vc_data *vc = tty->driver_data; |
978 | int ret; | 976 | int ret; |
979 | 977 | ||
980 | acquire_console_sem(); | 978 | acquire_console_sem(); |
981 | ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row); | 979 | ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row); |
982 | release_console_sem(); | 980 | release_console_sem(); |
983 | return ret; | 981 | return ret; |
984 | } | 982 | } |
@@ -2679,7 +2677,7 @@ static int con_write_room(struct tty_struct *tty) | |||
2679 | { | 2677 | { |
2680 | if (tty->stopped) | 2678 | if (tty->stopped) |
2681 | return 0; | 2679 | return 0; |
2682 | return 4096; /* No limit, really; we're not buffering */ | 2680 | return 32768; /* No limit, really; we're not buffering */ |
2683 | } | 2681 | } |
2684 | 2682 | ||
2685 | static int con_chars_in_buffer(struct tty_struct *tty) | 2683 | static int con_chars_in_buffer(struct tty_struct *tty) |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 8944ce508e2f..a2dee0eb6dad 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -366,7 +366,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_ | |||
366 | int vt_ioctl(struct tty_struct *tty, struct file * file, | 366 | int vt_ioctl(struct tty_struct *tty, struct file * file, |
367 | unsigned int cmd, unsigned long arg) | 367 | unsigned int cmd, unsigned long arg) |
368 | { | 368 | { |
369 | struct vc_data *vc = (struct vc_data *)tty->driver_data; | 369 | struct vc_data *vc = tty->driver_data; |
370 | struct console_font_op op; /* used in multiple places here */ | 370 | struct console_font_op op; /* used in multiple places here */ |
371 | struct kbd_struct * kbd; | 371 | struct kbd_struct * kbd; |
372 | unsigned int console; | 372 | unsigned int console; |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index c9f21e3d4ead..4ee85fcf9aaf 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -137,6 +137,7 @@ config BLK_DEV_DELKIN | |||
137 | 137 | ||
138 | config BLK_DEV_IDECD | 138 | config BLK_DEV_IDECD |
139 | tristate "Include IDE/ATAPI CDROM support" | 139 | tristate "Include IDE/ATAPI CDROM support" |
140 | select IDE_ATAPI | ||
140 | ---help--- | 141 | ---help--- |
141 | If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is | 142 | If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is |
142 | a newer protocol used by IDE CD-ROM and TAPE drives, similar to the | 143 | a newer protocol used by IDE CD-ROM and TAPE drives, similar to the |
@@ -185,23 +186,6 @@ config BLK_DEV_IDETAPE | |||
185 | To compile this driver as a module, choose M here: the | 186 | To compile this driver as a module, choose M here: the |
186 | module will be called ide-tape. | 187 | module will be called ide-tape. |
187 | 188 | ||
188 | config BLK_DEV_IDESCSI | ||
189 | tristate "SCSI emulation support (DEPRECATED)" | ||
190 | depends on SCSI | ||
191 | select IDE_ATAPI | ||
192 | ---help--- | ||
193 | WARNING: ide-scsi is no longer needed for cd writing applications! | ||
194 | The 2.6 kernel supports direct writing to ide-cd, which eliminates | ||
195 | the need for ide-scsi + the entire scsi stack just for writing a | ||
196 | cd. The new method is more efficient in every way. | ||
197 | |||
198 | This will provide SCSI host adapter emulation for IDE ATAPI devices, | ||
199 | and will allow you to use a SCSI device driver instead of a native | ||
200 | ATAPI driver. | ||
201 | |||
202 | If both this SCSI emulation and native ATAPI support are compiled | ||
203 | into the kernel, the native support will be used. | ||
204 | |||
205 | config BLK_DEV_IDEACPI | 189 | config BLK_DEV_IDEACPI |
206 | bool "IDE ACPI support" | 190 | bool "IDE ACPI support" |
207 | depends on ACPI | 191 | depends on ACPI |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 177e3f8523ed..410728992e6a 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | EXTRA_CFLAGS += -Idrivers/ide | 5 | EXTRA_CFLAGS += -Idrivers/ide |
6 | 6 | ||
7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ | 7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ |
8 | ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o | 8 | ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o |
9 | 9 | ||
10 | # core IDE code | 10 | # core IDE code |
11 | ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o | 11 | ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o |
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 4e58b9e7a58a..e8688c0f8645 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/cdrom.h> | ||
6 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
7 | #include <linux/ide.h> | 8 | #include <linux/ide.h> |
8 | #include <scsi/scsi.h> | 9 | #include <scsi/scsi.h> |
@@ -14,6 +15,13 @@ | |||
14 | #define debug_log(fmt, args...) do {} while (0) | 15 | #define debug_log(fmt, args...) do {} while (0) |
15 | #endif | 16 | #endif |
16 | 17 | ||
18 | #define ATAPI_MIN_CDB_BYTES 12 | ||
19 | |||
20 | static inline int dev_is_idecd(ide_drive_t *drive) | ||
21 | { | ||
22 | return drive->media == ide_cdrom || drive->media == ide_optical; | ||
23 | } | ||
24 | |||
17 | /* | 25 | /* |
18 | * Check whether we can support a device, | 26 | * Check whether we can support a device, |
19 | * based on the ATAPI IDENTIFY command results. | 27 | * based on the ATAPI IDENTIFY command results. |
@@ -233,18 +241,49 @@ void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) | |||
233 | } | 241 | } |
234 | EXPORT_SYMBOL_GPL(ide_retry_pc); | 242 | EXPORT_SYMBOL_GPL(ide_retry_pc); |
235 | 243 | ||
236 | int ide_scsi_expiry(ide_drive_t *drive) | 244 | int ide_cd_expiry(ide_drive_t *drive) |
237 | { | 245 | { |
238 | struct ide_atapi_pc *pc = drive->pc; | 246 | struct request *rq = HWGROUP(drive)->rq; |
247 | unsigned long wait = 0; | ||
239 | 248 | ||
240 | debug_log("%s called for %lu at %lu\n", __func__, | 249 | debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]); |
241 | pc->scsi_cmd->serial_number, jiffies); | ||
242 | 250 | ||
243 | pc->flags |= PC_FLAG_TIMEDOUT; | 251 | /* |
252 | * Some commands are *slow* and normally take a long time to complete. | ||
253 | * Usually we can use the ATAPI "disconnect" to bypass this, but not all | ||
254 | * commands/drives support that. Let ide_timer_expiry keep polling us | ||
255 | * for these. | ||
256 | */ | ||
257 | switch (rq->cmd[0]) { | ||
258 | case GPCMD_BLANK: | ||
259 | case GPCMD_FORMAT_UNIT: | ||
260 | case GPCMD_RESERVE_RZONE_TRACK: | ||
261 | case GPCMD_CLOSE_TRACK: | ||
262 | case GPCMD_FLUSH_CACHE: | ||
263 | wait = ATAPI_WAIT_PC; | ||
264 | break; | ||
265 | default: | ||
266 | if (!(rq->cmd_flags & REQ_QUIET)) | ||
267 | printk(KERN_INFO "cmd 0x%x timed out\n", | ||
268 | rq->cmd[0]); | ||
269 | wait = 0; | ||
270 | break; | ||
271 | } | ||
272 | return wait; | ||
273 | } | ||
274 | EXPORT_SYMBOL_GPL(ide_cd_expiry); | ||
244 | 275 | ||
245 | return 0; /* we do not want the IDE subsystem to retry */ | 276 | int ide_cd_get_xferlen(struct request *rq) |
277 | { | ||
278 | if (blk_fs_request(rq)) | ||
279 | return 32768; | ||
280 | else if (blk_sense_request(rq) || blk_pc_request(rq) || | ||
281 | rq->cmd_type == REQ_TYPE_ATA_PC) | ||
282 | return rq->data_len; | ||
283 | else | ||
284 | return 0; | ||
246 | } | 285 | } |
247 | EXPORT_SYMBOL_GPL(ide_scsi_expiry); | 286 | EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); |
248 | 287 | ||
249 | /* | 288 | /* |
250 | * This is the usual interrupt handler which will be called during a packet | 289 | * This is the usual interrupt handler which will be called during a packet |
@@ -258,21 +297,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
258 | struct request *rq = hwif->hwgroup->rq; | 297 | struct request *rq = hwif->hwgroup->rq; |
259 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 298 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
260 | xfer_func_t *xferfunc; | 299 | xfer_func_t *xferfunc; |
261 | ide_expiry_t *expiry; | ||
262 | unsigned int timeout, temp; | 300 | unsigned int timeout, temp; |
263 | u16 bcount; | 301 | u16 bcount; |
264 | u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0; | 302 | u8 stat, ireason, dsc = 0; |
265 | 303 | ||
266 | debug_log("Enter %s - interrupt handler\n", __func__); | 304 | debug_log("Enter %s - interrupt handler\n", __func__); |
267 | 305 | ||
268 | if (scsi) { | 306 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD |
269 | timeout = ide_scsi_get_timeout(pc); | 307 | : WAIT_TAPE_CMD; |
270 | expiry = ide_scsi_expiry; | ||
271 | } else { | ||
272 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | ||
273 | : WAIT_TAPE_CMD; | ||
274 | expiry = NULL; | ||
275 | } | ||
276 | 308 | ||
277 | if (pc->flags & PC_FLAG_TIMEDOUT) { | 309 | if (pc->flags & PC_FLAG_TIMEDOUT) { |
278 | drive->pc_callback(drive, 0); | 310 | drive->pc_callback(drive, 0); |
@@ -284,8 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
284 | 316 | ||
285 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | 317 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
286 | if (hwif->dma_ops->dma_end(drive) || | 318 | if (hwif->dma_ops->dma_end(drive) || |
287 | (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) { | 319 | (drive->media == ide_tape && (stat & ATA_ERR))) { |
288 | if (drive->media == ide_floppy && !scsi) | 320 | if (drive->media == ide_floppy) |
289 | printk(KERN_ERR "%s: DMA %s error\n", | 321 | printk(KERN_ERR "%s: DMA %s error\n", |
290 | drive->name, rq_data_dir(pc->rq) | 322 | drive->name, rq_data_dir(pc->rq) |
291 | ? "write" : "read"); | 323 | ? "write" : "read"); |
@@ -307,7 +339,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
307 | 339 | ||
308 | local_irq_enable_in_hardirq(); | 340 | local_irq_enable_in_hardirq(); |
309 | 341 | ||
310 | if (drive->media == ide_tape && !scsi && | 342 | if (drive->media == ide_tape && |
311 | (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) | 343 | (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) |
312 | stat &= ~ATA_ERR; | 344 | stat &= ~ATA_ERR; |
313 | 345 | ||
@@ -315,11 +347,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
315 | /* Error detected */ | 347 | /* Error detected */ |
316 | debug_log("%s: I/O error\n", drive->name); | 348 | debug_log("%s: I/O error\n", drive->name); |
317 | 349 | ||
318 | if (drive->media != ide_tape || scsi) { | 350 | if (drive->media != ide_tape) |
319 | pc->rq->errors++; | 351 | pc->rq->errors++; |
320 | if (scsi) | ||
321 | goto cmd_finished; | ||
322 | } | ||
323 | 352 | ||
324 | if (rq->cmd[0] == REQUEST_SENSE) { | 353 | if (rq->cmd[0] == REQUEST_SENSE) { |
325 | printk(KERN_ERR "%s: I/O error in request sense" | 354 | printk(KERN_ERR "%s: I/O error in request sense" |
@@ -335,7 +364,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
335 | /* queued, but not started */ | 364 | /* queued, but not started */ |
336 | return ide_stopped; | 365 | return ide_stopped; |
337 | } | 366 | } |
338 | cmd_finished: | ||
339 | pc->error = 0; | 367 | pc->error = 0; |
340 | 368 | ||
341 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) | 369 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) |
@@ -382,25 +410,8 @@ cmd_finished: | |||
382 | "us more data than expected - " | 410 | "us more data than expected - " |
383 | "discarding data\n", | 411 | "discarding data\n", |
384 | drive->name); | 412 | drive->name); |
385 | if (scsi) | 413 | |
386 | temp = pc->buf_size - pc->xferred; | 414 | ide_pad_transfer(drive, 0, bcount); |
387 | else | ||
388 | temp = 0; | ||
389 | if (temp) { | ||
390 | if (pc->sg) | ||
391 | drive->pc_io_buffers(drive, pc, | ||
392 | temp, 0); | ||
393 | else | ||
394 | tp_ops->input_data(drive, NULL, | ||
395 | pc->cur_pos, temp); | ||
396 | printk(KERN_ERR "%s: transferred %d of " | ||
397 | "%d bytes\n", | ||
398 | drive->name, | ||
399 | temp, bcount); | ||
400 | } | ||
401 | pc->xferred += temp; | ||
402 | pc->cur_pos += temp; | ||
403 | ide_pad_transfer(drive, 0, bcount - temp); | ||
404 | goto next_irq; | 415 | goto next_irq; |
405 | } | 416 | } |
406 | debug_log("The device wants to send us more data than " | 417 | debug_log("The device wants to send us more data than " |
@@ -410,14 +421,13 @@ cmd_finished: | |||
410 | } else | 421 | } else |
411 | xferfunc = tp_ops->output_data; | 422 | xferfunc = tp_ops->output_data; |
412 | 423 | ||
413 | if ((drive->media == ide_floppy && !scsi && !pc->buf) || | 424 | if ((drive->media == ide_floppy && !pc->buf) || |
414 | (drive->media == ide_tape && !scsi && pc->bh) || | 425 | (drive->media == ide_tape && pc->bh)) { |
415 | (scsi && pc->sg)) { | ||
416 | int done = drive->pc_io_buffers(drive, pc, bcount, | 426 | int done = drive->pc_io_buffers(drive, pc, bcount, |
417 | !!(pc->flags & PC_FLAG_WRITING)); | 427 | !!(pc->flags & PC_FLAG_WRITING)); |
418 | 428 | ||
419 | /* FIXME: don't do partial completions */ | 429 | /* FIXME: don't do partial completions */ |
420 | if (drive->media == ide_floppy && !scsi) | 430 | if (drive->media == ide_floppy) |
421 | ide_end_request(drive, 1, done >> 9); | 431 | ide_end_request(drive, 1, done >> 9); |
422 | } else | 432 | } else |
423 | xferfunc(drive, NULL, pc->cur_pos, bcount); | 433 | xferfunc(drive, NULL, pc->cur_pos, bcount); |
@@ -430,7 +440,7 @@ cmd_finished: | |||
430 | rq->cmd[0], bcount); | 440 | rq->cmd[0], bcount); |
431 | next_irq: | 441 | next_irq: |
432 | /* And set the interrupt handler again */ | 442 | /* And set the interrupt handler again */ |
433 | ide_set_handler(drive, ide_pc_intr, timeout, expiry); | 443 | ide_set_handler(drive, ide_pc_intr, timeout, NULL); |
434 | return ide_started; | 444 | return ide_started; |
435 | } | 445 | } |
436 | 446 | ||
@@ -479,11 +489,12 @@ static int ide_delayed_transfer_pc(ide_drive_t *drive) | |||
479 | 489 | ||
480 | static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | 490 | static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) |
481 | { | 491 | { |
482 | struct ide_atapi_pc *pc = drive->pc; | 492 | struct ide_atapi_pc *uninitialized_var(pc); |
483 | ide_hwif_t *hwif = drive->hwif; | 493 | ide_hwif_t *hwif = drive->hwif; |
484 | struct request *rq = hwif->hwgroup->rq; | 494 | struct request *rq = hwif->hwgroup->rq; |
485 | ide_expiry_t *expiry; | 495 | ide_expiry_t *expiry; |
486 | unsigned int timeout; | 496 | unsigned int timeout; |
497 | int cmd_len; | ||
487 | ide_startstop_t startstop; | 498 | ide_startstop_t startstop; |
488 | u8 ireason; | 499 | u8 ireason; |
489 | 500 | ||
@@ -493,101 +504,124 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | |||
493 | return startstop; | 504 | return startstop; |
494 | } | 505 | } |
495 | 506 | ||
496 | ireason = ide_read_ireason(drive); | 507 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { |
497 | if (drive->media == ide_tape && | 508 | if (drive->dma) |
498 | (drive->dev_flags & IDE_DFLAG_SCSI) == 0) | 509 | drive->waiting_for_dma = 1; |
499 | ireason = ide_wait_ireason(drive, ireason); | ||
500 | |||
501 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { | ||
502 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " | ||
503 | "a packet command\n", drive->name); | ||
504 | return ide_do_reset(drive); | ||
505 | } | 510 | } |
506 | 511 | ||
507 | /* | 512 | if (dev_is_idecd(drive)) { |
508 | * If necessary schedule the packet transfer to occur 'timeout' | 513 | /* ATAPI commands get padded out to 12 bytes minimum */ |
509 | * miliseconds later in ide_delayed_transfer_pc() after the device | 514 | cmd_len = COMMAND_SIZE(rq->cmd[0]); |
510 | * says it's ready for a packet. | 515 | if (cmd_len < ATAPI_MIN_CDB_BYTES) |
511 | */ | 516 | cmd_len = ATAPI_MIN_CDB_BYTES; |
512 | if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) { | 517 | |
513 | timeout = drive->pc_delay; | 518 | timeout = rq->timeout; |
514 | expiry = &ide_delayed_transfer_pc; | 519 | expiry = ide_cd_expiry; |
515 | } else { | 520 | } else { |
516 | if (drive->dev_flags & IDE_DFLAG_SCSI) { | 521 | pc = drive->pc; |
517 | timeout = ide_scsi_get_timeout(pc); | 522 | |
518 | expiry = ide_scsi_expiry; | 523 | cmd_len = ATAPI_MIN_CDB_BYTES; |
524 | |||
525 | /* | ||
526 | * If necessary schedule the packet transfer to occur 'timeout' | ||
527 | * miliseconds later in ide_delayed_transfer_pc() after the | ||
528 | * device says it's ready for a packet. | ||
529 | */ | ||
530 | if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) { | ||
531 | timeout = drive->pc_delay; | ||
532 | expiry = &ide_delayed_transfer_pc; | ||
519 | } else { | 533 | } else { |
520 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | 534 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD |
521 | : WAIT_TAPE_CMD; | 535 | : WAIT_TAPE_CMD; |
522 | expiry = NULL; | 536 | expiry = NULL; |
523 | } | 537 | } |
538 | |||
539 | ireason = ide_read_ireason(drive); | ||
540 | if (drive->media == ide_tape) | ||
541 | ireason = ide_wait_ireason(drive, ireason); | ||
542 | |||
543 | if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) { | ||
544 | printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing " | ||
545 | "a packet command\n", drive->name); | ||
546 | |||
547 | return ide_do_reset(drive); | ||
548 | } | ||
524 | } | 549 | } |
525 | 550 | ||
526 | /* Set the interrupt routine */ | 551 | /* Set the interrupt routine */ |
527 | ide_set_handler(drive, ide_pc_intr, timeout, expiry); | 552 | ide_set_handler(drive, ide_pc_intr, timeout, expiry); |
528 | 553 | ||
529 | /* Begin DMA, if necessary */ | 554 | /* Begin DMA, if necessary */ |
530 | if (pc->flags & PC_FLAG_DMA_OK) { | 555 | if (dev_is_idecd(drive)) { |
531 | pc->flags |= PC_FLAG_DMA_IN_PROGRESS; | 556 | if (drive->dma) |
532 | hwif->dma_ops->dma_start(drive); | 557 | hwif->dma_ops->dma_start(drive); |
558 | } else { | ||
559 | if (pc->flags & PC_FLAG_DMA_OK) { | ||
560 | pc->flags |= PC_FLAG_DMA_IN_PROGRESS; | ||
561 | hwif->dma_ops->dma_start(drive); | ||
562 | } | ||
533 | } | 563 | } |
534 | 564 | ||
535 | /* Send the actual packet */ | 565 | /* Send the actual packet */ |
536 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) | 566 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) |
537 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12); | 567 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); |
538 | 568 | ||
539 | return ide_started; | 569 | return ide_started; |
540 | } | 570 | } |
541 | 571 | ||
542 | ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout, | 572 | ide_startstop_t ide_issue_pc(ide_drive_t *drive) |
543 | ide_expiry_t *expiry) | ||
544 | { | 573 | { |
545 | struct ide_atapi_pc *pc = drive->pc; | 574 | struct ide_atapi_pc *pc; |
546 | ide_hwif_t *hwif = drive->hwif; | 575 | ide_hwif_t *hwif = drive->hwif; |
576 | ide_expiry_t *expiry = NULL; | ||
577 | unsigned int timeout; | ||
547 | u32 tf_flags; | 578 | u32 tf_flags; |
548 | u16 bcount; | 579 | u16 bcount; |
549 | u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI); | ||
550 | 580 | ||
551 | /* We haven't transferred any data yet */ | 581 | if (dev_is_idecd(drive)) { |
552 | pc->xferred = 0; | 582 | tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; |
553 | pc->cur_pos = pc->buf; | 583 | bcount = ide_cd_get_xferlen(hwif->hwgroup->rq); |
584 | expiry = ide_cd_expiry; | ||
585 | timeout = ATAPI_WAIT_PC; | ||
554 | 586 | ||
555 | /* Request to transfer the entire buffer at once */ | 587 | if (drive->dma) |
556 | if (drive->media == ide_tape && scsi == 0) | 588 | drive->dma = !hwif->dma_ops->dma_setup(drive); |
557 | bcount = pc->req_xfer; | 589 | } else { |
558 | else | 590 | pc = drive->pc; |
559 | bcount = min(pc->req_xfer, 63 * 1024); | ||
560 | 591 | ||
561 | if (pc->flags & PC_FLAG_DMA_ERROR) { | 592 | /* We haven't transferred any data yet */ |
562 | pc->flags &= ~PC_FLAG_DMA_ERROR; | 593 | pc->xferred = 0; |
563 | ide_dma_off(drive); | 594 | pc->cur_pos = pc->buf; |
564 | } | ||
565 | 595 | ||
566 | if ((pc->flags & PC_FLAG_DMA_OK) && | 596 | tf_flags = IDE_TFLAG_OUT_DEVICE; |
567 | (drive->dev_flags & IDE_DFLAG_USING_DMA)) { | 597 | bcount = ((drive->media == ide_tape) ? |
568 | if (scsi) | 598 | pc->req_xfer : |
569 | hwif->sg_mapped = 1; | 599 | min(pc->req_xfer, 63 * 1024)); |
570 | drive->dma = !hwif->dma_ops->dma_setup(drive); | ||
571 | if (scsi) | ||
572 | hwif->sg_mapped = 0; | ||
573 | } | ||
574 | 600 | ||
575 | if (!drive->dma) | 601 | if (pc->flags & PC_FLAG_DMA_ERROR) { |
576 | pc->flags &= ~PC_FLAG_DMA_OK; | 602 | pc->flags &= ~PC_FLAG_DMA_ERROR; |
603 | ide_dma_off(drive); | ||
604 | } | ||
577 | 605 | ||
578 | if (scsi) | 606 | if ((pc->flags & PC_FLAG_DMA_OK) && |
579 | tf_flags = 0; | 607 | (drive->dev_flags & IDE_DFLAG_USING_DMA)) |
580 | else if (drive->media == ide_cdrom || drive->media == ide_optical) | 608 | drive->dma = !hwif->dma_ops->dma_setup(drive); |
581 | tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; | 609 | |
582 | else | 610 | if (!drive->dma) |
583 | tf_flags = IDE_TFLAG_OUT_DEVICE; | 611 | pc->flags &= ~PC_FLAG_DMA_OK; |
612 | |||
613 | timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD | ||
614 | : WAIT_TAPE_CMD; | ||
615 | } | ||
584 | 616 | ||
585 | ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); | 617 | ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); |
586 | 618 | ||
587 | /* Issue the packet command */ | 619 | /* Issue the packet command */ |
588 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { | 620 | if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { |
621 | if (drive->dma) | ||
622 | drive->waiting_for_dma = 0; | ||
589 | ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, | 623 | ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, |
590 | timeout, NULL); | 624 | timeout, expiry); |
591 | return ide_started; | 625 | return ide_started; |
592 | } else { | 626 | } else { |
593 | ide_execute_pkt_cmd(drive); | 627 | ide_execute_pkt_cmd(drive); |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 5daa4dd1b018..1a7410f88249 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -53,14 +53,6 @@ | |||
53 | 53 | ||
54 | #include "ide-cd.h" | 54 | #include "ide-cd.h" |
55 | 55 | ||
56 | #define IDECD_DEBUG_LOG 1 | ||
57 | |||
58 | #if IDECD_DEBUG_LOG | ||
59 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) | ||
60 | #else | ||
61 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
62 | #endif | ||
63 | |||
64 | static DEFINE_MUTEX(idecd_ref_mutex); | 56 | static DEFINE_MUTEX(idecd_ref_mutex); |
65 | 57 | ||
66 | static void ide_cd_release(struct kref *); | 58 | static void ide_cd_release(struct kref *); |
@@ -519,37 +511,8 @@ end_request: | |||
519 | return 1; | 511 | return 1; |
520 | } | 512 | } |
521 | 513 | ||
522 | static int cdrom_timer_expiry(ide_drive_t *drive) | 514 | static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *); |
523 | { | 515 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); |
524 | struct request *rq = HWGROUP(drive)->rq; | ||
525 | unsigned long wait = 0; | ||
526 | |||
527 | ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__, | ||
528 | rq->cmd[0]); | ||
529 | |||
530 | /* | ||
531 | * Some commands are *slow* and normally take a long time to complete. | ||
532 | * Usually we can use the ATAPI "disconnect" to bypass this, but not all | ||
533 | * commands/drives support that. Let ide_timer_expiry keep polling us | ||
534 | * for these. | ||
535 | */ | ||
536 | switch (rq->cmd[0]) { | ||
537 | case GPCMD_BLANK: | ||
538 | case GPCMD_FORMAT_UNIT: | ||
539 | case GPCMD_RESERVE_RZONE_TRACK: | ||
540 | case GPCMD_CLOSE_TRACK: | ||
541 | case GPCMD_FLUSH_CACHE: | ||
542 | wait = ATAPI_WAIT_PC; | ||
543 | break; | ||
544 | default: | ||
545 | if (!(rq->cmd_flags & REQ_QUIET)) | ||
546 | printk(KERN_INFO PFX "cmd 0x%x timed out\n", | ||
547 | rq->cmd[0]); | ||
548 | wait = 0; | ||
549 | break; | ||
550 | } | ||
551 | return wait; | ||
552 | } | ||
553 | 516 | ||
554 | /* | 517 | /* |
555 | * Set up the device registers for transferring a packet command on DEV, | 518 | * Set up the device registers for transferring a packet command on DEV, |
@@ -559,11 +522,13 @@ static int cdrom_timer_expiry(ide_drive_t *drive) | |||
559 | * called when the interrupt from the drive arrives. Otherwise, HANDLER | 522 | * called when the interrupt from the drive arrives. Otherwise, HANDLER |
560 | * will be called immediately after the drive is prepared for the transfer. | 523 | * will be called immediately after the drive is prepared for the transfer. |
561 | */ | 524 | */ |
562 | static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, | 525 | static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive) |
563 | int xferlen, | ||
564 | ide_handler_t *handler) | ||
565 | { | 526 | { |
566 | ide_hwif_t *hwif = drive->hwif; | 527 | ide_hwif_t *hwif = drive->hwif; |
528 | struct request *rq = hwif->hwgroup->rq; | ||
529 | int xferlen; | ||
530 | |||
531 | xferlen = ide_cd_get_xferlen(rq); | ||
567 | 532 | ||
568 | ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen); | 533 | ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen); |
569 | 534 | ||
@@ -581,13 +546,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, | |||
581 | drive->waiting_for_dma = 0; | 546 | drive->waiting_for_dma = 0; |
582 | 547 | ||
583 | /* packet command */ | 548 | /* packet command */ |
584 | ide_execute_command(drive, ATA_CMD_PACKET, handler, | 549 | ide_execute_command(drive, ATA_CMD_PACKET, |
585 | ATAPI_WAIT_PC, cdrom_timer_expiry); | 550 | cdrom_transfer_packet_command, |
551 | ATAPI_WAIT_PC, ide_cd_expiry); | ||
586 | return ide_started; | 552 | return ide_started; |
587 | } else { | 553 | } else { |
588 | ide_execute_pkt_cmd(drive); | 554 | ide_execute_pkt_cmd(drive); |
589 | 555 | ||
590 | return (*handler) (drive); | 556 | return cdrom_transfer_packet_command(drive); |
591 | } | 557 | } |
592 | } | 558 | } |
593 | 559 | ||
@@ -598,11 +564,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, | |||
598 | * there's data ready. | 564 | * there's data ready. |
599 | */ | 565 | */ |
600 | #define ATAPI_MIN_CDB_BYTES 12 | 566 | #define ATAPI_MIN_CDB_BYTES 12 |
601 | static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, | 567 | static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive) |
602 | struct request *rq, | ||
603 | ide_handler_t *handler) | ||
604 | { | 568 | { |
605 | ide_hwif_t *hwif = drive->hwif; | 569 | ide_hwif_t *hwif = drive->hwif; |
570 | struct request *rq = hwif->hwgroup->rq; | ||
606 | int cmd_len; | 571 | int cmd_len; |
607 | ide_startstop_t startstop; | 572 | ide_startstop_t startstop; |
608 | 573 | ||
@@ -629,7 +594,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, | |||
629 | } | 594 | } |
630 | 595 | ||
631 | /* arm the interrupt handler */ | 596 | /* arm the interrupt handler */ |
632 | ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry); | 597 | ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, ide_cd_expiry); |
633 | 598 | ||
634 | /* ATAPI commands get padded out to 12 bytes minimum */ | 599 | /* ATAPI commands get padded out to 12 bytes minimum */ |
635 | cmd_len = COMMAND_SIZE(rq->cmd[0]); | 600 | cmd_len = COMMAND_SIZE(rq->cmd[0]); |
@@ -717,8 +682,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) | |||
717 | return 1; | 682 | return 1; |
718 | } | 683 | } |
719 | 684 | ||
720 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); | ||
721 | |||
722 | static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, | 685 | static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, |
723 | struct request *rq) | 686 | struct request *rq) |
724 | { | 687 | { |
@@ -761,20 +724,6 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, | |||
761 | } | 724 | } |
762 | 725 | ||
763 | /* | 726 | /* |
764 | * Routine to send a read/write packet command to the drive. This is usually | ||
765 | * called directly from cdrom_start_{read,write}(). However, for drq_interrupt | ||
766 | * devices, it is called from an interrupt when the drive is ready to accept | ||
767 | * the command. | ||
768 | */ | ||
769 | static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) | ||
770 | { | ||
771 | struct request *rq = drive->hwif->hwgroup->rq; | ||
772 | |||
773 | /* send the command to the drive and return */ | ||
774 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | * Fix up a possibly partially-processed request so that we can start it over | 727 | * Fix up a possibly partially-processed request so that we can start it over |
779 | * entirely, or even put it back on the request queue. | 728 | * entirely, or even put it back on the request queue. |
780 | */ | 729 | */ |
@@ -1096,7 +1045,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1096 | } else { | 1045 | } else { |
1097 | timeout = ATAPI_WAIT_PC; | 1046 | timeout = ATAPI_WAIT_PC; |
1098 | if (!blk_fs_request(rq)) | 1047 | if (!blk_fs_request(rq)) |
1099 | expiry = cdrom_timer_expiry; | 1048 | expiry = ide_cd_expiry; |
1100 | } | 1049 | } |
1101 | 1050 | ||
1102 | ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); | 1051 | ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); |
@@ -1163,13 +1112,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
1163 | return ide_started; | 1112 | return ide_started; |
1164 | } | 1113 | } |
1165 | 1114 | ||
1166 | static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive) | ||
1167 | { | ||
1168 | struct request *rq = HWGROUP(drive)->rq; | ||
1169 | |||
1170 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); | ||
1171 | } | ||
1172 | |||
1173 | static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | 1115 | static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) |
1174 | { | 1116 | { |
1175 | 1117 | ||
@@ -1214,18 +1156,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
1214 | static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | 1156 | static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, |
1215 | sector_t block) | 1157 | sector_t block) |
1216 | { | 1158 | { |
1217 | ide_handler_t *fn; | ||
1218 | int xferlen; | ||
1219 | |||
1220 | ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, " | 1159 | ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, " |
1221 | "rq->cmd_type: 0x%x, block: %llu\n", | 1160 | "rq->cmd_type: 0x%x, block: %llu\n", |
1222 | __func__, rq->cmd[0], rq->cmd_type, | 1161 | __func__, rq->cmd[0], rq->cmd_type, |
1223 | (unsigned long long)block); | 1162 | (unsigned long long)block); |
1224 | 1163 | ||
1225 | if (blk_fs_request(rq)) { | 1164 | if (blk_fs_request(rq)) { |
1226 | xferlen = 32768; | ||
1227 | fn = cdrom_start_rw_cont; | ||
1228 | |||
1229 | if (cdrom_start_rw(drive, rq) == ide_stopped) | 1165 | if (cdrom_start_rw(drive, rq) == ide_stopped) |
1230 | return ide_stopped; | 1166 | return ide_stopped; |
1231 | 1167 | ||
@@ -1233,9 +1169,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1233 | return ide_stopped; | 1169 | return ide_stopped; |
1234 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || | 1170 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || |
1235 | rq->cmd_type == REQ_TYPE_ATA_PC) { | 1171 | rq->cmd_type == REQ_TYPE_ATA_PC) { |
1236 | xferlen = rq->data_len; | ||
1237 | fn = cdrom_do_newpc_cont; | ||
1238 | |||
1239 | if (!rq->timeout) | 1172 | if (!rq->timeout) |
1240 | rq->timeout = ATAPI_WAIT_PC; | 1173 | rq->timeout = ATAPI_WAIT_PC; |
1241 | 1174 | ||
@@ -1250,7 +1183,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1250 | return ide_stopped; | 1183 | return ide_stopped; |
1251 | } | 1184 | } |
1252 | 1185 | ||
1253 | return cdrom_start_packet_command(drive, xferlen, fn); | 1186 | return cdrom_start_packet_command(drive); |
1254 | } | 1187 | } |
1255 | 1188 | ||
1256 | /* | 1189 | /* |
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index d5ce3362dbd1..bf676b262181 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h | |||
@@ -8,10 +8,14 @@ | |||
8 | #include <linux/cdrom.h> | 8 | #include <linux/cdrom.h> |
9 | #include <asm/byteorder.h> | 9 | #include <asm/byteorder.h> |
10 | 10 | ||
11 | /* | 11 | #define IDECD_DEBUG_LOG 0 |
12 | * typical timeout for packet command | 12 | |
13 | */ | 13 | #if IDECD_DEBUG_LOG |
14 | #define ATAPI_WAIT_PC (60 * HZ) | 14 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) |
15 | #else | ||
16 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
17 | #endif | ||
18 | |||
15 | #define ATAPI_WAIT_WRITE_BUSY (10 * HZ) | 19 | #define ATAPI_WAIT_WRITE_BUSY (10 * HZ) |
16 | 20 | ||
17 | /************************************************************************/ | 21 | /************************************************************************/ |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index aeb1ad782f54..0a48e2dc53a2 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -197,7 +197,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, | |||
197 | 197 | ||
198 | pc->retries++; | 198 | pc->retries++; |
199 | 199 | ||
200 | return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL); | 200 | return ide_issue_pc(drive); |
201 | } | 201 | } |
202 | 202 | ||
203 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) | 203 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) |
@@ -342,38 +342,38 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
342 | * Look at the flexible disk page parameters. We ignore the CHS capacity | 342 | * Look at the flexible disk page parameters. We ignore the CHS capacity |
343 | * parameters and use the LBA parameters instead. | 343 | * parameters and use the LBA parameters instead. |
344 | */ | 344 | */ |
345 | static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) | 345 | static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive, |
346 | struct ide_atapi_pc *pc) | ||
346 | { | 347 | { |
347 | struct ide_disk_obj *floppy = drive->driver_data; | 348 | struct ide_disk_obj *floppy = drive->driver_data; |
348 | struct gendisk *disk = floppy->disk; | 349 | struct gendisk *disk = floppy->disk; |
349 | struct ide_atapi_pc pc; | ||
350 | u8 *page; | 350 | u8 *page; |
351 | int capacity, lba_capacity; | 351 | int capacity, lba_capacity; |
352 | u16 transfer_rate, sector_size, cyls, rpm; | 352 | u16 transfer_rate, sector_size, cyls, rpm; |
353 | u8 heads, sectors; | 353 | u8 heads, sectors; |
354 | 354 | ||
355 | ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); | 355 | ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); |
356 | 356 | ||
357 | if (ide_queue_pc_tail(drive, disk, &pc)) { | 357 | if (ide_queue_pc_tail(drive, disk, pc)) { |
358 | printk(KERN_ERR PFX "Can't get flexible disk page params\n"); | 358 | printk(KERN_ERR PFX "Can't get flexible disk page params\n"); |
359 | return 1; | 359 | return 1; |
360 | } | 360 | } |
361 | 361 | ||
362 | if (pc.buf[3] & 0x80) | 362 | if (pc->buf[3] & 0x80) |
363 | drive->dev_flags |= IDE_DFLAG_WP; | 363 | drive->dev_flags |= IDE_DFLAG_WP; |
364 | else | 364 | else |
365 | drive->dev_flags &= ~IDE_DFLAG_WP; | 365 | drive->dev_flags &= ~IDE_DFLAG_WP; |
366 | 366 | ||
367 | set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); | 367 | set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); |
368 | 368 | ||
369 | page = &pc.buf[8]; | 369 | page = &pc->buf[8]; |
370 | 370 | ||
371 | transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]); | 371 | transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]); |
372 | sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]); | 372 | sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]); |
373 | cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]); | 373 | cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]); |
374 | rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]); | 374 | rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]); |
375 | heads = pc.buf[8 + 4]; | 375 | heads = pc->buf[8 + 4]; |
376 | sectors = pc.buf[8 + 5]; | 376 | sectors = pc->buf[8 + 5]; |
377 | 377 | ||
378 | capacity = cyls * heads * sectors * sector_size; | 378 | capacity = cyls * heads * sectors * sector_size; |
379 | 379 | ||
@@ -499,7 +499,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
499 | 499 | ||
500 | /* Clik! disk does not support get_flexible_disk_page */ | 500 | /* Clik! disk does not support get_flexible_disk_page */ |
501 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) | 501 | if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) |
502 | (void) ide_floppy_get_flexible_disk_page(drive); | 502 | (void) ide_floppy_get_flexible_disk_page(drive, &pc); |
503 | 503 | ||
504 | return rc; | 504 | return rc; |
505 | } | 505 | } |
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 2bc51ff73fee..8f8be8546038 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c | |||
@@ -31,10 +31,11 @@ | |||
31 | * On exit we set nformats to the number of records we've actually initialized. | 31 | * On exit we set nformats to the number of records we've actually initialized. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) | 34 | static int ide_floppy_get_format_capacities(ide_drive_t *drive, |
35 | struct ide_atapi_pc *pc, | ||
36 | int __user *arg) | ||
35 | { | 37 | { |
36 | struct ide_disk_obj *floppy = drive->driver_data; | 38 | struct ide_disk_obj *floppy = drive->driver_data; |
37 | struct ide_atapi_pc pc; | ||
38 | u8 header_len, desc_cnt; | 39 | u8 header_len, desc_cnt; |
39 | int i, blocks, length, u_array_size, u_index; | 40 | int i, blocks, length, u_array_size, u_index; |
40 | int __user *argp; | 41 | int __user *argp; |
@@ -45,13 +46,13 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) | |||
45 | if (u_array_size <= 0) | 46 | if (u_array_size <= 0) |
46 | return -EINVAL; | 47 | return -EINVAL; |
47 | 48 | ||
48 | ide_floppy_create_read_capacity_cmd(&pc); | 49 | ide_floppy_create_read_capacity_cmd(pc); |
49 | if (ide_queue_pc_tail(drive, floppy->disk, &pc)) { | 50 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) { |
50 | printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); | 51 | printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); |
51 | return -EIO; | 52 | return -EIO; |
52 | } | 53 | } |
53 | 54 | ||
54 | header_len = pc.buf[3]; | 55 | header_len = pc->buf[3]; |
55 | desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ | 56 | desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ |
56 | 57 | ||
57 | u_index = 0; | 58 | u_index = 0; |
@@ -68,8 +69,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) | |||
68 | if (u_index >= u_array_size) | 69 | if (u_index >= u_array_size) |
69 | break; /* User-supplied buffer too small */ | 70 | break; /* User-supplied buffer too small */ |
70 | 71 | ||
71 | blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); | 72 | blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]); |
72 | length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); | 73 | length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]); |
73 | 74 | ||
74 | if (put_user(blocks, argp)) | 75 | if (put_user(blocks, argp)) |
75 | return -EFAULT; | 76 | return -EFAULT; |
@@ -111,29 +112,28 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, | |||
111 | pc->flags |= PC_FLAG_WRITING; | 112 | pc->flags |= PC_FLAG_WRITING; |
112 | } | 113 | } |
113 | 114 | ||
114 | static int ide_floppy_get_sfrp_bit(ide_drive_t *drive) | 115 | static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc) |
115 | { | 116 | { |
116 | struct ide_disk_obj *floppy = drive->driver_data; | 117 | struct ide_disk_obj *floppy = drive->driver_data; |
117 | struct ide_atapi_pc pc; | ||
118 | 118 | ||
119 | drive->atapi_flags &= ~IDE_AFLAG_SRFP; | 119 | drive->atapi_flags &= ~IDE_AFLAG_SRFP; |
120 | 120 | ||
121 | ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); | 121 | ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE); |
122 | pc.flags |= PC_FLAG_SUPPRESS_ERROR; | 122 | pc->flags |= PC_FLAG_SUPPRESS_ERROR; |
123 | 123 | ||
124 | if (ide_queue_pc_tail(drive, floppy->disk, &pc)) | 124 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) |
125 | return 1; | 125 | return 1; |
126 | 126 | ||
127 | if (pc.buf[8 + 2] & 0x40) | 127 | if (pc->buf[8 + 2] & 0x40) |
128 | drive->atapi_flags |= IDE_AFLAG_SRFP; | 128 | drive->atapi_flags |= IDE_AFLAG_SRFP; |
129 | 129 | ||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) | 133 | static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc, |
134 | int __user *arg) | ||
134 | { | 135 | { |
135 | struct ide_disk_obj *floppy = drive->driver_data; | 136 | struct ide_disk_obj *floppy = drive->driver_data; |
136 | struct ide_atapi_pc pc; | ||
137 | int blocks, length, flags, err = 0; | 137 | int blocks, length, flags, err = 0; |
138 | 138 | ||
139 | if (floppy->openers > 1) { | 139 | if (floppy->openers > 1) { |
@@ -166,10 +166,10 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) | |||
166 | goto out; | 166 | goto out; |
167 | } | 167 | } |
168 | 168 | ||
169 | (void)ide_floppy_get_sfrp_bit(drive); | 169 | ide_floppy_get_sfrp_bit(drive, pc); |
170 | ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags); | 170 | ide_floppy_create_format_unit_cmd(pc, blocks, length, flags); |
171 | 171 | ||
172 | if (ide_queue_pc_tail(drive, floppy->disk, &pc)) | 172 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) |
173 | err = -EIO; | 173 | err = -EIO; |
174 | 174 | ||
175 | out: | 175 | out: |
@@ -188,15 +188,16 @@ out: | |||
188 | * the dsc bit, and return either 0 or 65536. | 188 | * the dsc bit, and return either 0 or 65536. |
189 | */ | 189 | */ |
190 | 190 | ||
191 | static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) | 191 | static int ide_floppy_get_format_progress(ide_drive_t *drive, |
192 | struct ide_atapi_pc *pc, | ||
193 | int __user *arg) | ||
192 | { | 194 | { |
193 | struct ide_disk_obj *floppy = drive->driver_data; | 195 | struct ide_disk_obj *floppy = drive->driver_data; |
194 | struct ide_atapi_pc pc; | ||
195 | int progress_indication = 0x10000; | 196 | int progress_indication = 0x10000; |
196 | 197 | ||
197 | if (drive->atapi_flags & IDE_AFLAG_SRFP) { | 198 | if (drive->atapi_flags & IDE_AFLAG_SRFP) { |
198 | ide_create_request_sense_cmd(drive, &pc); | 199 | ide_create_request_sense_cmd(drive, pc); |
199 | if (ide_queue_pc_tail(drive, floppy->disk, &pc)) | 200 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) |
200 | return -EIO; | 201 | return -EIO; |
201 | 202 | ||
202 | if (floppy->sense_key == 2 && | 203 | if (floppy->sense_key == 2 && |
@@ -241,20 +242,21 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
241 | return 0; | 242 | return 0; |
242 | } | 243 | } |
243 | 244 | ||
244 | static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode, | 245 | static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc, |
245 | unsigned int cmd, void __user *argp) | 246 | fmode_t mode, unsigned int cmd, |
247 | void __user *argp) | ||
246 | { | 248 | { |
247 | switch (cmd) { | 249 | switch (cmd) { |
248 | case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: | 250 | case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: |
249 | return 0; | 251 | return 0; |
250 | case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: | 252 | case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: |
251 | return ide_floppy_get_format_capacities(drive, argp); | 253 | return ide_floppy_get_format_capacities(drive, pc, argp); |
252 | case IDEFLOPPY_IOCTL_FORMAT_START: | 254 | case IDEFLOPPY_IOCTL_FORMAT_START: |
253 | if (!(mode & FMODE_WRITE)) | 255 | if (!(mode & FMODE_WRITE)) |
254 | return -EPERM; | 256 | return -EPERM; |
255 | return ide_floppy_format_unit(drive, (int __user *)argp); | 257 | return ide_floppy_format_unit(drive, pc, (int __user *)argp); |
256 | case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: | 258 | case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: |
257 | return ide_floppy_get_format_progress(drive, argp); | 259 | return ide_floppy_get_format_progress(drive, pc, argp); |
258 | default: | 260 | default: |
259 | return -ENOTTY; | 261 | return -ENOTTY; |
260 | } | 262 | } |
@@ -270,7 +272,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, | |||
270 | if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) | 272 | if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) |
271 | return ide_floppy_lockdoor(drive, &pc, arg, cmd); | 273 | return ide_floppy_lockdoor(drive, &pc, arg, cmd); |
272 | 274 | ||
273 | err = ide_floppy_format_ioctl(drive, mode, cmd, argp); | 275 | err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); |
274 | if (err != -ENOTTY) | 276 | if (err != -ENOTTY) |
275 | return err; | 277 | return err; |
276 | 278 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ecacc008fdaf..1c36a8e83d36 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -426,9 +426,6 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) | |||
426 | ide_hwif_t *hwif = drive->hwif; | 426 | ide_hwif_t *hwif = drive->hwif; |
427 | struct scatterlist *sg = hwif->sg_table; | 427 | struct scatterlist *sg = hwif->sg_table; |
428 | 428 | ||
429 | if (hwif->sg_mapped) /* needed by ide-scsi */ | ||
430 | return; | ||
431 | |||
432 | if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { | 429 | if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { |
433 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | 430 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); |
434 | } else { | 431 | } else { |
@@ -667,85 +664,10 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) | |||
667 | drive->sleep = timeout + jiffies; | 664 | drive->sleep = timeout + jiffies; |
668 | drive->dev_flags |= IDE_DFLAG_SLEEPING; | 665 | drive->dev_flags |= IDE_DFLAG_SLEEPING; |
669 | } | 666 | } |
670 | |||
671 | EXPORT_SYMBOL(ide_stall_queue); | 667 | EXPORT_SYMBOL(ide_stall_queue); |
672 | 668 | ||
673 | #define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) | ||
674 | |||
675 | /** | ||
676 | * choose_drive - select a drive to service | ||
677 | * @hwgroup: hardware group to select on | ||
678 | * | ||
679 | * choose_drive() selects the next drive which will be serviced. | ||
680 | * This is necessary because the IDE layer can't issue commands | ||
681 | * to both drives on the same cable, unlike SCSI. | ||
682 | */ | ||
683 | |||
684 | static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) | ||
685 | { | ||
686 | ide_drive_t *drive, *best; | ||
687 | |||
688 | repeat: | ||
689 | best = NULL; | ||
690 | drive = hwgroup->drive; | ||
691 | |||
692 | /* | ||
693 | * drive is doing pre-flush, ordered write, post-flush sequence. even | ||
694 | * though that is 3 requests, it must be seen as a single transaction. | ||
695 | * we must not preempt this drive until that is complete | ||
696 | */ | ||
697 | if (blk_queue_flushing(drive->queue)) { | ||
698 | /* | ||
699 | * small race where queue could get replugged during | ||
700 | * the 3-request flush cycle, just yank the plug since | ||
701 | * we want it to finish asap | ||
702 | */ | ||
703 | blk_remove_plug(drive->queue); | ||
704 | return drive; | ||
705 | } | ||
706 | |||
707 | do { | ||
708 | u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING); | ||
709 | u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING)); | ||
710 | |||
711 | if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) && | ||
712 | !elv_queue_empty(drive->queue)) { | ||
713 | if (best == NULL || | ||
714 | (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) || | ||
715 | (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) { | ||
716 | if (!blk_queue_plugged(drive->queue)) | ||
717 | best = drive; | ||
718 | } | ||
719 | } | ||
720 | } while ((drive = drive->next) != hwgroup->drive); | ||
721 | |||
722 | if (best && (best->dev_flags & IDE_DFLAG_NICE1) && | ||
723 | (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 && | ||
724 | best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { | ||
725 | long t = (signed long)(WAKEUP(best) - jiffies); | ||
726 | if (t >= WAIT_MIN_SLEEP) { | ||
727 | /* | ||
728 | * We *may* have some time to spare, but first let's see if | ||
729 | * someone can potentially benefit from our nice mood today.. | ||
730 | */ | ||
731 | drive = best->next; | ||
732 | do { | ||
733 | if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0 | ||
734 | && time_before(jiffies - best->service_time, WAKEUP(drive)) | ||
735 | && time_before(WAKEUP(drive), jiffies + t)) | ||
736 | { | ||
737 | ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP)); | ||
738 | goto repeat; | ||
739 | } | ||
740 | } while ((drive = drive->next) != best); | ||
741 | } | ||
742 | } | ||
743 | return best; | ||
744 | } | ||
745 | |||
746 | /* | 669 | /* |
747 | * Issue a new request to a drive from hwgroup | 670 | * Issue a new request to a drive from hwgroup |
748 | * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..); | ||
749 | * | 671 | * |
750 | * A hwgroup is a serialized group of IDE interfaces. Usually there is | 672 | * A hwgroup is a serialized group of IDE interfaces. Usually there is |
751 | * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) | 673 | * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) |
@@ -757,8 +679,7 @@ repeat: | |||
757 | * possibly along with many other devices. This is especially common in | 679 | * possibly along with many other devices. This is especially common in |
758 | * PCI-based systems with off-board IDE controller cards. | 680 | * PCI-based systems with off-board IDE controller cards. |
759 | * | 681 | * |
760 | * The IDE driver uses a per-hwgroup spinlock to protect | 682 | * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag. |
761 | * access to the request queues, and to protect the hwgroup->busy flag. | ||
762 | * | 683 | * |
763 | * The first thread into the driver for a particular hwgroup sets the | 684 | * The first thread into the driver for a particular hwgroup sets the |
764 | * hwgroup->busy flag to indicate that this hwgroup is now active, | 685 | * hwgroup->busy flag to indicate that this hwgroup is now active, |
@@ -778,69 +699,41 @@ repeat: | |||
778 | * the driver. This makes the driver much more friendlier to shared IRQs | 699 | * the driver. This makes the driver much more friendlier to shared IRQs |
779 | * than previous designs, while remaining 100% (?) SMP safe and capable. | 700 | * than previous designs, while remaining 100% (?) SMP safe and capable. |
780 | */ | 701 | */ |
781 | static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | 702 | void do_ide_request(struct request_queue *q) |
782 | { | 703 | { |
783 | ide_drive_t *drive; | 704 | ide_drive_t *drive = q->queuedata; |
784 | ide_hwif_t *hwif; | 705 | ide_hwif_t *hwif = drive->hwif; |
706 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
785 | struct request *rq; | 707 | struct request *rq; |
786 | ide_startstop_t startstop; | 708 | ide_startstop_t startstop; |
787 | int loops = 0; | 709 | |
788 | 710 | /* | |
789 | /* caller must own hwgroup->lock */ | 711 | * drive is doing pre-flush, ordered write, post-flush sequence. even |
790 | BUG_ON(!irqs_disabled()); | 712 | * though that is 3 requests, it must be seen as a single transaction. |
791 | 713 | * we must not preempt this drive until that is complete | |
792 | while (!hwgroup->busy) { | 714 | */ |
793 | hwgroup->busy = 1; | 715 | if (blk_queue_flushing(q)) |
794 | /* for atari only */ | ||
795 | ide_get_lock(ide_intr, hwgroup); | ||
796 | drive = choose_drive(hwgroup); | ||
797 | if (drive == NULL) { | ||
798 | int sleeping = 0; | ||
799 | unsigned long sleep = 0; /* shut up, gcc */ | ||
800 | hwgroup->rq = NULL; | ||
801 | drive = hwgroup->drive; | ||
802 | do { | ||
803 | if ((drive->dev_flags & IDE_DFLAG_SLEEPING) && | ||
804 | (sleeping == 0 || | ||
805 | time_before(drive->sleep, sleep))) { | ||
806 | sleeping = 1; | ||
807 | sleep = drive->sleep; | ||
808 | } | ||
809 | } while ((drive = drive->next) != hwgroup->drive); | ||
810 | if (sleeping) { | ||
811 | /* | 716 | /* |
812 | * Take a short snooze, and then wake up this hwgroup again. | 717 | * small race where queue could get replugged during |
813 | * This gives other hwgroups on the same a chance to | 718 | * the 3-request flush cycle, just yank the plug since |
814 | * play fairly with us, just in case there are big differences | 719 | * we want it to finish asap |
815 | * in relative throughputs.. don't want to hog the cpu too much. | ||
816 | */ | 720 | */ |
817 | if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) | 721 | blk_remove_plug(q); |
818 | sleep = jiffies + WAIT_MIN_SLEEP; | ||
819 | #if 1 | ||
820 | if (timer_pending(&hwgroup->timer)) | ||
821 | printk(KERN_CRIT "ide_set_handler: timer already active\n"); | ||
822 | #endif | ||
823 | /* so that ide_timer_expiry knows what to do */ | ||
824 | hwgroup->sleeping = 1; | ||
825 | hwgroup->req_gen_timer = hwgroup->req_gen; | ||
826 | mod_timer(&hwgroup->timer, sleep); | ||
827 | /* we purposely leave hwgroup->busy==1 | ||
828 | * while sleeping */ | ||
829 | } else { | ||
830 | /* Ugly, but how can we sleep for the lock | ||
831 | * otherwise? perhaps from tq_disk? | ||
832 | */ | ||
833 | 722 | ||
834 | /* for atari only */ | 723 | spin_unlock_irq(q->queue_lock); |
835 | ide_release_lock(); | 724 | spin_lock_irq(&hwgroup->lock); |
836 | hwgroup->busy = 0; | 725 | |
837 | } | 726 | if (!ide_lock_hwgroup(hwgroup)) { |
727 | repeat: | ||
728 | hwgroup->rq = NULL; | ||
838 | 729 | ||
839 | /* no more work for this hwgroup (for now) */ | 730 | if (drive->dev_flags & IDE_DFLAG_SLEEPING) { |
840 | return; | 731 | if (time_before(drive->sleep, jiffies)) { |
732 | ide_unlock_hwgroup(hwgroup); | ||
733 | goto plug_device; | ||
734 | } | ||
841 | } | 735 | } |
842 | again: | 736 | |
843 | hwif = HWIF(drive); | ||
844 | if (hwif != hwgroup->hwif) { | 737 | if (hwif != hwgroup->hwif) { |
845 | /* | 738 | /* |
846 | * set nIEN for previous hwif, drives in the | 739 | * set nIEN for previous hwif, drives in the |
@@ -852,16 +745,20 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
852 | hwgroup->hwif = hwif; | 745 | hwgroup->hwif = hwif; |
853 | hwgroup->drive = drive; | 746 | hwgroup->drive = drive; |
854 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); | 747 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); |
855 | drive->service_start = jiffies; | ||
856 | 748 | ||
749 | spin_unlock_irq(&hwgroup->lock); | ||
750 | spin_lock_irq(q->queue_lock); | ||
857 | /* | 751 | /* |
858 | * we know that the queue isn't empty, but this can happen | 752 | * we know that the queue isn't empty, but this can happen |
859 | * if the q->prep_rq_fn() decides to kill a request | 753 | * if the q->prep_rq_fn() decides to kill a request |
860 | */ | 754 | */ |
861 | rq = elv_next_request(drive->queue); | 755 | rq = elv_next_request(drive->queue); |
756 | spin_unlock_irq(q->queue_lock); | ||
757 | spin_lock_irq(&hwgroup->lock); | ||
758 | |||
862 | if (!rq) { | 759 | if (!rq) { |
863 | hwgroup->busy = 0; | 760 | ide_unlock_hwgroup(hwgroup); |
864 | break; | 761 | goto out; |
865 | } | 762 | } |
866 | 763 | ||
867 | /* | 764 | /* |
@@ -876,53 +773,36 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
876 | * though. I hope that doesn't happen too much, hopefully not | 773 | * though. I hope that doesn't happen too much, hopefully not |
877 | * unless the subdriver triggers such a thing in its own PM | 774 | * unless the subdriver triggers such a thing in its own PM |
878 | * state machine. | 775 | * state machine. |
879 | * | ||
880 | * We count how many times we loop here to make sure we service | ||
881 | * all drives in the hwgroup without looping for ever | ||
882 | */ | 776 | */ |
883 | if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && | 777 | if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && |
884 | blk_pm_request(rq) == 0 && | 778 | blk_pm_request(rq) == 0 && |
885 | (rq->cmd_flags & REQ_PREEMPT) == 0) { | 779 | (rq->cmd_flags & REQ_PREEMPT) == 0) { |
886 | drive = drive->next ? drive->next : hwgroup->drive; | 780 | /* there should be no pending command at this point */ |
887 | if (loops++ < 4 && !blk_queue_plugged(drive->queue)) | 781 | ide_unlock_hwgroup(hwgroup); |
888 | goto again; | 782 | goto plug_device; |
889 | /* We clear busy, there should be no pending ATA command at this point. */ | ||
890 | hwgroup->busy = 0; | ||
891 | break; | ||
892 | } | 783 | } |
893 | 784 | ||
894 | hwgroup->rq = rq; | 785 | hwgroup->rq = rq; |
895 | 786 | ||
896 | /* | 787 | spin_unlock_irq(&hwgroup->lock); |
897 | * Some systems have trouble with IDE IRQs arriving while | ||
898 | * the driver is still setting things up. So, here we disable | ||
899 | * the IRQ used by this interface while the request is being started. | ||
900 | * This may look bad at first, but pretty much the same thing | ||
901 | * happens anyway when any interrupt comes in, IDE or otherwise | ||
902 | * -- the kernel masks the IRQ while it is being handled. | ||
903 | */ | ||
904 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) | ||
905 | disable_irq_nosync(hwif->irq); | ||
906 | spin_unlock(&hwgroup->lock); | ||
907 | local_irq_enable_in_hardirq(); | ||
908 | /* allow other IRQs while we start this request */ | ||
909 | startstop = start_request(drive, rq); | 788 | startstop = start_request(drive, rq); |
910 | spin_lock_irq(&hwgroup->lock); | 789 | spin_lock_irq(&hwgroup->lock); |
911 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) | 790 | |
912 | enable_irq(hwif->irq); | ||
913 | if (startstop == ide_stopped) | 791 | if (startstop == ide_stopped) |
914 | hwgroup->busy = 0; | 792 | goto repeat; |
915 | } | 793 | } else |
916 | } | 794 | goto plug_device; |
795 | out: | ||
796 | spin_unlock_irq(&hwgroup->lock); | ||
797 | spin_lock_irq(q->queue_lock); | ||
798 | return; | ||
917 | 799 | ||
918 | /* | 800 | plug_device: |
919 | * Passes the stuff to ide_do_request | 801 | spin_unlock_irq(&hwgroup->lock); |
920 | */ | 802 | spin_lock_irq(q->queue_lock); |
921 | void do_ide_request(struct request_queue *q) | ||
922 | { | ||
923 | ide_drive_t *drive = q->queuedata; | ||
924 | 803 | ||
925 | ide_do_request(HWGROUP(drive), IDE_NO_IRQ); | 804 | if (!elv_queue_empty(q)) |
805 | blk_plug_device(q); | ||
926 | } | 806 | } |
927 | 807 | ||
928 | /* | 808 | /* |
@@ -983,6 +863,17 @@ out: | |||
983 | return ret; | 863 | return ret; |
984 | } | 864 | } |
985 | 865 | ||
866 | static void ide_plug_device(ide_drive_t *drive) | ||
867 | { | ||
868 | struct request_queue *q = drive->queue; | ||
869 | unsigned long flags; | ||
870 | |||
871 | spin_lock_irqsave(q->queue_lock, flags); | ||
872 | if (!elv_queue_empty(q)) | ||
873 | blk_plug_device(q); | ||
874 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
875 | } | ||
876 | |||
986 | /** | 877 | /** |
987 | * ide_timer_expiry - handle lack of an IDE interrupt | 878 | * ide_timer_expiry - handle lack of an IDE interrupt |
988 | * @data: timer callback magic (hwgroup) | 879 | * @data: timer callback magic (hwgroup) |
@@ -1000,10 +891,12 @@ out: | |||
1000 | void ide_timer_expiry (unsigned long data) | 891 | void ide_timer_expiry (unsigned long data) |
1001 | { | 892 | { |
1002 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; | 893 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; |
894 | ide_drive_t *uninitialized_var(drive); | ||
1003 | ide_handler_t *handler; | 895 | ide_handler_t *handler; |
1004 | ide_expiry_t *expiry; | 896 | ide_expiry_t *expiry; |
1005 | unsigned long flags; | 897 | unsigned long flags; |
1006 | unsigned long wait = -1; | 898 | unsigned long wait = -1; |
899 | int plug_device = 0; | ||
1007 | 900 | ||
1008 | spin_lock_irqsave(&hwgroup->lock, flags); | 901 | spin_lock_irqsave(&hwgroup->lock, flags); |
1009 | 902 | ||
@@ -1015,22 +908,15 @@ void ide_timer_expiry (unsigned long data) | |||
1015 | * or we were "sleeping" to give other devices a chance. | 908 | * or we were "sleeping" to give other devices a chance. |
1016 | * Either way, we don't really want to complain about anything. | 909 | * Either way, we don't really want to complain about anything. |
1017 | */ | 910 | */ |
1018 | if (hwgroup->sleeping) { | ||
1019 | hwgroup->sleeping = 0; | ||
1020 | hwgroup->busy = 0; | ||
1021 | } | ||
1022 | } else { | 911 | } else { |
1023 | ide_drive_t *drive = hwgroup->drive; | 912 | drive = hwgroup->drive; |
1024 | if (!drive) { | 913 | if (!drive) { |
1025 | printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); | 914 | printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); |
1026 | hwgroup->handler = NULL; | 915 | hwgroup->handler = NULL; |
1027 | } else { | 916 | } else { |
1028 | ide_hwif_t *hwif; | 917 | ide_hwif_t *hwif; |
1029 | ide_startstop_t startstop = ide_stopped; | 918 | ide_startstop_t startstop = ide_stopped; |
1030 | if (!hwgroup->busy) { | 919 | |
1031 | hwgroup->busy = 1; /* paranoia */ | ||
1032 | printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); | ||
1033 | } | ||
1034 | if ((expiry = hwgroup->expiry) != NULL) { | 920 | if ((expiry = hwgroup->expiry) != NULL) { |
1035 | /* continue */ | 921 | /* continue */ |
1036 | if ((wait = expiry(drive)) > 0) { | 922 | if ((wait = expiry(drive)) > 0) { |
@@ -1071,15 +957,18 @@ void ide_timer_expiry (unsigned long data) | |||
1071 | ide_error(drive, "irq timeout", | 957 | ide_error(drive, "irq timeout", |
1072 | hwif->tp_ops->read_status(hwif)); | 958 | hwif->tp_ops->read_status(hwif)); |
1073 | } | 959 | } |
1074 | drive->service_time = jiffies - drive->service_start; | ||
1075 | spin_lock_irq(&hwgroup->lock); | 960 | spin_lock_irq(&hwgroup->lock); |
1076 | enable_irq(hwif->irq); | 961 | enable_irq(hwif->irq); |
1077 | if (startstop == ide_stopped) | 962 | if (startstop == ide_stopped) { |
1078 | hwgroup->busy = 0; | 963 | ide_unlock_hwgroup(hwgroup); |
964 | plug_device = 1; | ||
965 | } | ||
1079 | } | 966 | } |
1080 | } | 967 | } |
1081 | ide_do_request(hwgroup, IDE_NO_IRQ); | ||
1082 | spin_unlock_irqrestore(&hwgroup->lock, flags); | 968 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
969 | |||
970 | if (plug_device) | ||
971 | ide_plug_device(drive); | ||
1083 | } | 972 | } |
1084 | 973 | ||
1085 | /** | 974 | /** |
@@ -1173,10 +1062,11 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1173 | unsigned long flags; | 1062 | unsigned long flags; |
1174 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; | 1063 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; |
1175 | ide_hwif_t *hwif = hwgroup->hwif; | 1064 | ide_hwif_t *hwif = hwgroup->hwif; |
1176 | ide_drive_t *drive; | 1065 | ide_drive_t *uninitialized_var(drive); |
1177 | ide_handler_t *handler; | 1066 | ide_handler_t *handler; |
1178 | ide_startstop_t startstop; | 1067 | ide_startstop_t startstop; |
1179 | irqreturn_t irq_ret = IRQ_NONE; | 1068 | irqreturn_t irq_ret = IRQ_NONE; |
1069 | int plug_device = 0; | ||
1180 | 1070 | ||
1181 | spin_lock_irqsave(&hwgroup->lock, flags); | 1071 | spin_lock_irqsave(&hwgroup->lock, flags); |
1182 | 1072 | ||
@@ -1241,10 +1131,6 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1241 | */ | 1131 | */ |
1242 | goto out; | 1132 | goto out; |
1243 | 1133 | ||
1244 | if (!hwgroup->busy) { | ||
1245 | hwgroup->busy = 1; /* paranoia */ | ||
1246 | printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); | ||
1247 | } | ||
1248 | hwgroup->handler = NULL; | 1134 | hwgroup->handler = NULL; |
1249 | hwgroup->req_gen++; | 1135 | hwgroup->req_gen++; |
1250 | del_timer(&hwgroup->timer); | 1136 | del_timer(&hwgroup->timer); |
@@ -1267,20 +1153,22 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1267 | * same irq as is currently being serviced here, and Linux | 1153 | * same irq as is currently being serviced here, and Linux |
1268 | * won't allow another of the same (on any CPU) until we return. | 1154 | * won't allow another of the same (on any CPU) until we return. |
1269 | */ | 1155 | */ |
1270 | drive->service_time = jiffies - drive->service_start; | ||
1271 | if (startstop == ide_stopped) { | 1156 | if (startstop == ide_stopped) { |
1272 | if (hwgroup->handler == NULL) { /* paranoia */ | 1157 | if (hwgroup->handler == NULL) { /* paranoia */ |
1273 | hwgroup->busy = 0; | 1158 | ide_unlock_hwgroup(hwgroup); |
1274 | ide_do_request(hwgroup, hwif->irq); | 1159 | plug_device = 1; |
1275 | } else { | 1160 | } else |
1276 | printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " | 1161 | printk(KERN_ERR "%s: %s: huh? expected NULL handler " |
1277 | "on exit\n", drive->name); | 1162 | "on exit\n", __func__, drive->name); |
1278 | } | ||
1279 | } | 1163 | } |
1280 | out_handled: | 1164 | out_handled: |
1281 | irq_ret = IRQ_HANDLED; | 1165 | irq_ret = IRQ_HANDLED; |
1282 | out: | 1166 | out: |
1283 | spin_unlock_irqrestore(&hwgroup->lock, flags); | 1167 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1168 | |||
1169 | if (plug_device) | ||
1170 | ide_plug_device(drive); | ||
1171 | |||
1284 | return irq_ret; | 1172 | return irq_ret; |
1285 | } | 1173 | } |
1286 | 1174 | ||
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 28232c64c346..1be263eb9c07 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
@@ -95,8 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) | |||
95 | return -EPERM; | 95 | return -EPERM; |
96 | 96 | ||
97 | if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && | 97 | if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && |
98 | (drive->media != ide_tape || | 98 | (drive->media != ide_tape)) |
99 | (drive->dev_flags & IDE_DFLAG_SCSI))) | ||
100 | return -EPERM; | 99 | return -EPERM; |
101 | 100 | ||
102 | if ((arg >> IDE_NICE_DSC_OVERLAP) & 1) | 101 | if ((arg >> IDE_NICE_DSC_OVERLAP) & 1) |
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 63d01c55f865..678454ac2483 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c | |||
@@ -16,16 +16,19 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | |||
16 | spin_lock_irq(&hwgroup->lock); | 16 | spin_lock_irq(&hwgroup->lock); |
17 | if (drive->dev_flags & IDE_DFLAG_PARKED) { | 17 | if (drive->dev_flags & IDE_DFLAG_PARKED) { |
18 | int reset_timer = time_before(timeout, drive->sleep); | 18 | int reset_timer = time_before(timeout, drive->sleep); |
19 | int start_queue = 0; | ||
19 | 20 | ||
20 | drive->sleep = timeout; | 21 | drive->sleep = timeout; |
21 | wake_up_all(&ide_park_wq); | 22 | wake_up_all(&ide_park_wq); |
22 | if (reset_timer && hwgroup->sleeping && | 23 | if (reset_timer && del_timer(&hwgroup->timer)) |
23 | del_timer(&hwgroup->timer)) { | 24 | start_queue = 1; |
24 | hwgroup->sleeping = 0; | 25 | spin_unlock_irq(&hwgroup->lock); |
25 | hwgroup->busy = 0; | 26 | |
27 | if (start_queue) { | ||
28 | spin_lock_irq(q->queue_lock); | ||
26 | blk_start_queueing(q); | 29 | blk_start_queueing(q); |
30 | spin_unlock_irq(q->queue_lock); | ||
27 | } | 31 | } |
28 | spin_unlock_irq(&hwgroup->lock); | ||
29 | return; | 32 | return; |
30 | } | 33 | } |
31 | spin_unlock_irq(&hwgroup->lock); | 34 | spin_unlock_irq(&hwgroup->lock); |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a64ec259f3d1..c5adb7b9c5b5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) | |||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | static void ide_classify_ata_dev(ide_drive_t *drive) | ||
105 | { | ||
106 | u16 *id = drive->id; | ||
107 | char *m = (char *)&id[ATA_ID_PROD]; | ||
108 | int is_cfa = ata_id_is_cfa(id); | ||
109 | |||
110 | /* CF devices are *not* removable in Linux definition of the term */ | ||
111 | if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) | ||
112 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
113 | |||
114 | drive->media = ide_disk; | ||
115 | |||
116 | if (!ata_id_has_unload(drive->id)) | ||
117 | drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; | ||
118 | |||
119 | printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m, | ||
120 | is_cfa ? "CFA" : "ATA"); | ||
121 | } | ||
122 | |||
123 | static void ide_classify_atapi_dev(ide_drive_t *drive) | ||
124 | { | ||
125 | u16 *id = drive->id; | ||
126 | char *m = (char *)&id[ATA_ID_PROD]; | ||
127 | u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; | ||
128 | |||
129 | printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m); | ||
130 | switch (type) { | ||
131 | case ide_floppy: | ||
132 | if (!strstr(m, "CD-ROM")) { | ||
133 | if (!strstr(m, "oppy") && | ||
134 | !strstr(m, "poyp") && | ||
135 | !strstr(m, "ZIP")) | ||
136 | printk(KERN_CONT "cdrom or floppy?, assuming "); | ||
137 | if (drive->media != ide_cdrom) { | ||
138 | printk(KERN_CONT "FLOPPY"); | ||
139 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | /* Early cdrom models used zero */ | ||
144 | type = ide_cdrom; | ||
145 | case ide_cdrom: | ||
146 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
147 | #ifdef CONFIG_PPC | ||
148 | /* kludge for Apple PowerBook internal zip */ | ||
149 | if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { | ||
150 | printk(KERN_CONT "FLOPPY"); | ||
151 | type = ide_floppy; | ||
152 | break; | ||
153 | } | ||
154 | #endif | ||
155 | printk(KERN_CONT "CD/DVD-ROM"); | ||
156 | break; | ||
157 | case ide_tape: | ||
158 | printk(KERN_CONT "TAPE"); | ||
159 | break; | ||
160 | case ide_optical: | ||
161 | printk(KERN_CONT "OPTICAL"); | ||
162 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
163 | break; | ||
164 | default: | ||
165 | printk(KERN_CONT "UNKNOWN (type %d)", type); | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | printk(KERN_CONT " drive\n"); | ||
170 | drive->media = type; | ||
171 | /* an ATAPI device ignores DRDY */ | ||
172 | drive->ready_stat = 0; | ||
173 | if (ata_id_cdb_intr(id)) | ||
174 | drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; | ||
175 | drive->dev_flags |= IDE_DFLAG_DOORLOCKING; | ||
176 | /* we don't do head unloading on ATAPI devices */ | ||
177 | drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; | ||
178 | } | ||
179 | |||
104 | /** | 180 | /** |
105 | * do_identify - identify a drive | 181 | * do_identify - identify a drive |
106 | * @drive: drive to identify | 182 | * @drive: drive to identify |
@@ -117,7 +193,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd) | |||
117 | u16 *id = drive->id; | 193 | u16 *id = drive->id; |
118 | char *m = (char *)&id[ATA_ID_PROD]; | 194 | char *m = (char *)&id[ATA_ID_PROD]; |
119 | unsigned long flags; | 195 | unsigned long flags; |
120 | int bswap = 1, is_cfa; | 196 | int bswap = 1; |
121 | 197 | ||
122 | /* local CPU only; some systems need this */ | 198 | /* local CPU only; some systems need this */ |
123 | local_irq_save(flags); | 199 | local_irq_save(flags); |
@@ -154,91 +230,23 @@ static void do_identify(ide_drive_t *drive, u8 cmd) | |||
154 | if (strstr(m, "E X A B Y T E N E S T")) | 230 | if (strstr(m, "E X A B Y T E N E S T")) |
155 | goto err_misc; | 231 | goto err_misc; |
156 | 232 | ||
157 | printk(KERN_INFO "%s: %s, ", drive->name, m); | ||
158 | |||
159 | drive->dev_flags |= IDE_DFLAG_PRESENT; | 233 | drive->dev_flags |= IDE_DFLAG_PRESENT; |
160 | drive->dev_flags &= ~IDE_DFLAG_DEAD; | 234 | drive->dev_flags &= ~IDE_DFLAG_DEAD; |
161 | 235 | ||
162 | /* | 236 | /* |
163 | * Check for an ATAPI device | 237 | * Check for an ATAPI device |
164 | */ | 238 | */ |
165 | if (cmd == ATA_CMD_ID_ATAPI) { | 239 | if (cmd == ATA_CMD_ID_ATAPI) |
166 | u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; | 240 | ide_classify_atapi_dev(drive); |
167 | 241 | else | |
168 | printk(KERN_CONT "ATAPI "); | ||
169 | switch (type) { | ||
170 | case ide_floppy: | ||
171 | if (!strstr(m, "CD-ROM")) { | ||
172 | if (!strstr(m, "oppy") && | ||
173 | !strstr(m, "poyp") && | ||
174 | !strstr(m, "ZIP")) | ||
175 | printk(KERN_CONT "cdrom or floppy?, assuming "); | ||
176 | if (drive->media != ide_cdrom) { | ||
177 | printk(KERN_CONT "FLOPPY"); | ||
178 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
179 | break; | ||
180 | } | ||
181 | } | ||
182 | /* Early cdrom models used zero */ | ||
183 | type = ide_cdrom; | ||
184 | case ide_cdrom: | ||
185 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
186 | #ifdef CONFIG_PPC | ||
187 | /* kludge for Apple PowerBook internal zip */ | ||
188 | if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { | ||
189 | printk(KERN_CONT "FLOPPY"); | ||
190 | type = ide_floppy; | ||
191 | break; | ||
192 | } | ||
193 | #endif | ||
194 | printk(KERN_CONT "CD/DVD-ROM"); | ||
195 | break; | ||
196 | case ide_tape: | ||
197 | printk(KERN_CONT "TAPE"); | ||
198 | break; | ||
199 | case ide_optical: | ||
200 | printk(KERN_CONT "OPTICAL"); | ||
201 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
202 | break; | ||
203 | default: | ||
204 | printk(KERN_CONT "UNKNOWN (type %d)", type); | ||
205 | break; | ||
206 | } | ||
207 | printk(KERN_CONT " drive\n"); | ||
208 | drive->media = type; | ||
209 | /* an ATAPI device ignores DRDY */ | ||
210 | drive->ready_stat = 0; | ||
211 | if (ata_id_cdb_intr(id)) | ||
212 | drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; | ||
213 | drive->dev_flags |= IDE_DFLAG_DOORLOCKING; | ||
214 | /* we don't do head unloading on ATAPI devices */ | ||
215 | drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | /* | 242 | /* |
220 | * Not an ATAPI device: looks like a "regular" hard disk | 243 | * Not an ATAPI device: looks like a "regular" hard disk |
221 | */ | 244 | */ |
222 | 245 | ide_classify_ata_dev(drive); | |
223 | is_cfa = ata_id_is_cfa(id); | ||
224 | |||
225 | /* CF devices are *not* removable in Linux definition of the term */ | ||
226 | if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) | ||
227 | drive->dev_flags |= IDE_DFLAG_REMOVABLE; | ||
228 | |||
229 | drive->media = ide_disk; | ||
230 | |||
231 | if (!ata_id_has_unload(drive->id)) | ||
232 | drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; | ||
233 | |||
234 | printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA"); | ||
235 | |||
236 | return; | 246 | return; |
237 | |||
238 | err_misc: | 247 | err_misc: |
239 | kfree(id); | 248 | kfree(id); |
240 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 249 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
241 | return; | ||
242 | } | 250 | } |
243 | 251 | ||
244 | /** | 252 | /** |
@@ -641,14 +649,9 @@ static int ide_register_port(ide_hwif_t *hwif) | |||
641 | /* register with global device tree */ | 649 | /* register with global device tree */ |
642 | dev_set_name(&hwif->gendev, hwif->name); | 650 | dev_set_name(&hwif->gendev, hwif->name); |
643 | hwif->gendev.driver_data = hwif; | 651 | hwif->gendev.driver_data = hwif; |
644 | if (hwif->gendev.parent == NULL) { | 652 | hwif->gendev.parent = hwif->dev; |
645 | if (hwif->dev) | ||
646 | hwif->gendev.parent = hwif->dev; | ||
647 | else | ||
648 | /* Would like to do = &device_legacy */ | ||
649 | hwif->gendev.parent = NULL; | ||
650 | } | ||
651 | hwif->gendev.release = hwif_release_dev; | 653 | hwif->gendev.release = hwif_release_dev; |
654 | |||
652 | ret = device_register(&hwif->gendev); | 655 | ret = device_register(&hwif->gendev); |
653 | if (ret < 0) { | 656 | if (ret < 0) { |
654 | printk(KERN_WARNING "IDE: %s: device_register error: %d\n", | 657 | printk(KERN_WARNING "IDE: %s: device_register error: %d\n", |
@@ -878,8 +881,7 @@ static int ide_init_queue(ide_drive_t *drive) | |||
878 | * do not. | 881 | * do not. |
879 | */ | 882 | */ |
880 | 883 | ||
881 | q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock, | 884 | q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif)); |
882 | hwif_to_node(hwif)); | ||
883 | if (!q) | 885 | if (!q) |
884 | return 1; | 886 | return 1; |
885 | 887 | ||
@@ -1139,8 +1141,6 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data) | |||
1139 | 1141 | ||
1140 | if (drive->media == ide_disk) | 1142 | if (drive->media == ide_disk) |
1141 | request_module("ide-disk"); | 1143 | request_module("ide-disk"); |
1142 | if (drive->dev_flags & IDE_DFLAG_SCSI) | ||
1143 | request_module("ide-scsi"); | ||
1144 | if (drive->media == ide_cdrom || drive->media == ide_optical) | 1144 | if (drive->media == ide_cdrom || drive->media == ide_optical) |
1145 | request_module("ide-cd"); | 1145 | request_module("ide-cd"); |
1146 | if (drive->media == ide_tape) | 1146 | if (drive->media == ide_tape) |
@@ -1417,58 +1417,6 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) | |||
1417 | } | 1417 | } |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static ssize_t store_delete_devices(struct device *portdev, | ||
1421 | struct device_attribute *attr, | ||
1422 | const char *buf, size_t n) | ||
1423 | { | ||
1424 | ide_hwif_t *hwif = dev_get_drvdata(portdev); | ||
1425 | |||
1426 | if (strncmp(buf, "1", n)) | ||
1427 | return -EINVAL; | ||
1428 | |||
1429 | ide_port_unregister_devices(hwif); | ||
1430 | |||
1431 | return n; | ||
1432 | }; | ||
1433 | |||
1434 | static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); | ||
1435 | |||
1436 | static ssize_t store_scan(struct device *portdev, | ||
1437 | struct device_attribute *attr, | ||
1438 | const char *buf, size_t n) | ||
1439 | { | ||
1440 | ide_hwif_t *hwif = dev_get_drvdata(portdev); | ||
1441 | |||
1442 | if (strncmp(buf, "1", n)) | ||
1443 | return -EINVAL; | ||
1444 | |||
1445 | ide_port_unregister_devices(hwif); | ||
1446 | ide_port_scan(hwif); | ||
1447 | |||
1448 | return n; | ||
1449 | }; | ||
1450 | |||
1451 | static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); | ||
1452 | |||
1453 | static struct device_attribute *ide_port_attrs[] = { | ||
1454 | &dev_attr_delete_devices, | ||
1455 | &dev_attr_scan, | ||
1456 | NULL | ||
1457 | }; | ||
1458 | |||
1459 | static int ide_sysfs_register_port(ide_hwif_t *hwif) | ||
1460 | { | ||
1461 | int i, uninitialized_var(rc); | ||
1462 | |||
1463 | for (i = 0; ide_port_attrs[i]; i++) { | ||
1464 | rc = device_create_file(hwif->portdev, ide_port_attrs[i]); | ||
1465 | if (rc) | ||
1466 | break; | ||
1467 | } | ||
1468 | |||
1469 | return rc; | ||
1470 | } | ||
1471 | |||
1472 | static unsigned int ide_indexes; | 1420 | static unsigned int ide_indexes; |
1473 | 1421 | ||
1474 | /** | 1422 | /** |
@@ -1655,9 +1603,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
1655 | if (hwif == NULL) | 1603 | if (hwif == NULL) |
1656 | continue; | 1604 | continue; |
1657 | 1605 | ||
1658 | if (hwif->chipset == ide_unknown) | ||
1659 | hwif->chipset = ide_generic; | ||
1660 | |||
1661 | if (hwif->present) | 1606 | if (hwif->present) |
1662 | hwif_register_devices(hwif); | 1607 | hwif_register_devices(hwif); |
1663 | } | 1608 | } |
diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c new file mode 100644 index 000000000000..883ffacaf45a --- /dev/null +++ b/drivers/ide/ide-sysfs.c | |||
@@ -0,0 +1,125 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/ide.h> | ||
3 | |||
4 | char *ide_media_string(ide_drive_t *drive) | ||
5 | { | ||
6 | switch (drive->media) { | ||
7 | case ide_disk: | ||
8 | return "disk"; | ||
9 | case ide_cdrom: | ||
10 | return "cdrom"; | ||
11 | case ide_tape: | ||
12 | return "tape"; | ||
13 | case ide_floppy: | ||
14 | return "floppy"; | ||
15 | case ide_optical: | ||
16 | return "optical"; | ||
17 | default: | ||
18 | return "UNKNOWN"; | ||
19 | } | ||
20 | } | ||
21 | |||
22 | static ssize_t media_show(struct device *dev, struct device_attribute *attr, | ||
23 | char *buf) | ||
24 | { | ||
25 | ide_drive_t *drive = to_ide_device(dev); | ||
26 | return sprintf(buf, "%s\n", ide_media_string(drive)); | ||
27 | } | ||
28 | |||
29 | static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, | ||
30 | char *buf) | ||
31 | { | ||
32 | ide_drive_t *drive = to_ide_device(dev); | ||
33 | return sprintf(buf, "%s\n", drive->name); | ||
34 | } | ||
35 | |||
36 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | ||
37 | char *buf) | ||
38 | { | ||
39 | ide_drive_t *drive = to_ide_device(dev); | ||
40 | return sprintf(buf, "ide:m-%s\n", ide_media_string(drive)); | ||
41 | } | ||
42 | |||
43 | static ssize_t model_show(struct device *dev, struct device_attribute *attr, | ||
44 | char *buf) | ||
45 | { | ||
46 | ide_drive_t *drive = to_ide_device(dev); | ||
47 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); | ||
48 | } | ||
49 | |||
50 | static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, | ||
51 | char *buf) | ||
52 | { | ||
53 | ide_drive_t *drive = to_ide_device(dev); | ||
54 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); | ||
55 | } | ||
56 | |||
57 | static ssize_t serial_show(struct device *dev, struct device_attribute *attr, | ||
58 | char *buf) | ||
59 | { | ||
60 | ide_drive_t *drive = to_ide_device(dev); | ||
61 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); | ||
62 | } | ||
63 | |||
64 | struct device_attribute ide_dev_attrs[] = { | ||
65 | __ATTR_RO(media), | ||
66 | __ATTR_RO(drivename), | ||
67 | __ATTR_RO(modalias), | ||
68 | __ATTR_RO(model), | ||
69 | __ATTR_RO(firmware), | ||
70 | __ATTR(serial, 0400, serial_show, NULL), | ||
71 | __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), | ||
72 | __ATTR_NULL | ||
73 | }; | ||
74 | |||
75 | static ssize_t store_delete_devices(struct device *portdev, | ||
76 | struct device_attribute *attr, | ||
77 | const char *buf, size_t n) | ||
78 | { | ||
79 | ide_hwif_t *hwif = dev_get_drvdata(portdev); | ||
80 | |||
81 | if (strncmp(buf, "1", n)) | ||
82 | return -EINVAL; | ||
83 | |||
84 | ide_port_unregister_devices(hwif); | ||
85 | |||
86 | return n; | ||
87 | }; | ||
88 | |||
89 | static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); | ||
90 | |||
91 | static ssize_t store_scan(struct device *portdev, | ||
92 | struct device_attribute *attr, | ||
93 | const char *buf, size_t n) | ||
94 | { | ||
95 | ide_hwif_t *hwif = dev_get_drvdata(portdev); | ||
96 | |||
97 | if (strncmp(buf, "1", n)) | ||
98 | return -EINVAL; | ||
99 | |||
100 | ide_port_unregister_devices(hwif); | ||
101 | ide_port_scan(hwif); | ||
102 | |||
103 | return n; | ||
104 | }; | ||
105 | |||
106 | static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); | ||
107 | |||
108 | static struct device_attribute *ide_port_attrs[] = { | ||
109 | &dev_attr_delete_devices, | ||
110 | &dev_attr_scan, | ||
111 | NULL | ||
112 | }; | ||
113 | |||
114 | int ide_sysfs_register_port(ide_hwif_t *hwif) | ||
115 | { | ||
116 | int i, uninitialized_var(rc); | ||
117 | |||
118 | for (i = 0; ide_port_attrs[i]; i++) { | ||
119 | rc = device_create_file(hwif->portdev, ide_port_attrs[i]); | ||
120 | if (rc) | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | return rc; | ||
125 | } | ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index a2d470eb2b55..5d2aa22cd6e4 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -694,7 +694,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, | |||
694 | 694 | ||
695 | pc->retries++; | 695 | pc->retries++; |
696 | 696 | ||
697 | return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL); | 697 | return ide_issue_pc(drive); |
698 | } | 698 | } |
699 | 699 | ||
700 | /* A mode sense command is used to "sense" tape parameters. */ | 700 | /* A mode sense command is used to "sense" tape parameters. */ |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index f0f09f702e9c..46a2d4ca812b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -440,81 +440,13 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv) | |||
440 | return 1; | 440 | return 1; |
441 | } | 441 | } |
442 | 442 | ||
443 | static char *media_string(ide_drive_t *drive) | ||
444 | { | ||
445 | switch (drive->media) { | ||
446 | case ide_disk: | ||
447 | return "disk"; | ||
448 | case ide_cdrom: | ||
449 | return "cdrom"; | ||
450 | case ide_tape: | ||
451 | return "tape"; | ||
452 | case ide_floppy: | ||
453 | return "floppy"; | ||
454 | case ide_optical: | ||
455 | return "optical"; | ||
456 | default: | ||
457 | return "UNKNOWN"; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
462 | { | ||
463 | ide_drive_t *drive = to_ide_device(dev); | ||
464 | return sprintf(buf, "%s\n", media_string(drive)); | ||
465 | } | ||
466 | |||
467 | static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
468 | { | ||
469 | ide_drive_t *drive = to_ide_device(dev); | ||
470 | return sprintf(buf, "%s\n", drive->name); | ||
471 | } | ||
472 | |||
473 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
474 | { | ||
475 | ide_drive_t *drive = to_ide_device(dev); | ||
476 | return sprintf(buf, "ide:m-%s\n", media_string(drive)); | ||
477 | } | ||
478 | |||
479 | static ssize_t model_show(struct device *dev, struct device_attribute *attr, | ||
480 | char *buf) | ||
481 | { | ||
482 | ide_drive_t *drive = to_ide_device(dev); | ||
483 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); | ||
484 | } | ||
485 | |||
486 | static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, | ||
487 | char *buf) | ||
488 | { | ||
489 | ide_drive_t *drive = to_ide_device(dev); | ||
490 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); | ||
491 | } | ||
492 | |||
493 | static ssize_t serial_show(struct device *dev, struct device_attribute *attr, | ||
494 | char *buf) | ||
495 | { | ||
496 | ide_drive_t *drive = to_ide_device(dev); | ||
497 | return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); | ||
498 | } | ||
499 | |||
500 | static struct device_attribute ide_dev_attrs[] = { | ||
501 | __ATTR_RO(media), | ||
502 | __ATTR_RO(drivename), | ||
503 | __ATTR_RO(modalias), | ||
504 | __ATTR_RO(model), | ||
505 | __ATTR_RO(firmware), | ||
506 | __ATTR(serial, 0400, serial_show, NULL), | ||
507 | __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), | ||
508 | __ATTR_NULL | ||
509 | }; | ||
510 | |||
511 | static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) | 443 | static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) |
512 | { | 444 | { |
513 | ide_drive_t *drive = to_ide_device(dev); | 445 | ide_drive_t *drive = to_ide_device(dev); |
514 | 446 | ||
515 | add_uevent_var(env, "MEDIA=%s", media_string(drive)); | 447 | add_uevent_var(env, "MEDIA=%s", ide_media_string(drive)); |
516 | add_uevent_var(env, "DRIVENAME=%s", drive->name); | 448 | add_uevent_var(env, "DRIVENAME=%s", drive->name); |
517 | add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); | 449 | add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive)); |
518 | return 0; | 450 | return 0; |
519 | } | 451 | } |
520 | 452 | ||
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 13b63e7fa353..b4ef218072cd 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -216,16 +216,17 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { | |||
216 | #endif /* __BIG_ENDIAN */ | 216 | #endif /* __BIG_ENDIAN */ |
217 | 217 | ||
218 | static const struct ide_port_ops tx4938ide_port_ops = { | 218 | static const struct ide_port_ops tx4938ide_port_ops = { |
219 | .set_pio_mode = tx4938ide_set_pio_mode, | 219 | .set_pio_mode = tx4938ide_set_pio_mode, |
220 | }; | 220 | }; |
221 | 221 | ||
222 | static const struct ide_port_info tx4938ide_port_info __initdata = { | 222 | static const struct ide_port_info tx4938ide_port_info __initdata = { |
223 | .port_ops = &tx4938ide_port_ops, | 223 | .port_ops = &tx4938ide_port_ops, |
224 | #ifdef __BIG_ENDIAN | 224 | #ifdef __BIG_ENDIAN |
225 | .tp_ops = &tx4938ide_tp_ops, | 225 | .tp_ops = &tx4938ide_tp_ops, |
226 | #endif | 226 | #endif |
227 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | 227 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, |
228 | .pio_mask = ATA_PIO5, | 228 | .pio_mask = ATA_PIO5, |
229 | .chipset = ide_generic, | ||
229 | }; | 230 | }; |
230 | 231 | ||
231 | static int __init tx4938ide_probe(struct platform_device *pdev) | 232 | static int __init tx4938ide_probe(struct platform_device *pdev) |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 97cd9e0f66f6..4a8c5a21bd4c 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -623,33 +623,34 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { | |||
623 | #endif /* __LITTLE_ENDIAN */ | 623 | #endif /* __LITTLE_ENDIAN */ |
624 | 624 | ||
625 | static const struct ide_port_ops tx4939ide_port_ops = { | 625 | static const struct ide_port_ops tx4939ide_port_ops = { |
626 | .set_pio_mode = tx4939ide_set_pio_mode, | 626 | .set_pio_mode = tx4939ide_set_pio_mode, |
627 | .set_dma_mode = tx4939ide_set_dma_mode, | 627 | .set_dma_mode = tx4939ide_set_dma_mode, |
628 | .clear_irq = tx4939ide_clear_irq, | 628 | .clear_irq = tx4939ide_clear_irq, |
629 | .cable_detect = tx4939ide_cable_detect, | 629 | .cable_detect = tx4939ide_cable_detect, |
630 | }; | 630 | }; |
631 | 631 | ||
632 | static const struct ide_dma_ops tx4939ide_dma_ops = { | 632 | static const struct ide_dma_ops tx4939ide_dma_ops = { |
633 | .dma_host_set = tx4939ide_dma_host_set, | 633 | .dma_host_set = tx4939ide_dma_host_set, |
634 | .dma_setup = tx4939ide_dma_setup, | 634 | .dma_setup = tx4939ide_dma_setup, |
635 | .dma_exec_cmd = ide_dma_exec_cmd, | 635 | .dma_exec_cmd = ide_dma_exec_cmd, |
636 | .dma_start = ide_dma_start, | 636 | .dma_start = ide_dma_start, |
637 | .dma_end = tx4939ide_dma_end, | 637 | .dma_end = tx4939ide_dma_end, |
638 | .dma_test_irq = tx4939ide_dma_test_irq, | 638 | .dma_test_irq = tx4939ide_dma_test_irq, |
639 | .dma_lost_irq = ide_dma_lost_irq, | 639 | .dma_lost_irq = ide_dma_lost_irq, |
640 | .dma_timeout = ide_dma_timeout, | 640 | .dma_timeout = ide_dma_timeout, |
641 | }; | 641 | }; |
642 | 642 | ||
643 | static const struct ide_port_info tx4939ide_port_info __initdata = { | 643 | static const struct ide_port_info tx4939ide_port_info __initdata = { |
644 | .init_hwif = tx4939ide_init_hwif, | 644 | .init_hwif = tx4939ide_init_hwif, |
645 | .init_dma = tx4939ide_init_dma, | 645 | .init_dma = tx4939ide_init_dma, |
646 | .port_ops = &tx4939ide_port_ops, | 646 | .port_ops = &tx4939ide_port_ops, |
647 | .dma_ops = &tx4939ide_dma_ops, | 647 | .dma_ops = &tx4939ide_dma_ops, |
648 | .tp_ops = &tx4939ide_tp_ops, | 648 | .tp_ops = &tx4939ide_tp_ops, |
649 | .host_flags = IDE_HFLAG_MMIO, | 649 | .host_flags = IDE_HFLAG_MMIO, |
650 | .pio_mask = ATA_PIO4, | 650 | .pio_mask = ATA_PIO4, |
651 | .mwdma_mask = ATA_MWDMA2, | 651 | .mwdma_mask = ATA_MWDMA2, |
652 | .udma_mask = ATA_UDMA5, | 652 | .udma_mask = ATA_UDMA5, |
653 | .chipset = ide_generic, | ||
653 | }; | 654 | }; |
654 | 655 | ||
655 | static int __init tx4939ide_probe(struct platform_device *pdev) | 656 | static int __init tx4939ide_probe(struct platform_device *pdev) |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 9f7896a25f1b..c4918b86ed19 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * Driver for Option High Speed Mobile Devices. | 3 | * Driver for Option High Speed Mobile Devices. |
4 | * | 4 | * |
5 | * Copyright (C) 2008 Option International | 5 | * Copyright (C) 2008 Option International |
6 | * Filip Aben <f.aben@option.com> | ||
7 | * Denis Joseph Barrow <d.barow@option.com> | ||
6 | * Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd) | 8 | * Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd) |
7 | * <ajb@spheresystems.co.uk> | 9 | * <ajb@spheresystems.co.uk> |
8 | * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> | 10 | * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> |
@@ -39,8 +41,11 @@ | |||
39 | * port is opened, as this have a huge impact on the network port | 41 | * port is opened, as this have a huge impact on the network port |
40 | * throughput. | 42 | * throughput. |
41 | * | 43 | * |
42 | * Interface 2: Standard modem interface - circuit switched interface, should | 44 | * Interface 2: Standard modem interface - circuit switched interface, this |
43 | * not be used. | 45 | * can be used to make a standard ppp connection however it |
46 | * should not be used in conjunction with the IP network interface | ||
47 | * enabled for USB performance reasons i.e. if using this set | ||
48 | * ideally disable_net=1. | ||
44 | * | 49 | * |
45 | *****************************************************************************/ | 50 | *****************************************************************************/ |
46 | 51 | ||
@@ -63,6 +68,8 @@ | |||
63 | #include <linux/usb/cdc.h> | 68 | #include <linux/usb/cdc.h> |
64 | #include <net/arp.h> | 69 | #include <net/arp.h> |
65 | #include <asm/byteorder.h> | 70 | #include <asm/byteorder.h> |
71 | #include <linux/serial_core.h> | ||
72 | #include <linux/serial.h> | ||
66 | 73 | ||
67 | 74 | ||
68 | #define DRIVER_VERSION "1.2" | 75 | #define DRIVER_VERSION "1.2" |
@@ -182,6 +189,41 @@ enum rx_ctrl_state{ | |||
182 | RX_PENDING | 189 | RX_PENDING |
183 | }; | 190 | }; |
184 | 191 | ||
192 | #define BM_REQUEST_TYPE (0xa1) | ||
193 | #define B_NOTIFICATION (0x20) | ||
194 | #define W_VALUE (0x0) | ||
195 | #define W_INDEX (0x2) | ||
196 | #define W_LENGTH (0x2) | ||
197 | |||
198 | #define B_OVERRUN (0x1<<6) | ||
199 | #define B_PARITY (0x1<<5) | ||
200 | #define B_FRAMING (0x1<<4) | ||
201 | #define B_RING_SIGNAL (0x1<<3) | ||
202 | #define B_BREAK (0x1<<2) | ||
203 | #define B_TX_CARRIER (0x1<<1) | ||
204 | #define B_RX_CARRIER (0x1<<0) | ||
205 | |||
206 | struct hso_serial_state_notification { | ||
207 | u8 bmRequestType; | ||
208 | u8 bNotification; | ||
209 | u16 wValue; | ||
210 | u16 wIndex; | ||
211 | u16 wLength; | ||
212 | u16 UART_state_bitmap; | ||
213 | } __attribute__((packed)); | ||
214 | |||
215 | struct hso_tiocmget { | ||
216 | struct mutex mutex; | ||
217 | wait_queue_head_t waitq; | ||
218 | int intr_completed; | ||
219 | struct usb_endpoint_descriptor *endp; | ||
220 | struct urb *urb; | ||
221 | struct hso_serial_state_notification serial_state_notification; | ||
222 | u16 prev_UART_state_bitmap; | ||
223 | struct uart_icount icount; | ||
224 | }; | ||
225 | |||
226 | |||
185 | struct hso_serial { | 227 | struct hso_serial { |
186 | struct hso_device *parent; | 228 | struct hso_device *parent; |
187 | int magic; | 229 | int magic; |
@@ -219,6 +261,7 @@ struct hso_serial { | |||
219 | spinlock_t serial_lock; | 261 | spinlock_t serial_lock; |
220 | 262 | ||
221 | int (*write_data) (struct hso_serial *serial); | 263 | int (*write_data) (struct hso_serial *serial); |
264 | struct hso_tiocmget *tiocmget; | ||
222 | /* Hacks required to get flow control | 265 | /* Hacks required to get flow control |
223 | * working on the serial receive buffers | 266 | * working on the serial receive buffers |
224 | * so as not to drop characters on the floor. | 267 | * so as not to drop characters on the floor. |
@@ -305,7 +348,7 @@ static void async_get_intf(struct work_struct *data); | |||
305 | static void async_put_intf(struct work_struct *data); | 348 | static void async_put_intf(struct work_struct *data); |
306 | static int hso_put_activity(struct hso_device *hso_dev); | 349 | static int hso_put_activity(struct hso_device *hso_dev); |
307 | static int hso_get_activity(struct hso_device *hso_dev); | 350 | static int hso_get_activity(struct hso_device *hso_dev); |
308 | 351 | static void tiocmget_intr_callback(struct urb *urb); | |
309 | /*****************************************************************************/ | 352 | /*****************************************************************************/ |
310 | /* Helping functions */ | 353 | /* Helping functions */ |
311 | /*****************************************************************************/ | 354 | /*****************************************************************************/ |
@@ -362,8 +405,6 @@ static struct tty_driver *tty_drv; | |||
362 | static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS]; | 405 | static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS]; |
363 | static struct hso_device *network_table[HSO_MAX_NET_DEVICES]; | 406 | static struct hso_device *network_table[HSO_MAX_NET_DEVICES]; |
364 | static spinlock_t serial_table_lock; | 407 | static spinlock_t serial_table_lock; |
365 | static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS]; | ||
366 | static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS]; | ||
367 | 408 | ||
368 | static const s32 default_port_spec[] = { | 409 | static const s32 default_port_spec[] = { |
369 | HSO_INTF_MUX | HSO_PORT_NETWORK, | 410 | HSO_INTF_MUX | HSO_PORT_NETWORK, |
@@ -1009,23 +1050,11 @@ static void read_bulk_callback(struct urb *urb) | |||
1009 | 1050 | ||
1010 | /* Serial driver functions */ | 1051 | /* Serial driver functions */ |
1011 | 1052 | ||
1012 | static void _hso_serial_set_termios(struct tty_struct *tty, | 1053 | static void hso_init_termios(struct ktermios *termios) |
1013 | struct ktermios *old) | ||
1014 | { | 1054 | { |
1015 | struct hso_serial *serial = get_serial_by_tty(tty); | ||
1016 | struct ktermios *termios; | ||
1017 | |||
1018 | if ((!tty) || (!tty->termios) || (!serial)) { | ||
1019 | printk(KERN_ERR "%s: no tty structures", __func__); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | D4("port %d", serial->minor); | ||
1024 | |||
1025 | /* | 1055 | /* |
1026 | * The default requirements for this device are: | 1056 | * The default requirements for this device are: |
1027 | */ | 1057 | */ |
1028 | termios = tty->termios; | ||
1029 | termios->c_iflag &= | 1058 | termios->c_iflag &= |
1030 | ~(IGNBRK /* disable ignore break */ | 1059 | ~(IGNBRK /* disable ignore break */ |
1031 | | BRKINT /* disable break causes interrupt */ | 1060 | | BRKINT /* disable break causes interrupt */ |
@@ -1057,15 +1086,38 @@ static void _hso_serial_set_termios(struct tty_struct *tty, | |||
1057 | termios->c_cflag |= CS8; /* character size 8 bits */ | 1086 | termios->c_cflag |= CS8; /* character size 8 bits */ |
1058 | 1087 | ||
1059 | /* baud rate 115200 */ | 1088 | /* baud rate 115200 */ |
1060 | tty_encode_baud_rate(serial->tty, 115200, 115200); | 1089 | tty_termios_encode_baud_rate(termios, 115200, 115200); |
1090 | } | ||
1091 | |||
1092 | static void _hso_serial_set_termios(struct tty_struct *tty, | ||
1093 | struct ktermios *old) | ||
1094 | { | ||
1095 | struct hso_serial *serial = get_serial_by_tty(tty); | ||
1096 | struct ktermios *termios; | ||
1097 | |||
1098 | if (!serial) { | ||
1099 | printk(KERN_ERR "%s: no tty structures", __func__); | ||
1100 | return; | ||
1101 | } | ||
1102 | |||
1103 | D4("port %d", serial->minor); | ||
1061 | 1104 | ||
1062 | /* | 1105 | /* |
1063 | * Force low_latency on; otherwise the pushes are scheduled; | 1106 | * Fix up unsupported bits |
1064 | * this is bad as it opens up the possibility of dropping bytes | ||
1065 | * on the floor. We don't want to drop bytes on the floor. :) | ||
1066 | */ | 1107 | */ |
1067 | serial->tty->low_latency = 1; | 1108 | termios = tty->termios; |
1068 | return; | 1109 | termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */ |
1110 | |||
1111 | termios->c_cflag &= | ||
1112 | ~(CSIZE /* no size */ | ||
1113 | | PARENB /* disable parity bit */ | ||
1114 | | CBAUD /* clear current baud rate */ | ||
1115 | | CBAUDEX); /* clear current buad rate */ | ||
1116 | |||
1117 | termios->c_cflag |= CS8; /* character size 8 bits */ | ||
1118 | |||
1119 | /* baud rate 115200 */ | ||
1120 | tty_encode_baud_rate(tty, 115200, 115200); | ||
1069 | } | 1121 | } |
1070 | 1122 | ||
1071 | static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb) | 1123 | static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb) |
@@ -1228,6 +1280,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1228 | 1280 | ||
1229 | /* sanity check */ | 1281 | /* sanity check */ |
1230 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { | 1282 | if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) { |
1283 | WARN_ON(1); | ||
1231 | tty->driver_data = NULL; | 1284 | tty->driver_data = NULL; |
1232 | D1("Failed to open port"); | 1285 | D1("Failed to open port"); |
1233 | return -ENODEV; | 1286 | return -ENODEV; |
@@ -1242,8 +1295,10 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) | |||
1242 | kref_get(&serial->parent->ref); | 1295 | kref_get(&serial->parent->ref); |
1243 | 1296 | ||
1244 | /* setup */ | 1297 | /* setup */ |
1298 | spin_lock_irq(&serial->serial_lock); | ||
1245 | tty->driver_data = serial; | 1299 | tty->driver_data = serial; |
1246 | serial->tty = tty; | 1300 | serial->tty = tty_kref_get(tty); |
1301 | spin_unlock_irq(&serial->serial_lock); | ||
1247 | 1302 | ||
1248 | /* check for port already opened, if not set the termios */ | 1303 | /* check for port already opened, if not set the termios */ |
1249 | serial->open_count++; | 1304 | serial->open_count++; |
@@ -1285,6 +1340,10 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1285 | 1340 | ||
1286 | D1("Closing serial port"); | 1341 | D1("Closing serial port"); |
1287 | 1342 | ||
1343 | /* Open failed, no close cleanup required */ | ||
1344 | if (serial == NULL) | ||
1345 | return; | ||
1346 | |||
1288 | mutex_lock(&serial->parent->mutex); | 1347 | mutex_lock(&serial->parent->mutex); |
1289 | usb_gone = serial->parent->usb_gone; | 1348 | usb_gone = serial->parent->usb_gone; |
1290 | 1349 | ||
@@ -1297,10 +1356,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) | |||
1297 | kref_put(&serial->parent->ref, hso_serial_ref_free); | 1356 | kref_put(&serial->parent->ref, hso_serial_ref_free); |
1298 | if (serial->open_count <= 0) { | 1357 | if (serial->open_count <= 0) { |
1299 | serial->open_count = 0; | 1358 | serial->open_count = 0; |
1300 | if (serial->tty) { | 1359 | spin_lock_irq(&serial->serial_lock); |
1360 | if (serial->tty == tty) { | ||
1301 | serial->tty->driver_data = NULL; | 1361 | serial->tty->driver_data = NULL; |
1302 | serial->tty = NULL; | 1362 | serial->tty = NULL; |
1363 | tty_kref_put(tty); | ||
1303 | } | 1364 | } |
1365 | spin_unlock_irq(&serial->serial_lock); | ||
1304 | if (!usb_gone) | 1366 | if (!usb_gone) |
1305 | hso_stop_serial_device(serial->parent); | 1367 | hso_stop_serial_device(serial->parent); |
1306 | tasklet_kill(&serial->unthrottle_tasklet); | 1368 | tasklet_kill(&serial->unthrottle_tasklet); |
@@ -1400,25 +1462,217 @@ static int hso_serial_chars_in_buffer(struct tty_struct *tty) | |||
1400 | 1462 | ||
1401 | return chars; | 1463 | return chars; |
1402 | } | 1464 | } |
1465 | int tiocmget_submit_urb(struct hso_serial *serial, | ||
1466 | struct hso_tiocmget *tiocmget, | ||
1467 | struct usb_device *usb) | ||
1468 | { | ||
1469 | int result; | ||
1470 | |||
1471 | if (serial->parent->usb_gone) | ||
1472 | return -ENODEV; | ||
1473 | usb_fill_int_urb(tiocmget->urb, usb, | ||
1474 | usb_rcvintpipe(usb, | ||
1475 | tiocmget->endp-> | ||
1476 | bEndpointAddress & 0x7F), | ||
1477 | &tiocmget->serial_state_notification, | ||
1478 | sizeof(struct hso_serial_state_notification), | ||
1479 | tiocmget_intr_callback, serial, | ||
1480 | tiocmget->endp->bInterval); | ||
1481 | result = usb_submit_urb(tiocmget->urb, GFP_ATOMIC); | ||
1482 | if (result) { | ||
1483 | dev_warn(&usb->dev, "%s usb_submit_urb failed %d\n", __func__, | ||
1484 | result); | ||
1485 | } | ||
1486 | return result; | ||
1487 | |||
1488 | } | ||
1489 | |||
1490 | static void tiocmget_intr_callback(struct urb *urb) | ||
1491 | { | ||
1492 | struct hso_serial *serial = urb->context; | ||
1493 | struct hso_tiocmget *tiocmget; | ||
1494 | int status = urb->status; | ||
1495 | u16 UART_state_bitmap, prev_UART_state_bitmap; | ||
1496 | struct uart_icount *icount; | ||
1497 | struct hso_serial_state_notification *serial_state_notification; | ||
1498 | struct usb_device *usb; | ||
1499 | |||
1500 | /* Sanity checks */ | ||
1501 | if (!serial) | ||
1502 | return; | ||
1503 | if (status) { | ||
1504 | log_usb_status(status, __func__); | ||
1505 | return; | ||
1506 | } | ||
1507 | tiocmget = serial->tiocmget; | ||
1508 | if (!tiocmget) | ||
1509 | return; | ||
1510 | usb = serial->parent->usb; | ||
1511 | serial_state_notification = &tiocmget->serial_state_notification; | ||
1512 | if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE || | ||
1513 | serial_state_notification->bNotification != B_NOTIFICATION || | ||
1514 | le16_to_cpu(serial_state_notification->wValue) != W_VALUE || | ||
1515 | le16_to_cpu(serial_state_notification->wIndex) != W_INDEX || | ||
1516 | le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) { | ||
1517 | dev_warn(&usb->dev, | ||
1518 | "hso received invalid serial state notification\n"); | ||
1519 | DUMP(serial_state_notification, | ||
1520 | sizeof(hso_serial_state_notifation)) | ||
1521 | } else { | ||
1522 | |||
1523 | UART_state_bitmap = le16_to_cpu(serial_state_notification-> | ||
1524 | UART_state_bitmap); | ||
1525 | prev_UART_state_bitmap = tiocmget->prev_UART_state_bitmap; | ||
1526 | icount = &tiocmget->icount; | ||
1527 | spin_lock(&serial->serial_lock); | ||
1528 | if ((UART_state_bitmap & B_OVERRUN) != | ||
1529 | (prev_UART_state_bitmap & B_OVERRUN)) | ||
1530 | icount->parity++; | ||
1531 | if ((UART_state_bitmap & B_PARITY) != | ||
1532 | (prev_UART_state_bitmap & B_PARITY)) | ||
1533 | icount->parity++; | ||
1534 | if ((UART_state_bitmap & B_FRAMING) != | ||
1535 | (prev_UART_state_bitmap & B_FRAMING)) | ||
1536 | icount->frame++; | ||
1537 | if ((UART_state_bitmap & B_RING_SIGNAL) && | ||
1538 | !(prev_UART_state_bitmap & B_RING_SIGNAL)) | ||
1539 | icount->rng++; | ||
1540 | if ((UART_state_bitmap & B_BREAK) != | ||
1541 | (prev_UART_state_bitmap & B_BREAK)) | ||
1542 | icount->brk++; | ||
1543 | if ((UART_state_bitmap & B_TX_CARRIER) != | ||
1544 | (prev_UART_state_bitmap & B_TX_CARRIER)) | ||
1545 | icount->dsr++; | ||
1546 | if ((UART_state_bitmap & B_RX_CARRIER) != | ||
1547 | (prev_UART_state_bitmap & B_RX_CARRIER)) | ||
1548 | icount->dcd++; | ||
1549 | tiocmget->prev_UART_state_bitmap = UART_state_bitmap; | ||
1550 | spin_unlock(&serial->serial_lock); | ||
1551 | tiocmget->intr_completed = 1; | ||
1552 | wake_up_interruptible(&tiocmget->waitq); | ||
1553 | } | ||
1554 | memset(serial_state_notification, 0, | ||
1555 | sizeof(struct hso_serial_state_notification)); | ||
1556 | tiocmget_submit_urb(serial, | ||
1557 | tiocmget, | ||
1558 | serial->parent->usb); | ||
1559 | } | ||
1560 | |||
1561 | /* | ||
1562 | * next few functions largely stolen from drivers/serial/serial_core.c | ||
1563 | */ | ||
1564 | /* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | ||
1565 | * - mask passed in arg for lines of interest | ||
1566 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | ||
1567 | * Caller should use TIOCGICOUNT to see which one it was | ||
1568 | */ | ||
1569 | static int | ||
1570 | hso_wait_modem_status(struct hso_serial *serial, unsigned long arg) | ||
1571 | { | ||
1572 | DECLARE_WAITQUEUE(wait, current); | ||
1573 | struct uart_icount cprev, cnow; | ||
1574 | struct hso_tiocmget *tiocmget; | ||
1575 | int ret; | ||
1576 | |||
1577 | tiocmget = serial->tiocmget; | ||
1578 | if (!tiocmget) | ||
1579 | return -ENOENT; | ||
1580 | /* | ||
1581 | * note the counters on entry | ||
1582 | */ | ||
1583 | spin_lock_irq(&serial->serial_lock); | ||
1584 | memcpy(&cprev, &tiocmget->icount, sizeof(struct uart_icount)); | ||
1585 | spin_unlock_irq(&serial->serial_lock); | ||
1586 | add_wait_queue(&tiocmget->waitq, &wait); | ||
1587 | for (;;) { | ||
1588 | spin_lock_irq(&serial->serial_lock); | ||
1589 | memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount)); | ||
1590 | spin_unlock_irq(&serial->serial_lock); | ||
1591 | set_current_state(TASK_INTERRUPTIBLE); | ||
1592 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
1593 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
1594 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd))) { | ||
1595 | ret = 0; | ||
1596 | break; | ||
1597 | } | ||
1598 | schedule(); | ||
1599 | /* see if a signal did it */ | ||
1600 | if (signal_pending(current)) { | ||
1601 | ret = -ERESTARTSYS; | ||
1602 | break; | ||
1603 | } | ||
1604 | cprev = cnow; | ||
1605 | } | ||
1606 | current->state = TASK_RUNNING; | ||
1607 | remove_wait_queue(&tiocmget->waitq, &wait); | ||
1608 | |||
1609 | return ret; | ||
1610 | } | ||
1611 | |||
1612 | /* | ||
1613 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1614 | * Return: write counters to the user passed counter struct | ||
1615 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1616 | * RI where only 0->1 is counted. | ||
1617 | */ | ||
1618 | static int hso_get_count(struct hso_serial *serial, | ||
1619 | struct serial_icounter_struct __user *icnt) | ||
1620 | { | ||
1621 | struct serial_icounter_struct icount; | ||
1622 | struct uart_icount cnow; | ||
1623 | struct hso_tiocmget *tiocmget = serial->tiocmget; | ||
1624 | |||
1625 | if (!tiocmget) | ||
1626 | return -ENOENT; | ||
1627 | spin_lock_irq(&serial->serial_lock); | ||
1628 | memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount)); | ||
1629 | spin_unlock_irq(&serial->serial_lock); | ||
1630 | |||
1631 | icount.cts = cnow.cts; | ||
1632 | icount.dsr = cnow.dsr; | ||
1633 | icount.rng = cnow.rng; | ||
1634 | icount.dcd = cnow.dcd; | ||
1635 | icount.rx = cnow.rx; | ||
1636 | icount.tx = cnow.tx; | ||
1637 | icount.frame = cnow.frame; | ||
1638 | icount.overrun = cnow.overrun; | ||
1639 | icount.parity = cnow.parity; | ||
1640 | icount.brk = cnow.brk; | ||
1641 | icount.buf_overrun = cnow.buf_overrun; | ||
1642 | |||
1643 | return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; | ||
1644 | } | ||
1645 | |||
1403 | 1646 | ||
1404 | static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file) | 1647 | static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file) |
1405 | { | 1648 | { |
1406 | unsigned int value; | 1649 | int retval; |
1407 | struct hso_serial *serial = get_serial_by_tty(tty); | 1650 | struct hso_serial *serial = get_serial_by_tty(tty); |
1408 | unsigned long flags; | 1651 | struct hso_tiocmget *tiocmget; |
1652 | u16 UART_state_bitmap; | ||
1409 | 1653 | ||
1410 | /* sanity check */ | 1654 | /* sanity check */ |
1411 | if (!serial) { | 1655 | if (!serial) { |
1412 | D1("no tty structures"); | 1656 | D1("no tty structures"); |
1413 | return -EINVAL; | 1657 | return -EINVAL; |
1414 | } | 1658 | } |
1415 | 1659 | spin_lock_irq(&serial->serial_lock); | |
1416 | spin_lock_irqsave(&serial->serial_lock, flags); | 1660 | retval = ((serial->rts_state) ? TIOCM_RTS : 0) | |
1417 | value = ((serial->rts_state) ? TIOCM_RTS : 0) | | ||
1418 | ((serial->dtr_state) ? TIOCM_DTR : 0); | 1661 | ((serial->dtr_state) ? TIOCM_DTR : 0); |
1419 | spin_unlock_irqrestore(&serial->serial_lock, flags); | 1662 | tiocmget = serial->tiocmget; |
1663 | if (tiocmget) { | ||
1420 | 1664 | ||
1421 | return value; | 1665 | UART_state_bitmap = le16_to_cpu( |
1666 | tiocmget->prev_UART_state_bitmap); | ||
1667 | if (UART_state_bitmap & B_RING_SIGNAL) | ||
1668 | retval |= TIOCM_RNG; | ||
1669 | if (UART_state_bitmap & B_RX_CARRIER) | ||
1670 | retval |= TIOCM_CD; | ||
1671 | if (UART_state_bitmap & B_TX_CARRIER) | ||
1672 | retval |= TIOCM_DSR; | ||
1673 | } | ||
1674 | spin_unlock_irq(&serial->serial_lock); | ||
1675 | return retval; | ||
1422 | } | 1676 | } |
1423 | 1677 | ||
1424 | static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, | 1678 | static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, |
@@ -1460,6 +1714,32 @@ static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file, | |||
1460 | USB_CTRL_SET_TIMEOUT); | 1714 | USB_CTRL_SET_TIMEOUT); |
1461 | } | 1715 | } |
1462 | 1716 | ||
1717 | static int hso_serial_ioctl(struct tty_struct *tty, struct file *file, | ||
1718 | unsigned int cmd, unsigned long arg) | ||
1719 | { | ||
1720 | struct hso_serial *serial = get_serial_by_tty(tty); | ||
1721 | void __user *uarg = (void __user *)arg; | ||
1722 | int ret = 0; | ||
1723 | D4("IOCTL cmd: %d, arg: %ld", cmd, arg); | ||
1724 | |||
1725 | if (!serial) | ||
1726 | return -ENODEV; | ||
1727 | switch (cmd) { | ||
1728 | case TIOCMIWAIT: | ||
1729 | ret = hso_wait_modem_status(serial, arg); | ||
1730 | break; | ||
1731 | |||
1732 | case TIOCGICOUNT: | ||
1733 | ret = hso_get_count(serial, uarg); | ||
1734 | break; | ||
1735 | default: | ||
1736 | ret = -ENOIOCTLCMD; | ||
1737 | break; | ||
1738 | } | ||
1739 | return ret; | ||
1740 | } | ||
1741 | |||
1742 | |||
1463 | /* starts a transmit */ | 1743 | /* starts a transmit */ |
1464 | static void hso_kick_transmit(struct hso_serial *serial) | 1744 | static void hso_kick_transmit(struct hso_serial *serial) |
1465 | { | 1745 | { |
@@ -1653,6 +1933,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
1653 | { | 1933 | { |
1654 | struct hso_serial *serial = urb->context; | 1934 | struct hso_serial *serial = urb->context; |
1655 | int status = urb->status; | 1935 | int status = urb->status; |
1936 | struct tty_struct *tty; | ||
1656 | 1937 | ||
1657 | /* sanity check */ | 1938 | /* sanity check */ |
1658 | if (!serial) { | 1939 | if (!serial) { |
@@ -1662,14 +1943,18 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) | |||
1662 | 1943 | ||
1663 | spin_lock(&serial->serial_lock); | 1944 | spin_lock(&serial->serial_lock); |
1664 | serial->tx_urb_used = 0; | 1945 | serial->tx_urb_used = 0; |
1946 | tty = tty_kref_get(serial->tty); | ||
1665 | spin_unlock(&serial->serial_lock); | 1947 | spin_unlock(&serial->serial_lock); |
1666 | if (status) { | 1948 | if (status) { |
1667 | log_usb_status(status, __func__); | 1949 | log_usb_status(status, __func__); |
1950 | tty_kref_put(tty); | ||
1668 | return; | 1951 | return; |
1669 | } | 1952 | } |
1670 | hso_put_activity(serial->parent); | 1953 | hso_put_activity(serial->parent); |
1671 | if (serial->tty) | 1954 | if (tty) { |
1672 | tty_wakeup(serial->tty); | 1955 | tty_wakeup(tty); |
1956 | tty_kref_put(tty); | ||
1957 | } | ||
1673 | hso_kick_transmit(serial); | 1958 | hso_kick_transmit(serial); |
1674 | 1959 | ||
1675 | D1(" "); | 1960 | D1(" "); |
@@ -1706,6 +1991,7 @@ static void ctrl_callback(struct urb *urb) | |||
1706 | struct hso_serial *serial = urb->context; | 1991 | struct hso_serial *serial = urb->context; |
1707 | struct usb_ctrlrequest *req; | 1992 | struct usb_ctrlrequest *req; |
1708 | int status = urb->status; | 1993 | int status = urb->status; |
1994 | struct tty_struct *tty; | ||
1709 | 1995 | ||
1710 | /* sanity check */ | 1996 | /* sanity check */ |
1711 | if (!serial) | 1997 | if (!serial) |
@@ -1713,9 +1999,11 @@ static void ctrl_callback(struct urb *urb) | |||
1713 | 1999 | ||
1714 | spin_lock(&serial->serial_lock); | 2000 | spin_lock(&serial->serial_lock); |
1715 | serial->tx_urb_used = 0; | 2001 | serial->tx_urb_used = 0; |
2002 | tty = tty_kref_get(serial->tty); | ||
1716 | spin_unlock(&serial->serial_lock); | 2003 | spin_unlock(&serial->serial_lock); |
1717 | if (status) { | 2004 | if (status) { |
1718 | log_usb_status(status, __func__); | 2005 | log_usb_status(status, __func__); |
2006 | tty_kref_put(tty); | ||
1719 | return; | 2007 | return; |
1720 | } | 2008 | } |
1721 | 2009 | ||
@@ -1734,25 +2022,31 @@ static void ctrl_callback(struct urb *urb) | |||
1734 | spin_unlock(&serial->serial_lock); | 2022 | spin_unlock(&serial->serial_lock); |
1735 | } else { | 2023 | } else { |
1736 | hso_put_activity(serial->parent); | 2024 | hso_put_activity(serial->parent); |
1737 | if (serial->tty) | 2025 | if (tty) |
1738 | tty_wakeup(serial->tty); | 2026 | tty_wakeup(tty); |
1739 | /* response to a write command */ | 2027 | /* response to a write command */ |
1740 | hso_kick_transmit(serial); | 2028 | hso_kick_transmit(serial); |
1741 | } | 2029 | } |
2030 | tty_kref_put(tty); | ||
1742 | } | 2031 | } |
1743 | 2032 | ||
1744 | /* handle RX data for serial port */ | 2033 | /* handle RX data for serial port */ |
1745 | static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) | 2034 | static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) |
1746 | { | 2035 | { |
1747 | struct tty_struct *tty = serial->tty; | 2036 | struct tty_struct *tty; |
1748 | int write_length_remaining = 0; | 2037 | int write_length_remaining = 0; |
1749 | int curr_write_len; | 2038 | int curr_write_len; |
2039 | |||
1750 | /* Sanity check */ | 2040 | /* Sanity check */ |
1751 | if (urb == NULL || serial == NULL) { | 2041 | if (urb == NULL || serial == NULL) { |
1752 | D1("serial = NULL"); | 2042 | D1("serial = NULL"); |
1753 | return -2; | 2043 | return -2; |
1754 | } | 2044 | } |
1755 | 2045 | ||
2046 | spin_lock(&serial->serial_lock); | ||
2047 | tty = tty_kref_get(serial->tty); | ||
2048 | spin_unlock(&serial->serial_lock); | ||
2049 | |||
1756 | /* Push data to tty */ | 2050 | /* Push data to tty */ |
1757 | if (tty) { | 2051 | if (tty) { |
1758 | write_length_remaining = urb->actual_length - | 2052 | write_length_remaining = urb->actual_length - |
@@ -1774,6 +2068,7 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) | |||
1774 | serial->curr_rx_urb_offset = 0; | 2068 | serial->curr_rx_urb_offset = 0; |
1775 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; | 2069 | serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; |
1776 | } | 2070 | } |
2071 | tty_kref_put(tty); | ||
1777 | return write_length_remaining; | 2072 | return write_length_remaining; |
1778 | } | 2073 | } |
1779 | 2074 | ||
@@ -1922,7 +2217,10 @@ static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags) | |||
1922 | serial->shared_int->use_count++; | 2217 | serial->shared_int->use_count++; |
1923 | mutex_unlock(&serial->shared_int->shared_int_lock); | 2218 | mutex_unlock(&serial->shared_int->shared_int_lock); |
1924 | } | 2219 | } |
1925 | 2220 | if (serial->tiocmget) | |
2221 | tiocmget_submit_urb(serial, | ||
2222 | serial->tiocmget, | ||
2223 | serial->parent->usb); | ||
1926 | return result; | 2224 | return result; |
1927 | } | 2225 | } |
1928 | 2226 | ||
@@ -1930,6 +2228,7 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) | |||
1930 | { | 2228 | { |
1931 | int i; | 2229 | int i; |
1932 | struct hso_serial *serial = dev2ser(hso_dev); | 2230 | struct hso_serial *serial = dev2ser(hso_dev); |
2231 | struct hso_tiocmget *tiocmget; | ||
1933 | 2232 | ||
1934 | if (!serial) | 2233 | if (!serial) |
1935 | return -ENODEV; | 2234 | return -ENODEV; |
@@ -1958,6 +2257,11 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) | |||
1958 | } | 2257 | } |
1959 | mutex_unlock(&serial->shared_int->shared_int_lock); | 2258 | mutex_unlock(&serial->shared_int->shared_int_lock); |
1960 | } | 2259 | } |
2260 | tiocmget = serial->tiocmget; | ||
2261 | if (tiocmget) { | ||
2262 | wake_up_interruptible(&tiocmget->waitq); | ||
2263 | usb_kill_urb(tiocmget->urb); | ||
2264 | } | ||
1961 | 2265 | ||
1962 | return 0; | 2266 | return 0; |
1963 | } | 2267 | } |
@@ -2304,6 +2608,20 @@ exit: | |||
2304 | return NULL; | 2608 | return NULL; |
2305 | } | 2609 | } |
2306 | 2610 | ||
2611 | static void hso_free_tiomget(struct hso_serial *serial) | ||
2612 | { | ||
2613 | struct hso_tiocmget *tiocmget = serial->tiocmget; | ||
2614 | if (tiocmget) { | ||
2615 | kfree(tiocmget); | ||
2616 | if (tiocmget->urb) { | ||
2617 | usb_free_urb(tiocmget->urb); | ||
2618 | tiocmget->urb = NULL; | ||
2619 | } | ||
2620 | serial->tiocmget = NULL; | ||
2621 | |||
2622 | } | ||
2623 | } | ||
2624 | |||
2307 | /* Frees an AT channel ( goes for both mux and non-mux ) */ | 2625 | /* Frees an AT channel ( goes for both mux and non-mux ) */ |
2308 | static void hso_free_serial_device(struct hso_device *hso_dev) | 2626 | static void hso_free_serial_device(struct hso_device *hso_dev) |
2309 | { | 2627 | { |
@@ -2322,6 +2640,7 @@ static void hso_free_serial_device(struct hso_device *hso_dev) | |||
2322 | else | 2640 | else |
2323 | mutex_unlock(&serial->shared_int->shared_int_lock); | 2641 | mutex_unlock(&serial->shared_int->shared_int_lock); |
2324 | } | 2642 | } |
2643 | hso_free_tiomget(serial); | ||
2325 | kfree(serial); | 2644 | kfree(serial); |
2326 | hso_free_device(hso_dev); | 2645 | hso_free_device(hso_dev); |
2327 | } | 2646 | } |
@@ -2333,6 +2652,7 @@ static struct hso_device *hso_create_bulk_serial_device( | |||
2333 | struct hso_device *hso_dev; | 2652 | struct hso_device *hso_dev; |
2334 | struct hso_serial *serial; | 2653 | struct hso_serial *serial; |
2335 | int num_urbs; | 2654 | int num_urbs; |
2655 | struct hso_tiocmget *tiocmget; | ||
2336 | 2656 | ||
2337 | hso_dev = hso_create_device(interface, port); | 2657 | hso_dev = hso_create_device(interface, port); |
2338 | if (!hso_dev) | 2658 | if (!hso_dev) |
@@ -2345,8 +2665,27 @@ static struct hso_device *hso_create_bulk_serial_device( | |||
2345 | serial->parent = hso_dev; | 2665 | serial->parent = hso_dev; |
2346 | hso_dev->port_data.dev_serial = serial; | 2666 | hso_dev->port_data.dev_serial = serial; |
2347 | 2667 | ||
2348 | if (port & HSO_PORT_MODEM) | 2668 | if ((port & HSO_PORT_MASK) == HSO_PORT_MODEM) { |
2349 | num_urbs = 2; | 2669 | num_urbs = 2; |
2670 | serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget), | ||
2671 | GFP_KERNEL); | ||
2672 | /* it isn't going to break our heart if serial->tiocmget | ||
2673 | * allocation fails don't bother checking this. | ||
2674 | */ | ||
2675 | if (serial->tiocmget) { | ||
2676 | tiocmget = serial->tiocmget; | ||
2677 | tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2678 | if (tiocmget->urb) { | ||
2679 | mutex_init(&tiocmget->mutex); | ||
2680 | init_waitqueue_head(&tiocmget->waitq); | ||
2681 | tiocmget->endp = hso_get_ep( | ||
2682 | interface, | ||
2683 | USB_ENDPOINT_XFER_INT, | ||
2684 | USB_DIR_IN); | ||
2685 | } else | ||
2686 | hso_free_tiomget(serial); | ||
2687 | } | ||
2688 | } | ||
2350 | else | 2689 | else |
2351 | num_urbs = 1; | 2690 | num_urbs = 1; |
2352 | 2691 | ||
@@ -2382,6 +2721,7 @@ static struct hso_device *hso_create_bulk_serial_device( | |||
2382 | exit2: | 2721 | exit2: |
2383 | hso_serial_common_free(serial); | 2722 | hso_serial_common_free(serial); |
2384 | exit: | 2723 | exit: |
2724 | hso_free_tiomget(serial); | ||
2385 | kfree(serial); | 2725 | kfree(serial); |
2386 | hso_free_device(hso_dev); | 2726 | hso_free_device(hso_dev); |
2387 | return NULL; | 2727 | return NULL; |
@@ -2786,15 +3126,20 @@ static void hso_serial_ref_free(struct kref *ref) | |||
2786 | static void hso_free_interface(struct usb_interface *interface) | 3126 | static void hso_free_interface(struct usb_interface *interface) |
2787 | { | 3127 | { |
2788 | struct hso_serial *hso_dev; | 3128 | struct hso_serial *hso_dev; |
3129 | struct tty_struct *tty; | ||
2789 | int i; | 3130 | int i; |
2790 | 3131 | ||
2791 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { | 3132 | for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { |
2792 | if (serial_table[i] | 3133 | if (serial_table[i] |
2793 | && (serial_table[i]->interface == interface)) { | 3134 | && (serial_table[i]->interface == interface)) { |
2794 | hso_dev = dev2ser(serial_table[i]); | 3135 | hso_dev = dev2ser(serial_table[i]); |
2795 | if (hso_dev->tty) | 3136 | spin_lock_irq(&hso_dev->serial_lock); |
2796 | tty_hangup(hso_dev->tty); | 3137 | tty = tty_kref_get(hso_dev->tty); |
3138 | spin_unlock_irq(&hso_dev->serial_lock); | ||
3139 | if (tty) | ||
3140 | tty_hangup(tty); | ||
2797 | mutex_lock(&hso_dev->parent->mutex); | 3141 | mutex_lock(&hso_dev->parent->mutex); |
3142 | tty_kref_put(tty); | ||
2798 | hso_dev->parent->usb_gone = 1; | 3143 | hso_dev->parent->usb_gone = 1; |
2799 | mutex_unlock(&hso_dev->parent->mutex); | 3144 | mutex_unlock(&hso_dev->parent->mutex); |
2800 | kref_put(&serial_table[i]->ref, hso_serial_ref_free); | 3145 | kref_put(&serial_table[i]->ref, hso_serial_ref_free); |
@@ -2887,6 +3232,7 @@ static const struct tty_operations hso_serial_ops = { | |||
2887 | .close = hso_serial_close, | 3232 | .close = hso_serial_close, |
2888 | .write = hso_serial_write, | 3233 | .write = hso_serial_write, |
2889 | .write_room = hso_serial_write_room, | 3234 | .write_room = hso_serial_write_room, |
3235 | .ioctl = hso_serial_ioctl, | ||
2890 | .set_termios = hso_serial_set_termios, | 3236 | .set_termios = hso_serial_set_termios, |
2891 | .chars_in_buffer = hso_serial_chars_in_buffer, | 3237 | .chars_in_buffer = hso_serial_chars_in_buffer, |
2892 | .tiocmget = hso_serial_tiocmget, | 3238 | .tiocmget = hso_serial_tiocmget, |
@@ -2939,9 +3285,7 @@ static int __init hso_init(void) | |||
2939 | tty_drv->subtype = SERIAL_TYPE_NORMAL; | 3285 | tty_drv->subtype = SERIAL_TYPE_NORMAL; |
2940 | tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 3286 | tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
2941 | tty_drv->init_termios = tty_std_termios; | 3287 | tty_drv->init_termios = tty_std_termios; |
2942 | tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 3288 | hso_init_termios(&tty_drv->init_termios); |
2943 | tty_drv->termios = hso_serial_termios; | ||
2944 | tty_drv->termios_locked = hso_serial_termios_locked; | ||
2945 | tty_set_operations(tty_drv, &hso_serial_ops); | 3289 | tty_set_operations(tty_drv, &hso_serial_ops); |
2946 | 3290 | ||
2947 | /* register the tty driver */ | 3291 | /* register the tty driver */ |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 737bd9484822..65e8294a9e29 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -200,7 +200,7 @@ static inline unsigned long fast_get_dcookie(struct path *path) | |||
200 | { | 200 | { |
201 | unsigned long cookie; | 201 | unsigned long cookie; |
202 | 202 | ||
203 | if (path->dentry->d_cookie) | 203 | if (path->dentry->d_flags & DCACHE_COOKIE) |
204 | return (unsigned long)path->dentry; | 204 | return (unsigned long)path->dentry; |
205 | get_dcookie(path, &cookie); | 205 | get_dcookie(path, &cookie); |
206 | return cookie; | 206 | return cookie; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 152d4aa9354f..b7322976d2b7 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -21,7 +21,7 @@ config SCSI | |||
21 | You also need to say Y here if you have a device which speaks | 21 | You also need to say Y here if you have a device which speaks |
22 | the SCSI protocol. Examples of this include the parallel port | 22 | the SCSI protocol. Examples of this include the parallel port |
23 | version of the IOMEGA ZIP drive, USB storage devices, Fibre | 23 | version of the IOMEGA ZIP drive, USB storage devices, Fibre |
24 | Channel, FireWire storage and the IDE-SCSI emulation driver. | 24 | Channel, and FireWire storage. |
25 | 25 | ||
26 | To compile this driver as a module, choose M here and read | 26 | To compile this driver as a module, choose M here and read |
27 | <file:Documentation/scsi/scsi.txt>. | 27 | <file:Documentation/scsi/scsi.txt>. |
@@ -101,9 +101,9 @@ config CHR_DEV_OSST | |||
101 | ---help--- | 101 | ---help--- |
102 | The OnStream SC-x0 SCSI tape drives cannot be driven by the | 102 | The OnStream SC-x0 SCSI tape drives cannot be driven by the |
103 | standard st driver, but instead need this special osst driver and | 103 | standard st driver, but instead need this special osst driver and |
104 | use the /dev/osstX char device nodes (major 206). Via usb-storage | 104 | use the /dev/osstX char device nodes (major 206). Via usb-storage, |
105 | and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives | 105 | you may be able to drive the USB-x0 and DI-x0 drives as well. |
106 | as well. Note that there is also a second generation of OnStream | 106 | Note that there is also a second generation of OnStream |
107 | tape drives (ADR-x0) that supports the standard SCSI-2 commands for | 107 | tape drives (ADR-x0) that supports the standard SCSI-2 commands for |
108 | tapes (QIC-157) and can be driven by the standard driver st. | 108 | tapes (QIC-157) and can be driven by the standard driver st. |
109 | For more information, you may have a look at the SCSI-HOWTO | 109 | For more information, you may have a look at the SCSI-HOWTO |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 1410697257cb..7461eb09a031 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -105,7 +105,6 @@ obj-$(CONFIG_SCSI_GDTH) += gdth.o | |||
105 | obj-$(CONFIG_SCSI_INITIO) += initio.o | 105 | obj-$(CONFIG_SCSI_INITIO) += initio.o |
106 | obj-$(CONFIG_SCSI_INIA100) += a100u2w.o | 106 | obj-$(CONFIG_SCSI_INIA100) += a100u2w.o |
107 | obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o | 107 | obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o |
108 | obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o | ||
109 | obj-$(CONFIG_SCSI_MESH) += mesh.o | 108 | obj-$(CONFIG_SCSI_MESH) += mesh.o |
110 | obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o | 109 | obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o |
111 | obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o | 110 | obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c deleted file mode 100644 index c24140aff8e7..000000000000 --- a/drivers/scsi/ide-scsi.c +++ /dev/null | |||
@@ -1,840 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il> | ||
3 | * Copyright (C) 2004-2005 Bartlomiej Zolnierkiewicz | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * Emulation of a SCSI host adapter for IDE ATAPI devices. | ||
8 | * | ||
9 | * With this driver, one can use the Linux SCSI drivers instead of the | ||
10 | * native IDE ATAPI drivers. | ||
11 | * | ||
12 | * Ver 0.1 Dec 3 96 Initial version. | ||
13 | * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation | ||
14 | * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks | ||
15 | * to Janos Farkas for pointing this out. | ||
16 | * Avoid using bitfields in structures for m68k. | ||
17 | * Added Scatter/Gather and DMA support. | ||
18 | * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives. | ||
19 | * Use variable timeout for each command. | ||
20 | * Ver 0.5 Jan 2 98 Fix previous PD/CD support. | ||
21 | * Allow disabling of SCSI-6 to SCSI-10 transformation. | ||
22 | * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer | ||
23 | * for access through /dev/sg. | ||
24 | * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation. | ||
25 | * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple | ||
26 | * detection of devices with CONFIG_SCSI_MULTI_LUN | ||
27 | * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7. | ||
28 | * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM. | ||
29 | * Ver 0.91 Jun 10 02 Fix "off by one" error in transforms | ||
30 | * Ver 0.92 Dec 31 02 Implement new SCSI mid level API | ||
31 | */ | ||
32 | |||
33 | #define IDESCSI_VERSION "0.92" | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <linux/types.h> | ||
37 | #include <linux/string.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/mm.h> | ||
40 | #include <linux/ioport.h> | ||
41 | #include <linux/blkdev.h> | ||
42 | #include <linux/errno.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/ide.h> | ||
45 | #include <linux/scatterlist.h> | ||
46 | #include <linux/delay.h> | ||
47 | #include <linux/mutex.h> | ||
48 | #include <linux/bitops.h> | ||
49 | |||
50 | #include <asm/io.h> | ||
51 | #include <asm/uaccess.h> | ||
52 | |||
53 | #include <scsi/scsi.h> | ||
54 | #include <scsi/scsi_cmnd.h> | ||
55 | #include <scsi/scsi_device.h> | ||
56 | #include <scsi/scsi_host.h> | ||
57 | #include <scsi/scsi_tcq.h> | ||
58 | #include <scsi/sg.h> | ||
59 | |||
60 | #define IDESCSI_DEBUG_LOG 0 | ||
61 | |||
62 | #if IDESCSI_DEBUG_LOG | ||
63 | #define debug_log(fmt, args...) \ | ||
64 | printk(KERN_INFO "ide-scsi: " fmt, ## args) | ||
65 | #else | ||
66 | #define debug_log(fmt, args...) do {} while (0) | ||
67 | #endif | ||
68 | |||
69 | /* | ||
70 | * SCSI command transformation layer | ||
71 | */ | ||
72 | #define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ | ||
73 | |||
74 | /* | ||
75 | * Log flags | ||
76 | */ | ||
77 | #define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ | ||
78 | |||
79 | typedef struct ide_scsi_obj { | ||
80 | ide_drive_t *drive; | ||
81 | ide_driver_t *driver; | ||
82 | struct gendisk *disk; | ||
83 | struct Scsi_Host *host; | ||
84 | |||
85 | unsigned long transform; /* SCSI cmd translation layer */ | ||
86 | unsigned long log; /* log flags */ | ||
87 | } idescsi_scsi_t; | ||
88 | |||
89 | static DEFINE_MUTEX(idescsi_ref_mutex); | ||
90 | /* Set by module param to skip cd */ | ||
91 | static int idescsi_nocd; | ||
92 | |||
93 | #define ide_scsi_g(disk) \ | ||
94 | container_of((disk)->private_data, struct ide_scsi_obj, driver) | ||
95 | |||
96 | static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) | ||
97 | { | ||
98 | struct ide_scsi_obj *scsi = NULL; | ||
99 | |||
100 | mutex_lock(&idescsi_ref_mutex); | ||
101 | scsi = ide_scsi_g(disk); | ||
102 | if (scsi) { | ||
103 | if (ide_device_get(scsi->drive)) | ||
104 | scsi = NULL; | ||
105 | else | ||
106 | scsi_host_get(scsi->host); | ||
107 | } | ||
108 | mutex_unlock(&idescsi_ref_mutex); | ||
109 | return scsi; | ||
110 | } | ||
111 | |||
112 | static void ide_scsi_put(struct ide_scsi_obj *scsi) | ||
113 | { | ||
114 | ide_drive_t *drive = scsi->drive; | ||
115 | |||
116 | mutex_lock(&idescsi_ref_mutex); | ||
117 | scsi_host_put(scsi->host); | ||
118 | ide_device_put(drive); | ||
119 | mutex_unlock(&idescsi_ref_mutex); | ||
120 | } | ||
121 | |||
122 | static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host) | ||
123 | { | ||
124 | return (idescsi_scsi_t*) (&host[1]); | ||
125 | } | ||
126 | |||
127 | static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive) | ||
128 | { | ||
129 | return scsihost_to_idescsi(ide_drive->driver_data); | ||
130 | } | ||
131 | |||
132 | static void ide_scsi_hex_dump(u8 *data, int len) | ||
133 | { | ||
134 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0); | ||
135 | } | ||
136 | |||
137 | static int idescsi_end_request(ide_drive_t *, int, int); | ||
138 | |||
139 | static void ide_scsi_callback(ide_drive_t *drive, int dsc) | ||
140 | { | ||
141 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | ||
142 | struct ide_atapi_pc *pc = drive->pc; | ||
143 | |||
144 | if (pc->flags & PC_FLAG_TIMEDOUT) | ||
145 | debug_log("%s: got timed out packet %lu at %lu\n", __func__, | ||
146 | pc->scsi_cmd->serial_number, jiffies); | ||
147 | /* end this request now - scsi should retry it*/ | ||
148 | else if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | ||
149 | printk(KERN_INFO "Packet command completed, %d bytes" | ||
150 | " transferred\n", pc->xferred); | ||
151 | |||
152 | idescsi_end_request(drive, 1, 0); | ||
153 | } | ||
154 | |||
155 | static int idescsi_check_condition(ide_drive_t *drive, | ||
156 | struct request *failed_cmd) | ||
157 | { | ||
158 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | ||
159 | struct ide_atapi_pc *pc; | ||
160 | struct request *rq; | ||
161 | u8 *buf; | ||
162 | |||
163 | /* stuff a sense request in front of our current request */ | ||
164 | pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC); | ||
165 | rq = blk_get_request(drive->queue, READ, GFP_ATOMIC); | ||
166 | buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC); | ||
167 | if (!pc || !rq || !buf) { | ||
168 | kfree(buf); | ||
169 | if (rq) | ||
170 | blk_put_request(rq); | ||
171 | kfree(pc); | ||
172 | return -ENOMEM; | ||
173 | } | ||
174 | rq->special = (char *) pc; | ||
175 | pc->rq = rq; | ||
176 | pc->buf = buf; | ||
177 | pc->c[0] = REQUEST_SENSE; | ||
178 | pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE; | ||
179 | rq->cmd_type = REQ_TYPE_SENSE; | ||
180 | rq->cmd_flags |= REQ_PREEMPT; | ||
181 | pc->timeout = jiffies + WAIT_READY; | ||
182 | /* NOTE! Save the failed packet command in "rq->buffer" */ | ||
183 | rq->buffer = (void *) failed_cmd->special; | ||
184 | pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd; | ||
185 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { | ||
186 | printk ("ide-scsi: %s: queue cmd = ", drive->name); | ||
187 | ide_scsi_hex_dump(pc->c, 6); | ||
188 | } | ||
189 | rq->rq_disk = scsi->disk; | ||
190 | rq->ref_count++; | ||
191 | memcpy(rq->cmd, pc->c, 12); | ||
192 | ide_do_drive_cmd(drive, rq); | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static ide_startstop_t | ||
197 | idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
198 | { | ||
199 | ide_hwif_t *hwif = drive->hwif; | ||
200 | |||
201 | if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) | ||
202 | /* force an abort */ | ||
203 | hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); | ||
204 | |||
205 | rq->errors++; | ||
206 | |||
207 | idescsi_end_request(drive, 0, 0); | ||
208 | |||
209 | return ide_stopped; | ||
210 | } | ||
211 | |||
212 | static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) | ||
213 | { | ||
214 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | ||
215 | struct request *rq = HWGROUP(drive)->rq; | ||
216 | struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special; | ||
217 | int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); | ||
218 | struct Scsi_Host *host; | ||
219 | int errors = rq->errors; | ||
220 | unsigned long flags; | ||
221 | |||
222 | if (!blk_special_request(rq) && !blk_sense_request(rq)) { | ||
223 | ide_end_request(drive, uptodate, nrsecs); | ||
224 | return 0; | ||
225 | } | ||
226 | ide_end_drive_cmd (drive, 0, 0); | ||
227 | if (blk_sense_request(rq)) { | ||
228 | struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer; | ||
229 | if (log) { | ||
230 | printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); | ||
231 | ide_scsi_hex_dump(pc->buf, 16); | ||
232 | } | ||
233 | memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf, | ||
234 | SCSI_SENSE_BUFFERSIZE); | ||
235 | kfree(pc->buf); | ||
236 | kfree(pc); | ||
237 | blk_put_request(rq); | ||
238 | pc = opc; | ||
239 | rq = pc->rq; | ||
240 | pc->scsi_cmd->result = (CHECK_CONDITION << 1) | | ||
241 | (((pc->flags & PC_FLAG_TIMEDOUT) ? | ||
242 | DID_TIME_OUT : | ||
243 | DID_OK) << 16); | ||
244 | } else if (pc->flags & PC_FLAG_TIMEDOUT) { | ||
245 | if (log) | ||
246 | printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n", | ||
247 | drive->name, pc->scsi_cmd->serial_number); | ||
248 | pc->scsi_cmd->result = DID_TIME_OUT << 16; | ||
249 | } else if (errors >= ERROR_MAX) { | ||
250 | pc->scsi_cmd->result = DID_ERROR << 16; | ||
251 | if (log) | ||
252 | printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number); | ||
253 | } else if (errors) { | ||
254 | if (log) | ||
255 | printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number); | ||
256 | if (!idescsi_check_condition(drive, rq)) | ||
257 | /* we started a request sense, so we'll be back, exit for now */ | ||
258 | return 0; | ||
259 | pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); | ||
260 | } else { | ||
261 | pc->scsi_cmd->result = DID_OK << 16; | ||
262 | } | ||
263 | host = pc->scsi_cmd->device->host; | ||
264 | spin_lock_irqsave(host->host_lock, flags); | ||
265 | pc->done(pc->scsi_cmd); | ||
266 | spin_unlock_irqrestore(host->host_lock, flags); | ||
267 | kfree(pc); | ||
268 | blk_put_request(rq); | ||
269 | drive->pc = NULL; | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static inline int idescsi_set_direction(struct ide_atapi_pc *pc) | ||
274 | { | ||
275 | switch (pc->c[0]) { | ||
276 | case READ_6: case READ_10: case READ_12: | ||
277 | pc->flags &= ~PC_FLAG_WRITING; | ||
278 | return 0; | ||
279 | case WRITE_6: case WRITE_10: case WRITE_12: | ||
280 | pc->flags |= PC_FLAG_WRITING; | ||
281 | return 0; | ||
282 | default: | ||
283 | return 1; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc) | ||
288 | { | ||
289 | ide_hwif_t *hwif = drive->hwif; | ||
290 | struct scatterlist *sg, *scsi_sg; | ||
291 | int segments; | ||
292 | |||
293 | if (!pc->req_xfer || pc->req_xfer % 1024) | ||
294 | return 1; | ||
295 | |||
296 | if (idescsi_set_direction(pc)) | ||
297 | return 1; | ||
298 | |||
299 | sg = hwif->sg_table; | ||
300 | scsi_sg = scsi_sglist(pc->scsi_cmd); | ||
301 | segments = scsi_sg_count(pc->scsi_cmd); | ||
302 | |||
303 | if (segments > hwif->sg_max_nents) | ||
304 | return 1; | ||
305 | |||
306 | hwif->sg_nents = segments; | ||
307 | memcpy(sg, scsi_sg, sizeof(*sg) * segments); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive, | ||
313 | struct ide_atapi_pc *pc) | ||
314 | { | ||
315 | /* Set the current packet command */ | ||
316 | drive->pc = pc; | ||
317 | |||
318 | return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * idescsi_do_request is our request handling function. | ||
323 | */ | ||
324 | static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block) | ||
325 | { | ||
326 | debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name, | ||
327 | rq->cmd[0], rq->errors); | ||
328 | debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n", | ||
329 | rq->sector, rq->nr_sectors, rq->current_nr_sectors); | ||
330 | |||
331 | if (blk_sense_request(rq) || blk_special_request(rq)) { | ||
332 | struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special; | ||
333 | |||
334 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && | ||
335 | idescsi_map_sg(drive, pc) == 0) | ||
336 | pc->flags |= PC_FLAG_DMA_OK; | ||
337 | |||
338 | return idescsi_issue_pc(drive, pc); | ||
339 | } | ||
340 | blk_dump_rq_flags(rq, "ide-scsi: unsup command"); | ||
341 | idescsi_end_request (drive, 0, 0); | ||
342 | return ide_stopped; | ||
343 | } | ||
344 | |||
345 | #ifdef CONFIG_IDE_PROC_FS | ||
346 | static ide_proc_entry_t idescsi_proc[] = { | ||
347 | { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, | ||
348 | { NULL, 0, NULL, NULL } | ||
349 | }; | ||
350 | |||
351 | #define ide_scsi_devset_get(name, field) \ | ||
352 | static int get_##name(ide_drive_t *drive) \ | ||
353 | { \ | ||
354 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); \ | ||
355 | return scsi->field; \ | ||
356 | } | ||
357 | |||
358 | #define ide_scsi_devset_set(name, field) \ | ||
359 | static int set_##name(ide_drive_t *drive, int arg) \ | ||
360 | { \ | ||
361 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); \ | ||
362 | scsi->field = arg; \ | ||
363 | return 0; \ | ||
364 | } | ||
365 | |||
366 | #define ide_scsi_devset_rw_field(_name, _field) \ | ||
367 | ide_scsi_devset_get(_name, _field); \ | ||
368 | ide_scsi_devset_set(_name, _field); \ | ||
369 | IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name); | ||
370 | |||
371 | ide_devset_rw_field(bios_cyl, bios_cyl); | ||
372 | ide_devset_rw_field(bios_head, bios_head); | ||
373 | ide_devset_rw_field(bios_sect, bios_sect); | ||
374 | |||
375 | ide_scsi_devset_rw_field(transform, transform); | ||
376 | ide_scsi_devset_rw_field(log, log); | ||
377 | |||
378 | static const struct ide_proc_devset idescsi_settings[] = { | ||
379 | IDE_PROC_DEVSET(bios_cyl, 0, 1023), | ||
380 | IDE_PROC_DEVSET(bios_head, 0, 255), | ||
381 | IDE_PROC_DEVSET(bios_sect, 0, 63), | ||
382 | IDE_PROC_DEVSET(log, 0, 1), | ||
383 | IDE_PROC_DEVSET(transform, 0, 3), | ||
384 | { 0 }, | ||
385 | }; | ||
386 | |||
387 | static ide_proc_entry_t *ide_scsi_proc_entries(ide_drive_t *drive) | ||
388 | { | ||
389 | return idescsi_proc; | ||
390 | } | ||
391 | |||
392 | static const struct ide_proc_devset *ide_scsi_proc_devsets(ide_drive_t *drive) | ||
393 | { | ||
394 | return idescsi_settings; | ||
395 | } | ||
396 | #endif | ||
397 | |||
398 | /* | ||
399 | * Driver initialization. | ||
400 | */ | ||
401 | static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) | ||
402 | { | ||
403 | clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); | ||
404 | #if IDESCSI_DEBUG_LOG | ||
405 | set_bit(IDESCSI_LOG_CMD, &scsi->log); | ||
406 | #endif /* IDESCSI_DEBUG_LOG */ | ||
407 | |||
408 | drive->pc_callback = ide_scsi_callback; | ||
409 | drive->pc_update_buffers = NULL; | ||
410 | drive->pc_io_buffers = ide_io_buffers; | ||
411 | |||
412 | ide_proc_register_driver(drive, scsi->driver); | ||
413 | } | ||
414 | |||
415 | static void ide_scsi_remove(ide_drive_t *drive) | ||
416 | { | ||
417 | struct Scsi_Host *scsihost = drive->driver_data; | ||
418 | struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); | ||
419 | struct gendisk *g = scsi->disk; | ||
420 | |||
421 | scsi_remove_host(scsihost); | ||
422 | ide_proc_unregister_driver(drive, scsi->driver); | ||
423 | |||
424 | ide_unregister_region(g); | ||
425 | |||
426 | drive->driver_data = NULL; | ||
427 | g->private_data = NULL; | ||
428 | put_disk(g); | ||
429 | |||
430 | ide_scsi_put(scsi); | ||
431 | |||
432 | drive->dev_flags &= ~IDE_DFLAG_SCSI; | ||
433 | } | ||
434 | |||
435 | static int ide_scsi_probe(ide_drive_t *); | ||
436 | |||
437 | static ide_driver_t idescsi_driver = { | ||
438 | .gen_driver = { | ||
439 | .owner = THIS_MODULE, | ||
440 | .name = "ide-scsi", | ||
441 | .bus = &ide_bus_type, | ||
442 | }, | ||
443 | .probe = ide_scsi_probe, | ||
444 | .remove = ide_scsi_remove, | ||
445 | .version = IDESCSI_VERSION, | ||
446 | .do_request = idescsi_do_request, | ||
447 | .end_request = idescsi_end_request, | ||
448 | .error = idescsi_atapi_error, | ||
449 | #ifdef CONFIG_IDE_PROC_FS | ||
450 | .proc_entries = ide_scsi_proc_entries, | ||
451 | .proc_devsets = ide_scsi_proc_devsets, | ||
452 | #endif | ||
453 | }; | ||
454 | |||
455 | static int idescsi_ide_open(struct block_device *bdev, fmode_t mode) | ||
456 | { | ||
457 | struct ide_scsi_obj *scsi = ide_scsi_get(bdev->bd_disk); | ||
458 | |||
459 | if (!scsi) | ||
460 | return -ENXIO; | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int idescsi_ide_release(struct gendisk *disk, fmode_t mode) | ||
466 | { | ||
467 | ide_scsi_put(ide_scsi_g(disk)); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int idescsi_ide_ioctl(struct block_device *bdev, fmode_t mode, | ||
472 | unsigned int cmd, unsigned long arg) | ||
473 | { | ||
474 | struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk); | ||
475 | return generic_ide_ioctl(scsi->drive, bdev, cmd, arg); | ||
476 | } | ||
477 | |||
478 | static struct block_device_operations idescsi_ops = { | ||
479 | .owner = THIS_MODULE, | ||
480 | .open = idescsi_ide_open, | ||
481 | .release = idescsi_ide_release, | ||
482 | .locked_ioctl = idescsi_ide_ioctl, | ||
483 | }; | ||
484 | |||
485 | static int idescsi_slave_configure(struct scsi_device * sdp) | ||
486 | { | ||
487 | /* Configure detected device */ | ||
488 | sdp->use_10_for_rw = 1; | ||
489 | sdp->use_10_for_ms = 1; | ||
490 | scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static const char *idescsi_info (struct Scsi_Host *host) | ||
495 | { | ||
496 | return "SCSI host adapter emulation for IDE ATAPI devices"; | ||
497 | } | ||
498 | |||
499 | static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg) | ||
500 | { | ||
501 | idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host); | ||
502 | |||
503 | if (cmd == SG_SET_TRANSFORM) { | ||
504 | if (arg) | ||
505 | set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); | ||
506 | else | ||
507 | clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); | ||
508 | return 0; | ||
509 | } else if (cmd == SG_GET_TRANSFORM) | ||
510 | return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int __user *) arg); | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | |||
514 | static int idescsi_queue (struct scsi_cmnd *cmd, | ||
515 | void (*done)(struct scsi_cmnd *)) | ||
516 | { | ||
517 | struct Scsi_Host *host = cmd->device->host; | ||
518 | idescsi_scsi_t *scsi = scsihost_to_idescsi(host); | ||
519 | ide_drive_t *drive = scsi->drive; | ||
520 | struct request *rq = NULL; | ||
521 | struct ide_atapi_pc *pc = NULL; | ||
522 | int write = cmd->sc_data_direction == DMA_TO_DEVICE; | ||
523 | |||
524 | if (!drive) { | ||
525 | scmd_printk (KERN_ERR, cmd, "drive not present\n"); | ||
526 | goto abort; | ||
527 | } | ||
528 | scsi = drive_to_idescsi(drive); | ||
529 | pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC); | ||
530 | rq = blk_get_request(drive->queue, write, GFP_ATOMIC); | ||
531 | if (rq == NULL || pc == NULL) { | ||
532 | printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name); | ||
533 | goto abort; | ||
534 | } | ||
535 | |||
536 | memset (pc->c, 0, 12); | ||
537 | pc->flags = 0; | ||
538 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
539 | pc->flags |= PC_FLAG_WRITING; | ||
540 | pc->rq = rq; | ||
541 | memcpy (pc->c, cmd->cmnd, cmd->cmd_len); | ||
542 | pc->buf = NULL; | ||
543 | pc->sg = scsi_sglist(cmd); | ||
544 | pc->sg_cnt = scsi_sg_count(cmd); | ||
545 | pc->b_count = 0; | ||
546 | pc->req_xfer = pc->buf_size = scsi_bufflen(cmd); | ||
547 | pc->scsi_cmd = cmd; | ||
548 | pc->done = done; | ||
549 | pc->timeout = jiffies + cmd->request->timeout; | ||
550 | |||
551 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { | ||
552 | printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); | ||
553 | ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len); | ||
554 | if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) { | ||
555 | printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number); | ||
556 | ide_scsi_hex_dump(pc->c, 12); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | rq->special = (char *) pc; | ||
561 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
562 | spin_unlock_irq(host->host_lock); | ||
563 | rq->ref_count++; | ||
564 | memcpy(rq->cmd, pc->c, 12); | ||
565 | blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL); | ||
566 | spin_lock_irq(host->host_lock); | ||
567 | return 0; | ||
568 | abort: | ||
569 | kfree (pc); | ||
570 | if (rq) | ||
571 | blk_put_request(rq); | ||
572 | cmd->result = DID_ERROR << 16; | ||
573 | done(cmd); | ||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int idescsi_eh_abort (struct scsi_cmnd *cmd) | ||
578 | { | ||
579 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); | ||
580 | ide_drive_t *drive = scsi->drive; | ||
581 | ide_hwif_t *hwif; | ||
582 | ide_hwgroup_t *hwgroup; | ||
583 | int busy; | ||
584 | int ret = FAILED; | ||
585 | |||
586 | struct ide_atapi_pc *pc; | ||
587 | |||
588 | /* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */ | ||
589 | |||
590 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | ||
591 | printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number); | ||
592 | |||
593 | if (!drive) { | ||
594 | printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n"); | ||
595 | WARN_ON(1); | ||
596 | goto no_drive; | ||
597 | } | ||
598 | |||
599 | hwif = drive->hwif; | ||
600 | hwgroup = hwif->hwgroup; | ||
601 | |||
602 | /* First give it some more time, how much is "right" is hard to say :-( | ||
603 | FIXME - uses mdelay which causes latency? */ | ||
604 | busy = ide_wait_not_busy(hwif, 100); | ||
605 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | ||
606 | printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":""); | ||
607 | |||
608 | spin_lock_irq(&hwgroup->lock); | ||
609 | |||
610 | /* If there is no pc running we're done (our interrupt took care of it) */ | ||
611 | pc = drive->pc; | ||
612 | if (pc == NULL) { | ||
613 | ret = SUCCESS; | ||
614 | goto ide_unlock; | ||
615 | } | ||
616 | |||
617 | /* It's somewhere in flight. Does ide subsystem agree? */ | ||
618 | if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy && | ||
619 | elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) { | ||
620 | /* | ||
621 | * FIXME - not sure this condition can ever occur | ||
622 | */ | ||
623 | printk (KERN_ERR "ide-scsi: cmd aborted!\n"); | ||
624 | |||
625 | if (blk_sense_request(pc->rq)) | ||
626 | kfree(pc->buf); | ||
627 | /* we need to call blk_put_request twice. */ | ||
628 | blk_put_request(pc->rq); | ||
629 | blk_put_request(pc->rq); | ||
630 | kfree(pc); | ||
631 | drive->pc = NULL; | ||
632 | |||
633 | ret = SUCCESS; | ||
634 | } | ||
635 | |||
636 | ide_unlock: | ||
637 | spin_unlock_irq(&hwgroup->lock); | ||
638 | no_drive: | ||
639 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | ||
640 | printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed"); | ||
641 | |||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | static int idescsi_eh_reset (struct scsi_cmnd *cmd) | ||
646 | { | ||
647 | struct request *req; | ||
648 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); | ||
649 | ide_drive_t *drive = scsi->drive; | ||
650 | ide_hwgroup_t *hwgroup; | ||
651 | int ready = 0; | ||
652 | int ret = SUCCESS; | ||
653 | |||
654 | struct ide_atapi_pc *pc; | ||
655 | |||
656 | /* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */ | ||
657 | |||
658 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | ||
659 | printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number); | ||
660 | |||
661 | if (!drive) { | ||
662 | printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n"); | ||
663 | WARN_ON(1); | ||
664 | return FAILED; | ||
665 | } | ||
666 | |||
667 | hwgroup = drive->hwif->hwgroup; | ||
668 | |||
669 | spin_lock_irq(cmd->device->host->host_lock); | ||
670 | spin_lock(&hwgroup->lock); | ||
671 | |||
672 | pc = drive->pc; | ||
673 | if (pc) | ||
674 | req = pc->rq; | ||
675 | |||
676 | if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) { | ||
677 | printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); | ||
678 | spin_unlock(&hwgroup->lock); | ||
679 | spin_unlock_irq(cmd->device->host->host_lock); | ||
680 | return FAILED; | ||
681 | } | ||
682 | |||
683 | /* kill current request */ | ||
684 | if (__blk_end_request(req, -EIO, 0)) | ||
685 | BUG(); | ||
686 | if (blk_sense_request(req)) | ||
687 | kfree(pc->buf); | ||
688 | kfree(pc); | ||
689 | drive->pc = NULL; | ||
690 | blk_put_request(req); | ||
691 | |||
692 | /* now nuke the drive queue */ | ||
693 | while ((req = elv_next_request(drive->queue))) { | ||
694 | if (__blk_end_request(req, -EIO, 0)) | ||
695 | BUG(); | ||
696 | } | ||
697 | |||
698 | hwgroup->rq = NULL; | ||
699 | hwgroup->handler = NULL; | ||
700 | hwgroup->busy = 1; /* will set this to zero when ide reset finished */ | ||
701 | spin_unlock(&hwgroup->lock); | ||
702 | |||
703 | ide_do_reset(drive); | ||
704 | |||
705 | /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */ | ||
706 | |||
707 | do { | ||
708 | spin_unlock_irq(cmd->device->host->host_lock); | ||
709 | msleep(50); | ||
710 | spin_lock_irq(cmd->device->host->host_lock); | ||
711 | } while ( HWGROUP(drive)->handler ); | ||
712 | |||
713 | ready = drive_is_ready(drive); | ||
714 | HWGROUP(drive)->busy--; | ||
715 | if (!ready) { | ||
716 | printk (KERN_ERR "ide-scsi: reset failed!\n"); | ||
717 | ret = FAILED; | ||
718 | } | ||
719 | |||
720 | spin_unlock_irq(cmd->device->host->host_lock); | ||
721 | return ret; | ||
722 | } | ||
723 | |||
724 | static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev, | ||
725 | sector_t capacity, int *parm) | ||
726 | { | ||
727 | idescsi_scsi_t *idescsi = scsihost_to_idescsi(sdev->host); | ||
728 | ide_drive_t *drive = idescsi->drive; | ||
729 | |||
730 | if (drive->bios_cyl && drive->bios_head && drive->bios_sect) { | ||
731 | parm[0] = drive->bios_head; | ||
732 | parm[1] = drive->bios_sect; | ||
733 | parm[2] = drive->bios_cyl; | ||
734 | } | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static struct scsi_host_template idescsi_template = { | ||
739 | .module = THIS_MODULE, | ||
740 | .name = "idescsi", | ||
741 | .info = idescsi_info, | ||
742 | .slave_configure = idescsi_slave_configure, | ||
743 | .ioctl = idescsi_ioctl, | ||
744 | .queuecommand = idescsi_queue, | ||
745 | .eh_abort_handler = idescsi_eh_abort, | ||
746 | .eh_host_reset_handler = idescsi_eh_reset, | ||
747 | .bios_param = idescsi_bios, | ||
748 | .can_queue = 40, | ||
749 | .this_id = -1, | ||
750 | .sg_tablesize = 256, | ||
751 | .cmd_per_lun = 5, | ||
752 | .max_sectors = 128, | ||
753 | .use_clustering = DISABLE_CLUSTERING, | ||
754 | .emulated = 1, | ||
755 | .proc_name = "ide-scsi", | ||
756 | }; | ||
757 | |||
758 | static int ide_scsi_probe(ide_drive_t *drive) | ||
759 | { | ||
760 | idescsi_scsi_t *idescsi; | ||
761 | struct Scsi_Host *host; | ||
762 | struct gendisk *g; | ||
763 | static int warned; | ||
764 | int err = -ENOMEM; | ||
765 | u16 last_lun; | ||
766 | |||
767 | if (!warned && drive->media == ide_cdrom) { | ||
768 | printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n"); | ||
769 | warned = 1; | ||
770 | } | ||
771 | |||
772 | if (idescsi_nocd && drive->media == ide_cdrom) | ||
773 | return -ENODEV; | ||
774 | |||
775 | if (!strstr("ide-scsi", drive->driver_req) || | ||
776 | drive->media == ide_disk || | ||
777 | !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) | ||
778 | return -ENODEV; | ||
779 | |||
780 | drive->dev_flags |= IDE_DFLAG_SCSI; | ||
781 | |||
782 | g = alloc_disk(1 << PARTN_BITS); | ||
783 | if (!g) | ||
784 | goto out_host_put; | ||
785 | |||
786 | ide_init_disk(g, drive); | ||
787 | |||
788 | host->max_id = 1; | ||
789 | |||
790 | last_lun = drive->id[ATA_ID_LAST_LUN]; | ||
791 | if (last_lun) | ||
792 | debug_log("%s: last_lun=%u\n", drive->name, last_lun); | ||
793 | |||
794 | if ((last_lun & 7) != 7) | ||
795 | host->max_lun = (last_lun & 7) + 1; | ||
796 | else | ||
797 | host->max_lun = 1; | ||
798 | |||
799 | drive->driver_data = host; | ||
800 | idescsi = scsihost_to_idescsi(host); | ||
801 | idescsi->drive = drive; | ||
802 | idescsi->driver = &idescsi_driver; | ||
803 | idescsi->host = host; | ||
804 | idescsi->disk = g; | ||
805 | g->private_data = &idescsi->driver; | ||
806 | err = 0; | ||
807 | idescsi_setup(drive, idescsi); | ||
808 | g->fops = &idescsi_ops; | ||
809 | ide_register_region(g); | ||
810 | err = scsi_add_host(host, &drive->gendev); | ||
811 | if (!err) { | ||
812 | scsi_scan_host(host); | ||
813 | return 0; | ||
814 | } | ||
815 | /* fall through on error */ | ||
816 | ide_unregister_region(g); | ||
817 | ide_proc_unregister_driver(drive, &idescsi_driver); | ||
818 | |||
819 | put_disk(g); | ||
820 | out_host_put: | ||
821 | drive->dev_flags &= ~IDE_DFLAG_SCSI; | ||
822 | scsi_host_put(host); | ||
823 | return err; | ||
824 | } | ||
825 | |||
826 | static int __init init_idescsi_module(void) | ||
827 | { | ||
828 | return driver_register(&idescsi_driver.gen_driver); | ||
829 | } | ||
830 | |||
831 | static void __exit exit_idescsi_module(void) | ||
832 | { | ||
833 | driver_unregister(&idescsi_driver.gen_driver); | ||
834 | } | ||
835 | |||
836 | module_param(idescsi_nocd, int, 0600); | ||
837 | MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd"); | ||
838 | module_init(init_idescsi_module); | ||
839 | module_exit(exit_idescsi_module); | ||
840 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 303272af386e..daa00567bc44 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -279,6 +279,13 @@ static const struct serial8250_config uart_config[] = { | |||
279 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 279 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
280 | .flags = UART_CAP_FIFO, | 280 | .flags = UART_CAP_FIFO, |
281 | }, | 281 | }, |
282 | [PORT_OCTEON] = { | ||
283 | .name = "OCTEON", | ||
284 | .fifo_size = 64, | ||
285 | .tx_loadsz = 64, | ||
286 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
287 | .flags = UART_CAP_FIFO, | ||
288 | }, | ||
282 | }; | 289 | }; |
283 | 290 | ||
284 | #if defined (CONFIG_SERIAL_8250_AU1X00) | 291 | #if defined (CONFIG_SERIAL_8250_AU1X00) |
@@ -303,16 +310,16 @@ static const u8 au_io_out_map[] = { | |||
303 | }; | 310 | }; |
304 | 311 | ||
305 | /* sane hardware needs no mapping */ | 312 | /* sane hardware needs no mapping */ |
306 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | 313 | static inline int map_8250_in_reg(struct uart_port *p, int offset) |
307 | { | 314 | { |
308 | if (up->port.iotype != UPIO_AU) | 315 | if (p->iotype != UPIO_AU) |
309 | return offset; | 316 | return offset; |
310 | return au_io_in_map[offset]; | 317 | return au_io_in_map[offset]; |
311 | } | 318 | } |
312 | 319 | ||
313 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | 320 | static inline int map_8250_out_reg(struct uart_port *p, int offset) |
314 | { | 321 | { |
315 | if (up->port.iotype != UPIO_AU) | 322 | if (p->iotype != UPIO_AU) |
316 | return offset; | 323 | return offset; |
317 | return au_io_out_map[offset]; | 324 | return au_io_out_map[offset]; |
318 | } | 325 | } |
@@ -341,16 +348,16 @@ static const u8 | |||
341 | [UART_SCR] = 0x2c | 348 | [UART_SCR] = 0x2c |
342 | }; | 349 | }; |
343 | 350 | ||
344 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | 351 | static inline int map_8250_in_reg(struct uart_port *p, int offset) |
345 | { | 352 | { |
346 | if (up->port.iotype != UPIO_RM9000) | 353 | if (p->iotype != UPIO_RM9000) |
347 | return offset; | 354 | return offset; |
348 | return regmap_in[offset]; | 355 | return regmap_in[offset]; |
349 | } | 356 | } |
350 | 357 | ||
351 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | 358 | static inline int map_8250_out_reg(struct uart_port *p, int offset) |
352 | { | 359 | { |
353 | if (up->port.iotype != UPIO_RM9000) | 360 | if (p->iotype != UPIO_RM9000) |
354 | return offset; | 361 | return offset; |
355 | return regmap_out[offset]; | 362 | return regmap_out[offset]; |
356 | } | 363 | } |
@@ -363,108 +370,170 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | |||
363 | 370 | ||
364 | #endif | 371 | #endif |
365 | 372 | ||
366 | static unsigned int serial_in(struct uart_8250_port *up, int offset) | 373 | static unsigned int hub6_serial_in(struct uart_port *p, int offset) |
367 | { | 374 | { |
368 | unsigned int tmp; | 375 | offset = map_8250_in_reg(p, offset) << p->regshift; |
369 | offset = map_8250_in_reg(up, offset) << up->port.regshift; | 376 | outb(p->hub6 - 1 + offset, p->iobase); |
377 | return inb(p->iobase + 1); | ||
378 | } | ||
370 | 379 | ||
371 | switch (up->port.iotype) { | 380 | static void hub6_serial_out(struct uart_port *p, int offset, int value) |
372 | case UPIO_HUB6: | 381 | { |
373 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 382 | offset = map_8250_out_reg(p, offset) << p->regshift; |
374 | return inb(up->port.iobase + 1); | 383 | outb(p->hub6 - 1 + offset, p->iobase); |
384 | outb(value, p->iobase + 1); | ||
385 | } | ||
375 | 386 | ||
376 | case UPIO_MEM: | 387 | static unsigned int mem_serial_in(struct uart_port *p, int offset) |
377 | case UPIO_DWAPB: | 388 | { |
378 | return readb(up->port.membase + offset); | 389 | offset = map_8250_in_reg(p, offset) << p->regshift; |
390 | return readb(p->membase + offset); | ||
391 | } | ||
379 | 392 | ||
380 | case UPIO_RM9000: | 393 | static void mem_serial_out(struct uart_port *p, int offset, int value) |
381 | case UPIO_MEM32: | 394 | { |
382 | return readl(up->port.membase + offset); | 395 | offset = map_8250_out_reg(p, offset) << p->regshift; |
396 | writeb(value, p->membase + offset); | ||
397 | } | ||
398 | |||
399 | static void mem32_serial_out(struct uart_port *p, int offset, int value) | ||
400 | { | ||
401 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
402 | writel(value, p->membase + offset); | ||
403 | } | ||
404 | |||
405 | static unsigned int mem32_serial_in(struct uart_port *p, int offset) | ||
406 | { | ||
407 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
408 | return readl(p->membase + offset); | ||
409 | } | ||
383 | 410 | ||
384 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 411 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
385 | case UPIO_AU: | 412 | static unsigned int au_serial_in(struct uart_port *p, int offset) |
386 | return __raw_readl(up->port.membase + offset); | 413 | { |
414 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
415 | return __raw_readl(p->membase + offset); | ||
416 | } | ||
417 | |||
418 | static void au_serial_out(struct uart_port *p, int offset, int value) | ||
419 | { | ||
420 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
421 | __raw_writel(value, p->membase + offset); | ||
422 | } | ||
387 | #endif | 423 | #endif |
388 | 424 | ||
389 | case UPIO_TSI: | 425 | static unsigned int tsi_serial_in(struct uart_port *p, int offset) |
390 | if (offset == UART_IIR) { | 426 | { |
391 | tmp = readl(up->port.membase + (UART_IIR & ~3)); | 427 | unsigned int tmp; |
392 | return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ | 428 | offset = map_8250_in_reg(p, offset) << p->regshift; |
393 | } else | 429 | if (offset == UART_IIR) { |
394 | return readb(up->port.membase + offset); | 430 | tmp = readl(p->membase + (UART_IIR & ~3)); |
431 | return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ | ||
432 | } else | ||
433 | return readb(p->membase + offset); | ||
434 | } | ||
395 | 435 | ||
396 | default: | 436 | static void tsi_serial_out(struct uart_port *p, int offset, int value) |
397 | return inb(up->port.iobase + offset); | 437 | { |
398 | } | 438 | offset = map_8250_out_reg(p, offset) << p->regshift; |
439 | if (!((offset == UART_IER) && (value & UART_IER_UUE))) | ||
440 | writeb(value, p->membase + offset); | ||
399 | } | 441 | } |
400 | 442 | ||
401 | static void | 443 | static void dwapb_serial_out(struct uart_port *p, int offset, int value) |
402 | serial_out(struct uart_8250_port *up, int offset, int value) | ||
403 | { | 444 | { |
404 | /* Save the offset before it's remapped */ | ||
405 | int save_offset = offset; | 445 | int save_offset = offset; |
406 | offset = map_8250_out_reg(up, offset) << up->port.regshift; | 446 | offset = map_8250_out_reg(p, offset) << p->regshift; |
447 | /* Save the LCR value so it can be re-written when a | ||
448 | * Busy Detect interrupt occurs. */ | ||
449 | if (save_offset == UART_LCR) { | ||
450 | struct uart_8250_port *up = (struct uart_8250_port *)p; | ||
451 | up->lcr = value; | ||
452 | } | ||
453 | writeb(value, p->membase + offset); | ||
454 | /* Read the IER to ensure any interrupt is cleared before | ||
455 | * returning from ISR. */ | ||
456 | if (save_offset == UART_TX || save_offset == UART_IER) | ||
457 | value = p->serial_in(p, UART_IER); | ||
458 | } | ||
407 | 459 | ||
408 | switch (up->port.iotype) { | 460 | static unsigned int io_serial_in(struct uart_port *p, int offset) |
461 | { | ||
462 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
463 | return inb(p->iobase + offset); | ||
464 | } | ||
465 | |||
466 | static void io_serial_out(struct uart_port *p, int offset, int value) | ||
467 | { | ||
468 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
469 | outb(value, p->iobase + offset); | ||
470 | } | ||
471 | |||
472 | static void set_io_from_upio(struct uart_port *p) | ||
473 | { | ||
474 | switch (p->iotype) { | ||
409 | case UPIO_HUB6: | 475 | case UPIO_HUB6: |
410 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 476 | p->serial_in = hub6_serial_in; |
411 | outb(value, up->port.iobase + 1); | 477 | p->serial_out = hub6_serial_out; |
412 | break; | 478 | break; |
413 | 479 | ||
414 | case UPIO_MEM: | 480 | case UPIO_MEM: |
415 | writeb(value, up->port.membase + offset); | 481 | p->serial_in = mem_serial_in; |
482 | p->serial_out = mem_serial_out; | ||
416 | break; | 483 | break; |
417 | 484 | ||
418 | case UPIO_RM9000: | 485 | case UPIO_RM9000: |
419 | case UPIO_MEM32: | 486 | case UPIO_MEM32: |
420 | writel(value, up->port.membase + offset); | 487 | p->serial_in = mem32_serial_in; |
488 | p->serial_out = mem32_serial_out; | ||
421 | break; | 489 | break; |
422 | 490 | ||
423 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 491 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
424 | case UPIO_AU: | 492 | case UPIO_AU: |
425 | __raw_writel(value, up->port.membase + offset); | 493 | p->serial_in = au_serial_in; |
494 | p->serial_out = au_serial_out; | ||
426 | break; | 495 | break; |
427 | #endif | 496 | #endif |
428 | case UPIO_TSI: | 497 | case UPIO_TSI: |
429 | if (!((offset == UART_IER) && (value & UART_IER_UUE))) | 498 | p->serial_in = tsi_serial_in; |
430 | writeb(value, up->port.membase + offset); | 499 | p->serial_out = tsi_serial_out; |
431 | break; | 500 | break; |
432 | 501 | ||
433 | case UPIO_DWAPB: | 502 | case UPIO_DWAPB: |
434 | /* Save the LCR value so it can be re-written when a | 503 | p->serial_in = mem_serial_in; |
435 | * Busy Detect interrupt occurs. */ | 504 | p->serial_out = dwapb_serial_out; |
436 | if (save_offset == UART_LCR) | ||
437 | up->lcr = value; | ||
438 | writeb(value, up->port.membase + offset); | ||
439 | /* Read the IER to ensure any interrupt is cleared before | ||
440 | * returning from ISR. */ | ||
441 | if (save_offset == UART_TX || save_offset == UART_IER) | ||
442 | value = serial_in(up, UART_IER); | ||
443 | break; | 505 | break; |
444 | 506 | ||
445 | default: | 507 | default: |
446 | outb(value, up->port.iobase + offset); | 508 | p->serial_in = io_serial_in; |
509 | p->serial_out = io_serial_out; | ||
510 | break; | ||
447 | } | 511 | } |
448 | } | 512 | } |
449 | 513 | ||
450 | static void | 514 | static void |
451 | serial_out_sync(struct uart_8250_port *up, int offset, int value) | 515 | serial_out_sync(struct uart_8250_port *up, int offset, int value) |
452 | { | 516 | { |
453 | switch (up->port.iotype) { | 517 | struct uart_port *p = &up->port; |
518 | switch (p->iotype) { | ||
454 | case UPIO_MEM: | 519 | case UPIO_MEM: |
455 | case UPIO_MEM32: | 520 | case UPIO_MEM32: |
456 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 521 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
457 | case UPIO_AU: | 522 | case UPIO_AU: |
458 | #endif | 523 | #endif |
459 | case UPIO_DWAPB: | 524 | case UPIO_DWAPB: |
460 | serial_out(up, offset, value); | 525 | p->serial_out(p, offset, value); |
461 | serial_in(up, UART_LCR); /* safe, no side-effects */ | 526 | p->serial_in(p, UART_LCR); /* safe, no side-effects */ |
462 | break; | 527 | break; |
463 | default: | 528 | default: |
464 | serial_out(up, offset, value); | 529 | p->serial_out(p, offset, value); |
465 | } | 530 | } |
466 | } | 531 | } |
467 | 532 | ||
533 | #define serial_in(up, offset) \ | ||
534 | (up->port.serial_in(&(up)->port, (offset))) | ||
535 | #define serial_out(up, offset, value) \ | ||
536 | (up->port.serial_out(&(up)->port, (offset), (value))) | ||
468 | /* | 537 | /* |
469 | * We used to support using pause I/O for certain machines. We | 538 | * We used to support using pause I/O for certain machines. We |
470 | * haven't supported this for a while, but just in case it's badly | 539 | * haven't supported this for a while, but just in case it's badly |
@@ -2576,6 +2645,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2576 | up->port.membase = old_serial_port[i].iomem_base; | 2645 | up->port.membase = old_serial_port[i].iomem_base; |
2577 | up->port.iotype = old_serial_port[i].io_type; | 2646 | up->port.iotype = old_serial_port[i].io_type; |
2578 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 2647 | up->port.regshift = old_serial_port[i].iomem_reg_shift; |
2648 | set_io_from_upio(&up->port); | ||
2579 | if (share_irqs) | 2649 | if (share_irqs) |
2580 | up->port.flags |= UPF_SHARE_IRQ; | 2650 | up->port.flags |= UPF_SHARE_IRQ; |
2581 | } | 2651 | } |
@@ -2752,12 +2822,30 @@ static struct uart_driver serial8250_reg = { | |||
2752 | */ | 2822 | */ |
2753 | int __init early_serial_setup(struct uart_port *port) | 2823 | int __init early_serial_setup(struct uart_port *port) |
2754 | { | 2824 | { |
2825 | struct uart_port *p; | ||
2826 | |||
2755 | if (port->line >= ARRAY_SIZE(serial8250_ports)) | 2827 | if (port->line >= ARRAY_SIZE(serial8250_ports)) |
2756 | return -ENODEV; | 2828 | return -ENODEV; |
2757 | 2829 | ||
2758 | serial8250_isa_init_ports(); | 2830 | serial8250_isa_init_ports(); |
2759 | serial8250_ports[port->line].port = *port; | 2831 | p = &serial8250_ports[port->line].port; |
2760 | serial8250_ports[port->line].port.ops = &serial8250_pops; | 2832 | p->iobase = port->iobase; |
2833 | p->membase = port->membase; | ||
2834 | p->irq = port->irq; | ||
2835 | p->uartclk = port->uartclk; | ||
2836 | p->fifosize = port->fifosize; | ||
2837 | p->regshift = port->regshift; | ||
2838 | p->iotype = port->iotype; | ||
2839 | p->flags = port->flags; | ||
2840 | p->mapbase = port->mapbase; | ||
2841 | p->private_data = port->private_data; | ||
2842 | |||
2843 | set_io_from_upio(p); | ||
2844 | if (port->serial_in) | ||
2845 | p->serial_in = port->serial_in; | ||
2846 | if (port->serial_out) | ||
2847 | p->serial_out = port->serial_out; | ||
2848 | |||
2761 | return 0; | 2849 | return 0; |
2762 | } | 2850 | } |
2763 | 2851 | ||
@@ -2822,6 +2910,9 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2822 | port.mapbase = p->mapbase; | 2910 | port.mapbase = p->mapbase; |
2823 | port.hub6 = p->hub6; | 2911 | port.hub6 = p->hub6; |
2824 | port.private_data = p->private_data; | 2912 | port.private_data = p->private_data; |
2913 | port.type = p->type; | ||
2914 | port.serial_in = p->serial_in; | ||
2915 | port.serial_out = p->serial_out; | ||
2825 | port.dev = &dev->dev; | 2916 | port.dev = &dev->dev; |
2826 | if (share_irqs) | 2917 | if (share_irqs) |
2827 | port.flags |= UPF_SHARE_IRQ; | 2918 | port.flags |= UPF_SHARE_IRQ; |
@@ -2976,6 +3067,20 @@ int serial8250_register_port(struct uart_port *port) | |||
2976 | if (port->dev) | 3067 | if (port->dev) |
2977 | uart->port.dev = port->dev; | 3068 | uart->port.dev = port->dev; |
2978 | 3069 | ||
3070 | if (port->flags & UPF_FIXED_TYPE) { | ||
3071 | uart->port.type = port->type; | ||
3072 | uart->port.fifosize = uart_config[port->type].fifo_size; | ||
3073 | uart->capabilities = uart_config[port->type].flags; | ||
3074 | uart->tx_loadsz = uart_config[port->type].tx_loadsz; | ||
3075 | } | ||
3076 | |||
3077 | set_io_from_upio(&uart->port); | ||
3078 | /* Possibly override default I/O functions. */ | ||
3079 | if (port->serial_in) | ||
3080 | uart->port.serial_in = port->serial_in; | ||
3081 | if (port->serial_out) | ||
3082 | uart->port.serial_out = port->serial_out; | ||
3083 | |||
2979 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 3084 | ret = uart_add_one_port(&serial8250_reg, &uart->port); |
2980 | if (ret == 0) | 3085 | if (ret == 0) |
2981 | ret = uart->port.line; | 3086 | ret = uart->port.line; |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 5450a0e5ecdb..c088146b7513 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -42,7 +42,8 @@ struct pci_serial_quirk { | |||
42 | u32 subvendor; | 42 | u32 subvendor; |
43 | u32 subdevice; | 43 | u32 subdevice; |
44 | int (*init)(struct pci_dev *dev); | 44 | int (*init)(struct pci_dev *dev); |
45 | int (*setup)(struct serial_private *, struct pciserial_board *, | 45 | int (*setup)(struct serial_private *, |
46 | const struct pciserial_board *, | ||
46 | struct uart_port *, int); | 47 | struct uart_port *, int); |
47 | void (*exit)(struct pci_dev *dev); | 48 | void (*exit)(struct pci_dev *dev); |
48 | }; | 49 | }; |
@@ -107,7 +108,7 @@ setup_port(struct serial_private *priv, struct uart_port *port, | |||
107 | * ADDI-DATA GmbH communication cards <info@addi-data.com> | 108 | * ADDI-DATA GmbH communication cards <info@addi-data.com> |
108 | */ | 109 | */ |
109 | static int addidata_apci7800_setup(struct serial_private *priv, | 110 | static int addidata_apci7800_setup(struct serial_private *priv, |
110 | struct pciserial_board *board, | 111 | const struct pciserial_board *board, |
111 | struct uart_port *port, int idx) | 112 | struct uart_port *port, int idx) |
112 | { | 113 | { |
113 | unsigned int bar = 0, offset = board->first_offset; | 114 | unsigned int bar = 0, offset = board->first_offset; |
@@ -134,7 +135,7 @@ static int addidata_apci7800_setup(struct serial_private *priv, | |||
134 | * Not that ugly ;) -- HW | 135 | * Not that ugly ;) -- HW |
135 | */ | 136 | */ |
136 | static int | 137 | static int |
137 | afavlab_setup(struct serial_private *priv, struct pciserial_board *board, | 138 | afavlab_setup(struct serial_private *priv, const struct pciserial_board *board, |
138 | struct uart_port *port, int idx) | 139 | struct uart_port *port, int idx) |
139 | { | 140 | { |
140 | unsigned int bar, offset = board->first_offset; | 141 | unsigned int bar, offset = board->first_offset; |
@@ -188,8 +189,9 @@ static int pci_hp_diva_init(struct pci_dev *dev) | |||
188 | * some serial ports are supposed to be hidden on certain models. | 189 | * some serial ports are supposed to be hidden on certain models. |
189 | */ | 190 | */ |
190 | static int | 191 | static int |
191 | pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board, | 192 | pci_hp_diva_setup(struct serial_private *priv, |
192 | struct uart_port *port, int idx) | 193 | const struct pciserial_board *board, |
194 | struct uart_port *port, int idx) | ||
193 | { | 195 | { |
194 | unsigned int offset = board->first_offset; | 196 | unsigned int offset = board->first_offset; |
195 | unsigned int bar = FL_GET_BASE(board->flags); | 197 | unsigned int bar = FL_GET_BASE(board->flags); |
@@ -306,7 +308,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) | |||
306 | 308 | ||
307 | /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ | 309 | /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ |
308 | static int | 310 | static int |
309 | sbs_setup(struct serial_private *priv, struct pciserial_board *board, | 311 | sbs_setup(struct serial_private *priv, const struct pciserial_board *board, |
310 | struct uart_port *port, int idx) | 312 | struct uart_port *port, int idx) |
311 | { | 313 | { |
312 | unsigned int bar, offset = board->first_offset; | 314 | unsigned int bar, offset = board->first_offset; |
@@ -463,7 +465,7 @@ static int pci_siig_init(struct pci_dev *dev) | |||
463 | } | 465 | } |
464 | 466 | ||
465 | static int pci_siig_setup(struct serial_private *priv, | 467 | static int pci_siig_setup(struct serial_private *priv, |
466 | struct pciserial_board *board, | 468 | const struct pciserial_board *board, |
467 | struct uart_port *port, int idx) | 469 | struct uart_port *port, int idx) |
468 | { | 470 | { |
469 | unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; | 471 | unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; |
@@ -534,7 +536,8 @@ static int pci_timedia_init(struct pci_dev *dev) | |||
534 | * Ugh, this is ugly as all hell --- TYT | 536 | * Ugh, this is ugly as all hell --- TYT |
535 | */ | 537 | */ |
536 | static int | 538 | static int |
537 | pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board, | 539 | pci_timedia_setup(struct serial_private *priv, |
540 | const struct pciserial_board *board, | ||
538 | struct uart_port *port, int idx) | 541 | struct uart_port *port, int idx) |
539 | { | 542 | { |
540 | unsigned int bar = 0, offset = board->first_offset; | 543 | unsigned int bar = 0, offset = board->first_offset; |
@@ -568,7 +571,7 @@ pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board, | |||
568 | */ | 571 | */ |
569 | static int | 572 | static int |
570 | titan_400l_800l_setup(struct serial_private *priv, | 573 | titan_400l_800l_setup(struct serial_private *priv, |
571 | struct pciserial_board *board, | 574 | const struct pciserial_board *board, |
572 | struct uart_port *port, int idx) | 575 | struct uart_port *port, int idx) |
573 | { | 576 | { |
574 | unsigned int bar, offset = board->first_offset; | 577 | unsigned int bar, offset = board->first_offset; |
@@ -737,8 +740,41 @@ static void __devexit pci_ite887x_exit(struct pci_dev *dev) | |||
737 | release_region(ioport, ITE_887x_IOSIZE); | 740 | release_region(ioport, ITE_887x_IOSIZE); |
738 | } | 741 | } |
739 | 742 | ||
743 | /* | ||
744 | * Oxford Semiconductor Inc. | ||
745 | * Check that device is part of the Tornado range of devices, then determine | ||
746 | * the number of ports available on the device. | ||
747 | */ | ||
748 | static int pci_oxsemi_tornado_init(struct pci_dev *dev) | ||
749 | { | ||
750 | u8 __iomem *p; | ||
751 | unsigned long deviceID; | ||
752 | unsigned int number_uarts = 0; | ||
753 | |||
754 | /* OxSemi Tornado devices are all 0xCxxx */ | ||
755 | if (dev->vendor == PCI_VENDOR_ID_OXSEMI && | ||
756 | (dev->device & 0xF000) != 0xC000) | ||
757 | return 0; | ||
758 | |||
759 | p = pci_iomap(dev, 0, 5); | ||
760 | if (p == NULL) | ||
761 | return -ENOMEM; | ||
762 | |||
763 | deviceID = ioread32(p); | ||
764 | /* Tornado device */ | ||
765 | if (deviceID == 0x07000200) { | ||
766 | number_uarts = ioread8(p + 4); | ||
767 | printk(KERN_DEBUG | ||
768 | "%d ports detected on Oxford PCI Express device\n", | ||
769 | number_uarts); | ||
770 | } | ||
771 | pci_iounmap(dev, p); | ||
772 | return number_uarts; | ||
773 | } | ||
774 | |||
740 | static int | 775 | static int |
741 | pci_default_setup(struct serial_private *priv, struct pciserial_board *board, | 776 | pci_default_setup(struct serial_private *priv, |
777 | const struct pciserial_board *board, | ||
742 | struct uart_port *port, int idx) | 778 | struct uart_port *port, int idx) |
743 | { | 779 | { |
744 | unsigned int bar, offset = board->first_offset, maxnr; | 780 | unsigned int bar, offset = board->first_offset, maxnr; |
@@ -1018,6 +1054,25 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1018 | .setup = pci_default_setup, | 1054 | .setup = pci_default_setup, |
1019 | }, | 1055 | }, |
1020 | /* | 1056 | /* |
1057 | * For Oxford Semiconductor and Mainpine | ||
1058 | */ | ||
1059 | { | ||
1060 | .vendor = PCI_VENDOR_ID_OXSEMI, | ||
1061 | .device = PCI_ANY_ID, | ||
1062 | .subvendor = PCI_ANY_ID, | ||
1063 | .subdevice = PCI_ANY_ID, | ||
1064 | .init = pci_oxsemi_tornado_init, | ||
1065 | .setup = pci_default_setup, | ||
1066 | }, | ||
1067 | { | ||
1068 | .vendor = PCI_VENDOR_ID_MAINPINE, | ||
1069 | .device = PCI_ANY_ID, | ||
1070 | .subvendor = PCI_ANY_ID, | ||
1071 | .subdevice = PCI_ANY_ID, | ||
1072 | .init = pci_oxsemi_tornado_init, | ||
1073 | .setup = pci_default_setup, | ||
1074 | }, | ||
1075 | /* | ||
1021 | * Default "match everything" terminator entry | 1076 | * Default "match everything" terminator entry |
1022 | */ | 1077 | */ |
1023 | { | 1078 | { |
@@ -1048,7 +1103,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) | |||
1048 | } | 1103 | } |
1049 | 1104 | ||
1050 | static inline int get_pci_irq(struct pci_dev *dev, | 1105 | static inline int get_pci_irq(struct pci_dev *dev, |
1051 | struct pciserial_board *board) | 1106 | const struct pciserial_board *board) |
1052 | { | 1107 | { |
1053 | if (board->flags & FL_NOIRQ) | 1108 | if (board->flags & FL_NOIRQ) |
1054 | return 0; | 1109 | return 0; |
@@ -1843,8 +1898,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) | |||
1843 | } | 1898 | } |
1844 | 1899 | ||
1845 | static inline int | 1900 | static inline int |
1846 | serial_pci_matches(struct pciserial_board *board, | 1901 | serial_pci_matches(const struct pciserial_board *board, |
1847 | struct pciserial_board *guessed) | 1902 | const struct pciserial_board *guessed) |
1848 | { | 1903 | { |
1849 | return | 1904 | return |
1850 | board->num_ports == guessed->num_ports && | 1905 | board->num_ports == guessed->num_ports && |
@@ -1854,54 +1909,14 @@ serial_pci_matches(struct pciserial_board *board, | |||
1854 | board->first_offset == guessed->first_offset; | 1909 | board->first_offset == guessed->first_offset; |
1855 | } | 1910 | } |
1856 | 1911 | ||
1857 | /* | ||
1858 | * Oxford Semiconductor Inc. | ||
1859 | * Check that device is part of the Tornado range of devices, then determine | ||
1860 | * the number of ports available on the device. | ||
1861 | */ | ||
1862 | static int pci_oxsemi_tornado_init(struct pci_dev *dev, struct pciserial_board *board) | ||
1863 | { | ||
1864 | u8 __iomem *p; | ||
1865 | unsigned long deviceID; | ||
1866 | unsigned int number_uarts; | ||
1867 | |||
1868 | /* OxSemi Tornado devices are all 0xCxxx */ | ||
1869 | if (dev->vendor == PCI_VENDOR_ID_OXSEMI && | ||
1870 | (dev->device & 0xF000) != 0xC000) | ||
1871 | return 0; | ||
1872 | |||
1873 | p = pci_iomap(dev, 0, 5); | ||
1874 | if (p == NULL) | ||
1875 | return -ENOMEM; | ||
1876 | |||
1877 | deviceID = ioread32(p); | ||
1878 | /* Tornado device */ | ||
1879 | if (deviceID == 0x07000200) { | ||
1880 | number_uarts = ioread8(p + 4); | ||
1881 | board->num_ports = number_uarts; | ||
1882 | printk(KERN_DEBUG | ||
1883 | "%d ports detected on Oxford PCI Express device\n", | ||
1884 | number_uarts); | ||
1885 | } | ||
1886 | pci_iounmap(dev, p); | ||
1887 | return 0; | ||
1888 | } | ||
1889 | |||
1890 | struct serial_private * | 1912 | struct serial_private * |
1891 | pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board) | 1913 | pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) |
1892 | { | 1914 | { |
1893 | struct uart_port serial_port; | 1915 | struct uart_port serial_port; |
1894 | struct serial_private *priv; | 1916 | struct serial_private *priv; |
1895 | struct pci_serial_quirk *quirk; | 1917 | struct pci_serial_quirk *quirk; |
1896 | int rc, nr_ports, i; | 1918 | int rc, nr_ports, i; |
1897 | 1919 | ||
1898 | /* | ||
1899 | * Find number of ports on board | ||
1900 | */ | ||
1901 | if (dev->vendor == PCI_VENDOR_ID_OXSEMI || | ||
1902 | dev->vendor == PCI_VENDOR_ID_MAINPINE) | ||
1903 | pci_oxsemi_tornado_init(dev, board); | ||
1904 | |||
1905 | nr_ports = board->num_ports; | 1920 | nr_ports = board->num_ports; |
1906 | 1921 | ||
1907 | /* | 1922 | /* |
@@ -2028,7 +2043,8 @@ static int __devinit | |||
2028 | pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | 2043 | pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) |
2029 | { | 2044 | { |
2030 | struct serial_private *priv; | 2045 | struct serial_private *priv; |
2031 | struct pciserial_board *board, tmp; | 2046 | const struct pciserial_board *board; |
2047 | struct pciserial_board tmp; | ||
2032 | int rc; | 2048 | int rc; |
2033 | 2049 | ||
2034 | if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { | 2050 | if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { |
@@ -2055,7 +2071,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) | |||
2055 | * We matched one of our class entries. Try to | 2071 | * We matched one of our class entries. Try to |
2056 | * determine the parameters of this board. | 2072 | * determine the parameters of this board. |
2057 | */ | 2073 | */ |
2058 | rc = serial_pci_guess_board(dev, board); | 2074 | rc = serial_pci_guess_board(dev, &tmp); |
2059 | if (rc) | 2075 | if (rc) |
2060 | goto disable; | 2076 | goto disable; |
2061 | } else { | 2077 | } else { |
@@ -2271,6 +2287,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
2271 | { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, | 2287 | { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, |
2272 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2288 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2273 | pbn_b2_8_115200 }, | 2289 | pbn_b2_8_115200 }, |
2290 | { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803, | ||
2291 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
2292 | pbn_b2_8_460800 }, | ||
2274 | { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8, | 2293 | { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8, |
2275 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2294 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2276 | pbn_b2_8_115200 }, | 2295 | pbn_b2_8_115200 }, |
@@ -2372,6 +2391,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
2372 | * For now just used the hex ID 0x950a. | 2391 | * For now just used the hex ID 0x950a. |
2373 | */ | 2392 | */ |
2374 | { PCI_VENDOR_ID_OXSEMI, 0x950a, | 2393 | { PCI_VENDOR_ID_OXSEMI, 0x950a, |
2394 | PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, | ||
2395 | pbn_b0_2_115200 }, | ||
2396 | { PCI_VENDOR_ID_OXSEMI, 0x950a, | ||
2375 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2397 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2376 | pbn_b0_2_1130000 }, | 2398 | pbn_b0_2_1130000 }, |
2377 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, | 2399 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 569f0e2476c6..318d69dce8e1 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -22,7 +22,8 @@ | |||
22 | #include <linux/tty_flip.h> | 22 | #include <linux/tty_flip.h> |
23 | #include <linux/serial_core.h> | 23 | #include <linux/serial_core.h> |
24 | 24 | ||
25 | #ifdef CONFIG_KGDB_UART | 25 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
26 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
26 | #include <linux/kgdb.h> | 27 | #include <linux/kgdb.h> |
27 | #include <asm/irq_regs.h> | 28 | #include <asm/irq_regs.h> |
28 | #endif | 29 | #endif |
@@ -45,6 +46,16 @@ | |||
45 | static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | 46 | static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; |
46 | static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource); | 47 | static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource); |
47 | 48 | ||
49 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
50 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
51 | |||
52 | # ifndef CONFIG_SERIAL_BFIN_PIO | ||
53 | # error KGDB only support UART in PIO mode. | ||
54 | # endif | ||
55 | |||
56 | static int kgdboc_port_line; | ||
57 | static int kgdboc_break_enabled; | ||
58 | #endif | ||
48 | /* | 59 | /* |
49 | * Setup for console. Argument comes from the menuconfig | 60 | * Setup for console. Argument comes from the menuconfig |
50 | */ | 61 | */ |
@@ -62,13 +73,17 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart); | |||
62 | 73 | ||
63 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); | 74 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); |
64 | 75 | ||
76 | static void bfin_serial_reset_irda(struct uart_port *port); | ||
77 | |||
65 | /* | 78 | /* |
66 | * interrupts are disabled on entry | 79 | * interrupts are disabled on entry |
67 | */ | 80 | */ |
68 | static void bfin_serial_stop_tx(struct uart_port *port) | 81 | static void bfin_serial_stop_tx(struct uart_port *port) |
69 | { | 82 | { |
70 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 83 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
84 | #ifdef CONFIG_SERIAL_BFIN_DMA | ||
71 | struct circ_buf *xmit = &uart->port.info->xmit; | 85 | struct circ_buf *xmit = &uart->port.info->xmit; |
86 | #endif | ||
72 | 87 | ||
73 | while (!(UART_GET_LSR(uart) & TEMT)) | 88 | while (!(UART_GET_LSR(uart) & TEMT)) |
74 | cpu_relax(); | 89 | cpu_relax(); |
@@ -94,6 +109,14 @@ static void bfin_serial_stop_tx(struct uart_port *port) | |||
94 | static void bfin_serial_start_tx(struct uart_port *port) | 109 | static void bfin_serial_start_tx(struct uart_port *port) |
95 | { | 110 | { |
96 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 111 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
112 | struct tty_struct *tty = uart->port.info->port.tty; | ||
113 | |||
114 | /* | ||
115 | * To avoid losting RX interrupt, we reset IR function | ||
116 | * before sending data. | ||
117 | */ | ||
118 | if (tty->termios->c_line == N_IRDA) | ||
119 | bfin_serial_reset_irda(port); | ||
97 | 120 | ||
98 | #ifdef CONFIG_SERIAL_BFIN_DMA | 121 | #ifdef CONFIG_SERIAL_BFIN_DMA |
99 | if (uart->tx_done) | 122 | if (uart->tx_done) |
@@ -110,9 +133,7 @@ static void bfin_serial_start_tx(struct uart_port *port) | |||
110 | static void bfin_serial_stop_rx(struct uart_port *port) | 133 | static void bfin_serial_stop_rx(struct uart_port *port) |
111 | { | 134 | { |
112 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 135 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
113 | #ifdef CONFIG_KGDB_UART | 136 | |
114 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
115 | #endif | ||
116 | UART_CLEAR_IER(uart, ERBFI); | 137 | UART_CLEAR_IER(uart, ERBFI); |
117 | } | 138 | } |
118 | 139 | ||
@@ -123,49 +144,6 @@ static void bfin_serial_enable_ms(struct uart_port *port) | |||
123 | { | 144 | { |
124 | } | 145 | } |
125 | 146 | ||
126 | #ifdef CONFIG_KGDB_UART | ||
127 | static int kgdb_entry_state; | ||
128 | |||
129 | void kgdb_put_debug_char(int chr) | ||
130 | { | ||
131 | struct bfin_serial_port *uart; | ||
132 | |||
133 | if (CONFIG_KGDB_UART_PORT < 0 | ||
134 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) | ||
135 | uart = &bfin_serial_ports[0]; | ||
136 | else | ||
137 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
138 | |||
139 | while (!(UART_GET_LSR(uart) & THRE)) { | ||
140 | SSYNC(); | ||
141 | } | ||
142 | |||
143 | UART_CLEAR_DLAB(uart); | ||
144 | UART_PUT_CHAR(uart, (unsigned char)chr); | ||
145 | SSYNC(); | ||
146 | } | ||
147 | |||
148 | int kgdb_get_debug_char(void) | ||
149 | { | ||
150 | struct bfin_serial_port *uart; | ||
151 | unsigned char chr; | ||
152 | |||
153 | if (CONFIG_KGDB_UART_PORT < 0 | ||
154 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) | ||
155 | uart = &bfin_serial_ports[0]; | ||
156 | else | ||
157 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
158 | |||
159 | while(!(UART_GET_LSR(uart) & DR)) { | ||
160 | SSYNC(); | ||
161 | } | ||
162 | UART_CLEAR_DLAB(uart); | ||
163 | chr = UART_GET_CHAR(uart); | ||
164 | SSYNC(); | ||
165 | |||
166 | return chr; | ||
167 | } | ||
168 | #endif | ||
169 | 147 | ||
170 | #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO) | 148 | #if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO) |
171 | # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) | 149 | # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) |
@@ -178,7 +156,7 @@ int kgdb_get_debug_char(void) | |||
178 | #ifdef CONFIG_SERIAL_BFIN_PIO | 156 | #ifdef CONFIG_SERIAL_BFIN_PIO |
179 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | 157 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) |
180 | { | 158 | { |
181 | struct tty_struct *tty = uart->port.info->port.tty; | 159 | struct tty_struct *tty = NULL; |
182 | unsigned int status, ch, flg; | 160 | unsigned int status, ch, flg; |
183 | static struct timeval anomaly_start = { .tv_sec = 0 }; | 161 | static struct timeval anomaly_start = { .tv_sec = 0 }; |
184 | 162 | ||
@@ -188,27 +166,18 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
188 | ch = UART_GET_CHAR(uart); | 166 | ch = UART_GET_CHAR(uart); |
189 | uart->port.icount.rx++; | 167 | uart->port.icount.rx++; |
190 | 168 | ||
191 | #ifdef CONFIG_KGDB_UART | 169 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
192 | if (uart->port.line == CONFIG_KGDB_UART_PORT) { | 170 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
193 | struct pt_regs *regs = get_irq_regs(); | 171 | if (kgdb_connected && kgdboc_port_line == uart->port.line) |
194 | if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */ | 172 | if (ch == 0x3) {/* Ctrl + C */ |
195 | kgdb_breakkey_pressed(regs); | 173 | kgdb_breakpoint(); |
196 | return; | ||
197 | } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */ | ||
198 | kgdb_entry_state = 1; | ||
199 | } else if (kgdb_entry_state == 1 && ch == 'q') { | ||
200 | kgdb_entry_state = 0; | ||
201 | kgdb_breakkey_pressed(regs); | ||
202 | return; | ||
203 | } else if (ch == 0x3) {/* Ctrl + C */ | ||
204 | kgdb_entry_state = 0; | ||
205 | kgdb_breakkey_pressed(regs); | ||
206 | return; | 174 | return; |
207 | } else { | ||
208 | kgdb_entry_state = 0; | ||
209 | } | 175 | } |
210 | } | 176 | |
177 | if (!uart->port.info || !uart->port.info->tty) | ||
178 | return; | ||
211 | #endif | 179 | #endif |
180 | tty = uart->port.info->tty; | ||
212 | 181 | ||
213 | if (ANOMALY_05000363) { | 182 | if (ANOMALY_05000363) { |
214 | /* The BF533 (and BF561) family of processors have a nice anomaly | 183 | /* The BF533 (and BF561) family of processors have a nice anomaly |
@@ -250,6 +219,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
250 | return; | 219 | return; |
251 | 220 | ||
252 | known_good_char: | 221 | known_good_char: |
222 | status &= ~BI; | ||
253 | anomaly_start.tv_sec = 0; | 223 | anomaly_start.tv_sec = 0; |
254 | } | 224 | } |
255 | } | 225 | } |
@@ -445,7 +415,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
445 | 415 | ||
446 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | 416 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) |
447 | { | 417 | { |
448 | int x_pos, pos; | 418 | int x_pos, pos, flags; |
419 | |||
420 | spin_lock_irqsave(&uart->port.lock, flags); | ||
449 | 421 | ||
450 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); | 422 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); |
451 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); | 423 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); |
@@ -463,6 +435,8 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
463 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; | 435 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; |
464 | } | 436 | } |
465 | 437 | ||
438 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
439 | |||
466 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); | 440 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); |
467 | } | 441 | } |
468 | 442 | ||
@@ -497,10 +471,9 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) | |||
497 | spin_lock(&uart->port.lock); | 471 | spin_lock(&uart->port.lock); |
498 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); | 472 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); |
499 | clear_dma_irqstat(uart->rx_dma_channel); | 473 | clear_dma_irqstat(uart->rx_dma_channel); |
474 | bfin_serial_dma_rx_chars(uart); | ||
500 | spin_unlock(&uart->port.lock); | 475 | spin_unlock(&uart->port.lock); |
501 | 476 | ||
502 | mod_timer(&(uart->rx_dma_timer), jiffies); | ||
503 | |||
504 | return IRQ_HANDLED; | 477 | return IRQ_HANDLED; |
505 | } | 478 | } |
506 | #endif | 479 | #endif |
@@ -630,16 +603,16 @@ static int bfin_serial_startup(struct uart_port *port) | |||
630 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 603 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
631 | add_timer(&(uart->rx_dma_timer)); | 604 | add_timer(&(uart->rx_dma_timer)); |
632 | #else | 605 | #else |
606 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
607 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
608 | if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled) | ||
609 | kgdboc_break_enabled = 0; | ||
610 | else { | ||
611 | # endif | ||
633 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | 612 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, |
634 | "BFIN_UART_RX", uart)) { | 613 | "BFIN_UART_RX", uart)) { |
635 | # ifdef CONFIG_KGDB_UART | ||
636 | if (uart->port.line != CONFIG_KGDB_UART_PORT) { | ||
637 | # endif | ||
638 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); | 614 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
639 | return -EBUSY; | 615 | return -EBUSY; |
640 | # ifdef CONFIG_KGDB_UART | ||
641 | } | ||
642 | # endif | ||
643 | } | 616 | } |
644 | 617 | ||
645 | if (request_irq | 618 | if (request_irq |
@@ -685,6 +658,10 @@ static int bfin_serial_startup(struct uart_port *port) | |||
685 | } | 658 | } |
686 | } | 659 | } |
687 | # endif | 660 | # endif |
661 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
662 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
663 | } | ||
664 | # endif | ||
688 | #endif | 665 | #endif |
689 | UART_SET_IER(uart, ERBFI); | 666 | UART_SET_IER(uart, ERBFI); |
690 | return 0; | 667 | return 0; |
@@ -716,9 +693,6 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
716 | break; | 693 | break; |
717 | }; | 694 | }; |
718 | #endif | 695 | #endif |
719 | #ifdef CONFIG_KGDB_UART | ||
720 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | ||
721 | #endif | ||
722 | free_irq(uart->port.irq, uart); | 696 | free_irq(uart->port.irq, uart); |
723 | free_irq(uart->port.irq+1, uart); | 697 | free_irq(uart->port.irq+1, uart); |
724 | #endif | 698 | #endif |
@@ -887,6 +861,65 @@ static void bfin_serial_set_ldisc(struct uart_port *port) | |||
887 | } | 861 | } |
888 | } | 862 | } |
889 | 863 | ||
864 | #ifdef CONFIG_CONSOLE_POLL | ||
865 | static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) | ||
866 | { | ||
867 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
868 | |||
869 | while (!(UART_GET_LSR(uart) & THRE)) | ||
870 | cpu_relax(); | ||
871 | |||
872 | UART_CLEAR_DLAB(uart); | ||
873 | UART_PUT_CHAR(uart, (unsigned char)chr); | ||
874 | } | ||
875 | |||
876 | static int bfin_serial_poll_get_char(struct uart_port *port) | ||
877 | { | ||
878 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | ||
879 | unsigned char chr; | ||
880 | |||
881 | while (!(UART_GET_LSR(uart) & DR)) | ||
882 | cpu_relax(); | ||
883 | |||
884 | UART_CLEAR_DLAB(uart); | ||
885 | chr = UART_GET_CHAR(uart); | ||
886 | |||
887 | return chr; | ||
888 | } | ||
889 | #endif | ||
890 | |||
891 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
892 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
893 | static void bfin_kgdboc_port_shutdown(struct uart_port *port) | ||
894 | { | ||
895 | if (kgdboc_break_enabled) { | ||
896 | kgdboc_break_enabled = 0; | ||
897 | bfin_serial_shutdown(port); | ||
898 | } | ||
899 | } | ||
900 | |||
901 | static int bfin_kgdboc_port_startup(struct uart_port *port) | ||
902 | { | ||
903 | kgdboc_port_line = port->line; | ||
904 | kgdboc_break_enabled = !bfin_serial_startup(port); | ||
905 | return 0; | ||
906 | } | ||
907 | #endif | ||
908 | |||
909 | static void bfin_serial_reset_irda(struct uart_port *port) | ||
910 | { | ||
911 | int line = port->line; | ||
912 | unsigned short val; | ||
913 | |||
914 | val = UART_GET_GCTL(&bfin_serial_ports[line]); | ||
915 | val &= ~(IREN | RPOLC); | ||
916 | UART_PUT_GCTL(&bfin_serial_ports[line], val); | ||
917 | SSYNC(); | ||
918 | val |= (IREN | RPOLC); | ||
919 | UART_PUT_GCTL(&bfin_serial_ports[line], val); | ||
920 | SSYNC(); | ||
921 | } | ||
922 | |||
890 | static struct uart_ops bfin_serial_pops = { | 923 | static struct uart_ops bfin_serial_pops = { |
891 | .tx_empty = bfin_serial_tx_empty, | 924 | .tx_empty = bfin_serial_tx_empty, |
892 | .set_mctrl = bfin_serial_set_mctrl, | 925 | .set_mctrl = bfin_serial_set_mctrl, |
@@ -905,6 +938,15 @@ static struct uart_ops bfin_serial_pops = { | |||
905 | .request_port = bfin_serial_request_port, | 938 | .request_port = bfin_serial_request_port, |
906 | .config_port = bfin_serial_config_port, | 939 | .config_port = bfin_serial_config_port, |
907 | .verify_port = bfin_serial_verify_port, | 940 | .verify_port = bfin_serial_verify_port, |
941 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | ||
942 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | ||
943 | .kgdboc_port_startup = bfin_kgdboc_port_startup, | ||
944 | .kgdboc_port_shutdown = bfin_kgdboc_port_shutdown, | ||
945 | #endif | ||
946 | #ifdef CONFIG_CONSOLE_POLL | ||
947 | .poll_put_char = bfin_serial_poll_put_char, | ||
948 | .poll_get_char = bfin_serial_poll_get_char, | ||
949 | #endif | ||
908 | }; | 950 | }; |
909 | 951 | ||
910 | static void __init bfin_serial_init_ports(void) | 952 | static void __init bfin_serial_init_ports(void) |
@@ -950,7 +992,7 @@ static void __init bfin_serial_init_ports(void) | |||
950 | 992 | ||
951 | } | 993 | } |
952 | 994 | ||
953 | #ifdef CONFIG_SERIAL_BFIN_CONSOLE | 995 | #if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK) |
954 | /* | 996 | /* |
955 | * If the port was already initialised (eg, by a boot loader), | 997 | * If the port was already initialised (eg, by a boot loader), |
956 | * try to determine the current setup. | 998 | * try to determine the current setup. |
@@ -994,24 +1036,20 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, | |||
994 | } | 1036 | } |
995 | pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits); | 1037 | pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits); |
996 | } | 1038 | } |
997 | #endif | ||
998 | 1039 | ||
999 | #if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK) | ||
1000 | static struct uart_driver bfin_serial_reg; | 1040 | static struct uart_driver bfin_serial_reg; |
1001 | 1041 | ||
1002 | static int __init | 1042 | static int __init |
1003 | bfin_serial_console_setup(struct console *co, char *options) | 1043 | bfin_serial_console_setup(struct console *co, char *options) |
1004 | { | 1044 | { |
1005 | struct bfin_serial_port *uart; | 1045 | struct bfin_serial_port *uart; |
1006 | # ifdef CONFIG_SERIAL_BFIN_CONSOLE | ||
1007 | int baud = 57600; | 1046 | int baud = 57600; |
1008 | int bits = 8; | 1047 | int bits = 8; |
1009 | int parity = 'n'; | 1048 | int parity = 'n'; |
1010 | # ifdef CONFIG_SERIAL_BFIN_CTSRTS | 1049 | # ifdef CONFIG_SERIAL_BFIN_CTSRTS |
1011 | int flow = 'r'; | 1050 | int flow = 'r'; |
1012 | # else | 1051 | # else |
1013 | int flow = 'n'; | 1052 | int flow = 'n'; |
1014 | # endif | ||
1015 | # endif | 1053 | # endif |
1016 | 1054 | ||
1017 | /* | 1055 | /* |
@@ -1023,16 +1061,12 @@ bfin_serial_console_setup(struct console *co, char *options) | |||
1023 | co->index = 0; | 1061 | co->index = 0; |
1024 | uart = &bfin_serial_ports[co->index]; | 1062 | uart = &bfin_serial_ports[co->index]; |
1025 | 1063 | ||
1026 | # ifdef CONFIG_SERIAL_BFIN_CONSOLE | ||
1027 | if (options) | 1064 | if (options) |
1028 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1065 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
1029 | else | 1066 | else |
1030 | bfin_serial_console_get_options(uart, &baud, &parity, &bits); | 1067 | bfin_serial_console_get_options(uart, &baud, &parity, &bits); |
1031 | 1068 | ||
1032 | return uart_set_options(&uart->port, co, baud, parity, bits, flow); | 1069 | return uart_set_options(&uart->port, co, baud, parity, bits, flow); |
1033 | # else | ||
1034 | return 0; | ||
1035 | # endif | ||
1036 | } | 1070 | } |
1037 | #endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) || | 1071 | #endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) || |
1038 | defined (CONFIG_EARLY_PRINTK) */ | 1072 | defined (CONFIG_EARLY_PRINTK) */ |
@@ -1076,10 +1110,7 @@ static int __init bfin_serial_rs_console_init(void) | |||
1076 | { | 1110 | { |
1077 | bfin_serial_init_ports(); | 1111 | bfin_serial_init_ports(); |
1078 | register_console(&bfin_serial_console); | 1112 | register_console(&bfin_serial_console); |
1079 | #ifdef CONFIG_KGDB_UART | 1113 | |
1080 | kgdb_entry_state = 0; | ||
1081 | init_kgdb_uart(); | ||
1082 | #endif | ||
1083 | return 0; | 1114 | return 0; |
1084 | } | 1115 | } |
1085 | console_initcall(bfin_serial_rs_console_init); | 1116 | console_initcall(bfin_serial_rs_console_init); |
@@ -1144,7 +1175,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port, | |||
1144 | return &bfin_early_serial_console; | 1175 | return &bfin_early_serial_console; |
1145 | } | 1176 | } |
1146 | 1177 | ||
1147 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ | 1178 | #endif /* CONFIG_EARLY_PRINTK */ |
1148 | 1179 | ||
1149 | static struct uart_driver bfin_serial_reg = { | 1180 | static struct uart_driver bfin_serial_reg = { |
1150 | .owner = THIS_MODULE, | 1181 | .owner = THIS_MODULE, |
@@ -1235,10 +1266,6 @@ static struct platform_driver bfin_serial_driver = { | |||
1235 | static int __init bfin_serial_init(void) | 1266 | static int __init bfin_serial_init(void) |
1236 | { | 1267 | { |
1237 | int ret; | 1268 | int ret; |
1238 | #ifdef CONFIG_KGDB_UART | ||
1239 | struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | ||
1240 | struct ktermios t; | ||
1241 | #endif | ||
1242 | 1269 | ||
1243 | pr_info("Serial: Blackfin serial driver\n"); | 1270 | pr_info("Serial: Blackfin serial driver\n"); |
1244 | 1271 | ||
@@ -1252,21 +1279,6 @@ static int __init bfin_serial_init(void) | |||
1252 | uart_unregister_driver(&bfin_serial_reg); | 1279 | uart_unregister_driver(&bfin_serial_reg); |
1253 | } | 1280 | } |
1254 | } | 1281 | } |
1255 | #ifdef CONFIG_KGDB_UART | ||
1256 | if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) { | ||
1257 | request_irq(uart->port.irq, bfin_serial_rx_int, | ||
1258 | IRQF_DISABLED, "BFIN_UART_RX", uart); | ||
1259 | pr_info("Request irq for kgdb uart port\n"); | ||
1260 | UART_SET_IER(uart, ERBFI); | ||
1261 | SSYNC(); | ||
1262 | t.c_cflag = CS8|B57600; | ||
1263 | t.c_iflag = 0; | ||
1264 | t.c_oflag = 0; | ||
1265 | t.c_lflag = ICANON; | ||
1266 | t.c_line = CONFIG_KGDB_UART_PORT; | ||
1267 | bfin_serial_set_termios(&uart->port, &t, &t); | ||
1268 | } | ||
1269 | #endif | ||
1270 | return ret; | 1282 | return ret; |
1271 | } | 1283 | } |
1272 | 1284 | ||
@@ -1276,6 +1288,7 @@ static void __exit bfin_serial_exit(void) | |||
1276 | uart_unregister_driver(&bfin_serial_reg); | 1288 | uart_unregister_driver(&bfin_serial_reg); |
1277 | } | 1289 | } |
1278 | 1290 | ||
1291 | |||
1279 | module_init(bfin_serial_init); | 1292 | module_init(bfin_serial_init); |
1280 | module_exit(bfin_serial_exit); | 1293 | module_exit(bfin_serial_exit); |
1281 | 1294 | ||
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index dd8564d25051..529c0ff7952c 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
@@ -99,7 +99,7 @@ static void sport_stop_tx(struct uart_port *port); | |||
99 | 99 | ||
100 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | 100 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) |
101 | { | 101 | { |
102 | pr_debug("%s value:%x\n", __FUNCTION__, value); | 102 | pr_debug("%s value:%x\n", __func__, value); |
103 | /* Place a Start and Stop bit */ | 103 | /* Place a Start and Stop bit */ |
104 | __asm__ volatile ( | 104 | __asm__ volatile ( |
105 | "R2 = b#01111111100;\n\t" | 105 | "R2 = b#01111111100;\n\t" |
@@ -110,7 +110,7 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | |||
110 | :"=r"(value) | 110 | :"=r"(value) |
111 | :"0"(value) | 111 | :"0"(value) |
112 | :"R2", "R3"); | 112 | :"R2", "R3"); |
113 | pr_debug("%s value:%x\n", __FUNCTION__, value); | 113 | pr_debug("%s value:%x\n", __func__, value); |
114 | 114 | ||
115 | SPORT_PUT_TX(up, value); | 115 | SPORT_PUT_TX(up, value); |
116 | } | 116 | } |
@@ -120,7 +120,7 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up) | |||
120 | unsigned int value, extract; | 120 | unsigned int value, extract; |
121 | 121 | ||
122 | value = SPORT_GET_RX32(up); | 122 | value = SPORT_GET_RX32(up); |
123 | pr_debug("%s value:%x\n", __FUNCTION__, value); | 123 | pr_debug("%s value:%x\n", __func__, value); |
124 | 124 | ||
125 | /* Extract 8 bits data */ | 125 | /* Extract 8 bits data */ |
126 | __asm__ volatile ( | 126 | __asm__ volatile ( |
@@ -151,12 +151,12 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) | |||
151 | /* Set TCR1 and TCR2 */ | 151 | /* Set TCR1 and TCR2 */ |
152 | SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK)); | 152 | SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK)); |
153 | SPORT_PUT_TCR2(up, 10); | 153 | SPORT_PUT_TCR2(up, 10); |
154 | pr_debug("%s TCR1:%x, TCR2:%x\n", __FUNCTION__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); | 154 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); |
155 | 155 | ||
156 | /* Set RCR1 and RCR2 */ | 156 | /* Set RCR1 and RCR2 */ |
157 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); | 157 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); |
158 | SPORT_PUT_RCR2(up, 28); | 158 | SPORT_PUT_RCR2(up, 28); |
159 | pr_debug("%s RCR1:%x, RCR2:%x\n", __FUNCTION__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); | 159 | pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); |
160 | 160 | ||
161 | tclkdiv = sclk/(2 * baud_rate) - 1; | 161 | tclkdiv = sclk/(2 * baud_rate) - 1; |
162 | tfsdiv = 12; | 162 | tfsdiv = 12; |
@@ -166,7 +166,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) | |||
166 | SPORT_PUT_RCLKDIV(up, rclkdiv); | 166 | SPORT_PUT_RCLKDIV(up, rclkdiv); |
167 | SSYNC(); | 167 | SSYNC(); |
168 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n", | 168 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n", |
169 | __FUNCTION__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv); | 169 | __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv); |
170 | 170 | ||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
@@ -231,7 +231,7 @@ static int sport_startup(struct uart_port *port) | |||
231 | char buffer[20]; | 231 | char buffer[20]; |
232 | int retval; | 232 | int retval; |
233 | 233 | ||
234 | pr_debug("%s enter\n", __FUNCTION__); | 234 | pr_debug("%s enter\n", __func__); |
235 | memset(buffer, 20, '\0'); | 235 | memset(buffer, 20, '\0'); |
236 | snprintf(buffer, 20, "%s rx", up->name); | 236 | snprintf(buffer, 20, "%s rx", up->name); |
237 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 237 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); |
@@ -320,7 +320,7 @@ static unsigned int sport_tx_empty(struct uart_port *port) | |||
320 | unsigned int stat; | 320 | unsigned int stat; |
321 | 321 | ||
322 | stat = SPORT_GET_STAT(up); | 322 | stat = SPORT_GET_STAT(up); |
323 | pr_debug("%s stat:%04x\n", __FUNCTION__, stat); | 323 | pr_debug("%s stat:%04x\n", __func__, stat); |
324 | if (stat & TXHRE) { | 324 | if (stat & TXHRE) { |
325 | return TIOCSER_TEMT; | 325 | return TIOCSER_TEMT; |
326 | } else | 326 | } else |
@@ -329,13 +329,13 @@ static unsigned int sport_tx_empty(struct uart_port *port) | |||
329 | 329 | ||
330 | static unsigned int sport_get_mctrl(struct uart_port *port) | 330 | static unsigned int sport_get_mctrl(struct uart_port *port) |
331 | { | 331 | { |
332 | pr_debug("%s enter\n", __FUNCTION__); | 332 | pr_debug("%s enter\n", __func__); |
333 | return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR); | 333 | return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR); |
334 | } | 334 | } |
335 | 335 | ||
336 | static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | 336 | static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) |
337 | { | 337 | { |
338 | pr_debug("%s enter\n", __FUNCTION__); | 338 | pr_debug("%s enter\n", __func__); |
339 | } | 339 | } |
340 | 340 | ||
341 | static void sport_stop_tx(struct uart_port *port) | 341 | static void sport_stop_tx(struct uart_port *port) |
@@ -343,7 +343,7 @@ static void sport_stop_tx(struct uart_port *port) | |||
343 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 343 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
344 | unsigned int stat; | 344 | unsigned int stat; |
345 | 345 | ||
346 | pr_debug("%s enter\n", __FUNCTION__); | 346 | pr_debug("%s enter\n", __func__); |
347 | 347 | ||
348 | stat = SPORT_GET_STAT(up); | 348 | stat = SPORT_GET_STAT(up); |
349 | while(!(stat & TXHRE)) { | 349 | while(!(stat & TXHRE)) { |
@@ -366,21 +366,21 @@ static void sport_start_tx(struct uart_port *port) | |||
366 | { | 366 | { |
367 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 367 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
368 | 368 | ||
369 | pr_debug("%s enter\n", __FUNCTION__); | 369 | pr_debug("%s enter\n", __func__); |
370 | /* Write data into SPORT FIFO before enable SPROT to transmit */ | 370 | /* Write data into SPORT FIFO before enable SPROT to transmit */ |
371 | sport_uart_tx_chars(up); | 371 | sport_uart_tx_chars(up); |
372 | 372 | ||
373 | /* Enable transmit, then an interrupt will generated */ | 373 | /* Enable transmit, then an interrupt will generated */ |
374 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | 374 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); |
375 | SSYNC(); | 375 | SSYNC(); |
376 | pr_debug("%s exit\n", __FUNCTION__); | 376 | pr_debug("%s exit\n", __func__); |
377 | } | 377 | } |
378 | 378 | ||
379 | static void sport_stop_rx(struct uart_port *port) | 379 | static void sport_stop_rx(struct uart_port *port) |
380 | { | 380 | { |
381 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 381 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
382 | 382 | ||
383 | pr_debug("%s enter\n", __FUNCTION__); | 383 | pr_debug("%s enter\n", __func__); |
384 | /* Disable sport to stop rx */ | 384 | /* Disable sport to stop rx */ |
385 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); | 385 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); |
386 | SSYNC(); | 386 | SSYNC(); |
@@ -388,19 +388,19 @@ static void sport_stop_rx(struct uart_port *port) | |||
388 | 388 | ||
389 | static void sport_enable_ms(struct uart_port *port) | 389 | static void sport_enable_ms(struct uart_port *port) |
390 | { | 390 | { |
391 | pr_debug("%s enter\n", __FUNCTION__); | 391 | pr_debug("%s enter\n", __func__); |
392 | } | 392 | } |
393 | 393 | ||
394 | static void sport_break_ctl(struct uart_port *port, int break_state) | 394 | static void sport_break_ctl(struct uart_port *port, int break_state) |
395 | { | 395 | { |
396 | pr_debug("%s enter\n", __FUNCTION__); | 396 | pr_debug("%s enter\n", __func__); |
397 | } | 397 | } |
398 | 398 | ||
399 | static void sport_shutdown(struct uart_port *port) | 399 | static void sport_shutdown(struct uart_port *port) |
400 | { | 400 | { |
401 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 401 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
402 | 402 | ||
403 | pr_debug("%s enter\n", __FUNCTION__); | 403 | pr_debug("%s enter\n", __func__); |
404 | 404 | ||
405 | /* Disable sport */ | 405 | /* Disable sport */ |
406 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | 406 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); |
@@ -421,7 +421,7 @@ static void sport_shutdown(struct uart_port *port) | |||
421 | static void sport_set_termios(struct uart_port *port, | 421 | static void sport_set_termios(struct uart_port *port, |
422 | struct termios *termios, struct termios *old) | 422 | struct termios *termios, struct termios *old) |
423 | { | 423 | { |
424 | pr_debug("%s enter, c_cflag:%08x\n", __FUNCTION__, termios->c_cflag); | 424 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); |
425 | uart_update_timeout(port, CS8 ,port->uartclk); | 425 | uart_update_timeout(port, CS8 ,port->uartclk); |
426 | } | 426 | } |
427 | 427 | ||
@@ -429,18 +429,18 @@ static const char *sport_type(struct uart_port *port) | |||
429 | { | 429 | { |
430 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 430 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
431 | 431 | ||
432 | pr_debug("%s enter\n", __FUNCTION__); | 432 | pr_debug("%s enter\n", __func__); |
433 | return up->name; | 433 | return up->name; |
434 | } | 434 | } |
435 | 435 | ||
436 | static void sport_release_port(struct uart_port *port) | 436 | static void sport_release_port(struct uart_port *port) |
437 | { | 437 | { |
438 | pr_debug("%s enter\n", __FUNCTION__); | 438 | pr_debug("%s enter\n", __func__); |
439 | } | 439 | } |
440 | 440 | ||
441 | static int sport_request_port(struct uart_port *port) | 441 | static int sport_request_port(struct uart_port *port) |
442 | { | 442 | { |
443 | pr_debug("%s enter\n", __FUNCTION__); | 443 | pr_debug("%s enter\n", __func__); |
444 | return 0; | 444 | return 0; |
445 | } | 445 | } |
446 | 446 | ||
@@ -448,13 +448,13 @@ static void sport_config_port(struct uart_port *port, int flags) | |||
448 | { | 448 | { |
449 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 449 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
450 | 450 | ||
451 | pr_debug("%s enter\n", __FUNCTION__); | 451 | pr_debug("%s enter\n", __func__); |
452 | up->port.type = PORT_BFIN_SPORT; | 452 | up->port.type = PORT_BFIN_SPORT; |
453 | } | 453 | } |
454 | 454 | ||
455 | static int sport_verify_port(struct uart_port *port, struct serial_struct *ser) | 455 | static int sport_verify_port(struct uart_port *port, struct serial_struct *ser) |
456 | { | 456 | { |
457 | pr_debug("%s enter\n", __FUNCTION__); | 457 | pr_debug("%s enter\n", __func__); |
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
@@ -527,7 +527,7 @@ static int sport_uart_suspend(struct platform_device *dev, pm_message_t state) | |||
527 | { | 527 | { |
528 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 528 | struct sport_uart_port *sport = platform_get_drvdata(dev); |
529 | 529 | ||
530 | pr_debug("%s enter\n", __FUNCTION__); | 530 | pr_debug("%s enter\n", __func__); |
531 | if (sport) | 531 | if (sport) |
532 | uart_suspend_port(&sport_uart_reg, &sport->port); | 532 | uart_suspend_port(&sport_uart_reg, &sport->port); |
533 | 533 | ||
@@ -538,7 +538,7 @@ static int sport_uart_resume(struct platform_device *dev) | |||
538 | { | 538 | { |
539 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 539 | struct sport_uart_port *sport = platform_get_drvdata(dev); |
540 | 540 | ||
541 | pr_debug("%s enter\n", __FUNCTION__); | 541 | pr_debug("%s enter\n", __func__); |
542 | if (sport) | 542 | if (sport) |
543 | uart_resume_port(&sport_uart_reg, &sport->port); | 543 | uart_resume_port(&sport_uart_reg, &sport->port); |
544 | 544 | ||
@@ -547,7 +547,7 @@ static int sport_uart_resume(struct platform_device *dev) | |||
547 | 547 | ||
548 | static int sport_uart_probe(struct platform_device *dev) | 548 | static int sport_uart_probe(struct platform_device *dev) |
549 | { | 549 | { |
550 | pr_debug("%s enter\n", __FUNCTION__); | 550 | pr_debug("%s enter\n", __func__); |
551 | sport_uart_ports[dev->id].port.dev = &dev->dev; | 551 | sport_uart_ports[dev->id].port.dev = &dev->dev; |
552 | uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port); | 552 | uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port); |
553 | platform_set_drvdata(dev, &sport_uart_ports[dev->id]); | 553 | platform_set_drvdata(dev, &sport_uart_ports[dev->id]); |
@@ -559,7 +559,7 @@ static int sport_uart_remove(struct platform_device *dev) | |||
559 | { | 559 | { |
560 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 560 | struct sport_uart_port *sport = platform_get_drvdata(dev); |
561 | 561 | ||
562 | pr_debug("%s enter\n", __FUNCTION__); | 562 | pr_debug("%s enter\n", __func__); |
563 | platform_set_drvdata(dev, NULL); | 563 | platform_set_drvdata(dev, NULL); |
564 | 564 | ||
565 | if (sport) | 565 | if (sport) |
@@ -582,7 +582,7 @@ static int __init sport_uart_init(void) | |||
582 | { | 582 | { |
583 | int ret; | 583 | int ret; |
584 | 584 | ||
585 | pr_debug("%s enter\n", __FUNCTION__); | 585 | pr_debug("%s enter\n", __func__); |
586 | ret = uart_register_driver(&sport_uart_reg); | 586 | ret = uart_register_driver(&sport_uart_reg); |
587 | if (ret != 0) { | 587 | if (ret != 0) { |
588 | printk(KERN_ERR "Failed to register %s:%d\n", | 588 | printk(KERN_ERR "Failed to register %s:%d\n", |
@@ -597,13 +597,13 @@ static int __init sport_uart_init(void) | |||
597 | } | 597 | } |
598 | 598 | ||
599 | 599 | ||
600 | pr_debug("%s exit\n", __FUNCTION__); | 600 | pr_debug("%s exit\n", __func__); |
601 | return ret; | 601 | return ret; |
602 | } | 602 | } |
603 | 603 | ||
604 | static void __exit sport_uart_exit(void) | 604 | static void __exit sport_uart_exit(void) |
605 | { | 605 | { |
606 | pr_debug("%s enter\n", __FUNCTION__); | 606 | pr_debug("%s enter\n", __func__); |
607 | platform_driver_unregister(&sport_uart_driver); | 607 | platform_driver_unregister(&sport_uart_driver); |
608 | uart_unregister_driver(&sport_uart_reg); | 608 | uart_unregister_driver(&sport_uart_reg); |
609 | } | 609 | } |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index a697914ae3d0..3547558d2caf 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -272,7 +272,7 @@ static void jsm_tty_close(struct uart_port *port) | |||
272 | jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); | 272 | jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); |
273 | 273 | ||
274 | bd = channel->ch_bd; | 274 | bd = channel->ch_bd; |
275 | ts = channel->uart_port.info->port.tty->termios; | 275 | ts = port->info->port.tty->termios; |
276 | 276 | ||
277 | channel->ch_flags &= ~(CH_STOPI); | 277 | channel->ch_flags &= ~(CH_STOPI); |
278 | 278 | ||
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 874786a11fe9..dc68b7e0c930 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -50,7 +50,7 @@ static struct lock_class_key port_lock_key; | |||
50 | 50 | ||
51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 51 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
52 | 52 | ||
53 | #define uart_users(state) ((state)->count + ((state)->info ? (state)->info->port.blocked_open : 0)) | 53 | #define uart_users(state) ((state)->count + (state)->info.port.blocked_open) |
54 | 54 | ||
55 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | 55 | #ifdef CONFIG_SERIAL_CORE_CONSOLE |
56 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) | 56 | #define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) |
@@ -94,7 +94,7 @@ static void __uart_start(struct tty_struct *tty) | |||
94 | struct uart_state *state = tty->driver_data; | 94 | struct uart_state *state = tty->driver_data; |
95 | struct uart_port *port = state->port; | 95 | struct uart_port *port = state->port; |
96 | 96 | ||
97 | if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && | 97 | if (!uart_circ_empty(&state->info.xmit) && state->info.xmit.buf && |
98 | !tty->stopped && !tty->hw_stopped) | 98 | !tty->stopped && !tty->hw_stopped) |
99 | port->ops->start_tx(port); | 99 | port->ops->start_tx(port); |
100 | } | 100 | } |
@@ -113,7 +113,7 @@ static void uart_start(struct tty_struct *tty) | |||
113 | static void uart_tasklet_action(unsigned long data) | 113 | static void uart_tasklet_action(unsigned long data) |
114 | { | 114 | { |
115 | struct uart_state *state = (struct uart_state *)data; | 115 | struct uart_state *state = (struct uart_state *)data; |
116 | tty_wakeup(state->info->port.tty); | 116 | tty_wakeup(state->info.port.tty); |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void | 119 | static inline void |
@@ -139,7 +139,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
139 | */ | 139 | */ |
140 | static int uart_startup(struct uart_state *state, int init_hw) | 140 | static int uart_startup(struct uart_state *state, int init_hw) |
141 | { | 141 | { |
142 | struct uart_info *info = state->info; | 142 | struct uart_info *info = &state->info; |
143 | struct uart_port *port = state->port; | 143 | struct uart_port *port = state->port; |
144 | unsigned long page; | 144 | unsigned long page; |
145 | int retval = 0; | 145 | int retval = 0; |
@@ -212,14 +212,15 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
212 | */ | 212 | */ |
213 | static void uart_shutdown(struct uart_state *state) | 213 | static void uart_shutdown(struct uart_state *state) |
214 | { | 214 | { |
215 | struct uart_info *info = state->info; | 215 | struct uart_info *info = &state->info; |
216 | struct uart_port *port = state->port; | 216 | struct uart_port *port = state->port; |
217 | struct tty_struct *tty = info->port.tty; | ||
217 | 218 | ||
218 | /* | 219 | /* |
219 | * Set the TTY IO error marker | 220 | * Set the TTY IO error marker |
220 | */ | 221 | */ |
221 | if (info->port.tty) | 222 | if (tty) |
222 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | 223 | set_bit(TTY_IO_ERROR, &tty->flags); |
223 | 224 | ||
224 | if (info->flags & UIF_INITIALIZED) { | 225 | if (info->flags & UIF_INITIALIZED) { |
225 | info->flags &= ~UIF_INITIALIZED; | 226 | info->flags &= ~UIF_INITIALIZED; |
@@ -227,7 +228,7 @@ static void uart_shutdown(struct uart_state *state) | |||
227 | /* | 228 | /* |
228 | * Turn off DTR and RTS early. | 229 | * Turn off DTR and RTS early. |
229 | */ | 230 | */ |
230 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | 231 | if (!tty || (tty->termios->c_cflag & HUPCL)) |
231 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 232 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
232 | 233 | ||
233 | /* | 234 | /* |
@@ -427,7 +428,7 @@ EXPORT_SYMBOL(uart_get_divisor); | |||
427 | static void | 428 | static void |
428 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 429 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) |
429 | { | 430 | { |
430 | struct tty_struct *tty = state->info->port.tty; | 431 | struct tty_struct *tty = state->info.port.tty; |
431 | struct uart_port *port = state->port; | 432 | struct uart_port *port = state->port; |
432 | struct ktermios *termios; | 433 | struct ktermios *termios; |
433 | 434 | ||
@@ -444,14 +445,14 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | |||
444 | * Set flags based on termios cflag | 445 | * Set flags based on termios cflag |
445 | */ | 446 | */ |
446 | if (termios->c_cflag & CRTSCTS) | 447 | if (termios->c_cflag & CRTSCTS) |
447 | state->info->flags |= UIF_CTS_FLOW; | 448 | state->info.flags |= UIF_CTS_FLOW; |
448 | else | 449 | else |
449 | state->info->flags &= ~UIF_CTS_FLOW; | 450 | state->info.flags &= ~UIF_CTS_FLOW; |
450 | 451 | ||
451 | if (termios->c_cflag & CLOCAL) | 452 | if (termios->c_cflag & CLOCAL) |
452 | state->info->flags &= ~UIF_CHECK_CD; | 453 | state->info.flags &= ~UIF_CHECK_CD; |
453 | else | 454 | else |
454 | state->info->flags |= UIF_CHECK_CD; | 455 | state->info.flags |= UIF_CHECK_CD; |
455 | 456 | ||
456 | port->ops->set_termios(port, termios, old_termios); | 457 | port->ops->set_termios(port, termios, old_termios); |
457 | } | 458 | } |
@@ -479,7 +480,7 @@ static int uart_put_char(struct tty_struct *tty, unsigned char ch) | |||
479 | { | 480 | { |
480 | struct uart_state *state = tty->driver_data; | 481 | struct uart_state *state = tty->driver_data; |
481 | 482 | ||
482 | return __uart_put_char(state->port, &state->info->xmit, ch); | 483 | return __uart_put_char(state->port, &state->info.xmit, ch); |
483 | } | 484 | } |
484 | 485 | ||
485 | static void uart_flush_chars(struct tty_struct *tty) | 486 | static void uart_flush_chars(struct tty_struct *tty) |
@@ -500,13 +501,13 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
500 | * This means you called this function _after_ the port was | 501 | * This means you called this function _after_ the port was |
501 | * closed. No cookie for you. | 502 | * closed. No cookie for you. |
502 | */ | 503 | */ |
503 | if (!state || !state->info) { | 504 | if (!state) { |
504 | WARN_ON(1); | 505 | WARN_ON(1); |
505 | return -EL3HLT; | 506 | return -EL3HLT; |
506 | } | 507 | } |
507 | 508 | ||
508 | port = state->port; | 509 | port = state->port; |
509 | circ = &state->info->xmit; | 510 | circ = &state->info.xmit; |
510 | 511 | ||
511 | if (!circ->buf) | 512 | if (!circ->buf) |
512 | return 0; | 513 | return 0; |
@@ -537,7 +538,7 @@ static int uart_write_room(struct tty_struct *tty) | |||
537 | int ret; | 538 | int ret; |
538 | 539 | ||
539 | spin_lock_irqsave(&state->port->lock, flags); | 540 | spin_lock_irqsave(&state->port->lock, flags); |
540 | ret = uart_circ_chars_free(&state->info->xmit); | 541 | ret = uart_circ_chars_free(&state->info.xmit); |
541 | spin_unlock_irqrestore(&state->port->lock, flags); | 542 | spin_unlock_irqrestore(&state->port->lock, flags); |
542 | return ret; | 543 | return ret; |
543 | } | 544 | } |
@@ -549,7 +550,7 @@ static int uart_chars_in_buffer(struct tty_struct *tty) | |||
549 | int ret; | 550 | int ret; |
550 | 551 | ||
551 | spin_lock_irqsave(&state->port->lock, flags); | 552 | spin_lock_irqsave(&state->port->lock, flags); |
552 | ret = uart_circ_chars_pending(&state->info->xmit); | 553 | ret = uart_circ_chars_pending(&state->info.xmit); |
553 | spin_unlock_irqrestore(&state->port->lock, flags); | 554 | spin_unlock_irqrestore(&state->port->lock, flags); |
554 | return ret; | 555 | return ret; |
555 | } | 556 | } |
@@ -564,7 +565,7 @@ static void uart_flush_buffer(struct tty_struct *tty) | |||
564 | * This means you called this function _after_ the port was | 565 | * This means you called this function _after_ the port was |
565 | * closed. No cookie for you. | 566 | * closed. No cookie for you. |
566 | */ | 567 | */ |
567 | if (!state || !state->info) { | 568 | if (!state) { |
568 | WARN_ON(1); | 569 | WARN_ON(1); |
569 | return; | 570 | return; |
570 | } | 571 | } |
@@ -573,7 +574,7 @@ static void uart_flush_buffer(struct tty_struct *tty) | |||
573 | pr_debug("uart_flush_buffer(%d) called\n", tty->index); | 574 | pr_debug("uart_flush_buffer(%d) called\n", tty->index); |
574 | 575 | ||
575 | spin_lock_irqsave(&port->lock, flags); | 576 | spin_lock_irqsave(&port->lock, flags); |
576 | uart_circ_clear(&state->info->xmit); | 577 | uart_circ_clear(&state->info.xmit); |
577 | if (port->ops->flush_buffer) | 578 | if (port->ops->flush_buffer) |
578 | port->ops->flush_buffer(port); | 579 | port->ops->flush_buffer(port); |
579 | spin_unlock_irqrestore(&port->lock, flags); | 580 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -837,15 +838,15 @@ static int uart_set_info(struct uart_state *state, | |||
837 | state->closing_wait = closing_wait; | 838 | state->closing_wait = closing_wait; |
838 | if (new_serial.xmit_fifo_size) | 839 | if (new_serial.xmit_fifo_size) |
839 | port->fifosize = new_serial.xmit_fifo_size; | 840 | port->fifosize = new_serial.xmit_fifo_size; |
840 | if (state->info->port.tty) | 841 | if (state->info.port.tty) |
841 | state->info->port.tty->low_latency = | 842 | state->info.port.tty->low_latency = |
842 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 843 | (port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
843 | 844 | ||
844 | check_and_exit: | 845 | check_and_exit: |
845 | retval = 0; | 846 | retval = 0; |
846 | if (port->type == PORT_UNKNOWN) | 847 | if (port->type == PORT_UNKNOWN) |
847 | goto exit; | 848 | goto exit; |
848 | if (state->info->flags & UIF_INITIALIZED) { | 849 | if (state->info.flags & UIF_INITIALIZED) { |
849 | if (((old_flags ^ port->flags) & UPF_SPD_MASK) || | 850 | if (((old_flags ^ port->flags) & UPF_SPD_MASK) || |
850 | old_custom_divisor != port->custom_divisor) { | 851 | old_custom_divisor != port->custom_divisor) { |
851 | /* | 852 | /* |
@@ -858,7 +859,7 @@ static int uart_set_info(struct uart_state *state, | |||
858 | printk(KERN_NOTICE | 859 | printk(KERN_NOTICE |
859 | "%s sets custom speed on %s. This " | 860 | "%s sets custom speed on %s. This " |
860 | "is deprecated.\n", current->comm, | 861 | "is deprecated.\n", current->comm, |
861 | tty_name(state->info->port.tty, buf)); | 862 | tty_name(state->info.port.tty, buf)); |
862 | } | 863 | } |
863 | uart_change_speed(state, NULL); | 864 | uart_change_speed(state, NULL); |
864 | } | 865 | } |
@@ -889,8 +890,8 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
889 | * interrupt happens). | 890 | * interrupt happens). |
890 | */ | 891 | */ |
891 | if (port->x_char || | 892 | if (port->x_char || |
892 | ((uart_circ_chars_pending(&state->info->xmit) > 0) && | 893 | ((uart_circ_chars_pending(&state->info.xmit) > 0) && |
893 | !state->info->port.tty->stopped && !state->info->port.tty->hw_stopped)) | 894 | !state->info.port.tty->stopped && !state->info.port.tty->hw_stopped)) |
894 | result &= ~TIOCSER_TEMT; | 895 | result &= ~TIOCSER_TEMT; |
895 | 896 | ||
896 | return put_user(result, value); | 897 | return put_user(result, value); |
@@ -1017,7 +1018,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) | |||
1017 | port->ops->enable_ms(port); | 1018 | port->ops->enable_ms(port); |
1018 | spin_unlock_irq(&port->lock); | 1019 | spin_unlock_irq(&port->lock); |
1019 | 1020 | ||
1020 | add_wait_queue(&state->info->delta_msr_wait, &wait); | 1021 | add_wait_queue(&state->info.delta_msr_wait, &wait); |
1021 | for (;;) { | 1022 | for (;;) { |
1022 | spin_lock_irq(&port->lock); | 1023 | spin_lock_irq(&port->lock); |
1023 | memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); | 1024 | memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); |
@@ -1045,7 +1046,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) | |||
1045 | } | 1046 | } |
1046 | 1047 | ||
1047 | current->state = TASK_RUNNING; | 1048 | current->state = TASK_RUNNING; |
1048 | remove_wait_queue(&state->info->delta_msr_wait, &wait); | 1049 | remove_wait_queue(&state->info.delta_msr_wait, &wait); |
1049 | 1050 | ||
1050 | return ret; | 1051 | return ret; |
1051 | } | 1052 | } |
@@ -1241,7 +1242,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1241 | */ | 1242 | */ |
1242 | if (!(old_termios->c_cflag & CLOCAL) && | 1243 | if (!(old_termios->c_cflag & CLOCAL) && |
1243 | (tty->termios->c_cflag & CLOCAL)) | 1244 | (tty->termios->c_cflag & CLOCAL)) |
1244 | wake_up_interruptible(&state->info->port.open_wait); | 1245 | wake_up_interruptible(&info->port.open_wait); |
1245 | #endif | 1246 | #endif |
1246 | } | 1247 | } |
1247 | 1248 | ||
@@ -1303,7 +1304,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1303 | * At this point, we stop accepting input. To do this, we | 1304 | * At this point, we stop accepting input. To do this, we |
1304 | * disable the receive line status interrupts. | 1305 | * disable the receive line status interrupts. |
1305 | */ | 1306 | */ |
1306 | if (state->info->flags & UIF_INITIALIZED) { | 1307 | if (state->info.flags & UIF_INITIALIZED) { |
1307 | unsigned long flags; | 1308 | unsigned long flags; |
1308 | spin_lock_irqsave(&port->lock, flags); | 1309 | spin_lock_irqsave(&port->lock, flags); |
1309 | port->ops->stop_rx(port); | 1310 | port->ops->stop_rx(port); |
@@ -1322,9 +1323,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1322 | tty_ldisc_flush(tty); | 1323 | tty_ldisc_flush(tty); |
1323 | 1324 | ||
1324 | tty->closing = 0; | 1325 | tty->closing = 0; |
1325 | state->info->port.tty = NULL; | 1326 | state->info.port.tty = NULL; |
1326 | 1327 | ||
1327 | if (state->info->port.blocked_open) { | 1328 | if (state->info.port.blocked_open) { |
1328 | if (state->close_delay) | 1329 | if (state->close_delay) |
1329 | msleep_interruptible(state->close_delay); | 1330 | msleep_interruptible(state->close_delay); |
1330 | } else if (!uart_console(port)) { | 1331 | } else if (!uart_console(port)) { |
@@ -1334,8 +1335,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1334 | /* | 1335 | /* |
1335 | * Wake up anyone trying to open this port. | 1336 | * Wake up anyone trying to open this port. |
1336 | */ | 1337 | */ |
1337 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1338 | state->info.flags &= ~UIF_NORMAL_ACTIVE; |
1338 | wake_up_interruptible(&state->info->port.open_wait); | 1339 | wake_up_interruptible(&state->info.port.open_wait); |
1339 | 1340 | ||
1340 | done: | 1341 | done: |
1341 | mutex_unlock(&state->mutex); | 1342 | mutex_unlock(&state->mutex); |
@@ -1409,19 +1410,20 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1409 | static void uart_hangup(struct tty_struct *tty) | 1410 | static void uart_hangup(struct tty_struct *tty) |
1410 | { | 1411 | { |
1411 | struct uart_state *state = tty->driver_data; | 1412 | struct uart_state *state = tty->driver_data; |
1413 | struct uart_info *info = &state->info; | ||
1412 | 1414 | ||
1413 | BUG_ON(!kernel_locked()); | 1415 | BUG_ON(!kernel_locked()); |
1414 | pr_debug("uart_hangup(%d)\n", state->port->line); | 1416 | pr_debug("uart_hangup(%d)\n", state->port->line); |
1415 | 1417 | ||
1416 | mutex_lock(&state->mutex); | 1418 | mutex_lock(&state->mutex); |
1417 | if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { | 1419 | if (info->flags & UIF_NORMAL_ACTIVE) { |
1418 | uart_flush_buffer(tty); | 1420 | uart_flush_buffer(tty); |
1419 | uart_shutdown(state); | 1421 | uart_shutdown(state); |
1420 | state->count = 0; | 1422 | state->count = 0; |
1421 | state->info->flags &= ~UIF_NORMAL_ACTIVE; | 1423 | info->flags &= ~UIF_NORMAL_ACTIVE; |
1422 | state->info->port.tty = NULL; | 1424 | info->port.tty = NULL; |
1423 | wake_up_interruptible(&state->info->port.open_wait); | 1425 | wake_up_interruptible(&info->port.open_wait); |
1424 | wake_up_interruptible(&state->info->delta_msr_wait); | 1426 | wake_up_interruptible(&info->delta_msr_wait); |
1425 | } | 1427 | } |
1426 | mutex_unlock(&state->mutex); | 1428 | mutex_unlock(&state->mutex); |
1427 | } | 1429 | } |
@@ -1434,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty) | |||
1434 | */ | 1436 | */ |
1435 | static void uart_update_termios(struct uart_state *state) | 1437 | static void uart_update_termios(struct uart_state *state) |
1436 | { | 1438 | { |
1437 | struct tty_struct *tty = state->info->port.tty; | 1439 | struct tty_struct *tty = state->info.port.tty; |
1438 | struct uart_port *port = state->port; | 1440 | struct uart_port *port = state->port; |
1439 | 1441 | ||
1440 | if (uart_console(port) && port->cons->cflag) { | 1442 | if (uart_console(port) && port->cons->cflag) { |
@@ -1469,7 +1471,7 @@ static int | |||
1469 | uart_block_til_ready(struct file *filp, struct uart_state *state) | 1471 | uart_block_til_ready(struct file *filp, struct uart_state *state) |
1470 | { | 1472 | { |
1471 | DECLARE_WAITQUEUE(wait, current); | 1473 | DECLARE_WAITQUEUE(wait, current); |
1472 | struct uart_info *info = state->info; | 1474 | struct uart_info *info = &state->info; |
1473 | struct uart_port *port = state->port; | 1475 | struct uart_port *port = state->port; |
1474 | unsigned int mctrl; | 1476 | unsigned int mctrl; |
1475 | 1477 | ||
@@ -1563,28 +1565,6 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1563 | ret = -ENXIO; | 1565 | ret = -ENXIO; |
1564 | goto err_unlock; | 1566 | goto err_unlock; |
1565 | } | 1567 | } |
1566 | |||
1567 | /* BKL: RACE HERE - LEAK */ | ||
1568 | /* We should move this into the uart_state structure and kill off | ||
1569 | this whole complexity */ | ||
1570 | if (!state->info) { | ||
1571 | state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL); | ||
1572 | if (state->info) { | ||
1573 | init_waitqueue_head(&state->info->port.open_wait); | ||
1574 | init_waitqueue_head(&state->info->delta_msr_wait); | ||
1575 | |||
1576 | /* | ||
1577 | * Link the info into the other structures. | ||
1578 | */ | ||
1579 | state->port->info = state->info; | ||
1580 | |||
1581 | tasklet_init(&state->info->tlet, uart_tasklet_action, | ||
1582 | (unsigned long)state); | ||
1583 | } else { | ||
1584 | ret = -ENOMEM; | ||
1585 | goto err_unlock; | ||
1586 | } | ||
1587 | } | ||
1588 | return state; | 1568 | return state; |
1589 | 1569 | ||
1590 | err_unlock: | 1570 | err_unlock: |
@@ -1641,9 +1621,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1641 | * Any failures from here onwards should not touch the count. | 1621 | * Any failures from here onwards should not touch the count. |
1642 | */ | 1622 | */ |
1643 | tty->driver_data = state; | 1623 | tty->driver_data = state; |
1624 | state->port->info = &state->info; | ||
1644 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; | 1625 | tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; |
1645 | tty->alt_speed = 0; | 1626 | tty->alt_speed = 0; |
1646 | state->info->port.tty = tty; | 1627 | state->info.port.tty = tty; |
1647 | 1628 | ||
1648 | /* | 1629 | /* |
1649 | * If the port is in the middle of closing, bail out now. | 1630 | * If the port is in the middle of closing, bail out now. |
@@ -1676,8 +1657,8 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1676 | /* | 1657 | /* |
1677 | * If this is the first open to succeed, adjust things to suit. | 1658 | * If this is the first open to succeed, adjust things to suit. |
1678 | */ | 1659 | */ |
1679 | if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { | 1660 | if (retval == 0 && !(state->info.flags & UIF_NORMAL_ACTIVE)) { |
1680 | state->info->flags |= UIF_NORMAL_ACTIVE; | 1661 | state->info.flags |= UIF_NORMAL_ACTIVE; |
1681 | 1662 | ||
1682 | uart_update_termios(state); | 1663 | uart_update_termios(state); |
1683 | } | 1664 | } |
@@ -2028,11 +2009,11 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | |||
2028 | } | 2009 | } |
2029 | port->suspended = 1; | 2010 | port->suspended = 1; |
2030 | 2011 | ||
2031 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 2012 | if (state->info.flags & UIF_INITIALIZED) { |
2032 | const struct uart_ops *ops = port->ops; | 2013 | const struct uart_ops *ops = port->ops; |
2033 | int tries; | 2014 | int tries; |
2034 | 2015 | ||
2035 | state->info->flags = (state->info->flags & ~UIF_INITIALIZED) | 2016 | state->info.flags = (state->info.flags & ~UIF_INITIALIZED) |
2036 | | UIF_SUSPENDED; | 2017 | | UIF_SUSPENDED; |
2037 | 2018 | ||
2038 | spin_lock_irq(&port->lock); | 2019 | spin_lock_irq(&port->lock); |
@@ -2107,15 +2088,15 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2107 | /* | 2088 | /* |
2108 | * If that's unset, use the tty termios setting. | 2089 | * If that's unset, use the tty termios setting. |
2109 | */ | 2090 | */ |
2110 | if (state->info && state->info->port.tty && termios.c_cflag == 0) | 2091 | if (state->info.port.tty && termios.c_cflag == 0) |
2111 | termios = *state->info->port.tty->termios; | 2092 | termios = *state->info.port.tty->termios; |
2112 | 2093 | ||
2113 | uart_change_pm(state, 0); | 2094 | uart_change_pm(state, 0); |
2114 | port->ops->set_termios(port, &termios, NULL); | 2095 | port->ops->set_termios(port, &termios, NULL); |
2115 | console_start(port->cons); | 2096 | console_start(port->cons); |
2116 | } | 2097 | } |
2117 | 2098 | ||
2118 | if (state->info && state->info->flags & UIF_SUSPENDED) { | 2099 | if (state->info.flags & UIF_SUSPENDED) { |
2119 | const struct uart_ops *ops = port->ops; | 2100 | const struct uart_ops *ops = port->ops; |
2120 | int ret; | 2101 | int ret; |
2121 | 2102 | ||
@@ -2130,7 +2111,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2130 | ops->set_mctrl(port, port->mctrl); | 2111 | ops->set_mctrl(port, port->mctrl); |
2131 | ops->start_tx(port); | 2112 | ops->start_tx(port); |
2132 | spin_unlock_irq(&port->lock); | 2113 | spin_unlock_irq(&port->lock); |
2133 | state->info->flags |= UIF_INITIALIZED; | 2114 | state->info.flags |= UIF_INITIALIZED; |
2134 | } else { | 2115 | } else { |
2135 | /* | 2116 | /* |
2136 | * Failed to resume - maybe hardware went away? | 2117 | * Failed to resume - maybe hardware went away? |
@@ -2140,7 +2121,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
2140 | uart_shutdown(state); | 2121 | uart_shutdown(state); |
2141 | } | 2122 | } |
2142 | 2123 | ||
2143 | state->info->flags &= ~UIF_SUSPENDED; | 2124 | state->info.flags &= ~UIF_SUSPENDED; |
2144 | } | 2125 | } |
2145 | 2126 | ||
2146 | mutex_unlock(&state->mutex); | 2127 | mutex_unlock(&state->mutex); |
@@ -2198,11 +2179,14 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, | |||
2198 | * Now do the auto configuration stuff. Note that config_port | 2179 | * Now do the auto configuration stuff. Note that config_port |
2199 | * is expected to claim the resources and map the port for us. | 2180 | * is expected to claim the resources and map the port for us. |
2200 | */ | 2181 | */ |
2201 | flags = UART_CONFIG_TYPE; | 2182 | flags = 0; |
2202 | if (port->flags & UPF_AUTO_IRQ) | 2183 | if (port->flags & UPF_AUTO_IRQ) |
2203 | flags |= UART_CONFIG_IRQ; | 2184 | flags |= UART_CONFIG_IRQ; |
2204 | if (port->flags & UPF_BOOT_AUTOCONF) { | 2185 | if (port->flags & UPF_BOOT_AUTOCONF) { |
2205 | port->type = PORT_UNKNOWN; | 2186 | if (!(port->flags & UPF_FIXED_TYPE)) { |
2187 | port->type = PORT_UNKNOWN; | ||
2188 | flags |= UART_CONFIG_TYPE; | ||
2189 | } | ||
2206 | port->ops->config_port(port, flags); | 2190 | port->ops->config_port(port, flags); |
2207 | } | 2191 | } |
2208 | 2192 | ||
@@ -2383,8 +2367,12 @@ int uart_register_driver(struct uart_driver *drv) | |||
2383 | 2367 | ||
2384 | state->close_delay = 500; /* .5 seconds */ | 2368 | state->close_delay = 500; /* .5 seconds */ |
2385 | state->closing_wait = 30000; /* 30 seconds */ | 2369 | state->closing_wait = 30000; /* 30 seconds */ |
2386 | |||
2387 | mutex_init(&state->mutex); | 2370 | mutex_init(&state->mutex); |
2371 | |||
2372 | tty_port_init(&state->info.port); | ||
2373 | init_waitqueue_head(&state->info.delta_msr_wait); | ||
2374 | tasklet_init(&state->info.tlet, uart_tasklet_action, | ||
2375 | (unsigned long)state); | ||
2388 | } | 2376 | } |
2389 | 2377 | ||
2390 | retval = tty_register_driver(normal); | 2378 | retval = tty_register_driver(normal); |
@@ -2455,7 +2443,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2455 | state->pm_state = -1; | 2443 | state->pm_state = -1; |
2456 | 2444 | ||
2457 | port->cons = drv->cons; | 2445 | port->cons = drv->cons; |
2458 | port->info = state->info; | 2446 | port->info = &state->info; |
2459 | 2447 | ||
2460 | /* | 2448 | /* |
2461 | * If this port is a console, then the spinlock is already | 2449 | * If this port is a console, then the spinlock is already |
@@ -2527,18 +2515,11 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2527 | */ | 2515 | */ |
2528 | tty_unregister_device(drv->tty_driver, port->line); | 2516 | tty_unregister_device(drv->tty_driver, port->line); |
2529 | 2517 | ||
2530 | info = state->info; | 2518 | info = &state->info; |
2531 | if (info && info->port.tty) | 2519 | if (info && info->port.tty) |
2532 | tty_vhangup(info->port.tty); | 2520 | tty_vhangup(info->port.tty); |
2533 | 2521 | ||
2534 | /* | 2522 | /* |
2535 | * All users of this port should now be disconnected from | ||
2536 | * this driver, and the port shut down. We should be the | ||
2537 | * only thread fiddling with this port from now on. | ||
2538 | */ | ||
2539 | state->info = NULL; | ||
2540 | |||
2541 | /* | ||
2542 | * Free the port IO and memory resources, if any. | 2523 | * Free the port IO and memory resources, if any. |
2543 | */ | 2524 | */ |
2544 | if (port->type != PORT_UNKNOWN) | 2525 | if (port->type != PORT_UNKNOWN) |
@@ -2552,10 +2533,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2552 | /* | 2533 | /* |
2553 | * Kill the tasklet, and free resources. | 2534 | * Kill the tasklet, and free resources. |
2554 | */ | 2535 | */ |
2555 | if (info) { | 2536 | if (info) |
2556 | tasklet_kill(&info->tlet); | 2537 | tasklet_kill(&info->tlet); |
2557 | kfree(info); | ||
2558 | } | ||
2559 | 2538 | ||
2560 | state->port = NULL; | 2539 | state->port = NULL; |
2561 | mutex_unlock(&port_mutex); | 2540 | mutex_unlock(&port_mutex); |
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 64be4d88df11..8582236e4cad 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c | |||
@@ -54,7 +54,6 @@ | |||
54 | * DWA). | 54 | * DWA). |
55 | */ | 55 | */ |
56 | #include <linux/kernel.h> | 56 | #include <linux/kernel.h> |
57 | #include <linux/version.h> | ||
58 | #include <linux/init.h> | 57 | #include <linux/init.h> |
59 | #include <linux/module.h> | 58 | #include <linux/module.h> |
60 | #include <linux/workqueue.h> | 59 | #include <linux/workqueue.h> |
@@ -63,16 +62,12 @@ | |||
63 | #include "../wusbcore/wa-hc.h" | 62 | #include "../wusbcore/wa-hc.h" |
64 | #include "../wusbcore/wusbhc.h" | 63 | #include "../wusbcore/wusbhc.h" |
65 | 64 | ||
66 | #define D_LOCAL 0 | ||
67 | #include <linux/uwb/debug.h> | ||
68 | |||
69 | struct hwahc { | 65 | struct hwahc { |
70 | struct wusbhc wusbhc; /* has to be 1st */ | 66 | struct wusbhc wusbhc; /* has to be 1st */ |
71 | struct wahc wa; | 67 | struct wahc wa; |
72 | u8 buffer[16]; /* for misc usb transactions */ | ||
73 | }; | 68 | }; |
74 | 69 | ||
75 | /** | 70 | /* |
76 | * FIXME should be wusbhc | 71 | * FIXME should be wusbhc |
77 | * | 72 | * |
78 | * NOTE: we need to cache the Cluster ID because later...there is no | 73 | * NOTE: we need to cache the Cluster ID because later...there is no |
@@ -126,7 +121,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) | |||
126 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | 121 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); |
127 | struct device *dev = &hwahc->wa.usb_iface->dev; | 122 | struct device *dev = &hwahc->wa.usb_iface->dev; |
128 | 123 | ||
129 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
130 | mutex_lock(&wusbhc->mutex); | 124 | mutex_lock(&wusbhc->mutex); |
131 | wa_nep_disarm(&hwahc->wa); | 125 | wa_nep_disarm(&hwahc->wa); |
132 | result = __wa_set_feature(&hwahc->wa, WA_RESET); | 126 | result = __wa_set_feature(&hwahc->wa, WA_RESET); |
@@ -134,7 +128,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) | |||
134 | dev_err(dev, "error commanding HC to reset: %d\n", result); | 128 | dev_err(dev, "error commanding HC to reset: %d\n", result); |
135 | goto error_unlock; | 129 | goto error_unlock; |
136 | } | 130 | } |
137 | d_printf(3, dev, "reset: waiting for device to change state\n"); | ||
138 | result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0); | 131 | result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0); |
139 | if (result < 0) { | 132 | if (result < 0) { |
140 | dev_err(dev, "error waiting for HC to reset: %d\n", result); | 133 | dev_err(dev, "error waiting for HC to reset: %d\n", result); |
@@ -142,7 +135,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) | |||
142 | } | 135 | } |
143 | error_unlock: | 136 | error_unlock: |
144 | mutex_unlock(&wusbhc->mutex); | 137 | mutex_unlock(&wusbhc->mutex); |
145 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
146 | return result; | 138 | return result; |
147 | } | 139 | } |
148 | 140 | ||
@@ -155,15 +147,9 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) | |||
155 | int result; | 147 | int result; |
156 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 148 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
157 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | 149 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); |
158 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
159 | 150 | ||
160 | /* Set up a Host Info WUSB Information Element */ | ||
161 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
162 | result = -ENOSPC; | 151 | result = -ENOSPC; |
163 | mutex_lock(&wusbhc->mutex); | 152 | mutex_lock(&wusbhc->mutex); |
164 | /* Start the numbering from the top so that the bottom | ||
165 | * range of the unauth addr space is used for devices, | ||
166 | * the top for HCs; use 0xfe - RC# */ | ||
167 | addr = wusb_cluster_id_get(); | 153 | addr = wusb_cluster_id_get(); |
168 | if (addr == 0) | 154 | if (addr == 0) |
169 | goto error_cluster_id_get; | 155 | goto error_cluster_id_get; |
@@ -171,22 +157,14 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) | |||
171 | if (result < 0) | 157 | if (result < 0) |
172 | goto error_set_cluster_id; | 158 | goto error_set_cluster_id; |
173 | 159 | ||
174 | result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); | ||
175 | if (result < 0) { | ||
176 | dev_err(dev, "cannot listen to notifications: %d\n", result); | ||
177 | goto error_stop; | ||
178 | } | ||
179 | usb_hcd->uses_new_polling = 1; | 160 | usb_hcd->uses_new_polling = 1; |
180 | usb_hcd->poll_rh = 1; | 161 | usb_hcd->poll_rh = 1; |
181 | usb_hcd->state = HC_STATE_RUNNING; | 162 | usb_hcd->state = HC_STATE_RUNNING; |
182 | result = 0; | 163 | result = 0; |
183 | out: | 164 | out: |
184 | mutex_unlock(&wusbhc->mutex); | 165 | mutex_unlock(&wusbhc->mutex); |
185 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
186 | return result; | 166 | return result; |
187 | 167 | ||
188 | error_stop: | ||
189 | __wa_stop(&hwahc->wa); | ||
190 | error_set_cluster_id: | 168 | error_set_cluster_id: |
191 | wusb_cluster_id_put(wusbhc->cluster_id); | 169 | wusb_cluster_id_put(wusbhc->cluster_id); |
192 | error_cluster_id_get: | 170 | error_cluster_id_get: |
@@ -194,39 +172,6 @@ error_cluster_id_get: | |||
194 | 172 | ||
195 | } | 173 | } |
196 | 174 | ||
197 | /* | ||
198 | * FIXME: break this function up | ||
199 | */ | ||
200 | static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) | ||
201 | { | ||
202 | int result; | ||
203 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
204 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
205 | |||
206 | /* Set up a Host Info WUSB Information Element */ | ||
207 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
208 | result = -ENOSPC; | ||
209 | |||
210 | result = __wa_set_feature(&hwahc->wa, WA_ENABLE); | ||
211 | if (result < 0) { | ||
212 | dev_err(dev, "error commanding HC to start: %d\n", result); | ||
213 | goto error_stop; | ||
214 | } | ||
215 | result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); | ||
216 | if (result < 0) { | ||
217 | dev_err(dev, "error waiting for HC to start: %d\n", result); | ||
218 | goto error_stop; | ||
219 | } | ||
220 | result = 0; | ||
221 | out: | ||
222 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
223 | return result; | ||
224 | |||
225 | error_stop: | ||
226 | result = __wa_clear_feature(&hwahc->wa, WA_ENABLE); | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) | 175 | static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) |
231 | { | 176 | { |
232 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 177 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
@@ -246,18 +191,6 @@ static int hwahc_op_resume(struct usb_hcd *usb_hcd) | |||
246 | return -ENOSYS; | 191 | return -ENOSYS; |
247 | } | 192 | } |
248 | 193 | ||
249 | static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) | ||
250 | { | ||
251 | int result; | ||
252 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
253 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
254 | |||
255 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
256 | /* Nothing for now */ | ||
257 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | /* | 194 | /* |
262 | * No need to abort pipes, as when this is called, all the children | 195 | * No need to abort pipes, as when this is called, all the children |
263 | * has been disconnected and that has done it [through | 196 | * has been disconnected and that has done it [through |
@@ -266,21 +199,11 @@ static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) | |||
266 | */ | 199 | */ |
267 | static void hwahc_op_stop(struct usb_hcd *usb_hcd) | 200 | static void hwahc_op_stop(struct usb_hcd *usb_hcd) |
268 | { | 201 | { |
269 | int result; | ||
270 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 202 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
271 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
272 | struct wahc *wa = &hwahc->wa; | ||
273 | struct device *dev = &wa->usb_iface->dev; | ||
274 | 203 | ||
275 | d_fnstart(4, dev, "(hwahc %p)\n", hwahc); | ||
276 | mutex_lock(&wusbhc->mutex); | 204 | mutex_lock(&wusbhc->mutex); |
277 | wusbhc_stop(wusbhc); | ||
278 | wa_nep_disarm(&hwahc->wa); | ||
279 | result = __wa_stop(&hwahc->wa); | ||
280 | wusb_cluster_id_put(wusbhc->cluster_id); | 205 | wusb_cluster_id_put(wusbhc->cluster_id); |
281 | mutex_unlock(&wusbhc->mutex); | 206 | mutex_unlock(&wusbhc->mutex); |
282 | d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); | ||
283 | return; | ||
284 | } | 207 | } |
285 | 208 | ||
286 | static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd) | 209 | static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd) |
@@ -325,6 +248,54 @@ static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd, | |||
325 | rpipe_ep_disable(&hwahc->wa, ep); | 248 | rpipe_ep_disable(&hwahc->wa, ep); |
326 | } | 249 | } |
327 | 250 | ||
251 | static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) | ||
252 | { | ||
253 | int result; | ||
254 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
255 | struct device *dev = &hwahc->wa.usb_iface->dev; | ||
256 | |||
257 | result = __wa_set_feature(&hwahc->wa, WA_ENABLE); | ||
258 | if (result < 0) { | ||
259 | dev_err(dev, "error commanding HC to start: %d\n", result); | ||
260 | goto error_stop; | ||
261 | } | ||
262 | result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); | ||
263 | if (result < 0) { | ||
264 | dev_err(dev, "error waiting for HC to start: %d\n", result); | ||
265 | goto error_stop; | ||
266 | } | ||
267 | result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); | ||
268 | if (result < 0) { | ||
269 | dev_err(dev, "cannot listen to notifications: %d\n", result); | ||
270 | goto error_stop; | ||
271 | } | ||
272 | return result; | ||
273 | |||
274 | error_stop: | ||
275 | __wa_clear_feature(&hwahc->wa, WA_ENABLE); | ||
276 | return result; | ||
277 | } | ||
278 | |||
279 | static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay) | ||
280 | { | ||
281 | struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); | ||
282 | struct wahc *wa = &hwahc->wa; | ||
283 | u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; | ||
284 | int ret; | ||
285 | |||
286 | ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), | ||
287 | WUSB_REQ_CHAN_STOP, | ||
288 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
289 | delay * 1000, | ||
290 | iface_no, | ||
291 | NULL, 0, 1000 /* FIXME: arbitrary */); | ||
292 | if (ret == 0) | ||
293 | msleep(delay); | ||
294 | |||
295 | wa_nep_disarm(&hwahc->wa); | ||
296 | __wa_stop(&hwahc->wa); | ||
297 | } | ||
298 | |||
328 | /* | 299 | /* |
329 | * Set the UWB MAS allocation for the WUSB cluster | 300 | * Set the UWB MAS allocation for the WUSB cluster |
330 | * | 301 | * |
@@ -581,11 +552,11 @@ static int wa_fill_descr(struct wahc *wa) | |||
581 | itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); | 552 | itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); |
582 | while (itr_size >= sizeof(*hdr)) { | 553 | while (itr_size >= sizeof(*hdr)) { |
583 | hdr = (struct usb_descriptor_header *) itr; | 554 | hdr = (struct usb_descriptor_header *) itr; |
584 | d_printf(3, dev, "Extra device descriptor: " | 555 | dev_dbg(dev, "Extra device descriptor: " |
585 | "type %02x/%u bytes @ %zu (%zu left)\n", | 556 | "type %02x/%u bytes @ %zu (%zu left)\n", |
586 | hdr->bDescriptorType, hdr->bLength, | 557 | hdr->bDescriptorType, hdr->bLength, |
587 | (itr - usb_dev->rawdescriptors[actconfig_idx]), | 558 | (itr - usb_dev->rawdescriptors[actconfig_idx]), |
588 | itr_size); | 559 | itr_size); |
589 | if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER) | 560 | if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER) |
590 | goto found; | 561 | goto found; |
591 | itr += hdr->bLength; | 562 | itr += hdr->bLength; |
@@ -794,7 +765,6 @@ static void hwahc_destroy(struct hwahc *hwahc) | |||
794 | { | 765 | { |
795 | struct wusbhc *wusbhc = &hwahc->wusbhc; | 766 | struct wusbhc *wusbhc = &hwahc->wusbhc; |
796 | 767 | ||
797 | d_fnstart(1, NULL, "(hwahc %p)\n", hwahc); | ||
798 | mutex_lock(&wusbhc->mutex); | 768 | mutex_lock(&wusbhc->mutex); |
799 | __wa_destroy(&hwahc->wa); | 769 | __wa_destroy(&hwahc->wa); |
800 | wusbhc_destroy(&hwahc->wusbhc); | 770 | wusbhc_destroy(&hwahc->wusbhc); |
@@ -804,7 +774,6 @@ static void hwahc_destroy(struct hwahc *hwahc) | |||
804 | usb_put_intf(hwahc->wa.usb_iface); | 774 | usb_put_intf(hwahc->wa.usb_iface); |
805 | usb_put_dev(hwahc->wa.usb_dev); | 775 | usb_put_dev(hwahc->wa.usb_dev); |
806 | mutex_unlock(&wusbhc->mutex); | 776 | mutex_unlock(&wusbhc->mutex); |
807 | d_fnend(1, NULL, "(hwahc %p) = void\n", hwahc); | ||
808 | } | 777 | } |
809 | 778 | ||
810 | static void hwahc_init(struct hwahc *hwahc) | 779 | static void hwahc_init(struct hwahc *hwahc) |
@@ -821,7 +790,6 @@ static int hwahc_probe(struct usb_interface *usb_iface, | |||
821 | struct hwahc *hwahc; | 790 | struct hwahc *hwahc; |
822 | struct device *dev = &usb_iface->dev; | 791 | struct device *dev = &usb_iface->dev; |
823 | 792 | ||
824 | d_fnstart(4, dev, "(%p, %p)\n", usb_iface, id); | ||
825 | result = -ENOMEM; | 793 | result = -ENOMEM; |
826 | usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa"); | 794 | usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa"); |
827 | if (usb_hcd == NULL) { | 795 | if (usb_hcd == NULL) { |
@@ -848,7 +816,6 @@ static int hwahc_probe(struct usb_interface *usb_iface, | |||
848 | dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); | 816 | dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); |
849 | goto error_wusbhc_b_create; | 817 | goto error_wusbhc_b_create; |
850 | } | 818 | } |
851 | d_fnend(4, dev, "(%p, %p) = 0\n", usb_iface, id); | ||
852 | return 0; | 819 | return 0; |
853 | 820 | ||
854 | error_wusbhc_b_create: | 821 | error_wusbhc_b_create: |
@@ -858,7 +825,6 @@ error_add_hcd: | |||
858 | error_hwahc_create: | 825 | error_hwahc_create: |
859 | usb_put_hcd(usb_hcd); | 826 | usb_put_hcd(usb_hcd); |
860 | error_alloc: | 827 | error_alloc: |
861 | d_fnend(4, dev, "(%p, %p) = %d\n", usb_iface, id, result); | ||
862 | return result; | 828 | return result; |
863 | } | 829 | } |
864 | 830 | ||
@@ -872,16 +838,12 @@ static void hwahc_disconnect(struct usb_interface *usb_iface) | |||
872 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 838 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
873 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); | 839 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); |
874 | 840 | ||
875 | d_fnstart(1, NULL, "(hwahc %p [usb_iface %p])\n", hwahc, usb_iface); | ||
876 | wusbhc_b_destroy(&hwahc->wusbhc); | 841 | wusbhc_b_destroy(&hwahc->wusbhc); |
877 | usb_remove_hcd(usb_hcd); | 842 | usb_remove_hcd(usb_hcd); |
878 | hwahc_destroy(hwahc); | 843 | hwahc_destroy(hwahc); |
879 | usb_put_hcd(usb_hcd); | 844 | usb_put_hcd(usb_hcd); |
880 | d_fnend(1, NULL, "(hwahc %p [usb_iface %p]) = void\n", hwahc, | ||
881 | usb_iface); | ||
882 | } | 845 | } |
883 | 846 | ||
884 | /** USB device ID's that we handle */ | ||
885 | static struct usb_device_id hwahc_id_table[] = { | 847 | static struct usb_device_id hwahc_id_table[] = { |
886 | /* FIXME: use class labels for this */ | 848 | /* FIXME: use class labels for this */ |
887 | { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), }, | 849 | { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), }, |
@@ -898,18 +860,7 @@ static struct usb_driver hwahc_driver = { | |||
898 | 860 | ||
899 | static int __init hwahc_driver_init(void) | 861 | static int __init hwahc_driver_init(void) |
900 | { | 862 | { |
901 | int result; | 863 | return usb_register(&hwahc_driver); |
902 | result = usb_register(&hwahc_driver); | ||
903 | if (result < 0) { | ||
904 | printk(KERN_ERR "WA-CDS: Cannot register USB driver: %d\n", | ||
905 | result); | ||
906 | goto error_usb_register; | ||
907 | } | ||
908 | return 0; | ||
909 | |||
910 | error_usb_register: | ||
911 | return result; | ||
912 | |||
913 | } | 864 | } |
914 | module_init(hwahc_driver_init); | 865 | module_init(hwahc_driver_init); |
915 | 866 | ||
diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Kbuild index 26a3871ea0f9..11e5040b8337 100644 --- a/drivers/usb/host/whci/Kbuild +++ b/drivers/usb/host/whci/Kbuild | |||
@@ -2,6 +2,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o | |||
2 | 2 | ||
3 | whci-hcd-y := \ | 3 | whci-hcd-y := \ |
4 | asl.o \ | 4 | asl.o \ |
5 | debug.o \ | ||
5 | hcd.o \ | 6 | hcd.o \ |
6 | hw.o \ | 7 | hw.o \ |
7 | init.o \ | 8 | init.o \ |
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 4d7078e50572..577c0d29849d 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -19,32 +19,11 @@ | |||
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/uwb/umc.h> | 20 | #include <linux/uwb/umc.h> |
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | #define D_LOCAL 0 | ||
23 | #include <linux/uwb/debug.h> | ||
24 | 22 | ||
25 | #include "../../wusbcore/wusbhc.h" | 23 | #include "../../wusbcore/wusbhc.h" |
26 | 24 | ||
27 | #include "whcd.h" | 25 | #include "whcd.h" |
28 | 26 | ||
29 | #if D_LOCAL >= 4 | ||
30 | static void dump_asl(struct whc *whc, const char *tag) | ||
31 | { | ||
32 | struct device *dev = &whc->umc->dev; | ||
33 | struct whc_qset *qset; | ||
34 | |||
35 | d_printf(4, dev, "ASL %s\n", tag); | ||
36 | |||
37 | list_for_each_entry(qset, &whc->async_list, list_node) { | ||
38 | dump_qset(qset, dev); | ||
39 | } | ||
40 | } | ||
41 | #else | ||
42 | static inline void dump_asl(struct whc *whc, const char *tag) | ||
43 | { | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | |||
48 | static void qset_get_next_prev(struct whc *whc, struct whc_qset *qset, | 27 | static void qset_get_next_prev(struct whc *whc, struct whc_qset *qset, |
49 | struct whc_qset **next, struct whc_qset **prev) | 28 | struct whc_qset **next, struct whc_qset **prev) |
50 | { | 29 | { |
@@ -179,11 +158,26 @@ void asl_stop(struct whc *whc) | |||
179 | 1000, "stop ASL"); | 158 | 1000, "stop ASL"); |
180 | } | 159 | } |
181 | 160 | ||
161 | /** | ||
162 | * asl_update - request an ASL update and wait for the hardware to be synced | ||
163 | * @whc: the WHCI HC | ||
164 | * @wusbcmd: WUSBCMD value to start the update. | ||
165 | * | ||
166 | * If the WUSB HC is inactive (i.e., the ASL is stopped) then the | ||
167 | * update must be skipped as the hardware may not respond to update | ||
168 | * requests. | ||
169 | */ | ||
182 | void asl_update(struct whc *whc, uint32_t wusbcmd) | 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) |
183 | { | 171 | { |
184 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 172 | struct wusbhc *wusbhc = &whc->wusbhc; |
185 | wait_event(whc->async_list_wq, | 173 | |
186 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); | 174 | mutex_lock(&wusbhc->mutex); |
175 | if (wusbhc->active) { | ||
176 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | ||
177 | wait_event(whc->async_list_wq, | ||
178 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); | ||
179 | } | ||
180 | mutex_unlock(&wusbhc->mutex); | ||
187 | } | 181 | } |
188 | 182 | ||
189 | /** | 183 | /** |
@@ -202,8 +196,6 @@ void scan_async_work(struct work_struct *work) | |||
202 | 196 | ||
203 | spin_lock_irq(&whc->lock); | 197 | spin_lock_irq(&whc->lock); |
204 | 198 | ||
205 | dump_asl(whc, "before processing"); | ||
206 | |||
207 | /* | 199 | /* |
208 | * Transerve the software list backwards so new qsets can be | 200 | * Transerve the software list backwards so new qsets can be |
209 | * safely inserted into the ASL without making it non-circular. | 201 | * safely inserted into the ASL without making it non-circular. |
@@ -217,8 +209,6 @@ void scan_async_work(struct work_struct *work) | |||
217 | update |= process_qset(whc, qset); | 209 | update |= process_qset(whc, qset); |
218 | } | 210 | } |
219 | 211 | ||
220 | dump_asl(whc, "after processing"); | ||
221 | |||
222 | spin_unlock_irq(&whc->lock); | 212 | spin_unlock_irq(&whc->lock); |
223 | 213 | ||
224 | if (update) { | 214 | if (update) { |
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c new file mode 100644 index 000000000000..cf2d45946c57 --- /dev/null +++ b/drivers/usb/host/whci/debug.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * Wireless Host Controller (WHC) debug. | ||
3 | * | ||
4 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | |||
22 | #include "../../wusbcore/wusbhc.h" | ||
23 | |||
24 | #include "whcd.h" | ||
25 | |||
26 | struct whc_dbg { | ||
27 | struct dentry *di_f; | ||
28 | struct dentry *asl_f; | ||
29 | struct dentry *pzl_f; | ||
30 | }; | ||
31 | |||
32 | void qset_print(struct seq_file *s, struct whc_qset *qset) | ||
33 | { | ||
34 | struct whc_std *std; | ||
35 | struct urb *urb = NULL; | ||
36 | int i; | ||
37 | |||
38 | seq_printf(s, "qset %08x\n", (u32)qset->qset_dma); | ||
39 | seq_printf(s, " -> %08x\n", (u32)qset->qh.link); | ||
40 | seq_printf(s, " info: %08x %08x %08x\n", | ||
41 | qset->qh.info1, qset->qh.info2, qset->qh.info3); | ||
42 | seq_printf(s, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); | ||
43 | seq_printf(s, " TD: sts: %08x opts: %08x\n", | ||
44 | qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); | ||
45 | |||
46 | for (i = 0; i < WHCI_QSET_TD_MAX; i++) { | ||
47 | seq_printf(s, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", | ||
48 | i == qset->td_start ? 'S' : ' ', | ||
49 | i == qset->td_end ? 'E' : ' ', | ||
50 | i, qset->qtd[i].status, qset->qtd[i].options, | ||
51 | (u32)qset->qtd[i].page_list_ptr); | ||
52 | } | ||
53 | seq_printf(s, " ntds: %d\n", qset->ntds); | ||
54 | list_for_each_entry(std, &qset->stds, list_node) { | ||
55 | if (urb != std->urb) { | ||
56 | urb = std->urb; | ||
57 | seq_printf(s, " urb %p transferred: %d bytes\n", urb, | ||
58 | urb->actual_length); | ||
59 | } | ||
60 | if (std->qtd) | ||
61 | seq_printf(s, " sTD[%td]: %zu bytes @ %08x\n", | ||
62 | std->qtd - &qset->qtd[0], | ||
63 | std->len, std->num_pointers ? | ||
64 | (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); | ||
65 | else | ||
66 | seq_printf(s, " sTD[-]: %zd bytes @ %08x\n", | ||
67 | std->len, std->num_pointers ? | ||
68 | (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static int di_print(struct seq_file *s, void *p) | ||
73 | { | ||
74 | struct whc *whc = s->private; | ||
75 | char buf[72]; | ||
76 | int d; | ||
77 | |||
78 | for (d = 0; d < whc->n_devices; d++) { | ||
79 | struct di_buf_entry *di = &whc->di_buf[d]; | ||
80 | |||
81 | bitmap_scnprintf(buf, sizeof(buf), | ||
82 | (unsigned long *)di->availability_info, UWB_NUM_MAS); | ||
83 | |||
84 | seq_printf(s, "DI[%d]\n", d); | ||
85 | seq_printf(s, " availability: %s\n", buf); | ||
86 | seq_printf(s, " %c%c key idx: %d dev addr: %d\n", | ||
87 | (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ', | ||
88 | (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ', | ||
89 | (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8, | ||
90 | (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK)); | ||
91 | } | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int asl_print(struct seq_file *s, void *p) | ||
96 | { | ||
97 | struct whc *whc = s->private; | ||
98 | struct whc_qset *qset; | ||
99 | |||
100 | list_for_each_entry(qset, &whc->async_list, list_node) { | ||
101 | qset_print(s, qset); | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int pzl_print(struct seq_file *s, void *p) | ||
108 | { | ||
109 | struct whc *whc = s->private; | ||
110 | struct whc_qset *qset; | ||
111 | int period; | ||
112 | |||
113 | for (period = 0; period < 5; period++) { | ||
114 | seq_printf(s, "Period %d\n", period); | ||
115 | list_for_each_entry(qset, &whc->periodic_list[period], list_node) { | ||
116 | qset_print(s, qset); | ||
117 | } | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int di_open(struct inode *inode, struct file *file) | ||
123 | { | ||
124 | return single_open(file, di_print, inode->i_private); | ||
125 | } | ||
126 | |||
127 | static int asl_open(struct inode *inode, struct file *file) | ||
128 | { | ||
129 | return single_open(file, asl_print, inode->i_private); | ||
130 | } | ||
131 | |||
132 | static int pzl_open(struct inode *inode, struct file *file) | ||
133 | { | ||
134 | return single_open(file, pzl_print, inode->i_private); | ||
135 | } | ||
136 | |||
137 | static struct file_operations di_fops = { | ||
138 | .open = di_open, | ||
139 | .read = seq_read, | ||
140 | .llseek = seq_lseek, | ||
141 | .release = single_release, | ||
142 | .owner = THIS_MODULE, | ||
143 | }; | ||
144 | |||
145 | static struct file_operations asl_fops = { | ||
146 | .open = asl_open, | ||
147 | .read = seq_read, | ||
148 | .llseek = seq_lseek, | ||
149 | .release = single_release, | ||
150 | .owner = THIS_MODULE, | ||
151 | }; | ||
152 | |||
153 | static struct file_operations pzl_fops = { | ||
154 | .open = pzl_open, | ||
155 | .read = seq_read, | ||
156 | .llseek = seq_lseek, | ||
157 | .release = single_release, | ||
158 | .owner = THIS_MODULE, | ||
159 | }; | ||
160 | |||
161 | void whc_dbg_init(struct whc *whc) | ||
162 | { | ||
163 | if (whc->wusbhc.pal.debugfs_dir == NULL) | ||
164 | return; | ||
165 | |||
166 | whc->dbg = kzalloc(sizeof(struct whc_dbg), GFP_KERNEL); | ||
167 | if (whc->dbg == NULL) | ||
168 | return; | ||
169 | |||
170 | whc->dbg->di_f = debugfs_create_file("di", 0444, | ||
171 | whc->wusbhc.pal.debugfs_dir, whc, | ||
172 | &di_fops); | ||
173 | whc->dbg->asl_f = debugfs_create_file("asl", 0444, | ||
174 | whc->wusbhc.pal.debugfs_dir, whc, | ||
175 | &asl_fops); | ||
176 | whc->dbg->pzl_f = debugfs_create_file("pzl", 0444, | ||
177 | whc->wusbhc.pal.debugfs_dir, whc, | ||
178 | &pzl_fops); | ||
179 | } | ||
180 | |||
181 | void whc_dbg_clean_up(struct whc *whc) | ||
182 | { | ||
183 | if (whc->dbg) { | ||
184 | debugfs_remove(whc->dbg->pzl_f); | ||
185 | debugfs_remove(whc->dbg->asl_f); | ||
186 | debugfs_remove(whc->dbg->di_f); | ||
187 | kfree(whc->dbg); | ||
188 | } | ||
189 | } | ||
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index ef3ad4dca945..1569afd6245b 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/uwb/umc.h> | 20 | #include <linux/uwb/umc.h> |
@@ -92,8 +91,6 @@ static void whc_stop(struct usb_hcd *usb_hcd) | |||
92 | 91 | ||
93 | mutex_lock(&wusbhc->mutex); | 92 | mutex_lock(&wusbhc->mutex); |
94 | 93 | ||
95 | wusbhc_stop(wusbhc); | ||
96 | |||
97 | /* stop HC */ | 94 | /* stop HC */ |
98 | le_writel(0, whc->base + WUSBINTR); | 95 | le_writel(0, whc->base + WUSBINTR); |
99 | whc_write_wusbcmd(whc, WUSBCMD_RUN, 0); | 96 | whc_write_wusbcmd(whc, WUSBCMD_RUN, 0); |
@@ -276,6 +273,8 @@ static int whc_probe(struct umc_dev *umc) | |||
276 | goto error_wusbhc_b_create; | 273 | goto error_wusbhc_b_create; |
277 | } | 274 | } |
278 | 275 | ||
276 | whc_dbg_init(whc); | ||
277 | |||
279 | return 0; | 278 | return 0; |
280 | 279 | ||
281 | error_wusbhc_b_create: | 280 | error_wusbhc_b_create: |
@@ -299,6 +298,7 @@ static void whc_remove(struct umc_dev *umc) | |||
299 | struct whc *whc = wusbhc_to_whc(wusbhc); | 298 | struct whc *whc = wusbhc_to_whc(wusbhc); |
300 | 299 | ||
301 | if (usb_hcd) { | 300 | if (usb_hcd) { |
301 | whc_dbg_clean_up(whc); | ||
302 | wusbhc_b_destroy(wusbhc); | 302 | wusbhc_b_destroy(wusbhc); |
303 | usb_remove_hcd(usb_hcd); | 303 | usb_remove_hcd(usb_hcd); |
304 | wusbhc_destroy(wusbhc); | 304 | wusbhc_destroy(wusbhc); |
diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index ac86e59c1225..d498e7203217 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c | |||
@@ -50,6 +50,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len) | |||
50 | unsigned long flags; | 50 | unsigned long flags; |
51 | dma_addr_t dma_addr; | 51 | dma_addr_t dma_addr; |
52 | int t; | 52 | int t; |
53 | int ret = 0; | ||
53 | 54 | ||
54 | mutex_lock(&whc->mutex); | 55 | mutex_lock(&whc->mutex); |
55 | 56 | ||
@@ -61,7 +62,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len) | |||
61 | dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n", | 62 | dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n", |
62 | le_readl(whc->base + WUSBGENCMDSTS), | 63 | le_readl(whc->base + WUSBGENCMDSTS), |
63 | le_readl(whc->base + WUSBGENCMDPARAMS)); | 64 | le_readl(whc->base + WUSBGENCMDPARAMS)); |
64 | return -ETIMEDOUT; | 65 | ret = -ETIMEDOUT; |
66 | goto out; | ||
65 | } | 67 | } |
66 | 68 | ||
67 | if (addr) { | 69 | if (addr) { |
@@ -80,8 +82,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len) | |||
80 | whc->base + WUSBGENCMDSTS); | 82 | whc->base + WUSBGENCMDSTS); |
81 | 83 | ||
82 | spin_unlock_irqrestore(&whc->lock, flags); | 84 | spin_unlock_irqrestore(&whc->lock, flags); |
83 | 85 | out: | |
84 | mutex_unlock(&whc->mutex); | 86 | mutex_unlock(&whc->mutex); |
85 | 87 | ||
86 | return 0; | 88 | return ret; |
87 | } | 89 | } |
diff --git a/drivers/usb/host/whci/int.c b/drivers/usb/host/whci/int.c index fce01174aa9b..6aae70028101 100644 --- a/drivers/usb/host/whci/int.c +++ b/drivers/usb/host/whci/int.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/uwb/umc.h> | 20 | #include <linux/uwb/umc.h> |
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 8d62df0c330b..2ae5abf69a6a 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
@@ -19,35 +19,11 @@ | |||
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/uwb/umc.h> | 20 | #include <linux/uwb/umc.h> |
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | #define D_LOCAL 0 | ||
23 | #include <linux/uwb/debug.h> | ||
24 | 22 | ||
25 | #include "../../wusbcore/wusbhc.h" | 23 | #include "../../wusbcore/wusbhc.h" |
26 | 24 | ||
27 | #include "whcd.h" | 25 | #include "whcd.h" |
28 | 26 | ||
29 | #if D_LOCAL >= 4 | ||
30 | static void dump_pzl(struct whc *whc, const char *tag) | ||
31 | { | ||
32 | struct device *dev = &whc->umc->dev; | ||
33 | struct whc_qset *qset; | ||
34 | int period = 0; | ||
35 | |||
36 | d_printf(4, dev, "PZL %s\n", tag); | ||
37 | |||
38 | for (period = 0; period < 5; period++) { | ||
39 | d_printf(4, dev, "Period %d\n", period); | ||
40 | list_for_each_entry(qset, &whc->periodic_list[period], list_node) { | ||
41 | dump_qset(qset, dev); | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | #else | ||
46 | static inline void dump_pzl(struct whc *whc, const char *tag) | ||
47 | { | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | static void update_pzl_pointers(struct whc *whc, int period, u64 addr) | 27 | static void update_pzl_pointers(struct whc *whc, int period, u64 addr) |
52 | { | 28 | { |
53 | switch (period) { | 29 | switch (period) { |
@@ -195,11 +171,26 @@ void pzl_stop(struct whc *whc) | |||
195 | 1000, "stop PZL"); | 171 | 1000, "stop PZL"); |
196 | } | 172 | } |
197 | 173 | ||
174 | /** | ||
175 | * pzl_update - request a PZL update and wait for the hardware to be synced | ||
176 | * @whc: the WHCI HC | ||
177 | * @wusbcmd: WUSBCMD value to start the update. | ||
178 | * | ||
179 | * If the WUSB HC is inactive (i.e., the PZL is stopped) then the | ||
180 | * update must be skipped as the hardware may not respond to update | ||
181 | * requests. | ||
182 | */ | ||
198 | void pzl_update(struct whc *whc, uint32_t wusbcmd) | 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) |
199 | { | 184 | { |
200 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 185 | struct wusbhc *wusbhc = &whc->wusbhc; |
201 | wait_event(whc->periodic_list_wq, | 186 | |
202 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); | 187 | mutex_lock(&wusbhc->mutex); |
188 | if (wusbhc->active) { | ||
189 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | ||
190 | wait_event(whc->periodic_list_wq, | ||
191 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); | ||
192 | } | ||
193 | mutex_unlock(&wusbhc->mutex); | ||
203 | } | 194 | } |
204 | 195 | ||
205 | static void update_pzl_hw_view(struct whc *whc) | 196 | static void update_pzl_hw_view(struct whc *whc) |
@@ -235,8 +226,6 @@ void scan_periodic_work(struct work_struct *work) | |||
235 | 226 | ||
236 | spin_lock_irq(&whc->lock); | 227 | spin_lock_irq(&whc->lock); |
237 | 228 | ||
238 | dump_pzl(whc, "before processing"); | ||
239 | |||
240 | for (period = 4; period >= 0; period--) { | 229 | for (period = 4; period >= 0; period--) { |
241 | list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) { | 230 | list_for_each_entry_safe(qset, t, &whc->periodic_list[period], list_node) { |
242 | if (!qset->in_hw_list) | 231 | if (!qset->in_hw_list) |
@@ -248,8 +237,6 @@ void scan_periodic_work(struct work_struct *work) | |||
248 | if (update & (WHC_UPDATE_ADDED | WHC_UPDATE_REMOVED)) | 237 | if (update & (WHC_UPDATE_ADDED | WHC_UPDATE_REMOVED)) |
249 | update_pzl_hw_view(whc); | 238 | update_pzl_hw_view(whc); |
250 | 239 | ||
251 | dump_pzl(whc, "after processing"); | ||
252 | |||
253 | spin_unlock_irq(&whc->lock); | 240 | spin_unlock_irq(&whc->lock); |
254 | 241 | ||
255 | if (update) { | 242 | if (update) { |
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 0420037d2e18..7be74314ee12 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c | |||
@@ -24,46 +24,6 @@ | |||
24 | 24 | ||
25 | #include "whcd.h" | 25 | #include "whcd.h" |
26 | 26 | ||
27 | void dump_qset(struct whc_qset *qset, struct device *dev) | ||
28 | { | ||
29 | struct whc_std *std; | ||
30 | struct urb *urb = NULL; | ||
31 | int i; | ||
32 | |||
33 | dev_dbg(dev, "qset %08x\n", (u32)qset->qset_dma); | ||
34 | dev_dbg(dev, " -> %08x\n", (u32)qset->qh.link); | ||
35 | dev_dbg(dev, " info: %08x %08x %08x\n", | ||
36 | qset->qh.info1, qset->qh.info2, qset->qh.info3); | ||
37 | dev_dbg(dev, " sts: %04x errs: %d\n", qset->qh.status, qset->qh.err_count); | ||
38 | dev_dbg(dev, " TD: sts: %08x opts: %08x\n", | ||
39 | qset->qh.overlay.qtd.status, qset->qh.overlay.qtd.options); | ||
40 | |||
41 | for (i = 0; i < WHCI_QSET_TD_MAX; i++) { | ||
42 | dev_dbg(dev, " %c%c TD[%d]: sts: %08x opts: %08x ptr: %08x\n", | ||
43 | i == qset->td_start ? 'S' : ' ', | ||
44 | i == qset->td_end ? 'E' : ' ', | ||
45 | i, qset->qtd[i].status, qset->qtd[i].options, | ||
46 | (u32)qset->qtd[i].page_list_ptr); | ||
47 | } | ||
48 | dev_dbg(dev, " ntds: %d\n", qset->ntds); | ||
49 | list_for_each_entry(std, &qset->stds, list_node) { | ||
50 | if (urb != std->urb) { | ||
51 | urb = std->urb; | ||
52 | dev_dbg(dev, " urb %p transferred: %d bytes\n", urb, | ||
53 | urb->actual_length); | ||
54 | } | ||
55 | if (std->qtd) | ||
56 | dev_dbg(dev, " sTD[%td]: %zu bytes @ %08x\n", | ||
57 | std->qtd - &qset->qtd[0], | ||
58 | std->len, std->num_pointers ? | ||
59 | (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); | ||
60 | else | ||
61 | dev_dbg(dev, " sTD[-]: %zd bytes @ %08x\n", | ||
62 | std->len, std->num_pointers ? | ||
63 | (u32)(std->pl_virt[0].buf_ptr) : (u32)std->dma_addr); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) | 27 | struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags) |
68 | { | 28 | { |
69 | struct whc_qset *qset; | 29 | struct whc_qset *qset; |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 1d2a53bd39fd..0f3540f04f53 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define __WHCD_H | 21 | #define __WHCD_H |
22 | 22 | ||
23 | #include <linux/uwb/whci.h> | 23 | #include <linux/uwb/whci.h> |
24 | #include <linux/uwb/umc.h> | ||
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
25 | 26 | ||
26 | #include "whci-hc.h" | 27 | #include "whci-hc.h" |
@@ -28,6 +29,7 @@ | |||
28 | /* Generic command timeout. */ | 29 | /* Generic command timeout. */ |
29 | #define WHC_GENCMD_TIMEOUT_MS 100 | 30 | #define WHC_GENCMD_TIMEOUT_MS 100 |
30 | 31 | ||
32 | struct whc_dbg; | ||
31 | 33 | ||
32 | struct whc { | 34 | struct whc { |
33 | struct wusbhc wusbhc; | 35 | struct wusbhc wusbhc; |
@@ -69,6 +71,8 @@ struct whc { | |||
69 | struct list_head periodic_removed_list; | 71 | struct list_head periodic_removed_list; |
70 | wait_queue_head_t periodic_list_wq; | 72 | wait_queue_head_t periodic_list_wq; |
71 | struct work_struct periodic_work; | 73 | struct work_struct periodic_work; |
74 | |||
75 | struct whc_dbg *dbg; | ||
72 | }; | 76 | }; |
73 | 77 | ||
74 | #define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc)) | 78 | #define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc)) |
@@ -136,7 +140,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | |||
136 | 140 | ||
137 | /* wusb.c */ | 141 | /* wusb.c */ |
138 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 142 | int whc_wusbhc_start(struct wusbhc *wusbhc); |
139 | void whc_wusbhc_stop(struct wusbhc *wusbhc); | 143 | void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay); |
140 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 144 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
141 | u8 handle, struct wuie_hdr *wuie); | 145 | u8 handle, struct wuie_hdr *wuie); |
142 | int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); | 146 | int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle); |
@@ -190,8 +194,11 @@ void process_inactive_qtd(struct whc *whc, struct whc_qset *qset, | |||
190 | struct whc_qtd *qtd); | 194 | struct whc_qtd *qtd); |
191 | enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset); | 195 | enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset); |
192 | void qset_remove_complete(struct whc *whc, struct whc_qset *qset); | 196 | void qset_remove_complete(struct whc *whc, struct whc_qset *qset); |
193 | void dump_qset(struct whc_qset *qset, struct device *dev); | ||
194 | void pzl_update(struct whc *whc, uint32_t wusbcmd); | 197 | void pzl_update(struct whc *whc, uint32_t wusbcmd); |
195 | void asl_update(struct whc *whc, uint32_t wusbcmd); | 198 | void asl_update(struct whc *whc, uint32_t wusbcmd); |
196 | 199 | ||
200 | /* debug.c */ | ||
201 | void whc_dbg_init(struct whc *whc); | ||
202 | void whc_dbg_clean_up(struct whc *whc); | ||
203 | |||
197 | #endif /* #ifndef __WHCD_H */ | 204 | #endif /* #ifndef __WHCD_H */ |
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h index bff1eb7a35cf..51df7e313b38 100644 --- a/drivers/usb/host/whci/whci-hc.h +++ b/drivers/usb/host/whci/whci-hc.h | |||
@@ -410,6 +410,8 @@ struct dn_buf_entry { | |||
410 | # define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) | 410 | # define WUSBDNTSCTRL_SLOTS(s) ((s) << 0) |
411 | 411 | ||
412 | #define WUSBTIME 0x68 | 412 | #define WUSBTIME 0x68 |
413 | # define WUSBTIME_CHANNEL_TIME_MASK 0x00ffffff | ||
414 | |||
413 | #define WUSBBPST 0x6c | 415 | #define WUSBBPST 0x6c |
414 | #define WUSBDIBUPDATED 0x70 | 416 | #define WUSBDIBUPDATED 0x70 |
415 | 417 | ||
diff --git a/drivers/usb/host/whci/wusb.c b/drivers/usb/host/whci/wusb.c index 66e4ddcd961d..f24efdebad17 100644 --- a/drivers/usb/host/whci/wusb.c +++ b/drivers/usb/host/whci/wusb.c | |||
@@ -15,47 +15,19 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/init.h> | 19 | #include <linux/init.h> |
21 | #include <linux/uwb/umc.h> | 20 | #include <linux/uwb/umc.h> |
22 | #define D_LOCAL 1 | ||
23 | #include <linux/uwb/debug.h> | ||
24 | 21 | ||
25 | #include "../../wusbcore/wusbhc.h" | 22 | #include "../../wusbcore/wusbhc.h" |
26 | 23 | ||
27 | #include "whcd.h" | 24 | #include "whcd.h" |
28 | 25 | ||
29 | #if D_LOCAL >= 1 | ||
30 | static void dump_di(struct whc *whc, int idx) | ||
31 | { | ||
32 | struct di_buf_entry *di = &whc->di_buf[idx]; | ||
33 | struct device *dev = &whc->umc->dev; | ||
34 | char buf[128]; | ||
35 | |||
36 | bitmap_scnprintf(buf, sizeof(buf), (unsigned long *)di->availability_info, UWB_NUM_MAS); | ||
37 | |||
38 | d_printf(1, dev, "DI[%d]\n", idx); | ||
39 | d_printf(1, dev, " availability: %s\n", buf); | ||
40 | d_printf(1, dev, " %c%c key idx: %d dev addr: %d\n", | ||
41 | (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ', | ||
42 | (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ', | ||
43 | (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8, | ||
44 | (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK)); | ||
45 | } | ||
46 | #else | ||
47 | static inline void dump_di(struct whc *whc, int idx) | ||
48 | { | ||
49 | } | ||
50 | #endif | ||
51 | |||
52 | static int whc_update_di(struct whc *whc, int idx) | 26 | static int whc_update_di(struct whc *whc, int idx) |
53 | { | 27 | { |
54 | int offset = idx / 32; | 28 | int offset = idx / 32; |
55 | u32 bit = 1 << (idx % 32); | 29 | u32 bit = 1 << (idx % 32); |
56 | 30 | ||
57 | dump_di(whc, idx); | ||
58 | |||
59 | le_writel(bit, whc->base + WUSBDIBUPDATED + offset); | 31 | le_writel(bit, whc->base + WUSBDIBUPDATED + offset); |
60 | 32 | ||
61 | return whci_wait_for(&whc->umc->dev, | 33 | return whci_wait_for(&whc->umc->dev, |
@@ -64,8 +36,9 @@ static int whc_update_di(struct whc *whc, int idx) | |||
64 | } | 36 | } |
65 | 37 | ||
66 | /* | 38 | /* |
67 | * WHCI starts and stops MMCs based on there being a valid GTK so | 39 | * WHCI starts MMCs based on there being a valid GTK so these need |
68 | * these need only start/stop the asynchronous and periodic schedules. | 40 | * only start/stop the asynchronous and periodic schedules and send a |
41 | * channel stop command. | ||
69 | */ | 42 | */ |
70 | 43 | ||
71 | int whc_wusbhc_start(struct wusbhc *wusbhc) | 44 | int whc_wusbhc_start(struct wusbhc *wusbhc) |
@@ -78,12 +51,20 @@ int whc_wusbhc_start(struct wusbhc *wusbhc) | |||
78 | return 0; | 51 | return 0; |
79 | } | 52 | } |
80 | 53 | ||
81 | void whc_wusbhc_stop(struct wusbhc *wusbhc) | 54 | void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay) |
82 | { | 55 | { |
83 | struct whc *whc = wusbhc_to_whc(wusbhc); | 56 | struct whc *whc = wusbhc_to_whc(wusbhc); |
57 | u32 stop_time, now_time; | ||
58 | int ret; | ||
84 | 59 | ||
85 | pzl_stop(whc); | 60 | pzl_stop(whc); |
86 | asl_stop(whc); | 61 | asl_stop(whc); |
62 | |||
63 | now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK; | ||
64 | stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff; | ||
65 | ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0); | ||
66 | if (ret == 0) | ||
67 | msleep(delay); | ||
87 | } | 68 | } |
88 | 69 | ||
89 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 70 | int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5b95009d2fbb..19e24045b137 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -241,12 +241,25 @@ static void usb_console_write(struct console *co, | |||
241 | } | 241 | } |
242 | } | 242 | } |
243 | 243 | ||
244 | static struct tty_driver *usb_console_device(struct console *co, int *index) | ||
245 | { | ||
246 | struct tty_driver **p = (struct tty_driver **)co->data; | ||
247 | |||
248 | if (!*p) | ||
249 | return NULL; | ||
250 | |||
251 | *index = co->index; | ||
252 | return *p; | ||
253 | } | ||
254 | |||
244 | static struct console usbcons = { | 255 | static struct console usbcons = { |
245 | .name = "ttyUSB", | 256 | .name = "ttyUSB", |
246 | .write = usb_console_write, | 257 | .write = usb_console_write, |
258 | .device = usb_console_device, | ||
247 | .setup = usb_console_setup, | 259 | .setup = usb_console_setup, |
248 | .flags = CON_PRINTBUFFER, | 260 | .flags = CON_PRINTBUFFER, |
249 | .index = -1, | 261 | .index = -1, |
262 | .data = &usb_serial_tty_driver, | ||
250 | }; | 263 | }; |
251 | 264 | ||
252 | void usb_serial_console_disconnect(struct usb_serial *serial) | 265 | void usb_serial_console_disconnect(struct usb_serial *serial) |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fb6f2933b01b..ef6cfa5a447f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1054,6 +1054,8 @@ static int set_serial_info(struct tty_struct *tty, | |||
1054 | 1054 | ||
1055 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | 1055 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) |
1056 | return -EFAULT; | 1056 | return -EFAULT; |
1057 | |||
1058 | lock_kernel(); | ||
1057 | old_priv = *priv; | 1059 | old_priv = *priv; |
1058 | 1060 | ||
1059 | /* Do error checking and permission checking */ | 1061 | /* Do error checking and permission checking */ |
@@ -1069,8 +1071,10 @@ static int set_serial_info(struct tty_struct *tty, | |||
1069 | } | 1071 | } |
1070 | 1072 | ||
1071 | if ((new_serial.baud_base != priv->baud_base) && | 1073 | if ((new_serial.baud_base != priv->baud_base) && |
1072 | (new_serial.baud_base < 9600)) | 1074 | (new_serial.baud_base < 9600)) { |
1075 | unlock_kernel(); | ||
1073 | return -EINVAL; | 1076 | return -EINVAL; |
1077 | } | ||
1074 | 1078 | ||
1075 | /* Make the changes - these are privileged changes! */ | 1079 | /* Make the changes - these are privileged changes! */ |
1076 | 1080 | ||
@@ -1098,8 +1102,11 @@ check_and_exit: | |||
1098 | (priv->flags & ASYNC_SPD_MASK)) || | 1102 | (priv->flags & ASYNC_SPD_MASK)) || |
1099 | (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && | 1103 | (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && |
1100 | (old_priv.custom_divisor != priv->custom_divisor))) { | 1104 | (old_priv.custom_divisor != priv->custom_divisor))) { |
1105 | unlock_kernel(); | ||
1101 | change_speed(tty, port); | 1106 | change_speed(tty, port); |
1102 | } | 1107 | } |
1108 | else | ||
1109 | unlock_kernel(); | ||
1103 | return 0; | 1110 | return 0; |
1104 | 1111 | ||
1105 | } /* set_serial_info */ | 1112 | } /* set_serial_info */ |
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index dc36a052766f..fcd9082f3e7f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -878,6 +878,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | |||
878 | 878 | ||
879 | dbg("%sstate=%d", __func__, break_state); | 879 | dbg("%sstate=%d", __func__, break_state); |
880 | 880 | ||
881 | /* LOCKING */ | ||
881 | if (break_state) | 882 | if (break_state) |
882 | lcr |= MCT_U232_SET_BREAK; | 883 | lcr |= MCT_U232_SET_BREAK; |
883 | 884 | ||
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 07710cf31d0d..82930a7d5093 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -721,10 +721,10 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | |||
721 | 721 | ||
722 | spin_lock_irqsave(&priv->lock, flags); | 722 | spin_lock_irqsave(&priv->lock, flags); |
723 | lcr = priv->last_lcr; | 723 | lcr = priv->last_lcr; |
724 | spin_unlock_irqrestore(&priv->lock, flags); | ||
725 | 724 | ||
726 | if (break_state) | 725 | if (break_state) |
727 | lcr |= MCT_U232_SET_BREAK; | 726 | lcr |= MCT_U232_SET_BREAK; |
727 | spin_unlock_irqrestore(&priv->lock, flags); | ||
728 | 728 | ||
729 | mct_u232_set_line_ctrl(serial, lcr); | 729 | mct_u232_set_line_ctrl(serial, lcr); |
730 | } /* mct_u232_break_ctl */ | 730 | } /* mct_u232_break_ctl */ |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index fda4a6421c44..96a8c7713212 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -1343,6 +1343,7 @@ static void mos7840_break(struct tty_struct *tty, int break_state) | |||
1343 | else | 1343 | else |
1344 | data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; | 1344 | data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; |
1345 | 1345 | ||
1346 | /* FIXME: no locking on shadowLCR anywhere in driver */ | ||
1346 | mos7840_port->shadowLCR = data; | 1347 | mos7840_port->shadowLCR = data; |
1347 | dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", | 1348 | dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", |
1348 | mos7840_port->shadowLCR); | 1349 | mos7840_port->shadowLCR); |
@@ -2214,10 +2215,12 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port, | |||
2214 | break; | 2215 | break; |
2215 | } | 2216 | } |
2216 | 2217 | ||
2218 | lock_kernel(); | ||
2217 | mos7840_port->shadowMCR = mcr; | 2219 | mos7840_port->shadowMCR = mcr; |
2218 | 2220 | ||
2219 | Data = mos7840_port->shadowMCR; | 2221 | Data = mos7840_port->shadowMCR; |
2220 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 2222 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
2223 | unlock_kernel(); | ||
2221 | if (status < 0) { | 2224 | if (status < 0) { |
2222 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); | 2225 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); |
2223 | return -1; | 2226 | return -1; |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0f2b67244af6..d9bf9a5c20ec 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -442,7 +442,7 @@ static void sierra_indat_callback(struct urb *urb) | |||
442 | " endpoint %02x.", __func__, status, endpoint); | 442 | " endpoint %02x.", __func__, status, endpoint); |
443 | } else { | 443 | } else { |
444 | if (urb->actual_length) { | 444 | if (urb->actual_length) { |
445 | tty = tty_port_tty_get(&port->port); | 445 | tty = tty_port_tty_get(&port->port); |
446 | tty_buffer_request_room(tty, urb->actual_length); | 446 | tty_buffer_request_room(tty, urb->actual_length); |
447 | tty_insert_flip_string(tty, data, urb->actual_length); | 447 | tty_insert_flip_string(tty, data, urb->actual_length); |
448 | tty_flip_buffer_push(tty); | 448 | tty_flip_buffer_push(tty); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 794b5ffe4397..080ade223d53 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -269,15 +269,19 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
269 | return; | 269 | return; |
270 | } | 270 | } |
271 | 271 | ||
272 | --port->port.count; | 272 | if (port->port.count == 1) |
273 | if (port->port.count == 0) | ||
274 | /* only call the device specific close if this | 273 | /* only call the device specific close if this |
275 | * port is being closed by the last owner */ | 274 | * port is being closed by the last owner. Ensure we do |
275 | * this before we drop the port count. The call is protected | ||
276 | * by the port mutex | ||
277 | */ | ||
276 | port->serial->type->close(tty, port, filp); | 278 | port->serial->type->close(tty, port, filp); |
277 | 279 | ||
278 | if (port->port.count == (port->console? 1 : 0)) { | 280 | if (port->port.count == (port->console ? 2 : 1)) { |
279 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 281 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
280 | if (tty) { | 282 | if (tty) { |
283 | /* We must do this before we drop the port count to | ||
284 | zero. */ | ||
281 | if (tty->driver_data) | 285 | if (tty->driver_data) |
282 | tty->driver_data = NULL; | 286 | tty->driver_data = NULL; |
283 | tty_port_tty_set(&port->port, NULL); | 287 | tty_port_tty_set(&port->port, NULL); |
@@ -285,13 +289,14 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
285 | } | 289 | } |
286 | } | 290 | } |
287 | 291 | ||
288 | if (port->port.count == 0) { | 292 | if (port->port.count == 1) { |
289 | mutex_lock(&port->serial->disc_mutex); | 293 | mutex_lock(&port->serial->disc_mutex); |
290 | if (!port->serial->disconnected) | 294 | if (!port->serial->disconnected) |
291 | usb_autopm_put_interface(port->serial->interface); | 295 | usb_autopm_put_interface(port->serial->interface); |
292 | mutex_unlock(&port->serial->disc_mutex); | 296 | mutex_unlock(&port->serial->disc_mutex); |
293 | module_put(port->serial->type->driver.owner); | 297 | module_put(port->serial->type->driver.owner); |
294 | } | 298 | } |
299 | --port->port.count; | ||
295 | 300 | ||
296 | mutex_unlock(&port->mutex); | 301 | mutex_unlock(&port->mutex); |
297 | usb_serial_put(port->serial); | 302 | usb_serial_put(port->serial); |
@@ -334,6 +339,10 @@ static int serial_chars_in_buffer(struct tty_struct *tty) | |||
334 | dbg("%s = port %d", __func__, port->number); | 339 | dbg("%s = port %d", __func__, port->number); |
335 | 340 | ||
336 | WARN_ON(!port->port.count); | 341 | WARN_ON(!port->port.count); |
342 | /* if the device was unplugged then any remaining characters | ||
343 | fell out of the connector ;) */ | ||
344 | if (port->serial->disconnected) | ||
345 | return 0; | ||
337 | /* pass on to the driver specific version of this function */ | 346 | /* pass on to the driver specific version of this function */ |
338 | return port->serial->type->chars_in_buffer(tty); | 347 | return port->serial->type->chars_in_buffer(tty); |
339 | } | 348 | } |
@@ -373,9 +382,7 @@ static int serial_ioctl(struct tty_struct *tty, struct file *file, | |||
373 | /* pass on to the driver specific version of this function | 382 | /* pass on to the driver specific version of this function |
374 | if it is available */ | 383 | if it is available */ |
375 | if (port->serial->type->ioctl) { | 384 | if (port->serial->type->ioctl) { |
376 | lock_kernel(); | ||
377 | retval = port->serial->type->ioctl(tty, file, cmd, arg); | 385 | retval = port->serial->type->ioctl(tty, file, cmd, arg); |
378 | unlock_kernel(); | ||
379 | } else | 386 | } else |
380 | retval = -ENOIOCTLCMD; | 387 | retval = -ENOIOCTLCMD; |
381 | return retval; | 388 | return retval; |
@@ -404,11 +411,8 @@ static int serial_break(struct tty_struct *tty, int break_state) | |||
404 | WARN_ON(!port->port.count); | 411 | WARN_ON(!port->port.count); |
405 | /* pass on to the driver specific version of this function | 412 | /* pass on to the driver specific version of this function |
406 | if it is available */ | 413 | if it is available */ |
407 | if (port->serial->type->break_ctl) { | 414 | if (port->serial->type->break_ctl) |
408 | lock_kernel(); | ||
409 | port->serial->type->break_ctl(tty, break_state); | 415 | port->serial->type->break_ctl(tty, break_state); |
410 | unlock_kernel(); | ||
411 | } | ||
412 | return 0; | 416 | return 0; |
413 | } | 417 | } |
414 | 418 | ||
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index ab4788d1785a..1335cbe1191d 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c | |||
@@ -88,7 +88,6 @@ | |||
88 | */ | 88 | */ |
89 | #include <linux/module.h> | 89 | #include <linux/module.h> |
90 | #include <linux/ctype.h> | 90 | #include <linux/ctype.h> |
91 | #include <linux/version.h> | ||
92 | #include <linux/usb.h> | 91 | #include <linux/usb.h> |
93 | #include <linux/interrupt.h> | 92 | #include <linux/interrupt.h> |
94 | #include <linux/delay.h> | 93 | #include <linux/delay.h> |
diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index c36c4389baae..9ec7fd5da489 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c | |||
@@ -51,9 +51,17 @@ | |||
51 | #include <linux/uwb.h> | 51 | #include <linux/uwb.h> |
52 | #include <linux/usb/wusb.h> | 52 | #include <linux/usb/wusb.h> |
53 | #include <linux/scatterlist.h> | 53 | #include <linux/scatterlist.h> |
54 | #define D_LOCAL 0 | ||
55 | #include <linux/uwb/debug.h> | ||
56 | 54 | ||
55 | static int debug_crypto_verify = 0; | ||
56 | |||
57 | module_param(debug_crypto_verify, int, 0); | ||
58 | MODULE_PARM_DESC(debug_crypto_verify, "verify the key generation algorithms"); | ||
59 | |||
60 | static void wusb_key_dump(const void *buf, size_t len) | ||
61 | { | ||
62 | print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_OFFSET, 16, 1, | ||
63 | buf, len, 0); | ||
64 | } | ||
57 | 65 | ||
58 | /* | 66 | /* |
59 | * Block of data, as understood by AES-CCM | 67 | * Block of data, as understood by AES-CCM |
@@ -203,9 +211,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, | |||
203 | const u8 bzero[16] = { 0 }; | 211 | const u8 bzero[16] = { 0 }; |
204 | size_t zero_padding; | 212 | size_t zero_padding; |
205 | 213 | ||
206 | d_fnstart(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, " | ||
207 | "n %p, a %p, b %p, blen %zu)\n", | ||
208 | tfm_cbc, tfm_aes, mic, n, a, b, blen); | ||
209 | /* | 214 | /* |
210 | * These checks should be compile time optimized out | 215 | * These checks should be compile time optimized out |
211 | * ensure @a fills b1's mac_header and following fields | 216 | * ensure @a fills b1's mac_header and following fields |
@@ -247,16 +252,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, | |||
247 | b1.la = cpu_to_be16(blen + 14); | 252 | b1.la = cpu_to_be16(blen + 14); |
248 | memcpy(&b1.mac_header, a, sizeof(*a)); | 253 | memcpy(&b1.mac_header, a, sizeof(*a)); |
249 | 254 | ||
250 | d_printf(4, NULL, "I: B0 (%zu bytes)\n", sizeof(b0)); | ||
251 | d_dump(4, NULL, &b0, sizeof(b0)); | ||
252 | d_printf(4, NULL, "I: B1 (%zu bytes)\n", sizeof(b1)); | ||
253 | d_dump(4, NULL, &b1, sizeof(b1)); | ||
254 | d_printf(4, NULL, "I: B (%zu bytes)\n", blen); | ||
255 | d_dump(4, NULL, b, blen); | ||
256 | d_printf(4, NULL, "I: B 0-padding (%zu bytes)\n", zero_padding); | ||
257 | d_printf(4, NULL, "D: IV before crypto (%zu)\n", ivsize); | ||
258 | d_dump(4, NULL, iv, ivsize); | ||
259 | |||
260 | sg_init_table(sg, ARRAY_SIZE(sg)); | 255 | sg_init_table(sg, ARRAY_SIZE(sg)); |
261 | sg_set_buf(&sg[0], &b0, sizeof(b0)); | 256 | sg_set_buf(&sg[0], &b0, sizeof(b0)); |
262 | sg_set_buf(&sg[1], &b1, sizeof(b1)); | 257 | sg_set_buf(&sg[1], &b1, sizeof(b1)); |
@@ -273,8 +268,6 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, | |||
273 | result); | 268 | result); |
274 | goto error_cbc_crypt; | 269 | goto error_cbc_crypt; |
275 | } | 270 | } |
276 | d_printf(4, NULL, "D: MIC tag\n"); | ||
277 | d_dump(4, NULL, iv, ivsize); | ||
278 | 271 | ||
279 | /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] | 272 | /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] |
280 | * The procedure is to AES crypt the A0 block and XOR the MIC | 273 | * The procedure is to AES crypt the A0 block and XOR the MIC |
@@ -289,17 +282,10 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, | |||
289 | ax.counter = 0; | 282 | ax.counter = 0; |
290 | crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); | 283 | crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); |
291 | bytewise_xor(mic, &ax, iv, 8); | 284 | bytewise_xor(mic, &ax, iv, 8); |
292 | d_printf(4, NULL, "D: CTR[MIC]\n"); | ||
293 | d_dump(4, NULL, &ax, 8); | ||
294 | d_printf(4, NULL, "D: CCM-MIC tag\n"); | ||
295 | d_dump(4, NULL, mic, 8); | ||
296 | result = 8; | 285 | result = 8; |
297 | error_cbc_crypt: | 286 | error_cbc_crypt: |
298 | kfree(dst_buf); | 287 | kfree(dst_buf); |
299 | error_dst_buf: | 288 | error_dst_buf: |
300 | d_fnend(3, NULL, "(tfm_cbc %p, tfm_aes %p, mic %p, " | ||
301 | "n %p, a %p, b %p, blen %zu)\n", | ||
302 | tfm_cbc, tfm_aes, mic, n, a, b, blen); | ||
303 | return result; | 289 | return result; |
304 | } | 290 | } |
305 | 291 | ||
@@ -321,10 +307,6 @@ ssize_t wusb_prf(void *out, size_t out_size, | |||
321 | u64 sfn = 0; | 307 | u64 sfn = 0; |
322 | __le64 sfn_le; | 308 | __le64 sfn_le; |
323 | 309 | ||
324 | d_fnstart(3, NULL, "(out %p, out_size %zu, key %p, _n %p, " | ||
325 | "a %p, b %p, blen %zu, len %zu)\n", out, out_size, | ||
326 | key, _n, a, b, blen, len); | ||
327 | |||
328 | tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); | 310 | tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); |
329 | if (IS_ERR(tfm_cbc)) { | 311 | if (IS_ERR(tfm_cbc)) { |
330 | result = PTR_ERR(tfm_cbc); | 312 | result = PTR_ERR(tfm_cbc); |
@@ -366,9 +348,6 @@ error_alloc_aes: | |||
366 | error_setkey_cbc: | 348 | error_setkey_cbc: |
367 | crypto_free_blkcipher(tfm_cbc); | 349 | crypto_free_blkcipher(tfm_cbc); |
368 | error_alloc_cbc: | 350 | error_alloc_cbc: |
369 | d_fnend(3, NULL, "(out %p, out_size %zu, key %p, _n %p, " | ||
370 | "a %p, b %p, blen %zu, len %zu) = %d\n", out, out_size, | ||
371 | key, _n, a, b, blen, len, (int)bytes); | ||
372 | return result; | 351 | return result; |
373 | } | 352 | } |
374 | 353 | ||
@@ -422,14 +401,14 @@ static int wusb_oob_mic_verify(void) | |||
422 | "mismatch between MIC result and WUSB1.0[A2]\n"); | 401 | "mismatch between MIC result and WUSB1.0[A2]\n"); |
423 | hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC); | 402 | hs_size = sizeof(stv_hsmic_hs) - sizeof(stv_hsmic_hs.MIC); |
424 | printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size); | 403 | printk(KERN_ERR "E: Handshake2 in: (%zu bytes)\n", hs_size); |
425 | dump_bytes(NULL, &stv_hsmic_hs, hs_size); | 404 | wusb_key_dump(&stv_hsmic_hs, hs_size); |
426 | printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n", | 405 | printk(KERN_ERR "E: CCM Nonce in: (%zu bytes)\n", |
427 | sizeof(stv_hsmic_n)); | 406 | sizeof(stv_hsmic_n)); |
428 | dump_bytes(NULL, &stv_hsmic_n, sizeof(stv_hsmic_n)); | 407 | wusb_key_dump(&stv_hsmic_n, sizeof(stv_hsmic_n)); |
429 | printk(KERN_ERR "E: MIC out:\n"); | 408 | printk(KERN_ERR "E: MIC out:\n"); |
430 | dump_bytes(NULL, mic, sizeof(mic)); | 409 | wusb_key_dump(mic, sizeof(mic)); |
431 | printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n"); | 410 | printk(KERN_ERR "E: MIC out (from WUSB1.0[A.2]):\n"); |
432 | dump_bytes(NULL, stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC)); | 411 | wusb_key_dump(stv_hsmic_hs.MIC, sizeof(stv_hsmic_hs.MIC)); |
433 | result = -EINVAL; | 412 | result = -EINVAL; |
434 | } else | 413 | } else |
435 | result = 0; | 414 | result = 0; |
@@ -497,19 +476,16 @@ static int wusb_key_derive_verify(void) | |||
497 | printk(KERN_ERR "E: WUSB key derivation test: " | 476 | printk(KERN_ERR "E: WUSB key derivation test: " |
498 | "mismatch between key derivation result " | 477 | "mismatch between key derivation result " |
499 | "and WUSB1.0[A1] Errata 2006/12\n"); | 478 | "and WUSB1.0[A1] Errata 2006/12\n"); |
500 | printk(KERN_ERR "E: keydvt in: key (%zu bytes)\n", | 479 | printk(KERN_ERR "E: keydvt in: key\n"); |
501 | sizeof(stv_key_a1)); | 480 | wusb_key_dump(stv_key_a1, sizeof(stv_key_a1)); |
502 | dump_bytes(NULL, stv_key_a1, sizeof(stv_key_a1)); | 481 | printk(KERN_ERR "E: keydvt in: nonce\n"); |
503 | printk(KERN_ERR "E: keydvt in: nonce (%zu bytes)\n", | 482 | wusb_key_dump( &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1)); |
504 | sizeof(stv_keydvt_n_a1)); | 483 | printk(KERN_ERR "E: keydvt in: hnonce & dnonce\n"); |
505 | dump_bytes(NULL, &stv_keydvt_n_a1, sizeof(stv_keydvt_n_a1)); | 484 | wusb_key_dump(&stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1)); |
506 | printk(KERN_ERR "E: keydvt in: hnonce & dnonce (%zu bytes)\n", | ||
507 | sizeof(stv_keydvt_in_a1)); | ||
508 | dump_bytes(NULL, &stv_keydvt_in_a1, sizeof(stv_keydvt_in_a1)); | ||
509 | printk(KERN_ERR "E: keydvt out: KCK\n"); | 485 | printk(KERN_ERR "E: keydvt out: KCK\n"); |
510 | dump_bytes(NULL, &keydvt_out.kck, sizeof(keydvt_out.kck)); | 486 | wusb_key_dump(&keydvt_out.kck, sizeof(keydvt_out.kck)); |
511 | printk(KERN_ERR "E: keydvt out: PTK\n"); | 487 | printk(KERN_ERR "E: keydvt out: PTK\n"); |
512 | dump_bytes(NULL, &keydvt_out.ptk, sizeof(keydvt_out.ptk)); | 488 | wusb_key_dump(&keydvt_out.ptk, sizeof(keydvt_out.ptk)); |
513 | result = -EINVAL; | 489 | result = -EINVAL; |
514 | } else | 490 | } else |
515 | result = 0; | 491 | result = 0; |
@@ -526,10 +502,13 @@ int wusb_crypto_init(void) | |||
526 | { | 502 | { |
527 | int result; | 503 | int result; |
528 | 504 | ||
529 | result = wusb_key_derive_verify(); | 505 | if (debug_crypto_verify) { |
530 | if (result < 0) | 506 | result = wusb_key_derive_verify(); |
531 | return result; | 507 | if (result < 0) |
532 | return wusb_oob_mic_verify(); | 508 | return result; |
509 | return wusb_oob_mic_verify(); | ||
510 | } | ||
511 | return 0; | ||
533 | } | 512 | } |
534 | 513 | ||
535 | void wusb_crypto_exit(void) | 514 | void wusb_crypto_exit(void) |
diff --git a/drivers/usb/wusbcore/dev-sysfs.c b/drivers/usb/wusbcore/dev-sysfs.c index 7897a19652e5..101834576236 100644 --- a/drivers/usb/wusbcore/dev-sysfs.c +++ b/drivers/usb/wusbcore/dev-sysfs.c | |||
@@ -28,10 +28,6 @@ | |||
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include "wusbhc.h" | 29 | #include "wusbhc.h" |
30 | 30 | ||
31 | #undef D_LOCAL | ||
32 | #define D_LOCAL 4 | ||
33 | #include <linux/uwb/debug.h> | ||
34 | |||
35 | static ssize_t wusb_disconnect_store(struct device *dev, | 31 | static ssize_t wusb_disconnect_store(struct device *dev, |
36 | struct device_attribute *attr, | 32 | struct device_attribute *attr, |
37 | const char *buf, size_t size) | 33 | const char *buf, size_t size) |
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index f45d777bef34..e2e7e4bc8463 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c | |||
@@ -57,9 +57,6 @@ | |||
57 | * Called by notif.c:wusb_handle_dn_connect() | 57 | * Called by notif.c:wusb_handle_dn_connect() |
58 | * when a DN_Connect is received. | 58 | * when a DN_Connect is received. |
59 | * | 59 | * |
60 | * wusbhc_devconnect_auth() Called by rh.c:wusbhc_rh_port_reset() when | ||
61 | * doing the device connect sequence. | ||
62 | * | ||
63 | * wusb_devconnect_acked() Ack done, release resources. | 60 | * wusb_devconnect_acked() Ack done, release resources. |
64 | * | 61 | * |
65 | * wusb_handle_dn_alive() Called by notif.c:wusb_handle_dn() | 62 | * wusb_handle_dn_alive() Called by notif.c:wusb_handle_dn() |
@@ -69,9 +66,6 @@ | |||
69 | * process a disconenct request from a | 66 | * process a disconenct request from a |
70 | * device. | 67 | * device. |
71 | * | 68 | * |
72 | * wusb_dev_reset() Called by rh.c:wusbhc_rh_port_reset() when | ||
73 | * resetting a device. | ||
74 | * | ||
75 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when | 69 | * __wusb_dev_disable() Called by rh.c:wusbhc_rh_clear_port_feat() when |
76 | * disabling a port. | 70 | * disabling a port. |
77 | * | 71 | * |
@@ -97,10 +91,6 @@ | |||
97 | #include <linux/workqueue.h> | 91 | #include <linux/workqueue.h> |
98 | #include "wusbhc.h" | 92 | #include "wusbhc.h" |
99 | 93 | ||
100 | #undef D_LOCAL | ||
101 | #define D_LOCAL 1 | ||
102 | #include <linux/uwb/debug.h> | ||
103 | |||
104 | static void wusbhc_devconnect_acked_work(struct work_struct *work); | 94 | static void wusbhc_devconnect_acked_work(struct work_struct *work); |
105 | 95 | ||
106 | static void wusb_dev_free(struct wusb_dev *wusb_dev) | 96 | static void wusb_dev_free(struct wusb_dev *wusb_dev) |
@@ -240,6 +230,7 @@ static struct wusb_dev *wusbhc_cack_add(struct wusbhc *wusbhc, | |||
240 | list_add_tail(&wusb_dev->cack_node, &wusbhc->cack_list); | 230 | list_add_tail(&wusb_dev->cack_node, &wusbhc->cack_list); |
241 | wusbhc->cack_count++; | 231 | wusbhc->cack_count++; |
242 | wusbhc_fill_cack_ie(wusbhc); | 232 | wusbhc_fill_cack_ie(wusbhc); |
233 | |||
243 | return wusb_dev; | 234 | return wusb_dev; |
244 | } | 235 | } |
245 | 236 | ||
@@ -250,12 +241,9 @@ static struct wusb_dev *wusbhc_cack_add(struct wusbhc *wusbhc, | |||
250 | */ | 241 | */ |
251 | static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) | 242 | static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) |
252 | { | 243 | { |
253 | struct device *dev = wusbhc->dev; | ||
254 | d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev); | ||
255 | list_del_init(&wusb_dev->cack_node); | 244 | list_del_init(&wusb_dev->cack_node); |
256 | wusbhc->cack_count--; | 245 | wusbhc->cack_count--; |
257 | wusbhc_fill_cack_ie(wusbhc); | 246 | wusbhc_fill_cack_ie(wusbhc); |
258 | d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev); | ||
259 | } | 247 | } |
260 | 248 | ||
261 | /* | 249 | /* |
@@ -263,14 +251,11 @@ static void wusbhc_cack_rm(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) | |||
263 | static | 251 | static |
264 | void wusbhc_devconnect_acked(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) | 252 | void wusbhc_devconnect_acked(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) |
265 | { | 253 | { |
266 | struct device *dev = wusbhc->dev; | ||
267 | d_fnstart(3, dev, "(wusbhc %p wusb_dev %p)\n", wusbhc, wusb_dev); | ||
268 | wusbhc_cack_rm(wusbhc, wusb_dev); | 254 | wusbhc_cack_rm(wusbhc, wusb_dev); |
269 | if (wusbhc->cack_count) | 255 | if (wusbhc->cack_count) |
270 | wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->cack_ie.hdr); | 256 | wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->cack_ie.hdr); |
271 | else | 257 | else |
272 | wusbhc_mmcie_rm(wusbhc, &wusbhc->cack_ie.hdr); | 258 | wusbhc_mmcie_rm(wusbhc, &wusbhc->cack_ie.hdr); |
273 | d_fnend(3, dev, "(wusbhc %p wusb_dev %p) = void\n", wusbhc, wusb_dev); | ||
274 | } | 259 | } |
275 | 260 | ||
276 | static void wusbhc_devconnect_acked_work(struct work_struct *work) | 261 | static void wusbhc_devconnect_acked_work(struct work_struct *work) |
@@ -320,7 +305,6 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc, | |||
320 | struct wusb_port *port; | 305 | struct wusb_port *port; |
321 | unsigned idx, devnum; | 306 | unsigned idx, devnum; |
322 | 307 | ||
323 | d_fnstart(3, dev, "(%p, %p, %s)\n", wusbhc, dnc, pr_cdid); | ||
324 | mutex_lock(&wusbhc->mutex); | 308 | mutex_lock(&wusbhc->mutex); |
325 | 309 | ||
326 | /* Check we are not handling it already */ | 310 | /* Check we are not handling it already */ |
@@ -366,16 +350,13 @@ void wusbhc_devconnect_ack(struct wusbhc *wusbhc, struct wusb_dn_connect *dnc, | |||
366 | port->wusb_dev = wusb_dev; | 350 | port->wusb_dev = wusb_dev; |
367 | port->status |= USB_PORT_STAT_CONNECTION; | 351 | port->status |= USB_PORT_STAT_CONNECTION; |
368 | port->change |= USB_PORT_STAT_C_CONNECTION; | 352 | port->change |= USB_PORT_STAT_C_CONNECTION; |
369 | port->reset_count = 0; | ||
370 | /* Now the port status changed to connected; khubd will | 353 | /* Now the port status changed to connected; khubd will |
371 | * pick the change up and try to reset the port to bring it to | 354 | * pick the change up and try to reset the port to bring it to |
372 | * the enabled state--so this process returns up to the stack | 355 | * the enabled state--so this process returns up to the stack |
373 | * and it calls back into wusbhc_rh_port_reset() who will call | 356 | * and it calls back into wusbhc_rh_port_reset(). |
374 | * devconnect_auth(). | ||
375 | */ | 357 | */ |
376 | error_unlock: | 358 | error_unlock: |
377 | mutex_unlock(&wusbhc->mutex); | 359 | mutex_unlock(&wusbhc->mutex); |
378 | d_fnend(3, dev, "(%p, %p, %s) = void\n", wusbhc, dnc, pr_cdid); | ||
379 | return; | 360 | return; |
380 | 361 | ||
381 | } | 362 | } |
@@ -398,10 +379,8 @@ error_unlock: | |||
398 | static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | 379 | static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, |
399 | struct wusb_port *port) | 380 | struct wusb_port *port) |
400 | { | 381 | { |
401 | struct device *dev = wusbhc->dev; | ||
402 | struct wusb_dev *wusb_dev = port->wusb_dev; | 382 | struct wusb_dev *wusb_dev = port->wusb_dev; |
403 | 383 | ||
404 | d_fnstart(3, dev, "(wusbhc %p, port %p)\n", wusbhc, port); | ||
405 | port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | 384 | port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE |
406 | | USB_PORT_STAT_SUSPEND | USB_PORT_STAT_RESET | 385 | | USB_PORT_STAT_SUSPEND | USB_PORT_STAT_RESET |
407 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); | 386 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); |
@@ -413,15 +392,11 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
413 | wusb_dev_put(wusb_dev); | 392 | wusb_dev_put(wusb_dev); |
414 | } | 393 | } |
415 | port->wusb_dev = NULL; | 394 | port->wusb_dev = NULL; |
416 | /* don't reset the reset_count to zero or wusbhc_rh_port_reset will get | ||
417 | * confused! We only reset to zero when we connect a new device. | ||
418 | */ | ||
419 | 395 | ||
420 | /* After a device disconnects, change the GTK (see [WUSB] | 396 | /* After a device disconnects, change the GTK (see [WUSB] |
421 | * section 6.2.11.2). */ | 397 | * section 6.2.11.2). */ |
422 | wusbhc_gtk_rekey(wusbhc); | 398 | wusbhc_gtk_rekey(wusbhc); |
423 | 399 | ||
424 | d_fnend(3, dev, "(wusbhc %p, port %p) = void\n", wusbhc, port); | ||
425 | /* The Wireless USB part has forgotten about the device already; now | 400 | /* The Wireless USB part has forgotten about the device already; now |
426 | * khubd's timer will pick up the disconnection and remove the USB | 401 | * khubd's timer will pick up the disconnection and remove the USB |
427 | * device from the system | 402 | * device from the system |
@@ -429,39 +404,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
429 | } | 404 | } |
430 | 405 | ||
431 | /* | 406 | /* |
432 | * Authenticate a device into the WUSB Cluster | ||
433 | * | ||
434 | * Called from the Root Hub code (rh.c:wusbhc_rh_port_reset()) when | ||
435 | * asking for a reset on a port that is not enabled (ie: first connect | ||
436 | * on the port). | ||
437 | * | ||
438 | * Performs the 4way handshake to allow the device to comunicate w/ the | ||
439 | * WUSB Cluster securely; once done, issue a request to the device for | ||
440 | * it to change to address 0. | ||
441 | * | ||
442 | * This mimics the reset step of Wired USB that once resetting a | ||
443 | * device, leaves the port in enabled state and the dev with the | ||
444 | * default address (0). | ||
445 | * | ||
446 | * WUSB1.0[7.1.2] | ||
447 | * | ||
448 | * @port_idx: port where the change happened--This is the index into | ||
449 | * the wusbhc port array, not the USB port number. | ||
450 | */ | ||
451 | int wusbhc_devconnect_auth(struct wusbhc *wusbhc, u8 port_idx) | ||
452 | { | ||
453 | struct device *dev = wusbhc->dev; | ||
454 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | ||
455 | |||
456 | d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); | ||
457 | port->status &= ~USB_PORT_STAT_RESET; | ||
458 | port->status |= USB_PORT_STAT_ENABLE; | ||
459 | port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; | ||
460 | d_fnend(3, dev, "(%p, %u) = 0\n", wusbhc, port_idx); | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Refresh the list of keep alives to emit in the MMC | 407 | * Refresh the list of keep alives to emit in the MMC |
466 | * | 408 | * |
467 | * Some devices don't respond to keep alives unless they've been | 409 | * Some devices don't respond to keep alives unless they've been |
@@ -528,21 +470,15 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc) | |||
528 | */ | 470 | */ |
529 | static void wusbhc_keep_alive_run(struct work_struct *ws) | 471 | static void wusbhc_keep_alive_run(struct work_struct *ws) |
530 | { | 472 | { |
531 | struct delayed_work *dw = | 473 | struct delayed_work *dw = container_of(ws, struct delayed_work, work); |
532 | container_of(ws, struct delayed_work, work); | 474 | struct wusbhc *wusbhc = container_of(dw, struct wusbhc, keep_alive_timer); |
533 | struct wusbhc *wusbhc = | 475 | |
534 | container_of(dw, struct wusbhc, keep_alive_timer); | 476 | mutex_lock(&wusbhc->mutex); |
535 | 477 | __wusbhc_keep_alive(wusbhc); | |
536 | d_fnstart(5, wusbhc->dev, "(wusbhc %p)\n", wusbhc); | 478 | mutex_unlock(&wusbhc->mutex); |
537 | if (wusbhc->active) { | 479 | |
538 | mutex_lock(&wusbhc->mutex); | 480 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, |
539 | __wusbhc_keep_alive(wusbhc); | 481 | msecs_to_jiffies(wusbhc->trust_timeout / 2)); |
540 | mutex_unlock(&wusbhc->mutex); | ||
541 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, | ||
542 | (wusbhc->trust_timeout * CONFIG_HZ)/1000/2); | ||
543 | } | ||
544 | d_fnend(5, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); | ||
545 | return; | ||
546 | } | 482 | } |
547 | 483 | ||
548 | /* | 484 | /* |
@@ -585,10 +521,6 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr) | |||
585 | */ | 521 | */ |
586 | static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) | 522 | static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) |
587 | { | 523 | { |
588 | struct device *dev = wusbhc->dev; | ||
589 | |||
590 | d_printf(2, dev, "DN ALIVE: device 0x%02x pong\n", wusb_dev->addr); | ||
591 | |||
592 | mutex_lock(&wusbhc->mutex); | 524 | mutex_lock(&wusbhc->mutex); |
593 | wusb_dev->entry_ts = jiffies; | 525 | wusb_dev->entry_ts = jiffies; |
594 | __wusbhc_keep_alive(wusbhc); | 526 | __wusbhc_keep_alive(wusbhc); |
@@ -621,11 +553,10 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc, | |||
621 | "no-beacon" | 553 | "no-beacon" |
622 | }; | 554 | }; |
623 | 555 | ||
624 | d_fnstart(3, dev, "(%p, %p, %zu)\n", wusbhc, dn_hdr, size); | ||
625 | if (size < sizeof(*dnc)) { | 556 | if (size < sizeof(*dnc)) { |
626 | dev_err(dev, "DN CONNECT: short notification (%zu < %zu)\n", | 557 | dev_err(dev, "DN CONNECT: short notification (%zu < %zu)\n", |
627 | size, sizeof(*dnc)); | 558 | size, sizeof(*dnc)); |
628 | goto out; | 559 | return; |
629 | } | 560 | } |
630 | 561 | ||
631 | dnc = container_of(dn_hdr, struct wusb_dn_connect, hdr); | 562 | dnc = container_of(dn_hdr, struct wusb_dn_connect, hdr); |
@@ -637,10 +568,6 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc, | |||
637 | wusb_dn_connect_new_connection(dnc) ? "connect" : "reconnect"); | 568 | wusb_dn_connect_new_connection(dnc) ? "connect" : "reconnect"); |
638 | /* ACK the connect */ | 569 | /* ACK the connect */ |
639 | wusbhc_devconnect_ack(wusbhc, dnc, pr_cdid); | 570 | wusbhc_devconnect_ack(wusbhc, dnc, pr_cdid); |
640 | out: | ||
641 | d_fnend(3, dev, "(%p, %p, %zu) = void\n", | ||
642 | wusbhc, dn_hdr, size); | ||
643 | return; | ||
644 | } | 571 | } |
645 | 572 | ||
646 | /* | 573 | /* |
@@ -662,60 +589,6 @@ static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev * | |||
662 | } | 589 | } |
663 | 590 | ||
664 | /* | 591 | /* |
665 | * Reset a WUSB device on a HWA | ||
666 | * | ||
667 | * @wusbhc | ||
668 | * @port_idx Index of the port where the device is | ||
669 | * | ||
670 | * In Wireless USB, a reset is more or less equivalent to a full | ||
671 | * disconnect; so we just do a full disconnect and send the device a | ||
672 | * Device Reset IE (WUSB1.0[7.5.11]) giving it a few millisecs (6 MMCs). | ||
673 | * | ||
674 | * @wusbhc should be refcounted and unlocked | ||
675 | */ | ||
676 | int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port_idx) | ||
677 | { | ||
678 | int result; | ||
679 | struct device *dev = wusbhc->dev; | ||
680 | struct wusb_dev *wusb_dev; | ||
681 | struct wuie_reset *ie; | ||
682 | |||
683 | d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); | ||
684 | mutex_lock(&wusbhc->mutex); | ||
685 | result = 0; | ||
686 | wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; | ||
687 | if (wusb_dev == NULL) { | ||
688 | /* reset no device? ignore */ | ||
689 | dev_dbg(dev, "RESET: no device at port %u, ignoring\n", | ||
690 | port_idx); | ||
691 | goto error_unlock; | ||
692 | } | ||
693 | result = -ENOMEM; | ||
694 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); | ||
695 | if (ie == NULL) | ||
696 | goto error_unlock; | ||
697 | ie->hdr.bLength = sizeof(ie->hdr) + sizeof(ie->CDID); | ||
698 | ie->hdr.bIEIdentifier = WUIE_ID_RESET_DEVICE; | ||
699 | ie->CDID = wusb_dev->cdid; | ||
700 | result = wusbhc_mmcie_set(wusbhc, 0xff, 6, &ie->hdr); | ||
701 | if (result < 0) { | ||
702 | dev_err(dev, "RESET: cant's set MMC: %d\n", result); | ||
703 | goto error_kfree; | ||
704 | } | ||
705 | __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); | ||
706 | |||
707 | /* 120ms, hopefully 6 MMCs (FIXME) */ | ||
708 | msleep(120); | ||
709 | wusbhc_mmcie_rm(wusbhc, &ie->hdr); | ||
710 | error_kfree: | ||
711 | kfree(ie); | ||
712 | error_unlock: | ||
713 | mutex_unlock(&wusbhc->mutex); | ||
714 | d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result); | ||
715 | return result; | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * Handle a Device Notification coming a host | 592 | * Handle a Device Notification coming a host |
720 | * | 593 | * |
721 | * The Device Notification comes from a host (HWA, DWA or WHCI) | 594 | * The Device Notification comes from a host (HWA, DWA or WHCI) |
@@ -735,19 +608,17 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr, | |||
735 | struct device *dev = wusbhc->dev; | 608 | struct device *dev = wusbhc->dev; |
736 | struct wusb_dev *wusb_dev; | 609 | struct wusb_dev *wusb_dev; |
737 | 610 | ||
738 | d_fnstart(3, dev, "(%p, %p)\n", wusbhc, dn_hdr); | ||
739 | |||
740 | if (size < sizeof(struct wusb_dn_hdr)) { | 611 | if (size < sizeof(struct wusb_dn_hdr)) { |
741 | dev_err(dev, "DN data shorter than DN header (%d < %d)\n", | 612 | dev_err(dev, "DN data shorter than DN header (%d < %d)\n", |
742 | (int)size, (int)sizeof(struct wusb_dn_hdr)); | 613 | (int)size, (int)sizeof(struct wusb_dn_hdr)); |
743 | goto out; | 614 | return; |
744 | } | 615 | } |
745 | 616 | ||
746 | wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); | 617 | wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); |
747 | if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) { | 618 | if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) { |
748 | dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n", | 619 | dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n", |
749 | dn_hdr->bType, srcaddr); | 620 | dn_hdr->bType, srcaddr); |
750 | goto out; | 621 | return; |
751 | } | 622 | } |
752 | 623 | ||
753 | switch (dn_hdr->bType) { | 624 | switch (dn_hdr->bType) { |
@@ -772,9 +643,6 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr, | |||
772 | dev_warn(dev, "unknown DN %u (%d octets) from %u\n", | 643 | dev_warn(dev, "unknown DN %u (%d octets) from %u\n", |
773 | dn_hdr->bType, (int)size, srcaddr); | 644 | dn_hdr->bType, (int)size, srcaddr); |
774 | } | 645 | } |
775 | out: | ||
776 | d_fnend(3, dev, "(%p, %p) = void\n", wusbhc, dn_hdr); | ||
777 | return; | ||
778 | } | 646 | } |
779 | EXPORT_SYMBOL_GPL(wusbhc_handle_dn); | 647 | EXPORT_SYMBOL_GPL(wusbhc_handle_dn); |
780 | 648 | ||
@@ -804,59 +672,30 @@ void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port_idx) | |||
804 | struct wusb_dev *wusb_dev; | 672 | struct wusb_dev *wusb_dev; |
805 | struct wuie_disconnect *ie; | 673 | struct wuie_disconnect *ie; |
806 | 674 | ||
807 | d_fnstart(3, dev, "(%p, %u)\n", wusbhc, port_idx); | ||
808 | result = 0; | ||
809 | wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; | 675 | wusb_dev = wusb_port_by_idx(wusbhc, port_idx)->wusb_dev; |
810 | if (wusb_dev == NULL) { | 676 | if (wusb_dev == NULL) { |
811 | /* reset no device? ignore */ | 677 | /* reset no device? ignore */ |
812 | dev_dbg(dev, "DISCONNECT: no device at port %u, ignoring\n", | 678 | dev_dbg(dev, "DISCONNECT: no device at port %u, ignoring\n", |
813 | port_idx); | 679 | port_idx); |
814 | goto error; | 680 | return; |
815 | } | 681 | } |
816 | __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); | 682 | __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, port_idx)); |
817 | 683 | ||
818 | result = -ENOMEM; | ||
819 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); | 684 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); |
820 | if (ie == NULL) | 685 | if (ie == NULL) |
821 | goto error; | 686 | return; |
822 | ie->hdr.bLength = sizeof(*ie); | 687 | ie->hdr.bLength = sizeof(*ie); |
823 | ie->hdr.bIEIdentifier = WUIE_ID_DEVICE_DISCONNECT; | 688 | ie->hdr.bIEIdentifier = WUIE_ID_DEVICE_DISCONNECT; |
824 | ie->bDeviceAddress = wusb_dev->addr; | 689 | ie->bDeviceAddress = wusb_dev->addr; |
825 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &ie->hdr); | 690 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &ie->hdr); |
826 | if (result < 0) { | 691 | if (result < 0) |
827 | dev_err(dev, "DISCONNECT: can't set MMC: %d\n", result); | 692 | dev_err(dev, "DISCONNECT: can't set MMC: %d\n", result); |
828 | goto error_kfree; | 693 | else { |
694 | /* At least 6 MMCs, assuming at least 1 MMC per zone. */ | ||
695 | msleep(7*4); | ||
696 | wusbhc_mmcie_rm(wusbhc, &ie->hdr); | ||
829 | } | 697 | } |
830 | |||
831 | /* 120ms, hopefully 6 MMCs */ | ||
832 | msleep(100); | ||
833 | wusbhc_mmcie_rm(wusbhc, &ie->hdr); | ||
834 | error_kfree: | ||
835 | kfree(ie); | 698 | kfree(ie); |
836 | error: | ||
837 | d_fnend(3, dev, "(%p, %u) = %d\n", wusbhc, port_idx, result); | ||
838 | return; | ||
839 | } | ||
840 | |||
841 | static void wusb_cap_descr_printf(const unsigned level, struct device *dev, | ||
842 | const struct usb_wireless_cap_descriptor *wcd) | ||
843 | { | ||
844 | d_printf(level, dev, | ||
845 | "WUSB Capability Descriptor\n" | ||
846 | " bDevCapabilityType 0x%02x\n" | ||
847 | " bmAttributes 0x%02x\n" | ||
848 | " wPhyRates 0x%04x\n" | ||
849 | " bmTFITXPowerInfo 0x%02x\n" | ||
850 | " bmFFITXPowerInfo 0x%02x\n" | ||
851 | " bmBandGroup 0x%04x\n" | ||
852 | " bReserved 0x%02x\n", | ||
853 | wcd->bDevCapabilityType, | ||
854 | wcd->bmAttributes, | ||
855 | le16_to_cpu(wcd->wPHYRates), | ||
856 | wcd->bmTFITXPowerInfo, | ||
857 | wcd->bmFFITXPowerInfo, | ||
858 | wcd->bmBandGroup, | ||
859 | wcd->bReserved); | ||
860 | } | 699 | } |
861 | 700 | ||
862 | /* | 701 | /* |
@@ -899,8 +738,6 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev, | |||
899 | } | 738 | } |
900 | cap_size = cap_hdr->bLength; | 739 | cap_size = cap_hdr->bLength; |
901 | cap_type = cap_hdr->bDevCapabilityType; | 740 | cap_type = cap_hdr->bDevCapabilityType; |
902 | d_printf(4, dev, "BOS Capability: 0x%02x (%zu bytes)\n", | ||
903 | cap_type, cap_size); | ||
904 | if (cap_size == 0) | 741 | if (cap_size == 0) |
905 | break; | 742 | break; |
906 | if (cap_size > top - itr) { | 743 | if (cap_size > top - itr) { |
@@ -912,7 +749,6 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev, | |||
912 | result = -EBADF; | 749 | result = -EBADF; |
913 | goto error_bad_cap; | 750 | goto error_bad_cap; |
914 | } | 751 | } |
915 | d_dump(3, dev, itr, cap_size); | ||
916 | switch (cap_type) { | 752 | switch (cap_type) { |
917 | case USB_CAP_TYPE_WIRELESS_USB: | 753 | case USB_CAP_TYPE_WIRELESS_USB: |
918 | if (cap_size != sizeof(*wusb_dev->wusb_cap_descr)) | 754 | if (cap_size != sizeof(*wusb_dev->wusb_cap_descr)) |
@@ -920,10 +756,8 @@ static int wusb_dev_bos_grok(struct usb_device *usb_dev, | |||
920 | "descriptor is %zu bytes vs %zu " | 756 | "descriptor is %zu bytes vs %zu " |
921 | "needed\n", cap_size, | 757 | "needed\n", cap_size, |
922 | sizeof(*wusb_dev->wusb_cap_descr)); | 758 | sizeof(*wusb_dev->wusb_cap_descr)); |
923 | else { | 759 | else |
924 | wusb_dev->wusb_cap_descr = itr; | 760 | wusb_dev->wusb_cap_descr = itr; |
925 | wusb_cap_descr_printf(3, dev, itr); | ||
926 | } | ||
927 | break; | 761 | break; |
928 | default: | 762 | default: |
929 | dev_err(dev, "BUG? Unknown BOS capability 0x%02x " | 763 | dev_err(dev, "BUG? Unknown BOS capability 0x%02x " |
@@ -988,9 +822,7 @@ static int wusb_dev_bos_add(struct usb_device *usb_dev, | |||
988 | "%zu bytes): %zd\n", desc_size, result); | 822 | "%zu bytes): %zd\n", desc_size, result); |
989 | goto error_get_descriptor; | 823 | goto error_get_descriptor; |
990 | } | 824 | } |
991 | d_printf(2, dev, "Got BOS descriptor %zd bytes, %u capabilities\n", | 825 | |
992 | result, bos->bNumDeviceCaps); | ||
993 | d_dump(2, dev, bos, result); | ||
994 | result = wusb_dev_bos_grok(usb_dev, wusb_dev, bos, result); | 826 | result = wusb_dev_bos_grok(usb_dev, wusb_dev, bos, result); |
995 | if (result < 0) | 827 | if (result < 0) |
996 | goto error_bad_bos; | 828 | goto error_bad_bos; |
@@ -1056,8 +888,6 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev) | |||
1056 | if (usb_dev->wusb == 0 || usb_dev->devnum == 1) | 888 | if (usb_dev->wusb == 0 || usb_dev->devnum == 1) |
1057 | return; /* skip non wusb and wusb RHs */ | 889 | return; /* skip non wusb and wusb RHs */ |
1058 | 890 | ||
1059 | d_fnstart(3, dev, "(usb_dev %p)\n", usb_dev); | ||
1060 | |||
1061 | wusbhc = wusbhc_get_by_usb_dev(usb_dev); | 891 | wusbhc = wusbhc_get_by_usb_dev(usb_dev); |
1062 | if (wusbhc == NULL) | 892 | if (wusbhc == NULL) |
1063 | goto error_nodev; | 893 | goto error_nodev; |
@@ -1087,7 +917,6 @@ out: | |||
1087 | wusb_dev_put(wusb_dev); | 917 | wusb_dev_put(wusb_dev); |
1088 | wusbhc_put(wusbhc); | 918 | wusbhc_put(wusbhc); |
1089 | error_nodev: | 919 | error_nodev: |
1090 | d_fnend(3, dev, "(usb_dev %p) = void\n", usb_dev); | ||
1091 | return; | 920 | return; |
1092 | 921 | ||
1093 | wusb_dev_sysfs_rm(wusb_dev); | 922 | wusb_dev_sysfs_rm(wusb_dev); |
@@ -1174,11 +1003,10 @@ EXPORT_SYMBOL_GPL(__wusb_dev_get_by_usb_dev); | |||
1174 | 1003 | ||
1175 | void wusb_dev_destroy(struct kref *_wusb_dev) | 1004 | void wusb_dev_destroy(struct kref *_wusb_dev) |
1176 | { | 1005 | { |
1177 | struct wusb_dev *wusb_dev | 1006 | struct wusb_dev *wusb_dev = container_of(_wusb_dev, struct wusb_dev, refcnt); |
1178 | = container_of(_wusb_dev, struct wusb_dev, refcnt); | 1007 | |
1179 | list_del_init(&wusb_dev->cack_node); | 1008 | list_del_init(&wusb_dev->cack_node); |
1180 | wusb_dev_free(wusb_dev); | 1009 | wusb_dev_free(wusb_dev); |
1181 | d_fnend(1, NULL, "%s (wusb_dev %p) = void\n", __func__, wusb_dev); | ||
1182 | } | 1010 | } |
1183 | EXPORT_SYMBOL_GPL(wusb_dev_destroy); | 1011 | EXPORT_SYMBOL_GPL(wusb_dev_destroy); |
1184 | 1012 | ||
@@ -1190,8 +1018,6 @@ EXPORT_SYMBOL_GPL(wusb_dev_destroy); | |||
1190 | */ | 1018 | */ |
1191 | int wusbhc_devconnect_create(struct wusbhc *wusbhc) | 1019 | int wusbhc_devconnect_create(struct wusbhc *wusbhc) |
1192 | { | 1020 | { |
1193 | d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc); | ||
1194 | |||
1195 | wusbhc->keep_alive_ie.hdr.bIEIdentifier = WUIE_ID_KEEP_ALIVE; | 1021 | wusbhc->keep_alive_ie.hdr.bIEIdentifier = WUIE_ID_KEEP_ALIVE; |
1196 | wusbhc->keep_alive_ie.hdr.bLength = sizeof(wusbhc->keep_alive_ie.hdr); | 1022 | wusbhc->keep_alive_ie.hdr.bLength = sizeof(wusbhc->keep_alive_ie.hdr); |
1197 | INIT_DELAYED_WORK(&wusbhc->keep_alive_timer, wusbhc_keep_alive_run); | 1023 | INIT_DELAYED_WORK(&wusbhc->keep_alive_timer, wusbhc_keep_alive_run); |
@@ -1200,7 +1026,6 @@ int wusbhc_devconnect_create(struct wusbhc *wusbhc) | |||
1200 | wusbhc->cack_ie.hdr.bLength = sizeof(wusbhc->cack_ie.hdr); | 1026 | wusbhc->cack_ie.hdr.bLength = sizeof(wusbhc->cack_ie.hdr); |
1201 | INIT_LIST_HEAD(&wusbhc->cack_list); | 1027 | INIT_LIST_HEAD(&wusbhc->cack_list); |
1202 | 1028 | ||
1203 | d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); | ||
1204 | return 0; | 1029 | return 0; |
1205 | } | 1030 | } |
1206 | 1031 | ||
@@ -1209,8 +1034,7 @@ int wusbhc_devconnect_create(struct wusbhc *wusbhc) | |||
1209 | */ | 1034 | */ |
1210 | void wusbhc_devconnect_destroy(struct wusbhc *wusbhc) | 1035 | void wusbhc_devconnect_destroy(struct wusbhc *wusbhc) |
1211 | { | 1036 | { |
1212 | d_fnstart(3, wusbhc->dev, "(wusbhc %p)\n", wusbhc); | 1037 | /* no op */ |
1213 | d_fnend(3, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc); | ||
1214 | } | 1038 | } |
1215 | 1039 | ||
1216 | /* | 1040 | /* |
@@ -1222,8 +1046,7 @@ void wusbhc_devconnect_destroy(struct wusbhc *wusbhc) | |||
1222 | * FIXME: This also enables the keep alives but this is not necessary | 1046 | * FIXME: This also enables the keep alives but this is not necessary |
1223 | * until there are connected and authenticated devices. | 1047 | * until there are connected and authenticated devices. |
1224 | */ | 1048 | */ |
1225 | int wusbhc_devconnect_start(struct wusbhc *wusbhc, | 1049 | int wusbhc_devconnect_start(struct wusbhc *wusbhc) |
1226 | const struct wusb_ckhdid *chid) | ||
1227 | { | 1050 | { |
1228 | struct device *dev = wusbhc->dev; | 1051 | struct device *dev = wusbhc->dev; |
1229 | struct wuie_host_info *hi; | 1052 | struct wuie_host_info *hi; |
@@ -1236,7 +1059,7 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc, | |||
1236 | hi->hdr.bLength = sizeof(*hi); | 1059 | hi->hdr.bLength = sizeof(*hi); |
1237 | hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO; | 1060 | hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO; |
1238 | hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL); | 1061 | hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL); |
1239 | hi->CHID = *chid; | 1062 | hi->CHID = wusbhc->chid; |
1240 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr); | 1063 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr); |
1241 | if (result < 0) { | 1064 | if (result < 0) { |
1242 | dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result); | 1065 | dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result); |
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c index cfa77a01cebd..3b52161e6e9c 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/usb/wusbcore/mmc.c | |||
@@ -159,15 +159,35 @@ found: | |||
159 | } | 159 | } |
160 | EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm); | 160 | EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm); |
161 | 161 | ||
162 | static int wusbhc_mmc_start(struct wusbhc *wusbhc) | ||
163 | { | ||
164 | int ret; | ||
165 | |||
166 | mutex_lock(&wusbhc->mutex); | ||
167 | ret = wusbhc->start(wusbhc); | ||
168 | if (ret >= 0) | ||
169 | wusbhc->active = 1; | ||
170 | mutex_unlock(&wusbhc->mutex); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static void wusbhc_mmc_stop(struct wusbhc *wusbhc) | ||
176 | { | ||
177 | mutex_lock(&wusbhc->mutex); | ||
178 | wusbhc->active = 0; | ||
179 | wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS); | ||
180 | mutex_unlock(&wusbhc->mutex); | ||
181 | } | ||
182 | |||
162 | /* | 183 | /* |
163 | * wusbhc_start - start transmitting MMCs and accepting connections | 184 | * wusbhc_start - start transmitting MMCs and accepting connections |
164 | * @wusbhc: the HC to start | 185 | * @wusbhc: the HC to start |
165 | * @chid: the CHID to use for this host | ||
166 | * | 186 | * |
167 | * Establishes a cluster reservation, enables device connections, and | 187 | * Establishes a cluster reservation, enables device connections, and |
168 | * starts MMCs with appropriate DNTS parameters. | 188 | * starts MMCs with appropriate DNTS parameters. |
169 | */ | 189 | */ |
170 | int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | 190 | int wusbhc_start(struct wusbhc *wusbhc) |
171 | { | 191 | { |
172 | int result; | 192 | int result; |
173 | struct device *dev = wusbhc->dev; | 193 | struct device *dev = wusbhc->dev; |
@@ -181,7 +201,7 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | |||
181 | goto error_rsv_establish; | 201 | goto error_rsv_establish; |
182 | } | 202 | } |
183 | 203 | ||
184 | result = wusbhc_devconnect_start(wusbhc, chid); | 204 | result = wusbhc_devconnect_start(wusbhc); |
185 | if (result < 0) { | 205 | if (result < 0) { |
186 | dev_err(dev, "error enabling device connections: %d\n", result); | 206 | dev_err(dev, "error enabling device connections: %d\n", result); |
187 | goto error_devconnect_start; | 207 | goto error_devconnect_start; |
@@ -199,12 +219,12 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | |||
199 | dev_err(dev, "Cannot set DNTS parameters: %d\n", result); | 219 | dev_err(dev, "Cannot set DNTS parameters: %d\n", result); |
200 | goto error_set_num_dnts; | 220 | goto error_set_num_dnts; |
201 | } | 221 | } |
202 | result = wusbhc->start(wusbhc); | 222 | result = wusbhc_mmc_start(wusbhc); |
203 | if (result < 0) { | 223 | if (result < 0) { |
204 | dev_err(dev, "error starting wusbch: %d\n", result); | 224 | dev_err(dev, "error starting wusbch: %d\n", result); |
205 | goto error_wusbhc_start; | 225 | goto error_wusbhc_start; |
206 | } | 226 | } |
207 | wusbhc->active = 1; | 227 | |
208 | return 0; | 228 | return 0; |
209 | 229 | ||
210 | error_wusbhc_start: | 230 | error_wusbhc_start: |
@@ -219,76 +239,17 @@ error_rsv_establish: | |||
219 | } | 239 | } |
220 | 240 | ||
221 | /* | 241 | /* |
222 | * Disconnect all from the WUSB Channel | ||
223 | * | ||
224 | * Send a Host Disconnect IE in the MMC, wait, don't send it any more | ||
225 | */ | ||
226 | static int __wusbhc_host_disconnect_ie(struct wusbhc *wusbhc) | ||
227 | { | ||
228 | int result = -ENOMEM; | ||
229 | struct wuie_host_disconnect *host_disconnect_ie; | ||
230 | might_sleep(); | ||
231 | host_disconnect_ie = kmalloc(sizeof(*host_disconnect_ie), GFP_KERNEL); | ||
232 | if (host_disconnect_ie == NULL) | ||
233 | goto error_alloc; | ||
234 | host_disconnect_ie->hdr.bLength = sizeof(*host_disconnect_ie); | ||
235 | host_disconnect_ie->hdr.bIEIdentifier = WUIE_ID_HOST_DISCONNECT; | ||
236 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &host_disconnect_ie->hdr); | ||
237 | if (result < 0) | ||
238 | goto error_mmcie_set; | ||
239 | |||
240 | /* WUSB1.0[8.5.3.1 & 7.5.2] */ | ||
241 | msleep(100); | ||
242 | wusbhc_mmcie_rm(wusbhc, &host_disconnect_ie->hdr); | ||
243 | error_mmcie_set: | ||
244 | kfree(host_disconnect_ie); | ||
245 | error_alloc: | ||
246 | return result; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * wusbhc_stop - stop transmitting MMCs | 242 | * wusbhc_stop - stop transmitting MMCs |
251 | * @wusbhc: the HC to stop | 243 | * @wusbhc: the HC to stop |
252 | * | 244 | * |
253 | * Send a Host Disconnect IE, wait, remove all the MMCs (stop sending MMCs). | 245 | * Stops the WUSB channel and removes the cluster reservation. |
254 | * | ||
255 | * If we can't allocate a Host Stop IE, screw it, we don't notify the | ||
256 | * devices we are disconnecting... | ||
257 | */ | 246 | */ |
258 | void wusbhc_stop(struct wusbhc *wusbhc) | 247 | void wusbhc_stop(struct wusbhc *wusbhc) |
259 | { | 248 | { |
260 | if (wusbhc->active) { | 249 | wusbhc_mmc_stop(wusbhc); |
261 | wusbhc->active = 0; | 250 | wusbhc_sec_stop(wusbhc); |
262 | wusbhc->stop(wusbhc); | 251 | wusbhc_devconnect_stop(wusbhc); |
263 | wusbhc_sec_stop(wusbhc); | 252 | wusbhc_rsv_terminate(wusbhc); |
264 | __wusbhc_host_disconnect_ie(wusbhc); | ||
265 | wusbhc_devconnect_stop(wusbhc); | ||
266 | wusbhc_rsv_terminate(wusbhc); | ||
267 | } | ||
268 | } | ||
269 | EXPORT_SYMBOL_GPL(wusbhc_stop); | ||
270 | |||
271 | /* | ||
272 | * Change the CHID in a WUSB Channel | ||
273 | * | ||
274 | * If it is just a new CHID, send a Host Disconnect IE and then change | ||
275 | * the CHID IE. | ||
276 | */ | ||
277 | static int __wusbhc_chid_change(struct wusbhc *wusbhc, | ||
278 | const struct wusb_ckhdid *chid) | ||
279 | { | ||
280 | int result = -ENOSYS; | ||
281 | struct device *dev = wusbhc->dev; | ||
282 | dev_err(dev, "%s() not implemented yet\n", __func__); | ||
283 | return result; | ||
284 | |||
285 | BUG_ON(wusbhc->wuie_host_info == NULL); | ||
286 | __wusbhc_host_disconnect_ie(wusbhc); | ||
287 | wusbhc->wuie_host_info->CHID = *chid; | ||
288 | result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->wuie_host_info->hdr); | ||
289 | if (result < 0) | ||
290 | dev_err(dev, "Can't update Host Info WUSB IE: %d\n", result); | ||
291 | return result; | ||
292 | } | 253 | } |
293 | 254 | ||
294 | /* | 255 | /* |
@@ -306,16 +267,19 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | |||
306 | chid = NULL; | 267 | chid = NULL; |
307 | 268 | ||
308 | mutex_lock(&wusbhc->mutex); | 269 | mutex_lock(&wusbhc->mutex); |
309 | if (wusbhc->active) { | 270 | if (chid) { |
310 | if (chid) | 271 | if (wusbhc->active) { |
311 | result = __wusbhc_chid_change(wusbhc, chid); | 272 | mutex_unlock(&wusbhc->mutex); |
312 | else | 273 | return -EBUSY; |
313 | wusbhc_stop(wusbhc); | 274 | } |
314 | } else { | 275 | wusbhc->chid = *chid; |
315 | if (chid) | ||
316 | wusbhc_start(wusbhc, chid); | ||
317 | } | 276 | } |
318 | mutex_unlock(&wusbhc->mutex); | 277 | mutex_unlock(&wusbhc->mutex); |
278 | |||
279 | if (chid) | ||
280 | result = uwb_radio_start(&wusbhc->pal); | ||
281 | else | ||
282 | uwb_radio_stop(&wusbhc->pal); | ||
319 | return result; | 283 | return result; |
320 | } | 284 | } |
321 | EXPORT_SYMBOL_GPL(wusbhc_chid_set); | 285 | EXPORT_SYMBOL_GPL(wusbhc_chid_set); |
diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c index 7cc51e9905cf..d0b172c5ecc7 100644 --- a/drivers/usb/wusbcore/pal.c +++ b/drivers/usb/wusbcore/pal.c | |||
@@ -18,6 +18,16 @@ | |||
18 | */ | 18 | */ |
19 | #include "wusbhc.h" | 19 | #include "wusbhc.h" |
20 | 20 | ||
21 | static void wusbhc_channel_changed(struct uwb_pal *pal, int channel) | ||
22 | { | ||
23 | struct wusbhc *wusbhc = container_of(pal, struct wusbhc, pal); | ||
24 | |||
25 | if (channel < 0) | ||
26 | wusbhc_stop(wusbhc); | ||
27 | else | ||
28 | wusbhc_start(wusbhc); | ||
29 | } | ||
30 | |||
21 | /** | 31 | /** |
22 | * wusbhc_pal_register - register the WUSB HC as a UWB PAL | 32 | * wusbhc_pal_register - register the WUSB HC as a UWB PAL |
23 | * @wusbhc: the WUSB HC | 33 | * @wusbhc: the WUSB HC |
@@ -28,8 +38,10 @@ int wusbhc_pal_register(struct wusbhc *wusbhc) | |||
28 | 38 | ||
29 | wusbhc->pal.name = "wusbhc"; | 39 | wusbhc->pal.name = "wusbhc"; |
30 | wusbhc->pal.device = wusbhc->usb_hcd.self.controller; | 40 | wusbhc->pal.device = wusbhc->usb_hcd.self.controller; |
41 | wusbhc->pal.rc = wusbhc->uwb_rc; | ||
42 | wusbhc->pal.channel_changed = wusbhc_channel_changed; | ||
31 | 43 | ||
32 | return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal); | 44 | return uwb_pal_register(&wusbhc->pal); |
33 | } | 45 | } |
34 | 46 | ||
35 | /** | 47 | /** |
@@ -38,5 +50,5 @@ int wusbhc_pal_register(struct wusbhc *wusbhc) | |||
38 | */ | 50 | */ |
39 | void wusbhc_pal_unregister(struct wusbhc *wusbhc) | 51 | void wusbhc_pal_unregister(struct wusbhc *wusbhc) |
40 | { | 52 | { |
41 | uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal); | 53 | uwb_pal_unregister(&wusbhc->pal); |
42 | } | 54 | } |
diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c index fc63e77ded2d..4ed97360c046 100644 --- a/drivers/usb/wusbcore/reservation.c +++ b/drivers/usb/wusbcore/reservation.c | |||
@@ -48,18 +48,19 @@ static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv) | |||
48 | { | 48 | { |
49 | struct wusbhc *wusbhc = rsv->pal_priv; | 49 | struct wusbhc *wusbhc = rsv->pal_priv; |
50 | struct device *dev = wusbhc->dev; | 50 | struct device *dev = wusbhc->dev; |
51 | struct uwb_mas_bm mas; | ||
51 | char buf[72]; | 52 | char buf[72]; |
52 | 53 | ||
53 | switch (rsv->state) { | 54 | switch (rsv->state) { |
54 | case UWB_RSV_STATE_O_ESTABLISHED: | 55 | case UWB_RSV_STATE_O_ESTABLISHED: |
55 | bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS); | 56 | uwb_rsv_get_usable_mas(rsv, &mas); |
57 | bitmap_scnprintf(buf, sizeof(buf), mas.bm, UWB_NUM_MAS); | ||
56 | dev_dbg(dev, "established reservation: %s\n", buf); | 58 | dev_dbg(dev, "established reservation: %s\n", buf); |
57 | wusbhc_bwa_set(wusbhc, rsv->stream, &rsv->mas); | 59 | wusbhc_bwa_set(wusbhc, rsv->stream, &mas); |
58 | break; | 60 | break; |
59 | case UWB_RSV_STATE_NONE: | 61 | case UWB_RSV_STATE_NONE: |
60 | dev_dbg(dev, "removed reservation\n"); | 62 | dev_dbg(dev, "removed reservation\n"); |
61 | wusbhc_bwa_set(wusbhc, 0, NULL); | 63 | wusbhc_bwa_set(wusbhc, 0, NULL); |
62 | wusbhc->rsv = NULL; | ||
63 | break; | 64 | break; |
64 | default: | 65 | default: |
65 | dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state); | 66 | dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state); |
@@ -86,13 +87,12 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc) | |||
86 | bcid.data[0] = wusbhc->cluster_id; | 87 | bcid.data[0] = wusbhc->cluster_id; |
87 | bcid.data[1] = 0; | 88 | bcid.data[1] = 0; |
88 | 89 | ||
89 | rsv->owner = &rc->uwb_dev; | ||
90 | rsv->target.type = UWB_RSV_TARGET_DEVADDR; | 90 | rsv->target.type = UWB_RSV_TARGET_DEVADDR; |
91 | rsv->target.devaddr = bcid; | 91 | rsv->target.devaddr = bcid; |
92 | rsv->type = UWB_DRP_TYPE_PRIVATE; | 92 | rsv->type = UWB_DRP_TYPE_PRIVATE; |
93 | rsv->max_mas = 256; | 93 | rsv->max_mas = 256; /* try to get as much as possible */ |
94 | rsv->min_mas = 16; /* one MAS per zone? */ | 94 | rsv->min_mas = 15; /* one MAS per zone */ |
95 | rsv->sparsity = 16; /* at least one MAS in each zone? */ | 95 | rsv->max_interval = 1; /* max latency is one zone */ |
96 | rsv->is_multicast = true; | 96 | rsv->is_multicast = true; |
97 | 97 | ||
98 | ret = uwb_rsv_establish(rsv); | 98 | ret = uwb_rsv_establish(rsv); |
@@ -105,11 +105,14 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc) | |||
105 | 105 | ||
106 | 106 | ||
107 | /** | 107 | /** |
108 | * wusbhc_rsv_terminate - terminate any cluster reservation | 108 | * wusbhc_rsv_terminate - terminate the cluster reservation |
109 | * @wusbhc: the WUSB host whose reservation is to be terminated | 109 | * @wusbhc: the WUSB host whose reservation is to be terminated |
110 | */ | 110 | */ |
111 | void wusbhc_rsv_terminate(struct wusbhc *wusbhc) | 111 | void wusbhc_rsv_terminate(struct wusbhc *wusbhc) |
112 | { | 112 | { |
113 | if (wusbhc->rsv) | 113 | if (wusbhc->rsv) { |
114 | uwb_rsv_terminate(wusbhc->rsv); | 114 | uwb_rsv_terminate(wusbhc->rsv); |
115 | uwb_rsv_destroy(wusbhc->rsv); | ||
116 | wusbhc->rsv = NULL; | ||
117 | } | ||
115 | } | 118 | } |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 267a64325106..95c6fa3bf6b2 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
@@ -71,19 +71,20 @@ | |||
71 | */ | 71 | */ |
72 | #include "wusbhc.h" | 72 | #include "wusbhc.h" |
73 | 73 | ||
74 | #define D_LOCAL 0 | ||
75 | #include <linux/uwb/debug.h> | ||
76 | |||
77 | /* | 74 | /* |
78 | * Reset a fake port | 75 | * Reset a fake port |
79 | * | 76 | * |
80 | * This can be called to reset a port from any other state or to reset | 77 | * Using a Reset Device IE is too heavyweight as it causes the device |
81 | * it when connecting. In Wireless USB they are different; when doing | 78 | * to enter the UnConnected state and leave the cluster, this can mean |
82 | * a new connect that involves going over the authentication. When | 79 | * that when the device reconnects it is connected to a different fake |
83 | * just reseting, its a different story. | 80 | * port. |
81 | * | ||
82 | * Instead, reset authenticated devices with a SetAddress(0), followed | ||
83 | * by a SetAddresss(AuthAddr). | ||
84 | * | 84 | * |
85 | * The Linux USB stack resets a port twice before it considers it | 85 | * For unauthenticated devices just pretend to reset but do nothing. |
86 | * enabled, so we have to detect and ignore that. | 86 | * If the device initialization continues to fail it will eventually |
87 | * time out after TrustTimeout and enter the UnConnected state. | ||
87 | * | 88 | * |
88 | * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. | 89 | * @wusbhc is assumed referenced and @wusbhc->mutex unlocked. |
89 | * | 90 | * |
@@ -97,20 +98,20 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) | |||
97 | { | 98 | { |
98 | int result = 0; | 99 | int result = 0; |
99 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | 100 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); |
101 | struct wusb_dev *wusb_dev = port->wusb_dev; | ||
100 | 102 | ||
101 | d_fnstart(3, wusbhc->dev, "(wusbhc %p port_idx %u)\n", | 103 | port->status |= USB_PORT_STAT_RESET; |
102 | wusbhc, port_idx); | 104 | port->change |= USB_PORT_STAT_C_RESET; |
103 | if (port->reset_count == 0) { | 105 | |
104 | wusbhc_devconnect_auth(wusbhc, port_idx); | 106 | if (wusb_dev->addr & WUSB_DEV_ADDR_UNAUTH) |
105 | port->reset_count++; | 107 | result = 0; |
106 | } else if (port->reset_count == 1) | ||
107 | /* see header */ | ||
108 | d_printf(2, wusbhc->dev, "Ignoring second reset on port_idx " | ||
109 | "%u\n", port_idx); | ||
110 | else | 108 | else |
111 | result = wusbhc_dev_reset(wusbhc, port_idx); | 109 | result = wusb_dev_update_address(wusbhc, wusb_dev); |
112 | d_fnend(3, wusbhc->dev, "(wusbhc %p port_idx %u) = %d\n", | 110 | |
113 | wusbhc, port_idx, result); | 111 | port->status &= ~USB_PORT_STAT_RESET; |
112 | port->status |= USB_PORT_STAT_ENABLE; | ||
113 | port->change |= USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_ENABLE; | ||
114 | |||
114 | return result; | 115 | return result; |
115 | } | 116 | } |
116 | 117 | ||
@@ -138,7 +139,6 @@ int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) | |||
138 | size_t cnt, size; | 139 | size_t cnt, size; |
139 | unsigned long *buf = (unsigned long *) _buf; | 140 | unsigned long *buf = (unsigned long *) _buf; |
140 | 141 | ||
141 | d_fnstart(1, wusbhc->dev, "(wusbhc %p)\n", wusbhc); | ||
142 | /* WE DON'T LOCK, see comment */ | 142 | /* WE DON'T LOCK, see comment */ |
143 | size = wusbhc->ports_max + 1 /* hub bit */; | 143 | size = wusbhc->ports_max + 1 /* hub bit */; |
144 | size = (size + 8 - 1) / 8; /* round to bytes */ | 144 | size = (size + 8 - 1) / 8; /* round to bytes */ |
@@ -147,8 +147,6 @@ int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf) | |||
147 | set_bit(cnt + 1, buf); | 147 | set_bit(cnt + 1, buf); |
148 | else | 148 | else |
149 | clear_bit(cnt + 1, buf); | 149 | clear_bit(cnt + 1, buf); |
150 | d_fnend(1, wusbhc->dev, "(wusbhc %p) %u, buffer:\n", wusbhc, (int)size); | ||
151 | d_dump(1, wusbhc->dev, _buf, size); | ||
152 | return size; | 150 | return size; |
153 | } | 151 | } |
154 | EXPORT_SYMBOL_GPL(wusbhc_rh_status_data); | 152 | EXPORT_SYMBOL_GPL(wusbhc_rh_status_data); |
@@ -197,9 +195,7 @@ static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue, | |||
197 | static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature) | 195 | static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature) |
198 | { | 196 | { |
199 | int result; | 197 | int result; |
200 | struct device *dev = wusbhc->dev; | ||
201 | 198 | ||
202 | d_fnstart(4, dev, "(%p, feature 0x%04u)\n", wusbhc, feature); | ||
203 | switch (feature) { | 199 | switch (feature) { |
204 | case C_HUB_LOCAL_POWER: | 200 | case C_HUB_LOCAL_POWER: |
205 | /* FIXME: maybe plug bit 0 to the power input status, | 201 | /* FIXME: maybe plug bit 0 to the power input status, |
@@ -211,7 +207,6 @@ static int wusbhc_rh_clear_hub_feat(struct wusbhc *wusbhc, u16 feature) | |||
211 | default: | 207 | default: |
212 | result = -EPIPE; | 208 | result = -EPIPE; |
213 | } | 209 | } |
214 | d_fnend(4, dev, "(%p, feature 0x%04u), %d\n", wusbhc, feature, result); | ||
215 | return result; | 210 | return result; |
216 | } | 211 | } |
217 | 212 | ||
@@ -238,14 +233,10 @@ static int wusbhc_rh_get_hub_status(struct wusbhc *wusbhc, u32 *buf, | |||
238 | static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature, | 233 | static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature, |
239 | u8 selector, u8 port_idx) | 234 | u8 selector, u8 port_idx) |
240 | { | 235 | { |
241 | int result = -EINVAL; | ||
242 | struct device *dev = wusbhc->dev; | 236 | struct device *dev = wusbhc->dev; |
243 | 237 | ||
244 | d_fnstart(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d)\n", | ||
245 | feature, selector, port_idx); | ||
246 | |||
247 | if (port_idx > wusbhc->ports_max) | 238 | if (port_idx > wusbhc->ports_max) |
248 | goto error; | 239 | return -EINVAL; |
249 | 240 | ||
250 | switch (feature) { | 241 | switch (feature) { |
251 | /* According to USB2.0[11.24.2.13]p2, these features | 242 | /* According to USB2.0[11.24.2.13]p2, these features |
@@ -255,35 +246,27 @@ static int wusbhc_rh_set_port_feat(struct wusbhc *wusbhc, u16 feature, | |||
255 | case USB_PORT_FEAT_C_SUSPEND: | 246 | case USB_PORT_FEAT_C_SUSPEND: |
256 | case USB_PORT_FEAT_C_CONNECTION: | 247 | case USB_PORT_FEAT_C_CONNECTION: |
257 | case USB_PORT_FEAT_C_RESET: | 248 | case USB_PORT_FEAT_C_RESET: |
258 | result = 0; | 249 | return 0; |
259 | break; | ||
260 | |||
261 | case USB_PORT_FEAT_POWER: | 250 | case USB_PORT_FEAT_POWER: |
262 | /* No such thing, but we fake it works */ | 251 | /* No such thing, but we fake it works */ |
263 | mutex_lock(&wusbhc->mutex); | 252 | mutex_lock(&wusbhc->mutex); |
264 | wusb_port_by_idx(wusbhc, port_idx)->status |= USB_PORT_STAT_POWER; | 253 | wusb_port_by_idx(wusbhc, port_idx)->status |= USB_PORT_STAT_POWER; |
265 | mutex_unlock(&wusbhc->mutex); | 254 | mutex_unlock(&wusbhc->mutex); |
266 | result = 0; | 255 | return 0; |
267 | break; | ||
268 | case USB_PORT_FEAT_RESET: | 256 | case USB_PORT_FEAT_RESET: |
269 | result = wusbhc_rh_port_reset(wusbhc, port_idx); | 257 | return wusbhc_rh_port_reset(wusbhc, port_idx); |
270 | break; | ||
271 | case USB_PORT_FEAT_ENABLE: | 258 | case USB_PORT_FEAT_ENABLE: |
272 | case USB_PORT_FEAT_SUSPEND: | 259 | case USB_PORT_FEAT_SUSPEND: |
273 | dev_err(dev, "(port_idx %d) set feat %d/%d UNIMPLEMENTED\n", | 260 | dev_err(dev, "(port_idx %d) set feat %d/%d UNIMPLEMENTED\n", |
274 | port_idx, feature, selector); | 261 | port_idx, feature, selector); |
275 | result = -ENOSYS; | 262 | return -ENOSYS; |
276 | break; | ||
277 | default: | 263 | default: |
278 | dev_err(dev, "(port_idx %d) set feat %d/%d UNKNOWN\n", | 264 | dev_err(dev, "(port_idx %d) set feat %d/%d UNKNOWN\n", |
279 | port_idx, feature, selector); | 265 | port_idx, feature, selector); |
280 | result = -EPIPE; | 266 | return -EPIPE; |
281 | break; | ||
282 | } | 267 | } |
283 | error: | 268 | |
284 | d_fnend(4, dev, "(feat 0x%04u, selector 0x%u, port_idx %d) = %d\n", | 269 | return 0; |
285 | feature, selector, port_idx, result); | ||
286 | return result; | ||
287 | } | 270 | } |
288 | 271 | ||
289 | /* | 272 | /* |
@@ -294,17 +277,13 @@ error: | |||
294 | static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, | 277 | static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, |
295 | u8 selector, u8 port_idx) | 278 | u8 selector, u8 port_idx) |
296 | { | 279 | { |
297 | int result = -EINVAL; | 280 | int result = 0; |
298 | struct device *dev = wusbhc->dev; | 281 | struct device *dev = wusbhc->dev; |
299 | 282 | ||
300 | d_fnstart(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d)\n", | ||
301 | wusbhc, feature, selector, port_idx); | ||
302 | |||
303 | if (port_idx > wusbhc->ports_max) | 283 | if (port_idx > wusbhc->ports_max) |
304 | goto error; | 284 | return -EINVAL; |
305 | 285 | ||
306 | mutex_lock(&wusbhc->mutex); | 286 | mutex_lock(&wusbhc->mutex); |
307 | result = 0; | ||
308 | switch (feature) { | 287 | switch (feature) { |
309 | case USB_PORT_FEAT_POWER: /* fake port always on */ | 288 | case USB_PORT_FEAT_POWER: /* fake port always on */ |
310 | /* According to USB2.0[11.24.2.7.1.4], no need to implement? */ | 289 | /* According to USB2.0[11.24.2.7.1.4], no need to implement? */ |
@@ -324,10 +303,8 @@ static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, | |||
324 | break; | 303 | break; |
325 | case USB_PORT_FEAT_SUSPEND: | 304 | case USB_PORT_FEAT_SUSPEND: |
326 | case USB_PORT_FEAT_C_SUSPEND: | 305 | case USB_PORT_FEAT_C_SUSPEND: |
327 | case 0xffff: /* ??? FIXME */ | ||
328 | dev_err(dev, "(port_idx %d) Clear feat %d/%d UNIMPLEMENTED\n", | 306 | dev_err(dev, "(port_idx %d) Clear feat %d/%d UNIMPLEMENTED\n", |
329 | port_idx, feature, selector); | 307 | port_idx, feature, selector); |
330 | /* dump_stack(); */ | ||
331 | result = -ENOSYS; | 308 | result = -ENOSYS; |
332 | break; | 309 | break; |
333 | default: | 310 | default: |
@@ -337,9 +314,7 @@ static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, | |||
337 | break; | 314 | break; |
338 | } | 315 | } |
339 | mutex_unlock(&wusbhc->mutex); | 316 | mutex_unlock(&wusbhc->mutex); |
340 | error: | 317 | |
341 | d_fnend(4, dev, "(wusbhc %p feat 0x%04x selector %d port_idx %d) = " | ||
342 | "%d\n", wusbhc, feature, selector, port_idx, result); | ||
343 | return result; | 318 | return result; |
344 | } | 319 | } |
345 | 320 | ||
@@ -351,22 +326,17 @@ error: | |||
351 | static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, | 326 | static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, |
352 | u32 *_buf, u16 wLength) | 327 | u32 *_buf, u16 wLength) |
353 | { | 328 | { |
354 | int result = -EINVAL; | ||
355 | u16 *buf = (u16 *) _buf; | 329 | u16 *buf = (u16 *) _buf; |
356 | 330 | ||
357 | d_fnstart(1, wusbhc->dev, "(wusbhc %p port_idx %u wLength %u)\n", | ||
358 | wusbhc, port_idx, wLength); | ||
359 | if (port_idx > wusbhc->ports_max) | 331 | if (port_idx > wusbhc->ports_max) |
360 | goto error; | 332 | return -EINVAL; |
333 | |||
361 | mutex_lock(&wusbhc->mutex); | 334 | mutex_lock(&wusbhc->mutex); |
362 | buf[0] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->status); | 335 | buf[0] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->status); |
363 | buf[1] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->change); | 336 | buf[1] = cpu_to_le16(wusb_port_by_idx(wusbhc, port_idx)->change); |
364 | result = 0; | ||
365 | mutex_unlock(&wusbhc->mutex); | 337 | mutex_unlock(&wusbhc->mutex); |
366 | error: | 338 | |
367 | d_fnend(1, wusbhc->dev, "(wusbhc %p) = %d, buffer:\n", wusbhc, result); | 339 | return 0; |
368 | d_dump(1, wusbhc->dev, _buf, wLength); | ||
369 | return result; | ||
370 | } | 340 | } |
371 | 341 | ||
372 | /* | 342 | /* |
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index a101cad6a8d4..f4aa28eca70d 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c | |||
@@ -27,19 +27,6 @@ | |||
27 | #include <linux/random.h> | 27 | #include <linux/random.h> |
28 | #include "wusbhc.h" | 28 | #include "wusbhc.h" |
29 | 29 | ||
30 | /* | ||
31 | * DEBUG & SECURITY WARNING!!!! | ||
32 | * | ||
33 | * If you enable this past 1, the debug code will weaken the | ||
34 | * cryptographic safety of the system (on purpose, for debugging). | ||
35 | * | ||
36 | * Weaken means: | ||
37 | * we print secret keys and intermediate values all the way, | ||
38 | */ | ||
39 | #undef D_LOCAL | ||
40 | #define D_LOCAL 2 | ||
41 | #include <linux/uwb/debug.h> | ||
42 | |||
43 | static void wusbhc_set_gtk_callback(struct urb *urb); | 30 | static void wusbhc_set_gtk_callback(struct urb *urb); |
44 | static void wusbhc_gtk_rekey_done_work(struct work_struct *work); | 31 | static void wusbhc_gtk_rekey_done_work(struct work_struct *work); |
45 | 32 | ||
@@ -219,7 +206,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
219 | const void *itr, *top; | 206 | const void *itr, *top; |
220 | char buf[64]; | 207 | char buf[64]; |
221 | 208 | ||
222 | d_fnstart(3, dev, "(usb_dev %p, wusb_dev %p)\n", usb_dev, wusb_dev); | ||
223 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, | 209 | result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, |
224 | 0, &secd, sizeof(secd)); | 210 | 0, &secd, sizeof(secd)); |
225 | if (result < sizeof(secd)) { | 211 | if (result < sizeof(secd)) { |
@@ -228,8 +214,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
228 | goto error_secd; | 214 | goto error_secd; |
229 | } | 215 | } |
230 | secd_size = le16_to_cpu(secd.wTotalLength); | 216 | secd_size = le16_to_cpu(secd.wTotalLength); |
231 | d_printf(5, dev, "got %d bytes of sec descriptor, total is %d\n", | ||
232 | result, secd_size); | ||
233 | secd_buf = kmalloc(secd_size, GFP_KERNEL); | 217 | secd_buf = kmalloc(secd_size, GFP_KERNEL); |
234 | if (secd_buf == NULL) { | 218 | if (secd_buf == NULL) { |
235 | dev_err(dev, "Can't allocate space for security descriptors\n"); | 219 | dev_err(dev, "Can't allocate space for security descriptors\n"); |
@@ -242,7 +226,6 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
242 | "not enough data: %d\n", result); | 226 | "not enough data: %d\n", result); |
243 | goto error_secd_all; | 227 | goto error_secd_all; |
244 | } | 228 | } |
245 | d_printf(5, dev, "got %d bytes of sec descriptors\n", result); | ||
246 | bytes = 0; | 229 | bytes = 0; |
247 | itr = secd_buf + sizeof(secd); | 230 | itr = secd_buf + sizeof(secd); |
248 | top = secd_buf + result; | 231 | top = secd_buf + result; |
@@ -279,14 +262,12 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, | |||
279 | goto error_no_ccm1; | 262 | goto error_no_ccm1; |
280 | } | 263 | } |
281 | wusb_dev->ccm1_etd = *ccm1_etd; | 264 | wusb_dev->ccm1_etd = *ccm1_etd; |
282 | dev_info(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", | 265 | dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", |
283 | buf, wusb_et_name(ccm1_etd->bEncryptionType), | 266 | buf, wusb_et_name(ccm1_etd->bEncryptionType), |
284 | ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); | 267 | ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); |
285 | result = 0; | 268 | result = 0; |
286 | kfree(secd_buf); | 269 | kfree(secd_buf); |
287 | out: | 270 | out: |
288 | d_fnend(3, dev, "(usb_dev %p, wusb_dev %p) = %d\n", | ||
289 | usb_dev, wusb_dev, result); | ||
290 | return result; | 271 | return result; |
291 | 272 | ||
292 | 273 | ||
@@ -303,32 +284,6 @@ void wusb_dev_sec_rm(struct wusb_dev *wusb_dev) | |||
303 | /* Nothing so far */ | 284 | /* Nothing so far */ |
304 | } | 285 | } |
305 | 286 | ||
306 | static void hs_printk(unsigned level, struct device *dev, | ||
307 | struct usb_handshake *hs) | ||
308 | { | ||
309 | d_printf(level, dev, | ||
310 | " bMessageNumber: %u\n" | ||
311 | " bStatus: %u\n" | ||
312 | " tTKID: %02x %02x %02x\n" | ||
313 | " CDID: %02x %02x %02x %02x %02x %02x %02x %02x\n" | ||
314 | " %02x %02x %02x %02x %02x %02x %02x %02x\n" | ||
315 | " nonce: %02x %02x %02x %02x %02x %02x %02x %02x\n" | ||
316 | " %02x %02x %02x %02x %02x %02x %02x %02x\n" | ||
317 | " MIC: %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
318 | hs->bMessageNumber, hs->bStatus, | ||
319 | hs->tTKID[2], hs->tTKID[1], hs->tTKID[0], | ||
320 | hs->CDID[0], hs->CDID[1], hs->CDID[2], hs->CDID[3], | ||
321 | hs->CDID[4], hs->CDID[5], hs->CDID[6], hs->CDID[7], | ||
322 | hs->CDID[8], hs->CDID[9], hs->CDID[10], hs->CDID[11], | ||
323 | hs->CDID[12], hs->CDID[13], hs->CDID[14], hs->CDID[15], | ||
324 | hs->nonce[0], hs->nonce[1], hs->nonce[2], hs->nonce[3], | ||
325 | hs->nonce[4], hs->nonce[5], hs->nonce[6], hs->nonce[7], | ||
326 | hs->nonce[8], hs->nonce[9], hs->nonce[10], hs->nonce[11], | ||
327 | hs->nonce[12], hs->nonce[13], hs->nonce[14], hs->nonce[15], | ||
328 | hs->MIC[0], hs->MIC[1], hs->MIC[2], hs->MIC[3], | ||
329 | hs->MIC[4], hs->MIC[5], hs->MIC[6], hs->MIC[7]); | ||
330 | } | ||
331 | |||
332 | /** | 287 | /** |
333 | * Update the address of an unauthenticated WUSB device | 288 | * Update the address of an unauthenticated WUSB device |
334 | * | 289 | * |
@@ -338,8 +293,7 @@ static void hs_printk(unsigned level, struct device *dev, | |||
338 | * Before the device's address (as known by it) was usb_dev->devnum | | 293 | * Before the device's address (as known by it) was usb_dev->devnum | |
339 | * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum. | 294 | * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum. |
340 | */ | 295 | */ |
341 | static int wusb_dev_update_address(struct wusbhc *wusbhc, | 296 | int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) |
342 | struct wusb_dev *wusb_dev) | ||
343 | { | 297 | { |
344 | int result = -ENOMEM; | 298 | int result = -ENOMEM; |
345 | struct usb_device *usb_dev = wusb_dev->usb_dev; | 299 | struct usb_device *usb_dev = wusb_dev->usb_dev; |
@@ -422,9 +376,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
422 | get_random_bytes(&hs[0].nonce, sizeof(hs[0].nonce)); | 376 | get_random_bytes(&hs[0].nonce, sizeof(hs[0].nonce)); |
423 | memset(hs[0].MIC, 0, sizeof(hs[0].MIC)); /* Per WUSB1.0[T7-22] */ | 377 | memset(hs[0].MIC, 0, sizeof(hs[0].MIC)); /* Per WUSB1.0[T7-22] */ |
424 | 378 | ||
425 | d_printf(1, dev, "I: sending hs1:\n"); | ||
426 | hs_printk(2, dev, &hs[0]); | ||
427 | |||
428 | result = usb_control_msg( | 379 | result = usb_control_msg( |
429 | usb_dev, usb_sndctrlpipe(usb_dev, 0), | 380 | usb_dev, usb_sndctrlpipe(usb_dev, 0), |
430 | USB_REQ_SET_HANDSHAKE, | 381 | USB_REQ_SET_HANDSHAKE, |
@@ -445,8 +396,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
445 | dev_err(dev, "Handshake2: request failed: %d\n", result); | 396 | dev_err(dev, "Handshake2: request failed: %d\n", result); |
446 | goto error_hs2; | 397 | goto error_hs2; |
447 | } | 398 | } |
448 | d_printf(1, dev, "got HS2:\n"); | ||
449 | hs_printk(2, dev, &hs[1]); | ||
450 | 399 | ||
451 | result = -EINVAL; | 400 | result = -EINVAL; |
452 | if (hs[1].bMessageNumber != 2) { | 401 | if (hs[1].bMessageNumber != 2) { |
@@ -487,10 +436,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
487 | result); | 436 | result); |
488 | goto error_hs2; | 437 | goto error_hs2; |
489 | } | 438 | } |
490 | d_printf(2, dev, "KCK:\n"); | ||
491 | d_dump(2, dev, keydvt_out.kck, sizeof(keydvt_out.kck)); | ||
492 | d_printf(2, dev, "PTK:\n"); | ||
493 | d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk)); | ||
494 | 439 | ||
495 | /* Compute MIC and verify it */ | 440 | /* Compute MIC and verify it */ |
496 | result = wusb_oob_mic(mic, keydvt_out.kck, &ccm_n, &hs[1]); | 441 | result = wusb_oob_mic(mic, keydvt_out.kck, &ccm_n, &hs[1]); |
@@ -500,8 +445,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
500 | goto error_hs2; | 445 | goto error_hs2; |
501 | } | 446 | } |
502 | 447 | ||
503 | d_printf(2, dev, "MIC:\n"); | ||
504 | d_dump(2, dev, mic, sizeof(mic)); | ||
505 | if (memcmp(hs[1].MIC, mic, sizeof(hs[1].MIC))) { | 448 | if (memcmp(hs[1].MIC, mic, sizeof(hs[1].MIC))) { |
506 | dev_err(dev, "Handshake2 failed: MIC mismatch\n"); | 449 | dev_err(dev, "Handshake2 failed: MIC mismatch\n"); |
507 | goto error_hs2; | 450 | goto error_hs2; |
@@ -521,9 +464,6 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
521 | goto error_hs2; | 464 | goto error_hs2; |
522 | } | 465 | } |
523 | 466 | ||
524 | d_printf(1, dev, "I: sending hs3:\n"); | ||
525 | hs_printk(2, dev, &hs[2]); | ||
526 | |||
527 | result = usb_control_msg( | 467 | result = usb_control_msg( |
528 | usb_dev, usb_sndctrlpipe(usb_dev, 0), | 468 | usb_dev, usb_sndctrlpipe(usb_dev, 0), |
529 | USB_REQ_SET_HANDSHAKE, | 469 | USB_REQ_SET_HANDSHAKE, |
@@ -534,14 +474,11 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
534 | goto error_hs3; | 474 | goto error_hs3; |
535 | } | 475 | } |
536 | 476 | ||
537 | d_printf(1, dev, "I: turning on encryption on host for device\n"); | ||
538 | d_dump(2, dev, keydvt_out.ptk, sizeof(keydvt_out.ptk)); | ||
539 | result = wusbhc->set_ptk(wusbhc, wusb_dev->port_idx, tkid, | 477 | result = wusbhc->set_ptk(wusbhc, wusb_dev->port_idx, tkid, |
540 | keydvt_out.ptk, sizeof(keydvt_out.ptk)); | 478 | keydvt_out.ptk, sizeof(keydvt_out.ptk)); |
541 | if (result < 0) | 479 | if (result < 0) |
542 | goto error_wusbhc_set_ptk; | 480 | goto error_wusbhc_set_ptk; |
543 | 481 | ||
544 | d_printf(1, dev, "I: setting a GTK\n"); | ||
545 | result = wusb_dev_set_gtk(wusbhc, wusb_dev); | 482 | result = wusb_dev_set_gtk(wusbhc, wusb_dev); |
546 | if (result < 0) { | 483 | if (result < 0) { |
547 | dev_err(dev, "Set GTK for device: request failed: %d\n", | 484 | dev_err(dev, "Set GTK for device: request failed: %d\n", |
@@ -551,13 +488,12 @@ int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev, | |||
551 | 488 | ||
552 | /* Update the device's address from unauth to auth */ | 489 | /* Update the device's address from unauth to auth */ |
553 | if (usb_dev->authenticated == 0) { | 490 | if (usb_dev->authenticated == 0) { |
554 | d_printf(1, dev, "I: updating addres to auth from non-auth\n"); | ||
555 | result = wusb_dev_update_address(wusbhc, wusb_dev); | 491 | result = wusb_dev_update_address(wusbhc, wusb_dev); |
556 | if (result < 0) | 492 | if (result < 0) |
557 | goto error_dev_update_address; | 493 | goto error_dev_update_address; |
558 | } | 494 | } |
559 | result = 0; | 495 | result = 0; |
560 | d_printf(1, dev, "I: 4way handshke done, device authenticated\n"); | 496 | dev_info(dev, "device authenticated\n"); |
561 | 497 | ||
562 | error_dev_update_address: | 498 | error_dev_update_address: |
563 | error_wusbhc_set_gtk: | 499 | error_wusbhc_set_gtk: |
@@ -570,10 +506,8 @@ error_hs1: | |||
570 | memset(&keydvt_in, 0, sizeof(keydvt_in)); | 506 | memset(&keydvt_in, 0, sizeof(keydvt_in)); |
571 | memset(&ccm_n, 0, sizeof(ccm_n)); | 507 | memset(&ccm_n, 0, sizeof(ccm_n)); |
572 | memset(mic, 0, sizeof(mic)); | 508 | memset(mic, 0, sizeof(mic)); |
573 | if (result < 0) { | 509 | if (result < 0) |
574 | /* error path */ | ||
575 | wusb_dev_set_encryption(usb_dev, 0); | 510 | wusb_dev_set_encryption(usb_dev, 0); |
576 | } | ||
577 | error_dev_set_encryption: | 511 | error_dev_set_encryption: |
578 | kfree(hs); | 512 | kfree(hs); |
579 | error_kzalloc: | 513 | error_kzalloc: |
diff --git a/drivers/usb/wusbcore/wa-nep.c b/drivers/usb/wusbcore/wa-nep.c index 3f542990c73f..17d2626038be 100644 --- a/drivers/usb/wusbcore/wa-nep.c +++ b/drivers/usb/wusbcore/wa-nep.c | |||
@@ -51,7 +51,7 @@ | |||
51 | */ | 51 | */ |
52 | #include <linux/workqueue.h> | 52 | #include <linux/workqueue.h> |
53 | #include <linux/ctype.h> | 53 | #include <linux/ctype.h> |
54 | #include <linux/uwb/debug.h> | 54 | |
55 | #include "wa-hc.h" | 55 | #include "wa-hc.h" |
56 | #include "wusbhc.h" | 56 | #include "wusbhc.h" |
57 | 57 | ||
@@ -139,13 +139,10 @@ static void wa_notif_dispatch(struct work_struct *ws) | |||
139 | /* FIXME: unimplemented WA NOTIFs */ | 139 | /* FIXME: unimplemented WA NOTIFs */ |
140 | /* fallthru */ | 140 | /* fallthru */ |
141 | default: | 141 | default: |
142 | if (printk_ratelimit()) { | 142 | dev_err(dev, "HWA: unknown notification 0x%x, " |
143 | dev_err(dev, "HWA: unknown notification 0x%x, " | 143 | "%zu bytes; discarding\n", |
144 | "%zu bytes; discarding\n", | 144 | notif_hdr->bNotifyType, |
145 | notif_hdr->bNotifyType, | 145 | (size_t)notif_hdr->bLength); |
146 | (size_t)notif_hdr->bLength); | ||
147 | dump_bytes(dev, notif_hdr, 16); | ||
148 | } | ||
149 | break; | 146 | break; |
150 | } | 147 | } |
151 | } | 148 | } |
@@ -160,12 +157,9 @@ out: | |||
160 | * discard the data, as this should not happen. | 157 | * discard the data, as this should not happen. |
161 | */ | 158 | */ |
162 | exhausted_buffer: | 159 | exhausted_buffer: |
163 | if (!printk_ratelimit()) | ||
164 | goto out; | ||
165 | dev_warn(dev, "HWA: device sent short notification, " | 160 | dev_warn(dev, "HWA: device sent short notification, " |
166 | "%d bytes missing; discarding %d bytes.\n", | 161 | "%d bytes missing; discarding %d bytes.\n", |
167 | missing, (int)size); | 162 | missing, (int)size); |
168 | dump_bytes(dev, itr, size); | ||
169 | goto out; | 163 | goto out; |
170 | } | 164 | } |
171 | 165 | ||
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index f18e4aae66e9..7369655f69cd 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c | |||
@@ -60,13 +60,10 @@ | |||
60 | #include <linux/init.h> | 60 | #include <linux/init.h> |
61 | #include <asm/atomic.h> | 61 | #include <asm/atomic.h> |
62 | #include <linux/bitmap.h> | 62 | #include <linux/bitmap.h> |
63 | |||
63 | #include "wusbhc.h" | 64 | #include "wusbhc.h" |
64 | #include "wa-hc.h" | 65 | #include "wa-hc.h" |
65 | 66 | ||
66 | #define D_LOCAL 0 | ||
67 | #include <linux/uwb/debug.h> | ||
68 | |||
69 | |||
70 | static int __rpipe_get_descr(struct wahc *wa, | 67 | static int __rpipe_get_descr(struct wahc *wa, |
71 | struct usb_rpipe_descriptor *descr, u16 index) | 68 | struct usb_rpipe_descriptor *descr, u16 index) |
72 | { | 69 | { |
@@ -76,7 +73,6 @@ static int __rpipe_get_descr(struct wahc *wa, | |||
76 | /* Get the RPIPE descriptor -- we cannot use the usb_get_descriptor() | 73 | /* Get the RPIPE descriptor -- we cannot use the usb_get_descriptor() |
77 | * function because the arguments are different. | 74 | * function because the arguments are different. |
78 | */ | 75 | */ |
79 | d_printf(1, dev, "rpipe %u: get descr\n", index); | ||
80 | result = usb_control_msg( | 76 | result = usb_control_msg( |
81 | wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), | 77 | wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), |
82 | USB_REQ_GET_DESCRIPTOR, | 78 | USB_REQ_GET_DESCRIPTOR, |
@@ -115,7 +111,6 @@ static int __rpipe_set_descr(struct wahc *wa, | |||
115 | /* we cannot use the usb_get_descriptor() function because the | 111 | /* we cannot use the usb_get_descriptor() function because the |
116 | * arguments are different. | 112 | * arguments are different. |
117 | */ | 113 | */ |
118 | d_printf(1, dev, "rpipe %u: set descr\n", index); | ||
119 | result = usb_control_msg( | 114 | result = usb_control_msg( |
120 | wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), | 115 | wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), |
121 | USB_REQ_SET_DESCRIPTOR, | 116 | USB_REQ_SET_DESCRIPTOR, |
@@ -174,13 +169,12 @@ void rpipe_destroy(struct kref *_rpipe) | |||
174 | { | 169 | { |
175 | struct wa_rpipe *rpipe = container_of(_rpipe, struct wa_rpipe, refcnt); | 170 | struct wa_rpipe *rpipe = container_of(_rpipe, struct wa_rpipe, refcnt); |
176 | u8 index = le16_to_cpu(rpipe->descr.wRPipeIndex); | 171 | u8 index = le16_to_cpu(rpipe->descr.wRPipeIndex); |
177 | d_fnstart(1, NULL, "(rpipe %p %u)\n", rpipe, index); | 172 | |
178 | if (rpipe->ep) | 173 | if (rpipe->ep) |
179 | rpipe->ep->hcpriv = NULL; | 174 | rpipe->ep->hcpriv = NULL; |
180 | rpipe_put_idx(rpipe->wa, index); | 175 | rpipe_put_idx(rpipe->wa, index); |
181 | wa_put(rpipe->wa); | 176 | wa_put(rpipe->wa); |
182 | kfree(rpipe); | 177 | kfree(rpipe); |
183 | d_fnend(1, NULL, "(rpipe %p %u)\n", rpipe, index); | ||
184 | } | 178 | } |
185 | EXPORT_SYMBOL_GPL(rpipe_destroy); | 179 | EXPORT_SYMBOL_GPL(rpipe_destroy); |
186 | 180 | ||
@@ -202,7 +196,6 @@ static int rpipe_get_idle(struct wa_rpipe **prpipe, struct wahc *wa, u8 crs, | |||
202 | struct wa_rpipe *rpipe; | 196 | struct wa_rpipe *rpipe; |
203 | struct device *dev = &wa->usb_iface->dev; | 197 | struct device *dev = &wa->usb_iface->dev; |
204 | 198 | ||
205 | d_fnstart(3, dev, "(wa %p crs 0x%02x)\n", wa, crs); | ||
206 | rpipe = kzalloc(sizeof(*rpipe), gfp); | 199 | rpipe = kzalloc(sizeof(*rpipe), gfp); |
207 | if (rpipe == NULL) | 200 | if (rpipe == NULL) |
208 | return -ENOMEM; | 201 | return -ENOMEM; |
@@ -223,14 +216,12 @@ static int rpipe_get_idle(struct wa_rpipe **prpipe, struct wahc *wa, u8 crs, | |||
223 | } | 216 | } |
224 | *prpipe = NULL; | 217 | *prpipe = NULL; |
225 | kfree(rpipe); | 218 | kfree(rpipe); |
226 | d_fnend(3, dev, "(wa %p crs 0x%02x) = -ENXIO\n", wa, crs); | ||
227 | return -ENXIO; | 219 | return -ENXIO; |
228 | 220 | ||
229 | found: | 221 | found: |
230 | set_bit(rpipe_idx, wa->rpipe_bm); | 222 | set_bit(rpipe_idx, wa->rpipe_bm); |
231 | rpipe->wa = wa_get(wa); | 223 | rpipe->wa = wa_get(wa); |
232 | *prpipe = rpipe; | 224 | *prpipe = rpipe; |
233 | d_fnstart(3, dev, "(wa %p crs 0x%02x) = 0\n", wa, crs); | ||
234 | return 0; | 225 | return 0; |
235 | } | 226 | } |
236 | 227 | ||
@@ -239,7 +230,6 @@ static int __rpipe_reset(struct wahc *wa, unsigned index) | |||
239 | int result; | 230 | int result; |
240 | struct device *dev = &wa->usb_iface->dev; | 231 | struct device *dev = &wa->usb_iface->dev; |
241 | 232 | ||
242 | d_printf(1, dev, "rpipe %u: reset\n", index); | ||
243 | result = usb_control_msg( | 233 | result = usb_control_msg( |
244 | wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), | 234 | wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), |
245 | USB_REQ_RPIPE_RESET, | 235 | USB_REQ_RPIPE_RESET, |
@@ -276,7 +266,6 @@ static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find( | |||
276 | struct usb_descriptor_header *hdr; | 266 | struct usb_descriptor_header *hdr; |
277 | struct usb_wireless_ep_comp_descriptor *epcd; | 267 | struct usb_wireless_ep_comp_descriptor *epcd; |
278 | 268 | ||
279 | d_fnstart(3, dev, "(ep %p)\n", ep); | ||
280 | if (ep->desc.bEndpointAddress == 0) { | 269 | if (ep->desc.bEndpointAddress == 0) { |
281 | epcd = &epc0; | 270 | epcd = &epc0; |
282 | goto out; | 271 | goto out; |
@@ -310,7 +299,6 @@ static struct usb_wireless_ep_comp_descriptor *rpipe_epc_find( | |||
310 | itr_size -= hdr->bDescriptorType; | 299 | itr_size -= hdr->bDescriptorType; |
311 | } | 300 | } |
312 | out: | 301 | out: |
313 | d_fnend(3, dev, "(ep %p) = %p\n", ep, epcd); | ||
314 | return epcd; | 302 | return epcd; |
315 | } | 303 | } |
316 | 304 | ||
@@ -329,8 +317,6 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
329 | struct usb_wireless_ep_comp_descriptor *epcd; | 317 | struct usb_wireless_ep_comp_descriptor *epcd; |
330 | u8 unauth; | 318 | u8 unauth; |
331 | 319 | ||
332 | d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n", | ||
333 | rpipe, wa, ep, urb); | ||
334 | epcd = rpipe_epc_find(dev, ep); | 320 | epcd = rpipe_epc_find(dev, ep); |
335 | if (epcd == NULL) { | 321 | if (epcd == NULL) { |
336 | dev_err(dev, "ep 0x%02x: can't find companion descriptor\n", | 322 | dev_err(dev, "ep 0x%02x: can't find companion descriptor\n", |
@@ -350,10 +336,12 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
350 | /* FIXME: use maximum speed as supported or recommended by device */ | 336 | /* FIXME: use maximum speed as supported or recommended by device */ |
351 | rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? | 337 | rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? |
352 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200; | 338 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200; |
353 | d_printf(2, dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n", | 339 | |
354 | urb->dev->devnum, urb->dev->devnum | unauth, | 340 | dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n", |
355 | le16_to_cpu(rpipe->descr.wRPipeIndex), | 341 | urb->dev->devnum, urb->dev->devnum | unauth, |
356 | usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); | 342 | le16_to_cpu(rpipe->descr.wRPipeIndex), |
343 | usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); | ||
344 | |||
357 | /* see security.c:wusb_update_address() */ | 345 | /* see security.c:wusb_update_address() */ |
358 | if (unlikely(urb->dev->devnum == 0x80)) | 346 | if (unlikely(urb->dev->devnum == 0x80)) |
359 | rpipe->descr.bDeviceAddress = 0; | 347 | rpipe->descr.bDeviceAddress = 0; |
@@ -384,8 +372,6 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
384 | } | 372 | } |
385 | result = 0; | 373 | result = 0; |
386 | error: | 374 | error: |
387 | d_fnend(3, dev, "(rpipe %p wa %p ep %p urb %p) = %d\n", | ||
388 | rpipe, wa, ep, urb, result); | ||
389 | return result; | 375 | return result; |
390 | } | 376 | } |
391 | 377 | ||
@@ -405,8 +391,6 @@ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, | |||
405 | u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; | 391 | u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; |
406 | u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); | 392 | u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); |
407 | 393 | ||
408 | d_fnstart(3, dev, "(rpipe %p wa %p ep %p, urb %p)\n", | ||
409 | rpipe, wa, ep, urb); | ||
410 | #define AIM_CHECK(rdf, val, text) \ | 394 | #define AIM_CHECK(rdf, val, text) \ |
411 | do { \ | 395 | do { \ |
412 | if (rpipe->descr.rdf != (val)) { \ | 396 | if (rpipe->descr.rdf != (val)) { \ |
@@ -451,8 +435,6 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep, | |||
451 | struct wa_rpipe *rpipe; | 435 | struct wa_rpipe *rpipe; |
452 | u8 eptype; | 436 | u8 eptype; |
453 | 437 | ||
454 | d_fnstart(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb, | ||
455 | gfp); | ||
456 | mutex_lock(&wa->rpipe_mutex); | 438 | mutex_lock(&wa->rpipe_mutex); |
457 | rpipe = ep->hcpriv; | 439 | rpipe = ep->hcpriv; |
458 | if (rpipe != NULL) { | 440 | if (rpipe != NULL) { |
@@ -462,9 +444,9 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep, | |||
462 | goto error; | 444 | goto error; |
463 | } | 445 | } |
464 | __rpipe_get(rpipe); | 446 | __rpipe_get(rpipe); |
465 | d_printf(2, dev, "ep 0x%02x: reusing rpipe %u\n", | 447 | dev_dbg(dev, "ep 0x%02x: reusing rpipe %u\n", |
466 | ep->desc.bEndpointAddress, | 448 | ep->desc.bEndpointAddress, |
467 | le16_to_cpu(rpipe->descr.wRPipeIndex)); | 449 | le16_to_cpu(rpipe->descr.wRPipeIndex)); |
468 | } else { | 450 | } else { |
469 | /* hmm, assign idle rpipe, aim it */ | 451 | /* hmm, assign idle rpipe, aim it */ |
470 | result = -ENOBUFS; | 452 | result = -ENOBUFS; |
@@ -480,14 +462,12 @@ int rpipe_get_by_ep(struct wahc *wa, struct usb_host_endpoint *ep, | |||
480 | ep->hcpriv = rpipe; | 462 | ep->hcpriv = rpipe; |
481 | rpipe->ep = ep; | 463 | rpipe->ep = ep; |
482 | __rpipe_get(rpipe); /* for caching into ep->hcpriv */ | 464 | __rpipe_get(rpipe); /* for caching into ep->hcpriv */ |
483 | d_printf(2, dev, "ep 0x%02x: using rpipe %u\n", | 465 | dev_dbg(dev, "ep 0x%02x: using rpipe %u\n", |
484 | ep->desc.bEndpointAddress, | 466 | ep->desc.bEndpointAddress, |
485 | le16_to_cpu(rpipe->descr.wRPipeIndex)); | 467 | le16_to_cpu(rpipe->descr.wRPipeIndex)); |
486 | } | 468 | } |
487 | d_dump(4, dev, &rpipe->descr, sizeof(rpipe->descr)); | ||
488 | error: | 469 | error: |
489 | mutex_unlock(&wa->rpipe_mutex); | 470 | mutex_unlock(&wa->rpipe_mutex); |
490 | d_fnend(3, dev, "(wa %p ep %p urb %p gfp 0x%08x)\n", wa, ep, urb, gfp); | ||
491 | return result; | 471 | return result; |
492 | } | 472 | } |
493 | 473 | ||
@@ -507,7 +487,7 @@ int wa_rpipes_create(struct wahc *wa) | |||
507 | void wa_rpipes_destroy(struct wahc *wa) | 487 | void wa_rpipes_destroy(struct wahc *wa) |
508 | { | 488 | { |
509 | struct device *dev = &wa->usb_iface->dev; | 489 | struct device *dev = &wa->usb_iface->dev; |
510 | d_fnstart(3, dev, "(wa %p)\n", wa); | 490 | |
511 | if (!bitmap_empty(wa->rpipe_bm, wa->rpipes)) { | 491 | if (!bitmap_empty(wa->rpipe_bm, wa->rpipes)) { |
512 | char buf[256]; | 492 | char buf[256]; |
513 | WARN_ON(1); | 493 | WARN_ON(1); |
@@ -515,7 +495,6 @@ void wa_rpipes_destroy(struct wahc *wa) | |||
515 | dev_err(dev, "BUG: pipes not released on exit: %s\n", buf); | 495 | dev_err(dev, "BUG: pipes not released on exit: %s\n", buf); |
516 | } | 496 | } |
517 | kfree(wa->rpipe_bm); | 497 | kfree(wa->rpipe_bm); |
518 | d_fnend(3, dev, "(wa %p)\n", wa); | ||
519 | } | 498 | } |
520 | 499 | ||
521 | /* | 500 | /* |
@@ -530,33 +509,20 @@ void wa_rpipes_destroy(struct wahc *wa) | |||
530 | */ | 509 | */ |
531 | void rpipe_ep_disable(struct wahc *wa, struct usb_host_endpoint *ep) | 510 | void rpipe_ep_disable(struct wahc *wa, struct usb_host_endpoint *ep) |
532 | { | 511 | { |
533 | struct device *dev = &wa->usb_iface->dev; | ||
534 | struct wa_rpipe *rpipe; | 512 | struct wa_rpipe *rpipe; |
535 | d_fnstart(2, dev, "(wa %p ep %p)\n", wa, ep); | 513 | |
536 | mutex_lock(&wa->rpipe_mutex); | 514 | mutex_lock(&wa->rpipe_mutex); |
537 | rpipe = ep->hcpriv; | 515 | rpipe = ep->hcpriv; |
538 | if (rpipe != NULL) { | 516 | if (rpipe != NULL) { |
539 | unsigned rc = atomic_read(&rpipe->refcnt.refcount); | ||
540 | int result; | ||
541 | u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex); | 517 | u16 index = le16_to_cpu(rpipe->descr.wRPipeIndex); |
542 | 518 | ||
543 | if (rc != 1) | 519 | usb_control_msg( |
544 | d_printf(1, dev, "(wa %p ep %p) rpipe %p refcnt %u\n", | ||
545 | wa, ep, rpipe, rc); | ||
546 | |||
547 | d_printf(1, dev, "rpipe %u: abort\n", index); | ||
548 | result = usb_control_msg( | ||
549 | wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), | 520 | wa->usb_dev, usb_rcvctrlpipe(wa->usb_dev, 0), |
550 | USB_REQ_RPIPE_ABORT, | 521 | USB_REQ_RPIPE_ABORT, |
551 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, | 522 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_RPIPE, |
552 | 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); | 523 | 0, index, NULL, 0, 1000 /* FIXME: arbitrary */); |
553 | if (result < 0 && result != -ENODEV /* dev is gone */) | ||
554 | d_printf(1, dev, "(wa %p rpipe %u): abort failed: %d\n", | ||
555 | wa, index, result); | ||
556 | rpipe_put(rpipe); | 524 | rpipe_put(rpipe); |
557 | } | 525 | } |
558 | mutex_unlock(&wa->rpipe_mutex); | 526 | mutex_unlock(&wa->rpipe_mutex); |
559 | d_fnend(2, dev, "(wa %p ep %p)\n", wa, ep); | ||
560 | return; | ||
561 | } | 527 | } |
562 | EXPORT_SYMBOL_GPL(rpipe_ep_disable); | 528 | EXPORT_SYMBOL_GPL(rpipe_ep_disable); |
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index c038635d1c64..238a96aee3a1 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c | |||
@@ -82,13 +82,10 @@ | |||
82 | #include <linux/init.h> | 82 | #include <linux/init.h> |
83 | #include <linux/spinlock.h> | 83 | #include <linux/spinlock.h> |
84 | #include <linux/hash.h> | 84 | #include <linux/hash.h> |
85 | |||
85 | #include "wa-hc.h" | 86 | #include "wa-hc.h" |
86 | #include "wusbhc.h" | 87 | #include "wusbhc.h" |
87 | 88 | ||
88 | #undef D_LOCAL | ||
89 | #define D_LOCAL 0 /* 0 disabled, > 0 different levels... */ | ||
90 | #include <linux/uwb/debug.h> | ||
91 | |||
92 | enum { | 89 | enum { |
93 | WA_SEGS_MAX = 255, | 90 | WA_SEGS_MAX = 255, |
94 | }; | 91 | }; |
@@ -180,7 +177,6 @@ static void wa_xfer_destroy(struct kref *_xfer) | |||
180 | } | 177 | } |
181 | } | 178 | } |
182 | kfree(xfer); | 179 | kfree(xfer); |
183 | d_printf(2, NULL, "xfer %p destroyed\n", xfer); | ||
184 | } | 180 | } |
185 | 181 | ||
186 | static void wa_xfer_get(struct wa_xfer *xfer) | 182 | static void wa_xfer_get(struct wa_xfer *xfer) |
@@ -190,10 +186,7 @@ static void wa_xfer_get(struct wa_xfer *xfer) | |||
190 | 186 | ||
191 | static void wa_xfer_put(struct wa_xfer *xfer) | 187 | static void wa_xfer_put(struct wa_xfer *xfer) |
192 | { | 188 | { |
193 | d_fnstart(3, NULL, "(xfer %p) -- ref count bef put %d\n", | ||
194 | xfer, atomic_read(&xfer->refcnt.refcount)); | ||
195 | kref_put(&xfer->refcnt, wa_xfer_destroy); | 189 | kref_put(&xfer->refcnt, wa_xfer_destroy); |
196 | d_fnend(3, NULL, "(xfer %p) = void\n", xfer); | ||
197 | } | 190 | } |
198 | 191 | ||
199 | /* | 192 | /* |
@@ -209,7 +202,7 @@ static void wa_xfer_put(struct wa_xfer *xfer) | |||
209 | static void wa_xfer_giveback(struct wa_xfer *xfer) | 202 | static void wa_xfer_giveback(struct wa_xfer *xfer) |
210 | { | 203 | { |
211 | unsigned long flags; | 204 | unsigned long flags; |
212 | d_fnstart(3, NULL, "(xfer %p)\n", xfer); | 205 | |
213 | spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags); | 206 | spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags); |
214 | list_del_init(&xfer->list_node); | 207 | list_del_init(&xfer->list_node); |
215 | spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags); | 208 | spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags); |
@@ -217,7 +210,6 @@ static void wa_xfer_giveback(struct wa_xfer *xfer) | |||
217 | wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result); | 210 | wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result); |
218 | wa_put(xfer->wa); | 211 | wa_put(xfer->wa); |
219 | wa_xfer_put(xfer); | 212 | wa_xfer_put(xfer); |
220 | d_fnend(3, NULL, "(xfer %p) = void\n", xfer); | ||
221 | } | 213 | } |
222 | 214 | ||
223 | /* | 215 | /* |
@@ -227,13 +219,10 @@ static void wa_xfer_giveback(struct wa_xfer *xfer) | |||
227 | */ | 219 | */ |
228 | static void wa_xfer_completion(struct wa_xfer *xfer) | 220 | static void wa_xfer_completion(struct wa_xfer *xfer) |
229 | { | 221 | { |
230 | d_fnstart(3, NULL, "(xfer %p)\n", xfer); | ||
231 | if (xfer->wusb_dev) | 222 | if (xfer->wusb_dev) |
232 | wusb_dev_put(xfer->wusb_dev); | 223 | wusb_dev_put(xfer->wusb_dev); |
233 | rpipe_put(xfer->ep->hcpriv); | 224 | rpipe_put(xfer->ep->hcpriv); |
234 | wa_xfer_giveback(xfer); | 225 | wa_xfer_giveback(xfer); |
235 | d_fnend(3, NULL, "(xfer %p) = void\n", xfer); | ||
236 | return; | ||
237 | } | 226 | } |
238 | 227 | ||
239 | /* | 228 | /* |
@@ -243,12 +232,12 @@ static void wa_xfer_completion(struct wa_xfer *xfer) | |||
243 | */ | 232 | */ |
244 | static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) | 233 | static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) |
245 | { | 234 | { |
235 | struct device *dev = &xfer->wa->usb_iface->dev; | ||
246 | unsigned result, cnt; | 236 | unsigned result, cnt; |
247 | struct wa_seg *seg; | 237 | struct wa_seg *seg; |
248 | struct urb *urb = xfer->urb; | 238 | struct urb *urb = xfer->urb; |
249 | unsigned found_short = 0; | 239 | unsigned found_short = 0; |
250 | 240 | ||
251 | d_fnstart(3, NULL, "(xfer %p)\n", xfer); | ||
252 | result = xfer->segs_done == xfer->segs_submitted; | 241 | result = xfer->segs_done == xfer->segs_submitted; |
253 | if (result == 0) | 242 | if (result == 0) |
254 | goto out; | 243 | goto out; |
@@ -258,10 +247,8 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) | |||
258 | switch (seg->status) { | 247 | switch (seg->status) { |
259 | case WA_SEG_DONE: | 248 | case WA_SEG_DONE: |
260 | if (found_short && seg->result > 0) { | 249 | if (found_short && seg->result > 0) { |
261 | if (printk_ratelimit()) | 250 | dev_dbg(dev, "xfer %p#%u: bad short segments (%zu)\n", |
262 | printk(KERN_ERR "xfer %p#%u: bad short " | 251 | xfer, cnt, seg->result); |
263 | "segments (%zu)\n", xfer, cnt, | ||
264 | seg->result); | ||
265 | urb->status = -EINVAL; | 252 | urb->status = -EINVAL; |
266 | goto out; | 253 | goto out; |
267 | } | 254 | } |
@@ -269,36 +256,30 @@ static unsigned __wa_xfer_is_done(struct wa_xfer *xfer) | |||
269 | if (seg->result < xfer->seg_size | 256 | if (seg->result < xfer->seg_size |
270 | && cnt != xfer->segs-1) | 257 | && cnt != xfer->segs-1) |
271 | found_short = 1; | 258 | found_short = 1; |
272 | d_printf(2, NULL, "xfer %p#%u: DONE short %d " | 259 | dev_dbg(dev, "xfer %p#%u: DONE short %d " |
273 | "result %zu urb->actual_length %d\n", | 260 | "result %zu urb->actual_length %d\n", |
274 | xfer, seg->index, found_short, seg->result, | 261 | xfer, seg->index, found_short, seg->result, |
275 | urb->actual_length); | 262 | urb->actual_length); |
276 | break; | 263 | break; |
277 | case WA_SEG_ERROR: | 264 | case WA_SEG_ERROR: |
278 | xfer->result = seg->result; | 265 | xfer->result = seg->result; |
279 | d_printf(2, NULL, "xfer %p#%u: ERROR result %zu\n", | 266 | dev_dbg(dev, "xfer %p#%u: ERROR result %zu\n", |
280 | xfer, seg->index, seg->result); | 267 | xfer, seg->index, seg->result); |
281 | goto out; | 268 | goto out; |
282 | case WA_SEG_ABORTED: | 269 | case WA_SEG_ABORTED: |
283 | WARN_ON(urb->status != -ECONNRESET | 270 | dev_dbg(dev, "xfer %p#%u ABORTED: result %d\n", |
284 | && urb->status != -ENOENT); | 271 | xfer, seg->index, urb->status); |
285 | d_printf(2, NULL, "xfer %p#%u ABORTED: result %d\n", | ||
286 | xfer, seg->index, urb->status); | ||
287 | xfer->result = urb->status; | 272 | xfer->result = urb->status; |
288 | goto out; | 273 | goto out; |
289 | default: | 274 | default: |
290 | /* if (printk_ratelimit()) */ | 275 | dev_warn(dev, "xfer %p#%u: is_done bad state %d\n", |
291 | printk(KERN_ERR "xfer %p#%u: " | 276 | xfer, cnt, seg->status); |
292 | "is_done bad state %d\n", | ||
293 | xfer, cnt, seg->status); | ||
294 | xfer->result = -EINVAL; | 277 | xfer->result = -EINVAL; |
295 | WARN_ON(1); | ||
296 | goto out; | 278 | goto out; |
297 | } | 279 | } |
298 | } | 280 | } |
299 | xfer->result = 0; | 281 | xfer->result = 0; |
300 | out: | 282 | out: |
301 | d_fnend(3, NULL, "(xfer %p) = void\n", xfer); | ||
302 | return result; | 283 | return result; |
303 | } | 284 | } |
304 | 285 | ||
@@ -424,8 +405,6 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, | |||
424 | struct urb *urb = xfer->urb; | 405 | struct urb *urb = xfer->urb; |
425 | struct wa_rpipe *rpipe = xfer->ep->hcpriv; | 406 | struct wa_rpipe *rpipe = xfer->ep->hcpriv; |
426 | 407 | ||
427 | d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n", | ||
428 | xfer, rpipe, urb); | ||
429 | switch (rpipe->descr.bmAttribute & 0x3) { | 408 | switch (rpipe->descr.bmAttribute & 0x3) { |
430 | case USB_ENDPOINT_XFER_CONTROL: | 409 | case USB_ENDPOINT_XFER_CONTROL: |
431 | *pxfer_type = WA_XFER_TYPE_CTL; | 410 | *pxfer_type = WA_XFER_TYPE_CTL; |
@@ -472,12 +451,10 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, | |||
472 | if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL) | 451 | if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL) |
473 | xfer->segs = 1; | 452 | xfer->segs = 1; |
474 | error: | 453 | error: |
475 | d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n", | ||
476 | xfer, rpipe, urb, (int)result); | ||
477 | return result; | 454 | return result; |
478 | } | 455 | } |
479 | 456 | ||
480 | /** Fill in the common request header and xfer-type specific data. */ | 457 | /* Fill in the common request header and xfer-type specific data. */ |
481 | static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, | 458 | static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, |
482 | struct wa_xfer_hdr *xfer_hdr0, | 459 | struct wa_xfer_hdr *xfer_hdr0, |
483 | enum wa_xfer_type xfer_type, | 460 | enum wa_xfer_type xfer_type, |
@@ -534,14 +511,13 @@ static void wa_seg_dto_cb(struct urb *urb) | |||
534 | unsigned rpipe_ready = 0; | 511 | unsigned rpipe_ready = 0; |
535 | u8 done = 0; | 512 | u8 done = 0; |
536 | 513 | ||
537 | d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); | ||
538 | switch (urb->status) { | 514 | switch (urb->status) { |
539 | case 0: | 515 | case 0: |
540 | spin_lock_irqsave(&xfer->lock, flags); | 516 | spin_lock_irqsave(&xfer->lock, flags); |
541 | wa = xfer->wa; | 517 | wa = xfer->wa; |
542 | dev = &wa->usb_iface->dev; | 518 | dev = &wa->usb_iface->dev; |
543 | d_printf(2, dev, "xfer %p#%u: data out done (%d bytes)\n", | 519 | dev_dbg(dev, "xfer %p#%u: data out done (%d bytes)\n", |
544 | xfer, seg->index, urb->actual_length); | 520 | xfer, seg->index, urb->actual_length); |
545 | if (seg->status < WA_SEG_PENDING) | 521 | if (seg->status < WA_SEG_PENDING) |
546 | seg->status = WA_SEG_PENDING; | 522 | seg->status = WA_SEG_PENDING; |
547 | seg->result = urb->actual_length; | 523 | seg->result = urb->actual_length; |
@@ -555,9 +531,8 @@ static void wa_seg_dto_cb(struct urb *urb) | |||
555 | wa = xfer->wa; | 531 | wa = xfer->wa; |
556 | dev = &wa->usb_iface->dev; | 532 | dev = &wa->usb_iface->dev; |
557 | rpipe = xfer->ep->hcpriv; | 533 | rpipe = xfer->ep->hcpriv; |
558 | if (printk_ratelimit()) | 534 | dev_dbg(dev, "xfer %p#%u: data out error %d\n", |
559 | dev_err(dev, "xfer %p#%u: data out error %d\n", | 535 | xfer, seg->index, urb->status); |
560 | xfer, seg->index, urb->status); | ||
561 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, | 536 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, |
562 | EDC_ERROR_TIMEFRAME)){ | 537 | EDC_ERROR_TIMEFRAME)){ |
563 | dev_err(dev, "DTO: URB max acceptable errors " | 538 | dev_err(dev, "DTO: URB max acceptable errors " |
@@ -578,7 +553,6 @@ static void wa_seg_dto_cb(struct urb *urb) | |||
578 | if (rpipe_ready) | 553 | if (rpipe_ready) |
579 | wa_xfer_delayed_run(rpipe); | 554 | wa_xfer_delayed_run(rpipe); |
580 | } | 555 | } |
581 | d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); | ||
582 | } | 556 | } |
583 | 557 | ||
584 | /* | 558 | /* |
@@ -610,14 +584,12 @@ static void wa_seg_cb(struct urb *urb) | |||
610 | unsigned rpipe_ready; | 584 | unsigned rpipe_ready; |
611 | u8 done = 0; | 585 | u8 done = 0; |
612 | 586 | ||
613 | d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); | ||
614 | switch (urb->status) { | 587 | switch (urb->status) { |
615 | case 0: | 588 | case 0: |
616 | spin_lock_irqsave(&xfer->lock, flags); | 589 | spin_lock_irqsave(&xfer->lock, flags); |
617 | wa = xfer->wa; | 590 | wa = xfer->wa; |
618 | dev = &wa->usb_iface->dev; | 591 | dev = &wa->usb_iface->dev; |
619 | d_printf(2, dev, "xfer %p#%u: request done\n", | 592 | dev_dbg(dev, "xfer %p#%u: request done\n", xfer, seg->index); |
620 | xfer, seg->index); | ||
621 | if (xfer->is_inbound && seg->status < WA_SEG_PENDING) | 593 | if (xfer->is_inbound && seg->status < WA_SEG_PENDING) |
622 | seg->status = WA_SEG_PENDING; | 594 | seg->status = WA_SEG_PENDING; |
623 | spin_unlock_irqrestore(&xfer->lock, flags); | 595 | spin_unlock_irqrestore(&xfer->lock, flags); |
@@ -652,7 +624,6 @@ static void wa_seg_cb(struct urb *urb) | |||
652 | if (rpipe_ready) | 624 | if (rpipe_ready) |
653 | wa_xfer_delayed_run(rpipe); | 625 | wa_xfer_delayed_run(rpipe); |
654 | } | 626 | } |
655 | d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); | ||
656 | } | 627 | } |
657 | 628 | ||
658 | /* | 629 | /* |
@@ -750,9 +721,6 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) | |||
750 | size_t xfer_hdr_size, cnt, transfer_size; | 721 | size_t xfer_hdr_size, cnt, transfer_size; |
751 | struct wa_xfer_hdr *xfer_hdr0, *xfer_hdr; | 722 | struct wa_xfer_hdr *xfer_hdr0, *xfer_hdr; |
752 | 723 | ||
753 | d_fnstart(3, dev, "(xfer %p [rpipe %p] urb %p)\n", | ||
754 | xfer, xfer->ep->hcpriv, urb); | ||
755 | |||
756 | result = __wa_xfer_setup_sizes(xfer, &xfer_type); | 724 | result = __wa_xfer_setup_sizes(xfer, &xfer_type); |
757 | if (result < 0) | 725 | if (result < 0) |
758 | goto error_setup_sizes; | 726 | goto error_setup_sizes; |
@@ -788,8 +756,6 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) | |||
788 | result = 0; | 756 | result = 0; |
789 | error_setup_segs: | 757 | error_setup_segs: |
790 | error_setup_sizes: | 758 | error_setup_sizes: |
791 | d_fnend(3, dev, "(xfer %p [rpipe %p] urb %p) = %d\n", | ||
792 | xfer, xfer->ep->hcpriv, urb, result); | ||
793 | return result; | 759 | return result; |
794 | } | 760 | } |
795 | 761 | ||
@@ -843,9 +809,6 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe) | |||
843 | struct wa_xfer *xfer; | 809 | struct wa_xfer *xfer; |
844 | unsigned long flags; | 810 | unsigned long flags; |
845 | 811 | ||
846 | d_fnstart(1, dev, "(rpipe #%d) %d segments available\n", | ||
847 | le16_to_cpu(rpipe->descr.wRPipeIndex), | ||
848 | atomic_read(&rpipe->segs_available)); | ||
849 | spin_lock_irqsave(&rpipe->seg_lock, flags); | 812 | spin_lock_irqsave(&rpipe->seg_lock, flags); |
850 | while (atomic_read(&rpipe->segs_available) > 0 | 813 | while (atomic_read(&rpipe->segs_available) > 0 |
851 | && !list_empty(&rpipe->seg_list)) { | 814 | && !list_empty(&rpipe->seg_list)) { |
@@ -854,10 +817,8 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe) | |||
854 | list_del(&seg->list_node); | 817 | list_del(&seg->list_node); |
855 | xfer = seg->xfer; | 818 | xfer = seg->xfer; |
856 | result = __wa_seg_submit(rpipe, xfer, seg); | 819 | result = __wa_seg_submit(rpipe, xfer, seg); |
857 | d_printf(1, dev, "xfer %p#%u submitted from delayed " | 820 | dev_dbg(dev, "xfer %p#%u submitted from delayed [%d segments available] %d\n", |
858 | "[%d segments available] %d\n", | 821 | xfer, seg->index, atomic_read(&rpipe->segs_available), result); |
859 | xfer, seg->index, | ||
860 | atomic_read(&rpipe->segs_available), result); | ||
861 | if (unlikely(result < 0)) { | 822 | if (unlikely(result < 0)) { |
862 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); | 823 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); |
863 | spin_lock_irqsave(&xfer->lock, flags); | 824 | spin_lock_irqsave(&xfer->lock, flags); |
@@ -868,10 +829,6 @@ static void wa_xfer_delayed_run(struct wa_rpipe *rpipe) | |||
868 | } | 829 | } |
869 | } | 830 | } |
870 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); | 831 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); |
871 | d_fnend(1, dev, "(rpipe #%d) = void, %d segments available\n", | ||
872 | le16_to_cpu(rpipe->descr.wRPipeIndex), | ||
873 | atomic_read(&rpipe->segs_available)); | ||
874 | |||
875 | } | 832 | } |
876 | 833 | ||
877 | /* | 834 | /* |
@@ -894,9 +851,6 @@ static int __wa_xfer_submit(struct wa_xfer *xfer) | |||
894 | u8 available; | 851 | u8 available; |
895 | u8 empty; | 852 | u8 empty; |
896 | 853 | ||
897 | d_fnstart(3, dev, "(xfer %p [rpipe %p])\n", | ||
898 | xfer, xfer->ep->hcpriv); | ||
899 | |||
900 | spin_lock_irqsave(&wa->xfer_list_lock, flags); | 854 | spin_lock_irqsave(&wa->xfer_list_lock, flags); |
901 | list_add_tail(&xfer->list_node, &wa->xfer_list); | 855 | list_add_tail(&xfer->list_node, &wa->xfer_list); |
902 | spin_unlock_irqrestore(&wa->xfer_list_lock, flags); | 856 | spin_unlock_irqrestore(&wa->xfer_list_lock, flags); |
@@ -908,30 +862,24 @@ static int __wa_xfer_submit(struct wa_xfer *xfer) | |||
908 | available = atomic_read(&rpipe->segs_available); | 862 | available = atomic_read(&rpipe->segs_available); |
909 | empty = list_empty(&rpipe->seg_list); | 863 | empty = list_empty(&rpipe->seg_list); |
910 | seg = xfer->seg[cnt]; | 864 | seg = xfer->seg[cnt]; |
911 | d_printf(2, dev, "xfer %p#%u: available %u empty %u (%s)\n", | 865 | dev_dbg(dev, "xfer %p#%u: available %u empty %u (%s)\n", |
912 | xfer, cnt, available, empty, | 866 | xfer, cnt, available, empty, |
913 | available == 0 || !empty ? "delayed" : "submitted"); | 867 | available == 0 || !empty ? "delayed" : "submitted"); |
914 | if (available == 0 || !empty) { | 868 | if (available == 0 || !empty) { |
915 | d_printf(1, dev, "xfer %p#%u: delayed\n", xfer, cnt); | 869 | dev_dbg(dev, "xfer %p#%u: delayed\n", xfer, cnt); |
916 | seg->status = WA_SEG_DELAYED; | 870 | seg->status = WA_SEG_DELAYED; |
917 | list_add_tail(&seg->list_node, &rpipe->seg_list); | 871 | list_add_tail(&seg->list_node, &rpipe->seg_list); |
918 | } else { | 872 | } else { |
919 | result = __wa_seg_submit(rpipe, xfer, seg); | 873 | result = __wa_seg_submit(rpipe, xfer, seg); |
920 | if (result < 0) | 874 | if (result < 0) { |
875 | __wa_xfer_abort(xfer); | ||
921 | goto error_seg_submit; | 876 | goto error_seg_submit; |
877 | } | ||
922 | } | 878 | } |
923 | xfer->segs_submitted++; | 879 | xfer->segs_submitted++; |
924 | } | 880 | } |
925 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); | ||
926 | d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer, | ||
927 | xfer->ep->hcpriv); | ||
928 | return result; | ||
929 | |||
930 | error_seg_submit: | 881 | error_seg_submit: |
931 | __wa_xfer_abort(xfer); | ||
932 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); | 882 | spin_unlock_irqrestore(&rpipe->seg_lock, flags); |
933 | d_fnend(3, dev, "(xfer %p [rpipe %p]) = void\n", xfer, | ||
934 | xfer->ep->hcpriv); | ||
935 | return result; | 883 | return result; |
936 | } | 884 | } |
937 | 885 | ||
@@ -964,11 +912,9 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) | |||
964 | struct urb *urb = xfer->urb; | 912 | struct urb *urb = xfer->urb; |
965 | struct wahc *wa = xfer->wa; | 913 | struct wahc *wa = xfer->wa; |
966 | struct wusbhc *wusbhc = wa->wusb; | 914 | struct wusbhc *wusbhc = wa->wusb; |
967 | struct device *dev = &wa->usb_iface->dev; | ||
968 | struct wusb_dev *wusb_dev; | 915 | struct wusb_dev *wusb_dev; |
969 | unsigned done; | 916 | unsigned done; |
970 | 917 | ||
971 | d_fnstart(3, dev, "(wa %p urb %p)\n", wa, urb); | ||
972 | result = rpipe_get_by_ep(wa, xfer->ep, urb, xfer->gfp); | 918 | result = rpipe_get_by_ep(wa, xfer->ep, urb, xfer->gfp); |
973 | if (result < 0) | 919 | if (result < 0) |
974 | goto error_rpipe_get; | 920 | goto error_rpipe_get; |
@@ -997,7 +943,6 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) | |||
997 | if (result < 0) | 943 | if (result < 0) |
998 | goto error_xfer_submit; | 944 | goto error_xfer_submit; |
999 | spin_unlock_irqrestore(&xfer->lock, flags); | 945 | spin_unlock_irqrestore(&xfer->lock, flags); |
1000 | d_fnend(3, dev, "(wa %p urb %p) = void\n", wa, urb); | ||
1001 | return; | 946 | return; |
1002 | 947 | ||
1003 | /* this is basically wa_xfer_completion() broken up wa_xfer_giveback() | 948 | /* this is basically wa_xfer_completion() broken up wa_xfer_giveback() |
@@ -1015,7 +960,6 @@ error_dev_gone: | |||
1015 | error_rpipe_get: | 960 | error_rpipe_get: |
1016 | xfer->result = result; | 961 | xfer->result = result; |
1017 | wa_xfer_giveback(xfer); | 962 | wa_xfer_giveback(xfer); |
1018 | d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result); | ||
1019 | return; | 963 | return; |
1020 | 964 | ||
1021 | error_xfer_submit: | 965 | error_xfer_submit: |
@@ -1024,8 +968,6 @@ error_xfer_submit: | |||
1024 | spin_unlock_irqrestore(&xfer->lock, flags); | 968 | spin_unlock_irqrestore(&xfer->lock, flags); |
1025 | if (done) | 969 | if (done) |
1026 | wa_xfer_completion(xfer); | 970 | wa_xfer_completion(xfer); |
1027 | d_fnend(3, dev, "(wa %p urb %p) = (void) %d\n", wa, urb, result); | ||
1028 | return; | ||
1029 | } | 971 | } |
1030 | 972 | ||
1031 | /* | 973 | /* |
@@ -1041,11 +983,9 @@ error_xfer_submit: | |||
1041 | void wa_urb_enqueue_run(struct work_struct *ws) | 983 | void wa_urb_enqueue_run(struct work_struct *ws) |
1042 | { | 984 | { |
1043 | struct wahc *wa = container_of(ws, struct wahc, xfer_work); | 985 | struct wahc *wa = container_of(ws, struct wahc, xfer_work); |
1044 | struct device *dev = &wa->usb_iface->dev; | ||
1045 | struct wa_xfer *xfer, *next; | 986 | struct wa_xfer *xfer, *next; |
1046 | struct urb *urb; | 987 | struct urb *urb; |
1047 | 988 | ||
1048 | d_fnstart(3, dev, "(wa %p)\n", wa); | ||
1049 | spin_lock_irq(&wa->xfer_list_lock); | 989 | spin_lock_irq(&wa->xfer_list_lock); |
1050 | list_for_each_entry_safe(xfer, next, &wa->xfer_delayed_list, | 990 | list_for_each_entry_safe(xfer, next, &wa->xfer_delayed_list, |
1051 | list_node) { | 991 | list_node) { |
@@ -1059,7 +999,6 @@ void wa_urb_enqueue_run(struct work_struct *ws) | |||
1059 | spin_lock_irq(&wa->xfer_list_lock); | 999 | spin_lock_irq(&wa->xfer_list_lock); |
1060 | } | 1000 | } |
1061 | spin_unlock_irq(&wa->xfer_list_lock); | 1001 | spin_unlock_irq(&wa->xfer_list_lock); |
1062 | d_fnend(3, dev, "(wa %p) = void\n", wa); | ||
1063 | } | 1002 | } |
1064 | EXPORT_SYMBOL_GPL(wa_urb_enqueue_run); | 1003 | EXPORT_SYMBOL_GPL(wa_urb_enqueue_run); |
1065 | 1004 | ||
@@ -1084,9 +1023,6 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, | |||
1084 | unsigned long my_flags; | 1023 | unsigned long my_flags; |
1085 | unsigned cant_sleep = irqs_disabled() | in_atomic(); | 1024 | unsigned cant_sleep = irqs_disabled() | in_atomic(); |
1086 | 1025 | ||
1087 | d_fnstart(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x)\n", | ||
1088 | wa, ep, urb, urb->transfer_buffer_length, gfp); | ||
1089 | |||
1090 | if (urb->transfer_buffer == NULL | 1026 | if (urb->transfer_buffer == NULL |
1091 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 1027 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
1092 | && urb->transfer_buffer_length != 0) { | 1028 | && urb->transfer_buffer_length != 0) { |
@@ -1108,11 +1044,13 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, | |||
1108 | xfer->gfp = gfp; | 1044 | xfer->gfp = gfp; |
1109 | xfer->ep = ep; | 1045 | xfer->ep = ep; |
1110 | urb->hcpriv = xfer; | 1046 | urb->hcpriv = xfer; |
1111 | d_printf(2, dev, "xfer %p urb %p pipe 0x%02x [%d bytes] %s %s %s\n", | 1047 | |
1112 | xfer, urb, urb->pipe, urb->transfer_buffer_length, | 1048 | dev_dbg(dev, "xfer %p urb %p pipe 0x%02x [%d bytes] %s %s %s\n", |
1113 | urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? "dma" : "nodma", | 1049 | xfer, urb, urb->pipe, urb->transfer_buffer_length, |
1114 | urb->pipe & USB_DIR_IN ? "inbound" : "outbound", | 1050 | urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? "dma" : "nodma", |
1115 | cant_sleep ? "deferred" : "inline"); | 1051 | urb->pipe & USB_DIR_IN ? "inbound" : "outbound", |
1052 | cant_sleep ? "deferred" : "inline"); | ||
1053 | |||
1116 | if (cant_sleep) { | 1054 | if (cant_sleep) { |
1117 | usb_get_urb(urb); | 1055 | usb_get_urb(urb); |
1118 | spin_lock_irqsave(&wa->xfer_list_lock, my_flags); | 1056 | spin_lock_irqsave(&wa->xfer_list_lock, my_flags); |
@@ -1122,15 +1060,11 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, | |||
1122 | } else { | 1060 | } else { |
1123 | wa_urb_enqueue_b(xfer); | 1061 | wa_urb_enqueue_b(xfer); |
1124 | } | 1062 | } |
1125 | d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = 0\n", | ||
1126 | wa, ep, urb, urb->transfer_buffer_length, gfp); | ||
1127 | return 0; | 1063 | return 0; |
1128 | 1064 | ||
1129 | error_dequeued: | 1065 | error_dequeued: |
1130 | kfree(xfer); | 1066 | kfree(xfer); |
1131 | error_kmalloc: | 1067 | error_kmalloc: |
1132 | d_fnend(3, dev, "(wa %p ep %p urb %p [%d] gfp 0x%x) = %d\n", | ||
1133 | wa, ep, urb, urb->transfer_buffer_length, gfp, result); | ||
1134 | return result; | 1068 | return result; |
1135 | } | 1069 | } |
1136 | EXPORT_SYMBOL_GPL(wa_urb_enqueue); | 1070 | EXPORT_SYMBOL_GPL(wa_urb_enqueue); |
@@ -1155,7 +1089,6 @@ EXPORT_SYMBOL_GPL(wa_urb_enqueue); | |||
1155 | */ | 1089 | */ |
1156 | int wa_urb_dequeue(struct wahc *wa, struct urb *urb) | 1090 | int wa_urb_dequeue(struct wahc *wa, struct urb *urb) |
1157 | { | 1091 | { |
1158 | struct device *dev = &wa->usb_iface->dev; | ||
1159 | unsigned long flags, flags2; | 1092 | unsigned long flags, flags2; |
1160 | struct wa_xfer *xfer; | 1093 | struct wa_xfer *xfer; |
1161 | struct wa_seg *seg; | 1094 | struct wa_seg *seg; |
@@ -1163,9 +1096,6 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb) | |||
1163 | unsigned cnt; | 1096 | unsigned cnt; |
1164 | unsigned rpipe_ready = 0; | 1097 | unsigned rpipe_ready = 0; |
1165 | 1098 | ||
1166 | d_fnstart(3, dev, "(wa %p, urb %p)\n", wa, urb); | ||
1167 | |||
1168 | d_printf(1, dev, "xfer %p urb %p: aborting\n", urb->hcpriv, urb); | ||
1169 | xfer = urb->hcpriv; | 1099 | xfer = urb->hcpriv; |
1170 | if (xfer == NULL) { | 1100 | if (xfer == NULL) { |
1171 | /* NOthing setup yet enqueue will see urb->status != | 1101 | /* NOthing setup yet enqueue will see urb->status != |
@@ -1234,13 +1164,11 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb) | |||
1234 | wa_xfer_completion(xfer); | 1164 | wa_xfer_completion(xfer); |
1235 | if (rpipe_ready) | 1165 | if (rpipe_ready) |
1236 | wa_xfer_delayed_run(rpipe); | 1166 | wa_xfer_delayed_run(rpipe); |
1237 | d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); | ||
1238 | return 0; | 1167 | return 0; |
1239 | 1168 | ||
1240 | out_unlock: | 1169 | out_unlock: |
1241 | spin_unlock_irqrestore(&xfer->lock, flags); | 1170 | spin_unlock_irqrestore(&xfer->lock, flags); |
1242 | out: | 1171 | out: |
1243 | d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); | ||
1244 | return 0; | 1172 | return 0; |
1245 | 1173 | ||
1246 | dequeue_delayed: | 1174 | dequeue_delayed: |
@@ -1250,7 +1178,6 @@ dequeue_delayed: | |||
1250 | spin_unlock_irqrestore(&xfer->lock, flags); | 1178 | spin_unlock_irqrestore(&xfer->lock, flags); |
1251 | wa_xfer_giveback(xfer); | 1179 | wa_xfer_giveback(xfer); |
1252 | usb_put_urb(urb); /* we got a ref in enqueue() */ | 1180 | usb_put_urb(urb); /* we got a ref in enqueue() */ |
1253 | d_fnend(3, dev, "(wa %p, urb %p) = 0\n", wa, urb); | ||
1254 | return 0; | 1181 | return 0; |
1255 | } | 1182 | } |
1256 | EXPORT_SYMBOL_GPL(wa_urb_dequeue); | 1183 | EXPORT_SYMBOL_GPL(wa_urb_dequeue); |
@@ -1326,7 +1253,6 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1326 | u8 usb_status; | 1253 | u8 usb_status; |
1327 | unsigned rpipe_ready = 0; | 1254 | unsigned rpipe_ready = 0; |
1328 | 1255 | ||
1329 | d_fnstart(3, dev, "(wa %p xfer %p)\n", wa, xfer); | ||
1330 | spin_lock_irqsave(&xfer->lock, flags); | 1256 | spin_lock_irqsave(&xfer->lock, flags); |
1331 | seg_idx = xfer_result->bTransferSegment & 0x7f; | 1257 | seg_idx = xfer_result->bTransferSegment & 0x7f; |
1332 | if (unlikely(seg_idx >= xfer->segs)) | 1258 | if (unlikely(seg_idx >= xfer->segs)) |
@@ -1334,8 +1260,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1334 | seg = xfer->seg[seg_idx]; | 1260 | seg = xfer->seg[seg_idx]; |
1335 | rpipe = xfer->ep->hcpriv; | 1261 | rpipe = xfer->ep->hcpriv; |
1336 | usb_status = xfer_result->bTransferStatus; | 1262 | usb_status = xfer_result->bTransferStatus; |
1337 | d_printf(2, dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n", | 1263 | dev_dbg(dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n", |
1338 | xfer, seg_idx, usb_status, seg->status); | 1264 | xfer, seg_idx, usb_status, seg->status); |
1339 | if (seg->status == WA_SEG_ABORTED | 1265 | if (seg->status == WA_SEG_ABORTED |
1340 | || seg->status == WA_SEG_ERROR) /* already handled */ | 1266 | || seg->status == WA_SEG_ERROR) /* already handled */ |
1341 | goto segment_aborted; | 1267 | goto segment_aborted; |
@@ -1391,10 +1317,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1391 | wa_xfer_completion(xfer); | 1317 | wa_xfer_completion(xfer); |
1392 | if (rpipe_ready) | 1318 | if (rpipe_ready) |
1393 | wa_xfer_delayed_run(rpipe); | 1319 | wa_xfer_delayed_run(rpipe); |
1394 | d_fnend(3, dev, "(wa %p xfer %p) = void\n", wa, xfer); | ||
1395 | return; | 1320 | return; |
1396 | 1321 | ||
1397 | |||
1398 | error_submit_buf_in: | 1322 | error_submit_buf_in: |
1399 | if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { | 1323 | if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { |
1400 | dev_err(dev, "DTI: URB max acceptable errors " | 1324 | dev_err(dev, "DTI: URB max acceptable errors " |
@@ -1416,11 +1340,8 @@ error_complete: | |||
1416 | wa_xfer_completion(xfer); | 1340 | wa_xfer_completion(xfer); |
1417 | if (rpipe_ready) | 1341 | if (rpipe_ready) |
1418 | wa_xfer_delayed_run(rpipe); | 1342 | wa_xfer_delayed_run(rpipe); |
1419 | d_fnend(3, dev, "(wa %p xfer %p) = void [segment/DTI-submit error]\n", | ||
1420 | wa, xfer); | ||
1421 | return; | 1343 | return; |
1422 | 1344 | ||
1423 | |||
1424 | error_bad_seg: | 1345 | error_bad_seg: |
1425 | spin_unlock_irqrestore(&xfer->lock, flags); | 1346 | spin_unlock_irqrestore(&xfer->lock, flags); |
1426 | wa_urb_dequeue(wa, xfer->urb); | 1347 | wa_urb_dequeue(wa, xfer->urb); |
@@ -1431,17 +1352,11 @@ error_bad_seg: | |||
1431 | "exceeded, resetting device\n"); | 1352 | "exceeded, resetting device\n"); |
1432 | wa_reset_all(wa); | 1353 | wa_reset_all(wa); |
1433 | } | 1354 | } |
1434 | d_fnend(3, dev, "(wa %p xfer %p) = void [bad seg]\n", wa, xfer); | ||
1435 | return; | 1355 | return; |
1436 | 1356 | ||
1437 | |||
1438 | segment_aborted: | 1357 | segment_aborted: |
1439 | /* nothing to do, as the aborter did the completion */ | 1358 | /* nothing to do, as the aborter did the completion */ |
1440 | spin_unlock_irqrestore(&xfer->lock, flags); | 1359 | spin_unlock_irqrestore(&xfer->lock, flags); |
1441 | d_fnend(3, dev, "(wa %p xfer %p) = void [segment aborted]\n", | ||
1442 | wa, xfer); | ||
1443 | return; | ||
1444 | |||
1445 | } | 1360 | } |
1446 | 1361 | ||
1447 | /* | 1362 | /* |
@@ -1465,15 +1380,14 @@ static void wa_buf_in_cb(struct urb *urb) | |||
1465 | unsigned long flags; | 1380 | unsigned long flags; |
1466 | u8 done = 0; | 1381 | u8 done = 0; |
1467 | 1382 | ||
1468 | d_fnstart(3, NULL, "(urb %p [%d])\n", urb, urb->status); | ||
1469 | switch (urb->status) { | 1383 | switch (urb->status) { |
1470 | case 0: | 1384 | case 0: |
1471 | spin_lock_irqsave(&xfer->lock, flags); | 1385 | spin_lock_irqsave(&xfer->lock, flags); |
1472 | wa = xfer->wa; | 1386 | wa = xfer->wa; |
1473 | dev = &wa->usb_iface->dev; | 1387 | dev = &wa->usb_iface->dev; |
1474 | rpipe = xfer->ep->hcpriv; | 1388 | rpipe = xfer->ep->hcpriv; |
1475 | d_printf(2, dev, "xfer %p#%u: data in done (%zu bytes)\n", | 1389 | dev_dbg(dev, "xfer %p#%u: data in done (%zu bytes)\n", |
1476 | xfer, seg->index, (size_t)urb->actual_length); | 1390 | xfer, seg->index, (size_t)urb->actual_length); |
1477 | seg->status = WA_SEG_DONE; | 1391 | seg->status = WA_SEG_DONE; |
1478 | seg->result = urb->actual_length; | 1392 | seg->result = urb->actual_length; |
1479 | xfer->segs_done++; | 1393 | xfer->segs_done++; |
@@ -1514,7 +1428,6 @@ static void wa_buf_in_cb(struct urb *urb) | |||
1514 | if (rpipe_ready) | 1428 | if (rpipe_ready) |
1515 | wa_xfer_delayed_run(rpipe); | 1429 | wa_xfer_delayed_run(rpipe); |
1516 | } | 1430 | } |
1517 | d_fnend(3, NULL, "(urb %p [%d]) = void\n", urb, urb->status); | ||
1518 | } | 1431 | } |
1519 | 1432 | ||
1520 | /* | 1433 | /* |
@@ -1553,14 +1466,12 @@ static void wa_xfer_result_cb(struct urb *urb) | |||
1553 | struct wa_xfer *xfer; | 1466 | struct wa_xfer *xfer; |
1554 | u8 usb_status; | 1467 | u8 usb_status; |
1555 | 1468 | ||
1556 | d_fnstart(3, dev, "(%p)\n", wa); | ||
1557 | BUG_ON(wa->dti_urb != urb); | 1469 | BUG_ON(wa->dti_urb != urb); |
1558 | switch (wa->dti_urb->status) { | 1470 | switch (wa->dti_urb->status) { |
1559 | case 0: | 1471 | case 0: |
1560 | /* We have a xfer result buffer; check it */ | 1472 | /* We have a xfer result buffer; check it */ |
1561 | d_printf(2, dev, "DTI: xfer result %d bytes at %p\n", | 1473 | dev_dbg(dev, "DTI: xfer result %d bytes at %p\n", |
1562 | urb->actual_length, urb->transfer_buffer); | 1474 | urb->actual_length, urb->transfer_buffer); |
1563 | d_dump(3, dev, urb->transfer_buffer, urb->actual_length); | ||
1564 | if (wa->dti_urb->actual_length != sizeof(*xfer_result)) { | 1475 | if (wa->dti_urb->actual_length != sizeof(*xfer_result)) { |
1565 | dev_err(dev, "DTI Error: xfer result--bad size " | 1476 | dev_err(dev, "DTI Error: xfer result--bad size " |
1566 | "xfer result (%d bytes vs %zu needed)\n", | 1477 | "xfer result (%d bytes vs %zu needed)\n", |
@@ -1622,7 +1533,6 @@ static void wa_xfer_result_cb(struct urb *urb) | |||
1622 | wa_reset_all(wa); | 1533 | wa_reset_all(wa); |
1623 | } | 1534 | } |
1624 | out: | 1535 | out: |
1625 | d_fnend(3, dev, "(%p) = void\n", wa); | ||
1626 | return; | 1536 | return; |
1627 | } | 1537 | } |
1628 | 1538 | ||
@@ -1653,7 +1563,6 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) | |||
1653 | struct wa_notif_xfer *notif_xfer; | 1563 | struct wa_notif_xfer *notif_xfer; |
1654 | const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; | 1564 | const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; |
1655 | 1565 | ||
1656 | d_fnstart(4, dev, "(%p, %p)\n", wa, notif_hdr); | ||
1657 | notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr); | 1566 | notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr); |
1658 | BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER); | 1567 | BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER); |
1659 | 1568 | ||
@@ -1693,7 +1602,6 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) | |||
1693 | goto error_dti_urb_submit; | 1602 | goto error_dti_urb_submit; |
1694 | } | 1603 | } |
1695 | out: | 1604 | out: |
1696 | d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr); | ||
1697 | return; | 1605 | return; |
1698 | 1606 | ||
1699 | error_dti_urb_submit: | 1607 | error_dti_urb_submit: |
@@ -1704,6 +1612,4 @@ error_buf_in_urb_alloc: | |||
1704 | error_dti_urb_alloc: | 1612 | error_dti_urb_alloc: |
1705 | error: | 1613 | error: |
1706 | wa_reset_all(wa); | 1614 | wa_reset_all(wa); |
1707 | d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr); | ||
1708 | return; | ||
1709 | } | 1615 | } |
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index d0c132434f1b..797c2453a35b 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h | |||
@@ -64,6 +64,13 @@ | |||
64 | #include <linux/uwb.h> | 64 | #include <linux/uwb.h> |
65 | #include <linux/usb/wusb.h> | 65 | #include <linux/usb/wusb.h> |
66 | 66 | ||
67 | /* | ||
68 | * Time from a WUSB channel stop request to the last transmitted MMC. | ||
69 | * | ||
70 | * This needs to be > 4.096 ms in case no MMCs can be transmitted in | ||
71 | * zone 0. | ||
72 | */ | ||
73 | #define WUSB_CHANNEL_STOP_DELAY_MS 8 | ||
67 | 74 | ||
68 | /** | 75 | /** |
69 | * Wireless USB device | 76 | * Wireless USB device |
@@ -147,7 +154,6 @@ struct wusb_port { | |||
147 | u16 status; | 154 | u16 status; |
148 | u16 change; | 155 | u16 change; |
149 | struct wusb_dev *wusb_dev; /* connected device's info */ | 156 | struct wusb_dev *wusb_dev; /* connected device's info */ |
150 | unsigned reset_count; | ||
151 | u32 ptk_tkid; | 157 | u32 ptk_tkid; |
152 | }; | 158 | }; |
153 | 159 | ||
@@ -198,21 +204,18 @@ struct wusb_port { | |||
198 | * @mmcies_max Max number of Information Elements this HC can send | 204 | * @mmcies_max Max number of Information Elements this HC can send |
199 | * in its MMC. Read-only. | 205 | * in its MMC. Read-only. |
200 | * | 206 | * |
207 | * @start Start the WUSB channel. | ||
208 | * | ||
209 | * @stop Stop the WUSB channel after the specified number of | ||
210 | * milliseconds. Channel Stop IEs should be transmitted | ||
211 | * as required by [WUSB] 4.16.2.1. | ||
212 | * | ||
201 | * @mmcie_add HC specific operation (WHCI or HWA) for adding an | 213 | * @mmcie_add HC specific operation (WHCI or HWA) for adding an |
202 | * MMCIE. | 214 | * MMCIE. |
203 | * | 215 | * |
204 | * @mmcie_rm HC specific operation (WHCI or HWA) for removing an | 216 | * @mmcie_rm HC specific operation (WHCI or HWA) for removing an |
205 | * MMCIE. | 217 | * MMCIE. |
206 | * | 218 | * |
207 | * @enc_types Array which describes the encryptions methods | ||
208 | * supported by the host as described in WUSB1.0 -- | ||
209 | * one entry per supported method. As of WUSB1.0 there | ||
210 | * is only four methods, we make space for eight just in | ||
211 | * case they decide to add some more (and pray they do | ||
212 | * it in sequential order). if 'enc_types[enc_method] | ||
213 | * != 0', then it is supported by the host. enc_method | ||
214 | * is USB_ENC_TYPE*. | ||
215 | * | ||
216 | * @set_ptk: Set the PTK and enable encryption for a device. Or, if | 219 | * @set_ptk: Set the PTK and enable encryption for a device. Or, if |
217 | * the supplied key is NULL, disable encryption for that | 220 | * the supplied key is NULL, disable encryption for that |
218 | * device. | 221 | * device. |
@@ -249,7 +252,8 @@ struct wusbhc { | |||
249 | struct uwb_pal pal; | 252 | struct uwb_pal pal; |
250 | 253 | ||
251 | unsigned trust_timeout; /* in jiffies */ | 254 | unsigned trust_timeout; /* in jiffies */ |
252 | struct wuie_host_info *wuie_host_info; /* Includes CHID */ | 255 | struct wusb_ckhdid chid; |
256 | struct wuie_host_info *wuie_host_info; | ||
253 | 257 | ||
254 | struct mutex mutex; /* locks everything else */ | 258 | struct mutex mutex; /* locks everything else */ |
255 | u16 cluster_id; /* Wireless USB Cluster ID */ | 259 | u16 cluster_id; /* Wireless USB Cluster ID */ |
@@ -269,7 +273,7 @@ struct wusbhc { | |||
269 | u8 mmcies_max; | 273 | u8 mmcies_max; |
270 | /* FIXME: make wusbhc_ops? */ | 274 | /* FIXME: make wusbhc_ops? */ |
271 | int (*start)(struct wusbhc *wusbhc); | 275 | int (*start)(struct wusbhc *wusbhc); |
272 | void (*stop)(struct wusbhc *wusbhc); | 276 | void (*stop)(struct wusbhc *wusbhc, int delay); |
273 | int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, | 277 | int (*mmcie_add)(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt, |
274 | u8 handle, struct wuie_hdr *wuie); | 278 | u8 handle, struct wuie_hdr *wuie); |
275 | int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle); | 279 | int (*mmcie_rm)(struct wusbhc *wusbhc, u8 handle); |
@@ -373,20 +377,17 @@ static inline void wusbhc_put(struct wusbhc *wusbhc) | |||
373 | usb_put_hcd(&wusbhc->usb_hcd); | 377 | usb_put_hcd(&wusbhc->usb_hcd); |
374 | } | 378 | } |
375 | 379 | ||
376 | int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid); | 380 | int wusbhc_start(struct wusbhc *wusbhc); |
377 | void wusbhc_stop(struct wusbhc *wusbhc); | 381 | void wusbhc_stop(struct wusbhc *wusbhc); |
378 | extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); | 382 | extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *); |
379 | 383 | ||
380 | /* Device connect handling */ | 384 | /* Device connect handling */ |
381 | extern int wusbhc_devconnect_create(struct wusbhc *); | 385 | extern int wusbhc_devconnect_create(struct wusbhc *); |
382 | extern void wusbhc_devconnect_destroy(struct wusbhc *); | 386 | extern void wusbhc_devconnect_destroy(struct wusbhc *); |
383 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc, | 387 | extern int wusbhc_devconnect_start(struct wusbhc *wusbhc); |
384 | const struct wusb_ckhdid *chid); | ||
385 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); | 388 | extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc); |
386 | extern int wusbhc_devconnect_auth(struct wusbhc *, u8); | ||
387 | extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, | 389 | extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr, |
388 | struct wusb_dn_hdr *dn_hdr, size_t size); | 390 | struct wusb_dn_hdr *dn_hdr, size_t size); |
389 | extern int wusbhc_dev_reset(struct wusbhc *wusbhc, u8 port); | ||
390 | extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port); | 391 | extern void __wusbhc_dev_disable(struct wusbhc *wusbhc, u8 port); |
391 | extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, | 392 | extern int wusb_usb_ncb(struct notifier_block *nb, unsigned long val, |
392 | void *priv); | 393 | void *priv); |
@@ -432,6 +433,7 @@ extern void wusb_dev_sec_rm(struct wusb_dev *) ; | |||
432 | extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *, | 433 | extern int wusb_dev_4way_handshake(struct wusbhc *, struct wusb_dev *, |
433 | struct wusb_ckhdid *ck); | 434 | struct wusb_ckhdid *ck); |
434 | void wusbhc_gtk_rekey(struct wusbhc *wusbhc); | 435 | void wusbhc_gtk_rekey(struct wusbhc *wusbhc); |
436 | int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev); | ||
435 | 437 | ||
436 | 438 | ||
437 | /* WUSB Cluster ID handling */ | 439 | /* WUSB Cluster ID handling */ |
diff --git a/drivers/uwb/Makefile b/drivers/uwb/Makefile index 257e6908304c..2f98d080fe78 100644 --- a/drivers/uwb/Makefile +++ b/drivers/uwb/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_UWB_I1480U) += i1480/ | |||
6 | 6 | ||
7 | uwb-objs := \ | 7 | uwb-objs := \ |
8 | address.o \ | 8 | address.o \ |
9 | allocator.o \ | ||
9 | beacon.o \ | 10 | beacon.o \ |
10 | driver.o \ | 11 | driver.o \ |
11 | drp.o \ | 12 | drp.o \ |
@@ -13,10 +14,12 @@ uwb-objs := \ | |||
13 | drp-ie.o \ | 14 | drp-ie.o \ |
14 | est.o \ | 15 | est.o \ |
15 | ie.o \ | 16 | ie.o \ |
17 | ie-rcv.o \ | ||
16 | lc-dev.o \ | 18 | lc-dev.o \ |
17 | lc-rc.o \ | 19 | lc-rc.o \ |
18 | neh.o \ | 20 | neh.o \ |
19 | pal.o \ | 21 | pal.o \ |
22 | radio.o \ | ||
20 | reset.o \ | 23 | reset.o \ |
21 | rsv.o \ | 24 | rsv.o \ |
22 | scan.o \ | 25 | scan.o \ |
diff --git a/drivers/uwb/address.c b/drivers/uwb/address.c index 1664ae5f1706..ad21b1d7218c 100644 --- a/drivers/uwb/address.c +++ b/drivers/uwb/address.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/random.h> | 29 | #include <linux/random.h> |
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/uwb/debug.h> | 31 | |
32 | #include "uwb-internal.h" | 32 | #include "uwb-internal.h" |
33 | 33 | ||
34 | 34 | ||
diff --git a/drivers/uwb/allocator.c b/drivers/uwb/allocator.c new file mode 100644 index 000000000000..c8185e6b0cd5 --- /dev/null +++ b/drivers/uwb/allocator.c | |||
@@ -0,0 +1,386 @@ | |||
1 | /* | ||
2 | * UWB reservation management. | ||
3 | * | ||
4 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/uwb.h> | ||
21 | |||
22 | #include "uwb-internal.h" | ||
23 | |||
24 | static void uwb_rsv_fill_column_alloc(struct uwb_rsv_alloc_info *ai) | ||
25 | { | ||
26 | int col, mas, safe_mas, unsafe_mas; | ||
27 | unsigned char *bm = ai->bm; | ||
28 | struct uwb_rsv_col_info *ci = ai->ci; | ||
29 | unsigned char c; | ||
30 | |||
31 | for (col = ci->csi.start_col; col < UWB_NUM_ZONES; col += ci->csi.interval) { | ||
32 | |||
33 | safe_mas = ci->csi.safe_mas_per_col; | ||
34 | unsafe_mas = ci->csi.unsafe_mas_per_col; | ||
35 | |||
36 | for (mas = 0; mas < UWB_MAS_PER_ZONE; mas++ ) { | ||
37 | if (bm[col * UWB_MAS_PER_ZONE + mas] == 0) { | ||
38 | |||
39 | if (safe_mas > 0) { | ||
40 | safe_mas--; | ||
41 | c = UWB_RSV_MAS_SAFE; | ||
42 | } else if (unsafe_mas > 0) { | ||
43 | unsafe_mas--; | ||
44 | c = UWB_RSV_MAS_UNSAFE; | ||
45 | } else { | ||
46 | break; | ||
47 | } | ||
48 | bm[col * UWB_MAS_PER_ZONE + mas] = c; | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | static void uwb_rsv_fill_row_alloc(struct uwb_rsv_alloc_info *ai) | ||
55 | { | ||
56 | int mas, col, rows; | ||
57 | unsigned char *bm = ai->bm; | ||
58 | struct uwb_rsv_row_info *ri = &ai->ri; | ||
59 | unsigned char c; | ||
60 | |||
61 | rows = 1; | ||
62 | c = UWB_RSV_MAS_SAFE; | ||
63 | for (mas = UWB_MAS_PER_ZONE - 1; mas >= 0; mas--) { | ||
64 | if (ri->avail[mas] == 1) { | ||
65 | |||
66 | if (rows > ri->used_rows) { | ||
67 | break; | ||
68 | } else if (rows > 7) { | ||
69 | c = UWB_RSV_MAS_UNSAFE; | ||
70 | } | ||
71 | |||
72 | for (col = 0; col < UWB_NUM_ZONES; col++) { | ||
73 | if (bm[col * UWB_NUM_ZONES + mas] != UWB_RSV_MAS_NOT_AVAIL) { | ||
74 | bm[col * UWB_NUM_ZONES + mas] = c; | ||
75 | if(c == UWB_RSV_MAS_SAFE) | ||
76 | ai->safe_allocated_mases++; | ||
77 | else | ||
78 | ai->unsafe_allocated_mases++; | ||
79 | } | ||
80 | } | ||
81 | rows++; | ||
82 | } | ||
83 | } | ||
84 | ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Find the best column set for a given availability, interval, num safe mas and | ||
89 | * num unsafe mas. | ||
90 | * | ||
91 | * The different sets are tried in order as shown below, depending on the interval. | ||
92 | * | ||
93 | * interval = 16 | ||
94 | * deep = 0 | ||
95 | * set 1 -> { 8 } | ||
96 | * deep = 1 | ||
97 | * set 1 -> { 4 } | ||
98 | * set 2 -> { 12 } | ||
99 | * deep = 2 | ||
100 | * set 1 -> { 2 } | ||
101 | * set 2 -> { 6 } | ||
102 | * set 3 -> { 10 } | ||
103 | * set 4 -> { 14 } | ||
104 | * deep = 3 | ||
105 | * set 1 -> { 1 } | ||
106 | * set 2 -> { 3 } | ||
107 | * set 3 -> { 5 } | ||
108 | * set 4 -> { 7 } | ||
109 | * set 5 -> { 9 } | ||
110 | * set 6 -> { 11 } | ||
111 | * set 7 -> { 13 } | ||
112 | * set 8 -> { 15 } | ||
113 | * | ||
114 | * interval = 8 | ||
115 | * deep = 0 | ||
116 | * set 1 -> { 4 12 } | ||
117 | * deep = 1 | ||
118 | * set 1 -> { 2 10 } | ||
119 | * set 2 -> { 6 14 } | ||
120 | * deep = 2 | ||
121 | * set 1 -> { 1 9 } | ||
122 | * set 2 -> { 3 11 } | ||
123 | * set 3 -> { 5 13 } | ||
124 | * set 4 -> { 7 15 } | ||
125 | * | ||
126 | * interval = 4 | ||
127 | * deep = 0 | ||
128 | * set 1 -> { 2 6 10 14 } | ||
129 | * deep = 1 | ||
130 | * set 1 -> { 1 5 9 13 } | ||
131 | * set 2 -> { 3 7 11 15 } | ||
132 | * | ||
133 | * interval = 2 | ||
134 | * deep = 0 | ||
135 | * set 1 -> { 1 3 5 7 9 11 13 15 } | ||
136 | */ | ||
137 | static int uwb_rsv_find_best_column_set(struct uwb_rsv_alloc_info *ai, int interval, | ||
138 | int num_safe_mas, int num_unsafe_mas) | ||
139 | { | ||
140 | struct uwb_rsv_col_info *ci = ai->ci; | ||
141 | struct uwb_rsv_col_set_info *csi = &ci->csi; | ||
142 | struct uwb_rsv_col_set_info tmp_csi; | ||
143 | int deep, set, col, start_col_deep, col_start_set; | ||
144 | int start_col, max_mas_in_set, lowest_max_mas_in_deep; | ||
145 | int n_mas; | ||
146 | int found = UWB_RSV_ALLOC_NOT_FOUND; | ||
147 | |||
148 | tmp_csi.start_col = 0; | ||
149 | start_col_deep = interval; | ||
150 | n_mas = num_unsafe_mas + num_safe_mas; | ||
151 | |||
152 | for (deep = 0; ((interval >> deep) & 0x1) == 0; deep++) { | ||
153 | start_col_deep /= 2; | ||
154 | col_start_set = 0; | ||
155 | lowest_max_mas_in_deep = UWB_MAS_PER_ZONE; | ||
156 | |||
157 | for (set = 1; set <= (1 << deep); set++) { | ||
158 | max_mas_in_set = 0; | ||
159 | start_col = start_col_deep + col_start_set; | ||
160 | for (col = start_col; col < UWB_NUM_ZONES; col += interval) { | ||
161 | |||
162 | if (ci[col].max_avail_safe >= num_safe_mas && | ||
163 | ci[col].max_avail_unsafe >= n_mas) { | ||
164 | if (ci[col].highest_mas[n_mas] > max_mas_in_set) | ||
165 | max_mas_in_set = ci[col].highest_mas[n_mas]; | ||
166 | } else { | ||
167 | max_mas_in_set = 0; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | if ((lowest_max_mas_in_deep > max_mas_in_set) && max_mas_in_set) { | ||
172 | lowest_max_mas_in_deep = max_mas_in_set; | ||
173 | |||
174 | tmp_csi.start_col = start_col; | ||
175 | } | ||
176 | col_start_set += (interval >> deep); | ||
177 | } | ||
178 | |||
179 | if (lowest_max_mas_in_deep < 8) { | ||
180 | csi->start_col = tmp_csi.start_col; | ||
181 | found = UWB_RSV_ALLOC_FOUND; | ||
182 | break; | ||
183 | } else if ((lowest_max_mas_in_deep > 8) && | ||
184 | (lowest_max_mas_in_deep != UWB_MAS_PER_ZONE) && | ||
185 | (found == UWB_RSV_ALLOC_NOT_FOUND)) { | ||
186 | csi->start_col = tmp_csi.start_col; | ||
187 | found = UWB_RSV_ALLOC_FOUND; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | if (found == UWB_RSV_ALLOC_FOUND) { | ||
192 | csi->interval = interval; | ||
193 | csi->safe_mas_per_col = num_safe_mas; | ||
194 | csi->unsafe_mas_per_col = num_unsafe_mas; | ||
195 | |||
196 | ai->safe_allocated_mases = (UWB_NUM_ZONES / interval) * num_safe_mas; | ||
197 | ai->unsafe_allocated_mases = (UWB_NUM_ZONES / interval) * num_unsafe_mas; | ||
198 | ai->total_allocated_mases = ai->safe_allocated_mases + ai->unsafe_allocated_mases; | ||
199 | ai->interval = interval; | ||
200 | } | ||
201 | return found; | ||
202 | } | ||
203 | |||
204 | static void get_row_descriptors(struct uwb_rsv_alloc_info *ai) | ||
205 | { | ||
206 | unsigned char *bm = ai->bm; | ||
207 | struct uwb_rsv_row_info *ri = &ai->ri; | ||
208 | int col, mas; | ||
209 | |||
210 | ri->free_rows = 16; | ||
211 | for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) { | ||
212 | ri->avail[mas] = 1; | ||
213 | for (col = 1; col < UWB_NUM_ZONES; col++) { | ||
214 | if (bm[col * UWB_NUM_ZONES + mas] == UWB_RSV_MAS_NOT_AVAIL) { | ||
215 | ri->free_rows--; | ||
216 | ri->avail[mas]=0; | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static void uwb_rsv_fill_column_info(unsigned char *bm, int column, struct uwb_rsv_col_info *rci) | ||
224 | { | ||
225 | int mas; | ||
226 | int block_count = 0, start_block = 0; | ||
227 | int previous_avail = 0; | ||
228 | int available = 0; | ||
229 | int safe_mas_in_row[UWB_MAS_PER_ZONE] = { | ||
230 | 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, | ||
231 | }; | ||
232 | |||
233 | rci->max_avail_safe = 0; | ||
234 | |||
235 | for (mas = 0; mas < UWB_MAS_PER_ZONE; mas ++) { | ||
236 | if (!bm[column * UWB_NUM_ZONES + mas]) { | ||
237 | available++; | ||
238 | rci->max_avail_unsafe = available; | ||
239 | |||
240 | rci->highest_mas[available] = mas; | ||
241 | |||
242 | if (previous_avail) { | ||
243 | block_count++; | ||
244 | if ((block_count > safe_mas_in_row[start_block]) && | ||
245 | (!rci->max_avail_safe)) | ||
246 | rci->max_avail_safe = available - 1; | ||
247 | } else { | ||
248 | previous_avail = 1; | ||
249 | start_block = mas; | ||
250 | block_count = 1; | ||
251 | } | ||
252 | } else { | ||
253 | previous_avail = 0; | ||
254 | } | ||
255 | } | ||
256 | if (!rci->max_avail_safe) | ||
257 | rci->max_avail_safe = rci->max_avail_unsafe; | ||
258 | } | ||
259 | |||
260 | static void get_column_descriptors(struct uwb_rsv_alloc_info *ai) | ||
261 | { | ||
262 | unsigned char *bm = ai->bm; | ||
263 | struct uwb_rsv_col_info *ci = ai->ci; | ||
264 | int col; | ||
265 | |||
266 | for (col = 1; col < UWB_NUM_ZONES; col++) { | ||
267 | uwb_rsv_fill_column_info(bm, col, &ci[col]); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static int uwb_rsv_find_best_row_alloc(struct uwb_rsv_alloc_info *ai) | ||
272 | { | ||
273 | int n_rows; | ||
274 | int max_rows = ai->max_mas / UWB_USABLE_MAS_PER_ROW; | ||
275 | int min_rows = ai->min_mas / UWB_USABLE_MAS_PER_ROW; | ||
276 | if (ai->min_mas % UWB_USABLE_MAS_PER_ROW) | ||
277 | min_rows++; | ||
278 | for (n_rows = max_rows; n_rows >= min_rows; n_rows--) { | ||
279 | if (n_rows <= ai->ri.free_rows) { | ||
280 | ai->ri.used_rows = n_rows; | ||
281 | ai->interval = 1; /* row reservation */ | ||
282 | uwb_rsv_fill_row_alloc(ai); | ||
283 | return UWB_RSV_ALLOC_FOUND; | ||
284 | } | ||
285 | } | ||
286 | return UWB_RSV_ALLOC_NOT_FOUND; | ||
287 | } | ||
288 | |||
289 | static int uwb_rsv_find_best_col_alloc(struct uwb_rsv_alloc_info *ai, int interval) | ||
290 | { | ||
291 | int n_safe, n_unsafe, n_mas; | ||
292 | int n_column = UWB_NUM_ZONES / interval; | ||
293 | int max_per_zone = ai->max_mas / n_column; | ||
294 | int min_per_zone = ai->min_mas / n_column; | ||
295 | |||
296 | if (ai->min_mas % n_column) | ||
297 | min_per_zone++; | ||
298 | |||
299 | if (min_per_zone > UWB_MAS_PER_ZONE) { | ||
300 | return UWB_RSV_ALLOC_NOT_FOUND; | ||
301 | } | ||
302 | |||
303 | if (max_per_zone > UWB_MAS_PER_ZONE) { | ||
304 | max_per_zone = UWB_MAS_PER_ZONE; | ||
305 | } | ||
306 | |||
307 | for (n_mas = max_per_zone; n_mas >= min_per_zone; n_mas--) { | ||
308 | if (uwb_rsv_find_best_column_set(ai, interval, 0, n_mas) == UWB_RSV_ALLOC_NOT_FOUND) | ||
309 | continue; | ||
310 | for (n_safe = n_mas; n_safe >= 0; n_safe--) { | ||
311 | n_unsafe = n_mas - n_safe; | ||
312 | if (uwb_rsv_find_best_column_set(ai, interval, n_safe, n_unsafe) == UWB_RSV_ALLOC_FOUND) { | ||
313 | uwb_rsv_fill_column_alloc(ai); | ||
314 | return UWB_RSV_ALLOC_FOUND; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | return UWB_RSV_ALLOC_NOT_FOUND; | ||
319 | } | ||
320 | |||
321 | int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *available, | ||
322 | struct uwb_mas_bm *result) | ||
323 | { | ||
324 | struct uwb_rsv_alloc_info *ai; | ||
325 | int interval; | ||
326 | int bit_index; | ||
327 | |||
328 | ai = kzalloc(sizeof(struct uwb_rsv_alloc_info), GFP_KERNEL); | ||
329 | |||
330 | ai->min_mas = rsv->min_mas; | ||
331 | ai->max_mas = rsv->max_mas; | ||
332 | ai->max_interval = rsv->max_interval; | ||
333 | |||
334 | |||
335 | /* fill the not available vector from the available bm */ | ||
336 | for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) { | ||
337 | if (!test_bit(bit_index, available->bm)) | ||
338 | ai->bm[bit_index] = UWB_RSV_MAS_NOT_AVAIL; | ||
339 | } | ||
340 | |||
341 | if (ai->max_interval == 1) { | ||
342 | get_row_descriptors(ai); | ||
343 | if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND) | ||
344 | goto alloc_found; | ||
345 | else | ||
346 | goto alloc_not_found; | ||
347 | } | ||
348 | |||
349 | get_column_descriptors(ai); | ||
350 | |||
351 | for (interval = 16; interval >= 2; interval>>=1) { | ||
352 | if (interval > ai->max_interval) | ||
353 | continue; | ||
354 | if (uwb_rsv_find_best_col_alloc(ai, interval) == UWB_RSV_ALLOC_FOUND) | ||
355 | goto alloc_found; | ||
356 | } | ||
357 | |||
358 | /* try row reservation if no column is found */ | ||
359 | get_row_descriptors(ai); | ||
360 | if (uwb_rsv_find_best_row_alloc(ai) == UWB_RSV_ALLOC_FOUND) | ||
361 | goto alloc_found; | ||
362 | else | ||
363 | goto alloc_not_found; | ||
364 | |||
365 | alloc_found: | ||
366 | bitmap_zero(result->bm, UWB_NUM_MAS); | ||
367 | bitmap_zero(result->unsafe_bm, UWB_NUM_MAS); | ||
368 | /* fill the safe and unsafe bitmaps */ | ||
369 | for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) { | ||
370 | if (ai->bm[bit_index] == UWB_RSV_MAS_SAFE) | ||
371 | set_bit(bit_index, result->bm); | ||
372 | else if (ai->bm[bit_index] == UWB_RSV_MAS_UNSAFE) | ||
373 | set_bit(bit_index, result->unsafe_bm); | ||
374 | } | ||
375 | bitmap_or(result->bm, result->bm, result->unsafe_bm, UWB_NUM_MAS); | ||
376 | |||
377 | result->safe = ai->safe_allocated_mases; | ||
378 | result->unsafe = ai->unsafe_allocated_mases; | ||
379 | |||
380 | kfree(ai); | ||
381 | return UWB_RSV_ALLOC_FOUND; | ||
382 | |||
383 | alloc_not_found: | ||
384 | kfree(ai); | ||
385 | return UWB_RSV_ALLOC_NOT_FOUND; | ||
386 | } | ||
diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c index 46b18eec5026..36bc3158006f 100644 --- a/drivers/uwb/beacon.c +++ b/drivers/uwb/beacon.c | |||
@@ -22,19 +22,16 @@ | |||
22 | * | 22 | * |
23 | * FIXME: docs | 23 | * FIXME: docs |
24 | */ | 24 | */ |
25 | |||
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/device.h> | 28 | #include <linux/device.h> |
30 | #include <linux/err.h> | 29 | #include <linux/err.h> |
31 | #include <linux/kdev_t.h> | 30 | #include <linux/kdev_t.h> |
32 | #include "uwb-internal.h" | ||
33 | 31 | ||
34 | #define D_LOCAL 0 | 32 | #include "uwb-internal.h" |
35 | #include <linux/uwb/debug.h> | ||
36 | 33 | ||
37 | /** Start Beaconing command structure */ | 34 | /* Start Beaconing command structure */ |
38 | struct uwb_rc_cmd_start_beacon { | 35 | struct uwb_rc_cmd_start_beacon { |
39 | struct uwb_rccb rccb; | 36 | struct uwb_rccb rccb; |
40 | __le16 wBPSTOffset; | 37 | __le16 wBPSTOffset; |
@@ -119,7 +116,6 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
119 | int result; | 116 | int result; |
120 | struct device *dev = &rc->uwb_dev.dev; | 117 | struct device *dev = &rc->uwb_dev.dev; |
121 | 118 | ||
122 | mutex_lock(&rc->uwb_dev.mutex); | ||
123 | if (channel < 0) | 119 | if (channel < 0) |
124 | channel = -1; | 120 | channel = -1; |
125 | if (channel == -1) | 121 | if (channel == -1) |
@@ -128,7 +124,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
128 | /* channel >= 0...dah */ | 124 | /* channel >= 0...dah */ |
129 | result = uwb_rc_start_beacon(rc, bpst_offset, channel); | 125 | result = uwb_rc_start_beacon(rc, bpst_offset, channel); |
130 | if (result < 0) | 126 | if (result < 0) |
131 | goto out_up; | 127 | return result; |
132 | if (le16_to_cpu(rc->ies->wIELength) > 0) { | 128 | if (le16_to_cpu(rc->ies->wIELength) > 0) { |
133 | result = uwb_rc_set_ie(rc, rc->ies); | 129 | result = uwb_rc_set_ie(rc, rc->ies); |
134 | if (result < 0) { | 130 | if (result < 0) { |
@@ -137,19 +133,12 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset) | |||
137 | result = uwb_rc_stop_beacon(rc); | 133 | result = uwb_rc_stop_beacon(rc); |
138 | channel = -1; | 134 | channel = -1; |
139 | bpst_offset = 0; | 135 | bpst_offset = 0; |
140 | } else | 136 | } |
141 | result = 0; | ||
142 | } | 137 | } |
143 | } | 138 | } |
144 | 139 | ||
145 | if (result < 0) | 140 | if (result >= 0) |
146 | goto out_up; | 141 | rc->beaconing = channel; |
147 | rc->beaconing = channel; | ||
148 | |||
149 | uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE); | ||
150 | |||
151 | out_up: | ||
152 | mutex_unlock(&rc->uwb_dev.mutex); | ||
153 | return result; | 142 | return result; |
154 | } | 143 | } |
155 | 144 | ||
@@ -168,12 +157,6 @@ out_up: | |||
168 | * FIXME: use something faster for search than a list | 157 | * FIXME: use something faster for search than a list |
169 | */ | 158 | */ |
170 | 159 | ||
171 | struct uwb_beca uwb_beca = { | ||
172 | .list = LIST_HEAD_INIT(uwb_beca.list), | ||
173 | .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex) | ||
174 | }; | ||
175 | |||
176 | |||
177 | void uwb_bce_kfree(struct kref *_bce) | 160 | void uwb_bce_kfree(struct kref *_bce) |
178 | { | 161 | { |
179 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); | 162 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); |
@@ -185,13 +168,11 @@ void uwb_bce_kfree(struct kref *_bce) | |||
185 | 168 | ||
186 | /* Find a beacon by dev addr in the cache */ | 169 | /* Find a beacon by dev addr in the cache */ |
187 | static | 170 | static |
188 | struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) | 171 | struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc, |
172 | const struct uwb_dev_addr *dev_addr) | ||
189 | { | 173 | { |
190 | struct uwb_beca_e *bce, *next; | 174 | struct uwb_beca_e *bce, *next; |
191 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 175 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
192 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", | ||
193 | dev_addr->data[0], dev_addr->data[1], | ||
194 | bce->dev_addr.data[0], bce->dev_addr.data[1]); | ||
195 | if (!memcmp(&bce->dev_addr, dev_addr, sizeof(bce->dev_addr))) | 176 | if (!memcmp(&bce->dev_addr, dev_addr, sizeof(bce->dev_addr))) |
196 | goto out; | 177 | goto out; |
197 | } | 178 | } |
@@ -202,10 +183,11 @@ out: | |||
202 | 183 | ||
203 | /* Find a beacon by dev addr in the cache */ | 184 | /* Find a beacon by dev addr in the cache */ |
204 | static | 185 | static |
205 | struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) | 186 | struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc, |
187 | const struct uwb_mac_addr *mac_addr) | ||
206 | { | 188 | { |
207 | struct uwb_beca_e *bce, *next; | 189 | struct uwb_beca_e *bce, *next; |
208 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 190 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
209 | if (!memcmp(bce->mac_addr, mac_addr->data, | 191 | if (!memcmp(bce->mac_addr, mac_addr->data, |
210 | sizeof(struct uwb_mac_addr))) | 192 | sizeof(struct uwb_mac_addr))) |
211 | goto out; | 193 | goto out; |
@@ -229,11 +211,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | |||
229 | struct uwb_dev *found = NULL; | 211 | struct uwb_dev *found = NULL; |
230 | struct uwb_beca_e *bce; | 212 | struct uwb_beca_e *bce; |
231 | 213 | ||
232 | mutex_lock(&uwb_beca.mutex); | 214 | mutex_lock(&rc->uwb_beca.mutex); |
233 | bce = __uwb_beca_find_bydev(devaddr); | 215 | bce = __uwb_beca_find_bydev(rc, devaddr); |
234 | if (bce) | 216 | if (bce) |
235 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 217 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
236 | mutex_unlock(&uwb_beca.mutex); | 218 | mutex_unlock(&rc->uwb_beca.mutex); |
237 | 219 | ||
238 | return found; | 220 | return found; |
239 | } | 221 | } |
@@ -249,11 +231,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | |||
249 | struct uwb_dev *found = NULL; | 231 | struct uwb_dev *found = NULL; |
250 | struct uwb_beca_e *bce; | 232 | struct uwb_beca_e *bce; |
251 | 233 | ||
252 | mutex_lock(&uwb_beca.mutex); | 234 | mutex_lock(&rc->uwb_beca.mutex); |
253 | bce = __uwb_beca_find_bymac(macaddr); | 235 | bce = __uwb_beca_find_bymac(rc, macaddr); |
254 | if (bce) | 236 | if (bce) |
255 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 237 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
256 | mutex_unlock(&uwb_beca.mutex); | 238 | mutex_unlock(&rc->uwb_beca.mutex); |
257 | 239 | ||
258 | return found; | 240 | return found; |
259 | } | 241 | } |
@@ -274,7 +256,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce) | |||
274 | * @bf: Beacon frame (part of b, really) | 256 | * @bf: Beacon frame (part of b, really) |
275 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received | 257 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received |
276 | */ | 258 | */ |
277 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | 259 | static |
260 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc, | ||
261 | struct uwb_rc_evt_beacon *be, | ||
278 | struct uwb_beacon_frame *bf, | 262 | struct uwb_beacon_frame *bf, |
279 | unsigned long ts_jiffies) | 263 | unsigned long ts_jiffies) |
280 | { | 264 | { |
@@ -286,7 +270,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
286 | uwb_beca_e_init(bce); | 270 | uwb_beca_e_init(bce); |
287 | bce->ts_jiffies = ts_jiffies; | 271 | bce->ts_jiffies = ts_jiffies; |
288 | bce->uwb_dev = NULL; | 272 | bce->uwb_dev = NULL; |
289 | list_add(&bce->node, &uwb_beca.list); | 273 | list_add(&bce->node, &rc->uwb_beca.list); |
290 | return bce; | 274 | return bce; |
291 | } | 275 | } |
292 | 276 | ||
@@ -295,33 +279,32 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
295 | * | 279 | * |
296 | * Remove associated devicest too. | 280 | * Remove associated devicest too. |
297 | */ | 281 | */ |
298 | void uwb_beca_purge(void) | 282 | void uwb_beca_purge(struct uwb_rc *rc) |
299 | { | 283 | { |
300 | struct uwb_beca_e *bce, *next; | 284 | struct uwb_beca_e *bce, *next; |
301 | unsigned long expires; | 285 | unsigned long expires; |
302 | 286 | ||
303 | mutex_lock(&uwb_beca.mutex); | 287 | mutex_lock(&rc->uwb_beca.mutex); |
304 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 288 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
305 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); | 289 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); |
306 | if (time_after(jiffies, expires)) { | 290 | if (time_after(jiffies, expires)) { |
307 | uwbd_dev_offair(bce); | 291 | uwbd_dev_offair(bce); |
308 | list_del(&bce->node); | ||
309 | uwb_bce_put(bce); | ||
310 | } | 292 | } |
311 | } | 293 | } |
312 | mutex_unlock(&uwb_beca.mutex); | 294 | mutex_unlock(&rc->uwb_beca.mutex); |
313 | } | 295 | } |
314 | 296 | ||
315 | /* Clean up the whole beacon cache. Called on shutdown */ | 297 | /* Clean up the whole beacon cache. Called on shutdown */ |
316 | void uwb_beca_release(void) | 298 | void uwb_beca_release(struct uwb_rc *rc) |
317 | { | 299 | { |
318 | struct uwb_beca_e *bce, *next; | 300 | struct uwb_beca_e *bce, *next; |
319 | mutex_lock(&uwb_beca.mutex); | 301 | |
320 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 302 | mutex_lock(&rc->uwb_beca.mutex); |
303 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { | ||
321 | list_del(&bce->node); | 304 | list_del(&bce->node); |
322 | uwb_bce_put(bce); | 305 | uwb_bce_put(bce); |
323 | } | 306 | } |
324 | mutex_unlock(&uwb_beca.mutex); | 307 | mutex_unlock(&rc->uwb_beca.mutex); |
325 | } | 308 | } |
326 | 309 | ||
327 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, | 310 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, |
@@ -349,22 +332,22 @@ ssize_t uwb_bce_print_IEs(struct uwb_dev *uwb_dev, struct uwb_beca_e *bce, | |||
349 | ssize_t result = 0; | 332 | ssize_t result = 0; |
350 | struct uwb_rc_evt_beacon *be; | 333 | struct uwb_rc_evt_beacon *be; |
351 | struct uwb_beacon_frame *bf; | 334 | struct uwb_beacon_frame *bf; |
352 | struct uwb_buf_ctx ctx = { | 335 | int ies_len; |
353 | .buf = buf, | 336 | struct uwb_ie_hdr *ies; |
354 | .bytes = 0, | ||
355 | .size = size | ||
356 | }; | ||
357 | 337 | ||
358 | mutex_lock(&bce->mutex); | 338 | mutex_lock(&bce->mutex); |
339 | |||
359 | be = bce->be; | 340 | be = bce->be; |
360 | if (be == NULL) | 341 | if (be) { |
361 | goto out; | 342 | bf = (struct uwb_beacon_frame *)bce->be->BeaconInfo; |
362 | bf = (void *) be->BeaconInfo; | 343 | ies_len = be->wBeaconInfoLength - sizeof(struct uwb_beacon_frame); |
363 | uwb_ie_for_each(uwb_dev, uwb_ie_dump_hex, &ctx, | 344 | ies = (struct uwb_ie_hdr *)bf->IEData; |
364 | bf->IEData, be->wBeaconInfoLength - sizeof(*bf)); | 345 | |
365 | result = ctx.bytes; | 346 | result = uwb_ie_dump_hex(ies, ies_len, buf, size); |
366 | out: | 347 | } |
348 | |||
367 | mutex_unlock(&bce->mutex); | 349 | mutex_unlock(&bce->mutex); |
350 | |||
368 | return result; | 351 | return result; |
369 | } | 352 | } |
370 | 353 | ||
@@ -437,18 +420,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt) | |||
437 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) | 420 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) |
438 | return 0; | 421 | return 0; |
439 | 422 | ||
440 | mutex_lock(&uwb_beca.mutex); | 423 | mutex_lock(&rc->uwb_beca.mutex); |
441 | bce = __uwb_beca_find_bymac(&bf->Device_Identifier); | 424 | bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier); |
442 | if (bce == NULL) { | 425 | if (bce == NULL) { |
443 | /* Not in there, a new device is pinging */ | 426 | /* Not in there, a new device is pinging */ |
444 | uwb_beacon_print(evt->rc, be, bf); | 427 | uwb_beacon_print(evt->rc, be, bf); |
445 | bce = __uwb_beca_add(be, bf, evt->ts_jiffies); | 428 | bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies); |
446 | if (bce == NULL) { | 429 | if (bce == NULL) { |
447 | mutex_unlock(&uwb_beca.mutex); | 430 | mutex_unlock(&rc->uwb_beca.mutex); |
448 | return -ENOMEM; | 431 | return -ENOMEM; |
449 | } | 432 | } |
450 | } | 433 | } |
451 | mutex_unlock(&uwb_beca.mutex); | 434 | mutex_unlock(&rc->uwb_beca.mutex); |
452 | 435 | ||
453 | mutex_lock(&bce->mutex); | 436 | mutex_lock(&bce->mutex); |
454 | /* purge old beacon data */ | 437 | /* purge old beacon data */ |
@@ -588,19 +571,6 @@ error: | |||
588 | return result; | 571 | return result; |
589 | } | 572 | } |
590 | 573 | ||
591 | /** | ||
592 | * uwb_bg_joined - is the RC in a beacon group? | ||
593 | * @rc: the radio controller | ||
594 | * | ||
595 | * Returns true if the radio controller is in a beacon group (even if | ||
596 | * it's the sole member). | ||
597 | */ | ||
598 | int uwb_bg_joined(struct uwb_rc *rc) | ||
599 | { | ||
600 | return rc->beaconing != -1; | ||
601 | } | ||
602 | EXPORT_SYMBOL_GPL(uwb_bg_joined); | ||
603 | |||
604 | /* | 574 | /* |
605 | * Print beaconing state. | 575 | * Print beaconing state. |
606 | */ | 576 | */ |
@@ -619,9 +589,6 @@ static ssize_t uwb_rc_beacon_show(struct device *dev, | |||
619 | 589 | ||
620 | /* | 590 | /* |
621 | * Start beaconing on the specified channel, or stop beaconing. | 591 | * Start beaconing on the specified channel, or stop beaconing. |
622 | * | ||
623 | * The BPST offset of when to start searching for a beacon group to | ||
624 | * join may be specified. | ||
625 | */ | 592 | */ |
626 | static ssize_t uwb_rc_beacon_store(struct device *dev, | 593 | static ssize_t uwb_rc_beacon_store(struct device *dev, |
627 | struct device_attribute *attr, | 594 | struct device_attribute *attr, |
@@ -630,12 +597,11 @@ static ssize_t uwb_rc_beacon_store(struct device *dev, | |||
630 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); | 597 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); |
631 | struct uwb_rc *rc = uwb_dev->rc; | 598 | struct uwb_rc *rc = uwb_dev->rc; |
632 | int channel; | 599 | int channel; |
633 | unsigned bpst_offset = 0; | ||
634 | ssize_t result = -EINVAL; | 600 | ssize_t result = -EINVAL; |
635 | 601 | ||
636 | result = sscanf(buf, "%d %u\n", &channel, &bpst_offset); | 602 | result = sscanf(buf, "%d", &channel); |
637 | if (result >= 1) | 603 | if (result >= 1) |
638 | result = uwb_rc_beacon(rc, channel, bpst_offset); | 604 | result = uwb_radio_force_channel(rc, channel); |
639 | 605 | ||
640 | return result < 0 ? result : size; | 606 | return result < 0 ? result : size; |
641 | } | 607 | } |
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 521cdeb84971..da77e41de990 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #include <linux/err.h> | 53 | #include <linux/err.h> |
54 | #include <linux/kdev_t.h> | 54 | #include <linux/kdev_t.h> |
55 | #include <linux/random.h> | 55 | #include <linux/random.h> |
56 | #include <linux/uwb/debug.h> | 56 | |
57 | #include "uwb-internal.h" | 57 | #include "uwb-internal.h" |
58 | 58 | ||
59 | 59 | ||
@@ -118,7 +118,6 @@ static int __init uwb_subsys_init(void) | |||
118 | result = class_register(&uwb_rc_class); | 118 | result = class_register(&uwb_rc_class); |
119 | if (result < 0) | 119 | if (result < 0) |
120 | goto error_uwb_rc_class_register; | 120 | goto error_uwb_rc_class_register; |
121 | uwbd_start(); | ||
122 | uwb_dbg_init(); | 121 | uwb_dbg_init(); |
123 | return 0; | 122 | return 0; |
124 | 123 | ||
@@ -132,7 +131,6 @@ module_init(uwb_subsys_init); | |||
132 | static void __exit uwb_subsys_exit(void) | 131 | static void __exit uwb_subsys_exit(void) |
133 | { | 132 | { |
134 | uwb_dbg_exit(); | 133 | uwb_dbg_exit(); |
135 | uwbd_stop(); | ||
136 | class_unregister(&uwb_rc_class); | 134 | class_unregister(&uwb_rc_class); |
137 | uwb_est_destroy(); | 135 | uwb_est_destroy(); |
138 | return; | 136 | return; |
diff --git a/drivers/uwb/drp-avail.c b/drivers/uwb/drp-avail.c index 3febd8552808..40a540a5a72e 100644 --- a/drivers/uwb/drp-avail.c +++ b/drivers/uwb/drp-avail.c | |||
@@ -58,7 +58,7 @@ void uwb_drp_avail_init(struct uwb_rc *rc) | |||
58 | * | 58 | * |
59 | * avail = global & local & pending | 59 | * avail = global & local & pending |
60 | */ | 60 | */ |
61 | static void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail) | 61 | void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail) |
62 | { | 62 | { |
63 | bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); | 63 | bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS); |
64 | bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS); | 64 | bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS); |
@@ -105,6 +105,7 @@ void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas) | |||
105 | bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); | 105 | bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS); |
106 | bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); | 106 | bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS); |
107 | rc->drp_avail.ie_valid = false; | 107 | rc->drp_avail.ie_valid = false; |
108 | uwb_rsv_handle_drp_avail_change(rc); | ||
108 | } | 109 | } |
109 | 110 | ||
110 | /** | 111 | /** |
@@ -280,6 +281,7 @@ int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt) | |||
280 | mutex_lock(&rc->rsvs_mutex); | 281 | mutex_lock(&rc->rsvs_mutex); |
281 | bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS); | 282 | bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS); |
282 | rc->drp_avail.ie_valid = false; | 283 | rc->drp_avail.ie_valid = false; |
284 | uwb_rsv_handle_drp_avail_change(rc); | ||
283 | mutex_unlock(&rc->rsvs_mutex); | 285 | mutex_unlock(&rc->rsvs_mutex); |
284 | 286 | ||
285 | uwb_rsv_sched_update(rc); | 287 | uwb_rsv_sched_update(rc); |
diff --git a/drivers/uwb/drp-ie.c b/drivers/uwb/drp-ie.c index 882724c5f126..2840d7bf9e67 100644 --- a/drivers/uwb/drp-ie.c +++ b/drivers/uwb/drp-ie.c | |||
@@ -16,13 +16,102 @@ | |||
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | #include <linux/version.h> | ||
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/random.h> | 20 | #include <linux/random.h> |
22 | #include <linux/uwb.h> | 21 | #include <linux/uwb.h> |
23 | 22 | ||
24 | #include "uwb-internal.h" | 23 | #include "uwb-internal.h" |
25 | 24 | ||
25 | |||
26 | /* | ||
27 | * Return the reason code for a reservations's DRP IE. | ||
28 | */ | ||
29 | int uwb_rsv_reason_code(struct uwb_rsv *rsv) | ||
30 | { | ||
31 | static const int reason_codes[] = { | ||
32 | [UWB_RSV_STATE_O_INITIATED] = UWB_DRP_REASON_ACCEPTED, | ||
33 | [UWB_RSV_STATE_O_PENDING] = UWB_DRP_REASON_ACCEPTED, | ||
34 | [UWB_RSV_STATE_O_MODIFIED] = UWB_DRP_REASON_MODIFIED, | ||
35 | [UWB_RSV_STATE_O_ESTABLISHED] = UWB_DRP_REASON_ACCEPTED, | ||
36 | [UWB_RSV_STATE_O_TO_BE_MOVED] = UWB_DRP_REASON_ACCEPTED, | ||
37 | [UWB_RSV_STATE_O_MOVE_COMBINING] = UWB_DRP_REASON_MODIFIED, | ||
38 | [UWB_RSV_STATE_O_MOVE_REDUCING] = UWB_DRP_REASON_MODIFIED, | ||
39 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = UWB_DRP_REASON_ACCEPTED, | ||
40 | [UWB_RSV_STATE_T_ACCEPTED] = UWB_DRP_REASON_ACCEPTED, | ||
41 | [UWB_RSV_STATE_T_CONFLICT] = UWB_DRP_REASON_CONFLICT, | ||
42 | [UWB_RSV_STATE_T_PENDING] = UWB_DRP_REASON_PENDING, | ||
43 | [UWB_RSV_STATE_T_DENIED] = UWB_DRP_REASON_DENIED, | ||
44 | [UWB_RSV_STATE_T_RESIZED] = UWB_DRP_REASON_ACCEPTED, | ||
45 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED, | ||
46 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT, | ||
47 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = UWB_DRP_REASON_PENDING, | ||
48 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = UWB_DRP_REASON_DENIED, | ||
49 | }; | ||
50 | |||
51 | return reason_codes[rsv->state]; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Return the reason code for a reservations's companion DRP IE . | ||
56 | */ | ||
57 | int uwb_rsv_companion_reason_code(struct uwb_rsv *rsv) | ||
58 | { | ||
59 | static const int companion_reason_codes[] = { | ||
60 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = UWB_DRP_REASON_ACCEPTED, | ||
61 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = UWB_DRP_REASON_ACCEPTED, | ||
62 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = UWB_DRP_REASON_CONFLICT, | ||
63 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = UWB_DRP_REASON_PENDING, | ||
64 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = UWB_DRP_REASON_DENIED, | ||
65 | }; | ||
66 | |||
67 | return companion_reason_codes[rsv->state]; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Return the status bit for a reservations's DRP IE. | ||
72 | */ | ||
73 | int uwb_rsv_status(struct uwb_rsv *rsv) | ||
74 | { | ||
75 | static const int statuses[] = { | ||
76 | [UWB_RSV_STATE_O_INITIATED] = 0, | ||
77 | [UWB_RSV_STATE_O_PENDING] = 0, | ||
78 | [UWB_RSV_STATE_O_MODIFIED] = 1, | ||
79 | [UWB_RSV_STATE_O_ESTABLISHED] = 1, | ||
80 | [UWB_RSV_STATE_O_TO_BE_MOVED] = 0, | ||
81 | [UWB_RSV_STATE_O_MOVE_COMBINING] = 1, | ||
82 | [UWB_RSV_STATE_O_MOVE_REDUCING] = 1, | ||
83 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = 1, | ||
84 | [UWB_RSV_STATE_T_ACCEPTED] = 1, | ||
85 | [UWB_RSV_STATE_T_CONFLICT] = 0, | ||
86 | [UWB_RSV_STATE_T_PENDING] = 0, | ||
87 | [UWB_RSV_STATE_T_DENIED] = 0, | ||
88 | [UWB_RSV_STATE_T_RESIZED] = 1, | ||
89 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1, | ||
90 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 1, | ||
91 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = 1, | ||
92 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = 1, | ||
93 | |||
94 | }; | ||
95 | |||
96 | return statuses[rsv->state]; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Return the status bit for a reservations's companion DRP IE . | ||
101 | */ | ||
102 | int uwb_rsv_companion_status(struct uwb_rsv *rsv) | ||
103 | { | ||
104 | static const int companion_statuses[] = { | ||
105 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = 0, | ||
106 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = 1, | ||
107 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = 0, | ||
108 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = 0, | ||
109 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = 0, | ||
110 | }; | ||
111 | |||
112 | return companion_statuses[rsv->state]; | ||
113 | } | ||
114 | |||
26 | /* | 115 | /* |
27 | * Allocate a DRP IE. | 116 | * Allocate a DRP IE. |
28 | * | 117 | * |
@@ -34,16 +123,12 @@ | |||
34 | static struct uwb_ie_drp *uwb_drp_ie_alloc(void) | 123 | static struct uwb_ie_drp *uwb_drp_ie_alloc(void) |
35 | { | 124 | { |
36 | struct uwb_ie_drp *drp_ie; | 125 | struct uwb_ie_drp *drp_ie; |
37 | unsigned tiebreaker; | ||
38 | 126 | ||
39 | drp_ie = kzalloc(sizeof(struct uwb_ie_drp) + | 127 | drp_ie = kzalloc(sizeof(struct uwb_ie_drp) + |
40 | UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc), | 128 | UWB_NUM_ZONES * sizeof(struct uwb_drp_alloc), |
41 | GFP_KERNEL); | 129 | GFP_KERNEL); |
42 | if (drp_ie) { | 130 | if (drp_ie) { |
43 | drp_ie->hdr.element_id = UWB_IE_DRP; | 131 | drp_ie->hdr.element_id = UWB_IE_DRP; |
44 | |||
45 | get_random_bytes(&tiebreaker, sizeof(unsigned)); | ||
46 | uwb_ie_drp_set_tiebreaker(drp_ie, tiebreaker & 1); | ||
47 | } | 132 | } |
48 | return drp_ie; | 133 | return drp_ie; |
49 | } | 134 | } |
@@ -104,43 +189,17 @@ static void uwb_drp_ie_from_bm(struct uwb_ie_drp *drp_ie, | |||
104 | */ | 189 | */ |
105 | int uwb_drp_ie_update(struct uwb_rsv *rsv) | 190 | int uwb_drp_ie_update(struct uwb_rsv *rsv) |
106 | { | 191 | { |
107 | struct device *dev = &rsv->rc->uwb_dev.dev; | ||
108 | struct uwb_ie_drp *drp_ie; | 192 | struct uwb_ie_drp *drp_ie; |
109 | int reason_code, status; | 193 | struct uwb_rsv_move *mv; |
194 | int unsafe; | ||
110 | 195 | ||
111 | switch (rsv->state) { | 196 | if (rsv->state == UWB_RSV_STATE_NONE) { |
112 | case UWB_RSV_STATE_NONE: | ||
113 | kfree(rsv->drp_ie); | 197 | kfree(rsv->drp_ie); |
114 | rsv->drp_ie = NULL; | 198 | rsv->drp_ie = NULL; |
115 | return 0; | 199 | return 0; |
116 | case UWB_RSV_STATE_O_INITIATED: | ||
117 | reason_code = UWB_DRP_REASON_ACCEPTED; | ||
118 | status = 0; | ||
119 | break; | ||
120 | case UWB_RSV_STATE_O_PENDING: | ||
121 | reason_code = UWB_DRP_REASON_ACCEPTED; | ||
122 | status = 0; | ||
123 | break; | ||
124 | case UWB_RSV_STATE_O_MODIFIED: | ||
125 | reason_code = UWB_DRP_REASON_MODIFIED; | ||
126 | status = 1; | ||
127 | break; | ||
128 | case UWB_RSV_STATE_O_ESTABLISHED: | ||
129 | reason_code = UWB_DRP_REASON_ACCEPTED; | ||
130 | status = 1; | ||
131 | break; | ||
132 | case UWB_RSV_STATE_T_ACCEPTED: | ||
133 | reason_code = UWB_DRP_REASON_ACCEPTED; | ||
134 | status = 1; | ||
135 | break; | ||
136 | case UWB_RSV_STATE_T_DENIED: | ||
137 | reason_code = UWB_DRP_REASON_DENIED; | ||
138 | status = 0; | ||
139 | break; | ||
140 | default: | ||
141 | dev_dbg(dev, "rsv with unhandled state (%d)\n", rsv->state); | ||
142 | return -EINVAL; | ||
143 | } | 200 | } |
201 | |||
202 | unsafe = rsv->mas.unsafe ? 1 : 0; | ||
144 | 203 | ||
145 | if (rsv->drp_ie == NULL) { | 204 | if (rsv->drp_ie == NULL) { |
146 | rsv->drp_ie = uwb_drp_ie_alloc(); | 205 | rsv->drp_ie = uwb_drp_ie_alloc(); |
@@ -149,9 +208,11 @@ int uwb_drp_ie_update(struct uwb_rsv *rsv) | |||
149 | } | 208 | } |
150 | drp_ie = rsv->drp_ie; | 209 | drp_ie = rsv->drp_ie; |
151 | 210 | ||
211 | uwb_ie_drp_set_unsafe(drp_ie, unsafe); | ||
212 | uwb_ie_drp_set_tiebreaker(drp_ie, rsv->tiebreaker); | ||
152 | uwb_ie_drp_set_owner(drp_ie, uwb_rsv_is_owner(rsv)); | 213 | uwb_ie_drp_set_owner(drp_ie, uwb_rsv_is_owner(rsv)); |
153 | uwb_ie_drp_set_status(drp_ie, status); | 214 | uwb_ie_drp_set_status(drp_ie, uwb_rsv_status(rsv)); |
154 | uwb_ie_drp_set_reason_code(drp_ie, reason_code); | 215 | uwb_ie_drp_set_reason_code(drp_ie, uwb_rsv_reason_code(rsv)); |
155 | uwb_ie_drp_set_stream_index(drp_ie, rsv->stream); | 216 | uwb_ie_drp_set_stream_index(drp_ie, rsv->stream); |
156 | uwb_ie_drp_set_type(drp_ie, rsv->type); | 217 | uwb_ie_drp_set_type(drp_ie, rsv->type); |
157 | 218 | ||
@@ -169,6 +230,27 @@ int uwb_drp_ie_update(struct uwb_rsv *rsv) | |||
169 | 230 | ||
170 | uwb_drp_ie_from_bm(drp_ie, &rsv->mas); | 231 | uwb_drp_ie_from_bm(drp_ie, &rsv->mas); |
171 | 232 | ||
233 | if (uwb_rsv_has_two_drp_ies(rsv)) { | ||
234 | mv = &rsv->mv; | ||
235 | if (mv->companion_drp_ie == NULL) { | ||
236 | mv->companion_drp_ie = uwb_drp_ie_alloc(); | ||
237 | if (mv->companion_drp_ie == NULL) | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | drp_ie = mv->companion_drp_ie; | ||
241 | |||
242 | /* keep all the same configuration of the main drp_ie */ | ||
243 | memcpy(drp_ie, rsv->drp_ie, sizeof(struct uwb_ie_drp)); | ||
244 | |||
245 | |||
246 | /* FIXME: handle properly the unsafe bit */ | ||
247 | uwb_ie_drp_set_unsafe(drp_ie, 1); | ||
248 | uwb_ie_drp_set_status(drp_ie, uwb_rsv_companion_status(rsv)); | ||
249 | uwb_ie_drp_set_reason_code(drp_ie, uwb_rsv_companion_reason_code(rsv)); | ||
250 | |||
251 | uwb_drp_ie_from_bm(drp_ie, &mv->companion_mas); | ||
252 | } | ||
253 | |||
172 | rsv->ie_valid = true; | 254 | rsv->ie_valid = true; |
173 | return 0; | 255 | return 0; |
174 | } | 256 | } |
@@ -219,6 +301,8 @@ void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie) | |||
219 | u8 zone; | 301 | u8 zone; |
220 | u16 zone_mask; | 302 | u16 zone_mask; |
221 | 303 | ||
304 | bitmap_zero(bm->bm, UWB_NUM_MAS); | ||
305 | |||
222 | for (cnt = 0; cnt < numallocs; cnt++) { | 306 | for (cnt = 0; cnt < numallocs; cnt++) { |
223 | alloc = &drp_ie->allocs[cnt]; | 307 | alloc = &drp_ie->allocs[cnt]; |
224 | zone_bm = le16_to_cpu(alloc->zone_bm); | 308 | zone_bm = le16_to_cpu(alloc->zone_bm); |
@@ -230,3 +314,4 @@ void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie) | |||
230 | } | 314 | } |
231 | } | 315 | } |
232 | } | 316 | } |
317 | |||
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index c0b1e5e2bd08..2b4f9406789d 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c | |||
@@ -23,6 +23,59 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include "uwb-internal.h" | 24 | #include "uwb-internal.h" |
25 | 25 | ||
26 | |||
27 | /* DRP Conflict Actions ([ECMA-368 2nd Edition] 17.4.6) */ | ||
28 | enum uwb_drp_conflict_action { | ||
29 | /* Reservation is mantained, no action needed */ | ||
30 | UWB_DRP_CONFLICT_MANTAIN = 0, | ||
31 | |||
32 | /* the device shall not transmit frames in conflicting MASs in | ||
33 | * the following superframe. If the device is the reservation | ||
34 | * target, it shall also set the Reason Code in its DRP IE to | ||
35 | * Conflict in its beacon in the following superframe. | ||
36 | */ | ||
37 | UWB_DRP_CONFLICT_ACT1, | ||
38 | |||
39 | /* the device shall not set the Reservation Status bit to ONE | ||
40 | * and shall not transmit frames in conflicting MASs. If the | ||
41 | * device is the reservation target, it shall also set the | ||
42 | * Reason Code in its DRP IE to Conflict. | ||
43 | */ | ||
44 | UWB_DRP_CONFLICT_ACT2, | ||
45 | |||
46 | /* the device shall not transmit frames in conflicting MASs in | ||
47 | * the following superframe. It shall remove the conflicting | ||
48 | * MASs from the reservation or set the Reservation Status to | ||
49 | * ZERO in its beacon in the following superframe. If the | ||
50 | * device is the reservation target, it shall also set the | ||
51 | * Reason Code in its DRP IE to Conflict. | ||
52 | */ | ||
53 | UWB_DRP_CONFLICT_ACT3, | ||
54 | }; | ||
55 | |||
56 | |||
57 | static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, | ||
58 | struct uwb_rceb *reply, ssize_t reply_size) | ||
59 | { | ||
60 | struct uwb_rc_evt_set_drp_ie *r = (struct uwb_rc_evt_set_drp_ie *)reply; | ||
61 | |||
62 | if (r != NULL) { | ||
63 | if (r->bResultCode != UWB_RC_RES_SUCCESS) | ||
64 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE failed: %s (%d)\n", | ||
65 | uwb_rc_strerror(r->bResultCode), r->bResultCode); | ||
66 | } else | ||
67 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); | ||
68 | |||
69 | spin_lock(&rc->rsvs_lock); | ||
70 | if (rc->set_drp_ie_pending > 1) { | ||
71 | rc->set_drp_ie_pending = 0; | ||
72 | uwb_rsv_queue_update(rc); | ||
73 | } else { | ||
74 | rc->set_drp_ie_pending = 0; | ||
75 | } | ||
76 | spin_unlock(&rc->rsvs_lock); | ||
77 | } | ||
78 | |||
26 | /** | 79 | /** |
27 | * Construct and send the SET DRP IE | 80 | * Construct and send the SET DRP IE |
28 | * | 81 | * |
@@ -37,28 +90,32 @@ | |||
37 | * | 90 | * |
38 | * A DRP Availability IE is appended. | 91 | * A DRP Availability IE is appended. |
39 | * | 92 | * |
40 | * rc->uwb_dev.mutex is held | 93 | * rc->rsvs_mutex is held |
41 | * | 94 | * |
42 | * FIXME We currently ignore the returned value indicating the remaining space | 95 | * FIXME We currently ignore the returned value indicating the remaining space |
43 | * in beacon. This could be used to deny reservation requests earlier if | 96 | * in beacon. This could be used to deny reservation requests earlier if |
44 | * determined that they would cause the beacon space to be exceeded. | 97 | * determined that they would cause the beacon space to be exceeded. |
45 | */ | 98 | */ |
46 | static | 99 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) |
47 | int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc) | ||
48 | { | 100 | { |
49 | int result; | 101 | int result; |
50 | struct device *dev = &rc->uwb_dev.dev; | ||
51 | struct uwb_rc_cmd_set_drp_ie *cmd; | 102 | struct uwb_rc_cmd_set_drp_ie *cmd; |
52 | struct uwb_rc_evt_set_drp_ie reply; | ||
53 | struct uwb_rsv *rsv; | 103 | struct uwb_rsv *rsv; |
104 | struct uwb_rsv_move *mv; | ||
54 | int num_bytes = 0; | 105 | int num_bytes = 0; |
55 | u8 *IEDataptr; | 106 | u8 *IEDataptr; |
56 | 107 | ||
57 | result = -ENOMEM; | 108 | result = -ENOMEM; |
58 | /* First traverse all reservations to determine memory needed. */ | 109 | /* First traverse all reservations to determine memory needed. */ |
59 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | 110 | list_for_each_entry(rsv, &rc->reservations, rc_node) { |
60 | if (rsv->drp_ie != NULL) | 111 | if (rsv->drp_ie != NULL) { |
61 | num_bytes += rsv->drp_ie->hdr.length + 2; | 112 | num_bytes += rsv->drp_ie->hdr.length + 2; |
113 | if (uwb_rsv_has_two_drp_ies(rsv) && | ||
114 | (rsv->mv.companion_drp_ie != NULL)) { | ||
115 | mv = &rsv->mv; | ||
116 | num_bytes += mv->companion_drp_ie->hdr.length + 2; | ||
117 | } | ||
118 | } | ||
62 | } | 119 | } |
63 | num_bytes += sizeof(rc->drp_avail.ie); | 120 | num_bytes += sizeof(rc->drp_avail.ie); |
64 | cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL); | 121 | cmd = kzalloc(sizeof(*cmd) + num_bytes, GFP_KERNEL); |
@@ -69,128 +126,322 @@ int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc) | |||
69 | cmd->wIELength = num_bytes; | 126 | cmd->wIELength = num_bytes; |
70 | IEDataptr = (u8 *)&cmd->IEData[0]; | 127 | IEDataptr = (u8 *)&cmd->IEData[0]; |
71 | 128 | ||
129 | /* FIXME: DRV avail IE is not always needed */ | ||
130 | /* put DRP avail IE first */ | ||
131 | memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie)); | ||
132 | IEDataptr += sizeof(struct uwb_ie_drp_avail); | ||
133 | |||
72 | /* Next traverse all reservations to place IEs in allocated memory. */ | 134 | /* Next traverse all reservations to place IEs in allocated memory. */ |
73 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | 135 | list_for_each_entry(rsv, &rc->reservations, rc_node) { |
74 | if (rsv->drp_ie != NULL) { | 136 | if (rsv->drp_ie != NULL) { |
75 | memcpy(IEDataptr, rsv->drp_ie, | 137 | memcpy(IEDataptr, rsv->drp_ie, |
76 | rsv->drp_ie->hdr.length + 2); | 138 | rsv->drp_ie->hdr.length + 2); |
77 | IEDataptr += rsv->drp_ie->hdr.length + 2; | 139 | IEDataptr += rsv->drp_ie->hdr.length + 2; |
140 | |||
141 | if (uwb_rsv_has_two_drp_ies(rsv) && | ||
142 | (rsv->mv.companion_drp_ie != NULL)) { | ||
143 | mv = &rsv->mv; | ||
144 | memcpy(IEDataptr, mv->companion_drp_ie, | ||
145 | mv->companion_drp_ie->hdr.length + 2); | ||
146 | IEDataptr += mv->companion_drp_ie->hdr.length + 2; | ||
147 | } | ||
78 | } | 148 | } |
79 | } | 149 | } |
80 | memcpy(IEDataptr, &rc->drp_avail.ie, sizeof(rc->drp_avail.ie)); | ||
81 | 150 | ||
82 | reply.rceb.bEventType = UWB_RC_CET_GENERAL; | 151 | result = uwb_rc_cmd_async(rc, "SET-DRP-IE", &cmd->rccb, sizeof(*cmd) + num_bytes, |
83 | reply.rceb.wEvent = UWB_RC_CMD_SET_DRP_IE; | 152 | UWB_RC_CET_GENERAL, UWB_RC_CMD_SET_DRP_IE, |
84 | result = uwb_rc_cmd(rc, "SET-DRP-IE", &cmd->rccb, | 153 | uwb_rc_set_drp_cmd_done, NULL); |
85 | sizeof(*cmd) + num_bytes, &reply.rceb, | 154 | |
86 | sizeof(reply)); | 155 | rc->set_drp_ie_pending = 1; |
87 | if (result < 0) | 156 | |
88 | goto error_cmd; | ||
89 | result = le16_to_cpu(reply.wRemainingSpace); | ||
90 | if (reply.bResultCode != UWB_RC_RES_SUCCESS) { | ||
91 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: command execution " | ||
92 | "failed: %s (%d). RemainingSpace in beacon " | ||
93 | "= %d\n", uwb_rc_strerror(reply.bResultCode), | ||
94 | reply.bResultCode, result); | ||
95 | result = -EIO; | ||
96 | } else { | ||
97 | dev_dbg(dev, "SET-DRP-IE sent. RemainingSpace in beacon " | ||
98 | "= %d.\n", result); | ||
99 | result = 0; | ||
100 | } | ||
101 | error_cmd: | ||
102 | kfree(cmd); | 157 | kfree(cmd); |
103 | error: | 158 | error: |
104 | return result; | 159 | return result; |
105 | |||
106 | } | 160 | } |
107 | /** | 161 | |
108 | * Send all DRP IEs associated with this host | 162 | /* |
109 | * | 163 | * Evaluate the action to perform using conflict resolution rules |
110 | * @returns: >= 0 number of bytes still available in the beacon | ||
111 | * < 0 errno code on error. | ||
112 | * | 164 | * |
113 | * As per the protocol we obtain the host controller device lock to access | 165 | * Return a uwb_drp_conflict_action. |
114 | * bandwidth structures. | ||
115 | */ | 166 | */ |
116 | int uwb_rc_send_all_drp_ie(struct uwb_rc *rc) | 167 | static int evaluate_conflict_action(struct uwb_ie_drp *ext_drp_ie, int ext_beacon_slot, |
168 | struct uwb_rsv *rsv, int our_status) | ||
117 | { | 169 | { |
118 | int result; | 170 | int our_tie_breaker = rsv->tiebreaker; |
171 | int our_type = rsv->type; | ||
172 | int our_beacon_slot = rsv->rc->uwb_dev.beacon_slot; | ||
173 | |||
174 | int ext_tie_breaker = uwb_ie_drp_tiebreaker(ext_drp_ie); | ||
175 | int ext_status = uwb_ie_drp_status(ext_drp_ie); | ||
176 | int ext_type = uwb_ie_drp_type(ext_drp_ie); | ||
177 | |||
178 | |||
179 | /* [ECMA-368 2nd Edition] 17.4.6 */ | ||
180 | if (ext_type == UWB_DRP_TYPE_PCA && our_type == UWB_DRP_TYPE_PCA) { | ||
181 | return UWB_DRP_CONFLICT_MANTAIN; | ||
182 | } | ||
119 | 183 | ||
120 | mutex_lock(&rc->uwb_dev.mutex); | 184 | /* [ECMA-368 2nd Edition] 17.4.6-1 */ |
121 | result = uwb_rc_gen_send_drp_ie(rc); | 185 | if (our_type == UWB_DRP_TYPE_ALIEN_BP) { |
122 | mutex_unlock(&rc->uwb_dev.mutex); | 186 | return UWB_DRP_CONFLICT_MANTAIN; |
123 | return result; | 187 | } |
188 | |||
189 | /* [ECMA-368 2nd Edition] 17.4.6-2 */ | ||
190 | if (ext_type == UWB_DRP_TYPE_ALIEN_BP) { | ||
191 | /* here we know our_type != UWB_DRP_TYPE_ALIEN_BP */ | ||
192 | return UWB_DRP_CONFLICT_ACT1; | ||
193 | } | ||
194 | |||
195 | /* [ECMA-368 2nd Edition] 17.4.6-3 */ | ||
196 | if (our_status == 0 && ext_status == 1) { | ||
197 | return UWB_DRP_CONFLICT_ACT2; | ||
198 | } | ||
199 | |||
200 | /* [ECMA-368 2nd Edition] 17.4.6-4 */ | ||
201 | if (our_status == 1 && ext_status == 0) { | ||
202 | return UWB_DRP_CONFLICT_MANTAIN; | ||
203 | } | ||
204 | |||
205 | /* [ECMA-368 2nd Edition] 17.4.6-5a */ | ||
206 | if (our_tie_breaker == ext_tie_breaker && | ||
207 | our_beacon_slot < ext_beacon_slot) { | ||
208 | return UWB_DRP_CONFLICT_MANTAIN; | ||
209 | } | ||
210 | |||
211 | /* [ECMA-368 2nd Edition] 17.4.6-5b */ | ||
212 | if (our_tie_breaker != ext_tie_breaker && | ||
213 | our_beacon_slot > ext_beacon_slot) { | ||
214 | return UWB_DRP_CONFLICT_MANTAIN; | ||
215 | } | ||
216 | |||
217 | if (our_status == 0) { | ||
218 | if (our_tie_breaker == ext_tie_breaker) { | ||
219 | /* [ECMA-368 2nd Edition] 17.4.6-6a */ | ||
220 | if (our_beacon_slot > ext_beacon_slot) { | ||
221 | return UWB_DRP_CONFLICT_ACT2; | ||
222 | } | ||
223 | } else { | ||
224 | /* [ECMA-368 2nd Edition] 17.4.6-6b */ | ||
225 | if (our_beacon_slot < ext_beacon_slot) { | ||
226 | return UWB_DRP_CONFLICT_ACT2; | ||
227 | } | ||
228 | } | ||
229 | } else { | ||
230 | if (our_tie_breaker == ext_tie_breaker) { | ||
231 | /* [ECMA-368 2nd Edition] 17.4.6-7a */ | ||
232 | if (our_beacon_slot > ext_beacon_slot) { | ||
233 | return UWB_DRP_CONFLICT_ACT3; | ||
234 | } | ||
235 | } else { | ||
236 | /* [ECMA-368 2nd Edition] 17.4.6-7b */ | ||
237 | if (our_beacon_slot < ext_beacon_slot) { | ||
238 | return UWB_DRP_CONFLICT_ACT3; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | return UWB_DRP_CONFLICT_MANTAIN; | ||
124 | } | 243 | } |
125 | 244 | ||
126 | void uwb_drp_handle_timeout(struct uwb_rsv *rsv) | 245 | static void handle_conflict_normal(struct uwb_ie_drp *drp_ie, |
246 | int ext_beacon_slot, | ||
247 | struct uwb_rsv *rsv, | ||
248 | struct uwb_mas_bm *conflicting_mas) | ||
127 | { | 249 | { |
128 | struct device *dev = &rsv->rc->uwb_dev.dev; | 250 | struct uwb_rc *rc = rsv->rc; |
251 | struct uwb_rsv_move *mv = &rsv->mv; | ||
252 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
253 | int action; | ||
254 | |||
255 | action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, uwb_rsv_status(rsv)); | ||
256 | |||
257 | if (uwb_rsv_is_owner(rsv)) { | ||
258 | switch(action) { | ||
259 | case UWB_DRP_CONFLICT_ACT2: | ||
260 | /* try move */ | ||
261 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_TO_BE_MOVED); | ||
262 | if (bow->can_reserve_extra_mases == false) | ||
263 | uwb_rsv_backoff_win_increment(rc); | ||
264 | |||
265 | break; | ||
266 | case UWB_DRP_CONFLICT_ACT3: | ||
267 | uwb_rsv_backoff_win_increment(rc); | ||
268 | /* drop some mases with reason modified */ | ||
269 | /* put in the companion the mases to be dropped */ | ||
270 | bitmap_and(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS); | ||
271 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
272 | default: | ||
273 | break; | ||
274 | } | ||
275 | } else { | ||
276 | switch(action) { | ||
277 | case UWB_DRP_CONFLICT_ACT2: | ||
278 | case UWB_DRP_CONFLICT_ACT3: | ||
279 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT); | ||
280 | default: | ||
281 | break; | ||
282 | } | ||
129 | 283 | ||
130 | dev_dbg(dev, "reservation timeout in state %s (%d)\n", | 284 | } |
131 | uwb_rsv_state_str(rsv->state), rsv->state); | 285 | |
286 | } | ||
132 | 287 | ||
133 | switch (rsv->state) { | 288 | static void handle_conflict_expanding(struct uwb_ie_drp *drp_ie, int ext_beacon_slot, |
134 | case UWB_RSV_STATE_O_INITIATED: | 289 | struct uwb_rsv *rsv, bool companion_only, |
135 | if (rsv->is_multicast) { | 290 | struct uwb_mas_bm *conflicting_mas) |
136 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | 291 | { |
137 | return; | 292 | struct uwb_rc *rc = rsv->rc; |
293 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
294 | struct uwb_rsv_move *mv = &rsv->mv; | ||
295 | int action; | ||
296 | |||
297 | if (companion_only) { | ||
298 | /* status of companion is 0 at this point */ | ||
299 | action = evaluate_conflict_action(drp_ie, ext_beacon_slot, rsv, 0); | ||
300 | if (uwb_rsv_is_owner(rsv)) { | ||
301 | switch(action) { | ||
302 | case UWB_DRP_CONFLICT_ACT2: | ||
303 | case UWB_DRP_CONFLICT_ACT3: | ||
304 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
305 | rsv->needs_release_companion_mas = false; | ||
306 | if (bow->can_reserve_extra_mases == false) | ||
307 | uwb_rsv_backoff_win_increment(rc); | ||
308 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); | ||
309 | } | ||
310 | } else { /* rsv is target */ | ||
311 | switch(action) { | ||
312 | case UWB_DRP_CONFLICT_ACT2: | ||
313 | case UWB_DRP_CONFLICT_ACT3: | ||
314 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_CONFLICT); | ||
315 | /* send_drp_avail_ie = true; */ | ||
316 | } | ||
138 | } | 317 | } |
139 | break; | 318 | } else { /* also base part of the reservation is conflicting */ |
140 | case UWB_RSV_STATE_O_ESTABLISHED: | 319 | if (uwb_rsv_is_owner(rsv)) { |
141 | if (rsv->is_multicast) | 320 | uwb_rsv_backoff_win_increment(rc); |
142 | return; | 321 | /* remove companion part */ |
143 | break; | 322 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); |
144 | default: | 323 | |
145 | break; | 324 | /* drop some mases with reason modified */ |
325 | |||
326 | /* put in the companion the mases to be dropped */ | ||
327 | bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS); | ||
328 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
329 | } else { /* it is a target rsv */ | ||
330 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT); | ||
331 | /* send_drp_avail_ie = true; */ | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void uwb_drp_handle_conflict_rsv(struct uwb_rc *rc, struct uwb_rsv *rsv, | ||
337 | struct uwb_rc_evt_drp *drp_evt, | ||
338 | struct uwb_ie_drp *drp_ie, | ||
339 | struct uwb_mas_bm *conflicting_mas) | ||
340 | { | ||
341 | struct uwb_rsv_move *mv; | ||
342 | |||
343 | /* check if the conflicting reservation has two drp_ies */ | ||
344 | if (uwb_rsv_has_two_drp_ies(rsv)) { | ||
345 | mv = &rsv->mv; | ||
346 | if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
347 | handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number, | ||
348 | rsv, false, conflicting_mas); | ||
349 | } else { | ||
350 | if (bitmap_intersects(mv->companion_mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
351 | handle_conflict_expanding(drp_ie, drp_evt->beacon_slot_number, | ||
352 | rsv, true, conflicting_mas); | ||
353 | } | ||
354 | } | ||
355 | } else if (bitmap_intersects(rsv->mas.bm, conflicting_mas->bm, UWB_NUM_MAS)) { | ||
356 | handle_conflict_normal(drp_ie, drp_evt->beacon_slot_number, rsv, conflicting_mas); | ||
146 | } | 357 | } |
147 | uwb_rsv_remove(rsv); | ||
148 | } | 358 | } |
149 | 359 | ||
360 | static void uwb_drp_handle_all_conflict_rsv(struct uwb_rc *rc, | ||
361 | struct uwb_rc_evt_drp *drp_evt, | ||
362 | struct uwb_ie_drp *drp_ie, | ||
363 | struct uwb_mas_bm *conflicting_mas) | ||
364 | { | ||
365 | struct uwb_rsv *rsv; | ||
366 | |||
367 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
368 | uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, conflicting_mas); | ||
369 | } | ||
370 | } | ||
371 | |||
150 | /* | 372 | /* |
151 | * Based on the DRP IE, transition a target reservation to a new | 373 | * Based on the DRP IE, transition a target reservation to a new |
152 | * state. | 374 | * state. |
153 | */ | 375 | */ |
154 | static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, | 376 | static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, |
155 | struct uwb_ie_drp *drp_ie) | 377 | struct uwb_ie_drp *drp_ie, struct uwb_rc_evt_drp *drp_evt) |
156 | { | 378 | { |
157 | struct device *dev = &rc->uwb_dev.dev; | 379 | struct device *dev = &rc->uwb_dev.dev; |
380 | struct uwb_rsv_move *mv = &rsv->mv; | ||
158 | int status; | 381 | int status; |
159 | enum uwb_drp_reason reason_code; | 382 | enum uwb_drp_reason reason_code; |
160 | 383 | struct uwb_mas_bm mas; | |
384 | |||
161 | status = uwb_ie_drp_status(drp_ie); | 385 | status = uwb_ie_drp_status(drp_ie); |
162 | reason_code = uwb_ie_drp_reason_code(drp_ie); | 386 | reason_code = uwb_ie_drp_reason_code(drp_ie); |
387 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
163 | 388 | ||
164 | if (status) { | 389 | switch (reason_code) { |
165 | switch (reason_code) { | 390 | case UWB_DRP_REASON_ACCEPTED: |
166 | case UWB_DRP_REASON_ACCEPTED: | 391 | |
167 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | 392 | if (rsv->state == UWB_RSV_STATE_T_CONFLICT) { |
168 | break; | 393 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_CONFLICT); |
169 | case UWB_DRP_REASON_MODIFIED: | ||
170 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | ||
171 | reason_code, status); | ||
172 | break; | 394 | break; |
173 | default: | ||
174 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
175 | reason_code, status); | ||
176 | } | 395 | } |
177 | } else { | 396 | |
178 | switch (reason_code) { | 397 | if (rsv->state == UWB_RSV_STATE_T_EXPANDING_ACCEPTED) { |
179 | case UWB_DRP_REASON_ACCEPTED: | 398 | /* drp_ie is companion */ |
180 | /* New reservations are handled in uwb_rsv_find(). */ | 399 | if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) |
181 | break; | 400 | /* stroke companion */ |
182 | case UWB_DRP_REASON_DENIED: | 401 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); |
183 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 402 | } else { |
184 | break; | 403 | if (!bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) { |
185 | case UWB_DRP_REASON_CONFLICT: | 404 | if (uwb_drp_avail_reserve_pending(rc, &mas) == -EBUSY) { |
186 | case UWB_DRP_REASON_MODIFIED: | 405 | /* FIXME: there is a conflict, find |
187 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 406 | * the conflicting reservations and |
188 | reason_code, status); | 407 | * take a sensible action. Consider |
408 | * that in drp_ie there is the | ||
409 | * "neighbour" */ | ||
410 | uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas); | ||
411 | } else { | ||
412 | /* accept the extra reservation */ | ||
413 | bitmap_copy(mv->companion_mas.bm, mas.bm, UWB_NUM_MAS); | ||
414 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); | ||
415 | } | ||
416 | } else { | ||
417 | if (status) { | ||
418 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | } | ||
423 | break; | ||
424 | |||
425 | case UWB_DRP_REASON_MODIFIED: | ||
426 | /* check to see if we have already modified the reservation */ | ||
427 | if (bitmap_equal(rsv->mas.bm, mas.bm, UWB_NUM_MAS)) { | ||
428 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | ||
189 | break; | 429 | break; |
190 | default: | ||
191 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
192 | reason_code, status); | ||
193 | } | 430 | } |
431 | |||
432 | /* find if the owner wants to expand or reduce */ | ||
433 | if (bitmap_subset(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
434 | /* owner is reducing */ | ||
435 | bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mas.bm, UWB_NUM_MAS); | ||
436 | uwb_drp_avail_release(rsv->rc, &mv->companion_mas); | ||
437 | } | ||
438 | |||
439 | bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS); | ||
440 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_RESIZED); | ||
441 | break; | ||
442 | default: | ||
443 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | ||
444 | reason_code, status); | ||
194 | } | 445 | } |
195 | } | 446 | } |
196 | 447 | ||
@@ -199,23 +450,60 @@ static void uwb_drp_process_target(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
199 | * state. | 450 | * state. |
200 | */ | 451 | */ |
201 | static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | 452 | static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, |
202 | struct uwb_ie_drp *drp_ie) | 453 | struct uwb_dev *src, struct uwb_ie_drp *drp_ie, |
454 | struct uwb_rc_evt_drp *drp_evt) | ||
203 | { | 455 | { |
204 | struct device *dev = &rc->uwb_dev.dev; | 456 | struct device *dev = &rc->uwb_dev.dev; |
457 | struct uwb_rsv_move *mv = &rsv->mv; | ||
205 | int status; | 458 | int status; |
206 | enum uwb_drp_reason reason_code; | 459 | enum uwb_drp_reason reason_code; |
460 | struct uwb_mas_bm mas; | ||
207 | 461 | ||
208 | status = uwb_ie_drp_status(drp_ie); | 462 | status = uwb_ie_drp_status(drp_ie); |
209 | reason_code = uwb_ie_drp_reason_code(drp_ie); | 463 | reason_code = uwb_ie_drp_reason_code(drp_ie); |
464 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
210 | 465 | ||
211 | if (status) { | 466 | if (status) { |
212 | switch (reason_code) { | 467 | switch (reason_code) { |
213 | case UWB_DRP_REASON_ACCEPTED: | 468 | case UWB_DRP_REASON_ACCEPTED: |
214 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | 469 | switch (rsv->state) { |
215 | break; | 470 | case UWB_RSV_STATE_O_PENDING: |
216 | case UWB_DRP_REASON_MODIFIED: | 471 | case UWB_RSV_STATE_O_INITIATED: |
217 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 472 | case UWB_RSV_STATE_O_ESTABLISHED: |
218 | reason_code, status); | 473 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); |
474 | break; | ||
475 | case UWB_RSV_STATE_O_MODIFIED: | ||
476 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
477 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
478 | } else { | ||
479 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
480 | } | ||
481 | break; | ||
482 | |||
483 | case UWB_RSV_STATE_O_MOVE_REDUCING: /* shouldn' t be a problem */ | ||
484 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) { | ||
485 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
486 | } else { | ||
487 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
488 | } | ||
489 | break; | ||
490 | case UWB_RSV_STATE_O_MOVE_EXPANDING: | ||
491 | if (bitmap_equal(mas.bm, mv->companion_mas.bm, UWB_NUM_MAS)) { | ||
492 | /* Companion reservation accepted */ | ||
493 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
494 | } else { | ||
495 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); | ||
496 | } | ||
497 | break; | ||
498 | case UWB_RSV_STATE_O_MOVE_COMBINING: | ||
499 | if (bitmap_equal(mas.bm, rsv->mas.bm, UWB_NUM_MAS)) | ||
500 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
501 | else | ||
502 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
503 | break; | ||
504 | default: | ||
505 | break; | ||
506 | } | ||
219 | break; | 507 | break; |
220 | default: | 508 | default: |
221 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | 509 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", |
@@ -230,9 +518,10 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
230 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 518 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
231 | break; | 519 | break; |
232 | case UWB_DRP_REASON_CONFLICT: | 520 | case UWB_DRP_REASON_CONFLICT: |
233 | case UWB_DRP_REASON_MODIFIED: | 521 | /* resolve the conflict */ |
234 | dev_err(dev, "FIXME: unhandled reason code (%d/%d)\n", | 522 | bitmap_complement(mas.bm, src->last_availability_bm, |
235 | reason_code, status); | 523 | UWB_NUM_MAS); |
524 | uwb_drp_handle_conflict_rsv(rc, rsv, drp_evt, drp_ie, &mas); | ||
236 | break; | 525 | break; |
237 | default: | 526 | default: |
238 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", | 527 | dev_warn(dev, "ignoring invalid DRP IE state (%d/%d)\n", |
@@ -241,12 +530,110 @@ static void uwb_drp_process_owner(struct uwb_rc *rc, struct uwb_rsv *rsv, | |||
241 | } | 530 | } |
242 | } | 531 | } |
243 | 532 | ||
533 | static void uwb_cnflt_alien_stroke_timer(struct uwb_cnflt_alien *cnflt) | ||
534 | { | ||
535 | unsigned timeout_us = UWB_MAX_LOST_BEACONS * UWB_SUPERFRAME_LENGTH_US; | ||
536 | mod_timer(&cnflt->timer, jiffies + usecs_to_jiffies(timeout_us)); | ||
537 | } | ||
538 | |||
539 | static void uwb_cnflt_update_work(struct work_struct *work) | ||
540 | { | ||
541 | struct uwb_cnflt_alien *cnflt = container_of(work, | ||
542 | struct uwb_cnflt_alien, | ||
543 | cnflt_update_work); | ||
544 | struct uwb_cnflt_alien *c; | ||
545 | struct uwb_rc *rc = cnflt->rc; | ||
546 | |||
547 | unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; | ||
548 | |||
549 | mutex_lock(&rc->rsvs_mutex); | ||
550 | |||
551 | list_del(&cnflt->rc_node); | ||
552 | |||
553 | /* update rc global conflicting alien bitmap */ | ||
554 | bitmap_zero(rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS); | ||
555 | |||
556 | list_for_each_entry(c, &rc->cnflt_alien_list, rc_node) { | ||
557 | bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, c->mas.bm, UWB_NUM_MAS); | ||
558 | } | ||
559 | |||
560 | queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us)); | ||
561 | |||
562 | kfree(cnflt); | ||
563 | mutex_unlock(&rc->rsvs_mutex); | ||
564 | } | ||
565 | |||
566 | static void uwb_cnflt_timer(unsigned long arg) | ||
567 | { | ||
568 | struct uwb_cnflt_alien *cnflt = (struct uwb_cnflt_alien *)arg; | ||
569 | |||
570 | queue_work(cnflt->rc->rsv_workq, &cnflt->cnflt_update_work); | ||
571 | } | ||
572 | |||
244 | /* | 573 | /* |
245 | * Process a received DRP IE, it's either for a reservation owned by | 574 | * We have received an DRP_IE of type Alien BP and we need to make |
246 | * the RC or targeted at it (or it's for a WUSB cluster reservation). | 575 | * sure we do not transmit in conflicting MASs. |
247 | */ | 576 | */ |
248 | static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | 577 | static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie) |
249 | struct uwb_ie_drp *drp_ie) | 578 | { |
579 | struct device *dev = &rc->uwb_dev.dev; | ||
580 | struct uwb_mas_bm mas; | ||
581 | struct uwb_cnflt_alien *cnflt; | ||
582 | char buf[72]; | ||
583 | unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; | ||
584 | |||
585 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
586 | bitmap_scnprintf(buf, sizeof(buf), mas.bm, UWB_NUM_MAS); | ||
587 | |||
588 | list_for_each_entry(cnflt, &rc->cnflt_alien_list, rc_node) { | ||
589 | if (bitmap_equal(cnflt->mas.bm, mas.bm, UWB_NUM_MAS)) { | ||
590 | /* Existing alien BP reservation conflicting | ||
591 | * bitmap, just reset the timer */ | ||
592 | uwb_cnflt_alien_stroke_timer(cnflt); | ||
593 | return; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | /* New alien BP reservation conflicting bitmap */ | ||
598 | |||
599 | /* alloc and initialize new uwb_cnflt_alien */ | ||
600 | cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL); | ||
601 | if (!cnflt) | ||
602 | dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n"); | ||
603 | INIT_LIST_HEAD(&cnflt->rc_node); | ||
604 | init_timer(&cnflt->timer); | ||
605 | cnflt->timer.function = uwb_cnflt_timer; | ||
606 | cnflt->timer.data = (unsigned long)cnflt; | ||
607 | |||
608 | cnflt->rc = rc; | ||
609 | INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work); | ||
610 | |||
611 | bitmap_copy(cnflt->mas.bm, mas.bm, UWB_NUM_MAS); | ||
612 | |||
613 | list_add_tail(&cnflt->rc_node, &rc->cnflt_alien_list); | ||
614 | |||
615 | /* update rc global conflicting alien bitmap */ | ||
616 | bitmap_or(rc->cnflt_alien_bitmap.bm, rc->cnflt_alien_bitmap.bm, mas.bm, UWB_NUM_MAS); | ||
617 | |||
618 | queue_delayed_work(rc->rsv_workq, &rc->rsv_alien_bp_work, usecs_to_jiffies(delay_us)); | ||
619 | |||
620 | /* start the timer */ | ||
621 | uwb_cnflt_alien_stroke_timer(cnflt); | ||
622 | } | ||
623 | |||
624 | static void uwb_drp_process_not_involved(struct uwb_rc *rc, | ||
625 | struct uwb_rc_evt_drp *drp_evt, | ||
626 | struct uwb_ie_drp *drp_ie) | ||
627 | { | ||
628 | struct uwb_mas_bm mas; | ||
629 | |||
630 | uwb_drp_ie_to_bm(&mas, drp_ie); | ||
631 | uwb_drp_handle_all_conflict_rsv(rc, drp_evt, drp_ie, &mas); | ||
632 | } | ||
633 | |||
634 | static void uwb_drp_process_involved(struct uwb_rc *rc, struct uwb_dev *src, | ||
635 | struct uwb_rc_evt_drp *drp_evt, | ||
636 | struct uwb_ie_drp *drp_ie) | ||
250 | { | 637 | { |
251 | struct uwb_rsv *rsv; | 638 | struct uwb_rsv *rsv; |
252 | 639 | ||
@@ -259,7 +646,7 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | |||
259 | */ | 646 | */ |
260 | return; | 647 | return; |
261 | } | 648 | } |
262 | 649 | ||
263 | /* | 650 | /* |
264 | * Do nothing with DRP IEs for reservations that have been | 651 | * Do nothing with DRP IEs for reservations that have been |
265 | * terminated. | 652 | * terminated. |
@@ -268,13 +655,43 @@ static void uwb_drp_process(struct uwb_rc *rc, struct uwb_dev *src, | |||
268 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 655 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
269 | return; | 656 | return; |
270 | } | 657 | } |
271 | 658 | ||
272 | if (uwb_ie_drp_owner(drp_ie)) | 659 | if (uwb_ie_drp_owner(drp_ie)) |
273 | uwb_drp_process_target(rc, rsv, drp_ie); | 660 | uwb_drp_process_target(rc, rsv, drp_ie, drp_evt); |
661 | else | ||
662 | uwb_drp_process_owner(rc, rsv, src, drp_ie, drp_evt); | ||
663 | |||
664 | } | ||
665 | |||
666 | |||
667 | static bool uwb_drp_involves_us(struct uwb_rc *rc, struct uwb_ie_drp *drp_ie) | ||
668 | { | ||
669 | return uwb_dev_addr_cmp(&rc->uwb_dev.dev_addr, &drp_ie->dev_addr) == 0; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * Process a received DRP IE. | ||
674 | */ | ||
675 | static void uwb_drp_process(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | ||
676 | struct uwb_dev *src, struct uwb_ie_drp *drp_ie) | ||
677 | { | ||
678 | if (uwb_ie_drp_type(drp_ie) == UWB_DRP_TYPE_ALIEN_BP) | ||
679 | uwb_drp_handle_alien_drp(rc, drp_ie); | ||
680 | else if (uwb_drp_involves_us(rc, drp_ie)) | ||
681 | uwb_drp_process_involved(rc, src, drp_evt, drp_ie); | ||
274 | else | 682 | else |
275 | uwb_drp_process_owner(rc, rsv, drp_ie); | 683 | uwb_drp_process_not_involved(rc, drp_evt, drp_ie); |
276 | } | 684 | } |
277 | 685 | ||
686 | /* | ||
687 | * Process a received DRP Availability IE | ||
688 | */ | ||
689 | static void uwb_drp_availability_process(struct uwb_rc *rc, struct uwb_dev *src, | ||
690 | struct uwb_ie_drp_avail *drp_availability_ie) | ||
691 | { | ||
692 | bitmap_copy(src->last_availability_bm, | ||
693 | drp_availability_ie->bmp, UWB_NUM_MAS); | ||
694 | } | ||
278 | 695 | ||
279 | /* | 696 | /* |
280 | * Process all the DRP IEs (both DRP IEs and the DRP Availability IE) | 697 | * Process all the DRP IEs (both DRP IEs and the DRP Availability IE) |
@@ -296,10 +713,10 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | |||
296 | 713 | ||
297 | switch (ie_hdr->element_id) { | 714 | switch (ie_hdr->element_id) { |
298 | case UWB_IE_DRP_AVAILABILITY: | 715 | case UWB_IE_DRP_AVAILABILITY: |
299 | /* FIXME: does something need to be done with this? */ | 716 | uwb_drp_availability_process(rc, src_dev, (struct uwb_ie_drp_avail *)ie_hdr); |
300 | break; | 717 | break; |
301 | case UWB_IE_DRP: | 718 | case UWB_IE_DRP: |
302 | uwb_drp_process(rc, src_dev, (struct uwb_ie_drp *)ie_hdr); | 719 | uwb_drp_process(rc, drp_evt, src_dev, (struct uwb_ie_drp *)ie_hdr); |
303 | break; | 720 | break; |
304 | default: | 721 | default: |
305 | dev_warn(dev, "unexpected IE in DRP notification\n"); | 722 | dev_warn(dev, "unexpected IE in DRP notification\n"); |
@@ -312,55 +729,6 @@ void uwb_drp_process_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | |||
312 | (int)ielen); | 729 | (int)ielen); |
313 | } | 730 | } |
314 | 731 | ||
315 | |||
316 | /* | ||
317 | * Go through all the DRP IEs and find the ones that conflict with our | ||
318 | * reservations. | ||
319 | * | ||
320 | * FIXME: must resolve the conflict according the the rules in | ||
321 | * [ECMA-368]. | ||
322 | */ | ||
323 | static | ||
324 | void uwb_drp_process_conflict_all(struct uwb_rc *rc, struct uwb_rc_evt_drp *drp_evt, | ||
325 | size_t ielen, struct uwb_dev *src_dev) | ||
326 | { | ||
327 | struct device *dev = &rc->uwb_dev.dev; | ||
328 | struct uwb_ie_hdr *ie_hdr; | ||
329 | struct uwb_ie_drp *drp_ie; | ||
330 | void *ptr; | ||
331 | |||
332 | ptr = drp_evt->ie_data; | ||
333 | for (;;) { | ||
334 | ie_hdr = uwb_ie_next(&ptr, &ielen); | ||
335 | if (!ie_hdr) | ||
336 | break; | ||
337 | |||
338 | drp_ie = container_of(ie_hdr, struct uwb_ie_drp, hdr); | ||
339 | |||
340 | /* FIXME: check if this DRP IE conflicts. */ | ||
341 | } | ||
342 | |||
343 | if (ielen > 0) | ||
344 | dev_warn(dev, "%d octets remaining in DRP notification\n", | ||
345 | (int)ielen); | ||
346 | } | ||
347 | |||
348 | |||
349 | /* | ||
350 | * Terminate all reservations owned by, or targeted at, 'uwb_dev'. | ||
351 | */ | ||
352 | static void uwb_drp_terminate_all(struct uwb_rc *rc, struct uwb_dev *uwb_dev) | ||
353 | { | ||
354 | struct uwb_rsv *rsv; | ||
355 | |||
356 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
357 | if (rsv->owner == uwb_dev | ||
358 | || (rsv->target.type == UWB_RSV_TARGET_DEV && rsv->target.dev == uwb_dev)) | ||
359 | uwb_rsv_remove(rsv); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | 732 | /** |
365 | * uwbd_evt_handle_rc_drp - handle a DRP_IE event | 733 | * uwbd_evt_handle_rc_drp - handle a DRP_IE event |
366 | * @evt: the DRP_IE event from the radio controller | 734 | * @evt: the DRP_IE event from the radio controller |
@@ -401,7 +769,6 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt) | |||
401 | size_t ielength, bytes_left; | 769 | size_t ielength, bytes_left; |
402 | struct uwb_dev_addr src_addr; | 770 | struct uwb_dev_addr src_addr; |
403 | struct uwb_dev *src_dev; | 771 | struct uwb_dev *src_dev; |
404 | int reason; | ||
405 | 772 | ||
406 | /* Is there enough data to decode the event (and any IEs in | 773 | /* Is there enough data to decode the event (and any IEs in |
407 | its payload)? */ | 774 | its payload)? */ |
@@ -437,22 +804,8 @@ int uwbd_evt_handle_rc_drp(struct uwb_event *evt) | |||
437 | 804 | ||
438 | mutex_lock(&rc->rsvs_mutex); | 805 | mutex_lock(&rc->rsvs_mutex); |
439 | 806 | ||
440 | reason = uwb_rc_evt_drp_reason(drp_evt); | 807 | /* We do not distinguish from the reason */ |
441 | 808 | uwb_drp_process_all(rc, drp_evt, ielength, src_dev); | |
442 | switch (reason) { | ||
443 | case UWB_DRP_NOTIF_DRP_IE_RCVD: | ||
444 | uwb_drp_process_all(rc, drp_evt, ielength, src_dev); | ||
445 | break; | ||
446 | case UWB_DRP_NOTIF_CONFLICT: | ||
447 | uwb_drp_process_conflict_all(rc, drp_evt, ielength, src_dev); | ||
448 | break; | ||
449 | case UWB_DRP_NOTIF_TERMINATE: | ||
450 | uwb_drp_terminate_all(rc, src_dev); | ||
451 | break; | ||
452 | default: | ||
453 | dev_warn(dev, "ignored DRP event with reason code: %d\n", reason); | ||
454 | break; | ||
455 | } | ||
456 | 809 | ||
457 | mutex_unlock(&rc->rsvs_mutex); | 810 | mutex_unlock(&rc->rsvs_mutex); |
458 | 811 | ||
diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c index 5fe566b7c845..328fcc2b6099 100644 --- a/drivers/uwb/est.c +++ b/drivers/uwb/est.c | |||
@@ -40,10 +40,8 @@ | |||
40 | * uwb_est_get_size() | 40 | * uwb_est_get_size() |
41 | */ | 41 | */ |
42 | #include <linux/spinlock.h> | 42 | #include <linux/spinlock.h> |
43 | #define D_LOCAL 0 | ||
44 | #include <linux/uwb/debug.h> | ||
45 | #include "uwb-internal.h" | ||
46 | 43 | ||
44 | #include "uwb-internal.h" | ||
47 | 45 | ||
48 | struct uwb_est { | 46 | struct uwb_est { |
49 | u16 type_event_high; | 47 | u16 type_event_high; |
@@ -52,7 +50,6 @@ struct uwb_est { | |||
52 | const struct uwb_est_entry *entry; | 50 | const struct uwb_est_entry *entry; |
53 | }; | 51 | }; |
54 | 52 | ||
55 | |||
56 | static struct uwb_est *uwb_est; | 53 | static struct uwb_est *uwb_est; |
57 | static u8 uwb_est_size; | 54 | static u8 uwb_est_size; |
58 | static u8 uwb_est_used; | 55 | static u8 uwb_est_used; |
@@ -440,21 +437,12 @@ ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, | |||
440 | u8 *ptr = (u8 *) rceb; | 437 | u8 *ptr = (u8 *) rceb; |
441 | 438 | ||
442 | read_lock_irqsave(&uwb_est_lock, flags); | 439 | read_lock_irqsave(&uwb_est_lock, flags); |
443 | d_printf(2, dev, "Size query for event 0x%02x/%04x/%02x," | ||
444 | " buffer size %ld\n", | ||
445 | (unsigned) rceb->bEventType, | ||
446 | (unsigned) le16_to_cpu(rceb->wEvent), | ||
447 | (unsigned) rceb->bEventContext, | ||
448 | (long) rceb_size); | ||
449 | size = -ENOSPC; | 440 | size = -ENOSPC; |
450 | if (rceb_size < sizeof(*rceb)) | 441 | if (rceb_size < sizeof(*rceb)) |
451 | goto out; | 442 | goto out; |
452 | event = le16_to_cpu(rceb->wEvent); | 443 | event = le16_to_cpu(rceb->wEvent); |
453 | type_event_high = rceb->bEventType << 8 | (event & 0xff00) >> 8; | 444 | type_event_high = rceb->bEventType << 8 | (event & 0xff00) >> 8; |
454 | for (itr = 0; itr < uwb_est_used; itr++) { | 445 | for (itr = 0; itr < uwb_est_used; itr++) { |
455 | d_printf(3, dev, "Checking EST 0x%04x/%04x/%04x\n", | ||
456 | uwb_est[itr].type_event_high, uwb_est[itr].vendor, | ||
457 | uwb_est[itr].product); | ||
458 | if (uwb_est[itr].type_event_high != type_event_high) | 446 | if (uwb_est[itr].type_event_high != type_event_high) |
459 | continue; | 447 | continue; |
460 | size = uwb_est_get_size(rc, &uwb_est[itr], | 448 | size = uwb_est_get_size(rc, &uwb_est[itr], |
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 3d26fa0f8ae1..559f8784acf3 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
@@ -51,16 +51,14 @@ | |||
51 | * | 51 | * |
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | #include <linux/version.h> | ||
55 | #include <linux/init.h> | 54 | #include <linux/init.h> |
56 | #include <linux/module.h> | 55 | #include <linux/module.h> |
57 | #include <linux/usb.h> | 56 | #include <linux/usb.h> |
58 | #include <linux/usb/wusb.h> | 57 | #include <linux/usb/wusb.h> |
59 | #include <linux/usb/wusb-wa.h> | 58 | #include <linux/usb/wusb-wa.h> |
60 | #include <linux/uwb.h> | 59 | #include <linux/uwb.h> |
60 | |||
61 | #include "uwb-internal.h" | 61 | #include "uwb-internal.h" |
62 | #define D_LOCAL 1 | ||
63 | #include <linux/uwb/debug.h> | ||
64 | 62 | ||
65 | /* The device uses commands and events from the WHCI specification, although | 63 | /* The device uses commands and events from the WHCI specification, although |
66 | * reporting itself as WUSB compliant. */ | 64 | * reporting itself as WUSB compliant. */ |
@@ -631,17 +629,13 @@ void hwarc_neep_cb(struct urb *urb) | |||
631 | 629 | ||
632 | switch (result = urb->status) { | 630 | switch (result = urb->status) { |
633 | case 0: | 631 | case 0: |
634 | d_printf(3, dev, "NEEP: receive stat %d, %zu bytes\n", | ||
635 | urb->status, (size_t)urb->actual_length); | ||
636 | uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer, | 632 | uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer, |
637 | urb->actual_length); | 633 | urb->actual_length); |
638 | break; | 634 | break; |
639 | case -ECONNRESET: /* Not an error, but a controlled situation; */ | 635 | case -ECONNRESET: /* Not an error, but a controlled situation; */ |
640 | case -ENOENT: /* (we killed the URB)...so, no broadcast */ | 636 | case -ENOENT: /* (we killed the URB)...so, no broadcast */ |
641 | d_printf(2, dev, "NEEP: URB reset/noent %d\n", urb->status); | ||
642 | goto out; | 637 | goto out; |
643 | case -ESHUTDOWN: /* going away! */ | 638 | case -ESHUTDOWN: /* going away! */ |
644 | d_printf(2, dev, "NEEP: URB down %d\n", urb->status); | ||
645 | goto out; | 639 | goto out; |
646 | default: /* On general errors, retry unless it gets ugly */ | 640 | default: /* On general errors, retry unless it gets ugly */ |
647 | if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS, | 641 | if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS, |
@@ -650,7 +644,6 @@ void hwarc_neep_cb(struct urb *urb) | |||
650 | dev_err(dev, "NEEP: URB error %d\n", urb->status); | 644 | dev_err(dev, "NEEP: URB error %d\n", urb->status); |
651 | } | 645 | } |
652 | result = usb_submit_urb(urb, GFP_ATOMIC); | 646 | result = usb_submit_urb(urb, GFP_ATOMIC); |
653 | d_printf(3, dev, "NEEP: submit %d\n", result); | ||
654 | if (result < 0) { | 647 | if (result < 0) { |
655 | dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n", | 648 | dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n", |
656 | result); | 649 | result); |
@@ -759,11 +752,11 @@ static int hwarc_get_version(struct uwb_rc *rc) | |||
759 | itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); | 752 | itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); |
760 | while (itr_size >= sizeof(*hdr)) { | 753 | while (itr_size >= sizeof(*hdr)) { |
761 | hdr = (struct usb_descriptor_header *) itr; | 754 | hdr = (struct usb_descriptor_header *) itr; |
762 | d_printf(3, dev, "Extra device descriptor: " | 755 | dev_dbg(dev, "Extra device descriptor: " |
763 | "type %02x/%u bytes @ %zu (%zu left)\n", | 756 | "type %02x/%u bytes @ %zu (%zu left)\n", |
764 | hdr->bDescriptorType, hdr->bLength, | 757 | hdr->bDescriptorType, hdr->bLength, |
765 | (itr - usb_dev->rawdescriptors[actconfig_idx]), | 758 | (itr - usb_dev->rawdescriptors[actconfig_idx]), |
766 | itr_size); | 759 | itr_size); |
767 | if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL) | 760 | if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL) |
768 | goto found; | 761 | goto found; |
769 | itr += hdr->bLength; | 762 | itr += hdr->bLength; |
@@ -795,8 +788,7 @@ found: | |||
795 | goto error; | 788 | goto error; |
796 | } | 789 | } |
797 | rc->version = version; | 790 | rc->version = version; |
798 | d_printf(3, dev, "Device supports WUSB protocol version 0x%04x \n", | 791 | dev_dbg(dev, "Device supports WUSB protocol version 0x%04x \n", rc->version); |
799 | rc->version); | ||
800 | result = 0; | 792 | result = 0; |
801 | error: | 793 | error: |
802 | return result; | 794 | return result; |
@@ -877,11 +869,28 @@ static void hwarc_disconnect(struct usb_interface *iface) | |||
877 | uwb_rc_rm(uwb_rc); | 869 | uwb_rc_rm(uwb_rc); |
878 | usb_put_intf(hwarc->usb_iface); | 870 | usb_put_intf(hwarc->usb_iface); |
879 | usb_put_dev(hwarc->usb_dev); | 871 | usb_put_dev(hwarc->usb_dev); |
880 | d_printf(1, &hwarc->usb_iface->dev, "freed hwarc %p\n", hwarc); | ||
881 | kfree(hwarc); | 872 | kfree(hwarc); |
882 | uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ | 873 | uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ |
883 | } | 874 | } |
884 | 875 | ||
876 | static int hwarc_pre_reset(struct usb_interface *iface) | ||
877 | { | ||
878 | struct hwarc *hwarc = usb_get_intfdata(iface); | ||
879 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | ||
880 | |||
881 | uwb_rc_pre_reset(uwb_rc); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int hwarc_post_reset(struct usb_interface *iface) | ||
886 | { | ||
887 | struct hwarc *hwarc = usb_get_intfdata(iface); | ||
888 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | ||
889 | |||
890 | uwb_rc_post_reset(uwb_rc); | ||
891 | return 0; | ||
892 | } | ||
893 | |||
885 | /** USB device ID's that we handle */ | 894 | /** USB device ID's that we handle */ |
886 | static struct usb_device_id hwarc_id_table[] = { | 895 | static struct usb_device_id hwarc_id_table[] = { |
887 | /* D-Link DUB-1210 */ | 896 | /* D-Link DUB-1210 */ |
@@ -898,20 +907,16 @@ MODULE_DEVICE_TABLE(usb, hwarc_id_table); | |||
898 | 907 | ||
899 | static struct usb_driver hwarc_driver = { | 908 | static struct usb_driver hwarc_driver = { |
900 | .name = "hwa-rc", | 909 | .name = "hwa-rc", |
910 | .id_table = hwarc_id_table, | ||
901 | .probe = hwarc_probe, | 911 | .probe = hwarc_probe, |
902 | .disconnect = hwarc_disconnect, | 912 | .disconnect = hwarc_disconnect, |
903 | .id_table = hwarc_id_table, | 913 | .pre_reset = hwarc_pre_reset, |
914 | .post_reset = hwarc_post_reset, | ||
904 | }; | 915 | }; |
905 | 916 | ||
906 | static int __init hwarc_driver_init(void) | 917 | static int __init hwarc_driver_init(void) |
907 | { | 918 | { |
908 | int result; | 919 | return usb_register(&hwarc_driver); |
909 | result = usb_register(&hwarc_driver); | ||
910 | if (result < 0) | ||
911 | printk(KERN_ERR "HWA-RC: Cannot register USB driver: %d\n", | ||
912 | result); | ||
913 | return result; | ||
914 | |||
915 | } | 920 | } |
916 | module_init(hwarc_driver_init); | 921 | module_init(hwarc_driver_init); |
917 | 922 | ||
diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/uwb/i1480/dfu/dfu.c index 9097b3b30385..da7b1d08003c 100644 --- a/drivers/uwb/i1480/dfu/dfu.c +++ b/drivers/uwb/i1480/dfu/dfu.c | |||
@@ -34,10 +34,7 @@ | |||
34 | #include <linux/uwb.h> | 34 | #include <linux/uwb.h> |
35 | #include <linux/random.h> | 35 | #include <linux/random.h> |
36 | 36 | ||
37 | #define D_LOCAL 0 | 37 | /* |
38 | #include <linux/uwb/debug.h> | ||
39 | |||
40 | /** | ||
41 | * i1480_rceb_check - Check RCEB for expected field values | 38 | * i1480_rceb_check - Check RCEB for expected field values |
42 | * @i1480: pointer to device for which RCEB is being checked | 39 | * @i1480: pointer to device for which RCEB is being checked |
43 | * @rceb: RCEB being checked | 40 | * @rceb: RCEB being checked |
@@ -83,7 +80,7 @@ int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb, | |||
83 | EXPORT_SYMBOL_GPL(i1480_rceb_check); | 80 | EXPORT_SYMBOL_GPL(i1480_rceb_check); |
84 | 81 | ||
85 | 82 | ||
86 | /** | 83 | /* |
87 | * Execute a Radio Control Command | 84 | * Execute a Radio Control Command |
88 | * | 85 | * |
89 | * Command data has to be in i1480->cmd_buf. | 86 | * Command data has to be in i1480->cmd_buf. |
@@ -101,7 +98,6 @@ ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size, | |||
101 | u8 expected_type = reply->bEventType; | 98 | u8 expected_type = reply->bEventType; |
102 | u8 context; | 99 | u8 context; |
103 | 100 | ||
104 | d_fnstart(3, i1480->dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size); | ||
105 | init_completion(&i1480->evt_complete); | 101 | init_completion(&i1480->evt_complete); |
106 | i1480->evt_result = -EINPROGRESS; | 102 | i1480->evt_result = -EINPROGRESS; |
107 | do { | 103 | do { |
@@ -150,8 +146,6 @@ ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size, | |||
150 | result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context, | 146 | result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context, |
151 | expected_type, expected_event); | 147 | expected_type, expected_event); |
152 | error: | 148 | error: |
153 | d_fnend(3, i1480->dev, "(%p, %s, %zu) = %zd\n", | ||
154 | i1480, cmd_name, cmd_size, result); | ||
155 | return result; | 149 | return result; |
156 | } | 150 | } |
157 | EXPORT_SYMBOL_GPL(i1480_cmd); | 151 | EXPORT_SYMBOL_GPL(i1480_cmd); |
diff --git a/drivers/uwb/i1480/dfu/mac.c b/drivers/uwb/i1480/dfu/mac.c index 2e4d8f07c165..694d0daf88ab 100644 --- a/drivers/uwb/i1480/dfu/mac.c +++ b/drivers/uwb/i1480/dfu/mac.c | |||
@@ -31,9 +31,6 @@ | |||
31 | #include <linux/uwb.h> | 31 | #include <linux/uwb.h> |
32 | #include "i1480-dfu.h" | 32 | #include "i1480-dfu.h" |
33 | 33 | ||
34 | #define D_LOCAL 0 | ||
35 | #include <linux/uwb/debug.h> | ||
36 | |||
37 | /* | 34 | /* |
38 | * Descriptor for a continuous segment of MAC fw data | 35 | * Descriptor for a continuous segment of MAC fw data |
39 | */ | 36 | */ |
@@ -184,10 +181,6 @@ ssize_t i1480_fw_cmp(struct i1480 *i1480, struct fw_hdr *hdr) | |||
184 | } | 181 | } |
185 | if (memcmp(i1480->cmd_buf, bin + src_itr, result)) { | 182 | if (memcmp(i1480->cmd_buf, bin + src_itr, result)) { |
186 | u8 *buf = i1480->cmd_buf; | 183 | u8 *buf = i1480->cmd_buf; |
187 | d_printf(2, i1480->dev, | ||
188 | "original data @ %p + %u, %zu bytes\n", | ||
189 | bin, src_itr, result); | ||
190 | d_dump(4, i1480->dev, bin + src_itr, result); | ||
191 | for (cnt = 0; cnt < result; cnt++) | 184 | for (cnt = 0; cnt < result; cnt++) |
192 | if (bin[src_itr + cnt] != buf[cnt]) { | 185 | if (bin[src_itr + cnt] != buf[cnt]) { |
193 | dev_err(i1480->dev, "byte failed at " | 186 | dev_err(i1480->dev, "byte failed at " |
@@ -224,7 +217,6 @@ int mac_fw_hdrs_push(struct i1480 *i1480, struct fw_hdr *hdr, | |||
224 | struct fw_hdr *hdr_itr; | 217 | struct fw_hdr *hdr_itr; |
225 | int verif_retry_count; | 218 | int verif_retry_count; |
226 | 219 | ||
227 | d_fnstart(3, dev, "(%p, %p)\n", i1480, hdr); | ||
228 | /* Now, header by header, push them to the hw */ | 220 | /* Now, header by header, push them to the hw */ |
229 | for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) { | 221 | for (hdr_itr = hdr; hdr_itr != NULL; hdr_itr = hdr_itr->next) { |
230 | verif_retry_count = 0; | 222 | verif_retry_count = 0; |
@@ -264,7 +256,6 @@ retry: | |||
264 | break; | 256 | break; |
265 | } | 257 | } |
266 | } | 258 | } |
267 | d_fnend(3, dev, "(%zd)\n", result); | ||
268 | return result; | 259 | return result; |
269 | } | 260 | } |
270 | 261 | ||
@@ -337,11 +328,9 @@ int __mac_fw_upload(struct i1480 *i1480, const char *fw_name, | |||
337 | const struct firmware *fw; | 328 | const struct firmware *fw; |
338 | struct fw_hdr *fw_hdrs; | 329 | struct fw_hdr *fw_hdrs; |
339 | 330 | ||
340 | d_fnstart(3, i1480->dev, "(%p, %s, %s)\n", i1480, fw_name, fw_tag); | ||
341 | result = request_firmware(&fw, fw_name, i1480->dev); | 331 | result = request_firmware(&fw, fw_name, i1480->dev); |
342 | if (result < 0) /* Up to caller to complain on -ENOENT */ | 332 | if (result < 0) /* Up to caller to complain on -ENOENT */ |
343 | goto out; | 333 | goto out; |
344 | d_printf(3, i1480->dev, "%s fw '%s': uploading\n", fw_tag, fw_name); | ||
345 | result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size); | 334 | result = fw_hdrs_load(i1480, &fw_hdrs, fw->data, fw->size); |
346 | if (result < 0) { | 335 | if (result < 0) { |
347 | dev_err(i1480->dev, "%s fw '%s': failed to parse firmware " | 336 | dev_err(i1480->dev, "%s fw '%s': failed to parse firmware " |
@@ -363,8 +352,6 @@ out_hdrs_release: | |||
363 | out_release: | 352 | out_release: |
364 | release_firmware(fw); | 353 | release_firmware(fw); |
365 | out: | 354 | out: |
366 | d_fnend(3, i1480->dev, "(%p, %s, %s) = %d\n", i1480, fw_name, fw_tag, | ||
367 | result); | ||
368 | return result; | 355 | return result; |
369 | } | 356 | } |
370 | 357 | ||
@@ -433,7 +420,6 @@ int i1480_fw_is_running_q(struct i1480 *i1480) | |||
433 | int result; | 420 | int result; |
434 | u32 *val = (u32 *) i1480->cmd_buf; | 421 | u32 *val = (u32 *) i1480->cmd_buf; |
435 | 422 | ||
436 | d_fnstart(3, i1480->dev, "(i1480 %p)\n", i1480); | ||
437 | for (cnt = 0; cnt < 10; cnt++) { | 423 | for (cnt = 0; cnt < 10; cnt++) { |
438 | msleep(100); | 424 | msleep(100); |
439 | result = i1480->read(i1480, 0x80080000, 4); | 425 | result = i1480->read(i1480, 0x80080000, 4); |
@@ -447,7 +433,6 @@ int i1480_fw_is_running_q(struct i1480 *i1480) | |||
447 | dev_err(i1480->dev, "Timed out waiting for fw to start\n"); | 433 | dev_err(i1480->dev, "Timed out waiting for fw to start\n"); |
448 | result = -ETIMEDOUT; | 434 | result = -ETIMEDOUT; |
449 | out: | 435 | out: |
450 | d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result); | ||
451 | return result; | 436 | return result; |
452 | 437 | ||
453 | } | 438 | } |
@@ -467,7 +452,6 @@ int i1480_mac_fw_upload(struct i1480 *i1480) | |||
467 | int result = 0, deprecated_name = 0; | 452 | int result = 0, deprecated_name = 0; |
468 | struct i1480_rceb *rcebe = (void *) i1480->evt_buf; | 453 | struct i1480_rceb *rcebe = (void *) i1480->evt_buf; |
469 | 454 | ||
470 | d_fnstart(3, i1480->dev, "(%p)\n", i1480); | ||
471 | result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC"); | 455 | result = __mac_fw_upload(i1480, i1480->mac_fw_name, "MAC"); |
472 | if (result == -ENOENT) { | 456 | if (result == -ENOENT) { |
473 | result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate, | 457 | result = __mac_fw_upload(i1480, i1480->mac_fw_name_deprecate, |
@@ -501,7 +485,6 @@ int i1480_mac_fw_upload(struct i1480 *i1480) | |||
501 | dev_err(i1480->dev, "MAC fw '%s': initialization event returns " | 485 | dev_err(i1480->dev, "MAC fw '%s': initialization event returns " |
502 | "wrong size (%zu bytes vs %zu needed)\n", | 486 | "wrong size (%zu bytes vs %zu needed)\n", |
503 | i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe)); | 487 | i1480->mac_fw_name, i1480->evt_result, sizeof(*rcebe)); |
504 | dump_bytes(i1480->dev, rcebe, min(i1480->evt_result, (ssize_t)32)); | ||
505 | goto error_size; | 488 | goto error_size; |
506 | } | 489 | } |
507 | result = -EIO; | 490 | result = -EIO; |
@@ -522,6 +505,5 @@ error_fw_not_running: | |||
522 | error_init_timeout: | 505 | error_init_timeout: |
523 | error_size: | 506 | error_size: |
524 | error_setup: | 507 | error_setup: |
525 | d_fnend(3, i1480->dev, "(i1480 %p) = %d\n", i1480, result); | ||
526 | return result; | 508 | return result; |
527 | } | 509 | } |
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 98eeeff051aa..686795e97195 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c | |||
@@ -35,7 +35,6 @@ | |||
35 | * the functions are i1480_usb_NAME(). | 35 | * the functions are i1480_usb_NAME(). |
36 | */ | 36 | */ |
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/version.h> | ||
39 | #include <linux/usb.h> | 38 | #include <linux/usb.h> |
40 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
41 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
@@ -44,10 +43,6 @@ | |||
44 | #include <linux/usb/wusb-wa.h> | 43 | #include <linux/usb/wusb-wa.h> |
45 | #include "i1480-dfu.h" | 44 | #include "i1480-dfu.h" |
46 | 45 | ||
47 | #define D_LOCAL 0 | ||
48 | #include <linux/uwb/debug.h> | ||
49 | |||
50 | |||
51 | struct i1480_usb { | 46 | struct i1480_usb { |
52 | struct i1480 i1480; | 47 | struct i1480 i1480; |
53 | struct usb_device *usb_dev; | 48 | struct usb_device *usb_dev; |
@@ -118,8 +113,6 @@ int i1480_usb_write(struct i1480 *i1480, u32 memory_address, | |||
118 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); | 113 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); |
119 | size_t buffer_size, itr = 0; | 114 | size_t buffer_size, itr = 0; |
120 | 115 | ||
121 | d_fnstart(3, i1480->dev, "(%p, 0x%08x, %p, %zu)\n", | ||
122 | i1480, memory_address, buffer, size); | ||
123 | BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ | 116 | BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ |
124 | while (size > 0) { | 117 | while (size > 0) { |
125 | buffer_size = size < i1480->buf_size ? size : i1480->buf_size; | 118 | buffer_size = size < i1480->buf_size ? size : i1480->buf_size; |
@@ -132,16 +125,10 @@ int i1480_usb_write(struct i1480 *i1480, u32 memory_address, | |||
132 | i1480->cmd_buf, buffer_size, 100 /* FIXME: arbitrary */); | 125 | i1480->cmd_buf, buffer_size, 100 /* FIXME: arbitrary */); |
133 | if (result < 0) | 126 | if (result < 0) |
134 | break; | 127 | break; |
135 | d_printf(3, i1480->dev, | ||
136 | "wrote @ 0x%08x %u bytes (of %zu bytes requested)\n", | ||
137 | memory_address, result, buffer_size); | ||
138 | d_dump(4, i1480->dev, i1480->cmd_buf, result); | ||
139 | itr += result; | 128 | itr += result; |
140 | memory_address += result; | 129 | memory_address += result; |
141 | size -= result; | 130 | size -= result; |
142 | } | 131 | } |
143 | d_fnend(3, i1480->dev, "(%p, 0x%08x, %p, %zu) = %d\n", | ||
144 | i1480, memory_address, buffer, size, result); | ||
145 | return result; | 132 | return result; |
146 | } | 133 | } |
147 | 134 | ||
@@ -166,8 +153,6 @@ int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size) | |||
166 | size_t itr, read_size = i1480->buf_size; | 153 | size_t itr, read_size = i1480->buf_size; |
167 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); | 154 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); |
168 | 155 | ||
169 | d_fnstart(3, i1480->dev, "(%p, 0x%08x, %zu)\n", | ||
170 | i1480, addr, size); | ||
171 | BUG_ON(size > i1480->buf_size); | 156 | BUG_ON(size > i1480->buf_size); |
172 | BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ | 157 | BUG_ON(size & 0x3); /* Needs to be a multiple of 4 */ |
173 | BUG_ON(read_size > 512); | 158 | BUG_ON(read_size > 512); |
@@ -201,10 +186,6 @@ int i1480_usb_read(struct i1480 *i1480, u32 addr, size_t size) | |||
201 | } | 186 | } |
202 | result = bytes; | 187 | result = bytes; |
203 | out: | 188 | out: |
204 | d_fnend(3, i1480->dev, "(%p, 0x%08x, %zu) = %zd\n", | ||
205 | i1480, addr, size, result); | ||
206 | if (result > 0) | ||
207 | d_dump(4, i1480->dev, i1480->cmd_buf, result); | ||
208 | return result; | 189 | return result; |
209 | } | 190 | } |
210 | 191 | ||
@@ -260,7 +241,6 @@ int i1480_usb_wait_init_done(struct i1480 *i1480) | |||
260 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); | 241 | struct i1480_usb *i1480_usb = container_of(i1480, struct i1480_usb, i1480); |
261 | struct usb_endpoint_descriptor *epd; | 242 | struct usb_endpoint_descriptor *epd; |
262 | 243 | ||
263 | d_fnstart(3, dev, "(%p)\n", i1480); | ||
264 | init_completion(&i1480->evt_complete); | 244 | init_completion(&i1480->evt_complete); |
265 | i1480->evt_result = -EINPROGRESS; | 245 | i1480->evt_result = -EINPROGRESS; |
266 | epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; | 246 | epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; |
@@ -282,14 +262,12 @@ int i1480_usb_wait_init_done(struct i1480 *i1480) | |||
282 | goto error_wait; | 262 | goto error_wait; |
283 | } | 263 | } |
284 | usb_kill_urb(i1480_usb->neep_urb); | 264 | usb_kill_urb(i1480_usb->neep_urb); |
285 | d_fnend(3, dev, "(%p) = 0\n", i1480); | ||
286 | return 0; | 265 | return 0; |
287 | 266 | ||
288 | error_wait: | 267 | error_wait: |
289 | usb_kill_urb(i1480_usb->neep_urb); | 268 | usb_kill_urb(i1480_usb->neep_urb); |
290 | error_submit: | 269 | error_submit: |
291 | i1480->evt_result = result; | 270 | i1480->evt_result = result; |
292 | d_fnend(3, dev, "(%p) = %d\n", i1480, result); | ||
293 | return result; | 271 | return result; |
294 | } | 272 | } |
295 | 273 | ||
@@ -320,7 +298,6 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size) | |||
320 | struct uwb_rccb *cmd = i1480->cmd_buf; | 298 | struct uwb_rccb *cmd = i1480->cmd_buf; |
321 | u8 iface_no; | 299 | u8 iface_no; |
322 | 300 | ||
323 | d_fnstart(3, dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size); | ||
324 | /* Post a read on the notification & event endpoint */ | 301 | /* Post a read on the notification & event endpoint */ |
325 | iface_no = i1480_usb->usb_iface->cur_altsetting->desc.bInterfaceNumber; | 302 | iface_no = i1480_usb->usb_iface->cur_altsetting->desc.bInterfaceNumber; |
326 | epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; | 303 | epd = &i1480_usb->usb_iface->cur_altsetting->endpoint[0].desc; |
@@ -348,15 +325,11 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size) | |||
348 | cmd_name, result); | 325 | cmd_name, result); |
349 | goto error_submit_ep0; | 326 | goto error_submit_ep0; |
350 | } | 327 | } |
351 | d_fnend(3, dev, "(%p, %s, %zu) = %d\n", | ||
352 | i1480, cmd_name, cmd_size, result); | ||
353 | return result; | 328 | return result; |
354 | 329 | ||
355 | error_submit_ep0: | 330 | error_submit_ep0: |
356 | usb_kill_urb(i1480_usb->neep_urb); | 331 | usb_kill_urb(i1480_usb->neep_urb); |
357 | error_submit_ep1: | 332 | error_submit_ep1: |
358 | d_fnend(3, dev, "(%p, %s, %zu) = %d\n", | ||
359 | i1480, cmd_name, cmd_size, result); | ||
360 | return result; | 333 | return result; |
361 | } | 334 | } |
362 | 335 | ||
diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c index 737d60cd5b73..049c05d4cc6a 100644 --- a/drivers/uwb/i1480/i1480u-wlp/lc.c +++ b/drivers/uwb/i1480/i1480u-wlp/lc.c | |||
@@ -55,10 +55,9 @@ | |||
55 | * is being removed. | 55 | * is being removed. |
56 | * i1480u_rm() | 56 | * i1480u_rm() |
57 | */ | 57 | */ |
58 | #include <linux/version.h> | ||
59 | #include <linux/if_arp.h> | 58 | #include <linux/if_arp.h> |
60 | #include <linux/etherdevice.h> | 59 | #include <linux/etherdevice.h> |
61 | #include <linux/uwb/debug.h> | 60 | |
62 | #include "i1480u-wlp.h" | 61 | #include "i1480u-wlp.h" |
63 | 62 | ||
64 | 63 | ||
@@ -207,7 +206,7 @@ int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface) | |||
207 | wlp->fill_device_info = i1480u_fill_device_info; | 206 | wlp->fill_device_info = i1480u_fill_device_info; |
208 | wlp->stop_queue = i1480u_stop_queue; | 207 | wlp->stop_queue = i1480u_stop_queue; |
209 | wlp->start_queue = i1480u_start_queue; | 208 | wlp->start_queue = i1480u_start_queue; |
210 | result = wlp_setup(wlp, rc); | 209 | result = wlp_setup(wlp, rc, net_dev); |
211 | if (result < 0) { | 210 | if (result < 0) { |
212 | dev_err(&iface->dev, "Cannot setup WLP\n"); | 211 | dev_err(&iface->dev, "Cannot setup WLP\n"); |
213 | goto error_wlp_setup; | 212 | goto error_wlp_setup; |
diff --git a/drivers/uwb/i1480/i1480u-wlp/netdev.c b/drivers/uwb/i1480/i1480u-wlp/netdev.c index 8802ac43d872..e3873ffb942c 100644 --- a/drivers/uwb/i1480/i1480u-wlp/netdev.c +++ b/drivers/uwb/i1480/i1480u-wlp/netdev.c | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | #include <linux/if_arp.h> | 42 | #include <linux/if_arp.h> |
43 | #include <linux/etherdevice.h> | 43 | #include <linux/etherdevice.h> |
44 | #include <linux/uwb/debug.h> | 44 | |
45 | #include "i1480u-wlp.h" | 45 | #include "i1480u-wlp.h" |
46 | 46 | ||
47 | struct i1480u_cmd_set_ip_mas { | 47 | struct i1480u_cmd_set_ip_mas { |
@@ -207,6 +207,11 @@ int i1480u_open(struct net_device *net_dev) | |||
207 | result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ | 207 | result = i1480u_rx_setup(i1480u); /* Alloc RX stuff */ |
208 | if (result < 0) | 208 | if (result < 0) |
209 | goto error_rx_setup; | 209 | goto error_rx_setup; |
210 | |||
211 | result = uwb_radio_start(&wlp->pal); | ||
212 | if (result < 0) | ||
213 | goto error_radio_start; | ||
214 | |||
210 | netif_wake_queue(net_dev); | 215 | netif_wake_queue(net_dev); |
211 | #ifdef i1480u_FLOW_CONTROL | 216 | #ifdef i1480u_FLOW_CONTROL |
212 | result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);; | 217 | result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);; |
@@ -215,25 +220,20 @@ int i1480u_open(struct net_device *net_dev) | |||
215 | goto error_notif_urb_submit; | 220 | goto error_notif_urb_submit; |
216 | } | 221 | } |
217 | #endif | 222 | #endif |
218 | i1480u->uwb_notifs_handler.cb = i1480u_uwb_notifs_cb; | ||
219 | i1480u->uwb_notifs_handler.data = i1480u; | ||
220 | if (uwb_bg_joined(rc)) | ||
221 | netif_carrier_on(net_dev); | ||
222 | else | ||
223 | netif_carrier_off(net_dev); | ||
224 | uwb_notifs_register(rc, &i1480u->uwb_notifs_handler); | ||
225 | /* Interface is up with an address, now we can create WSS */ | 223 | /* Interface is up with an address, now we can create WSS */ |
226 | result = wlp_wss_setup(net_dev, &wlp->wss); | 224 | result = wlp_wss_setup(net_dev, &wlp->wss); |
227 | if (result < 0) { | 225 | if (result < 0) { |
228 | dev_err(dev, "Can't create WSS: %d. \n", result); | 226 | dev_err(dev, "Can't create WSS: %d. \n", result); |
229 | goto error_notif_deregister; | 227 | goto error_wss_setup; |
230 | } | 228 | } |
231 | return 0; | 229 | return 0; |
232 | error_notif_deregister: | 230 | error_wss_setup: |
233 | uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); | ||
234 | #ifdef i1480u_FLOW_CONTROL | 231 | #ifdef i1480u_FLOW_CONTROL |
232 | usb_kill_urb(i1480u->notif_urb); | ||
235 | error_notif_urb_submit: | 233 | error_notif_urb_submit: |
236 | #endif | 234 | #endif |
235 | uwb_radio_stop(&wlp->pal); | ||
236 | error_radio_start: | ||
237 | netif_stop_queue(net_dev); | 237 | netif_stop_queue(net_dev); |
238 | i1480u_rx_release(i1480u); | 238 | i1480u_rx_release(i1480u); |
239 | error_rx_setup: | 239 | error_rx_setup: |
@@ -248,16 +248,15 @@ int i1480u_stop(struct net_device *net_dev) | |||
248 | { | 248 | { |
249 | struct i1480u *i1480u = netdev_priv(net_dev); | 249 | struct i1480u *i1480u = netdev_priv(net_dev); |
250 | struct wlp *wlp = &i1480u->wlp; | 250 | struct wlp *wlp = &i1480u->wlp; |
251 | struct uwb_rc *rc = wlp->rc; | ||
252 | 251 | ||
253 | BUG_ON(wlp->rc == NULL); | 252 | BUG_ON(wlp->rc == NULL); |
254 | wlp_wss_remove(&wlp->wss); | 253 | wlp_wss_remove(&wlp->wss); |
255 | uwb_notifs_deregister(rc, &i1480u->uwb_notifs_handler); | ||
256 | netif_carrier_off(net_dev); | 254 | netif_carrier_off(net_dev); |
257 | #ifdef i1480u_FLOW_CONTROL | 255 | #ifdef i1480u_FLOW_CONTROL |
258 | usb_kill_urb(i1480u->notif_urb); | 256 | usb_kill_urb(i1480u->notif_urb); |
259 | #endif | 257 | #endif |
260 | netif_stop_queue(net_dev); | 258 | netif_stop_queue(net_dev); |
259 | uwb_radio_stop(&wlp->pal); | ||
261 | i1480u_rx_release(i1480u); | 260 | i1480u_rx_release(i1480u); |
262 | i1480u_tx_release(i1480u); | 261 | i1480u_tx_release(i1480u); |
263 | return 0; | 262 | return 0; |
@@ -303,34 +302,6 @@ int i1480u_change_mtu(struct net_device *net_dev, int mtu) | |||
303 | return 0; | 302 | return 0; |
304 | } | 303 | } |
305 | 304 | ||
306 | |||
307 | /** | ||
308 | * Callback function to handle events from UWB | ||
309 | * When we see other devices we know the carrier is ok, | ||
310 | * if we are the only device in the beacon group we set the carrier | ||
311 | * state to off. | ||
312 | * */ | ||
313 | void i1480u_uwb_notifs_cb(void *data, struct uwb_dev *uwb_dev, | ||
314 | enum uwb_notifs event) | ||
315 | { | ||
316 | struct i1480u *i1480u = data; | ||
317 | struct net_device *net_dev = i1480u->net_dev; | ||
318 | struct device *dev = &i1480u->usb_iface->dev; | ||
319 | switch (event) { | ||
320 | case UWB_NOTIF_BG_JOIN: | ||
321 | netif_carrier_on(net_dev); | ||
322 | dev_info(dev, "Link is up\n"); | ||
323 | break; | ||
324 | case UWB_NOTIF_BG_LEAVE: | ||
325 | netif_carrier_off(net_dev); | ||
326 | dev_info(dev, "Link is down\n"); | ||
327 | break; | ||
328 | default: | ||
329 | dev_err(dev, "don't know how to handle event %d from uwb\n", | ||
330 | event); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | /** | 305 | /** |
335 | * Stop the network queue | 306 | * Stop the network queue |
336 | * | 307 | * |
diff --git a/drivers/uwb/i1480/i1480u-wlp/rx.c b/drivers/uwb/i1480/i1480u-wlp/rx.c index 9fc035354a76..34f4cf9a7d34 100644 --- a/drivers/uwb/i1480/i1480u-wlp/rx.c +++ b/drivers/uwb/i1480/i1480u-wlp/rx.c | |||
@@ -68,11 +68,7 @@ | |||
68 | #include <linux/etherdevice.h> | 68 | #include <linux/etherdevice.h> |
69 | #include "i1480u-wlp.h" | 69 | #include "i1480u-wlp.h" |
70 | 70 | ||
71 | #define D_LOCAL 0 | 71 | /* |
72 | #include <linux/uwb/debug.h> | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Setup the RX context | 72 | * Setup the RX context |
77 | * | 73 | * |
78 | * Each URB is provided with a transfer_buffer that is the data field | 74 | * Each URB is provided with a transfer_buffer that is the data field |
@@ -129,7 +125,7 @@ error: | |||
129 | } | 125 | } |
130 | 126 | ||
131 | 127 | ||
132 | /** Release resources associated to the rx context */ | 128 | /* Release resources associated to the rx context */ |
133 | void i1480u_rx_release(struct i1480u *i1480u) | 129 | void i1480u_rx_release(struct i1480u *i1480u) |
134 | { | 130 | { |
135 | int cnt; | 131 | int cnt; |
@@ -155,7 +151,7 @@ void i1480u_rx_unlink_urbs(struct i1480u *i1480u) | |||
155 | } | 151 | } |
156 | } | 152 | } |
157 | 153 | ||
158 | /** Fix an out-of-sequence packet */ | 154 | /* Fix an out-of-sequence packet */ |
159 | #define i1480u_fix(i1480u, msg...) \ | 155 | #define i1480u_fix(i1480u, msg...) \ |
160 | do { \ | 156 | do { \ |
161 | if (printk_ratelimit()) \ | 157 | if (printk_ratelimit()) \ |
@@ -166,7 +162,7 @@ do { \ | |||
166 | } while (0) | 162 | } while (0) |
167 | 163 | ||
168 | 164 | ||
169 | /** Drop an out-of-sequence packet */ | 165 | /* Drop an out-of-sequence packet */ |
170 | #define i1480u_drop(i1480u, msg...) \ | 166 | #define i1480u_drop(i1480u, msg...) \ |
171 | do { \ | 167 | do { \ |
172 | if (printk_ratelimit()) \ | 168 | if (printk_ratelimit()) \ |
@@ -177,7 +173,7 @@ do { \ | |||
177 | 173 | ||
178 | 174 | ||
179 | 175 | ||
180 | /** Finalizes setting up the SKB and delivers it | 176 | /* Finalizes setting up the SKB and delivers it |
181 | * | 177 | * |
182 | * We first pass the incoming frame to WLP substack for verification. It | 178 | * We first pass the incoming frame to WLP substack for verification. It |
183 | * may also be a WLP association frame in which case WLP will take over the | 179 | * may also be a WLP association frame in which case WLP will take over the |
@@ -192,18 +188,11 @@ void i1480u_skb_deliver(struct i1480u *i1480u) | |||
192 | struct net_device *net_dev = i1480u->net_dev; | 188 | struct net_device *net_dev = i1480u->net_dev; |
193 | struct device *dev = &i1480u->usb_iface->dev; | 189 | struct device *dev = &i1480u->usb_iface->dev; |
194 | 190 | ||
195 | d_printf(6, dev, "RX delivered pre skb(%p), %u bytes\n", | ||
196 | i1480u->rx_skb, i1480u->rx_skb->len); | ||
197 | d_dump(7, dev, i1480u->rx_skb->data, i1480u->rx_skb->len); | ||
198 | should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb, | 191 | should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb, |
199 | &i1480u->rx_srcaddr); | 192 | &i1480u->rx_srcaddr); |
200 | if (!should_parse) | 193 | if (!should_parse) |
201 | goto out; | 194 | goto out; |
202 | i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev); | 195 | i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev); |
203 | d_printf(5, dev, "RX delivered skb(%p), %u bytes\n", | ||
204 | i1480u->rx_skb, i1480u->rx_skb->len); | ||
205 | d_dump(7, dev, i1480u->rx_skb->data, | ||
206 | i1480u->rx_skb->len > 72 ? 72 : i1480u->rx_skb->len); | ||
207 | i1480u->stats.rx_packets++; | 196 | i1480u->stats.rx_packets++; |
208 | i1480u->stats.rx_bytes += i1480u->rx_untd_pkt_size; | 197 | i1480u->stats.rx_bytes += i1480u->rx_untd_pkt_size; |
209 | net_dev->last_rx = jiffies; | 198 | net_dev->last_rx = jiffies; |
@@ -216,7 +205,7 @@ out: | |||
216 | } | 205 | } |
217 | 206 | ||
218 | 207 | ||
219 | /** | 208 | /* |
220 | * Process a buffer of data received from the USB RX endpoint | 209 | * Process a buffer of data received from the USB RX endpoint |
221 | * | 210 | * |
222 | * First fragment arrives with next or last fragment. All other fragments | 211 | * First fragment arrives with next or last fragment. All other fragments |
@@ -404,7 +393,7 @@ out: | |||
404 | } | 393 | } |
405 | 394 | ||
406 | 395 | ||
407 | /** | 396 | /* |
408 | * Called when an RX URB has finished receiving or has found some kind | 397 | * Called when an RX URB has finished receiving or has found some kind |
409 | * of error condition. | 398 | * of error condition. |
410 | * | 399 | * |
diff --git a/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/drivers/uwb/i1480/i1480u-wlp/sysfs.c index a1d8ca6ac935..4ffaf546cc6c 100644 --- a/drivers/uwb/i1480/i1480u-wlp/sysfs.c +++ b/drivers/uwb/i1480/i1480u-wlp/sysfs.c | |||
@@ -25,8 +25,8 @@ | |||
25 | 25 | ||
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
28 | #include <linux/uwb/debug.h> | ||
29 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | |||
30 | #include "i1480u-wlp.h" | 30 | #include "i1480u-wlp.h" |
31 | 31 | ||
32 | 32 | ||
@@ -226,7 +226,6 @@ ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight, | |||
226 | * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a | 226 | * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a |
227 | * class_device_attr_NAME or device_attr_NAME (for group registration). | 227 | * class_device_attr_NAME or device_attr_NAME (for group registration). |
228 | */ | 228 | */ |
229 | #include <linux/version.h> | ||
230 | 229 | ||
231 | #define i1480u_SHOW(name, fn, param) \ | 230 | #define i1480u_SHOW(name, fn, param) \ |
232 | static ssize_t i1480u_show_##name(struct device *dev, \ | 231 | static ssize_t i1480u_show_##name(struct device *dev, \ |
diff --git a/drivers/uwb/i1480/i1480u-wlp/tx.c b/drivers/uwb/i1480/i1480u-wlp/tx.c index 3426bfb68240..39032cc3503e 100644 --- a/drivers/uwb/i1480/i1480u-wlp/tx.c +++ b/drivers/uwb/i1480/i1480u-wlp/tx.c | |||
@@ -55,8 +55,6 @@ | |||
55 | */ | 55 | */ |
56 | 56 | ||
57 | #include "i1480u-wlp.h" | 57 | #include "i1480u-wlp.h" |
58 | #define D_LOCAL 5 | ||
59 | #include <linux/uwb/debug.h> | ||
60 | 58 | ||
61 | enum { | 59 | enum { |
62 | /* This is only for Next and Last TX packets */ | 60 | /* This is only for Next and Last TX packets */ |
@@ -64,7 +62,7 @@ enum { | |||
64 | - sizeof(struct untd_hdr_rst), | 62 | - sizeof(struct untd_hdr_rst), |
65 | }; | 63 | }; |
66 | 64 | ||
67 | /** Free resources allocated to a i1480u tx context. */ | 65 | /* Free resources allocated to a i1480u tx context. */ |
68 | static | 66 | static |
69 | void i1480u_tx_free(struct i1480u_tx *wtx) | 67 | void i1480u_tx_free(struct i1480u_tx *wtx) |
70 | { | 68 | { |
@@ -99,7 +97,7 @@ void i1480u_tx_unlink_urbs(struct i1480u *i1480u) | |||
99 | } | 97 | } |
100 | 98 | ||
101 | 99 | ||
102 | /** | 100 | /* |
103 | * Callback for a completed tx USB URB. | 101 | * Callback for a completed tx USB URB. |
104 | * | 102 | * |
105 | * TODO: | 103 | * TODO: |
@@ -149,8 +147,6 @@ void i1480u_tx_cb(struct urb *urb) | |||
149 | <= i1480u->tx_inflight.threshold | 147 | <= i1480u->tx_inflight.threshold |
150 | && netif_queue_stopped(net_dev) | 148 | && netif_queue_stopped(net_dev) |
151 | && i1480u->tx_inflight.threshold != 0) { | 149 | && i1480u->tx_inflight.threshold != 0) { |
152 | if (d_test(2) && printk_ratelimit()) | ||
153 | d_printf(2, dev, "Restart queue. \n"); | ||
154 | netif_start_queue(net_dev); | 150 | netif_start_queue(net_dev); |
155 | atomic_inc(&i1480u->tx_inflight.restart_count); | 151 | atomic_inc(&i1480u->tx_inflight.restart_count); |
156 | } | 152 | } |
@@ -158,7 +154,7 @@ void i1480u_tx_cb(struct urb *urb) | |||
158 | } | 154 | } |
159 | 155 | ||
160 | 156 | ||
161 | /** | 157 | /* |
162 | * Given a buffer that doesn't fit in a single fragment, create an | 158 | * Given a buffer that doesn't fit in a single fragment, create an |
163 | * scatter/gather structure for delivery to the USB pipe. | 159 | * scatter/gather structure for delivery to the USB pipe. |
164 | * | 160 | * |
@@ -253,15 +249,11 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb, | |||
253 | /* Now do each remaining fragment */ | 249 | /* Now do each remaining fragment */ |
254 | result = -EINVAL; | 250 | result = -EINVAL; |
255 | while (pl_size_left > 0) { | 251 | while (pl_size_left > 0) { |
256 | d_printf(5, NULL, "ITR HDR: pl_size_left %zu buf_itr %zu\n", | ||
257 | pl_size_left, buf_itr - wtx->buf); | ||
258 | if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf | 252 | if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf |
259 | > wtx->buf_size) { | 253 | > wtx->buf_size) { |
260 | printk(KERN_ERR "BUG: no space for header\n"); | 254 | printk(KERN_ERR "BUG: no space for header\n"); |
261 | goto error_bug; | 255 | goto error_bug; |
262 | } | 256 | } |
263 | d_printf(5, NULL, "ITR HDR 2: pl_size_left %zu buf_itr %zu\n", | ||
264 | pl_size_left, buf_itr - wtx->buf); | ||
265 | untd_hdr_rst = buf_itr; | 257 | untd_hdr_rst = buf_itr; |
266 | buf_itr += sizeof(*untd_hdr_rst); | 258 | buf_itr += sizeof(*untd_hdr_rst); |
267 | if (pl_size_left > i1480u_MAX_PL_SIZE) { | 259 | if (pl_size_left > i1480u_MAX_PL_SIZE) { |
@@ -271,9 +263,6 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb, | |||
271 | frg_pl_size = pl_size_left; | 263 | frg_pl_size = pl_size_left; |
272 | untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST); | 264 | untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST); |
273 | } | 265 | } |
274 | d_printf(5, NULL, | ||
275 | "ITR PL: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n", | ||
276 | pl_size_left, buf_itr - wtx->buf, frg_pl_size); | ||
277 | untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0); | 266 | untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0); |
278 | untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size); | 267 | untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size); |
279 | untd_hdr_rst->padding = 0; | 268 | untd_hdr_rst->padding = 0; |
@@ -286,9 +275,6 @@ int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb, | |||
286 | buf_itr += frg_pl_size; | 275 | buf_itr += frg_pl_size; |
287 | pl_itr += frg_pl_size; | 276 | pl_itr += frg_pl_size; |
288 | pl_size_left -= frg_pl_size; | 277 | pl_size_left -= frg_pl_size; |
289 | d_printf(5, NULL, | ||
290 | "ITR PL 2: pl_size_left %zu buf_itr %zu frg_pl_size %zu\n", | ||
291 | pl_size_left, buf_itr - wtx->buf, frg_pl_size); | ||
292 | } | 278 | } |
293 | dev_kfree_skb_irq(skb); | 279 | dev_kfree_skb_irq(skb); |
294 | return 0; | 280 | return 0; |
@@ -308,7 +294,7 @@ error_buf_alloc: | |||
308 | } | 294 | } |
309 | 295 | ||
310 | 296 | ||
311 | /** | 297 | /* |
312 | * Given a buffer that fits in a single fragment, fill out a @wtx | 298 | * Given a buffer that fits in a single fragment, fill out a @wtx |
313 | * struct for transmitting it down the USB pipe. | 299 | * struct for transmitting it down the USB pipe. |
314 | * | 300 | * |
@@ -346,7 +332,7 @@ int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb, | |||
346 | } | 332 | } |
347 | 333 | ||
348 | 334 | ||
349 | /** | 335 | /* |
350 | * Given a skb to transmit, massage it to become palatable for the TX pipe | 336 | * Given a skb to transmit, massage it to become palatable for the TX pipe |
351 | * | 337 | * |
352 | * This will break the buffer in chunks smaller than | 338 | * This will break the buffer in chunks smaller than |
@@ -425,7 +411,7 @@ error_wtx_alloc: | |||
425 | return NULL; | 411 | return NULL; |
426 | } | 412 | } |
427 | 413 | ||
428 | /** | 414 | /* |
429 | * Actual fragmentation and transmission of frame | 415 | * Actual fragmentation and transmission of frame |
430 | * | 416 | * |
431 | * @wlp: WLP substack data structure | 417 | * @wlp: WLP substack data structure |
@@ -447,20 +433,12 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb, | |||
447 | struct i1480u_tx *wtx; | 433 | struct i1480u_tx *wtx; |
448 | struct wlp_tx_hdr *wlp_tx_hdr; | 434 | struct wlp_tx_hdr *wlp_tx_hdr; |
449 | static unsigned char dev_bcast[2] = { 0xff, 0xff }; | 435 | static unsigned char dev_bcast[2] = { 0xff, 0xff }; |
450 | #if 0 | ||
451 | int lockup = 50; | ||
452 | #endif | ||
453 | 436 | ||
454 | d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len, | ||
455 | net_dev); | ||
456 | BUG_ON(i1480u->wlp.rc == NULL); | 437 | BUG_ON(i1480u->wlp.rc == NULL); |
457 | if ((net_dev->flags & IFF_UP) == 0) | 438 | if ((net_dev->flags & IFF_UP) == 0) |
458 | goto out; | 439 | goto out; |
459 | result = -EBUSY; | 440 | result = -EBUSY; |
460 | if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) { | 441 | if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) { |
461 | if (d_test(2) && printk_ratelimit()) | ||
462 | d_printf(2, dev, "Max frames in flight " | ||
463 | "stopping queue.\n"); | ||
464 | netif_stop_queue(net_dev); | 442 | netif_stop_queue(net_dev); |
465 | goto error_max_inflight; | 443 | goto error_max_inflight; |
466 | } | 444 | } |
@@ -489,21 +467,6 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb, | |||
489 | wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority); | 467 | wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority); |
490 | } | 468 | } |
491 | 469 | ||
492 | #if 0 | ||
493 | dev_info(dev, "TX delivering skb -> USB, %zu bytes\n", skb->len); | ||
494 | dump_bytes(dev, skb->data, skb->len > 72 ? 72 : skb->len); | ||
495 | #endif | ||
496 | #if 0 | ||
497 | /* simulates a device lockup after every lockup# packets */ | ||
498 | if (lockup && ((i1480u->stats.tx_packets + 1) % lockup) == 0) { | ||
499 | /* Simulate a dropped transmit interrupt */ | ||
500 | net_dev->trans_start = jiffies; | ||
501 | netif_stop_queue(net_dev); | ||
502 | dev_err(dev, "Simulate lockup at %ld\n", jiffies); | ||
503 | return result; | ||
504 | } | ||
505 | #endif | ||
506 | |||
507 | result = usb_submit_urb(wtx->urb, GFP_ATOMIC); /* Go baby */ | 470 | result = usb_submit_urb(wtx->urb, GFP_ATOMIC); /* Go baby */ |
508 | if (result < 0) { | 471 | if (result < 0) { |
509 | dev_err(dev, "TX: cannot submit URB: %d\n", result); | 472 | dev_err(dev, "TX: cannot submit URB: %d\n", result); |
@@ -513,8 +476,6 @@ int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb, | |||
513 | } | 476 | } |
514 | atomic_inc(&i1480u->tx_inflight.count); | 477 | atomic_inc(&i1480u->tx_inflight.count); |
515 | net_dev->trans_start = jiffies; | 478 | net_dev->trans_start = jiffies; |
516 | d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, | ||
517 | net_dev, result); | ||
518 | return result; | 479 | return result; |
519 | 480 | ||
520 | error_tx_urb_submit: | 481 | error_tx_urb_submit: |
@@ -522,13 +483,11 @@ error_tx_urb_submit: | |||
522 | error_wtx_alloc: | 483 | error_wtx_alloc: |
523 | error_max_inflight: | 484 | error_max_inflight: |
524 | out: | 485 | out: |
525 | d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, | ||
526 | net_dev, result); | ||
527 | return result; | 486 | return result; |
528 | } | 487 | } |
529 | 488 | ||
530 | 489 | ||
531 | /** | 490 | /* |
532 | * Transmit an skb Called when an skbuf has to be transmitted | 491 | * Transmit an skb Called when an skbuf has to be transmitted |
533 | * | 492 | * |
534 | * The skb is first passed to WLP substack to ensure this is a valid | 493 | * The skb is first passed to WLP substack to ensure this is a valid |
@@ -551,9 +510,6 @@ int i1480u_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) | |||
551 | struct device *dev = &i1480u->usb_iface->dev; | 510 | struct device *dev = &i1480u->usb_iface->dev; |
552 | struct uwb_dev_addr dst; | 511 | struct uwb_dev_addr dst; |
553 | 512 | ||
554 | d_fnstart(6, dev, "(skb %p (%u), net_dev %p)\n", skb, skb->len, | ||
555 | net_dev); | ||
556 | BUG_ON(i1480u->wlp.rc == NULL); | ||
557 | if ((net_dev->flags & IFF_UP) == 0) | 513 | if ((net_dev->flags & IFF_UP) == 0) |
558 | goto error; | 514 | goto error; |
559 | result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst); | 515 | result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst); |
@@ -562,31 +518,25 @@ int i1480u_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) | |||
562 | "Dropping packet.\n", result); | 518 | "Dropping packet.\n", result); |
563 | goto error; | 519 | goto error; |
564 | } else if (result == 1) { | 520 | } else if (result == 1) { |
565 | d_printf(6, dev, "WLP will transmit frame. \n"); | ||
566 | /* trans_start time will be set when WLP actually transmits | 521 | /* trans_start time will be set when WLP actually transmits |
567 | * the frame */ | 522 | * the frame */ |
568 | goto out; | 523 | goto out; |
569 | } | 524 | } |
570 | d_printf(6, dev, "Transmitting frame. \n"); | ||
571 | result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst); | 525 | result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst); |
572 | if (result < 0) { | 526 | if (result < 0) { |
573 | dev_err(dev, "Frame TX failed (%d).\n", result); | 527 | dev_err(dev, "Frame TX failed (%d).\n", result); |
574 | goto error; | 528 | goto error; |
575 | } | 529 | } |
576 | d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, | ||
577 | net_dev, result); | ||
578 | return NETDEV_TX_OK; | 530 | return NETDEV_TX_OK; |
579 | error: | 531 | error: |
580 | dev_kfree_skb_any(skb); | 532 | dev_kfree_skb_any(skb); |
581 | i1480u->stats.tx_dropped++; | 533 | i1480u->stats.tx_dropped++; |
582 | out: | 534 | out: |
583 | d_fnend(6, dev, "(skb %p (%u), net_dev %p) = %d\n", skb, skb->len, | ||
584 | net_dev, result); | ||
585 | return NETDEV_TX_OK; | 535 | return NETDEV_TX_OK; |
586 | } | 536 | } |
587 | 537 | ||
588 | 538 | ||
589 | /** | 539 | /* |
590 | * Called when a pkt transmission doesn't complete in a reasonable period | 540 | * Called when a pkt transmission doesn't complete in a reasonable period |
591 | * Device reset may sleep - do it outside of interrupt context (delayed) | 541 | * Device reset may sleep - do it outside of interrupt context (delayed) |
592 | */ | 542 | */ |
diff --git a/drivers/uwb/ie-rcv.c b/drivers/uwb/ie-rcv.c new file mode 100644 index 000000000000..917e6d78a798 --- /dev/null +++ b/drivers/uwb/ie-rcv.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Ultra Wide Band | ||
3 | * IE Received notification handling. | ||
4 | * | ||
5 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/bitmap.h> | ||
24 | #include "uwb-internal.h" | ||
25 | |||
26 | /* | ||
27 | * Process an incoming IE Received notification. | ||
28 | */ | ||
29 | int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *evt) | ||
30 | { | ||
31 | int result = -EINVAL; | ||
32 | struct device *dev = &evt->rc->uwb_dev.dev; | ||
33 | struct uwb_rc_evt_ie_rcv *iercv; | ||
34 | size_t iesize; | ||
35 | |||
36 | /* Is there enough data to decode it? */ | ||
37 | if (evt->notif.size < sizeof(*iercv)) { | ||
38 | dev_err(dev, "IE Received notification: Not enough data to " | ||
39 | "decode (%zu vs %zu bytes needed)\n", | ||
40 | evt->notif.size, sizeof(*iercv)); | ||
41 | goto error; | ||
42 | } | ||
43 | iercv = container_of(evt->notif.rceb, struct uwb_rc_evt_ie_rcv, rceb); | ||
44 | iesize = le16_to_cpu(iercv->wIELength); | ||
45 | |||
46 | dev_dbg(dev, "IE received, element ID=%d\n", iercv->IEData[0]); | ||
47 | |||
48 | if (iercv->IEData[0] == UWB_RELINQUISH_REQUEST_IE) { | ||
49 | dev_warn(dev, "unhandled Relinquish Request IE\n"); | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | error: | ||
54 | return result; | ||
55 | } | ||
diff --git a/drivers/uwb/ie.c b/drivers/uwb/ie.c index cf6f3d152b9d..ab976686175b 100644 --- a/drivers/uwb/ie.c +++ b/drivers/uwb/ie.c | |||
@@ -25,8 +25,6 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include "uwb-internal.h" | 27 | #include "uwb-internal.h" |
28 | #define D_LOCAL 0 | ||
29 | #include <linux/uwb/debug.h> | ||
30 | 28 | ||
31 | /** | 29 | /** |
32 | * uwb_ie_next - get the next IE in a buffer | 30 | * uwb_ie_next - get the next IE in a buffer |
@@ -61,6 +59,42 @@ struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len) | |||
61 | EXPORT_SYMBOL_GPL(uwb_ie_next); | 59 | EXPORT_SYMBOL_GPL(uwb_ie_next); |
62 | 60 | ||
63 | /** | 61 | /** |
62 | * uwb_ie_dump_hex - print IEs to a character buffer | ||
63 | * @ies: the IEs to print. | ||
64 | * @len: length of all the IEs. | ||
65 | * @buf: the destination buffer. | ||
66 | * @size: size of @buf. | ||
67 | * | ||
68 | * Returns the number of characters written. | ||
69 | */ | ||
70 | int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len, | ||
71 | char *buf, size_t size) | ||
72 | { | ||
73 | void *ptr; | ||
74 | const struct uwb_ie_hdr *ie; | ||
75 | int r = 0; | ||
76 | u8 *d; | ||
77 | |||
78 | ptr = (void *)ies; | ||
79 | for (;;) { | ||
80 | ie = uwb_ie_next(&ptr, &len); | ||
81 | if (!ie) | ||
82 | break; | ||
83 | |||
84 | r += scnprintf(buf + r, size - r, "%02x %02x", | ||
85 | (unsigned)ie->element_id, | ||
86 | (unsigned)ie->length); | ||
87 | d = (uint8_t *)ie + sizeof(struct uwb_ie_hdr); | ||
88 | while (d != ptr && r < size) | ||
89 | r += scnprintf(buf + r, size - r, " %02x", (unsigned)*d++); | ||
90 | if (r < size) | ||
91 | buf[r++] = '\n'; | ||
92 | }; | ||
93 | |||
94 | return r; | ||
95 | } | ||
96 | |||
97 | /** | ||
64 | * Get the IEs that a radio controller is sending in its beacon | 98 | * Get the IEs that a radio controller is sending in its beacon |
65 | * | 99 | * |
66 | * @uwb_rc: UWB Radio Controller | 100 | * @uwb_rc: UWB Radio Controller |
@@ -70,6 +104,7 @@ EXPORT_SYMBOL_GPL(uwb_ie_next); | |||
70 | * anything. Once done with the iedata buffer, call | 104 | * anything. Once done with the iedata buffer, call |
71 | * uwb_rc_ie_release(iedata). Don't call kfree on it. | 105 | * uwb_rc_ie_release(iedata). Don't call kfree on it. |
72 | */ | 106 | */ |
107 | static | ||
73 | ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) | 108 | ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) |
74 | { | 109 | { |
75 | ssize_t result; | 110 | ssize_t result; |
@@ -78,148 +113,35 @@ ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) | |||
78 | struct uwb_rceb *reply = NULL; | 113 | struct uwb_rceb *reply = NULL; |
79 | struct uwb_rc_evt_get_ie *get_ie; | 114 | struct uwb_rc_evt_get_ie *get_ie; |
80 | 115 | ||
81 | d_fnstart(3, dev, "(%p, %p)\n", uwb_rc, pget_ie); | ||
82 | result = -ENOMEM; | ||
83 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 116 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
84 | if (cmd == NULL) | 117 | if (cmd == NULL) |
85 | goto error_kzalloc; | 118 | return -ENOMEM; |
119 | |||
86 | cmd->bCommandType = UWB_RC_CET_GENERAL; | 120 | cmd->bCommandType = UWB_RC_CET_GENERAL; |
87 | cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); | 121 | cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); |
88 | result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), | 122 | result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), |
89 | UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, | 123 | UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, |
90 | &reply); | 124 | &reply); |
125 | kfree(cmd); | ||
91 | if (result < 0) | 126 | if (result < 0) |
92 | goto error_cmd; | 127 | return result; |
128 | |||
93 | get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); | 129 | get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); |
94 | if (result < sizeof(*get_ie)) { | 130 | if (result < sizeof(*get_ie)) { |
95 | dev_err(dev, "not enough data returned for decoding GET IE " | 131 | dev_err(dev, "not enough data returned for decoding GET IE " |
96 | "(%zu bytes received vs %zu needed)\n", | 132 | "(%zu bytes received vs %zu needed)\n", |
97 | result, sizeof(*get_ie)); | 133 | result, sizeof(*get_ie)); |
98 | result = -EINVAL; | 134 | return -EINVAL; |
99 | } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { | 135 | } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { |
100 | dev_err(dev, "not enough data returned for decoding GET IE " | 136 | dev_err(dev, "not enough data returned for decoding GET IE " |
101 | "payload (%zu bytes received vs %zu needed)\n", result, | 137 | "payload (%zu bytes received vs %zu needed)\n", result, |
102 | sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); | 138 | sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); |
103 | result = -EINVAL; | ||
104 | } else | ||
105 | *pget_ie = get_ie; | ||
106 | error_cmd: | ||
107 | kfree(cmd); | ||
108 | error_kzalloc: | ||
109 | d_fnend(3, dev, "(%p, %p) = %d\n", uwb_rc, pget_ie, (int)result); | ||
110 | return result; | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(uwb_rc_get_ie); | ||
113 | |||
114 | |||
115 | /* | ||
116 | * Given a pointer to an IE, print it in ASCII/hex followed by a new line | ||
117 | * | ||
118 | * @ie_hdr: pointer to the IE header. Length is in there, and it is | ||
119 | * guaranteed that the ie_hdr->length bytes following it are | ||
120 | * safely accesible. | ||
121 | * | ||
122 | * @_data: context data passed from uwb_ie_for_each(), an struct output_ctx | ||
123 | */ | ||
124 | int uwb_ie_dump_hex(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | ||
125 | size_t offset, void *_ctx) | ||
126 | { | ||
127 | struct uwb_buf_ctx *ctx = _ctx; | ||
128 | const u8 *pl = (void *)(ie_hdr + 1); | ||
129 | u8 pl_itr; | ||
130 | |||
131 | ctx->bytes += scnprintf(ctx->buf + ctx->bytes, ctx->size - ctx->bytes, | ||
132 | "%02x %02x ", (unsigned) ie_hdr->element_id, | ||
133 | (unsigned) ie_hdr->length); | ||
134 | pl_itr = 0; | ||
135 | while (pl_itr < ie_hdr->length && ctx->bytes < ctx->size) | ||
136 | ctx->bytes += scnprintf(ctx->buf + ctx->bytes, | ||
137 | ctx->size - ctx->bytes, | ||
138 | "%02x ", (unsigned) pl[pl_itr++]); | ||
139 | if (ctx->bytes < ctx->size) | ||
140 | ctx->buf[ctx->bytes++] = '\n'; | ||
141 | return 0; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(uwb_ie_dump_hex); | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Verify that a pointer in a buffer points to valid IE | ||
148 | * | ||
149 | * @start: pointer to start of buffer in which IE appears | ||
150 | * @itr: pointer to IE inside buffer that will be verified | ||
151 | * @top: pointer to end of buffer | ||
152 | * | ||
153 | * @returns: 0 if IE is valid, <0 otherwise | ||
154 | * | ||
155 | * Verification involves checking that the buffer can contain a | ||
156 | * header and the amount of data reported in the IE header can be found in | ||
157 | * the buffer. | ||
158 | */ | ||
159 | static | ||
160 | int uwb_rc_ie_verify(struct uwb_dev *uwb_dev, const void *start, | ||
161 | const void *itr, const void *top) | ||
162 | { | ||
163 | struct device *dev = &uwb_dev->dev; | ||
164 | const struct uwb_ie_hdr *ie_hdr; | ||
165 | |||
166 | if (top - itr < sizeof(*ie_hdr)) { | ||
167 | dev_err(dev, "Bad IE: no data to decode header " | ||
168 | "(%zu bytes left vs %zu needed) at offset %zu\n", | ||
169 | top - itr, sizeof(*ie_hdr), itr - start); | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | ie_hdr = itr; | ||
173 | itr += sizeof(*ie_hdr); | ||
174 | if (top - itr < ie_hdr->length) { | ||
175 | dev_err(dev, "Bad IE: not enough data for payload " | ||
176 | "(%zu bytes left vs %zu needed) at offset %zu\n", | ||
177 | top - itr, (size_t)ie_hdr->length, | ||
178 | (void *)ie_hdr - start); | ||
179 | return -EINVAL; | 139 | return -EINVAL; |
180 | } | 140 | } |
181 | return 0; | ||
182 | } | ||
183 | 141 | ||
184 | 142 | *pget_ie = get_ie; | |
185 | /** | ||
186 | * Walk a buffer filled with consecutive IE's a buffer | ||
187 | * | ||
188 | * @uwb_dev: UWB device this IEs belong to (for err messages mainly) | ||
189 | * | ||
190 | * @fn: function to call with each IE; if it returns 0, we keep | ||
191 | * traversing the buffer. If it returns !0, we'll stop and return | ||
192 | * that value. | ||
193 | * | ||
194 | * @data: pointer passed to @fn | ||
195 | * | ||
196 | * @buf: buffer where the consecutive IEs are located | ||
197 | * | ||
198 | * @size: size of @buf | ||
199 | * | ||
200 | * Each IE is checked for basic correctness (there is space left for | ||
201 | * the header and the payload). If that test is failed, we stop | ||
202 | * processing. For every good IE, @fn is called. | ||
203 | */ | ||
204 | ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, | ||
205 | const void *buf, size_t size) | ||
206 | { | ||
207 | ssize_t result = 0; | ||
208 | const struct uwb_ie_hdr *ie_hdr; | ||
209 | const void *itr = buf, *top = itr + size; | ||
210 | |||
211 | while (itr < top) { | ||
212 | if (uwb_rc_ie_verify(uwb_dev, buf, itr, top) != 0) | ||
213 | break; | ||
214 | ie_hdr = itr; | ||
215 | itr += sizeof(*ie_hdr) + ie_hdr->length; | ||
216 | result = fn(uwb_dev, ie_hdr, itr - buf, data); | ||
217 | if (result != 0) | ||
218 | break; | ||
219 | } | ||
220 | return result; | 143 | return result; |
221 | } | 144 | } |
222 | EXPORT_SYMBOL_GPL(uwb_ie_for_each); | ||
223 | 145 | ||
224 | 146 | ||
225 | /** | 147 | /** |
@@ -256,70 +178,6 @@ error_cmd: | |||
256 | return result; | 178 | return result; |
257 | } | 179 | } |
258 | 180 | ||
259 | /** | ||
260 | * Determine by IE id if IE is host settable | ||
261 | * WUSB 1.0 [8.6.2.8 Table 8.85] | ||
262 | * | ||
263 | * EXCEPTION: | ||
264 | * All but UWB_IE_WLP appears in Table 8.85 from WUSB 1.0. Setting this IE | ||
265 | * is required for the WLP substack to perform association with its WSS so | ||
266 | * we hope that the WUSB spec will be changed to reflect this. | ||
267 | */ | ||
268 | static | ||
269 | int uwb_rc_ie_is_host_settable(enum uwb_ie element_id) | ||
270 | { | ||
271 | if (element_id == UWB_PCA_AVAILABILITY || | ||
272 | element_id == UWB_BP_SWITCH_IE || | ||
273 | element_id == UWB_MAC_CAPABILITIES_IE || | ||
274 | element_id == UWB_PHY_CAPABILITIES_IE || | ||
275 | element_id == UWB_APP_SPEC_PROBE_IE || | ||
276 | element_id == UWB_IDENTIFICATION_IE || | ||
277 | element_id == UWB_MASTER_KEY_ID_IE || | ||
278 | element_id == UWB_IE_WLP || | ||
279 | element_id == UWB_APP_SPEC_IE) | ||
280 | return 1; | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Extract Host Settable IEs from IE | ||
287 | * | ||
288 | * @ie_data: pointer to buffer containing all IEs | ||
289 | * @size: size of buffer | ||
290 | * | ||
291 | * @returns: length of buffer that only includes host settable IEs | ||
292 | * | ||
293 | * Given a buffer of IEs we move all Host Settable IEs to front of buffer | ||
294 | * by overwriting the IEs that are not Host Settable. | ||
295 | * Buffer length is adjusted accordingly. | ||
296 | */ | ||
297 | static | ||
298 | ssize_t uwb_rc_parse_host_settable_ie(struct uwb_dev *uwb_dev, | ||
299 | void *ie_data, size_t size) | ||
300 | { | ||
301 | size_t new_len = size; | ||
302 | struct uwb_ie_hdr *ie_hdr; | ||
303 | size_t ie_length; | ||
304 | void *itr = ie_data, *top = itr + size; | ||
305 | |||
306 | while (itr < top) { | ||
307 | if (uwb_rc_ie_verify(uwb_dev, ie_data, itr, top) != 0) | ||
308 | break; | ||
309 | ie_hdr = itr; | ||
310 | ie_length = sizeof(*ie_hdr) + ie_hdr->length; | ||
311 | if (uwb_rc_ie_is_host_settable(ie_hdr->element_id)) { | ||
312 | itr += ie_length; | ||
313 | } else { | ||
314 | memmove(itr, itr + ie_length, top - (itr + ie_length)); | ||
315 | new_len -= ie_length; | ||
316 | top -= ie_length; | ||
317 | } | ||
318 | } | ||
319 | return new_len; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* Cleanup the whole IE management subsystem */ | 181 | /* Cleanup the whole IE management subsystem */ |
324 | void uwb_rc_ie_init(struct uwb_rc *uwb_rc) | 182 | void uwb_rc_ie_init(struct uwb_rc *uwb_rc) |
325 | { | 183 | { |
@@ -328,49 +186,34 @@ void uwb_rc_ie_init(struct uwb_rc *uwb_rc) | |||
328 | 186 | ||
329 | 187 | ||
330 | /** | 188 | /** |
331 | * Set up cache for host settable IEs currently being transmitted | 189 | * uwb_rc_ie_setup - setup a radio controller's IE manager |
190 | * @uwb_rc: the radio controller. | ||
332 | * | 191 | * |
333 | * First we just call GET-IE to get the current IEs being transmitted | 192 | * The current set of IEs are obtained from the hardware with a GET-IE |
334 | * (or we workaround and pretend we did) and (because the format is | 193 | * command (since the radio controller is not yet beaconing this will |
335 | * the same) reuse that as the IE cache (with the command prefix, as | 194 | * be just the hardware's MAC and PHY Capability IEs). |
336 | * explained in 'struct uwb_rc'). | ||
337 | * | 195 | * |
338 | * @returns: size of cache created | 196 | * Returns 0 on success; -ve on an error. |
339 | */ | 197 | */ |
340 | ssize_t uwb_rc_ie_setup(struct uwb_rc *uwb_rc) | 198 | int uwb_rc_ie_setup(struct uwb_rc *uwb_rc) |
341 | { | 199 | { |
342 | struct device *dev = &uwb_rc->uwb_dev.dev; | 200 | struct uwb_rc_evt_get_ie *ie_info = NULL; |
343 | ssize_t result; | 201 | int capacity; |
344 | size_t capacity; | 202 | |
345 | struct uwb_rc_evt_get_ie *ie_info; | 203 | capacity = uwb_rc_get_ie(uwb_rc, &ie_info); |
204 | if (capacity < 0) | ||
205 | return capacity; | ||
346 | 206 | ||
347 | d_fnstart(3, dev, "(%p)\n", uwb_rc); | ||
348 | mutex_lock(&uwb_rc->ies_mutex); | 207 | mutex_lock(&uwb_rc->ies_mutex); |
349 | result = uwb_rc_get_ie(uwb_rc, &ie_info); | 208 | |
350 | if (result < 0) | 209 | uwb_rc->ies = (struct uwb_rc_cmd_set_ie *)ie_info; |
351 | goto error_get_ie; | ||
352 | capacity = result; | ||
353 | d_printf(5, dev, "Got IEs %zu bytes (%zu long at %p)\n", result, | ||
354 | (size_t)le16_to_cpu(ie_info->wIELength), ie_info); | ||
355 | |||
356 | /* Remove IEs that host should not set. */ | ||
357 | result = uwb_rc_parse_host_settable_ie(&uwb_rc->uwb_dev, | ||
358 | ie_info->IEData, le16_to_cpu(ie_info->wIELength)); | ||
359 | if (result < 0) | ||
360 | goto error_parse; | ||
361 | d_printf(5, dev, "purged non-settable IEs to %zu bytes\n", result); | ||
362 | uwb_rc->ies = (void *) ie_info; | ||
363 | uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL; | 210 | uwb_rc->ies->rccb.bCommandType = UWB_RC_CET_GENERAL; |
364 | uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE); | 211 | uwb_rc->ies->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SET_IE); |
365 | uwb_rc->ies_capacity = capacity; | 212 | uwb_rc->ies_capacity = capacity; |
366 | d_printf(5, dev, "IE cache at %p %zu bytes, %zu capacity\n", | 213 | |
367 | ie_info, result, capacity); | ||
368 | result = 0; | ||
369 | error_parse: | ||
370 | error_get_ie: | ||
371 | mutex_unlock(&uwb_rc->ies_mutex); | 214 | mutex_unlock(&uwb_rc->ies_mutex); |
372 | d_fnend(3, dev, "(%p) = %zu\n", uwb_rc, result); | 215 | |
373 | return result; | 216 | return 0; |
374 | } | 217 | } |
375 | 218 | ||
376 | 219 | ||
@@ -383,26 +226,47 @@ void uwb_rc_ie_release(struct uwb_rc *uwb_rc) | |||
383 | } | 226 | } |
384 | 227 | ||
385 | 228 | ||
386 | static | 229 | static int uwb_rc_ie_add_one(struct uwb_rc *rc, const struct uwb_ie_hdr *new_ie) |
387 | int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | ||
388 | size_t offset, void *_ctx) | ||
389 | { | 230 | { |
390 | size_t *acc_size = _ctx; | 231 | struct uwb_rc_cmd_set_ie *new_ies; |
391 | *acc_size += sizeof(*ie_hdr) + ie_hdr->length; | 232 | void *ptr, *prev_ie; |
392 | d_printf(6, &uwb_dev->dev, "new acc size %zu\n", *acc_size); | 233 | struct uwb_ie_hdr *ie; |
234 | size_t length, new_ie_len, new_capacity, size, prev_size; | ||
235 | |||
236 | length = le16_to_cpu(rc->ies->wIELength); | ||
237 | new_ie_len = sizeof(struct uwb_ie_hdr) + new_ie->length; | ||
238 | new_capacity = sizeof(struct uwb_rc_cmd_set_ie) + length + new_ie_len; | ||
239 | |||
240 | if (new_capacity > rc->ies_capacity) { | ||
241 | new_ies = krealloc(rc->ies, new_capacity, GFP_KERNEL); | ||
242 | if (!new_ies) | ||
243 | return -ENOMEM; | ||
244 | rc->ies = new_ies; | ||
245 | } | ||
246 | |||
247 | ptr = rc->ies->IEData; | ||
248 | size = length; | ||
249 | for (;;) { | ||
250 | prev_ie = ptr; | ||
251 | prev_size = size; | ||
252 | ie = uwb_ie_next(&ptr, &size); | ||
253 | if (!ie || ie->element_id > new_ie->element_id) | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | memmove(prev_ie + new_ie_len, prev_ie, prev_size); | ||
258 | memcpy(prev_ie, new_ie, new_ie_len); | ||
259 | rc->ies->wIELength = cpu_to_le16(length + new_ie_len); | ||
260 | |||
393 | return 0; | 261 | return 0; |
394 | } | 262 | } |
395 | 263 | ||
396 | |||
397 | /** | 264 | /** |
398 | * Add a new IE to IEs currently being transmitted by device | 265 | * uwb_rc_ie_add - add new IEs to the radio controller's beacon |
399 | * | 266 | * @uwb_rc: the radio controller. |
400 | * @ies: the buffer containing the new IE or IEs to be added to | 267 | * @ies: the buffer containing the new IE or IEs to be added to |
401 | * the device's beacon. The buffer will be verified for | 268 | * the device's beacon. |
402 | * consistence (meaning the headers should be right) and | 269 | * @size: length of all the IEs. |
403 | * consistent with the buffer size. | ||
404 | * @size: size of @ies (in bytes, total buffer size) | ||
405 | * @returns: 0 if ok, <0 errno code on error | ||
406 | * | 270 | * |
407 | * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB | 271 | * According to WHCI 0.95 [4.13.6] the driver will only receive the RCEB |
408 | * after the device sent the first beacon that includes the IEs specified | 272 | * after the device sent the first beacon that includes the IEs specified |
@@ -411,66 +275,40 @@ int __acc_size(struct uwb_dev *uwb_dev, const struct uwb_ie_hdr *ie_hdr, | |||
411 | * we start beaconing. | 275 | * we start beaconing. |
412 | * | 276 | * |
413 | * Setting an IE on the device will overwrite all current IEs in device. So | 277 | * Setting an IE on the device will overwrite all current IEs in device. So |
414 | * we take the current IEs being transmitted by the device, append the | 278 | * we take the current IEs being transmitted by the device, insert the |
415 | * new one, and call SET IE with all the IEs needed. | 279 | * new one, and call SET IE with all the IEs needed. |
416 | * | 280 | * |
417 | * The local IE cache will only be updated with the new IE if SET IE | 281 | * Returns 0 on success; or -ENOMEM. |
418 | * completed successfully. | ||
419 | */ | 282 | */ |
420 | int uwb_rc_ie_add(struct uwb_rc *uwb_rc, | 283 | int uwb_rc_ie_add(struct uwb_rc *uwb_rc, |
421 | const struct uwb_ie_hdr *ies, size_t size) | 284 | const struct uwb_ie_hdr *ies, size_t size) |
422 | { | 285 | { |
423 | int result = 0; | 286 | int result = 0; |
424 | struct device *dev = &uwb_rc->uwb_dev.dev; | 287 | void *ptr; |
425 | struct uwb_rc_cmd_set_ie *new_ies; | 288 | const struct uwb_ie_hdr *ie; |
426 | size_t ies_size, total_size, acc_size = 0; | 289 | |
427 | |||
428 | if (uwb_rc->ies == NULL) | ||
429 | return -ESHUTDOWN; | ||
430 | uwb_ie_for_each(&uwb_rc->uwb_dev, __acc_size, &acc_size, ies, size); | ||
431 | if (acc_size != size) { | ||
432 | dev_err(dev, "BUG: bad IEs, misconstructed headers " | ||
433 | "[%zu bytes reported vs %zu calculated]\n", | ||
434 | size, acc_size); | ||
435 | WARN_ON(1); | ||
436 | return -EINVAL; | ||
437 | } | ||
438 | mutex_lock(&uwb_rc->ies_mutex); | 290 | mutex_lock(&uwb_rc->ies_mutex); |
439 | ies_size = le16_to_cpu(uwb_rc->ies->wIELength); | 291 | |
440 | total_size = sizeof(*uwb_rc->ies) + ies_size; | 292 | ptr = (void *)ies; |
441 | if (total_size + size > uwb_rc->ies_capacity) { | 293 | for (;;) { |
442 | d_printf(4, dev, "Reallocating IE cache from %p capacity %zu " | 294 | ie = uwb_ie_next(&ptr, &size); |
443 | "to capacity %zu\n", uwb_rc->ies, uwb_rc->ies_capacity, | 295 | if (!ie) |
444 | total_size + size); | 296 | break; |
445 | new_ies = kzalloc(total_size + size, GFP_KERNEL); | 297 | |
446 | if (new_ies == NULL) { | 298 | result = uwb_rc_ie_add_one(uwb_rc, ie); |
447 | dev_err(dev, "No memory for adding new IE\n"); | 299 | if (result < 0) |
448 | result = -ENOMEM; | 300 | break; |
449 | goto error_alloc; | ||
450 | } | ||
451 | memcpy(new_ies, uwb_rc->ies, total_size); | ||
452 | uwb_rc->ies_capacity = total_size + size; | ||
453 | kfree(uwb_rc->ies); | ||
454 | uwb_rc->ies = new_ies; | ||
455 | d_printf(4, dev, "New IE cache at %p capacity %zu\n", | ||
456 | uwb_rc->ies, uwb_rc->ies_capacity); | ||
457 | } | 301 | } |
458 | memcpy((void *)uwb_rc->ies + total_size, ies, size); | 302 | if (result >= 0) { |
459 | uwb_rc->ies->wIELength = cpu_to_le16(ies_size + size); | 303 | if (size == 0) { |
460 | if (uwb_rc->beaconing != -1) { | 304 | if (uwb_rc->beaconing != -1) |
461 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); | 305 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); |
462 | if (result < 0) { | ||
463 | dev_err(dev, "Cannot set new IE on device: %d\n", | ||
464 | result); | ||
465 | uwb_rc->ies->wIELength = cpu_to_le16(ies_size); | ||
466 | } else | 306 | } else |
467 | result = 0; | 307 | result = -EINVAL; |
468 | } | 308 | } |
469 | d_printf(4, dev, "IEs now occupy %hu bytes of %zu capacity at %p\n", | 309 | |
470 | le16_to_cpu(uwb_rc->ies->wIELength), uwb_rc->ies_capacity, | ||
471 | uwb_rc->ies); | ||
472 | error_alloc: | ||
473 | mutex_unlock(&uwb_rc->ies_mutex); | 310 | mutex_unlock(&uwb_rc->ies_mutex); |
311 | |||
474 | return result; | 312 | return result; |
475 | } | 313 | } |
476 | EXPORT_SYMBOL_GPL(uwb_rc_ie_add); | 314 | EXPORT_SYMBOL_GPL(uwb_rc_ie_add); |
@@ -489,53 +327,52 @@ EXPORT_SYMBOL_GPL(uwb_rc_ie_add); | |||
489 | * beacon. We don't reallocate, we just mark the size smaller. | 327 | * beacon. We don't reallocate, we just mark the size smaller. |
490 | */ | 328 | */ |
491 | static | 329 | static |
492 | int uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) | 330 | void uwb_rc_ie_cache_rm(struct uwb_rc *uwb_rc, enum uwb_ie to_remove) |
493 | { | 331 | { |
494 | struct uwb_ie_hdr *ie_hdr; | 332 | struct uwb_ie_hdr *ie; |
495 | size_t new_len = le16_to_cpu(uwb_rc->ies->wIELength); | 333 | size_t len = le16_to_cpu(uwb_rc->ies->wIELength); |
496 | void *itr = uwb_rc->ies->IEData; | 334 | void *ptr; |
497 | void *top = itr + new_len; | 335 | size_t size; |
498 | 336 | ||
499 | while (itr < top) { | 337 | ptr = uwb_rc->ies->IEData; |
500 | ie_hdr = itr; | 338 | size = len; |
501 | if (ie_hdr->element_id != to_remove) { | 339 | for (;;) { |
502 | itr += sizeof(*ie_hdr) + ie_hdr->length; | 340 | ie = uwb_ie_next(&ptr, &size); |
503 | } else { | 341 | if (!ie) |
504 | int ie_length; | 342 | break; |
505 | ie_length = sizeof(*ie_hdr) + ie_hdr->length; | 343 | if (ie->element_id == to_remove) { |
506 | if (top - itr != ie_length) | 344 | len -= sizeof(struct uwb_ie_hdr) + ie->length; |
507 | memmove(itr, itr + ie_length, top - itr + ie_length); | 345 | memmove(ie, ptr, size); |
508 | top -= ie_length; | 346 | ptr = ie; |
509 | new_len -= ie_length; | ||
510 | } | 347 | } |
511 | } | 348 | } |
512 | uwb_rc->ies->wIELength = cpu_to_le16(new_len); | 349 | uwb_rc->ies->wIELength = cpu_to_le16(len); |
513 | return 0; | ||
514 | } | 350 | } |
515 | 351 | ||
516 | 352 | ||
517 | /** | 353 | /** |
518 | * Remove an IE currently being transmitted by device | 354 | * uwb_rc_ie_rm - remove an IE from the radio controller's beacon |
355 | * @uwb_rc: the radio controller. | ||
356 | * @element_id: the element ID of the IE to remove. | ||
519 | * | 357 | * |
520 | * @element_id: id of IE to be removed from device's beacon | 358 | * Only IEs previously added with uwb_rc_ie_add() may be removed. |
359 | * | ||
360 | * Returns 0 on success; or -ve the SET-IE command to the radio | ||
361 | * controller failed. | ||
521 | */ | 362 | */ |
522 | int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) | 363 | int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id) |
523 | { | 364 | { |
524 | struct device *dev = &uwb_rc->uwb_dev.dev; | 365 | int result = 0; |
525 | int result; | ||
526 | 366 | ||
527 | if (uwb_rc->ies == NULL) | ||
528 | return -ESHUTDOWN; | ||
529 | mutex_lock(&uwb_rc->ies_mutex); | 367 | mutex_lock(&uwb_rc->ies_mutex); |
530 | result = uwb_rc_ie_cache_rm(uwb_rc, element_id); | 368 | |
531 | if (result < 0) | 369 | uwb_rc_ie_cache_rm(uwb_rc, element_id); |
532 | dev_err(dev, "Cannot remove IE from cache.\n"); | 370 | |
533 | if (uwb_rc->beaconing != -1) { | 371 | if (uwb_rc->beaconing != -1) |
534 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); | 372 | result = uwb_rc_set_ie(uwb_rc, uwb_rc->ies); |
535 | if (result < 0) | 373 | |
536 | dev_err(dev, "Cannot set new IE on device.\n"); | ||
537 | } | ||
538 | mutex_unlock(&uwb_rc->ies_mutex); | 374 | mutex_unlock(&uwb_rc->ies_mutex); |
375 | |||
539 | return result; | 376 | return result; |
540 | } | 377 | } |
541 | EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); | 378 | EXPORT_SYMBOL_GPL(uwb_rc_ie_rm); |
diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c index 15f856c9689a..e9fe1bb7eb23 100644 --- a/drivers/uwb/lc-dev.c +++ b/drivers/uwb/lc-dev.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * | 22 | * |
23 | * FIXME: docs | 23 | * FIXME: docs |
24 | */ | 24 | */ |
25 | |||
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/device.h> | 26 | #include <linux/device.h> |
28 | #include <linux/err.h> | 27 | #include <linux/err.h> |
@@ -30,10 +29,6 @@ | |||
30 | #include <linux/random.h> | 29 | #include <linux/random.h> |
31 | #include "uwb-internal.h" | 30 | #include "uwb-internal.h" |
32 | 31 | ||
33 | #define D_LOCAL 1 | ||
34 | #include <linux/uwb/debug.h> | ||
35 | |||
36 | |||
37 | /* We initialize addresses to 0xff (invalid, as it is bcast) */ | 32 | /* We initialize addresses to 0xff (invalid, as it is bcast) */ |
38 | static inline void uwb_dev_addr_init(struct uwb_dev_addr *addr) | 33 | static inline void uwb_dev_addr_init(struct uwb_dev_addr *addr) |
39 | { | 34 | { |
@@ -104,12 +99,9 @@ static void uwb_dev_sys_release(struct device *dev) | |||
104 | { | 99 | { |
105 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); | 100 | struct uwb_dev *uwb_dev = to_uwb_dev(dev); |
106 | 101 | ||
107 | d_fnstart(4, NULL, "(dev %p uwb_dev %p)\n", dev, uwb_dev); | ||
108 | uwb_bce_put(uwb_dev->bce); | 102 | uwb_bce_put(uwb_dev->bce); |
109 | d_printf(0, &uwb_dev->dev, "uwb_dev %p freed\n", uwb_dev); | ||
110 | memset(uwb_dev, 0x69, sizeof(*uwb_dev)); | 103 | memset(uwb_dev, 0x69, sizeof(*uwb_dev)); |
111 | kfree(uwb_dev); | 104 | kfree(uwb_dev); |
112 | d_fnend(4, NULL, "(dev %p uwb_dev %p) = void\n", dev, uwb_dev); | ||
113 | } | 105 | } |
114 | 106 | ||
115 | /* | 107 | /* |
@@ -275,12 +267,8 @@ static struct attribute_group *groups[] = { | |||
275 | */ | 267 | */ |
276 | static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) | 268 | static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) |
277 | { | 269 | { |
278 | int result; | ||
279 | struct device *dev; | 270 | struct device *dev; |
280 | 271 | ||
281 | d_fnstart(4, NULL, "(uwb_dev %p parent_dev %p)\n", uwb_dev, parent_dev); | ||
282 | BUG_ON(parent_dev == NULL); | ||
283 | |||
284 | dev = &uwb_dev->dev; | 272 | dev = &uwb_dev->dev; |
285 | /* Device sysfs files are only useful for neighbor devices not | 273 | /* Device sysfs files are only useful for neighbor devices not |
286 | local radio controllers. */ | 274 | local radio controllers. */ |
@@ -289,18 +277,14 @@ static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev) | |||
289 | dev->parent = parent_dev; | 277 | dev->parent = parent_dev; |
290 | dev_set_drvdata(dev, uwb_dev); | 278 | dev_set_drvdata(dev, uwb_dev); |
291 | 279 | ||
292 | result = device_add(dev); | 280 | return device_add(dev); |
293 | d_fnend(4, NULL, "(uwb_dev %p parent_dev %p) = %d\n", uwb_dev, parent_dev, result); | ||
294 | return result; | ||
295 | } | 281 | } |
296 | 282 | ||
297 | 283 | ||
298 | static void __uwb_dev_sys_rm(struct uwb_dev *uwb_dev) | 284 | static void __uwb_dev_sys_rm(struct uwb_dev *uwb_dev) |
299 | { | 285 | { |
300 | d_fnstart(4, NULL, "(uwb_dev %p)\n", uwb_dev); | ||
301 | dev_set_drvdata(&uwb_dev->dev, NULL); | 286 | dev_set_drvdata(&uwb_dev->dev, NULL); |
302 | device_del(&uwb_dev->dev); | 287 | device_del(&uwb_dev->dev); |
303 | d_fnend(4, NULL, "(uwb_dev %p) = void\n", uwb_dev); | ||
304 | } | 288 | } |
305 | 289 | ||
306 | 290 | ||
@@ -384,7 +368,6 @@ int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) | |||
384 | struct device *dev = &uwb_dev->dev; | 368 | struct device *dev = &uwb_dev->dev; |
385 | char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; | 369 | char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE]; |
386 | 370 | ||
387 | d_fnstart(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p)\n", dev, uwb_dev, rc); | ||
388 | uwb_mac_addr_print(macbuf, sizeof(macbuf), &uwb_dev->mac_addr); | 371 | uwb_mac_addr_print(macbuf, sizeof(macbuf), &uwb_dev->mac_addr); |
389 | uwb_dev_addr_print(devbuf, sizeof(devbuf), &uwb_dev->dev_addr); | 372 | uwb_dev_addr_print(devbuf, sizeof(devbuf), &uwb_dev->dev_addr); |
390 | dev_info(dev, "uwb device (mac %s dev %s) disconnected from %s %s\n", | 373 | dev_info(dev, "uwb device (mac %s dev %s) disconnected from %s %s\n", |
@@ -392,8 +375,10 @@ int __uwb_dev_offair(struct uwb_dev *uwb_dev, struct uwb_rc *rc) | |||
392 | rc ? rc->uwb_dev.dev.parent->bus->name : "n/a", | 375 | rc ? rc->uwb_dev.dev.parent->bus->name : "n/a", |
393 | rc ? dev_name(rc->uwb_dev.dev.parent) : ""); | 376 | rc ? dev_name(rc->uwb_dev.dev.parent) : ""); |
394 | uwb_dev_rm(uwb_dev); | 377 | uwb_dev_rm(uwb_dev); |
378 | list_del(&uwb_dev->bce->node); | ||
379 | uwb_bce_put(uwb_dev->bce); | ||
395 | uwb_dev_put(uwb_dev); /* for the creation in _onair() */ | 380 | uwb_dev_put(uwb_dev); /* for the creation in _onair() */ |
396 | d_fnend(3, NULL, "(dev %p [uwb_dev %p], uwb_rc %p) = 0\n", dev, uwb_dev, rc); | 381 | |
397 | return 0; | 382 | return 0; |
398 | } | 383 | } |
399 | 384 | ||
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c index ee5772f00d42..9cf21e6bb624 100644 --- a/drivers/uwb/lc-rc.c +++ b/drivers/uwb/lc-rc.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <linux/etherdevice.h> | 36 | #include <linux/etherdevice.h> |
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | 38 | ||
39 | #define D_LOCAL 1 | ||
40 | #include <linux/uwb/debug.h> | ||
41 | #include "uwb-internal.h" | 39 | #include "uwb-internal.h" |
42 | 40 | ||
43 | static int uwb_rc_index_match(struct device *dev, void *data) | 41 | static int uwb_rc_index_match(struct device *dev, void *data) |
@@ -81,9 +79,7 @@ static void uwb_rc_sys_release(struct device *dev) | |||
81 | struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); | 79 | struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev); |
82 | struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); | 80 | struct uwb_rc *rc = container_of(uwb_dev, struct uwb_rc, uwb_dev); |
83 | 81 | ||
84 | uwb_rc_neh_destroy(rc); | ||
85 | uwb_rc_ie_release(rc); | 82 | uwb_rc_ie_release(rc); |
86 | d_printf(1, dev, "freed uwb_rc %p\n", rc); | ||
87 | kfree(rc); | 83 | kfree(rc); |
88 | } | 84 | } |
89 | 85 | ||
@@ -100,6 +96,8 @@ void uwb_rc_init(struct uwb_rc *rc) | |||
100 | rc->scan_type = UWB_SCAN_DISABLED; | 96 | rc->scan_type = UWB_SCAN_DISABLED; |
101 | INIT_LIST_HEAD(&rc->notifs_chain.list); | 97 | INIT_LIST_HEAD(&rc->notifs_chain.list); |
102 | mutex_init(&rc->notifs_chain.mutex); | 98 | mutex_init(&rc->notifs_chain.mutex); |
99 | INIT_LIST_HEAD(&rc->uwb_beca.list); | ||
100 | mutex_init(&rc->uwb_beca.mutex); | ||
103 | uwb_drp_avail_init(rc); | 101 | uwb_drp_avail_init(rc); |
104 | uwb_rc_ie_init(rc); | 102 | uwb_rc_ie_init(rc); |
105 | uwb_rsv_init(rc); | 103 | uwb_rsv_init(rc); |
@@ -191,9 +189,9 @@ static int uwb_rc_setup(struct uwb_rc *rc) | |||
191 | int result; | 189 | int result; |
192 | struct device *dev = &rc->uwb_dev.dev; | 190 | struct device *dev = &rc->uwb_dev.dev; |
193 | 191 | ||
194 | result = uwb_rc_reset(rc); | 192 | result = uwb_radio_setup(rc); |
195 | if (result < 0) { | 193 | if (result < 0) { |
196 | dev_err(dev, "cannot reset UWB radio: %d\n", result); | 194 | dev_err(dev, "cannot setup UWB radio: %d\n", result); |
197 | goto error; | 195 | goto error; |
198 | } | 196 | } |
199 | result = uwb_rc_mac_addr_setup(rc); | 197 | result = uwb_rc_mac_addr_setup(rc); |
@@ -250,6 +248,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) | |||
250 | 248 | ||
251 | rc->priv = priv; | 249 | rc->priv = priv; |
252 | 250 | ||
251 | init_waitqueue_head(&rc->uwbd.wq); | ||
252 | INIT_LIST_HEAD(&rc->uwbd.event_list); | ||
253 | spin_lock_init(&rc->uwbd.event_list_lock); | ||
254 | |||
255 | uwbd_start(rc); | ||
256 | |||
253 | result = rc->start(rc); | 257 | result = rc->start(rc); |
254 | if (result < 0) | 258 | if (result < 0) |
255 | goto error_rc_start; | 259 | goto error_rc_start; |
@@ -284,7 +288,7 @@ error_sys_add: | |||
284 | error_dev_add: | 288 | error_dev_add: |
285 | error_rc_setup: | 289 | error_rc_setup: |
286 | rc->stop(rc); | 290 | rc->stop(rc); |
287 | uwbd_flush(rc); | 291 | uwbd_stop(rc); |
288 | error_rc_start: | 292 | error_rc_start: |
289 | return result; | 293 | return result; |
290 | } | 294 | } |
@@ -306,25 +310,24 @@ void uwb_rc_rm(struct uwb_rc *rc) | |||
306 | rc->ready = 0; | 310 | rc->ready = 0; |
307 | 311 | ||
308 | uwb_dbg_del_rc(rc); | 312 | uwb_dbg_del_rc(rc); |
309 | uwb_rsv_cleanup(rc); | 313 | uwb_rsv_remove_all(rc); |
310 | uwb_rc_ie_rm(rc, UWB_IDENTIFICATION_IE); | 314 | uwb_radio_shutdown(rc); |
311 | if (rc->beaconing >= 0) | ||
312 | uwb_rc_beacon(rc, -1, 0); | ||
313 | if (rc->scan_type != UWB_SCAN_DISABLED) | ||
314 | uwb_rc_scan(rc, rc->scanning, UWB_SCAN_DISABLED, 0); | ||
315 | uwb_rc_reset(rc); | ||
316 | 315 | ||
317 | rc->stop(rc); | 316 | rc->stop(rc); |
318 | uwbd_flush(rc); | 317 | |
318 | uwbd_stop(rc); | ||
319 | uwb_rc_neh_destroy(rc); | ||
319 | 320 | ||
320 | uwb_dev_lock(&rc->uwb_dev); | 321 | uwb_dev_lock(&rc->uwb_dev); |
321 | rc->priv = NULL; | 322 | rc->priv = NULL; |
322 | rc->cmd = NULL; | 323 | rc->cmd = NULL; |
323 | uwb_dev_unlock(&rc->uwb_dev); | 324 | uwb_dev_unlock(&rc->uwb_dev); |
324 | mutex_lock(&uwb_beca.mutex); | 325 | mutex_lock(&rc->uwb_beca.mutex); |
325 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); | 326 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); |
326 | __uwb_rc_sys_rm(rc); | 327 | __uwb_rc_sys_rm(rc); |
327 | mutex_unlock(&uwb_beca.mutex); | 328 | mutex_unlock(&rc->uwb_beca.mutex); |
329 | uwb_rsv_cleanup(rc); | ||
330 | uwb_beca_release(rc); | ||
328 | uwb_dev_rm(&rc->uwb_dev); | 331 | uwb_dev_rm(&rc->uwb_dev); |
329 | } | 332 | } |
330 | EXPORT_SYMBOL_GPL(uwb_rc_rm); | 333 | EXPORT_SYMBOL_GPL(uwb_rc_rm); |
@@ -468,28 +471,3 @@ void uwb_rc_put(struct uwb_rc *rc) | |||
468 | __uwb_rc_put(rc); | 471 | __uwb_rc_put(rc); |
469 | } | 472 | } |
470 | EXPORT_SYMBOL_GPL(uwb_rc_put); | 473 | EXPORT_SYMBOL_GPL(uwb_rc_put); |
471 | |||
472 | /* | ||
473 | * | ||
474 | * | ||
475 | */ | ||
476 | ssize_t uwb_rc_print_IEs(struct uwb_rc *uwb_rc, char *buf, size_t size) | ||
477 | { | ||
478 | ssize_t result; | ||
479 | struct uwb_rc_evt_get_ie *ie_info; | ||
480 | struct uwb_buf_ctx ctx; | ||
481 | |||
482 | result = uwb_rc_get_ie(uwb_rc, &ie_info); | ||
483 | if (result < 0) | ||
484 | goto error_get_ie; | ||
485 | ctx.buf = buf; | ||
486 | ctx.size = size; | ||
487 | ctx.bytes = 0; | ||
488 | uwb_ie_for_each(&uwb_rc->uwb_dev, uwb_ie_dump_hex, &ctx, | ||
489 | ie_info->IEData, result - sizeof(*ie_info)); | ||
490 | result = ctx.bytes; | ||
491 | kfree(ie_info); | ||
492 | error_get_ie: | ||
493 | return result; | ||
494 | } | ||
495 | |||
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c index 9b4eb64327ac..0af8916d9bef 100644 --- a/drivers/uwb/neh.c +++ b/drivers/uwb/neh.c | |||
@@ -86,8 +86,6 @@ | |||
86 | #include <linux/err.h> | 86 | #include <linux/err.h> |
87 | 87 | ||
88 | #include "uwb-internal.h" | 88 | #include "uwb-internal.h" |
89 | #define D_LOCAL 0 | ||
90 | #include <linux/uwb/debug.h> | ||
91 | 89 | ||
92 | /* | 90 | /* |
93 | * UWB Radio Controller Notification/Event Handle | 91 | * UWB Radio Controller Notification/Event Handle |
@@ -254,7 +252,6 @@ error_kzalloc: | |||
254 | 252 | ||
255 | static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) | 253 | static void __uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) |
256 | { | 254 | { |
257 | del_timer(&neh->timer); | ||
258 | __uwb_rc_ctx_put(rc, neh); | 255 | __uwb_rc_ctx_put(rc, neh); |
259 | list_del(&neh->list_node); | 256 | list_del(&neh->list_node); |
260 | } | 257 | } |
@@ -275,6 +272,7 @@ void uwb_rc_neh_rm(struct uwb_rc *rc, struct uwb_rc_neh *neh) | |||
275 | __uwb_rc_neh_rm(rc, neh); | 272 | __uwb_rc_neh_rm(rc, neh); |
276 | spin_unlock_irqrestore(&rc->neh_lock, flags); | 273 | spin_unlock_irqrestore(&rc->neh_lock, flags); |
277 | 274 | ||
275 | del_timer_sync(&neh->timer); | ||
278 | uwb_rc_neh_put(neh); | 276 | uwb_rc_neh_put(neh); |
279 | } | 277 | } |
280 | 278 | ||
@@ -349,7 +347,7 @@ struct uwb_rc_neh *uwb_rc_neh_lookup(struct uwb_rc *rc, | |||
349 | } | 347 | } |
350 | 348 | ||
351 | 349 | ||
352 | /** | 350 | /* |
353 | * Process notifications coming from the radio control interface | 351 | * Process notifications coming from the radio control interface |
354 | * | 352 | * |
355 | * @rc: UWB Radio Control Interface descriptor | 353 | * @rc: UWB Radio Control Interface descriptor |
@@ -401,23 +399,6 @@ void uwb_rc_notif(struct uwb_rc *rc, struct uwb_rceb *rceb, ssize_t size) | |||
401 | uwb_evt->notif.size = size; | 399 | uwb_evt->notif.size = size; |
402 | uwb_evt->notif.rceb = rceb; | 400 | uwb_evt->notif.rceb = rceb; |
403 | 401 | ||
404 | switch (le16_to_cpu(rceb->wEvent)) { | ||
405 | /* Trap some vendor specific events | ||
406 | * | ||
407 | * FIXME: move this to handling in ptc-est, where we | ||
408 | * register a NULL event handler for these two guys | ||
409 | * using the Intel IDs. | ||
410 | */ | ||
411 | case 0x0103: | ||
412 | dev_info(dev, "FIXME: DEVICE ADD\n"); | ||
413 | return; | ||
414 | case 0x0104: | ||
415 | dev_info(dev, "FIXME: DEVICE RM\n"); | ||
416 | return; | ||
417 | default: | ||
418 | break; | ||
419 | } | ||
420 | |||
421 | uwbd_event_queue(uwb_evt); | 402 | uwbd_event_queue(uwb_evt); |
422 | } | 403 | } |
423 | 404 | ||
@@ -438,9 +419,10 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size | |||
438 | rceb->bEventContext, size); | 419 | rceb->bEventContext, size); |
439 | } else { | 420 | } else { |
440 | neh = uwb_rc_neh_lookup(rc, rceb); | 421 | neh = uwb_rc_neh_lookup(rc, rceb); |
441 | if (neh) | 422 | if (neh) { |
423 | del_timer_sync(&neh->timer); | ||
442 | uwb_rc_neh_cb(neh, rceb, size); | 424 | uwb_rc_neh_cb(neh, rceb, size); |
443 | else | 425 | } else |
444 | dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", | 426 | dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n", |
445 | rceb->bEventType, le16_to_cpu(rceb->wEvent), | 427 | rceb->bEventType, le16_to_cpu(rceb->wEvent), |
446 | rceb->bEventContext, size); | 428 | rceb->bEventContext, size); |
@@ -495,8 +477,6 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) | |||
495 | size_t size, real_size, event_size; | 477 | size_t size, real_size, event_size; |
496 | int needtofree; | 478 | int needtofree; |
497 | 479 | ||
498 | d_fnstart(3, dev, "(rc %p buf %p %zu buf_size)\n", rc, buf, buf_size); | ||
499 | d_printf(2, dev, "groking event block: %zu bytes\n", buf_size); | ||
500 | itr = buf; | 480 | itr = buf; |
501 | size = buf_size; | 481 | size = buf_size; |
502 | while (size > 0) { | 482 | while (size > 0) { |
@@ -544,10 +524,7 @@ void uwb_rc_neh_grok(struct uwb_rc *rc, void *buf, size_t buf_size) | |||
544 | 524 | ||
545 | itr += real_size; | 525 | itr += real_size; |
546 | size -= real_size; | 526 | size -= real_size; |
547 | d_printf(2, dev, "consumed %zd bytes, %zu left\n", | ||
548 | event_size, size); | ||
549 | } | 527 | } |
550 | d_fnend(3, dev, "(rc %p buf %p %zu buf_size) = void\n", rc, buf, buf_size); | ||
551 | } | 528 | } |
552 | EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); | 529 | EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); |
553 | 530 | ||
@@ -562,16 +539,22 @@ EXPORT_SYMBOL_GPL(uwb_rc_neh_grok); | |||
562 | */ | 539 | */ |
563 | void uwb_rc_neh_error(struct uwb_rc *rc, int error) | 540 | void uwb_rc_neh_error(struct uwb_rc *rc, int error) |
564 | { | 541 | { |
565 | struct uwb_rc_neh *neh, *next; | 542 | struct uwb_rc_neh *neh; |
566 | unsigned long flags; | 543 | unsigned long flags; |
567 | 544 | ||
568 | BUG_ON(error >= 0); | 545 | for (;;) { |
569 | spin_lock_irqsave(&rc->neh_lock, flags); | 546 | spin_lock_irqsave(&rc->neh_lock, flags); |
570 | list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { | 547 | if (list_empty(&rc->neh_list)) { |
548 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
549 | break; | ||
550 | } | ||
551 | neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); | ||
571 | __uwb_rc_neh_rm(rc, neh); | 552 | __uwb_rc_neh_rm(rc, neh); |
553 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
554 | |||
555 | del_timer_sync(&neh->timer); | ||
572 | uwb_rc_neh_cb(neh, NULL, error); | 556 | uwb_rc_neh_cb(neh, NULL, error); |
573 | } | 557 | } |
574 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
575 | } | 558 | } |
576 | EXPORT_SYMBOL_GPL(uwb_rc_neh_error); | 559 | EXPORT_SYMBOL_GPL(uwb_rc_neh_error); |
577 | 560 | ||
@@ -583,10 +566,14 @@ static void uwb_rc_neh_timer(unsigned long arg) | |||
583 | unsigned long flags; | 566 | unsigned long flags; |
584 | 567 | ||
585 | spin_lock_irqsave(&rc->neh_lock, flags); | 568 | spin_lock_irqsave(&rc->neh_lock, flags); |
586 | __uwb_rc_neh_rm(rc, neh); | 569 | if (neh->context) |
570 | __uwb_rc_neh_rm(rc, neh); | ||
571 | else | ||
572 | neh = NULL; | ||
587 | spin_unlock_irqrestore(&rc->neh_lock, flags); | 573 | spin_unlock_irqrestore(&rc->neh_lock, flags); |
588 | 574 | ||
589 | uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); | 575 | if (neh) |
576 | uwb_rc_neh_cb(neh, NULL, -ETIMEDOUT); | ||
590 | } | 577 | } |
591 | 578 | ||
592 | /** Initializes the @rc's neh subsystem | 579 | /** Initializes the @rc's neh subsystem |
@@ -605,12 +592,19 @@ void uwb_rc_neh_create(struct uwb_rc *rc) | |||
605 | void uwb_rc_neh_destroy(struct uwb_rc *rc) | 592 | void uwb_rc_neh_destroy(struct uwb_rc *rc) |
606 | { | 593 | { |
607 | unsigned long flags; | 594 | unsigned long flags; |
608 | struct uwb_rc_neh *neh, *next; | 595 | struct uwb_rc_neh *neh; |
609 | 596 | ||
610 | spin_lock_irqsave(&rc->neh_lock, flags); | 597 | for (;;) { |
611 | list_for_each_entry_safe(neh, next, &rc->neh_list, list_node) { | 598 | spin_lock_irqsave(&rc->neh_lock, flags); |
599 | if (list_empty(&rc->neh_list)) { | ||
600 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
601 | break; | ||
602 | } | ||
603 | neh = list_first_entry(&rc->neh_list, struct uwb_rc_neh, list_node); | ||
612 | __uwb_rc_neh_rm(rc, neh); | 604 | __uwb_rc_neh_rm(rc, neh); |
605 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
606 | |||
607 | del_timer_sync(&neh->timer); | ||
613 | uwb_rc_neh_put(neh); | 608 | uwb_rc_neh_put(neh); |
614 | } | 609 | } |
615 | spin_unlock_irqrestore(&rc->neh_lock, flags); | ||
616 | } | 610 | } |
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c index 1afb38eacb9a..99a19c199095 100644 --- a/drivers/uwb/pal.c +++ b/drivers/uwb/pal.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/debugfs.h> | ||
19 | #include <linux/uwb.h> | 20 | #include <linux/uwb.h> |
20 | 21 | ||
21 | #include "uwb-internal.h" | 22 | #include "uwb-internal.h" |
@@ -32,13 +33,13 @@ EXPORT_SYMBOL_GPL(uwb_pal_init); | |||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * uwb_pal_register - register a UWB PAL | 35 | * uwb_pal_register - register a UWB PAL |
35 | * @rc: the radio controller the PAL will be using | ||
36 | * @pal: the PAL | 36 | * @pal: the PAL |
37 | * | 37 | * |
38 | * The PAL must be initialized with uwb_pal_init(). | 38 | * The PAL must be initialized with uwb_pal_init(). |
39 | */ | 39 | */ |
40 | int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) | 40 | int uwb_pal_register(struct uwb_pal *pal) |
41 | { | 41 | { |
42 | struct uwb_rc *rc = pal->rc; | ||
42 | int ret; | 43 | int ret; |
43 | 44 | ||
44 | if (pal->device) { | 45 | if (pal->device) { |
@@ -54,9 +55,11 @@ int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal) | |||
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | spin_lock(&rc->pal_lock); | 58 | pal->debugfs_dir = uwb_dbg_create_pal_dir(pal); |
59 | |||
60 | mutex_lock(&rc->uwb_dev.mutex); | ||
58 | list_add(&pal->node, &rc->pals); | 61 | list_add(&pal->node, &rc->pals); |
59 | spin_unlock(&rc->pal_lock); | 62 | mutex_unlock(&rc->uwb_dev.mutex); |
60 | 63 | ||
61 | return 0; | 64 | return 0; |
62 | } | 65 | } |
@@ -64,14 +67,19 @@ EXPORT_SYMBOL_GPL(uwb_pal_register); | |||
64 | 67 | ||
65 | /** | 68 | /** |
66 | * uwb_pal_register - unregister a UWB PAL | 69 | * uwb_pal_register - unregister a UWB PAL |
67 | * @rc: the radio controller the PAL was using | ||
68 | * @pal: the PAL | 70 | * @pal: the PAL |
69 | */ | 71 | */ |
70 | void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal) | 72 | void uwb_pal_unregister(struct uwb_pal *pal) |
71 | { | 73 | { |
72 | spin_lock(&rc->pal_lock); | 74 | struct uwb_rc *rc = pal->rc; |
75 | |||
76 | uwb_radio_stop(pal); | ||
77 | |||
78 | mutex_lock(&rc->uwb_dev.mutex); | ||
73 | list_del(&pal->node); | 79 | list_del(&pal->node); |
74 | spin_unlock(&rc->pal_lock); | 80 | mutex_unlock(&rc->uwb_dev.mutex); |
81 | |||
82 | debugfs_remove(pal->debugfs_dir); | ||
75 | 83 | ||
76 | if (pal->device) { | 84 | if (pal->device) { |
77 | sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); | 85 | sysfs_remove_link(&rc->uwb_dev.dev.kobj, pal->name); |
@@ -86,6 +94,5 @@ EXPORT_SYMBOL_GPL(uwb_pal_unregister); | |||
86 | */ | 94 | */ |
87 | void uwb_rc_pal_init(struct uwb_rc *rc) | 95 | void uwb_rc_pal_init(struct uwb_rc *rc) |
88 | { | 96 | { |
89 | spin_lock_init(&rc->pal_lock); | ||
90 | INIT_LIST_HEAD(&rc->pals); | 97 | INIT_LIST_HEAD(&rc->pals); |
91 | } | 98 | } |
diff --git a/drivers/uwb/radio.c b/drivers/uwb/radio.c new file mode 100644 index 000000000000..f0d55495f5e9 --- /dev/null +++ b/drivers/uwb/radio.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * UWB radio (channel) management. | ||
3 | * | ||
4 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/uwb.h> | ||
20 | |||
21 | #include "uwb-internal.h" | ||
22 | |||
23 | |||
24 | static int uwb_radio_select_channel(struct uwb_rc *rc) | ||
25 | { | ||
26 | /* | ||
27 | * Default to channel 9 (BG1, TFC1) unless the user has | ||
28 | * selected a specific channel or there are no active PALs. | ||
29 | */ | ||
30 | if (rc->active_pals == 0) | ||
31 | return -1; | ||
32 | if (rc->beaconing_forced) | ||
33 | return rc->beaconing_forced; | ||
34 | return 9; | ||
35 | } | ||
36 | |||
37 | |||
38 | /* | ||
39 | * Notify all active PALs that the channel has changed. | ||
40 | */ | ||
41 | static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel) | ||
42 | { | ||
43 | struct uwb_pal *pal; | ||
44 | |||
45 | list_for_each_entry(pal, &rc->pals, node) { | ||
46 | if (pal->channel && channel != pal->channel) { | ||
47 | pal->channel = channel; | ||
48 | if (pal->channel_changed) | ||
49 | pal->channel_changed(pal, pal->channel); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Change to a new channel and notify any active PALs of the new | ||
56 | * channel. | ||
57 | * | ||
58 | * When stopping the radio, PALs need to be notified first so they can | ||
59 | * terminate any active reservations. | ||
60 | */ | ||
61 | static int uwb_radio_change_channel(struct uwb_rc *rc, int channel) | ||
62 | { | ||
63 | int ret = 0; | ||
64 | |||
65 | if (channel == -1) | ||
66 | uwb_radio_channel_changed(rc, channel); | ||
67 | |||
68 | if (channel != rc->beaconing) { | ||
69 | if (rc->beaconing != -1 && channel != -1) { | ||
70 | /* | ||
71 | * FIXME: should signal the channel change | ||
72 | * with a Channel Change IE. | ||
73 | */ | ||
74 | ret = uwb_radio_change_channel(rc, -1); | ||
75 | if (ret < 0) | ||
76 | return ret; | ||
77 | } | ||
78 | ret = uwb_rc_beacon(rc, channel, 0); | ||
79 | } | ||
80 | |||
81 | if (channel != -1) | ||
82 | uwb_radio_channel_changed(rc, rc->beaconing); | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * uwb_radio_start - request that the radio be started | ||
89 | * @pal: the PAL making the request. | ||
90 | * | ||
91 | * If the radio is not already active, aa suitable channel is selected | ||
92 | * and beacons are started. | ||
93 | */ | ||
94 | int uwb_radio_start(struct uwb_pal *pal) | ||
95 | { | ||
96 | struct uwb_rc *rc = pal->rc; | ||
97 | int ret = 0; | ||
98 | |||
99 | mutex_lock(&rc->uwb_dev.mutex); | ||
100 | |||
101 | if (!pal->channel) { | ||
102 | pal->channel = -1; | ||
103 | rc->active_pals++; | ||
104 | ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
105 | } | ||
106 | |||
107 | mutex_unlock(&rc->uwb_dev.mutex); | ||
108 | return ret; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(uwb_radio_start); | ||
111 | |||
112 | /** | ||
113 | * uwb_radio_stop - request tha the radio be stopped. | ||
114 | * @pal: the PAL making the request. | ||
115 | * | ||
116 | * Stops the radio if no other PAL is making use of it. | ||
117 | */ | ||
118 | void uwb_radio_stop(struct uwb_pal *pal) | ||
119 | { | ||
120 | struct uwb_rc *rc = pal->rc; | ||
121 | |||
122 | mutex_lock(&rc->uwb_dev.mutex); | ||
123 | |||
124 | if (pal->channel) { | ||
125 | rc->active_pals--; | ||
126 | uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
127 | pal->channel = 0; | ||
128 | } | ||
129 | |||
130 | mutex_unlock(&rc->uwb_dev.mutex); | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(uwb_radio_stop); | ||
133 | |||
134 | /* | ||
135 | * uwb_radio_force_channel - force a specific channel to be used | ||
136 | * @rc: the radio controller. | ||
137 | * @channel: the channel to use; -1 to force the radio to stop; 0 to | ||
138 | * use the default channel selection algorithm. | ||
139 | */ | ||
140 | int uwb_radio_force_channel(struct uwb_rc *rc, int channel) | ||
141 | { | ||
142 | int ret = 0; | ||
143 | |||
144 | mutex_lock(&rc->uwb_dev.mutex); | ||
145 | |||
146 | rc->beaconing_forced = channel; | ||
147 | ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc)); | ||
148 | |||
149 | mutex_unlock(&rc->uwb_dev.mutex); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * uwb_radio_setup - setup the radio manager | ||
155 | * @rc: the radio controller. | ||
156 | * | ||
157 | * The radio controller is reset to ensure it's in a known state | ||
158 | * before it's used. | ||
159 | */ | ||
160 | int uwb_radio_setup(struct uwb_rc *rc) | ||
161 | { | ||
162 | return uwb_rc_reset(rc); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * uwb_radio_reset_state - reset any radio manager state | ||
167 | * @rc: the radio controller. | ||
168 | * | ||
169 | * All internal radio manager state is reset to values corresponding | ||
170 | * to a reset radio controller. | ||
171 | */ | ||
172 | void uwb_radio_reset_state(struct uwb_rc *rc) | ||
173 | { | ||
174 | struct uwb_pal *pal; | ||
175 | |||
176 | mutex_lock(&rc->uwb_dev.mutex); | ||
177 | |||
178 | list_for_each_entry(pal, &rc->pals, node) { | ||
179 | if (pal->channel) { | ||
180 | pal->channel = -1; | ||
181 | if (pal->channel_changed) | ||
182 | pal->channel_changed(pal, -1); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | rc->beaconing = -1; | ||
187 | rc->scanning = -1; | ||
188 | |||
189 | mutex_unlock(&rc->uwb_dev.mutex); | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * uwb_radio_shutdown - shutdown the radio manager | ||
194 | * @rc: the radio controller. | ||
195 | * | ||
196 | * The radio controller is reset. | ||
197 | */ | ||
198 | void uwb_radio_shutdown(struct uwb_rc *rc) | ||
199 | { | ||
200 | uwb_radio_reset_state(rc); | ||
201 | uwb_rc_reset(rc); | ||
202 | } | ||
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 8de856fa7958..70f8050221ff 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | 33 | ||
34 | #include "uwb-internal.h" | 34 | #include "uwb-internal.h" |
35 | #define D_LOCAL 0 | ||
36 | #include <linux/uwb/debug.h> | ||
37 | 35 | ||
38 | /** | 36 | /** |
39 | * Command result codes (WUSB1.0[T8-69]) | 37 | * Command result codes (WUSB1.0[T8-69]) |
@@ -323,17 +321,16 @@ int uwbd_msg_handle_reset(struct uwb_event *evt) | |||
323 | struct uwb_rc *rc = evt->rc; | 321 | struct uwb_rc *rc = evt->rc; |
324 | int ret; | 322 | int ret; |
325 | 323 | ||
326 | /* Need to prevent the RC hardware module going away while in | ||
327 | the rc->reset() call. */ | ||
328 | if (!try_module_get(rc->owner)) | ||
329 | return 0; | ||
330 | |||
331 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); | 324 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); |
332 | ret = rc->reset(rc); | 325 | ret = rc->reset(rc); |
333 | if (ret) | 326 | if (ret) { |
334 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); | 327 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); |
335 | 328 | goto error; | |
336 | module_put(rc->owner); | 329 | } |
330 | return 0; | ||
331 | error: | ||
332 | /* Nothing can be done except try the reset again. */ | ||
333 | uwb_rc_reset_all(rc); | ||
337 | return ret; | 334 | return ret; |
338 | } | 335 | } |
339 | 336 | ||
@@ -360,3 +357,33 @@ void uwb_rc_reset_all(struct uwb_rc *rc) | |||
360 | uwbd_event_queue(evt); | 357 | uwbd_event_queue(evt); |
361 | } | 358 | } |
362 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); | 359 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); |
360 | |||
361 | void uwb_rc_pre_reset(struct uwb_rc *rc) | ||
362 | { | ||
363 | rc->stop(rc); | ||
364 | uwbd_flush(rc); | ||
365 | |||
366 | uwb_radio_reset_state(rc); | ||
367 | uwb_rsv_remove_all(rc); | ||
368 | } | ||
369 | EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); | ||
370 | |||
371 | void uwb_rc_post_reset(struct uwb_rc *rc) | ||
372 | { | ||
373 | int ret; | ||
374 | |||
375 | ret = rc->start(rc); | ||
376 | if (ret) | ||
377 | goto error; | ||
378 | ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); | ||
379 | if (ret) | ||
380 | goto error; | ||
381 | ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); | ||
382 | if (ret) | ||
383 | goto error; | ||
384 | return; | ||
385 | error: | ||
386 | /* Nothing can be done except try the reset again. */ | ||
387 | uwb_rc_reset_all(rc); | ||
388 | } | ||
389 | EXPORT_SYMBOL_GPL(uwb_rc_post_reset); | ||
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index bae16204576d..ec6eecb32f30 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c | |||
@@ -15,23 +15,33 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/uwb.h> | 19 | #include <linux/uwb.h> |
20 | #include <linux/random.h> | ||
21 | 21 | ||
22 | #include "uwb-internal.h" | 22 | #include "uwb-internal.h" |
23 | 23 | ||
24 | static void uwb_rsv_timer(unsigned long arg); | 24 | static void uwb_rsv_timer(unsigned long arg); |
25 | 25 | ||
26 | static const char *rsv_states[] = { | 26 | static const char *rsv_states[] = { |
27 | [UWB_RSV_STATE_NONE] = "none", | 27 | [UWB_RSV_STATE_NONE] = "none ", |
28 | [UWB_RSV_STATE_O_INITIATED] = "initiated", | 28 | [UWB_RSV_STATE_O_INITIATED] = "o initiated ", |
29 | [UWB_RSV_STATE_O_PENDING] = "pending", | 29 | [UWB_RSV_STATE_O_PENDING] = "o pending ", |
30 | [UWB_RSV_STATE_O_MODIFIED] = "modified", | 30 | [UWB_RSV_STATE_O_MODIFIED] = "o modified ", |
31 | [UWB_RSV_STATE_O_ESTABLISHED] = "established", | 31 | [UWB_RSV_STATE_O_ESTABLISHED] = "o established ", |
32 | [UWB_RSV_STATE_T_ACCEPTED] = "accepted", | 32 | [UWB_RSV_STATE_O_TO_BE_MOVED] = "o to be moved ", |
33 | [UWB_RSV_STATE_T_DENIED] = "denied", | 33 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = "o move expanding", |
34 | [UWB_RSV_STATE_T_PENDING] = "pending", | 34 | [UWB_RSV_STATE_O_MOVE_COMBINING] = "o move combining", |
35 | [UWB_RSV_STATE_O_MOVE_REDUCING] = "o move reducing ", | ||
36 | [UWB_RSV_STATE_T_ACCEPTED] = "t accepted ", | ||
37 | [UWB_RSV_STATE_T_CONFLICT] = "t conflict ", | ||
38 | [UWB_RSV_STATE_T_PENDING] = "t pending ", | ||
39 | [UWB_RSV_STATE_T_DENIED] = "t denied ", | ||
40 | [UWB_RSV_STATE_T_RESIZED] = "t resized ", | ||
41 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = "t expanding acc ", | ||
42 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = "t expanding conf", | ||
43 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = "t expanding pend", | ||
44 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = "t expanding den ", | ||
35 | }; | 45 | }; |
36 | 46 | ||
37 | static const char *rsv_types[] = { | 47 | static const char *rsv_types[] = { |
@@ -42,6 +52,31 @@ static const char *rsv_types[] = { | |||
42 | [UWB_DRP_TYPE_PCA] = "pca", | 52 | [UWB_DRP_TYPE_PCA] = "pca", |
43 | }; | 53 | }; |
44 | 54 | ||
55 | bool uwb_rsv_has_two_drp_ies(struct uwb_rsv *rsv) | ||
56 | { | ||
57 | static const bool has_two_drp_ies[] = { | ||
58 | [UWB_RSV_STATE_O_INITIATED] = false, | ||
59 | [UWB_RSV_STATE_O_PENDING] = false, | ||
60 | [UWB_RSV_STATE_O_MODIFIED] = false, | ||
61 | [UWB_RSV_STATE_O_ESTABLISHED] = false, | ||
62 | [UWB_RSV_STATE_O_TO_BE_MOVED] = false, | ||
63 | [UWB_RSV_STATE_O_MOVE_COMBINING] = false, | ||
64 | [UWB_RSV_STATE_O_MOVE_REDUCING] = false, | ||
65 | [UWB_RSV_STATE_O_MOVE_EXPANDING] = true, | ||
66 | [UWB_RSV_STATE_T_ACCEPTED] = false, | ||
67 | [UWB_RSV_STATE_T_CONFLICT] = false, | ||
68 | [UWB_RSV_STATE_T_PENDING] = false, | ||
69 | [UWB_RSV_STATE_T_DENIED] = false, | ||
70 | [UWB_RSV_STATE_T_RESIZED] = false, | ||
71 | [UWB_RSV_STATE_T_EXPANDING_ACCEPTED] = true, | ||
72 | [UWB_RSV_STATE_T_EXPANDING_CONFLICT] = true, | ||
73 | [UWB_RSV_STATE_T_EXPANDING_PENDING] = true, | ||
74 | [UWB_RSV_STATE_T_EXPANDING_DENIED] = true, | ||
75 | }; | ||
76 | |||
77 | return has_two_drp_ies[rsv->state]; | ||
78 | } | ||
79 | |||
45 | /** | 80 | /** |
46 | * uwb_rsv_state_str - return a string for a reservation state | 81 | * uwb_rsv_state_str - return a string for a reservation state |
47 | * @state: the reservation state. | 82 | * @state: the reservation state. |
@@ -66,7 +101,7 @@ const char *uwb_rsv_type_str(enum uwb_drp_type type) | |||
66 | } | 101 | } |
67 | EXPORT_SYMBOL_GPL(uwb_rsv_type_str); | 102 | EXPORT_SYMBOL_GPL(uwb_rsv_type_str); |
68 | 103 | ||
69 | static void uwb_rsv_dump(struct uwb_rsv *rsv) | 104 | void uwb_rsv_dump(char *text, struct uwb_rsv *rsv) |
70 | { | 105 | { |
71 | struct device *dev = &rsv->rc->uwb_dev.dev; | 106 | struct device *dev = &rsv->rc->uwb_dev.dev; |
72 | struct uwb_dev_addr devaddr; | 107 | struct uwb_dev_addr devaddr; |
@@ -82,6 +117,23 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv) | |||
82 | dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); | 117 | dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); |
83 | } | 118 | } |
84 | 119 | ||
120 | static void uwb_rsv_release(struct kref *kref) | ||
121 | { | ||
122 | struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref); | ||
123 | |||
124 | kfree(rsv); | ||
125 | } | ||
126 | |||
127 | void uwb_rsv_get(struct uwb_rsv *rsv) | ||
128 | { | ||
129 | kref_get(&rsv->kref); | ||
130 | } | ||
131 | |||
132 | void uwb_rsv_put(struct uwb_rsv *rsv) | ||
133 | { | ||
134 | kref_put(&rsv->kref, uwb_rsv_release); | ||
135 | } | ||
136 | |||
85 | /* | 137 | /* |
86 | * Get a free stream index for a reservation. | 138 | * Get a free stream index for a reservation. |
87 | * | 139 | * |
@@ -92,6 +144,7 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv) | |||
92 | static int uwb_rsv_get_stream(struct uwb_rsv *rsv) | 144 | static int uwb_rsv_get_stream(struct uwb_rsv *rsv) |
93 | { | 145 | { |
94 | struct uwb_rc *rc = rsv->rc; | 146 | struct uwb_rc *rc = rsv->rc; |
147 | struct device *dev = &rc->uwb_dev.dev; | ||
95 | unsigned long *streams_bm; | 148 | unsigned long *streams_bm; |
96 | int stream; | 149 | int stream; |
97 | 150 | ||
@@ -113,12 +166,15 @@ static int uwb_rsv_get_stream(struct uwb_rsv *rsv) | |||
113 | rsv->stream = stream; | 166 | rsv->stream = stream; |
114 | set_bit(stream, streams_bm); | 167 | set_bit(stream, streams_bm); |
115 | 168 | ||
169 | dev_dbg(dev, "get stream %d\n", rsv->stream); | ||
170 | |||
116 | return 0; | 171 | return 0; |
117 | } | 172 | } |
118 | 173 | ||
119 | static void uwb_rsv_put_stream(struct uwb_rsv *rsv) | 174 | static void uwb_rsv_put_stream(struct uwb_rsv *rsv) |
120 | { | 175 | { |
121 | struct uwb_rc *rc = rsv->rc; | 176 | struct uwb_rc *rc = rsv->rc; |
177 | struct device *dev = &rc->uwb_dev.dev; | ||
122 | unsigned long *streams_bm; | 178 | unsigned long *streams_bm; |
123 | 179 | ||
124 | switch (rsv->target.type) { | 180 | switch (rsv->target.type) { |
@@ -133,86 +189,52 @@ static void uwb_rsv_put_stream(struct uwb_rsv *rsv) | |||
133 | } | 189 | } |
134 | 190 | ||
135 | clear_bit(rsv->stream, streams_bm); | 191 | clear_bit(rsv->stream, streams_bm); |
192 | |||
193 | dev_dbg(dev, "put stream %d\n", rsv->stream); | ||
136 | } | 194 | } |
137 | 195 | ||
138 | /* | 196 | void uwb_rsv_backoff_win_timer(unsigned long arg) |
139 | * Generate a MAS allocation with a single row component. | ||
140 | */ | ||
141 | static void uwb_rsv_gen_alloc_row(struct uwb_mas_bm *mas, | ||
142 | int first_mas, int mas_per_zone, | ||
143 | int zs, int ze) | ||
144 | { | 197 | { |
145 | struct uwb_mas_bm col; | 198 | struct uwb_drp_backoff_win *bow = (struct uwb_drp_backoff_win *)arg; |
146 | int z; | 199 | struct uwb_rc *rc = container_of(bow, struct uwb_rc, bow); |
147 | 200 | struct device *dev = &rc->uwb_dev.dev; | |
148 | bitmap_zero(mas->bm, UWB_NUM_MAS); | 201 | |
149 | bitmap_zero(col.bm, UWB_NUM_MAS); | 202 | bow->can_reserve_extra_mases = true; |
150 | bitmap_fill(col.bm, mas_per_zone); | 203 | if (bow->total_expired <= 4) { |
151 | bitmap_shift_left(col.bm, col.bm, first_mas + zs * UWB_MAS_PER_ZONE, UWB_NUM_MAS); | 204 | bow->total_expired++; |
152 | 205 | } else { | |
153 | for (z = zs; z <= ze; z++) { | 206 | /* after 4 backoff window has expired we can exit from |
154 | bitmap_or(mas->bm, mas->bm, col.bm, UWB_NUM_MAS); | 207 | * the backoff procedure */ |
155 | bitmap_shift_left(col.bm, col.bm, UWB_MAS_PER_ZONE, UWB_NUM_MAS); | 208 | bow->total_expired = 0; |
209 | bow->window = UWB_DRP_BACKOFF_WIN_MIN >> 1; | ||
156 | } | 210 | } |
211 | dev_dbg(dev, "backoff_win_timer total_expired=%d, n=%d\n: ", bow->total_expired, bow->n); | ||
212 | |||
213 | /* try to relocate all the "to be moved" relocations */ | ||
214 | uwb_rsv_handle_drp_avail_change(rc); | ||
157 | } | 215 | } |
158 | 216 | ||
159 | /* | 217 | void uwb_rsv_backoff_win_increment(struct uwb_rc *rc) |
160 | * Allocate some MAS for this reservation based on current local | ||
161 | * availability, the reservation parameters (max_mas, min_mas, | ||
162 | * sparsity), and the WiMedia rules for MAS allocations. | ||
163 | * | ||
164 | * Returns -EBUSY is insufficient free MAS are available. | ||
165 | * | ||
166 | * FIXME: to simplify this, only safe reservations with a single row | ||
167 | * component in zones 1 to 15 are tried (zone 0 is skipped to avoid | ||
168 | * problems with the MAS reserved for the BP). | ||
169 | * | ||
170 | * [ECMA-368] section B.2. | ||
171 | */ | ||
172 | static int uwb_rsv_alloc_mas(struct uwb_rsv *rsv) | ||
173 | { | 218 | { |
174 | static const int safe_mas_in_row[UWB_NUM_ZONES] = { | 219 | struct uwb_drp_backoff_win *bow = &rc->bow; |
175 | 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, | 220 | struct device *dev = &rc->uwb_dev.dev; |
176 | }; | 221 | unsigned timeout_us; |
177 | int n, r; | ||
178 | struct uwb_mas_bm mas; | ||
179 | bool found = false; | ||
180 | 222 | ||
181 | /* | 223 | dev_dbg(dev, "backoff_win_increment: window=%d\n", bow->window); |
182 | * Search all valid safe allocations until either: too few MAS | ||
183 | * are available; or the smallest allocation with sufficient | ||
184 | * MAS is found. | ||
185 | * | ||
186 | * The top of the zones are preferred, so space for larger | ||
187 | * allocations is available in the bottom of the zone (e.g., a | ||
188 | * 15 MAS allocation should start in row 14 leaving space for | ||
189 | * a 120 MAS allocation at row 0). | ||
190 | */ | ||
191 | for (n = safe_mas_in_row[0]; n >= 1; n--) { | ||
192 | int num_mas; | ||
193 | 224 | ||
194 | num_mas = n * (UWB_NUM_ZONES - 1); | 225 | bow->can_reserve_extra_mases = false; |
195 | if (num_mas < rsv->min_mas) | ||
196 | break; | ||
197 | if (found && num_mas < rsv->max_mas) | ||
198 | break; | ||
199 | 226 | ||
200 | for (r = UWB_MAS_PER_ZONE-1; r >= 0; r--) { | 227 | if((bow->window << 1) == UWB_DRP_BACKOFF_WIN_MAX) |
201 | if (safe_mas_in_row[r] < n) | 228 | return; |
202 | continue; | ||
203 | uwb_rsv_gen_alloc_row(&mas, r, n, 1, UWB_NUM_ZONES); | ||
204 | if (uwb_drp_avail_reserve_pending(rsv->rc, &mas) == 0) { | ||
205 | found = true; | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | 229 | ||
211 | if (!found) | 230 | bow->window <<= 1; |
212 | return -EBUSY; | 231 | bow->n = random32() & (bow->window - 1); |
232 | dev_dbg(dev, "new_window=%d, n=%d\n: ", bow->window, bow->n); | ||
213 | 233 | ||
214 | bitmap_copy(rsv->mas.bm, mas.bm, UWB_NUM_MAS); | 234 | /* reset the timer associated variables */ |
215 | return 0; | 235 | timeout_us = bow->n * UWB_SUPERFRAME_LENGTH_US; |
236 | bow->total_expired = 0; | ||
237 | mod_timer(&bow->timer, jiffies + usecs_to_jiffies(timeout_us)); | ||
216 | } | 238 | } |
217 | 239 | ||
218 | static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) | 240 | static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) |
@@ -225,13 +247,16 @@ static void uwb_rsv_stroke_timer(struct uwb_rsv *rsv) | |||
225 | * received. | 247 | * received. |
226 | */ | 248 | */ |
227 | if (rsv->is_multicast) { | 249 | if (rsv->is_multicast) { |
228 | if (rsv->state == UWB_RSV_STATE_O_INITIATED) | 250 | if (rsv->state == UWB_RSV_STATE_O_INITIATED |
251 | || rsv->state == UWB_RSV_STATE_O_MOVE_EXPANDING | ||
252 | || rsv->state == UWB_RSV_STATE_O_MOVE_COMBINING | ||
253 | || rsv->state == UWB_RSV_STATE_O_MOVE_REDUCING) | ||
229 | sframes = 1; | 254 | sframes = 1; |
230 | if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED) | 255 | if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED) |
231 | sframes = 0; | 256 | sframes = 0; |
257 | |||
232 | } | 258 | } |
233 | 259 | ||
234 | rsv->expired = false; | ||
235 | if (sframes > 0) { | 260 | if (sframes > 0) { |
236 | /* | 261 | /* |
237 | * Add an additional 2 superframes to account for the | 262 | * Add an additional 2 superframes to account for the |
@@ -253,7 +278,7 @@ static void uwb_rsv_state_update(struct uwb_rsv *rsv, | |||
253 | rsv->state = new_state; | 278 | rsv->state = new_state; |
254 | rsv->ie_valid = false; | 279 | rsv->ie_valid = false; |
255 | 280 | ||
256 | uwb_rsv_dump(rsv); | 281 | uwb_rsv_dump("SU", rsv); |
257 | 282 | ||
258 | uwb_rsv_stroke_timer(rsv); | 283 | uwb_rsv_stroke_timer(rsv); |
259 | uwb_rsv_sched_update(rsv->rc); | 284 | uwb_rsv_sched_update(rsv->rc); |
@@ -267,10 +292,17 @@ static void uwb_rsv_callback(struct uwb_rsv *rsv) | |||
267 | 292 | ||
268 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) | 293 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) |
269 | { | 294 | { |
295 | struct uwb_rsv_move *mv = &rsv->mv; | ||
296 | |||
270 | if (rsv->state == new_state) { | 297 | if (rsv->state == new_state) { |
271 | switch (rsv->state) { | 298 | switch (rsv->state) { |
272 | case UWB_RSV_STATE_O_ESTABLISHED: | 299 | case UWB_RSV_STATE_O_ESTABLISHED: |
300 | case UWB_RSV_STATE_O_MOVE_EXPANDING: | ||
301 | case UWB_RSV_STATE_O_MOVE_COMBINING: | ||
302 | case UWB_RSV_STATE_O_MOVE_REDUCING: | ||
273 | case UWB_RSV_STATE_T_ACCEPTED: | 303 | case UWB_RSV_STATE_T_ACCEPTED: |
304 | case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: | ||
305 | case UWB_RSV_STATE_T_RESIZED: | ||
274 | case UWB_RSV_STATE_NONE: | 306 | case UWB_RSV_STATE_NONE: |
275 | uwb_rsv_stroke_timer(rsv); | 307 | uwb_rsv_stroke_timer(rsv); |
276 | break; | 308 | break; |
@@ -282,10 +314,10 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) | |||
282 | return; | 314 | return; |
283 | } | 315 | } |
284 | 316 | ||
317 | uwb_rsv_dump("SC", rsv); | ||
318 | |||
285 | switch (new_state) { | 319 | switch (new_state) { |
286 | case UWB_RSV_STATE_NONE: | 320 | case UWB_RSV_STATE_NONE: |
287 | uwb_drp_avail_release(rsv->rc, &rsv->mas); | ||
288 | uwb_rsv_put_stream(rsv); | ||
289 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); | 321 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_NONE); |
290 | uwb_rsv_callback(rsv); | 322 | uwb_rsv_callback(rsv); |
291 | break; | 323 | break; |
@@ -295,12 +327,45 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) | |||
295 | case UWB_RSV_STATE_O_PENDING: | 327 | case UWB_RSV_STATE_O_PENDING: |
296 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_PENDING); | 328 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_PENDING); |
297 | break; | 329 | break; |
330 | case UWB_RSV_STATE_O_MODIFIED: | ||
331 | /* in the companion there are the MASes to drop */ | ||
332 | bitmap_andnot(rsv->mas.bm, rsv->mas.bm, mv->companion_mas.bm, UWB_NUM_MAS); | ||
333 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MODIFIED); | ||
334 | break; | ||
298 | case UWB_RSV_STATE_O_ESTABLISHED: | 335 | case UWB_RSV_STATE_O_ESTABLISHED: |
336 | if (rsv->state == UWB_RSV_STATE_O_MODIFIED | ||
337 | || rsv->state == UWB_RSV_STATE_O_MOVE_REDUCING) { | ||
338 | uwb_drp_avail_release(rsv->rc, &mv->companion_mas); | ||
339 | rsv->needs_release_companion_mas = false; | ||
340 | } | ||
299 | uwb_drp_avail_reserve(rsv->rc, &rsv->mas); | 341 | uwb_drp_avail_reserve(rsv->rc, &rsv->mas); |
300 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_ESTABLISHED); | 342 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_ESTABLISHED); |
301 | uwb_rsv_callback(rsv); | 343 | uwb_rsv_callback(rsv); |
302 | break; | 344 | break; |
345 | case UWB_RSV_STATE_O_MOVE_EXPANDING: | ||
346 | rsv->needs_release_companion_mas = true; | ||
347 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); | ||
348 | break; | ||
349 | case UWB_RSV_STATE_O_MOVE_COMBINING: | ||
350 | rsv->needs_release_companion_mas = false; | ||
351 | uwb_drp_avail_reserve(rsv->rc, &mv->companion_mas); | ||
352 | bitmap_or(rsv->mas.bm, rsv->mas.bm, mv->companion_mas.bm, UWB_NUM_MAS); | ||
353 | rsv->mas.safe += mv->companion_mas.safe; | ||
354 | rsv->mas.unsafe += mv->companion_mas.unsafe; | ||
355 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
356 | break; | ||
357 | case UWB_RSV_STATE_O_MOVE_REDUCING: | ||
358 | bitmap_andnot(mv->companion_mas.bm, rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS); | ||
359 | rsv->needs_release_companion_mas = true; | ||
360 | rsv->mas.safe = mv->final_mas.safe; | ||
361 | rsv->mas.unsafe = mv->final_mas.unsafe; | ||
362 | bitmap_copy(rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS); | ||
363 | bitmap_copy(rsv->mas.unsafe_bm, mv->final_mas.unsafe_bm, UWB_NUM_MAS); | ||
364 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
365 | break; | ||
303 | case UWB_RSV_STATE_T_ACCEPTED: | 366 | case UWB_RSV_STATE_T_ACCEPTED: |
367 | case UWB_RSV_STATE_T_RESIZED: | ||
368 | rsv->needs_release_companion_mas = false; | ||
304 | uwb_drp_avail_reserve(rsv->rc, &rsv->mas); | 369 | uwb_drp_avail_reserve(rsv->rc, &rsv->mas); |
305 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_ACCEPTED); | 370 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_ACCEPTED); |
306 | uwb_rsv_callback(rsv); | 371 | uwb_rsv_callback(rsv); |
@@ -308,12 +373,82 @@ void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state) | |||
308 | case UWB_RSV_STATE_T_DENIED: | 373 | case UWB_RSV_STATE_T_DENIED: |
309 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_DENIED); | 374 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_DENIED); |
310 | break; | 375 | break; |
376 | case UWB_RSV_STATE_T_CONFLICT: | ||
377 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_CONFLICT); | ||
378 | break; | ||
379 | case UWB_RSV_STATE_T_PENDING: | ||
380 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_PENDING); | ||
381 | break; | ||
382 | case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: | ||
383 | rsv->needs_release_companion_mas = true; | ||
384 | uwb_drp_avail_reserve(rsv->rc, &mv->companion_mas); | ||
385 | uwb_rsv_state_update(rsv, UWB_RSV_STATE_T_EXPANDING_ACCEPTED); | ||
386 | break; | ||
311 | default: | 387 | default: |
312 | dev_err(&rsv->rc->uwb_dev.dev, "unhandled state: %s (%d)\n", | 388 | dev_err(&rsv->rc->uwb_dev.dev, "unhandled state: %s (%d)\n", |
313 | uwb_rsv_state_str(new_state), new_state); | 389 | uwb_rsv_state_str(new_state), new_state); |
314 | } | 390 | } |
315 | } | 391 | } |
316 | 392 | ||
393 | static void uwb_rsv_handle_timeout_work(struct work_struct *work) | ||
394 | { | ||
395 | struct uwb_rsv *rsv = container_of(work, struct uwb_rsv, | ||
396 | handle_timeout_work); | ||
397 | struct uwb_rc *rc = rsv->rc; | ||
398 | |||
399 | mutex_lock(&rc->rsvs_mutex); | ||
400 | |||
401 | uwb_rsv_dump("TO", rsv); | ||
402 | |||
403 | switch (rsv->state) { | ||
404 | case UWB_RSV_STATE_O_INITIATED: | ||
405 | if (rsv->is_multicast) { | ||
406 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
407 | goto unlock; | ||
408 | } | ||
409 | break; | ||
410 | case UWB_RSV_STATE_O_MOVE_EXPANDING: | ||
411 | if (rsv->is_multicast) { | ||
412 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_COMBINING); | ||
413 | goto unlock; | ||
414 | } | ||
415 | break; | ||
416 | case UWB_RSV_STATE_O_MOVE_COMBINING: | ||
417 | if (rsv->is_multicast) { | ||
418 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_REDUCING); | ||
419 | goto unlock; | ||
420 | } | ||
421 | break; | ||
422 | case UWB_RSV_STATE_O_MOVE_REDUCING: | ||
423 | if (rsv->is_multicast) { | ||
424 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_ESTABLISHED); | ||
425 | goto unlock; | ||
426 | } | ||
427 | break; | ||
428 | case UWB_RSV_STATE_O_ESTABLISHED: | ||
429 | if (rsv->is_multicast) | ||
430 | goto unlock; | ||
431 | break; | ||
432 | case UWB_RSV_STATE_T_EXPANDING_ACCEPTED: | ||
433 | /* | ||
434 | * The time out could be for the main or of the | ||
435 | * companion DRP, assume it's for the companion and | ||
436 | * drop that first. A further time out is required to | ||
437 | * drop the main. | ||
438 | */ | ||
439 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_T_ACCEPTED); | ||
440 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); | ||
441 | goto unlock; | ||
442 | default: | ||
443 | break; | ||
444 | } | ||
445 | |||
446 | uwb_rsv_remove(rsv); | ||
447 | |||
448 | unlock: | ||
449 | mutex_unlock(&rc->rsvs_mutex); | ||
450 | } | ||
451 | |||
317 | static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) | 452 | static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) |
318 | { | 453 | { |
319 | struct uwb_rsv *rsv; | 454 | struct uwb_rsv *rsv; |
@@ -324,23 +459,17 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc) | |||
324 | 459 | ||
325 | INIT_LIST_HEAD(&rsv->rc_node); | 460 | INIT_LIST_HEAD(&rsv->rc_node); |
326 | INIT_LIST_HEAD(&rsv->pal_node); | 461 | INIT_LIST_HEAD(&rsv->pal_node); |
462 | kref_init(&rsv->kref); | ||
327 | init_timer(&rsv->timer); | 463 | init_timer(&rsv->timer); |
328 | rsv->timer.function = uwb_rsv_timer; | 464 | rsv->timer.function = uwb_rsv_timer; |
329 | rsv->timer.data = (unsigned long)rsv; | 465 | rsv->timer.data = (unsigned long)rsv; |
330 | 466 | ||
331 | rsv->rc = rc; | 467 | rsv->rc = rc; |
468 | INIT_WORK(&rsv->handle_timeout_work, uwb_rsv_handle_timeout_work); | ||
332 | 469 | ||
333 | return rsv; | 470 | return rsv; |
334 | } | 471 | } |
335 | 472 | ||
336 | static void uwb_rsv_free(struct uwb_rsv *rsv) | ||
337 | { | ||
338 | uwb_dev_put(rsv->owner); | ||
339 | if (rsv->target.type == UWB_RSV_TARGET_DEV) | ||
340 | uwb_dev_put(rsv->target.dev); | ||
341 | kfree(rsv); | ||
342 | } | ||
343 | |||
344 | /** | 473 | /** |
345 | * uwb_rsv_create - allocate and initialize a UWB reservation structure | 474 | * uwb_rsv_create - allocate and initialize a UWB reservation structure |
346 | * @rc: the radio controller | 475 | * @rc: the radio controller |
@@ -371,26 +500,36 @@ EXPORT_SYMBOL_GPL(uwb_rsv_create); | |||
371 | 500 | ||
372 | void uwb_rsv_remove(struct uwb_rsv *rsv) | 501 | void uwb_rsv_remove(struct uwb_rsv *rsv) |
373 | { | 502 | { |
503 | uwb_rsv_dump("RM", rsv); | ||
504 | |||
374 | if (rsv->state != UWB_RSV_STATE_NONE) | 505 | if (rsv->state != UWB_RSV_STATE_NONE) |
375 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 506 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); |
507 | |||
508 | if (rsv->needs_release_companion_mas) | ||
509 | uwb_drp_avail_release(rsv->rc, &rsv->mv.companion_mas); | ||
510 | uwb_drp_avail_release(rsv->rc, &rsv->mas); | ||
511 | |||
512 | if (uwb_rsv_is_owner(rsv)) | ||
513 | uwb_rsv_put_stream(rsv); | ||
514 | |||
376 | del_timer_sync(&rsv->timer); | 515 | del_timer_sync(&rsv->timer); |
377 | list_del(&rsv->rc_node); | 516 | uwb_dev_put(rsv->owner); |
378 | uwb_rsv_free(rsv); | 517 | if (rsv->target.type == UWB_RSV_TARGET_DEV) |
518 | uwb_dev_put(rsv->target.dev); | ||
519 | |||
520 | list_del_init(&rsv->rc_node); | ||
521 | uwb_rsv_put(rsv); | ||
379 | } | 522 | } |
380 | 523 | ||
381 | /** | 524 | /** |
382 | * uwb_rsv_destroy - free a UWB reservation structure | 525 | * uwb_rsv_destroy - free a UWB reservation structure |
383 | * @rsv: the reservation to free | 526 | * @rsv: the reservation to free |
384 | * | 527 | * |
385 | * The reservation will be terminated if it is pending or established. | 528 | * The reservation must already be terminated. |
386 | */ | 529 | */ |
387 | void uwb_rsv_destroy(struct uwb_rsv *rsv) | 530 | void uwb_rsv_destroy(struct uwb_rsv *rsv) |
388 | { | 531 | { |
389 | struct uwb_rc *rc = rsv->rc; | 532 | uwb_rsv_put(rsv); |
390 | |||
391 | mutex_lock(&rc->rsvs_mutex); | ||
392 | uwb_rsv_remove(rsv); | ||
393 | mutex_unlock(&rc->rsvs_mutex); | ||
394 | } | 533 | } |
395 | EXPORT_SYMBOL_GPL(uwb_rsv_destroy); | 534 | EXPORT_SYMBOL_GPL(uwb_rsv_destroy); |
396 | 535 | ||
@@ -399,7 +538,7 @@ EXPORT_SYMBOL_GPL(uwb_rsv_destroy); | |||
399 | * @rsv: the reservation | 538 | * @rsv: the reservation |
400 | * | 539 | * |
401 | * The PAL should fill in @rsv's owner, target, type, max_mas, | 540 | * The PAL should fill in @rsv's owner, target, type, max_mas, |
402 | * min_mas, sparsity and is_multicast fields. If the target is a | 541 | * min_mas, max_interval and is_multicast fields. If the target is a |
403 | * uwb_dev it must be referenced. | 542 | * uwb_dev it must be referenced. |
404 | * | 543 | * |
405 | * The reservation's callback will be called when the reservation is | 544 | * The reservation's callback will be called when the reservation is |
@@ -408,20 +547,32 @@ EXPORT_SYMBOL_GPL(uwb_rsv_destroy); | |||
408 | int uwb_rsv_establish(struct uwb_rsv *rsv) | 547 | int uwb_rsv_establish(struct uwb_rsv *rsv) |
409 | { | 548 | { |
410 | struct uwb_rc *rc = rsv->rc; | 549 | struct uwb_rc *rc = rsv->rc; |
550 | struct uwb_mas_bm available; | ||
411 | int ret; | 551 | int ret; |
412 | 552 | ||
413 | mutex_lock(&rc->rsvs_mutex); | 553 | mutex_lock(&rc->rsvs_mutex); |
414 | |||
415 | ret = uwb_rsv_get_stream(rsv); | 554 | ret = uwb_rsv_get_stream(rsv); |
416 | if (ret) | 555 | if (ret) |
417 | goto out; | 556 | goto out; |
418 | 557 | ||
419 | ret = uwb_rsv_alloc_mas(rsv); | 558 | rsv->tiebreaker = random32() & 1; |
420 | if (ret) { | 559 | /* get available mas bitmap */ |
560 | uwb_drp_available(rc, &available); | ||
561 | |||
562 | ret = uwb_rsv_find_best_allocation(rsv, &available, &rsv->mas); | ||
563 | if (ret == UWB_RSV_ALLOC_NOT_FOUND) { | ||
564 | ret = -EBUSY; | ||
565 | uwb_rsv_put_stream(rsv); | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | ret = uwb_drp_avail_reserve_pending(rc, &rsv->mas); | ||
570 | if (ret != 0) { | ||
421 | uwb_rsv_put_stream(rsv); | 571 | uwb_rsv_put_stream(rsv); |
422 | goto out; | 572 | goto out; |
423 | } | 573 | } |
424 | 574 | ||
575 | uwb_rsv_get(rsv); | ||
425 | list_add_tail(&rsv->rc_node, &rc->reservations); | 576 | list_add_tail(&rsv->rc_node, &rc->reservations); |
426 | rsv->owner = &rc->uwb_dev; | 577 | rsv->owner = &rc->uwb_dev; |
427 | uwb_dev_get(rsv->owner); | 578 | uwb_dev_get(rsv->owner); |
@@ -437,16 +588,71 @@ EXPORT_SYMBOL_GPL(uwb_rsv_establish); | |||
437 | * @rsv: the reservation to modify | 588 | * @rsv: the reservation to modify |
438 | * @max_mas: new maximum MAS to reserve | 589 | * @max_mas: new maximum MAS to reserve |
439 | * @min_mas: new minimum MAS to reserve | 590 | * @min_mas: new minimum MAS to reserve |
440 | * @sparsity: new sparsity to use | 591 | * @max_interval: new max_interval to use |
441 | * | 592 | * |
442 | * FIXME: implement this once there are PALs that use it. | 593 | * FIXME: implement this once there are PALs that use it. |
443 | */ | 594 | */ |
444 | int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int sparsity) | 595 | int uwb_rsv_modify(struct uwb_rsv *rsv, int max_mas, int min_mas, int max_interval) |
445 | { | 596 | { |
446 | return -ENOSYS; | 597 | return -ENOSYS; |
447 | } | 598 | } |
448 | EXPORT_SYMBOL_GPL(uwb_rsv_modify); | 599 | EXPORT_SYMBOL_GPL(uwb_rsv_modify); |
449 | 600 | ||
601 | /* | ||
602 | * move an already established reservation (rc->rsvs_mutex must to be | ||
603 | * taken when tis function is called) | ||
604 | */ | ||
605 | int uwb_rsv_try_move(struct uwb_rsv *rsv, struct uwb_mas_bm *available) | ||
606 | { | ||
607 | struct uwb_rc *rc = rsv->rc; | ||
608 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
609 | struct device *dev = &rc->uwb_dev.dev; | ||
610 | struct uwb_rsv_move *mv; | ||
611 | int ret = 0; | ||
612 | |||
613 | if (bow->can_reserve_extra_mases == false) | ||
614 | return -EBUSY; | ||
615 | |||
616 | mv = &rsv->mv; | ||
617 | |||
618 | if (uwb_rsv_find_best_allocation(rsv, available, &mv->final_mas) == UWB_RSV_ALLOC_FOUND) { | ||
619 | |||
620 | if (!bitmap_equal(rsv->mas.bm, mv->final_mas.bm, UWB_NUM_MAS)) { | ||
621 | /* We want to move the reservation */ | ||
622 | bitmap_andnot(mv->companion_mas.bm, mv->final_mas.bm, rsv->mas.bm, UWB_NUM_MAS); | ||
623 | uwb_drp_avail_reserve_pending(rc, &mv->companion_mas); | ||
624 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_O_MOVE_EXPANDING); | ||
625 | } | ||
626 | } else { | ||
627 | dev_dbg(dev, "new allocation not found\n"); | ||
628 | } | ||
629 | |||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | /* It will try to move every reservation in state O_ESTABLISHED giving | ||
634 | * to the MAS allocator algorithm an availability that is the real one | ||
635 | * plus the allocation already established from the reservation. */ | ||
636 | void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc) | ||
637 | { | ||
638 | struct uwb_drp_backoff_win *bow = &rc->bow; | ||
639 | struct uwb_rsv *rsv; | ||
640 | struct uwb_mas_bm mas; | ||
641 | |||
642 | if (bow->can_reserve_extra_mases == false) | ||
643 | return; | ||
644 | |||
645 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
646 | if (rsv->state == UWB_RSV_STATE_O_ESTABLISHED || | ||
647 | rsv->state == UWB_RSV_STATE_O_TO_BE_MOVED) { | ||
648 | uwb_drp_available(rc, &mas); | ||
649 | bitmap_or(mas.bm, mas.bm, rsv->mas.bm, UWB_NUM_MAS); | ||
650 | uwb_rsv_try_move(rsv, &mas); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | } | ||
655 | |||
450 | /** | 656 | /** |
451 | * uwb_rsv_terminate - terminate an established reservation | 657 | * uwb_rsv_terminate - terminate an established reservation |
452 | * @rsv: the reservation to terminate | 658 | * @rsv: the reservation to terminate |
@@ -463,7 +669,8 @@ void uwb_rsv_terminate(struct uwb_rsv *rsv) | |||
463 | 669 | ||
464 | mutex_lock(&rc->rsvs_mutex); | 670 | mutex_lock(&rc->rsvs_mutex); |
465 | 671 | ||
466 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | 672 | if (rsv->state != UWB_RSV_STATE_NONE) |
673 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | ||
467 | 674 | ||
468 | mutex_unlock(&rc->rsvs_mutex); | 675 | mutex_unlock(&rc->rsvs_mutex); |
469 | } | 676 | } |
@@ -477,9 +684,14 @@ EXPORT_SYMBOL_GPL(uwb_rsv_terminate); | |||
477 | * | 684 | * |
478 | * Reservation requests from peers are denied unless a PAL accepts it | 685 | * Reservation requests from peers are denied unless a PAL accepts it |
479 | * by calling this function. | 686 | * by calling this function. |
687 | * | ||
688 | * The PAL call uwb_rsv_destroy() for all accepted reservations before | ||
689 | * calling uwb_pal_unregister(). | ||
480 | */ | 690 | */ |
481 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) | 691 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) |
482 | { | 692 | { |
693 | uwb_rsv_get(rsv); | ||
694 | |||
483 | rsv->callback = cb; | 695 | rsv->callback = cb; |
484 | rsv->pal_priv = pal_priv; | 696 | rsv->pal_priv = pal_priv; |
485 | rsv->state = UWB_RSV_STATE_T_ACCEPTED; | 697 | rsv->state = UWB_RSV_STATE_T_ACCEPTED; |
@@ -530,9 +742,9 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, | |||
530 | uwb_dev_get(rsv->owner); | 742 | uwb_dev_get(rsv->owner); |
531 | rsv->target.type = UWB_RSV_TARGET_DEV; | 743 | rsv->target.type = UWB_RSV_TARGET_DEV; |
532 | rsv->target.dev = &rc->uwb_dev; | 744 | rsv->target.dev = &rc->uwb_dev; |
745 | uwb_dev_get(&rc->uwb_dev); | ||
533 | rsv->type = uwb_ie_drp_type(drp_ie); | 746 | rsv->type = uwb_ie_drp_type(drp_ie); |
534 | rsv->stream = uwb_ie_drp_stream_index(drp_ie); | 747 | rsv->stream = uwb_ie_drp_stream_index(drp_ie); |
535 | set_bit(rsv->stream, rsv->owner->streams); | ||
536 | uwb_drp_ie_to_bm(&rsv->mas, drp_ie); | 748 | uwb_drp_ie_to_bm(&rsv->mas, drp_ie); |
537 | 749 | ||
538 | /* | 750 | /* |
@@ -540,24 +752,46 @@ static struct uwb_rsv *uwb_rsv_new_target(struct uwb_rc *rc, | |||
540 | * deny the request. | 752 | * deny the request. |
541 | */ | 753 | */ |
542 | rsv->state = UWB_RSV_STATE_T_DENIED; | 754 | rsv->state = UWB_RSV_STATE_T_DENIED; |
543 | spin_lock(&rc->pal_lock); | 755 | mutex_lock(&rc->uwb_dev.mutex); |
544 | list_for_each_entry(pal, &rc->pals, node) { | 756 | list_for_each_entry(pal, &rc->pals, node) { |
545 | if (pal->new_rsv) | 757 | if (pal->new_rsv) |
546 | pal->new_rsv(rsv); | 758 | pal->new_rsv(pal, rsv); |
547 | if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) | 759 | if (rsv->state == UWB_RSV_STATE_T_ACCEPTED) |
548 | break; | 760 | break; |
549 | } | 761 | } |
550 | spin_unlock(&rc->pal_lock); | 762 | mutex_unlock(&rc->uwb_dev.mutex); |
551 | 763 | ||
552 | list_add_tail(&rsv->rc_node, &rc->reservations); | 764 | list_add_tail(&rsv->rc_node, &rc->reservations); |
553 | state = rsv->state; | 765 | state = rsv->state; |
554 | rsv->state = UWB_RSV_STATE_NONE; | 766 | rsv->state = UWB_RSV_STATE_NONE; |
555 | uwb_rsv_set_state(rsv, state); | 767 | |
768 | /* FIXME: do something sensible here */ | ||
769 | if (state == UWB_RSV_STATE_T_ACCEPTED | ||
770 | && uwb_drp_avail_reserve_pending(rc, &rsv->mas) == -EBUSY) { | ||
771 | /* FIXME: do something sensible here */ | ||
772 | } else { | ||
773 | uwb_rsv_set_state(rsv, state); | ||
774 | } | ||
556 | 775 | ||
557 | return rsv; | 776 | return rsv; |
558 | } | 777 | } |
559 | 778 | ||
560 | /** | 779 | /** |
780 | * uwb_rsv_get_usable_mas - get the bitmap of the usable MAS of a reservations | ||
781 | * @rsv: the reservation. | ||
782 | * @mas: returns the available MAS. | ||
783 | * | ||
784 | * The usable MAS of a reservation may be less than the negotiated MAS | ||
785 | * if alien BPs are present. | ||
786 | */ | ||
787 | void uwb_rsv_get_usable_mas(struct uwb_rsv *rsv, struct uwb_mas_bm *mas) | ||
788 | { | ||
789 | bitmap_zero(mas->bm, UWB_NUM_MAS); | ||
790 | bitmap_andnot(mas->bm, rsv->mas.bm, rsv->rc->cnflt_alien_bitmap.bm, UWB_NUM_MAS); | ||
791 | } | ||
792 | EXPORT_SYMBOL_GPL(uwb_rsv_get_usable_mas); | ||
793 | |||
794 | /** | ||
561 | * uwb_rsv_find - find a reservation for a received DRP IE. | 795 | * uwb_rsv_find - find a reservation for a received DRP IE. |
562 | * @rc: the radio controller | 796 | * @rc: the radio controller |
563 | * @src: source of the DRP IE | 797 | * @src: source of the DRP IE |
@@ -596,8 +830,6 @@ static bool uwb_rsv_update_all(struct uwb_rc *rc) | |||
596 | bool ie_updated = false; | 830 | bool ie_updated = false; |
597 | 831 | ||
598 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | 832 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { |
599 | if (rsv->expired) | ||
600 | uwb_drp_handle_timeout(rsv); | ||
601 | if (!rsv->ie_valid) { | 833 | if (!rsv->ie_valid) { |
602 | uwb_drp_ie_update(rsv); | 834 | uwb_drp_ie_update(rsv); |
603 | ie_updated = true; | 835 | ie_updated = true; |
@@ -607,9 +839,47 @@ static bool uwb_rsv_update_all(struct uwb_rc *rc) | |||
607 | return ie_updated; | 839 | return ie_updated; |
608 | } | 840 | } |
609 | 841 | ||
842 | void uwb_rsv_queue_update(struct uwb_rc *rc) | ||
843 | { | ||
844 | unsigned long delay_us = UWB_MAS_LENGTH_US * UWB_MAS_PER_ZONE; | ||
845 | |||
846 | queue_delayed_work(rc->rsv_workq, &rc->rsv_update_work, usecs_to_jiffies(delay_us)); | ||
847 | } | ||
848 | |||
849 | /** | ||
850 | * uwb_rsv_sched_update - schedule an update of the DRP IEs | ||
851 | * @rc: the radio controller. | ||
852 | * | ||
853 | * To improve performance and ensure correctness with [ECMA-368] the | ||
854 | * number of SET-DRP-IE commands that are done are limited. | ||
855 | * | ||
856 | * DRP IEs update come from two sources: DRP events from the hardware | ||
857 | * which all occur at the beginning of the superframe ('syncronous' | ||
858 | * events) and reservation establishment/termination requests from | ||
859 | * PALs or timers ('asynchronous' events). | ||
860 | * | ||
861 | * A delayed work ensures that all the synchronous events result in | ||
862 | * one SET-DRP-IE command. | ||
863 | * | ||
864 | * Additional logic (the set_drp_ie_pending and rsv_updated_postponed | ||
865 | * flags) will prevent an asynchrous event starting a SET-DRP-IE | ||
866 | * command if one is currently awaiting a response. | ||
867 | * | ||
868 | * FIXME: this does leave a window where an asynchrous event can delay | ||
869 | * the SET-DRP-IE for a synchronous event by one superframe. | ||
870 | */ | ||
610 | void uwb_rsv_sched_update(struct uwb_rc *rc) | 871 | void uwb_rsv_sched_update(struct uwb_rc *rc) |
611 | { | 872 | { |
612 | queue_work(rc->rsv_workq, &rc->rsv_update_work); | 873 | spin_lock(&rc->rsvs_lock); |
874 | if (!delayed_work_pending(&rc->rsv_update_work)) { | ||
875 | if (rc->set_drp_ie_pending > 0) { | ||
876 | rc->set_drp_ie_pending++; | ||
877 | goto unlock; | ||
878 | } | ||
879 | uwb_rsv_queue_update(rc); | ||
880 | } | ||
881 | unlock: | ||
882 | spin_unlock(&rc->rsvs_lock); | ||
613 | } | 883 | } |
614 | 884 | ||
615 | /* | 885 | /* |
@@ -618,7 +888,8 @@ void uwb_rsv_sched_update(struct uwb_rc *rc) | |||
618 | */ | 888 | */ |
619 | static void uwb_rsv_update_work(struct work_struct *work) | 889 | static void uwb_rsv_update_work(struct work_struct *work) |
620 | { | 890 | { |
621 | struct uwb_rc *rc = container_of(work, struct uwb_rc, rsv_update_work); | 891 | struct uwb_rc *rc = container_of(work, struct uwb_rc, |
892 | rsv_update_work.work); | ||
622 | bool ie_updated; | 893 | bool ie_updated; |
623 | 894 | ||
624 | mutex_lock(&rc->rsvs_mutex); | 895 | mutex_lock(&rc->rsvs_mutex); |
@@ -630,25 +901,71 @@ static void uwb_rsv_update_work(struct work_struct *work) | |||
630 | ie_updated = true; | 901 | ie_updated = true; |
631 | } | 902 | } |
632 | 903 | ||
633 | if (ie_updated) | 904 | if (ie_updated && (rc->set_drp_ie_pending == 0)) |
634 | uwb_rc_send_all_drp_ie(rc); | 905 | uwb_rc_send_all_drp_ie(rc); |
635 | 906 | ||
636 | mutex_unlock(&rc->rsvs_mutex); | 907 | mutex_unlock(&rc->rsvs_mutex); |
637 | } | 908 | } |
638 | 909 | ||
910 | static void uwb_rsv_alien_bp_work(struct work_struct *work) | ||
911 | { | ||
912 | struct uwb_rc *rc = container_of(work, struct uwb_rc, | ||
913 | rsv_alien_bp_work.work); | ||
914 | struct uwb_rsv *rsv; | ||
915 | |||
916 | mutex_lock(&rc->rsvs_mutex); | ||
917 | |||
918 | list_for_each_entry(rsv, &rc->reservations, rc_node) { | ||
919 | if (rsv->type != UWB_DRP_TYPE_ALIEN_BP) { | ||
920 | rsv->callback(rsv); | ||
921 | } | ||
922 | } | ||
923 | |||
924 | mutex_unlock(&rc->rsvs_mutex); | ||
925 | } | ||
926 | |||
639 | static void uwb_rsv_timer(unsigned long arg) | 927 | static void uwb_rsv_timer(unsigned long arg) |
640 | { | 928 | { |
641 | struct uwb_rsv *rsv = (struct uwb_rsv *)arg; | 929 | struct uwb_rsv *rsv = (struct uwb_rsv *)arg; |
642 | 930 | ||
643 | rsv->expired = true; | 931 | queue_work(rsv->rc->rsv_workq, &rsv->handle_timeout_work); |
644 | uwb_rsv_sched_update(rsv->rc); | 932 | } |
933 | |||
934 | /** | ||
935 | * uwb_rsv_remove_all - remove all reservations | ||
936 | * @rc: the radio controller | ||
937 | * | ||
938 | * A DRP IE update is not done. | ||
939 | */ | ||
940 | void uwb_rsv_remove_all(struct uwb_rc *rc) | ||
941 | { | ||
942 | struct uwb_rsv *rsv, *t; | ||
943 | |||
944 | mutex_lock(&rc->rsvs_mutex); | ||
945 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | ||
946 | uwb_rsv_remove(rsv); | ||
947 | } | ||
948 | /* Cancel any postponed update. */ | ||
949 | rc->set_drp_ie_pending = 0; | ||
950 | mutex_unlock(&rc->rsvs_mutex); | ||
951 | |||
952 | cancel_delayed_work_sync(&rc->rsv_update_work); | ||
645 | } | 953 | } |
646 | 954 | ||
647 | void uwb_rsv_init(struct uwb_rc *rc) | 955 | void uwb_rsv_init(struct uwb_rc *rc) |
648 | { | 956 | { |
649 | INIT_LIST_HEAD(&rc->reservations); | 957 | INIT_LIST_HEAD(&rc->reservations); |
958 | INIT_LIST_HEAD(&rc->cnflt_alien_list); | ||
650 | mutex_init(&rc->rsvs_mutex); | 959 | mutex_init(&rc->rsvs_mutex); |
651 | INIT_WORK(&rc->rsv_update_work, uwb_rsv_update_work); | 960 | spin_lock_init(&rc->rsvs_lock); |
961 | INIT_DELAYED_WORK(&rc->rsv_update_work, uwb_rsv_update_work); | ||
962 | INIT_DELAYED_WORK(&rc->rsv_alien_bp_work, uwb_rsv_alien_bp_work); | ||
963 | rc->bow.can_reserve_extra_mases = true; | ||
964 | rc->bow.total_expired = 0; | ||
965 | rc->bow.window = UWB_DRP_BACKOFF_WIN_MIN >> 1; | ||
966 | init_timer(&rc->bow.timer); | ||
967 | rc->bow.timer.function = uwb_rsv_backoff_win_timer; | ||
968 | rc->bow.timer.data = (unsigned long)&rc->bow; | ||
652 | 969 | ||
653 | bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS); | 970 | bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS); |
654 | } | 971 | } |
@@ -667,14 +984,6 @@ int uwb_rsv_setup(struct uwb_rc *rc) | |||
667 | 984 | ||
668 | void uwb_rsv_cleanup(struct uwb_rc *rc) | 985 | void uwb_rsv_cleanup(struct uwb_rc *rc) |
669 | { | 986 | { |
670 | struct uwb_rsv *rsv, *t; | 987 | uwb_rsv_remove_all(rc); |
671 | |||
672 | mutex_lock(&rc->rsvs_mutex); | ||
673 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | ||
674 | uwb_rsv_remove(rsv); | ||
675 | } | ||
676 | mutex_unlock(&rc->rsvs_mutex); | ||
677 | |||
678 | cancel_work_sync(&rc->rsv_update_work); | ||
679 | destroy_workqueue(rc->rsv_workq); | 988 | destroy_workqueue(rc->rsv_workq); |
680 | } | 989 | } |
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index 2d8d62d9f53e..5ad36164c13b 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c | |||
@@ -11,23 +11,48 @@ | |||
11 | #include <linux/uwb/umc.h> | 11 | #include <linux/uwb/umc.h> |
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | 13 | ||
14 | static int umc_bus_unbind_helper(struct device *dev, void *data) | 14 | static int umc_bus_pre_reset_helper(struct device *dev, void *data) |
15 | { | 15 | { |
16 | struct device *parent = data; | 16 | int ret = 0; |
17 | 17 | ||
18 | if (dev->parent == parent && dev->driver) | 18 | if (dev->driver) { |
19 | device_release_driver(dev); | 19 | struct umc_dev *umc = to_umc_dev(dev); |
20 | return 0; | 20 | struct umc_driver *umc_drv = to_umc_driver(dev->driver); |
21 | |||
22 | if (umc_drv->pre_reset) | ||
23 | ret = umc_drv->pre_reset(umc); | ||
24 | else | ||
25 | device_release_driver(dev); | ||
26 | } | ||
27 | return ret; | ||
28 | } | ||
29 | |||
30 | static int umc_bus_post_reset_helper(struct device *dev, void *data) | ||
31 | { | ||
32 | int ret = 0; | ||
33 | |||
34 | if (dev->driver) { | ||
35 | struct umc_dev *umc = to_umc_dev(dev); | ||
36 | struct umc_driver *umc_drv = to_umc_driver(dev->driver); | ||
37 | |||
38 | if (umc_drv->post_reset) | ||
39 | ret = umc_drv->post_reset(umc); | ||
40 | } else | ||
41 | ret = device_attach(dev); | ||
42 | |||
43 | return ret; | ||
21 | } | 44 | } |
22 | 45 | ||
23 | /** | 46 | /** |
24 | * umc_controller_reset - reset the whole UMC controller | 47 | * umc_controller_reset - reset the whole UMC controller |
25 | * @umc: the UMC device for the radio controller. | 48 | * @umc: the UMC device for the radio controller. |
26 | * | 49 | * |
27 | * Drivers will be unbound from all UMC devices belonging to the | 50 | * Drivers or all capabilities of the controller will have their |
28 | * controller and then the radio controller will be rebound. The | 51 | * pre_reset methods called or be unbound from their device. Then all |
29 | * radio controller is expected to do a full hardware reset when it is | 52 | * post_reset methods will be called or the drivers will be rebound. |
30 | * probed. | 53 | * |
54 | * Radio controllers must provide pre_reset and post_reset methods and | ||
55 | * reset the hardware in their start method. | ||
31 | * | 56 | * |
32 | * If this is called while a probe() or remove() is in progress it | 57 | * If this is called while a probe() or remove() is in progress it |
33 | * will return -EAGAIN and not perform the reset. | 58 | * will return -EAGAIN and not perform the reset. |
@@ -35,14 +60,13 @@ static int umc_bus_unbind_helper(struct device *dev, void *data) | |||
35 | int umc_controller_reset(struct umc_dev *umc) | 60 | int umc_controller_reset(struct umc_dev *umc) |
36 | { | 61 | { |
37 | struct device *parent = umc->dev.parent; | 62 | struct device *parent = umc->dev.parent; |
38 | int ret; | 63 | int ret = 0; |
39 | 64 | ||
40 | if (down_trylock(&parent->sem)) | 65 | if(down_trylock(&parent->sem)) |
41 | return -EAGAIN; | 66 | return -EAGAIN; |
42 | bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); | 67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); |
43 | ret = device_attach(&umc->dev); | 68 | if (ret >= 0) |
44 | if (ret == 1) | 69 | device_for_each_child(parent, parent, umc_bus_post_reset_helper); |
45 | ret = 0; | ||
46 | up(&parent->sem); | 70 | up(&parent->sem); |
47 | 71 | ||
48 | return ret; | 72 | return ret; |
@@ -75,10 +99,10 @@ static int umc_bus_rescan_helper(struct device *dev, void *data) | |||
75 | if (!dev->driver) | 99 | if (!dev->driver) |
76 | ret = device_attach(dev); | 100 | ret = device_attach(dev); |
77 | 101 | ||
78 | return ret < 0 ? ret : 0; | 102 | return ret; |
79 | } | 103 | } |
80 | 104 | ||
81 | static void umc_bus_rescan(void) | 105 | static void umc_bus_rescan(struct device *parent) |
82 | { | 106 | { |
83 | int err; | 107 | int err; |
84 | 108 | ||
@@ -86,7 +110,7 @@ static void umc_bus_rescan(void) | |||
86 | * We can't use bus_rescan_devices() here as it deadlocks when | 110 | * We can't use bus_rescan_devices() here as it deadlocks when |
87 | * it tries to retake the dev->parent semaphore. | 111 | * it tries to retake the dev->parent semaphore. |
88 | */ | 112 | */ |
89 | err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); | 113 | err = device_for_each_child(parent, NULL, umc_bus_rescan_helper); |
90 | if (err < 0) | 114 | if (err < 0) |
91 | printk(KERN_WARNING "%s: rescan of bus failed: %d\n", | 115 | printk(KERN_WARNING "%s: rescan of bus failed: %d\n", |
92 | KBUILD_MODNAME, err); | 116 | KBUILD_MODNAME, err); |
@@ -120,7 +144,7 @@ static int umc_device_probe(struct device *dev) | |||
120 | if (err) | 144 | if (err) |
121 | put_device(dev); | 145 | put_device(dev); |
122 | else | 146 | else |
123 | umc_bus_rescan(); | 147 | umc_bus_rescan(dev->parent); |
124 | 148 | ||
125 | return err; | 149 | return err; |
126 | } | 150 | } |
diff --git a/drivers/uwb/umc-dev.c b/drivers/uwb/umc-dev.c index aa44e1c1a102..1fc7d8270bb8 100644 --- a/drivers/uwb/umc-dev.c +++ b/drivers/uwb/umc-dev.c | |||
@@ -7,8 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <linux/uwb/umc.h> | 9 | #include <linux/uwb/umc.h> |
10 | #define D_LOCAL 0 | ||
11 | #include <linux/uwb/debug.h> | ||
12 | 10 | ||
13 | static void umc_device_release(struct device *dev) | 11 | static void umc_device_release(struct device *dev) |
14 | { | 12 | { |
@@ -31,8 +29,7 @@ struct umc_dev *umc_device_create(struct device *parent, int n) | |||
31 | 29 | ||
32 | umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); | 30 | umc = kzalloc(sizeof(struct umc_dev), GFP_KERNEL); |
33 | if (umc) { | 31 | if (umc) { |
34 | snprintf(umc->dev.bus_id, sizeof(umc->dev.bus_id), "%s-%d", | 32 | dev_set_name(&umc->dev, "%s-%d", dev_name(parent), n); |
35 | parent->bus_id, n); | ||
36 | umc->dev.parent = parent; | 33 | umc->dev.parent = parent; |
37 | umc->dev.bus = &umc_bus_type; | 34 | umc->dev.bus = &umc_bus_type; |
38 | umc->dev.release = umc_device_release; | 35 | umc->dev.release = umc_device_release; |
@@ -54,8 +51,6 @@ int umc_device_register(struct umc_dev *umc) | |||
54 | { | 51 | { |
55 | int err; | 52 | int err; |
56 | 53 | ||
57 | d_fnstart(3, &umc->dev, "(umc_dev %p)\n", umc); | ||
58 | |||
59 | err = request_resource(umc->resource.parent, &umc->resource); | 54 | err = request_resource(umc->resource.parent, &umc->resource); |
60 | if (err < 0) { | 55 | if (err < 0) { |
61 | dev_err(&umc->dev, "can't allocate resource range " | 56 | dev_err(&umc->dev, "can't allocate resource range " |
@@ -69,13 +64,11 @@ int umc_device_register(struct umc_dev *umc) | |||
69 | err = device_register(&umc->dev); | 64 | err = device_register(&umc->dev); |
70 | if (err < 0) | 65 | if (err < 0) |
71 | goto error_device_register; | 66 | goto error_device_register; |
72 | d_fnend(3, &umc->dev, "(umc_dev %p) = 0\n", umc); | ||
73 | return 0; | 67 | return 0; |
74 | 68 | ||
75 | error_device_register: | 69 | error_device_register: |
76 | release_resource(&umc->resource); | 70 | release_resource(&umc->resource); |
77 | error_request_resource: | 71 | error_request_resource: |
78 | d_fnend(3, &umc->dev, "(umc_dev %p) = %d\n", umc, err); | ||
79 | return err; | 72 | return err; |
80 | } | 73 | } |
81 | EXPORT_SYMBOL_GPL(umc_device_register); | 74 | EXPORT_SYMBOL_GPL(umc_device_register); |
@@ -95,10 +88,8 @@ void umc_device_unregister(struct umc_dev *umc) | |||
95 | if (!umc) | 88 | if (!umc) |
96 | return; | 89 | return; |
97 | dev = get_device(&umc->dev); | 90 | dev = get_device(&umc->dev); |
98 | d_fnstart(3, dev, "(umc_dev %p)\n", umc); | ||
99 | device_unregister(&umc->dev); | 91 | device_unregister(&umc->dev); |
100 | release_resource(&umc->resource); | 92 | release_resource(&umc->resource); |
101 | d_fnend(3, dev, "(umc_dev %p) = void\n", umc); | ||
102 | put_device(dev); | 93 | put_device(dev); |
103 | } | 94 | } |
104 | EXPORT_SYMBOL_GPL(umc_device_unregister); | 95 | EXPORT_SYMBOL_GPL(umc_device_unregister); |
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c index 6d232c35d07d..4a42993700c1 100644 --- a/drivers/uwb/uwb-debug.c +++ b/drivers/uwb/uwb-debug.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 2005-2006 Intel Corporation | 5 | * Copyright (C) 2005-2006 Intel Corporation |
6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | 6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> |
7 | * Copyright (C) 2008 Cambridge Silicon Radio Ltd. | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License version | 10 | * modify it under the terms of the GNU General Public License version |
@@ -33,31 +34,9 @@ | |||
33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
34 | 35 | ||
35 | #include <linux/uwb/debug-cmd.h> | 36 | #include <linux/uwb/debug-cmd.h> |
36 | #define D_LOCAL 0 | ||
37 | #include <linux/uwb/debug.h> | ||
38 | 37 | ||
39 | #include "uwb-internal.h" | 38 | #include "uwb-internal.h" |
40 | 39 | ||
41 | void dump_bytes(struct device *dev, const void *_buf, size_t rsize) | ||
42 | { | ||
43 | const char *buf = _buf; | ||
44 | char line[32]; | ||
45 | size_t offset = 0; | ||
46 | int cnt, cnt2; | ||
47 | for (cnt = 0; cnt < rsize; cnt += 8) { | ||
48 | size_t rtop = rsize - cnt < 8 ? rsize - cnt : 8; | ||
49 | for (offset = cnt2 = 0; cnt2 < rtop; cnt2++) { | ||
50 | offset += scnprintf(line + offset, sizeof(line) - offset, | ||
51 | "%02x ", buf[cnt + cnt2] & 0xff); | ||
52 | } | ||
53 | if (dev) | ||
54 | dev_info(dev, "%s\n", line); | ||
55 | else | ||
56 | printk(KERN_INFO "%s\n", line); | ||
57 | } | ||
58 | } | ||
59 | EXPORT_SYMBOL_GPL(dump_bytes); | ||
60 | |||
61 | /* | 40 | /* |
62 | * Debug interface | 41 | * Debug interface |
63 | * | 42 | * |
@@ -84,26 +63,23 @@ struct uwb_dbg { | |||
84 | struct dentry *reservations_f; | 63 | struct dentry *reservations_f; |
85 | struct dentry *accept_f; | 64 | struct dentry *accept_f; |
86 | struct dentry *drp_avail_f; | 65 | struct dentry *drp_avail_f; |
66 | spinlock_t list_lock; | ||
87 | }; | 67 | }; |
88 | 68 | ||
89 | static struct dentry *root_dir; | 69 | static struct dentry *root_dir; |
90 | 70 | ||
91 | static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) | 71 | static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) |
92 | { | 72 | { |
93 | struct uwb_rc *rc = rsv->rc; | 73 | struct uwb_dbg *dbg = rsv->pal_priv; |
94 | struct device *dev = &rc->uwb_dev.dev; | ||
95 | struct uwb_dev_addr devaddr; | ||
96 | char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; | ||
97 | |||
98 | uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); | ||
99 | if (rsv->target.type == UWB_RSV_TARGET_DEV) | ||
100 | devaddr = rsv->target.dev->dev_addr; | ||
101 | else | ||
102 | devaddr = rsv->target.devaddr; | ||
103 | uwb_dev_addr_print(target, sizeof(target), &devaddr); | ||
104 | 74 | ||
105 | dev_dbg(dev, "debug: rsv %s -> %s: %s\n", | 75 | uwb_rsv_dump("debug", rsv); |
106 | owner, target, uwb_rsv_state_str(rsv->state)); | 76 | |
77 | if (rsv->state == UWB_RSV_STATE_NONE) { | ||
78 | spin_lock(&dbg->list_lock); | ||
79 | list_del(&rsv->pal_node); | ||
80 | spin_unlock(&dbg->list_lock); | ||
81 | uwb_rsv_destroy(rsv); | ||
82 | } | ||
107 | } | 83 | } |
108 | 84 | ||
109 | static int cmd_rsv_establish(struct uwb_rc *rc, | 85 | static int cmd_rsv_establish(struct uwb_rc *rc, |
@@ -119,26 +95,27 @@ static int cmd_rsv_establish(struct uwb_rc *rc, | |||
119 | if (target == NULL) | 95 | if (target == NULL) |
120 | return -ENODEV; | 96 | return -ENODEV; |
121 | 97 | ||
122 | rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, NULL); | 98 | rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, rc->dbg); |
123 | if (rsv == NULL) { | 99 | if (rsv == NULL) { |
124 | uwb_dev_put(target); | 100 | uwb_dev_put(target); |
125 | return -ENOMEM; | 101 | return -ENOMEM; |
126 | } | 102 | } |
127 | 103 | ||
128 | rsv->owner = &rc->uwb_dev; | 104 | rsv->target.type = UWB_RSV_TARGET_DEV; |
129 | rsv->target.type = UWB_RSV_TARGET_DEV; | 105 | rsv->target.dev = target; |
130 | rsv->target.dev = target; | 106 | rsv->type = cmd->type; |
131 | rsv->type = cmd->type; | 107 | rsv->max_mas = cmd->max_mas; |
132 | rsv->max_mas = cmd->max_mas; | 108 | rsv->min_mas = cmd->min_mas; |
133 | rsv->min_mas = cmd->min_mas; | 109 | rsv->max_interval = cmd->max_interval; |
134 | rsv->sparsity = cmd->sparsity; | ||
135 | 110 | ||
136 | ret = uwb_rsv_establish(rsv); | 111 | ret = uwb_rsv_establish(rsv); |
137 | if (ret) | 112 | if (ret) |
138 | uwb_rsv_destroy(rsv); | 113 | uwb_rsv_destroy(rsv); |
139 | else | 114 | else { |
115 | spin_lock(&(rc->dbg)->list_lock); | ||
140 | list_add_tail(&rsv->pal_node, &rc->dbg->rsvs); | 116 | list_add_tail(&rsv->pal_node, &rc->dbg->rsvs); |
141 | 117 | spin_unlock(&(rc->dbg)->list_lock); | |
118 | } | ||
142 | return ret; | 119 | return ret; |
143 | } | 120 | } |
144 | 121 | ||
@@ -148,21 +125,40 @@ static int cmd_rsv_terminate(struct uwb_rc *rc, | |||
148 | struct uwb_rsv *rsv, *found = NULL; | 125 | struct uwb_rsv *rsv, *found = NULL; |
149 | int i = 0; | 126 | int i = 0; |
150 | 127 | ||
128 | spin_lock(&(rc->dbg)->list_lock); | ||
129 | |||
151 | list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) { | 130 | list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) { |
152 | if (i == cmd->index) { | 131 | if (i == cmd->index) { |
153 | found = rsv; | 132 | found = rsv; |
133 | uwb_rsv_get(found); | ||
154 | break; | 134 | break; |
155 | } | 135 | } |
136 | i++; | ||
156 | } | 137 | } |
138 | |||
139 | spin_unlock(&(rc->dbg)->list_lock); | ||
140 | |||
157 | if (!found) | 141 | if (!found) |
158 | return -EINVAL; | 142 | return -EINVAL; |
159 | 143 | ||
160 | list_del(&found->pal_node); | ||
161 | uwb_rsv_terminate(found); | 144 | uwb_rsv_terminate(found); |
145 | uwb_rsv_put(found); | ||
162 | 146 | ||
163 | return 0; | 147 | return 0; |
164 | } | 148 | } |
165 | 149 | ||
150 | static int cmd_ie_add(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_add) | ||
151 | { | ||
152 | return uwb_rc_ie_add(rc, | ||
153 | (const struct uwb_ie_hdr *) ie_to_add->data, | ||
154 | ie_to_add->len); | ||
155 | } | ||
156 | |||
157 | static int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm) | ||
158 | { | ||
159 | return uwb_rc_ie_rm(rc, ie_to_rm->data[0]); | ||
160 | } | ||
161 | |||
166 | static int command_open(struct inode *inode, struct file *file) | 162 | static int command_open(struct inode *inode, struct file *file) |
167 | { | 163 | { |
168 | file->private_data = inode->i_private; | 164 | file->private_data = inode->i_private; |
@@ -175,8 +171,8 @@ static ssize_t command_write(struct file *file, const char __user *buf, | |||
175 | { | 171 | { |
176 | struct uwb_rc *rc = file->private_data; | 172 | struct uwb_rc *rc = file->private_data; |
177 | struct uwb_dbg_cmd cmd; | 173 | struct uwb_dbg_cmd cmd; |
178 | int ret; | 174 | int ret = 0; |
179 | 175 | ||
180 | if (len != sizeof(struct uwb_dbg_cmd)) | 176 | if (len != sizeof(struct uwb_dbg_cmd)) |
181 | return -EINVAL; | 177 | return -EINVAL; |
182 | 178 | ||
@@ -190,6 +186,18 @@ static ssize_t command_write(struct file *file, const char __user *buf, | |||
190 | case UWB_DBG_CMD_RSV_TERMINATE: | 186 | case UWB_DBG_CMD_RSV_TERMINATE: |
191 | ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); | 187 | ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); |
192 | break; | 188 | break; |
189 | case UWB_DBG_CMD_IE_ADD: | ||
190 | ret = cmd_ie_add(rc, &cmd.ie_add); | ||
191 | break; | ||
192 | case UWB_DBG_CMD_IE_RM: | ||
193 | ret = cmd_ie_rm(rc, &cmd.ie_rm); | ||
194 | break; | ||
195 | case UWB_DBG_CMD_RADIO_START: | ||
196 | ret = uwb_radio_start(&rc->dbg->pal); | ||
197 | break; | ||
198 | case UWB_DBG_CMD_RADIO_STOP: | ||
199 | uwb_radio_stop(&rc->dbg->pal); | ||
200 | break; | ||
193 | default: | 201 | default: |
194 | return -EINVAL; | 202 | return -EINVAL; |
195 | } | 203 | } |
@@ -283,12 +291,26 @@ static struct file_operations drp_avail_fops = { | |||
283 | .owner = THIS_MODULE, | 291 | .owner = THIS_MODULE, |
284 | }; | 292 | }; |
285 | 293 | ||
286 | static void uwb_dbg_new_rsv(struct uwb_rsv *rsv) | 294 | static void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel) |
295 | { | ||
296 | struct device *dev = &pal->rc->uwb_dev.dev; | ||
297 | |||
298 | if (channel > 0) | ||
299 | dev_info(dev, "debug: channel %d started\n", channel); | ||
300 | else | ||
301 | dev_info(dev, "debug: channel stopped\n"); | ||
302 | } | ||
303 | |||
304 | static void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv) | ||
287 | { | 305 | { |
288 | struct uwb_rc *rc = rsv->rc; | 306 | struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal); |
289 | 307 | ||
290 | if (rc->dbg->accept) | 308 | if (dbg->accept) { |
291 | uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL); | 309 | spin_lock(&dbg->list_lock); |
310 | list_add_tail(&rsv->pal_node, &dbg->rsvs); | ||
311 | spin_unlock(&dbg->list_lock); | ||
312 | uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, dbg); | ||
313 | } | ||
292 | } | 314 | } |
293 | 315 | ||
294 | /** | 316 | /** |
@@ -302,10 +324,14 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) | |||
302 | return; | 324 | return; |
303 | 325 | ||
304 | INIT_LIST_HEAD(&rc->dbg->rsvs); | 326 | INIT_LIST_HEAD(&rc->dbg->rsvs); |
327 | spin_lock_init(&(rc->dbg)->list_lock); | ||
305 | 328 | ||
306 | uwb_pal_init(&rc->dbg->pal); | 329 | uwb_pal_init(&rc->dbg->pal); |
330 | rc->dbg->pal.rc = rc; | ||
331 | rc->dbg->pal.channel_changed = uwb_dbg_channel_changed; | ||
307 | rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; | 332 | rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; |
308 | uwb_pal_register(rc, &rc->dbg->pal); | 333 | uwb_pal_register(&rc->dbg->pal); |
334 | |||
309 | if (root_dir) { | 335 | if (root_dir) { |
310 | rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), | 336 | rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), |
311 | root_dir); | 337 | root_dir); |
@@ -325,7 +351,7 @@ void uwb_dbg_add_rc(struct uwb_rc *rc) | |||
325 | } | 351 | } |
326 | 352 | ||
327 | /** | 353 | /** |
328 | * uwb_dbg_add_rc - remove a radio controller's debug interface | 354 | * uwb_dbg_del_rc - remove a radio controller's debug interface |
329 | * @rc: the radio controller | 355 | * @rc: the radio controller |
330 | */ | 356 | */ |
331 | void uwb_dbg_del_rc(struct uwb_rc *rc) | 357 | void uwb_dbg_del_rc(struct uwb_rc *rc) |
@@ -336,10 +362,10 @@ void uwb_dbg_del_rc(struct uwb_rc *rc) | |||
336 | return; | 362 | return; |
337 | 363 | ||
338 | list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { | 364 | list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { |
339 | uwb_rsv_destroy(rsv); | 365 | uwb_rsv_terminate(rsv); |
340 | } | 366 | } |
341 | 367 | ||
342 | uwb_pal_unregister(rc, &rc->dbg->pal); | 368 | uwb_pal_unregister(&rc->dbg->pal); |
343 | 369 | ||
344 | if (root_dir) { | 370 | if (root_dir) { |
345 | debugfs_remove(rc->dbg->drp_avail_f); | 371 | debugfs_remove(rc->dbg->drp_avail_f); |
@@ -365,3 +391,16 @@ void uwb_dbg_exit(void) | |||
365 | { | 391 | { |
366 | debugfs_remove(root_dir); | 392 | debugfs_remove(root_dir); |
367 | } | 393 | } |
394 | |||
395 | /** | ||
396 | * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL | ||
397 | * @pal: The PAL. | ||
398 | */ | ||
399 | struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal) | ||
400 | { | ||
401 | struct uwb_rc *rc = pal->rc; | ||
402 | |||
403 | if (root_dir && rc->dbg && rc->dbg->root_d && pal->name) | ||
404 | return debugfs_create_dir(pal->name, rc->dbg->root_d); | ||
405 | return NULL; | ||
406 | } | ||
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 2ad307d12961..d5bcfc1c227a 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
@@ -66,14 +66,14 @@ extern int uwb_rc_scan(struct uwb_rc *rc, | |||
66 | unsigned channel, enum uwb_scan_type type, | 66 | unsigned channel, enum uwb_scan_type type, |
67 | unsigned bpst_offset); | 67 | unsigned bpst_offset); |
68 | extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); | 68 | extern int uwb_rc_send_all_drp_ie(struct uwb_rc *rc); |
69 | extern ssize_t uwb_rc_print_IEs(struct uwb_rc *rc, char *, size_t); | 69 | |
70 | extern void uwb_rc_ie_init(struct uwb_rc *); | 70 | void uwb_rc_ie_init(struct uwb_rc *); |
71 | extern void uwb_rc_ie_init(struct uwb_rc *); | 71 | int uwb_rc_ie_setup(struct uwb_rc *); |
72 | extern ssize_t uwb_rc_ie_setup(struct uwb_rc *); | 72 | void uwb_rc_ie_release(struct uwb_rc *); |
73 | extern void uwb_rc_ie_release(struct uwb_rc *); | 73 | int uwb_ie_dump_hex(const struct uwb_ie_hdr *ies, size_t len, |
74 | extern int uwb_rc_ie_add(struct uwb_rc *, | 74 | char *buf, size_t size); |
75 | const struct uwb_ie_hdr *, size_t); | 75 | int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); |
76 | extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); | 76 | |
77 | 77 | ||
78 | extern const char *uwb_rc_strerror(unsigned code); | 78 | extern const char *uwb_rc_strerror(unsigned code); |
79 | 79 | ||
@@ -92,6 +92,12 @@ extern const char *uwb_rc_strerror(unsigned code); | |||
92 | 92 | ||
93 | struct uwb_rc_neh; | 93 | struct uwb_rc_neh; |
94 | 94 | ||
95 | extern int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, | ||
96 | struct uwb_rccb *cmd, size_t cmd_size, | ||
97 | u8 expected_type, u16 expected_event, | ||
98 | uwb_rc_cmd_cb_f cb, void *arg); | ||
99 | |||
100 | |||
95 | void uwb_rc_neh_create(struct uwb_rc *rc); | 101 | void uwb_rc_neh_create(struct uwb_rc *rc); |
96 | void uwb_rc_neh_destroy(struct uwb_rc *rc); | 102 | void uwb_rc_neh_destroy(struct uwb_rc *rc); |
97 | 103 | ||
@@ -106,7 +112,69 @@ void uwb_rc_neh_put(struct uwb_rc_neh *neh); | |||
106 | extern int uwb_est_create(void); | 112 | extern int uwb_est_create(void); |
107 | extern void uwb_est_destroy(void); | 113 | extern void uwb_est_destroy(void); |
108 | 114 | ||
115 | /* | ||
116 | * UWB conflicting alien reservations | ||
117 | */ | ||
118 | struct uwb_cnflt_alien { | ||
119 | struct uwb_rc *rc; | ||
120 | struct list_head rc_node; | ||
121 | struct uwb_mas_bm mas; | ||
122 | struct timer_list timer; | ||
123 | struct work_struct cnflt_update_work; | ||
124 | }; | ||
125 | |||
126 | enum uwb_uwb_rsv_alloc_result { | ||
127 | UWB_RSV_ALLOC_FOUND = 0, | ||
128 | UWB_RSV_ALLOC_NOT_FOUND, | ||
129 | }; | ||
130 | |||
131 | enum uwb_rsv_mas_status { | ||
132 | UWB_RSV_MAS_NOT_AVAIL = 1, | ||
133 | UWB_RSV_MAS_SAFE, | ||
134 | UWB_RSV_MAS_UNSAFE, | ||
135 | }; | ||
136 | |||
137 | struct uwb_rsv_col_set_info { | ||
138 | unsigned char start_col; | ||
139 | unsigned char interval; | ||
140 | unsigned char safe_mas_per_col; | ||
141 | unsigned char unsafe_mas_per_col; | ||
142 | }; | ||
143 | |||
144 | struct uwb_rsv_col_info { | ||
145 | unsigned char max_avail_safe; | ||
146 | unsigned char max_avail_unsafe; | ||
147 | unsigned char highest_mas[UWB_MAS_PER_ZONE]; | ||
148 | struct uwb_rsv_col_set_info csi; | ||
149 | }; | ||
150 | |||
151 | struct uwb_rsv_row_info { | ||
152 | unsigned char avail[UWB_MAS_PER_ZONE]; | ||
153 | unsigned char free_rows; | ||
154 | unsigned char used_rows; | ||
155 | }; | ||
156 | |||
157 | /* | ||
158 | * UWB find allocation | ||
159 | */ | ||
160 | struct uwb_rsv_alloc_info { | ||
161 | unsigned char bm[UWB_MAS_PER_ZONE * UWB_NUM_ZONES]; | ||
162 | struct uwb_rsv_col_info ci[UWB_NUM_ZONES]; | ||
163 | struct uwb_rsv_row_info ri; | ||
164 | struct uwb_mas_bm *not_available; | ||
165 | struct uwb_mas_bm *result; | ||
166 | int min_mas; | ||
167 | int max_mas; | ||
168 | int max_interval; | ||
169 | int total_allocated_mases; | ||
170 | int safe_allocated_mases; | ||
171 | int unsafe_allocated_mases; | ||
172 | int interval; | ||
173 | }; | ||
109 | 174 | ||
175 | int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *available, | ||
176 | struct uwb_mas_bm *result); | ||
177 | void uwb_rsv_handle_drp_avail_change(struct uwb_rc *rc); | ||
110 | /* | 178 | /* |
111 | * UWB Events & management daemon | 179 | * UWB Events & management daemon |
112 | */ | 180 | */ |
@@ -160,13 +228,14 @@ struct uwb_event { | |||
160 | }; | 228 | }; |
161 | }; | 229 | }; |
162 | 230 | ||
163 | extern void uwbd_start(void); | 231 | extern void uwbd_start(struct uwb_rc *rc); |
164 | extern void uwbd_stop(void); | 232 | extern void uwbd_stop(struct uwb_rc *rc); |
165 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); | 233 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); |
166 | extern void uwbd_event_queue(struct uwb_event *); | 234 | extern void uwbd_event_queue(struct uwb_event *); |
167 | void uwbd_flush(struct uwb_rc *rc); | 235 | void uwbd_flush(struct uwb_rc *rc); |
168 | 236 | ||
169 | /* UWB event handlers */ | 237 | /* UWB event handlers */ |
238 | extern int uwbd_evt_handle_rc_ie_rcv(struct uwb_event *); | ||
170 | extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); | 239 | extern int uwbd_evt_handle_rc_beacon(struct uwb_event *); |
171 | extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); | 240 | extern int uwbd_evt_handle_rc_beacon_size(struct uwb_event *); |
172 | extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); | 241 | extern int uwbd_evt_handle_rc_bpoie_change(struct uwb_event *); |
@@ -193,15 +262,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); | |||
193 | 262 | ||
194 | extern unsigned long beacon_timeout_ms; | 263 | extern unsigned long beacon_timeout_ms; |
195 | 264 | ||
196 | /** Beacon cache list */ | ||
197 | struct uwb_beca { | ||
198 | struct list_head list; | ||
199 | size_t entries; | ||
200 | struct mutex mutex; | ||
201 | }; | ||
202 | |||
203 | extern struct uwb_beca uwb_beca; | ||
204 | |||
205 | /** | 265 | /** |
206 | * Beacon cache entry | 266 | * Beacon cache entry |
207 | * | 267 | * |
@@ -228,9 +288,6 @@ struct uwb_beca_e { | |||
228 | struct uwb_beacon_frame; | 288 | struct uwb_beacon_frame; |
229 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, | 289 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, |
230 | char *, size_t); | 290 | char *, size_t); |
231 | extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, | ||
232 | struct uwb_beacon_frame *, | ||
233 | unsigned long); | ||
234 | 291 | ||
235 | extern void uwb_bce_kfree(struct kref *_bce); | 292 | extern void uwb_bce_kfree(struct kref *_bce); |
236 | static inline void uwb_bce_get(struct uwb_beca_e *bce) | 293 | static inline void uwb_bce_get(struct uwb_beca_e *bce) |
@@ -241,14 +298,19 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce) | |||
241 | { | 298 | { |
242 | kref_put(&bce->refcnt, uwb_bce_kfree); | 299 | kref_put(&bce->refcnt, uwb_bce_kfree); |
243 | } | 300 | } |
244 | extern void uwb_beca_purge(void); | 301 | extern void uwb_beca_purge(struct uwb_rc *rc); |
245 | extern void uwb_beca_release(void); | 302 | extern void uwb_beca_release(struct uwb_rc *rc); |
246 | 303 | ||
247 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | 304 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, |
248 | const struct uwb_dev_addr *devaddr); | 305 | const struct uwb_dev_addr *devaddr); |
249 | struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | 306 | struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, |
250 | const struct uwb_mac_addr *macaddr); | 307 | const struct uwb_mac_addr *macaddr); |
251 | 308 | ||
309 | int uwb_radio_setup(struct uwb_rc *rc); | ||
310 | void uwb_radio_reset_state(struct uwb_rc *rc); | ||
311 | void uwb_radio_shutdown(struct uwb_rc *rc); | ||
312 | int uwb_radio_force_channel(struct uwb_rc *rc, int channel); | ||
313 | |||
252 | /* -- UWB Sysfs representation */ | 314 | /* -- UWB Sysfs representation */ |
253 | extern struct class uwb_rc_class; | 315 | extern struct class uwb_rc_class; |
254 | extern struct device_attribute dev_attr_mac_address; | 316 | extern struct device_attribute dev_attr_mac_address; |
@@ -259,18 +321,29 @@ extern struct device_attribute dev_attr_scan; | |||
259 | void uwb_rsv_init(struct uwb_rc *rc); | 321 | void uwb_rsv_init(struct uwb_rc *rc); |
260 | int uwb_rsv_setup(struct uwb_rc *rc); | 322 | int uwb_rsv_setup(struct uwb_rc *rc); |
261 | void uwb_rsv_cleanup(struct uwb_rc *rc); | 323 | void uwb_rsv_cleanup(struct uwb_rc *rc); |
324 | void uwb_rsv_remove_all(struct uwb_rc *rc); | ||
325 | void uwb_rsv_get(struct uwb_rsv *rsv); | ||
326 | void uwb_rsv_put(struct uwb_rsv *rsv); | ||
327 | bool uwb_rsv_has_two_drp_ies(struct uwb_rsv *rsv); | ||
328 | void uwb_rsv_dump(char *text, struct uwb_rsv *rsv); | ||
329 | int uwb_rsv_try_move(struct uwb_rsv *rsv, struct uwb_mas_bm *available); | ||
330 | void uwb_rsv_backoff_win_timer(unsigned long arg); | ||
331 | void uwb_rsv_backoff_win_increment(struct uwb_rc *rc); | ||
332 | int uwb_rsv_status(struct uwb_rsv *rsv); | ||
333 | int uwb_rsv_companion_status(struct uwb_rsv *rsv); | ||
262 | 334 | ||
263 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); | 335 | void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); |
264 | void uwb_rsv_remove(struct uwb_rsv *rsv); | 336 | void uwb_rsv_remove(struct uwb_rsv *rsv); |
265 | struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src, | 337 | struct uwb_rsv *uwb_rsv_find(struct uwb_rc *rc, struct uwb_dev *src, |
266 | struct uwb_ie_drp *drp_ie); | 338 | struct uwb_ie_drp *drp_ie); |
267 | void uwb_rsv_sched_update(struct uwb_rc *rc); | 339 | void uwb_rsv_sched_update(struct uwb_rc *rc); |
340 | void uwb_rsv_queue_update(struct uwb_rc *rc); | ||
268 | 341 | ||
269 | void uwb_drp_handle_timeout(struct uwb_rsv *rsv); | ||
270 | int uwb_drp_ie_update(struct uwb_rsv *rsv); | 342 | int uwb_drp_ie_update(struct uwb_rsv *rsv); |
271 | void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie); | 343 | void uwb_drp_ie_to_bm(struct uwb_mas_bm *bm, const struct uwb_ie_drp *drp_ie); |
272 | 344 | ||
273 | void uwb_drp_avail_init(struct uwb_rc *rc); | 345 | void uwb_drp_avail_init(struct uwb_rc *rc); |
346 | void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail); | ||
274 | int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas); | 347 | int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas); |
275 | void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas); | 348 | void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas); |
276 | void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas); | 349 | void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas); |
@@ -289,8 +362,7 @@ void uwb_dbg_init(void); | |||
289 | void uwb_dbg_exit(void); | 362 | void uwb_dbg_exit(void); |
290 | void uwb_dbg_add_rc(struct uwb_rc *rc); | 363 | void uwb_dbg_add_rc(struct uwb_rc *rc); |
291 | void uwb_dbg_del_rc(struct uwb_rc *rc); | 364 | void uwb_dbg_del_rc(struct uwb_rc *rc); |
292 | 365 | struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal); | |
293 | /* Workarounds for version specific stuff */ | ||
294 | 366 | ||
295 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) | 367 | static inline void uwb_dev_lock(struct uwb_dev *uwb_dev) |
296 | { | 368 | { |
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 78908416e42c..57bd6bfef37e 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c | |||
@@ -68,17 +68,13 @@ | |||
68 | * | 68 | * |
69 | * Handler functions are called normally uwbd_evt_handle_*(). | 69 | * Handler functions are called normally uwbd_evt_handle_*(). |
70 | */ | 70 | */ |
71 | |||
72 | #include <linux/kthread.h> | 71 | #include <linux/kthread.h> |
73 | #include <linux/module.h> | 72 | #include <linux/module.h> |
74 | #include <linux/freezer.h> | 73 | #include <linux/freezer.h> |
75 | #include "uwb-internal.h" | ||
76 | |||
77 | #define D_LOCAL 1 | ||
78 | #include <linux/uwb/debug.h> | ||
79 | 74 | ||
75 | #include "uwb-internal.h" | ||
80 | 76 | ||
81 | /** | 77 | /* |
82 | * UWBD Event handler function signature | 78 | * UWBD Event handler function signature |
83 | * | 79 | * |
84 | * Return !0 if the event needs not to be freed (ie the handler | 80 | * Return !0 if the event needs not to be freed (ie the handler |
@@ -101,9 +97,12 @@ struct uwbd_event { | |||
101 | const char *name; | 97 | const char *name; |
102 | }; | 98 | }; |
103 | 99 | ||
104 | /** Table of handlers for and properties of the UWBD Radio Control Events */ | 100 | /* Table of handlers for and properties of the UWBD Radio Control Events */ |
105 | static | 101 | static struct uwbd_event uwbd_urc_events[] = { |
106 | struct uwbd_event uwbd_events[] = { | 102 | [UWB_RC_EVT_IE_RCV] = { |
103 | .handler = uwbd_evt_handle_rc_ie_rcv, | ||
104 | .name = "IE_RECEIVED" | ||
105 | }, | ||
107 | [UWB_RC_EVT_BEACON] = { | 106 | [UWB_RC_EVT_BEACON] = { |
108 | .handler = uwbd_evt_handle_rc_beacon, | 107 | .handler = uwbd_evt_handle_rc_beacon, |
109 | .name = "BEACON_RECEIVED" | 108 | .name = "BEACON_RECEIVED" |
@@ -142,23 +141,15 @@ struct uwbd_evt_type_handler { | |||
142 | size_t size; | 141 | size_t size; |
143 | }; | 142 | }; |
144 | 143 | ||
145 | #define UWBD_EVT_TYPE_HANDLER(n,a) { \ | 144 | /* Table of handlers for each UWBD Event type. */ |
146 | .name = (n), \ | 145 | static struct uwbd_evt_type_handler uwbd_urc_evt_type_handlers[] = { |
147 | .uwbd_events = (a), \ | 146 | [UWB_RC_CET_GENERAL] = { |
148 | .size = sizeof(a)/sizeof((a)[0]) \ | 147 | .name = "URC", |
149 | } | 148 | .uwbd_events = uwbd_urc_events, |
150 | 149 | .size = ARRAY_SIZE(uwbd_urc_events), | |
151 | 150 | }, | |
152 | /** Table of handlers for each UWBD Event type. */ | ||
153 | static | ||
154 | struct uwbd_evt_type_handler uwbd_evt_type_handlers[] = { | ||
155 | [UWB_RC_CET_GENERAL] = UWBD_EVT_TYPE_HANDLER("RC", uwbd_events) | ||
156 | }; | 151 | }; |
157 | 152 | ||
158 | static const | ||
159 | size_t uwbd_evt_type_handlers_len = | ||
160 | sizeof(uwbd_evt_type_handlers) / sizeof(uwbd_evt_type_handlers[0]); | ||
161 | |||
162 | static const struct uwbd_event uwbd_message_handlers[] = { | 153 | static const struct uwbd_event uwbd_message_handlers[] = { |
163 | [UWB_EVT_MSG_RESET] = { | 154 | [UWB_EVT_MSG_RESET] = { |
164 | .handler = uwbd_msg_handle_reset, | 155 | .handler = uwbd_msg_handle_reset, |
@@ -166,9 +157,7 @@ static const struct uwbd_event uwbd_message_handlers[] = { | |||
166 | }, | 157 | }, |
167 | }; | 158 | }; |
168 | 159 | ||
169 | static DEFINE_MUTEX(uwbd_event_mutex); | 160 | /* |
170 | |||
171 | /** | ||
172 | * Handle an URC event passed to the UWB Daemon | 161 | * Handle an URC event passed to the UWB Daemon |
173 | * | 162 | * |
174 | * @evt: the event to handle | 163 | * @evt: the event to handle |
@@ -188,6 +177,7 @@ static DEFINE_MUTEX(uwbd_event_mutex); | |||
188 | static | 177 | static |
189 | int uwbd_event_handle_urc(struct uwb_event *evt) | 178 | int uwbd_event_handle_urc(struct uwb_event *evt) |
190 | { | 179 | { |
180 | int result = -EINVAL; | ||
191 | struct uwbd_evt_type_handler *type_table; | 181 | struct uwbd_evt_type_handler *type_table; |
192 | uwbd_evt_handler_f handler; | 182 | uwbd_evt_handler_f handler; |
193 | u8 type, context; | 183 | u8 type, context; |
@@ -197,26 +187,24 @@ int uwbd_event_handle_urc(struct uwb_event *evt) | |||
197 | event = le16_to_cpu(evt->notif.rceb->wEvent); | 187 | event = le16_to_cpu(evt->notif.rceb->wEvent); |
198 | context = evt->notif.rceb->bEventContext; | 188 | context = evt->notif.rceb->bEventContext; |
199 | 189 | ||
200 | if (type > uwbd_evt_type_handlers_len) { | 190 | if (type > ARRAY_SIZE(uwbd_urc_evt_type_handlers)) |
201 | printk(KERN_ERR "UWBD: event type %u: unknown (too high)\n", type); | 191 | goto out; |
202 | return -EINVAL; | 192 | type_table = &uwbd_urc_evt_type_handlers[type]; |
203 | } | 193 | if (type_table->uwbd_events == NULL) |
204 | type_table = &uwbd_evt_type_handlers[type]; | 194 | goto out; |
205 | if (type_table->uwbd_events == NULL) { | 195 | if (event > type_table->size) |
206 | printk(KERN_ERR "UWBD: event type %u: unknown\n", type); | 196 | goto out; |
207 | return -EINVAL; | ||
208 | } | ||
209 | if (event > type_table->size) { | ||
210 | printk(KERN_ERR "UWBD: event %s[%u]: unknown (too high)\n", | ||
211 | type_table->name, event); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | handler = type_table->uwbd_events[event].handler; | 197 | handler = type_table->uwbd_events[event].handler; |
215 | if (handler == NULL) { | 198 | if (handler == NULL) |
216 | printk(KERN_ERR "UWBD: event %s[%u]: unknown\n", type_table->name, event); | 199 | goto out; |
217 | return -EINVAL; | 200 | |
218 | } | 201 | result = (*handler)(evt); |
219 | return (*handler)(evt); | 202 | out: |
203 | if (result < 0) | ||
204 | dev_err(&evt->rc->uwb_dev.dev, | ||
205 | "UWBD: event 0x%02x/%04x/%02x, handling failed: %d\n", | ||
206 | type, event, context, result); | ||
207 | return result; | ||
220 | } | 208 | } |
221 | 209 | ||
222 | static void uwbd_event_handle_message(struct uwb_event *evt) | 210 | static void uwbd_event_handle_message(struct uwb_event *evt) |
@@ -231,19 +219,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt) | |||
231 | return; | 219 | return; |
232 | } | 220 | } |
233 | 221 | ||
234 | /* If this is a reset event we need to drop the | ||
235 | * uwbd_event_mutex or it deadlocks when the reset handler | ||
236 | * attempts to flush the uwbd events. */ | ||
237 | if (evt->message == UWB_EVT_MSG_RESET) | ||
238 | mutex_unlock(&uwbd_event_mutex); | ||
239 | |||
240 | result = uwbd_message_handlers[evt->message].handler(evt); | 222 | result = uwbd_message_handlers[evt->message].handler(evt); |
241 | if (result < 0) | 223 | if (result < 0) |
242 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", | 224 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", |
243 | uwbd_message_handlers[evt->message].name, result); | 225 | uwbd_message_handlers[evt->message].name, result); |
244 | |||
245 | if (evt->message == UWB_EVT_MSG_RESET) | ||
246 | mutex_lock(&uwbd_event_mutex); | ||
247 | } | 226 | } |
248 | 227 | ||
249 | static void uwbd_event_handle(struct uwb_event *evt) | 228 | static void uwbd_event_handle(struct uwb_event *evt) |
@@ -271,20 +250,6 @@ static void uwbd_event_handle(struct uwb_event *evt) | |||
271 | 250 | ||
272 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ | 251 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ |
273 | } | 252 | } |
274 | /* The UWB Daemon */ | ||
275 | |||
276 | |||
277 | /** Daemon's PID: used to decide if we can queue or not */ | ||
278 | static int uwbd_pid; | ||
279 | /** Daemon's task struct for managing the kthread */ | ||
280 | static struct task_struct *uwbd_task; | ||
281 | /** Daemon's waitqueue for waiting for new events */ | ||
282 | static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); | ||
283 | /** Daemon's list of events; we queue/dequeue here */ | ||
284 | static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); | ||
285 | /** Daemon's list lock to protect concurent access */ | ||
286 | static DEFINE_SPINLOCK(uwbd_event_list_lock); | ||
287 | |||
288 | 253 | ||
289 | /** | 254 | /** |
290 | * UWB Daemon | 255 | * UWB Daemon |
@@ -298,65 +263,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock); | |||
298 | * FIXME: should change so we don't have a 1HZ timer all the time, but | 263 | * FIXME: should change so we don't have a 1HZ timer all the time, but |
299 | * only if there are devices. | 264 | * only if there are devices. |
300 | */ | 265 | */ |
301 | static int uwbd(void *unused) | 266 | static int uwbd(void *param) |
302 | { | 267 | { |
268 | struct uwb_rc *rc = param; | ||
303 | unsigned long flags; | 269 | unsigned long flags; |
304 | struct list_head list = LIST_HEAD_INIT(list); | 270 | struct uwb_event *evt; |
305 | struct uwb_event *evt, *nxt; | ||
306 | int should_stop = 0; | 271 | int should_stop = 0; |
272 | |||
307 | while (1) { | 273 | while (1) { |
308 | wait_event_interruptible_timeout( | 274 | wait_event_interruptible_timeout( |
309 | uwbd_wq, | 275 | rc->uwbd.wq, |
310 | !list_empty(&uwbd_event_list) | 276 | !list_empty(&rc->uwbd.event_list) |
311 | || (should_stop = kthread_should_stop()), | 277 | || (should_stop = kthread_should_stop()), |
312 | HZ); | 278 | HZ); |
313 | if (should_stop) | 279 | if (should_stop) |
314 | break; | 280 | break; |
315 | try_to_freeze(); | 281 | try_to_freeze(); |
316 | 282 | ||
317 | mutex_lock(&uwbd_event_mutex); | 283 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
318 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 284 | if (!list_empty(&rc->uwbd.event_list)) { |
319 | list_splice_init(&uwbd_event_list, &list); | 285 | evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); |
320 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
321 | list_for_each_entry_safe(evt, nxt, &list, list_node) { | ||
322 | list_del(&evt->list_node); | 286 | list_del(&evt->list_node); |
287 | } else | ||
288 | evt = NULL; | ||
289 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); | ||
290 | |||
291 | if (evt) { | ||
323 | uwbd_event_handle(evt); | 292 | uwbd_event_handle(evt); |
324 | kfree(evt); | 293 | kfree(evt); |
325 | } | 294 | } |
326 | mutex_unlock(&uwbd_event_mutex); | ||
327 | 295 | ||
328 | uwb_beca_purge(); /* Purge devices that left */ | 296 | uwb_beca_purge(rc); /* Purge devices that left */ |
329 | } | 297 | } |
330 | return 0; | 298 | return 0; |
331 | } | 299 | } |
332 | 300 | ||
333 | 301 | ||
334 | /** Start the UWB daemon */ | 302 | /** Start the UWB daemon */ |
335 | void uwbd_start(void) | 303 | void uwbd_start(struct uwb_rc *rc) |
336 | { | 304 | { |
337 | uwbd_task = kthread_run(uwbd, NULL, "uwbd"); | 305 | rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); |
338 | if (uwbd_task == NULL) | 306 | if (rc->uwbd.task == NULL) |
339 | printk(KERN_ERR "UWB: Cannot start management daemon; " | 307 | printk(KERN_ERR "UWB: Cannot start management daemon; " |
340 | "UWB won't work\n"); | 308 | "UWB won't work\n"); |
341 | else | 309 | else |
342 | uwbd_pid = uwbd_task->pid; | 310 | rc->uwbd.pid = rc->uwbd.task->pid; |
343 | } | 311 | } |
344 | 312 | ||
345 | /* Stop the UWB daemon and free any unprocessed events */ | 313 | /* Stop the UWB daemon and free any unprocessed events */ |
346 | void uwbd_stop(void) | 314 | void uwbd_stop(struct uwb_rc *rc) |
347 | { | 315 | { |
348 | unsigned long flags; | 316 | kthread_stop(rc->uwbd.task); |
349 | struct uwb_event *evt, *nxt; | 317 | uwbd_flush(rc); |
350 | kthread_stop(uwbd_task); | ||
351 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | ||
352 | uwbd_pid = 0; | ||
353 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
354 | if (evt->type == UWB_EVT_TYPE_NOTIF) | ||
355 | kfree(evt->notif.rceb); | ||
356 | kfree(evt); | ||
357 | } | ||
358 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
359 | uwb_beca_release(); | ||
360 | } | 318 | } |
361 | 319 | ||
362 | /* | 320 | /* |
@@ -373,18 +331,20 @@ void uwbd_stop(void) | |||
373 | */ | 331 | */ |
374 | void uwbd_event_queue(struct uwb_event *evt) | 332 | void uwbd_event_queue(struct uwb_event *evt) |
375 | { | 333 | { |
334 | struct uwb_rc *rc = evt->rc; | ||
376 | unsigned long flags; | 335 | unsigned long flags; |
377 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 336 | |
378 | if (uwbd_pid != 0) { | 337 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
379 | list_add(&evt->list_node, &uwbd_event_list); | 338 | if (rc->uwbd.pid != 0) { |
380 | wake_up_all(&uwbd_wq); | 339 | list_add(&evt->list_node, &rc->uwbd.event_list); |
340 | wake_up_all(&rc->uwbd.wq); | ||
381 | } else { | 341 | } else { |
382 | __uwb_rc_put(evt->rc); | 342 | __uwb_rc_put(evt->rc); |
383 | if (evt->type == UWB_EVT_TYPE_NOTIF) | 343 | if (evt->type == UWB_EVT_TYPE_NOTIF) |
384 | kfree(evt->notif.rceb); | 344 | kfree(evt->notif.rceb); |
385 | kfree(evt); | 345 | kfree(evt); |
386 | } | 346 | } |
387 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | 347 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); |
388 | return; | 348 | return; |
389 | } | 349 | } |
390 | 350 | ||
@@ -392,10 +352,8 @@ void uwbd_flush(struct uwb_rc *rc) | |||
392 | { | 352 | { |
393 | struct uwb_event *evt, *nxt; | 353 | struct uwb_event *evt, *nxt; |
394 | 354 | ||
395 | mutex_lock(&uwbd_event_mutex); | 355 | spin_lock_irq(&rc->uwbd.event_list_lock); |
396 | 356 | list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { | |
397 | spin_lock_irq(&uwbd_event_list_lock); | ||
398 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
399 | if (evt->rc == rc) { | 357 | if (evt->rc == rc) { |
400 | __uwb_rc_put(rc); | 358 | __uwb_rc_put(rc); |
401 | list_del(&evt->list_node); | 359 | list_del(&evt->list_node); |
@@ -404,7 +362,5 @@ void uwbd_flush(struct uwb_rc *rc) | |||
404 | kfree(evt); | 362 | kfree(evt); |
405 | } | 363 | } |
406 | } | 364 | } |
407 | spin_unlock_irq(&uwbd_event_list_lock); | 365 | spin_unlock_irq(&rc->uwbd.event_list_lock); |
408 | |||
409 | mutex_unlock(&uwbd_event_mutex); | ||
410 | } | 366 | } |
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c index 1711deadb114..19a1dd129212 100644 --- a/drivers/uwb/whc-rc.c +++ b/drivers/uwb/whc-rc.c | |||
@@ -39,7 +39,6 @@ | |||
39 | * them to the hw and transfer the replies/notifications back to the | 39 | * them to the hw and transfer the replies/notifications back to the |
40 | * UWB stack through the UWB daemon (UWBD). | 40 | * UWB stack through the UWB daemon (UWBD). |
41 | */ | 41 | */ |
42 | #include <linux/version.h> | ||
43 | #include <linux/init.h> | 42 | #include <linux/init.h> |
44 | #include <linux/module.h> | 43 | #include <linux/module.h> |
45 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
@@ -49,10 +48,8 @@ | |||
49 | #include <linux/uwb.h> | 48 | #include <linux/uwb.h> |
50 | #include <linux/uwb/whci.h> | 49 | #include <linux/uwb/whci.h> |
51 | #include <linux/uwb/umc.h> | 50 | #include <linux/uwb/umc.h> |
52 | #include "uwb-internal.h" | ||
53 | 51 | ||
54 | #define D_LOCAL 0 | 52 | #include "uwb-internal.h" |
55 | #include <linux/uwb/debug.h> | ||
56 | 53 | ||
57 | /** | 54 | /** |
58 | * Descriptor for an instance of the UWB Radio Control Driver that | 55 | * Descriptor for an instance of the UWB Radio Control Driver that |
@@ -98,13 +95,8 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, | |||
98 | struct device *dev = &whcrc->umc_dev->dev; | 95 | struct device *dev = &whcrc->umc_dev->dev; |
99 | u32 urccmd; | 96 | u32 urccmd; |
100 | 97 | ||
101 | d_fnstart(3, dev, "(%p, %p, %zu)\n", uwb_rc, cmd, cmd_size); | 98 | if (cmd_size >= 4096) |
102 | might_sleep(); | 99 | return -EINVAL; |
103 | |||
104 | if (cmd_size >= 4096) { | ||
105 | result = -E2BIG; | ||
106 | goto error; | ||
107 | } | ||
108 | 100 | ||
109 | /* | 101 | /* |
110 | * If the URC is halted, then the hardware has reset itself. | 102 | * If the URC is halted, then the hardware has reset itself. |
@@ -115,16 +107,14 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, | |||
115 | if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) { | 107 | if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) { |
116 | dev_err(dev, "requesting reset of halted radio controller\n"); | 108 | dev_err(dev, "requesting reset of halted radio controller\n"); |
117 | uwb_rc_reset_all(uwb_rc); | 109 | uwb_rc_reset_all(uwb_rc); |
118 | result = -EIO; | 110 | return -EIO; |
119 | goto error; | ||
120 | } | 111 | } |
121 | 112 | ||
122 | result = wait_event_timeout(whcrc->cmd_wq, | 113 | result = wait_event_timeout(whcrc->cmd_wq, |
123 | !(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2); | 114 | !(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2); |
124 | if (result == 0) { | 115 | if (result == 0) { |
125 | dev_err(dev, "device is not ready to execute commands\n"); | 116 | dev_err(dev, "device is not ready to execute commands\n"); |
126 | result = -ETIMEDOUT; | 117 | return -ETIMEDOUT; |
127 | goto error; | ||
128 | } | 118 | } |
129 | 119 | ||
130 | memmove(whcrc->cmd_buf, cmd, cmd_size); | 120 | memmove(whcrc->cmd_buf, cmd, cmd_size); |
@@ -137,10 +127,7 @@ static int whcrc_cmd(struct uwb_rc *uwb_rc, | |||
137 | whcrc->rc_base + URCCMD); | 127 | whcrc->rc_base + URCCMD); |
138 | spin_unlock(&whcrc->irq_lock); | 128 | spin_unlock(&whcrc->irq_lock); |
139 | 129 | ||
140 | error: | 130 | return 0; |
141 | d_fnend(3, dev, "(%p, %p, %zu) = %d\n", | ||
142 | uwb_rc, cmd, cmd_size, result); | ||
143 | return result; | ||
144 | } | 131 | } |
145 | 132 | ||
146 | static int whcrc_reset(struct uwb_rc *rc) | 133 | static int whcrc_reset(struct uwb_rc *rc) |
@@ -167,34 +154,25 @@ static int whcrc_reset(struct uwb_rc *rc) | |||
167 | static | 154 | static |
168 | void whcrc_enable_events(struct whcrc *whcrc) | 155 | void whcrc_enable_events(struct whcrc *whcrc) |
169 | { | 156 | { |
170 | struct device *dev = &whcrc->umc_dev->dev; | ||
171 | u32 urccmd; | 157 | u32 urccmd; |
172 | 158 | ||
173 | d_fnstart(4, dev, "(whcrc %p)\n", whcrc); | ||
174 | |||
175 | le_writeq(whcrc->evt_dma_buf, whcrc->rc_base + URCEVTADDR); | 159 | le_writeq(whcrc->evt_dma_buf, whcrc->rc_base + URCEVTADDR); |
176 | 160 | ||
177 | spin_lock(&whcrc->irq_lock); | 161 | spin_lock(&whcrc->irq_lock); |
178 | urccmd = le_readl(whcrc->rc_base + URCCMD) & ~URCCMD_ACTIVE; | 162 | urccmd = le_readl(whcrc->rc_base + URCCMD) & ~URCCMD_ACTIVE; |
179 | le_writel(urccmd | URCCMD_EARV, whcrc->rc_base + URCCMD); | 163 | le_writel(urccmd | URCCMD_EARV, whcrc->rc_base + URCCMD); |
180 | spin_unlock(&whcrc->irq_lock); | 164 | spin_unlock(&whcrc->irq_lock); |
181 | |||
182 | d_fnend(4, dev, "(whcrc %p) = void\n", whcrc); | ||
183 | } | 165 | } |
184 | 166 | ||
185 | static void whcrc_event_work(struct work_struct *work) | 167 | static void whcrc_event_work(struct work_struct *work) |
186 | { | 168 | { |
187 | struct whcrc *whcrc = container_of(work, struct whcrc, event_work); | 169 | struct whcrc *whcrc = container_of(work, struct whcrc, event_work); |
188 | struct device *dev = &whcrc->umc_dev->dev; | ||
189 | size_t size; | 170 | size_t size; |
190 | u64 urcevtaddr; | 171 | u64 urcevtaddr; |
191 | 172 | ||
192 | urcevtaddr = le_readq(whcrc->rc_base + URCEVTADDR); | 173 | urcevtaddr = le_readq(whcrc->rc_base + URCEVTADDR); |
193 | size = urcevtaddr & URCEVTADDR_OFFSET_MASK; | 174 | size = urcevtaddr & URCEVTADDR_OFFSET_MASK; |
194 | 175 | ||
195 | d_printf(3, dev, "received %zu octet event\n", size); | ||
196 | d_dump(4, dev, whcrc->evt_buf, size > 32 ? 32 : size); | ||
197 | |||
198 | uwb_rc_neh_grok(whcrc->uwb_rc, whcrc->evt_buf, size); | 176 | uwb_rc_neh_grok(whcrc->uwb_rc, whcrc->evt_buf, size); |
199 | whcrc_enable_events(whcrc); | 177 | whcrc_enable_events(whcrc); |
200 | } | 178 | } |
@@ -217,22 +195,15 @@ irqreturn_t whcrc_irq_cb(int irq, void *_whcrc) | |||
217 | return IRQ_NONE; | 195 | return IRQ_NONE; |
218 | le_writel(urcsts & URCSTS_INT_MASK, whcrc->rc_base + URCSTS); | 196 | le_writel(urcsts & URCSTS_INT_MASK, whcrc->rc_base + URCSTS); |
219 | 197 | ||
220 | d_printf(4, dev, "acked 0x%08x, urcsts 0x%08x\n", | ||
221 | le_readl(whcrc->rc_base + URCSTS), urcsts); | ||
222 | |||
223 | if (urcsts & URCSTS_HSE) { | 198 | if (urcsts & URCSTS_HSE) { |
224 | dev_err(dev, "host system error -- hardware halted\n"); | 199 | dev_err(dev, "host system error -- hardware halted\n"); |
225 | /* FIXME: do something sensible here */ | 200 | /* FIXME: do something sensible here */ |
226 | goto out; | 201 | goto out; |
227 | } | 202 | } |
228 | if (urcsts & URCSTS_ER) { | 203 | if (urcsts & URCSTS_ER) |
229 | d_printf(3, dev, "ER: event ready\n"); | ||
230 | schedule_work(&whcrc->event_work); | 204 | schedule_work(&whcrc->event_work); |
231 | } | 205 | if (urcsts & URCSTS_RCI) |
232 | if (urcsts & URCSTS_RCI) { | ||
233 | d_printf(3, dev, "RCI: ready to execute another command\n"); | ||
234 | wake_up_all(&whcrc->cmd_wq); | 206 | wake_up_all(&whcrc->cmd_wq); |
235 | } | ||
236 | out: | 207 | out: |
237 | return IRQ_HANDLED; | 208 | return IRQ_HANDLED; |
238 | } | 209 | } |
@@ -251,8 +222,7 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc) | |||
251 | whcrc->area = umc_dev->resource.start; | 222 | whcrc->area = umc_dev->resource.start; |
252 | whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1; | 223 | whcrc->rc_len = umc_dev->resource.end - umc_dev->resource.start + 1; |
253 | result = -EBUSY; | 224 | result = -EBUSY; |
254 | if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) | 225 | if (request_mem_region(whcrc->area, whcrc->rc_len, KBUILD_MODNAME) == NULL) { |
255 | == NULL) { | ||
256 | dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n", | 226 | dev_err(dev, "can't request URC region (%zu bytes @ 0x%lx): %d\n", |
257 | whcrc->rc_len, whcrc->area, result); | 227 | whcrc->rc_len, whcrc->area, result); |
258 | goto error_request_region; | 228 | goto error_request_region; |
@@ -287,8 +257,6 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc) | |||
287 | dev_err(dev, "Can't allocate evt transfer buffer\n"); | 257 | dev_err(dev, "Can't allocate evt transfer buffer\n"); |
288 | goto error_evt_buffer; | 258 | goto error_evt_buffer; |
289 | } | 259 | } |
290 | d_printf(3, dev, "UWB RC Interface: %zu bytes at 0x%p, irq %u\n", | ||
291 | whcrc->rc_len, whcrc->rc_base, umc_dev->irq); | ||
292 | return 0; | 260 | return 0; |
293 | 261 | ||
294 | error_evt_buffer: | 262 | error_evt_buffer: |
@@ -333,47 +301,23 @@ void whcrc_release_rc_umc(struct whcrc *whcrc) | |||
333 | static int whcrc_start_rc(struct uwb_rc *rc) | 301 | static int whcrc_start_rc(struct uwb_rc *rc) |
334 | { | 302 | { |
335 | struct whcrc *whcrc = rc->priv; | 303 | struct whcrc *whcrc = rc->priv; |
336 | int result = 0; | ||
337 | struct device *dev = &whcrc->umc_dev->dev; | 304 | struct device *dev = &whcrc->umc_dev->dev; |
338 | unsigned long start, duration; | ||
339 | 305 | ||
340 | /* Reset the thing */ | 306 | /* Reset the thing */ |
341 | le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); | 307 | le_writel(URCCMD_RESET, whcrc->rc_base + URCCMD); |
342 | if (d_test(3)) | ||
343 | start = jiffies; | ||
344 | if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, | 308 | if (whci_wait_for(dev, whcrc->rc_base + URCCMD, URCCMD_RESET, 0, |
345 | 5000, "device to reset at init") < 0) { | 309 | 5000, "hardware reset") < 0) |
346 | result = -EBUSY; | 310 | return -EBUSY; |
347 | goto error; | ||
348 | } else if (d_test(3)) { | ||
349 | duration = jiffies - start; | ||
350 | if (duration > msecs_to_jiffies(40)) | ||
351 | dev_err(dev, "Device took %ums to " | ||
352 | "reset. MAX expected: 40ms\n", | ||
353 | jiffies_to_msecs(duration)); | ||
354 | } | ||
355 | 311 | ||
356 | /* Set the event buffer, start the controller (enable IRQs later) */ | 312 | /* Set the event buffer, start the controller (enable IRQs later) */ |
357 | le_writel(0, whcrc->rc_base + URCINTR); | 313 | le_writel(0, whcrc->rc_base + URCINTR); |
358 | le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); | 314 | le_writel(URCCMD_RS, whcrc->rc_base + URCCMD); |
359 | result = -ETIMEDOUT; | ||
360 | if (d_test(3)) | ||
361 | start = jiffies; | ||
362 | if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, | 315 | if (whci_wait_for(dev, whcrc->rc_base + URCSTS, URCSTS_HALTED, 0, |
363 | 5000, "device to start") < 0) | 316 | 5000, "radio controller start") < 0) |
364 | goto error; | 317 | return -ETIMEDOUT; |
365 | if (d_test(3)) { | ||
366 | duration = jiffies - start; | ||
367 | if (duration > msecs_to_jiffies(40)) | ||
368 | dev_err(dev, "Device took %ums to start. " | ||
369 | "MAX expected: 40ms\n", | ||
370 | jiffies_to_msecs(duration)); | ||
371 | } | ||
372 | whcrc_enable_events(whcrc); | 318 | whcrc_enable_events(whcrc); |
373 | result = 0; | ||
374 | le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); | 319 | le_writel(URCINTR_EN_ALL, whcrc->rc_base + URCINTR); |
375 | error: | 320 | return 0; |
376 | return result; | ||
377 | } | 321 | } |
378 | 322 | ||
379 | 323 | ||
@@ -395,7 +339,7 @@ void whcrc_stop_rc(struct uwb_rc *rc) | |||
395 | 339 | ||
396 | le_writel(0, whcrc->rc_base + URCCMD); | 340 | le_writel(0, whcrc->rc_base + URCCMD); |
397 | whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, | 341 | whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, |
398 | URCSTS_HALTED, 0, 40, "URCSTS.HALTED"); | 342 | URCSTS_HALTED, URCSTS_HALTED, 100, "radio controller stop"); |
399 | } | 343 | } |
400 | 344 | ||
401 | static void whcrc_init(struct whcrc *whcrc) | 345 | static void whcrc_init(struct whcrc *whcrc) |
@@ -421,7 +365,6 @@ int whcrc_probe(struct umc_dev *umc_dev) | |||
421 | struct whcrc *whcrc; | 365 | struct whcrc *whcrc; |
422 | struct device *dev = &umc_dev->dev; | 366 | struct device *dev = &umc_dev->dev; |
423 | 367 | ||
424 | d_fnstart(3, dev, "(umc_dev %p)\n", umc_dev); | ||
425 | result = -ENOMEM; | 368 | result = -ENOMEM; |
426 | uwb_rc = uwb_rc_alloc(); | 369 | uwb_rc = uwb_rc_alloc(); |
427 | if (uwb_rc == NULL) { | 370 | if (uwb_rc == NULL) { |
@@ -453,7 +396,6 @@ int whcrc_probe(struct umc_dev *umc_dev) | |||
453 | if (result < 0) | 396 | if (result < 0) |
454 | goto error_rc_add; | 397 | goto error_rc_add; |
455 | umc_set_drvdata(umc_dev, whcrc); | 398 | umc_set_drvdata(umc_dev, whcrc); |
456 | d_fnend(3, dev, "(umc_dev %p) = 0\n", umc_dev); | ||
457 | return 0; | 399 | return 0; |
458 | 400 | ||
459 | error_rc_add: | 401 | error_rc_add: |
@@ -463,7 +405,6 @@ error_setup_rc_umc: | |||
463 | error_alloc: | 405 | error_alloc: |
464 | uwb_rc_put(uwb_rc); | 406 | uwb_rc_put(uwb_rc); |
465 | error_rc_alloc: | 407 | error_rc_alloc: |
466 | d_fnend(3, dev, "(umc_dev %p) = %d\n", umc_dev, result); | ||
467 | return result; | 408 | return result; |
468 | } | 409 | } |
469 | 410 | ||
@@ -486,7 +427,24 @@ static void whcrc_remove(struct umc_dev *umc_dev) | |||
486 | whcrc_release_rc_umc(whcrc); | 427 | whcrc_release_rc_umc(whcrc); |
487 | kfree(whcrc); | 428 | kfree(whcrc); |
488 | uwb_rc_put(uwb_rc); | 429 | uwb_rc_put(uwb_rc); |
489 | d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); | 430 | } |
431 | |||
432 | static int whcrc_pre_reset(struct umc_dev *umc) | ||
433 | { | ||
434 | struct whcrc *whcrc = umc_get_drvdata(umc); | ||
435 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; | ||
436 | |||
437 | uwb_rc_pre_reset(uwb_rc); | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int whcrc_post_reset(struct umc_dev *umc) | ||
442 | { | ||
443 | struct whcrc *whcrc = umc_get_drvdata(umc); | ||
444 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; | ||
445 | |||
446 | uwb_rc_post_reset(uwb_rc); | ||
447 | return 0; | ||
490 | } | 448 | } |
491 | 449 | ||
492 | /* PCI device ID's that we handle [so it gets loaded] */ | 450 | /* PCI device ID's that we handle [so it gets loaded] */ |
@@ -497,10 +455,12 @@ static struct pci_device_id whcrc_id_table[] = { | |||
497 | MODULE_DEVICE_TABLE(pci, whcrc_id_table); | 455 | MODULE_DEVICE_TABLE(pci, whcrc_id_table); |
498 | 456 | ||
499 | static struct umc_driver whcrc_driver = { | 457 | static struct umc_driver whcrc_driver = { |
500 | .name = "whc-rc", | 458 | .name = "whc-rc", |
501 | .cap_id = UMC_CAP_ID_WHCI_RC, | 459 | .cap_id = UMC_CAP_ID_WHCI_RC, |
502 | .probe = whcrc_probe, | 460 | .probe = whcrc_probe, |
503 | .remove = whcrc_remove, | 461 | .remove = whcrc_remove, |
462 | .pre_reset = whcrc_pre_reset, | ||
463 | .post_reset = whcrc_post_reset, | ||
504 | }; | 464 | }; |
505 | 465 | ||
506 | static int __init whcrc_driver_init(void) | 466 | static int __init whcrc_driver_init(void) |
diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c index 3df2388f908f..1f8964ed9882 100644 --- a/drivers/uwb/whci.c +++ b/drivers/uwb/whci.c | |||
@@ -67,11 +67,11 @@ int whci_wait_for(struct device *dev, u32 __iomem *reg, u32 mask, u32 result, | |||
67 | val = le_readl(reg); | 67 | val = le_readl(reg); |
68 | if ((val & mask) == result) | 68 | if ((val & mask) == result) |
69 | break; | 69 | break; |
70 | msleep(10); | ||
71 | if (t >= max_ms) { | 70 | if (t >= max_ms) { |
72 | dev_err(dev, "timed out waiting for %s ", tag); | 71 | dev_err(dev, "%s timed out\n", tag); |
73 | return -ETIMEDOUT; | 72 | return -ETIMEDOUT; |
74 | } | 73 | } |
74 | msleep(10); | ||
75 | t += 10; | 75 | t += 10; |
76 | } | 76 | } |
77 | return 0; | 77 | return 0; |
@@ -111,7 +111,7 @@ static int whci_add_cap(struct whci_card *card, int n) | |||
111 | + UWBCAPDATA_TO_OFFSET(capdata); | 111 | + UWBCAPDATA_TO_OFFSET(capdata); |
112 | umc->resource.end = umc->resource.start | 112 | umc->resource.end = umc->resource.start |
113 | + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; | 113 | + (n == 0 ? 0x20 : UWBCAPDATA_TO_SIZE(capdata)) - 1; |
114 | umc->resource.name = umc->dev.bus_id; | 114 | umc->resource.name = dev_name(&umc->dev); |
115 | umc->resource.flags = card->pci->resource[bar].flags; | 115 | umc->resource.flags = card->pci->resource[bar].flags; |
116 | umc->resource.parent = &card->pci->resource[bar]; | 116 | umc->resource.parent = &card->pci->resource[bar]; |
117 | umc->irq = card->pci->irq; | 117 | umc->irq = card->pci->irq; |
diff --git a/drivers/uwb/wlp/eda.c b/drivers/uwb/wlp/eda.c index 10985fa233cc..69e020039718 100644 --- a/drivers/uwb/wlp/eda.c +++ b/drivers/uwb/wlp/eda.c | |||
@@ -51,9 +51,7 @@ | |||
51 | * the tag and address of the transmitting neighbor. | 51 | * the tag and address of the transmitting neighbor. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | #define D_LOCAL 5 | ||
55 | #include <linux/netdevice.h> | 54 | #include <linux/netdevice.h> |
56 | #include <linux/uwb/debug.h> | ||
57 | #include <linux/etherdevice.h> | 55 | #include <linux/etherdevice.h> |
58 | #include <linux/wlp.h> | 56 | #include <linux/wlp.h> |
59 | #include "wlp-internal.h" | 57 | #include "wlp-internal.h" |
@@ -304,7 +302,6 @@ int wlp_eda_for_virtual(struct wlp_eda *eda, | |||
304 | { | 302 | { |
305 | int result = 0; | 303 | int result = 0; |
306 | struct wlp *wlp = container_of(eda, struct wlp, eda); | 304 | struct wlp *wlp = container_of(eda, struct wlp, eda); |
307 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
308 | struct wlp_eda_node *itr; | 305 | struct wlp_eda_node *itr; |
309 | unsigned long flags; | 306 | unsigned long flags; |
310 | int found = 0; | 307 | int found = 0; |
@@ -313,26 +310,14 @@ int wlp_eda_for_virtual(struct wlp_eda *eda, | |||
313 | list_for_each_entry(itr, &eda->cache, list_node) { | 310 | list_for_each_entry(itr, &eda->cache, list_node) { |
314 | if (!memcmp(itr->virt_addr, virt_addr, | 311 | if (!memcmp(itr->virt_addr, virt_addr, |
315 | sizeof(itr->virt_addr))) { | 312 | sizeof(itr->virt_addr))) { |
316 | d_printf(6, dev, "EDA: looking for %pM hit %02x:%02x " | ||
317 | "wss %p tag 0x%02x state %u\n", | ||
318 | virt_addr, | ||
319 | itr->dev_addr.data[1], | ||
320 | itr->dev_addr.data[0], itr->wss, | ||
321 | itr->tag, itr->state); | ||
322 | result = (*function)(wlp, itr, priv); | 313 | result = (*function)(wlp, itr, priv); |
323 | *dev_addr = itr->dev_addr; | 314 | *dev_addr = itr->dev_addr; |
324 | found = 1; | 315 | found = 1; |
325 | break; | 316 | break; |
326 | } else | 317 | } |
327 | d_printf(6, dev, "EDA: looking for %pM against %pM miss\n", | ||
328 | virt_addr, itr->virt_addr); | ||
329 | } | 318 | } |
330 | if (!found) { | 319 | if (!found) |
331 | if (printk_ratelimit()) | ||
332 | dev_err(dev, "EDA: Eth addr %pM not found.\n", | ||
333 | virt_addr); | ||
334 | result = -ENODEV; | 320 | result = -ENODEV; |
335 | } | ||
336 | spin_unlock_irqrestore(&eda->lock, flags); | 321 | spin_unlock_irqrestore(&eda->lock, flags); |
337 | return result; | 322 | return result; |
338 | } | 323 | } |
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c index a64cb8241713..aa42fcee4c4f 100644 --- a/drivers/uwb/wlp/messages.c +++ b/drivers/uwb/wlp/messages.c | |||
@@ -24,8 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/wlp.h> | 26 | #include <linux/wlp.h> |
27 | #define D_LOCAL 6 | 27 | |
28 | #include <linux/uwb/debug.h> | ||
29 | #include "wlp-internal.h" | 28 | #include "wlp-internal.h" |
30 | 29 | ||
31 | static | 30 | static |
@@ -105,24 +104,18 @@ static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type, | |||
105 | #define wlp_set(type, type_code, name) \ | 104 | #define wlp_set(type, type_code, name) \ |
106 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ | 105 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ |
107 | { \ | 106 | { \ |
108 | d_fnstart(6, NULL, "(attribute %p)\n", attr); \ | ||
109 | wlp_set_attr_hdr(&attr->hdr, type_code, \ | 107 | wlp_set_attr_hdr(&attr->hdr, type_code, \ |
110 | sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ | 108 | sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ |
111 | attr->name = value; \ | 109 | attr->name = value; \ |
112 | d_dump(6, NULL, attr, sizeof(*attr)); \ | ||
113 | d_fnend(6, NULL, "(attribute %p)\n", attr); \ | ||
114 | return sizeof(*attr); \ | 110 | return sizeof(*attr); \ |
115 | } | 111 | } |
116 | 112 | ||
117 | #define wlp_pset(type, type_code, name) \ | 113 | #define wlp_pset(type, type_code, name) \ |
118 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ | 114 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ |
119 | { \ | 115 | { \ |
120 | d_fnstart(6, NULL, "(attribute %p)\n", attr); \ | ||
121 | wlp_set_attr_hdr(&attr->hdr, type_code, \ | 116 | wlp_set_attr_hdr(&attr->hdr, type_code, \ |
122 | sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ | 117 | sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \ |
123 | attr->name = *value; \ | 118 | attr->name = *value; \ |
124 | d_dump(6, NULL, attr, sizeof(*attr)); \ | ||
125 | d_fnend(6, NULL, "(attribute %p)\n", attr); \ | ||
126 | return sizeof(*attr); \ | 119 | return sizeof(*attr); \ |
127 | } | 120 | } |
128 | 121 | ||
@@ -139,11 +132,8 @@ static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \ | |||
139 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \ | 132 | static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \ |
140 | size_t len) \ | 133 | size_t len) \ |
141 | { \ | 134 | { \ |
142 | d_fnstart(6, NULL, "(attribute %p)\n", attr); \ | ||
143 | wlp_set_attr_hdr(&attr->hdr, type_code, len); \ | 135 | wlp_set_attr_hdr(&attr->hdr, type_code, len); \ |
144 | memcpy(attr->name, value, len); \ | 136 | memcpy(attr->name, value, len); \ |
145 | d_dump(6, NULL, attr, sizeof(*attr) + len); \ | ||
146 | d_fnend(6, NULL, "(attribute %p)\n", attr); \ | ||
147 | return sizeof(*attr) + len; \ | 137 | return sizeof(*attr) + len; \ |
148 | } | 138 | } |
149 | 139 | ||
@@ -182,7 +172,7 @@ static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr, | |||
182 | size_t datalen; | 172 | size_t datalen; |
183 | void *ptr = attr->wss_info; | 173 | void *ptr = attr->wss_info; |
184 | size_t used = sizeof(*attr); | 174 | size_t used = sizeof(*attr); |
185 | d_fnstart(6, NULL, "(attribute %p)\n", attr); | 175 | |
186 | datalen = sizeof(struct wlp_wss_info) + strlen(wss->name); | 176 | datalen = sizeof(struct wlp_wss_info) + strlen(wss->name); |
187 | wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen); | 177 | wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen); |
188 | used = wlp_set_wssid(ptr, &wss->wssid); | 178 | used = wlp_set_wssid(ptr, &wss->wssid); |
@@ -190,9 +180,6 @@ static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr, | |||
190 | used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll); | 180 | used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll); |
191 | used += wlp_set_wss_sec_status(ptr + used, wss->secure_status); | 181 | used += wlp_set_wss_sec_status(ptr + used, wss->secure_status); |
192 | used += wlp_set_wss_bcast(ptr + used, &wss->bcast); | 182 | used += wlp_set_wss_bcast(ptr + used, &wss->bcast); |
193 | d_dump(6, NULL, attr, sizeof(*attr) + datalen); | ||
194 | d_fnend(6, NULL, "(attribute %p, used %d)\n", | ||
195 | attr, (int)(sizeof(*attr) + used)); | ||
196 | return sizeof(*attr) + used; | 183 | return sizeof(*attr) + used; |
197 | } | 184 | } |
198 | 185 | ||
@@ -414,7 +401,6 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, | |||
414 | size_t used = 0; | 401 | size_t used = 0; |
415 | ssize_t result = -EINVAL; | 402 | ssize_t result = -EINVAL; |
416 | 403 | ||
417 | d_printf(6, dev, "WLP: WSS info: Retrieving WSS name\n"); | ||
418 | result = wlp_get_wss_name(wlp, ptr, info->name, buflen); | 404 | result = wlp_get_wss_name(wlp, ptr, info->name, buflen); |
419 | if (result < 0) { | 405 | if (result < 0) { |
420 | dev_err(dev, "WLP: unable to obtain WSS name from " | 406 | dev_err(dev, "WLP: unable to obtain WSS name from " |
@@ -422,7 +408,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, | |||
422 | goto error_parse; | 408 | goto error_parse; |
423 | } | 409 | } |
424 | used += result; | 410 | used += result; |
425 | d_printf(6, dev, "WLP: WSS info: Retrieving accept enroll\n"); | 411 | |
426 | result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll, | 412 | result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll, |
427 | buflen - used); | 413 | buflen - used); |
428 | if (result < 0) { | 414 | if (result < 0) { |
@@ -437,7 +423,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, | |||
437 | goto error_parse; | 423 | goto error_parse; |
438 | } | 424 | } |
439 | used += result; | 425 | used += result; |
440 | d_printf(6, dev, "WLP: WSS info: Retrieving secure status\n"); | 426 | |
441 | result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status, | 427 | result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status, |
442 | buflen - used); | 428 | buflen - used); |
443 | if (result < 0) { | 429 | if (result < 0) { |
@@ -452,7 +438,7 @@ static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp, | |||
452 | goto error_parse; | 438 | goto error_parse; |
453 | } | 439 | } |
454 | used += result; | 440 | used += result; |
455 | d_printf(6, dev, "WLP: WSS info: Retrieving broadcast\n"); | 441 | |
456 | result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast, | 442 | result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast, |
457 | buflen - used); | 443 | buflen - used); |
458 | if (result < 0) { | 444 | if (result < 0) { |
@@ -530,7 +516,7 @@ static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr, | |||
530 | len = result; | 516 | len = result; |
531 | used = sizeof(*attr); | 517 | used = sizeof(*attr); |
532 | ptr = attr; | 518 | ptr = attr; |
533 | d_printf(6, dev, "WLP: WSS info: Retrieving WSSID\n"); | 519 | |
534 | result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used); | 520 | result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used); |
535 | if (result < 0) { | 521 | if (result < 0) { |
536 | dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n"); | 522 | dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n"); |
@@ -553,8 +539,6 @@ static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr, | |||
553 | goto out; | 539 | goto out; |
554 | } | 540 | } |
555 | result = used; | 541 | result = used; |
556 | d_printf(6, dev, "WLP: Successfully parsed WLP information " | ||
557 | "attribute. used %zu bytes\n", used); | ||
558 | out: | 542 | out: |
559 | return result; | 543 | return result; |
560 | } | 544 | } |
@@ -598,8 +582,6 @@ static ssize_t wlp_get_all_wss_info(struct wlp *wlp, | |||
598 | struct wlp_wssid_e *wssid_e; | 582 | struct wlp_wssid_e *wssid_e; |
599 | char buf[WLP_WSS_UUID_STRSIZE]; | 583 | char buf[WLP_WSS_UUID_STRSIZE]; |
600 | 584 | ||
601 | d_fnstart(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d \n", | ||
602 | wlp, attr, neighbor, wss, (int)buflen); | ||
603 | if (buflen < 0) | 585 | if (buflen < 0) |
604 | goto out; | 586 | goto out; |
605 | 587 | ||
@@ -638,8 +620,7 @@ static ssize_t wlp_get_all_wss_info(struct wlp *wlp, | |||
638 | wss->accept_enroll = wss_info.accept_enroll; | 620 | wss->accept_enroll = wss_info.accept_enroll; |
639 | wss->state = WLP_WSS_STATE_PART_ENROLLED; | 621 | wss->state = WLP_WSS_STATE_PART_ENROLLED; |
640 | wlp_wss_uuid_print(buf, sizeof(buf), &wssid); | 622 | wlp_wss_uuid_print(buf, sizeof(buf), &wssid); |
641 | d_printf(2, dev, "WLP: Found WSS %s. Enrolling.\n", | 623 | dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf); |
642 | buf); | ||
643 | } else { | 624 | } else { |
644 | wssid_e = wlp_create_wssid_e(wlp, neighbor); | 625 | wssid_e = wlp_create_wssid_e(wlp, neighbor); |
645 | if (wssid_e == NULL) { | 626 | if (wssid_e == NULL) { |
@@ -660,9 +641,6 @@ error_parse: | |||
660 | if (result < 0 && !enroll) /* this was a discovery */ | 641 | if (result < 0 && !enroll) /* this was a discovery */ |
661 | wlp_remove_neighbor_tmp_info(neighbor); | 642 | wlp_remove_neighbor_tmp_info(neighbor); |
662 | out: | 643 | out: |
663 | d_fnend(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d, " | ||
664 | "result %d \n", wlp, attr, neighbor, wss, (int)buflen, | ||
665 | (int)result); | ||
666 | return result; | 644 | return result; |
667 | 645 | ||
668 | } | 646 | } |
@@ -718,7 +696,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, | |||
718 | struct sk_buff *_skb; | 696 | struct sk_buff *_skb; |
719 | void *d1_itr; | 697 | void *d1_itr; |
720 | 698 | ||
721 | d_fnstart(6, dev, "wlp %p\n", wlp); | ||
722 | if (wlp->dev_info == NULL) { | 699 | if (wlp->dev_info == NULL) { |
723 | result = __wlp_setup_device_info(wlp); | 700 | result = __wlp_setup_device_info(wlp); |
724 | if (result < 0) { | 701 | if (result < 0) { |
@@ -728,24 +705,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, | |||
728 | } | 705 | } |
729 | } | 706 | } |
730 | info = wlp->dev_info; | 707 | info = wlp->dev_info; |
731 | d_printf(6, dev, "Local properties:\n" | ||
732 | "Device name (%d bytes): %s\n" | ||
733 | "Model name (%d bytes): %s\n" | ||
734 | "Manufacturer (%d bytes): %s\n" | ||
735 | "Model number (%d bytes): %s\n" | ||
736 | "Serial number (%d bytes): %s\n" | ||
737 | "Primary device type: \n" | ||
738 | " Category: %d \n" | ||
739 | " OUI: %02x:%02x:%02x \n" | ||
740 | " OUI Subdivision: %u \n", | ||
741 | (int)strlen(info->name), info->name, | ||
742 | (int)strlen(info->model_name), info->model_name, | ||
743 | (int)strlen(info->manufacturer), info->manufacturer, | ||
744 | (int)strlen(info->model_nr), info->model_nr, | ||
745 | (int)strlen(info->serial), info->serial, | ||
746 | info->prim_dev_type.category, | ||
747 | info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], | ||
748 | info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); | ||
749 | _skb = dev_alloc_skb(sizeof(*_d1) | 708 | _skb = dev_alloc_skb(sizeof(*_d1) |
750 | + sizeof(struct wlp_attr_uuid_e) | 709 | + sizeof(struct wlp_attr_uuid_e) |
751 | + sizeof(struct wlp_attr_wss_sel_mthd) | 710 | + sizeof(struct wlp_attr_wss_sel_mthd) |
@@ -768,7 +727,6 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, | |||
768 | goto error; | 727 | goto error; |
769 | } | 728 | } |
770 | _d1 = (void *) _skb->data; | 729 | _d1 = (void *) _skb->data; |
771 | d_printf(6, dev, "D1 starts at %p \n", _d1); | ||
772 | _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); | 730 | _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); |
773 | _d1->hdr.type = WLP_FRAME_ASSOCIATION; | 731 | _d1->hdr.type = WLP_FRAME_ASSOCIATION; |
774 | _d1->type = WLP_ASSOC_D1; | 732 | _d1->type = WLP_ASSOC_D1; |
@@ -791,25 +749,8 @@ static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss, | |||
791 | used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type); | 749 | used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type); |
792 | used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE); | 750 | used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE); |
793 | skb_put(_skb, sizeof(*_d1) + used); | 751 | skb_put(_skb, sizeof(*_d1) + used); |
794 | d_printf(6, dev, "D1 message:\n"); | ||
795 | d_dump(6, dev, _d1, sizeof(*_d1) | ||
796 | + sizeof(struct wlp_attr_uuid_e) | ||
797 | + sizeof(struct wlp_attr_wss_sel_mthd) | ||
798 | + sizeof(struct wlp_attr_dev_name) | ||
799 | + strlen(info->name) | ||
800 | + sizeof(struct wlp_attr_manufacturer) | ||
801 | + strlen(info->manufacturer) | ||
802 | + sizeof(struct wlp_attr_model_name) | ||
803 | + strlen(info->model_name) | ||
804 | + sizeof(struct wlp_attr_model_nr) | ||
805 | + strlen(info->model_nr) | ||
806 | + sizeof(struct wlp_attr_serial) | ||
807 | + strlen(info->serial) | ||
808 | + sizeof(struct wlp_attr_prim_dev_type) | ||
809 | + sizeof(struct wlp_attr_wlp_assc_err)); | ||
810 | *skb = _skb; | 752 | *skb = _skb; |
811 | error: | 753 | error: |
812 | d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); | ||
813 | return result; | 754 | return result; |
814 | } | 755 | } |
815 | 756 | ||
@@ -837,7 +778,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, | |||
837 | void *d2_itr; | 778 | void *d2_itr; |
838 | size_t mem_needed; | 779 | size_t mem_needed; |
839 | 780 | ||
840 | d_fnstart(6, dev, "wlp %p\n", wlp); | ||
841 | if (wlp->dev_info == NULL) { | 781 | if (wlp->dev_info == NULL) { |
842 | result = __wlp_setup_device_info(wlp); | 782 | result = __wlp_setup_device_info(wlp); |
843 | if (result < 0) { | 783 | if (result < 0) { |
@@ -847,24 +787,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, | |||
847 | } | 787 | } |
848 | } | 788 | } |
849 | info = wlp->dev_info; | 789 | info = wlp->dev_info; |
850 | d_printf(6, dev, "Local properties:\n" | ||
851 | "Device name (%d bytes): %s\n" | ||
852 | "Model name (%d bytes): %s\n" | ||
853 | "Manufacturer (%d bytes): %s\n" | ||
854 | "Model number (%d bytes): %s\n" | ||
855 | "Serial number (%d bytes): %s\n" | ||
856 | "Primary device type: \n" | ||
857 | " Category: %d \n" | ||
858 | " OUI: %02x:%02x:%02x \n" | ||
859 | " OUI Subdivision: %u \n", | ||
860 | (int)strlen(info->name), info->name, | ||
861 | (int)strlen(info->model_name), info->model_name, | ||
862 | (int)strlen(info->manufacturer), info->manufacturer, | ||
863 | (int)strlen(info->model_nr), info->model_nr, | ||
864 | (int)strlen(info->serial), info->serial, | ||
865 | info->prim_dev_type.category, | ||
866 | info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1], | ||
867 | info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv); | ||
868 | mem_needed = sizeof(*_d2) | 790 | mem_needed = sizeof(*_d2) |
869 | + sizeof(struct wlp_attr_uuid_e) | 791 | + sizeof(struct wlp_attr_uuid_e) |
870 | + sizeof(struct wlp_attr_uuid_r) | 792 | + sizeof(struct wlp_attr_uuid_r) |
@@ -892,7 +814,6 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, | |||
892 | goto error; | 814 | goto error; |
893 | } | 815 | } |
894 | _d2 = (void *) _skb->data; | 816 | _d2 = (void *) _skb->data; |
895 | d_printf(6, dev, "D2 starts at %p \n", _d2); | ||
896 | _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); | 817 | _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); |
897 | _d2->hdr.type = WLP_FRAME_ASSOCIATION; | 818 | _d2->hdr.type = WLP_FRAME_ASSOCIATION; |
898 | _d2->type = WLP_ASSOC_D2; | 819 | _d2->type = WLP_ASSOC_D2; |
@@ -917,11 +838,8 @@ int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss, | |||
917 | used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type); | 838 | used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type); |
918 | used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE); | 839 | used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE); |
919 | skb_put(_skb, sizeof(*_d2) + used); | 840 | skb_put(_skb, sizeof(*_d2) + used); |
920 | d_printf(6, dev, "D2 message:\n"); | ||
921 | d_dump(6, dev, _d2, mem_needed); | ||
922 | *skb = _skb; | 841 | *skb = _skb; |
923 | error: | 842 | error: |
924 | d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); | ||
925 | return result; | 843 | return result; |
926 | } | 844 | } |
927 | 845 | ||
@@ -947,7 +865,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, | |||
947 | struct sk_buff *_skb; | 865 | struct sk_buff *_skb; |
948 | struct wlp_nonce tmp; | 866 | struct wlp_nonce tmp; |
949 | 867 | ||
950 | d_fnstart(6, dev, "wlp %p\n", wlp); | ||
951 | _skb = dev_alloc_skb(sizeof(*f0)); | 868 | _skb = dev_alloc_skb(sizeof(*f0)); |
952 | if (_skb == NULL) { | 869 | if (_skb == NULL) { |
953 | dev_err(dev, "WLP: Unable to allocate memory for F0 " | 870 | dev_err(dev, "WLP: Unable to allocate memory for F0 " |
@@ -955,7 +872,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, | |||
955 | goto error_alloc; | 872 | goto error_alloc; |
956 | } | 873 | } |
957 | f0 = (void *) _skb->data; | 874 | f0 = (void *) _skb->data; |
958 | d_printf(6, dev, "F0 starts at %p \n", f0); | ||
959 | f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); | 875 | f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); |
960 | f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION; | 876 | f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION; |
961 | f0->f0_hdr.type = WLP_ASSOC_F0; | 877 | f0->f0_hdr.type = WLP_ASSOC_F0; |
@@ -969,7 +885,6 @@ int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb, | |||
969 | *skb = _skb; | 885 | *skb = _skb; |
970 | result = 0; | 886 | result = 0; |
971 | error_alloc: | 887 | error_alloc: |
972 | d_fnend(6, dev, "wlp %p, result %d \n", wlp, result); | ||
973 | return result; | 888 | return result; |
974 | } | 889 | } |
975 | 890 | ||
@@ -1242,12 +1157,9 @@ void wlp_handle_d1_frame(struct work_struct *ws) | |||
1242 | enum wlp_wss_sel_mthd sel_mthd = 0; | 1157 | enum wlp_wss_sel_mthd sel_mthd = 0; |
1243 | struct wlp_device_info dev_info; | 1158 | struct wlp_device_info dev_info; |
1244 | enum wlp_assc_error assc_err; | 1159 | enum wlp_assc_error assc_err; |
1245 | char uuid[WLP_WSS_UUID_STRSIZE]; | ||
1246 | struct sk_buff *resp = NULL; | 1160 | struct sk_buff *resp = NULL; |
1247 | 1161 | ||
1248 | /* Parse D1 frame */ | 1162 | /* Parse D1 frame */ |
1249 | d_fnstart(6, dev, "WLP: handle D1 frame. wlp = %p, skb = %p\n", | ||
1250 | wlp, skb); | ||
1251 | mutex_lock(&wss->mutex); | 1163 | mutex_lock(&wss->mutex); |
1252 | mutex_lock(&wlp->mutex); /* to access wlp->uuid */ | 1164 | mutex_lock(&wlp->mutex); /* to access wlp->uuid */ |
1253 | memset(&dev_info, 0, sizeof(dev_info)); | 1165 | memset(&dev_info, 0, sizeof(dev_info)); |
@@ -1258,30 +1170,6 @@ void wlp_handle_d1_frame(struct work_struct *ws) | |||
1258 | kfree_skb(skb); | 1170 | kfree_skb(skb); |
1259 | goto out; | 1171 | goto out; |
1260 | } | 1172 | } |
1261 | wlp_wss_uuid_print(uuid, sizeof(uuid), &uuid_e); | ||
1262 | d_printf(6, dev, "From D1 frame:\n" | ||
1263 | "UUID-E: %s\n" | ||
1264 | "Selection method: %d\n" | ||
1265 | "Device name (%d bytes): %s\n" | ||
1266 | "Model name (%d bytes): %s\n" | ||
1267 | "Manufacturer (%d bytes): %s\n" | ||
1268 | "Model number (%d bytes): %s\n" | ||
1269 | "Serial number (%d bytes): %s\n" | ||
1270 | "Primary device type: \n" | ||
1271 | " Category: %d \n" | ||
1272 | " OUI: %02x:%02x:%02x \n" | ||
1273 | " OUI Subdivision: %u \n", | ||
1274 | uuid, sel_mthd, | ||
1275 | (int)strlen(dev_info.name), dev_info.name, | ||
1276 | (int)strlen(dev_info.model_name), dev_info.model_name, | ||
1277 | (int)strlen(dev_info.manufacturer), dev_info.manufacturer, | ||
1278 | (int)strlen(dev_info.model_nr), dev_info.model_nr, | ||
1279 | (int)strlen(dev_info.serial), dev_info.serial, | ||
1280 | dev_info.prim_dev_type.category, | ||
1281 | dev_info.prim_dev_type.OUI[0], | ||
1282 | dev_info.prim_dev_type.OUI[1], | ||
1283 | dev_info.prim_dev_type.OUI[2], | ||
1284 | dev_info.prim_dev_type.OUIsubdiv); | ||
1285 | 1173 | ||
1286 | kfree_skb(skb); | 1174 | kfree_skb(skb); |
1287 | if (!wlp_uuid_is_set(&wlp->uuid)) { | 1175 | if (!wlp_uuid_is_set(&wlp->uuid)) { |
@@ -1316,7 +1204,6 @@ out: | |||
1316 | kfree(frame_ctx); | 1204 | kfree(frame_ctx); |
1317 | mutex_unlock(&wlp->mutex); | 1205 | mutex_unlock(&wlp->mutex); |
1318 | mutex_unlock(&wss->mutex); | 1206 | mutex_unlock(&wss->mutex); |
1319 | d_fnend(6, dev, "WLP: handle D1 frame. wlp = %p\n", wlp); | ||
1320 | } | 1207 | } |
1321 | 1208 | ||
1322 | /** | 1209 | /** |
@@ -1546,10 +1433,8 @@ int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb, | |||
1546 | void *ptr = skb->data; | 1433 | void *ptr = skb->data; |
1547 | size_t len = skb->len; | 1434 | size_t len = skb->len; |
1548 | size_t used; | 1435 | size_t used; |
1549 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
1550 | struct wlp_frame_assoc *assoc = ptr; | 1436 | struct wlp_frame_assoc *assoc = ptr; |
1551 | 1437 | ||
1552 | d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); | ||
1553 | used = sizeof(*assoc); | 1438 | used = sizeof(*assoc); |
1554 | result = wlp_get_wssid(wlp, ptr + used, wssid, len - used); | 1439 | result = wlp_get_wssid(wlp, ptr + used, wssid, len - used); |
1555 | if (result < 0) { | 1440 | if (result < 0) { |
@@ -1572,14 +1457,7 @@ int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb, | |||
1572 | wlp_assoc_frame_str(assoc->type)); | 1457 | wlp_assoc_frame_str(assoc->type)); |
1573 | goto error_parse; | 1458 | goto error_parse; |
1574 | } | 1459 | } |
1575 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | ||
1576 | d_printf(6, dev, "WLP: parsed: WSSID %s, tag 0x%02x, virt " | ||
1577 | "%02x:%02x:%02x:%02x:%02x:%02x \n", buf, *tag, | ||
1578 | virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], | ||
1579 | virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); | ||
1580 | |||
1581 | error_parse: | 1460 | error_parse: |
1582 | d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); | ||
1583 | return result; | 1461 | return result; |
1584 | } | 1462 | } |
1585 | 1463 | ||
@@ -1600,7 +1478,6 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, | |||
1600 | } *c; | 1478 | } *c; |
1601 | struct sk_buff *_skb; | 1479 | struct sk_buff *_skb; |
1602 | 1480 | ||
1603 | d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); | ||
1604 | _skb = dev_alloc_skb(sizeof(*c)); | 1481 | _skb = dev_alloc_skb(sizeof(*c)); |
1605 | if (_skb == NULL) { | 1482 | if (_skb == NULL) { |
1606 | dev_err(dev, "WLP: Unable to allocate memory for C1/C2 " | 1483 | dev_err(dev, "WLP: Unable to allocate memory for C1/C2 " |
@@ -1608,7 +1485,6 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, | |||
1608 | goto error_alloc; | 1485 | goto error_alloc; |
1609 | } | 1486 | } |
1610 | c = (void *) _skb->data; | 1487 | c = (void *) _skb->data; |
1611 | d_printf(6, dev, "C1/C2 starts at %p \n", c); | ||
1612 | c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); | 1488 | c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); |
1613 | c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; | 1489 | c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; |
1614 | c->c_hdr.type = type; | 1490 | c->c_hdr.type = type; |
@@ -1616,12 +1492,9 @@ int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss, | |||
1616 | wlp_set_msg_type(&c->c_hdr.msg_type, type); | 1492 | wlp_set_msg_type(&c->c_hdr.msg_type, type); |
1617 | wlp_set_wssid(&c->wssid, &wss->wssid); | 1493 | wlp_set_wssid(&c->wssid, &wss->wssid); |
1618 | skb_put(_skb, sizeof(*c)); | 1494 | skb_put(_skb, sizeof(*c)); |
1619 | d_printf(6, dev, "C1/C2 message:\n"); | ||
1620 | d_dump(6, dev, c, sizeof(*c)); | ||
1621 | *skb = _skb; | 1495 | *skb = _skb; |
1622 | result = 0; | 1496 | result = 0; |
1623 | error_alloc: | 1497 | error_alloc: |
1624 | d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); | ||
1625 | return result; | 1498 | return result; |
1626 | } | 1499 | } |
1627 | 1500 | ||
@@ -1660,7 +1533,6 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, | |||
1660 | } *c; | 1533 | } *c; |
1661 | struct sk_buff *_skb; | 1534 | struct sk_buff *_skb; |
1662 | 1535 | ||
1663 | d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss); | ||
1664 | _skb = dev_alloc_skb(sizeof(*c)); | 1536 | _skb = dev_alloc_skb(sizeof(*c)); |
1665 | if (_skb == NULL) { | 1537 | if (_skb == NULL) { |
1666 | dev_err(dev, "WLP: Unable to allocate memory for C3/C4 " | 1538 | dev_err(dev, "WLP: Unable to allocate memory for C3/C4 " |
@@ -1668,7 +1540,6 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, | |||
1668 | goto error_alloc; | 1540 | goto error_alloc; |
1669 | } | 1541 | } |
1670 | c = (void *) _skb->data; | 1542 | c = (void *) _skb->data; |
1671 | d_printf(6, dev, "C3/C4 starts at %p \n", c); | ||
1672 | c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); | 1543 | c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID); |
1673 | c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; | 1544 | c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION; |
1674 | c->c_hdr.type = type; | 1545 | c->c_hdr.type = type; |
@@ -1678,12 +1549,9 @@ int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss, | |||
1678 | wlp_set_wss_tag(&c->wss_tag, wss->tag); | 1549 | wlp_set_wss_tag(&c->wss_tag, wss->tag); |
1679 | wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr); | 1550 | wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr); |
1680 | skb_put(_skb, sizeof(*c)); | 1551 | skb_put(_skb, sizeof(*c)); |
1681 | d_printf(6, dev, "C3/C4 message:\n"); | ||
1682 | d_dump(6, dev, c, sizeof(*c)); | ||
1683 | *skb = _skb; | 1552 | *skb = _skb; |
1684 | result = 0; | 1553 | result = 0; |
1685 | error_alloc: | 1554 | error_alloc: |
1686 | d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result); | ||
1687 | return result; | 1555 | return result; |
1688 | } | 1556 | } |
1689 | 1557 | ||
@@ -1709,10 +1577,7 @@ static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \ | |||
1709 | struct device *dev = &wlp->rc->uwb_dev.dev; \ | 1577 | struct device *dev = &wlp->rc->uwb_dev.dev; \ |
1710 | int result; \ | 1578 | int result; \ |
1711 | struct sk_buff *skb = NULL; \ | 1579 | struct sk_buff *skb = NULL; \ |
1712 | d_fnstart(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ | 1580 | \ |
1713 | wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ | ||
1714 | d_printf(6, dev, "WLP: Constructing %s frame. \n", \ | ||
1715 | wlp_assoc_frame_str(id)); \ | ||
1716 | /* Build the frame */ \ | 1581 | /* Build the frame */ \ |
1717 | result = wlp_build_assoc_##type(wlp, wss, &skb); \ | 1582 | result = wlp_build_assoc_##type(wlp, wss, &skb); \ |
1718 | if (result < 0) { \ | 1583 | if (result < 0) { \ |
@@ -1721,9 +1586,6 @@ static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \ | |||
1721 | goto error_build_assoc; \ | 1586 | goto error_build_assoc; \ |
1722 | } \ | 1587 | } \ |
1723 | /* Send the frame */ \ | 1588 | /* Send the frame */ \ |
1724 | d_printf(6, dev, "Transmitting %s frame to %02x:%02x \n", \ | ||
1725 | wlp_assoc_frame_str(id), \ | ||
1726 | dev_addr->data[1], dev_addr->data[0]); \ | ||
1727 | BUG_ON(wlp->xmit_frame == NULL); \ | 1589 | BUG_ON(wlp->xmit_frame == NULL); \ |
1728 | result = wlp->xmit_frame(wlp, skb, dev_addr); \ | 1590 | result = wlp->xmit_frame(wlp, skb, dev_addr); \ |
1729 | if (result < 0) { \ | 1591 | if (result < 0) { \ |
@@ -1740,8 +1602,6 @@ error_xmit: \ | |||
1740 | /* We could try again ... */ \ | 1602 | /* We could try again ... */ \ |
1741 | dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \ | 1603 | dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \ |
1742 | error_build_assoc: \ | 1604 | error_build_assoc: \ |
1743 | d_fnend(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \ | ||
1744 | wlp, wss, dev_addr->data[1], dev_addr->data[0]); \ | ||
1745 | return result; \ | 1605 | return result; \ |
1746 | } | 1606 | } |
1747 | 1607 | ||
@@ -1794,12 +1654,9 @@ void wlp_handle_c1_frame(struct work_struct *ws) | |||
1794 | struct uwb_dev_addr *src = &frame_ctx->src; | 1654 | struct uwb_dev_addr *src = &frame_ctx->src; |
1795 | int result; | 1655 | int result; |
1796 | struct wlp_uuid wssid; | 1656 | struct wlp_uuid wssid; |
1797 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
1798 | struct sk_buff *resp = NULL; | 1657 | struct sk_buff *resp = NULL; |
1799 | 1658 | ||
1800 | /* Parse C1 frame */ | 1659 | /* Parse C1 frame */ |
1801 | d_fnstart(6, dev, "WLP: handle C1 frame. wlp = %p, c1 = %p\n", | ||
1802 | wlp, c1); | ||
1803 | mutex_lock(&wss->mutex); | 1660 | mutex_lock(&wss->mutex); |
1804 | result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid, | 1661 | result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid, |
1805 | len - sizeof(*c1)); | 1662 | len - sizeof(*c1)); |
@@ -1807,12 +1664,8 @@ void wlp_handle_c1_frame(struct work_struct *ws) | |||
1807 | dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n"); | 1664 | dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n"); |
1808 | goto out; | 1665 | goto out; |
1809 | } | 1666 | } |
1810 | wlp_wss_uuid_print(buf, sizeof(buf), &wssid); | ||
1811 | d_printf(6, dev, "Received C1 frame with WSSID %s \n", buf); | ||
1812 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) | 1667 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) |
1813 | && wss->state == WLP_WSS_STATE_ACTIVE) { | 1668 | && wss->state == WLP_WSS_STATE_ACTIVE) { |
1814 | d_printf(6, dev, "WSSID from C1 frame is known locally " | ||
1815 | "and is active\n"); | ||
1816 | /* Construct C2 frame */ | 1669 | /* Construct C2 frame */ |
1817 | result = wlp_build_assoc_c2(wlp, wss, &resp); | 1670 | result = wlp_build_assoc_c2(wlp, wss, &resp); |
1818 | if (result < 0) { | 1671 | if (result < 0) { |
@@ -1820,8 +1673,6 @@ void wlp_handle_c1_frame(struct work_struct *ws) | |||
1820 | goto out; | 1673 | goto out; |
1821 | } | 1674 | } |
1822 | } else { | 1675 | } else { |
1823 | d_printf(6, dev, "WSSID from C1 frame is not known locally " | ||
1824 | "or is not active\n"); | ||
1825 | /* Construct F0 frame */ | 1676 | /* Construct F0 frame */ |
1826 | result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); | 1677 | result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); |
1827 | if (result < 0) { | 1678 | if (result < 0) { |
@@ -1830,8 +1681,6 @@ void wlp_handle_c1_frame(struct work_struct *ws) | |||
1830 | } | 1681 | } |
1831 | } | 1682 | } |
1832 | /* Send C2 frame */ | 1683 | /* Send C2 frame */ |
1833 | d_printf(6, dev, "Transmitting response (C2/F0) frame to %02x:%02x \n", | ||
1834 | src->data[1], src->data[0]); | ||
1835 | BUG_ON(wlp->xmit_frame == NULL); | 1684 | BUG_ON(wlp->xmit_frame == NULL); |
1836 | result = wlp->xmit_frame(wlp, resp, src); | 1685 | result = wlp->xmit_frame(wlp, resp, src); |
1837 | if (result < 0) { | 1686 | if (result < 0) { |
@@ -1846,7 +1695,6 @@ out: | |||
1846 | kfree_skb(frame_ctx->skb); | 1695 | kfree_skb(frame_ctx->skb); |
1847 | kfree(frame_ctx); | 1696 | kfree(frame_ctx); |
1848 | mutex_unlock(&wss->mutex); | 1697 | mutex_unlock(&wss->mutex); |
1849 | d_fnend(6, dev, "WLP: handle C1 frame. wlp = %p\n", wlp); | ||
1850 | } | 1698 | } |
1851 | 1699 | ||
1852 | /** | 1700 | /** |
@@ -1868,27 +1716,20 @@ void wlp_handle_c3_frame(struct work_struct *ws) | |||
1868 | struct sk_buff *skb = frame_ctx->skb; | 1716 | struct sk_buff *skb = frame_ctx->skb; |
1869 | struct uwb_dev_addr *src = &frame_ctx->src; | 1717 | struct uwb_dev_addr *src = &frame_ctx->src; |
1870 | int result; | 1718 | int result; |
1871 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
1872 | struct sk_buff *resp = NULL; | 1719 | struct sk_buff *resp = NULL; |
1873 | struct wlp_uuid wssid; | 1720 | struct wlp_uuid wssid; |
1874 | u8 tag; | 1721 | u8 tag; |
1875 | struct uwb_mac_addr virt_addr; | 1722 | struct uwb_mac_addr virt_addr; |
1876 | 1723 | ||
1877 | /* Parse C3 frame */ | 1724 | /* Parse C3 frame */ |
1878 | d_fnstart(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", | ||
1879 | wlp, skb); | ||
1880 | mutex_lock(&wss->mutex); | 1725 | mutex_lock(&wss->mutex); |
1881 | result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr); | 1726 | result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr); |
1882 | if (result < 0) { | 1727 | if (result < 0) { |
1883 | dev_err(dev, "WLP: unable to obtain values from C3 frame.\n"); | 1728 | dev_err(dev, "WLP: unable to obtain values from C3 frame.\n"); |
1884 | goto out; | 1729 | goto out; |
1885 | } | 1730 | } |
1886 | wlp_wss_uuid_print(buf, sizeof(buf), &wssid); | ||
1887 | d_printf(6, dev, "Received C3 frame with WSSID %s \n", buf); | ||
1888 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) | 1731 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)) |
1889 | && wss->state >= WLP_WSS_STATE_ACTIVE) { | 1732 | && wss->state >= WLP_WSS_STATE_ACTIVE) { |
1890 | d_printf(6, dev, "WSSID from C3 frame is known locally " | ||
1891 | "and is active\n"); | ||
1892 | result = wlp_eda_update_node(&wlp->eda, src, wss, | 1733 | result = wlp_eda_update_node(&wlp->eda, src, wss, |
1893 | (void *) virt_addr.data, tag, | 1734 | (void *) virt_addr.data, tag, |
1894 | WLP_WSS_CONNECTED); | 1735 | WLP_WSS_CONNECTED); |
@@ -1913,8 +1754,6 @@ void wlp_handle_c3_frame(struct work_struct *ws) | |||
1913 | } | 1754 | } |
1914 | } | 1755 | } |
1915 | } else { | 1756 | } else { |
1916 | d_printf(6, dev, "WSSID from C3 frame is not known locally " | ||
1917 | "or is not active\n"); | ||
1918 | /* Construct F0 frame */ | 1757 | /* Construct F0 frame */ |
1919 | result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); | 1758 | result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV); |
1920 | if (result < 0) { | 1759 | if (result < 0) { |
@@ -1923,8 +1762,6 @@ void wlp_handle_c3_frame(struct work_struct *ws) | |||
1923 | } | 1762 | } |
1924 | } | 1763 | } |
1925 | /* Send C4 frame */ | 1764 | /* Send C4 frame */ |
1926 | d_printf(6, dev, "Transmitting response (C4/F0) frame to %02x:%02x \n", | ||
1927 | src->data[1], src->data[0]); | ||
1928 | BUG_ON(wlp->xmit_frame == NULL); | 1765 | BUG_ON(wlp->xmit_frame == NULL); |
1929 | result = wlp->xmit_frame(wlp, resp, src); | 1766 | result = wlp->xmit_frame(wlp, resp, src); |
1930 | if (result < 0) { | 1767 | if (result < 0) { |
@@ -1939,8 +1776,6 @@ out: | |||
1939 | kfree_skb(frame_ctx->skb); | 1776 | kfree_skb(frame_ctx->skb); |
1940 | kfree(frame_ctx); | 1777 | kfree(frame_ctx); |
1941 | mutex_unlock(&wss->mutex); | 1778 | mutex_unlock(&wss->mutex); |
1942 | d_fnend(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n", | ||
1943 | wlp, skb); | ||
1944 | } | 1779 | } |
1945 | 1780 | ||
1946 | 1781 | ||
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c index 1bb9b1f97d47..0370399ff4bb 100644 --- a/drivers/uwb/wlp/sysfs.c +++ b/drivers/uwb/wlp/sysfs.c | |||
@@ -23,8 +23,8 @@ | |||
23 | * FIXME: Docs | 23 | * FIXME: Docs |
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | |||
27 | #include <linux/wlp.h> | 26 | #include <linux/wlp.h> |
27 | |||
28 | #include "wlp-internal.h" | 28 | #include "wlp-internal.h" |
29 | 29 | ||
30 | static | 30 | static |
diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c index c701bd1a2887..cd2035768b47 100644 --- a/drivers/uwb/wlp/txrx.c +++ b/drivers/uwb/wlp/txrx.c | |||
@@ -26,12 +26,10 @@ | |||
26 | 26 | ||
27 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
28 | #include <linux/wlp.h> | 28 | #include <linux/wlp.h> |
29 | #define D_LOCAL 5 | ||
30 | #include <linux/uwb/debug.h> | ||
31 | #include "wlp-internal.h" | ||
32 | 29 | ||
30 | #include "wlp-internal.h" | ||
33 | 31 | ||
34 | /** | 32 | /* |
35 | * Direct incoming association msg to correct parsing routine | 33 | * Direct incoming association msg to correct parsing routine |
36 | * | 34 | * |
37 | * We only expect D1, E1, C1, C3 messages as new. All other incoming | 35 | * We only expect D1, E1, C1, C3 messages as new. All other incoming |
@@ -48,35 +46,31 @@ void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | |||
48 | struct device *dev = &wlp->rc->uwb_dev.dev; | 46 | struct device *dev = &wlp->rc->uwb_dev.dev; |
49 | struct wlp_frame_assoc *assoc = (void *) skb->data; | 47 | struct wlp_frame_assoc *assoc = (void *) skb->data; |
50 | struct wlp_assoc_frame_ctx *frame_ctx; | 48 | struct wlp_assoc_frame_ctx *frame_ctx; |
51 | d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); | 49 | |
52 | frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC); | 50 | frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC); |
53 | if (frame_ctx == NULL) { | 51 | if (frame_ctx == NULL) { |
54 | dev_err(dev, "WLP: Unable to allocate memory for association " | 52 | dev_err(dev, "WLP: Unable to allocate memory for association " |
55 | "frame handling.\n"); | 53 | "frame handling.\n"); |
56 | kfree_skb(skb); | 54 | kfree_skb(skb); |
57 | goto out; | 55 | return; |
58 | } | 56 | } |
59 | frame_ctx->wlp = wlp; | 57 | frame_ctx->wlp = wlp; |
60 | frame_ctx->skb = skb; | 58 | frame_ctx->skb = skb; |
61 | frame_ctx->src = *src; | 59 | frame_ctx->src = *src; |
62 | switch (assoc->type) { | 60 | switch (assoc->type) { |
63 | case WLP_ASSOC_D1: | 61 | case WLP_ASSOC_D1: |
64 | d_printf(5, dev, "Received a D1 frame.\n"); | ||
65 | INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame); | 62 | INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame); |
66 | schedule_work(&frame_ctx->ws); | 63 | schedule_work(&frame_ctx->ws); |
67 | break; | 64 | break; |
68 | case WLP_ASSOC_E1: | 65 | case WLP_ASSOC_E1: |
69 | d_printf(5, dev, "Received a E1 frame. FIXME?\n"); | ||
70 | kfree_skb(skb); /* Temporary until we handle it */ | 66 | kfree_skb(skb); /* Temporary until we handle it */ |
71 | kfree(frame_ctx); /* Temporary until we handle it */ | 67 | kfree(frame_ctx); /* Temporary until we handle it */ |
72 | break; | 68 | break; |
73 | case WLP_ASSOC_C1: | 69 | case WLP_ASSOC_C1: |
74 | d_printf(5, dev, "Received a C1 frame.\n"); | ||
75 | INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame); | 70 | INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame); |
76 | schedule_work(&frame_ctx->ws); | 71 | schedule_work(&frame_ctx->ws); |
77 | break; | 72 | break; |
78 | case WLP_ASSOC_C3: | 73 | case WLP_ASSOC_C3: |
79 | d_printf(5, dev, "Received a C3 frame.\n"); | ||
80 | INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame); | 74 | INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame); |
81 | schedule_work(&frame_ctx->ws); | 75 | schedule_work(&frame_ctx->ws); |
82 | break; | 76 | break; |
@@ -87,11 +81,9 @@ void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | |||
87 | kfree(frame_ctx); | 81 | kfree(frame_ctx); |
88 | break; | 82 | break; |
89 | } | 83 | } |
90 | out: | ||
91 | d_fnend(5, dev, "wlp %p\n", wlp); | ||
92 | } | 84 | } |
93 | 85 | ||
94 | /** | 86 | /* |
95 | * Process incoming association frame | 87 | * Process incoming association frame |
96 | * | 88 | * |
97 | * Although it could be possible to deal with some incoming association | 89 | * Although it could be possible to deal with some incoming association |
@@ -112,7 +104,6 @@ void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | |||
112 | struct wlp_frame_assoc *assoc = (void *) skb->data; | 104 | struct wlp_frame_assoc *assoc = (void *) skb->data; |
113 | struct wlp_session *session = wlp->session; | 105 | struct wlp_session *session = wlp->session; |
114 | u8 version; | 106 | u8 version; |
115 | d_fnstart(5, dev, "wlp %p, skb %p\n", wlp, skb); | ||
116 | 107 | ||
117 | if (wlp_get_version(wlp, &assoc->version, &version, | 108 | if (wlp_get_version(wlp, &assoc->version, &version, |
118 | sizeof(assoc->version)) < 0) | 109 | sizeof(assoc->version)) < 0) |
@@ -150,14 +141,12 @@ void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb, | |||
150 | } else { | 141 | } else { |
151 | wlp_direct_assoc_frame(wlp, skb, src); | 142 | wlp_direct_assoc_frame(wlp, skb, src); |
152 | } | 143 | } |
153 | d_fnend(5, dev, "wlp %p\n", wlp); | ||
154 | return; | 144 | return; |
155 | error: | 145 | error: |
156 | kfree_skb(skb); | 146 | kfree_skb(skb); |
157 | d_fnend(5, dev, "wlp %p\n", wlp); | ||
158 | } | 147 | } |
159 | 148 | ||
160 | /** | 149 | /* |
161 | * Verify incoming frame is from connected neighbor, prep to pass to WLP client | 150 | * Verify incoming frame is from connected neighbor, prep to pass to WLP client |
162 | * | 151 | * |
163 | * Verification proceeds according to WLP 0.99 [7.3.1]. The source address | 152 | * Verification proceeds according to WLP 0.99 [7.3.1]. The source address |
@@ -176,7 +165,6 @@ int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, | |||
176 | struct wlp_eda_node eda_entry; | 165 | struct wlp_eda_node eda_entry; |
177 | struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data; | 166 | struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data; |
178 | 167 | ||
179 | d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb); | ||
180 | /*verify*/ | 168 | /*verify*/ |
181 | result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry); | 169 | result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry); |
182 | if (result < 0) { | 170 | if (result < 0) { |
@@ -207,11 +195,10 @@ int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb, | |||
207 | /*prep*/ | 195 | /*prep*/ |
208 | skb_pull(skb, sizeof(*hdr)); | 196 | skb_pull(skb, sizeof(*hdr)); |
209 | out: | 197 | out: |
210 | d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result); | ||
211 | return result; | 198 | return result; |
212 | } | 199 | } |
213 | 200 | ||
214 | /** | 201 | /* |
215 | * Receive a WLP frame from device | 202 | * Receive a WLP frame from device |
216 | * | 203 | * |
217 | * @returns: 1 if calling function should free the skb | 204 | * @returns: 1 if calling function should free the skb |
@@ -226,14 +213,12 @@ int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, | |||
226 | struct wlp_frame_hdr *hdr; | 213 | struct wlp_frame_hdr *hdr; |
227 | int result = 0; | 214 | int result = 0; |
228 | 215 | ||
229 | d_fnstart(6, dev, "skb (%p), len (%u)\n", skb, len); | ||
230 | if (len < sizeof(*hdr)) { | 216 | if (len < sizeof(*hdr)) { |
231 | dev_err(dev, "Not enough data to parse WLP header.\n"); | 217 | dev_err(dev, "Not enough data to parse WLP header.\n"); |
232 | result = -EINVAL; | 218 | result = -EINVAL; |
233 | goto out; | 219 | goto out; |
234 | } | 220 | } |
235 | hdr = ptr; | 221 | hdr = ptr; |
236 | d_dump(6, dev, hdr, sizeof(*hdr)); | ||
237 | if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) { | 222 | if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) { |
238 | dev_err(dev, "Not a WLP frame type.\n"); | 223 | dev_err(dev, "Not a WLP frame type.\n"); |
239 | result = -EINVAL; | 224 | result = -EINVAL; |
@@ -270,7 +255,6 @@ int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb, | |||
270 | "WLP header.\n"); | 255 | "WLP header.\n"); |
271 | goto out; | 256 | goto out; |
272 | } | 257 | } |
273 | d_printf(5, dev, "Association frame received.\n"); | ||
274 | wlp_receive_assoc_frame(wlp, skb, src); | 258 | wlp_receive_assoc_frame(wlp, skb, src); |
275 | break; | 259 | break; |
276 | default: | 260 | default: |
@@ -283,13 +267,12 @@ out: | |||
283 | kfree_skb(skb); | 267 | kfree_skb(skb); |
284 | result = 0; | 268 | result = 0; |
285 | } | 269 | } |
286 | d_fnend(6, dev, "skb (%p)\n", skb); | ||
287 | return result; | 270 | return result; |
288 | } | 271 | } |
289 | EXPORT_SYMBOL_GPL(wlp_receive_frame); | 272 | EXPORT_SYMBOL_GPL(wlp_receive_frame); |
290 | 273 | ||
291 | 274 | ||
292 | /** | 275 | /* |
293 | * Verify frame from network stack, prepare for further transmission | 276 | * Verify frame from network stack, prepare for further transmission |
294 | * | 277 | * |
295 | * @skb: the socket buffer that needs to be prepared for transmission (it | 278 | * @skb: the socket buffer that needs to be prepared for transmission (it |
@@ -343,9 +326,7 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, | |||
343 | int result = -EINVAL; | 326 | int result = -EINVAL; |
344 | struct ethhdr *eth_hdr = (void *) skb->data; | 327 | struct ethhdr *eth_hdr = (void *) skb->data; |
345 | 328 | ||
346 | d_fnstart(6, dev, "wlp (%p), skb (%p) \n", wlp, skb); | ||
347 | if (is_broadcast_ether_addr(eth_hdr->h_dest)) { | 329 | if (is_broadcast_ether_addr(eth_hdr->h_dest)) { |
348 | d_printf(6, dev, "WLP: handling broadcast frame. \n"); | ||
349 | result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); | 330 | result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb); |
350 | if (result < 0) { | 331 | if (result < 0) { |
351 | if (printk_ratelimit()) | 332 | if (printk_ratelimit()) |
@@ -357,7 +338,6 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, | |||
357 | result = 1; | 338 | result = 1; |
358 | /* Frame will be transmitted by WLP. */ | 339 | /* Frame will be transmitted by WLP. */ |
359 | } else { | 340 | } else { |
360 | d_printf(6, dev, "WLP: handling unicast frame. \n"); | ||
361 | result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst, | 341 | result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst, |
362 | wlp_wss_prep_hdr, skb); | 342 | wlp_wss_prep_hdr, skb); |
363 | if (unlikely(result < 0)) { | 343 | if (unlikely(result < 0)) { |
@@ -368,7 +348,6 @@ int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp, | |||
368 | } | 348 | } |
369 | } | 349 | } |
370 | out: | 350 | out: |
371 | d_fnend(6, dev, "wlp (%p), skb (%p). result = %d \n", wlp, skb, result); | ||
372 | return result; | 351 | return result; |
373 | } | 352 | } |
374 | EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame); | 353 | EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame); |
diff --git a/drivers/uwb/wlp/wlp-internal.h b/drivers/uwb/wlp/wlp-internal.h index 1c94fabfb1a7..3e8d5de7c5b9 100644 --- a/drivers/uwb/wlp/wlp-internal.h +++ b/drivers/uwb/wlp/wlp-internal.h | |||
@@ -42,10 +42,6 @@ enum wlp_wss_connect { | |||
42 | extern struct kobj_type wss_ktype; | 42 | extern struct kobj_type wss_ktype; |
43 | extern struct attribute_group wss_attr_group; | 43 | extern struct attribute_group wss_attr_group; |
44 | 44 | ||
45 | extern int uwb_rc_ie_add(struct uwb_rc *, const struct uwb_ie_hdr *, size_t); | ||
46 | extern int uwb_rc_ie_rm(struct uwb_rc *, enum uwb_ie); | ||
47 | |||
48 | |||
49 | /* This should be changed to a dynamic array where entries are sorted | 45 | /* This should be changed to a dynamic array where entries are sorted |
50 | * by eth_addr and search is done in a binary form | 46 | * by eth_addr and search is done in a binary form |
51 | * | 47 | * |
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c index 0799402e73fb..13db739c4e39 100644 --- a/drivers/uwb/wlp/wlp-lc.c +++ b/drivers/uwb/wlp/wlp-lc.c | |||
@@ -21,12 +21,9 @@ | |||
21 | * | 21 | * |
22 | * FIXME: docs | 22 | * FIXME: docs |
23 | */ | 23 | */ |
24 | |||
25 | #include <linux/wlp.h> | 24 | #include <linux/wlp.h> |
26 | #define D_LOCAL 6 | ||
27 | #include <linux/uwb/debug.h> | ||
28 | #include "wlp-internal.h" | ||
29 | 25 | ||
26 | #include "wlp-internal.h" | ||
30 | 27 | ||
31 | static | 28 | static |
32 | void wlp_neighbor_init(struct wlp_neighbor_e *neighbor) | 29 | void wlp_neighbor_init(struct wlp_neighbor_e *neighbor) |
@@ -61,11 +58,6 @@ int __wlp_alloc_device_info(struct wlp *wlp) | |||
61 | static | 58 | static |
62 | void __wlp_fill_device_info(struct wlp *wlp) | 59 | void __wlp_fill_device_info(struct wlp *wlp) |
63 | { | 60 | { |
64 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
65 | |||
66 | BUG_ON(wlp->fill_device_info == NULL); | ||
67 | d_printf(6, dev, "Retrieving device information " | ||
68 | "from device driver.\n"); | ||
69 | wlp->fill_device_info(wlp, wlp->dev_info); | 61 | wlp->fill_device_info(wlp, wlp->dev_info); |
70 | } | 62 | } |
71 | 63 | ||
@@ -127,7 +119,7 @@ void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor) | |||
127 | } | 119 | } |
128 | } | 120 | } |
129 | 121 | ||
130 | /** | 122 | /* |
131 | * Populate WLP neighborhood cache with neighbor information | 123 | * Populate WLP neighborhood cache with neighbor information |
132 | * | 124 | * |
133 | * A new neighbor is found. If it is discoverable then we add it to the | 125 | * A new neighbor is found. If it is discoverable then we add it to the |
@@ -141,10 +133,7 @@ int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev) | |||
141 | int discoverable; | 133 | int discoverable; |
142 | struct wlp_neighbor_e *neighbor; | 134 | struct wlp_neighbor_e *neighbor; |
143 | 135 | ||
144 | d_fnstart(6, &dev->dev, "uwb %p \n", dev); | 136 | /* |
145 | d_printf(6, &dev->dev, "Found neighbor device %02x:%02x \n", | ||
146 | dev->dev_addr.data[1], dev->dev_addr.data[0]); | ||
147 | /** | ||
148 | * FIXME: | 137 | * FIXME: |
149 | * Use contents of WLP IE found in beacon cache to determine if | 138 | * Use contents of WLP IE found in beacon cache to determine if |
150 | * neighbor is discoverable. | 139 | * neighbor is discoverable. |
@@ -167,7 +156,6 @@ int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev) | |||
167 | list_add(&neighbor->node, &wlp->neighbors); | 156 | list_add(&neighbor->node, &wlp->neighbors); |
168 | } | 157 | } |
169 | error_no_mem: | 158 | error_no_mem: |
170 | d_fnend(6, &dev->dev, "uwb %p, result = %d \n", dev, result); | ||
171 | return result; | 159 | return result; |
172 | } | 160 | } |
173 | 161 | ||
@@ -255,8 +243,6 @@ int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor, | |||
255 | dev_err(dev, "Unable to send D1 frame to neighbor " | 243 | dev_err(dev, "Unable to send D1 frame to neighbor " |
256 | "%02x:%02x (%d)\n", dev_addr->data[1], | 244 | "%02x:%02x (%d)\n", dev_addr->data[1], |
257 | dev_addr->data[0], result); | 245 | dev_addr->data[0], result); |
258 | d_printf(6, dev, "Add placeholders into buffer next to " | ||
259 | "neighbor information we have (dev address).\n"); | ||
260 | goto out; | 246 | goto out; |
261 | } | 247 | } |
262 | /* Create session, wait for response */ | 248 | /* Create session, wait for response */ |
@@ -284,8 +270,6 @@ int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor, | |||
284 | /* Parse message in session->data: it will be either D2 or F0 */ | 270 | /* Parse message in session->data: it will be either D2 or F0 */ |
285 | skb = session.data; | 271 | skb = session.data; |
286 | resp = (void *) skb->data; | 272 | resp = (void *) skb->data; |
287 | d_printf(6, dev, "Received response to D1 frame. \n"); | ||
288 | d_dump(6, dev, skb->data, skb->len > 72 ? 72 : skb->len); | ||
289 | 273 | ||
290 | if (resp->type == WLP_ASSOC_F0) { | 274 | if (resp->type == WLP_ASSOC_F0) { |
291 | result = wlp_parse_f0(wlp, skb); | 275 | result = wlp_parse_f0(wlp, skb); |
@@ -337,10 +321,9 @@ int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor, | |||
337 | struct device *dev = &wlp->rc->uwb_dev.dev; | 321 | struct device *dev = &wlp->rc->uwb_dev.dev; |
338 | char buf[WLP_WSS_UUID_STRSIZE]; | 322 | char buf[WLP_WSS_UUID_STRSIZE]; |
339 | struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr; | 323 | struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr; |
324 | |||
340 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | 325 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); |
341 | d_fnstart(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", | 326 | |
342 | wlp, neighbor, wss, wssid, buf); | ||
343 | d_printf(6, dev, "Complete me.\n"); | ||
344 | result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid); | 327 | result = wlp_d1d2_exchange(wlp, neighbor, wss, wssid); |
345 | if (result < 0) { | 328 | if (result < 0) { |
346 | dev_err(dev, "WLP: D1/D2 message exchange for enrollment " | 329 | dev_err(dev, "WLP: D1/D2 message exchange for enrollment " |
@@ -360,13 +343,10 @@ int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor, | |||
360 | goto error; | 343 | goto error; |
361 | } else { | 344 | } else { |
362 | wss->state = WLP_WSS_STATE_ENROLLED; | 345 | wss->state = WLP_WSS_STATE_ENROLLED; |
363 | d_printf(2, dev, "WLP: Success Enrollment into unsecure WSS " | 346 | dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS " |
364 | "%s using neighbor %02x:%02x. \n", buf, | 347 | "%s using neighbor %02x:%02x. \n", |
365 | dev_addr->data[1], dev_addr->data[0]); | 348 | buf, dev_addr->data[1], dev_addr->data[0]); |
366 | } | 349 | } |
367 | |||
368 | d_fnend(6, dev, "wlp %p, neighbor %p, wss %p, wssid %p (%s)\n", | ||
369 | wlp, neighbor, wss, wssid, buf); | ||
370 | out: | 350 | out: |
371 | return result; | 351 | return result; |
372 | error: | 352 | error: |
@@ -449,7 +429,6 @@ ssize_t wlp_discover(struct wlp *wlp) | |||
449 | int result = 0; | 429 | int result = 0; |
450 | struct device *dev = &wlp->rc->uwb_dev.dev; | 430 | struct device *dev = &wlp->rc->uwb_dev.dev; |
451 | 431 | ||
452 | d_fnstart(6, dev, "wlp %p \n", wlp); | ||
453 | mutex_lock(&wlp->nbmutex); | 432 | mutex_lock(&wlp->nbmutex); |
454 | /* Clear current neighborhood cache. */ | 433 | /* Clear current neighborhood cache. */ |
455 | __wlp_neighbors_release(wlp); | 434 | __wlp_neighbors_release(wlp); |
@@ -469,7 +448,6 @@ ssize_t wlp_discover(struct wlp *wlp) | |||
469 | } | 448 | } |
470 | error_dev_for_each: | 449 | error_dev_for_each: |
471 | mutex_unlock(&wlp->nbmutex); | 450 | mutex_unlock(&wlp->nbmutex); |
472 | d_fnend(6, dev, "wlp %p \n", wlp); | ||
473 | return result; | 451 | return result; |
474 | } | 452 | } |
475 | 453 | ||
@@ -492,9 +470,6 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, | |||
492 | int result; | 470 | int result; |
493 | switch (event) { | 471 | switch (event) { |
494 | case UWB_NOTIF_ONAIR: | 472 | case UWB_NOTIF_ONAIR: |
495 | d_printf(6, dev, "UWB device %02x:%02x is onair\n", | ||
496 | uwb_dev->dev_addr.data[1], | ||
497 | uwb_dev->dev_addr.data[0]); | ||
498 | result = wlp_eda_create_node(&wlp->eda, | 473 | result = wlp_eda_create_node(&wlp->eda, |
499 | uwb_dev->mac_addr.data, | 474 | uwb_dev->mac_addr.data, |
500 | &uwb_dev->dev_addr); | 475 | &uwb_dev->dev_addr); |
@@ -505,18 +480,11 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, | |||
505 | uwb_dev->dev_addr.data[0]); | 480 | uwb_dev->dev_addr.data[0]); |
506 | break; | 481 | break; |
507 | case UWB_NOTIF_OFFAIR: | 482 | case UWB_NOTIF_OFFAIR: |
508 | d_printf(6, dev, "UWB device %02x:%02x is offair\n", | ||
509 | uwb_dev->dev_addr.data[1], | ||
510 | uwb_dev->dev_addr.data[0]); | ||
511 | wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr); | 483 | wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr); |
512 | mutex_lock(&wlp->nbmutex); | 484 | mutex_lock(&wlp->nbmutex); |
513 | list_for_each_entry_safe(neighbor, next, &wlp->neighbors, | 485 | list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) { |
514 | node) { | 486 | if (neighbor->uwb_dev == uwb_dev) |
515 | if (neighbor->uwb_dev == uwb_dev) { | ||
516 | d_printf(6, dev, "Removing device from " | ||
517 | "neighborhood.\n"); | ||
518 | __wlp_neighbor_release(neighbor); | 487 | __wlp_neighbor_release(neighbor); |
519 | } | ||
520 | } | 488 | } |
521 | mutex_unlock(&wlp->nbmutex); | 489 | mutex_unlock(&wlp->nbmutex); |
522 | break; | 490 | break; |
@@ -526,38 +494,47 @@ void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev, | |||
526 | } | 494 | } |
527 | } | 495 | } |
528 | 496 | ||
529 | int wlp_setup(struct wlp *wlp, struct uwb_rc *rc) | 497 | static void wlp_channel_changed(struct uwb_pal *pal, int channel) |
498 | { | ||
499 | struct wlp *wlp = container_of(pal, struct wlp, pal); | ||
500 | |||
501 | if (channel < 0) | ||
502 | netif_carrier_off(wlp->ndev); | ||
503 | else | ||
504 | netif_carrier_on(wlp->ndev); | ||
505 | } | ||
506 | |||
507 | int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev) | ||
530 | { | 508 | { |
531 | struct device *dev = &rc->uwb_dev.dev; | ||
532 | int result; | 509 | int result; |
533 | 510 | ||
534 | d_fnstart(6, dev, "wlp %p\n", wlp); | ||
535 | BUG_ON(wlp->fill_device_info == NULL); | 511 | BUG_ON(wlp->fill_device_info == NULL); |
536 | BUG_ON(wlp->xmit_frame == NULL); | 512 | BUG_ON(wlp->xmit_frame == NULL); |
537 | BUG_ON(wlp->stop_queue == NULL); | 513 | BUG_ON(wlp->stop_queue == NULL); |
538 | BUG_ON(wlp->start_queue == NULL); | 514 | BUG_ON(wlp->start_queue == NULL); |
515 | |||
539 | wlp->rc = rc; | 516 | wlp->rc = rc; |
517 | wlp->ndev = ndev; | ||
540 | wlp_eda_init(&wlp->eda);/* Set up address cache */ | 518 | wlp_eda_init(&wlp->eda);/* Set up address cache */ |
541 | wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; | 519 | wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb; |
542 | wlp->uwb_notifs_handler.data = wlp; | 520 | wlp->uwb_notifs_handler.data = wlp; |
543 | uwb_notifs_register(rc, &wlp->uwb_notifs_handler); | 521 | uwb_notifs_register(rc, &wlp->uwb_notifs_handler); |
544 | 522 | ||
545 | uwb_pal_init(&wlp->pal); | 523 | uwb_pal_init(&wlp->pal); |
546 | result = uwb_pal_register(rc, &wlp->pal); | 524 | wlp->pal.rc = rc; |
525 | wlp->pal.channel_changed = wlp_channel_changed; | ||
526 | result = uwb_pal_register(&wlp->pal); | ||
547 | if (result < 0) | 527 | if (result < 0) |
548 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); | 528 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); |
549 | 529 | ||
550 | d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result); | ||
551 | return result; | 530 | return result; |
552 | } | 531 | } |
553 | EXPORT_SYMBOL_GPL(wlp_setup); | 532 | EXPORT_SYMBOL_GPL(wlp_setup); |
554 | 533 | ||
555 | void wlp_remove(struct wlp *wlp) | 534 | void wlp_remove(struct wlp *wlp) |
556 | { | 535 | { |
557 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
558 | d_fnstart(6, dev, "wlp %p\n", wlp); | ||
559 | wlp_neighbors_release(wlp); | 536 | wlp_neighbors_release(wlp); |
560 | uwb_pal_unregister(wlp->rc, &wlp->pal); | 537 | uwb_pal_unregister(&wlp->pal); |
561 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); | 538 | uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler); |
562 | wlp_eda_release(&wlp->eda); | 539 | wlp_eda_release(&wlp->eda); |
563 | mutex_lock(&wlp->mutex); | 540 | mutex_lock(&wlp->mutex); |
@@ -565,9 +542,6 @@ void wlp_remove(struct wlp *wlp) | |||
565 | kfree(wlp->dev_info); | 542 | kfree(wlp->dev_info); |
566 | mutex_unlock(&wlp->mutex); | 543 | mutex_unlock(&wlp->mutex); |
567 | wlp->rc = NULL; | 544 | wlp->rc = NULL; |
568 | /* We have to use NULL here because this function can be called | ||
569 | * when the device disappeared. */ | ||
570 | d_fnend(6, NULL, "wlp %p\n", wlp); | ||
571 | } | 545 | } |
572 | EXPORT_SYMBOL_GPL(wlp_remove); | 546 | EXPORT_SYMBOL_GPL(wlp_remove); |
573 | 547 | ||
diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c index 96b18c9bd6e9..5913c7a5d922 100644 --- a/drivers/uwb/wlp/wss-lc.c +++ b/drivers/uwb/wlp/wss-lc.c | |||
@@ -43,14 +43,11 @@ | |||
43 | * wlp_wss_release() | 43 | * wlp_wss_release() |
44 | * wlp_wss_reset() | 44 | * wlp_wss_reset() |
45 | */ | 45 | */ |
46 | |||
47 | #include <linux/etherdevice.h> /* for is_valid_ether_addr */ | 46 | #include <linux/etherdevice.h> /* for is_valid_ether_addr */ |
48 | #include <linux/skbuff.h> | 47 | #include <linux/skbuff.h> |
49 | #include <linux/wlp.h> | 48 | #include <linux/wlp.h> |
50 | #define D_LOCAL 5 | ||
51 | #include <linux/uwb/debug.h> | ||
52 | #include "wlp-internal.h" | ||
53 | 49 | ||
50 | #include "wlp-internal.h" | ||
54 | 51 | ||
55 | size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key) | 52 | size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key) |
56 | { | 53 | { |
@@ -116,9 +113,6 @@ struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss) | |||
116 | */ | 113 | */ |
117 | void wlp_wss_reset(struct wlp_wss *wss) | 114 | void wlp_wss_reset(struct wlp_wss *wss) |
118 | { | 115 | { |
119 | struct wlp *wlp = container_of(wss, struct wlp, wss); | ||
120 | struct device *dev = &wlp->rc->uwb_dev.dev; | ||
121 | d_fnstart(5, dev, "wss (%p) \n", wss); | ||
122 | memset(&wss->wssid, 0, sizeof(wss->wssid)); | 116 | memset(&wss->wssid, 0, sizeof(wss->wssid)); |
123 | wss->hash = 0; | 117 | wss->hash = 0; |
124 | memset(&wss->name[0], 0, sizeof(wss->name)); | 118 | memset(&wss->name[0], 0, sizeof(wss->name)); |
@@ -127,7 +121,6 @@ void wlp_wss_reset(struct wlp_wss *wss) | |||
127 | memset(&wss->master_key[0], 0, sizeof(wss->master_key)); | 121 | memset(&wss->master_key[0], 0, sizeof(wss->master_key)); |
128 | wss->tag = 0; | 122 | wss->tag = 0; |
129 | wss->state = WLP_WSS_STATE_NONE; | 123 | wss->state = WLP_WSS_STATE_NONE; |
130 | d_fnend(5, dev, "wss (%p) \n", wss); | ||
131 | } | 124 | } |
132 | 125 | ||
133 | /** | 126 | /** |
@@ -145,7 +138,6 @@ int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str) | |||
145 | struct device *dev = &wlp->rc->uwb_dev.dev; | 138 | struct device *dev = &wlp->rc->uwb_dev.dev; |
146 | int result; | 139 | int result; |
147 | 140 | ||
148 | d_fnstart(5, dev, "wss (%p), wssid: %s\n", wss, wssid_str); | ||
149 | result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str); | 141 | result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str); |
150 | if (result < 0) | 142 | if (result < 0) |
151 | return result; | 143 | return result; |
@@ -162,7 +154,6 @@ int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str) | |||
162 | result); | 154 | result); |
163 | goto error_sysfs_create_group; | 155 | goto error_sysfs_create_group; |
164 | } | 156 | } |
165 | d_fnend(5, dev, "Completed. result = %d \n", result); | ||
166 | return 0; | 157 | return 0; |
167 | error_sysfs_create_group: | 158 | error_sysfs_create_group: |
168 | 159 | ||
@@ -214,22 +205,14 @@ int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
214 | struct wlp *wlp = container_of(wss, struct wlp, wss); | 205 | struct wlp *wlp = container_of(wss, struct wlp, wss); |
215 | struct device *dev = &wlp->rc->uwb_dev.dev; | 206 | struct device *dev = &wlp->rc->uwb_dev.dev; |
216 | struct wlp_neighbor_e *neighbor; | 207 | struct wlp_neighbor_e *neighbor; |
217 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
218 | int result = -ENXIO; | 208 | int result = -ENXIO; |
219 | struct uwb_dev_addr *dev_addr; | 209 | struct uwb_dev_addr *dev_addr; |
220 | 210 | ||
221 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | ||
222 | d_fnstart(5, dev, "wss %p, wssid %s, registrar %02x:%02x \n", | ||
223 | wss, buf, dest->data[1], dest->data[0]); | ||
224 | mutex_lock(&wlp->nbmutex); | 211 | mutex_lock(&wlp->nbmutex); |
225 | list_for_each_entry(neighbor, &wlp->neighbors, node) { | 212 | list_for_each_entry(neighbor, &wlp->neighbors, node) { |
226 | dev_addr = &neighbor->uwb_dev->dev_addr; | 213 | dev_addr = &neighbor->uwb_dev->dev_addr; |
227 | if (!memcmp(dest, dev_addr, sizeof(*dest))) { | 214 | if (!memcmp(dest, dev_addr, sizeof(*dest))) { |
228 | d_printf(5, dev, "Neighbor %02x:%02x is valid, " | 215 | result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid); |
229 | "enrolling. \n", | ||
230 | dev_addr->data[1], dev_addr->data[0]); | ||
231 | result = wlp_enroll_neighbor(wlp, neighbor, wss, | ||
232 | wssid); | ||
233 | break; | 216 | break; |
234 | } | 217 | } |
235 | } | 218 | } |
@@ -237,8 +220,6 @@ int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
237 | dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n", | 220 | dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n", |
238 | dest->data[1], dest->data[0]); | 221 | dest->data[1], dest->data[0]); |
239 | mutex_unlock(&wlp->nbmutex); | 222 | mutex_unlock(&wlp->nbmutex); |
240 | d_fnend(5, dev, "wss %p, wssid %s, registrar %02x:%02x, result %d \n", | ||
241 | wss, buf, dest->data[1], dest->data[0], result); | ||
242 | return result; | 223 | return result; |
243 | } | 224 | } |
244 | 225 | ||
@@ -260,16 +241,11 @@ int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid) | |||
260 | char buf[WLP_WSS_UUID_STRSIZE]; | 241 | char buf[WLP_WSS_UUID_STRSIZE]; |
261 | int result = -ENXIO; | 242 | int result = -ENXIO; |
262 | 243 | ||
263 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | 244 | |
264 | d_fnstart(5, dev, "wss %p, wssid %s \n", wss, buf); | ||
265 | mutex_lock(&wlp->nbmutex); | 245 | mutex_lock(&wlp->nbmutex); |
266 | list_for_each_entry(neighbor, &wlp->neighbors, node) { | 246 | list_for_each_entry(neighbor, &wlp->neighbors, node) { |
267 | list_for_each_entry(wssid_e, &neighbor->wssid, node) { | 247 | list_for_each_entry(wssid_e, &neighbor->wssid, node) { |
268 | if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) { | 248 | if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) { |
269 | d_printf(5, dev, "Found WSSID %s in neighbor " | ||
270 | "%02x:%02x cache. \n", buf, | ||
271 | neighbor->uwb_dev->dev_addr.data[1], | ||
272 | neighbor->uwb_dev->dev_addr.data[0]); | ||
273 | result = wlp_enroll_neighbor(wlp, neighbor, | 249 | result = wlp_enroll_neighbor(wlp, neighbor, |
274 | wss, wssid); | 250 | wss, wssid); |
275 | if (result == 0) /* enrollment success */ | 251 | if (result == 0) /* enrollment success */ |
@@ -279,10 +255,11 @@ int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid) | |||
279 | } | 255 | } |
280 | } | 256 | } |
281 | out: | 257 | out: |
282 | if (result == -ENXIO) | 258 | if (result == -ENXIO) { |
259 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | ||
283 | dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf); | 260 | dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf); |
261 | } | ||
284 | mutex_unlock(&wlp->nbmutex); | 262 | mutex_unlock(&wlp->nbmutex); |
285 | d_fnend(5, dev, "wss %p, wssid %s, result %d \n", wss, buf, result); | ||
286 | return result; | 263 | return result; |
287 | } | 264 | } |
288 | 265 | ||
@@ -307,27 +284,22 @@ int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
307 | struct uwb_dev_addr bcast = {.data = {0xff, 0xff} }; | 284 | struct uwb_dev_addr bcast = {.data = {0xff, 0xff} }; |
308 | 285 | ||
309 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | 286 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); |
287 | |||
310 | if (wss->state != WLP_WSS_STATE_NONE) { | 288 | if (wss->state != WLP_WSS_STATE_NONE) { |
311 | dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf); | 289 | dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf); |
312 | result = -EEXIST; | 290 | result = -EEXIST; |
313 | goto error; | 291 | goto error; |
314 | } | 292 | } |
315 | if (!memcmp(&bcast, devaddr, sizeof(bcast))) { | 293 | if (!memcmp(&bcast, devaddr, sizeof(bcast))) |
316 | d_printf(5, dev, "Request to enroll in discovered WSS " | ||
317 | "with WSSID %s \n", buf); | ||
318 | result = wlp_wss_enroll_discovered(wss, wssid); | 294 | result = wlp_wss_enroll_discovered(wss, wssid); |
319 | } else { | 295 | else |
320 | d_printf(5, dev, "Request to enroll in WSSID %s with " | ||
321 | "registrar %02x:%02x\n", buf, devaddr->data[1], | ||
322 | devaddr->data[0]); | ||
323 | result = wlp_wss_enroll_target(wss, wssid, devaddr); | 296 | result = wlp_wss_enroll_target(wss, wssid, devaddr); |
324 | } | ||
325 | if (result < 0) { | 297 | if (result < 0) { |
326 | dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n", | 298 | dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n", |
327 | buf, result); | 299 | buf, result); |
328 | goto error; | 300 | goto error; |
329 | } | 301 | } |
330 | d_printf(2, dev, "Successfully enrolled into WSS %s \n", buf); | 302 | dev_dbg(dev, "Successfully enrolled into WSS %s \n", buf); |
331 | result = wlp_wss_sysfs_add(wss, buf); | 303 | result = wlp_wss_sysfs_add(wss, buf); |
332 | if (result < 0) { | 304 | if (result < 0) { |
333 | dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n"); | 305 | dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n"); |
@@ -363,7 +335,6 @@ int wlp_wss_activate(struct wlp_wss *wss) | |||
363 | u8 hash; /* only include one hash */ | 335 | u8 hash; /* only include one hash */ |
364 | } ie_data; | 336 | } ie_data; |
365 | 337 | ||
366 | d_fnstart(5, dev, "Activating WSS %p. \n", wss); | ||
367 | BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED); | 338 | BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED); |
368 | wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid); | 339 | wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid); |
369 | wss->tag = wss->hash; | 340 | wss->tag = wss->hash; |
@@ -382,7 +353,6 @@ int wlp_wss_activate(struct wlp_wss *wss) | |||
382 | wss->state = WLP_WSS_STATE_ACTIVE; | 353 | wss->state = WLP_WSS_STATE_ACTIVE; |
383 | result = 0; | 354 | result = 0; |
384 | error_wlp_ie: | 355 | error_wlp_ie: |
385 | d_fnend(5, dev, "Activating WSS %p, result = %d \n", wss, result); | ||
386 | return result; | 356 | return result; |
387 | } | 357 | } |
388 | 358 | ||
@@ -405,7 +375,6 @@ int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
405 | int result = 0; | 375 | int result = 0; |
406 | char buf[WLP_WSS_UUID_STRSIZE]; | 376 | char buf[WLP_WSS_UUID_STRSIZE]; |
407 | 377 | ||
408 | d_fnstart(5, dev, "Enrollment and activation requested. \n"); | ||
409 | mutex_lock(&wss->mutex); | 378 | mutex_lock(&wss->mutex); |
410 | result = wlp_wss_enroll(wss, wssid, devaddr); | 379 | result = wlp_wss_enroll(wss, wssid, devaddr); |
411 | if (result < 0) { | 380 | if (result < 0) { |
@@ -424,7 +393,6 @@ int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
424 | error_activate: | 393 | error_activate: |
425 | error_enroll: | 394 | error_enroll: |
426 | mutex_unlock(&wss->mutex); | 395 | mutex_unlock(&wss->mutex); |
427 | d_fnend(5, dev, "Completed. result = %d \n", result); | ||
428 | return result; | 396 | return result; |
429 | } | 397 | } |
430 | 398 | ||
@@ -447,11 +415,9 @@ int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
447 | struct device *dev = &wlp->rc->uwb_dev.dev; | 415 | struct device *dev = &wlp->rc->uwb_dev.dev; |
448 | int result = 0; | 416 | int result = 0; |
449 | char buf[WLP_WSS_UUID_STRSIZE]; | 417 | char buf[WLP_WSS_UUID_STRSIZE]; |
450 | d_fnstart(5, dev, "Request to create new WSS.\n"); | 418 | |
451 | result = wlp_wss_uuid_print(buf, sizeof(buf), wssid); | 419 | result = wlp_wss_uuid_print(buf, sizeof(buf), wssid); |
452 | d_printf(5, dev, "Request to create WSS: WSSID=%s, name=%s, " | 420 | |
453 | "sec_status=%u, accepting enrollment=%u \n", | ||
454 | buf, name, sec_status, accept); | ||
455 | if (!mutex_trylock(&wss->mutex)) { | 421 | if (!mutex_trylock(&wss->mutex)) { |
456 | dev_err(dev, "WLP: WLP association session in progress.\n"); | 422 | dev_err(dev, "WLP: WLP association session in progress.\n"); |
457 | return -EBUSY; | 423 | return -EBUSY; |
@@ -498,7 +464,6 @@ int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid, | |||
498 | result = 0; | 464 | result = 0; |
499 | out: | 465 | out: |
500 | mutex_unlock(&wss->mutex); | 466 | mutex_unlock(&wss->mutex); |
501 | d_fnend(5, dev, "Completed. result = %d \n", result); | ||
502 | return result; | 467 | return result; |
503 | } | 468 | } |
504 | 469 | ||
@@ -520,16 +485,12 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, | |||
520 | { | 485 | { |
521 | int result = 0; | 486 | int result = 0; |
522 | struct device *dev = &wlp->rc->uwb_dev.dev; | 487 | struct device *dev = &wlp->rc->uwb_dev.dev; |
523 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
524 | DECLARE_COMPLETION_ONSTACK(completion); | 488 | DECLARE_COMPLETION_ONSTACK(completion); |
525 | struct wlp_session session; | 489 | struct wlp_session session; |
526 | struct sk_buff *skb; | 490 | struct sk_buff *skb; |
527 | struct wlp_frame_assoc *resp; | 491 | struct wlp_frame_assoc *resp; |
528 | struct wlp_uuid wssid; | 492 | struct wlp_uuid wssid; |
529 | 493 | ||
530 | wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); | ||
531 | d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", | ||
532 | wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); | ||
533 | mutex_lock(&wlp->mutex); | 494 | mutex_lock(&wlp->mutex); |
534 | /* Send C1 association frame */ | 495 | /* Send C1 association frame */ |
535 | result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1); | 496 | result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1); |
@@ -565,8 +526,6 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, | |||
565 | /* Parse message in session->data: it will be either C2 or F0 */ | 526 | /* Parse message in session->data: it will be either C2 or F0 */ |
566 | skb = session.data; | 527 | skb = session.data; |
567 | resp = (void *) skb->data; | 528 | resp = (void *) skb->data; |
568 | d_printf(5, dev, "Received response to C1 frame. \n"); | ||
569 | d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); | ||
570 | if (resp->type == WLP_ASSOC_F0) { | 529 | if (resp->type == WLP_ASSOC_F0) { |
571 | result = wlp_parse_f0(wlp, skb); | 530 | result = wlp_parse_f0(wlp, skb); |
572 | if (result < 0) | 531 | if (result < 0) |
@@ -584,11 +543,9 @@ int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss, | |||
584 | result = 0; | 543 | result = 0; |
585 | goto error_resp_parse; | 544 | goto error_resp_parse; |
586 | } | 545 | } |
587 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))) { | 546 | if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))) |
588 | d_printf(5, dev, "WSSID in C2 frame matches local " | ||
589 | "active WSS.\n"); | ||
590 | result = 1; | 547 | result = 1; |
591 | } else { | 548 | else { |
592 | dev_err(dev, "WLP: Received a C2 frame without matching " | 549 | dev_err(dev, "WLP: Received a C2 frame without matching " |
593 | "WSSID.\n"); | 550 | "WSSID.\n"); |
594 | result = 0; | 551 | result = 0; |
@@ -598,8 +555,6 @@ error_resp_parse: | |||
598 | out: | 555 | out: |
599 | wlp->session = NULL; | 556 | wlp->session = NULL; |
600 | mutex_unlock(&wlp->mutex); | 557 | mutex_unlock(&wlp->mutex); |
601 | d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", | ||
602 | wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); | ||
603 | return result; | 558 | return result; |
604 | } | 559 | } |
605 | 560 | ||
@@ -620,16 +575,8 @@ int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss, | |||
620 | { | 575 | { |
621 | struct device *dev = &wlp->rc->uwb_dev.dev; | 576 | struct device *dev = &wlp->rc->uwb_dev.dev; |
622 | int result = 0; | 577 | int result = 0; |
623 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
624 | wlp_wss_uuid_print(buf, sizeof(buf), wssid); | ||
625 | d_fnstart(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " | ||
626 | "%02x:%02x:%02x:%02x:%02x:%02x \n", wlp, wss, buf, *tag, | ||
627 | virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], | ||
628 | virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]); | ||
629 | 578 | ||
630 | if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) { | 579 | if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) { |
631 | d_printf(5, dev, "WSSID from neighbor frame matches local " | ||
632 | "active WSS.\n"); | ||
633 | /* Update EDA cache */ | 580 | /* Update EDA cache */ |
634 | result = wlp_eda_update_node(&wlp->eda, dev_addr, wss, | 581 | result = wlp_eda_update_node(&wlp->eda, dev_addr, wss, |
635 | (void *) virt_addr->data, *tag, | 582 | (void *) virt_addr->data, *tag, |
@@ -638,18 +585,9 @@ int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss, | |||
638 | dev_err(dev, "WLP: Unable to update EDA cache " | 585 | dev_err(dev, "WLP: Unable to update EDA cache " |
639 | "with new connected neighbor information.\n"); | 586 | "with new connected neighbor information.\n"); |
640 | } else { | 587 | } else { |
641 | dev_err(dev, "WLP: Neighbor does not have matching " | 588 | dev_err(dev, "WLP: Neighbor does not have matching WSSID.\n"); |
642 | "WSSID.\n"); | ||
643 | result = -EINVAL; | 589 | result = -EINVAL; |
644 | } | 590 | } |
645 | |||
646 | d_fnend(5, dev, "wlp %p, wss %p, wssid %s, tag %u, virtual " | ||
647 | "%02x:%02x:%02x:%02x:%02x:%02x, result = %d \n", | ||
648 | wlp, wss, buf, *tag, | ||
649 | virt_addr->data[0], virt_addr->data[1], virt_addr->data[2], | ||
650 | virt_addr->data[3], virt_addr->data[4], virt_addr->data[5], | ||
651 | result); | ||
652 | |||
653 | return result; | 591 | return result; |
654 | } | 592 | } |
655 | 593 | ||
@@ -665,7 +603,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, | |||
665 | { | 603 | { |
666 | int result; | 604 | int result; |
667 | struct device *dev = &wlp->rc->uwb_dev.dev; | 605 | struct device *dev = &wlp->rc->uwb_dev.dev; |
668 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
669 | struct wlp_uuid wssid; | 606 | struct wlp_uuid wssid; |
670 | u8 tag; | 607 | u8 tag; |
671 | struct uwb_mac_addr virt_addr; | 608 | struct uwb_mac_addr virt_addr; |
@@ -674,9 +611,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, | |||
674 | struct wlp_frame_assoc *resp; | 611 | struct wlp_frame_assoc *resp; |
675 | struct sk_buff *skb; | 612 | struct sk_buff *skb; |
676 | 613 | ||
677 | wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); | ||
678 | d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", | ||
679 | wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); | ||
680 | mutex_lock(&wlp->mutex); | 614 | mutex_lock(&wlp->mutex); |
681 | /* Send C3 association frame */ | 615 | /* Send C3 association frame */ |
682 | result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3); | 616 | result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3); |
@@ -711,8 +645,6 @@ int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss, | |||
711 | /* Parse message in session->data: it will be either C4 or F0 */ | 645 | /* Parse message in session->data: it will be either C4 or F0 */ |
712 | skb = session.data; | 646 | skb = session.data; |
713 | resp = (void *) skb->data; | 647 | resp = (void *) skb->data; |
714 | d_printf(5, dev, "Received response to C3 frame. \n"); | ||
715 | d_dump(5, dev, skb->data, skb->len > 72 ? 72 : skb->len); | ||
716 | if (resp->type == WLP_ASSOC_F0) { | 648 | if (resp->type == WLP_ASSOC_F0) { |
717 | result = wlp_parse_f0(wlp, skb); | 649 | result = wlp_parse_f0(wlp, skb); |
718 | if (result < 0) | 650 | if (result < 0) |
@@ -744,8 +676,6 @@ out: | |||
744 | WLP_WSS_CONNECT_FAILED); | 676 | WLP_WSS_CONNECT_FAILED); |
745 | wlp->session = NULL; | 677 | wlp->session = NULL; |
746 | mutex_unlock(&wlp->mutex); | 678 | mutex_unlock(&wlp->mutex); |
747 | d_fnend(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", | ||
748 | wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); | ||
749 | return result; | 679 | return result; |
750 | } | 680 | } |
751 | 681 | ||
@@ -780,12 +710,8 @@ void wlp_wss_connect_send(struct work_struct *ws) | |||
780 | struct wlp_wss *wss = &wlp->wss; | 710 | struct wlp_wss *wss = &wlp->wss; |
781 | int result; | 711 | int result; |
782 | struct device *dev = &wlp->rc->uwb_dev.dev; | 712 | struct device *dev = &wlp->rc->uwb_dev.dev; |
783 | char buf[WLP_WSS_UUID_STRSIZE]; | ||
784 | 713 | ||
785 | mutex_lock(&wss->mutex); | 714 | mutex_lock(&wss->mutex); |
786 | wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid); | ||
787 | d_fnstart(5, dev, "wlp %p, wss %p (wssid %s), neighbor %02x:%02x \n", | ||
788 | wlp, wss, buf, dev_addr->data[1], dev_addr->data[0]); | ||
789 | if (wss->state < WLP_WSS_STATE_ACTIVE) { | 715 | if (wss->state < WLP_WSS_STATE_ACTIVE) { |
790 | if (printk_ratelimit()) | 716 | if (printk_ratelimit()) |
791 | dev_err(dev, "WLP: Attempting to connect with " | 717 | dev_err(dev, "WLP: Attempting to connect with " |
@@ -836,7 +762,6 @@ out: | |||
836 | BUG_ON(wlp->start_queue == NULL); | 762 | BUG_ON(wlp->start_queue == NULL); |
837 | wlp->start_queue(wlp); | 763 | wlp->start_queue(wlp); |
838 | mutex_unlock(&wss->mutex); | 764 | mutex_unlock(&wss->mutex); |
839 | d_fnend(5, dev, "wlp %p, wss %p (wssid %s)\n", wlp, wss, buf); | ||
840 | } | 765 | } |
841 | 766 | ||
842 | /** | 767 | /** |
@@ -855,7 +780,6 @@ int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
855 | struct sk_buff *skb = _skb; | 780 | struct sk_buff *skb = _skb; |
856 | struct wlp_frame_std_abbrv_hdr *std_hdr; | 781 | struct wlp_frame_std_abbrv_hdr *std_hdr; |
857 | 782 | ||
858 | d_fnstart(6, dev, "wlp %p \n", wlp); | ||
859 | if (eda_entry->state == WLP_WSS_CONNECTED) { | 783 | if (eda_entry->state == WLP_WSS_CONNECTED) { |
860 | /* Add WLP header */ | 784 | /* Add WLP header */ |
861 | BUG_ON(skb_headroom(skb) < sizeof(*std_hdr)); | 785 | BUG_ON(skb_headroom(skb) < sizeof(*std_hdr)); |
@@ -873,7 +797,6 @@ int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
873 | dev_addr->data[0]); | 797 | dev_addr->data[0]); |
874 | result = -EINVAL; | 798 | result = -EINVAL; |
875 | } | 799 | } |
876 | d_fnend(6, dev, "wlp %p \n", wlp); | ||
877 | return result; | 800 | return result; |
878 | } | 801 | } |
879 | 802 | ||
@@ -893,16 +816,9 @@ int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
893 | { | 816 | { |
894 | int result = 0; | 817 | int result = 0; |
895 | struct device *dev = &wlp->rc->uwb_dev.dev; | 818 | struct device *dev = &wlp->rc->uwb_dev.dev; |
896 | struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; | ||
897 | unsigned char *eth_addr = eda_entry->eth_addr; | ||
898 | struct sk_buff *skb = _skb; | 819 | struct sk_buff *skb = _skb; |
899 | struct wlp_assoc_conn_ctx *conn_ctx; | 820 | struct wlp_assoc_conn_ctx *conn_ctx; |
900 | 821 | ||
901 | d_fnstart(5, dev, "wlp %p\n", wlp); | ||
902 | d_printf(5, dev, "To neighbor %02x:%02x with eth " | ||
903 | "%02x:%02x:%02x:%02x:%02x:%02x\n", dev_addr->data[1], | ||
904 | dev_addr->data[0], eth_addr[0], eth_addr[1], eth_addr[2], | ||
905 | eth_addr[3], eth_addr[4], eth_addr[5]); | ||
906 | if (eda_entry->state == WLP_WSS_UNCONNECTED) { | 822 | if (eda_entry->state == WLP_WSS_UNCONNECTED) { |
907 | /* We don't want any more packets while we set up connection */ | 823 | /* We don't want any more packets while we set up connection */ |
908 | BUG_ON(wlp->stop_queue == NULL); | 824 | BUG_ON(wlp->stop_queue == NULL); |
@@ -929,12 +845,9 @@ int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
929 | "previously. Not retrying. \n"); | 845 | "previously. Not retrying. \n"); |
930 | result = -ENONET; | 846 | result = -ENONET; |
931 | goto out; | 847 | goto out; |
932 | } else { /* eda_entry->state == WLP_WSS_CONNECTED */ | 848 | } else /* eda_entry->state == WLP_WSS_CONNECTED */ |
933 | d_printf(5, dev, "Neighbor is connected, preparing frame.\n"); | ||
934 | result = wlp_wss_prep_hdr(wlp, eda_entry, skb); | 849 | result = wlp_wss_prep_hdr(wlp, eda_entry, skb); |
935 | } | ||
936 | out: | 850 | out: |
937 | d_fnend(5, dev, "wlp %p, result = %d \n", wlp, result); | ||
938 | return result; | 851 | return result; |
939 | } | 852 | } |
940 | 853 | ||
@@ -957,8 +870,6 @@ int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
957 | struct sk_buff *copy; | 870 | struct sk_buff *copy; |
958 | struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; | 871 | struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr; |
959 | 872 | ||
960 | d_fnstart(5, dev, "to neighbor %02x:%02x, skb (%p) \n", | ||
961 | dev_addr->data[1], dev_addr->data[0], skb); | ||
962 | copy = skb_copy(skb, GFP_ATOMIC); | 873 | copy = skb_copy(skb, GFP_ATOMIC); |
963 | if (copy == NULL) { | 874 | if (copy == NULL) { |
964 | if (printk_ratelimit()) | 875 | if (printk_ratelimit()) |
@@ -988,8 +899,6 @@ int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry, | |||
988 | dev_kfree_skb_irq(copy);/*we need to free if tx fails */ | 899 | dev_kfree_skb_irq(copy);/*we need to free if tx fails */ |
989 | } | 900 | } |
990 | out: | 901 | out: |
991 | d_fnend(5, dev, "to neighbor %02x:%02x \n", dev_addr->data[1], | ||
992 | dev_addr->data[0]); | ||
993 | return result; | 902 | return result; |
994 | } | 903 | } |
995 | 904 | ||
@@ -1005,7 +914,7 @@ int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss) | |||
1005 | struct wlp *wlp = container_of(wss, struct wlp, wss); | 914 | struct wlp *wlp = container_of(wss, struct wlp, wss); |
1006 | struct device *dev = &wlp->rc->uwb_dev.dev; | 915 | struct device *dev = &wlp->rc->uwb_dev.dev; |
1007 | int result = 0; | 916 | int result = 0; |
1008 | d_fnstart(5, dev, "wss (%p) \n", wss); | 917 | |
1009 | mutex_lock(&wss->mutex); | 918 | mutex_lock(&wss->mutex); |
1010 | wss->kobj.parent = &net_dev->dev.kobj; | 919 | wss->kobj.parent = &net_dev->dev.kobj; |
1011 | if (!is_valid_ether_addr(net_dev->dev_addr)) { | 920 | if (!is_valid_ether_addr(net_dev->dev_addr)) { |
@@ -1018,7 +927,6 @@ int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss) | |||
1018 | sizeof(wss->virtual_addr.data)); | 927 | sizeof(wss->virtual_addr.data)); |
1019 | out: | 928 | out: |
1020 | mutex_unlock(&wss->mutex); | 929 | mutex_unlock(&wss->mutex); |
1021 | d_fnend(5, dev, "wss (%p) \n", wss); | ||
1022 | return result; | 930 | return result; |
1023 | } | 931 | } |
1024 | EXPORT_SYMBOL_GPL(wlp_wss_setup); | 932 | EXPORT_SYMBOL_GPL(wlp_wss_setup); |
@@ -1035,8 +943,7 @@ EXPORT_SYMBOL_GPL(wlp_wss_setup); | |||
1035 | void wlp_wss_remove(struct wlp_wss *wss) | 943 | void wlp_wss_remove(struct wlp_wss *wss) |
1036 | { | 944 | { |
1037 | struct wlp *wlp = container_of(wss, struct wlp, wss); | 945 | struct wlp *wlp = container_of(wss, struct wlp, wss); |
1038 | struct device *dev = &wlp->rc->uwb_dev.dev; | 946 | |
1039 | d_fnstart(5, dev, "wss (%p) \n", wss); | ||
1040 | mutex_lock(&wss->mutex); | 947 | mutex_lock(&wss->mutex); |
1041 | if (wss->state == WLP_WSS_STATE_ACTIVE) | 948 | if (wss->state == WLP_WSS_STATE_ACTIVE) |
1042 | uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP); | 949 | uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP); |
@@ -1050,6 +957,5 @@ void wlp_wss_remove(struct wlp_wss *wss) | |||
1050 | wlp_eda_release(&wlp->eda); | 957 | wlp_eda_release(&wlp->eda); |
1051 | wlp_eda_init(&wlp->eda); | 958 | wlp_eda_init(&wlp->eda); |
1052 | mutex_unlock(&wss->mutex); | 959 | mutex_unlock(&wss->mutex); |
1053 | d_fnend(5, dev, "wss (%p) \n", wss); | ||
1054 | } | 960 | } |
1055 | EXPORT_SYMBOL_GPL(wlp_wss_remove); | 961 | EXPORT_SYMBOL_GPL(wlp_wss_remove); |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 46625cd38743..e26733a9df21 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -142,9 +142,6 @@ static void init_evtchn_cpu_bindings(void) | |||
142 | 142 | ||
143 | /* By default all event channels notify CPU#0. */ | 143 | /* By default all event channels notify CPU#0. */ |
144 | for_each_irq_desc(i, desc) { | 144 | for_each_irq_desc(i, desc) { |
145 | if (!desc) | ||
146 | continue; | ||
147 | |||
148 | desc->affinity = cpumask_of_cpu(0); | 145 | desc->affinity = cpumask_of_cpu(0); |
149 | } | 146 | } |
150 | #endif | 147 | #endif |
diff --git a/fs/Kconfig b/fs/Kconfig index 522469a7eca3..ff0e81980207 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -270,44 +270,7 @@ config OCFS2_COMPAT_JBD | |||
270 | 270 | ||
271 | endif # BLOCK | 271 | endif # BLOCK |
272 | 272 | ||
273 | config DNOTIFY | 273 | source "fs/notify/Kconfig" |
274 | bool "Dnotify support" | ||
275 | default y | ||
276 | help | ||
277 | Dnotify is a directory-based per-fd file change notification system | ||
278 | that uses signals to communicate events to user-space. There exist | ||
279 | superior alternatives, but some applications may still rely on | ||
280 | dnotify. | ||
281 | |||
282 | If unsure, say Y. | ||
283 | |||
284 | config INOTIFY | ||
285 | bool "Inotify file change notification support" | ||
286 | default y | ||
287 | ---help--- | ||
288 | Say Y here to enable inotify support. Inotify is a file change | ||
289 | notification system and a replacement for dnotify. Inotify fixes | ||
290 | numerous shortcomings in dnotify and introduces several new features | ||
291 | including multiple file events, one-shot support, and unmount | ||
292 | notification. | ||
293 | |||
294 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
295 | |||
296 | If unsure, say Y. | ||
297 | |||
298 | config INOTIFY_USER | ||
299 | bool "Inotify support for userspace" | ||
300 | depends on INOTIFY | ||
301 | default y | ||
302 | ---help--- | ||
303 | Say Y here to enable inotify support for userspace, including the | ||
304 | associated system calls. Inotify allows monitoring of both files and | ||
305 | directories via a single open fd. Events are read from the file | ||
306 | descriptor, which is also select()- and poll()-able. | ||
307 | |||
308 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
309 | |||
310 | If unsure, say Y. | ||
311 | 274 | ||
312 | config QUOTA | 275 | config QUOTA |
313 | bool "Quota support" | 276 | bool "Quota support" |
diff --git a/fs/Makefile b/fs/Makefile index d9f8afe6f0c4..e6f423d1d228 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -20,8 +20,7 @@ obj-y += no-block.o | |||
20 | endif | 20 | endif |
21 | 21 | ||
22 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o | 22 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o |
23 | obj-$(CONFIG_INOTIFY) += inotify.o | 23 | obj-y += notify/ |
24 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | ||
25 | obj-$(CONFIG_EPOLL) += eventpoll.o | 24 | obj-$(CONFIG_EPOLL) += eventpoll.o |
26 | obj-$(CONFIG_ANON_INODES) += anon_inodes.o | 25 | obj-$(CONFIG_ANON_INODES) += anon_inodes.o |
27 | obj-$(CONFIG_SIGNALFD) += signalfd.o | 26 | obj-$(CONFIG_SIGNALFD) += signalfd.o |
@@ -57,8 +56,6 @@ obj-$(CONFIG_QFMT_V1) += quota_v1.o | |||
57 | obj-$(CONFIG_QFMT_V2) += quota_v2.o | 56 | obj-$(CONFIG_QFMT_V2) += quota_v2.o |
58 | obj-$(CONFIG_QUOTACTL) += quota.o | 57 | obj-$(CONFIG_QUOTACTL) += quota.o |
59 | 58 | ||
60 | obj-$(CONFIG_DNOTIFY) += dnotify.o | ||
61 | |||
62 | obj-$(CONFIG_PROC_FS) += proc/ | 59 | obj-$(CONFIG_PROC_FS) += proc/ |
63 | obj-y += partitions/ | 60 | obj-y += partitions/ |
64 | obj-$(CONFIG_SYSFS) += sysfs/ | 61 | obj-$(CONFIG_SYSFS) += sysfs/ |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 5f1538c03b1b..a05287a23f62 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -132,11 +132,6 @@ static int bad_file_check_flags(int flags) | |||
132 | return -EIO; | 132 | return -EIO; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int bad_file_dir_notify(struct file *file, unsigned long arg) | ||
136 | { | ||
137 | return -EIO; | ||
138 | } | ||
139 | |||
140 | static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl) | 135 | static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl) |
141 | { | 136 | { |
142 | return -EIO; | 137 | return -EIO; |
@@ -179,7 +174,6 @@ static const struct file_operations bad_file_ops = | |||
179 | .sendpage = bad_file_sendpage, | 174 | .sendpage = bad_file_sendpage, |
180 | .get_unmapped_area = bad_file_get_unmapped_area, | 175 | .get_unmapped_area = bad_file_get_unmapped_area, |
181 | .check_flags = bad_file_check_flags, | 176 | .check_flags = bad_file_check_flags, |
182 | .dir_notify = bad_file_dir_notify, | ||
183 | .flock = bad_file_flock, | 177 | .flock = bad_file_flock, |
184 | .splice_write = bad_file_splice_write, | 178 | .splice_write = bad_file_splice_write, |
185 | .splice_read = bad_file_splice_read, | 179 | .splice_read = bad_file_splice_read, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index b6dfee37c7b7..d06cb023ad02 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -378,7 +378,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) | |||
378 | inode->i_size = 0; | 378 | inode->i_size = 0; |
379 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; | 379 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; |
380 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, | 380 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, |
381 | BEFS_SYMLINK_LEN); | 381 | BEFS_SYMLINK_LEN - 1); |
382 | befs_ino->i_data.symlink[BEFS_SYMLINK_LEN - 1] = '\0'; | ||
382 | } else { | 383 | } else { |
383 | int num_blks; | 384 | int num_blks; |
384 | 385 | ||
@@ -477,6 +478,8 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
477 | kfree(link); | 478 | kfree(link); |
478 | befs_error(sb, "Failed to read entire long symlink"); | 479 | befs_error(sb, "Failed to read entire long symlink"); |
479 | link = ERR_PTR(-EIO); | 480 | link = ERR_PTR(-EIO); |
481 | } else { | ||
482 | link[len - 1] = '\0'; | ||
480 | } | 483 | } |
481 | } else { | 484 | } else { |
482 | link = befs_ino->i_data.symlink; | 485 | link = befs_ino->i_data.symlink; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 99e0ae1a4c78..349a26c10001 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -326,12 +326,13 @@ static struct file_system_type bd_type = { | |||
326 | .kill_sb = kill_anon_super, | 326 | .kill_sb = kill_anon_super, |
327 | }; | 327 | }; |
328 | 328 | ||
329 | static struct vfsmount *bd_mnt __read_mostly; | 329 | struct super_block *blockdev_superblock __read_mostly; |
330 | struct super_block *blockdev_superblock; | ||
331 | 330 | ||
332 | void __init bdev_cache_init(void) | 331 | void __init bdev_cache_init(void) |
333 | { | 332 | { |
334 | int err; | 333 | int err; |
334 | struct vfsmount *bd_mnt; | ||
335 | |||
335 | bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), | 336 | bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), |
336 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| | 337 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| |
337 | SLAB_MEM_SPREAD|SLAB_PANIC), | 338 | SLAB_MEM_SPREAD|SLAB_PANIC), |
@@ -373,7 +374,7 @@ struct block_device *bdget(dev_t dev) | |||
373 | struct block_device *bdev; | 374 | struct block_device *bdev; |
374 | struct inode *inode; | 375 | struct inode *inode; |
375 | 376 | ||
376 | inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), | 377 | inode = iget5_locked(blockdev_superblock, hash(dev), |
377 | bdev_test, bdev_set, &dev); | 378 | bdev_test, bdev_set, &dev); |
378 | 379 | ||
379 | if (!inode) | 380 | if (!inode) |
@@ -463,7 +464,7 @@ void bd_forget(struct inode *inode) | |||
463 | 464 | ||
464 | spin_lock(&bdev_lock); | 465 | spin_lock(&bdev_lock); |
465 | if (inode->i_bdev) { | 466 | if (inode->i_bdev) { |
466 | if (inode->i_sb != blockdev_superblock) | 467 | if (!sb_is_blkdev_sb(inode->i_sb)) |
467 | bdev = inode->i_bdev; | 468 | bdev = inode->i_bdev; |
468 | __bd_forget(inode); | 469 | __bd_forget(inode); |
469 | } | 470 | } |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 6ba43fb346fb..9948c0030e86 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -5,7 +5,7 @@ obj-$(CONFIG_CIFS) += cifs.o | |||
5 | 5 | ||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ |
8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \ | 8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
9 | readdir.o ioctl.o sess.o export.o cifsacl.o | 9 | readdir.o ioctl.o sess.o export.o cifsacl.o |
10 | 10 | ||
11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | 11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0005a194a75c..13ea53251dcf 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -747,7 +747,6 @@ const struct file_operations cifs_file_ops = { | |||
747 | #endif /* CONFIG_CIFS_POSIX */ | 747 | #endif /* CONFIG_CIFS_POSIX */ |
748 | 748 | ||
749 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 749 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
750 | .dir_notify = cifs_dir_notify, | ||
751 | .setlease = cifs_setlease, | 750 | .setlease = cifs_setlease, |
752 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 751 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
753 | }; | 752 | }; |
@@ -768,7 +767,6 @@ const struct file_operations cifs_file_direct_ops = { | |||
768 | #endif /* CONFIG_CIFS_POSIX */ | 767 | #endif /* CONFIG_CIFS_POSIX */ |
769 | .llseek = cifs_llseek, | 768 | .llseek = cifs_llseek, |
770 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 769 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
771 | .dir_notify = cifs_dir_notify, | ||
772 | .setlease = cifs_setlease, | 770 | .setlease = cifs_setlease, |
773 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 771 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
774 | }; | 772 | }; |
@@ -789,7 +787,6 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
789 | #endif /* CONFIG_CIFS_POSIX */ | 787 | #endif /* CONFIG_CIFS_POSIX */ |
790 | 788 | ||
791 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 789 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
792 | .dir_notify = cifs_dir_notify, | ||
793 | .setlease = cifs_setlease, | 790 | .setlease = cifs_setlease, |
794 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 791 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
795 | }; | 792 | }; |
@@ -809,7 +806,6 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
809 | #endif /* CONFIG_CIFS_POSIX */ | 806 | #endif /* CONFIG_CIFS_POSIX */ |
810 | .llseek = cifs_llseek, | 807 | .llseek = cifs_llseek, |
811 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 808 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
812 | .dir_notify = cifs_dir_notify, | ||
813 | .setlease = cifs_setlease, | 809 | .setlease = cifs_setlease, |
814 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 810 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
815 | }; | 811 | }; |
@@ -818,9 +814,6 @@ const struct file_operations cifs_dir_ops = { | |||
818 | .readdir = cifs_readdir, | 814 | .readdir = cifs_readdir, |
819 | .release = cifs_closedir, | 815 | .release = cifs_closedir, |
820 | .read = generic_read_dir, | 816 | .read = generic_read_dir, |
821 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
822 | .dir_notify = cifs_dir_notify, | ||
823 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
824 | .unlocked_ioctl = cifs_ioctl, | 817 | .unlocked_ioctl = cifs_ioctl, |
825 | .llseek = generic_file_llseek, | 818 | .llseek = generic_file_llseek, |
826 | }; | 819 | }; |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 2ce04c73d74e..7ac481841f87 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -76,7 +76,6 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | |||
76 | extern const struct file_operations cifs_dir_ops; | 76 | extern const struct file_operations cifs_dir_ops; |
77 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 77 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
79 | extern int cifs_dir_notify(struct file *, unsigned long arg); | ||
80 | 79 | ||
81 | /* Functions related to dir entries */ | 80 | /* Functions related to dir entries */ |
82 | extern struct dentry_operations cifs_dentry_ops; | 81 | extern struct dentry_operations cifs_dentry_ops; |
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c deleted file mode 100644 index 5a57581eb4b2..000000000000 --- a/fs/cifs/fcntl.c +++ /dev/null | |||
@@ -1,118 +0,0 @@ | |||
1 | /* | ||
2 | * fs/cifs/fcntl.c | ||
3 | * | ||
4 | * vfs operations that deal with the file control API | ||
5 | * | ||
6 | * Copyright (C) International Business Machines Corp., 2003,2004 | ||
7 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
8 | * | ||
9 | * This library is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published | ||
11 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This library is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
17 | * the GNU Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this library; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/stat.h> | ||
25 | #include <linux/fcntl.h> | ||
26 | #include "cifsglob.h" | ||
27 | #include "cifsproto.h" | ||
28 | #include "cifs_unicode.h" | ||
29 | #include "cifs_debug.h" | ||
30 | #include "cifsfs.h" | ||
31 | |||
32 | static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) | ||
33 | { | ||
34 | __u32 cifs_ntfy_flags = 0; | ||
35 | |||
36 | /* No way on Linux VFS to ask to monitor xattr | ||
37 | changes (and no stream support either */ | ||
38 | if (fcntl_notify_flags & DN_ACCESS) | ||
39 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; | ||
40 | if (fcntl_notify_flags & DN_MODIFY) { | ||
41 | /* What does this mean on directories? */ | ||
42 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | | ||
43 | FILE_NOTIFY_CHANGE_SIZE; | ||
44 | } | ||
45 | if (fcntl_notify_flags & DN_CREATE) { | ||
46 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | | ||
47 | FILE_NOTIFY_CHANGE_LAST_WRITE; | ||
48 | } | ||
49 | if (fcntl_notify_flags & DN_DELETE) | ||
50 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; | ||
51 | if (fcntl_notify_flags & DN_RENAME) { | ||
52 | /* BB review this - checking various server behaviors */ | ||
53 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | | ||
54 | FILE_NOTIFY_CHANGE_FILE_NAME; | ||
55 | } | ||
56 | if (fcntl_notify_flags & DN_ATTRIB) { | ||
57 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | | ||
58 | FILE_NOTIFY_CHANGE_ATTRIBUTES; | ||
59 | } | ||
60 | /* if (fcntl_notify_flags & DN_MULTISHOT) { | ||
61 | cifs_ntfy_flags |= ; | ||
62 | } */ /* BB fixme - not sure how to handle this with CIFS yet */ | ||
63 | |||
64 | return cifs_ntfy_flags; | ||
65 | } | ||
66 | |||
67 | int cifs_dir_notify(struct file *file, unsigned long arg) | ||
68 | { | ||
69 | int xid; | ||
70 | int rc = -EINVAL; | ||
71 | int oplock = 0; | ||
72 | struct cifs_sb_info *cifs_sb; | ||
73 | struct cifsTconInfo *pTcon; | ||
74 | char *full_path = NULL; | ||
75 | __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; | ||
76 | __u16 netfid; | ||
77 | |||
78 | if (experimEnabled == 0) | ||
79 | return 0; | ||
80 | |||
81 | xid = GetXid(); | ||
82 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
83 | pTcon = cifs_sb->tcon; | ||
84 | |||
85 | full_path = build_path_from_dentry(file->f_path.dentry); | ||
86 | |||
87 | if (full_path == NULL) { | ||
88 | rc = -ENOMEM; | ||
89 | } else { | ||
90 | cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg)); | ||
91 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
92 | GENERIC_READ | SYNCHRONIZE, 0 /* create options */, | ||
93 | &netfid, &oplock, NULL, cifs_sb->local_nls, | ||
94 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
95 | /* BB fixme - add this handle to a notify handle list */ | ||
96 | if (rc) { | ||
97 | cFYI(1, ("Could not open directory for notify")); | ||
98 | } else { | ||
99 | filter = convert_to_cifs_notify_flags(arg); | ||
100 | if (filter != 0) { | ||
101 | rc = CIFSSMBNotify(xid, pTcon, | ||
102 | 0 /* no subdirs */, netfid, | ||
103 | filter, file, arg & DN_MULTISHOT, | ||
104 | cifs_sb->local_nls); | ||
105 | } else { | ||
106 | rc = -EINVAL; | ||
107 | } | ||
108 | /* BB add code to close file eventually (at unmount | ||
109 | it would close automatically but may be a way | ||
110 | to do it easily when inode freed or when | ||
111 | notify info is cleared/changed */ | ||
112 | cFYI(1, ("notify rc %d", rc)); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | FreeXid(xid); | ||
117 | return rc; | ||
118 | } | ||
diff --git a/fs/dcache.c b/fs/dcache.c index a1d86c7f3e66..e88c23b85a32 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | 36 | ||
37 | |||
38 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 37 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
39 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
40 | 39 | ||
@@ -948,9 +947,6 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
948 | dentry->d_op = NULL; | 947 | dentry->d_op = NULL; |
949 | dentry->d_fsdata = NULL; | 948 | dentry->d_fsdata = NULL; |
950 | dentry->d_mounted = 0; | 949 | dentry->d_mounted = 0; |
951 | #ifdef CONFIG_PROFILING | ||
952 | dentry->d_cookie = NULL; | ||
953 | #endif | ||
954 | INIT_HLIST_NODE(&dentry->d_hash); | 950 | INIT_HLIST_NODE(&dentry->d_hash); |
955 | INIT_LIST_HEAD(&dentry->d_lru); | 951 | INIT_LIST_HEAD(&dentry->d_lru); |
956 | INIT_LIST_HEAD(&dentry->d_subdirs); | 952 | INIT_LIST_HEAD(&dentry->d_subdirs); |
@@ -1336,7 +1332,7 @@ err_out: | |||
1336 | * | 1332 | * |
1337 | * Searches the children of the parent dentry for the name in question. If | 1333 | * Searches the children of the parent dentry for the name in question. If |
1338 | * the dentry is found its reference count is incremented and the dentry | 1334 | * the dentry is found its reference count is incremented and the dentry |
1339 | * is returned. The caller must use d_put to free the entry when it has | 1335 | * is returned. The caller must use dput to free the entry when it has |
1340 | * finished using it. %NULL is returned on failure. | 1336 | * finished using it. %NULL is returned on failure. |
1341 | * | 1337 | * |
1342 | * __d_lookup is dcache_lock free. The hash list is protected using RCU. | 1338 | * __d_lookup is dcache_lock free. The hash list is protected using RCU. |
@@ -1620,8 +1616,11 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
1620 | */ | 1616 | */ |
1621 | memcpy(dentry->d_iname, target->d_name.name, | 1617 | memcpy(dentry->d_iname, target->d_name.name, |
1622 | target->d_name.len + 1); | 1618 | target->d_name.len + 1); |
1619 | dentry->d_name.len = target->d_name.len; | ||
1620 | return; | ||
1623 | } | 1621 | } |
1624 | } | 1622 | } |
1623 | do_switch(dentry->d_name.len, target->d_name.len); | ||
1625 | } | 1624 | } |
1626 | 1625 | ||
1627 | /* | 1626 | /* |
@@ -1681,7 +1680,6 @@ already_unhashed: | |||
1681 | 1680 | ||
1682 | /* Switch the names.. */ | 1681 | /* Switch the names.. */ |
1683 | switch_names(dentry, target); | 1682 | switch_names(dentry, target); |
1684 | do_switch(dentry->d_name.len, target->d_name.len); | ||
1685 | do_switch(dentry->d_name.hash, target->d_name.hash); | 1683 | do_switch(dentry->d_name.hash, target->d_name.hash); |
1686 | 1684 | ||
1687 | /* ... and switch the parents */ | 1685 | /* ... and switch the parents */ |
@@ -1791,7 +1789,6 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | |||
1791 | struct dentry *dparent, *aparent; | 1789 | struct dentry *dparent, *aparent; |
1792 | 1790 | ||
1793 | switch_names(dentry, anon); | 1791 | switch_names(dentry, anon); |
1794 | do_switch(dentry->d_name.len, anon->d_name.len); | ||
1795 | do_switch(dentry->d_name.hash, anon->d_name.hash); | 1792 | do_switch(dentry->d_name.hash, anon->d_name.hash); |
1796 | 1793 | ||
1797 | dparent = dentry->d_parent; | 1794 | dparent = dentry->d_parent; |
@@ -1911,7 +1908,8 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) | |||
1911 | * Convert a dentry into an ASCII path name. If the entry has been deleted | 1908 | * Convert a dentry into an ASCII path name. If the entry has been deleted |
1912 | * the string " (deleted)" is appended. Note that this is ambiguous. | 1909 | * the string " (deleted)" is appended. Note that this is ambiguous. |
1913 | * | 1910 | * |
1914 | * Returns the buffer or an error code if the path was too long. | 1911 | * Returns a pointer into the buffer or an error code if the |
1912 | * path was too long. | ||
1915 | * | 1913 | * |
1916 | * "buflen" should be positive. Caller holds the dcache_lock. | 1914 | * "buflen" should be positive. Caller holds the dcache_lock. |
1917 | * | 1915 | * |
@@ -1987,7 +1985,10 @@ Elong: | |||
1987 | * Convert a dentry into an ASCII path name. If the entry has been deleted | 1985 | * Convert a dentry into an ASCII path name. If the entry has been deleted |
1988 | * the string " (deleted)" is appended. Note that this is ambiguous. | 1986 | * the string " (deleted)" is appended. Note that this is ambiguous. |
1989 | * | 1987 | * |
1990 | * Returns the buffer or an error code if the path was too long. | 1988 | * Returns a pointer into the buffer or an error code if the path was |
1989 | * too long. Note: Callers should use the returned pointer, not the passed | ||
1990 | * in buffer, to use the name! The implementation often starts at an offset | ||
1991 | * into the buffer, and may leave 0 bytes at the start. | ||
1991 | * | 1992 | * |
1992 | * "buflen" should be positive. | 1993 | * "buflen" should be positive. |
1993 | */ | 1994 | */ |
@@ -2313,9 +2314,6 @@ static void __init dcache_init(void) | |||
2313 | /* SLAB cache for __getname() consumers */ | 2314 | /* SLAB cache for __getname() consumers */ |
2314 | struct kmem_cache *names_cachep __read_mostly; | 2315 | struct kmem_cache *names_cachep __read_mostly; |
2315 | 2316 | ||
2316 | /* SLAB cache for file structures */ | ||
2317 | struct kmem_cache *filp_cachep __read_mostly; | ||
2318 | |||
2319 | EXPORT_SYMBOL(d_genocide); | 2317 | EXPORT_SYMBOL(d_genocide); |
2320 | 2318 | ||
2321 | void __init vfs_caches_init_early(void) | 2319 | void __init vfs_caches_init_early(void) |
@@ -2337,9 +2335,6 @@ void __init vfs_caches_init(unsigned long mempages) | |||
2337 | names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, | 2335 | names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, |
2338 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 2336 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); |
2339 | 2337 | ||
2340 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | ||
2341 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | ||
2342 | |||
2343 | dcache_init(); | 2338 | dcache_init(); |
2344 | inode_init(); | 2339 | inode_init(); |
2345 | files_init(mempages); | 2340 | files_init(mempages); |
diff --git a/fs/dcookies.c b/fs/dcookies.c index 855d4b1d619a..180e9fec4ad8 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
@@ -93,10 +93,15 @@ static struct dcookie_struct *alloc_dcookie(struct path *path) | |||
93 | { | 93 | { |
94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, | 94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, |
95 | GFP_KERNEL); | 95 | GFP_KERNEL); |
96 | struct dentry *d; | ||
96 | if (!dcs) | 97 | if (!dcs) |
97 | return NULL; | 98 | return NULL; |
98 | 99 | ||
99 | path->dentry->d_cookie = dcs; | 100 | d = path->dentry; |
101 | spin_lock(&d->d_lock); | ||
102 | d->d_flags |= DCACHE_COOKIE; | ||
103 | spin_unlock(&d->d_lock); | ||
104 | |||
100 | dcs->path = *path; | 105 | dcs->path = *path; |
101 | path_get(path); | 106 | path_get(path); |
102 | hash_dcookie(dcs); | 107 | hash_dcookie(dcs); |
@@ -119,14 +124,14 @@ int get_dcookie(struct path *path, unsigned long *cookie) | |||
119 | goto out; | 124 | goto out; |
120 | } | 125 | } |
121 | 126 | ||
122 | dcs = path->dentry->d_cookie; | 127 | if (path->dentry->d_flags & DCACHE_COOKIE) { |
123 | 128 | dcs = find_dcookie((unsigned long)path->dentry); | |
124 | if (!dcs) | 129 | } else { |
125 | dcs = alloc_dcookie(path); | 130 | dcs = alloc_dcookie(path); |
126 | 131 | if (!dcs) { | |
127 | if (!dcs) { | 132 | err = -ENOMEM; |
128 | err = -ENOMEM; | 133 | goto out; |
129 | goto out; | 134 | } |
130 | } | 135 | } |
131 | 136 | ||
132 | *cookie = dcookie_value(dcs); | 137 | *cookie = dcookie_value(dcs); |
@@ -251,7 +256,12 @@ out_kmem: | |||
251 | 256 | ||
252 | static void free_dcookie(struct dcookie_struct * dcs) | 257 | static void free_dcookie(struct dcookie_struct * dcs) |
253 | { | 258 | { |
254 | dcs->path.dentry->d_cookie = NULL; | 259 | struct dentry *d = dcs->path.dentry; |
260 | |||
261 | spin_lock(&d->d_lock); | ||
262 | d->d_flags &= ~DCACHE_COOKIE; | ||
263 | spin_unlock(&d->d_lock); | ||
264 | |||
255 | path_put(&dcs->path); | 265 | path_put(&dcs->path); |
256 | kmem_cache_free(dcookie_cache, dcs); | 266 | kmem_cache_free(dcookie_cache, dcs); |
257 | } | 267 | } |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 5d61b7c06e13..fff96e152c0c 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -27,25 +27,32 @@ | |||
27 | #define DEVPTS_SUPER_MAGIC 0x1cd1 | 27 | #define DEVPTS_SUPER_MAGIC 0x1cd1 |
28 | 28 | ||
29 | #define DEVPTS_DEFAULT_MODE 0600 | 29 | #define DEVPTS_DEFAULT_MODE 0600 |
30 | /* | ||
31 | * ptmx is a new node in /dev/pts and will be unused in legacy (single- | ||
32 | * instance) mode. To prevent surprises in user space, set permissions of | ||
33 | * ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful | ||
34 | * permissions. | ||
35 | */ | ||
36 | #define DEVPTS_DEFAULT_PTMX_MODE 0000 | ||
30 | #define PTMX_MINOR 2 | 37 | #define PTMX_MINOR 2 |
31 | 38 | ||
32 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 39 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
33 | static DEFINE_IDA(allocated_ptys); | ||
34 | static DEFINE_MUTEX(allocated_ptys_lock); | 40 | static DEFINE_MUTEX(allocated_ptys_lock); |
35 | 41 | ||
36 | static struct vfsmount *devpts_mnt; | 42 | static struct vfsmount *devpts_mnt; |
37 | static struct dentry *devpts_root; | ||
38 | 43 | ||
39 | static struct { | 44 | struct pts_mount_opts { |
40 | int setuid; | 45 | int setuid; |
41 | int setgid; | 46 | int setgid; |
42 | uid_t uid; | 47 | uid_t uid; |
43 | gid_t gid; | 48 | gid_t gid; |
44 | umode_t mode; | 49 | umode_t mode; |
45 | } config = {.mode = DEVPTS_DEFAULT_MODE}; | 50 | umode_t ptmxmode; |
51 | int newinstance; | ||
52 | }; | ||
46 | 53 | ||
47 | enum { | 54 | enum { |
48 | Opt_uid, Opt_gid, Opt_mode, | 55 | Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, |
49 | Opt_err | 56 | Opt_err |
50 | }; | 57 | }; |
51 | 58 | ||
@@ -53,18 +60,50 @@ static const match_table_t tokens = { | |||
53 | {Opt_uid, "uid=%u"}, | 60 | {Opt_uid, "uid=%u"}, |
54 | {Opt_gid, "gid=%u"}, | 61 | {Opt_gid, "gid=%u"}, |
55 | {Opt_mode, "mode=%o"}, | 62 | {Opt_mode, "mode=%o"}, |
63 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
64 | {Opt_ptmxmode, "ptmxmode=%o"}, | ||
65 | {Opt_newinstance, "newinstance"}, | ||
66 | #endif | ||
56 | {Opt_err, NULL} | 67 | {Opt_err, NULL} |
57 | }; | 68 | }; |
58 | 69 | ||
59 | static int devpts_remount(struct super_block *sb, int *flags, char *data) | 70 | struct pts_fs_info { |
71 | struct ida allocated_ptys; | ||
72 | struct pts_mount_opts mount_opts; | ||
73 | struct dentry *ptmx_dentry; | ||
74 | }; | ||
75 | |||
76 | static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb) | ||
77 | { | ||
78 | return sb->s_fs_info; | ||
79 | } | ||
80 | |||
81 | static inline struct super_block *pts_sb_from_inode(struct inode *inode) | ||
82 | { | ||
83 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
84 | if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) | ||
85 | return inode->i_sb; | ||
86 | #endif | ||
87 | return devpts_mnt->mnt_sb; | ||
88 | } | ||
89 | |||
90 | #define PARSE_MOUNT 0 | ||
91 | #define PARSE_REMOUNT 1 | ||
92 | |||
93 | static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) | ||
60 | { | 94 | { |
61 | char *p; | 95 | char *p; |
62 | 96 | ||
63 | config.setuid = 0; | 97 | opts->setuid = 0; |
64 | config.setgid = 0; | 98 | opts->setgid = 0; |
65 | config.uid = 0; | 99 | opts->uid = 0; |
66 | config.gid = 0; | 100 | opts->gid = 0; |
67 | config.mode = DEVPTS_DEFAULT_MODE; | 101 | opts->mode = DEVPTS_DEFAULT_MODE; |
102 | opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; | ||
103 | |||
104 | /* newinstance makes sense only on initial mount */ | ||
105 | if (op == PARSE_MOUNT) | ||
106 | opts->newinstance = 0; | ||
68 | 107 | ||
69 | while ((p = strsep(&data, ",")) != NULL) { | 108 | while ((p = strsep(&data, ",")) != NULL) { |
70 | substring_t args[MAX_OPT_ARGS]; | 109 | substring_t args[MAX_OPT_ARGS]; |
@@ -79,20 +118,32 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) | |||
79 | case Opt_uid: | 118 | case Opt_uid: |
80 | if (match_int(&args[0], &option)) | 119 | if (match_int(&args[0], &option)) |
81 | return -EINVAL; | 120 | return -EINVAL; |
82 | config.uid = option; | 121 | opts->uid = option; |
83 | config.setuid = 1; | 122 | opts->setuid = 1; |
84 | break; | 123 | break; |
85 | case Opt_gid: | 124 | case Opt_gid: |
86 | if (match_int(&args[0], &option)) | 125 | if (match_int(&args[0], &option)) |
87 | return -EINVAL; | 126 | return -EINVAL; |
88 | config.gid = option; | 127 | opts->gid = option; |
89 | config.setgid = 1; | 128 | opts->setgid = 1; |
90 | break; | 129 | break; |
91 | case Opt_mode: | 130 | case Opt_mode: |
92 | if (match_octal(&args[0], &option)) | 131 | if (match_octal(&args[0], &option)) |
93 | return -EINVAL; | 132 | return -EINVAL; |
94 | config.mode = option & S_IALLUGO; | 133 | opts->mode = option & S_IALLUGO; |
134 | break; | ||
135 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
136 | case Opt_ptmxmode: | ||
137 | if (match_octal(&args[0], &option)) | ||
138 | return -EINVAL; | ||
139 | opts->ptmxmode = option & S_IALLUGO; | ||
140 | break; | ||
141 | case Opt_newinstance: | ||
142 | /* newinstance makes sense only on initial mount */ | ||
143 | if (op == PARSE_MOUNT) | ||
144 | opts->newinstance = 1; | ||
95 | break; | 145 | break; |
146 | #endif | ||
96 | default: | 147 | default: |
97 | printk(KERN_ERR "devpts: called with bogus options\n"); | 148 | printk(KERN_ERR "devpts: called with bogus options\n"); |
98 | return -EINVAL; | 149 | return -EINVAL; |
@@ -102,13 +153,108 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data) | |||
102 | return 0; | 153 | return 0; |
103 | } | 154 | } |
104 | 155 | ||
156 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
157 | static int mknod_ptmx(struct super_block *sb) | ||
158 | { | ||
159 | int mode; | ||
160 | int rc = -ENOMEM; | ||
161 | struct dentry *dentry; | ||
162 | struct inode *inode; | ||
163 | struct dentry *root = sb->s_root; | ||
164 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
165 | struct pts_mount_opts *opts = &fsi->mount_opts; | ||
166 | |||
167 | mutex_lock(&root->d_inode->i_mutex); | ||
168 | |||
169 | /* If we have already created ptmx node, return */ | ||
170 | if (fsi->ptmx_dentry) { | ||
171 | rc = 0; | ||
172 | goto out; | ||
173 | } | ||
174 | |||
175 | dentry = d_alloc_name(root, "ptmx"); | ||
176 | if (!dentry) { | ||
177 | printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n"); | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Create a new 'ptmx' node in this mount of devpts. | ||
183 | */ | ||
184 | inode = new_inode(sb); | ||
185 | if (!inode) { | ||
186 | printk(KERN_ERR "Unable to alloc inode for ptmx node\n"); | ||
187 | dput(dentry); | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | inode->i_ino = 2; | ||
192 | inode->i_uid = inode->i_gid = 0; | ||
193 | inode->i_blocks = 0; | ||
194 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
195 | |||
196 | mode = S_IFCHR|opts->ptmxmode; | ||
197 | init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2)); | ||
198 | |||
199 | d_add(dentry, inode); | ||
200 | |||
201 | fsi->ptmx_dentry = dentry; | ||
202 | rc = 0; | ||
203 | |||
204 | printk(KERN_DEBUG "Created ptmx node in devpts ino %lu\n", | ||
205 | inode->i_ino); | ||
206 | out: | ||
207 | mutex_unlock(&root->d_inode->i_mutex); | ||
208 | return rc; | ||
209 | } | ||
210 | |||
211 | static void update_ptmx_mode(struct pts_fs_info *fsi) | ||
212 | { | ||
213 | struct inode *inode; | ||
214 | if (fsi->ptmx_dentry) { | ||
215 | inode = fsi->ptmx_dentry->d_inode; | ||
216 | inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode; | ||
217 | } | ||
218 | } | ||
219 | #else | ||
220 | static inline void update_ptmx_mode(struct pts_fs_info *fsi) | ||
221 | { | ||
222 | return; | ||
223 | } | ||
224 | #endif | ||
225 | |||
226 | static int devpts_remount(struct super_block *sb, int *flags, char *data) | ||
227 | { | ||
228 | int err; | ||
229 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
230 | struct pts_mount_opts *opts = &fsi->mount_opts; | ||
231 | |||
232 | err = parse_mount_options(data, PARSE_REMOUNT, opts); | ||
233 | |||
234 | /* | ||
235 | * parse_mount_options() restores options to default values | ||
236 | * before parsing and may have changed ptmxmode. So, update the | ||
237 | * mode in the inode too. Bogus options don't fail the remount, | ||
238 | * so do this even on error return. | ||
239 | */ | ||
240 | update_ptmx_mode(fsi); | ||
241 | |||
242 | return err; | ||
243 | } | ||
244 | |||
105 | static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs) | 245 | static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs) |
106 | { | 246 | { |
107 | if (config.setuid) | 247 | struct pts_fs_info *fsi = DEVPTS_SB(vfs->mnt_sb); |
108 | seq_printf(seq, ",uid=%u", config.uid); | 248 | struct pts_mount_opts *opts = &fsi->mount_opts; |
109 | if (config.setgid) | 249 | |
110 | seq_printf(seq, ",gid=%u", config.gid); | 250 | if (opts->setuid) |
111 | seq_printf(seq, ",mode=%03o", config.mode); | 251 | seq_printf(seq, ",uid=%u", opts->uid); |
252 | if (opts->setgid) | ||
253 | seq_printf(seq, ",gid=%u", opts->gid); | ||
254 | seq_printf(seq, ",mode=%03o", opts->mode); | ||
255 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
256 | seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); | ||
257 | #endif | ||
112 | 258 | ||
113 | return 0; | 259 | return 0; |
114 | } | 260 | } |
@@ -119,10 +265,25 @@ static const struct super_operations devpts_sops = { | |||
119 | .show_options = devpts_show_options, | 265 | .show_options = devpts_show_options, |
120 | }; | 266 | }; |
121 | 267 | ||
268 | static void *new_pts_fs_info(void) | ||
269 | { | ||
270 | struct pts_fs_info *fsi; | ||
271 | |||
272 | fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL); | ||
273 | if (!fsi) | ||
274 | return NULL; | ||
275 | |||
276 | ida_init(&fsi->allocated_ptys); | ||
277 | fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE; | ||
278 | fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; | ||
279 | |||
280 | return fsi; | ||
281 | } | ||
282 | |||
122 | static int | 283 | static int |
123 | devpts_fill_super(struct super_block *s, void *data, int silent) | 284 | devpts_fill_super(struct super_block *s, void *data, int silent) |
124 | { | 285 | { |
125 | struct inode * inode; | 286 | struct inode *inode; |
126 | 287 | ||
127 | s->s_blocksize = 1024; | 288 | s->s_blocksize = 1024; |
128 | s->s_blocksize_bits = 10; | 289 | s->s_blocksize_bits = 10; |
@@ -130,9 +291,13 @@ devpts_fill_super(struct super_block *s, void *data, int silent) | |||
130 | s->s_op = &devpts_sops; | 291 | s->s_op = &devpts_sops; |
131 | s->s_time_gran = 1; | 292 | s->s_time_gran = 1; |
132 | 293 | ||
294 | s->s_fs_info = new_pts_fs_info(); | ||
295 | if (!s->s_fs_info) | ||
296 | goto fail; | ||
297 | |||
133 | inode = new_inode(s); | 298 | inode = new_inode(s); |
134 | if (!inode) | 299 | if (!inode) |
135 | goto fail; | 300 | goto free_fsi; |
136 | inode->i_ino = 1; | 301 | inode->i_ino = 1; |
137 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 302 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
138 | inode->i_blocks = 0; | 303 | inode->i_blocks = 0; |
@@ -142,27 +307,226 @@ devpts_fill_super(struct super_block *s, void *data, int silent) | |||
142 | inode->i_fop = &simple_dir_operations; | 307 | inode->i_fop = &simple_dir_operations; |
143 | inode->i_nlink = 2; | 308 | inode->i_nlink = 2; |
144 | 309 | ||
145 | devpts_root = s->s_root = d_alloc_root(inode); | 310 | s->s_root = d_alloc_root(inode); |
146 | if (s->s_root) | 311 | if (s->s_root) |
147 | return 0; | 312 | return 0; |
148 | 313 | ||
149 | printk("devpts: get root dentry failed\n"); | 314 | printk(KERN_ERR "devpts: get root dentry failed\n"); |
150 | iput(inode); | 315 | iput(inode); |
316 | |||
317 | free_fsi: | ||
318 | kfree(s->s_fs_info); | ||
151 | fail: | 319 | fail: |
152 | return -ENOMEM; | 320 | return -ENOMEM; |
153 | } | 321 | } |
154 | 322 | ||
323 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | ||
324 | static int compare_init_pts_sb(struct super_block *s, void *p) | ||
325 | { | ||
326 | if (devpts_mnt) | ||
327 | return devpts_mnt->mnt_sb == s; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * Safely parse the mount options in @data and update @opts. | ||
333 | * | ||
334 | * devpts ends up parsing options two times during mount, due to the | ||
335 | * two modes of operation it supports. The first parse occurs in | ||
336 | * devpts_get_sb() when determining the mode (single-instance or | ||
337 | * multi-instance mode). The second parse happens in devpts_remount() | ||
338 | * or new_pts_mount() depending on the mode. | ||
339 | * | ||
340 | * Parsing of options modifies the @data making subsequent parsing | ||
341 | * incorrect. So make a local copy of @data and parse it. | ||
342 | * | ||
343 | * Return: 0 On success, -errno on error | ||
344 | */ | ||
345 | static int safe_parse_mount_options(void *data, struct pts_mount_opts *opts) | ||
346 | { | ||
347 | int rc; | ||
348 | void *datacp; | ||
349 | |||
350 | if (!data) | ||
351 | return 0; | ||
352 | |||
353 | /* Use kstrdup() ? */ | ||
354 | datacp = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
355 | if (!datacp) | ||
356 | return -ENOMEM; | ||
357 | |||
358 | memcpy(datacp, data, PAGE_SIZE); | ||
359 | rc = parse_mount_options((char *)datacp, PARSE_MOUNT, opts); | ||
360 | kfree(datacp); | ||
361 | |||
362 | return rc; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Mount a new (private) instance of devpts. PTYs created in this | ||
367 | * instance are independent of the PTYs in other devpts instances. | ||
368 | */ | ||
369 | static int new_pts_mount(struct file_system_type *fs_type, int flags, | ||
370 | void *data, struct vfsmount *mnt) | ||
371 | { | ||
372 | int err; | ||
373 | struct pts_fs_info *fsi; | ||
374 | struct pts_mount_opts *opts; | ||
375 | |||
376 | printk(KERN_NOTICE "devpts: newinstance mount\n"); | ||
377 | |||
378 | err = get_sb_nodev(fs_type, flags, data, devpts_fill_super, mnt); | ||
379 | if (err) | ||
380 | return err; | ||
381 | |||
382 | fsi = DEVPTS_SB(mnt->mnt_sb); | ||
383 | opts = &fsi->mount_opts; | ||
384 | |||
385 | err = parse_mount_options(data, PARSE_MOUNT, opts); | ||
386 | if (err) | ||
387 | goto fail; | ||
388 | |||
389 | err = mknod_ptmx(mnt->mnt_sb); | ||
390 | if (err) | ||
391 | goto fail; | ||
392 | |||
393 | return 0; | ||
394 | |||
395 | fail: | ||
396 | dput(mnt->mnt_sb->s_root); | ||
397 | deactivate_super(mnt->mnt_sb); | ||
398 | return err; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Check if 'newinstance' mount option was specified in @data. | ||
403 | * | ||
404 | * Return: -errno on error (eg: invalid mount options specified) | ||
405 | * : 1 if 'newinstance' mount option was specified | ||
406 | * : 0 if 'newinstance' mount option was NOT specified | ||
407 | */ | ||
408 | static int is_new_instance_mount(void *data) | ||
409 | { | ||
410 | int rc; | ||
411 | struct pts_mount_opts opts; | ||
412 | |||
413 | if (!data) | ||
414 | return 0; | ||
415 | |||
416 | rc = safe_parse_mount_options(data, &opts); | ||
417 | if (!rc) | ||
418 | rc = opts.newinstance; | ||
419 | |||
420 | return rc; | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * get_init_pts_sb() | ||
425 | * | ||
426 | * This interface is needed to support multiple namespace semantics in | ||
427 | * devpts while preserving backward compatibility of the current 'single- | ||
428 | * namespace' semantics. i.e all mounts of devpts without the 'newinstance' | ||
429 | * mount option should bind to the initial kernel mount, like | ||
430 | * get_sb_single(). | ||
431 | * | ||
432 | * Mounts with 'newinstance' option create a new private namespace. | ||
433 | * | ||
434 | * But for single-mount semantics, devpts cannot use get_sb_single(), | ||
435 | * because get_sb_single()/sget() find and use the super-block from | ||
436 | * the most recent mount of devpts. But that recent mount may be a | ||
437 | * 'newinstance' mount and get_sb_single() would pick the newinstance | ||
438 | * super-block instead of the initial super-block. | ||
439 | * | ||
440 | * This interface is identical to get_sb_single() except that it | ||
441 | * consistently selects the 'single-namespace' superblock even in the | ||
442 | * presence of the private namespace (i.e 'newinstance') super-blocks. | ||
443 | */ | ||
444 | static int get_init_pts_sb(struct file_system_type *fs_type, int flags, | ||
445 | void *data, struct vfsmount *mnt) | ||
446 | { | ||
447 | struct super_block *s; | ||
448 | int error; | ||
449 | |||
450 | s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); | ||
451 | if (IS_ERR(s)) | ||
452 | return PTR_ERR(s); | ||
453 | |||
454 | if (!s->s_root) { | ||
455 | s->s_flags = flags; | ||
456 | error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | ||
457 | if (error) { | ||
458 | up_write(&s->s_umount); | ||
459 | deactivate_super(s); | ||
460 | return error; | ||
461 | } | ||
462 | s->s_flags |= MS_ACTIVE; | ||
463 | } | ||
464 | do_remount_sb(s, flags, data, 0); | ||
465 | return simple_set_mnt(mnt, s); | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * Mount or remount the initial kernel mount of devpts. This type of | ||
470 | * mount maintains the legacy, single-instance semantics, while the | ||
471 | * kernel still allows multiple-instances. | ||
472 | */ | ||
473 | static int init_pts_mount(struct file_system_type *fs_type, int flags, | ||
474 | void *data, struct vfsmount *mnt) | ||
475 | { | ||
476 | int err; | ||
477 | |||
478 | err = get_init_pts_sb(fs_type, flags, data, mnt); | ||
479 | if (err) | ||
480 | return err; | ||
481 | |||
482 | err = mknod_ptmx(mnt->mnt_sb); | ||
483 | if (err) { | ||
484 | dput(mnt->mnt_sb->s_root); | ||
485 | deactivate_super(mnt->mnt_sb); | ||
486 | } | ||
487 | |||
488 | return err; | ||
489 | } | ||
490 | |||
155 | static int devpts_get_sb(struct file_system_type *fs_type, | 491 | static int devpts_get_sb(struct file_system_type *fs_type, |
156 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 492 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
157 | { | 493 | { |
494 | int new; | ||
495 | |||
496 | new = is_new_instance_mount(data); | ||
497 | if (new < 0) | ||
498 | return new; | ||
499 | |||
500 | if (new) | ||
501 | return new_pts_mount(fs_type, flags, data, mnt); | ||
502 | |||
503 | return init_pts_mount(fs_type, flags, data, mnt); | ||
504 | } | ||
505 | #else | ||
506 | /* | ||
507 | * This supports only the legacy single-instance semantics (no | ||
508 | * multiple-instance semantics) | ||
509 | */ | ||
510 | static int devpts_get_sb(struct file_system_type *fs_type, int flags, | ||
511 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
512 | { | ||
158 | return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); | 513 | return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); |
159 | } | 514 | } |
515 | #endif | ||
516 | |||
517 | static void devpts_kill_sb(struct super_block *sb) | ||
518 | { | ||
519 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
520 | |||
521 | kfree(fsi); | ||
522 | kill_litter_super(sb); | ||
523 | } | ||
160 | 524 | ||
161 | static struct file_system_type devpts_fs_type = { | 525 | static struct file_system_type devpts_fs_type = { |
162 | .owner = THIS_MODULE, | 526 | .owner = THIS_MODULE, |
163 | .name = "devpts", | 527 | .name = "devpts", |
164 | .get_sb = devpts_get_sb, | 528 | .get_sb = devpts_get_sb, |
165 | .kill_sb = kill_anon_super, | 529 | .kill_sb = devpts_kill_sb, |
166 | }; | 530 | }; |
167 | 531 | ||
168 | /* | 532 | /* |
@@ -172,16 +536,17 @@ static struct file_system_type devpts_fs_type = { | |||
172 | 536 | ||
173 | int devpts_new_index(struct inode *ptmx_inode) | 537 | int devpts_new_index(struct inode *ptmx_inode) |
174 | { | 538 | { |
539 | struct super_block *sb = pts_sb_from_inode(ptmx_inode); | ||
540 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
175 | int index; | 541 | int index; |
176 | int ida_ret; | 542 | int ida_ret; |
177 | 543 | ||
178 | retry: | 544 | retry: |
179 | if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) { | 545 | if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) |
180 | return -ENOMEM; | 546 | return -ENOMEM; |
181 | } | ||
182 | 547 | ||
183 | mutex_lock(&allocated_ptys_lock); | 548 | mutex_lock(&allocated_ptys_lock); |
184 | ida_ret = ida_get_new(&allocated_ptys, &index); | 549 | ida_ret = ida_get_new(&fsi->allocated_ptys, &index); |
185 | if (ida_ret < 0) { | 550 | if (ida_ret < 0) { |
186 | mutex_unlock(&allocated_ptys_lock); | 551 | mutex_unlock(&allocated_ptys_lock); |
187 | if (ida_ret == -EAGAIN) | 552 | if (ida_ret == -EAGAIN) |
@@ -190,7 +555,7 @@ retry: | |||
190 | } | 555 | } |
191 | 556 | ||
192 | if (index >= pty_limit) { | 557 | if (index >= pty_limit) { |
193 | ida_remove(&allocated_ptys, index); | 558 | ida_remove(&fsi->allocated_ptys, index); |
194 | mutex_unlock(&allocated_ptys_lock); | 559 | mutex_unlock(&allocated_ptys_lock); |
195 | return -EIO; | 560 | return -EIO; |
196 | } | 561 | } |
@@ -200,18 +565,26 @@ retry: | |||
200 | 565 | ||
201 | void devpts_kill_index(struct inode *ptmx_inode, int idx) | 566 | void devpts_kill_index(struct inode *ptmx_inode, int idx) |
202 | { | 567 | { |
568 | struct super_block *sb = pts_sb_from_inode(ptmx_inode); | ||
569 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
570 | |||
203 | mutex_lock(&allocated_ptys_lock); | 571 | mutex_lock(&allocated_ptys_lock); |
204 | ida_remove(&allocated_ptys, idx); | 572 | ida_remove(&fsi->allocated_ptys, idx); |
205 | mutex_unlock(&allocated_ptys_lock); | 573 | mutex_unlock(&allocated_ptys_lock); |
206 | } | 574 | } |
207 | 575 | ||
208 | int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) | 576 | int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) |
209 | { | 577 | { |
210 | int number = tty->index; /* tty layer puts index from devpts_new_index() in here */ | 578 | /* tty layer puts index from devpts_new_index() in here */ |
579 | int number = tty->index; | ||
211 | struct tty_driver *driver = tty->driver; | 580 | struct tty_driver *driver = tty->driver; |
212 | dev_t device = MKDEV(driver->major, driver->minor_start+number); | 581 | dev_t device = MKDEV(driver->major, driver->minor_start+number); |
213 | struct dentry *dentry; | 582 | struct dentry *dentry; |
214 | struct inode *inode = new_inode(devpts_mnt->mnt_sb); | 583 | struct super_block *sb = pts_sb_from_inode(ptmx_inode); |
584 | struct inode *inode = new_inode(sb); | ||
585 | struct dentry *root = sb->s_root; | ||
586 | struct pts_fs_info *fsi = DEVPTS_SB(sb); | ||
587 | struct pts_mount_opts *opts = &fsi->mount_opts; | ||
215 | char s[12]; | 588 | char s[12]; |
216 | 589 | ||
217 | /* We're supposed to be given the slave end of a pty */ | 590 | /* We're supposed to be given the slave end of a pty */ |
@@ -221,25 +594,25 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) | |||
221 | if (!inode) | 594 | if (!inode) |
222 | return -ENOMEM; | 595 | return -ENOMEM; |
223 | 596 | ||
224 | inode->i_ino = number+2; | 597 | inode->i_ino = number + 3; |
225 | inode->i_uid = config.setuid ? config.uid : current_fsuid(); | 598 | inode->i_uid = opts->setuid ? opts->uid : current_fsuid(); |
226 | inode->i_gid = config.setgid ? config.gid : current_fsgid(); | 599 | inode->i_gid = opts->setgid ? opts->gid : current_fsgid(); |
227 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 600 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
228 | init_special_inode(inode, S_IFCHR|config.mode, device); | 601 | init_special_inode(inode, S_IFCHR|opts->mode, device); |
229 | inode->i_private = tty; | 602 | inode->i_private = tty; |
230 | tty->driver_data = inode; | 603 | tty->driver_data = inode; |
231 | 604 | ||
232 | sprintf(s, "%d", number); | 605 | sprintf(s, "%d", number); |
233 | 606 | ||
234 | mutex_lock(&devpts_root->d_inode->i_mutex); | 607 | mutex_lock(&root->d_inode->i_mutex); |
235 | 608 | ||
236 | dentry = d_alloc_name(devpts_root, s); | 609 | dentry = d_alloc_name(root, s); |
237 | if (!IS_ERR(dentry)) { | 610 | if (!IS_ERR(dentry)) { |
238 | d_add(dentry, inode); | 611 | d_add(dentry, inode); |
239 | fsnotify_create(devpts_root->d_inode, dentry); | 612 | fsnotify_create(root->d_inode, dentry); |
240 | } | 613 | } |
241 | 614 | ||
242 | mutex_unlock(&devpts_root->d_inode->i_mutex); | 615 | mutex_unlock(&root->d_inode->i_mutex); |
243 | 616 | ||
244 | return 0; | 617 | return 0; |
245 | } | 618 | } |
@@ -256,20 +629,27 @@ struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) | |||
256 | void devpts_pty_kill(struct tty_struct *tty) | 629 | void devpts_pty_kill(struct tty_struct *tty) |
257 | { | 630 | { |
258 | struct inode *inode = tty->driver_data; | 631 | struct inode *inode = tty->driver_data; |
632 | struct super_block *sb = pts_sb_from_inode(inode); | ||
633 | struct dentry *root = sb->s_root; | ||
259 | struct dentry *dentry; | 634 | struct dentry *dentry; |
260 | 635 | ||
261 | BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); | 636 | BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
262 | 637 | ||
263 | mutex_lock(&devpts_root->d_inode->i_mutex); | 638 | mutex_lock(&root->d_inode->i_mutex); |
264 | 639 | ||
265 | dentry = d_find_alias(inode); | 640 | dentry = d_find_alias(inode); |
266 | if (dentry && !IS_ERR(dentry)) { | 641 | if (IS_ERR(dentry)) |
642 | goto out; | ||
643 | |||
644 | if (dentry) { | ||
267 | inode->i_nlink--; | 645 | inode->i_nlink--; |
268 | d_delete(dentry); | 646 | d_delete(dentry); |
269 | dput(dentry); | 647 | dput(dentry); /* d_alloc_name() in devpts_pty_new() */ |
270 | } | 648 | } |
271 | 649 | ||
272 | mutex_unlock(&devpts_root->d_inode->i_mutex); | 650 | dput(dentry); /* d_find_alias above */ |
651 | out: | ||
652 | mutex_unlock(&root->d_inode->i_mutex); | ||
273 | } | 653 | } |
274 | 654 | ||
275 | static int __init init_devpts_fs(void) | 655 | static int __init init_devpts_fs(void) |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 89209f00f9c7..5e78fc179886 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -673,10 +673,11 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
673 | ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " | 673 | ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " |
674 | "dentry->d_name.name = [%s]\n", dentry->d_name.name); | 674 | "dentry->d_name.name = [%s]\n", dentry->d_name.name); |
675 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); | 675 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); |
676 | buf[rc] = '\0'; | ||
677 | set_fs(old_fs); | 676 | set_fs(old_fs); |
678 | if (rc < 0) | 677 | if (rc < 0) |
679 | goto out_free; | 678 | goto out_free; |
679 | else | ||
680 | buf[rc] = '\0'; | ||
680 | rc = 0; | 681 | rc = 0; |
681 | nd_set_link(nd, buf); | 682 | nd_set_link(nd, buf); |
682 | goto out; | 683 | goto out; |
@@ -127,7 +127,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
127 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 127 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
128 | goto exit; | 128 | goto exit; |
129 | 129 | ||
130 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | 130 | error = inode_permission(nd.path.dentry->d_inode, |
131 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
131 | if (error) | 132 | if (error) |
132 | goto exit; | 133 | goto exit; |
133 | 134 | ||
@@ -680,7 +681,7 @@ struct file *open_exec(const char *name) | |||
680 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 681 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
681 | goto out_path_put; | 682 | goto out_path_put; |
682 | 683 | ||
683 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); | 684 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
684 | if (err) | 685 | if (err) |
685 | goto out_path_put; | 686 | goto out_path_put; |
686 | 687 | ||
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 8d0add625870..c454d5db28a5 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
@@ -585,7 +585,10 @@ got: | |||
585 | spin_lock(&sbi->s_next_gen_lock); | 585 | spin_lock(&sbi->s_next_gen_lock); |
586 | inode->i_generation = sbi->s_next_generation++; | 586 | inode->i_generation = sbi->s_next_generation++; |
587 | spin_unlock(&sbi->s_next_gen_lock); | 587 | spin_unlock(&sbi->s_next_gen_lock); |
588 | insert_inode_hash(inode); | 588 | if (insert_inode_locked(inode) < 0) { |
589 | err = -EINVAL; | ||
590 | goto fail_drop; | ||
591 | } | ||
589 | 592 | ||
590 | if (DQUOT_ALLOC_INODE(inode)) { | 593 | if (DQUOT_ALLOC_INODE(inode)) { |
591 | err = -EDQUOT; | 594 | err = -EDQUOT; |
@@ -612,6 +615,7 @@ fail_drop: | |||
612 | DQUOT_DROP(inode); | 615 | DQUOT_DROP(inode); |
613 | inode->i_flags |= S_NOQUOTA; | 616 | inode->i_flags |= S_NOQUOTA; |
614 | inode->i_nlink = 0; | 617 | inode->i_nlink = 0; |
618 | unlock_new_inode(inode); | ||
615 | iput(inode); | 619 | iput(inode); |
616 | return ERR_PTR(err); | 620 | return ERR_PTR(err); |
617 | 621 | ||
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 7658b33e2653..02b39a5deb74 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/buffer_head.h> | 32 | #include <linux/buffer_head.h> |
33 | #include <linux/mpage.h> | 33 | #include <linux/mpage.h> |
34 | #include <linux/fiemap.h> | 34 | #include <linux/fiemap.h> |
35 | #include <linux/namei.h> | ||
35 | #include "ext2.h" | 36 | #include "ext2.h" |
36 | #include "acl.h" | 37 | #include "acl.h" |
37 | #include "xip.h" | 38 | #include "xip.h" |
@@ -1286,9 +1287,11 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
1286 | else | 1287 | else |
1287 | inode->i_mapping->a_ops = &ext2_aops; | 1288 | inode->i_mapping->a_ops = &ext2_aops; |
1288 | } else if (S_ISLNK(inode->i_mode)) { | 1289 | } else if (S_ISLNK(inode->i_mode)) { |
1289 | if (ext2_inode_is_fast_symlink(inode)) | 1290 | if (ext2_inode_is_fast_symlink(inode)) { |
1290 | inode->i_op = &ext2_fast_symlink_inode_operations; | 1291 | inode->i_op = &ext2_fast_symlink_inode_operations; |
1291 | else { | 1292 | nd_terminate_link(ei->i_data, inode->i_size, |
1293 | sizeof(ei->i_data) - 1); | ||
1294 | } else { | ||
1292 | inode->i_op = &ext2_symlink_inode_operations; | 1295 | inode->i_op = &ext2_symlink_inode_operations; |
1293 | if (test_opt(inode->i_sb, NOBH)) | 1296 | if (test_opt(inode->i_sb, NOBH)) |
1294 | inode->i_mapping->a_ops = &ext2_nobh_aops; | 1297 | inode->i_mapping->a_ops = &ext2_nobh_aops; |
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 2a747252ec12..90ea17998a73 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
@@ -41,9 +41,11 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) | |||
41 | int err = ext2_add_link(dentry, inode); | 41 | int err = ext2_add_link(dentry, inode); |
42 | if (!err) { | 42 | if (!err) { |
43 | d_instantiate(dentry, inode); | 43 | d_instantiate(dentry, inode); |
44 | unlock_new_inode(inode); | ||
44 | return 0; | 45 | return 0; |
45 | } | 46 | } |
46 | inode_dec_link_count(inode); | 47 | inode_dec_link_count(inode); |
48 | unlock_new_inode(inode); | ||
47 | iput(inode); | 49 | iput(inode); |
48 | return err; | 50 | return err; |
49 | } | 51 | } |
@@ -170,6 +172,7 @@ out: | |||
170 | 172 | ||
171 | out_fail: | 173 | out_fail: |
172 | inode_dec_link_count(inode); | 174 | inode_dec_link_count(inode); |
175 | unlock_new_inode(inode); | ||
173 | iput (inode); | 176 | iput (inode); |
174 | goto out; | 177 | goto out; |
175 | } | 178 | } |
@@ -178,6 +181,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, | |||
178 | struct dentry *dentry) | 181 | struct dentry *dentry) |
179 | { | 182 | { |
180 | struct inode *inode = old_dentry->d_inode; | 183 | struct inode *inode = old_dentry->d_inode; |
184 | int err; | ||
181 | 185 | ||
182 | if (inode->i_nlink >= EXT2_LINK_MAX) | 186 | if (inode->i_nlink >= EXT2_LINK_MAX) |
183 | return -EMLINK; | 187 | return -EMLINK; |
@@ -186,7 +190,14 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, | |||
186 | inode_inc_link_count(inode); | 190 | inode_inc_link_count(inode); |
187 | atomic_inc(&inode->i_count); | 191 | atomic_inc(&inode->i_count); |
188 | 192 | ||
189 | return ext2_add_nondir(dentry, inode); | 193 | err = ext2_add_link(dentry, inode); |
194 | if (!err) { | ||
195 | d_instantiate(dentry, inode); | ||
196 | return 0; | ||
197 | } | ||
198 | inode_dec_link_count(inode); | ||
199 | iput(inode); | ||
200 | return err; | ||
190 | } | 201 | } |
191 | 202 | ||
192 | static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) | 203 | static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) |
@@ -222,12 +233,14 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) | |||
222 | goto out_fail; | 233 | goto out_fail; |
223 | 234 | ||
224 | d_instantiate(dentry, inode); | 235 | d_instantiate(dentry, inode); |
236 | unlock_new_inode(inode); | ||
225 | out: | 237 | out: |
226 | return err; | 238 | return err; |
227 | 239 | ||
228 | out_fail: | 240 | out_fail: |
229 | inode_dec_link_count(inode); | 241 | inode_dec_link_count(inode); |
230 | inode_dec_link_count(inode); | 242 | inode_dec_link_count(inode); |
243 | unlock_new_inode(inode); | ||
231 | iput(inode); | 244 | iput(inode); |
232 | out_dir: | 245 | out_dir: |
233 | inode_dec_link_count(dir); | 246 | inode_dec_link_count(dir); |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 490bd0ed7896..5655fbcbd11f 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
@@ -579,7 +579,10 @@ got: | |||
579 | ext3_set_inode_flags(inode); | 579 | ext3_set_inode_flags(inode); |
580 | if (IS_DIRSYNC(inode)) | 580 | if (IS_DIRSYNC(inode)) |
581 | handle->h_sync = 1; | 581 | handle->h_sync = 1; |
582 | insert_inode_hash(inode); | 582 | if (insert_inode_locked(inode) < 0) { |
583 | err = -EINVAL; | ||
584 | goto fail_drop; | ||
585 | } | ||
583 | spin_lock(&sbi->s_next_gen_lock); | 586 | spin_lock(&sbi->s_next_gen_lock); |
584 | inode->i_generation = sbi->s_next_generation++; | 587 | inode->i_generation = sbi->s_next_generation++; |
585 | spin_unlock(&sbi->s_next_gen_lock); | 588 | spin_unlock(&sbi->s_next_gen_lock); |
@@ -627,6 +630,7 @@ fail_drop: | |||
627 | DQUOT_DROP(inode); | 630 | DQUOT_DROP(inode); |
628 | inode->i_flags |= S_NOQUOTA; | 631 | inode->i_flags |= S_NOQUOTA; |
629 | inode->i_nlink = 0; | 632 | inode->i_nlink = 0; |
633 | unlock_new_inode(inode); | ||
630 | iput(inode); | 634 | iput(inode); |
631 | brelse(bitmap_bh); | 635 | brelse(bitmap_bh); |
632 | return ERR_PTR(err); | 636 | return ERR_PTR(err); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index f8424ad89971..c4bdccf976b5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/uio.h> | 37 | #include <linux/uio.h> |
38 | #include <linux/bio.h> | 38 | #include <linux/bio.h> |
39 | #include <linux/fiemap.h> | 39 | #include <linux/fiemap.h> |
40 | #include <linux/namei.h> | ||
40 | #include "xattr.h" | 41 | #include "xattr.h" |
41 | #include "acl.h" | 42 | #include "acl.h" |
42 | 43 | ||
@@ -2817,9 +2818,11 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
2817 | inode->i_op = &ext3_dir_inode_operations; | 2818 | inode->i_op = &ext3_dir_inode_operations; |
2818 | inode->i_fop = &ext3_dir_operations; | 2819 | inode->i_fop = &ext3_dir_operations; |
2819 | } else if (S_ISLNK(inode->i_mode)) { | 2820 | } else if (S_ISLNK(inode->i_mode)) { |
2820 | if (ext3_inode_is_fast_symlink(inode)) | 2821 | if (ext3_inode_is_fast_symlink(inode)) { |
2821 | inode->i_op = &ext3_fast_symlink_inode_operations; | 2822 | inode->i_op = &ext3_fast_symlink_inode_operations; |
2822 | else { | 2823 | nd_terminate_link(ei->i_data, inode->i_size, |
2824 | sizeof(ei->i_data) - 1); | ||
2825 | } else { | ||
2823 | inode->i_op = &ext3_symlink_inode_operations; | 2826 | inode->i_op = &ext3_symlink_inode_operations; |
2824 | ext3_set_aops(inode); | 2827 | ext3_set_aops(inode); |
2825 | } | 2828 | } |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 3e5edc92aa0b..297ea8dfac7c 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1652,9 +1652,11 @@ static int ext3_add_nondir(handle_t *handle, | |||
1652 | if (!err) { | 1652 | if (!err) { |
1653 | ext3_mark_inode_dirty(handle, inode); | 1653 | ext3_mark_inode_dirty(handle, inode); |
1654 | d_instantiate(dentry, inode); | 1654 | d_instantiate(dentry, inode); |
1655 | unlock_new_inode(inode); | ||
1655 | return 0; | 1656 | return 0; |
1656 | } | 1657 | } |
1657 | drop_nlink(inode); | 1658 | drop_nlink(inode); |
1659 | unlock_new_inode(inode); | ||
1658 | iput(inode); | 1660 | iput(inode); |
1659 | return err; | 1661 | return err; |
1660 | } | 1662 | } |
@@ -1765,6 +1767,7 @@ retry: | |||
1765 | dir_block = ext3_bread (handle, inode, 0, 1, &err); | 1767 | dir_block = ext3_bread (handle, inode, 0, 1, &err); |
1766 | if (!dir_block) { | 1768 | if (!dir_block) { |
1767 | drop_nlink(inode); /* is this nlink == 0? */ | 1769 | drop_nlink(inode); /* is this nlink == 0? */ |
1770 | unlock_new_inode(inode); | ||
1768 | ext3_mark_inode_dirty(handle, inode); | 1771 | ext3_mark_inode_dirty(handle, inode); |
1769 | iput (inode); | 1772 | iput (inode); |
1770 | goto out_stop; | 1773 | goto out_stop; |
@@ -1792,6 +1795,7 @@ retry: | |||
1792 | err = ext3_add_entry (handle, dentry, inode); | 1795 | err = ext3_add_entry (handle, dentry, inode); |
1793 | if (err) { | 1796 | if (err) { |
1794 | inode->i_nlink = 0; | 1797 | inode->i_nlink = 0; |
1798 | unlock_new_inode(inode); | ||
1795 | ext3_mark_inode_dirty(handle, inode); | 1799 | ext3_mark_inode_dirty(handle, inode); |
1796 | iput (inode); | 1800 | iput (inode); |
1797 | goto out_stop; | 1801 | goto out_stop; |
@@ -1800,6 +1804,7 @@ retry: | |||
1800 | ext3_update_dx_flag(dir); | 1804 | ext3_update_dx_flag(dir); |
1801 | ext3_mark_inode_dirty(handle, dir); | 1805 | ext3_mark_inode_dirty(handle, dir); |
1802 | d_instantiate(dentry, inode); | 1806 | d_instantiate(dentry, inode); |
1807 | unlock_new_inode(inode); | ||
1803 | out_stop: | 1808 | out_stop: |
1804 | ext3_journal_stop(handle); | 1809 | ext3_journal_stop(handle); |
1805 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 1810 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
@@ -2174,6 +2179,7 @@ retry: | |||
2174 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2179 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
2175 | if (err) { | 2180 | if (err) { |
2176 | drop_nlink(inode); | 2181 | drop_nlink(inode); |
2182 | unlock_new_inode(inode); | ||
2177 | ext3_mark_inode_dirty(handle, inode); | 2183 | ext3_mark_inode_dirty(handle, inode); |
2178 | iput (inode); | 2184 | iput (inode); |
2179 | goto out_stop; | 2185 | goto out_stop; |
@@ -2221,7 +2227,14 @@ retry: | |||
2221 | inc_nlink(inode); | 2227 | inc_nlink(inode); |
2222 | atomic_inc(&inode->i_count); | 2228 | atomic_inc(&inode->i_count); |
2223 | 2229 | ||
2224 | err = ext3_add_nondir(handle, dentry, inode); | 2230 | err = ext3_add_entry(handle, dentry, inode); |
2231 | if (!err) { | ||
2232 | ext3_mark_inode_dirty(handle, inode); | ||
2233 | d_instantiate(dentry, inode); | ||
2234 | } else { | ||
2235 | drop_nlink(inode); | ||
2236 | iput(inode); | ||
2237 | } | ||
2225 | ext3_journal_stop(handle); | 2238 | ext3_journal_stop(handle); |
2226 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 2239 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
2227 | goto retry; | 2240 | goto retry; |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 08cac9fcace2..6e6052879aa2 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -826,7 +826,10 @@ got: | |||
826 | ext4_set_inode_flags(inode); | 826 | ext4_set_inode_flags(inode); |
827 | if (IS_DIRSYNC(inode)) | 827 | if (IS_DIRSYNC(inode)) |
828 | handle->h_sync = 1; | 828 | handle->h_sync = 1; |
829 | insert_inode_hash(inode); | 829 | if (insert_inode_locked(inode) < 0) { |
830 | err = -EINVAL; | ||
831 | goto fail_drop; | ||
832 | } | ||
830 | spin_lock(&sbi->s_next_gen_lock); | 833 | spin_lock(&sbi->s_next_gen_lock); |
831 | inode->i_generation = sbi->s_next_generation++; | 834 | inode->i_generation = sbi->s_next_generation++; |
832 | spin_unlock(&sbi->s_next_gen_lock); | 835 | spin_unlock(&sbi->s_next_gen_lock); |
@@ -881,6 +884,7 @@ fail_drop: | |||
881 | DQUOT_DROP(inode); | 884 | DQUOT_DROP(inode); |
882 | inode->i_flags |= S_NOQUOTA; | 885 | inode->i_flags |= S_NOQUOTA; |
883 | inode->i_nlink = 0; | 886 | inode->i_nlink = 0; |
887 | unlock_new_inode(inode); | ||
884 | iput(inode); | 888 | iput(inode); |
885 | brelse(bitmap_bh); | 889 | brelse(bitmap_bh); |
886 | return ERR_PTR(err); | 890 | return ERR_PTR(err); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index be21a5ae33cb..7c3325e0b005 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/writeback.h> | 34 | #include <linux/writeback.h> |
35 | #include <linux/pagevec.h> | 35 | #include <linux/pagevec.h> |
36 | #include <linux/mpage.h> | 36 | #include <linux/mpage.h> |
37 | #include <linux/namei.h> | ||
37 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
38 | #include <linux/bio.h> | 39 | #include <linux/bio.h> |
39 | #include "ext4_jbd2.h" | 40 | #include "ext4_jbd2.h" |
@@ -4164,9 +4165,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4164 | inode->i_op = &ext4_dir_inode_operations; | 4165 | inode->i_op = &ext4_dir_inode_operations; |
4165 | inode->i_fop = &ext4_dir_operations; | 4166 | inode->i_fop = &ext4_dir_operations; |
4166 | } else if (S_ISLNK(inode->i_mode)) { | 4167 | } else if (S_ISLNK(inode->i_mode)) { |
4167 | if (ext4_inode_is_fast_symlink(inode)) | 4168 | if (ext4_inode_is_fast_symlink(inode)) { |
4168 | inode->i_op = &ext4_fast_symlink_inode_operations; | 4169 | inode->i_op = &ext4_fast_symlink_inode_operations; |
4169 | else { | 4170 | nd_terminate_link(ei->i_data, inode->i_size, |
4171 | sizeof(ei->i_data) - 1); | ||
4172 | } else { | ||
4170 | inode->i_op = &ext4_symlink_inode_operations; | 4173 | inode->i_op = &ext4_symlink_inode_operations; |
4171 | ext4_set_aops(inode); | 4174 | ext4_set_aops(inode); |
4172 | } | 4175 | } |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 63adcb792988..da98a9012fa5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1693,9 +1693,11 @@ static int ext4_add_nondir(handle_t *handle, | |||
1693 | if (!err) { | 1693 | if (!err) { |
1694 | ext4_mark_inode_dirty(handle, inode); | 1694 | ext4_mark_inode_dirty(handle, inode); |
1695 | d_instantiate(dentry, inode); | 1695 | d_instantiate(dentry, inode); |
1696 | unlock_new_inode(inode); | ||
1696 | return 0; | 1697 | return 0; |
1697 | } | 1698 | } |
1698 | drop_nlink(inode); | 1699 | drop_nlink(inode); |
1700 | unlock_new_inode(inode); | ||
1699 | iput(inode); | 1701 | iput(inode); |
1700 | return err; | 1702 | return err; |
1701 | } | 1703 | } |
@@ -1830,6 +1832,7 @@ retry: | |||
1830 | if (err) { | 1832 | if (err) { |
1831 | out_clear_inode: | 1833 | out_clear_inode: |
1832 | clear_nlink(inode); | 1834 | clear_nlink(inode); |
1835 | unlock_new_inode(inode); | ||
1833 | ext4_mark_inode_dirty(handle, inode); | 1836 | ext4_mark_inode_dirty(handle, inode); |
1834 | iput(inode); | 1837 | iput(inode); |
1835 | goto out_stop; | 1838 | goto out_stop; |
@@ -1838,6 +1841,7 @@ out_clear_inode: | |||
1838 | ext4_update_dx_flag(dir); | 1841 | ext4_update_dx_flag(dir); |
1839 | ext4_mark_inode_dirty(handle, dir); | 1842 | ext4_mark_inode_dirty(handle, dir); |
1840 | d_instantiate(dentry, inode); | 1843 | d_instantiate(dentry, inode); |
1844 | unlock_new_inode(inode); | ||
1841 | out_stop: | 1845 | out_stop: |
1842 | ext4_journal_stop(handle); | 1846 | ext4_journal_stop(handle); |
1843 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 1847 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
@@ -2212,6 +2216,7 @@ retry: | |||
2212 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2216 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
2213 | if (err) { | 2217 | if (err) { |
2214 | clear_nlink(inode); | 2218 | clear_nlink(inode); |
2219 | unlock_new_inode(inode); | ||
2215 | ext4_mark_inode_dirty(handle, inode); | 2220 | ext4_mark_inode_dirty(handle, inode); |
2216 | iput(inode); | 2221 | iput(inode); |
2217 | goto out_stop; | 2222 | goto out_stop; |
@@ -2262,7 +2267,14 @@ retry: | |||
2262 | ext4_inc_count(handle, inode); | 2267 | ext4_inc_count(handle, inode); |
2263 | atomic_inc(&inode->i_count); | 2268 | atomic_inc(&inode->i_count); |
2264 | 2269 | ||
2265 | err = ext4_add_nondir(handle, dentry, inode); | 2270 | err = ext4_add_entry(handle, dentry, inode); |
2271 | if (!err) { | ||
2272 | ext4_mark_inode_dirty(handle, inode); | ||
2273 | d_instantiate(dentry, inode); | ||
2274 | } else { | ||
2275 | drop_nlink(inode); | ||
2276 | iput(inode); | ||
2277 | } | ||
2266 | ext4_journal_stop(handle); | 2278 | ext4_journal_stop(handle); |
2267 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 2279 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
2268 | goto retry; | 2280 | goto retry; |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 67e058357098..3a7f603b6982 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -841,7 +841,6 @@ const struct file_operations fat_dir_operations = { | |||
841 | .compat_ioctl = fat_compat_dir_ioctl, | 841 | .compat_ioctl = fat_compat_dir_ioctl, |
842 | #endif | 842 | #endif |
843 | .fsync = file_fsync, | 843 | .fsync = file_fsync, |
844 | .llseek = generic_file_llseek, | ||
845 | }; | 844 | }; |
846 | 845 | ||
847 | static int fat_get_short_entry(struct inode *dir, loff_t *pos, | 846 | static int fat_get_short_entry(struct inode *dir, loff_t *pos, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index d937aaf77374..6b74d09adbe5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -749,6 +749,8 @@ static struct dentry *fat_get_parent(struct dentry *child) | |||
749 | brelse(bh); | 749 | brelse(bh); |
750 | 750 | ||
751 | parent = d_obtain_alias(inode); | 751 | parent = d_obtain_alias(inode); |
752 | if (!IS_ERR(parent)) | ||
753 | parent->d_op = sb->s_root->d_op; | ||
752 | out: | 754 | out: |
753 | unlock_super(sb); | 755 | unlock_super(sb); |
754 | 756 | ||
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index bf326d4356a3..8ae32e37673c 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
@@ -78,7 +78,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | |||
78 | * for creation. | 78 | * for creation. |
79 | */ | 79 | */ |
80 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { | 80 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { |
81 | if (nd->flags & LOOKUP_CREATE) | 81 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/fs/file_table.c b/fs/file_table.c index 0fbcacc3ea75..bbeeac6efa1a 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -32,6 +32,9 @@ struct files_stat_struct files_stat = { | |||
32 | /* public. Not pretty! */ | 32 | /* public. Not pretty! */ |
33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); | 33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); |
34 | 34 | ||
35 | /* SLAB cache for file structures */ | ||
36 | static struct kmem_cache *filp_cachep __read_mostly; | ||
37 | |||
35 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; | 38 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; |
36 | 39 | ||
37 | static inline void file_free_rcu(struct rcu_head *head) | 40 | static inline void file_free_rcu(struct rcu_head *head) |
@@ -397,7 +400,12 @@ too_bad: | |||
397 | void __init files_init(unsigned long mempages) | 400 | void __init files_init(unsigned long mempages) |
398 | { | 401 | { |
399 | int n; | 402 | int n; |
400 | /* One file with associated inode and dcache is very roughly 1K. | 403 | |
404 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | ||
405 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | ||
406 | |||
407 | /* | ||
408 | * One file with associated inode and dcache is very roughly 1K. | ||
401 | * Per default don't use more than 10% of our memory for files. | 409 | * Per default don't use more than 10% of our memory for files. |
402 | */ | 410 | */ |
403 | 411 | ||
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 9f3f2ceb73f0..03a6ea5e99f7 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c | |||
@@ -325,8 +325,10 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
325 | if (!VXFS_ISIMMED(vip)) { | 325 | if (!VXFS_ISIMMED(vip)) { |
326 | ip->i_op = &page_symlink_inode_operations; | 326 | ip->i_op = &page_symlink_inode_operations; |
327 | ip->i_mapping->a_ops = &vxfs_aops; | 327 | ip->i_mapping->a_ops = &vxfs_aops; |
328 | } else | 328 | } else { |
329 | ip->i_op = &vxfs_immed_symlink_iops; | 329 | ip->i_op = &vxfs_immed_symlink_iops; |
330 | vip->vii_immed.vi_immed[ip->i_size] = '\0'; | ||
331 | } | ||
330 | } else | 332 | } else |
331 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); | 333 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); |
332 | 334 | ||
diff --git a/fs/inode.c b/fs/inode.c index 098a2443196f..7de1cda92489 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1032,6 +1032,65 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino) | |||
1032 | 1032 | ||
1033 | EXPORT_SYMBOL(iget_locked); | 1033 | EXPORT_SYMBOL(iget_locked); |
1034 | 1034 | ||
1035 | int insert_inode_locked(struct inode *inode) | ||
1036 | { | ||
1037 | struct super_block *sb = inode->i_sb; | ||
1038 | ino_t ino = inode->i_ino; | ||
1039 | struct hlist_head *head = inode_hashtable + hash(sb, ino); | ||
1040 | struct inode *old; | ||
1041 | |||
1042 | inode->i_state |= I_LOCK|I_NEW; | ||
1043 | while (1) { | ||
1044 | spin_lock(&inode_lock); | ||
1045 | old = find_inode_fast(sb, head, ino); | ||
1046 | if (likely(!old)) { | ||
1047 | hlist_add_head(&inode->i_hash, head); | ||
1048 | spin_unlock(&inode_lock); | ||
1049 | return 0; | ||
1050 | } | ||
1051 | __iget(old); | ||
1052 | spin_unlock(&inode_lock); | ||
1053 | wait_on_inode(old); | ||
1054 | if (unlikely(!hlist_unhashed(&old->i_hash))) { | ||
1055 | iput(old); | ||
1056 | return -EBUSY; | ||
1057 | } | ||
1058 | iput(old); | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | EXPORT_SYMBOL(insert_inode_locked); | ||
1063 | |||
1064 | int insert_inode_locked4(struct inode *inode, unsigned long hashval, | ||
1065 | int (*test)(struct inode *, void *), void *data) | ||
1066 | { | ||
1067 | struct super_block *sb = inode->i_sb; | ||
1068 | struct hlist_head *head = inode_hashtable + hash(sb, hashval); | ||
1069 | struct inode *old; | ||
1070 | |||
1071 | inode->i_state |= I_LOCK|I_NEW; | ||
1072 | |||
1073 | while (1) { | ||
1074 | spin_lock(&inode_lock); | ||
1075 | old = find_inode(sb, head, test, data); | ||
1076 | if (likely(!old)) { | ||
1077 | hlist_add_head(&inode->i_hash, head); | ||
1078 | spin_unlock(&inode_lock); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | __iget(old); | ||
1082 | spin_unlock(&inode_lock); | ||
1083 | wait_on_inode(old); | ||
1084 | if (unlikely(!hlist_unhashed(&old->i_hash))) { | ||
1085 | iput(old); | ||
1086 | return -EBUSY; | ||
1087 | } | ||
1088 | iput(old); | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | EXPORT_SYMBOL(insert_inode_locked4); | ||
1093 | |||
1035 | /** | 1094 | /** |
1036 | * __insert_inode_hash - hash an inode | 1095 | * __insert_inode_hash - hash an inode |
1037 | * @inode: unhashed inode | 1096 | * @inode: unhashed inode |
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index 70022fd1c539..d4d142c2edd4 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c | |||
@@ -79,7 +79,8 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
79 | inode = new_inode(sb); | 79 | inode = new_inode(sb); |
80 | if (!inode) { | 80 | if (!inode) { |
81 | jfs_warn("ialloc: new_inode returned NULL!"); | 81 | jfs_warn("ialloc: new_inode returned NULL!"); |
82 | return ERR_PTR(-ENOMEM); | 82 | rc = -ENOMEM; |
83 | goto fail; | ||
83 | } | 84 | } |
84 | 85 | ||
85 | jfs_inode = JFS_IP(inode); | 86 | jfs_inode = JFS_IP(inode); |
@@ -89,8 +90,12 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
89 | jfs_warn("ialloc: diAlloc returned %d!", rc); | 90 | jfs_warn("ialloc: diAlloc returned %d!", rc); |
90 | if (rc == -EIO) | 91 | if (rc == -EIO) |
91 | make_bad_inode(inode); | 92 | make_bad_inode(inode); |
92 | iput(inode); | 93 | goto fail_put; |
93 | return ERR_PTR(rc); | 94 | } |
95 | |||
96 | if (insert_inode_locked(inode) < 0) { | ||
97 | rc = -EINVAL; | ||
98 | goto fail_unlock; | ||
94 | } | 99 | } |
95 | 100 | ||
96 | inode->i_uid = current_fsuid(); | 101 | inode->i_uid = current_fsuid(); |
@@ -112,11 +117,8 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
112 | * Allocate inode to quota. | 117 | * Allocate inode to quota. |
113 | */ | 118 | */ |
114 | if (DQUOT_ALLOC_INODE(inode)) { | 119 | if (DQUOT_ALLOC_INODE(inode)) { |
115 | DQUOT_DROP(inode); | 120 | rc = -EDQUOT; |
116 | inode->i_flags |= S_NOQUOTA; | 121 | goto fail_drop; |
117 | inode->i_nlink = 0; | ||
118 | iput(inode); | ||
119 | return ERR_PTR(-EDQUOT); | ||
120 | } | 122 | } |
121 | 123 | ||
122 | inode->i_mode = mode; | 124 | inode->i_mode = mode; |
@@ -158,4 +160,15 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
158 | jfs_info("ialloc returns inode = 0x%p\n", inode); | 160 | jfs_info("ialloc returns inode = 0x%p\n", inode); |
159 | 161 | ||
160 | return inode; | 162 | return inode; |
163 | |||
164 | fail_drop: | ||
165 | DQUOT_DROP(inode); | ||
166 | inode->i_flags |= S_NOQUOTA; | ||
167 | fail_unlock: | ||
168 | inode->i_nlink = 0; | ||
169 | unlock_new_inode(inode); | ||
170 | fail_put: | ||
171 | iput(inode); | ||
172 | fail: | ||
173 | return ERR_PTR(rc); | ||
161 | } | 174 | } |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index cc3cedffbfa1..b4de56b851e4 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -155,7 +155,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
155 | ip->i_fop = &jfs_file_operations; | 155 | ip->i_fop = &jfs_file_operations; |
156 | ip->i_mapping->a_ops = &jfs_aops; | 156 | ip->i_mapping->a_ops = &jfs_aops; |
157 | 157 | ||
158 | insert_inode_hash(ip); | ||
159 | mark_inode_dirty(ip); | 158 | mark_inode_dirty(ip); |
160 | 159 | ||
161 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 160 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
@@ -171,9 +170,12 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
171 | if (rc) { | 170 | if (rc) { |
172 | free_ea_wmap(ip); | 171 | free_ea_wmap(ip); |
173 | ip->i_nlink = 0; | 172 | ip->i_nlink = 0; |
173 | unlock_new_inode(ip); | ||
174 | iput(ip); | 174 | iput(ip); |
175 | } else | 175 | } else { |
176 | d_instantiate(dentry, ip); | 176 | d_instantiate(dentry, ip); |
177 | unlock_new_inode(ip); | ||
178 | } | ||
177 | 179 | ||
178 | out2: | 180 | out2: |
179 | free_UCSname(&dname); | 181 | free_UCSname(&dname); |
@@ -289,7 +291,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
289 | ip->i_op = &jfs_dir_inode_operations; | 291 | ip->i_op = &jfs_dir_inode_operations; |
290 | ip->i_fop = &jfs_dir_operations; | 292 | ip->i_fop = &jfs_dir_operations; |
291 | 293 | ||
292 | insert_inode_hash(ip); | ||
293 | mark_inode_dirty(ip); | 294 | mark_inode_dirty(ip); |
294 | 295 | ||
295 | /* update parent directory inode */ | 296 | /* update parent directory inode */ |
@@ -306,9 +307,12 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
306 | if (rc) { | 307 | if (rc) { |
307 | free_ea_wmap(ip); | 308 | free_ea_wmap(ip); |
308 | ip->i_nlink = 0; | 309 | ip->i_nlink = 0; |
310 | unlock_new_inode(ip); | ||
309 | iput(ip); | 311 | iput(ip); |
310 | } else | 312 | } else { |
311 | d_instantiate(dentry, ip); | 313 | d_instantiate(dentry, ip); |
314 | unlock_new_inode(ip); | ||
315 | } | ||
312 | 316 | ||
313 | out2: | 317 | out2: |
314 | free_UCSname(&dname); | 318 | free_UCSname(&dname); |
@@ -1019,7 +1023,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
1019 | goto out3; | 1023 | goto out3; |
1020 | } | 1024 | } |
1021 | 1025 | ||
1022 | insert_inode_hash(ip); | ||
1023 | mark_inode_dirty(ip); | 1026 | mark_inode_dirty(ip); |
1024 | 1027 | ||
1025 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 1028 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
@@ -1039,9 +1042,12 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
1039 | if (rc) { | 1042 | if (rc) { |
1040 | free_ea_wmap(ip); | 1043 | free_ea_wmap(ip); |
1041 | ip->i_nlink = 0; | 1044 | ip->i_nlink = 0; |
1045 | unlock_new_inode(ip); | ||
1042 | iput(ip); | 1046 | iput(ip); |
1043 | } else | 1047 | } else { |
1044 | d_instantiate(dentry, ip); | 1048 | d_instantiate(dentry, ip); |
1049 | unlock_new_inode(ip); | ||
1050 | } | ||
1045 | 1051 | ||
1046 | out2: | 1052 | out2: |
1047 | free_UCSname(&dname); | 1053 | free_UCSname(&dname); |
@@ -1399,7 +1405,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1399 | jfs_ip->dev = new_encode_dev(rdev); | 1405 | jfs_ip->dev = new_encode_dev(rdev); |
1400 | init_special_inode(ip, ip->i_mode, rdev); | 1406 | init_special_inode(ip, ip->i_mode, rdev); |
1401 | 1407 | ||
1402 | insert_inode_hash(ip); | ||
1403 | mark_inode_dirty(ip); | 1408 | mark_inode_dirty(ip); |
1404 | 1409 | ||
1405 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 1410 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
@@ -1417,9 +1422,12 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1417 | if (rc) { | 1422 | if (rc) { |
1418 | free_ea_wmap(ip); | 1423 | free_ea_wmap(ip); |
1419 | ip->i_nlink = 0; | 1424 | ip->i_nlink = 0; |
1425 | unlock_new_inode(ip); | ||
1420 | iput(ip); | 1426 | iput(ip); |
1421 | } else | 1427 | } else { |
1422 | d_instantiate(dentry, ip); | 1428 | d_instantiate(dentry, ip); |
1429 | unlock_new_inode(ip); | ||
1430 | } | ||
1423 | 1431 | ||
1424 | out1: | 1432 | out1: |
1425 | free_UCSname(&dname); | 1433 | free_UCSname(&dname); |
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..dd5c9f0bf829 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -226,6 +226,16 @@ int generic_permission(struct inode *inode, int mask, | |||
226 | return -EACCES; | 226 | return -EACCES; |
227 | } | 227 | } |
228 | 228 | ||
229 | /** | ||
230 | * inode_permission - check for access rights to a given inode | ||
231 | * @inode: inode to check permission on | ||
232 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
233 | * | ||
234 | * Used to check for read/write/execute permissions on an inode. | ||
235 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
236 | * for filesystem access without changing the "normal" uids which | ||
237 | * are used for other things. | ||
238 | */ | ||
229 | int inode_permission(struct inode *inode, int mask) | 239 | int inode_permission(struct inode *inode, int mask) |
230 | { | 240 | { |
231 | int retval; | 241 | int retval; |
@@ -247,7 +257,6 @@ int inode_permission(struct inode *inode, int mask) | |||
247 | return -EACCES; | 257 | return -EACCES; |
248 | } | 258 | } |
249 | 259 | ||
250 | /* Ordinary permission routines do not understand MAY_APPEND. */ | ||
251 | if (inode->i_op && inode->i_op->permission) | 260 | if (inode->i_op && inode->i_op->permission) |
252 | retval = inode->i_op->permission(inode, mask); | 261 | retval = inode->i_op->permission(inode, mask); |
253 | else | 262 | else |
@@ -265,21 +274,6 @@ int inode_permission(struct inode *inode, int mask) | |||
265 | } | 274 | } |
266 | 275 | ||
267 | /** | 276 | /** |
268 | * vfs_permission - check for access rights to a given path | ||
269 | * @nd: lookup result that describes the path | ||
270 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
271 | * | ||
272 | * Used to check for read/write/execute permissions on a path. | ||
273 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
274 | * for filesystem access without changing the "normal" uids which | ||
275 | * are used for other things. | ||
276 | */ | ||
277 | int vfs_permission(struct nameidata *nd, int mask) | ||
278 | { | ||
279 | return inode_permission(nd->path.dentry->d_inode, mask); | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * file_permission - check for additional access rights to a given file | 277 | * file_permission - check for additional access rights to a given file |
284 | * @file: file to check access rights for | 278 | * @file: file to check access rights for |
285 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 279 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
@@ -289,7 +283,7 @@ int vfs_permission(struct nameidata *nd, int mask) | |||
289 | * | 283 | * |
290 | * Note: | 284 | * Note: |
291 | * Do not use this function in new code. All access checks should | 285 | * Do not use this function in new code. All access checks should |
292 | * be done using vfs_permission(). | 286 | * be done using inode_permission(). |
293 | */ | 287 | */ |
294 | int file_permission(struct file *file, int mask) | 288 | int file_permission(struct file *file, int mask) |
295 | { | 289 | { |
@@ -527,18 +521,6 @@ out_unlock: | |||
527 | return result; | 521 | return result; |
528 | } | 522 | } |
529 | 523 | ||
530 | /* SMP-safe */ | ||
531 | static __always_inline void | ||
532 | walk_init_root(const char *name, struct nameidata *nd) | ||
533 | { | ||
534 | struct fs_struct *fs = current->fs; | ||
535 | |||
536 | read_lock(&fs->lock); | ||
537 | nd->path = fs->root; | ||
538 | path_get(&fs->root); | ||
539 | read_unlock(&fs->lock); | ||
540 | } | ||
541 | |||
542 | /* | 524 | /* |
543 | * Wrapper to retry pathname resolution whenever the underlying | 525 | * Wrapper to retry pathname resolution whenever the underlying |
544 | * file system returns an ESTALE. | 526 | * file system returns an ESTALE. |
@@ -576,9 +558,16 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
576 | goto fail; | 558 | goto fail; |
577 | 559 | ||
578 | if (*link == '/') { | 560 | if (*link == '/') { |
561 | struct fs_struct *fs = current->fs; | ||
562 | |||
579 | path_put(&nd->path); | 563 | path_put(&nd->path); |
580 | walk_init_root(link, nd); | 564 | |
565 | read_lock(&fs->lock); | ||
566 | nd->path = fs->root; | ||
567 | path_get(&fs->root); | ||
568 | read_unlock(&fs->lock); | ||
581 | } | 569 | } |
570 | |||
582 | res = link_path_walk(link, nd); | 571 | res = link_path_walk(link, nd); |
583 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 572 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
584 | return res; | 573 | return res; |
@@ -859,7 +848,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
859 | nd->flags |= LOOKUP_CONTINUE; | 848 | nd->flags |= LOOKUP_CONTINUE; |
860 | err = exec_permission_lite(inode); | 849 | err = exec_permission_lite(inode); |
861 | if (err == -EAGAIN) | 850 | if (err == -EAGAIN) |
862 | err = vfs_permission(nd, MAY_EXEC); | 851 | err = inode_permission(nd->path.dentry->d_inode, |
852 | MAY_EXEC); | ||
863 | if (err) | 853 | if (err) |
864 | break; | 854 | break; |
865 | 855 | ||
@@ -1493,9 +1483,9 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1493 | return error; | 1483 | return error; |
1494 | } | 1484 | } |
1495 | 1485 | ||
1496 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1486 | int may_open(struct path *path, int acc_mode, int flag) |
1497 | { | 1487 | { |
1498 | struct dentry *dentry = nd->path.dentry; | 1488 | struct dentry *dentry = path->dentry; |
1499 | struct inode *inode = dentry->d_inode; | 1489 | struct inode *inode = dentry->d_inode; |
1500 | int error; | 1490 | int error; |
1501 | 1491 | ||
@@ -1516,13 +1506,13 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1516 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1506 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
1517 | flag &= ~O_TRUNC; | 1507 | flag &= ~O_TRUNC; |
1518 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1508 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
1519 | if (nd->path.mnt->mnt_flags & MNT_NODEV) | 1509 | if (path->mnt->mnt_flags & MNT_NODEV) |
1520 | return -EACCES; | 1510 | return -EACCES; |
1521 | 1511 | ||
1522 | flag &= ~O_TRUNC; | 1512 | flag &= ~O_TRUNC; |
1523 | } | 1513 | } |
1524 | 1514 | ||
1525 | error = vfs_permission(nd, acc_mode); | 1515 | error = inode_permission(inode, acc_mode); |
1526 | if (error) | 1516 | if (error) |
1527 | return error; | 1517 | return error; |
1528 | /* | 1518 | /* |
@@ -1556,6 +1546,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1556 | * Refuse to truncate files with mandatory locks held on them. | 1546 | * Refuse to truncate files with mandatory locks held on them. |
1557 | */ | 1547 | */ |
1558 | error = locks_verify_locked(inode); | 1548 | error = locks_verify_locked(inode); |
1549 | if (!error) | ||
1550 | error = security_path_truncate(path, 0, | ||
1551 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
1559 | if (!error) { | 1552 | if (!error) { |
1560 | DQUOT_INIT(inode); | 1553 | DQUOT_INIT(inode); |
1561 | 1554 | ||
@@ -1586,14 +1579,18 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
1586 | 1579 | ||
1587 | if (!IS_POSIXACL(dir->d_inode)) | 1580 | if (!IS_POSIXACL(dir->d_inode)) |
1588 | mode &= ~current->fs->umask; | 1581 | mode &= ~current->fs->umask; |
1582 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
1583 | if (error) | ||
1584 | goto out_unlock; | ||
1589 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1585 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
1586 | out_unlock: | ||
1590 | mutex_unlock(&dir->d_inode->i_mutex); | 1587 | mutex_unlock(&dir->d_inode->i_mutex); |
1591 | dput(nd->path.dentry); | 1588 | dput(nd->path.dentry); |
1592 | nd->path.dentry = path->dentry; | 1589 | nd->path.dentry = path->dentry; |
1593 | if (error) | 1590 | if (error) |
1594 | return error; | 1591 | return error; |
1595 | /* Don't check for write permission, don't truncate */ | 1592 | /* Don't check for write permission, don't truncate */ |
1596 | return may_open(nd, 0, flag & ~O_TRUNC); | 1593 | return may_open(&nd->path, 0, flag & ~O_TRUNC); |
1597 | } | 1594 | } |
1598 | 1595 | ||
1599 | /* | 1596 | /* |
@@ -1779,7 +1776,7 @@ ok: | |||
1779 | if (error) | 1776 | if (error) |
1780 | goto exit; | 1777 | goto exit; |
1781 | } | 1778 | } |
1782 | error = may_open(&nd, acc_mode, flag); | 1779 | error = may_open(&nd.path, acc_mode, flag); |
1783 | if (error) { | 1780 | if (error) { |
1784 | if (will_write) | 1781 | if (will_write) |
1785 | mnt_drop_write(nd.path.mnt); | 1782 | mnt_drop_write(nd.path.mnt); |
@@ -1999,6 +1996,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1999 | error = mnt_want_write(nd.path.mnt); | 1996 | error = mnt_want_write(nd.path.mnt); |
2000 | if (error) | 1997 | if (error) |
2001 | goto out_dput; | 1998 | goto out_dput; |
1999 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
2000 | if (error) | ||
2001 | goto out_drop_write; | ||
2002 | switch (mode & S_IFMT) { | 2002 | switch (mode & S_IFMT) { |
2003 | case 0: case S_IFREG: | 2003 | case 0: case S_IFREG: |
2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
@@ -2011,6 +2011,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
2012 | break; | 2012 | break; |
2013 | } | 2013 | } |
2014 | out_drop_write: | ||
2014 | mnt_drop_write(nd.path.mnt); | 2015 | mnt_drop_write(nd.path.mnt); |
2015 | out_dput: | 2016 | out_dput: |
2016 | dput(dentry); | 2017 | dput(dentry); |
@@ -2070,7 +2071,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2070 | error = mnt_want_write(nd.path.mnt); | 2071 | error = mnt_want_write(nd.path.mnt); |
2071 | if (error) | 2072 | if (error) |
2072 | goto out_dput; | 2073 | goto out_dput; |
2074 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
2075 | if (error) | ||
2076 | goto out_drop_write; | ||
2073 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2077 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2078 | out_drop_write: | ||
2074 | mnt_drop_write(nd.path.mnt); | 2079 | mnt_drop_write(nd.path.mnt); |
2075 | out_dput: | 2080 | out_dput: |
2076 | dput(dentry); | 2081 | dput(dentry); |
@@ -2180,7 +2185,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2180 | error = mnt_want_write(nd.path.mnt); | 2185 | error = mnt_want_write(nd.path.mnt); |
2181 | if (error) | 2186 | if (error) |
2182 | goto exit3; | 2187 | goto exit3; |
2188 | error = security_path_rmdir(&nd.path, dentry); | ||
2189 | if (error) | ||
2190 | goto exit4; | ||
2183 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2191 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2192 | exit4: | ||
2184 | mnt_drop_write(nd.path.mnt); | 2193 | mnt_drop_write(nd.path.mnt); |
2185 | exit3: | 2194 | exit3: |
2186 | dput(dentry); | 2195 | dput(dentry); |
@@ -2265,7 +2274,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2265 | error = mnt_want_write(nd.path.mnt); | 2274 | error = mnt_want_write(nd.path.mnt); |
2266 | if (error) | 2275 | if (error) |
2267 | goto exit2; | 2276 | goto exit2; |
2277 | error = security_path_unlink(&nd.path, dentry); | ||
2278 | if (error) | ||
2279 | goto exit3; | ||
2268 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2280 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2281 | exit3: | ||
2269 | mnt_drop_write(nd.path.mnt); | 2282 | mnt_drop_write(nd.path.mnt); |
2270 | exit2: | 2283 | exit2: |
2271 | dput(dentry); | 2284 | dput(dentry); |
@@ -2346,7 +2359,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2346 | error = mnt_want_write(nd.path.mnt); | 2359 | error = mnt_want_write(nd.path.mnt); |
2347 | if (error) | 2360 | if (error) |
2348 | goto out_dput; | 2361 | goto out_dput; |
2362 | error = security_path_symlink(&nd.path, dentry, from); | ||
2363 | if (error) | ||
2364 | goto out_drop_write; | ||
2349 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2365 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
2366 | out_drop_write: | ||
2350 | mnt_drop_write(nd.path.mnt); | 2367 | mnt_drop_write(nd.path.mnt); |
2351 | out_dput: | 2368 | out_dput: |
2352 | dput(dentry); | 2369 | dput(dentry); |
@@ -2443,7 +2460,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2443 | error = mnt_want_write(nd.path.mnt); | 2460 | error = mnt_want_write(nd.path.mnt); |
2444 | if (error) | 2461 | if (error) |
2445 | goto out_dput; | 2462 | goto out_dput; |
2463 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
2464 | if (error) | ||
2465 | goto out_drop_write; | ||
2446 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2466 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
2467 | out_drop_write: | ||
2447 | mnt_drop_write(nd.path.mnt); | 2468 | mnt_drop_write(nd.path.mnt); |
2448 | out_dput: | 2469 | out_dput: |
2449 | dput(new_dentry); | 2470 | dput(new_dentry); |
@@ -2679,8 +2700,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
2679 | error = mnt_want_write(oldnd.path.mnt); | 2700 | error = mnt_want_write(oldnd.path.mnt); |
2680 | if (error) | 2701 | if (error) |
2681 | goto exit5; | 2702 | goto exit5; |
2703 | error = security_path_rename(&oldnd.path, old_dentry, | ||
2704 | &newnd.path, new_dentry); | ||
2705 | if (error) | ||
2706 | goto exit6; | ||
2682 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2707 | error = vfs_rename(old_dir->d_inode, old_dentry, |
2683 | new_dir->d_inode, new_dentry); | 2708 | new_dir->d_inode, new_dentry); |
2709 | exit6: | ||
2684 | mnt_drop_write(oldnd.path.mnt); | 2710 | mnt_drop_write(oldnd.path.mnt); |
2685 | exit5: | 2711 | exit5: |
2686 | dput(new_dentry); | 2712 | dput(new_dentry); |
@@ -2750,13 +2776,16 @@ int vfs_follow_link(struct nameidata *nd, const char *link) | |||
2750 | /* get the link contents into pagecache */ | 2776 | /* get the link contents into pagecache */ |
2751 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 2777 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
2752 | { | 2778 | { |
2753 | struct page * page; | 2779 | char *kaddr; |
2780 | struct page *page; | ||
2754 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2781 | struct address_space *mapping = dentry->d_inode->i_mapping; |
2755 | page = read_mapping_page(mapping, 0, NULL); | 2782 | page = read_mapping_page(mapping, 0, NULL); |
2756 | if (IS_ERR(page)) | 2783 | if (IS_ERR(page)) |
2757 | return (char*)page; | 2784 | return (char*)page; |
2758 | *ppage = page; | 2785 | *ppage = page; |
2759 | return kmap(page); | 2786 | kaddr = kmap(page); |
2787 | nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); | ||
2788 | return kaddr; | ||
2760 | } | 2789 | } |
2761 | 2790 | ||
2762 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2791 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
@@ -2849,7 +2878,6 @@ EXPORT_SYMBOL(path_lookup); | |||
2849 | EXPORT_SYMBOL(kern_path); | 2878 | EXPORT_SYMBOL(kern_path); |
2850 | EXPORT_SYMBOL(vfs_path_lookup); | 2879 | EXPORT_SYMBOL(vfs_path_lookup); |
2851 | EXPORT_SYMBOL(inode_permission); | 2880 | EXPORT_SYMBOL(inode_permission); |
2852 | EXPORT_SYMBOL(vfs_permission); | ||
2853 | EXPORT_SYMBOL(file_permission); | 2881 | EXPORT_SYMBOL(file_permission); |
2854 | EXPORT_SYMBOL(unlock_rename); | 2882 | EXPORT_SYMBOL(unlock_rename); |
2855 | EXPORT_SYMBOL(vfs_create); | 2883 | EXPORT_SYMBOL(vfs_create); |
@@ -2865,3 +2893,10 @@ EXPORT_SYMBOL(vfs_symlink); | |||
2865 | EXPORT_SYMBOL(vfs_unlink); | 2893 | EXPORT_SYMBOL(vfs_unlink); |
2866 | EXPORT_SYMBOL(dentry_unhash); | 2894 | EXPORT_SYMBOL(dentry_unhash); |
2867 | EXPORT_SYMBOL(generic_readlink); | 2895 | EXPORT_SYMBOL(generic_readlink); |
2896 | |||
2897 | /* to be mentioned only in INIT_TASK */ | ||
2898 | struct fs_struct init_fs = { | ||
2899 | .count = ATOMIC_INIT(1), | ||
2900 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
2901 | .umask = 0022, | ||
2902 | }; | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 1c09cab8f7cf..a40685d800a8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1990,7 +1990,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
1990 | if (!new_ns->root) { | 1990 | if (!new_ns->root) { |
1991 | up_write(&namespace_sem); | 1991 | up_write(&namespace_sem); |
1992 | kfree(new_ns); | 1992 | kfree(new_ns); |
1993 | return ERR_PTR(-ENOMEM);; | 1993 | return ERR_PTR(-ENOMEM); |
1994 | } | 1994 | } |
1995 | spin_lock(&vfsmount_lock); | 1995 | spin_lock(&vfsmount_lock); |
1996 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); | 1996 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); |
diff --git a/fs/nfsctl.c b/fs/nfsctl.c index b1acbd6ab6fb..b27451909dff 100644 --- a/fs/nfsctl.c +++ b/fs/nfsctl.c | |||
@@ -38,9 +38,10 @@ static struct file *do_open(char *name, int flags) | |||
38 | return ERR_PTR(error); | 38 | return ERR_PTR(error); |
39 | 39 | ||
40 | if (flags == O_RDWR) | 40 | if (flags == O_RDWR) |
41 | error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); | 41 | error = may_open(&nd.path, MAY_READ|MAY_WRITE, |
42 | FMODE_READ|FMODE_WRITE); | ||
42 | else | 43 | else |
43 | error = may_open(&nd, MAY_WRITE, FMODE_WRITE); | 44 | error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE); |
44 | 45 | ||
45 | if (!error) | 46 | if (!error) |
46 | return dentry_open(nd.path.dentry, nd.path.mnt, flags, | 47 | return dentry_open(nd.path.dentry, nd.path.mnt, flags, |
diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig new file mode 100644 index 000000000000..50914d7303c6 --- /dev/null +++ b/fs/notify/Kconfig | |||
@@ -0,0 +1,2 @@ | |||
1 | source "fs/notify/dnotify/Kconfig" | ||
2 | source "fs/notify/inotify/Kconfig" | ||
diff --git a/fs/notify/Makefile b/fs/notify/Makefile new file mode 100644 index 000000000000..5a95b6010ce7 --- /dev/null +++ b/fs/notify/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-y += dnotify/ | ||
2 | obj-y += inotify/ | ||
diff --git a/fs/notify/dnotify/Kconfig b/fs/notify/dnotify/Kconfig new file mode 100644 index 000000000000..26adf5dfa646 --- /dev/null +++ b/fs/notify/dnotify/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config DNOTIFY | ||
2 | bool "Dnotify support" | ||
3 | default y | ||
4 | help | ||
5 | Dnotify is a directory-based per-fd file change notification system | ||
6 | that uses signals to communicate events to user-space. There exist | ||
7 | superior alternatives, but some applications may still rely on | ||
8 | dnotify. | ||
9 | |||
10 | If unsure, say Y. | ||
diff --git a/fs/notify/dnotify/Makefile b/fs/notify/dnotify/Makefile new file mode 100644 index 000000000000..f145251dcadb --- /dev/null +++ b/fs/notify/dnotify/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_DNOTIFY) += dnotify.o | |||
diff --git a/fs/dnotify.c b/fs/notify/dnotify/dnotify.c index 676073b8dda5..b0aa2cde80bd 100644 --- a/fs/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
@@ -115,9 +115,6 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
115 | dn->dn_next = inode->i_dnotify; | 115 | dn->dn_next = inode->i_dnotify; |
116 | inode->i_dnotify = dn; | 116 | inode->i_dnotify = dn; |
117 | spin_unlock(&inode->i_lock); | 117 | spin_unlock(&inode->i_lock); |
118 | |||
119 | if (filp->f_op && filp->f_op->dir_notify) | ||
120 | return filp->f_op->dir_notify(filp, arg); | ||
121 | return 0; | 118 | return 0; |
122 | 119 | ||
123 | out_free: | 120 | out_free: |
diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig new file mode 100644 index 000000000000..446792841023 --- /dev/null +++ b/fs/notify/inotify/Kconfig | |||
@@ -0,0 +1,27 @@ | |||
1 | config INOTIFY | ||
2 | bool "Inotify file change notification support" | ||
3 | default y | ||
4 | ---help--- | ||
5 | Say Y here to enable inotify support. Inotify is a file change | ||
6 | notification system and a replacement for dnotify. Inotify fixes | ||
7 | numerous shortcomings in dnotify and introduces several new features | ||
8 | including multiple file events, one-shot support, and unmount | ||
9 | notification. | ||
10 | |||
11 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
12 | |||
13 | If unsure, say Y. | ||
14 | |||
15 | config INOTIFY_USER | ||
16 | bool "Inotify support for userspace" | ||
17 | depends on INOTIFY | ||
18 | default y | ||
19 | ---help--- | ||
20 | Say Y here to enable inotify support for userspace, including the | ||
21 | associated system calls. Inotify allows monitoring of both files and | ||
22 | directories via a single open fd. Events are read from the file | ||
23 | descriptor, which is also select()- and poll()-able. | ||
24 | |||
25 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
26 | |||
27 | If unsure, say Y. | ||
diff --git a/fs/notify/inotify/Makefile b/fs/notify/inotify/Makefile new file mode 100644 index 000000000000..e290f3bb9d8d --- /dev/null +++ b/fs/notify/inotify/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_INOTIFY) += inotify.o | ||
2 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | ||
diff --git a/fs/inotify.c b/fs/notify/inotify/inotify.c index dae3f28f30d4..dae3f28f30d4 100644 --- a/fs/inotify.c +++ b/fs/notify/inotify/inotify.c | |||
diff --git a/fs/inotify_user.c b/fs/notify/inotify/inotify_user.c index e2425bbd871f..400f8064a548 100644 --- a/fs/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -76,10 +76,10 @@ struct inotify_device { | |||
76 | struct mutex ev_mutex; /* protects event queue */ | 76 | struct mutex ev_mutex; /* protects event queue */ |
77 | struct mutex up_mutex; /* synchronizes watch updates */ | 77 | struct mutex up_mutex; /* synchronizes watch updates */ |
78 | struct list_head events; /* list of queued events */ | 78 | struct list_head events; /* list of queued events */ |
79 | atomic_t count; /* reference count */ | ||
80 | struct user_struct *user; /* user who opened this dev */ | 79 | struct user_struct *user; /* user who opened this dev */ |
81 | struct inotify_handle *ih; /* inotify handle */ | 80 | struct inotify_handle *ih; /* inotify handle */ |
82 | struct fasync_struct *fa; /* async notification */ | 81 | struct fasync_struct *fa; /* async notification */ |
82 | atomic_t count; /* reference count */ | ||
83 | unsigned int queue_size; /* size of the queue (bytes) */ | 83 | unsigned int queue_size; /* size of the queue (bytes) */ |
84 | unsigned int event_count; /* number of pending events */ | 84 | unsigned int event_count; /* number of pending events */ |
85 | unsigned int max_events; /* maximum number of events */ | 85 | unsigned int max_events; /* maximum number of events */ |
@@ -272,6 +272,8 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
272 | goto put_write_and_out; | 272 | goto put_write_and_out; |
273 | 273 | ||
274 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
275 | if (!error) | ||
276 | error = security_path_truncate(&path, length, 0); | ||
275 | if (!error) { | 277 | if (!error) { |
276 | DQUOT_INIT(inode); | 278 | DQUOT_INIT(inode); |
277 | error = do_truncate(path.dentry, length, 0, NULL); | 279 | error = do_truncate(path.dentry, length, 0, NULL); |
@@ -329,6 +331,9 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
329 | 331 | ||
330 | error = locks_verify_truncate(inode, file, length); | 332 | error = locks_verify_truncate(inode, file, length); |
331 | if (!error) | 333 | if (!error) |
334 | error = security_path_truncate(&file->f_path, length, | ||
335 | ATTR_MTIME|ATTR_CTIME); | ||
336 | if (!error) | ||
332 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 337 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
333 | out_putf: | 338 | out_putf: |
334 | fput(file); | 339 | fput(file); |
diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 3bb1cf1e7425..f75efa22df5e 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
12 | #include <linux/irqnr.h> | ||
12 | #include <asm/cputime.h> | 13 | #include <asm/cputime.h> |
13 | 14 | ||
14 | #ifndef arch_irq_stat_cpu | 15 | #ifndef arch_irq_stat_cpu |
@@ -45,10 +46,6 @@ static int show_stat(struct seq_file *p, void *v) | |||
45 | steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); | 46 | steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); |
46 | guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); | 47 | guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); |
47 | for_each_irq_nr(j) { | 48 | for_each_irq_nr(j) { |
48 | #ifdef CONFIG_SPARSE_IRQ | ||
49 | if (!irq_to_desc(j)) | ||
50 | continue; | ||
51 | #endif | ||
52 | sum += kstat_irqs_cpu(j, i); | 49 | sum += kstat_irqs_cpu(j, i); |
53 | } | 50 | } |
54 | sum += arch_irq_stat_cpu(i); | 51 | sum += arch_irq_stat_cpu(i); |
@@ -95,12 +92,6 @@ static int show_stat(struct seq_file *p, void *v) | |||
95 | /* sum again ? it could be updated? */ | 92 | /* sum again ? it could be updated? */ |
96 | for_each_irq_nr(j) { | 93 | for_each_irq_nr(j) { |
97 | per_irq_sum = 0; | 94 | per_irq_sum = 0; |
98 | #ifdef CONFIG_SPARSE_IRQ | ||
99 | if (!irq_to_desc(j)) { | ||
100 | seq_printf(p, " %u", per_irq_sum); | ||
101 | continue; | ||
102 | } | ||
103 | #endif | ||
104 | for_each_possible_cpu(i) | 95 | for_each_possible_cpu(i) |
105 | per_irq_sum += kstat_irqs_cpu(j, i); | 96 | per_irq_sum += kstat_irqs_cpu(j, i); |
106 | 97 | ||
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6c4c2c69449f..145c2d3e5e01 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1753,6 +1753,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1753 | struct inode *inode) | 1753 | struct inode *inode) |
1754 | { | 1754 | { |
1755 | struct super_block *sb; | 1755 | struct super_block *sb; |
1756 | struct reiserfs_iget_args args; | ||
1756 | INITIALIZE_PATH(path_to_key); | 1757 | INITIALIZE_PATH(path_to_key); |
1757 | struct cpu_key key; | 1758 | struct cpu_key key; |
1758 | struct item_head ih; | 1759 | struct item_head ih; |
@@ -1780,6 +1781,14 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1780 | err = -ENOMEM; | 1781 | err = -ENOMEM; |
1781 | goto out_bad_inode; | 1782 | goto out_bad_inode; |
1782 | } | 1783 | } |
1784 | args.objectid = inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid); | ||
1785 | memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE); | ||
1786 | args.dirid = le32_to_cpu(ih.ih_key.k_dir_id); | ||
1787 | if (insert_inode_locked4(inode, args.objectid, | ||
1788 | reiserfs_find_actor, &args) < 0) { | ||
1789 | err = -EINVAL; | ||
1790 | goto out_bad_inode; | ||
1791 | } | ||
1783 | if (old_format_only(sb)) | 1792 | if (old_format_only(sb)) |
1784 | /* not a perfect generation count, as object ids can be reused, but | 1793 | /* not a perfect generation count, as object ids can be reused, but |
1785 | ** this is as good as reiserfs can do right now. | 1794 | ** this is as good as reiserfs can do right now. |
@@ -1859,13 +1868,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1859 | } else { | 1868 | } else { |
1860 | inode2sd(&sd, inode, inode->i_size); | 1869 | inode2sd(&sd, inode, inode->i_size); |
1861 | } | 1870 | } |
1862 | // these do not go to on-disk stat data | ||
1863 | inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid); | ||
1864 | |||
1865 | // store in in-core inode the key of stat data and version all | 1871 | // store in in-core inode the key of stat data and version all |
1866 | // object items will have (directory items will have old offset | 1872 | // object items will have (directory items will have old offset |
1867 | // format, other new objects will consist of new items) | 1873 | // format, other new objects will consist of new items) |
1868 | memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE); | ||
1869 | if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode)) | 1874 | if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode)) |
1870 | set_inode_item_key_version(inode, KEY_FORMAT_3_5); | 1875 | set_inode_item_key_version(inode, KEY_FORMAT_3_5); |
1871 | else | 1876 | else |
@@ -1929,7 +1934,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1929 | reiserfs_mark_inode_private(inode); | 1934 | reiserfs_mark_inode_private(inode); |
1930 | } | 1935 | } |
1931 | 1936 | ||
1932 | insert_inode_hash(inode); | ||
1933 | reiserfs_update_sd(th, inode); | 1937 | reiserfs_update_sd(th, inode); |
1934 | reiserfs_check_path(&path_to_key); | 1938 | reiserfs_check_path(&path_to_key); |
1935 | 1939 | ||
@@ -1956,6 +1960,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1956 | out_inserted_sd: | 1960 | out_inserted_sd: |
1957 | inode->i_nlink = 0; | 1961 | inode->i_nlink = 0; |
1958 | th->t_trans_id = 0; /* so the caller can't use this handle later */ | 1962 | th->t_trans_id = 0; /* so the caller can't use this handle later */ |
1963 | unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ | ||
1959 | 1964 | ||
1960 | /* If we were inheriting an ACL, we need to release the lock so that | 1965 | /* If we were inheriting an ACL, we need to release the lock so that |
1961 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking | 1966 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 4f322e5ed840..738967f6c8ee 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -646,6 +646,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
646 | err = journal_end(&th, dir->i_sb, jbegin_count); | 646 | err = journal_end(&th, dir->i_sb, jbegin_count); |
647 | if (err) | 647 | if (err) |
648 | retval = err; | 648 | retval = err; |
649 | unlock_new_inode(inode); | ||
649 | iput(inode); | 650 | iput(inode); |
650 | goto out_failed; | 651 | goto out_failed; |
651 | } | 652 | } |
@@ -653,6 +654,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
653 | reiserfs_update_inode_transaction(dir); | 654 | reiserfs_update_inode_transaction(dir); |
654 | 655 | ||
655 | d_instantiate(dentry, inode); | 656 | d_instantiate(dentry, inode); |
657 | unlock_new_inode(inode); | ||
656 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 658 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
657 | 659 | ||
658 | out_failed: | 660 | out_failed: |
@@ -727,11 +729,13 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
727 | err = journal_end(&th, dir->i_sb, jbegin_count); | 729 | err = journal_end(&th, dir->i_sb, jbegin_count); |
728 | if (err) | 730 | if (err) |
729 | retval = err; | 731 | retval = err; |
732 | unlock_new_inode(inode); | ||
730 | iput(inode); | 733 | iput(inode); |
731 | goto out_failed; | 734 | goto out_failed; |
732 | } | 735 | } |
733 | 736 | ||
734 | d_instantiate(dentry, inode); | 737 | d_instantiate(dentry, inode); |
738 | unlock_new_inode(inode); | ||
735 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 739 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
736 | 740 | ||
737 | out_failed: | 741 | out_failed: |
@@ -812,6 +816,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
812 | err = journal_end(&th, dir->i_sb, jbegin_count); | 816 | err = journal_end(&th, dir->i_sb, jbegin_count); |
813 | if (err) | 817 | if (err) |
814 | retval = err; | 818 | retval = err; |
819 | unlock_new_inode(inode); | ||
815 | iput(inode); | 820 | iput(inode); |
816 | goto out_failed; | 821 | goto out_failed; |
817 | } | 822 | } |
@@ -819,6 +824,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
819 | reiserfs_update_sd(&th, dir); | 824 | reiserfs_update_sd(&th, dir); |
820 | 825 | ||
821 | d_instantiate(dentry, inode); | 826 | d_instantiate(dentry, inode); |
827 | unlock_new_inode(inode); | ||
822 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 828 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
823 | out_failed: | 829 | out_failed: |
824 | if (locked) | 830 | if (locked) |
@@ -1096,11 +1102,13 @@ static int reiserfs_symlink(struct inode *parent_dir, | |||
1096 | err = journal_end(&th, parent_dir->i_sb, jbegin_count); | 1102 | err = journal_end(&th, parent_dir->i_sb, jbegin_count); |
1097 | if (err) | 1103 | if (err) |
1098 | retval = err; | 1104 | retval = err; |
1105 | unlock_new_inode(inode); | ||
1099 | iput(inode); | 1106 | iput(inode); |
1100 | goto out_failed; | 1107 | goto out_failed; |
1101 | } | 1108 | } |
1102 | 1109 | ||
1103 | d_instantiate(dentry, inode); | 1110 | d_instantiate(dentry, inode); |
1111 | unlock_new_inode(inode); | ||
1104 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); | 1112 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); |
1105 | out_failed: | 1113 | out_failed: |
1106 | reiserfs_write_unlock(parent_dir->i_sb); | 1114 | reiserfs_write_unlock(parent_dir->i_sb); |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 16c211558c22..99d8b8cfc9b7 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -389,8 +389,14 @@ char *mangle_path(char *s, char *p, char *esc) | |||
389 | } | 389 | } |
390 | EXPORT_SYMBOL(mangle_path); | 390 | EXPORT_SYMBOL(mangle_path); |
391 | 391 | ||
392 | /* | 392 | /** |
393 | * return the absolute path of 'dentry' residing in mount 'mnt'. | 393 | * seq_path - seq_file interface to print a pathname |
394 | * @m: the seq_file handle | ||
395 | * @path: the struct path to print | ||
396 | * @esc: set of characters to escape in the output | ||
397 | * | ||
398 | * return the absolute path of 'path', as represented by the | ||
399 | * dentry / mnt pair in the path parameter. | ||
394 | */ | 400 | */ |
395 | int seq_path(struct seq_file *m, struct path *path, char *esc) | 401 | int seq_path(struct seq_file *m, struct path *path, char *esc) |
396 | { | 402 | { |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index df0d435baa48..3d81bf58dae2 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
29 | #include <linux/vfs.h> | 29 | #include <linux/vfs.h> |
30 | #include <linux/namei.h> | ||
30 | #include <asm/byteorder.h> | 31 | #include <asm/byteorder.h> |
31 | #include "sysv.h" | 32 | #include "sysv.h" |
32 | 33 | ||
@@ -163,8 +164,11 @@ void sysv_set_inode(struct inode *inode, dev_t rdev) | |||
163 | if (inode->i_blocks) { | 164 | if (inode->i_blocks) { |
164 | inode->i_op = &sysv_symlink_inode_operations; | 165 | inode->i_op = &sysv_symlink_inode_operations; |
165 | inode->i_mapping->a_ops = &sysv_aops; | 166 | inode->i_mapping->a_ops = &sysv_aops; |
166 | } else | 167 | } else { |
167 | inode->i_op = &sysv_fast_symlink_inode_operations; | 168 | inode->i_op = &sysv_fast_symlink_inode_operations; |
169 | nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size, | ||
170 | sizeof(SYSV_I(inode)->i_data) - 1); | ||
171 | } | ||
168 | } else | 172 | } else |
169 | init_special_inode(inode, inode->i_mode, rdev); | 173 | init_special_inode(inode, inode->i_mode, rdev); |
170 | } | 174 | } |
diff --git a/include/linux/8250_pci.h b/include/linux/8250_pci.h index 3209dd46ea7d..b24ff086a662 100644 --- a/include/linux/8250_pci.h +++ b/include/linux/8250_pci.h | |||
@@ -31,7 +31,7 @@ struct pciserial_board { | |||
31 | struct serial_private; | 31 | struct serial_private; |
32 | 32 | ||
33 | struct serial_private * | 33 | struct serial_private * |
34 | pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board); | 34 | pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board); |
35 | void pciserial_remove_ports(struct serial_private *priv); | 35 | void pciserial_remove_ports(struct serial_private *priv); |
36 | void pciserial_suspend_ports(struct serial_private *priv); | 36 | void pciserial_suspend_ports(struct serial_private *priv); |
37 | void pciserial_resume_ports(struct serial_private *priv); | 37 | void pciserial_resume_ports(struct serial_private *priv); |
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 5c8351b859f0..af40f8eb86f0 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h | |||
@@ -61,3 +61,8 @@ | |||
61 | #define noinline __attribute__((noinline)) | 61 | #define noinline __attribute__((noinline)) |
62 | #define __attribute_const__ __attribute__((__const__)) | 62 | #define __attribute_const__ __attribute__((__const__)) |
63 | #define __maybe_unused __attribute__((unused)) | 63 | #define __maybe_unused __attribute__((unused)) |
64 | |||
65 | #define __gcc_header(x) #x | ||
66 | #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) | ||
67 | #define gcc_header(x) _gcc_header(x) | ||
68 | #include gcc_header(__GNUC__) | ||
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h index e5eb795f78a1..2befe6513ce4 100644 --- a/include/linux/compiler-gcc3.h +++ b/include/linux/compiler-gcc3.h | |||
@@ -2,9 +2,6 @@ | |||
2 | #error "Please don't include <linux/compiler-gcc3.h> directly, include <linux/compiler.h> instead." | 2 | #error "Please don't include <linux/compiler-gcc3.h> directly, include <linux/compiler.h> instead." |
3 | #endif | 3 | #endif |
4 | 4 | ||
5 | /* These definitions are for GCC v3.x. */ | ||
6 | #include <linux/compiler-gcc.h> | ||
7 | |||
8 | #if __GNUC_MINOR__ >= 3 | 5 | #if __GNUC_MINOR__ >= 3 |
9 | # define __used __attribute__((__used__)) | 6 | # define __used __attribute__((__used__)) |
10 | #else | 7 | #else |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 974f5b7bb205..09992718f9e8 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
@@ -2,8 +2,10 @@ | |||
2 | #error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead." | 2 | #error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead." |
3 | #endif | 3 | #endif |
4 | 4 | ||
5 | /* These definitions are for GCC v4.x. */ | 5 | /* GCC 4.1.[01] miscompiles __weak */ |
6 | #include <linux/compiler-gcc.h> | 6 | #if __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 1 |
7 | # error Your version of gcc miscompiles the __weak directive | ||
8 | #endif | ||
7 | 9 | ||
8 | #define __used __attribute__((__used__)) | 10 | #define __used __attribute__((__used__)) |
9 | #define __must_check __attribute__((warn_unused_result)) | 11 | #define __must_check __attribute__((warn_unused_result)) |
@@ -16,7 +18,7 @@ | |||
16 | */ | 18 | */ |
17 | #define uninitialized_var(x) x = x | 19 | #define uninitialized_var(x) x = x |
18 | 20 | ||
19 | #if !(__GNUC__ == 4 && __GNUC_MINOR__ < 3) | 21 | #if __GNUC_MINOR__ >= 3 |
20 | /* Mark functions as cold. gcc will assume any path leading to a call | 22 | /* Mark functions as cold. gcc will assume any path leading to a call |
21 | to them will be unlikely. This means a lot of manual unlikely()s | 23 | to them will be unlikely. This means a lot of manual unlikely()s |
22 | are unnecessary now for any paths leading to the usual suspects | 24 | are unnecessary now for any paths leading to the usual suspects |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index ea7c6be354b7..d95da1020f1c 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -36,12 +36,8 @@ extern void __chk_io_ptr(const volatile void __iomem *); | |||
36 | 36 | ||
37 | #ifdef __KERNEL__ | 37 | #ifdef __KERNEL__ |
38 | 38 | ||
39 | #if __GNUC__ >= 4 | 39 | #ifdef __GNUC__ |
40 | # include <linux/compiler-gcc4.h> | 40 | #include <linux/compiler-gcc.h> |
41 | #elif __GNUC__ == 3 && __GNUC_MINOR__ >= 2 | ||
42 | # include <linux/compiler-gcc3.h> | ||
43 | #else | ||
44 | # error Sorry, your compiler is too old/not recognized. | ||
45 | #endif | 41 | #endif |
46 | 42 | ||
47 | #define notrace __attribute__((no_instrument_function)) | 43 | #define notrace __attribute__((no_instrument_function)) |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index a37359d0bad1..c66d22487bf8 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -75,14 +75,22 @@ full_name_hash(const unsigned char *name, unsigned int len) | |||
75 | return end_name_hash(hash); | 75 | return end_name_hash(hash); |
76 | } | 76 | } |
77 | 77 | ||
78 | struct dcookie_struct; | 78 | /* |
79 | 79 | * Try to keep struct dentry aligned on 64 byte cachelines (this will | |
80 | #define DNAME_INLINE_LEN_MIN 36 | 80 | * give reasonable cacheline footprint with larger lines without the |
81 | * large memory footprint increase). | ||
82 | */ | ||
83 | #ifdef CONFIG_64BIT | ||
84 | #define DNAME_INLINE_LEN_MIN 32 /* 192 bytes */ | ||
85 | #else | ||
86 | #define DNAME_INLINE_LEN_MIN 40 /* 128 bytes */ | ||
87 | #endif | ||
81 | 88 | ||
82 | struct dentry { | 89 | struct dentry { |
83 | atomic_t d_count; | 90 | atomic_t d_count; |
84 | unsigned int d_flags; /* protected by d_lock */ | 91 | unsigned int d_flags; /* protected by d_lock */ |
85 | spinlock_t d_lock; /* per dentry lock */ | 92 | spinlock_t d_lock; /* per dentry lock */ |
93 | int d_mounted; | ||
86 | struct inode *d_inode; /* Where the name belongs to - NULL is | 94 | struct inode *d_inode; /* Where the name belongs to - NULL is |
87 | * negative */ | 95 | * negative */ |
88 | /* | 96 | /* |
@@ -107,10 +115,7 @@ struct dentry { | |||
107 | struct dentry_operations *d_op; | 115 | struct dentry_operations *d_op; |
108 | struct super_block *d_sb; /* The root of the dentry tree */ | 116 | struct super_block *d_sb; /* The root of the dentry tree */ |
109 | void *d_fsdata; /* fs-specific data */ | 117 | void *d_fsdata; /* fs-specific data */ |
110 | #ifdef CONFIG_PROFILING | 118 | |
111 | struct dcookie_struct *d_cookie; /* cookie, if any */ | ||
112 | #endif | ||
113 | int d_mounted; | ||
114 | unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ | 119 | unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ |
115 | }; | 120 | }; |
116 | 121 | ||
@@ -177,6 +182,8 @@ d_iput: no no no yes | |||
177 | 182 | ||
178 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ | 183 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ |
179 | 184 | ||
185 | #define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */ | ||
186 | |||
180 | extern spinlock_t dcache_lock; | 187 | extern spinlock_t dcache_lock; |
181 | extern seqlock_t rename_lock; | 188 | extern seqlock_t rename_lock; |
182 | 189 | ||
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 4aab6f12cfab..09d6c5bbdddd 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h | |||
@@ -57,8 +57,6 @@ struct files_struct { | |||
57 | 57 | ||
58 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) | 58 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) |
59 | 59 | ||
60 | extern struct kmem_cache *filp_cachep; | ||
61 | |||
62 | struct file_operations; | 60 | struct file_operations; |
63 | struct vfsmount; | 61 | struct vfsmount; |
64 | struct dentry; | 62 | struct dentry; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 001ded4845b4..e2170ee21e18 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | /* Fixed constants first: */ | 22 | /* Fixed constants first: */ |
23 | #undef NR_OPEN | 23 | #undef NR_OPEN |
24 | extern int sysctl_nr_open; | ||
25 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ | 24 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ |
26 | 25 | ||
27 | #define BLOCK_SIZE_BITS 10 | 26 | #define BLOCK_SIZE_BITS 10 |
@@ -38,21 +37,13 @@ struct files_stat_struct { | |||
38 | int nr_free_files; /* read only */ | 37 | int nr_free_files; /* read only */ |
39 | int max_files; /* tunable */ | 38 | int max_files; /* tunable */ |
40 | }; | 39 | }; |
41 | extern struct files_stat_struct files_stat; | ||
42 | extern int get_max_files(void); | ||
43 | 40 | ||
44 | struct inodes_stat_t { | 41 | struct inodes_stat_t { |
45 | int nr_inodes; | 42 | int nr_inodes; |
46 | int nr_unused; | 43 | int nr_unused; |
47 | int dummy[5]; /* padding for sysctl ABI compatibility */ | 44 | int dummy[5]; /* padding for sysctl ABI compatibility */ |
48 | }; | 45 | }; |
49 | extern struct inodes_stat_t inodes_stat; | ||
50 | 46 | ||
51 | extern int leases_enable, lease_break_time; | ||
52 | |||
53 | #ifdef CONFIG_DNOTIFY | ||
54 | extern int dir_notify_enable; | ||
55 | #endif | ||
56 | 47 | ||
57 | #define NR_FILE 8192 /* this can well be larger on a larger system */ | 48 | #define NR_FILE 8192 /* this can well be larger on a larger system */ |
58 | 49 | ||
@@ -330,6 +321,15 @@ extern void __init inode_init(void); | |||
330 | extern void __init inode_init_early(void); | 321 | extern void __init inode_init_early(void); |
331 | extern void __init files_init(unsigned long); | 322 | extern void __init files_init(unsigned long); |
332 | 323 | ||
324 | extern struct files_stat_struct files_stat; | ||
325 | extern int get_max_files(void); | ||
326 | extern int sysctl_nr_open; | ||
327 | extern struct inodes_stat_t inodes_stat; | ||
328 | extern int leases_enable, lease_break_time; | ||
329 | #ifdef CONFIG_DNOTIFY | ||
330 | extern int dir_notify_enable; | ||
331 | #endif | ||
332 | |||
333 | struct buffer_head; | 333 | struct buffer_head; |
334 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 334 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
335 | struct buffer_head *bh_result, int create); | 335 | struct buffer_head *bh_result, int create); |
@@ -1212,7 +1212,6 @@ extern void unlock_super(struct super_block *); | |||
1212 | /* | 1212 | /* |
1213 | * VFS helper functions.. | 1213 | * VFS helper functions.. |
1214 | */ | 1214 | */ |
1215 | extern int vfs_permission(struct nameidata *, int); | ||
1216 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 1215 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); |
1217 | extern int vfs_mkdir(struct inode *, struct dentry *, int); | 1216 | extern int vfs_mkdir(struct inode *, struct dentry *, int); |
1218 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); | 1217 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); |
@@ -1310,7 +1309,6 @@ struct file_operations { | |||
1310 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 1309 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
1311 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 1310 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
1312 | int (*check_flags)(int); | 1311 | int (*check_flags)(int); |
1313 | int (*dir_notify)(struct file *filp, unsigned long arg); | ||
1314 | int (*flock) (struct file *, int, struct file_lock *); | 1312 | int (*flock) (struct file *, int, struct file_lock *); |
1315 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); | 1313 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); |
1316 | ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); | 1314 | ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); |
@@ -1869,7 +1867,7 @@ extern void free_write_pipe(struct file *); | |||
1869 | 1867 | ||
1870 | extern struct file *do_filp_open(int dfd, const char *pathname, | 1868 | extern struct file *do_filp_open(int dfd, const char *pathname, |
1871 | int open_flag, int mode); | 1869 | int open_flag, int mode); |
1872 | extern int may_open(struct nameidata *, int, int); | 1870 | extern int may_open(struct path *, int, int); |
1873 | 1871 | ||
1874 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); | 1872 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); |
1875 | extern struct file * open_exec(const char *); | 1873 | extern struct file * open_exec(const char *); |
@@ -1904,6 +1902,8 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); | |||
1904 | 1902 | ||
1905 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); | 1903 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); |
1906 | extern struct inode * iget_locked(struct super_block *, unsigned long); | 1904 | extern struct inode * iget_locked(struct super_block *, unsigned long); |
1905 | extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *); | ||
1906 | extern int insert_inode_locked(struct inode *); | ||
1907 | extern void unlock_new_inode(struct inode *); | 1907 | extern void unlock_new_inode(struct inode *); |
1908 | 1908 | ||
1909 | extern void __iget(struct inode * inode); | 1909 | extern void __iget(struct inode * inode); |
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 9e5a06e78d02..a97c053d3a9a 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h | |||
@@ -10,12 +10,6 @@ struct fs_struct { | |||
10 | struct path root, pwd; | 10 | struct path root, pwd; |
11 | }; | 11 | }; |
12 | 12 | ||
13 | #define INIT_FS { \ | ||
14 | .count = ATOMIC_INIT(1), \ | ||
15 | .lock = RW_LOCK_UNLOCKED, \ | ||
16 | .umask = 0022, \ | ||
17 | } | ||
18 | |||
19 | extern struct kmem_cache *fs_cachep; | 13 | extern struct kmem_cache *fs_cachep; |
20 | 14 | ||
21 | extern void exit_fs(struct task_struct *); | 15 | extern void exit_fs(struct task_struct *); |
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index 4cc913939817..fadff28505bb 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h | |||
@@ -21,7 +21,6 @@ struct real_driver { | |||
21 | void (*enable_tx_interrupts) (void *); | 21 | void (*enable_tx_interrupts) (void *); |
22 | void (*disable_rx_interrupts) (void *); | 22 | void (*disable_rx_interrupts) (void *); |
23 | void (*enable_rx_interrupts) (void *); | 23 | void (*enable_rx_interrupts) (void *); |
24 | int (*get_CD) (void *); | ||
25 | void (*shutdown_port) (void*); | 24 | void (*shutdown_port) (void*); |
26 | int (*set_real_termios) (void*); | 25 | int (*set_real_termios) (void*); |
27 | int (*chars_in_buffer) (void*); | 26 | int (*chars_in_buffer) (void*); |
diff --git a/include/linux/ide.h b/include/linux/ide.h index e99c56de7f56..db5ef8ae1ab9 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -32,13 +32,6 @@ | |||
32 | # define SUPPORT_VLB_SYNC 1 | 32 | # define SUPPORT_VLB_SYNC 1 |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | /* | ||
36 | * Used to indicate "no IRQ", should be a value that cannot be an IRQ | ||
37 | * number. | ||
38 | */ | ||
39 | |||
40 | #define IDE_NO_IRQ (-1) | ||
41 | |||
42 | typedef unsigned char byte; /* used everywhere */ | 35 | typedef unsigned char byte; /* used everywhere */ |
43 | 36 | ||
44 | /* | 37 | /* |
@@ -403,6 +396,7 @@ enum { | |||
403 | * This is used for several packet commands (not for READ/WRITE commands). | 396 | * This is used for several packet commands (not for READ/WRITE commands). |
404 | */ | 397 | */ |
405 | #define IDE_PC_BUFFER_SIZE 256 | 398 | #define IDE_PC_BUFFER_SIZE 256 |
399 | #define ATAPI_WAIT_PC (60 * HZ) | ||
406 | 400 | ||
407 | struct ide_atapi_pc { | 401 | struct ide_atapi_pc { |
408 | /* actual packet bytes */ | 402 | /* actual packet bytes */ |
@@ -480,53 +474,53 @@ enum { | |||
480 | 474 | ||
481 | /* ide-cd */ | 475 | /* ide-cd */ |
482 | /* Drive cannot eject the disc. */ | 476 | /* Drive cannot eject the disc. */ |
483 | IDE_AFLAG_NO_EJECT = (1 << 3), | 477 | IDE_AFLAG_NO_EJECT = (1 << 1), |
484 | /* Drive is a pre ATAPI 1.2 drive. */ | 478 | /* Drive is a pre ATAPI 1.2 drive. */ |
485 | IDE_AFLAG_PRE_ATAPI12 = (1 << 4), | 479 | IDE_AFLAG_PRE_ATAPI12 = (1 << 2), |
486 | /* TOC addresses are in BCD. */ | 480 | /* TOC addresses are in BCD. */ |
487 | IDE_AFLAG_TOCADDR_AS_BCD = (1 << 5), | 481 | IDE_AFLAG_TOCADDR_AS_BCD = (1 << 3), |
488 | /* TOC track numbers are in BCD. */ | 482 | /* TOC track numbers are in BCD. */ |
489 | IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 6), | 483 | IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 4), |
490 | /* | 484 | /* |
491 | * Drive does not provide data in multiples of SECTOR_SIZE | 485 | * Drive does not provide data in multiples of SECTOR_SIZE |
492 | * when more than one interrupt is needed. | 486 | * when more than one interrupt is needed. |
493 | */ | 487 | */ |
494 | IDE_AFLAG_LIMIT_NFRAMES = (1 << 7), | 488 | IDE_AFLAG_LIMIT_NFRAMES = (1 << 5), |
495 | /* Saved TOC information is current. */ | 489 | /* Saved TOC information is current. */ |
496 | IDE_AFLAG_TOC_VALID = (1 << 9), | 490 | IDE_AFLAG_TOC_VALID = (1 << 6), |
497 | /* We think that the drive door is locked. */ | 491 | /* We think that the drive door is locked. */ |
498 | IDE_AFLAG_DOOR_LOCKED = (1 << 10), | 492 | IDE_AFLAG_DOOR_LOCKED = (1 << 7), |
499 | /* SET_CD_SPEED command is unsupported. */ | 493 | /* SET_CD_SPEED command is unsupported. */ |
500 | IDE_AFLAG_NO_SPEED_SELECT = (1 << 11), | 494 | IDE_AFLAG_NO_SPEED_SELECT = (1 << 8), |
501 | IDE_AFLAG_VERTOS_300_SSD = (1 << 12), | 495 | IDE_AFLAG_VERTOS_300_SSD = (1 << 9), |
502 | IDE_AFLAG_VERTOS_600_ESD = (1 << 13), | 496 | IDE_AFLAG_VERTOS_600_ESD = (1 << 10), |
503 | IDE_AFLAG_SANYO_3CD = (1 << 14), | 497 | IDE_AFLAG_SANYO_3CD = (1 << 11), |
504 | IDE_AFLAG_FULL_CAPS_PAGE = (1 << 15), | 498 | IDE_AFLAG_FULL_CAPS_PAGE = (1 << 12), |
505 | IDE_AFLAG_PLAY_AUDIO_OK = (1 << 16), | 499 | IDE_AFLAG_PLAY_AUDIO_OK = (1 << 13), |
506 | IDE_AFLAG_LE_SPEED_FIELDS = (1 << 17), | 500 | IDE_AFLAG_LE_SPEED_FIELDS = (1 << 14), |
507 | 501 | ||
508 | /* ide-floppy */ | 502 | /* ide-floppy */ |
509 | /* Avoid commands not supported in Clik drive */ | 503 | /* Avoid commands not supported in Clik drive */ |
510 | IDE_AFLAG_CLIK_DRIVE = (1 << 19), | 504 | IDE_AFLAG_CLIK_DRIVE = (1 << 15), |
511 | /* Requires BH algorithm for packets */ | 505 | /* Requires BH algorithm for packets */ |
512 | IDE_AFLAG_ZIP_DRIVE = (1 << 20), | 506 | IDE_AFLAG_ZIP_DRIVE = (1 << 16), |
513 | /* Supports format progress report */ | 507 | /* Supports format progress report */ |
514 | IDE_AFLAG_SRFP = (1 << 22), | 508 | IDE_AFLAG_SRFP = (1 << 17), |
515 | 509 | ||
516 | /* ide-tape */ | 510 | /* ide-tape */ |
517 | IDE_AFLAG_IGNORE_DSC = (1 << 23), | 511 | IDE_AFLAG_IGNORE_DSC = (1 << 18), |
518 | /* 0 When the tape position is unknown */ | 512 | /* 0 When the tape position is unknown */ |
519 | IDE_AFLAG_ADDRESS_VALID = (1 << 24), | 513 | IDE_AFLAG_ADDRESS_VALID = (1 << 19), |
520 | /* Device already opened */ | 514 | /* Device already opened */ |
521 | IDE_AFLAG_BUSY = (1 << 25), | 515 | IDE_AFLAG_BUSY = (1 << 20), |
522 | /* Attempt to auto-detect the current user block size */ | 516 | /* Attempt to auto-detect the current user block size */ |
523 | IDE_AFLAG_DETECT_BS = (1 << 26), | 517 | IDE_AFLAG_DETECT_BS = (1 << 21), |
524 | /* Currently on a filemark */ | 518 | /* Currently on a filemark */ |
525 | IDE_AFLAG_FILEMARK = (1 << 27), | 519 | IDE_AFLAG_FILEMARK = (1 << 22), |
526 | /* 0 = no tape is loaded, so we don't rewind after ejecting */ | 520 | /* 0 = no tape is loaded, so we don't rewind after ejecting */ |
527 | IDE_AFLAG_MEDIUM_PRESENT = (1 << 28), | 521 | IDE_AFLAG_MEDIUM_PRESENT = (1 << 23), |
528 | 522 | ||
529 | IDE_AFLAG_NO_AUTOCLOSE = (1 << 29), | 523 | IDE_AFLAG_NO_AUTOCLOSE = (1 << 24), |
530 | }; | 524 | }; |
531 | 525 | ||
532 | /* device flags */ | 526 | /* device flags */ |
@@ -565,28 +559,26 @@ enum { | |||
565 | IDE_DFLAG_NODMA = (1 << 16), | 559 | IDE_DFLAG_NODMA = (1 << 16), |
566 | /* powermanagment told us not to do anything, so sleep nicely */ | 560 | /* powermanagment told us not to do anything, so sleep nicely */ |
567 | IDE_DFLAG_BLOCKED = (1 << 17), | 561 | IDE_DFLAG_BLOCKED = (1 << 17), |
568 | /* ide-scsi emulation */ | ||
569 | IDE_DFLAG_SCSI = (1 << 18), | ||
570 | /* sleeping & sleep field valid */ | 562 | /* sleeping & sleep field valid */ |
571 | IDE_DFLAG_SLEEPING = (1 << 19), | 563 | IDE_DFLAG_SLEEPING = (1 << 18), |
572 | IDE_DFLAG_POST_RESET = (1 << 20), | 564 | IDE_DFLAG_POST_RESET = (1 << 19), |
573 | IDE_DFLAG_UDMA33_WARNED = (1 << 21), | 565 | IDE_DFLAG_UDMA33_WARNED = (1 << 20), |
574 | IDE_DFLAG_LBA48 = (1 << 22), | 566 | IDE_DFLAG_LBA48 = (1 << 21), |
575 | /* status of write cache */ | 567 | /* status of write cache */ |
576 | IDE_DFLAG_WCACHE = (1 << 23), | 568 | IDE_DFLAG_WCACHE = (1 << 22), |
577 | /* used for ignoring ATA_DF */ | 569 | /* used for ignoring ATA_DF */ |
578 | IDE_DFLAG_NOWERR = (1 << 24), | 570 | IDE_DFLAG_NOWERR = (1 << 23), |
579 | /* retrying in PIO */ | 571 | /* retrying in PIO */ |
580 | IDE_DFLAG_DMA_PIO_RETRY = (1 << 25), | 572 | IDE_DFLAG_DMA_PIO_RETRY = (1 << 24), |
581 | IDE_DFLAG_LBA = (1 << 26), | 573 | IDE_DFLAG_LBA = (1 << 25), |
582 | /* don't unload heads */ | 574 | /* don't unload heads */ |
583 | IDE_DFLAG_NO_UNLOAD = (1 << 27), | 575 | IDE_DFLAG_NO_UNLOAD = (1 << 26), |
584 | /* heads unloaded, please don't reset port */ | 576 | /* heads unloaded, please don't reset port */ |
585 | IDE_DFLAG_PARKED = (1 << 28), | 577 | IDE_DFLAG_PARKED = (1 << 27), |
586 | IDE_DFLAG_MEDIA_CHANGED = (1 << 29), | 578 | IDE_DFLAG_MEDIA_CHANGED = (1 << 28), |
587 | /* write protect */ | 579 | /* write protect */ |
588 | IDE_DFLAG_WP = (1 << 30), | 580 | IDE_DFLAG_WP = (1 << 29), |
589 | IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 31), | 581 | IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), |
590 | }; | 582 | }; |
591 | 583 | ||
592 | struct ide_drive_s { | 584 | struct ide_drive_s { |
@@ -610,8 +602,6 @@ struct ide_drive_s { | |||
610 | unsigned long dev_flags; | 602 | unsigned long dev_flags; |
611 | 603 | ||
612 | unsigned long sleep; /* sleep until this time */ | 604 | unsigned long sleep; /* sleep until this time */ |
613 | unsigned long service_start; /* time we started last request */ | ||
614 | unsigned long service_time; /* service time of last request */ | ||
615 | unsigned long timeout; /* max time to wait for irq */ | 605 | unsigned long timeout; /* max time to wait for irq */ |
616 | 606 | ||
617 | special_t special; /* special action flags */ | 607 | special_t special; /* special action flags */ |
@@ -879,8 +869,6 @@ typedef struct hwgroup_s { | |||
879 | 869 | ||
880 | /* BOOL: protects all fields below */ | 870 | /* BOOL: protects all fields below */ |
881 | volatile int busy; | 871 | volatile int busy; |
882 | /* BOOL: wake us up on timer expiry */ | ||
883 | unsigned int sleeping : 1; | ||
884 | /* BOOL: polling active & poll_timeout field valid */ | 872 | /* BOOL: polling active & poll_timeout field valid */ |
885 | unsigned int polling : 1; | 873 | unsigned int polling : 1; |
886 | 874 | ||
@@ -1258,14 +1246,11 @@ int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); | |||
1258 | void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *); | 1246 | void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *); |
1259 | void ide_retry_pc(ide_drive_t *, struct gendisk *); | 1247 | void ide_retry_pc(ide_drive_t *, struct gendisk *); |
1260 | 1248 | ||
1261 | static inline unsigned long ide_scsi_get_timeout(struct ide_atapi_pc *pc) | 1249 | int ide_cd_expiry(ide_drive_t *); |
1262 | { | ||
1263 | return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies); | ||
1264 | } | ||
1265 | 1250 | ||
1266 | int ide_scsi_expiry(ide_drive_t *); | 1251 | int ide_cd_get_xferlen(struct request *); |
1267 | 1252 | ||
1268 | ide_startstop_t ide_issue_pc(ide_drive_t *, unsigned int, ide_expiry_t *); | 1253 | ide_startstop_t ide_issue_pc(ide_drive_t *); |
1269 | 1254 | ||
1270 | ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *); | 1255 | ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *); |
1271 | 1256 | ||
@@ -1287,6 +1272,26 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); | |||
1287 | 1272 | ||
1288 | extern void ide_timer_expiry(unsigned long); | 1273 | extern void ide_timer_expiry(unsigned long); |
1289 | extern irqreturn_t ide_intr(int irq, void *dev_id); | 1274 | extern irqreturn_t ide_intr(int irq, void *dev_id); |
1275 | |||
1276 | static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup) | ||
1277 | { | ||
1278 | if (hwgroup->busy) | ||
1279 | return 1; | ||
1280 | |||
1281 | hwgroup->busy = 1; | ||
1282 | /* for atari only */ | ||
1283 | ide_get_lock(ide_intr, hwgroup); | ||
1284 | |||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1288 | static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup) | ||
1289 | { | ||
1290 | /* for atari only */ | ||
1291 | ide_release_lock(); | ||
1292 | hwgroup->busy = 0; | ||
1293 | } | ||
1294 | |||
1290 | extern void do_ide_request(struct request_queue *); | 1295 | extern void do_ide_request(struct request_queue *); |
1291 | 1296 | ||
1292 | void ide_init_disk(struct gendisk *, ide_drive_t *); | 1297 | void ide_init_disk(struct gendisk *, ide_drive_t *); |
@@ -1533,6 +1538,7 @@ void ide_unregister_region(struct gendisk *); | |||
1533 | void ide_undecoded_slave(ide_drive_t *); | 1538 | void ide_undecoded_slave(ide_drive_t *); |
1534 | 1539 | ||
1535 | void ide_port_apply_params(ide_hwif_t *); | 1540 | void ide_port_apply_params(ide_hwif_t *); |
1541 | int ide_sysfs_register_port(ide_hwif_t *); | ||
1536 | 1542 | ||
1537 | struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); | 1543 | struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); |
1538 | void ide_host_free(struct ide_host *); | 1544 | void ide_host_free(struct ide_host *); |
@@ -1627,6 +1633,9 @@ extern struct mutex ide_cfg_mtx; | |||
1627 | 1633 | ||
1628 | #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) | 1634 | #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) |
1629 | 1635 | ||
1636 | char *ide_media_string(ide_drive_t *); | ||
1637 | |||
1638 | extern struct device_attribute ide_dev_attrs[]; | ||
1630 | extern struct bus_type ide_bus_type; | 1639 | extern struct bus_type ide_bus_type; |
1631 | extern struct class *ide_port_class; | 1640 | extern struct class *ide_port_class; |
1632 | 1641 | ||
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 959f5522d10a..2f3c2d4ef73b 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <net/net_namespace.h> | 12 | #include <net/net_namespace.h> |
13 | 13 | ||
14 | extern struct files_struct init_files; | 14 | extern struct files_struct init_files; |
15 | extern struct fs_struct init_fs; | ||
15 | 16 | ||
16 | #define INIT_KIOCTX(name, which_mm) \ | 17 | #define INIT_KIOCTX(name, which_mm) \ |
17 | { \ | 18 | { \ |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index be3c484b5242..8cc8ef47f5b6 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -464,4 +464,10 @@ static inline void init_irq_proc(void) | |||
464 | 464 | ||
465 | int show_interrupts(struct seq_file *p, void *v); | 465 | int show_interrupts(struct seq_file *p, void *v); |
466 | 466 | ||
467 | struct irq_desc; | ||
468 | |||
469 | extern int early_irq_init(void); | ||
470 | extern int arch_early_irq_init(void); | ||
471 | extern int arch_init_chip_data(struct irq_desc *desc, int cpu); | ||
472 | |||
467 | #endif | 473 | #endif |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 98564dc64476..d64a6d49bdef 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -193,42 +193,23 @@ struct irq_desc { | |||
193 | const char *name; | 193 | const char *name; |
194 | } ____cacheline_internodealigned_in_smp; | 194 | } ____cacheline_internodealigned_in_smp; |
195 | 195 | ||
196 | extern void early_irq_init(void); | ||
197 | extern void arch_early_irq_init(void); | ||
198 | extern void arch_init_chip_data(struct irq_desc *desc, int cpu); | ||
199 | extern void arch_init_copy_chip_data(struct irq_desc *old_desc, | 196 | extern void arch_init_copy_chip_data(struct irq_desc *old_desc, |
200 | struct irq_desc *desc, int cpu); | 197 | struct irq_desc *desc, int cpu); |
201 | extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc); | 198 | extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc); |
202 | 199 | ||
203 | #ifndef CONFIG_SPARSE_IRQ | 200 | #ifndef CONFIG_SPARSE_IRQ |
204 | extern struct irq_desc irq_desc[NR_IRQS]; | 201 | extern struct irq_desc irq_desc[NR_IRQS]; |
205 | 202 | #else /* CONFIG_SPARSE_IRQ */ | |
206 | static inline struct irq_desc *irq_to_desc(unsigned int irq) | ||
207 | { | ||
208 | return (irq < NR_IRQS) ? irq_desc + irq : NULL; | ||
209 | } | ||
210 | static inline struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | ||
211 | { | ||
212 | return irq_to_desc(irq); | ||
213 | } | ||
214 | |||
215 | #else | ||
216 | |||
217 | extern struct irq_desc *irq_to_desc(unsigned int irq); | ||
218 | extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu); | ||
219 | extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu); | 203 | extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu); |
220 | 204 | ||
221 | # define for_each_irq_desc(irq, desc) \ | ||
222 | for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; irq++, desc = irq_to_desc(irq)) | ||
223 | # define for_each_irq_desc_reverse(irq, desc) \ | ||
224 | for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; irq--, desc = irq_to_desc(irq)) | ||
225 | |||
226 | #define kstat_irqs_this_cpu(DESC) \ | 205 | #define kstat_irqs_this_cpu(DESC) \ |
227 | ((DESC)->kstat_irqs[smp_processor_id()]) | 206 | ((DESC)->kstat_irqs[smp_processor_id()]) |
228 | #define kstat_incr_irqs_this_cpu(irqno, DESC) \ | 207 | #define kstat_incr_irqs_this_cpu(irqno, DESC) \ |
229 | ((DESC)->kstat_irqs[smp_processor_id()]++) | 208 | ((DESC)->kstat_irqs[smp_processor_id()]++) |
230 | 209 | ||
231 | #endif | 210 | #endif /* CONFIG_SPARSE_IRQ */ |
211 | |||
212 | extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu); | ||
232 | 213 | ||
233 | static inline struct irq_desc * | 214 | static inline struct irq_desc * |
234 | irq_remap_to_desc(unsigned int irq, struct irq_desc *desc) | 215 | irq_remap_to_desc(unsigned int irq, struct irq_desc *desc) |
diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index 95d2b74641f5..5504a5c97836 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h | |||
@@ -15,20 +15,23 @@ | |||
15 | 15 | ||
16 | # define for_each_irq_desc_reverse(irq, desc) \ | 16 | # define for_each_irq_desc_reverse(irq, desc) \ |
17 | for (irq = nr_irqs - 1; irq >= 0; irq--) | 17 | for (irq = nr_irqs - 1; irq >= 0; irq--) |
18 | #else | 18 | #else /* CONFIG_GENERIC_HARDIRQS */ |
19 | 19 | ||
20 | extern int nr_irqs; | 20 | extern int nr_irqs; |
21 | extern struct irq_desc *irq_to_desc(unsigned int irq); | ||
21 | 22 | ||
22 | #ifndef CONFIG_SPARSE_IRQ | 23 | # define for_each_irq_desc(irq, desc) \ |
24 | for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; \ | ||
25 | irq++, desc = irq_to_desc(irq)) \ | ||
26 | if (desc) | ||
23 | 27 | ||
24 | struct irq_desc; | 28 | |
25 | # define for_each_irq_desc(irq, desc) \ | 29 | # define for_each_irq_desc_reverse(irq, desc) \ |
26 | for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++) | 30 | for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; \ |
27 | # define for_each_irq_desc_reverse(irq, desc) \ | 31 | irq--, desc = irq_to_desc(irq)) \ |
28 | for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \ | 32 | if (desc) |
29 | irq >= 0; irq--, desc--) | 33 | |
30 | #endif | 34 | #endif /* CONFIG_GENERIC_HARDIRQS */ |
31 | #endif | ||
32 | 35 | ||
33 | #define for_each_irq_nr(irq) \ | 36 | #define for_each_irq_nr(irq) \ |
34 | for (irq = 0; irq < nr_irqs; irq++) | 37 | for (irq = 0; irq < nr_irqs; irq++) |
diff --git a/include/linux/istallion.h b/include/linux/istallion.h index 0d1840723249..7faca98c7d14 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h | |||
@@ -59,9 +59,7 @@ struct stliport { | |||
59 | unsigned int devnr; | 59 | unsigned int devnr; |
60 | int baud_base; | 60 | int baud_base; |
61 | int custom_divisor; | 61 | int custom_divisor; |
62 | int close_delay; | ||
63 | int closing_wait; | 62 | int closing_wait; |
64 | int openwaitcnt; | ||
65 | int rc; | 63 | int rc; |
66 | int argsize; | 64 | int argsize; |
67 | void *argp; | 65 | void *argp; |
diff --git a/include/linux/namei.h b/include/linux/namei.h index 99eb80306dc5..fc2e03579877 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -94,4 +94,9 @@ static inline char *nd_get_link(struct nameidata *nd) | |||
94 | return nd->saved_names[nd->depth]; | 94 | return nd->saved_names[nd->depth]; |
95 | } | 95 | } |
96 | 96 | ||
97 | static inline void nd_terminate_link(void *name, size_t len, size_t maxlen) | ||
98 | { | ||
99 | ((char *) name)[min(len, maxlen)] = '\0'; | ||
100 | } | ||
101 | |||
97 | #endif /* _LINUX_NAMEI_H */ | 102 | #endif /* _LINUX_NAMEI_H */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b6e694454280..218c73b1e6d4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -1766,6 +1766,7 @@ | |||
1766 | #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 | 1766 | #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 |
1767 | #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 | 1767 | #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 |
1768 | #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 | 1768 | #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 |
1769 | #define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 | ||
1769 | 1770 | ||
1770 | #define PCI_VENDOR_ID_RADISYS 0x1331 | 1771 | #define PCI_VENDOR_ID_RADISYS 0x1331 |
1771 | 1772 | ||
@@ -1795,6 +1796,7 @@ | |||
1795 | #define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202 | 1796 | #define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202 |
1796 | #define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401 | 1797 | #define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401 |
1797 | #define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801 | 1798 | #define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801 |
1799 | #define PCI_DEVICE_ID_SEALEVEL_7803 0x7803 | ||
1798 | #define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804 | 1800 | #define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804 |
1799 | 1801 | ||
1800 | #define PCI_VENDOR_ID_HYPERCOPE 0x1365 | 1802 | #define PCI_VENDOR_ID_HYPERCOPE 0x1365 |
diff --git a/include/linux/security.h b/include/linux/security.h index 3416cb85e77b..b92b5e453f64 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -335,17 +335,37 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
335 | * @dir contains the inode structure of the parent directory of the new link. | 335 | * @dir contains the inode structure of the parent directory of the new link. |
336 | * @new_dentry contains the dentry structure for the new link. | 336 | * @new_dentry contains the dentry structure for the new link. |
337 | * Return 0 if permission is granted. | 337 | * Return 0 if permission is granted. |
338 | * @path_link: | ||
339 | * Check permission before creating a new hard link to a file. | ||
340 | * @old_dentry contains the dentry structure for an existing link | ||
341 | * to the file. | ||
342 | * @new_dir contains the path structure of the parent directory of | ||
343 | * the new link. | ||
344 | * @new_dentry contains the dentry structure for the new link. | ||
345 | * Return 0 if permission is granted. | ||
338 | * @inode_unlink: | 346 | * @inode_unlink: |
339 | * Check the permission to remove a hard link to a file. | 347 | * Check the permission to remove a hard link to a file. |
340 | * @dir contains the inode structure of parent directory of the file. | 348 | * @dir contains the inode structure of parent directory of the file. |
341 | * @dentry contains the dentry structure for file to be unlinked. | 349 | * @dentry contains the dentry structure for file to be unlinked. |
342 | * Return 0 if permission is granted. | 350 | * Return 0 if permission is granted. |
351 | * @path_unlink: | ||
352 | * Check the permission to remove a hard link to a file. | ||
353 | * @dir contains the path structure of parent directory of the file. | ||
354 | * @dentry contains the dentry structure for file to be unlinked. | ||
355 | * Return 0 if permission is granted. | ||
343 | * @inode_symlink: | 356 | * @inode_symlink: |
344 | * Check the permission to create a symbolic link to a file. | 357 | * Check the permission to create a symbolic link to a file. |
345 | * @dir contains the inode structure of parent directory of the symbolic link. | 358 | * @dir contains the inode structure of parent directory of the symbolic link. |
346 | * @dentry contains the dentry structure of the symbolic link. | 359 | * @dentry contains the dentry structure of the symbolic link. |
347 | * @old_name contains the pathname of file. | 360 | * @old_name contains the pathname of file. |
348 | * Return 0 if permission is granted. | 361 | * Return 0 if permission is granted. |
362 | * @path_symlink: | ||
363 | * Check the permission to create a symbolic link to a file. | ||
364 | * @dir contains the path structure of parent directory of | ||
365 | * the symbolic link. | ||
366 | * @dentry contains the dentry structure of the symbolic link. | ||
367 | * @old_name contains the pathname of file. | ||
368 | * Return 0 if permission is granted. | ||
349 | * @inode_mkdir: | 369 | * @inode_mkdir: |
350 | * Check permissions to create a new directory in the existing directory | 370 | * Check permissions to create a new directory in the existing directory |
351 | * associated with inode strcture @dir. | 371 | * associated with inode strcture @dir. |
@@ -353,11 +373,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
353 | * @dentry contains the dentry structure of new directory. | 373 | * @dentry contains the dentry structure of new directory. |
354 | * @mode contains the mode of new directory. | 374 | * @mode contains the mode of new directory. |
355 | * Return 0 if permission is granted. | 375 | * Return 0 if permission is granted. |
376 | * @path_mkdir: | ||
377 | * Check permissions to create a new directory in the existing directory | ||
378 | * associated with path strcture @path. | ||
379 | * @dir containst the path structure of parent of the directory | ||
380 | * to be created. | ||
381 | * @dentry contains the dentry structure of new directory. | ||
382 | * @mode contains the mode of new directory. | ||
383 | * Return 0 if permission is granted. | ||
356 | * @inode_rmdir: | 384 | * @inode_rmdir: |
357 | * Check the permission to remove a directory. | 385 | * Check the permission to remove a directory. |
358 | * @dir contains the inode structure of parent of the directory to be removed. | 386 | * @dir contains the inode structure of parent of the directory to be removed. |
359 | * @dentry contains the dentry structure of directory to be removed. | 387 | * @dentry contains the dentry structure of directory to be removed. |
360 | * Return 0 if permission is granted. | 388 | * Return 0 if permission is granted. |
389 | * @path_rmdir: | ||
390 | * Check the permission to remove a directory. | ||
391 | * @dir contains the path structure of parent of the directory to be | ||
392 | * removed. | ||
393 | * @dentry contains the dentry structure of directory to be removed. | ||
394 | * Return 0 if permission is granted. | ||
361 | * @inode_mknod: | 395 | * @inode_mknod: |
362 | * Check permissions when creating a special file (or a socket or a fifo | 396 | * Check permissions when creating a special file (or a socket or a fifo |
363 | * file created via the mknod system call). Note that if mknod operation | 397 | * file created via the mknod system call). Note that if mknod operation |
@@ -368,6 +402,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
368 | * @mode contains the mode of the new file. | 402 | * @mode contains the mode of the new file. |
369 | * @dev contains the device number. | 403 | * @dev contains the device number. |
370 | * Return 0 if permission is granted. | 404 | * Return 0 if permission is granted. |
405 | * @path_mknod: | ||
406 | * Check permissions when creating a file. Note that this hook is called | ||
407 | * even if mknod operation is being done for a regular file. | ||
408 | * @dir contains the path structure of parent of the new file. | ||
409 | * @dentry contains the dentry structure of the new file. | ||
410 | * @mode contains the mode of the new file. | ||
411 | * @dev contains the undecoded device number. Use new_decode_dev() to get | ||
412 | * the decoded device number. | ||
413 | * Return 0 if permission is granted. | ||
371 | * @inode_rename: | 414 | * @inode_rename: |
372 | * Check for permission to rename a file or directory. | 415 | * Check for permission to rename a file or directory. |
373 | * @old_dir contains the inode structure for parent of the old link. | 416 | * @old_dir contains the inode structure for parent of the old link. |
@@ -375,6 +418,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
375 | * @new_dir contains the inode structure for parent of the new link. | 418 | * @new_dir contains the inode structure for parent of the new link. |
376 | * @new_dentry contains the dentry structure of the new link. | 419 | * @new_dentry contains the dentry structure of the new link. |
377 | * Return 0 if permission is granted. | 420 | * Return 0 if permission is granted. |
421 | * @path_rename: | ||
422 | * Check for permission to rename a file or directory. | ||
423 | * @old_dir contains the path structure for parent of the old link. | ||
424 | * @old_dentry contains the dentry structure of the old link. | ||
425 | * @new_dir contains the path structure for parent of the new link. | ||
426 | * @new_dentry contains the dentry structure of the new link. | ||
427 | * Return 0 if permission is granted. | ||
378 | * @inode_readlink: | 428 | * @inode_readlink: |
379 | * Check the permission to read the symbolic link. | 429 | * Check the permission to read the symbolic link. |
380 | * @dentry contains the dentry structure for the file link. | 430 | * @dentry contains the dentry structure for the file link. |
@@ -403,6 +453,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
403 | * @dentry contains the dentry structure for the file. | 453 | * @dentry contains the dentry structure for the file. |
404 | * @attr is the iattr structure containing the new file attributes. | 454 | * @attr is the iattr structure containing the new file attributes. |
405 | * Return 0 if permission is granted. | 455 | * Return 0 if permission is granted. |
456 | * @path_truncate: | ||
457 | * Check permission before truncating a file. | ||
458 | * @path contains the path structure for the file. | ||
459 | * @length is the new length of the file. | ||
460 | * @time_attrs is the flags passed to do_truncate(). | ||
461 | * Return 0 if permission is granted. | ||
406 | * @inode_getattr: | 462 | * @inode_getattr: |
407 | * Check permission before obtaining file attributes. | 463 | * Check permission before obtaining file attributes. |
408 | * @mnt is the vfsmount where the dentry was looked up | 464 | * @mnt is the vfsmount where the dentry was looked up |
@@ -1331,6 +1387,22 @@ struct security_operations { | |||
1331 | struct super_block *newsb); | 1387 | struct super_block *newsb); |
1332 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1388 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
1333 | 1389 | ||
1390 | #ifdef CONFIG_SECURITY_PATH | ||
1391 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | ||
1392 | int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); | ||
1393 | int (*path_rmdir) (struct path *dir, struct dentry *dentry); | ||
1394 | int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, | ||
1395 | unsigned int dev); | ||
1396 | int (*path_truncate) (struct path *path, loff_t length, | ||
1397 | unsigned int time_attrs); | ||
1398 | int (*path_symlink) (struct path *dir, struct dentry *dentry, | ||
1399 | const char *old_name); | ||
1400 | int (*path_link) (struct dentry *old_dentry, struct path *new_dir, | ||
1401 | struct dentry *new_dentry); | ||
1402 | int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, | ||
1403 | struct path *new_dir, struct dentry *new_dentry); | ||
1404 | #endif | ||
1405 | |||
1334 | int (*inode_alloc_security) (struct inode *inode); | 1406 | int (*inode_alloc_security) (struct inode *inode); |
1335 | void (*inode_free_security) (struct inode *inode); | 1407 | void (*inode_free_security) (struct inode *inode); |
1336 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | 1408 | int (*inode_init_security) (struct inode *inode, struct inode *dir, |
@@ -2705,6 +2777,71 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi | |||
2705 | 2777 | ||
2706 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 2778 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
2707 | 2779 | ||
2780 | #ifdef CONFIG_SECURITY_PATH | ||
2781 | int security_path_unlink(struct path *dir, struct dentry *dentry); | ||
2782 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); | ||
2783 | int security_path_rmdir(struct path *dir, struct dentry *dentry); | ||
2784 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
2785 | unsigned int dev); | ||
2786 | int security_path_truncate(struct path *path, loff_t length, | ||
2787 | unsigned int time_attrs); | ||
2788 | int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
2789 | const char *old_name); | ||
2790 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
2791 | struct dentry *new_dentry); | ||
2792 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
2793 | struct path *new_dir, struct dentry *new_dentry); | ||
2794 | #else /* CONFIG_SECURITY_PATH */ | ||
2795 | static inline int security_path_unlink(struct path *dir, struct dentry *dentry) | ||
2796 | { | ||
2797 | return 0; | ||
2798 | } | ||
2799 | |||
2800 | static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, | ||
2801 | int mode) | ||
2802 | { | ||
2803 | return 0; | ||
2804 | } | ||
2805 | |||
2806 | static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) | ||
2807 | { | ||
2808 | return 0; | ||
2809 | } | ||
2810 | |||
2811 | static inline int security_path_mknod(struct path *dir, struct dentry *dentry, | ||
2812 | int mode, unsigned int dev) | ||
2813 | { | ||
2814 | return 0; | ||
2815 | } | ||
2816 | |||
2817 | static inline int security_path_truncate(struct path *path, loff_t length, | ||
2818 | unsigned int time_attrs) | ||
2819 | { | ||
2820 | return 0; | ||
2821 | } | ||
2822 | |||
2823 | static inline int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
2824 | const char *old_name) | ||
2825 | { | ||
2826 | return 0; | ||
2827 | } | ||
2828 | |||
2829 | static inline int security_path_link(struct dentry *old_dentry, | ||
2830 | struct path *new_dir, | ||
2831 | struct dentry *new_dentry) | ||
2832 | { | ||
2833 | return 0; | ||
2834 | } | ||
2835 | |||
2836 | static inline int security_path_rename(struct path *old_dir, | ||
2837 | struct dentry *old_dentry, | ||
2838 | struct path *new_dir, | ||
2839 | struct dentry *new_dentry) | ||
2840 | { | ||
2841 | return 0; | ||
2842 | } | ||
2843 | #endif /* CONFIG_SECURITY_PATH */ | ||
2844 | |||
2708 | #ifdef CONFIG_KEYS | 2845 | #ifdef CONFIG_KEYS |
2709 | #ifdef CONFIG_SECURITY | 2846 | #ifdef CONFIG_SECURITY |
2710 | 2847 | ||
diff --git a/include/linux/serial.h b/include/linux/serial.h index 1ea8d9265bf6..9136cc5608c3 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h | |||
@@ -10,8 +10,9 @@ | |||
10 | #ifndef _LINUX_SERIAL_H | 10 | #ifndef _LINUX_SERIAL_H |
11 | #define _LINUX_SERIAL_H | 11 | #define _LINUX_SERIAL_H |
12 | 12 | ||
13 | #ifdef __KERNEL__ | ||
14 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | |||
15 | #ifdef __KERNEL__ | ||
15 | #include <asm/page.h> | 16 | #include <asm/page.h> |
16 | 17 | ||
17 | /* | 18 | /* |
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 3d37c94abbc8..d4d2a78ad43e 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h | |||
@@ -28,6 +28,9 @@ struct plat_serial8250_port { | |||
28 | unsigned char iotype; /* UPIO_* */ | 28 | unsigned char iotype; /* UPIO_* */ |
29 | unsigned char hub6; | 29 | unsigned char hub6; |
30 | upf_t flags; /* UPF_* flags */ | 30 | upf_t flags; /* UPF_* flags */ |
31 | unsigned int type; /* If UPF_FIXED_TYPE */ | ||
32 | unsigned int (*serial_in)(struct uart_port *, int); | ||
33 | void (*serial_out)(struct uart_port *, int, int); | ||
31 | }; | 34 | }; |
32 | 35 | ||
33 | /* | 36 | /* |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index feb3b939ec4b..b4199841f1fc 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -40,7 +40,8 @@ | |||
40 | #define PORT_NS16550A 14 | 40 | #define PORT_NS16550A 14 |
41 | #define PORT_XSCALE 15 | 41 | #define PORT_XSCALE 15 |
42 | #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ | 42 | #define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */ |
43 | #define PORT_MAX_8250 16 /* max port ID */ | 43 | #define PORT_OCTEON 17 /* Cavium OCTEON internal UART */ |
44 | #define PORT_MAX_8250 17 /* max port ID */ | ||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * ARM specific type numbers. These are not currently guaranteed | 47 | * ARM specific type numbers. These are not currently guaranteed |
@@ -248,6 +249,8 @@ struct uart_port { | |||
248 | spinlock_t lock; /* port lock */ | 249 | spinlock_t lock; /* port lock */ |
249 | unsigned long iobase; /* in/out[bwl] */ | 250 | unsigned long iobase; /* in/out[bwl] */ |
250 | unsigned char __iomem *membase; /* read/write[bwl] */ | 251 | unsigned char __iomem *membase; /* read/write[bwl] */ |
252 | unsigned int (*serial_in)(struct uart_port *, int); | ||
253 | void (*serial_out)(struct uart_port *, int, int); | ||
251 | unsigned int irq; /* irq number */ | 254 | unsigned int irq; /* irq number */ |
252 | unsigned int uartclk; /* base uart clock */ | 255 | unsigned int uartclk; /* base uart clock */ |
253 | unsigned int fifosize; /* tx fifo size */ | 256 | unsigned int fifosize; /* tx fifo size */ |
@@ -293,6 +296,8 @@ struct uart_port { | |||
293 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) | 296 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) |
294 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) | 297 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) |
295 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) | 298 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) |
299 | /* The exact UART type is known and should not be probed. */ | ||
300 | #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) | ||
296 | #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) | 301 | #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) |
297 | #define UPF_FIXED_PORT ((__force upf_t) (1 << 29)) | 302 | #define UPF_FIXED_PORT ((__force upf_t) (1 << 29)) |
298 | #define UPF_DEAD ((__force upf_t) (1 << 30)) | 303 | #define UPF_DEAD ((__force upf_t) (1 << 30)) |
@@ -316,35 +321,13 @@ struct uart_port { | |||
316 | }; | 321 | }; |
317 | 322 | ||
318 | /* | 323 | /* |
319 | * This is the state information which is persistent across opens. | ||
320 | * The low level driver must not to touch any elements contained | ||
321 | * within. | ||
322 | */ | ||
323 | struct uart_state { | ||
324 | unsigned int close_delay; /* msec */ | ||
325 | unsigned int closing_wait; /* msec */ | ||
326 | |||
327 | #define USF_CLOSING_WAIT_INF (0) | ||
328 | #define USF_CLOSING_WAIT_NONE (~0U) | ||
329 | |||
330 | int count; | ||
331 | int pm_state; | ||
332 | struct uart_info *info; | ||
333 | struct uart_port *port; | ||
334 | |||
335 | struct mutex mutex; | ||
336 | }; | ||
337 | |||
338 | #define UART_XMIT_SIZE PAGE_SIZE | ||
339 | |||
340 | typedef unsigned int __bitwise__ uif_t; | ||
341 | |||
342 | /* | ||
343 | * This is the state information which is only valid when the port | 324 | * This is the state information which is only valid when the port |
344 | * is open; it may be freed by the core driver once the device has | 325 | * is open; it may be cleared the core driver once the device has |
345 | * been closed. Either the low level driver or the core can modify | 326 | * been closed. Either the low level driver or the core can modify |
346 | * stuff here. | 327 | * stuff here. |
347 | */ | 328 | */ |
329 | typedef unsigned int __bitwise__ uif_t; | ||
330 | |||
348 | struct uart_info { | 331 | struct uart_info { |
349 | struct tty_port port; | 332 | struct tty_port port; |
350 | struct circ_buf xmit; | 333 | struct circ_buf xmit; |
@@ -366,6 +349,29 @@ struct uart_info { | |||
366 | wait_queue_head_t delta_msr_wait; | 349 | wait_queue_head_t delta_msr_wait; |
367 | }; | 350 | }; |
368 | 351 | ||
352 | /* | ||
353 | * This is the state information which is persistent across opens. | ||
354 | * The low level driver must not to touch any elements contained | ||
355 | * within. | ||
356 | */ | ||
357 | struct uart_state { | ||
358 | unsigned int close_delay; /* msec */ | ||
359 | unsigned int closing_wait; /* msec */ | ||
360 | |||
361 | #define USF_CLOSING_WAIT_INF (0) | ||
362 | #define USF_CLOSING_WAIT_NONE (~0U) | ||
363 | |||
364 | int count; | ||
365 | int pm_state; | ||
366 | struct uart_info info; | ||
367 | struct uart_port *port; | ||
368 | |||
369 | struct mutex mutex; | ||
370 | }; | ||
371 | |||
372 | #define UART_XMIT_SIZE PAGE_SIZE | ||
373 | |||
374 | |||
369 | /* number of characters left in xmit buffer before we ask for more */ | 375 | /* number of characters left in xmit buffer before we ask for more */ |
370 | #define WAKEUP_CHARS 256 | 376 | #define WAKEUP_CHARS 256 |
371 | 377 | ||
@@ -439,8 +445,13 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); | |||
439 | #define uart_circ_chars_free(circ) \ | 445 | #define uart_circ_chars_free(circ) \ |
440 | (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) | 446 | (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE)) |
441 | 447 | ||
442 | #define uart_tx_stopped(portp) \ | 448 | static inline int uart_tx_stopped(struct uart_port *port) |
443 | ((portp)->info->port.tty->stopped || (portp)->info->port.tty->hw_stopped) | 449 | { |
450 | struct tty_struct *tty = port->info->port.tty; | ||
451 | if(tty->stopped || tty->hw_stopped) | ||
452 | return 1; | ||
453 | return 0; | ||
454 | } | ||
444 | 455 | ||
445 | /* | 456 | /* |
446 | * The following are helper functions for the low level drivers. | 457 | * The following are helper functions for the low level drivers. |
@@ -451,7 +462,7 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) | |||
451 | #ifdef SUPPORT_SYSRQ | 462 | #ifdef SUPPORT_SYSRQ |
452 | if (port->sysrq) { | 463 | if (port->sysrq) { |
453 | if (ch && time_before(jiffies, port->sysrq)) { | 464 | if (ch && time_before(jiffies, port->sysrq)) { |
454 | handle_sysrq(ch, port->info ? port->info->port.tty : NULL); | 465 | handle_sysrq(ch, port->info->port.tty); |
455 | port->sysrq = 0; | 466 | port->sysrq = 0; |
456 | return 1; | 467 | return 1; |
457 | } | 468 | } |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 3f4954c55e53..fc39db95499f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -180,8 +180,17 @@ struct signal_struct; | |||
180 | * until a hangup so don't use the wrong path. | 180 | * until a hangup so don't use the wrong path. |
181 | */ | 181 | */ |
182 | 182 | ||
183 | struct tty_port; | ||
184 | |||
185 | struct tty_port_operations { | ||
186 | /* Return 1 if the carrier is raised */ | ||
187 | int (*carrier_raised)(struct tty_port *port); | ||
188 | void (*raise_dtr_rts)(struct tty_port *port); | ||
189 | }; | ||
190 | |||
183 | struct tty_port { | 191 | struct tty_port { |
184 | struct tty_struct *tty; /* Back pointer */ | 192 | struct tty_struct *tty; /* Back pointer */ |
193 | const struct tty_port_operations *ops; /* Port operations */ | ||
185 | spinlock_t lock; /* Lock protecting tty field */ | 194 | spinlock_t lock; /* Lock protecting tty field */ |
186 | int blocked_open; /* Waiting to open */ | 195 | int blocked_open; /* Waiting to open */ |
187 | int count; /* Usage count */ | 196 | int count; /* Usage count */ |
@@ -253,6 +262,7 @@ struct tty_struct { | |||
253 | unsigned int column; | 262 | unsigned int column; |
254 | unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; | 263 | unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; |
255 | unsigned char closing:1; | 264 | unsigned char closing:1; |
265 | unsigned char echo_overrun:1; | ||
256 | unsigned short minimum_to_wake; | 266 | unsigned short minimum_to_wake; |
257 | unsigned long overrun_time; | 267 | unsigned long overrun_time; |
258 | int num_overrun; | 268 | int num_overrun; |
@@ -262,11 +272,16 @@ struct tty_struct { | |||
262 | int read_tail; | 272 | int read_tail; |
263 | int read_cnt; | 273 | int read_cnt; |
264 | unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))]; | 274 | unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))]; |
275 | unsigned char *echo_buf; | ||
276 | unsigned int echo_pos; | ||
277 | unsigned int echo_cnt; | ||
265 | int canon_data; | 278 | int canon_data; |
266 | unsigned long canon_head; | 279 | unsigned long canon_head; |
267 | unsigned int canon_column; | 280 | unsigned int canon_column; |
268 | struct mutex atomic_read_lock; | 281 | struct mutex atomic_read_lock; |
269 | struct mutex atomic_write_lock; | 282 | struct mutex atomic_write_lock; |
283 | struct mutex output_lock; | ||
284 | struct mutex echo_lock; | ||
270 | unsigned char *write_buf; | 285 | unsigned char *write_buf; |
271 | int write_cnt; | 286 | int write_cnt; |
272 | spinlock_t read_lock; | 287 | spinlock_t read_lock; |
@@ -295,6 +310,7 @@ struct tty_struct { | |||
295 | #define TTY_PUSH 6 /* n_tty private */ | 310 | #define TTY_PUSH 6 /* n_tty private */ |
296 | #define TTY_CLOSING 7 /* ->close() in progress */ | 311 | #define TTY_CLOSING 7 /* ->close() in progress */ |
297 | #define TTY_LDISC 9 /* Line discipline attached */ | 312 | #define TTY_LDISC 9 /* Line discipline attached */ |
313 | #define TTY_LDISC_CHANGING 10 /* Line discipline changing */ | ||
298 | #define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */ | 314 | #define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */ |
299 | #define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */ | 315 | #define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */ |
300 | #define TTY_PTY_LOCK 16 /* pty private */ | 316 | #define TTY_PTY_LOCK 16 /* pty private */ |
@@ -354,8 +370,7 @@ extern int tty_write_room(struct tty_struct *tty); | |||
354 | extern void tty_driver_flush_buffer(struct tty_struct *tty); | 370 | extern void tty_driver_flush_buffer(struct tty_struct *tty); |
355 | extern void tty_throttle(struct tty_struct *tty); | 371 | extern void tty_throttle(struct tty_struct *tty); |
356 | extern void tty_unthrottle(struct tty_struct *tty); | 372 | extern void tty_unthrottle(struct tty_struct *tty); |
357 | extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 373 | extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); |
358 | struct winsize *ws); | ||
359 | extern void tty_shutdown(struct tty_struct *tty); | 374 | extern void tty_shutdown(struct tty_struct *tty); |
360 | extern void tty_free_termios(struct tty_struct *tty); | 375 | extern void tty_free_termios(struct tty_struct *tty); |
361 | extern int is_current_pgrp_orphaned(void); | 376 | extern int is_current_pgrp_orphaned(void); |
@@ -421,6 +436,14 @@ extern int tty_port_alloc_xmit_buf(struct tty_port *port); | |||
421 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 436 | extern void tty_port_free_xmit_buf(struct tty_port *port); |
422 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); | 437 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); |
423 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); | 438 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); |
439 | extern int tty_port_carrier_raised(struct tty_port *port); | ||
440 | extern void tty_port_raise_dtr_rts(struct tty_port *port); | ||
441 | extern void tty_port_hangup(struct tty_port *port); | ||
442 | extern int tty_port_block_til_ready(struct tty_port *port, | ||
443 | struct tty_struct *tty, struct file *filp); | ||
444 | extern int tty_port_close_start(struct tty_port *port, | ||
445 | struct tty_struct *tty, struct file *filp); | ||
446 | extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); | ||
424 | 447 | ||
425 | extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); | 448 | extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); |
426 | extern int tty_unregister_ldisc(int disc); | 449 | extern int tty_unregister_ldisc(int disc); |
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 78416b901589..08e088334dba 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h | |||
@@ -196,8 +196,7 @@ | |||
196 | * Optional: If not provided then the write method is called under | 196 | * Optional: If not provided then the write method is called under |
197 | * the atomic write lock to keep it serialized with the ldisc. | 197 | * the atomic write lock to keep it serialized with the ldisc. |
198 | * | 198 | * |
199 | * int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, | 199 | * int (*resize)(struct tty_struct *tty, struct winsize *ws) |
200 | * unsigned int rows, unsigned int cols); | ||
201 | * | 200 | * |
202 | * Called when a termios request is issued which changes the | 201 | * Called when a termios request is issued which changes the |
203 | * requested terminal geometry. | 202 | * requested terminal geometry. |
@@ -258,8 +257,7 @@ struct tty_operations { | |||
258 | int (*tiocmget)(struct tty_struct *tty, struct file *file); | 257 | int (*tiocmget)(struct tty_struct *tty, struct file *file); |
259 | int (*tiocmset)(struct tty_struct *tty, struct file *file, | 258 | int (*tiocmset)(struct tty_struct *tty, struct file *file, |
260 | unsigned int set, unsigned int clear); | 259 | unsigned int set, unsigned int clear); |
261 | int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, | 260 | int (*resize)(struct tty_struct *tty, struct winsize *ws); |
262 | struct winsize *ws); | ||
263 | int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); | 261 | int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); |
264 | #ifdef CONFIG_CONSOLE_POLL | 262 | #ifdef CONFIG_CONSOLE_POLL |
265 | int (*poll_init)(struct tty_driver *driver, int line, char *options); | 263 | int (*poll_init)(struct tty_driver *driver, int line, char *options); |
diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h index a102561e7026..fb7c359bdfba 100644 --- a/include/linux/usb/wusb-wa.h +++ b/include/linux/usb/wusb-wa.h | |||
@@ -51,6 +51,7 @@ enum { | |||
51 | WUSB_REQ_GET_TIME = 25, | 51 | WUSB_REQ_GET_TIME = 25, |
52 | WUSB_REQ_SET_STREAM_IDX = 26, | 52 | WUSB_REQ_SET_STREAM_IDX = 26, |
53 | WUSB_REQ_SET_WUSB_MAS = 27, | 53 | WUSB_REQ_SET_WUSB_MAS = 27, |
54 | WUSB_REQ_CHAN_STOP = 28, | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | 57 | ||
diff --git a/include/linux/uwb.h b/include/linux/uwb.h index f9ccbd9a2ced..c02128991ff7 100644 --- a/include/linux/uwb.h +++ b/include/linux/uwb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
33 | #include <linux/wait.h> | ||
33 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
34 | #include <linux/uwb/spec.h> | 35 | #include <linux/uwb/spec.h> |
35 | 36 | ||
@@ -66,6 +67,7 @@ struct uwb_dev { | |||
66 | struct uwb_dev_addr dev_addr; | 67 | struct uwb_dev_addr dev_addr; |
67 | int beacon_slot; | 68 | int beacon_slot; |
68 | DECLARE_BITMAP(streams, UWB_NUM_STREAMS); | 69 | DECLARE_BITMAP(streams, UWB_NUM_STREAMS); |
70 | DECLARE_BITMAP(last_availability_bm, UWB_NUM_MAS); | ||
69 | }; | 71 | }; |
70 | #define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) | 72 | #define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) |
71 | 73 | ||
@@ -86,12 +88,31 @@ struct uwb_notifs_chain { | |||
86 | struct mutex mutex; | 88 | struct mutex mutex; |
87 | }; | 89 | }; |
88 | 90 | ||
91 | /* Beacon cache list */ | ||
92 | struct uwb_beca { | ||
93 | struct list_head list; | ||
94 | size_t entries; | ||
95 | struct mutex mutex; | ||
96 | }; | ||
97 | |||
98 | /* Event handling thread. */ | ||
99 | struct uwbd { | ||
100 | int pid; | ||
101 | struct task_struct *task; | ||
102 | wait_queue_head_t wq; | ||
103 | struct list_head event_list; | ||
104 | spinlock_t event_list_lock; | ||
105 | }; | ||
106 | |||
89 | /** | 107 | /** |
90 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe | 108 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe |
91 | * @bm: a bitmap of length #UWB_NUM_MAS | 109 | * @bm: a bitmap of length #UWB_NUM_MAS |
92 | */ | 110 | */ |
93 | struct uwb_mas_bm { | 111 | struct uwb_mas_bm { |
94 | DECLARE_BITMAP(bm, UWB_NUM_MAS); | 112 | DECLARE_BITMAP(bm, UWB_NUM_MAS); |
113 | DECLARE_BITMAP(unsafe_bm, UWB_NUM_MAS); | ||
114 | int safe; | ||
115 | int unsafe; | ||
95 | }; | 116 | }; |
96 | 117 | ||
97 | /** | 118 | /** |
@@ -117,14 +138,24 @@ struct uwb_mas_bm { | |||
117 | * FIXME: further target states TBD. | 138 | * FIXME: further target states TBD. |
118 | */ | 139 | */ |
119 | enum uwb_rsv_state { | 140 | enum uwb_rsv_state { |
120 | UWB_RSV_STATE_NONE, | 141 | UWB_RSV_STATE_NONE = 0, |
121 | UWB_RSV_STATE_O_INITIATED, | 142 | UWB_RSV_STATE_O_INITIATED, |
122 | UWB_RSV_STATE_O_PENDING, | 143 | UWB_RSV_STATE_O_PENDING, |
123 | UWB_RSV_STATE_O_MODIFIED, | 144 | UWB_RSV_STATE_O_MODIFIED, |
124 | UWB_RSV_STATE_O_ESTABLISHED, | 145 | UWB_RSV_STATE_O_ESTABLISHED, |
146 | UWB_RSV_STATE_O_TO_BE_MOVED, | ||
147 | UWB_RSV_STATE_O_MOVE_EXPANDING, | ||
148 | UWB_RSV_STATE_O_MOVE_COMBINING, | ||
149 | UWB_RSV_STATE_O_MOVE_REDUCING, | ||
125 | UWB_RSV_STATE_T_ACCEPTED, | 150 | UWB_RSV_STATE_T_ACCEPTED, |
126 | UWB_RSV_STATE_T_DENIED, | 151 | UWB_RSV_STATE_T_DENIED, |
152 | UWB_RSV_STATE_T_CONFLICT, | ||
127 | UWB_RSV_STATE_T_PENDING, | 153 | UWB_RSV_STATE_T_PENDING, |
154 | UWB_RSV_STATE_T_EXPANDING_ACCEPTED, | ||
155 | UWB_RSV_STATE_T_EXPANDING_CONFLICT, | ||
156 | UWB_RSV_STATE_T_EXPANDING_PENDING, | ||
157 | UWB_RSV_STATE_T_EXPANDING_DENIED, | ||
158 | UWB_RSV_STATE_T_RESIZED, | ||
128 | 159 | ||
129 | UWB_RSV_STATE_LAST, | 160 | UWB_RSV_STATE_LAST, |
130 | }; | 161 | }; |
@@ -149,6 +180,12 @@ struct uwb_rsv_target { | |||
149 | }; | 180 | }; |
150 | }; | 181 | }; |
151 | 182 | ||
183 | struct uwb_rsv_move { | ||
184 | struct uwb_mas_bm final_mas; | ||
185 | struct uwb_ie_drp *companion_drp_ie; | ||
186 | struct uwb_mas_bm companion_mas; | ||
187 | }; | ||
188 | |||
152 | /* | 189 | /* |
153 | * Number of streams reserved for reservations targeted at DevAddrs. | 190 | * Number of streams reserved for reservations targeted at DevAddrs. |
154 | */ | 191 | */ |
@@ -186,6 +223,7 @@ typedef void (*uwb_rsv_cb_f)(struct uwb_rsv *rsv); | |||
186 | * | 223 | * |
187 | * @status: negotiation status | 224 | * @status: negotiation status |
188 | * @stream: stream index allocated for this reservation | 225 | * @stream: stream index allocated for this reservation |
226 | * @tiebreaker: conflict tiebreaker for this reservation | ||
189 | * @mas: reserved MAS | 227 | * @mas: reserved MAS |
190 | * @drp_ie: the DRP IE | 228 | * @drp_ie: the DRP IE |
191 | * @ie_valid: true iff the DRP IE matches the reservation parameters | 229 | * @ie_valid: true iff the DRP IE matches the reservation parameters |
@@ -201,25 +239,29 @@ struct uwb_rsv { | |||
201 | struct uwb_rc *rc; | 239 | struct uwb_rc *rc; |
202 | struct list_head rc_node; | 240 | struct list_head rc_node; |
203 | struct list_head pal_node; | 241 | struct list_head pal_node; |
242 | struct kref kref; | ||
204 | 243 | ||
205 | struct uwb_dev *owner; | 244 | struct uwb_dev *owner; |
206 | struct uwb_rsv_target target; | 245 | struct uwb_rsv_target target; |
207 | enum uwb_drp_type type; | 246 | enum uwb_drp_type type; |
208 | int max_mas; | 247 | int max_mas; |
209 | int min_mas; | 248 | int min_mas; |
210 | int sparsity; | 249 | int max_interval; |
211 | bool is_multicast; | 250 | bool is_multicast; |
212 | 251 | ||
213 | uwb_rsv_cb_f callback; | 252 | uwb_rsv_cb_f callback; |
214 | void *pal_priv; | 253 | void *pal_priv; |
215 | 254 | ||
216 | enum uwb_rsv_state state; | 255 | enum uwb_rsv_state state; |
256 | bool needs_release_companion_mas; | ||
217 | u8 stream; | 257 | u8 stream; |
258 | u8 tiebreaker; | ||
218 | struct uwb_mas_bm mas; | 259 | struct uwb_mas_bm mas; |
219 | struct uwb_ie_drp *drp_ie; | 260 | struct uwb_ie_drp *drp_ie; |
261 | struct uwb_rsv_move mv; | ||
220 | bool ie_valid; | 262 | bool ie_valid; |
221 | struct timer_list timer; | 263 | struct timer_list timer; |
222 | bool expired; | 264 | struct work_struct handle_timeout_work; |
223 | }; | 265 | }; |
224 | 266 | ||
225 | static const | 267 | static const |
@@ -261,6 +303,13 @@ struct uwb_drp_avail { | |||
261 | bool ie_valid; | 303 | bool ie_valid; |
262 | }; | 304 | }; |
263 | 305 | ||
306 | struct uwb_drp_backoff_win { | ||
307 | u8 window; | ||
308 | u8 n; | ||
309 | int total_expired; | ||
310 | struct timer_list timer; | ||
311 | bool can_reserve_extra_mases; | ||
312 | }; | ||
264 | 313 | ||
265 | const char *uwb_rsv_state_str(enum uwb_rsv_state state); | 314 | const char *uwb_rsv_state_str(enum uwb_rsv_state state); |
266 | const char *uwb_rsv_type_str(enum uwb_drp_type type); | 315 | const char *uwb_rsv_type_str(enum uwb_drp_type type); |
@@ -276,6 +325,8 @@ void uwb_rsv_terminate(struct uwb_rsv *rsv); | |||
276 | 325 | ||
277 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); | 326 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); |
278 | 327 | ||
328 | void uwb_rsv_get_usable_mas(struct uwb_rsv *orig_rsv, struct uwb_mas_bm *mas); | ||
329 | |||
279 | /** | 330 | /** |
280 | * Radio Control Interface instance | 331 | * Radio Control Interface instance |
281 | * | 332 | * |
@@ -337,23 +388,33 @@ struct uwb_rc { | |||
337 | u8 ctx_roll; | 388 | u8 ctx_roll; |
338 | 389 | ||
339 | int beaconing; /* Beaconing state [channel number] */ | 390 | int beaconing; /* Beaconing state [channel number] */ |
391 | int beaconing_forced; | ||
340 | int scanning; | 392 | int scanning; |
341 | enum uwb_scan_type scan_type:3; | 393 | enum uwb_scan_type scan_type:3; |
342 | unsigned ready:1; | 394 | unsigned ready:1; |
343 | struct uwb_notifs_chain notifs_chain; | 395 | struct uwb_notifs_chain notifs_chain; |
396 | struct uwb_beca uwb_beca; | ||
397 | |||
398 | struct uwbd uwbd; | ||
344 | 399 | ||
400 | struct uwb_drp_backoff_win bow; | ||
345 | struct uwb_drp_avail drp_avail; | 401 | struct uwb_drp_avail drp_avail; |
346 | struct list_head reservations; | 402 | struct list_head reservations; |
403 | struct list_head cnflt_alien_list; | ||
404 | struct uwb_mas_bm cnflt_alien_bitmap; | ||
347 | struct mutex rsvs_mutex; | 405 | struct mutex rsvs_mutex; |
406 | spinlock_t rsvs_lock; | ||
348 | struct workqueue_struct *rsv_workq; | 407 | struct workqueue_struct *rsv_workq; |
349 | struct work_struct rsv_update_work; | ||
350 | 408 | ||
409 | struct delayed_work rsv_update_work; | ||
410 | struct delayed_work rsv_alien_bp_work; | ||
411 | int set_drp_ie_pending; | ||
351 | struct mutex ies_mutex; | 412 | struct mutex ies_mutex; |
352 | struct uwb_rc_cmd_set_ie *ies; | 413 | struct uwb_rc_cmd_set_ie *ies; |
353 | size_t ies_capacity; | 414 | size_t ies_capacity; |
354 | 415 | ||
355 | spinlock_t pal_lock; | ||
356 | struct list_head pals; | 416 | struct list_head pals; |
417 | int active_pals; | ||
357 | 418 | ||
358 | struct uwb_dbg *dbg; | 419 | struct uwb_dbg *dbg; |
359 | }; | 420 | }; |
@@ -361,11 +422,19 @@ struct uwb_rc { | |||
361 | 422 | ||
362 | /** | 423 | /** |
363 | * struct uwb_pal - a UWB PAL | 424 | * struct uwb_pal - a UWB PAL |
364 | * @name: descriptive name for this PAL (wushc, wlp, etc.). | 425 | * @name: descriptive name for this PAL (wusbhc, wlp, etc.). |
365 | * @device: a device for the PAL. Used to link the PAL and the radio | 426 | * @device: a device for the PAL. Used to link the PAL and the radio |
366 | * controller in sysfs. | 427 | * controller in sysfs. |
428 | * @rc: the radio controller the PAL uses. | ||
429 | * @channel_changed: called when the channel used by the radio changes. | ||
430 | * A channel of -1 means the channel has been stopped. | ||
367 | * @new_rsv: called when a peer requests a reservation (may be NULL if | 431 | * @new_rsv: called when a peer requests a reservation (may be NULL if |
368 | * the PAL cannot accept reservation requests). | 432 | * the PAL cannot accept reservation requests). |
433 | * @channel: channel being used by the PAL; 0 if the PAL isn't using | ||
434 | * the radio; -1 if the PAL wishes to use the radio but | ||
435 | * cannot. | ||
436 | * @debugfs_dir: a debugfs directory which the PAL can use for its own | ||
437 | * debugfs files. | ||
369 | * | 438 | * |
370 | * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB | 439 | * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB |
371 | * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). | 440 | * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). |
@@ -384,12 +453,21 @@ struct uwb_pal { | |||
384 | struct list_head node; | 453 | struct list_head node; |
385 | const char *name; | 454 | const char *name; |
386 | struct device *device; | 455 | struct device *device; |
387 | void (*new_rsv)(struct uwb_rsv *rsv); | 456 | struct uwb_rc *rc; |
457 | |||
458 | void (*channel_changed)(struct uwb_pal *pal, int channel); | ||
459 | void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv); | ||
460 | |||
461 | int channel; | ||
462 | struct dentry *debugfs_dir; | ||
388 | }; | 463 | }; |
389 | 464 | ||
390 | void uwb_pal_init(struct uwb_pal *pal); | 465 | void uwb_pal_init(struct uwb_pal *pal); |
391 | int uwb_pal_register(struct uwb_rc *rc, struct uwb_pal *pal); | 466 | int uwb_pal_register(struct uwb_pal *pal); |
392 | void uwb_pal_unregister(struct uwb_rc *rc, struct uwb_pal *pal); | 467 | void uwb_pal_unregister(struct uwb_pal *pal); |
468 | |||
469 | int uwb_radio_start(struct uwb_pal *pal); | ||
470 | void uwb_radio_stop(struct uwb_pal *pal); | ||
393 | 471 | ||
394 | /* | 472 | /* |
395 | * General public API | 473 | * General public API |
@@ -443,8 +521,6 @@ ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, | |||
443 | struct uwb_rccb *cmd, size_t cmd_size, | 521 | struct uwb_rccb *cmd, size_t cmd_size, |
444 | u8 expected_type, u16 expected_event, | 522 | u8 expected_type, u16 expected_event, |
445 | struct uwb_rceb **preply); | 523 | struct uwb_rceb **preply); |
446 | ssize_t uwb_rc_get_ie(struct uwb_rc *, struct uwb_rc_evt_get_ie **); | ||
447 | int uwb_bg_joined(struct uwb_rc *rc); | ||
448 | 524 | ||
449 | size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); | 525 | size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); |
450 | 526 | ||
@@ -520,6 +596,8 @@ void uwb_rc_rm(struct uwb_rc *); | |||
520 | void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); | 596 | void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); |
521 | void uwb_rc_neh_error(struct uwb_rc *, int); | 597 | void uwb_rc_neh_error(struct uwb_rc *, int); |
522 | void uwb_rc_reset_all(struct uwb_rc *rc); | 598 | void uwb_rc_reset_all(struct uwb_rc *rc); |
599 | void uwb_rc_pre_reset(struct uwb_rc *rc); | ||
600 | void uwb_rc_post_reset(struct uwb_rc *rc); | ||
523 | 601 | ||
524 | /** | 602 | /** |
525 | * uwb_rsv_is_owner - is the owner of this reservation the RC? | 603 | * uwb_rsv_is_owner - is the owner of this reservation the RC? |
@@ -531,7 +609,9 @@ static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) | |||
531 | } | 609 | } |
532 | 610 | ||
533 | /** | 611 | /** |
534 | * Events generated by UWB that can be passed to any listeners | 612 | * enum uwb_notifs - UWB events that can be passed to any listeners |
613 | * @UWB_NOTIF_ONAIR: a new neighbour has joined the beacon group. | ||
614 | * @UWB_NOTIF_OFFAIR: a neighbour has left the beacon group. | ||
535 | * | 615 | * |
536 | * Higher layers can register callback functions with the radio | 616 | * Higher layers can register callback functions with the radio |
537 | * controller using uwb_notifs_register(). The radio controller | 617 | * controller using uwb_notifs_register(). The radio controller |
@@ -539,8 +619,6 @@ static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) | |||
539 | * nodes when an event occurs. | 619 | * nodes when an event occurs. |
540 | */ | 620 | */ |
541 | enum uwb_notifs { | 621 | enum uwb_notifs { |
542 | UWB_NOTIF_BG_JOIN = 0, /* radio controller joined a beacon group */ | ||
543 | UWB_NOTIF_BG_LEAVE = 1, /* radio controller left a beacon group */ | ||
544 | UWB_NOTIF_ONAIR, | 622 | UWB_NOTIF_ONAIR, |
545 | UWB_NOTIF_OFFAIR, | 623 | UWB_NOTIF_OFFAIR, |
546 | }; | 624 | }; |
@@ -652,22 +730,9 @@ static inline int edc_inc(struct edc *err_hist, u16 max_err, u16 timeframe) | |||
652 | 730 | ||
653 | /* Information Element handling */ | 731 | /* Information Element handling */ |
654 | 732 | ||
655 | /* For representing the state of writing to a buffer when iterating */ | ||
656 | struct uwb_buf_ctx { | ||
657 | char *buf; | ||
658 | size_t bytes, size; | ||
659 | }; | ||
660 | |||
661 | typedef int (*uwb_ie_f)(struct uwb_dev *, const struct uwb_ie_hdr *, | ||
662 | size_t, void *); | ||
663 | struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); | 733 | struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); |
664 | ssize_t uwb_ie_for_each(struct uwb_dev *uwb_dev, uwb_ie_f fn, void *data, | 734 | int uwb_rc_ie_add(struct uwb_rc *uwb_rc, const struct uwb_ie_hdr *ies, size_t size); |
665 | const void *buf, size_t size); | 735 | int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id); |
666 | int uwb_ie_dump_hex(struct uwb_dev *, const struct uwb_ie_hdr *, | ||
667 | size_t, void *); | ||
668 | int uwb_rc_set_ie(struct uwb_rc *, struct uwb_rc_cmd_set_ie *); | ||
669 | struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); | ||
670 | |||
671 | 736 | ||
672 | /* | 737 | /* |
673 | * Transmission statistics | 738 | * Transmission statistics |
diff --git a/include/linux/uwb/debug-cmd.h b/include/linux/uwb/debug-cmd.h index 1141f41bab5c..8da004e25628 100644 --- a/include/linux/uwb/debug-cmd.h +++ b/include/linux/uwb/debug-cmd.h | |||
@@ -32,6 +32,10 @@ | |||
32 | enum uwb_dbg_cmd_type { | 32 | enum uwb_dbg_cmd_type { |
33 | UWB_DBG_CMD_RSV_ESTABLISH = 1, | 33 | UWB_DBG_CMD_RSV_ESTABLISH = 1, |
34 | UWB_DBG_CMD_RSV_TERMINATE = 2, | 34 | UWB_DBG_CMD_RSV_TERMINATE = 2, |
35 | UWB_DBG_CMD_IE_ADD = 3, | ||
36 | UWB_DBG_CMD_IE_RM = 4, | ||
37 | UWB_DBG_CMD_RADIO_START = 5, | ||
38 | UWB_DBG_CMD_RADIO_STOP = 6, | ||
35 | }; | 39 | }; |
36 | 40 | ||
37 | struct uwb_dbg_cmd_rsv_establish { | 41 | struct uwb_dbg_cmd_rsv_establish { |
@@ -39,18 +43,25 @@ struct uwb_dbg_cmd_rsv_establish { | |||
39 | __u8 type; | 43 | __u8 type; |
40 | __u16 max_mas; | 44 | __u16 max_mas; |
41 | __u16 min_mas; | 45 | __u16 min_mas; |
42 | __u8 sparsity; | 46 | __u8 max_interval; |
43 | }; | 47 | }; |
44 | 48 | ||
45 | struct uwb_dbg_cmd_rsv_terminate { | 49 | struct uwb_dbg_cmd_rsv_terminate { |
46 | int index; | 50 | int index; |
47 | }; | 51 | }; |
48 | 52 | ||
53 | struct uwb_dbg_cmd_ie { | ||
54 | __u8 data[128]; | ||
55 | int len; | ||
56 | }; | ||
57 | |||
49 | struct uwb_dbg_cmd { | 58 | struct uwb_dbg_cmd { |
50 | __u32 type; | 59 | __u32 type; |
51 | union { | 60 | union { |
52 | struct uwb_dbg_cmd_rsv_establish rsv_establish; | 61 | struct uwb_dbg_cmd_rsv_establish rsv_establish; |
53 | struct uwb_dbg_cmd_rsv_terminate rsv_terminate; | 62 | struct uwb_dbg_cmd_rsv_terminate rsv_terminate; |
63 | struct uwb_dbg_cmd_ie ie_add; | ||
64 | struct uwb_dbg_cmd_ie ie_rm; | ||
54 | }; | 65 | }; |
55 | }; | 66 | }; |
56 | 67 | ||
diff --git a/include/linux/uwb/debug.h b/include/linux/uwb/debug.h deleted file mode 100644 index a86a73fe303f..000000000000 --- a/include/linux/uwb/debug.h +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /* | ||
2 | * Ultra Wide Band | ||
3 | * Debug Support | ||
4 | * | ||
5 | * Copyright (C) 2005-2006 Intel Corporation | ||
6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301, USA. | ||
21 | * | ||
22 | * | ||
23 | * FIXME: doc | ||
24 | * Invoke like: | ||
25 | * | ||
26 | * #define D_LOCAL 4 | ||
27 | * #include <linux/uwb/debug.h> | ||
28 | * | ||
29 | * At the end of your include files. | ||
30 | */ | ||
31 | #include <linux/types.h> | ||
32 | |||
33 | struct device; | ||
34 | extern void dump_bytes(struct device *dev, const void *_buf, size_t rsize); | ||
35 | |||
36 | /* Master debug switch; !0 enables, 0 disables */ | ||
37 | #define D_MASTER (!0) | ||
38 | |||
39 | /* Local (per-file) debug switch; #define before #including */ | ||
40 | #ifndef D_LOCAL | ||
41 | #define D_LOCAL 0 | ||
42 | #endif | ||
43 | |||
44 | #undef __d_printf | ||
45 | #undef d_fnstart | ||
46 | #undef d_fnend | ||
47 | #undef d_printf | ||
48 | #undef d_dump | ||
49 | |||
50 | #define __d_printf(l, _tag, _dev, f, a...) \ | ||
51 | do { \ | ||
52 | struct device *__dev = (_dev); \ | ||
53 | if (D_MASTER && D_LOCAL >= (l)) { \ | ||
54 | char __head[64] = ""; \ | ||
55 | if (_dev != NULL) { \ | ||
56 | if ((unsigned long)__dev < 4096) \ | ||
57 | printk(KERN_ERR "E: Corrupt dev %p\n", \ | ||
58 | __dev); \ | ||
59 | else \ | ||
60 | snprintf(__head, sizeof(__head), \ | ||
61 | "%s %s: ", \ | ||
62 | dev_driver_string(__dev), \ | ||
63 | __dev->bus_id); \ | ||
64 | } \ | ||
65 | printk(KERN_ERR "%s%s" _tag ": " f, __head, \ | ||
66 | __func__, ## a); \ | ||
67 | } \ | ||
68 | } while (0 && _dev) | ||
69 | |||
70 | #define d_fnstart(l, _dev, f, a...) \ | ||
71 | __d_printf(l, " FNSTART", _dev, f, ## a) | ||
72 | #define d_fnend(l, _dev, f, a...) \ | ||
73 | __d_printf(l, " FNEND", _dev, f, ## a) | ||
74 | #define d_printf(l, _dev, f, a...) \ | ||
75 | __d_printf(l, "", _dev, f, ## a) | ||
76 | #define d_dump(l, _dev, ptr, size) \ | ||
77 | do { \ | ||
78 | struct device *__dev = _dev; \ | ||
79 | if (D_MASTER && D_LOCAL >= (l)) \ | ||
80 | dump_bytes(__dev, ptr, size); \ | ||
81 | } while (0 && _dev) | ||
82 | #define d_test(l) (D_MASTER && D_LOCAL >= (l)) | ||
diff --git a/include/linux/uwb/spec.h b/include/linux/uwb/spec.h index 198c15f8e251..b52e44f1bd33 100644 --- a/include/linux/uwb/spec.h +++ b/include/linux/uwb/spec.h | |||
@@ -59,6 +59,11 @@ enum { UWB_NUM_ZONES = 16 }; | |||
59 | #define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) | 59 | #define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * Number of MAS required before a row can be considered available. | ||
63 | */ | ||
64 | #define UWB_USABLE_MAS_PER_ROW (UWB_NUM_ZONES - 1) | ||
65 | |||
66 | /* | ||
62 | * Number of streams per DRP reservation between a pair of devices. | 67 | * Number of streams per DRP reservation between a pair of devices. |
63 | * | 68 | * |
64 | * [ECMA-368] section 16.8.6. | 69 | * [ECMA-368] section 16.8.6. |
@@ -94,6 +99,26 @@ enum { UWB_BEACON_SLOT_LENGTH_US = 85 }; | |||
94 | enum { UWB_MAX_LOST_BEACONS = 3 }; | 99 | enum { UWB_MAX_LOST_BEACONS = 3 }; |
95 | 100 | ||
96 | /* | 101 | /* |
102 | * mDRPBackOffWinMin | ||
103 | * | ||
104 | * The minimum number of superframes to wait before trying to reserve | ||
105 | * extra MAS. | ||
106 | * | ||
107 | * [ECMA-368] section 17.16 | ||
108 | */ | ||
109 | enum { UWB_DRP_BACKOFF_WIN_MIN = 2 }; | ||
110 | |||
111 | /* | ||
112 | * mDRPBackOffWinMax | ||
113 | * | ||
114 | * The maximum number of superframes to wait before trying to reserve | ||
115 | * extra MAS. | ||
116 | * | ||
117 | * [ECMA-368] section 17.16 | ||
118 | */ | ||
119 | enum { UWB_DRP_BACKOFF_WIN_MAX = 16 }; | ||
120 | |||
121 | /* | ||
97 | * Length of a superframe in microseconds. | 122 | * Length of a superframe in microseconds. |
98 | */ | 123 | */ |
99 | #define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) | 124 | #define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) |
@@ -200,6 +225,12 @@ enum uwb_drp_reason { | |||
200 | UWB_DRP_REASON_MODIFIED, | 225 | UWB_DRP_REASON_MODIFIED, |
201 | }; | 226 | }; |
202 | 227 | ||
228 | /** Relinquish Request Reason Codes ([ECMA-368] table 113) */ | ||
229 | enum uwb_relinquish_req_reason { | ||
230 | UWB_RELINQUISH_REQ_REASON_NON_SPECIFIC = 0, | ||
231 | UWB_RELINQUISH_REQ_REASON_OVER_ALLOCATION, | ||
232 | }; | ||
233 | |||
203 | /** | 234 | /** |
204 | * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) | 235 | * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) |
205 | */ | 236 | */ |
@@ -252,6 +283,7 @@ enum uwb_ie { | |||
252 | UWB_APP_SPEC_PROBE_IE = 15, | 283 | UWB_APP_SPEC_PROBE_IE = 15, |
253 | UWB_IDENTIFICATION_IE = 19, | 284 | UWB_IDENTIFICATION_IE = 19, |
254 | UWB_MASTER_KEY_ID_IE = 20, | 285 | UWB_MASTER_KEY_ID_IE = 20, |
286 | UWB_RELINQUISH_REQUEST_IE = 21, | ||
255 | UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ | 287 | UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ |
256 | UWB_APP_SPEC_IE = 255, | 288 | UWB_APP_SPEC_IE = 255, |
257 | }; | 289 | }; |
@@ -365,6 +397,27 @@ struct uwb_ie_drp_avail { | |||
365 | DECLARE_BITMAP(bmp, UWB_NUM_MAS); | 397 | DECLARE_BITMAP(bmp, UWB_NUM_MAS); |
366 | } __attribute__((packed)); | 398 | } __attribute__((packed)); |
367 | 399 | ||
400 | /* Relinqish Request IE ([ECMA-368] section 16.8.19). */ | ||
401 | struct uwb_relinquish_request_ie { | ||
402 | struct uwb_ie_hdr hdr; | ||
403 | __le16 relinquish_req_control; | ||
404 | struct uwb_dev_addr dev_addr; | ||
405 | struct uwb_drp_alloc allocs[]; | ||
406 | } __attribute__((packed)); | ||
407 | |||
408 | static inline int uwb_ie_relinquish_req_reason_code(struct uwb_relinquish_request_ie *ie) | ||
409 | { | ||
410 | return (le16_to_cpu(ie->relinquish_req_control) >> 0) & 0xf; | ||
411 | } | ||
412 | |||
413 | static inline void uwb_ie_relinquish_req_set_reason_code(struct uwb_relinquish_request_ie *ie, | ||
414 | int reason_code) | ||
415 | { | ||
416 | u16 ctrl = le16_to_cpu(ie->relinquish_req_control); | ||
417 | ctrl = (ctrl & ~(0xf << 0)) | (reason_code << 0); | ||
418 | ie->relinquish_req_control = cpu_to_le16(ctrl); | ||
419 | } | ||
420 | |||
368 | /** | 421 | /** |
369 | * The Vendor ID is set to an OUI that indicates the vendor of the device. | 422 | * The Vendor ID is set to an OUI that indicates the vendor of the device. |
370 | * ECMA-368 [16.8.10] | 423 | * ECMA-368 [16.8.10] |
diff --git a/include/linux/uwb/umc.h b/include/linux/uwb/umc.h index 36a39e34f8d7..4b4fc0f43855 100644 --- a/include/linux/uwb/umc.h +++ b/include/linux/uwb/umc.h | |||
@@ -89,6 +89,8 @@ struct umc_driver { | |||
89 | void (*remove)(struct umc_dev *); | 89 | void (*remove)(struct umc_dev *); |
90 | int (*suspend)(struct umc_dev *, pm_message_t state); | 90 | int (*suspend)(struct umc_dev *, pm_message_t state); |
91 | int (*resume)(struct umc_dev *); | 91 | int (*resume)(struct umc_dev *); |
92 | int (*pre_reset)(struct umc_dev *); | ||
93 | int (*post_reset)(struct umc_dev *); | ||
92 | 94 | ||
93 | struct device_driver driver; | 95 | struct device_driver driver; |
94 | }; | 96 | }; |
diff --git a/include/linux/wlp.h b/include/linux/wlp.h index 033545e145c7..ac95ce6606ac 100644 --- a/include/linux/wlp.h +++ b/include/linux/wlp.h | |||
@@ -646,6 +646,7 @@ struct wlp_wss { | |||
646 | struct wlp { | 646 | struct wlp { |
647 | struct mutex mutex; | 647 | struct mutex mutex; |
648 | struct uwb_rc *rc; /* UWB radio controller */ | 648 | struct uwb_rc *rc; /* UWB radio controller */ |
649 | struct net_device *ndev; | ||
649 | struct uwb_pal pal; | 650 | struct uwb_pal pal; |
650 | struct wlp_eda eda; | 651 | struct wlp_eda eda; |
651 | struct wlp_uuid uuid; | 652 | struct wlp_uuid uuid; |
@@ -675,7 +676,7 @@ struct wlp_wss_attribute { | |||
675 | static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \ | 676 | static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode, \ |
676 | _show, _store) | 677 | _show, _store) |
677 | 678 | ||
678 | extern int wlp_setup(struct wlp *, struct uwb_rc *); | 679 | extern int wlp_setup(struct wlp *, struct uwb_rc *, struct net_device *ndev); |
679 | extern void wlp_remove(struct wlp *); | 680 | extern void wlp_remove(struct wlp *); |
680 | extern ssize_t wlp_neighborhood_show(struct wlp *, char *); | 681 | extern ssize_t wlp_neighborhood_show(struct wlp *, char *); |
681 | extern int wlp_wss_setup(struct net_device *, struct wlp_wss *); | 682 | extern int wlp_wss_setup(struct net_device *, struct wlp_wss *); |
diff --git a/init/main.c b/init/main.c index 2a7ce0f8e453..ad8f9f53f8d1 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -75,15 +75,6 @@ | |||
75 | #include <asm/smp.h> | 75 | #include <asm/smp.h> |
76 | #endif | 76 | #endif |
77 | 77 | ||
78 | /* | ||
79 | * This is one of the first .c files built. Error out early if we have compiler | ||
80 | * trouble. | ||
81 | */ | ||
82 | |||
83 | #if __GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 0 | ||
84 | #warning gcc-4.1.0 is known to miscompile the kernel. A different compiler version is recommended. | ||
85 | #endif | ||
86 | |||
87 | static int kernel_init(void *); | 78 | static int kernel_init(void *); |
88 | 79 | ||
89 | extern void init_IRQ(void); | 80 | extern void init_IRQ(void); |
@@ -540,15 +531,6 @@ void __init __weak thread_info_cache_init(void) | |||
540 | { | 531 | { |
541 | } | 532 | } |
542 | 533 | ||
543 | void __init __weak arch_early_irq_init(void) | ||
544 | { | ||
545 | } | ||
546 | |||
547 | void __init __weak early_irq_init(void) | ||
548 | { | ||
549 | arch_early_irq_init(); | ||
550 | } | ||
551 | |||
552 | asmlinkage void __init start_kernel(void) | 534 | asmlinkage void __init start_kernel(void) |
553 | { | 535 | { |
554 | char * command_line; | 536 | char * command_line; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index bda9cb924276..eb2bfefa6dcc 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -32,7 +32,6 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/cpu.h> | 34 | #include <linux/cpu.h> |
35 | #include <linux/irq.h> | ||
36 | #include <linux/module.h> | 35 | #include <linux/module.h> |
37 | #include <linux/percpu.h> | 36 | #include <linux/percpu.h> |
38 | #include <linux/hrtimer.h> | 37 | #include <linux/hrtimer.h> |
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index 650ce4102a63..cc0f7321b8ce 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c | |||
@@ -40,9 +40,6 @@ unsigned long probe_irq_on(void) | |||
40 | * flush such a longstanding irq before considering it as spurious. | 40 | * flush such a longstanding irq before considering it as spurious. |
41 | */ | 41 | */ |
42 | for_each_irq_desc_reverse(i, desc) { | 42 | for_each_irq_desc_reverse(i, desc) { |
43 | if (!desc) | ||
44 | continue; | ||
45 | |||
46 | spin_lock_irq(&desc->lock); | 43 | spin_lock_irq(&desc->lock); |
47 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 44 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
48 | /* | 45 | /* |
@@ -71,9 +68,6 @@ unsigned long probe_irq_on(void) | |||
71 | * happened in the previous stage, it may have masked itself) | 68 | * happened in the previous stage, it may have masked itself) |
72 | */ | 69 | */ |
73 | for_each_irq_desc_reverse(i, desc) { | 70 | for_each_irq_desc_reverse(i, desc) { |
74 | if (!desc) | ||
75 | continue; | ||
76 | |||
77 | spin_lock_irq(&desc->lock); | 71 | spin_lock_irq(&desc->lock); |
78 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 72 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
79 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; | 73 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; |
@@ -92,9 +86,6 @@ unsigned long probe_irq_on(void) | |||
92 | * Now filter out any obviously spurious interrupts | 86 | * Now filter out any obviously spurious interrupts |
93 | */ | 87 | */ |
94 | for_each_irq_desc(i, desc) { | 88 | for_each_irq_desc(i, desc) { |
95 | if (!desc) | ||
96 | continue; | ||
97 | |||
98 | spin_lock_irq(&desc->lock); | 89 | spin_lock_irq(&desc->lock); |
99 | status = desc->status; | 90 | status = desc->status; |
100 | 91 | ||
@@ -133,9 +124,6 @@ unsigned int probe_irq_mask(unsigned long val) | |||
133 | int i; | 124 | int i; |
134 | 125 | ||
135 | for_each_irq_desc(i, desc) { | 126 | for_each_irq_desc(i, desc) { |
136 | if (!desc) | ||
137 | continue; | ||
138 | |||
139 | spin_lock_irq(&desc->lock); | 127 | spin_lock_irq(&desc->lock); |
140 | status = desc->status; | 128 | status = desc->status; |
141 | 129 | ||
@@ -178,9 +166,6 @@ int probe_irq_off(unsigned long val) | |||
178 | unsigned int status; | 166 | unsigned int status; |
179 | 167 | ||
180 | for_each_irq_desc(i, desc) { | 168 | for_each_irq_desc(i, desc) { |
181 | if (!desc) | ||
182 | continue; | ||
183 | |||
184 | spin_lock_irq(&desc->lock); | 169 | spin_lock_irq(&desc->lock); |
185 | status = desc->status; | 170 | status = desc->status; |
186 | 171 | ||
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 6492400cb50d..c20db0be9173 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -56,10 +56,6 @@ void handle_bad_irq(unsigned int irq, struct irq_desc *desc) | |||
56 | int nr_irqs = NR_IRQS; | 56 | int nr_irqs = NR_IRQS; |
57 | EXPORT_SYMBOL_GPL(nr_irqs); | 57 | EXPORT_SYMBOL_GPL(nr_irqs); |
58 | 58 | ||
59 | void __init __attribute__((weak)) arch_early_irq_init(void) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | #ifdef CONFIG_SPARSE_IRQ | 59 | #ifdef CONFIG_SPARSE_IRQ |
64 | static struct irq_desc irq_desc_init = { | 60 | static struct irq_desc irq_desc_init = { |
65 | .irq = -1, | 61 | .irq = -1, |
@@ -90,13 +86,11 @@ void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) | |||
90 | desc->kstat_irqs = (unsigned int *)ptr; | 86 | desc->kstat_irqs = (unsigned int *)ptr; |
91 | } | 87 | } |
92 | 88 | ||
93 | void __attribute__((weak)) arch_init_chip_data(struct irq_desc *desc, int cpu) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) | 89 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) |
98 | { | 90 | { |
99 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); | 91 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); |
92 | |||
93 | spin_lock_init(&desc->lock); | ||
100 | desc->irq = irq; | 94 | desc->irq = irq; |
101 | #ifdef CONFIG_SMP | 95 | #ifdef CONFIG_SMP |
102 | desc->cpu = cpu; | 96 | desc->cpu = cpu; |
@@ -134,7 +128,7 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm | |||
134 | /* FIXME: use bootmem alloc ...*/ | 128 | /* FIXME: use bootmem alloc ...*/ |
135 | static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS]; | 129 | static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS]; |
136 | 130 | ||
137 | void __init early_irq_init(void) | 131 | int __init early_irq_init(void) |
138 | { | 132 | { |
139 | struct irq_desc *desc; | 133 | struct irq_desc *desc; |
140 | int legacy_count; | 134 | int legacy_count; |
@@ -146,6 +140,7 @@ void __init early_irq_init(void) | |||
146 | for (i = 0; i < legacy_count; i++) { | 140 | for (i = 0; i < legacy_count; i++) { |
147 | desc[i].irq = i; | 141 | desc[i].irq = i; |
148 | desc[i].kstat_irqs = kstat_irqs_legacy[i]; | 142 | desc[i].kstat_irqs = kstat_irqs_legacy[i]; |
143 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | ||
149 | 144 | ||
150 | irq_desc_ptrs[i] = desc + i; | 145 | irq_desc_ptrs[i] = desc + i; |
151 | } | 146 | } |
@@ -153,7 +148,7 @@ void __init early_irq_init(void) | |||
153 | for (i = legacy_count; i < NR_IRQS; i++) | 148 | for (i = legacy_count; i < NR_IRQS; i++) |
154 | irq_desc_ptrs[i] = NULL; | 149 | irq_desc_ptrs[i] = NULL; |
155 | 150 | ||
156 | arch_early_irq_init(); | 151 | return arch_early_irq_init(); |
157 | } | 152 | } |
158 | 153 | ||
159 | struct irq_desc *irq_to_desc(unsigned int irq) | 154 | struct irq_desc *irq_to_desc(unsigned int irq) |
@@ -203,7 +198,7 @@ out_unlock: | |||
203 | return desc; | 198 | return desc; |
204 | } | 199 | } |
205 | 200 | ||
206 | #else | 201 | #else /* !CONFIG_SPARSE_IRQ */ |
207 | 202 | ||
208 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 203 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
209 | [0 ... NR_IRQS-1] = { | 204 | [0 ... NR_IRQS-1] = { |
@@ -218,7 +213,31 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
218 | } | 213 | } |
219 | }; | 214 | }; |
220 | 215 | ||
221 | #endif | 216 | int __init early_irq_init(void) |
217 | { | ||
218 | struct irq_desc *desc; | ||
219 | int count; | ||
220 | int i; | ||
221 | |||
222 | desc = irq_desc; | ||
223 | count = ARRAY_SIZE(irq_desc); | ||
224 | |||
225 | for (i = 0; i < count; i++) | ||
226 | desc[i].irq = i; | ||
227 | |||
228 | return arch_early_irq_init(); | ||
229 | } | ||
230 | |||
231 | struct irq_desc *irq_to_desc(unsigned int irq) | ||
232 | { | ||
233 | return (irq < NR_IRQS) ? irq_desc + irq : NULL; | ||
234 | } | ||
235 | |||
236 | struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) | ||
237 | { | ||
238 | return irq_to_desc(irq); | ||
239 | } | ||
240 | #endif /* !CONFIG_SPARSE_IRQ */ | ||
222 | 241 | ||
223 | /* | 242 | /* |
224 | * What should we do if we get a hw irq event on an illegal vector? | 243 | * What should we do if we get a hw irq event on an illegal vector? |
@@ -428,9 +447,6 @@ void early_init_irq_lock_class(void) | |||
428 | int i; | 447 | int i; |
429 | 448 | ||
430 | for_each_irq_desc(i, desc) { | 449 | for_each_irq_desc(i, desc) { |
431 | if (!desc) | ||
432 | continue; | ||
433 | |||
434 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | 450 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
435 | } | 451 | } |
436 | } | 452 | } |
@@ -439,7 +455,7 @@ void early_init_irq_lock_class(void) | |||
439 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | 455 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) |
440 | { | 456 | { |
441 | struct irq_desc *desc = irq_to_desc(irq); | 457 | struct irq_desc *desc = irq_to_desc(irq); |
442 | return desc->kstat_irqs[cpu]; | 458 | return desc ? desc->kstat_irqs[cpu] : 0; |
443 | } | 459 | } |
444 | #endif | 460 | #endif |
445 | EXPORT_SYMBOL(kstat_irqs_cpu); | 461 | EXPORT_SYMBOL(kstat_irqs_cpu); |
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index 089c3746358a..ecf765c6a77a 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c | |||
@@ -42,6 +42,7 @@ static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, | |||
42 | struct irq_desc *desc, int cpu) | 42 | struct irq_desc *desc, int cpu) |
43 | { | 43 | { |
44 | memcpy(desc, old_desc, sizeof(struct irq_desc)); | 44 | memcpy(desc, old_desc, sizeof(struct irq_desc)); |
45 | spin_lock_init(&desc->lock); | ||
45 | desc->cpu = cpu; | 46 | desc->cpu = cpu; |
46 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | 47 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
47 | init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); | 48 | init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); |
@@ -74,10 +75,8 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, | |||
74 | 75 | ||
75 | node = cpu_to_node(cpu); | 76 | node = cpu_to_node(cpu); |
76 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); | 77 | desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); |
77 | printk(KERN_DEBUG " move irq_desc for %d to cpu %d node %d\n", | ||
78 | irq, cpu, node); | ||
79 | if (!desc) { | 78 | if (!desc) { |
80 | printk(KERN_ERR "can not get new irq_desc for moving\n"); | 79 | printk(KERN_ERR "irq %d: can not get new irq_desc for migration.\n", irq); |
81 | /* still use old one */ | 80 | /* still use old one */ |
82 | desc = old_desc; | 81 | desc = old_desc; |
83 | goto out_unlock; | 82 | goto out_unlock; |
@@ -106,8 +105,6 @@ struct irq_desc *move_irq_desc(struct irq_desc *desc, int cpu) | |||
106 | return desc; | 105 | return desc; |
107 | 106 | ||
108 | old_cpu = desc->cpu; | 107 | old_cpu = desc->cpu; |
109 | printk(KERN_DEBUG | ||
110 | "try to move irq_desc from cpu %d to %d\n", old_cpu, cpu); | ||
111 | if (old_cpu != cpu) { | 108 | if (old_cpu != cpu) { |
112 | node = cpu_to_node(cpu); | 109 | node = cpu_to_node(cpu); |
113 | old_node = cpu_to_node(old_cpu); | 110 | old_node = cpu_to_node(old_cpu); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 3738107531fd..dd364c11e56e 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -91,9 +91,6 @@ static int misrouted_irq(int irq) | |||
91 | int i, ok = 0; | 91 | int i, ok = 0; |
92 | 92 | ||
93 | for_each_irq_desc(i, desc) { | 93 | for_each_irq_desc(i, desc) { |
94 | if (!desc) | ||
95 | continue; | ||
96 | |||
97 | if (!i) | 94 | if (!i) |
98 | continue; | 95 | continue; |
99 | 96 | ||
@@ -115,8 +112,6 @@ static void poll_spurious_irqs(unsigned long dummy) | |||
115 | for_each_irq_desc(i, desc) { | 112 | for_each_irq_desc(i, desc) { |
116 | unsigned int status; | 113 | unsigned int status; |
117 | 114 | ||
118 | if (!desc) | ||
119 | continue; | ||
120 | if (!i) | 115 | if (!i) |
121 | continue; | 116 | continue; |
122 | 117 | ||
diff --git a/kernel/softirq.c b/kernel/softirq.c index 466e75ce271a..670c1eca47ec 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -784,3 +784,23 @@ int on_each_cpu(void (*func) (void *info), void *info, int wait) | |||
784 | } | 784 | } |
785 | EXPORT_SYMBOL(on_each_cpu); | 785 | EXPORT_SYMBOL(on_each_cpu); |
786 | #endif | 786 | #endif |
787 | |||
788 | /* | ||
789 | * [ These __weak aliases are kept in a separate compilation unit, so that | ||
790 | * GCC does not inline them incorrectly. ] | ||
791 | */ | ||
792 | |||
793 | int __init __weak early_irq_init(void) | ||
794 | { | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | int __init __weak arch_early_irq_init(void) | ||
799 | { | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | int __weak arch_init_chip_data(struct irq_desc *desc, int cpu) | ||
804 | { | ||
805 | return 0; | ||
806 | } | ||
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index e4e2caeb9d82..086d5ef098fd 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -371,9 +371,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
371 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 371 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
372 | 372 | ||
373 | line = tty->index; | 373 | line = tty->index; |
374 | if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) { | 374 | if (line >= IRCOMM_TTY_PORTS) |
375 | return -ENODEV; | 375 | return -ENODEV; |
376 | } | ||
377 | 376 | ||
378 | /* Check if instance already exists */ | 377 | /* Check if instance already exists */ |
379 | self = hashbin_lock_find(ircomm_tty, line, NULL); | 378 | self = hashbin_lock_find(ircomm_tty, line, NULL); |
@@ -405,6 +404,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
405 | * Force TTY into raw mode by default which is usually what | 404 | * Force TTY into raw mode by default which is usually what |
406 | * we want for IrCOMM and IrLPT. This way applications will | 405 | * we want for IrCOMM and IrLPT. This way applications will |
407 | * not have to twiddle with printcap etc. | 406 | * not have to twiddle with printcap etc. |
407 | * | ||
408 | * Note this is completely usafe and doesn't work properly | ||
408 | */ | 409 | */ |
409 | tty->termios->c_iflag = 0; | 410 | tty->termios->c_iflag = 0; |
410 | tty->termios->c_oflag = 0; | 411 | tty->termios->c_oflag = 0; |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c6250d0055d2..d1b89820ab4f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -836,7 +836,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
836 | err = mnt_want_write(nd.path.mnt); | 836 | err = mnt_want_write(nd.path.mnt); |
837 | if (err) | 837 | if (err) |
838 | goto out_mknod_dput; | 838 | goto out_mknod_dput; |
839 | err = security_path_mknod(&nd.path, dentry, mode, 0); | ||
840 | if (err) | ||
841 | goto out_mknod_drop_write; | ||
839 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); | 842 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); |
843 | out_mknod_drop_write: | ||
840 | mnt_drop_write(nd.path.mnt); | 844 | mnt_drop_write(nd.path.mnt); |
841 | if (err) | 845 | if (err) |
842 | goto out_mknod_dput; | 846 | goto out_mknod_dput; |
diff --git a/security/Kconfig b/security/Kconfig index d9f47ce7e207..9438535d7fd0 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -81,6 +81,15 @@ config SECURITY_NETWORK_XFRM | |||
81 | IPSec. | 81 | IPSec. |
82 | If you are unsure how to answer this question, answer N. | 82 | If you are unsure how to answer this question, answer N. |
83 | 83 | ||
84 | config SECURITY_PATH | ||
85 | bool "Security hooks for pathname based access control" | ||
86 | depends on SECURITY | ||
87 | help | ||
88 | This enables the security hooks for pathname based access control. | ||
89 | If enabled, a security module can use these hooks to | ||
90 | implement pathname based access controls. | ||
91 | If you are unsure how to answer this question, answer N. | ||
92 | |||
84 | config SECURITY_FILE_CAPABILITIES | 93 | config SECURITY_FILE_CAPABILITIES |
85 | bool "File POSIX Capabilities" | 94 | bool "File POSIX Capabilities" |
86 | default n | 95 | default n |
diff --git a/security/capability.c b/security/capability.c index 2dce66fcb992..c545bd1300b5 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -263,6 +263,53 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid) | |||
263 | *secid = 0; | 263 | *secid = 0; |
264 | } | 264 | } |
265 | 265 | ||
266 | #ifdef CONFIG_SECURITY_PATH | ||
267 | static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
268 | unsigned int dev) | ||
269 | { | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode) | ||
274 | { | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int cap_path_rmdir(struct path *dir, struct dentry *dentry) | ||
279 | { | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int cap_path_unlink(struct path *dir, struct dentry *dentry) | ||
284 | { | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int cap_path_symlink(struct path *dir, struct dentry *dentry, | ||
289 | const char *old_name) | ||
290 | { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int cap_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
295 | struct dentry *new_dentry) | ||
296 | { | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int cap_path_rename(struct path *old_path, struct dentry *old_dentry, | ||
301 | struct path *new_path, struct dentry *new_dentry) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int cap_path_truncate(struct path *path, loff_t length, | ||
307 | unsigned int time_attrs) | ||
308 | { | ||
309 | return 0; | ||
310 | } | ||
311 | #endif | ||
312 | |||
266 | static int cap_file_permission(struct file *file, int mask) | 313 | static int cap_file_permission(struct file *file, int mask) |
267 | { | 314 | { |
268 | return 0; | 315 | return 0; |
@@ -883,6 +930,16 @@ void security_fixup_ops(struct security_operations *ops) | |||
883 | set_to_cap_if_null(ops, inode_setsecurity); | 930 | set_to_cap_if_null(ops, inode_setsecurity); |
884 | set_to_cap_if_null(ops, inode_listsecurity); | 931 | set_to_cap_if_null(ops, inode_listsecurity); |
885 | set_to_cap_if_null(ops, inode_getsecid); | 932 | set_to_cap_if_null(ops, inode_getsecid); |
933 | #ifdef CONFIG_SECURITY_PATH | ||
934 | set_to_cap_if_null(ops, path_mknod); | ||
935 | set_to_cap_if_null(ops, path_mkdir); | ||
936 | set_to_cap_if_null(ops, path_rmdir); | ||
937 | set_to_cap_if_null(ops, path_unlink); | ||
938 | set_to_cap_if_null(ops, path_symlink); | ||
939 | set_to_cap_if_null(ops, path_link); | ||
940 | set_to_cap_if_null(ops, path_rename); | ||
941 | set_to_cap_if_null(ops, path_truncate); | ||
942 | #endif | ||
886 | set_to_cap_if_null(ops, file_permission); | 943 | set_to_cap_if_null(ops, file_permission); |
887 | set_to_cap_if_null(ops, file_alloc_security); | 944 | set_to_cap_if_null(ops, file_alloc_security); |
888 | set_to_cap_if_null(ops, file_free_security); | 945 | set_to_cap_if_null(ops, file_free_security); |
diff --git a/security/security.c b/security/security.c index d85dbb37c972..678d4d07b852 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -355,6 +355,72 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, | |||
355 | } | 355 | } |
356 | EXPORT_SYMBOL(security_inode_init_security); | 356 | EXPORT_SYMBOL(security_inode_init_security); |
357 | 357 | ||
358 | #ifdef CONFIG_SECURITY_PATH | ||
359 | int security_path_mknod(struct path *path, struct dentry *dentry, int mode, | ||
360 | unsigned int dev) | ||
361 | { | ||
362 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
363 | return 0; | ||
364 | return security_ops->path_mknod(path, dentry, mode, dev); | ||
365 | } | ||
366 | EXPORT_SYMBOL(security_path_mknod); | ||
367 | |||
368 | int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) | ||
369 | { | ||
370 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
371 | return 0; | ||
372 | return security_ops->path_mkdir(path, dentry, mode); | ||
373 | } | ||
374 | |||
375 | int security_path_rmdir(struct path *path, struct dentry *dentry) | ||
376 | { | ||
377 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
378 | return 0; | ||
379 | return security_ops->path_rmdir(path, dentry); | ||
380 | } | ||
381 | |||
382 | int security_path_unlink(struct path *path, struct dentry *dentry) | ||
383 | { | ||
384 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
385 | return 0; | ||
386 | return security_ops->path_unlink(path, dentry); | ||
387 | } | ||
388 | |||
389 | int security_path_symlink(struct path *path, struct dentry *dentry, | ||
390 | const char *old_name) | ||
391 | { | ||
392 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
393 | return 0; | ||
394 | return security_ops->path_symlink(path, dentry, old_name); | ||
395 | } | ||
396 | |||
397 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
398 | struct dentry *new_dentry) | ||
399 | { | ||
400 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) | ||
401 | return 0; | ||
402 | return security_ops->path_link(old_dentry, new_dir, new_dentry); | ||
403 | } | ||
404 | |||
405 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
406 | struct path *new_dir, struct dentry *new_dentry) | ||
407 | { | ||
408 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | ||
409 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | ||
410 | return 0; | ||
411 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | ||
412 | new_dentry); | ||
413 | } | ||
414 | |||
415 | int security_path_truncate(struct path *path, loff_t length, | ||
416 | unsigned int time_attrs) | ||
417 | { | ||
418 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
419 | return 0; | ||
420 | return security_ops->path_truncate(path, length, time_attrs); | ||
421 | } | ||
422 | #endif | ||
423 | |||
358 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) | 424 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) |
359 | { | 425 | { |
360 | if (unlikely(IS_PRIVATE(dir))) | 426 | if (unlikely(IS_PRIVATE(dir))) |