diff options
348 files changed, 16213 insertions, 8990 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 08687e45e19d..1a7f53068ec2 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ | |||
11 | procfs-guide.xml writing_usb_driver.xml \ | 11 | procfs-guide.xml writing_usb_driver.xml \ |
12 | kernel-api.xml filesystems.xml lsm.xml usb.xml \ | 12 | kernel-api.xml filesystems.xml lsm.xml usb.xml \ |
13 | gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ | 13 | gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ |
14 | genericirq.xml | 14 | genericirq.xml s390-drivers.xml |
15 | 15 | ||
16 | ### | 16 | ### |
17 | # The build process is as follows (targets): | 17 | # The build process is as follows (targets): |
diff --git a/Documentation/DocBook/s390-drivers.tmpl b/Documentation/DocBook/s390-drivers.tmpl new file mode 100644 index 000000000000..254e769282a4 --- /dev/null +++ b/Documentation/DocBook/s390-drivers.tmpl | |||
@@ -0,0 +1,149 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" | ||
3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> | ||
4 | |||
5 | <book id="s390drivers"> | ||
6 | <bookinfo> | ||
7 | <title>Writing s390 channel device drivers</title> | ||
8 | |||
9 | <authorgroup> | ||
10 | <author> | ||
11 | <firstname>Cornelia</firstname> | ||
12 | <surname>Huck</surname> | ||
13 | <affiliation> | ||
14 | <address> | ||
15 | <email>cornelia.huck@de.ibm.com</email> | ||
16 | </address> | ||
17 | </affiliation> | ||
18 | </author> | ||
19 | </authorgroup> | ||
20 | |||
21 | <copyright> | ||
22 | <year>2007</year> | ||
23 | <holder>IBM Corp.</holder> | ||
24 | </copyright> | ||
25 | |||
26 | <legalnotice> | ||
27 | <para> | ||
28 | This documentation is free software; you can redistribute | ||
29 | it and/or modify it under the terms of the GNU General Public | ||
30 | License as published by the Free Software Foundation; either | ||
31 | version 2 of the License, or (at your option) any later | ||
32 | version. | ||
33 | </para> | ||
34 | |||
35 | <para> | ||
36 | This program is distributed in the hope that it will be | ||
37 | useful, but WITHOUT ANY WARRANTY; without even the implied | ||
38 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
39 | See the GNU General Public License for more details. | ||
40 | </para> | ||
41 | |||
42 | <para> | ||
43 | You should have received a copy of the GNU General Public | ||
44 | License along with this program; if not, write to the Free | ||
45 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
46 | MA 02111-1307 USA | ||
47 | </para> | ||
48 | |||
49 | <para> | ||
50 | For more details see the file COPYING in the source | ||
51 | distribution of Linux. | ||
52 | </para> | ||
53 | </legalnotice> | ||
54 | </bookinfo> | ||
55 | |||
56 | <toc></toc> | ||
57 | |||
58 | <chapter id="intro"> | ||
59 | <title>Introduction</title> | ||
60 | <para> | ||
61 | This document describes the interfaces available for device drivers that | ||
62 | drive s390 based channel attached devices. This includes interfaces for | ||
63 | interaction with the hardware and interfaces for interacting with the | ||
64 | common driver core. Those interfaces are provided by the s390 common I/O | ||
65 | layer. | ||
66 | </para> | ||
67 | <para> | ||
68 | The document assumes a familarity with the technical terms associated | ||
69 | with the s390 channel I/O architecture. For a description of this | ||
70 | architecture, please refer to the "z/Architecture: Principles of | ||
71 | Operation", IBM publication no. SA22-7832. | ||
72 | </para> | ||
73 | <para> | ||
74 | While most I/O devices on a s390 system are typically driven through the | ||
75 | channel I/O mechanism described here, there are various other methods | ||
76 | (like the diag interface). These are out of the scope of this document. | ||
77 | </para> | ||
78 | <para> | ||
79 | Some additional information can also be found in the kernel source | ||
80 | under Documentation/s390/driver-model.txt. | ||
81 | </para> | ||
82 | </chapter> | ||
83 | <chapter id="ccw"> | ||
84 | <title>The ccw bus</title> | ||
85 | <para> | ||
86 | The ccw bus typically contains the majority of devices available to | ||
87 | a s390 system. Named after the channel command word (ccw), the basic | ||
88 | command structure used to address its devices, the ccw bus contains | ||
89 | so-called channel attached devices. They are addressed via subchannels, | ||
90 | visible on the css bus. A device driver, however, will never interact | ||
91 | with the subchannel directly, but only via the device on the ccw bus, | ||
92 | the ccw device. | ||
93 | </para> | ||
94 | <sect1 id="channelIO"> | ||
95 | <title>I/O functions for channel-attached devices</title> | ||
96 | <para> | ||
97 | Some hardware structures have been translated into C structures for use | ||
98 | by the common I/O layer and device drivers. For more information on | ||
99 | the hardware structures represented here, please consult the Principles | ||
100 | of Operation. | ||
101 | </para> | ||
102 | !Iinclude/asm-s390/cio.h | ||
103 | </sect1> | ||
104 | <sect1 id="ccwdev"> | ||
105 | <title>ccw devices</title> | ||
106 | <para> | ||
107 | Devices that want to initiate channel I/O need to attach to the ccw bus. | ||
108 | Interaction with the driver core is done via the common I/O layer, which | ||
109 | provides the abstractions of ccw devices and ccw device drivers. | ||
110 | </para> | ||
111 | <para> | ||
112 | The functions that initiate or terminate channel I/O all act upon a | ||
113 | ccw device structure. Device drivers must not bypass those functions | ||
114 | or strange side effects may happen. | ||
115 | </para> | ||
116 | !Iinclude/asm-s390/ccwdev.h | ||
117 | !Edrivers/s390/cio/device.c | ||
118 | !Edrivers/s390/cio/device_ops.c | ||
119 | </sect1> | ||
120 | <sect1 id="cmf"> | ||
121 | <title>The channel-measurement facility</title> | ||
122 | <para> | ||
123 | The channel-measurement facility provides a means to collect | ||
124 | measurement data which is made available by the channel subsystem | ||
125 | for each channel attached device. | ||
126 | </para> | ||
127 | !Iinclude/asm-s390/cmb.h | ||
128 | !Edrivers/s390/cio/cmf.c | ||
129 | </sect1> | ||
130 | </chapter> | ||
131 | |||
132 | <chapter id="ccwgroup"> | ||
133 | <title>The ccwgroup bus</title> | ||
134 | <para> | ||
135 | The ccwgroup bus only contains artificial devices, created by the user. | ||
136 | Many networking devices (e.g. qeth) are in fact composed of several | ||
137 | ccw devices (like read, write and data channel for qeth). The | ||
138 | ccwgroup bus provides a mechanism to create a meta-device which | ||
139 | contains those ccw devices as slave devices and can be associated | ||
140 | with the netdevice. | ||
141 | </para> | ||
142 | <sect1 id="ccwgroupdevices"> | ||
143 | <title>ccw group devices</title> | ||
144 | !Iinclude/asm-s390/ccwgroup.h | ||
145 | !Edrivers/s390/cio/ccwgroup.c | ||
146 | </sect1> | ||
147 | </chapter> | ||
148 | |||
149 | </book> | ||
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 8ee10ec88293..e79ee2db183a 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt | |||
@@ -407,7 +407,7 @@ raiddev /dev/md0 | |||
407 | device /dev/hda5 | 407 | device /dev/hda5 |
408 | raid-disk 0 | 408 | raid-disk 0 |
409 | device /dev/hdb1 | 409 | device /dev/hdb1 |
410 | raid-disl 1 | 410 | raid-disk 1 |
411 | 411 | ||
412 | For linear raid, just change the raid-level above to "raid-level linear", for | 412 | For linear raid, just change the raid-level above to "raid-level linear", for |
413 | mirrors, change it to "raid-level 1", and for stripe sets with parity, change | 413 | mirrors, change it to "raid-level 1", and for stripe sets with parity, change |
@@ -457,6 +457,8 @@ ChangeLog | |||
457 | 457 | ||
458 | Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. | 458 | Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. |
459 | 459 | ||
460 | 2.1.29: | ||
461 | - Fix a deadlock when mounting read-write. | ||
460 | 2.1.28: | 462 | 2.1.28: |
461 | - Fix a deadlock. | 463 | - Fix a deadlock. |
462 | 2.1.27: | 464 | 2.1.27: |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index bdddd3cd46dd..912c57c2334e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1009,6 +1009,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1009 | meye.*= [HW] Set MotionEye Camera parameters | 1009 | meye.*= [HW] Set MotionEye Camera parameters |
1010 | See Documentation/video4linux/meye.txt. | 1010 | See Documentation/video4linux/meye.txt. |
1011 | 1011 | ||
1012 | mfgpt_irq= [IA-32] Specify the IRQ to use for the | ||
1013 | Multi-Function General Purpose Timers on AMD Geode | ||
1014 | platforms. | ||
1015 | |||
1012 | mga= [HW,DRM] | 1016 | mga= [HW,DRM] |
1013 | 1017 | ||
1014 | mousedev.tap_time= | 1018 | mousedev.tap_time= |
@@ -1160,6 +1164,9 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1160 | 1164 | ||
1161 | nomce [X86-32] Machine Check Exception | 1165 | nomce [X86-32] Machine Check Exception |
1162 | 1166 | ||
1167 | nomfgpt [X86-32] Disable Multi-Function General Purpose | ||
1168 | Timer usage (for AMD Geode machines). | ||
1169 | |||
1163 | noreplace-paravirt [X86-32,PV_OPS] Don't patch paravirt_ops | 1170 | noreplace-paravirt [X86-32,PV_OPS] Don't patch paravirt_ops |
1164 | 1171 | ||
1165 | noreplace-smp [X86-32,SMP] Don't replace SMP instructions | 1172 | noreplace-smp [X86-32,SMP] Don't replace SMP instructions |
diff --git a/Documentation/s390/00-INDEX b/Documentation/s390/00-INDEX new file mode 100644 index 000000000000..3a2b96302ecc --- /dev/null +++ b/Documentation/s390/00-INDEX | |||
@@ -0,0 +1,26 @@ | |||
1 | 00-INDEX | ||
2 | - this file. | ||
3 | 3270.ChangeLog | ||
4 | - ChangeLog for the UTS Global 3270-support patch (outdated). | ||
5 | 3270.txt | ||
6 | - how to use the IBM 3270 display system support. | ||
7 | cds.txt | ||
8 | - s390 common device support (common I/O layer). | ||
9 | CommonIO | ||
10 | - common I/O layer command line parameters, procfs and debugfs entries | ||
11 | config3270.sh | ||
12 | - example configuration for 3270 devices. | ||
13 | DASD | ||
14 | - information on the DASD disk device driver. | ||
15 | Debugging390.txt | ||
16 | - hints for debugging on s390 systems. | ||
17 | driver-model.txt | ||
18 | - information on s390 devices and the driver model. | ||
19 | monreader.txt | ||
20 | - information on accessing the z/VM monitor stream from Linux. | ||
21 | s390dbf.txt | ||
22 | - information on using the s390 debug feature. | ||
23 | TAPE | ||
24 | - information on the driver for channel-attached tapes. | ||
25 | zfcpdump | ||
26 | - information on the s390 SCSI dump tool. | ||
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO index 22f82f21bc60..86320aa3fb0b 100644 --- a/Documentation/s390/CommonIO +++ b/Documentation/s390/CommonIO | |||
@@ -1,5 +1,5 @@ | |||
1 | S/390 common I/O-Layer - command line parameters and /proc entries | 1 | S/390 common I/O-Layer - command line parameters, procfs and debugfs entries |
2 | ================================================================== | 2 | ============================================================================ |
3 | 3 | ||
4 | Command line parameters | 4 | Command line parameters |
5 | ----------------------- | 5 | ----------------------- |
@@ -7,9 +7,9 @@ Command line parameters | |||
7 | * cio_msg = yes | no | 7 | * cio_msg = yes | no |
8 | 8 | ||
9 | Determines whether information on found devices and sensed device | 9 | Determines whether information on found devices and sensed device |
10 | characteristics should be shown during startup, i. e. messages of the types | 10 | characteristics should be shown during startup or when new devices are |
11 | "Detected device 0.0.4711 on subchannel 0.0.0042" and "SenseID: Device | 11 | found, i. e. messages of the types "Detected device 0.0.4711 on subchannel |
12 | 0.0.4711 reports: ...". | 12 | 0.0.0042" and "SenseID: Device 0.0.4711 reports: ...". |
13 | 13 | ||
14 | Default is off. | 14 | Default is off. |
15 | 15 | ||
@@ -26,8 +26,10 @@ Command line parameters | |||
26 | An ignored device can be un-ignored later; see the "/proc entries"-section for | 26 | An ignored device can be un-ignored later; see the "/proc entries"-section for |
27 | details. | 27 | details. |
28 | 28 | ||
29 | The devices must be given either as bus ids (0.0.abcd) or as hexadecimal | 29 | The devices must be given either as bus ids (0.x.abcd) or as hexadecimal |
30 | device numbers (0xabcd or abcd, for 2.4 backward compatibility). | 30 | device numbers (0xabcd or abcd, for 2.4 backward compatibility). If you |
31 | give a device number 0xabcd, it will be interpreted as 0.0.abcd. | ||
32 | |||
31 | You can use the 'all' keyword to ignore all devices. | 33 | You can use the 'all' keyword to ignore all devices. |
32 | The '!' operator will cause the I/O-layer to _not_ ignore a device. | 34 | The '!' operator will cause the I/O-layer to _not_ ignore a device. |
33 | The command line is parsed from left to right. | 35 | The command line is parsed from left to right. |
@@ -81,31 +83,36 @@ Command line parameters | |||
81 | will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored | 83 | will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored |
82 | devices. | 84 | devices. |
83 | 85 | ||
84 | The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward | 86 | The devices can be specified either by bus id (0.x.abcd) or, for 2.4 backward |
85 | compatibility, by the device number in hexadecimal (0xabcd or abcd). | 87 | compatibility, by the device number in hexadecimal (0xabcd or abcd). Device |
88 | numbers given as 0xabcd will be interpreted as 0.0.abcd. | ||
89 | |||
90 | * For some of the information present in the /proc filesystem in 2.4 (namely, | ||
91 | /proc/subchannels and /proc/chpids), see driver-model.txt. | ||
92 | Information formerly in /proc/irq_count is now in /proc/interrupts. | ||
93 | |||
86 | 94 | ||
95 | debugfs entries | ||
96 | --------------- | ||
87 | 97 | ||
88 | * /proc/s390dbf/cio_*/ (S/390 debug feature) | 98 | * /sys/kernel/debug/s390dbf/cio_*/ (S/390 debug feature) |
89 | 99 | ||
90 | Some views generated by the debug feature to hold various debug outputs. | 100 | Some views generated by the debug feature to hold various debug outputs. |
91 | 101 | ||
92 | - /proc/s390dbf/cio_crw/sprintf | 102 | - /sys/kernel/debug/s390dbf/cio_crw/sprintf |
93 | Messages from the processing of pending channel report words (machine check | 103 | Messages from the processing of pending channel report words (machine check |
94 | handling), which will also show when CONFIG_DEBUG_CRW is defined. | 104 | handling). |
95 | 105 | ||
96 | - /proc/s390dbf/cio_msg/sprintf | 106 | - /sys/kernel/debug/s390dbf/cio_msg/sprintf |
97 | Various debug messages from the common I/O-layer; generally, messages which | 107 | Various debug messages from the common I/O-layer, including messages |
98 | will also show when CONFIG_DEBUG_IO is defined. | 108 | printed when cio_msg=yes. |
99 | 109 | ||
100 | - /proc/s390dbf/cio_trace/hex_ascii | 110 | - /sys/kernel/debug/s390dbf/cio_trace/hex_ascii |
101 | Logs the calling of functions in the common I/O-layer and, if applicable, | 111 | Logs the calling of functions in the common I/O-layer and, if applicable, |
102 | which subchannel they were called for, as well as dumps of some data | 112 | which subchannel they were called for, as well as dumps of some data |
103 | structures (like irb in an error case). | 113 | structures (like irb in an error case). |
104 | 114 | ||
105 | The level of logging can be changed to be more or less verbose by piping to | 115 | The level of logging can be changed to be more or less verbose by piping to |
106 | /proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on | 116 | /sys/kernel/debug/s390dbf/cio_*/level a number between 0 and 6; see the |
107 | the S/390 debug feature (Documentation/s390/s390dbf.txt) for details. | 117 | documentation on the S/390 debug feature (Documentation/s390/s390dbf.txt) |
108 | 118 | for details. | |
109 | * For some of the information present in the /proc filesystem in 2.4 (namely, | ||
110 | /proc/subchannels and /proc/chpids), see driver-model.txt. | ||
111 | Information formerly in /proc/irq_count is now in /proc/interrupts. | ||
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt index 58919d6a593a..3081927cc2d6 100644 --- a/Documentation/s390/cds.txt +++ b/Documentation/s390/cds.txt | |||
@@ -286,10 +286,10 @@ first: | |||
286 | timeout value | 286 | timeout value |
287 | -EIO: the common I/O layer terminated the request due to an error state | 287 | -EIO: the common I/O layer terminated the request due to an error state |
288 | 288 | ||
289 | If the concurrent sense flag in the extended status word in the irb is set, the | 289 | If the concurrent sense flag in the extended status word (esw) in the irb is |
290 | field irb->scsw.count describes the number of device specific sense bytes | 290 | set, the field erw.scnt in the esw describes the number of device specific |
291 | available in the extended control word irb->scsw.ecw[0]. No device sensing by | 291 | sense bytes available in the extended control word irb->scsw.ecw[]. No device |
292 | the device driver itself is required. | 292 | sensing by the device driver itself is required. |
293 | 293 | ||
294 | The device interrupt handler can use the following definitions to investigate | 294 | The device interrupt handler can use the following definitions to investigate |
295 | the primary unit check source coded in sense byte 0 : | 295 | the primary unit check source coded in sense byte 0 : |
diff --git a/Documentation/usb/authorization.txt b/Documentation/usb/authorization.txt new file mode 100644 index 000000000000..2af400609498 --- /dev/null +++ b/Documentation/usb/authorization.txt | |||
@@ -0,0 +1,92 @@ | |||
1 | |||
2 | Authorizing (or not) your USB devices to connect to the system | ||
3 | |||
4 | (C) 2007 Inaky Perez-Gonzalez <inaky@linux.intel.com> Intel Corporation | ||
5 | |||
6 | This feature allows you to control if a USB device can be used (or | ||
7 | not) in a system. This feature will allow you to implement a lock-down | ||
8 | of USB devices, fully controlled by user space. | ||
9 | |||
10 | As of now, when a USB device is connected it is configured and | ||
11 | it's interfaces inmediately made available to the users. With this | ||
12 | modification, only if root authorizes the device to be configured will | ||
13 | then it be possible to use it. | ||
14 | |||
15 | Usage: | ||
16 | |||
17 | Authorize a device to connect: | ||
18 | |||
19 | $ echo 1 > /sys/usb/devices/DEVICE/authorized | ||
20 | |||
21 | Deauthorize a device: | ||
22 | |||
23 | $ echo 0 > /sys/usb/devices/DEVICE/authorized | ||
24 | |||
25 | Set new devices connected to hostX to be deauthorized by default (ie: | ||
26 | lock down): | ||
27 | |||
28 | $ echo 0 > /sys/bus/devices/usbX/authorized_default | ||
29 | |||
30 | Remove the lock down: | ||
31 | |||
32 | $ echo 1 > /sys/bus/devices/usbX/authorized_default | ||
33 | |||
34 | By default, Wired USB devices are authorized by default to | ||
35 | connect. Wireless USB hosts deauthorize by default all new connected | ||
36 | devices (this is so because we need to do an authentication phase | ||
37 | before authorizing). | ||
38 | |||
39 | |||
40 | Example system lockdown (lame) | ||
41 | ----------------------- | ||
42 | |||
43 | Imagine you want to implement a lockdown so only devices of type XYZ | ||
44 | can be connected (for example, it is a kiosk machine with a visible | ||
45 | USB port): | ||
46 | |||
47 | boot up | ||
48 | rc.local -> | ||
49 | |||
50 | for host in /sys/bus/devices/usb* | ||
51 | do | ||
52 | echo 0 > $host/authorized_default | ||
53 | done | ||
54 | |||
55 | Hookup an script to udev, for new USB devices | ||
56 | |||
57 | if device_is_my_type $DEV | ||
58 | then | ||
59 | echo 1 > $device_path/authorized | ||
60 | done | ||
61 | |||
62 | |||
63 | Now, device_is_my_type() is where the juice for a lockdown is. Just | ||
64 | checking if the class, type and protocol match something is the worse | ||
65 | security verification you can make (or the best, for someone willing | ||
66 | to break it). If you need something secure, use crypto and Certificate | ||
67 | Authentication or stuff like that. Something simple for an storage key | ||
68 | could be: | ||
69 | |||
70 | function device_is_my_type() | ||
71 | { | ||
72 | echo 1 > authorized # temporarily authorize it | ||
73 | # FIXME: make sure none can mount it | ||
74 | mount DEVICENODE /mntpoint | ||
75 | sum=$(md5sum /mntpoint/.signature) | ||
76 | if [ $sum = $(cat /etc/lockdown/keysum) ] | ||
77 | then | ||
78 | echo "We are good, connected" | ||
79 | umount /mntpoint | ||
80 | # Other stuff so others can use it | ||
81 | else | ||
82 | echo 0 > authorized | ||
83 | fi | ||
84 | } | ||
85 | |||
86 | |||
87 | Of course, this is lame, you'd want to do a real certificate | ||
88 | verification stuff with PKI, so you don't depend on a shared secret, | ||
89 | etc, but you get the idea. Anybody with access to a device gadget kit | ||
90 | can fake descriptors and device info. Don't trust that. You are | ||
91 | welcome. | ||
92 | |||
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt new file mode 100644 index 000000000000..97842deec471 --- /dev/null +++ b/Documentation/usb/power-management.txt | |||
@@ -0,0 +1,517 @@ | |||
1 | Power Management for USB | ||
2 | |||
3 | Alan Stern <stern@rowland.harvard.edu> | ||
4 | |||
5 | October 5, 2007 | ||
6 | |||
7 | |||
8 | |||
9 | What is Power Management? | ||
10 | ------------------------- | ||
11 | |||
12 | Power Management (PM) is the practice of saving energy by suspending | ||
13 | parts of a computer system when they aren't being used. While a | ||
14 | component is "suspended" it is in a nonfunctional low-power state; it | ||
15 | might even be turned off completely. A suspended component can be | ||
16 | "resumed" (returned to a functional full-power state) when the kernel | ||
17 | needs to use it. (There also are forms of PM in which components are | ||
18 | placed in a less functional but still usable state instead of being | ||
19 | suspended; an example would be reducing the CPU's clock rate. This | ||
20 | document will not discuss those other forms.) | ||
21 | |||
22 | When the parts being suspended include the CPU and most of the rest of | ||
23 | the system, we speak of it as a "system suspend". When a particular | ||
24 | device is turned off while the system as a whole remains running, we | ||
25 | call it a "dynamic suspend" (also known as a "runtime suspend" or | ||
26 | "selective suspend"). This document concentrates mostly on how | ||
27 | dynamic PM is implemented in the USB subsystem, although system PM is | ||
28 | covered to some extent (see Documentation/power/*.txt for more | ||
29 | information about system PM). | ||
30 | |||
31 | Note: Dynamic PM support for USB is present only if the kernel was | ||
32 | built with CONFIG_USB_SUSPEND enabled. System PM support is present | ||
33 | only if the kernel was built with CONFIG_SUSPEND or CONFIG_HIBERNATION | ||
34 | enabled. | ||
35 | |||
36 | |||
37 | What is Remote Wakeup? | ||
38 | ---------------------- | ||
39 | |||
40 | When a device has been suspended, it generally doesn't resume until | ||
41 | the computer tells it to. Likewise, if the entire computer has been | ||
42 | suspended, it generally doesn't resume until the user tells it to, say | ||
43 | by pressing a power button or opening the cover. | ||
44 | |||
45 | However some devices have the capability of resuming by themselves, or | ||
46 | asking the kernel to resume them, or even telling the entire computer | ||
47 | to resume. This capability goes by several names such as "Wake On | ||
48 | LAN"; we will refer to it generically as "remote wakeup". When a | ||
49 | device is enabled for remote wakeup and it is suspended, it may resume | ||
50 | itself (or send a request to be resumed) in response to some external | ||
51 | event. Examples include a suspended keyboard resuming when a key is | ||
52 | pressed, or a suspended USB hub resuming when a device is plugged in. | ||
53 | |||
54 | |||
55 | When is a USB device idle? | ||
56 | -------------------------- | ||
57 | |||
58 | A device is idle whenever the kernel thinks it's not busy doing | ||
59 | anything important and thus is a candidate for being suspended. The | ||
60 | exact definition depends on the device's driver; drivers are allowed | ||
61 | to declare that a device isn't idle even when there's no actual | ||
62 | communication taking place. (For example, a hub isn't considered idle | ||
63 | unless all the devices plugged into that hub are already suspended.) | ||
64 | In addition, a device isn't considered idle so long as a program keeps | ||
65 | its usbfs file open, whether or not any I/O is going on. | ||
66 | |||
67 | If a USB device has no driver, its usbfs file isn't open, and it isn't | ||
68 | being accessed through sysfs, then it definitely is idle. | ||
69 | |||
70 | |||
71 | Forms of dynamic PM | ||
72 | ------------------- | ||
73 | |||
74 | Dynamic suspends can occur in two ways: manual and automatic. | ||
75 | "Manual" means that the user has told the kernel to suspend a device, | ||
76 | whereas "automatic" means that the kernel has decided all by itself to | ||
77 | suspend a device. Automatic suspend is called "autosuspend" for | ||
78 | short. In general, a device won't be autosuspended unless it has been | ||
79 | idle for some minimum period of time, the so-called idle-delay time. | ||
80 | |||
81 | Of course, nothing the kernel does on its own initiative should | ||
82 | prevent the computer or its devices from working properly. If a | ||
83 | device has been autosuspended and a program tries to use it, the | ||
84 | kernel will automatically resume the device (autoresume). For the | ||
85 | same reason, an autosuspended device will usually have remote wakeup | ||
86 | enabled, if the device supports remote wakeup. | ||
87 | |||
88 | It is worth mentioning that many USB drivers don't support | ||
89 | autosuspend. In fact, at the time of this writing (Linux 2.6.23) the | ||
90 | only drivers which do support it are the hub driver, kaweth, asix, | ||
91 | usblp, usblcd, and usb-skeleton (which doesn't count). If a | ||
92 | non-supporting driver is bound to a device, the device won't be | ||
93 | autosuspended. In effect, the kernel pretends the device is never | ||
94 | idle. | ||
95 | |||
96 | We can categorize power management events in two broad classes: | ||
97 | external and internal. External events are those triggered by some | ||
98 | agent outside the USB stack: system suspend/resume (triggered by | ||
99 | userspace), manual dynamic suspend/resume (also triggered by | ||
100 | userspace), and remote wakeup (triggered by the device). Internal | ||
101 | events are those triggered within the USB stack: autosuspend and | ||
102 | autoresume. | ||
103 | |||
104 | |||
105 | The user interface for dynamic PM | ||
106 | --------------------------------- | ||
107 | |||
108 | The user interface for controlling dynamic PM is located in the power/ | ||
109 | subdirectory of each USB device's sysfs directory, that is, in | ||
110 | /sys/bus/usb/devices/.../power/ where "..." is the device's ID. The | ||
111 | relevant attribute files are: wakeup, level, and autosuspend. | ||
112 | |||
113 | power/wakeup | ||
114 | |||
115 | This file is empty if the device does not support | ||
116 | remote wakeup. Otherwise the file contains either the | ||
117 | word "enabled" or the word "disabled", and you can | ||
118 | write those words to the file. The setting determines | ||
119 | whether or not remote wakeup will be enabled when the | ||
120 | device is next suspended. (If the setting is changed | ||
121 | while the device is suspended, the change won't take | ||
122 | effect until the following suspend.) | ||
123 | |||
124 | power/level | ||
125 | |||
126 | This file contains one of three words: "on", "auto", | ||
127 | or "suspend". You can write those words to the file | ||
128 | to change the device's setting. | ||
129 | |||
130 | "on" means that the device should be resumed and | ||
131 | autosuspend is not allowed. (Of course, system | ||
132 | suspends are still allowed.) | ||
133 | |||
134 | "auto" is the normal state in which the kernel is | ||
135 | allowed to autosuspend and autoresume the device. | ||
136 | |||
137 | "suspend" means that the device should remain | ||
138 | suspended, and autoresume is not allowed. (But remote | ||
139 | wakeup may still be allowed, since it is controlled | ||
140 | separately by the power/wakeup attribute.) | ||
141 | |||
142 | power/autosuspend | ||
143 | |||
144 | This file contains an integer value, which is the | ||
145 | number of seconds the device should remain idle before | ||
146 | the kernel will autosuspend it (the idle-delay time). | ||
147 | The default is 2. 0 means to autosuspend as soon as | ||
148 | the device becomes idle, and -1 means never to | ||
149 | autosuspend. You can write a number to the file to | ||
150 | change the autosuspend idle-delay time. | ||
151 | |||
152 | Writing "-1" to power/autosuspend and writing "on" to power/level do | ||
153 | essentially the same thing -- they both prevent the device from being | ||
154 | autosuspended. Yes, this is a redundancy in the API. | ||
155 | |||
156 | (In 2.6.21 writing "0" to power/autosuspend would prevent the device | ||
157 | from being autosuspended; the behavior was changed in 2.6.22. The | ||
158 | power/autosuspend attribute did not exist prior to 2.6.21, and the | ||
159 | power/level attribute did not exist prior to 2.6.22.) | ||
160 | |||
161 | |||
162 | Changing the default idle-delay time | ||
163 | ------------------------------------ | ||
164 | |||
165 | The default autosuspend idle-delay time is controlled by a module | ||
166 | parameter in usbcore. You can specify the value when usbcore is | ||
167 | loaded. For example, to set it to 5 seconds instead of 2 you would | ||
168 | do: | ||
169 | |||
170 | modprobe usbcore autosuspend=5 | ||
171 | |||
172 | Equivalently, you could add to /etc/modprobe.conf a line saying: | ||
173 | |||
174 | options usbcore autosuspend=5 | ||
175 | |||
176 | Some distributions load the usbcore module very early during the boot | ||
177 | process, by means of a program or script running from an initramfs | ||
178 | image. To alter the parameter value you would have to rebuild that | ||
179 | image. | ||
180 | |||
181 | If usbcore is compiled into the kernel rather than built as a loadable | ||
182 | module, you can add | ||
183 | |||
184 | usbcore.autosuspend=5 | ||
185 | |||
186 | to the kernel's boot command line. | ||
187 | |||
188 | Finally, the parameter value can be changed while the system is | ||
189 | running. If you do: | ||
190 | |||
191 | echo 5 >/sys/module/usbcore/parameters/autosuspend | ||
192 | |||
193 | then each new USB device will have its autosuspend idle-delay | ||
194 | initialized to 5. (The idle-delay values for already existing devices | ||
195 | will not be affected.) | ||
196 | |||
197 | Setting the initial default idle-delay to -1 will prevent any | ||
198 | autosuspend of any USB device. This is a simple alternative to | ||
199 | disabling CONFIG_USB_SUSPEND and rebuilding the kernel, and it has the | ||
200 | added benefit of allowing you to enable autosuspend for selected | ||
201 | devices. | ||
202 | |||
203 | |||
204 | Warnings | ||
205 | -------- | ||
206 | |||
207 | The USB specification states that all USB devices must support power | ||
208 | management. Nevertheless, the sad fact is that many devices do not | ||
209 | support it very well. You can suspend them all right, but when you | ||
210 | try to resume them they disconnect themselves from the USB bus or | ||
211 | they stop working entirely. This seems to be especially prevalent | ||
212 | among printers and scanners, but plenty of other types of device have | ||
213 | the same deficiency. | ||
214 | |||
215 | For this reason, by default the kernel disables autosuspend (the | ||
216 | power/level attribute is initialized to "on") for all devices other | ||
217 | than hubs. Hubs, at least, appear to be reasonably well-behaved in | ||
218 | this regard. | ||
219 | |||
220 | (In 2.6.21 and 2.6.22 this wasn't the case. Autosuspend was enabled | ||
221 | by default for almost all USB devices. A number of people experienced | ||
222 | problems as a result.) | ||
223 | |||
224 | This means that non-hub devices won't be autosuspended unless the user | ||
225 | or a program explicitly enables it. As of this writing there aren't | ||
226 | any widespread programs which will do this; we hope that in the near | ||
227 | future device managers such as HAL will take on this added | ||
228 | responsibility. In the meantime you can always carry out the | ||
229 | necessary operations by hand or add them to a udev script. You can | ||
230 | also change the idle-delay time; 2 seconds is not the best choice for | ||
231 | every device. | ||
232 | |||
233 | Sometimes it turns out that even when a device does work okay with | ||
234 | autosuspend there are still problems. For example, there are | ||
235 | experimental patches adding autosuspend support to the usbhid driver, | ||
236 | which manages keyboards and mice, among other things. Tests with a | ||
237 | number of keyboards showed that typing on a suspended keyboard, while | ||
238 | causing the keyboard to do a remote wakeup all right, would | ||
239 | nonetheless frequently result in lost keystrokes. Tests with mice | ||
240 | showed that some of them would issue a remote-wakeup request in | ||
241 | response to button presses but not to motion, and some in response to | ||
242 | neither. | ||
243 | |||
244 | The kernel will not prevent you from enabling autosuspend on devices | ||
245 | that can't handle it. It is even possible in theory to damage a | ||
246 | device by suspending it at the wrong time -- for example, suspending a | ||
247 | USB hard disk might cause it to spin down without parking the heads. | ||
248 | (Highly unlikely, but possible.) Take care. | ||
249 | |||
250 | |||
251 | The driver interface for Power Management | ||
252 | ----------------------------------------- | ||
253 | |||
254 | The requirements for a USB driver to support external power management | ||
255 | are pretty modest; the driver need only define | ||
256 | |||
257 | .suspend | ||
258 | .resume | ||
259 | .reset_resume | ||
260 | |||
261 | methods in its usb_driver structure, and the reset_resume method is | ||
262 | optional. The methods' jobs are quite simple: | ||
263 | |||
264 | The suspend method is called to warn the driver that the | ||
265 | device is going to be suspended. If the driver returns a | ||
266 | negative error code, the suspend will be aborted. Normally | ||
267 | the driver will return 0, in which case it must cancel all | ||
268 | outstanding URBs (usb_kill_urb()) and not submit any more. | ||
269 | |||
270 | The resume method is called to tell the driver that the | ||
271 | device has been resumed and the driver can return to normal | ||
272 | operation. URBs may once more be submitted. | ||
273 | |||
274 | The reset_resume method is called to tell the driver that | ||
275 | the device has been resumed and it also has been reset. | ||
276 | The driver should redo any necessary device initialization, | ||
277 | since the device has probably lost most or all of its state | ||
278 | (although the interfaces will be in the same altsettings as | ||
279 | before the suspend). | ||
280 | |||
281 | The reset_resume method is used by the USB Persist facility (see | ||
282 | Documentation/usb/persist.txt) and it can also be used under certain | ||
283 | circumstances when CONFIG_USB_PERSIST is not enabled. Currently, if a | ||
284 | device is reset during a resume and the driver does not have a | ||
285 | reset_resume method, the driver won't receive any notification about | ||
286 | the resume. Later kernels will call the driver's disconnect method; | ||
287 | 2.6.23 doesn't do this. | ||
288 | |||
289 | USB drivers are bound to interfaces, so their suspend and resume | ||
290 | methods get called when the interfaces are suspended or resumed. In | ||
291 | principle one might want to suspend some interfaces on a device (i.e., | ||
292 | force the drivers for those interface to stop all activity) without | ||
293 | suspending the other interfaces. The USB core doesn't allow this; all | ||
294 | interfaces are suspended when the device itself is suspended and all | ||
295 | interfaces are resumed when the device is resumed. It isn't possible | ||
296 | to suspend or resume some but not all of a device's interfaces. The | ||
297 | closest you can come is to unbind the interfaces' drivers. | ||
298 | |||
299 | |||
300 | The driver interface for autosuspend and autoresume | ||
301 | --------------------------------------------------- | ||
302 | |||
303 | To support autosuspend and autoresume, a driver should implement all | ||
304 | three of the methods listed above. In addition, a driver indicates | ||
305 | that it supports autosuspend by setting the .supports_autosuspend flag | ||
306 | in its usb_driver structure. It is then responsible for informing the | ||
307 | USB core whenever one of its interfaces becomes busy or idle. The | ||
308 | driver does so by calling these three functions: | ||
309 | |||
310 | int usb_autopm_get_interface(struct usb_interface *intf); | ||
311 | void usb_autopm_put_interface(struct usb_interface *intf); | ||
312 | int usb_autopm_set_interface(struct usb_interface *intf); | ||
313 | |||
314 | The functions work by maintaining a counter in the usb_interface | ||
315 | structure. When intf->pm_usage_count is > 0 then the interface is | ||
316 | deemed to be busy, and the kernel will not autosuspend the interface's | ||
317 | device. When intf->pm_usage_count is <= 0 then the interface is | ||
318 | considered to be idle, and the kernel may autosuspend the device. | ||
319 | |||
320 | (There is a similar pm_usage_count field in struct usb_device, | ||
321 | associated with the device itself rather than any of its interfaces. | ||
322 | This field is used only by the USB core.) | ||
323 | |||
324 | The driver owns intf->pm_usage_count; it can modify the value however | ||
325 | and whenever it likes. A nice aspect of the usb_autopm_* routines is | ||
326 | that the changes they make are protected by the usb_device structure's | ||
327 | PM mutex (udev->pm_mutex); however drivers may change pm_usage_count | ||
328 | without holding the mutex. | ||
329 | |||
330 | usb_autopm_get_interface() increments pm_usage_count and | ||
331 | attempts an autoresume if the new value is > 0 and the | ||
332 | device is suspended. | ||
333 | |||
334 | usb_autopm_put_interface() decrements pm_usage_count and | ||
335 | attempts an autosuspend if the new value is <= 0 and the | ||
336 | device isn't suspended. | ||
337 | |||
338 | usb_autopm_set_interface() leaves pm_usage_count alone. | ||
339 | It attempts an autoresume if the value is > 0 and the device | ||
340 | is suspended, and it attempts an autosuspend if the value is | ||
341 | <= 0 and the device isn't suspended. | ||
342 | |||
343 | There also are a couple of utility routines drivers can use: | ||
344 | |||
345 | usb_autopm_enable() sets pm_usage_cnt to 1 and then calls | ||
346 | usb_autopm_set_interface(), which will attempt an autoresume. | ||
347 | |||
348 | usb_autopm_disable() sets pm_usage_cnt to 0 and then calls | ||
349 | usb_autopm_set_interface(), which will attempt an autosuspend. | ||
350 | |||
351 | The conventional usage pattern is that a driver calls | ||
352 | usb_autopm_get_interface() in its open routine and | ||
353 | usb_autopm_put_interface() in its close or release routine. But | ||
354 | other patterns are possible. | ||
355 | |||
356 | The autosuspend attempts mentioned above will often fail for one | ||
357 | reason or another. For example, the power/level attribute might be | ||
358 | set to "on", or another interface in the same device might not be | ||
359 | idle. This is perfectly normal. If the reason for failure was that | ||
360 | the device hasn't been idle for long enough, a delayed workqueue | ||
361 | routine is automatically set up to carry out the operation when the | ||
362 | autosuspend idle-delay has expired. | ||
363 | |||
364 | Autoresume attempts also can fail. This will happen if power/level is | ||
365 | set to "suspend" or if the device doesn't manage to resume properly. | ||
366 | Unlike autosuspend, there's no delay for an autoresume. | ||
367 | |||
368 | |||
369 | Other parts of the driver interface | ||
370 | ----------------------------------- | ||
371 | |||
372 | Sometimes a driver needs to make sure that remote wakeup is enabled | ||
373 | during autosuspend. For example, there's not much point | ||
374 | autosuspending a keyboard if the user can't cause the keyboard to do a | ||
375 | remote wakeup by typing on it. If the driver sets | ||
376 | intf->needs_remote_wakeup to 1, the kernel won't autosuspend the | ||
377 | device if remote wakeup isn't available or has been disabled through | ||
378 | the power/wakeup attribute. (If the device is already autosuspended, | ||
379 | though, setting this flag won't cause the kernel to autoresume it. | ||
380 | Normally a driver would set this flag in its probe method, at which | ||
381 | time the device is guaranteed not to be autosuspended.) | ||
382 | |||
383 | The usb_autopm_* routines have to run in a sleepable process context; | ||
384 | they must not be called from an interrupt handler or while holding a | ||
385 | spinlock. In fact, the entire autosuspend mechanism is not well geared | ||
386 | toward interrupt-driven operation. However there is one thing a | ||
387 | driver can do in an interrupt handler: | ||
388 | |||
389 | usb_mark_last_busy(struct usb_device *udev); | ||
390 | |||
391 | This sets udev->last_busy to the current time. udev->last_busy is the | ||
392 | field used for idle-delay calculations; updating it will cause any | ||
393 | pending autosuspend to be moved back. The usb_autopm_* routines will | ||
394 | also set the last_busy field to the current time. | ||
395 | |||
396 | Calling urb_mark_last_busy() from within an URB completion handler is | ||
397 | subject to races: The kernel may have just finished deciding the | ||
398 | device has been idle for long enough but not yet gotten around to | ||
399 | calling the driver's suspend method. The driver would have to be | ||
400 | responsible for synchronizing its suspend method with its URB | ||
401 | completion handler and causing the autosuspend to fail with -EBUSY if | ||
402 | an URB had completed too recently. | ||
403 | |||
404 | External suspend calls should never be allowed to fail in this way, | ||
405 | only autosuspend calls. The driver can tell them apart by checking | ||
406 | udev->auto_pm; this flag will be set to 1 for internal PM events | ||
407 | (autosuspend or autoresume) and 0 for external PM events. | ||
408 | |||
409 | Many of the ingredients in the autosuspend framework are oriented | ||
410 | towards interfaces: The usb_interface structure contains the | ||
411 | pm_usage_cnt field, and the usb_autopm_* routines take an interface | ||
412 | pointer as their argument. But somewhat confusingly, a few of the | ||
413 | pieces (usb_mark_last_busy() and udev->auto_pm) use the usb_device | ||
414 | structure instead. Drivers need to keep this straight; they can call | ||
415 | interface_to_usbdev() to find the device structure for a given | ||
416 | interface. | ||
417 | |||
418 | |||
419 | Locking requirements | ||
420 | -------------------- | ||
421 | |||
422 | All three suspend/resume methods are always called while holding the | ||
423 | usb_device's PM mutex. For external events -- but not necessarily for | ||
424 | autosuspend or autoresume -- the device semaphore (udev->dev.sem) will | ||
425 | also be held. This implies that external suspend/resume events are | ||
426 | mutually exclusive with calls to probe, disconnect, pre_reset, and | ||
427 | post_reset; the USB core guarantees that this is true of internal | ||
428 | suspend/resume events as well. | ||
429 | |||
430 | If a driver wants to block all suspend/resume calls during some | ||
431 | critical section, it can simply acquire udev->pm_mutex. | ||
432 | Alternatively, if the critical section might call some of the | ||
433 | usb_autopm_* routines, the driver can avoid deadlock by doing: | ||
434 | |||
435 | down(&udev->dev.sem); | ||
436 | rc = usb_autopm_get_interface(intf); | ||
437 | |||
438 | and at the end of the critical section: | ||
439 | |||
440 | if (!rc) | ||
441 | usb_autopm_put_interface(intf); | ||
442 | up(&udev->dev.sem); | ||
443 | |||
444 | Holding the device semaphore will block all external PM calls, and the | ||
445 | usb_autopm_get_interface() will prevent any internal PM calls, even if | ||
446 | it fails. (Exercise: Why?) | ||
447 | |||
448 | The rules for locking order are: | ||
449 | |||
450 | Never acquire any device semaphore while holding any PM mutex. | ||
451 | |||
452 | Never acquire udev->pm_mutex while holding the PM mutex for | ||
453 | a device that isn't a descendant of udev. | ||
454 | |||
455 | In other words, PM mutexes should only be acquired going up the device | ||
456 | tree, and they should be acquired only after locking all the device | ||
457 | semaphores you need to hold. These rules don't matter to drivers very | ||
458 | much; they usually affect just the USB core. | ||
459 | |||
460 | Still, drivers do need to be careful. For example, many drivers use a | ||
461 | private mutex to synchronize their normal I/O activities with their | ||
462 | disconnect method. Now if the driver supports autosuspend then it | ||
463 | must call usb_autopm_put_interface() from somewhere -- maybe from its | ||
464 | close method. It should make the call while holding the private mutex, | ||
465 | since a driver shouldn't call any of the usb_autopm_* functions for an | ||
466 | interface from which it has been unbound. | ||
467 | |||
468 | But the usb_autpm_* routines always acquire the device's PM mutex, and | ||
469 | consequently the locking order has to be: private mutex first, PM | ||
470 | mutex second. Since the suspend method is always called with the PM | ||
471 | mutex held, it mustn't try to acquire the private mutex. It has to | ||
472 | synchronize with the driver's I/O activities in some other way. | ||
473 | |||
474 | |||
475 | Interaction between dynamic PM and system PM | ||
476 | -------------------------------------------- | ||
477 | |||
478 | Dynamic power management and system power management can interact in | ||
479 | a couple of ways. | ||
480 | |||
481 | Firstly, a device may already be manually suspended or autosuspended | ||
482 | when a system suspend occurs. Since system suspends are supposed to | ||
483 | be as transparent as possible, the device should remain suspended | ||
484 | following the system resume. The 2.6.23 kernel obeys this principle | ||
485 | for manually suspended devices but not for autosuspended devices; they | ||
486 | do get resumed when the system wakes up. (Presumably they will be | ||
487 | autosuspended again after their idle-delay time expires.) In later | ||
488 | kernels this behavior will be fixed. | ||
489 | |||
490 | (There is an exception. If a device would undergo a reset-resume | ||
491 | instead of a normal resume, and the device is enabled for remote | ||
492 | wakeup, then the reset-resume takes place even if the device was | ||
493 | already suspended when the system suspend began. The justification is | ||
494 | that a reset-resume is a kind of remote-wakeup event. Or to put it | ||
495 | another way, a device which needs a reset won't be able to generate | ||
496 | normal remote-wakeup signals, so it ought to be resumed immediately.) | ||
497 | |||
498 | Secondly, a dynamic power-management event may occur as a system | ||
499 | suspend is underway. The window for this is short, since system | ||
500 | suspends don't take long (a few seconds usually), but it can happen. | ||
501 | For example, a suspended device may send a remote-wakeup signal while | ||
502 | the system is suspending. The remote wakeup may succeed, which would | ||
503 | cause the system suspend to abort. If the remote wakeup doesn't | ||
504 | succeed, it may still remain active and thus cause the system to | ||
505 | resume as soon as the system suspend is complete. Or the remote | ||
506 | wakeup may fail and get lost. Which outcome occurs depends on timing | ||
507 | and on the hardware and firmware design. | ||
508 | |||
509 | More interestingly, a device might undergo a manual resume or | ||
510 | autoresume during system suspend. With current kernels this shouldn't | ||
511 | happen, because manual resumes must be initiated by userspace and | ||
512 | autoresumes happen in response to I/O requests, but all user processes | ||
513 | and I/O should be quiescent during a system suspend -- thanks to the | ||
514 | freezer. However there are plans to do away with the freezer, which | ||
515 | would mean these things would become possible. If and when this comes | ||
516 | about, the USB core will carefully arrange matters so that either type | ||
517 | of resume will block until the entire system has resumed. | ||
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 5b635ae84944..4e0b62b8566f 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt | |||
@@ -428,6 +428,17 @@ Options supported: | |||
428 | See http://www.uuhaus.de/linux/palmconnect.html for up-to-date | 428 | See http://www.uuhaus.de/linux/palmconnect.html for up-to-date |
429 | information on this driver. | 429 | information on this driver. |
430 | 430 | ||
431 | Winchiphead CH341 Driver | ||
432 | |||
433 | This driver is for the Winchiphead CH341 USB-RS232 Converter. This chip | ||
434 | also implements an IEEE 1284 parallel port, I2C and SPI, but that is not | ||
435 | supported by the driver. The protocol was analyzed from the behaviour | ||
436 | of the Windows driver, no datasheet is available at present. | ||
437 | The manufacturer's website: http://www.winchiphead.com/. | ||
438 | For any questions or problems with this driver, please contact | ||
439 | frank@kingswood-consulting.co.uk. | ||
440 | |||
441 | |||
431 | Generic Serial driver | 442 | Generic Serial driver |
432 | 443 | ||
433 | If your device is not one of the above listed devices, compatible with | 444 | If your device is not one of the above listed devices, compatible with |
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 53ae866ae37b..2917ce4ffdc4 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt | |||
@@ -34,9 +34,12 @@ if usbmon is built into the kernel. | |||
34 | Verify that bus sockets are present. | 34 | Verify that bus sockets are present. |
35 | 35 | ||
36 | # ls /sys/kernel/debug/usbmon | 36 | # ls /sys/kernel/debug/usbmon |
37 | 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u | 37 | 0s 0t 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u |
38 | # | 38 | # |
39 | 39 | ||
40 | Now you can choose to either use the sockets numbered '0' (to capture packets on | ||
41 | all buses), and skip to step #3, or find the bus used by your device with step #2. | ||
42 | |||
40 | 2. Find which bus connects to the desired device | 43 | 2. Find which bus connects to the desired device |
41 | 44 | ||
42 | Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to | 45 | Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to |
@@ -56,6 +59,10 @@ Bus=03 means it's bus 3. | |||
56 | 59 | ||
57 | # cat /sys/kernel/debug/usbmon/3u > /tmp/1.mon.out | 60 | # cat /sys/kernel/debug/usbmon/3u > /tmp/1.mon.out |
58 | 61 | ||
62 | to listen on a single bus, otherwise, to listen on all buses, type: | ||
63 | |||
64 | # cat /sys/kernel/debug/usbmon/0u > /tmp/1.mon.out | ||
65 | |||
59 | This process will be reading until killed. Naturally, the output can be | 66 | This process will be reading until killed. Naturally, the output can be |
60 | redirected to a desirable location. This is preferred, because it is going | 67 | redirected to a desirable location. This is preferred, because it is going |
61 | to be quite long. | 68 | to be quite long. |
diff --git a/MAINTAINERS b/MAINTAINERS index c4eca56ed5bf..60e649ff6fdc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -677,6 +677,13 @@ P: Haavard Skinnemoen | |||
677 | M: hskinnemoen@atmel.com | 677 | M: hskinnemoen@atmel.com |
678 | S: Supported | 678 | S: Supported |
679 | 679 | ||
680 | ATMEL USBA UDC DRIVER | ||
681 | P: Haavard Skinnemoen | ||
682 | M: hskinnemoen@atmel.com | ||
683 | L: kernel@avr32linux.org | ||
684 | W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver | ||
685 | S: Supported | ||
686 | |||
680 | ATMEL WIRELESS DRIVER | 687 | ATMEL WIRELESS DRIVER |
681 | P: Simon Kelley | 688 | P: Simon Kelley |
682 | M: simon@thekelleys.org.uk | 689 | M: simon@thekelleys.org.uk |
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c index 467d899fbe75..e548ba74a4d2 100644 --- a/arch/arm/mach-imx/cpufreq.c +++ b/arch/arm/mach-imx/cpufreq.c | |||
@@ -269,7 +269,6 @@ static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy) | |||
269 | return -EINVAL; | 269 | return -EINVAL; |
270 | 270 | ||
271 | policy->cur = policy->min = policy->max = imx_get_speed(0); | 271 | policy->cur = policy->min = policy->max = imx_get_speed(0); |
272 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
273 | policy->cpuinfo.min_freq = 8000; | 272 | policy->cpuinfo.min_freq = 8000; |
274 | policy->cpuinfo.max_freq = 200000; | 273 | policy->cpuinfo.max_freq = 200000; |
275 | /* Manual states, that PLL stabilizes in two CLK32 periods */ | 274 | /* Manual states, that PLL stabilizes in two CLK32 periods */ |
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 78f4c1346044..36b47ff5af11 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c | |||
@@ -331,7 +331,6 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) | |||
331 | if (policy->cpu != 0) | 331 | if (policy->cpu != 0) |
332 | return -EINVAL; | 332 | return -EINVAL; |
333 | policy->cur = policy->min = policy->max = sa11x0_getspeed(0); | 333 | policy->cur = policy->min = policy->max = sa11x0_getspeed(0); |
334 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
335 | policy->cpuinfo.min_freq = 59000; | 334 | policy->cpuinfo.min_freq = 59000; |
336 | policy->cpuinfo.max_freq = 287000; | 335 | policy->cpuinfo.max_freq = 287000; |
337 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 336 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index a0c71dca2373..c0d63b0c61c9 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c | |||
@@ -108,7 +108,6 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) | |||
108 | if (policy->cpu != 0) | 108 | if (policy->cpu != 0) |
109 | return -EINVAL; | 109 | return -EINVAL; |
110 | policy->cur = policy->min = policy->max = omap_getspeed(0); | 110 | policy->cur = policy->min = policy->max = omap_getspeed(0); |
111 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
112 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; | 111 | policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; |
113 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; | 112 | policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; |
114 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 113 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c index 6fd9cfd0a31b..b7a0e0fbd9af 100644 --- a/arch/blackfin/mach-bf533/cpu.c +++ b/arch/blackfin/mach-bf533/cpu.c | |||
@@ -118,8 +118,6 @@ static int __init __bf533_cpu_init(struct cpufreq_policy *policy) | |||
118 | if (policy->cpu != 0) | 118 | if (policy->cpu != 0) |
119 | return -EINVAL; | 119 | return -EINVAL; |
120 | 120 | ||
121 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
122 | |||
123 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 121 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
124 | /*Now ,only support one cpu */ | 122 | /*Now ,only support one cpu */ |
125 | policy->cur = bf533_getfreq(0); | 123 | policy->cur = bf533_getfreq(0); |
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index 5e9d09eb8579..6668c8e4a3fc 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/pata_platform.h> | 40 | #include <linux/pata_platform.h> |
41 | #include <linux/irq.h> | 41 | #include <linux/irq.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/usb_sl811.h> | 43 | #include <linux/usb/sl811.h> |
44 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
45 | #include <asm/bfin5xx_spi.h> | 45 | #include <asm/bfin5xx_spi.h> |
46 | #include <asm/reboot.h> | 46 | #include <asm/reboot.h> |
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 20507e92a3a4..f83a2544004d 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/irq.h> | 40 | #include <linux/irq.h> |
41 | #include <asm/dma.h> | 41 | #include <asm/dma.h> |
42 | #include <asm/bfin5xx_spi.h> | 42 | #include <asm/bfin5xx_spi.h> |
43 | #include <linux/usb_sl811.h> | 43 | #include <linux/usb/sl811.h> |
44 | 44 | ||
45 | #include <linux/spi/ad7877.h> | 45 | #include <linux/spi/ad7877.h> |
46 | 46 | ||
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 47d7d4a0e73d..f42ba3aa86d7 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/pata_platform.h> | 40 | #include <linux/pata_platform.h> |
41 | #include <linux/irq.h> | 41 | #include <linux/irq.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/usb_sl811.h> | 43 | #include <linux/usb/sl811.h> |
44 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
45 | #include <asm/bfin5xx_spi.h> | 45 | #include <asm/bfin5xx_spi.h> |
46 | #include <asm/reboot.h> | 46 | #include <asm/reboot.h> |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 2d85e4b87307..6bbbc2755e44 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -1206,6 +1206,16 @@ config SCx200HR_TIMER | |||
1206 | processor goes idle (as is done by the scheduler). The | 1206 | processor goes idle (as is done by the scheduler). The |
1207 | other workaround is idle=poll boot option. | 1207 | other workaround is idle=poll boot option. |
1208 | 1208 | ||
1209 | config GEODE_MFGPT_TIMER | ||
1210 | bool "Geode Multi-Function General Purpose Timer (MFGPT) events" | ||
1211 | depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS | ||
1212 | default y | ||
1213 | help | ||
1214 | This driver provides a clock event source based on the MFGPT | ||
1215 | timer(s) in the CS5535 and CS5536 companion chip for the geode. | ||
1216 | MFGPTs have a better resolution and max interval than the | ||
1217 | generic PIT, and are suitable for use as high-res timers. | ||
1218 | |||
1209 | config K8_NB | 1219 | config K8_NB |
1210 | def_bool y | 1220 | def_bool y |
1211 | depends on AGP_AMD64 | 1221 | depends on AGP_AMD64 |
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c index 8c6ec7070844..b8498ea62068 100644 --- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c +++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c | |||
@@ -321,8 +321,6 @@ acpi_cpufreq_cpu_init ( | |||
321 | data->acpi_data.states[i].transition_latency * 1000; | 321 | data->acpi_data.states[i].transition_latency * 1000; |
322 | } | 322 | } |
323 | } | 323 | } |
324 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
325 | |||
326 | policy->cur = processor_get_freq(data, policy->cpu); | 324 | policy->cur = processor_get_freq(data, policy->cpu); |
327 | 325 | ||
328 | /* table init */ | 326 | /* table init */ |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 901236fa0f07..5123e9d4164b 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c | |||
@@ -107,8 +107,6 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
107 | pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); | 107 | pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); |
108 | } | 108 | } |
109 | 109 | ||
110 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
111 | |||
112 | /* if DEBUG is enabled set_pmode() measures the latency | 110 | /* if DEBUG is enabled set_pmode() measures the latency |
113 | * of a transition */ | 111 | * of a transition */ |
114 | policy->cpuinfo.transition_latency = 25000; | 112 | policy->cpuinfo.transition_latency = 25000; |
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 3ae083851b01..1cfb8b0c8fec 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c | |||
@@ -195,8 +195,6 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
195 | pr_debug("%d: %d\n", i, pas_freqs[i].frequency); | 195 | pr_debug("%d: %d\n", i, pas_freqs[i].frequency); |
196 | } | 196 | } |
197 | 197 | ||
198 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
199 | |||
200 | policy->cpuinfo.transition_latency = get_gizmo_latency(); | 198 | policy->cpuinfo.transition_latency = get_gizmo_latency(); |
201 | 199 | ||
202 | cur_astate = get_cur_astate(policy->cpu); | 200 | cur_astate = get_cur_astate(policy->cpu); |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 1fe35dab0e9e..c04abcc28a7a 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c | |||
@@ -410,7 +410,6 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
410 | if (policy->cpu != 0) | 410 | if (policy->cpu != 0) |
411 | return -ENODEV; | 411 | return -ENODEV; |
412 | 412 | ||
413 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
414 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 413 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
415 | policy->cur = cur_freq; | 414 | policy->cur = cur_freq; |
416 | 415 | ||
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index 00f50298c342..4dfb4bc242b5 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c | |||
@@ -357,7 +357,6 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu) | |||
357 | 357 | ||
358 | static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) | 358 | static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) |
359 | { | 359 | { |
360 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
361 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 360 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
362 | policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; | 361 | policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; |
363 | /* secondary CPUs are tied to the primary one by the | 362 | /* secondary CPUs are tied to the primary one by the |
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 62391fb1f61f..ac61cf43a7d9 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
@@ -547,8 +547,7 @@ static void __cpuinit appldata_online_cpu(int cpu) | |||
547 | spin_unlock(&appldata_timer_lock); | 547 | spin_unlock(&appldata_timer_lock); |
548 | } | 548 | } |
549 | 549 | ||
550 | static void | 550 | static void __cpuinit appldata_offline_cpu(int cpu) |
551 | appldata_offline_cpu(int cpu) | ||
552 | { | 551 | { |
553 | del_virt_timer(&per_cpu(appldata_timer, cpu)); | 552 | del_virt_timer(&per_cpu(appldata_timer, cpu)); |
554 | if (atomic_dec_and_test(&appldata_expire_count)) { | 553 | if (atomic_dec_and_test(&appldata_expire_count)) { |
@@ -560,9 +559,9 @@ appldata_offline_cpu(int cpu) | |||
560 | spin_unlock(&appldata_timer_lock); | 559 | spin_unlock(&appldata_timer_lock); |
561 | } | 560 | } |
562 | 561 | ||
563 | static int __cpuinit | 562 | static int __cpuinit appldata_cpu_notify(struct notifier_block *self, |
564 | appldata_cpu_notify(struct notifier_block *self, | 563 | unsigned long action, |
565 | unsigned long action, void *hcpu) | 564 | void *hcpu) |
566 | { | 565 | { |
567 | switch (action) { | 566 | switch (action) { |
568 | case CPU_ONLINE: | 567 | case CPU_ONLINE: |
@@ -608,63 +607,15 @@ static int __init appldata_init(void) | |||
608 | register_hotcpu_notifier(&appldata_nb); | 607 | register_hotcpu_notifier(&appldata_nb); |
609 | 608 | ||
610 | appldata_sysctl_header = register_sysctl_table(appldata_dir_table); | 609 | appldata_sysctl_header = register_sysctl_table(appldata_dir_table); |
611 | #ifdef MODULE | ||
612 | appldata_dir_table[0].de->owner = THIS_MODULE; | ||
613 | appldata_table[0].de->owner = THIS_MODULE; | ||
614 | appldata_table[1].de->owner = THIS_MODULE; | ||
615 | #endif | ||
616 | 610 | ||
617 | P_DEBUG("Base interface initialized.\n"); | 611 | P_DEBUG("Base interface initialized.\n"); |
618 | return 0; | 612 | return 0; |
619 | } | 613 | } |
620 | 614 | ||
621 | /* | 615 | __initcall(appldata_init); |
622 | * appldata_exit() | ||
623 | * | ||
624 | * stop timer, unregister /proc entries | ||
625 | */ | ||
626 | static void __exit appldata_exit(void) | ||
627 | { | ||
628 | struct list_head *lh; | ||
629 | struct appldata_ops *ops; | ||
630 | int rc, i; | ||
631 | 616 | ||
632 | P_DEBUG("Unloading module ...\n"); | ||
633 | /* | ||
634 | * ops list should be empty, but just in case something went wrong... | ||
635 | */ | ||
636 | spin_lock(&appldata_ops_lock); | ||
637 | list_for_each(lh, &appldata_ops_list) { | ||
638 | ops = list_entry(lh, struct appldata_ops, list); | ||
639 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, | ||
640 | (unsigned long) ops->data, ops->size, | ||
641 | ops->mod_lvl); | ||
642 | if (rc != 0) { | ||
643 | P_ERROR("STOP DIAG 0xDC for %s failed, " | ||
644 | "return code: %d\n", ops->name, rc); | ||
645 | } | ||
646 | } | ||
647 | spin_unlock(&appldata_ops_lock); | ||
648 | |||
649 | for_each_online_cpu(i) | ||
650 | appldata_offline_cpu(i); | ||
651 | |||
652 | appldata_timer_active = 0; | ||
653 | |||
654 | unregister_sysctl_table(appldata_sysctl_header); | ||
655 | |||
656 | destroy_workqueue(appldata_wq); | ||
657 | P_DEBUG("... module unloaded!\n"); | ||
658 | } | ||
659 | /**************************** init / exit <END> ******************************/ | 617 | /**************************** init / exit <END> ******************************/ |
660 | 618 | ||
661 | |||
662 | module_init(appldata_init); | ||
663 | module_exit(appldata_exit); | ||
664 | MODULE_LICENSE("GPL"); | ||
665 | MODULE_AUTHOR("Gerald Schaefer"); | ||
666 | MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure"); | ||
667 | |||
668 | EXPORT_SYMBOL_GPL(appldata_register_ops); | 619 | EXPORT_SYMBOL_GPL(appldata_register_ops); |
669 | EXPORT_SYMBOL_GPL(appldata_unregister_ops); | 620 | EXPORT_SYMBOL_GPL(appldata_unregister_ops); |
670 | EXPORT_SYMBOL_GPL(appldata_diag); | 621 | EXPORT_SYMBOL_GPL(appldata_diag); |
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c index d1c76fe10f29..f4932c22ebe4 100644 --- a/arch/s390/kernel/audit.c +++ b/arch/s390/kernel/audit.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/types.h> | 2 | #include <linux/types.h> |
3 | #include <linux/audit.h> | 3 | #include <linux/audit.h> |
4 | #include <asm/unistd.h> | 4 | #include <asm/unistd.h> |
5 | #include "audit.h" | ||
5 | 6 | ||
6 | static unsigned dir_class[] = { | 7 | static unsigned dir_class[] = { |
7 | #include <asm-generic/audit_dir_write.h> | 8 | #include <asm-generic/audit_dir_write.h> |
@@ -40,7 +41,6 @@ int audit_classify_arch(int arch) | |||
40 | int audit_classify_syscall(int abi, unsigned syscall) | 41 | int audit_classify_syscall(int abi, unsigned syscall) |
41 | { | 42 | { |
42 | #ifdef CONFIG_COMPAT | 43 | #ifdef CONFIG_COMPAT |
43 | extern int s390_classify_syscall(unsigned); | ||
44 | if (abi == AUDIT_ARCH_S390) | 44 | if (abi == AUDIT_ARCH_S390) |
45 | return s390_classify_syscall(syscall); | 45 | return s390_classify_syscall(syscall); |
46 | #endif | 46 | #endif |
@@ -61,11 +61,6 @@ int audit_classify_syscall(int abi, unsigned syscall) | |||
61 | static int __init audit_classes_init(void) | 61 | static int __init audit_classes_init(void) |
62 | { | 62 | { |
63 | #ifdef CONFIG_COMPAT | 63 | #ifdef CONFIG_COMPAT |
64 | extern __u32 s390_dir_class[]; | ||
65 | extern __u32 s390_write_class[]; | ||
66 | extern __u32 s390_read_class[]; | ||
67 | extern __u32 s390_chattr_class[]; | ||
68 | extern __u32 s390_signal_class[]; | ||
69 | audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); | 64 | audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); |
70 | audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); | 65 | audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); |
71 | audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); | 66 | audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); |
diff --git a/arch/s390/kernel/audit.h b/arch/s390/kernel/audit.h new file mode 100644 index 000000000000..12b56f4b5a73 --- /dev/null +++ b/arch/s390/kernel/audit.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef __ARCH_S390_KERNEL_AUDIT_H | ||
2 | #define __ARCH_S390_KERNEL_AUDIT_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | #ifdef CONFIG_COMPAT | ||
7 | extern int s390_classify_syscall(unsigned); | ||
8 | extern __u32 s390_dir_class[]; | ||
9 | extern __u32 s390_write_class[]; | ||
10 | extern __u32 s390_read_class[]; | ||
11 | extern __u32 s390_chattr_class[]; | ||
12 | extern __u32 s390_signal_class[]; | ||
13 | #endif /* CONFIG_COMPAT */ | ||
14 | |||
15 | #endif /* __ARCH_S390_KERNEL_AUDIT_H */ | ||
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c index 0569f5126e49..d6487bf879e5 100644 --- a/arch/s390/kernel/compat_audit.c +++ b/arch/s390/kernel/compat_audit.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #undef __s390x__ | 1 | #undef __s390x__ |
2 | #include <asm/unistd.h> | 2 | #include <asm/unistd.h> |
3 | #include "audit.h" | ||
3 | 4 | ||
4 | unsigned s390_dir_class[] = { | 5 | unsigned s390_dir_class[] = { |
5 | #include <asm-generic/audit_dir_write.h> | 6 | #include <asm-generic/audit_dir_write.h> |
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 6c89f30c8e31..d8c1131e0815 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/s390/kernel/cpcmd.c | 2 | * arch/s390/kernel/cpcmd.c |
3 | * | 3 | * |
4 | * S390 version | 4 | * S390 version |
5 | * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation | 5 | * Copyright IBM Corp. 1999,2007 |
6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 6 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), |
7 | * Christian Borntraeger (cborntra@de.ibm.com), | 7 | * Christian Borntraeger (cborntra@de.ibm.com), |
8 | */ | 8 | */ |
@@ -21,6 +21,49 @@ | |||
21 | static DEFINE_SPINLOCK(cpcmd_lock); | 21 | static DEFINE_SPINLOCK(cpcmd_lock); |
22 | static char cpcmd_buf[241]; | 22 | static char cpcmd_buf[241]; |
23 | 23 | ||
24 | static int diag8_noresponse(int cmdlen) | ||
25 | { | ||
26 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | ||
27 | register unsigned long reg3 asm ("3") = cmdlen; | ||
28 | |||
29 | asm volatile( | ||
30 | #ifndef CONFIG_64BIT | ||
31 | " diag %1,%0,0x8\n" | ||
32 | #else /* CONFIG_64BIT */ | ||
33 | " sam31\n" | ||
34 | " diag %1,%0,0x8\n" | ||
35 | " sam64\n" | ||
36 | #endif /* CONFIG_64BIT */ | ||
37 | : "+d" (reg3) : "d" (reg2) : "cc"); | ||
38 | return reg3; | ||
39 | } | ||
40 | |||
41 | static int diag8_response(int cmdlen, char *response, int *rlen) | ||
42 | { | ||
43 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | ||
44 | register unsigned long reg3 asm ("3") = (addr_t) response; | ||
45 | register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; | ||
46 | register unsigned long reg5 asm ("5") = *rlen; | ||
47 | |||
48 | asm volatile( | ||
49 | #ifndef CONFIG_64BIT | ||
50 | " diag %2,%0,0x8\n" | ||
51 | " brc 8,1f\n" | ||
52 | " ar %1,%4\n" | ||
53 | #else /* CONFIG_64BIT */ | ||
54 | " sam31\n" | ||
55 | " diag %2,%0,0x8\n" | ||
56 | " sam64\n" | ||
57 | " brc 8,1f\n" | ||
58 | " agr %1,%4\n" | ||
59 | #endif /* CONFIG_64BIT */ | ||
60 | "1:\n" | ||
61 | : "+d" (reg4), "+d" (reg5) | ||
62 | : "d" (reg2), "d" (reg3), "d" (*rlen) : "cc"); | ||
63 | *rlen = reg5; | ||
64 | return reg4; | ||
65 | } | ||
66 | |||
24 | /* | 67 | /* |
25 | * __cpcmd has some restrictions over cpcmd | 68 | * __cpcmd has some restrictions over cpcmd |
26 | * - the response buffer must reside below 2GB (if any) | 69 | * - the response buffer must reside below 2GB (if any) |
@@ -28,59 +71,27 @@ static char cpcmd_buf[241]; | |||
28 | */ | 71 | */ |
29 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 72 | int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
30 | { | 73 | { |
31 | unsigned cmdlen; | 74 | int cmdlen; |
32 | int return_code, return_len; | 75 | int rc; |
76 | int response_len; | ||
33 | 77 | ||
34 | cmdlen = strlen(cmd); | 78 | cmdlen = strlen(cmd); |
35 | BUG_ON(cmdlen > 240); | 79 | BUG_ON(cmdlen > 240); |
36 | memcpy(cpcmd_buf, cmd, cmdlen); | 80 | memcpy(cpcmd_buf, cmd, cmdlen); |
37 | ASCEBC(cpcmd_buf, cmdlen); | 81 | ASCEBC(cpcmd_buf, cmdlen); |
38 | 82 | ||
39 | if (response != NULL && rlen > 0) { | 83 | if (response) { |
40 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | ||
41 | register unsigned long reg3 asm ("3") = (addr_t) response; | ||
42 | register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; | ||
43 | register unsigned long reg5 asm ("5") = rlen; | ||
44 | |||
45 | memset(response, 0, rlen); | 84 | memset(response, 0, rlen); |
46 | asm volatile( | 85 | response_len = rlen; |
47 | #ifndef CONFIG_64BIT | 86 | rc = diag8_response(cmdlen, response, &rlen); |
48 | " diag %2,%0,0x8\n" | 87 | EBCASC(response, response_len); |
49 | " brc 8,1f\n" | ||
50 | " ar %1,%4\n" | ||
51 | #else /* CONFIG_64BIT */ | ||
52 | " sam31\n" | ||
53 | " diag %2,%0,0x8\n" | ||
54 | " sam64\n" | ||
55 | " brc 8,1f\n" | ||
56 | " agr %1,%4\n" | ||
57 | #endif /* CONFIG_64BIT */ | ||
58 | "1:\n" | ||
59 | : "+d" (reg4), "+d" (reg5) | ||
60 | : "d" (reg2), "d" (reg3), "d" (rlen) : "cc"); | ||
61 | return_code = (int) reg4; | ||
62 | return_len = (int) reg5; | ||
63 | EBCASC(response, rlen); | ||
64 | } else { | 88 | } else { |
65 | register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; | 89 | rc = diag8_noresponse(cmdlen); |
66 | register unsigned long reg3 asm ("3") = cmdlen; | ||
67 | return_len = 0; | ||
68 | asm volatile( | ||
69 | #ifndef CONFIG_64BIT | ||
70 | " diag %1,%0,0x8\n" | ||
71 | #else /* CONFIG_64BIT */ | ||
72 | " sam31\n" | ||
73 | " diag %1,%0,0x8\n" | ||
74 | " sam64\n" | ||
75 | #endif /* CONFIG_64BIT */ | ||
76 | : "+d" (reg3) : "d" (reg2) : "cc"); | ||
77 | return_code = (int) reg3; | ||
78 | } | 90 | } |
79 | if (response_code != NULL) | 91 | if (response_code) |
80 | *response_code = return_code; | 92 | *response_code = rc; |
81 | return return_len; | 93 | return rlen; |
82 | } | 94 | } |
83 | |||
84 | EXPORT_SYMBOL(__cpcmd); | 95 | EXPORT_SYMBOL(__cpcmd); |
85 | 96 | ||
86 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | 97 | int cpcmd(const char *cmd, char *response, int rlen, int *response_code) |
@@ -109,5 +120,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) | |||
109 | } | 120 | } |
110 | return len; | 121 | return len; |
111 | } | 122 | } |
112 | |||
113 | EXPORT_SYMBOL(cpcmd); | 123 | EXPORT_SYMBOL(cpcmd); |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 50d2235df732..c14a336f6300 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -1162,6 +1162,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) | |||
1162 | unsigned int value; | 1162 | unsigned int value; |
1163 | char separator; | 1163 | char separator; |
1164 | char *ptr; | 1164 | char *ptr; |
1165 | int i; | ||
1165 | 1166 | ||
1166 | ptr = buffer; | 1167 | ptr = buffer; |
1167 | insn = find_insn(code); | 1168 | insn = find_insn(code); |
@@ -1169,7 +1170,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) | |||
1169 | ptr += sprintf(ptr, "%.5s\t", insn->name); | 1170 | ptr += sprintf(ptr, "%.5s\t", insn->name); |
1170 | /* Extract the operands. */ | 1171 | /* Extract the operands. */ |
1171 | separator = 0; | 1172 | separator = 0; |
1172 | for (ops = formats[insn->format] + 1; *ops != 0; ops++) { | 1173 | for (ops = formats[insn->format] + 1, i = 0; |
1174 | *ops != 0 && i < 6; ops++, i++) { | ||
1173 | operand = operands + *ops; | 1175 | operand = operands + *ops; |
1174 | value = extract_operand(code, operand); | 1176 | value = extract_operand(code, operand); |
1175 | if ((operand->flags & OPERAND_INDEX) && value == 0) | 1177 | if ((operand->flags & OPERAND_INDEX) && value == 0) |
@@ -1241,7 +1243,6 @@ void show_code(struct pt_regs *regs) | |||
1241 | } | 1243 | } |
1242 | /* Find a starting point for the disassembly. */ | 1244 | /* Find a starting point for the disassembly. */ |
1243 | while (start < 32) { | 1245 | while (start < 32) { |
1244 | hops = 0; | ||
1245 | for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) { | 1246 | for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) { |
1246 | if (!find_insn(code + start + i)) | 1247 | if (!find_insn(code + start + i)) |
1247 | break; | 1248 | break; |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 8b8f136d9cc7..66b51901c87d 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -735,10 +735,10 @@ void do_reipl(void) | |||
735 | case REIPL_METHOD_CCW_VM: | 735 | case REIPL_METHOD_CCW_VM: |
736 | reipl_get_ascii_loadparm(loadparm); | 736 | reipl_get_ascii_loadparm(loadparm); |
737 | if (strlen(loadparm) == 0) | 737 | if (strlen(loadparm) == 0) |
738 | sprintf(buf, "IPL %X", | 738 | sprintf(buf, "IPL %X CLEAR", |
739 | reipl_block_ccw->ipl_info.ccw.devno); | 739 | reipl_block_ccw->ipl_info.ccw.devno); |
740 | else | 740 | else |
741 | sprintf(buf, "IPL %X LOADPARM '%s'", | 741 | sprintf(buf, "IPL %X CLEAR LOADPARM '%s'", |
742 | reipl_block_ccw->ipl_info.ccw.devno, loadparm); | 742 | reipl_block_ccw->ipl_info.ccw.devno, loadparm); |
743 | __cpcmd(buf, NULL, 0, NULL); | 743 | __cpcmd(buf, NULL, 0, NULL); |
744 | break; | 744 | break; |
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index b4622a3889b0..849120e3e28a 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -2,6 +2,7 @@ | |||
2 | * Written by Martin Schwidefsky (schwidefsky@de.ibm.com) | 2 | * Written by Martin Schwidefsky (schwidefsky@de.ibm.com) |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <asm/page.h> | ||
5 | #include <asm-generic/vmlinux.lds.h> | 6 | #include <asm-generic/vmlinux.lds.h> |
6 | 7 | ||
7 | #ifndef CONFIG_64BIT | 8 | #ifndef CONFIG_64BIT |
@@ -18,121 +19,142 @@ jiffies = jiffies_64; | |||
18 | 19 | ||
19 | SECTIONS | 20 | SECTIONS |
20 | { | 21 | { |
21 | . = 0x00000000; | 22 | . = 0x00000000; |
22 | _text = .; /* Text and read-only data */ | 23 | .text : { |
23 | .text : { | 24 | _text = .; /* Text and read-only data */ |
24 | *(.text.head) | 25 | *(.text.head) |
25 | TEXT_TEXT | 26 | TEXT_TEXT |
26 | SCHED_TEXT | 27 | SCHED_TEXT |
27 | LOCK_TEXT | 28 | LOCK_TEXT |
28 | KPROBES_TEXT | 29 | KPROBES_TEXT |
29 | *(.fixup) | 30 | *(.fixup) |
30 | *(.gnu.warning) | 31 | *(.gnu.warning) |
31 | } = 0x0700 | 32 | } = 0x0700 |
32 | 33 | ||
33 | _etext = .; /* End of text section */ | 34 | _etext = .; /* End of text section */ |
34 | 35 | ||
35 | RODATA | 36 | RODATA |
36 | 37 | ||
37 | #ifdef CONFIG_SHARED_KERNEL | 38 | #ifdef CONFIG_SHARED_KERNEL |
38 | . = ALIGN(1048576); /* VM shared segments are 1MB aligned */ | 39 | . = ALIGN(0x100000); /* VM shared segments are 1MB aligned */ |
39 | #endif | 40 | #endif |
40 | 41 | ||
41 | . = ALIGN(4096); | 42 | . = ALIGN(PAGE_SIZE); |
42 | _eshared = .; /* End of shareable data */ | 43 | _eshared = .; /* End of shareable data */ |
43 | 44 | ||
44 | . = ALIGN(16); /* Exception table */ | 45 | . = ALIGN(16); /* Exception table */ |
45 | __start___ex_table = .; | 46 | __ex_table : { |
46 | __ex_table : { *(__ex_table) } | 47 | __start___ex_table = .; |
47 | __stop___ex_table = .; | 48 | *(__ex_table) |
48 | 49 | __stop___ex_table = .; | |
49 | NOTES | 50 | } |
50 | 51 | ||
51 | BUG_TABLE | 52 | NOTES |
52 | 53 | BUG_TABLE | |
53 | .data : { /* Data */ | 54 | |
54 | DATA_DATA | 55 | .data : { /* Data */ |
55 | CONSTRUCTORS | 56 | DATA_DATA |
56 | } | 57 | CONSTRUCTORS |
57 | 58 | } | |
58 | . = ALIGN(4096); | 59 | |
59 | __nosave_begin = .; | 60 | . = ALIGN(PAGE_SIZE); |
60 | .data_nosave : { *(.data.nosave) } | 61 | .data_nosave : { |
61 | . = ALIGN(4096); | 62 | __nosave_begin = .; |
62 | __nosave_end = .; | 63 | *(.data.nosave) |
63 | 64 | } | |
64 | . = ALIGN(4096); | 65 | . = ALIGN(PAGE_SIZE); |
65 | .data.page_aligned : { *(.data.idt) } | 66 | __nosave_end = .; |
66 | 67 | ||
67 | . = ALIGN(256); | 68 | . = ALIGN(PAGE_SIZE); |
68 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } | 69 | .data.page_aligned : { |
69 | 70 | *(.data.idt) | |
70 | . = ALIGN(256); | 71 | } |
71 | .data.read_mostly : { *(.data.read_mostly) } | 72 | |
72 | _edata = .; /* End of data section */ | 73 | . = ALIGN(0x100); |
73 | 74 | .data.cacheline_aligned : { | |
74 | . = ALIGN(8192); /* init_task */ | 75 | *(.data.cacheline_aligned) |
75 | .data.init_task : { *(.data.init_task) } | 76 | } |
76 | 77 | ||
77 | /* will be freed after init */ | 78 | . = ALIGN(0x100); |
78 | . = ALIGN(4096); /* Init code and data */ | 79 | .data.read_mostly : { |
79 | __init_begin = .; | 80 | *(.data.read_mostly) |
80 | .init.text : { | 81 | } |
81 | _sinittext = .; | 82 | _edata = .; /* End of data section */ |
82 | *(.init.text) | 83 | |
83 | _einittext = .; | 84 | . = ALIGN(2 * PAGE_SIZE); /* init_task */ |
84 | } | 85 | .data.init_task : { |
85 | /* | 86 | *(.data.init_task) |
86 | * .exit.text is discarded at runtime, not link time, | 87 | } |
87 | * to deal with references from __bug_table | 88 | |
88 | */ | 89 | /* will be freed after init */ |
89 | .exit.text : { *(.exit.text) } | 90 | . = ALIGN(PAGE_SIZE); /* Init code and data */ |
90 | 91 | __init_begin = .; | |
91 | .init.data : { *(.init.data) } | 92 | .init.text : { |
92 | . = ALIGN(256); | 93 | _sinittext = .; |
93 | __setup_start = .; | 94 | *(.init.text) |
94 | .init.setup : { *(.init.setup) } | 95 | _einittext = .; |
95 | __setup_end = .; | 96 | } |
96 | __initcall_start = .; | 97 | /* |
97 | .initcall.init : { | 98 | * .exit.text is discarded at runtime, not link time, |
98 | INITCALLS | 99 | * to deal with references from __bug_table |
99 | } | 100 | */ |
100 | __initcall_end = .; | 101 | .exit.text : { |
101 | __con_initcall_start = .; | 102 | *(.exit.text) |
102 | .con_initcall.init : { *(.con_initcall.init) } | 103 | } |
103 | __con_initcall_end = .; | 104 | |
104 | SECURITY_INIT | 105 | .init.data : { |
106 | *(.init.data) | ||
107 | } | ||
108 | . = ALIGN(0x100); | ||
109 | .init.setup : { | ||
110 | __setup_start = .; | ||
111 | *(.init.setup) | ||
112 | __setup_end = .; | ||
113 | } | ||
114 | .initcall.init : { | ||
115 | __initcall_start = .; | ||
116 | INITCALLS | ||
117 | __initcall_end = .; | ||
118 | } | ||
119 | |||
120 | .con_initcall.init : { | ||
121 | __con_initcall_start = .; | ||
122 | *(.con_initcall.init) | ||
123 | __con_initcall_end = .; | ||
124 | } | ||
125 | SECURITY_INIT | ||
105 | 126 | ||
106 | #ifdef CONFIG_BLK_DEV_INITRD | 127 | #ifdef CONFIG_BLK_DEV_INITRD |
107 | . = ALIGN(256); | 128 | . = ALIGN(0x100); |
108 | __initramfs_start = .; | 129 | .init.ramfs : { |
109 | .init.ramfs : { *(.init.initramfs) } | 130 | __initramfs_start = .; |
110 | . = ALIGN(2); | 131 | *(.init.ramfs) |
111 | __initramfs_end = .; | 132 | . = ALIGN(2); |
133 | __initramfs_end = .; | ||
134 | } | ||
112 | #endif | 135 | #endif |
113 | PERCPU(4096) | 136 | |
114 | . = ALIGN(4096); | 137 | PERCPU(PAGE_SIZE) |
115 | __init_end = .; | 138 | . = ALIGN(PAGE_SIZE); |
116 | /* freed after init ends here */ | 139 | __init_end = .; /* freed after init ends here */ |
117 | 140 | ||
118 | __bss_start = .; /* BSS */ | 141 | /* BSS */ |
119 | .bss : { *(.bss) } | 142 | .bss : { |
120 | . = ALIGN(2); | 143 | __bss_start = .; |
121 | __bss_stop = .; | 144 | *(.bss) |
122 | 145 | . = ALIGN(2); | |
123 | _end = . ; | 146 | __bss_stop = .; |
124 | 147 | } | |
125 | /* Sections to be discarded */ | 148 | |
126 | /DISCARD/ : { | 149 | _end = . ; |
127 | *(.exit.data) *(.exitcall.exit) | 150 | |
128 | } | 151 | /* Sections to be discarded */ |
129 | 152 | /DISCARD/ : { | |
130 | /* Stabs debugging sections. */ | 153 | *(.exit.data) |
131 | .stab 0 : { *(.stab) } | 154 | *(.exitcall.exit) |
132 | .stabstr 0 : { *(.stabstr) } | 155 | } |
133 | .stab.excl 0 : { *(.stab.excl) } | 156 | |
134 | .stab.exclstr 0 : { *(.stab.exclstr) } | 157 | /* Debugging sections. */ |
135 | .stab.index 0 : { *(.stab.index) } | 158 | STABS_DEBUG |
136 | .stab.indexstr 0 : { *(.stab.indexstr) } | 159 | DWARF_DEBUG |
137 | .comment 0 : { *(.comment) } | ||
138 | } | 160 | } |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 54055194e9af..4c1ac341ec80 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -468,7 +468,7 @@ typedef struct { | |||
468 | __u64 refselmk; | 468 | __u64 refselmk; |
469 | __u64 refcmpmk; | 469 | __u64 refcmpmk; |
470 | __u64 reserved; | 470 | __u64 reserved; |
471 | } __attribute__ ((packed)) pfault_refbk_t; | 471 | } __attribute__ ((packed, aligned(8))) pfault_refbk_t; |
472 | 472 | ||
473 | int pfault_init(void) | 473 | int pfault_init(void) |
474 | { | 474 | { |
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index e61890217c50..71d1c427b907 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c | |||
@@ -93,7 +93,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
93 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | 93 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; |
94 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 94 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
95 | 95 | ||
96 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
97 | policy->cur = sh_cpufreq_get(policy->cpu); | 96 | policy->cur = sh_cpufreq_get(policy->cpu); |
98 | policy->min = policy->cpuinfo.min_freq; | 97 | policy->min = policy->cpuinfo.min_freq; |
99 | policy->max = policy->cpuinfo.max_freq; | 98 | policy->max = policy->cpuinfo.max_freq; |
diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c index 1f83fe6a82d6..791c15138f3a 100644 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ b/arch/sparc64/kernel/us2e_cpufreq.c | |||
@@ -326,7 +326,6 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) | |||
326 | table[2].index = 5; | 326 | table[2].index = 5; |
327 | table[3].frequency = CPUFREQ_TABLE_END; | 327 | table[3].frequency = CPUFREQ_TABLE_END; |
328 | 328 | ||
329 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
330 | policy->cpuinfo.transition_latency = 0; | 329 | policy->cpuinfo.transition_latency = 0; |
331 | policy->cur = clock_tick; | 330 | policy->cur = clock_tick; |
332 | 331 | ||
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index c624193740fd..7ff02063b858 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 | |||
@@ -7,7 +7,7 @@ extra-y := head_32.o init_task_32.o vmlinux.lds | |||
7 | obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ | 7 | obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ |
8 | ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ | 8 | ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ |
9 | pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ | 9 | pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ |
10 | quirks.o i8237.o topology.o alternative.o i8253_32.o tsc_32.o | 10 | quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o |
11 | 11 | ||
12 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 12 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
13 | obj-y += cpu/ | 13 | obj-y += cpu/ |
@@ -37,9 +37,9 @@ obj-$(CONFIG_EFI) += efi_32.o efi_stub_32.o | |||
37 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | 37 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o |
38 | obj-$(CONFIG_VM86) += vm86_32.o | 38 | obj-$(CONFIG_VM86) += vm86_32.o |
39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
40 | obj-$(CONFIG_HPET_TIMER) += hpet_32.o | 40 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
41 | obj-$(CONFIG_K8_NB) += k8.o | 41 | obj-$(CONFIG_K8_NB) += k8.o |
42 | obj-$(CONFIG_MGEODE_LX) += geode_32.o | 42 | obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o |
43 | 43 | ||
44 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o | 44 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o |
45 | obj-$(CONFIG_PARAVIRT) += paravirt_32.o | 45 | obj-$(CONFIG_PARAVIRT) += paravirt_32.o |
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 3ab017a0a3b9..43da66213a47 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 | |||
@@ -8,8 +8,8 @@ obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ | |||
8 | ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ | 8 | ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ |
9 | x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ | 9 | x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ |
10 | setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ | 10 | setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ |
11 | pci-dma_64.o pci-nommu_64.o alternative.o hpet_64.o tsc_64.o bugs_64.o \ | 11 | pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \ |
12 | perfctr-watchdog.o | 12 | perfctr-watchdog.o i8253.o |
13 | 13 | ||
14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
15 | obj-$(CONFIG_X86_MCE) += mce_64.o therm_throt.o | 15 | obj-$(CONFIG_X86_MCE) += mce_64.o therm_throt.o |
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 925758dbca0c..395928de28ea 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sysdev.h> | 25 | #include <linux/sysdev.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/clockchips.h> | ||
28 | 29 | ||
29 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
30 | #include <asm/smp.h> | 31 | #include <asm/smp.h> |
@@ -39,12 +40,9 @@ | |||
39 | #include <asm/hpet.h> | 40 | #include <asm/hpet.h> |
40 | #include <asm/apic.h> | 41 | #include <asm/apic.h> |
41 | 42 | ||
42 | int apic_mapped; | ||
43 | int apic_verbosity; | 43 | int apic_verbosity; |
44 | int apic_runs_main_timer; | 44 | int disable_apic_timer __cpuinitdata; |
45 | int apic_calibrate_pmtmr __initdata; | 45 | static int apic_calibrate_pmtmr __initdata; |
46 | |||
47 | int disable_apic_timer __initdata; | ||
48 | 46 | ||
49 | /* Local APIC timer works in C2? */ | 47 | /* Local APIC timer works in C2? */ |
50 | int local_apic_timer_c2_ok; | 48 | int local_apic_timer_c2_ok; |
@@ -56,14 +54,78 @@ static struct resource lapic_resource = { | |||
56 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | 54 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, |
57 | }; | 55 | }; |
58 | 56 | ||
57 | static unsigned int calibration_result; | ||
58 | |||
59 | static int lapic_next_event(unsigned long delta, | ||
60 | struct clock_event_device *evt); | ||
61 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
62 | struct clock_event_device *evt); | ||
63 | |||
64 | static void lapic_timer_broadcast(cpumask_t mask); | ||
65 | |||
66 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen); | ||
67 | |||
68 | static struct clock_event_device lapic_clockevent = { | ||
69 | .name = "lapic", | ||
70 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
71 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
72 | .shift = 32, | ||
73 | .set_mode = lapic_timer_setup, | ||
74 | .set_next_event = lapic_next_event, | ||
75 | .broadcast = lapic_timer_broadcast, | ||
76 | .rating = 100, | ||
77 | .irq = -1, | ||
78 | }; | ||
79 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
80 | |||
81 | static int lapic_next_event(unsigned long delta, | ||
82 | struct clock_event_device *evt) | ||
83 | { | ||
84 | apic_write(APIC_TMICT, delta); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
89 | struct clock_event_device *evt) | ||
90 | { | ||
91 | unsigned long flags; | ||
92 | unsigned int v; | ||
93 | |||
94 | /* Lapic used as dummy for broadcast ? */ | ||
95 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) | ||
96 | return; | ||
97 | |||
98 | local_irq_save(flags); | ||
99 | |||
100 | switch (mode) { | ||
101 | case CLOCK_EVT_MODE_PERIODIC: | ||
102 | case CLOCK_EVT_MODE_ONESHOT: | ||
103 | __setup_APIC_LVTT(calibration_result, | ||
104 | mode != CLOCK_EVT_MODE_PERIODIC, 1); | ||
105 | break; | ||
106 | case CLOCK_EVT_MODE_UNUSED: | ||
107 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
108 | v = apic_read(APIC_LVTT); | ||
109 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
110 | apic_write(APIC_LVTT, v); | ||
111 | break; | ||
112 | case CLOCK_EVT_MODE_RESUME: | ||
113 | /* Nothing to do here */ | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | local_irq_restore(flags); | ||
118 | } | ||
119 | |||
59 | /* | 120 | /* |
60 | * cpu_mask that denotes the CPUs that needs timer interrupt coming in as | 121 | * Local APIC timer broadcast function |
61 | * IPIs in place of local APIC timers | ||
62 | */ | 122 | */ |
63 | static cpumask_t timer_interrupt_broadcast_ipi_mask; | 123 | static void lapic_timer_broadcast(cpumask_t mask) |
64 | 124 | { | |
65 | /* Using APIC to generate smp_local_timer_interrupt? */ | 125 | #ifdef CONFIG_SMP |
66 | int using_apic_timer __read_mostly = 0; | 126 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); |
127 | #endif | ||
128 | } | ||
67 | 129 | ||
68 | static void apic_pm_activate(void); | 130 | static void apic_pm_activate(void); |
69 | 131 | ||
@@ -184,7 +246,10 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
184 | apic_write(APIC_SPIV, value); | 246 | apic_write(APIC_SPIV, value); |
185 | 247 | ||
186 | if (!virt_wire_setup) { | 248 | if (!virt_wire_setup) { |
187 | /* For LVT0 make it edge triggered, active high, external and enabled */ | 249 | /* |
250 | * For LVT0 make it edge triggered, active high, | ||
251 | * external and enabled | ||
252 | */ | ||
188 | value = apic_read(APIC_LVT0); | 253 | value = apic_read(APIC_LVT0); |
189 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | 254 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | |
190 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | 255 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | |
@@ -420,10 +485,12 @@ void __cpuinit setup_local_APIC (void) | |||
420 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | 485 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; |
421 | if (!smp_processor_id() && !value) { | 486 | if (!smp_processor_id() && !value) { |
422 | value = APIC_DM_EXTINT; | 487 | value = APIC_DM_EXTINT; |
423 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id()); | 488 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", |
489 | smp_processor_id()); | ||
424 | } else { | 490 | } else { |
425 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | 491 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; |
426 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id()); | 492 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", |
493 | smp_processor_id()); | ||
427 | } | 494 | } |
428 | apic_write(APIC_LVT0, value); | 495 | apic_write(APIC_LVT0, value); |
429 | 496 | ||
@@ -706,8 +773,8 @@ void __init init_apic_mappings(void) | |||
706 | apic_phys = mp_lapic_addr; | 773 | apic_phys = mp_lapic_addr; |
707 | 774 | ||
708 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 775 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); |
709 | apic_mapped = 1; | 776 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", |
710 | apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); | 777 | APIC_BASE, apic_phys); |
711 | 778 | ||
712 | /* Put local APIC into the resource map. */ | 779 | /* Put local APIC into the resource map. */ |
713 | lapic_resource.start = apic_phys; | 780 | lapic_resource.start = apic_phys; |
@@ -730,12 +797,14 @@ void __init init_apic_mappings(void) | |||
730 | if (smp_found_config) { | 797 | if (smp_found_config) { |
731 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; | 798 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; |
732 | } else { | 799 | } else { |
733 | ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | 800 | ioapic_phys = (unsigned long) |
801 | alloc_bootmem_pages(PAGE_SIZE); | ||
734 | ioapic_phys = __pa(ioapic_phys); | 802 | ioapic_phys = __pa(ioapic_phys); |
735 | } | 803 | } |
736 | set_fixmap_nocache(idx, ioapic_phys); | 804 | set_fixmap_nocache(idx, ioapic_phys); |
737 | apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n", | 805 | apic_printk(APIC_VERBOSE, |
738 | __fix_to_virt(idx), ioapic_phys); | 806 | "mapped IOAPIC to %016lx (%016lx)\n", |
807 | __fix_to_virt(idx), ioapic_phys); | ||
739 | idx++; | 808 | idx++; |
740 | 809 | ||
741 | if (ioapic_res != NULL) { | 810 | if (ioapic_res != NULL) { |
@@ -758,16 +827,14 @@ void __init init_apic_mappings(void) | |||
758 | * P5 APIC double write bug. | 827 | * P5 APIC double write bug. |
759 | */ | 828 | */ |
760 | 829 | ||
761 | #define APIC_DIVISOR 16 | 830 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) |
762 | |||
763 | static void __setup_APIC_LVTT(unsigned int clocks) | ||
764 | { | 831 | { |
765 | unsigned int lvtt_value, tmp_value; | 832 | unsigned int lvtt_value, tmp_value; |
766 | int cpu = smp_processor_id(); | ||
767 | 833 | ||
768 | lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; | 834 | lvtt_value = LOCAL_TIMER_VECTOR; |
769 | 835 | if (!oneshot) | |
770 | if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) | 836 | lvtt_value |= APIC_LVT_TIMER_PERIODIC; |
837 | if (!irqen) | ||
771 | lvtt_value |= APIC_LVT_MASKED; | 838 | lvtt_value |= APIC_LVT_MASKED; |
772 | 839 | ||
773 | apic_write(APIC_LVTT, lvtt_value); | 840 | apic_write(APIC_LVTT, lvtt_value); |
@@ -780,44 +847,18 @@ static void __setup_APIC_LVTT(unsigned int clocks) | |||
780 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | 847 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) |
781 | | APIC_TDR_DIV_16); | 848 | | APIC_TDR_DIV_16); |
782 | 849 | ||
783 | apic_write(APIC_TMICT, clocks/APIC_DIVISOR); | 850 | if (!oneshot) |
851 | apic_write(APIC_TMICT, clocks); | ||
784 | } | 852 | } |
785 | 853 | ||
786 | static void setup_APIC_timer(unsigned int clocks) | 854 | static void setup_APIC_timer(void) |
787 | { | 855 | { |
788 | unsigned long flags; | 856 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
789 | 857 | ||
790 | local_irq_save(flags); | 858 | memcpy(levt, &lapic_clockevent, sizeof(*levt)); |
859 | levt->cpumask = cpumask_of_cpu(smp_processor_id()); | ||
791 | 860 | ||
792 | /* wait for irq slice */ | 861 | clockevents_register_device(levt); |
793 | if (hpet_address && hpet_use_timer) { | ||
794 | u32 trigger = hpet_readl(HPET_T0_CMP); | ||
795 | while (hpet_readl(HPET_T0_CMP) == trigger) | ||
796 | /* do nothing */ ; | ||
797 | } else { | ||
798 | int c1, c2; | ||
799 | outb_p(0x00, 0x43); | ||
800 | c2 = inb_p(0x40); | ||
801 | c2 |= inb_p(0x40) << 8; | ||
802 | do { | ||
803 | c1 = c2; | ||
804 | outb_p(0x00, 0x43); | ||
805 | c2 = inb_p(0x40); | ||
806 | c2 |= inb_p(0x40) << 8; | ||
807 | } while (c2 - c1 < 300); | ||
808 | } | ||
809 | __setup_APIC_LVTT(clocks); | ||
810 | /* Turn off PIT interrupt if we use APIC timer as main timer. | ||
811 | Only works with the PM timer right now | ||
812 | TBD fix it for HPET too. */ | ||
813 | if ((pmtmr_ioport != 0) && | ||
814 | smp_processor_id() == boot_cpu_id && | ||
815 | apic_runs_main_timer == 1 && | ||
816 | !cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) { | ||
817 | stop_timer_interrupt(); | ||
818 | apic_runs_main_timer++; | ||
819 | } | ||
820 | local_irq_restore(flags); | ||
821 | } | 862 | } |
822 | 863 | ||
823 | /* | 864 | /* |
@@ -835,17 +876,22 @@ static void setup_APIC_timer(unsigned int clocks) | |||
835 | 876 | ||
836 | #define TICK_COUNT 100000000 | 877 | #define TICK_COUNT 100000000 |
837 | 878 | ||
838 | static int __init calibrate_APIC_clock(void) | 879 | static void __init calibrate_APIC_clock(void) |
839 | { | 880 | { |
840 | unsigned apic, apic_start; | 881 | unsigned apic, apic_start; |
841 | unsigned long tsc, tsc_start; | 882 | unsigned long tsc, tsc_start; |
842 | int result; | 883 | int result; |
884 | |||
885 | local_irq_disable(); | ||
886 | |||
843 | /* | 887 | /* |
844 | * Put whatever arbitrary (but long enough) timeout | 888 | * Put whatever arbitrary (but long enough) timeout |
845 | * value into the APIC clock, we just want to get the | 889 | * value into the APIC clock, we just want to get the |
846 | * counter running for calibration. | 890 | * counter running for calibration. |
891 | * | ||
892 | * No interrupt enable ! | ||
847 | */ | 893 | */ |
848 | __setup_APIC_LVTT(4000000000); | 894 | __setup_APIC_LVTT(250000000, 0, 0); |
849 | 895 | ||
850 | apic_start = apic_read(APIC_TMCCT); | 896 | apic_start = apic_read(APIC_TMCCT); |
851 | #ifdef CONFIG_X86_PM_TIMER | 897 | #ifdef CONFIG_X86_PM_TIMER |
@@ -867,123 +913,62 @@ static int __init calibrate_APIC_clock(void) | |||
867 | result = (apic_start - apic) * 1000L * tsc_khz / | 913 | result = (apic_start - apic) * 1000L * tsc_khz / |
868 | (tsc - tsc_start); | 914 | (tsc - tsc_start); |
869 | } | 915 | } |
870 | printk("result %d\n", result); | ||
871 | 916 | ||
917 | local_irq_enable(); | ||
918 | |||
919 | printk(KERN_DEBUG "APIC timer calibration result %d\n", result); | ||
872 | 920 | ||
873 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", | 921 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", |
874 | result / 1000 / 1000, result / 1000 % 1000); | 922 | result / 1000 / 1000, result / 1000 % 1000); |
875 | 923 | ||
876 | return result * APIC_DIVISOR / HZ; | 924 | /* Calculate the scaled math multiplication factor */ |
877 | } | 925 | lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32); |
926 | lapic_clockevent.max_delta_ns = | ||
927 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | ||
928 | lapic_clockevent.min_delta_ns = | ||
929 | clockevent_delta2ns(0xF, &lapic_clockevent); | ||
878 | 930 | ||
879 | static unsigned int calibration_result; | 931 | calibration_result = result / HZ; |
932 | } | ||
880 | 933 | ||
881 | void __init setup_boot_APIC_clock (void) | 934 | void __init setup_boot_APIC_clock (void) |
882 | { | 935 | { |
936 | /* | ||
937 | * The local apic timer can be disabled via the kernel commandline. | ||
938 | * Register the lapic timer as a dummy clock event source on SMP | ||
939 | * systems, so the broadcast mechanism is used. On UP systems simply | ||
940 | * ignore it. | ||
941 | */ | ||
883 | if (disable_apic_timer) { | 942 | if (disable_apic_timer) { |
884 | printk(KERN_INFO "Disabling APIC timer\n"); | 943 | printk(KERN_INFO "Disabling APIC timer\n"); |
944 | /* No broadcast on UP ! */ | ||
945 | if (num_possible_cpus() > 1) | ||
946 | setup_APIC_timer(); | ||
885 | return; | 947 | return; |
886 | } | 948 | } |
887 | 949 | ||
888 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); | 950 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); |
889 | using_apic_timer = 1; | 951 | calibrate_APIC_clock(); |
890 | |||
891 | local_irq_disable(); | ||
892 | 952 | ||
893 | calibration_result = calibrate_APIC_clock(); | ||
894 | /* | 953 | /* |
895 | * Now set up the timer for real. | 954 | * If nmi_watchdog is set to IO_APIC, we need the |
955 | * PIT/HPET going. Otherwise register lapic as a dummy | ||
956 | * device. | ||
896 | */ | 957 | */ |
897 | setup_APIC_timer(calibration_result); | 958 | if (nmi_watchdog != NMI_IO_APIC) |
959 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | ||
960 | else | ||
961 | printk(KERN_WARNING "APIC timer registered as dummy," | ||
962 | " due to nmi_watchdog=1!\n"); | ||
898 | 963 | ||
899 | local_irq_enable(); | 964 | setup_APIC_timer(); |
900 | } | 965 | } |
901 | 966 | ||
902 | void __cpuinit setup_secondary_APIC_clock(void) | 967 | void __cpuinit setup_secondary_APIC_clock(void) |
903 | { | 968 | { |
904 | local_irq_disable(); /* FIXME: Do we need this? --RR */ | 969 | setup_APIC_timer(); |
905 | setup_APIC_timer(calibration_result); | ||
906 | local_irq_enable(); | ||
907 | } | 970 | } |
908 | 971 | ||
909 | void disable_APIC_timer(void) | ||
910 | { | ||
911 | if (using_apic_timer) { | ||
912 | unsigned long v; | ||
913 | |||
914 | v = apic_read(APIC_LVTT); | ||
915 | /* | ||
916 | * When an illegal vector value (0-15) is written to an LVT | ||
917 | * entry and delivery mode is Fixed, the APIC may signal an | ||
918 | * illegal vector error, with out regard to whether the mask | ||
919 | * bit is set or whether an interrupt is actually seen on input. | ||
920 | * | ||
921 | * Boot sequence might call this function when the LVTT has | ||
922 | * '0' vector value. So make sure vector field is set to | ||
923 | * valid value. | ||
924 | */ | ||
925 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
926 | apic_write(APIC_LVTT, v); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | void enable_APIC_timer(void) | ||
931 | { | ||
932 | int cpu = smp_processor_id(); | ||
933 | |||
934 | if (using_apic_timer && | ||
935 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
936 | unsigned long v; | ||
937 | |||
938 | v = apic_read(APIC_LVTT); | ||
939 | apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | void switch_APIC_timer_to_ipi(void *cpumask) | ||
944 | { | ||
945 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
946 | int cpu = smp_processor_id(); | ||
947 | |||
948 | if (cpu_isset(cpu, mask) && | ||
949 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
950 | disable_APIC_timer(); | ||
951 | cpu_set(cpu, timer_interrupt_broadcast_ipi_mask); | ||
952 | } | ||
953 | } | ||
954 | EXPORT_SYMBOL(switch_APIC_timer_to_ipi); | ||
955 | |||
956 | void smp_send_timer_broadcast_ipi(void) | ||
957 | { | ||
958 | int cpu = smp_processor_id(); | ||
959 | cpumask_t mask; | ||
960 | |||
961 | cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); | ||
962 | |||
963 | if (cpu_isset(cpu, mask)) { | ||
964 | cpu_clear(cpu, mask); | ||
965 | add_pda(apic_timer_irqs, 1); | ||
966 | smp_local_timer_interrupt(); | ||
967 | } | ||
968 | |||
969 | if (!cpus_empty(mask)) { | ||
970 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); | ||
971 | } | ||
972 | } | ||
973 | |||
974 | void switch_ipi_to_APIC_timer(void *cpumask) | ||
975 | { | ||
976 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
977 | int cpu = smp_processor_id(); | ||
978 | |||
979 | if (cpu_isset(cpu, mask) && | ||
980 | cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
981 | cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask); | ||
982 | enable_APIC_timer(); | ||
983 | } | ||
984 | } | ||
985 | EXPORT_SYMBOL(switch_ipi_to_APIC_timer); | ||
986 | |||
987 | int setup_profiling_timer(unsigned int multiplier) | 972 | int setup_profiling_timer(unsigned int multiplier) |
988 | { | 973 | { |
989 | return -EINVAL; | 974 | return -EINVAL; |
@@ -997,8 +982,6 @@ void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | |||
997 | apic_write(reg, v); | 982 | apic_write(reg, v); |
998 | } | 983 | } |
999 | 984 | ||
1000 | #undef APIC_DIVISOR | ||
1001 | |||
1002 | /* | 985 | /* |
1003 | * Local timer interrupt handler. It does both profiling and | 986 | * Local timer interrupt handler. It does both profiling and |
1004 | * process statistics/rescheduling. | 987 | * process statistics/rescheduling. |
@@ -1011,22 +994,34 @@ void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | |||
1011 | 994 | ||
1012 | void smp_local_timer_interrupt(void) | 995 | void smp_local_timer_interrupt(void) |
1013 | { | 996 | { |
1014 | profile_tick(CPU_PROFILING); | 997 | int cpu = smp_processor_id(); |
1015 | #ifdef CONFIG_SMP | 998 | struct clock_event_device *evt = &per_cpu(lapic_events, cpu); |
1016 | update_process_times(user_mode(get_irq_regs())); | 999 | |
1017 | #endif | ||
1018 | if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id) | ||
1019 | main_timer_handler(); | ||
1020 | /* | 1000 | /* |
1021 | * We take the 'long' return path, and there every subsystem | 1001 | * Normally we should not be here till LAPIC has been initialized but |
1022 | * grabs the appropriate locks (kernel lock/ irq lock). | 1002 | * in some cases like kdump, its possible that there is a pending LAPIC |
1003 | * timer interrupt from previous kernel's context and is delivered in | ||
1004 | * new kernel the moment interrupts are enabled. | ||
1023 | * | 1005 | * |
1024 | * We might want to decouple profiling from the 'long path', | 1006 | * Interrupts are enabled early and LAPIC is setup much later, hence |
1025 | * and do the profiling totally in assembly. | 1007 | * its possible that when we get here evt->event_handler is NULL. |
1026 | * | 1008 | * Check for event_handler being NULL and discard the interrupt as |
1027 | * Currently this isn't too much of an issue (performance wise), | 1009 | * spurious. |
1028 | * we can take more than 100K local irqs per second on a 100 MHz P5. | 1010 | */ |
1011 | if (!evt->event_handler) { | ||
1012 | printk(KERN_WARNING | ||
1013 | "Spurious LAPIC timer interrupt on cpu %d\n", cpu); | ||
1014 | /* Switch it off */ | ||
1015 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); | ||
1016 | return; | ||
1017 | } | ||
1018 | |||
1019 | /* | ||
1020 | * the NMI deadlock-detector uses this. | ||
1029 | */ | 1021 | */ |
1022 | add_pda(apic_timer_irqs, 1); | ||
1023 | |||
1024 | evt->event_handler(evt); | ||
1030 | } | 1025 | } |
1031 | 1026 | ||
1032 | /* | 1027 | /* |
@@ -1042,11 +1037,6 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) | |||
1042 | struct pt_regs *old_regs = set_irq_regs(regs); | 1037 | struct pt_regs *old_regs = set_irq_regs(regs); |
1043 | 1038 | ||
1044 | /* | 1039 | /* |
1045 | * the NMI deadlock-detector uses this. | ||
1046 | */ | ||
1047 | add_pda(apic_timer_irqs, 1); | ||
1048 | |||
1049 | /* | ||
1050 | * NOTE! We'd better ACK the irq immediately, | 1040 | * NOTE! We'd better ACK the irq immediately, |
1051 | * because timer handling can be slow. | 1041 | * because timer handling can be slow. |
1052 | */ | 1042 | */ |
@@ -1225,29 +1215,13 @@ static __init int setup_noapictimer(char *str) | |||
1225 | disable_apic_timer = 1; | 1215 | disable_apic_timer = 1; |
1226 | return 1; | 1216 | return 1; |
1227 | } | 1217 | } |
1228 | 1218 | __setup("noapictimer", setup_noapictimer); | |
1229 | static __init int setup_apicmaintimer(char *str) | ||
1230 | { | ||
1231 | apic_runs_main_timer = 1; | ||
1232 | nohpet = 1; | ||
1233 | return 1; | ||
1234 | } | ||
1235 | __setup("apicmaintimer", setup_apicmaintimer); | ||
1236 | |||
1237 | static __init int setup_noapicmaintimer(char *str) | ||
1238 | { | ||
1239 | apic_runs_main_timer = -1; | ||
1240 | return 1; | ||
1241 | } | ||
1242 | __setup("noapicmaintimer", setup_noapicmaintimer); | ||
1243 | 1219 | ||
1244 | static __init int setup_apicpmtimer(char *s) | 1220 | static __init int setup_apicpmtimer(char *s) |
1245 | { | 1221 | { |
1246 | apic_calibrate_pmtmr = 1; | 1222 | apic_calibrate_pmtmr = 1; |
1247 | notsc_setup(NULL); | 1223 | notsc_setup(NULL); |
1248 | return setup_apicmaintimer(NULL); | 1224 | return 0; |
1249 | } | 1225 | } |
1250 | __setup("apicpmtimer", setup_apicpmtimer); | 1226 | __setup("apicpmtimer", setup_apicpmtimer); |
1251 | 1227 | ||
1252 | __setup("noapictimer", setup_noapictimer); | ||
1253 | |||
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index b6434a7ef8b2..ffd01e5dcb52 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -646,7 +646,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
646 | policy->cpuinfo.transition_latency = | 646 | policy->cpuinfo.transition_latency = |
647 | perf->states[i].transition_latency * 1000; | 647 | perf->states[i].transition_latency * 1000; |
648 | } | 648 | } |
649 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
650 | 649 | ||
651 | data->max_freq = perf->states[0].core_frequency * 1000; | 650 | data->max_freq = perf->states[0].core_frequency * 1000; |
652 | /* table init */ | 651 | /* table init */ |
diff --git a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c index 66acd5039918..32f0bda3fc95 100644 --- a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c | |||
@@ -363,7 +363,6 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) | |||
363 | policy->cur = nforce2_get(policy->cpu); | 363 | policy->cur = nforce2_get(policy->cpu); |
364 | policy->min = policy->cpuinfo.min_freq; | 364 | policy->min = policy->cpuinfo.min_freq; |
365 | policy->max = policy->cpuinfo.max_freq; | 365 | policy->max = policy->cpuinfo.max_freq; |
366 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
367 | 366 | ||
368 | return 0; | 367 | return 0; |
369 | } | 368 | } |
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c index f43d98e11cc7..c11baaf9f2b4 100644 --- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c +++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c | |||
@@ -253,7 +253,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy) | |||
253 | f_table[k].frequency = CPUFREQ_TABLE_END; | 253 | f_table[k].frequency = CPUFREQ_TABLE_END; |
254 | } | 254 | } |
255 | 255 | ||
256 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
257 | policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ | 256 | policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ |
258 | policy->cur = fsb * current_multiplier; | 257 | policy->cur = fsb * current_multiplier; |
259 | 258 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index f317276afa7a..1e7ae7dafcf6 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c | |||
@@ -219,7 +219,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) | |||
219 | } | 219 | } |
220 | 220 | ||
221 | /* cpuinfo and default policy values */ | 221 | /* cpuinfo and default policy values */ |
222 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
223 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 222 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
224 | policy->cur = elanfreq_get_cpu_frequency(0); | 223 | policy->cur = elanfreq_get_cpu_frequency(0); |
225 | 224 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c index 461dabc4e495..ed2bda127c44 100644 --- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c | |||
@@ -420,7 +420,6 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) | |||
420 | policy->min = maxfreq / POLICY_MIN_DIV; | 420 | policy->min = maxfreq / POLICY_MIN_DIV; |
421 | policy->max = maxfreq; | 421 | policy->max = maxfreq; |
422 | policy->cur = curfreq; | 422 | policy->cur = curfreq; |
423 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
424 | policy->cpuinfo.min_freq = maxfreq / max_duration; | 423 | policy->cpuinfo.min_freq = maxfreq / max_duration; |
425 | policy->cpuinfo.max_freq = maxfreq; | 424 | policy->cpuinfo.max_freq = maxfreq; |
426 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 425 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c index f0cce3c2dc3a..5045f5d583c8 100644 --- a/arch/x86/kernel/cpu/cpufreq/longhaul.c +++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c | |||
@@ -710,6 +710,10 @@ static int enable_arbiter_disable(void) | |||
710 | reg = 0x78; | 710 | reg = 0x78; |
711 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, | 711 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, |
712 | NULL); | 712 | NULL); |
713 | /* Find PM133/VT8605 host bridge */ | ||
714 | if (dev == NULL) | ||
715 | dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
716 | PCI_DEVICE_ID_VIA_8605_0, NULL); | ||
713 | /* Find CLE266 host bridge */ | 717 | /* Find CLE266 host bridge */ |
714 | if (dev == NULL) { | 718 | if (dev == NULL) { |
715 | reg = 0x76; | 719 | reg = 0x76; |
@@ -918,7 +922,6 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
918 | if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0)) | 922 | if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0)) |
919 | longhaul_setup_voltagescaling(); | 923 | longhaul_setup_voltagescaling(); |
920 | 924 | ||
921 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
922 | policy->cpuinfo.transition_latency = 200000; /* nsec */ | 925 | policy->cpuinfo.transition_latency = 200000; /* nsec */ |
923 | policy->cur = calc_speed(longhaul_get_cpu_mult()); | 926 | policy->cur = calc_speed(longhaul_get_cpu_mult()); |
924 | 927 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 4c76b511e194..8eb414b906d2 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | |||
@@ -229,7 +229,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) | |||
229 | cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); | 229 | cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); |
230 | 230 | ||
231 | /* cpuinfo and default policy values */ | 231 | /* cpuinfo and default policy values */ |
232 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
233 | policy->cpuinfo.transition_latency = 1000000; /* assumed */ | 232 | policy->cpuinfo.transition_latency = 1000000; /* assumed */ |
234 | policy->cur = stock_freq; | 233 | policy->cur = stock_freq; |
235 | 234 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index f89524051e4a..6d0285339317 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c | |||
@@ -160,7 +160,6 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | |||
160 | } | 160 | } |
161 | 161 | ||
162 | /* cpuinfo and default policy values */ | 162 | /* cpuinfo and default policy values */ |
163 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
164 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 163 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
165 | policy->cur = busfreq * max_multiplier; | 164 | policy->cur = busfreq * max_multiplier; |
166 | 165 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c index ca3e1d341889..7decd6a50ffa 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c | |||
@@ -637,8 +637,6 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) | |||
637 | printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", | 637 | printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", |
638 | minimum_speed/1000, maximum_speed/1000); | 638 | minimum_speed/1000, maximum_speed/1000); |
639 | 639 | ||
640 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
641 | |||
642 | policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); | 640 | policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); |
643 | 641 | ||
644 | policy->cur = powernow_get(0); | 642 | policy->cur = powernow_get(0); |
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 34ed53a06730..b273b69cfddf 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -76,7 +76,10 @@ static u32 find_khz_freq_from_fid(u32 fid) | |||
76 | /* Return a frequency in MHz, given an input fid and did */ | 76 | /* Return a frequency in MHz, given an input fid and did */ |
77 | static u32 find_freq_from_fiddid(u32 fid, u32 did) | 77 | static u32 find_freq_from_fiddid(u32 fid, u32 did) |
78 | { | 78 | { |
79 | return 100 * (fid + 0x10) >> did; | 79 | if (current_cpu_data.x86 == 0x10) |
80 | return 100 * (fid + 0x10) >> did; | ||
81 | else | ||
82 | return 100 * (fid + 0x8) >> did; | ||
80 | } | 83 | } |
81 | 84 | ||
82 | static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) | 85 | static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) |
@@ -1208,7 +1211,6 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1208 | /* run on any CPU again */ | 1211 | /* run on any CPU again */ |
1209 | set_cpus_allowed(current, oldmask); | 1212 | set_cpus_allowed(current, oldmask); |
1210 | 1213 | ||
1211 | pol->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
1212 | if (cpu_family == CPU_HW_PSTATE) | 1214 | if (cpu_family == CPU_HW_PSTATE) |
1213 | pol->cpus = cpumask_of_cpu(pol->cpu); | 1215 | pol->cpus = cpumask_of_cpu(pol->cpu); |
1214 | else | 1216 | else |
@@ -1325,21 +1327,16 @@ static struct cpufreq_driver cpufreq_amd64_driver = { | |||
1325 | static int __cpuinit powernowk8_init(void) | 1327 | static int __cpuinit powernowk8_init(void) |
1326 | { | 1328 | { |
1327 | unsigned int i, supported_cpus = 0; | 1329 | unsigned int i, supported_cpus = 0; |
1328 | unsigned int booted_cores = 1; | ||
1329 | 1330 | ||
1330 | for_each_online_cpu(i) { | 1331 | for_each_online_cpu(i) { |
1331 | if (check_supported_cpu(i)) | 1332 | if (check_supported_cpu(i)) |
1332 | supported_cpus++; | 1333 | supported_cpus++; |
1333 | } | 1334 | } |
1334 | 1335 | ||
1335 | #ifdef CONFIG_SMP | ||
1336 | booted_cores = cpu_data[0].booted_cores; | ||
1337 | #endif | ||
1338 | |||
1339 | if (supported_cpus == num_online_cpus()) { | 1336 | if (supported_cpus == num_online_cpus()) { |
1340 | printk(KERN_INFO PFX "Found %d %s " | 1337 | printk(KERN_INFO PFX "Found %d %s " |
1341 | "processors (%d cpu cores) (" VERSION ")\n", | 1338 | "processors (%d cpu cores) (" VERSION ")\n", |
1342 | supported_cpus/booted_cores, | 1339 | num_online_nodes(), |
1343 | boot_cpu_data.x86_model_id, supported_cpus); | 1340 | boot_cpu_data.x86_model_id, supported_cpus); |
1344 | return cpufreq_register_driver(&cpufreq_amd64_driver); | 1341 | return cpufreq_register_driver(&cpufreq_amd64_driver); |
1345 | } | 1342 | } |
diff --git a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c index b8fb4b521c62..d9f3e90a7ae0 100644 --- a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c +++ b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c | |||
@@ -111,7 +111,6 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) | |||
111 | return -ENODEV; | 111 | return -ENODEV; |
112 | 112 | ||
113 | /* cpuinfo and default policy values */ | 113 | /* cpuinfo and default policy values */ |
114 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
115 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ | 114 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ |
116 | policy->cur = sc520_freq_get_cpu_frequency(0); | 115 | policy->cur = sc520_freq_get_cpu_frequency(0); |
117 | 116 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 6c5dc2c85aeb..811d47438546 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -393,7 +393,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
393 | 393 | ||
394 | freq = get_cur_freq(policy->cpu); | 394 | freq = get_cur_freq(policy->cpu); |
395 | 395 | ||
396 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
397 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ | 396 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ |
398 | policy->cur = freq; | 397 | policy->cur = freq; |
399 | 398 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index a5b2346faf1f..36685e8f7be1 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c | |||
@@ -348,7 +348,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) | |||
348 | (speed / 1000)); | 348 | (speed / 1000)); |
349 | 349 | ||
350 | /* cpuinfo and default policy values */ | 350 | /* cpuinfo and default policy values */ |
351 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
352 | policy->cur = speed; | 351 | policy->cur = speed; |
353 | 352 | ||
354 | result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); | 353 | result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index e1c509aa3054..f2b5a621d27b 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c | |||
@@ -290,7 +290,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) | |||
290 | (speed / 1000)); | 290 | (speed / 1000)); |
291 | 291 | ||
292 | /* cpuinfo and default policy values */ | 292 | /* cpuinfo and default policy values */ |
293 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
294 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 293 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
295 | policy->cur = speed; | 294 | policy->cur = speed; |
296 | 295 | ||
diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c index 41e8aec4c61d..f12d8c5d9809 100644 --- a/arch/x86/kernel/geode_32.c +++ b/arch/x86/kernel/geode_32.c | |||
@@ -145,10 +145,14 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event); | |||
145 | 145 | ||
146 | static int __init geode_southbridge_init(void) | 146 | static int __init geode_southbridge_init(void) |
147 | { | 147 | { |
148 | int timers; | ||
149 | |||
148 | if (!is_geode()) | 150 | if (!is_geode()) |
149 | return -ENODEV; | 151 | return -ENODEV; |
150 | 152 | ||
151 | init_lbars(); | 153 | init_lbars(); |
154 | timers = geode_mfgpt_detect(); | ||
155 | printk(KERN_INFO "geode: %d MFGPT timers available.\n", timers); | ||
152 | return 0; | 156 | return 0; |
153 | } | 157 | } |
154 | 158 | ||
diff --git a/arch/x86/kernel/hpet_32.c b/arch/x86/kernel/hpet.c index 533d4932bc79..f8367074da0d 100644 --- a/arch/x86/kernel/hpet_32.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/clocksource.h> | 1 | #include <linux/clocksource.h> |
2 | #include <linux/clockchips.h> | 2 | #include <linux/clockchips.h> |
3 | #include <linux/delay.h> | ||
3 | #include <linux/errno.h> | 4 | #include <linux/errno.h> |
4 | #include <linux/hpet.h> | 5 | #include <linux/hpet.h> |
5 | #include <linux/init.h> | 6 | #include <linux/init.h> |
@@ -7,11 +8,11 @@ | |||
7 | #include <linux/pm.h> | 8 | #include <linux/pm.h> |
8 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
9 | 10 | ||
11 | #include <asm/fixmap.h> | ||
10 | #include <asm/hpet.h> | 12 | #include <asm/hpet.h> |
13 | #include <asm/i8253.h> | ||
11 | #include <asm/io.h> | 14 | #include <asm/io.h> |
12 | 15 | ||
13 | extern struct clock_event_device *global_clock_event; | ||
14 | |||
15 | #define HPET_MASK CLOCKSOURCE_MASK(32) | 16 | #define HPET_MASK CLOCKSOURCE_MASK(32) |
16 | #define HPET_SHIFT 22 | 17 | #define HPET_SHIFT 22 |
17 | 18 | ||
@@ -22,9 +23,9 @@ extern struct clock_event_device *global_clock_event; | |||
22 | * HPET address is set in acpi/boot.c, when an ACPI entry exists | 23 | * HPET address is set in acpi/boot.c, when an ACPI entry exists |
23 | */ | 24 | */ |
24 | unsigned long hpet_address; | 25 | unsigned long hpet_address; |
25 | static void __iomem * hpet_virt_address; | 26 | static void __iomem *hpet_virt_address; |
26 | 27 | ||
27 | static inline unsigned long hpet_readl(unsigned long a) | 28 | unsigned long hpet_readl(unsigned long a) |
28 | { | 29 | { |
29 | return readl(hpet_virt_address + a); | 30 | return readl(hpet_virt_address + a); |
30 | } | 31 | } |
@@ -34,6 +35,36 @@ static inline void hpet_writel(unsigned long d, unsigned long a) | |||
34 | writel(d, hpet_virt_address + a); | 35 | writel(d, hpet_virt_address + a); |
35 | } | 36 | } |
36 | 37 | ||
38 | #ifdef CONFIG_X86_64 | ||
39 | |||
40 | #include <asm/pgtable.h> | ||
41 | |||
42 | static inline void hpet_set_mapping(void) | ||
43 | { | ||
44 | set_fixmap_nocache(FIX_HPET_BASE, hpet_address); | ||
45 | __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); | ||
46 | hpet_virt_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE); | ||
47 | } | ||
48 | |||
49 | static inline void hpet_clear_mapping(void) | ||
50 | { | ||
51 | hpet_virt_address = NULL; | ||
52 | } | ||
53 | |||
54 | #else | ||
55 | |||
56 | static inline void hpet_set_mapping(void) | ||
57 | { | ||
58 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | ||
59 | } | ||
60 | |||
61 | static inline void hpet_clear_mapping(void) | ||
62 | { | ||
63 | iounmap(hpet_virt_address); | ||
64 | hpet_virt_address = NULL; | ||
65 | } | ||
66 | #endif | ||
67 | |||
37 | /* | 68 | /* |
38 | * HPET command line enable / disable | 69 | * HPET command line enable / disable |
39 | */ | 70 | */ |
@@ -49,6 +80,13 @@ static int __init hpet_setup(char* str) | |||
49 | } | 80 | } |
50 | __setup("hpet=", hpet_setup); | 81 | __setup("hpet=", hpet_setup); |
51 | 82 | ||
83 | static int __init disable_hpet(char *str) | ||
84 | { | ||
85 | boot_hpet_disable = 1; | ||
86 | return 1; | ||
87 | } | ||
88 | __setup("nohpet", disable_hpet); | ||
89 | |||
52 | static inline int is_hpet_capable(void) | 90 | static inline int is_hpet_capable(void) |
53 | { | 91 | { |
54 | return (!boot_hpet_disable && hpet_address); | 92 | return (!boot_hpet_disable && hpet_address); |
@@ -83,7 +121,7 @@ static void hpet_reserve_platform_timers(unsigned long id) | |||
83 | 121 | ||
84 | memset(&hd, 0, sizeof (hd)); | 122 | memset(&hd, 0, sizeof (hd)); |
85 | hd.hd_phys_address = hpet_address; | 123 | hd.hd_phys_address = hpet_address; |
86 | hd.hd_address = hpet_virt_address; | 124 | hd.hd_address = hpet; |
87 | hd.hd_nirqs = nrtimers; | 125 | hd.hd_nirqs = nrtimers; |
88 | hd.hd_flags = HPET_DATA_PLATFORM; | 126 | hd.hd_flags = HPET_DATA_PLATFORM; |
89 | hpet_reserve_timer(&hd, 0); | 127 | hpet_reserve_timer(&hd, 0); |
@@ -111,9 +149,9 @@ static void hpet_reserve_platform_timers(unsigned long id) { } | |||
111 | */ | 149 | */ |
112 | static unsigned long hpet_period; | 150 | static unsigned long hpet_period; |
113 | 151 | ||
114 | static void hpet_set_mode(enum clock_event_mode mode, | 152 | static void hpet_legacy_set_mode(enum clock_event_mode mode, |
115 | struct clock_event_device *evt); | 153 | struct clock_event_device *evt); |
116 | static int hpet_next_event(unsigned long delta, | 154 | static int hpet_legacy_next_event(unsigned long delta, |
117 | struct clock_event_device *evt); | 155 | struct clock_event_device *evt); |
118 | 156 | ||
119 | /* | 157 | /* |
@@ -122,10 +160,11 @@ static int hpet_next_event(unsigned long delta, | |||
122 | static struct clock_event_device hpet_clockevent = { | 160 | static struct clock_event_device hpet_clockevent = { |
123 | .name = "hpet", | 161 | .name = "hpet", |
124 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 162 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
125 | .set_mode = hpet_set_mode, | 163 | .set_mode = hpet_legacy_set_mode, |
126 | .set_next_event = hpet_next_event, | 164 | .set_next_event = hpet_legacy_next_event, |
127 | .shift = 32, | 165 | .shift = 32, |
128 | .irq = 0, | 166 | .irq = 0, |
167 | .rating = 50, | ||
129 | }; | 168 | }; |
130 | 169 | ||
131 | static void hpet_start_counter(void) | 170 | static void hpet_start_counter(void) |
@@ -140,7 +179,18 @@ static void hpet_start_counter(void) | |||
140 | hpet_writel(cfg, HPET_CFG); | 179 | hpet_writel(cfg, HPET_CFG); |
141 | } | 180 | } |
142 | 181 | ||
143 | static void hpet_enable_int(void) | 182 | static void hpet_resume_device(void) |
183 | { | ||
184 | force_hpet_resume(); | ||
185 | } | ||
186 | |||
187 | static void hpet_restart_counter(void) | ||
188 | { | ||
189 | hpet_resume_device(); | ||
190 | hpet_start_counter(); | ||
191 | } | ||
192 | |||
193 | static void hpet_enable_legacy_int(void) | ||
144 | { | 194 | { |
145 | unsigned long cfg = hpet_readl(HPET_CFG); | 195 | unsigned long cfg = hpet_readl(HPET_CFG); |
146 | 196 | ||
@@ -149,7 +199,39 @@ static void hpet_enable_int(void) | |||
149 | hpet_legacy_int_enabled = 1; | 199 | hpet_legacy_int_enabled = 1; |
150 | } | 200 | } |
151 | 201 | ||
152 | static void hpet_set_mode(enum clock_event_mode mode, | 202 | static void hpet_legacy_clockevent_register(void) |
203 | { | ||
204 | uint64_t hpet_freq; | ||
205 | |||
206 | /* Start HPET legacy interrupts */ | ||
207 | hpet_enable_legacy_int(); | ||
208 | |||
209 | /* | ||
210 | * The period is a femto seconds value. We need to calculate the | ||
211 | * scaled math multiplication factor for nanosecond to hpet tick | ||
212 | * conversion. | ||
213 | */ | ||
214 | hpet_freq = 1000000000000000ULL; | ||
215 | do_div(hpet_freq, hpet_period); | ||
216 | hpet_clockevent.mult = div_sc((unsigned long) hpet_freq, | ||
217 | NSEC_PER_SEC, 32); | ||
218 | /* Calculate the min / max delta */ | ||
219 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | ||
220 | &hpet_clockevent); | ||
221 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | ||
222 | &hpet_clockevent); | ||
223 | |||
224 | /* | ||
225 | * Start hpet with the boot cpu mask and make it | ||
226 | * global after the IO_APIC has been initialized. | ||
227 | */ | ||
228 | hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); | ||
229 | clockevents_register_device(&hpet_clockevent); | ||
230 | global_clock_event = &hpet_clockevent; | ||
231 | printk(KERN_DEBUG "hpet clockevent registered\n"); | ||
232 | } | ||
233 | |||
234 | static void hpet_legacy_set_mode(enum clock_event_mode mode, | ||
153 | struct clock_event_device *evt) | 235 | struct clock_event_device *evt) |
154 | { | 236 | { |
155 | unsigned long cfg, cmp, now; | 237 | unsigned long cfg, cmp, now; |
@@ -190,12 +272,12 @@ static void hpet_set_mode(enum clock_event_mode mode, | |||
190 | break; | 272 | break; |
191 | 273 | ||
192 | case CLOCK_EVT_MODE_RESUME: | 274 | case CLOCK_EVT_MODE_RESUME: |
193 | hpet_enable_int(); | 275 | hpet_enable_legacy_int(); |
194 | break; | 276 | break; |
195 | } | 277 | } |
196 | } | 278 | } |
197 | 279 | ||
198 | static int hpet_next_event(unsigned long delta, | 280 | static int hpet_legacy_next_event(unsigned long delta, |
199 | struct clock_event_device *evt) | 281 | struct clock_event_device *evt) |
200 | { | 282 | { |
201 | unsigned long cnt; | 283 | unsigned long cnt; |
@@ -215,6 +297,13 @@ static cycle_t read_hpet(void) | |||
215 | return (cycle_t)hpet_readl(HPET_COUNTER); | 297 | return (cycle_t)hpet_readl(HPET_COUNTER); |
216 | } | 298 | } |
217 | 299 | ||
300 | #ifdef CONFIG_X86_64 | ||
301 | static cycle_t __vsyscall_fn vread_hpet(void) | ||
302 | { | ||
303 | return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0); | ||
304 | } | ||
305 | #endif | ||
306 | |||
218 | static struct clocksource clocksource_hpet = { | 307 | static struct clocksource clocksource_hpet = { |
219 | .name = "hpet", | 308 | .name = "hpet", |
220 | .rating = 250, | 309 | .rating = 250, |
@@ -222,61 +311,17 @@ static struct clocksource clocksource_hpet = { | |||
222 | .mask = HPET_MASK, | 311 | .mask = HPET_MASK, |
223 | .shift = HPET_SHIFT, | 312 | .shift = HPET_SHIFT, |
224 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 313 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
225 | .resume = hpet_start_counter, | 314 | .resume = hpet_restart_counter, |
315 | #ifdef CONFIG_X86_64 | ||
316 | .vread = vread_hpet, | ||
317 | #endif | ||
226 | }; | 318 | }; |
227 | 319 | ||
228 | /* | 320 | static int hpet_clocksource_register(void) |
229 | * Try to setup the HPET timer | ||
230 | */ | ||
231 | int __init hpet_enable(void) | ||
232 | { | 321 | { |
233 | unsigned long id; | ||
234 | uint64_t hpet_freq; | ||
235 | u64 tmp, start, now; | 322 | u64 tmp, start, now; |
236 | cycle_t t1; | 323 | cycle_t t1; |
237 | 324 | ||
238 | if (!is_hpet_capable()) | ||
239 | return 0; | ||
240 | |||
241 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | ||
242 | |||
243 | /* | ||
244 | * Read the period and check for a sane value: | ||
245 | */ | ||
246 | hpet_period = hpet_readl(HPET_PERIOD); | ||
247 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) | ||
248 | goto out_nohpet; | ||
249 | |||
250 | /* | ||
251 | * The period is a femto seconds value. We need to calculate the | ||
252 | * scaled math multiplication factor for nanosecond to hpet tick | ||
253 | * conversion. | ||
254 | */ | ||
255 | hpet_freq = 1000000000000000ULL; | ||
256 | do_div(hpet_freq, hpet_period); | ||
257 | hpet_clockevent.mult = div_sc((unsigned long) hpet_freq, | ||
258 | NSEC_PER_SEC, 32); | ||
259 | /* Calculate the min / max delta */ | ||
260 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | ||
261 | &hpet_clockevent); | ||
262 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | ||
263 | &hpet_clockevent); | ||
264 | |||
265 | /* | ||
266 | * Read the HPET ID register to retrieve the IRQ routing | ||
267 | * information and the number of channels | ||
268 | */ | ||
269 | id = hpet_readl(HPET_ID); | ||
270 | |||
271 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
272 | /* | ||
273 | * The legacy routing mode needs at least two channels, tick timer | ||
274 | * and the rtc emulation channel. | ||
275 | */ | ||
276 | if (!(id & HPET_ID_NUMBER)) | ||
277 | goto out_nohpet; | ||
278 | #endif | ||
279 | |||
280 | /* Start the counter */ | 325 | /* Start the counter */ |
281 | hpet_start_counter(); | 326 | hpet_start_counter(); |
282 | 327 | ||
@@ -298,7 +343,7 @@ int __init hpet_enable(void) | |||
298 | if (t1 == read_hpet()) { | 343 | if (t1 == read_hpet()) { |
299 | printk(KERN_WARNING | 344 | printk(KERN_WARNING |
300 | "HPET counter not counting. HPET disabled\n"); | 345 | "HPET counter not counting. HPET disabled\n"); |
301 | goto out_nohpet; | 346 | return -ENODEV; |
302 | } | 347 | } |
303 | 348 | ||
304 | /* Initialize and register HPET clocksource | 349 | /* Initialize and register HPET clocksource |
@@ -319,27 +364,84 @@ int __init hpet_enable(void) | |||
319 | 364 | ||
320 | clocksource_register(&clocksource_hpet); | 365 | clocksource_register(&clocksource_hpet); |
321 | 366 | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Try to setup the HPET timer | ||
372 | */ | ||
373 | int __init hpet_enable(void) | ||
374 | { | ||
375 | unsigned long id; | ||
376 | |||
377 | if (!is_hpet_capable()) | ||
378 | return 0; | ||
379 | |||
380 | hpet_set_mapping(); | ||
381 | |||
382 | /* | ||
383 | * Read the period and check for a sane value: | ||
384 | */ | ||
385 | hpet_period = hpet_readl(HPET_PERIOD); | ||
386 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) | ||
387 | goto out_nohpet; | ||
388 | |||
389 | /* | ||
390 | * Read the HPET ID register to retrieve the IRQ routing | ||
391 | * information and the number of channels | ||
392 | */ | ||
393 | id = hpet_readl(HPET_ID); | ||
394 | |||
395 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
396 | /* | ||
397 | * The legacy routing mode needs at least two channels, tick timer | ||
398 | * and the rtc emulation channel. | ||
399 | */ | ||
400 | if (!(id & HPET_ID_NUMBER)) | ||
401 | goto out_nohpet; | ||
402 | #endif | ||
403 | |||
404 | if (hpet_clocksource_register()) | ||
405 | goto out_nohpet; | ||
406 | |||
322 | if (id & HPET_ID_LEGSUP) { | 407 | if (id & HPET_ID_LEGSUP) { |
323 | hpet_enable_int(); | 408 | hpet_legacy_clockevent_register(); |
324 | hpet_reserve_platform_timers(id); | ||
325 | /* | ||
326 | * Start hpet with the boot cpu mask and make it | ||
327 | * global after the IO_APIC has been initialized. | ||
328 | */ | ||
329 | hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); | ||
330 | clockevents_register_device(&hpet_clockevent); | ||
331 | global_clock_event = &hpet_clockevent; | ||
332 | return 1; | 409 | return 1; |
333 | } | 410 | } |
334 | return 0; | 411 | return 0; |
335 | 412 | ||
336 | out_nohpet: | 413 | out_nohpet: |
337 | iounmap(hpet_virt_address); | 414 | hpet_clear_mapping(); |
338 | hpet_virt_address = NULL; | ||
339 | boot_hpet_disable = 1; | 415 | boot_hpet_disable = 1; |
340 | return 0; | 416 | return 0; |
341 | } | 417 | } |
342 | 418 | ||
419 | /* | ||
420 | * Needs to be late, as the reserve_timer code calls kalloc ! | ||
421 | * | ||
422 | * Not a problem on i386 as hpet_enable is called from late_time_init, | ||
423 | * but on x86_64 it is necessary ! | ||
424 | */ | ||
425 | static __init int hpet_late_init(void) | ||
426 | { | ||
427 | if (boot_hpet_disable) | ||
428 | return -ENODEV; | ||
429 | |||
430 | if (!hpet_address) { | ||
431 | if (!force_hpet_address) | ||
432 | return -ENODEV; | ||
433 | |||
434 | hpet_address = force_hpet_address; | ||
435 | hpet_enable(); | ||
436 | if (!hpet_virt_address) | ||
437 | return -ENODEV; | ||
438 | } | ||
439 | |||
440 | hpet_reserve_platform_timers(hpet_readl(HPET_ID)); | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | fs_initcall(hpet_late_init); | ||
343 | 445 | ||
344 | #ifdef CONFIG_HPET_EMULATE_RTC | 446 | #ifdef CONFIG_HPET_EMULATE_RTC |
345 | 447 | ||
diff --git a/arch/x86/kernel/hpet_64.c b/arch/x86/kernel/hpet_64.c deleted file mode 100644 index e2d1b912e154..000000000000 --- a/arch/x86/kernel/hpet_64.c +++ /dev/null | |||
@@ -1,493 +0,0 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/sched.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/mc146818rtc.h> | ||
5 | #include <linux/time.h> | ||
6 | #include <linux/clocksource.h> | ||
7 | #include <linux/ioport.h> | ||
8 | #include <linux/acpi.h> | ||
9 | #include <linux/hpet.h> | ||
10 | #include <asm/pgtable.h> | ||
11 | #include <asm/vsyscall.h> | ||
12 | #include <asm/timex.h> | ||
13 | #include <asm/hpet.h> | ||
14 | |||
15 | #define HPET_MASK 0xFFFFFFFF | ||
16 | #define HPET_SHIFT 22 | ||
17 | |||
18 | /* FSEC = 10^-15 NSEC = 10^-9 */ | ||
19 | #define FSEC_PER_NSEC 1000000 | ||
20 | |||
21 | int nohpet __initdata; | ||
22 | |||
23 | unsigned long hpet_address; | ||
24 | unsigned long hpet_period; /* fsecs / HPET clock */ | ||
25 | unsigned long hpet_tick; /* HPET clocks / interrupt */ | ||
26 | |||
27 | int hpet_use_timer; /* Use counter of hpet for time keeping, | ||
28 | * otherwise PIT | ||
29 | */ | ||
30 | |||
31 | #ifdef CONFIG_HPET | ||
32 | static __init int late_hpet_init(void) | ||
33 | { | ||
34 | struct hpet_data hd; | ||
35 | unsigned int ntimer; | ||
36 | |||
37 | if (!hpet_address) | ||
38 | return 0; | ||
39 | |||
40 | memset(&hd, 0, sizeof(hd)); | ||
41 | |||
42 | ntimer = hpet_readl(HPET_ID); | ||
43 | ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; | ||
44 | ntimer++; | ||
45 | |||
46 | /* | ||
47 | * Register with driver. | ||
48 | * Timer0 and Timer1 is used by platform. | ||
49 | */ | ||
50 | hd.hd_phys_address = hpet_address; | ||
51 | hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE); | ||
52 | hd.hd_nirqs = ntimer; | ||
53 | hd.hd_flags = HPET_DATA_PLATFORM; | ||
54 | hpet_reserve_timer(&hd, 0); | ||
55 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
56 | hpet_reserve_timer(&hd, 1); | ||
57 | #endif | ||
58 | hd.hd_irq[0] = HPET_LEGACY_8254; | ||
59 | hd.hd_irq[1] = HPET_LEGACY_RTC; | ||
60 | if (ntimer > 2) { | ||
61 | struct hpet *hpet; | ||
62 | struct hpet_timer *timer; | ||
63 | int i; | ||
64 | |||
65 | hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE); | ||
66 | timer = &hpet->hpet_timers[2]; | ||
67 | for (i = 2; i < ntimer; timer++, i++) | ||
68 | hd.hd_irq[i] = (timer->hpet_config & | ||
69 | Tn_INT_ROUTE_CNF_MASK) >> | ||
70 | Tn_INT_ROUTE_CNF_SHIFT; | ||
71 | |||
72 | } | ||
73 | |||
74 | hpet_alloc(&hd); | ||
75 | return 0; | ||
76 | } | ||
77 | fs_initcall(late_hpet_init); | ||
78 | #endif | ||
79 | |||
80 | int hpet_timer_stop_set_go(unsigned long tick) | ||
81 | { | ||
82 | unsigned int cfg; | ||
83 | |||
84 | /* | ||
85 | * Stop the timers and reset the main counter. | ||
86 | */ | ||
87 | |||
88 | cfg = hpet_readl(HPET_CFG); | ||
89 | cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY); | ||
90 | hpet_writel(cfg, HPET_CFG); | ||
91 | hpet_writel(0, HPET_COUNTER); | ||
92 | hpet_writel(0, HPET_COUNTER + 4); | ||
93 | |||
94 | /* | ||
95 | * Set up timer 0, as periodic with first interrupt to happen at hpet_tick, | ||
96 | * and period also hpet_tick. | ||
97 | */ | ||
98 | if (hpet_use_timer) { | ||
99 | hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | | ||
100 | HPET_TN_32BIT, HPET_T0_CFG); | ||
101 | hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */ | ||
102 | hpet_writel(hpet_tick, HPET_T0_CMP); /* period */ | ||
103 | cfg |= HPET_CFG_LEGACY; | ||
104 | } | ||
105 | /* | ||
106 | * Go! | ||
107 | */ | ||
108 | |||
109 | cfg |= HPET_CFG_ENABLE; | ||
110 | hpet_writel(cfg, HPET_CFG); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static cycle_t read_hpet(void) | ||
116 | { | ||
117 | return (cycle_t)hpet_readl(HPET_COUNTER); | ||
118 | } | ||
119 | |||
120 | static cycle_t __vsyscall_fn vread_hpet(void) | ||
121 | { | ||
122 | return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0); | ||
123 | } | ||
124 | |||
125 | struct clocksource clocksource_hpet = { | ||
126 | .name = "hpet", | ||
127 | .rating = 250, | ||
128 | .read = read_hpet, | ||
129 | .mask = (cycle_t)HPET_MASK, | ||
130 | .mult = 0, /* set below */ | ||
131 | .shift = HPET_SHIFT, | ||
132 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
133 | .vread = vread_hpet, | ||
134 | }; | ||
135 | |||
136 | int __init hpet_arch_init(void) | ||
137 | { | ||
138 | unsigned int id; | ||
139 | u64 tmp; | ||
140 | |||
141 | if (!hpet_address) | ||
142 | return -1; | ||
143 | set_fixmap_nocache(FIX_HPET_BASE, hpet_address); | ||
144 | __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); | ||
145 | |||
146 | /* | ||
147 | * Read the period, compute tick and quotient. | ||
148 | */ | ||
149 | |||
150 | id = hpet_readl(HPET_ID); | ||
151 | |||
152 | if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER)) | ||
153 | return -1; | ||
154 | |||
155 | hpet_period = hpet_readl(HPET_PERIOD); | ||
156 | if (hpet_period < 100000 || hpet_period > 100000000) | ||
157 | return -1; | ||
158 | |||
159 | hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period; | ||
160 | |||
161 | hpet_use_timer = (id & HPET_ID_LEGSUP); | ||
162 | |||
163 | /* | ||
164 | * hpet period is in femto seconds per cycle | ||
165 | * so we need to convert this to ns/cyc units | ||
166 | * aproximated by mult/2^shift | ||
167 | * | ||
168 | * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift | ||
169 | * fsec/cyc * 1ns/1000000fsec * 2^shift = mult | ||
170 | * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult | ||
171 | * (fsec/cyc << shift)/1000000 = mult | ||
172 | * (hpet_period << shift)/FSEC_PER_NSEC = mult | ||
173 | */ | ||
174 | tmp = (u64)hpet_period << HPET_SHIFT; | ||
175 | do_div(tmp, FSEC_PER_NSEC); | ||
176 | clocksource_hpet.mult = (u32)tmp; | ||
177 | clocksource_register(&clocksource_hpet); | ||
178 | |||
179 | return hpet_timer_stop_set_go(hpet_tick); | ||
180 | } | ||
181 | |||
182 | int hpet_reenable(void) | ||
183 | { | ||
184 | return hpet_timer_stop_set_go(hpet_tick); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing | ||
189 | * it to the HPET timer of known frequency. | ||
190 | */ | ||
191 | |||
192 | #define TICK_COUNT 100000000 | ||
193 | #define SMI_THRESHOLD 50000 | ||
194 | #define MAX_TRIES 5 | ||
195 | |||
196 | /* | ||
197 | * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none | ||
198 | * occurs between the reads of the hpet & TSC. | ||
199 | */ | ||
200 | static void __init read_hpet_tsc(int *hpet, int *tsc) | ||
201 | { | ||
202 | int tsc1, tsc2, hpet1, i; | ||
203 | |||
204 | for (i = 0; i < MAX_TRIES; i++) { | ||
205 | tsc1 = get_cycles_sync(); | ||
206 | hpet1 = hpet_readl(HPET_COUNTER); | ||
207 | tsc2 = get_cycles_sync(); | ||
208 | if ((tsc2 - tsc1) < SMI_THRESHOLD) | ||
209 | break; | ||
210 | } | ||
211 | *hpet = hpet1; | ||
212 | *tsc = tsc2; | ||
213 | } | ||
214 | |||
215 | unsigned int __init hpet_calibrate_tsc(void) | ||
216 | { | ||
217 | int tsc_start, hpet_start; | ||
218 | int tsc_now, hpet_now; | ||
219 | unsigned long flags; | ||
220 | |||
221 | local_irq_save(flags); | ||
222 | |||
223 | read_hpet_tsc(&hpet_start, &tsc_start); | ||
224 | |||
225 | do { | ||
226 | local_irq_disable(); | ||
227 | read_hpet_tsc(&hpet_now, &tsc_now); | ||
228 | local_irq_restore(flags); | ||
229 | } while ((tsc_now - tsc_start) < TICK_COUNT && | ||
230 | (hpet_now - hpet_start) < TICK_COUNT); | ||
231 | |||
232 | return (tsc_now - tsc_start) * 1000000000L | ||
233 | / ((hpet_now - hpet_start) * hpet_period / 1000); | ||
234 | } | ||
235 | |||
236 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
237 | /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET | ||
238 | * is enabled, we support RTC interrupt functionality in software. | ||
239 | * RTC has 3 kinds of interrupts: | ||
240 | * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock | ||
241 | * is updated | ||
242 | * 2) Alarm Interrupt - generate an interrupt at a specific time of day | ||
243 | * 3) Periodic Interrupt - generate periodic interrupt, with frequencies | ||
244 | * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2) | ||
245 | * (1) and (2) above are implemented using polling at a frequency of | ||
246 | * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt | ||
247 | * overhead. (DEFAULT_RTC_INT_FREQ) | ||
248 | * For (3), we use interrupts at 64Hz or user specified periodic | ||
249 | * frequency, whichever is higher. | ||
250 | */ | ||
251 | #include <linux/rtc.h> | ||
252 | |||
253 | #define DEFAULT_RTC_INT_FREQ 64 | ||
254 | #define RTC_NUM_INTS 1 | ||
255 | |||
256 | static unsigned long UIE_on; | ||
257 | static unsigned long prev_update_sec; | ||
258 | |||
259 | static unsigned long AIE_on; | ||
260 | static struct rtc_time alarm_time; | ||
261 | |||
262 | static unsigned long PIE_on; | ||
263 | static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; | ||
264 | static unsigned long PIE_count; | ||
265 | |||
266 | static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ | ||
267 | static unsigned int hpet_t1_cmp; /* cached comparator register */ | ||
268 | |||
269 | int is_hpet_enabled(void) | ||
270 | { | ||
271 | return hpet_address != 0; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Timer 1 for RTC, we do not use periodic interrupt feature, | ||
276 | * even if HPET supports periodic interrupts on Timer 1. | ||
277 | * The reason being, to set up a periodic interrupt in HPET, we need to | ||
278 | * stop the main counter. And if we do that everytime someone diables/enables | ||
279 | * RTC, we will have adverse effect on main kernel timer running on Timer 0. | ||
280 | * So, for the time being, simulate the periodic interrupt in software. | ||
281 | * | ||
282 | * hpet_rtc_timer_init() is called for the first time and during subsequent | ||
283 | * interuppts reinit happens through hpet_rtc_timer_reinit(). | ||
284 | */ | ||
285 | int hpet_rtc_timer_init(void) | ||
286 | { | ||
287 | unsigned int cfg, cnt; | ||
288 | unsigned long flags; | ||
289 | |||
290 | if (!is_hpet_enabled()) | ||
291 | return 0; | ||
292 | /* | ||
293 | * Set the counter 1 and enable the interrupts. | ||
294 | */ | ||
295 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
296 | hpet_rtc_int_freq = PIE_freq; | ||
297 | else | ||
298 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
299 | |||
300 | local_irq_save(flags); | ||
301 | |||
302 | cnt = hpet_readl(HPET_COUNTER); | ||
303 | cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); | ||
304 | hpet_writel(cnt, HPET_T1_CMP); | ||
305 | hpet_t1_cmp = cnt; | ||
306 | |||
307 | cfg = hpet_readl(HPET_T1_CFG); | ||
308 | cfg &= ~HPET_TN_PERIODIC; | ||
309 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
310 | hpet_writel(cfg, HPET_T1_CFG); | ||
311 | |||
312 | local_irq_restore(flags); | ||
313 | |||
314 | return 1; | ||
315 | } | ||
316 | |||
317 | static void hpet_rtc_timer_reinit(void) | ||
318 | { | ||
319 | unsigned int cfg, cnt, ticks_per_int, lost_ints; | ||
320 | |||
321 | if (unlikely(!(PIE_on | AIE_on | UIE_on))) { | ||
322 | cfg = hpet_readl(HPET_T1_CFG); | ||
323 | cfg &= ~HPET_TN_ENABLE; | ||
324 | hpet_writel(cfg, HPET_T1_CFG); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
329 | hpet_rtc_int_freq = PIE_freq; | ||
330 | else | ||
331 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
332 | |||
333 | /* It is more accurate to use the comparator value than current count.*/ | ||
334 | ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq; | ||
335 | hpet_t1_cmp += ticks_per_int; | ||
336 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
337 | |||
338 | /* | ||
339 | * If the interrupt handler was delayed too long, the write above tries | ||
340 | * to schedule the next interrupt in the past and the hardware would | ||
341 | * not interrupt until the counter had wrapped around. | ||
342 | * So we have to check that the comparator wasn't set to a past time. | ||
343 | */ | ||
344 | cnt = hpet_readl(HPET_COUNTER); | ||
345 | if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) { | ||
346 | lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1; | ||
347 | /* Make sure that, even with the time needed to execute | ||
348 | * this code, the next scheduled interrupt has been moved | ||
349 | * back to the future: */ | ||
350 | lost_ints++; | ||
351 | |||
352 | hpet_t1_cmp += lost_ints * ticks_per_int; | ||
353 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
354 | |||
355 | if (PIE_on) | ||
356 | PIE_count += lost_ints; | ||
357 | |||
358 | if (printk_ratelimit()) | ||
359 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", | ||
360 | hpet_rtc_int_freq); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * The functions below are called from rtc driver. | ||
366 | * Return 0 if HPET is not being used. | ||
367 | * Otherwise do the necessary changes and return 1. | ||
368 | */ | ||
369 | int hpet_mask_rtc_irq_bit(unsigned long bit_mask) | ||
370 | { | ||
371 | if (!is_hpet_enabled()) | ||
372 | return 0; | ||
373 | |||
374 | if (bit_mask & RTC_UIE) | ||
375 | UIE_on = 0; | ||
376 | if (bit_mask & RTC_PIE) | ||
377 | PIE_on = 0; | ||
378 | if (bit_mask & RTC_AIE) | ||
379 | AIE_on = 0; | ||
380 | |||
381 | return 1; | ||
382 | } | ||
383 | |||
384 | int hpet_set_rtc_irq_bit(unsigned long bit_mask) | ||
385 | { | ||
386 | int timer_init_reqd = 0; | ||
387 | |||
388 | if (!is_hpet_enabled()) | ||
389 | return 0; | ||
390 | |||
391 | if (!(PIE_on | AIE_on | UIE_on)) | ||
392 | timer_init_reqd = 1; | ||
393 | |||
394 | if (bit_mask & RTC_UIE) { | ||
395 | UIE_on = 1; | ||
396 | } | ||
397 | if (bit_mask & RTC_PIE) { | ||
398 | PIE_on = 1; | ||
399 | PIE_count = 0; | ||
400 | } | ||
401 | if (bit_mask & RTC_AIE) { | ||
402 | AIE_on = 1; | ||
403 | } | ||
404 | |||
405 | if (timer_init_reqd) | ||
406 | hpet_rtc_timer_init(); | ||
407 | |||
408 | return 1; | ||
409 | } | ||
410 | |||
411 | int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
412 | { | ||
413 | if (!is_hpet_enabled()) | ||
414 | return 0; | ||
415 | |||
416 | alarm_time.tm_hour = hrs; | ||
417 | alarm_time.tm_min = min; | ||
418 | alarm_time.tm_sec = sec; | ||
419 | |||
420 | return 1; | ||
421 | } | ||
422 | |||
423 | int hpet_set_periodic_freq(unsigned long freq) | ||
424 | { | ||
425 | if (!is_hpet_enabled()) | ||
426 | return 0; | ||
427 | |||
428 | PIE_freq = freq; | ||
429 | PIE_count = 0; | ||
430 | |||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | int hpet_rtc_dropped_irq(void) | ||
435 | { | ||
436 | if (!is_hpet_enabled()) | ||
437 | return 0; | ||
438 | |||
439 | return 1; | ||
440 | } | ||
441 | |||
442 | irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | ||
443 | { | ||
444 | struct rtc_time curr_time; | ||
445 | unsigned long rtc_int_flag = 0; | ||
446 | int call_rtc_interrupt = 0; | ||
447 | |||
448 | hpet_rtc_timer_reinit(); | ||
449 | |||
450 | if (UIE_on | AIE_on) { | ||
451 | rtc_get_rtc_time(&curr_time); | ||
452 | } | ||
453 | if (UIE_on) { | ||
454 | if (curr_time.tm_sec != prev_update_sec) { | ||
455 | /* Set update int info, call real rtc int routine */ | ||
456 | call_rtc_interrupt = 1; | ||
457 | rtc_int_flag = RTC_UF; | ||
458 | prev_update_sec = curr_time.tm_sec; | ||
459 | } | ||
460 | } | ||
461 | if (PIE_on) { | ||
462 | PIE_count++; | ||
463 | if (PIE_count >= hpet_rtc_int_freq/PIE_freq) { | ||
464 | /* Set periodic int info, call real rtc int routine */ | ||
465 | call_rtc_interrupt = 1; | ||
466 | rtc_int_flag |= RTC_PF; | ||
467 | PIE_count = 0; | ||
468 | } | ||
469 | } | ||
470 | if (AIE_on) { | ||
471 | if ((curr_time.tm_sec == alarm_time.tm_sec) && | ||
472 | (curr_time.tm_min == alarm_time.tm_min) && | ||
473 | (curr_time.tm_hour == alarm_time.tm_hour)) { | ||
474 | /* Set alarm int info, call real rtc int routine */ | ||
475 | call_rtc_interrupt = 1; | ||
476 | rtc_int_flag |= RTC_AF; | ||
477 | } | ||
478 | } | ||
479 | if (call_rtc_interrupt) { | ||
480 | rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); | ||
481 | rtc_interrupt(rtc_int_flag, dev_id); | ||
482 | } | ||
483 | return IRQ_HANDLED; | ||
484 | } | ||
485 | #endif | ||
486 | |||
487 | static int __init nohpet_setup(char *s) | ||
488 | { | ||
489 | nohpet = 1; | ||
490 | return 1; | ||
491 | } | ||
492 | |||
493 | __setup("nohpet", nohpet_setup); | ||
diff --git a/arch/x86/kernel/i8253_32.c b/arch/x86/kernel/i8253.c index 6d839f2f1b1a..ac15e4cbd9c1 100644 --- a/arch/x86/kernel/i8253_32.c +++ b/arch/x86/kernel/i8253.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/delay.h> | 13 | #include <asm/delay.h> |
14 | #include <asm/i8253.h> | 14 | #include <asm/i8253.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/timer.h> | ||
17 | 16 | ||
18 | DEFINE_SPINLOCK(i8253_lock); | 17 | DEFINE_SPINLOCK(i8253_lock); |
19 | EXPORT_SYMBOL(i8253_lock); | 18 | EXPORT_SYMBOL(i8253_lock); |
@@ -120,6 +119,7 @@ void __init setup_pit_timer(void) | |||
120 | global_clock_event = &pit_clockevent; | 119 | global_clock_event = &pit_clockevent; |
121 | } | 120 | } |
122 | 121 | ||
122 | #ifndef CONFIG_X86_64 | ||
123 | /* | 123 | /* |
124 | * Since the PIT overflows every tick, its not very useful | 124 | * Since the PIT overflows every tick, its not very useful |
125 | * to just read by itself. So use jiffies to emulate a free | 125 | * to just read by itself. So use jiffies to emulate a free |
@@ -204,3 +204,5 @@ static int __init init_pit_clocksource(void) | |||
204 | return clocksource_register(&clocksource_pit); | 204 | return clocksource_register(&clocksource_pit); |
205 | } | 205 | } |
206 | arch_initcall(init_pit_clocksource); | 206 | arch_initcall(init_pit_clocksource); |
207 | |||
208 | #endif | ||
diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c index 0499cbe9871a..679bb33acbf1 100644 --- a/arch/x86/kernel/i8259_32.c +++ b/arch/x86/kernel/i8259_32.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/sysdev.h> | 10 | #include <linux/sysdev.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | 12 | ||
13 | #include <asm/8253pit.h> | ||
14 | #include <asm/atomic.h> | 13 | #include <asm/atomic.h> |
15 | #include <asm/system.h> | 14 | #include <asm/system.h> |
16 | #include <asm/io.h> | 15 | #include <asm/io.h> |
diff --git a/arch/x86/kernel/i8259_64.c b/arch/x86/kernel/i8259_64.c index 948cae646099..eb72976cc13c 100644 --- a/arch/x86/kernel/i8259_64.c +++ b/arch/x86/kernel/i8259_64.c | |||
@@ -444,46 +444,6 @@ void __init init_ISA_irqs (void) | |||
444 | } | 444 | } |
445 | } | 445 | } |
446 | 446 | ||
447 | static void setup_timer_hardware(void) | ||
448 | { | ||
449 | outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ | ||
450 | udelay(10); | ||
451 | outb_p(LATCH & 0xff , 0x40); /* LSB */ | ||
452 | udelay(10); | ||
453 | outb(LATCH >> 8 , 0x40); /* MSB */ | ||
454 | } | ||
455 | |||
456 | static int timer_resume(struct sys_device *dev) | ||
457 | { | ||
458 | setup_timer_hardware(); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | void i8254_timer_resume(void) | ||
463 | { | ||
464 | setup_timer_hardware(); | ||
465 | } | ||
466 | |||
467 | static struct sysdev_class timer_sysclass = { | ||
468 | set_kset_name("timer_pit"), | ||
469 | .resume = timer_resume, | ||
470 | }; | ||
471 | |||
472 | static struct sys_device device_timer = { | ||
473 | .id = 0, | ||
474 | .cls = &timer_sysclass, | ||
475 | }; | ||
476 | |||
477 | static int __init init_timer_sysfs(void) | ||
478 | { | ||
479 | int error = sysdev_class_register(&timer_sysclass); | ||
480 | if (!error) | ||
481 | error = sysdev_register(&device_timer); | ||
482 | return error; | ||
483 | } | ||
484 | |||
485 | device_initcall(init_timer_sysfs); | ||
486 | |||
487 | void __init init_IRQ(void) | 447 | void __init init_IRQ(void) |
488 | { | 448 | { |
489 | int i; | 449 | int i; |
@@ -533,12 +493,6 @@ void __init init_IRQ(void) | |||
533 | set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 493 | set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
534 | set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 494 | set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
535 | 495 | ||
536 | /* | ||
537 | * Set the clock to HZ Hz, we already have a valid | ||
538 | * vector now: | ||
539 | */ | ||
540 | setup_timer_hardware(); | ||
541 | |||
542 | if (!acpi_ioapic) | 496 | if (!acpi_ioapic) |
543 | setup_irq(2, &irq2); | 497 | setup_irq(2, &irq2); |
544 | } | 498 | } |
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c new file mode 100644 index 000000000000..0ab680f2d9db --- /dev/null +++ b/arch/x86/kernel/mfgpt_32.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Driver/API for AMD Geode Multi-Function General Purpose Timers (MFGPT) | ||
3 | * | ||
4 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
5 | * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of version 2 of the GNU General Public License | ||
9 | * as published by the Free Software Foundation. | ||
10 | * | ||
11 | * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * We are using the 32Khz input clock - its the only one that has the | ||
16 | * ranges we find desirable. The following table lists the suitable | ||
17 | * divisors and the associated hz, minimum interval | ||
18 | * and the maximum interval: | ||
19 | * | ||
20 | * Divisor Hz Min Delta (S) Max Delta (S) | ||
21 | * 1 32000 .0005 2.048 | ||
22 | * 2 16000 .001 4.096 | ||
23 | * 4 8000 .002 8.192 | ||
24 | * 8 4000 .004 16.384 | ||
25 | * 16 2000 .008 32.768 | ||
26 | * 32 1000 .016 65.536 | ||
27 | * 64 500 .032 131.072 | ||
28 | * 128 250 .064 262.144 | ||
29 | * 256 125 .128 524.288 | ||
30 | */ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <asm/geode.h> | ||
36 | |||
37 | #define F_AVAIL 0x01 | ||
38 | |||
39 | static struct mfgpt_timer_t { | ||
40 | int flags; | ||
41 | struct module *owner; | ||
42 | } mfgpt_timers[MFGPT_MAX_TIMERS]; | ||
43 | |||
44 | /* Selected from the table above */ | ||
45 | |||
46 | #define MFGPT_DIVISOR 16 | ||
47 | #define MFGPT_SCALE 4 /* divisor = 2^(scale) */ | ||
48 | #define MFGPT_HZ (32000 / MFGPT_DIVISOR) | ||
49 | #define MFGPT_PERIODIC (MFGPT_HZ / HZ) | ||
50 | |||
51 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
52 | static int __init mfgpt_timer_setup(void); | ||
53 | #else | ||
54 | #define mfgpt_timer_setup() (0) | ||
55 | #endif | ||
56 | |||
57 | /* Allow for disabling of MFGPTs */ | ||
58 | static int disable; | ||
59 | static int __init mfgpt_disable(char *s) | ||
60 | { | ||
61 | disable = 1; | ||
62 | return 1; | ||
63 | } | ||
64 | __setup("nomfgpt", mfgpt_disable); | ||
65 | |||
66 | /* | ||
67 | * Check whether any MFGPTs are available for the kernel to use. In most | ||
68 | * cases, firmware that uses AMD's VSA code will claim all timers during | ||
69 | * bootup; we certainly don't want to take them if they're already in use. | ||
70 | * In other cases (such as with VSAless OpenFirmware), the system firmware | ||
71 | * leaves timers available for us to use. | ||
72 | */ | ||
73 | int __init geode_mfgpt_detect(void) | ||
74 | { | ||
75 | int count = 0, i; | ||
76 | u16 val; | ||
77 | |||
78 | if (disable) { | ||
79 | printk(KERN_INFO "geode-mfgpt: Skipping MFGPT setup\n"); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
84 | val = geode_mfgpt_read(i, MFGPT_REG_SETUP); | ||
85 | if (!(val & MFGPT_SETUP_SETUP)) { | ||
86 | mfgpt_timers[i].flags = F_AVAIL; | ||
87 | count++; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* set up clock event device, if desired */ | ||
92 | i = mfgpt_timer_setup(); | ||
93 | |||
94 | return count; | ||
95 | } | ||
96 | |||
97 | int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable) | ||
98 | { | ||
99 | u32 msr, mask, value, dummy; | ||
100 | int shift = (cmp == MFGPT_CMP1) ? 0 : 8; | ||
101 | |||
102 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
103 | return -EIO; | ||
104 | |||
105 | /* | ||
106 | * The register maps for these are described in sections 6.17.1.x of | ||
107 | * the AMD Geode CS5536 Companion Device Data Book. | ||
108 | */ | ||
109 | switch (event) { | ||
110 | case MFGPT_EVENT_RESET: | ||
111 | /* | ||
112 | * XXX: According to the docs, we cannot reset timers above | ||
113 | * 6; that is, resets for 7 and 8 will be ignored. Is this | ||
114 | * a problem? -dilinger | ||
115 | */ | ||
116 | msr = MFGPT_NR_MSR; | ||
117 | mask = 1 << (timer + 24); | ||
118 | break; | ||
119 | |||
120 | case MFGPT_EVENT_NMI: | ||
121 | msr = MFGPT_NR_MSR; | ||
122 | mask = 1 << (timer + shift); | ||
123 | break; | ||
124 | |||
125 | case MFGPT_EVENT_IRQ: | ||
126 | msr = MFGPT_IRQ_MSR; | ||
127 | mask = 1 << (timer + shift); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | return -EIO; | ||
132 | } | ||
133 | |||
134 | rdmsr(msr, value, dummy); | ||
135 | |||
136 | if (enable) | ||
137 | value |= mask; | ||
138 | else | ||
139 | value &= ~mask; | ||
140 | |||
141 | wrmsr(msr, value, dummy); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable) | ||
146 | { | ||
147 | u32 val, dummy; | ||
148 | int offset; | ||
149 | |||
150 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
151 | return -EIO; | ||
152 | |||
153 | if (geode_mfgpt_toggle_event(timer, cmp, MFGPT_EVENT_IRQ, enable)) | ||
154 | return -EIO; | ||
155 | |||
156 | rdmsr(MSR_PIC_ZSEL_LOW, val, dummy); | ||
157 | |||
158 | offset = (timer % 4) * 4; | ||
159 | |||
160 | val &= ~((0xF << offset) | (0xF << (offset + 16))); | ||
161 | |||
162 | if (enable) { | ||
163 | val |= (irq & 0x0F) << (offset); | ||
164 | val |= (irq & 0x0F) << (offset + 16); | ||
165 | } | ||
166 | |||
167 | wrmsr(MSR_PIC_ZSEL_LOW, val, dummy); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int mfgpt_get(int timer, struct module *owner) | ||
172 | { | ||
173 | mfgpt_timers[timer].flags &= ~F_AVAIL; | ||
174 | mfgpt_timers[timer].owner = owner; | ||
175 | printk(KERN_INFO "geode-mfgpt: Registered timer %d\n", timer); | ||
176 | return timer; | ||
177 | } | ||
178 | |||
179 | int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner) | ||
180 | { | ||
181 | int i; | ||
182 | |||
183 | if (!geode_get_dev_base(GEODE_DEV_MFGPT)) | ||
184 | return -ENODEV; | ||
185 | if (timer >= MFGPT_MAX_TIMERS) | ||
186 | return -EIO; | ||
187 | |||
188 | if (timer < 0) { | ||
189 | /* Try to find an available timer */ | ||
190 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
191 | if (mfgpt_timers[i].flags & F_AVAIL) | ||
192 | return mfgpt_get(i, owner); | ||
193 | |||
194 | if (i == 5 && domain == MFGPT_DOMAIN_WORKING) | ||
195 | break; | ||
196 | } | ||
197 | } else { | ||
198 | /* If they requested a specific timer, try to honor that */ | ||
199 | if (mfgpt_timers[timer].flags & F_AVAIL) | ||
200 | return mfgpt_get(timer, owner); | ||
201 | } | ||
202 | |||
203 | /* No timers available - too bad */ | ||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | |||
208 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
209 | |||
210 | /* | ||
211 | * The MFPGT timers on the CS5536 provide us with suitable timers to use | ||
212 | * as clock event sources - not as good as a HPET or APIC, but certainly | ||
213 | * better then the PIT. This isn't a general purpose MFGPT driver, but | ||
214 | * a simplified one designed specifically to act as a clock event source. | ||
215 | * For full details about the MFGPT, please consult the CS5536 data sheet. | ||
216 | */ | ||
217 | |||
218 | #include <linux/clocksource.h> | ||
219 | #include <linux/clockchips.h> | ||
220 | |||
221 | static unsigned int mfgpt_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | ||
222 | static u16 mfgpt_event_clock; | ||
223 | |||
224 | static int irq = 7; | ||
225 | static int __init mfgpt_setup(char *str) | ||
226 | { | ||
227 | get_option(&str, &irq); | ||
228 | return 1; | ||
229 | } | ||
230 | __setup("mfgpt_irq=", mfgpt_setup); | ||
231 | |||
232 | static inline void mfgpt_disable_timer(u16 clock) | ||
233 | { | ||
234 | u16 val = geode_mfgpt_read(clock, MFGPT_REG_SETUP); | ||
235 | geode_mfgpt_write(clock, MFGPT_REG_SETUP, val & ~MFGPT_SETUP_CNTEN); | ||
236 | } | ||
237 | |||
238 | static int mfgpt_next_event(unsigned long, struct clock_event_device *); | ||
239 | static void mfgpt_set_mode(enum clock_event_mode, struct clock_event_device *); | ||
240 | |||
241 | static struct clock_event_device mfgpt_clockevent = { | ||
242 | .name = "mfgpt-timer", | ||
243 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
244 | .set_mode = mfgpt_set_mode, | ||
245 | .set_next_event = mfgpt_next_event, | ||
246 | .rating = 250, | ||
247 | .cpumask = CPU_MASK_ALL, | ||
248 | .shift = 32 | ||
249 | }; | ||
250 | |||
251 | static inline void mfgpt_start_timer(u16 clock, u16 delta) | ||
252 | { | ||
253 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta); | ||
254 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
255 | |||
256 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
257 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
258 | } | ||
259 | |||
260 | static void mfgpt_set_mode(enum clock_event_mode mode, | ||
261 | struct clock_event_device *evt) | ||
262 | { | ||
263 | mfgpt_disable_timer(mfgpt_event_clock); | ||
264 | |||
265 | if (mode == CLOCK_EVT_MODE_PERIODIC) | ||
266 | mfgpt_start_timer(mfgpt_event_clock, MFGPT_PERIODIC); | ||
267 | |||
268 | mfgpt_tick_mode = mode; | ||
269 | } | ||
270 | |||
271 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | ||
272 | { | ||
273 | mfgpt_start_timer(mfgpt_event_clock, delta); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /* Assume (foolishly?), that this interrupt was due to our tick */ | ||
278 | |||
279 | static irqreturn_t mfgpt_tick(int irq, void *dev_id) | ||
280 | { | ||
281 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | ||
282 | return IRQ_HANDLED; | ||
283 | |||
284 | /* Turn off the clock */ | ||
285 | mfgpt_disable_timer(mfgpt_event_clock); | ||
286 | |||
287 | /* Clear the counter */ | ||
288 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
289 | |||
290 | /* Restart the clock in periodic mode */ | ||
291 | |||
292 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_PERIODIC) { | ||
293 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
294 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
295 | } | ||
296 | |||
297 | mfgpt_clockevent.event_handler(&mfgpt_clockevent); | ||
298 | return IRQ_HANDLED; | ||
299 | } | ||
300 | |||
301 | static struct irqaction mfgptirq = { | ||
302 | .handler = mfgpt_tick, | ||
303 | .flags = IRQF_DISABLED | IRQF_NOBALANCING, | ||
304 | .mask = CPU_MASK_NONE, | ||
305 | .name = "mfgpt-timer" | ||
306 | }; | ||
307 | |||
308 | static int __init mfgpt_timer_setup(void) | ||
309 | { | ||
310 | int timer, ret; | ||
311 | u16 val; | ||
312 | |||
313 | timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING, | ||
314 | THIS_MODULE); | ||
315 | if (timer < 0) { | ||
316 | printk(KERN_ERR | ||
317 | "mfgpt-timer: Could not allocate a MFPGT timer\n"); | ||
318 | return -ENODEV; | ||
319 | } | ||
320 | |||
321 | mfgpt_event_clock = timer; | ||
322 | /* Set the clock scale and enable the event mode for CMP2 */ | ||
323 | val = MFGPT_SCALE | (3 << 8); | ||
324 | |||
325 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val); | ||
326 | |||
327 | /* Set up the IRQ on the MFGPT side */ | ||
328 | if (geode_mfgpt_setup_irq(mfgpt_event_clock, MFGPT_CMP2, irq)) { | ||
329 | printk(KERN_ERR "mfgpt-timer: Could not set up IRQ %d\n", irq); | ||
330 | return -EIO; | ||
331 | } | ||
332 | |||
333 | /* And register it with the kernel */ | ||
334 | ret = setup_irq(irq, &mfgptirq); | ||
335 | |||
336 | if (ret) { | ||
337 | printk(KERN_ERR | ||
338 | "mfgpt-timer: Unable to set up the interrupt.\n"); | ||
339 | goto err; | ||
340 | } | ||
341 | |||
342 | /* Set up the clock event */ | ||
343 | mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32); | ||
344 | mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF, | ||
345 | &mfgpt_clockevent); | ||
346 | mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, | ||
347 | &mfgpt_clockevent); | ||
348 | |||
349 | printk(KERN_INFO | ||
350 | "mfgpt-timer: registering the MFGT timer as a clock event.\n"); | ||
351 | clockevents_register_device(&mfgpt_clockevent); | ||
352 | |||
353 | return 0; | ||
354 | |||
355 | err: | ||
356 | geode_mfgpt_release_irq(mfgpt_event_clock, MFGPT_CMP2, irq); | ||
357 | printk(KERN_ERR | ||
358 | "mfgpt-timer: Unable to set up the MFGPT clock source\n"); | ||
359 | return -EIO; | ||
360 | } | ||
361 | |||
362 | #endif | ||
diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c index c7227e2180f8..95d3fc203cf7 100644 --- a/arch/x86/kernel/nmi_32.c +++ b/arch/x86/kernel/nmi_32.c | |||
@@ -353,7 +353,8 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
353 | * Take the local apic timer and PIT/HPET into account. We don't | 353 | * Take the local apic timer and PIT/HPET into account. We don't |
354 | * know which one is active, when we have highres/dyntick on | 354 | * know which one is active, when we have highres/dyntick on |
355 | */ | 355 | */ |
356 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_cpu(cpu).irqs[0]; | 356 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + |
357 | per_cpu(irq_stat, cpu).irq0_irqs; | ||
357 | 358 | ||
358 | /* if the none of the timers isn't firing, this cpu isn't doing much */ | 359 | /* if the none of the timers isn't firing, this cpu isn't doing much */ |
359 | if (!touched && last_irq_sums[cpu] == sum) { | 360 | if (!touched && last_irq_sums[cpu] == sum) { |
diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c index 0ec6d2ddb931..e60ac0da5283 100644 --- a/arch/x86/kernel/nmi_64.c +++ b/arch/x86/kernel/nmi_64.c | |||
@@ -329,7 +329,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
329 | touched = 1; | 329 | touched = 1; |
330 | } | 330 | } |
331 | 331 | ||
332 | sum = read_pda(apic_timer_irqs); | 332 | sum = read_pda(apic_timer_irqs) + read_pda(irq0_irqs); |
333 | if (__get_cpu_var(nmi_touch)) { | 333 | if (__get_cpu_var(nmi_touch)) { |
334 | __get_cpu_var(nmi_touch) = 0; | 334 | __get_cpu_var(nmi_touch) = 0; |
335 | touched = 1; | 335 | touched = 1; |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 98956555450b..6f9dbbe65eef 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/notifier.h> | 38 | #include <linux/notifier.h> |
39 | #include <linux/kprobes.h> | 39 | #include <linux/kprobes.h> |
40 | #include <linux/kdebug.h> | 40 | #include <linux/kdebug.h> |
41 | #include <linux/tick.h> | ||
41 | 42 | ||
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | #include <asm/pgtable.h> | 44 | #include <asm/pgtable.h> |
@@ -208,6 +209,8 @@ void cpu_idle (void) | |||
208 | if (__get_cpu_var(cpu_idle_state)) | 209 | if (__get_cpu_var(cpu_idle_state)) |
209 | __get_cpu_var(cpu_idle_state) = 0; | 210 | __get_cpu_var(cpu_idle_state) = 0; |
210 | 211 | ||
212 | tick_nohz_stop_sched_tick(); | ||
213 | |||
211 | rmb(); | 214 | rmb(); |
212 | idle = pm_idle; | 215 | idle = pm_idle; |
213 | if (!idle) | 216 | if (!idle) |
@@ -228,6 +231,7 @@ void cpu_idle (void) | |||
228 | __exit_idle(); | 231 | __exit_idle(); |
229 | } | 232 | } |
230 | 233 | ||
234 | tick_nohz_restart_sched_tick(); | ||
231 | preempt_enable_no_resched(); | 235 | preempt_enable_no_resched(); |
232 | schedule(); | 236 | schedule(); |
233 | preempt_disable(); | 237 | preempt_disable(); |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 6722469c2633..d769e204f942 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
5 | #include <linux/irq.h> | 5 | #include <linux/irq.h> |
6 | 6 | ||
7 | #include <asm/hpet.h> | ||
8 | |||
7 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) | 9 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) |
8 | 10 | ||
9 | static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) | 11 | static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) |
@@ -47,3 +49,206 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quir | |||
47 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); | 49 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); |
48 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); | 50 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); |
49 | #endif | 51 | #endif |
52 | |||
53 | #if defined(CONFIG_HPET_TIMER) | ||
54 | unsigned long force_hpet_address; | ||
55 | |||
56 | static enum { | ||
57 | NONE_FORCE_HPET_RESUME, | ||
58 | OLD_ICH_FORCE_HPET_RESUME, | ||
59 | ICH_FORCE_HPET_RESUME | ||
60 | } force_hpet_resume_type; | ||
61 | |||
62 | static void __iomem *rcba_base; | ||
63 | |||
64 | static void ich_force_hpet_resume(void) | ||
65 | { | ||
66 | u32 val; | ||
67 | |||
68 | if (!force_hpet_address) | ||
69 | return; | ||
70 | |||
71 | if (rcba_base == NULL) | ||
72 | BUG(); | ||
73 | |||
74 | /* read the Function Disable register, dword mode only */ | ||
75 | val = readl(rcba_base + 0x3404); | ||
76 | if (!(val & 0x80)) { | ||
77 | /* HPET disabled in HPTC. Trying to enable */ | ||
78 | writel(val | 0x80, rcba_base + 0x3404); | ||
79 | } | ||
80 | |||
81 | val = readl(rcba_base + 0x3404); | ||
82 | if (!(val & 0x80)) | ||
83 | BUG(); | ||
84 | else | ||
85 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
86 | |||
87 | return; | ||
88 | } | ||
89 | |||
90 | static void ich_force_enable_hpet(struct pci_dev *dev) | ||
91 | { | ||
92 | u32 val; | ||
93 | u32 uninitialized_var(rcba); | ||
94 | int err = 0; | ||
95 | |||
96 | if (hpet_address || force_hpet_address) | ||
97 | return; | ||
98 | |||
99 | pci_read_config_dword(dev, 0xF0, &rcba); | ||
100 | rcba &= 0xFFFFC000; | ||
101 | if (rcba == 0) { | ||
102 | printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n"); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | /* use bits 31:14, 16 kB aligned */ | ||
107 | rcba_base = ioremap_nocache(rcba, 0x4000); | ||
108 | if (rcba_base == NULL) { | ||
109 | printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n"); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | /* read the Function Disable register, dword mode only */ | ||
114 | val = readl(rcba_base + 0x3404); | ||
115 | |||
116 | if (val & 0x80) { | ||
117 | /* HPET is enabled in HPTC. Just not reported by BIOS */ | ||
118 | val = val & 0x3; | ||
119 | force_hpet_address = 0xFED00000 | (val << 12); | ||
120 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
121 | force_hpet_address); | ||
122 | iounmap(rcba_base); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | /* HPET disabled in HPTC. Trying to enable */ | ||
127 | writel(val | 0x80, rcba_base + 0x3404); | ||
128 | |||
129 | val = readl(rcba_base + 0x3404); | ||
130 | if (!(val & 0x80)) { | ||
131 | err = 1; | ||
132 | } else { | ||
133 | val = val & 0x3; | ||
134 | force_hpet_address = 0xFED00000 | (val << 12); | ||
135 | } | ||
136 | |||
137 | if (err) { | ||
138 | force_hpet_address = 0; | ||
139 | iounmap(rcba_base); | ||
140 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
141 | } else { | ||
142 | force_hpet_resume_type = ICH_FORCE_HPET_RESUME; | ||
143 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
144 | force_hpet_address); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, | ||
149 | ich_force_enable_hpet); | ||
150 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, | ||
151 | ich_force_enable_hpet); | ||
152 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, | ||
153 | ich_force_enable_hpet); | ||
154 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, | ||
155 | ich_force_enable_hpet); | ||
156 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, | ||
157 | ich_force_enable_hpet); | ||
158 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, | ||
159 | ich_force_enable_hpet); | ||
160 | |||
161 | |||
162 | static struct pci_dev *cached_dev; | ||
163 | |||
164 | static void old_ich_force_hpet_resume(void) | ||
165 | { | ||
166 | u32 val; | ||
167 | u32 uninitialized_var(gen_cntl); | ||
168 | |||
169 | if (!force_hpet_address || !cached_dev) | ||
170 | return; | ||
171 | |||
172 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
173 | gen_cntl &= (~(0x7 << 15)); | ||
174 | gen_cntl |= (0x4 << 15); | ||
175 | |||
176 | pci_write_config_dword(cached_dev, 0xD0, gen_cntl); | ||
177 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
178 | val = gen_cntl >> 15; | ||
179 | val &= 0x7; | ||
180 | if (val == 0x4) | ||
181 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
182 | else | ||
183 | BUG(); | ||
184 | } | ||
185 | |||
186 | static void old_ich_force_enable_hpet(struct pci_dev *dev) | ||
187 | { | ||
188 | u32 val; | ||
189 | u32 uninitialized_var(gen_cntl); | ||
190 | |||
191 | if (hpet_address || force_hpet_address) | ||
192 | return; | ||
193 | |||
194 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
195 | /* | ||
196 | * Bit 17 is HPET enable bit. | ||
197 | * Bit 16:15 control the HPET base address. | ||
198 | */ | ||
199 | val = gen_cntl >> 15; | ||
200 | val &= 0x7; | ||
201 | if (val & 0x4) { | ||
202 | val &= 0x3; | ||
203 | force_hpet_address = 0xFED00000 | (val << 12); | ||
204 | printk(KERN_DEBUG "HPET at base address 0x%lx\n", | ||
205 | force_hpet_address); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * HPET is disabled. Trying enabling at FED00000 and check | ||
211 | * whether it sticks | ||
212 | */ | ||
213 | gen_cntl &= (~(0x7 << 15)); | ||
214 | gen_cntl |= (0x4 << 15); | ||
215 | pci_write_config_dword(dev, 0xD0, gen_cntl); | ||
216 | |||
217 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
218 | |||
219 | val = gen_cntl >> 15; | ||
220 | val &= 0x7; | ||
221 | if (val & 0x4) { | ||
222 | /* HPET is enabled in HPTC. Just not reported by BIOS */ | ||
223 | val &= 0x3; | ||
224 | force_hpet_address = 0xFED00000 | (val << 12); | ||
225 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
226 | force_hpet_address); | ||
227 | cached_dev = dev; | ||
228 | force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME; | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
233 | } | ||
234 | |||
235 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, | ||
236 | old_ich_force_enable_hpet); | ||
237 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, | ||
238 | old_ich_force_enable_hpet); | ||
239 | |||
240 | void force_hpet_resume(void) | ||
241 | { | ||
242 | switch (force_hpet_resume_type) { | ||
243 | case ICH_FORCE_HPET_RESUME: | ||
244 | return ich_force_hpet_resume(); | ||
245 | |||
246 | case OLD_ICH_FORCE_HPET_RESUME: | ||
247 | return old_ich_force_hpet_resume(); | ||
248 | |||
249 | default: | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | #endif | ||
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index af838f6b0b7f..32054bf5ba40 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -546,6 +546,37 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
546 | #endif | 546 | #endif |
547 | } | 547 | } |
548 | 548 | ||
549 | #define ENABLE_C1E_MASK 0x18000000 | ||
550 | #define CPUID_PROCESSOR_SIGNATURE 1 | ||
551 | #define CPUID_XFAM 0x0ff00000 | ||
552 | #define CPUID_XFAM_K8 0x00000000 | ||
553 | #define CPUID_XFAM_10H 0x00100000 | ||
554 | #define CPUID_XFAM_11H 0x00200000 | ||
555 | #define CPUID_XMOD 0x000f0000 | ||
556 | #define CPUID_XMOD_REV_F 0x00040000 | ||
557 | |||
558 | /* AMD systems with C1E don't have a working lAPIC timer. Check for that. */ | ||
559 | static __cpuinit int amd_apic_timer_broken(void) | ||
560 | { | ||
561 | u32 lo, hi; | ||
562 | u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); | ||
563 | switch (eax & CPUID_XFAM) { | ||
564 | case CPUID_XFAM_K8: | ||
565 | if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F) | ||
566 | break; | ||
567 | case CPUID_XFAM_10H: | ||
568 | case CPUID_XFAM_11H: | ||
569 | rdmsr(MSR_K8_ENABLE_C1E, lo, hi); | ||
570 | if (lo & ENABLE_C1E_MASK) | ||
571 | return 1; | ||
572 | break; | ||
573 | default: | ||
574 | /* err on the side of caution */ | ||
575 | return 1; | ||
576 | } | ||
577 | return 0; | ||
578 | } | ||
579 | |||
549 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 580 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) |
550 | { | 581 | { |
551 | unsigned level; | 582 | unsigned level; |
@@ -617,6 +648,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
617 | /* Family 10 doesn't support C states in MWAIT so don't use it */ | 648 | /* Family 10 doesn't support C states in MWAIT so don't use it */ |
618 | if (c->x86 == 0x10 && !force_mwait) | 649 | if (c->x86 == 0x10 && !force_mwait) |
619 | clear_bit(X86_FEATURE_MWAIT, &c->x86_capability); | 650 | clear_bit(X86_FEATURE_MWAIT, &c->x86_capability); |
651 | |||
652 | if (amd_apic_timer_broken()) | ||
653 | disable_apic_timer = 1; | ||
620 | } | 654 | } |
621 | 655 | ||
622 | static void __cpuinit detect_ht(struct cpuinfo_x86 *c) | 656 | static void __cpuinit detect_ht(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index 32f50783edc8..57ccf7cb6b91 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c | |||
@@ -223,8 +223,6 @@ void __cpuinit smp_callin(void) | |||
223 | local_irq_disable(); | 223 | local_irq_disable(); |
224 | Dprintk("Stack at about %p\n",&cpuid); | 224 | Dprintk("Stack at about %p\n",&cpuid); |
225 | 225 | ||
226 | disable_APIC_timer(); | ||
227 | |||
228 | /* | 226 | /* |
229 | * Save our processor parameters | 227 | * Save our processor parameters |
230 | */ | 228 | */ |
@@ -348,8 +346,6 @@ void __cpuinit start_secondary(void) | |||
348 | enable_8259A_irq(0); | 346 | enable_8259A_irq(0); |
349 | } | 347 | } |
350 | 348 | ||
351 | enable_APIC_timer(); | ||
352 | |||
353 | /* | 349 | /* |
354 | * The sibling maps must be set before turing the online map on for | 350 | * The sibling maps must be set before turing the online map on for |
355 | * this cpu | 351 | * this cpu |
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index 19a6c678d02e..56dadfc2f41c 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c | |||
@@ -157,6 +157,9 @@ EXPORT_SYMBOL(profile_pc); | |||
157 | */ | 157 | */ |
158 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 158 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
159 | { | 159 | { |
160 | /* Keep nmi watchdog up to date */ | ||
161 | per_cpu(irq_stat, smp_processor_id()).irq0_irqs++; | ||
162 | |||
160 | #ifdef CONFIG_X86_IO_APIC | 163 | #ifdef CONFIG_X86_IO_APIC |
161 | if (timer_ack) { | 164 | if (timer_ack) { |
162 | /* | 165 | /* |
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index 6d48a4e826d9..e0134d6c88da 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -28,11 +28,12 @@ | |||
28 | #include <linux/cpu.h> | 28 | #include <linux/cpu.h> |
29 | #include <linux/kallsyms.h> | 29 | #include <linux/kallsyms.h> |
30 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
31 | #include <linux/clockchips.h> | ||
32 | |||
31 | #ifdef CONFIG_ACPI | 33 | #ifdef CONFIG_ACPI |
32 | #include <acpi/achware.h> /* for PM timer frequency */ | 34 | #include <acpi/achware.h> /* for PM timer frequency */ |
33 | #include <acpi/acpi_bus.h> | 35 | #include <acpi/acpi_bus.h> |
34 | #endif | 36 | #endif |
35 | #include <asm/8253pit.h> | ||
36 | #include <asm/i8253.h> | 37 | #include <asm/i8253.h> |
37 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
38 | #include <asm/vsyscall.h> | 39 | #include <asm/vsyscall.h> |
@@ -47,12 +48,8 @@ | |||
47 | #include <asm/nmi.h> | 48 | #include <asm/nmi.h> |
48 | #include <asm/vgtod.h> | 49 | #include <asm/vgtod.h> |
49 | 50 | ||
50 | static char *timename = NULL; | ||
51 | |||
52 | DEFINE_SPINLOCK(rtc_lock); | 51 | DEFINE_SPINLOCK(rtc_lock); |
53 | EXPORT_SYMBOL(rtc_lock); | 52 | EXPORT_SYMBOL(rtc_lock); |
54 | DEFINE_SPINLOCK(i8253_lock); | ||
55 | EXPORT_SYMBOL(i8253_lock); | ||
56 | 53 | ||
57 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; | 54 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; |
58 | 55 | ||
@@ -153,45 +150,12 @@ int update_persistent_clock(struct timespec now) | |||
153 | return set_rtc_mmss(now.tv_sec); | 150 | return set_rtc_mmss(now.tv_sec); |
154 | } | 151 | } |
155 | 152 | ||
156 | void main_timer_handler(void) | 153 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) |
157 | { | 154 | { |
158 | /* | 155 | add_pda(irq0_irqs, 1); |
159 | * Here we are in the timer irq handler. We have irqs locally disabled (so we | ||
160 | * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running | ||
161 | * on the other CPU, so we need a lock. We also need to lock the vsyscall | ||
162 | * variables, because both do_timer() and us change them -arca+vojtech | ||
163 | */ | ||
164 | |||
165 | write_seqlock(&xtime_lock); | ||
166 | 156 | ||
167 | /* | 157 | global_clock_event->event_handler(global_clock_event); |
168 | * Do the timer stuff. | ||
169 | */ | ||
170 | |||
171 | do_timer(1); | ||
172 | #ifndef CONFIG_SMP | ||
173 | update_process_times(user_mode(get_irq_regs())); | ||
174 | #endif | ||
175 | 158 | ||
176 | /* | ||
177 | * In the SMP case we use the local APIC timer interrupt to do the profiling, | ||
178 | * except when we simulate SMP mode on a uniprocessor system, in that case we | ||
179 | * have to call the local interrupt handler. | ||
180 | */ | ||
181 | |||
182 | if (!using_apic_timer) | ||
183 | smp_local_timer_interrupt(); | ||
184 | |||
185 | write_sequnlock(&xtime_lock); | ||
186 | } | ||
187 | |||
188 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
189 | { | ||
190 | if (apic_runs_main_timer > 1) | ||
191 | return IRQ_HANDLED; | ||
192 | main_timer_handler(); | ||
193 | if (using_apic_timer) | ||
194 | smp_send_timer_broadcast_ipi(); | ||
195 | return IRQ_HANDLED; | 159 | return IRQ_HANDLED; |
196 | } | 160 | } |
197 | 161 | ||
@@ -292,97 +256,21 @@ static unsigned int __init tsc_calibrate_cpu_khz(void) | |||
292 | return pmc_now * tsc_khz / (tsc_now - tsc_start); | 256 | return pmc_now * tsc_khz / (tsc_now - tsc_start); |
293 | } | 257 | } |
294 | 258 | ||
295 | /* | ||
296 | * pit_calibrate_tsc() uses the speaker output (channel 2) of | ||
297 | * the PIT. This is better than using the timer interrupt output, | ||
298 | * because we can read the value of the speaker with just one inb(), | ||
299 | * where we need three i/o operations for the interrupt channel. | ||
300 | * We count how many ticks the TSC does in 50 ms. | ||
301 | */ | ||
302 | |||
303 | static unsigned int __init pit_calibrate_tsc(void) | ||
304 | { | ||
305 | unsigned long start, end; | ||
306 | unsigned long flags; | ||
307 | |||
308 | spin_lock_irqsave(&i8253_lock, flags); | ||
309 | |||
310 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | ||
311 | |||
312 | outb(0xb0, 0x43); | ||
313 | outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); | ||
314 | outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); | ||
315 | start = get_cycles_sync(); | ||
316 | while ((inb(0x61) & 0x20) == 0); | ||
317 | end = get_cycles_sync(); | ||
318 | |||
319 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
320 | |||
321 | return (end - start) / 50; | ||
322 | } | ||
323 | |||
324 | #define PIT_MODE 0x43 | ||
325 | #define PIT_CH0 0x40 | ||
326 | |||
327 | static void __pit_init(int val, u8 mode) | ||
328 | { | ||
329 | unsigned long flags; | ||
330 | |||
331 | spin_lock_irqsave(&i8253_lock, flags); | ||
332 | outb_p(mode, PIT_MODE); | ||
333 | outb_p(val & 0xff, PIT_CH0); /* LSB */ | ||
334 | outb_p(val >> 8, PIT_CH0); /* MSB */ | ||
335 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
336 | } | ||
337 | |||
338 | void __init pit_init(void) | ||
339 | { | ||
340 | __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ | ||
341 | } | ||
342 | |||
343 | void pit_stop_interrupt(void) | ||
344 | { | ||
345 | __pit_init(0, 0x30); /* mode 0 */ | ||
346 | } | ||
347 | |||
348 | void stop_timer_interrupt(void) | ||
349 | { | ||
350 | char *name; | ||
351 | if (hpet_address) { | ||
352 | name = "HPET"; | ||
353 | hpet_timer_stop_set_go(0); | ||
354 | } else { | ||
355 | name = "PIT"; | ||
356 | pit_stop_interrupt(); | ||
357 | } | ||
358 | printk(KERN_INFO "timer: %s interrupt stopped.\n", name); | ||
359 | } | ||
360 | |||
361 | static struct irqaction irq0 = { | 259 | static struct irqaction irq0 = { |
362 | .handler = timer_interrupt, | 260 | .handler = timer_event_interrupt, |
363 | .flags = IRQF_DISABLED | IRQF_IRQPOLL, | 261 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, |
364 | .mask = CPU_MASK_NONE, | 262 | .mask = CPU_MASK_NONE, |
365 | .name = "timer" | 263 | .name = "timer" |
366 | }; | 264 | }; |
367 | 265 | ||
368 | void __init time_init(void) | 266 | void __init time_init(void) |
369 | { | 267 | { |
370 | if (nohpet) | 268 | if (!hpet_enable()) |
371 | hpet_address = 0; | 269 | setup_pit_timer(); |
372 | 270 | ||
373 | if (hpet_arch_init()) | 271 | setup_irq(0, &irq0); |
374 | hpet_address = 0; | ||
375 | 272 | ||
376 | if (hpet_use_timer) { | 273 | tsc_calibrate(); |
377 | /* set tick_nsec to use the proper rate for HPET */ | ||
378 | tick_nsec = TICK_NSEC_HPET; | ||
379 | tsc_khz = hpet_calibrate_tsc(); | ||
380 | timename = "HPET"; | ||
381 | } else { | ||
382 | pit_init(); | ||
383 | tsc_khz = pit_calibrate_tsc(); | ||
384 | timename = "PIT"; | ||
385 | } | ||
386 | 274 | ||
387 | cpu_khz = tsc_khz; | 275 | cpu_khz = tsc_khz; |
388 | if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) && | 276 | if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) && |
@@ -398,50 +286,7 @@ void __init time_init(void) | |||
398 | else | 286 | else |
399 | vgetcpu_mode = VGETCPU_LSL; | 287 | vgetcpu_mode = VGETCPU_LSL; |
400 | 288 | ||
401 | set_cyc2ns_scale(tsc_khz); | ||
402 | printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", | 289 | printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", |
403 | cpu_khz / 1000, cpu_khz % 1000); | 290 | cpu_khz / 1000, cpu_khz % 1000); |
404 | init_tsc_clocksource(); | 291 | init_tsc_clocksource(); |
405 | |||
406 | setup_irq(0, &irq0); | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * sysfs support for the timer. | ||
411 | */ | ||
412 | |||
413 | static int timer_suspend(struct sys_device *dev, pm_message_t state) | ||
414 | { | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int timer_resume(struct sys_device *dev) | ||
419 | { | ||
420 | if (hpet_address) | ||
421 | hpet_reenable(); | ||
422 | else | ||
423 | i8254_timer_resume(); | ||
424 | return 0; | ||
425 | } | 292 | } |
426 | |||
427 | static struct sysdev_class timer_sysclass = { | ||
428 | .resume = timer_resume, | ||
429 | .suspend = timer_suspend, | ||
430 | set_kset_name("timer"), | ||
431 | }; | ||
432 | |||
433 | /* XXX this sysfs stuff should probably go elsewhere later -john */ | ||
434 | static struct sys_device device_timer = { | ||
435 | .id = 0, | ||
436 | .cls = &timer_sysclass, | ||
437 | }; | ||
438 | |||
439 | static int time_init_device(void) | ||
440 | { | ||
441 | int error = sysdev_class_register(&timer_sysclass); | ||
442 | if (!error) | ||
443 | error = sysdev_register(&device_timer); | ||
444 | return error; | ||
445 | } | ||
446 | |||
447 | device_initcall(time_init_device); | ||
diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 2a59bde663f2..9f22e542c374 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c | |||
@@ -6,7 +6,9 @@ | |||
6 | #include <linux/time.h> | 6 | #include <linux/time.h> |
7 | #include <linux/acpi.h> | 7 | #include <linux/acpi.h> |
8 | #include <linux/cpufreq.h> | 8 | #include <linux/cpufreq.h> |
9 | #include <linux/acpi_pmtmr.h> | ||
9 | 10 | ||
11 | #include <asm/hpet.h> | ||
10 | #include <asm/timex.h> | 12 | #include <asm/timex.h> |
11 | 13 | ||
12 | static int notsc __initdata = 0; | 14 | static int notsc __initdata = 0; |
@@ -18,7 +20,7 @@ EXPORT_SYMBOL(tsc_khz); | |||
18 | 20 | ||
19 | static unsigned int cyc2ns_scale __read_mostly; | 21 | static unsigned int cyc2ns_scale __read_mostly; |
20 | 22 | ||
21 | void set_cyc2ns_scale(unsigned long khz) | 23 | static inline void set_cyc2ns_scale(unsigned long khz) |
22 | { | 24 | { |
23 | cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz; | 25 | cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz; |
24 | } | 26 | } |
@@ -118,6 +120,95 @@ core_initcall(cpufreq_tsc); | |||
118 | 120 | ||
119 | #endif | 121 | #endif |
120 | 122 | ||
123 | #define MAX_RETRIES 5 | ||
124 | #define SMI_TRESHOLD 50000 | ||
125 | |||
126 | /* | ||
127 | * Read TSC and the reference counters. Take care of SMI disturbance | ||
128 | */ | ||
129 | static unsigned long __init tsc_read_refs(unsigned long *pm, | ||
130 | unsigned long *hpet) | ||
131 | { | ||
132 | unsigned long t1, t2; | ||
133 | int i; | ||
134 | |||
135 | for (i = 0; i < MAX_RETRIES; i++) { | ||
136 | t1 = get_cycles_sync(); | ||
137 | if (hpet) | ||
138 | *hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; | ||
139 | else | ||
140 | *pm = acpi_pm_read_early(); | ||
141 | t2 = get_cycles_sync(); | ||
142 | if ((t2 - t1) < SMI_TRESHOLD) | ||
143 | return t2; | ||
144 | } | ||
145 | return ULONG_MAX; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * tsc_calibrate - calibrate the tsc on boot | ||
150 | */ | ||
151 | void __init tsc_calibrate(void) | ||
152 | { | ||
153 | unsigned long flags, tsc1, tsc2, tr1, tr2, pm1, pm2, hpet1, hpet2; | ||
154 | int hpet = is_hpet_enabled(); | ||
155 | |||
156 | local_irq_save(flags); | ||
157 | |||
158 | tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); | ||
159 | |||
160 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | ||
161 | |||
162 | outb(0xb0, 0x43); | ||
163 | outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); | ||
164 | outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); | ||
165 | tr1 = get_cycles_sync(); | ||
166 | while ((inb(0x61) & 0x20) == 0); | ||
167 | tr2 = get_cycles_sync(); | ||
168 | |||
169 | tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); | ||
170 | |||
171 | local_irq_restore(flags); | ||
172 | |||
173 | /* | ||
174 | * Preset the result with the raw and inaccurate PIT | ||
175 | * calibration value | ||
176 | */ | ||
177 | tsc_khz = (tr2 - tr1) / 50; | ||
178 | |||
179 | /* hpet or pmtimer available ? */ | ||
180 | if (!hpet && !pm1 && !pm2) { | ||
181 | printk(KERN_INFO "TSC calibrated against PIT\n"); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | /* Check, whether the sampling was disturbed by an SMI */ | ||
186 | if (tsc1 == ULONG_MAX || tsc2 == ULONG_MAX) { | ||
187 | printk(KERN_WARNING "TSC calibration disturbed by SMI, " | ||
188 | "using PIT calibration result\n"); | ||
189 | return; | ||
190 | } | ||
191 | |||
192 | tsc2 = (tsc2 - tsc1) * 1000000L; | ||
193 | |||
194 | if (hpet) { | ||
195 | printk(KERN_INFO "TSC calibrated against HPET\n"); | ||
196 | if (hpet2 < hpet1) | ||
197 | hpet2 += 0x100000000; | ||
198 | hpet2 -= hpet1; | ||
199 | tsc1 = (hpet2 * hpet_readl(HPET_PERIOD)) / 1000000; | ||
200 | } else { | ||
201 | printk(KERN_INFO "TSC calibrated against PM_TIMER\n"); | ||
202 | if (pm2 < pm1) | ||
203 | pm2 += ACPI_PM_OVRRUN; | ||
204 | pm2 -= pm1; | ||
205 | tsc1 = (pm2 * 1000000000) / PMTMR_TICKS_PER_SEC; | ||
206 | } | ||
207 | |||
208 | tsc_khz = tsc2 / tsc1; | ||
209 | set_cyc2ns_scale(tsc_khz); | ||
210 | } | ||
211 | |||
121 | /* | 212 | /* |
122 | * Make an educated guess if the TSC is trustworthy and synchronized | 213 | * Make an educated guess if the TSC is trustworthy and synchronized |
123 | * over all CPUs. | 214 | * over all CPUs. |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index b1b98e614f7c..eb80f5aca54e 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -36,6 +36,18 @@ config GENERIC_CMOS_UPDATE | |||
36 | bool | 36 | bool |
37 | default y | 37 | default y |
38 | 38 | ||
39 | config CLOCKSOURCE_WATCHDOG | ||
40 | bool | ||
41 | default y | ||
42 | |||
43 | config GENERIC_CLOCKEVENTS | ||
44 | bool | ||
45 | default y | ||
46 | |||
47 | config GENERIC_CLOCKEVENTS_BROADCAST | ||
48 | bool | ||
49 | default y | ||
50 | |||
39 | config ZONE_DMA32 | 51 | config ZONE_DMA32 |
40 | bool | 52 | bool |
41 | default y | 53 | default y |
@@ -130,6 +142,8 @@ source "init/Kconfig" | |||
130 | 142 | ||
131 | menu "Processor type and features" | 143 | menu "Processor type and features" |
132 | 144 | ||
145 | source "kernel/time/Kconfig" | ||
146 | |||
133 | choice | 147 | choice |
134 | prompt "Subarchitecture Type" | 148 | prompt "Subarchitecture Type" |
135 | default X86_PC | 149 | default X86_PC |
diff --git a/block/Kconfig b/block/Kconfig index 2484e0e9d89c..e10895647f72 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
@@ -62,6 +62,10 @@ config BLK_DEV_BSG | |||
62 | protocols (e.g. Task Management Functions and SMP in Serial | 62 | protocols (e.g. Task Management Functions and SMP in Serial |
63 | Attached SCSI). | 63 | Attached SCSI). |
64 | 64 | ||
65 | config BLOCK_COMPAT | ||
66 | bool | ||
67 | default y | ||
68 | |||
65 | endif # BLOCK | 69 | endif # BLOCK |
66 | 70 | ||
67 | source block/Kconfig.iosched | 71 | source block/Kconfig.iosched |
diff --git a/block/Makefile b/block/Makefile index 3cfe7cebaa6a..826108190f00 100644 --- a/block/Makefile +++ b/block/Makefile | |||
@@ -11,4 +11,4 @@ obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o | |||
11 | obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o | 11 | obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o |
12 | 12 | ||
13 | obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o | 13 | obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o |
14 | obj-$(CONFIG_COMPAT) += compat_ioctl.o | 14 | obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 1e8287b4f40c..1f6fb38de017 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -276,21 +276,12 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | |||
276 | 276 | ||
277 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) | 277 | static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) |
278 | { | 278 | { |
279 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
280 | unsigned long reason; | 279 | unsigned long reason; |
281 | 280 | ||
282 | reason = pr->power.timer_broadcast_on_state < INT_MAX ? | 281 | reason = pr->power.timer_broadcast_on_state < INT_MAX ? |
283 | CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF; | 282 | CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF; |
284 | 283 | ||
285 | clockevents_notify(reason, &pr->id); | 284 | clockevents_notify(reason, &pr->id); |
286 | #else | ||
287 | cpumask_t mask = cpumask_of_cpu(pr->id); | ||
288 | |||
289 | if (pr->power.timer_broadcast_on_state < INT_MAX) | ||
290 | on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); | ||
291 | else | ||
292 | on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); | ||
293 | #endif | ||
294 | } | 285 | } |
295 | 286 | ||
296 | /* Power(C) State timer broadcast control */ | 287 | /* Power(C) State timer broadcast control */ |
@@ -298,8 +289,6 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
298 | struct acpi_processor_cx *cx, | 289 | struct acpi_processor_cx *cx, |
299 | int broadcast) | 290 | int broadcast) |
300 | { | 291 | { |
301 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
302 | |||
303 | int state = cx - pr->power.states; | 292 | int state = cx - pr->power.states; |
304 | 293 | ||
305 | if (state >= pr->power.timer_broadcast_on_state) { | 294 | if (state >= pr->power.timer_broadcast_on_state) { |
@@ -309,7 +298,6 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
309 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT; | 298 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT; |
310 | clockevents_notify(reason, &pr->id); | 299 | clockevents_notify(reason, &pr->id); |
311 | } | 300 | } |
312 | #endif | ||
313 | } | 301 | } |
314 | 302 | ||
315 | #else | 303 | #else |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 4245b7f80a49..ca4d7f0d09b7 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -361,8 +361,7 @@ config BLK_DEV_RAM_SIZE | |||
361 | default "4096" | 361 | default "4096" |
362 | help | 362 | help |
363 | The default value is 4096 kilobytes. Only change this if you know | 363 | The default value is 4096 kilobytes. Only change this if you know |
364 | what are you doing. If you are using IBM S/390, then set this to | 364 | what are you doing. |
365 | 8192. | ||
366 | 365 | ||
367 | config BLK_DEV_RAM_BLOCKSIZE | 366 | config BLK_DEV_RAM_BLOCKSIZE |
368 | int "Default RAM disk block size (bytes)" | 367 | int "Default RAM disk block size (bytes)" |
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 993fa7b89253..721f86f4f008 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -56,10 +56,6 @@ config CPU_FREQ_STAT_DETAILS | |||
56 | 56 | ||
57 | If in doubt, say N. | 57 | If in doubt, say N. |
58 | 58 | ||
59 | # Note that it is not currently possible to set the other governors (such as ondemand) | ||
60 | # as the default, since if they fail to initialise, cpufreq will be | ||
61 | # left in an undefined state. | ||
62 | |||
63 | choice | 59 | choice |
64 | prompt "Default CPUFreq governor" | 60 | prompt "Default CPUFreq governor" |
65 | default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110 | 61 | default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110 |
@@ -85,6 +81,29 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE | |||
85 | program shall be able to set the CPU dynamically without having | 81 | program shall be able to set the CPU dynamically without having |
86 | to enable the userspace governor manually. | 82 | to enable the userspace governor manually. |
87 | 83 | ||
84 | config CPU_FREQ_DEFAULT_GOV_ONDEMAND | ||
85 | bool "ondemand" | ||
86 | select CPU_FREQ_GOV_ONDEMAND | ||
87 | select CPU_FREQ_GOV_PERFORMANCE | ||
88 | help | ||
89 | Use the CPUFreq governor 'ondemand' as default. This allows | ||
90 | you to get a full dynamic frequency capable system by simply | ||
91 | loading your cpufreq low-level hardware driver. | ||
92 | Be aware that not all cpufreq drivers support the ondemand | ||
93 | governor. If unsure have a look at the help section of the | ||
94 | driver. Fallback governor will be the performance governor. | ||
95 | |||
96 | config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE | ||
97 | bool "conservative" | ||
98 | select CPU_FREQ_GOV_CONSERVATIVE | ||
99 | select CPU_FREQ_GOV_PERFORMANCE | ||
100 | help | ||
101 | Use the CPUFreq governor 'conservative' as default. This allows | ||
102 | you to get a full dynamic frequency capable system by simply | ||
103 | loading your cpufreq low-level hardware driver. | ||
104 | Be aware that not all cpufreq drivers support the conservative | ||
105 | governor. If unsure have a look at the help section of the | ||
106 | driver. Fallback governor will be the performance governor. | ||
88 | endchoice | 107 | endchoice |
89 | 108 | ||
90 | config CPU_FREQ_GOV_PERFORMANCE | 109 | config CPU_FREQ_GOV_PERFORMANCE |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2ce3de5e84af..5e626b12b97e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -763,6 +763,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
763 | init_completion(&policy->kobj_unregister); | 763 | init_completion(&policy->kobj_unregister); |
764 | INIT_WORK(&policy->update, handle_update); | 764 | INIT_WORK(&policy->update, handle_update); |
765 | 765 | ||
766 | /* Set governor before ->init, so that driver could check it */ | ||
767 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
766 | /* call driver. From then on the cpufreq must be able | 768 | /* call driver. From then on the cpufreq must be able |
767 | * to accept all calls to ->verify and ->setpolicy for this CPU | 769 | * to accept all calls to ->verify and ->setpolicy for this CPU |
768 | */ | 770 | */ |
@@ -1109,12 +1111,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu) | |||
1109 | unsigned int ret_freq = 0; | 1111 | unsigned int ret_freq = 0; |
1110 | 1112 | ||
1111 | if (policy) { | 1113 | if (policy) { |
1112 | if (unlikely(lock_policy_rwsem_read(cpu))) | ||
1113 | return ret_freq; | ||
1114 | |||
1115 | ret_freq = policy->cur; | 1114 | ret_freq = policy->cur; |
1116 | |||
1117 | unlock_policy_rwsem_read(cpu); | ||
1118 | cpufreq_cpu_put(policy); | 1115 | cpufreq_cpu_put(policy); |
1119 | } | 1116 | } |
1120 | 1117 | ||
@@ -1483,6 +1480,31 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, | |||
1483 | { | 1480 | { |
1484 | int ret; | 1481 | int ret; |
1485 | 1482 | ||
1483 | /* Only must be defined when default governor is known to have latency | ||
1484 | restrictions, like e.g. conservative or ondemand. | ||
1485 | That this is the case is already ensured in Kconfig | ||
1486 | */ | ||
1487 | #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE | ||
1488 | struct cpufreq_governor *gov = &cpufreq_gov_performance; | ||
1489 | #else | ||
1490 | struct cpufreq_governor *gov = NULL; | ||
1491 | #endif | ||
1492 | |||
1493 | if (policy->governor->max_transition_latency && | ||
1494 | policy->cpuinfo.transition_latency > | ||
1495 | policy->governor->max_transition_latency) { | ||
1496 | if (!gov) | ||
1497 | return -EINVAL; | ||
1498 | else { | ||
1499 | printk(KERN_WARNING "%s governor failed, too long" | ||
1500 | " transition latency of HW, fallback" | ||
1501 | " to %s governor\n", | ||
1502 | policy->governor->name, | ||
1503 | gov->name); | ||
1504 | policy->governor = gov; | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1486 | if (!try_module_get(policy->governor->owner)) | 1508 | if (!try_module_get(policy->governor->owner)) |
1487 | return -EINVAL; | 1509 | return -EINVAL; |
1488 | 1510 | ||
@@ -1703,7 +1725,7 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1703 | } | 1725 | } |
1704 | EXPORT_SYMBOL(cpufreq_update_policy); | 1726 | EXPORT_SYMBOL(cpufreq_update_policy); |
1705 | 1727 | ||
1706 | static int cpufreq_cpu_callback(struct notifier_block *nfb, | 1728 | static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, |
1707 | unsigned long action, void *hcpu) | 1729 | unsigned long action, void *hcpu) |
1708 | { | 1730 | { |
1709 | unsigned int cpu = (unsigned long)hcpu; | 1731 | unsigned int cpu = (unsigned long)hcpu; |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 26f440ccc3fb..4bd33ce8a6f3 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
@@ -58,7 +58,7 @@ static unsigned int def_sampling_rate; | |||
58 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) | 58 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) |
59 | #define DEF_SAMPLING_DOWN_FACTOR (1) | 59 | #define DEF_SAMPLING_DOWN_FACTOR (1) |
60 | #define MAX_SAMPLING_DOWN_FACTOR (10) | 60 | #define MAX_SAMPLING_DOWN_FACTOR (10) |
61 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) | 61 | #define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) |
62 | 62 | ||
63 | static void do_dbs_timer(struct work_struct *work); | 63 | static void do_dbs_timer(struct work_struct *work); |
64 | 64 | ||
@@ -466,9 +466,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
466 | (!policy->cur)) | 466 | (!policy->cur)) |
467 | return -EINVAL; | 467 | return -EINVAL; |
468 | 468 | ||
469 | if (policy->cpuinfo.transition_latency > | ||
470 | (TRANSITION_LATENCY_LIMIT * 1000)) | ||
471 | return -EINVAL; | ||
472 | if (this_dbs_info->enable) /* Already enabled */ | 469 | if (this_dbs_info->enable) /* Already enabled */ |
473 | break; | 470 | break; |
474 | 471 | ||
@@ -551,15 +548,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
551 | return 0; | 548 | return 0; |
552 | } | 549 | } |
553 | 550 | ||
554 | static struct cpufreq_governor cpufreq_gov_dbs = { | 551 | struct cpufreq_governor cpufreq_gov_conservative = { |
555 | .name = "conservative", | 552 | .name = "conservative", |
556 | .governor = cpufreq_governor_dbs, | 553 | .governor = cpufreq_governor_dbs, |
557 | .owner = THIS_MODULE, | 554 | .max_transition_latency = TRANSITION_LATENCY_LIMIT, |
555 | .owner = THIS_MODULE, | ||
558 | }; | 556 | }; |
557 | EXPORT_SYMBOL(cpufreq_gov_conservative); | ||
559 | 558 | ||
560 | static int __init cpufreq_gov_dbs_init(void) | 559 | static int __init cpufreq_gov_dbs_init(void) |
561 | { | 560 | { |
562 | return cpufreq_register_governor(&cpufreq_gov_dbs); | 561 | return cpufreq_register_governor(&cpufreq_gov_conservative); |
563 | } | 562 | } |
564 | 563 | ||
565 | static void __exit cpufreq_gov_dbs_exit(void) | 564 | static void __exit cpufreq_gov_dbs_exit(void) |
@@ -567,7 +566,7 @@ static void __exit cpufreq_gov_dbs_exit(void) | |||
567 | /* Make sure that the scheduled work is indeed not running */ | 566 | /* Make sure that the scheduled work is indeed not running */ |
568 | flush_scheduled_work(); | 567 | flush_scheduled_work(); |
569 | 568 | ||
570 | cpufreq_unregister_governor(&cpufreq_gov_dbs); | 569 | cpufreq_unregister_governor(&cpufreq_gov_conservative); |
571 | } | 570 | } |
572 | 571 | ||
573 | 572 | ||
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index e794527e4925..369f44595150 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -47,7 +47,7 @@ static unsigned int def_sampling_rate; | |||
47 | (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) | 47 | (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) |
48 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) | 48 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) |
49 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) | 49 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) |
50 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) | 50 | #define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) |
51 | 51 | ||
52 | static void do_dbs_timer(struct work_struct *work); | 52 | static void do_dbs_timer(struct work_struct *work); |
53 | 53 | ||
@@ -508,12 +508,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
508 | if ((!cpu_online(cpu)) || (!policy->cur)) | 508 | if ((!cpu_online(cpu)) || (!policy->cur)) |
509 | return -EINVAL; | 509 | return -EINVAL; |
510 | 510 | ||
511 | if (policy->cpuinfo.transition_latency > | ||
512 | (TRANSITION_LATENCY_LIMIT * 1000)) { | ||
513 | printk(KERN_WARNING "ondemand governor failed to load " | ||
514 | "due to too long transition latency\n"); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | if (this_dbs_info->enable) /* Already enabled */ | 511 | if (this_dbs_info->enable) /* Already enabled */ |
518 | break; | 512 | break; |
519 | 513 | ||
@@ -585,11 +579,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
585 | return 0; | 579 | return 0; |
586 | } | 580 | } |
587 | 581 | ||
588 | static struct cpufreq_governor cpufreq_gov_dbs = { | 582 | struct cpufreq_governor cpufreq_gov_ondemand = { |
589 | .name = "ondemand", | 583 | .name = "ondemand", |
590 | .governor = cpufreq_governor_dbs, | 584 | .governor = cpufreq_governor_dbs, |
591 | .owner = THIS_MODULE, | 585 | .max_transition_latency = TRANSITION_LATENCY_LIMIT, |
586 | .owner = THIS_MODULE, | ||
592 | }; | 587 | }; |
588 | EXPORT_SYMBOL(cpufreq_gov_ondemand); | ||
593 | 589 | ||
594 | static int __init cpufreq_gov_dbs_init(void) | 590 | static int __init cpufreq_gov_dbs_init(void) |
595 | { | 591 | { |
@@ -598,12 +594,12 @@ static int __init cpufreq_gov_dbs_init(void) | |||
598 | printk(KERN_ERR "Creation of kondemand failed\n"); | 594 | printk(KERN_ERR "Creation of kondemand failed\n"); |
599 | return -EFAULT; | 595 | return -EFAULT; |
600 | } | 596 | } |
601 | return cpufreq_register_governor(&cpufreq_gov_dbs); | 597 | return cpufreq_register_governor(&cpufreq_gov_ondemand); |
602 | } | 598 | } |
603 | 599 | ||
604 | static void __exit cpufreq_gov_dbs_exit(void) | 600 | static void __exit cpufreq_gov_dbs_exit(void) |
605 | { | 601 | { |
606 | cpufreq_unregister_governor(&cpufreq_gov_dbs); | 602 | cpufreq_unregister_governor(&cpufreq_gov_ondemand); |
607 | destroy_workqueue(kondemand_wq); | 603 | destroy_workqueue(kondemand_wq); |
608 | } | 604 | } |
609 | 605 | ||
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 917b9bab9ccb..8a45d0f93e26 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -164,8 +164,7 @@ freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) | |||
164 | return -1; | 164 | return -1; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void | 167 | static void __cpuexit cpufreq_stats_free_table(unsigned int cpu) |
168 | cpufreq_stats_free_table (unsigned int cpu) | ||
169 | { | 168 | { |
170 | struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; | 169 | struct cpufreq_stats *stat = cpufreq_stats_table[cpu]; |
171 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); | 170 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); |
@@ -305,8 +304,9 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, | |||
305 | return 0; | 304 | return 0; |
306 | } | 305 | } |
307 | 306 | ||
308 | static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, | 307 | static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, |
309 | unsigned long action, void *hcpu) | 308 | unsigned long action, |
309 | void *hcpu) | ||
310 | { | 310 | { |
311 | unsigned int cpu = (unsigned long)hcpu; | 311 | unsigned int cpu = (unsigned long)hcpu; |
312 | 312 | ||
@@ -323,7 +323,7 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, | |||
323 | return NOTIFY_OK; | 323 | return NOTIFY_OK; |
324 | } | 324 | } |
325 | 325 | ||
326 | static struct notifier_block cpufreq_stat_cpu_notifier = | 326 | static struct notifier_block cpufreq_stat_cpu_notifier __cpuinitdata = |
327 | { | 327 | { |
328 | .notifier_call = cpufreq_stat_cpu_callback, | 328 | .notifier_call = cpufreq_stat_cpu_callback, |
329 | }; | 329 | }; |
@@ -356,8 +356,7 @@ __init cpufreq_stats_init(void) | |||
356 | 356 | ||
357 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | 357 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); |
358 | for_each_online_cpu(cpu) { | 358 | for_each_online_cpu(cpu) { |
359 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, | 359 | cpufreq_update_policy(cpu); |
360 | CPU_ONLINE, (void *)(long)cpu); | ||
361 | } | 360 | } |
362 | return 0; | 361 | return 0; |
363 | } | 362 | } |
@@ -372,13 +371,12 @@ __exit cpufreq_stats_exit(void) | |||
372 | CPUFREQ_TRANSITION_NOTIFIER); | 371 | CPUFREQ_TRANSITION_NOTIFIER); |
373 | unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | 372 | unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); |
374 | for_each_online_cpu(cpu) { | 373 | for_each_online_cpu(cpu) { |
375 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, | 374 | cpufreq_stats_free_table(cpu); |
376 | CPU_DEAD, (void *)(long)cpu); | ||
377 | } | 375 | } |
378 | } | 376 | } |
379 | 377 | ||
380 | MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); | 378 | MODULE_AUTHOR ("Zou Nan hai <nanhai.zou@intel.com>"); |
381 | MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats" | 379 | MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats " |
382 | "through sysfs filesystem"); | 380 | "through sysfs filesystem"); |
383 | MODULE_LICENSE ("GPL"); | 381 | MODULE_LICENSE ("GPL"); |
384 | 382 | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index e1a44020ed2b..c19f77fbaf2a 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <asm/8253pit.h> | ||
21 | #include <asm/io.h> | 20 | #include <asm/io.h> |
22 | 21 | ||
23 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 22 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
@@ -29,6 +28,7 @@ MODULE_ALIAS("platform:pcspkr"); | |||
29 | /* Use the global PIT lock ! */ | 28 | /* Use the global PIT lock ! */ |
30 | #include <asm/i8253.h> | 29 | #include <asm/i8253.h> |
31 | #else | 30 | #else |
31 | #include <asm/8253pit.h> | ||
32 | static DEFINE_SPINLOCK(i8253_lock); | 32 | static DEFINE_SPINLOCK(i8253_lock); |
33 | #endif | 33 | #endif |
34 | 34 | ||
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index b04a178e5021..f8b79783c8b3 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/isapnp.h> | 20 | #include <linux/isapnp.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | 22 | ||
23 | extern const char *CardType[]; | ||
24 | static const char *avm_pci_rev = "$Revision: 1.29.2.4 $"; | 23 | static const char *avm_pci_rev = "$Revision: 1.29.2.4 $"; |
25 | 24 | ||
26 | #define AVM_FRITZ_PCI 1 | 25 | #define AVM_FRITZ_PCI 1 |
@@ -726,100 +725,15 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) | |||
726 | return(0); | 725 | return(0); |
727 | } | 726 | } |
728 | 727 | ||
729 | #ifdef CONFIG_PCI | 728 | static int __devinit avm_setup_rest(struct IsdnCardState *cs) |
730 | static struct pci_dev *dev_avm __devinitdata = NULL; | ||
731 | #endif | ||
732 | #ifdef __ISAPNP__ | ||
733 | static struct pnp_card *pnp_avm_c __devinitdata = NULL; | ||
734 | #endif | ||
735 | |||
736 | int __devinit | ||
737 | setup_avm_pcipnp(struct IsdnCard *card) | ||
738 | { | 729 | { |
739 | u_int val, ver; | 730 | u_int val, ver; |
740 | struct IsdnCardState *cs = card->cs; | ||
741 | char tmp[64]; | ||
742 | 731 | ||
743 | strcpy(tmp, avm_pci_rev); | ||
744 | printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); | ||
745 | if (cs->typ != ISDN_CTYPE_FRITZPCI) | ||
746 | return (0); | ||
747 | if (card->para[1]) { | ||
748 | /* old manual method */ | ||
749 | cs->hw.avm.cfg_reg = card->para[1]; | ||
750 | cs->irq = card->para[0]; | ||
751 | cs->subtyp = AVM_FRITZ_PNP; | ||
752 | goto ready; | ||
753 | } | ||
754 | #ifdef __ISAPNP__ | ||
755 | if (isapnp_present()) { | ||
756 | struct pnp_dev *pnp_avm_d = NULL; | ||
757 | if ((pnp_avm_c = pnp_find_card( | ||
758 | ISAPNP_VENDOR('A', 'V', 'M'), | ||
759 | ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { | ||
760 | if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, | ||
761 | ISAPNP_VENDOR('A', 'V', 'M'), | ||
762 | ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { | ||
763 | int err; | ||
764 | |||
765 | pnp_disable_dev(pnp_avm_d); | ||
766 | err = pnp_activate_dev(pnp_avm_d); | ||
767 | if (err<0) { | ||
768 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
769 | __FUNCTION__, err); | ||
770 | return(0); | ||
771 | } | ||
772 | cs->hw.avm.cfg_reg = | ||
773 | pnp_port_start(pnp_avm_d, 0); | ||
774 | cs->irq = pnp_irq(pnp_avm_d, 0); | ||
775 | if (!cs->irq) { | ||
776 | printk(KERN_ERR "FritzPnP:No IRQ\n"); | ||
777 | return(0); | ||
778 | } | ||
779 | if (!cs->hw.avm.cfg_reg) { | ||
780 | printk(KERN_ERR "FritzPnP:No IO address\n"); | ||
781 | return(0); | ||
782 | } | ||
783 | cs->subtyp = AVM_FRITZ_PNP; | ||
784 | goto ready; | ||
785 | } | ||
786 | } | ||
787 | } else { | ||
788 | printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); | ||
789 | } | ||
790 | #endif | ||
791 | #ifdef CONFIG_PCI | ||
792 | if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, | ||
793 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { | ||
794 | if (pci_enable_device(dev_avm)) | ||
795 | return(0); | ||
796 | cs->irq = dev_avm->irq; | ||
797 | if (!cs->irq) { | ||
798 | printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); | ||
799 | return(0); | ||
800 | } | ||
801 | cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); | ||
802 | if (!cs->hw.avm.cfg_reg) { | ||
803 | printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); | ||
804 | return(0); | ||
805 | } | ||
806 | cs->subtyp = AVM_FRITZ_PCI; | ||
807 | } else { | ||
808 | printk(KERN_WARNING "FritzPCI: No PCI card found\n"); | ||
809 | return(0); | ||
810 | } | ||
811 | cs->irq_flags |= IRQF_SHARED; | ||
812 | #else | ||
813 | printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); | ||
814 | return (0); | ||
815 | #endif /* CONFIG_PCI */ | ||
816 | ready: | ||
817 | cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; | 732 | cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; |
818 | if (!request_region(cs->hw.avm.cfg_reg, 32, | 733 | if (!request_region(cs->hw.avm.cfg_reg, 32, |
819 | (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) { | 734 | (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) { |
820 | printk(KERN_WARNING | 735 | printk(KERN_WARNING |
821 | "HiSax: %s config port %x-%x already in use\n", | 736 | "HiSax: Fritz!PCI/PNP config port %x-%x already in use\n", |
822 | CardType[card->typ], | ||
823 | cs->hw.avm.cfg_reg, | 737 | cs->hw.avm.cfg_reg, |
824 | cs->hw.avm.cfg_reg + 31); | 738 | cs->hw.avm.cfg_reg + 31); |
825 | return (0); | 739 | return (0); |
@@ -860,3 +774,137 @@ ready: | |||
860 | ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); | 774 | ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); |
861 | return (1); | 775 | return (1); |
862 | } | 776 | } |
777 | |||
778 | #ifndef __ISAPNP__ | ||
779 | |||
780 | static int __devinit avm_pnp_setup(struct IsdnCardState *cs) | ||
781 | { | ||
782 | return(1); /* no-op: success */ | ||
783 | } | ||
784 | |||
785 | #else | ||
786 | |||
787 | static struct pnp_card *pnp_avm_c __devinitdata = NULL; | ||
788 | |||
789 | static int __devinit avm_pnp_setup(struct IsdnCardState *cs) | ||
790 | { | ||
791 | struct pnp_dev *pnp_avm_d = NULL; | ||
792 | |||
793 | if (!isapnp_present()) | ||
794 | return(1); /* no-op: success */ | ||
795 | |||
796 | if ((pnp_avm_c = pnp_find_card( | ||
797 | ISAPNP_VENDOR('A', 'V', 'M'), | ||
798 | ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { | ||
799 | if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, | ||
800 | ISAPNP_VENDOR('A', 'V', 'M'), | ||
801 | ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { | ||
802 | int err; | ||
803 | |||
804 | pnp_disable_dev(pnp_avm_d); | ||
805 | err = pnp_activate_dev(pnp_avm_d); | ||
806 | if (err<0) { | ||
807 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
808 | __FUNCTION__, err); | ||
809 | return(0); | ||
810 | } | ||
811 | cs->hw.avm.cfg_reg = | ||
812 | pnp_port_start(pnp_avm_d, 0); | ||
813 | cs->irq = pnp_irq(pnp_avm_d, 0); | ||
814 | if (!cs->irq) { | ||
815 | printk(KERN_ERR "FritzPnP:No IRQ\n"); | ||
816 | return(0); | ||
817 | } | ||
818 | if (!cs->hw.avm.cfg_reg) { | ||
819 | printk(KERN_ERR "FritzPnP:No IO address\n"); | ||
820 | return(0); | ||
821 | } | ||
822 | cs->subtyp = AVM_FRITZ_PNP; | ||
823 | |||
824 | return (2); /* goto 'ready' label */ | ||
825 | } | ||
826 | } | ||
827 | |||
828 | return (1); | ||
829 | } | ||
830 | |||
831 | #endif /* __ISAPNP__ */ | ||
832 | |||
833 | #ifndef CONFIG_PCI | ||
834 | |||
835 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | ||
836 | { | ||
837 | return(1); /* no-op: success */ | ||
838 | } | ||
839 | |||
840 | #else | ||
841 | |||
842 | static struct pci_dev *dev_avm __devinitdata = NULL; | ||
843 | |||
844 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | ||
845 | { | ||
846 | if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, | ||
847 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { | ||
848 | |||
849 | if (pci_enable_device(dev_avm)) | ||
850 | return(0); | ||
851 | |||
852 | cs->irq = dev_avm->irq; | ||
853 | if (!cs->irq) { | ||
854 | printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); | ||
855 | return(0); | ||
856 | } | ||
857 | |||
858 | cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); | ||
859 | if (!cs->hw.avm.cfg_reg) { | ||
860 | printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); | ||
861 | return(0); | ||
862 | } | ||
863 | |||
864 | cs->subtyp = AVM_FRITZ_PCI; | ||
865 | } else { | ||
866 | printk(KERN_WARNING "FritzPCI: No PCI card found\n"); | ||
867 | return(0); | ||
868 | } | ||
869 | |||
870 | cs->irq_flags |= IRQF_SHARED; | ||
871 | |||
872 | return (1); | ||
873 | } | ||
874 | |||
875 | #endif /* CONFIG_PCI */ | ||
876 | |||
877 | int __devinit | ||
878 | setup_avm_pcipnp(struct IsdnCard *card) | ||
879 | { | ||
880 | struct IsdnCardState *cs = card->cs; | ||
881 | char tmp[64]; | ||
882 | int rc; | ||
883 | |||
884 | strcpy(tmp, avm_pci_rev); | ||
885 | printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); | ||
886 | |||
887 | if (cs->typ != ISDN_CTYPE_FRITZPCI) | ||
888 | return (0); | ||
889 | |||
890 | if (card->para[1]) { | ||
891 | /* old manual method */ | ||
892 | cs->hw.avm.cfg_reg = card->para[1]; | ||
893 | cs->irq = card->para[0]; | ||
894 | cs->subtyp = AVM_FRITZ_PNP; | ||
895 | goto ready; | ||
896 | } | ||
897 | |||
898 | rc = avm_pnp_setup(cs); | ||
899 | if (rc < 1) | ||
900 | return (0); | ||
901 | if (rc == 2) | ||
902 | goto ready; | ||
903 | |||
904 | rc = avm_pci_setup(cs); | ||
905 | if (rc < 1) | ||
906 | return (0); | ||
907 | |||
908 | ready: | ||
909 | return avm_setup_rest(cs); | ||
910 | } | ||
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index 6339bb443f62..99ef3b43fcd7 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include "bkm_ax.h" | 21 | #include "bkm_ax.h" |
22 | 22 | ||
23 | #ifdef CONFIG_PCI | ||
24 | |||
25 | #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ | 23 | #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ |
26 | 24 | ||
27 | extern const char *CardType[]; | 25 | extern const char *CardType[]; |
@@ -279,12 +277,9 @@ static u_char pci_bus __devinitdata = 0; | |||
279 | static u_char pci_device_fn __devinitdata = 0; | 277 | static u_char pci_device_fn __devinitdata = 0; |
280 | static u_char pci_irq __devinitdata = 0; | 278 | static u_char pci_irq __devinitdata = 0; |
281 | 279 | ||
282 | #endif /* CONFIG_PCI */ | ||
283 | |||
284 | int __devinit | 280 | int __devinit |
285 | setup_sct_quadro(struct IsdnCard *card) | 281 | setup_sct_quadro(struct IsdnCard *card) |
286 | { | 282 | { |
287 | #ifdef CONFIG_PCI | ||
288 | struct IsdnCardState *cs = card->cs; | 283 | struct IsdnCardState *cs = card->cs; |
289 | char tmp[64]; | 284 | char tmp[64]; |
290 | u_int found = 0; | 285 | u_int found = 0; |
@@ -442,7 +437,4 @@ setup_sct_quadro(struct IsdnCard *card) | |||
442 | sct_quadro_subtypes[cs->subtyp], | 437 | sct_quadro_subtypes[cs->subtyp], |
443 | readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); | 438 | readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); |
444 | return (1); | 439 | return (1); |
445 | #else | ||
446 | printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); | ||
447 | #endif /* CONFIG_PCI */ | ||
448 | } | 440 | } |
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 6eebeb441bfd..826745078746 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/isapnp.h> | 26 | #include <linux/isapnp.h> |
27 | 27 | ||
28 | extern const char *CardType[]; | ||
29 | |||
30 | static const char *Diva_revision = "$Revision: 1.33.2.6 $"; | 28 | static const char *Diva_revision = "$Revision: 1.33.2.6 $"; |
31 | 29 | ||
32 | #define byteout(addr,val) outb(val,addr) | 30 | #define byteout(addr,val) outb(val,addr) |
@@ -906,225 +904,15 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) | |||
906 | return(0); | 904 | return(0); |
907 | } | 905 | } |
908 | 906 | ||
909 | static struct pci_dev *dev_diva __devinitdata = NULL; | 907 | static int __devinit setup_diva_common(struct IsdnCardState *cs) |
910 | static struct pci_dev *dev_diva_u __devinitdata = NULL; | ||
911 | static struct pci_dev *dev_diva201 __devinitdata = NULL; | ||
912 | static struct pci_dev *dev_diva202 __devinitdata = NULL; | ||
913 | |||
914 | #ifdef __ISAPNP__ | ||
915 | static struct isapnp_device_id diva_ids[] __devinitdata = { | ||
916 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
917 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
918 | (unsigned long) "Diva picola" }, | ||
919 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
920 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), | ||
921 | (unsigned long) "Diva picola" }, | ||
922 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
923 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
924 | (unsigned long) "Diva 2.0" }, | ||
925 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
926 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), | ||
927 | (unsigned long) "Diva 2.0" }, | ||
928 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
929 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
930 | (unsigned long) "Diva 2.01" }, | ||
931 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
932 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), | ||
933 | (unsigned long) "Diva 2.01" }, | ||
934 | { 0, } | ||
935 | }; | ||
936 | |||
937 | static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0]; | ||
938 | static struct pnp_card *pnp_c __devinitdata = NULL; | ||
939 | #endif | ||
940 | |||
941 | |||
942 | int __devinit | ||
943 | setup_diva(struct IsdnCard *card) | ||
944 | { | 908 | { |
945 | int bytecnt = 8; | 909 | int bytecnt; |
946 | u_char val; | 910 | u_char val; |
947 | struct IsdnCardState *cs = card->cs; | ||
948 | char tmp[64]; | ||
949 | |||
950 | strcpy(tmp, Diva_revision); | ||
951 | printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); | ||
952 | if (cs->typ != ISDN_CTYPE_DIEHLDIVA) | ||
953 | return(0); | ||
954 | cs->hw.diva.status = 0; | ||
955 | if (card->para[1]) { | ||
956 | cs->hw.diva.ctrl_reg = 0; | ||
957 | cs->hw.diva.cfg_reg = card->para[1]; | ||
958 | val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, | ||
959 | cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); | ||
960 | printk(KERN_INFO "Diva: IPAC version %x\n", val); | ||
961 | if ((val == 1) || (val==2)) { | ||
962 | cs->subtyp = DIVA_IPAC_ISA; | ||
963 | cs->hw.diva.ctrl = 0; | ||
964 | cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; | ||
965 | cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; | ||
966 | cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; | ||
967 | cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; | ||
968 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
969 | } else { | ||
970 | cs->subtyp = DIVA_ISA; | ||
971 | cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; | ||
972 | cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; | ||
973 | cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; | ||
974 | cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; | ||
975 | cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; | ||
976 | } | ||
977 | cs->irq = card->para[0]; | ||
978 | } else { | ||
979 | #ifdef __ISAPNP__ | ||
980 | if (isapnp_present()) { | ||
981 | struct pnp_dev *pnp_d; | ||
982 | while(ipid->card_vendor) { | ||
983 | if ((pnp_c = pnp_find_card(ipid->card_vendor, | ||
984 | ipid->card_device, pnp_c))) { | ||
985 | pnp_d = NULL; | ||
986 | if ((pnp_d = pnp_find_dev(pnp_c, | ||
987 | ipid->vendor, ipid->function, pnp_d))) { | ||
988 | int err; | ||
989 | |||
990 | printk(KERN_INFO "HiSax: %s detected\n", | ||
991 | (char *)ipid->driver_data); | ||
992 | pnp_disable_dev(pnp_d); | ||
993 | err = pnp_activate_dev(pnp_d); | ||
994 | if (err<0) { | ||
995 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
996 | __FUNCTION__, err); | ||
997 | return(0); | ||
998 | } | ||
999 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
1000 | card->para[0] = pnp_irq(pnp_d, 0); | ||
1001 | if (!card->para[0] || !card->para[1]) { | ||
1002 | printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", | ||
1003 | card->para[0], card->para[1]); | ||
1004 | pnp_disable_dev(pnp_d); | ||
1005 | return(0); | ||
1006 | } | ||
1007 | cs->hw.diva.cfg_reg = card->para[1]; | ||
1008 | cs->irq = card->para[0]; | ||
1009 | if (ipid->function == ISAPNP_FUNCTION(0xA1)) { | ||
1010 | cs->subtyp = DIVA_IPAC_ISA; | ||
1011 | cs->hw.diva.ctrl = 0; | ||
1012 | cs->hw.diva.isac = | ||
1013 | card->para[1] + DIVA_IPAC_DATA; | ||
1014 | cs->hw.diva.hscx = | ||
1015 | card->para[1] + DIVA_IPAC_DATA; | ||
1016 | cs->hw.diva.isac_adr = | ||
1017 | card->para[1] + DIVA_IPAC_ADR; | ||
1018 | cs->hw.diva.hscx_adr = | ||
1019 | card->para[1] + DIVA_IPAC_ADR; | ||
1020 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1021 | } else { | ||
1022 | cs->subtyp = DIVA_ISA; | ||
1023 | cs->hw.diva.ctrl = | ||
1024 | card->para[1] + DIVA_ISA_CTRL; | ||
1025 | cs->hw.diva.isac = | ||
1026 | card->para[1] + DIVA_ISA_ISAC_DATA; | ||
1027 | cs->hw.diva.hscx = | ||
1028 | card->para[1] + DIVA_HSCX_DATA; | ||
1029 | cs->hw.diva.isac_adr = | ||
1030 | card->para[1] + DIVA_ISA_ISAC_ADR; | ||
1031 | cs->hw.diva.hscx_adr = | ||
1032 | card->para[1] + DIVA_HSCX_ADR; | ||
1033 | } | ||
1034 | goto ready; | ||
1035 | } else { | ||
1036 | printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); | ||
1037 | return(0); | ||
1038 | } | ||
1039 | } | ||
1040 | ipid++; | ||
1041 | pnp_c=NULL; | ||
1042 | } | ||
1043 | if (!ipid->card_vendor) { | ||
1044 | printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); | ||
1045 | } | ||
1046 | } | ||
1047 | #endif | ||
1048 | #ifdef CONFIG_PCI | ||
1049 | cs->subtyp = 0; | ||
1050 | if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1051 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { | ||
1052 | if (pci_enable_device(dev_diva)) | ||
1053 | return(0); | ||
1054 | cs->subtyp = DIVA_PCI; | ||
1055 | cs->irq = dev_diva->irq; | ||
1056 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); | ||
1057 | } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1058 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { | ||
1059 | if (pci_enable_device(dev_diva_u)) | ||
1060 | return(0); | ||
1061 | cs->subtyp = DIVA_PCI; | ||
1062 | cs->irq = dev_diva_u->irq; | ||
1063 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); | ||
1064 | } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1065 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { | ||
1066 | if (pci_enable_device(dev_diva201)) | ||
1067 | return(0); | ||
1068 | cs->subtyp = DIVA_IPAC_PCI; | ||
1069 | cs->irq = dev_diva201->irq; | ||
1070 | cs->hw.diva.pci_cfg = | ||
1071 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); | ||
1072 | cs->hw.diva.cfg_reg = | ||
1073 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); | ||
1074 | } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1075 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { | ||
1076 | if (pci_enable_device(dev_diva202)) | ||
1077 | return(0); | ||
1078 | cs->subtyp = DIVA_IPACX_PCI; | ||
1079 | cs->irq = dev_diva202->irq; | ||
1080 | cs->hw.diva.pci_cfg = | ||
1081 | (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096); | ||
1082 | cs->hw.diva.cfg_reg = | ||
1083 | (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096); | ||
1084 | } else { | ||
1085 | printk(KERN_WARNING "Diva: No PCI card found\n"); | ||
1086 | return(0); | ||
1087 | } | ||
1088 | |||
1089 | if (!cs->irq) { | ||
1090 | printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); | ||
1091 | iounmap_diva(cs); | ||
1092 | return(0); | ||
1093 | } | ||
1094 | |||
1095 | if (!cs->hw.diva.cfg_reg) { | ||
1096 | printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); | ||
1097 | iounmap_diva(cs); | ||
1098 | return(0); | ||
1099 | } | ||
1100 | cs->irq_flags |= IRQF_SHARED; | ||
1101 | #else | ||
1102 | printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); | ||
1103 | printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); | ||
1104 | return (0); | ||
1105 | #endif /* CONFIG_PCI */ | ||
1106 | if ((cs->subtyp == DIVA_IPAC_PCI) || | ||
1107 | (cs->subtyp == DIVA_IPACX_PCI) ) { | ||
1108 | cs->hw.diva.ctrl = 0; | ||
1109 | cs->hw.diva.isac = 0; | ||
1110 | cs->hw.diva.hscx = 0; | ||
1111 | cs->hw.diva.isac_adr = 0; | ||
1112 | cs->hw.diva.hscx_adr = 0; | ||
1113 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1114 | bytecnt = 0; | ||
1115 | } else { | ||
1116 | cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; | ||
1117 | cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; | ||
1118 | cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; | ||
1119 | cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; | ||
1120 | cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; | ||
1121 | bytecnt = 32; | ||
1122 | } | ||
1123 | } | ||
1124 | 911 | ||
1125 | #ifdef __ISAPNP__ | 912 | if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) |
1126 | ready: | 913 | bytecnt = 8; |
1127 | #endif | 914 | else |
915 | bytecnt = 32; | ||
1128 | 916 | ||
1129 | printk(KERN_INFO | 917 | printk(KERN_INFO |
1130 | "Diva: %s card configured at %#lx IRQ %d\n", | 918 | "Diva: %s card configured at %#lx IRQ %d\n", |
@@ -1145,7 +933,7 @@ ready: | |||
1145 | if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) { | 933 | if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) { |
1146 | printk(KERN_WARNING | 934 | printk(KERN_WARNING |
1147 | "HiSax: %s config port %lx-%lx already in use\n", | 935 | "HiSax: %s config port %lx-%lx already in use\n", |
1148 | CardType[card->typ], | 936 | "diva", |
1149 | cs->hw.diva.cfg_reg, | 937 | cs->hw.diva.cfg_reg, |
1150 | cs->hw.diva.cfg_reg + bytecnt); | 938 | cs->hw.diva.cfg_reg + bytecnt); |
1151 | iounmap_diva(cs); | 939 | iounmap_diva(cs); |
@@ -1206,3 +994,290 @@ ready: | |||
1206 | } | 994 | } |
1207 | return (1); | 995 | return (1); |
1208 | } | 996 | } |
997 | |||
998 | #ifdef CONFIG_ISA | ||
999 | |||
1000 | static int __devinit setup_diva_isa(struct IsdnCard *card) | ||
1001 | { | ||
1002 | struct IsdnCardState *cs = card->cs; | ||
1003 | u_char val; | ||
1004 | |||
1005 | if (!card->para[1]) | ||
1006 | return (-1); /* card not found; continue search */ | ||
1007 | |||
1008 | cs->hw.diva.ctrl_reg = 0; | ||
1009 | cs->hw.diva.cfg_reg = card->para[1]; | ||
1010 | val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, | ||
1011 | cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); | ||
1012 | printk(KERN_INFO "Diva: IPAC version %x\n", val); | ||
1013 | if ((val == 1) || (val==2)) { | ||
1014 | cs->subtyp = DIVA_IPAC_ISA; | ||
1015 | cs->hw.diva.ctrl = 0; | ||
1016 | cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; | ||
1017 | cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; | ||
1018 | cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; | ||
1019 | cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; | ||
1020 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1021 | } else { | ||
1022 | cs->subtyp = DIVA_ISA; | ||
1023 | cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; | ||
1024 | cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; | ||
1025 | cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; | ||
1026 | cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; | ||
1027 | cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; | ||
1028 | } | ||
1029 | cs->irq = card->para[0]; | ||
1030 | |||
1031 | return (1); /* card found */ | ||
1032 | } | ||
1033 | |||
1034 | #else /* if !CONFIG_ISA */ | ||
1035 | |||
1036 | static int __devinit setup_diva_isa(struct IsdnCard *card) | ||
1037 | { | ||
1038 | return (-1); /* card not found; continue search */ | ||
1039 | } | ||
1040 | |||
1041 | #endif /* CONFIG_ISA */ | ||
1042 | |||
1043 | #ifdef __ISAPNP__ | ||
1044 | static struct isapnp_device_id diva_ids[] __devinitdata = { | ||
1045 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
1046 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
1047 | (unsigned long) "Diva picola" }, | ||
1048 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), | ||
1049 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), | ||
1050 | (unsigned long) "Diva picola" }, | ||
1051 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
1052 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
1053 | (unsigned long) "Diva 2.0" }, | ||
1054 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), | ||
1055 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), | ||
1056 | (unsigned long) "Diva 2.0" }, | ||
1057 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
1058 | ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
1059 | (unsigned long) "Diva 2.01" }, | ||
1060 | { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), | ||
1061 | ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), | ||
1062 | (unsigned long) "Diva 2.01" }, | ||
1063 | { 0, } | ||
1064 | }; | ||
1065 | |||
1066 | static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0]; | ||
1067 | static struct pnp_card *pnp_c __devinitdata = NULL; | ||
1068 | |||
1069 | static int __devinit setup_diva_isapnp(struct IsdnCard *card) | ||
1070 | { | ||
1071 | struct IsdnCardState *cs = card->cs; | ||
1072 | struct pnp_dev *pnp_d; | ||
1073 | |||
1074 | if (!isapnp_present()) | ||
1075 | return (-1); /* card not found; continue search */ | ||
1076 | |||
1077 | while(ipid->card_vendor) { | ||
1078 | if ((pnp_c = pnp_find_card(ipid->card_vendor, | ||
1079 | ipid->card_device, pnp_c))) { | ||
1080 | pnp_d = NULL; | ||
1081 | if ((pnp_d = pnp_find_dev(pnp_c, | ||
1082 | ipid->vendor, ipid->function, pnp_d))) { | ||
1083 | int err; | ||
1084 | |||
1085 | printk(KERN_INFO "HiSax: %s detected\n", | ||
1086 | (char *)ipid->driver_data); | ||
1087 | pnp_disable_dev(pnp_d); | ||
1088 | err = pnp_activate_dev(pnp_d); | ||
1089 | if (err<0) { | ||
1090 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
1091 | __FUNCTION__, err); | ||
1092 | return(0); | ||
1093 | } | ||
1094 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
1095 | card->para[0] = pnp_irq(pnp_d, 0); | ||
1096 | if (!card->para[0] || !card->para[1]) { | ||
1097 | printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", | ||
1098 | card->para[0], card->para[1]); | ||
1099 | pnp_disable_dev(pnp_d); | ||
1100 | return(0); | ||
1101 | } | ||
1102 | cs->hw.diva.cfg_reg = card->para[1]; | ||
1103 | cs->irq = card->para[0]; | ||
1104 | if (ipid->function == ISAPNP_FUNCTION(0xA1)) { | ||
1105 | cs->subtyp = DIVA_IPAC_ISA; | ||
1106 | cs->hw.diva.ctrl = 0; | ||
1107 | cs->hw.diva.isac = | ||
1108 | card->para[1] + DIVA_IPAC_DATA; | ||
1109 | cs->hw.diva.hscx = | ||
1110 | card->para[1] + DIVA_IPAC_DATA; | ||
1111 | cs->hw.diva.isac_adr = | ||
1112 | card->para[1] + DIVA_IPAC_ADR; | ||
1113 | cs->hw.diva.hscx_adr = | ||
1114 | card->para[1] + DIVA_IPAC_ADR; | ||
1115 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1116 | } else { | ||
1117 | cs->subtyp = DIVA_ISA; | ||
1118 | cs->hw.diva.ctrl = | ||
1119 | card->para[1] + DIVA_ISA_CTRL; | ||
1120 | cs->hw.diva.isac = | ||
1121 | card->para[1] + DIVA_ISA_ISAC_DATA; | ||
1122 | cs->hw.diva.hscx = | ||
1123 | card->para[1] + DIVA_HSCX_DATA; | ||
1124 | cs->hw.diva.isac_adr = | ||
1125 | card->para[1] + DIVA_ISA_ISAC_ADR; | ||
1126 | cs->hw.diva.hscx_adr = | ||
1127 | card->para[1] + DIVA_HSCX_ADR; | ||
1128 | } | ||
1129 | return (1); /* card found */ | ||
1130 | } else { | ||
1131 | printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); | ||
1132 | return(0); | ||
1133 | } | ||
1134 | } | ||
1135 | ipid++; | ||
1136 | pnp_c=NULL; | ||
1137 | } | ||
1138 | |||
1139 | return (-1); /* card not found; continue search */ | ||
1140 | } | ||
1141 | |||
1142 | #else /* if !ISAPNP */ | ||
1143 | |||
1144 | static int __devinit setup_diva_isapnp(struct IsdnCard *card) | ||
1145 | { | ||
1146 | return (-1); /* card not found; continue search */ | ||
1147 | } | ||
1148 | |||
1149 | #endif /* ISAPNP */ | ||
1150 | |||
1151 | #ifdef CONFIG_PCI | ||
1152 | static struct pci_dev *dev_diva __devinitdata = NULL; | ||
1153 | static struct pci_dev *dev_diva_u __devinitdata = NULL; | ||
1154 | static struct pci_dev *dev_diva201 __devinitdata = NULL; | ||
1155 | static struct pci_dev *dev_diva202 __devinitdata = NULL; | ||
1156 | |||
1157 | static int __devinit setup_diva_pci(struct IsdnCard *card) | ||
1158 | { | ||
1159 | struct IsdnCardState *cs = card->cs; | ||
1160 | |||
1161 | cs->subtyp = 0; | ||
1162 | if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1163 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { | ||
1164 | if (pci_enable_device(dev_diva)) | ||
1165 | return(0); | ||
1166 | cs->subtyp = DIVA_PCI; | ||
1167 | cs->irq = dev_diva->irq; | ||
1168 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); | ||
1169 | } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1170 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { | ||
1171 | if (pci_enable_device(dev_diva_u)) | ||
1172 | return(0); | ||
1173 | cs->subtyp = DIVA_PCI; | ||
1174 | cs->irq = dev_diva_u->irq; | ||
1175 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); | ||
1176 | } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1177 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { | ||
1178 | if (pci_enable_device(dev_diva201)) | ||
1179 | return(0); | ||
1180 | cs->subtyp = DIVA_IPAC_PCI; | ||
1181 | cs->irq = dev_diva201->irq; | ||
1182 | cs->hw.diva.pci_cfg = | ||
1183 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); | ||
1184 | cs->hw.diva.cfg_reg = | ||
1185 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); | ||
1186 | } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, | ||
1187 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { | ||
1188 | if (pci_enable_device(dev_diva202)) | ||
1189 | return(0); | ||
1190 | cs->subtyp = DIVA_IPACX_PCI; | ||
1191 | cs->irq = dev_diva202->irq; | ||
1192 | cs->hw.diva.pci_cfg = | ||
1193 | (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096); | ||
1194 | cs->hw.diva.cfg_reg = | ||
1195 | (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096); | ||
1196 | } else { | ||
1197 | return (-1); /* card not found; continue search */ | ||
1198 | } | ||
1199 | |||
1200 | if (!cs->irq) { | ||
1201 | printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); | ||
1202 | iounmap_diva(cs); | ||
1203 | return(0); | ||
1204 | } | ||
1205 | |||
1206 | if (!cs->hw.diva.cfg_reg) { | ||
1207 | printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); | ||
1208 | iounmap_diva(cs); | ||
1209 | return(0); | ||
1210 | } | ||
1211 | cs->irq_flags |= IRQF_SHARED; | ||
1212 | |||
1213 | if ((cs->subtyp == DIVA_IPAC_PCI) || | ||
1214 | (cs->subtyp == DIVA_IPACX_PCI) ) { | ||
1215 | cs->hw.diva.ctrl = 0; | ||
1216 | cs->hw.diva.isac = 0; | ||
1217 | cs->hw.diva.hscx = 0; | ||
1218 | cs->hw.diva.isac_adr = 0; | ||
1219 | cs->hw.diva.hscx_adr = 0; | ||
1220 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1221 | } else { | ||
1222 | cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; | ||
1223 | cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; | ||
1224 | cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; | ||
1225 | cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; | ||
1226 | cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; | ||
1227 | } | ||
1228 | |||
1229 | return (1); /* card found */ | ||
1230 | } | ||
1231 | |||
1232 | #else /* if !CONFIG_PCI */ | ||
1233 | |||
1234 | static int __devinit setup_diva_pci(struct IsdnCard *card) | ||
1235 | { | ||
1236 | return (-1); /* card not found; continue search */ | ||
1237 | } | ||
1238 | |||
1239 | #endif /* CONFIG_PCI */ | ||
1240 | |||
1241 | int __devinit | ||
1242 | setup_diva(struct IsdnCard *card) | ||
1243 | { | ||
1244 | int rc, have_card = 0; | ||
1245 | struct IsdnCardState *cs = card->cs; | ||
1246 | char tmp[64]; | ||
1247 | |||
1248 | strcpy(tmp, Diva_revision); | ||
1249 | printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); | ||
1250 | if (cs->typ != ISDN_CTYPE_DIEHLDIVA) | ||
1251 | return(0); | ||
1252 | cs->hw.diva.status = 0; | ||
1253 | |||
1254 | rc = setup_diva_isa(card); | ||
1255 | if (!rc) | ||
1256 | return rc; | ||
1257 | if (rc > 0) { | ||
1258 | have_card = 1; | ||
1259 | goto ready; | ||
1260 | } | ||
1261 | |||
1262 | rc = setup_diva_isapnp(card); | ||
1263 | if (!rc) | ||
1264 | return rc; | ||
1265 | if (rc > 0) { | ||
1266 | have_card = 1; | ||
1267 | goto ready; | ||
1268 | } | ||
1269 | |||
1270 | rc = setup_diva_pci(card); | ||
1271 | if (!rc) | ||
1272 | return rc; | ||
1273 | if (rc > 0) | ||
1274 | have_card = 1; | ||
1275 | |||
1276 | ready: | ||
1277 | if (!have_card) { | ||
1278 | printk(KERN_WARNING "Diva: No ISA, ISAPNP or PCI card found\n"); | ||
1279 | return(0); | ||
1280 | } | ||
1281 | |||
1282 | return setup_diva_common(card->cs); | ||
1283 | } | ||
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index fab3e4ea0595..0c1351b23840 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <linux/serial.h> | 30 | #include <linux/serial.h> |
31 | #include <linux/serial_reg.h> | 31 | #include <linux/serial_reg.h> |
32 | 32 | ||
33 | extern const char *CardType[]; | ||
34 | |||
35 | static const char *Elsa_revision = "$Revision: 2.32.2.4 $"; | 33 | static const char *Elsa_revision = "$Revision: 2.32.2.4 $"; |
36 | static const char *Elsa_Types[] = | 34 | static const char *Elsa_Types[] = |
37 | {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", | 35 | {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", |
@@ -832,8 +830,75 @@ probe_elsa(struct IsdnCardState *cs) | |||
832 | return (CARD_portlist[i]); | 830 | return (CARD_portlist[i]); |
833 | } | 831 | } |
834 | 832 | ||
835 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; | 833 | static int __devinit |
836 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; | 834 | setup_elsa_isa(struct IsdnCard *card) |
835 | { | ||
836 | struct IsdnCardState *cs = card->cs; | ||
837 | u_char val; | ||
838 | |||
839 | cs->hw.elsa.base = card->para[0]; | ||
840 | printk(KERN_INFO "Elsa: Microlink IO probing\n"); | ||
841 | if (cs->hw.elsa.base) { | ||
842 | if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, | ||
843 | cs->typ))) { | ||
844 | printk(KERN_WARNING | ||
845 | "Elsa: no Elsa Microlink at %#lx\n", | ||
846 | cs->hw.elsa.base); | ||
847 | return (0); | ||
848 | } | ||
849 | } else | ||
850 | cs->hw.elsa.base = probe_elsa(cs); | ||
851 | |||
852 | if (!cs->hw.elsa.base) { | ||
853 | printk(KERN_WARNING | ||
854 | "No Elsa Microlink found\n"); | ||
855 | return (0); | ||
856 | } | ||
857 | |||
858 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; | ||
859 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; | ||
860 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; | ||
861 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; | ||
862 | cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; | ||
863 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; | ||
864 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; | ||
865 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; | ||
866 | val = bytein(cs->hw.elsa.cfg); | ||
867 | if (cs->subtyp == ELSA_PC) { | ||
868 | const u_char CARD_IrqTab[8] = | ||
869 | {7, 3, 5, 9, 0, 0, 0, 0}; | ||
870 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; | ||
871 | } else if (cs->subtyp == ELSA_PCC8) { | ||
872 | const u_char CARD_IrqTab[8] = | ||
873 | {7, 3, 5, 9, 0, 0, 0, 0}; | ||
874 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; | ||
875 | } else { | ||
876 | const u_char CARD_IrqTab[8] = | ||
877 | {15, 10, 15, 3, 11, 5, 11, 9}; | ||
878 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; | ||
879 | } | ||
880 | val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; | ||
881 | if (val < 3) | ||
882 | val |= 8; | ||
883 | val += 'A' - 3; | ||
884 | if (val == 'B' || val == 'C') | ||
885 | val ^= 1; | ||
886 | if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) | ||
887 | val = 'C'; | ||
888 | printk(KERN_INFO | ||
889 | "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", | ||
890 | Elsa_Types[cs->subtyp], | ||
891 | cs->hw.elsa.base, | ||
892 | val, cs->irq); | ||
893 | val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; | ||
894 | if (val) { | ||
895 | printk(KERN_WARNING | ||
896 | "Elsa: Microlink S0 bus power bad\n"); | ||
897 | cs->hw.elsa.status |= ELSA_BAD_PWR; | ||
898 | } | ||
899 | |||
900 | return (1); | ||
901 | } | ||
837 | 902 | ||
838 | #ifdef __ISAPNP__ | 903 | #ifdef __ISAPNP__ |
839 | static struct isapnp_device_id elsa_ids[] __devinitdata = { | 904 | static struct isapnp_device_id elsa_ids[] __devinitdata = { |
@@ -848,233 +913,194 @@ static struct isapnp_device_id elsa_ids[] __devinitdata = { | |||
848 | 913 | ||
849 | static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0]; | 914 | static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0]; |
850 | static struct pnp_card *pnp_c __devinitdata = NULL; | 915 | static struct pnp_card *pnp_c __devinitdata = NULL; |
851 | #endif | 916 | #endif /* __ISAPNP__ */ |
852 | 917 | ||
853 | int __devinit | 918 | static int __devinit |
854 | setup_elsa(struct IsdnCard *card) | 919 | setup_elsa_isapnp(struct IsdnCard *card) |
855 | { | 920 | { |
856 | int bytecnt; | ||
857 | u_char val; | ||
858 | struct IsdnCardState *cs = card->cs; | 921 | struct IsdnCardState *cs = card->cs; |
859 | char tmp[64]; | ||
860 | 922 | ||
861 | strcpy(tmp, Elsa_revision); | ||
862 | printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); | ||
863 | cs->hw.elsa.ctrl_reg = 0; | ||
864 | cs->hw.elsa.status = 0; | ||
865 | cs->hw.elsa.MFlag = 0; | ||
866 | cs->subtyp = 0; | ||
867 | if (cs->typ == ISDN_CTYPE_ELSA) { | ||
868 | cs->hw.elsa.base = card->para[0]; | ||
869 | printk(KERN_INFO "Elsa: Microlink IO probing\n"); | ||
870 | if (cs->hw.elsa.base) { | ||
871 | if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, | ||
872 | cs->typ))) { | ||
873 | printk(KERN_WARNING | ||
874 | "Elsa: no Elsa Microlink at %#lx\n", | ||
875 | cs->hw.elsa.base); | ||
876 | return (0); | ||
877 | } | ||
878 | } else | ||
879 | cs->hw.elsa.base = probe_elsa(cs); | ||
880 | if (cs->hw.elsa.base) { | ||
881 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; | ||
882 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; | ||
883 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; | ||
884 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; | ||
885 | cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; | ||
886 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; | ||
887 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; | ||
888 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; | ||
889 | val = bytein(cs->hw.elsa.cfg); | ||
890 | if (cs->subtyp == ELSA_PC) { | ||
891 | const u_char CARD_IrqTab[8] = | ||
892 | {7, 3, 5, 9, 0, 0, 0, 0}; | ||
893 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; | ||
894 | } else if (cs->subtyp == ELSA_PCC8) { | ||
895 | const u_char CARD_IrqTab[8] = | ||
896 | {7, 3, 5, 9, 0, 0, 0, 0}; | ||
897 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; | ||
898 | } else { | ||
899 | const u_char CARD_IrqTab[8] = | ||
900 | {15, 10, 15, 3, 11, 5, 11, 9}; | ||
901 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; | ||
902 | } | ||
903 | val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; | ||
904 | if (val < 3) | ||
905 | val |= 8; | ||
906 | val += 'A' - 3; | ||
907 | if (val == 'B' || val == 'C') | ||
908 | val ^= 1; | ||
909 | if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) | ||
910 | val = 'C'; | ||
911 | printk(KERN_INFO | ||
912 | "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", | ||
913 | Elsa_Types[cs->subtyp], | ||
914 | cs->hw.elsa.base, | ||
915 | val, cs->irq); | ||
916 | val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; | ||
917 | if (val) { | ||
918 | printk(KERN_WARNING | ||
919 | "Elsa: Microlink S0 bus power bad\n"); | ||
920 | cs->hw.elsa.status |= ELSA_BAD_PWR; | ||
921 | } | ||
922 | } else { | ||
923 | printk(KERN_WARNING | ||
924 | "No Elsa Microlink found\n"); | ||
925 | return (0); | ||
926 | } | ||
927 | } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { | ||
928 | #ifdef __ISAPNP__ | 923 | #ifdef __ISAPNP__ |
929 | if (!card->para[1] && isapnp_present()) { | 924 | if (!card->para[1] && isapnp_present()) { |
930 | struct pnp_dev *pnp_d; | 925 | struct pnp_dev *pnp_d; |
931 | while(ipid->card_vendor) { | 926 | while(ipid->card_vendor) { |
932 | if ((pnp_c = pnp_find_card(ipid->card_vendor, | 927 | if ((pnp_c = pnp_find_card(ipid->card_vendor, |
933 | ipid->card_device, pnp_c))) { | 928 | ipid->card_device, pnp_c))) { |
934 | pnp_d = NULL; | 929 | pnp_d = NULL; |
935 | if ((pnp_d = pnp_find_dev(pnp_c, | 930 | if ((pnp_d = pnp_find_dev(pnp_c, |
936 | ipid->vendor, ipid->function, pnp_d))) { | 931 | ipid->vendor, ipid->function, pnp_d))) { |
937 | int err; | 932 | int err; |
938 | 933 | ||
939 | printk(KERN_INFO "HiSax: %s detected\n", | 934 | printk(KERN_INFO "HiSax: %s detected\n", |
940 | (char *)ipid->driver_data); | 935 | (char *)ipid->driver_data); |
936 | pnp_disable_dev(pnp_d); | ||
937 | err = pnp_activate_dev(pnp_d); | ||
938 | if (err<0) { | ||
939 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
940 | __FUNCTION__, err); | ||
941 | return(0); | ||
942 | } | ||
943 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
944 | card->para[0] = pnp_irq(pnp_d, 0); | ||
945 | |||
946 | if (!card->para[0] || !card->para[1]) { | ||
947 | printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", | ||
948 | card->para[0], card->para[1]); | ||
941 | pnp_disable_dev(pnp_d); | 949 | pnp_disable_dev(pnp_d); |
942 | err = pnp_activate_dev(pnp_d); | ||
943 | if (err<0) { | ||
944 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
945 | __FUNCTION__, err); | ||
946 | return(0); | ||
947 | } | ||
948 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
949 | card->para[0] = pnp_irq(pnp_d, 0); | ||
950 | |||
951 | if (!card->para[0] || !card->para[1]) { | ||
952 | printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", | ||
953 | card->para[0], card->para[1]); | ||
954 | pnp_disable_dev(pnp_d); | ||
955 | return(0); | ||
956 | } | ||
957 | if (ipid->function == ISAPNP_FUNCTION(0x133)) | ||
958 | cs->subtyp = ELSA_QS1000; | ||
959 | else | ||
960 | cs->subtyp = ELSA_QS3000; | ||
961 | break; | ||
962 | } else { | ||
963 | printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); | ||
964 | return(0); | 950 | return(0); |
965 | } | 951 | } |
952 | if (ipid->function == ISAPNP_FUNCTION(0x133)) | ||
953 | cs->subtyp = ELSA_QS1000; | ||
954 | else | ||
955 | cs->subtyp = ELSA_QS3000; | ||
956 | break; | ||
957 | } else { | ||
958 | printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); | ||
959 | return(0); | ||
966 | } | 960 | } |
967 | ipid++; | ||
968 | pnp_c=NULL; | ||
969 | } | ||
970 | if (!ipid->card_vendor) { | ||
971 | printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n"); | ||
972 | return(0); | ||
973 | } | 961 | } |
962 | ipid++; | ||
963 | pnp_c=NULL; | ||
964 | } | ||
965 | if (!ipid->card_vendor) { | ||
966 | printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n"); | ||
967 | return(0); | ||
974 | } | 968 | } |
975 | #endif | 969 | } |
976 | if (card->para[1] && card->para[0]) { | 970 | #endif /* __ISAPNP__ */ |
977 | cs->hw.elsa.base = card->para[1]; | 971 | |
978 | cs->irq = card->para[0]; | 972 | if (card->para[1] && card->para[0]) { |
979 | if (!cs->subtyp) | ||
980 | cs->subtyp = ELSA_QS1000; | ||
981 | } else { | ||
982 | printk(KERN_ERR "Elsa PnP: no parameter\n"); | ||
983 | } | ||
984 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; | ||
985 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; | ||
986 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; | ||
987 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; | ||
988 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; | ||
989 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; | ||
990 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; | ||
991 | printk(KERN_INFO | ||
992 | "Elsa: %s defined at %#lx IRQ %d\n", | ||
993 | Elsa_Types[cs->subtyp], | ||
994 | cs->hw.elsa.base, | ||
995 | cs->irq); | ||
996 | } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) { | ||
997 | cs->hw.elsa.base = card->para[1]; | 973 | cs->hw.elsa.base = card->para[1]; |
998 | cs->irq = card->para[0]; | 974 | cs->irq = card->para[0]; |
999 | val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID); | 975 | if (!cs->subtyp) |
1000 | if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ | 976 | cs->subtyp = ELSA_QS1000; |
1001 | cs->subtyp = ELSA_PCMCIA_IPAC; | 977 | } else { |
1002 | cs->hw.elsa.ale = cs->hw.elsa.base + 0; | 978 | printk(KERN_ERR "Elsa PnP: no parameter\n"); |
1003 | cs->hw.elsa.isac = cs->hw.elsa.base + 2; | 979 | } |
1004 | cs->hw.elsa.hscx = cs->hw.elsa.base + 2; | 980 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; |
1005 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | 981 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; |
1006 | } else { | 982 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; |
1007 | cs->subtyp = ELSA_PCMCIA; | 983 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; |
1008 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; | 984 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; |
1009 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; | 985 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; |
1010 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; | 986 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; |
1011 | } | 987 | printk(KERN_INFO |
1012 | cs->hw.elsa.timer = 0; | 988 | "Elsa: %s defined at %#lx IRQ %d\n", |
1013 | cs->hw.elsa.trig = 0; | 989 | Elsa_Types[cs->subtyp], |
1014 | cs->hw.elsa.ctrl = 0; | 990 | cs->hw.elsa.base, |
1015 | cs->irq_flags |= IRQF_SHARED; | 991 | cs->irq); |
1016 | printk(KERN_INFO | 992 | |
1017 | "Elsa: %s defined at %#lx IRQ %d\n", | 993 | return (1); |
1018 | Elsa_Types[cs->subtyp], | 994 | } |
1019 | cs->hw.elsa.base, | 995 | |
1020 | cs->irq); | 996 | static void __devinit |
1021 | } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { | 997 | setup_elsa_pcmcia(struct IsdnCard *card) |
998 | { | ||
999 | struct IsdnCardState *cs = card->cs; | ||
1000 | u_char val; | ||
1001 | |||
1002 | cs->hw.elsa.base = card->para[1]; | ||
1003 | cs->irq = card->para[0]; | ||
1004 | val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID); | ||
1005 | if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ | ||
1006 | cs->subtyp = ELSA_PCMCIA_IPAC; | ||
1007 | cs->hw.elsa.ale = cs->hw.elsa.base + 0; | ||
1008 | cs->hw.elsa.isac = cs->hw.elsa.base + 2; | ||
1009 | cs->hw.elsa.hscx = cs->hw.elsa.base + 2; | ||
1010 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1011 | } else { | ||
1012 | cs->subtyp = ELSA_PCMCIA; | ||
1013 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; | ||
1014 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; | ||
1015 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; | ||
1016 | } | ||
1017 | cs->hw.elsa.timer = 0; | ||
1018 | cs->hw.elsa.trig = 0; | ||
1019 | cs->hw.elsa.ctrl = 0; | ||
1020 | cs->irq_flags |= IRQF_SHARED; | ||
1021 | printk(KERN_INFO | ||
1022 | "Elsa: %s defined at %#lx IRQ %d\n", | ||
1023 | Elsa_Types[cs->subtyp], | ||
1024 | cs->hw.elsa.base, | ||
1025 | cs->irq); | ||
1026 | } | ||
1027 | |||
1022 | #ifdef CONFIG_PCI | 1028 | #ifdef CONFIG_PCI |
1023 | cs->subtyp = 0; | 1029 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; |
1024 | if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1030 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; |
1025 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { | 1031 | |
1026 | if (pci_enable_device(dev_qs1000)) | 1032 | static int __devinit |
1027 | return(0); | 1033 | setup_elsa_pci(struct IsdnCard *card) |
1028 | cs->subtyp = ELSA_QS1000PCI; | 1034 | { |
1029 | cs->irq = dev_qs1000->irq; | 1035 | struct IsdnCardState *cs = card->cs; |
1030 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); | 1036 | |
1031 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); | 1037 | cs->subtyp = 0; |
1032 | } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1038 | if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, |
1033 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { | 1039 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { |
1034 | if (pci_enable_device(dev_qs3000)) | 1040 | if (pci_enable_device(dev_qs1000)) |
1035 | return(0); | ||
1036 | cs->subtyp = ELSA_QS3000PCI; | ||
1037 | cs->irq = dev_qs3000->irq; | ||
1038 | cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); | ||
1039 | cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); | ||
1040 | } else { | ||
1041 | printk(KERN_WARNING "Elsa: No PCI card found\n"); | ||
1042 | return(0); | 1041 | return(0); |
1043 | } | 1042 | cs->subtyp = ELSA_QS1000PCI; |
1044 | if (!cs->irq) { | 1043 | cs->irq = dev_qs1000->irq; |
1045 | printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); | 1044 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); |
1045 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); | ||
1046 | } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, | ||
1047 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { | ||
1048 | if (pci_enable_device(dev_qs3000)) | ||
1046 | return(0); | 1049 | return(0); |
1047 | } | 1050 | cs->subtyp = ELSA_QS3000PCI; |
1051 | cs->irq = dev_qs3000->irq; | ||
1052 | cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); | ||
1053 | cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); | ||
1054 | } else { | ||
1055 | printk(KERN_WARNING "Elsa: No PCI card found\n"); | ||
1056 | return(0); | ||
1057 | } | ||
1058 | if (!cs->irq) { | ||
1059 | printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); | ||
1060 | return(0); | ||
1061 | } | ||
1062 | |||
1063 | if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { | ||
1064 | printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); | ||
1065 | return(0); | ||
1066 | } | ||
1067 | if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { | ||
1068 | printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); | ||
1069 | printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); | ||
1070 | printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); | ||
1071 | } | ||
1072 | cs->hw.elsa.ale = cs->hw.elsa.base; | ||
1073 | cs->hw.elsa.isac = cs->hw.elsa.base +1; | ||
1074 | cs->hw.elsa.hscx = cs->hw.elsa.base +1; | ||
1075 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1076 | cs->hw.elsa.timer = 0; | ||
1077 | cs->hw.elsa.trig = 0; | ||
1078 | cs->irq_flags |= IRQF_SHARED; | ||
1079 | printk(KERN_INFO | ||
1080 | "Elsa: %s defined at %#lx/0x%x IRQ %d\n", | ||
1081 | Elsa_Types[cs->subtyp], | ||
1082 | cs->hw.elsa.base, | ||
1083 | cs->hw.elsa.cfg, | ||
1084 | cs->irq); | ||
1085 | |||
1086 | return (1); | ||
1087 | } | ||
1048 | 1088 | ||
1049 | if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { | ||
1050 | printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); | ||
1051 | return(0); | ||
1052 | } | ||
1053 | if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { | ||
1054 | printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); | ||
1055 | printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); | ||
1056 | printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); | ||
1057 | } | ||
1058 | cs->hw.elsa.ale = cs->hw.elsa.base; | ||
1059 | cs->hw.elsa.isac = cs->hw.elsa.base +1; | ||
1060 | cs->hw.elsa.hscx = cs->hw.elsa.base +1; | ||
1061 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); | ||
1062 | cs->hw.elsa.timer = 0; | ||
1063 | cs->hw.elsa.trig = 0; | ||
1064 | cs->irq_flags |= IRQF_SHARED; | ||
1065 | printk(KERN_INFO | ||
1066 | "Elsa: %s defined at %#lx/0x%x IRQ %d\n", | ||
1067 | Elsa_Types[cs->subtyp], | ||
1068 | cs->hw.elsa.base, | ||
1069 | cs->hw.elsa.cfg, | ||
1070 | cs->irq); | ||
1071 | #else | 1089 | #else |
1072 | printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n"); | 1090 | |
1073 | printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n"); | 1091 | static void __devinit |
1074 | return (0); | 1092 | setup_elsa_pci(struct IsdnCard *card) |
1093 | { | ||
1094 | return (1); | ||
1095 | } | ||
1075 | #endif /* CONFIG_PCI */ | 1096 | #endif /* CONFIG_PCI */ |
1076 | } else | 1097 | |
1077 | return (0); | 1098 | static int __devinit |
1099 | setup_elsa_common(struct IsdnCard *card) | ||
1100 | { | ||
1101 | struct IsdnCardState *cs = card->cs; | ||
1102 | u_char val; | ||
1103 | int bytecnt; | ||
1078 | 1104 | ||
1079 | switch (cs->subtyp) { | 1105 | switch (cs->subtyp) { |
1080 | case ELSA_PC: | 1106 | case ELSA_PC: |
@@ -1104,8 +1130,7 @@ setup_elsa(struct IsdnCard *card) | |||
1104 | here, it would fail. */ | 1130 | here, it would fail. */ |
1105 | if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { | 1131 | if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { |
1106 | printk(KERN_WARNING | 1132 | printk(KERN_WARNING |
1107 | "HiSax: %s config port %#lx-%#lx already in use\n", | 1133 | "HiSax: ELSA config port %#lx-%#lx already in use\n", |
1108 | CardType[card->typ], | ||
1109 | cs->hw.elsa.base, | 1134 | cs->hw.elsa.base, |
1110 | cs->hw.elsa.base + bytecnt); | 1135 | cs->hw.elsa.base + bytecnt); |
1111 | return (0); | 1136 | return (0); |
@@ -1113,8 +1138,7 @@ setup_elsa(struct IsdnCard *card) | |||
1113 | if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { | 1138 | if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { |
1114 | if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { | 1139 | if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { |
1115 | printk(KERN_WARNING | 1140 | printk(KERN_WARNING |
1116 | "HiSax: %s pci port %x-%x already in use\n", | 1141 | "HiSax: ELSA pci port %x-%x already in use\n", |
1117 | CardType[card->typ], | ||
1118 | cs->hw.elsa.cfg, | 1142 | cs->hw.elsa.cfg, |
1119 | cs->hw.elsa.cfg + 0x80); | 1143 | cs->hw.elsa.cfg + 0x80); |
1120 | release_region(cs->hw.elsa.base, bytecnt); | 1144 | release_region(cs->hw.elsa.base, bytecnt); |
@@ -1186,3 +1210,41 @@ setup_elsa(struct IsdnCard *card) | |||
1186 | } | 1210 | } |
1187 | return (1); | 1211 | return (1); |
1188 | } | 1212 | } |
1213 | |||
1214 | int __devinit | ||
1215 | setup_elsa(struct IsdnCard *card) | ||
1216 | { | ||
1217 | int rc; | ||
1218 | struct IsdnCardState *cs = card->cs; | ||
1219 | char tmp[64]; | ||
1220 | |||
1221 | strcpy(tmp, Elsa_revision); | ||
1222 | printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); | ||
1223 | cs->hw.elsa.ctrl_reg = 0; | ||
1224 | cs->hw.elsa.status = 0; | ||
1225 | cs->hw.elsa.MFlag = 0; | ||
1226 | cs->subtyp = 0; | ||
1227 | |||
1228 | if (cs->typ == ISDN_CTYPE_ELSA) { | ||
1229 | rc = setup_elsa_isa(card); | ||
1230 | if (!rc) | ||
1231 | return (0); | ||
1232 | |||
1233 | } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { | ||
1234 | rc = setup_elsa_isapnp(card); | ||
1235 | if (!rc) | ||
1236 | return (0); | ||
1237 | |||
1238 | } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) | ||
1239 | setup_elsa_pcmcia(card); | ||
1240 | |||
1241 | else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { | ||
1242 | rc = setup_elsa_pci(card); | ||
1243 | if (!rc) | ||
1244 | return (0); | ||
1245 | |||
1246 | } else | ||
1247 | return (0); | ||
1248 | |||
1249 | return setup_elsa_common(card); | ||
1250 | } | ||
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index ad06f3cc60fb..03dfc32166a0 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c | |||
@@ -518,8 +518,6 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) | |||
518 | return(0); | 518 | return(0); |
519 | } | 519 | } |
520 | 520 | ||
521 | static struct pci_dev *dev_sedl __devinitdata = NULL; | ||
522 | |||
523 | #ifdef __ISAPNP__ | 521 | #ifdef __ISAPNP__ |
524 | static struct isapnp_device_id sedl_ids[] __devinitdata = { | 522 | static struct isapnp_device_id sedl_ids[] __devinitdata = { |
525 | { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01), | 523 | { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01), |
@@ -533,15 +531,158 @@ static struct isapnp_device_id sedl_ids[] __devinitdata = { | |||
533 | 531 | ||
534 | static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0]; | 532 | static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0]; |
535 | static struct pnp_card *pnp_c __devinitdata = NULL; | 533 | static struct pnp_card *pnp_c __devinitdata = NULL; |
536 | #endif | 534 | |
535 | static int __devinit | ||
536 | setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) | ||
537 | { | ||
538 | struct IsdnCardState *cs = card->cs; | ||
539 | struct pnp_dev *pnp_d; | ||
540 | |||
541 | if (!isapnp_present()) | ||
542 | return -1; | ||
543 | |||
544 | while(ipid->card_vendor) { | ||
545 | if ((pnp_c = pnp_find_card(ipid->card_vendor, | ||
546 | ipid->card_device, pnp_c))) { | ||
547 | pnp_d = NULL; | ||
548 | if ((pnp_d = pnp_find_dev(pnp_c, | ||
549 | ipid->vendor, ipid->function, pnp_d))) { | ||
550 | int err; | ||
551 | |||
552 | printk(KERN_INFO "HiSax: %s detected\n", | ||
553 | (char *)ipid->driver_data); | ||
554 | pnp_disable_dev(pnp_d); | ||
555 | err = pnp_activate_dev(pnp_d); | ||
556 | if (err<0) { | ||
557 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
558 | __FUNCTION__, err); | ||
559 | return(0); | ||
560 | } | ||
561 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
562 | card->para[0] = pnp_irq(pnp_d, 0); | ||
563 | |||
564 | if (!card->para[0] || !card->para[1]) { | ||
565 | printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", | ||
566 | card->para[0], card->para[1]); | ||
567 | pnp_disable_dev(pnp_d); | ||
568 | return(0); | ||
569 | } | ||
570 | cs->hw.sedl.cfg_reg = card->para[1]; | ||
571 | cs->irq = card->para[0]; | ||
572 | if (ipid->function == ISAPNP_FUNCTION(0x2)) { | ||
573 | cs->subtyp = SEDL_SPEED_FAX; | ||
574 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
575 | *bytecnt = 16; | ||
576 | } else { | ||
577 | cs->subtyp = SEDL_SPEED_CARD_WIN; | ||
578 | cs->hw.sedl.chip = SEDL_CHIP_TEST; | ||
579 | } | ||
580 | |||
581 | return (1); | ||
582 | } else { | ||
583 | printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); | ||
584 | return(0); | ||
585 | } | ||
586 | } | ||
587 | ipid++; | ||
588 | pnp_c = NULL; | ||
589 | } | ||
590 | |||
591 | printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); | ||
592 | return -1; | ||
593 | } | ||
594 | #else | ||
595 | |||
596 | static int __devinit | ||
597 | setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) | ||
598 | { | ||
599 | return -1; | ||
600 | } | ||
601 | #endif /* __ISAPNP__ */ | ||
602 | |||
603 | #ifdef CONFIG_PCI | ||
604 | static struct pci_dev *dev_sedl __devinitdata = NULL; | ||
605 | |||
606 | static int __devinit | ||
607 | setup_sedlbauer_pci(struct IsdnCard *card) | ||
608 | { | ||
609 | struct IsdnCardState *cs = card->cs; | ||
610 | u16 sub_vendor_id, sub_id; | ||
611 | |||
612 | if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, | ||
613 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { | ||
614 | if (pci_enable_device(dev_sedl)) | ||
615 | return(0); | ||
616 | cs->irq = dev_sedl->irq; | ||
617 | if (!cs->irq) { | ||
618 | printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); | ||
619 | return(0); | ||
620 | } | ||
621 | cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); | ||
622 | } else { | ||
623 | printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); | ||
624 | return(0); | ||
625 | } | ||
626 | cs->irq_flags |= IRQF_SHARED; | ||
627 | cs->hw.sedl.bus = SEDL_BUS_PCI; | ||
628 | sub_vendor_id = dev_sedl->subsystem_vendor; | ||
629 | sub_id = dev_sedl->subsystem_device; | ||
630 | printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", | ||
631 | sub_vendor_id, sub_id); | ||
632 | printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", | ||
633 | cs->hw.sedl.cfg_reg); | ||
634 | if (sub_id != PCI_SUB_ID_SEDLBAUER) { | ||
635 | printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); | ||
636 | return(0); | ||
637 | } | ||
638 | if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { | ||
639 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
640 | cs->subtyp = SEDL_SPEEDFAX_PYRAMID; | ||
641 | } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { | ||
642 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
643 | cs->subtyp = SEDL_SPEEDFAX_PCI; | ||
644 | } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) { | ||
645 | cs->hw.sedl.chip = SEDL_CHIP_IPAC; | ||
646 | cs->subtyp = HST_SAPHIR3; | ||
647 | } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { | ||
648 | cs->hw.sedl.chip = SEDL_CHIP_IPAC; | ||
649 | cs->subtyp = SEDL_SPEED_PCI; | ||
650 | } else { | ||
651 | printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", | ||
652 | sub_vendor_id); | ||
653 | return(0); | ||
654 | } | ||
655 | |||
656 | cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; | ||
657 | cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; | ||
658 | byteout(cs->hw.sedl.cfg_reg, 0xff); | ||
659 | byteout(cs->hw.sedl.cfg_reg, 0x00); | ||
660 | byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); | ||
661 | byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */ | ||
662 | byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); | ||
663 | mdelay(2); | ||
664 | byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); | ||
665 | mdelay(10); | ||
666 | |||
667 | return (1); | ||
668 | } | ||
669 | |||
670 | #else | ||
671 | |||
672 | static int __devinit | ||
673 | setup_sedlbauer_pci(struct IsdnCard *card) | ||
674 | { | ||
675 | return (1); | ||
676 | } | ||
677 | |||
678 | #endif /* CONFIG_PCI */ | ||
537 | 679 | ||
538 | int __devinit | 680 | int __devinit |
539 | setup_sedlbauer(struct IsdnCard *card) | 681 | setup_sedlbauer(struct IsdnCard *card) |
540 | { | 682 | { |
541 | int bytecnt, ver, val; | 683 | int bytecnt = 8, ver, val, rc; |
542 | struct IsdnCardState *cs = card->cs; | 684 | struct IsdnCardState *cs = card->cs; |
543 | char tmp[64]; | 685 | char tmp[64]; |
544 | u16 sub_vendor_id, sub_id; | ||
545 | 686 | ||
546 | strcpy(tmp, Sedlbauer_revision); | 687 | strcpy(tmp, Sedlbauer_revision); |
547 | printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); | 688 | printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); |
@@ -569,124 +710,21 @@ setup_sedlbauer(struct IsdnCard *card) | |||
569 | bytecnt = 16; | 710 | bytecnt = 16; |
570 | } | 711 | } |
571 | } else { | 712 | } else { |
572 | #ifdef __ISAPNP__ | 713 | rc = setup_sedlbauer_isapnp(card, &bytecnt); |
573 | if (isapnp_present()) { | 714 | if (!rc) |
574 | struct pnp_dev *pnp_d; | 715 | return (0); |
575 | while(ipid->card_vendor) { | 716 | if (rc > 0) |
576 | if ((pnp_c = pnp_find_card(ipid->card_vendor, | 717 | goto ready; |
577 | ipid->card_device, pnp_c))) { | 718 | |
578 | pnp_d = NULL; | 719 | /* Probe for Sedlbauer speed pci */ |
579 | if ((pnp_d = pnp_find_dev(pnp_c, | 720 | rc = setup_sedlbauer_pci(card); |
580 | ipid->vendor, ipid->function, pnp_d))) { | 721 | if (!rc) |
581 | int err; | 722 | return (0); |
582 | 723 | ||
583 | printk(KERN_INFO "HiSax: %s detected\n", | ||
584 | (char *)ipid->driver_data); | ||
585 | pnp_disable_dev(pnp_d); | ||
586 | err = pnp_activate_dev(pnp_d); | ||
587 | if (err<0) { | ||
588 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", | ||
589 | __FUNCTION__, err); | ||
590 | return(0); | ||
591 | } | ||
592 | card->para[1] = pnp_port_start(pnp_d, 0); | ||
593 | card->para[0] = pnp_irq(pnp_d, 0); | ||
594 | |||
595 | if (!card->para[0] || !card->para[1]) { | ||
596 | printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", | ||
597 | card->para[0], card->para[1]); | ||
598 | pnp_disable_dev(pnp_d); | ||
599 | return(0); | ||
600 | } | ||
601 | cs->hw.sedl.cfg_reg = card->para[1]; | ||
602 | cs->irq = card->para[0]; | ||
603 | if (ipid->function == ISAPNP_FUNCTION(0x2)) { | ||
604 | cs->subtyp = SEDL_SPEED_FAX; | ||
605 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
606 | bytecnt = 16; | ||
607 | } else { | ||
608 | cs->subtyp = SEDL_SPEED_CARD_WIN; | ||
609 | cs->hw.sedl.chip = SEDL_CHIP_TEST; | ||
610 | } | ||
611 | goto ready; | ||
612 | } else { | ||
613 | printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); | ||
614 | return(0); | ||
615 | } | ||
616 | } | ||
617 | ipid++; | ||
618 | pnp_c = NULL; | ||
619 | } | ||
620 | if (!ipid->card_vendor) { | ||
621 | printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); | ||
622 | } | ||
623 | } | ||
624 | #endif | ||
625 | /* Probe for Sedlbauer speed pci */ | ||
626 | #ifdef CONFIG_PCI | ||
627 | if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, | ||
628 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { | ||
629 | if (pci_enable_device(dev_sedl)) | ||
630 | return(0); | ||
631 | cs->irq = dev_sedl->irq; | ||
632 | if (!cs->irq) { | ||
633 | printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); | ||
634 | return(0); | ||
635 | } | ||
636 | cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); | ||
637 | } else { | ||
638 | printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); | ||
639 | return(0); | ||
640 | } | ||
641 | cs->irq_flags |= IRQF_SHARED; | ||
642 | cs->hw.sedl.bus = SEDL_BUS_PCI; | ||
643 | sub_vendor_id = dev_sedl->subsystem_vendor; | ||
644 | sub_id = dev_sedl->subsystem_device; | ||
645 | printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", | ||
646 | sub_vendor_id, sub_id); | ||
647 | printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", | ||
648 | cs->hw.sedl.cfg_reg); | ||
649 | if (sub_id != PCI_SUB_ID_SEDLBAUER) { | ||
650 | printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); | ||
651 | return(0); | ||
652 | } | ||
653 | if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { | ||
654 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
655 | cs->subtyp = SEDL_SPEEDFAX_PYRAMID; | ||
656 | } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { | ||
657 | cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; | ||
658 | cs->subtyp = SEDL_SPEEDFAX_PCI; | ||
659 | } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) { | ||
660 | cs->hw.sedl.chip = SEDL_CHIP_IPAC; | ||
661 | cs->subtyp = HST_SAPHIR3; | ||
662 | } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { | ||
663 | cs->hw.sedl.chip = SEDL_CHIP_IPAC; | ||
664 | cs->subtyp = SEDL_SPEED_PCI; | ||
665 | } else { | ||
666 | printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", | ||
667 | sub_vendor_id); | ||
668 | return(0); | ||
669 | } | ||
670 | bytecnt = 256; | 724 | bytecnt = 256; |
671 | cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; | ||
672 | cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; | ||
673 | byteout(cs->hw.sedl.cfg_reg, 0xff); | ||
674 | byteout(cs->hw.sedl.cfg_reg, 0x00); | ||
675 | byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); | ||
676 | byteout(cs->hw.sedl.cfg_reg+ 5, 0); /* disable all IRQ */ | ||
677 | byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); | ||
678 | mdelay(2); | ||
679 | byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); | ||
680 | mdelay(10); | ||
681 | #else | ||
682 | printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); | ||
683 | return (0); | ||
684 | #endif /* CONFIG_PCI */ | ||
685 | } | 725 | } |
686 | 726 | ||
687 | #ifdef __ISAPNP__ | ||
688 | ready: | 727 | ready: |
689 | #endif | ||
690 | 728 | ||
691 | /* In case of the sedlbauer pcmcia card, this region is in use, | 729 | /* In case of the sedlbauer pcmcia card, this region is in use, |
692 | * reserved for us by the card manager. So we do not check it | 730 | * reserved for us by the card manager. So we do not check it |
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index d09f6d033f15..4393003ae162 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c | |||
@@ -295,11 +295,12 @@ setup_telespci(struct IsdnCard *card) | |||
295 | #ifdef __BIG_ENDIAN | 295 | #ifdef __BIG_ENDIAN |
296 | #error "not running on big endian machines now" | 296 | #error "not running on big endian machines now" |
297 | #endif | 297 | #endif |
298 | |||
298 | strcpy(tmp, telespci_revision); | 299 | strcpy(tmp, telespci_revision); |
299 | printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); | 300 | printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); |
300 | if (cs->typ != ISDN_CTYPE_TELESPCI) | 301 | if (cs->typ != ISDN_CTYPE_TELESPCI) |
301 | return (0); | 302 | return (0); |
302 | #ifdef CONFIG_PCI | 303 | |
303 | if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { | 304 | if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { |
304 | if (pci_enable_device(dev_tel)) | 305 | if (pci_enable_device(dev_tel)) |
305 | return(0); | 306 | return(0); |
@@ -317,11 +318,6 @@ setup_telespci(struct IsdnCard *card) | |||
317 | printk(KERN_WARNING "TelesPCI: No PCI card found\n"); | 318 | printk(KERN_WARNING "TelesPCI: No PCI card found\n"); |
318 | return(0); | 319 | return(0); |
319 | } | 320 | } |
320 | #else | ||
321 | printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); | ||
322 | printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); | ||
323 | return (0); | ||
324 | #endif /* CONFIG_PCI */ | ||
325 | 321 | ||
326 | /* Initialize Zoran PCI controller */ | 322 | /* Initialize Zoran PCI controller */ |
327 | writel(0x00000000, cs->hw.teles0.membase + 0x28); | 323 | writel(0x00000000, cs->hw.teles0.membase + 0x28); |
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 3aeceaf9769e..39129b94f8be 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c | |||
@@ -1009,7 +1009,7 @@ setup_w6692(struct IsdnCard *card) | |||
1009 | printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); | 1009 | printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); |
1010 | if (cs->typ != ISDN_CTYPE_W6692) | 1010 | if (cs->typ != ISDN_CTYPE_W6692) |
1011 | return (0); | 1011 | return (0); |
1012 | #ifdef CONFIG_PCI | 1012 | |
1013 | while (id_list[id_idx].vendor_id) { | 1013 | while (id_list[id_idx].vendor_id) { |
1014 | dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, | 1014 | dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, |
1015 | id_list[id_idx].device_id, | 1015 | id_list[id_idx].device_id, |
@@ -1061,11 +1061,6 @@ setup_w6692(struct IsdnCard *card) | |||
1061 | cs->hw.w6692.iobase + 255); | 1061 | cs->hw.w6692.iobase + 255); |
1062 | return (0); | 1062 | return (0); |
1063 | } | 1063 | } |
1064 | #else | ||
1065 | printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); | ||
1066 | printk(KERN_WARNING "HiSax: W6692 unable to config\n"); | ||
1067 | return (0); | ||
1068 | #endif /* CONFIG_PCI */ | ||
1069 | 1064 | ||
1070 | printk(KERN_INFO | 1065 | printk(KERN_INFO |
1071 | "HiSax: %s config irq:%d I/O:%x\n", | 1066 | "HiSax: %s config irq:%d I/O:%x\n", |
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index 9e01748a176e..b7cc5c2f08c6 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c | |||
@@ -20,10 +20,15 @@ | |||
20 | #include "hysdn_defs.h" | 20 | #include "hysdn_defs.h" |
21 | 21 | ||
22 | static struct pci_device_id hysdn_pci_tbl[] = { | 22 | static struct pci_device_id hysdn_pci_tbl[] = { |
23 | {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO}, | 23 | { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, |
24 | {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2}, | 24 | PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO }, |
25 | {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO}, | 25 | { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, |
26 | {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO}, | 26 | PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 }, |
27 | { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, | ||
28 | PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO }, | ||
29 | { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, | ||
30 | PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO }, | ||
31 | |||
27 | { } /* Terminating entry */ | 32 | { } /* Terminating entry */ |
28 | }; | 33 | }; |
29 | MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl); | 34 | MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl); |
@@ -34,128 +39,7 @@ MODULE_LICENSE("GPL"); | |||
34 | static char *hysdn_init_revision = "$Revision: 1.6.6.6 $"; | 39 | static char *hysdn_init_revision = "$Revision: 1.6.6.6 $"; |
35 | static int cardmax; /* number of found cards */ | 40 | static int cardmax; /* number of found cards */ |
36 | hysdn_card *card_root = NULL; /* pointer to first card */ | 41 | hysdn_card *card_root = NULL; /* pointer to first card */ |
37 | 42 | static hysdn_card *card_last = NULL; /* pointer to first card */ | |
38 | /**********************************************/ | ||
39 | /* table assigning PCI-sub ids to board types */ | ||
40 | /* the last entry contains all 0 */ | ||
41 | /**********************************************/ | ||
42 | static struct { | ||
43 | unsigned short subid; /* PCI sub id */ | ||
44 | unsigned char cardtyp; /* card type assigned */ | ||
45 | } pci_subid_map[] = { | ||
46 | |||
47 | { | ||
48 | PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO | ||
49 | }, | ||
50 | { | ||
51 | PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2 | ||
52 | }, | ||
53 | { | ||
54 | PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO | ||
55 | }, | ||
56 | { | ||
57 | PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO | ||
58 | }, | ||
59 | { | ||
60 | 0, 0 | ||
61 | } /* terminating entry */ | ||
62 | }; | ||
63 | |||
64 | |||
65 | /*********************************************************************/ | ||
66 | /* search_cards searches for available cards in the pci config data. */ | ||
67 | /* If a card is found, the card structure is allocated and the cards */ | ||
68 | /* ressources are reserved. cardmax is incremented. */ | ||
69 | /*********************************************************************/ | ||
70 | static void | ||
71 | search_cards(void) | ||
72 | { | ||
73 | struct pci_dev *akt_pcidev = NULL; | ||
74 | hysdn_card *card, *card_last; | ||
75 | int i; | ||
76 | |||
77 | card_root = NULL; | ||
78 | card_last = NULL; | ||
79 | while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, | ||
80 | akt_pcidev)) != NULL) { | ||
81 | if (pci_enable_device(akt_pcidev)) | ||
82 | continue; | ||
83 | |||
84 | if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { | ||
85 | printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); | ||
86 | return; | ||
87 | } | ||
88 | card->myid = cardmax; /* set own id */ | ||
89 | card->bus = akt_pcidev->bus->number; | ||
90 | card->devfn = akt_pcidev->devfn; /* slot + function */ | ||
91 | card->subsysid = akt_pcidev->subsystem_device; | ||
92 | card->irq = akt_pcidev->irq; | ||
93 | card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE); | ||
94 | card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE); | ||
95 | card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE); | ||
96 | card->brdtype = BD_NONE; /* unknown */ | ||
97 | card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ | ||
98 | card->faxchans = 0; /* default no fax channels */ | ||
99 | card->bchans = 2; /* and 2 b-channels */ | ||
100 | for (i = 0; pci_subid_map[i].subid; i++) | ||
101 | if (pci_subid_map[i].subid == card->subsysid) { | ||
102 | card->brdtype = pci_subid_map[i].cardtyp; | ||
103 | break; | ||
104 | } | ||
105 | if (card->brdtype != BD_NONE) { | ||
106 | if (ergo_inithardware(card)) { | ||
107 | printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); | ||
108 | kfree(card); | ||
109 | continue; | ||
110 | } | ||
111 | } else { | ||
112 | printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid); | ||
113 | kfree(card); /* release mem */ | ||
114 | continue; | ||
115 | } | ||
116 | cardmax++; | ||
117 | card->next = NULL; /*end of chain */ | ||
118 | if (card_last) | ||
119 | card_last->next = card; /* pointer to next card */ | ||
120 | else | ||
121 | card_root = card; | ||
122 | card_last = card; /* new chain end */ | ||
123 | } /* device found */ | ||
124 | } /* search_cards */ | ||
125 | |||
126 | /************************************************************************************/ | ||
127 | /* free_resources frees the acquired PCI resources and returns the allocated memory */ | ||
128 | /************************************************************************************/ | ||
129 | static void | ||
130 | free_resources(void) | ||
131 | { | ||
132 | hysdn_card *card; | ||
133 | |||
134 | while (card_root) { | ||
135 | card = card_root; | ||
136 | if (card->releasehardware) | ||
137 | card->releasehardware(card); /* free all hardware resources */ | ||
138 | card_root = card_root->next; /* remove card from chain */ | ||
139 | kfree(card); /* return mem */ | ||
140 | |||
141 | } /* while card_root */ | ||
142 | } /* free_resources */ | ||
143 | |||
144 | /**************************************************************************/ | ||
145 | /* stop_cards disables (hardware resets) all cards and disables interrupt */ | ||
146 | /**************************************************************************/ | ||
147 | static void | ||
148 | stop_cards(void) | ||
149 | { | ||
150 | hysdn_card *card; | ||
151 | |||
152 | card = card_root; /* first in chain */ | ||
153 | while (card) { | ||
154 | if (card->stopcard) | ||
155 | card->stopcard(card); | ||
156 | card = card->next; /* remove card from chain */ | ||
157 | } /* while card */ | ||
158 | } /* stop_cards */ | ||
159 | 43 | ||
160 | 44 | ||
161 | /****************************************************************************/ | 45 | /****************************************************************************/ |
@@ -191,31 +75,138 @@ hysdn_getrev(const char *revision) | |||
191 | /* and the module is added to the list in /proc/modules, otherwise an error */ | 75 | /* and the module is added to the list in /proc/modules, otherwise an error */ |
192 | /* is assumed and the module will not be kept in memory. */ | 76 | /* is assumed and the module will not be kept in memory. */ |
193 | /****************************************************************************/ | 77 | /****************************************************************************/ |
78 | |||
79 | static int __devinit hysdn_pci_init_one(struct pci_dev *akt_pcidev, | ||
80 | const struct pci_device_id *ent) | ||
81 | { | ||
82 | hysdn_card *card; | ||
83 | int rc; | ||
84 | |||
85 | rc = pci_enable_device(akt_pcidev); | ||
86 | if (rc) | ||
87 | return rc; | ||
88 | |||
89 | if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { | ||
90 | printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); | ||
91 | rc = -ENOMEM; | ||
92 | goto err_out; | ||
93 | } | ||
94 | card->myid = cardmax; /* set own id */ | ||
95 | card->bus = akt_pcidev->bus->number; | ||
96 | card->devfn = akt_pcidev->devfn; /* slot + function */ | ||
97 | card->subsysid = akt_pcidev->subsystem_device; | ||
98 | card->irq = akt_pcidev->irq; | ||
99 | card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE); | ||
100 | card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE); | ||
101 | card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE); | ||
102 | card->brdtype = BD_NONE; /* unknown */ | ||
103 | card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ | ||
104 | card->faxchans = 0; /* default no fax channels */ | ||
105 | card->bchans = 2; /* and 2 b-channels */ | ||
106 | card->brdtype = ent->driver_data; | ||
107 | |||
108 | if (ergo_inithardware(card)) { | ||
109 | printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); | ||
110 | rc = -EBUSY; | ||
111 | goto err_out_card; | ||
112 | } | ||
113 | |||
114 | cardmax++; | ||
115 | card->next = NULL; /*end of chain */ | ||
116 | if (card_last) | ||
117 | card_last->next = card; /* pointer to next card */ | ||
118 | else | ||
119 | card_root = card; | ||
120 | card_last = card; /* new chain end */ | ||
121 | |||
122 | pci_set_drvdata(akt_pcidev, card); | ||
123 | return 0; | ||
124 | |||
125 | err_out_card: | ||
126 | kfree(card); | ||
127 | err_out: | ||
128 | pci_disable_device(akt_pcidev); | ||
129 | return rc; | ||
130 | } | ||
131 | |||
132 | static void __devexit hysdn_pci_remove_one(struct pci_dev *akt_pcidev) | ||
133 | { | ||
134 | hysdn_card *card = pci_get_drvdata(akt_pcidev); | ||
135 | |||
136 | pci_set_drvdata(akt_pcidev, NULL); | ||
137 | |||
138 | if (card->stopcard) | ||
139 | card->stopcard(card); | ||
140 | |||
141 | #ifdef CONFIG_HYSDN_CAPI | ||
142 | hycapi_capi_release(card); | ||
143 | #endif | ||
144 | |||
145 | if (card->releasehardware) | ||
146 | card->releasehardware(card); /* free all hardware resources */ | ||
147 | |||
148 | if (card == card_root) { | ||
149 | card_root = card_root->next; | ||
150 | if (!card_root) | ||
151 | card_last = NULL; | ||
152 | } else { | ||
153 | hysdn_card *tmp = card_root; | ||
154 | while (tmp) { | ||
155 | if (tmp->next == card) | ||
156 | tmp->next = card->next; | ||
157 | card_last = tmp; | ||
158 | tmp = tmp->next; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | kfree(card); | ||
163 | pci_disable_device(akt_pcidev); | ||
164 | } | ||
165 | |||
166 | static struct pci_driver hysdn_pci_driver = { | ||
167 | .name = "hysdn", | ||
168 | .id_table = hysdn_pci_tbl, | ||
169 | .probe = hysdn_pci_init_one, | ||
170 | .remove = __devexit_p(hysdn_pci_remove_one), | ||
171 | }; | ||
172 | |||
173 | static int hysdn_have_procfs; | ||
174 | |||
194 | static int __init | 175 | static int __init |
195 | hysdn_init(void) | 176 | hysdn_init(void) |
196 | { | 177 | { |
197 | char tmp[50]; | 178 | char tmp[50]; |
179 | int rc; | ||
198 | 180 | ||
199 | strcpy(tmp, hysdn_init_revision); | 181 | strcpy(tmp, hysdn_init_revision); |
200 | printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp)); | 182 | printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp)); |
201 | strcpy(tmp, hysdn_net_revision); | 183 | strcpy(tmp, hysdn_net_revision); |
202 | printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp)); | 184 | printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp)); |
203 | search_cards(); | 185 | |
186 | rc = pci_register_driver(&hysdn_pci_driver); | ||
187 | if (rc) | ||
188 | return rc; | ||
189 | |||
204 | printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); | 190 | printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); |
205 | 191 | ||
206 | if (hysdn_procconf_init()) { | 192 | if (!hysdn_procconf_init()) |
207 | free_resources(); /* proc file_sys not created */ | 193 | hysdn_have_procfs = 1; |
208 | return (-1); | 194 | |
209 | } | ||
210 | #ifdef CONFIG_HYSDN_CAPI | 195 | #ifdef CONFIG_HYSDN_CAPI |
211 | if(cardmax > 0) { | 196 | if(cardmax > 0) { |
212 | if(hycapi_init()) { | 197 | if(hycapi_init()) { |
213 | printk(KERN_ERR "HYCAPI: init failed\n"); | 198 | printk(KERN_ERR "HYCAPI: init failed\n"); |
214 | return(-1); | 199 | |
200 | if (hysdn_have_procfs) | ||
201 | hysdn_procconf_release(); | ||
202 | |||
203 | pci_unregister_driver(&hysdn_pci_driver); | ||
204 | return -ESPIPE; | ||
215 | } | 205 | } |
216 | } | 206 | } |
217 | #endif /* CONFIG_HYSDN_CAPI */ | 207 | #endif /* CONFIG_HYSDN_CAPI */ |
218 | return (0); /* no error */ | 208 | |
209 | return 0; /* no error */ | ||
219 | } /* init_module */ | 210 | } /* init_module */ |
220 | 211 | ||
221 | 212 | ||
@@ -230,20 +221,15 @@ hysdn_init(void) | |||
230 | static void __exit | 221 | static void __exit |
231 | hysdn_exit(void) | 222 | hysdn_exit(void) |
232 | { | 223 | { |
224 | if (hysdn_have_procfs) | ||
225 | hysdn_procconf_release(); | ||
226 | |||
227 | pci_unregister_driver(&hysdn_pci_driver); | ||
228 | |||
233 | #ifdef CONFIG_HYSDN_CAPI | 229 | #ifdef CONFIG_HYSDN_CAPI |
234 | hysdn_card *card; | ||
235 | #endif /* CONFIG_HYSDN_CAPI */ | ||
236 | stop_cards(); | ||
237 | #ifdef CONFIG_HYSDN_CAPI | ||
238 | card = card_root; /* first in chain */ | ||
239 | while (card) { | ||
240 | hycapi_capi_release(card); | ||
241 | card = card->next; /* remove card from chain */ | ||
242 | } /* while card */ | ||
243 | hycapi_cleanup(); | 230 | hycapi_cleanup(); |
244 | #endif /* CONFIG_HYSDN_CAPI */ | 231 | #endif /* CONFIG_HYSDN_CAPI */ |
245 | hysdn_procconf_release(); | 232 | |
246 | free_resources(); | ||
247 | printk(KERN_NOTICE "HYSDN: module unloaded\n"); | 233 | printk(KERN_NOTICE "HYSDN: module unloaded\n"); |
248 | } /* cleanup_module */ | 234 | } /* cleanup_module */ |
249 | 235 | ||
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 64fbc9759a30..c65d203a846d 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -143,7 +143,7 @@ void mmc_remove_host(struct mmc_host *host) | |||
143 | 143 | ||
144 | device_del(&host->class_dev); | 144 | device_del(&host->class_dev); |
145 | 145 | ||
146 | led_trigger_unregister(host->led); | 146 | led_trigger_unregister_simple(host->led); |
147 | 147 | ||
148 | spin_lock(&mmc_host_lock); | 148 | spin_lock(&mmc_host_lock); |
149 | idr_remove(&mmc_host_idr, host->index); | 149 | idr_remove(&mmc_host_idr, host->index); |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d68accea380b..78ed633ceb82 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget) | |||
2652 | REG_RD(bp, BNX2_HC_COMMAND); | 2652 | REG_RD(bp, BNX2_HC_COMMAND); |
2653 | } | 2653 | } |
2654 | 2654 | ||
2655 | if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) | 2655 | if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) |
2656 | bnx2_tx_int(bp); | 2656 | bnx2_tx_int(bp); |
2657 | 2657 | ||
2658 | if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) | 2658 | if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) |
2659 | work_done += bnx2_rx_int(bp, budget - work_done); | 2659 | work_done += bnx2_rx_int(bp, budget - work_done); |
2660 | 2660 | ||
2661 | return work_done; | 2661 | return work_done; |
@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget) | |||
2665 | { | 2665 | { |
2666 | struct bnx2 *bp = container_of(napi, struct bnx2, napi); | 2666 | struct bnx2 *bp = container_of(napi, struct bnx2, napi); |
2667 | int work_done = 0; | 2667 | int work_done = 0; |
2668 | struct status_block *sblk = bp->status_blk; | ||
2668 | 2669 | ||
2669 | while (1) { | 2670 | while (1) { |
2670 | work_done = bnx2_poll_work(bp, work_done, budget); | 2671 | work_done = bnx2_poll_work(bp, work_done, budget); |
@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget) | |||
2672 | if (unlikely(work_done >= budget)) | 2673 | if (unlikely(work_done >= budget)) |
2673 | break; | 2674 | break; |
2674 | 2675 | ||
2676 | /* bp->last_status_idx is used below to tell the hw how | ||
2677 | * much work has been processed, so we must read it before | ||
2678 | * checking for more work. | ||
2679 | */ | ||
2680 | bp->last_status_idx = sblk->status_idx; | ||
2681 | rmb(); | ||
2675 | if (likely(!bnx2_has_work(bp))) { | 2682 | if (likely(!bnx2_has_work(bp))) { |
2676 | bp->last_status_idx = bp->status_blk->status_idx; | ||
2677 | rmb(); | ||
2678 | |||
2679 | netif_rx_complete(bp->dev, napi); | 2683 | netif_rx_complete(bp->dev, napi); |
2680 | if (likely(bp->flags & USING_MSI_FLAG)) { | 2684 | if (likely(bp->flags & USING_MSI_FLAG)) { |
2681 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, | 2685 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, |
2682 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | | 2686 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | |
2683 | bp->last_status_idx); | 2687 | bp->last_status_idx); |
2684 | return 0; | 2688 | break; |
2685 | } | 2689 | } |
2686 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, | 2690 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, |
2687 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | | 2691 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e795c33b982d..30b1cca8144c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -3576,7 +3576,7 @@ static int tg3_poll_work(struct tg3 *tp, int work_done, int budget) | |||
3576 | if (sblk->idx[0].tx_consumer != tp->tx_cons) { | 3576 | if (sblk->idx[0].tx_consumer != tp->tx_cons) { |
3577 | tg3_tx(tp); | 3577 | tg3_tx(tp); |
3578 | if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) | 3578 | if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) |
3579 | return 0; | 3579 | return work_done; |
3580 | } | 3580 | } |
3581 | 3581 | ||
3582 | /* run RX thread, within the bounds set by NAPI. | 3582 | /* run RX thread, within the bounds set by NAPI. |
@@ -3593,6 +3593,7 @@ static int tg3_poll(struct napi_struct *napi, int budget) | |||
3593 | { | 3593 | { |
3594 | struct tg3 *tp = container_of(napi, struct tg3, napi); | 3594 | struct tg3 *tp = container_of(napi, struct tg3, napi); |
3595 | int work_done = 0; | 3595 | int work_done = 0; |
3596 | struct tg3_hw_status *sblk = tp->hw_status; | ||
3596 | 3597 | ||
3597 | while (1) { | 3598 | while (1) { |
3598 | work_done = tg3_poll_work(tp, work_done, budget); | 3599 | work_done = tg3_poll_work(tp, work_done, budget); |
@@ -3603,15 +3604,17 @@ static int tg3_poll(struct napi_struct *napi, int budget) | |||
3603 | if (unlikely(work_done >= budget)) | 3604 | if (unlikely(work_done >= budget)) |
3604 | break; | 3605 | break; |
3605 | 3606 | ||
3606 | if (likely(!tg3_has_work(tp))) { | 3607 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { |
3607 | struct tg3_hw_status *sblk = tp->hw_status; | 3608 | /* tp->last_tag is used in tg3_restart_ints() below |
3608 | 3609 | * to tell the hw how much work has been processed, | |
3609 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) { | 3610 | * so we must read it before checking for more work. |
3610 | tp->last_tag = sblk->status_tag; | 3611 | */ |
3611 | rmb(); | 3612 | tp->last_tag = sblk->status_tag; |
3612 | } else | 3613 | rmb(); |
3613 | sblk->status &= ~SD_STATUS_UPDATED; | 3614 | } else |
3615 | sblk->status &= ~SD_STATUS_UPDATED; | ||
3614 | 3616 | ||
3617 | if (likely(!tg3_has_work(tp))) { | ||
3615 | netif_rx_complete(tp->dev, napi); | 3618 | netif_rx_complete(tp->dev, napi); |
3616 | tg3_restart_ints(tp); | 3619 | tg3_restart_ints(tp); |
3617 | break; | 3620 | break; |
@@ -3621,9 +3624,10 @@ static int tg3_poll(struct napi_struct *napi, int budget) | |||
3621 | return work_done; | 3624 | return work_done; |
3622 | 3625 | ||
3623 | tx_recovery: | 3626 | tx_recovery: |
3627 | /* work_done is guaranteed to be less than budget. */ | ||
3624 | netif_rx_complete(tp->dev, napi); | 3628 | netif_rx_complete(tp->dev, napi); |
3625 | schedule_work(&tp->reset_task); | 3629 | schedule_work(&tp->reset_task); |
3626 | return 0; | 3630 | return work_done; |
3627 | } | 3631 | } |
3628 | 3632 | ||
3629 | static void tg3_irq_quiesce(struct tg3 *tp) | 3633 | static void tg3_irq_quiesce(struct tg3 *tp) |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index aeda52682446..d427daeef511 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/genhd.h> | 53 | #include <linux/genhd.h> |
54 | #include <linux/hdreg.h> | 54 | #include <linux/hdreg.h> |
55 | #include <linux/interrupt.h> | 55 | #include <linux/interrupt.h> |
56 | #include <linux/log2.h> | ||
56 | #include <asm/ccwdev.h> | 57 | #include <asm/ccwdev.h> |
57 | #include <linux/workqueue.h> | 58 | #include <linux/workqueue.h> |
58 | #include <asm/debug.h> | 59 | #include <asm/debug.h> |
@@ -456,7 +457,7 @@ dasd_free_chunk(struct list_head *chunk_list, void *mem) | |||
456 | static inline int | 457 | static inline int |
457 | dasd_check_blocksize(int bsize) | 458 | dasd_check_blocksize(int bsize) |
458 | { | 459 | { |
459 | if (bsize < 512 || bsize > 4096 || (bsize & (bsize - 1)) != 0) | 460 | if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize)) |
460 | return -EMEDIUMTYPE; | 461 | return -EMEDIUMTYPE; |
461 | return 0; | 462 | return 0; |
462 | } | 463 | } |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 0fbacc8b1063..f231bc21b1ca 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
@@ -230,7 +230,7 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio) | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | set_bit(BIO_UPTODATE, &bio->bi_flags); | 232 | set_bit(BIO_UPTODATE, &bio->bi_flags); |
233 | bio_end_io(bio, 0); | 233 | bio_endio(bio, 0); |
234 | return 0; | 234 | return 0; |
235 | fail: | 235 | fail: |
236 | bio_io_error(bio); | 236 | bio_io_error(bio); |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 6000bdee4082..0e1f35c9ed9d 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -667,6 +667,9 @@ raw3215_probe (struct ccw_device *cdev) | |||
667 | struct raw3215_info *raw; | 667 | struct raw3215_info *raw; |
668 | int line; | 668 | int line; |
669 | 669 | ||
670 | /* Console is special. */ | ||
671 | if (raw3215[0] && (cdev->dev.driver_data == raw3215[0])) | ||
672 | return 0; | ||
670 | raw = kmalloc(sizeof(struct raw3215_info) + | 673 | raw = kmalloc(sizeof(struct raw3215_info) + |
671 | RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); | 674 | RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); |
672 | if (raw == NULL) | 675 | if (raw == NULL) |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index fd3479119eb4..0b040557db02 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/ebcdic.h> | 22 | #include <asm/ebcdic.h> |
23 | 23 | ||
24 | #include "raw3270.h" | 24 | #include "raw3270.h" |
25 | #include "tty3270.h" | ||
25 | #include "ctrlchar.h" | 26 | #include "ctrlchar.h" |
26 | 27 | ||
27 | #define CON3270_OUTPUT_BUFFER_SIZE 1024 | 28 | #define CON3270_OUTPUT_BUFFER_SIZE 1024 |
@@ -507,8 +508,6 @@ con3270_write(struct console *co, const char *str, unsigned int count) | |||
507 | spin_unlock_irqrestore(&cp->view.lock,flags); | 508 | spin_unlock_irqrestore(&cp->view.lock,flags); |
508 | } | 509 | } |
509 | 510 | ||
510 | extern struct tty_driver *tty3270_driver; | ||
511 | |||
512 | static struct tty_driver * | 511 | static struct tty_driver * |
513 | con3270_device(struct console *c, int *index) | 512 | con3270_device(struct console *c, int *index) |
514 | { | 513 | { |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index fa62e6944057..25629b92dec3 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -93,6 +93,7 @@ static volatile enum sclp_mask_state_t { | |||
93 | #define SCLP_RETRY_INTERVAL 30 | 93 | #define SCLP_RETRY_INTERVAL 30 |
94 | 94 | ||
95 | static void sclp_process_queue(void); | 95 | static void sclp_process_queue(void); |
96 | static void __sclp_make_read_req(void); | ||
96 | static int sclp_init_mask(int calculate); | 97 | static int sclp_init_mask(int calculate); |
97 | static int sclp_init(void); | 98 | static int sclp_init(void); |
98 | 99 | ||
@@ -115,7 +116,6 @@ sclp_service_call(sclp_cmdw_t command, void *sccb) | |||
115 | return 0; | 116 | return 0; |
116 | } | 117 | } |
117 | 118 | ||
118 | static inline void __sclp_make_read_req(void); | ||
119 | 119 | ||
120 | static void | 120 | static void |
121 | __sclp_queue_read_req(void) | 121 | __sclp_queue_read_req(void) |
@@ -318,8 +318,7 @@ sclp_read_cb(struct sclp_req *req, void *data) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | /* Prepare read event data request. Called while sclp_lock is locked. */ | 320 | /* Prepare read event data request. Called while sclp_lock is locked. */ |
321 | static inline void | 321 | static void __sclp_make_read_req(void) |
322 | __sclp_make_read_req(void) | ||
323 | { | 322 | { |
324 | struct sccb_header *sccb; | 323 | struct sccb_header *sccb; |
325 | 324 | ||
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 9f244c591eeb..da25f8e24152 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -708,16 +708,22 @@ static void tape_3590_med_state_set(struct tape_device *device, | |||
708 | 708 | ||
709 | c_info = &TAPE_3590_CRYPT_INFO(device); | 709 | c_info = &TAPE_3590_CRYPT_INFO(device); |
710 | 710 | ||
711 | if (sense->masst == MSENSE_UNASSOCIATED) { | 711 | DBF_EVENT(6, "medium state: %x:%x\n", sense->macst, sense->masst); |
712 | switch (sense->macst) { | ||
713 | case 0x04: | ||
714 | case 0x05: | ||
715 | case 0x06: | ||
712 | tape_med_state_set(device, MS_UNLOADED); | 716 | tape_med_state_set(device, MS_UNLOADED); |
713 | TAPE_3590_CRYPT_INFO(device).medium_status = 0; | 717 | TAPE_3590_CRYPT_INFO(device).medium_status = 0; |
714 | return; | 718 | return; |
715 | } | 719 | case 0x08: |
716 | if (sense->masst != MSENSE_ASSOCIATED_MOUNT) { | 720 | case 0x09: |
717 | PRINT_ERR("Unknown medium state: %x\n", sense->masst); | 721 | tape_med_state_set(device, MS_LOADED); |
722 | break; | ||
723 | default: | ||
724 | tape_med_state_set(device, MS_UNKNOWN); | ||
718 | return; | 725 | return; |
719 | } | 726 | } |
720 | tape_med_state_set(device, MS_LOADED); | ||
721 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; | 727 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; |
722 | if (sense->flags & MSENSE_CRYPT_MASK) { | 728 | if (sense->flags & MSENSE_CRYPT_MASK) { |
723 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); | 729 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); |
@@ -835,15 +841,17 @@ tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb) | |||
835 | /* Probably result of halt ssch */ | 841 | /* Probably result of halt ssch */ |
836 | return TAPE_IO_PENDING; | 842 | return TAPE_IO_PENDING; |
837 | else if (irb->scsw.dstat == 0x85) | 843 | else if (irb->scsw.dstat == 0x85) |
838 | /* Device Ready -> check medium state */ | 844 | /* Device Ready */ |
839 | tape_3590_schedule_work(device, TO_MSEN); | 845 | DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id); |
840 | else if (irb->scsw.dstat & DEV_STAT_ATTENTION) | 846 | else if (irb->scsw.dstat & DEV_STAT_ATTENTION) { |
841 | tape_3590_schedule_work(device, TO_READ_ATTMSG); | 847 | tape_3590_schedule_work(device, TO_READ_ATTMSG); |
842 | else { | 848 | } else { |
843 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); | 849 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); |
844 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); | 850 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); |
845 | tape_dump_sense(device, NULL, irb); | 851 | tape_dump_sense(device, NULL, irb); |
846 | } | 852 | } |
853 | /* check medium state */ | ||
854 | tape_3590_schedule_work(device, TO_MSEN); | ||
847 | return TAPE_IO_SUCCESS; | 855 | return TAPE_IO_SUCCESS; |
848 | } | 856 | } |
849 | 857 | ||
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index bc33068b9ce2..70b1980a08b6 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | 27 | ||
28 | |||
29 | #include "raw3270.h" | 28 | #include "raw3270.h" |
29 | #include "tty3270.h" | ||
30 | #include "keyboard.h" | 30 | #include "keyboard.h" |
31 | 31 | ||
32 | #define TTY3270_CHAR_BUF_SIZE 256 | 32 | #define TTY3270_CHAR_BUF_SIZE 256 |
@@ -1338,8 +1338,11 @@ tty3270_getpar(struct tty3270 *tp, int ix) | |||
1338 | static void | 1338 | static void |
1339 | tty3270_goto_xy(struct tty3270 *tp, int cx, int cy) | 1339 | tty3270_goto_xy(struct tty3270 *tp, int cx, int cy) |
1340 | { | 1340 | { |
1341 | tp->cx = min_t(int, tp->view.cols - 1, max_t(int, 0, cx)); | 1341 | int max_cx = max(0, cx); |
1342 | cy = min_t(int, tp->view.rows - 3, max_t(int, 0, cy)); | 1342 | int max_cy = max(0, cy); |
1343 | |||
1344 | tp->cx = min_t(int, tp->view.cols - 1, max_cx); | ||
1345 | cy = min_t(int, tp->view.rows - 3, max_cy); | ||
1343 | if (cy != tp->cy) { | 1346 | if (cy != tp->cy) { |
1344 | tty3270_convert_line(tp, tp->cy); | 1347 | tty3270_convert_line(tp, tp->cy); |
1345 | tp->cy = cy; | 1348 | tp->cy = cy; |
diff --git a/drivers/s390/char/tty3270.h b/drivers/s390/char/tty3270.h new file mode 100644 index 000000000000..799da57f0390 --- /dev/null +++ b/drivers/s390/char/tty3270.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * drivers/s390/char/tty3270.h | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #ifndef __DRIVERS_S390_CHAR_TTY3270_H | ||
9 | #define __DRIVERS_S390_CHAR_TTY3270_H | ||
10 | |||
11 | #include <linux/tty.h> | ||
12 | #include <linux/tty_driver.h> | ||
13 | |||
14 | extern struct tty_driver *tty3270_driver; | ||
15 | |||
16 | #endif /* __DRIVERS_S390_CHAR_TTY3270_H */ | ||
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c index 680b9b58b80e..6f40facb1c4d 100644 --- a/drivers/s390/char/vmwatchdog.c +++ b/drivers/s390/char/vmwatchdog.c | |||
@@ -66,8 +66,8 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout, | |||
66 | "0: la %0,0\n" | 66 | "0: la %0,0\n" |
67 | "1:\n" | 67 | "1:\n" |
68 | EX_TABLE(0b,1b) | 68 | EX_TABLE(0b,1b) |
69 | : "=d" (err) : "d"(__func), "d"(__timeout), | 69 | : "+d" (err) : "d"(__func), "d"(__timeout), |
70 | "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc"); | 70 | "d"(__cmdp), "d"(__cmdl) : "1", "cc"); |
71 | return err; | 71 | return err; |
72 | } | 72 | } |
73 | 73 | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 3712ede16723..7073daf77981 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -141,15 +141,16 @@ static int memcpy_real(void *dest, unsigned long src, size_t count) | |||
141 | 141 | ||
142 | if (count == 0) | 142 | if (count == 0) |
143 | return 0; | 143 | return 0; |
144 | flags = __raw_local_irq_stnsm(0xf8); /* switch to real mode */ | 144 | flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */ |
145 | asm volatile ( | 145 | asm volatile ( |
146 | "0: mvcle %1,%2,0x0\n" | 146 | "0: mvcle %1,%2,0x0\n" |
147 | "1: jo 0b\n" | 147 | "1: jo 0b\n" |
148 | " lhi %0,0x0\n" | 148 | " lhi %0,0x0\n" |
149 | "2:\n" | 149 | "2:\n" |
150 | EX_TABLE(1b,2b) | 150 | EX_TABLE(1b,2b) |
151 | : "+d" (rc) | 151 | : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1), |
152 | : "d" (_dest), "d" (_src), "d" (_len1), "d" (_len2) | 152 | "+d" (_len2), "=m" (*((long*)dest)) |
153 | : "m" (*((long*)src)) | ||
153 | : "cc", "memory"); | 154 | : "cc", "memory"); |
154 | __raw_local_irq_ssm(flags); | 155 | __raw_local_irq_ssm(flags); |
155 | 156 | ||
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5d967c439822..5baa517c3b66 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -151,16 +151,24 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | |||
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | /* | 154 | /** |
155 | * try to add a new ccwgroup device for one driver | 155 | * ccwgroup_create() - create and register a ccw group device |
156 | * argc and argv[] are a list of bus_id's of devices | 156 | * @root: parent device for the new device |
157 | * belonging to the driver. | 157 | * @creator_id: identifier of creating driver |
158 | * @cdrv: ccw driver of slave devices | ||
159 | * @argc: number of slave devices | ||
160 | * @argv: bus ids of slave devices | ||
161 | * | ||
162 | * Create and register a new ccw group device as a child of @root. Slave | ||
163 | * devices are obtained from the list of bus ids given in @argv[] and must all | ||
164 | * belong to @cdrv. | ||
165 | * Returns: | ||
166 | * %0 on success and an error code on failure. | ||
167 | * Context: | ||
168 | * non-atomic | ||
158 | */ | 169 | */ |
159 | int | 170 | int ccwgroup_create(struct device *root, unsigned int creator_id, |
160 | ccwgroup_create(struct device *root, | 171 | struct ccw_driver *cdrv, int argc, char *argv[]) |
161 | unsigned int creator_id, | ||
162 | struct ccw_driver *cdrv, | ||
163 | int argc, char *argv[]) | ||
164 | { | 172 | { |
165 | struct ccwgroup_device *gdev; | 173 | struct ccwgroup_device *gdev; |
166 | int i; | 174 | int i; |
@@ -389,8 +397,13 @@ static struct bus_type ccwgroup_bus_type = { | |||
389 | .remove = ccwgroup_remove, | 397 | .remove = ccwgroup_remove, |
390 | }; | 398 | }; |
391 | 399 | ||
392 | int | 400 | /** |
393 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | 401 | * ccwgroup_driver_register() - register a ccw group driver |
402 | * @cdriver: driver to be registered | ||
403 | * | ||
404 | * This function is mainly a wrapper around driver_register(). | ||
405 | */ | ||
406 | int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) | ||
394 | { | 407 | { |
395 | /* register our new driver with the core */ | 408 | /* register our new driver with the core */ |
396 | cdriver->driver.bus = &ccwgroup_bus_type; | 409 | cdriver->driver.bus = &ccwgroup_bus_type; |
@@ -405,8 +418,13 @@ __ccwgroup_match_all(struct device *dev, void *data) | |||
405 | return 1; | 418 | return 1; |
406 | } | 419 | } |
407 | 420 | ||
408 | void | 421 | /** |
409 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 422 | * ccwgroup_driver_unregister() - deregister a ccw group driver |
423 | * @cdriver: driver to be deregistered | ||
424 | * | ||
425 | * This function is mainly a wrapper around driver_unregister(). | ||
426 | */ | ||
427 | void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | ||
410 | { | 428 | { |
411 | struct device *dev; | 429 | struct device *dev; |
412 | 430 | ||
@@ -426,8 +444,16 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | |||
426 | driver_unregister(&cdriver->driver); | 444 | driver_unregister(&cdriver->driver); |
427 | } | 445 | } |
428 | 446 | ||
429 | int | 447 | /** |
430 | ccwgroup_probe_ccwdev(struct ccw_device *cdev) | 448 | * ccwgroup_probe_ccwdev() - probe function for slave devices |
449 | * @cdev: ccw device to be probed | ||
450 | * | ||
451 | * This is a dummy probe function for ccw devices that are slave devices in | ||
452 | * a ccw group device. | ||
453 | * Returns: | ||
454 | * always %0 | ||
455 | */ | ||
456 | int ccwgroup_probe_ccwdev(struct ccw_device *cdev) | ||
431 | { | 457 | { |
432 | return 0; | 458 | return 0; |
433 | } | 459 | } |
@@ -451,8 +477,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) | |||
451 | return NULL; | 477 | return NULL; |
452 | } | 478 | } |
453 | 479 | ||
454 | void | 480 | /** |
455 | ccwgroup_remove_ccwdev(struct ccw_device *cdev) | 481 | * ccwgroup_remove_ccwdev() - remove function for slave devices |
482 | * @cdev: ccw device to be removed | ||
483 | * | ||
484 | * This is a remove function for ccw devices that are slave devices in a ccw | ||
485 | * group device. It sets the ccw device offline and also deregisters the | ||
486 | * embedding ccw group device. | ||
487 | */ | ||
488 | void ccwgroup_remove_ccwdev(struct ccw_device *cdev) | ||
456 | { | 489 | { |
457 | struct ccwgroup_device *gdev; | 490 | struct ccwgroup_device *gdev; |
458 | 491 | ||
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 920dd71e6434..42c1f4659adb 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
15 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <asm/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <asm/chpid.h> | 18 | #include <asm/chpid.h> |
19 | #include <asm/sclp.h> | 19 | #include <asm/sclp.h> |
20 | 20 | ||
@@ -55,7 +55,7 @@ static wait_queue_head_t cfg_wait_queue; | |||
55 | /* Return channel_path struct for given chpid. */ | 55 | /* Return channel_path struct for given chpid. */ |
56 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) | 56 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) |
57 | { | 57 | { |
58 | return css[chpid.cssid]->chps[chpid.id]; | 58 | return channel_subsystems[chpid.cssid]->chps[chpid.id]; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Set vary state for given chpid. */ | 61 | /* Set vary state for given chpid. */ |
@@ -86,7 +86,7 @@ u8 chp_get_sch_opm(struct subchannel *sch) | |||
86 | 86 | ||
87 | opm = 0; | 87 | opm = 0; |
88 | chp_id_init(&chpid); | 88 | chp_id_init(&chpid); |
89 | for (i=0; i < 8; i++) { | 89 | for (i = 0; i < 8; i++) { |
90 | opm <<= 1; | 90 | opm <<= 1; |
91 | chpid.id = sch->schib.pmcw.chpid[i]; | 91 | chpid.id = sch->schib.pmcw.chpid[i]; |
92 | if (chp_get_status(chpid) != 0) | 92 | if (chp_get_status(chpid) != 0) |
@@ -118,7 +118,7 @@ static int s390_vary_chpid(struct chp_id chpid, int on) | |||
118 | 118 | ||
119 | sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, | 119 | sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, |
120 | chpid.id); | 120 | chpid.id); |
121 | CIO_TRACE_EVENT( 2, dbf_text); | 121 | CIO_TRACE_EVENT(2, dbf_text); |
122 | 122 | ||
123 | status = chp_get_status(chpid); | 123 | status = chp_get_status(chpid); |
124 | if (!on && !status) { | 124 | if (!on && !status) { |
@@ -140,9 +140,11 @@ static ssize_t chp_measurement_chars_read(struct kobject *kobj, | |||
140 | char *buf, loff_t off, size_t count) | 140 | char *buf, loff_t off, size_t count) |
141 | { | 141 | { |
142 | struct channel_path *chp; | 142 | struct channel_path *chp; |
143 | struct device *device; | ||
143 | unsigned int size; | 144 | unsigned int size; |
144 | 145 | ||
145 | chp = to_channelpath(container_of(kobj, struct device, kobj)); | 146 | device = container_of(kobj, struct device, kobj); |
147 | chp = to_channelpath(device); | ||
146 | if (!chp->cmg_chars) | 148 | if (!chp->cmg_chars) |
147 | return 0; | 149 | return 0; |
148 | 150 | ||
@@ -193,9 +195,11 @@ static ssize_t chp_measurement_read(struct kobject *kobj, | |||
193 | { | 195 | { |
194 | struct channel_path *chp; | 196 | struct channel_path *chp; |
195 | struct channel_subsystem *css; | 197 | struct channel_subsystem *css; |
198 | struct device *device; | ||
196 | unsigned int size; | 199 | unsigned int size; |
197 | 200 | ||
198 | chp = to_channelpath(container_of(kobj, struct device, kobj)); | 201 | device = container_of(kobj, struct device, kobj); |
202 | chp = to_channelpath(device); | ||
199 | css = to_css(chp->dev.parent); | 203 | css = to_css(chp->dev.parent); |
200 | 204 | ||
201 | size = sizeof(struct cmg_entry); | 205 | size = sizeof(struct cmg_entry); |
@@ -353,7 +357,7 @@ static ssize_t chp_shared_show(struct device *dev, | |||
353 | 357 | ||
354 | static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); | 358 | static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); |
355 | 359 | ||
356 | static struct attribute * chp_attrs[] = { | 360 | static struct attribute *chp_attrs[] = { |
357 | &dev_attr_status.attr, | 361 | &dev_attr_status.attr, |
358 | &dev_attr_configure.attr, | 362 | &dev_attr_configure.attr, |
359 | &dev_attr_type.attr, | 363 | &dev_attr_type.attr, |
@@ -395,7 +399,7 @@ int chp_new(struct chp_id chpid) | |||
395 | /* fill in status, etc. */ | 399 | /* fill in status, etc. */ |
396 | chp->chpid = chpid; | 400 | chp->chpid = chpid; |
397 | chp->state = 1; | 401 | chp->state = 1; |
398 | chp->dev.parent = &css[chpid.cssid]->device; | 402 | chp->dev.parent = &channel_subsystems[chpid.cssid]->device; |
399 | chp->dev.release = chp_release; | 403 | chp->dev.release = chp_release; |
400 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, | 404 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, |
401 | chpid.id); | 405 | chpid.id); |
@@ -430,18 +434,18 @@ int chp_new(struct chp_id chpid) | |||
430 | device_unregister(&chp->dev); | 434 | device_unregister(&chp->dev); |
431 | goto out_free; | 435 | goto out_free; |
432 | } | 436 | } |
433 | mutex_lock(&css[chpid.cssid]->mutex); | 437 | mutex_lock(&channel_subsystems[chpid.cssid]->mutex); |
434 | if (css[chpid.cssid]->cm_enabled) { | 438 | if (channel_subsystems[chpid.cssid]->cm_enabled) { |
435 | ret = chp_add_cmg_attr(chp); | 439 | ret = chp_add_cmg_attr(chp); |
436 | if (ret) { | 440 | if (ret) { |
437 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); | 441 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); |
438 | device_unregister(&chp->dev); | 442 | device_unregister(&chp->dev); |
439 | mutex_unlock(&css[chpid.cssid]->mutex); | 443 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); |
440 | goto out_free; | 444 | goto out_free; |
441 | } | 445 | } |
442 | } | 446 | } |
443 | css[chpid.cssid]->chps[chpid.id] = chp; | 447 | channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; |
444 | mutex_unlock(&css[chpid.cssid]->mutex); | 448 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); |
445 | return ret; | 449 | return ret; |
446 | out_free: | 450 | out_free: |
447 | kfree(chp); | 451 | kfree(chp); |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index f2708d65be5a..46905345159e 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -619,6 +619,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
619 | sch->schib.pmcw.ena = 0; | 619 | sch->schib.pmcw.ena = 0; |
620 | if ((sch->lpm & (sch->lpm - 1)) != 0) | 620 | if ((sch->lpm & (sch->lpm - 1)) != 0) |
621 | sch->schib.pmcw.mp = 1; /* multipath mode */ | 621 | sch->schib.pmcw.mp = 1; /* multipath mode */ |
622 | /* clean up possible residual cmf stuff */ | ||
623 | sch->schib.pmcw.mme = 0; | ||
624 | sch->schib.pmcw.mbfc = 0; | ||
625 | sch->schib.pmcw.mbi = 0; | ||
626 | sch->schib.mba = 0; | ||
622 | return 0; | 627 | return 0; |
623 | out: | 628 | out: |
624 | if (!cio_is_console(schid)) | 629 | if (!cio_is_console(schid)) |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 34a796913b06..b960f66843e4 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -45,7 +45,8 @@ | |||
45 | #include "ioasm.h" | 45 | #include "ioasm.h" |
46 | #include "chsc.h" | 46 | #include "chsc.h" |
47 | 47 | ||
48 | /* parameter to enable cmf during boot, possible uses are: | 48 | /* |
49 | * parameter to enable cmf during boot, possible uses are: | ||
49 | * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be | 50 | * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be |
50 | * used on any subchannel | 51 | * used on any subchannel |
51 | * "s390cmf=<num>" -- enable cmf and allocate enough memory to measure | 52 | * "s390cmf=<num>" -- enable cmf and allocate enough memory to measure |
@@ -73,18 +74,20 @@ enum cmb_index { | |||
73 | * enum cmb_format - types of supported measurement block formats | 74 | * enum cmb_format - types of supported measurement block formats |
74 | * | 75 | * |
75 | * @CMF_BASIC: traditional channel measurement blocks supported | 76 | * @CMF_BASIC: traditional channel measurement blocks supported |
76 | * by all machines that we run on | 77 | * by all machines that we run on |
77 | * @CMF_EXTENDED: improved format that was introduced with the z990 | 78 | * @CMF_EXTENDED: improved format that was introduced with the z990 |
78 | * machine | 79 | * machine |
79 | * @CMF_AUTODETECT: default: use extended format when running on a z990 | 80 | * @CMF_AUTODETECT: default: use extended format when running on a machine |
80 | * or later machine, otherwise fall back to basic format | 81 | * supporting extended format, otherwise fall back to |
81 | **/ | 82 | * basic format |
83 | */ | ||
82 | enum cmb_format { | 84 | enum cmb_format { |
83 | CMF_BASIC, | 85 | CMF_BASIC, |
84 | CMF_EXTENDED, | 86 | CMF_EXTENDED, |
85 | CMF_AUTODETECT = -1, | 87 | CMF_AUTODETECT = -1, |
86 | }; | 88 | }; |
87 | /** | 89 | |
90 | /* | ||
88 | * format - actual format for all measurement blocks | 91 | * format - actual format for all measurement blocks |
89 | * | 92 | * |
90 | * The format module parameter can be set to a value of 0 (zero) | 93 | * The format module parameter can be set to a value of 0 (zero) |
@@ -105,20 +108,21 @@ module_param(format, bool, 0444); | |||
105 | * either with the help of a special pool or with kmalloc | 108 | * either with the help of a special pool or with kmalloc |
106 | * @free: free memory allocated with @alloc | 109 | * @free: free memory allocated with @alloc |
107 | * @set: enable or disable measurement | 110 | * @set: enable or disable measurement |
111 | * @read: read a measurement entry at an index | ||
108 | * @readall: read a measurement block in a common format | 112 | * @readall: read a measurement block in a common format |
109 | * @reset: clear the data in the associated measurement block and | 113 | * @reset: clear the data in the associated measurement block and |
110 | * reset its time stamp | 114 | * reset its time stamp |
111 | * @align: align an allocated block so that the hardware can use it | 115 | * @align: align an allocated block so that the hardware can use it |
112 | */ | 116 | */ |
113 | struct cmb_operations { | 117 | struct cmb_operations { |
114 | int (*alloc) (struct ccw_device*); | 118 | int (*alloc) (struct ccw_device *); |
115 | void(*free) (struct ccw_device*); | 119 | void (*free) (struct ccw_device *); |
116 | int (*set) (struct ccw_device*, u32); | 120 | int (*set) (struct ccw_device *, u32); |
117 | u64 (*read) (struct ccw_device*, int); | 121 | u64 (*read) (struct ccw_device *, int); |
118 | int (*readall)(struct ccw_device*, struct cmbdata *); | 122 | int (*readall)(struct ccw_device *, struct cmbdata *); |
119 | void (*reset) (struct ccw_device*); | 123 | void (*reset) (struct ccw_device *); |
120 | void * (*align) (void *); | 124 | void *(*align) (void *); |
121 | 125 | /* private: */ | |
122 | struct attribute_group *attr_group; | 126 | struct attribute_group *attr_group; |
123 | }; | 127 | }; |
124 | static struct cmb_operations *cmbops; | 128 | static struct cmb_operations *cmbops; |
@@ -130,9 +134,11 @@ struct cmb_data { | |||
130 | unsigned long long last_update; /* when last_block was updated */ | 134 | unsigned long long last_update; /* when last_block was updated */ |
131 | }; | 135 | }; |
132 | 136 | ||
133 | /* our user interface is designed in terms of nanoseconds, | 137 | /* |
138 | * Our user interface is designed in terms of nanoseconds, | ||
134 | * while the hardware measures total times in its own | 139 | * while the hardware measures total times in its own |
135 | * unit.*/ | 140 | * unit. |
141 | */ | ||
136 | static inline u64 time_to_nsec(u32 value) | 142 | static inline u64 time_to_nsec(u32 value) |
137 | { | 143 | { |
138 | return ((u64)value) * 128000ull; | 144 | return ((u64)value) * 128000ull; |
@@ -159,12 +165,13 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count) | |||
159 | return ret; | 165 | return ret; |
160 | } | 166 | } |
161 | 167 | ||
162 | /* activate or deactivate the channel monitor. When area is NULL, | 168 | /* |
169 | * Activate or deactivate the channel monitor. When area is NULL, | ||
163 | * the monitor is deactivated. The channel monitor needs to | 170 | * the monitor is deactivated. The channel monitor needs to |
164 | * be active in order to measure subchannels, which also need | 171 | * be active in order to measure subchannels, which also need |
165 | * to be enabled. */ | 172 | * to be enabled. |
166 | static inline void | 173 | */ |
167 | cmf_activate(void *area, unsigned int onoff) | 174 | static inline void cmf_activate(void *area, unsigned int onoff) |
168 | { | 175 | { |
169 | register void * __gpr2 asm("2"); | 176 | register void * __gpr2 asm("2"); |
170 | register long __gpr1 asm("1"); | 177 | register long __gpr1 asm("1"); |
@@ -175,8 +182,8 @@ cmf_activate(void *area, unsigned int onoff) | |||
175 | asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); | 182 | asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); |
176 | } | 183 | } |
177 | 184 | ||
178 | static int | 185 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, |
179 | set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) | 186 | unsigned long address) |
180 | { | 187 | { |
181 | int ret; | 188 | int ret; |
182 | int retry; | 189 | int retry; |
@@ -466,6 +473,7 @@ static void cmf_generic_reset(struct ccw_device *cdev) | |||
466 | * | 473 | * |
467 | * @mem: pointer to CMBs (only in basic measurement mode) | 474 | * @mem: pointer to CMBs (only in basic measurement mode) |
468 | * @list: contains a linked list of all subchannels | 475 | * @list: contains a linked list of all subchannels |
476 | * @num_channels: number of channels to be measured | ||
469 | * @lock: protect concurrent access to @mem and @list | 477 | * @lock: protect concurrent access to @mem and @list |
470 | */ | 478 | */ |
471 | struct cmb_area { | 479 | struct cmb_area { |
@@ -481,28 +489,36 @@ static struct cmb_area cmb_area = { | |||
481 | .num_channels = 1024, | 489 | .num_channels = 1024, |
482 | }; | 490 | }; |
483 | 491 | ||
484 | |||
485 | /* ****** old style CMB handling ********/ | 492 | /* ****** old style CMB handling ********/ |
486 | 493 | ||
487 | /** int maxchannels | 494 | /* |
488 | * | ||
489 | * Basic channel measurement blocks are allocated in one contiguous | 495 | * Basic channel measurement blocks are allocated in one contiguous |
490 | * block of memory, which can not be moved as long as any channel | 496 | * block of memory, which can not be moved as long as any channel |
491 | * is active. Therefore, a maximum number of subchannels needs to | 497 | * is active. Therefore, a maximum number of subchannels needs to |
492 | * be defined somewhere. This is a module parameter, defaulting to | 498 | * be defined somewhere. This is a module parameter, defaulting to |
493 | * a resonable value of 1024, or 32 kb of memory. | 499 | * a resonable value of 1024, or 32 kb of memory. |
494 | * Current kernels don't allow kmalloc with more than 128kb, so the | 500 | * Current kernels don't allow kmalloc with more than 128kb, so the |
495 | * maximum is 4096 | 501 | * maximum is 4096. |
496 | */ | 502 | */ |
497 | 503 | ||
498 | module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); | 504 | module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); |
499 | 505 | ||
500 | /** | 506 | /** |
501 | * struct cmb - basic channel measurement block | 507 | * struct cmb - basic channel measurement block |
508 | * @ssch_rsch_count: number of ssch and rsch | ||
509 | * @sample_count: number of samples | ||
510 | * @device_connect_time: time of device connect | ||
511 | * @function_pending_time: time of function pending | ||
512 | * @device_disconnect_time: time of device disconnect | ||
513 | * @control_unit_queuing_time: time of control unit queuing | ||
514 | * @device_active_only_time: time of device active only | ||
515 | * @reserved: unused in basic measurement mode | ||
516 | * | ||
517 | * The measurement block as used by the hardware. The fields are described | ||
518 | * further in z/Architecture Principles of Operation, chapter 17. | ||
502 | * | 519 | * |
503 | * cmb as used by the hardware the fields are described in z/Architecture | 520 | * The cmb area made up from these blocks must be a contiguous array and may |
504 | * Principles of Operation, chapter 17. | 521 | * not be reallocated or freed. |
505 | * The area to be a contiguous array and may not be reallocated or freed. | ||
506 | * Only one cmb area can be present in the system. | 522 | * Only one cmb area can be present in the system. |
507 | */ | 523 | */ |
508 | struct cmb { | 524 | struct cmb { |
@@ -516,8 +532,9 @@ struct cmb { | |||
516 | u32 reserved[2]; | 532 | u32 reserved[2]; |
517 | }; | 533 | }; |
518 | 534 | ||
519 | /* insert a single device into the cmb_area list | 535 | /* |
520 | * called with cmb_area.lock held from alloc_cmb | 536 | * Insert a single device into the cmb_area list. |
537 | * Called with cmb_area.lock held from alloc_cmb. | ||
521 | */ | 538 | */ |
522 | static int alloc_cmb_single(struct ccw_device *cdev, | 539 | static int alloc_cmb_single(struct ccw_device *cdev, |
523 | struct cmb_data *cmb_data) | 540 | struct cmb_data *cmb_data) |
@@ -532,9 +549,11 @@ static int alloc_cmb_single(struct ccw_device *cdev, | |||
532 | goto out; | 549 | goto out; |
533 | } | 550 | } |
534 | 551 | ||
535 | /* find first unused cmb in cmb_area.mem. | 552 | /* |
536 | * this is a little tricky: cmb_area.list | 553 | * Find first unused cmb in cmb_area.mem. |
537 | * remains sorted by ->cmb->hw_data pointers */ | 554 | * This is a little tricky: cmb_area.list |
555 | * remains sorted by ->cmb->hw_data pointers. | ||
556 | */ | ||
538 | cmb = cmb_area.mem; | 557 | cmb = cmb_area.mem; |
539 | list_for_each_entry(node, &cmb_area.list, cmb_list) { | 558 | list_for_each_entry(node, &cmb_area.list, cmb_list) { |
540 | struct cmb_data *data; | 559 | struct cmb_data *data; |
@@ -558,8 +577,7 @@ out: | |||
558 | return ret; | 577 | return ret; |
559 | } | 578 | } |
560 | 579 | ||
561 | static int | 580 | static int alloc_cmb(struct ccw_device *cdev) |
562 | alloc_cmb (struct ccw_device *cdev) | ||
563 | { | 581 | { |
564 | int ret; | 582 | int ret; |
565 | struct cmb *mem; | 583 | struct cmb *mem; |
@@ -670,7 +688,7 @@ static int set_cmb(struct ccw_device *cdev, u32 mme) | |||
670 | return set_schib_wait(cdev, mme, 0, offset); | 688 | return set_schib_wait(cdev, mme, 0, offset); |
671 | } | 689 | } |
672 | 690 | ||
673 | static u64 read_cmb (struct ccw_device *cdev, int index) | 691 | static u64 read_cmb(struct ccw_device *cdev, int index) |
674 | { | 692 | { |
675 | struct cmb *cmb; | 693 | struct cmb *cmb; |
676 | u32 val; | 694 | u32 val; |
@@ -720,7 +738,7 @@ out: | |||
720 | return ret; | 738 | return ret; |
721 | } | 739 | } |
722 | 740 | ||
723 | static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data) | 741 | static int readall_cmb(struct ccw_device *cdev, struct cmbdata *data) |
724 | { | 742 | { |
725 | struct cmb *cmb; | 743 | struct cmb *cmb; |
726 | struct cmb_data *cmb_data; | 744 | struct cmb_data *cmb_data; |
@@ -793,14 +811,25 @@ static struct cmb_operations cmbops_basic = { | |||
793 | .align = align_cmb, | 811 | .align = align_cmb, |
794 | .attr_group = &cmf_attr_group, | 812 | .attr_group = &cmf_attr_group, |
795 | }; | 813 | }; |
796 | 814 | ||
797 | /* ******** extended cmb handling ********/ | 815 | /* ******** extended cmb handling ********/ |
798 | 816 | ||
799 | /** | 817 | /** |
800 | * struct cmbe - extended channel measurement block | 818 | * struct cmbe - extended channel measurement block |
819 | * @ssch_rsch_count: number of ssch and rsch | ||
820 | * @sample_count: number of samples | ||
821 | * @device_connect_time: time of device connect | ||
822 | * @function_pending_time: time of function pending | ||
823 | * @device_disconnect_time: time of device disconnect | ||
824 | * @control_unit_queuing_time: time of control unit queuing | ||
825 | * @device_active_only_time: time of device active only | ||
826 | * @device_busy_time: time of device busy | ||
827 | * @initial_command_response_time: initial command response time | ||
828 | * @reserved: unused | ||
801 | * | 829 | * |
802 | * cmb as used by the hardware, may be in any 64 bit physical location, | 830 | * The measurement block as used by the hardware. May be in any 64 bit physical |
803 | * the fields are described in z/Architecture Principles of Operation, | 831 | * location. |
832 | * The fields are described further in z/Architecture Principles of Operation, | ||
804 | * third edition, chapter 17. | 833 | * third edition, chapter 17. |
805 | */ | 834 | */ |
806 | struct cmbe { | 835 | struct cmbe { |
@@ -816,10 +845,12 @@ struct cmbe { | |||
816 | u32 reserved[7]; | 845 | u32 reserved[7]; |
817 | }; | 846 | }; |
818 | 847 | ||
819 | /* kmalloc only guarantees 8 byte alignment, but we need cmbe | 848 | /* |
849 | * kmalloc only guarantees 8 byte alignment, but we need cmbe | ||
820 | * pointers to be naturally aligned. Make sure to allocate | 850 | * pointers to be naturally aligned. Make sure to allocate |
821 | * enough space for two cmbes */ | 851 | * enough space for two cmbes. |
822 | static inline struct cmbe* cmbe_align(struct cmbe *c) | 852 | */ |
853 | static inline struct cmbe *cmbe_align(struct cmbe *c) | ||
823 | { | 854 | { |
824 | unsigned long addr; | 855 | unsigned long addr; |
825 | addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & | 856 | addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & |
@@ -827,7 +858,7 @@ static inline struct cmbe* cmbe_align(struct cmbe *c) | |||
827 | return (struct cmbe*)addr; | 858 | return (struct cmbe*)addr; |
828 | } | 859 | } |
829 | 860 | ||
830 | static int alloc_cmbe (struct ccw_device *cdev) | 861 | static int alloc_cmbe(struct ccw_device *cdev) |
831 | { | 862 | { |
832 | struct cmbe *cmbe; | 863 | struct cmbe *cmbe; |
833 | struct cmb_data *cmb_data; | 864 | struct cmb_data *cmb_data; |
@@ -873,7 +904,7 @@ out_free: | |||
873 | return ret; | 904 | return ret; |
874 | } | 905 | } |
875 | 906 | ||
876 | static void free_cmbe (struct ccw_device *cdev) | 907 | static void free_cmbe(struct ccw_device *cdev) |
877 | { | 908 | { |
878 | struct cmb_data *cmb_data; | 909 | struct cmb_data *cmb_data; |
879 | 910 | ||
@@ -912,7 +943,7 @@ static int set_cmbe(struct ccw_device *cdev, u32 mme) | |||
912 | } | 943 | } |
913 | 944 | ||
914 | 945 | ||
915 | static u64 read_cmbe (struct ccw_device *cdev, int index) | 946 | static u64 read_cmbe(struct ccw_device *cdev, int index) |
916 | { | 947 | { |
917 | struct cmbe *cmb; | 948 | struct cmbe *cmb; |
918 | struct cmb_data *cmb_data; | 949 | struct cmb_data *cmb_data; |
@@ -970,7 +1001,7 @@ out: | |||
970 | return ret; | 1001 | return ret; |
971 | } | 1002 | } |
972 | 1003 | ||
973 | static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) | 1004 | static int readall_cmbe(struct ccw_device *cdev, struct cmbdata *data) |
974 | { | 1005 | { |
975 | struct cmbe *cmb; | 1006 | struct cmbe *cmb; |
976 | struct cmb_data *cmb_data; | 1007 | struct cmb_data *cmb_data; |
@@ -1047,17 +1078,16 @@ static struct cmb_operations cmbops_extended = { | |||
1047 | .align = align_cmbe, | 1078 | .align = align_cmbe, |
1048 | .attr_group = &cmf_attr_group_ext, | 1079 | .attr_group = &cmf_attr_group_ext, |
1049 | }; | 1080 | }; |
1050 | |||
1051 | 1081 | ||
1052 | static ssize_t | 1082 | static ssize_t cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) |
1053 | cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) | ||
1054 | { | 1083 | { |
1055 | return sprintf(buf, "%lld\n", | 1084 | return sprintf(buf, "%lld\n", |
1056 | (unsigned long long) cmf_read(to_ccwdev(dev), idx)); | 1085 | (unsigned long long) cmf_read(to_ccwdev(dev), idx)); |
1057 | } | 1086 | } |
1058 | 1087 | ||
1059 | static ssize_t | 1088 | static ssize_t cmb_show_avg_sample_interval(struct device *dev, |
1060 | cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf) | 1089 | struct device_attribute *attr, |
1090 | char *buf) | ||
1061 | { | 1091 | { |
1062 | struct ccw_device *cdev; | 1092 | struct ccw_device *cdev; |
1063 | long interval; | 1093 | long interval; |
@@ -1079,8 +1109,9 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, | |||
1079 | return sprintf(buf, "%ld\n", interval); | 1109 | return sprintf(buf, "%ld\n", interval); |
1080 | } | 1110 | } |
1081 | 1111 | ||
1082 | static ssize_t | 1112 | static ssize_t cmb_show_avg_utilization(struct device *dev, |
1083 | cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf) | 1113 | struct device_attribute *attr, |
1114 | char *buf) | ||
1084 | { | 1115 | { |
1085 | struct cmbdata data; | 1116 | struct cmbdata data; |
1086 | u64 utilization; | 1117 | u64 utilization; |
@@ -1112,14 +1143,16 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char | |||
1112 | } | 1143 | } |
1113 | 1144 | ||
1114 | #define cmf_attr(name) \ | 1145 | #define cmf_attr(name) \ |
1115 | static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ | 1146 | static ssize_t show_##name(struct device *dev, \ |
1116 | { return cmb_show_attr((dev), buf, cmb_ ## name); } \ | 1147 | struct device_attribute *attr, char *buf) \ |
1117 | static DEVICE_ATTR(name, 0444, show_ ## name, NULL); | 1148 | { return cmb_show_attr((dev), buf, cmb_##name); } \ |
1149 | static DEVICE_ATTR(name, 0444, show_##name, NULL); | ||
1118 | 1150 | ||
1119 | #define cmf_attr_avg(name) \ | 1151 | #define cmf_attr_avg(name) \ |
1120 | static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ | 1152 | static ssize_t show_avg_##name(struct device *dev, \ |
1121 | { return cmb_show_attr((dev), buf, cmb_ ## name); } \ | 1153 | struct device_attribute *attr, char *buf) \ |
1122 | static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL); | 1154 | { return cmb_show_attr((dev), buf, cmb_##name); } \ |
1155 | static DEVICE_ATTR(avg_##name, 0444, show_avg_##name, NULL); | ||
1123 | 1156 | ||
1124 | cmf_attr(ssch_rsch_count); | 1157 | cmf_attr(ssch_rsch_count); |
1125 | cmf_attr(sample_count); | 1158 | cmf_attr(sample_count); |
@@ -1131,7 +1164,8 @@ cmf_attr_avg(device_active_only_time); | |||
1131 | cmf_attr_avg(device_busy_time); | 1164 | cmf_attr_avg(device_busy_time); |
1132 | cmf_attr_avg(initial_command_response_time); | 1165 | cmf_attr_avg(initial_command_response_time); |
1133 | 1166 | ||
1134 | static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL); | 1167 | static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, |
1168 | NULL); | ||
1135 | static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); | 1169 | static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); |
1136 | 1170 | ||
1137 | static struct attribute *cmf_attributes[] = { | 1171 | static struct attribute *cmf_attributes[] = { |
@@ -1172,12 +1206,16 @@ static struct attribute_group cmf_attr_group_ext = { | |||
1172 | .attrs = cmf_attributes_ext, | 1206 | .attrs = cmf_attributes_ext, |
1173 | }; | 1207 | }; |
1174 | 1208 | ||
1175 | static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf) | 1209 | static ssize_t cmb_enable_show(struct device *dev, |
1210 | struct device_attribute *attr, | ||
1211 | char *buf) | ||
1176 | { | 1212 | { |
1177 | return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); | 1213 | return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); |
1178 | } | 1214 | } |
1179 | 1215 | ||
1180 | static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c) | 1216 | static ssize_t cmb_enable_store(struct device *dev, |
1217 | struct device_attribute *attr, const char *buf, | ||
1218 | size_t c) | ||
1181 | { | 1219 | { |
1182 | struct ccw_device *cdev; | 1220 | struct ccw_device *cdev; |
1183 | int ret; | 1221 | int ret; |
@@ -1202,9 +1240,16 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att | |||
1202 | 1240 | ||
1203 | DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); | 1241 | DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); |
1204 | 1242 | ||
1205 | /* enable_cmf/disable_cmf: module interface for cmf (de)activation */ | 1243 | /** |
1206 | int | 1244 | * enable_cmf() - switch on the channel measurement for a specific device |
1207 | enable_cmf(struct ccw_device *cdev) | 1245 | * @cdev: The ccw device to be enabled |
1246 | * | ||
1247 | * Returns %0 for success or a negative error value. | ||
1248 | * | ||
1249 | * Context: | ||
1250 | * non-atomic | ||
1251 | */ | ||
1252 | int enable_cmf(struct ccw_device *cdev) | ||
1208 | { | 1253 | { |
1209 | int ret; | 1254 | int ret; |
1210 | 1255 | ||
@@ -1225,8 +1270,16 @@ enable_cmf(struct ccw_device *cdev) | |||
1225 | return ret; | 1270 | return ret; |
1226 | } | 1271 | } |
1227 | 1272 | ||
1228 | int | 1273 | /** |
1229 | disable_cmf(struct ccw_device *cdev) | 1274 | * disable_cmf() - switch off the channel measurement for a specific device |
1275 | * @cdev: The ccw device to be disabled | ||
1276 | * | ||
1277 | * Returns %0 for success or a negative error value. | ||
1278 | * | ||
1279 | * Context: | ||
1280 | * non-atomic | ||
1281 | */ | ||
1282 | int disable_cmf(struct ccw_device *cdev) | ||
1230 | { | 1283 | { |
1231 | int ret; | 1284 | int ret; |
1232 | 1285 | ||
@@ -1238,14 +1291,32 @@ disable_cmf(struct ccw_device *cdev) | |||
1238 | return ret; | 1291 | return ret; |
1239 | } | 1292 | } |
1240 | 1293 | ||
1241 | u64 | 1294 | /** |
1242 | cmf_read(struct ccw_device *cdev, int index) | 1295 | * cmf_read() - read one value from the current channel measurement block |
1296 | * @cdev: the channel to be read | ||
1297 | * @index: the index of the value to be read | ||
1298 | * | ||
1299 | * Returns the value read or %0 if the value cannot be read. | ||
1300 | * | ||
1301 | * Context: | ||
1302 | * any | ||
1303 | */ | ||
1304 | u64 cmf_read(struct ccw_device *cdev, int index) | ||
1243 | { | 1305 | { |
1244 | return cmbops->read(cdev, index); | 1306 | return cmbops->read(cdev, index); |
1245 | } | 1307 | } |
1246 | 1308 | ||
1247 | int | 1309 | /** |
1248 | cmf_readall(struct ccw_device *cdev, struct cmbdata *data) | 1310 | * cmf_readall() - read the current channel measurement block |
1311 | * @cdev: the channel to be read | ||
1312 | * @data: a pointer to a data block that will be filled | ||
1313 | * | ||
1314 | * Returns %0 on success, a negative error value otherwise. | ||
1315 | * | ||
1316 | * Context: | ||
1317 | * any | ||
1318 | */ | ||
1319 | int cmf_readall(struct ccw_device *cdev, struct cmbdata *data) | ||
1249 | { | 1320 | { |
1250 | return cmbops->readall(cdev, data); | 1321 | return cmbops->readall(cdev, data); |
1251 | } | 1322 | } |
@@ -1257,15 +1328,16 @@ int cmf_reenable(struct ccw_device *cdev) | |||
1257 | return cmbops->set(cdev, 2); | 1328 | return cmbops->set(cdev, 2); |
1258 | } | 1329 | } |
1259 | 1330 | ||
1260 | static int __init | 1331 | static int __init init_cmf(void) |
1261 | init_cmf(void) | ||
1262 | { | 1332 | { |
1263 | char *format_string; | 1333 | char *format_string; |
1264 | char *detect_string = "parameter"; | 1334 | char *detect_string = "parameter"; |
1265 | 1335 | ||
1266 | /* We cannot really autoprobe this. If the user did not give a parameter, | 1336 | /* |
1267 | see if we are running on z990 or up, otherwise fall back to basic mode. */ | 1337 | * If the user did not give a parameter, see if we are running on a |
1268 | 1338 | * machine supporting extended measurement blocks, otherwise fall back | |
1339 | * to basic mode. | ||
1340 | */ | ||
1269 | if (format == CMF_AUTODETECT) { | 1341 | if (format == CMF_AUTODETECT) { |
1270 | if (!css_characteristics_avail || | 1342 | if (!css_characteristics_avail || |
1271 | !css_general_characteristics.ext_mb) { | 1343 | !css_general_characteristics.ext_mb) { |
@@ -1284,7 +1356,7 @@ init_cmf(void) | |||
1284 | cmbops = &cmbops_basic; | 1356 | cmbops = &cmbops_basic; |
1285 | break; | 1357 | break; |
1286 | case CMF_EXTENDED: | 1358 | case CMF_EXTENDED: |
1287 | format_string = "extended"; | 1359 | format_string = "extended"; |
1288 | cmbops = &cmbops_extended; | 1360 | cmbops = &cmbops_extended; |
1289 | break; | 1361 | break; |
1290 | default: | 1362 | default: |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 5635e656c1a3..5d83dd471461 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/reboot.h> | ||
16 | 17 | ||
17 | #include "css.h" | 18 | #include "css.h" |
18 | #include "cio.h" | 19 | #include "cio.h" |
@@ -27,7 +28,7 @@ int css_init_done = 0; | |||
27 | static int need_reprobe = 0; | 28 | static int need_reprobe = 0; |
28 | static int max_ssid = 0; | 29 | static int max_ssid = 0; |
29 | 30 | ||
30 | struct channel_subsystem *css[__MAX_CSSID + 1]; | 31 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; |
31 | 32 | ||
32 | int css_characteristics_avail = 0; | 33 | int css_characteristics_avail = 0; |
33 | 34 | ||
@@ -177,7 +178,7 @@ static int css_register_subchannel(struct subchannel *sch) | |||
177 | int ret; | 178 | int ret; |
178 | 179 | ||
179 | /* Initialize the subchannel structure */ | 180 | /* Initialize the subchannel structure */ |
180 | sch->dev.parent = &css[0]->device; | 181 | sch->dev.parent = &channel_subsystems[0]->device; |
181 | sch->dev.bus = &css_bus_type; | 182 | sch->dev.bus = &css_bus_type; |
182 | sch->dev.release = &css_subchannel_release; | 183 | sch->dev.release = &css_subchannel_release; |
183 | sch->dev.groups = subch_attr_groups; | 184 | sch->dev.groups = subch_attr_groups; |
@@ -606,30 +607,55 @@ static int __init setup_css(int nr) | |||
606 | { | 607 | { |
607 | u32 tod_high; | 608 | u32 tod_high; |
608 | int ret; | 609 | int ret; |
610 | struct channel_subsystem *css; | ||
609 | 611 | ||
610 | memset(css[nr], 0, sizeof(struct channel_subsystem)); | 612 | css = channel_subsystems[nr]; |
611 | css[nr]->pseudo_subchannel = | 613 | memset(css, 0, sizeof(struct channel_subsystem)); |
612 | kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL); | 614 | css->pseudo_subchannel = |
613 | if (!css[nr]->pseudo_subchannel) | 615 | kzalloc(sizeof(*css->pseudo_subchannel), GFP_KERNEL); |
616 | if (!css->pseudo_subchannel) | ||
614 | return -ENOMEM; | 617 | return -ENOMEM; |
615 | css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device; | 618 | css->pseudo_subchannel->dev.parent = &css->device; |
616 | css[nr]->pseudo_subchannel->dev.release = css_subchannel_release; | 619 | css->pseudo_subchannel->dev.release = css_subchannel_release; |
617 | sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct"); | 620 | sprintf(css->pseudo_subchannel->dev.bus_id, "defunct"); |
618 | ret = cio_create_sch_lock(css[nr]->pseudo_subchannel); | 621 | ret = cio_create_sch_lock(css->pseudo_subchannel); |
619 | if (ret) { | 622 | if (ret) { |
620 | kfree(css[nr]->pseudo_subchannel); | 623 | kfree(css->pseudo_subchannel); |
621 | return ret; | 624 | return ret; |
622 | } | 625 | } |
623 | mutex_init(&css[nr]->mutex); | 626 | mutex_init(&css->mutex); |
624 | css[nr]->valid = 1; | 627 | css->valid = 1; |
625 | css[nr]->cssid = nr; | 628 | css->cssid = nr; |
626 | sprintf(css[nr]->device.bus_id, "css%x", nr); | 629 | sprintf(css->device.bus_id, "css%x", nr); |
627 | css[nr]->device.release = channel_subsystem_release; | 630 | css->device.release = channel_subsystem_release; |
628 | tod_high = (u32) (get_clock() >> 32); | 631 | tod_high = (u32) (get_clock() >> 32); |
629 | css_generate_pgid(css[nr], tod_high); | 632 | css_generate_pgid(css, tod_high); |
630 | return 0; | 633 | return 0; |
631 | } | 634 | } |
632 | 635 | ||
636 | static int css_reboot_event(struct notifier_block *this, | ||
637 | unsigned long event, | ||
638 | void *ptr) | ||
639 | { | ||
640 | int ret, i; | ||
641 | |||
642 | ret = NOTIFY_DONE; | ||
643 | for (i = 0; i <= __MAX_CSSID; i++) { | ||
644 | struct channel_subsystem *css; | ||
645 | |||
646 | css = channel_subsystems[i]; | ||
647 | if (css->cm_enabled) | ||
648 | if (chsc_secm(css, 0)) | ||
649 | ret = NOTIFY_BAD; | ||
650 | } | ||
651 | |||
652 | return ret; | ||
653 | } | ||
654 | |||
655 | static struct notifier_block css_reboot_notifier = { | ||
656 | .notifier_call = css_reboot_event, | ||
657 | }; | ||
658 | |||
633 | /* | 659 | /* |
634 | * Now that the driver core is running, we can setup our channel subsystem. | 660 | * Now that the driver core is running, we can setup our channel subsystem. |
635 | * The struct subchannel's are created during probing (except for the | 661 | * The struct subchannel's are created during probing (except for the |
@@ -670,51 +696,63 @@ init_channel_subsystem (void) | |||
670 | } | 696 | } |
671 | /* Setup css structure. */ | 697 | /* Setup css structure. */ |
672 | for (i = 0; i <= __MAX_CSSID; i++) { | 698 | for (i = 0; i <= __MAX_CSSID; i++) { |
673 | css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); | 699 | struct channel_subsystem *css; |
674 | if (!css[i]) { | 700 | |
701 | css = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); | ||
702 | if (!css) { | ||
675 | ret = -ENOMEM; | 703 | ret = -ENOMEM; |
676 | goto out_unregister; | 704 | goto out_unregister; |
677 | } | 705 | } |
706 | channel_subsystems[i] = css; | ||
678 | ret = setup_css(i); | 707 | ret = setup_css(i); |
679 | if (ret) | 708 | if (ret) |
680 | goto out_free; | 709 | goto out_free; |
681 | ret = device_register(&css[i]->device); | 710 | ret = device_register(&css->device); |
682 | if (ret) | 711 | if (ret) |
683 | goto out_free_all; | 712 | goto out_free_all; |
684 | if (css_characteristics_avail && | 713 | if (css_characteristics_avail && |
685 | css_chsc_characteristics.secm) { | 714 | css_chsc_characteristics.secm) { |
686 | ret = device_create_file(&css[i]->device, | 715 | ret = device_create_file(&css->device, |
687 | &dev_attr_cm_enable); | 716 | &dev_attr_cm_enable); |
688 | if (ret) | 717 | if (ret) |
689 | goto out_device; | 718 | goto out_device; |
690 | } | 719 | } |
691 | ret = device_register(&css[i]->pseudo_subchannel->dev); | 720 | ret = device_register(&css->pseudo_subchannel->dev); |
692 | if (ret) | 721 | if (ret) |
693 | goto out_file; | 722 | goto out_file; |
694 | } | 723 | } |
724 | ret = register_reboot_notifier(&css_reboot_notifier); | ||
725 | if (ret) | ||
726 | goto out_pseudo; | ||
695 | css_init_done = 1; | 727 | css_init_done = 1; |
696 | 728 | ||
697 | ctl_set_bit(6, 28); | 729 | ctl_set_bit(6, 28); |
698 | 730 | ||
699 | for_each_subchannel(__init_channel_subsystem, NULL); | 731 | for_each_subchannel(__init_channel_subsystem, NULL); |
700 | return 0; | 732 | return 0; |
733 | out_pseudo: | ||
734 | device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev); | ||
701 | out_file: | 735 | out_file: |
702 | device_remove_file(&css[i]->device, &dev_attr_cm_enable); | 736 | device_remove_file(&channel_subsystems[i]->device, |
737 | &dev_attr_cm_enable); | ||
703 | out_device: | 738 | out_device: |
704 | device_unregister(&css[i]->device); | 739 | device_unregister(&channel_subsystems[i]->device); |
705 | out_free_all: | 740 | out_free_all: |
706 | kfree(css[i]->pseudo_subchannel->lock); | 741 | kfree(channel_subsystems[i]->pseudo_subchannel->lock); |
707 | kfree(css[i]->pseudo_subchannel); | 742 | kfree(channel_subsystems[i]->pseudo_subchannel); |
708 | out_free: | 743 | out_free: |
709 | kfree(css[i]); | 744 | kfree(channel_subsystems[i]); |
710 | out_unregister: | 745 | out_unregister: |
711 | while (i > 0) { | 746 | while (i > 0) { |
747 | struct channel_subsystem *css; | ||
748 | |||
712 | i--; | 749 | i--; |
713 | device_unregister(&css[i]->pseudo_subchannel->dev); | 750 | css = channel_subsystems[i]; |
751 | device_unregister(&css->pseudo_subchannel->dev); | ||
714 | if (css_characteristics_avail && css_chsc_characteristics.secm) | 752 | if (css_characteristics_avail && css_chsc_characteristics.secm) |
715 | device_remove_file(&css[i]->device, | 753 | device_remove_file(&css->device, |
716 | &dev_attr_cm_enable); | 754 | &dev_attr_cm_enable); |
717 | device_unregister(&css[i]->device); | 755 | device_unregister(&css->device); |
718 | } | 756 | } |
719 | out_bus: | 757 | out_bus: |
720 | bus_unregister(&css_bus_type); | 758 | bus_unregister(&css_bus_type); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 5d65e83ca66e..81215ef32435 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -167,7 +167,7 @@ struct channel_subsystem { | |||
167 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) | 167 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) |
168 | 168 | ||
169 | extern struct bus_type css_bus_type; | 169 | extern struct bus_type css_bus_type; |
170 | extern struct channel_subsystem *css[]; | 170 | extern struct channel_subsystem *channel_subsystems[]; |
171 | 171 | ||
172 | /* Some helper functions for disconnected state. */ | 172 | /* Some helper functions for disconnected state. */ |
173 | int device_is_disconnected(struct subchannel *); | 173 | int device_is_disconnected(struct subchannel *); |
@@ -191,6 +191,5 @@ int sch_is_pseudo_sch(struct subchannel *); | |||
191 | 191 | ||
192 | extern struct workqueue_struct *slow_path_wq; | 192 | extern struct workqueue_struct *slow_path_wq; |
193 | 193 | ||
194 | int subchannel_add_files (struct device *); | ||
195 | extern struct attribute_group *subch_attr_groups[]; | 194 | extern struct attribute_group *subch_attr_groups[]; |
196 | #endif | 195 | #endif |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 606bb53e9fae..7ee57f084a89 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/ccwdev.h> | 21 | #include <asm/ccwdev.h> |
22 | #include <asm/cio.h> | 22 | #include <asm/cio.h> |
23 | #include <asm/param.h> /* HZ */ | 23 | #include <asm/param.h> /* HZ */ |
24 | #include <asm/cmb.h> | ||
24 | 25 | ||
25 | #include "cio.h" | 26 | #include "cio.h" |
26 | #include "cio_debug.h" | 27 | #include "cio_debug.h" |
@@ -346,8 +347,18 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
346 | cdev->private->dev_id.devno); | 347 | cdev->private->dev_id.devno); |
347 | } | 348 | } |
348 | 349 | ||
349 | int | 350 | /** |
350 | ccw_device_set_offline(struct ccw_device *cdev) | 351 | * ccw_device_set_offline() - disable a ccw device for I/O |
352 | * @cdev: target ccw device | ||
353 | * | ||
354 | * This function calls the driver's set_offline() function for @cdev, if | ||
355 | * given, and then disables @cdev. | ||
356 | * Returns: | ||
357 | * %0 on success and a negative error value on failure. | ||
358 | * Context: | ||
359 | * enabled, ccw device lock not held | ||
360 | */ | ||
361 | int ccw_device_set_offline(struct ccw_device *cdev) | ||
351 | { | 362 | { |
352 | int ret; | 363 | int ret; |
353 | 364 | ||
@@ -385,8 +396,19 @@ ccw_device_set_offline(struct ccw_device *cdev) | |||
385 | return ret; | 396 | return ret; |
386 | } | 397 | } |
387 | 398 | ||
388 | int | 399 | /** |
389 | ccw_device_set_online(struct ccw_device *cdev) | 400 | * ccw_device_set_online() - enable a ccw device for I/O |
401 | * @cdev: target ccw device | ||
402 | * | ||
403 | * This function first enables @cdev and then calls the driver's set_online() | ||
404 | * function for @cdev, if given. If set_online() returns an error, @cdev is | ||
405 | * disabled again. | ||
406 | * Returns: | ||
407 | * %0 on success and a negative error value on failure. | ||
408 | * Context: | ||
409 | * enabled, ccw device lock not held | ||
410 | */ | ||
411 | int ccw_device_set_online(struct ccw_device *cdev) | ||
390 | { | 412 | { |
391 | int ret; | 413 | int ret; |
392 | 414 | ||
@@ -936,8 +958,7 @@ out: | |||
936 | wake_up(&ccw_device_init_wq); | 958 | wake_up(&ccw_device_init_wq); |
937 | } | 959 | } |
938 | 960 | ||
939 | void | 961 | static void ccw_device_call_sch_unregister(struct work_struct *work) |
940 | ccw_device_call_sch_unregister(struct work_struct *work) | ||
941 | { | 962 | { |
942 | struct ccw_device_private *priv; | 963 | struct ccw_device_private *priv; |
943 | struct ccw_device *cdev; | 964 | struct ccw_device *cdev; |
@@ -1090,6 +1111,7 @@ io_subchannel_probe (struct subchannel *sch) | |||
1090 | * device, e.g. the console. | 1111 | * device, e.g. the console. |
1091 | */ | 1112 | */ |
1092 | cdev = sch->dev.driver_data; | 1113 | cdev = sch->dev.driver_data; |
1114 | cdev->dev.groups = ccwdev_attr_groups; | ||
1093 | device_initialize(&cdev->dev); | 1115 | device_initialize(&cdev->dev); |
1094 | ccw_device_register(cdev); | 1116 | ccw_device_register(cdev); |
1095 | /* | 1117 | /* |
@@ -1315,8 +1337,19 @@ __ccwdev_check_busid(struct device *dev, void *id) | |||
1315 | } | 1337 | } |
1316 | 1338 | ||
1317 | 1339 | ||
1318 | struct ccw_device * | 1340 | /** |
1319 | get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) | 1341 | * get_ccwdev_by_busid() - obtain device from a bus id |
1342 | * @cdrv: driver the device is owned by | ||
1343 | * @bus_id: bus id of the device to be searched | ||
1344 | * | ||
1345 | * This function searches all devices owned by @cdrv for a device with a bus | ||
1346 | * id matching @bus_id. | ||
1347 | * Returns: | ||
1348 | * If a match is found, its reference count of the found device is increased | ||
1349 | * and it is returned; else %NULL is returned. | ||
1350 | */ | ||
1351 | struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | ||
1352 | const char *bus_id) | ||
1320 | { | 1353 | { |
1321 | struct device *dev; | 1354 | struct device *dev; |
1322 | struct device_driver *drv; | 1355 | struct device_driver *drv; |
@@ -1390,16 +1423,34 @@ ccw_device_remove (struct device *dev) | |||
1390 | return 0; | 1423 | return 0; |
1391 | } | 1424 | } |
1392 | 1425 | ||
1426 | static void ccw_device_shutdown(struct device *dev) | ||
1427 | { | ||
1428 | struct ccw_device *cdev; | ||
1429 | |||
1430 | cdev = to_ccwdev(dev); | ||
1431 | if (cdev->drv && cdev->drv->shutdown) | ||
1432 | cdev->drv->shutdown(cdev); | ||
1433 | disable_cmf(cdev); | ||
1434 | } | ||
1435 | |||
1393 | struct bus_type ccw_bus_type = { | 1436 | struct bus_type ccw_bus_type = { |
1394 | .name = "ccw", | 1437 | .name = "ccw", |
1395 | .match = ccw_bus_match, | 1438 | .match = ccw_bus_match, |
1396 | .uevent = ccw_uevent, | 1439 | .uevent = ccw_uevent, |
1397 | .probe = ccw_device_probe, | 1440 | .probe = ccw_device_probe, |
1398 | .remove = ccw_device_remove, | 1441 | .remove = ccw_device_remove, |
1442 | .shutdown = ccw_device_shutdown, | ||
1399 | }; | 1443 | }; |
1400 | 1444 | ||
1401 | int | 1445 | /** |
1402 | ccw_driver_register (struct ccw_driver *cdriver) | 1446 | * ccw_driver_register() - register a ccw driver |
1447 | * @cdriver: driver to be registered | ||
1448 | * | ||
1449 | * This function is mainly a wrapper around driver_register(). | ||
1450 | * Returns: | ||
1451 | * %0 on success and a negative error value on failure. | ||
1452 | */ | ||
1453 | int ccw_driver_register(struct ccw_driver *cdriver) | ||
1403 | { | 1454 | { |
1404 | struct device_driver *drv = &cdriver->driver; | 1455 | struct device_driver *drv = &cdriver->driver; |
1405 | 1456 | ||
@@ -1409,8 +1460,13 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
1409 | return driver_register(drv); | 1460 | return driver_register(drv); |
1410 | } | 1461 | } |
1411 | 1462 | ||
1412 | void | 1463 | /** |
1413 | ccw_driver_unregister (struct ccw_driver *cdriver) | 1464 | * ccw_driver_unregister() - deregister a ccw driver |
1465 | * @cdriver: driver to be deregistered | ||
1466 | * | ||
1467 | * This function is mainly a wrapper around driver_unregister(). | ||
1468 | */ | ||
1469 | void ccw_driver_unregister(struct ccw_driver *cdriver) | ||
1414 | { | 1470 | { |
1415 | driver_unregister(&cdriver->driver); | 1471 | driver_unregister(&cdriver->driver); |
1416 | } | 1472 | } |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index b66338b76579..0d4089600439 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -80,7 +80,6 @@ void io_subchannel_recog_done(struct ccw_device *cdev); | |||
80 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 80 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
81 | 81 | ||
82 | void ccw_device_do_unreg_rereg(struct work_struct *); | 82 | void ccw_device_do_unreg_rereg(struct work_struct *); |
83 | void ccw_device_call_sch_unregister(struct work_struct *); | ||
84 | void ccw_device_move_to_orphanage(struct work_struct *); | 83 | void ccw_device_move_to_orphanage(struct work_struct *); |
85 | int ccw_device_is_orphan(struct ccw_device *); | 84 | int ccw_device_is_orphan(struct ccw_device *); |
86 | 85 | ||
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8633dc537695..8867443b8060 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -446,7 +446,8 @@ static void __ccw_device_get_common_pgid(struct ccw_device *cdev) | |||
446 | if (cdev->private->pgid[last].inf.ps.state1 == | 446 | if (cdev->private->pgid[last].inf.ps.state1 == |
447 | SNID_STATE1_RESET) | 447 | SNID_STATE1_RESET) |
448 | /* No previous pgid found */ | 448 | /* No previous pgid found */ |
449 | memcpy(&cdev->private->pgid[0], &css[0]->global_pgid, | 449 | memcpy(&cdev->private->pgid[0], |
450 | &channel_subsystems[0]->global_pgid, | ||
450 | sizeof(struct pgid)); | 451 | sizeof(struct pgid)); |
451 | else | 452 | else |
452 | /* Use existing pgid */ | 453 | /* Use existing pgid */ |
@@ -543,51 +544,6 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
543 | } | 544 | } |
544 | 545 | ||
545 | 546 | ||
546 | static void | ||
547 | ccw_device_nopath_notify(struct work_struct *work) | ||
548 | { | ||
549 | struct ccw_device_private *priv; | ||
550 | struct ccw_device *cdev; | ||
551 | struct subchannel *sch; | ||
552 | int ret; | ||
553 | unsigned long flags; | ||
554 | |||
555 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
556 | cdev = priv->cdev; | ||
557 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
558 | sch = to_subchannel(cdev->dev.parent); | ||
559 | /* Extra sanity. */ | ||
560 | if (sch->lpm) | ||
561 | goto out_unlock; | ||
562 | if (sch->driver && sch->driver->notify) { | ||
563 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
564 | ret = sch->driver->notify(&sch->dev, CIO_NO_PATH); | ||
565 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
566 | } else | ||
567 | ret = 0; | ||
568 | if (!ret) { | ||
569 | if (get_device(&sch->dev)) { | ||
570 | /* Driver doesn't want to keep device. */ | ||
571 | cio_disable_subchannel(sch); | ||
572 | if (get_device(&cdev->dev)) { | ||
573 | PREPARE_WORK(&cdev->private->kick_work, | ||
574 | ccw_device_call_sch_unregister); | ||
575 | queue_work(ccw_device_work, | ||
576 | &cdev->private->kick_work); | ||
577 | } else | ||
578 | put_device(&sch->dev); | ||
579 | } | ||
580 | } else { | ||
581 | cio_disable_subchannel(sch); | ||
582 | ccw_device_set_timeout(cdev, 0); | ||
583 | cdev->private->flags.fake_irb = 0; | ||
584 | cdev->private->state = DEV_STATE_DISCONNECTED; | ||
585 | wake_up(&cdev->private->wait_q); | ||
586 | } | ||
587 | out_unlock: | ||
588 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
589 | } | ||
590 | |||
591 | void | 547 | void |
592 | ccw_device_verify_done(struct ccw_device *cdev, int err) | 548 | ccw_device_verify_done(struct ccw_device *cdev, int err) |
593 | { | 549 | { |
@@ -631,12 +587,9 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) | |||
631 | default: | 587 | default: |
632 | /* Reset oper notify indication after verify error. */ | 588 | /* Reset oper notify indication after verify error. */ |
633 | cdev->private->flags.donotify = 0; | 589 | cdev->private->flags.donotify = 0; |
634 | if (cdev->online) { | 590 | if (cdev->online) |
635 | PREPARE_WORK(&cdev->private->kick_work, | 591 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
636 | ccw_device_nopath_notify); | 592 | else |
637 | queue_work(ccw_device_notify_work, | ||
638 | &cdev->private->kick_work); | ||
639 | } else | ||
640 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | 593 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); |
641 | break; | 594 | break; |
642 | } | 595 | } |
@@ -690,11 +643,7 @@ ccw_device_disband_done(struct ccw_device *cdev, int err) | |||
690 | break; | 643 | break; |
691 | default: | 644 | default: |
692 | cdev->private->flags.donotify = 0; | 645 | cdev->private->flags.donotify = 0; |
693 | if (get_device(&cdev->dev)) { | 646 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
694 | PREPARE_WORK(&cdev->private->kick_work, | ||
695 | ccw_device_call_sch_unregister); | ||
696 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
697 | } | ||
698 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | 647 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); |
699 | break; | 648 | break; |
700 | } | 649 | } |
@@ -765,59 +714,16 @@ ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event) | |||
765 | } | 714 | } |
766 | 715 | ||
767 | /* | 716 | /* |
768 | * Handle not operational event while offline. | 717 | * Handle not operational event in non-special state. |
769 | */ | 718 | */ |
770 | static void | 719 | static void ccw_device_generic_notoper(struct ccw_device *cdev, |
771 | ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event) | 720 | enum dev_event dev_event) |
772 | { | 721 | { |
773 | struct subchannel *sch; | 722 | struct subchannel *sch; |
774 | 723 | ||
775 | cdev->private->state = DEV_STATE_NOT_OPER; | 724 | cdev->private->state = DEV_STATE_NOT_OPER; |
776 | sch = to_subchannel(cdev->dev.parent); | 725 | sch = to_subchannel(cdev->dev.parent); |
777 | if (get_device(&cdev->dev)) { | 726 | css_schedule_eval(sch->schid); |
778 | PREPARE_WORK(&cdev->private->kick_work, | ||
779 | ccw_device_call_sch_unregister); | ||
780 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
781 | } | ||
782 | wake_up(&cdev->private->wait_q); | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Handle not operational event while online. | ||
787 | */ | ||
788 | static void | ||
789 | ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event) | ||
790 | { | ||
791 | struct subchannel *sch; | ||
792 | int ret; | ||
793 | |||
794 | sch = to_subchannel(cdev->dev.parent); | ||
795 | if (sch->driver->notify) { | ||
796 | spin_unlock_irq(cdev->ccwlock); | ||
797 | ret = sch->driver->notify(&sch->dev, | ||
798 | sch->lpm ? CIO_GONE : CIO_NO_PATH); | ||
799 | spin_lock_irq(cdev->ccwlock); | ||
800 | } else | ||
801 | ret = 0; | ||
802 | if (ret) { | ||
803 | ccw_device_set_timeout(cdev, 0); | ||
804 | cdev->private->flags.fake_irb = 0; | ||
805 | cdev->private->state = DEV_STATE_DISCONNECTED; | ||
806 | wake_up(&cdev->private->wait_q); | ||
807 | return; | ||
808 | } | ||
809 | cdev->private->state = DEV_STATE_NOT_OPER; | ||
810 | cio_disable_subchannel(sch); | ||
811 | if (sch->schib.scsw.actl != 0) { | ||
812 | // FIXME: not-oper indication to device driver ? | ||
813 | ccw_device_call_handler(cdev); | ||
814 | } | ||
815 | if (get_device(&cdev->dev)) { | ||
816 | PREPARE_WORK(&cdev->private->kick_work, | ||
817 | ccw_device_call_sch_unregister); | ||
818 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
819 | } | ||
820 | wake_up(&cdev->private->wait_q); | ||
821 | } | 727 | } |
822 | 728 | ||
823 | /* | 729 | /* |
@@ -915,18 +821,9 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
915 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; | 821 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; |
916 | return; | 822 | return; |
917 | } | 823 | } |
918 | if (ret == -ENODEV) { | 824 | if (ret == -ENODEV) |
919 | struct subchannel *sch; | 825 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
920 | 826 | else if (cdev->handler) | |
921 | sch = to_subchannel(cdev->dev.parent); | ||
922 | if (!sch->lpm) { | ||
923 | PREPARE_WORK(&cdev->private->kick_work, | ||
924 | ccw_device_nopath_notify); | ||
925 | queue_work(ccw_device_notify_work, | ||
926 | &cdev->private->kick_work); | ||
927 | } else | ||
928 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
929 | } else if (cdev->handler) | ||
930 | cdev->handler(cdev, cdev->private->intparm, | 827 | cdev->handler(cdev, cdev->private->intparm, |
931 | ERR_PTR(-ETIMEDOUT)); | 828 | ERR_PTR(-ETIMEDOUT)); |
932 | } | 829 | } |
@@ -1233,7 +1130,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1233 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1130 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1234 | }, | 1131 | }, |
1235 | [DEV_STATE_SENSE_PGID] = { | 1132 | [DEV_STATE_SENSE_PGID] = { |
1236 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1133 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1237 | [DEV_EVENT_INTERRUPT] = ccw_device_sense_pgid_irq, | 1134 | [DEV_EVENT_INTERRUPT] = ccw_device_sense_pgid_irq, |
1238 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1135 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1239 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1136 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
@@ -1245,50 +1142,50 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1245 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1142 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1246 | }, | 1143 | }, |
1247 | [DEV_STATE_OFFLINE] = { | 1144 | [DEV_STATE_OFFLINE] = { |
1248 | [DEV_EVENT_NOTOPER] = ccw_device_offline_notoper, | 1145 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1249 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, | 1146 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, |
1250 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1147 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1251 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1148 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1252 | }, | 1149 | }, |
1253 | [DEV_STATE_VERIFY] = { | 1150 | [DEV_STATE_VERIFY] = { |
1254 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1151 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1255 | [DEV_EVENT_INTERRUPT] = ccw_device_verify_irq, | 1152 | [DEV_EVENT_INTERRUPT] = ccw_device_verify_irq, |
1256 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1153 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1257 | [DEV_EVENT_VERIFY] = ccw_device_delay_verify, | 1154 | [DEV_EVENT_VERIFY] = ccw_device_delay_verify, |
1258 | }, | 1155 | }, |
1259 | [DEV_STATE_ONLINE] = { | 1156 | [DEV_STATE_ONLINE] = { |
1260 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1157 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1261 | [DEV_EVENT_INTERRUPT] = ccw_device_irq, | 1158 | [DEV_EVENT_INTERRUPT] = ccw_device_irq, |
1262 | [DEV_EVENT_TIMEOUT] = ccw_device_online_timeout, | 1159 | [DEV_EVENT_TIMEOUT] = ccw_device_online_timeout, |
1263 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, | 1160 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, |
1264 | }, | 1161 | }, |
1265 | [DEV_STATE_W4SENSE] = { | 1162 | [DEV_STATE_W4SENSE] = { |
1266 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1163 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1267 | [DEV_EVENT_INTERRUPT] = ccw_device_w4sense, | 1164 | [DEV_EVENT_INTERRUPT] = ccw_device_w4sense, |
1268 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1165 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1269 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, | 1166 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, |
1270 | }, | 1167 | }, |
1271 | [DEV_STATE_DISBAND_PGID] = { | 1168 | [DEV_STATE_DISBAND_PGID] = { |
1272 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1169 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1273 | [DEV_EVENT_INTERRUPT] = ccw_device_disband_irq, | 1170 | [DEV_EVENT_INTERRUPT] = ccw_device_disband_irq, |
1274 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1171 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1275 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1172 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1276 | }, | 1173 | }, |
1277 | [DEV_STATE_BOXED] = { | 1174 | [DEV_STATE_BOXED] = { |
1278 | [DEV_EVENT_NOTOPER] = ccw_device_offline_notoper, | 1175 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1279 | [DEV_EVENT_INTERRUPT] = ccw_device_stlck_done, | 1176 | [DEV_EVENT_INTERRUPT] = ccw_device_stlck_done, |
1280 | [DEV_EVENT_TIMEOUT] = ccw_device_stlck_done, | 1177 | [DEV_EVENT_TIMEOUT] = ccw_device_stlck_done, |
1281 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1178 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1282 | }, | 1179 | }, |
1283 | /* states to wait for i/o completion before doing something */ | 1180 | /* states to wait for i/o completion before doing something */ |
1284 | [DEV_STATE_CLEAR_VERIFY] = { | 1181 | [DEV_STATE_CLEAR_VERIFY] = { |
1285 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1182 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1286 | [DEV_EVENT_INTERRUPT] = ccw_device_clear_verify, | 1183 | [DEV_EVENT_INTERRUPT] = ccw_device_clear_verify, |
1287 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1184 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1288 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1185 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1289 | }, | 1186 | }, |
1290 | [DEV_STATE_TIMEOUT_KILL] = { | 1187 | [DEV_STATE_TIMEOUT_KILL] = { |
1291 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1188 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1292 | [DEV_EVENT_INTERRUPT] = ccw_device_killing_irq, | 1189 | [DEV_EVENT_INTERRUPT] = ccw_device_killing_irq, |
1293 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, | 1190 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, |
1294 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME | 1191 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 14eba854b155..7fd2dadc3297 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -25,6 +25,16 @@ | |||
25 | #include "device.h" | 25 | #include "device.h" |
26 | #include "chp.h" | 26 | #include "chp.h" |
27 | 27 | ||
28 | /** | ||
29 | * ccw_device_set_options_mask() - set some options and unset the rest | ||
30 | * @cdev: device for which the options are to be set | ||
31 | * @flags: options to be set | ||
32 | * | ||
33 | * All flags specified in @flags are set, all flags not specified in @flags | ||
34 | * are cleared. | ||
35 | * Returns: | ||
36 | * %0 on success, -%EINVAL on an invalid flag combination. | ||
37 | */ | ||
28 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | 38 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) |
29 | { | 39 | { |
30 | /* | 40 | /* |
@@ -40,6 +50,15 @@ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | |||
40 | return 0; | 50 | return 0; |
41 | } | 51 | } |
42 | 52 | ||
53 | /** | ||
54 | * ccw_device_set_options() - set some options | ||
55 | * @cdev: device for which the options are to be set | ||
56 | * @flags: options to be set | ||
57 | * | ||
58 | * All flags specified in @flags are set, the remainder is left untouched. | ||
59 | * Returns: | ||
60 | * %0 on success, -%EINVAL if an invalid flag combination would ensue. | ||
61 | */ | ||
43 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | 62 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) |
44 | { | 63 | { |
45 | /* | 64 | /* |
@@ -59,6 +78,13 @@ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | |||
59 | return 0; | 78 | return 0; |
60 | } | 79 | } |
61 | 80 | ||
81 | /** | ||
82 | * ccw_device_clear_options() - clear some options | ||
83 | * @cdev: device for which the options are to be cleared | ||
84 | * @flags: options to be cleared | ||
85 | * | ||
86 | * All flags specified in @flags are cleared, the remainder is left untouched. | ||
87 | */ | ||
62 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | 88 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) |
63 | { | 89 | { |
64 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; | 90 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; |
@@ -67,8 +93,22 @@ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | |||
67 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; | 93 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; |
68 | } | 94 | } |
69 | 95 | ||
70 | int | 96 | /** |
71 | ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | 97 | * ccw_device_clear() - terminate I/O request processing |
98 | * @cdev: target ccw device | ||
99 | * @intparm: interruption parameter; value is only used if no I/O is | ||
100 | * outstanding, otherwise the intparm associated with the I/O request | ||
101 | * is returned | ||
102 | * | ||
103 | * ccw_device_clear() calls csch on @cdev's subchannel. | ||
104 | * Returns: | ||
105 | * %0 on success, | ||
106 | * -%ENODEV on device not operational, | ||
107 | * -%EINVAL on invalid device state. | ||
108 | * Context: | ||
109 | * Interrupts disabled, ccw device lock held | ||
110 | */ | ||
111 | int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | ||
72 | { | 112 | { |
73 | struct subchannel *sch; | 113 | struct subchannel *sch; |
74 | int ret; | 114 | int ret; |
@@ -89,10 +129,33 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | |||
89 | return ret; | 129 | return ret; |
90 | } | 130 | } |
91 | 131 | ||
92 | int | 132 | /** |
93 | ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | 133 | * ccw_device_start_key() - start a s390 channel program with key |
94 | unsigned long intparm, __u8 lpm, __u8 key, | 134 | * @cdev: target ccw device |
95 | unsigned long flags) | 135 | * @cpa: logical start address of channel program |
136 | * @intparm: user specific interruption parameter; will be presented back to | ||
137 | * @cdev's interrupt handler. Allows a device driver to associate | ||
138 | * the interrupt with a particular I/O request. | ||
139 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
140 | * value of 0 will make cio use the opm. | ||
141 | * @key: storage key to be used for the I/O | ||
142 | * @flags: additional flags; defines the action to be performed for I/O | ||
143 | * processing. | ||
144 | * | ||
145 | * Start a S/390 channel program. When the interrupt arrives, the | ||
146 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
147 | * or sense required) or never (no IRQ handler registered). | ||
148 | * Returns: | ||
149 | * %0, if the operation was successful; | ||
150 | * -%EBUSY, if the device is busy, or status pending; | ||
151 | * -%EACCES, if no path specified in @lpm is operational; | ||
152 | * -%ENODEV, if the device is not operational. | ||
153 | * Context: | ||
154 | * Interrupts disabled, ccw device lock held | ||
155 | */ | ||
156 | int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
157 | unsigned long intparm, __u8 lpm, __u8 key, | ||
158 | unsigned long flags) | ||
96 | { | 159 | { |
97 | struct subchannel *sch; | 160 | struct subchannel *sch; |
98 | int ret; | 161 | int ret; |
@@ -135,11 +198,38 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
135 | return ret; | 198 | return ret; |
136 | } | 199 | } |
137 | 200 | ||
138 | 201 | /** | |
139 | int | 202 | * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key |
140 | ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | 203 | * @cdev: target ccw device |
141 | unsigned long intparm, __u8 lpm, __u8 key, | 204 | * @cpa: logical start address of channel program |
142 | unsigned long flags, int expires) | 205 | * @intparm: user specific interruption parameter; will be presented back to |
206 | * @cdev's interrupt handler. Allows a device driver to associate | ||
207 | * the interrupt with a particular I/O request. | ||
208 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
209 | * value of 0 will make cio use the opm. | ||
210 | * @key: storage key to be used for the I/O | ||
211 | * @flags: additional flags; defines the action to be performed for I/O | ||
212 | * processing. | ||
213 | * @expires: timeout value in jiffies | ||
214 | * | ||
215 | * Start a S/390 channel program. When the interrupt arrives, the | ||
216 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
217 | * or sense required) or never (no IRQ handler registered). | ||
218 | * This function notifies the device driver if the channel program has not | ||
219 | * completed during the time specified by @expires. If a timeout occurs, the | ||
220 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
221 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
222 | * Returns: | ||
223 | * %0, if the operation was successful; | ||
224 | * -%EBUSY, if the device is busy, or status pending; | ||
225 | * -%EACCES, if no path specified in @lpm is operational; | ||
226 | * -%ENODEV, if the device is not operational. | ||
227 | * Context: | ||
228 | * Interrupts disabled, ccw device lock held | ||
229 | */ | ||
230 | int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
231 | unsigned long intparm, __u8 lpm, __u8 key, | ||
232 | unsigned long flags, int expires) | ||
143 | { | 233 | { |
144 | int ret; | 234 | int ret; |
145 | 235 | ||
@@ -152,18 +242,67 @@ ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
152 | return ret; | 242 | return ret; |
153 | } | 243 | } |
154 | 244 | ||
155 | int | 245 | /** |
156 | ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | 246 | * ccw_device_start() - start a s390 channel program |
157 | unsigned long intparm, __u8 lpm, unsigned long flags) | 247 | * @cdev: target ccw device |
248 | * @cpa: logical start address of channel program | ||
249 | * @intparm: user specific interruption parameter; will be presented back to | ||
250 | * @cdev's interrupt handler. Allows a device driver to associate | ||
251 | * the interrupt with a particular I/O request. | ||
252 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
253 | * value of 0 will make cio use the opm. | ||
254 | * @flags: additional flags; defines the action to be performed for I/O | ||
255 | * processing. | ||
256 | * | ||
257 | * Start a S/390 channel program. When the interrupt arrives, the | ||
258 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
259 | * or sense required) or never (no IRQ handler registered). | ||
260 | * Returns: | ||
261 | * %0, if the operation was successful; | ||
262 | * -%EBUSY, if the device is busy, or status pending; | ||
263 | * -%EACCES, if no path specified in @lpm is operational; | ||
264 | * -%ENODEV, if the device is not operational. | ||
265 | * Context: | ||
266 | * Interrupts disabled, ccw device lock held | ||
267 | */ | ||
268 | int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | ||
269 | unsigned long intparm, __u8 lpm, unsigned long flags) | ||
158 | { | 270 | { |
159 | return ccw_device_start_key(cdev, cpa, intparm, lpm, | 271 | return ccw_device_start_key(cdev, cpa, intparm, lpm, |
160 | PAGE_DEFAULT_KEY, flags); | 272 | PAGE_DEFAULT_KEY, flags); |
161 | } | 273 | } |
162 | 274 | ||
163 | int | 275 | /** |
164 | ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | 276 | * ccw_device_start_timeout() - start a s390 channel program with timeout |
165 | unsigned long intparm, __u8 lpm, unsigned long flags, | 277 | * @cdev: target ccw device |
166 | int expires) | 278 | * @cpa: logical start address of channel program |
279 | * @intparm: user specific interruption parameter; will be presented back to | ||
280 | * @cdev's interrupt handler. Allows a device driver to associate | ||
281 | * the interrupt with a particular I/O request. | ||
282 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
283 | * value of 0 will make cio use the opm. | ||
284 | * @flags: additional flags; defines the action to be performed for I/O | ||
285 | * processing. | ||
286 | * @expires: timeout value in jiffies | ||
287 | * | ||
288 | * Start a S/390 channel program. When the interrupt arrives, the | ||
289 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
290 | * or sense required) or never (no IRQ handler registered). | ||
291 | * This function notifies the device driver if the channel program has not | ||
292 | * completed during the time specified by @expires. If a timeout occurs, the | ||
293 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
294 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
295 | * Returns: | ||
296 | * %0, if the operation was successful; | ||
297 | * -%EBUSY, if the device is busy, or status pending; | ||
298 | * -%EACCES, if no path specified in @lpm is operational; | ||
299 | * -%ENODEV, if the device is not operational. | ||
300 | * Context: | ||
301 | * Interrupts disabled, ccw device lock held | ||
302 | */ | ||
303 | int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | ||
304 | unsigned long intparm, __u8 lpm, | ||
305 | unsigned long flags, int expires) | ||
167 | { | 306 | { |
168 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, | 307 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, |
169 | PAGE_DEFAULT_KEY, flags, | 308 | PAGE_DEFAULT_KEY, flags, |
@@ -171,8 +310,23 @@ ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | |||
171 | } | 310 | } |
172 | 311 | ||
173 | 312 | ||
174 | int | 313 | /** |
175 | ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | 314 | * ccw_device_halt() - halt I/O request processing |
315 | * @cdev: target ccw device | ||
316 | * @intparm: interruption parameter; value is only used if no I/O is | ||
317 | * outstanding, otherwise the intparm associated with the I/O request | ||
318 | * is returned | ||
319 | * | ||
320 | * ccw_device_halt() calls hsch on @cdev's subchannel. | ||
321 | * Returns: | ||
322 | * %0 on success, | ||
323 | * -%ENODEV on device not operational, | ||
324 | * -%EINVAL on invalid device state, | ||
325 | * -%EBUSY on device busy or interrupt pending. | ||
326 | * Context: | ||
327 | * Interrupts disabled, ccw device lock held | ||
328 | */ | ||
329 | int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | ||
176 | { | 330 | { |
177 | struct subchannel *sch; | 331 | struct subchannel *sch; |
178 | int ret; | 332 | int ret; |
@@ -193,8 +347,20 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | |||
193 | return ret; | 347 | return ret; |
194 | } | 348 | } |
195 | 349 | ||
196 | int | 350 | /** |
197 | ccw_device_resume(struct ccw_device *cdev) | 351 | * ccw_device_resume() - resume channel program execution |
352 | * @cdev: target ccw device | ||
353 | * | ||
354 | * ccw_device_resume() calls rsch on @cdev's subchannel. | ||
355 | * Returns: | ||
356 | * %0 on success, | ||
357 | * -%ENODEV on device not operational, | ||
358 | * -%EINVAL on invalid device state, | ||
359 | * -%EBUSY on device busy or interrupt pending. | ||
360 | * Context: | ||
361 | * Interrupts disabled, ccw device lock held | ||
362 | */ | ||
363 | int ccw_device_resume(struct ccw_device *cdev) | ||
198 | { | 364 | { |
199 | struct subchannel *sch; | 365 | struct subchannel *sch; |
200 | 366 | ||
@@ -260,11 +426,21 @@ ccw_device_call_handler(struct ccw_device *cdev) | |||
260 | return 1; | 426 | return 1; |
261 | } | 427 | } |
262 | 428 | ||
263 | /* | 429 | /** |
264 | * Search for CIW command in extended sense data. | 430 | * ccw_device_get_ciw() - Search for CIW command in extended sense data. |
431 | * @cdev: ccw device to inspect | ||
432 | * @ct: command type to look for | ||
433 | * | ||
434 | * During SenseID, command information words (CIWs) describing special | ||
435 | * commands available to the device may have been stored in the extended | ||
436 | * sense data. This function searches for CIWs of a specified command | ||
437 | * type in the extended sense data. | ||
438 | * Returns: | ||
439 | * %NULL if no extended sense data has been stored or if no CIW of the | ||
440 | * specified command type could be found, | ||
441 | * else a pointer to the CIW of the specified command type. | ||
265 | */ | 442 | */ |
266 | struct ciw * | 443 | struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) |
267 | ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | ||
268 | { | 444 | { |
269 | int ciw_cnt; | 445 | int ciw_cnt; |
270 | 446 | ||
@@ -276,8 +452,14 @@ ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | |||
276 | return NULL; | 452 | return NULL; |
277 | } | 453 | } |
278 | 454 | ||
279 | __u8 | 455 | /** |
280 | ccw_device_get_path_mask(struct ccw_device *cdev) | 456 | * ccw_device_get_path_mask() - get currently available paths |
457 | * @cdev: ccw device to be queried | ||
458 | * Returns: | ||
459 | * %0 if no subchannel for the device is available, | ||
460 | * else the mask of currently available paths for the ccw device's subchannel. | ||
461 | */ | ||
462 | __u8 ccw_device_get_path_mask(struct ccw_device *cdev) | ||
281 | { | 463 | { |
282 | struct subchannel *sch; | 464 | struct subchannel *sch; |
283 | 465 | ||
@@ -357,8 +539,7 @@ out_unlock: | |||
357 | return ret; | 539 | return ret; |
358 | } | 540 | } |
359 | 541 | ||
360 | void * | 542 | void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) |
361 | ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) | ||
362 | { | 543 | { |
363 | struct subchannel *sch; | 544 | struct subchannel *sch; |
364 | struct chp_id chpid; | 545 | struct chp_id chpid; |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index d8d479876ec7..40a3208c7cf3 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -1024,9 +1024,9 @@ __qdio_outbound_processing(struct qdio_q *q) | |||
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static void | 1026 | static void |
1027 | qdio_outbound_processing(struct qdio_q *q) | 1027 | qdio_outbound_processing(unsigned long q) |
1028 | { | 1028 | { |
1029 | __qdio_outbound_processing(q); | 1029 | __qdio_outbound_processing((struct qdio_q *) q); |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | /************************* INBOUND ROUTINES *******************************/ | 1032 | /************************* INBOUND ROUTINES *******************************/ |
@@ -1449,9 +1449,10 @@ out: | |||
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | static void | 1451 | static void |
1452 | tiqdio_inbound_processing(struct qdio_q *q) | 1452 | tiqdio_inbound_processing(unsigned long q) |
1453 | { | 1453 | { |
1454 | __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); | 1454 | __tiqdio_inbound_processing((struct qdio_q *) q, |
1455 | atomic_read(&spare_indicator_usecount)); | ||
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | static void | 1458 | static void |
@@ -1494,9 +1495,9 @@ again: | |||
1494 | } | 1495 | } |
1495 | 1496 | ||
1496 | static void | 1497 | static void |
1497 | qdio_inbound_processing(struct qdio_q *q) | 1498 | qdio_inbound_processing(unsigned long q) |
1498 | { | 1499 | { |
1499 | __qdio_inbound_processing(q); | 1500 | __qdio_inbound_processing((struct qdio_q *) q); |
1500 | } | 1501 | } |
1501 | 1502 | ||
1502 | /************************* MAIN ROUTINES *******************************/ | 1503 | /************************* MAIN ROUTINES *******************************/ |
@@ -1760,12 +1761,15 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1760 | q->handler=input_handler; | 1761 | q->handler=input_handler; |
1761 | q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; | 1762 | q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; |
1762 | 1763 | ||
1763 | q->tasklet.data=(unsigned long)q; | ||
1764 | /* q->is_thinint_q isn't valid at this time, but | 1764 | /* q->is_thinint_q isn't valid at this time, but |
1765 | * irq_ptr->is_thinint_irq is */ | 1765 | * irq_ptr->is_thinint_irq is |
1766 | q->tasklet.func=(void(*)(unsigned long)) | 1766 | */ |
1767 | ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing: | 1767 | if (irq_ptr->is_thinint_irq) |
1768 | &qdio_inbound_processing); | 1768 | tasklet_init(&q->tasklet, tiqdio_inbound_processing, |
1769 | (unsigned long) q); | ||
1770 | else | ||
1771 | tasklet_init(&q->tasklet, qdio_inbound_processing, | ||
1772 | (unsigned long) q); | ||
1769 | 1773 | ||
1770 | /* actually this is not used for inbound queues. yet. */ | 1774 | /* actually this is not used for inbound queues. yet. */ |
1771 | atomic_set(&q->busy_siga_counter,0); | 1775 | atomic_set(&q->busy_siga_counter,0); |
@@ -1836,13 +1840,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1836 | q->last_move_ftc=0; | 1840 | q->last_move_ftc=0; |
1837 | q->handler=output_handler; | 1841 | q->handler=output_handler; |
1838 | 1842 | ||
1839 | q->tasklet.data=(unsigned long)q; | 1843 | tasklet_init(&q->tasklet, qdio_outbound_processing, |
1840 | q->tasklet.func=(void(*)(unsigned long)) | 1844 | (unsigned long) q); |
1841 | &qdio_outbound_processing; | 1845 | setup_timer(&q->timer, qdio_outbound_processing, |
1842 | q->timer.function=(void(*)(unsigned long)) | 1846 | (unsigned long) q); |
1843 | &qdio_outbound_processing; | ||
1844 | q->timer.data = (long)q; | ||
1845 | init_timer(&q->timer); | ||
1846 | 1847 | ||
1847 | atomic_set(&q->busy_siga_counter,0); | 1848 | atomic_set(&q->busy_siga_counter,0); |
1848 | q->timing.busy_start=0; | 1849 | q->timing.busy_start=0; |
@@ -3726,7 +3727,7 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count | |||
3726 | #endif /* CONFIG_64BIT */ | 3727 | #endif /* CONFIG_64BIT */ |
3727 | } | 3728 | } |
3728 | } else { | 3729 | } else { |
3729 | QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n"); | 3730 | QDIO_PRINT_ERR("QDIO performance_stats: write 0 or 1 to this file!\n"); |
3730 | return -EINVAL; | 3731 | return -EINVAL; |
3731 | } | 3732 | } |
3732 | return count; | 3733 | return count; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index e99713041591..67aaff3e668d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -1225,8 +1225,9 @@ static void ap_reset_domain(void) | |||
1225 | { | 1225 | { |
1226 | int i; | 1226 | int i; |
1227 | 1227 | ||
1228 | for (i = 0; i < AP_DEVICES; i++) | 1228 | if (ap_domain_index != -1) |
1229 | ap_reset_queue(AP_MKQID(i, ap_domain_index)); | 1229 | for (i = 0; i < AP_DEVICES; i++) |
1230 | ap_reset_queue(AP_MKQID(i, ap_domain_index)); | ||
1230 | } | 1231 | } |
1231 | 1232 | ||
1232 | static void ap_reset_all(void) | 1233 | static void ap_reset_all(void) |
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c index 2a9349ad68b7..44253fdd4136 100644 --- a/drivers/s390/crypto/zcrypt_mono.c +++ b/drivers/s390/crypto/zcrypt_mono.c | |||
@@ -45,7 +45,7 @@ | |||
45 | /** | 45 | /** |
46 | * The module initialization code. | 46 | * The module initialization code. |
47 | */ | 47 | */ |
48 | int __init zcrypt_init(void) | 48 | static int __init zcrypt_init(void) |
49 | { | 49 | { |
50 | int rc; | 50 | int rc; |
51 | 51 | ||
@@ -86,7 +86,7 @@ out: | |||
86 | /** | 86 | /** |
87 | * The module termination code. | 87 | * The module termination code. |
88 | */ | 88 | */ |
89 | void __exit zcrypt_exit(void) | 89 | static void __exit zcrypt_exit(void) |
90 | { | 90 | { |
91 | zcrypt_cex2a_exit(); | 91 | zcrypt_cex2a_exit(); |
92 | zcrypt_pcixcc_exit(); | 92 | zcrypt_pcixcc_exit(); |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 64948788d301..70b9ddc8cf9d 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -277,7 +277,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | |||
277 | }; | 277 | }; |
278 | struct { | 278 | struct { |
279 | struct type6_hdr hdr; | 279 | struct type6_hdr hdr; |
280 | struct ica_CPRBX cprbx; | 280 | struct CPRBX cprbx; |
281 | } __attribute__((packed)) *msg = ap_msg->message; | 281 | } __attribute__((packed)) *msg = ap_msg->message; |
282 | 282 | ||
283 | int rcblen = CEIL4(xcRB->request_control_blk_length); | 283 | int rcblen = CEIL4(xcRB->request_control_blk_length); |
@@ -432,14 +432,17 @@ static int convert_type86_ica(struct zcrypt_device *zdev, | |||
432 | } | 432 | } |
433 | if (service_rc == 8 && service_rs == 770) { | 433 | if (service_rc == 8 && service_rs == 770) { |
434 | PDEBUG("Invalid key length on PCIXCC/CEX2C\n"); | 434 | PDEBUG("Invalid key length on PCIXCC/CEX2C\n"); |
435 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | 435 | return -EINVAL; |
436 | return -EAGAIN; | ||
437 | } | 436 | } |
438 | if (service_rc == 8 && service_rs == 783) { | 437 | if (service_rc == 8 && service_rs == 783) { |
439 | PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n"); | 438 | PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n"); |
440 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | 439 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; |
441 | return -EAGAIN; | 440 | return -EAGAIN; |
442 | } | 441 | } |
442 | if (service_rc == 12 && service_rs == 769) { | ||
443 | PDEBUG("Invalid key on PCIXCC/CEX2C\n"); | ||
444 | return -EINVAL; | ||
445 | } | ||
443 | PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n", | 446 | PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n", |
444 | service_rc, service_rs); | 447 | service_rc, service_rs); |
445 | zdev->online = 0; | 448 | zdev->online = 0; |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.h b/drivers/s390/crypto/zcrypt_pcixcc.h index a78ff307fd19..8cb7d7a6973b 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.h +++ b/drivers/s390/crypto/zcrypt_pcixcc.h | |||
@@ -28,51 +28,6 @@ | |||
28 | #ifndef _ZCRYPT_PCIXCC_H_ | 28 | #ifndef _ZCRYPT_PCIXCC_H_ |
29 | #define _ZCRYPT_PCIXCC_H_ | 29 | #define _ZCRYPT_PCIXCC_H_ |
30 | 30 | ||
31 | /** | ||
32 | * CPRBX | ||
33 | * Note that all shorts and ints are big-endian. | ||
34 | * All pointer fields are 16 bytes long, and mean nothing. | ||
35 | * | ||
36 | * A request CPRB is followed by a request_parameter_block. | ||
37 | * | ||
38 | * The request (or reply) parameter block is organized thus: | ||
39 | * function code | ||
40 | * VUD block | ||
41 | * key block | ||
42 | */ | ||
43 | struct CPRBX { | ||
44 | unsigned short cprb_len; /* CPRB length 220 */ | ||
45 | unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ | ||
46 | unsigned char pad_000[3]; /* Alignment pad bytes */ | ||
47 | unsigned char func_id[2]; /* function id 0x5432 */ | ||
48 | unsigned char cprb_flags[4]; /* Flags */ | ||
49 | unsigned int req_parml; /* request parameter buffer len */ | ||
50 | unsigned int req_datal; /* request data buffer */ | ||
51 | unsigned int rpl_msgbl; /* reply message block length */ | ||
52 | unsigned int rpld_parml; /* replied parameter block len */ | ||
53 | unsigned int rpl_datal; /* reply data block len */ | ||
54 | unsigned int rpld_datal; /* replied data block len */ | ||
55 | unsigned int req_extbl; /* request extension block len */ | ||
56 | unsigned char pad_001[4]; /* reserved */ | ||
57 | unsigned int rpld_extbl; /* replied extension block len */ | ||
58 | unsigned char req_parmb[16]; /* request parm block 'address' */ | ||
59 | unsigned char req_datab[16]; /* request data block 'address' */ | ||
60 | unsigned char rpl_parmb[16]; /* reply parm block 'address' */ | ||
61 | unsigned char rpl_datab[16]; /* reply data block 'address' */ | ||
62 | unsigned char req_extb[16]; /* request extension block 'addr'*/ | ||
63 | unsigned char rpl_extb[16]; /* reply extension block 'addres'*/ | ||
64 | unsigned short ccp_rtcode; /* server return code */ | ||
65 | unsigned short ccp_rscode; /* server reason code */ | ||
66 | unsigned int mac_data_len; /* Mac Data Length */ | ||
67 | unsigned char logon_id[8]; /* Logon Identifier */ | ||
68 | unsigned char mac_value[8]; /* Mac Value */ | ||
69 | unsigned char mac_content_flgs;/* Mac content flag byte */ | ||
70 | unsigned char pad_002; /* Alignment */ | ||
71 | unsigned short domain; /* Domain */ | ||
72 | unsigned char pad_003[12]; /* Domain masks */ | ||
73 | unsigned char pad_004[36]; /* reserved */ | ||
74 | } __attribute__((packed)); | ||
75 | |||
76 | int zcrypt_pcixcc_init(void); | 31 | int zcrypt_pcixcc_init(void); |
77 | void zcrypt_pcixcc_exit(void); | 32 | void zcrypt_pcixcc_exit(void); |
78 | 33 | ||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 1c8f71a59855..c0d1c0eb3209 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -28,7 +28,7 @@ static void zfcp_ccw_remove(struct ccw_device *); | |||
28 | static int zfcp_ccw_set_online(struct ccw_device *); | 28 | static int zfcp_ccw_set_online(struct ccw_device *); |
29 | static int zfcp_ccw_set_offline(struct ccw_device *); | 29 | static int zfcp_ccw_set_offline(struct ccw_device *); |
30 | static int zfcp_ccw_notify(struct ccw_device *, int); | 30 | static int zfcp_ccw_notify(struct ccw_device *, int); |
31 | static void zfcp_ccw_shutdown(struct device *); | 31 | static void zfcp_ccw_shutdown(struct ccw_device *); |
32 | 32 | ||
33 | static struct ccw_device_id zfcp_ccw_device_id[] = { | 33 | static struct ccw_device_id zfcp_ccw_device_id[] = { |
34 | {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, | 34 | {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, |
@@ -51,9 +51,7 @@ static struct ccw_driver zfcp_ccw_driver = { | |||
51 | .set_online = zfcp_ccw_set_online, | 51 | .set_online = zfcp_ccw_set_online, |
52 | .set_offline = zfcp_ccw_set_offline, | 52 | .set_offline = zfcp_ccw_set_offline, |
53 | .notify = zfcp_ccw_notify, | 53 | .notify = zfcp_ccw_notify, |
54 | .driver = { | 54 | .shutdown = zfcp_ccw_shutdown, |
55 | .shutdown = zfcp_ccw_shutdown, | ||
56 | }, | ||
57 | }; | 55 | }; |
58 | 56 | ||
59 | MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); | 57 | MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); |
@@ -277,12 +275,12 @@ zfcp_ccw_register(void) | |||
277 | * Makes sure that QDIO queues are down when the system gets stopped. | 275 | * Makes sure that QDIO queues are down when the system gets stopped. |
278 | */ | 276 | */ |
279 | static void | 277 | static void |
280 | zfcp_ccw_shutdown(struct device *dev) | 278 | zfcp_ccw_shutdown(struct ccw_device *cdev) |
281 | { | 279 | { |
282 | struct zfcp_adapter *adapter; | 280 | struct zfcp_adapter *adapter; |
283 | 281 | ||
284 | down(&zfcp_data.config_sema); | 282 | down(&zfcp_data.config_sema); |
285 | adapter = dev_get_drvdata(dev); | 283 | adapter = dev_get_drvdata(&cdev->dev); |
286 | zfcp_erp_adapter_shutdown(adapter, 0); | 284 | zfcp_erp_adapter_shutdown(adapter, 0); |
287 | zfcp_erp_wait(adapter); | 285 | zfcp_erp_wait(adapter); |
288 | up(&zfcp_data.config_sema); | 286 | up(&zfcp_data.config_sema); |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 5f3212440f68..ffa3bf756943 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -19,8 +19,8 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/debug.h> | ||
23 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <asm/debug.h> | ||
24 | #include "zfcp_ext.h" | 24 | #include "zfcp_ext.h" |
25 | 25 | ||
26 | static u32 dbfsize = 4; | 26 | static u32 dbfsize = 4; |
@@ -35,17 +35,17 @@ static int | |||
35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) | 35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) |
36 | { | 36 | { |
37 | unsigned long long sec; | 37 | unsigned long long sec; |
38 | struct timespec xtime; | 38 | struct timespec dbftime; |
39 | int len = 0; | 39 | int len = 0; |
40 | 40 | ||
41 | stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); | 41 | stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); |
42 | sec = stck >> 12; | 42 | sec = stck >> 12; |
43 | do_div(sec, 1000000); | 43 | do_div(sec, 1000000); |
44 | xtime.tv_sec = sec; | 44 | dbftime.tv_sec = sec; |
45 | stck -= (sec * 1000000) << 12; | 45 | stck -= (sec * 1000000) << 12; |
46 | xtime.tv_nsec = ((stck * 1000) >> 12); | 46 | dbftime.tv_nsec = ((stck * 1000) >> 12); |
47 | len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", | 47 | len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", |
48 | label, xtime.tv_sec, xtime.tv_nsec); | 48 | label, dbftime.tv_sec, dbftime.tv_nsec); |
49 | 49 | ||
50 | return len; | 50 | return len; |
51 | } | 51 | } |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index d8cd75ce2d9a..16b4418ab257 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -54,7 +54,7 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int); | |||
54 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, | 54 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, |
55 | struct zfcp_port *, | 55 | struct zfcp_port *, |
56 | struct zfcp_unit *, int); | 56 | struct zfcp_unit *, int); |
57 | static inline int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); | 57 | static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); |
58 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, | 58 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, |
59 | struct zfcp_port *, | 59 | struct zfcp_port *, |
60 | struct zfcp_unit *, int); | 60 | struct zfcp_unit *, int); |
@@ -106,8 +106,8 @@ static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *, | |||
106 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); | 106 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); |
107 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); | 107 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); |
108 | 108 | ||
109 | static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *); | 109 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); |
110 | static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *); | 110 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *); |
111 | 111 | ||
112 | static void zfcp_erp_memwait_handler(unsigned long); | 112 | static void zfcp_erp_memwait_handler(unsigned long); |
113 | 113 | ||
@@ -952,7 +952,7 @@ zfcp_erp_memwait_handler(unsigned long data) | |||
952 | * action gets an appropriate flag and will be processed | 952 | * action gets an appropriate flag and will be processed |
953 | * accordingly | 953 | * accordingly |
954 | */ | 954 | */ |
955 | void zfcp_erp_timeout_handler(unsigned long data) | 955 | static void zfcp_erp_timeout_handler(unsigned long data) |
956 | { | 956 | { |
957 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | 957 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; |
958 | struct zfcp_adapter *adapter = erp_action->adapter; | 958 | struct zfcp_adapter *adapter = erp_action->adapter; |
@@ -1491,7 +1491,7 @@ zfcp_erp_strategy_statechange(int action, | |||
1491 | return retval; | 1491 | return retval; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static inline int | 1494 | static int |
1495 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) | 1495 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) |
1496 | { | 1496 | { |
1497 | return | 1497 | return |
@@ -2001,7 +2001,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) | |||
2001 | * returns: 0 - successful setup | 2001 | * returns: 0 - successful setup |
2002 | * !0 - failed setup | 2002 | * !0 - failed setup |
2003 | */ | 2003 | */ |
2004 | int | 2004 | static int |
2005 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | 2005 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) |
2006 | { | 2006 | { |
2007 | int retval; | 2007 | int retval; |
@@ -3248,8 +3248,7 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | |||
3248 | zfcp_erp_action_dismiss(&unit->erp_action); | 3248 | zfcp_erp_action_dismiss(&unit->erp_action); |
3249 | } | 3249 | } |
3250 | 3250 | ||
3251 | static inline void | 3251 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
3252 | zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | ||
3253 | { | 3252 | { |
3254 | struct zfcp_adapter *adapter = erp_action->adapter; | 3253 | struct zfcp_adapter *adapter = erp_action->adapter; |
3255 | 3254 | ||
@@ -3258,8 +3257,7 @@ zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | |||
3258 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); | 3257 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); |
3259 | } | 3258 | } |
3260 | 3259 | ||
3261 | static inline void | 3260 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) |
3262 | zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) | ||
3263 | { | 3261 | { |
3264 | struct zfcp_adapter *adapter = erp_action->adapter; | 3262 | struct zfcp_adapter *adapter = erp_action->adapter; |
3265 | 3263 | ||
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index ac49b15fa768..516a6400db43 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -28,27 +28,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ | |||
28 | 28 | ||
29 | obj-$(CONFIG_USB_SERIAL) += serial/ | 29 | obj-$(CONFIG_USB_SERIAL) += serial/ |
30 | 30 | ||
31 | obj-$(CONFIG_USB_ADUTUX) += misc/ | 31 | obj-$(CONFIG_USB) += misc/ |
32 | obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ | ||
33 | obj-$(CONFIG_USB_AUERSWALD) += misc/ | ||
34 | obj-$(CONFIG_USB_BERRY_CHARGE) += misc/ | ||
35 | obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/ | ||
36 | obj-$(CONFIG_USB_CYTHERM) += misc/ | ||
37 | obj-$(CONFIG_USB_EMI26) += misc/ | ||
38 | obj-$(CONFIG_USB_EMI62) += misc/ | ||
39 | obj-$(CONFIG_USB_FTDI_ELAN) += misc/ | ||
40 | obj-$(CONFIG_USB_IDMOUSE) += misc/ | ||
41 | obj-$(CONFIG_USB_LCD) += misc/ | ||
42 | obj-$(CONFIG_USB_LD) += misc/ | ||
43 | obj-$(CONFIG_USB_LED) += misc/ | ||
44 | obj-$(CONFIG_USB_LEGOTOWER) += misc/ | ||
45 | obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ | ||
46 | obj-$(CONFIG_USB_RIO500) += misc/ | ||
47 | obj-$(CONFIG_USB_SISUSBVGA) += misc/ | ||
48 | obj-$(CONFIG_USB_TEST) += misc/ | ||
49 | obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/ | ||
50 | obj-$(CONFIG_USB_USS720) += misc/ | ||
51 | obj-$(CONFIG_USB_IOWARRIOR) += misc/ | ||
52 | 32 | ||
53 | obj-$(CONFIG_USB_ATM) += atm/ | 33 | obj-$(CONFIG_USB_ATM) += atm/ |
54 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ | 34 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ |
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index a73e714288e5..a51eeedc18d4 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
@@ -482,7 +482,9 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | |||
482 | int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE; | 482 | int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE; |
483 | 483 | ||
484 | if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) { | 484 | if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) { |
485 | dbg("too big transfer requested"); | 485 | if (printk_ratelimit()) |
486 | usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n", | ||
487 | wbuflen, rbuflen); | ||
486 | ret = -ENOMEM; | 488 | ret = -ENOMEM; |
487 | goto fail; | 489 | goto fail; |
488 | } | 490 | } |
@@ -493,8 +495,9 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | |||
493 | init_completion(&instance->rcv_done); | 495 | init_completion(&instance->rcv_done); |
494 | ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL); | 496 | ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL); |
495 | if (ret < 0) { | 497 | if (ret < 0) { |
496 | dbg("submitting read urb for cm %#x failed", cm); | 498 | if (printk_ratelimit()) |
497 | ret = ret; | 499 | usb_err(instance->usbatm, "submit of read urb for cm %#x failed (%d)\n", |
500 | cm, ret); | ||
498 | goto fail; | 501 | goto fail; |
499 | } | 502 | } |
500 | 503 | ||
@@ -510,27 +513,29 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | |||
510 | init_completion(&instance->snd_done); | 513 | init_completion(&instance->snd_done); |
511 | ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL); | 514 | ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL); |
512 | if (ret < 0) { | 515 | if (ret < 0) { |
513 | dbg("submitting write urb for cm %#x failed", cm); | 516 | if (printk_ratelimit()) |
514 | ret = ret; | 517 | usb_err(instance->usbatm, "submit of write urb for cm %#x failed (%d)\n", |
518 | cm, ret); | ||
515 | goto fail; | 519 | goto fail; |
516 | } | 520 | } |
517 | 521 | ||
518 | ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL); | 522 | ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL); |
519 | if (ret < 0) { | 523 | if (ret < 0) { |
520 | dbg("sending cm %#x failed", cm); | 524 | if (printk_ratelimit()) |
521 | ret = ret; | 525 | usb_err(instance->usbatm, "send of cm %#x failed (%d)\n", cm, ret); |
522 | goto fail; | 526 | goto fail; |
523 | } | 527 | } |
524 | 528 | ||
525 | ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen); | 529 | ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen); |
526 | if (ret < 0) { | 530 | if (ret < 0) { |
527 | dbg("receiving cm %#x failed", cm); | 531 | if (printk_ratelimit()) |
528 | ret = ret; | 532 | usb_err(instance->usbatm, "receive of cm %#x failed (%d)\n", cm, ret); |
529 | goto fail; | 533 | goto fail; |
530 | } | 534 | } |
531 | if (actlen % CMD_PACKET_SIZE || !actlen) { | 535 | if (actlen % CMD_PACKET_SIZE || !actlen) { |
532 | dbg("response is not a positive multiple of %d: %#x", | 536 | if (printk_ratelimit()) |
533 | CMD_PACKET_SIZE, actlen); | 537 | usb_err(instance->usbatm, "invalid response length to cm %#x: %d\n", |
538 | cm, actlen); | ||
534 | ret = -EIO; | 539 | ret = -EIO; |
535 | goto fail; | 540 | goto fail; |
536 | } | 541 | } |
@@ -538,12 +543,16 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | |||
538 | /* check the return status and copy the data to the output buffer, if needed */ | 543 | /* check the return status and copy the data to the output buffer, if needed */ |
539 | for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) { | 544 | for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) { |
540 | if (rbuf[offb] != cm) { | 545 | if (rbuf[offb] != cm) { |
541 | dbg("wrong cm %#x in response", rbuf[offb]); | 546 | if (printk_ratelimit()) |
547 | usb_err(instance->usbatm, "wrong cm %#x in response to cm %#x\n", | ||
548 | rbuf[offb], cm); | ||
542 | ret = -EIO; | 549 | ret = -EIO; |
543 | goto fail; | 550 | goto fail; |
544 | } | 551 | } |
545 | if (rbuf[offb + 1] != CM_STATUS_SUCCESS) { | 552 | if (rbuf[offb + 1] != CM_STATUS_SUCCESS) { |
546 | dbg("response failed: %#x", rbuf[offb + 1]); | 553 | if (printk_ratelimit()) |
554 | usb_err(instance->usbatm, "response to cm %#x failed: %#x\n", | ||
555 | cm, rbuf[offb + 1]); | ||
547 | ret = -EIO; | 556 | ret = -EIO; |
548 | goto fail; | 557 | goto fail; |
549 | } | 558 | } |
@@ -582,14 +591,18 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ | |||
582 | for (offb = 0; offb < len; ) { | 591 | for (offb = 0; offb < len; ) { |
583 | int l = le32_to_cpu(buf[offb++]); | 592 | int l = le32_to_cpu(buf[offb++]); |
584 | if (l > stride || l > (len - offb) / 2) { | 593 | if (l > stride || l > (len - offb) / 2) { |
585 | dbg("wrong data length %#x in response", l); | 594 | if (printk_ratelimit()) |
595 | usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n", | ||
596 | cm, l); | ||
586 | ret = -EIO; | 597 | ret = -EIO; |
587 | goto cleanup; | 598 | goto cleanup; |
588 | } | 599 | } |
589 | while (l--) { | 600 | while (l--) { |
590 | offd = le32_to_cpu(buf[offb++]); | 601 | offd = le32_to_cpu(buf[offb++]); |
591 | if (offd >= size) { | 602 | if (offd >= size) { |
592 | dbg("wrong index %#x in response", offd); | 603 | if (printk_ratelimit()) |
604 | usb_err(instance->usbatm, "wrong index #%x in response to cm #%x\n", | ||
605 | offd, cm); | ||
593 | ret = -EIO; | 606 | ret = -EIO; |
594 | goto cleanup; | 607 | goto cleanup; |
595 | } | 608 | } |
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index eb0615abff68..8b132c4a503b 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
@@ -251,7 +251,6 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
251 | { | 251 | { |
252 | unsigned char *buffer; | 252 | unsigned char *buffer; |
253 | struct usbatm_data *usbatm = instance->usbatm; | 253 | struct usbatm_data *usbatm = instance->usbatm; |
254 | struct usb_interface *intf; | ||
255 | struct usb_device *usb_dev = usbatm->usb_dev; | 254 | struct usb_device *usb_dev = usbatm->usb_dev; |
256 | int actual_length; | 255 | int actual_length; |
257 | int ret = 0; | 256 | int ret = 0; |
@@ -265,7 +264,7 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, | |||
265 | goto out; | 264 | goto out; |
266 | } | 265 | } |
267 | 266 | ||
268 | if (!(intf = usb_ifnum_to_if(usb_dev, 2))) { | 267 | if (!usb_ifnum_to_if(usb_dev, 2)) { |
269 | ret = -ENODEV; | 268 | ret = -ENODEV; |
270 | usb_dbg(usbatm, "%s: interface not found!\n", __func__); | 269 | usb_dbg(usbatm, "%s: interface not found!\n", __func__); |
271 | goto out_free; | 270 | goto out_free; |
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 29807d048b04..389c5b164eb2 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * Copyright (c) 2003, 2004 | 2 | * Copyright (c) 2003, 2004 |
3 | * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved. | 3 | * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved. |
4 | * | 4 | * |
5 | * Copyright (c) 2005 Matthieu Castet <castet.matthieu@free.fr> | 5 | * Copyright (c) 2005-2007 Matthieu Castet <castet.matthieu@free.fr> |
6 | * Copyright (c) 2005-2007 Stanislaw Gruszka <stf_xl@wp.pl> | ||
6 | * | 7 | * |
7 | * This software is available to you under a choice of one of two | 8 | * This software is available to you under a choice of one of two |
8 | * licenses. You may choose to be licensed under the terms of the GNU | 9 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -107,18 +108,51 @@ | |||
107 | #define uea_info(usb_dev, format,args...) \ | 108 | #define uea_info(usb_dev, format,args...) \ |
108 | dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) | 109 | dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) |
109 | 110 | ||
110 | struct uea_cmvs { | 111 | struct intr_pkt; |
112 | |||
113 | /* cmv's from firmware */ | ||
114 | struct uea_cmvs_v1 { | ||
111 | u32 address; | 115 | u32 address; |
112 | u16 offset; | 116 | u16 offset; |
113 | u32 data; | 117 | u32 data; |
114 | } __attribute__ ((packed)); | 118 | } __attribute__ ((packed)); |
115 | 119 | ||
120 | struct uea_cmvs_v2 { | ||
121 | u32 group; | ||
122 | u32 address; | ||
123 | u32 offset; | ||
124 | u32 data; | ||
125 | } __attribute__ ((packed)); | ||
126 | |||
127 | /* information about currently processed cmv */ | ||
128 | struct cmv_dsc_e1 { | ||
129 | u8 function; | ||
130 | u16 idx; | ||
131 | u32 address; | ||
132 | u16 offset; | ||
133 | }; | ||
134 | |||
135 | struct cmv_dsc_e4 { | ||
136 | u16 function; | ||
137 | u16 offset; | ||
138 | u16 address; | ||
139 | u16 group; | ||
140 | }; | ||
141 | |||
142 | union cmv_dsc { | ||
143 | struct cmv_dsc_e1 e1; | ||
144 | struct cmv_dsc_e4 e4; | ||
145 | }; | ||
146 | |||
116 | struct uea_softc { | 147 | struct uea_softc { |
117 | struct usb_device *usb_dev; | 148 | struct usb_device *usb_dev; |
118 | struct usbatm_data *usbatm; | 149 | struct usbatm_data *usbatm; |
119 | 150 | ||
120 | int modem_index; | 151 | int modem_index; |
121 | unsigned int driver_info; | 152 | unsigned int driver_info; |
153 | int annex; | ||
154 | #define ANNEXA 0 | ||
155 | #define ANNEXB 1 | ||
122 | 156 | ||
123 | int booting; | 157 | int booting; |
124 | int reset; | 158 | int reset; |
@@ -127,20 +161,23 @@ struct uea_softc { | |||
127 | 161 | ||
128 | struct task_struct *kthread; | 162 | struct task_struct *kthread; |
129 | u32 data; | 163 | u32 data; |
130 | wait_queue_head_t cmv_ack_wait; | 164 | u32 data1; |
165 | |||
131 | int cmv_ack; | 166 | int cmv_ack; |
167 | union cmv_dsc cmv_dsc; | ||
132 | 168 | ||
133 | struct work_struct task; | 169 | struct work_struct task; |
170 | struct workqueue_struct *work_q; | ||
134 | u16 pageno; | 171 | u16 pageno; |
135 | u16 ovl; | 172 | u16 ovl; |
136 | 173 | ||
137 | const struct firmware *dsp_firm; | 174 | const struct firmware *dsp_firm; |
138 | struct urb *urb_int; | 175 | struct urb *urb_int; |
139 | 176 | ||
140 | u8 cmv_function; | 177 | void (*dispatch_cmv) (struct uea_softc *, struct intr_pkt *); |
141 | u16 cmv_idx; | 178 | void (*schedule_load_page) (struct uea_softc *, struct intr_pkt *); |
142 | u32 cmv_address; | 179 | int (*stat) (struct uea_softc *); |
143 | u16 cmv_offset; | 180 | int (*send_cmvs) (struct uea_softc *); |
144 | 181 | ||
145 | /* keep in sync with eaglectl */ | 182 | /* keep in sync with eaglectl */ |
146 | struct uea_stats { | 183 | struct uea_stats { |
@@ -174,10 +211,34 @@ struct uea_softc { | |||
174 | #define ELSA_PID_PSTFIRM 0x3350 | 211 | #define ELSA_PID_PSTFIRM 0x3350 |
175 | #define ELSA_PID_PREFIRM 0x3351 | 212 | #define ELSA_PID_PREFIRM 0x3351 |
176 | 213 | ||
214 | #define ELSA_PID_A_PREFIRM 0x3352 | ||
215 | #define ELSA_PID_A_PSTFIRM 0x3353 | ||
216 | #define ELSA_PID_B_PREFIRM 0x3362 | ||
217 | #define ELSA_PID_B_PSTFIRM 0x3363 | ||
218 | |||
177 | /* | 219 | /* |
178 | * Sagem USB IDs | 220 | * Devolo IDs : pots if (pid & 0x10) |
179 | */ | 221 | */ |
180 | #define EAGLE_VID 0x1110 | 222 | #define DEVOLO_VID 0x1039 |
223 | #define DEVOLO_EAGLE_I_A_PID_PSTFIRM 0x2110 | ||
224 | #define DEVOLO_EAGLE_I_A_PID_PREFIRM 0x2111 | ||
225 | |||
226 | #define DEVOLO_EAGLE_I_B_PID_PSTFIRM 0x2100 | ||
227 | #define DEVOLO_EAGLE_I_B_PID_PREFIRM 0x2101 | ||
228 | |||
229 | #define DEVOLO_EAGLE_II_A_PID_PSTFIRM 0x2130 | ||
230 | #define DEVOLO_EAGLE_II_A_PID_PREFIRM 0x2131 | ||
231 | |||
232 | #define DEVOLO_EAGLE_II_B_PID_PSTFIRM 0x2120 | ||
233 | #define DEVOLO_EAGLE_II_B_PID_PREFIRM 0x2121 | ||
234 | |||
235 | /* | ||
236 | * Reference design USB IDs | ||
237 | */ | ||
238 | #define ANALOG_VID 0x1110 | ||
239 | #define ADI930_PID_PREFIRM 0x9001 | ||
240 | #define ADI930_PID_PSTFIRM 0x9000 | ||
241 | |||
181 | #define EAGLE_I_PID_PREFIRM 0x9010 /* Eagle I */ | 242 | #define EAGLE_I_PID_PREFIRM 0x9010 /* Eagle I */ |
182 | #define EAGLE_I_PID_PSTFIRM 0x900F /* Eagle I */ | 243 | #define EAGLE_I_PID_PSTFIRM 0x900F /* Eagle I */ |
183 | 244 | ||
@@ -187,12 +248,12 @@ struct uea_softc { | |||
187 | #define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ | 248 | #define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ |
188 | #define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ | 249 | #define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ |
189 | 250 | ||
190 | /* | ||
191 | * Eagle III Pid | ||
192 | */ | ||
193 | #define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ | 251 | #define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ |
194 | #define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ | 252 | #define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ |
195 | 253 | ||
254 | #define EAGLE_IV_PID_PREFIRM 0x9042 /* Eagle IV */ | ||
255 | #define EAGLE_IV_PID_PSTFIRM 0x9041 /* Eagle IV */ | ||
256 | |||
196 | /* | 257 | /* |
197 | * USR USB IDs | 258 | * USR USB IDs |
198 | */ | 259 | */ |
@@ -208,11 +269,15 @@ struct uea_softc { | |||
208 | 269 | ||
209 | #define PREFIRM 0 | 270 | #define PREFIRM 0 |
210 | #define PSTFIRM (1<<7) | 271 | #define PSTFIRM (1<<7) |
272 | #define AUTO_ANNEX_A (1<<8) | ||
273 | #define AUTO_ANNEX_B (1<<9) | ||
274 | |||
211 | enum { | 275 | enum { |
212 | ADI930 = 0, | 276 | ADI930 = 0, |
213 | EAGLE_I, | 277 | EAGLE_I, |
214 | EAGLE_II, | 278 | EAGLE_II, |
215 | EAGLE_III | 279 | EAGLE_III, |
280 | EAGLE_IV | ||
216 | }; | 281 | }; |
217 | 282 | ||
218 | /* macros for both struct usb_device_id and struct uea_softc */ | 283 | /* macros for both struct usb_device_id and struct uea_softc */ |
@@ -221,15 +286,18 @@ enum { | |||
221 | #define UEA_CHIP_VERSION(x) \ | 286 | #define UEA_CHIP_VERSION(x) \ |
222 | ((x)->driver_info & 0xf) | 287 | ((x)->driver_info & 0xf) |
223 | 288 | ||
224 | #define IS_ISDN(usb_dev) \ | 289 | #define IS_ISDN(x) \ |
225 | (le16_to_cpu((usb_dev)->descriptor.bcdDevice) & 0x80) | 290 | ((x)->annex & ANNEXB) |
226 | 291 | ||
227 | #define INS_TO_USBDEV(ins) ins->usb_dev | 292 | #define INS_TO_USBDEV(ins) ins->usb_dev |
228 | 293 | ||
229 | #define GET_STATUS(data) \ | 294 | #define GET_STATUS(data) \ |
230 | ((data >> 8) & 0xf) | 295 | ((data >> 8) & 0xf) |
296 | |||
231 | #define IS_OPERATIONAL(sc) \ | 297 | #define IS_OPERATIONAL(sc) \ |
232 | (GET_STATUS(sc->stats.phy.state) == 2) | 298 | ((UEA_CHIP_VERSION(sc) != EAGLE_IV) ? \ |
299 | (GET_STATUS(sc->stats.phy.state) == 2) : \ | ||
300 | (sc->stats.phy.state == 7)) | ||
233 | 301 | ||
234 | /* | 302 | /* |
235 | * Set of macros to handle unaligned data in the firmware blob. | 303 | * Set of macros to handle unaligned data in the firmware blob. |
@@ -259,7 +327,8 @@ enum { | |||
259 | #define UEA_INTR_PIPE 0x04 | 327 | #define UEA_INTR_PIPE 0x04 |
260 | #define UEA_ISO_DATA_PIPE 0x08 | 328 | #define UEA_ISO_DATA_PIPE 0x08 |
261 | 329 | ||
262 | #define UEA_SET_BLOCK 0x0001 | 330 | #define UEA_E1_SET_BLOCK 0x0001 |
331 | #define UEA_E4_SET_BLOCK 0x002c | ||
263 | #define UEA_SET_MODE 0x0003 | 332 | #define UEA_SET_MODE 0x0003 |
264 | #define UEA_SET_2183_DATA 0x0004 | 333 | #define UEA_SET_2183_DATA 0x0004 |
265 | #define UEA_SET_TIMEOUT 0x0011 | 334 | #define UEA_SET_TIMEOUT 0x0011 |
@@ -275,71 +344,179 @@ enum { | |||
275 | #define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) | 344 | #define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) |
276 | #define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) | 345 | #define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) |
277 | 346 | ||
278 | /* structure describing a block within a DSP page */ | 347 | /* block information in eagle4 dsp firmware */ |
279 | struct block_info { | 348 | struct block_index { |
349 | __le32 PageOffset; | ||
350 | __le32 NotLastBlock; | ||
351 | __le32 dummy; | ||
352 | __le32 PageSize; | ||
353 | __le32 PageAddress; | ||
354 | __le16 dummy1; | ||
355 | __le16 PageNumber; | ||
356 | } __attribute__ ((packed)); | ||
357 | |||
358 | #define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000) | ||
359 | #define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4) | ||
360 | |||
361 | #define E4_L1_STRING_HEADER 0x10 | ||
362 | #define E4_MAX_PAGE_NUMBER 0x58 | ||
363 | #define E4_NO_SWAPPAGE_HEADERS 0x31 | ||
364 | |||
365 | /* l1_code is eagle4 dsp firmware format */ | ||
366 | struct l1_code { | ||
367 | u8 string_header[E4_L1_STRING_HEADER]; | ||
368 | u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER]; | ||
369 | struct block_index page_header[E4_NO_SWAPPAGE_HEADERS]; | ||
370 | u8 code [0]; | ||
371 | } __attribute__ ((packed)); | ||
372 | |||
373 | /* structures describing a block within a DSP page */ | ||
374 | struct block_info_e1 { | ||
280 | __le16 wHdr; | 375 | __le16 wHdr; |
281 | #define UEA_BIHDR 0xabcd | ||
282 | __le16 wAddress; | 376 | __le16 wAddress; |
283 | __le16 wSize; | 377 | __le16 wSize; |
284 | __le16 wOvlOffset; | 378 | __le16 wOvlOffset; |
285 | __le16 wOvl; /* overlay */ | 379 | __le16 wOvl; /* overlay */ |
286 | __le16 wLast; | 380 | __le16 wLast; |
287 | } __attribute__ ((packed)); | 381 | } __attribute__ ((packed)); |
288 | #define BLOCK_INFO_SIZE 12 | 382 | #define E1_BLOCK_INFO_SIZE 12 |
383 | |||
384 | struct block_info_e4 { | ||
385 | __be16 wHdr; | ||
386 | __u8 bBootPage; | ||
387 | __u8 bPageNumber; | ||
388 | __be32 dwSize; | ||
389 | __be32 dwAddress; | ||
390 | __be16 wReserved; | ||
391 | } __attribute__ ((packed)); | ||
392 | #define E4_BLOCK_INFO_SIZE 14 | ||
289 | 393 | ||
290 | /* structure representing a CMV (Configuration and Management Variable) */ | 394 | #define UEA_BIHDR 0xabcd |
291 | struct cmv { | 395 | #define UEA_RESERVED 0xffff |
292 | __le16 wPreamble; | 396 | |
293 | #define PREAMBLE 0x535c | 397 | /* constants describing cmv type */ |
294 | __u8 bDirection; | 398 | #define E1_PREAMBLE 0x535c |
295 | #define MODEMTOHOST 0x01 | 399 | #define E1_MODEMTOHOST 0x01 |
296 | #define HOSTTOMODEM 0x10 | 400 | #define E1_HOSTTOMODEM 0x10 |
297 | __u8 bFunction; | 401 | |
298 | #define FUNCTION_TYPE(f) ((f) >> 4) | 402 | #define E1_MEMACCESS 0x1 |
299 | #define MEMACCESS 0x1 | 403 | #define E1_ADSLDIRECTIVE 0x7 |
300 | #define ADSLDIRECTIVE 0x7 | 404 | #define E1_FUNCTION_TYPE(f) ((f) >> 4) |
405 | #define E1_FUNCTION_SUBTYPE(f) ((f) & 0x0f) | ||
406 | |||
407 | #define E4_MEMACCESS 0 | ||
408 | #define E4_ADSLDIRECTIVE 0xf | ||
409 | #define E4_FUNCTION_TYPE(f) ((f) >> 8) | ||
410 | #define E4_FUNCTION_SIZE(f) ((f) & 0x0f) | ||
411 | #define E4_FUNCTION_SUBTYPE(f) (((f) >> 4) & 0x0f) | ||
301 | 412 | ||
302 | #define FUNCTION_SUBTYPE(f) ((f) & 0x0f) | ||
303 | /* for MEMACCESS */ | 413 | /* for MEMACCESS */ |
304 | #define REQUESTREAD 0x0 | 414 | #define E1_REQUESTREAD 0x0 |
305 | #define REQUESTWRITE 0x1 | 415 | #define E1_REQUESTWRITE 0x1 |
306 | #define REPLYREAD 0x2 | 416 | #define E1_REPLYREAD 0x2 |
307 | #define REPLYWRITE 0x3 | 417 | #define E1_REPLYWRITE 0x3 |
418 | |||
419 | #define E4_REQUESTREAD 0x0 | ||
420 | #define E4_REQUESTWRITE 0x4 | ||
421 | #define E4_REPLYREAD (E4_REQUESTREAD | 1) | ||
422 | #define E4_REPLYWRITE (E4_REQUESTWRITE | 1) | ||
423 | |||
308 | /* for ADSLDIRECTIVE */ | 424 | /* for ADSLDIRECTIVE */ |
309 | #define KERNELREADY 0x0 | 425 | #define E1_KERNELREADY 0x0 |
310 | #define MODEMREADY 0x1 | 426 | #define E1_MODEMREADY 0x1 |
311 | 427 | ||
312 | #define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) | 428 | #define E4_KERNELREADY 0x0 |
313 | __le16 wIndex; | 429 | #define E4_MODEMREADY 0x1 |
314 | __le32 dwSymbolicAddress; | 430 | |
315 | #define MAKESA(a, b, c, d) \ | 431 | #define E1_MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) |
432 | #define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | ((st) & 0xf) << 4 | ((s) & 0xf)) | ||
433 | |||
434 | #define E1_MAKESA(a, b, c, d) \ | ||
316 | (((c) & 0xff) << 24 | \ | 435 | (((c) & 0xff) << 24 | \ |
317 | ((d) & 0xff) << 16 | \ | 436 | ((d) & 0xff) << 16 | \ |
318 | ((a) & 0xff) << 8 | \ | 437 | ((a) & 0xff) << 8 | \ |
319 | ((b) & 0xff)) | 438 | ((b) & 0xff)) |
320 | #define GETSA1(a) ((a >> 8) & 0xff) | 439 | |
321 | #define GETSA2(a) (a & 0xff) | 440 | #define E1_GETSA1(a) ((a >> 8) & 0xff) |
322 | #define GETSA3(a) ((a >> 24) & 0xff) | 441 | #define E1_GETSA2(a) (a & 0xff) |
323 | #define GETSA4(a) ((a >> 16) & 0xff) | 442 | #define E1_GETSA3(a) ((a >> 24) & 0xff) |
324 | 443 | #define E1_GETSA4(a) ((a >> 16) & 0xff) | |
325 | #define SA_CNTL MAKESA('C', 'N', 'T', 'L') | 444 | |
326 | #define SA_DIAG MAKESA('D', 'I', 'A', 'G') | 445 | #define E1_SA_CNTL E1_MAKESA('C', 'N', 'T', 'L') |
327 | #define SA_INFO MAKESA('I', 'N', 'F', 'O') | 446 | #define E1_SA_DIAG E1_MAKESA('D', 'I', 'A', 'G') |
328 | #define SA_OPTN MAKESA('O', 'P', 'T', 'N') | 447 | #define E1_SA_INFO E1_MAKESA('I', 'N', 'F', 'O') |
329 | #define SA_RATE MAKESA('R', 'A', 'T', 'E') | 448 | #define E1_SA_OPTN E1_MAKESA('O', 'P', 'T', 'N') |
330 | #define SA_STAT MAKESA('S', 'T', 'A', 'T') | 449 | #define E1_SA_RATE E1_MAKESA('R', 'A', 'T', 'E') |
450 | #define E1_SA_STAT E1_MAKESA('S', 'T', 'A', 'T') | ||
451 | |||
452 | #define E4_SA_CNTL 1 | ||
453 | #define E4_SA_STAT 2 | ||
454 | #define E4_SA_INFO 3 | ||
455 | #define E4_SA_TEST 4 | ||
456 | #define E4_SA_OPTN 5 | ||
457 | #define E4_SA_RATE 6 | ||
458 | #define E4_SA_DIAG 7 | ||
459 | #define E4_SA_CNFG 8 | ||
460 | |||
461 | /* structures representing a CMV (Configuration and Management Variable) */ | ||
462 | struct cmv_e1 { | ||
463 | __le16 wPreamble; | ||
464 | __u8 bDirection; | ||
465 | __u8 bFunction; | ||
466 | __le16 wIndex; | ||
467 | __le32 dwSymbolicAddress; | ||
331 | __le16 wOffsetAddress; | 468 | __le16 wOffsetAddress; |
332 | __le32 dwData; | 469 | __le32 dwData; |
333 | } __attribute__ ((packed)); | 470 | } __attribute__ ((packed)); |
334 | #define CMV_SIZE 16 | ||
335 | 471 | ||
336 | /* structure representing swap information */ | 472 | struct cmv_e4 { |
337 | struct swap_info { | 473 | __be16 wGroup; |
474 | __be16 wFunction; | ||
475 | __be16 wOffset; | ||
476 | __be16 wAddress; | ||
477 | __be32 dwData [6]; | ||
478 | } __attribute__ ((packed)); | ||
479 | |||
480 | /* structures representing swap information */ | ||
481 | struct swap_info_e1 { | ||
338 | __u8 bSwapPageNo; | 482 | __u8 bSwapPageNo; |
339 | __u8 bOvl; /* overlay */ | 483 | __u8 bOvl; /* overlay */ |
340 | } __attribute__ ((packed)); | 484 | } __attribute__ ((packed)); |
341 | 485 | ||
342 | /* structure representing interrupt data */ | 486 | struct swap_info_e4 { |
487 | __u8 bSwapPageNo; | ||
488 | } __attribute__ ((packed)); | ||
489 | |||
490 | /* structures representing interrupt data */ | ||
491 | #define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo | ||
492 | #define e1_bOvl u.e1.s1.swapinfo.bOvl | ||
493 | #define e4_bSwapPageNo u.e4.s1.swapinfo.bSwapPageNo | ||
494 | |||
495 | #define INT_LOADSWAPPAGE 0x0001 | ||
496 | #define INT_INCOMINGCMV 0x0002 | ||
497 | |||
498 | union intr_data_e1 { | ||
499 | struct { | ||
500 | struct swap_info_e1 swapinfo; | ||
501 | __le16 wDataSize; | ||
502 | } __attribute__ ((packed)) s1; | ||
503 | struct { | ||
504 | struct cmv_e1 cmv; | ||
505 | __le16 wDataSize; | ||
506 | } __attribute__ ((packed)) s2; | ||
507 | } __attribute__ ((packed)); | ||
508 | |||
509 | union intr_data_e4 { | ||
510 | struct { | ||
511 | struct swap_info_e4 swapinfo; | ||
512 | __le16 wDataSize; | ||
513 | } __attribute__ ((packed)) s1; | ||
514 | struct { | ||
515 | struct cmv_e4 cmv; | ||
516 | __le16 wDataSize; | ||
517 | } __attribute__ ((packed)) s2; | ||
518 | } __attribute__ ((packed)); | ||
519 | |||
343 | struct intr_pkt { | 520 | struct intr_pkt { |
344 | __u8 bType; | 521 | __u8 bType; |
345 | __u8 bNotification; | 522 | __u8 bNotification; |
@@ -347,43 +524,48 @@ struct intr_pkt { | |||
347 | __le16 wIndex; | 524 | __le16 wIndex; |
348 | __le16 wLength; | 525 | __le16 wLength; |
349 | __le16 wInterrupt; | 526 | __le16 wInterrupt; |
350 | #define INT_LOADSWAPPAGE 0x0001 | ||
351 | #define INT_INCOMINGCMV 0x0002 | ||
352 | union { | 527 | union { |
353 | struct { | 528 | union intr_data_e1 e1; |
354 | struct swap_info swapinfo; | 529 | union intr_data_e4 e4; |
355 | __le16 wDataSize; | 530 | } u; |
356 | } __attribute__ ((packed)) s1; | ||
357 | |||
358 | struct { | ||
359 | struct cmv cmv; | ||
360 | __le16 wDataSize; | ||
361 | } __attribute__ ((packed)) s2; | ||
362 | } __attribute__ ((packed)) u; | ||
363 | #define bSwapPageNo u.s1.swapinfo.bSwapPageNo | ||
364 | #define bOvl u.s1.swapinfo.bOvl | ||
365 | } __attribute__ ((packed)); | 531 | } __attribute__ ((packed)); |
366 | #define INTR_PKT_SIZE 28 | 532 | |
533 | #define E1_INTR_PKT_SIZE 28 | ||
534 | #define E4_INTR_PKT_SIZE 64 | ||
367 | 535 | ||
368 | static struct usb_driver uea_driver; | 536 | static struct usb_driver uea_driver; |
369 | static DEFINE_MUTEX(uea_mutex); | 537 | static DEFINE_MUTEX(uea_mutex); |
370 | static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"}; | 538 | static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"}; |
371 | 539 | ||
372 | static int modem_index; | 540 | static int modem_index; |
373 | static unsigned int debug; | 541 | static unsigned int debug; |
374 | static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1}; | 542 | static unsigned int altsetting[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF}; |
375 | static int sync_wait[NB_MODEM]; | 543 | static int sync_wait[NB_MODEM]; |
376 | static char *cmv_file[NB_MODEM]; | 544 | static char *cmv_file[NB_MODEM]; |
545 | static int annex[NB_MODEM]; | ||
377 | 546 | ||
378 | module_param(debug, uint, 0644); | 547 | module_param(debug, uint, 0644); |
379 | MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)"); | 548 | MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)"); |
380 | module_param_array(use_iso, bool, NULL, 0644); | 549 | module_param_array(altsetting, uint, NULL, 0644); |
381 | MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic"); | 550 | MODULE_PARM_DESC(altsetting, "alternate setting for incoming traffic: 0=bulk, " |
551 | "1=isoc slowest, ... , 8=isoc fastest (default)"); | ||
382 | module_param_array(sync_wait, bool, NULL, 0644); | 552 | module_param_array(sync_wait, bool, NULL, 0644); |
383 | MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM"); | 553 | MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM"); |
384 | module_param_array(cmv_file, charp, NULL, 0644); | 554 | module_param_array(cmv_file, charp, NULL, 0644); |
385 | MODULE_PARM_DESC(cmv_file, | 555 | MODULE_PARM_DESC(cmv_file, |
386 | "file name with configuration and management variables"); | 556 | "file name with configuration and management variables"); |
557 | module_param_array(annex, uint, NULL, 0644); | ||
558 | MODULE_PARM_DESC(annex, | ||
559 | "manually set annex a/b (0=auto, 1=annex a, 2=annex b)"); | ||
560 | |||
561 | #define uea_wait(sc, cond, timeo) \ | ||
562 | ({ \ | ||
563 | int _r = wait_event_interruptible_timeout(sc->sync_q, \ | ||
564 | (cond) || kthread_should_stop(), timeo); \ | ||
565 | if (kthread_should_stop()) \ | ||
566 | _r = -ENODEV; \ | ||
567 | _r; \ | ||
568 | }) | ||
387 | 569 | ||
388 | #define UPDATE_ATM_STAT(type, val) \ | 570 | #define UPDATE_ATM_STAT(type, val) \ |
389 | do { \ | 571 | do { \ |
@@ -519,6 +701,9 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) | |||
519 | case EAGLE_III: | 701 | case EAGLE_III: |
520 | fw_name = FW_DIR "eagleIII.fw"; | 702 | fw_name = FW_DIR "eagleIII.fw"; |
521 | break; | 703 | break; |
704 | case EAGLE_IV: | ||
705 | fw_name = FW_DIR "eagleIV.fw"; | ||
706 | break; | ||
522 | } | 707 | } |
523 | 708 | ||
524 | ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); | 709 | ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); |
@@ -537,7 +722,7 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) | |||
537 | /* | 722 | /* |
538 | * Make sure that the DSP code provided is safe to use. | 723 | * Make sure that the DSP code provided is safe to use. |
539 | */ | 724 | */ |
540 | static int check_dsp(u8 *dsp, unsigned int len) | 725 | static int check_dsp_e1(u8 *dsp, unsigned int len) |
541 | { | 726 | { |
542 | u8 pagecount, blockcount; | 727 | u8 pagecount, blockcount; |
543 | u16 blocksize; | 728 | u16 blocksize; |
@@ -588,6 +773,51 @@ static int check_dsp(u8 *dsp, unsigned int len) | |||
588 | return 0; | 773 | return 0; |
589 | } | 774 | } |
590 | 775 | ||
776 | static int check_dsp_e4(u8 *dsp, int len) | ||
777 | { | ||
778 | int i; | ||
779 | struct l1_code *p = (struct l1_code *) dsp; | ||
780 | unsigned int sum = p->code - dsp; | ||
781 | |||
782 | if (len < sum) | ||
783 | return 1; | ||
784 | |||
785 | if (strcmp("STRATIPHY ANEXA", p->string_header) != 0 && | ||
786 | strcmp("STRATIPHY ANEXB", p->string_header) != 0) | ||
787 | return 1; | ||
788 | |||
789 | for (i = 0; i < E4_MAX_PAGE_NUMBER; i++) { | ||
790 | struct block_index *blockidx; | ||
791 | u8 blockno = p->page_number_to_block_index[i]; | ||
792 | if (blockno >= E4_NO_SWAPPAGE_HEADERS) | ||
793 | continue; | ||
794 | |||
795 | do { | ||
796 | u64 l; | ||
797 | |||
798 | if (blockno >= E4_NO_SWAPPAGE_HEADERS) | ||
799 | return 1; | ||
800 | |||
801 | blockidx = &p->page_header[blockno++]; | ||
802 | if ((u8 *)(blockidx + 1) - dsp >= len) | ||
803 | return 1; | ||
804 | |||
805 | if (le16_to_cpu(blockidx->PageNumber) != i) | ||
806 | return 1; | ||
807 | |||
808 | l = E4_PAGE_BYTES(blockidx->PageSize); | ||
809 | sum += l; | ||
810 | l += le32_to_cpu(blockidx->PageOffset); | ||
811 | if (l > len) | ||
812 | return 1; | ||
813 | |||
814 | /* zero is zero regardless endianes */ | ||
815 | } while (blockidx->NotLastBlock); | ||
816 | } | ||
817 | |||
818 | return (sum == len) ? 0 : 1; | ||
819 | } | ||
820 | |||
591 | /* | 821 | /* |
592 | * send data to the idma pipe | 822 | * send data to the idma pipe |
593 | * */ | 823 | * */ |
@@ -624,13 +854,18 @@ static int request_dsp(struct uea_softc *sc) | |||
624 | int ret; | 854 | int ret; |
625 | char *dsp_name; | 855 | char *dsp_name; |
626 | 856 | ||
627 | if (UEA_CHIP_VERSION(sc) == ADI930) { | 857 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
628 | if (IS_ISDN(sc->usb_dev)) | 858 | if (IS_ISDN(sc)) |
859 | dsp_name = FW_DIR "DSP4i.bin"; | ||
860 | else | ||
861 | dsp_name = FW_DIR "DSP4p.bin"; | ||
862 | } else if (UEA_CHIP_VERSION(sc) == ADI930) { | ||
863 | if (IS_ISDN(sc)) | ||
629 | dsp_name = FW_DIR "DSP9i.bin"; | 864 | dsp_name = FW_DIR "DSP9i.bin"; |
630 | else | 865 | else |
631 | dsp_name = FW_DIR "DSP9p.bin"; | 866 | dsp_name = FW_DIR "DSP9p.bin"; |
632 | } else { | 867 | } else { |
633 | if (IS_ISDN(sc->usb_dev)) | 868 | if (IS_ISDN(sc)) |
634 | dsp_name = FW_DIR "DSPei.bin"; | 869 | dsp_name = FW_DIR "DSPei.bin"; |
635 | else | 870 | else |
636 | dsp_name = FW_DIR "DSPep.bin"; | 871 | dsp_name = FW_DIR "DSPep.bin"; |
@@ -640,11 +875,16 @@ static int request_dsp(struct uea_softc *sc) | |||
640 | if (ret < 0) { | 875 | if (ret < 0) { |
641 | uea_err(INS_TO_USBDEV(sc), | 876 | uea_err(INS_TO_USBDEV(sc), |
642 | "requesting firmware %s failed with error %d\n", | 877 | "requesting firmware %s failed with error %d\n", |
643 | dsp_name, ret); | 878 | dsp_name, ret); |
644 | return ret; | 879 | return ret; |
645 | } | 880 | } |
646 | 881 | ||
647 | if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) { | 882 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) |
883 | ret = check_dsp_e4(sc->dsp_firm->data, sc->dsp_firm->size); | ||
884 | else | ||
885 | ret = check_dsp_e1(sc->dsp_firm->data, sc->dsp_firm->size); | ||
886 | |||
887 | if (ret) { | ||
648 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", | 888 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", |
649 | dsp_name); | 889 | dsp_name); |
650 | release_firmware(sc->dsp_firm); | 890 | release_firmware(sc->dsp_firm); |
@@ -658,12 +898,12 @@ static int request_dsp(struct uea_softc *sc) | |||
658 | /* | 898 | /* |
659 | * The uea_load_page() function must be called within a process context | 899 | * The uea_load_page() function must be called within a process context |
660 | */ | 900 | */ |
661 | static void uea_load_page(struct work_struct *work) | 901 | static void uea_load_page_e1(struct work_struct *work) |
662 | { | 902 | { |
663 | struct uea_softc *sc = container_of(work, struct uea_softc, task); | 903 | struct uea_softc *sc = container_of(work, struct uea_softc, task); |
664 | u16 pageno = sc->pageno; | 904 | u16 pageno = sc->pageno; |
665 | u16 ovl = sc->ovl; | 905 | u16 ovl = sc->ovl; |
666 | struct block_info bi; | 906 | struct block_info_e1 bi; |
667 | 907 | ||
668 | u8 *p; | 908 | u8 *p; |
669 | u8 pagecount, blockcount; | 909 | u8 pagecount, blockcount; |
@@ -716,7 +956,7 @@ static void uea_load_page(struct work_struct *work) | |||
716 | bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0); | 956 | bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0); |
717 | 957 | ||
718 | /* send block info through the IDMA pipe */ | 958 | /* send block info through the IDMA pipe */ |
719 | if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE)) | 959 | if (uea_idma_write(sc, &bi, E1_BLOCK_INFO_SIZE)) |
720 | goto bad2; | 960 | goto bad2; |
721 | 961 | ||
722 | /* send block data through the IDMA pipe */ | 962 | /* send block data through the IDMA pipe */ |
@@ -735,17 +975,114 @@ bad1: | |||
735 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); | 975 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); |
736 | } | 976 | } |
737 | 977 | ||
978 | static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot) | ||
979 | { | ||
980 | struct block_info_e4 bi; | ||
981 | struct block_index *blockidx; | ||
982 | struct l1_code *p = (struct l1_code *) sc->dsp_firm->data; | ||
983 | u8 blockno = p->page_number_to_block_index[pageno]; | ||
984 | |||
985 | bi.wHdr = cpu_to_be16(UEA_BIHDR); | ||
986 | bi.bBootPage = boot; | ||
987 | bi.bPageNumber = pageno; | ||
988 | bi.wReserved = cpu_to_be16(UEA_RESERVED); | ||
989 | |||
990 | do { | ||
991 | u8 *blockoffset; | ||
992 | unsigned int blocksize; | ||
993 | |||
994 | blockidx = &p->page_header[blockno]; | ||
995 | blocksize = E4_PAGE_BYTES(blockidx->PageSize); | ||
996 | blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset); | ||
997 | |||
998 | bi.dwSize = cpu_to_be32(blocksize); | ||
999 | bi.dwAddress = swab32(blockidx->PageAddress); | ||
1000 | |||
1001 | uea_dbg(INS_TO_USBDEV(sc), | ||
1002 | "sending block %u for DSP page %u size %u adress %x\n", | ||
1003 | blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress)); | ||
1004 | |||
1005 | /* send block info through the IDMA pipe */ | ||
1006 | if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE)) | ||
1007 | goto bad; | ||
1008 | |||
1009 | /* send block data through the IDMA pipe */ | ||
1010 | if (uea_idma_write(sc, blockoffset, blocksize)) | ||
1011 | goto bad; | ||
1012 | |||
1013 | blockno++; | ||
1014 | } while (blockidx->NotLastBlock); | ||
1015 | |||
1016 | return; | ||
1017 | |||
1018 | bad: | ||
1019 | uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", blockno); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | static void uea_load_page_e4(struct work_struct *work) | ||
1024 | { | ||
1025 | struct uea_softc *sc = container_of(work, struct uea_softc, task); | ||
1026 | u8 pageno = sc->pageno; | ||
1027 | int i; | ||
1028 | struct block_info_e4 bi; | ||
1029 | struct l1_code *p; | ||
1030 | |||
1031 | uea_dbg(INS_TO_USBDEV(sc), "sending DSP page %u\n", pageno); | ||
1032 | |||
1033 | /* reload firmware when reboot start and it's loaded already */ | ||
1034 | if (pageno == 0 && sc->dsp_firm) { | ||
1035 | release_firmware(sc->dsp_firm); | ||
1036 | sc->dsp_firm = NULL; | ||
1037 | } | ||
1038 | |||
1039 | if (sc->dsp_firm == NULL && request_dsp(sc) < 0) | ||
1040 | return; | ||
1041 | |||
1042 | p = (struct l1_code *) sc->dsp_firm->data; | ||
1043 | if (pageno >= p->page_header[0].PageNumber) { | ||
1044 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | if (pageno != 0) { | ||
1049 | __uea_load_page_e4(sc, pageno, 0); | ||
1050 | return; | ||
1051 | } | ||
1052 | |||
1053 | uea_dbg(INS_TO_USBDEV(sc), | ||
1054 | "sending Main DSP page %u\n", p->page_header[0].PageNumber); | ||
1055 | |||
1056 | for (i = 0; i < le16_to_cpu(p->page_header[0].PageNumber); i++) { | ||
1057 | if (E4_IS_BOOT_PAGE(p->page_header[i].PageSize)) | ||
1058 | __uea_load_page_e4(sc, i, 1); | ||
1059 | } | ||
1060 | |||
1061 | uea_dbg(INS_TO_USBDEV(sc),"sending start bi\n"); | ||
1062 | |||
1063 | bi.wHdr = cpu_to_be16(UEA_BIHDR); | ||
1064 | bi.bBootPage = 0; | ||
1065 | bi.bPageNumber = 0xff; | ||
1066 | bi.wReserved = cpu_to_be16(UEA_RESERVED); | ||
1067 | bi.dwSize = cpu_to_be32(E4_PAGE_BYTES(p->page_header[0].PageSize)); | ||
1068 | bi.dwAddress = swab32(p->page_header[0].PageAddress); | ||
1069 | |||
1070 | /* send block info through the IDMA pipe */ | ||
1071 | if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE)) | ||
1072 | uea_err(INS_TO_USBDEV(sc), "sending DSP start bi failed\n"); | ||
1073 | } | ||
1074 | |||
738 | static inline void wake_up_cmv_ack(struct uea_softc *sc) | 1075 | static inline void wake_up_cmv_ack(struct uea_softc *sc) |
739 | { | 1076 | { |
740 | BUG_ON(sc->cmv_ack); | 1077 | BUG_ON(sc->cmv_ack); |
741 | sc->cmv_ack = 1; | 1078 | sc->cmv_ack = 1; |
742 | wake_up(&sc->cmv_ack_wait); | 1079 | wake_up(&sc->sync_q); |
743 | } | 1080 | } |
744 | 1081 | ||
745 | static inline int wait_cmv_ack(struct uea_softc *sc) | 1082 | static inline int wait_cmv_ack(struct uea_softc *sc) |
746 | { | 1083 | { |
747 | int ret = wait_event_interruptible_timeout(sc->cmv_ack_wait, | 1084 | int ret = uea_wait(sc, sc->cmv_ack , ACK_TIMEOUT); |
748 | sc->cmv_ack, ACK_TIMEOUT); | 1085 | |
749 | sc->cmv_ack = 0; | 1086 | sc->cmv_ack = 0; |
750 | 1087 | ||
751 | uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n", | 1088 | uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n", |
@@ -792,33 +1129,68 @@ static int uea_request(struct uea_softc *sc, | |||
792 | return 0; | 1129 | return 0; |
793 | } | 1130 | } |
794 | 1131 | ||
795 | static int uea_cmv(struct uea_softc *sc, | 1132 | static int uea_cmv_e1(struct uea_softc *sc, |
796 | u8 function, u32 address, u16 offset, u32 data) | 1133 | u8 function, u32 address, u16 offset, u32 data) |
797 | { | 1134 | { |
798 | struct cmv cmv; | 1135 | struct cmv_e1 cmv; |
799 | int ret; | 1136 | int ret; |
800 | 1137 | ||
801 | uea_enters(INS_TO_USBDEV(sc)); | 1138 | uea_enters(INS_TO_USBDEV(sc)); |
802 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, " | 1139 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, " |
803 | "offset : 0x%04x, data : 0x%08x\n", | 1140 | "offset : 0x%04x, data : 0x%08x\n", |
804 | FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function), | 1141 | E1_FUNCTION_TYPE(function), E1_FUNCTION_SUBTYPE(function), |
805 | GETSA1(address), GETSA2(address), GETSA3(address), | 1142 | E1_GETSA1(address), E1_GETSA2(address), E1_GETSA3(address), |
806 | GETSA4(address), offset, data); | 1143 | E1_GETSA4(address), offset, data); |
1144 | |||
807 | /* we send a request, but we expect a reply */ | 1145 | /* we send a request, but we expect a reply */ |
808 | sc->cmv_function = function | 0x2; | 1146 | sc->cmv_dsc.e1.function = function | 0x2; |
809 | sc->cmv_idx++; | 1147 | sc->cmv_dsc.e1.idx++; |
810 | sc->cmv_address = address; | 1148 | sc->cmv_dsc.e1.address = address; |
811 | sc->cmv_offset = offset; | 1149 | sc->cmv_dsc.e1.offset = offset; |
812 | 1150 | ||
813 | cmv.wPreamble = cpu_to_le16(PREAMBLE); | 1151 | cmv.wPreamble = cpu_to_le16(E1_PREAMBLE); |
814 | cmv.bDirection = HOSTTOMODEM; | 1152 | cmv.bDirection = E1_HOSTTOMODEM; |
815 | cmv.bFunction = function; | 1153 | cmv.bFunction = function; |
816 | cmv.wIndex = cpu_to_le16(sc->cmv_idx); | 1154 | cmv.wIndex = cpu_to_le16(sc->cmv_dsc.e1.idx); |
817 | put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress); | 1155 | put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress); |
818 | cmv.wOffsetAddress = cpu_to_le16(offset); | 1156 | cmv.wOffsetAddress = cpu_to_le16(offset); |
819 | put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData); | 1157 | put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData); |
820 | 1158 | ||
821 | ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv); | 1159 | ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv); |
1160 | if (ret < 0) | ||
1161 | return ret; | ||
1162 | ret = wait_cmv_ack(sc); | ||
1163 | uea_leaves(INS_TO_USBDEV(sc)); | ||
1164 | return ret; | ||
1165 | } | ||
1166 | |||
1167 | static int uea_cmv_e4(struct uea_softc *sc, | ||
1168 | u16 function, u16 group, u16 address, u16 offset, u32 data) | ||
1169 | { | ||
1170 | struct cmv_e4 cmv; | ||
1171 | int ret; | ||
1172 | |||
1173 | uea_enters(INS_TO_USBDEV(sc)); | ||
1174 | memset(&cmv, 0, sizeof(cmv)); | ||
1175 | |||
1176 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Group : 0x%04x, " | ||
1177 | "Address : 0x%04x, offset : 0x%04x, data : 0x%08x\n", | ||
1178 | E4_FUNCTION_TYPE(function), E4_FUNCTION_SUBTYPE(function), | ||
1179 | group, address, offset, data); | ||
1180 | |||
1181 | /* we send a request, but we expect a reply */ | ||
1182 | sc->cmv_dsc.e4.function = function | (0x1 << 4); | ||
1183 | sc->cmv_dsc.e4.offset = offset; | ||
1184 | sc->cmv_dsc.e4.address = address; | ||
1185 | sc->cmv_dsc.e4.group = group; | ||
1186 | |||
1187 | cmv.wFunction = cpu_to_be16(function); | ||
1188 | cmv.wGroup = cpu_to_be16(group); | ||
1189 | cmv.wAddress = cpu_to_be16(address); | ||
1190 | cmv.wOffset = cpu_to_be16(offset); | ||
1191 | cmv.dwData[0] = cpu_to_be32(data); | ||
1192 | |||
1193 | ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv); | ||
822 | if (ret < 0) | 1194 | if (ret < 0) |
823 | return ret; | 1195 | return ret; |
824 | ret = wait_cmv_ack(sc); | 1196 | ret = wait_cmv_ack(sc); |
@@ -826,10 +1198,10 @@ static int uea_cmv(struct uea_softc *sc, | |||
826 | return ret; | 1198 | return ret; |
827 | } | 1199 | } |
828 | 1200 | ||
829 | static inline int uea_read_cmv(struct uea_softc *sc, | 1201 | static inline int uea_read_cmv_e1(struct uea_softc *sc, |
830 | u32 address, u16 offset, u32 *data) | 1202 | u32 address, u16 offset, u32 *data) |
831 | { | 1203 | { |
832 | int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD), | 1204 | int ret = uea_cmv_e1(sc, E1_MAKEFUNCTION(E1_MEMACCESS, E1_REQUESTREAD), |
833 | address, offset, 0); | 1205 | address, offset, 0); |
834 | if (ret < 0) | 1206 | if (ret < 0) |
835 | uea_err(INS_TO_USBDEV(sc), | 1207 | uea_err(INS_TO_USBDEV(sc), |
@@ -840,10 +1212,27 @@ static inline int uea_read_cmv(struct uea_softc *sc, | |||
840 | return ret; | 1212 | return ret; |
841 | } | 1213 | } |
842 | 1214 | ||
843 | static inline int uea_write_cmv(struct uea_softc *sc, | 1215 | static inline int uea_read_cmv_e4(struct uea_softc *sc, |
1216 | u8 size, u16 group, u16 address, u16 offset, u32 *data) | ||
1217 | { | ||
1218 | int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTREAD, size), | ||
1219 | group, address, offset, 0); | ||
1220 | if (ret < 0) | ||
1221 | uea_err(INS_TO_USBDEV(sc), | ||
1222 | "reading cmv failed with error %d\n", ret); | ||
1223 | else { | ||
1224 | *data = sc->data; | ||
1225 | /* size is in 16-bit word quantities */ | ||
1226 | if (size > 2) | ||
1227 | *(data + 1) = sc->data1; | ||
1228 | } | ||
1229 | return ret; | ||
1230 | } | ||
1231 | |||
1232 | static inline int uea_write_cmv_e1(struct uea_softc *sc, | ||
844 | u32 address, u16 offset, u32 data) | 1233 | u32 address, u16 offset, u32 data) |
845 | { | 1234 | { |
846 | int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE), | 1235 | int ret = uea_cmv_e1(sc, E1_MAKEFUNCTION(E1_MEMACCESS, E1_REQUESTWRITE), |
847 | address, offset, data); | 1236 | address, offset, data); |
848 | if (ret < 0) | 1237 | if (ret < 0) |
849 | uea_err(INS_TO_USBDEV(sc), | 1238 | uea_err(INS_TO_USBDEV(sc), |
@@ -852,12 +1241,48 @@ static inline int uea_write_cmv(struct uea_softc *sc, | |||
852 | return ret; | 1241 | return ret; |
853 | } | 1242 | } |
854 | 1243 | ||
1244 | static inline int uea_write_cmv_e4(struct uea_softc *sc, | ||
1245 | u8 size, u16 group, u16 address, u16 offset, u32 data) | ||
1246 | { | ||
1247 | int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTWRITE, size), | ||
1248 | group, address, offset, data); | ||
1249 | if (ret < 0) | ||
1250 | uea_err(INS_TO_USBDEV(sc), | ||
1251 | "writing cmv failed with error %d\n", ret); | ||
1252 | |||
1253 | return ret; | ||
1254 | } | ||
1255 | |||
1256 | static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate) | ||
1257 | { | ||
1258 | int ret; | ||
1259 | u16 timeout; | ||
1260 | |||
1261 | /* in bulk mode the modem have problem with high rate | ||
1262 | * changing internal timing could improve things, but the | ||
1263 | * value is misterious. | ||
1264 | * ADI930 don't support it (-EPIPE error). | ||
1265 | */ | ||
1266 | |||
1267 | if (UEA_CHIP_VERSION(sc) == ADI930 || | ||
1268 | altsetting[sc->modem_index] > 0 || | ||
1269 | sc->stats.phy.dsrate == dsrate) | ||
1270 | return; | ||
1271 | |||
1272 | /* Original timming (1Mbit/s) from ADI (used in windows driver) */ | ||
1273 | timeout = (dsrate <= 1024*1024) ? 0 : 1; | ||
1274 | ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL); | ||
1275 | uea_info(INS_TO_USBDEV(sc), "setting new timeout %d%s\n", | ||
1276 | timeout, ret < 0 ? " failed" : ""); | ||
1277 | |||
1278 | } | ||
1279 | |||
855 | /* | 1280 | /* |
856 | * Monitor the modem and update the stat | 1281 | * Monitor the modem and update the stat |
857 | * return 0 if everything is ok | 1282 | * return 0 if everything is ok |
858 | * return < 0 if an error occurs (-EAGAIN reboot needed) | 1283 | * return < 0 if an error occurs (-EAGAIN reboot needed) |
859 | */ | 1284 | */ |
860 | static int uea_stat(struct uea_softc *sc) | 1285 | static int uea_stat_e1(struct uea_softc *sc) |
861 | { | 1286 | { |
862 | u32 data; | 1287 | u32 data; |
863 | int ret; | 1288 | int ret; |
@@ -865,7 +1290,7 @@ static int uea_stat(struct uea_softc *sc) | |||
865 | uea_enters(INS_TO_USBDEV(sc)); | 1290 | uea_enters(INS_TO_USBDEV(sc)); |
866 | data = sc->stats.phy.state; | 1291 | data = sc->stats.phy.state; |
867 | 1292 | ||
868 | ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state); | 1293 | ret = uea_read_cmv_e1(sc, E1_SA_STAT, 0, &sc->stats.phy.state); |
869 | if (ret < 0) | 1294 | if (ret < 0) |
870 | return ret; | 1295 | return ret; |
871 | 1296 | ||
@@ -885,7 +1310,7 @@ static int uea_stat(struct uea_softc *sc) | |||
885 | 1310 | ||
886 | case 3: /* fail ... */ | 1311 | case 3: /* fail ... */ |
887 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" | 1312 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" |
888 | " (may be try other cmv/dsp)\n"); | 1313 | " (may be try other cmv/dsp)\n"); |
889 | return -EAGAIN; | 1314 | return -EAGAIN; |
890 | 1315 | ||
891 | case 4 ... 6: /* test state */ | 1316 | case 4 ... 6: /* test state */ |
@@ -923,7 +1348,7 @@ static int uea_stat(struct uea_softc *sc) | |||
923 | /* wake up processes waiting for synchronization */ | 1348 | /* wake up processes waiting for synchronization */ |
924 | wake_up(&sc->sync_q); | 1349 | wake_up(&sc->sync_q); |
925 | 1350 | ||
926 | ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags); | 1351 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 2, &sc->stats.phy.flags); |
927 | if (ret < 0) | 1352 | if (ret < 0) |
928 | return ret; | 1353 | return ret; |
929 | sc->stats.phy.mflags |= sc->stats.phy.flags; | 1354 | sc->stats.phy.mflags |= sc->stats.phy.flags; |
@@ -937,105 +1362,223 @@ static int uea_stat(struct uea_softc *sc) | |||
937 | return 0; | 1362 | return 0; |
938 | } | 1363 | } |
939 | 1364 | ||
940 | ret = uea_read_cmv(sc, SA_RATE, 0, &data); | 1365 | ret = uea_read_cmv_e1(sc, E1_SA_RATE, 0, &data); |
941 | if (ret < 0) | 1366 | if (ret < 0) |
942 | return ret; | 1367 | return ret; |
943 | 1368 | ||
944 | /* in bulk mode the modem have problem with high rate | 1369 | uea_set_bulk_timeout(sc, (data >> 16) * 32); |
945 | * changing internal timing could improve things, but the | ||
946 | * value is misterious. | ||
947 | * ADI930 don't support it (-EPIPE error). | ||
948 | */ | ||
949 | if (UEA_CHIP_VERSION(sc) != ADI930 | ||
950 | && !use_iso[sc->modem_index] | ||
951 | && sc->stats.phy.dsrate != (data >> 16) * 32) { | ||
952 | /* Original timming from ADI(used in windows driver) | ||
953 | * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits | ||
954 | */ | ||
955 | u16 timeout = (data <= 0x20ffff) ? 0 : 1; | ||
956 | ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL); | ||
957 | uea_info(INS_TO_USBDEV(sc), | ||
958 | "setting new timeout %d%s\n", timeout, | ||
959 | ret < 0?" failed":""); | ||
960 | } | ||
961 | sc->stats.phy.dsrate = (data >> 16) * 32; | 1370 | sc->stats.phy.dsrate = (data >> 16) * 32; |
962 | sc->stats.phy.usrate = (data & 0xffff) * 32; | 1371 | sc->stats.phy.usrate = (data & 0xffff) * 32; |
963 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); | 1372 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); |
964 | 1373 | ||
965 | ret = uea_read_cmv(sc, SA_DIAG, 23, &data); | 1374 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 23, &data); |
966 | if (ret < 0) | 1375 | if (ret < 0) |
967 | return ret; | 1376 | return ret; |
968 | sc->stats.phy.dsattenuation = (data & 0xff) / 2; | 1377 | sc->stats.phy.dsattenuation = (data & 0xff) / 2; |
969 | 1378 | ||
970 | ret = uea_read_cmv(sc, SA_DIAG, 47, &data); | 1379 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 47, &data); |
971 | if (ret < 0) | 1380 | if (ret < 0) |
972 | return ret; | 1381 | return ret; |
973 | sc->stats.phy.usattenuation = (data & 0xff) / 2; | 1382 | sc->stats.phy.usattenuation = (data & 0xff) / 2; |
974 | 1383 | ||
975 | ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin); | 1384 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 25, &sc->stats.phy.dsmargin); |
976 | if (ret < 0) | 1385 | if (ret < 0) |
977 | return ret; | 1386 | return ret; |
978 | 1387 | ||
979 | ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin); | 1388 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 49, &sc->stats.phy.usmargin); |
980 | if (ret < 0) | 1389 | if (ret < 0) |
981 | return ret; | 1390 | return ret; |
982 | 1391 | ||
983 | ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow); | 1392 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 51, &sc->stats.phy.rxflow); |
984 | if (ret < 0) | 1393 | if (ret < 0) |
985 | return ret; | 1394 | return ret; |
986 | 1395 | ||
987 | ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow); | 1396 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 52, &sc->stats.phy.txflow); |
988 | if (ret < 0) | 1397 | if (ret < 0) |
989 | return ret; | 1398 | return ret; |
990 | 1399 | ||
991 | ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc); | 1400 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 54, &sc->stats.phy.dsunc); |
992 | if (ret < 0) | 1401 | if (ret < 0) |
993 | return ret; | 1402 | return ret; |
994 | 1403 | ||
995 | /* only for atu-c */ | 1404 | /* only for atu-c */ |
996 | ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc); | 1405 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 58, &sc->stats.phy.usunc); |
997 | if (ret < 0) | 1406 | if (ret < 0) |
998 | return ret; | 1407 | return ret; |
999 | 1408 | ||
1000 | ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr); | 1409 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 53, &sc->stats.phy.dscorr); |
1001 | if (ret < 0) | 1410 | if (ret < 0) |
1002 | return ret; | 1411 | return ret; |
1003 | 1412 | ||
1004 | /* only for atu-c */ | 1413 | /* only for atu-c */ |
1005 | ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr); | 1414 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 57, &sc->stats.phy.uscorr); |
1006 | if (ret < 0) | 1415 | if (ret < 0) |
1007 | return ret; | 1416 | return ret; |
1008 | 1417 | ||
1009 | ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco); | 1418 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 8, &sc->stats.phy.vidco); |
1010 | if (ret < 0) | 1419 | if (ret < 0) |
1011 | return ret; | 1420 | return ret; |
1012 | 1421 | ||
1013 | ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe); | 1422 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 13, &sc->stats.phy.vidcpe); |
1014 | if (ret < 0) | 1423 | if (ret < 0) |
1015 | return ret; | 1424 | return ret; |
1016 | 1425 | ||
1017 | return 0; | 1426 | return 0; |
1018 | } | 1427 | } |
1019 | 1428 | ||
1020 | static int request_cmvs(struct uea_softc *sc, | 1429 | static int uea_stat_e4(struct uea_softc *sc) |
1021 | struct uea_cmvs **cmvs, const struct firmware **fw) | ||
1022 | { | 1430 | { |
1023 | int ret, size; | 1431 | u32 data; |
1024 | u8 *data; | 1432 | u32 tmp_arr[2]; |
1433 | int ret; | ||
1434 | |||
1435 | uea_enters(INS_TO_USBDEV(sc)); | ||
1436 | data = sc->stats.phy.state; | ||
1437 | |||
1438 | /* XXX only need to be done before operationnal... */ | ||
1439 | ret = uea_read_cmv_e4(sc, 1, E4_SA_STAT, 0, 0, &sc->stats.phy.state); | ||
1440 | if (ret < 0) | ||
1441 | return ret; | ||
1442 | |||
1443 | switch (sc->stats.phy.state) { | ||
1444 | case 0x0: /* not yet synchronized */ | ||
1445 | case 0x1: | ||
1446 | case 0x3: | ||
1447 | case 0x4: | ||
1448 | uea_dbg(INS_TO_USBDEV(sc), "modem not yet synchronized\n"); | ||
1449 | return 0; | ||
1450 | case 0x5: /* initialization */ | ||
1451 | case 0x6: | ||
1452 | case 0x9: | ||
1453 | case 0xa: | ||
1454 | uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n"); | ||
1455 | return 0; | ||
1456 | case 0x2: /* fail ... */ | ||
1457 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" | ||
1458 | " (may be try other cmv/dsp)\n"); | ||
1459 | return -EAGAIN; | ||
1460 | case 0x7: /* operational */ | ||
1461 | break; | ||
1462 | default: | ||
1463 | uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n", sc->stats.phy.state); | ||
1464 | return 0; | ||
1465 | } | ||
1466 | |||
1467 | if (data != 7) { | ||
1468 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL); | ||
1469 | uea_info(INS_TO_USBDEV(sc), "modem operational\n"); | ||
1470 | |||
1471 | /* release the dsp firmware as it is not needed until | ||
1472 | * the next failure | ||
1473 | */ | ||
1474 | if (sc->dsp_firm) { | ||
1475 | release_firmware(sc->dsp_firm); | ||
1476 | sc->dsp_firm = NULL; | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | /* always update it as atm layer could not be init when we switch to | ||
1481 | * operational state | ||
1482 | */ | ||
1483 | UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND); | ||
1484 | |||
1485 | /* wake up processes waiting for synchronization */ | ||
1486 | wake_up(&sc->sync_q); | ||
1487 | |||
1488 | /* TODO improve this state machine : | ||
1489 | * we need some CMV info : what they do and their unit | ||
1490 | * we should find the equivalent of eagle3- CMV | ||
1491 | */ | ||
1492 | /* check flags */ | ||
1493 | ret = uea_read_cmv_e4(sc, 1, E4_SA_DIAG, 0, 0, &sc->stats.phy.flags); | ||
1494 | if (ret < 0) | ||
1495 | return ret; | ||
1496 | sc->stats.phy.mflags |= sc->stats.phy.flags; | ||
1497 | |||
1498 | /* in case of a flags ( for example delineation LOSS (& 0x10)), | ||
1499 | * we check the status again in order to detect the failure earlier | ||
1500 | */ | ||
1501 | if (sc->stats.phy.flags) { | ||
1502 | uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n", | ||
1503 | sc->stats.phy.flags); | ||
1504 | if (sc->stats.phy.flags & 1) //delineation LOSS | ||
1505 | return -EAGAIN; | ||
1506 | if (sc->stats.phy.flags & 0x4000) //Reset Flag | ||
1507 | return -EAGAIN; | ||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | /* rate data may be in upper or lower half of 64 bit word, strange */ | ||
1512 | ret = uea_read_cmv_e4(sc, 4, E4_SA_RATE, 0, 0, tmp_arr); | ||
1513 | if (ret < 0) | ||
1514 | return ret; | ||
1515 | data = (tmp_arr[0]) ? tmp_arr[0] : tmp_arr[1]; | ||
1516 | sc->stats.phy.usrate = data / 1000; | ||
1517 | |||
1518 | ret = uea_read_cmv_e4(sc, 4, E4_SA_RATE, 1, 0, tmp_arr); | ||
1519 | if (ret < 0) | ||
1520 | return ret; | ||
1521 | data = (tmp_arr[0]) ? tmp_arr[0] : tmp_arr[1]; | ||
1522 | uea_set_bulk_timeout(sc, data / 1000); | ||
1523 | sc->stats.phy.dsrate = data / 1000; | ||
1524 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); | ||
1525 | |||
1526 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 68, 1, &data); | ||
1527 | if (ret < 0) | ||
1528 | return ret; | ||
1529 | sc->stats.phy.dsattenuation = data / 10; | ||
1530 | |||
1531 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 69, 1, &data); | ||
1532 | if (ret < 0) | ||
1533 | return ret; | ||
1534 | sc->stats.phy.usattenuation = data / 10; | ||
1535 | |||
1536 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 68, 3, &data); | ||
1537 | if (ret < 0) | ||
1538 | return ret; | ||
1539 | sc->stats.phy.dsmargin = data / 2; | ||
1540 | |||
1541 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 69, 3, &data); | ||
1542 | if (ret < 0) | ||
1543 | return ret; | ||
1544 | sc->stats.phy.usmargin = data / 10; | ||
1545 | |||
1546 | return 0; | ||
1547 | } | ||
1548 | |||
1549 | static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | ||
1550 | { | ||
1551 | char file_arr[] = "CMVxy.bin"; | ||
1025 | char *file; | 1552 | char *file; |
1026 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1027 | 1553 | ||
1554 | /* set proper name corresponding modem version and line type */ | ||
1028 | if (cmv_file[sc->modem_index] == NULL) { | 1555 | if (cmv_file[sc->modem_index] == NULL) { |
1029 | if (UEA_CHIP_VERSION(sc) == ADI930) | 1556 | if (UEA_CHIP_VERSION(sc) == ADI930) |
1030 | file = (IS_ISDN(sc->usb_dev)) ? "CMV9i.bin" : "CMV9p.bin"; | 1557 | file_arr[3] = '9'; |
1558 | else if (UEA_CHIP_VERSION(sc) == EAGLE_IV) | ||
1559 | file_arr[3] = '4'; | ||
1031 | else | 1560 | else |
1032 | file = (IS_ISDN(sc->usb_dev)) ? "CMVei.bin" : "CMVep.bin"; | 1561 | file_arr[3] = 'e'; |
1562 | |||
1563 | file_arr[4] = IS_ISDN(sc) ? 'i' : 'p'; | ||
1564 | file = file_arr; | ||
1033 | } else | 1565 | } else |
1034 | file = cmv_file[sc->modem_index]; | 1566 | file = cmv_file[sc->modem_index]; |
1035 | 1567 | ||
1036 | strcpy(cmv_name, FW_DIR); | 1568 | strcpy(cmv_name, FW_DIR); |
1037 | strlcat(cmv_name, file, sizeof(cmv_name)); | 1569 | strlcat(cmv_name, file, FIRMWARE_NAME_MAX); |
1570 | if (ver == 2) | ||
1571 | strlcat(cmv_name, ".v2", FIRMWARE_NAME_MAX); | ||
1572 | } | ||
1573 | |||
1574 | static int request_cmvs_old(struct uea_softc *sc, | ||
1575 | void **cmvs, const struct firmware **fw) | ||
1576 | { | ||
1577 | int ret, size; | ||
1578 | u8 *data; | ||
1579 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1038 | 1580 | ||
1581 | cmvs_file_name(sc, cmv_name, 1); | ||
1039 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); | 1582 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); |
1040 | if (ret < 0) { | 1583 | if (ret < 0) { |
1041 | uea_err(INS_TO_USBDEV(sc), | 1584 | uea_err(INS_TO_USBDEV(sc), |
@@ -1045,16 +1588,197 @@ static int request_cmvs(struct uea_softc *sc, | |||
1045 | } | 1588 | } |
1046 | 1589 | ||
1047 | data = (u8 *) (*fw)->data; | 1590 | data = (u8 *) (*fw)->data; |
1048 | size = *data * sizeof(struct uea_cmvs) + 1; | 1591 | size = (*fw)->size; |
1049 | if (size != (*fw)->size) { | 1592 | if (size < 1) |
1050 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", | 1593 | goto err_fw_corrupted; |
1051 | cmv_name); | 1594 | |
1052 | release_firmware(*fw); | 1595 | if (size != *data * sizeof(struct uea_cmvs_v1) + 1) |
1053 | return -EILSEQ; | 1596 | goto err_fw_corrupted; |
1597 | |||
1598 | *cmvs = (void *)(data + 1); | ||
1599 | return *data; | ||
1600 | |||
1601 | err_fw_corrupted: | ||
1602 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", cmv_name); | ||
1603 | release_firmware(*fw); | ||
1604 | return -EILSEQ; | ||
1605 | } | ||
1606 | |||
1607 | static int request_cmvs(struct uea_softc *sc, | ||
1608 | void **cmvs, const struct firmware **fw, int *ver) | ||
1609 | { | ||
1610 | int ret, size; | ||
1611 | u32 crc; | ||
1612 | u8 *data; | ||
1613 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1614 | |||
1615 | cmvs_file_name(sc, cmv_name, 2); | ||
1616 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); | ||
1617 | if (ret < 0) { | ||
1618 | /* if caller can handle old version, try to provide it */ | ||
1619 | if (*ver == 1) { | ||
1620 | uea_warn(INS_TO_USBDEV(sc), "requesting firmware %s failed, " | ||
1621 | "try to get older cmvs\n", cmv_name); | ||
1622 | return request_cmvs_old(sc, cmvs, fw); | ||
1623 | } | ||
1624 | uea_err(INS_TO_USBDEV(sc), | ||
1625 | "requesting firmware %s failed with error %d\n", | ||
1626 | cmv_name, ret); | ||
1627 | return ret; | ||
1628 | } | ||
1629 | |||
1630 | size = (*fw)->size; | ||
1631 | data = (u8 *) (*fw)->data; | ||
1632 | if (size < 4 || strncmp(data, "cmv2", 4) != 0) { | ||
1633 | if (*ver == 1) { | ||
1634 | uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted, " | ||
1635 | "try to get older cmvs\n", cmv_name); | ||
1636 | release_firmware(*fw); | ||
1637 | return request_cmvs_old(sc, cmvs, fw); | ||
1638 | } | ||
1639 | goto err_fw_corrupted; | ||
1054 | } | 1640 | } |
1055 | 1641 | ||
1056 | *cmvs = (struct uea_cmvs *)(data + 1); | 1642 | *ver = 2; |
1643 | |||
1644 | data += 4; | ||
1645 | size -= 4; | ||
1646 | if (size < 5) | ||
1647 | goto err_fw_corrupted; | ||
1648 | |||
1649 | crc = FW_GET_LONG(data); | ||
1650 | data += 4; | ||
1651 | size -= 4; | ||
1652 | if (crc32_be(0, data, size) != crc) | ||
1653 | goto err_fw_corrupted; | ||
1654 | |||
1655 | if (size != *data * sizeof(struct uea_cmvs_v2) + 1) | ||
1656 | goto err_fw_corrupted; | ||
1657 | |||
1658 | *cmvs = (void *) (data + 1); | ||
1057 | return *data; | 1659 | return *data; |
1660 | |||
1661 | err_fw_corrupted: | ||
1662 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", cmv_name); | ||
1663 | release_firmware(*fw); | ||
1664 | return -EILSEQ; | ||
1665 | } | ||
1666 | |||
1667 | static int uea_send_cmvs_e1(struct uea_softc *sc) | ||
1668 | { | ||
1669 | int i, ret, len; | ||
1670 | void *cmvs_ptr; | ||
1671 | const struct firmware *cmvs_fw; | ||
1672 | int ver = 1; // we can handle v1 cmv firmware version; | ||
1673 | |||
1674 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | ||
1675 | ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 1); | ||
1676 | if (ret < 0) | ||
1677 | return ret; | ||
1678 | |||
1679 | /* Dump firmware version */ | ||
1680 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 10, &sc->stats.phy.firmid); | ||
1681 | if (ret < 0) | ||
1682 | return ret; | ||
1683 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1684 | sc->stats.phy.firmid); | ||
1685 | |||
1686 | /* get options */ | ||
1687 | ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver); | ||
1688 | if (ret < 0) | ||
1689 | return ret; | ||
1690 | |||
1691 | /* send options */ | ||
1692 | if (ver == 1) { | ||
1693 | struct uea_cmvs_v1 *cmvs_v1 = cmvs_ptr; | ||
1694 | |||
1695 | uea_warn(INS_TO_USBDEV(sc), "use deprecated cmvs version, " | ||
1696 | "please update your firmware\n"); | ||
1697 | |||
1698 | for (i = 0; i < len; i++) { | ||
1699 | ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v1[i].address), | ||
1700 | FW_GET_WORD(&cmvs_v1[i].offset), | ||
1701 | FW_GET_LONG(&cmvs_v1[i].data)); | ||
1702 | if (ret < 0) | ||
1703 | goto out; | ||
1704 | } | ||
1705 | } else if (ver == 2) { | ||
1706 | struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr; | ||
1707 | |||
1708 | for (i = 0; i < len; i++) { | ||
1709 | ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v2[i].address), | ||
1710 | (u16) FW_GET_LONG(&cmvs_v2[i].offset), | ||
1711 | FW_GET_LONG(&cmvs_v2[i].data)); | ||
1712 | if (ret < 0) | ||
1713 | goto out; | ||
1714 | } | ||
1715 | } else { | ||
1716 | /* This realy should not happen */ | ||
1717 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | ||
1718 | goto out; | ||
1719 | } | ||
1720 | |||
1721 | /* Enter in R-ACT-REQ */ | ||
1722 | ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 2); | ||
1723 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1724 | uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n"); | ||
1725 | out: | ||
1726 | release_firmware(cmvs_fw); | ||
1727 | return ret; | ||
1728 | } | ||
1729 | |||
1730 | static int uea_send_cmvs_e4(struct uea_softc *sc) | ||
1731 | { | ||
1732 | int i, ret, len; | ||
1733 | void *cmvs_ptr; | ||
1734 | const struct firmware *cmvs_fw; | ||
1735 | int ver = 2; // we can only handle v2 cmv firmware version; | ||
1736 | |||
1737 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | ||
1738 | ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 1); | ||
1739 | if (ret < 0) | ||
1740 | return ret; | ||
1741 | |||
1742 | /* Dump firmware version */ | ||
1743 | /* XXX don't read the 3th byte as it is always 6 */ | ||
1744 | ret = uea_read_cmv_e4(sc, 2, E4_SA_INFO, 55, 0, &sc->stats.phy.firmid); | ||
1745 | if (ret < 0) | ||
1746 | return ret; | ||
1747 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1748 | sc->stats.phy.firmid); | ||
1749 | |||
1750 | |||
1751 | /* get options */ | ||
1752 | ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver); | ||
1753 | if (ret < 0) | ||
1754 | return ret; | ||
1755 | |||
1756 | /* send options */ | ||
1757 | if (ver == 2) { | ||
1758 | struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr; | ||
1759 | |||
1760 | for (i = 0; i < len; i++) { | ||
1761 | ret = uea_write_cmv_e4(sc, 1, | ||
1762 | FW_GET_LONG(&cmvs_v2[i].group), | ||
1763 | FW_GET_LONG(&cmvs_v2[i].address), | ||
1764 | FW_GET_LONG(&cmvs_v2[i].offset), | ||
1765 | FW_GET_LONG(&cmvs_v2[i].data)); | ||
1766 | if (ret < 0) | ||
1767 | goto out; | ||
1768 | } | ||
1769 | } else { | ||
1770 | /* This realy should not happen */ | ||
1771 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | ||
1772 | goto out; | ||
1773 | } | ||
1774 | |||
1775 | /* Enter in R-ACT-REQ */ | ||
1776 | ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 2); | ||
1777 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1778 | uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n"); | ||
1779 | out: | ||
1780 | release_firmware(cmvs_fw); | ||
1781 | return ret; | ||
1058 | } | 1782 | } |
1059 | 1783 | ||
1060 | /* Start boot post firmware modem: | 1784 | /* Start boot post firmware modem: |
@@ -1066,9 +1790,7 @@ static int request_cmvs(struct uea_softc *sc, | |||
1066 | static int uea_start_reset(struct uea_softc *sc) | 1790 | static int uea_start_reset(struct uea_softc *sc) |
1067 | { | 1791 | { |
1068 | u16 zero = 0; /* ;-) */ | 1792 | u16 zero = 0; /* ;-) */ |
1069 | int i, len, ret; | 1793 | int ret; |
1070 | struct uea_cmvs *cmvs; | ||
1071 | const struct firmware *cmvs_fw; | ||
1072 | 1794 | ||
1073 | uea_enters(INS_TO_USBDEV(sc)); | 1795 | uea_enters(INS_TO_USBDEV(sc)); |
1074 | uea_info(INS_TO_USBDEV(sc), "(re)booting started\n"); | 1796 | uea_info(INS_TO_USBDEV(sc), "(re)booting started\n"); |
@@ -1093,25 +1815,36 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1093 | uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL); | 1815 | uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL); |
1094 | 1816 | ||
1095 | /* original driver use 200ms, but windows driver use 100ms */ | 1817 | /* original driver use 200ms, but windows driver use 100ms */ |
1096 | msleep(100); | 1818 | ret = uea_wait(sc, 0, msecs_to_jiffies(100)); |
1819 | if (ret < 0) | ||
1820 | return ret; | ||
1097 | 1821 | ||
1098 | /* leave reset mode */ | 1822 | /* leave reset mode */ |
1099 | uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL); | 1823 | uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL); |
1100 | 1824 | ||
1101 | /* clear tx and rx mailboxes */ | 1825 | if (UEA_CHIP_VERSION(sc) != EAGLE_IV) { |
1102 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero); | 1826 | /* clear tx and rx mailboxes */ |
1103 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero); | 1827 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero); |
1104 | uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero); | 1828 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero); |
1829 | uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero); | ||
1830 | } | ||
1831 | |||
1832 | ret = uea_wait(sc, 0, msecs_to_jiffies(1000)); | ||
1833 | if (ret < 0) | ||
1834 | return ret; | ||
1835 | |||
1836 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) | ||
1837 | sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1); | ||
1838 | else | ||
1839 | sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY); | ||
1105 | 1840 | ||
1106 | msleep(1000); | ||
1107 | sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY); | ||
1108 | /* demask interrupt */ | 1841 | /* demask interrupt */ |
1109 | sc->booting = 0; | 1842 | sc->booting = 0; |
1110 | 1843 | ||
1111 | /* start loading DSP */ | 1844 | /* start loading DSP */ |
1112 | sc->pageno = 0; | 1845 | sc->pageno = 0; |
1113 | sc->ovl = 0; | 1846 | sc->ovl = 0; |
1114 | schedule_work(&sc->task); | 1847 | queue_work(sc->work_q, &sc->task); |
1115 | 1848 | ||
1116 | /* wait for modem ready CMV */ | 1849 | /* wait for modem ready CMV */ |
1117 | ret = wait_cmv_ack(sc); | 1850 | ret = wait_cmv_ack(sc); |
@@ -1120,38 +1853,10 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1120 | 1853 | ||
1121 | uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n"); | 1854 | uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n"); |
1122 | 1855 | ||
1123 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | 1856 | ret = sc->send_cmvs(sc); |
1124 | ret = uea_write_cmv(sc, SA_CNTL, 0, 1); | ||
1125 | if (ret < 0) | ||
1126 | return ret; | ||
1127 | |||
1128 | /* Dump firmware version */ | ||
1129 | ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid); | ||
1130 | if (ret < 0) | 1857 | if (ret < 0) |
1131 | return ret; | 1858 | return ret; |
1132 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1133 | sc->stats.phy.firmid); | ||
1134 | 1859 | ||
1135 | /* get options */ | ||
1136 | ret = len = request_cmvs(sc, &cmvs, &cmvs_fw); | ||
1137 | if (ret < 0) | ||
1138 | return ret; | ||
1139 | |||
1140 | /* send options */ | ||
1141 | for (i = 0; i < len; i++) { | ||
1142 | ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address), | ||
1143 | FW_GET_WORD(&cmvs[i].offset), | ||
1144 | FW_GET_LONG(&cmvs[i].data)); | ||
1145 | if (ret < 0) | ||
1146 | goto out; | ||
1147 | } | ||
1148 | /* Enter in R-ACT-REQ */ | ||
1149 | ret = uea_write_cmv(sc, SA_CNTL, 0, 2); | ||
1150 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1151 | uea_info(INS_TO_USBDEV(sc), "Modem started, " | ||
1152 | "waiting synchronization\n"); | ||
1153 | out: | ||
1154 | release_firmware(cmvs_fw); | ||
1155 | sc->reset = 0; | 1860 | sc->reset = 0; |
1156 | uea_leaves(INS_TO_USBDEV(sc)); | 1861 | uea_leaves(INS_TO_USBDEV(sc)); |
1157 | return ret; | 1862 | return ret; |
@@ -1174,12 +1879,10 @@ static int uea_kthread(void *data) | |||
1174 | if (ret < 0 || sc->reset) | 1879 | if (ret < 0 || sc->reset) |
1175 | ret = uea_start_reset(sc); | 1880 | ret = uea_start_reset(sc); |
1176 | if (!ret) | 1881 | if (!ret) |
1177 | ret = uea_stat(sc); | 1882 | ret = sc->stat(sc); |
1178 | if (ret != -EAGAIN) | 1883 | if (ret != -EAGAIN) |
1179 | msleep_interruptible(1000); | 1884 | uea_wait(sc, 0, msecs_to_jiffies(1000)); |
1180 | if (try_to_freeze()) | 1885 | try_to_freeze(); |
1181 | uea_err(INS_TO_USBDEV(sc), "suspend/resume not supported, " | ||
1182 | "please unplug/replug your modem\n"); | ||
1183 | } | 1886 | } |
1184 | uea_leaves(INS_TO_USBDEV(sc)); | 1887 | uea_leaves(INS_TO_USBDEV(sc)); |
1185 | return ret; | 1888 | return ret; |
@@ -1234,7 +1937,6 @@ static int load_XILINX_firmware(struct uea_softc *sc) | |||
1234 | if (ret < 0) | 1937 | if (ret < 0) |
1235 | uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret); | 1938 | uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret); |
1236 | 1939 | ||
1237 | |||
1238 | err1: | 1940 | err1: |
1239 | release_firmware(fw_entry); | 1941 | release_firmware(fw_entry); |
1240 | err0: | 1942 | err0: |
@@ -1243,40 +1945,41 @@ err0: | |||
1243 | } | 1945 | } |
1244 | 1946 | ||
1245 | /* The modem send us an ack. First with check if it right */ | 1947 | /* The modem send us an ack. First with check if it right */ |
1246 | static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) | 1948 | static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr) |
1247 | { | 1949 | { |
1950 | struct cmv_dsc_e1 *dsc = &sc->cmv_dsc.e1; | ||
1951 | struct cmv_e1 *cmv = &intr->u.e1.s2.cmv; | ||
1952 | |||
1248 | uea_enters(INS_TO_USBDEV(sc)); | 1953 | uea_enters(INS_TO_USBDEV(sc)); |
1249 | if (le16_to_cpu(cmv->wPreamble) != PREAMBLE) | 1954 | if (le16_to_cpu(cmv->wPreamble) != E1_PREAMBLE) |
1250 | goto bad1; | 1955 | goto bad1; |
1251 | 1956 | ||
1252 | if (cmv->bDirection != MODEMTOHOST) | 1957 | if (cmv->bDirection != E1_MODEMTOHOST) |
1253 | goto bad1; | 1958 | goto bad1; |
1254 | 1959 | ||
1255 | /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to | 1960 | /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to |
1256 | * the first MEMACESS cmv. Ignore it... | 1961 | * the first MEMACESS cmv. Ignore it... |
1257 | */ | 1962 | */ |
1258 | if (cmv->bFunction != sc->cmv_function) { | 1963 | if (cmv->bFunction != dsc->function) { |
1259 | if (UEA_CHIP_VERSION(sc) == ADI930 | 1964 | if (UEA_CHIP_VERSION(sc) == ADI930 |
1260 | && cmv->bFunction == MAKEFUNCTION(2, 2)) { | 1965 | && cmv->bFunction == E1_MAKEFUNCTION(2, 2)) { |
1261 | cmv->wIndex = cpu_to_le16(sc->cmv_idx); | 1966 | cmv->wIndex = cpu_to_le16(dsc->idx); |
1262 | put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress); | 1967 | put_unaligned(cpu_to_le32(dsc->address), &cmv->dwSymbolicAddress); |
1263 | cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset); | 1968 | cmv->wOffsetAddress = cpu_to_le16(dsc->offset); |
1264 | } | 1969 | } else |
1265 | else | ||
1266 | goto bad2; | 1970 | goto bad2; |
1267 | } | 1971 | } |
1268 | 1972 | ||
1269 | if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) { | 1973 | if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY)) { |
1270 | wake_up_cmv_ack(sc); | 1974 | wake_up_cmv_ack(sc); |
1271 | uea_leaves(INS_TO_USBDEV(sc)); | 1975 | uea_leaves(INS_TO_USBDEV(sc)); |
1272 | return; | 1976 | return; |
1273 | } | 1977 | } |
1274 | 1978 | ||
1275 | /* in case of MEMACCESS */ | 1979 | /* in case of MEMACCESS */ |
1276 | if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx || | 1980 | if (le16_to_cpu(cmv->wIndex) != dsc->idx || |
1277 | le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != | 1981 | le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != dsc->address || |
1278 | sc->cmv_address | 1982 | le16_to_cpu(cmv->wOffsetAddress) != dsc->offset) |
1279 | || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset) | ||
1280 | goto bad2; | 1983 | goto bad2; |
1281 | 1984 | ||
1282 | sc->data = le32_to_cpu(get_unaligned(&cmv->dwData)); | 1985 | sc->data = le32_to_cpu(get_unaligned(&cmv->dwData)); |
@@ -1289,8 +1992,8 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) | |||
1289 | bad2: | 1992 | bad2: |
1290 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," | 1993 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," |
1291 | "Function : %d, Subfunction : %d\n", | 1994 | "Function : %d, Subfunction : %d\n", |
1292 | FUNCTION_TYPE(cmv->bFunction), | 1995 | E1_FUNCTION_TYPE(cmv->bFunction), |
1293 | FUNCTION_SUBTYPE(cmv->bFunction)); | 1996 | E1_FUNCTION_SUBTYPE(cmv->bFunction)); |
1294 | uea_leaves(INS_TO_USBDEV(sc)); | 1997 | uea_leaves(INS_TO_USBDEV(sc)); |
1295 | return; | 1998 | return; |
1296 | 1999 | ||
@@ -1301,6 +2004,61 @@ bad1: | |||
1301 | uea_leaves(INS_TO_USBDEV(sc)); | 2004 | uea_leaves(INS_TO_USBDEV(sc)); |
1302 | } | 2005 | } |
1303 | 2006 | ||
2007 | /* The modem send us an ack. First with check if it right */ | ||
2008 | static void uea_dispatch_cmv_e4(struct uea_softc *sc, struct intr_pkt *intr) | ||
2009 | { | ||
2010 | struct cmv_dsc_e4 *dsc = &sc->cmv_dsc.e4; | ||
2011 | struct cmv_e4 *cmv = &intr->u.e4.s2.cmv; | ||
2012 | |||
2013 | uea_enters(INS_TO_USBDEV(sc)); | ||
2014 | uea_dbg(INS_TO_USBDEV(sc), "cmv %x %x %x %x %x %x\n", | ||
2015 | be16_to_cpu(cmv->wGroup), be16_to_cpu(cmv->wFunction), | ||
2016 | be16_to_cpu(cmv->wOffset), be16_to_cpu(cmv->wAddress), | ||
2017 | be32_to_cpu(cmv->dwData[0]), be32_to_cpu(cmv->dwData[1])); | ||
2018 | |||
2019 | if (be16_to_cpu(cmv->wFunction) != dsc->function) | ||
2020 | goto bad2; | ||
2021 | |||
2022 | if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1)) { | ||
2023 | wake_up_cmv_ack(sc); | ||
2024 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2025 | return; | ||
2026 | } | ||
2027 | |||
2028 | /* in case of MEMACCESS */ | ||
2029 | if (be16_to_cpu(cmv->wOffset) != dsc->offset || | ||
2030 | be16_to_cpu(cmv->wGroup) != dsc->group || | ||
2031 | be16_to_cpu(cmv->wAddress) != dsc->address) | ||
2032 | goto bad2; | ||
2033 | |||
2034 | sc->data = be32_to_cpu(cmv->dwData[0]); | ||
2035 | sc->data1 = be32_to_cpu(cmv->dwData[1]); | ||
2036 | wake_up_cmv_ack(sc); | ||
2037 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2038 | return; | ||
2039 | |||
2040 | bad2: | ||
2041 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," | ||
2042 | "Function : %d, Subfunction : %d\n", | ||
2043 | E4_FUNCTION_TYPE(cmv->wFunction), | ||
2044 | E4_FUNCTION_SUBTYPE(cmv->wFunction)); | ||
2045 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2046 | return; | ||
2047 | } | ||
2048 | |||
2049 | static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *intr) | ||
2050 | { | ||
2051 | sc->pageno = intr->e1_bSwapPageNo; | ||
2052 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; | ||
2053 | queue_work(sc->work_q, &sc->task); | ||
2054 | } | ||
2055 | |||
2056 | static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr) | ||
2057 | { | ||
2058 | sc->pageno = intr->e4_bSwapPageNo; | ||
2059 | queue_work(sc->work_q, &sc->task); | ||
2060 | } | ||
2061 | |||
1304 | /* | 2062 | /* |
1305 | * interrupt handler | 2063 | * interrupt handler |
1306 | */ | 2064 | */ |
@@ -1326,13 +2084,11 @@ static void uea_intr(struct urb *urb) | |||
1326 | 2084 | ||
1327 | switch (le16_to_cpu(intr->wInterrupt)) { | 2085 | switch (le16_to_cpu(intr->wInterrupt)) { |
1328 | case INT_LOADSWAPPAGE: | 2086 | case INT_LOADSWAPPAGE: |
1329 | sc->pageno = intr->bSwapPageNo; | 2087 | sc->schedule_load_page(sc, intr); |
1330 | sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4; | ||
1331 | schedule_work(&sc->task); | ||
1332 | break; | 2088 | break; |
1333 | 2089 | ||
1334 | case INT_INCOMINGCMV: | 2090 | case INT_INCOMINGCMV: |
1335 | uea_dispatch_cmv(sc, &intr->u.s2.cmv); | 2091 | sc->dispatch_cmv(sc, intr); |
1336 | break; | 2092 | break; |
1337 | 2093 | ||
1338 | default: | 2094 | default: |
@@ -1349,35 +2105,55 @@ resubmit: | |||
1349 | */ | 2105 | */ |
1350 | static int uea_boot(struct uea_softc *sc) | 2106 | static int uea_boot(struct uea_softc *sc) |
1351 | { | 2107 | { |
1352 | int ret; | 2108 | int ret, size; |
1353 | struct intr_pkt *intr; | 2109 | struct intr_pkt *intr; |
1354 | 2110 | ||
1355 | uea_enters(INS_TO_USBDEV(sc)); | 2111 | uea_enters(INS_TO_USBDEV(sc)); |
1356 | 2112 | ||
1357 | INIT_WORK(&sc->task, uea_load_page); | 2113 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
2114 | size = E4_INTR_PKT_SIZE; | ||
2115 | sc->dispatch_cmv = uea_dispatch_cmv_e4; | ||
2116 | sc->schedule_load_page = uea_schedule_load_page_e4; | ||
2117 | sc->stat = uea_stat_e4; | ||
2118 | sc->send_cmvs = uea_send_cmvs_e4; | ||
2119 | INIT_WORK(&sc->task, uea_load_page_e4); | ||
2120 | } else { | ||
2121 | size = E1_INTR_PKT_SIZE; | ||
2122 | sc->dispatch_cmv = uea_dispatch_cmv_e1; | ||
2123 | sc->schedule_load_page = uea_schedule_load_page_e1; | ||
2124 | sc->stat = uea_stat_e1; | ||
2125 | sc->send_cmvs = uea_send_cmvs_e1; | ||
2126 | INIT_WORK(&sc->task, uea_load_page_e1); | ||
2127 | } | ||
2128 | |||
1358 | init_waitqueue_head(&sc->sync_q); | 2129 | init_waitqueue_head(&sc->sync_q); |
1359 | init_waitqueue_head(&sc->cmv_ack_wait); | 2130 | |
2131 | sc->work_q = create_workqueue("ueagle-dsp"); | ||
2132 | if (!sc->work_q) { | ||
2133 | uea_err(INS_TO_USBDEV(sc), "cannot allocate workqueue\n"); | ||
2134 | uea_leaves(INS_TO_USBDEV(sc)); | ||
2135 | return -ENOMEM; | ||
2136 | } | ||
1360 | 2137 | ||
1361 | if (UEA_CHIP_VERSION(sc) == ADI930) | 2138 | if (UEA_CHIP_VERSION(sc) == ADI930) |
1362 | load_XILINX_firmware(sc); | 2139 | load_XILINX_firmware(sc); |
1363 | 2140 | ||
1364 | intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL); | 2141 | intr = kmalloc(size, GFP_KERNEL); |
1365 | if (!intr) { | 2142 | if (!intr) { |
1366 | uea_err(INS_TO_USBDEV(sc), | 2143 | uea_err(INS_TO_USBDEV(sc), |
1367 | "cannot allocate interrupt package\n"); | 2144 | "cannot allocate interrupt package\n"); |
1368 | uea_leaves(INS_TO_USBDEV(sc)); | 2145 | goto err0; |
1369 | return -ENOMEM; | ||
1370 | } | 2146 | } |
1371 | 2147 | ||
1372 | sc->urb_int = usb_alloc_urb(0, GFP_KERNEL); | 2148 | sc->urb_int = usb_alloc_urb(0, GFP_KERNEL); |
1373 | if (!sc->urb_int) { | 2149 | if (!sc->urb_int) { |
1374 | uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n"); | 2150 | uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n"); |
1375 | goto err; | 2151 | goto err1; |
1376 | } | 2152 | } |
1377 | 2153 | ||
1378 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, | 2154 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, |
1379 | usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), | 2155 | usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), |
1380 | intr, INTR_PKT_SIZE, uea_intr, sc, | 2156 | intr, size, uea_intr, sc, |
1381 | sc->usb_dev->actconfig->interface[0]->altsetting[0]. | 2157 | sc->usb_dev->actconfig->interface[0]->altsetting[0]. |
1382 | endpoint[0].desc.bInterval); | 2158 | endpoint[0].desc.bInterval); |
1383 | 2159 | ||
@@ -1385,7 +2161,7 @@ static int uea_boot(struct uea_softc *sc) | |||
1385 | if (ret < 0) { | 2161 | if (ret < 0) { |
1386 | uea_err(INS_TO_USBDEV(sc), | 2162 | uea_err(INS_TO_USBDEV(sc), |
1387 | "urb submition failed with error %d\n", ret); | 2163 | "urb submition failed with error %d\n", ret); |
1388 | goto err; | 2164 | goto err1; |
1389 | } | 2165 | } |
1390 | 2166 | ||
1391 | sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); | 2167 | sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); |
@@ -1399,10 +2175,12 @@ static int uea_boot(struct uea_softc *sc) | |||
1399 | 2175 | ||
1400 | err2: | 2176 | err2: |
1401 | usb_kill_urb(sc->urb_int); | 2177 | usb_kill_urb(sc->urb_int); |
1402 | err: | 2178 | err1: |
1403 | usb_free_urb(sc->urb_int); | 2179 | usb_free_urb(sc->urb_int); |
1404 | sc->urb_int = NULL; | 2180 | sc->urb_int = NULL; |
1405 | kfree(intr); | 2181 | kfree(intr); |
2182 | err0: | ||
2183 | destroy_workqueue(sc->work_q); | ||
1406 | uea_leaves(INS_TO_USBDEV(sc)); | 2184 | uea_leaves(INS_TO_USBDEV(sc)); |
1407 | return -ENOMEM; | 2185 | return -ENOMEM; |
1408 | } | 2186 | } |
@@ -1417,15 +2195,15 @@ static void uea_stop(struct uea_softc *sc) | |||
1417 | ret = kthread_stop(sc->kthread); | 2195 | ret = kthread_stop(sc->kthread); |
1418 | uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); | 2196 | uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret); |
1419 | 2197 | ||
1420 | /* stop any pending boot process */ | ||
1421 | flush_scheduled_work(); | ||
1422 | |||
1423 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); | 2198 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL); |
1424 | 2199 | ||
1425 | usb_kill_urb(sc->urb_int); | 2200 | usb_kill_urb(sc->urb_int); |
1426 | kfree(sc->urb_int->transfer_buffer); | 2201 | kfree(sc->urb_int->transfer_buffer); |
1427 | usb_free_urb(sc->urb_int); | 2202 | usb_free_urb(sc->urb_int); |
1428 | 2203 | ||
2204 | /* stop any pending boot process, when no one can schedule work */ | ||
2205 | destroy_workqueue(sc->work_q); | ||
2206 | |||
1429 | if (sc->dsp_firm) | 2207 | if (sc->dsp_firm) |
1430 | release_firmware(sc->dsp_firm); | 2208 | release_firmware(sc->dsp_firm); |
1431 | uea_leaves(INS_TO_USBDEV(sc)); | 2209 | uea_leaves(INS_TO_USBDEV(sc)); |
@@ -1487,6 +2265,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1487 | char *buf) | 2265 | char *buf) |
1488 | { | 2266 | { |
1489 | int ret = -ENODEV; | 2267 | int ret = -ENODEV; |
2268 | int modem_state; | ||
1490 | struct uea_softc *sc; | 2269 | struct uea_softc *sc; |
1491 | 2270 | ||
1492 | mutex_lock(&uea_mutex); | 2271 | mutex_lock(&uea_mutex); |
@@ -1494,7 +2273,34 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1494 | if (!sc) | 2273 | if (!sc) |
1495 | goto out; | 2274 | goto out; |
1496 | 2275 | ||
1497 | switch (GET_STATUS(sc->stats.phy.state)) { | 2276 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
2277 | switch (sc->stats.phy.state) { | ||
2278 | case 0x0: /* not yet synchronized */ | ||
2279 | case 0x1: | ||
2280 | case 0x3: | ||
2281 | case 0x4: | ||
2282 | modem_state = 0; | ||
2283 | break; | ||
2284 | case 0x5: /* initialization */ | ||
2285 | case 0x6: | ||
2286 | case 0x9: | ||
2287 | case 0xa: | ||
2288 | modem_state = 1; | ||
2289 | break; | ||
2290 | case 0x7: /* operational */ | ||
2291 | modem_state = 2; | ||
2292 | break; | ||
2293 | case 0x2: /* fail ... */ | ||
2294 | modem_state = 3; | ||
2295 | break; | ||
2296 | default: /* unknown */ | ||
2297 | modem_state = 4; | ||
2298 | break; | ||
2299 | } | ||
2300 | } else | ||
2301 | modem_state = GET_STATUS(sc->stats.phy.state); | ||
2302 | |||
2303 | switch (modem_state) { | ||
1498 | case 0: | 2304 | case 0: |
1499 | ret = sprintf(buf, "Modem is booting\n"); | 2305 | ret = sprintf(buf, "Modem is booting\n"); |
1500 | break; | 2306 | break; |
@@ -1504,9 +2310,12 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1504 | case 2: | 2310 | case 2: |
1505 | ret = sprintf(buf, "Modem is operational\n"); | 2311 | ret = sprintf(buf, "Modem is operational\n"); |
1506 | break; | 2312 | break; |
1507 | default: | 2313 | case 3: |
1508 | ret = sprintf(buf, "Modem synchronization failed\n"); | 2314 | ret = sprintf(buf, "Modem synchronization failed\n"); |
1509 | break; | 2315 | break; |
2316 | default: | ||
2317 | ret = sprintf(buf, "Modem state is unknown\n"); | ||
2318 | break; | ||
1510 | } | 2319 | } |
1511 | out: | 2320 | out: |
1512 | mutex_unlock(&uea_mutex); | 2321 | mutex_unlock(&uea_mutex); |
@@ -1520,18 +2329,26 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr, | |||
1520 | { | 2329 | { |
1521 | int ret = -ENODEV; | 2330 | int ret = -ENODEV; |
1522 | struct uea_softc *sc; | 2331 | struct uea_softc *sc; |
2332 | char *delin = "GOOD"; | ||
1523 | 2333 | ||
1524 | mutex_lock(&uea_mutex); | 2334 | mutex_lock(&uea_mutex); |
1525 | sc = dev_to_uea(dev); | 2335 | sc = dev_to_uea(dev); |
1526 | if (!sc) | 2336 | if (!sc) |
1527 | goto out; | 2337 | goto out; |
1528 | 2338 | ||
1529 | if (sc->stats.phy.flags & 0x0C00) | 2339 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
1530 | ret = sprintf(buf, "ERROR\n"); | 2340 | if (sc->stats.phy.flags & 0x4000) |
1531 | else if (sc->stats.phy.flags & 0x0030) | 2341 | delin = "RESET"; |
1532 | ret = sprintf(buf, "LOSS\n"); | 2342 | else if (sc->stats.phy.flags & 0x0001) |
1533 | else | 2343 | delin = "LOSS"; |
1534 | ret = sprintf(buf, "GOOD\n"); | 2344 | } else { |
2345 | if (sc->stats.phy.flags & 0x0C00) | ||
2346 | delin = "ERROR"; | ||
2347 | else if (sc->stats.phy.flags & 0x0030) | ||
2348 | delin = "LOSS"; | ||
2349 | } | ||
2350 | |||
2351 | ret = sprintf(buf, "%s\n", delin); | ||
1535 | out: | 2352 | out: |
1536 | mutex_unlock(&uea_mutex); | 2353 | mutex_unlock(&uea_mutex); |
1537 | return ret; | 2354 | return ret; |
@@ -1662,6 +2479,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, | |||
1662 | struct usb_device *usb = interface_to_usbdev(intf); | 2479 | struct usb_device *usb = interface_to_usbdev(intf); |
1663 | struct uea_softc *sc; | 2480 | struct uea_softc *sc; |
1664 | int ret, ifnum = intf->altsetting->desc.bInterfaceNumber; | 2481 | int ret, ifnum = intf->altsetting->desc.bInterfaceNumber; |
2482 | unsigned int alt; | ||
1665 | 2483 | ||
1666 | uea_enters(usb); | 2484 | uea_enters(usb); |
1667 | 2485 | ||
@@ -1696,22 +2514,29 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, | |||
1696 | sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0; | 2514 | sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0; |
1697 | sc->driver_info = id->driver_info; | 2515 | sc->driver_info = id->driver_info; |
1698 | 2516 | ||
1699 | /* ADI930 don't support iso */ | 2517 | /* first try to use module parameter */ |
1700 | if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) { | 2518 | if (annex[sc->modem_index] == 1) |
1701 | int i; | 2519 | sc->annex = ANNEXA; |
1702 | 2520 | else if (annex[sc->modem_index] == 2) | |
1703 | /* try set fastest alternate for inbound traffic interface */ | 2521 | sc->annex = ANNEXB; |
1704 | for (i = FASTEST_ISO_INTF; i > 0; i--) | 2522 | /* try to autodetect annex */ |
1705 | if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0) | 2523 | else if (sc->driver_info & AUTO_ANNEX_A) |
1706 | break; | 2524 | sc->annex = ANNEXA; |
2525 | else if (sc->driver_info & AUTO_ANNEX_B) | ||
2526 | sc->annex = ANNEXB; | ||
2527 | else | ||
2528 | sc->annex = (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)?ANNEXB:ANNEXA; | ||
1707 | 2529 | ||
1708 | if (i > 0) { | 2530 | alt = altsetting[sc->modem_index]; |
1709 | uea_dbg(usb, "set alternate %d for 2 interface\n", i); | 2531 | /* ADI930 don't support iso */ |
2532 | if (UEA_CHIP_VERSION(id) != ADI930 && alt > 0) { | ||
2533 | if (alt <= 8 && usb_set_interface(usb, UEA_DS_IFACE_NO, alt) == 0) { | ||
2534 | uea_dbg(usb, "set alternate %u for 2 interface\n", alt); | ||
1710 | uea_info(usb, "using iso mode\n"); | 2535 | uea_info(usb, "using iso mode\n"); |
1711 | usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ; | 2536 | usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ; |
1712 | } else { | 2537 | } else { |
1713 | uea_err(usb, "setting any alternate failed for " | 2538 | uea_err(usb, "setting alternate %u failed for " |
1714 | "2 interface, using bulk mode\n"); | 2539 | "2 interface, using bulk mode\n", alt); |
1715 | } | 2540 | } |
1716 | } | 2541 | } |
1717 | 2542 | ||
@@ -1757,10 +2582,11 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1757 | struct usb_device *usb = interface_to_usbdev(intf); | 2582 | struct usb_device *usb = interface_to_usbdev(intf); |
1758 | 2583 | ||
1759 | uea_enters(usb); | 2584 | uea_enters(usb); |
1760 | uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s %s\n", | 2585 | uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n", |
1761 | le16_to_cpu(usb->descriptor.idVendor), | 2586 | le16_to_cpu(usb->descriptor.idVendor), |
1762 | le16_to_cpu(usb->descriptor.idProduct), | 2587 | le16_to_cpu(usb->descriptor.idProduct), |
1763 | chip_name[UEA_CHIP_VERSION(id)], IS_ISDN(usb)?"isdn":"pots"); | 2588 | le16_to_cpu(usb->descriptor.bcdDevice), |
2589 | chip_name[UEA_CHIP_VERSION(id)]); | ||
1764 | 2590 | ||
1765 | usb_reset_device(usb); | 2591 | usb_reset_device(usb); |
1766 | 2592 | ||
@@ -1793,24 +2619,40 @@ static void uea_disconnect(struct usb_interface *intf) | |||
1793 | * List of supported VID/PID | 2619 | * List of supported VID/PID |
1794 | */ | 2620 | */ |
1795 | static const struct usb_device_id uea_ids[] = { | 2621 | static const struct usb_device_id uea_ids[] = { |
2622 | {USB_DEVICE(ANALOG_VID, ADI930_PID_PREFIRM), .driver_info = ADI930 | PREFIRM}, | ||
2623 | {USB_DEVICE(ANALOG_VID, ADI930_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM}, | ||
2624 | {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | ||
2625 | {USB_DEVICE(ANALOG_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, | ||
2626 | {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | ||
2627 | {USB_DEVICE(ANALOG_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, | ||
2628 | {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | ||
2629 | {USB_DEVICE(ANALOG_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, | ||
2630 | {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM}, | ||
2631 | {USB_DEVICE(ANALOG_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM}, | ||
2632 | {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PREFIRM), .driver_info = EAGLE_IV | PREFIRM}, | ||
2633 | {USB_DEVICE(ANALOG_VID, EAGLE_IV_PID_PSTFIRM), .driver_info = EAGLE_IV | PSTFIRM}, | ||
2634 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | ||
2635 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A}, | ||
2636 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | ||
2637 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_I_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B}, | ||
2638 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | ||
2639 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_A_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_A}, | ||
2640 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | ||
2641 | {USB_DEVICE(DEVOLO_VID, DEVOLO_EAGLE_II_B_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM | AUTO_ANNEX_B}, | ||
1796 | {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM}, | 2642 | {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM}, |
1797 | {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM}, | 2643 | {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM}, |
1798 | {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | 2644 | {USB_DEVICE(ELSA_VID, ELSA_PID_A_PREFIRM), .driver_info = ADI930 | PREFIRM}, |
1799 | {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, | 2645 | {USB_DEVICE(ELSA_VID, ELSA_PID_A_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_A}, |
1800 | {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | 2646 | {USB_DEVICE(ELSA_VID, ELSA_PID_B_PREFIRM), .driver_info = ADI930 | PREFIRM}, |
1801 | {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, | 2647 | {USB_DEVICE(ELSA_VID, ELSA_PID_B_PSTFIRM), .driver_info = ADI930 | PSTFIRM | AUTO_ANNEX_B}, |
1802 | {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM}, | ||
1803 | {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, | ||
1804 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM}, | ||
1805 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM}, | ||
1806 | {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | 2648 | {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, |
1807 | {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, | 2649 | {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A}, |
1808 | {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | 2650 | {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, |
1809 | {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, | 2651 | {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B}, |
1810 | {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, | 2652 | {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, |
1811 | {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM}, | 2653 | {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_A}, |
1812 | {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, | 2654 | {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM}, |
1813 | {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM}, | 2655 | {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM | AUTO_ANNEX_B}, |
1814 | {} | 2656 | {} |
1815 | }; | 2657 | }; |
1816 | 2658 | ||
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 5192cd9356de..ad632f2d6f94 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal) | 28 | * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal) |
29 | * v0.13 - alloc space for statusbuf (<status> not on stack); | 29 | * v0.13 - alloc space for statusbuf (<status> not on stack); |
30 | * use usb_buffer_alloc() for read buf & write buf; | 30 | * use usb_buffer_alloc() for read buf & write buf; |
31 | * none - Maintained in Linux kernel after v0.13 | ||
31 | */ | 32 | */ |
32 | 33 | ||
33 | /* | 34 | /* |
@@ -69,7 +70,6 @@ | |||
69 | #define USBLP_DEVICE_ID_SIZE 1024 | 70 | #define USBLP_DEVICE_ID_SIZE 1024 |
70 | 71 | ||
71 | /* ioctls: */ | 72 | /* ioctls: */ |
72 | #define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */ | ||
73 | #define IOCNR_GET_DEVICE_ID 1 | 73 | #define IOCNR_GET_DEVICE_ID 1 |
74 | #define IOCNR_GET_PROTOCOLS 2 | 74 | #define IOCNR_GET_PROTOCOLS 2 |
75 | #define IOCNR_SET_PROTOCOL 3 | 75 | #define IOCNR_SET_PROTOCOL 3 |
@@ -115,7 +115,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H | |||
115 | #define USBLP_MINORS 16 | 115 | #define USBLP_MINORS 16 |
116 | #define USBLP_MINOR_BASE 0 | 116 | #define USBLP_MINOR_BASE 0 |
117 | 117 | ||
118 | #define USBLP_WRITE_TIMEOUT (5000) /* 5 seconds */ | 118 | #define USBLP_CTL_TIMEOUT 5000 /* 5 seconds */ |
119 | 119 | ||
120 | #define USBLP_FIRST_PROTOCOL 1 | 120 | #define USBLP_FIRST_PROTOCOL 1 |
121 | #define USBLP_LAST_PROTOCOL 3 | 121 | #define USBLP_LAST_PROTOCOL 3 |
@@ -159,10 +159,12 @@ struct usblp { | |||
159 | int wstatus; /* bytes written or error */ | 159 | int wstatus; /* bytes written or error */ |
160 | int rstatus; /* bytes ready or error */ | 160 | int rstatus; /* bytes ready or error */ |
161 | unsigned int quirks; /* quirks flags */ | 161 | unsigned int quirks; /* quirks flags */ |
162 | unsigned int flags; /* mode flags */ | ||
162 | unsigned char used; /* True if open */ | 163 | unsigned char used; /* True if open */ |
163 | unsigned char present; /* True if not disconnected */ | 164 | unsigned char present; /* True if not disconnected */ |
164 | unsigned char bidir; /* interface is bidirectional */ | 165 | unsigned char bidir; /* interface is bidirectional */ |
165 | unsigned char sleeping; /* interface is suspended */ | 166 | unsigned char sleeping; /* interface is suspended */ |
167 | unsigned char no_paper; /* Paper Out happened */ | ||
166 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ | 168 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ |
167 | /* first 2 bytes are (big-endian) length */ | 169 | /* first 2 bytes are (big-endian) length */ |
168 | }; | 170 | }; |
@@ -259,7 +261,7 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i | |||
259 | 261 | ||
260 | retval = usb_control_msg(usblp->dev, | 262 | retval = usb_control_msg(usblp->dev, |
261 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), | 263 | dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), |
262 | request, type | dir | recip, value, index, buf, len, USBLP_WRITE_TIMEOUT); | 264 | request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT); |
263 | dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", | 265 | dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", |
264 | request, !!dir, recip, value, index, len, retval); | 266 | request, !!dir, recip, value, index, len, retval); |
265 | return retval < 0 ? retval : 0; | 267 | return retval < 0 ? retval : 0; |
@@ -325,13 +327,11 @@ static void usblp_bulk_write(struct urb *urb) | |||
325 | usblp->wstatus = status; | 327 | usblp->wstatus = status; |
326 | else | 328 | else |
327 | usblp->wstatus = urb->actual_length; | 329 | usblp->wstatus = urb->actual_length; |
330 | usblp->no_paper = 0; | ||
328 | usblp->wcomplete = 1; | 331 | usblp->wcomplete = 1; |
329 | wake_up(&usblp->wwait); | 332 | wake_up(&usblp->wwait); |
330 | spin_unlock(&usblp->lock); | 333 | spin_unlock(&usblp->lock); |
331 | 334 | ||
332 | /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */ | ||
333 | kfree(urb->transfer_buffer); | ||
334 | urb->transfer_buffer = NULL; /* Not refcounted, so to be safe... */ | ||
335 | usb_free_urb(urb); | 335 | usb_free_urb(urb); |
336 | } | 336 | } |
337 | 337 | ||
@@ -346,16 +346,17 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
346 | unsigned char status, newerr = 0; | 346 | unsigned char status, newerr = 0; |
347 | int error; | 347 | int error; |
348 | 348 | ||
349 | error = usblp_read_status (usblp, usblp->statusbuf); | 349 | mutex_lock(&usblp->mut); |
350 | if (error < 0) { | 350 | if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) { |
351 | mutex_unlock(&usblp->mut); | ||
351 | if (printk_ratelimit()) | 352 | if (printk_ratelimit()) |
352 | printk(KERN_ERR | 353 | printk(KERN_ERR |
353 | "usblp%d: error %d reading printer status\n", | 354 | "usblp%d: error %d reading printer status\n", |
354 | usblp->minor, error); | 355 | usblp->minor, error); |
355 | return 0; | 356 | return 0; |
356 | } | 357 | } |
357 | |||
358 | status = *usblp->statusbuf; | 358 | status = *usblp->statusbuf; |
359 | mutex_unlock(&usblp->mut); | ||
359 | 360 | ||
360 | if (~status & LP_PERRORP) | 361 | if (~status & LP_PERRORP) |
361 | newerr = 3; | 362 | newerr = 3; |
@@ -411,18 +412,10 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
411 | goto out; | 412 | goto out; |
412 | 413 | ||
413 | /* | 414 | /* |
414 | * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ??? | 415 | * We do not implement LP_ABORTOPEN/LPABORTOPEN for two reasons: |
415 | * This is #if 0-ed because we *don't* want to fail an open | 416 | * - We do not want persistent state which close(2) does not clear |
416 | * just because the printer is off-line. | 417 | * - It is not used anyway, according to CUPS people |
417 | */ | 418 | */ |
418 | #if 0 | ||
419 | if ((retval = usblp_check_status(usblp, 0))) { | ||
420 | retval = retval > 1 ? -EIO : -ENOSPC; | ||
421 | goto out; | ||
422 | } | ||
423 | #else | ||
424 | retval = 0; | ||
425 | #endif | ||
426 | 419 | ||
427 | retval = usb_autopm_get_interface(intf); | 420 | retval = usb_autopm_get_interface(intf); |
428 | if (retval < 0) | 421 | if (retval < 0) |
@@ -463,6 +456,8 @@ static int usblp_release(struct inode *inode, struct file *file) | |||
463 | { | 456 | { |
464 | struct usblp *usblp = file->private_data; | 457 | struct usblp *usblp = file->private_data; |
465 | 458 | ||
459 | usblp->flags &= ~LP_ABORT; | ||
460 | |||
466 | mutex_lock (&usblp_mutex); | 461 | mutex_lock (&usblp_mutex); |
467 | usblp->used = 0; | 462 | usblp->used = 0; |
468 | if (usblp->present) { | 463 | if (usblp->present) { |
@@ -485,8 +480,8 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait | |||
485 | poll_wait(file, &usblp->rwait, wait); | 480 | poll_wait(file, &usblp->rwait, wait); |
486 | poll_wait(file, &usblp->wwait, wait); | 481 | poll_wait(file, &usblp->wwait, wait); |
487 | spin_lock_irqsave(&usblp->lock, flags); | 482 | spin_lock_irqsave(&usblp->lock, flags); |
488 | ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM) | 483 | ret = ((usblp->bidir && usblp->rcomplete) ? POLLIN | POLLRDNORM : 0) | |
489 | | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM); | 484 | ((usblp->no_paper || usblp->wcomplete) ? POLLOUT | POLLWRNORM : 0); |
490 | spin_unlock_irqrestore(&usblp->lock, flags); | 485 | spin_unlock_irqrestore(&usblp->lock, flags); |
491 | return ret; | 486 | return ret; |
492 | } | 487 | } |
@@ -675,6 +670,13 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
675 | retval = -EFAULT; | 670 | retval = -EFAULT; |
676 | break; | 671 | break; |
677 | 672 | ||
673 | case LPABORT: | ||
674 | if (arg) | ||
675 | usblp->flags |= LP_ABORT; | ||
676 | else | ||
677 | usblp->flags &= ~LP_ABORT; | ||
678 | break; | ||
679 | |||
678 | default: | 680 | default: |
679 | retval = -ENOTTY; | 681 | retval = -ENOTTY; |
680 | } | 682 | } |
@@ -684,10 +686,30 @@ done: | |||
684 | return retval; | 686 | return retval; |
685 | } | 687 | } |
686 | 688 | ||
689 | static struct urb *usblp_new_writeurb(struct usblp *usblp, int transfer_length) | ||
690 | { | ||
691 | struct urb *urb; | ||
692 | char *writebuf; | ||
693 | |||
694 | if ((writebuf = kmalloc(transfer_length, GFP_KERNEL)) == NULL) | ||
695 | return NULL; | ||
696 | if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) { | ||
697 | kfree(writebuf); | ||
698 | return NULL; | ||
699 | } | ||
700 | |||
701 | usb_fill_bulk_urb(urb, usblp->dev, | ||
702 | usb_sndbulkpipe(usblp->dev, | ||
703 | usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress), | ||
704 | writebuf, transfer_length, usblp_bulk_write, usblp); | ||
705 | urb->transfer_flags |= URB_FREE_BUFFER; | ||
706 | |||
707 | return urb; | ||
708 | } | ||
709 | |||
687 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 710 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
688 | { | 711 | { |
689 | struct usblp *usblp = file->private_data; | 712 | struct usblp *usblp = file->private_data; |
690 | char *writebuf; | ||
691 | struct urb *writeurb; | 713 | struct urb *writeurb; |
692 | int rv; | 714 | int rv; |
693 | int transfer_length; | 715 | int transfer_length; |
@@ -708,17 +730,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
708 | transfer_length = USBLP_BUF_SIZE; | 730 | transfer_length = USBLP_BUF_SIZE; |
709 | 731 | ||
710 | rv = -ENOMEM; | 732 | rv = -ENOMEM; |
711 | if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL) | 733 | if ((writeurb = usblp_new_writeurb(usblp, transfer_length)) == NULL) |
712 | goto raise_buf; | ||
713 | if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) | ||
714 | goto raise_urb; | 734 | goto raise_urb; |
715 | usb_fill_bulk_urb(writeurb, usblp->dev, | ||
716 | usb_sndbulkpipe(usblp->dev, | ||
717 | usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress), | ||
718 | writebuf, transfer_length, usblp_bulk_write, usblp); | ||
719 | usb_anchor_urb(writeurb, &usblp->urbs); | 735 | usb_anchor_urb(writeurb, &usblp->urbs); |
720 | 736 | ||
721 | if (copy_from_user(writebuf, | 737 | if (copy_from_user(writeurb->transfer_buffer, |
722 | buffer + writecount, transfer_length)) { | 738 | buffer + writecount, transfer_length)) { |
723 | rv = -EFAULT; | 739 | rv = -EFAULT; |
724 | goto raise_badaddr; | 740 | goto raise_badaddr; |
@@ -730,6 +746,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
730 | if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) { | 746 | if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) { |
731 | usblp->wstatus = 0; | 747 | usblp->wstatus = 0; |
732 | spin_lock_irq(&usblp->lock); | 748 | spin_lock_irq(&usblp->lock); |
749 | usblp->no_paper = 0; | ||
733 | usblp->wcomplete = 1; | 750 | usblp->wcomplete = 1; |
734 | wake_up(&usblp->wwait); | 751 | wake_up(&usblp->wwait); |
735 | spin_unlock_irq(&usblp->lock); | 752 | spin_unlock_irq(&usblp->lock); |
@@ -747,12 +764,17 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t | |||
747 | /* Presume that it's going to complete well. */ | 764 | /* Presume that it's going to complete well. */ |
748 | writecount += transfer_length; | 765 | writecount += transfer_length; |
749 | } | 766 | } |
767 | if (rv == -ENOSPC) { | ||
768 | spin_lock_irq(&usblp->lock); | ||
769 | usblp->no_paper = 1; /* Mark for poll(2) */ | ||
770 | spin_unlock_irq(&usblp->lock); | ||
771 | writecount += transfer_length; | ||
772 | } | ||
750 | /* Leave URB dangling, to be cleaned on close. */ | 773 | /* Leave URB dangling, to be cleaned on close. */ |
751 | goto collect_error; | 774 | goto collect_error; |
752 | } | 775 | } |
753 | 776 | ||
754 | if (usblp->wstatus < 0) { | 777 | if (usblp->wstatus < 0) { |
755 | usblp_check_status(usblp, 0); | ||
756 | rv = -EIO; | 778 | rv = -EIO; |
757 | goto collect_error; | 779 | goto collect_error; |
758 | } | 780 | } |
@@ -771,8 +793,6 @@ raise_badaddr: | |||
771 | usb_unanchor_urb(writeurb); | 793 | usb_unanchor_urb(writeurb); |
772 | usb_free_urb(writeurb); | 794 | usb_free_urb(writeurb); |
773 | raise_urb: | 795 | raise_urb: |
774 | kfree(writebuf); | ||
775 | raise_buf: | ||
776 | raise_wait: | 796 | raise_wait: |
777 | collect_error: /* Out of raise sequence */ | 797 | collect_error: /* Out of raise sequence */ |
778 | mutex_unlock(&usblp->wmut); | 798 | mutex_unlock(&usblp->wmut); |
@@ -838,32 +858,36 @@ done: | |||
838 | * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use | 858 | * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use |
839 | * select(2) or poll(2) to wait for the buffer to drain before closing. | 859 | * select(2) or poll(2) to wait for the buffer to drain before closing. |
840 | * Alternatively, set blocking mode with fcntl and issue a zero-size write. | 860 | * Alternatively, set blocking mode with fcntl and issue a zero-size write. |
841 | * | ||
842 | * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot | ||
843 | * to check the return code for timeout expiration, so it had no effect. | ||
844 | * Apparently, it was intended to check for error conditons, such as out | ||
845 | * of paper. It is going to return when we settle things with CUPS. XXX | ||
846 | */ | 861 | */ |
847 | static int usblp_wwait(struct usblp *usblp, int nonblock) | 862 | static int usblp_wwait(struct usblp *usblp, int nonblock) |
848 | { | 863 | { |
849 | DECLARE_WAITQUEUE(waita, current); | 864 | DECLARE_WAITQUEUE(waita, current); |
850 | int rc; | 865 | int rc; |
866 | int err = 0; | ||
851 | 867 | ||
852 | add_wait_queue(&usblp->wwait, &waita); | 868 | add_wait_queue(&usblp->wwait, &waita); |
853 | for (;;) { | 869 | for (;;) { |
870 | set_current_state(TASK_INTERRUPTIBLE); | ||
854 | if (mutex_lock_interruptible(&usblp->mut)) { | 871 | if (mutex_lock_interruptible(&usblp->mut)) { |
855 | rc = -EINTR; | 872 | rc = -EINTR; |
856 | break; | 873 | break; |
857 | } | 874 | } |
858 | set_current_state(TASK_INTERRUPTIBLE); | 875 | rc = usblp_wtest(usblp, nonblock); |
859 | if ((rc = usblp_wtest(usblp, nonblock)) < 0) { | ||
860 | mutex_unlock(&usblp->mut); | ||
861 | break; | ||
862 | } | ||
863 | mutex_unlock(&usblp->mut); | 876 | mutex_unlock(&usblp->mut); |
864 | if (rc == 0) | 877 | if (rc <= 0) |
865 | break; | 878 | break; |
866 | schedule(); | 879 | |
880 | if (usblp->flags & LP_ABORT) { | ||
881 | if (schedule_timeout(msecs_to_jiffies(5000)) == 0) { | ||
882 | err = usblp_check_status(usblp, err); | ||
883 | if (err == 1) { /* Paper out */ | ||
884 | rc = -ENOSPC; | ||
885 | break; | ||
886 | } | ||
887 | } | ||
888 | } else { | ||
889 | schedule(); | ||
890 | } | ||
867 | } | 891 | } |
868 | set_current_state(TASK_RUNNING); | 892 | set_current_state(TASK_RUNNING); |
869 | remove_wait_queue(&usblp->wwait, &waita); | 893 | remove_wait_queue(&usblp->wwait, &waita); |
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index cb69aa1e02e8..1a8edcee7f30 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -507,18 +507,30 @@ void usb_destroy_configuration(struct usb_device *dev) | |||
507 | } | 507 | } |
508 | 508 | ||
509 | 509 | ||
510 | // hub-only!! ... and only in reset path, or usb_new_device() | 510 | /* |
511 | // (used by real hubs and virtual root hubs) | 511 | * Get the USB config descriptors, cache and parse'em |
512 | * | ||
513 | * hub-only!! ... and only in reset path, or usb_new_device() | ||
514 | * (used by real hubs and virtual root hubs) | ||
515 | * | ||
516 | * NOTE: if this is a WUSB device and is not authorized, we skip the | ||
517 | * whole thing. A non-authorized USB device has no | ||
518 | * configurations. | ||
519 | */ | ||
512 | int usb_get_configuration(struct usb_device *dev) | 520 | int usb_get_configuration(struct usb_device *dev) |
513 | { | 521 | { |
514 | struct device *ddev = &dev->dev; | 522 | struct device *ddev = &dev->dev; |
515 | int ncfg = dev->descriptor.bNumConfigurations; | 523 | int ncfg = dev->descriptor.bNumConfigurations; |
516 | int result = -ENOMEM; | 524 | int result = 0; |
517 | unsigned int cfgno, length; | 525 | unsigned int cfgno, length; |
518 | unsigned char *buffer; | 526 | unsigned char *buffer; |
519 | unsigned char *bigbuffer; | 527 | unsigned char *bigbuffer; |
520 | struct usb_config_descriptor *desc; | 528 | struct usb_config_descriptor *desc; |
521 | 529 | ||
530 | cfgno = 0; | ||
531 | if (dev->authorized == 0) /* Not really an error */ | ||
532 | goto out_not_authorized; | ||
533 | result = -ENOMEM; | ||
522 | if (ncfg > USB_MAXCONFIG) { | 534 | if (ncfg > USB_MAXCONFIG) { |
523 | dev_warn(ddev, "too many configurations: %d, " | 535 | dev_warn(ddev, "too many configurations: %d, " |
524 | "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); | 536 | "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); |
@@ -545,14 +557,15 @@ int usb_get_configuration(struct usb_device *dev) | |||
545 | goto err2; | 557 | goto err2; |
546 | desc = (struct usb_config_descriptor *)buffer; | 558 | desc = (struct usb_config_descriptor *)buffer; |
547 | 559 | ||
548 | for (cfgno = 0; cfgno < ncfg; cfgno++) { | 560 | result = 0; |
561 | for (; cfgno < ncfg; cfgno++) { | ||
549 | /* We grab just the first descriptor so we know how long | 562 | /* We grab just the first descriptor so we know how long |
550 | * the whole configuration is */ | 563 | * the whole configuration is */ |
551 | result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, | 564 | result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, |
552 | buffer, USB_DT_CONFIG_SIZE); | 565 | buffer, USB_DT_CONFIG_SIZE); |
553 | if (result < 0) { | 566 | if (result < 0) { |
554 | dev_err(ddev, "unable to read config index %d " | 567 | dev_err(ddev, "unable to read config index %d " |
555 | "descriptor/%s\n", cfgno, "start"); | 568 | "descriptor/%s: %d\n", cfgno, "start", result); |
556 | dev_err(ddev, "chopping to %d config(s)\n", cfgno); | 569 | dev_err(ddev, "chopping to %d config(s)\n", cfgno); |
557 | dev->descriptor.bNumConfigurations = cfgno; | 570 | dev->descriptor.bNumConfigurations = cfgno; |
558 | break; | 571 | break; |
@@ -599,6 +612,7 @@ int usb_get_configuration(struct usb_device *dev) | |||
599 | 612 | ||
600 | err: | 613 | err: |
601 | kfree(buffer); | 614 | kfree(buffer); |
615 | out_not_authorized: | ||
602 | dev->descriptor.bNumConfigurations = cfgno; | 616 | dev->descriptor.bNumConfigurations = cfgno; |
603 | err2: | 617 | err2: |
604 | if (result == -ENOMEM) | 618 | if (result == -ENOMEM) |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fe98796d2ff1..f013b4012c9a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -71,6 +71,7 @@ struct async { | |||
71 | void __user *userbuffer; | 71 | void __user *userbuffer; |
72 | void __user *userurb; | 72 | void __user *userurb; |
73 | struct urb *urb; | 73 | struct urb *urb; |
74 | int status; | ||
74 | u32 secid; | 75 | u32 secid; |
75 | }; | 76 | }; |
76 | 77 | ||
@@ -289,10 +290,8 @@ static void snoop_urb(struct urb *urb, void __user *userurb) | |||
289 | if (!usbfs_snoop) | 290 | if (!usbfs_snoop) |
290 | return; | 291 | return; |
291 | 292 | ||
292 | if (urb->pipe & USB_DIR_IN) | 293 | dev_info(&urb->dev->dev, "direction=%s\n", |
293 | dev_info(&urb->dev->dev, "direction=IN\n"); | 294 | usb_urb_dir_in(urb) ? "IN" : "OUT"); |
294 | else | ||
295 | dev_info(&urb->dev->dev, "direction=OUT\n"); | ||
296 | dev_info(&urb->dev->dev, "userurb=%p\n", userurb); | 295 | dev_info(&urb->dev->dev, "userurb=%p\n", userurb); |
297 | dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", | 296 | dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", |
298 | urb->transfer_buffer_length); | 297 | urb->transfer_buffer_length); |
@@ -312,9 +311,10 @@ static void async_completed(struct urb *urb) | |||
312 | spin_lock(&ps->lock); | 311 | spin_lock(&ps->lock); |
313 | list_move_tail(&as->asynclist, &ps->async_completed); | 312 | list_move_tail(&as->asynclist, &ps->async_completed); |
314 | spin_unlock(&ps->lock); | 313 | spin_unlock(&ps->lock); |
314 | as->status = urb->status; | ||
315 | if (as->signr) { | 315 | if (as->signr) { |
316 | sinfo.si_signo = as->signr; | 316 | sinfo.si_signo = as->signr; |
317 | sinfo.si_errno = as->urb->status; | 317 | sinfo.si_errno = as->status; |
318 | sinfo.si_code = SI_ASYNCIO; | 318 | sinfo.si_code = SI_ASYNCIO; |
319 | sinfo.si_addr = as->userurb; | 319 | sinfo.si_addr = as->userurb; |
320 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, | 320 | kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid, |
@@ -910,6 +910,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
910 | struct usb_ctrlrequest *dr = NULL; | 910 | struct usb_ctrlrequest *dr = NULL; |
911 | unsigned int u, totlen, isofrmlen; | 911 | unsigned int u, totlen, isofrmlen; |
912 | int ret, ifnum = -1; | 912 | int ret, ifnum = -1; |
913 | int is_in; | ||
913 | 914 | ||
914 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| | 915 | if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK| |
915 | URB_NO_FSBR|URB_ZERO_PACKET)) | 916 | URB_NO_FSBR|URB_ZERO_PACKET)) |
@@ -924,16 +925,18 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
924 | if ((ret = checkintf(ps, ifnum))) | 925 | if ((ret = checkintf(ps, ifnum))) |
925 | return ret; | 926 | return ret; |
926 | } | 927 | } |
927 | if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) | 928 | if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) { |
928 | ep = ps->dev->ep_in [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; | 929 | is_in = 1; |
929 | else | 930 | ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; |
930 | ep = ps->dev->ep_out [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; | 931 | } else { |
932 | is_in = 0; | ||
933 | ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK]; | ||
934 | } | ||
931 | if (!ep) | 935 | if (!ep) |
932 | return -ENOENT; | 936 | return -ENOENT; |
933 | switch(uurb->type) { | 937 | switch(uurb->type) { |
934 | case USBDEVFS_URB_TYPE_CONTROL: | 938 | case USBDEVFS_URB_TYPE_CONTROL: |
935 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 939 | if (!usb_endpoint_xfer_control(&ep->desc)) |
936 | != USB_ENDPOINT_XFER_CONTROL) | ||
937 | return -EINVAL; | 940 | return -EINVAL; |
938 | /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ | 941 | /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ |
939 | if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) | 942 | if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) |
@@ -952,23 +955,32 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
952 | kfree(dr); | 955 | kfree(dr); |
953 | return ret; | 956 | return ret; |
954 | } | 957 | } |
955 | uurb->endpoint = (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK); | ||
956 | uurb->number_of_packets = 0; | 958 | uurb->number_of_packets = 0; |
957 | uurb->buffer_length = le16_to_cpup(&dr->wLength); | 959 | uurb->buffer_length = le16_to_cpup(&dr->wLength); |
958 | uurb->buffer += 8; | 960 | uurb->buffer += 8; |
959 | if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) { | 961 | if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { |
962 | is_in = 1; | ||
963 | uurb->endpoint |= USB_DIR_IN; | ||
964 | } else { | ||
965 | is_in = 0; | ||
966 | uurb->endpoint &= ~USB_DIR_IN; | ||
967 | } | ||
968 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, | ||
969 | uurb->buffer, uurb->buffer_length)) { | ||
960 | kfree(dr); | 970 | kfree(dr); |
961 | return -EFAULT; | 971 | return -EFAULT; |
962 | } | 972 | } |
963 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " | 973 | snoop(&ps->dev->dev, "control urb: bRequest=%02x " |
964 | "bRrequestType=%02x wValue=%04x " | 974 | "bRrequestType=%02x wValue=%04x " |
965 | "wIndex=%04x wLength=%04x\n", | 975 | "wIndex=%04x wLength=%04x\n", |
966 | dr->bRequest, dr->bRequestType, dr->wValue, | 976 | dr->bRequest, dr->bRequestType, |
967 | dr->wIndex, dr->wLength); | 977 | __le16_to_cpup(&dr->wValue), |
978 | __le16_to_cpup(&dr->wIndex), | ||
979 | __le16_to_cpup(&dr->wLength)); | ||
968 | break; | 980 | break; |
969 | 981 | ||
970 | case USBDEVFS_URB_TYPE_BULK: | 982 | case USBDEVFS_URB_TYPE_BULK: |
971 | switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | 983 | switch (usb_endpoint_type(&ep->desc)) { |
972 | case USB_ENDPOINT_XFER_CONTROL: | 984 | case USB_ENDPOINT_XFER_CONTROL: |
973 | case USB_ENDPOINT_XFER_ISOC: | 985 | case USB_ENDPOINT_XFER_ISOC: |
974 | return -EINVAL; | 986 | return -EINVAL; |
@@ -977,7 +989,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
977 | uurb->number_of_packets = 0; | 989 | uurb->number_of_packets = 0; |
978 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 990 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
979 | return -EINVAL; | 991 | return -EINVAL; |
980 | if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) | 992 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
993 | uurb->buffer, uurb->buffer_length)) | ||
981 | return -EFAULT; | 994 | return -EFAULT; |
982 | snoop(&ps->dev->dev, "bulk urb\n"); | 995 | snoop(&ps->dev->dev, "bulk urb\n"); |
983 | break; | 996 | break; |
@@ -986,8 +999,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
986 | /* arbitrary limit */ | 999 | /* arbitrary limit */ |
987 | if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128) | 1000 | if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128) |
988 | return -EINVAL; | 1001 | return -EINVAL; |
989 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 1002 | if (!usb_endpoint_xfer_isoc(&ep->desc)) |
990 | != USB_ENDPOINT_XFER_ISOC) | ||
991 | return -EINVAL; | 1003 | return -EINVAL; |
992 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; | 1004 | isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; |
993 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) | 1005 | if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) |
@@ -1014,12 +1026,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1014 | 1026 | ||
1015 | case USBDEVFS_URB_TYPE_INTERRUPT: | 1027 | case USBDEVFS_URB_TYPE_INTERRUPT: |
1016 | uurb->number_of_packets = 0; | 1028 | uurb->number_of_packets = 0; |
1017 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 1029 | if (!usb_endpoint_xfer_int(&ep->desc)) |
1018 | != USB_ENDPOINT_XFER_INT) | ||
1019 | return -EINVAL; | 1030 | return -EINVAL; |
1020 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) | 1031 | if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) |
1021 | return -EINVAL; | 1032 | return -EINVAL; |
1022 | if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) | 1033 | if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, |
1034 | uurb->buffer, uurb->buffer_length)) | ||
1023 | return -EFAULT; | 1035 | return -EFAULT; |
1024 | snoop(&ps->dev->dev, "interrupt urb\n"); | 1036 | snoop(&ps->dev->dev, "interrupt urb\n"); |
1025 | break; | 1037 | break; |
@@ -1039,8 +1051,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1039 | return -ENOMEM; | 1051 | return -ENOMEM; |
1040 | } | 1052 | } |
1041 | as->urb->dev = ps->dev; | 1053 | as->urb->dev = ps->dev; |
1042 | as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN); | 1054 | as->urb->pipe = (uurb->type << 30) | |
1043 | as->urb->transfer_flags = uurb->flags; | 1055 | __create_pipe(ps->dev, uurb->endpoint & 0xf) | |
1056 | (uurb->endpoint & USB_DIR_IN); | ||
1057 | as->urb->transfer_flags = uurb->flags | | ||
1058 | (is_in ? URB_DIR_IN : URB_DIR_OUT); | ||
1044 | as->urb->transfer_buffer_length = uurb->buffer_length; | 1059 | as->urb->transfer_buffer_length = uurb->buffer_length; |
1045 | as->urb->setup_packet = (unsigned char*)dr; | 1060 | as->urb->setup_packet = (unsigned char*)dr; |
1046 | as->urb->start_frame = uurb->start_frame; | 1061 | as->urb->start_frame = uurb->start_frame; |
@@ -1070,13 +1085,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1070 | as->uid = current->uid; | 1085 | as->uid = current->uid; |
1071 | as->euid = current->euid; | 1086 | as->euid = current->euid; |
1072 | security_task_getsecid(current, &as->secid); | 1087 | security_task_getsecid(current, &as->secid); |
1073 | if (!(uurb->endpoint & USB_DIR_IN)) { | 1088 | if (!is_in) { |
1074 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) { | 1089 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
1090 | as->urb->transfer_buffer_length)) { | ||
1075 | free_async(as); | 1091 | free_async(as); |
1076 | return -EFAULT; | 1092 | return -EFAULT; |
1077 | } | 1093 | } |
1078 | } | 1094 | } |
1079 | snoop(&as->urb->dev->dev, "submit urb\n"); | ||
1080 | snoop_urb(as->urb, as->userurb); | 1095 | snoop_urb(as->urb, as->userurb); |
1081 | async_newpending(as); | 1096 | async_newpending(as); |
1082 | if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { | 1097 | if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { |
@@ -1119,14 +1134,14 @@ static int processcompl(struct async *as, void __user * __user *arg) | |||
1119 | if (as->userbuffer) | 1134 | if (as->userbuffer) |
1120 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length)) | 1135 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length)) |
1121 | return -EFAULT; | 1136 | return -EFAULT; |
1122 | if (put_user(urb->status, &userurb->status)) | 1137 | if (put_user(as->status, &userurb->status)) |
1123 | return -EFAULT; | 1138 | return -EFAULT; |
1124 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1139 | if (put_user(urb->actual_length, &userurb->actual_length)) |
1125 | return -EFAULT; | 1140 | return -EFAULT; |
1126 | if (put_user(urb->error_count, &userurb->error_count)) | 1141 | if (put_user(urb->error_count, &userurb->error_count)) |
1127 | return -EFAULT; | 1142 | return -EFAULT; |
1128 | 1143 | ||
1129 | if (usb_pipeisoc(urb->pipe)) { | 1144 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
1130 | for (i = 0; i < urb->number_of_packets; i++) { | 1145 | for (i = 0; i < urb->number_of_packets; i++) { |
1131 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1146 | if (put_user(urb->iso_frame_desc[i].actual_length, |
1132 | &userurb->iso_frame_desc[i].actual_length)) | 1147 | &userurb->iso_frame_desc[i].actual_length)) |
@@ -1233,14 +1248,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) | |||
1233 | if (as->userbuffer) | 1248 | if (as->userbuffer) |
1234 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length)) | 1249 | if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length)) |
1235 | return -EFAULT; | 1250 | return -EFAULT; |
1236 | if (put_user(urb->status, &userurb->status)) | 1251 | if (put_user(as->status, &userurb->status)) |
1237 | return -EFAULT; | 1252 | return -EFAULT; |
1238 | if (put_user(urb->actual_length, &userurb->actual_length)) | 1253 | if (put_user(urb->actual_length, &userurb->actual_length)) |
1239 | return -EFAULT; | 1254 | return -EFAULT; |
1240 | if (put_user(urb->error_count, &userurb->error_count)) | 1255 | if (put_user(urb->error_count, &userurb->error_count)) |
1241 | return -EFAULT; | 1256 | return -EFAULT; |
1242 | 1257 | ||
1243 | if (usb_pipeisoc(urb->pipe)) { | 1258 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) { |
1244 | for (i = 0; i < urb->number_of_packets; i++) { | 1259 | for (i = 0; i < urb->number_of_packets; i++) { |
1245 | if (put_user(urb->iso_frame_desc[i].actual_length, | 1260 | if (put_user(urb->iso_frame_desc[i].actual_length, |
1246 | &userurb->iso_frame_desc[i].actual_length)) | 1261 | &userurb->iso_frame_desc[i].actual_length)) |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 6273a5197e6a..8586817698ad 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -202,6 +202,11 @@ static int usb_probe_interface(struct device *dev) | |||
202 | intf = to_usb_interface(dev); | 202 | intf = to_usb_interface(dev); |
203 | udev = interface_to_usbdev(intf); | 203 | udev = interface_to_usbdev(intf); |
204 | 204 | ||
205 | if (udev->authorized == 0) { | ||
206 | dev_err(&intf->dev, "Device is not authorized for usage\n"); | ||
207 | return -ENODEV; | ||
208 | } | ||
209 | |||
205 | id = usb_match_id(intf, driver->id_table); | 210 | id = usb_match_id(intf, driver->id_table); |
206 | if (!id) | 211 | if (!id) |
207 | id = usb_match_dynamic_id(intf, driver); | 212 | id = usb_match_dynamic_id(intf, driver); |
@@ -930,11 +935,11 @@ done: | |||
930 | #ifdef CONFIG_USB_SUSPEND | 935 | #ifdef CONFIG_USB_SUSPEND |
931 | 936 | ||
932 | /* Internal routine to check whether we may autosuspend a device. */ | 937 | /* Internal routine to check whether we may autosuspend a device. */ |
933 | static int autosuspend_check(struct usb_device *udev) | 938 | static int autosuspend_check(struct usb_device *udev, int reschedule) |
934 | { | 939 | { |
935 | int i; | 940 | int i; |
936 | struct usb_interface *intf; | 941 | struct usb_interface *intf; |
937 | unsigned long suspend_time; | 942 | unsigned long suspend_time, j; |
938 | 943 | ||
939 | /* For autosuspend, fail fast if anything is in use or autosuspend | 944 | /* For autosuspend, fail fast if anything is in use or autosuspend |
940 | * is disabled. Also fail if any interfaces require remote wakeup | 945 | * is disabled. Also fail if any interfaces require remote wakeup |
@@ -976,20 +981,20 @@ static int autosuspend_check(struct usb_device *udev) | |||
976 | } | 981 | } |
977 | 982 | ||
978 | /* If everything is okay but the device hasn't been idle for long | 983 | /* If everything is okay but the device hasn't been idle for long |
979 | * enough, queue a delayed autosuspend request. | 984 | * enough, queue a delayed autosuspend request. If the device |
985 | * _has_ been idle for long enough and the reschedule flag is set, | ||
986 | * likewise queue a delayed (1 second) autosuspend request. | ||
980 | */ | 987 | */ |
981 | if (time_after(suspend_time, jiffies)) { | 988 | j = jiffies; |
989 | if (time_before(j, suspend_time)) | ||
990 | reschedule = 1; | ||
991 | else | ||
992 | suspend_time = j + HZ; | ||
993 | if (reschedule) { | ||
982 | if (!timer_pending(&udev->autosuspend.timer)) { | 994 | if (!timer_pending(&udev->autosuspend.timer)) { |
983 | |||
984 | /* The value of jiffies may change between the | ||
985 | * time_after() comparison above and the subtraction | ||
986 | * below. That's okay; the system behaves sanely | ||
987 | * when a timer is registered for the present moment | ||
988 | * or for the past. | ||
989 | */ | ||
990 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 995 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
991 | round_jiffies_relative(suspend_time - jiffies)); | 996 | round_jiffies_relative(suspend_time - j)); |
992 | } | 997 | } |
993 | return -EAGAIN; | 998 | return -EAGAIN; |
994 | } | 999 | } |
995 | return 0; | 1000 | return 0; |
@@ -997,7 +1002,7 @@ static int autosuspend_check(struct usb_device *udev) | |||
997 | 1002 | ||
998 | #else | 1003 | #else |
999 | 1004 | ||
1000 | static inline int autosuspend_check(struct usb_device *udev) | 1005 | static inline int autosuspend_check(struct usb_device *udev, int reschedule) |
1001 | { | 1006 | { |
1002 | return 0; | 1007 | return 0; |
1003 | } | 1008 | } |
@@ -1054,7 +1059,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1054 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 1059 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); |
1055 | 1060 | ||
1056 | if (udev->auto_pm) { | 1061 | if (udev->auto_pm) { |
1057 | status = autosuspend_check(udev); | 1062 | status = autosuspend_check(udev, 0); |
1058 | if (status < 0) | 1063 | if (status < 0) |
1059 | goto done; | 1064 | goto done; |
1060 | } | 1065 | } |
@@ -1068,15 +1073,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1068 | break; | 1073 | break; |
1069 | } | 1074 | } |
1070 | } | 1075 | } |
1071 | if (status == 0) { | 1076 | if (status == 0) |
1072 | |||
1073 | /* Non-root devices don't need to do anything for FREEZE | ||
1074 | * or PRETHAW. */ | ||
1075 | if (udev->parent && (msg.event == PM_EVENT_FREEZE || | ||
1076 | msg.event == PM_EVENT_PRETHAW)) | ||
1077 | goto done; | ||
1078 | status = usb_suspend_device(udev, msg); | 1077 | status = usb_suspend_device(udev, msg); |
1079 | } | ||
1080 | 1078 | ||
1081 | /* If the suspend failed, resume interfaces that did get suspended */ | 1079 | /* If the suspend failed, resume interfaces that did get suspended */ |
1082 | if (status != 0) { | 1080 | if (status != 0) { |
@@ -1087,12 +1085,24 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1087 | 1085 | ||
1088 | /* Try another autosuspend when the interfaces aren't busy */ | 1086 | /* Try another autosuspend when the interfaces aren't busy */ |
1089 | if (udev->auto_pm) | 1087 | if (udev->auto_pm) |
1090 | autosuspend_check(udev); | 1088 | autosuspend_check(udev, status == -EBUSY); |
1091 | 1089 | ||
1092 | /* If the suspend succeeded, propagate it up the tree */ | 1090 | /* If the suspend succeeded then prevent any more URB submissions, |
1091 | * flush any outstanding URBs, and propagate the suspend up the tree. | ||
1092 | */ | ||
1093 | } else { | 1093 | } else { |
1094 | cancel_delayed_work(&udev->autosuspend); | 1094 | cancel_delayed_work(&udev->autosuspend); |
1095 | if (parent) | 1095 | udev->can_submit = 0; |
1096 | for (i = 0; i < 16; ++i) { | ||
1097 | usb_hcd_flush_endpoint(udev, udev->ep_out[i]); | ||
1098 | usb_hcd_flush_endpoint(udev, udev->ep_in[i]); | ||
1099 | } | ||
1100 | |||
1101 | /* If this is just a FREEZE or a PRETHAW, udev might | ||
1102 | * not really be suspended. Only true suspends get | ||
1103 | * propagated up the device tree. | ||
1104 | */ | ||
1105 | if (parent && udev->state == USB_STATE_SUSPENDED) | ||
1096 | usb_autosuspend_device(parent); | 1106 | usb_autosuspend_device(parent); |
1097 | } | 1107 | } |
1098 | 1108 | ||
@@ -1141,6 +1151,7 @@ static int usb_resume_both(struct usb_device *udev) | |||
1141 | status = -ENODEV; | 1151 | status = -ENODEV; |
1142 | goto done; | 1152 | goto done; |
1143 | } | 1153 | } |
1154 | udev->can_submit = 1; | ||
1144 | 1155 | ||
1145 | /* Propagate the resume up the tree, if necessary */ | 1156 | /* Propagate the resume up the tree, if necessary */ |
1146 | if (udev->state == USB_STATE_SUSPENDED) { | 1157 | if (udev->state == USB_STATE_SUSPENDED) { |
@@ -1514,9 +1525,21 @@ int usb_external_resume_device(struct usb_device *udev) | |||
1514 | 1525 | ||
1515 | static int usb_suspend(struct device *dev, pm_message_t message) | 1526 | static int usb_suspend(struct device *dev, pm_message_t message) |
1516 | { | 1527 | { |
1528 | struct usb_device *udev; | ||
1529 | |||
1517 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ | 1530 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ |
1518 | return 0; | 1531 | return 0; |
1519 | return usb_external_suspend_device(to_usb_device(dev), message); | 1532 | udev = to_usb_device(dev); |
1533 | |||
1534 | /* If udev is already suspended, we can skip this suspend and | ||
1535 | * we should also skip the upcoming system resume. */ | ||
1536 | if (udev->state == USB_STATE_SUSPENDED) { | ||
1537 | udev->skip_sys_resume = 1; | ||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | udev->skip_sys_resume = 0; | ||
1542 | return usb_external_suspend_device(udev, message); | ||
1520 | } | 1543 | } |
1521 | 1544 | ||
1522 | static int usb_resume(struct device *dev) | 1545 | static int usb_resume(struct device *dev) |
@@ -1527,13 +1550,14 @@ static int usb_resume(struct device *dev) | |||
1527 | return 0; | 1550 | return 0; |
1528 | udev = to_usb_device(dev); | 1551 | udev = to_usb_device(dev); |
1529 | 1552 | ||
1530 | /* If autoresume is disabled then we also want to prevent resume | 1553 | /* If udev->skip_sys_resume is set then udev was already suspended |
1531 | * during system wakeup. However, a "persistent-device" reset-resume | 1554 | * when the system suspend started, so we don't want to resume |
1532 | * after power loss counts as a wakeup event. So allow a | 1555 | * udev during this system wakeup. However a reset-resume counts |
1533 | * reset-resume to occur if remote wakeup is enabled. */ | 1556 | * as a wakeup event, so allow a reset-resume to occur if remote |
1534 | if (udev->autoresume_disabled) { | 1557 | * wakeup is enabled. */ |
1558 | if (udev->skip_sys_resume) { | ||
1535 | if (!(udev->reset_resume && udev->do_remote_wakeup)) | 1559 | if (!(udev->reset_resume && udev->do_remote_wakeup)) |
1536 | return -EPERM; | 1560 | return -EHOSTUNREACH; |
1537 | } | 1561 | } |
1538 | return usb_external_resume_device(udev); | 1562 | return usb_external_resume_device(udev); |
1539 | } | 1563 | } |
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index e0ec7045e865..7dc123d6b2d0 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c | |||
@@ -267,7 +267,6 @@ static void ep_device_release(struct device *dev) | |||
267 | { | 267 | { |
268 | struct ep_device *ep_dev = to_ep_device(dev); | 268 | struct ep_device *ep_dev = to_ep_device(dev); |
269 | 269 | ||
270 | dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id); | ||
271 | endpoint_free_minor(ep_dev); | 270 | endpoint_free_minor(ep_dev); |
272 | kfree(ep_dev); | 271 | kfree(ep_dev); |
273 | } | 272 | } |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index b2fc2b115256..c1cb94e9f242 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -40,7 +40,7 @@ static int is_activesync(struct usb_interface_descriptor *desc) | |||
40 | && desc->bInterfaceProtocol == 1; | 40 | && desc->bInterfaceProtocol == 1; |
41 | } | 41 | } |
42 | 42 | ||
43 | static int choose_configuration(struct usb_device *udev) | 43 | int usb_choose_configuration(struct usb_device *udev) |
44 | { | 44 | { |
45 | int i; | 45 | int i; |
46 | int num_configs; | 46 | int num_configs; |
@@ -161,17 +161,20 @@ static int generic_probe(struct usb_device *udev) | |||
161 | /* Choose and set the configuration. This registers the interfaces | 161 | /* Choose and set the configuration. This registers the interfaces |
162 | * with the driver core and lets interface drivers bind to them. | 162 | * with the driver core and lets interface drivers bind to them. |
163 | */ | 163 | */ |
164 | c = choose_configuration(udev); | 164 | if (udev->authorized == 0) |
165 | if (c >= 0) { | 165 | dev_err(&udev->dev, "Device is not authorized for usage\n"); |
166 | err = usb_set_configuration(udev, c); | 166 | else { |
167 | if (err) { | 167 | c = usb_choose_configuration(udev); |
168 | dev_err(&udev->dev, "can't set config #%d, error %d\n", | 168 | if (c >= 0) { |
169 | err = usb_set_configuration(udev, c); | ||
170 | if (err) { | ||
171 | dev_err(&udev->dev, "can't set config #%d, error %d\n", | ||
169 | c, err); | 172 | c, err); |
170 | /* This need not be fatal. The user can try to | 173 | /* This need not be fatal. The user can try to |
171 | * set other configurations. */ | 174 | * set other configurations. */ |
175 | } | ||
172 | } | 176 | } |
173 | } | 177 | } |
174 | |||
175 | /* USB device state == configured ... usable */ | 178 | /* USB device state == configured ... usable */ |
176 | usb_notify_add_device(udev); | 179 | usb_notify_add_device(udev); |
177 | 180 | ||
@@ -203,8 +206,13 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) | |||
203 | */ | 206 | */ |
204 | if (!udev->parent) | 207 | if (!udev->parent) |
205 | rc = hcd_bus_suspend(udev); | 208 | rc = hcd_bus_suspend(udev); |
209 | |||
210 | /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ | ||
211 | else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) | ||
212 | rc = 0; | ||
206 | else | 213 | else |
207 | rc = usb_port_suspend(udev); | 214 | rc = usb_port_suspend(udev); |
215 | |||
208 | return rc; | 216 | return rc; |
209 | } | 217 | } |
210 | 218 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 42ef1d5f6c8a..3dd997df8505 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -356,10 +356,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
356 | const u8 *bufp = tbuf; | 356 | const u8 *bufp = tbuf; |
357 | int len = 0; | 357 | int len = 0; |
358 | int patch_wakeup = 0; | 358 | int patch_wakeup = 0; |
359 | unsigned long flags; | 359 | int status; |
360 | int status = 0; | ||
361 | int n; | 360 | int n; |
362 | 361 | ||
362 | might_sleep(); | ||
363 | |||
364 | spin_lock_irq(&hcd_root_hub_lock); | ||
365 | status = usb_hcd_link_urb_to_ep(hcd, urb); | ||
366 | spin_unlock_irq(&hcd_root_hub_lock); | ||
367 | if (status) | ||
368 | return status; | ||
369 | urb->hcpriv = hcd; /* Indicate it's queued */ | ||
370 | |||
363 | cmd = (struct usb_ctrlrequest *) urb->setup_packet; | 371 | cmd = (struct usb_ctrlrequest *) urb->setup_packet; |
364 | typeReq = (cmd->bRequestType << 8) | cmd->bRequest; | 372 | typeReq = (cmd->bRequestType << 8) | cmd->bRequest; |
365 | wValue = le16_to_cpu (cmd->wValue); | 373 | wValue = le16_to_cpu (cmd->wValue); |
@@ -523,13 +531,18 @@ error: | |||
523 | } | 531 | } |
524 | 532 | ||
525 | /* any errors get returned through the urb completion */ | 533 | /* any errors get returned through the urb completion */ |
526 | local_irq_save (flags); | 534 | spin_lock_irq(&hcd_root_hub_lock); |
527 | spin_lock (&urb->lock); | 535 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
528 | if (urb->status == -EINPROGRESS) | 536 | |
529 | urb->status = status; | 537 | /* This peculiar use of spinlocks echoes what real HC drivers do. |
530 | spin_unlock (&urb->lock); | 538 | * Avoiding calls to local_irq_disable/enable makes the code |
531 | usb_hcd_giveback_urb (hcd, urb); | 539 | * RT-friendly. |
532 | local_irq_restore (flags); | 540 | */ |
541 | spin_unlock(&hcd_root_hub_lock); | ||
542 | usb_hcd_giveback_urb(hcd, urb, status); | ||
543 | spin_lock(&hcd_root_hub_lock); | ||
544 | |||
545 | spin_unlock_irq(&hcd_root_hub_lock); | ||
533 | return 0; | 546 | return 0; |
534 | } | 547 | } |
535 | 548 | ||
@@ -559,31 +572,23 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
559 | if (length > 0) { | 572 | if (length > 0) { |
560 | 573 | ||
561 | /* try to complete the status urb */ | 574 | /* try to complete the status urb */ |
562 | local_irq_save (flags); | 575 | spin_lock_irqsave(&hcd_root_hub_lock, flags); |
563 | spin_lock(&hcd_root_hub_lock); | ||
564 | urb = hcd->status_urb; | 576 | urb = hcd->status_urb; |
565 | if (urb) { | 577 | if (urb) { |
566 | spin_lock(&urb->lock); | 578 | hcd->poll_pending = 0; |
567 | if (urb->status == -EINPROGRESS) { | 579 | hcd->status_urb = NULL; |
568 | hcd->poll_pending = 0; | 580 | urb->actual_length = length; |
569 | hcd->status_urb = NULL; | 581 | memcpy(urb->transfer_buffer, buffer, length); |
570 | urb->status = 0; | ||
571 | urb->hcpriv = NULL; | ||
572 | urb->actual_length = length; | ||
573 | memcpy(urb->transfer_buffer, buffer, length); | ||
574 | } else /* urb has been unlinked */ | ||
575 | length = 0; | ||
576 | spin_unlock(&urb->lock); | ||
577 | } else | ||
578 | length = 0; | ||
579 | spin_unlock(&hcd_root_hub_lock); | ||
580 | 582 | ||
581 | /* local irqs are always blocked in completions */ | 583 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
582 | if (length > 0) | 584 | spin_unlock(&hcd_root_hub_lock); |
583 | usb_hcd_giveback_urb (hcd, urb); | 585 | usb_hcd_giveback_urb(hcd, urb, 0); |
584 | else | 586 | spin_lock(&hcd_root_hub_lock); |
587 | } else { | ||
588 | length = 0; | ||
585 | hcd->poll_pending = 1; | 589 | hcd->poll_pending = 1; |
586 | local_irq_restore (flags); | 590 | } |
591 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); | ||
587 | } | 592 | } |
588 | 593 | ||
589 | /* The USB 2.0 spec says 256 ms. This is close enough and won't | 594 | /* The USB 2.0 spec says 256 ms. This is close enough and won't |
@@ -611,33 +616,35 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | |||
611 | int len = 1 + (urb->dev->maxchild / 8); | 616 | int len = 1 + (urb->dev->maxchild / 8); |
612 | 617 | ||
613 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 618 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
614 | if (urb->status != -EINPROGRESS) /* already unlinked */ | 619 | if (hcd->status_urb || urb->transfer_buffer_length < len) { |
615 | retval = urb->status; | ||
616 | else if (hcd->status_urb || urb->transfer_buffer_length < len) { | ||
617 | dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); | 620 | dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); |
618 | retval = -EINVAL; | 621 | retval = -EINVAL; |
619 | } else { | 622 | goto done; |
620 | hcd->status_urb = urb; | 623 | } |
621 | urb->hcpriv = hcd; /* indicate it's queued */ | ||
622 | 624 | ||
623 | if (!hcd->uses_new_polling) | 625 | retval = usb_hcd_link_urb_to_ep(hcd, urb); |
624 | mod_timer (&hcd->rh_timer, | 626 | if (retval) |
625 | (jiffies/(HZ/4) + 1) * (HZ/4)); | 627 | goto done; |
626 | 628 | ||
627 | /* If a status change has already occurred, report it ASAP */ | 629 | hcd->status_urb = urb; |
628 | else if (hcd->poll_pending) | 630 | urb->hcpriv = hcd; /* indicate it's queued */ |
629 | mod_timer (&hcd->rh_timer, jiffies); | 631 | if (!hcd->uses_new_polling) |
630 | retval = 0; | 632 | mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
631 | } | 633 | |
634 | /* If a status change has already occurred, report it ASAP */ | ||
635 | else if (hcd->poll_pending) | ||
636 | mod_timer(&hcd->rh_timer, jiffies); | ||
637 | retval = 0; | ||
638 | done: | ||
632 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); | 639 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); |
633 | return retval; | 640 | return retval; |
634 | } | 641 | } |
635 | 642 | ||
636 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) | 643 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) |
637 | { | 644 | { |
638 | if (usb_pipeint (urb->pipe)) | 645 | if (usb_endpoint_xfer_int(&urb->ep->desc)) |
639 | return rh_queue_status (hcd, urb); | 646 | return rh_queue_status (hcd, urb); |
640 | if (usb_pipecontrol (urb->pipe)) | 647 | if (usb_endpoint_xfer_control(&urb->ep->desc)) |
641 | return rh_call_control (hcd, urb); | 648 | return rh_call_control (hcd, urb); |
642 | return -EINVAL; | 649 | return -EINVAL; |
643 | } | 650 | } |
@@ -647,32 +654,96 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) | |||
647 | /* Unlinks of root-hub control URBs are legal, but they don't do anything | 654 | /* Unlinks of root-hub control URBs are legal, but they don't do anything |
648 | * since these URBs always execute synchronously. | 655 | * since these URBs always execute synchronously. |
649 | */ | 656 | */ |
650 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 657 | static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
651 | { | 658 | { |
652 | unsigned long flags; | 659 | unsigned long flags; |
660 | int rc; | ||
661 | |||
662 | spin_lock_irqsave(&hcd_root_hub_lock, flags); | ||
663 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
664 | if (rc) | ||
665 | goto done; | ||
653 | 666 | ||
654 | if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ | 667 | if (usb_endpoint_num(&urb->ep->desc) == 0) { /* Control URB */ |
655 | ; /* Do nothing */ | 668 | ; /* Do nothing */ |
656 | 669 | ||
657 | } else { /* Status URB */ | 670 | } else { /* Status URB */ |
658 | if (!hcd->uses_new_polling) | 671 | if (!hcd->uses_new_polling) |
659 | del_timer (&hcd->rh_timer); | 672 | del_timer (&hcd->rh_timer); |
660 | local_irq_save (flags); | ||
661 | spin_lock (&hcd_root_hub_lock); | ||
662 | if (urb == hcd->status_urb) { | 673 | if (urb == hcd->status_urb) { |
663 | hcd->status_urb = NULL; | 674 | hcd->status_urb = NULL; |
664 | urb->hcpriv = NULL; | 675 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
665 | } else | 676 | |
666 | urb = NULL; /* wasn't fully queued */ | 677 | spin_unlock(&hcd_root_hub_lock); |
667 | spin_unlock (&hcd_root_hub_lock); | 678 | usb_hcd_giveback_urb(hcd, urb, status); |
668 | if (urb) | 679 | spin_lock(&hcd_root_hub_lock); |
669 | usb_hcd_giveback_urb (hcd, urb); | 680 | } |
670 | local_irq_restore (flags); | ||
671 | } | 681 | } |
682 | done: | ||
683 | spin_unlock_irqrestore(&hcd_root_hub_lock, flags); | ||
684 | return rc; | ||
685 | } | ||
672 | 686 | ||
673 | return 0; | 687 | |
688 | |||
689 | /* | ||
690 | * Show & store the current value of authorized_default | ||
691 | */ | ||
692 | static ssize_t usb_host_authorized_default_show(struct device *dev, | ||
693 | struct device_attribute *attr, | ||
694 | char *buf) | ||
695 | { | ||
696 | struct usb_device *rh_usb_dev = to_usb_device(dev); | ||
697 | struct usb_bus *usb_bus = rh_usb_dev->bus; | ||
698 | struct usb_hcd *usb_hcd; | ||
699 | |||
700 | if (usb_bus == NULL) /* FIXME: not sure if this case is possible */ | ||
701 | return -ENODEV; | ||
702 | usb_hcd = bus_to_hcd(usb_bus); | ||
703 | return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default); | ||
704 | } | ||
705 | |||
706 | static ssize_t usb_host_authorized_default_store(struct device *dev, | ||
707 | struct device_attribute *attr, | ||
708 | const char *buf, size_t size) | ||
709 | { | ||
710 | ssize_t result; | ||
711 | unsigned val; | ||
712 | struct usb_device *rh_usb_dev = to_usb_device(dev); | ||
713 | struct usb_bus *usb_bus = rh_usb_dev->bus; | ||
714 | struct usb_hcd *usb_hcd; | ||
715 | |||
716 | if (usb_bus == NULL) /* FIXME: not sure if this case is possible */ | ||
717 | return -ENODEV; | ||
718 | usb_hcd = bus_to_hcd(usb_bus); | ||
719 | result = sscanf(buf, "%u\n", &val); | ||
720 | if (result == 1) { | ||
721 | usb_hcd->authorized_default = val? 1 : 0; | ||
722 | result = size; | ||
723 | } | ||
724 | else | ||
725 | result = -EINVAL; | ||
726 | return result; | ||
674 | } | 727 | } |
675 | 728 | ||
729 | static DEVICE_ATTR(authorized_default, 0644, | ||
730 | usb_host_authorized_default_show, | ||
731 | usb_host_authorized_default_store); | ||
732 | |||
733 | |||
734 | /* Group all the USB bus attributes */ | ||
735 | static struct attribute *usb_bus_attrs[] = { | ||
736 | &dev_attr_authorized_default.attr, | ||
737 | NULL, | ||
738 | }; | ||
739 | |||
740 | static struct attribute_group usb_bus_attr_group = { | ||
741 | .name = NULL, /* we want them in the same directory */ | ||
742 | .attrs = usb_bus_attrs, | ||
743 | }; | ||
744 | |||
745 | |||
746 | |||
676 | /*-------------------------------------------------------------------------*/ | 747 | /*-------------------------------------------------------------------------*/ |
677 | 748 | ||
678 | static struct class *usb_host_class; | 749 | static struct class *usb_host_class; |
@@ -726,27 +797,23 @@ static void usb_bus_init (struct usb_bus *bus) | |||
726 | */ | 797 | */ |
727 | static int usb_register_bus(struct usb_bus *bus) | 798 | static int usb_register_bus(struct usb_bus *bus) |
728 | { | 799 | { |
800 | int result = -E2BIG; | ||
729 | int busnum; | 801 | int busnum; |
730 | 802 | ||
731 | mutex_lock(&usb_bus_list_lock); | 803 | mutex_lock(&usb_bus_list_lock); |
732 | busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); | 804 | busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); |
733 | if (busnum < USB_MAXBUS) { | 805 | if (busnum >= USB_MAXBUS) { |
734 | set_bit (busnum, busmap.busmap); | ||
735 | bus->busnum = busnum; | ||
736 | } else { | ||
737 | printk (KERN_ERR "%s: too many buses\n", usbcore_name); | 806 | printk (KERN_ERR "%s: too many buses\n", usbcore_name); |
738 | mutex_unlock(&usb_bus_list_lock); | 807 | goto error_find_busnum; |
739 | return -E2BIG; | ||
740 | } | 808 | } |
741 | 809 | set_bit (busnum, busmap.busmap); | |
810 | bus->busnum = busnum; | ||
742 | bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0), | 811 | bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0), |
743 | bus->controller, "usb_host%d", busnum); | 812 | bus->controller, "usb_host%d", |
744 | if (IS_ERR(bus->class_dev)) { | 813 | busnum); |
745 | clear_bit(busnum, busmap.busmap); | 814 | result = PTR_ERR(bus->class_dev); |
746 | mutex_unlock(&usb_bus_list_lock); | 815 | if (IS_ERR(bus->class_dev)) |
747 | return PTR_ERR(bus->class_dev); | 816 | goto error_create_class_dev; |
748 | } | ||
749 | |||
750 | class_set_devdata(bus->class_dev, bus); | 817 | class_set_devdata(bus->class_dev, bus); |
751 | 818 | ||
752 | /* Add it to the local list of buses */ | 819 | /* Add it to the local list of buses */ |
@@ -755,8 +822,15 @@ static int usb_register_bus(struct usb_bus *bus) | |||
755 | 822 | ||
756 | usb_notify_add_bus(bus); | 823 | usb_notify_add_bus(bus); |
757 | 824 | ||
758 | dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); | 825 | dev_info (bus->controller, "new USB bus registered, assigned bus " |
826 | "number %d\n", bus->busnum); | ||
759 | return 0; | 827 | return 0; |
828 | |||
829 | error_create_class_dev: | ||
830 | clear_bit(busnum, busmap.busmap); | ||
831 | error_find_busnum: | ||
832 | mutex_unlock(&usb_bus_list_lock); | ||
833 | return result; | ||
760 | } | 834 | } |
761 | 835 | ||
762 | /** | 836 | /** |
@@ -908,103 +982,145 @@ EXPORT_SYMBOL (usb_calc_bus_time); | |||
908 | 982 | ||
909 | /*-------------------------------------------------------------------------*/ | 983 | /*-------------------------------------------------------------------------*/ |
910 | 984 | ||
911 | static void urb_unlink(struct usb_hcd *hcd, struct urb *urb) | 985 | /** |
986 | * usb_hcd_link_urb_to_ep - add an URB to its endpoint queue | ||
987 | * @hcd: host controller to which @urb was submitted | ||
988 | * @urb: URB being submitted | ||
989 | * | ||
990 | * Host controller drivers should call this routine in their enqueue() | ||
991 | * method. The HCD's private spinlock must be held and interrupts must | ||
992 | * be disabled. The actions carried out here are required for URB | ||
993 | * submission, as well as for endpoint shutdown and for usb_kill_urb. | ||
994 | * | ||
995 | * Returns 0 for no error, otherwise a negative error code (in which case | ||
996 | * the enqueue() method must fail). If no error occurs but enqueue() fails | ||
997 | * anyway, it must call usb_hcd_unlink_urb_from_ep() before releasing | ||
998 | * the private spinlock and returning. | ||
999 | */ | ||
1000 | int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb) | ||
912 | { | 1001 | { |
913 | unsigned long flags; | 1002 | int rc = 0; |
914 | 1003 | ||
915 | /* clear all state linking urb to this dev (and hcd) */ | 1004 | spin_lock(&hcd_urb_list_lock); |
916 | spin_lock_irqsave(&hcd_urb_list_lock, flags); | ||
917 | list_del_init (&urb->urb_list); | ||
918 | spin_unlock_irqrestore(&hcd_urb_list_lock, flags); | ||
919 | 1005 | ||
920 | if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { | 1006 | /* Check that the URB isn't being killed */ |
921 | if (usb_pipecontrol (urb->pipe) | 1007 | if (unlikely(urb->reject)) { |
922 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1008 | rc = -EPERM; |
923 | dma_unmap_single (hcd->self.controller, urb->setup_dma, | 1009 | goto done; |
924 | sizeof (struct usb_ctrlrequest), | ||
925 | DMA_TO_DEVICE); | ||
926 | if (urb->transfer_buffer_length != 0 | ||
927 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | ||
928 | dma_unmap_single (hcd->self.controller, | ||
929 | urb->transfer_dma, | ||
930 | urb->transfer_buffer_length, | ||
931 | usb_pipein (urb->pipe) | ||
932 | ? DMA_FROM_DEVICE | ||
933 | : DMA_TO_DEVICE); | ||
934 | } | 1010 | } |
935 | } | ||
936 | |||
937 | /* may be called in any context with a valid urb->dev usecount | ||
938 | * caller surrenders "ownership" of urb | ||
939 | * expects usb_submit_urb() to have sanity checked and conditioned all | ||
940 | * inputs in the urb | ||
941 | */ | ||
942 | int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | ||
943 | { | ||
944 | int status; | ||
945 | struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); | ||
946 | struct usb_host_endpoint *ep; | ||
947 | unsigned long flags; | ||
948 | 1011 | ||
949 | if (!hcd) | 1012 | if (unlikely(!urb->ep->enabled)) { |
950 | return -ENODEV; | 1013 | rc = -ENOENT; |
1014 | goto done; | ||
1015 | } | ||
951 | 1016 | ||
952 | usbmon_urb_submit(&hcd->self, urb); | 1017 | if (unlikely(!urb->dev->can_submit)) { |
1018 | rc = -EHOSTUNREACH; | ||
1019 | goto done; | ||
1020 | } | ||
953 | 1021 | ||
954 | /* | 1022 | /* |
955 | * Atomically queue the urb, first to our records, then to the HCD. | 1023 | * Check the host controller's state and add the URB to the |
956 | * Access to urb->status is controlled by urb->lock ... changes on | 1024 | * endpoint's queue. |
957 | * i/o completion (normal or fault) or unlinking. | ||
958 | */ | 1025 | */ |
959 | 1026 | switch (hcd->state) { | |
960 | // FIXME: verify that quiescing hc works right (RH cleans up) | ||
961 | |||
962 | spin_lock_irqsave(&hcd_urb_list_lock, flags); | ||
963 | ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) | ||
964 | [usb_pipeendpoint(urb->pipe)]; | ||
965 | if (unlikely (!ep)) | ||
966 | status = -ENOENT; | ||
967 | else if (unlikely (urb->reject)) | ||
968 | status = -EPERM; | ||
969 | else switch (hcd->state) { | ||
970 | case HC_STATE_RUNNING: | 1027 | case HC_STATE_RUNNING: |
971 | case HC_STATE_RESUMING: | 1028 | case HC_STATE_RESUMING: |
972 | list_add_tail (&urb->urb_list, &ep->urb_list); | 1029 | urb->unlinked = 0; |
973 | status = 0; | 1030 | list_add_tail(&urb->urb_list, &urb->ep->urb_list); |
974 | break; | 1031 | break; |
975 | default: | 1032 | default: |
976 | status = -ESHUTDOWN; | 1033 | rc = -ESHUTDOWN; |
977 | break; | 1034 | goto done; |
978 | } | 1035 | } |
979 | spin_unlock_irqrestore(&hcd_urb_list_lock, flags); | 1036 | done: |
980 | if (status) { | 1037 | spin_unlock(&hcd_urb_list_lock); |
981 | INIT_LIST_HEAD (&urb->urb_list); | 1038 | return rc; |
982 | usbmon_urb_submit_error(&hcd->self, urb, status); | 1039 | } |
983 | return status; | 1040 | EXPORT_SYMBOL_GPL(usb_hcd_link_urb_to_ep); |
1041 | |||
1042 | /** | ||
1043 | * usb_hcd_check_unlink_urb - check whether an URB may be unlinked | ||
1044 | * @hcd: host controller to which @urb was submitted | ||
1045 | * @urb: URB being checked for unlinkability | ||
1046 | * @status: error code to store in @urb if the unlink succeeds | ||
1047 | * | ||
1048 | * Host controller drivers should call this routine in their dequeue() | ||
1049 | * method. The HCD's private spinlock must be held and interrupts must | ||
1050 | * be disabled. The actions carried out here are required for making | ||
1051 | * sure than an unlink is valid. | ||
1052 | * | ||
1053 | * Returns 0 for no error, otherwise a negative error code (in which case | ||
1054 | * the dequeue() method must fail). The possible error codes are: | ||
1055 | * | ||
1056 | * -EIDRM: @urb was not submitted or has already completed. | ||
1057 | * The completion function may not have been called yet. | ||
1058 | * | ||
1059 | * -EBUSY: @urb has already been unlinked. | ||
1060 | */ | ||
1061 | int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, | ||
1062 | int status) | ||
1063 | { | ||
1064 | struct list_head *tmp; | ||
1065 | |||
1066 | /* insist the urb is still queued */ | ||
1067 | list_for_each(tmp, &urb->ep->urb_list) { | ||
1068 | if (tmp == &urb->urb_list) | ||
1069 | break; | ||
984 | } | 1070 | } |
1071 | if (tmp != &urb->urb_list) | ||
1072 | return -EIDRM; | ||
985 | 1073 | ||
986 | /* increment urb's reference count as part of giving it to the HCD | 1074 | /* Any status except -EINPROGRESS means something already started to |
987 | * (which now controls it). HCD guarantees that it either returns | 1075 | * unlink this URB from the hardware. So there's no more work to do. |
988 | * an error or calls giveback(), but not both. | ||
989 | */ | 1076 | */ |
990 | urb = usb_get_urb (urb); | 1077 | if (urb->unlinked) |
991 | atomic_inc (&urb->use_count); | 1078 | return -EBUSY; |
992 | 1079 | urb->unlinked = status; | |
993 | if (is_root_hub(urb->dev)) { | 1080 | |
994 | /* NOTE: requirement on hub callers (usbfs and the hub | 1081 | /* IRQ setup can easily be broken so that USB controllers |
995 | * driver, for now) that URBs' urb->transfer_buffer be | 1082 | * never get completion IRQs ... maybe even the ones we need to |
996 | * valid and usb_buffer_{sync,unmap}() not be needed, since | 1083 | * finish unlinking the initial failed usb_set_address() |
997 | * they could clobber root hub response data. | 1084 | * or device descriptor fetch. |
998 | */ | 1085 | */ |
999 | status = rh_urb_enqueue (hcd, urb); | 1086 | if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && |
1000 | goto done; | 1087 | !is_root_hub(urb->dev)) { |
1088 | dev_warn(hcd->self.controller, "Unlink after no-IRQ? " | ||
1089 | "Controller is probably using the wrong IRQ.\n"); | ||
1090 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | ||
1001 | } | 1091 | } |
1002 | 1092 | ||
1003 | /* lower level hcd code should use *_dma exclusively, | 1093 | return 0; |
1094 | } | ||
1095 | EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb); | ||
1096 | |||
1097 | /** | ||
1098 | * usb_hcd_unlink_urb_from_ep - remove an URB from its endpoint queue | ||
1099 | * @hcd: host controller to which @urb was submitted | ||
1100 | * @urb: URB being unlinked | ||
1101 | * | ||
1102 | * Host controller drivers should call this routine before calling | ||
1103 | * usb_hcd_giveback_urb(). The HCD's private spinlock must be held and | ||
1104 | * interrupts must be disabled. The actions carried out here are required | ||
1105 | * for URB completion. | ||
1106 | */ | ||
1107 | void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb) | ||
1108 | { | ||
1109 | /* clear all state linking urb to this dev (and hcd) */ | ||
1110 | spin_lock(&hcd_urb_list_lock); | ||
1111 | list_del_init(&urb->urb_list); | ||
1112 | spin_unlock(&hcd_urb_list_lock); | ||
1113 | } | ||
1114 | EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep); | ||
1115 | |||
1116 | static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | ||
1117 | { | ||
1118 | /* Map the URB's buffers for DMA access. | ||
1119 | * Lower level HCD code should use *_dma exclusively, | ||
1004 | * unless it uses pio or talks to another transport. | 1120 | * unless it uses pio or talks to another transport. |
1005 | */ | 1121 | */ |
1006 | if (hcd->self.uses_dma) { | 1122 | if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { |
1007 | if (usb_pipecontrol (urb->pipe) | 1123 | if (usb_endpoint_xfer_control(&urb->ep->desc) |
1008 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | 1124 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) |
1009 | urb->setup_dma = dma_map_single ( | 1125 | urb->setup_dma = dma_map_single ( |
1010 | hcd->self.controller, | 1126 | hcd->self.controller, |
@@ -1017,20 +1133,75 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
1017 | hcd->self.controller, | 1133 | hcd->self.controller, |
1018 | urb->transfer_buffer, | 1134 | urb->transfer_buffer, |
1019 | urb->transfer_buffer_length, | 1135 | urb->transfer_buffer_length, |
1020 | usb_pipein (urb->pipe) | 1136 | usb_urb_dir_in(urb) |
1021 | ? DMA_FROM_DEVICE | 1137 | ? DMA_FROM_DEVICE |
1022 | : DMA_TO_DEVICE); | 1138 | : DMA_TO_DEVICE); |
1023 | } | 1139 | } |
1140 | } | ||
1024 | 1141 | ||
1025 | status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); | 1142 | static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) |
1026 | done: | 1143 | { |
1027 | if (unlikely (status)) { | 1144 | if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { |
1028 | urb_unlink(hcd, urb); | 1145 | if (usb_endpoint_xfer_control(&urb->ep->desc) |
1029 | atomic_dec (&urb->use_count); | 1146 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) |
1030 | if (urb->reject) | 1147 | dma_unmap_single(hcd->self.controller, urb->setup_dma, |
1031 | wake_up (&usb_kill_urb_queue); | 1148 | sizeof(struct usb_ctrlrequest), |
1149 | DMA_TO_DEVICE); | ||
1150 | if (urb->transfer_buffer_length != 0 | ||
1151 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | ||
1152 | dma_unmap_single(hcd->self.controller, | ||
1153 | urb->transfer_dma, | ||
1154 | urb->transfer_buffer_length, | ||
1155 | usb_urb_dir_in(urb) | ||
1156 | ? DMA_FROM_DEVICE | ||
1157 | : DMA_TO_DEVICE); | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | /*-------------------------------------------------------------------------*/ | ||
1162 | |||
1163 | /* may be called in any context with a valid urb->dev usecount | ||
1164 | * caller surrenders "ownership" of urb | ||
1165 | * expects usb_submit_urb() to have sanity checked and conditioned all | ||
1166 | * inputs in the urb | ||
1167 | */ | ||
1168 | int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | ||
1169 | { | ||
1170 | int status; | ||
1171 | struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); | ||
1172 | |||
1173 | /* increment urb's reference count as part of giving it to the HCD | ||
1174 | * (which will control it). HCD guarantees that it either returns | ||
1175 | * an error or calls giveback(), but not both. | ||
1176 | */ | ||
1177 | usb_get_urb(urb); | ||
1178 | atomic_inc(&urb->use_count); | ||
1179 | atomic_inc(&urb->dev->urbnum); | ||
1180 | usbmon_urb_submit(&hcd->self, urb); | ||
1181 | |||
1182 | /* NOTE requirements on root-hub callers (usbfs and the hub | ||
1183 | * driver, for now): URBs' urb->transfer_buffer must be | ||
1184 | * valid and usb_buffer_{sync,unmap}() not be needed, since | ||
1185 | * they could clobber root hub response data. Also, control | ||
1186 | * URBs must be submitted in process context with interrupts | ||
1187 | * enabled. | ||
1188 | */ | ||
1189 | map_urb_for_dma(hcd, urb); | ||
1190 | if (is_root_hub(urb->dev)) | ||
1191 | status = rh_urb_enqueue(hcd, urb); | ||
1192 | else | ||
1193 | status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); | ||
1194 | |||
1195 | if (unlikely(status)) { | ||
1032 | usbmon_urb_submit_error(&hcd->self, urb, status); | 1196 | usbmon_urb_submit_error(&hcd->self, urb, status); |
1033 | usb_put_urb (urb); | 1197 | unmap_urb_for_dma(hcd, urb); |
1198 | urb->hcpriv = NULL; | ||
1199 | INIT_LIST_HEAD(&urb->urb_list); | ||
1200 | atomic_dec(&urb->use_count); | ||
1201 | atomic_dec(&urb->dev->urbnum); | ||
1202 | if (urb->reject) | ||
1203 | wake_up(&usb_kill_urb_queue); | ||
1204 | usb_put_urb(urb); | ||
1034 | } | 1205 | } |
1035 | return status; | 1206 | return status; |
1036 | } | 1207 | } |
@@ -1042,24 +1213,19 @@ done: | |||
1042 | * soon as practical. we've already set up the urb's return status, | 1213 | * soon as practical. we've already set up the urb's return status, |
1043 | * but we can't know if the callback completed already. | 1214 | * but we can't know if the callback completed already. |
1044 | */ | 1215 | */ |
1045 | static int | 1216 | static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) |
1046 | unlink1 (struct usb_hcd *hcd, struct urb *urb) | ||
1047 | { | 1217 | { |
1048 | int value; | 1218 | int value; |
1049 | 1219 | ||
1050 | if (is_root_hub(urb->dev)) | 1220 | if (is_root_hub(urb->dev)) |
1051 | value = usb_rh_urb_dequeue (hcd, urb); | 1221 | value = usb_rh_urb_dequeue(hcd, urb, status); |
1052 | else { | 1222 | else { |
1053 | 1223 | ||
1054 | /* The only reason an HCD might fail this call is if | 1224 | /* The only reason an HCD might fail this call is if |
1055 | * it has not yet fully queued the urb to begin with. | 1225 | * it has not yet fully queued the urb to begin with. |
1056 | * Such failures should be harmless. */ | 1226 | * Such failures should be harmless. */ |
1057 | value = hcd->driver->urb_dequeue (hcd, urb); | 1227 | value = hcd->driver->urb_dequeue(hcd, urb, status); |
1058 | } | 1228 | } |
1059 | |||
1060 | if (value != 0) | ||
1061 | dev_dbg (hcd->self.controller, "dequeue %p --> %d\n", | ||
1062 | urb, value); | ||
1063 | return value; | 1229 | return value; |
1064 | } | 1230 | } |
1065 | 1231 | ||
@@ -1071,88 +1237,17 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) | |||
1071 | */ | 1237 | */ |
1072 | int usb_hcd_unlink_urb (struct urb *urb, int status) | 1238 | int usb_hcd_unlink_urb (struct urb *urb, int status) |
1073 | { | 1239 | { |
1074 | struct usb_host_endpoint *ep; | 1240 | struct usb_hcd *hcd; |
1075 | struct usb_hcd *hcd = NULL; | 1241 | int retval; |
1076 | struct device *sys = NULL; | ||
1077 | unsigned long flags; | ||
1078 | struct list_head *tmp; | ||
1079 | int retval; | ||
1080 | |||
1081 | if (!urb) | ||
1082 | return -EINVAL; | ||
1083 | if (!urb->dev || !urb->dev->bus) | ||
1084 | return -ENODEV; | ||
1085 | ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) | ||
1086 | [usb_pipeendpoint(urb->pipe)]; | ||
1087 | if (!ep) | ||
1088 | return -ENODEV; | ||
1089 | |||
1090 | /* | ||
1091 | * we contend for urb->status with the hcd core, | ||
1092 | * which changes it while returning the urb. | ||
1093 | * | ||
1094 | * Caller guaranteed that the urb pointer hasn't been freed, and | ||
1095 | * that it was submitted. But as a rule it can't know whether or | ||
1096 | * not it's already been unlinked ... so we respect the reversed | ||
1097 | * lock sequence needed for the usb_hcd_giveback_urb() code paths | ||
1098 | * (urb lock, then hcd_urb_list_lock) in case some other CPU is now | ||
1099 | * unlinking it. | ||
1100 | */ | ||
1101 | spin_lock_irqsave (&urb->lock, flags); | ||
1102 | spin_lock(&hcd_urb_list_lock); | ||
1103 | 1242 | ||
1104 | sys = &urb->dev->dev; | ||
1105 | hcd = bus_to_hcd(urb->dev->bus); | 1243 | hcd = bus_to_hcd(urb->dev->bus); |
1106 | if (hcd == NULL) { | 1244 | retval = unlink1(hcd, urb, status); |
1107 | retval = -ENODEV; | ||
1108 | goto done; | ||
1109 | } | ||
1110 | 1245 | ||
1111 | /* insist the urb is still queued */ | ||
1112 | list_for_each(tmp, &ep->urb_list) { | ||
1113 | if (tmp == &urb->urb_list) | ||
1114 | break; | ||
1115 | } | ||
1116 | if (tmp != &urb->urb_list) { | ||
1117 | retval = -EIDRM; | ||
1118 | goto done; | ||
1119 | } | ||
1120 | |||
1121 | /* Any status except -EINPROGRESS means something already started to | ||
1122 | * unlink this URB from the hardware. So there's no more work to do. | ||
1123 | */ | ||
1124 | if (urb->status != -EINPROGRESS) { | ||
1125 | retval = -EBUSY; | ||
1126 | goto done; | ||
1127 | } | ||
1128 | |||
1129 | /* IRQ setup can easily be broken so that USB controllers | ||
1130 | * never get completion IRQs ... maybe even the ones we need to | ||
1131 | * finish unlinking the initial failed usb_set_address() | ||
1132 | * or device descriptor fetch. | ||
1133 | */ | ||
1134 | if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && | ||
1135 | !is_root_hub(urb->dev)) { | ||
1136 | dev_warn (hcd->self.controller, "Unlink after no-IRQ? " | ||
1137 | "Controller is probably using the wrong IRQ.\n"); | ||
1138 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | ||
1139 | } | ||
1140 | |||
1141 | urb->status = status; | ||
1142 | |||
1143 | spin_unlock(&hcd_urb_list_lock); | ||
1144 | spin_unlock_irqrestore (&urb->lock, flags); | ||
1145 | |||
1146 | retval = unlink1 (hcd, urb); | ||
1147 | if (retval == 0) | 1246 | if (retval == 0) |
1148 | retval = -EINPROGRESS; | 1247 | retval = -EINPROGRESS; |
1149 | return retval; | 1248 | else if (retval != -EIDRM && retval != -EBUSY) |
1150 | 1249 | dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n", | |
1151 | done: | 1250 | urb, retval); |
1152 | spin_unlock(&hcd_urb_list_lock); | ||
1153 | spin_unlock_irqrestore (&urb->lock, flags); | ||
1154 | if (retval != -EIDRM && sys && sys->driver) | ||
1155 | dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); | ||
1156 | return retval; | 1251 | return retval; |
1157 | } | 1252 | } |
1158 | 1253 | ||
@@ -1162,6 +1257,7 @@ done: | |||
1162 | * usb_hcd_giveback_urb - return URB from HCD to device driver | 1257 | * usb_hcd_giveback_urb - return URB from HCD to device driver |
1163 | * @hcd: host controller returning the URB | 1258 | * @hcd: host controller returning the URB |
1164 | * @urb: urb being returned to the USB device driver. | 1259 | * @urb: urb being returned to the USB device driver. |
1260 | * @status: completion status code for the URB. | ||
1165 | * Context: in_interrupt() | 1261 | * Context: in_interrupt() |
1166 | * | 1262 | * |
1167 | * This hands the URB from HCD to its USB device driver, using its | 1263 | * This hands the URB from HCD to its USB device driver, using its |
@@ -1169,14 +1265,27 @@ done: | |||
1169 | * (and is done using urb->hcpriv). It also released all HCD locks; | 1265 | * (and is done using urb->hcpriv). It also released all HCD locks; |
1170 | * the device driver won't cause problems if it frees, modifies, | 1266 | * the device driver won't cause problems if it frees, modifies, |
1171 | * or resubmits this URB. | 1267 | * or resubmits this URB. |
1268 | * | ||
1269 | * If @urb was unlinked, the value of @status will be overridden by | ||
1270 | * @urb->unlinked. Erroneous short transfers are detected in case | ||
1271 | * the HCD hasn't checked for them. | ||
1172 | */ | 1272 | */ |
1173 | void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) | 1273 | void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) |
1174 | { | 1274 | { |
1175 | urb_unlink(hcd, urb); | 1275 | urb->hcpriv = NULL; |
1176 | usbmon_urb_complete (&hcd->self, urb); | 1276 | if (unlikely(urb->unlinked)) |
1277 | status = urb->unlinked; | ||
1278 | else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && | ||
1279 | urb->actual_length < urb->transfer_buffer_length && | ||
1280 | !status)) | ||
1281 | status = -EREMOTEIO; | ||
1282 | |||
1283 | unmap_urb_for_dma(hcd, urb); | ||
1284 | usbmon_urb_complete(&hcd->self, urb, status); | ||
1177 | usb_unanchor_urb(urb); | 1285 | usb_unanchor_urb(urb); |
1178 | 1286 | ||
1179 | /* pass ownership to the completion handler */ | 1287 | /* pass ownership to the completion handler */ |
1288 | urb->status = status; | ||
1180 | urb->complete (urb); | 1289 | urb->complete (urb); |
1181 | atomic_dec (&urb->use_count); | 1290 | atomic_dec (&urb->use_count); |
1182 | if (unlikely (urb->reject)) | 1291 | if (unlikely (urb->reject)) |
@@ -1187,78 +1296,61 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb); | |||
1187 | 1296 | ||
1188 | /*-------------------------------------------------------------------------*/ | 1297 | /*-------------------------------------------------------------------------*/ |
1189 | 1298 | ||
1190 | /* disables the endpoint: cancels any pending urbs, then synchronizes with | 1299 | /* Cancel all URBs pending on this endpoint and wait for the endpoint's |
1191 | * the hcd to make sure all endpoint state is gone from hardware, and then | 1300 | * queue to drain completely. The caller must first insure that no more |
1192 | * waits until the endpoint's queue is completely drained. use for | 1301 | * URBs can be submitted for this endpoint. |
1193 | * set_configuration, set_interface, driver removal, physical disconnect. | ||
1194 | * | ||
1195 | * example: a qh stored in ep->hcpriv, holding state related to endpoint | ||
1196 | * type, maxpacket size, toggle, halt status, and scheduling. | ||
1197 | */ | 1302 | */ |
1198 | void usb_hcd_endpoint_disable (struct usb_device *udev, | 1303 | void usb_hcd_flush_endpoint(struct usb_device *udev, |
1199 | struct usb_host_endpoint *ep) | 1304 | struct usb_host_endpoint *ep) |
1200 | { | 1305 | { |
1201 | struct usb_hcd *hcd; | 1306 | struct usb_hcd *hcd; |
1202 | struct urb *urb; | 1307 | struct urb *urb; |
1203 | 1308 | ||
1309 | if (!ep) | ||
1310 | return; | ||
1311 | might_sleep(); | ||
1204 | hcd = bus_to_hcd(udev->bus); | 1312 | hcd = bus_to_hcd(udev->bus); |
1205 | local_irq_disable (); | ||
1206 | 1313 | ||
1207 | /* ep is already gone from udev->ep_{in,out}[]; no more submits */ | 1314 | /* No more submits can occur */ |
1208 | rescan: | 1315 | rescan: |
1209 | spin_lock(&hcd_urb_list_lock); | 1316 | spin_lock_irq(&hcd_urb_list_lock); |
1210 | list_for_each_entry (urb, &ep->urb_list, urb_list) { | 1317 | list_for_each_entry (urb, &ep->urb_list, urb_list) { |
1211 | int tmp; | 1318 | int is_in; |
1212 | 1319 | ||
1213 | /* the urb may already have been unlinked */ | 1320 | if (urb->unlinked) |
1214 | if (urb->status != -EINPROGRESS) | ||
1215 | continue; | 1321 | continue; |
1216 | usb_get_urb (urb); | 1322 | usb_get_urb (urb); |
1323 | is_in = usb_urb_dir_in(urb); | ||
1217 | spin_unlock(&hcd_urb_list_lock); | 1324 | spin_unlock(&hcd_urb_list_lock); |
1218 | 1325 | ||
1219 | spin_lock (&urb->lock); | 1326 | /* kick hcd */ |
1220 | tmp = urb->status; | 1327 | unlink1(hcd, urb, -ESHUTDOWN); |
1221 | if (tmp == -EINPROGRESS) | 1328 | dev_dbg (hcd->self.controller, |
1222 | urb->status = -ESHUTDOWN; | 1329 | "shutdown urb %p ep%d%s%s\n", |
1223 | spin_unlock (&urb->lock); | 1330 | urb, usb_endpoint_num(&ep->desc), |
1224 | 1331 | is_in ? "in" : "out", | |
1225 | /* kick hcd unless it's already returning this */ | 1332 | ({ char *s; |
1226 | if (tmp == -EINPROGRESS) { | 1333 | |
1227 | tmp = urb->pipe; | 1334 | switch (usb_endpoint_type(&ep->desc)) { |
1228 | unlink1 (hcd, urb); | 1335 | case USB_ENDPOINT_XFER_CONTROL: |
1229 | dev_dbg (hcd->self.controller, | 1336 | s = ""; break; |
1230 | "shutdown urb %p pipe %08x ep%d%s%s\n", | 1337 | case USB_ENDPOINT_XFER_BULK: |
1231 | urb, tmp, usb_pipeendpoint (tmp), | 1338 | s = "-bulk"; break; |
1232 | (tmp & USB_DIR_IN) ? "in" : "out", | 1339 | case USB_ENDPOINT_XFER_INT: |
1233 | ({ char *s; \ | 1340 | s = "-intr"; break; |
1234 | switch (usb_pipetype (tmp)) { \ | 1341 | default: |
1235 | case PIPE_CONTROL: s = ""; break; \ | 1342 | s = "-iso"; break; |
1236 | case PIPE_BULK: s = "-bulk"; break; \ | 1343 | }; |
1237 | case PIPE_INTERRUPT: s = "-intr"; break; \ | 1344 | s; |
1238 | default: s = "-iso"; break; \ | 1345 | })); |
1239 | }; s;})); | ||
1240 | } | ||
1241 | usb_put_urb (urb); | 1346 | usb_put_urb (urb); |
1242 | 1347 | ||
1243 | /* list contents may have changed */ | 1348 | /* list contents may have changed */ |
1244 | goto rescan; | 1349 | goto rescan; |
1245 | } | 1350 | } |
1246 | spin_unlock(&hcd_urb_list_lock); | 1351 | spin_unlock_irq(&hcd_urb_list_lock); |
1247 | local_irq_enable (); | ||
1248 | |||
1249 | /* synchronize with the hardware, so old configuration state | ||
1250 | * clears out immediately (and will be freed). | ||
1251 | */ | ||
1252 | might_sleep (); | ||
1253 | if (hcd->driver->endpoint_disable) | ||
1254 | hcd->driver->endpoint_disable (hcd, ep); | ||
1255 | 1352 | ||
1256 | /* Wait until the endpoint queue is completely empty. Most HCDs | 1353 | /* Wait until the endpoint queue is completely empty */ |
1257 | * will have done this already in their endpoint_disable method, | ||
1258 | * but some might not. And there could be root-hub control URBs | ||
1259 | * still pending since they aren't affected by the HCDs' | ||
1260 | * endpoint_disable methods. | ||
1261 | */ | ||
1262 | while (!list_empty (&ep->urb_list)) { | 1354 | while (!list_empty (&ep->urb_list)) { |
1263 | spin_lock_irq(&hcd_urb_list_lock); | 1355 | spin_lock_irq(&hcd_urb_list_lock); |
1264 | 1356 | ||
@@ -1278,6 +1370,25 @@ rescan: | |||
1278 | } | 1370 | } |
1279 | } | 1371 | } |
1280 | 1372 | ||
1373 | /* Disables the endpoint: synchronizes with the hcd to make sure all | ||
1374 | * endpoint state is gone from hardware. usb_hcd_flush_endpoint() must | ||
1375 | * have been called previously. Use for set_configuration, set_interface, | ||
1376 | * driver removal, physical disconnect. | ||
1377 | * | ||
1378 | * example: a qh stored in ep->hcpriv, holding state related to endpoint | ||
1379 | * type, maxpacket size, toggle, halt status, and scheduling. | ||
1380 | */ | ||
1381 | void usb_hcd_disable_endpoint(struct usb_device *udev, | ||
1382 | struct usb_host_endpoint *ep) | ||
1383 | { | ||
1384 | struct usb_hcd *hcd; | ||
1385 | |||
1386 | might_sleep(); | ||
1387 | hcd = bus_to_hcd(udev->bus); | ||
1388 | if (hcd->driver->endpoint_disable) | ||
1389 | hcd->driver->endpoint_disable(hcd, ep); | ||
1390 | } | ||
1391 | |||
1281 | /*-------------------------------------------------------------------------*/ | 1392 | /*-------------------------------------------------------------------------*/ |
1282 | 1393 | ||
1283 | /* called in any context */ | 1394 | /* called in any context */ |
@@ -1525,7 +1636,6 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1525 | hcd->driver = driver; | 1636 | hcd->driver = driver; |
1526 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : | 1637 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : |
1527 | "USB Host Controller"; | 1638 | "USB Host Controller"; |
1528 | |||
1529 | return hcd; | 1639 | return hcd; |
1530 | } | 1640 | } |
1531 | EXPORT_SYMBOL (usb_create_hcd); | 1641 | EXPORT_SYMBOL (usb_create_hcd); |
@@ -1570,6 +1680,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1570 | 1680 | ||
1571 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); | 1681 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); |
1572 | 1682 | ||
1683 | hcd->authorized_default = hcd->wireless? 0 : 1; | ||
1573 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 1684 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
1574 | 1685 | ||
1575 | /* HC is in reset state, but accessible. Now do the one-time init, | 1686 | /* HC is in reset state, but accessible. Now do the one-time init, |
@@ -1646,10 +1757,20 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1646 | if ((retval = register_root_hub(hcd)) != 0) | 1757 | if ((retval = register_root_hub(hcd)) != 0) |
1647 | goto err_register_root_hub; | 1758 | goto err_register_root_hub; |
1648 | 1759 | ||
1760 | retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group); | ||
1761 | if (retval < 0) { | ||
1762 | printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n", | ||
1763 | retval); | ||
1764 | goto error_create_attr_group; | ||
1765 | } | ||
1649 | if (hcd->uses_new_polling && hcd->poll_rh) | 1766 | if (hcd->uses_new_polling && hcd->poll_rh) |
1650 | usb_hcd_poll_rh_status(hcd); | 1767 | usb_hcd_poll_rh_status(hcd); |
1651 | return retval; | 1768 | return retval; |
1652 | 1769 | ||
1770 | error_create_attr_group: | ||
1771 | mutex_lock(&usb_bus_list_lock); | ||
1772 | usb_disconnect(&hcd->self.root_hub); | ||
1773 | mutex_unlock(&usb_bus_list_lock); | ||
1653 | err_register_root_hub: | 1774 | err_register_root_hub: |
1654 | hcd->driver->stop(hcd); | 1775 | hcd->driver->stop(hcd); |
1655 | err_hcd_driver_start: | 1776 | err_hcd_driver_start: |
@@ -1691,6 +1812,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
1691 | cancel_work_sync(&hcd->wakeup_work); | 1812 | cancel_work_sync(&hcd->wakeup_work); |
1692 | #endif | 1813 | #endif |
1693 | 1814 | ||
1815 | sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group); | ||
1694 | mutex_lock(&usb_bus_list_lock); | 1816 | mutex_lock(&usb_bus_list_lock); |
1695 | usb_disconnect(&hcd->self.root_hub); | 1817 | usb_disconnect(&hcd->self.root_hub); |
1696 | mutex_unlock(&usb_bus_list_lock); | 1818 | mutex_unlock(&usb_bus_list_lock); |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index b5ebb73c2332..98e24194a4ab 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #ifdef __KERNEL__ | 20 | #ifdef __KERNEL__ |
21 | 21 | ||
22 | #include <linux/rwsem.h> | ||
23 | |||
22 | /* This file contains declarations of usbcore internals that are mostly | 24 | /* This file contains declarations of usbcore internals that are mostly |
23 | * used or exposed by Host Controller Drivers. | 25 | * used or exposed by Host Controller Drivers. |
24 | */ | 26 | */ |
@@ -51,6 +53,12 @@ | |||
51 | * | 53 | * |
52 | * Since "struct usb_bus" is so thin, you can't share much code in it. | 54 | * Since "struct usb_bus" is so thin, you can't share much code in it. |
53 | * This framework is a layer over that, and should be more sharable. | 55 | * This framework is a layer over that, and should be more sharable. |
56 | * | ||
57 | * @authorized_default: Specifies if new devices are authorized to | ||
58 | * connect by default or they require explicit | ||
59 | * user space authorization; this bit is settable | ||
60 | * through /sys/class/usb_host/X/authorized_default. | ||
61 | * For the rest is RO, so we don't lock to r/w it. | ||
54 | */ | 62 | */ |
55 | 63 | ||
56 | /*-------------------------------------------------------------------------*/ | 64 | /*-------------------------------------------------------------------------*/ |
@@ -90,6 +98,7 @@ struct usb_hcd { | |||
90 | unsigned poll_rh:1; /* poll for rh status? */ | 98 | unsigned poll_rh:1; /* poll for rh status? */ |
91 | unsigned poll_pending:1; /* status has changed? */ | 99 | unsigned poll_pending:1; /* status has changed? */ |
92 | unsigned wireless:1; /* Wireless USB HCD */ | 100 | unsigned wireless:1; /* Wireless USB HCD */ |
101 | unsigned authorized_default:1; | ||
93 | 102 | ||
94 | int irq; /* irq allocated */ | 103 | int irq; /* irq allocated */ |
95 | void __iomem *regs; /* device memory/io */ | 104 | void __iomem *regs; /* device memory/io */ |
@@ -182,11 +191,10 @@ struct hc_driver { | |||
182 | int (*get_frame_number) (struct usb_hcd *hcd); | 191 | int (*get_frame_number) (struct usb_hcd *hcd); |
183 | 192 | ||
184 | /* manage i/o requests, device state */ | 193 | /* manage i/o requests, device state */ |
185 | int (*urb_enqueue) (struct usb_hcd *hcd, | 194 | int (*urb_enqueue)(struct usb_hcd *hcd, |
186 | struct usb_host_endpoint *ep, | 195 | struct urb *urb, gfp_t mem_flags); |
187 | struct urb *urb, | 196 | int (*urb_dequeue)(struct usb_hcd *hcd, |
188 | gfp_t mem_flags); | 197 | struct urb *urb, int status); |
189 | int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); | ||
190 | 198 | ||
191 | /* hw synch, freeing endpoint resources that urb_dequeue can't */ | 199 | /* hw synch, freeing endpoint resources that urb_dequeue can't */ |
192 | void (*endpoint_disable)(struct usb_hcd *hcd, | 200 | void (*endpoint_disable)(struct usb_hcd *hcd, |
@@ -204,10 +212,18 @@ struct hc_driver { | |||
204 | /* Needed only if port-change IRQs are level-triggered */ | 212 | /* Needed only if port-change IRQs are level-triggered */ |
205 | }; | 213 | }; |
206 | 214 | ||
215 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); | ||
216 | extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, | ||
217 | int status); | ||
218 | extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb); | ||
219 | |||
207 | extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); | 220 | extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); |
208 | extern int usb_hcd_unlink_urb (struct urb *urb, int status); | 221 | extern int usb_hcd_unlink_urb (struct urb *urb, int status); |
209 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb); | 222 | extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, |
210 | extern void usb_hcd_endpoint_disable (struct usb_device *udev, | 223 | int status); |
224 | extern void usb_hcd_flush_endpoint(struct usb_device *udev, | ||
225 | struct usb_host_endpoint *ep); | ||
226 | extern void usb_hcd_disable_endpoint(struct usb_device *udev, | ||
211 | struct usb_host_endpoint *ep); | 227 | struct usb_host_endpoint *ep); |
212 | extern int usb_hcd_get_frame_number (struct usb_device *udev); | 228 | extern int usb_hcd_get_frame_number (struct usb_device *udev); |
213 | 229 | ||
@@ -402,7 +418,7 @@ static inline void usbfs_cleanup(void) { } | |||
402 | struct usb_mon_operations { | 418 | struct usb_mon_operations { |
403 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); | 419 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); |
404 | void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); | 420 | void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); |
405 | void (*urb_complete)(struct usb_bus *bus, struct urb *urb); | 421 | void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status); |
406 | /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ | 422 | /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ |
407 | }; | 423 | }; |
408 | 424 | ||
@@ -421,10 +437,11 @@ static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, | |||
421 | (*mon_ops->urb_submit_error)(bus, urb, error); | 437 | (*mon_ops->urb_submit_error)(bus, urb, error); |
422 | } | 438 | } |
423 | 439 | ||
424 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) | 440 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, |
441 | int status) | ||
425 | { | 442 | { |
426 | if (bus->monitored) | 443 | if (bus->monitored) |
427 | (*mon_ops->urb_complete)(bus, urb); | 444 | (*mon_ops->urb_complete)(bus, urb, status); |
428 | } | 445 | } |
429 | 446 | ||
430 | int usb_mon_register(struct usb_mon_operations *ops); | 447 | int usb_mon_register(struct usb_mon_operations *ops); |
@@ -435,7 +452,8 @@ void usb_mon_deregister(void); | |||
435 | static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} | 452 | static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} |
436 | static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, | 453 | static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, |
437 | int error) {} | 454 | int error) {} |
438 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {} | 455 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, |
456 | int status) {} | ||
439 | 457 | ||
440 | #endif /* CONFIG_USB_MON */ | 458 | #endif /* CONFIG_USB_MON */ |
441 | 459 | ||
@@ -454,5 +472,9 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {} | |||
454 | : (in_interrupt () ? "in_interrupt" : "can sleep")) | 472 | : (in_interrupt () ? "in_interrupt" : "can sleep")) |
455 | 473 | ||
456 | 474 | ||
457 | #endif /* __KERNEL__ */ | 475 | /* This rwsem is for use only by the hub driver and ehci-hcd. |
476 | * Nobody else should touch it. | ||
477 | */ | ||
478 | extern struct rw_semaphore ehci_cf_port_reset_rwsem; | ||
458 | 479 | ||
480 | #endif /* __KERNEL__ */ | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f7b337feb3ea..d20cb545a6e4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -125,6 +125,12 @@ MODULE_PARM_DESC(use_both_schemes, | |||
125 | "try the other device initialization scheme if the " | 125 | "try the other device initialization scheme if the " |
126 | "first one fails"); | 126 | "first one fails"); |
127 | 127 | ||
128 | /* Mutual exclusion for EHCI CF initialization. This interferes with | ||
129 | * port reset on some companion controllers. | ||
130 | */ | ||
131 | DECLARE_RWSEM(ehci_cf_port_reset_rwsem); | ||
132 | EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); | ||
133 | |||
128 | 134 | ||
129 | static inline char *portspeed(int portstatus) | 135 | static inline char *portspeed(int portstatus) |
130 | { | 136 | { |
@@ -347,11 +353,11 @@ void usb_kick_khubd(struct usb_device *hdev) | |||
347 | static void hub_irq(struct urb *urb) | 353 | static void hub_irq(struct urb *urb) |
348 | { | 354 | { |
349 | struct usb_hub *hub = urb->context; | 355 | struct usb_hub *hub = urb->context; |
350 | int status; | 356 | int status = urb->status; |
351 | int i; | 357 | int i; |
352 | unsigned long bits; | 358 | unsigned long bits; |
353 | 359 | ||
354 | switch (urb->status) { | 360 | switch (status) { |
355 | case -ENOENT: /* synchronous unlink */ | 361 | case -ENOENT: /* synchronous unlink */ |
356 | case -ECONNRESET: /* async unlink */ | 362 | case -ECONNRESET: /* async unlink */ |
357 | case -ESHUTDOWN: /* hardware going away */ | 363 | case -ESHUTDOWN: /* hardware going away */ |
@@ -359,10 +365,10 @@ static void hub_irq(struct urb *urb) | |||
359 | 365 | ||
360 | default: /* presumably an error */ | 366 | default: /* presumably an error */ |
361 | /* Cause a hub reset after 10 consecutive errors */ | 367 | /* Cause a hub reset after 10 consecutive errors */ |
362 | dev_dbg (hub->intfdev, "transfer --> %d\n", urb->status); | 368 | dev_dbg (hub->intfdev, "transfer --> %d\n", status); |
363 | if ((++hub->nerrors < 10) || hub->error) | 369 | if ((++hub->nerrors < 10) || hub->error) |
364 | goto resubmit; | 370 | goto resubmit; |
365 | hub->error = urb->status; | 371 | hub->error = status; |
366 | /* FALL THROUGH */ | 372 | /* FALL THROUGH */ |
367 | 373 | ||
368 | /* let khubd handle things */ | 374 | /* let khubd handle things */ |
@@ -1220,54 +1226,14 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) | |||
1220 | #endif | 1226 | #endif |
1221 | 1227 | ||
1222 | /** | 1228 | /** |
1223 | * usb_new_device - perform initial device setup (usbcore-internal) | 1229 | * usb_configure_device_otg - FIXME (usbcore-internal) |
1224 | * @udev: newly addressed device (in ADDRESS state) | 1230 | * @udev: newly addressed device (in ADDRESS state) |
1225 | * | 1231 | * |
1226 | * This is called with devices which have been enumerated, but not yet | 1232 | * Do configuration for On-The-Go devices |
1227 | * configured. The device descriptor is available, but not descriptors | ||
1228 | * for any device configuration. The caller must have locked either | ||
1229 | * the parent hub (if udev is a normal device) or else the | ||
1230 | * usb_bus_list_lock (if udev is a root hub). The parent's pointer to | ||
1231 | * udev has already been installed, but udev is not yet visible through | ||
1232 | * sysfs or other filesystem code. | ||
1233 | * | ||
1234 | * It will return if the device is configured properly or not. Zero if | ||
1235 | * the interface was registered with the driver core; else a negative | ||
1236 | * errno value. | ||
1237 | * | ||
1238 | * This call is synchronous, and may not be used in an interrupt context. | ||
1239 | * | ||
1240 | * Only the hub driver or root-hub registrar should ever call this. | ||
1241 | */ | 1233 | */ |
1242 | int usb_new_device(struct usb_device *udev) | 1234 | static int usb_configure_device_otg(struct usb_device *udev) |
1243 | { | 1235 | { |
1244 | int err; | 1236 | int err = 0; |
1245 | |||
1246 | /* Determine quirks */ | ||
1247 | usb_detect_quirks(udev); | ||
1248 | |||
1249 | err = usb_get_configuration(udev); | ||
1250 | if (err < 0) { | ||
1251 | dev_err(&udev->dev, "can't read configurations, error %d\n", | ||
1252 | err); | ||
1253 | goto fail; | ||
1254 | } | ||
1255 | |||
1256 | /* read the standard strings and cache them if present */ | ||
1257 | udev->product = usb_cache_string(udev, udev->descriptor.iProduct); | ||
1258 | udev->manufacturer = usb_cache_string(udev, | ||
1259 | udev->descriptor.iManufacturer); | ||
1260 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); | ||
1261 | |||
1262 | /* Tell the world! */ | ||
1263 | dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " | ||
1264 | "SerialNumber=%d\n", | ||
1265 | udev->descriptor.iManufacturer, | ||
1266 | udev->descriptor.iProduct, | ||
1267 | udev->descriptor.iSerialNumber); | ||
1268 | show_string(udev, "Product", udev->product); | ||
1269 | show_string(udev, "Manufacturer", udev->manufacturer); | ||
1270 | show_string(udev, "SerialNumber", udev->serial); | ||
1271 | 1237 | ||
1272 | #ifdef CONFIG_USB_OTG | 1238 | #ifdef CONFIG_USB_OTG |
1273 | /* | 1239 | /* |
@@ -1329,8 +1295,82 @@ int usb_new_device(struct usb_device *udev) | |||
1329 | err = -ENOTSUPP; | 1295 | err = -ENOTSUPP; |
1330 | goto fail; | 1296 | goto fail; |
1331 | } | 1297 | } |
1298 | fail: | ||
1332 | #endif | 1299 | #endif |
1300 | return err; | ||
1301 | } | ||
1302 | |||
1303 | |||
1304 | /** | ||
1305 | * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal) | ||
1306 | * @udev: newly addressed device (in ADDRESS state) | ||
1307 | * | ||
1308 | * This is only called by usb_new_device() and usb_authorize_device() | ||
1309 | * and FIXME -- all comments that apply to them apply here wrt to | ||
1310 | * environment. | ||
1311 | * | ||
1312 | * If the device is WUSB and not authorized, we don't attempt to read | ||
1313 | * the string descriptors, as they will be errored out by the device | ||
1314 | * until it has been authorized. | ||
1315 | */ | ||
1316 | static int usb_configure_device(struct usb_device *udev) | ||
1317 | { | ||
1318 | int err; | ||
1333 | 1319 | ||
1320 | if (udev->config == NULL) { | ||
1321 | err = usb_get_configuration(udev); | ||
1322 | if (err < 0) { | ||
1323 | dev_err(&udev->dev, "can't read configurations, error %d\n", | ||
1324 | err); | ||
1325 | goto fail; | ||
1326 | } | ||
1327 | } | ||
1328 | if (udev->wusb == 1 && udev->authorized == 0) { | ||
1329 | udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1330 | udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1331 | udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1332 | } | ||
1333 | else { | ||
1334 | /* read the standard strings and cache them if present */ | ||
1335 | udev->product = usb_cache_string(udev, udev->descriptor.iProduct); | ||
1336 | udev->manufacturer = usb_cache_string(udev, | ||
1337 | udev->descriptor.iManufacturer); | ||
1338 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); | ||
1339 | } | ||
1340 | err = usb_configure_device_otg(udev); | ||
1341 | fail: | ||
1342 | return err; | ||
1343 | } | ||
1344 | |||
1345 | |||
1346 | /** | ||
1347 | * usb_new_device - perform initial device setup (usbcore-internal) | ||
1348 | * @udev: newly addressed device (in ADDRESS state) | ||
1349 | * | ||
1350 | * This is called with devices which have been enumerated, but not yet | ||
1351 | * configured. The device descriptor is available, but not descriptors | ||
1352 | * for any device configuration. The caller must have locked either | ||
1353 | * the parent hub (if udev is a normal device) or else the | ||
1354 | * usb_bus_list_lock (if udev is a root hub). The parent's pointer to | ||
1355 | * udev has already been installed, but udev is not yet visible through | ||
1356 | * sysfs or other filesystem code. | ||
1357 | * | ||
1358 | * It will return if the device is configured properly or not. Zero if | ||
1359 | * the interface was registered with the driver core; else a negative | ||
1360 | * errno value. | ||
1361 | * | ||
1362 | * This call is synchronous, and may not be used in an interrupt context. | ||
1363 | * | ||
1364 | * Only the hub driver or root-hub registrar should ever call this. | ||
1365 | */ | ||
1366 | int usb_new_device(struct usb_device *udev) | ||
1367 | { | ||
1368 | int err; | ||
1369 | |||
1370 | usb_detect_quirks(udev); /* Determine quirks */ | ||
1371 | err = usb_configure_device(udev); /* detect & probe dev/intfs */ | ||
1372 | if (err < 0) | ||
1373 | goto fail; | ||
1334 | /* export the usbdev device-node for libusb */ | 1374 | /* export the usbdev device-node for libusb */ |
1335 | udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, | 1375 | udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, |
1336 | (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); | 1376 | (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); |
@@ -1346,19 +1386,106 @@ int usb_new_device(struct usb_device *udev) | |||
1346 | err = device_add(&udev->dev); | 1386 | err = device_add(&udev->dev); |
1347 | if (err) { | 1387 | if (err) { |
1348 | dev_err(&udev->dev, "can't device_add, error %d\n", err); | 1388 | dev_err(&udev->dev, "can't device_add, error %d\n", err); |
1349 | if (udev->parent) | ||
1350 | usb_autosuspend_device(udev->parent); | ||
1351 | goto fail; | 1389 | goto fail; |
1352 | } | 1390 | } |
1353 | 1391 | ||
1354 | exit: | 1392 | /* Tell the world! */ |
1393 | dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, " | ||
1394 | "SerialNumber=%d\n", | ||
1395 | udev->descriptor.iManufacturer, | ||
1396 | udev->descriptor.iProduct, | ||
1397 | udev->descriptor.iSerialNumber); | ||
1398 | show_string(udev, "Product", udev->product); | ||
1399 | show_string(udev, "Manufacturer", udev->manufacturer); | ||
1400 | show_string(udev, "SerialNumber", udev->serial); | ||
1355 | return err; | 1401 | return err; |
1356 | 1402 | ||
1357 | fail: | 1403 | fail: |
1358 | usb_set_device_state(udev, USB_STATE_NOTATTACHED); | 1404 | usb_set_device_state(udev, USB_STATE_NOTATTACHED); |
1359 | goto exit; | 1405 | return err; |
1360 | } | 1406 | } |
1361 | 1407 | ||
1408 | |||
1409 | /** | ||
1410 | * Similar to usb_disconnect() | ||
1411 | * | ||
1412 | * We share a lock (that we have) with device_del(), so we need to | ||
1413 | * defer its call. | ||
1414 | */ | ||
1415 | int usb_deauthorize_device(struct usb_device *usb_dev) | ||
1416 | { | ||
1417 | unsigned cnt; | ||
1418 | usb_lock_device(usb_dev); | ||
1419 | if (usb_dev->authorized == 0) | ||
1420 | goto out_unauthorized; | ||
1421 | usb_dev->authorized = 0; | ||
1422 | usb_set_configuration(usb_dev, -1); | ||
1423 | usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1424 | usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1425 | usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); | ||
1426 | kfree(usb_dev->config); | ||
1427 | usb_dev->config = NULL; | ||
1428 | for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++) | ||
1429 | kfree(usb_dev->rawdescriptors[cnt]); | ||
1430 | usb_dev->descriptor.bNumConfigurations = 0; | ||
1431 | kfree(usb_dev->rawdescriptors); | ||
1432 | out_unauthorized: | ||
1433 | usb_unlock_device(usb_dev); | ||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | int usb_authorize_device(struct usb_device *usb_dev) | ||
1439 | { | ||
1440 | int result = 0, c; | ||
1441 | usb_lock_device(usb_dev); | ||
1442 | if (usb_dev->authorized == 1) | ||
1443 | goto out_authorized; | ||
1444 | kfree(usb_dev->product); | ||
1445 | usb_dev->product = NULL; | ||
1446 | kfree(usb_dev->manufacturer); | ||
1447 | usb_dev->manufacturer = NULL; | ||
1448 | kfree(usb_dev->serial); | ||
1449 | usb_dev->serial = NULL; | ||
1450 | result = usb_autoresume_device(usb_dev); | ||
1451 | if (result < 0) { | ||
1452 | dev_err(&usb_dev->dev, | ||
1453 | "can't autoresume for authorization: %d\n", result); | ||
1454 | goto error_autoresume; | ||
1455 | } | ||
1456 | result = usb_get_device_descriptor(usb_dev, sizeof(usb_dev->descriptor)); | ||
1457 | if (result < 0) { | ||
1458 | dev_err(&usb_dev->dev, "can't re-read device descriptor for " | ||
1459 | "authorization: %d\n", result); | ||
1460 | goto error_device_descriptor; | ||
1461 | } | ||
1462 | usb_dev->authorized = 1; | ||
1463 | result = usb_configure_device(usb_dev); | ||
1464 | if (result < 0) | ||
1465 | goto error_configure; | ||
1466 | /* Choose and set the configuration. This registers the interfaces | ||
1467 | * with the driver core and lets interface drivers bind to them. | ||
1468 | */ | ||
1469 | c = usb_choose_configuration(usb_dev); | ||
1470 | if (c >= 0) { | ||
1471 | result = usb_set_configuration(usb_dev, c); | ||
1472 | if (result) { | ||
1473 | dev_err(&usb_dev->dev, | ||
1474 | "can't set config #%d, error %d\n", c, result); | ||
1475 | /* This need not be fatal. The user can try to | ||
1476 | * set other configurations. */ | ||
1477 | } | ||
1478 | } | ||
1479 | dev_info(&usb_dev->dev, "authorized to connect\n"); | ||
1480 | error_configure: | ||
1481 | error_device_descriptor: | ||
1482 | error_autoresume: | ||
1483 | out_authorized: | ||
1484 | usb_unlock_device(usb_dev); // complements locktree | ||
1485 | return result; | ||
1486 | } | ||
1487 | |||
1488 | |||
1362 | static int hub_port_status(struct usb_hub *hub, int port1, | 1489 | static int hub_port_status(struct usb_hub *hub, int port1, |
1363 | u16 *status, u16 *change) | 1490 | u16 *status, u16 *change) |
1364 | { | 1491 | { |
@@ -1460,6 +1587,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
1460 | { | 1587 | { |
1461 | int i, status; | 1588 | int i, status; |
1462 | 1589 | ||
1590 | /* Block EHCI CF initialization during the port reset. | ||
1591 | * Some companion controllers don't like it when they mix. | ||
1592 | */ | ||
1593 | down_read(&ehci_cf_port_reset_rwsem); | ||
1594 | |||
1463 | /* Reset the port */ | 1595 | /* Reset the port */ |
1464 | for (i = 0; i < PORT_RESET_TRIES; i++) { | 1596 | for (i = 0; i < PORT_RESET_TRIES; i++) { |
1465 | status = set_port_feature(hub->hdev, | 1597 | status = set_port_feature(hub->hdev, |
@@ -1481,6 +1613,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
1481 | case 0: | 1613 | case 0: |
1482 | /* TRSTRCY = 10 ms; plus some extra */ | 1614 | /* TRSTRCY = 10 ms; plus some extra */ |
1483 | msleep(10 + 40); | 1615 | msleep(10 + 40); |
1616 | udev->devnum = 0; /* Device now at address 0 */ | ||
1484 | /* FALL THROUGH */ | 1617 | /* FALL THROUGH */ |
1485 | case -ENOTCONN: | 1618 | case -ENOTCONN: |
1486 | case -ENODEV: | 1619 | case -ENODEV: |
@@ -1490,7 +1623,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
1490 | usb_set_device_state(udev, status | 1623 | usb_set_device_state(udev, status |
1491 | ? USB_STATE_NOTATTACHED | 1624 | ? USB_STATE_NOTATTACHED |
1492 | : USB_STATE_DEFAULT); | 1625 | : USB_STATE_DEFAULT); |
1493 | return status; | 1626 | goto done; |
1494 | } | 1627 | } |
1495 | 1628 | ||
1496 | dev_dbg (hub->intfdev, | 1629 | dev_dbg (hub->intfdev, |
@@ -1503,6 +1636,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
1503 | "Cannot enable port %i. Maybe the USB cable is bad?\n", | 1636 | "Cannot enable port %i. Maybe the USB cable is bad?\n", |
1504 | port1); | 1637 | port1); |
1505 | 1638 | ||
1639 | done: | ||
1640 | up_read(&ehci_cf_port_reset_rwsem); | ||
1506 | return status; | 1641 | return status; |
1507 | } | 1642 | } |
1508 | 1643 | ||
@@ -1833,14 +1968,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1833 | struct usb_device *udev; | 1968 | struct usb_device *udev; |
1834 | 1969 | ||
1835 | udev = hdev->children [port1-1]; | 1970 | udev = hdev->children [port1-1]; |
1836 | if (udev && msg.event == PM_EVENT_SUSPEND && | 1971 | if (udev && udev->can_submit) { |
1837 | #ifdef CONFIG_USB_SUSPEND | ||
1838 | udev->state != USB_STATE_SUSPENDED | ||
1839 | #else | ||
1840 | udev->dev.power.power_state.event | ||
1841 | == PM_EVENT_ON | ||
1842 | #endif | ||
1843 | ) { | ||
1844 | if (!hdev->auto_pm) | 1972 | if (!hdev->auto_pm) |
1845 | dev_dbg(&intf->dev, "port %d nyet suspended\n", | 1973 | dev_dbg(&intf->dev, "port %d nyet suspended\n", |
1846 | port1); | 1974 | port1); |
@@ -1999,26 +2127,27 @@ static void ep0_reinit(struct usb_device *udev) | |||
1999 | { | 2127 | { |
2000 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); | 2128 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); |
2001 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); | 2129 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); |
2002 | udev->ep_in[0] = udev->ep_out[0] = &udev->ep0; | 2130 | usb_enable_endpoint(udev, &udev->ep0); |
2003 | } | 2131 | } |
2004 | 2132 | ||
2005 | #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) | 2133 | #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) |
2006 | #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) | 2134 | #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) |
2007 | 2135 | ||
2008 | static int hub_set_address(struct usb_device *udev) | 2136 | static int hub_set_address(struct usb_device *udev, int devnum) |
2009 | { | 2137 | { |
2010 | int retval; | 2138 | int retval; |
2011 | 2139 | ||
2012 | if (udev->devnum == 0) | 2140 | if (devnum <= 1) |
2013 | return -EINVAL; | 2141 | return -EINVAL; |
2014 | if (udev->state == USB_STATE_ADDRESS) | 2142 | if (udev->state == USB_STATE_ADDRESS) |
2015 | return 0; | 2143 | return 0; |
2016 | if (udev->state != USB_STATE_DEFAULT) | 2144 | if (udev->state != USB_STATE_DEFAULT) |
2017 | return -EINVAL; | 2145 | return -EINVAL; |
2018 | retval = usb_control_msg(udev, usb_sndaddr0pipe(), | 2146 | retval = usb_control_msg(udev, usb_sndaddr0pipe(), |
2019 | USB_REQ_SET_ADDRESS, 0, udev->devnum, 0, | 2147 | USB_REQ_SET_ADDRESS, 0, devnum, 0, |
2020 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 2148 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
2021 | if (retval == 0) { | 2149 | if (retval == 0) { |
2150 | udev->devnum = devnum; /* Device now using proper address */ | ||
2022 | usb_set_device_state(udev, USB_STATE_ADDRESS); | 2151 | usb_set_device_state(udev, USB_STATE_ADDRESS); |
2023 | ep0_reinit(udev); | 2152 | ep0_reinit(udev); |
2024 | } | 2153 | } |
@@ -2045,6 +2174,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2045 | unsigned delay = HUB_SHORT_RESET_TIME; | 2174 | unsigned delay = HUB_SHORT_RESET_TIME; |
2046 | enum usb_device_speed oldspeed = udev->speed; | 2175 | enum usb_device_speed oldspeed = udev->speed; |
2047 | char *speed, *type; | 2176 | char *speed, *type; |
2177 | int devnum = udev->devnum; | ||
2048 | 2178 | ||
2049 | /* root hub ports have a slightly longer reset period | 2179 | /* root hub ports have a slightly longer reset period |
2050 | * (from USB 2.0 spec, section 7.1.7.5) | 2180 | * (from USB 2.0 spec, section 7.1.7.5) |
@@ -2074,7 +2204,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2074 | goto fail; | 2204 | goto fail; |
2075 | } | 2205 | } |
2076 | oldspeed = udev->speed; | 2206 | oldspeed = udev->speed; |
2077 | 2207 | ||
2078 | /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... | 2208 | /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... |
2079 | * it's fixed size except for full speed devices. | 2209 | * it's fixed size except for full speed devices. |
2080 | * For Wireless USB devices, ep0 max packet is always 512 (tho | 2210 | * For Wireless USB devices, ep0 max packet is always 512 (tho |
@@ -2115,7 +2245,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2115 | dev_info (&udev->dev, | 2245 | dev_info (&udev->dev, |
2116 | "%s %s speed %sUSB device using %s and address %d\n", | 2246 | "%s %s speed %sUSB device using %s and address %d\n", |
2117 | (udev->config) ? "reset" : "new", speed, type, | 2247 | (udev->config) ? "reset" : "new", speed, type, |
2118 | udev->bus->controller->driver->name, udev->devnum); | 2248 | udev->bus->controller->driver->name, devnum); |
2119 | 2249 | ||
2120 | /* Set up TT records, if needed */ | 2250 | /* Set up TT records, if needed */ |
2121 | if (hdev->tt) { | 2251 | if (hdev->tt) { |
@@ -2202,7 +2332,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2202 | } | 2332 | } |
2203 | 2333 | ||
2204 | for (j = 0; j < SET_ADDRESS_TRIES; ++j) { | 2334 | for (j = 0; j < SET_ADDRESS_TRIES; ++j) { |
2205 | retval = hub_set_address(udev); | 2335 | retval = hub_set_address(udev, devnum); |
2206 | if (retval >= 0) | 2336 | if (retval >= 0) |
2207 | break; | 2337 | break; |
2208 | msleep(200); | 2338 | msleep(200); |
@@ -2210,7 +2340,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2210 | if (retval < 0) { | 2340 | if (retval < 0) { |
2211 | dev_err(&udev->dev, | 2341 | dev_err(&udev->dev, |
2212 | "device not accepting address %d, error %d\n", | 2342 | "device not accepting address %d, error %d\n", |
2213 | udev->devnum, retval); | 2343 | devnum, retval); |
2214 | goto fail; | 2344 | goto fail; |
2215 | } | 2345 | } |
2216 | 2346 | ||
@@ -2263,8 +2393,10 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2263 | retval = 0; | 2393 | retval = 0; |
2264 | 2394 | ||
2265 | fail: | 2395 | fail: |
2266 | if (retval) | 2396 | if (retval) { |
2267 | hub_port_disable(hub, port1, 0); | 2397 | hub_port_disable(hub, port1, 0); |
2398 | udev->devnum = devnum; /* for disconnect processing */ | ||
2399 | } | ||
2268 | mutex_unlock(&usb_address0_mutex); | 2400 | mutex_unlock(&usb_address0_mutex); |
2269 | return retval; | 2401 | return retval; |
2270 | } | 2402 | } |
@@ -2699,9 +2831,9 @@ static void hub_events(void) | |||
2699 | clear_hub_feature(hdev, C_HUB_LOCAL_POWER); | 2831 | clear_hub_feature(hdev, C_HUB_LOCAL_POWER); |
2700 | if (hubstatus & HUB_STATUS_LOCAL_POWER) | 2832 | if (hubstatus & HUB_STATUS_LOCAL_POWER) |
2701 | /* FIXME: Is this always true? */ | 2833 | /* FIXME: Is this always true? */ |
2702 | hub->limited_power = 0; | ||
2703 | else | ||
2704 | hub->limited_power = 1; | 2834 | hub->limited_power = 1; |
2835 | else | ||
2836 | hub->limited_power = 0; | ||
2705 | } | 2837 | } |
2706 | if (hubchange & HUB_CHANGE_OVERCURRENT) { | 2838 | if (hubchange & HUB_CHANGE_OVERCURRENT) { |
2707 | dev_dbg (hub_dev, "overcurrent change\n"); | 2839 | dev_dbg (hub_dev, "overcurrent change\n"); |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 95a49d8efe7a..c021af390372 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -59,8 +59,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) | |||
59 | dev_dbg(&urb->dev->dev, | 59 | dev_dbg(&urb->dev->dev, |
60 | "%s timed out on ep%d%s len=%d/%d\n", | 60 | "%s timed out on ep%d%s len=%d/%d\n", |
61 | current->comm, | 61 | current->comm, |
62 | usb_pipeendpoint(urb->pipe), | 62 | usb_endpoint_num(&urb->ep->desc), |
63 | usb_pipein(urb->pipe) ? "in" : "out", | 63 | usb_urb_dir_in(urb) ? "in" : "out", |
64 | urb->actual_length, | 64 | urb->actual_length, |
65 | urb->transfer_buffer_length); | 65 | urb->transfer_buffer_length); |
66 | } else | 66 | } else |
@@ -250,7 +250,8 @@ static void sg_clean (struct usb_sg_request *io) | |||
250 | io->urbs = NULL; | 250 | io->urbs = NULL; |
251 | } | 251 | } |
252 | if (io->dev->dev.dma_mask != NULL) | 252 | if (io->dev->dev.dma_mask != NULL) |
253 | usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); | 253 | usb_buffer_unmap_sg (io->dev, usb_pipein(io->pipe), |
254 | io->sg, io->nents); | ||
254 | io->dev = NULL; | 255 | io->dev = NULL; |
255 | } | 256 | } |
256 | 257 | ||
@@ -278,8 +279,8 @@ static void sg_complete (struct urb *urb) | |||
278 | dev_err (io->dev->bus->controller, | 279 | dev_err (io->dev->bus->controller, |
279 | "dev %s ep%d%s scatterlist error %d/%d\n", | 280 | "dev %s ep%d%s scatterlist error %d/%d\n", |
280 | io->dev->devpath, | 281 | io->dev->devpath, |
281 | usb_pipeendpoint (urb->pipe), | 282 | usb_endpoint_num(&urb->ep->desc), |
282 | usb_pipein (urb->pipe) ? "in" : "out", | 283 | usb_urb_dir_in(urb) ? "in" : "out", |
283 | status, io->status); | 284 | status, io->status); |
284 | // BUG (); | 285 | // BUG (); |
285 | } | 286 | } |
@@ -379,7 +380,8 @@ int usb_sg_init ( | |||
379 | */ | 380 | */ |
380 | dma = (dev->dev.dma_mask != NULL); | 381 | dma = (dev->dev.dma_mask != NULL); |
381 | if (dma) | 382 | if (dma) |
382 | io->entries = usb_buffer_map_sg (dev, pipe, sg, nents); | 383 | io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe), |
384 | sg, nents); | ||
383 | else | 385 | else |
384 | io->entries = nents; | 386 | io->entries = nents; |
385 | 387 | ||
@@ -1013,8 +1015,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
1013 | ep = dev->ep_in[epnum]; | 1015 | ep = dev->ep_in[epnum]; |
1014 | dev->ep_in[epnum] = NULL; | 1016 | dev->ep_in[epnum] = NULL; |
1015 | } | 1017 | } |
1016 | if (ep && dev->bus) | 1018 | if (ep) { |
1017 | usb_hcd_endpoint_disable(dev, ep); | 1019 | ep->enabled = 0; |
1020 | usb_hcd_flush_endpoint(dev, ep); | ||
1021 | usb_hcd_disable_endpoint(dev, ep); | ||
1022 | } | ||
1018 | } | 1023 | } |
1019 | 1024 | ||
1020 | /** | 1025 | /** |
@@ -1096,23 +1101,21 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1096 | * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers. | 1101 | * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers. |
1097 | * For control endpoints, both the input and output sides are handled. | 1102 | * For control endpoints, both the input and output sides are handled. |
1098 | */ | 1103 | */ |
1099 | static void | 1104 | void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep) |
1100 | usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep) | ||
1101 | { | 1105 | { |
1102 | unsigned int epaddr = ep->desc.bEndpointAddress; | 1106 | int epnum = usb_endpoint_num(&ep->desc); |
1103 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; | 1107 | int is_out = usb_endpoint_dir_out(&ep->desc); |
1104 | int is_control; | 1108 | int is_control = usb_endpoint_xfer_control(&ep->desc); |
1105 | 1109 | ||
1106 | is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 1110 | if (is_out || is_control) { |
1107 | == USB_ENDPOINT_XFER_CONTROL); | ||
1108 | if (usb_endpoint_out(epaddr) || is_control) { | ||
1109 | usb_settoggle(dev, epnum, 1, 0); | 1111 | usb_settoggle(dev, epnum, 1, 0); |
1110 | dev->ep_out[epnum] = ep; | 1112 | dev->ep_out[epnum] = ep; |
1111 | } | 1113 | } |
1112 | if (!usb_endpoint_out(epaddr) || is_control) { | 1114 | if (!is_out || is_control) { |
1113 | usb_settoggle(dev, epnum, 0, 0); | 1115 | usb_settoggle(dev, epnum, 0, 0); |
1114 | dev->ep_in[epnum] = ep; | 1116 | dev->ep_in[epnum] = ep; |
1115 | } | 1117 | } |
1118 | ep->enabled = 1; | ||
1116 | } | 1119 | } |
1117 | 1120 | ||
1118 | /* | 1121 | /* |
@@ -1171,6 +1174,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1171 | struct usb_host_interface *alt; | 1174 | struct usb_host_interface *alt; |
1172 | int ret; | 1175 | int ret; |
1173 | int manual = 0; | 1176 | int manual = 0; |
1177 | int changed; | ||
1174 | 1178 | ||
1175 | if (dev->state == USB_STATE_SUSPENDED) | 1179 | if (dev->state == USB_STATE_SUSPENDED) |
1176 | return -EHOSTUNREACH; | 1180 | return -EHOSTUNREACH; |
@@ -1210,7 +1214,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1210 | */ | 1214 | */ |
1211 | 1215 | ||
1212 | /* prevent submissions using previous endpoint settings */ | 1216 | /* prevent submissions using previous endpoint settings */ |
1213 | if (device_is_registered(&iface->dev)) | 1217 | changed = (iface->cur_altsetting != alt); |
1218 | if (changed && device_is_registered(&iface->dev)) | ||
1214 | usb_remove_sysfs_intf_files(iface); | 1219 | usb_remove_sysfs_intf_files(iface); |
1215 | usb_disable_interface(dev, iface); | 1220 | usb_disable_interface(dev, iface); |
1216 | 1221 | ||
@@ -1247,7 +1252,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1247 | * (Likewise, EP0 never "halts" on well designed devices.) | 1252 | * (Likewise, EP0 never "halts" on well designed devices.) |
1248 | */ | 1253 | */ |
1249 | usb_enable_interface(dev, iface); | 1254 | usb_enable_interface(dev, iface); |
1250 | if (device_is_registered(&iface->dev)) | 1255 | if (changed && device_is_registered(&iface->dev)) |
1251 | usb_create_sysfs_intf_files(iface); | 1256 | usb_create_sysfs_intf_files(iface); |
1252 | 1257 | ||
1253 | return 0; | 1258 | return 0; |
@@ -1328,7 +1333,7 @@ int usb_reset_configuration(struct usb_device *dev) | |||
1328 | return 0; | 1333 | return 0; |
1329 | } | 1334 | } |
1330 | 1335 | ||
1331 | void usb_release_interface(struct device *dev) | 1336 | static void usb_release_interface(struct device *dev) |
1332 | { | 1337 | { |
1333 | struct usb_interface *intf = to_usb_interface(dev); | 1338 | struct usb_interface *intf = to_usb_interface(dev); |
1334 | struct usb_interface_cache *intfc = | 1339 | struct usb_interface_cache *intfc = |
@@ -1467,6 +1472,9 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, | |||
1467 | * channels are available independently; and choosing between open | 1472 | * channels are available independently; and choosing between open |
1468 | * standard device protocols (like CDC) or proprietary ones. | 1473 | * standard device protocols (like CDC) or proprietary ones. |
1469 | * | 1474 | * |
1475 | * Note that a non-authorized device (dev->authorized == 0) will only | ||
1476 | * be put in unconfigured mode. | ||
1477 | * | ||
1470 | * Note that USB has an additional level of device configurability, | 1478 | * Note that USB has an additional level of device configurability, |
1471 | * associated with interfaces. That configurability is accessed using | 1479 | * associated with interfaces. That configurability is accessed using |
1472 | * usb_set_interface(). | 1480 | * usb_set_interface(). |
@@ -1488,7 +1496,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) | |||
1488 | struct usb_interface **new_interfaces = NULL; | 1496 | struct usb_interface **new_interfaces = NULL; |
1489 | int n, nintf; | 1497 | int n, nintf; |
1490 | 1498 | ||
1491 | if (configuration == -1) | 1499 | if (dev->authorized == 0 || configuration == -1) |
1492 | configuration = 0; | 1500 | configuration = 0; |
1493 | else { | 1501 | else { |
1494 | for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { | 1502 | for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index ebf3dc20110a..d42c561c75f1 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -32,52 +32,6 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
32 | { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME }, | 32 | { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME }, |
33 | /* HP 5300/5370C scanner */ | 33 | /* HP 5300/5370C scanner */ |
34 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, | 34 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, |
35 | /* Hewlett-Packard PhotoSmart 720 / PhotoSmart 935 (storage) */ | ||
36 | { USB_DEVICE(0x03f0, 0x4002), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
37 | |||
38 | /* SGS Thomson Microelectronics 4in1 card reader */ | ||
39 | { USB_DEVICE(0x0483, 0x0321), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
40 | |||
41 | /* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */ | ||
42 | { USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
43 | /* Benq S2W 3300U */ | ||
44 | { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
45 | /* Canon, Inc. CanoScan N1240U/LiDE30 */ | ||
46 | { USB_DEVICE(0x04a9, 0x220e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
47 | /* Canon, Inc. CanoScan N650U/N656U */ | ||
48 | { USB_DEVICE(0x04a9, 0x2206), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
49 | /* Canon, Inc. CanoScan 1220U */ | ||
50 | { USB_DEVICE(0x04a9, 0x2207), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
51 | /* Canon, Inc. CanoScan N670U/N676U/LiDE 20 */ | ||
52 | { USB_DEVICE(0x04a9, 0x220d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
53 | /* old Cannon scanner */ | ||
54 | { USB_DEVICE(0x04a9, 0x2220), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
55 | /* Seiko Epson Corp. Perfection 1200 */ | ||
56 | { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
57 | /* Seiko Epson Corp. Perfection 660 */ | ||
58 | { USB_DEVICE(0x04b8, 0x0114), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
59 | /* Epson Perfection 1260 Photo */ | ||
60 | { USB_DEVICE(0x04b8, 0x011d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
61 | /* Seiko Epson Corp - Perfection 1670 */ | ||
62 | { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
63 | /* EPSON Perfection 2480 */ | ||
64 | { USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
65 | /* Seiko Epson Corp.*/ | ||
66 | { USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
67 | /* Samsung ML-2010 printer */ | ||
68 | { USB_DEVICE(0x04e8, 0x326c), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
69 | /* Samsung ML-2510 Series printer */ | ||
70 | { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
71 | /* Elsa MicroLink 56k (V.250) */ | ||
72 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
73 | /* Ultima Electronics Corp.*/ | ||
74 | { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
75 | |||
76 | /* Genesys USB-to-IDE */ | ||
77 | { USB_DEVICE(0x0503, 0x0702), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
78 | |||
79 | /* USB Graphical LCD - EEH Datalink GmbH */ | ||
80 | { USB_DEVICE(0x060c, 0x04eb), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
81 | 35 | ||
82 | /* INTEL VALUE SSD */ | 36 | /* INTEL VALUE SSD */ |
83 | { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, | 37 | { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, |
@@ -85,44 +39,15 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
85 | /* M-Systems Flash Disk Pioneers */ | 39 | /* M-Systems Flash Disk Pioneers */ |
86 | { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, | 40 | { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, |
87 | 41 | ||
88 | /* Agfa Snapscan1212u */ | ||
89 | { USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
90 | /* Seagate RSS LLC */ | ||
91 | { USB_DEVICE(0x0bc2, 0x3000), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
92 | /* Umax [hex] Astra 3400U */ | ||
93 | { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
94 | |||
95 | /* Philips PSC805 audio device */ | 42 | /* Philips PSC805 audio device */ |
96 | { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, | 43 | { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, |
97 | 44 | ||
98 | /* Alcor multi-card reader */ | ||
99 | { USB_DEVICE(0x058f, 0x6366), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
100 | |||
101 | /* Canon EOS 5D in PC Connection mode */ | ||
102 | { USB_DEVICE(0x04a9, 0x3101), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
103 | |||
104 | /* RIM Blackberry */ | ||
105 | { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
106 | { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
107 | { USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
108 | |||
109 | /* Apple iPhone */ | ||
110 | { USB_DEVICE(0x05ac, 0x1290), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
111 | |||
112 | /* SKYMEDI USB_DRIVE */ | 45 | /* SKYMEDI USB_DRIVE */ |
113 | { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, | 46 | { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, |
114 | 47 | ||
115 | { } /* terminating entry must be last */ | 48 | { } /* terminating entry must be last */ |
116 | }; | 49 | }; |
117 | 50 | ||
118 | static void usb_autosuspend_quirk(struct usb_device *udev) | ||
119 | { | ||
120 | #ifdef CONFIG_USB_SUSPEND | ||
121 | /* disable autosuspend, but allow the user to re-enable it via sysfs */ | ||
122 | udev->autosuspend_disabled = 1; | ||
123 | #endif | ||
124 | } | ||
125 | |||
126 | static const struct usb_device_id *find_id(struct usb_device *udev) | 51 | static const struct usb_device_id *find_id(struct usb_device *udev) |
127 | { | 52 | { |
128 | const struct usb_device_id *id = usb_quirk_list; | 53 | const struct usb_device_id *id = usb_quirk_list; |
@@ -149,13 +74,9 @@ void usb_detect_quirks(struct usb_device *udev) | |||
149 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", | 74 | dev_dbg(&udev->dev, "USB quirks for this device: %x\n", |
150 | udev->quirks); | 75 | udev->quirks); |
151 | 76 | ||
152 | /* do any special quirk handling here if needed */ | ||
153 | if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND) | ||
154 | usb_autosuspend_quirk(udev); | ||
155 | |||
156 | /* By default, disable autosuspend for all non-hubs */ | 77 | /* By default, disable autosuspend for all non-hubs */ |
157 | #ifdef CONFIG_USB_SUSPEND | 78 | #ifdef CONFIG_USB_SUSPEND |
158 | if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) | 79 | if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) |
159 | udev->autosuspend_delay = -1; | 80 | udev->autosuspend_disabled = 1; |
160 | #endif | 81 | #endif |
161 | } | 82 | } |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 2ab222be8fd1..b04afd06e502 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -169,6 +169,16 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf) | |||
169 | } | 169 | } |
170 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); | 170 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); |
171 | 171 | ||
172 | static ssize_t | ||
173 | show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) | ||
174 | { | ||
175 | struct usb_device *udev; | ||
176 | |||
177 | udev = to_usb_device(dev); | ||
178 | return sprintf(buf, "%d\n", atomic_read(&udev->urbnum)); | ||
179 | } | ||
180 | static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); | ||
181 | |||
172 | 182 | ||
173 | #if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) | 183 | #if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) |
174 | static const char power_group[] = "power"; | 184 | static const char power_group[] = "power"; |
@@ -413,6 +423,44 @@ usb_descriptor_attr(bDeviceProtocol, "%02x\n") | |||
413 | usb_descriptor_attr(bNumConfigurations, "%d\n") | 423 | usb_descriptor_attr(bNumConfigurations, "%d\n") |
414 | usb_descriptor_attr(bMaxPacketSize0, "%d\n") | 424 | usb_descriptor_attr(bMaxPacketSize0, "%d\n") |
415 | 425 | ||
426 | |||
427 | |||
428 | /* show if the device is authorized (1) or not (0) */ | ||
429 | static ssize_t usb_dev_authorized_show(struct device *dev, | ||
430 | struct device_attribute *attr, | ||
431 | char *buf) | ||
432 | { | ||
433 | struct usb_device *usb_dev = to_usb_device(dev); | ||
434 | return snprintf(buf, PAGE_SIZE, "%u\n", usb_dev->authorized); | ||
435 | } | ||
436 | |||
437 | |||
438 | /* | ||
439 | * Authorize a device to be used in the system | ||
440 | * | ||
441 | * Writing a 0 deauthorizes the device, writing a 1 authorizes it. | ||
442 | */ | ||
443 | static ssize_t usb_dev_authorized_store(struct device *dev, | ||
444 | struct device_attribute *attr, | ||
445 | const char *buf, size_t size) | ||
446 | { | ||
447 | ssize_t result; | ||
448 | struct usb_device *usb_dev = to_usb_device(dev); | ||
449 | unsigned val; | ||
450 | result = sscanf(buf, "%u\n", &val); | ||
451 | if (result != 1) | ||
452 | result = -EINVAL; | ||
453 | else if (val == 0) | ||
454 | result = usb_deauthorize_device(usb_dev); | ||
455 | else | ||
456 | result = usb_authorize_device(usb_dev); | ||
457 | return result < 0? result : size; | ||
458 | } | ||
459 | |||
460 | static DEVICE_ATTR(authorized, 0644, | ||
461 | usb_dev_authorized_show, usb_dev_authorized_store); | ||
462 | |||
463 | |||
416 | static struct attribute *dev_attrs[] = { | 464 | static struct attribute *dev_attrs[] = { |
417 | /* current configuration's attributes */ | 465 | /* current configuration's attributes */ |
418 | &dev_attr_configuration.attr, | 466 | &dev_attr_configuration.attr, |
@@ -420,6 +468,7 @@ static struct attribute *dev_attrs[] = { | |||
420 | &dev_attr_bConfigurationValue.attr, | 468 | &dev_attr_bConfigurationValue.attr, |
421 | &dev_attr_bmAttributes.attr, | 469 | &dev_attr_bmAttributes.attr, |
422 | &dev_attr_bMaxPower.attr, | 470 | &dev_attr_bMaxPower.attr, |
471 | &dev_attr_urbnum.attr, | ||
423 | /* device attributes */ | 472 | /* device attributes */ |
424 | &dev_attr_idVendor.attr, | 473 | &dev_attr_idVendor.attr, |
425 | &dev_attr_idProduct.attr, | 474 | &dev_attr_idProduct.attr, |
@@ -435,6 +484,7 @@ static struct attribute *dev_attrs[] = { | |||
435 | &dev_attr_version.attr, | 484 | &dev_attr_version.attr, |
436 | &dev_attr_maxchild.attr, | 485 | &dev_attr_maxchild.attr, |
437 | &dev_attr_quirks.attr, | 486 | &dev_attr_quirks.attr, |
487 | &dev_attr_authorized.attr, | ||
438 | NULL, | 488 | NULL, |
439 | }; | 489 | }; |
440 | static struct attribute_group dev_attr_grp = { | 490 | static struct attribute_group dev_attr_grp = { |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index be630228461c..c20c03aaf012 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/bitops.h> | 3 | #include <linux/bitops.h> |
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
6 | #include <linux/log2.h> | ||
6 | #include <linux/usb.h> | 7 | #include <linux/usb.h> |
7 | #include <linux/wait.h> | 8 | #include <linux/wait.h> |
8 | #include "hcd.h" | 9 | #include "hcd.h" |
@@ -38,7 +39,6 @@ void usb_init_urb(struct urb *urb) | |||
38 | if (urb) { | 39 | if (urb) { |
39 | memset(urb, 0, sizeof(*urb)); | 40 | memset(urb, 0, sizeof(*urb)); |
40 | kref_init(&urb->kref); | 41 | kref_init(&urb->kref); |
41 | spin_lock_init(&urb->lock); | ||
42 | INIT_LIST_HEAD(&urb->anchor_list); | 42 | INIT_LIST_HEAD(&urb->anchor_list); |
43 | } | 43 | } |
44 | } | 44 | } |
@@ -277,44 +277,58 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); | |||
277 | */ | 277 | */ |
278 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | 278 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) |
279 | { | 279 | { |
280 | int pipe, temp, max; | 280 | int xfertype, max; |
281 | struct usb_device *dev; | 281 | struct usb_device *dev; |
282 | int is_out; | 282 | struct usb_host_endpoint *ep; |
283 | int is_out; | ||
283 | 284 | ||
284 | if (!urb || urb->hcpriv || !urb->complete) | 285 | if (!urb || urb->hcpriv || !urb->complete) |
285 | return -EINVAL; | 286 | return -EINVAL; |
286 | if (!(dev = urb->dev) || | 287 | if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT) |
287 | (dev->state < USB_STATE_DEFAULT) || | ||
288 | (!dev->bus) || (dev->devnum <= 0)) | ||
289 | return -ENODEV; | 288 | return -ENODEV; |
290 | if (dev->bus->controller->power.power_state.event != PM_EVENT_ON | ||
291 | || dev->state == USB_STATE_SUSPENDED) | ||
292 | return -EHOSTUNREACH; | ||
293 | 289 | ||
290 | /* For now, get the endpoint from the pipe. Eventually drivers | ||
291 | * will be required to set urb->ep directly and we will eliminate | ||
292 | * urb->pipe. | ||
293 | */ | ||
294 | ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out) | ||
295 | [usb_pipeendpoint(urb->pipe)]; | ||
296 | if (!ep) | ||
297 | return -ENOENT; | ||
298 | |||
299 | urb->ep = ep; | ||
294 | urb->status = -EINPROGRESS; | 300 | urb->status = -EINPROGRESS; |
295 | urb->actual_length = 0; | 301 | urb->actual_length = 0; |
296 | 302 | ||
297 | /* Lots of sanity checks, so HCDs can rely on clean data | 303 | /* Lots of sanity checks, so HCDs can rely on clean data |
298 | * and don't need to duplicate tests | 304 | * and don't need to duplicate tests |
299 | */ | 305 | */ |
300 | pipe = urb->pipe; | 306 | xfertype = usb_endpoint_type(&ep->desc); |
301 | temp = usb_pipetype(pipe); | 307 | if (xfertype == USB_ENDPOINT_XFER_CONTROL) { |
302 | is_out = usb_pipeout(pipe); | 308 | struct usb_ctrlrequest *setup = |
309 | (struct usb_ctrlrequest *) urb->setup_packet; | ||
310 | |||
311 | if (!setup) | ||
312 | return -ENOEXEC; | ||
313 | is_out = !(setup->bRequestType & USB_DIR_IN) || | ||
314 | !setup->wLength; | ||
315 | } else { | ||
316 | is_out = usb_endpoint_dir_out(&ep->desc); | ||
317 | } | ||
303 | 318 | ||
304 | if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED) | 319 | /* Cache the direction for later use */ |
305 | return -ENODEV; | 320 | urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) | |
321 | (is_out ? URB_DIR_OUT : URB_DIR_IN); | ||
306 | 322 | ||
307 | /* FIXME there should be a sharable lock protecting us against | 323 | if (xfertype != USB_ENDPOINT_XFER_CONTROL && |
308 | * config/altsetting changes and disconnects, kicking in here. | 324 | dev->state < USB_STATE_CONFIGURED) |
309 | * (here == before maxpacket, and eventually endpoint type, | 325 | return -ENODEV; |
310 | * checks get made.) | ||
311 | */ | ||
312 | 326 | ||
313 | max = usb_maxpacket(dev, pipe, is_out); | 327 | max = le16_to_cpu(ep->desc.wMaxPacketSize); |
314 | if (max <= 0) { | 328 | if (max <= 0) { |
315 | dev_dbg(&dev->dev, | 329 | dev_dbg(&dev->dev, |
316 | "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", | 330 | "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", |
317 | usb_pipeendpoint(pipe), is_out ? "out" : "in", | 331 | usb_endpoint_num(&ep->desc), is_out ? "out" : "in", |
318 | __FUNCTION__, max); | 332 | __FUNCTION__, max); |
319 | return -EMSGSIZE; | 333 | return -EMSGSIZE; |
320 | } | 334 | } |
@@ -323,7 +337,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
323 | * but drivers only control those sizes for ISO. | 337 | * but drivers only control those sizes for ISO. |
324 | * while we're checking, initialize return status. | 338 | * while we're checking, initialize return status. |
325 | */ | 339 | */ |
326 | if (temp == PIPE_ISOCHRONOUS) { | 340 | if (xfertype == USB_ENDPOINT_XFER_ISOC) { |
327 | int n, len; | 341 | int n, len; |
328 | 342 | ||
329 | /* "high bandwidth" mode, 1-3 packets/uframe? */ | 343 | /* "high bandwidth" mode, 1-3 packets/uframe? */ |
@@ -358,20 +372,20 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
358 | 372 | ||
359 | /* enforce simple/standard policy */ | 373 | /* enforce simple/standard policy */ |
360 | allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | | 374 | allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | |
361 | URB_NO_INTERRUPT); | 375 | URB_NO_INTERRUPT | URB_DIR_MASK); |
362 | switch (temp) { | 376 | switch (xfertype) { |
363 | case PIPE_BULK: | 377 | case USB_ENDPOINT_XFER_BULK: |
364 | if (is_out) | 378 | if (is_out) |
365 | allowed |= URB_ZERO_PACKET; | 379 | allowed |= URB_ZERO_PACKET; |
366 | /* FALLTHROUGH */ | 380 | /* FALLTHROUGH */ |
367 | case PIPE_CONTROL: | 381 | case USB_ENDPOINT_XFER_CONTROL: |
368 | allowed |= URB_NO_FSBR; /* only affects UHCI */ | 382 | allowed |= URB_NO_FSBR; /* only affects UHCI */ |
369 | /* FALLTHROUGH */ | 383 | /* FALLTHROUGH */ |
370 | default: /* all non-iso endpoints */ | 384 | default: /* all non-iso endpoints */ |
371 | if (!is_out) | 385 | if (!is_out) |
372 | allowed |= URB_SHORT_NOT_OK; | 386 | allowed |= URB_SHORT_NOT_OK; |
373 | break; | 387 | break; |
374 | case PIPE_ISOCHRONOUS: | 388 | case USB_ENDPOINT_XFER_ISOC: |
375 | allowed |= URB_ISO_ASAP; | 389 | allowed |= URB_ISO_ASAP; |
376 | break; | 390 | break; |
377 | } | 391 | } |
@@ -393,9 +407,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
393 | * supports different values... this uses EHCI/UHCI defaults (and | 407 | * supports different values... this uses EHCI/UHCI defaults (and |
394 | * EHCI can use smaller non-default values). | 408 | * EHCI can use smaller non-default values). |
395 | */ | 409 | */ |
396 | switch (temp) { | 410 | switch (xfertype) { |
397 | case PIPE_ISOCHRONOUS: | 411 | case USB_ENDPOINT_XFER_ISOC: |
398 | case PIPE_INTERRUPT: | 412 | case USB_ENDPOINT_XFER_INT: |
399 | /* too small? */ | 413 | /* too small? */ |
400 | if (urb->interval <= 0) | 414 | if (urb->interval <= 0) |
401 | return -EINVAL; | 415 | return -EINVAL; |
@@ -405,29 +419,27 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
405 | // NOTE usb handles 2^15 | 419 | // NOTE usb handles 2^15 |
406 | if (urb->interval > (1024 * 8)) | 420 | if (urb->interval > (1024 * 8)) |
407 | urb->interval = 1024 * 8; | 421 | urb->interval = 1024 * 8; |
408 | temp = 1024 * 8; | 422 | max = 1024 * 8; |
409 | break; | 423 | break; |
410 | case USB_SPEED_FULL: /* units are frames/msec */ | 424 | case USB_SPEED_FULL: /* units are frames/msec */ |
411 | case USB_SPEED_LOW: | 425 | case USB_SPEED_LOW: |
412 | if (temp == PIPE_INTERRUPT) { | 426 | if (xfertype == USB_ENDPOINT_XFER_INT) { |
413 | if (urb->interval > 255) | 427 | if (urb->interval > 255) |
414 | return -EINVAL; | 428 | return -EINVAL; |
415 | // NOTE ohci only handles up to 32 | 429 | // NOTE ohci only handles up to 32 |
416 | temp = 128; | 430 | max = 128; |
417 | } else { | 431 | } else { |
418 | if (urb->interval > 1024) | 432 | if (urb->interval > 1024) |
419 | urb->interval = 1024; | 433 | urb->interval = 1024; |
420 | // NOTE usb and ohci handle up to 2^15 | 434 | // NOTE usb and ohci handle up to 2^15 |
421 | temp = 1024; | 435 | max = 1024; |
422 | } | 436 | } |
423 | break; | 437 | break; |
424 | default: | 438 | default: |
425 | return -EINVAL; | 439 | return -EINVAL; |
426 | } | 440 | } |
427 | /* power of two? */ | 441 | /* Round down to a power of 2, no more than max */ |
428 | while (temp > urb->interval) | 442 | urb->interval = min(max, 1 << ilog2(urb->interval)); |
429 | temp >>= 1; | ||
430 | urb->interval = temp; | ||
431 | } | 443 | } |
432 | 444 | ||
433 | return usb_hcd_submit_urb(urb, mem_flags); | 445 | return usb_hcd_submit_urb(urb, mem_flags); |
@@ -496,8 +508,10 @@ int usb_unlink_urb(struct urb *urb) | |||
496 | { | 508 | { |
497 | if (!urb) | 509 | if (!urb) |
498 | return -EINVAL; | 510 | return -EINVAL; |
499 | if (!(urb->dev && urb->dev->bus)) | 511 | if (!urb->dev) |
500 | return -ENODEV; | 512 | return -ENODEV; |
513 | if (!urb->ep) | ||
514 | return -EIDRM; | ||
501 | return usb_hcd_unlink_urb(urb, -ECONNRESET); | 515 | return usb_hcd_unlink_urb(urb, -ECONNRESET); |
502 | } | 516 | } |
503 | 517 | ||
@@ -523,19 +537,21 @@ int usb_unlink_urb(struct urb *urb) | |||
523 | */ | 537 | */ |
524 | void usb_kill_urb(struct urb *urb) | 538 | void usb_kill_urb(struct urb *urb) |
525 | { | 539 | { |
540 | static DEFINE_MUTEX(reject_mutex); | ||
541 | |||
526 | might_sleep(); | 542 | might_sleep(); |
527 | if (!(urb && urb->dev && urb->dev->bus)) | 543 | if (!(urb && urb->dev && urb->ep)) |
528 | return; | 544 | return; |
529 | spin_lock_irq(&urb->lock); | 545 | mutex_lock(&reject_mutex); |
530 | ++urb->reject; | 546 | ++urb->reject; |
531 | spin_unlock_irq(&urb->lock); | 547 | mutex_unlock(&reject_mutex); |
532 | 548 | ||
533 | usb_hcd_unlink_urb(urb, -ENOENT); | 549 | usb_hcd_unlink_urb(urb, -ENOENT); |
534 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); | 550 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); |
535 | 551 | ||
536 | spin_lock_irq(&urb->lock); | 552 | mutex_lock(&reject_mutex); |
537 | --urb->reject; | 553 | --urb->reject; |
538 | spin_unlock_irq(&urb->lock); | 554 | mutex_unlock(&reject_mutex); |
539 | } | 555 | } |
540 | 556 | ||
541 | /** | 557 | /** |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0fee5c66fd64..c99938d5f78e 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -223,6 +223,15 @@ static void ksuspend_usb_cleanup(void) | |||
223 | 223 | ||
224 | #endif /* CONFIG_PM */ | 224 | #endif /* CONFIG_PM */ |
225 | 225 | ||
226 | |||
227 | /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ | ||
228 | static unsigned usb_bus_is_wusb(struct usb_bus *bus) | ||
229 | { | ||
230 | struct usb_hcd *hcd = container_of(bus, struct usb_hcd, self); | ||
231 | return hcd->wireless; | ||
232 | } | ||
233 | |||
234 | |||
226 | /** | 235 | /** |
227 | * usb_alloc_dev - usb device constructor (usbcore-internal) | 236 | * usb_alloc_dev - usb device constructor (usbcore-internal) |
228 | * @parent: hub to which device is connected; null to allocate a root hub | 237 | * @parent: hub to which device is connected; null to allocate a root hub |
@@ -239,6 +248,8 @@ struct usb_device * | |||
239 | usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | 248 | usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) |
240 | { | 249 | { |
241 | struct usb_device *dev; | 250 | struct usb_device *dev; |
251 | struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self); | ||
252 | unsigned root_hub = 0; | ||
242 | 253 | ||
243 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 254 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
244 | if (!dev) | 255 | if (!dev) |
@@ -255,12 +266,14 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
255 | dev->dev.dma_mask = bus->controller->dma_mask; | 266 | dev->dev.dma_mask = bus->controller->dma_mask; |
256 | set_dev_node(&dev->dev, dev_to_node(bus->controller)); | 267 | set_dev_node(&dev->dev, dev_to_node(bus->controller)); |
257 | dev->state = USB_STATE_ATTACHED; | 268 | dev->state = USB_STATE_ATTACHED; |
269 | atomic_set(&dev->urbnum, 0); | ||
258 | 270 | ||
259 | INIT_LIST_HEAD(&dev->ep0.urb_list); | 271 | INIT_LIST_HEAD(&dev->ep0.urb_list); |
260 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; | 272 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; |
261 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; | 273 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; |
262 | /* ep0 maxpacket comes later, from device descriptor */ | 274 | /* ep0 maxpacket comes later, from device descriptor */ |
263 | dev->ep_in[0] = dev->ep_out[0] = &dev->ep0; | 275 | usb_enable_endpoint(dev, &dev->ep0); |
276 | dev->can_submit = 1; | ||
264 | 277 | ||
265 | /* Save readable and stable topology id, distinguishing devices | 278 | /* Save readable and stable topology id, distinguishing devices |
266 | * by location for diagnostics, tools, driver model, etc. The | 279 | * by location for diagnostics, tools, driver model, etc. The |
@@ -275,6 +288,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
275 | 288 | ||
276 | dev->dev.parent = bus->controller; | 289 | dev->dev.parent = bus->controller; |
277 | sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum); | 290 | sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum); |
291 | root_hub = 1; | ||
278 | } else { | 292 | } else { |
279 | /* match any labeling on the hubs; it's one-based */ | 293 | /* match any labeling on the hubs; it's one-based */ |
280 | if (parent->devpath[0] == '0') | 294 | if (parent->devpath[0] == '0') |
@@ -301,6 +315,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
301 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); | 315 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); |
302 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; | 316 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; |
303 | #endif | 317 | #endif |
318 | if (root_hub) /* Root hub always ok [and always wired] */ | ||
319 | dev->authorized = 1; | ||
320 | else { | ||
321 | dev->authorized = usb_hcd->authorized_default; | ||
322 | dev->wusb = usb_bus_is_wusb(bus)? 1 : 0; | ||
323 | } | ||
304 | return dev; | 324 | return dev; |
305 | } | 325 | } |
306 | 326 | ||
@@ -748,7 +768,7 @@ void usb_buffer_unmap(struct urb *urb) | |||
748 | /** | 768 | /** |
749 | * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint | 769 | * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint |
750 | * @dev: device to which the scatterlist will be mapped | 770 | * @dev: device to which the scatterlist will be mapped |
751 | * @pipe: endpoint defining the mapping direction | 771 | * @is_in: mapping transfer direction |
752 | * @sg: the scatterlist to map | 772 | * @sg: the scatterlist to map |
753 | * @nents: the number of entries in the scatterlist | 773 | * @nents: the number of entries in the scatterlist |
754 | * | 774 | * |
@@ -771,14 +791,13 @@ void usb_buffer_unmap(struct urb *urb) | |||
771 | * | 791 | * |
772 | * Reverse the effect of this call with usb_buffer_unmap_sg(). | 792 | * Reverse the effect of this call with usb_buffer_unmap_sg(). |
773 | */ | 793 | */ |
774 | int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, | 794 | int usb_buffer_map_sg(const struct usb_device *dev, int is_in, |
775 | struct scatterlist *sg, int nents) | 795 | struct scatterlist *sg, int nents) |
776 | { | 796 | { |
777 | struct usb_bus *bus; | 797 | struct usb_bus *bus; |
778 | struct device *controller; | 798 | struct device *controller; |
779 | 799 | ||
780 | if (!dev | 800 | if (!dev |
781 | || usb_pipecontrol(pipe) | ||
782 | || !(bus = dev->bus) | 801 | || !(bus = dev->bus) |
783 | || !(controller = bus->controller) | 802 | || !(controller = bus->controller) |
784 | || !controller->dma_mask) | 803 | || !controller->dma_mask) |
@@ -786,7 +805,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, | |||
786 | 805 | ||
787 | // FIXME generic api broken like pci, can't report errors | 806 | // FIXME generic api broken like pci, can't report errors |
788 | return dma_map_sg(controller, sg, nents, | 807 | return dma_map_sg(controller, sg, nents, |
789 | usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 808 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
790 | } | 809 | } |
791 | 810 | ||
792 | /* XXX DISABLED, no users currently. If you wish to re-enable this | 811 | /* XXX DISABLED, no users currently. If you wish to re-enable this |
@@ -799,14 +818,14 @@ int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, | |||
799 | /** | 818 | /** |
800 | * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s) | 819 | * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s) |
801 | * @dev: device to which the scatterlist will be mapped | 820 | * @dev: device to which the scatterlist will be mapped |
802 | * @pipe: endpoint defining the mapping direction | 821 | * @is_in: mapping transfer direction |
803 | * @sg: the scatterlist to synchronize | 822 | * @sg: the scatterlist to synchronize |
804 | * @n_hw_ents: the positive return value from usb_buffer_map_sg | 823 | * @n_hw_ents: the positive return value from usb_buffer_map_sg |
805 | * | 824 | * |
806 | * Use this when you are re-using a scatterlist's data buffers for | 825 | * Use this when you are re-using a scatterlist's data buffers for |
807 | * another USB request. | 826 | * another USB request. |
808 | */ | 827 | */ |
809 | void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, | 828 | void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in, |
810 | struct scatterlist *sg, int n_hw_ents) | 829 | struct scatterlist *sg, int n_hw_ents) |
811 | { | 830 | { |
812 | struct usb_bus *bus; | 831 | struct usb_bus *bus; |
@@ -819,20 +838,20 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, | |||
819 | return; | 838 | return; |
820 | 839 | ||
821 | dma_sync_sg(controller, sg, n_hw_ents, | 840 | dma_sync_sg(controller, sg, n_hw_ents, |
822 | usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 841 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
823 | } | 842 | } |
824 | #endif | 843 | #endif |
825 | 844 | ||
826 | /** | 845 | /** |
827 | * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist | 846 | * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist |
828 | * @dev: device to which the scatterlist will be mapped | 847 | * @dev: device to which the scatterlist will be mapped |
829 | * @pipe: endpoint defining the mapping direction | 848 | * @is_in: mapping transfer direction |
830 | * @sg: the scatterlist to unmap | 849 | * @sg: the scatterlist to unmap |
831 | * @n_hw_ents: the positive return value from usb_buffer_map_sg | 850 | * @n_hw_ents: the positive return value from usb_buffer_map_sg |
832 | * | 851 | * |
833 | * Reverses the effect of usb_buffer_map_sg(). | 852 | * Reverses the effect of usb_buffer_map_sg(). |
834 | */ | 853 | */ |
835 | void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, | 854 | void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in, |
836 | struct scatterlist *sg, int n_hw_ents) | 855 | struct scatterlist *sg, int n_hw_ents) |
837 | { | 856 | { |
838 | struct usb_bus *bus; | 857 | struct usb_bus *bus; |
@@ -845,7 +864,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, | |||
845 | return; | 864 | return; |
846 | 865 | ||
847 | dma_unmap_sg(controller, sg, n_hw_ents, | 866 | dma_unmap_sg(controller, sg, n_hw_ents, |
848 | usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | 867 | is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); |
849 | } | 868 | } |
850 | 869 | ||
851 | /* format to disable USB on kernel command line is: nousb */ | 870 | /* format to disable USB on kernel command line is: nousb */ |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index ad5fa0338f49..c52626c51f70 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -8,17 +8,22 @@ extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint * | |||
8 | struct usb_device *udev); | 8 | struct usb_device *udev); |
9 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); | 9 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); |
10 | 10 | ||
11 | extern void usb_enable_endpoint(struct usb_device *dev, | ||
12 | struct usb_host_endpoint *ep); | ||
11 | extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); | 13 | extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); |
12 | extern void usb_disable_interface (struct usb_device *dev, | 14 | extern void usb_disable_interface (struct usb_device *dev, |
13 | struct usb_interface *intf); | 15 | struct usb_interface *intf); |
14 | extern void usb_release_interface_cache(struct kref *ref); | 16 | extern void usb_release_interface_cache(struct kref *ref); |
15 | extern void usb_disable_device (struct usb_device *dev, int skip_ep0); | 17 | extern void usb_disable_device (struct usb_device *dev, int skip_ep0); |
18 | extern int usb_deauthorize_device (struct usb_device *); | ||
19 | extern int usb_authorize_device (struct usb_device *); | ||
16 | extern void usb_detect_quirks(struct usb_device *udev); | 20 | extern void usb_detect_quirks(struct usb_device *udev); |
17 | 21 | ||
18 | extern int usb_get_device_descriptor(struct usb_device *dev, | 22 | extern int usb_get_device_descriptor(struct usb_device *dev, |
19 | unsigned int size); | 23 | unsigned int size); |
20 | extern char *usb_cache_string(struct usb_device *udev, int index); | 24 | extern char *usb_cache_string(struct usb_device *udev, int index); |
21 | extern int usb_set_configuration(struct usb_device *dev, int configuration); | 25 | extern int usb_set_configuration(struct usb_device *dev, int configuration); |
26 | extern int usb_choose_configuration(struct usb_device *udev); | ||
22 | 27 | ||
23 | extern void usb_kick_khubd(struct usb_device *dev); | 28 | extern void usb_kick_khubd(struct usb_device *dev); |
24 | extern int usb_match_device(struct usb_device *dev, | 29 | extern int usb_match_device(struct usb_device *dev, |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 767aed5b4bea..f81d08d6538b 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -67,6 +67,17 @@ config USB_GADGET_DEBUG_FILES | |||
67 | driver on a new board. Enable these files by choosing "Y" | 67 | driver on a new board. Enable these files by choosing "Y" |
68 | here. If in doubt, or to conserve kernel memory, say "N". | 68 | here. If in doubt, or to conserve kernel memory, say "N". |
69 | 69 | ||
70 | config USB_GADGET_DEBUG_FS | ||
71 | boolean "Debugging information files in debugfs" | ||
72 | depends on USB_GADGET && DEBUG_FS | ||
73 | help | ||
74 | Some of the drivers in the "gadget" framework can expose | ||
75 | debugging information in files under /sys/kernel/debug/. | ||
76 | The information in these files may help when you're | ||
77 | troubleshooting or bringing up a driver on a new board. | ||
78 | Enable these files by choosing "Y" here. If in doubt, or | ||
79 | to conserve kernel memory, say "N". | ||
80 | |||
70 | config USB_GADGET_SELECTED | 81 | config USB_GADGET_SELECTED |
71 | boolean | 82 | boolean |
72 | 83 | ||
@@ -103,6 +114,20 @@ config USB_AMD5536UDC | |||
103 | default USB_GADGET | 114 | default USB_GADGET |
104 | select USB_GADGET_SELECTED | 115 | select USB_GADGET_SELECTED |
105 | 116 | ||
117 | config USB_GADGET_ATMEL_USBA | ||
118 | boolean "Atmel USBA" | ||
119 | select USB_GADGET_DUALSPEED | ||
120 | depends on AVR32 | ||
121 | help | ||
122 | USBA is the integrated high-speed USB Device controller on | ||
123 | the AT32AP700x processors from Atmel. | ||
124 | |||
125 | config USB_ATMEL_USBA | ||
126 | tristate | ||
127 | depends on USB_GADGET_ATMEL_USBA | ||
128 | default USB_GADGET | ||
129 | select USB_GADGET_SELECTED | ||
130 | |||
106 | config USB_GADGET_FSL_USB2 | 131 | config USB_GADGET_FSL_USB2 |
107 | boolean "Freescale Highspeed USB DR Peripheral Controller" | 132 | boolean "Freescale Highspeed USB DR Peripheral Controller" |
108 | depends on MPC834x || PPC_MPC831x | 133 | depends on MPC834x || PPC_MPC831x |
@@ -228,7 +253,6 @@ config USB_LH7A40X | |||
228 | default USB_GADGET | 253 | default USB_GADGET |
229 | select USB_GADGET_SELECTED | 254 | select USB_GADGET_SELECTED |
230 | 255 | ||
231 | |||
232 | config USB_GADGET_OMAP | 256 | config USB_GADGET_OMAP |
233 | boolean "OMAP USB Device Controller" | 257 | boolean "OMAP USB Device Controller" |
234 | depends on ARCH_OMAP | 258 | depends on ARCH_OMAP |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 1bc0f03550ce..904e57bf6112 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_OMAP) += omap_udc.o | |||
14 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o | 14 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o |
15 | obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o | 15 | obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o |
16 | obj-$(CONFIG_USB_AT91) += at91_udc.o | 16 | obj-$(CONFIG_USB_AT91) += at91_udc.o |
17 | obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o | ||
17 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o | 18 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o |
18 | obj-$(CONFIG_USB_M66592) += m66592-udc.o | 19 | obj-$(CONFIG_USB_M66592) += m66592-udc.o |
19 | 20 | ||
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 714156ca8fe4..1c8040602525 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c | |||
@@ -69,7 +69,7 @@ | |||
69 | 69 | ||
70 | /* gadget stack */ | 70 | /* gadget stack */ |
71 | #include <linux/usb/ch9.h> | 71 | #include <linux/usb/ch9.h> |
72 | #include <linux/usb_gadget.h> | 72 | #include <linux/usb/gadget.h> |
73 | 73 | ||
74 | /* udc specific */ | 74 | /* udc specific */ |
75 | #include "amd5536udc.h" | 75 | #include "amd5536udc.h" |
@@ -3244,7 +3244,6 @@ static int udc_pci_probe( | |||
3244 | retval = -ENOMEM; | 3244 | retval = -ENOMEM; |
3245 | goto finished; | 3245 | goto finished; |
3246 | } | 3246 | } |
3247 | memset(dev, 0, sizeof(struct udc)); | ||
3248 | 3247 | ||
3249 | /* pci setup */ | 3248 | /* pci setup */ |
3250 | if (pci_enable_device(pdev) < 0) { | 3249 | if (pci_enable_device(pdev) < 0) { |
@@ -3286,14 +3285,12 @@ static int udc_pci_probe( | |||
3286 | 3285 | ||
3287 | pci_set_drvdata(pdev, dev); | 3286 | pci_set_drvdata(pdev, dev); |
3288 | 3287 | ||
3289 | /* chip revision */ | 3288 | /* chip revision for Hs AMD5536 */ |
3290 | dev->chiprev = 0; | 3289 | dev->chiprev = pdev->revision; |
3291 | 3290 | ||
3292 | pci_set_master(pdev); | 3291 | pci_set_master(pdev); |
3293 | pci_set_mwi(pdev); | 3292 | pci_set_mwi(pdev); |
3294 | 3293 | ||
3295 | /* chip rev for Hs AMD5536 */ | ||
3296 | pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) &dev->chiprev); | ||
3297 | /* init dma pools */ | 3294 | /* init dma pools */ |
3298 | if (use_dma) { | 3295 | if (use_dma) { |
3299 | retval = init_dma_pools(dev); | 3296 | retval = init_dma_pools(dev); |
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 63d7d6568699..a6adf7e0f6f8 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/proc_fs.h> | 38 | #include <linux/proc_fs.h> |
39 | #include <linux/clk.h> | 39 | #include <linux/clk.h> |
40 | #include <linux/usb/ch9.h> | 40 | #include <linux/usb/ch9.h> |
41 | #include <linux/usb_gadget.h> | 41 | #include <linux/usb/gadget.h> |
42 | 42 | ||
43 | #include <asm/byteorder.h> | 43 | #include <asm/byteorder.h> |
44 | #include <asm/hardware.h> | 44 | #include <asm/hardware.h> |
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c new file mode 100644 index 000000000000..4fb5ff469574 --- /dev/null +++ b/drivers/usb/gadget/atmel_usba_udc.c | |||
@@ -0,0 +1,2077 @@ | |||
1 | /* | ||
2 | * Driver for the Atmel USBA high speed USB device controller | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/clk.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/usb/ch9.h> | ||
20 | #include <linux/usb/gadget.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include <asm/gpio.h> | ||
24 | #include <asm/arch/board.h> | ||
25 | |||
26 | #include "atmel_usba_udc.h" | ||
27 | |||
28 | |||
29 | static struct usba_udc the_udc; | ||
30 | |||
31 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | ||
32 | #include <linux/debugfs.h> | ||
33 | #include <linux/uaccess.h> | ||
34 | |||
35 | static int queue_dbg_open(struct inode *inode, struct file *file) | ||
36 | { | ||
37 | struct usba_ep *ep = inode->i_private; | ||
38 | struct usba_request *req, *req_copy; | ||
39 | struct list_head *queue_data; | ||
40 | |||
41 | queue_data = kmalloc(sizeof(*queue_data), GFP_KERNEL); | ||
42 | if (!queue_data) | ||
43 | return -ENOMEM; | ||
44 | INIT_LIST_HEAD(queue_data); | ||
45 | |||
46 | spin_lock_irq(&ep->udc->lock); | ||
47 | list_for_each_entry(req, &ep->queue, queue) { | ||
48 | req_copy = kmalloc(sizeof(*req_copy), GFP_ATOMIC); | ||
49 | if (!req_copy) | ||
50 | goto fail; | ||
51 | memcpy(req_copy, req, sizeof(*req_copy)); | ||
52 | list_add_tail(&req_copy->queue, queue_data); | ||
53 | } | ||
54 | spin_unlock_irq(&ep->udc->lock); | ||
55 | |||
56 | file->private_data = queue_data; | ||
57 | return 0; | ||
58 | |||
59 | fail: | ||
60 | spin_unlock_irq(&ep->udc->lock); | ||
61 | list_for_each_entry_safe(req, req_copy, queue_data, queue) { | ||
62 | list_del(&req->queue); | ||
63 | kfree(req); | ||
64 | } | ||
65 | kfree(queue_data); | ||
66 | return -ENOMEM; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * bbbbbbbb llllllll IZS sssss nnnn FDL\n\0 | ||
71 | * | ||
72 | * b: buffer address | ||
73 | * l: buffer length | ||
74 | * I/i: interrupt/no interrupt | ||
75 | * Z/z: zero/no zero | ||
76 | * S/s: short ok/short not ok | ||
77 | * s: status | ||
78 | * n: nr_packets | ||
79 | * F/f: submitted/not submitted to FIFO | ||
80 | * D/d: using/not using DMA | ||
81 | * L/l: last transaction/not last transaction | ||
82 | */ | ||
83 | static ssize_t queue_dbg_read(struct file *file, char __user *buf, | ||
84 | size_t nbytes, loff_t *ppos) | ||
85 | { | ||
86 | struct list_head *queue = file->private_data; | ||
87 | struct usba_request *req, *tmp_req; | ||
88 | size_t len, remaining, actual = 0; | ||
89 | char tmpbuf[38]; | ||
90 | |||
91 | if (!access_ok(VERIFY_WRITE, buf, nbytes)) | ||
92 | return -EFAULT; | ||
93 | |||
94 | mutex_lock(&file->f_dentry->d_inode->i_mutex); | ||
95 | list_for_each_entry_safe(req, tmp_req, queue, queue) { | ||
96 | len = snprintf(tmpbuf, sizeof(tmpbuf), | ||
97 | "%8p %08x %c%c%c %5d %c%c%c\n", | ||
98 | req->req.buf, req->req.length, | ||
99 | req->req.no_interrupt ? 'i' : 'I', | ||
100 | req->req.zero ? 'Z' : 'z', | ||
101 | req->req.short_not_ok ? 's' : 'S', | ||
102 | req->req.status, | ||
103 | req->submitted ? 'F' : 'f', | ||
104 | req->using_dma ? 'D' : 'd', | ||
105 | req->last_transaction ? 'L' : 'l'); | ||
106 | len = min(len, sizeof(tmpbuf)); | ||
107 | if (len > nbytes) | ||
108 | break; | ||
109 | |||
110 | list_del(&req->queue); | ||
111 | kfree(req); | ||
112 | |||
113 | remaining = __copy_to_user(buf, tmpbuf, len); | ||
114 | actual += len - remaining; | ||
115 | if (remaining) | ||
116 | break; | ||
117 | |||
118 | nbytes -= len; | ||
119 | buf += len; | ||
120 | } | ||
121 | mutex_unlock(&file->f_dentry->d_inode->i_mutex); | ||
122 | |||
123 | return actual; | ||
124 | } | ||
125 | |||
126 | static int queue_dbg_release(struct inode *inode, struct file *file) | ||
127 | { | ||
128 | struct list_head *queue_data = file->private_data; | ||
129 | struct usba_request *req, *tmp_req; | ||
130 | |||
131 | list_for_each_entry_safe(req, tmp_req, queue_data, queue) { | ||
132 | list_del(&req->queue); | ||
133 | kfree(req); | ||
134 | } | ||
135 | kfree(queue_data); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int regs_dbg_open(struct inode *inode, struct file *file) | ||
140 | { | ||
141 | struct usba_udc *udc; | ||
142 | unsigned int i; | ||
143 | u32 *data; | ||
144 | int ret = -ENOMEM; | ||
145 | |||
146 | mutex_lock(&inode->i_mutex); | ||
147 | udc = inode->i_private; | ||
148 | data = kmalloc(inode->i_size, GFP_KERNEL); | ||
149 | if (!data) | ||
150 | goto out; | ||
151 | |||
152 | spin_lock_irq(&udc->lock); | ||
153 | for (i = 0; i < inode->i_size / 4; i++) | ||
154 | data[i] = __raw_readl(udc->regs + i * 4); | ||
155 | spin_unlock_irq(&udc->lock); | ||
156 | |||
157 | file->private_data = data; | ||
158 | ret = 0; | ||
159 | |||
160 | out: | ||
161 | mutex_unlock(&inode->i_mutex); | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | static ssize_t regs_dbg_read(struct file *file, char __user *buf, | ||
167 | size_t nbytes, loff_t *ppos) | ||
168 | { | ||
169 | struct inode *inode = file->f_dentry->d_inode; | ||
170 | int ret; | ||
171 | |||
172 | mutex_lock(&inode->i_mutex); | ||
173 | ret = simple_read_from_buffer(buf, nbytes, ppos, | ||
174 | file->private_data, | ||
175 | file->f_dentry->d_inode->i_size); | ||
176 | mutex_unlock(&inode->i_mutex); | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static int regs_dbg_release(struct inode *inode, struct file *file) | ||
182 | { | ||
183 | kfree(file->private_data); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | const struct file_operations queue_dbg_fops = { | ||
188 | .owner = THIS_MODULE, | ||
189 | .open = queue_dbg_open, | ||
190 | .llseek = no_llseek, | ||
191 | .read = queue_dbg_read, | ||
192 | .release = queue_dbg_release, | ||
193 | }; | ||
194 | |||
195 | const struct file_operations regs_dbg_fops = { | ||
196 | .owner = THIS_MODULE, | ||
197 | .open = regs_dbg_open, | ||
198 | .llseek = generic_file_llseek, | ||
199 | .read = regs_dbg_read, | ||
200 | .release = regs_dbg_release, | ||
201 | }; | ||
202 | |||
203 | static void usba_ep_init_debugfs(struct usba_udc *udc, | ||
204 | struct usba_ep *ep) | ||
205 | { | ||
206 | struct dentry *ep_root; | ||
207 | |||
208 | ep_root = debugfs_create_dir(ep->ep.name, udc->debugfs_root); | ||
209 | if (!ep_root) | ||
210 | goto err_root; | ||
211 | ep->debugfs_dir = ep_root; | ||
212 | |||
213 | ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root, | ||
214 | ep, &queue_dbg_fops); | ||
215 | if (!ep->debugfs_queue) | ||
216 | goto err_queue; | ||
217 | |||
218 | if (ep->can_dma) { | ||
219 | ep->debugfs_dma_status | ||
220 | = debugfs_create_u32("dma_status", 0400, ep_root, | ||
221 | &ep->last_dma_status); | ||
222 | if (!ep->debugfs_dma_status) | ||
223 | goto err_dma_status; | ||
224 | } | ||
225 | if (ep_is_control(ep)) { | ||
226 | ep->debugfs_state | ||
227 | = debugfs_create_u32("state", 0400, ep_root, | ||
228 | &ep->state); | ||
229 | if (!ep->debugfs_state) | ||
230 | goto err_state; | ||
231 | } | ||
232 | |||
233 | return; | ||
234 | |||
235 | err_state: | ||
236 | if (ep->can_dma) | ||
237 | debugfs_remove(ep->debugfs_dma_status); | ||
238 | err_dma_status: | ||
239 | debugfs_remove(ep->debugfs_queue); | ||
240 | err_queue: | ||
241 | debugfs_remove(ep_root); | ||
242 | err_root: | ||
243 | dev_err(&ep->udc->pdev->dev, | ||
244 | "failed to create debugfs directory for %s\n", ep->ep.name); | ||
245 | } | ||
246 | |||
247 | static void usba_ep_cleanup_debugfs(struct usba_ep *ep) | ||
248 | { | ||
249 | debugfs_remove(ep->debugfs_queue); | ||
250 | debugfs_remove(ep->debugfs_dma_status); | ||
251 | debugfs_remove(ep->debugfs_state); | ||
252 | debugfs_remove(ep->debugfs_dir); | ||
253 | ep->debugfs_dma_status = NULL; | ||
254 | ep->debugfs_dir = NULL; | ||
255 | } | ||
256 | |||
257 | static void usba_init_debugfs(struct usba_udc *udc) | ||
258 | { | ||
259 | struct dentry *root, *regs; | ||
260 | struct resource *regs_resource; | ||
261 | |||
262 | root = debugfs_create_dir(udc->gadget.name, NULL); | ||
263 | if (IS_ERR(root) || !root) | ||
264 | goto err_root; | ||
265 | udc->debugfs_root = root; | ||
266 | |||
267 | regs = debugfs_create_file("regs", 0400, root, udc, ®s_dbg_fops); | ||
268 | if (!regs) | ||
269 | goto err_regs; | ||
270 | |||
271 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, | ||
272 | CTRL_IOMEM_ID); | ||
273 | regs->d_inode->i_size = regs_resource->end - regs_resource->start + 1; | ||
274 | udc->debugfs_regs = regs; | ||
275 | |||
276 | usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); | ||
277 | |||
278 | return; | ||
279 | |||
280 | err_regs: | ||
281 | debugfs_remove(root); | ||
282 | err_root: | ||
283 | udc->debugfs_root = NULL; | ||
284 | dev_err(&udc->pdev->dev, "debugfs is not available\n"); | ||
285 | } | ||
286 | |||
287 | static void usba_cleanup_debugfs(struct usba_udc *udc) | ||
288 | { | ||
289 | usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0)); | ||
290 | debugfs_remove(udc->debugfs_regs); | ||
291 | debugfs_remove(udc->debugfs_root); | ||
292 | udc->debugfs_regs = NULL; | ||
293 | udc->debugfs_root = NULL; | ||
294 | } | ||
295 | #else | ||
296 | static inline void usba_ep_init_debugfs(struct usba_udc *udc, | ||
297 | struct usba_ep *ep) | ||
298 | { | ||
299 | |||
300 | } | ||
301 | |||
302 | static inline void usba_ep_cleanup_debugfs(struct usba_ep *ep) | ||
303 | { | ||
304 | |||
305 | } | ||
306 | |||
307 | static inline void usba_init_debugfs(struct usba_udc *udc) | ||
308 | { | ||
309 | |||
310 | } | ||
311 | |||
312 | static inline void usba_cleanup_debugfs(struct usba_udc *udc) | ||
313 | { | ||
314 | |||
315 | } | ||
316 | #endif | ||
317 | |||
318 | static int vbus_is_present(struct usba_udc *udc) | ||
319 | { | ||
320 | if (udc->vbus_pin != -1) | ||
321 | return gpio_get_value(udc->vbus_pin); | ||
322 | |||
323 | /* No Vbus detection: Assume always present */ | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | static void copy_to_fifo(void __iomem *fifo, const void *buf, int len) | ||
328 | { | ||
329 | unsigned long tmp; | ||
330 | |||
331 | DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len); | ||
332 | for (; len > 0; len -= 4, buf += 4, fifo += 4) { | ||
333 | tmp = *(unsigned long *)buf; | ||
334 | if (len >= 4) { | ||
335 | DBG(DBG_FIFO, " -> %08lx\n", tmp); | ||
336 | __raw_writel(tmp, fifo); | ||
337 | } else { | ||
338 | do { | ||
339 | DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24); | ||
340 | __raw_writeb(tmp >> 24, fifo); | ||
341 | fifo++; | ||
342 | tmp <<= 8; | ||
343 | } while (--len); | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static void copy_from_fifo(void *buf, void __iomem *fifo, int len) | ||
350 | { | ||
351 | union { | ||
352 | unsigned long *w; | ||
353 | unsigned char *b; | ||
354 | } p; | ||
355 | unsigned long tmp; | ||
356 | |||
357 | DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len); | ||
358 | for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) { | ||
359 | if (len >= 4) { | ||
360 | tmp = __raw_readl(fifo); | ||
361 | *p.w = tmp; | ||
362 | DBG(DBG_FIFO, " -> %08lx\n", tmp); | ||
363 | } else { | ||
364 | do { | ||
365 | tmp = __raw_readb(fifo); | ||
366 | *p.b = tmp; | ||
367 | DBG(DBG_FIFO, " -> %02lx\n", tmp); | ||
368 | fifo++, p.b++; | ||
369 | } while (--len); | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req) | ||
375 | { | ||
376 | unsigned int transaction_len; | ||
377 | |||
378 | transaction_len = req->req.length - req->req.actual; | ||
379 | req->last_transaction = 1; | ||
380 | if (transaction_len > ep->ep.maxpacket) { | ||
381 | transaction_len = ep->ep.maxpacket; | ||
382 | req->last_transaction = 0; | ||
383 | } else if (transaction_len == ep->ep.maxpacket && req->req.zero) | ||
384 | req->last_transaction = 0; | ||
385 | |||
386 | DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n", | ||
387 | ep->ep.name, req, transaction_len, | ||
388 | req->last_transaction ? ", done" : ""); | ||
389 | |||
390 | copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len); | ||
391 | usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); | ||
392 | req->req.actual += transaction_len; | ||
393 | } | ||
394 | |||
395 | static void submit_request(struct usba_ep *ep, struct usba_request *req) | ||
396 | { | ||
397 | DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d)\n", | ||
398 | ep->ep.name, req, req->req.length); | ||
399 | |||
400 | req->req.actual = 0; | ||
401 | req->submitted = 1; | ||
402 | |||
403 | if (req->using_dma) { | ||
404 | if (req->req.length == 0) { | ||
405 | usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | if (req->req.zero) | ||
410 | usba_ep_writel(ep, CTL_ENB, USBA_SHORT_PACKET); | ||
411 | else | ||
412 | usba_ep_writel(ep, CTL_DIS, USBA_SHORT_PACKET); | ||
413 | |||
414 | usba_dma_writel(ep, ADDRESS, req->req.dma); | ||
415 | usba_dma_writel(ep, CONTROL, req->ctrl); | ||
416 | } else { | ||
417 | next_fifo_transaction(ep, req); | ||
418 | if (req->last_transaction) { | ||
419 | usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); | ||
420 | usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); | ||
421 | } else { | ||
422 | usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); | ||
423 | usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); | ||
424 | } | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static void submit_next_request(struct usba_ep *ep) | ||
429 | { | ||
430 | struct usba_request *req; | ||
431 | |||
432 | if (list_empty(&ep->queue)) { | ||
433 | usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY); | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | req = list_entry(ep->queue.next, struct usba_request, queue); | ||
438 | if (!req->submitted) | ||
439 | submit_request(ep, req); | ||
440 | } | ||
441 | |||
442 | static void send_status(struct usba_udc *udc, struct usba_ep *ep) | ||
443 | { | ||
444 | ep->state = STATUS_STAGE_IN; | ||
445 | usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); | ||
446 | usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); | ||
447 | } | ||
448 | |||
449 | static void receive_data(struct usba_ep *ep) | ||
450 | { | ||
451 | struct usba_udc *udc = ep->udc; | ||
452 | struct usba_request *req; | ||
453 | unsigned long status; | ||
454 | unsigned int bytecount, nr_busy; | ||
455 | int is_complete = 0; | ||
456 | |||
457 | status = usba_ep_readl(ep, STA); | ||
458 | nr_busy = USBA_BFEXT(BUSY_BANKS, status); | ||
459 | |||
460 | DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy); | ||
461 | |||
462 | while (nr_busy > 0) { | ||
463 | if (list_empty(&ep->queue)) { | ||
464 | usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); | ||
465 | break; | ||
466 | } | ||
467 | req = list_entry(ep->queue.next, | ||
468 | struct usba_request, queue); | ||
469 | |||
470 | bytecount = USBA_BFEXT(BYTE_COUNT, status); | ||
471 | |||
472 | if (status & (1 << 31)) | ||
473 | is_complete = 1; | ||
474 | if (req->req.actual + bytecount >= req->req.length) { | ||
475 | is_complete = 1; | ||
476 | bytecount = req->req.length - req->req.actual; | ||
477 | } | ||
478 | |||
479 | copy_from_fifo(req->req.buf + req->req.actual, | ||
480 | ep->fifo, bytecount); | ||
481 | req->req.actual += bytecount; | ||
482 | |||
483 | usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); | ||
484 | |||
485 | if (is_complete) { | ||
486 | DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name); | ||
487 | req->req.status = 0; | ||
488 | list_del_init(&req->queue); | ||
489 | usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); | ||
490 | spin_unlock(&udc->lock); | ||
491 | req->req.complete(&ep->ep, &req->req); | ||
492 | spin_lock(&udc->lock); | ||
493 | } | ||
494 | |||
495 | status = usba_ep_readl(ep, STA); | ||
496 | nr_busy = USBA_BFEXT(BUSY_BANKS, status); | ||
497 | |||
498 | if (is_complete && ep_is_control(ep)) { | ||
499 | send_status(udc, ep); | ||
500 | break; | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | |||
505 | static void | ||
506 | request_complete(struct usba_ep *ep, struct usba_request *req, int status) | ||
507 | { | ||
508 | struct usba_udc *udc = ep->udc; | ||
509 | |||
510 | WARN_ON(!list_empty(&req->queue)); | ||
511 | |||
512 | if (req->req.status == -EINPROGRESS) | ||
513 | req->req.status = status; | ||
514 | |||
515 | if (req->mapped) { | ||
516 | dma_unmap_single( | ||
517 | &udc->pdev->dev, req->req.dma, req->req.length, | ||
518 | ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
519 | req->req.dma = DMA_ADDR_INVALID; | ||
520 | req->mapped = 0; | ||
521 | } | ||
522 | |||
523 | DBG(DBG_GADGET | DBG_REQ, | ||
524 | "%s: req %p complete: status %d, actual %u\n", | ||
525 | ep->ep.name, req, req->req.status, req->req.actual); | ||
526 | |||
527 | spin_unlock(&udc->lock); | ||
528 | req->req.complete(&ep->ep, &req->req); | ||
529 | spin_lock(&udc->lock); | ||
530 | } | ||
531 | |||
532 | static void | ||
533 | request_complete_list(struct usba_ep *ep, struct list_head *list, int status) | ||
534 | { | ||
535 | struct usba_request *req, *tmp_req; | ||
536 | |||
537 | list_for_each_entry_safe(req, tmp_req, list, queue) { | ||
538 | list_del_init(&req->queue); | ||
539 | request_complete(ep, req, status); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | static int | ||
544 | usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | ||
545 | { | ||
546 | struct usba_ep *ep = to_usba_ep(_ep); | ||
547 | struct usba_udc *udc = ep->udc; | ||
548 | unsigned long flags, ept_cfg, maxpacket; | ||
549 | unsigned int nr_trans; | ||
550 | |||
551 | DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); | ||
552 | |||
553 | maxpacket = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; | ||
554 | |||
555 | if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index) | ||
556 | || ep->index == 0 | ||
557 | || desc->bDescriptorType != USB_DT_ENDPOINT | ||
558 | || maxpacket == 0 | ||
559 | || maxpacket > ep->fifo_size) { | ||
560 | DBG(DBG_ERR, "ep_enable: Invalid argument"); | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | |||
564 | ep->is_isoc = 0; | ||
565 | ep->is_in = 0; | ||
566 | |||
567 | if (maxpacket <= 8) | ||
568 | ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8); | ||
569 | else | ||
570 | /* LSB is bit 1, not 0 */ | ||
571 | ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3); | ||
572 | |||
573 | DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n", | ||
574 | ep->ep.name, ept_cfg, maxpacket); | ||
575 | |||
576 | if ((desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { | ||
577 | ep->is_in = 1; | ||
578 | ept_cfg |= USBA_EPT_DIR_IN; | ||
579 | } | ||
580 | |||
581 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
582 | case USB_ENDPOINT_XFER_CONTROL: | ||
583 | ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL); | ||
584 | ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE); | ||
585 | break; | ||
586 | case USB_ENDPOINT_XFER_ISOC: | ||
587 | if (!ep->can_isoc) { | ||
588 | DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n", | ||
589 | ep->ep.name); | ||
590 | return -EINVAL; | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Bits 11:12 specify number of _additional_ | ||
595 | * transactions per microframe. | ||
596 | */ | ||
597 | nr_trans = ((le16_to_cpu(desc->wMaxPacketSize) >> 11) & 3) + 1; | ||
598 | if (nr_trans > 3) | ||
599 | return -EINVAL; | ||
600 | |||
601 | ep->is_isoc = 1; | ||
602 | ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO); | ||
603 | |||
604 | /* | ||
605 | * Do triple-buffering on high-bandwidth iso endpoints. | ||
606 | */ | ||
607 | if (nr_trans > 1 && ep->nr_banks == 3) | ||
608 | ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE); | ||
609 | else | ||
610 | ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); | ||
611 | ept_cfg |= USBA_BF(NB_TRANS, nr_trans); | ||
612 | break; | ||
613 | case USB_ENDPOINT_XFER_BULK: | ||
614 | ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK); | ||
615 | ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); | ||
616 | break; | ||
617 | case USB_ENDPOINT_XFER_INT: | ||
618 | ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT); | ||
619 | ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE); | ||
620 | break; | ||
621 | } | ||
622 | |||
623 | spin_lock_irqsave(&ep->udc->lock, flags); | ||
624 | |||
625 | if (ep->desc) { | ||
626 | spin_unlock_irqrestore(&ep->udc->lock, flags); | ||
627 | DBG(DBG_ERR, "ep%d already enabled\n", ep->index); | ||
628 | return -EBUSY; | ||
629 | } | ||
630 | |||
631 | ep->desc = desc; | ||
632 | ep->ep.maxpacket = maxpacket; | ||
633 | |||
634 | usba_ep_writel(ep, CFG, ept_cfg); | ||
635 | usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); | ||
636 | |||
637 | if (ep->can_dma) { | ||
638 | u32 ctrl; | ||
639 | |||
640 | usba_writel(udc, INT_ENB, | ||
641 | (usba_readl(udc, INT_ENB) | ||
642 | | USBA_BF(EPT_INT, 1 << ep->index) | ||
643 | | USBA_BF(DMA_INT, 1 << ep->index))); | ||
644 | ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA; | ||
645 | usba_ep_writel(ep, CTL_ENB, ctrl); | ||
646 | } else { | ||
647 | usba_writel(udc, INT_ENB, | ||
648 | (usba_readl(udc, INT_ENB) | ||
649 | | USBA_BF(EPT_INT, 1 << ep->index))); | ||
650 | } | ||
651 | |||
652 | spin_unlock_irqrestore(&udc->lock, flags); | ||
653 | |||
654 | DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index, | ||
655 | (unsigned long)usba_ep_readl(ep, CFG)); | ||
656 | DBG(DBG_HW, "INT_ENB after init: %#08lx\n", | ||
657 | (unsigned long)usba_readl(udc, INT_ENB)); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static int usba_ep_disable(struct usb_ep *_ep) | ||
663 | { | ||
664 | struct usba_ep *ep = to_usba_ep(_ep); | ||
665 | struct usba_udc *udc = ep->udc; | ||
666 | LIST_HEAD(req_list); | ||
667 | unsigned long flags; | ||
668 | |||
669 | DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name); | ||
670 | |||
671 | spin_lock_irqsave(&udc->lock, flags); | ||
672 | |||
673 | if (!ep->desc) { | ||
674 | spin_unlock_irqrestore(&udc->lock, flags); | ||
675 | DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); | ||
676 | return -EINVAL; | ||
677 | } | ||
678 | ep->desc = NULL; | ||
679 | |||
680 | list_splice_init(&ep->queue, &req_list); | ||
681 | if (ep->can_dma) { | ||
682 | usba_dma_writel(ep, CONTROL, 0); | ||
683 | usba_dma_writel(ep, ADDRESS, 0); | ||
684 | usba_dma_readl(ep, STATUS); | ||
685 | } | ||
686 | usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); | ||
687 | usba_writel(udc, INT_ENB, | ||
688 | usba_readl(udc, INT_ENB) | ||
689 | & ~USBA_BF(EPT_INT, 1 << ep->index)); | ||
690 | |||
691 | request_complete_list(ep, &req_list, -ESHUTDOWN); | ||
692 | |||
693 | spin_unlock_irqrestore(&udc->lock, flags); | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static struct usb_request * | ||
699 | usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) | ||
700 | { | ||
701 | struct usba_request *req; | ||
702 | |||
703 | DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags); | ||
704 | |||
705 | req = kzalloc(sizeof(*req), gfp_flags); | ||
706 | if (!req) | ||
707 | return NULL; | ||
708 | |||
709 | INIT_LIST_HEAD(&req->queue); | ||
710 | req->req.dma = DMA_ADDR_INVALID; | ||
711 | |||
712 | return &req->req; | ||
713 | } | ||
714 | |||
715 | static void | ||
716 | usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) | ||
717 | { | ||
718 | struct usba_request *req = to_usba_req(_req); | ||
719 | |||
720 | DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req); | ||
721 | |||
722 | kfree(req); | ||
723 | } | ||
724 | |||
725 | static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, | ||
726 | struct usba_request *req, gfp_t gfp_flags) | ||
727 | { | ||
728 | unsigned long flags; | ||
729 | int ret; | ||
730 | |||
731 | DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n", | ||
732 | ep->ep.name, req->req.length, req->req.dma, | ||
733 | req->req.zero ? 'Z' : 'z', | ||
734 | req->req.short_not_ok ? 'S' : 's', | ||
735 | req->req.no_interrupt ? 'I' : 'i'); | ||
736 | |||
737 | if (req->req.length > 0x10000) { | ||
738 | /* Lengths from 0 to 65536 (inclusive) are supported */ | ||
739 | DBG(DBG_ERR, "invalid request length %u\n", req->req.length); | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | |||
743 | req->using_dma = 1; | ||
744 | |||
745 | if (req->req.dma == DMA_ADDR_INVALID) { | ||
746 | req->req.dma = dma_map_single( | ||
747 | &udc->pdev->dev, req->req.buf, req->req.length, | ||
748 | ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
749 | req->mapped = 1; | ||
750 | } else { | ||
751 | dma_sync_single_for_device( | ||
752 | &udc->pdev->dev, req->req.dma, req->req.length, | ||
753 | ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
754 | req->mapped = 0; | ||
755 | } | ||
756 | |||
757 | req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length) | ||
758 | | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE | ||
759 | | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE; | ||
760 | |||
761 | if (ep->is_in) | ||
762 | req->ctrl |= USBA_DMA_END_BUF_EN; | ||
763 | |||
764 | /* | ||
765 | * Add this request to the queue and submit for DMA if | ||
766 | * possible. Check if we're still alive first -- we may have | ||
767 | * received a reset since last time we checked. | ||
768 | */ | ||
769 | ret = -ESHUTDOWN; | ||
770 | spin_lock_irqsave(&udc->lock, flags); | ||
771 | if (ep->desc) { | ||
772 | if (list_empty(&ep->queue)) | ||
773 | submit_request(ep, req); | ||
774 | |||
775 | list_add_tail(&req->queue, &ep->queue); | ||
776 | ret = 0; | ||
777 | } | ||
778 | spin_unlock_irqrestore(&udc->lock, flags); | ||
779 | |||
780 | return ret; | ||
781 | } | ||
782 | |||
783 | static int | ||
784 | usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | ||
785 | { | ||
786 | struct usba_request *req = to_usba_req(_req); | ||
787 | struct usba_ep *ep = to_usba_ep(_ep); | ||
788 | struct usba_udc *udc = ep->udc; | ||
789 | unsigned long flags; | ||
790 | int ret; | ||
791 | |||
792 | DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n", | ||
793 | ep->ep.name, req, _req->length); | ||
794 | |||
795 | if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN || !ep->desc) | ||
796 | return -ESHUTDOWN; | ||
797 | |||
798 | req->submitted = 0; | ||
799 | req->using_dma = 0; | ||
800 | req->last_transaction = 0; | ||
801 | |||
802 | _req->status = -EINPROGRESS; | ||
803 | _req->actual = 0; | ||
804 | |||
805 | if (ep->can_dma) | ||
806 | return queue_dma(udc, ep, req, gfp_flags); | ||
807 | |||
808 | /* May have received a reset since last time we checked */ | ||
809 | ret = -ESHUTDOWN; | ||
810 | spin_lock_irqsave(&udc->lock, flags); | ||
811 | if (ep->desc) { | ||
812 | list_add_tail(&req->queue, &ep->queue); | ||
813 | |||
814 | if (ep->is_in || (ep_is_control(ep) | ||
815 | && (ep->state == DATA_STAGE_IN | ||
816 | || ep->state == STATUS_STAGE_IN))) | ||
817 | usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); | ||
818 | else | ||
819 | usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY); | ||
820 | ret = 0; | ||
821 | } | ||
822 | spin_unlock_irqrestore(&udc->lock, flags); | ||
823 | |||
824 | return ret; | ||
825 | } | ||
826 | |||
827 | static void | ||
828 | usba_update_req(struct usba_ep *ep, struct usba_request *req, u32 status) | ||
829 | { | ||
830 | req->req.actual = req->req.length - USBA_BFEXT(DMA_BUF_LEN, status); | ||
831 | } | ||
832 | |||
833 | static int stop_dma(struct usba_ep *ep, u32 *pstatus) | ||
834 | { | ||
835 | unsigned int timeout; | ||
836 | u32 status; | ||
837 | |||
838 | /* | ||
839 | * Stop the DMA controller. When writing both CH_EN | ||
840 | * and LINK to 0, the other bits are not affected. | ||
841 | */ | ||
842 | usba_dma_writel(ep, CONTROL, 0); | ||
843 | |||
844 | /* Wait for the FIFO to empty */ | ||
845 | for (timeout = 40; timeout; --timeout) { | ||
846 | status = usba_dma_readl(ep, STATUS); | ||
847 | if (!(status & USBA_DMA_CH_EN)) | ||
848 | break; | ||
849 | udelay(1); | ||
850 | } | ||
851 | |||
852 | if (pstatus) | ||
853 | *pstatus = status; | ||
854 | |||
855 | if (timeout == 0) { | ||
856 | dev_err(&ep->udc->pdev->dev, | ||
857 | "%s: timed out waiting for DMA FIFO to empty\n", | ||
858 | ep->ep.name); | ||
859 | return -ETIMEDOUT; | ||
860 | } | ||
861 | |||
862 | return 0; | ||
863 | } | ||
864 | |||
865 | static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
866 | { | ||
867 | struct usba_ep *ep = to_usba_ep(_ep); | ||
868 | struct usba_udc *udc = ep->udc; | ||
869 | struct usba_request *req = to_usba_req(_req); | ||
870 | unsigned long flags; | ||
871 | u32 status; | ||
872 | |||
873 | DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", | ||
874 | ep->ep.name, req); | ||
875 | |||
876 | spin_lock_irqsave(&udc->lock, flags); | ||
877 | |||
878 | if (req->using_dma) { | ||
879 | /* | ||
880 | * If this request is currently being transferred, | ||
881 | * stop the DMA controller and reset the FIFO. | ||
882 | */ | ||
883 | if (ep->queue.next == &req->queue) { | ||
884 | status = usba_dma_readl(ep, STATUS); | ||
885 | if (status & USBA_DMA_CH_EN) | ||
886 | stop_dma(ep, &status); | ||
887 | |||
888 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | ||
889 | ep->last_dma_status = status; | ||
890 | #endif | ||
891 | |||
892 | usba_writel(udc, EPT_RST, 1 << ep->index); | ||
893 | |||
894 | usba_update_req(ep, req, status); | ||
895 | } | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * Errors should stop the queue from advancing until the | ||
900 | * completion function returns. | ||
901 | */ | ||
902 | list_del_init(&req->queue); | ||
903 | |||
904 | request_complete(ep, req, -ECONNRESET); | ||
905 | |||
906 | /* Process the next request if any */ | ||
907 | submit_next_request(ep); | ||
908 | spin_unlock_irqrestore(&udc->lock, flags); | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | static int usba_ep_set_halt(struct usb_ep *_ep, int value) | ||
914 | { | ||
915 | struct usba_ep *ep = to_usba_ep(_ep); | ||
916 | struct usba_udc *udc = ep->udc; | ||
917 | unsigned long flags; | ||
918 | int ret = 0; | ||
919 | |||
920 | DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name, | ||
921 | value ? "set" : "clear"); | ||
922 | |||
923 | if (!ep->desc) { | ||
924 | DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n", | ||
925 | ep->ep.name); | ||
926 | return -ENODEV; | ||
927 | } | ||
928 | if (ep->is_isoc) { | ||
929 | DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n", | ||
930 | ep->ep.name); | ||
931 | return -ENOTTY; | ||
932 | } | ||
933 | |||
934 | spin_lock_irqsave(&udc->lock, flags); | ||
935 | |||
936 | /* | ||
937 | * We can't halt IN endpoints while there are still data to be | ||
938 | * transferred | ||
939 | */ | ||
940 | if (!list_empty(&ep->queue) | ||
941 | || ((value && ep->is_in && (usba_ep_readl(ep, STA) | ||
942 | & USBA_BF(BUSY_BANKS, -1L))))) { | ||
943 | ret = -EAGAIN; | ||
944 | } else { | ||
945 | if (value) | ||
946 | usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL); | ||
947 | else | ||
948 | usba_ep_writel(ep, CLR_STA, | ||
949 | USBA_FORCE_STALL | USBA_TOGGLE_CLR); | ||
950 | usba_ep_readl(ep, STA); | ||
951 | } | ||
952 | |||
953 | spin_unlock_irqrestore(&udc->lock, flags); | ||
954 | |||
955 | return ret; | ||
956 | } | ||
957 | |||
958 | static int usba_ep_fifo_status(struct usb_ep *_ep) | ||
959 | { | ||
960 | struct usba_ep *ep = to_usba_ep(_ep); | ||
961 | |||
962 | return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); | ||
963 | } | ||
964 | |||
965 | static void usba_ep_fifo_flush(struct usb_ep *_ep) | ||
966 | { | ||
967 | struct usba_ep *ep = to_usba_ep(_ep); | ||
968 | struct usba_udc *udc = ep->udc; | ||
969 | |||
970 | usba_writel(udc, EPT_RST, 1 << ep->index); | ||
971 | } | ||
972 | |||
973 | static const struct usb_ep_ops usba_ep_ops = { | ||
974 | .enable = usba_ep_enable, | ||
975 | .disable = usba_ep_disable, | ||
976 | .alloc_request = usba_ep_alloc_request, | ||
977 | .free_request = usba_ep_free_request, | ||
978 | .queue = usba_ep_queue, | ||
979 | .dequeue = usba_ep_dequeue, | ||
980 | .set_halt = usba_ep_set_halt, | ||
981 | .fifo_status = usba_ep_fifo_status, | ||
982 | .fifo_flush = usba_ep_fifo_flush, | ||
983 | }; | ||
984 | |||
985 | static int usba_udc_get_frame(struct usb_gadget *gadget) | ||
986 | { | ||
987 | struct usba_udc *udc = to_usba_udc(gadget); | ||
988 | |||
989 | return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM)); | ||
990 | } | ||
991 | |||
992 | static int usba_udc_wakeup(struct usb_gadget *gadget) | ||
993 | { | ||
994 | struct usba_udc *udc = to_usba_udc(gadget); | ||
995 | unsigned long flags; | ||
996 | u32 ctrl; | ||
997 | int ret = -EINVAL; | ||
998 | |||
999 | spin_lock_irqsave(&udc->lock, flags); | ||
1000 | if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | ||
1001 | ctrl = usba_readl(udc, CTRL); | ||
1002 | usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP); | ||
1003 | ret = 0; | ||
1004 | } | ||
1005 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1006 | |||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | static int | ||
1011 | usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) | ||
1012 | { | ||
1013 | struct usba_udc *udc = to_usba_udc(gadget); | ||
1014 | unsigned long flags; | ||
1015 | |||
1016 | spin_lock_irqsave(&udc->lock, flags); | ||
1017 | if (is_selfpowered) | ||
1018 | udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; | ||
1019 | else | ||
1020 | udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); | ||
1021 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static const struct usb_gadget_ops usba_udc_ops = { | ||
1027 | .get_frame = usba_udc_get_frame, | ||
1028 | .wakeup = usba_udc_wakeup, | ||
1029 | .set_selfpowered = usba_udc_set_selfpowered, | ||
1030 | }; | ||
1031 | |||
1032 | #define EP(nam, idx, maxpkt, maxbk, dma, isoc) \ | ||
1033 | { \ | ||
1034 | .ep = { \ | ||
1035 | .ops = &usba_ep_ops, \ | ||
1036 | .name = nam, \ | ||
1037 | .maxpacket = maxpkt, \ | ||
1038 | }, \ | ||
1039 | .udc = &the_udc, \ | ||
1040 | .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \ | ||
1041 | .fifo_size = maxpkt, \ | ||
1042 | .nr_banks = maxbk, \ | ||
1043 | .index = idx, \ | ||
1044 | .can_dma = dma, \ | ||
1045 | .can_isoc = isoc, \ | ||
1046 | } | ||
1047 | |||
1048 | static struct usba_ep usba_ep[] = { | ||
1049 | EP("ep0", 0, 64, 1, 0, 0), | ||
1050 | EP("ep1in-bulk", 1, 512, 2, 1, 1), | ||
1051 | EP("ep2out-bulk", 2, 512, 2, 1, 1), | ||
1052 | EP("ep3in-int", 3, 64, 3, 1, 0), | ||
1053 | EP("ep4out-int", 4, 64, 3, 1, 0), | ||
1054 | EP("ep5in-iso", 5, 1024, 3, 1, 1), | ||
1055 | EP("ep6out-iso", 6, 1024, 3, 1, 1), | ||
1056 | }; | ||
1057 | #undef EP | ||
1058 | |||
1059 | static struct usb_endpoint_descriptor usba_ep0_desc = { | ||
1060 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
1061 | .bDescriptorType = USB_DT_ENDPOINT, | ||
1062 | .bEndpointAddress = 0, | ||
1063 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
1064 | .wMaxPacketSize = __constant_cpu_to_le16(64), | ||
1065 | /* FIXME: I have no idea what to put here */ | ||
1066 | .bInterval = 1, | ||
1067 | }; | ||
1068 | |||
1069 | static void nop_release(struct device *dev) | ||
1070 | { | ||
1071 | |||
1072 | } | ||
1073 | |||
1074 | static struct usba_udc the_udc = { | ||
1075 | .gadget = { | ||
1076 | .ops = &usba_udc_ops, | ||
1077 | .ep0 = &usba_ep[0].ep, | ||
1078 | .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list), | ||
1079 | .is_dualspeed = 1, | ||
1080 | .name = "atmel_usba_udc", | ||
1081 | .dev = { | ||
1082 | .bus_id = "gadget", | ||
1083 | .release = nop_release, | ||
1084 | }, | ||
1085 | }, | ||
1086 | |||
1087 | .lock = SPIN_LOCK_UNLOCKED, | ||
1088 | }; | ||
1089 | |||
1090 | /* | ||
1091 | * Called with interrupts disabled and udc->lock held. | ||
1092 | */ | ||
1093 | static void reset_all_endpoints(struct usba_udc *udc) | ||
1094 | { | ||
1095 | struct usba_ep *ep; | ||
1096 | struct usba_request *req, *tmp_req; | ||
1097 | |||
1098 | usba_writel(udc, EPT_RST, ~0UL); | ||
1099 | |||
1100 | ep = to_usba_ep(udc->gadget.ep0); | ||
1101 | list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) { | ||
1102 | list_del_init(&req->queue); | ||
1103 | request_complete(ep, req, -ECONNRESET); | ||
1104 | } | ||
1105 | |||
1106 | list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { | ||
1107 | if (ep->desc) { | ||
1108 | spin_unlock(&udc->lock); | ||
1109 | usba_ep_disable(&ep->ep); | ||
1110 | spin_lock(&udc->lock); | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex) | ||
1116 | { | ||
1117 | struct usba_ep *ep; | ||
1118 | |||
1119 | if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) | ||
1120 | return to_usba_ep(udc->gadget.ep0); | ||
1121 | |||
1122 | list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { | ||
1123 | u8 bEndpointAddress; | ||
1124 | |||
1125 | if (!ep->desc) | ||
1126 | continue; | ||
1127 | bEndpointAddress = ep->desc->bEndpointAddress; | ||
1128 | if ((wIndex ^ bEndpointAddress) & USB_DIR_IN) | ||
1129 | continue; | ||
1130 | if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) | ||
1131 | == (wIndex & USB_ENDPOINT_NUMBER_MASK)) | ||
1132 | return ep; | ||
1133 | } | ||
1134 | |||
1135 | return NULL; | ||
1136 | } | ||
1137 | |||
1138 | /* Called with interrupts disabled and udc->lock held */ | ||
1139 | static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep) | ||
1140 | { | ||
1141 | usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL); | ||
1142 | ep->state = WAIT_FOR_SETUP; | ||
1143 | } | ||
1144 | |||
1145 | static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep) | ||
1146 | { | ||
1147 | if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL) | ||
1148 | return 1; | ||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | static inline void set_address(struct usba_udc *udc, unsigned int addr) | ||
1153 | { | ||
1154 | u32 regval; | ||
1155 | |||
1156 | DBG(DBG_BUS, "setting address %u...\n", addr); | ||
1157 | regval = usba_readl(udc, CTRL); | ||
1158 | regval = USBA_BFINS(DEV_ADDR, addr, regval); | ||
1159 | usba_writel(udc, CTRL, regval); | ||
1160 | } | ||
1161 | |||
1162 | static int do_test_mode(struct usba_udc *udc) | ||
1163 | { | ||
1164 | static const char test_packet_buffer[] = { | ||
1165 | /* JKJKJKJK * 9 */ | ||
1166 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1167 | /* JJKKJJKK * 8 */ | ||
1168 | 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, | ||
1169 | /* JJKKJJKK * 8 */ | ||
1170 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, | ||
1171 | /* JJJJJJJKKKKKKK * 8 */ | ||
1172 | 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
1173 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
1174 | /* JJJJJJJK * 8 */ | ||
1175 | 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, | ||
1176 | /* {JKKKKKKK * 10}, JK */ | ||
1177 | 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E | ||
1178 | }; | ||
1179 | struct usba_ep *ep; | ||
1180 | struct device *dev = &udc->pdev->dev; | ||
1181 | int test_mode; | ||
1182 | |||
1183 | test_mode = udc->test_mode; | ||
1184 | |||
1185 | /* Start from a clean slate */ | ||
1186 | reset_all_endpoints(udc); | ||
1187 | |||
1188 | switch (test_mode) { | ||
1189 | case 0x0100: | ||
1190 | /* Test_J */ | ||
1191 | usba_writel(udc, TST, USBA_TST_J_MODE); | ||
1192 | dev_info(dev, "Entering Test_J mode...\n"); | ||
1193 | break; | ||
1194 | case 0x0200: | ||
1195 | /* Test_K */ | ||
1196 | usba_writel(udc, TST, USBA_TST_K_MODE); | ||
1197 | dev_info(dev, "Entering Test_K mode...\n"); | ||
1198 | break; | ||
1199 | case 0x0300: | ||
1200 | /* | ||
1201 | * Test_SE0_NAK: Force high-speed mode and set up ep0 | ||
1202 | * for Bulk IN transfers | ||
1203 | */ | ||
1204 | ep = &usba_ep[0]; | ||
1205 | usba_writel(udc, TST, | ||
1206 | USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH)); | ||
1207 | usba_ep_writel(ep, CFG, | ||
1208 | USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64) | ||
1209 | | USBA_EPT_DIR_IN | ||
1210 | | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK) | ||
1211 | | USBA_BF(BK_NUMBER, 1)); | ||
1212 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) { | ||
1213 | set_protocol_stall(udc, ep); | ||
1214 | dev_err(dev, "Test_SE0_NAK: ep0 not mapped\n"); | ||
1215 | } else { | ||
1216 | usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); | ||
1217 | dev_info(dev, "Entering Test_SE0_NAK mode...\n"); | ||
1218 | } | ||
1219 | break; | ||
1220 | case 0x0400: | ||
1221 | /* Test_Packet */ | ||
1222 | ep = &usba_ep[0]; | ||
1223 | usba_ep_writel(ep, CFG, | ||
1224 | USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64) | ||
1225 | | USBA_EPT_DIR_IN | ||
1226 | | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK) | ||
1227 | | USBA_BF(BK_NUMBER, 1)); | ||
1228 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) { | ||
1229 | set_protocol_stall(udc, ep); | ||
1230 | dev_err(dev, "Test_Packet: ep0 not mapped\n"); | ||
1231 | } else { | ||
1232 | usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE); | ||
1233 | usba_writel(udc, TST, USBA_TST_PKT_MODE); | ||
1234 | copy_to_fifo(ep->fifo, test_packet_buffer, | ||
1235 | sizeof(test_packet_buffer)); | ||
1236 | usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); | ||
1237 | dev_info(dev, "Entering Test_Packet mode...\n"); | ||
1238 | } | ||
1239 | break; | ||
1240 | default: | ||
1241 | dev_err(dev, "Invalid test mode: 0x%04x\n", test_mode); | ||
1242 | return -EINVAL; | ||
1243 | } | ||
1244 | |||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1248 | /* Avoid overly long expressions */ | ||
1249 | static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq) | ||
1250 | { | ||
1251 | if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) | ||
1252 | return true; | ||
1253 | return false; | ||
1254 | } | ||
1255 | |||
1256 | static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq) | ||
1257 | { | ||
1258 | if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE)) | ||
1259 | return true; | ||
1260 | return false; | ||
1261 | } | ||
1262 | |||
1263 | static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) | ||
1264 | { | ||
1265 | if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT)) | ||
1266 | return true; | ||
1267 | return false; | ||
1268 | } | ||
1269 | |||
1270 | static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, | ||
1271 | struct usb_ctrlrequest *crq) | ||
1272 | { | ||
1273 | int retval = 0;; | ||
1274 | |||
1275 | switch (crq->bRequest) { | ||
1276 | case USB_REQ_GET_STATUS: { | ||
1277 | u16 status; | ||
1278 | |||
1279 | if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) { | ||
1280 | status = cpu_to_le16(udc->devstatus); | ||
1281 | } else if (crq->bRequestType | ||
1282 | == (USB_DIR_IN | USB_RECIP_INTERFACE)) { | ||
1283 | status = __constant_cpu_to_le16(0); | ||
1284 | } else if (crq->bRequestType | ||
1285 | == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { | ||
1286 | struct usba_ep *target; | ||
1287 | |||
1288 | target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); | ||
1289 | if (!target) | ||
1290 | goto stall; | ||
1291 | |||
1292 | status = 0; | ||
1293 | if (is_stalled(udc, target)) | ||
1294 | status |= __constant_cpu_to_le16(1); | ||
1295 | } else | ||
1296 | goto delegate; | ||
1297 | |||
1298 | /* Write directly to the FIFO. No queueing is done. */ | ||
1299 | if (crq->wLength != __constant_cpu_to_le16(sizeof(status))) | ||
1300 | goto stall; | ||
1301 | ep->state = DATA_STAGE_IN; | ||
1302 | __raw_writew(status, ep->fifo); | ||
1303 | usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY); | ||
1304 | break; | ||
1305 | } | ||
1306 | |||
1307 | case USB_REQ_CLEAR_FEATURE: { | ||
1308 | if (crq->bRequestType == USB_RECIP_DEVICE) { | ||
1309 | if (feature_is_dev_remote_wakeup(crq)) | ||
1310 | udc->devstatus | ||
1311 | &= ~(1 << USB_DEVICE_REMOTE_WAKEUP); | ||
1312 | else | ||
1313 | /* Can't CLEAR_FEATURE TEST_MODE */ | ||
1314 | goto stall; | ||
1315 | } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { | ||
1316 | struct usba_ep *target; | ||
1317 | |||
1318 | if (crq->wLength != __constant_cpu_to_le16(0) | ||
1319 | || !feature_is_ep_halt(crq)) | ||
1320 | goto stall; | ||
1321 | target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); | ||
1322 | if (!target) | ||
1323 | goto stall; | ||
1324 | |||
1325 | usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL); | ||
1326 | if (target->index != 0) | ||
1327 | usba_ep_writel(target, CLR_STA, | ||
1328 | USBA_TOGGLE_CLR); | ||
1329 | } else { | ||
1330 | goto delegate; | ||
1331 | } | ||
1332 | |||
1333 | send_status(udc, ep); | ||
1334 | break; | ||
1335 | } | ||
1336 | |||
1337 | case USB_REQ_SET_FEATURE: { | ||
1338 | if (crq->bRequestType == USB_RECIP_DEVICE) { | ||
1339 | if (feature_is_dev_test_mode(crq)) { | ||
1340 | send_status(udc, ep); | ||
1341 | ep->state = STATUS_STAGE_TEST; | ||
1342 | udc->test_mode = le16_to_cpu(crq->wIndex); | ||
1343 | return 0; | ||
1344 | } else if (feature_is_dev_remote_wakeup(crq)) { | ||
1345 | udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP; | ||
1346 | } else { | ||
1347 | goto stall; | ||
1348 | } | ||
1349 | } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { | ||
1350 | struct usba_ep *target; | ||
1351 | |||
1352 | if (crq->wLength != __constant_cpu_to_le16(0) | ||
1353 | || !feature_is_ep_halt(crq)) | ||
1354 | goto stall; | ||
1355 | |||
1356 | target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); | ||
1357 | if (!target) | ||
1358 | goto stall; | ||
1359 | |||
1360 | usba_ep_writel(target, SET_STA, USBA_FORCE_STALL); | ||
1361 | } else | ||
1362 | goto delegate; | ||
1363 | |||
1364 | send_status(udc, ep); | ||
1365 | break; | ||
1366 | } | ||
1367 | |||
1368 | case USB_REQ_SET_ADDRESS: | ||
1369 | if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE)) | ||
1370 | goto delegate; | ||
1371 | |||
1372 | set_address(udc, le16_to_cpu(crq->wValue)); | ||
1373 | send_status(udc, ep); | ||
1374 | ep->state = STATUS_STAGE_ADDR; | ||
1375 | break; | ||
1376 | |||
1377 | default: | ||
1378 | delegate: | ||
1379 | spin_unlock(&udc->lock); | ||
1380 | retval = udc->driver->setup(&udc->gadget, crq); | ||
1381 | spin_lock(&udc->lock); | ||
1382 | } | ||
1383 | |||
1384 | return retval; | ||
1385 | |||
1386 | stall: | ||
1387 | printk(KERN_ERR | ||
1388 | "udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, " | ||
1389 | "halting endpoint...\n", | ||
1390 | ep->ep.name, crq->bRequestType, crq->bRequest, | ||
1391 | le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex), | ||
1392 | le16_to_cpu(crq->wLength)); | ||
1393 | set_protocol_stall(udc, ep); | ||
1394 | return -1; | ||
1395 | } | ||
1396 | |||
1397 | static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep) | ||
1398 | { | ||
1399 | struct usba_request *req; | ||
1400 | u32 epstatus; | ||
1401 | u32 epctrl; | ||
1402 | |||
1403 | restart: | ||
1404 | epstatus = usba_ep_readl(ep, STA); | ||
1405 | epctrl = usba_ep_readl(ep, CTL); | ||
1406 | |||
1407 | DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n", | ||
1408 | ep->ep.name, ep->state, epstatus, epctrl); | ||
1409 | |||
1410 | req = NULL; | ||
1411 | if (!list_empty(&ep->queue)) | ||
1412 | req = list_entry(ep->queue.next, | ||
1413 | struct usba_request, queue); | ||
1414 | |||
1415 | if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) { | ||
1416 | if (req->submitted) | ||
1417 | next_fifo_transaction(ep, req); | ||
1418 | else | ||
1419 | submit_request(ep, req); | ||
1420 | |||
1421 | if (req->last_transaction) { | ||
1422 | usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); | ||
1423 | usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); | ||
1424 | } | ||
1425 | goto restart; | ||
1426 | } | ||
1427 | if ((epstatus & epctrl) & USBA_TX_COMPLETE) { | ||
1428 | usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE); | ||
1429 | |||
1430 | switch (ep->state) { | ||
1431 | case DATA_STAGE_IN: | ||
1432 | usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY); | ||
1433 | usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); | ||
1434 | ep->state = STATUS_STAGE_OUT; | ||
1435 | break; | ||
1436 | case STATUS_STAGE_ADDR: | ||
1437 | /* Activate our new address */ | ||
1438 | usba_writel(udc, CTRL, (usba_readl(udc, CTRL) | ||
1439 | | USBA_FADDR_EN)); | ||
1440 | usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); | ||
1441 | ep->state = WAIT_FOR_SETUP; | ||
1442 | break; | ||
1443 | case STATUS_STAGE_IN: | ||
1444 | if (req) { | ||
1445 | list_del_init(&req->queue); | ||
1446 | request_complete(ep, req, 0); | ||
1447 | submit_next_request(ep); | ||
1448 | } | ||
1449 | usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); | ||
1450 | ep->state = WAIT_FOR_SETUP; | ||
1451 | break; | ||
1452 | case STATUS_STAGE_TEST: | ||
1453 | usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); | ||
1454 | ep->state = WAIT_FOR_SETUP; | ||
1455 | if (do_test_mode(udc)) | ||
1456 | set_protocol_stall(udc, ep); | ||
1457 | break; | ||
1458 | default: | ||
1459 | printk(KERN_ERR | ||
1460 | "udc: %s: TXCOMP: Invalid endpoint state %d, " | ||
1461 | "halting endpoint...\n", | ||
1462 | ep->ep.name, ep->state); | ||
1463 | set_protocol_stall(udc, ep); | ||
1464 | break; | ||
1465 | } | ||
1466 | |||
1467 | goto restart; | ||
1468 | } | ||
1469 | if ((epstatus & epctrl) & USBA_RX_BK_RDY) { | ||
1470 | switch (ep->state) { | ||
1471 | case STATUS_STAGE_OUT: | ||
1472 | usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); | ||
1473 | usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); | ||
1474 | |||
1475 | if (req) { | ||
1476 | list_del_init(&req->queue); | ||
1477 | request_complete(ep, req, 0); | ||
1478 | } | ||
1479 | ep->state = WAIT_FOR_SETUP; | ||
1480 | break; | ||
1481 | |||
1482 | case DATA_STAGE_OUT: | ||
1483 | receive_data(ep); | ||
1484 | break; | ||
1485 | |||
1486 | default: | ||
1487 | usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); | ||
1488 | usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); | ||
1489 | printk(KERN_ERR | ||
1490 | "udc: %s: RXRDY: Invalid endpoint state %d, " | ||
1491 | "halting endpoint...\n", | ||
1492 | ep->ep.name, ep->state); | ||
1493 | set_protocol_stall(udc, ep); | ||
1494 | break; | ||
1495 | } | ||
1496 | |||
1497 | goto restart; | ||
1498 | } | ||
1499 | if (epstatus & USBA_RX_SETUP) { | ||
1500 | union { | ||
1501 | struct usb_ctrlrequest crq; | ||
1502 | unsigned long data[2]; | ||
1503 | } crq; | ||
1504 | unsigned int pkt_len; | ||
1505 | int ret; | ||
1506 | |||
1507 | if (ep->state != WAIT_FOR_SETUP) { | ||
1508 | /* | ||
1509 | * Didn't expect a SETUP packet at this | ||
1510 | * point. Clean up any pending requests (which | ||
1511 | * may be successful). | ||
1512 | */ | ||
1513 | int status = -EPROTO; | ||
1514 | |||
1515 | /* | ||
1516 | * RXRDY and TXCOMP are dropped when SETUP | ||
1517 | * packets arrive. Just pretend we received | ||
1518 | * the status packet. | ||
1519 | */ | ||
1520 | if (ep->state == STATUS_STAGE_OUT | ||
1521 | || ep->state == STATUS_STAGE_IN) { | ||
1522 | usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY); | ||
1523 | status = 0; | ||
1524 | } | ||
1525 | |||
1526 | if (req) { | ||
1527 | list_del_init(&req->queue); | ||
1528 | request_complete(ep, req, status); | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA)); | ||
1533 | DBG(DBG_HW, "Packet length: %u\n", pkt_len); | ||
1534 | if (pkt_len != sizeof(crq)) { | ||
1535 | printk(KERN_WARNING "udc: Invalid packet length %u " | ||
1536 | "(expected %lu)\n", pkt_len, sizeof(crq)); | ||
1537 | set_protocol_stall(udc, ep); | ||
1538 | return; | ||
1539 | } | ||
1540 | |||
1541 | DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo); | ||
1542 | copy_from_fifo(crq.data, ep->fifo, sizeof(crq)); | ||
1543 | |||
1544 | /* Free up one bank in the FIFO so that we can | ||
1545 | * generate or receive a reply right away. */ | ||
1546 | usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP); | ||
1547 | |||
1548 | /* printk(KERN_DEBUG "setup: %d: %02x.%02x\n", | ||
1549 | ep->state, crq.crq.bRequestType, | ||
1550 | crq.crq.bRequest); */ | ||
1551 | |||
1552 | if (crq.crq.bRequestType & USB_DIR_IN) { | ||
1553 | /* | ||
1554 | * The USB 2.0 spec states that "if wLength is | ||
1555 | * zero, there is no data transfer phase." | ||
1556 | * However, testusb #14 seems to actually | ||
1557 | * expect a data phase even if wLength = 0... | ||
1558 | */ | ||
1559 | ep->state = DATA_STAGE_IN; | ||
1560 | } else { | ||
1561 | if (crq.crq.wLength != __constant_cpu_to_le16(0)) | ||
1562 | ep->state = DATA_STAGE_OUT; | ||
1563 | else | ||
1564 | ep->state = STATUS_STAGE_IN; | ||
1565 | } | ||
1566 | |||
1567 | ret = -1; | ||
1568 | if (ep->index == 0) | ||
1569 | ret = handle_ep0_setup(udc, ep, &crq.crq); | ||
1570 | else { | ||
1571 | spin_unlock(&udc->lock); | ||
1572 | ret = udc->driver->setup(&udc->gadget, &crq.crq); | ||
1573 | spin_lock(&udc->lock); | ||
1574 | } | ||
1575 | |||
1576 | DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n", | ||
1577 | crq.crq.bRequestType, crq.crq.bRequest, | ||
1578 | le16_to_cpu(crq.crq.wLength), ep->state, ret); | ||
1579 | |||
1580 | if (ret < 0) { | ||
1581 | /* Let the host know that we failed */ | ||
1582 | set_protocol_stall(udc, ep); | ||
1583 | } | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep) | ||
1588 | { | ||
1589 | struct usba_request *req; | ||
1590 | u32 epstatus; | ||
1591 | u32 epctrl; | ||
1592 | |||
1593 | epstatus = usba_ep_readl(ep, STA); | ||
1594 | epctrl = usba_ep_readl(ep, CTL); | ||
1595 | |||
1596 | DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus); | ||
1597 | |||
1598 | while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) { | ||
1599 | DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name); | ||
1600 | |||
1601 | if (list_empty(&ep->queue)) { | ||
1602 | dev_warn(&udc->pdev->dev, "ep_irq: queue empty\n"); | ||
1603 | usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); | ||
1604 | return; | ||
1605 | } | ||
1606 | |||
1607 | req = list_entry(ep->queue.next, struct usba_request, queue); | ||
1608 | |||
1609 | if (req->using_dma) { | ||
1610 | /* Send a zero-length packet */ | ||
1611 | usba_ep_writel(ep, SET_STA, | ||
1612 | USBA_TX_PK_RDY); | ||
1613 | usba_ep_writel(ep, CTL_DIS, | ||
1614 | USBA_TX_PK_RDY); | ||
1615 | list_del_init(&req->queue); | ||
1616 | submit_next_request(ep); | ||
1617 | request_complete(ep, req, 0); | ||
1618 | } else { | ||
1619 | if (req->submitted) | ||
1620 | next_fifo_transaction(ep, req); | ||
1621 | else | ||
1622 | submit_request(ep, req); | ||
1623 | |||
1624 | if (req->last_transaction) { | ||
1625 | list_del_init(&req->queue); | ||
1626 | submit_next_request(ep); | ||
1627 | request_complete(ep, req, 0); | ||
1628 | } | ||
1629 | } | ||
1630 | |||
1631 | epstatus = usba_ep_readl(ep, STA); | ||
1632 | epctrl = usba_ep_readl(ep, CTL); | ||
1633 | } | ||
1634 | if ((epstatus & epctrl) & USBA_RX_BK_RDY) { | ||
1635 | DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name); | ||
1636 | receive_data(ep); | ||
1637 | usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY); | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep) | ||
1642 | { | ||
1643 | struct usba_request *req; | ||
1644 | u32 status, control, pending; | ||
1645 | |||
1646 | status = usba_dma_readl(ep, STATUS); | ||
1647 | control = usba_dma_readl(ep, CONTROL); | ||
1648 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | ||
1649 | ep->last_dma_status = status; | ||
1650 | #endif | ||
1651 | pending = status & control; | ||
1652 | DBG(DBG_INT | DBG_DMA, "dma irq, s/%#08x, c/%#08x\n", status, control); | ||
1653 | |||
1654 | if (status & USBA_DMA_CH_EN) { | ||
1655 | dev_err(&udc->pdev->dev, | ||
1656 | "DMA_CH_EN is set after transfer is finished!\n"); | ||
1657 | dev_err(&udc->pdev->dev, | ||
1658 | "status=%#08x, pending=%#08x, control=%#08x\n", | ||
1659 | status, pending, control); | ||
1660 | |||
1661 | /* | ||
1662 | * try to pretend nothing happened. We might have to | ||
1663 | * do something here... | ||
1664 | */ | ||
1665 | } | ||
1666 | |||
1667 | if (list_empty(&ep->queue)) | ||
1668 | /* Might happen if a reset comes along at the right moment */ | ||
1669 | return; | ||
1670 | |||
1671 | if (pending & (USBA_DMA_END_TR_ST | USBA_DMA_END_BUF_ST)) { | ||
1672 | req = list_entry(ep->queue.next, struct usba_request, queue); | ||
1673 | usba_update_req(ep, req, status); | ||
1674 | |||
1675 | list_del_init(&req->queue); | ||
1676 | submit_next_request(ep); | ||
1677 | request_complete(ep, req, 0); | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | static irqreturn_t usba_udc_irq(int irq, void *devid) | ||
1682 | { | ||
1683 | struct usba_udc *udc = devid; | ||
1684 | u32 status; | ||
1685 | u32 dma_status; | ||
1686 | u32 ep_status; | ||
1687 | |||
1688 | spin_lock(&udc->lock); | ||
1689 | |||
1690 | status = usba_readl(udc, INT_STA); | ||
1691 | DBG(DBG_INT, "irq, status=%#08x\n", status); | ||
1692 | |||
1693 | if (status & USBA_DET_SUSPEND) { | ||
1694 | usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); | ||
1695 | DBG(DBG_BUS, "Suspend detected\n"); | ||
1696 | if (udc->gadget.speed != USB_SPEED_UNKNOWN | ||
1697 | && udc->driver && udc->driver->suspend) { | ||
1698 | spin_unlock(&udc->lock); | ||
1699 | udc->driver->suspend(&udc->gadget); | ||
1700 | spin_lock(&udc->lock); | ||
1701 | } | ||
1702 | } | ||
1703 | |||
1704 | if (status & USBA_WAKE_UP) { | ||
1705 | usba_writel(udc, INT_CLR, USBA_WAKE_UP); | ||
1706 | DBG(DBG_BUS, "Wake Up CPU detected\n"); | ||
1707 | } | ||
1708 | |||
1709 | if (status & USBA_END_OF_RESUME) { | ||
1710 | usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); | ||
1711 | DBG(DBG_BUS, "Resume detected\n"); | ||
1712 | if (udc->gadget.speed != USB_SPEED_UNKNOWN | ||
1713 | && udc->driver && udc->driver->resume) { | ||
1714 | spin_unlock(&udc->lock); | ||
1715 | udc->driver->resume(&udc->gadget); | ||
1716 | spin_lock(&udc->lock); | ||
1717 | } | ||
1718 | } | ||
1719 | |||
1720 | dma_status = USBA_BFEXT(DMA_INT, status); | ||
1721 | if (dma_status) { | ||
1722 | int i; | ||
1723 | |||
1724 | for (i = 1; i < USBA_NR_ENDPOINTS; i++) | ||
1725 | if (dma_status & (1 << i)) | ||
1726 | usba_dma_irq(udc, &usba_ep[i]); | ||
1727 | } | ||
1728 | |||
1729 | ep_status = USBA_BFEXT(EPT_INT, status); | ||
1730 | if (ep_status) { | ||
1731 | int i; | ||
1732 | |||
1733 | for (i = 0; i < USBA_NR_ENDPOINTS; i++) | ||
1734 | if (ep_status & (1 << i)) { | ||
1735 | if (ep_is_control(&usba_ep[i])) | ||
1736 | usba_control_irq(udc, &usba_ep[i]); | ||
1737 | else | ||
1738 | usba_ep_irq(udc, &usba_ep[i]); | ||
1739 | } | ||
1740 | } | ||
1741 | |||
1742 | if (status & USBA_END_OF_RESET) { | ||
1743 | struct usba_ep *ep0; | ||
1744 | |||
1745 | usba_writel(udc, INT_CLR, USBA_END_OF_RESET); | ||
1746 | reset_all_endpoints(udc); | ||
1747 | |||
1748 | if (status & USBA_HIGH_SPEED) { | ||
1749 | DBG(DBG_BUS, "High-speed bus reset detected\n"); | ||
1750 | udc->gadget.speed = USB_SPEED_HIGH; | ||
1751 | } else { | ||
1752 | DBG(DBG_BUS, "Full-speed bus reset detected\n"); | ||
1753 | udc->gadget.speed = USB_SPEED_FULL; | ||
1754 | } | ||
1755 | |||
1756 | ep0 = &usba_ep[0]; | ||
1757 | ep0->desc = &usba_ep0_desc; | ||
1758 | ep0->state = WAIT_FOR_SETUP; | ||
1759 | usba_ep_writel(ep0, CFG, | ||
1760 | (USBA_BF(EPT_SIZE, EP0_EPT_SIZE) | ||
1761 | | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL) | ||
1762 | | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE))); | ||
1763 | usba_ep_writel(ep0, CTL_ENB, | ||
1764 | USBA_EPT_ENABLE | USBA_RX_SETUP); | ||
1765 | usba_writel(udc, INT_ENB, | ||
1766 | (usba_readl(udc, INT_ENB) | ||
1767 | | USBA_BF(EPT_INT, 1) | ||
1768 | | USBA_DET_SUSPEND | ||
1769 | | USBA_END_OF_RESUME)); | ||
1770 | |||
1771 | if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) | ||
1772 | dev_warn(&udc->pdev->dev, | ||
1773 | "WARNING: EP0 configuration is invalid!\n"); | ||
1774 | } | ||
1775 | |||
1776 | spin_unlock(&udc->lock); | ||
1777 | |||
1778 | return IRQ_HANDLED; | ||
1779 | } | ||
1780 | |||
1781 | static irqreturn_t usba_vbus_irq(int irq, void *devid) | ||
1782 | { | ||
1783 | struct usba_udc *udc = devid; | ||
1784 | int vbus; | ||
1785 | |||
1786 | /* debounce */ | ||
1787 | udelay(10); | ||
1788 | |||
1789 | spin_lock(&udc->lock); | ||
1790 | |||
1791 | /* May happen if Vbus pin toggles during probe() */ | ||
1792 | if (!udc->driver) | ||
1793 | goto out; | ||
1794 | |||
1795 | vbus = gpio_get_value(udc->vbus_pin); | ||
1796 | if (vbus != udc->vbus_prev) { | ||
1797 | if (vbus) { | ||
1798 | usba_writel(udc, CTRL, USBA_EN_USBA); | ||
1799 | usba_writel(udc, INT_ENB, USBA_END_OF_RESET); | ||
1800 | } else { | ||
1801 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1802 | reset_all_endpoints(udc); | ||
1803 | usba_writel(udc, CTRL, 0); | ||
1804 | spin_unlock(&udc->lock); | ||
1805 | udc->driver->disconnect(&udc->gadget); | ||
1806 | spin_lock(&udc->lock); | ||
1807 | } | ||
1808 | udc->vbus_prev = vbus; | ||
1809 | } | ||
1810 | |||
1811 | out: | ||
1812 | spin_unlock(&udc->lock); | ||
1813 | |||
1814 | return IRQ_HANDLED; | ||
1815 | } | ||
1816 | |||
1817 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
1818 | { | ||
1819 | struct usba_udc *udc = &the_udc; | ||
1820 | unsigned long flags; | ||
1821 | int ret; | ||
1822 | |||
1823 | if (!udc->pdev) | ||
1824 | return -ENODEV; | ||
1825 | |||
1826 | spin_lock_irqsave(&udc->lock, flags); | ||
1827 | if (udc->driver) { | ||
1828 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1829 | return -EBUSY; | ||
1830 | } | ||
1831 | |||
1832 | udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; | ||
1833 | udc->driver = driver; | ||
1834 | udc->gadget.dev.driver = &driver->driver; | ||
1835 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1836 | |||
1837 | clk_enable(udc->pclk); | ||
1838 | clk_enable(udc->hclk); | ||
1839 | |||
1840 | ret = driver->bind(&udc->gadget); | ||
1841 | if (ret) { | ||
1842 | DBG(DBG_ERR, "Could not bind to driver %s: error %d\n", | ||
1843 | driver->driver.name, ret); | ||
1844 | goto err_driver_bind; | ||
1845 | } | ||
1846 | |||
1847 | DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); | ||
1848 | |||
1849 | udc->vbus_prev = 0; | ||
1850 | if (udc->vbus_pin != -1) | ||
1851 | enable_irq(gpio_to_irq(udc->vbus_pin)); | ||
1852 | |||
1853 | /* If Vbus is present, enable the controller and wait for reset */ | ||
1854 | spin_lock_irqsave(&udc->lock, flags); | ||
1855 | if (vbus_is_present(udc) && udc->vbus_prev == 0) { | ||
1856 | usba_writel(udc, CTRL, USBA_EN_USBA); | ||
1857 | usba_writel(udc, INT_ENB, USBA_END_OF_RESET); | ||
1858 | } | ||
1859 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1860 | |||
1861 | return 0; | ||
1862 | |||
1863 | err_driver_bind: | ||
1864 | udc->driver = NULL; | ||
1865 | udc->gadget.dev.driver = NULL; | ||
1866 | return ret; | ||
1867 | } | ||
1868 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
1869 | |||
1870 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1871 | { | ||
1872 | struct usba_udc *udc = &the_udc; | ||
1873 | unsigned long flags; | ||
1874 | |||
1875 | if (!udc->pdev) | ||
1876 | return -ENODEV; | ||
1877 | if (driver != udc->driver) | ||
1878 | return -EINVAL; | ||
1879 | |||
1880 | if (udc->vbus_pin != -1) | ||
1881 | disable_irq(gpio_to_irq(udc->vbus_pin)); | ||
1882 | |||
1883 | spin_lock_irqsave(&udc->lock, flags); | ||
1884 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
1885 | reset_all_endpoints(udc); | ||
1886 | spin_unlock_irqrestore(&udc->lock, flags); | ||
1887 | |||
1888 | /* This will also disable the DP pullup */ | ||
1889 | usba_writel(udc, CTRL, 0); | ||
1890 | |||
1891 | driver->unbind(&udc->gadget); | ||
1892 | udc->gadget.dev.driver = NULL; | ||
1893 | udc->driver = NULL; | ||
1894 | |||
1895 | clk_disable(udc->hclk); | ||
1896 | clk_disable(udc->pclk); | ||
1897 | |||
1898 | DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name); | ||
1899 | |||
1900 | return 0; | ||
1901 | } | ||
1902 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1903 | |||
1904 | static int __init usba_udc_probe(struct platform_device *pdev) | ||
1905 | { | ||
1906 | struct usba_platform_data *pdata = pdev->dev.platform_data; | ||
1907 | struct resource *regs, *fifo; | ||
1908 | struct clk *pclk, *hclk; | ||
1909 | struct usba_udc *udc = &the_udc; | ||
1910 | int irq, ret, i; | ||
1911 | |||
1912 | regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); | ||
1913 | fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); | ||
1914 | if (!regs || !fifo) | ||
1915 | return -ENXIO; | ||
1916 | |||
1917 | irq = platform_get_irq(pdev, 0); | ||
1918 | if (irq < 0) | ||
1919 | return irq; | ||
1920 | |||
1921 | pclk = clk_get(&pdev->dev, "pclk"); | ||
1922 | if (IS_ERR(pclk)) | ||
1923 | return PTR_ERR(pclk); | ||
1924 | hclk = clk_get(&pdev->dev, "hclk"); | ||
1925 | if (IS_ERR(hclk)) { | ||
1926 | ret = PTR_ERR(hclk); | ||
1927 | goto err_get_hclk; | ||
1928 | } | ||
1929 | |||
1930 | udc->pdev = pdev; | ||
1931 | udc->pclk = pclk; | ||
1932 | udc->hclk = hclk; | ||
1933 | udc->vbus_pin = -1; | ||
1934 | |||
1935 | ret = -ENOMEM; | ||
1936 | udc->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
1937 | if (!udc->regs) { | ||
1938 | dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n"); | ||
1939 | goto err_map_regs; | ||
1940 | } | ||
1941 | dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n", | ||
1942 | (unsigned long)regs->start, udc->regs); | ||
1943 | udc->fifo = ioremap(fifo->start, fifo->end - fifo->start + 1); | ||
1944 | if (!udc->fifo) { | ||
1945 | dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n"); | ||
1946 | goto err_map_fifo; | ||
1947 | } | ||
1948 | dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n", | ||
1949 | (unsigned long)fifo->start, udc->fifo); | ||
1950 | |||
1951 | device_initialize(&udc->gadget.dev); | ||
1952 | udc->gadget.dev.parent = &pdev->dev; | ||
1953 | udc->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1954 | |||
1955 | platform_set_drvdata(pdev, udc); | ||
1956 | |||
1957 | /* Make sure we start from a clean slate */ | ||
1958 | clk_enable(pclk); | ||
1959 | usba_writel(udc, CTRL, 0); | ||
1960 | clk_disable(pclk); | ||
1961 | |||
1962 | INIT_LIST_HEAD(&usba_ep[0].ep.ep_list); | ||
1963 | usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0); | ||
1964 | usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0); | ||
1965 | usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0); | ||
1966 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) { | ||
1967 | struct usba_ep *ep = &usba_ep[i]; | ||
1968 | |||
1969 | ep->ep_regs = udc->regs + USBA_EPT_BASE(i); | ||
1970 | ep->dma_regs = udc->regs + USBA_DMA_BASE(i); | ||
1971 | ep->fifo = udc->fifo + USBA_FIFO_BASE(i); | ||
1972 | |||
1973 | list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); | ||
1974 | } | ||
1975 | |||
1976 | ret = request_irq(irq, usba_udc_irq, 0, "atmel_usba_udc", udc); | ||
1977 | if (ret) { | ||
1978 | dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n", | ||
1979 | irq, ret); | ||
1980 | goto err_request_irq; | ||
1981 | } | ||
1982 | udc->irq = irq; | ||
1983 | |||
1984 | ret = device_add(&udc->gadget.dev); | ||
1985 | if (ret) { | ||
1986 | dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret); | ||
1987 | goto err_device_add; | ||
1988 | } | ||
1989 | |||
1990 | if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) { | ||
1991 | if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { | ||
1992 | udc->vbus_pin = pdata->vbus_pin; | ||
1993 | |||
1994 | ret = request_irq(gpio_to_irq(udc->vbus_pin), | ||
1995 | usba_vbus_irq, 0, | ||
1996 | "atmel_usba_udc", udc); | ||
1997 | if (ret) { | ||
1998 | gpio_free(udc->vbus_pin); | ||
1999 | udc->vbus_pin = -1; | ||
2000 | dev_warn(&udc->pdev->dev, | ||
2001 | "failed to request vbus irq; " | ||
2002 | "assuming always on\n"); | ||
2003 | } else { | ||
2004 | disable_irq(gpio_to_irq(udc->vbus_pin)); | ||
2005 | } | ||
2006 | } | ||
2007 | } | ||
2008 | |||
2009 | usba_init_debugfs(udc); | ||
2010 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) | ||
2011 | usba_ep_init_debugfs(udc, &usba_ep[i]); | ||
2012 | |||
2013 | return 0; | ||
2014 | |||
2015 | err_device_add: | ||
2016 | free_irq(irq, udc); | ||
2017 | err_request_irq: | ||
2018 | iounmap(udc->fifo); | ||
2019 | err_map_fifo: | ||
2020 | iounmap(udc->regs); | ||
2021 | err_map_regs: | ||
2022 | clk_put(hclk); | ||
2023 | err_get_hclk: | ||
2024 | clk_put(pclk); | ||
2025 | |||
2026 | platform_set_drvdata(pdev, NULL); | ||
2027 | |||
2028 | return ret; | ||
2029 | } | ||
2030 | |||
2031 | static int __exit usba_udc_remove(struct platform_device *pdev) | ||
2032 | { | ||
2033 | struct usba_udc *udc; | ||
2034 | int i; | ||
2035 | |||
2036 | udc = platform_get_drvdata(pdev); | ||
2037 | |||
2038 | for (i = 1; i < ARRAY_SIZE(usba_ep); i++) | ||
2039 | usba_ep_cleanup_debugfs(&usba_ep[i]); | ||
2040 | usba_cleanup_debugfs(udc); | ||
2041 | |||
2042 | if (udc->vbus_pin != -1) | ||
2043 | gpio_free(udc->vbus_pin); | ||
2044 | |||
2045 | free_irq(udc->irq, udc); | ||
2046 | iounmap(udc->fifo); | ||
2047 | iounmap(udc->regs); | ||
2048 | clk_put(udc->hclk); | ||
2049 | clk_put(udc->pclk); | ||
2050 | |||
2051 | device_unregister(&udc->gadget.dev); | ||
2052 | |||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
2056 | static struct platform_driver udc_driver = { | ||
2057 | .remove = __exit_p(usba_udc_remove), | ||
2058 | .driver = { | ||
2059 | .name = "atmel_usba_udc", | ||
2060 | }, | ||
2061 | }; | ||
2062 | |||
2063 | static int __init udc_init(void) | ||
2064 | { | ||
2065 | return platform_driver_probe(&udc_driver, usba_udc_probe); | ||
2066 | } | ||
2067 | module_init(udc_init); | ||
2068 | |||
2069 | static void __exit udc_exit(void) | ||
2070 | { | ||
2071 | platform_driver_unregister(&udc_driver); | ||
2072 | } | ||
2073 | module_exit(udc_exit); | ||
2074 | |||
2075 | MODULE_DESCRIPTION("Atmel USBA UDC driver"); | ||
2076 | MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); | ||
2077 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h new file mode 100644 index 000000000000..a68304e31a68 --- /dev/null +++ b/drivers/usb/gadget/atmel_usba_udc.h | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * Driver for the Atmel USBA high speed USB device controller | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef __LINUX_USB_GADGET_USBA_UDC_H__ | ||
11 | #define __LINUX_USB_GADGET_USBA_UDC_H__ | ||
12 | |||
13 | /* USB register offsets */ | ||
14 | #define USBA_CTRL 0x0000 | ||
15 | #define USBA_FNUM 0x0004 | ||
16 | #define USBA_INT_ENB 0x0010 | ||
17 | #define USBA_INT_STA 0x0014 | ||
18 | #define USBA_INT_CLR 0x0018 | ||
19 | #define USBA_EPT_RST 0x001c | ||
20 | #define USBA_TST 0x00e0 | ||
21 | |||
22 | /* USB endpoint register offsets */ | ||
23 | #define USBA_EPT_CFG 0x0000 | ||
24 | #define USBA_EPT_CTL_ENB 0x0004 | ||
25 | #define USBA_EPT_CTL_DIS 0x0008 | ||
26 | #define USBA_EPT_CTL 0x000c | ||
27 | #define USBA_EPT_SET_STA 0x0014 | ||
28 | #define USBA_EPT_CLR_STA 0x0018 | ||
29 | #define USBA_EPT_STA 0x001c | ||
30 | |||
31 | /* USB DMA register offsets */ | ||
32 | #define USBA_DMA_NXT_DSC 0x0000 | ||
33 | #define USBA_DMA_ADDRESS 0x0004 | ||
34 | #define USBA_DMA_CONTROL 0x0008 | ||
35 | #define USBA_DMA_STATUS 0x000c | ||
36 | |||
37 | /* Bitfields in CTRL */ | ||
38 | #define USBA_DEV_ADDR_OFFSET 0 | ||
39 | #define USBA_DEV_ADDR_SIZE 7 | ||
40 | #define USBA_FADDR_EN (1 << 7) | ||
41 | #define USBA_EN_USBA (1 << 8) | ||
42 | #define USBA_DETACH (1 << 9) | ||
43 | #define USBA_REMOTE_WAKE_UP (1 << 10) | ||
44 | |||
45 | /* Bitfields in FNUM */ | ||
46 | #define USBA_MICRO_FRAME_NUM_OFFSET 0 | ||
47 | #define USBA_MICRO_FRAME_NUM_SIZE 3 | ||
48 | #define USBA_FRAME_NUMBER_OFFSET 3 | ||
49 | #define USBA_FRAME_NUMBER_SIZE 11 | ||
50 | #define USBA_FRAME_NUM_ERROR (1 << 31) | ||
51 | |||
52 | /* Bitfields in INT_ENB/INT_STA/INT_CLR */ | ||
53 | #define USBA_HIGH_SPEED (1 << 0) | ||
54 | #define USBA_DET_SUSPEND (1 << 1) | ||
55 | #define USBA_MICRO_SOF (1 << 2) | ||
56 | #define USBA_SOF (1 << 3) | ||
57 | #define USBA_END_OF_RESET (1 << 4) | ||
58 | #define USBA_WAKE_UP (1 << 5) | ||
59 | #define USBA_END_OF_RESUME (1 << 6) | ||
60 | #define USBA_UPSTREAM_RESUME (1 << 7) | ||
61 | #define USBA_EPT_INT_OFFSET 8 | ||
62 | #define USBA_EPT_INT_SIZE 16 | ||
63 | #define USBA_DMA_INT_OFFSET 24 | ||
64 | #define USBA_DMA_INT_SIZE 8 | ||
65 | |||
66 | /* Bitfields in EPT_RST */ | ||
67 | #define USBA_RST_OFFSET 0 | ||
68 | #define USBA_RST_SIZE 16 | ||
69 | |||
70 | /* Bitfields in USBA_TST */ | ||
71 | #define USBA_SPEED_CFG_OFFSET 0 | ||
72 | #define USBA_SPEED_CFG_SIZE 2 | ||
73 | #define USBA_TST_J_MODE (1 << 2) | ||
74 | #define USBA_TST_K_MODE (1 << 3) | ||
75 | #define USBA_TST_PKT_MODE (1 << 4) | ||
76 | #define USBA_OPMODE2 (1 << 5) | ||
77 | |||
78 | /* Bitfields in EPT_CFG */ | ||
79 | #define USBA_EPT_SIZE_OFFSET 0 | ||
80 | #define USBA_EPT_SIZE_SIZE 3 | ||
81 | #define USBA_EPT_DIR_IN (1 << 3) | ||
82 | #define USBA_EPT_TYPE_OFFSET 4 | ||
83 | #define USBA_EPT_TYPE_SIZE 2 | ||
84 | #define USBA_BK_NUMBER_OFFSET 6 | ||
85 | #define USBA_BK_NUMBER_SIZE 2 | ||
86 | #define USBA_NB_TRANS_OFFSET 8 | ||
87 | #define USBA_NB_TRANS_SIZE 2 | ||
88 | #define USBA_EPT_MAPPED (1 << 31) | ||
89 | |||
90 | /* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */ | ||
91 | #define USBA_EPT_ENABLE (1 << 0) | ||
92 | #define USBA_AUTO_VALID (1 << 1) | ||
93 | #define USBA_INTDIS_DMA (1 << 3) | ||
94 | #define USBA_NYET_DIS (1 << 4) | ||
95 | #define USBA_DATAX_RX (1 << 6) | ||
96 | #define USBA_MDATA_RX (1 << 7) | ||
97 | /* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */ | ||
98 | #define USBA_BUSY_BANK_IE (1 << 18) | ||
99 | |||
100 | /* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */ | ||
101 | #define USBA_FORCE_STALL (1 << 5) | ||
102 | #define USBA_TOGGLE_CLR (1 << 6) | ||
103 | #define USBA_TOGGLE_SEQ_OFFSET 6 | ||
104 | #define USBA_TOGGLE_SEQ_SIZE 2 | ||
105 | #define USBA_ERR_OVFLW (1 << 8) | ||
106 | #define USBA_RX_BK_RDY (1 << 9) | ||
107 | #define USBA_KILL_BANK (1 << 9) | ||
108 | #define USBA_TX_COMPLETE (1 << 10) | ||
109 | #define USBA_TX_PK_RDY (1 << 11) | ||
110 | #define USBA_ISO_ERR_TRANS (1 << 11) | ||
111 | #define USBA_RX_SETUP (1 << 12) | ||
112 | #define USBA_ISO_ERR_FLOW (1 << 12) | ||
113 | #define USBA_STALL_SENT (1 << 13) | ||
114 | #define USBA_ISO_ERR_CRC (1 << 13) | ||
115 | #define USBA_ISO_ERR_NBTRANS (1 << 13) | ||
116 | #define USBA_NAK_IN (1 << 14) | ||
117 | #define USBA_ISO_ERR_FLUSH (1 << 14) | ||
118 | #define USBA_NAK_OUT (1 << 15) | ||
119 | #define USBA_CURRENT_BANK_OFFSET 16 | ||
120 | #define USBA_CURRENT_BANK_SIZE 2 | ||
121 | #define USBA_BUSY_BANKS_OFFSET 18 | ||
122 | #define USBA_BUSY_BANKS_SIZE 2 | ||
123 | #define USBA_BYTE_COUNT_OFFSET 20 | ||
124 | #define USBA_BYTE_COUNT_SIZE 11 | ||
125 | #define USBA_SHORT_PACKET (1 << 31) | ||
126 | |||
127 | /* Bitfields in DMA_CONTROL */ | ||
128 | #define USBA_DMA_CH_EN (1 << 0) | ||
129 | #define USBA_DMA_LINK (1 << 1) | ||
130 | #define USBA_DMA_END_TR_EN (1 << 2) | ||
131 | #define USBA_DMA_END_BUF_EN (1 << 3) | ||
132 | #define USBA_DMA_END_TR_IE (1 << 4) | ||
133 | #define USBA_DMA_END_BUF_IE (1 << 5) | ||
134 | #define USBA_DMA_DESC_LOAD_IE (1 << 6) | ||
135 | #define USBA_DMA_BURST_LOCK (1 << 7) | ||
136 | #define USBA_DMA_BUF_LEN_OFFSET 16 | ||
137 | #define USBA_DMA_BUF_LEN_SIZE 16 | ||
138 | |||
139 | /* Bitfields in DMA_STATUS */ | ||
140 | #define USBA_DMA_CH_ACTIVE (1 << 1) | ||
141 | #define USBA_DMA_END_TR_ST (1 << 4) | ||
142 | #define USBA_DMA_END_BUF_ST (1 << 5) | ||
143 | #define USBA_DMA_DESC_LOAD_ST (1 << 6) | ||
144 | |||
145 | /* Constants for SPEED_CFG */ | ||
146 | #define USBA_SPEED_CFG_NORMAL 0 | ||
147 | #define USBA_SPEED_CFG_FORCE_HIGH 2 | ||
148 | #define USBA_SPEED_CFG_FORCE_FULL 3 | ||
149 | |||
150 | /* Constants for EPT_SIZE */ | ||
151 | #define USBA_EPT_SIZE_8 0 | ||
152 | #define USBA_EPT_SIZE_16 1 | ||
153 | #define USBA_EPT_SIZE_32 2 | ||
154 | #define USBA_EPT_SIZE_64 3 | ||
155 | #define USBA_EPT_SIZE_128 4 | ||
156 | #define USBA_EPT_SIZE_256 5 | ||
157 | #define USBA_EPT_SIZE_512 6 | ||
158 | #define USBA_EPT_SIZE_1024 7 | ||
159 | |||
160 | /* Constants for EPT_TYPE */ | ||
161 | #define USBA_EPT_TYPE_CONTROL 0 | ||
162 | #define USBA_EPT_TYPE_ISO 1 | ||
163 | #define USBA_EPT_TYPE_BULK 2 | ||
164 | #define USBA_EPT_TYPE_INT 3 | ||
165 | |||
166 | /* Constants for BK_NUMBER */ | ||
167 | #define USBA_BK_NUMBER_ZERO 0 | ||
168 | #define USBA_BK_NUMBER_ONE 1 | ||
169 | #define USBA_BK_NUMBER_DOUBLE 2 | ||
170 | #define USBA_BK_NUMBER_TRIPLE 3 | ||
171 | |||
172 | /* Bit manipulation macros */ | ||
173 | #define USBA_BF(name, value) \ | ||
174 | (((value) & ((1 << USBA_##name##_SIZE) - 1)) \ | ||
175 | << USBA_##name##_OFFSET) | ||
176 | #define USBA_BFEXT(name, value) \ | ||
177 | (((value) >> USBA_##name##_OFFSET) \ | ||
178 | & ((1 << USBA_##name##_SIZE) - 1)) | ||
179 | #define USBA_BFINS(name, value, old) \ | ||
180 | (((old) & ~(((1 << USBA_##name##_SIZE) - 1) \ | ||
181 | << USBA_##name##_OFFSET)) \ | ||
182 | | USBA_BF(name, value)) | ||
183 | |||
184 | /* Register access macros */ | ||
185 | #define usba_readl(udc, reg) \ | ||
186 | __raw_readl((udc)->regs + USBA_##reg) | ||
187 | #define usba_writel(udc, reg, value) \ | ||
188 | __raw_writel((value), (udc)->regs + USBA_##reg) | ||
189 | #define usba_ep_readl(ep, reg) \ | ||
190 | __raw_readl((ep)->ep_regs + USBA_EPT_##reg) | ||
191 | #define usba_ep_writel(ep, reg, value) \ | ||
192 | __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg) | ||
193 | #define usba_dma_readl(ep, reg) \ | ||
194 | __raw_readl((ep)->dma_regs + USBA_DMA_##reg) | ||
195 | #define usba_dma_writel(ep, reg, value) \ | ||
196 | __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg) | ||
197 | |||
198 | /* Calculate base address for a given endpoint or DMA controller */ | ||
199 | #define USBA_EPT_BASE(x) (0x100 + (x) * 0x20) | ||
200 | #define USBA_DMA_BASE(x) (0x300 + (x) * 0x10) | ||
201 | #define USBA_FIFO_BASE(x) ((x) << 16) | ||
202 | |||
203 | /* Synth parameters */ | ||
204 | #define USBA_NR_ENDPOINTS 7 | ||
205 | |||
206 | #define EP0_FIFO_SIZE 64 | ||
207 | #define EP0_EPT_SIZE USBA_EPT_SIZE_64 | ||
208 | #define EP0_NR_BANKS 1 | ||
209 | |||
210 | /* | ||
211 | * REVISIT: Try to eliminate this value. Can we rely on req->mapped to | ||
212 | * provide this information? | ||
213 | */ | ||
214 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | ||
215 | |||
216 | #define FIFO_IOMEM_ID 0 | ||
217 | #define CTRL_IOMEM_ID 1 | ||
218 | |||
219 | #ifdef DEBUG | ||
220 | #define DBG_ERR 0x0001 /* report all error returns */ | ||
221 | #define DBG_HW 0x0002 /* debug hardware initialization */ | ||
222 | #define DBG_GADGET 0x0004 /* calls to/from gadget driver */ | ||
223 | #define DBG_INT 0x0008 /* interrupts */ | ||
224 | #define DBG_BUS 0x0010 /* report changes in bus state */ | ||
225 | #define DBG_QUEUE 0x0020 /* debug request queue processing */ | ||
226 | #define DBG_FIFO 0x0040 /* debug FIFO contents */ | ||
227 | #define DBG_DMA 0x0080 /* debug DMA handling */ | ||
228 | #define DBG_REQ 0x0100 /* print out queued request length */ | ||
229 | #define DBG_ALL 0xffff | ||
230 | #define DBG_NONE 0x0000 | ||
231 | |||
232 | #define DEBUG_LEVEL (DBG_ERR) | ||
233 | #define DBG(level, fmt, ...) \ | ||
234 | do { \ | ||
235 | if ((level) & DEBUG_LEVEL) \ | ||
236 | printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__); \ | ||
237 | } while (0) | ||
238 | #else | ||
239 | #define DBG(level, fmt...) | ||
240 | #endif | ||
241 | |||
242 | enum usba_ctrl_state { | ||
243 | WAIT_FOR_SETUP, | ||
244 | DATA_STAGE_IN, | ||
245 | DATA_STAGE_OUT, | ||
246 | STATUS_STAGE_IN, | ||
247 | STATUS_STAGE_OUT, | ||
248 | STATUS_STAGE_ADDR, | ||
249 | STATUS_STAGE_TEST, | ||
250 | }; | ||
251 | /* | ||
252 | EP_STATE_IDLE, | ||
253 | EP_STATE_SETUP, | ||
254 | EP_STATE_IN_DATA, | ||
255 | EP_STATE_OUT_DATA, | ||
256 | EP_STATE_SET_ADDR_STATUS, | ||
257 | EP_STATE_RX_STATUS, | ||
258 | EP_STATE_TX_STATUS, | ||
259 | EP_STATE_HALT, | ||
260 | */ | ||
261 | |||
262 | struct usba_dma_desc { | ||
263 | dma_addr_t next; | ||
264 | dma_addr_t addr; | ||
265 | u32 ctrl; | ||
266 | }; | ||
267 | |||
268 | struct usba_ep { | ||
269 | int state; | ||
270 | void __iomem *ep_regs; | ||
271 | void __iomem *dma_regs; | ||
272 | void __iomem *fifo; | ||
273 | struct usb_ep ep; | ||
274 | struct usba_udc *udc; | ||
275 | |||
276 | struct list_head queue; | ||
277 | const struct usb_endpoint_descriptor *desc; | ||
278 | |||
279 | u16 fifo_size; | ||
280 | u8 nr_banks; | ||
281 | u8 index; | ||
282 | unsigned int can_dma:1; | ||
283 | unsigned int can_isoc:1; | ||
284 | unsigned int is_isoc:1; | ||
285 | unsigned int is_in:1; | ||
286 | |||
287 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | ||
288 | u32 last_dma_status; | ||
289 | struct dentry *debugfs_dir; | ||
290 | struct dentry *debugfs_queue; | ||
291 | struct dentry *debugfs_dma_status; | ||
292 | struct dentry *debugfs_state; | ||
293 | #endif | ||
294 | }; | ||
295 | |||
296 | struct usba_request { | ||
297 | struct usb_request req; | ||
298 | struct list_head queue; | ||
299 | |||
300 | u32 ctrl; | ||
301 | |||
302 | unsigned int submitted:1; | ||
303 | unsigned int last_transaction:1; | ||
304 | unsigned int using_dma:1; | ||
305 | unsigned int mapped:1; | ||
306 | }; | ||
307 | |||
308 | struct usba_udc { | ||
309 | /* Protect hw registers from concurrent modifications */ | ||
310 | spinlock_t lock; | ||
311 | |||
312 | void __iomem *regs; | ||
313 | void __iomem *fifo; | ||
314 | |||
315 | struct usb_gadget gadget; | ||
316 | struct usb_gadget_driver *driver; | ||
317 | struct platform_device *pdev; | ||
318 | int irq; | ||
319 | int vbus_pin; | ||
320 | struct clk *pclk; | ||
321 | struct clk *hclk; | ||
322 | |||
323 | u16 devstatus; | ||
324 | |||
325 | u16 test_mode; | ||
326 | int vbus_prev; | ||
327 | |||
328 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | ||
329 | struct dentry *debugfs_root; | ||
330 | struct dentry *debugfs_regs; | ||
331 | #endif | ||
332 | }; | ||
333 | |||
334 | static inline struct usba_ep *to_usba_ep(struct usb_ep *ep) | ||
335 | { | ||
336 | return container_of(ep, struct usba_ep, ep); | ||
337 | } | ||
338 | |||
339 | static inline struct usba_request *to_usba_req(struct usb_request *req) | ||
340 | { | ||
341 | return container_of(req, struct usba_request, req); | ||
342 | } | ||
343 | |||
344 | static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget) | ||
345 | { | ||
346 | return container_of(gadget, struct usba_udc, gadget); | ||
347 | } | ||
348 | |||
349 | #define ep_is_control(ep) ((ep)->index == 0) | ||
350 | #define ep_is_idle(ep) ((ep)->state == EP_STATE_IDLE) | ||
351 | |||
352 | #endif /* __LINUX_USB_GADGET_USBA_UDC_H */ | ||
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index c6760aee1e5c..a4e54b2743f0 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | 26 | ||
27 | #include <linux/usb/ch9.h> | 27 | #include <linux/usb/ch9.h> |
28 | #include <linux/usb_gadget.h> | 28 | #include <linux/usb/gadget.h> |
29 | 29 | ||
30 | 30 | ||
31 | /** | 31 | /** |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index d008d1360a7a..9db2482bdfa2 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <linux/interrupt.h> | 46 | #include <linux/interrupt.h> |
47 | #include <linux/platform_device.h> | 47 | #include <linux/platform_device.h> |
48 | #include <linux/usb.h> | 48 | #include <linux/usb.h> |
49 | #include <linux/usb_gadget.h> | 49 | #include <linux/usb/gadget.h> |
50 | 50 | ||
51 | #include <asm/byteorder.h> | 51 | #include <asm/byteorder.h> |
52 | #include <asm/io.h> | 52 | #include <asm/io.h> |
@@ -962,13 +962,13 @@ static struct platform_driver dummy_udc_driver = { | |||
962 | 962 | ||
963 | static int dummy_urb_enqueue ( | 963 | static int dummy_urb_enqueue ( |
964 | struct usb_hcd *hcd, | 964 | struct usb_hcd *hcd, |
965 | struct usb_host_endpoint *ep, | ||
966 | struct urb *urb, | 965 | struct urb *urb, |
967 | gfp_t mem_flags | 966 | gfp_t mem_flags |
968 | ) { | 967 | ) { |
969 | struct dummy *dum; | 968 | struct dummy *dum; |
970 | struct urbp *urbp; | 969 | struct urbp *urbp; |
971 | unsigned long flags; | 970 | unsigned long flags; |
971 | int rc; | ||
972 | 972 | ||
973 | if (!urb->transfer_buffer && urb->transfer_buffer_length) | 973 | if (!urb->transfer_buffer && urb->transfer_buffer_length) |
974 | return -EINVAL; | 974 | return -EINVAL; |
@@ -980,6 +980,11 @@ static int dummy_urb_enqueue ( | |||
980 | 980 | ||
981 | dum = hcd_to_dummy (hcd); | 981 | dum = hcd_to_dummy (hcd); |
982 | spin_lock_irqsave (&dum->lock, flags); | 982 | spin_lock_irqsave (&dum->lock, flags); |
983 | rc = usb_hcd_link_urb_to_ep(hcd, urb); | ||
984 | if (rc) { | ||
985 | kfree(urbp); | ||
986 | goto done; | ||
987 | } | ||
983 | 988 | ||
984 | if (!dum->udev) { | 989 | if (!dum->udev) { |
985 | dum->udev = urb->dev; | 990 | dum->udev = urb->dev; |
@@ -996,36 +1001,35 @@ static int dummy_urb_enqueue ( | |||
996 | if (!timer_pending (&dum->timer)) | 1001 | if (!timer_pending (&dum->timer)) |
997 | mod_timer (&dum->timer, jiffies + 1); | 1002 | mod_timer (&dum->timer, jiffies + 1); |
998 | 1003 | ||
999 | spin_unlock_irqrestore (&dum->lock, flags); | 1004 | done: |
1000 | return 0; | 1005 | spin_unlock_irqrestore(&dum->lock, flags); |
1006 | return rc; | ||
1001 | } | 1007 | } |
1002 | 1008 | ||
1003 | static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 1009 | static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
1004 | { | 1010 | { |
1005 | struct dummy *dum; | 1011 | struct dummy *dum; |
1006 | unsigned long flags; | 1012 | unsigned long flags; |
1013 | int rc; | ||
1007 | 1014 | ||
1008 | /* giveback happens automatically in timer callback, | 1015 | /* giveback happens automatically in timer callback, |
1009 | * so make sure the callback happens */ | 1016 | * so make sure the callback happens */ |
1010 | dum = hcd_to_dummy (hcd); | 1017 | dum = hcd_to_dummy (hcd); |
1011 | spin_lock_irqsave (&dum->lock, flags); | 1018 | spin_lock_irqsave (&dum->lock, flags); |
1012 | if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list)) | 1019 | |
1020 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
1021 | if (!rc && dum->rh_state != DUMMY_RH_RUNNING && | ||
1022 | !list_empty(&dum->urbp_list)) | ||
1013 | mod_timer (&dum->timer, jiffies); | 1023 | mod_timer (&dum->timer, jiffies); |
1014 | spin_unlock_irqrestore (&dum->lock, flags); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | 1024 | ||
1018 | static void maybe_set_status (struct urb *urb, int status) | 1025 | spin_unlock_irqrestore (&dum->lock, flags); |
1019 | { | 1026 | return rc; |
1020 | spin_lock (&urb->lock); | ||
1021 | if (urb->status == -EINPROGRESS) | ||
1022 | urb->status = status; | ||
1023 | spin_unlock (&urb->lock); | ||
1024 | } | 1027 | } |
1025 | 1028 | ||
1026 | /* transfer up to a frame's worth; caller must own lock */ | 1029 | /* transfer up to a frame's worth; caller must own lock */ |
1027 | static int | 1030 | static int |
1028 | transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit) | 1031 | transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit, |
1032 | int *status) | ||
1029 | { | 1033 | { |
1030 | struct dummy_request *req; | 1034 | struct dummy_request *req; |
1031 | 1035 | ||
@@ -1088,24 +1092,20 @@ top: | |||
1088 | * | 1092 | * |
1089 | * partially filling a buffer optionally blocks queue advances | 1093 | * partially filling a buffer optionally blocks queue advances |
1090 | * (so completion handlers can clean up the queue) but we don't | 1094 | * (so completion handlers can clean up the queue) but we don't |
1091 | * need to emulate such data-in-flight. so we only show part | 1095 | * need to emulate such data-in-flight. |
1092 | * of the URB_SHORT_NOT_OK effect: completion status. | ||
1093 | */ | 1096 | */ |
1094 | if (is_short) { | 1097 | if (is_short) { |
1095 | if (host_len == dev_len) { | 1098 | if (host_len == dev_len) { |
1096 | req->req.status = 0; | 1099 | req->req.status = 0; |
1097 | maybe_set_status (urb, 0); | 1100 | *status = 0; |
1098 | } else if (to_host) { | 1101 | } else if (to_host) { |
1099 | req->req.status = 0; | 1102 | req->req.status = 0; |
1100 | if (dev_len > host_len) | 1103 | if (dev_len > host_len) |
1101 | maybe_set_status (urb, -EOVERFLOW); | 1104 | *status = -EOVERFLOW; |
1102 | else | 1105 | else |
1103 | maybe_set_status (urb, | 1106 | *status = 0; |
1104 | (urb->transfer_flags | ||
1105 | & URB_SHORT_NOT_OK) | ||
1106 | ? -EREMOTEIO : 0); | ||
1107 | } else if (!to_host) { | 1107 | } else if (!to_host) { |
1108 | maybe_set_status (urb, 0); | 1108 | *status = 0; |
1109 | if (host_len > dev_len) | 1109 | if (host_len > dev_len) |
1110 | req->req.status = -EOVERFLOW; | 1110 | req->req.status = -EOVERFLOW; |
1111 | else | 1111 | else |
@@ -1119,9 +1119,8 @@ top: | |||
1119 | req->req.status = 0; | 1119 | req->req.status = 0; |
1120 | if (urb->transfer_buffer_length == urb->actual_length | 1120 | if (urb->transfer_buffer_length == urb->actual_length |
1121 | && !(urb->transfer_flags | 1121 | && !(urb->transfer_flags |
1122 | & URB_ZERO_PACKET)) { | 1122 | & URB_ZERO_PACKET)) |
1123 | maybe_set_status (urb, 0); | 1123 | *status = 0; |
1124 | } | ||
1125 | } | 1124 | } |
1126 | 1125 | ||
1127 | /* device side completion --> continuable */ | 1126 | /* device side completion --> continuable */ |
@@ -1137,7 +1136,7 @@ top: | |||
1137 | } | 1136 | } |
1138 | 1137 | ||
1139 | /* host side completion --> terminate */ | 1138 | /* host side completion --> terminate */ |
1140 | if (urb->status != -EINPROGRESS) | 1139 | if (*status != -EINPROGRESS) |
1141 | break; | 1140 | break; |
1142 | 1141 | ||
1143 | /* rescan to continue with any other queued i/o */ | 1142 | /* rescan to continue with any other queued i/o */ |
@@ -1248,12 +1247,12 @@ restart: | |||
1248 | u8 address; | 1247 | u8 address; |
1249 | struct dummy_ep *ep = NULL; | 1248 | struct dummy_ep *ep = NULL; |
1250 | int type; | 1249 | int type; |
1250 | int status = -EINPROGRESS; | ||
1251 | 1251 | ||
1252 | urb = urbp->urb; | 1252 | urb = urbp->urb; |
1253 | if (urb->status != -EINPROGRESS) { | 1253 | if (urb->unlinked) |
1254 | /* likely it was just unlinked */ | ||
1255 | goto return_urb; | 1254 | goto return_urb; |
1256 | } else if (dum->rh_state != DUMMY_RH_RUNNING) | 1255 | else if (dum->rh_state != DUMMY_RH_RUNNING) |
1257 | continue; | 1256 | continue; |
1258 | type = usb_pipetype (urb->pipe); | 1257 | type = usb_pipetype (urb->pipe); |
1259 | 1258 | ||
@@ -1274,7 +1273,7 @@ restart: | |||
1274 | dev_dbg (dummy_dev(dum), | 1273 | dev_dbg (dummy_dev(dum), |
1275 | "no ep configured for urb %p\n", | 1274 | "no ep configured for urb %p\n", |
1276 | urb); | 1275 | urb); |
1277 | maybe_set_status (urb, -EPROTO); | 1276 | status = -EPROTO; |
1278 | goto return_urb; | 1277 | goto return_urb; |
1279 | } | 1278 | } |
1280 | 1279 | ||
@@ -1289,7 +1288,7 @@ restart: | |||
1289 | /* NOTE: must not be iso! */ | 1288 | /* NOTE: must not be iso! */ |
1290 | dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n", | 1289 | dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n", |
1291 | ep->ep.name, urb); | 1290 | ep->ep.name, urb); |
1292 | maybe_set_status (urb, -EPIPE); | 1291 | status = -EPIPE; |
1293 | goto return_urb; | 1292 | goto return_urb; |
1294 | } | 1293 | } |
1295 | /* FIXME make sure both ends agree on maxpacket */ | 1294 | /* FIXME make sure both ends agree on maxpacket */ |
@@ -1307,7 +1306,7 @@ restart: | |||
1307 | w_value = le16_to_cpu(setup.wValue); | 1306 | w_value = le16_to_cpu(setup.wValue); |
1308 | if (le16_to_cpu(setup.wLength) != | 1307 | if (le16_to_cpu(setup.wLength) != |
1309 | urb->transfer_buffer_length) { | 1308 | urb->transfer_buffer_length) { |
1310 | maybe_set_status (urb, -EOVERFLOW); | 1309 | status = -EOVERFLOW; |
1311 | goto return_urb; | 1310 | goto return_urb; |
1312 | } | 1311 | } |
1313 | 1312 | ||
@@ -1337,7 +1336,7 @@ restart: | |||
1337 | if (setup.bRequestType != Dev_Request) | 1336 | if (setup.bRequestType != Dev_Request) |
1338 | break; | 1337 | break; |
1339 | dum->address = w_value; | 1338 | dum->address = w_value; |
1340 | maybe_set_status (urb, 0); | 1339 | status = 0; |
1341 | dev_dbg (udc_dev(dum), "set_address = %d\n", | 1340 | dev_dbg (udc_dev(dum), "set_address = %d\n", |
1342 | w_value); | 1341 | w_value); |
1343 | value = 0; | 1342 | value = 0; |
@@ -1364,7 +1363,7 @@ restart: | |||
1364 | if (value == 0) { | 1363 | if (value == 0) { |
1365 | dum->devstatus |= | 1364 | dum->devstatus |= |
1366 | (1 << w_value); | 1365 | (1 << w_value); |
1367 | maybe_set_status (urb, 0); | 1366 | status = 0; |
1368 | } | 1367 | } |
1369 | 1368 | ||
1370 | } else if (setup.bRequestType == Ep_Request) { | 1369 | } else if (setup.bRequestType == Ep_Request) { |
@@ -1376,7 +1375,7 @@ restart: | |||
1376 | } | 1375 | } |
1377 | ep2->halted = 1; | 1376 | ep2->halted = 1; |
1378 | value = 0; | 1377 | value = 0; |
1379 | maybe_set_status (urb, 0); | 1378 | status = 0; |
1380 | } | 1379 | } |
1381 | break; | 1380 | break; |
1382 | case USB_REQ_CLEAR_FEATURE: | 1381 | case USB_REQ_CLEAR_FEATURE: |
@@ -1386,7 +1385,7 @@ restart: | |||
1386 | dum->devstatus &= ~(1 << | 1385 | dum->devstatus &= ~(1 << |
1387 | USB_DEVICE_REMOTE_WAKEUP); | 1386 | USB_DEVICE_REMOTE_WAKEUP); |
1388 | value = 0; | 1387 | value = 0; |
1389 | maybe_set_status (urb, 0); | 1388 | status = 0; |
1390 | break; | 1389 | break; |
1391 | default: | 1390 | default: |
1392 | value = -EOPNOTSUPP; | 1391 | value = -EOPNOTSUPP; |
@@ -1401,7 +1400,7 @@ restart: | |||
1401 | } | 1400 | } |
1402 | ep2->halted = 0; | 1401 | ep2->halted = 0; |
1403 | value = 0; | 1402 | value = 0; |
1404 | maybe_set_status (urb, 0); | 1403 | status = 0; |
1405 | } | 1404 | } |
1406 | break; | 1405 | break; |
1407 | case USB_REQ_GET_STATUS: | 1406 | case USB_REQ_GET_STATUS: |
@@ -1438,7 +1437,7 @@ restart: | |||
1438 | urb->actual_length = min (2, | 1437 | urb->actual_length = min (2, |
1439 | urb->transfer_buffer_length); | 1438 | urb->transfer_buffer_length); |
1440 | value = 0; | 1439 | value = 0; |
1441 | maybe_set_status (urb, 0); | 1440 | status = 0; |
1442 | } | 1441 | } |
1443 | break; | 1442 | break; |
1444 | } | 1443 | } |
@@ -1465,7 +1464,7 @@ restart: | |||
1465 | dev_dbg (udc_dev(dum), | 1464 | dev_dbg (udc_dev(dum), |
1466 | "setup --> %d\n", | 1465 | "setup --> %d\n", |
1467 | value); | 1466 | value); |
1468 | maybe_set_status (urb, -EPIPE); | 1467 | status = -EPIPE; |
1469 | urb->actual_length = 0; | 1468 | urb->actual_length = 0; |
1470 | } | 1469 | } |
1471 | 1470 | ||
@@ -1482,7 +1481,7 @@ restart: | |||
1482 | * report random errors, to debug drivers. | 1481 | * report random errors, to debug drivers. |
1483 | */ | 1482 | */ |
1484 | limit = max (limit, periodic_bytes (dum, ep)); | 1483 | limit = max (limit, periodic_bytes (dum, ep)); |
1485 | maybe_set_status (urb, -ENOSYS); | 1484 | status = -ENOSYS; |
1486 | break; | 1485 | break; |
1487 | 1486 | ||
1488 | case PIPE_INTERRUPT: | 1487 | case PIPE_INTERRUPT: |
@@ -1496,23 +1495,23 @@ restart: | |||
1496 | default: | 1495 | default: |
1497 | treat_control_like_bulk: | 1496 | treat_control_like_bulk: |
1498 | ep->last_io = jiffies; | 1497 | ep->last_io = jiffies; |
1499 | total = transfer (dum, urb, ep, limit); | 1498 | total = transfer(dum, urb, ep, limit, &status); |
1500 | break; | 1499 | break; |
1501 | } | 1500 | } |
1502 | 1501 | ||
1503 | /* incomplete transfer? */ | 1502 | /* incomplete transfer? */ |
1504 | if (urb->status == -EINPROGRESS) | 1503 | if (status == -EINPROGRESS) |
1505 | continue; | 1504 | continue; |
1506 | 1505 | ||
1507 | return_urb: | 1506 | return_urb: |
1508 | urb->hcpriv = NULL; | ||
1509 | list_del (&urbp->urbp_list); | 1507 | list_del (&urbp->urbp_list); |
1510 | kfree (urbp); | 1508 | kfree (urbp); |
1511 | if (ep) | 1509 | if (ep) |
1512 | ep->already_seen = ep->setup_stage = 0; | 1510 | ep->already_seen = ep->setup_stage = 0; |
1513 | 1511 | ||
1512 | usb_hcd_unlink_urb_from_ep(dummy_to_hcd(dum), urb); | ||
1514 | spin_unlock (&dum->lock); | 1513 | spin_unlock (&dum->lock); |
1515 | usb_hcd_giveback_urb (dummy_to_hcd(dum), urb); | 1514 | usb_hcd_giveback_urb(dummy_to_hcd(dum), urb, status); |
1516 | spin_lock (&dum->lock); | 1515 | spin_lock (&dum->lock); |
1517 | 1516 | ||
1518 | goto restart; | 1517 | goto restart; |
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 3aa46cfa66ba..f9d07108bc30 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | 29 | ||
30 | #include <linux/usb/ch9.h> | 30 | #include <linux/usb/ch9.h> |
31 | #include <linux/usb_gadget.h> | 31 | #include <linux/usb/gadget.h> |
32 | 32 | ||
33 | #include "gadget_chips.h" | 33 | #include "gadget_chips.h" |
34 | 34 | ||
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index f70055473a00..9e732bff9df0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -19,40 +19,18 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* #define VERBOSE_DEBUG */ | ||
22 | 23 | ||
23 | // #define DEBUG 1 | ||
24 | // #define VERBOSE | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
28 | #include <linux/delay.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/utsname.h> | 25 | #include <linux/utsname.h> |
37 | #include <linux/device.h> | 26 | #include <linux/device.h> |
38 | #include <linux/moduleparam.h> | ||
39 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
40 | 28 | #include <linux/etherdevice.h> | |
41 | #include <asm/byteorder.h> | 29 | #include <linux/ethtool.h> |
42 | #include <asm/io.h> | ||
43 | #include <asm/irq.h> | ||
44 | #include <asm/system.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | #include <asm/unaligned.h> | ||
47 | 30 | ||
48 | #include <linux/usb/ch9.h> | 31 | #include <linux/usb/ch9.h> |
49 | #include <linux/usb/cdc.h> | 32 | #include <linux/usb/cdc.h> |
50 | #include <linux/usb_gadget.h> | 33 | #include <linux/usb/gadget.h> |
51 | |||
52 | #include <linux/random.h> | ||
53 | #include <linux/netdevice.h> | ||
54 | #include <linux/etherdevice.h> | ||
55 | #include <linux/ethtool.h> | ||
56 | 34 | ||
57 | #include "gadget_chips.h" | 35 | #include "gadget_chips.h" |
58 | 36 | ||
@@ -356,15 +334,15 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); | |||
356 | #define qlen(gadget) \ | 334 | #define qlen(gadget) \ |
357 | (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1)) | 335 | (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1)) |
358 | 336 | ||
359 | /* also defer IRQs on highspeed TX */ | ||
360 | #define TX_DELAY qmult | ||
361 | |||
362 | static inline int BITRATE(struct usb_gadget *g) | 337 | static inline int BITRATE(struct usb_gadget *g) |
363 | { | 338 | { |
364 | return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; | 339 | return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; |
365 | } | 340 | } |
366 | 341 | ||
367 | #else /* full speed (low speed doesn't do bulk) */ | 342 | #else /* full speed (low speed doesn't do bulk) */ |
343 | |||
344 | #define qmult 1 | ||
345 | |||
368 | #define DEVSPEED USB_SPEED_FULL | 346 | #define DEVSPEED USB_SPEED_FULL |
369 | 347 | ||
370 | #define qlen(gadget) DEFAULT_QLEN | 348 | #define qlen(gadget) DEFAULT_QLEN |
@@ -390,7 +368,7 @@ static inline int BITRATE(struct usb_gadget *g) | |||
390 | do { } while (0) | 368 | do { } while (0) |
391 | #endif /* DEBUG */ | 369 | #endif /* DEBUG */ |
392 | 370 | ||
393 | #ifdef VERBOSE | 371 | #ifdef VERBOSE_DEBUG |
394 | #define VDEBUG DEBUG | 372 | #define VDEBUG DEBUG |
395 | #else | 373 | #else |
396 | #define VDEBUG(dev,fmt,args...) \ | 374 | #define VDEBUG(dev,fmt,args...) \ |
@@ -830,8 +808,6 @@ static const struct usb_descriptor_header *fs_rndis_function [] = { | |||
830 | }; | 808 | }; |
831 | #endif | 809 | #endif |
832 | 810 | ||
833 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
834 | |||
835 | /* | 811 | /* |
836 | * usb 2.0 devices need to expose both high speed and full speed | 812 | * usb 2.0 devices need to expose both high speed and full speed |
837 | * descriptors, unless they only run at full speed. | 813 | * descriptors, unless they only run at full speed. |
@@ -934,18 +910,15 @@ static const struct usb_descriptor_header *hs_rndis_function [] = { | |||
934 | 910 | ||
935 | 911 | ||
936 | /* maxpacket and other transfer characteristics vary by speed. */ | 912 | /* maxpacket and other transfer characteristics vary by speed. */ |
937 | #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) | 913 | static inline struct usb_endpoint_descriptor * |
938 | 914 | ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, | |
939 | #else | 915 | struct usb_endpoint_descriptor *fs) |
940 | |||
941 | /* if there's no high speed support, maxpacket doesn't change. */ | ||
942 | #define ep_desc(g,hs,fs) (((void)(g)), (fs)) | ||
943 | |||
944 | static inline void __init hs_subset_descriptors(void) | ||
945 | { | 916 | { |
917 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | ||
918 | return hs; | ||
919 | return fs; | ||
946 | } | 920 | } |
947 | 921 | ||
948 | #endif /* !CONFIG_USB_GADGET_DUALSPEED */ | ||
949 | 922 | ||
950 | /*-------------------------------------------------------------------------*/ | 923 | /*-------------------------------------------------------------------------*/ |
951 | 924 | ||
@@ -989,22 +962,19 @@ static struct usb_gadget_strings stringtab = { | |||
989 | * complications: class descriptors, and an altsetting. | 962 | * complications: class descriptors, and an altsetting. |
990 | */ | 963 | */ |
991 | static int | 964 | static int |
992 | config_buf (enum usb_device_speed speed, | 965 | config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg) |
993 | u8 *buf, u8 type, | ||
994 | unsigned index, int is_otg) | ||
995 | { | 966 | { |
996 | int len; | 967 | int len; |
997 | const struct usb_config_descriptor *config; | 968 | const struct usb_config_descriptor *config; |
998 | const struct usb_descriptor_header **function; | 969 | const struct usb_descriptor_header **function; |
999 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 970 | int hs = 0; |
1000 | int hs = (speed == USB_SPEED_HIGH); | ||
1001 | 971 | ||
1002 | if (type == USB_DT_OTHER_SPEED_CONFIG) | 972 | if (gadget_is_dualspeed(g)) { |
1003 | hs = !hs; | 973 | hs = (g->speed == USB_SPEED_HIGH); |
974 | if (type == USB_DT_OTHER_SPEED_CONFIG) | ||
975 | hs = !hs; | ||
976 | } | ||
1004 | #define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function) | 977 | #define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function) |
1005 | #else | ||
1006 | #define which_fn(t) (fs_ ## t ## _function) | ||
1007 | #endif | ||
1008 | 978 | ||
1009 | if (index >= device_desc.bNumConfigurations) | 979 | if (index >= device_desc.bNumConfigurations) |
1010 | return -EINVAL; | 980 | return -EINVAL; |
@@ -1217,7 +1187,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags) | |||
1217 | if (number) | 1187 | if (number) |
1218 | eth_reset_config (dev); | 1188 | eth_reset_config (dev); |
1219 | usb_gadget_vbus_draw(dev->gadget, | 1189 | usb_gadget_vbus_draw(dev->gadget, |
1220 | dev->gadget->is_otg ? 8 : 100); | 1190 | gadget_is_otg(dev->gadget) ? 8 : 100); |
1221 | } else { | 1191 | } else { |
1222 | char *speed; | 1192 | char *speed; |
1223 | unsigned power; | 1193 | unsigned power; |
@@ -1399,24 +1369,22 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1399 | value = min (wLength, (u16) sizeof device_desc); | 1369 | value = min (wLength, (u16) sizeof device_desc); |
1400 | memcpy (req->buf, &device_desc, value); | 1370 | memcpy (req->buf, &device_desc, value); |
1401 | break; | 1371 | break; |
1402 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
1403 | case USB_DT_DEVICE_QUALIFIER: | 1372 | case USB_DT_DEVICE_QUALIFIER: |
1404 | if (!gadget->is_dualspeed) | 1373 | if (!gadget_is_dualspeed(gadget)) |
1405 | break; | 1374 | break; |
1406 | value = min (wLength, (u16) sizeof dev_qualifier); | 1375 | value = min (wLength, (u16) sizeof dev_qualifier); |
1407 | memcpy (req->buf, &dev_qualifier, value); | 1376 | memcpy (req->buf, &dev_qualifier, value); |
1408 | break; | 1377 | break; |
1409 | 1378 | ||
1410 | case USB_DT_OTHER_SPEED_CONFIG: | 1379 | case USB_DT_OTHER_SPEED_CONFIG: |
1411 | if (!gadget->is_dualspeed) | 1380 | if (!gadget_is_dualspeed(gadget)) |
1412 | break; | 1381 | break; |
1413 | // FALLTHROUGH | 1382 | // FALLTHROUGH |
1414 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | ||
1415 | case USB_DT_CONFIG: | 1383 | case USB_DT_CONFIG: |
1416 | value = config_buf (gadget->speed, req->buf, | 1384 | value = config_buf(gadget, req->buf, |
1417 | wValue >> 8, | 1385 | wValue >> 8, |
1418 | wValue & 0xff, | 1386 | wValue & 0xff, |
1419 | gadget->is_otg); | 1387 | gadget_is_otg(gadget)); |
1420 | if (value >= 0) | 1388 | if (value >= 0) |
1421 | value = min (wLength, (u16) value); | 1389 | value = min (wLength, (u16) value); |
1422 | break; | 1390 | break; |
@@ -1585,12 +1553,12 @@ done_set_intf: | |||
1585 | && rndis_control_intf.bInterfaceNumber | 1553 | && rndis_control_intf.bInterfaceNumber |
1586 | == wIndex) { | 1554 | == wIndex) { |
1587 | u8 *buf; | 1555 | u8 *buf; |
1556 | u32 n; | ||
1588 | 1557 | ||
1589 | /* return the result */ | 1558 | /* return the result */ |
1590 | buf = rndis_get_next_response (dev->rndis_config, | 1559 | buf = rndis_get_next_response(dev->rndis_config, &n); |
1591 | &value); | ||
1592 | if (buf) { | 1560 | if (buf) { |
1593 | memcpy (req->buf, buf, value); | 1561 | memcpy(req->buf, buf, n); |
1594 | req->complete = rndis_response_complete; | 1562 | req->complete = rndis_response_complete; |
1595 | rndis_free_response(dev->rndis_config, buf); | 1563 | rndis_free_response(dev->rndis_config, buf); |
1596 | } | 1564 | } |
@@ -1989,8 +1957,20 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1989 | } | 1957 | } |
1990 | 1958 | ||
1991 | spin_lock_irqsave(&dev->req_lock, flags); | 1959 | spin_lock_irqsave(&dev->req_lock, flags); |
1960 | /* | ||
1961 | * this freelist can be empty if an interrupt triggered disconnect() | ||
1962 | * and reconfigured the gadget (shutting down this queue) after the | ||
1963 | * network stack decided to xmit but before we got the spinlock. | ||
1964 | */ | ||
1965 | if (list_empty(&dev->tx_reqs)) { | ||
1966 | spin_unlock_irqrestore(&dev->req_lock, flags); | ||
1967 | return 1; | ||
1968 | } | ||
1969 | |||
1992 | req = container_of (dev->tx_reqs.next, struct usb_request, list); | 1970 | req = container_of (dev->tx_reqs.next, struct usb_request, list); |
1993 | list_del (&req->list); | 1971 | list_del (&req->list); |
1972 | |||
1973 | /* temporarily stop TX queue when the freelist empties */ | ||
1994 | if (list_empty (&dev->tx_reqs)) | 1974 | if (list_empty (&dev->tx_reqs)) |
1995 | netif_stop_queue (net); | 1975 | netif_stop_queue (net); |
1996 | spin_unlock_irqrestore(&dev->req_lock, flags); | 1976 | spin_unlock_irqrestore(&dev->req_lock, flags); |
@@ -2026,12 +2006,11 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
2026 | 2006 | ||
2027 | req->length = length; | 2007 | req->length = length; |
2028 | 2008 | ||
2029 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
2030 | /* throttle highspeed IRQ rate back slightly */ | 2009 | /* throttle highspeed IRQ rate back slightly */ |
2031 | req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) | 2010 | if (gadget_is_dualspeed(dev->gadget)) |
2032 | ? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0) | 2011 | req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) |
2033 | : 0; | 2012 | ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) |
2034 | #endif | 2013 | : 0; |
2035 | 2014 | ||
2036 | retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC); | 2015 | retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC); |
2037 | switch (retval) { | 2016 | switch (retval) { |
@@ -2188,8 +2167,7 @@ static int eth_stop (struct net_device *net) | |||
2188 | } | 2167 | } |
2189 | 2168 | ||
2190 | if (rndis_active(dev)) { | 2169 | if (rndis_active(dev)) { |
2191 | rndis_set_param_medium (dev->rndis_config, | 2170 | rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0); |
2192 | NDIS_MEDIUM_802_3, 0); | ||
2193 | (void) rndis_signal_disconnect (dev->rndis_config); | 2171 | (void) rndis_signal_disconnect (dev->rndis_config); |
2194 | } | 2172 | } |
2195 | 2173 | ||
@@ -2443,26 +2421,28 @@ autoconf_fail: | |||
2443 | if (rndis) | 2421 | if (rndis) |
2444 | device_desc.bNumConfigurations = 2; | 2422 | device_desc.bNumConfigurations = 2; |
2445 | 2423 | ||
2446 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 2424 | if (gadget_is_dualspeed(gadget)) { |
2447 | if (rndis) | 2425 | if (rndis) |
2448 | dev_qualifier.bNumConfigurations = 2; | 2426 | dev_qualifier.bNumConfigurations = 2; |
2449 | else if (!cdc) | 2427 | else if (!cdc) |
2450 | dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC; | 2428 | dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC; |
2451 | 2429 | ||
2452 | /* assumes ep0 uses the same value for both speeds ... */ | 2430 | /* assumes ep0 uses the same value for both speeds ... */ |
2453 | dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; | 2431 | dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; |
2454 | 2432 | ||
2455 | /* and that all endpoints are dual-speed */ | 2433 | /* and that all endpoints are dual-speed */ |
2456 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 2434 | hs_source_desc.bEndpointAddress = |
2457 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 2435 | fs_source_desc.bEndpointAddress; |
2436 | hs_sink_desc.bEndpointAddress = | ||
2437 | fs_sink_desc.bEndpointAddress; | ||
2458 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 2438 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) |
2459 | if (status_ep) | 2439 | if (status_ep) |
2460 | hs_status_desc.bEndpointAddress = | 2440 | hs_status_desc.bEndpointAddress = |
2461 | fs_status_desc.bEndpointAddress; | 2441 | fs_status_desc.bEndpointAddress; |
2462 | #endif | 2442 | #endif |
2463 | #endif /* DUALSPEED */ | 2443 | } |
2464 | 2444 | ||
2465 | if (gadget->is_otg) { | 2445 | if (gadget_is_otg(gadget)) { |
2466 | otg_descriptor.bmAttributes |= USB_OTG_HNP, | 2446 | otg_descriptor.bmAttributes |= USB_OTG_HNP, |
2467 | eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 2447 | eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
2468 | eth_config.bMaxPower = 4; | 2448 | eth_config.bMaxPower = 4; |
@@ -2598,12 +2578,11 @@ fail0: | |||
2598 | if (rndis_set_param_dev (dev->rndis_config, dev->net, | 2578 | if (rndis_set_param_dev (dev->rndis_config, dev->net, |
2599 | &dev->stats, &dev->cdc_filter)) | 2579 | &dev->stats, &dev->cdc_filter)) |
2600 | goto fail0; | 2580 | goto fail0; |
2601 | if (rndis_set_param_vendor (dev->rndis_config, vendorID, | 2581 | if (rndis_set_param_vendor(dev->rndis_config, vendorID, |
2602 | manufacturer)) | 2582 | manufacturer)) |
2603 | goto fail0; | 2583 | goto fail0; |
2604 | if (rndis_set_param_medium (dev->rndis_config, | 2584 | if (rndis_set_param_medium(dev->rndis_config, |
2605 | NDIS_MEDIUM_802_3, | 2585 | NDIS_MEDIUM_802_3, 0)) |
2606 | 0)) | ||
2607 | goto fail0; | 2586 | goto fail0; |
2608 | INFO (dev, "RNDIS ready\n"); | 2587 | INFO (dev, "RNDIS ready\n"); |
2609 | } | 2588 | } |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 965ad7bec7b7..73726c570a6e 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development | 2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2005 Alan Stern | 4 | * Copyright (C) 2003-2007 Alan Stern |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without |
@@ -217,17 +217,11 @@ | |||
217 | */ | 217 | */ |
218 | 218 | ||
219 | 219 | ||
220 | #undef DEBUG | 220 | /* #define VERBOSE_DEBUG */ |
221 | #undef VERBOSE | 221 | /* #define DUMP_MSGS */ |
222 | #undef DUMP_MSGS | ||
223 | |||
224 | 222 | ||
225 | #include <asm/system.h> | ||
226 | #include <asm/uaccess.h> | ||
227 | 223 | ||
228 | #include <linux/bitops.h> | ||
229 | #include <linux/blkdev.h> | 224 | #include <linux/blkdev.h> |
230 | #include <linux/compiler.h> | ||
231 | #include <linux/completion.h> | 225 | #include <linux/completion.h> |
232 | #include <linux/dcache.h> | 226 | #include <linux/dcache.h> |
233 | #include <linux/delay.h> | 227 | #include <linux/delay.h> |
@@ -235,18 +229,10 @@ | |||
235 | #include <linux/fcntl.h> | 229 | #include <linux/fcntl.h> |
236 | #include <linux/file.h> | 230 | #include <linux/file.h> |
237 | #include <linux/fs.h> | 231 | #include <linux/fs.h> |
238 | #include <linux/init.h> | ||
239 | #include <linux/kernel.h> | ||
240 | #include <linux/kref.h> | 232 | #include <linux/kref.h> |
241 | #include <linux/kthread.h> | 233 | #include <linux/kthread.h> |
242 | #include <linux/limits.h> | 234 | #include <linux/limits.h> |
243 | #include <linux/list.h> | ||
244 | #include <linux/module.h> | ||
245 | #include <linux/moduleparam.h> | ||
246 | #include <linux/pagemap.h> | ||
247 | #include <linux/rwsem.h> | 235 | #include <linux/rwsem.h> |
248 | #include <linux/sched.h> | ||
249 | #include <linux/signal.h> | ||
250 | #include <linux/slab.h> | 236 | #include <linux/slab.h> |
251 | #include <linux/spinlock.h> | 237 | #include <linux/spinlock.h> |
252 | #include <linux/string.h> | 238 | #include <linux/string.h> |
@@ -254,7 +240,7 @@ | |||
254 | #include <linux/utsname.h> | 240 | #include <linux/utsname.h> |
255 | 241 | ||
256 | #include <linux/usb/ch9.h> | 242 | #include <linux/usb/ch9.h> |
257 | #include <linux/usb_gadget.h> | 243 | #include <linux/usb/gadget.h> |
258 | 244 | ||
259 | #include "gadget_chips.h" | 245 | #include "gadget_chips.h" |
260 | 246 | ||
@@ -263,7 +249,7 @@ | |||
263 | 249 | ||
264 | #define DRIVER_DESC "File-backed Storage Gadget" | 250 | #define DRIVER_DESC "File-backed Storage Gadget" |
265 | #define DRIVER_NAME "g_file_storage" | 251 | #define DRIVER_NAME "g_file_storage" |
266 | #define DRIVER_VERSION "28 November 2005" | 252 | #define DRIVER_VERSION "7 August 2007" |
267 | 253 | ||
268 | static const char longname[] = DRIVER_DESC; | 254 | static const char longname[] = DRIVER_DESC; |
269 | static const char shortname[] = DRIVER_NAME; | 255 | static const char shortname[] = DRIVER_NAME; |
@@ -289,57 +275,48 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
289 | 275 | ||
290 | /*-------------------------------------------------------------------------*/ | 276 | /*-------------------------------------------------------------------------*/ |
291 | 277 | ||
292 | #define xprintk(f,level,fmt,args...) \ | ||
293 | dev_printk(level , &(f)->gadget->dev , fmt , ## args) | ||
294 | #define yprintk(l,level,fmt,args...) \ | ||
295 | dev_printk(level , &(l)->dev , fmt , ## args) | ||
296 | |||
297 | #ifdef DEBUG | 278 | #ifdef DEBUG |
298 | #define DBG(fsg,fmt,args...) \ | ||
299 | xprintk(fsg , KERN_DEBUG , fmt , ## args) | ||
300 | #define LDBG(lun,fmt,args...) \ | 279 | #define LDBG(lun,fmt,args...) \ |
301 | yprintk(lun , KERN_DEBUG , fmt , ## args) | 280 | dev_dbg(&(lun)->dev , fmt , ## args) |
302 | #define MDBG(fmt,args...) \ | 281 | #define MDBG(fmt,args...) \ |
303 | printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args) | 282 | printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args) |
304 | #else | 283 | #else |
305 | #define DBG(fsg,fmt,args...) \ | ||
306 | do { } while (0) | ||
307 | #define LDBG(lun,fmt,args...) \ | 284 | #define LDBG(lun,fmt,args...) \ |
308 | do { } while (0) | 285 | do { } while (0) |
309 | #define MDBG(fmt,args...) \ | 286 | #define MDBG(fmt,args...) \ |
310 | do { } while (0) | 287 | do { } while (0) |
311 | #undef VERBOSE | 288 | #undef VERBOSE_DEBUG |
312 | #undef DUMP_MSGS | 289 | #undef DUMP_MSGS |
313 | #endif /* DEBUG */ | 290 | #endif /* DEBUG */ |
314 | 291 | ||
315 | #ifdef VERBOSE | 292 | #ifdef VERBOSE_DEBUG |
316 | #define VDBG DBG | ||
317 | #define VLDBG LDBG | 293 | #define VLDBG LDBG |
318 | #else | 294 | #else |
319 | #define VDBG(fsg,fmt,args...) \ | ||
320 | do { } while (0) | ||
321 | #define VLDBG(lun,fmt,args...) \ | 295 | #define VLDBG(lun,fmt,args...) \ |
322 | do { } while (0) | 296 | do { } while (0) |
323 | #endif /* VERBOSE */ | 297 | #endif /* VERBOSE_DEBUG */ |
324 | 298 | ||
325 | #define ERROR(fsg,fmt,args...) \ | ||
326 | xprintk(fsg , KERN_ERR , fmt , ## args) | ||
327 | #define LERROR(lun,fmt,args...) \ | 299 | #define LERROR(lun,fmt,args...) \ |
328 | yprintk(lun , KERN_ERR , fmt , ## args) | 300 | dev_err(&(lun)->dev , fmt , ## args) |
329 | |||
330 | #define WARN(fsg,fmt,args...) \ | ||
331 | xprintk(fsg , KERN_WARNING , fmt , ## args) | ||
332 | #define LWARN(lun,fmt,args...) \ | 301 | #define LWARN(lun,fmt,args...) \ |
333 | yprintk(lun , KERN_WARNING , fmt , ## args) | 302 | dev_warn(&(lun)->dev , fmt , ## args) |
334 | |||
335 | #define INFO(fsg,fmt,args...) \ | ||
336 | xprintk(fsg , KERN_INFO , fmt , ## args) | ||
337 | #define LINFO(lun,fmt,args...) \ | 303 | #define LINFO(lun,fmt,args...) \ |
338 | yprintk(lun , KERN_INFO , fmt , ## args) | 304 | dev_info(&(lun)->dev , fmt , ## args) |
339 | 305 | ||
340 | #define MINFO(fmt,args...) \ | 306 | #define MINFO(fmt,args...) \ |
341 | printk(KERN_INFO DRIVER_NAME ": " fmt , ## args) | 307 | printk(KERN_INFO DRIVER_NAME ": " fmt , ## args) |
342 | 308 | ||
309 | #define DBG(d, fmt, args...) \ | ||
310 | dev_dbg(&(d)->gadget->dev , fmt , ## args) | ||
311 | #define VDBG(d, fmt, args...) \ | ||
312 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) | ||
313 | #define ERROR(d, fmt, args...) \ | ||
314 | dev_err(&(d)->gadget->dev , fmt , ## args) | ||
315 | #define WARN(d, fmt, args...) \ | ||
316 | dev_warn(&(d)->gadget->dev , fmt , ## args) | ||
317 | #define INFO(d, fmt, args...) \ | ||
318 | dev_info(&(d)->gadget->dev , fmt , ## args) | ||
319 | |||
343 | 320 | ||
344 | /*-------------------------------------------------------------------------*/ | 321 | /*-------------------------------------------------------------------------*/ |
345 | 322 | ||
@@ -350,8 +327,8 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
350 | static struct { | 327 | static struct { |
351 | char *file[MAX_LUNS]; | 328 | char *file[MAX_LUNS]; |
352 | int ro[MAX_LUNS]; | 329 | int ro[MAX_LUNS]; |
353 | int num_filenames; | 330 | unsigned int num_filenames; |
354 | int num_ros; | 331 | unsigned int num_ros; |
355 | unsigned int nluns; | 332 | unsigned int nluns; |
356 | 333 | ||
357 | int removable; | 334 | int removable; |
@@ -578,7 +555,7 @@ struct lun { | |||
578 | 555 | ||
579 | #define backing_file_is_open(curlun) ((curlun)->filp != NULL) | 556 | #define backing_file_is_open(curlun) ((curlun)->filp != NULL) |
580 | 557 | ||
581 | static inline struct lun *dev_to_lun(struct device *dev) | 558 | static struct lun *dev_to_lun(struct device *dev) |
582 | { | 559 | { |
583 | return container_of(dev, struct lun, dev); | 560 | return container_of(dev, struct lun, dev); |
584 | } | 561 | } |
@@ -711,13 +688,13 @@ struct fsg_dev { | |||
711 | 688 | ||
712 | typedef void (*fsg_routine_t)(struct fsg_dev *); | 689 | typedef void (*fsg_routine_t)(struct fsg_dev *); |
713 | 690 | ||
714 | static int inline exception_in_progress(struct fsg_dev *fsg) | 691 | static int exception_in_progress(struct fsg_dev *fsg) |
715 | { | 692 | { |
716 | return (fsg->state > FSG_STATE_IDLE); | 693 | return (fsg->state > FSG_STATE_IDLE); |
717 | } | 694 | } |
718 | 695 | ||
719 | /* Make bulk-out requests be divisible by the maxpacket size */ | 696 | /* Make bulk-out requests be divisible by the maxpacket size */ |
720 | static void inline set_bulk_out_req_length(struct fsg_dev *fsg, | 697 | static void set_bulk_out_req_length(struct fsg_dev *fsg, |
721 | struct fsg_buffhd *bh, unsigned int length) | 698 | struct fsg_buffhd *bh, unsigned int length) |
722 | { | 699 | { |
723 | unsigned int rem; | 700 | unsigned int rem; |
@@ -743,50 +720,36 @@ static void close_all_backing_files(struct fsg_dev *fsg); | |||
743 | static void dump_msg(struct fsg_dev *fsg, const char *label, | 720 | static void dump_msg(struct fsg_dev *fsg, const char *label, |
744 | const u8 *buf, unsigned int length) | 721 | const u8 *buf, unsigned int length) |
745 | { | 722 | { |
746 | unsigned int start, num, i; | 723 | if (length < 512) { |
747 | char line[52], *p; | 724 | DBG(fsg, "%s, length %u:\n", label, length); |
748 | 725 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, | |
749 | if (length >= 512) | 726 | 16, 1, buf, length, 0); |
750 | return; | ||
751 | DBG(fsg, "%s, length %u:\n", label, length); | ||
752 | |||
753 | start = 0; | ||
754 | while (length > 0) { | ||
755 | num = min(length, 16u); | ||
756 | p = line; | ||
757 | for (i = 0; i < num; ++i) { | ||
758 | if (i == 8) | ||
759 | *p++ = ' '; | ||
760 | sprintf(p, " %02x", buf[i]); | ||
761 | p += 3; | ||
762 | } | ||
763 | *p = 0; | ||
764 | printk(KERN_DEBUG "%6x: %s\n", start, line); | ||
765 | buf += num; | ||
766 | start += num; | ||
767 | length -= num; | ||
768 | } | 727 | } |
769 | } | 728 | } |
770 | 729 | ||
771 | static void inline dump_cdb(struct fsg_dev *fsg) | 730 | static void dump_cdb(struct fsg_dev *fsg) |
772 | {} | 731 | {} |
773 | 732 | ||
774 | #else | 733 | #else |
775 | 734 | ||
776 | static void inline dump_msg(struct fsg_dev *fsg, const char *label, | 735 | static void dump_msg(struct fsg_dev *fsg, const char *label, |
777 | const u8 *buf, unsigned int length) | 736 | const u8 *buf, unsigned int length) |
778 | {} | 737 | {} |
779 | 738 | ||
780 | static void inline dump_cdb(struct fsg_dev *fsg) | 739 | #ifdef VERBOSE_DEBUG |
781 | { | ||
782 | int i; | ||
783 | char cmdbuf[3*MAX_COMMAND_SIZE + 1]; | ||
784 | 740 | ||
785 | for (i = 0; i < fsg->cmnd_size; ++i) | 741 | static void dump_cdb(struct fsg_dev *fsg) |
786 | sprintf(cmdbuf + i*3, " %02x", fsg->cmnd[i]); | 742 | { |
787 | VDBG(fsg, "SCSI CDB: %s\n", cmdbuf); | 743 | print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, |
744 | 16, 1, fsg->cmnd, fsg->cmnd_size, 0); | ||
788 | } | 745 | } |
789 | 746 | ||
747 | #else | ||
748 | |||
749 | static void dump_cdb(struct fsg_dev *fsg) | ||
750 | {} | ||
751 | |||
752 | #endif /* VERBOSE_DEBUG */ | ||
790 | #endif /* DUMP_MSGS */ | 753 | #endif /* DUMP_MSGS */ |
791 | 754 | ||
792 | 755 | ||
@@ -809,24 +772,24 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) | |||
809 | 772 | ||
810 | /* Routines for unaligned data access */ | 773 | /* Routines for unaligned data access */ |
811 | 774 | ||
812 | static u16 inline get_be16(u8 *buf) | 775 | static u16 get_be16(u8 *buf) |
813 | { | 776 | { |
814 | return ((u16) buf[0] << 8) | ((u16) buf[1]); | 777 | return ((u16) buf[0] << 8) | ((u16) buf[1]); |
815 | } | 778 | } |
816 | 779 | ||
817 | static u32 inline get_be32(u8 *buf) | 780 | static u32 get_be32(u8 *buf) |
818 | { | 781 | { |
819 | return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | | 782 | return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | |
820 | ((u32) buf[2] << 8) | ((u32) buf[3]); | 783 | ((u32) buf[2] << 8) | ((u32) buf[3]); |
821 | } | 784 | } |
822 | 785 | ||
823 | static void inline put_be16(u8 *buf, u16 val) | 786 | static void put_be16(u8 *buf, u16 val) |
824 | { | 787 | { |
825 | buf[0] = val >> 8; | 788 | buf[0] = val >> 8; |
826 | buf[1] = val; | 789 | buf[1] = val; |
827 | } | 790 | } |
828 | 791 | ||
829 | static void inline put_be32(u8 *buf, u32 val) | 792 | static void put_be32(u8 *buf, u32 val) |
830 | { | 793 | { |
831 | buf[0] = val >> 24; | 794 | buf[0] = val >> 24; |
832 | buf[1] = val >> 16; | 795 | buf[1] = val >> 16; |
@@ -950,8 +913,6 @@ static const struct usb_descriptor_header *fs_function[] = { | |||
950 | #define FS_FUNCTION_PRE_EP_ENTRIES 2 | 913 | #define FS_FUNCTION_PRE_EP_ENTRIES 2 |
951 | 914 | ||
952 | 915 | ||
953 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
954 | |||
955 | /* | 916 | /* |
956 | * USB 2.0 devices need to expose both high speed and full speed | 917 | * USB 2.0 devices need to expose both high speed and full speed |
957 | * descriptors, unless they only run at full speed. | 918 | * descriptors, unless they only run at full speed. |
@@ -1014,14 +975,14 @@ static const struct usb_descriptor_header *hs_function[] = { | |||
1014 | #define HS_FUNCTION_PRE_EP_ENTRIES 2 | 975 | #define HS_FUNCTION_PRE_EP_ENTRIES 2 |
1015 | 976 | ||
1016 | /* Maxpacket and other transfer characteristics vary by speed. */ | 977 | /* Maxpacket and other transfer characteristics vary by speed. */ |
1017 | #define ep_desc(g,fs,hs) (((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs)) | 978 | static struct usb_endpoint_descriptor * |
1018 | 979 | ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, | |
1019 | #else | 980 | struct usb_endpoint_descriptor *hs) |
1020 | 981 | { | |
1021 | /* If there's no high speed support, always use the full-speed descriptor. */ | 982 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) |
1022 | #define ep_desc(g,fs,hs) fs | 983 | return hs; |
1023 | 984 | return fs; | |
1024 | #endif /* !CONFIG_USB_GADGET_DUALSPEED */ | 985 | } |
1025 | 986 | ||
1026 | 987 | ||
1027 | /* The CBI specification limits the serial string to 12 uppercase hexadecimal | 988 | /* The CBI specification limits the serial string to 12 uppercase hexadecimal |
@@ -1053,26 +1014,22 @@ static struct usb_gadget_strings stringtab = { | |||
1053 | static int populate_config_buf(struct usb_gadget *gadget, | 1014 | static int populate_config_buf(struct usb_gadget *gadget, |
1054 | u8 *buf, u8 type, unsigned index) | 1015 | u8 *buf, u8 type, unsigned index) |
1055 | { | 1016 | { |
1056 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
1057 | enum usb_device_speed speed = gadget->speed; | 1017 | enum usb_device_speed speed = gadget->speed; |
1058 | #endif | ||
1059 | int len; | 1018 | int len; |
1060 | const struct usb_descriptor_header **function; | 1019 | const struct usb_descriptor_header **function; |
1061 | 1020 | ||
1062 | if (index > 0) | 1021 | if (index > 0) |
1063 | return -EINVAL; | 1022 | return -EINVAL; |
1064 | 1023 | ||
1065 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1024 | if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) |
1066 | if (type == USB_DT_OTHER_SPEED_CONFIG) | ||
1067 | speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; | 1025 | speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; |
1068 | if (speed == USB_SPEED_HIGH) | 1026 | if (gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH) |
1069 | function = hs_function; | 1027 | function = hs_function; |
1070 | else | 1028 | else |
1071 | #endif | ||
1072 | function = fs_function; | 1029 | function = fs_function; |
1073 | 1030 | ||
1074 | /* for now, don't advertise srp-only devices */ | 1031 | /* for now, don't advertise srp-only devices */ |
1075 | if (!gadget->is_otg) | 1032 | if (!gadget_is_otg(gadget)) |
1076 | function++; | 1033 | function++; |
1077 | 1034 | ||
1078 | len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); | 1035 | len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); |
@@ -1394,10 +1351,9 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1394 | value = sizeof device_desc; | 1351 | value = sizeof device_desc; |
1395 | memcpy(req->buf, &device_desc, value); | 1352 | memcpy(req->buf, &device_desc, value); |
1396 | break; | 1353 | break; |
1397 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
1398 | case USB_DT_DEVICE_QUALIFIER: | 1354 | case USB_DT_DEVICE_QUALIFIER: |
1399 | VDBG(fsg, "get device qualifier\n"); | 1355 | VDBG(fsg, "get device qualifier\n"); |
1400 | if (!fsg->gadget->is_dualspeed) | 1356 | if (!gadget_is_dualspeed(fsg->gadget)) |
1401 | break; | 1357 | break; |
1402 | value = sizeof dev_qualifier; | 1358 | value = sizeof dev_qualifier; |
1403 | memcpy(req->buf, &dev_qualifier, value); | 1359 | memcpy(req->buf, &dev_qualifier, value); |
@@ -1405,15 +1361,12 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1405 | 1361 | ||
1406 | case USB_DT_OTHER_SPEED_CONFIG: | 1362 | case USB_DT_OTHER_SPEED_CONFIG: |
1407 | VDBG(fsg, "get other-speed config descriptor\n"); | 1363 | VDBG(fsg, "get other-speed config descriptor\n"); |
1408 | if (!fsg->gadget->is_dualspeed) | 1364 | if (!gadget_is_dualspeed(fsg->gadget)) |
1409 | break; | 1365 | break; |
1410 | goto get_config; | 1366 | goto get_config; |
1411 | #endif | ||
1412 | case USB_DT_CONFIG: | 1367 | case USB_DT_CONFIG: |
1413 | VDBG(fsg, "get configuration descriptor\n"); | 1368 | VDBG(fsg, "get configuration descriptor\n"); |
1414 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1369 | get_config: |
1415 | get_config: | ||
1416 | #endif | ||
1417 | value = populate_config_buf(fsg->gadget, | 1370 | value = populate_config_buf(fsg->gadget, |
1418 | req->buf, | 1371 | req->buf, |
1419 | w_value >> 8, | 1372 | w_value >> 8, |
@@ -1646,7 +1599,8 @@ static int do_read(struct fsg_dev *fsg) | |||
1646 | /* Wait for the next buffer to become available */ | 1599 | /* Wait for the next buffer to become available */ |
1647 | bh = fsg->next_buffhd_to_fill; | 1600 | bh = fsg->next_buffhd_to_fill; |
1648 | while (bh->state != BUF_STATE_EMPTY) { | 1601 | while (bh->state != BUF_STATE_EMPTY) { |
1649 | if ((rc = sleep_thread(fsg)) != 0) | 1602 | rc = sleep_thread(fsg); |
1603 | if (rc) | ||
1650 | return rc; | 1604 | return rc; |
1651 | } | 1605 | } |
1652 | 1606 | ||
@@ -1885,7 +1839,8 @@ static int do_write(struct fsg_dev *fsg) | |||
1885 | } | 1839 | } |
1886 | 1840 | ||
1887 | /* Wait for something to happen */ | 1841 | /* Wait for something to happen */ |
1888 | if ((rc = sleep_thread(fsg)) != 0) | 1842 | rc = sleep_thread(fsg); |
1843 | if (rc) | ||
1889 | return rc; | 1844 | return rc; |
1890 | } | 1845 | } |
1891 | 1846 | ||
@@ -2369,7 +2324,8 @@ static int pad_with_zeros(struct fsg_dev *fsg) | |||
2369 | 2324 | ||
2370 | /* Wait for the next buffer to be free */ | 2325 | /* Wait for the next buffer to be free */ |
2371 | while (bh->state != BUF_STATE_EMPTY) { | 2326 | while (bh->state != BUF_STATE_EMPTY) { |
2372 | if ((rc = sleep_thread(fsg)) != 0) | 2327 | rc = sleep_thread(fsg); |
2328 | if (rc) | ||
2373 | return rc; | 2329 | return rc; |
2374 | } | 2330 | } |
2375 | 2331 | ||
@@ -2429,7 +2385,8 @@ static int throw_away_data(struct fsg_dev *fsg) | |||
2429 | } | 2385 | } |
2430 | 2386 | ||
2431 | /* Otherwise wait for something to happen */ | 2387 | /* Otherwise wait for something to happen */ |
2432 | if ((rc = sleep_thread(fsg)) != 0) | 2388 | rc = sleep_thread(fsg); |
2389 | if (rc) | ||
2433 | return rc; | 2390 | return rc; |
2434 | } | 2391 | } |
2435 | return 0; | 2392 | return 0; |
@@ -2551,7 +2508,8 @@ static int send_status(struct fsg_dev *fsg) | |||
2551 | /* Wait for the next buffer to become available */ | 2508 | /* Wait for the next buffer to become available */ |
2552 | bh = fsg->next_buffhd_to_fill; | 2509 | bh = fsg->next_buffhd_to_fill; |
2553 | while (bh->state != BUF_STATE_EMPTY) { | 2510 | while (bh->state != BUF_STATE_EMPTY) { |
2554 | if ((rc = sleep_thread(fsg)) != 0) | 2511 | rc = sleep_thread(fsg); |
2512 | if (rc) | ||
2555 | return rc; | 2513 | return rc; |
2556 | } | 2514 | } |
2557 | 2515 | ||
@@ -2771,9 +2729,10 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
2771 | /* Wait for the next buffer to become available for data or status */ | 2729 | /* Wait for the next buffer to become available for data or status */ |
2772 | bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; | 2730 | bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; |
2773 | while (bh->state != BUF_STATE_EMPTY) { | 2731 | while (bh->state != BUF_STATE_EMPTY) { |
2774 | if ((rc = sleep_thread(fsg)) != 0) | 2732 | rc = sleep_thread(fsg); |
2733 | if (rc) | ||
2775 | return rc; | 2734 | return rc; |
2776 | } | 2735 | } |
2777 | fsg->phase_error = 0; | 2736 | fsg->phase_error = 0; |
2778 | fsg->short_packet_received = 0; | 2737 | fsg->short_packet_received = 0; |
2779 | 2738 | ||
@@ -3005,7 +2964,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
3005 | 2964 | ||
3006 | /* Is the CBW meaningful? */ | 2965 | /* Is the CBW meaningful? */ |
3007 | if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || | 2966 | if (cbw->Lun >= MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || |
3008 | cbw->Length < 6 || cbw->Length > MAX_COMMAND_SIZE) { | 2967 | cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { |
3009 | DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " | 2968 | DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " |
3010 | "cmdlen %u\n", | 2969 | "cmdlen %u\n", |
3011 | cbw->Lun, cbw->Flags, cbw->Length); | 2970 | cbw->Lun, cbw->Flags, cbw->Length); |
@@ -3045,9 +3004,10 @@ static int get_next_command(struct fsg_dev *fsg) | |||
3045 | /* Wait for the next buffer to become available */ | 3004 | /* Wait for the next buffer to become available */ |
3046 | bh = fsg->next_buffhd_to_fill; | 3005 | bh = fsg->next_buffhd_to_fill; |
3047 | while (bh->state != BUF_STATE_EMPTY) { | 3006 | while (bh->state != BUF_STATE_EMPTY) { |
3048 | if ((rc = sleep_thread(fsg)) != 0) | 3007 | rc = sleep_thread(fsg); |
3008 | if (rc) | ||
3049 | return rc; | 3009 | return rc; |
3050 | } | 3010 | } |
3051 | 3011 | ||
3052 | /* Queue a request to read a Bulk-only CBW */ | 3012 | /* Queue a request to read a Bulk-only CBW */ |
3053 | set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); | 3013 | set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); |
@@ -3061,9 +3021,10 @@ static int get_next_command(struct fsg_dev *fsg) | |||
3061 | 3021 | ||
3062 | /* Wait for the CBW to arrive */ | 3022 | /* Wait for the CBW to arrive */ |
3063 | while (bh->state != BUF_STATE_FULL) { | 3023 | while (bh->state != BUF_STATE_FULL) { |
3064 | if ((rc = sleep_thread(fsg)) != 0) | 3024 | rc = sleep_thread(fsg); |
3025 | if (rc) | ||
3065 | return rc; | 3026 | return rc; |
3066 | } | 3027 | } |
3067 | smp_rmb(); | 3028 | smp_rmb(); |
3068 | rc = received_cbw(fsg, bh); | 3029 | rc = received_cbw(fsg, bh); |
3069 | bh->state = BUF_STATE_EMPTY; | 3030 | bh->state = BUF_STATE_EMPTY; |
@@ -3072,9 +3033,10 @@ static int get_next_command(struct fsg_dev *fsg) | |||
3072 | 3033 | ||
3073 | /* Wait for the next command to arrive */ | 3034 | /* Wait for the next command to arrive */ |
3074 | while (fsg->cbbuf_cmnd_size == 0) { | 3035 | while (fsg->cbbuf_cmnd_size == 0) { |
3075 | if ((rc = sleep_thread(fsg)) != 0) | 3036 | rc = sleep_thread(fsg); |
3037 | if (rc) | ||
3076 | return rc; | 3038 | return rc; |
3077 | } | 3039 | } |
3078 | 3040 | ||
3079 | /* Is the previous status interrupt request still busy? | 3041 | /* Is the previous status interrupt request still busy? |
3080 | * The host is allowed to skip reading the status, | 3042 | * The host is allowed to skip reading the status, |
@@ -3595,7 +3557,8 @@ static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char * | |||
3595 | return sprintf(buf, "%d\n", curlun->ro); | 3557 | return sprintf(buf, "%d\n", curlun->ro); |
3596 | } | 3558 | } |
3597 | 3559 | ||
3598 | static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf) | 3560 | static ssize_t show_file(struct device *dev, struct device_attribute *attr, |
3561 | char *buf) | ||
3599 | { | 3562 | { |
3600 | struct lun *curlun = dev_to_lun(dev); | 3563 | struct lun *curlun = dev_to_lun(dev); |
3601 | struct fsg_dev *fsg = dev_get_drvdata(dev); | 3564 | struct fsg_dev *fsg = dev_get_drvdata(dev); |
@@ -3604,8 +3567,8 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char | |||
3604 | 3567 | ||
3605 | down_read(&fsg->filesem); | 3568 | down_read(&fsg->filesem); |
3606 | if (backing_file_is_open(curlun)) { // Get the complete pathname | 3569 | if (backing_file_is_open(curlun)) { // Get the complete pathname |
3607 | p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt, | 3570 | p = d_path(curlun->filp->f_path.dentry, |
3608 | buf, PAGE_SIZE - 1); | 3571 | curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1); |
3609 | if (IS_ERR(p)) | 3572 | if (IS_ERR(p)) |
3610 | rc = PTR_ERR(p); | 3573 | rc = PTR_ERR(p); |
3611 | else { | 3574 | else { |
@@ -3623,7 +3586,8 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char | |||
3623 | } | 3586 | } |
3624 | 3587 | ||
3625 | 3588 | ||
3626 | static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 3589 | static ssize_t store_ro(struct device *dev, struct device_attribute *attr, |
3590 | const char *buf, size_t count) | ||
3627 | { | 3591 | { |
3628 | ssize_t rc = count; | 3592 | ssize_t rc = count; |
3629 | struct lun *curlun = dev_to_lun(dev); | 3593 | struct lun *curlun = dev_to_lun(dev); |
@@ -3647,7 +3611,8 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const | |||
3647 | return rc; | 3611 | return rc; |
3648 | } | 3612 | } |
3649 | 3613 | ||
3650 | static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 3614 | static ssize_t store_file(struct device *dev, struct device_attribute *attr, |
3615 | const char *buf, size_t count) | ||
3651 | { | 3616 | { |
3652 | struct lun *curlun = dev_to_lun(dev); | 3617 | struct lun *curlun = dev_to_lun(dev); |
3653 | struct fsg_dev *fsg = dev_get_drvdata(dev); | 3618 | struct fsg_dev *fsg = dev_get_drvdata(dev); |
@@ -3859,7 +3824,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3859 | /* Find out how many LUNs there should be */ | 3824 | /* Find out how many LUNs there should be */ |
3860 | i = mod_data.nluns; | 3825 | i = mod_data.nluns; |
3861 | if (i == 0) | 3826 | if (i == 0) |
3862 | i = max(mod_data.num_filenames, 1); | 3827 | i = max(mod_data.num_filenames, 1u); |
3863 | if (i > MAX_LUNS) { | 3828 | if (i > MAX_LUNS) { |
3864 | ERROR(fsg, "invalid number of LUNs: %d\n", i); | 3829 | ERROR(fsg, "invalid number of LUNs: %d\n", i); |
3865 | rc = -EINVAL; | 3830 | rc = -EINVAL; |
@@ -3944,21 +3909,23 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3944 | intf_desc.bInterfaceProtocol = mod_data.transport_type; | 3909 | intf_desc.bInterfaceProtocol = mod_data.transport_type; |
3945 | fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL; | 3910 | fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL; |
3946 | 3911 | ||
3947 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 3912 | if (gadget_is_dualspeed(gadget)) { |
3948 | hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL; | 3913 | hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL; |
3949 | 3914 | ||
3950 | /* Assume ep0 uses the same maxpacket value for both speeds */ | 3915 | /* Assume ep0 uses the same maxpacket value for both speeds */ |
3951 | dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; | 3916 | dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; |
3952 | 3917 | ||
3953 | /* Assume that all endpoint addresses are the same for both speeds */ | 3918 | /* Assume endpoint addresses are the same for both speeds */ |
3954 | hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress; | 3919 | hs_bulk_in_desc.bEndpointAddress = |
3955 | hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress; | 3920 | fs_bulk_in_desc.bEndpointAddress; |
3956 | hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress; | 3921 | hs_bulk_out_desc.bEndpointAddress = |
3957 | #endif | 3922 | fs_bulk_out_desc.bEndpointAddress; |
3923 | hs_intr_in_desc.bEndpointAddress = | ||
3924 | fs_intr_in_desc.bEndpointAddress; | ||
3925 | } | ||
3958 | 3926 | ||
3959 | if (gadget->is_otg) { | 3927 | if (gadget_is_otg(gadget)) |
3960 | otg_desc.bmAttributes |= USB_OTG_HNP; | 3928 | otg_desc.bmAttributes |= USB_OTG_HNP; |
3961 | } | ||
3962 | 3929 | ||
3963 | rc = -ENOMEM; | 3930 | rc = -ENOMEM; |
3964 | 3931 | ||
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index d57bcfbc08a5..9bb7f64a85cd 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/device.h> | 36 | #include <linux/device.h> |
37 | #include <linux/usb/ch9.h> | 37 | #include <linux/usb/ch9.h> |
38 | #include <linux/usb_gadget.h> | 38 | #include <linux/usb/gadget.h> |
39 | #include <linux/usb/otg.h> | 39 | #include <linux/usb/otg.h> |
40 | #include <linux/dma-mapping.h> | 40 | #include <linux/dma-mapping.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
@@ -1090,14 +1090,11 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) | |||
1090 | */ | 1090 | */ |
1091 | static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) | 1091 | static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) |
1092 | { | 1092 | { |
1093 | #ifdef CONFIG_USB_OTG | ||
1094 | struct fsl_udc *udc; | 1093 | struct fsl_udc *udc; |
1095 | 1094 | ||
1096 | udc = container_of(gadget, struct fsl_udc, gadget); | 1095 | udc = container_of(gadget, struct fsl_udc, gadget); |
1097 | |||
1098 | if (udc->transceiver) | 1096 | if (udc->transceiver) |
1099 | return otg_set_power(udc->transceiver, mA); | 1097 | return otg_set_power(udc->transceiver, mA); |
1100 | #endif | ||
1101 | return -ENOTSUPP; | 1098 | return -ENOTSUPP; |
1102 | } | 1099 | } |
1103 | 1100 | ||
@@ -1120,7 +1117,7 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on) | |||
1120 | return 0; | 1117 | return 0; |
1121 | } | 1118 | } |
1122 | 1119 | ||
1123 | /* defined in usb_gadget.h */ | 1120 | /* defined in gadget.h */ |
1124 | static struct usb_gadget_ops fsl_gadget_ops = { | 1121 | static struct usb_gadget_ops fsl_gadget_ops = { |
1125 | .get_frame = fsl_get_frame, | 1122 | .get_frame = fsl_get_frame, |
1126 | .wakeup = fsl_wakeup, | 1123 | .wakeup = fsl_wakeup, |
@@ -1321,7 +1318,7 @@ static void setup_received_irq(struct fsl_udc *udc, | |||
1321 | | USB_TYPE_STANDARD)) { | 1318 | | USB_TYPE_STANDARD)) { |
1322 | /* Note: The driver has not include OTG support yet. | 1319 | /* Note: The driver has not include OTG support yet. |
1323 | * This will be set when OTG support is added */ | 1320 | * This will be set when OTG support is added */ |
1324 | if (!udc->gadget.is_otg) | 1321 | if (!gadget_is_otg(udc->gadget)) |
1325 | break; | 1322 | break; |
1326 | else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) | 1323 | else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) |
1327 | udc->gadget.b_hnp_enable = 1; | 1324 | udc->gadget.b_hnp_enable = 1; |
@@ -1330,6 +1327,8 @@ static void setup_received_irq(struct fsl_udc *udc, | |||
1330 | else if (setup->bRequest == | 1327 | else if (setup->bRequest == |
1331 | USB_DEVICE_A_ALT_HNP_SUPPORT) | 1328 | USB_DEVICE_A_ALT_HNP_SUPPORT) |
1332 | udc->gadget.a_alt_hnp_support = 1; | 1329 | udc->gadget.a_alt_hnp_support = 1; |
1330 | else | ||
1331 | break; | ||
1333 | rc = 0; | 1332 | rc = 0; |
1334 | } else | 1333 | } else |
1335 | break; | 1334 | break; |
@@ -1840,10 +1839,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1840 | if (!driver || driver != udc_controller->driver || !driver->unbind) | 1839 | if (!driver || driver != udc_controller->driver || !driver->unbind) |
1841 | return -EINVAL; | 1840 | return -EINVAL; |
1842 | 1841 | ||
1843 | #ifdef CONFIG_USB_OTG | ||
1844 | if (udc_controller->transceiver) | 1842 | if (udc_controller->transceiver) |
1845 | (void)otg_set_peripheral(udc_controller->transceiver, 0); | 1843 | (void)otg_set_peripheral(udc_controller->transceiver, 0); |
1846 | #endif | ||
1847 | 1844 | ||
1848 | /* stop DR, disable intr */ | 1845 | /* stop DR, disable intr */ |
1849 | dr_controller_stop(udc_controller); | 1846 | dr_controller_stop(udc_controller); |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 1c5aa49d7432..0689189550bc 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c | |||
@@ -18,17 +18,11 @@ | |||
18 | * http://www.usb.org/developers/devclass_docs/midi10.pdf | 18 | * http://www.usb.org/developers/devclass_docs/midi10.pdf |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #define DEBUG 1 | 21 | /* #define VERBOSE_DEBUG */ |
22 | // #define VERBOSE | ||
23 | 22 | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
26 | #include <linux/delay.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/utsname.h> | 24 | #include <linux/utsname.h> |
30 | #include <linux/device.h> | 25 | #include <linux/device.h> |
31 | #include <linux/moduleparam.h> | ||
32 | 26 | ||
33 | #include <sound/driver.h> | 27 | #include <sound/driver.h> |
34 | #include <sound/core.h> | 28 | #include <sound/core.h> |
@@ -36,7 +30,7 @@ | |||
36 | #include <sound/rawmidi.h> | 30 | #include <sound/rawmidi.h> |
37 | 31 | ||
38 | #include <linux/usb/ch9.h> | 32 | #include <linux/usb/ch9.h> |
39 | #include <linux/usb_gadget.h> | 33 | #include <linux/usb/gadget.h> |
40 | #include <linux/usb/audio.h> | 34 | #include <linux/usb/audio.h> |
41 | #include <linux/usb/midi.h> | 35 | #include <linux/usb/midi.h> |
42 | 36 | ||
@@ -139,30 +133,16 @@ struct gmidi_device { | |||
139 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); | 133 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req); |
140 | 134 | ||
141 | 135 | ||
142 | #define xprintk(d,level,fmt,args...) \ | 136 | #define DBG(d, fmt, args...) \ |
143 | dev_printk(level , &(d)->gadget->dev , fmt , ## args) | 137 | dev_dbg(&(d)->gadget->dev , fmt , ## args) |
144 | 138 | #define VDBG(d, fmt, args...) \ | |
145 | #ifdef DEBUG | 139 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
146 | #define DBG(dev,fmt,args...) \ | 140 | #define ERROR(d, fmt, args...) \ |
147 | xprintk(dev , KERN_DEBUG , fmt , ## args) | 141 | dev_err(&(d)->gadget->dev , fmt , ## args) |
148 | #else | 142 | #define WARN(d, fmt, args...) \ |
149 | #define DBG(dev,fmt,args...) \ | 143 | dev_warn(&(d)->gadget->dev , fmt , ## args) |
150 | do { } while (0) | 144 | #define INFO(d, fmt, args...) \ |
151 | #endif /* DEBUG */ | 145 | dev_info(&(d)->gadget->dev , fmt , ## args) |
152 | |||
153 | #ifdef VERBOSE | ||
154 | #define VDBG DBG | ||
155 | #else | ||
156 | #define VDBG(dev,fmt,args...) \ | ||
157 | do { } while (0) | ||
158 | #endif /* VERBOSE */ | ||
159 | |||
160 | #define ERROR(dev,fmt,args...) \ | ||
161 | xprintk(dev , KERN_ERR , fmt , ## args) | ||
162 | #define WARN(dev,fmt,args...) \ | ||
163 | xprintk(dev , KERN_WARNING , fmt , ## args) | ||
164 | #define INFO(dev,fmt,args...) \ | ||
165 | xprintk(dev , KERN_INFO , fmt , ## args) | ||
166 | 146 | ||
167 | 147 | ||
168 | static unsigned buflen = 256; | 148 | static unsigned buflen = 256; |
@@ -425,7 +405,7 @@ static int config_buf(struct usb_gadget *gadget, | |||
425 | return len; | 405 | return len; |
426 | } | 406 | } |
427 | 407 | ||
428 | static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length) | 408 | static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) |
429 | { | 409 | { |
430 | struct usb_request *req; | 410 | struct usb_request *req; |
431 | 411 | ||
@@ -455,7 +435,7 @@ static const uint8_t gmidi_cin_length[] = { | |||
455 | * Receives a chunk of MIDI data. | 435 | * Receives a chunk of MIDI data. |
456 | */ | 436 | */ |
457 | static void gmidi_read_data(struct usb_ep *ep, int cable, | 437 | static void gmidi_read_data(struct usb_ep *ep, int cable, |
458 | uint8_t* data, int length) | 438 | uint8_t *data, int length) |
459 | { | 439 | { |
460 | struct gmidi_device *dev = ep->driver_data; | 440 | struct gmidi_device *dev = ep->driver_data; |
461 | /* cable is ignored, because for now we only have one. */ | 441 | /* cable is ignored, because for now we only have one. */ |
@@ -541,7 +521,7 @@ static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags) | |||
541 | { | 521 | { |
542 | int err = 0; | 522 | int err = 0; |
543 | struct usb_request *req; | 523 | struct usb_request *req; |
544 | struct usb_ep* ep; | 524 | struct usb_ep *ep; |
545 | unsigned i; | 525 | unsigned i; |
546 | 526 | ||
547 | err = usb_ep_enable(dev->in_ep, &bulk_in_desc); | 527 | err = usb_ep_enable(dev->in_ep, &bulk_in_desc); |
@@ -628,7 +608,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) | |||
628 | 608 | ||
629 | if (gadget_is_sa1100(gadget) && dev->config) { | 609 | if (gadget_is_sa1100(gadget) && dev->config) { |
630 | /* tx fifo is full, but we can't clear it...*/ | 610 | /* tx fifo is full, but we can't clear it...*/ |
631 | INFO(dev, "can't change configurations\n"); | 611 | ERROR(dev, "can't change configurations\n"); |
632 | return -ESPIPE; | 612 | return -ESPIPE; |
633 | } | 613 | } |
634 | gmidi_reset_config(dev); | 614 | gmidi_reset_config(dev); |
@@ -843,7 +823,7 @@ static void gmidi_disconnect(struct usb_gadget *gadget) | |||
843 | static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget) | 823 | static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget) |
844 | { | 824 | { |
845 | struct gmidi_device *dev = get_gadget_data(gadget); | 825 | struct gmidi_device *dev = get_gadget_data(gadget); |
846 | struct snd_card* card; | 826 | struct snd_card *card; |
847 | 827 | ||
848 | DBG(dev, "unbind\n"); | 828 | DBG(dev, "unbind\n"); |
849 | 829 | ||
@@ -867,12 +847,12 @@ static int gmidi_snd_free(struct snd_device *device) | |||
867 | return 0; | 847 | return 0; |
868 | } | 848 | } |
869 | 849 | ||
870 | static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0, | 850 | static void gmidi_transmit_packet(struct usb_request *req, uint8_t p0, |
871 | uint8_t p1, uint8_t p2, uint8_t p3) | 851 | uint8_t p1, uint8_t p2, uint8_t p3) |
872 | { | 852 | { |
873 | unsigned length = req->length; | 853 | unsigned length = req->length; |
854 | u8 *buf = (u8 *)req->buf + length; | ||
874 | 855 | ||
875 | uint8_t* buf = (uint8_t*)req->buf + length; | ||
876 | buf[0] = p0; | 856 | buf[0] = p0; |
877 | buf[1] = p1; | 857 | buf[1] = p1; |
878 | buf[2] = p2; | 858 | buf[2] = p2; |
@@ -883,8 +863,8 @@ static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0, | |||
883 | /* | 863 | /* |
884 | * Converts MIDI commands to USB MIDI packets. | 864 | * Converts MIDI commands to USB MIDI packets. |
885 | */ | 865 | */ |
886 | static void gmidi_transmit_byte(struct usb_request* req, | 866 | static void gmidi_transmit_byte(struct usb_request *req, |
887 | struct gmidi_in_port* port, uint8_t b) | 867 | struct gmidi_in_port *port, uint8_t b) |
888 | { | 868 | { |
889 | uint8_t p0 = port->cable; | 869 | uint8_t p0 = port->cable; |
890 | 870 | ||
@@ -981,10 +961,10 @@ static void gmidi_transmit_byte(struct usb_request* req, | |||
981 | } | 961 | } |
982 | } | 962 | } |
983 | 963 | ||
984 | static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req) | 964 | static void gmidi_transmit(struct gmidi_device *dev, struct usb_request *req) |
985 | { | 965 | { |
986 | struct usb_ep* ep = dev->in_ep; | 966 | struct usb_ep *ep = dev->in_ep; |
987 | struct gmidi_in_port* port = &dev->in_port; | 967 | struct gmidi_in_port *port = &dev->in_port; |
988 | 968 | ||
989 | if (!ep) { | 969 | if (!ep) { |
990 | return; | 970 | return; |
@@ -1020,14 +1000,14 @@ static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req) | |||
1020 | 1000 | ||
1021 | static void gmidi_in_tasklet(unsigned long data) | 1001 | static void gmidi_in_tasklet(unsigned long data) |
1022 | { | 1002 | { |
1023 | struct gmidi_device* dev = (struct gmidi_device*)data; | 1003 | struct gmidi_device *dev = (struct gmidi_device *)data; |
1024 | 1004 | ||
1025 | gmidi_transmit(dev, NULL); | 1005 | gmidi_transmit(dev, NULL); |
1026 | } | 1006 | } |
1027 | 1007 | ||
1028 | static int gmidi_in_open(struct snd_rawmidi_substream *substream) | 1008 | static int gmidi_in_open(struct snd_rawmidi_substream *substream) |
1029 | { | 1009 | { |
1030 | struct gmidi_device* dev = substream->rmidi->private_data; | 1010 | struct gmidi_device *dev = substream->rmidi->private_data; |
1031 | 1011 | ||
1032 | VDBG(dev, "gmidi_in_open\n"); | 1012 | VDBG(dev, "gmidi_in_open\n"); |
1033 | dev->in_substream = substream; | 1013 | dev->in_substream = substream; |
@@ -1037,13 +1017,15 @@ static int gmidi_in_open(struct snd_rawmidi_substream *substream) | |||
1037 | 1017 | ||
1038 | static int gmidi_in_close(struct snd_rawmidi_substream *substream) | 1018 | static int gmidi_in_close(struct snd_rawmidi_substream *substream) |
1039 | { | 1019 | { |
1020 | struct gmidi_device *dev = substream->rmidi->private_data; | ||
1021 | |||
1040 | VDBG(dev, "gmidi_in_close\n"); | 1022 | VDBG(dev, "gmidi_in_close\n"); |
1041 | return 0; | 1023 | return 0; |
1042 | } | 1024 | } |
1043 | 1025 | ||
1044 | static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) | 1026 | static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) |
1045 | { | 1027 | { |
1046 | struct gmidi_device* dev = substream->rmidi->private_data; | 1028 | struct gmidi_device *dev = substream->rmidi->private_data; |
1047 | 1029 | ||
1048 | VDBG(dev, "gmidi_in_trigger %d\n", up); | 1030 | VDBG(dev, "gmidi_in_trigger %d\n", up); |
1049 | dev->in_port.active = up; | 1031 | dev->in_port.active = up; |
@@ -1054,7 +1036,7 @@ static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up) | |||
1054 | 1036 | ||
1055 | static int gmidi_out_open(struct snd_rawmidi_substream *substream) | 1037 | static int gmidi_out_open(struct snd_rawmidi_substream *substream) |
1056 | { | 1038 | { |
1057 | struct gmidi_device* dev = substream->rmidi->private_data; | 1039 | struct gmidi_device *dev = substream->rmidi->private_data; |
1058 | 1040 | ||
1059 | VDBG(dev, "gmidi_out_open\n"); | 1041 | VDBG(dev, "gmidi_out_open\n"); |
1060 | dev->out_substream = substream; | 1042 | dev->out_substream = substream; |
@@ -1063,13 +1045,15 @@ static int gmidi_out_open(struct snd_rawmidi_substream *substream) | |||
1063 | 1045 | ||
1064 | static int gmidi_out_close(struct snd_rawmidi_substream *substream) | 1046 | static int gmidi_out_close(struct snd_rawmidi_substream *substream) |
1065 | { | 1047 | { |
1048 | struct gmidi_device *dev = substream->rmidi->private_data; | ||
1049 | |||
1066 | VDBG(dev, "gmidi_out_close\n"); | 1050 | VDBG(dev, "gmidi_out_close\n"); |
1067 | return 0; | 1051 | return 0; |
1068 | } | 1052 | } |
1069 | 1053 | ||
1070 | static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up) | 1054 | static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up) |
1071 | { | 1055 | { |
1072 | struct gmidi_device* dev = substream->rmidi->private_data; | 1056 | struct gmidi_device *dev = substream->rmidi->private_data; |
1073 | 1057 | ||
1074 | VDBG(dev, "gmidi_out_trigger %d\n", up); | 1058 | VDBG(dev, "gmidi_out_trigger %d\n", up); |
1075 | if (up) { | 1059 | if (up) { |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 349b8166f34a..2ec9d196a8cf 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/device.h> | 38 | #include <linux/device.h> |
39 | #include <linux/usb/ch9.h> | 39 | #include <linux/usb/ch9.h> |
40 | #include <linux/usb_gadget.h> | 40 | #include <linux/usb/gadget.h> |
41 | 41 | ||
42 | #include <asm/byteorder.h> | 42 | #include <asm/byteorder.h> |
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 173004f60fea..47ef8bd58a00 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -20,8 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | // #define DEBUG /* data to help fault diagnosis */ | 23 | /* #define VERBOSE_DEBUG */ |
24 | // #define VERBOSE /* extra debug messages (success too) */ | ||
25 | 24 | ||
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -38,7 +37,7 @@ | |||
38 | #include <linux/moduleparam.h> | 37 | #include <linux/moduleparam.h> |
39 | 38 | ||
40 | #include <linux/usb/gadgetfs.h> | 39 | #include <linux/usb/gadgetfs.h> |
41 | #include <linux/usb_gadget.h> | 40 | #include <linux/usb/gadget.h> |
42 | 41 | ||
43 | 42 | ||
44 | /* | 43 | /* |
@@ -253,7 +252,7 @@ static const char *CHIP; | |||
253 | do { } while (0) | 252 | do { } while (0) |
254 | #endif /* DEBUG */ | 253 | #endif /* DEBUG */ |
255 | 254 | ||
256 | #ifdef VERBOSE | 255 | #ifdef VERBOSE_DEBUG |
257 | #define VDEBUG DBG | 256 | #define VDEBUG DBG |
258 | #else | 257 | #else |
259 | #define VDEBUG(dev,fmt,args...) \ | 258 | #define VDEBUG(dev,fmt,args...) \ |
@@ -1010,11 +1009,12 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) | |||
1010 | /* assume that was SET_CONFIGURATION */ | 1009 | /* assume that was SET_CONFIGURATION */ |
1011 | if (dev->current_config) { | 1010 | if (dev->current_config) { |
1012 | unsigned power; | 1011 | unsigned power; |
1013 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1012 | |
1014 | if (dev->gadget->speed == USB_SPEED_HIGH) | 1013 | if (gadget_is_dualspeed(dev->gadget) |
1014 | && (dev->gadget->speed | ||
1015 | == USB_SPEED_HIGH)) | ||
1015 | power = dev->hs_config->bMaxPower; | 1016 | power = dev->hs_config->bMaxPower; |
1016 | else | 1017 | else |
1017 | #endif | ||
1018 | power = dev->config->bMaxPower; | 1018 | power = dev->config->bMaxPower; |
1019 | usb_gadget_vbus_draw(dev->gadget, 2 * power); | 1019 | usb_gadget_vbus_draw(dev->gadget, 2 * power); |
1020 | } | 1020 | } |
@@ -1355,24 +1355,21 @@ static int | |||
1355 | config_buf (struct dev_data *dev, u8 type, unsigned index) | 1355 | config_buf (struct dev_data *dev, u8 type, unsigned index) |
1356 | { | 1356 | { |
1357 | int len; | 1357 | int len; |
1358 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1358 | int hs = 0; |
1359 | int hs; | ||
1360 | #endif | ||
1361 | 1359 | ||
1362 | /* only one configuration */ | 1360 | /* only one configuration */ |
1363 | if (index > 0) | 1361 | if (index > 0) |
1364 | return -EINVAL; | 1362 | return -EINVAL; |
1365 | 1363 | ||
1366 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1364 | if (gadget_is_dualspeed(dev->gadget)) { |
1367 | hs = (dev->gadget->speed == USB_SPEED_HIGH); | 1365 | hs = (dev->gadget->speed == USB_SPEED_HIGH); |
1368 | if (type == USB_DT_OTHER_SPEED_CONFIG) | 1366 | if (type == USB_DT_OTHER_SPEED_CONFIG) |
1369 | hs = !hs; | 1367 | hs = !hs; |
1368 | } | ||
1370 | if (hs) { | 1369 | if (hs) { |
1371 | dev->req->buf = dev->hs_config; | 1370 | dev->req->buf = dev->hs_config; |
1372 | len = le16_to_cpu(dev->hs_config->wTotalLength); | 1371 | len = le16_to_cpu(dev->hs_config->wTotalLength); |
1373 | } else | 1372 | } else { |
1374 | #endif | ||
1375 | { | ||
1376 | dev->req->buf = dev->config; | 1373 | dev->req->buf = dev->config; |
1377 | len = le16_to_cpu(dev->config->wTotalLength); | 1374 | len = le16_to_cpu(dev->config->wTotalLength); |
1378 | } | 1375 | } |
@@ -1393,13 +1390,13 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1393 | spin_lock (&dev->lock); | 1390 | spin_lock (&dev->lock); |
1394 | dev->setup_abort = 0; | 1391 | dev->setup_abort = 0; |
1395 | if (dev->state == STATE_DEV_UNCONNECTED) { | 1392 | if (dev->state == STATE_DEV_UNCONNECTED) { |
1396 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1393 | if (gadget_is_dualspeed(gadget) |
1397 | if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == NULL) { | 1394 | && gadget->speed == USB_SPEED_HIGH |
1395 | && dev->hs_config == NULL) { | ||
1398 | spin_unlock(&dev->lock); | 1396 | spin_unlock(&dev->lock); |
1399 | ERROR (dev, "no high speed config??\n"); | 1397 | ERROR (dev, "no high speed config??\n"); |
1400 | return -EINVAL; | 1398 | return -EINVAL; |
1401 | } | 1399 | } |
1402 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | ||
1403 | 1400 | ||
1404 | dev->state = STATE_DEV_CONNECTED; | 1401 | dev->state = STATE_DEV_CONNECTED; |
1405 | dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; | 1402 | dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; |
@@ -1469,13 +1466,12 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1469 | // user mode expected to disable endpoints | 1466 | // user mode expected to disable endpoints |
1470 | } else { | 1467 | } else { |
1471 | u8 config, power; | 1468 | u8 config, power; |
1472 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1469 | |
1473 | if (gadget->speed == USB_SPEED_HIGH) { | 1470 | if (gadget_is_dualspeed(gadget) |
1471 | && gadget->speed == USB_SPEED_HIGH) { | ||
1474 | config = dev->hs_config->bConfigurationValue; | 1472 | config = dev->hs_config->bConfigurationValue; |
1475 | power = dev->hs_config->bMaxPower; | 1473 | power = dev->hs_config->bMaxPower; |
1476 | } else | 1474 | } else { |
1477 | #endif | ||
1478 | { | ||
1479 | config = dev->config->bConfigurationValue; | 1475 | config = dev->config->bConfigurationValue; |
1480 | power = dev->config->bMaxPower; | 1476 | power = dev->config->bMaxPower; |
1481 | } | 1477 | } |
diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h index b3fe197e1eeb..1ecfd6366b9a 100644 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ b/drivers/usb/gadget/lh7a40x_udc.h | |||
@@ -50,7 +50,7 @@ | |||
50 | #include <asm/hardware.h> | 50 | #include <asm/hardware.h> |
51 | 51 | ||
52 | #include <linux/usb/ch9.h> | 52 | #include <linux/usb/ch9.h> |
53 | #include <linux/usb_gadget.h> | 53 | #include <linux/usb/gadget.h> |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Memory map | 56 | * Memory map |
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 4b27d12f049d..ebc5536aa271 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | 28 | ||
29 | #include <linux/usb/ch9.h> | 29 | #include <linux/usb/ch9.h> |
30 | #include <linux/usb_gadget.h> | 30 | #include <linux/usb/gadget.h> |
31 | 31 | ||
32 | #include "m66592-udc.h" | 32 | #include "m66592-udc.h" |
33 | 33 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index c3d364ecd4f8..d5d473f8144b 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #include <linux/moduleparam.h> | 62 | #include <linux/moduleparam.h> |
63 | #include <linux/device.h> | 63 | #include <linux/device.h> |
64 | #include <linux/usb/ch9.h> | 64 | #include <linux/usb/ch9.h> |
65 | #include <linux/usb_gadget.h> | 65 | #include <linux/usb/gadget.h> |
66 | 66 | ||
67 | #include <asm/byteorder.h> | 67 | #include <asm/byteorder.h> |
68 | #include <asm/io.h> | 68 | #include <asm/io.h> |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 9b0f0925dddf..87c4f50dfb61 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
39 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
40 | #include <linux/usb/ch9.h> | 40 | #include <linux/usb/ch9.h> |
41 | #include <linux/usb_gadget.h> | 41 | #include <linux/usb/gadget.h> |
42 | #include <linux/usb/otg.h> | 42 | #include <linux/usb/otg.h> |
43 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
44 | #include <linux/clk.h> | 44 | #include <linux/clk.h> |
@@ -1241,19 +1241,15 @@ static void pullup_enable(struct omap_udc *udc) | |||
1241 | udc->gadget.dev.parent->power.power_state = PMSG_ON; | 1241 | udc->gadget.dev.parent->power.power_state = PMSG_ON; |
1242 | udc->gadget.dev.power.power_state = PMSG_ON; | 1242 | udc->gadget.dev.power.power_state = PMSG_ON; |
1243 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; | 1243 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; |
1244 | #ifndef CONFIG_USB_OTG | 1244 | if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) |
1245 | if (!cpu_is_omap15xx()) | ||
1246 | OTG_CTRL_REG |= OTG_BSESSVLD; | 1245 | OTG_CTRL_REG |= OTG_BSESSVLD; |
1247 | #endif | ||
1248 | UDC_IRQ_EN_REG = UDC_DS_CHG_IE; | 1246 | UDC_IRQ_EN_REG = UDC_DS_CHG_IE; |
1249 | } | 1247 | } |
1250 | 1248 | ||
1251 | static void pullup_disable(struct omap_udc *udc) | 1249 | static void pullup_disable(struct omap_udc *udc) |
1252 | { | 1250 | { |
1253 | #ifndef CONFIG_USB_OTG | 1251 | if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) |
1254 | if (!cpu_is_omap15xx()) | ||
1255 | OTG_CTRL_REG &= ~OTG_BSESSVLD; | 1252 | OTG_CTRL_REG &= ~OTG_BSESSVLD; |
1256 | #endif | ||
1257 | UDC_IRQ_EN_REG = UDC_DS_CHG_IE; | 1253 | UDC_IRQ_EN_REG = UDC_DS_CHG_IE; |
1258 | UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; | 1254 | UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; |
1259 | } | 1255 | } |
@@ -1390,7 +1386,7 @@ static void update_otg(struct omap_udc *udc) | |||
1390 | { | 1386 | { |
1391 | u16 devstat; | 1387 | u16 devstat; |
1392 | 1388 | ||
1393 | if (!udc->gadget.is_otg) | 1389 | if (!gadget_is_otg(udc->gadget)) |
1394 | return; | 1390 | return; |
1395 | 1391 | ||
1396 | if (OTG_CTRL_REG & OTG_ID) | 1392 | if (OTG_CTRL_REG & OTG_ID) |
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1407ad1c8128..3e715082de36 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #include <asm/hardware.h> | 54 | #include <asm/hardware.h> |
55 | 55 | ||
56 | #include <linux/usb/ch9.h> | 56 | #include <linux/usb/ch9.h> |
57 | #include <linux/usb_gadget.h> | 57 | #include <linux/usb/gadget.h> |
58 | 58 | ||
59 | #include <asm/mach/udc_pxa2xx.h> | 59 | #include <asm/mach/udc_pxa2xx.h> |
60 | 60 | ||
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 0be80c635c48..e3e90f8a75e7 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
43 | 43 | ||
44 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
45 | #include <linux/usb_gadget.h> | 45 | #include <linux/usb/gadget.h> |
46 | 46 | ||
47 | #include <asm/byteorder.h> | 47 | #include <asm/byteorder.h> |
48 | #include <asm/io.h> | 48 | #include <asm/io.h> |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ce4d2e09633d..f5738eb8e765 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -17,34 +17,15 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
22 | #include <linux/delay.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/utsname.h> | 21 | #include <linux/utsname.h> |
31 | #include <linux/wait.h> | ||
32 | #include <linux/proc_fs.h> | ||
33 | #include <linux/device.h> | 22 | #include <linux/device.h> |
34 | #include <linux/tty.h> | 23 | #include <linux/tty.h> |
35 | #include <linux/tty_flip.h> | 24 | #include <linux/tty_flip.h> |
36 | #include <linux/mutex.h> | ||
37 | |||
38 | #include <asm/byteorder.h> | ||
39 | #include <asm/io.h> | ||
40 | #include <asm/irq.h> | ||
41 | #include <asm/system.h> | ||
42 | #include <asm/unaligned.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | 25 | ||
45 | #include <linux/usb/ch9.h> | 26 | #include <linux/usb/ch9.h> |
46 | #include <linux/usb/cdc.h> | 27 | #include <linux/usb/cdc.h> |
47 | #include <linux/usb_gadget.h> | 28 | #include <linux/usb/gadget.h> |
48 | 29 | ||
49 | #include "gadget_chips.h" | 30 | #include "gadget_chips.h" |
50 | 31 | ||
@@ -89,30 +70,29 @@ | |||
89 | #define GS_DEFAULT_PARITY USB_CDC_NO_PARITY | 70 | #define GS_DEFAULT_PARITY USB_CDC_NO_PARITY |
90 | #define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS | 71 | #define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS |
91 | 72 | ||
92 | /* select highspeed/fullspeed, hiding highspeed if not configured */ | 73 | /* maxpacket and other transfer characteristics vary by speed. */ |
93 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 74 | static inline struct usb_endpoint_descriptor * |
94 | #define GS_SPEED_SELECT(is_hs,hs,fs) ((is_hs) ? (hs) : (fs)) | 75 | choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, |
95 | #else | 76 | struct usb_endpoint_descriptor *fs) |
96 | #define GS_SPEED_SELECT(is_hs,hs,fs) (fs) | 77 | { |
97 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | 78 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) |
79 | return hs; | ||
80 | return fs; | ||
81 | } | ||
82 | |||
98 | 83 | ||
99 | /* debug settings */ | 84 | /* debug settings */ |
100 | #ifdef GS_DEBUG | 85 | #ifdef DEBUG |
101 | static int debug = 1; | 86 | static int debug = 1; |
87 | #else | ||
88 | #define debug 0 | ||
89 | #endif | ||
102 | 90 | ||
103 | #define gs_debug(format, arg...) \ | 91 | #define gs_debug(format, arg...) \ |
104 | do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0) | 92 | do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0) |
105 | #define gs_debug_level(level, format, arg...) \ | 93 | #define gs_debug_level(level, format, arg...) \ |
106 | do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0) | 94 | do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0) |
107 | 95 | ||
108 | #else | ||
109 | |||
110 | #define gs_debug(format, arg...) \ | ||
111 | do { } while(0) | ||
112 | #define gs_debug_level(level, format, arg...) \ | ||
113 | do { } while(0) | ||
114 | |||
115 | #endif /* GS_DEBUG */ | ||
116 | 96 | ||
117 | /* Thanks to NetChip Technologies for donating this product ID. | 97 | /* Thanks to NetChip Technologies for donating this product ID. |
118 | * | 98 | * |
@@ -147,10 +127,10 @@ struct gs_req_entry { | |||
147 | 127 | ||
148 | /* the port structure holds info for each port, one for each minor number */ | 128 | /* the port structure holds info for each port, one for each minor number */ |
149 | struct gs_port { | 129 | struct gs_port { |
150 | struct gs_dev *port_dev; /* pointer to device struct */ | 130 | struct gs_dev *port_dev; /* pointer to device struct */ |
151 | struct tty_struct *port_tty; /* pointer to tty struct */ | 131 | struct tty_struct *port_tty; /* pointer to tty struct */ |
152 | spinlock_t port_lock; | 132 | spinlock_t port_lock; |
153 | int port_num; | 133 | int port_num; |
154 | int port_open_count; | 134 | int port_open_count; |
155 | int port_in_use; /* open/close in progress */ | 135 | int port_in_use; /* open/close in progress */ |
156 | wait_queue_head_t port_write_wait;/* waiting to write */ | 136 | wait_queue_head_t port_write_wait;/* waiting to write */ |
@@ -188,7 +168,7 @@ static void __exit gs_module_exit(void); | |||
188 | /* tty driver */ | 168 | /* tty driver */ |
189 | static int gs_open(struct tty_struct *tty, struct file *file); | 169 | static int gs_open(struct tty_struct *tty, struct file *file); |
190 | static void gs_close(struct tty_struct *tty, struct file *file); | 170 | static void gs_close(struct tty_struct *tty, struct file *file); |
191 | static int gs_write(struct tty_struct *tty, | 171 | static int gs_write(struct tty_struct *tty, |
192 | const unsigned char *buf, int count); | 172 | const unsigned char *buf, int count); |
193 | static void gs_put_char(struct tty_struct *tty, unsigned char ch); | 173 | static void gs_put_char(struct tty_struct *tty, unsigned char ch); |
194 | static void gs_flush_chars(struct tty_struct *tty); | 174 | static void gs_flush_chars(struct tty_struct *tty); |
@@ -222,7 +202,7 @@ static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req); | |||
222 | static void gs_disconnect(struct usb_gadget *gadget); | 202 | static void gs_disconnect(struct usb_gadget *gadget); |
223 | static int gs_set_config(struct gs_dev *dev, unsigned config); | 203 | static int gs_set_config(struct gs_dev *dev, unsigned config); |
224 | static void gs_reset_config(struct gs_dev *dev); | 204 | static void gs_reset_config(struct gs_dev *dev); |
225 | static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | 205 | static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, |
226 | u8 type, unsigned int index, int is_otg); | 206 | u8 type, unsigned int index, int is_otg); |
227 | 207 | ||
228 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, | 208 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, |
@@ -415,18 +395,18 @@ static const struct usb_cdc_header_desc gs_header_desc = { | |||
415 | }; | 395 | }; |
416 | 396 | ||
417 | static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = { | 397 | static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = { |
418 | .bLength = sizeof(gs_call_mgmt_descriptor), | 398 | .bLength = sizeof(gs_call_mgmt_descriptor), |
419 | .bDescriptorType = USB_DT_CS_INTERFACE, | 399 | .bDescriptorType = USB_DT_CS_INTERFACE, |
420 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, | 400 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, |
421 | .bmCapabilities = 0, | 401 | .bmCapabilities = 0, |
422 | .bDataInterface = 1, /* index of data interface */ | 402 | .bDataInterface = 1, /* index of data interface */ |
423 | }; | 403 | }; |
424 | 404 | ||
425 | static struct usb_cdc_acm_descriptor gs_acm_descriptor = { | 405 | static struct usb_cdc_acm_descriptor gs_acm_descriptor = { |
426 | .bLength = sizeof(gs_acm_descriptor), | 406 | .bLength = sizeof(gs_acm_descriptor), |
427 | .bDescriptorType = USB_DT_CS_INTERFACE, | 407 | .bDescriptorType = USB_DT_CS_INTERFACE, |
428 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | 408 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
429 | .bmCapabilities = 0, | 409 | .bmCapabilities = 0, |
430 | }; | 410 | }; |
431 | 411 | ||
432 | static const struct usb_cdc_union_desc gs_union_desc = { | 412 | static const struct usb_cdc_union_desc gs_union_desc = { |
@@ -436,7 +416,7 @@ static const struct usb_cdc_union_desc gs_union_desc = { | |||
436 | .bMasterInterface0 = 0, /* index of control interface */ | 416 | .bMasterInterface0 = 0, /* index of control interface */ |
437 | .bSlaveInterface0 = 1, /* index of data interface */ | 417 | .bSlaveInterface0 = 1, /* index of data interface */ |
438 | }; | 418 | }; |
439 | 419 | ||
440 | static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = { | 420 | static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = { |
441 | .bLength = USB_DT_ENDPOINT_SIZE, | 421 | .bLength = USB_DT_ENDPOINT_SIZE, |
442 | .bDescriptorType = USB_DT_ENDPOINT, | 422 | .bDescriptorType = USB_DT_ENDPOINT, |
@@ -482,7 +462,6 @@ static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = { | |||
482 | NULL, | 462 | NULL, |
483 | }; | 463 | }; |
484 | 464 | ||
485 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
486 | static struct usb_endpoint_descriptor gs_highspeed_notify_desc = { | 465 | static struct usb_endpoint_descriptor gs_highspeed_notify_desc = { |
487 | .bLength = USB_DT_ENDPOINT_SIZE, | 466 | .bLength = USB_DT_ENDPOINT_SIZE, |
488 | .bDescriptorType = USB_DT_ENDPOINT, | 467 | .bDescriptorType = USB_DT_ENDPOINT, |
@@ -536,15 +515,13 @@ static const struct usb_descriptor_header *gs_acm_highspeed_function[] = { | |||
536 | NULL, | 515 | NULL, |
537 | }; | 516 | }; |
538 | 517 | ||
539 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | ||
540 | |||
541 | 518 | ||
542 | /* Module */ | 519 | /* Module */ |
543 | MODULE_DESCRIPTION(GS_LONG_NAME); | 520 | MODULE_DESCRIPTION(GS_LONG_NAME); |
544 | MODULE_AUTHOR("Al Borchers"); | 521 | MODULE_AUTHOR("Al Borchers"); |
545 | MODULE_LICENSE("GPL"); | 522 | MODULE_LICENSE("GPL"); |
546 | 523 | ||
547 | #ifdef GS_DEBUG | 524 | #ifdef DEBUG |
548 | module_param(debug, int, S_IRUGO|S_IWUSR); | 525 | module_param(debug, int, S_IRUGO|S_IWUSR); |
549 | MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); | 526 | MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); |
550 | #endif | 527 | #endif |
@@ -915,7 +892,8 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch) | |||
915 | return; | 892 | return; |
916 | } | 893 | } |
917 | 894 | ||
918 | gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2)); | 895 | gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n", |
896 | port->port_num, tty, ch, __builtin_return_address(0)); | ||
919 | 897 | ||
920 | spin_lock_irqsave(&port->port_lock, flags); | 898 | spin_lock_irqsave(&port->port_lock, flags); |
921 | 899 | ||
@@ -1116,7 +1094,11 @@ static int gs_send(struct gs_dev *dev) | |||
1116 | len = gs_send_packet(dev, req->buf, ep->maxpacket); | 1094 | len = gs_send_packet(dev, req->buf, ep->maxpacket); |
1117 | 1095 | ||
1118 | if (len > 0) { | 1096 | if (len > 0) { |
1119 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); | 1097 | gs_debug_level(3, "gs_send: len=%d, 0x%2.2x " |
1098 | "0x%2.2x 0x%2.2x ...\n", len, | ||
1099 | *((unsigned char *)req->buf), | ||
1100 | *((unsigned char *)req->buf+1), | ||
1101 | *((unsigned char *)req->buf+2)); | ||
1120 | list_del(&req_entry->re_entry); | 1102 | list_del(&req_entry->re_entry); |
1121 | req->length = len; | 1103 | req->length = len; |
1122 | spin_unlock_irqrestore(&dev->dev_lock, flags); | 1104 | spin_unlock_irqrestore(&dev->dev_lock, flags); |
@@ -1269,7 +1251,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) | |||
1269 | 1251 | ||
1270 | switch(req->status) { | 1252 | switch(req->status) { |
1271 | case 0: | 1253 | case 0: |
1272 | /* normal completion */ | 1254 | /* normal completion */ |
1273 | gs_recv_packet(dev, req->buf, req->actual); | 1255 | gs_recv_packet(dev, req->buf, req->actual); |
1274 | requeue: | 1256 | requeue: |
1275 | req->length = ep->maxpacket; | 1257 | req->length = ep->maxpacket; |
@@ -1406,23 +1388,24 @@ static int __init gs_bind(struct usb_gadget *gadget) | |||
1406 | ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; | 1388 | ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; |
1407 | gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; | 1389 | gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; |
1408 | 1390 | ||
1409 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1391 | if (gadget_is_dualspeed(gadget)) { |
1410 | gs_qualifier_desc.bDeviceClass = use_acm | 1392 | gs_qualifier_desc.bDeviceClass = use_acm |
1411 | ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; | 1393 | ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; |
1412 | /* assume ep0 uses the same packet size for both speeds */ | 1394 | /* assume ep0 uses the same packet size for both speeds */ |
1413 | gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0; | 1395 | gs_qualifier_desc.bMaxPacketSize0 = |
1414 | /* assume endpoints are dual-speed */ | 1396 | gs_device_desc.bMaxPacketSize0; |
1415 | gs_highspeed_notify_desc.bEndpointAddress = | 1397 | /* assume endpoints are dual-speed */ |
1416 | gs_fullspeed_notify_desc.bEndpointAddress; | 1398 | gs_highspeed_notify_desc.bEndpointAddress = |
1417 | gs_highspeed_in_desc.bEndpointAddress = | 1399 | gs_fullspeed_notify_desc.bEndpointAddress; |
1418 | gs_fullspeed_in_desc.bEndpointAddress; | 1400 | gs_highspeed_in_desc.bEndpointAddress = |
1419 | gs_highspeed_out_desc.bEndpointAddress = | 1401 | gs_fullspeed_in_desc.bEndpointAddress; |
1420 | gs_fullspeed_out_desc.bEndpointAddress; | 1402 | gs_highspeed_out_desc.bEndpointAddress = |
1421 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | 1403 | gs_fullspeed_out_desc.bEndpointAddress; |
1404 | } | ||
1422 | 1405 | ||
1423 | usb_gadget_set_selfpowered(gadget); | 1406 | usb_gadget_set_selfpowered(gadget); |
1424 | 1407 | ||
1425 | if (gadget->is_otg) { | 1408 | if (gadget_is_otg(gadget)) { |
1426 | gs_otg_descriptor.bmAttributes |= USB_OTG_HNP, | 1409 | gs_otg_descriptor.bmAttributes |= USB_OTG_HNP, |
1427 | gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 1410 | gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
1428 | gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 1411 | gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
@@ -1487,6 +1470,12 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) | |||
1487 | dev->dev_ctrl_req = NULL; | 1470 | dev->dev_ctrl_req = NULL; |
1488 | } | 1471 | } |
1489 | gs_free_ports(dev); | 1472 | gs_free_ports(dev); |
1473 | if (dev->dev_notify_ep) | ||
1474 | usb_ep_disable(dev->dev_notify_ep); | ||
1475 | if (dev->dev_in_ep) | ||
1476 | usb_ep_disable(dev->dev_in_ep); | ||
1477 | if (dev->dev_out_ep) | ||
1478 | usb_ep_disable(dev->dev_out_ep); | ||
1490 | kfree(dev); | 1479 | kfree(dev); |
1491 | set_gadget_data(gadget, NULL); | 1480 | set_gadget_data(gadget, NULL); |
1492 | } | 1481 | } |
@@ -1570,9 +1559,8 @@ static int gs_setup_standard(struct usb_gadget *gadget, | |||
1570 | memcpy(req->buf, &gs_device_desc, ret); | 1559 | memcpy(req->buf, &gs_device_desc, ret); |
1571 | break; | 1560 | break; |
1572 | 1561 | ||
1573 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
1574 | case USB_DT_DEVICE_QUALIFIER: | 1562 | case USB_DT_DEVICE_QUALIFIER: |
1575 | if (!gadget->is_dualspeed) | 1563 | if (!gadget_is_dualspeed(gadget)) |
1576 | break; | 1564 | break; |
1577 | ret = min(wLength, | 1565 | ret = min(wLength, |
1578 | (u16)sizeof(struct usb_qualifier_descriptor)); | 1566 | (u16)sizeof(struct usb_qualifier_descriptor)); |
@@ -1580,14 +1568,13 @@ static int gs_setup_standard(struct usb_gadget *gadget, | |||
1580 | break; | 1568 | break; |
1581 | 1569 | ||
1582 | case USB_DT_OTHER_SPEED_CONFIG: | 1570 | case USB_DT_OTHER_SPEED_CONFIG: |
1583 | if (!gadget->is_dualspeed) | 1571 | if (!gadget_is_dualspeed(gadget)) |
1584 | break; | 1572 | break; |
1585 | /* fall through */ | 1573 | /* fall through */ |
1586 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | ||
1587 | case USB_DT_CONFIG: | 1574 | case USB_DT_CONFIG: |
1588 | ret = gs_build_config_buf(req->buf, gadget->speed, | 1575 | ret = gs_build_config_buf(req->buf, gadget, |
1589 | wValue >> 8, wValue & 0xff, | 1576 | wValue >> 8, wValue & 0xff, |
1590 | gadget->is_otg); | 1577 | gadget_is_otg(gadget)); |
1591 | if (ret >= 0) | 1578 | if (ret >= 0) |
1592 | ret = min(wLength, (u16)ret); | 1579 | ret = min(wLength, (u16)ret); |
1593 | break; | 1580 | break; |
@@ -1827,8 +1814,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) | |||
1827 | 1814 | ||
1828 | if (EP_NOTIFY_NAME | 1815 | if (EP_NOTIFY_NAME |
1829 | && strcmp(ep->name, EP_NOTIFY_NAME) == 0) { | 1816 | && strcmp(ep->name, EP_NOTIFY_NAME) == 0) { |
1830 | ep_desc = GS_SPEED_SELECT( | 1817 | ep_desc = choose_ep_desc(gadget, |
1831 | gadget->speed == USB_SPEED_HIGH, | ||
1832 | &gs_highspeed_notify_desc, | 1818 | &gs_highspeed_notify_desc, |
1833 | &gs_fullspeed_notify_desc); | 1819 | &gs_fullspeed_notify_desc); |
1834 | ret = usb_ep_enable(ep,ep_desc); | 1820 | ret = usb_ep_enable(ep,ep_desc); |
@@ -1844,9 +1830,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) | |||
1844 | } | 1830 | } |
1845 | 1831 | ||
1846 | else if (strcmp(ep->name, EP_IN_NAME) == 0) { | 1832 | else if (strcmp(ep->name, EP_IN_NAME) == 0) { |
1847 | ep_desc = GS_SPEED_SELECT( | 1833 | ep_desc = choose_ep_desc(gadget, |
1848 | gadget->speed == USB_SPEED_HIGH, | 1834 | &gs_highspeed_in_desc, |
1849 | &gs_highspeed_in_desc, | ||
1850 | &gs_fullspeed_in_desc); | 1835 | &gs_fullspeed_in_desc); |
1851 | ret = usb_ep_enable(ep,ep_desc); | 1836 | ret = usb_ep_enable(ep,ep_desc); |
1852 | if (ret == 0) { | 1837 | if (ret == 0) { |
@@ -1861,8 +1846,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) | |||
1861 | } | 1846 | } |
1862 | 1847 | ||
1863 | else if (strcmp(ep->name, EP_OUT_NAME) == 0) { | 1848 | else if (strcmp(ep->name, EP_OUT_NAME) == 0) { |
1864 | ep_desc = GS_SPEED_SELECT( | 1849 | ep_desc = choose_ep_desc(gadget, |
1865 | gadget->speed == USB_SPEED_HIGH, | ||
1866 | &gs_highspeed_out_desc, | 1850 | &gs_highspeed_out_desc, |
1867 | &gs_fullspeed_out_desc); | 1851 | &gs_fullspeed_out_desc); |
1868 | ret = usb_ep_enable(ep,ep_desc); | 1852 | ret = usb_ep_enable(ep,ep_desc); |
@@ -1981,11 +1965,11 @@ static void gs_reset_config(struct gs_dev *dev) | |||
1981 | * Builds the config descriptors in the given buffer and returns the | 1965 | * Builds the config descriptors in the given buffer and returns the |
1982 | * length, or a negative error number. | 1966 | * length, or a negative error number. |
1983 | */ | 1967 | */ |
1984 | static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | 1968 | static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, |
1985 | u8 type, unsigned int index, int is_otg) | 1969 | u8 type, unsigned int index, int is_otg) |
1986 | { | 1970 | { |
1987 | int len; | 1971 | int len; |
1988 | int high_speed; | 1972 | int high_speed = 0; |
1989 | const struct usb_config_descriptor *config_desc; | 1973 | const struct usb_config_descriptor *config_desc; |
1990 | const struct usb_descriptor_header **function; | 1974 | const struct usb_descriptor_header **function; |
1991 | 1975 | ||
@@ -1993,20 +1977,22 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | |||
1993 | return -EINVAL; | 1977 | return -EINVAL; |
1994 | 1978 | ||
1995 | /* other speed switches high and full speed */ | 1979 | /* other speed switches high and full speed */ |
1996 | high_speed = (speed == USB_SPEED_HIGH); | 1980 | if (gadget_is_dualspeed(g)) { |
1997 | if (type == USB_DT_OTHER_SPEED_CONFIG) | 1981 | high_speed = (g->speed == USB_SPEED_HIGH); |
1998 | high_speed = !high_speed; | 1982 | if (type == USB_DT_OTHER_SPEED_CONFIG) |
1983 | high_speed = !high_speed; | ||
1984 | } | ||
1999 | 1985 | ||
2000 | if (use_acm) { | 1986 | if (use_acm) { |
2001 | config_desc = &gs_acm_config_desc; | 1987 | config_desc = &gs_acm_config_desc; |
2002 | function = GS_SPEED_SELECT(high_speed, | 1988 | function = high_speed |
2003 | gs_acm_highspeed_function, | 1989 | ? gs_acm_highspeed_function |
2004 | gs_acm_fullspeed_function); | 1990 | : gs_acm_fullspeed_function; |
2005 | } else { | 1991 | } else { |
2006 | config_desc = &gs_bulk_config_desc; | 1992 | config_desc = &gs_bulk_config_desc; |
2007 | function = GS_SPEED_SELECT(high_speed, | 1993 | function = high_speed |
2008 | gs_bulk_highspeed_function, | 1994 | ? gs_bulk_highspeed_function |
2009 | gs_bulk_fullspeed_function); | 1995 | : gs_bulk_fullspeed_function; |
2010 | } | 1996 | } |
2011 | 1997 | ||
2012 | /* for now, don't advertise srp-only devices */ | 1998 | /* for now, don't advertise srp-only devices */ |
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 3459ea6c6c0b..878e428a0ec1 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | 16 | ||
17 | #include <linux/usb/ch9.h> | 17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb_gadget.h> | 18 | #include <linux/usb/gadget.h> |
19 | 19 | ||
20 | #include <asm/unaligned.h> | 20 | #include <asm/unaligned.h> |
21 | 21 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index fcfe869acb94..fcde5d9c87df 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -1,38 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * zero.c -- Gadget Zero, for USB development | 2 | * zero.c -- Gadget Zero, for USB development |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2004 David Brownell | 4 | * Copyright (C) 2003-2007 David Brownell |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * modification, are permitted provided that the following conditions | 8 | * it under the terms of the GNU General Public License as published by |
9 | * are met: | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * (at your option) any later version. |
11 | * notice, this list of conditions, and the following disclaimer, | ||
12 | * without modification. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. The names of the above-listed copyright holders may not be used | ||
17 | * to endorse or promote products derived from this software without | ||
18 | * specific prior written permission. | ||
19 | * | 11 | * |
20 | * ALTERNATIVELY, this software may be distributed under the terms of the | 12 | * This program is distributed in the hope that it will be useful, |
21 | * GNU General Public License ("GPL") as published by the Free Software | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * Foundation, either version 2 of that License or (at your option) any | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * later version. | 15 | * GNU General Public License for more details. |
24 | * | 16 | * |
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | 17 | * You should have received a copy of the GNU General Public License |
26 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 18 | * along with this program; if not, write to the Free Software |
27 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
29 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
30 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
31 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
32 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
33 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
34 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
35 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
36 | */ | 20 | */ |
37 | 21 | ||
38 | 22 | ||
@@ -57,40 +41,28 @@ | |||
57 | * Many drivers will only have one configuration, letting them be much | 41 | * Many drivers will only have one configuration, letting them be much |
58 | * simpler if they also don't support high speed operation (like this | 42 | * simpler if they also don't support high speed operation (like this |
59 | * driver does). | 43 | * driver does). |
44 | * | ||
45 | * Why is *this* driver using two configurations, rather than setting up | ||
46 | * two interfaces with different functions? To help verify that multiple | ||
47 | * configuration infrastucture is working correctly; also, so that it can | ||
48 | * work with low capability USB controllers without four bulk endpoints. | ||
60 | */ | 49 | */ |
61 | 50 | ||
62 | #define DEBUG 1 | 51 | /* #define VERBOSE_DEBUG */ |
63 | // #define VERBOSE | ||
64 | 52 | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/kernel.h> | 53 | #include <linux/kernel.h> |
67 | #include <linux/delay.h> | ||
68 | #include <linux/ioport.h> | ||
69 | #include <linux/slab.h> | ||
70 | #include <linux/errno.h> | ||
71 | #include <linux/init.h> | ||
72 | #include <linux/timer.h> | ||
73 | #include <linux/list.h> | ||
74 | #include <linux/interrupt.h> | ||
75 | #include <linux/utsname.h> | 54 | #include <linux/utsname.h> |
76 | #include <linux/device.h> | 55 | #include <linux/device.h> |
77 | #include <linux/moduleparam.h> | ||
78 | |||
79 | #include <asm/byteorder.h> | ||
80 | #include <asm/io.h> | ||
81 | #include <asm/irq.h> | ||
82 | #include <asm/system.h> | ||
83 | #include <asm/unaligned.h> | ||
84 | 56 | ||
85 | #include <linux/usb/ch9.h> | 57 | #include <linux/usb/ch9.h> |
86 | #include <linux/usb_gadget.h> | 58 | #include <linux/usb/gadget.h> |
87 | 59 | ||
88 | #include "gadget_chips.h" | 60 | #include "gadget_chips.h" |
89 | 61 | ||
90 | 62 | ||
91 | /*-------------------------------------------------------------------------*/ | 63 | /*-------------------------------------------------------------------------*/ |
92 | 64 | ||
93 | #define DRIVER_VERSION "St Patrick's Day 2004" | 65 | #define DRIVER_VERSION "Lughnasadh, 2007" |
94 | 66 | ||
95 | static const char shortname [] = "zero"; | 67 | static const char shortname [] = "zero"; |
96 | static const char longname [] = "Gadget Zero"; | 68 | static const char longname [] = "Gadget Zero"; |
@@ -131,30 +103,16 @@ struct zero_dev { | |||
131 | struct timer_list resume; | 103 | struct timer_list resume; |
132 | }; | 104 | }; |
133 | 105 | ||
134 | #define xprintk(d,level,fmt,args...) \ | 106 | #define DBG(d, fmt, args...) \ |
135 | dev_printk(level , &(d)->gadget->dev , fmt , ## args) | 107 | dev_dbg(&(d)->gadget->dev , fmt , ## args) |
136 | 108 | #define VDBG(d, fmt, args...) \ | |
137 | #ifdef DEBUG | 109 | dev_vdbg(&(d)->gadget->dev , fmt , ## args) |
138 | #define DBG(dev,fmt,args...) \ | 110 | #define ERROR(d, fmt, args...) \ |
139 | xprintk(dev , KERN_DEBUG , fmt , ## args) | 111 | dev_err(&(d)->gadget->dev , fmt , ## args) |
140 | #else | 112 | #define WARN(d, fmt, args...) \ |
141 | #define DBG(dev,fmt,args...) \ | 113 | dev_warn(&(d)->gadget->dev , fmt , ## args) |
142 | do { } while (0) | 114 | #define INFO(d, fmt, args...) \ |
143 | #endif /* DEBUG */ | 115 | dev_info(&(d)->gadget->dev , fmt , ## args) |
144 | |||
145 | #ifdef VERBOSE | ||
146 | #define VDBG DBG | ||
147 | #else | ||
148 | #define VDBG(dev,fmt,args...) \ | ||
149 | do { } while (0) | ||
150 | #endif /* VERBOSE */ | ||
151 | |||
152 | #define ERROR(dev,fmt,args...) \ | ||
153 | xprintk(dev , KERN_ERR , fmt , ## args) | ||
154 | #define WARN(dev,fmt,args...) \ | ||
155 | xprintk(dev , KERN_WARNING , fmt , ## args) | ||
156 | #define INFO(dev,fmt,args...) \ | ||
157 | xprintk(dev , KERN_INFO , fmt , ## args) | ||
158 | 116 | ||
159 | /*-------------------------------------------------------------------------*/ | 117 | /*-------------------------------------------------------------------------*/ |
160 | 118 | ||
@@ -326,8 +284,6 @@ static const struct usb_descriptor_header *fs_loopback_function [] = { | |||
326 | NULL, | 284 | NULL, |
327 | }; | 285 | }; |
328 | 286 | ||
329 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
330 | |||
331 | /* | 287 | /* |
332 | * usb 2.0 devices need to expose both high speed and full speed | 288 | * usb 2.0 devices need to expose both high speed and full speed |
333 | * descriptors, unless they only run at full speed. | 289 | * descriptors, unless they only run at full speed. |
@@ -383,17 +339,20 @@ static const struct usb_descriptor_header *hs_loopback_function [] = { | |||
383 | }; | 339 | }; |
384 | 340 | ||
385 | /* maxpacket and other transfer characteristics vary by speed. */ | 341 | /* maxpacket and other transfer characteristics vary by speed. */ |
386 | #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) | 342 | static inline struct usb_endpoint_descriptor * |
387 | 343 | ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, | |
388 | #else | 344 | struct usb_endpoint_descriptor *fs) |
345 | { | ||
346 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | ||
347 | return hs; | ||
348 | return fs; | ||
349 | } | ||
389 | 350 | ||
390 | /* if there's no high speed support, maxpacket doesn't change. */ | 351 | static char manufacturer[50]; |
391 | #define ep_desc(g,hs,fs) fs | ||
392 | 352 | ||
393 | #endif /* !CONFIG_USB_GADGET_DUALSPEED */ | 353 | /* default serial number takes at least two packets */ |
354 | static char serial[] = "0123456789.0123456789.0123456789"; | ||
394 | 355 | ||
395 | static char manufacturer [50]; | ||
396 | static char serial [40]; | ||
397 | 356 | ||
398 | /* static strings, in UTF-8 */ | 357 | /* static strings, in UTF-8 */ |
399 | static struct usb_string strings [] = { | 358 | static struct usb_string strings [] = { |
@@ -435,30 +394,29 @@ config_buf (struct usb_gadget *gadget, | |||
435 | int is_source_sink; | 394 | int is_source_sink; |
436 | int len; | 395 | int len; |
437 | const struct usb_descriptor_header **function; | 396 | const struct usb_descriptor_header **function; |
438 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 397 | int hs = 0; |
439 | int hs = (gadget->speed == USB_SPEED_HIGH); | ||
440 | #endif | ||
441 | 398 | ||
442 | /* two configurations will always be index 0 and index 1 */ | 399 | /* two configurations will always be index 0 and index 1 */ |
443 | if (index > 1) | 400 | if (index > 1) |
444 | return -EINVAL; | 401 | return -EINVAL; |
445 | is_source_sink = loopdefault ? (index == 1) : (index == 0); | 402 | is_source_sink = loopdefault ? (index == 1) : (index == 0); |
446 | 403 | ||
447 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 404 | if (gadget_is_dualspeed(gadget)) { |
448 | if (type == USB_DT_OTHER_SPEED_CONFIG) | 405 | hs = (gadget->speed == USB_SPEED_HIGH); |
449 | hs = !hs; | 406 | if (type == USB_DT_OTHER_SPEED_CONFIG) |
407 | hs = !hs; | ||
408 | } | ||
450 | if (hs) | 409 | if (hs) |
451 | function = is_source_sink | 410 | function = is_source_sink |
452 | ? hs_source_sink_function | 411 | ? hs_source_sink_function |
453 | : hs_loopback_function; | 412 | : hs_loopback_function; |
454 | else | 413 | else |
455 | #endif | ||
456 | function = is_source_sink | 414 | function = is_source_sink |
457 | ? fs_source_sink_function | 415 | ? fs_source_sink_function |
458 | : fs_loopback_function; | 416 | : fs_loopback_function; |
459 | 417 | ||
460 | /* for now, don't advertise srp-only devices */ | 418 | /* for now, don't advertise srp-only devices */ |
461 | if (!gadget->is_otg) | 419 | if (!gadget_is_otg(gadget)) |
462 | function++; | 420 | function++; |
463 | 421 | ||
464 | len = usb_gadget_config_buf (is_source_sink | 422 | len = usb_gadget_config_buf (is_source_sink |
@@ -498,6 +456,19 @@ static void free_ep_req (struct usb_ep *ep, struct usb_request *req) | |||
498 | 456 | ||
499 | /*-------------------------------------------------------------------------*/ | 457 | /*-------------------------------------------------------------------------*/ |
500 | 458 | ||
459 | /* | ||
460 | * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals, | ||
461 | * this just sinks bulk packets OUT to the peripheral and sources them IN | ||
462 | * to the host, optionally with specific data patterns. | ||
463 | * | ||
464 | * In terms of control messaging, this supports all the standard requests | ||
465 | * plus two that support control-OUT tests. | ||
466 | * | ||
467 | * Note that because this doesn't queue more than one request at a time, | ||
468 | * some other function must be used to test queueing logic. The network | ||
469 | * link (g_ether) is probably the best option for that. | ||
470 | */ | ||
471 | |||
501 | /* optionally require specific source/sink data patterns */ | 472 | /* optionally require specific source/sink data patterns */ |
502 | 473 | ||
503 | static int | 474 | static int |
@@ -534,12 +505,7 @@ check_read_data ( | |||
534 | return 0; | 505 | return 0; |
535 | } | 506 | } |
536 | 507 | ||
537 | static void | 508 | static void reinit_write_data(struct usb_ep *ep, struct usb_request *req) |
538 | reinit_write_data ( | ||
539 | struct zero_dev *dev, | ||
540 | struct usb_ep *ep, | ||
541 | struct usb_request *req | ||
542 | ) | ||
543 | { | 509 | { |
544 | unsigned i; | 510 | unsigned i; |
545 | u8 *buf = req->buf; | 511 | u8 *buf = req->buf; |
@@ -566,16 +532,16 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) | |||
566 | 532 | ||
567 | switch (status) { | 533 | switch (status) { |
568 | 534 | ||
569 | case 0: /* normal completion? */ | 535 | case 0: /* normal completion? */ |
570 | if (ep == dev->out_ep) { | 536 | if (ep == dev->out_ep) { |
571 | check_read_data (dev, ep, req); | 537 | check_read_data (dev, ep, req); |
572 | memset (req->buf, 0x55, req->length); | 538 | memset (req->buf, 0x55, req->length); |
573 | } else | 539 | } else |
574 | reinit_write_data (dev, ep, req); | 540 | reinit_write_data(ep, req); |
575 | break; | 541 | break; |
576 | 542 | ||
577 | /* this endpoint is normally active while we're configured */ | 543 | /* this endpoint is normally active while we're configured */ |
578 | case -ECONNABORTED: /* hardware forced ep reset */ | 544 | case -ECONNABORTED: /* hardware forced ep reset */ |
579 | case -ECONNRESET: /* request dequeued */ | 545 | case -ECONNRESET: /* request dequeued */ |
580 | case -ESHUTDOWN: /* disconnect from host */ | 546 | case -ESHUTDOWN: /* disconnect from host */ |
581 | VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status, | 547 | VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status, |
@@ -607,8 +573,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) | |||
607 | } | 573 | } |
608 | } | 574 | } |
609 | 575 | ||
610 | static struct usb_request * | 576 | static struct usb_request *source_sink_start_ep(struct usb_ep *ep) |
611 | source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags) | ||
612 | { | 577 | { |
613 | struct usb_request *req; | 578 | struct usb_request *req; |
614 | int status; | 579 | int status; |
@@ -621,11 +586,11 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags) | |||
621 | req->complete = source_sink_complete; | 586 | req->complete = source_sink_complete; |
622 | 587 | ||
623 | if (strcmp (ep->name, EP_IN_NAME) == 0) | 588 | if (strcmp (ep->name, EP_IN_NAME) == 0) |
624 | reinit_write_data (ep->driver_data, ep, req); | 589 | reinit_write_data(ep, req); |
625 | else | 590 | else |
626 | memset (req->buf, 0x55, req->length); | 591 | memset (req->buf, 0x55, req->length); |
627 | 592 | ||
628 | status = usb_ep_queue (ep, req, gfp_flags); | 593 | status = usb_ep_queue(ep, req, GFP_ATOMIC); |
629 | if (status) { | 594 | if (status) { |
630 | struct zero_dev *dev = ep->driver_data; | 595 | struct zero_dev *dev = ep->driver_data; |
631 | 596 | ||
@@ -637,8 +602,7 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags) | |||
637 | return req; | 602 | return req; |
638 | } | 603 | } |
639 | 604 | ||
640 | static int | 605 | static int set_source_sink_config(struct zero_dev *dev) |
641 | set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) | ||
642 | { | 606 | { |
643 | int result = 0; | 607 | int result = 0; |
644 | struct usb_ep *ep; | 608 | struct usb_ep *ep; |
@@ -653,8 +617,7 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) | |||
653 | result = usb_ep_enable (ep, d); | 617 | result = usb_ep_enable (ep, d); |
654 | if (result == 0) { | 618 | if (result == 0) { |
655 | ep->driver_data = dev; | 619 | ep->driver_data = dev; |
656 | if (source_sink_start_ep(ep, gfp_flags) | 620 | if (source_sink_start_ep(ep) != NULL) { |
657 | != NULL) { | ||
658 | dev->in_ep = ep; | 621 | dev->in_ep = ep; |
659 | continue; | 622 | continue; |
660 | } | 623 | } |
@@ -668,8 +631,7 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) | |||
668 | result = usb_ep_enable (ep, d); | 631 | result = usb_ep_enable (ep, d); |
669 | if (result == 0) { | 632 | if (result == 0) { |
670 | ep->driver_data = dev; | 633 | ep->driver_data = dev; |
671 | if (source_sink_start_ep(ep, gfp_flags) | 634 | if (source_sink_start_ep(ep) != NULL) { |
672 | != NULL) { | ||
673 | dev->out_ep = ep; | 635 | dev->out_ep = ep; |
674 | continue; | 636 | continue; |
675 | } | 637 | } |
@@ -701,7 +663,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req) | |||
701 | 663 | ||
702 | switch (status) { | 664 | switch (status) { |
703 | 665 | ||
704 | case 0: /* normal completion? */ | 666 | case 0: /* normal completion? */ |
705 | if (ep == dev->out_ep) { | 667 | if (ep == dev->out_ep) { |
706 | /* loop this OUT packet back IN to the host */ | 668 | /* loop this OUT packet back IN to the host */ |
707 | req->zero = (req->actual < req->length); | 669 | req->zero = (req->actual < req->length); |
@@ -735,7 +697,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req) | |||
735 | * rely on the hardware driver to clean up on disconnect or | 697 | * rely on the hardware driver to clean up on disconnect or |
736 | * endpoint disable. | 698 | * endpoint disable. |
737 | */ | 699 | */ |
738 | case -ECONNABORTED: /* hardware forced ep reset */ | 700 | case -ECONNABORTED: /* hardware forced ep reset */ |
739 | case -ECONNRESET: /* request dequeued */ | 701 | case -ECONNRESET: /* request dequeued */ |
740 | case -ESHUTDOWN: /* disconnect from host */ | 702 | case -ESHUTDOWN: /* disconnect from host */ |
741 | free_ep_req (ep, req); | 703 | free_ep_req (ep, req); |
@@ -743,8 +705,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req) | |||
743 | } | 705 | } |
744 | } | 706 | } |
745 | 707 | ||
746 | static int | 708 | static int set_loopback_config(struct zero_dev *dev) |
747 | set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags) | ||
748 | { | 709 | { |
749 | int result = 0; | 710 | int result = 0; |
750 | struct usb_ep *ep; | 711 | struct usb_ep *ep; |
@@ -844,8 +805,7 @@ static void zero_reset_config (struct zero_dev *dev) | |||
844 | * code can do, perhaps by disallowing more than one configuration or | 805 | * code can do, perhaps by disallowing more than one configuration or |
845 | * by limiting configuration choices (like the pxa2xx). | 806 | * by limiting configuration choices (like the pxa2xx). |
846 | */ | 807 | */ |
847 | static int | 808 | static int zero_set_config(struct zero_dev *dev, unsigned number) |
848 | zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags) | ||
849 | { | 809 | { |
850 | int result = 0; | 810 | int result = 0; |
851 | struct usb_gadget *gadget = dev->gadget; | 811 | struct usb_gadget *gadget = dev->gadget; |
@@ -855,17 +815,17 @@ zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags) | |||
855 | 815 | ||
856 | if (gadget_is_sa1100 (gadget) && dev->config) { | 816 | if (gadget_is_sa1100 (gadget) && dev->config) { |
857 | /* tx fifo is full, but we can't clear it...*/ | 817 | /* tx fifo is full, but we can't clear it...*/ |
858 | INFO (dev, "can't change configurations\n"); | 818 | ERROR(dev, "can't change configurations\n"); |
859 | return -ESPIPE; | 819 | return -ESPIPE; |
860 | } | 820 | } |
861 | zero_reset_config (dev); | 821 | zero_reset_config (dev); |
862 | 822 | ||
863 | switch (number) { | 823 | switch (number) { |
864 | case CONFIG_SOURCE_SINK: | 824 | case CONFIG_SOURCE_SINK: |
865 | result = set_source_sink_config (dev, gfp_flags); | 825 | result = set_source_sink_config(dev); |
866 | break; | 826 | break; |
867 | case CONFIG_LOOPBACK: | 827 | case CONFIG_LOOPBACK: |
868 | result = set_loopback_config (dev, gfp_flags); | 828 | result = set_loopback_config(dev); |
869 | break; | 829 | break; |
870 | default: | 830 | default: |
871 | result = -EINVAL; | 831 | result = -EINVAL; |
@@ -885,7 +845,7 @@ zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags) | |||
885 | case USB_SPEED_LOW: speed = "low"; break; | 845 | case USB_SPEED_LOW: speed = "low"; break; |
886 | case USB_SPEED_FULL: speed = "full"; break; | 846 | case USB_SPEED_FULL: speed = "full"; break; |
887 | case USB_SPEED_HIGH: speed = "high"; break; | 847 | case USB_SPEED_HIGH: speed = "high"; break; |
888 | default: speed = "?"; break; | 848 | default: speed = "?"; break; |
889 | } | 849 | } |
890 | 850 | ||
891 | dev->config = number; | 851 | dev->config = number; |
@@ -938,19 +898,17 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
938 | value = min (w_length, (u16) sizeof device_desc); | 898 | value = min (w_length, (u16) sizeof device_desc); |
939 | memcpy (req->buf, &device_desc, value); | 899 | memcpy (req->buf, &device_desc, value); |
940 | break; | 900 | break; |
941 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
942 | case USB_DT_DEVICE_QUALIFIER: | 901 | case USB_DT_DEVICE_QUALIFIER: |
943 | if (!gadget->is_dualspeed) | 902 | if (!gadget_is_dualspeed(gadget)) |
944 | break; | 903 | break; |
945 | value = min (w_length, (u16) sizeof dev_qualifier); | 904 | value = min (w_length, (u16) sizeof dev_qualifier); |
946 | memcpy (req->buf, &dev_qualifier, value); | 905 | memcpy (req->buf, &dev_qualifier, value); |
947 | break; | 906 | break; |
948 | 907 | ||
949 | case USB_DT_OTHER_SPEED_CONFIG: | 908 | case USB_DT_OTHER_SPEED_CONFIG: |
950 | if (!gadget->is_dualspeed) | 909 | if (!gadget_is_dualspeed(gadget)) |
951 | break; | 910 | break; |
952 | // FALLTHROUGH | 911 | // FALLTHROUGH |
953 | #endif /* CONFIG_USB_GADGET_DUALSPEED */ | ||
954 | case USB_DT_CONFIG: | 912 | case USB_DT_CONFIG: |
955 | value = config_buf (gadget, req->buf, | 913 | value = config_buf (gadget, req->buf, |
956 | w_value >> 8, | 914 | w_value >> 8, |
@@ -984,7 +942,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
984 | else | 942 | else |
985 | VDBG (dev, "HNP inactive\n"); | 943 | VDBG (dev, "HNP inactive\n"); |
986 | spin_lock (&dev->lock); | 944 | spin_lock (&dev->lock); |
987 | value = zero_set_config (dev, w_value, GFP_ATOMIC); | 945 | value = zero_set_config(dev, w_value); |
988 | spin_unlock (&dev->lock); | 946 | spin_unlock (&dev->lock); |
989 | break; | 947 | break; |
990 | case USB_REQ_GET_CONFIGURATION: | 948 | case USB_REQ_GET_CONFIGURATION: |
@@ -1013,7 +971,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1013 | * use this "reset the config" shortcut. | 971 | * use this "reset the config" shortcut. |
1014 | */ | 972 | */ |
1015 | zero_reset_config (dev); | 973 | zero_reset_config (dev); |
1016 | zero_set_config (dev, config, GFP_ATOMIC); | 974 | zero_set_config(dev, config); |
1017 | value = 0; | 975 | value = 0; |
1018 | } | 976 | } |
1019 | spin_unlock (&dev->lock); | 977 | spin_unlock (&dev->lock); |
@@ -1163,7 +1121,7 @@ autoconf_fail: | |||
1163 | } | 1121 | } |
1164 | EP_IN_NAME = ep->name; | 1122 | EP_IN_NAME = ep->name; |
1165 | ep->driver_data = ep; /* claim */ | 1123 | ep->driver_data = ep; /* claim */ |
1166 | 1124 | ||
1167 | ep = usb_ep_autoconfig (gadget, &fs_sink_desc); | 1125 | ep = usb_ep_autoconfig (gadget, &fs_sink_desc); |
1168 | if (!ep) | 1126 | if (!ep) |
1169 | goto autoconf_fail; | 1127 | goto autoconf_fail; |
@@ -1207,16 +1165,18 @@ autoconf_fail: | |||
1207 | 1165 | ||
1208 | device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; | 1166 | device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; |
1209 | 1167 | ||
1210 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1168 | if (gadget_is_dualspeed(gadget)) { |
1211 | /* assume ep0 uses the same value for both speeds ... */ | 1169 | /* assume ep0 uses the same value for both speeds ... */ |
1212 | dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; | 1170 | dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; |
1213 | 1171 | ||
1214 | /* and that all endpoints are dual-speed */ | 1172 | /* and that all endpoints are dual-speed */ |
1215 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 1173 | hs_source_desc.bEndpointAddress = |
1216 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 1174 | fs_source_desc.bEndpointAddress; |
1217 | #endif | 1175 | hs_sink_desc.bEndpointAddress = |
1176 | fs_sink_desc.bEndpointAddress; | ||
1177 | } | ||
1218 | 1178 | ||
1219 | if (gadget->is_otg) { | 1179 | if (gadget_is_otg(gadget)) { |
1220 | otg_descriptor.bmAttributes |= USB_OTG_HNP, | 1180 | otg_descriptor.bmAttributes |= USB_OTG_HNP, |
1221 | source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 1181 | source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
1222 | loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 1182 | loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
@@ -1294,23 +1254,18 @@ static struct usb_gadget_driver zero_driver = { | |||
1294 | .suspend = zero_suspend, | 1254 | .suspend = zero_suspend, |
1295 | .resume = zero_resume, | 1255 | .resume = zero_resume, |
1296 | 1256 | ||
1297 | .driver = { | 1257 | .driver = { |
1298 | .name = (char *) shortname, | 1258 | .name = (char *) shortname, |
1299 | .owner = THIS_MODULE, | 1259 | .owner = THIS_MODULE, |
1300 | }, | 1260 | }, |
1301 | }; | 1261 | }; |
1302 | 1262 | ||
1303 | MODULE_AUTHOR ("David Brownell"); | 1263 | MODULE_AUTHOR("David Brownell"); |
1304 | MODULE_LICENSE ("Dual BSD/GPL"); | 1264 | MODULE_LICENSE("GPL"); |
1305 | 1265 | ||
1306 | 1266 | ||
1307 | static int __init init (void) | 1267 | static int __init init (void) |
1308 | { | 1268 | { |
1309 | /* a real value would likely come through some id prom | ||
1310 | * or module option. this one takes at least two packets. | ||
1311 | */ | ||
1312 | strlcpy (serial, "0123456789.0123456789.0123456789", sizeof serial); | ||
1313 | |||
1314 | return usb_gadget_register_driver (&zero_driver); | 1269 | return usb_gadget_register_driver (&zero_driver); |
1315 | } | 1270 | } |
1316 | module_init (init); | 1271 | module_init (init); |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 565d6ef4c4cf..c978d622fa8a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -154,6 +154,19 @@ config USB_OHCI_HCD_PCI | |||
154 | Enables support for PCI-bus plug-in USB controller cards. | 154 | Enables support for PCI-bus plug-in USB controller cards. |
155 | If unsure, say Y. | 155 | If unsure, say Y. |
156 | 156 | ||
157 | config USB_OHCI_HCD_SSB | ||
158 | bool "OHCI support for Broadcom SSB OHCI core" | ||
159 | depends on USB_OHCI_HCD && SSB && EXPERIMENTAL | ||
160 | default n | ||
161 | ---help--- | ||
162 | Support for the Sonics Silicon Backplane (SSB) attached | ||
163 | Broadcom USB OHCI core. | ||
164 | |||
165 | This device is present in some embedded devices with | ||
166 | Broadcom based SSB bus. | ||
167 | |||
168 | If unsure, say N. | ||
169 | |||
157 | config USB_OHCI_BIG_ENDIAN_DESC | 170 | config USB_OHCI_BIG_ENDIAN_DESC |
158 | bool | 171 | bool |
159 | depends on USB_OHCI_HCD | 172 | depends on USB_OHCI_HCD |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index b1d19268cb23..766ef68a0b43 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -220,10 +220,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { | |||
220 | */ | 220 | */ |
221 | .hub_status_data = ehci_hub_status_data, | 221 | .hub_status_data = ehci_hub_status_data, |
222 | .hub_control = ehci_hub_control, | 222 | .hub_control = ehci_hub_control, |
223 | #ifdef CONFIG_PM | 223 | .bus_suspend = ehci_bus_suspend, |
224 | .hub_suspend = ehci_hub_suspend, | 224 | .bus_resume = ehci_bus_resume, |
225 | .hub_resume = ehci_hub_resume, | ||
226 | #endif | ||
227 | }; | 225 | }; |
228 | 226 | ||
229 | /*-------------------------------------------------------------------------*/ | 227 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 35cdba10411b..c1514442883e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -570,10 +570,18 @@ static int ehci_run (struct usb_hcd *hcd) | |||
570 | * are explicitly handed to companion controller(s), so no TT is | 570 | * are explicitly handed to companion controller(s), so no TT is |
571 | * involved with the root hub. (Except where one is integrated, | 571 | * involved with the root hub. (Except where one is integrated, |
572 | * and there's no companion controller unless maybe for USB OTG.) | 572 | * and there's no companion controller unless maybe for USB OTG.) |
573 | * | ||
574 | * Turning on the CF flag will transfer ownership of all ports | ||
575 | * from the companions to the EHCI controller. If any of the | ||
576 | * companions are in the middle of a port reset at the time, it | ||
577 | * could cause trouble. Write-locking ehci_cf_port_reset_rwsem | ||
578 | * guarantees that no resets are in progress. | ||
573 | */ | 579 | */ |
580 | down_write(&ehci_cf_port_reset_rwsem); | ||
574 | hcd->state = HC_STATE_RUNNING; | 581 | hcd->state = HC_STATE_RUNNING; |
575 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | 582 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
576 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | 583 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
584 | up_write(&ehci_cf_port_reset_rwsem); | ||
577 | 585 | ||
578 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); | 586 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
579 | ehci_info (ehci, | 587 | ehci_info (ehci, |
@@ -719,7 +727,6 @@ dead: | |||
719 | */ | 727 | */ |
720 | static int ehci_urb_enqueue ( | 728 | static int ehci_urb_enqueue ( |
721 | struct usb_hcd *hcd, | 729 | struct usb_hcd *hcd, |
722 | struct usb_host_endpoint *ep, | ||
723 | struct urb *urb, | 730 | struct urb *urb, |
724 | gfp_t mem_flags | 731 | gfp_t mem_flags |
725 | ) { | 732 | ) { |
@@ -734,12 +741,12 @@ static int ehci_urb_enqueue ( | |||
734 | default: | 741 | default: |
735 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) | 742 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) |
736 | return -ENOMEM; | 743 | return -ENOMEM; |
737 | return submit_async (ehci, ep, urb, &qtd_list, mem_flags); | 744 | return submit_async(ehci, urb, &qtd_list, mem_flags); |
738 | 745 | ||
739 | case PIPE_INTERRUPT: | 746 | case PIPE_INTERRUPT: |
740 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) | 747 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) |
741 | return -ENOMEM; | 748 | return -ENOMEM; |
742 | return intr_submit (ehci, ep, urb, &qtd_list, mem_flags); | 749 | return intr_submit(ehci, urb, &qtd_list, mem_flags); |
743 | 750 | ||
744 | case PIPE_ISOCHRONOUS: | 751 | case PIPE_ISOCHRONOUS: |
745 | if (urb->dev->speed == USB_SPEED_HIGH) | 752 | if (urb->dev->speed == USB_SPEED_HIGH) |
@@ -777,13 +784,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
777 | * completions normally happen asynchronously | 784 | * completions normally happen asynchronously |
778 | */ | 785 | */ |
779 | 786 | ||
780 | static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 787 | static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
781 | { | 788 | { |
782 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 789 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
783 | struct ehci_qh *qh; | 790 | struct ehci_qh *qh; |
784 | unsigned long flags; | 791 | unsigned long flags; |
792 | int rc; | ||
785 | 793 | ||
786 | spin_lock_irqsave (&ehci->lock, flags); | 794 | spin_lock_irqsave (&ehci->lock, flags); |
795 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
796 | if (rc) | ||
797 | goto done; | ||
798 | |||
787 | switch (usb_pipetype (urb->pipe)) { | 799 | switch (usb_pipetype (urb->pipe)) { |
788 | // case PIPE_CONTROL: | 800 | // case PIPE_CONTROL: |
789 | // case PIPE_BULK: | 801 | // case PIPE_BULK: |
@@ -838,7 +850,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
838 | } | 850 | } |
839 | done: | 851 | done: |
840 | spin_unlock_irqrestore (&ehci->lock, flags); | 852 | spin_unlock_irqrestore (&ehci->lock, flags); |
841 | return 0; | 853 | return rc; |
842 | } | 854 | } |
843 | 855 | ||
844 | /*-------------------------------------------------------------------------*/ | 856 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a7816e392a85..ad0d4965f2fb 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -58,8 +58,6 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
58 | if (!retval) | 58 | if (!retval) |
59 | ehci_dbg(ehci, "MWI active\n"); | 59 | ehci_dbg(ehci, "MWI active\n"); |
60 | 60 | ||
61 | ehci_port_power(ehci, 0); | ||
62 | |||
63 | return 0; | 61 | return 0; |
64 | } | 62 | } |
65 | 63 | ||
@@ -156,8 +154,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
156 | break; | 154 | break; |
157 | } | 155 | } |
158 | 156 | ||
159 | if (ehci_is_TDI(ehci)) | 157 | ehci_reset(ehci); |
160 | ehci_reset(ehci); | ||
161 | 158 | ||
162 | /* at least the Genesys GL880S needs fixup here */ | 159 | /* at least the Genesys GL880S needs fixup here */ |
163 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); | 160 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); |
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c index 4f99b0eb27bc..452d4b1bc859 100644 --- a/drivers/usb/host/ehci-ppc-soc.c +++ b/drivers/usb/host/ehci-ppc-soc.c | |||
@@ -160,10 +160,8 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { | |||
160 | */ | 160 | */ |
161 | .hub_status_data = ehci_hub_status_data, | 161 | .hub_status_data = ehci_hub_status_data, |
162 | .hub_control = ehci_hub_control, | 162 | .hub_control = ehci_hub_control, |
163 | #ifdef CONFIG_PM | 163 | .bus_suspend = ehci_bus_suspend, |
164 | .hub_suspend = ehci_hub_suspend, | 164 | .bus_resume = ehci_bus_resume, |
165 | .hub_resume = ehci_hub_resume, | ||
166 | #endif | ||
167 | }; | 165 | }; |
168 | 166 | ||
169 | static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) | 167 | static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 829fe649a981..03a6b2f4e6ed 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
@@ -47,7 +47,7 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd) | |||
47 | if (result) | 47 | if (result) |
48 | return result; | 48 | return result; |
49 | 49 | ||
50 | ehci_port_power(ehci, 0); | 50 | ehci_reset(ehci); |
51 | 51 | ||
52 | return result; | 52 | return result; |
53 | } | 53 | } |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 140bfa423e07..b10f39c047e9 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -139,63 +139,65 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
139 | 139 | ||
140 | /*-------------------------------------------------------------------------*/ | 140 | /*-------------------------------------------------------------------------*/ |
141 | 141 | ||
142 | static void qtd_copy_status ( | 142 | static int qtd_copy_status ( |
143 | struct ehci_hcd *ehci, | 143 | struct ehci_hcd *ehci, |
144 | struct urb *urb, | 144 | struct urb *urb, |
145 | size_t length, | 145 | size_t length, |
146 | u32 token | 146 | u32 token |
147 | ) | 147 | ) |
148 | { | 148 | { |
149 | int status = -EINPROGRESS; | ||
150 | |||
149 | /* count IN/OUT bytes, not SETUP (even short packets) */ | 151 | /* count IN/OUT bytes, not SETUP (even short packets) */ |
150 | if (likely (QTD_PID (token) != 2)) | 152 | if (likely (QTD_PID (token) != 2)) |
151 | urb->actual_length += length - QTD_LENGTH (token); | 153 | urb->actual_length += length - QTD_LENGTH (token); |
152 | 154 | ||
153 | /* don't modify error codes */ | 155 | /* don't modify error codes */ |
154 | if (unlikely (urb->status != -EINPROGRESS)) | 156 | if (unlikely(urb->unlinked)) |
155 | return; | 157 | return status; |
156 | 158 | ||
157 | /* force cleanup after short read; not always an error */ | 159 | /* force cleanup after short read; not always an error */ |
158 | if (unlikely (IS_SHORT_READ (token))) | 160 | if (unlikely (IS_SHORT_READ (token))) |
159 | urb->status = -EREMOTEIO; | 161 | status = -EREMOTEIO; |
160 | 162 | ||
161 | /* serious "can't proceed" faults reported by the hardware */ | 163 | /* serious "can't proceed" faults reported by the hardware */ |
162 | if (token & QTD_STS_HALT) { | 164 | if (token & QTD_STS_HALT) { |
163 | if (token & QTD_STS_BABBLE) { | 165 | if (token & QTD_STS_BABBLE) { |
164 | /* FIXME "must" disable babbling device's port too */ | 166 | /* FIXME "must" disable babbling device's port too */ |
165 | urb->status = -EOVERFLOW; | 167 | status = -EOVERFLOW; |
166 | } else if (token & QTD_STS_MMF) { | 168 | } else if (token & QTD_STS_MMF) { |
167 | /* fs/ls interrupt xfer missed the complete-split */ | 169 | /* fs/ls interrupt xfer missed the complete-split */ |
168 | urb->status = -EPROTO; | 170 | status = -EPROTO; |
169 | } else if (token & QTD_STS_DBE) { | 171 | } else if (token & QTD_STS_DBE) { |
170 | urb->status = (QTD_PID (token) == 1) /* IN ? */ | 172 | status = (QTD_PID (token) == 1) /* IN ? */ |
171 | ? -ENOSR /* hc couldn't read data */ | 173 | ? -ENOSR /* hc couldn't read data */ |
172 | : -ECOMM; /* hc couldn't write data */ | 174 | : -ECOMM; /* hc couldn't write data */ |
173 | } else if (token & QTD_STS_XACT) { | 175 | } else if (token & QTD_STS_XACT) { |
174 | /* timeout, bad crc, wrong PID, etc; retried */ | 176 | /* timeout, bad crc, wrong PID, etc; retried */ |
175 | if (QTD_CERR (token)) | 177 | if (QTD_CERR (token)) |
176 | urb->status = -EPIPE; | 178 | status = -EPIPE; |
177 | else { | 179 | else { |
178 | ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", | 180 | ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n", |
179 | urb->dev->devpath, | 181 | urb->dev->devpath, |
180 | usb_pipeendpoint (urb->pipe), | 182 | usb_pipeendpoint (urb->pipe), |
181 | usb_pipein (urb->pipe) ? "in" : "out"); | 183 | usb_pipein (urb->pipe) ? "in" : "out"); |
182 | urb->status = -EPROTO; | 184 | status = -EPROTO; |
183 | } | 185 | } |
184 | /* CERR nonzero + no errors + halt --> stall */ | 186 | /* CERR nonzero + no errors + halt --> stall */ |
185 | } else if (QTD_CERR (token)) | 187 | } else if (QTD_CERR (token)) |
186 | urb->status = -EPIPE; | 188 | status = -EPIPE; |
187 | else /* unknown */ | 189 | else /* unknown */ |
188 | urb->status = -EPROTO; | 190 | status = -EPROTO; |
189 | 191 | ||
190 | ehci_vdbg (ehci, | 192 | ehci_vdbg (ehci, |
191 | "dev%d ep%d%s qtd token %08x --> status %d\n", | 193 | "dev%d ep%d%s qtd token %08x --> status %d\n", |
192 | usb_pipedevice (urb->pipe), | 194 | usb_pipedevice (urb->pipe), |
193 | usb_pipeendpoint (urb->pipe), | 195 | usb_pipeendpoint (urb->pipe), |
194 | usb_pipein (urb->pipe) ? "in" : "out", | 196 | usb_pipein (urb->pipe) ? "in" : "out", |
195 | token, urb->status); | 197 | token, status); |
196 | 198 | ||
197 | /* if async CSPLIT failed, try cleaning out the TT buffer */ | 199 | /* if async CSPLIT failed, try cleaning out the TT buffer */ |
198 | if (urb->status != -EPIPE | 200 | if (status != -EPIPE |
199 | && urb->dev->tt && !usb_pipeint (urb->pipe) | 201 | && urb->dev->tt && !usb_pipeint (urb->pipe) |
200 | && ((token & QTD_STS_MMF) != 0 | 202 | && ((token & QTD_STS_MMF) != 0 |
201 | || QTD_CERR(token) == 0) | 203 | || QTD_CERR(token) == 0) |
@@ -212,10 +214,12 @@ static void qtd_copy_status ( | |||
212 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); | 214 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); |
213 | } | 215 | } |
214 | } | 216 | } |
217 | |||
218 | return status; | ||
215 | } | 219 | } |
216 | 220 | ||
217 | static void | 221 | static void |
218 | ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb) | 222 | ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) |
219 | __releases(ehci->lock) | 223 | __releases(ehci->lock) |
220 | __acquires(ehci->lock) | 224 | __acquires(ehci->lock) |
221 | { | 225 | { |
@@ -231,25 +235,13 @@ __acquires(ehci->lock) | |||
231 | qh_put (qh); | 235 | qh_put (qh); |
232 | } | 236 | } |
233 | 237 | ||
234 | spin_lock (&urb->lock); | 238 | if (unlikely(urb->unlinked)) { |
235 | urb->hcpriv = NULL; | 239 | COUNT(ehci->stats.unlink); |
236 | switch (urb->status) { | 240 | } else { |
237 | case -EINPROGRESS: /* success */ | 241 | if (likely(status == -EINPROGRESS)) |
238 | urb->status = 0; | 242 | status = 0; |
239 | default: /* fault */ | 243 | COUNT(ehci->stats.complete); |
240 | COUNT (ehci->stats.complete); | ||
241 | break; | ||
242 | case -EREMOTEIO: /* fault or normal */ | ||
243 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) | ||
244 | urb->status = 0; | ||
245 | COUNT (ehci->stats.complete); | ||
246 | break; | ||
247 | case -ECONNRESET: /* canceled */ | ||
248 | case -ENOENT: | ||
249 | COUNT (ehci->stats.unlink); | ||
250 | break; | ||
251 | } | 244 | } |
252 | spin_unlock (&urb->lock); | ||
253 | 245 | ||
254 | #ifdef EHCI_URB_TRACE | 246 | #ifdef EHCI_URB_TRACE |
255 | ehci_dbg (ehci, | 247 | ehci_dbg (ehci, |
@@ -257,13 +249,14 @@ __acquires(ehci->lock) | |||
257 | __FUNCTION__, urb->dev->devpath, urb, | 249 | __FUNCTION__, urb->dev->devpath, urb, |
258 | usb_pipeendpoint (urb->pipe), | 250 | usb_pipeendpoint (urb->pipe), |
259 | usb_pipein (urb->pipe) ? "in" : "out", | 251 | usb_pipein (urb->pipe) ? "in" : "out", |
260 | urb->status, | 252 | status, |
261 | urb->actual_length, urb->transfer_buffer_length); | 253 | urb->actual_length, urb->transfer_buffer_length); |
262 | #endif | 254 | #endif |
263 | 255 | ||
264 | /* complete() can reenter this HCD */ | 256 | /* complete() can reenter this HCD */ |
257 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | ||
265 | spin_unlock (&ehci->lock); | 258 | spin_unlock (&ehci->lock); |
266 | usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb); | 259 | usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status); |
267 | spin_lock (&ehci->lock); | 260 | spin_lock (&ehci->lock); |
268 | } | 261 | } |
269 | 262 | ||
@@ -283,6 +276,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
283 | { | 276 | { |
284 | struct ehci_qtd *last = NULL, *end = qh->dummy; | 277 | struct ehci_qtd *last = NULL, *end = qh->dummy; |
285 | struct list_head *entry, *tmp; | 278 | struct list_head *entry, *tmp; |
279 | int last_status = -EINPROGRESS; | ||
286 | int stopped; | 280 | int stopped; |
287 | unsigned count = 0; | 281 | unsigned count = 0; |
288 | int do_status = 0; | 282 | int do_status = 0; |
@@ -311,6 +305,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
311 | struct ehci_qtd *qtd; | 305 | struct ehci_qtd *qtd; |
312 | struct urb *urb; | 306 | struct urb *urb; |
313 | u32 token = 0; | 307 | u32 token = 0; |
308 | int qtd_status; | ||
314 | 309 | ||
315 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); | 310 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); |
316 | urb = qtd->urb; | 311 | urb = qtd->urb; |
@@ -318,11 +313,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
318 | /* clean up any state from previous QTD ...*/ | 313 | /* clean up any state from previous QTD ...*/ |
319 | if (last) { | 314 | if (last) { |
320 | if (likely (last->urb != urb)) { | 315 | if (likely (last->urb != urb)) { |
321 | ehci_urb_done (ehci, last->urb); | 316 | ehci_urb_done(ehci, last->urb, last_status); |
322 | count++; | 317 | count++; |
323 | } | 318 | } |
324 | ehci_qtd_free (ehci, last); | 319 | ehci_qtd_free (ehci, last); |
325 | last = NULL; | 320 | last = NULL; |
321 | last_status = -EINPROGRESS; | ||
326 | } | 322 | } |
327 | 323 | ||
328 | /* ignore urbs submitted during completions we reported */ | 324 | /* ignore urbs submitted during completions we reported */ |
@@ -358,13 +354,14 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
358 | stopped = 1; | 354 | stopped = 1; |
359 | 355 | ||
360 | if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) | 356 | if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) |
361 | urb->status = -ESHUTDOWN; | 357 | last_status = -ESHUTDOWN; |
362 | 358 | ||
363 | /* ignore active urbs unless some previous qtd | 359 | /* ignore active urbs unless some previous qtd |
364 | * for the urb faulted (including short read) or | 360 | * for the urb faulted (including short read) or |
365 | * its urb was canceled. we may patch qh or qtds. | 361 | * its urb was canceled. we may patch qh or qtds. |
366 | */ | 362 | */ |
367 | if (likely (urb->status == -EINPROGRESS)) | 363 | if (likely(last_status == -EINPROGRESS && |
364 | !urb->unlinked)) | ||
368 | continue; | 365 | continue; |
369 | 366 | ||
370 | /* issue status after short control reads */ | 367 | /* issue status after short control reads */ |
@@ -392,11 +389,14 @@ halt: | |||
392 | } | 389 | } |
393 | 390 | ||
394 | /* remove it from the queue */ | 391 | /* remove it from the queue */ |
395 | spin_lock (&urb->lock); | 392 | qtd_status = qtd_copy_status(ehci, urb, qtd->length, token); |
396 | qtd_copy_status (ehci, urb, qtd->length, token); | 393 | if (unlikely(qtd_status == -EREMOTEIO)) { |
397 | do_status = (urb->status == -EREMOTEIO) | 394 | do_status = (!urb->unlinked && |
398 | && usb_pipecontrol (urb->pipe); | 395 | usb_pipecontrol(urb->pipe)); |
399 | spin_unlock (&urb->lock); | 396 | qtd_status = 0; |
397 | } | ||
398 | if (likely(last_status == -EINPROGRESS)) | ||
399 | last_status = qtd_status; | ||
400 | 400 | ||
401 | if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { | 401 | if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { |
402 | last = list_entry (qtd->qtd_list.prev, | 402 | last = list_entry (qtd->qtd_list.prev, |
@@ -409,7 +409,7 @@ halt: | |||
409 | 409 | ||
410 | /* last urb's completion might still need calling */ | 410 | /* last urb's completion might still need calling */ |
411 | if (likely (last != NULL)) { | 411 | if (likely (last != NULL)) { |
412 | ehci_urb_done (ehci, last->urb); | 412 | ehci_urb_done(ehci, last->urb, last_status); |
413 | count++; | 413 | count++; |
414 | ehci_qtd_free (ehci, last); | 414 | ehci_qtd_free (ehci, last); |
415 | } | 415 | } |
@@ -913,7 +913,6 @@ static struct ehci_qh *qh_append_tds ( | |||
913 | static int | 913 | static int |
914 | submit_async ( | 914 | submit_async ( |
915 | struct ehci_hcd *ehci, | 915 | struct ehci_hcd *ehci, |
916 | struct usb_host_endpoint *ep, | ||
917 | struct urb *urb, | 916 | struct urb *urb, |
918 | struct list_head *qtd_list, | 917 | struct list_head *qtd_list, |
919 | gfp_t mem_flags | 918 | gfp_t mem_flags |
@@ -922,10 +921,10 @@ submit_async ( | |||
922 | int epnum; | 921 | int epnum; |
923 | unsigned long flags; | 922 | unsigned long flags; |
924 | struct ehci_qh *qh = NULL; | 923 | struct ehci_qh *qh = NULL; |
925 | int rc = 0; | 924 | int rc; |
926 | 925 | ||
927 | qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); | 926 | qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); |
928 | epnum = ep->desc.bEndpointAddress; | 927 | epnum = urb->ep->desc.bEndpointAddress; |
929 | 928 | ||
930 | #ifdef EHCI_URB_TRACE | 929 | #ifdef EHCI_URB_TRACE |
931 | ehci_dbg (ehci, | 930 | ehci_dbg (ehci, |
@@ -933,7 +932,7 @@ submit_async ( | |||
933 | __FUNCTION__, urb->dev->devpath, urb, | 932 | __FUNCTION__, urb->dev->devpath, urb, |
934 | epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", | 933 | epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", |
935 | urb->transfer_buffer_length, | 934 | urb->transfer_buffer_length, |
936 | qtd, ep->hcpriv); | 935 | qtd, urb->ep->hcpriv); |
937 | #endif | 936 | #endif |
938 | 937 | ||
939 | spin_lock_irqsave (&ehci->lock, flags); | 938 | spin_lock_irqsave (&ehci->lock, flags); |
@@ -942,9 +941,13 @@ submit_async ( | |||
942 | rc = -ESHUTDOWN; | 941 | rc = -ESHUTDOWN; |
943 | goto done; | 942 | goto done; |
944 | } | 943 | } |
944 | rc = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); | ||
945 | if (unlikely(rc)) | ||
946 | goto done; | ||
945 | 947 | ||
946 | qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); | 948 | qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); |
947 | if (unlikely(qh == NULL)) { | 949 | if (unlikely(qh == NULL)) { |
950 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | ||
948 | rc = -ENOMEM; | 951 | rc = -ENOMEM; |
949 | goto done; | 952 | goto done; |
950 | } | 953 | } |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index e682f2342ef8..80d99bce2b38 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -797,7 +797,6 @@ done: | |||
797 | 797 | ||
798 | static int intr_submit ( | 798 | static int intr_submit ( |
799 | struct ehci_hcd *ehci, | 799 | struct ehci_hcd *ehci, |
800 | struct usb_host_endpoint *ep, | ||
801 | struct urb *urb, | 800 | struct urb *urb, |
802 | struct list_head *qtd_list, | 801 | struct list_head *qtd_list, |
803 | gfp_t mem_flags | 802 | gfp_t mem_flags |
@@ -805,23 +804,26 @@ static int intr_submit ( | |||
805 | unsigned epnum; | 804 | unsigned epnum; |
806 | unsigned long flags; | 805 | unsigned long flags; |
807 | struct ehci_qh *qh; | 806 | struct ehci_qh *qh; |
808 | int status = 0; | 807 | int status; |
809 | struct list_head empty; | 808 | struct list_head empty; |
810 | 809 | ||
811 | /* get endpoint and transfer/schedule data */ | 810 | /* get endpoint and transfer/schedule data */ |
812 | epnum = ep->desc.bEndpointAddress; | 811 | epnum = urb->ep->desc.bEndpointAddress; |
813 | 812 | ||
814 | spin_lock_irqsave (&ehci->lock, flags); | 813 | spin_lock_irqsave (&ehci->lock, flags); |
815 | 814 | ||
816 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 815 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
817 | &ehci_to_hcd(ehci)->flags))) { | 816 | &ehci_to_hcd(ehci)->flags))) { |
818 | status = -ESHUTDOWN; | 817 | status = -ESHUTDOWN; |
819 | goto done; | 818 | goto done_not_linked; |
820 | } | 819 | } |
820 | status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); | ||
821 | if (unlikely(status)) | ||
822 | goto done_not_linked; | ||
821 | 823 | ||
822 | /* get qh and force any scheduling errors */ | 824 | /* get qh and force any scheduling errors */ |
823 | INIT_LIST_HEAD (&empty); | 825 | INIT_LIST_HEAD (&empty); |
824 | qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); | 826 | qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); |
825 | if (qh == NULL) { | 827 | if (qh == NULL) { |
826 | status = -ENOMEM; | 828 | status = -ENOMEM; |
827 | goto done; | 829 | goto done; |
@@ -832,13 +834,16 @@ static int intr_submit ( | |||
832 | } | 834 | } |
833 | 835 | ||
834 | /* then queue the urb's tds to the qh */ | 836 | /* then queue the urb's tds to the qh */ |
835 | qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); | 837 | qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); |
836 | BUG_ON (qh == NULL); | 838 | BUG_ON (qh == NULL); |
837 | 839 | ||
838 | /* ... update usbfs periodic stats */ | 840 | /* ... update usbfs periodic stats */ |
839 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; | 841 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; |
840 | 842 | ||
841 | done: | 843 | done: |
844 | if (unlikely(status)) | ||
845 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | ||
846 | done_not_linked: | ||
842 | spin_unlock_irqrestore (&ehci->lock, flags); | 847 | spin_unlock_irqrestore (&ehci->lock, flags); |
843 | if (status) | 848 | if (status) |
844 | qtd_list_free (ehci, urb, qtd_list); | 849 | qtd_list_free (ehci, urb, qtd_list); |
@@ -1622,7 +1627,7 @@ itd_complete ( | |||
1622 | 1627 | ||
1623 | /* give urb back to the driver ... can be out-of-order */ | 1628 | /* give urb back to the driver ... can be out-of-order */ |
1624 | dev = urb->dev; | 1629 | dev = urb->dev; |
1625 | ehci_urb_done (ehci, urb); | 1630 | ehci_urb_done(ehci, urb, 0); |
1626 | urb = NULL; | 1631 | urb = NULL; |
1627 | 1632 | ||
1628 | /* defer stopping schedule; completion can submit */ | 1633 | /* defer stopping schedule; completion can submit */ |
@@ -1686,12 +1691,19 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
1686 | /* schedule ... need to lock */ | 1691 | /* schedule ... need to lock */ |
1687 | spin_lock_irqsave (&ehci->lock, flags); | 1692 | spin_lock_irqsave (&ehci->lock, flags); |
1688 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 1693 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
1689 | &ehci_to_hcd(ehci)->flags))) | 1694 | &ehci_to_hcd(ehci)->flags))) { |
1690 | status = -ESHUTDOWN; | 1695 | status = -ESHUTDOWN; |
1691 | else | 1696 | goto done_not_linked; |
1692 | status = iso_stream_schedule (ehci, urb, stream); | 1697 | } |
1698 | status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); | ||
1699 | if (unlikely(status)) | ||
1700 | goto done_not_linked; | ||
1701 | status = iso_stream_schedule(ehci, urb, stream); | ||
1693 | if (likely (status == 0)) | 1702 | if (likely (status == 0)) |
1694 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1703 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
1704 | else | ||
1705 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | ||
1706 | done_not_linked: | ||
1695 | spin_unlock_irqrestore (&ehci->lock, flags); | 1707 | spin_unlock_irqrestore (&ehci->lock, flags); |
1696 | 1708 | ||
1697 | done: | 1709 | done: |
@@ -1988,7 +2000,7 @@ sitd_complete ( | |||
1988 | 2000 | ||
1989 | /* give urb back to the driver */ | 2001 | /* give urb back to the driver */ |
1990 | dev = urb->dev; | 2002 | dev = urb->dev; |
1991 | ehci_urb_done (ehci, urb); | 2003 | ehci_urb_done(ehci, urb, 0); |
1992 | urb = NULL; | 2004 | urb = NULL; |
1993 | 2005 | ||
1994 | /* defer stopping schedule; completion can submit */ | 2006 | /* defer stopping schedule; completion can submit */ |
@@ -2049,12 +2061,19 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
2049 | /* schedule ... need to lock */ | 2061 | /* schedule ... need to lock */ |
2050 | spin_lock_irqsave (&ehci->lock, flags); | 2062 | spin_lock_irqsave (&ehci->lock, flags); |
2051 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 2063 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
2052 | &ehci_to_hcd(ehci)->flags))) | 2064 | &ehci_to_hcd(ehci)->flags))) { |
2053 | status = -ESHUTDOWN; | 2065 | status = -ESHUTDOWN; |
2054 | else | 2066 | goto done_not_linked; |
2055 | status = iso_stream_schedule (ehci, urb, stream); | 2067 | } |
2068 | status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); | ||
2069 | if (unlikely(status)) | ||
2070 | goto done_not_linked; | ||
2071 | status = iso_stream_schedule(ehci, urb, stream); | ||
2056 | if (status == 0) | 2072 | if (status == 0) |
2057 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 2073 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
2074 | else | ||
2075 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | ||
2076 | done_not_linked: | ||
2058 | spin_unlock_irqrestore (&ehci->lock, flags); | 2077 | spin_unlock_irqrestore (&ehci->lock, flags); |
2059 | 2078 | ||
2060 | done: | 2079 | done: |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 5c851a36de72..c27417f5b9d8 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -277,12 +277,11 @@ static void preproc_atl_queue(struct isp116x *isp116x) | |||
277 | processed urbs. | 277 | processed urbs. |
278 | */ | 278 | */ |
279 | static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, | 279 | static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, |
280 | struct urb *urb) | 280 | struct urb *urb, int status) |
281 | __releases(isp116x->lock) __acquires(isp116x->lock) | 281 | __releases(isp116x->lock) __acquires(isp116x->lock) |
282 | { | 282 | { |
283 | unsigned i; | 283 | unsigned i; |
284 | 284 | ||
285 | urb->hcpriv = NULL; | ||
286 | ep->error_count = 0; | 285 | ep->error_count = 0; |
287 | 286 | ||
288 | if (usb_pipecontrol(urb->pipe)) | 287 | if (usb_pipecontrol(urb->pipe)) |
@@ -290,8 +289,9 @@ __releases(isp116x->lock) __acquires(isp116x->lock) | |||
290 | 289 | ||
291 | urb_dbg(urb, "Finish"); | 290 | urb_dbg(urb, "Finish"); |
292 | 291 | ||
292 | usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb); | ||
293 | spin_unlock(&isp116x->lock); | 293 | spin_unlock(&isp116x->lock); |
294 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); | 294 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, status); |
295 | spin_lock(&isp116x->lock); | 295 | spin_lock(&isp116x->lock); |
296 | 296 | ||
297 | /* take idle endpoints out of the schedule */ | 297 | /* take idle endpoints out of the schedule */ |
@@ -445,12 +445,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) | |||
445 | if (PTD_GET_ACTIVE(ptd) | 445 | if (PTD_GET_ACTIVE(ptd) |
446 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | 446 | || (cc != TD_CC_NOERROR && cc < 0x0E)) |
447 | break; | 447 | break; |
448 | if ((urb->transfer_flags & URB_SHORT_NOT_OK) && | 448 | status = 0; |
449 | urb->actual_length < | ||
450 | urb->transfer_buffer_length) | ||
451 | status = -EREMOTEIO; | ||
452 | else | ||
453 | status = 0; | ||
454 | ep->nextpid = 0; | 449 | ep->nextpid = 0; |
455 | break; | 450 | break; |
456 | default: | 451 | default: |
@@ -458,14 +453,8 @@ static void postproc_atl_queue(struct isp116x *isp116x) | |||
458 | } | 453 | } |
459 | 454 | ||
460 | done: | 455 | done: |
461 | if (status != -EINPROGRESS) { | 456 | if (status != -EINPROGRESS || urb->unlinked) |
462 | spin_lock(&urb->lock); | 457 | finish_request(isp116x, ep, urb, status); |
463 | if (urb->status == -EINPROGRESS) | ||
464 | urb->status = status; | ||
465 | spin_unlock(&urb->lock); | ||
466 | } | ||
467 | if (urb->status != -EINPROGRESS) | ||
468 | finish_request(isp116x, ep, urb); | ||
469 | } | 458 | } |
470 | } | 459 | } |
471 | 460 | ||
@@ -673,7 +662,7 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load) | |||
673 | /*-----------------------------------------------------------------*/ | 662 | /*-----------------------------------------------------------------*/ |
674 | 663 | ||
675 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, | 664 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, |
676 | struct usb_host_endpoint *hep, struct urb *urb, | 665 | struct urb *urb, |
677 | gfp_t mem_flags) | 666 | gfp_t mem_flags) |
678 | { | 667 | { |
679 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 668 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
@@ -682,6 +671,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
682 | int is_out = !usb_pipein(pipe); | 671 | int is_out = !usb_pipein(pipe); |
683 | int type = usb_pipetype(pipe); | 672 | int type = usb_pipetype(pipe); |
684 | int epnum = usb_pipeendpoint(pipe); | 673 | int epnum = usb_pipeendpoint(pipe); |
674 | struct usb_host_endpoint *hep = urb->ep; | ||
685 | struct isp116x_ep *ep = NULL; | 675 | struct isp116x_ep *ep = NULL; |
686 | unsigned long flags; | 676 | unsigned long flags; |
687 | int i; | 677 | int i; |
@@ -705,7 +695,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
705 | if (!HC_IS_RUNNING(hcd->state)) { | 695 | if (!HC_IS_RUNNING(hcd->state)) { |
706 | kfree(ep); | 696 | kfree(ep); |
707 | ret = -ENODEV; | 697 | ret = -ENODEV; |
708 | goto fail; | 698 | goto fail_not_linked; |
699 | } | ||
700 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
701 | if (ret) { | ||
702 | kfree(ep); | ||
703 | goto fail_not_linked; | ||
709 | } | 704 | } |
710 | 705 | ||
711 | if (hep->hcpriv) | 706 | if (hep->hcpriv) |
@@ -808,16 +803,13 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
808 | } | 803 | } |
809 | } | 804 | } |
810 | 805 | ||
811 | /* in case of unlink-during-submit */ | ||
812 | if (urb->status != -EINPROGRESS) { | ||
813 | finish_request(isp116x, ep, urb); | ||
814 | ret = 0; | ||
815 | goto fail; | ||
816 | } | ||
817 | urb->hcpriv = hep; | 806 | urb->hcpriv = hep; |
818 | start_atl_transfers(isp116x); | 807 | start_atl_transfers(isp116x); |
819 | 808 | ||
820 | fail: | 809 | fail: |
810 | if (ret) | ||
811 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
812 | fail_not_linked: | ||
821 | spin_unlock_irqrestore(&isp116x->lock, flags); | 813 | spin_unlock_irqrestore(&isp116x->lock, flags); |
822 | return ret; | 814 | return ret; |
823 | } | 815 | } |
@@ -825,20 +817,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
825 | /* | 817 | /* |
826 | Dequeue URBs. | 818 | Dequeue URBs. |
827 | */ | 819 | */ |
828 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 820 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, |
821 | int status) | ||
829 | { | 822 | { |
830 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 823 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
831 | struct usb_host_endpoint *hep; | 824 | struct usb_host_endpoint *hep; |
832 | struct isp116x_ep *ep, *ep_act; | 825 | struct isp116x_ep *ep, *ep_act; |
833 | unsigned long flags; | 826 | unsigned long flags; |
827 | int rc; | ||
834 | 828 | ||
835 | spin_lock_irqsave(&isp116x->lock, flags); | 829 | spin_lock_irqsave(&isp116x->lock, flags); |
830 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
831 | if (rc) | ||
832 | goto done; | ||
833 | |||
836 | hep = urb->hcpriv; | 834 | hep = urb->hcpriv; |
837 | /* URB already unlinked (or never linked)? */ | ||
838 | if (!hep) { | ||
839 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
840 | return 0; | ||
841 | } | ||
842 | ep = hep->hcpriv; | 835 | ep = hep->hcpriv; |
843 | WARN_ON(hep != ep->hep); | 836 | WARN_ON(hep != ep->hep); |
844 | 837 | ||
@@ -855,10 +848,10 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
855 | } | 848 | } |
856 | 849 | ||
857 | if (urb) | 850 | if (urb) |
858 | finish_request(isp116x, ep, urb); | 851 | finish_request(isp116x, ep, urb, status); |
859 | 852 | done: | |
860 | spin_unlock_irqrestore(&isp116x->lock, flags); | 853 | spin_unlock_irqrestore(&isp116x->lock, flags); |
861 | return 0; | 854 | return rc; |
862 | } | 855 | } |
863 | 856 | ||
864 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, | 857 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index f61c6cdd06f2..ebab5ce8f5ce 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * small: 0) header + data packets 1) just header | 24 | * small: 0) header + data packets 1) just header |
25 | */ | 25 | */ |
26 | static void __maybe_unused | 26 | static void __maybe_unused |
27 | urb_print (struct urb * urb, char * str, int small) | 27 | urb_print(struct urb * urb, char * str, int small, int status) |
28 | { | 28 | { |
29 | unsigned int pipe= urb->pipe; | 29 | unsigned int pipe= urb->pipe; |
30 | 30 | ||
@@ -34,7 +34,7 @@ urb_print (struct urb * urb, char * str, int small) | |||
34 | } | 34 | } |
35 | 35 | ||
36 | #ifndef OHCI_VERBOSE_DEBUG | 36 | #ifndef OHCI_VERBOSE_DEBUG |
37 | if (urb->status != 0) | 37 | if (status != 0) |
38 | #endif | 38 | #endif |
39 | dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", | 39 | dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", |
40 | str, | 40 | str, |
@@ -46,7 +46,7 @@ urb_print (struct urb * urb, char * str, int small) | |||
46 | urb->transfer_flags, | 46 | urb->transfer_flags, |
47 | urb->actual_length, | 47 | urb->actual_length, |
48 | urb->transfer_buffer_length, | 48 | urb->transfer_buffer_length, |
49 | urb->status); | 49 | status); |
50 | 50 | ||
51 | #ifdef OHCI_VERBOSE_DEBUG | 51 | #ifdef OHCI_VERBOSE_DEBUG |
52 | if (!small) { | 52 | if (!small) { |
@@ -66,7 +66,7 @@ urb_print (struct urb * urb, char * str, int small) | |||
66 | urb->transfer_buffer_length: urb->actual_length; | 66 | urb->transfer_buffer_length: urb->actual_length; |
67 | for (i = 0; i < 16 && i < len; i++) | 67 | for (i = 0; i < 16 && i < len; i++) |
68 | printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); | 68 | printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); |
69 | printk ("%s stat:%d\n", i < len? "...": "", urb->status); | 69 | printk ("%s stat:%d\n", i < len? "...": "", status); |
70 | } | 70 | } |
71 | } | 71 | } |
72 | #endif | 72 | #endif |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 6edf4097d2d2..240c7f507541 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -81,7 +81,6 @@ static void ohci_dump (struct ohci_hcd *ohci, int verbose); | |||
81 | static int ohci_init (struct ohci_hcd *ohci); | 81 | static int ohci_init (struct ohci_hcd *ohci); |
82 | static void ohci_stop (struct usb_hcd *hcd); | 82 | static void ohci_stop (struct usb_hcd *hcd); |
83 | static int ohci_restart (struct ohci_hcd *ohci); | 83 | static int ohci_restart (struct ohci_hcd *ohci); |
84 | static void ohci_quirk_nec_worker (struct work_struct *work); | ||
85 | 84 | ||
86 | #include "ohci-hub.c" | 85 | #include "ohci-hub.c" |
87 | #include "ohci-dbg.c" | 86 | #include "ohci-dbg.c" |
@@ -118,7 +117,6 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake"); | |||
118 | */ | 117 | */ |
119 | static int ohci_urb_enqueue ( | 118 | static int ohci_urb_enqueue ( |
120 | struct usb_hcd *hcd, | 119 | struct usb_hcd *hcd, |
121 | struct usb_host_endpoint *ep, | ||
122 | struct urb *urb, | 120 | struct urb *urb, |
123 | gfp_t mem_flags | 121 | gfp_t mem_flags |
124 | ) { | 122 | ) { |
@@ -131,11 +129,11 @@ static int ohci_urb_enqueue ( | |||
131 | int retval = 0; | 129 | int retval = 0; |
132 | 130 | ||
133 | #ifdef OHCI_VERBOSE_DEBUG | 131 | #ifdef OHCI_VERBOSE_DEBUG |
134 | urb_print (urb, "SUB", usb_pipein (pipe)); | 132 | urb_print(urb, "SUB", usb_pipein(pipe), -EINPROGRESS); |
135 | #endif | 133 | #endif |
136 | 134 | ||
137 | /* every endpoint has a ed, locate and maybe (re)initialize it */ | 135 | /* every endpoint has a ed, locate and maybe (re)initialize it */ |
138 | if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval))) | 136 | if (! (ed = ed_get (ohci, urb->ep, urb->dev, pipe, urb->interval))) |
139 | return -ENOMEM; | 137 | return -ENOMEM; |
140 | 138 | ||
141 | /* for the private part of the URB we need the number of TDs (size) */ | 139 | /* for the private part of the URB we need the number of TDs (size) */ |
@@ -200,22 +198,17 @@ static int ohci_urb_enqueue ( | |||
200 | retval = -ENODEV; | 198 | retval = -ENODEV; |
201 | goto fail; | 199 | goto fail; |
202 | } | 200 | } |
203 | 201 | retval = usb_hcd_link_urb_to_ep(hcd, urb); | |
204 | /* in case of unlink-during-submit */ | 202 | if (retval) |
205 | spin_lock (&urb->lock); | ||
206 | if (urb->status != -EINPROGRESS) { | ||
207 | spin_unlock (&urb->lock); | ||
208 | urb->hcpriv = urb_priv; | ||
209 | finish_urb (ohci, urb); | ||
210 | retval = 0; | ||
211 | goto fail; | 203 | goto fail; |
212 | } | ||
213 | 204 | ||
214 | /* schedule the ed if needed */ | 205 | /* schedule the ed if needed */ |
215 | if (ed->state == ED_IDLE) { | 206 | if (ed->state == ED_IDLE) { |
216 | retval = ed_schedule (ohci, ed); | 207 | retval = ed_schedule (ohci, ed); |
217 | if (retval < 0) | 208 | if (retval < 0) { |
218 | goto fail0; | 209 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
210 | goto fail; | ||
211 | } | ||
219 | if (ed->type == PIPE_ISOCHRONOUS) { | 212 | if (ed->type == PIPE_ISOCHRONOUS) { |
220 | u16 frame = ohci_frame_no(ohci); | 213 | u16 frame = ohci_frame_no(ohci); |
221 | 214 | ||
@@ -239,8 +232,6 @@ static int ohci_urb_enqueue ( | |||
239 | urb->hcpriv = urb_priv; | 232 | urb->hcpriv = urb_priv; |
240 | td_submit_urb (ohci, urb); | 233 | td_submit_urb (ohci, urb); |
241 | 234 | ||
242 | fail0: | ||
243 | spin_unlock (&urb->lock); | ||
244 | fail: | 235 | fail: |
245 | if (retval) | 236 | if (retval) |
246 | urb_free_priv (ohci, urb_priv); | 237 | urb_free_priv (ohci, urb_priv); |
@@ -249,22 +240,26 @@ fail: | |||
249 | } | 240 | } |
250 | 241 | ||
251 | /* | 242 | /* |
252 | * decouple the URB from the HC queues (TDs, urb_priv); it's | 243 | * decouple the URB from the HC queues (TDs, urb_priv). |
253 | * already marked using urb->status. reporting is always done | 244 | * reporting is always done |
254 | * asynchronously, and we might be dealing with an urb that's | 245 | * asynchronously, and we might be dealing with an urb that's |
255 | * partially transferred, or an ED with other urbs being unlinked. | 246 | * partially transferred, or an ED with other urbs being unlinked. |
256 | */ | 247 | */ |
257 | static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 248 | static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
258 | { | 249 | { |
259 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 250 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
260 | unsigned long flags; | 251 | unsigned long flags; |
252 | int rc; | ||
261 | 253 | ||
262 | #ifdef OHCI_VERBOSE_DEBUG | 254 | #ifdef OHCI_VERBOSE_DEBUG |
263 | urb_print (urb, "UNLINK", 1); | 255 | urb_print(urb, "UNLINK", 1, status); |
264 | #endif | 256 | #endif |
265 | 257 | ||
266 | spin_lock_irqsave (&ohci->lock, flags); | 258 | spin_lock_irqsave (&ohci->lock, flags); |
267 | if (HC_IS_RUNNING(hcd->state)) { | 259 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); |
260 | if (rc) { | ||
261 | ; /* Do nothing */ | ||
262 | } else if (HC_IS_RUNNING(hcd->state)) { | ||
268 | urb_priv_t *urb_priv; | 263 | urb_priv_t *urb_priv; |
269 | 264 | ||
270 | /* Unless an IRQ completed the unlink while it was being | 265 | /* Unless an IRQ completed the unlink while it was being |
@@ -282,10 +277,10 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
282 | * any more ... just clean up every urb's memory. | 277 | * any more ... just clean up every urb's memory. |
283 | */ | 278 | */ |
284 | if (urb->hcpriv) | 279 | if (urb->hcpriv) |
285 | finish_urb (ohci, urb); | 280 | finish_urb(ohci, urb, status); |
286 | } | 281 | } |
287 | spin_unlock_irqrestore (&ohci->lock, flags); | 282 | spin_unlock_irqrestore (&ohci->lock, flags); |
288 | return 0; | 283 | return rc; |
289 | } | 284 | } |
290 | 285 | ||
291 | /*-------------------------------------------------------------------------*/ | 286 | /*-------------------------------------------------------------------------*/ |
@@ -314,6 +309,8 @@ rescan: | |||
314 | if (!HC_IS_RUNNING (hcd->state)) { | 309 | if (!HC_IS_RUNNING (hcd->state)) { |
315 | sanitize: | 310 | sanitize: |
316 | ed->state = ED_IDLE; | 311 | ed->state = ED_IDLE; |
312 | if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) | ||
313 | ohci->eds_scheduled--; | ||
317 | finish_unlinks (ohci, 0); | 314 | finish_unlinks (ohci, 0); |
318 | } | 315 | } |
319 | 316 | ||
@@ -321,7 +318,12 @@ sanitize: | |||
321 | case ED_UNLINK: /* wait for hw to finish? */ | 318 | case ED_UNLINK: /* wait for hw to finish? */ |
322 | /* major IRQ delivery trouble loses INTR_SF too... */ | 319 | /* major IRQ delivery trouble loses INTR_SF too... */ |
323 | if (limit-- == 0) { | 320 | if (limit-- == 0) { |
324 | ohci_warn (ohci, "IRQ INTR_SF lossage\n"); | 321 | ohci_warn(ohci, "ED unlink timeout\n"); |
322 | if (quirk_zfmicro(ohci)) { | ||
323 | ohci_warn(ohci, "Attempting ZF TD recovery\n"); | ||
324 | ohci->ed_to_check = ed; | ||
325 | ohci->zf_delay = 2; | ||
326 | } | ||
325 | goto sanitize; | 327 | goto sanitize; |
326 | } | 328 | } |
327 | spin_unlock_irqrestore (&ohci->lock, flags); | 329 | spin_unlock_irqrestore (&ohci->lock, flags); |
@@ -379,6 +381,93 @@ ohci_shutdown (struct usb_hcd *hcd) | |||
379 | (void) ohci_readl (ohci, &ohci->regs->control); | 381 | (void) ohci_readl (ohci, &ohci->regs->control); |
380 | } | 382 | } |
381 | 383 | ||
384 | static int check_ed(struct ohci_hcd *ohci, struct ed *ed) | ||
385 | { | ||
386 | return (hc32_to_cpu(ohci, ed->hwINFO) & ED_IN) != 0 | ||
387 | && (hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK) | ||
388 | == (hc32_to_cpu(ohci, ed->hwTailP) & TD_MASK) | ||
389 | && !list_empty(&ed->td_list); | ||
390 | } | ||
391 | |||
392 | /* ZF Micro watchdog timer callback. The ZF Micro chipset sometimes completes | ||
393 | * an interrupt TD but neglects to add it to the donelist. On systems with | ||
394 | * this chipset, we need to periodically check the state of the queues to look | ||
395 | * for such "lost" TDs. | ||
396 | */ | ||
397 | static void unlink_watchdog_func(unsigned long _ohci) | ||
398 | { | ||
399 | long flags; | ||
400 | unsigned max; | ||
401 | unsigned seen_count = 0; | ||
402 | unsigned i; | ||
403 | struct ed **seen = NULL; | ||
404 | struct ohci_hcd *ohci = (struct ohci_hcd *) _ohci; | ||
405 | |||
406 | spin_lock_irqsave(&ohci->lock, flags); | ||
407 | max = ohci->eds_scheduled; | ||
408 | if (!max) | ||
409 | goto done; | ||
410 | |||
411 | if (ohci->ed_to_check) | ||
412 | goto out; | ||
413 | |||
414 | seen = kcalloc(max, sizeof *seen, GFP_ATOMIC); | ||
415 | if (!seen) | ||
416 | goto out; | ||
417 | |||
418 | for (i = 0; i < NUM_INTS; i++) { | ||
419 | struct ed *ed = ohci->periodic[i]; | ||
420 | |||
421 | while (ed) { | ||
422 | unsigned temp; | ||
423 | |||
424 | /* scan this branch of the periodic schedule tree */ | ||
425 | for (temp = 0; temp < seen_count; temp++) { | ||
426 | if (seen[temp] == ed) { | ||
427 | /* we've checked it and what's after */ | ||
428 | ed = NULL; | ||
429 | break; | ||
430 | } | ||
431 | } | ||
432 | if (!ed) | ||
433 | break; | ||
434 | seen[seen_count++] = ed; | ||
435 | if (!check_ed(ohci, ed)) { | ||
436 | ed = ed->ed_next; | ||
437 | continue; | ||
438 | } | ||
439 | |||
440 | /* HC's TD list is empty, but HCD sees at least one | ||
441 | * TD that's not been sent through the donelist. | ||
442 | */ | ||
443 | ohci->ed_to_check = ed; | ||
444 | ohci->zf_delay = 2; | ||
445 | |||
446 | /* The HC may wait until the next frame to report the | ||
447 | * TD as done through the donelist and INTR_WDH. (We | ||
448 | * just *assume* it's not a multi-TD interrupt URB; | ||
449 | * those could defer the IRQ more than one frame, using | ||
450 | * DI...) Check again after the next INTR_SF. | ||
451 | */ | ||
452 | ohci_writel(ohci, OHCI_INTR_SF, | ||
453 | &ohci->regs->intrstatus); | ||
454 | ohci_writel(ohci, OHCI_INTR_SF, | ||
455 | &ohci->regs->intrenable); | ||
456 | |||
457 | /* flush those writes */ | ||
458 | (void) ohci_readl(ohci, &ohci->regs->control); | ||
459 | |||
460 | goto out; | ||
461 | } | ||
462 | } | ||
463 | out: | ||
464 | kfree(seen); | ||
465 | if (ohci->eds_scheduled) | ||
466 | mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ)); | ||
467 | done: | ||
468 | spin_unlock_irqrestore(&ohci->lock, flags); | ||
469 | } | ||
470 | |||
382 | /*-------------------------------------------------------------------------* | 471 | /*-------------------------------------------------------------------------* |
383 | * HC functions | 472 | * HC functions |
384 | *-------------------------------------------------------------------------*/ | 473 | *-------------------------------------------------------------------------*/ |
@@ -616,6 +705,15 @@ retry: | |||
616 | mdelay ((temp >> 23) & 0x1fe); | 705 | mdelay ((temp >> 23) & 0x1fe); |
617 | hcd->state = HC_STATE_RUNNING; | 706 | hcd->state = HC_STATE_RUNNING; |
618 | 707 | ||
708 | if (quirk_zfmicro(ohci)) { | ||
709 | /* Create timer to watch for bad queue state on ZF Micro */ | ||
710 | setup_timer(&ohci->unlink_watchdog, unlink_watchdog_func, | ||
711 | (unsigned long) ohci); | ||
712 | |||
713 | ohci->eds_scheduled = 0; | ||
714 | ohci->ed_to_check = NULL; | ||
715 | } | ||
716 | |||
619 | ohci_dump (ohci, 1); | 717 | ohci_dump (ohci, 1); |
620 | 718 | ||
621 | return 0; | 719 | return 0; |
@@ -629,10 +727,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
629 | { | 727 | { |
630 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 728 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
631 | struct ohci_regs __iomem *regs = ohci->regs; | 729 | struct ohci_regs __iomem *regs = ohci->regs; |
632 | int ints; | 730 | int ints; |
633 | 731 | ||
634 | /* we can eliminate a (slow) ohci_readl() | 732 | /* we can eliminate a (slow) ohci_readl() |
635 | if _only_ WDH caused this irq */ | 733 | * if _only_ WDH caused this irq |
734 | */ | ||
636 | if ((ohci->hcca->done_head != 0) | 735 | if ((ohci->hcca->done_head != 0) |
637 | && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) | 736 | && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) |
638 | & 0x01)) { | 737 | & 0x01)) { |
@@ -651,7 +750,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
651 | 750 | ||
652 | if (ints & OHCI_INTR_UE) { | 751 | if (ints & OHCI_INTR_UE) { |
653 | // e.g. due to PCI Master/Target Abort | 752 | // e.g. due to PCI Master/Target Abort |
654 | if (ohci->flags & OHCI_QUIRK_NEC) { | 753 | if (quirk_nec(ohci)) { |
655 | /* Workaround for a silicon bug in some NEC chips used | 754 | /* Workaround for a silicon bug in some NEC chips used |
656 | * in Apple's PowerBooks. Adapted from Darwin code. | 755 | * in Apple's PowerBooks. Adapted from Darwin code. |
657 | */ | 756 | */ |
@@ -713,6 +812,31 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
713 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); | 812 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); |
714 | } | 813 | } |
715 | 814 | ||
815 | if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) { | ||
816 | spin_lock(&ohci->lock); | ||
817 | if (ohci->ed_to_check) { | ||
818 | struct ed *ed = ohci->ed_to_check; | ||
819 | |||
820 | if (check_ed(ohci, ed)) { | ||
821 | /* HC thinks the TD list is empty; HCD knows | ||
822 | * at least one TD is outstanding | ||
823 | */ | ||
824 | if (--ohci->zf_delay == 0) { | ||
825 | struct td *td = list_entry( | ||
826 | ed->td_list.next, | ||
827 | struct td, td_list); | ||
828 | ohci_warn(ohci, | ||
829 | "Reclaiming orphan TD %p\n", | ||
830 | td); | ||
831 | takeback_td(ohci, td); | ||
832 | ohci->ed_to_check = NULL; | ||
833 | } | ||
834 | } else | ||
835 | ohci->ed_to_check = NULL; | ||
836 | } | ||
837 | spin_unlock(&ohci->lock); | ||
838 | } | ||
839 | |||
716 | /* could track INTR_SO to reduce available PCI/... bandwidth */ | 840 | /* could track INTR_SO to reduce available PCI/... bandwidth */ |
717 | 841 | ||
718 | /* handle any pending URB/ED unlinks, leaving INTR_SF enabled | 842 | /* handle any pending URB/ED unlinks, leaving INTR_SF enabled |
@@ -721,7 +845,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
721 | spin_lock (&ohci->lock); | 845 | spin_lock (&ohci->lock); |
722 | if (ohci->ed_rm_list) | 846 | if (ohci->ed_rm_list) |
723 | finish_unlinks (ohci, ohci_frame_no(ohci)); | 847 | finish_unlinks (ohci, ohci_frame_no(ohci)); |
724 | if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list | 848 | if ((ints & OHCI_INTR_SF) != 0 |
849 | && !ohci->ed_rm_list | ||
850 | && !ohci->ed_to_check | ||
725 | && HC_IS_RUNNING(hcd->state)) | 851 | && HC_IS_RUNNING(hcd->state)) |
726 | ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); | 852 | ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); |
727 | spin_unlock (&ohci->lock); | 853 | spin_unlock (&ohci->lock); |
@@ -751,6 +877,9 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
751 | free_irq(hcd->irq, hcd); | 877 | free_irq(hcd->irq, hcd); |
752 | hcd->irq = -1; | 878 | hcd->irq = -1; |
753 | 879 | ||
880 | if (quirk_zfmicro(ohci)) | ||
881 | del_timer(&ohci->unlink_watchdog); | ||
882 | |||
754 | remove_debug_files (ohci); | 883 | remove_debug_files (ohci); |
755 | ohci_mem_cleanup (ohci); | 884 | ohci_mem_cleanup (ohci); |
756 | if (ohci->hcca) { | 885 | if (ohci->hcca) { |
@@ -798,9 +927,8 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
798 | ed, ed->state); | 927 | ed, ed->state); |
799 | } | 928 | } |
800 | 929 | ||
801 | spin_lock (&urb->lock); | 930 | if (!urb->unlinked) |
802 | urb->status = -ESHUTDOWN; | 931 | urb->unlinked = -ESHUTDOWN; |
803 | spin_unlock (&urb->lock); | ||
804 | } | 932 | } |
805 | finish_unlinks (ohci, 0); | 933 | finish_unlinks (ohci, 0); |
806 | spin_unlock_irq(&ohci->lock); | 934 | spin_unlock_irq(&ohci->lock); |
@@ -828,27 +956,6 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
828 | 956 | ||
829 | /*-------------------------------------------------------------------------*/ | 957 | /*-------------------------------------------------------------------------*/ |
830 | 958 | ||
831 | /* NEC workaround */ | ||
832 | static void ohci_quirk_nec_worker(struct work_struct *work) | ||
833 | { | ||
834 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); | ||
835 | int status; | ||
836 | |||
837 | status = ohci_init(ohci); | ||
838 | if (status != 0) { | ||
839 | ohci_err(ohci, "Restarting NEC controller failed " | ||
840 | "in ohci_init, %d\n", status); | ||
841 | return; | ||
842 | } | ||
843 | |||
844 | status = ohci_restart(ohci); | ||
845 | if (status != 0) | ||
846 | ohci_err(ohci, "Restarting NEC controller failed " | ||
847 | "in ohci_restart, %d\n", status); | ||
848 | } | ||
849 | |||
850 | /*-------------------------------------------------------------------------*/ | ||
851 | |||
852 | #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC | 959 | #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC |
853 | 960 | ||
854 | MODULE_AUTHOR (DRIVER_AUTHOR); | 961 | MODULE_AUTHOR (DRIVER_AUTHOR); |
@@ -926,11 +1033,17 @@ MODULE_LICENSE ("GPL"); | |||
926 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver | 1033 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver |
927 | #endif | 1034 | #endif |
928 | 1035 | ||
1036 | #ifdef CONFIG_USB_OHCI_HCD_SSB | ||
1037 | #include "ohci-ssb.c" | ||
1038 | #define SSB_OHCI_DRIVER ssb_ohci_driver | ||
1039 | #endif | ||
1040 | |||
929 | #if !defined(PCI_DRIVER) && \ | 1041 | #if !defined(PCI_DRIVER) && \ |
930 | !defined(PLATFORM_DRIVER) && \ | 1042 | !defined(PLATFORM_DRIVER) && \ |
931 | !defined(OF_PLATFORM_DRIVER) && \ | 1043 | !defined(OF_PLATFORM_DRIVER) && \ |
932 | !defined(SA1111_DRIVER) && \ | 1044 | !defined(SA1111_DRIVER) && \ |
933 | !defined(PS3_SYSTEM_BUS_DRIVER) | 1045 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ |
1046 | !defined(SSB_OHCI_DRIVER) | ||
934 | #error "missing bus glue for ohci-hcd" | 1047 | #error "missing bus glue for ohci-hcd" |
935 | #endif | 1048 | #endif |
936 | 1049 | ||
@@ -975,10 +1088,20 @@ static int __init ohci_hcd_mod_init(void) | |||
975 | goto error_pci; | 1088 | goto error_pci; |
976 | #endif | 1089 | #endif |
977 | 1090 | ||
1091 | #ifdef SSB_OHCI_DRIVER | ||
1092 | retval = ssb_driver_register(&SSB_OHCI_DRIVER); | ||
1093 | if (retval) | ||
1094 | goto error_ssb; | ||
1095 | #endif | ||
1096 | |||
978 | return retval; | 1097 | return retval; |
979 | 1098 | ||
980 | /* Error path */ | 1099 | /* Error path */ |
1100 | #ifdef SSB_OHCI_DRIVER | ||
1101 | error_ssb: | ||
1102 | #endif | ||
981 | #ifdef PCI_DRIVER | 1103 | #ifdef PCI_DRIVER |
1104 | pci_unregister_driver(&PCI_DRIVER); | ||
982 | error_pci: | 1105 | error_pci: |
983 | #endif | 1106 | #endif |
984 | #ifdef SA1111_DRIVER | 1107 | #ifdef SA1111_DRIVER |
@@ -1003,6 +1126,9 @@ module_init(ohci_hcd_mod_init); | |||
1003 | 1126 | ||
1004 | static void __exit ohci_hcd_mod_exit(void) | 1127 | static void __exit ohci_hcd_mod_exit(void) |
1005 | { | 1128 | { |
1129 | #ifdef SSB_OHCI_DRIVER | ||
1130 | ssb_driver_unregister(&SSB_OHCI_DRIVER); | ||
1131 | #endif | ||
1006 | #ifdef PCI_DRIVER | 1132 | #ifdef PCI_DRIVER |
1007 | pci_unregister_driver(&PCI_DRIVER); | 1133 | pci_unregister_driver(&PCI_DRIVER); |
1008 | #endif | 1134 | #endif |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index 450c7b460c5a..2f20d3dc895b 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
28 | ohci->next_statechange = jiffies; | 28 | ohci->next_statechange = jiffies; |
29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
31 | INIT_WORK (&ohci->nec_work, ohci_quirk_nec_worker); | ||
32 | } | 31 | } |
33 | 32 | ||
34 | /*-------------------------------------------------------------------------*/ | 33 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index a5e2eb85d073..d0360f65ebd9 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -84,7 +84,7 @@ static int ohci_quirk_zfmicro(struct usb_hcd *hcd) | |||
84 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 84 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
85 | 85 | ||
86 | ohci->flags |= OHCI_QUIRK_ZFMICRO; | 86 | ohci->flags |= OHCI_QUIRK_ZFMICRO; |
87 | ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); | 87 | ohci_dbg(ohci, "enabled Compaq ZFMicro chipset quirks\n"); |
88 | 88 | ||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
@@ -113,11 +113,31 @@ static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd) | |||
113 | 113 | ||
114 | /* Check for NEC chip and apply quirk for allegedly lost interrupts. | 114 | /* Check for NEC chip and apply quirk for allegedly lost interrupts. |
115 | */ | 115 | */ |
116 | |||
117 | static void ohci_quirk_nec_worker(struct work_struct *work) | ||
118 | { | ||
119 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); | ||
120 | int status; | ||
121 | |||
122 | status = ohci_init(ohci); | ||
123 | if (status != 0) { | ||
124 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | ||
125 | "ohci_init", status); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | status = ohci_restart(ohci); | ||
130 | if (status != 0) | ||
131 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | ||
132 | "ohci_restart", status); | ||
133 | } | ||
134 | |||
116 | static int ohci_quirk_nec(struct usb_hcd *hcd) | 135 | static int ohci_quirk_nec(struct usb_hcd *hcd) |
117 | { | 136 | { |
118 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 137 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
119 | 138 | ||
120 | ohci->flags |= OHCI_QUIRK_NEC; | 139 | ohci->flags |= OHCI_QUIRK_NEC; |
140 | INIT_WORK(&ohci->nec_work, ohci_quirk_nec_worker); | ||
121 | ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n"); | 141 | ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n"); |
122 | 142 | ||
123 | return 0; | 143 | return 0; |
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index c43b66acd4d5..0a7426920150 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -134,8 +134,11 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | ohci = hcd_to_ohci(hcd); | 136 | ohci = hcd_to_ohci(hcd); |
137 | if (is_bigendian) | 137 | if (is_bigendian) { |
138 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; | 138 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; |
139 | if (of_device_is_compatible(dn, "mpc5200-ohci")) | ||
140 | ohci->flags |= OHCI_QUIRK_FRAME_NO; | ||
141 | } | ||
139 | 142 | ||
140 | ohci_hcd_init(ohci); | 143 | ohci_hcd_init(ohci); |
141 | 144 | ||
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 1a2e1777ca61..f95be1896b0d 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
@@ -73,6 +73,11 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
73 | 73 | ||
74 | ohci = hcd_to_ohci(hcd); | 74 | ohci = hcd_to_ohci(hcd); |
75 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; | 75 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; |
76 | |||
77 | #ifdef CONFIG_PPC_MPC52xx | ||
78 | /* MPC52xx doesn't need frame_no shift */ | ||
79 | ohci->flags |= OHCI_QUIRK_FRAME_NO; | ||
80 | #endif | ||
76 | ohci_hcd_init(ohci); | 81 | ohci_hcd_init(ohci); |
77 | 82 | ||
78 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 83 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); |
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 830a3fe8615e..51817322232b 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c | |||
@@ -36,29 +36,15 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) | |||
36 | * PRECONDITION: ohci lock held, irqs blocked. | 36 | * PRECONDITION: ohci lock held, irqs blocked. |
37 | */ | 37 | */ |
38 | static void | 38 | static void |
39 | finish_urb (struct ohci_hcd *ohci, struct urb *urb) | 39 | finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status) |
40 | __releases(ohci->lock) | 40 | __releases(ohci->lock) |
41 | __acquires(ohci->lock) | 41 | __acquires(ohci->lock) |
42 | { | 42 | { |
43 | // ASSERT (urb->hcpriv != 0); | 43 | // ASSERT (urb->hcpriv != 0); |
44 | 44 | ||
45 | urb_free_priv (ohci, urb->hcpriv); | 45 | urb_free_priv (ohci, urb->hcpriv); |
46 | urb->hcpriv = NULL; | 46 | if (likely(status == -EINPROGRESS)) |
47 | 47 | status = 0; | |
48 | spin_lock (&urb->lock); | ||
49 | if (likely (urb->status == -EINPROGRESS)) | ||
50 | urb->status = 0; | ||
51 | /* report short control reads right even though the data TD always | ||
52 | * has TD_R set. (much simpler, but creates the 1-td limit.) | ||
53 | */ | ||
54 | if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK) | ||
55 | && unlikely (usb_pipecontrol (urb->pipe)) | ||
56 | && urb->actual_length < urb->transfer_buffer_length | ||
57 | && usb_pipein (urb->pipe) | ||
58 | && urb->status == 0) { | ||
59 | urb->status = -EREMOTEIO; | ||
60 | } | ||
61 | spin_unlock (&urb->lock); | ||
62 | 48 | ||
63 | switch (usb_pipetype (urb->pipe)) { | 49 | switch (usb_pipetype (urb->pipe)) { |
64 | case PIPE_ISOCHRONOUS: | 50 | case PIPE_ISOCHRONOUS: |
@@ -70,12 +56,13 @@ __acquires(ohci->lock) | |||
70 | } | 56 | } |
71 | 57 | ||
72 | #ifdef OHCI_VERBOSE_DEBUG | 58 | #ifdef OHCI_VERBOSE_DEBUG |
73 | urb_print (urb, "RET", usb_pipeout (urb->pipe)); | 59 | urb_print(urb, "RET", usb_pipeout (urb->pipe), status); |
74 | #endif | 60 | #endif |
75 | 61 | ||
76 | /* urb->complete() can reenter this HCD */ | 62 | /* urb->complete() can reenter this HCD */ |
63 | usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb); | ||
77 | spin_unlock (&ohci->lock); | 64 | spin_unlock (&ohci->lock); |
78 | usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb); | 65 | usb_hcd_giveback_urb(ohci_to_hcd(ohci), urb, status); |
79 | spin_lock (&ohci->lock); | 66 | spin_lock (&ohci->lock); |
80 | 67 | ||
81 | /* stop periodic dma if it's not needed */ | 68 | /* stop periodic dma if it's not needed */ |
@@ -179,6 +166,10 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) | |||
179 | ed->ed_prev = NULL; | 166 | ed->ed_prev = NULL; |
180 | ed->ed_next = NULL; | 167 | ed->ed_next = NULL; |
181 | ed->hwNextED = 0; | 168 | ed->hwNextED = 0; |
169 | if (quirk_zfmicro(ohci) | ||
170 | && (ed->type == PIPE_INTERRUPT) | ||
171 | && !(ohci->eds_scheduled++)) | ||
172 | mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ)); | ||
182 | wmb (); | 173 | wmb (); |
183 | 174 | ||
184 | /* we care about rm_list when setting CLE/BLE in case the HC was at | 175 | /* we care about rm_list when setting CLE/BLE in case the HC was at |
@@ -708,19 +699,18 @@ static void td_submit_urb ( | |||
708 | * Done List handling functions | 699 | * Done List handling functions |
709 | *-------------------------------------------------------------------------*/ | 700 | *-------------------------------------------------------------------------*/ |
710 | 701 | ||
711 | /* calculate transfer length/status and update the urb | 702 | /* calculate transfer length/status and update the urb */ |
712 | * PRECONDITION: irqsafe (only for urb->status locking) | 703 | static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td) |
713 | */ | ||
714 | static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | ||
715 | { | 704 | { |
716 | u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO); | 705 | u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO); |
717 | int cc = 0; | 706 | int cc = 0; |
707 | int status = -EINPROGRESS; | ||
718 | 708 | ||
719 | list_del (&td->td_list); | 709 | list_del (&td->td_list); |
720 | 710 | ||
721 | /* ISO ... drivers see per-TD length/status */ | 711 | /* ISO ... drivers see per-TD length/status */ |
722 | if (tdINFO & TD_ISO) { | 712 | if (tdINFO & TD_ISO) { |
723 | u16 tdPSW = ohci_hwPSW (ohci, td, 0); | 713 | u16 tdPSW = ohci_hwPSW(ohci, td, 0); |
724 | int dlen = 0; | 714 | int dlen = 0; |
725 | 715 | ||
726 | /* NOTE: assumes FC in tdINFO == 0, and that | 716 | /* NOTE: assumes FC in tdINFO == 0, and that |
@@ -729,7 +719,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
729 | 719 | ||
730 | cc = (tdPSW >> 12) & 0xF; | 720 | cc = (tdPSW >> 12) & 0xF; |
731 | if (tdINFO & TD_CC) /* hc didn't touch? */ | 721 | if (tdINFO & TD_CC) /* hc didn't touch? */ |
732 | return; | 722 | return status; |
733 | 723 | ||
734 | if (usb_pipeout (urb->pipe)) | 724 | if (usb_pipeout (urb->pipe)) |
735 | dlen = urb->iso_frame_desc [td->index].length; | 725 | dlen = urb->iso_frame_desc [td->index].length; |
@@ -762,12 +752,8 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
762 | if (cc == TD_DATAUNDERRUN | 752 | if (cc == TD_DATAUNDERRUN |
763 | && !(urb->transfer_flags & URB_SHORT_NOT_OK)) | 753 | && !(urb->transfer_flags & URB_SHORT_NOT_OK)) |
764 | cc = TD_CC_NOERROR; | 754 | cc = TD_CC_NOERROR; |
765 | if (cc != TD_CC_NOERROR && cc < 0x0E) { | 755 | if (cc != TD_CC_NOERROR && cc < 0x0E) |
766 | spin_lock (&urb->lock); | 756 | status = cc_to_error[cc]; |
767 | if (urb->status == -EINPROGRESS) | ||
768 | urb->status = cc_to_error [cc]; | ||
769 | spin_unlock (&urb->lock); | ||
770 | } | ||
771 | 757 | ||
772 | /* count all non-empty packets except control SETUP packet */ | 758 | /* count all non-empty packets except control SETUP packet */ |
773 | if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) { | 759 | if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) { |
@@ -786,14 +772,15 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
786 | urb->actual_length, | 772 | urb->actual_length, |
787 | urb->transfer_buffer_length); | 773 | urb->transfer_buffer_length); |
788 | } | 774 | } |
775 | return status; | ||
789 | } | 776 | } |
790 | 777 | ||
791 | /*-------------------------------------------------------------------------*/ | 778 | /*-------------------------------------------------------------------------*/ |
792 | 779 | ||
793 | static inline struct td * | 780 | static void ed_halted(struct ohci_hcd *ohci, struct td *td, int cc) |
794 | ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | ||
795 | { | 781 | { |
796 | struct urb *urb = td->urb; | 782 | struct urb *urb = td->urb; |
783 | urb_priv_t *urb_priv = urb->hcpriv; | ||
797 | struct ed *ed = td->ed; | 784 | struct ed *ed = td->ed; |
798 | struct list_head *tmp = td->td_list.next; | 785 | struct list_head *tmp = td->td_list.next; |
799 | __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C); | 786 | __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C); |
@@ -805,13 +792,12 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | |||
805 | wmb (); | 792 | wmb (); |
806 | ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H); | 793 | ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H); |
807 | 794 | ||
808 | /* put any later tds from this urb onto the donelist, after 'td', | 795 | /* Get rid of all later tds from this urb. We don't have |
809 | * order won't matter here: no errors, and nothing was transferred. | 796 | * to be careful: no errors and nothing was transferred. |
810 | * also patch the ed so it looks as if those tds completed normally. | 797 | * Also patch the ed so it looks as if those tds completed normally. |
811 | */ | 798 | */ |
812 | while (tmp != &ed->td_list) { | 799 | while (tmp != &ed->td_list) { |
813 | struct td *next; | 800 | struct td *next; |
814 | __hc32 info; | ||
815 | 801 | ||
816 | next = list_entry (tmp, struct td, td_list); | 802 | next = list_entry (tmp, struct td, td_list); |
817 | tmp = next->td_list.next; | 803 | tmp = next->td_list.next; |
@@ -826,14 +812,9 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | |||
826 | * then we need to leave the control STATUS packet queued | 812 | * then we need to leave the control STATUS packet queued |
827 | * and clear ED_SKIP. | 813 | * and clear ED_SKIP. |
828 | */ | 814 | */ |
829 | info = next->hwINFO; | ||
830 | info |= cpu_to_hc32 (ohci, TD_DONE); | ||
831 | info &= ~cpu_to_hc32 (ohci, TD_CC); | ||
832 | next->hwINFO = info; | ||
833 | |||
834 | next->next_dl_td = rev; | ||
835 | rev = next; | ||
836 | 815 | ||
816 | list_del(&next->td_list); | ||
817 | urb_priv->td_cnt++; | ||
837 | ed->hwHeadP = next->hwNextTD | toggle; | 818 | ed->hwHeadP = next->hwNextTD | toggle; |
838 | } | 819 | } |
839 | 820 | ||
@@ -859,8 +840,6 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | |||
859 | hc32_to_cpu (ohci, td->hwINFO), | 840 | hc32_to_cpu (ohci, td->hwINFO), |
860 | cc, cc_to_error [cc]); | 841 | cc, cc_to_error [cc]); |
861 | } | 842 | } |
862 | |||
863 | return rev; | ||
864 | } | 843 | } |
865 | 844 | ||
866 | /* replies to the request have to be on a FIFO basis so | 845 | /* replies to the request have to be on a FIFO basis so |
@@ -897,7 +876,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) | |||
897 | */ | 876 | */ |
898 | if (cc != TD_CC_NOERROR | 877 | if (cc != TD_CC_NOERROR |
899 | && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H))) | 878 | && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H))) |
900 | td_rev = ed_halted (ohci, td, cc, td_rev); | 879 | ed_halted(ohci, td, cc); |
901 | 880 | ||
902 | td->next_dl_td = td_rev; | 881 | td->next_dl_td = td_rev; |
903 | td_rev = td; | 882 | td_rev = td; |
@@ -940,8 +919,12 @@ skip_ed: | |||
940 | TD_MASK; | 919 | TD_MASK; |
941 | 920 | ||
942 | /* INTR_WDH may need to clean up first */ | 921 | /* INTR_WDH may need to clean up first */ |
943 | if (td->td_dma != head) | 922 | if (td->td_dma != head) { |
944 | goto skip_ed; | 923 | if (ed == ohci->ed_to_check) |
924 | ohci->ed_to_check = NULL; | ||
925 | else | ||
926 | goto skip_ed; | ||
927 | } | ||
945 | } | 928 | } |
946 | } | 929 | } |
947 | 930 | ||
@@ -974,7 +957,7 @@ rescan_this: | |||
974 | urb = td->urb; | 957 | urb = td->urb; |
975 | urb_priv = td->urb->hcpriv; | 958 | urb_priv = td->urb->hcpriv; |
976 | 959 | ||
977 | if (urb->status == -EINPROGRESS) { | 960 | if (!urb->unlinked) { |
978 | prev = &td->hwNextTD; | 961 | prev = &td->hwNextTD; |
979 | continue; | 962 | continue; |
980 | } | 963 | } |
@@ -990,7 +973,7 @@ rescan_this: | |||
990 | /* if URB is done, clean up */ | 973 | /* if URB is done, clean up */ |
991 | if (urb_priv->td_cnt == urb_priv->length) { | 974 | if (urb_priv->td_cnt == urb_priv->length) { |
992 | modified = completed = 1; | 975 | modified = completed = 1; |
993 | finish_urb (ohci, urb); | 976 | finish_urb(ohci, urb, 0); |
994 | } | 977 | } |
995 | } | 978 | } |
996 | if (completed && !list_empty (&ed->td_list)) | 979 | if (completed && !list_empty (&ed->td_list)) |
@@ -998,6 +981,8 @@ rescan_this: | |||
998 | 981 | ||
999 | /* ED's now officially unlinked, hc doesn't see */ | 982 | /* ED's now officially unlinked, hc doesn't see */ |
1000 | ed->state = ED_IDLE; | 983 | ed->state = ED_IDLE; |
984 | if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) | ||
985 | ohci->eds_scheduled--; | ||
1001 | ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); | 986 | ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); |
1002 | ed->hwNextED = 0; | 987 | ed->hwNextED = 0; |
1003 | wmb (); | 988 | wmb (); |
@@ -1021,7 +1006,7 @@ rescan_this: | |||
1021 | 1006 | ||
1022 | if (ohci->ed_controltail) { | 1007 | if (ohci->ed_controltail) { |
1023 | command |= OHCI_CLF; | 1008 | command |= OHCI_CLF; |
1024 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1009 | if (quirk_zfmicro(ohci)) |
1025 | mdelay(1); | 1010 | mdelay(1); |
1026 | if (!(ohci->hc_control & OHCI_CTRL_CLE)) { | 1011 | if (!(ohci->hc_control & OHCI_CTRL_CLE)) { |
1027 | control |= OHCI_CTRL_CLE; | 1012 | control |= OHCI_CTRL_CLE; |
@@ -1031,7 +1016,7 @@ rescan_this: | |||
1031 | } | 1016 | } |
1032 | if (ohci->ed_bulktail) { | 1017 | if (ohci->ed_bulktail) { |
1033 | command |= OHCI_BLF; | 1018 | command |= OHCI_BLF; |
1034 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1019 | if (quirk_zfmicro(ohci)) |
1035 | mdelay(1); | 1020 | mdelay(1); |
1036 | if (!(ohci->hc_control & OHCI_CTRL_BLE)) { | 1021 | if (!(ohci->hc_control & OHCI_CTRL_BLE)) { |
1037 | control |= OHCI_CTRL_BLE; | 1022 | control |= OHCI_CTRL_BLE; |
@@ -1043,13 +1028,13 @@ rescan_this: | |||
1043 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ | 1028 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ |
1044 | if (control) { | 1029 | if (control) { |
1045 | ohci->hc_control |= control; | 1030 | ohci->hc_control |= control; |
1046 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1031 | if (quirk_zfmicro(ohci)) |
1047 | mdelay(1); | 1032 | mdelay(1); |
1048 | ohci_writel (ohci, ohci->hc_control, | 1033 | ohci_writel (ohci, ohci->hc_control, |
1049 | &ohci->regs->control); | 1034 | &ohci->regs->control); |
1050 | } | 1035 | } |
1051 | if (command) { | 1036 | if (command) { |
1052 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1037 | if (quirk_zfmicro(ohci)) |
1053 | mdelay(1); | 1038 | mdelay(1); |
1054 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); | 1039 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); |
1055 | } | 1040 | } |
@@ -1061,11 +1046,60 @@ rescan_this: | |||
1061 | /*-------------------------------------------------------------------------*/ | 1046 | /*-------------------------------------------------------------------------*/ |
1062 | 1047 | ||
1063 | /* | 1048 | /* |
1049 | * Used to take back a TD from the host controller. This would normally be | ||
1050 | * called from within dl_done_list, however it may be called directly if the | ||
1051 | * HC no longer sees the TD and it has not appeared on the donelist (after | ||
1052 | * two frames). This bug has been observed on ZF Micro systems. | ||
1053 | */ | ||
1054 | static void takeback_td(struct ohci_hcd *ohci, struct td *td) | ||
1055 | { | ||
1056 | struct urb *urb = td->urb; | ||
1057 | urb_priv_t *urb_priv = urb->hcpriv; | ||
1058 | struct ed *ed = td->ed; | ||
1059 | int status; | ||
1060 | |||
1061 | /* update URB's length and status from TD */ | ||
1062 | status = td_done(ohci, urb, td); | ||
1063 | urb_priv->td_cnt++; | ||
1064 | |||
1065 | /* If all this urb's TDs are done, call complete() */ | ||
1066 | if (urb_priv->td_cnt == urb_priv->length) | ||
1067 | finish_urb(ohci, urb, status); | ||
1068 | |||
1069 | /* clean schedule: unlink EDs that are no longer busy */ | ||
1070 | if (list_empty(&ed->td_list)) { | ||
1071 | if (ed->state == ED_OPER) | ||
1072 | start_ed_unlink(ohci, ed); | ||
1073 | |||
1074 | /* ... reenabling halted EDs only after fault cleanup */ | ||
1075 | } else if ((ed->hwINFO & cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE)) | ||
1076 | == cpu_to_hc32(ohci, ED_SKIP)) { | ||
1077 | td = list_entry(ed->td_list.next, struct td, td_list); | ||
1078 | if (!(td->hwINFO & cpu_to_hc32(ohci, TD_DONE))) { | ||
1079 | ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP); | ||
1080 | /* ... hc may need waking-up */ | ||
1081 | switch (ed->type) { | ||
1082 | case PIPE_CONTROL: | ||
1083 | ohci_writel(ohci, OHCI_CLF, | ||
1084 | &ohci->regs->cmdstatus); | ||
1085 | break; | ||
1086 | case PIPE_BULK: | ||
1087 | ohci_writel(ohci, OHCI_BLF, | ||
1088 | &ohci->regs->cmdstatus); | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | /* | ||
1064 | * Process normal completions (error or success) and clean the schedules. | 1096 | * Process normal completions (error or success) and clean the schedules. |
1065 | * | 1097 | * |
1066 | * This is the main path for handing urbs back to drivers. The only other | 1098 | * This is the main path for handing urbs back to drivers. The only other |
1067 | * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of | 1099 | * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list, |
1068 | * scanning the (re-reversed) donelist as this does. | 1100 | * instead of scanning the (re-reversed) donelist as this does. There's |
1101 | * an abnormal path too, handling a quirk in some Compaq silicon: URBs | ||
1102 | * with TDs that appear to be orphaned are directly reclaimed. | ||
1069 | */ | 1103 | */ |
1070 | static void | 1104 | static void |
1071 | dl_done_list (struct ohci_hcd *ohci) | 1105 | dl_done_list (struct ohci_hcd *ohci) |
@@ -1074,44 +1108,7 @@ dl_done_list (struct ohci_hcd *ohci) | |||
1074 | 1108 | ||
1075 | while (td) { | 1109 | while (td) { |
1076 | struct td *td_next = td->next_dl_td; | 1110 | struct td *td_next = td->next_dl_td; |
1077 | struct urb *urb = td->urb; | 1111 | takeback_td(ohci, td); |
1078 | urb_priv_t *urb_priv = urb->hcpriv; | ||
1079 | struct ed *ed = td->ed; | ||
1080 | |||
1081 | /* update URB's length and status from TD */ | ||
1082 | td_done (ohci, urb, td); | ||
1083 | urb_priv->td_cnt++; | ||
1084 | |||
1085 | /* If all this urb's TDs are done, call complete() */ | ||
1086 | if (urb_priv->td_cnt == urb_priv->length) | ||
1087 | finish_urb (ohci, urb); | ||
1088 | |||
1089 | /* clean schedule: unlink EDs that are no longer busy */ | ||
1090 | if (list_empty (&ed->td_list)) { | ||
1091 | if (ed->state == ED_OPER) | ||
1092 | start_ed_unlink (ohci, ed); | ||
1093 | |||
1094 | /* ... reenabling halted EDs only after fault cleanup */ | ||
1095 | } else if ((ed->hwINFO & cpu_to_hc32 (ohci, | ||
1096 | ED_SKIP | ED_DEQUEUE)) | ||
1097 | == cpu_to_hc32 (ohci, ED_SKIP)) { | ||
1098 | td = list_entry (ed->td_list.next, struct td, td_list); | ||
1099 | if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) { | ||
1100 | ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP); | ||
1101 | /* ... hc may need waking-up */ | ||
1102 | switch (ed->type) { | ||
1103 | case PIPE_CONTROL: | ||
1104 | ohci_writel (ohci, OHCI_CLF, | ||
1105 | &ohci->regs->cmdstatus); | ||
1106 | break; | ||
1107 | case PIPE_BULK: | ||
1108 | ohci_writel (ohci, OHCI_BLF, | ||
1109 | &ohci->regs->cmdstatus); | ||
1110 | break; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | td = td_next; | 1112 | td = td_next; |
1116 | } | 1113 | } |
1117 | } | 1114 | } |
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c new file mode 100644 index 000000000000..bc3e785d8c00 --- /dev/null +++ b/drivers/usb/host/ohci-ssb.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * Broadcom USB-core OHCI driver | ||
4 | * | ||
5 | * Copyright 2007 Michael Buesch <mb@bu3sch.de> | ||
6 | * | ||
7 | * Derived from the OHCI-PCI driver | ||
8 | * Copyright 1999 Roman Weissgaerber | ||
9 | * Copyright 2000-2002 David Brownell | ||
10 | * Copyright 1999 Linus Torvalds | ||
11 | * Copyright 1999 Gregory P. Smith | ||
12 | * | ||
13 | * Derived from the USBcore related parts of Broadcom-SB | ||
14 | * Copyright 2005 Broadcom Corporation | ||
15 | * | ||
16 | * Licensed under the GNU/GPL. See COPYING for details. | ||
17 | */ | ||
18 | #include <linux/ssb/ssb.h> | ||
19 | |||
20 | |||
21 | #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29) | ||
22 | |||
23 | struct ssb_ohci_device { | ||
24 | struct ohci_hcd ohci; /* _must_ be at the beginning. */ | ||
25 | |||
26 | u32 enable_flags; | ||
27 | }; | ||
28 | |||
29 | static inline | ||
30 | struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd) | ||
31 | { | ||
32 | return (struct ssb_ohci_device *)(hcd->hcd_priv); | ||
33 | } | ||
34 | |||
35 | |||
36 | static int ssb_ohci_reset(struct usb_hcd *hcd) | ||
37 | { | ||
38 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
39 | struct ohci_hcd *ohci = &ohcidev->ohci; | ||
40 | int err; | ||
41 | |||
42 | ohci_hcd_init(ohci); | ||
43 | err = ohci_init(ohci); | ||
44 | |||
45 | return err; | ||
46 | } | ||
47 | |||
48 | static int ssb_ohci_start(struct usb_hcd *hcd) | ||
49 | { | ||
50 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
51 | struct ohci_hcd *ohci = &ohcidev->ohci; | ||
52 | int err; | ||
53 | |||
54 | err = ohci_run(ohci); | ||
55 | if (err < 0) { | ||
56 | ohci_err(ohci, "can't start\n"); | ||
57 | ohci_stop(hcd); | ||
58 | } | ||
59 | |||
60 | return err; | ||
61 | } | ||
62 | |||
63 | #ifdef CONFIG_PM | ||
64 | static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message) | ||
65 | { | ||
66 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
67 | struct ohci_hcd *ohci = &ohcidev->ohci; | ||
68 | unsigned long flags; | ||
69 | |||
70 | spin_lock_irqsave(&ohci->lock, flags); | ||
71 | |||
72 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
73 | ohci_readl(ohci, &ohci->regs->intrdisable); /* commit write */ | ||
74 | |||
75 | /* make sure snapshot being resumed re-enumerates everything */ | ||
76 | if (message.event == PM_EVENT_PRETHAW) | ||
77 | ohci_usb_reset(ohci); | ||
78 | |||
79 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
80 | |||
81 | spin_unlock_irqrestore(&ohci->lock, flags); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int ssb_ohci_hcd_resume(struct usb_hcd *hcd) | ||
86 | { | ||
87 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
88 | usb_hcd_resume_root_hub(hcd); | ||
89 | return 0; | ||
90 | } | ||
91 | #endif /* CONFIG_PM */ | ||
92 | |||
93 | static const struct hc_driver ssb_ohci_hc_driver = { | ||
94 | .description = "ssb-usb-ohci", | ||
95 | .product_desc = "SSB OHCI Controller", | ||
96 | .hcd_priv_size = sizeof(struct ssb_ohci_device), | ||
97 | |||
98 | .irq = ohci_irq, | ||
99 | .flags = HCD_MEMORY | HCD_USB11, | ||
100 | |||
101 | .reset = ssb_ohci_reset, | ||
102 | .start = ssb_ohci_start, | ||
103 | .stop = ohci_stop, | ||
104 | .shutdown = ohci_shutdown, | ||
105 | |||
106 | #ifdef CONFIG_PM | ||
107 | .suspend = ssb_ohci_hcd_suspend, | ||
108 | .resume = ssb_ohci_hcd_resume, | ||
109 | #endif | ||
110 | |||
111 | .urb_enqueue = ohci_urb_enqueue, | ||
112 | .urb_dequeue = ohci_urb_dequeue, | ||
113 | .endpoint_disable = ohci_endpoint_disable, | ||
114 | |||
115 | .get_frame_number = ohci_get_frame, | ||
116 | |||
117 | .hub_status_data = ohci_hub_status_data, | ||
118 | .hub_control = ohci_hub_control, | ||
119 | .hub_irq_enable = ohci_rhsc_enable, | ||
120 | .bus_suspend = ohci_bus_suspend, | ||
121 | .bus_resume = ohci_bus_resume, | ||
122 | |||
123 | .start_port_reset = ohci_start_port_reset, | ||
124 | }; | ||
125 | |||
126 | static void ssb_ohci_detach(struct ssb_device *dev) | ||
127 | { | ||
128 | struct usb_hcd *hcd = ssb_get_drvdata(dev); | ||
129 | |||
130 | usb_remove_hcd(hcd); | ||
131 | iounmap(hcd->regs); | ||
132 | usb_put_hcd(hcd); | ||
133 | ssb_device_disable(dev, 0); | ||
134 | } | ||
135 | |||
136 | static int ssb_ohci_attach(struct ssb_device *dev) | ||
137 | { | ||
138 | struct ssb_ohci_device *ohcidev; | ||
139 | struct usb_hcd *hcd; | ||
140 | int err = -ENOMEM; | ||
141 | u32 tmp, flags = 0; | ||
142 | |||
143 | if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) | ||
144 | flags |= SSB_OHCI_TMSLOW_HOSTMODE; | ||
145 | |||
146 | ssb_device_enable(dev, flags); | ||
147 | |||
148 | hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, | ||
149 | dev->dev->bus_id); | ||
150 | if (!hcd) | ||
151 | goto err_dev_disable; | ||
152 | ohcidev = hcd_to_ssb_ohci(hcd); | ||
153 | ohcidev->enable_flags = flags; | ||
154 | |||
155 | tmp = ssb_read32(dev, SSB_ADMATCH0); | ||
156 | hcd->rsrc_start = ssb_admatch_base(tmp); | ||
157 | hcd->rsrc_len = ssb_admatch_size(tmp); | ||
158 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | ||
159 | if (!hcd->regs) | ||
160 | goto err_put_hcd; | ||
161 | err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); | ||
162 | if (err) | ||
163 | goto err_iounmap; | ||
164 | |||
165 | ssb_set_drvdata(dev, hcd); | ||
166 | |||
167 | return err; | ||
168 | |||
169 | err_iounmap: | ||
170 | iounmap(hcd->regs); | ||
171 | err_put_hcd: | ||
172 | usb_put_hcd(hcd); | ||
173 | err_dev_disable: | ||
174 | ssb_device_disable(dev, flags); | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | static int ssb_ohci_probe(struct ssb_device *dev, | ||
179 | const struct ssb_device_id *id) | ||
180 | { | ||
181 | int err; | ||
182 | u16 chipid_top; | ||
183 | |||
184 | /* USBcores are only connected on embedded devices. */ | ||
185 | chipid_top = (dev->bus->chip_id & 0xFF00); | ||
186 | if (chipid_top != 0x4700 && chipid_top != 0x5300) | ||
187 | return -ENODEV; | ||
188 | |||
189 | /* TODO: Probably need checks here; is the core connected? */ | ||
190 | |||
191 | if (usb_disabled()) | ||
192 | return -ENODEV; | ||
193 | |||
194 | /* We currently always attach SSB_DEV_USB11_HOSTDEV | ||
195 | * as HOST OHCI. If we want to attach it as Client device, | ||
196 | * we must branch here and call into the (yet to | ||
197 | * be written) Client mode driver. Same for remove(). */ | ||
198 | |||
199 | err = ssb_ohci_attach(dev); | ||
200 | |||
201 | return err; | ||
202 | } | ||
203 | |||
204 | static void ssb_ohci_remove(struct ssb_device *dev) | ||
205 | { | ||
206 | ssb_ohci_detach(dev); | ||
207 | } | ||
208 | |||
209 | #ifdef CONFIG_PM | ||
210 | |||
211 | static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state) | ||
212 | { | ||
213 | ssb_device_disable(dev, 0); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int ssb_ohci_resume(struct ssb_device *dev) | ||
219 | { | ||
220 | struct usb_hcd *hcd = ssb_get_drvdata(dev); | ||
221 | struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd); | ||
222 | |||
223 | ssb_device_enable(dev, ohcidev->enable_flags); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | #else /* !CONFIG_PM */ | ||
229 | #define ssb_ohci_suspend NULL | ||
230 | #define ssb_ohci_resume NULL | ||
231 | #endif /* CONFIG_PM */ | ||
232 | |||
233 | static const struct ssb_device_id ssb_ohci_table[] = { | ||
234 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), | ||
235 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), | ||
236 | SSB_DEVTABLE_END | ||
237 | }; | ||
238 | MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); | ||
239 | |||
240 | static struct ssb_driver ssb_ohci_driver = { | ||
241 | .name = KBUILD_MODNAME, | ||
242 | .id_table = ssb_ohci_table, | ||
243 | .probe = ssb_ohci_probe, | ||
244 | .remove = ssb_ohci_remove, | ||
245 | .suspend = ssb_ohci_suspend, | ||
246 | .resume = ssb_ohci_resume, | ||
247 | }; | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 4ada43cf1387..47c5c66a282c 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -398,11 +398,38 @@ struct ohci_hcd { | |||
398 | #define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ | 398 | #define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ |
399 | #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ | 399 | #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ |
400 | #define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ | 400 | #define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ |
401 | #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */ | ||
401 | // there are also chip quirks/bugs in init logic | 402 | // there are also chip quirks/bugs in init logic |
402 | 403 | ||
403 | struct work_struct nec_work; /* Worker for NEC quirk */ | 404 | struct work_struct nec_work; /* Worker for NEC quirk */ |
405 | |||
406 | /* Needed for ZF Micro quirk */ | ||
407 | struct timer_list unlink_watchdog; | ||
408 | unsigned eds_scheduled; | ||
409 | struct ed *ed_to_check; | ||
410 | unsigned zf_delay; | ||
404 | }; | 411 | }; |
405 | 412 | ||
413 | #ifdef CONFIG_PCI | ||
414 | static inline int quirk_nec(struct ohci_hcd *ohci) | ||
415 | { | ||
416 | return ohci->flags & OHCI_QUIRK_NEC; | ||
417 | } | ||
418 | static inline int quirk_zfmicro(struct ohci_hcd *ohci) | ||
419 | { | ||
420 | return ohci->flags & OHCI_QUIRK_ZFMICRO; | ||
421 | } | ||
422 | #else | ||
423 | static inline int quirk_nec(struct ohci_hcd *ohci) | ||
424 | { | ||
425 | return 0; | ||
426 | } | ||
427 | static inline int quirk_zfmicro(struct ohci_hcd *ohci) | ||
428 | { | ||
429 | return 0; | ||
430 | } | ||
431 | #endif | ||
432 | |||
406 | /* convert between an hcd pointer and the corresponding ohci_hcd */ | 433 | /* convert between an hcd pointer and the corresponding ohci_hcd */ |
407 | static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd) | 434 | static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd) |
408 | { | 435 | { |
@@ -607,15 +634,12 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) | |||
607 | /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all | 634 | /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all |
608 | * hardware handles 16 bit reads. That creates a different confusion on | 635 | * hardware handles 16 bit reads. That creates a different confusion on |
609 | * some big-endian SOC implementations. Same thing happens with PSW access. | 636 | * some big-endian SOC implementations. Same thing happens with PSW access. |
610 | * | ||
611 | * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over | ||
612 | * to arch/powerpc | ||
613 | */ | 637 | */ |
614 | 638 | ||
615 | #ifdef CONFIG_STB03xxx | 639 | #ifdef CONFIG_PPC_MPC52xx |
616 | #define OHCI_BE_FRAME_NO_SHIFT 16 | 640 | #define big_endian_frame_no_quirk(ohci) (ohci->flags & OHCI_QUIRK_FRAME_NO) |
617 | #else | 641 | #else |
618 | #define OHCI_BE_FRAME_NO_SHIFT 0 | 642 | #define big_endian_frame_no_quirk(ohci) 0 |
619 | #endif | 643 | #endif |
620 | 644 | ||
621 | static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) | 645 | static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) |
@@ -623,7 +647,8 @@ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) | |||
623 | u32 tmp; | 647 | u32 tmp; |
624 | if (big_endian_desc(ohci)) { | 648 | if (big_endian_desc(ohci)) { |
625 | tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); | 649 | tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); |
626 | tmp >>= OHCI_BE_FRAME_NO_SHIFT; | 650 | if (!big_endian_frame_no_quirk(ohci)) |
651 | tmp >>= 16; | ||
627 | } else | 652 | } else |
628 | tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no); | 653 | tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no); |
629 | 654 | ||
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 40a1de4c256e..ae8ec4474eb8 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -782,10 +782,12 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | |||
782 | kfree(td); | 782 | kfree(td); |
783 | 783 | ||
784 | if (urb) { | 784 | if (urb) { |
785 | urb->status = -ENODEV; | 785 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), |
786 | urb->hcpriv = NULL; | 786 | urb); |
787 | |||
787 | spin_unlock(&r8a66597->lock); | 788 | spin_unlock(&r8a66597->lock); |
788 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb); | 789 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, |
790 | -ENODEV); | ||
789 | spin_lock(&r8a66597->lock); | 791 | spin_lock(&r8a66597->lock); |
790 | } | 792 | } |
791 | break; | 793 | break; |
@@ -832,7 +834,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | |||
832 | info.pipenum = get_empty_pipenum(r8a66597, ep); | 834 | info.pipenum = get_empty_pipenum(r8a66597, ep); |
833 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); | 835 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); |
834 | info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 836 | info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
835 | info.maxpacket = ep->wMaxPacketSize; | 837 | info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); |
836 | info.type = get_r8a66597_type(ep->bmAttributes | 838 | info.type = get_r8a66597_type(ep->bmAttributes |
837 | & USB_ENDPOINT_XFERTYPE_MASK); | 839 | & USB_ENDPOINT_XFERTYPE_MASK); |
838 | info.bufnum = get_bufnum(info.pipenum); | 840 | info.bufnum = get_bufnum(info.pipenum); |
@@ -923,7 +925,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597, | |||
923 | r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); | 925 | r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); |
924 | 926 | ||
925 | for (i = 0; i < 4; i++) { | 927 | for (i = 0; i < 4; i++) { |
926 | r8a66597_write(r8a66597, p[i], setup_addr); | 928 | r8a66597_write(r8a66597, cpu_to_le16(p[i]), setup_addr); |
927 | setup_addr += 2; | 929 | setup_addr += 2; |
928 | } | 930 | } |
929 | r8a66597_write(r8a66597, SUREQ, DCPCTR); | 931 | r8a66597_write(r8a66597, SUREQ, DCPCTR); |
@@ -1032,6 +1034,15 @@ static void prepare_status_packet(struct r8a66597 *r8a66597, | |||
1032 | pipe_start(r8a66597, td->pipe); | 1034 | pipe_start(r8a66597, td->pipe); |
1033 | } | 1035 | } |
1034 | 1036 | ||
1037 | static int is_set_address(unsigned char *setup_packet) | ||
1038 | { | ||
1039 | if (((setup_packet[0] & USB_TYPE_MASK) == USB_TYPE_STANDARD) && | ||
1040 | setup_packet[1] == USB_REQ_SET_ADDRESS) | ||
1041 | return 1; | ||
1042 | else | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1035 | /* this function must be called with interrupt disabled */ | 1046 | /* this function must be called with interrupt disabled */ |
1036 | static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td) | 1047 | static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td) |
1037 | { | 1048 | { |
@@ -1039,7 +1050,7 @@ static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td) | |||
1039 | 1050 | ||
1040 | switch (td->type) { | 1051 | switch (td->type) { |
1041 | case USB_PID_SETUP: | 1052 | case USB_PID_SETUP: |
1042 | if (td->urb->setup_packet[1] == USB_REQ_SET_ADDRESS) { | 1053 | if (is_set_address(td->urb->setup_packet)) { |
1043 | td->set_address = 1; | 1054 | td->set_address = 1; |
1044 | td->urb->setup_packet[2] = alloc_usb_address(r8a66597, | 1055 | td->urb->setup_packet[2] = alloc_usb_address(r8a66597, |
1045 | td->urb); | 1056 | td->urb); |
@@ -1106,8 +1117,9 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) | |||
1106 | } | 1117 | } |
1107 | 1118 | ||
1108 | /* this function must be called with interrupt disabled */ | 1119 | /* this function must be called with interrupt disabled */ |
1109 | static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td, | 1120 | static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td, |
1110 | u16 pipenum, struct urb *urb) | 1121 | u16 pipenum, struct urb *urb, int status) |
1122 | __releases(r8a66597->lock) __acquires(r8a66597->lock) | ||
1111 | { | 1123 | { |
1112 | int restart = 0; | 1124 | int restart = 0; |
1113 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | 1125 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); |
@@ -1115,7 +1127,7 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td, | |||
1115 | r8a66597->timeout_map &= ~(1 << pipenum); | 1127 | r8a66597->timeout_map &= ~(1 << pipenum); |
1116 | 1128 | ||
1117 | if (likely(td)) { | 1129 | if (likely(td)) { |
1118 | if (td->set_address && urb->status != 0) | 1130 | if (td->set_address && (status != 0 || urb->unlinked)) |
1119 | r8a66597->address_map &= ~(1 << urb->setup_packet[2]); | 1131 | r8a66597->address_map &= ~(1 << urb->setup_packet[2]); |
1120 | 1132 | ||
1121 | pipe_toggle_save(r8a66597, td->pipe, urb); | 1133 | pipe_toggle_save(r8a66597, td->pipe, urb); |
@@ -1130,9 +1142,9 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td, | |||
1130 | if (usb_pipeisoc(urb->pipe)) | 1142 | if (usb_pipeisoc(urb->pipe)) |
1131 | urb->start_frame = r8a66597_get_frame(hcd); | 1143 | urb->start_frame = r8a66597_get_frame(hcd); |
1132 | 1144 | ||
1133 | urb->hcpriv = NULL; | 1145 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); |
1134 | spin_unlock(&r8a66597->lock); | 1146 | spin_unlock(&r8a66597->lock); |
1135 | usb_hcd_giveback_urb(hcd, urb); | 1147 | usb_hcd_giveback_urb(hcd, urb, status); |
1136 | spin_lock(&r8a66597->lock); | 1148 | spin_lock(&r8a66597->lock); |
1137 | } | 1149 | } |
1138 | 1150 | ||
@@ -1146,14 +1158,6 @@ static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td, | |||
1146 | } | 1158 | } |
1147 | } | 1159 | } |
1148 | 1160 | ||
1149 | /* this function must be called with interrupt disabled */ | ||
1150 | static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td, | ||
1151 | u16 pipenum, struct urb *urb) | ||
1152 | __releases(r8a66597->lock) __acquires(r8a66597->lock) | ||
1153 | { | ||
1154 | done(r8a66597, td, pipenum, urb); | ||
1155 | } | ||
1156 | |||
1157 | static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | 1161 | static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) |
1158 | { | 1162 | { |
1159 | u16 tmp; | 1163 | u16 tmp; |
@@ -1162,6 +1166,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | |||
1162 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); | 1166 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); |
1163 | struct urb *urb; | 1167 | struct urb *urb; |
1164 | int finish = 0; | 1168 | int finish = 0; |
1169 | int status = 0; | ||
1165 | 1170 | ||
1166 | if (unlikely(!td)) | 1171 | if (unlikely(!td)) |
1167 | return; | 1172 | return; |
@@ -1170,17 +1175,15 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | |||
1170 | fifo_change_from_pipe(r8a66597, td->pipe); | 1175 | fifo_change_from_pipe(r8a66597, td->pipe); |
1171 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); | 1176 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); |
1172 | if (unlikely((tmp & FRDY) == 0)) { | 1177 | if (unlikely((tmp & FRDY) == 0)) { |
1173 | urb->status = -EPIPE; | ||
1174 | pipe_stop(r8a66597, td->pipe); | 1178 | pipe_stop(r8a66597, td->pipe); |
1175 | pipe_irq_disable(r8a66597, pipenum); | 1179 | pipe_irq_disable(r8a66597, pipenum); |
1176 | err("in fifo not ready (%d)", pipenum); | 1180 | err("in fifo not ready (%d)", pipenum); |
1177 | finish_request(r8a66597, td, pipenum, td->urb); | 1181 | finish_request(r8a66597, td, pipenum, td->urb, -EPIPE); |
1178 | return; | 1182 | return; |
1179 | } | 1183 | } |
1180 | 1184 | ||
1181 | /* prepare parameters */ | 1185 | /* prepare parameters */ |
1182 | rcv_len = tmp & DTLN; | 1186 | rcv_len = tmp & DTLN; |
1183 | bufsize = td->maxpacket; | ||
1184 | if (usb_pipeisoc(urb->pipe)) { | 1187 | if (usb_pipeisoc(urb->pipe)) { |
1185 | buf = (u16 *)(urb->transfer_buffer + | 1188 | buf = (u16 *)(urb->transfer_buffer + |
1186 | urb->iso_frame_desc[td->iso_cnt].offset); | 1189 | urb->iso_frame_desc[td->iso_cnt].offset); |
@@ -1189,29 +1192,31 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | |||
1189 | buf = (void *)urb->transfer_buffer + urb->actual_length; | 1192 | buf = (void *)urb->transfer_buffer + urb->actual_length; |
1190 | urb_len = urb->transfer_buffer_length - urb->actual_length; | 1193 | urb_len = urb->transfer_buffer_length - urb->actual_length; |
1191 | } | 1194 | } |
1192 | if (rcv_len < bufsize) | 1195 | bufsize = min(urb_len, (int) td->maxpacket); |
1193 | size = min(rcv_len, urb_len); | 1196 | if (rcv_len <= bufsize) { |
1194 | else | 1197 | size = rcv_len; |
1195 | size = min(bufsize, urb_len); | 1198 | } else { |
1199 | size = bufsize; | ||
1200 | status = -EOVERFLOW; | ||
1201 | finish = 1; | ||
1202 | } | ||
1196 | 1203 | ||
1197 | /* update parameters */ | 1204 | /* update parameters */ |
1198 | urb->actual_length += size; | 1205 | urb->actual_length += size; |
1199 | if (rcv_len == 0) | 1206 | if (rcv_len == 0) |
1200 | td->zero_packet = 1; | 1207 | td->zero_packet = 1; |
1201 | if ((size % td->maxpacket) > 0) { | 1208 | if (rcv_len < bufsize) { |
1202 | td->short_packet = 1; | 1209 | td->short_packet = 1; |
1203 | if (urb->transfer_buffer_length != urb->actual_length && | ||
1204 | urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1205 | td->urb->status = -EREMOTEIO; | ||
1206 | } | 1210 | } |
1207 | if (usb_pipeisoc(urb->pipe)) { | 1211 | if (usb_pipeisoc(urb->pipe)) { |
1208 | urb->iso_frame_desc[td->iso_cnt].actual_length = size; | 1212 | urb->iso_frame_desc[td->iso_cnt].actual_length = size; |
1209 | urb->iso_frame_desc[td->iso_cnt].status = 0; | 1213 | urb->iso_frame_desc[td->iso_cnt].status = status; |
1210 | td->iso_cnt++; | 1214 | td->iso_cnt++; |
1215 | finish = 0; | ||
1211 | } | 1216 | } |
1212 | 1217 | ||
1213 | /* check transfer finish */ | 1218 | /* check transfer finish */ |
1214 | if (check_transfer_finish(td, urb)) { | 1219 | if (finish || check_transfer_finish(td, urb)) { |
1215 | pipe_stop(r8a66597, td->pipe); | 1220 | pipe_stop(r8a66597, td->pipe); |
1216 | pipe_irq_disable(r8a66597, pipenum); | 1221 | pipe_irq_disable(r8a66597, pipenum); |
1217 | finish = 1; | 1222 | finish = 1; |
@@ -1226,11 +1231,8 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | |||
1226 | buf, size); | 1231 | buf, size); |
1227 | } | 1232 | } |
1228 | 1233 | ||
1229 | if (finish && pipenum != 0) { | 1234 | if (finish && pipenum != 0) |
1230 | if (td->urb->status == -EINPROGRESS) | 1235 | finish_request(r8a66597, td, pipenum, urb, status); |
1231 | td->urb->status = 0; | ||
1232 | finish_request(r8a66597, td, pipenum, urb); | ||
1233 | } | ||
1234 | } | 1236 | } |
1235 | 1237 | ||
1236 | static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | 1238 | static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) |
@@ -1248,11 +1250,10 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | |||
1248 | fifo_change_from_pipe(r8a66597, td->pipe); | 1250 | fifo_change_from_pipe(r8a66597, td->pipe); |
1249 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); | 1251 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); |
1250 | if (unlikely((tmp & FRDY) == 0)) { | 1252 | if (unlikely((tmp & FRDY) == 0)) { |
1251 | urb->status = -EPIPE; | ||
1252 | pipe_stop(r8a66597, td->pipe); | 1253 | pipe_stop(r8a66597, td->pipe); |
1253 | pipe_irq_disable(r8a66597, pipenum); | 1254 | pipe_irq_disable(r8a66597, pipenum); |
1254 | err("out write fifo not ready. (%d)", pipenum); | 1255 | err("out write fifo not ready. (%d)", pipenum); |
1255 | finish_request(r8a66597, td, pipenum, td->urb); | 1256 | finish_request(r8a66597, td, pipenum, urb, -EPIPE); |
1256 | return; | 1257 | return; |
1257 | } | 1258 | } |
1258 | 1259 | ||
@@ -1297,7 +1298,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | |||
1297 | } | 1298 | } |
1298 | 1299 | ||
1299 | 1300 | ||
1300 | static void check_next_phase(struct r8a66597 *r8a66597) | 1301 | static void check_next_phase(struct r8a66597 *r8a66597, int status) |
1301 | { | 1302 | { |
1302 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0); | 1303 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0); |
1303 | struct urb *urb; | 1304 | struct urb *urb; |
@@ -1310,49 +1311,41 @@ static void check_next_phase(struct r8a66597 *r8a66597) | |||
1310 | switch (td->type) { | 1311 | switch (td->type) { |
1311 | case USB_PID_IN: | 1312 | case USB_PID_IN: |
1312 | case USB_PID_OUT: | 1313 | case USB_PID_OUT: |
1313 | if (urb->status != -EINPROGRESS) { | ||
1314 | finish = 1; | ||
1315 | break; | ||
1316 | } | ||
1317 | if (check_transfer_finish(td, urb)) | 1314 | if (check_transfer_finish(td, urb)) |
1318 | td->type = USB_PID_ACK; | 1315 | td->type = USB_PID_ACK; |
1319 | break; | 1316 | break; |
1320 | case USB_PID_SETUP: | 1317 | case USB_PID_SETUP: |
1321 | if (urb->status != -EINPROGRESS) | 1318 | if (urb->transfer_buffer_length == urb->actual_length) |
1322 | finish = 1; | ||
1323 | else if (urb->transfer_buffer_length == urb->actual_length) { | ||
1324 | td->type = USB_PID_ACK; | 1319 | td->type = USB_PID_ACK; |
1325 | urb->status = 0; | 1320 | else if (usb_pipeout(urb->pipe)) |
1326 | } else if (usb_pipeout(urb->pipe)) | ||
1327 | td->type = USB_PID_OUT; | 1321 | td->type = USB_PID_OUT; |
1328 | else | 1322 | else |
1329 | td->type = USB_PID_IN; | 1323 | td->type = USB_PID_IN; |
1330 | break; | 1324 | break; |
1331 | case USB_PID_ACK: | 1325 | case USB_PID_ACK: |
1332 | finish = 1; | 1326 | finish = 1; |
1333 | if (urb->status == -EINPROGRESS) | ||
1334 | urb->status = 0; | ||
1335 | break; | 1327 | break; |
1336 | } | 1328 | } |
1337 | 1329 | ||
1338 | if (finish) | 1330 | if (finish || status != 0 || urb->unlinked) |
1339 | finish_request(r8a66597, td, 0, urb); | 1331 | finish_request(r8a66597, td, 0, urb, status); |
1340 | else | 1332 | else |
1341 | start_transfer(r8a66597, td); | 1333 | start_transfer(r8a66597, td); |
1342 | } | 1334 | } |
1343 | 1335 | ||
1344 | static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum) | 1336 | static int get_urb_error(struct r8a66597 *r8a66597, u16 pipenum) |
1345 | { | 1337 | { |
1346 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); | 1338 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); |
1347 | 1339 | ||
1348 | if (td && td->urb) { | 1340 | if (td) { |
1349 | u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID; | 1341 | u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID; |
1350 | 1342 | ||
1351 | if (pid == PID_NAK) | 1343 | if (pid == PID_NAK) |
1352 | td->urb->status = -ECONNRESET; | 1344 | return -ECONNRESET; |
1353 | else | 1345 | else |
1354 | td->urb->status = -EPIPE; | 1346 | return -EPIPE; |
1355 | } | 1347 | } |
1348 | return 0; | ||
1356 | } | 1349 | } |
1357 | 1350 | ||
1358 | static void irq_pipe_ready(struct r8a66597 *r8a66597) | 1351 | static void irq_pipe_ready(struct r8a66597 *r8a66597) |
@@ -1371,7 +1364,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597) | |||
1371 | packet_read(r8a66597, 0); | 1364 | packet_read(r8a66597, 0); |
1372 | else | 1365 | else |
1373 | pipe_irq_disable(r8a66597, 0); | 1366 | pipe_irq_disable(r8a66597, 0); |
1374 | check_next_phase(r8a66597); | 1367 | check_next_phase(r8a66597, 0); |
1375 | } | 1368 | } |
1376 | 1369 | ||
1377 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | 1370 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { |
@@ -1405,7 +1398,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597) | |||
1405 | td = r8a66597_get_td(r8a66597, 0); | 1398 | td = r8a66597_get_td(r8a66597, 0); |
1406 | if (td && td->type != USB_PID_OUT) | 1399 | if (td && td->type != USB_PID_OUT) |
1407 | disable_irq_empty(r8a66597, 0); | 1400 | disable_irq_empty(r8a66597, 0); |
1408 | check_next_phase(r8a66597); | 1401 | check_next_phase(r8a66597, 0); |
1409 | } | 1402 | } |
1410 | 1403 | ||
1411 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | 1404 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { |
@@ -1420,9 +1413,8 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597) | |||
1420 | if ((tmp & INBUFM) == 0) { | 1413 | if ((tmp & INBUFM) == 0) { |
1421 | disable_irq_empty(r8a66597, pipenum); | 1414 | disable_irq_empty(r8a66597, pipenum); |
1422 | pipe_irq_disable(r8a66597, pipenum); | 1415 | pipe_irq_disable(r8a66597, pipenum); |
1423 | if (td->urb->status == -EINPROGRESS) | 1416 | finish_request(r8a66597, td, pipenum, td->urb, |
1424 | td->urb->status = 0; | 1417 | 0); |
1425 | finish_request(r8a66597, td, pipenum, td->urb); | ||
1426 | } | 1418 | } |
1427 | } | 1419 | } |
1428 | } | 1420 | } |
@@ -1433,15 +1425,16 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597) | |||
1433 | u16 check; | 1425 | u16 check; |
1434 | u16 pipenum; | 1426 | u16 pipenum; |
1435 | u16 mask; | 1427 | u16 mask; |
1428 | int status; | ||
1436 | 1429 | ||
1437 | mask = r8a66597_read(r8a66597, NRDYSTS) | 1430 | mask = r8a66597_read(r8a66597, NRDYSTS) |
1438 | & r8a66597_read(r8a66597, NRDYENB); | 1431 | & r8a66597_read(r8a66597, NRDYENB); |
1439 | r8a66597_write(r8a66597, ~mask, NRDYSTS); | 1432 | r8a66597_write(r8a66597, ~mask, NRDYSTS); |
1440 | if (mask & NRDY0) { | 1433 | if (mask & NRDY0) { |
1441 | cfifo_change(r8a66597, 0); | 1434 | cfifo_change(r8a66597, 0); |
1442 | set_urb_error(r8a66597, 0); | 1435 | status = get_urb_error(r8a66597, 0); |
1443 | pipe_irq_disable(r8a66597, 0); | 1436 | pipe_irq_disable(r8a66597, 0); |
1444 | check_next_phase(r8a66597); | 1437 | check_next_phase(r8a66597, status); |
1445 | } | 1438 | } |
1446 | 1439 | ||
1447 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | 1440 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { |
@@ -1452,10 +1445,10 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597) | |||
1452 | if (unlikely(!td)) | 1445 | if (unlikely(!td)) |
1453 | continue; | 1446 | continue; |
1454 | 1447 | ||
1455 | set_urb_error(r8a66597, pipenum); | 1448 | status = get_urb_error(r8a66597, pipenum); |
1456 | pipe_irq_disable(r8a66597, pipenum); | 1449 | pipe_irq_disable(r8a66597, pipenum); |
1457 | pipe_stop(r8a66597, td->pipe); | 1450 | pipe_stop(r8a66597, td->pipe); |
1458 | finish_request(r8a66597, td, pipenum, td->urb); | 1451 | finish_request(r8a66597, td, pipenum, td->urb, status); |
1459 | } | 1452 | } |
1460 | } | 1453 | } |
1461 | } | 1454 | } |
@@ -1475,6 +1468,7 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1475 | u16 intsts0, intsts1, intsts2; | 1468 | u16 intsts0, intsts1, intsts2; |
1476 | u16 intenb0, intenb1, intenb2; | 1469 | u16 intenb0, intenb1, intenb2; |
1477 | u16 mask0, mask1, mask2; | 1470 | u16 mask0, mask1, mask2; |
1471 | int status; | ||
1478 | 1472 | ||
1479 | spin_lock(&r8a66597->lock); | 1473 | spin_lock(&r8a66597->lock); |
1480 | 1474 | ||
@@ -1518,12 +1512,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | |||
1518 | } | 1512 | } |
1519 | if (mask1 & SIGN) { | 1513 | if (mask1 & SIGN) { |
1520 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); | 1514 | r8a66597_write(r8a66597, ~SIGN, INTSTS1); |
1521 | set_urb_error(r8a66597, 0); | 1515 | status = get_urb_error(r8a66597, 0); |
1522 | check_next_phase(r8a66597); | 1516 | check_next_phase(r8a66597, status); |
1523 | } | 1517 | } |
1524 | if (mask1 & SACK) { | 1518 | if (mask1 & SACK) { |
1525 | r8a66597_write(r8a66597, ~SACK, INTSTS1); | 1519 | r8a66597_write(r8a66597, ~SACK, INTSTS1); |
1526 | check_next_phase(r8a66597); | 1520 | check_next_phase(r8a66597, 0); |
1527 | } | 1521 | } |
1528 | } | 1522 | } |
1529 | if (mask0) { | 1523 | if (mask0) { |
@@ -1722,21 +1716,25 @@ static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597, | |||
1722 | } | 1716 | } |
1723 | 1717 | ||
1724 | static int r8a66597_urb_enqueue(struct usb_hcd *hcd, | 1718 | static int r8a66597_urb_enqueue(struct usb_hcd *hcd, |
1725 | struct usb_host_endpoint *hep, | ||
1726 | struct urb *urb, | 1719 | struct urb *urb, |
1727 | gfp_t mem_flags) | 1720 | gfp_t mem_flags) |
1728 | { | 1721 | { |
1722 | struct usb_host_endpoint *hep = urb->ep; | ||
1729 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | 1723 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); |
1730 | struct r8a66597_td *td = NULL; | 1724 | struct r8a66597_td *td = NULL; |
1731 | int ret = 0, request = 0; | 1725 | int ret, request = 0; |
1732 | unsigned long flags; | 1726 | unsigned long flags; |
1733 | 1727 | ||
1734 | spin_lock_irqsave(&r8a66597->lock, flags); | 1728 | spin_lock_irqsave(&r8a66597->lock, flags); |
1735 | if (!get_urb_to_r8a66597_dev(r8a66597, urb)) { | 1729 | if (!get_urb_to_r8a66597_dev(r8a66597, urb)) { |
1736 | ret = -ENODEV; | 1730 | ret = -ENODEV; |
1737 | goto error; | 1731 | goto error_not_linked; |
1738 | } | 1732 | } |
1739 | 1733 | ||
1734 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
1735 | if (ret) | ||
1736 | goto error_not_linked; | ||
1737 | |||
1740 | if (!hep->hcpriv) { | 1738 | if (!hep->hcpriv) { |
1741 | hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), | 1739 | hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), |
1742 | GFP_ATOMIC); | 1740 | GFP_ATOMIC); |
@@ -1761,15 +1759,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, | |||
1761 | if (list_empty(&r8a66597->pipe_queue[td->pipenum])) | 1759 | if (list_empty(&r8a66597->pipe_queue[td->pipenum])) |
1762 | request = 1; | 1760 | request = 1; |
1763 | list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]); | 1761 | list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]); |
1764 | |||
1765 | spin_lock(&urb->lock); | ||
1766 | if (urb->status != -EINPROGRESS) { | ||
1767 | spin_unlock(&urb->lock); | ||
1768 | ret = -EPIPE; | ||
1769 | goto error; | ||
1770 | } | ||
1771 | urb->hcpriv = td; | 1762 | urb->hcpriv = td; |
1772 | spin_unlock(&urb->lock); | ||
1773 | 1763 | ||
1774 | if (request) { | 1764 | if (request) { |
1775 | ret = start_transfer(r8a66597, td); | 1765 | ret = start_transfer(r8a66597, td); |
@@ -1781,26 +1771,36 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, | |||
1781 | set_td_timer(r8a66597, td); | 1771 | set_td_timer(r8a66597, td); |
1782 | 1772 | ||
1783 | error: | 1773 | error: |
1774 | if (ret) | ||
1775 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
1776 | error_not_linked: | ||
1784 | spin_unlock_irqrestore(&r8a66597->lock, flags); | 1777 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
1785 | return ret; | 1778 | return ret; |
1786 | } | 1779 | } |
1787 | 1780 | ||
1788 | static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 1781 | static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, |
1782 | int status) | ||
1789 | { | 1783 | { |
1790 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | 1784 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); |
1791 | struct r8a66597_td *td; | 1785 | struct r8a66597_td *td; |
1792 | unsigned long flags; | 1786 | unsigned long flags; |
1787 | int rc; | ||
1793 | 1788 | ||
1794 | spin_lock_irqsave(&r8a66597->lock, flags); | 1789 | spin_lock_irqsave(&r8a66597->lock, flags); |
1790 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
1791 | if (rc) | ||
1792 | goto done; | ||
1793 | |||
1795 | if (urb->hcpriv) { | 1794 | if (urb->hcpriv) { |
1796 | td = urb->hcpriv; | 1795 | td = urb->hcpriv; |
1797 | pipe_stop(r8a66597, td->pipe); | 1796 | pipe_stop(r8a66597, td->pipe); |
1798 | pipe_irq_disable(r8a66597, td->pipenum); | 1797 | pipe_irq_disable(r8a66597, td->pipenum); |
1799 | disable_irq_empty(r8a66597, td->pipenum); | 1798 | disable_irq_empty(r8a66597, td->pipenum); |
1800 | done(r8a66597, td, td->pipenum, urb); | 1799 | finish_request(r8a66597, td, td->pipenum, urb, status); |
1801 | } | 1800 | } |
1801 | done: | ||
1802 | spin_unlock_irqrestore(&r8a66597->lock, flags); | 1802 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
1803 | return 0; | 1803 | return rc; |
1804 | } | 1804 | } |
1805 | 1805 | ||
1806 | static void r8a66597_endpoint_disable(struct usb_hcd *hcd, | 1806 | static void r8a66597_endpoint_disable(struct usb_hcd *hcd, |
@@ -1830,7 +1830,7 @@ static void r8a66597_endpoint_disable(struct usb_hcd *hcd, | |||
1830 | td = r8a66597_get_td(r8a66597, pipenum); | 1830 | td = r8a66597_get_td(r8a66597, pipenum); |
1831 | if (td) | 1831 | if (td) |
1832 | urb = td->urb; | 1832 | urb = td->urb; |
1833 | done(r8a66597, td, pipenum, urb); | 1833 | finish_request(r8a66597, td, pipenum, urb, -ESHUTDOWN); |
1834 | kfree(hep->hcpriv); | 1834 | kfree(hep->hcpriv); |
1835 | hep->hcpriv = NULL; | 1835 | hep->hcpriv = NULL; |
1836 | spin_unlock_irqrestore(&r8a66597->lock, flags); | 1836 | spin_unlock_irqrestore(&r8a66597->lock, flags); |
@@ -2027,7 +2027,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2027 | case GetPortStatus: | 2027 | case GetPortStatus: |
2028 | if (wIndex > R8A66597_MAX_ROOT_HUB) | 2028 | if (wIndex > R8A66597_MAX_ROOT_HUB) |
2029 | goto error; | 2029 | goto error; |
2030 | *(u32 *)buf = rh->port; | 2030 | *(u32 *)buf = cpu_to_le32(rh->port); |
2031 | break; | 2031 | break; |
2032 | case SetPortFeature: | 2032 | case SetPortFeature: |
2033 | if (wIndex > R8A66597_MAX_ROOT_HUB) | 2033 | if (wIndex > R8A66597_MAX_ROOT_HUB) |
@@ -2126,8 +2126,8 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) | |||
2126 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | 2126 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); |
2127 | 2127 | ||
2128 | del_timer_sync(&r8a66597->rh_timer); | 2128 | del_timer_sync(&r8a66597->rh_timer); |
2129 | iounmap((void *)r8a66597->reg); | ||
2130 | usb_remove_hcd(hcd); | 2129 | usb_remove_hcd(hcd); |
2130 | iounmap((void *)r8a66597->reg); | ||
2131 | usb_put_hcd(hcd); | 2131 | usb_put_hcd(hcd); |
2132 | return 0; | 2132 | return 0; |
2133 | } | 2133 | } |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 4cfa3ff2c993..94d859aa73f8 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -435,14 +435,9 @@ static void finish_request( | |||
435 | if (usb_pipecontrol(urb->pipe)) | 435 | if (usb_pipecontrol(urb->pipe)) |
436 | ep->nextpid = USB_PID_SETUP; | 436 | ep->nextpid = USB_PID_SETUP; |
437 | 437 | ||
438 | spin_lock(&urb->lock); | 438 | usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb); |
439 | if (urb->status == -EINPROGRESS) | ||
440 | urb->status = status; | ||
441 | urb->hcpriv = NULL; | ||
442 | spin_unlock(&urb->lock); | ||
443 | |||
444 | spin_unlock(&sl811->lock); | 439 | spin_unlock(&sl811->lock); |
445 | usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb); | 440 | usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, status); |
446 | spin_lock(&sl811->lock); | 441 | spin_lock(&sl811->lock); |
447 | 442 | ||
448 | /* leave active endpoints in the schedule */ | 443 | /* leave active endpoints in the schedule */ |
@@ -538,35 +533,21 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) | |||
538 | bank + SL11H_XFERCNTREG); | 533 | bank + SL11H_XFERCNTREG); |
539 | if (len > ep->length) { | 534 | if (len > ep->length) { |
540 | len = ep->length; | 535 | len = ep->length; |
541 | urb->status = -EOVERFLOW; | 536 | urbstat = -EOVERFLOW; |
542 | } | 537 | } |
543 | urb->actual_length += len; | 538 | urb->actual_length += len; |
544 | sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0), | 539 | sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0), |
545 | buf, len); | 540 | buf, len); |
546 | usb_dotoggle(udev, ep->epnum, 0); | 541 | usb_dotoggle(udev, ep->epnum, 0); |
547 | if (urb->actual_length == urb->transfer_buffer_length) | 542 | if (urbstat == -EINPROGRESS && |
548 | urbstat = 0; | 543 | (len < ep->maxpacket || |
549 | else if (len < ep->maxpacket) { | 544 | urb->actual_length == |
550 | if (urb->transfer_flags & URB_SHORT_NOT_OK) | 545 | urb->transfer_buffer_length)) { |
551 | urbstat = -EREMOTEIO; | 546 | if (usb_pipecontrol(urb->pipe)) |
547 | ep->nextpid = USB_PID_ACK; | ||
552 | else | 548 | else |
553 | urbstat = 0; | 549 | urbstat = 0; |
554 | } | 550 | } |
555 | if (usb_pipecontrol(urb->pipe) | ||
556 | && (urbstat == -EREMOTEIO | ||
557 | || urbstat == 0)) { | ||
558 | |||
559 | /* NOTE if the status stage STALLs (why?), | ||
560 | * this reports the wrong urb status. | ||
561 | */ | ||
562 | spin_lock(&urb->lock); | ||
563 | if (urb->status == -EINPROGRESS) | ||
564 | urb->status = urbstat; | ||
565 | spin_unlock(&urb->lock); | ||
566 | |||
567 | urb = NULL; | ||
568 | ep->nextpid = USB_PID_ACK; | ||
569 | } | ||
570 | break; | 551 | break; |
571 | case USB_PID_SETUP: | 552 | case USB_PID_SETUP: |
572 | // PACKET("...ACK/setup_%02x qh%p\n", bank, ep); | 553 | // PACKET("...ACK/setup_%02x qh%p\n", bank, ep); |
@@ -605,7 +586,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) | |||
605 | bank, status, ep, urbstat); | 586 | bank, status, ep, urbstat); |
606 | } | 587 | } |
607 | 588 | ||
608 | if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)) | 589 | if (urbstat != -EINPROGRESS || urb->unlinked) |
609 | finish_request(sl811, ep, urb, urbstat); | 590 | finish_request(sl811, ep, urb, urbstat); |
610 | } | 591 | } |
611 | 592 | ||
@@ -807,7 +788,6 @@ static int balance(struct sl811 *sl811, u16 period, u16 load) | |||
807 | 788 | ||
808 | static int sl811h_urb_enqueue( | 789 | static int sl811h_urb_enqueue( |
809 | struct usb_hcd *hcd, | 790 | struct usb_hcd *hcd, |
810 | struct usb_host_endpoint *hep, | ||
811 | struct urb *urb, | 791 | struct urb *urb, |
812 | gfp_t mem_flags | 792 | gfp_t mem_flags |
813 | ) { | 793 | ) { |
@@ -820,7 +800,8 @@ static int sl811h_urb_enqueue( | |||
820 | struct sl811h_ep *ep = NULL; | 800 | struct sl811h_ep *ep = NULL; |
821 | unsigned long flags; | 801 | unsigned long flags; |
822 | int i; | 802 | int i; |
823 | int retval = 0; | 803 | int retval; |
804 | struct usb_host_endpoint *hep = urb->ep; | ||
824 | 805 | ||
825 | #ifdef DISABLE_ISO | 806 | #ifdef DISABLE_ISO |
826 | if (type == PIPE_ISOCHRONOUS) | 807 | if (type == PIPE_ISOCHRONOUS) |
@@ -838,7 +819,12 @@ static int sl811h_urb_enqueue( | |||
838 | || !HC_IS_RUNNING(hcd->state)) { | 819 | || !HC_IS_RUNNING(hcd->state)) { |
839 | retval = -ENODEV; | 820 | retval = -ENODEV; |
840 | kfree(ep); | 821 | kfree(ep); |
841 | goto fail; | 822 | goto fail_not_linked; |
823 | } | ||
824 | retval = usb_hcd_link_urb_to_ep(hcd, urb); | ||
825 | if (retval) { | ||
826 | kfree(ep); | ||
827 | goto fail_not_linked; | ||
842 | } | 828 | } |
843 | 829 | ||
844 | if (hep->hcpriv) { | 830 | if (hep->hcpriv) { |
@@ -951,37 +937,31 @@ static int sl811h_urb_enqueue( | |||
951 | sofirq_on(sl811); | 937 | sofirq_on(sl811); |
952 | } | 938 | } |
953 | 939 | ||
954 | /* in case of unlink-during-submit */ | ||
955 | spin_lock(&urb->lock); | ||
956 | if (urb->status != -EINPROGRESS) { | ||
957 | spin_unlock(&urb->lock); | ||
958 | finish_request(sl811, ep, urb, 0); | ||
959 | retval = 0; | ||
960 | goto fail; | ||
961 | } | ||
962 | urb->hcpriv = hep; | 940 | urb->hcpriv = hep; |
963 | spin_unlock(&urb->lock); | ||
964 | |||
965 | start_transfer(sl811); | 941 | start_transfer(sl811); |
966 | sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); | 942 | sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); |
967 | fail: | 943 | fail: |
944 | if (retval) | ||
945 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
946 | fail_not_linked: | ||
968 | spin_unlock_irqrestore(&sl811->lock, flags); | 947 | spin_unlock_irqrestore(&sl811->lock, flags); |
969 | return retval; | 948 | return retval; |
970 | } | 949 | } |
971 | 950 | ||
972 | static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 951 | static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
973 | { | 952 | { |
974 | struct sl811 *sl811 = hcd_to_sl811(hcd); | 953 | struct sl811 *sl811 = hcd_to_sl811(hcd); |
975 | struct usb_host_endpoint *hep; | 954 | struct usb_host_endpoint *hep; |
976 | unsigned long flags; | 955 | unsigned long flags; |
977 | struct sl811h_ep *ep; | 956 | struct sl811h_ep *ep; |
978 | int retval = 0; | 957 | int retval; |
979 | 958 | ||
980 | spin_lock_irqsave(&sl811->lock, flags); | 959 | spin_lock_irqsave(&sl811->lock, flags); |
981 | hep = urb->hcpriv; | 960 | retval = usb_hcd_check_unlink_urb(hcd, urb, status); |
982 | if (!hep) | 961 | if (retval) |
983 | goto fail; | 962 | goto fail; |
984 | 963 | ||
964 | hep = urb->hcpriv; | ||
985 | ep = hep->hcpriv; | 965 | ep = hep->hcpriv; |
986 | if (ep) { | 966 | if (ep) { |
987 | /* finish right away if this urb can't be active ... | 967 | /* finish right away if this urb can't be active ... |
@@ -1029,8 +1009,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
1029 | VDBG("dequeue, urb %p active %s; wait4irq\n", urb, | 1009 | VDBG("dequeue, urb %p active %s; wait4irq\n", urb, |
1030 | (sl811->active_a == ep) ? "A" : "B"); | 1010 | (sl811->active_a == ep) ? "A" : "B"); |
1031 | } else | 1011 | } else |
1032 | fail: | ||
1033 | retval = -EINVAL; | 1012 | retval = -EINVAL; |
1013 | fail: | ||
1034 | spin_unlock_irqrestore(&sl811->lock, flags); | 1014 | spin_unlock_irqrestore(&sl811->lock, flags); |
1035 | return retval; | 1015 | return retval; |
1036 | } | 1016 | } |
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index b88eb3c62c02..ac283b09a63f 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <linux/usb.h> | 51 | #include <linux/usb.h> |
52 | #include <linux/workqueue.h> | 52 | #include <linux/workqueue.h> |
53 | #include <linux/platform_device.h> | 53 | #include <linux/platform_device.h> |
54 | #include <linux/pci_ids.h> | ||
55 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
56 | #include <asm/io.h> | 55 | #include <asm/io.h> |
57 | #include <asm/irq.h> | 56 | #include <asm/irq.h> |
@@ -184,7 +183,7 @@ struct u132_ring { | |||
184 | struct u132 { | 183 | struct u132 { |
185 | struct kref kref; | 184 | struct kref kref; |
186 | struct list_head u132_list; | 185 | struct list_head u132_list; |
187 | struct semaphore sw_lock; | 186 | struct mutex sw_lock; |
188 | struct semaphore scheduler_lock; | 187 | struct semaphore scheduler_lock; |
189 | struct u132_platform_data *board; | 188 | struct u132_platform_data *board; |
190 | struct platform_device *platform_dev; | 189 | struct platform_device *platform_dev; |
@@ -493,20 +492,20 @@ static void u132_hcd_monitor_work(struct work_struct *work) | |||
493 | return; | 492 | return; |
494 | } else { | 493 | } else { |
495 | int retval; | 494 | int retval; |
496 | down(&u132->sw_lock); | 495 | mutex_lock(&u132->sw_lock); |
497 | retval = read_roothub_info(u132); | 496 | retval = read_roothub_info(u132); |
498 | if (retval) { | 497 | if (retval) { |
499 | struct usb_hcd *hcd = u132_to_hcd(u132); | 498 | struct usb_hcd *hcd = u132_to_hcd(u132); |
500 | u132_disable(u132); | 499 | u132_disable(u132); |
501 | u132->going = 1; | 500 | u132->going = 1; |
502 | up(&u132->sw_lock); | 501 | mutex_unlock(&u132->sw_lock); |
503 | usb_hc_died(hcd); | 502 | usb_hc_died(hcd); |
504 | ftdi_elan_gone_away(u132->platform_dev); | 503 | ftdi_elan_gone_away(u132->platform_dev); |
505 | u132_monitor_put_kref(u132); | 504 | u132_monitor_put_kref(u132); |
506 | return; | 505 | return; |
507 | } else { | 506 | } else { |
508 | u132_monitor_requeue_work(u132, 500); | 507 | u132_monitor_requeue_work(u132, 500); |
509 | up(&u132->sw_lock); | 508 | mutex_unlock(&u132->sw_lock); |
510 | return; | 509 | return; |
511 | } | 510 | } |
512 | } | 511 | } |
@@ -519,9 +518,8 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, | |||
519 | unsigned long irqs; | 518 | unsigned long irqs; |
520 | struct usb_hcd *hcd = u132_to_hcd(u132); | 519 | struct usb_hcd *hcd = u132_to_hcd(u132); |
521 | urb->error_count = 0; | 520 | urb->error_count = 0; |
522 | urb->status = status; | ||
523 | urb->hcpriv = NULL; | ||
524 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 521 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); |
522 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
525 | endp->queue_next += 1; | 523 | endp->queue_next += 1; |
526 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { | 524 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { |
527 | endp->active = 0; | 525 | endp->active = 0; |
@@ -543,7 +541,7 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp, | |||
543 | u132_ring_queue_work(u132, ring, 0); | 541 | u132_ring_queue_work(u132, ring, 0); |
544 | up(&u132->scheduler_lock); | 542 | up(&u132->scheduler_lock); |
545 | u132_endp_put_kref(u132, endp); | 543 | u132_endp_put_kref(u132, endp); |
546 | usb_hcd_giveback_urb(hcd, urb); | 544 | usb_hcd_giveback_urb(hcd, urb, status); |
547 | return; | 545 | return; |
548 | } | 546 | } |
549 | 547 | ||
@@ -559,9 +557,8 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, | |||
559 | unsigned long irqs; | 557 | unsigned long irqs; |
560 | struct usb_hcd *hcd = u132_to_hcd(u132); | 558 | struct usb_hcd *hcd = u132_to_hcd(u132); |
561 | urb->error_count = 0; | 559 | urb->error_count = 0; |
562 | urb->status = status; | ||
563 | urb->hcpriv = NULL; | ||
564 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 560 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); |
561 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
565 | endp->queue_next += 1; | 562 | endp->queue_next += 1; |
566 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { | 563 | if (ENDP_QUEUE_SIZE > --endp->queue_size) { |
567 | endp->active = 0; | 564 | endp->active = 0; |
@@ -576,7 +573,7 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp, | |||
576 | endp->active = 0; | 573 | endp->active = 0; |
577 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 574 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); |
578 | kfree(urbq); | 575 | kfree(urbq); |
579 | } usb_hcd_giveback_urb(hcd, urb); | 576 | } usb_hcd_giveback_urb(hcd, urb, status); |
580 | return; | 577 | return; |
581 | } | 578 | } |
582 | 579 | ||
@@ -646,12 +643,12 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, | |||
646 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 643 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
647 | return; | 644 | return; |
648 | } else if (u132->going > 0) { | 645 | } else if (u132->going > 0) { |
649 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 646 | dev_err(&u132->platform_dev->dev, "device is being removed " |
650 | "%p status=%d\n", urb, urb->status); | 647 | "urb=%p\n", urb); |
651 | up(&u132->scheduler_lock); | 648 | up(&u132->scheduler_lock); |
652 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 649 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
653 | return; | 650 | return; |
654 | } else if (urb->status == -EINPROGRESS) { | 651 | } else if (!urb->unlinked) { |
655 | struct u132_ring *ring = endp->ring; | 652 | struct u132_ring *ring = endp->ring; |
656 | u8 *u = urb->transfer_buffer + urb->actual_length; | 653 | u8 *u = urb->transfer_buffer + urb->actual_length; |
657 | u8 *b = buf; | 654 | u8 *b = buf; |
@@ -717,10 +714,10 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, | |||
717 | return; | 714 | return; |
718 | } | 715 | } |
719 | } else { | 716 | } else { |
720 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 717 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
721 | "s=%d\n", urb, urb->status); | 718 | "unlinked=%d\n", urb, urb->unlinked); |
722 | up(&u132->scheduler_lock); | 719 | up(&u132->scheduler_lock); |
723 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 720 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
724 | return; | 721 | return; |
725 | } | 722 | } |
726 | } | 723 | } |
@@ -745,12 +742,12 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, | |||
745 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 742 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
746 | return; | 743 | return; |
747 | } else if (u132->going > 0) { | 744 | } else if (u132->going > 0) { |
748 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 745 | dev_err(&u132->platform_dev->dev, "device is being removed " |
749 | "%p status=%d\n", urb, urb->status); | 746 | "urb=%p\n", urb); |
750 | up(&u132->scheduler_lock); | 747 | up(&u132->scheduler_lock); |
751 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 748 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
752 | return; | 749 | return; |
753 | } else if (urb->status == -EINPROGRESS) { | 750 | } else if (!urb->unlinked) { |
754 | struct u132_ring *ring = endp->ring; | 751 | struct u132_ring *ring = endp->ring; |
755 | urb->actual_length += len; | 752 | urb->actual_length += len; |
756 | endp->toggle_bits = toggle_bits; | 753 | endp->toggle_bits = toggle_bits; |
@@ -769,10 +766,10 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, | |||
769 | return; | 766 | return; |
770 | } | 767 | } |
771 | } else { | 768 | } else { |
772 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 769 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
773 | "s=%d\n", urb, urb->status); | 770 | "unlinked=%d\n", urb, urb->unlinked); |
774 | up(&u132->scheduler_lock); | 771 | up(&u132->scheduler_lock); |
775 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 772 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
776 | return; | 773 | return; |
777 | } | 774 | } |
778 | } | 775 | } |
@@ -798,12 +795,12 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, | |||
798 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 795 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
799 | return; | 796 | return; |
800 | } else if (u132->going > 0) { | 797 | } else if (u132->going > 0) { |
801 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 798 | dev_err(&u132->platform_dev->dev, "device is being removed " |
802 | "%p status=%d\n", urb, urb->status); | 799 | "urb=%p\n", urb); |
803 | up(&u132->scheduler_lock); | 800 | up(&u132->scheduler_lock); |
804 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 801 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
805 | return; | 802 | return; |
806 | } else if (urb->status == -EINPROGRESS) { | 803 | } else if (!urb->unlinked) { |
807 | struct u132_ring *ring = endp->ring; | 804 | struct u132_ring *ring = endp->ring; |
808 | u8 *u = urb->transfer_buffer + urb->actual_length; | 805 | u8 *u = urb->transfer_buffer + urb->actual_length; |
809 | u8 *b = buf; | 806 | u8 *b = buf; |
@@ -872,10 +869,10 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, | |||
872 | return; | 869 | return; |
873 | } | 870 | } |
874 | } else { | 871 | } else { |
875 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 872 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
876 | "s=%d\n", urb, urb->status); | 873 | "unlinked=%d\n", urb, urb->unlinked); |
877 | up(&u132->scheduler_lock); | 874 | up(&u132->scheduler_lock); |
878 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 875 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
879 | return; | 876 | return; |
880 | } | 877 | } |
881 | } | 878 | } |
@@ -899,20 +896,20 @@ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf, | |||
899 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 896 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
900 | return; | 897 | return; |
901 | } else if (u132->going > 0) { | 898 | } else if (u132->going > 0) { |
902 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 899 | dev_err(&u132->platform_dev->dev, "device is being removed " |
903 | "%p status=%d\n", urb, urb->status); | 900 | "urb=%p\n", urb); |
904 | up(&u132->scheduler_lock); | 901 | up(&u132->scheduler_lock); |
905 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 902 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
906 | return; | 903 | return; |
907 | } else if (urb->status == -EINPROGRESS) { | 904 | } else if (!urb->unlinked) { |
908 | up(&u132->scheduler_lock); | 905 | up(&u132->scheduler_lock); |
909 | u132_hcd_giveback_urb(u132, endp, urb, 0); | 906 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
910 | return; | 907 | return; |
911 | } else { | 908 | } else { |
912 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 909 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
913 | "s=%d\n", urb, urb->status); | 910 | "unlinked=%d\n", urb, urb->unlinked); |
914 | up(&u132->scheduler_lock); | 911 | up(&u132->scheduler_lock); |
915 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 912 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
916 | return; | 913 | return; |
917 | } | 914 | } |
918 | } | 915 | } |
@@ -937,12 +934,12 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, | |||
937 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 934 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
938 | return; | 935 | return; |
939 | } else if (u132->going > 0) { | 936 | } else if (u132->going > 0) { |
940 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 937 | dev_err(&u132->platform_dev->dev, "device is being removed " |
941 | "%p status=%d\n", urb, urb->status); | 938 | "urb=%p\n", urb); |
942 | up(&u132->scheduler_lock); | 939 | up(&u132->scheduler_lock); |
943 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 940 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
944 | return; | 941 | return; |
945 | } else if (urb->status == -EINPROGRESS) { | 942 | } else if (!urb->unlinked) { |
946 | struct u132_ring *ring = endp->ring; | 943 | struct u132_ring *ring = endp->ring; |
947 | u8 *u = urb->transfer_buffer; | 944 | u8 *u = urb->transfer_buffer; |
948 | u8 *b = buf; | 945 | u8 *b = buf; |
@@ -981,10 +978,10 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, | |||
981 | return; | 978 | return; |
982 | } | 979 | } |
983 | } else { | 980 | } else { |
984 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 981 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
985 | "s=%d\n", urb, urb->status); | 982 | "unlinked=%d\n", urb, urb->unlinked); |
986 | up(&u132->scheduler_lock); | 983 | up(&u132->scheduler_lock); |
987 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 984 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
988 | return; | 985 | return; |
989 | } | 986 | } |
990 | } | 987 | } |
@@ -1008,20 +1005,20 @@ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf, | |||
1008 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1005 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1009 | return; | 1006 | return; |
1010 | } else if (u132->going > 0) { | 1007 | } else if (u132->going > 0) { |
1011 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1008 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1012 | "%p status=%d\n", urb, urb->status); | 1009 | "urb=%p\n", urb); |
1013 | up(&u132->scheduler_lock); | 1010 | up(&u132->scheduler_lock); |
1014 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1011 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1015 | return; | 1012 | return; |
1016 | } else if (urb->status == -EINPROGRESS) { | 1013 | } else if (!urb->unlinked) { |
1017 | up(&u132->scheduler_lock); | 1014 | up(&u132->scheduler_lock); |
1018 | u132_hcd_giveback_urb(u132, endp, urb, 0); | 1015 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1019 | return; | 1016 | return; |
1020 | } else { | 1017 | } else { |
1021 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1018 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1022 | "s=%d\n", urb, urb->status); | 1019 | "unlinked=%d\n", urb, urb->unlinked); |
1023 | up(&u132->scheduler_lock); | 1020 | up(&u132->scheduler_lock); |
1024 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1021 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1025 | return; | 1022 | return; |
1026 | } | 1023 | } |
1027 | } | 1024 | } |
@@ -1046,12 +1043,12 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, | |||
1046 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1043 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1047 | return; | 1044 | return; |
1048 | } else if (u132->going > 0) { | 1045 | } else if (u132->going > 0) { |
1049 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1046 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1050 | "%p status=%d\n", urb, urb->status); | 1047 | "urb=%p\n", urb); |
1051 | up(&u132->scheduler_lock); | 1048 | up(&u132->scheduler_lock); |
1052 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1049 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1053 | return; | 1050 | return; |
1054 | } else if (urb->status == -EINPROGRESS) { | 1051 | } else if (!urb->unlinked) { |
1055 | if (usb_pipein(urb->pipe)) { | 1052 | if (usb_pipein(urb->pipe)) { |
1056 | int retval; | 1053 | int retval; |
1057 | struct u132_ring *ring = endp->ring; | 1054 | struct u132_ring *ring = endp->ring; |
@@ -1078,10 +1075,10 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, | |||
1078 | return; | 1075 | return; |
1079 | } | 1076 | } |
1080 | } else { | 1077 | } else { |
1081 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1078 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1082 | "s=%d\n", urb, urb->status); | 1079 | "unlinked=%d\n", urb, urb->unlinked); |
1083 | up(&u132->scheduler_lock); | 1080 | up(&u132->scheduler_lock); |
1084 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1081 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1085 | return; | 1082 | return; |
1086 | } | 1083 | } |
1087 | } | 1084 | } |
@@ -1107,22 +1104,22 @@ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb, | |||
1107 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1104 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1108 | return; | 1105 | return; |
1109 | } else if (u132->going > 0) { | 1106 | } else if (u132->going > 0) { |
1110 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1107 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1111 | "%p status=%d\n", urb, urb->status); | 1108 | "urb=%p\n", urb); |
1112 | up(&u132->scheduler_lock); | 1109 | up(&u132->scheduler_lock); |
1113 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1110 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1114 | return; | 1111 | return; |
1115 | } else if (urb->status == -EINPROGRESS) { | 1112 | } else if (!urb->unlinked) { |
1116 | u132->addr[0].address = 0; | 1113 | u132->addr[0].address = 0; |
1117 | endp->usb_addr = udev->usb_addr; | 1114 | endp->usb_addr = udev->usb_addr; |
1118 | up(&u132->scheduler_lock); | 1115 | up(&u132->scheduler_lock); |
1119 | u132_hcd_giveback_urb(u132, endp, urb, 0); | 1116 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1120 | return; | 1117 | return; |
1121 | } else { | 1118 | } else { |
1122 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1119 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1123 | "s=%d\n", urb, urb->status); | 1120 | "unlinked=%d\n", urb, urb->unlinked); |
1124 | up(&u132->scheduler_lock); | 1121 | up(&u132->scheduler_lock); |
1125 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1122 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1126 | return; | 1123 | return; |
1127 | } | 1124 | } |
1128 | } | 1125 | } |
@@ -1146,12 +1143,12 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, | |||
1146 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1143 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1147 | return; | 1144 | return; |
1148 | } else if (u132->going > 0) { | 1145 | } else if (u132->going > 0) { |
1149 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1146 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1150 | "%p status=%d\n", urb, urb->status); | 1147 | "urb=%p\n", urb); |
1151 | up(&u132->scheduler_lock); | 1148 | up(&u132->scheduler_lock); |
1152 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1149 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1153 | return; | 1150 | return; |
1154 | } else if (urb->status == -EINPROGRESS) { | 1151 | } else if (!urb->unlinked) { |
1155 | int retval; | 1152 | int retval; |
1156 | struct u132_ring *ring = endp->ring; | 1153 | struct u132_ring *ring = endp->ring; |
1157 | up(&u132->scheduler_lock); | 1154 | up(&u132->scheduler_lock); |
@@ -1163,10 +1160,10 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, | |||
1163 | u132_hcd_giveback_urb(u132, endp, urb, retval); | 1160 | u132_hcd_giveback_urb(u132, endp, urb, retval); |
1164 | return; | 1161 | return; |
1165 | } else { | 1162 | } else { |
1166 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1163 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1167 | "s=%d\n", urb, urb->status); | 1164 | "unlinked=%d\n", urb, urb->unlinked); |
1168 | up(&u132->scheduler_lock); | 1165 | up(&u132->scheduler_lock); |
1169 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1166 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1170 | return; | 1167 | return; |
1171 | } | 1168 | } |
1172 | } | 1169 | } |
@@ -1190,20 +1187,20 @@ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf, | |||
1190 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1187 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1191 | return; | 1188 | return; |
1192 | } else if (u132->going > 0) { | 1189 | } else if (u132->going > 0) { |
1193 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1190 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1194 | "%p status=%d\n", urb, urb->status); | 1191 | "urb=%p\n", urb); |
1195 | up(&u132->scheduler_lock); | 1192 | up(&u132->scheduler_lock); |
1196 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1193 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1197 | return; | 1194 | return; |
1198 | } else if (urb->status == -EINPROGRESS) { | 1195 | } else if (!urb->unlinked) { |
1199 | up(&u132->scheduler_lock); | 1196 | up(&u132->scheduler_lock); |
1200 | u132_hcd_giveback_urb(u132, endp, urb, 0); | 1197 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1201 | return; | 1198 | return; |
1202 | } else { | 1199 | } else { |
1203 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1200 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1204 | "s=%d\n", urb, urb->status); | 1201 | "unlinked=%d\n", urb, urb->unlinked); |
1205 | up(&u132->scheduler_lock); | 1202 | up(&u132->scheduler_lock); |
1206 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1203 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1207 | return; | 1204 | return; |
1208 | } | 1205 | } |
1209 | } | 1206 | } |
@@ -1228,12 +1225,12 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, | |||
1228 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1225 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1229 | return; | 1226 | return; |
1230 | } else if (u132->going > 0) { | 1227 | } else if (u132->going > 0) { |
1231 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1228 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1232 | "%p status=%d\n", urb, urb->status); | 1229 | "urb=%p\n", urb); |
1233 | up(&u132->scheduler_lock); | 1230 | up(&u132->scheduler_lock); |
1234 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1231 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1235 | return; | 1232 | return; |
1236 | } else if (urb->status == -EINPROGRESS) { | 1233 | } else if (!urb->unlinked) { |
1237 | int retval; | 1234 | int retval; |
1238 | struct u132_ring *ring = endp->ring; | 1235 | struct u132_ring *ring = endp->ring; |
1239 | u8 *u = urb->transfer_buffer; | 1236 | u8 *u = urb->transfer_buffer; |
@@ -1252,10 +1249,10 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, | |||
1252 | u132_hcd_giveback_urb(u132, endp, urb, retval); | 1249 | u132_hcd_giveback_urb(u132, endp, urb, retval); |
1253 | return; | 1250 | return; |
1254 | } else { | 1251 | } else { |
1255 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1252 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1256 | "s=%d\n", urb, urb->status); | 1253 | "unlinked=%d\n", urb, urb->unlinked); |
1257 | up(&u132->scheduler_lock); | 1254 | up(&u132->scheduler_lock); |
1258 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1255 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1259 | return; | 1256 | return; |
1260 | } | 1257 | } |
1261 | } | 1258 | } |
@@ -1280,12 +1277,12 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, | |||
1280 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); | 1277 | u132_hcd_giveback_urb(u132, endp, urb, -EINTR); |
1281 | return; | 1278 | return; |
1282 | } else if (u132->going > 0) { | 1279 | } else if (u132->going > 0) { |
1283 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 1280 | dev_err(&u132->platform_dev->dev, "device is being removed " |
1284 | "%p status=%d\n", urb, urb->status); | 1281 | "urb=%p\n", urb); |
1285 | up(&u132->scheduler_lock); | 1282 | up(&u132->scheduler_lock); |
1286 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); | 1283 | u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); |
1287 | return; | 1284 | return; |
1288 | } else if (urb->status == -EINPROGRESS) { | 1285 | } else if (!urb->unlinked) { |
1289 | int retval; | 1286 | int retval; |
1290 | struct u132_ring *ring = endp->ring; | 1287 | struct u132_ring *ring = endp->ring; |
1291 | up(&u132->scheduler_lock); | 1288 | up(&u132->scheduler_lock); |
@@ -1297,10 +1294,10 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, | |||
1297 | u132_hcd_giveback_urb(u132, endp, urb, retval); | 1294 | u132_hcd_giveback_urb(u132, endp, urb, retval); |
1298 | return; | 1295 | return; |
1299 | } else { | 1296 | } else { |
1300 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" | 1297 | dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " |
1301 | "s=%d\n", urb, urb->status); | 1298 | "unlinked=%d\n", urb, urb->unlinked); |
1302 | up(&u132->scheduler_lock); | 1299 | up(&u132->scheduler_lock); |
1303 | u132_hcd_giveback_urb(u132, endp, urb, urb->status); | 1300 | u132_hcd_giveback_urb(u132, endp, urb, 0); |
1304 | return; | 1301 | return; |
1305 | } | 1302 | } |
1306 | } | 1303 | } |
@@ -1805,10 +1802,10 @@ static void u132_hcd_stop(struct usb_hcd *hcd) | |||
1805 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 1802 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
1806 | "ed\n", hcd); | 1803 | "ed\n", hcd); |
1807 | } else { | 1804 | } else { |
1808 | down(&u132->sw_lock); | 1805 | mutex_lock(&u132->sw_lock); |
1809 | msleep(100); | 1806 | msleep(100); |
1810 | u132_power(u132, 0); | 1807 | u132_power(u132, 0); |
1811 | up(&u132->sw_lock); | 1808 | mutex_unlock(&u132->sw_lock); |
1812 | } | 1809 | } |
1813 | } | 1810 | } |
1814 | 1811 | ||
@@ -1830,7 +1827,7 @@ static int u132_hcd_start(struct usb_hcd *hcd) | |||
1830 | (pdev->dev.platform_data))->vendor; | 1827 | (pdev->dev.platform_data))->vendor; |
1831 | u16 device = ((struct u132_platform_data *) | 1828 | u16 device = ((struct u132_platform_data *) |
1832 | (pdev->dev.platform_data))->device; | 1829 | (pdev->dev.platform_data))->device; |
1833 | down(&u132->sw_lock); | 1830 | mutex_lock(&u132->sw_lock); |
1834 | msleep(10); | 1831 | msleep(10); |
1835 | if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) { | 1832 | if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) { |
1836 | u132->flags = OHCI_QUIRK_AMD756; | 1833 | u132->flags = OHCI_QUIRK_AMD756; |
@@ -1845,7 +1842,7 @@ static int u132_hcd_start(struct usb_hcd *hcd) | |||
1845 | u132->going = 1; | 1842 | u132->going = 1; |
1846 | } | 1843 | } |
1847 | msleep(100); | 1844 | msleep(100); |
1848 | up(&u132->sw_lock); | 1845 | mutex_unlock(&u132->sw_lock); |
1849 | return retval; | 1846 | return retval; |
1850 | } else { | 1847 | } else { |
1851 | dev_err(&u132->platform_dev->dev, "platform_device missing\n"); | 1848 | dev_err(&u132->platform_dev->dev, "platform_device missing\n"); |
@@ -1865,32 +1862,44 @@ static int u132_hcd_reset(struct usb_hcd *hcd) | |||
1865 | return -ESHUTDOWN; | 1862 | return -ESHUTDOWN; |
1866 | } else { | 1863 | } else { |
1867 | int retval; | 1864 | int retval; |
1868 | down(&u132->sw_lock); | 1865 | mutex_lock(&u132->sw_lock); |
1869 | retval = u132_init(u132); | 1866 | retval = u132_init(u132); |
1870 | if (retval) { | 1867 | if (retval) { |
1871 | u132_disable(u132); | 1868 | u132_disable(u132); |
1872 | u132->going = 1; | 1869 | u132->going = 1; |
1873 | } | 1870 | } |
1874 | up(&u132->sw_lock); | 1871 | mutex_unlock(&u132->sw_lock); |
1875 | return retval; | 1872 | return retval; |
1876 | } | 1873 | } |
1877 | } | 1874 | } |
1878 | 1875 | ||
1879 | static int create_endpoint_and_queue_int(struct u132 *u132, | 1876 | static int create_endpoint_and_queue_int(struct u132 *u132, |
1880 | struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | 1877 | struct u132_udev *udev, struct urb *urb, |
1881 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | 1878 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, |
1882 | gfp_t mem_flags) | 1879 | gfp_t mem_flags) |
1883 | { | 1880 | { |
1884 | struct u132_ring *ring; | 1881 | struct u132_ring *ring; |
1885 | unsigned long irqs; | 1882 | unsigned long irqs; |
1886 | u8 endp_number = ++u132->num_endpoints; | 1883 | int rc; |
1887 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 1884 | u8 endp_number; |
1888 | kmalloc(sizeof(struct u132_endp), mem_flags); | 1885 | struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags); |
1886 | |||
1889 | if (!endp) { | 1887 | if (!endp) { |
1890 | return -ENOMEM; | 1888 | return -ENOMEM; |
1891 | } | 1889 | } |
1890 | |||
1891 | spin_lock_init(&endp->queue_lock.slock); | ||
1892 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
1893 | rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb); | ||
1894 | if (rc) { | ||
1895 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
1896 | kfree(endp); | ||
1897 | return rc; | ||
1898 | } | ||
1899 | |||
1900 | endp_number = ++u132->num_endpoints; | ||
1901 | urb->ep->hcpriv = u132->endp[endp_number - 1] = endp; | ||
1892 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); | 1902 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); |
1893 | spin_lock_init(&endp->queue_lock.slock); | ||
1894 | INIT_LIST_HEAD(&endp->urb_more); | 1903 | INIT_LIST_HEAD(&endp->urb_more); |
1895 | ring = endp->ring = &u132->ring[0]; | 1904 | ring = endp->ring = &u132->ring[0]; |
1896 | if (ring->curr_endp) { | 1905 | if (ring->curr_endp) { |
@@ -1906,7 +1915,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132, | |||
1906 | endp->delayed = 0; | 1915 | endp->delayed = 0; |
1907 | endp->endp_number = endp_number; | 1916 | endp->endp_number = endp_number; |
1908 | endp->u132 = u132; | 1917 | endp->u132 = u132; |
1909 | endp->hep = hep; | 1918 | endp->hep = urb->ep; |
1910 | endp->pipetype = usb_pipetype(urb->pipe); | 1919 | endp->pipetype = usb_pipetype(urb->pipe); |
1911 | u132_endp_init_kref(u132, endp); | 1920 | u132_endp_init_kref(u132, endp); |
1912 | if (usb_pipein(urb->pipe)) { | 1921 | if (usb_pipein(urb->pipe)) { |
@@ -1925,7 +1934,6 @@ static int create_endpoint_and_queue_int(struct u132 *u132, | |||
1925 | u132_udev_get_kref(u132, udev); | 1934 | u132_udev_get_kref(u132, udev); |
1926 | } | 1935 | } |
1927 | urb->hcpriv = u132; | 1936 | urb->hcpriv = u132; |
1928 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
1929 | endp->delayed = 1; | 1937 | endp->delayed = 1; |
1930 | endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); | 1938 | endp->jiffies = jiffies + msecs_to_jiffies(urb->interval); |
1931 | endp->udev_number = address; | 1939 | endp->udev_number = address; |
@@ -1940,8 +1948,8 @@ static int create_endpoint_and_queue_int(struct u132 *u132, | |||
1940 | return 0; | 1948 | return 0; |
1941 | } | 1949 | } |
1942 | 1950 | ||
1943 | static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | 1951 | static int queue_int_on_old_endpoint(struct u132 *u132, |
1944 | struct usb_host_endpoint *hep, struct urb *urb, | 1952 | struct u132_udev *udev, struct urb *urb, |
1945 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 1953 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, |
1946 | u8 usb_endp, u8 address) | 1954 | u8 usb_endp, u8 address) |
1947 | { | 1955 | { |
@@ -1965,21 +1973,33 @@ static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | |||
1965 | } | 1973 | } |
1966 | 1974 | ||
1967 | static int create_endpoint_and_queue_bulk(struct u132 *u132, | 1975 | static int create_endpoint_and_queue_bulk(struct u132 *u132, |
1968 | struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb, | 1976 | struct u132_udev *udev, struct urb *urb, |
1969 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, | 1977 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address, |
1970 | gfp_t mem_flags) | 1978 | gfp_t mem_flags) |
1971 | { | 1979 | { |
1972 | int ring_number; | 1980 | int ring_number; |
1973 | struct u132_ring *ring; | 1981 | struct u132_ring *ring; |
1974 | unsigned long irqs; | 1982 | unsigned long irqs; |
1975 | u8 endp_number = ++u132->num_endpoints; | 1983 | int rc; |
1976 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 1984 | u8 endp_number; |
1977 | kmalloc(sizeof(struct u132_endp), mem_flags); | 1985 | struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags); |
1986 | |||
1978 | if (!endp) { | 1987 | if (!endp) { |
1979 | return -ENOMEM; | 1988 | return -ENOMEM; |
1980 | } | 1989 | } |
1990 | |||
1991 | spin_lock_init(&endp->queue_lock.slock); | ||
1992 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
1993 | rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb); | ||
1994 | if (rc) { | ||
1995 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
1996 | kfree(endp); | ||
1997 | return rc; | ||
1998 | } | ||
1999 | |||
2000 | endp_number = ++u132->num_endpoints; | ||
2001 | urb->ep->hcpriv = u132->endp[endp_number - 1] = endp; | ||
1981 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); | 2002 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); |
1982 | spin_lock_init(&endp->queue_lock.slock); | ||
1983 | INIT_LIST_HEAD(&endp->urb_more); | 2003 | INIT_LIST_HEAD(&endp->urb_more); |
1984 | endp->dequeueing = 0; | 2004 | endp->dequeueing = 0; |
1985 | endp->edset_flush = 0; | 2005 | endp->edset_flush = 0; |
@@ -1987,7 +2007,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, | |||
1987 | endp->delayed = 0; | 2007 | endp->delayed = 0; |
1988 | endp->endp_number = endp_number; | 2008 | endp->endp_number = endp_number; |
1989 | endp->u132 = u132; | 2009 | endp->u132 = u132; |
1990 | endp->hep = hep; | 2010 | endp->hep = urb->ep; |
1991 | endp->pipetype = usb_pipetype(urb->pipe); | 2011 | endp->pipetype = usb_pipetype(urb->pipe); |
1992 | u132_endp_init_kref(u132, endp); | 2012 | u132_endp_init_kref(u132, endp); |
1993 | if (usb_pipein(urb->pipe)) { | 2013 | if (usb_pipein(urb->pipe)) { |
@@ -2016,7 +2036,6 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, | |||
2016 | } | 2036 | } |
2017 | ring->length += 1; | 2037 | ring->length += 1; |
2018 | urb->hcpriv = u132; | 2038 | urb->hcpriv = u132; |
2019 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2020 | endp->udev_number = address; | 2039 | endp->udev_number = address; |
2021 | endp->usb_addr = usb_addr; | 2040 | endp->usb_addr = usb_addr; |
2022 | endp->usb_endp = usb_endp; | 2041 | endp->usb_endp = usb_endp; |
@@ -2030,7 +2049,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, | |||
2030 | } | 2049 | } |
2031 | 2050 | ||
2032 | static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | 2051 | static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, |
2033 | struct usb_host_endpoint *hep, struct urb *urb, | 2052 | struct urb *urb, |
2034 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 2053 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, |
2035 | u8 usb_endp, u8 address) | 2054 | u8 usb_endp, u8 address) |
2036 | { | 2055 | { |
@@ -2052,19 +2071,32 @@ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev, | |||
2052 | } | 2071 | } |
2053 | 2072 | ||
2054 | static int create_endpoint_and_queue_control(struct u132 *u132, | 2073 | static int create_endpoint_and_queue_control(struct u132 *u132, |
2055 | struct usb_host_endpoint *hep, struct urb *urb, | 2074 | struct urb *urb, |
2056 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, | 2075 | struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, |
2057 | gfp_t mem_flags) | 2076 | gfp_t mem_flags) |
2058 | { | 2077 | { |
2059 | struct u132_ring *ring; | 2078 | struct u132_ring *ring; |
2060 | u8 endp_number = ++u132->num_endpoints; | 2079 | unsigned long irqs; |
2061 | struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] = | 2080 | int rc; |
2062 | kmalloc(sizeof(struct u132_endp), mem_flags); | 2081 | u8 endp_number; |
2082 | struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags); | ||
2083 | |||
2063 | if (!endp) { | 2084 | if (!endp) { |
2064 | return -ENOMEM; | 2085 | return -ENOMEM; |
2065 | } | 2086 | } |
2087 | |||
2088 | spin_lock_init(&endp->queue_lock.slock); | ||
2089 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2090 | rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb); | ||
2091 | if (rc) { | ||
2092 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2093 | kfree(endp); | ||
2094 | return rc; | ||
2095 | } | ||
2096 | |||
2097 | endp_number = ++u132->num_endpoints; | ||
2098 | urb->ep->hcpriv = u132->endp[endp_number - 1] = endp; | ||
2066 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); | 2099 | INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); |
2067 | spin_lock_init(&endp->queue_lock.slock); | ||
2068 | INIT_LIST_HEAD(&endp->urb_more); | 2100 | INIT_LIST_HEAD(&endp->urb_more); |
2069 | ring = endp->ring = &u132->ring[0]; | 2101 | ring = endp->ring = &u132->ring[0]; |
2070 | if (ring->curr_endp) { | 2102 | if (ring->curr_endp) { |
@@ -2080,11 +2112,10 @@ static int create_endpoint_and_queue_control(struct u132 *u132, | |||
2080 | endp->delayed = 0; | 2112 | endp->delayed = 0; |
2081 | endp->endp_number = endp_number; | 2113 | endp->endp_number = endp_number; |
2082 | endp->u132 = u132; | 2114 | endp->u132 = u132; |
2083 | endp->hep = hep; | 2115 | endp->hep = urb->ep; |
2084 | u132_endp_init_kref(u132, endp); | 2116 | u132_endp_init_kref(u132, endp); |
2085 | u132_endp_get_kref(u132, endp); | 2117 | u132_endp_get_kref(u132, endp); |
2086 | if (usb_addr == 0) { | 2118 | if (usb_addr == 0) { |
2087 | unsigned long irqs; | ||
2088 | u8 address = u132->addr[usb_addr].address; | 2119 | u8 address = u132->addr[usb_addr].address; |
2089 | struct u132_udev *udev = &u132->udev[address]; | 2120 | struct u132_udev *udev = &u132->udev[address]; |
2090 | endp->udev_number = address; | 2121 | endp->udev_number = address; |
@@ -2098,7 +2129,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132, | |||
2098 | udev->endp_number_in[usb_endp] = endp_number; | 2129 | udev->endp_number_in[usb_endp] = endp_number; |
2099 | udev->endp_number_out[usb_endp] = endp_number; | 2130 | udev->endp_number_out[usb_endp] = endp_number; |
2100 | urb->hcpriv = u132; | 2131 | urb->hcpriv = u132; |
2101 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2102 | endp->queue_size = 1; | 2132 | endp->queue_size = 1; |
2103 | endp->queue_last = 0; | 2133 | endp->queue_last = 0; |
2104 | endp->queue_next = 0; | 2134 | endp->queue_next = 0; |
@@ -2107,7 +2137,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132, | |||
2107 | u132_endp_queue_work(u132, endp, 0); | 2137 | u132_endp_queue_work(u132, endp, 0); |
2108 | return 0; | 2138 | return 0; |
2109 | } else { /*(usb_addr > 0) */ | 2139 | } else { /*(usb_addr > 0) */ |
2110 | unsigned long irqs; | ||
2111 | u8 address = u132->addr[usb_addr].address; | 2140 | u8 address = u132->addr[usb_addr].address; |
2112 | struct u132_udev *udev = &u132->udev[address]; | 2141 | struct u132_udev *udev = &u132->udev[address]; |
2113 | endp->udev_number = address; | 2142 | endp->udev_number = address; |
@@ -2121,7 +2150,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132, | |||
2121 | udev->endp_number_in[usb_endp] = endp_number; | 2150 | udev->endp_number_in[usb_endp] = endp_number; |
2122 | udev->endp_number_out[usb_endp] = endp_number; | 2151 | udev->endp_number_out[usb_endp] = endp_number; |
2123 | urb->hcpriv = u132; | 2152 | urb->hcpriv = u132; |
2124 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | ||
2125 | endp->queue_size = 1; | 2153 | endp->queue_size = 1; |
2126 | endp->queue_last = 0; | 2154 | endp->queue_last = 0; |
2127 | endp->queue_next = 0; | 2155 | endp->queue_next = 0; |
@@ -2133,7 +2161,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132, | |||
2133 | } | 2161 | } |
2134 | 2162 | ||
2135 | static int queue_control_on_old_endpoint(struct u132 *u132, | 2163 | static int queue_control_on_old_endpoint(struct u132 *u132, |
2136 | struct usb_host_endpoint *hep, struct urb *urb, | 2164 | struct urb *urb, |
2137 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, | 2165 | struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr, |
2138 | u8 usb_endp) | 2166 | u8 usb_endp) |
2139 | { | 2167 | { |
@@ -2233,8 +2261,8 @@ static int queue_control_on_old_endpoint(struct u132 *u132, | |||
2233 | } | 2261 | } |
2234 | } | 2262 | } |
2235 | 2263 | ||
2236 | static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | 2264 | static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, |
2237 | struct urb *urb, gfp_t mem_flags) | 2265 | gfp_t mem_flags) |
2238 | { | 2266 | { |
2239 | struct u132 *u132 = hcd_to_u132(hcd); | 2267 | struct u132 *u132 = hcd_to_u132(hcd); |
2240 | if (irqs_disabled()) { | 2268 | if (irqs_disabled()) { |
@@ -2249,8 +2277,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2249 | , u132->going); | 2277 | , u132->going); |
2250 | return -ENODEV; | 2278 | return -ENODEV; |
2251 | } else if (u132->going > 0) { | 2279 | } else if (u132->going > 0) { |
2252 | dev_err(&u132->platform_dev->dev, "device is being removed urb=" | 2280 | dev_err(&u132->platform_dev->dev, "device is being removed " |
2253 | "%p status=%d\n", urb, urb->status); | 2281 | "urb=%p\n", urb); |
2254 | return -ESHUTDOWN; | 2282 | return -ESHUTDOWN; |
2255 | } else { | 2283 | } else { |
2256 | u8 usb_addr = usb_pipedevice(urb->pipe); | 2284 | u8 usb_addr = usb_pipedevice(urb->pipe); |
@@ -2259,16 +2287,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2259 | if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { | 2287 | if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { |
2260 | u8 address = u132->addr[usb_addr].address; | 2288 | u8 address = u132->addr[usb_addr].address; |
2261 | struct u132_udev *udev = &u132->udev[address]; | 2289 | struct u132_udev *udev = &u132->udev[address]; |
2262 | struct u132_endp *endp = hep->hcpriv; | 2290 | struct u132_endp *endp = urb->ep->hcpriv; |
2263 | urb->actual_length = 0; | 2291 | urb->actual_length = 0; |
2264 | if (endp) { | 2292 | if (endp) { |
2265 | unsigned long irqs; | 2293 | unsigned long irqs; |
2266 | int retval; | 2294 | int retval; |
2267 | spin_lock_irqsave(&endp->queue_lock.slock, | 2295 | spin_lock_irqsave(&endp->queue_lock.slock, |
2268 | irqs); | 2296 | irqs); |
2269 | retval = queue_int_on_old_endpoint(u132, udev, | 2297 | retval = usb_hcd_link_urb_to_ep(hcd, urb); |
2270 | hep, urb, usb_dev, endp, usb_addr, | 2298 | if (retval == 0) { |
2271 | usb_endp, address); | 2299 | retval = queue_int_on_old_endpoint( |
2300 | u132, udev, urb, | ||
2301 | usb_dev, endp, | ||
2302 | usb_addr, usb_endp, | ||
2303 | address); | ||
2304 | if (retval) | ||
2305 | usb_hcd_unlink_urb_from_ep( | ||
2306 | hcd, urb); | ||
2307 | } | ||
2272 | spin_unlock_irqrestore(&endp->queue_lock.slock, | 2308 | spin_unlock_irqrestore(&endp->queue_lock.slock, |
2273 | irqs); | 2309 | irqs); |
2274 | if (retval) { | 2310 | if (retval) { |
@@ -2283,8 +2319,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2283 | return -EINVAL; | 2319 | return -EINVAL; |
2284 | } else { /*(endp == NULL) */ | 2320 | } else { /*(endp == NULL) */ |
2285 | return create_endpoint_and_queue_int(u132, udev, | 2321 | return create_endpoint_and_queue_int(u132, udev, |
2286 | hep, urb, usb_dev, usb_addr, usb_endp, | 2322 | urb, usb_dev, usb_addr, |
2287 | address, mem_flags); | 2323 | usb_endp, address, mem_flags); |
2288 | } | 2324 | } |
2289 | } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { | 2325 | } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { |
2290 | dev_err(&u132->platform_dev->dev, "the hardware does no" | 2326 | dev_err(&u132->platform_dev->dev, "the hardware does no" |
@@ -2293,16 +2329,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2293 | } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { | 2329 | } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { |
2294 | u8 address = u132->addr[usb_addr].address; | 2330 | u8 address = u132->addr[usb_addr].address; |
2295 | struct u132_udev *udev = &u132->udev[address]; | 2331 | struct u132_udev *udev = &u132->udev[address]; |
2296 | struct u132_endp *endp = hep->hcpriv; | 2332 | struct u132_endp *endp = urb->ep->hcpriv; |
2297 | urb->actual_length = 0; | 2333 | urb->actual_length = 0; |
2298 | if (endp) { | 2334 | if (endp) { |
2299 | unsigned long irqs; | 2335 | unsigned long irqs; |
2300 | int retval; | 2336 | int retval; |
2301 | spin_lock_irqsave(&endp->queue_lock.slock, | 2337 | spin_lock_irqsave(&endp->queue_lock.slock, |
2302 | irqs); | 2338 | irqs); |
2303 | retval = queue_bulk_on_old_endpoint(u132, udev, | 2339 | retval = usb_hcd_link_urb_to_ep(hcd, urb); |
2304 | hep, urb, usb_dev, endp, usb_addr, | 2340 | if (retval == 0) { |
2305 | usb_endp, address); | 2341 | retval = queue_bulk_on_old_endpoint( |
2342 | u132, udev, urb, | ||
2343 | usb_dev, endp, | ||
2344 | usb_addr, usb_endp, | ||
2345 | address); | ||
2346 | if (retval) | ||
2347 | usb_hcd_unlink_urb_from_ep( | ||
2348 | hcd, urb); | ||
2349 | } | ||
2306 | spin_unlock_irqrestore(&endp->queue_lock.slock, | 2350 | spin_unlock_irqrestore(&endp->queue_lock.slock, |
2307 | irqs); | 2351 | irqs); |
2308 | if (retval) { | 2352 | if (retval) { |
@@ -2315,10 +2359,10 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2315 | return -EINVAL; | 2359 | return -EINVAL; |
2316 | } else | 2360 | } else |
2317 | return create_endpoint_and_queue_bulk(u132, | 2361 | return create_endpoint_and_queue_bulk(u132, |
2318 | udev, hep, urb, usb_dev, usb_addr, | 2362 | udev, urb, usb_dev, usb_addr, |
2319 | usb_endp, address, mem_flags); | 2363 | usb_endp, address, mem_flags); |
2320 | } else { | 2364 | } else { |
2321 | struct u132_endp *endp = hep->hcpriv; | 2365 | struct u132_endp *endp = urb->ep->hcpriv; |
2322 | u16 urb_size = 8; | 2366 | u16 urb_size = 8; |
2323 | u8 *b = urb->setup_packet; | 2367 | u8 *b = urb->setup_packet; |
2324 | int i = 0; | 2368 | int i = 0; |
@@ -2341,9 +2385,16 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2341 | int retval; | 2385 | int retval; |
2342 | spin_lock_irqsave(&endp->queue_lock.slock, | 2386 | spin_lock_irqsave(&endp->queue_lock.slock, |
2343 | irqs); | 2387 | irqs); |
2344 | retval = queue_control_on_old_endpoint(u132, | 2388 | retval = usb_hcd_link_urb_to_ep(hcd, urb); |
2345 | hep, urb, usb_dev, endp, usb_addr, | 2389 | if (retval == 0) { |
2346 | usb_endp); | 2390 | retval = queue_control_on_old_endpoint( |
2391 | u132, urb, usb_dev, | ||
2392 | endp, usb_addr, | ||
2393 | usb_endp); | ||
2394 | if (retval) | ||
2395 | usb_hcd_unlink_urb_from_ep( | ||
2396 | hcd, urb); | ||
2397 | } | ||
2347 | spin_unlock_irqrestore(&endp->queue_lock.slock, | 2398 | spin_unlock_irqrestore(&endp->queue_lock.slock, |
2348 | irqs); | 2399 | irqs); |
2349 | if (retval) { | 2400 | if (retval) { |
@@ -2356,7 +2407,7 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep, | |||
2356 | return -EINVAL; | 2407 | return -EINVAL; |
2357 | } else | 2408 | } else |
2358 | return create_endpoint_and_queue_control(u132, | 2409 | return create_endpoint_and_queue_control(u132, |
2359 | hep, urb, usb_dev, usb_addr, usb_endp, | 2410 | urb, usb_dev, usb_addr, usb_endp, |
2360 | mem_flags); | 2411 | mem_flags); |
2361 | } | 2412 | } |
2362 | } | 2413 | } |
@@ -2375,8 +2426,7 @@ static int dequeue_from_overflow_chain(struct u132 *u132, | |||
2375 | list_del(scan); | 2426 | list_del(scan); |
2376 | endp->queue_size -= 1; | 2427 | endp->queue_size -= 1; |
2377 | urb->error_count = 0; | 2428 | urb->error_count = 0; |
2378 | urb->hcpriv = NULL; | 2429 | usb_hcd_giveback_urb(hcd, urb, 0); |
2379 | usb_hcd_giveback_urb(hcd, urb); | ||
2380 | return 0; | 2430 | return 0; |
2381 | } else | 2431 | } else |
2382 | continue; | 2432 | continue; |
@@ -2391,10 +2441,17 @@ static int dequeue_from_overflow_chain(struct u132 *u132, | |||
2391 | } | 2441 | } |
2392 | 2442 | ||
2393 | static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | 2443 | static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, |
2394 | struct urb *urb) | 2444 | struct urb *urb, int status) |
2395 | { | 2445 | { |
2396 | unsigned long irqs; | 2446 | unsigned long irqs; |
2447 | int rc; | ||
2448 | |||
2397 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); | 2449 | spin_lock_irqsave(&endp->queue_lock.slock, irqs); |
2450 | rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status); | ||
2451 | if (rc) { | ||
2452 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | ||
2453 | return rc; | ||
2454 | } | ||
2398 | if (endp->queue_size == 0) { | 2455 | if (endp->queue_size == 0) { |
2399 | dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]" | 2456 | dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]" |
2400 | "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb, | 2457 | "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb, |
@@ -2410,11 +2467,10 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | |||
2410 | endp->edset_flush = 1; | 2467 | endp->edset_flush = 1; |
2411 | u132_endp_queue_work(u132, endp, 0); | 2468 | u132_endp_queue_work(u132, endp, 0); |
2412 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 2469 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); |
2413 | urb->hcpriv = NULL; | ||
2414 | return 0; | 2470 | return 0; |
2415 | } else { | 2471 | } else { |
2416 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 2472 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); |
2417 | u132_hcd_abandon_urb(u132, endp, urb, urb->status); | 2473 | u132_hcd_abandon_urb(u132, endp, urb, status); |
2418 | return 0; | 2474 | return 0; |
2419 | } | 2475 | } |
2420 | } else { | 2476 | } else { |
@@ -2439,6 +2495,8 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | |||
2439 | } | 2495 | } |
2440 | if (urb_slot) { | 2496 | if (urb_slot) { |
2441 | struct usb_hcd *hcd = u132_to_hcd(u132); | 2497 | struct usb_hcd *hcd = u132_to_hcd(u132); |
2498 | |||
2499 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
2442 | endp->queue_size -= 1; | 2500 | endp->queue_size -= 1; |
2443 | if (list_empty(&endp->urb_more)) { | 2501 | if (list_empty(&endp->urb_more)) { |
2444 | spin_unlock_irqrestore(&endp->queue_lock.slock, | 2502 | spin_unlock_irqrestore(&endp->queue_lock.slock, |
@@ -2453,8 +2511,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | |||
2453 | irqs); | 2511 | irqs); |
2454 | kfree(urbq); | 2512 | kfree(urbq); |
2455 | } urb->error_count = 0; | 2513 | } urb->error_count = 0; |
2456 | urb->hcpriv = NULL; | 2514 | usb_hcd_giveback_urb(hcd, urb, status); |
2457 | usb_hcd_giveback_urb(hcd, urb); | ||
2458 | return 0; | 2515 | return 0; |
2459 | } else if (list_empty(&endp->urb_more)) { | 2516 | } else if (list_empty(&endp->urb_more)) { |
2460 | dev_err(&u132->platform_dev->dev, "urb=%p not found in " | 2517 | dev_err(&u132->platform_dev->dev, "urb=%p not found in " |
@@ -2468,7 +2525,10 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | |||
2468 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 2525 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); |
2469 | return -EINVAL; | 2526 | return -EINVAL; |
2470 | } else { | 2527 | } else { |
2471 | int retval = dequeue_from_overflow_chain(u132, endp, | 2528 | int retval; |
2529 | |||
2530 | usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb); | ||
2531 | retval = dequeue_from_overflow_chain(u132, endp, | ||
2472 | urb); | 2532 | urb); |
2473 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); | 2533 | spin_unlock_irqrestore(&endp->queue_lock.slock, irqs); |
2474 | return retval; | 2534 | return retval; |
@@ -2476,7 +2536,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp, | |||
2476 | } | 2536 | } |
2477 | } | 2537 | } |
2478 | 2538 | ||
2479 | static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 2539 | static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
2480 | { | 2540 | { |
2481 | struct u132 *u132 = hcd_to_u132(hcd); | 2541 | struct u132 *u132 = hcd_to_u132(hcd); |
2482 | if (u132->going > 2) { | 2542 | if (u132->going > 2) { |
@@ -2491,11 +2551,11 @@ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
2491 | if (usb_pipein(urb->pipe)) { | 2551 | if (usb_pipein(urb->pipe)) { |
2492 | u8 endp_number = udev->endp_number_in[usb_endp]; | 2552 | u8 endp_number = udev->endp_number_in[usb_endp]; |
2493 | struct u132_endp *endp = u132->endp[endp_number - 1]; | 2553 | struct u132_endp *endp = u132->endp[endp_number - 1]; |
2494 | return u132_endp_urb_dequeue(u132, endp, urb); | 2554 | return u132_endp_urb_dequeue(u132, endp, urb, status); |
2495 | } else { | 2555 | } else { |
2496 | u8 endp_number = udev->endp_number_out[usb_endp]; | 2556 | u8 endp_number = udev->endp_number_out[usb_endp]; |
2497 | struct u132_endp *endp = u132->endp[endp_number - 1]; | 2557 | struct u132_endp *endp = u132->endp[endp_number - 1]; |
2498 | return u132_endp_urb_dequeue(u132, endp, urb); | 2558 | return u132_endp_urb_dequeue(u132, endp, urb, status); |
2499 | } | 2559 | } |
2500 | } | 2560 | } |
2501 | } | 2561 | } |
@@ -2805,7 +2865,7 @@ static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2805 | return -ESHUTDOWN; | 2865 | return -ESHUTDOWN; |
2806 | } else { | 2866 | } else { |
2807 | int retval = 0; | 2867 | int retval = 0; |
2808 | down(&u132->sw_lock); | 2868 | mutex_lock(&u132->sw_lock); |
2809 | switch (typeReq) { | 2869 | switch (typeReq) { |
2810 | case ClearHubFeature: | 2870 | case ClearHubFeature: |
2811 | switch (wValue) { | 2871 | switch (wValue) { |
@@ -2868,7 +2928,7 @@ static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
2868 | stall:retval = -EPIPE; | 2928 | stall:retval = -EPIPE; |
2869 | break; | 2929 | break; |
2870 | } | 2930 | } |
2871 | up(&u132->sw_lock); | 2931 | mutex_unlock(&u132->sw_lock); |
2872 | return retval; | 2932 | return retval; |
2873 | } | 2933 | } |
2874 | } | 2934 | } |
@@ -3004,7 +3064,7 @@ static int __devexit u132_remove(struct platform_device *pdev) | |||
3004 | dev_err(&u132->platform_dev->dev, "removing device u132" | 3064 | dev_err(&u132->platform_dev->dev, "removing device u132" |
3005 | ".%d\n", u132->sequence_num); | 3065 | ".%d\n", u132->sequence_num); |
3006 | msleep(100); | 3066 | msleep(100); |
3007 | down(&u132->sw_lock); | 3067 | mutex_lock(&u132->sw_lock); |
3008 | u132_monitor_cancel_work(u132); | 3068 | u132_monitor_cancel_work(u132); |
3009 | while (rings-- > 0) { | 3069 | while (rings-- > 0) { |
3010 | struct u132_ring *ring = &u132->ring[rings]; | 3070 | struct u132_ring *ring = &u132->ring[rings]; |
@@ -3017,7 +3077,7 @@ static int __devexit u132_remove(struct platform_device *pdev) | |||
3017 | u132->going += 1; | 3077 | u132->going += 1; |
3018 | printk(KERN_INFO "removing device u132.%d\n", | 3078 | printk(KERN_INFO "removing device u132.%d\n", |
3019 | u132->sequence_num); | 3079 | u132->sequence_num); |
3020 | up(&u132->sw_lock); | 3080 | mutex_unlock(&u132->sw_lock); |
3021 | usb_remove_hcd(hcd); | 3081 | usb_remove_hcd(hcd); |
3022 | u132_u132_put_kref(u132); | 3082 | u132_u132_put_kref(u132); |
3023 | return 0; | 3083 | return 0; |
@@ -3037,7 +3097,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3037 | u132->platform_dev = pdev; | 3097 | u132->platform_dev = pdev; |
3038 | u132->power = 0; | 3098 | u132->power = 0; |
3039 | u132->reset = 0; | 3099 | u132->reset = 0; |
3040 | init_MUTEX(&u132->sw_lock); | 3100 | mutex_init(&u132->sw_lock); |
3041 | init_MUTEX(&u132->scheduler_lock); | 3101 | init_MUTEX(&u132->scheduler_lock); |
3042 | while (rings-- > 0) { | 3102 | while (rings-- > 0) { |
3043 | struct u132_ring *ring = &u132->ring[rings]; | 3103 | struct u132_ring *ring = &u132->ring[rings]; |
@@ -3047,7 +3107,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3047 | ring->curr_endp = NULL; | 3107 | ring->curr_endp = NULL; |
3048 | INIT_DELAYED_WORK(&ring->scheduler, | 3108 | INIT_DELAYED_WORK(&ring->scheduler, |
3049 | u132_hcd_ring_work_scheduler); | 3109 | u132_hcd_ring_work_scheduler); |
3050 | } down(&u132->sw_lock); | 3110 | } mutex_lock(&u132->sw_lock); |
3051 | INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work); | 3111 | INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work); |
3052 | while (ports-- > 0) { | 3112 | while (ports-- > 0) { |
3053 | struct u132_port *port = &u132->port[ports]; | 3113 | struct u132_port *port = &u132->port[ports]; |
@@ -3077,7 +3137,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3077 | while (endps-- > 0) { | 3137 | while (endps-- > 0) { |
3078 | u132->endp[endps] = NULL; | 3138 | u132->endp[endps] = NULL; |
3079 | } | 3139 | } |
3080 | up(&u132->sw_lock); | 3140 | mutex_unlock(&u132->sw_lock); |
3081 | return; | 3141 | return; |
3082 | } | 3142 | } |
3083 | 3143 | ||
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 1497371583b9..20cc58b97807 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -120,8 +120,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) | |||
120 | out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); | 120 | out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); |
121 | out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); | 121 | out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); |
122 | 122 | ||
123 | if (urbp->urb->status != -EINPROGRESS) | 123 | if (urbp->urb->unlinked) |
124 | out += sprintf(out, " Status=%d", urbp->urb->status); | 124 | out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); |
125 | out += sprintf(out, "\n"); | 125 | out += sprintf(out, "\n"); |
126 | 126 | ||
127 | i = nactive = ninactive = 0; | 127 | i = nactive = ninactive = 0; |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 1b3d23406ac4..340d6ed3e6e9 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -146,7 +146,6 @@ struct uhci_qh { | |||
146 | short phase; /* Between 0 and period-1 */ | 146 | short phase; /* Between 0 and period-1 */ |
147 | short load; /* Periodic time requirement, in us */ | 147 | short load; /* Periodic time requirement, in us */ |
148 | unsigned int iso_frame; /* Frame # for iso_packet_desc */ | 148 | unsigned int iso_frame; /* Frame # for iso_packet_desc */ |
149 | int iso_status; /* Status for Isochronous URBs */ | ||
150 | 149 | ||
151 | int state; /* QH_STATE_xxx; see above */ | 150 | int state; /* QH_STATE_xxx; see above */ |
152 | int type; /* Queue type (control, bulk, etc) */ | 151 | int type; /* Queue type (control, bulk, etc) */ |
@@ -457,21 +456,6 @@ struct urb_priv { | |||
457 | }; | 456 | }; |
458 | 457 | ||
459 | 458 | ||
460 | /* | ||
461 | * Locking in uhci.c | ||
462 | * | ||
463 | * Almost everything relating to the hardware schedule and processing | ||
464 | * of URBs is protected by uhci->lock. urb->status is protected by | ||
465 | * urb->lock; that's the one exception. | ||
466 | * | ||
467 | * To prevent deadlocks, never lock uhci->lock while holding urb->lock. | ||
468 | * The safe order of locking is: | ||
469 | * | ||
470 | * #1 uhci->lock | ||
471 | * #2 urb->lock | ||
472 | */ | ||
473 | |||
474 | |||
475 | /* Some special IDs */ | 459 | /* Some special IDs */ |
476 | 460 | ||
477 | #define PCI_VENDOR_ID_GENESYS 0x17a0 | 461 | #define PCI_VENDOR_ID_GENESYS 0x17a0 |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 3bb908ca38e9..e5d60d5b105a 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -757,7 +757,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci, | |||
757 | uhci_free_td(uhci, td); | 757 | uhci_free_td(uhci, td); |
758 | } | 758 | } |
759 | 759 | ||
760 | urbp->urb->hcpriv = NULL; | ||
761 | kmem_cache_free(uhci_up_cachep, urbp); | 760 | kmem_cache_free(uhci_up_cachep, urbp); |
762 | } | 761 | } |
763 | 762 | ||
@@ -1324,7 +1323,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1324 | if (list_empty(&qh->queue)) { | 1323 | if (list_empty(&qh->queue)) { |
1325 | qh->iso_packet_desc = &urb->iso_frame_desc[0]; | 1324 | qh->iso_packet_desc = &urb->iso_frame_desc[0]; |
1326 | qh->iso_frame = urb->start_frame; | 1325 | qh->iso_frame = urb->start_frame; |
1327 | qh->iso_status = 0; | ||
1328 | } | 1326 | } |
1329 | 1327 | ||
1330 | qh->skel = SKEL_ISO; | 1328 | qh->skel = SKEL_ISO; |
@@ -1361,22 +1359,18 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
1361 | qh->iso_packet_desc->actual_length = actlength; | 1359 | qh->iso_packet_desc->actual_length = actlength; |
1362 | qh->iso_packet_desc->status = status; | 1360 | qh->iso_packet_desc->status = status; |
1363 | } | 1361 | } |
1364 | 1362 | if (status) | |
1365 | if (status) { | ||
1366 | urb->error_count++; | 1363 | urb->error_count++; |
1367 | qh->iso_status = status; | ||
1368 | } | ||
1369 | 1364 | ||
1370 | uhci_remove_td_from_urbp(td); | 1365 | uhci_remove_td_from_urbp(td); |
1371 | uhci_free_td(uhci, td); | 1366 | uhci_free_td(uhci, td); |
1372 | qh->iso_frame += qh->period; | 1367 | qh->iso_frame += qh->period; |
1373 | ++qh->iso_packet_desc; | 1368 | ++qh->iso_packet_desc; |
1374 | } | 1369 | } |
1375 | return qh->iso_status; | 1370 | return 0; |
1376 | } | 1371 | } |
1377 | 1372 | ||
1378 | static int uhci_urb_enqueue(struct usb_hcd *hcd, | 1373 | static int uhci_urb_enqueue(struct usb_hcd *hcd, |
1379 | struct usb_host_endpoint *hep, | ||
1380 | struct urb *urb, gfp_t mem_flags) | 1374 | struct urb *urb, gfp_t mem_flags) |
1381 | { | 1375 | { |
1382 | int ret; | 1376 | int ret; |
@@ -1387,19 +1381,19 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1387 | 1381 | ||
1388 | spin_lock_irqsave(&uhci->lock, flags); | 1382 | spin_lock_irqsave(&uhci->lock, flags); |
1389 | 1383 | ||
1390 | ret = urb->status; | 1384 | ret = usb_hcd_link_urb_to_ep(hcd, urb); |
1391 | if (ret != -EINPROGRESS) /* URB already unlinked! */ | 1385 | if (ret) |
1392 | goto done; | 1386 | goto done_not_linked; |
1393 | 1387 | ||
1394 | ret = -ENOMEM; | 1388 | ret = -ENOMEM; |
1395 | urbp = uhci_alloc_urb_priv(uhci, urb); | 1389 | urbp = uhci_alloc_urb_priv(uhci, urb); |
1396 | if (!urbp) | 1390 | if (!urbp) |
1397 | goto done; | 1391 | goto done; |
1398 | 1392 | ||
1399 | if (hep->hcpriv) | 1393 | if (urb->ep->hcpriv) |
1400 | qh = (struct uhci_qh *) hep->hcpriv; | 1394 | qh = urb->ep->hcpriv; |
1401 | else { | 1395 | else { |
1402 | qh = uhci_alloc_qh(uhci, urb->dev, hep); | 1396 | qh = uhci_alloc_qh(uhci, urb->dev, urb->ep); |
1403 | if (!qh) | 1397 | if (!qh) |
1404 | goto err_no_qh; | 1398 | goto err_no_qh; |
1405 | } | 1399 | } |
@@ -1440,27 +1434,29 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1440 | err_submit_failed: | 1434 | err_submit_failed: |
1441 | if (qh->state == QH_STATE_IDLE) | 1435 | if (qh->state == QH_STATE_IDLE) |
1442 | uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ | 1436 | uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ |
1443 | |||
1444 | err_no_qh: | 1437 | err_no_qh: |
1445 | uhci_free_urb_priv(uhci, urbp); | 1438 | uhci_free_urb_priv(uhci, urbp); |
1446 | |||
1447 | done: | 1439 | done: |
1440 | if (ret) | ||
1441 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
1442 | done_not_linked: | ||
1448 | spin_unlock_irqrestore(&uhci->lock, flags); | 1443 | spin_unlock_irqrestore(&uhci->lock, flags); |
1449 | return ret; | 1444 | return ret; |
1450 | } | 1445 | } |
1451 | 1446 | ||
1452 | static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 1447 | static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
1453 | { | 1448 | { |
1454 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 1449 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
1455 | unsigned long flags; | 1450 | unsigned long flags; |
1456 | struct urb_priv *urbp; | ||
1457 | struct uhci_qh *qh; | 1451 | struct uhci_qh *qh; |
1452 | int rc; | ||
1458 | 1453 | ||
1459 | spin_lock_irqsave(&uhci->lock, flags); | 1454 | spin_lock_irqsave(&uhci->lock, flags); |
1460 | urbp = urb->hcpriv; | 1455 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); |
1461 | if (!urbp) /* URB was never linked! */ | 1456 | if (rc) |
1462 | goto done; | 1457 | goto done; |
1463 | qh = urbp->qh; | 1458 | |
1459 | qh = ((struct urb_priv *) urb->hcpriv)->qh; | ||
1464 | 1460 | ||
1465 | /* Remove Isochronous TDs from the frame list ASAP */ | 1461 | /* Remove Isochronous TDs from the frame list ASAP */ |
1466 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { | 1462 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { |
@@ -1477,14 +1473,14 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
1477 | 1473 | ||
1478 | done: | 1474 | done: |
1479 | spin_unlock_irqrestore(&uhci->lock, flags); | 1475 | spin_unlock_irqrestore(&uhci->lock, flags); |
1480 | return 0; | 1476 | return rc; |
1481 | } | 1477 | } |
1482 | 1478 | ||
1483 | /* | 1479 | /* |
1484 | * Finish unlinking an URB and give it back | 1480 | * Finish unlinking an URB and give it back |
1485 | */ | 1481 | */ |
1486 | static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh, | 1482 | static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh, |
1487 | struct urb *urb) | 1483 | struct urb *urb, int status) |
1488 | __releases(uhci->lock) | 1484 | __releases(uhci->lock) |
1489 | __acquires(uhci->lock) | 1485 | __acquires(uhci->lock) |
1490 | { | 1486 | { |
@@ -1497,13 +1493,6 @@ __acquires(uhci->lock) | |||
1497 | * unlinked first. Regardless, don't confuse people with a | 1493 | * unlinked first. Regardless, don't confuse people with a |
1498 | * negative length. */ | 1494 | * negative length. */ |
1499 | urb->actual_length = max(urb->actual_length, 0); | 1495 | urb->actual_length = max(urb->actual_length, 0); |
1500 | |||
1501 | /* Report erroneous short transfers */ | ||
1502 | if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && | ||
1503 | urb->actual_length < | ||
1504 | urb->transfer_buffer_length && | ||
1505 | urb->status == 0)) | ||
1506 | urb->status = -EREMOTEIO; | ||
1507 | } | 1496 | } |
1508 | 1497 | ||
1509 | /* When giving back the first URB in an Isochronous queue, | 1498 | /* When giving back the first URB in an Isochronous queue, |
@@ -1516,7 +1505,6 @@ __acquires(uhci->lock) | |||
1516 | 1505 | ||
1517 | qh->iso_packet_desc = &nurb->iso_frame_desc[0]; | 1506 | qh->iso_packet_desc = &nurb->iso_frame_desc[0]; |
1518 | qh->iso_frame = nurb->start_frame; | 1507 | qh->iso_frame = nurb->start_frame; |
1519 | qh->iso_status = 0; | ||
1520 | } | 1508 | } |
1521 | 1509 | ||
1522 | /* Take the URB off the QH's queue. If the queue is now empty, | 1510 | /* Take the URB off the QH's queue. If the queue is now empty, |
@@ -1529,9 +1517,10 @@ __acquires(uhci->lock) | |||
1529 | } | 1517 | } |
1530 | 1518 | ||
1531 | uhci_free_urb_priv(uhci, urbp); | 1519 | uhci_free_urb_priv(uhci, urbp); |
1520 | usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb); | ||
1532 | 1521 | ||
1533 | spin_unlock(&uhci->lock); | 1522 | spin_unlock(&uhci->lock); |
1534 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); | 1523 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, status); |
1535 | spin_lock(&uhci->lock); | 1524 | spin_lock(&uhci->lock); |
1536 | 1525 | ||
1537 | /* If the queue is now empty, we can unlink the QH and give up its | 1526 | /* If the queue is now empty, we can unlink the QH and give up its |
@@ -1567,24 +1556,17 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
1567 | if (status == -EINPROGRESS) | 1556 | if (status == -EINPROGRESS) |
1568 | break; | 1557 | break; |
1569 | 1558 | ||
1570 | spin_lock(&urb->lock); | ||
1571 | if (urb->status == -EINPROGRESS) /* Not dequeued */ | ||
1572 | urb->status = status; | ||
1573 | else | ||
1574 | status = ECONNRESET; /* Not -ECONNRESET */ | ||
1575 | spin_unlock(&urb->lock); | ||
1576 | |||
1577 | /* Dequeued but completed URBs can't be given back unless | 1559 | /* Dequeued but completed URBs can't be given back unless |
1578 | * the QH is stopped or has finished unlinking. */ | 1560 | * the QH is stopped or has finished unlinking. */ |
1579 | if (status == ECONNRESET) { | 1561 | if (urb->unlinked) { |
1580 | if (QH_FINISHED_UNLINKING(qh)) | 1562 | if (QH_FINISHED_UNLINKING(qh)) |
1581 | qh->is_stopped = 1; | 1563 | qh->is_stopped = 1; |
1582 | else if (!qh->is_stopped) | 1564 | else if (!qh->is_stopped) |
1583 | return; | 1565 | return; |
1584 | } | 1566 | } |
1585 | 1567 | ||
1586 | uhci_giveback_urb(uhci, qh, urb); | 1568 | uhci_giveback_urb(uhci, qh, urb, status); |
1587 | if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC) | 1569 | if (status < 0) |
1588 | break; | 1570 | break; |
1589 | } | 1571 | } |
1590 | 1572 | ||
@@ -1599,7 +1581,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
1599 | restart: | 1581 | restart: |
1600 | list_for_each_entry(urbp, &qh->queue, node) { | 1582 | list_for_each_entry(urbp, &qh->queue, node) { |
1601 | urb = urbp->urb; | 1583 | urb = urbp->urb; |
1602 | if (urb->status != -EINPROGRESS) { | 1584 | if (urb->unlinked) { |
1603 | 1585 | ||
1604 | /* Fix up the TD links and save the toggles for | 1586 | /* Fix up the TD links and save the toggles for |
1605 | * non-Isochronous queues. For Isochronous queues, | 1587 | * non-Isochronous queues. For Isochronous queues, |
@@ -1608,7 +1590,7 @@ restart: | |||
1608 | qh->is_stopped = 0; | 1590 | qh->is_stopped = 0; |
1609 | return; | 1591 | return; |
1610 | } | 1592 | } |
1611 | uhci_giveback_urb(uhci, qh, urb); | 1593 | uhci_giveback_urb(uhci, qh, urb, 0); |
1612 | goto restart; | 1594 | goto restart; |
1613 | } | 1595 | } |
1614 | } | 1596 | } |
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index e9fdbc8997b3..5131cbfb2f52 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -188,7 +188,8 @@ static void adu_interrupt_in_callback(struct urb *urb) | |||
188 | spin_lock(&dev->buflock); | 188 | spin_lock(&dev->buflock); |
189 | 189 | ||
190 | if (status != 0) { | 190 | if (status != 0) { |
191 | if ((status != -ENOENT) && (status != -ECONNRESET)) { | 191 | if ((status != -ENOENT) && (status != -ECONNRESET) && |
192 | (status != -ESHUTDOWN)) { | ||
192 | dbg(1," %s : nonzero status received: %d", | 193 | dbg(1," %s : nonzero status received: %d", |
193 | __FUNCTION__, status); | 194 | __FUNCTION__, status); |
194 | } | 195 | } |
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index 92c1d2768df9..24e2dc3148a4 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c | |||
@@ -71,7 +71,7 @@ static int magic_charge(struct usb_device *udev) | |||
71 | if (retval != 2) { | 71 | if (retval != 2) { |
72 | dev_err(&udev->dev, "First magic command failed: %d.\n", | 72 | dev_err(&udev->dev, "First magic command failed: %d.\n", |
73 | retval); | 73 | retval); |
74 | return retval; | 74 | goto exit; |
75 | } | 75 | } |
76 | 76 | ||
77 | dbg(&udev->dev, "Sending second magic command\n"); | 77 | dbg(&udev->dev, "Sending second magic command\n"); |
@@ -80,7 +80,7 @@ static int magic_charge(struct usb_device *udev) | |||
80 | if (retval != 0) { | 80 | if (retval != 0) { |
81 | dev_err(&udev->dev, "Second magic command failed: %d.\n", | 81 | dev_err(&udev->dev, "Second magic command failed: %d.\n", |
82 | retval); | 82 | retval); |
83 | return retval; | 83 | goto exit; |
84 | } | 84 | } |
85 | 85 | ||
86 | dbg(&udev->dev, "Calling set_configuration\n"); | 86 | dbg(&udev->dev, "Calling set_configuration\n"); |
@@ -88,6 +88,8 @@ static int magic_charge(struct usb_device *udev) | |||
88 | if (retval) | 88 | if (retval) |
89 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); | 89 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); |
90 | 90 | ||
91 | exit: | ||
92 | kfree(dummy_buffer); | ||
91 | return retval; | 93 | return retval; |
92 | } | 94 | } |
93 | 95 | ||
@@ -112,6 +114,7 @@ static int magic_dual_mode(struct usb_device *udev) | |||
112 | if (retval) | 114 | if (retval) |
113 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); | 115 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); |
114 | 116 | ||
117 | kfree(dummy_buffer); | ||
115 | return retval; | 118 | return retval; |
116 | } | 119 | } |
117 | 120 | ||
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 538b535e955b..d3d8cd6ff103 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -2777,12 +2777,14 @@ static int ftdi_elan_probe(struct usb_interface *interface, | |||
2777 | size_t buffer_size; | 2777 | size_t buffer_size; |
2778 | int i; | 2778 | int i; |
2779 | int retval = -ENOMEM; | 2779 | int retval = -ENOMEM; |
2780 | struct usb_ftdi *ftdi = kmalloc(sizeof(struct usb_ftdi), GFP_KERNEL); | 2780 | struct usb_ftdi *ftdi; |
2781 | if (ftdi == NULL) { | 2781 | |
2782 | ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL); | ||
2783 | if (!ftdi) { | ||
2782 | printk(KERN_ERR "Out of memory\n"); | 2784 | printk(KERN_ERR "Out of memory\n"); |
2783 | return -ENOMEM; | 2785 | return -ENOMEM; |
2784 | } | 2786 | } |
2785 | memset(ftdi, 0x00, sizeof(struct usb_ftdi)); | 2787 | |
2786 | mutex_lock(&ftdi_module_lock); | 2788 | mutex_lock(&ftdi_module_lock); |
2787 | list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); | 2789 | list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); |
2788 | ftdi->sequence_num = ++ftdi_instances; | 2790 | ftdi->sequence_num = ++ftdi_instances; |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index b64ca91d9b02..9244d067cec1 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -32,7 +32,7 @@ | |||
32 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | * | 34 | * |
35 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 35 | * Author: Thomas Winischhofer <thomas@winischhofer.net> |
36 | * | 36 | * |
37 | */ | 37 | */ |
38 | 38 | ||
@@ -962,12 +962,12 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, | |||
962 | packet.address = 0x00000194; | 962 | packet.address = 0x00000194; |
963 | packet.data = addr; | 963 | packet.data = addr; |
964 | ret = sisusb_send_bridge_packet(sisusb, 10, | 964 | ret = sisusb_send_bridge_packet(sisusb, 10, |
965 | &packet, 0); | 965 | &packet, 0); |
966 | packet.header = 0x001f; | 966 | packet.header = 0x001f; |
967 | packet.address = 0x00000190; | 967 | packet.address = 0x00000190; |
968 | packet.data = (length & ~3); | 968 | packet.data = (length & ~3); |
969 | ret |= sisusb_send_bridge_packet(sisusb, 10, | 969 | ret |= sisusb_send_bridge_packet(sisusb, 10, |
970 | &packet, 0); | 970 | &packet, 0); |
971 | if (sisusb->flagb0 != 0x16) { | 971 | if (sisusb->flagb0 != 0x16) { |
972 | packet.header = 0x001f; | 972 | packet.header = 0x001f; |
973 | packet.address = 0x00000180; | 973 | packet.address = 0x00000180; |
@@ -1003,23 +1003,17 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, | |||
1003 | if (ret) { | 1003 | if (ret) { |
1004 | msgcount++; | 1004 | msgcount++; |
1005 | if (msgcount < 500) | 1005 | if (msgcount < 500) |
1006 | printk(KERN_ERR | 1006 | dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n", |
1007 | "sisusbvga[%d]: Wrote %zd of " | 1007 | *bytes_written, length, ret); |
1008 | "%d bytes, error %d\n", | ||
1009 | sisusb->minor, *bytes_written, | ||
1010 | length, ret); | ||
1011 | else if (msgcount == 500) | 1008 | else if (msgcount == 500) |
1012 | printk(KERN_ERR | 1009 | dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n"); |
1013 | "sisusbvga[%d]: Too many errors" | ||
1014 | ", logging stopped\n", | ||
1015 | sisusb->minor); | ||
1016 | } | 1010 | } |
1017 | addr += (*bytes_written); | 1011 | addr += (*bytes_written); |
1018 | length -= (*bytes_written); | 1012 | length -= (*bytes_written); |
1019 | } | 1013 | } |
1020 | 1014 | ||
1021 | if (ret) | 1015 | if (ret) |
1022 | break; | 1016 | break; |
1023 | 1017 | ||
1024 | } | 1018 | } |
1025 | 1019 | ||
@@ -1261,51 +1255,10 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, | |||
1261 | addr += 4; | 1255 | addr += 4; |
1262 | length -= 4; | 1256 | length -= 4; |
1263 | } | 1257 | } |
1264 | #if 0 /* That does not work, as EP 2 is an OUT EP! */ | ||
1265 | default: | ||
1266 | CLEARPACKET(&packet); | ||
1267 | packet.header = 0x001f; | ||
1268 | packet.address = 0x000001a0; | ||
1269 | packet.data = 0x00000006; | ||
1270 | ret |= sisusb_send_bridge_packet(sisusb, 10, | ||
1271 | &packet, 0); | ||
1272 | packet.header = 0x001f; | ||
1273 | packet.address = 0x000001b0; | ||
1274 | packet.data = (length & ~3) | 0x40000000; | ||
1275 | ret |= sisusb_send_bridge_packet(sisusb, 10, | ||
1276 | &packet, 0); | ||
1277 | packet.header = 0x001f; | ||
1278 | packet.address = 0x000001b4; | ||
1279 | packet.data = addr; | ||
1280 | ret |= sisusb_send_bridge_packet(sisusb, 10, | ||
1281 | &packet, 0); | ||
1282 | packet.header = 0x001f; | ||
1283 | packet.address = 0x000001a4; | ||
1284 | packet.data = 0x00000001; | ||
1285 | ret |= sisusb_send_bridge_packet(sisusb, 10, | ||
1286 | &packet, 0); | ||
1287 | if (userbuffer) { | ||
1288 | ret |= sisusb_recv_bulk_msg(sisusb, | ||
1289 | SISUSB_EP_GFX_BULK_IN, | ||
1290 | (length & ~3), | ||
1291 | NULL, userbuffer, | ||
1292 | bytes_read, 0); | ||
1293 | if (!ret) userbuffer += (*bytes_read); | ||
1294 | } else { | ||
1295 | ret |= sisusb_recv_bulk_msg(sisusb, | ||
1296 | SISUSB_EP_GFX_BULK_IN, | ||
1297 | (length & ~3), | ||
1298 | kernbuffer, NULL, | ||
1299 | bytes_read, 0); | ||
1300 | if (!ret) kernbuffer += (*bytes_read); | ||
1301 | } | ||
1302 | addr += (*bytes_read); | ||
1303 | length -= (*bytes_read); | ||
1304 | #endif | ||
1305 | } | 1258 | } |
1306 | 1259 | ||
1307 | if (ret) | 1260 | if (ret) |
1308 | break; | 1261 | break; |
1309 | } | 1262 | } |
1310 | 1263 | ||
1311 | return ret; | 1264 | return ret; |
@@ -1401,22 +1354,6 @@ sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) | |||
1401 | return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); | 1354 | return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); |
1402 | } | 1355 | } |
1403 | 1356 | ||
1404 | #if 0 | ||
1405 | |||
1406 | int | ||
1407 | sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) | ||
1408 | { | ||
1409 | return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); | ||
1410 | } | ||
1411 | |||
1412 | int | ||
1413 | sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data) | ||
1414 | { | ||
1415 | return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); | ||
1416 | } | ||
1417 | |||
1418 | #endif /* 0 */ | ||
1419 | |||
1420 | int | 1357 | int |
1421 | sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | 1358 | sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, |
1422 | u32 dest, int length, size_t *bytes_written) | 1359 | u32 dest, int length, size_t *bytes_written) |
@@ -1446,10 +1383,10 @@ sisusb_testreadwrite(struct sisusb_usb_data *sisusb) | |||
1446 | sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); | 1383 | sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); |
1447 | 1384 | ||
1448 | for(i = 1; i <= 7; i++) { | 1385 | for(i = 1; i <= 7; i++) { |
1449 | printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i); | 1386 | dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i); |
1450 | sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); | 1387 | sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); |
1451 | for(j = 0; j < i; j++) { | 1388 | for(j = 0; j < i; j++) { |
1452 | printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]); | 1389 | dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]); |
1453 | } | 1390 | } |
1454 | } | 1391 | } |
1455 | } | 1392 | } |
@@ -1533,9 +1470,9 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) | |||
1533 | #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a) | 1470 | #define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a) |
1534 | #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o) | 1471 | #define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o) |
1535 | #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) | 1472 | #define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) |
1536 | #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) | 1473 | #define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) |
1537 | #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) | 1474 | #define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) |
1538 | #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) | 1475 | #define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) |
1539 | 1476 | ||
1540 | static int | 1477 | static int |
1541 | sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) | 1478 | sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) |
@@ -2008,7 +1945,7 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) | |||
2008 | SETIREG(SISSR, 0x26, 0x00); | 1945 | SETIREG(SISSR, 0x26, 0x00); |
2009 | } | 1946 | } |
2010 | 1947 | ||
2011 | SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */ | 1948 | SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */ |
2012 | 1949 | ||
2013 | return ret; | 1950 | return ret; |
2014 | } | 1951 | } |
@@ -2168,17 +2105,12 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) | |||
2168 | if (ramtype <= 1) { | 2105 | if (ramtype <= 1) { |
2169 | ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); | 2106 | ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); |
2170 | if (iret) { | 2107 | if (iret) { |
2171 | printk(KERN_ERR "sisusbvga[%d]: RAM size " | 2108 | dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n"); |
2172 | "detection failed, " | ||
2173 | "assuming 8MB video RAM\n", | ||
2174 | sisusb->minor); | ||
2175 | ret |= SETIREG(SISSR,0x14,0x31); | 2109 | ret |= SETIREG(SISSR,0x14,0x31); |
2176 | /* TODO */ | 2110 | /* TODO */ |
2177 | } | 2111 | } |
2178 | } else { | 2112 | } else { |
2179 | printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, " | 2113 | dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n"); |
2180 | "assuming 8MB video RAM\n", | ||
2181 | sisusb->minor); | ||
2182 | ret |= SETIREG(SISSR,0x14,0x31); | 2114 | ret |= SETIREG(SISSR,0x14,0x31); |
2183 | /* *** TODO *** */ | 2115 | /* *** TODO *** */ |
2184 | } | 2116 | } |
@@ -2249,8 +2181,7 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) | |||
2249 | break; | 2181 | break; |
2250 | } | 2182 | } |
2251 | 2183 | ||
2252 | printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n", | 2184 | dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1, |
2253 | sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1, | ||
2254 | ramtypetext2[ramtype], bw); | 2185 | ramtypetext2[ramtype], bw); |
2255 | } | 2186 | } |
2256 | 2187 | ||
@@ -2509,11 +2440,8 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2509 | struct usb_interface *interface; | 2440 | struct usb_interface *interface; |
2510 | int subminor = iminor(inode); | 2441 | int subminor = iminor(inode); |
2511 | 2442 | ||
2512 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { | 2443 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) |
2513 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", | ||
2514 | subminor); | ||
2515 | return -ENODEV; | 2444 | return -ENODEV; |
2516 | } | ||
2517 | 2445 | ||
2518 | if (!(sisusb = usb_get_intfdata(interface))) | 2446 | if (!(sisusb = usb_get_intfdata(interface))) |
2519 | return -ENODEV; | 2447 | return -ENODEV; |
@@ -2534,18 +2462,12 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2534 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { | 2462 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { |
2535 | if (sisusb_init_gfxdevice(sisusb, 0)) { | 2463 | if (sisusb_init_gfxdevice(sisusb, 0)) { |
2536 | mutex_unlock(&sisusb->lock); | 2464 | mutex_unlock(&sisusb->lock); |
2537 | printk(KERN_ERR | 2465 | dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); |
2538 | "sisusbvga[%d]: Failed to initialize " | ||
2539 | "device\n", | ||
2540 | sisusb->minor); | ||
2541 | return -EIO; | 2466 | return -EIO; |
2542 | } | 2467 | } |
2543 | } else { | 2468 | } else { |
2544 | mutex_unlock(&sisusb->lock); | 2469 | mutex_unlock(&sisusb->lock); |
2545 | printk(KERN_ERR | 2470 | dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); |
2546 | "sisusbvga[%d]: Device not attached to " | ||
2547 | "USB 2.0 hub\n", | ||
2548 | sisusb->minor); | ||
2549 | return -EIO; | 2471 | return -EIO; |
2550 | } | 2472 | } |
2551 | } | 2473 | } |
@@ -2586,7 +2508,6 @@ static int | |||
2586 | sisusb_release(struct inode *inode, struct file *file) | 2508 | sisusb_release(struct inode *inode, struct file *file) |
2587 | { | 2509 | { |
2588 | struct sisusb_usb_data *sisusb; | 2510 | struct sisusb_usb_data *sisusb; |
2589 | int myminor; | ||
2590 | 2511 | ||
2591 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2512 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2592 | return -ENODEV; | 2513 | return -ENODEV; |
@@ -2599,8 +2520,6 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2599 | sisusb_kill_all_busy(sisusb); | 2520 | sisusb_kill_all_busy(sisusb); |
2600 | } | 2521 | } |
2601 | 2522 | ||
2602 | myminor = sisusb->minor; | ||
2603 | |||
2604 | sisusb->isopen = 0; | 2523 | sisusb->isopen = 0; |
2605 | file->private_data = NULL; | 2524 | file->private_data = NULL; |
2606 | 2525 | ||
@@ -2942,7 +2861,7 @@ static int | |||
2942 | sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, | 2861 | sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, |
2943 | unsigned long arg) | 2862 | unsigned long arg) |
2944 | { | 2863 | { |
2945 | int retval, port, length; | 2864 | int retval, port, length; |
2946 | u32 address; | 2865 | u32 address; |
2947 | 2866 | ||
2948 | /* All our commands require the device | 2867 | /* All our commands require the device |
@@ -3065,12 +2984,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, | |||
3065 | 2984 | ||
3066 | static int | 2985 | static int |
3067 | sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 2986 | sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, |
3068 | unsigned long arg) | 2987 | unsigned long arg) |
3069 | { | 2988 | { |
3070 | struct sisusb_usb_data *sisusb; | 2989 | struct sisusb_usb_data *sisusb; |
3071 | struct sisusb_info x; | 2990 | struct sisusb_info x; |
3072 | struct sisusb_command y; | 2991 | struct sisusb_command y; |
3073 | int retval = 0; | 2992 | int retval = 0; |
3074 | u32 __user *argp = (u32 __user *)arg; | 2993 | u32 __user *argp = (u32 __user *)arg; |
3075 | 2994 | ||
3076 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) | 2995 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
@@ -3095,7 +3014,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
3095 | 3014 | ||
3096 | case SISUSB_GET_CONFIG: | 3015 | case SISUSB_GET_CONFIG: |
3097 | 3016 | ||
3098 | x.sisusb_id = SISUSB_ID; | 3017 | x.sisusb_id = SISUSB_ID; |
3099 | x.sisusb_version = SISUSB_VERSION; | 3018 | x.sisusb_version = SISUSB_VERSION; |
3100 | x.sisusb_revision = SISUSB_REVISION; | 3019 | x.sisusb_revision = SISUSB_REVISION; |
3101 | x.sisusb_patchlevel = SISUSB_PATCHLEVEL; | 3020 | x.sisusb_patchlevel = SISUSB_PATCHLEVEL; |
@@ -3164,7 +3083,7 @@ static const struct file_operations usb_sisusb_fops = { | |||
3164 | .release = sisusb_release, | 3083 | .release = sisusb_release, |
3165 | .read = sisusb_read, | 3084 | .read = sisusb_read, |
3166 | .write = sisusb_write, | 3085 | .write = sisusb_write, |
3167 | .llseek = sisusb_lseek, | 3086 | .llseek = sisusb_lseek, |
3168 | #ifdef SISUSB_NEW_CONFIG_COMPAT | 3087 | #ifdef SISUSB_NEW_CONFIG_COMPAT |
3169 | .compat_ioctl = sisusb_compat_ioctl, | 3088 | .compat_ioctl = sisusb_compat_ioctl, |
3170 | #endif | 3089 | #endif |
@@ -3183,17 +3102,13 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3183 | struct usb_device *dev = interface_to_usbdev(intf); | 3102 | struct usb_device *dev = interface_to_usbdev(intf); |
3184 | struct sisusb_usb_data *sisusb; | 3103 | struct sisusb_usb_data *sisusb; |
3185 | int retval = 0, i; | 3104 | int retval = 0, i; |
3186 | const char *memfail = | ||
3187 | KERN_ERR | ||
3188 | "sisusbvga[%d]: Failed to allocate memory for %s buffer\n"; | ||
3189 | 3105 | ||
3190 | printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n", | 3106 | dev_info(&dev->dev, "USB2VGA dongle found at address %d\n", |
3191 | dev->devnum); | 3107 | dev->devnum); |
3192 | 3108 | ||
3193 | /* Allocate memory for our private */ | 3109 | /* Allocate memory for our private */ |
3194 | if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { | 3110 | if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { |
3195 | printk(KERN_ERR | 3111 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n"); |
3196 | "sisusb: Failed to allocate memory for private data\n"); | ||
3197 | return -ENOMEM; | 3112 | return -ENOMEM; |
3198 | } | 3113 | } |
3199 | kref_init(&sisusb->kref); | 3114 | kref_init(&sisusb->kref); |
@@ -3202,8 +3117,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3202 | 3117 | ||
3203 | /* Register device */ | 3118 | /* Register device */ |
3204 | if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { | 3119 | if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { |
3205 | printk(KERN_ERR | 3120 | dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n", |
3206 | "sisusb: Failed to get a minor for device %d\n", | ||
3207 | dev->devnum); | 3121 | dev->devnum); |
3208 | retval = -ENODEV; | 3122 | retval = -ENODEV; |
3209 | goto error_1; | 3123 | goto error_1; |
@@ -3221,7 +3135,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3221 | sisusb->ibufsize = SISUSB_IBUF_SIZE; | 3135 | sisusb->ibufsize = SISUSB_IBUF_SIZE; |
3222 | if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE, | 3136 | if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE, |
3223 | GFP_KERNEL, &sisusb->transfer_dma_in))) { | 3137 | GFP_KERNEL, &sisusb->transfer_dma_in))) { |
3224 | printk(memfail, "input", sisusb->minor); | 3138 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); |
3225 | retval = -ENOMEM; | 3139 | retval = -ENOMEM; |
3226 | goto error_2; | 3140 | goto error_2; |
3227 | } | 3141 | } |
@@ -3233,7 +3147,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3233 | GFP_KERNEL, | 3147 | GFP_KERNEL, |
3234 | &sisusb->transfer_dma_out[i]))) { | 3148 | &sisusb->transfer_dma_out[i]))) { |
3235 | if (i == 0) { | 3149 | if (i == 0) { |
3236 | printk(memfail, "output", sisusb->minor); | 3150 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); |
3237 | retval = -ENOMEM; | 3151 | retval = -ENOMEM; |
3238 | goto error_3; | 3152 | goto error_3; |
3239 | } | 3153 | } |
@@ -3245,9 +3159,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3245 | 3159 | ||
3246 | /* Allocate URBs */ | 3160 | /* Allocate URBs */ |
3247 | if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) { | 3161 | if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) { |
3248 | printk(KERN_ERR | 3162 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); |
3249 | "sisusbvga[%d]: Failed to allocate URBs\n", | ||
3250 | sisusb->minor); | ||
3251 | retval = -ENOMEM; | 3163 | retval = -ENOMEM; |
3252 | goto error_3; | 3164 | goto error_3; |
3253 | } | 3165 | } |
@@ -3255,9 +3167,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3255 | 3167 | ||
3256 | for (i = 0; i < sisusb->numobufs; i++) { | 3168 | for (i = 0; i < sisusb->numobufs; i++) { |
3257 | if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { | 3169 | if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { |
3258 | printk(KERN_ERR | 3170 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); |
3259 | "sisusbvga[%d]: Failed to allocate URBs\n", | ||
3260 | sisusb->minor); | ||
3261 | retval = -ENOMEM; | 3171 | retval = -ENOMEM; |
3262 | goto error_4; | 3172 | goto error_4; |
3263 | } | 3173 | } |
@@ -3266,15 +3176,12 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3266 | sisusb->urbstatus[i] = 0; | 3176 | sisusb->urbstatus[i] = 0; |
3267 | } | 3177 | } |
3268 | 3178 | ||
3269 | printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n", | 3179 | dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs); |
3270 | sisusb->minor, sisusb->numobufs); | ||
3271 | 3180 | ||
3272 | #ifdef INCL_SISUSB_CON | 3181 | #ifdef INCL_SISUSB_CON |
3273 | /* Allocate our SiS_Pr */ | 3182 | /* Allocate our SiS_Pr */ |
3274 | if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { | 3183 | if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { |
3275 | printk(KERN_ERR | 3184 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); |
3276 | "sisusbvga[%d]: Failed to allocate SiS_Pr\n", | ||
3277 | sisusb->minor); | ||
3278 | } | 3185 | } |
3279 | #endif | 3186 | #endif |
3280 | 3187 | ||
@@ -3296,10 +3203,7 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3296 | ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL); | 3203 | ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL); |
3297 | ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL); | 3204 | ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL); |
3298 | if (ret) | 3205 | if (ret) |
3299 | printk(KERN_ERR | 3206 | dev_err(&sisusb->sisusb_dev->dev, "Error registering ioctl32 translations\n"); |
3300 | "sisusbvga[%d]: Error registering ioctl32 " | ||
3301 | "translations\n", | ||
3302 | sisusb->minor); | ||
3303 | else | 3207 | else |
3304 | sisusb->ioctl32registered = 1; | 3208 | sisusb->ioctl32registered = 1; |
3305 | } | 3209 | } |
@@ -3315,23 +3219,17 @@ static int sisusb_probe(struct usb_interface *intf, | |||
3315 | initscreen = 0; | 3219 | initscreen = 0; |
3316 | #endif | 3220 | #endif |
3317 | if (sisusb_init_gfxdevice(sisusb, initscreen)) | 3221 | if (sisusb_init_gfxdevice(sisusb, initscreen)) |
3318 | printk(KERN_ERR | 3222 | dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n"); |
3319 | "sisusbvga[%d]: Failed to early " | ||
3320 | "initialize device\n", | ||
3321 | sisusb->minor); | ||
3322 | 3223 | ||
3323 | } else | 3224 | } else |
3324 | printk(KERN_INFO | 3225 | dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n"); |
3325 | "sisusbvga[%d]: Not attached to USB 2.0 hub, " | ||
3326 | "deferring init\n", | ||
3327 | sisusb->minor); | ||
3328 | 3226 | ||
3329 | sisusb->ready = 1; | 3227 | sisusb->ready = 1; |
3330 | 3228 | ||
3331 | #ifdef SISUSBENDIANTEST | 3229 | #ifdef SISUSBENDIANTEST |
3332 | printk(KERN_DEBUG "sisusb: *** RWTEST ***\n"); | 3230 | dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST ***\n"); |
3333 | sisusb_testreadwrite(sisusb); | 3231 | sisusb_testreadwrite(sisusb); |
3334 | printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n"); | 3232 | dev_dbg(&sisusb->sisusb_dev->dev, "*** RWTEST END ***\n"); |
3335 | #endif | 3233 | #endif |
3336 | 3234 | ||
3337 | #ifdef INCL_SISUSB_CON | 3235 | #ifdef INCL_SISUSB_CON |
@@ -3354,7 +3252,6 @@ error_1: | |||
3354 | static void sisusb_disconnect(struct usb_interface *intf) | 3252 | static void sisusb_disconnect(struct usb_interface *intf) |
3355 | { | 3253 | { |
3356 | struct sisusb_usb_data *sisusb; | 3254 | struct sisusb_usb_data *sisusb; |
3357 | int minor; | ||
3358 | 3255 | ||
3359 | /* This should *not* happen */ | 3256 | /* This should *not* happen */ |
3360 | if (!(sisusb = usb_get_intfdata(intf))) | 3257 | if (!(sisusb = usb_get_intfdata(intf))) |
@@ -3364,8 +3261,6 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3364 | sisusb_console_exit(sisusb); | 3261 | sisusb_console_exit(sisusb); |
3365 | #endif | 3262 | #endif |
3366 | 3263 | ||
3367 | minor = sisusb->minor; | ||
3368 | |||
3369 | usb_deregister_dev(intf, &usb_sisusb_class); | 3264 | usb_deregister_dev(intf, &usb_sisusb_class); |
3370 | 3265 | ||
3371 | mutex_lock(&sisusb->lock); | 3266 | mutex_lock(&sisusb->lock); |
@@ -3384,10 +3279,7 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3384 | ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG); | 3279 | ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG); |
3385 | ret |= unregister_ioctl32_conversion(SISUSB_COMMAND); | 3280 | ret |= unregister_ioctl32_conversion(SISUSB_COMMAND); |
3386 | if (ret) { | 3281 | if (ret) { |
3387 | printk(KERN_ERR | 3282 | dev_err(&sisusb->sisusb_dev->dev, "Error unregistering ioctl32 translations\n"); |
3388 | "sisusbvga[%d]: Error unregistering " | ||
3389 | "ioctl32 translations\n", | ||
3390 | minor); | ||
3391 | } | 3283 | } |
3392 | } | 3284 | } |
3393 | #endif | 3285 | #endif |
@@ -3400,7 +3292,7 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3400 | /* decrement our usage count */ | 3292 | /* decrement our usage count */ |
3401 | kref_put(&sisusb->kref, sisusb_delete); | 3293 | kref_put(&sisusb->kref, sisusb_delete); |
3402 | 3294 | ||
3403 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); | 3295 | dev_info(&sisusb->sisusb_dev->dev, "Disconnected\n"); |
3404 | } | 3296 | } |
3405 | 3297 | ||
3406 | static struct usb_device_id sisusb_table [] = { | 3298 | static struct usb_device_id sisusb_table [] = { |
@@ -3424,22 +3316,12 @@ static struct usb_driver sisusb_driver = { | |||
3424 | 3316 | ||
3425 | static int __init usb_sisusb_init(void) | 3317 | static int __init usb_sisusb_init(void) |
3426 | { | 3318 | { |
3427 | int retval; | ||
3428 | 3319 | ||
3429 | #ifdef INCL_SISUSB_CON | 3320 | #ifdef INCL_SISUSB_CON |
3430 | sisusb_init_concode(); | 3321 | sisusb_init_concode(); |
3431 | #endif | 3322 | #endif |
3432 | 3323 | ||
3433 | if (!(retval = usb_register(&sisusb_driver))) { | 3324 | return usb_register(&sisusb_driver); |
3434 | |||
3435 | printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n", | ||
3436 | SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL); | ||
3437 | printk(KERN_INFO | ||
3438 | "sisusb: Copyright (C) 2005 Thomas Winischhofer\n"); | ||
3439 | |||
3440 | } | ||
3441 | |||
3442 | return retval; | ||
3443 | } | 3325 | } |
3444 | 3326 | ||
3445 | static void __exit usb_sisusb_exit(void) | 3327 | static void __exit usb_sisusb_exit(void) |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index 8e1120a64806..d2d7872cd022 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h | |||
@@ -8,29 +8,29 @@ | |||
8 | * | 8 | * |
9 | * Otherwise, the following license terms apply: | 9 | * Otherwise, the following license terms apply: |
10 | * | 10 | * |
11 | * * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions |
13 | * * are met: | 13 | * are met: |
14 | * * 1) Redistributions of source code must retain the above copyright | 14 | * 1) Redistributions of source code must retain the above copyright |
15 | * * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * * 2) Redistributions in binary form must reproduce the above copyright | 16 | * 2) Redistributions in binary form must reproduce the above copyright |
17 | * * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. |
19 | * * 3) The name of the author may not be used to endorse or promote products | 19 | * 3) The name of the author may not be used to endorse or promote products |
20 | * * derived from this software without specific prior written permission. | 20 | * derived from this software without specific prior written permission. |
21 | * * | ||
22 | * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR | ||
23 | * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
24 | * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
25 | * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
28 | * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
29 | * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | * | 21 | * |
33 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | * | ||
33 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | ||
34 | * | 34 | * |
35 | */ | 35 | */ |
36 | 36 | ||
@@ -44,16 +44,14 @@ | |||
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | 45 | ||
46 | /* For older kernels, support for text consoles is by default | 46 | /* For older kernels, support for text consoles is by default |
47 | * off. To ensable text console support, change the following: | 47 | * off. To enable text console support, change the following: |
48 | */ | 48 | */ |
49 | #if 0 | 49 | /* #define CONFIG_USB_SISUSBVGA_CON */ |
50 | #define CONFIG_USB_SISUSBVGA_CON | ||
51 | #endif | ||
52 | 50 | ||
53 | /* Version Information */ | 51 | /* Version Information */ |
54 | 52 | ||
55 | #define SISUSB_VERSION 0 | 53 | #define SISUSB_VERSION 0 |
56 | #define SISUSB_REVISION 0 | 54 | #define SISUSB_REVISION 0 |
57 | #define SISUSB_PATCHLEVEL 8 | 55 | #define SISUSB_PATCHLEVEL 8 |
58 | 56 | ||
59 | /* Include console and mode switching code? */ | 57 | /* Include console and mode switching code? */ |
@@ -74,7 +72,7 @@ | |||
74 | #define SISUSB_IBUF_SIZE 0x01000 | 72 | #define SISUSB_IBUF_SIZE 0x01000 |
75 | #define SISUSB_OBUF_SIZE 0x10000 /* fixed */ | 73 | #define SISUSB_OBUF_SIZE 0x10000 /* fixed */ |
76 | 74 | ||
77 | #define NUMOBUFS 8 /* max number of output buffers/output URBs */ | 75 | #define NUMOBUFS 8 /* max number of output buffers/output URBs */ |
78 | 76 | ||
79 | /* About endianness: | 77 | /* About endianness: |
80 | * | 78 | * |
@@ -93,7 +91,7 @@ | |||
93 | */ | 91 | */ |
94 | 92 | ||
95 | #ifdef __BIG_ENDIAN | 93 | #ifdef __BIG_ENDIAN |
96 | #define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \ | 94 | #define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \ |
97 | do { \ | 95 | do { \ |
98 | p->header = cpu_to_le16(p->header); \ | 96 | p->header = cpu_to_le16(p->header); \ |
99 | p->address = cpu_to_le32(p->address); \ | 97 | p->address = cpu_to_le32(p->address); \ |
@@ -105,7 +103,7 @@ | |||
105 | 103 | ||
106 | struct sisusb_usb_data; | 104 | struct sisusb_usb_data; |
107 | 105 | ||
108 | struct sisusb_urb_context { /* urb->context for outbound bulk URBs */ | 106 | struct sisusb_urb_context { /* urb->context for outbound bulk URBs */ |
109 | struct sisusb_usb_data *sisusb; | 107 | struct sisusb_usb_data *sisusb; |
110 | int urbindex; | 108 | int urbindex; |
111 | int *actual_length; | 109 | int *actual_length; |
@@ -116,16 +114,16 @@ struct sisusb_usb_data { | |||
116 | struct usb_interface *interface; | 114 | struct usb_interface *interface; |
117 | struct kref kref; | 115 | struct kref kref; |
118 | wait_queue_head_t wait_q; /* for syncind and timeouts */ | 116 | wait_queue_head_t wait_q; /* for syncind and timeouts */ |
119 | struct mutex lock; /* general race avoidance */ | 117 | struct mutex lock; /* general race avoidance */ |
120 | unsigned int ifnum; /* interface number of the USB device */ | 118 | unsigned int ifnum; /* interface number of the USB device */ |
121 | int minor; /* minor (for logging clarity) */ | 119 | int minor; /* minor (for logging clarity) */ |
122 | int isopen; /* !=0 if open */ | 120 | int isopen; /* !=0 if open */ |
123 | int present; /* !=0 if device is present on the bus */ | 121 | int present; /* !=0 if device is present on the bus */ |
124 | int ready; /* !=0 if device is ready for userland */ | 122 | int ready; /* !=0 if device is ready for userland */ |
125 | #ifdef SISUSB_OLD_CONFIG_COMPAT | 123 | #ifdef SISUSB_OLD_CONFIG_COMPAT |
126 | int ioctl32registered; | 124 | int ioctl32registered; |
127 | #endif | 125 | #endif |
128 | int numobufs; /* number of obufs = number of out urbs */ | 126 | int numobufs; /* number of obufs = number of out urbs */ |
129 | char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */ | 127 | char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */ |
130 | int obufsize, ibufsize; | 128 | int obufsize, ibufsize; |
131 | dma_addr_t transfer_dma_out[NUMOBUFS]; | 129 | dma_addr_t transfer_dma_out[NUMOBUFS]; |
@@ -136,13 +134,13 @@ struct sisusb_usb_data { | |||
136 | unsigned char completein; | 134 | unsigned char completein; |
137 | struct sisusb_urb_context urbout_context[NUMOBUFS]; | 135 | struct sisusb_urb_context urbout_context[NUMOBUFS]; |
138 | unsigned long flagb0; | 136 | unsigned long flagb0; |
139 | unsigned long vrambase; /* framebuffer base */ | 137 | unsigned long vrambase; /* framebuffer base */ |
140 | unsigned int vramsize; /* framebuffer size (bytes) */ | 138 | unsigned int vramsize; /* framebuffer size (bytes) */ |
141 | unsigned long mmiobase; | 139 | unsigned long mmiobase; |
142 | unsigned int mmiosize; | 140 | unsigned int mmiosize; |
143 | unsigned long ioportbase; | 141 | unsigned long ioportbase; |
144 | unsigned char devinit; /* device initialized? */ | 142 | unsigned char devinit; /* device initialized? */ |
145 | unsigned char gfxinit; /* graphics core initialized? */ | 143 | unsigned char gfxinit; /* graphics core initialized? */ |
146 | unsigned short chipid, chipvendor; | 144 | unsigned short chipid, chipvendor; |
147 | unsigned short chiprevision; | 145 | unsigned short chiprevision; |
148 | #ifdef INCL_SISUSB_CON | 146 | #ifdef INCL_SISUSB_CON |
@@ -152,7 +150,7 @@ struct sisusb_usb_data { | |||
152 | int haveconsole, con_first, con_last; | 150 | int haveconsole, con_first, con_last; |
153 | int havethisconsole[MAX_NR_CONSOLES]; | 151 | int havethisconsole[MAX_NR_CONSOLES]; |
154 | int textmodedestroyed; | 152 | int textmodedestroyed; |
155 | unsigned int sisusb_num_columns; /* real number, not vt's idea */ | 153 | unsigned int sisusb_num_columns; /* real number, not vt's idea */ |
156 | int cur_start_addr, con_rolled_over; | 154 | int cur_start_addr, con_rolled_over; |
157 | int sisusb_cursor_loc, bad_cursor_pos; | 155 | int sisusb_cursor_loc, bad_cursor_pos; |
158 | int sisusb_cursor_size_from; | 156 | int sisusb_cursor_size_from; |
@@ -197,7 +195,7 @@ struct sisusb_packet { | |||
197 | unsigned short header; | 195 | unsigned short header; |
198 | u32 address; | 196 | u32 address; |
199 | u32 data; | 197 | u32 data; |
200 | } __attribute__((__packed__)); | 198 | } __attribute__ ((__packed__)); |
201 | 199 | ||
202 | #define CLEARPACKET(packet) memset(packet, 0, 10) | 200 | #define CLEARPACKET(packet) memset(packet, 0, 10) |
203 | 201 | ||
@@ -265,36 +263,36 @@ struct sisusb_packet { | |||
265 | 263 | ||
266 | /* Structure argument for SISUSB_GET_INFO ioctl */ | 264 | /* Structure argument for SISUSB_GET_INFO ioctl */ |
267 | struct sisusb_info { | 265 | struct sisusb_info { |
268 | __u32 sisusb_id; /* for identifying sisusb */ | 266 | __u32 sisusb_id; /* for identifying sisusb */ |
269 | #define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */ | 267 | #define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */ |
270 | __u8 sisusb_version; | 268 | __u8 sisusb_version; |
271 | __u8 sisusb_revision; | 269 | __u8 sisusb_revision; |
272 | __u8 sisusb_patchlevel; | 270 | __u8 sisusb_patchlevel; |
273 | __u8 sisusb_gfxinit; /* graphics core initialized? */ | 271 | __u8 sisusb_gfxinit; /* graphics core initialized? */ |
274 | 272 | ||
275 | __u32 sisusb_vrambase; | 273 | __u32 sisusb_vrambase; |
276 | __u32 sisusb_mmiobase; | 274 | __u32 sisusb_mmiobase; |
277 | __u32 sisusb_iobase; | 275 | __u32 sisusb_iobase; |
278 | __u32 sisusb_pcibase; | 276 | __u32 sisusb_pcibase; |
279 | 277 | ||
280 | __u32 sisusb_vramsize; /* framebuffer size in bytes */ | 278 | __u32 sisusb_vramsize; /* framebuffer size in bytes */ |
281 | 279 | ||
282 | __u32 sisusb_minor; | 280 | __u32 sisusb_minor; |
283 | 281 | ||
284 | __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */ | 282 | __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */ |
285 | 283 | ||
286 | __u32 sisusb_conactive; /* != 0 if console driver active */ | 284 | __u32 sisusb_conactive; /* != 0 if console driver active */ |
287 | 285 | ||
288 | __u8 sisusb_reserved[28]; /* for future use */ | 286 | __u8 sisusb_reserved[28]; /* for future use */ |
289 | }; | 287 | }; |
290 | 288 | ||
291 | struct sisusb_command { | 289 | struct sisusb_command { |
292 | __u8 operation; /* see below */ | 290 | __u8 operation; /* see below */ |
293 | __u8 data0; /* operation dependent */ | 291 | __u8 data0; /* operation dependent */ |
294 | __u8 data1; /* operation dependent */ | 292 | __u8 data1; /* operation dependent */ |
295 | __u8 data2; /* operation dependent */ | 293 | __u8 data2; /* operation dependent */ |
296 | __u32 data3; /* operation dependent */ | 294 | __u32 data3; /* operation dependent */ |
297 | __u32 data4; /* for future use */ | 295 | __u32 data4; /* for future use */ |
298 | }; | 296 | }; |
299 | 297 | ||
300 | #define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ | 298 | #define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */ |
@@ -306,7 +304,7 @@ struct sisusb_command { | |||
306 | 304 | ||
307 | #define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ | 305 | #define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */ |
308 | 306 | ||
309 | #define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */ | 307 | #define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */ |
310 | 308 | ||
311 | #define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */ | 309 | #define SUCMD_SETMODE 0x09 /* Set a display mode (data3 = SiS mode) */ |
312 | #define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */ | 310 | #define SUCMD_SETVESAMODE 0x0a /* Set a display mode (data3 = VESA mode) */ |
@@ -315,6 +313,4 @@ struct sisusb_command { | |||
315 | #define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) | 313 | #define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32) |
316 | #define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) | 314 | #define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info) |
317 | 315 | ||
318 | |||
319 | #endif /* SISUSB_H */ | 316 | #endif /* SISUSB_H */ |
320 | |||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 8d0edc867f33..43722e5a49d1 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/kernel.h> | 52 | #include <linux/kernel.h> |
53 | #include <linux/signal.h> | 53 | #include <linux/signal.h> |
54 | #include <linux/fs.h> | 54 | #include <linux/fs.h> |
55 | #include <linux/usb.h> | ||
55 | #include <linux/tty.h> | 56 | #include <linux/tty.h> |
56 | #include <linux/console.h> | 57 | #include <linux/console.h> |
57 | #include <linux/string.h> | 58 | #include <linux/string.h> |
@@ -373,14 +374,6 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x) | |||
373 | return; | 374 | return; |
374 | 375 | ||
375 | /* sisusb->lock is down */ | 376 | /* sisusb->lock is down */ |
376 | |||
377 | /* Don't need to put the character into buffer ourselves, | ||
378 | * because the vt does this BEFORE calling us. | ||
379 | */ | ||
380 | #if 0 | ||
381 | sisusbcon_writew(ch, SISUSB_VADDR(x, y)); | ||
382 | #endif | ||
383 | |||
384 | if (sisusb_is_inactive(c, sisusb)) { | 377 | if (sisusb_is_inactive(c, sisusb)) { |
385 | mutex_unlock(&sisusb->lock); | 378 | mutex_unlock(&sisusb->lock); |
386 | return; | 379 | return; |
@@ -490,10 +483,6 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, | |||
490 | struct sisusb_usb_data *sisusb; | 483 | struct sisusb_usb_data *sisusb; |
491 | ssize_t written; | 484 | ssize_t written; |
492 | int cols, length; | 485 | int cols, length; |
493 | #if 0 | ||
494 | u16 *src, *dest; | ||
495 | int i; | ||
496 | #endif | ||
497 | 486 | ||
498 | if (width <= 0 || height <= 0) | 487 | if (width <= 0 || height <= 0) |
499 | return; | 488 | return; |
@@ -505,41 +494,6 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx, | |||
505 | 494 | ||
506 | cols = sisusb->sisusb_num_columns; | 495 | cols = sisusb->sisusb_num_columns; |
507 | 496 | ||
508 | /* Don't need to move data outselves, because | ||
509 | * vt does this BEFORE calling us. | ||
510 | * This is only used by vt's insert/deletechar. | ||
511 | */ | ||
512 | #if 0 | ||
513 | if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) { | ||
514 | |||
515 | sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy), | ||
516 | height * width * 2); | ||
517 | |||
518 | } else if (dy < sy || (dy == sy && dx < sx)) { | ||
519 | |||
520 | src = SISUSB_VADDR(sx, sy); | ||
521 | dest = SISUSB_VADDR(dx, dy); | ||
522 | |||
523 | for (i = height; i > 0; i--) { | ||
524 | sisusbcon_memmovew(dest, src, width * 2); | ||
525 | src += cols; | ||
526 | dest += cols; | ||
527 | } | ||
528 | |||
529 | } else { | ||
530 | |||
531 | src = SISUSB_VADDR(sx, sy + height - 1); | ||
532 | dest = SISUSB_VADDR(dx, dy + height - 1); | ||
533 | |||
534 | for (i = height; i > 0; i--) { | ||
535 | sisusbcon_memmovew(dest, src, width * 2); | ||
536 | src -= cols; | ||
537 | dest -= cols; | ||
538 | } | ||
539 | |||
540 | } | ||
541 | #endif | ||
542 | |||
543 | if (sisusb_is_inactive(c, sisusb)) { | 497 | if (sisusb_is_inactive(c, sisusb)) { |
544 | mutex_unlock(&sisusb->lock); | 498 | mutex_unlock(&sisusb->lock); |
545 | return; | 499 | return; |
@@ -584,7 +538,7 @@ sisusbcon_switch(struct vc_data *c) | |||
584 | */ | 538 | */ |
585 | if (c->vc_origin == (unsigned long)c->vc_screenbuf) { | 539 | if (c->vc_origin == (unsigned long)c->vc_screenbuf) { |
586 | mutex_unlock(&sisusb->lock); | 540 | mutex_unlock(&sisusb->lock); |
587 | printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); | 541 | dev_dbg(&sisusb->sisusb_dev->dev, "ASSERT ORIGIN != SCREENBUF!\n"); |
588 | return 0; | 542 | return 0; |
589 | } | 543 | } |
590 | 544 | ||
@@ -1475,7 +1429,7 @@ static const struct consw sisusb_dummy_con = { | |||
1475 | int | 1429 | int |
1476 | sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | 1430 | sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) |
1477 | { | 1431 | { |
1478 | int i, ret, minor = sisusb->minor; | 1432 | int i, ret; |
1479 | 1433 | ||
1480 | mutex_lock(&sisusb->lock); | 1434 | mutex_lock(&sisusb->lock); |
1481 | 1435 | ||
@@ -1508,9 +1462,7 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1508 | /* Set up text mode (and upload default font) */ | 1462 | /* Set up text mode (and upload default font) */ |
1509 | if (sisusb_reset_text_mode(sisusb, 1)) { | 1463 | if (sisusb_reset_text_mode(sisusb, 1)) { |
1510 | mutex_unlock(&sisusb->lock); | 1464 | mutex_unlock(&sisusb->lock); |
1511 | printk(KERN_ERR | 1465 | dev_err(&sisusb->sisusb_dev->dev, "Failed to set up text mode\n"); |
1512 | "sisusbvga[%d]: Failed to set up text mode\n", | ||
1513 | minor); | ||
1514 | return 1; | 1466 | return 1; |
1515 | } | 1467 | } |
1516 | 1468 | ||
@@ -1531,9 +1483,7 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1531 | /* Allocate screen buffer */ | 1483 | /* Allocate screen buffer */ |
1532 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { | 1484 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { |
1533 | mutex_unlock(&sisusb->lock); | 1485 | mutex_unlock(&sisusb->lock); |
1534 | printk(KERN_ERR | 1486 | dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate screen buffer\n"); |
1535 | "sisusbvga[%d]: Failed to allocate screen buffer\n", | ||
1536 | minor); | ||
1537 | return 1; | 1487 | return 1; |
1538 | } | 1488 | } |
1539 | 1489 | ||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index 9b30f8962814..273de5d0934e 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c | |||
@@ -32,7 +32,7 @@ | |||
32 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | * | 34 | * |
35 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 35 | * Author: Thomas Winischhofer <thomas@winischhofer.net> |
36 | * | 36 | * |
37 | */ | 37 | */ |
38 | 38 | ||
@@ -55,109 +55,18 @@ | |||
55 | /* POINTER INITIALIZATION */ | 55 | /* POINTER INITIALIZATION */ |
56 | /*********************************************/ | 56 | /*********************************************/ |
57 | 57 | ||
58 | static void | 58 | static void SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) |
59 | SiSUSB_InitPtr(struct SiS_Private *SiS_Pr) | ||
60 | { | 59 | { |
61 | SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo; | 60 | SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo; |
62 | SiS_Pr->SiS_StandTable = SiSUSB_StandTable; | 61 | SiS_Pr->SiS_StandTable = SiSUSB_StandTable; |
63 | |||
64 | SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable; | ||
65 | SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable; | ||
66 | SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex; | ||
67 | SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table; | ||
68 | |||
69 | SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData; | ||
70 | } | ||
71 | |||
72 | /*********************************************/ | ||
73 | /* HELPER: Get ModeID */ | ||
74 | /*********************************************/ | ||
75 | 62 | ||
76 | #if 0 | 63 | SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable; |
77 | unsigned short | 64 | SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable; |
78 | SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) | 65 | SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex; |
79 | { | 66 | SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table; |
80 | unsigned short ModeIndex = 0; | ||
81 | |||
82 | switch (HDisplay) | ||
83 | { | ||
84 | case 320: | ||
85 | if (VDisplay == 200) | ||
86 | ModeIndex = ModeIndex_320x200[Depth]; | ||
87 | else if (VDisplay == 240) | ||
88 | ModeIndex = ModeIndex_320x240[Depth]; | ||
89 | break; | ||
90 | case 400: | ||
91 | if (VDisplay == 300) | ||
92 | ModeIndex = ModeIndex_400x300[Depth]; | ||
93 | break; | ||
94 | case 512: | ||
95 | if (VDisplay == 384) | ||
96 | ModeIndex = ModeIndex_512x384[Depth]; | ||
97 | break; | ||
98 | case 640: | ||
99 | if (VDisplay == 480) | ||
100 | ModeIndex = ModeIndex_640x480[Depth]; | ||
101 | else if (VDisplay == 400) | ||
102 | ModeIndex = ModeIndex_640x400[Depth]; | ||
103 | break; | ||
104 | case 720: | ||
105 | if (VDisplay == 480) | ||
106 | ModeIndex = ModeIndex_720x480[Depth]; | ||
107 | else if (VDisplay == 576) | ||
108 | ModeIndex = ModeIndex_720x576[Depth]; | ||
109 | break; | ||
110 | case 768: | ||
111 | if (VDisplay == 576) | ||
112 | ModeIndex = ModeIndex_768x576[Depth]; | ||
113 | break; | ||
114 | case 800: | ||
115 | if (VDisplay == 600) | ||
116 | ModeIndex = ModeIndex_800x600[Depth]; | ||
117 | else if (VDisplay == 480) | ||
118 | ModeIndex = ModeIndex_800x480[Depth]; | ||
119 | break; | ||
120 | case 848: | ||
121 | if (VDisplay == 480) | ||
122 | ModeIndex = ModeIndex_848x480[Depth]; | ||
123 | break; | ||
124 | case 856: | ||
125 | if (VDisplay == 480) | ||
126 | ModeIndex = ModeIndex_856x480[Depth]; | ||
127 | break; | ||
128 | case 960: | ||
129 | if (VDisplay == 540) | ||
130 | ModeIndex = ModeIndex_960x540[Depth]; | ||
131 | else if (VDisplay == 600) | ||
132 | ModeIndex = ModeIndex_960x600[Depth]; | ||
133 | break; | ||
134 | case 1024: | ||
135 | if (VDisplay == 576) | ||
136 | ModeIndex = ModeIndex_1024x576[Depth]; | ||
137 | else if (VDisplay == 768) | ||
138 | ModeIndex = ModeIndex_1024x768[Depth]; | ||
139 | break; | ||
140 | case 1152: | ||
141 | if (VDisplay == 864) | ||
142 | ModeIndex = ModeIndex_1152x864[Depth]; | ||
143 | break; | ||
144 | case 1280: | ||
145 | switch (VDisplay) { | ||
146 | case 720: | ||
147 | ModeIndex = ModeIndex_1280x720[Depth]; | ||
148 | break; | ||
149 | case 768: | ||
150 | ModeIndex = ModeIndex_1280x768[Depth]; | ||
151 | break; | ||
152 | case 1024: | ||
153 | ModeIndex = ModeIndex_1280x1024[Depth]; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | 67 | ||
158 | return ModeIndex; | 68 | SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData; |
159 | } | 69 | } |
160 | #endif /* 0 */ | ||
161 | 70 | ||
162 | /*********************************************/ | 71 | /*********************************************/ |
163 | /* HELPER: SetReg, GetReg */ | 72 | /* HELPER: SetReg, GetReg */ |
@@ -165,21 +74,20 @@ SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) | |||
165 | 74 | ||
166 | static void | 75 | static void |
167 | SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port, | 76 | SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port, |
168 | unsigned short index, unsigned short data) | 77 | unsigned short index, unsigned short data) |
169 | { | 78 | { |
170 | sisusb_setidxreg(SiS_Pr->sisusb, port, index, data); | 79 | sisusb_setidxreg(SiS_Pr->sisusb, port, index, data); |
171 | } | 80 | } |
172 | 81 | ||
173 | static void | 82 | static void |
174 | SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port, | 83 | SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port, |
175 | unsigned short data) | 84 | unsigned short data) |
176 | { | 85 | { |
177 | sisusb_setreg(SiS_Pr->sisusb, port, data); | 86 | sisusb_setreg(SiS_Pr->sisusb, port, data); |
178 | } | 87 | } |
179 | 88 | ||
180 | static unsigned char | 89 | static unsigned char |
181 | SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, | 90 | SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index) |
182 | unsigned short index) | ||
183 | { | 91 | { |
184 | u8 data; | 92 | u8 data; |
185 | 93 | ||
@@ -200,22 +108,22 @@ SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port) | |||
200 | 108 | ||
201 | static void | 109 | static void |
202 | SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port, | 110 | SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port, |
203 | unsigned short index, unsigned short DataAND, | 111 | unsigned short index, unsigned short DataAND, |
204 | unsigned short DataOR) | 112 | unsigned short DataOR) |
205 | { | 113 | { |
206 | sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR); | 114 | sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR); |
207 | } | 115 | } |
208 | 116 | ||
209 | static void | 117 | static void |
210 | SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port, | 118 | SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port, |
211 | unsigned short index, unsigned short DataAND) | 119 | unsigned short index, unsigned short DataAND) |
212 | { | 120 | { |
213 | sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND); | 121 | sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND); |
214 | } | 122 | } |
215 | 123 | ||
216 | static void | 124 | static void |
217 | SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port, | 125 | SiS_SetRegOR(struct SiS_Private *SiS_Pr, unsigned long port, |
218 | unsigned short index, unsigned short DataOR) | 126 | unsigned short index, unsigned short DataOR) |
219 | { | 127 | { |
220 | sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR); | 128 | sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR); |
221 | } | 129 | } |
@@ -224,8 +132,7 @@ SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port, | |||
224 | /* HELPER: DisplayOn, DisplayOff */ | 132 | /* HELPER: DisplayOn, DisplayOff */ |
225 | /*********************************************/ | 133 | /*********************************************/ |
226 | 134 | ||
227 | static void | 135 | static void SiS_DisplayOn(struct SiS_Private *SiS_Pr) |
228 | SiS_DisplayOn(struct SiS_Private *SiS_Pr) | ||
229 | { | 136 | { |
230 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF); | 137 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF); |
231 | } | 138 | } |
@@ -234,8 +141,7 @@ SiS_DisplayOn(struct SiS_Private *SiS_Pr) | |||
234 | /* HELPER: Init Port Addresses */ | 141 | /* HELPER: Init Port Addresses */ |
235 | /*********************************************/ | 142 | /*********************************************/ |
236 | 143 | ||
237 | static void | 144 | static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) |
238 | SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) | ||
239 | { | 145 | { |
240 | SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; | 146 | SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; |
241 | SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; | 147 | SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; |
@@ -258,8 +164,7 @@ SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) | |||
258 | /* HELPER: GetSysFlags */ | 164 | /* HELPER: GetSysFlags */ |
259 | /*********************************************/ | 165 | /*********************************************/ |
260 | 166 | ||
261 | static void | 167 | static void SiS_GetSysFlags(struct SiS_Private *SiS_Pr) |
262 | SiS_GetSysFlags(struct SiS_Private *SiS_Pr) | ||
263 | { | 168 | { |
264 | SiS_Pr->SiS_MyCR63 = 0x63; | 169 | SiS_Pr->SiS_MyCR63 = 0x63; |
265 | } | 170 | } |
@@ -268,8 +173,7 @@ SiS_GetSysFlags(struct SiS_Private *SiS_Pr) | |||
268 | /* HELPER: Init PCI & Engines */ | 173 | /* HELPER: Init PCI & Engines */ |
269 | /*********************************************/ | 174 | /*********************************************/ |
270 | 175 | ||
271 | static void | 176 | static void SiSInitPCIetc(struct SiS_Private *SiS_Pr) |
272 | SiSInitPCIetc(struct SiS_Private *SiS_Pr) | ||
273 | { | 177 | { |
274 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1); | 178 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1); |
275 | /* - Enable 2D (0x40) | 179 | /* - Enable 2D (0x40) |
@@ -285,8 +189,7 @@ SiSInitPCIetc(struct SiS_Private *SiS_Pr) | |||
285 | /* HELPER: SET SEGMENT REGISTERS */ | 189 | /* HELPER: SET SEGMENT REGISTERS */ |
286 | /*********************************************/ | 190 | /*********************************************/ |
287 | 191 | ||
288 | static void | 192 | static void SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value) |
289 | SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value) | ||
290 | { | 193 | { |
291 | unsigned short temp; | 194 | unsigned short temp; |
292 | 195 | ||
@@ -299,8 +202,7 @@ SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value) | |||
299 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); | 202 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); |
300 | } | 203 | } |
301 | 204 | ||
302 | static void | 205 | static void SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value) |
303 | SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value) | ||
304 | { | 206 | { |
305 | unsigned short temp; | 207 | unsigned short temp; |
306 | 208 | ||
@@ -313,15 +215,13 @@ SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value) | |||
313 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); | 215 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp); |
314 | } | 216 | } |
315 | 217 | ||
316 | static void | 218 | static void SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value) |
317 | SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value) | ||
318 | { | 219 | { |
319 | SiS_SetSegRegLower(SiS_Pr, value); | 220 | SiS_SetSegRegLower(SiS_Pr, value); |
320 | SiS_SetSegRegUpper(SiS_Pr, value); | 221 | SiS_SetSegRegUpper(SiS_Pr, value); |
321 | } | 222 | } |
322 | 223 | ||
323 | static void | 224 | static void SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr) |
324 | SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr) | ||
325 | { | 225 | { |
326 | SiS_SetSegmentReg(SiS_Pr, 0); | 226 | SiS_SetSegmentReg(SiS_Pr, 0); |
327 | } | 227 | } |
@@ -337,14 +237,12 @@ SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value) | |||
337 | SiS_SetSegmentReg(SiS_Pr, value); | 237 | SiS_SetSegmentReg(SiS_Pr, value); |
338 | } | 238 | } |
339 | 239 | ||
340 | static void | 240 | static void SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr) |
341 | SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr) | ||
342 | { | 241 | { |
343 | SiS_SetSegmentRegOver(SiS_Pr, 0); | 242 | SiS_SetSegmentRegOver(SiS_Pr, 0); |
344 | } | 243 | } |
345 | 244 | ||
346 | static void | 245 | static void SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr) |
347 | SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr) | ||
348 | { | 246 | { |
349 | SiS_ResetSegmentReg(SiS_Pr); | 247 | SiS_ResetSegmentReg(SiS_Pr); |
350 | SiS_ResetSegmentRegOver(SiS_Pr); | 248 | SiS_ResetSegmentRegOver(SiS_Pr); |
@@ -356,7 +254,7 @@ SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr) | |||
356 | 254 | ||
357 | static int | 255 | static int |
358 | SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, | 256 | SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, |
359 | unsigned short *ModeIdIndex) | 257 | unsigned short *ModeIdIndex) |
360 | { | 258 | { |
361 | if ((*ModeNo) <= 0x13) { | 259 | if ((*ModeNo) <= 0x13) { |
362 | 260 | ||
@@ -367,12 +265,14 @@ SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, | |||
367 | 265 | ||
368 | } else { | 266 | } else { |
369 | 267 | ||
370 | for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { | 268 | for (*ModeIdIndex = 0;; (*ModeIdIndex)++) { |
371 | 269 | ||
372 | if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) | 270 | if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == |
271 | (*ModeNo)) | ||
373 | break; | 272 | break; |
374 | 273 | ||
375 | if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) | 274 | if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == |
275 | 0xFF) | ||
376 | return 0; | 276 | return 0; |
377 | } | 277 | } |
378 | 278 | ||
@@ -385,8 +285,7 @@ SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, | |||
385 | /* HELPER: ENABLE CRT1 */ | 285 | /* HELPER: ENABLE CRT1 */ |
386 | /*********************************************/ | 286 | /*********************************************/ |
387 | 287 | ||
388 | static void | 288 | static void SiS_HandleCRT1(struct SiS_Private *SiS_Pr) |
389 | SiS_HandleCRT1(struct SiS_Private *SiS_Pr) | ||
390 | { | 289 | { |
391 | /* Enable CRT1 gating */ | 290 | /* Enable CRT1 gating */ |
392 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf); | 291 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf); |
@@ -398,9 +297,9 @@ SiS_HandleCRT1(struct SiS_Private *SiS_Pr) | |||
398 | 297 | ||
399 | static unsigned short | 298 | static unsigned short |
400 | SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 299 | SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
401 | unsigned short ModeIdIndex) | 300 | unsigned short ModeIdIndex) |
402 | { | 301 | { |
403 | static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8}; | 302 | static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 }; |
404 | unsigned short modeflag; | 303 | unsigned short modeflag; |
405 | short index; | 304 | short index; |
406 | 305 | ||
@@ -411,7 +310,8 @@ SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
411 | } | 310 | } |
412 | 311 | ||
413 | index = (modeflag & ModeTypeMask) - ModeEGA; | 312 | index = (modeflag & ModeTypeMask) - ModeEGA; |
414 | if (index < 0) index = 0; | 313 | if (index < 0) |
314 | index = 0; | ||
415 | return ColorDepth[index]; | 315 | return ColorDepth[index]; |
416 | } | 316 | } |
417 | 317 | ||
@@ -421,7 +321,7 @@ SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
421 | 321 | ||
422 | static unsigned short | 322 | static unsigned short |
423 | SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 323 | SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
424 | unsigned short ModeIdIndex, unsigned short rrti) | 324 | unsigned short ModeIdIndex, unsigned short rrti) |
425 | { | 325 | { |
426 | unsigned short xres, temp, colordepth, infoflag; | 326 | unsigned short xres, temp, colordepth, infoflag; |
427 | 327 | ||
@@ -458,8 +358,8 @@ SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) | |||
458 | SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20; | 358 | SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20; |
459 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata); | 359 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata); |
460 | 360 | ||
461 | for(i = 2; i <= 4; i++) { | 361 | for (i = 2; i <= 4; i++) { |
462 | SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; | 362 | SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1]; |
463 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata); | 363 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata); |
464 | } | 364 | } |
465 | } | 365 | } |
@@ -488,7 +388,7 @@ SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) | |||
488 | 388 | ||
489 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); | 389 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); |
490 | 390 | ||
491 | for(i = 0; i <= 0x18; i++) { | 391 | for (i = 0; i <= 0x18; i++) { |
492 | CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; | 392 | CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; |
493 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata); | 393 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata); |
494 | } | 394 | } |
@@ -504,7 +404,7 @@ SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) | |||
504 | unsigned char ARdata; | 404 | unsigned char ARdata; |
505 | unsigned short i; | 405 | unsigned short i; |
506 | 406 | ||
507 | for(i = 0; i <= 0x13; i++) { | 407 | for (i = 0; i <= 0x13; i++) { |
508 | ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; | 408 | ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; |
509 | SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); | 409 | SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); |
510 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i); | 410 | SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i); |
@@ -529,7 +429,7 @@ SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) | |||
529 | unsigned char GRdata; | 429 | unsigned char GRdata; |
530 | unsigned short i; | 430 | unsigned short i; |
531 | 431 | ||
532 | for(i = 0; i <= 0x08; i++) { | 432 | for (i = 0; i <= 0x08; i++) { |
533 | GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; | 433 | GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; |
534 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata); | 434 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata); |
535 | } | 435 | } |
@@ -544,12 +444,11 @@ SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex) | |||
544 | /* CLEAR EXTENDED REGISTERS */ | 444 | /* CLEAR EXTENDED REGISTERS */ |
545 | /*********************************************/ | 445 | /*********************************************/ |
546 | 446 | ||
547 | static void | 447 | static void SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo) |
548 | SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | ||
549 | { | 448 | { |
550 | int i; | 449 | int i; |
551 | 450 | ||
552 | for(i = 0x0A; i <= 0x0E; i++) { | 451 | for (i = 0x0A; i <= 0x0E; i++) { |
553 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00); | 452 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00); |
554 | } | 453 | } |
555 | 454 | ||
@@ -562,15 +461,16 @@ SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | |||
562 | 461 | ||
563 | static unsigned short | 462 | static unsigned short |
564 | SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 463 | SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
565 | unsigned short ModeIdIndex) | 464 | unsigned short ModeIdIndex) |
566 | { | 465 | { |
567 | unsigned short rrti, i, index, temp; | 466 | unsigned short rrti, i, index, temp; |
568 | 467 | ||
569 | if (ModeNo <= 0x13) | 468 | if (ModeNo <= 0x13) |
570 | return 0xFFFF; | 469 | return 0xFFFF; |
571 | 470 | ||
572 | index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F; | 471 | index = SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x33) & 0x0F; |
573 | if (index > 0) index--; | 472 | if (index > 0) |
473 | index--; | ||
574 | 474 | ||
575 | rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; | 475 | rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; |
576 | ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID; | 476 | ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID; |
@@ -580,13 +480,14 @@ SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
580 | if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo) | 480 | if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo) |
581 | break; | 481 | break; |
582 | 482 | ||
583 | temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask; | 483 | temp = |
484 | SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask; | ||
584 | if (temp < SiS_Pr->SiS_ModeType) | 485 | if (temp < SiS_Pr->SiS_ModeType) |
585 | break; | 486 | break; |
586 | 487 | ||
587 | i++; | 488 | i++; |
588 | index--; | 489 | index--; |
589 | } while(index != 0xFFFF); | 490 | } while (index != 0xFFFF); |
590 | 491 | ||
591 | i--; | 492 | i--; |
592 | 493 | ||
@@ -597,8 +498,7 @@ SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
597 | /* SYNC */ | 498 | /* SYNC */ |
598 | /*********************************************/ | 499 | /*********************************************/ |
599 | 500 | ||
600 | static void | 501 | static void SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti) |
601 | SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti) | ||
602 | { | 502 | { |
603 | unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8; | 503 | unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8; |
604 | sync &= 0xC0; | 504 | sync &= 0xC0; |
@@ -612,39 +512,40 @@ SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti) | |||
612 | 512 | ||
613 | static void | 513 | static void |
614 | SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 514 | SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
615 | unsigned short ModeIdIndex, unsigned short rrti) | 515 | unsigned short ModeIdIndex, unsigned short rrti) |
616 | { | 516 | { |
617 | unsigned char index; | 517 | unsigned char index; |
618 | unsigned short temp, i, j, modeflag; | 518 | unsigned short temp, i, j, modeflag; |
619 | 519 | ||
620 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f); | 520 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); |
621 | 521 | ||
622 | modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; | 522 | modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; |
623 | 523 | ||
624 | index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC; | 524 | index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC; |
625 | 525 | ||
626 | for(i = 0,j = 0; i <= 7; i++, j++) { | 526 | for (i = 0, j = 0; i <= 7; i++, j++) { |
627 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, | 527 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, |
628 | SiS_Pr->SiS_CRT1Table[index].CR[i]); | 528 | SiS_Pr->SiS_CRT1Table[index].CR[i]); |
629 | } | 529 | } |
630 | for(j = 0x10; i <= 10; i++, j++) { | 530 | for (j = 0x10; i <= 10; i++, j++) { |
631 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, | 531 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, |
632 | SiS_Pr->SiS_CRT1Table[index].CR[i]); | 532 | SiS_Pr->SiS_CRT1Table[index].CR[i]); |
633 | } | 533 | } |
634 | for(j = 0x15; i <= 12; i++, j++) { | 534 | for (j = 0x15; i <= 12; i++, j++) { |
635 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, | 535 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j, |
636 | SiS_Pr->SiS_CRT1Table[index].CR[i]); | 536 | SiS_Pr->SiS_CRT1Table[index].CR[i]); |
637 | } | 537 | } |
638 | for(j = 0x0A; i <= 15; i++, j++) { | 538 | for (j = 0x0A; i <= 15; i++, j++) { |
639 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j, | 539 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j, |
640 | SiS_Pr->SiS_CRT1Table[index].CR[i]); | 540 | SiS_Pr->SiS_CRT1Table[index].CR[i]); |
641 | } | 541 | } |
642 | 542 | ||
643 | temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; | 543 | temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; |
644 | SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp); | 544 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, temp); |
645 | 545 | ||
646 | temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; | 546 | temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; |
647 | if (modeflag & DoubleScanMode) temp |= 0x80; | 547 | if (modeflag & DoubleScanMode) |
548 | temp |= 0x80; | ||
648 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp); | 549 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp); |
649 | 550 | ||
650 | if (SiS_Pr->SiS_ModeType > ModeVGA) | 551 | if (SiS_Pr->SiS_ModeType > ModeVGA) |
@@ -659,10 +560,10 @@ SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
659 | 560 | ||
660 | static void | 561 | static void |
661 | SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 562 | SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
662 | unsigned short ModeIdIndex, unsigned short rrti) | 563 | unsigned short ModeIdIndex, unsigned short rrti) |
663 | { | 564 | { |
664 | unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti); | 565 | unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti); |
665 | unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; | 566 | unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; |
666 | unsigned short temp; | 567 | unsigned short temp; |
667 | 568 | ||
668 | temp = (du >> 8) & 0x0f; | 569 | temp = (du >> 8) & 0x0f; |
@@ -670,11 +571,13 @@ SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
670 | 571 | ||
671 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF)); | 572 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF)); |
672 | 573 | ||
673 | if (infoflag & InterlaceMode) du >>= 1; | 574 | if (infoflag & InterlaceMode) |
575 | du >>= 1; | ||
674 | 576 | ||
675 | du <<= 5; | 577 | du <<= 5; |
676 | temp = (du >> 8) & 0xff; | 578 | temp = (du >> 8) & 0xff; |
677 | if (du & 0xff) temp++; | 579 | if (du & 0xff) |
580 | temp++; | ||
678 | temp++; | 581 | temp++; |
679 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp); | 582 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp); |
680 | } | 583 | } |
@@ -685,17 +588,17 @@ SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
685 | 588 | ||
686 | static void | 589 | static void |
687 | SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 590 | SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
688 | unsigned short rrti) | 591 | unsigned short rrti) |
689 | { | 592 | { |
690 | unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; | 593 | unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK; |
691 | unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B; | 594 | unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B; |
692 | unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C; | 595 | unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C; |
693 | 596 | ||
694 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF); | 597 | SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xCF); |
695 | 598 | ||
696 | SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka); | 599 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2B, clka); |
697 | SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb); | 600 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2C, clkb); |
698 | SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01); | 601 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x2D, 0x01); |
699 | } | 602 | } |
700 | 603 | ||
701 | /*********************************************/ | 604 | /*********************************************/ |
@@ -704,7 +607,7 @@ SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
704 | 607 | ||
705 | static void | 608 | static void |
706 | SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 609 | SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
707 | unsigned short mi) | 610 | unsigned short mi) |
708 | { | 611 | { |
709 | unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; | 612 | unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag; |
710 | 613 | ||
@@ -729,7 +632,7 @@ SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
729 | 632 | ||
730 | static void | 633 | static void |
731 | SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 634 | SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
732 | unsigned short rrti) | 635 | unsigned short rrti) |
733 | { | 636 | { |
734 | unsigned short data = 0, VCLK = 0, index = 0; | 637 | unsigned short data = 0, VCLK = 0, index = 0; |
735 | 638 | ||
@@ -738,7 +641,8 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
738 | VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; | 641 | VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; |
739 | } | 642 | } |
740 | 643 | ||
741 | if (VCLK >= 166) data |= 0x0c; | 644 | if (VCLK >= 166) |
645 | data |= 0x0c; | ||
742 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data); | 646 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data); |
743 | 647 | ||
744 | if (VCLK >= 166) | 648 | if (VCLK >= 166) |
@@ -758,7 +662,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
758 | 662 | ||
759 | static void | 663 | static void |
760 | SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 664 | SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
761 | unsigned short ModeIdIndex, unsigned short rrti) | 665 | unsigned short ModeIdIndex, unsigned short rrti) |
762 | { | 666 | { |
763 | unsigned short data, infoflag = 0, modeflag; | 667 | unsigned short data, infoflag = 0, modeflag; |
764 | 668 | ||
@@ -778,17 +682,22 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
778 | data |= 0x02; | 682 | data |= 0x02; |
779 | data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); | 683 | data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); |
780 | } | 684 | } |
781 | if (infoflag & InterlaceMode) data |= 0x20; | 685 | if (infoflag & InterlaceMode) |
686 | data |= 0x20; | ||
782 | } | 687 | } |
783 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data); | 688 | SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data); |
784 | 689 | ||
785 | data = 0; | 690 | data = 0; |
786 | if (infoflag & InterlaceMode) { | 691 | if (infoflag & InterlaceMode) { |
787 | /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */ | 692 | /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */ |
788 | unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) | | 693 | unsigned short hrs = |
789 | ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3; | 694 | (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) | |
790 | unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) | | 695 | ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) |
791 | ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5; | 696 | - 3; |
697 | unsigned short hto = | ||
698 | (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) | | ||
699 | ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) | ||
700 | + 5; | ||
792 | data = hrs - (hto >> 1) + 3; | 701 | data = hrs - (hto >> 1) + 3; |
793 | } | 702 | } |
794 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF)); | 703 | SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF)); |
@@ -829,20 +738,26 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
829 | 738 | ||
830 | static void | 739 | static void |
831 | SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData, | 740 | SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData, |
832 | unsigned short shiftflag, unsigned short dl, unsigned short ah, | 741 | unsigned short shiftflag, unsigned short dl, unsigned short ah, |
833 | unsigned short al, unsigned short dh) | 742 | unsigned short al, unsigned short dh) |
834 | { | 743 | { |
835 | unsigned short d1, d2, d3; | 744 | unsigned short d1, d2, d3; |
836 | 745 | ||
837 | switch (dl) { | 746 | switch (dl) { |
838 | case 0: | 747 | case 0: |
839 | d1 = dh; d2 = ah; d3 = al; | 748 | d1 = dh; |
840 | break; | 749 | d2 = ah; |
841 | case 1: | 750 | d3 = al; |
842 | d1 = ah; d2 = al; d3 = dh; | 751 | break; |
843 | break; | 752 | case 1: |
844 | default: | 753 | d1 = ah; |
845 | d1 = al; d2 = dh; d3 = ah; | 754 | d2 = al; |
755 | d3 = dh; | ||
756 | break; | ||
757 | default: | ||
758 | d1 = al; | ||
759 | d2 = dh; | ||
760 | d3 = ah; | ||
846 | } | 761 | } |
847 | SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag)); | 762 | SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag)); |
848 | SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag)); | 763 | SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag)); |
@@ -850,7 +765,8 @@ SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData, | |||
850 | } | 765 | } |
851 | 766 | ||
852 | static void | 767 | static void |
853 | SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi) | 768 | SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
769 | unsigned short mi) | ||
854 | { | 770 | { |
855 | unsigned short data, data2, time, i, j, k, m, n, o; | 771 | unsigned short data, data2, time, i, j, k, m, n, o; |
856 | unsigned short si, di, bx, sf; | 772 | unsigned short si, di, bx, sf; |
@@ -884,41 +800,45 @@ SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi | |||
884 | 800 | ||
885 | SiS_SetRegByte(SiS_Pr, DACAddr, 0x00); | 801 | SiS_SetRegByte(SiS_Pr, DACAddr, 0x00); |
886 | 802 | ||
887 | for(i = 0; i < j; i++) { | 803 | for (i = 0; i < j; i++) { |
888 | data = table[i]; | 804 | data = table[i]; |
889 | for(k = 0; k < 3; k++) { | 805 | for (k = 0; k < 3; k++) { |
890 | data2 = 0; | 806 | data2 = 0; |
891 | if (data & 0x01) data2 += 0x2A; | 807 | if (data & 0x01) |
892 | if (data & 0x02) data2 += 0x15; | 808 | data2 += 0x2A; |
809 | if (data & 0x02) | ||
810 | data2 += 0x15; | ||
893 | SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf)); | 811 | SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf)); |
894 | data >>= 2; | 812 | data >>= 2; |
895 | } | 813 | } |
896 | } | 814 | } |
897 | 815 | ||
898 | if (time == 256) { | 816 | if (time == 256) { |
899 | for(i = 16; i < 32; i++) { | 817 | for (i = 16; i < 32; i++) { |
900 | data = table[i] << sf; | 818 | data = table[i] << sf; |
901 | for(k = 0; k < 3; k++) | 819 | for (k = 0; k < 3; k++) |
902 | SiS_SetRegByte(SiS_Pr, DACData, data); | 820 | SiS_SetRegByte(SiS_Pr, DACData, data); |
903 | } | 821 | } |
904 | si = 32; | 822 | si = 32; |
905 | for(m = 0; m < 9; m++) { | 823 | for (m = 0; m < 9; m++) { |
906 | di = si; | 824 | di = si; |
907 | bx = si + 4; | 825 | bx = si + 4; |
908 | for(n = 0; n < 3; n++) { | 826 | for (n = 0; n < 3; n++) { |
909 | for(o = 0; o < 5; o++) { | 827 | for (o = 0; o < 5; o++) { |
910 | SiS_WriteDAC(SiS_Pr, DACData, sf, n, | 828 | SiS_WriteDAC(SiS_Pr, DACData, sf, n, |
911 | table[di], table[bx], table[si]); | 829 | table[di], table[bx], |
830 | table[si]); | ||
912 | si++; | 831 | si++; |
913 | } | 832 | } |
914 | si -= 2; | 833 | si -= 2; |
915 | for(o = 0; o < 3; o++) { | 834 | for (o = 0; o < 3; o++) { |
916 | SiS_WriteDAC(SiS_Pr, DACData, sf, n, | 835 | SiS_WriteDAC(SiS_Pr, DACData, sf, n, |
917 | table[di], table[si], table[bx]); | 836 | table[di], table[si], |
837 | table[bx]); | ||
918 | si--; | 838 | si--; |
919 | } | 839 | } |
920 | } | 840 | } |
921 | si += 5; | 841 | si += 5; |
922 | } | 842 | } |
923 | } | 843 | } |
924 | } | 844 | } |
@@ -929,7 +849,7 @@ SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi | |||
929 | 849 | ||
930 | static void | 850 | static void |
931 | SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | 851 | SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, |
932 | unsigned short ModeIdIndex) | 852 | unsigned short ModeIdIndex) |
933 | { | 853 | { |
934 | unsigned short StandTableIndex, rrti; | 854 | unsigned short StandTableIndex, rrti; |
935 | 855 | ||
@@ -970,11 +890,10 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, | |||
970 | /* SiSSetMode() */ | 890 | /* SiSSetMode() */ |
971 | /*********************************************/ | 891 | /*********************************************/ |
972 | 892 | ||
973 | int | 893 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) |
974 | SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | ||
975 | { | 894 | { |
976 | unsigned short ModeIdIndex; | 895 | unsigned short ModeIdIndex; |
977 | unsigned long BaseAddr = SiS_Pr->IOAddress; | 896 | unsigned long BaseAddr = SiS_Pr->IOAddress; |
978 | 897 | ||
979 | SiSUSB_InitPtr(SiS_Pr); | 898 | SiSUSB_InitPtr(SiS_Pr); |
980 | SiSUSBRegInit(SiS_Pr, BaseAddr); | 899 | SiSUSBRegInit(SiS_Pr, BaseAddr); |
@@ -990,7 +909,7 @@ SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | |||
990 | ModeNo &= 0x7f; | 909 | ModeNo &= 0x7f; |
991 | 910 | ||
992 | SiS_Pr->SiS_ModeType = | 911 | SiS_Pr->SiS_ModeType = |
993 | SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask; | 912 | SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask; |
994 | 913 | ||
995 | SiS_Pr->SiS_SetFlag = LowModeTests; | 914 | SiS_Pr->SiS_SetFlag = LowModeTests; |
996 | 915 | ||
@@ -1008,8 +927,7 @@ SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | |||
1008 | return 1; | 927 | return 1; |
1009 | } | 928 | } |
1010 | 929 | ||
1011 | int | 930 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo) |
1012 | SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo) | ||
1013 | { | 931 | { |
1014 | unsigned short ModeNo = 0; | 932 | unsigned short ModeNo = 0; |
1015 | int i; | 933 | int i; |
@@ -1041,7 +959,3 @@ SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo) | |||
1041 | } | 959 | } |
1042 | 960 | ||
1043 | #endif /* INCL_SISUSB_CON */ | 961 | #endif /* INCL_SISUSB_CON */ |
1044 | |||
1045 | |||
1046 | |||
1047 | |||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index 864bc0e96591..c46ce42d4489 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h | |||
@@ -46,7 +46,7 @@ | |||
46 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 46 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
47 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 47 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
48 | * | 48 | * |
49 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 49 | * Author: Thomas Winischhofer <thomas@winischhofer.net> |
50 | * | 50 | * |
51 | */ | 51 | */ |
52 | 52 | ||
@@ -76,21 +76,21 @@ | |||
76 | #define CRT2Mode 0x0800 | 76 | #define CRT2Mode 0x0800 |
77 | #define HalfDCLK 0x1000 | 77 | #define HalfDCLK 0x1000 |
78 | #define NoSupportSimuTV 0x2000 | 78 | #define NoSupportSimuTV 0x2000 |
79 | #define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */ | 79 | #define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */ |
80 | #define DoubleScanMode 0x8000 | 80 | #define DoubleScanMode 0x8000 |
81 | 81 | ||
82 | /* Infoflag */ | 82 | /* Infoflag */ |
83 | #define SupportTV 0x0008 | 83 | #define SupportTV 0x0008 |
84 | #define SupportTV1024 0x0800 | 84 | #define SupportTV1024 0x0800 |
85 | #define SupportCHTV 0x0800 | 85 | #define SupportCHTV 0x0800 |
86 | #define Support64048060Hz 0x0800 /* Special for 640x480 LCD */ | 86 | #define Support64048060Hz 0x0800 /* Special for 640x480 LCD */ |
87 | #define SupportHiVision 0x0010 | 87 | #define SupportHiVision 0x0010 |
88 | #define SupportYPbPr750p 0x1000 | 88 | #define SupportYPbPr750p 0x1000 |
89 | #define SupportLCD 0x0020 | 89 | #define SupportLCD 0x0020 |
90 | #define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */ | 90 | #define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */ |
91 | #define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */ | 91 | #define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */ |
92 | #define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */ | 92 | #define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */ |
93 | #define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */ | 93 | #define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */ |
94 | #define InterlaceMode 0x0080 | 94 | #define InterlaceMode 0x0080 |
95 | #define SyncPP 0x0000 | 95 | #define SyncPP 0x0000 |
96 | #define SyncPN 0x4000 | 96 | #define SyncPN 0x4000 |
@@ -129,7 +129,7 @@ | |||
129 | #define SIS_RI_856x480 19 | 129 | #define SIS_RI_856x480 19 |
130 | #define SIS_RI_1280x768 20 | 130 | #define SIS_RI_1280x768 20 |
131 | #define SIS_RI_1400x1050 21 | 131 | #define SIS_RI_1400x1050 21 |
132 | #define SIS_RI_1152x864 22 /* Up to here SiS conforming */ | 132 | #define SIS_RI_1152x864 22 /* Up to here SiS conforming */ |
133 | #define SIS_RI_848x480 23 | 133 | #define SIS_RI_848x480 23 |
134 | #define SIS_RI_1360x768 24 | 134 | #define SIS_RI_1360x768 24 |
135 | #define SIS_RI_1024x600 25 | 135 | #define SIS_RI_1024x600 25 |
@@ -147,691 +147,691 @@ | |||
147 | #define SIS_CRT2_PORT_04 0x04 - 0x30 | 147 | #define SIS_CRT2_PORT_04 0x04 - 0x30 |
148 | 148 | ||
149 | /* Mode numbers */ | 149 | /* Mode numbers */ |
150 | static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f}; | 150 | static const unsigned short ModeIndex_320x200[] = { 0x59, 0x41, 0x00, 0x4f }; |
151 | static const unsigned short ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53}; | 151 | static const unsigned short ModeIndex_320x240[] = { 0x50, 0x56, 0x00, 0x53 }; |
152 | static const unsigned short ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54}; | 152 | static const unsigned short ModeIndex_400x300[] = { 0x51, 0x57, 0x00, 0x54 }; |
153 | static const unsigned short ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c}; | 153 | static const unsigned short ModeIndex_512x384[] = { 0x52, 0x58, 0x00, 0x5c }; |
154 | static const unsigned short ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e}; | 154 | static const unsigned short ModeIndex_640x400[] = { 0x2f, 0x5d, 0x00, 0x5e }; |
155 | static const unsigned short ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62}; | 155 | static const unsigned short ModeIndex_640x480[] = { 0x2e, 0x44, 0x00, 0x62 }; |
156 | static const unsigned short ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35}; | 156 | static const unsigned short ModeIndex_720x480[] = { 0x31, 0x33, 0x00, 0x35 }; |
157 | static const unsigned short ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36}; | 157 | static const unsigned short ModeIndex_720x576[] = { 0x32, 0x34, 0x00, 0x36 }; |
158 | static const unsigned short ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61}; | 158 | static const unsigned short ModeIndex_768x576[] = { 0x5f, 0x60, 0x00, 0x61 }; |
159 | static const unsigned short ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76}; | 159 | static const unsigned short ModeIndex_800x480[] = { 0x70, 0x7a, 0x00, 0x76 }; |
160 | static const unsigned short ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63}; | 160 | static const unsigned short ModeIndex_800x600[] = { 0x30, 0x47, 0x00, 0x63 }; |
161 | static const unsigned short ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e}; | 161 | static const unsigned short ModeIndex_848x480[] = { 0x39, 0x3b, 0x00, 0x3e }; |
162 | static const unsigned short ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45}; | 162 | static const unsigned short ModeIndex_856x480[] = { 0x3f, 0x42, 0x00, 0x45 }; |
163 | static const unsigned short ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; | 163 | static const unsigned short ModeIndex_960x540[] = { 0x1d, 0x1e, 0x00, 0x1f }; |
164 | static const unsigned short ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; | 164 | static const unsigned short ModeIndex_960x600[] = { 0x20, 0x21, 0x00, 0x22 }; |
165 | static const unsigned short ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64}; | 165 | static const unsigned short ModeIndex_1024x768[] = { 0x38, 0x4a, 0x00, 0x64 }; |
166 | static const unsigned short ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77}; | 166 | static const unsigned short ModeIndex_1024x576[] = { 0x71, 0x74, 0x00, 0x77 }; |
167 | static const unsigned short ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b}; | 167 | static const unsigned short ModeIndex_1152x864[] = { 0x29, 0x2a, 0x00, 0x2b }; |
168 | static const unsigned short ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78}; | 168 | static const unsigned short ModeIndex_1280x720[] = { 0x79, 0x75, 0x00, 0x78 }; |
169 | static const unsigned short ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25}; | 169 | static const unsigned short ModeIndex_1280x768[] = { 0x23, 0x24, 0x00, 0x25 }; |
170 | static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65}; | 170 | static const unsigned short ModeIndex_1280x1024[] = { 0x3a, 0x4d, 0x00, 0x65 }; |
171 | 171 | ||
172 | static const unsigned char SiS_MDA_DAC[] = | 172 | static const unsigned char SiS_MDA_DAC[] = { |
173 | { | 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
174 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 174 | 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, |
175 | 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, | 175 | 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, |
176 | 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, | 176 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, |
177 | 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, | 177 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
178 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 178 | 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, |
179 | 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, | 179 | 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, |
180 | 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, | 180 | 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F |
181 | 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F | ||
182 | }; | 181 | }; |
183 | 182 | ||
184 | static const unsigned char SiS_CGA_DAC[] = | 183 | static const unsigned char SiS_CGA_DAC[] = { |
185 | { | 184 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, |
186 | 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, | 185 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, |
187 | 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, | 186 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, |
188 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, | 187 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, |
189 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, | 188 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, |
190 | 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, | 189 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, |
191 | 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, | 190 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, |
192 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, | 191 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F |
193 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F | ||
194 | }; | 192 | }; |
195 | 193 | ||
196 | static const unsigned char SiS_EGA_DAC[] = | 194 | static const unsigned char SiS_EGA_DAC[] = { |
197 | { | 195 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x05, 0x15, |
198 | 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15, | 196 | 0x20, 0x30, 0x24, 0x34, 0x21, 0x31, 0x25, 0x35, |
199 | 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35, | 197 | 0x08, 0x18, 0x0C, 0x1C, 0x09, 0x19, 0x0D, 0x1D, |
200 | 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D, | 198 | 0x28, 0x38, 0x2C, 0x3C, 0x29, 0x39, 0x2D, 0x3D, |
201 | 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D, | 199 | 0x02, 0x12, 0x06, 0x16, 0x03, 0x13, 0x07, 0x17, |
202 | 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17, | 200 | 0x22, 0x32, 0x26, 0x36, 0x23, 0x33, 0x27, 0x37, |
203 | 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37, | 201 | 0x0A, 0x1A, 0x0E, 0x1E, 0x0B, 0x1B, 0x0F, 0x1F, |
204 | 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F, | 202 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F |
205 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F | ||
206 | }; | 203 | }; |
207 | 204 | ||
208 | static const unsigned char SiS_VGA_DAC[] = | 205 | static const unsigned char SiS_VGA_DAC[] = { |
209 | { | 206 | 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, |
210 | 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, | 207 | 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, |
211 | 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, | 208 | 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18, |
212 | 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18, | 209 | 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F, |
213 | 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F, | 210 | 0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F, |
214 | 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F, | 211 | 0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00, |
215 | 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00, | 212 | 0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18, |
216 | 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18, | 213 | 0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04, |
217 | 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04, | 214 | 0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10, |
218 | 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10, | 215 | 0x0B, 0x0C, 0x0D, 0x0F, 0x10 |
219 | 0x0B,0x0C,0x0D,0x0F,0x10 | ||
220 | }; | 216 | }; |
221 | 217 | ||
222 | static const struct SiS_St SiSUSB_SModeIDTable[] = | 218 | static const struct SiS_St SiSUSB_SModeIDTable[] = { |
223 | { | 219 | {0x03, 0x0010, 0x18, 0x02, 0x02, 0x00, 0x01, 0x03, 0x40}, |
224 | {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40}, | 220 | {0xff, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} |
225 | {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00} | ||
226 | }; | 221 | }; |
227 | 222 | ||
228 | static const struct SiS_StResInfo_S SiSUSB_StResInfo[] = | 223 | static const struct SiS_StResInfo_S SiSUSB_StResInfo[] = { |
229 | { | 224 | {640, 400}, |
230 | { 640,400}, | 225 | {640, 350}, |
231 | { 640,350}, | 226 | {720, 400}, |
232 | { 720,400}, | 227 | {720, 350}, |
233 | { 720,350}, | 228 | {640, 480} |
234 | { 640,480} | ||
235 | }; | 229 | }; |
236 | 230 | ||
237 | static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] = | 231 | static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] = { |
238 | { | 232 | {320, 200, 8, 8}, /* 0x00 */ |
239 | { 320, 200, 8, 8}, /* 0x00 */ | 233 | {320, 240, 8, 8}, /* 0x01 */ |
240 | { 320, 240, 8, 8}, /* 0x01 */ | 234 | {320, 400, 8, 8}, /* 0x02 */ |
241 | { 320, 400, 8, 8}, /* 0x02 */ | 235 | {400, 300, 8, 8}, /* 0x03 */ |
242 | { 400, 300, 8, 8}, /* 0x03 */ | 236 | {512, 384, 8, 8}, /* 0x04 */ |
243 | { 512, 384, 8, 8}, /* 0x04 */ | 237 | {640, 400, 8, 16}, /* 0x05 */ |
244 | { 640, 400, 8,16}, /* 0x05 */ | 238 | {640, 480, 8, 16}, /* 0x06 */ |
245 | { 640, 480, 8,16}, /* 0x06 */ | 239 | {800, 600, 8, 16}, /* 0x07 */ |
246 | { 800, 600, 8,16}, /* 0x07 */ | 240 | {1024, 768, 8, 16}, /* 0x08 */ |
247 | { 1024, 768, 8,16}, /* 0x08 */ | 241 | {1280, 1024, 8, 16}, /* 0x09 */ |
248 | { 1280,1024, 8,16}, /* 0x09 */ | 242 | {1600, 1200, 8, 16}, /* 0x0a */ |
249 | { 1600,1200, 8,16}, /* 0x0a */ | 243 | {1920, 1440, 8, 16}, /* 0x0b */ |
250 | { 1920,1440, 8,16}, /* 0x0b */ | 244 | {2048, 1536, 8, 16}, /* 0x0c */ |
251 | { 2048,1536, 8,16}, /* 0x0c */ | 245 | {720, 480, 8, 16}, /* 0x0d */ |
252 | { 720, 480, 8,16}, /* 0x0d */ | 246 | {720, 576, 8, 16}, /* 0x0e */ |
253 | { 720, 576, 8,16}, /* 0x0e */ | 247 | {1280, 960, 8, 16}, /* 0x0f */ |
254 | { 1280, 960, 8,16}, /* 0x0f */ | 248 | {800, 480, 8, 16}, /* 0x10 */ |
255 | { 800, 480, 8,16}, /* 0x10 */ | 249 | {1024, 576, 8, 16}, /* 0x11 */ |
256 | { 1024, 576, 8,16}, /* 0x11 */ | 250 | {1280, 720, 8, 16}, /* 0x12 */ |
257 | { 1280, 720, 8,16}, /* 0x12 */ | 251 | {856, 480, 8, 16}, /* 0x13 */ |
258 | { 856, 480, 8,16}, /* 0x13 */ | 252 | {1280, 768, 8, 16}, /* 0x14 */ |
259 | { 1280, 768, 8,16}, /* 0x14 */ | 253 | {1400, 1050, 8, 16}, /* 0x15 */ |
260 | { 1400,1050, 8,16}, /* 0x15 */ | 254 | {1152, 864, 8, 16}, /* 0x16 */ |
261 | { 1152, 864, 8,16}, /* 0x16 */ | 255 | {848, 480, 8, 16}, /* 0x17 */ |
262 | { 848, 480, 8,16}, /* 0x17 */ | 256 | {1360, 768, 8, 16}, /* 0x18 */ |
263 | { 1360, 768, 8,16}, /* 0x18 */ | 257 | {1024, 600, 8, 16}, /* 0x19 */ |
264 | { 1024, 600, 8,16}, /* 0x19 */ | 258 | {1152, 768, 8, 16}, /* 0x1a */ |
265 | { 1152, 768, 8,16}, /* 0x1a */ | 259 | {768, 576, 8, 16}, /* 0x1b */ |
266 | { 768, 576, 8,16}, /* 0x1b */ | 260 | {1360, 1024, 8, 16}, /* 0x1c */ |
267 | { 1360,1024, 8,16}, /* 0x1c */ | 261 | {1680, 1050, 8, 16}, /* 0x1d */ |
268 | { 1680,1050, 8,16}, /* 0x1d */ | 262 | {1280, 800, 8, 16}, /* 0x1e */ |
269 | { 1280, 800, 8,16}, /* 0x1e */ | 263 | {1920, 1080, 8, 16}, /* 0x1f */ |
270 | { 1920,1080, 8,16}, /* 0x1f */ | 264 | {960, 540, 8, 16}, /* 0x20 */ |
271 | { 960, 540, 8,16}, /* 0x20 */ | 265 | {960, 600, 8, 16} /* 0x21 */ |
272 | { 960, 600, 8,16} /* 0x21 */ | ||
273 | }; | 266 | }; |
274 | 267 | ||
275 | static const struct SiS_StandTable SiSUSB_StandTable[] = | 268 | static const struct SiS_StandTable SiSUSB_StandTable[] = { |
276 | { | ||
277 | /* MD_3_400 - mode 0x03 - 400 */ | 269 | /* MD_3_400 - mode 0x03 - 400 */ |
278 | { | 270 | { |
279 | 0x50,0x18,0x10,0x1000, | 271 | 0x50, 0x18, 0x10, 0x1000, |
280 | { 0x00,0x03,0x00,0x02 }, | 272 | {0x00, 0x03, 0x00, 0x02}, |
281 | 0x67, | 273 | 0x67, |
282 | { 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, | 274 | {0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, |
283 | 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, | 275 | 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, |
284 | 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, | 276 | 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, |
285 | 0xff }, | 277 | 0xff}, |
286 | { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, | 278 | {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, |
287 | 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, | 279 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, |
288 | 0x0c,0x00,0x0f,0x08 }, | 280 | 0x0c, 0x00, 0x0f, 0x08}, |
289 | { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff } | 281 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff} |
290 | }, | 282 | }, |
291 | /* Generic for VGA and higher */ | 283 | /* Generic for VGA and higher */ |
292 | { | 284 | { |
293 | 0x00,0x00,0x00,0x0000, | 285 | 0x00, 0x00, 0x00, 0x0000, |
294 | { 0x01,0x0f,0x00,0x0e }, | 286 | {0x01, 0x0f, 0x00, 0x0e}, |
295 | 0x23, | 287 | 0x23, |
296 | { 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, | 288 | {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, |
297 | 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, | 289 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
298 | 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, | 290 | 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, |
299 | 0xff }, | 291 | 0xff}, |
300 | { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, | 292 | {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
301 | 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, | 293 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
302 | 0x01,0x00,0x00,0x00 }, | 294 | 0x01, 0x00, 0x00, 0x00}, |
303 | { 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff } | 295 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff} |
304 | } | 296 | } |
305 | }; | 297 | }; |
306 | 298 | ||
307 | static const struct SiS_Ext SiSUSB_EModeIDTable[] = | 299 | static const struct SiS_Ext SiSUSB_EModeIDTable[] = { |
308 | { | 300 | {0x2e, 0x0a1b, 0x0101, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x8 */ |
309 | {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */ | 301 | {0x2f, 0x0a1b, 0x0100, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x05, 0x10, 0}, /* 640x400x8 */ |
310 | {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */ | 302 | {0x30, 0x2a1b, 0x0103, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x8 */ |
311 | {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */ | 303 | {0x31, 0x4a1b, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x8 */ |
312 | {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */ | 304 | {0x32, 0x4a1b, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x8 */ |
313 | {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */ | 305 | {0x33, 0x4a1d, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x16 */ |
314 | {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */ | 306 | {0x34, 0x6a1d, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x16 */ |
315 | {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */ | 307 | {0x35, 0x4a1f, 0x0000, SIS_RI_720x480, 0x00, 0x00, 0x06, 0x06, 0x11, -1}, /* 720x480x32 */ |
316 | {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */ | 308 | {0x36, 0x6a1f, 0x0000, SIS_RI_720x576, 0x00, 0x00, 0x06, 0x06, 0x12, -1}, /* 720x576x32 */ |
317 | {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */ | 309 | {0x38, 0x0a1b, 0x0105, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x8 */ |
318 | {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */ | 310 | {0x3a, 0x0e3b, 0x0107, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x8 */ |
319 | {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */ | 311 | {0x41, 0x9a1d, 0x010e, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x16 */ |
320 | {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */ | 312 | {0x44, 0x0a1d, 0x0111, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x16 */ |
321 | {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */ | 313 | {0x47, 0x2a1d, 0x0114, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x16 */ |
322 | {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */ | 314 | {0x4a, 0x0a3d, 0x0117, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x16 */ |
323 | {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */ | 315 | {0x4d, 0x0e7d, 0x011a, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x16 */ |
324 | {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */ | 316 | {0x50, 0x9a1b, 0x0132, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x8 */ |
325 | {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8 */ | 317 | {0x51, 0xba1b, 0x0133, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x8 */ |
326 | {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8 */ | 318 | {0x52, 0xba1b, 0x0134, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x8 */ |
327 | {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8 */ | 319 | {0x56, 0x9a1d, 0x0135, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x16 */ |
328 | {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */ | 320 | {0x57, 0xba1d, 0x0136, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x16 */ |
329 | {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */ | 321 | {0x58, 0xba1d, 0x0137, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x16 */ |
330 | {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */ | 322 | {0x59, 0x9a1b, 0x0138, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x8 */ |
331 | {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8 */ | 323 | {0x5c, 0xba1f, 0x0000, SIS_RI_512x384, 0x00, 0x00, 0x00, 0x00, 0x1d, 4}, /* 512x384x32 */ |
332 | {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */ | 324 | {0x5d, 0x0a1d, 0x0139, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x07, 0x10, 0}, /* 640x400x16 */ |
333 | {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */ | 325 | {0x5e, 0x0a1f, 0x0000, SIS_RI_640x400, 0x00, 0x00, 0x05, 0x07, 0x10, 0}, /* 640x400x32 */ |
334 | {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */ | 326 | {0x62, 0x0a3f, 0x013a, SIS_RI_640x480, 0x00, 0x00, 0x05, 0x05, 0x08, 2}, /* 640x480x32 */ |
335 | {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */ | 327 | {0x63, 0x2a3f, 0x013b, SIS_RI_800x600, 0x00, 0x00, 0x07, 0x06, 0x00, 3}, /* 800x600x32 */ |
336 | {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */ | 328 | {0x64, 0x0a7f, 0x013c, SIS_RI_1024x768, 0x00, 0x00, 0x08, 0x07, 0x13, 4}, /* 1024x768x32 */ |
337 | {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */ | 329 | {0x65, 0x0eff, 0x013d, SIS_RI_1280x1024, 0x00, 0x00, 0x00, 0x00, 0x2f, 8}, /* 1280x1024x32 */ |
338 | {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */ | 330 | {0x70, 0x6a1b, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x8 */ |
339 | {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */ | 331 | {0x71, 0x4a1b, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x8 */ |
340 | {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */ | 332 | {0x74, 0x4a1d, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x16 */ |
341 | {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */ | 333 | {0x75, 0x0a3d, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x16 */ |
342 | {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */ | 334 | {0x76, 0x6a1f, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x32 */ |
343 | {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */ | 335 | {0x77, 0x4a1f, 0x0000, SIS_RI_1024x576, 0x00, 0x00, 0x00, 0x00, 0x21, -1}, /* 1024x576x32 */ |
344 | {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */ | 336 | {0x78, 0x0a3f, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x32 */ |
345 | {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */ | 337 | {0x79, 0x0a3b, 0x0000, SIS_RI_1280x720, 0x00, 0x00, 0x00, 0x00, 0x24, 5}, /* 1280x720x8 */ |
346 | {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */ | 338 | {0x7a, 0x6a1d, 0x0000, SIS_RI_800x480, 0x00, 0x00, 0x07, 0x07, 0x1e, -1}, /* 800x480x16 */ |
347 | {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */ | 339 | {0x23, 0x0e3b, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x8 */ |
348 | {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */ | 340 | {0x24, 0x0e7d, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x16 */ |
349 | {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */ | 341 | {0x25, 0x0eff, 0x0000, SIS_RI_1280x768, 0x00, 0x00, 0x00, 0x00, 0x27, 6}, /* 1280x768x32 */ |
350 | {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */ | 342 | {0x39, 0x6a1b, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28, -1}, /* 848x480 */ |
351 | {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */ | 343 | {0x3b, 0x6a3d, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28, |
352 | {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, | 344 | -1}, |
353 | {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x28,-1}, | 345 | {0x3e, 0x6a7f, 0x0000, SIS_RI_848x480, 0x00, 0x00, 0x00, 0x00, 0x28, |
354 | {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */ | 346 | -1}, |
355 | {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, | 347 | {0x3f, 0x6a1b, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a, -1}, /* 856x480 */ |
356 | {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x2a,-1}, | 348 | {0x42, 0x6a3d, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a, |
357 | {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */ | 349 | -1}, |
358 | {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */ | 350 | {0x45, 0x6a7f, 0x0000, SIS_RI_856x480, 0x00, 0x00, 0x00, 0x00, 0x2a, |
359 | {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */ | 351 | -1}, |
360 | {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */ | 352 | {0x4f, 0x9a1f, 0x0000, SIS_RI_320x200, 0x00, 0x00, 0x04, 0x04, 0x1a, 0}, /* 320x200x32 */ |
361 | {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, | 353 | {0x53, 0x9a1f, 0x0000, SIS_RI_320x240, 0x00, 0x00, 0x04, 0x04, 0x1b, 2}, /* 320x240x32 */ |
362 | {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x2c,-1}, | 354 | {0x54, 0xba1f, 0x0000, SIS_RI_400x300, 0x00, 0x00, 0x07, 0x07, 0x1c, 3}, /* 400x300x32 */ |
363 | {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */ | 355 | {0x5f, 0x6a1b, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c, -1}, /* 768x576 */ |
364 | {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, | 356 | {0x60, 0x6a1d, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c, |
365 | {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x2d,-1}, | 357 | -1}, |
366 | {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */ | 358 | {0x61, 0x6a3f, 0x0000, SIS_RI_768x576, 0x00, 0x00, 0x06, 0x06, 0x2c, |
367 | {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, | 359 | -1}, |
368 | {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x2e,-1}, | 360 | {0x1d, 0x6a1b, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d, -1}, /* 960x540 */ |
369 | {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */ | 361 | {0x1e, 0x6a3d, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d, |
370 | {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, | 362 | -1}, |
371 | {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, | 363 | {0x1f, 0x6a7f, 0x0000, SIS_RI_960x540, 0x00, 0x00, 0x00, 0x00, 0x2d, |
372 | {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1} | 364 | -1}, |
365 | {0x20, 0x6a1b, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e, -1}, /* 960x600 */ | ||
366 | {0x21, 0x6a3d, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e, | ||
367 | -1}, | ||
368 | {0x22, 0x6a7f, 0x0000, SIS_RI_960x600, 0x00, 0x00, 0x00, 0x00, 0x2e, | ||
369 | -1}, | ||
370 | {0x29, 0x4e1b, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33, -1}, /* 1152x864 */ | ||
371 | {0x2a, 0x4e3d, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33, | ||
372 | -1}, | ||
373 | {0x2b, 0x4e7f, 0x0000, SIS_RI_1152x864, 0x00, 0x00, 0x00, 0x00, 0x33, | ||
374 | -1}, | ||
375 | {0xff, 0x0000, 0x0000, 0, 0x00, 0x00, 0x00, 0x00, 0x00, -1} | ||
373 | }; | 376 | }; |
374 | 377 | ||
375 | static const struct SiS_Ext2 SiSUSB_RefIndex[] = | 378 | static const struct SiS_Ext2 SiSUSB_RefIndex[] = { |
376 | { | 379 | {0x085f, 0x0d, 0x03, 0x05, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */ |
377 | {0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */ | 380 | {0x0067, 0x0e, 0x04, 0x05, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */ |
378 | {0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */ | 381 | {0x0067, 0x0f, 0x08, 0x48, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */ |
379 | {0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */ | 382 | {0x0067, 0x10, 0x07, 0x8b, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */ |
380 | {0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */ | 383 | {0x0047, 0x11, 0x0a, 0x00, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */ |
381 | {0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */ | 384 | {0x0047, 0x12, 0x0d, 0x00, 0x05, 0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */ |
382 | {0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */ | 385 | {0x0047, 0x13, 0x13, 0x00, 0x05, 0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */ |
383 | {0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */ | 386 | {0x0107, 0x14, 0x1c, 0x00, 0x05, 0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */ |
384 | {0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */ | 387 | {0xc85f, 0x05, 0x00, 0x04, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */ |
385 | {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */ | 388 | {0xc067, 0x06, 0x02, 0x04, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */ |
386 | {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */ | 389 | {0xc067, 0x07, 0x02, 0x47, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */ |
387 | {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */ | 390 | {0xc067, 0x08, 0x03, 0x8a, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */ |
388 | {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */ | 391 | {0xc047, 0x09, 0x05, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */ |
389 | {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */ | 392 | {0xc047, 0x0a, 0x09, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */ |
390 | {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */ | 393 | {0xc047, 0x0b, 0x0e, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */ |
391 | {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */ | 394 | {0xc047, 0x0c, 0x15, 0x00, 0x04, 0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */ |
392 | {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */ | 395 | {0x487f, 0x04, 0x00, 0x00, 0x00, 0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */ |
393 | {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */ | 396 | {0xc06f, 0x3c, 0x01, 0x06, 0x13, 0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */ |
394 | {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */ | 397 | {0x006f, 0x3d, 0x6f, 0x06, 0x14, 0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */ |
395 | {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */ | 398 | {0x0087, 0x15, 0x06, 0x00, 0x06, 0x38, 1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */ |
396 | {0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */ | 399 | {0xc877, 0x16, 0x0b, 0x06, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */ |
397 | {0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */ | 400 | {0xc067, 0x17, 0x0f, 0x49, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */ |
398 | {0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */ | 401 | {0x0067, 0x18, 0x11, 0x00, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */ |
399 | {0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */ | 402 | {0x0047, 0x19, 0x16, 0x8c, 0x06, 0x38, 1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */ |
400 | {0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */ | 403 | {0x0107, 0x1a, 0x1b, 0x00, 0x06, 0x38, 1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */ |
401 | {0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */ | 404 | {0x0107, 0x1b, 0x1f, 0x00, 0x06, 0x38, 1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */ |
402 | {0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */ | 405 | {0x407f, 0x00, 0x00, 0x00, 0x00, 0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */ |
403 | {0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */ | 406 | {0xc07f, 0x01, 0x00, 0x04, 0x04, 0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */ |
404 | {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */ | 407 | {0x007f, 0x02, 0x04, 0x05, 0x05, 0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */ |
405 | {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */ | 408 | {0xc077, 0x03, 0x0b, 0x06, 0x06, 0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */ |
406 | {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */ | 409 | {0x0077, 0x32, 0x40, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */ |
407 | {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */ | 410 | {0x0047, 0x33, 0x07, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */ |
408 | {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */ | 411 | {0x0047, 0x34, 0x0a, 0x08, 0x18, 0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */ |
409 | {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */ | 412 | {0x0077, 0x35, 0x0b, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */ |
410 | {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */ | 413 | {0x0047, 0x36, 0x11, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */ |
411 | {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */ | 414 | {0x0047, 0x37, 0x16, 0x09, 0x19, 0x71, 1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */ |
412 | {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */ | 415 | {0x1137, 0x38, 0x19, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */ |
413 | {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */ | 416 | {0x1107, 0x39, 0x1e, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */ |
414 | {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */ | 417 | {0x1307, 0x3a, 0x20, 0x0a, 0x0c, 0x75, 1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */ |
415 | {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */ | 418 | {0x0077, 0x42, 0x5b, 0x08, 0x11, 0x23, 1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */ |
416 | {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */ | 419 | {0x0087, 0x45, 0x57, 0x00, 0x16, 0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */ |
417 | {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi */ | 420 | {0xc067, 0x46, 0x55, 0x0b, 0x16, 0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */ |
418 | {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz */ | 421 | {0x0087, 0x47, 0x57, 0x00, 0x17, 0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */ |
419 | {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi */ | 422 | {0xc067, 0x48, 0x57, 0x00, 0x17, 0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */ |
420 | {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz */ | 423 | {0x006f, 0x4d, 0x71, 0x06, 0x15, 0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */ |
421 | {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz */ | 424 | {0x0067, 0x52, 0x6a, 0x00, 0x1c, 0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */ |
422 | {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */ | 425 | {0x0077, 0x53, 0x6b, 0x0b, 0x1d, 0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */ |
423 | {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */ | 426 | {0x0087, 0x1c, 0x11, 0x00, 0x07, 0x3a, 1280, 1024, 0x30, 0x00, 0x00}, /* 0x2f */ |
424 | {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */ | 427 | {0x0137, 0x1d, 0x19, 0x07, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x30 */ |
425 | {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */ | 428 | {0x0107, 0x1e, 0x1e, 0x00, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x31 */ |
426 | {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */ | 429 | {0x0207, 0x1f, 0x20, 0x00, 0x07, 0x3a, 1280, 1024, 0x00, 0x00, 0x00}, /* 0x32 */ |
427 | {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */ | 430 | {0x0127, 0x54, 0x6d, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */ |
428 | {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz */ | 431 | {0x0127, 0x44, 0x19, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */ |
429 | {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz */ | 432 | {0x0127, 0x4a, 0x1e, 0x00, 0x1a, 0x29, 1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */ |
430 | {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz */ | 433 | {0xffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x00, 0x00} |
431 | {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, 0x00, 0x00} | ||
432 | }; | 434 | }; |
433 | 435 | ||
434 | static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = | 436 | static const struct SiS_CRT1Table SiSUSB_CRT1Table[] = { |
435 | { | 437 | {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0xbf, 0x1f, |
436 | {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, | 438 | 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x00, |
437 | 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, | 439 | 0x00}}, /* 0x0 */ |
438 | 0x00}}, /* 0x0 */ | 440 | {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e, |
439 | {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, | 441 | 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x00, |
440 | 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, | 442 | 0x00}}, /* 0x1 */ |
441 | 0x00}}, /* 0x1 */ | 443 | {{0x3d, 0x31, 0x31, 0x81, 0x37, 0x1f, 0x72, 0xf0, |
442 | {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, | 444 | 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x05, |
443 | 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, | 445 | 0x01}}, /* 0x2 */ |
444 | 0x01}}, /* 0x2 */ | 446 | {{0x4f, 0x3f, 0x3f, 0x93, 0x45, 0x0d, 0x24, 0xf5, |
445 | {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, | 447 | 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x01, |
446 | 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, | 448 | 0x01}}, /* 0x3 */ |
447 | 0x01}}, /* 0x3 */ | 449 | {{0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, |
448 | {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, | 450 | 0x9c, 0x8e, 0x8f, 0x96, 0xb9, 0x30, 0x00, 0x05, |
449 | 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, | 451 | 0x00}}, /* 0x4 */ |
450 | 0x00}}, /* 0x4 */ | 452 | {{0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e, |
451 | {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, | 453 | 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05, |
452 | 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, | 454 | 0x00}}, /* 0x5 */ |
453 | 0x00}}, /* 0x5 */ | 455 | {{0x63, 0x4f, 0x4f, 0x87, 0x56, 0x9b, 0x06, 0x3e, |
454 | {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, | 456 | 0xe8, 0x8a, 0xdf, 0xe7, 0x07, 0x00, 0x00, 0x01, |
455 | 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, | 457 | 0x00}}, /* 0x6 */ |
456 | 0x00}}, /* 0x6 */ | 458 | {{0x64, 0x4f, 0x4f, 0x88, 0x55, 0x9d, 0xf2, 0x1f, |
457 | {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, | 459 | 0xe0, 0x83, 0xdf, 0xdf, 0xf3, 0x10, 0x00, 0x01, |
458 | 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, | 460 | 0x00}}, /* 0x7 */ |
459 | 0x00}}, /* 0x7 */ | 461 | {{0x63, 0x4f, 0x4f, 0x87, 0x5a, 0x81, 0xfb, 0x1f, |
460 | {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f, | 462 | 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05, |
461 | 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, | 463 | 0x00}}, /* 0x8 */ |
462 | 0x00}}, /* 0x8 */ | 464 | {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0xfb, 0x1f, |
463 | {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f, | 465 | 0xe0, 0x83, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x05, |
464 | 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, | 466 | 0x61}}, /* 0x9 */ |
465 | 0x61}}, /* 0x9 */ | 467 | {{0x65, 0x4f, 0x4f, 0x89, 0x58, 0x80, 0x01, 0x3e, |
466 | {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e, | 468 | 0xe0, 0x83, 0xdf, 0xdf, 0x02, 0x00, 0x00, 0x05, |
467 | 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05, | 469 | 0x61}}, /* 0xa */ |
468 | 0x61}}, /* 0xa */ | 470 | {{0x67, 0x4f, 0x4f, 0x8b, 0x58, 0x81, 0x0d, 0x3e, |
469 | {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e, | 471 | 0xe0, 0x83, 0xdf, 0xdf, 0x0e, 0x00, 0x00, 0x05, |
470 | 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, | 472 | 0x61}}, /* 0xb */ |
471 | 0x61}}, /* 0xb */ | 473 | {{0x65, 0x4f, 0x4f, 0x89, 0x57, 0x9f, 0xfb, 0x1f, |
472 | {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, | 474 | 0xe6, 0x8a, 0xdf, 0xdf, 0xfc, 0x10, 0x00, 0x01, |
473 | 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, | 475 | 0x00}}, /* 0xc */ |
474 | 0x00}}, /* 0xc */ | 476 | {{0x7b, 0x63, 0x63, 0x9f, 0x6a, 0x93, 0x6f, 0xf0, |
475 | {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, | 477 | 0x58, 0x8a, 0x57, 0x57, 0x70, 0x20, 0x00, 0x05, |
476 | 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, | 478 | 0x01}}, /* 0xd */ |
477 | 0x01}}, /* 0xd */ | 479 | {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xf0, |
478 | {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0, | 480 | 0x58, 0x8c, 0x57, 0x57, 0x73, 0x20, 0x00, 0x06, |
479 | 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06, | 481 | 0x01}}, /* 0xe */ |
480 | 0x01}}, /* 0xe */ | 482 | {{0x7d, 0x63, 0x63, 0x81, 0x6e, 0x1d, 0x98, 0xf0, |
481 | {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0, | 483 | 0x7c, 0x82, 0x57, 0x57, 0x99, 0x00, 0x00, 0x06, |
482 | 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06, | 484 | 0x01}}, /* 0xf */ |
483 | 0x01}}, /* 0xf */ | 485 | {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xf0, |
484 | {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0, | 486 | 0x58, 0x8b, 0x57, 0x57, 0x70, 0x20, 0x00, 0x06, |
485 | 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06, | 487 | 0x01}}, /* 0x10 */ |
486 | 0x01}}, /* 0x10 */ | 488 | {{0x7e, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xf0, |
487 | {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0, | 489 | 0x58, 0x8b, 0x57, 0x57, 0x76, 0x20, 0x00, 0x06, |
488 | 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06, | 490 | 0x01}}, /* 0x11 */ |
489 | 0x01}}, /* 0x11 */ | 491 | {{0x81, 0x63, 0x63, 0x85, 0x6d, 0x18, 0x7a, 0xf0, |
490 | {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0, | 492 | 0x58, 0x8b, 0x57, 0x57, 0x7b, 0x20, 0x00, 0x06, |
491 | 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06, | 493 | 0x61}}, /* 0x12 */ |
492 | 0x61}}, /* 0x12 */ | 494 | {{0x83, 0x63, 0x63, 0x87, 0x6e, 0x19, 0x81, 0xf0, |
493 | {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0, | 495 | 0x58, 0x8b, 0x57, 0x57, 0x82, 0x20, 0x00, 0x06, |
494 | 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06, | 496 | 0x61}}, /* 0x13 */ |
495 | 0x61}}, /* 0x13 */ | 497 | {{0x85, 0x63, 0x63, 0x89, 0x6f, 0x1a, 0x91, 0xf0, |
496 | {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0, | 498 | 0x58, 0x8b, 0x57, 0x57, 0x92, 0x20, 0x00, 0x06, |
497 | 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06, | 499 | 0x61}}, /* 0x14 */ |
498 | 0x61}}, /* 0x14 */ | 500 | {{0x99, 0x7f, 0x7f, 0x9d, 0x84, 0x1a, 0x96, 0x1f, |
499 | {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f, | 501 | 0x7f, 0x83, 0x7f, 0x7f, 0x97, 0x10, 0x00, 0x02, |
500 | 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02, | 502 | 0x00}}, /* 0x15 */ |
501 | 0x00}}, /* 0x15 */ | 503 | {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5, |
502 | {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, | 504 | 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02, |
503 | 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, | 505 | 0x01}}, /* 0x16 */ |
504 | 0x01}}, /* 0x16 */ | 506 | {{0xa1, 0x7f, 0x7f, 0x85, 0x86, 0x97, 0x24, 0xf5, |
505 | {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5, | 507 | 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02, |
506 | 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, | 508 | 0x01}}, /* 0x17 */ |
507 | 0x01}}, /* 0x17 */ | 509 | {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf5, |
508 | {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5, | 510 | 0x00, 0x83, 0xff, 0xff, 0x1f, 0x10, 0x00, 0x02, |
509 | 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02, | 511 | 0x01}}, /* 0x18 */ |
510 | 0x01}}, /* 0x18 */ | 512 | {{0xa7, 0x7f, 0x7f, 0x8b, 0x89, 0x95, 0x26, 0xf5, |
511 | {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5, | 513 | 0x00, 0x83, 0xff, 0xff, 0x27, 0x10, 0x00, 0x02, |
512 | 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02, | 514 | 0x01}}, /* 0x19 */ |
513 | 0x01}}, /* 0x19 */ | 515 | {{0xa9, 0x7f, 0x7f, 0x8d, 0x8c, 0x9a, 0x2c, 0xf5, |
514 | {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5, | 516 | 0x00, 0x83, 0xff, 0xff, 0x2d, 0x14, 0x00, 0x02, |
515 | 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02, | 517 | 0x62}}, /* 0x1a */ |
516 | 0x62}}, /* 0x1a */ | 518 | {{0xab, 0x7f, 0x7f, 0x8f, 0x8d, 0x9b, 0x35, 0xf5, |
517 | {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5, | 519 | 0x00, 0x83, 0xff, 0xff, 0x36, 0x14, 0x00, 0x02, |
518 | 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02, | 520 | 0x62}}, /* 0x1b */ |
519 | 0x62}}, /* 0x1b */ | 521 | {{0xcf, 0x9f, 0x9f, 0x93, 0xb2, 0x01, 0x14, 0xba, |
520 | {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba, | 522 | 0x00, 0x83, 0xff, 0xff, 0x15, 0x00, 0x00, 0x03, |
521 | 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03, | 523 | 0x00}}, /* 0x1c */ |
522 | 0x00}}, /* 0x1c */ | 524 | {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0x5a, |
523 | {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a, | 525 | 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07, |
524 | 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, | 526 | 0x01}}, /* 0x1d */ |
525 | 0x01}}, /* 0x1d */ | 527 | {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0x5a, |
526 | {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a, | 528 | 0x00, 0x83, 0xff, 0xff, 0x29, 0x09, 0x00, 0x07, |
527 | 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, | 529 | 0x01}}, /* 0x1e */ |
528 | 0x01}}, /* 0x1e */ | 530 | {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0x5a, |
529 | {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a, | 531 | 0x00, 0x83, 0xff, 0xff, 0x2f, 0x09, 0x00, 0x07, |
530 | 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07, | 532 | 0x01}}, /* 0x1f */ |
531 | 0x01}}, /* 0x1f */ | 533 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
532 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 534 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
533 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 535 | 0x00}}, /* 0x20 */ |
534 | 0x00}}, /* 0x20 */ | 536 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
535 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 537 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
536 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 538 | 0x00}}, /* 0x21 */ |
537 | 0x00}}, /* 0x21 */ | 539 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
538 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 540 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
539 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 541 | 0x00}}, /* 0x22 */ |
540 | 0x00}}, /* 0x22 */ | 542 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
541 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 543 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
542 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 544 | 0x00}}, /* 0x23 */ |
543 | 0x00}}, /* 0x23 */ | 545 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
544 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 546 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
545 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 547 | 0x00}}, /* 0x24 */ |
546 | 0x00}}, /* 0x24 */ | 548 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
547 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 549 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
548 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 550 | 0x00}}, /* 0x25 */ |
549 | 0x00}}, /* 0x25 */ | 551 | {{0x09, 0xc7, 0xc7, 0x8d, 0xd3, 0x0b, 0xe0, 0x10, |
550 | {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, | 552 | 0xb0, 0x83, 0xaf, 0xaf, 0xe1, 0x2f, 0x01, 0x04, |
551 | 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, | 553 | 0x00}}, /* 0x26 */ |
552 | 0x00}}, /* 0x26 */ | 554 | {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f, |
553 | {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, | 555 | 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01, |
554 | 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, | 556 | 0x00}}, /* 0x27 */ |
555 | 0x00}}, /* 0x27 */ | 557 | {{0x43, 0xef, 0xef, 0x87, 0x06, 0x00, 0xd4, 0x1f, |
556 | {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f, | 558 | 0xa0, 0x83, 0x9f, 0x9f, 0xd5, 0x1f, 0x41, 0x05, |
557 | 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05, | 559 | 0x63}}, /* 0x28 */ |
558 | 0x63}}, /* 0x28 */ | 560 | {{0x45, 0xef, 0xef, 0x89, 0x07, 0x01, 0xd9, 0x1f, |
559 | {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f, | 561 | 0xa0, 0x83, 0x9f, 0x9f, 0xda, 0x1f, 0x41, 0x05, |
560 | 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05, | 562 | 0x63}}, /* 0x29 */ |
561 | 0x63}}, /* 0x29 */ | 563 | {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f, |
562 | {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, | 564 | 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01, |
563 | 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, | 565 | 0x00}}, /* 0x2a */ |
564 | 0x00}}, /* 0x2a */ | 566 | {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f, |
565 | {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, | 567 | 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01, |
566 | 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, | 568 | 0x00}}, /* 0x2b */ |
567 | 0x00}}, /* 0x2b */ | 569 | {{0x40, 0xef, 0xef, 0x84, 0x03, 0x1d, 0xda, 0x1f, |
568 | {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, | 570 | 0xa0, 0x83, 0x9f, 0x9f, 0xdb, 0x1f, 0x41, 0x01, |
569 | 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, | 571 | 0x00}}, /* 0x2c */ |
570 | 0x00}}, /* 0x2c */ | 572 | {{0x59, 0xff, 0xff, 0x9d, 0x17, 0x13, 0x33, 0xba, |
571 | {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba, | 573 | 0x00, 0x83, 0xff, 0xff, 0x34, 0x0f, 0x41, 0x05, |
572 | 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05, | 574 | 0x44}}, /* 0x2d */ |
573 | 0x44}}, /* 0x2d */ | 575 | {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x38, 0xba, |
574 | {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba, | 576 | 0x00, 0x83, 0xff, 0xff, 0x39, 0x0f, 0x41, 0x05, |
575 | 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05, | 577 | 0x44}}, /* 0x2e */ |
576 | 0x44}}, /* 0x2e */ | 578 | {{0x5b, 0xff, 0xff, 0x9f, 0x18, 0x14, 0x3d, 0xba, |
577 | {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba, | 579 | 0x00, 0x83, 0xff, 0xff, 0x3e, 0x0f, 0x41, 0x05, |
578 | 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05, | 580 | 0x44}}, /* 0x2f */ |
579 | 0x44}}, /* 0x2f */ | 581 | {{0x5d, 0xff, 0xff, 0x81, 0x19, 0x95, 0x41, 0xba, |
580 | {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba, | 582 | 0x00, 0x84, 0xff, 0xff, 0x42, 0x0f, 0x41, 0x05, |
581 | 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05, | 583 | 0x44}}, /* 0x30 */ |
582 | 0x44}}, /* 0x30 */ | 584 | {{0x55, 0xff, 0xff, 0x99, 0x0d, 0x0c, 0x3e, 0xba, |
583 | {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba, | 585 | 0x00, 0x84, 0xff, 0xff, 0x3f, 0x0f, 0x41, 0x05, |
584 | 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05, | 586 | 0x00}}, /* 0x31 */ |
585 | 0x00}}, /* 0x31 */ | 587 | {{0x7f, 0x63, 0x63, 0x83, 0x6c, 0x1c, 0x72, 0xba, |
586 | {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, | 588 | 0x27, 0x8b, 0xdf, 0xdf, 0x73, 0x00, 0x00, 0x06, |
587 | 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, | 589 | 0x01}}, /* 0x32 */ |
588 | 0x01}}, /* 0x32 */ | 590 | {{0x7f, 0x63, 0x63, 0x83, 0x69, 0x13, 0x6f, 0xba, |
589 | {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, | 591 | 0x26, 0x89, 0xdf, 0xdf, 0x6f, 0x00, 0x00, 0x06, |
590 | 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, | 592 | 0x01}}, /* 0x33 */ |
591 | 0x01}}, /* 0x33 */ | 593 | {{0x7f, 0x63, 0x63, 0x82, 0x6b, 0x13, 0x75, 0xba, |
592 | {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, | 594 | 0x29, 0x8c, 0xdf, 0xdf, 0x75, 0x00, 0x00, 0x06, |
593 | 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, | 595 | 0x01}}, /* 0x34 */ |
594 | 0x01}}, /* 0x34 */ | 596 | {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf1, |
595 | {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, | 597 | 0xaf, 0x85, 0x3f, 0x3f, 0x25, 0x30, 0x00, 0x02, |
596 | 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, | 598 | 0x01}}, /* 0x35 */ |
597 | 0x01}}, /* 0x35 */ | 599 | {{0x9f, 0x7f, 0x7f, 0x83, 0x85, 0x91, 0x1e, 0xf1, |
598 | {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, | 600 | 0xad, 0x81, 0x3f, 0x3f, 0x1f, 0x30, 0x00, 0x02, |
599 | 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, | 601 | 0x01}}, /* 0x36 */ |
600 | 0x01}}, /* 0x36 */ | 602 | {{0xa7, 0x7f, 0x7f, 0x88, 0x89, 0x95, 0x26, 0xf1, |
601 | {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, | 603 | 0xb1, 0x85, 0x3f, 0x3f, 0x27, 0x30, 0x00, 0x02, |
602 | 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, | 604 | 0x01}}, /* 0x37 */ |
603 | 0x01}}, /* 0x37 */ | 605 | {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x28, 0xc4, |
604 | {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, | 606 | 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07, |
605 | 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, | 607 | 0x01}}, /* 0x38 */ |
606 | 0x01}}, /* 0x38 */ | 608 | {{0xce, 0x9f, 0x9f, 0x92, 0xa5, 0x17, 0x28, 0xd4, |
607 | {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, | 609 | 0x7a, 0x8e, 0xcf, 0xcf, 0x29, 0x21, 0x00, 0x07, |
608 | 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, | 610 | 0x01}}, /* 0x39 */ |
609 | 0x01}}, /* 0x39 */ | 611 | {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0x2e, 0xd4, |
610 | {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, | 612 | 0x7d, 0x81, 0xcf, 0xcf, 0x2f, 0x21, 0x00, 0x07, |
611 | 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, | 613 | 0x01}}, /* 0x3a */ |
612 | 0x01}}, /* 0x3a */ | 614 | {{0xdc, 0x9f, 0x9f, 0x80, 0xaf, 0x9d, 0xe6, 0xff, |
613 | {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, | 615 | 0xc0, 0x83, 0xbf, 0xbf, 0xe7, 0x10, 0x00, 0x07, |
614 | 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, | 616 | 0x01}}, /* 0x3b */ |
615 | 0x01}}, /* 0x3b */ | 617 | {{0x6b, 0x59, 0x59, 0x8f, 0x5e, 0x8c, 0x0b, 0x3e, |
616 | {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e, | 618 | 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x05, |
617 | 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, | 619 | 0x00}}, /* 0x3c */ |
618 | 0x00}}, /* 0x3c */ | 620 | {{0x6d, 0x59, 0x59, 0x91, 0x60, 0x89, 0x53, 0xf0, |
619 | {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0, | 621 | 0x41, 0x84, 0x3f, 0x3f, 0x54, 0x00, 0x00, 0x05, |
620 | 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05, | 622 | 0x41}}, /* 0x3d */ |
621 | 0x41}}, /* 0x3d */ | 623 | {{0x86, 0x6a, 0x6a, 0x8a, 0x74, 0x06, 0x8c, 0x15, |
622 | {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15, | 624 | 0x4f, 0x83, 0xef, 0xef, 0x8d, 0x30, 0x00, 0x02, |
623 | 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02, | 625 | 0x00}}, /* 0x3e */ |
624 | 0x00}}, /* 0x3e */ | 626 | {{0x81, 0x6a, 0x6a, 0x85, 0x70, 0x00, 0x0f, 0x3e, |
625 | {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e, | 627 | 0xeb, 0x8e, 0xdf, 0xdf, 0x10, 0x00, 0x00, 0x02, |
626 | 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02, | 628 | 0x00}}, /* 0x3f */ |
627 | 0x00}}, /* 0x3f */ | 629 | {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x1e, 0xf1, |
628 | {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, | 630 | 0xae, 0x85, 0x57, 0x57, 0x1f, 0x30, 0x00, 0x02, |
629 | 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, | 631 | 0x01}}, /* 0x40 */ |
630 | 0x01}}, /* 0x40 */ | 632 | {{0xa3, 0x7f, 0x7f, 0x87, 0x86, 0x97, 0x24, 0xf5, |
631 | {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, | 633 | 0x02, 0x88, 0xff, 0xff, 0x25, 0x10, 0x00, 0x02, |
632 | 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, | 634 | 0x01}}, /* 0x41 */ |
633 | 0x01}}, /* 0x41 */ | 635 | {{0xce, 0x9f, 0x9f, 0x92, 0xa9, 0x17, 0x20, 0xf5, |
634 | {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, | 636 | 0x03, 0x88, 0xff, 0xff, 0x21, 0x10, 0x00, 0x07, |
635 | 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07, | 637 | 0x01}}, /* 0x42 */ |
636 | 0x01}}, /* 0x42 */ | 638 | {{0xe6, 0xae, 0xae, 0x8a, 0xbd, 0x90, 0x3d, 0x10, |
637 | {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10, | 639 | 0x1a, 0x8d, 0x19, 0x19, 0x3e, 0x2f, 0x00, 0x03, |
638 | 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03, | 640 | 0x00}}, /* 0x43 */ |
639 | 0x00}}, /* 0x43 */ | 641 | {{0xc3, 0x8f, 0x8f, 0x87, 0x9b, 0x0b, 0x82, 0xef, |
640 | {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, | 642 | 0x60, 0x83, 0x5f, 0x5f, 0x83, 0x10, 0x00, 0x07, |
641 | 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, | 643 | 0x01}}, /* 0x44 */ |
642 | 0x01}}, /* 0x44 */ | 644 | {{0x86, 0x69, 0x69, 0x8A, 0x74, 0x06, 0x8C, 0x15, |
643 | {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, | 645 | 0x4F, 0x83, 0xEF, 0xEF, 0x8D, 0x30, 0x00, 0x02, |
644 | 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, | 646 | 0x00}}, /* 0x45 */ |
645 | 0x00}}, /* 0x45 */ | 647 | {{0x83, 0x69, 0x69, 0x87, 0x6f, 0x1d, 0x03, 0x3E, |
646 | {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, | 648 | 0xE5, 0x8d, 0xDF, 0xe4, 0x04, 0x00, 0x00, 0x06, |
647 | 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, | 649 | 0x00}}, /* 0x46 */ |
648 | 0x00}}, /* 0x46 */ | 650 | {{0x86, 0x6A, 0x6A, 0x8A, 0x74, 0x06, 0x8C, 0x15, |
649 | {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, | 651 | 0x4F, 0x83, 0xEF, 0xEF, 0x8D, 0x30, 0x00, 0x02, |
650 | 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, | 652 | 0x00}}, /* 0x47 */ |
651 | 0x00}}, /* 0x47 */ | 653 | {{0x81, 0x6A, 0x6A, 0x85, 0x70, 0x00, 0x0F, 0x3E, |
652 | {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, | 654 | 0xEB, 0x8E, 0xDF, 0xDF, 0x10, 0x00, 0x00, 0x02, |
653 | 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, | 655 | 0x00}}, /* 0x48 */ |
654 | 0x00}}, /* 0x48 */ | 656 | {{0xdd, 0xa9, 0xa9, 0x81, 0xb4, 0x97, 0x26, 0xfd, |
655 | {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, | 657 | 0x01, 0x8d, 0xff, 0x00, 0x27, 0x10, 0x00, 0x03, |
656 | 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, | 658 | 0x01}}, /* 0x49 */ |
657 | 0x01}}, /* 0x49 */ | 659 | {{0xd9, 0x8f, 0x8f, 0x9d, 0xba, 0x0a, 0x8a, 0xff, |
658 | {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, | 660 | 0x60, 0x8b, 0x5f, 0x5f, 0x8b, 0x10, 0x00, 0x03, |
659 | 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, | 661 | 0x01}}, /* 0x4a */ |
660 | 0x01}}, /* 0x4a */ | 662 | {{0xea, 0xae, 0xae, 0x8e, 0xba, 0x82, 0x40, 0x10, |
661 | {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, | 663 | 0x1b, 0x87, 0x19, 0x1a, 0x41, 0x0f, 0x00, 0x03, |
662 | 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03, | 664 | 0x00}}, /* 0x4b */ |
663 | 0x00}}, /* 0x4b */ | 665 | {{0xd3, 0x9f, 0x9f, 0x97, 0xab, 0x1f, 0xf1, 0xff, |
664 | {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, | 666 | 0xc0, 0x83, 0xbf, 0xbf, 0xf2, 0x10, 0x00, 0x07, |
665 | 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, | 667 | 0x01}}, /* 0x4c */ |
666 | 0x01}}, /* 0x4c */ | 668 | {{0x75, 0x5f, 0x5f, 0x99, 0x66, 0x90, 0x53, 0xf0, |
667 | {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, | 669 | 0x41, 0x84, 0x3f, 0x3f, 0x54, 0x00, 0x00, 0x05, |
668 | 0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05, | 670 | 0x41}}, |
669 | 0x41}}, | 671 | {{0x2d, 0x27, 0x28, 0x90, 0x2c, 0x80, 0x0b, 0x3e, |
670 | {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, | 672 | 0xe9, 0x8b, 0xdf, 0xe7, 0x04, 0x00, 0x00, 0x00, |
671 | 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, | 673 | 0x00}}, /* 0x4e */ |
672 | 0x00}}, /* 0x4e */ | 674 | {{0xcd, 0x9f, 0x9f, 0x91, 0xab, 0x1c, 0x3a, 0xff, |
673 | {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, | 675 | 0x20, 0x83, 0x1f, 0x1f, 0x3b, 0x10, 0x00, 0x07, |
674 | 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07, | 676 | 0x21}}, /* 0x4f */ |
675 | 0x21}}, /* 0x4f */ | 677 | {{0x15, 0xd1, 0xd1, 0x99, 0xe2, 0x19, 0x3d, 0x10, |
676 | {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, | 678 | 0x1a, 0x8d, 0x19, 0x19, 0x3e, 0x2f, 0x01, 0x0c, |
677 | 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c, | 679 | 0x20}}, /* 0x50 */ |
678 | 0x20}}, /* 0x50 */ | 680 | {{0x0e, 0xef, 0xef, 0x92, 0xfe, 0x03, 0x30, 0xf0, |
679 | {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, | 681 | 0x1e, 0x83, 0x1b, 0x1c, 0x31, 0x00, 0x01, 0x00, |
680 | 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00, | 682 | 0x61}}, /* 0x51 */ |
681 | 0x61}}, /* 0x51 */ | 683 | {{0x85, 0x77, 0x77, 0x89, 0x7d, 0x01, 0x31, 0xf0, |
682 | {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, | 684 | 0x1e, 0x84, 0x1b, 0x1c, 0x32, 0x00, 0x00, 0x02, |
683 | 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02, | 685 | 0x41}}, /* 0x52 */ |
684 | 0x41}}, /* 0x52 */ | 686 | {{0x87, 0x77, 0x77, 0x8b, 0x81, 0x0b, 0x68, 0xf0, |
685 | {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0, | 687 | 0x5a, 0x80, 0x57, 0x57, 0x69, 0x00, 0x00, 0x02, |
686 | 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02, | 688 | 0x01}}, /* 0x53 */ |
687 | 0x01}}, /* 0x53 */ | 689 | {{0xcd, 0x8f, 0x8f, 0x91, 0x9b, 0x1b, 0x7a, 0xff, |
688 | {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, | 690 | 0x64, 0x8c, 0x5f, 0x62, 0x7b, 0x10, 0x00, 0x07, |
689 | 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07, | 691 | 0x41}} /* 0x54 */ |
690 | 0x41}} /* 0x54 */ | ||
691 | }; | 692 | }; |
692 | 693 | ||
693 | static const struct SiS_VCLKData SiSUSB_VCLKData[] = | 694 | static const struct SiS_VCLKData SiSUSB_VCLKData[] = { |
694 | { | 695 | {0x1b, 0xe1, 25}, /* 0x00 */ |
695 | { 0x1b,0xe1, 25}, /* 0x00 */ | 696 | {0x4e, 0xe4, 28}, /* 0x01 */ |
696 | { 0x4e,0xe4, 28}, /* 0x01 */ | 697 | {0x57, 0xe4, 31}, /* 0x02 */ |
697 | { 0x57,0xe4, 31}, /* 0x02 */ | 698 | {0xc3, 0xc8, 36}, /* 0x03 */ |
698 | { 0xc3,0xc8, 36}, /* 0x03 */ | 699 | {0x42, 0xe2, 40}, /* 0x04 */ |
699 | { 0x42,0xe2, 40}, /* 0x04 */ | 700 | {0xfe, 0xcd, 43}, /* 0x05 */ |
700 | { 0xfe,0xcd, 43}, /* 0x05 */ | 701 | {0x5d, 0xc4, 44}, /* 0x06 */ |
701 | { 0x5d,0xc4, 44}, /* 0x06 */ | 702 | {0x52, 0xe2, 49}, /* 0x07 */ |
702 | { 0x52,0xe2, 49}, /* 0x07 */ | 703 | {0x53, 0xe2, 50}, /* 0x08 */ |
703 | { 0x53,0xe2, 50}, /* 0x08 */ | 704 | {0x74, 0x67, 52}, /* 0x09 */ |
704 | { 0x74,0x67, 52}, /* 0x09 */ | 705 | {0x6d, 0x66, 56}, /* 0x0a */ |
705 | { 0x6d,0x66, 56}, /* 0x0a */ | 706 | {0x5a, 0x64, 65}, /* 0x0b */ |
706 | { 0x5a,0x64, 65}, /* 0x0b */ | 707 | {0x46, 0x44, 67}, /* 0x0c */ |
707 | { 0x46,0x44, 67}, /* 0x0c */ | 708 | {0xb1, 0x46, 68}, /* 0x0d */ |
708 | { 0xb1,0x46, 68}, /* 0x0d */ | 709 | {0xd3, 0x4a, 72}, /* 0x0e */ |
709 | { 0xd3,0x4a, 72}, /* 0x0e */ | 710 | {0x29, 0x61, 75}, /* 0x0f */ |
710 | { 0x29,0x61, 75}, /* 0x0f */ | 711 | {0x6e, 0x46, 76}, /* 0x10 */ |
711 | { 0x6e,0x46, 76}, /* 0x10 */ | 712 | {0x2b, 0x61, 78}, /* 0x11 */ |
712 | { 0x2b,0x61, 78}, /* 0x11 */ | 713 | {0x31, 0x42, 79}, /* 0x12 */ |
713 | { 0x31,0x42, 79}, /* 0x12 */ | 714 | {0xab, 0x44, 83}, /* 0x13 */ |
714 | { 0xab,0x44, 83}, /* 0x13 */ | 715 | {0x46, 0x25, 84}, /* 0x14 */ |
715 | { 0x46,0x25, 84}, /* 0x14 */ | 716 | {0x78, 0x29, 86}, /* 0x15 */ |
716 | { 0x78,0x29, 86}, /* 0x15 */ | 717 | {0x62, 0x44, 94}, /* 0x16 */ |
717 | { 0x62,0x44, 94}, /* 0x16 */ | 718 | {0x2b, 0x41, 104}, /* 0x17 */ |
718 | { 0x2b,0x41,104}, /* 0x17 */ | 719 | {0x3a, 0x23, 105}, /* 0x18 */ |
719 | { 0x3a,0x23,105}, /* 0x18 */ | 720 | {0x70, 0x44, 108}, /* 0x19 */ |
720 | { 0x70,0x44,108}, /* 0x19 */ | 721 | {0x3c, 0x23, 109}, /* 0x1a */ |
721 | { 0x3c,0x23,109}, /* 0x1a */ | 722 | {0x5e, 0x43, 113}, /* 0x1b */ |
722 | { 0x5e,0x43,113}, /* 0x1b */ | 723 | {0xbc, 0x44, 116}, /* 0x1c */ |
723 | { 0xbc,0x44,116}, /* 0x1c */ | 724 | {0xe0, 0x46, 132}, /* 0x1d */ |
724 | { 0xe0,0x46,132}, /* 0x1d */ | 725 | {0x54, 0x42, 135}, /* 0x1e */ |
725 | { 0x54,0x42,135}, /* 0x1e */ | 726 | {0xea, 0x2a, 139}, /* 0x1f */ |
726 | { 0xea,0x2a,139}, /* 0x1f */ | 727 | {0x41, 0x22, 157}, /* 0x20 */ |
727 | { 0x41,0x22,157}, /* 0x20 */ | 728 | {0x70, 0x24, 162}, /* 0x21 */ |
728 | { 0x70,0x24,162}, /* 0x21 */ | 729 | {0x30, 0x21, 175}, /* 0x22 */ |
729 | { 0x30,0x21,175}, /* 0x22 */ | 730 | {0x4e, 0x22, 189}, /* 0x23 */ |
730 | { 0x4e,0x22,189}, /* 0x23 */ | 731 | {0xde, 0x26, 194}, /* 0x24 */ |
731 | { 0xde,0x26,194}, /* 0x24 */ | 732 | {0x62, 0x06, 202}, /* 0x25 */ |
732 | { 0x62,0x06,202}, /* 0x25 */ | 733 | {0x3f, 0x03, 229}, /* 0x26 */ |
733 | { 0x3f,0x03,229}, /* 0x26 */ | 734 | {0xb8, 0x06, 234}, /* 0x27 */ |
734 | { 0xb8,0x06,234}, /* 0x27 */ | 735 | {0x34, 0x02, 253}, /* 0x28 */ |
735 | { 0x34,0x02,253}, /* 0x28 */ | 736 | {0x58, 0x04, 255}, /* 0x29 */ |
736 | { 0x58,0x04,255}, /* 0x29 */ | 737 | {0x24, 0x01, 265}, /* 0x2a */ |
737 | { 0x24,0x01,265}, /* 0x2a */ | 738 | {0x9b, 0x02, 267}, /* 0x2b */ |
738 | { 0x9b,0x02,267}, /* 0x2b */ | 739 | {0x70, 0x05, 270}, /* 0x2c */ |
739 | { 0x70,0x05,270}, /* 0x2c */ | 740 | {0x25, 0x01, 272}, /* 0x2d */ |
740 | { 0x25,0x01,272}, /* 0x2d */ | 741 | {0x9c, 0x02, 277}, /* 0x2e */ |
741 | { 0x9c,0x02,277}, /* 0x2e */ | 742 | {0x27, 0x01, 286}, /* 0x2f */ |
742 | { 0x27,0x01,286}, /* 0x2f */ | 743 | {0x3c, 0x02, 291}, /* 0x30 */ |
743 | { 0x3c,0x02,291}, /* 0x30 */ | 744 | {0xef, 0x0a, 292}, /* 0x31 */ |
744 | { 0xef,0x0a,292}, /* 0x31 */ | 745 | {0xf6, 0x0a, 310}, /* 0x32 */ |
745 | { 0xf6,0x0a,310}, /* 0x32 */ | 746 | {0x95, 0x01, 315}, /* 0x33 */ |
746 | { 0x95,0x01,315}, /* 0x33 */ | 747 | {0xf0, 0x09, 324}, /* 0x34 */ |
747 | { 0xf0,0x09,324}, /* 0x34 */ | 748 | {0xfe, 0x0a, 331}, /* 0x35 */ |
748 | { 0xfe,0x0a,331}, /* 0x35 */ | 749 | {0xf3, 0x09, 332}, /* 0x36 */ |
749 | { 0xf3,0x09,332}, /* 0x36 */ | 750 | {0xea, 0x08, 340}, /* 0x37 */ |
750 | { 0xea,0x08,340}, /* 0x37 */ | 751 | {0xe8, 0x07, 376}, /* 0x38 */ |
751 | { 0xe8,0x07,376}, /* 0x38 */ | 752 | {0xde, 0x06, 389}, /* 0x39 */ |
752 | { 0xde,0x06,389}, /* 0x39 */ | 753 | {0x52, 0x2a, 54}, /* 0x3a 301 TV */ |
753 | { 0x52,0x2a, 54}, /* 0x3a 301 TV */ | 754 | {0x52, 0x6a, 27}, /* 0x3b 301 TV */ |
754 | { 0x52,0x6a, 27}, /* 0x3b 301 TV */ | 755 | {0x62, 0x24, 70}, /* 0x3c 301 TV */ |
755 | { 0x62,0x24, 70}, /* 0x3c 301 TV */ | 756 | {0x62, 0x64, 70}, /* 0x3d 301 TV */ |
756 | { 0x62,0x64, 70}, /* 0x3d 301 TV */ | 757 | {0xa8, 0x4c, 30}, /* 0x3e 301 TV */ |
757 | { 0xa8,0x4c, 30}, /* 0x3e 301 TV */ | 758 | {0x20, 0x26, 33}, /* 0x3f 301 TV */ |
758 | { 0x20,0x26, 33}, /* 0x3f 301 TV */ | 759 | {0x31, 0xc2, 39}, /* 0x40 */ |
759 | { 0x31,0xc2, 39}, /* 0x40 */ | 760 | {0x60, 0x36, 30}, /* 0x41 Chrontel */ |
760 | { 0x60,0x36, 30}, /* 0x41 Chrontel */ | 761 | {0x40, 0x4a, 28}, /* 0x42 Chrontel */ |
761 | { 0x40,0x4a, 28}, /* 0x42 Chrontel */ | 762 | {0x9f, 0x46, 44}, /* 0x43 Chrontel */ |
762 | { 0x9f,0x46, 44}, /* 0x43 Chrontel */ | 763 | {0x97, 0x2c, 26}, /* 0x44 */ |
763 | { 0x97,0x2c, 26}, /* 0x44 */ | 764 | {0x44, 0xe4, 25}, /* 0x45 Chrontel */ |
764 | { 0x44,0xe4, 25}, /* 0x45 Chrontel */ | 765 | {0x7e, 0x32, 47}, /* 0x46 Chrontel */ |
765 | { 0x7e,0x32, 47}, /* 0x46 Chrontel */ | 766 | {0x8a, 0x24, 31}, /* 0x47 Chrontel */ |
766 | { 0x8a,0x24, 31}, /* 0x47 Chrontel */ | 767 | {0x97, 0x2c, 26}, /* 0x48 Chrontel */ |
767 | { 0x97,0x2c, 26}, /* 0x48 Chrontel */ | 768 | {0xce, 0x3c, 39}, /* 0x49 */ |
768 | { 0xce,0x3c, 39}, /* 0x49 */ | 769 | {0x52, 0x4a, 36}, /* 0x4a Chrontel */ |
769 | { 0x52,0x4a, 36}, /* 0x4a Chrontel */ | 770 | {0x34, 0x61, 95}, /* 0x4b */ |
770 | { 0x34,0x61, 95}, /* 0x4b */ | 771 | {0x78, 0x27, 108}, /* 0x4c - was 102 */ |
771 | { 0x78,0x27,108}, /* 0x4c - was 102 */ | 772 | {0x66, 0x43, 123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */ |
772 | { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */ | 773 | {0x41, 0x4e, 21}, /* 0x4e */ |
773 | { 0x41,0x4e, 21}, /* 0x4e */ | 774 | {0xa1, 0x4a, 29}, /* 0x4f Chrontel */ |
774 | { 0xa1,0x4a, 29}, /* 0x4f Chrontel */ | 775 | {0x19, 0x42, 42}, /* 0x50 */ |
775 | { 0x19,0x42, 42}, /* 0x50 */ | 776 | {0x54, 0x46, 58}, /* 0x51 Chrontel */ |
776 | { 0x54,0x46, 58}, /* 0x51 Chrontel */ | 777 | {0x25, 0x42, 61}, /* 0x52 */ |
777 | { 0x25,0x42, 61}, /* 0x52 */ | 778 | {0x44, 0x44, 66}, /* 0x53 Chrontel */ |
778 | { 0x44,0x44, 66}, /* 0x53 Chrontel */ | 779 | {0x3a, 0x62, 70}, /* 0x54 Chrontel */ |
779 | { 0x3a,0x62, 70}, /* 0x54 Chrontel */ | 780 | {0x62, 0xc6, 34}, /* 0x55 848x480-60 */ |
780 | { 0x62,0xc6, 34}, /* 0x55 848x480-60 */ | 781 | {0x6a, 0xc6, 37}, /* 0x56 848x480-75 - TEMP */ |
781 | { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */ | 782 | {0xbf, 0xc8, 35}, /* 0x57 856x480-38i,60 */ |
782 | { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */ | 783 | {0x30, 0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */ |
783 | { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */ | 784 | {0x52, 0x07, 149}, /* 0x59 1280x960-85 */ |
784 | { 0x52,0x07,149}, /* 0x59 1280x960-85 */ | 785 | {0x56, 0x07, 156}, /* 0x5a 1400x1050-75 */ |
785 | { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */ | 786 | {0x70, 0x29, 81}, /* 0x5b 1280x768 LCD */ |
786 | { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */ | 787 | {0x45, 0x25, 83}, /* 0x5c 1280x800 */ |
787 | { 0x45,0x25, 83}, /* 0x5c 1280x800 */ | 788 | {0x70, 0x0a, 147}, /* 0x5d 1680x1050 */ |
788 | { 0x70,0x0a,147}, /* 0x5d 1680x1050 */ | 789 | {0x70, 0x24, 162}, /* 0x5e 1600x1200 */ |
789 | { 0x70,0x24,162}, /* 0x5e 1600x1200 */ | 790 | {0x5a, 0x64, 65}, /* 0x5f 1280x720 - temp */ |
790 | { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */ | 791 | {0x63, 0x46, 68}, /* 0x60 1280x768_2 */ |
791 | { 0x63,0x46, 68}, /* 0x60 1280x768_2 */ | 792 | {0x31, 0x42, 79}, /* 0x61 1280x768_3 - temp */ |
792 | { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */ | 793 | {0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */ |
793 | { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */ | 794 | {0x5a, 0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */ |
794 | { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */ | 795 | {0x70, 0x28, 90}, /* 0x64 1152x864@60 */ |
795 | { 0x70,0x28, 90}, /* 0x64 1152x864@60 */ | 796 | {0x41, 0xc4, 32}, /* 0x65 848x480@60 */ |
796 | { 0x41,0xc4, 32}, /* 0x65 848x480@60 */ | 797 | {0x5c, 0xc6, 32}, /* 0x66 856x480@60 */ |
797 | { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */ | 798 | {0x76, 0xe7, 27}, /* 0x67 720x480@60 */ |
798 | { 0x76,0xe7, 27}, /* 0x67 720x480@60 */ | 799 | {0x5f, 0xc6, 33}, /* 0x68 720/768x576@60 */ |
799 | { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */ | 800 | {0x52, 0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */ |
800 | { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */ | 801 | {0x7c, 0x6b, 38}, /* 0x6a 960x540@60 */ |
801 | { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */ | 802 | {0xe3, 0x56, 41}, /* 0x6b 960x600@60 */ |
802 | { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */ | 803 | {0x45, 0x25, 83}, /* 0x6c 1280x800 */ |
803 | { 0x45,0x25, 83}, /* 0x6c 1280x800 */ | 804 | {0x70, 0x28, 90}, /* 0x6d 1152x864@60 */ |
804 | { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */ | 805 | {0x15, 0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */ |
805 | { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */ | 806 | {0x5f, 0xc6, 33}, /* 0x6f 720x576@60 */ |
806 | { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */ | 807 | {0x37, 0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */ |
807 | { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */ | 808 | {0x2b, 0xc2, 35} /* 0x71 768@576@60 */ |
808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ | ||
809 | }; | 809 | }; |
810 | 810 | ||
811 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | 811 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); |
812 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); | 812 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); |
813 | 813 | ||
814 | extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); | 814 | extern int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); |
815 | extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); | 815 | extern int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 * data); |
816 | extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, | 816 | extern int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, |
817 | u8 index, u8 data); | 817 | u8 index, u8 data); |
818 | extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, | 818 | extern int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, |
819 | u8 index, u8 *data); | 819 | u8 index, u8 * data); |
820 | extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, | 820 | extern int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, |
821 | u8 idx, u8 myand, u8 myor); | 821 | u8 idx, u8 myand, u8 myor); |
822 | extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, | 822 | extern int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, |
823 | u8 index, u8 myor); | 823 | u8 index, u8 myor); |
824 | extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, | 824 | extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, |
825 | u8 idx, u8 myand); | 825 | u8 idx, u8 myand); |
826 | 826 | ||
827 | void sisusb_delete(struct kref *kref); | 827 | void sisusb_delete(struct kref *kref); |
828 | int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); | 828 | int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); |
829 | int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); | 829 | int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 * data); |
830 | int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, | 830 | int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, |
831 | u32 dest, int length, size_t *bytes_written); | 831 | u32 dest, int length, size_t * bytes_written); |
832 | int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); | 832 | int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); |
833 | int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, | 833 | int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, |
834 | u8 *arg, int cmapsz, int ch512, int dorecalc, | 834 | u8 * arg, int cmapsz, int ch512, int dorecalc, |
835 | struct vc_data *c, int fh, int uplock); | 835 | struct vc_data *c, int fh, int uplock); |
836 | void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); | 836 | void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); |
837 | int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); | 837 | int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); |
@@ -839,4 +839,3 @@ void sisusb_console_exit(struct sisusb_usb_data *sisusb); | |||
839 | void sisusb_init_concode(void); | 839 | void sisusb_init_concode(void); |
840 | 840 | ||
841 | #endif | 841 | #endif |
842 | |||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h index f325ecb29a61..1c4240e802c1 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_struct.h +++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h | |||
@@ -44,7 +44,7 @@ | |||
44 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 44 | * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
45 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 45 | * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
46 | * | 46 | * |
47 | * Author: Thomas Winischhofer <thomas@winischhofer.net> | 47 | * Author: Thomas Winischhofer <thomas@winischhofer.net> |
48 | * | 48 | * |
49 | */ | 49 | */ |
50 | 50 | ||
@@ -52,85 +52,78 @@ | |||
52 | #define _SISUSB_STRUCT_H_ | 52 | #define _SISUSB_STRUCT_H_ |
53 | 53 | ||
54 | struct SiS_St { | 54 | struct SiS_St { |
55 | unsigned char St_ModeID; | 55 | unsigned char St_ModeID; |
56 | unsigned short St_ModeFlag; | 56 | unsigned short St_ModeFlag; |
57 | unsigned char St_StTableIndex; | 57 | unsigned char St_StTableIndex; |
58 | unsigned char St_CRT2CRTC; | 58 | unsigned char St_CRT2CRTC; |
59 | unsigned char St_ResInfo; | 59 | unsigned char St_ResInfo; |
60 | unsigned char VB_StTVFlickerIndex; | 60 | unsigned char VB_StTVFlickerIndex; |
61 | unsigned char VB_StTVEdgeIndex; | 61 | unsigned char VB_StTVEdgeIndex; |
62 | unsigned char VB_StTVYFilterIndex; | 62 | unsigned char VB_StTVYFilterIndex; |
63 | unsigned char St_PDC; | 63 | unsigned char St_PDC; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct SiS_StandTable | 66 | struct SiS_StandTable { |
67 | { | 67 | unsigned char CRT_COLS; |
68 | unsigned char CRT_COLS; | 68 | unsigned char ROWS; |
69 | unsigned char ROWS; | 69 | unsigned char CHAR_HEIGHT; |
70 | unsigned char CHAR_HEIGHT; | 70 | unsigned short CRT_LEN; |
71 | unsigned short CRT_LEN; | 71 | unsigned char SR[4]; |
72 | unsigned char SR[4]; | 72 | unsigned char MISC; |
73 | unsigned char MISC; | 73 | unsigned char CRTC[0x19]; |
74 | unsigned char CRTC[0x19]; | 74 | unsigned char ATTR[0x14]; |
75 | unsigned char ATTR[0x14]; | 75 | unsigned char GRC[9]; |
76 | unsigned char GRC[9]; | ||
77 | }; | 76 | }; |
78 | 77 | ||
79 | struct SiS_StResInfo_S { | 78 | struct SiS_StResInfo_S { |
80 | unsigned short HTotal; | 79 | unsigned short HTotal; |
81 | unsigned short VTotal; | 80 | unsigned short VTotal; |
82 | }; | 81 | }; |
83 | 82 | ||
84 | struct SiS_Ext | 83 | struct SiS_Ext { |
85 | { | 84 | unsigned char Ext_ModeID; |
86 | unsigned char Ext_ModeID; | 85 | unsigned short Ext_ModeFlag; |
87 | unsigned short Ext_ModeFlag; | 86 | unsigned short Ext_VESAID; |
88 | unsigned short Ext_VESAID; | 87 | unsigned char Ext_RESINFO; |
89 | unsigned char Ext_RESINFO; | 88 | unsigned char VB_ExtTVFlickerIndex; |
90 | unsigned char VB_ExtTVFlickerIndex; | 89 | unsigned char VB_ExtTVEdgeIndex; |
91 | unsigned char VB_ExtTVEdgeIndex; | 90 | unsigned char VB_ExtTVYFilterIndex; |
92 | unsigned char VB_ExtTVYFilterIndex; | 91 | unsigned char VB_ExtTVYFilterIndexROM661; |
93 | unsigned char VB_ExtTVYFilterIndexROM661; | 92 | unsigned char REFindex; |
94 | unsigned char REFindex; | 93 | char ROMMODEIDX661; |
95 | char ROMMODEIDX661; | ||
96 | }; | 94 | }; |
97 | 95 | ||
98 | struct SiS_Ext2 | 96 | struct SiS_Ext2 { |
99 | { | 97 | unsigned short Ext_InfoFlag; |
100 | unsigned short Ext_InfoFlag; | 98 | unsigned char Ext_CRT1CRTC; |
101 | unsigned char Ext_CRT1CRTC; | 99 | unsigned char Ext_CRTVCLK; |
102 | unsigned char Ext_CRTVCLK; | 100 | unsigned char Ext_CRT2CRTC; |
103 | unsigned char Ext_CRT2CRTC; | 101 | unsigned char Ext_CRT2CRTC_NS; |
104 | unsigned char Ext_CRT2CRTC_NS; | 102 | unsigned char ModeID; |
105 | unsigned char ModeID; | 103 | unsigned short XRes; |
106 | unsigned short XRes; | 104 | unsigned short YRes; |
107 | unsigned short YRes; | 105 | unsigned char Ext_PDC; |
108 | unsigned char Ext_PDC; | 106 | unsigned char Ext_FakeCRT2CRTC; |
109 | unsigned char Ext_FakeCRT2CRTC; | 107 | unsigned char Ext_FakeCRT2Clk; |
110 | unsigned char Ext_FakeCRT2Clk; | ||
111 | }; | 108 | }; |
112 | 109 | ||
113 | struct SiS_CRT1Table | 110 | struct SiS_CRT1Table { |
114 | { | 111 | unsigned char CR[17]; |
115 | unsigned char CR[17]; | ||
116 | }; | 112 | }; |
117 | 113 | ||
118 | struct SiS_VCLKData | 114 | struct SiS_VCLKData { |
119 | { | 115 | unsigned char SR2B, SR2C; |
120 | unsigned char SR2B,SR2C; | 116 | unsigned short CLOCK; |
121 | unsigned short CLOCK; | ||
122 | }; | 117 | }; |
123 | 118 | ||
124 | struct SiS_ModeResInfo | 119 | struct SiS_ModeResInfo { |
125 | { | 120 | unsigned short HTotal; |
126 | unsigned short HTotal; | 121 | unsigned short VTotal; |
127 | unsigned short VTotal; | 122 | unsigned char XChar; |
128 | unsigned char XChar; | 123 | unsigned char YChar; |
129 | unsigned char YChar; | ||
130 | }; | 124 | }; |
131 | 125 | ||
132 | struct SiS_Private | 126 | struct SiS_Private { |
133 | { | ||
134 | void *sisusb; | 127 | void *sisusb; |
135 | 128 | ||
136 | unsigned long IOAddress; | 129 | unsigned long IOAddress; |
@@ -151,19 +144,18 @@ struct SiS_Private | |||
151 | unsigned long SiS_P3da; | 144 | unsigned long SiS_P3da; |
152 | unsigned long SiS_Part1Port; | 145 | unsigned long SiS_Part1Port; |
153 | 146 | ||
154 | unsigned char SiS_MyCR63; | 147 | unsigned char SiS_MyCR63; |
155 | unsigned short SiS_CRT1Mode; | 148 | unsigned short SiS_CRT1Mode; |
156 | unsigned short SiS_ModeType; | 149 | unsigned short SiS_ModeType; |
157 | unsigned short SiS_SetFlag; | 150 | unsigned short SiS_SetFlag; |
158 | 151 | ||
159 | const struct SiS_StandTable *SiS_StandTable; | 152 | const struct SiS_StandTable *SiS_StandTable; |
160 | const struct SiS_St *SiS_SModeIDTable; | 153 | const struct SiS_St *SiS_SModeIDTable; |
161 | const struct SiS_Ext *SiS_EModeIDTable; | 154 | const struct SiS_Ext *SiS_EModeIDTable; |
162 | const struct SiS_Ext2 *SiS_RefIndex; | 155 | const struct SiS_Ext2 *SiS_RefIndex; |
163 | const struct SiS_CRT1Table *SiS_CRT1Table; | 156 | const struct SiS_CRT1Table *SiS_CRT1Table; |
164 | const struct SiS_VCLKData *SiS_VCLKData; | 157 | const struct SiS_VCLKData *SiS_VCLKData; |
165 | const struct SiS_ModeResInfo *SiS_ModeResInfo; | 158 | const struct SiS_ModeResInfo *SiS_ModeResInfo; |
166 | }; | 159 | }; |
167 | 160 | ||
168 | #endif | 161 | #endif |
169 | |||
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index c03dfd7a9d36..f06e4e2b49d3 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -172,6 +172,10 @@ static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp, | |||
172 | 172 | ||
173 | #define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0) | 173 | #define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0) |
174 | 174 | ||
175 | static unsigned char xfer_to_pipe[4] = { | ||
176 | PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT | ||
177 | }; | ||
178 | |||
175 | static struct class *mon_bin_class; | 179 | static struct class *mon_bin_class; |
176 | static dev_t mon_bin_dev0; | 180 | static dev_t mon_bin_dev0; |
177 | static struct cdev mon_bin_cdev; | 181 | static struct cdev mon_bin_cdev; |
@@ -354,13 +358,9 @@ static inline char mon_bin_get_setup(unsigned char *setupb, | |||
354 | const struct urb *urb, char ev_type) | 358 | const struct urb *urb, char ev_type) |
355 | { | 359 | { |
356 | 360 | ||
357 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') | 361 | if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S') |
358 | return '-'; | 362 | return '-'; |
359 | 363 | ||
360 | if (urb->dev->bus->uses_dma && | ||
361 | (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | ||
362 | return mon_dmapeek(setupb, urb->setup_dma, SETUP_LEN); | ||
363 | } | ||
364 | if (urb->setup_packet == NULL) | 364 | if (urb->setup_packet == NULL) |
365 | return 'Z'; | 365 | return 'Z'; |
366 | 366 | ||
@@ -386,13 +386,15 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp, | |||
386 | } | 386 | } |
387 | 387 | ||
388 | static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | 388 | static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, |
389 | char ev_type) | 389 | char ev_type, int status) |
390 | { | 390 | { |
391 | const struct usb_endpoint_descriptor *epd = &urb->ep->desc; | ||
391 | unsigned long flags; | 392 | unsigned long flags; |
392 | struct timeval ts; | 393 | struct timeval ts; |
393 | unsigned int urb_length; | 394 | unsigned int urb_length; |
394 | unsigned int offset; | 395 | unsigned int offset; |
395 | unsigned int length; | 396 | unsigned int length; |
397 | unsigned char dir; | ||
396 | struct mon_bin_hdr *ep; | 398 | struct mon_bin_hdr *ep; |
397 | char data_tag = 0; | 399 | char data_tag = 0; |
398 | 400 | ||
@@ -410,16 +412,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | |||
410 | if (length >= rp->b_size/5) | 412 | if (length >= rp->b_size/5) |
411 | length = rp->b_size/5; | 413 | length = rp->b_size/5; |
412 | 414 | ||
413 | if (usb_pipein(urb->pipe)) { | 415 | if (usb_urb_dir_in(urb)) { |
414 | if (ev_type == 'S') { | 416 | if (ev_type == 'S') { |
415 | length = 0; | 417 | length = 0; |
416 | data_tag = '<'; | 418 | data_tag = '<'; |
417 | } | 419 | } |
420 | /* Cannot rely on endpoint number in case of control ep.0 */ | ||
421 | dir = USB_DIR_IN; | ||
418 | } else { | 422 | } else { |
419 | if (ev_type == 'C') { | 423 | if (ev_type == 'C') { |
420 | length = 0; | 424 | length = 0; |
421 | data_tag = '>'; | 425 | data_tag = '>'; |
422 | } | 426 | } |
427 | dir = 0; | ||
423 | } | 428 | } |
424 | 429 | ||
425 | if (rp->mmap_active) | 430 | if (rp->mmap_active) |
@@ -440,15 +445,14 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | |||
440 | */ | 445 | */ |
441 | memset(ep, 0, PKT_SIZE); | 446 | memset(ep, 0, PKT_SIZE); |
442 | ep->type = ev_type; | 447 | ep->type = ev_type; |
443 | ep->xfer_type = usb_pipetype(urb->pipe); | 448 | ep->xfer_type = xfer_to_pipe[usb_endpoint_type(epd)]; |
444 | /* We use the fact that usb_pipein() returns 0x80 */ | 449 | ep->epnum = dir | usb_endpoint_num(epd); |
445 | ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); | 450 | ep->devnum = urb->dev->devnum; |
446 | ep->devnum = usb_pipedevice(urb->pipe); | ||
447 | ep->busnum = urb->dev->bus->busnum; | 451 | ep->busnum = urb->dev->bus->busnum; |
448 | ep->id = (unsigned long) urb; | 452 | ep->id = (unsigned long) urb; |
449 | ep->ts_sec = ts.tv_sec; | 453 | ep->ts_sec = ts.tv_sec; |
450 | ep->ts_usec = ts.tv_usec; | 454 | ep->ts_usec = ts.tv_usec; |
451 | ep->status = urb->status; | 455 | ep->status = status; |
452 | ep->len_urb = urb_length; | 456 | ep->len_urb = urb_length; |
453 | ep->len_cap = length; | 457 | ep->len_cap = length; |
454 | 458 | ||
@@ -471,13 +475,13 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | |||
471 | static void mon_bin_submit(void *data, struct urb *urb) | 475 | static void mon_bin_submit(void *data, struct urb *urb) |
472 | { | 476 | { |
473 | struct mon_reader_bin *rp = data; | 477 | struct mon_reader_bin *rp = data; |
474 | mon_bin_event(rp, urb, 'S'); | 478 | mon_bin_event(rp, urb, 'S', -EINPROGRESS); |
475 | } | 479 | } |
476 | 480 | ||
477 | static void mon_bin_complete(void *data, struct urb *urb) | 481 | static void mon_bin_complete(void *data, struct urb *urb, int status) |
478 | { | 482 | { |
479 | struct mon_reader_bin *rp = data; | 483 | struct mon_reader_bin *rp = data; |
480 | mon_bin_event(rp, urb, 'C'); | 484 | mon_bin_event(rp, urb, 'C', status); |
481 | } | 485 | } |
482 | 486 | ||
483 | static void mon_bin_error(void *data, struct urb *urb, int error) | 487 | static void mon_bin_error(void *data, struct urb *urb, int error) |
@@ -500,10 +504,10 @@ static void mon_bin_error(void *data, struct urb *urb, int error) | |||
500 | 504 | ||
501 | memset(ep, 0, PKT_SIZE); | 505 | memset(ep, 0, PKT_SIZE); |
502 | ep->type = 'E'; | 506 | ep->type = 'E'; |
503 | ep->xfer_type = usb_pipetype(urb->pipe); | 507 | ep->xfer_type = xfer_to_pipe[usb_endpoint_type(&urb->ep->desc)]; |
504 | /* We use the fact that usb_pipein() returns 0x80 */ | 508 | ep->epnum = usb_urb_dir_in(urb) ? USB_DIR_IN : 0; |
505 | ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); | 509 | ep->epnum |= usb_endpoint_num(&urb->ep->desc); |
506 | ep->devnum = usb_pipedevice(urb->pipe); | 510 | ep->devnum = urb->dev->devnum; |
507 | ep->busnum = urb->dev->bus->busnum; | 511 | ep->busnum = urb->dev->bus->busnum; |
508 | ep->id = (unsigned long) urb; | 512 | ep->id = (unsigned long) urb; |
509 | ep->status = error; | 513 | ep->status = error; |
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index ce61d8b0fd86..b371ffd39d36 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -129,7 +129,8 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) | |||
129 | 129 | ||
130 | /* | 130 | /* |
131 | */ | 131 | */ |
132 | static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb) | 132 | static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, |
133 | int status) | ||
133 | { | 134 | { |
134 | unsigned long flags; | 135 | unsigned long flags; |
135 | struct list_head *pos; | 136 | struct list_head *pos; |
@@ -139,28 +140,18 @@ static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb) | |||
139 | mbus->cnt_events++; | 140 | mbus->cnt_events++; |
140 | list_for_each (pos, &mbus->r_list) { | 141 | list_for_each (pos, &mbus->r_list) { |
141 | r = list_entry(pos, struct mon_reader, r_link); | 142 | r = list_entry(pos, struct mon_reader, r_link); |
142 | r->rnf_complete(r->r_data, urb); | 143 | r->rnf_complete(r->r_data, urb, status); |
143 | } | 144 | } |
144 | spin_unlock_irqrestore(&mbus->lock, flags); | 145 | spin_unlock_irqrestore(&mbus->lock, flags); |
145 | } | 146 | } |
146 | 147 | ||
147 | static void mon_complete(struct usb_bus *ubus, struct urb *urb) | 148 | static void mon_complete(struct usb_bus *ubus, struct urb *urb, int status) |
148 | { | 149 | { |
149 | struct mon_bus *mbus; | 150 | struct mon_bus *mbus; |
150 | 151 | ||
151 | mbus = ubus->mon_bus; | 152 | if ((mbus = ubus->mon_bus) != NULL) |
152 | if (mbus == NULL) { | 153 | mon_bus_complete(mbus, urb, status); |
153 | /* | 154 | mon_bus_complete(&mon_bus0, urb, status); |
154 | * This should not happen. | ||
155 | * At this point we do not even know the bus number... | ||
156 | */ | ||
157 | printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n", | ||
158 | urb->pipe); | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | mon_bus_complete(mbus, urb); | ||
163 | mon_bus_complete(&mon_bus0, urb); | ||
164 | } | 155 | } |
165 | 156 | ||
166 | /* int (*unlink_urb) (struct urb *urb, int status); */ | 157 | /* int (*unlink_urb) (struct urb *urb, int status); */ |
@@ -170,7 +161,7 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb) | |||
170 | */ | 161 | */ |
171 | static void mon_stop(struct mon_bus *mbus) | 162 | static void mon_stop(struct mon_bus *mbus) |
172 | { | 163 | { |
173 | struct usb_bus *ubus = mbus->u_bus; | 164 | struct usb_bus *ubus; |
174 | struct list_head *p; | 165 | struct list_head *p; |
175 | 166 | ||
176 | if (mbus == &mon_bus0) { | 167 | if (mbus == &mon_bus0) { |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 8f27a9e1c36b..ebb04ac4857b 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -50,10 +50,13 @@ struct mon_iso_desc { | |||
50 | struct mon_event_text { | 50 | struct mon_event_text { |
51 | struct list_head e_link; | 51 | struct list_head e_link; |
52 | int type; /* submit, complete, etc. */ | 52 | int type; /* submit, complete, etc. */ |
53 | unsigned int pipe; /* Pipe */ | ||
54 | unsigned long id; /* From pointer, most of the time */ | 53 | unsigned long id; /* From pointer, most of the time */ |
55 | unsigned int tstamp; | 54 | unsigned int tstamp; |
56 | int busnum; | 55 | int busnum; |
56 | char devnum; | ||
57 | char epnum; | ||
58 | char is_in; | ||
59 | char xfertype; | ||
57 | int length; /* Depends on type: xfer length or act length */ | 60 | int length; /* Depends on type: xfer length or act length */ |
58 | int status; | 61 | int status; |
59 | int interval; | 62 | int interval; |
@@ -121,13 +124,9 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, | |||
121 | struct urb *urb, char ev_type, struct mon_bus *mbus) | 124 | struct urb *urb, char ev_type, struct mon_bus *mbus) |
122 | { | 125 | { |
123 | 126 | ||
124 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') | 127 | if (ep->xfertype != USB_ENDPOINT_XFER_CONTROL || ev_type != 'S') |
125 | return '-'; | 128 | return '-'; |
126 | 129 | ||
127 | if (urb->dev->bus->uses_dma && | ||
128 | (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { | ||
129 | return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX); | ||
130 | } | ||
131 | if (urb->setup_packet == NULL) | 130 | if (urb->setup_packet == NULL) |
132 | return 'Z'; /* '0' would be not as pretty. */ | 131 | return 'Z'; /* '0' would be not as pretty. */ |
133 | 132 | ||
@@ -138,14 +137,12 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, | |||
138 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | 137 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, |
139 | int len, char ev_type, struct mon_bus *mbus) | 138 | int len, char ev_type, struct mon_bus *mbus) |
140 | { | 139 | { |
141 | int pipe = urb->pipe; | ||
142 | |||
143 | if (len <= 0) | 140 | if (len <= 0) |
144 | return 'L'; | 141 | return 'L'; |
145 | if (len >= DATA_MAX) | 142 | if (len >= DATA_MAX) |
146 | len = DATA_MAX; | 143 | len = DATA_MAX; |
147 | 144 | ||
148 | if (usb_pipein(pipe)) { | 145 | if (ep->is_in) { |
149 | if (ev_type != 'C') | 146 | if (ev_type != 'C') |
150 | return '<'; | 147 | return '<'; |
151 | } else { | 148 | } else { |
@@ -186,7 +183,7 @@ static inline unsigned int mon_get_timestamp(void) | |||
186 | } | 183 | } |
187 | 184 | ||
188 | static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | 185 | static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, |
189 | char ev_type) | 186 | char ev_type, int status) |
190 | { | 187 | { |
191 | struct mon_event_text *ep; | 188 | struct mon_event_text *ep; |
192 | unsigned int stamp; | 189 | unsigned int stamp; |
@@ -203,24 +200,28 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | |||
203 | } | 200 | } |
204 | 201 | ||
205 | ep->type = ev_type; | 202 | ep->type = ev_type; |
206 | ep->pipe = urb->pipe; | ||
207 | ep->id = (unsigned long) urb; | 203 | ep->id = (unsigned long) urb; |
208 | ep->busnum = urb->dev->bus->busnum; | 204 | ep->busnum = urb->dev->bus->busnum; |
205 | ep->devnum = urb->dev->devnum; | ||
206 | ep->epnum = usb_endpoint_num(&urb->ep->desc); | ||
207 | ep->xfertype = usb_endpoint_type(&urb->ep->desc); | ||
208 | ep->is_in = usb_urb_dir_in(urb); | ||
209 | ep->tstamp = stamp; | 209 | ep->tstamp = stamp; |
210 | ep->length = (ev_type == 'S') ? | 210 | ep->length = (ev_type == 'S') ? |
211 | urb->transfer_buffer_length : urb->actual_length; | 211 | urb->transfer_buffer_length : urb->actual_length; |
212 | /* Collecting status makes debugging sense for submits, too */ | 212 | /* Collecting status makes debugging sense for submits, too */ |
213 | ep->status = urb->status; | 213 | ep->status = status; |
214 | 214 | ||
215 | if (usb_pipeint(urb->pipe)) { | 215 | if (ep->xfertype == USB_ENDPOINT_XFER_INT) { |
216 | ep->interval = urb->interval; | 216 | ep->interval = urb->interval; |
217 | } else if (usb_pipeisoc(urb->pipe)) { | 217 | } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { |
218 | ep->interval = urb->interval; | 218 | ep->interval = urb->interval; |
219 | ep->start_frame = urb->start_frame; | 219 | ep->start_frame = urb->start_frame; |
220 | ep->error_count = urb->error_count; | 220 | ep->error_count = urb->error_count; |
221 | } | 221 | } |
222 | ep->numdesc = urb->number_of_packets; | 222 | ep->numdesc = urb->number_of_packets; |
223 | if (usb_pipeisoc(urb->pipe) && urb->number_of_packets > 0) { | 223 | if (ep->xfertype == USB_ENDPOINT_XFER_ISOC && |
224 | urb->number_of_packets > 0) { | ||
224 | if ((ndesc = urb->number_of_packets) > ISODESC_MAX) | 225 | if ((ndesc = urb->number_of_packets) > ISODESC_MAX) |
225 | ndesc = ISODESC_MAX; | 226 | ndesc = ISODESC_MAX; |
226 | fp = urb->iso_frame_desc; | 227 | fp = urb->iso_frame_desc; |
@@ -247,13 +248,13 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | |||
247 | static void mon_text_submit(void *data, struct urb *urb) | 248 | static void mon_text_submit(void *data, struct urb *urb) |
248 | { | 249 | { |
249 | struct mon_reader_text *rp = data; | 250 | struct mon_reader_text *rp = data; |
250 | mon_text_event(rp, urb, 'S'); | 251 | mon_text_event(rp, urb, 'S', -EINPROGRESS); |
251 | } | 252 | } |
252 | 253 | ||
253 | static void mon_text_complete(void *data, struct urb *urb) | 254 | static void mon_text_complete(void *data, struct urb *urb, int status) |
254 | { | 255 | { |
255 | struct mon_reader_text *rp = data; | 256 | struct mon_reader_text *rp = data; |
256 | mon_text_event(rp, urb, 'C'); | 257 | mon_text_event(rp, urb, 'C', status); |
257 | } | 258 | } |
258 | 259 | ||
259 | static void mon_text_error(void *data, struct urb *urb, int error) | 260 | static void mon_text_error(void *data, struct urb *urb, int error) |
@@ -268,9 +269,12 @@ static void mon_text_error(void *data, struct urb *urb, int error) | |||
268 | } | 269 | } |
269 | 270 | ||
270 | ep->type = 'E'; | 271 | ep->type = 'E'; |
271 | ep->pipe = urb->pipe; | ||
272 | ep->id = (unsigned long) urb; | 272 | ep->id = (unsigned long) urb; |
273 | ep->busnum = 0; | 273 | ep->busnum = 0; |
274 | ep->devnum = urb->dev->devnum; | ||
275 | ep->epnum = usb_endpoint_num(&urb->ep->desc); | ||
276 | ep->xfertype = usb_endpoint_type(&urb->ep->desc); | ||
277 | ep->is_in = usb_urb_dir_in(urb); | ||
274 | ep->tstamp = 0; | 278 | ep->tstamp = 0; |
275 | ep->length = 0; | 279 | ep->length = 0; |
276 | ep->status = error; | 280 | ep->status = error; |
@@ -413,10 +417,10 @@ static ssize_t mon_text_read_u(struct file *file, char __user *buf, | |||
413 | mon_text_read_head_u(rp, &ptr, ep); | 417 | mon_text_read_head_u(rp, &ptr, ep); |
414 | if (ep->type == 'E') { | 418 | if (ep->type == 'E') { |
415 | mon_text_read_statset(rp, &ptr, ep); | 419 | mon_text_read_statset(rp, &ptr, ep); |
416 | } else if (usb_pipeisoc(ep->pipe)) { | 420 | } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { |
417 | mon_text_read_isostat(rp, &ptr, ep); | 421 | mon_text_read_isostat(rp, &ptr, ep); |
418 | mon_text_read_isodesc(rp, &ptr, ep); | 422 | mon_text_read_isodesc(rp, &ptr, ep); |
419 | } else if (usb_pipeint(ep->pipe)) { | 423 | } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { |
420 | mon_text_read_intstat(rp, &ptr, ep); | 424 | mon_text_read_intstat(rp, &ptr, ep); |
421 | } else { | 425 | } else { |
422 | mon_text_read_statset(rp, &ptr, ep); | 426 | mon_text_read_statset(rp, &ptr, ep); |
@@ -468,18 +472,17 @@ static void mon_text_read_head_t(struct mon_reader_text *rp, | |||
468 | { | 472 | { |
469 | char udir, utype; | 473 | char udir, utype; |
470 | 474 | ||
471 | udir = usb_pipein(ep->pipe) ? 'i' : 'o'; | 475 | udir = (ep->is_in ? 'i' : 'o'); |
472 | switch (usb_pipetype(ep->pipe)) { | 476 | switch (ep->xfertype) { |
473 | case PIPE_ISOCHRONOUS: utype = 'Z'; break; | 477 | case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break; |
474 | case PIPE_INTERRUPT: utype = 'I'; break; | 478 | case USB_ENDPOINT_XFER_INT: utype = 'I'; break; |
475 | case PIPE_CONTROL: utype = 'C'; break; | 479 | case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break; |
476 | default: /* PIPE_BULK */ utype = 'B'; | 480 | default: /* PIPE_BULK */ utype = 'B'; |
477 | } | 481 | } |
478 | p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, | 482 | p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, |
479 | "%lx %u %c %c%c:%03u:%02u", | 483 | "%lx %u %c %c%c:%03u:%02u", |
480 | ep->id, ep->tstamp, ep->type, | 484 | ep->id, ep->tstamp, ep->type, |
481 | utype, udir, | 485 | utype, udir, ep->devnum, ep->epnum); |
482 | usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); | ||
483 | } | 486 | } |
484 | 487 | ||
485 | static void mon_text_read_head_u(struct mon_reader_text *rp, | 488 | static void mon_text_read_head_u(struct mon_reader_text *rp, |
@@ -487,18 +490,17 @@ static void mon_text_read_head_u(struct mon_reader_text *rp, | |||
487 | { | 490 | { |
488 | char udir, utype; | 491 | char udir, utype; |
489 | 492 | ||
490 | udir = usb_pipein(ep->pipe) ? 'i' : 'o'; | 493 | udir = (ep->is_in ? 'i' : 'o'); |
491 | switch (usb_pipetype(ep->pipe)) { | 494 | switch (ep->xfertype) { |
492 | case PIPE_ISOCHRONOUS: utype = 'Z'; break; | 495 | case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break; |
493 | case PIPE_INTERRUPT: utype = 'I'; break; | 496 | case USB_ENDPOINT_XFER_INT: utype = 'I'; break; |
494 | case PIPE_CONTROL: utype = 'C'; break; | 497 | case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break; |
495 | default: /* PIPE_BULK */ utype = 'B'; | 498 | default: /* PIPE_BULK */ utype = 'B'; |
496 | } | 499 | } |
497 | p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, | 500 | p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, |
498 | "%lx %u %c %c%c:%d:%03u:%u", | 501 | "%lx %u %c %c%c:%d:%03u:%u", |
499 | ep->id, ep->tstamp, ep->type, | 502 | ep->id, ep->tstamp, ep->type, |
500 | utype, udir, | 503 | utype, udir, ep->busnum, ep->devnum, ep->epnum); |
501 | ep->busnum, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); | ||
502 | } | 504 | } |
503 | 505 | ||
504 | static void mon_text_read_statset(struct mon_reader_text *rp, | 506 | static void mon_text_read_statset(struct mon_reader_text *rp, |
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index f68ad6d99ad7..f5d84ff8c101 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h | |||
@@ -46,7 +46,7 @@ struct mon_reader { | |||
46 | 46 | ||
47 | void (*rnf_submit)(void *data, struct urb *urb); | 47 | void (*rnf_submit)(void *data, struct urb *urb); |
48 | void (*rnf_error)(void *data, struct urb *urb, int error); | 48 | void (*rnf_error)(void *data, struct urb *urb, int error); |
49 | void (*rnf_complete)(void *data, struct urb *urb); | 49 | void (*rnf_complete)(void *data, struct urb *urb, int status); |
50 | }; | 50 | }; |
51 | 51 | ||
52 | void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r); | 52 | void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r); |
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 43d6db696f90..99fefed77919 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -92,6 +92,16 @@ config USB_SERIAL_BELKIN | |||
92 | To compile this driver as a module, choose M here: the | 92 | To compile this driver as a module, choose M here: the |
93 | module will be called belkin_sa. | 93 | module will be called belkin_sa. |
94 | 94 | ||
95 | config USB_SERIAL_CH341 | ||
96 | tristate "USB Winchiphead CH341 Single Port Serial Driver" | ||
97 | depends on USB_SERIAL | ||
98 | help | ||
99 | Say Y here if you want to use a Winchiphead CH341 single port | ||
100 | USB to serial adapter. | ||
101 | |||
102 | To compile this driver as a module, choose M here: the | ||
103 | module will be called ch341. | ||
104 | |||
95 | config USB_SERIAL_WHITEHEAT | 105 | config USB_SERIAL_WHITEHEAT |
96 | tristate "USB ConnectTech WhiteHEAT Serial Driver" | 106 | tristate "USB ConnectTech WhiteHEAT Serial Driver" |
97 | depends on USB_SERIAL | 107 | depends on USB_SERIAL |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 07a976eca6b7..d6fb384e52b2 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o | |||
15 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o | 15 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o |
16 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o | 16 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o |
17 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o | 17 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o |
18 | obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o | ||
18 | obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o | 19 | obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o |
19 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o | 20 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o |
20 | obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o | 21 | obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o |
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index c9fd486c1c7d..2a8e537cb046 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -172,11 +172,6 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
172 | 172 | ||
173 | dbg("%s - port %d", __FUNCTION__, port->number); | 173 | dbg("%s - port %d", __FUNCTION__, port->number); |
174 | 174 | ||
175 | if (!port->tty || !port->tty->termios) { | ||
176 | dbg("%s - no tty structures", __FUNCTION__); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | spin_lock_irqsave(&priv->lock, flags); | 175 | spin_lock_irqsave(&priv->lock, flags); |
181 | if (!priv->termios_initialized) { | 176 | if (!priv->termios_initialized) { |
182 | *(port->tty->termios) = tty_std_termios; | 177 | *(port->tty->termios) = tty_std_termios; |
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index a47a24f8820d..0b14aea8ebd5 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -36,6 +36,16 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr | |||
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | static ssize_t show_port_number(struct device *dev, | ||
40 | struct device_attribute *attr, char *buf) | ||
41 | { | ||
42 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
43 | |||
44 | return sprintf(buf, "%d\n", port->number - port->serial->minor); | ||
45 | } | ||
46 | |||
47 | static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL); | ||
48 | |||
39 | static int usb_serial_device_probe (struct device *dev) | 49 | static int usb_serial_device_probe (struct device *dev) |
40 | { | 50 | { |
41 | struct usb_serial_driver *driver; | 51 | struct usb_serial_driver *driver; |
@@ -62,6 +72,10 @@ static int usb_serial_device_probe (struct device *dev) | |||
62 | goto exit; | 72 | goto exit; |
63 | } | 73 | } |
64 | 74 | ||
75 | retval = device_create_file(dev, &dev_attr_port_number); | ||
76 | if (retval) | ||
77 | goto exit; | ||
78 | |||
65 | minor = port->number; | 79 | minor = port->number; |
66 | tty_register_device (usb_serial_tty_driver, minor, dev); | 80 | tty_register_device (usb_serial_tty_driver, minor, dev); |
67 | dev_info(&port->serial->dev->dev, | 81 | dev_info(&port->serial->dev->dev, |
@@ -84,6 +98,8 @@ static int usb_serial_device_remove (struct device *dev) | |||
84 | return -ENODEV; | 98 | return -ENODEV; |
85 | } | 99 | } |
86 | 100 | ||
101 | device_remove_file(&port->dev, &dev_attr_port_number); | ||
102 | |||
87 | driver = port->serial->type; | 103 | driver = port->serial->type; |
88 | if (driver->port_remove) { | 104 | if (driver->port_remove) { |
89 | if (!try_module_get(driver->driver.owner)) { | 105 | if (!try_module_get(driver->driver.owner)) { |
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c new file mode 100644 index 000000000000..6b252ceb39a8 --- /dev/null +++ b/drivers/usb/serial/ch341.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk> | ||
3 | * | ||
4 | * ch341.c implements a serial port driver for the Winchiphead CH341. | ||
5 | * | ||
6 | * The CH341 device can be used to implement an RS232 asynchronous | ||
7 | * serial port, an IEEE-1284 parallel printer port or a memory-like | ||
8 | * interface. In all cases the CH341 supports an I2C interface as well. | ||
9 | * This driver only supports the asynchronous serial interface. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License version | ||
13 | * 2 as published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/tty.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/usb.h> | ||
21 | #include <linux/usb/serial.h> | ||
22 | #include <linux/serial.h> | ||
23 | |||
24 | #define DEFAULT_BAUD_RATE 2400 | ||
25 | #define DEFAULT_TIMEOUT 1000 | ||
26 | |||
27 | static int debug; | ||
28 | |||
29 | static struct usb_device_id id_table [] = { | ||
30 | { USB_DEVICE(0x4348, 0x5523) }, | ||
31 | { }, | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE(usb, id_table); | ||
34 | |||
35 | struct ch341_private { | ||
36 | unsigned baud_rate; | ||
37 | u8 dtr; | ||
38 | u8 rts; | ||
39 | }; | ||
40 | |||
41 | static int ch341_control_out(struct usb_device *dev, u8 request, | ||
42 | u16 value, u16 index) | ||
43 | { | ||
44 | int r; | ||
45 | dbg("ch341_control_out(%02x,%02x,%04x,%04x)", USB_DIR_OUT|0x40, | ||
46 | (int)request, (int)value, (int)index); | ||
47 | |||
48 | r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, | ||
49 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
50 | value, index, NULL, 0, DEFAULT_TIMEOUT); | ||
51 | |||
52 | return r; | ||
53 | } | ||
54 | |||
55 | static int ch341_control_in(struct usb_device *dev, | ||
56 | u8 request, u16 value, u16 index, | ||
57 | char *buf, unsigned bufsize) | ||
58 | { | ||
59 | int r; | ||
60 | dbg("ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)", USB_DIR_IN|0x40, | ||
61 | (int)request, (int)value, (int)index, buf, (int)bufsize); | ||
62 | |||
63 | r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, | ||
64 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
65 | value, index, buf, bufsize, DEFAULT_TIMEOUT); | ||
66 | return r; | ||
67 | } | ||
68 | |||
69 | static int ch341_set_baudrate(struct usb_device *dev, | ||
70 | struct ch341_private *priv) | ||
71 | { | ||
72 | short a, b; | ||
73 | int r; | ||
74 | |||
75 | dbg("ch341_set_baudrate(%d)", priv->baud_rate); | ||
76 | switch (priv->baud_rate) { | ||
77 | case 2400: | ||
78 | a = 0xd901; | ||
79 | b = 0x0038; | ||
80 | break; | ||
81 | case 4800: | ||
82 | a = 0x6402; | ||
83 | b = 0x001f; | ||
84 | break; | ||
85 | case 9600: | ||
86 | a = 0xb202; | ||
87 | b = 0x0013; | ||
88 | break; | ||
89 | case 19200: | ||
90 | a = 0xd902; | ||
91 | b = 0x000d; | ||
92 | break; | ||
93 | case 38400: | ||
94 | a = 0x6403; | ||
95 | b = 0x000a; | ||
96 | break; | ||
97 | case 115200: | ||
98 | a = 0xcc03; | ||
99 | b = 0x0008; | ||
100 | break; | ||
101 | default: | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | r = ch341_control_out(dev, 0x9a, 0x1312, a); | ||
106 | if (!r) | ||
107 | r = ch341_control_out(dev, 0x9a, 0x0f2c, b); | ||
108 | |||
109 | return r; | ||
110 | } | ||
111 | |||
112 | static int ch341_set_handshake(struct usb_device *dev, | ||
113 | struct ch341_private *priv) | ||
114 | { | ||
115 | dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); | ||
116 | return ch341_control_out(dev, 0xa4, | ||
117 | ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); | ||
118 | } | ||
119 | |||
120 | static int ch341_get_status(struct usb_device *dev) | ||
121 | { | ||
122 | char *buffer; | ||
123 | int r; | ||
124 | const unsigned size = 8; | ||
125 | |||
126 | dbg("ch341_get_status()"); | ||
127 | |||
128 | buffer = kmalloc(size, GFP_KERNEL); | ||
129 | if (!buffer) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size); | ||
133 | if ( r < 0) | ||
134 | goto out; | ||
135 | |||
136 | /* Not having the datasheet for the CH341, we ignore the bytes returned | ||
137 | * from the device. Return error if the device did not respond in time. | ||
138 | */ | ||
139 | r = 0; | ||
140 | |||
141 | out: kfree(buffer); | ||
142 | return r; | ||
143 | } | ||
144 | |||
145 | /* -------------------------------------------------------------------------- */ | ||
146 | |||
147 | static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) | ||
148 | { | ||
149 | char *buffer; | ||
150 | int r; | ||
151 | const unsigned size = 8; | ||
152 | |||
153 | dbg("ch341_configure()"); | ||
154 | |||
155 | buffer = kmalloc(size, GFP_KERNEL); | ||
156 | if (!buffer) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | /* expect two bytes 0x27 0x00 */ | ||
160 | r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size); | ||
161 | if (r < 0) | ||
162 | goto out; | ||
163 | |||
164 | r = ch341_control_out(dev, 0xa1, 0, 0); | ||
165 | if (r < 0) | ||
166 | goto out; | ||
167 | |||
168 | r = ch341_set_baudrate(dev, priv); | ||
169 | if (r < 0) | ||
170 | goto out; | ||
171 | |||
172 | /* expect two bytes 0x56 0x00 */ | ||
173 | r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size); | ||
174 | if (r < 0) | ||
175 | goto out; | ||
176 | |||
177 | r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050); | ||
178 | if (r < 0) | ||
179 | goto out; | ||
180 | |||
181 | /* expect 0xff 0xee */ | ||
182 | r = ch341_get_status(dev); | ||
183 | if (r < 0) | ||
184 | goto out; | ||
185 | |||
186 | r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a); | ||
187 | if (r < 0) | ||
188 | goto out; | ||
189 | |||
190 | r = ch341_set_baudrate(dev, priv); | ||
191 | if (r < 0) | ||
192 | goto out; | ||
193 | |||
194 | r = ch341_set_handshake(dev, priv); | ||
195 | if (r < 0) | ||
196 | goto out; | ||
197 | |||
198 | /* expect 0x9f 0xee */ | ||
199 | r = ch341_get_status(dev); | ||
200 | |||
201 | out: kfree(buffer); | ||
202 | return r; | ||
203 | } | ||
204 | |||
205 | /* allocate private data */ | ||
206 | static int ch341_attach(struct usb_serial *serial) | ||
207 | { | ||
208 | struct ch341_private *priv; | ||
209 | int r; | ||
210 | |||
211 | dbg("ch341_attach()"); | ||
212 | |||
213 | /* private data */ | ||
214 | priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); | ||
215 | if (!priv) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | priv->baud_rate = DEFAULT_BAUD_RATE; | ||
219 | priv->dtr = 1; | ||
220 | priv->rts = 1; | ||
221 | |||
222 | r = ch341_configure(serial->dev, priv); | ||
223 | if (r < 0) | ||
224 | goto error; | ||
225 | |||
226 | usb_set_serial_port_data(serial->port[0], priv); | ||
227 | return 0; | ||
228 | |||
229 | error: kfree(priv); | ||
230 | return r; | ||
231 | } | ||
232 | |||
233 | /* open this device, set default parameters */ | ||
234 | static int ch341_open(struct usb_serial_port *port, struct file *filp) | ||
235 | { | ||
236 | struct usb_serial *serial = port->serial; | ||
237 | struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); | ||
238 | int r; | ||
239 | |||
240 | dbg("ch341_open()"); | ||
241 | |||
242 | priv->baud_rate = DEFAULT_BAUD_RATE; | ||
243 | priv->dtr = 1; | ||
244 | priv->rts = 1; | ||
245 | |||
246 | r = ch341_configure(serial->dev, priv); | ||
247 | if (r) | ||
248 | goto out; | ||
249 | |||
250 | r = ch341_set_handshake(serial->dev, priv); | ||
251 | if (r) | ||
252 | goto out; | ||
253 | |||
254 | r = ch341_set_baudrate(serial->dev, priv); | ||
255 | if (r) | ||
256 | goto out; | ||
257 | |||
258 | r = usb_serial_generic_open(port, filp); | ||
259 | |||
260 | out: return r; | ||
261 | } | ||
262 | |||
263 | /* Old_termios contains the original termios settings and | ||
264 | * tty->termios contains the new setting to be used. | ||
265 | */ | ||
266 | static void ch341_set_termios(struct usb_serial_port *port, | ||
267 | struct ktermios *old_termios) | ||
268 | { | ||
269 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
270 | struct tty_struct *tty = port->tty; | ||
271 | unsigned baud_rate; | ||
272 | |||
273 | dbg("ch341_set_termios()"); | ||
274 | |||
275 | if (!tty || !tty->termios) | ||
276 | return; | ||
277 | |||
278 | baud_rate = tty_get_baud_rate(tty); | ||
279 | |||
280 | switch (baud_rate) { | ||
281 | case 2400: | ||
282 | case 4800: | ||
283 | case 9600: | ||
284 | case 19200: | ||
285 | case 38400: | ||
286 | case 115200: | ||
287 | priv->baud_rate = baud_rate; | ||
288 | break; | ||
289 | default: | ||
290 | dbg("Rate %d not supported, using %d", | ||
291 | baud_rate, DEFAULT_BAUD_RATE); | ||
292 | priv->baud_rate = DEFAULT_BAUD_RATE; | ||
293 | } | ||
294 | |||
295 | ch341_set_baudrate(port->serial->dev, priv); | ||
296 | |||
297 | /* Unimplemented: | ||
298 | * (cflag & CSIZE) : data bits [5, 8] | ||
299 | * (cflag & PARENB) : parity {NONE, EVEN, ODD} | ||
300 | * (cflag & CSTOPB) : stop bits [1, 2] | ||
301 | */ | ||
302 | } | ||
303 | |||
304 | static struct usb_driver ch341_driver = { | ||
305 | .name = "ch341", | ||
306 | .probe = usb_serial_probe, | ||
307 | .disconnect = usb_serial_disconnect, | ||
308 | .id_table = id_table, | ||
309 | .no_dynamic_id = 1, | ||
310 | }; | ||
311 | |||
312 | static struct usb_serial_driver ch341_device = { | ||
313 | .driver = { | ||
314 | .owner = THIS_MODULE, | ||
315 | .name = "ch341-uart", | ||
316 | }, | ||
317 | .id_table = id_table, | ||
318 | .usb_driver = &ch341_driver, | ||
319 | .num_interrupt_in = NUM_DONT_CARE, | ||
320 | .num_bulk_in = 1, | ||
321 | .num_bulk_out = 1, | ||
322 | .num_ports = 1, | ||
323 | .open = ch341_open, | ||
324 | .set_termios = ch341_set_termios, | ||
325 | .attach = ch341_attach, | ||
326 | }; | ||
327 | |||
328 | static int __init ch341_init(void) | ||
329 | { | ||
330 | int retval; | ||
331 | |||
332 | retval = usb_serial_register(&ch341_device); | ||
333 | if (retval) | ||
334 | return retval; | ||
335 | retval = usb_register(&ch341_driver); | ||
336 | if (retval) | ||
337 | usb_serial_deregister(&ch341_device); | ||
338 | return retval; | ||
339 | } | ||
340 | |||
341 | static void __exit ch341_exit(void) | ||
342 | { | ||
343 | usb_deregister(&ch341_driver); | ||
344 | usb_serial_deregister(&ch341_device); | ||
345 | } | ||
346 | |||
347 | module_init(ch341_init); | ||
348 | module_exit(ch341_exit); | ||
349 | MODULE_LICENSE("GPL"); | ||
350 | |||
351 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
352 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
353 | |||
354 | /* EOF ch341.c */ | ||
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 33f6ee50b8d3..eb7df1835c11 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
@@ -53,6 +53,7 @@ static void cp2101_shutdown(struct usb_serial*); | |||
53 | static int debug; | 53 | static int debug; |
54 | 54 | ||
55 | static struct usb_device_id id_table [] = { | 55 | static struct usb_device_id id_table [] = { |
56 | { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ | ||
56 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ | 57 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ |
57 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ | 58 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ |
58 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 59 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
@@ -521,7 +522,7 @@ static void cp2101_set_termios (struct usb_serial_port *port, | |||
521 | 522 | ||
522 | dbg("%s - port %d", __FUNCTION__, port->number); | 523 | dbg("%s - port %d", __FUNCTION__, port->number); |
523 | 524 | ||
524 | if ((!port->tty) || (!port->tty->termios)) { | 525 | if (!port->tty || !port->tty->termios) { |
525 | dbg("%s - no tty structures", __FUNCTION__); | 526 | dbg("%s - no tty structures", __FUNCTION__); |
526 | return; | 527 | return; |
527 | } | 528 | } |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 2d045857b181..e4c248c98e84 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1169,7 +1169,9 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) | |||
1169 | /* XXX see create_sysfs_attrs */ | 1169 | /* XXX see create_sysfs_attrs */ |
1170 | if (priv->chip_type != SIO) { | 1170 | if (priv->chip_type != SIO) { |
1171 | device_remove_file(&port->dev, &dev_attr_event_char); | 1171 | device_remove_file(&port->dev, &dev_attr_event_char); |
1172 | if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) { | 1172 | if (priv->chip_type == FT232BM || |
1173 | priv->chip_type == FT2232C || | ||
1174 | priv->chip_type == FT232RL) { | ||
1173 | device_remove_file(&port->dev, &dev_attr_latency_timer); | 1175 | device_remove_file(&port->dev, &dev_attr_latency_timer); |
1174 | } | 1176 | } |
1175 | } | 1177 | } |
@@ -2102,6 +2104,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) | |||
2102 | case FT8U232AM: | 2104 | case FT8U232AM: |
2103 | case FT232BM: | 2105 | case FT232BM: |
2104 | case FT2232C: | 2106 | case FT2232C: |
2107 | case FT232RL: | ||
2105 | /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same | 2108 | /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same |
2106 | format as the data returned from the in point */ | 2109 | format as the data returned from the in point */ |
2107 | if ((ret = usb_control_msg(port->serial->dev, | 2110 | if ((ret = usb_control_msg(port->serial->dev, |
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index 4092f6dc9efd..b5194dc7d3bb 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c | |||
@@ -24,26 +24,6 @@ static struct usb_device_id id_table [] = { | |||
24 | }; | 24 | }; |
25 | MODULE_DEVICE_TABLE(usb, id_table); | 25 | MODULE_DEVICE_TABLE(usb, id_table); |
26 | 26 | ||
27 | static int funsoft_ioctl(struct usb_serial_port *port, struct file *file, | ||
28 | unsigned int cmd, unsigned long arg) | ||
29 | { | ||
30 | struct ktermios t; | ||
31 | |||
32 | dbg("%s - port %d, cmd 0x%04x", __FUNCTION__, port->number, cmd); | ||
33 | |||
34 | if (cmd == TCSETSF) { | ||
35 | if (user_termios_to_kernel_termios(&t, (struct termios __user *)arg)) | ||
36 | return -EFAULT; | ||
37 | |||
38 | dbg("%s - iflag:%x oflag:%x cflag:%x lflag:%x", __FUNCTION__, | ||
39 | t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag); | ||
40 | |||
41 | if (!(t.c_lflag & ICANON)) | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | return -ENOIOCTLCMD; | ||
45 | } | ||
46 | |||
47 | static struct usb_driver funsoft_driver = { | 27 | static struct usb_driver funsoft_driver = { |
48 | .name = "funsoft", | 28 | .name = "funsoft", |
49 | .probe = usb_serial_probe, | 29 | .probe = usb_serial_probe, |
@@ -63,7 +43,6 @@ static struct usb_serial_driver funsoft_device = { | |||
63 | .num_bulk_in = NUM_DONT_CARE, | 43 | .num_bulk_in = NUM_DONT_CARE, |
64 | .num_bulk_out = NUM_DONT_CARE, | 44 | .num_bulk_out = NUM_DONT_CARE, |
65 | .num_ports = 1, | 45 | .num_ports = 1, |
66 | .ioctl = funsoft_ioctl, | ||
67 | }; | 46 | }; |
68 | 47 | ||
69 | static int __init funsoft_init(void) | 48 | static int __init funsoft_init(void) |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 6a3a704b5849..e836ad07fdb9 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -256,6 +256,7 @@ static struct usb_device_id ipaq_id_table [] = { | |||
256 | { USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */ | 256 | { USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */ |
257 | { USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */ | 257 | { USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */ |
258 | { USB_DEVICE(0x04DD, 0x9151) }, /* SHARP S01SH USB Modem */ | 258 | { USB_DEVICE(0x04DD, 0x9151) }, /* SHARP S01SH USB Modem */ |
259 | { USB_DEVICE(0x04DD, 0x91AC) }, /* SHARP WS011SH USB Modem */ | ||
259 | { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ | 260 | { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ |
260 | { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ | 261 | { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ |
261 | { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ | 262 | { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ |
@@ -646,11 +647,13 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) | |||
646 | kfree(port->bulk_out_buffer); | 647 | kfree(port->bulk_out_buffer); |
647 | port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); | 648 | port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); |
648 | if (port->bulk_in_buffer == NULL) { | 649 | if (port->bulk_in_buffer == NULL) { |
650 | port->bulk_out_buffer = NULL; /* prevent double free */ | ||
649 | goto enomem; | 651 | goto enomem; |
650 | } | 652 | } |
651 | port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); | 653 | port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL); |
652 | if (port->bulk_out_buffer == NULL) { | 654 | if (port->bulk_out_buffer == NULL) { |
653 | kfree(port->bulk_in_buffer); | 655 | kfree(port->bulk_in_buffer); |
656 | port->bulk_in_buffer = NULL; | ||
654 | goto enomem; | 657 | goto enomem; |
655 | } | 658 | } |
656 | port->read_urb->transfer_buffer = port->bulk_in_buffer; | 659 | port->read_urb->transfer_buffer = port->bulk_in_buffer; |
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 5a4127e62c4a..90e3216abd1f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -728,24 +728,32 @@ static void klsi_105_set_termios (struct usb_serial_port *port, | |||
728 | #endif | 728 | #endif |
729 | } | 729 | } |
730 | 730 | ||
731 | switch(cflag & CBAUD) { | 731 | switch(tty_get_baud_rate(port->tty)) { |
732 | case B0: /* handled below */ | 732 | case 0: /* handled below */ |
733 | break; | 733 | break; |
734 | case B1200: priv->cfg.baudrate = kl5kusb105a_sio_b1200; | 734 | case 1200: |
735 | priv->cfg.baudrate = kl5kusb105a_sio_b1200; | ||
735 | break; | 736 | break; |
736 | case B2400: priv->cfg.baudrate = kl5kusb105a_sio_b2400; | 737 | case 2400: |
738 | priv->cfg.baudrate = kl5kusb105a_sio_b2400; | ||
737 | break; | 739 | break; |
738 | case B4800: priv->cfg.baudrate = kl5kusb105a_sio_b4800; | 740 | case 4800: |
741 | priv->cfg.baudrate = kl5kusb105a_sio_b4800; | ||
739 | break; | 742 | break; |
740 | case B9600: priv->cfg.baudrate = kl5kusb105a_sio_b9600; | 743 | case 9600: |
744 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; | ||
741 | break; | 745 | break; |
742 | case B19200: priv->cfg.baudrate = kl5kusb105a_sio_b19200; | 746 | case 19200: |
747 | priv->cfg.baudrate = kl5kusb105a_sio_b19200; | ||
743 | break; | 748 | break; |
744 | case B38400: priv->cfg.baudrate = kl5kusb105a_sio_b38400; | 749 | case 38400: |
750 | priv->cfg.baudrate = kl5kusb105a_sio_b38400; | ||
745 | break; | 751 | break; |
746 | case B57600: priv->cfg.baudrate = kl5kusb105a_sio_b57600; | 752 | case 57600: |
753 | priv->cfg.baudrate = kl5kusb105a_sio_b57600; | ||
747 | break; | 754 | break; |
748 | case B115200: priv->cfg.baudrate = kl5kusb105a_sio_b115200; | 755 | case 115200: |
756 | priv->cfg.baudrate = kl5kusb105a_sio_b115200; | ||
749 | break; | 757 | break; |
750 | default: | 758 | default: |
751 | err("KLSI USB->Serial converter:" | 759 | err("KLSI USB->Serial converter:" |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 02a86dbc0e97..6f224195bd25 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -82,6 +82,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, | |||
82 | unsigned int set, unsigned int clear); | 82 | unsigned int set, unsigned int clear); |
83 | static void kobil_read_int_callback( struct urb *urb ); | 83 | static void kobil_read_int_callback( struct urb *urb ); |
84 | static void kobil_write_callback( struct urb *purb ); | 84 | static void kobil_write_callback( struct urb *purb ); |
85 | static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old); | ||
85 | 86 | ||
86 | 87 | ||
87 | static struct usb_device_id id_table [] = { | 88 | static struct usb_device_id id_table [] = { |
@@ -119,6 +120,7 @@ static struct usb_serial_driver kobil_device = { | |||
119 | .attach = kobil_startup, | 120 | .attach = kobil_startup, |
120 | .shutdown = kobil_shutdown, | 121 | .shutdown = kobil_shutdown, |
121 | .ioctl = kobil_ioctl, | 122 | .ioctl = kobil_ioctl, |
123 | .set_termios = kobil_set_termios, | ||
122 | .tiocmget = kobil_tiocmget, | 124 | .tiocmget = kobil_tiocmget, |
123 | .tiocmset = kobil_tiocmset, | 125 | .tiocmset = kobil_tiocmset, |
124 | .open = kobil_open, | 126 | .open = kobil_open, |
@@ -137,7 +139,6 @@ struct kobil_private { | |||
137 | int cur_pos; // index of the next char to send in buf | 139 | int cur_pos; // index of the next char to send in buf |
138 | __u16 device_type; | 140 | __u16 device_type; |
139 | int line_state; | 141 | int line_state; |
140 | struct ktermios internal_termios; | ||
141 | }; | 142 | }; |
142 | 143 | ||
143 | 144 | ||
@@ -216,7 +217,7 @@ static void kobil_shutdown (struct usb_serial *serial) | |||
216 | 217 | ||
217 | static int kobil_open (struct usb_serial_port *port, struct file *filp) | 218 | static int kobil_open (struct usb_serial_port *port, struct file *filp) |
218 | { | 219 | { |
219 | int i, result = 0; | 220 | int result = 0; |
220 | struct kobil_private *priv; | 221 | struct kobil_private *priv; |
221 | unsigned char *transfer_buffer; | 222 | unsigned char *transfer_buffer; |
222 | int transfer_buffer_length = 8; | 223 | int transfer_buffer_length = 8; |
@@ -242,16 +243,6 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) | |||
242 | port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; | 243 | port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF; |
243 | port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) | 244 | port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) |
244 | 245 | ||
245 | // set up internal termios structure | ||
246 | priv->internal_termios.c_iflag = port->tty->termios->c_iflag; | ||
247 | priv->internal_termios.c_oflag = port->tty->termios->c_oflag; | ||
248 | priv->internal_termios.c_cflag = port->tty->termios->c_cflag; | ||
249 | priv->internal_termios.c_lflag = port->tty->termios->c_lflag; | ||
250 | |||
251 | for (i=0; i<NCCS; i++) { | ||
252 | priv->internal_termios.c_cc[i] = port->tty->termios->c_cc[i]; | ||
253 | } | ||
254 | |||
255 | // allocate memory for transfer buffer | 246 | // allocate memory for transfer buffer |
256 | transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); | 247 | transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); |
257 | if (! transfer_buffer) { | 248 | if (! transfer_buffer) { |
@@ -607,102 +598,79 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, | |||
607 | return (result < 0) ? result : 0; | 598 | return (result < 0) ? result : 0; |
608 | } | 599 | } |
609 | 600 | ||
610 | 601 | static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old) | |
611 | static int kobil_ioctl(struct usb_serial_port *port, struct file *file, | ||
612 | unsigned int cmd, unsigned long arg) | ||
613 | { | 602 | { |
614 | struct kobil_private * priv; | 603 | struct kobil_private * priv; |
615 | int result; | 604 | int result; |
616 | unsigned short urb_val = 0; | 605 | unsigned short urb_val = 0; |
617 | unsigned char *transfer_buffer; | 606 | int c_cflag = port->tty->termios->c_cflag; |
618 | int transfer_buffer_length = 8; | 607 | speed_t speed; |
619 | char *settings; | 608 | void * settings; |
620 | void __user *user_arg = (void __user *)arg; | ||
621 | 609 | ||
622 | priv = usb_get_serial_port_data(port); | 610 | priv = usb_get_serial_port_data(port); |
623 | if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { | 611 | if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) |
624 | // This device doesn't support ioctl calls | 612 | // This device doesn't support ioctl calls |
625 | return 0; | 613 | return; |
626 | } | ||
627 | |||
628 | switch (cmd) { | ||
629 | case TCGETS: // 0x5401 | ||
630 | if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) { | ||
631 | dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); | ||
632 | return -EFAULT; | ||
633 | } | ||
634 | if (kernel_termios_to_user_termios((struct ktermios __user *)arg, | ||
635 | &priv->internal_termios)) | ||
636 | return -EFAULT; | ||
637 | return 0; | ||
638 | |||
639 | case TCSETS: // 0x5402 | ||
640 | if (!(port->tty->termios)) { | ||
641 | dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); | ||
642 | return -ENOTTY; | ||
643 | } | ||
644 | if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) { | ||
645 | dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); | ||
646 | return -EFAULT; | ||
647 | } | ||
648 | if (user_termios_to_kernel_termios(&priv->internal_termios, | ||
649 | (struct ktermios __user *)arg)) | ||
650 | return -EFAULT; | ||
651 | |||
652 | settings = kzalloc(50, GFP_KERNEL); | ||
653 | if (! settings) { | ||
654 | return -ENOBUFS; | ||
655 | } | ||
656 | 614 | ||
657 | switch (priv->internal_termios.c_cflag & CBAUD) { | 615 | switch (speed = tty_get_baud_rate(port->tty)) { |
658 | case B1200: | 616 | case 1200: |
659 | urb_val = SUSBCR_SBR_1200; | 617 | urb_val = SUSBCR_SBR_1200; |
660 | strcat(settings, "1200 "); | ||
661 | break; | 618 | break; |
662 | case B9600: | 619 | case 9600: |
663 | default: | 620 | default: |
664 | urb_val = SUSBCR_SBR_9600; | 621 | urb_val = SUSBCR_SBR_9600; |
665 | strcat(settings, "9600 "); | ||
666 | break; | 622 | break; |
667 | } | 623 | } |
624 | urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; | ||
625 | |||
626 | settings = kzalloc(50, GFP_KERNEL); | ||
627 | if (! settings) | ||
628 | return; | ||
668 | 629 | ||
669 | urb_val |= (priv->internal_termios.c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; | 630 | sprintf(settings, "%d ", speed); |
670 | strcat(settings, (priv->internal_termios.c_cflag & CSTOPB) ? "2 StopBits " : "1 StopBit "); | ||
671 | 631 | ||
672 | if (priv->internal_termios.c_cflag & PARENB) { | 632 | if (c_cflag & PARENB) { |
673 | if (priv->internal_termios.c_cflag & PARODD) { | 633 | if (c_cflag & PARODD) { |
674 | urb_val |= SUSBCR_SPASB_OddParity; | 634 | urb_val |= SUSBCR_SPASB_OddParity; |
675 | strcat(settings, "Odd Parity"); | 635 | strcat(settings, "Odd Parity"); |
676 | } else { | ||
677 | urb_val |= SUSBCR_SPASB_EvenParity; | ||
678 | strcat(settings, "Even Parity"); | ||
679 | } | ||
680 | } else { | 636 | } else { |
681 | urb_val |= SUSBCR_SPASB_NoParity; | 637 | urb_val |= SUSBCR_SPASB_EvenParity; |
682 | strcat(settings, "No Parity"); | 638 | strcat(settings, "Even Parity"); |
683 | } | 639 | } |
684 | dbg("%s - port %d setting port to: %s", __FUNCTION__, port->number, settings ); | 640 | } else { |
641 | urb_val |= SUSBCR_SPASB_NoParity; | ||
642 | strcat(settings, "No Parity"); | ||
643 | } | ||
685 | 644 | ||
686 | result = usb_control_msg( port->serial->dev, | 645 | result = usb_control_msg( port->serial->dev, |
687 | usb_rcvctrlpipe(port->serial->dev, 0 ), | 646 | usb_rcvctrlpipe(port->serial->dev, 0 ), |
688 | SUSBCRequest_SetBaudRateParityAndStopBits, | 647 | SUSBCRequest_SetBaudRateParityAndStopBits, |
689 | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, | 648 | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, |
690 | urb_val, | 649 | urb_val, |
691 | 0, | 650 | 0, |
692 | settings, | 651 | settings, |
693 | 0, | 652 | 0, |
694 | KOBIL_TIMEOUT | 653 | KOBIL_TIMEOUT |
695 | ); | 654 | ); |
655 | kfree(settings); | ||
656 | } | ||
696 | 657 | ||
697 | dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result); | 658 | static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) |
698 | kfree(settings); | 659 | { |
660 | struct kobil_private * priv = usb_get_serial_port_data(port); | ||
661 | unsigned char *transfer_buffer; | ||
662 | int transfer_buffer_length = 8; | ||
663 | int result; | ||
664 | |||
665 | if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) | ||
666 | // This device doesn't support ioctl calls | ||
699 | return 0; | 667 | return 0; |
700 | 668 | ||
669 | switch (cmd) { | ||
701 | case TCFLSH: // 0x540B | 670 | case TCFLSH: // 0x540B |
702 | transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); | 671 | transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); |
703 | if (! transfer_buffer) { | 672 | if (! transfer_buffer) |
704 | return -ENOBUFS; | 673 | return -ENOBUFS; |
705 | } | ||
706 | 674 | ||
707 | result = usb_control_msg( port->serial->dev, | 675 | result = usb_control_msg( port->serial->dev, |
708 | usb_rcvctrlpipe(port->serial->dev, 0 ), | 676 | usb_rcvctrlpipe(port->serial->dev, 0 ), |
@@ -716,15 +684,13 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, | |||
716 | ); | 684 | ); |
717 | 685 | ||
718 | dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result); | 686 | dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result); |
719 | |||
720 | kfree(transfer_buffer); | 687 | kfree(transfer_buffer); |
721 | return ((result < 0) ? -EFAULT : 0); | 688 | return (result < 0) ? -EFAULT : 0; |
722 | 689 | default: | |
690 | return -ENOIOCTLCMD; | ||
723 | } | 691 | } |
724 | return -ENOIOCTLCMD; | ||
725 | } | 692 | } |
726 | 693 | ||
727 | |||
728 | static int __init kobil_init (void) | 694 | static int __init kobil_init (void) |
729 | { | 695 | { |
730 | int retval; | 696 | int retval; |
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index e08c9bb403d8..0dc99f75bb09 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -206,20 +206,20 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value | |||
206 | } | 206 | } |
207 | } else { | 207 | } else { |
208 | switch (value) { | 208 | switch (value) { |
209 | case 300: break; | 209 | case 300: break; |
210 | case 600: break; | 210 | case 600: break; |
211 | case 1200: break; | 211 | case 1200: break; |
212 | case 2400: break; | 212 | case 2400: break; |
213 | case 4800: break; | 213 | case 4800: break; |
214 | case 9600: break; | 214 | case 9600: break; |
215 | case 19200: break; | 215 | case 19200: break; |
216 | case 38400: break; | 216 | case 38400: break; |
217 | case 57600: break; | 217 | case 57600: break; |
218 | case 115200: break; | 218 | case 115200: break; |
219 | default: | 219 | default: |
220 | err("MCT USB-RS232: unsupported baudrate request 0x%x," | 220 | err("MCT USB-RS232: unsupported baudrate request 0x%x," |
221 | " using default of B9600", value); | 221 | " using default of B9600", value); |
222 | value = 9600; | 222 | value = 9600; |
223 | } | 223 | } |
224 | return 115200/value; | 224 | return 115200/value; |
225 | } | 225 | } |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 64f3f66a7a35..d19861166b50 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -1144,7 +1144,7 @@ static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | |||
1144 | if (size == 0) | 1144 | if (size == 0) |
1145 | return NULL; | 1145 | return NULL; |
1146 | 1146 | ||
1147 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | 1147 | pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); |
1148 | if (pb == NULL) | 1148 | if (pb == NULL) |
1149 | return NULL; | 1149 | return NULL; |
1150 | 1150 | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index f9f85f56f0db..1da57fd9ea23 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -73,6 +73,7 @@ static struct usb_device_id id_table [] = { | |||
73 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, | 73 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, |
74 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, | 74 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, |
75 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, | 75 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, |
76 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, | ||
76 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, | 77 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, |
77 | { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, | 78 | { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, |
78 | { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, | 79 | { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, |
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index f9a71d0c102e..c39bace5cbcc 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #define SIEMENS_PRODUCT_ID_SX1 0x0001 | 59 | #define SIEMENS_PRODUCT_ID_SX1 0x0001 |
60 | #define SIEMENS_PRODUCT_ID_X65 0x0003 | 60 | #define SIEMENS_PRODUCT_ID_X65 0x0003 |
61 | #define SIEMENS_PRODUCT_ID_X75 0x0004 | 61 | #define SIEMENS_PRODUCT_ID_X75 0x0004 |
62 | #define SIEMENS_PRODUCT_ID_EF81 0x0005 | ||
62 | 63 | ||
63 | #define SYNTECH_VENDOR_ID 0x0745 | 64 | #define SYNTECH_VENDOR_ID 0x0745 |
64 | #define SYNTECH_PRODUCT_ID 0x0001 | 65 | #define SYNTECH_PRODUCT_ID 0x0001 |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 51669b7622bb..4e6dcc199be9 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -90,18 +90,12 @@ MODULE_AUTHOR (DRIVER_AUTHOR); | |||
90 | MODULE_DESCRIPTION (DRIVER_DESC); | 90 | MODULE_DESCRIPTION (DRIVER_DESC); |
91 | MODULE_LICENSE("GPL"); | 91 | MODULE_LICENSE("GPL"); |
92 | 92 | ||
93 | #if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT) | ||
94 | #error "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT" | ||
95 | #endif | ||
96 | |||
97 | #if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) | ||
98 | static __u16 vendor; // no default | 93 | static __u16 vendor; // no default |
99 | static __u16 product; // no default | 94 | static __u16 product; // no default |
100 | module_param(vendor, ushort, 0); | 95 | module_param(vendor, ushort, 0); |
101 | MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); | 96 | MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); |
102 | module_param(product, ushort, 0); | 97 | module_param(product, ushort, 0); |
103 | MODULE_PARM_DESC(product, "User specified USB idProduct (required)"); | 98 | MODULE_PARM_DESC(product, "User specified USB idProduct (required)"); |
104 | #endif | ||
105 | 99 | ||
106 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 100 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
107 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 101 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
@@ -145,11 +139,6 @@ static struct usb_device_id id_table[] = { | |||
145 | {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie | 139 | {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie |
146 | {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie | 140 | {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie |
147 | {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp | 141 | {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp |
148 | #if defined(CONFIG_USB_SAFE_SERIAL_VENDOR) | ||
149 | {MY_USB_DEVICE | ||
150 | (CONFIG_USB_SAFE_SERIAL_VENDOR, CONFIG_USB_SAFE_SERIAL_PRODUCT, CDC_DEVICE_CLASS, | ||
151 | LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, | ||
152 | #endif | ||
153 | // extra null entry for module | 142 | // extra null entry for module |
154 | // vendor/produc parameters | 143 | // vendor/produc parameters |
155 | {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, | 144 | {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9bf01a5efc84..4b1bd7def4a5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -578,6 +578,17 @@ static void kill_traffic(struct usb_serial_port *port) | |||
578 | { | 578 | { |
579 | usb_kill_urb(port->read_urb); | 579 | usb_kill_urb(port->read_urb); |
580 | usb_kill_urb(port->write_urb); | 580 | usb_kill_urb(port->write_urb); |
581 | /* | ||
582 | * This is tricky. | ||
583 | * Some drivers submit the read_urb in the | ||
584 | * handler for the write_urb or vice versa | ||
585 | * this order determines the order in which | ||
586 | * usb_kill_urb() must be used to reliably | ||
587 | * kill the URBs. As it is unknown here, | ||
588 | * both orders must be used in turn. | ||
589 | * The call below is not redundant. | ||
590 | */ | ||
591 | usb_kill_urb(port->read_urb); | ||
581 | usb_kill_urb(port->interrupt_in_urb); | 592 | usb_kill_urb(port->interrupt_in_urb); |
582 | usb_kill_urb(port->interrupt_out_urb); | 593 | usb_kill_urb(port->interrupt_out_urb); |
583 | } | 594 | } |
@@ -651,16 +662,14 @@ exit: | |||
651 | 662 | ||
652 | static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) | 663 | static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) |
653 | { | 664 | { |
654 | struct list_head *p; | ||
655 | const struct usb_device_id *id; | 665 | const struct usb_device_id *id; |
656 | struct usb_serial_driver *t; | 666 | struct usb_serial_driver *drv; |
657 | 667 | ||
658 | /* Check if the usb id matches a known device */ | 668 | /* Check if the usb id matches a known device */ |
659 | list_for_each(p, &usb_serial_driver_list) { | 669 | list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { |
660 | t = list_entry(p, struct usb_serial_driver, driver_list); | 670 | id = get_iface_id(drv, iface); |
661 | id = get_iface_id(t, iface); | ||
662 | if (id) | 671 | if (id) |
663 | return t; | 672 | return drv; |
664 | } | 673 | } |
665 | 674 | ||
666 | return NULL; | 675 | return NULL; |
@@ -800,9 +809,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
800 | /* END HORRIBLE HACK FOR PL2303 */ | 809 | /* END HORRIBLE HACK FOR PL2303 */ |
801 | #endif | 810 | #endif |
802 | 811 | ||
803 | /* found all that we need */ | ||
804 | dev_info(&interface->dev, "%s converter detected\n", type->description); | ||
805 | |||
806 | #ifdef CONFIG_USB_SERIAL_GENERIC | 812 | #ifdef CONFIG_USB_SERIAL_GENERIC |
807 | if (type == &usb_serial_generic_device) { | 813 | if (type == &usb_serial_generic_device) { |
808 | num_ports = num_bulk_out; | 814 | num_ports = num_bulk_out; |
@@ -836,6 +842,24 @@ int usb_serial_probe(struct usb_interface *interface, | |||
836 | serial->num_interrupt_in = num_interrupt_in; | 842 | serial->num_interrupt_in = num_interrupt_in; |
837 | serial->num_interrupt_out = num_interrupt_out; | 843 | serial->num_interrupt_out = num_interrupt_out; |
838 | 844 | ||
845 | /* check that the device meets the driver's requirements */ | ||
846 | if ((type->num_interrupt_in != NUM_DONT_CARE && | ||
847 | type->num_interrupt_in != num_interrupt_in) | ||
848 | || (type->num_interrupt_out != NUM_DONT_CARE && | ||
849 | type->num_interrupt_out != num_interrupt_out) | ||
850 | || (type->num_bulk_in != NUM_DONT_CARE && | ||
851 | type->num_bulk_in != num_bulk_in) | ||
852 | || (type->num_bulk_out != NUM_DONT_CARE && | ||
853 | type->num_bulk_out != num_bulk_out)) { | ||
854 | dbg("wrong number of endpoints"); | ||
855 | kfree(serial); | ||
856 | return -EIO; | ||
857 | } | ||
858 | |||
859 | /* found all that we need */ | ||
860 | dev_info(&interface->dev, "%s converter detected\n", | ||
861 | type->description); | ||
862 | |||
839 | /* create our ports, we need as many as the max endpoints */ | 863 | /* create our ports, we need as many as the max endpoints */ |
840 | /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ | 864 | /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ |
841 | max_endpoints = max(num_bulk_in, num_bulk_out); | 865 | max_endpoints = max(num_bulk_in, num_bulk_out); |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 30e08c0bcdc2..7ee087fed913 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -46,7 +46,6 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id | |||
46 | static int visor_calc_num_ports(struct usb_serial *serial); | 46 | static int visor_calc_num_ports(struct usb_serial *serial); |
47 | static void visor_shutdown (struct usb_serial *serial); | 47 | static void visor_shutdown (struct usb_serial *serial); |
48 | static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); | 48 | static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); |
49 | static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); | ||
50 | static void visor_write_bulk_callback (struct urb *urb); | 49 | static void visor_write_bulk_callback (struct urb *urb); |
51 | static void visor_read_bulk_callback (struct urb *urb); | 50 | static void visor_read_bulk_callback (struct urb *urb); |
52 | static void visor_read_int_callback (struct urb *urb); | 51 | static void visor_read_int_callback (struct urb *urb); |
@@ -203,7 +202,6 @@ static struct usb_serial_driver handspring_device = { | |||
203 | .calc_num_ports = visor_calc_num_ports, | 202 | .calc_num_ports = visor_calc_num_ports, |
204 | .shutdown = visor_shutdown, | 203 | .shutdown = visor_shutdown, |
205 | .ioctl = visor_ioctl, | 204 | .ioctl = visor_ioctl, |
206 | .set_termios = visor_set_termios, | ||
207 | .write = visor_write, | 205 | .write = visor_write, |
208 | .write_room = visor_write_room, | 206 | .write_room = visor_write_room, |
209 | .chars_in_buffer = visor_chars_in_buffer, | 207 | .chars_in_buffer = visor_chars_in_buffer, |
@@ -234,7 +232,6 @@ static struct usb_serial_driver clie_5_device = { | |||
234 | .calc_num_ports = visor_calc_num_ports, | 232 | .calc_num_ports = visor_calc_num_ports, |
235 | .shutdown = visor_shutdown, | 233 | .shutdown = visor_shutdown, |
236 | .ioctl = visor_ioctl, | 234 | .ioctl = visor_ioctl, |
237 | .set_termios = visor_set_termios, | ||
238 | .write = visor_write, | 235 | .write = visor_write, |
239 | .write_room = visor_write_room, | 236 | .write_room = visor_write_room, |
240 | .chars_in_buffer = visor_chars_in_buffer, | 237 | .chars_in_buffer = visor_chars_in_buffer, |
@@ -262,7 +259,6 @@ static struct usb_serial_driver clie_3_5_device = { | |||
262 | .unthrottle = visor_unthrottle, | 259 | .unthrottle = visor_unthrottle, |
263 | .attach = clie_3_5_startup, | 260 | .attach = clie_3_5_startup, |
264 | .ioctl = visor_ioctl, | 261 | .ioctl = visor_ioctl, |
265 | .set_termios = visor_set_termios, | ||
266 | .write = visor_write, | 262 | .write = visor_write, |
267 | .write_room = visor_write_room, | 263 | .write_room = visor_write_room, |
268 | .chars_in_buffer = visor_chars_in_buffer, | 264 | .chars_in_buffer = visor_chars_in_buffer, |
@@ -936,66 +932,6 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign | |||
936 | return -ENOIOCTLCMD; | 932 | return -ENOIOCTLCMD; |
937 | } | 933 | } |
938 | 934 | ||
939 | |||
940 | /* This function is all nice and good, but we don't change anything based on it :) */ | ||
941 | static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) | ||
942 | { | ||
943 | unsigned int cflag; | ||
944 | |||
945 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
946 | |||
947 | if ((!port->tty) || (!port->tty->termios)) { | ||
948 | dbg("%s - no tty structures", __FUNCTION__); | ||
949 | return; | ||
950 | } | ||
951 | |||
952 | cflag = port->tty->termios->c_cflag; | ||
953 | |||
954 | /* get the byte size */ | ||
955 | switch (cflag & CSIZE) { | ||
956 | case CS5: dbg("%s - data bits = 5", __FUNCTION__); break; | ||
957 | case CS6: dbg("%s - data bits = 6", __FUNCTION__); break; | ||
958 | case CS7: dbg("%s - data bits = 7", __FUNCTION__); break; | ||
959 | default: | ||
960 | case CS8: dbg("%s - data bits = 8", __FUNCTION__); break; | ||
961 | } | ||
962 | |||
963 | /* determine the parity */ | ||
964 | if (cflag & PARENB) | ||
965 | if (cflag & PARODD) | ||
966 | dbg("%s - parity = odd", __FUNCTION__); | ||
967 | else | ||
968 | dbg("%s - parity = even", __FUNCTION__); | ||
969 | else | ||
970 | dbg("%s - parity = none", __FUNCTION__); | ||
971 | |||
972 | /* figure out the stop bits requested */ | ||
973 | if (cflag & CSTOPB) | ||
974 | dbg("%s - stop bits = 2", __FUNCTION__); | ||
975 | else | ||
976 | dbg("%s - stop bits = 1", __FUNCTION__); | ||
977 | |||
978 | |||
979 | /* figure out the flow control settings */ | ||
980 | if (cflag & CRTSCTS) | ||
981 | dbg("%s - RTS/CTS is enabled", __FUNCTION__); | ||
982 | else | ||
983 | dbg("%s - RTS/CTS is disabled", __FUNCTION__); | ||
984 | |||
985 | /* determine software flow control */ | ||
986 | if (I_IXOFF(port->tty)) | ||
987 | dbg("%s - XON/XOFF is enabled, XON = %2x, XOFF = %2x", | ||
988 | __FUNCTION__, START_CHAR(port->tty), STOP_CHAR(port->tty)); | ||
989 | else | ||
990 | dbg("%s - XON/XOFF is disabled", __FUNCTION__); | ||
991 | |||
992 | /* get the baud rate wanted */ | ||
993 | dbg("%s - baud rate = %d", __FUNCTION__, tty_get_baud_rate(port->tty)); | ||
994 | |||
995 | return; | ||
996 | } | ||
997 | |||
998 | |||
999 | static int __init visor_init (void) | 935 | static int __init visor_init (void) |
1000 | { | 936 | { |
1001 | int i, retval; | 937 | int i, retval; |
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 3a41740cad97..ee5b42aa5363 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c | |||
@@ -90,3 +90,17 @@ int usb_stor_ucr61s2b_init(struct us_data *us) | |||
90 | 90 | ||
91 | return (res ? -1 : 0); | 91 | return (res ? -1 : 0); |
92 | } | 92 | } |
93 | |||
94 | /* This places the HUAWEI E220 devices in multi-port mode */ | ||
95 | int usb_stor_huawei_e220_init(struct us_data *us) | ||
96 | { | ||
97 | int result; | ||
98 | |||
99 | us->iobuf[0] = 0x1; | ||
100 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | ||
101 | USB_REQ_SET_FEATURE, | ||
102 | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | ||
103 | 0x01, 0x0, us->iobuf, 0x1, 1000); | ||
104 | US_DEBUGP("usb_control_msg performing result is %d\n", result); | ||
105 | return (result ? 0 : -1); | ||
106 | } | ||
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index e2967a4d48a2..ad3ffd4236c2 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h | |||
@@ -47,3 +47,6 @@ int usb_stor_euscsi_init(struct us_data *us); | |||
47 | /* This function is required to activate all four slots on the UCR-61S2B | 47 | /* This function is required to activate all four slots on the UCR-61S2B |
48 | * flash reader */ | 48 | * flash reader */ |
49 | int usb_stor_ucr61s2b_init(struct us_data *us); | 49 | int usb_stor_ucr61s2b_init(struct us_data *us); |
50 | |||
51 | /* This places the HUAWEI E220 devices in multi-port mode */ | ||
52 | int usb_stor_huawei_e220_init(struct us_data *us); | ||
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 5e27297c0175..17ca4d73577b 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c | |||
@@ -190,9 +190,6 @@ static int usbat_check_status(struct us_data *us) | |||
190 | unsigned char *reply = us->iobuf; | 190 | unsigned char *reply = us->iobuf; |
191 | int rc; | 191 | int rc; |
192 | 192 | ||
193 | if (!us) | ||
194 | return USB_STOR_TRANSPORT_ERROR; | ||
195 | |||
196 | rc = usbat_get_status(us, reply); | 193 | rc = usbat_get_status(us, reply); |
197 | if (rc != USB_STOR_XFER_GOOD) | 194 | if (rc != USB_STOR_XFER_GOOD) |
198 | return USB_STOR_TRANSPORT_FAILED; | 195 | return USB_STOR_TRANSPORT_FAILED; |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c6b78ba815ea..9b656ec427d0 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -198,7 +198,7 @@ UNUSUAL_DEV( 0x0421, 0x044e, 0x0100, 0x0100, | |||
198 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), | 198 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), |
199 | 199 | ||
200 | /* Reported by Bardur Arantsson <bardur@scientician.net> */ | 200 | /* Reported by Bardur Arantsson <bardur@scientician.net> */ |
201 | UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0370, | 201 | UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, |
202 | "Nokia", | 202 | "Nokia", |
203 | "6131", | 203 | "6131", |
204 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 204 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
@@ -341,6 +341,13 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, | |||
341 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 341 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
342 | US_FL_FIX_CAPACITY), | 342 | US_FL_FIX_CAPACITY), |
343 | 343 | ||
344 | /* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */ | ||
345 | UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200, | ||
346 | "NIKON", | ||
347 | "NIKON DSC D200", | ||
348 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
349 | US_FL_FIX_CAPACITY), | ||
350 | |||
344 | /* Reported by Emil Larsson <emil@swip.net> */ | 351 | /* Reported by Emil Larsson <emil@swip.net> */ |
345 | UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, | 352 | UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, |
346 | "NIKON", | 353 | "NIKON", |
@@ -355,6 +362,20 @@ UNUSUAL_DEV( 0x04b0, 0x0413, 0x0110, 0x0110, | |||
355 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 362 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
356 | US_FL_FIX_CAPACITY), | 363 | US_FL_FIX_CAPACITY), |
357 | 364 | ||
365 | /* Reported by Paul Check <paul@openstreet.com> */ | ||
366 | UNUSUAL_DEV( 0x04b0, 0x0415, 0x0100, 0x0100, | ||
367 | "NIKON", | ||
368 | "NIKON DSC D2Xs", | ||
369 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
370 | US_FL_FIX_CAPACITY), | ||
371 | |||
372 | /* Reported by Shan Destromp (shansan@gmail.com) */ | ||
373 | UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, | ||
374 | "NIKON", | ||
375 | "NIKON DSC D40X", | ||
376 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
377 | US_FL_FIX_CAPACITY), | ||
378 | |||
358 | /* BENQ DC5330 | 379 | /* BENQ DC5330 |
359 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | 380 | * Reported by Manuel Fombuena <mfombuena@ya.com> and |
360 | * Frank Copeland <fjc@thingy.apana.org.au> */ | 381 | * Frank Copeland <fjc@thingy.apana.org.au> */ |
@@ -1463,6 +1484,17 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, | |||
1463 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1484 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1464 | US_FL_IGNORE_RESIDUE ), | 1485 | US_FL_IGNORE_RESIDUE ), |
1465 | 1486 | ||
1487 | /* Reported by fangxiaozhi <fangxiaozhi60675@huawei.com> | ||
1488 | * and by linlei <linlei83@huawei.com> | ||
1489 | * Patch reworked by Johann Wilhelm <johann.wilhelm@student.tugraz.at> | ||
1490 | * This brings the HUAWEI E220 devices into multi-port mode | ||
1491 | */ | ||
1492 | UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, | ||
1493 | "HUAWEI MOBILE", | ||
1494 | "Mass Storage", | ||
1495 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1496 | 0), | ||
1497 | |||
1466 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ | 1498 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ |
1467 | UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001, | 1499 | UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001, |
1468 | "Minolta", | 1500 | "Minolta", |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 59181667066c..3451e8d03ab0 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -960,6 +960,10 @@ static int storage_probe(struct usb_interface *intf, | |||
960 | return -ENOMEM; | 960 | return -ENOMEM; |
961 | } | 961 | } |
962 | 962 | ||
963 | /* | ||
964 | * Allow 16-byte CDBs and thus > 2TB | ||
965 | */ | ||
966 | host->max_cmd_len = 16; | ||
963 | us = host_to_us(host); | 967 | us = host_to_us(host); |
964 | memset(us, 0, sizeof(struct us_data)); | 968 | memset(us, 0, sizeof(struct us_data)); |
965 | mutex_init(&(us->dev_mutex)); | 969 | mutex_init(&(us->dev_mutex)); |
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 8de11deb5d14..c815a40e167f 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -125,6 +125,7 @@ static int skel_open(struct inode *inode, struct file *file) | |||
125 | 125 | ||
126 | /* save our object in the file's private structure */ | 126 | /* save our object in the file's private structure */ |
127 | file->private_data = dev; | 127 | file->private_data = dev; |
128 | mutex_unlock(&dev->io_mutex); | ||
128 | 129 | ||
129 | exit: | 130 | exit: |
130 | return retval; | 131 | return retval; |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 74901e981e10..d2fc2384c3be 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -491,6 +491,7 @@ struct dlm_ls { | |||
491 | uint64_t ls_recover_seq; | 491 | uint64_t ls_recover_seq; |
492 | struct dlm_recover *ls_recover_args; | 492 | struct dlm_recover *ls_recover_args; |
493 | struct rw_semaphore ls_in_recovery; /* block local requests */ | 493 | struct rw_semaphore ls_in_recovery; /* block local requests */ |
494 | struct rw_semaphore ls_recv_active; /* block dlm_recv */ | ||
494 | struct list_head ls_requestqueue;/* queue remote requests */ | 495 | struct list_head ls_requestqueue;/* queue remote requests */ |
495 | struct mutex ls_requestqueue_mutex; | 496 | struct mutex ls_requestqueue_mutex; |
496 | char *ls_recover_buf; | 497 | char *ls_recover_buf; |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 2082daf083d8..3915b8e14146 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -3638,55 +3638,8 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3638 | dlm_put_lkb(lkb); | 3638 | dlm_put_lkb(lkb); |
3639 | } | 3639 | } |
3640 | 3640 | ||
3641 | int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) | 3641 | static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms) |
3642 | { | 3642 | { |
3643 | struct dlm_message *ms = (struct dlm_message *) hd; | ||
3644 | struct dlm_ls *ls; | ||
3645 | int error = 0; | ||
3646 | |||
3647 | if (!recovery) | ||
3648 | dlm_message_in(ms); | ||
3649 | |||
3650 | ls = dlm_find_lockspace_global(hd->h_lockspace); | ||
3651 | if (!ls) { | ||
3652 | log_print("drop message %d from %d for unknown lockspace %d", | ||
3653 | ms->m_type, nodeid, hd->h_lockspace); | ||
3654 | return -EINVAL; | ||
3655 | } | ||
3656 | |||
3657 | /* recovery may have just ended leaving a bunch of backed-up requests | ||
3658 | in the requestqueue; wait while dlm_recoverd clears them */ | ||
3659 | |||
3660 | if (!recovery) | ||
3661 | dlm_wait_requestqueue(ls); | ||
3662 | |||
3663 | /* recovery may have just started while there were a bunch of | ||
3664 | in-flight requests -- save them in requestqueue to be processed | ||
3665 | after recovery. we can't let dlm_recvd block on the recovery | ||
3666 | lock. if dlm_recoverd is calling this function to clear the | ||
3667 | requestqueue, it needs to be interrupted (-EINTR) if another | ||
3668 | recovery operation is starting. */ | ||
3669 | |||
3670 | while (1) { | ||
3671 | if (dlm_locking_stopped(ls)) { | ||
3672 | if (recovery) { | ||
3673 | error = -EINTR; | ||
3674 | goto out; | ||
3675 | } | ||
3676 | error = dlm_add_requestqueue(ls, nodeid, hd); | ||
3677 | if (error == -EAGAIN) | ||
3678 | continue; | ||
3679 | else { | ||
3680 | error = -EINTR; | ||
3681 | goto out; | ||
3682 | } | ||
3683 | } | ||
3684 | |||
3685 | if (dlm_lock_recovery_try(ls)) | ||
3686 | break; | ||
3687 | schedule(); | ||
3688 | } | ||
3689 | |||
3690 | switch (ms->m_type) { | 3643 | switch (ms->m_type) { |
3691 | 3644 | ||
3692 | /* messages sent to a master node */ | 3645 | /* messages sent to a master node */ |
@@ -3761,17 +3714,90 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) | |||
3761 | log_error(ls, "unknown message type %d", ms->m_type); | 3714 | log_error(ls, "unknown message type %d", ms->m_type); |
3762 | } | 3715 | } |
3763 | 3716 | ||
3764 | dlm_unlock_recovery(ls); | ||
3765 | out: | ||
3766 | dlm_put_lockspace(ls); | ||
3767 | dlm_astd_wake(); | 3717 | dlm_astd_wake(); |
3768 | return error; | ||
3769 | } | 3718 | } |
3770 | 3719 | ||
3720 | /* If the lockspace is in recovery mode (locking stopped), then normal | ||
3721 | messages are saved on the requestqueue for processing after recovery is | ||
3722 | done. When not in recovery mode, we wait for dlm_recoverd to drain saved | ||
3723 | messages off the requestqueue before we process new ones. This occurs right | ||
3724 | after recovery completes when we transition from saving all messages on | ||
3725 | requestqueue, to processing all the saved messages, to processing new | ||
3726 | messages as they arrive. */ | ||
3771 | 3727 | ||
3772 | /* | 3728 | static void dlm_receive_message(struct dlm_ls *ls, struct dlm_message *ms, |
3773 | * Recovery related | 3729 | int nodeid) |
3774 | */ | 3730 | { |
3731 | if (dlm_locking_stopped(ls)) { | ||
3732 | dlm_add_requestqueue(ls, nodeid, (struct dlm_header *) ms); | ||
3733 | } else { | ||
3734 | dlm_wait_requestqueue(ls); | ||
3735 | _receive_message(ls, ms); | ||
3736 | } | ||
3737 | } | ||
3738 | |||
3739 | /* This is called by dlm_recoverd to process messages that were saved on | ||
3740 | the requestqueue. */ | ||
3741 | |||
3742 | void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms) | ||
3743 | { | ||
3744 | _receive_message(ls, ms); | ||
3745 | } | ||
3746 | |||
3747 | /* This is called by the midcomms layer when something is received for | ||
3748 | the lockspace. It could be either a MSG (normal message sent as part of | ||
3749 | standard locking activity) or an RCOM (recovery message sent as part of | ||
3750 | lockspace recovery). */ | ||
3751 | |||
3752 | void dlm_receive_buffer(struct dlm_header *hd, int nodeid) | ||
3753 | { | ||
3754 | struct dlm_message *ms = (struct dlm_message *) hd; | ||
3755 | struct dlm_rcom *rc = (struct dlm_rcom *) hd; | ||
3756 | struct dlm_ls *ls; | ||
3757 | int type = 0; | ||
3758 | |||
3759 | switch (hd->h_cmd) { | ||
3760 | case DLM_MSG: | ||
3761 | dlm_message_in(ms); | ||
3762 | type = ms->m_type; | ||
3763 | break; | ||
3764 | case DLM_RCOM: | ||
3765 | dlm_rcom_in(rc); | ||
3766 | type = rc->rc_type; | ||
3767 | break; | ||
3768 | default: | ||
3769 | log_print("invalid h_cmd %d from %u", hd->h_cmd, nodeid); | ||
3770 | return; | ||
3771 | } | ||
3772 | |||
3773 | if (hd->h_nodeid != nodeid) { | ||
3774 | log_print("invalid h_nodeid %d from %d lockspace %x", | ||
3775 | hd->h_nodeid, nodeid, hd->h_lockspace); | ||
3776 | return; | ||
3777 | } | ||
3778 | |||
3779 | ls = dlm_find_lockspace_global(hd->h_lockspace); | ||
3780 | if (!ls) { | ||
3781 | log_print("invalid h_lockspace %x from %d cmd %d type %d", | ||
3782 | hd->h_lockspace, nodeid, hd->h_cmd, type); | ||
3783 | |||
3784 | if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS) | ||
3785 | dlm_send_ls_not_ready(nodeid, rc); | ||
3786 | return; | ||
3787 | } | ||
3788 | |||
3789 | /* this rwsem allows dlm_ls_stop() to wait for all dlm_recv threads to | ||
3790 | be inactive (in this ls) before transitioning to recovery mode */ | ||
3791 | |||
3792 | down_read(&ls->ls_recv_active); | ||
3793 | if (hd->h_cmd == DLM_MSG) | ||
3794 | dlm_receive_message(ls, ms, nodeid); | ||
3795 | else | ||
3796 | dlm_receive_rcom(ls, rc, nodeid); | ||
3797 | up_read(&ls->ls_recv_active); | ||
3798 | |||
3799 | dlm_put_lockspace(ls); | ||
3800 | } | ||
3775 | 3801 | ||
3776 | static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) | 3802 | static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) |
3777 | { | 3803 | { |
@@ -4429,7 +4455,8 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4429 | 4455 | ||
4430 | if (lvb_in && ua->lksb.sb_lvbptr) | 4456 | if (lvb_in && ua->lksb.sb_lvbptr) |
4431 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); | 4457 | memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); |
4432 | ua->castparam = ua_tmp->castparam; | 4458 | if (ua_tmp->castparam) |
4459 | ua->castparam = ua_tmp->castparam; | ||
4433 | ua->user_lksb = ua_tmp->user_lksb; | 4460 | ua->user_lksb = ua_tmp->user_lksb; |
4434 | 4461 | ||
4435 | error = set_unlock_args(flags, ua, &args); | 4462 | error = set_unlock_args(flags, ua, &args); |
@@ -4474,7 +4501,8 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
4474 | goto out; | 4501 | goto out; |
4475 | 4502 | ||
4476 | ua = (struct dlm_user_args *)lkb->lkb_astparam; | 4503 | ua = (struct dlm_user_args *)lkb->lkb_astparam; |
4477 | ua->castparam = ua_tmp->castparam; | 4504 | if (ua_tmp->castparam) |
4505 | ua->castparam = ua_tmp->castparam; | ||
4478 | ua->user_lksb = ua_tmp->user_lksb; | 4506 | ua->user_lksb = ua_tmp->user_lksb; |
4479 | 4507 | ||
4480 | error = set_unlock_args(flags, ua, &args); | 4508 | error = set_unlock_args(flags, ua, &args); |
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h index 1720313c22df..ada04680a1e5 100644 --- a/fs/dlm/lock.h +++ b/fs/dlm/lock.h | |||
@@ -16,7 +16,8 @@ | |||
16 | void dlm_print_rsb(struct dlm_rsb *r); | 16 | void dlm_print_rsb(struct dlm_rsb *r); |
17 | void dlm_dump_rsb(struct dlm_rsb *r); | 17 | void dlm_dump_rsb(struct dlm_rsb *r); |
18 | void dlm_print_lkb(struct dlm_lkb *lkb); | 18 | void dlm_print_lkb(struct dlm_lkb *lkb); |
19 | int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery); | 19 | void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms); |
20 | void dlm_receive_buffer(struct dlm_header *hd, int nodeid); | ||
20 | int dlm_modes_compat(int mode1, int mode2); | 21 | int dlm_modes_compat(int mode1, int mode2); |
21 | int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen, | 22 | int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen, |
22 | unsigned int flags, struct dlm_rsb **r_ret); | 23 | unsigned int flags, struct dlm_rsb **r_ret); |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index f88f88fdedf1..6353a8384520 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -519,6 +519,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
519 | ls->ls_recover_seq = 0; | 519 | ls->ls_recover_seq = 0; |
520 | ls->ls_recover_args = NULL; | 520 | ls->ls_recover_args = NULL; |
521 | init_rwsem(&ls->ls_in_recovery); | 521 | init_rwsem(&ls->ls_in_recovery); |
522 | init_rwsem(&ls->ls_recv_active); | ||
522 | INIT_LIST_HEAD(&ls->ls_requestqueue); | 523 | INIT_LIST_HEAD(&ls->ls_requestqueue); |
523 | mutex_init(&ls->ls_requestqueue_mutex); | 524 | mutex_init(&ls->ls_requestqueue_mutex); |
524 | mutex_init(&ls->ls_clear_proc_locks); | 525 | mutex_init(&ls->ls_clear_proc_locks); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 9e9d2e82f40f..58bf3f5cdbe2 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -334,18 +334,8 @@ static void close_connection(struct connection *con, bool and_other) | |||
334 | con->rx_page = NULL; | 334 | con->rx_page = NULL; |
335 | } | 335 | } |
336 | 336 | ||
337 | /* If we are an 'othercon' then NULL the pointer to us | 337 | con->retries = 0; |
338 | from the parent and tidy ourself up */ | 338 | mutex_unlock(&con->sock_mutex); |
339 | if (test_bit(CF_IS_OTHERCON, &con->flags)) { | ||
340 | struct connection *parent = __nodeid2con(con->nodeid, 0); | ||
341 | parent->othercon = NULL; | ||
342 | kmem_cache_free(con_cache, con); | ||
343 | } | ||
344 | else { | ||
345 | /* Parent connections get reused */ | ||
346 | con->retries = 0; | ||
347 | mutex_unlock(&con->sock_mutex); | ||
348 | } | ||
349 | } | 339 | } |
350 | 340 | ||
351 | /* We only send shutdown messages to nodes that are not part of the cluster */ | 341 | /* We only send shutdown messages to nodes that are not part of the cluster */ |
@@ -731,6 +721,8 @@ static int tcp_accept_from_sock(struct connection *con) | |||
731 | INIT_WORK(&othercon->swork, process_send_sockets); | 721 | INIT_WORK(&othercon->swork, process_send_sockets); |
732 | INIT_WORK(&othercon->rwork, process_recv_sockets); | 722 | INIT_WORK(&othercon->rwork, process_recv_sockets); |
733 | set_bit(CF_IS_OTHERCON, &othercon->flags); | 723 | set_bit(CF_IS_OTHERCON, &othercon->flags); |
724 | } | ||
725 | if (!othercon->sock) { | ||
734 | newcon->othercon = othercon; | 726 | newcon->othercon = othercon; |
735 | othercon->sock = newsock; | 727 | othercon->sock = newsock; |
736 | newsock->sk->sk_user_data = othercon; | 728 | newsock->sk->sk_user_data = othercon; |
@@ -1272,14 +1264,15 @@ static void send_to_sock(struct connection *con) | |||
1272 | if (len) { | 1264 | if (len) { |
1273 | ret = sendpage(con->sock, e->page, offset, len, | 1265 | ret = sendpage(con->sock, e->page, offset, len, |
1274 | msg_flags); | 1266 | msg_flags); |
1275 | if (ret == -EAGAIN || ret == 0) | 1267 | if (ret == -EAGAIN || ret == 0) { |
1268 | cond_resched(); | ||
1276 | goto out; | 1269 | goto out; |
1270 | } | ||
1277 | if (ret <= 0) | 1271 | if (ret <= 0) |
1278 | goto send_error; | 1272 | goto send_error; |
1279 | } else { | 1273 | } |
1280 | /* Don't starve people filling buffers */ | 1274 | /* Don't starve people filling buffers */ |
1281 | cond_resched(); | 1275 | cond_resched(); |
1282 | } | ||
1283 | 1276 | ||
1284 | spin_lock(&con->writequeue_lock); | 1277 | spin_lock(&con->writequeue_lock); |
1285 | e->offset += ret; | 1278 | e->offset += ret; |
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index d09977528f69..e9cdcab306e2 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -18,10 +18,6 @@ | |||
18 | #include "rcom.h" | 18 | #include "rcom.h" |
19 | #include "config.h" | 19 | #include "config.h" |
20 | 20 | ||
21 | /* | ||
22 | * Following called by dlm_recoverd thread | ||
23 | */ | ||
24 | |||
25 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) | 21 | static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new) |
26 | { | 22 | { |
27 | struct dlm_member *memb = NULL; | 23 | struct dlm_member *memb = NULL; |
@@ -250,18 +246,30 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out) | |||
250 | return error; | 246 | return error; |
251 | } | 247 | } |
252 | 248 | ||
253 | /* | 249 | /* Userspace guarantees that dlm_ls_stop() has completed on all nodes before |
254 | * Following called from lockspace.c | 250 | dlm_ls_start() is called on any of them to start the new recovery. */ |
255 | */ | ||
256 | 251 | ||
257 | int dlm_ls_stop(struct dlm_ls *ls) | 252 | int dlm_ls_stop(struct dlm_ls *ls) |
258 | { | 253 | { |
259 | int new; | 254 | int new; |
260 | 255 | ||
261 | /* | 256 | /* |
262 | * A stop cancels any recovery that's in progress (see RECOVERY_STOP, | 257 | * Prevent dlm_recv from being in the middle of something when we do |
263 | * dlm_recovery_stopped()) and prevents any new locks from being | 258 | * the stop. This includes ensuring dlm_recv isn't processing a |
264 | * processed (see RUNNING, dlm_locking_stopped()). | 259 | * recovery message (rcom), while dlm_recoverd is aborting and |
260 | * resetting things from an in-progress recovery. i.e. we want | ||
261 | * dlm_recoverd to abort its recovery without worrying about dlm_recv | ||
262 | * processing an rcom at the same time. Stopping dlm_recv also makes | ||
263 | * it easy for dlm_receive_message() to check locking stopped and add a | ||
264 | * message to the requestqueue without races. | ||
265 | */ | ||
266 | |||
267 | down_write(&ls->ls_recv_active); | ||
268 | |||
269 | /* | ||
270 | * Abort any recovery that's in progress (see RECOVERY_STOP, | ||
271 | * dlm_recovery_stopped()) and tell any other threads running in the | ||
272 | * dlm to quit any processing (see RUNNING, dlm_locking_stopped()). | ||
265 | */ | 273 | */ |
266 | 274 | ||
267 | spin_lock(&ls->ls_recover_lock); | 275 | spin_lock(&ls->ls_recover_lock); |
@@ -271,8 +279,14 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
271 | spin_unlock(&ls->ls_recover_lock); | 279 | spin_unlock(&ls->ls_recover_lock); |
272 | 280 | ||
273 | /* | 281 | /* |
282 | * Let dlm_recv run again, now any normal messages will be saved on the | ||
283 | * requestqueue for later. | ||
284 | */ | ||
285 | |||
286 | up_write(&ls->ls_recv_active); | ||
287 | |||
288 | /* | ||
274 | * This in_recovery lock does two things: | 289 | * This in_recovery lock does two things: |
275 | * | ||
276 | * 1) Keeps this function from returning until all threads are out | 290 | * 1) Keeps this function from returning until all threads are out |
277 | * of locking routines and locking is truely stopped. | 291 | * of locking routines and locking is truely stopped. |
278 | * 2) Keeps any new requests from being processed until it's unlocked | 292 | * 2) Keeps any new requests from being processed until it's unlocked |
@@ -284,9 +298,8 @@ int dlm_ls_stop(struct dlm_ls *ls) | |||
284 | 298 | ||
285 | /* | 299 | /* |
286 | * The recoverd suspend/resume makes sure that dlm_recoverd (if | 300 | * The recoverd suspend/resume makes sure that dlm_recoverd (if |
287 | * running) has noticed the clearing of RUNNING above and quit | 301 | * running) has noticed RECOVERY_STOP above and quit processing the |
288 | * processing the previous recovery. This will be true for all nodes | 302 | * previous recovery. |
289 | * before any nodes start the new recovery. | ||
290 | */ | 303 | */ |
291 | 304 | ||
292 | dlm_recoverd_suspend(ls); | 305 | dlm_recoverd_suspend(ls); |
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index a5126e0c68a6..f8c69dda16a0 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -27,7 +27,6 @@ | |||
27 | #include "dlm_internal.h" | 27 | #include "dlm_internal.h" |
28 | #include "lowcomms.h" | 28 | #include "lowcomms.h" |
29 | #include "config.h" | 29 | #include "config.h" |
30 | #include "rcom.h" | ||
31 | #include "lock.h" | 30 | #include "lock.h" |
32 | #include "midcomms.h" | 31 | #include "midcomms.h" |
33 | 32 | ||
@@ -117,19 +116,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, | |||
117 | offset &= (limit - 1); | 116 | offset &= (limit - 1); |
118 | len -= msglen; | 117 | len -= msglen; |
119 | 118 | ||
120 | switch (msg->h_cmd) { | 119 | dlm_receive_buffer(msg, nodeid); |
121 | case DLM_MSG: | ||
122 | dlm_receive_message(msg, nodeid, 0); | ||
123 | break; | ||
124 | |||
125 | case DLM_RCOM: | ||
126 | dlm_receive_rcom(msg, nodeid); | ||
127 | break; | ||
128 | |||
129 | default: | ||
130 | log_print("unknown msg type %x from %u: %u %u %u %u", | ||
131 | msg->h_cmd, nodeid, msglen, len, offset, ret); | ||
132 | } | ||
133 | } | 120 | } |
134 | 121 | ||
135 | if (msg != (struct dlm_header *) __tmp) | 122 | if (msg != (struct dlm_header *) __tmp) |
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 188b91c027e4..ae2fd97fa4ad 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -386,7 +386,10 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
386 | dlm_recover_process_copy(ls, rc_in); | 386 | dlm_recover_process_copy(ls, rc_in); |
387 | } | 387 | } |
388 | 388 | ||
389 | static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) | 389 | /* If the lockspace doesn't exist then still send a status message |
390 | back; it's possible that it just doesn't have its global_id yet. */ | ||
391 | |||
392 | int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) | ||
390 | { | 393 | { |
391 | struct dlm_rcom *rc; | 394 | struct dlm_rcom *rc; |
392 | struct rcom_config *rf; | 395 | struct rcom_config *rf; |
@@ -446,28 +449,11 @@ static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
446 | return rv; | 449 | return rv; |
447 | } | 450 | } |
448 | 451 | ||
449 | /* Called by dlm_recvd; corresponds to dlm_receive_message() but special | 452 | /* Called by dlm_recv; corresponds to dlm_receive_message() but special |
450 | recovery-only comms are sent through here. */ | 453 | recovery-only comms are sent through here. */ |
451 | 454 | ||
452 | void dlm_receive_rcom(struct dlm_header *hd, int nodeid) | 455 | void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) |
453 | { | 456 | { |
454 | struct dlm_rcom *rc = (struct dlm_rcom *) hd; | ||
455 | struct dlm_ls *ls; | ||
456 | |||
457 | dlm_rcom_in(rc); | ||
458 | |||
459 | /* If the lockspace doesn't exist then still send a status message | ||
460 | back; it's possible that it just doesn't have its global_id yet. */ | ||
461 | |||
462 | ls = dlm_find_lockspace_global(hd->h_lockspace); | ||
463 | if (!ls) { | ||
464 | log_print("lockspace %x from %d type %x not found", | ||
465 | hd->h_lockspace, nodeid, rc->rc_type); | ||
466 | if (rc->rc_type == DLM_RCOM_STATUS) | ||
467 | send_ls_not_ready(nodeid, rc); | ||
468 | return; | ||
469 | } | ||
470 | |||
471 | if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { | 457 | if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { |
472 | log_debug(ls, "ignoring recovery message %x from %d", | 458 | log_debug(ls, "ignoring recovery message %x from %d", |
473 | rc->rc_type, nodeid); | 459 | rc->rc_type, nodeid); |
@@ -477,12 +463,6 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) | |||
477 | if (is_old_reply(ls, rc)) | 463 | if (is_old_reply(ls, rc)) |
478 | goto out; | 464 | goto out; |
479 | 465 | ||
480 | if (nodeid != rc->rc_header.h_nodeid) { | ||
481 | log_error(ls, "bad rcom nodeid %d from %d", | ||
482 | rc->rc_header.h_nodeid, nodeid); | ||
483 | goto out; | ||
484 | } | ||
485 | |||
486 | switch (rc->rc_type) { | 466 | switch (rc->rc_type) { |
487 | case DLM_RCOM_STATUS: | 467 | case DLM_RCOM_STATUS: |
488 | receive_rcom_status(ls, rc); | 468 | receive_rcom_status(ls, rc); |
@@ -520,6 +500,6 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid) | |||
520 | DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type);); | 500 | DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type);); |
521 | } | 501 | } |
522 | out: | 502 | out: |
523 | dlm_put_lockspace(ls); | 503 | return; |
524 | } | 504 | } |
525 | 505 | ||
diff --git a/fs/dlm/rcom.h b/fs/dlm/rcom.h index d7984321ff41..b09abd29ba38 100644 --- a/fs/dlm/rcom.h +++ b/fs/dlm/rcom.h | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -18,7 +18,8 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid); | |||
18 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len); | 18 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len); |
19 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid); | 19 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid); |
20 | int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); | 20 | int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); |
21 | void dlm_receive_rcom(struct dlm_header *hd, int nodeid); | 21 | void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid); |
22 | int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in); | ||
22 | 23 | ||
23 | #endif | 24 | #endif |
24 | 25 | ||
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 66575997861c..4b89e20eebe7 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c | |||
@@ -24,19 +24,28 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | /* If the start for which we're re-enabling locking (seq) has been superseded | 26 | /* If the start for which we're re-enabling locking (seq) has been superseded |
27 | by a newer stop (ls_recover_seq), we need to leave locking disabled. */ | 27 | by a newer stop (ls_recover_seq), we need to leave locking disabled. |
28 | |||
29 | We suspend dlm_recv threads here to avoid the race where dlm_recv a) sees | ||
30 | locking stopped and b) adds a message to the requestqueue, but dlm_recoverd | ||
31 | enables locking and clears the requestqueue between a and b. */ | ||
28 | 32 | ||
29 | static int enable_locking(struct dlm_ls *ls, uint64_t seq) | 33 | static int enable_locking(struct dlm_ls *ls, uint64_t seq) |
30 | { | 34 | { |
31 | int error = -EINTR; | 35 | int error = -EINTR; |
32 | 36 | ||
37 | down_write(&ls->ls_recv_active); | ||
38 | |||
33 | spin_lock(&ls->ls_recover_lock); | 39 | spin_lock(&ls->ls_recover_lock); |
34 | if (ls->ls_recover_seq == seq) { | 40 | if (ls->ls_recover_seq == seq) { |
35 | set_bit(LSFL_RUNNING, &ls->ls_flags); | 41 | set_bit(LSFL_RUNNING, &ls->ls_flags); |
42 | /* unblocks processes waiting to enter the dlm */ | ||
36 | up_write(&ls->ls_in_recovery); | 43 | up_write(&ls->ls_in_recovery); |
37 | error = 0; | 44 | error = 0; |
38 | } | 45 | } |
39 | spin_unlock(&ls->ls_recover_lock); | 46 | spin_unlock(&ls->ls_recover_lock); |
47 | |||
48 | up_write(&ls->ls_recv_active); | ||
40 | return error; | 49 | return error; |
41 | } | 50 | } |
42 | 51 | ||
diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c index 65008d79c96d..0de04f17ccea 100644 --- a/fs/dlm/requestqueue.c +++ b/fs/dlm/requestqueue.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -20,7 +20,7 @@ | |||
20 | struct rq_entry { | 20 | struct rq_entry { |
21 | struct list_head list; | 21 | struct list_head list; |
22 | int nodeid; | 22 | int nodeid; |
23 | char request[1]; | 23 | char request[0]; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | /* | 26 | /* |
@@ -30,42 +30,39 @@ struct rq_entry { | |||
30 | * lockspace is enabled on some while still suspended on others. | 30 | * lockspace is enabled on some while still suspended on others. |
31 | */ | 31 | */ |
32 | 32 | ||
33 | int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) | 33 | void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) |
34 | { | 34 | { |
35 | struct rq_entry *e; | 35 | struct rq_entry *e; |
36 | int length = hd->h_length; | 36 | int length = hd->h_length; |
37 | int rv = 0; | ||
38 | 37 | ||
39 | e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL); | 38 | e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL); |
40 | if (!e) { | 39 | if (!e) { |
41 | log_print("dlm_add_requestqueue: out of memory\n"); | 40 | log_print("dlm_add_requestqueue: out of memory len %d", length); |
42 | return 0; | 41 | return; |
43 | } | 42 | } |
44 | 43 | ||
45 | e->nodeid = nodeid; | 44 | e->nodeid = nodeid; |
46 | memcpy(e->request, hd, length); | 45 | memcpy(e->request, hd, length); |
47 | 46 | ||
48 | /* We need to check dlm_locking_stopped() after taking the mutex to | ||
49 | avoid a race where dlm_recoverd enables locking and runs | ||
50 | process_requestqueue between our earlier dlm_locking_stopped check | ||
51 | and this addition to the requestqueue. */ | ||
52 | |||
53 | mutex_lock(&ls->ls_requestqueue_mutex); | 47 | mutex_lock(&ls->ls_requestqueue_mutex); |
54 | if (dlm_locking_stopped(ls)) | 48 | list_add_tail(&e->list, &ls->ls_requestqueue); |
55 | list_add_tail(&e->list, &ls->ls_requestqueue); | ||
56 | else { | ||
57 | log_debug(ls, "dlm_add_requestqueue skip from %d", nodeid); | ||
58 | kfree(e); | ||
59 | rv = -EAGAIN; | ||
60 | } | ||
61 | mutex_unlock(&ls->ls_requestqueue_mutex); | 49 | mutex_unlock(&ls->ls_requestqueue_mutex); |
62 | return rv; | ||
63 | } | 50 | } |
64 | 51 | ||
52 | /* | ||
53 | * Called by dlm_recoverd to process normal messages saved while recovery was | ||
54 | * happening. Normal locking has been enabled before this is called. dlm_recv | ||
55 | * upon receiving a message, will wait for all saved messages to be drained | ||
56 | * here before processing the message it got. If a new dlm_ls_stop() arrives | ||
57 | * while we're processing these saved messages, it may block trying to suspend | ||
58 | * dlm_recv if dlm_recv is waiting for us in dlm_wait_requestqueue. In that | ||
59 | * case, we don't abort since locking_stopped is still 0. If dlm_recv is not | ||
60 | * waiting for us, then this processing may be aborted due to locking_stopped. | ||
61 | */ | ||
62 | |||
65 | int dlm_process_requestqueue(struct dlm_ls *ls) | 63 | int dlm_process_requestqueue(struct dlm_ls *ls) |
66 | { | 64 | { |
67 | struct rq_entry *e; | 65 | struct rq_entry *e; |
68 | struct dlm_header *hd; | ||
69 | int error = 0; | 66 | int error = 0; |
70 | 67 | ||
71 | mutex_lock(&ls->ls_requestqueue_mutex); | 68 | mutex_lock(&ls->ls_requestqueue_mutex); |
@@ -79,14 +76,7 @@ int dlm_process_requestqueue(struct dlm_ls *ls) | |||
79 | e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list); | 76 | e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list); |
80 | mutex_unlock(&ls->ls_requestqueue_mutex); | 77 | mutex_unlock(&ls->ls_requestqueue_mutex); |
81 | 78 | ||
82 | hd = (struct dlm_header *) e->request; | 79 | dlm_receive_message_saved(ls, (struct dlm_message *)e->request); |
83 | error = dlm_receive_message(hd, e->nodeid, 1); | ||
84 | |||
85 | if (error == -EINTR) { | ||
86 | /* entry is left on requestqueue */ | ||
87 | log_debug(ls, "process_requestqueue abort eintr"); | ||
88 | break; | ||
89 | } | ||
90 | 80 | ||
91 | mutex_lock(&ls->ls_requestqueue_mutex); | 81 | mutex_lock(&ls->ls_requestqueue_mutex); |
92 | list_del(&e->list); | 82 | list_del(&e->list); |
@@ -106,10 +96,12 @@ int dlm_process_requestqueue(struct dlm_ls *ls) | |||
106 | 96 | ||
107 | /* | 97 | /* |
108 | * After recovery is done, locking is resumed and dlm_recoverd takes all the | 98 | * After recovery is done, locking is resumed and dlm_recoverd takes all the |
109 | * saved requests and processes them as they would have been by dlm_recvd. At | 99 | * saved requests and processes them as they would have been by dlm_recv. At |
110 | * the same time, dlm_recvd will start receiving new requests from remote | 100 | * the same time, dlm_recv will start receiving new requests from remote nodes. |
111 | * nodes. We want to delay dlm_recvd processing new requests until | 101 | * We want to delay dlm_recv processing new requests until dlm_recoverd has |
112 | * dlm_recoverd has finished processing the old saved requests. | 102 | * finished processing the old saved requests. We don't check for locking |
103 | * stopped here because dlm_ls_stop won't stop locking until it's suspended us | ||
104 | * (dlm_recv). | ||
113 | */ | 105 | */ |
114 | 106 | ||
115 | void dlm_wait_requestqueue(struct dlm_ls *ls) | 107 | void dlm_wait_requestqueue(struct dlm_ls *ls) |
@@ -118,8 +110,6 @@ void dlm_wait_requestqueue(struct dlm_ls *ls) | |||
118 | mutex_lock(&ls->ls_requestqueue_mutex); | 110 | mutex_lock(&ls->ls_requestqueue_mutex); |
119 | if (list_empty(&ls->ls_requestqueue)) | 111 | if (list_empty(&ls->ls_requestqueue)) |
120 | break; | 112 | break; |
121 | if (dlm_locking_stopped(ls)) | ||
122 | break; | ||
123 | mutex_unlock(&ls->ls_requestqueue_mutex); | 113 | mutex_unlock(&ls->ls_requestqueue_mutex); |
124 | schedule(); | 114 | schedule(); |
125 | } | 115 | } |
diff --git a/fs/dlm/requestqueue.h b/fs/dlm/requestqueue.h index 6a53ea03335d..aba34fc05ee4 100644 --- a/fs/dlm/requestqueue.h +++ b/fs/dlm/requestqueue.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -13,7 +13,7 @@ | |||
13 | #ifndef __REQUESTQUEUE_DOT_H__ | 13 | #ifndef __REQUESTQUEUE_DOT_H__ |
14 | #define __REQUESTQUEUE_DOT_H__ | 14 | #define __REQUESTQUEUE_DOT_H__ |
15 | 15 | ||
16 | int dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd); | 16 | void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd); |
17 | int dlm_process_requestqueue(struct dlm_ls *ls); | 17 | int dlm_process_requestqueue(struct dlm_ls *ls); |
18 | void dlm_wait_requestqueue(struct dlm_ls *ls); | 18 | void dlm_wait_requestqueue(struct dlm_ls *ls); |
19 | void dlm_purge_requestqueue(struct dlm_ls *ls); | 19 | void dlm_purge_requestqueue(struct dlm_ls *ls); |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index cd805a66880d..93fa427bb5f5 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -93,9 +93,10 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
93 | map_bh(bh, inode->i_sb, block); | 93 | map_bh(bh, inode->i_sb, block); |
94 | 94 | ||
95 | set_buffer_uptodate(bh); | 95 | set_buffer_uptodate(bh); |
96 | if (!gfs2_is_jdata(ip)) | ||
97 | mark_buffer_dirty(bh); | ||
96 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) | 98 | if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) |
97 | gfs2_trans_add_bh(ip->i_gl, bh, 0); | 99 | gfs2_trans_add_bh(ip->i_gl, bh, 0); |
98 | mark_buffer_dirty(bh); | ||
99 | 100 | ||
100 | if (release) { | 101 | if (release) { |
101 | unlock_page(page); | 102 | unlock_page(page); |
@@ -1085,6 +1086,33 @@ static int do_shrink(struct gfs2_inode *ip, u64 size) | |||
1085 | return error; | 1086 | return error; |
1086 | } | 1087 | } |
1087 | 1088 | ||
1089 | static int do_touch(struct gfs2_inode *ip, u64 size) | ||
1090 | { | ||
1091 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1092 | struct buffer_head *dibh; | ||
1093 | int error; | ||
1094 | |||
1095 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | ||
1096 | if (error) | ||
1097 | return error; | ||
1098 | |||
1099 | down_write(&ip->i_rw_mutex); | ||
1100 | |||
1101 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
1102 | if (error) | ||
1103 | goto do_touch_out; | ||
1104 | |||
1105 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | ||
1106 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
1107 | gfs2_dinode_out(ip, dibh->b_data); | ||
1108 | brelse(dibh); | ||
1109 | |||
1110 | do_touch_out: | ||
1111 | up_write(&ip->i_rw_mutex); | ||
1112 | gfs2_trans_end(sdp); | ||
1113 | return error; | ||
1114 | } | ||
1115 | |||
1088 | /** | 1116 | /** |
1089 | * gfs2_truncatei - make a file a given size | 1117 | * gfs2_truncatei - make a file a given size |
1090 | * @ip: the inode | 1118 | * @ip: the inode |
@@ -1105,8 +1133,11 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size) | |||
1105 | 1133 | ||
1106 | if (size > ip->i_di.di_size) | 1134 | if (size > ip->i_di.di_size) |
1107 | error = do_grow(ip, size); | 1135 | error = do_grow(ip, size); |
1108 | else | 1136 | else if (size < ip->i_di.di_size) |
1109 | error = do_shrink(ip, size); | 1137 | error = do_shrink(ip, size); |
1138 | else | ||
1139 | /* update time stamps */ | ||
1140 | error = do_touch(ip, size); | ||
1110 | 1141 | ||
1111 | return error; | 1142 | return error; |
1112 | } | 1143 | } |
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c index 3548d9f31e0d..3731ab0771d5 100644 --- a/fs/gfs2/daemon.c +++ b/fs/gfs2/daemon.c | |||
@@ -35,30 +35,6 @@ | |||
35 | The kthread functions used to start these daemons block and flush signals. */ | 35 | The kthread functions used to start these daemons block and flush signals. */ |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * gfs2_scand - Look for cached glocks and inodes to toss from memory | ||
39 | * @sdp: Pointer to GFS2 superblock | ||
40 | * | ||
41 | * One of these daemons runs, finding candidates to add to sd_reclaim_list. | ||
42 | * See gfs2_glockd() | ||
43 | */ | ||
44 | |||
45 | int gfs2_scand(void *data) | ||
46 | { | ||
47 | struct gfs2_sbd *sdp = data; | ||
48 | unsigned long t; | ||
49 | |||
50 | while (!kthread_should_stop()) { | ||
51 | gfs2_scand_internal(sdp); | ||
52 | t = gfs2_tune_get(sdp, gt_scand_secs) * HZ; | ||
53 | if (freezing(current)) | ||
54 | refrigerator(); | ||
55 | schedule_timeout_interruptible(t); | ||
56 | } | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * gfs2_glockd - Reclaim unused glock structures | 38 | * gfs2_glockd - Reclaim unused glock structures |
63 | * @sdp: Pointer to GFS2 superblock | 39 | * @sdp: Pointer to GFS2 superblock |
64 | * | 40 | * |
diff --git a/fs/gfs2/daemon.h b/fs/gfs2/daemon.h index 801007120fb2..0de9b3557955 100644 --- a/fs/gfs2/daemon.h +++ b/fs/gfs2/daemon.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #ifndef __DAEMON_DOT_H__ | 10 | #ifndef __DAEMON_DOT_H__ |
11 | #define __DAEMON_DOT_H__ | 11 | #define __DAEMON_DOT_H__ |
12 | 12 | ||
13 | int gfs2_scand(void *data); | ||
14 | int gfs2_glockd(void *data); | 13 | int gfs2_glockd(void *data); |
15 | int gfs2_recoverd(void *data); | 14 | int gfs2_recoverd(void *data); |
16 | int gfs2_logd(void *data); | 15 | int gfs2_logd(void *data); |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 2beb2f401aa2..9949bb746a52 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1043,6 +1043,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
1043 | 1043 | ||
1044 | error = gfs2_meta_inode_buffer(dip, &dibh); | 1044 | error = gfs2_meta_inode_buffer(dip, &dibh); |
1045 | if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { | 1045 | if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { |
1046 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); | ||
1046 | dip->i_di.di_blocks++; | 1047 | dip->i_di.di_blocks++; |
1047 | gfs2_set_inode_blocks(&dip->i_inode); | 1048 | gfs2_set_inode_blocks(&dip->i_inode); |
1048 | gfs2_dinode_out(dip, dibh->b_data); | 1049 | gfs2_dinode_out(dip, dibh->b_data); |
@@ -1501,7 +1502,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) | |||
1501 | inode = gfs2_inode_lookup(dir->i_sb, | 1502 | inode = gfs2_inode_lookup(dir->i_sb, |
1502 | be16_to_cpu(dent->de_type), | 1503 | be16_to_cpu(dent->de_type), |
1503 | be64_to_cpu(dent->de_inum.no_addr), | 1504 | be64_to_cpu(dent->de_inum.no_addr), |
1504 | be64_to_cpu(dent->de_inum.no_formal_ino)); | 1505 | be64_to_cpu(dent->de_inum.no_formal_ino), 0); |
1505 | brelse(bh); | 1506 | brelse(bh); |
1506 | return inode; | 1507 | return inode; |
1507 | } | 1508 | } |
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index 1ab3e9d73886..aa8dbf303f6d 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c | |||
@@ -200,28 +200,28 @@ static int security_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er) | |||
200 | return gfs2_ea_remove_i(ip, er); | 200 | return gfs2_ea_remove_i(ip, er); |
201 | } | 201 | } |
202 | 202 | ||
203 | static struct gfs2_eattr_operations gfs2_user_eaops = { | 203 | static const struct gfs2_eattr_operations gfs2_user_eaops = { |
204 | .eo_get = user_eo_get, | 204 | .eo_get = user_eo_get, |
205 | .eo_set = user_eo_set, | 205 | .eo_set = user_eo_set, |
206 | .eo_remove = user_eo_remove, | 206 | .eo_remove = user_eo_remove, |
207 | .eo_name = "user", | 207 | .eo_name = "user", |
208 | }; | 208 | }; |
209 | 209 | ||
210 | struct gfs2_eattr_operations gfs2_system_eaops = { | 210 | const struct gfs2_eattr_operations gfs2_system_eaops = { |
211 | .eo_get = system_eo_get, | 211 | .eo_get = system_eo_get, |
212 | .eo_set = system_eo_set, | 212 | .eo_set = system_eo_set, |
213 | .eo_remove = system_eo_remove, | 213 | .eo_remove = system_eo_remove, |
214 | .eo_name = "system", | 214 | .eo_name = "system", |
215 | }; | 215 | }; |
216 | 216 | ||
217 | static struct gfs2_eattr_operations gfs2_security_eaops = { | 217 | static const struct gfs2_eattr_operations gfs2_security_eaops = { |
218 | .eo_get = security_eo_get, | 218 | .eo_get = security_eo_get, |
219 | .eo_set = security_eo_set, | 219 | .eo_set = security_eo_set, |
220 | .eo_remove = security_eo_remove, | 220 | .eo_remove = security_eo_remove, |
221 | .eo_name = "security", | 221 | .eo_name = "security", |
222 | }; | 222 | }; |
223 | 223 | ||
224 | struct gfs2_eattr_operations *gfs2_ea_ops[] = { | 224 | const struct gfs2_eattr_operations *gfs2_ea_ops[] = { |
225 | NULL, | 225 | NULL, |
226 | &gfs2_user_eaops, | 226 | &gfs2_user_eaops, |
227 | &gfs2_system_eaops, | 227 | &gfs2_system_eaops, |
diff --git a/fs/gfs2/eaops.h b/fs/gfs2/eaops.h index 508b4f7a2449..da2f7fbbb40d 100644 --- a/fs/gfs2/eaops.h +++ b/fs/gfs2/eaops.h | |||
@@ -22,9 +22,9 @@ struct gfs2_eattr_operations { | |||
22 | 22 | ||
23 | unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name); | 23 | unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name); |
24 | 24 | ||
25 | extern struct gfs2_eattr_operations gfs2_system_eaops; | 25 | extern const struct gfs2_eattr_operations gfs2_system_eaops; |
26 | 26 | ||
27 | extern struct gfs2_eattr_operations *gfs2_ea_ops[]; | 27 | extern const struct gfs2_eattr_operations *gfs2_ea_ops[]; |
28 | 28 | ||
29 | #endif /* __EAOPS_DOT_H__ */ | 29 | #endif /* __EAOPS_DOT_H__ */ |
30 | 30 | ||
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 3f0974e1afef..a37efe4aae6f 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -25,8 +25,10 @@ | |||
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
28 | #include <linux/module.h> | 28 | #include <linux/kthread.h> |
29 | #include <linux/kallsyms.h> | 29 | #include <linux/freezer.h> |
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/jiffies.h> | ||
30 | 32 | ||
31 | #include "gfs2.h" | 33 | #include "gfs2.h" |
32 | #include "incore.h" | 34 | #include "incore.h" |
@@ -48,7 +50,6 @@ struct glock_iter { | |||
48 | int hash; /* hash bucket index */ | 50 | int hash; /* hash bucket index */ |
49 | struct gfs2_sbd *sdp; /* incore superblock */ | 51 | struct gfs2_sbd *sdp; /* incore superblock */ |
50 | struct gfs2_glock *gl; /* current glock struct */ | 52 | struct gfs2_glock *gl; /* current glock struct */ |
51 | struct hlist_head *hb_list; /* current hash bucket ptr */ | ||
52 | struct seq_file *seq; /* sequence file for debugfs */ | 53 | struct seq_file *seq; /* sequence file for debugfs */ |
53 | char string[512]; /* scratch space */ | 54 | char string[512]; /* scratch space */ |
54 | }; | 55 | }; |
@@ -59,8 +60,13 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); | |||
59 | static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl); | 60 | static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl); |
60 | static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh); | 61 | static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh); |
61 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); | 62 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); |
63 | static void run_queue(struct gfs2_glock *gl); | ||
64 | |||
62 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | 65 | static DECLARE_RWSEM(gfs2_umount_flush_sem); |
63 | static struct dentry *gfs2_root; | 66 | static struct dentry *gfs2_root; |
67 | static struct task_struct *scand_process; | ||
68 | static unsigned int scand_secs = 5; | ||
69 | static struct workqueue_struct *glock_workqueue; | ||
64 | 70 | ||
65 | #define GFS2_GL_HASH_SHIFT 15 | 71 | #define GFS2_GL_HASH_SHIFT 15 |
66 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) | 72 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) |
@@ -276,6 +282,18 @@ static struct gfs2_glock *gfs2_glock_find(const struct gfs2_sbd *sdp, | |||
276 | return gl; | 282 | return gl; |
277 | } | 283 | } |
278 | 284 | ||
285 | static void glock_work_func(struct work_struct *work) | ||
286 | { | ||
287 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); | ||
288 | |||
289 | spin_lock(&gl->gl_spin); | ||
290 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags)) | ||
291 | set_bit(GLF_DEMOTE, &gl->gl_flags); | ||
292 | run_queue(gl); | ||
293 | spin_unlock(&gl->gl_spin); | ||
294 | gfs2_glock_put(gl); | ||
295 | } | ||
296 | |||
279 | /** | 297 | /** |
280 | * gfs2_glock_get() - Get a glock, or create one if one doesn't exist | 298 | * gfs2_glock_get() - Get a glock, or create one if one doesn't exist |
281 | * @sdp: The GFS2 superblock | 299 | * @sdp: The GFS2 superblock |
@@ -315,6 +333,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
315 | gl->gl_name = name; | 333 | gl->gl_name = name; |
316 | atomic_set(&gl->gl_ref, 1); | 334 | atomic_set(&gl->gl_ref, 1); |
317 | gl->gl_state = LM_ST_UNLOCKED; | 335 | gl->gl_state = LM_ST_UNLOCKED; |
336 | gl->gl_demote_state = LM_ST_EXCLUSIVE; | ||
318 | gl->gl_hash = hash; | 337 | gl->gl_hash = hash; |
319 | gl->gl_owner_pid = 0; | 338 | gl->gl_owner_pid = 0; |
320 | gl->gl_ip = 0; | 339 | gl->gl_ip = 0; |
@@ -323,10 +342,12 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
323 | gl->gl_req_bh = NULL; | 342 | gl->gl_req_bh = NULL; |
324 | gl->gl_vn = 0; | 343 | gl->gl_vn = 0; |
325 | gl->gl_stamp = jiffies; | 344 | gl->gl_stamp = jiffies; |
345 | gl->gl_tchange = jiffies; | ||
326 | gl->gl_object = NULL; | 346 | gl->gl_object = NULL; |
327 | gl->gl_sbd = sdp; | 347 | gl->gl_sbd = sdp; |
328 | gl->gl_aspace = NULL; | 348 | gl->gl_aspace = NULL; |
329 | lops_init_le(&gl->gl_le, &gfs2_glock_lops); | 349 | lops_init_le(&gl->gl_le, &gfs2_glock_lops); |
350 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | ||
330 | 351 | ||
331 | /* If this glock protects actual on-disk data or metadata blocks, | 352 | /* If this glock protects actual on-disk data or metadata blocks, |
332 | create a VFS inode to manage the pages/buffers holding them. */ | 353 | create a VFS inode to manage the pages/buffers holding them. */ |
@@ -440,6 +461,8 @@ static void wait_on_holder(struct gfs2_holder *gh) | |||
440 | 461 | ||
441 | static void gfs2_demote_wake(struct gfs2_glock *gl) | 462 | static void gfs2_demote_wake(struct gfs2_glock *gl) |
442 | { | 463 | { |
464 | BUG_ON(!spin_is_locked(&gl->gl_spin)); | ||
465 | gl->gl_demote_state = LM_ST_EXCLUSIVE; | ||
443 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | 466 | clear_bit(GLF_DEMOTE, &gl->gl_flags); |
444 | smp_mb__after_clear_bit(); | 467 | smp_mb__after_clear_bit(); |
445 | wake_up_bit(&gl->gl_flags, GLF_DEMOTE); | 468 | wake_up_bit(&gl->gl_flags, GLF_DEMOTE); |
@@ -545,12 +568,14 @@ static int rq_demote(struct gfs2_glock *gl) | |||
545 | return 0; | 568 | return 0; |
546 | } | 569 | } |
547 | set_bit(GLF_LOCK, &gl->gl_flags); | 570 | set_bit(GLF_LOCK, &gl->gl_flags); |
548 | spin_unlock(&gl->gl_spin); | ||
549 | if (gl->gl_demote_state == LM_ST_UNLOCKED || | 571 | if (gl->gl_demote_state == LM_ST_UNLOCKED || |
550 | gl->gl_state != LM_ST_EXCLUSIVE) | 572 | gl->gl_state != LM_ST_EXCLUSIVE) { |
573 | spin_unlock(&gl->gl_spin); | ||
551 | gfs2_glock_drop_th(gl); | 574 | gfs2_glock_drop_th(gl); |
552 | else | 575 | } else { |
576 | spin_unlock(&gl->gl_spin); | ||
553 | gfs2_glock_xmote_th(gl, NULL); | 577 | gfs2_glock_xmote_th(gl, NULL); |
578 | } | ||
554 | spin_lock(&gl->gl_spin); | 579 | spin_lock(&gl->gl_spin); |
555 | 580 | ||
556 | return 0; | 581 | return 0; |
@@ -679,24 +704,25 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl) | |||
679 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED | 704 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED |
680 | */ | 705 | */ |
681 | 706 | ||
682 | static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote) | 707 | static void handle_callback(struct gfs2_glock *gl, unsigned int state, |
708 | int remote, unsigned long delay) | ||
683 | { | 709 | { |
710 | int bit = delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE; | ||
711 | |||
684 | spin_lock(&gl->gl_spin); | 712 | spin_lock(&gl->gl_spin); |
685 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { | 713 | set_bit(bit, &gl->gl_flags); |
714 | if (gl->gl_demote_state == LM_ST_EXCLUSIVE) { | ||
686 | gl->gl_demote_state = state; | 715 | gl->gl_demote_state = state; |
687 | gl->gl_demote_time = jiffies; | 716 | gl->gl_demote_time = jiffies; |
688 | if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN && | 717 | if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN && |
689 | gl->gl_object) { | 718 | gl->gl_object) { |
690 | struct inode *inode = igrab(gl->gl_object); | 719 | gfs2_glock_schedule_for_reclaim(gl); |
691 | spin_unlock(&gl->gl_spin); | 720 | spin_unlock(&gl->gl_spin); |
692 | if (inode) { | ||
693 | d_prune_aliases(inode); | ||
694 | iput(inode); | ||
695 | } | ||
696 | return; | 721 | return; |
697 | } | 722 | } |
698 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { | 723 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED && |
699 | gl->gl_demote_state = state; | 724 | gl->gl_demote_state != state) { |
725 | gl->gl_demote_state = LM_ST_UNLOCKED; | ||
700 | } | 726 | } |
701 | spin_unlock(&gl->gl_spin); | 727 | spin_unlock(&gl->gl_spin); |
702 | } | 728 | } |
@@ -723,6 +749,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) | |||
723 | } | 749 | } |
724 | 750 | ||
725 | gl->gl_state = new_state; | 751 | gl->gl_state = new_state; |
752 | gl->gl_tchange = jiffies; | ||
726 | } | 753 | } |
727 | 754 | ||
728 | /** | 755 | /** |
@@ -760,10 +787,20 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
760 | 787 | ||
761 | if (!gh) { | 788 | if (!gh) { |
762 | gl->gl_stamp = jiffies; | 789 | gl->gl_stamp = jiffies; |
763 | if (ret & LM_OUT_CANCELED) | 790 | if (ret & LM_OUT_CANCELED) { |
764 | op_done = 0; | 791 | op_done = 0; |
765 | else | 792 | } else { |
793 | spin_lock(&gl->gl_spin); | ||
794 | if (gl->gl_state != gl->gl_demote_state) { | ||
795 | gl->gl_req_bh = NULL; | ||
796 | spin_unlock(&gl->gl_spin); | ||
797 | gfs2_glock_drop_th(gl); | ||
798 | gfs2_glock_put(gl); | ||
799 | return; | ||
800 | } | ||
766 | gfs2_demote_wake(gl); | 801 | gfs2_demote_wake(gl); |
802 | spin_unlock(&gl->gl_spin); | ||
803 | } | ||
767 | } else { | 804 | } else { |
768 | spin_lock(&gl->gl_spin); | 805 | spin_lock(&gl->gl_spin); |
769 | list_del_init(&gh->gh_list); | 806 | list_del_init(&gh->gh_list); |
@@ -799,7 +836,6 @@ out: | |||
799 | gl->gl_req_gh = NULL; | 836 | gl->gl_req_gh = NULL; |
800 | gl->gl_req_bh = NULL; | 837 | gl->gl_req_bh = NULL; |
801 | clear_bit(GLF_LOCK, &gl->gl_flags); | 838 | clear_bit(GLF_LOCK, &gl->gl_flags); |
802 | run_queue(gl); | ||
803 | spin_unlock(&gl->gl_spin); | 839 | spin_unlock(&gl->gl_spin); |
804 | } | 840 | } |
805 | 841 | ||
@@ -817,7 +853,7 @@ out: | |||
817 | * | 853 | * |
818 | */ | 854 | */ |
819 | 855 | ||
820 | void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | 856 | static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) |
821 | { | 857 | { |
822 | struct gfs2_sbd *sdp = gl->gl_sbd; | 858 | struct gfs2_sbd *sdp = gl->gl_sbd; |
823 | int flags = gh ? gh->gh_flags : 0; | 859 | int flags = gh ? gh->gh_flags : 0; |
@@ -871,7 +907,6 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
871 | gfs2_assert_warn(sdp, !ret); | 907 | gfs2_assert_warn(sdp, !ret); |
872 | 908 | ||
873 | state_change(gl, LM_ST_UNLOCKED); | 909 | state_change(gl, LM_ST_UNLOCKED); |
874 | gfs2_demote_wake(gl); | ||
875 | 910 | ||
876 | if (glops->go_inval) | 911 | if (glops->go_inval) |
877 | glops->go_inval(gl, DIO_METADATA); | 912 | glops->go_inval(gl, DIO_METADATA); |
@@ -884,10 +919,10 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
884 | } | 919 | } |
885 | 920 | ||
886 | spin_lock(&gl->gl_spin); | 921 | spin_lock(&gl->gl_spin); |
922 | gfs2_demote_wake(gl); | ||
887 | gl->gl_req_gh = NULL; | 923 | gl->gl_req_gh = NULL; |
888 | gl->gl_req_bh = NULL; | 924 | gl->gl_req_bh = NULL; |
889 | clear_bit(GLF_LOCK, &gl->gl_flags); | 925 | clear_bit(GLF_LOCK, &gl->gl_flags); |
890 | run_queue(gl); | ||
891 | spin_unlock(&gl->gl_spin); | 926 | spin_unlock(&gl->gl_spin); |
892 | 927 | ||
893 | gfs2_glock_put(gl); | 928 | gfs2_glock_put(gl); |
@@ -1067,24 +1102,31 @@ static void add_to_queue(struct gfs2_holder *gh) | |||
1067 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) | 1102 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) |
1068 | BUG(); | 1103 | BUG(); |
1069 | 1104 | ||
1070 | existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner_pid); | 1105 | if (!(gh->gh_flags & GL_FLOCK)) { |
1071 | if (existing) { | 1106 | existing = find_holder_by_owner(&gl->gl_holders, |
1072 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); | 1107 | gh->gh_owner_pid); |
1073 | printk(KERN_INFO "pid : %d\n", existing->gh_owner_pid); | 1108 | if (existing) { |
1074 | printk(KERN_INFO "lock type : %d lock state : %d\n", | 1109 | print_symbol(KERN_WARNING "original: %s\n", |
1075 | existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state); | 1110 | existing->gh_ip); |
1076 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | 1111 | printk(KERN_INFO "pid : %d\n", existing->gh_owner_pid); |
1077 | printk(KERN_INFO "pid : %d\n", gh->gh_owner_pid); | 1112 | printk(KERN_INFO "lock type : %d lock state : %d\n", |
1078 | printk(KERN_INFO "lock type : %d lock state : %d\n", | 1113 | existing->gh_gl->gl_name.ln_type, |
1079 | gl->gl_name.ln_type, gl->gl_state); | 1114 | existing->gh_gl->gl_state); |
1080 | BUG(); | 1115 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); |
1081 | } | 1116 | printk(KERN_INFO "pid : %d\n", gh->gh_owner_pid); |
1082 | 1117 | printk(KERN_INFO "lock type : %d lock state : %d\n", | |
1083 | existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner_pid); | 1118 | gl->gl_name.ln_type, gl->gl_state); |
1084 | if (existing) { | 1119 | BUG(); |
1085 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); | 1120 | } |
1086 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | 1121 | |
1087 | BUG(); | 1122 | existing = find_holder_by_owner(&gl->gl_waiters3, |
1123 | gh->gh_owner_pid); | ||
1124 | if (existing) { | ||
1125 | print_symbol(KERN_WARNING "original: %s\n", | ||
1126 | existing->gh_ip); | ||
1127 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | ||
1128 | BUG(); | ||
1129 | } | ||
1088 | } | 1130 | } |
1089 | 1131 | ||
1090 | if (gh->gh_flags & LM_FLAG_PRIORITY) | 1132 | if (gh->gh_flags & LM_FLAG_PRIORITY) |
@@ -1195,9 +1237,10 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1195 | { | 1237 | { |
1196 | struct gfs2_glock *gl = gh->gh_gl; | 1238 | struct gfs2_glock *gl = gh->gh_gl; |
1197 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 1239 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
1240 | unsigned delay = 0; | ||
1198 | 1241 | ||
1199 | if (gh->gh_flags & GL_NOCACHE) | 1242 | if (gh->gh_flags & GL_NOCACHE) |
1200 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1243 | handle_callback(gl, LM_ST_UNLOCKED, 0, 0); |
1201 | 1244 | ||
1202 | gfs2_glmutex_lock(gl); | 1245 | gfs2_glmutex_lock(gl); |
1203 | 1246 | ||
@@ -1215,8 +1258,14 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1215 | } | 1258 | } |
1216 | 1259 | ||
1217 | clear_bit(GLF_LOCK, &gl->gl_flags); | 1260 | clear_bit(GLF_LOCK, &gl->gl_flags); |
1218 | run_queue(gl); | ||
1219 | spin_unlock(&gl->gl_spin); | 1261 | spin_unlock(&gl->gl_spin); |
1262 | |||
1263 | gfs2_glock_hold(gl); | ||
1264 | if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && | ||
1265 | !test_bit(GLF_DEMOTE, &gl->gl_flags)) | ||
1266 | delay = gl->gl_ops->go_min_hold_time; | ||
1267 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | ||
1268 | gfs2_glock_put(gl); | ||
1220 | } | 1269 | } |
1221 | 1270 | ||
1222 | void gfs2_glock_dq_wait(struct gfs2_holder *gh) | 1271 | void gfs2_glock_dq_wait(struct gfs2_holder *gh) |
@@ -1443,18 +1492,21 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, | |||
1443 | unsigned int state) | 1492 | unsigned int state) |
1444 | { | 1493 | { |
1445 | struct gfs2_glock *gl; | 1494 | struct gfs2_glock *gl; |
1495 | unsigned long delay = 0; | ||
1496 | unsigned long holdtime; | ||
1497 | unsigned long now = jiffies; | ||
1446 | 1498 | ||
1447 | gl = gfs2_glock_find(sdp, name); | 1499 | gl = gfs2_glock_find(sdp, name); |
1448 | if (!gl) | 1500 | if (!gl) |
1449 | return; | 1501 | return; |
1450 | 1502 | ||
1451 | handle_callback(gl, state, 1); | 1503 | holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time; |
1452 | 1504 | if (time_before(now, holdtime)) | |
1453 | spin_lock(&gl->gl_spin); | 1505 | delay = holdtime - now; |
1454 | run_queue(gl); | ||
1455 | spin_unlock(&gl->gl_spin); | ||
1456 | 1506 | ||
1457 | gfs2_glock_put(gl); | 1507 | handle_callback(gl, state, 1, delay); |
1508 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | ||
1509 | gfs2_glock_put(gl); | ||
1458 | } | 1510 | } |
1459 | 1511 | ||
1460 | /** | 1512 | /** |
@@ -1495,7 +1547,8 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data) | |||
1495 | return; | 1547 | return; |
1496 | if (!gfs2_assert_warn(sdp, gl->gl_req_bh)) | 1548 | if (!gfs2_assert_warn(sdp, gl->gl_req_bh)) |
1497 | gl->gl_req_bh(gl, async->lc_ret); | 1549 | gl->gl_req_bh(gl, async->lc_ret); |
1498 | gfs2_glock_put(gl); | 1550 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
1551 | gfs2_glock_put(gl); | ||
1499 | up_read(&gfs2_umount_flush_sem); | 1552 | up_read(&gfs2_umount_flush_sem); |
1500 | return; | 1553 | return; |
1501 | } | 1554 | } |
@@ -1588,7 +1641,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp) | |||
1588 | if (gfs2_glmutex_trylock(gl)) { | 1641 | if (gfs2_glmutex_trylock(gl)) { |
1589 | if (list_empty(&gl->gl_holders) && | 1642 | if (list_empty(&gl->gl_holders) && |
1590 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) | 1643 | gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) |
1591 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1644 | handle_callback(gl, LM_ST_UNLOCKED, 0, 0); |
1592 | gfs2_glmutex_unlock(gl); | 1645 | gfs2_glmutex_unlock(gl); |
1593 | } | 1646 | } |
1594 | 1647 | ||
@@ -1617,7 +1670,7 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp, | |||
1617 | goto out; | 1670 | goto out; |
1618 | gl = list_entry(head->first, struct gfs2_glock, gl_list); | 1671 | gl = list_entry(head->first, struct gfs2_glock, gl_list); |
1619 | while(1) { | 1672 | while(1) { |
1620 | if (gl->gl_sbd == sdp) { | 1673 | if (!sdp || gl->gl_sbd == sdp) { |
1621 | gfs2_glock_hold(gl); | 1674 | gfs2_glock_hold(gl); |
1622 | read_unlock(gl_lock_addr(hash)); | 1675 | read_unlock(gl_lock_addr(hash)); |
1623 | if (prev) | 1676 | if (prev) |
@@ -1635,6 +1688,7 @@ out: | |||
1635 | read_unlock(gl_lock_addr(hash)); | 1688 | read_unlock(gl_lock_addr(hash)); |
1636 | if (prev) | 1689 | if (prev) |
1637 | gfs2_glock_put(prev); | 1690 | gfs2_glock_put(prev); |
1691 | cond_resched(); | ||
1638 | return has_entries; | 1692 | return has_entries; |
1639 | } | 1693 | } |
1640 | 1694 | ||
@@ -1663,20 +1717,6 @@ out_schedule: | |||
1663 | } | 1717 | } |
1664 | 1718 | ||
1665 | /** | 1719 | /** |
1666 | * gfs2_scand_internal - Look for glocks and inodes to toss from memory | ||
1667 | * @sdp: the filesystem | ||
1668 | * | ||
1669 | */ | ||
1670 | |||
1671 | void gfs2_scand_internal(struct gfs2_sbd *sdp) | ||
1672 | { | ||
1673 | unsigned int x; | ||
1674 | |||
1675 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) | ||
1676 | examine_bucket(scan_glock, sdp, x); | ||
1677 | } | ||
1678 | |||
1679 | /** | ||
1680 | * clear_glock - look at a glock and see if we can free it from glock cache | 1720 | * clear_glock - look at a glock and see if we can free it from glock cache |
1681 | * @gl: the glock to look at | 1721 | * @gl: the glock to look at |
1682 | * | 1722 | * |
@@ -1701,7 +1741,7 @@ static void clear_glock(struct gfs2_glock *gl) | |||
1701 | if (gfs2_glmutex_trylock(gl)) { | 1741 | if (gfs2_glmutex_trylock(gl)) { |
1702 | if (list_empty(&gl->gl_holders) && | 1742 | if (list_empty(&gl->gl_holders) && |
1703 | gl->gl_state != LM_ST_UNLOCKED) | 1743 | gl->gl_state != LM_ST_UNLOCKED) |
1704 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1744 | handle_callback(gl, LM_ST_UNLOCKED, 0, 0); |
1705 | gfs2_glmutex_unlock(gl); | 1745 | gfs2_glmutex_unlock(gl); |
1706 | } | 1746 | } |
1707 | } | 1747 | } |
@@ -1843,7 +1883,7 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) | |||
1843 | 1883 | ||
1844 | spin_lock(&gl->gl_spin); | 1884 | spin_lock(&gl->gl_spin); |
1845 | 1885 | ||
1846 | print_dbg(gi, "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type, | 1886 | print_dbg(gi, "Glock 0x%p (%u, 0x%llx)\n", gl, gl->gl_name.ln_type, |
1847 | (unsigned long long)gl->gl_name.ln_number); | 1887 | (unsigned long long)gl->gl_name.ln_number); |
1848 | print_dbg(gi, " gl_flags ="); | 1888 | print_dbg(gi, " gl_flags ="); |
1849 | for (x = 0; x < 32; x++) { | 1889 | for (x = 0; x < 32; x++) { |
@@ -1963,6 +2003,35 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp) | |||
1963 | return error; | 2003 | return error; |
1964 | } | 2004 | } |
1965 | 2005 | ||
2006 | /** | ||
2007 | * gfs2_scand - Look for cached glocks and inodes to toss from memory | ||
2008 | * @sdp: Pointer to GFS2 superblock | ||
2009 | * | ||
2010 | * One of these daemons runs, finding candidates to add to sd_reclaim_list. | ||
2011 | * See gfs2_glockd() | ||
2012 | */ | ||
2013 | |||
2014 | static int gfs2_scand(void *data) | ||
2015 | { | ||
2016 | unsigned x; | ||
2017 | unsigned delay; | ||
2018 | |||
2019 | while (!kthread_should_stop()) { | ||
2020 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) | ||
2021 | examine_bucket(scan_glock, NULL, x); | ||
2022 | if (freezing(current)) | ||
2023 | refrigerator(); | ||
2024 | delay = scand_secs; | ||
2025 | if (delay < 1) | ||
2026 | delay = 1; | ||
2027 | schedule_timeout_interruptible(delay * HZ); | ||
2028 | } | ||
2029 | |||
2030 | return 0; | ||
2031 | } | ||
2032 | |||
2033 | |||
2034 | |||
1966 | int __init gfs2_glock_init(void) | 2035 | int __init gfs2_glock_init(void) |
1967 | { | 2036 | { |
1968 | unsigned i; | 2037 | unsigned i; |
@@ -1974,52 +2043,69 @@ int __init gfs2_glock_init(void) | |||
1974 | rwlock_init(&gl_hash_locks[i]); | 2043 | rwlock_init(&gl_hash_locks[i]); |
1975 | } | 2044 | } |
1976 | #endif | 2045 | #endif |
2046 | |||
2047 | scand_process = kthread_run(gfs2_scand, NULL, "gfs2_scand"); | ||
2048 | if (IS_ERR(scand_process)) | ||
2049 | return PTR_ERR(scand_process); | ||
2050 | |||
2051 | glock_workqueue = create_workqueue("glock_workqueue"); | ||
2052 | if (IS_ERR(glock_workqueue)) { | ||
2053 | kthread_stop(scand_process); | ||
2054 | return PTR_ERR(glock_workqueue); | ||
2055 | } | ||
2056 | |||
1977 | return 0; | 2057 | return 0; |
1978 | } | 2058 | } |
1979 | 2059 | ||
2060 | void gfs2_glock_exit(void) | ||
2061 | { | ||
2062 | destroy_workqueue(glock_workqueue); | ||
2063 | kthread_stop(scand_process); | ||
2064 | } | ||
2065 | |||
2066 | module_param(scand_secs, uint, S_IRUGO|S_IWUSR); | ||
2067 | MODULE_PARM_DESC(scand_secs, "The number of seconds between scand runs"); | ||
2068 | |||
1980 | static int gfs2_glock_iter_next(struct glock_iter *gi) | 2069 | static int gfs2_glock_iter_next(struct glock_iter *gi) |
1981 | { | 2070 | { |
2071 | struct gfs2_glock *gl; | ||
2072 | |||
2073 | restart: | ||
1982 | read_lock(gl_lock_addr(gi->hash)); | 2074 | read_lock(gl_lock_addr(gi->hash)); |
1983 | while (1) { | 2075 | gl = gi->gl; |
1984 | if (!gi->hb_list) { /* If we don't have a hash bucket yet */ | 2076 | if (gl) { |
1985 | gi->hb_list = &gl_hash_table[gi->hash].hb_list; | 2077 | gi->gl = hlist_entry(gl->gl_list.next, |
1986 | if (hlist_empty(gi->hb_list)) { | 2078 | struct gfs2_glock, gl_list); |
1987 | read_unlock(gl_lock_addr(gi->hash)); | ||
1988 | gi->hash++; | ||
1989 | read_lock(gl_lock_addr(gi->hash)); | ||
1990 | gi->hb_list = NULL; | ||
1991 | if (gi->hash >= GFS2_GL_HASH_SIZE) { | ||
1992 | read_unlock(gl_lock_addr(gi->hash)); | ||
1993 | return 1; | ||
1994 | } | ||
1995 | else | ||
1996 | continue; | ||
1997 | } | ||
1998 | if (!hlist_empty(gi->hb_list)) { | ||
1999 | gi->gl = list_entry(gi->hb_list->first, | ||
2000 | struct gfs2_glock, | ||
2001 | gl_list); | ||
2002 | } | ||
2003 | } else { | ||
2004 | if (gi->gl->gl_list.next == NULL) { | ||
2005 | read_unlock(gl_lock_addr(gi->hash)); | ||
2006 | gi->hash++; | ||
2007 | read_lock(gl_lock_addr(gi->hash)); | ||
2008 | gi->hb_list = NULL; | ||
2009 | continue; | ||
2010 | } | ||
2011 | gi->gl = list_entry(gi->gl->gl_list.next, | ||
2012 | struct gfs2_glock, gl_list); | ||
2013 | } | ||
2014 | if (gi->gl) | 2079 | if (gi->gl) |
2015 | break; | 2080 | gfs2_glock_hold(gi->gl); |
2016 | } | 2081 | } |
2017 | read_unlock(gl_lock_addr(gi->hash)); | 2082 | read_unlock(gl_lock_addr(gi->hash)); |
2083 | if (gl) | ||
2084 | gfs2_glock_put(gl); | ||
2085 | if (gl && gi->gl == NULL) | ||
2086 | gi->hash++; | ||
2087 | while(gi->gl == NULL) { | ||
2088 | if (gi->hash >= GFS2_GL_HASH_SIZE) | ||
2089 | return 1; | ||
2090 | read_lock(gl_lock_addr(gi->hash)); | ||
2091 | gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first, | ||
2092 | struct gfs2_glock, gl_list); | ||
2093 | if (gi->gl) | ||
2094 | gfs2_glock_hold(gi->gl); | ||
2095 | read_unlock(gl_lock_addr(gi->hash)); | ||
2096 | gi->hash++; | ||
2097 | } | ||
2098 | |||
2099 | if (gi->sdp != gi->gl->gl_sbd) | ||
2100 | goto restart; | ||
2101 | |||
2018 | return 0; | 2102 | return 0; |
2019 | } | 2103 | } |
2020 | 2104 | ||
2021 | static void gfs2_glock_iter_free(struct glock_iter *gi) | 2105 | static void gfs2_glock_iter_free(struct glock_iter *gi) |
2022 | { | 2106 | { |
2107 | if (gi->gl) | ||
2108 | gfs2_glock_put(gi->gl); | ||
2023 | kfree(gi); | 2109 | kfree(gi); |
2024 | } | 2110 | } |
2025 | 2111 | ||
@@ -2033,9 +2119,8 @@ static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp) | |||
2033 | 2119 | ||
2034 | gi->sdp = sdp; | 2120 | gi->sdp = sdp; |
2035 | gi->hash = 0; | 2121 | gi->hash = 0; |
2036 | gi->gl = NULL; | ||
2037 | gi->hb_list = NULL; | ||
2038 | gi->seq = NULL; | 2122 | gi->seq = NULL; |
2123 | gi->gl = NULL; | ||
2039 | memset(gi->string, 0, sizeof(gi->string)); | 2124 | memset(gi->string, 0, sizeof(gi->string)); |
2040 | 2125 | ||
2041 | if (gfs2_glock_iter_next(gi)) { | 2126 | if (gfs2_glock_iter_next(gi)) { |
@@ -2055,7 +2140,7 @@ static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos) | |||
2055 | if (!gi) | 2140 | if (!gi) |
2056 | return NULL; | 2141 | return NULL; |
2057 | 2142 | ||
2058 | while (n--) { | 2143 | while(n--) { |
2059 | if (gfs2_glock_iter_next(gi)) { | 2144 | if (gfs2_glock_iter_next(gi)) { |
2060 | gfs2_glock_iter_free(gi); | 2145 | gfs2_glock_iter_free(gi); |
2061 | return NULL; | 2146 | return NULL; |
@@ -2082,7 +2167,9 @@ static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr, | |||
2082 | 2167 | ||
2083 | static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) | 2168 | static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) |
2084 | { | 2169 | { |
2085 | /* nothing for now */ | 2170 | struct glock_iter *gi = iter_ptr; |
2171 | if (gi) | ||
2172 | gfs2_glock_iter_free(gi); | ||
2086 | } | 2173 | } |
2087 | 2174 | ||
2088 | static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) | 2175 | static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) |
@@ -2095,7 +2182,7 @@ static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) | |||
2095 | return 0; | 2182 | return 0; |
2096 | } | 2183 | } |
2097 | 2184 | ||
2098 | static struct seq_operations gfs2_glock_seq_ops = { | 2185 | static const struct seq_operations gfs2_glock_seq_ops = { |
2099 | .start = gfs2_glock_seq_start, | 2186 | .start = gfs2_glock_seq_start, |
2100 | .next = gfs2_glock_seq_next, | 2187 | .next = gfs2_glock_seq_next, |
2101 | .stop = gfs2_glock_seq_stop, | 2188 | .stop = gfs2_glock_seq_stop, |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 7721ca3fff9e..b16f604eea9f 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define GL_SKIP 0x00000100 | 26 | #define GL_SKIP 0x00000100 |
27 | #define GL_ATIME 0x00000200 | 27 | #define GL_ATIME 0x00000200 |
28 | #define GL_NOCACHE 0x00000400 | 28 | #define GL_NOCACHE 0x00000400 |
29 | #define GL_FLOCK 0x00000800 | ||
29 | #define GL_NOCANCEL 0x00001000 | 30 | #define GL_NOCANCEL 0x00001000 |
30 | 31 | ||
31 | #define GLR_TRYFAILED 13 | 32 | #define GLR_TRYFAILED 13 |
@@ -132,11 +133,11 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data); | |||
132 | 133 | ||
133 | void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl); | 134 | void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl); |
134 | void gfs2_reclaim_glock(struct gfs2_sbd *sdp); | 135 | void gfs2_reclaim_glock(struct gfs2_sbd *sdp); |
135 | |||
136 | void gfs2_scand_internal(struct gfs2_sbd *sdp); | ||
137 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); | 136 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); |
138 | 137 | ||
139 | int __init gfs2_glock_init(void); | 138 | int __init gfs2_glock_init(void); |
139 | void gfs2_glock_exit(void); | ||
140 | |||
140 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp); | 141 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp); |
141 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp); | 142 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp); |
142 | int gfs2_register_debugfs(void); | 143 | int gfs2_register_debugfs(void); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 777ca46010e8..4670dcb2a877 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -41,7 +41,6 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
41 | struct list_head *head = &gl->gl_ail_list; | 41 | struct list_head *head = &gl->gl_ail_list; |
42 | struct gfs2_bufdata *bd; | 42 | struct gfs2_bufdata *bd; |
43 | struct buffer_head *bh; | 43 | struct buffer_head *bh; |
44 | u64 blkno; | ||
45 | int error; | 44 | int error; |
46 | 45 | ||
47 | blocks = atomic_read(&gl->gl_ail_count); | 46 | blocks = atomic_read(&gl->gl_ail_count); |
@@ -57,19 +56,12 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
57 | bd = list_entry(head->next, struct gfs2_bufdata, | 56 | bd = list_entry(head->next, struct gfs2_bufdata, |
58 | bd_ail_gl_list); | 57 | bd_ail_gl_list); |
59 | bh = bd->bd_bh; | 58 | bh = bd->bd_bh; |
60 | blkno = bh->b_blocknr; | 59 | gfs2_remove_from_ail(NULL, bd); |
60 | bd->bd_bh = NULL; | ||
61 | bh->b_private = NULL; | ||
62 | bd->bd_blkno = bh->b_blocknr; | ||
61 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); | 63 | gfs2_assert_withdraw(sdp, !buffer_busy(bh)); |
62 | 64 | gfs2_trans_add_revoke(sdp, bd); | |
63 | bd->bd_ail = NULL; | ||
64 | list_del(&bd->bd_ail_st_list); | ||
65 | list_del(&bd->bd_ail_gl_list); | ||
66 | atomic_dec(&gl->gl_ail_count); | ||
67 | brelse(bh); | ||
68 | gfs2_log_unlock(sdp); | ||
69 | |||
70 | gfs2_trans_add_revoke(sdp, blkno); | ||
71 | |||
72 | gfs2_log_lock(sdp); | ||
73 | } | 65 | } |
74 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); | 66 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); |
75 | gfs2_log_unlock(sdp); | 67 | gfs2_log_unlock(sdp); |
@@ -156,9 +148,11 @@ static void inode_go_sync(struct gfs2_glock *gl) | |||
156 | ip = NULL; | 148 | ip = NULL; |
157 | 149 | ||
158 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { | 150 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { |
159 | if (ip) | 151 | if (ip && !gfs2_is_jdata(ip)) |
160 | filemap_fdatawrite(ip->i_inode.i_mapping); | 152 | filemap_fdatawrite(ip->i_inode.i_mapping); |
161 | gfs2_log_flush(gl->gl_sbd, gl); | 153 | gfs2_log_flush(gl->gl_sbd, gl); |
154 | if (ip && gfs2_is_jdata(ip)) | ||
155 | filemap_fdatawrite(ip->i_inode.i_mapping); | ||
162 | gfs2_meta_sync(gl); | 156 | gfs2_meta_sync(gl); |
163 | if (ip) { | 157 | if (ip) { |
164 | struct address_space *mapping = ip->i_inode.i_mapping; | 158 | struct address_space *mapping = ip->i_inode.i_mapping; |
@@ -452,6 +446,7 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
452 | .go_lock = inode_go_lock, | 446 | .go_lock = inode_go_lock, |
453 | .go_unlock = inode_go_unlock, | 447 | .go_unlock = inode_go_unlock, |
454 | .go_type = LM_TYPE_INODE, | 448 | .go_type = LM_TYPE_INODE, |
449 | .go_min_hold_time = HZ / 10, | ||
455 | }; | 450 | }; |
456 | 451 | ||
457 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 452 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
@@ -462,6 +457,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { | |||
462 | .go_lock = rgrp_go_lock, | 457 | .go_lock = rgrp_go_lock, |
463 | .go_unlock = rgrp_go_unlock, | 458 | .go_unlock = rgrp_go_unlock, |
464 | .go_type = LM_TYPE_RGRP, | 459 | .go_type = LM_TYPE_RGRP, |
460 | .go_min_hold_time = HZ / 10, | ||
465 | }; | 461 | }; |
466 | 462 | ||
467 | const struct gfs2_glock_operations gfs2_trans_glops = { | 463 | const struct gfs2_glock_operations gfs2_trans_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 170ba93829c0..eaddfb5a8e6f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #define __INCORE_DOT_H__ | 11 | #define __INCORE_DOT_H__ |
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/workqueue.h> | ||
14 | 15 | ||
15 | #define DIO_WAIT 0x00000010 | 16 | #define DIO_WAIT 0x00000010 |
16 | #define DIO_METADATA 0x00000020 | 17 | #define DIO_METADATA 0x00000020 |
@@ -113,7 +114,13 @@ struct gfs2_bufdata { | |||
113 | struct buffer_head *bd_bh; | 114 | struct buffer_head *bd_bh; |
114 | struct gfs2_glock *bd_gl; | 115 | struct gfs2_glock *bd_gl; |
115 | 116 | ||
116 | struct list_head bd_list_tr; | 117 | union { |
118 | struct list_head list_tr; | ||
119 | u64 blkno; | ||
120 | } u; | ||
121 | #define bd_list_tr u.list_tr | ||
122 | #define bd_blkno u.blkno | ||
123 | |||
117 | struct gfs2_log_element bd_le; | 124 | struct gfs2_log_element bd_le; |
118 | 125 | ||
119 | struct gfs2_ail *bd_ail; | 126 | struct gfs2_ail *bd_ail; |
@@ -130,6 +137,7 @@ struct gfs2_glock_operations { | |||
130 | int (*go_lock) (struct gfs2_holder *gh); | 137 | int (*go_lock) (struct gfs2_holder *gh); |
131 | void (*go_unlock) (struct gfs2_holder *gh); | 138 | void (*go_unlock) (struct gfs2_holder *gh); |
132 | const int go_type; | 139 | const int go_type; |
140 | const unsigned long go_min_hold_time; | ||
133 | }; | 141 | }; |
134 | 142 | ||
135 | enum { | 143 | enum { |
@@ -161,6 +169,7 @@ enum { | |||
161 | GLF_LOCK = 1, | 169 | GLF_LOCK = 1, |
162 | GLF_STICKY = 2, | 170 | GLF_STICKY = 2, |
163 | GLF_DEMOTE = 3, | 171 | GLF_DEMOTE = 3, |
172 | GLF_PENDING_DEMOTE = 4, | ||
164 | GLF_DIRTY = 5, | 173 | GLF_DIRTY = 5, |
165 | }; | 174 | }; |
166 | 175 | ||
@@ -193,6 +202,7 @@ struct gfs2_glock { | |||
193 | 202 | ||
194 | u64 gl_vn; | 203 | u64 gl_vn; |
195 | unsigned long gl_stamp; | 204 | unsigned long gl_stamp; |
205 | unsigned long gl_tchange; | ||
196 | void *gl_object; | 206 | void *gl_object; |
197 | 207 | ||
198 | struct list_head gl_reclaim; | 208 | struct list_head gl_reclaim; |
@@ -203,6 +213,7 @@ struct gfs2_glock { | |||
203 | struct gfs2_log_element gl_le; | 213 | struct gfs2_log_element gl_le; |
204 | struct list_head gl_ail_list; | 214 | struct list_head gl_ail_list; |
205 | atomic_t gl_ail_count; | 215 | atomic_t gl_ail_count; |
216 | struct delayed_work gl_work; | ||
206 | }; | 217 | }; |
207 | 218 | ||
208 | struct gfs2_alloc { | 219 | struct gfs2_alloc { |
@@ -293,11 +304,6 @@ struct gfs2_file { | |||
293 | struct gfs2_holder f_fl_gh; | 304 | struct gfs2_holder f_fl_gh; |
294 | }; | 305 | }; |
295 | 306 | ||
296 | struct gfs2_revoke { | ||
297 | struct gfs2_log_element rv_le; | ||
298 | u64 rv_blkno; | ||
299 | }; | ||
300 | |||
301 | struct gfs2_revoke_replay { | 307 | struct gfs2_revoke_replay { |
302 | struct list_head rr_list; | 308 | struct list_head rr_list; |
303 | u64 rr_blkno; | 309 | u64 rr_blkno; |
@@ -335,12 +341,6 @@ struct gfs2_quota_data { | |||
335 | unsigned long qd_last_touched; | 341 | unsigned long qd_last_touched; |
336 | }; | 342 | }; |
337 | 343 | ||
338 | struct gfs2_log_buf { | ||
339 | struct list_head lb_list; | ||
340 | struct buffer_head *lb_bh; | ||
341 | struct buffer_head *lb_real; | ||
342 | }; | ||
343 | |||
344 | struct gfs2_trans { | 344 | struct gfs2_trans { |
345 | unsigned long tr_ip; | 345 | unsigned long tr_ip; |
346 | 346 | ||
@@ -429,7 +429,6 @@ struct gfs2_tune { | |||
429 | unsigned int gt_log_flush_secs; | 429 | unsigned int gt_log_flush_secs; |
430 | unsigned int gt_jindex_refresh_secs; /* Check for new journal index */ | 430 | unsigned int gt_jindex_refresh_secs; /* Check for new journal index */ |
431 | 431 | ||
432 | unsigned int gt_scand_secs; | ||
433 | unsigned int gt_recoverd_secs; | 432 | unsigned int gt_recoverd_secs; |
434 | unsigned int gt_logd_secs; | 433 | unsigned int gt_logd_secs; |
435 | unsigned int gt_quotad_secs; | 434 | unsigned int gt_quotad_secs; |
@@ -574,7 +573,6 @@ struct gfs2_sbd { | |||
574 | 573 | ||
575 | /* Daemon stuff */ | 574 | /* Daemon stuff */ |
576 | 575 | ||
577 | struct task_struct *sd_scand_process; | ||
578 | struct task_struct *sd_recoverd_process; | 576 | struct task_struct *sd_recoverd_process; |
579 | struct task_struct *sd_logd_process; | 577 | struct task_struct *sd_logd_process; |
580 | struct task_struct *sd_quotad_process; | 578 | struct task_struct *sd_quotad_process; |
@@ -609,13 +607,13 @@ struct gfs2_sbd { | |||
609 | unsigned int sd_log_num_revoke; | 607 | unsigned int sd_log_num_revoke; |
610 | unsigned int sd_log_num_rg; | 608 | unsigned int sd_log_num_rg; |
611 | unsigned int sd_log_num_databuf; | 609 | unsigned int sd_log_num_databuf; |
612 | unsigned int sd_log_num_jdata; | ||
613 | 610 | ||
614 | struct list_head sd_log_le_gl; | 611 | struct list_head sd_log_le_gl; |
615 | struct list_head sd_log_le_buf; | 612 | struct list_head sd_log_le_buf; |
616 | struct list_head sd_log_le_revoke; | 613 | struct list_head sd_log_le_revoke; |
617 | struct list_head sd_log_le_rg; | 614 | struct list_head sd_log_le_rg; |
618 | struct list_head sd_log_le_databuf; | 615 | struct list_head sd_log_le_databuf; |
616 | struct list_head sd_log_le_ordered; | ||
619 | 617 | ||
620 | unsigned int sd_log_blks_free; | 618 | unsigned int sd_log_blks_free; |
621 | struct mutex sd_log_reserve_mutex; | 619 | struct mutex sd_log_reserve_mutex; |
@@ -627,7 +625,8 @@ struct gfs2_sbd { | |||
627 | 625 | ||
628 | unsigned long sd_log_flush_time; | 626 | unsigned long sd_log_flush_time; |
629 | struct rw_semaphore sd_log_flush_lock; | 627 | struct rw_semaphore sd_log_flush_lock; |
630 | struct list_head sd_log_flush_list; | 628 | atomic_t sd_log_in_flight; |
629 | wait_queue_head_t sd_log_flush_wait; | ||
631 | 630 | ||
632 | unsigned int sd_log_flush_head; | 631 | unsigned int sd_log_flush_head; |
633 | u64 sd_log_flush_wrapped; | 632 | u64 sd_log_flush_wrapped; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 34f7bcdea1e9..5f6dc32946cd 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -77,6 +77,49 @@ static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | |||
77 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); | 77 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); |
78 | } | 78 | } |
79 | 79 | ||
80 | struct gfs2_skip_data { | ||
81 | u64 no_addr; | ||
82 | int skipped; | ||
83 | }; | ||
84 | |||
85 | static int iget_skip_test(struct inode *inode, void *opaque) | ||
86 | { | ||
87 | struct gfs2_inode *ip = GFS2_I(inode); | ||
88 | struct gfs2_skip_data *data = opaque; | ||
89 | |||
90 | if (ip->i_no_addr == data->no_addr && inode->i_private != NULL){ | ||
91 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ | ||
92 | data->skipped = 1; | ||
93 | return 0; | ||
94 | } | ||
95 | return 1; | ||
96 | } | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int iget_skip_set(struct inode *inode, void *opaque) | ||
101 | { | ||
102 | struct gfs2_inode *ip = GFS2_I(inode); | ||
103 | struct gfs2_skip_data *data = opaque; | ||
104 | |||
105 | if (data->skipped) | ||
106 | return 1; | ||
107 | inode->i_ino = (unsigned long)(data->no_addr); | ||
108 | ip->i_no_addr = data->no_addr; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static struct inode *gfs2_iget_skip(struct super_block *sb, | ||
113 | u64 no_addr) | ||
114 | { | ||
115 | struct gfs2_skip_data data; | ||
116 | unsigned long hash = (unsigned long)no_addr; | ||
117 | |||
118 | data.no_addr = no_addr; | ||
119 | data.skipped = 0; | ||
120 | return iget5_locked(sb, hash, iget_skip_test, iget_skip_set, &data); | ||
121 | } | ||
122 | |||
80 | /** | 123 | /** |
81 | * GFS2 lookup code fills in vfs inode contents based on info obtained | 124 | * GFS2 lookup code fills in vfs inode contents based on info obtained |
82 | * from directory entry inside gfs2_inode_lookup(). This has caused issues | 125 | * from directory entry inside gfs2_inode_lookup(). This has caused issues |
@@ -112,6 +155,7 @@ void gfs2_set_iop(struct inode *inode) | |||
112 | * @sb: The super block | 155 | * @sb: The super block |
113 | * @no_addr: The inode number | 156 | * @no_addr: The inode number |
114 | * @type: The type of the inode | 157 | * @type: The type of the inode |
158 | * @skip_freeing: set this not return an inode if it is currently being freed. | ||
115 | * | 159 | * |
116 | * Returns: A VFS inode, or an error | 160 | * Returns: A VFS inode, or an error |
117 | */ | 161 | */ |
@@ -119,13 +163,19 @@ void gfs2_set_iop(struct inode *inode) | |||
119 | struct inode *gfs2_inode_lookup(struct super_block *sb, | 163 | struct inode *gfs2_inode_lookup(struct super_block *sb, |
120 | unsigned int type, | 164 | unsigned int type, |
121 | u64 no_addr, | 165 | u64 no_addr, |
122 | u64 no_formal_ino) | 166 | u64 no_formal_ino, int skip_freeing) |
123 | { | 167 | { |
124 | struct inode *inode = gfs2_iget(sb, no_addr); | 168 | struct inode *inode; |
125 | struct gfs2_inode *ip = GFS2_I(inode); | 169 | struct gfs2_inode *ip; |
126 | struct gfs2_glock *io_gl; | 170 | struct gfs2_glock *io_gl; |
127 | int error; | 171 | int error; |
128 | 172 | ||
173 | if (skip_freeing) | ||
174 | inode = gfs2_iget_skip(sb, no_addr); | ||
175 | else | ||
176 | inode = gfs2_iget(sb, no_addr); | ||
177 | ip = GFS2_I(inode); | ||
178 | |||
129 | if (!inode) | 179 | if (!inode) |
130 | return ERR_PTR(-ENOBUFS); | 180 | return ERR_PTR(-ENOBUFS); |
131 | 181 | ||
@@ -244,6 +294,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
244 | return 0; | 294 | return 0; |
245 | } | 295 | } |
246 | 296 | ||
297 | static void gfs2_inode_bh(struct gfs2_inode *ip, struct buffer_head *bh) | ||
298 | { | ||
299 | ip->i_cache[0] = bh; | ||
300 | } | ||
301 | |||
247 | /** | 302 | /** |
248 | * gfs2_inode_refresh - Refresh the incore copy of the dinode | 303 | * gfs2_inode_refresh - Refresh the incore copy of the dinode |
249 | * @ip: The GFS2 inode | 304 | * @ip: The GFS2 inode |
@@ -688,7 +743,7 @@ out: | |||
688 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 743 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, |
689 | const struct gfs2_inum_host *inum, unsigned int mode, | 744 | const struct gfs2_inum_host *inum, unsigned int mode, |
690 | unsigned int uid, unsigned int gid, | 745 | unsigned int uid, unsigned int gid, |
691 | const u64 *generation, dev_t dev) | 746 | const u64 *generation, dev_t dev, struct buffer_head **bhp) |
692 | { | 747 | { |
693 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 748 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
694 | struct gfs2_dinode *di; | 749 | struct gfs2_dinode *di; |
@@ -743,13 +798,15 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
743 | di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); | 798 | di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); |
744 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); | 799 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); |
745 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); | 800 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); |
801 | |||
802 | set_buffer_uptodate(dibh); | ||
746 | 803 | ||
747 | brelse(dibh); | 804 | *bhp = dibh; |
748 | } | 805 | } |
749 | 806 | ||
750 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 807 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, |
751 | unsigned int mode, const struct gfs2_inum_host *inum, | 808 | unsigned int mode, const struct gfs2_inum_host *inum, |
752 | const u64 *generation, dev_t dev) | 809 | const u64 *generation, dev_t dev, struct buffer_head **bhp) |
753 | { | 810 | { |
754 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 811 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
755 | unsigned int uid, gid; | 812 | unsigned int uid, gid; |
@@ -770,7 +827,7 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
770 | if (error) | 827 | if (error) |
771 | goto out_quota; | 828 | goto out_quota; |
772 | 829 | ||
773 | init_dinode(dip, gl, inum, mode, uid, gid, generation, dev); | 830 | init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, bhp); |
774 | gfs2_quota_change(dip, +1, uid, gid); | 831 | gfs2_quota_change(dip, +1, uid, gid); |
775 | gfs2_trans_end(sdp); | 832 | gfs2_trans_end(sdp); |
776 | 833 | ||
@@ -909,6 +966,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
909 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; | 966 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; |
910 | int error; | 967 | int error; |
911 | u64 generation; | 968 | u64 generation; |
969 | struct buffer_head *bh=NULL; | ||
912 | 970 | ||
913 | if (!name->len || name->len > GFS2_FNAMESIZE) | 971 | if (!name->len || name->len > GFS2_FNAMESIZE) |
914 | return ERR_PTR(-ENAMETOOLONG); | 972 | return ERR_PTR(-ENAMETOOLONG); |
@@ -935,16 +993,18 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
935 | if (error) | 993 | if (error) |
936 | goto fail_gunlock; | 994 | goto fail_gunlock; |
937 | 995 | ||
938 | error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev); | 996 | error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, &bh); |
939 | if (error) | 997 | if (error) |
940 | goto fail_gunlock2; | 998 | goto fail_gunlock2; |
941 | 999 | ||
942 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), | 1000 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), |
943 | inum.no_addr, | 1001 | inum.no_addr, |
944 | inum.no_formal_ino); | 1002 | inum.no_formal_ino, 0); |
945 | if (IS_ERR(inode)) | 1003 | if (IS_ERR(inode)) |
946 | goto fail_gunlock2; | 1004 | goto fail_gunlock2; |
947 | 1005 | ||
1006 | gfs2_inode_bh(GFS2_I(inode), bh); | ||
1007 | |||
948 | error = gfs2_inode_refresh(GFS2_I(inode)); | 1008 | error = gfs2_inode_refresh(GFS2_I(inode)); |
949 | if (error) | 1009 | if (error) |
950 | goto fail_gunlock2; | 1010 | goto fail_gunlock2; |
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 4517ac82c01c..351ac87ab384 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -49,7 +49,8 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip, | |||
49 | void gfs2_inode_attr_in(struct gfs2_inode *ip); | 49 | void gfs2_inode_attr_in(struct gfs2_inode *ip); |
50 | void gfs2_set_iop(struct inode *inode); | 50 | void gfs2_set_iop(struct inode *inode); |
51 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, | 51 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, |
52 | u64 no_addr, u64 no_formal_ino); | 52 | u64 no_addr, u64 no_formal_ino, |
53 | int skip_freeing); | ||
53 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); | 54 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); |
54 | 55 | ||
55 | int gfs2_inode_refresh(struct gfs2_inode *ip); | 56 | int gfs2_inode_refresh(struct gfs2_inode *ip); |
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h index 24d70f73b651..9e8265d28377 100644 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ b/fs/gfs2/locking/dlm/lock_dlm.h | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | 16 | #include <linux/types.h> |
18 | #include <linux/string.h> | 17 | #include <linux/string.h> |
19 | #include <linux/list.h> | 18 | #include <linux/list.h> |
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c index fba1f1d87e4f..1f7b038530b4 100644 --- a/fs/gfs2/locking/dlm/plock.c +++ b/fs/gfs2/locking/dlm/plock.c | |||
@@ -346,15 +346,16 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count, | |||
346 | 346 | ||
347 | static unsigned int dev_poll(struct file *file, poll_table *wait) | 347 | static unsigned int dev_poll(struct file *file, poll_table *wait) |
348 | { | 348 | { |
349 | unsigned int mask = 0; | ||
350 | |||
349 | poll_wait(file, &send_wq, wait); | 351 | poll_wait(file, &send_wq, wait); |
350 | 352 | ||
351 | spin_lock(&ops_lock); | 353 | spin_lock(&ops_lock); |
352 | if (!list_empty(&send_list)) { | 354 | if (!list_empty(&send_list)) |
353 | spin_unlock(&ops_lock); | 355 | mask = POLLIN | POLLRDNORM; |
354 | return POLLIN | POLLRDNORM; | ||
355 | } | ||
356 | spin_unlock(&ops_lock); | 356 | spin_unlock(&ops_lock); |
357 | return 0; | 357 | |
358 | return mask; | ||
358 | } | 359 | } |
359 | 360 | ||
360 | static const struct file_operations dev_fops = { | 361 | static const struct file_operations dev_fops = { |
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c index 1aca51e45092..bd938f06481d 100644 --- a/fs/gfs2/locking/dlm/thread.c +++ b/fs/gfs2/locking/dlm/thread.c | |||
@@ -268,20 +268,16 @@ static inline int check_drop(struct gdlm_ls *ls) | |||
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | static int gdlm_thread(void *data) | 271 | static int gdlm_thread(void *data, int blist) |
272 | { | 272 | { |
273 | struct gdlm_ls *ls = (struct gdlm_ls *) data; | 273 | struct gdlm_ls *ls = (struct gdlm_ls *) data; |
274 | struct gdlm_lock *lp = NULL; | 274 | struct gdlm_lock *lp = NULL; |
275 | int blist = 0; | ||
276 | uint8_t complete, blocking, submit, drop; | 275 | uint8_t complete, blocking, submit, drop; |
277 | DECLARE_WAITQUEUE(wait, current); | 276 | DECLARE_WAITQUEUE(wait, current); |
278 | 277 | ||
279 | /* Only thread1 is allowed to do blocking callbacks since gfs | 278 | /* Only thread1 is allowed to do blocking callbacks since gfs |
280 | may wait for a completion callback within a blocking cb. */ | 279 | may wait for a completion callback within a blocking cb. */ |
281 | 280 | ||
282 | if (current == ls->thread1) | ||
283 | blist = 1; | ||
284 | |||
285 | while (!kthread_should_stop()) { | 281 | while (!kthread_should_stop()) { |
286 | set_current_state(TASK_INTERRUPTIBLE); | 282 | set_current_state(TASK_INTERRUPTIBLE); |
287 | add_wait_queue(&ls->thread_wait, &wait); | 283 | add_wait_queue(&ls->thread_wait, &wait); |
@@ -333,12 +329,22 @@ static int gdlm_thread(void *data) | |||
333 | return 0; | 329 | return 0; |
334 | } | 330 | } |
335 | 331 | ||
332 | static int gdlm_thread1(void *data) | ||
333 | { | ||
334 | return gdlm_thread(data, 1); | ||
335 | } | ||
336 | |||
337 | static int gdlm_thread2(void *data) | ||
338 | { | ||
339 | return gdlm_thread(data, 0); | ||
340 | } | ||
341 | |||
336 | int gdlm_init_threads(struct gdlm_ls *ls) | 342 | int gdlm_init_threads(struct gdlm_ls *ls) |
337 | { | 343 | { |
338 | struct task_struct *p; | 344 | struct task_struct *p; |
339 | int error; | 345 | int error; |
340 | 346 | ||
341 | p = kthread_run(gdlm_thread, ls, "lock_dlm1"); | 347 | p = kthread_run(gdlm_thread1, ls, "lock_dlm1"); |
342 | error = IS_ERR(p); | 348 | error = IS_ERR(p); |
343 | if (error) { | 349 | if (error) { |
344 | log_error("can't start lock_dlm1 thread %d", error); | 350 | log_error("can't start lock_dlm1 thread %d", error); |
@@ -346,7 +352,7 @@ int gdlm_init_threads(struct gdlm_ls *ls) | |||
346 | } | 352 | } |
347 | ls->thread1 = p; | 353 | ls->thread1 = p; |
348 | 354 | ||
349 | p = kthread_run(gdlm_thread, ls, "lock_dlm2"); | 355 | p = kthread_run(gdlm_thread2, ls, "lock_dlm2"); |
350 | error = IS_ERR(p); | 356 | error = IS_ERR(p); |
351 | if (error) { | 357 | if (error) { |
352 | log_error("can't start lock_dlm2 thread %d", error); | 358 | log_error("can't start lock_dlm2 thread %d", error); |
diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c index 0d149c8c493a..d3b8ce6fbbe3 100644 --- a/fs/gfs2/locking/nolock/main.c +++ b/fs/gfs2/locking/nolock/main.c | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | 12 | #include <linux/init.h> |
14 | #include <linux/types.h> | 13 | #include <linux/types.h> |
15 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index f49a12e24086..7df702473252 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -60,6 +60,26 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, | |||
60 | } | 60 | } |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * gfs2_remove_from_ail - Remove an entry from the ail lists, updating counters | ||
64 | * @mapping: The associated mapping (maybe NULL) | ||
65 | * @bd: The gfs2_bufdata to remove | ||
66 | * | ||
67 | * The log lock _must_ be held when calling this function | ||
68 | * | ||
69 | */ | ||
70 | |||
71 | void gfs2_remove_from_ail(struct address_space *mapping, struct gfs2_bufdata *bd) | ||
72 | { | ||
73 | bd->bd_ail = NULL; | ||
74 | list_del_init(&bd->bd_ail_st_list); | ||
75 | list_del_init(&bd->bd_ail_gl_list); | ||
76 | atomic_dec(&bd->bd_gl->gl_ail_count); | ||
77 | if (mapping) | ||
78 | gfs2_meta_cache_flush(GFS2_I(mapping->host)); | ||
79 | brelse(bd->bd_bh); | ||
80 | } | ||
81 | |||
82 | /** | ||
63 | * gfs2_ail1_start_one - Start I/O on a part of the AIL | 83 | * gfs2_ail1_start_one - Start I/O on a part of the AIL |
64 | * @sdp: the filesystem | 84 | * @sdp: the filesystem |
65 | * @tr: the part of the AIL | 85 | * @tr: the part of the AIL |
@@ -83,17 +103,9 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
83 | 103 | ||
84 | gfs2_assert(sdp, bd->bd_ail == ai); | 104 | gfs2_assert(sdp, bd->bd_ail == ai); |
85 | 105 | ||
86 | if (!bh){ | ||
87 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
88 | continue; | ||
89 | } | ||
90 | |||
91 | if (!buffer_busy(bh)) { | 106 | if (!buffer_busy(bh)) { |
92 | if (!buffer_uptodate(bh)) { | 107 | if (!buffer_uptodate(bh)) |
93 | gfs2_log_unlock(sdp); | ||
94 | gfs2_io_error_bh(sdp, bh); | 108 | gfs2_io_error_bh(sdp, bh); |
95 | gfs2_log_lock(sdp); | ||
96 | } | ||
97 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | 109 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); |
98 | continue; | 110 | continue; |
99 | } | 111 | } |
@@ -103,9 +115,16 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
103 | 115 | ||
104 | list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); | 116 | list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); |
105 | 117 | ||
118 | get_bh(bh); | ||
106 | gfs2_log_unlock(sdp); | 119 | gfs2_log_unlock(sdp); |
107 | wait_on_buffer(bh); | 120 | lock_buffer(bh); |
108 | ll_rw_block(WRITE, 1, &bh); | 121 | if (test_clear_buffer_dirty(bh)) { |
122 | bh->b_end_io = end_buffer_write_sync; | ||
123 | submit_bh(WRITE, bh); | ||
124 | } else { | ||
125 | unlock_buffer(bh); | ||
126 | brelse(bh); | ||
127 | } | ||
109 | gfs2_log_lock(sdp); | 128 | gfs2_log_lock(sdp); |
110 | 129 | ||
111 | retry = 1; | 130 | retry = 1; |
@@ -130,11 +149,6 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
130 | bd_ail_st_list) { | 149 | bd_ail_st_list) { |
131 | bh = bd->bd_bh; | 150 | bh = bd->bd_bh; |
132 | 151 | ||
133 | if (!bh){ | ||
134 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | gfs2_assert(sdp, bd->bd_ail == ai); | 152 | gfs2_assert(sdp, bd->bd_ail == ai); |
139 | 153 | ||
140 | if (buffer_busy(bh)) { | 154 | if (buffer_busy(bh)) { |
@@ -155,13 +169,14 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
155 | 169 | ||
156 | static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) | 170 | static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) |
157 | { | 171 | { |
158 | struct list_head *head = &sdp->sd_ail1_list; | 172 | struct list_head *head; |
159 | u64 sync_gen; | 173 | u64 sync_gen; |
160 | struct list_head *first; | 174 | struct list_head *first; |
161 | struct gfs2_ail *first_ai, *ai, *tmp; | 175 | struct gfs2_ail *first_ai, *ai, *tmp; |
162 | int done = 0; | 176 | int done = 0; |
163 | 177 | ||
164 | gfs2_log_lock(sdp); | 178 | gfs2_log_lock(sdp); |
179 | head = &sdp->sd_ail1_list; | ||
165 | if (list_empty(head)) { | 180 | if (list_empty(head)) { |
166 | gfs2_log_unlock(sdp); | 181 | gfs2_log_unlock(sdp); |
167 | return; | 182 | return; |
@@ -233,11 +248,7 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
233 | bd = list_entry(head->prev, struct gfs2_bufdata, | 248 | bd = list_entry(head->prev, struct gfs2_bufdata, |
234 | bd_ail_st_list); | 249 | bd_ail_st_list); |
235 | gfs2_assert(sdp, bd->bd_ail == ai); | 250 | gfs2_assert(sdp, bd->bd_ail == ai); |
236 | bd->bd_ail = NULL; | 251 | gfs2_remove_from_ail(bd->bd_bh->b_page->mapping, bd); |
237 | list_del(&bd->bd_ail_st_list); | ||
238 | list_del(&bd->bd_ail_gl_list); | ||
239 | atomic_dec(&bd->bd_gl->gl_ail_count); | ||
240 | brelse(bd->bd_bh); | ||
241 | } | 252 | } |
242 | } | 253 | } |
243 | 254 | ||
@@ -439,10 +450,10 @@ static unsigned int current_tail(struct gfs2_sbd *sdp) | |||
439 | return tail; | 450 | return tail; |
440 | } | 451 | } |
441 | 452 | ||
442 | static inline void log_incr_head(struct gfs2_sbd *sdp) | 453 | void gfs2_log_incr_head(struct gfs2_sbd *sdp) |
443 | { | 454 | { |
444 | if (sdp->sd_log_flush_head == sdp->sd_log_tail) | 455 | if (sdp->sd_log_flush_head == sdp->sd_log_tail) |
445 | gfs2_assert_withdraw(sdp, sdp->sd_log_flush_head == sdp->sd_log_head); | 456 | BUG_ON(sdp->sd_log_flush_head != sdp->sd_log_head); |
446 | 457 | ||
447 | if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) { | 458 | if (++sdp->sd_log_flush_head == sdp->sd_jdesc->jd_blocks) { |
448 | sdp->sd_log_flush_head = 0; | 459 | sdp->sd_log_flush_head = 0; |
@@ -451,6 +462,23 @@ static inline void log_incr_head(struct gfs2_sbd *sdp) | |||
451 | } | 462 | } |
452 | 463 | ||
453 | /** | 464 | /** |
465 | * gfs2_log_write_endio - End of I/O for a log buffer | ||
466 | * @bh: The buffer head | ||
467 | * @uptodate: I/O Status | ||
468 | * | ||
469 | */ | ||
470 | |||
471 | static void gfs2_log_write_endio(struct buffer_head *bh, int uptodate) | ||
472 | { | ||
473 | struct gfs2_sbd *sdp = bh->b_private; | ||
474 | bh->b_private = NULL; | ||
475 | |||
476 | end_buffer_write_sync(bh, uptodate); | ||
477 | if (atomic_dec_and_test(&sdp->sd_log_in_flight)) | ||
478 | wake_up(&sdp->sd_log_flush_wait); | ||
479 | } | ||
480 | |||
481 | /** | ||
454 | * gfs2_log_get_buf - Get and initialize a buffer to use for log control data | 482 | * gfs2_log_get_buf - Get and initialize a buffer to use for log control data |
455 | * @sdp: The GFS2 superblock | 483 | * @sdp: The GFS2 superblock |
456 | * | 484 | * |
@@ -460,25 +488,43 @@ static inline void log_incr_head(struct gfs2_sbd *sdp) | |||
460 | struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp) | 488 | struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp) |
461 | { | 489 | { |
462 | u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); | 490 | u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); |
463 | struct gfs2_log_buf *lb; | ||
464 | struct buffer_head *bh; | 491 | struct buffer_head *bh; |
465 | 492 | ||
466 | lb = kzalloc(sizeof(struct gfs2_log_buf), GFP_NOFS | __GFP_NOFAIL); | 493 | bh = sb_getblk(sdp->sd_vfs, blkno); |
467 | list_add(&lb->lb_list, &sdp->sd_log_flush_list); | ||
468 | |||
469 | bh = lb->lb_bh = sb_getblk(sdp->sd_vfs, blkno); | ||
470 | lock_buffer(bh); | 494 | lock_buffer(bh); |
471 | memset(bh->b_data, 0, bh->b_size); | 495 | memset(bh->b_data, 0, bh->b_size); |
472 | set_buffer_uptodate(bh); | 496 | set_buffer_uptodate(bh); |
473 | clear_buffer_dirty(bh); | 497 | clear_buffer_dirty(bh); |
474 | unlock_buffer(bh); | 498 | gfs2_log_incr_head(sdp); |
475 | 499 | atomic_inc(&sdp->sd_log_in_flight); | |
476 | log_incr_head(sdp); | 500 | bh->b_private = sdp; |
501 | bh->b_end_io = gfs2_log_write_endio; | ||
477 | 502 | ||
478 | return bh; | 503 | return bh; |
479 | } | 504 | } |
480 | 505 | ||
481 | /** | 506 | /** |
507 | * gfs2_fake_write_endio - | ||
508 | * @bh: The buffer head | ||
509 | * @uptodate: The I/O Status | ||
510 | * | ||
511 | */ | ||
512 | |||
513 | static void gfs2_fake_write_endio(struct buffer_head *bh, int uptodate) | ||
514 | { | ||
515 | struct buffer_head *real_bh = bh->b_private; | ||
516 | struct gfs2_bufdata *bd = real_bh->b_private; | ||
517 | struct gfs2_sbd *sdp = bd->bd_gl->gl_sbd; | ||
518 | |||
519 | end_buffer_write_sync(bh, uptodate); | ||
520 | free_buffer_head(bh); | ||
521 | unlock_buffer(real_bh); | ||
522 | brelse(real_bh); | ||
523 | if (atomic_dec_and_test(&sdp->sd_log_in_flight)) | ||
524 | wake_up(&sdp->sd_log_flush_wait); | ||
525 | } | ||
526 | |||
527 | /** | ||
482 | * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log | 528 | * gfs2_log_fake_buf - Build a fake buffer head to write metadata buffer to log |
483 | * @sdp: the filesystem | 529 | * @sdp: the filesystem |
484 | * @data: the data the buffer_head should point to | 530 | * @data: the data the buffer_head should point to |
@@ -490,22 +536,20 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | |||
490 | struct buffer_head *real) | 536 | struct buffer_head *real) |
491 | { | 537 | { |
492 | u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); | 538 | u64 blkno = log_bmap(sdp, sdp->sd_log_flush_head); |
493 | struct gfs2_log_buf *lb; | ||
494 | struct buffer_head *bh; | 539 | struct buffer_head *bh; |
495 | 540 | ||
496 | lb = kzalloc(sizeof(struct gfs2_log_buf), GFP_NOFS | __GFP_NOFAIL); | 541 | bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL); |
497 | list_add(&lb->lb_list, &sdp->sd_log_flush_list); | ||
498 | lb->lb_real = real; | ||
499 | |||
500 | bh = lb->lb_bh = alloc_buffer_head(GFP_NOFS | __GFP_NOFAIL); | ||
501 | atomic_set(&bh->b_count, 1); | 542 | atomic_set(&bh->b_count, 1); |
502 | bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate); | 543 | bh->b_state = (1 << BH_Mapped) | (1 << BH_Uptodate) | (1 << BH_Lock); |
503 | set_bh_page(bh, real->b_page, bh_offset(real)); | 544 | set_bh_page(bh, real->b_page, bh_offset(real)); |
504 | bh->b_blocknr = blkno; | 545 | bh->b_blocknr = blkno; |
505 | bh->b_size = sdp->sd_sb.sb_bsize; | 546 | bh->b_size = sdp->sd_sb.sb_bsize; |
506 | bh->b_bdev = sdp->sd_vfs->s_bdev; | 547 | bh->b_bdev = sdp->sd_vfs->s_bdev; |
548 | bh->b_private = real; | ||
549 | bh->b_end_io = gfs2_fake_write_endio; | ||
507 | 550 | ||
508 | log_incr_head(sdp); | 551 | gfs2_log_incr_head(sdp); |
552 | atomic_inc(&sdp->sd_log_in_flight); | ||
509 | 553 | ||
510 | return bh; | 554 | return bh; |
511 | } | 555 | } |
@@ -572,45 +616,75 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) | |||
572 | gfs2_assert_withdraw(sdp, !pull); | 616 | gfs2_assert_withdraw(sdp, !pull); |
573 | 617 | ||
574 | sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); | 618 | sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); |
575 | log_incr_head(sdp); | 619 | gfs2_log_incr_head(sdp); |
576 | } | 620 | } |
577 | 621 | ||
578 | static void log_flush_commit(struct gfs2_sbd *sdp) | 622 | static void log_flush_commit(struct gfs2_sbd *sdp) |
579 | { | 623 | { |
580 | struct list_head *head = &sdp->sd_log_flush_list; | 624 | DEFINE_WAIT(wait); |
581 | struct gfs2_log_buf *lb; | 625 | |
582 | struct buffer_head *bh; | 626 | if (atomic_read(&sdp->sd_log_in_flight)) { |
583 | int flushcount = 0; | 627 | do { |
628 | prepare_to_wait(&sdp->sd_log_flush_wait, &wait, | ||
629 | TASK_UNINTERRUPTIBLE); | ||
630 | if (atomic_read(&sdp->sd_log_in_flight)) | ||
631 | io_schedule(); | ||
632 | } while(atomic_read(&sdp->sd_log_in_flight)); | ||
633 | finish_wait(&sdp->sd_log_flush_wait, &wait); | ||
634 | } | ||
584 | 635 | ||
585 | while (!list_empty(head)) { | 636 | log_write_header(sdp, 0, 0); |
586 | lb = list_entry(head->next, struct gfs2_log_buf, lb_list); | 637 | } |
587 | list_del(&lb->lb_list); | ||
588 | bh = lb->lb_bh; | ||
589 | 638 | ||
590 | wait_on_buffer(bh); | 639 | static void gfs2_ordered_write(struct gfs2_sbd *sdp) |
591 | if (!buffer_uptodate(bh)) | 640 | { |
592 | gfs2_io_error_bh(sdp, bh); | 641 | struct gfs2_bufdata *bd; |
593 | if (lb->lb_real) { | 642 | struct buffer_head *bh; |
594 | while (atomic_read(&bh->b_count) != 1) /* Grrrr... */ | 643 | LIST_HEAD(written); |
595 | schedule(); | 644 | |
596 | free_buffer_head(bh); | 645 | gfs2_log_lock(sdp); |
597 | } else | 646 | while (!list_empty(&sdp->sd_log_le_ordered)) { |
647 | bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list); | ||
648 | list_move(&bd->bd_le.le_list, &written); | ||
649 | bh = bd->bd_bh; | ||
650 | if (!buffer_dirty(bh)) | ||
651 | continue; | ||
652 | get_bh(bh); | ||
653 | gfs2_log_unlock(sdp); | ||
654 | lock_buffer(bh); | ||
655 | if (test_clear_buffer_dirty(bh)) { | ||
656 | bh->b_end_io = end_buffer_write_sync; | ||
657 | submit_bh(WRITE, bh); | ||
658 | } else { | ||
659 | unlock_buffer(bh); | ||
598 | brelse(bh); | 660 | brelse(bh); |
599 | kfree(lb); | 661 | } |
600 | flushcount++; | 662 | gfs2_log_lock(sdp); |
601 | } | 663 | } |
664 | list_splice(&written, &sdp->sd_log_le_ordered); | ||
665 | gfs2_log_unlock(sdp); | ||
666 | } | ||
602 | 667 | ||
603 | /* If nothing was journaled, the header is unplanned and unwanted. */ | 668 | static void gfs2_ordered_wait(struct gfs2_sbd *sdp) |
604 | if (flushcount) { | 669 | { |
605 | log_write_header(sdp, 0, 0); | 670 | struct gfs2_bufdata *bd; |
606 | } else { | 671 | struct buffer_head *bh; |
607 | unsigned int tail; | ||
608 | tail = current_tail(sdp); | ||
609 | 672 | ||
610 | gfs2_ail1_empty(sdp, 0); | 673 | gfs2_log_lock(sdp); |
611 | if (sdp->sd_log_tail != tail) | 674 | while (!list_empty(&sdp->sd_log_le_ordered)) { |
612 | log_pull_tail(sdp, tail); | 675 | bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list); |
676 | bh = bd->bd_bh; | ||
677 | if (buffer_locked(bh)) { | ||
678 | get_bh(bh); | ||
679 | gfs2_log_unlock(sdp); | ||
680 | wait_on_buffer(bh); | ||
681 | brelse(bh); | ||
682 | gfs2_log_lock(sdp); | ||
683 | continue; | ||
684 | } | ||
685 | list_del_init(&bd->bd_le.le_list); | ||
613 | } | 686 | } |
687 | gfs2_log_unlock(sdp); | ||
614 | } | 688 | } |
615 | 689 | ||
616 | /** | 690 | /** |
@@ -640,10 +714,16 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
640 | INIT_LIST_HEAD(&ai->ai_ail1_list); | 714 | INIT_LIST_HEAD(&ai->ai_ail1_list); |
641 | INIT_LIST_HEAD(&ai->ai_ail2_list); | 715 | INIT_LIST_HEAD(&ai->ai_ail2_list); |
642 | 716 | ||
643 | gfs2_assert_withdraw(sdp, | 717 | if (sdp->sd_log_num_buf != sdp->sd_log_commited_buf) { |
644 | sdp->sd_log_num_buf + sdp->sd_log_num_jdata == | 718 | printk(KERN_INFO "GFS2: log buf %u %u\n", sdp->sd_log_num_buf, |
645 | sdp->sd_log_commited_buf + | 719 | sdp->sd_log_commited_buf); |
646 | sdp->sd_log_commited_databuf); | 720 | gfs2_assert_withdraw(sdp, 0); |
721 | } | ||
722 | if (sdp->sd_log_num_databuf != sdp->sd_log_commited_databuf) { | ||
723 | printk(KERN_INFO "GFS2: log databuf %u %u\n", | ||
724 | sdp->sd_log_num_databuf, sdp->sd_log_commited_databuf); | ||
725 | gfs2_assert_withdraw(sdp, 0); | ||
726 | } | ||
647 | gfs2_assert_withdraw(sdp, | 727 | gfs2_assert_withdraw(sdp, |
648 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); | 728 | sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); |
649 | 729 | ||
@@ -651,8 +731,11 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) | |||
651 | sdp->sd_log_flush_wrapped = 0; | 731 | sdp->sd_log_flush_wrapped = 0; |
652 | ai->ai_first = sdp->sd_log_flush_head; | 732 | ai->ai_first = sdp->sd_log_flush_head; |
653 | 733 | ||
734 | gfs2_ordered_write(sdp); | ||
654 | lops_before_commit(sdp); | 735 | lops_before_commit(sdp); |
655 | if (!list_empty(&sdp->sd_log_flush_list)) | 736 | gfs2_ordered_wait(sdp); |
737 | |||
738 | if (sdp->sd_log_head != sdp->sd_log_flush_head) | ||
656 | log_flush_commit(sdp); | 739 | log_flush_commit(sdp); |
657 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ | 740 | else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ |
658 | gfs2_log_lock(sdp); | 741 | gfs2_log_lock(sdp); |
@@ -744,7 +827,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) | |||
744 | gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); | 827 | gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); |
745 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl); | 828 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl); |
746 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); | 829 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); |
747 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_jdata); | ||
748 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 830 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
749 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); | 831 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); |
750 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); | 832 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf); |
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 8e7aa0f29109..dae282400627 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h | |||
@@ -52,12 +52,14 @@ int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags); | |||
52 | 52 | ||
53 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); | 53 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); |
54 | void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); | 54 | void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks); |
55 | void gfs2_log_incr_head(struct gfs2_sbd *sdp); | ||
55 | 56 | ||
56 | struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp); | 57 | struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp); |
57 | struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | 58 | struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, |
58 | struct buffer_head *real); | 59 | struct buffer_head *real); |
59 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); | 60 | void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); |
60 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | 61 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); |
62 | void gfs2_remove_from_ail(struct address_space *mapping, struct gfs2_bufdata *bd); | ||
61 | 63 | ||
62 | void gfs2_log_shutdown(struct gfs2_sbd *sdp); | 64 | void gfs2_log_shutdown(struct gfs2_sbd *sdp); |
63 | void gfs2_meta_syncfs(struct gfs2_sbd *sdp); | 65 | void gfs2_meta_syncfs(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 3b395c41b2f3..6c27cea761c6 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -27,7 +27,104 @@ | |||
27 | #include "trans.h" | 27 | #include "trans.h" |
28 | #include "util.h" | 28 | #include "util.h" |
29 | 29 | ||
30 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | 30 | /** |
31 | * gfs2_pin - Pin a buffer in memory | ||
32 | * @sdp: The superblock | ||
33 | * @bh: The buffer to be pinned | ||
34 | * | ||
35 | * The log lock must be held when calling this function | ||
36 | */ | ||
37 | static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
38 | { | ||
39 | struct gfs2_bufdata *bd; | ||
40 | |||
41 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | ||
42 | |||
43 | clear_buffer_dirty(bh); | ||
44 | if (test_set_buffer_pinned(bh)) | ||
45 | gfs2_assert_withdraw(sdp, 0); | ||
46 | if (!buffer_uptodate(bh)) | ||
47 | gfs2_io_error_bh(sdp, bh); | ||
48 | bd = bh->b_private; | ||
49 | /* If this buffer is in the AIL and it has already been written | ||
50 | * to in-place disk block, remove it from the AIL. | ||
51 | */ | ||
52 | if (bd->bd_ail) | ||
53 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | ||
54 | get_bh(bh); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * gfs2_unpin - Unpin a buffer | ||
59 | * @sdp: the filesystem the buffer belongs to | ||
60 | * @bh: The buffer to unpin | ||
61 | * @ai: | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
66 | struct gfs2_ail *ai) | ||
67 | { | ||
68 | struct gfs2_bufdata *bd = bh->b_private; | ||
69 | |||
70 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | ||
71 | |||
72 | if (!buffer_pinned(bh)) | ||
73 | gfs2_assert_withdraw(sdp, 0); | ||
74 | |||
75 | lock_buffer(bh); | ||
76 | mark_buffer_dirty(bh); | ||
77 | clear_buffer_pinned(bh); | ||
78 | |||
79 | gfs2_log_lock(sdp); | ||
80 | if (bd->bd_ail) { | ||
81 | list_del(&bd->bd_ail_st_list); | ||
82 | brelse(bh); | ||
83 | } else { | ||
84 | struct gfs2_glock *gl = bd->bd_gl; | ||
85 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | ||
86 | atomic_inc(&gl->gl_ail_count); | ||
87 | } | ||
88 | bd->bd_ail = ai; | ||
89 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | ||
90 | gfs2_log_unlock(sdp); | ||
91 | unlock_buffer(bh); | ||
92 | } | ||
93 | |||
94 | |||
95 | static inline struct gfs2_log_descriptor *bh_log_desc(struct buffer_head *bh) | ||
96 | { | ||
97 | return (struct gfs2_log_descriptor *)bh->b_data; | ||
98 | } | ||
99 | |||
100 | static inline __be64 *bh_log_ptr(struct buffer_head *bh) | ||
101 | { | ||
102 | struct gfs2_log_descriptor *ld = bh_log_desc(bh); | ||
103 | return (__force __be64 *)(ld + 1); | ||
104 | } | ||
105 | |||
106 | static inline __be64 *bh_ptr_end(struct buffer_head *bh) | ||
107 | { | ||
108 | return (__force __be64 *)(bh->b_data + bh->b_size); | ||
109 | } | ||
110 | |||
111 | |||
112 | static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) | ||
113 | { | ||
114 | struct buffer_head *bh = gfs2_log_get_buf(sdp); | ||
115 | struct gfs2_log_descriptor *ld = bh_log_desc(bh); | ||
116 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
117 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | ||
118 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
119 | ld->ld_type = cpu_to_be32(ld_type); | ||
120 | ld->ld_length = 0; | ||
121 | ld->ld_data1 = 0; | ||
122 | ld->ld_data2 = 0; | ||
123 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
124 | return bh; | ||
125 | } | ||
126 | |||
127 | static void __glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
31 | { | 128 | { |
32 | struct gfs2_glock *gl; | 129 | struct gfs2_glock *gl; |
33 | struct gfs2_trans *tr = current->journal_info; | 130 | struct gfs2_trans *tr = current->journal_info; |
@@ -38,15 +135,19 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
38 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) | 135 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) |
39 | return; | 136 | return; |
40 | 137 | ||
41 | gfs2_log_lock(sdp); | 138 | if (!list_empty(&le->le_list)) |
42 | if (!list_empty(&le->le_list)){ | ||
43 | gfs2_log_unlock(sdp); | ||
44 | return; | 139 | return; |
45 | } | 140 | |
46 | gfs2_glock_hold(gl); | 141 | gfs2_glock_hold(gl); |
47 | set_bit(GLF_DIRTY, &gl->gl_flags); | 142 | set_bit(GLF_DIRTY, &gl->gl_flags); |
48 | sdp->sd_log_num_gl++; | 143 | sdp->sd_log_num_gl++; |
49 | list_add(&le->le_list, &sdp->sd_log_le_gl); | 144 | list_add(&le->le_list, &sdp->sd_log_le_gl); |
145 | } | ||
146 | |||
147 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
148 | { | ||
149 | gfs2_log_lock(sdp); | ||
150 | __glock_lo_add(sdp, le); | ||
50 | gfs2_log_unlock(sdp); | 151 | gfs2_log_unlock(sdp); |
51 | } | 152 | } |
52 | 153 | ||
@@ -71,30 +172,25 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
71 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); | 172 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); |
72 | struct gfs2_trans *tr; | 173 | struct gfs2_trans *tr; |
73 | 174 | ||
175 | lock_buffer(bd->bd_bh); | ||
74 | gfs2_log_lock(sdp); | 176 | gfs2_log_lock(sdp); |
75 | if (!list_empty(&bd->bd_list_tr)) { | 177 | if (!list_empty(&bd->bd_list_tr)) |
76 | gfs2_log_unlock(sdp); | 178 | goto out; |
77 | return; | ||
78 | } | ||
79 | tr = current->journal_info; | 179 | tr = current->journal_info; |
80 | tr->tr_touched = 1; | 180 | tr->tr_touched = 1; |
81 | tr->tr_num_buf++; | 181 | tr->tr_num_buf++; |
82 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 182 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
83 | gfs2_log_unlock(sdp); | ||
84 | |||
85 | if (!list_empty(&le->le_list)) | 183 | if (!list_empty(&le->le_list)) |
86 | return; | 184 | goto out; |
87 | 185 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); | |
88 | gfs2_trans_add_gl(bd->bd_gl); | ||
89 | |||
90 | gfs2_meta_check(sdp, bd->bd_bh); | 186 | gfs2_meta_check(sdp, bd->bd_bh); |
91 | gfs2_pin(sdp, bd->bd_bh); | 187 | gfs2_pin(sdp, bd->bd_bh); |
92 | gfs2_log_lock(sdp); | ||
93 | sdp->sd_log_num_buf++; | 188 | sdp->sd_log_num_buf++; |
94 | list_add(&le->le_list, &sdp->sd_log_le_buf); | 189 | list_add(&le->le_list, &sdp->sd_log_le_buf); |
95 | gfs2_log_unlock(sdp); | ||
96 | |||
97 | tr->tr_num_buf_new++; | 190 | tr->tr_num_buf_new++; |
191 | out: | ||
192 | gfs2_log_unlock(sdp); | ||
193 | unlock_buffer(bd->bd_bh); | ||
98 | } | 194 | } |
99 | 195 | ||
100 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 196 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
@@ -117,8 +213,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
117 | struct buffer_head *bh; | 213 | struct buffer_head *bh; |
118 | struct gfs2_log_descriptor *ld; | 214 | struct gfs2_log_descriptor *ld; |
119 | struct gfs2_bufdata *bd1 = NULL, *bd2; | 215 | struct gfs2_bufdata *bd1 = NULL, *bd2; |
120 | unsigned int total = sdp->sd_log_num_buf; | 216 | unsigned int total; |
121 | unsigned int offset = BUF_OFFSET; | ||
122 | unsigned int limit; | 217 | unsigned int limit; |
123 | unsigned int num; | 218 | unsigned int num; |
124 | unsigned n; | 219 | unsigned n; |
@@ -127,22 +222,20 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
127 | limit = buf_limit(sdp); | 222 | limit = buf_limit(sdp); |
128 | /* for 4k blocks, limit = 503 */ | 223 | /* for 4k blocks, limit = 503 */ |
129 | 224 | ||
225 | gfs2_log_lock(sdp); | ||
226 | total = sdp->sd_log_num_buf; | ||
130 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); | 227 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); |
131 | while(total) { | 228 | while(total) { |
132 | num = total; | 229 | num = total; |
133 | if (total > limit) | 230 | if (total > limit) |
134 | num = limit; | 231 | num = limit; |
135 | bh = gfs2_log_get_buf(sdp); | 232 | gfs2_log_unlock(sdp); |
136 | ld = (struct gfs2_log_descriptor *)bh->b_data; | 233 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA); |
137 | ptr = (__be64 *)(bh->b_data + offset); | 234 | gfs2_log_lock(sdp); |
138 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 235 | ld = bh_log_desc(bh); |
139 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | 236 | ptr = bh_log_ptr(bh); |
140 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
141 | ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_METADATA); | ||
142 | ld->ld_length = cpu_to_be32(num + 1); | 237 | ld->ld_length = cpu_to_be32(num + 1); |
143 | ld->ld_data1 = cpu_to_be32(num); | 238 | ld->ld_data1 = cpu_to_be32(num); |
144 | ld->ld_data2 = cpu_to_be32(0); | ||
145 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
146 | 239 | ||
147 | n = 0; | 240 | n = 0; |
148 | list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf, | 241 | list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf, |
@@ -152,21 +245,27 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
152 | break; | 245 | break; |
153 | } | 246 | } |
154 | 247 | ||
155 | set_buffer_dirty(bh); | 248 | gfs2_log_unlock(sdp); |
156 | ll_rw_block(WRITE, 1, &bh); | 249 | submit_bh(WRITE, bh); |
250 | gfs2_log_lock(sdp); | ||
157 | 251 | ||
158 | n = 0; | 252 | n = 0; |
159 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf, | 253 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf, |
160 | bd_le.le_list) { | 254 | bd_le.le_list) { |
255 | get_bh(bd2->bd_bh); | ||
256 | gfs2_log_unlock(sdp); | ||
257 | lock_buffer(bd2->bd_bh); | ||
161 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); | 258 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); |
162 | set_buffer_dirty(bh); | 259 | submit_bh(WRITE, bh); |
163 | ll_rw_block(WRITE, 1, &bh); | 260 | gfs2_log_lock(sdp); |
164 | if (++n >= num) | 261 | if (++n >= num) |
165 | break; | 262 | break; |
166 | } | 263 | } |
167 | 264 | ||
265 | BUG_ON(total < num); | ||
168 | total -= num; | 266 | total -= num; |
169 | } | 267 | } |
268 | gfs2_log_unlock(sdp); | ||
170 | } | 269 | } |
171 | 270 | ||
172 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 271 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) |
@@ -270,11 +369,8 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
270 | tr = current->journal_info; | 369 | tr = current->journal_info; |
271 | tr->tr_touched = 1; | 370 | tr->tr_touched = 1; |
272 | tr->tr_num_revoke++; | 371 | tr->tr_num_revoke++; |
273 | |||
274 | gfs2_log_lock(sdp); | ||
275 | sdp->sd_log_num_revoke++; | 372 | sdp->sd_log_num_revoke++; |
276 | list_add(&le->le_list, &sdp->sd_log_le_revoke); | 373 | list_add(&le->le_list, &sdp->sd_log_le_revoke); |
277 | gfs2_log_unlock(sdp); | ||
278 | } | 374 | } |
279 | 375 | ||
280 | static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | 376 | static void revoke_lo_before_commit(struct gfs2_sbd *sdp) |
@@ -284,32 +380,25 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
284 | struct buffer_head *bh; | 380 | struct buffer_head *bh; |
285 | unsigned int offset; | 381 | unsigned int offset; |
286 | struct list_head *head = &sdp->sd_log_le_revoke; | 382 | struct list_head *head = &sdp->sd_log_le_revoke; |
287 | struct gfs2_revoke *rv; | 383 | struct gfs2_bufdata *bd; |
288 | 384 | ||
289 | if (!sdp->sd_log_num_revoke) | 385 | if (!sdp->sd_log_num_revoke) |
290 | return; | 386 | return; |
291 | 387 | ||
292 | bh = gfs2_log_get_buf(sdp); | 388 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE); |
293 | ld = (struct gfs2_log_descriptor *)bh->b_data; | 389 | ld = bh_log_desc(bh); |
294 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
295 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | ||
296 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
297 | ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_REVOKE); | ||
298 | ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, | 390 | ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, |
299 | sizeof(u64))); | 391 | sizeof(u64))); |
300 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); | 392 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); |
301 | ld->ld_data2 = cpu_to_be32(0); | ||
302 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
303 | offset = sizeof(struct gfs2_log_descriptor); | 393 | offset = sizeof(struct gfs2_log_descriptor); |
304 | 394 | ||
305 | while (!list_empty(head)) { | 395 | while (!list_empty(head)) { |
306 | rv = list_entry(head->next, struct gfs2_revoke, rv_le.le_list); | 396 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); |
307 | list_del_init(&rv->rv_le.le_list); | 397 | list_del_init(&bd->bd_le.le_list); |
308 | sdp->sd_log_num_revoke--; | 398 | sdp->sd_log_num_revoke--; |
309 | 399 | ||
310 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { | 400 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { |
311 | set_buffer_dirty(bh); | 401 | submit_bh(WRITE, bh); |
312 | ll_rw_block(WRITE, 1, &bh); | ||
313 | 402 | ||
314 | bh = gfs2_log_get_buf(sdp); | 403 | bh = gfs2_log_get_buf(sdp); |
315 | mh = (struct gfs2_meta_header *)bh->b_data; | 404 | mh = (struct gfs2_meta_header *)bh->b_data; |
@@ -319,15 +408,14 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
319 | offset = sizeof(struct gfs2_meta_header); | 408 | offset = sizeof(struct gfs2_meta_header); |
320 | } | 409 | } |
321 | 410 | ||
322 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(rv->rv_blkno); | 411 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno); |
323 | kfree(rv); | 412 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
324 | 413 | ||
325 | offset += sizeof(u64); | 414 | offset += sizeof(u64); |
326 | } | 415 | } |
327 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 416 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
328 | 417 | ||
329 | set_buffer_dirty(bh); | 418 | submit_bh(WRITE, bh); |
330 | ll_rw_block(WRITE, 1, &bh); | ||
331 | } | 419 | } |
332 | 420 | ||
333 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, | 421 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |
@@ -466,222 +554,136 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
466 | struct address_space *mapping = bd->bd_bh->b_page->mapping; | 554 | struct address_space *mapping = bd->bd_bh->b_page->mapping; |
467 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 555 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
468 | 556 | ||
557 | lock_buffer(bd->bd_bh); | ||
469 | gfs2_log_lock(sdp); | 558 | gfs2_log_lock(sdp); |
470 | if (!list_empty(&bd->bd_list_tr)) { | 559 | if (!list_empty(&bd->bd_list_tr)) |
471 | gfs2_log_unlock(sdp); | 560 | goto out; |
472 | return; | ||
473 | } | ||
474 | tr->tr_touched = 1; | 561 | tr->tr_touched = 1; |
475 | if (gfs2_is_jdata(ip)) { | 562 | if (gfs2_is_jdata(ip)) { |
476 | tr->tr_num_buf++; | 563 | tr->tr_num_buf++; |
477 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 564 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
478 | } | 565 | } |
479 | gfs2_log_unlock(sdp); | ||
480 | if (!list_empty(&le->le_list)) | 566 | if (!list_empty(&le->le_list)) |
481 | return; | 567 | goto out; |
482 | 568 | ||
483 | gfs2_trans_add_gl(bd->bd_gl); | 569 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); |
484 | if (gfs2_is_jdata(ip)) { | 570 | if (gfs2_is_jdata(ip)) { |
485 | sdp->sd_log_num_jdata++; | ||
486 | gfs2_pin(sdp, bd->bd_bh); | 571 | gfs2_pin(sdp, bd->bd_bh); |
487 | tr->tr_num_databuf_new++; | 572 | tr->tr_num_databuf_new++; |
573 | sdp->sd_log_num_databuf++; | ||
574 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
575 | } else { | ||
576 | list_add(&le->le_list, &sdp->sd_log_le_ordered); | ||
488 | } | 577 | } |
489 | gfs2_log_lock(sdp); | 578 | out: |
490 | sdp->sd_log_num_databuf++; | ||
491 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
492 | gfs2_log_unlock(sdp); | 579 | gfs2_log_unlock(sdp); |
580 | unlock_buffer(bd->bd_bh); | ||
493 | } | 581 | } |
494 | 582 | ||
495 | static int gfs2_check_magic(struct buffer_head *bh) | 583 | static void gfs2_check_magic(struct buffer_head *bh) |
496 | { | 584 | { |
497 | struct page *page = bh->b_page; | ||
498 | void *kaddr; | 585 | void *kaddr; |
499 | __be32 *ptr; | 586 | __be32 *ptr; |
500 | int rv = 0; | ||
501 | 587 | ||
502 | kaddr = kmap_atomic(page, KM_USER0); | 588 | clear_buffer_escaped(bh); |
589 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | ||
503 | ptr = kaddr + bh_offset(bh); | 590 | ptr = kaddr + bh_offset(bh); |
504 | if (*ptr == cpu_to_be32(GFS2_MAGIC)) | 591 | if (*ptr == cpu_to_be32(GFS2_MAGIC)) |
505 | rv = 1; | 592 | set_buffer_escaped(bh); |
506 | kunmap_atomic(kaddr, KM_USER0); | 593 | kunmap_atomic(kaddr, KM_USER0); |
507 | |||
508 | return rv; | ||
509 | } | 594 | } |
510 | 595 | ||
511 | /** | 596 | static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, |
512 | * databuf_lo_before_commit - Scan the data buffers, writing as we go | 597 | struct list_head *list, struct list_head *done, |
513 | * | 598 | unsigned int n) |
514 | * Here we scan through the lists of buffers and make the assumption | ||
515 | * that any buffer thats been pinned is being journaled, and that | ||
516 | * any unpinned buffer is an ordered write data buffer and therefore | ||
517 | * will be written back rather than journaled. | ||
518 | */ | ||
519 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | ||
520 | { | 599 | { |
521 | LIST_HEAD(started); | 600 | struct buffer_head *bh1; |
522 | struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; | ||
523 | struct buffer_head *bh = NULL,*bh1 = NULL; | ||
524 | struct gfs2_log_descriptor *ld; | 601 | struct gfs2_log_descriptor *ld; |
525 | unsigned int limit; | 602 | struct gfs2_bufdata *bd; |
526 | unsigned int total_dbuf; | 603 | __be64 *ptr; |
527 | unsigned int total_jdata = sdp->sd_log_num_jdata; | 604 | |
528 | unsigned int num, n; | 605 | if (!bh) |
529 | __be64 *ptr = NULL; | 606 | return; |
530 | 607 | ||
531 | limit = databuf_limit(sdp); | 608 | ld = bh_log_desc(bh); |
609 | ld->ld_length = cpu_to_be32(n + 1); | ||
610 | ld->ld_data1 = cpu_to_be32(n); | ||
532 | 611 | ||
533 | /* | 612 | ptr = bh_log_ptr(bh); |
534 | * Start writing ordered buffers, write journaled buffers | 613 | |
535 | * into the log along with a header | 614 | get_bh(bh); |
536 | */ | 615 | submit_bh(WRITE, bh); |
537 | gfs2_log_lock(sdp); | 616 | gfs2_log_lock(sdp); |
538 | total_dbuf = sdp->sd_log_num_databuf; | 617 | while(!list_empty(list)) { |
539 | bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf, | 618 | bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list); |
540 | bd_le.le_list); | 619 | list_move_tail(&bd->bd_le.le_list, done); |
541 | while(total_dbuf) { | 620 | get_bh(bd->bd_bh); |
542 | num = total_jdata; | 621 | while (be64_to_cpu(*ptr) != bd->bd_bh->b_blocknr) { |
543 | if (num > limit) | 622 | gfs2_log_incr_head(sdp); |
544 | num = limit; | 623 | ptr += 2; |
545 | n = 0; | ||
546 | list_for_each_entry_safe_continue(bd1, bdt, | ||
547 | &sdp->sd_log_le_databuf, | ||
548 | bd_le.le_list) { | ||
549 | /* store off the buffer head in a local ptr since | ||
550 | * gfs2_bufdata might change when we drop the log lock | ||
551 | */ | ||
552 | bh1 = bd1->bd_bh; | ||
553 | |||
554 | /* An ordered write buffer */ | ||
555 | if (bh1 && !buffer_pinned(bh1)) { | ||
556 | list_move(&bd1->bd_le.le_list, &started); | ||
557 | if (bd1 == bd2) { | ||
558 | bd2 = NULL; | ||
559 | bd2 = list_prepare_entry(bd2, | ||
560 | &sdp->sd_log_le_databuf, | ||
561 | bd_le.le_list); | ||
562 | } | ||
563 | total_dbuf--; | ||
564 | if (bh1) { | ||
565 | if (buffer_dirty(bh1)) { | ||
566 | get_bh(bh1); | ||
567 | |||
568 | gfs2_log_unlock(sdp); | ||
569 | |||
570 | ll_rw_block(SWRITE, 1, &bh1); | ||
571 | brelse(bh1); | ||
572 | |||
573 | gfs2_log_lock(sdp); | ||
574 | } | ||
575 | continue; | ||
576 | } | ||
577 | continue; | ||
578 | } else if (bh1) { /* A journaled buffer */ | ||
579 | int magic; | ||
580 | gfs2_log_unlock(sdp); | ||
581 | if (!bh) { | ||
582 | bh = gfs2_log_get_buf(sdp); | ||
583 | ld = (struct gfs2_log_descriptor *) | ||
584 | bh->b_data; | ||
585 | ptr = (__be64 *)(bh->b_data + | ||
586 | DATABUF_OFFSET); | ||
587 | ld->ld_header.mh_magic = | ||
588 | cpu_to_be32(GFS2_MAGIC); | ||
589 | ld->ld_header.mh_type = | ||
590 | cpu_to_be32(GFS2_METATYPE_LD); | ||
591 | ld->ld_header.mh_format = | ||
592 | cpu_to_be32(GFS2_FORMAT_LD); | ||
593 | ld->ld_type = | ||
594 | cpu_to_be32(GFS2_LOG_DESC_JDATA); | ||
595 | ld->ld_length = cpu_to_be32(num + 1); | ||
596 | ld->ld_data1 = cpu_to_be32(num); | ||
597 | ld->ld_data2 = cpu_to_be32(0); | ||
598 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
599 | } | ||
600 | magic = gfs2_check_magic(bh1); | ||
601 | *ptr++ = cpu_to_be64(bh1->b_blocknr); | ||
602 | *ptr++ = cpu_to_be64((__u64)magic); | ||
603 | clear_buffer_escaped(bh1); | ||
604 | if (unlikely(magic != 0)) | ||
605 | set_buffer_escaped(bh1); | ||
606 | gfs2_log_lock(sdp); | ||
607 | if (++n >= num) | ||
608 | break; | ||
609 | } else if (!bh1) { | ||
610 | total_dbuf--; | ||
611 | sdp->sd_log_num_databuf--; | ||
612 | list_del_init(&bd1->bd_le.le_list); | ||
613 | if (bd1 == bd2) { | ||
614 | bd2 = NULL; | ||
615 | bd2 = list_prepare_entry(bd2, | ||
616 | &sdp->sd_log_le_databuf, | ||
617 | bd_le.le_list); | ||
618 | } | ||
619 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | ||
620 | } | ||
621 | } | 624 | } |
622 | gfs2_log_unlock(sdp); | 625 | gfs2_log_unlock(sdp); |
623 | if (bh) { | 626 | lock_buffer(bd->bd_bh); |
624 | set_buffer_mapped(bh); | 627 | if (buffer_escaped(bd->bd_bh)) { |
625 | set_buffer_dirty(bh); | 628 | void *kaddr; |
626 | ll_rw_block(WRITE, 1, &bh); | 629 | bh1 = gfs2_log_get_buf(sdp); |
627 | bh = NULL; | 630 | kaddr = kmap_atomic(bd->bd_bh->b_page, KM_USER0); |
631 | memcpy(bh1->b_data, kaddr + bh_offset(bd->bd_bh), | ||
632 | bh1->b_size); | ||
633 | kunmap_atomic(kaddr, KM_USER0); | ||
634 | *(__be32 *)bh1->b_data = 0; | ||
635 | clear_buffer_escaped(bd->bd_bh); | ||
636 | unlock_buffer(bd->bd_bh); | ||
637 | brelse(bd->bd_bh); | ||
638 | } else { | ||
639 | bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh); | ||
628 | } | 640 | } |
629 | n = 0; | 641 | submit_bh(WRITE, bh1); |
630 | gfs2_log_lock(sdp); | 642 | gfs2_log_lock(sdp); |
631 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_databuf, | 643 | ptr += 2; |
632 | bd_le.le_list) { | ||
633 | if (!bd2->bd_bh) | ||
634 | continue; | ||
635 | /* copy buffer if it needs escaping */ | ||
636 | gfs2_log_unlock(sdp); | ||
637 | if (unlikely(buffer_escaped(bd2->bd_bh))) { | ||
638 | void *kaddr; | ||
639 | struct page *page = bd2->bd_bh->b_page; | ||
640 | bh = gfs2_log_get_buf(sdp); | ||
641 | kaddr = kmap_atomic(page, KM_USER0); | ||
642 | memcpy(bh->b_data, | ||
643 | kaddr + bh_offset(bd2->bd_bh), | ||
644 | sdp->sd_sb.sb_bsize); | ||
645 | kunmap_atomic(kaddr, KM_USER0); | ||
646 | *(__be32 *)bh->b_data = 0; | ||
647 | } else { | ||
648 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); | ||
649 | } | ||
650 | set_buffer_dirty(bh); | ||
651 | ll_rw_block(WRITE, 1, &bh); | ||
652 | gfs2_log_lock(sdp); | ||
653 | if (++n >= num) | ||
654 | break; | ||
655 | } | ||
656 | bh = NULL; | ||
657 | BUG_ON(total_dbuf < num); | ||
658 | total_dbuf -= num; | ||
659 | total_jdata -= num; | ||
660 | } | 644 | } |
661 | gfs2_log_unlock(sdp); | 645 | gfs2_log_unlock(sdp); |
646 | brelse(bh); | ||
647 | } | ||
662 | 648 | ||
663 | /* Wait on all ordered buffers */ | 649 | /** |
664 | while (!list_empty(&started)) { | 650 | * databuf_lo_before_commit - Scan the data buffers, writing as we go |
665 | gfs2_log_lock(sdp); | 651 | * |
666 | bd1 = list_entry(started.next, struct gfs2_bufdata, | 652 | */ |
667 | bd_le.le_list); | ||
668 | list_del_init(&bd1->bd_le.le_list); | ||
669 | sdp->sd_log_num_databuf--; | ||
670 | bh = bd1->bd_bh; | ||
671 | if (bh) { | ||
672 | bh->b_private = NULL; | ||
673 | get_bh(bh); | ||
674 | gfs2_log_unlock(sdp); | ||
675 | wait_on_buffer(bh); | ||
676 | brelse(bh); | ||
677 | } else | ||
678 | gfs2_log_unlock(sdp); | ||
679 | 653 | ||
680 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | 654 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) |
681 | } | 655 | { |
656 | struct gfs2_bufdata *bd = NULL; | ||
657 | struct buffer_head *bh = NULL; | ||
658 | unsigned int n = 0; | ||
659 | __be64 *ptr = NULL, *end = NULL; | ||
660 | LIST_HEAD(processed); | ||
661 | LIST_HEAD(in_progress); | ||
682 | 662 | ||
683 | /* We've removed all the ordered write bufs here, so only jdata left */ | 663 | gfs2_log_lock(sdp); |
684 | gfs2_assert_warn(sdp, sdp->sd_log_num_databuf == sdp->sd_log_num_jdata); | 664 | while (!list_empty(&sdp->sd_log_le_databuf)) { |
665 | if (ptr == end) { | ||
666 | gfs2_log_unlock(sdp); | ||
667 | gfs2_write_blocks(sdp, bh, &in_progress, &processed, n); | ||
668 | n = 0; | ||
669 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_JDATA); | ||
670 | ptr = bh_log_ptr(bh); | ||
671 | end = bh_ptr_end(bh) - 1; | ||
672 | gfs2_log_lock(sdp); | ||
673 | continue; | ||
674 | } | ||
675 | bd = list_entry(sdp->sd_log_le_databuf.next, struct gfs2_bufdata, bd_le.le_list); | ||
676 | list_move_tail(&bd->bd_le.le_list, &in_progress); | ||
677 | gfs2_check_magic(bd->bd_bh); | ||
678 | *ptr++ = cpu_to_be64(bd->bd_bh->b_blocknr); | ||
679 | *ptr++ = cpu_to_be64(buffer_escaped(bh) ? 1 : 0); | ||
680 | n++; | ||
681 | } | ||
682 | gfs2_log_unlock(sdp); | ||
683 | gfs2_write_blocks(sdp, bh, &in_progress, &processed, n); | ||
684 | gfs2_log_lock(sdp); | ||
685 | list_splice(&processed, &sdp->sd_log_le_databuf); | ||
686 | gfs2_log_unlock(sdp); | ||
685 | } | 687 | } |
686 | 688 | ||
687 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, | 689 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, |
@@ -765,11 +767,9 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
765 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); | 767 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); |
766 | list_del_init(&bd->bd_le.le_list); | 768 | list_del_init(&bd->bd_le.le_list); |
767 | sdp->sd_log_num_databuf--; | 769 | sdp->sd_log_num_databuf--; |
768 | sdp->sd_log_num_jdata--; | ||
769 | gfs2_unpin(sdp, bd->bd_bh, ai); | 770 | gfs2_unpin(sdp, bd->bd_bh, ai); |
770 | } | 771 | } |
771 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); | 772 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); |
772 | gfs2_assert_warn(sdp, !sdp->sd_log_num_jdata); | ||
773 | } | 773 | } |
774 | 774 | ||
775 | 775 | ||
@@ -817,10 +817,10 @@ const struct gfs2_log_operations gfs2_databuf_lops = { | |||
817 | 817 | ||
818 | const struct gfs2_log_operations *gfs2_log_ops[] = { | 818 | const struct gfs2_log_operations *gfs2_log_ops[] = { |
819 | &gfs2_glock_lops, | 819 | &gfs2_glock_lops, |
820 | &gfs2_databuf_lops, | ||
820 | &gfs2_buf_lops, | 821 | &gfs2_buf_lops, |
821 | &gfs2_revoke_lops, | ||
822 | &gfs2_rg_lops, | 822 | &gfs2_rg_lops, |
823 | &gfs2_databuf_lops, | 823 | &gfs2_revoke_lops, |
824 | NULL, | 824 | NULL, |
825 | }; | 825 | }; |
826 | 826 | ||
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index d5d4e68b8807..79c91fd8381b 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -107,6 +107,8 @@ static int __init init_gfs2_fs(void) | |||
107 | fail_unregister: | 107 | fail_unregister: |
108 | unregister_filesystem(&gfs2_fs_type); | 108 | unregister_filesystem(&gfs2_fs_type); |
109 | fail: | 109 | fail: |
110 | gfs2_glock_exit(); | ||
111 | |||
110 | if (gfs2_bufdata_cachep) | 112 | if (gfs2_bufdata_cachep) |
111 | kmem_cache_destroy(gfs2_bufdata_cachep); | 113 | kmem_cache_destroy(gfs2_bufdata_cachep); |
112 | 114 | ||
@@ -127,6 +129,7 @@ fail: | |||
127 | 129 | ||
128 | static void __exit exit_gfs2_fs(void) | 130 | static void __exit exit_gfs2_fs(void) |
129 | { | 131 | { |
132 | gfs2_glock_exit(); | ||
130 | gfs2_unregister_debugfs(); | 133 | gfs2_unregister_debugfs(); |
131 | unregister_filesystem(&gfs2_fs_type); | 134 | unregister_filesystem(&gfs2_fs_type); |
132 | unregister_filesystem(&gfs2meta_fs_type); | 135 | unregister_filesystem(&gfs2meta_fs_type); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 8da343b34ae7..4da423985e4f 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -297,74 +297,35 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
297 | unlock_page(bh->b_page); | 297 | unlock_page(bh->b_page); |
298 | } | 298 | } |
299 | 299 | ||
300 | /** | 300 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) |
301 | * gfs2_pin - Pin a buffer in memory | ||
302 | * @sdp: the filesystem the buffer belongs to | ||
303 | * @bh: The buffer to be pinned | ||
304 | * | ||
305 | */ | ||
306 | |||
307 | void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
308 | { | 301 | { |
302 | struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host); | ||
309 | struct gfs2_bufdata *bd = bh->b_private; | 303 | struct gfs2_bufdata *bd = bh->b_private; |
310 | 304 | if (test_clear_buffer_pinned(bh)) { | |
311 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | 305 | list_del_init(&bd->bd_le.le_list); |
312 | 306 | if (meta) { | |
313 | if (test_set_buffer_pinned(bh)) | 307 | gfs2_assert_warn(sdp, sdp->sd_log_num_buf); |
314 | gfs2_assert_withdraw(sdp, 0); | 308 | sdp->sd_log_num_buf--; |
315 | 309 | tr->tr_num_buf_rm++; | |
316 | wait_on_buffer(bh); | 310 | } else { |
317 | 311 | gfs2_assert_warn(sdp, sdp->sd_log_num_databuf); | |
318 | /* If this buffer is in the AIL and it has already been written | 312 | sdp->sd_log_num_databuf--; |
319 | to in-place disk block, remove it from the AIL. */ | 313 | tr->tr_num_databuf_rm++; |
320 | 314 | } | |
321 | gfs2_log_lock(sdp); | 315 | tr->tr_touched = 1; |
322 | if (bd->bd_ail && !buffer_in_io(bh)) | ||
323 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | ||
324 | gfs2_log_unlock(sdp); | ||
325 | |||
326 | clear_buffer_dirty(bh); | ||
327 | wait_on_buffer(bh); | ||
328 | |||
329 | if (!buffer_uptodate(bh)) | ||
330 | gfs2_io_error_bh(sdp, bh); | ||
331 | |||
332 | get_bh(bh); | ||
333 | } | ||
334 | |||
335 | /** | ||
336 | * gfs2_unpin - Unpin a buffer | ||
337 | * @sdp: the filesystem the buffer belongs to | ||
338 | * @bh: The buffer to unpin | ||
339 | * @ai: | ||
340 | * | ||
341 | */ | ||
342 | |||
343 | void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
344 | struct gfs2_ail *ai) | ||
345 | { | ||
346 | struct gfs2_bufdata *bd = bh->b_private; | ||
347 | |||
348 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | ||
349 | |||
350 | if (!buffer_pinned(bh)) | ||
351 | gfs2_assert_withdraw(sdp, 0); | ||
352 | |||
353 | mark_buffer_dirty(bh); | ||
354 | clear_buffer_pinned(bh); | ||
355 | |||
356 | gfs2_log_lock(sdp); | ||
357 | if (bd->bd_ail) { | ||
358 | list_del(&bd->bd_ail_st_list); | ||
359 | brelse(bh); | 316 | brelse(bh); |
360 | } else { | ||
361 | struct gfs2_glock *gl = bd->bd_gl; | ||
362 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | ||
363 | atomic_inc(&gl->gl_ail_count); | ||
364 | } | 317 | } |
365 | bd->bd_ail = ai; | 318 | if (bd) { |
366 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | 319 | if (bd->bd_ail) { |
367 | gfs2_log_unlock(sdp); | 320 | gfs2_remove_from_ail(NULL, bd); |
321 | bh->b_private = NULL; | ||
322 | bd->bd_bh = NULL; | ||
323 | bd->bd_blkno = bh->b_blocknr; | ||
324 | gfs2_trans_add_revoke(sdp, bd); | ||
325 | } | ||
326 | } | ||
327 | clear_buffer_dirty(bh); | ||
328 | clear_buffer_uptodate(bh); | ||
368 | } | 329 | } |
369 | 330 | ||
370 | /** | 331 | /** |
@@ -383,44 +344,11 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) | |||
383 | while (blen) { | 344 | while (blen) { |
384 | bh = getbuf(ip->i_gl, bstart, NO_CREATE); | 345 | bh = getbuf(ip->i_gl, bstart, NO_CREATE); |
385 | if (bh) { | 346 | if (bh) { |
386 | struct gfs2_bufdata *bd = bh->b_private; | ||
387 | |||
388 | if (test_clear_buffer_pinned(bh)) { | ||
389 | struct gfs2_trans *tr = current->journal_info; | ||
390 | struct gfs2_inode *bh_ip = | ||
391 | GFS2_I(bh->b_page->mapping->host); | ||
392 | |||
393 | gfs2_log_lock(sdp); | ||
394 | list_del_init(&bd->bd_le.le_list); | ||
395 | gfs2_assert_warn(sdp, sdp->sd_log_num_buf); | ||
396 | sdp->sd_log_num_buf--; | ||
397 | gfs2_log_unlock(sdp); | ||
398 | if (bh_ip->i_inode.i_private != NULL) | ||
399 | tr->tr_num_databuf_rm++; | ||
400 | else | ||
401 | tr->tr_num_buf_rm++; | ||
402 | brelse(bh); | ||
403 | } | ||
404 | if (bd) { | ||
405 | gfs2_log_lock(sdp); | ||
406 | if (bd->bd_ail) { | ||
407 | u64 blkno = bh->b_blocknr; | ||
408 | bd->bd_ail = NULL; | ||
409 | list_del(&bd->bd_ail_st_list); | ||
410 | list_del(&bd->bd_ail_gl_list); | ||
411 | atomic_dec(&bd->bd_gl->gl_ail_count); | ||
412 | brelse(bh); | ||
413 | gfs2_log_unlock(sdp); | ||
414 | gfs2_trans_add_revoke(sdp, blkno); | ||
415 | } else | ||
416 | gfs2_log_unlock(sdp); | ||
417 | } | ||
418 | |||
419 | lock_buffer(bh); | 347 | lock_buffer(bh); |
420 | clear_buffer_dirty(bh); | 348 | gfs2_log_lock(sdp); |
421 | clear_buffer_uptodate(bh); | 349 | gfs2_remove_from_journal(bh, current->journal_info, 1); |
350 | gfs2_log_unlock(sdp); | ||
422 | unlock_buffer(bh); | 351 | unlock_buffer(bh); |
423 | |||
424 | brelse(bh); | 352 | brelse(bh); |
425 | } | 353 | } |
426 | 354 | ||
@@ -446,10 +374,10 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip) | |||
446 | 374 | ||
447 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) { | 375 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) { |
448 | bh_slot = &ip->i_cache[x]; | 376 | bh_slot = &ip->i_cache[x]; |
449 | if (!*bh_slot) | 377 | if (*bh_slot) { |
450 | break; | 378 | brelse(*bh_slot); |
451 | brelse(*bh_slot); | 379 | *bh_slot = NULL; |
452 | *bh_slot = NULL; | 380 | } |
453 | } | 381 | } |
454 | 382 | ||
455 | spin_unlock(&ip->i_spin); | 383 | spin_unlock(&ip->i_spin); |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index 527bf19d9690..b7048222ebb4 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -50,9 +50,9 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); | |||
50 | 50 | ||
51 | void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | 51 | void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, |
52 | int meta); | 52 | int meta); |
53 | void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); | 53 | |
54 | void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | 54 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, |
55 | struct gfs2_ail *ai); | 55 | int meta); |
56 | 56 | ||
57 | void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); | 57 | void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); |
58 | 58 | ||
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 4864659555d4..b941f9f9f958 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c | |||
@@ -42,6 +42,7 @@ enum { | |||
42 | Opt_nosuiddir, | 42 | Opt_nosuiddir, |
43 | Opt_data_writeback, | 43 | Opt_data_writeback, |
44 | Opt_data_ordered, | 44 | Opt_data_ordered, |
45 | Opt_err, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static match_table_t tokens = { | 48 | static match_table_t tokens = { |
@@ -64,7 +65,8 @@ static match_table_t tokens = { | |||
64 | {Opt_suiddir, "suiddir"}, | 65 | {Opt_suiddir, "suiddir"}, |
65 | {Opt_nosuiddir, "nosuiddir"}, | 66 | {Opt_nosuiddir, "nosuiddir"}, |
66 | {Opt_data_writeback, "data=writeback"}, | 67 | {Opt_data_writeback, "data=writeback"}, |
67 | {Opt_data_ordered, "data=ordered"} | 68 | {Opt_data_ordered, "data=ordered"}, |
69 | {Opt_err, NULL} | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | /** | 72 | /** |
@@ -237,6 +239,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
237 | case Opt_data_ordered: | 239 | case Opt_data_ordered: |
238 | args->ar_data = GFS2_DATA_ORDERED; | 240 | args->ar_data = GFS2_DATA_ORDERED; |
239 | break; | 241 | break; |
242 | case Opt_err: | ||
240 | default: | 243 | default: |
241 | fs_info(sdp, "unknown option: %s\n", o); | 244 | fs_info(sdp, "unknown option: %s\n", o); |
242 | error = -EINVAL; | 245 | error = -EINVAL; |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 42a5f58f6fca..873a511ef2be 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -90,7 +90,7 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock, | |||
90 | error = gfs2_block_map(inode, lblock, 0, bh_result); | 90 | error = gfs2_block_map(inode, lblock, 0, bh_result); |
91 | if (error) | 91 | if (error) |
92 | return error; | 92 | return error; |
93 | if (bh_result->b_blocknr == 0) | 93 | if (!buffer_mapped(bh_result)) |
94 | return -EIO; | 94 | return -EIO; |
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
@@ -414,7 +414,8 @@ static int gfs2_prepare_write(struct file *file, struct page *page, | |||
414 | if (ind_blocks || data_blocks) | 414 | if (ind_blocks || data_blocks) |
415 | rblocks += RES_STATFS + RES_QUOTA; | 415 | rblocks += RES_STATFS + RES_QUOTA; |
416 | 416 | ||
417 | error = gfs2_trans_begin(sdp, rblocks, 0); | 417 | error = gfs2_trans_begin(sdp, rblocks, |
418 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); | ||
418 | if (error) | 419 | if (error) |
419 | goto out_trans_fail; | 420 | goto out_trans_fail; |
420 | 421 | ||
@@ -616,58 +617,50 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock) | |||
616 | return dblock; | 617 | return dblock; |
617 | } | 618 | } |
618 | 619 | ||
619 | static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh) | 620 | static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh) |
620 | { | 621 | { |
621 | struct gfs2_bufdata *bd; | 622 | struct gfs2_bufdata *bd; |
622 | 623 | ||
624 | lock_buffer(bh); | ||
623 | gfs2_log_lock(sdp); | 625 | gfs2_log_lock(sdp); |
626 | clear_buffer_dirty(bh); | ||
624 | bd = bh->b_private; | 627 | bd = bh->b_private; |
625 | if (bd) { | 628 | if (bd) { |
626 | bd->bd_bh = NULL; | 629 | if (!list_empty(&bd->bd_le.le_list) && !buffer_pinned(bh)) |
627 | bh->b_private = NULL; | 630 | list_del_init(&bd->bd_le.le_list); |
628 | if (!bd->bd_ail && list_empty(&bd->bd_le.le_list)) | 631 | else |
629 | kmem_cache_free(gfs2_bufdata_cachep, bd); | 632 | gfs2_remove_from_journal(bh, current->journal_info, 0); |
630 | } | 633 | } |
631 | gfs2_log_unlock(sdp); | ||
632 | |||
633 | lock_buffer(bh); | ||
634 | clear_buffer_dirty(bh); | ||
635 | bh->b_bdev = NULL; | 634 | bh->b_bdev = NULL; |
636 | clear_buffer_mapped(bh); | 635 | clear_buffer_mapped(bh); |
637 | clear_buffer_req(bh); | 636 | clear_buffer_req(bh); |
638 | clear_buffer_new(bh); | 637 | clear_buffer_new(bh); |
639 | clear_buffer_delay(bh); | 638 | gfs2_log_unlock(sdp); |
640 | unlock_buffer(bh); | 639 | unlock_buffer(bh); |
641 | } | 640 | } |
642 | 641 | ||
643 | static void gfs2_invalidatepage(struct page *page, unsigned long offset) | 642 | static void gfs2_invalidatepage(struct page *page, unsigned long offset) |
644 | { | 643 | { |
645 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); | 644 | struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); |
646 | struct buffer_head *head, *bh, *next; | 645 | struct buffer_head *bh, *head; |
647 | unsigned int curr_off = 0; | 646 | unsigned long pos = 0; |
648 | 647 | ||
649 | BUG_ON(!PageLocked(page)); | 648 | BUG_ON(!PageLocked(page)); |
650 | if (offset == 0) | 649 | if (offset == 0) |
651 | ClearPageChecked(page); | 650 | ClearPageChecked(page); |
652 | if (!page_has_buffers(page)) | 651 | if (!page_has_buffers(page)) |
653 | return; | 652 | goto out; |
654 | 653 | ||
655 | bh = head = page_buffers(page); | 654 | bh = head = page_buffers(page); |
656 | do { | 655 | do { |
657 | unsigned int next_off = curr_off + bh->b_size; | 656 | if (offset <= pos) |
658 | next = bh->b_this_page; | 657 | gfs2_discard(sdp, bh); |
659 | 658 | pos += bh->b_size; | |
660 | if (offset <= curr_off) | 659 | bh = bh->b_this_page; |
661 | discard_buffer(sdp, bh); | ||
662 | |||
663 | curr_off = next_off; | ||
664 | bh = next; | ||
665 | } while (bh != head); | 660 | } while (bh != head); |
666 | 661 | out: | |
667 | if (!offset) | 662 | if (offset == 0) |
668 | try_to_release_page(page, 0); | 663 | try_to_release_page(page, 0); |
669 | |||
670 | return; | ||
671 | } | 664 | } |
672 | 665 | ||
673 | /** | 666 | /** |
@@ -736,59 +729,6 @@ out: | |||
736 | } | 729 | } |
737 | 730 | ||
738 | /** | 731 | /** |
739 | * stuck_releasepage - We're stuck in gfs2_releasepage(). Print stuff out. | ||
740 | * @bh: the buffer we're stuck on | ||
741 | * | ||
742 | */ | ||
743 | |||
744 | static void stuck_releasepage(struct buffer_head *bh) | ||
745 | { | ||
746 | struct inode *inode = bh->b_page->mapping->host; | ||
747 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | ||
748 | struct gfs2_bufdata *bd = bh->b_private; | ||
749 | struct gfs2_glock *gl; | ||
750 | static unsigned limit = 0; | ||
751 | |||
752 | if (limit > 3) | ||
753 | return; | ||
754 | limit++; | ||
755 | |||
756 | fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode); | ||
757 | fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n", | ||
758 | (unsigned long long)bh->b_blocknr, atomic_read(&bh->b_count)); | ||
759 | fs_warn(sdp, "pinned = %u\n", buffer_pinned(bh)); | ||
760 | fs_warn(sdp, "bh->b_private = %s\n", (bd) ? "!NULL" : "NULL"); | ||
761 | |||
762 | if (!bd) | ||
763 | return; | ||
764 | |||
765 | gl = bd->bd_gl; | ||
766 | |||
767 | fs_warn(sdp, "gl = (%u, %llu)\n", | ||
768 | gl->gl_name.ln_type, (unsigned long long)gl->gl_name.ln_number); | ||
769 | |||
770 | fs_warn(sdp, "bd_list_tr = %s, bd_le.le_list = %s\n", | ||
771 | (list_empty(&bd->bd_list_tr)) ? "no" : "yes", | ||
772 | (list_empty(&bd->bd_le.le_list)) ? "no" : "yes"); | ||
773 | |||
774 | if (gl->gl_ops == &gfs2_inode_glops) { | ||
775 | struct gfs2_inode *ip = gl->gl_object; | ||
776 | unsigned int x; | ||
777 | |||
778 | if (!ip) | ||
779 | return; | ||
780 | |||
781 | fs_warn(sdp, "ip = %llu %llu\n", | ||
782 | (unsigned long long)ip->i_no_formal_ino, | ||
783 | (unsigned long long)ip->i_no_addr); | ||
784 | |||
785 | for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) | ||
786 | fs_warn(sdp, "ip->i_cache[%u] = %s\n", | ||
787 | x, (ip->i_cache[x]) ? "!NULL" : "NULL"); | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /** | ||
792 | * gfs2_releasepage - free the metadata associated with a page | 732 | * gfs2_releasepage - free the metadata associated with a page |
793 | * @page: the page that's being released | 733 | * @page: the page that's being released |
794 | * @gfp_mask: passed from Linux VFS, ignored by us | 734 | * @gfp_mask: passed from Linux VFS, ignored by us |
@@ -805,41 +745,39 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
805 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 745 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; |
806 | struct buffer_head *bh, *head; | 746 | struct buffer_head *bh, *head; |
807 | struct gfs2_bufdata *bd; | 747 | struct gfs2_bufdata *bd; |
808 | unsigned long t = jiffies + gfs2_tune_get(sdp, gt_stall_secs) * HZ; | ||
809 | 748 | ||
810 | if (!page_has_buffers(page)) | 749 | if (!page_has_buffers(page)) |
811 | goto out; | 750 | return 0; |
812 | 751 | ||
752 | gfs2_log_lock(sdp); | ||
813 | head = bh = page_buffers(page); | 753 | head = bh = page_buffers(page); |
814 | do { | 754 | do { |
815 | while (atomic_read(&bh->b_count)) { | 755 | if (atomic_read(&bh->b_count)) |
816 | if (!atomic_read(&aspace->i_writecount)) | 756 | goto cannot_release; |
817 | return 0; | 757 | bd = bh->b_private; |
818 | 758 | if (bd && bd->bd_ail) | |
819 | if (!(gfp_mask & __GFP_WAIT)) | 759 | goto cannot_release; |
820 | return 0; | ||
821 | |||
822 | if (time_after_eq(jiffies, t)) { | ||
823 | stuck_releasepage(bh); | ||
824 | /* should we withdraw here? */ | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | yield(); | ||
829 | } | ||
830 | |||
831 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); | 760 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); |
832 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); | 761 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); |
762 | bh = bh->b_this_page; | ||
763 | } while(bh != head); | ||
764 | gfs2_log_unlock(sdp); | ||
833 | 765 | ||
766 | head = bh = page_buffers(page); | ||
767 | do { | ||
834 | gfs2_log_lock(sdp); | 768 | gfs2_log_lock(sdp); |
835 | bd = bh->b_private; | 769 | bd = bh->b_private; |
836 | if (bd) { | 770 | if (bd) { |
837 | gfs2_assert_warn(sdp, bd->bd_bh == bh); | 771 | gfs2_assert_warn(sdp, bd->bd_bh == bh); |
838 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); | 772 | gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr)); |
839 | gfs2_assert_warn(sdp, !bd->bd_ail); | 773 | if (!list_empty(&bd->bd_le.le_list)) { |
840 | bd->bd_bh = NULL; | 774 | if (!buffer_pinned(bh)) |
841 | if (!list_empty(&bd->bd_le.le_list)) | 775 | list_del_init(&bd->bd_le.le_list); |
842 | bd = NULL; | 776 | else |
777 | bd = NULL; | ||
778 | } | ||
779 | if (bd) | ||
780 | bd->bd_bh = NULL; | ||
843 | bh->b_private = NULL; | 781 | bh->b_private = NULL; |
844 | } | 782 | } |
845 | gfs2_log_unlock(sdp); | 783 | gfs2_log_unlock(sdp); |
@@ -849,8 +787,10 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
849 | bh = bh->b_this_page; | 787 | bh = bh->b_this_page; |
850 | } while (bh != head); | 788 | } while (bh != head); |
851 | 789 | ||
852 | out: | ||
853 | return try_to_free_buffers(page); | 790 | return try_to_free_buffers(page); |
791 | cannot_release: | ||
792 | gfs2_log_unlock(sdp); | ||
793 | return 0; | ||
854 | } | 794 | } |
855 | 795 | ||
856 | const struct address_space_operations gfs2_file_aops = { | 796 | const struct address_space_operations gfs2_file_aops = { |
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index b8312edee0e4..e2d1347796a9 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
@@ -237,7 +237,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) | |||
237 | 237 | ||
238 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, | 238 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, |
239 | inum->no_addr, | 239 | inum->no_addr, |
240 | 0); | 240 | 0, 0); |
241 | if (!inode) | 241 | if (!inode) |
242 | goto fail; | 242 | goto fail; |
243 | if (IS_ERR(inode)) { | 243 | if (IS_ERR(inode)) { |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 94d76ace0b95..46a9e10ff17b 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -571,7 +571,8 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) | |||
571 | int error = 0; | 571 | int error = 0; |
572 | 572 | ||
573 | state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; | 573 | state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; |
574 | flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; | 574 | flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE |
575 | | GL_FLOCK; | ||
575 | 576 | ||
576 | mutex_lock(&fp->f_fl_mutex); | 577 | mutex_lock(&fp->f_fl_mutex); |
577 | 578 | ||
@@ -579,21 +580,19 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) | |||
579 | if (gl) { | 580 | if (gl) { |
580 | if (fl_gh->gh_state == state) | 581 | if (fl_gh->gh_state == state) |
581 | goto out; | 582 | goto out; |
582 | gfs2_glock_hold(gl); | ||
583 | flock_lock_file_wait(file, | 583 | flock_lock_file_wait(file, |
584 | &(struct file_lock){.fl_type = F_UNLCK}); | 584 | &(struct file_lock){.fl_type = F_UNLCK}); |
585 | gfs2_glock_dq_uninit(fl_gh); | 585 | gfs2_glock_dq_wait(fl_gh); |
586 | gfs2_holder_reinit(state, flags, fl_gh); | ||
586 | } else { | 587 | } else { |
587 | error = gfs2_glock_get(GFS2_SB(&ip->i_inode), | 588 | error = gfs2_glock_get(GFS2_SB(&ip->i_inode), |
588 | ip->i_no_addr, &gfs2_flock_glops, | 589 | ip->i_no_addr, &gfs2_flock_glops, |
589 | CREATE, &gl); | 590 | CREATE, &gl); |
590 | if (error) | 591 | if (error) |
591 | goto out; | 592 | goto out; |
593 | gfs2_holder_init(gl, state, flags, fl_gh); | ||
594 | gfs2_glock_put(gl); | ||
592 | } | 595 | } |
593 | |||
594 | gfs2_holder_init(gl, state, flags, fl_gh); | ||
595 | gfs2_glock_put(gl); | ||
596 | |||
597 | error = gfs2_glock_nq(fl_gh); | 596 | error = gfs2_glock_nq(fl_gh); |
598 | if (error) { | 597 | if (error) { |
599 | gfs2_holder_uninit(fl_gh); | 598 | gfs2_holder_uninit(fl_gh); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index cf5aa5050548..17de58e83d92 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -28,18 +28,18 @@ | |||
28 | #include "lm.h" | 28 | #include "lm.h" |
29 | #include "mount.h" | 29 | #include "mount.h" |
30 | #include "ops_fstype.h" | 30 | #include "ops_fstype.h" |
31 | #include "ops_dentry.h" | ||
31 | #include "ops_super.h" | 32 | #include "ops_super.h" |
32 | #include "recovery.h" | 33 | #include "recovery.h" |
33 | #include "rgrp.h" | 34 | #include "rgrp.h" |
34 | #include "super.h" | 35 | #include "super.h" |
35 | #include "sys.h" | 36 | #include "sys.h" |
36 | #include "util.h" | 37 | #include "util.h" |
38 | #include "log.h" | ||
37 | 39 | ||
38 | #define DO 0 | 40 | #define DO 0 |
39 | #define UNDO 1 | 41 | #define UNDO 1 |
40 | 42 | ||
41 | extern struct dentry_operations gfs2_dops; | ||
42 | |||
43 | static struct gfs2_sbd *init_sbd(struct super_block *sb) | 43 | static struct gfs2_sbd *init_sbd(struct super_block *sb) |
44 | { | 44 | { |
45 | struct gfs2_sbd *sdp; | 45 | struct gfs2_sbd *sdp; |
@@ -82,13 +82,15 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
82 | INIT_LIST_HEAD(&sdp->sd_log_le_revoke); | 82 | INIT_LIST_HEAD(&sdp->sd_log_le_revoke); |
83 | INIT_LIST_HEAD(&sdp->sd_log_le_rg); | 83 | INIT_LIST_HEAD(&sdp->sd_log_le_rg); |
84 | INIT_LIST_HEAD(&sdp->sd_log_le_databuf); | 84 | INIT_LIST_HEAD(&sdp->sd_log_le_databuf); |
85 | INIT_LIST_HEAD(&sdp->sd_log_le_ordered); | ||
85 | 86 | ||
86 | mutex_init(&sdp->sd_log_reserve_mutex); | 87 | mutex_init(&sdp->sd_log_reserve_mutex); |
87 | INIT_LIST_HEAD(&sdp->sd_ail1_list); | 88 | INIT_LIST_HEAD(&sdp->sd_ail1_list); |
88 | INIT_LIST_HEAD(&sdp->sd_ail2_list); | 89 | INIT_LIST_HEAD(&sdp->sd_ail2_list); |
89 | 90 | ||
90 | init_rwsem(&sdp->sd_log_flush_lock); | 91 | init_rwsem(&sdp->sd_log_flush_lock); |
91 | INIT_LIST_HEAD(&sdp->sd_log_flush_list); | 92 | atomic_set(&sdp->sd_log_in_flight, 0); |
93 | init_waitqueue_head(&sdp->sd_log_flush_wait); | ||
92 | 94 | ||
93 | INIT_LIST_HEAD(&sdp->sd_revoke_list); | 95 | INIT_LIST_HEAD(&sdp->sd_revoke_list); |
94 | 96 | ||
@@ -145,7 +147,8 @@ static int init_names(struct gfs2_sbd *sdp, int silent) | |||
145 | snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); | 147 | snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); |
146 | snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); | 148 | snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); |
147 | 149 | ||
148 | while ((table = strchr(sdp->sd_table_name, '/'))) | 150 | table = sdp->sd_table_name; |
151 | while ((table = strchr(table, '/'))) | ||
149 | *table = '_'; | 152 | *table = '_'; |
150 | 153 | ||
151 | out: | 154 | out: |
@@ -161,14 +164,6 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, | |||
161 | if (undo) | 164 | if (undo) |
162 | goto fail_trans; | 165 | goto fail_trans; |
163 | 166 | ||
164 | p = kthread_run(gfs2_scand, sdp, "gfs2_scand"); | ||
165 | error = IS_ERR(p); | ||
166 | if (error) { | ||
167 | fs_err(sdp, "can't start scand thread: %d\n", error); | ||
168 | return error; | ||
169 | } | ||
170 | sdp->sd_scand_process = p; | ||
171 | |||
172 | for (sdp->sd_glockd_num = 0; | 167 | for (sdp->sd_glockd_num = 0; |
173 | sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd; | 168 | sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd; |
174 | sdp->sd_glockd_num++) { | 169 | sdp->sd_glockd_num++) { |
@@ -229,14 +224,13 @@ fail: | |||
229 | while (sdp->sd_glockd_num--) | 224 | while (sdp->sd_glockd_num--) |
230 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); | 225 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); |
231 | 226 | ||
232 | kthread_stop(sdp->sd_scand_process); | ||
233 | return error; | 227 | return error; |
234 | } | 228 | } |
235 | 229 | ||
236 | static inline struct inode *gfs2_lookup_root(struct super_block *sb, | 230 | static inline struct inode *gfs2_lookup_root(struct super_block *sb, |
237 | u64 no_addr) | 231 | u64 no_addr) |
238 | { | 232 | { |
239 | return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); | 233 | return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); |
240 | } | 234 | } |
241 | 235 | ||
242 | static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) | 236 | static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) |
@@ -301,8 +295,9 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) | |||
301 | fs_err(sdp, "can't get root dentry\n"); | 295 | fs_err(sdp, "can't get root dentry\n"); |
302 | error = -ENOMEM; | 296 | error = -ENOMEM; |
303 | iput(inode); | 297 | iput(inode); |
304 | } | 298 | } else |
305 | sb->s_root->d_op = &gfs2_dops; | 299 | sb->s_root->d_op = &gfs2_dops; |
300 | |||
306 | out: | 301 | out: |
307 | gfs2_glock_dq_uninit(&sb_gh); | 302 | gfs2_glock_dq_uninit(&sb_gh); |
308 | return error; | 303 | return error; |
@@ -368,7 +363,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
368 | 363 | ||
369 | ip = GFS2_I(sdp->sd_jdesc->jd_inode); | 364 | ip = GFS2_I(sdp->sd_jdesc->jd_inode); |
370 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, | 365 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, |
371 | LM_FLAG_NOEXP | GL_EXACT, | 366 | LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE, |
372 | &sdp->sd_jinode_gh); | 367 | &sdp->sd_jinode_gh); |
373 | if (error) { | 368 | if (error) { |
374 | fs_err(sdp, "can't acquire journal inode glock: %d\n", | 369 | fs_err(sdp, "can't acquire journal inode glock: %d\n", |
@@ -818,7 +813,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name) | |||
818 | struct nameidata nd; | 813 | struct nameidata nd; |
819 | struct file_system_type *fstype; | 814 | struct file_system_type *fstype; |
820 | struct super_block *sb = NULL, *s; | 815 | struct super_block *sb = NULL, *s; |
821 | struct list_head *l; | ||
822 | int error; | 816 | int error; |
823 | 817 | ||
824 | error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); | 818 | error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); |
@@ -830,8 +824,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) | |||
830 | error = vfs_getattr(nd.mnt, nd.dentry, &stat); | 824 | error = vfs_getattr(nd.mnt, nd.dentry, &stat); |
831 | 825 | ||
832 | fstype = get_fs_type("gfs2"); | 826 | fstype = get_fs_type("gfs2"); |
833 | list_for_each(l, &fstype->fs_supers) { | 827 | list_for_each_entry(s, &fstype->fs_supers, s_instances) { |
834 | s = list_entry(l, struct super_block, s_instances); | ||
835 | if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || | 828 | if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || |
836 | (S_ISDIR(stat.mode) && s == nd.dentry->d_inode->i_sb)) { | 829 | (S_ISDIR(stat.mode) && s == nd.dentry->d_inode->i_sb)) { |
837 | sb = s; | 830 | sb = s; |
@@ -861,7 +854,7 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | |||
861 | error = -ENOENT; | 854 | error = -ENOENT; |
862 | goto error; | 855 | goto error; |
863 | } | 856 | } |
864 | sdp = (struct gfs2_sbd*) sb->s_fs_info; | 857 | sdp = sb->s_fs_info; |
865 | if (sdp->sd_vfs_meta) { | 858 | if (sdp->sd_vfs_meta) { |
866 | printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); | 859 | printk(KERN_WARNING "GFS2: gfs2meta mount already exists\n"); |
867 | error = -EBUSY; | 860 | error = -EBUSY; |
@@ -896,7 +889,10 @@ error: | |||
896 | 889 | ||
897 | static void gfs2_kill_sb(struct super_block *sb) | 890 | static void gfs2_kill_sb(struct super_block *sb) |
898 | { | 891 | { |
899 | gfs2_delete_debugfs_file(sb->s_fs_info); | 892 | if (sb->s_fs_info) { |
893 | gfs2_delete_debugfs_file(sb->s_fs_info); | ||
894 | gfs2_meta_syncfs(sb->s_fs_info); | ||
895 | } | ||
900 | kill_block_super(sb); | 896 | kill_block_super(sb); |
901 | } | 897 | } |
902 | 898 | ||
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 911c115b5c6c..291f0c7eaa3b 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -69,7 +69,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry, | |||
69 | mark_inode_dirty(inode); | 69 | mark_inode_dirty(inode); |
70 | break; | 70 | break; |
71 | } else if (PTR_ERR(inode) != -EEXIST || | 71 | } else if (PTR_ERR(inode) != -EEXIST || |
72 | (nd->intent.open.flags & O_EXCL)) { | 72 | (nd && (nd->intent.open.flags & O_EXCL))) { |
73 | gfs2_holder_uninit(ghs); | 73 | gfs2_holder_uninit(ghs); |
74 | return PTR_ERR(inode); | 74 | return PTR_ERR(inode); |
75 | } | 75 | } |
@@ -278,17 +278,25 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
278 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | 278 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); |
279 | 279 | ||
280 | 280 | ||
281 | error = gfs2_glock_nq_m(3, ghs); | 281 | error = gfs2_glock_nq(ghs); /* parent */ |
282 | if (error) | 282 | if (error) |
283 | goto out; | 283 | goto out_parent; |
284 | |||
285 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
286 | if (error) | ||
287 | goto out_child; | ||
288 | |||
289 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | ||
290 | if (error) | ||
291 | goto out_rgrp; | ||
284 | 292 | ||
285 | error = gfs2_unlink_ok(dip, &dentry->d_name, ip); | 293 | error = gfs2_unlink_ok(dip, &dentry->d_name, ip); |
286 | if (error) | 294 | if (error) |
287 | goto out_gunlock; | 295 | goto out_rgrp; |
288 | 296 | ||
289 | error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); | 297 | error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); |
290 | if (error) | 298 | if (error) |
291 | goto out_gunlock; | 299 | goto out_rgrp; |
292 | 300 | ||
293 | error = gfs2_dir_del(dip, &dentry->d_name); | 301 | error = gfs2_dir_del(dip, &dentry->d_name); |
294 | if (error) | 302 | if (error) |
@@ -298,12 +306,15 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
298 | 306 | ||
299 | out_end_trans: | 307 | out_end_trans: |
300 | gfs2_trans_end(sdp); | 308 | gfs2_trans_end(sdp); |
301 | out_gunlock: | 309 | gfs2_glock_dq(ghs + 2); |
302 | gfs2_glock_dq_m(3, ghs); | 310 | out_rgrp: |
303 | out: | ||
304 | gfs2_holder_uninit(ghs); | ||
305 | gfs2_holder_uninit(ghs + 1); | ||
306 | gfs2_holder_uninit(ghs + 2); | 311 | gfs2_holder_uninit(ghs + 2); |
312 | gfs2_glock_dq(ghs + 1); | ||
313 | out_child: | ||
314 | gfs2_holder_uninit(ghs + 1); | ||
315 | gfs2_glock_dq(ghs); | ||
316 | out_parent: | ||
317 | gfs2_holder_uninit(ghs); | ||
307 | gfs2_glock_dq_uninit(&ri_gh); | 318 | gfs2_glock_dq_uninit(&ri_gh); |
308 | return error; | 319 | return error; |
309 | } | 320 | } |
@@ -894,12 +905,17 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
894 | static int setattr_size(struct inode *inode, struct iattr *attr) | 905 | static int setattr_size(struct inode *inode, struct iattr *attr) |
895 | { | 906 | { |
896 | struct gfs2_inode *ip = GFS2_I(inode); | 907 | struct gfs2_inode *ip = GFS2_I(inode); |
908 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
897 | int error; | 909 | int error; |
898 | 910 | ||
899 | if (attr->ia_size != ip->i_di.di_size) { | 911 | if (attr->ia_size != ip->i_di.di_size) { |
900 | error = vmtruncate(inode, attr->ia_size); | 912 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
901 | if (error) | 913 | if (error) |
902 | return error; | 914 | return error; |
915 | error = vmtruncate(inode, attr->ia_size); | ||
916 | gfs2_trans_end(sdp); | ||
917 | if (error) | ||
918 | return error; | ||
903 | } | 919 | } |
904 | 920 | ||
905 | error = gfs2_truncatei(ip, attr->ia_size); | 921 | error = gfs2_truncatei(ip, attr->ia_size); |
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 603d940f1159..950f31460e8b 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -92,7 +92,6 @@ static void gfs2_put_super(struct super_block *sb) | |||
92 | kthread_stop(sdp->sd_recoverd_process); | 92 | kthread_stop(sdp->sd_recoverd_process); |
93 | while (sdp->sd_glockd_num--) | 93 | while (sdp->sd_glockd_num--) |
94 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); | 94 | kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]); |
95 | kthread_stop(sdp->sd_scand_process); | ||
96 | 95 | ||
97 | if (!(sb->s_flags & MS_RDONLY)) { | 96 | if (!(sb->s_flags & MS_RDONLY)) { |
98 | error = gfs2_make_fs_ro(sdp); | 97 | error = gfs2_make_fs_ro(sdp); |
@@ -456,12 +455,15 @@ static void gfs2_delete_inode(struct inode *inode) | |||
456 | } | 455 | } |
457 | 456 | ||
458 | error = gfs2_dinode_dealloc(ip); | 457 | error = gfs2_dinode_dealloc(ip); |
459 | /* | 458 | if (error) |
460 | * Must do this before unlock to avoid trying to write back | 459 | goto out_unlock; |
461 | * potentially dirty data now that inode no longer exists | 460 | |
462 | * on disk. | 461 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
463 | */ | 462 | if (error) |
463 | goto out_unlock; | ||
464 | /* Needs to be done before glock release & also in a transaction */ | ||
464 | truncate_inode_pages(&inode->i_data, 0); | 465 | truncate_inode_pages(&inode->i_data, 0); |
466 | gfs2_trans_end(sdp); | ||
465 | 467 | ||
466 | out_unlock: | 468 | out_unlock: |
467 | gfs2_glock_dq(&ip->i_iopen_gh); | 469 | gfs2_glock_dq(&ip->i_iopen_gh); |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 6e546ee8f3d4..addb51e0f135 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -70,6 +70,7 @@ struct gfs2_quota_host { | |||
70 | u64 qu_limit; | 70 | u64 qu_limit; |
71 | u64 qu_warn; | 71 | u64 qu_warn; |
72 | s64 qu_value; | 72 | s64 qu_value; |
73 | u32 qu_ll_next; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | struct gfs2_quota_change_host { | 76 | struct gfs2_quota_change_host { |
@@ -580,6 +581,7 @@ static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) | |||
580 | qu->qu_limit = be64_to_cpu(str->qu_limit); | 581 | qu->qu_limit = be64_to_cpu(str->qu_limit); |
581 | qu->qu_warn = be64_to_cpu(str->qu_warn); | 582 | qu->qu_warn = be64_to_cpu(str->qu_warn); |
582 | qu->qu_value = be64_to_cpu(str->qu_value); | 583 | qu->qu_value = be64_to_cpu(str->qu_value); |
584 | qu->qu_ll_next = be32_to_cpu(str->qu_ll_next); | ||
583 | } | 585 | } |
584 | 586 | ||
585 | static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) | 587 | static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) |
@@ -589,6 +591,7 @@ static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) | |||
589 | str->qu_limit = cpu_to_be64(qu->qu_limit); | 591 | str->qu_limit = cpu_to_be64(qu->qu_limit); |
590 | str->qu_warn = cpu_to_be64(qu->qu_warn); | 592 | str->qu_warn = cpu_to_be64(qu->qu_warn); |
591 | str->qu_value = cpu_to_be64(qu->qu_value); | 593 | str->qu_value = cpu_to_be64(qu->qu_value); |
594 | str->qu_ll_next = cpu_to_be32(qu->qu_ll_next); | ||
592 | memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); | 595 | memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); |
593 | } | 596 | } |
594 | 597 | ||
@@ -614,6 +617,16 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
614 | s64 value; | 617 | s64 value; |
615 | int err = -EIO; | 618 | int err = -EIO; |
616 | 619 | ||
620 | if (gfs2_is_stuffed(ip)) { | ||
621 | struct gfs2_alloc *al = NULL; | ||
622 | al = gfs2_alloc_get(ip); | ||
623 | /* just request 1 blk */ | ||
624 | al->al_requested = 1; | ||
625 | gfs2_inplace_reserve(ip); | ||
626 | gfs2_unstuff_dinode(ip, NULL); | ||
627 | gfs2_inplace_release(ip); | ||
628 | gfs2_alloc_put(ip); | ||
629 | } | ||
617 | page = grab_cache_page(mapping, index); | 630 | page = grab_cache_page(mapping, index); |
618 | if (!page) | 631 | if (!page) |
619 | return -ENOMEM; | 632 | return -ENOMEM; |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 5ada38c99a2c..beb6c7ac0086 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -469,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd) | |||
469 | }; | 469 | }; |
470 | 470 | ||
471 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, | 471 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, |
472 | LM_FLAG_NOEXP, &ji_gh); | 472 | LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh); |
473 | if (error) | 473 | if (error) |
474 | goto fail_gunlock_j; | 474 | goto fail_gunlock_j; |
475 | } else { | 475 | } else { |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index ce48c4594ec8..708c287e1d0e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "inode.h" | 31 | #include "inode.h" |
32 | 32 | ||
33 | #define BFITNOENT ((u32)~0) | 33 | #define BFITNOENT ((u32)~0) |
34 | #define NO_BLOCK ((u64)~0) | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * These routines are used by the resource group routines (rgrp.c) | 37 | * These routines are used by the resource group routines (rgrp.c) |
@@ -116,8 +117,7 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | |||
116 | * @buffer: the buffer that holds the bitmaps | 117 | * @buffer: the buffer that holds the bitmaps |
117 | * @buflen: the length (in bytes) of the buffer | 118 | * @buflen: the length (in bytes) of the buffer |
118 | * @goal: start search at this block's bit-pair (within @buffer) | 119 | * @goal: start search at this block's bit-pair (within @buffer) |
119 | * @old_state: GFS2_BLKST_XXX the state of the block we're looking for; | 120 | * @old_state: GFS2_BLKST_XXX the state of the block we're looking for. |
120 | * bit 0 = alloc(1)/free(0), bit 1 = meta(1)/data(0) | ||
121 | * | 121 | * |
122 | * Scope of @goal and returned block number is only within this bitmap buffer, | 122 | * Scope of @goal and returned block number is only within this bitmap buffer, |
123 | * not entire rgrp or filesystem. @buffer will be offset from the actual | 123 | * not entire rgrp or filesystem. @buffer will be offset from the actual |
@@ -137,9 +137,13 @@ static u32 gfs2_bitfit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | |||
137 | byte = buffer + (goal / GFS2_NBBY); | 137 | byte = buffer + (goal / GFS2_NBBY); |
138 | bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; | 138 | bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; |
139 | end = buffer + buflen; | 139 | end = buffer + buflen; |
140 | alloc = (old_state & 1) ? 0 : 0x55; | 140 | alloc = (old_state == GFS2_BLKST_FREE) ? 0x55 : 0; |
141 | 141 | ||
142 | while (byte < end) { | 142 | while (byte < end) { |
143 | /* If we're looking for a free block we can eliminate all | ||
144 | bitmap settings with 0x55, which represents four data | ||
145 | blocks in a row. If we're looking for a data block, we can | ||
146 | eliminate 0x00 which corresponds to four free blocks. */ | ||
143 | if ((*byte & 0x55) == alloc) { | 147 | if ((*byte & 0x55) == alloc) { |
144 | blk += (8 - bit) >> 1; | 148 | blk += (8 - bit) >> 1; |
145 | 149 | ||
@@ -859,23 +863,28 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
859 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | 863 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) |
860 | { | 864 | { |
861 | struct inode *inode; | 865 | struct inode *inode; |
862 | u32 goal = 0; | 866 | u32 goal = 0, block; |
863 | u64 no_addr; | 867 | u64 no_addr; |
868 | struct gfs2_sbd *sdp = rgd->rd_sbd; | ||
864 | 869 | ||
865 | for(;;) { | 870 | for(;;) { |
866 | if (goal >= rgd->rd_data) | 871 | if (goal >= rgd->rd_data) |
867 | break; | 872 | break; |
868 | goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, | 873 | down_write(&sdp->sd_log_flush_lock); |
869 | GFS2_BLKST_UNLINKED); | 874 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, |
870 | if (goal == BFITNOENT) | 875 | GFS2_BLKST_UNLINKED); |
876 | up_write(&sdp->sd_log_flush_lock); | ||
877 | if (block == BFITNOENT) | ||
871 | break; | 878 | break; |
872 | no_addr = goal + rgd->rd_data0; | 879 | /* rgblk_search can return a block < goal, so we need to |
880 | keep it marching forward. */ | ||
881 | no_addr = block + rgd->rd_data0; | ||
873 | goal++; | 882 | goal++; |
874 | if (no_addr < *last_unlinked) | 883 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
875 | continue; | 884 | continue; |
876 | *last_unlinked = no_addr; | 885 | *last_unlinked = no_addr; |
877 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 886 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, |
878 | no_addr, -1); | 887 | no_addr, -1, 1); |
879 | if (!IS_ERR(inode)) | 888 | if (!IS_ERR(inode)) |
880 | return inode; | 889 | return inode; |
881 | } | 890 | } |
@@ -1152,7 +1161,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1152 | struct gfs2_alloc *al = &ip->i_alloc; | 1161 | struct gfs2_alloc *al = &ip->i_alloc; |
1153 | struct inode *inode; | 1162 | struct inode *inode; |
1154 | int error = 0; | 1163 | int error = 0; |
1155 | u64 last_unlinked = 0; | 1164 | u64 last_unlinked = NO_BLOCK; |
1156 | 1165 | ||
1157 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1166 | if (gfs2_assert_warn(sdp, al->al_requested)) |
1158 | return -EINVAL; | 1167 | return -EINVAL; |
@@ -1289,7 +1298,9 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1289 | allocatable block anywhere else, we want to be able wrap around and | 1298 | allocatable block anywhere else, we want to be able wrap around and |
1290 | search in the first part of our first-searched bit block. */ | 1299 | search in the first part of our first-searched bit block. */ |
1291 | for (x = 0; x <= length; x++) { | 1300 | for (x = 0; x <= length; x++) { |
1292 | if (bi->bi_clone) | 1301 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone |
1302 | bitmaps, so we must search the originals for that. */ | ||
1303 | if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) | ||
1293 | blk = gfs2_bitfit(rgd, bi->bi_clone + bi->bi_offset, | 1304 | blk = gfs2_bitfit(rgd, bi->bi_clone + bi->bi_offset, |
1294 | bi->bi_len, goal, old_state); | 1305 | bi->bi_len, goal, old_state); |
1295 | else | 1306 | else |
@@ -1305,9 +1316,7 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1305 | goal = 0; | 1316 | goal = 0; |
1306 | } | 1317 | } |
1307 | 1318 | ||
1308 | if (old_state != new_state) { | 1319 | if (blk != BFITNOENT && old_state != new_state) { |
1309 | gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT); | ||
1310 | |||
1311 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1320 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1312 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, | 1321 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, |
1313 | bi->bi_len, blk, new_state); | 1322 | bi->bi_len, blk, new_state); |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a2da76b5ae4c..dd3e737f528e 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -58,7 +58,6 @@ void gfs2_tune_init(struct gfs2_tune *gt) | |||
58 | gt->gt_incore_log_blocks = 1024; | 58 | gt->gt_incore_log_blocks = 1024; |
59 | gt->gt_log_flush_secs = 60; | 59 | gt->gt_log_flush_secs = 60; |
60 | gt->gt_jindex_refresh_secs = 60; | 60 | gt->gt_jindex_refresh_secs = 60; |
61 | gt->gt_scand_secs = 15; | ||
62 | gt->gt_recoverd_secs = 60; | 61 | gt->gt_recoverd_secs = 60; |
63 | gt->gt_logd_secs = 1; | 62 | gt->gt_logd_secs = 1; |
64 | gt->gt_quotad_secs = 5; | 63 | gt->gt_quotad_secs = 5; |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 640cb6a6fc4c..06e0b7768d97 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -441,7 +441,6 @@ TUNE_ATTR(quota_simul_sync, 1); | |||
441 | TUNE_ATTR(quota_cache_secs, 1); | 441 | TUNE_ATTR(quota_cache_secs, 1); |
442 | TUNE_ATTR(stall_secs, 1); | 442 | TUNE_ATTR(stall_secs, 1); |
443 | TUNE_ATTR(statfs_quantum, 1); | 443 | TUNE_ATTR(statfs_quantum, 1); |
444 | TUNE_ATTR_DAEMON(scand_secs, scand_process); | ||
445 | TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); | 444 | TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); |
446 | TUNE_ATTR_DAEMON(logd_secs, logd_process); | 445 | TUNE_ATTR_DAEMON(logd_secs, logd_process); |
447 | TUNE_ATTR_DAEMON(quotad_secs, quotad_process); | 446 | TUNE_ATTR_DAEMON(quotad_secs, quotad_process); |
@@ -463,7 +462,6 @@ static struct attribute *tune_attrs[] = { | |||
463 | &tune_attr_quota_cache_secs.attr, | 462 | &tune_attr_quota_cache_secs.attr, |
464 | &tune_attr_stall_secs.attr, | 463 | &tune_attr_stall_secs.attr, |
465 | &tune_attr_statfs_quantum.attr, | 464 | &tune_attr_statfs_quantum.attr, |
466 | &tune_attr_scand_secs.attr, | ||
467 | &tune_attr_recoverd_secs.attr, | 465 | &tune_attr_recoverd_secs.attr, |
468 | &tune_attr_logd_secs.attr, | 466 | &tune_attr_logd_secs.attr, |
469 | &tune_attr_quotad_secs.attr, | 467 | &tune_attr_quotad_secs.attr, |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index f8dabf8446bb..717983e2c2ae 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
@@ -142,25 +142,25 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) | |||
142 | lops_add(sdp, &bd->bd_le); | 142 | lops_add(sdp, &bd->bd_le); |
143 | } | 143 | } |
144 | 144 | ||
145 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, u64 blkno) | 145 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) |
146 | { | 146 | { |
147 | struct gfs2_revoke *rv = kmalloc(sizeof(struct gfs2_revoke), | 147 | BUG_ON(!list_empty(&bd->bd_le.le_list)); |
148 | GFP_NOFS | __GFP_NOFAIL); | 148 | BUG_ON(!list_empty(&bd->bd_ail_st_list)); |
149 | lops_init_le(&rv->rv_le, &gfs2_revoke_lops); | 149 | BUG_ON(!list_empty(&bd->bd_ail_gl_list)); |
150 | rv->rv_blkno = blkno; | 150 | lops_init_le(&bd->bd_le, &gfs2_revoke_lops); |
151 | lops_add(sdp, &rv->rv_le); | 151 | lops_add(sdp, &bd->bd_le); |
152 | } | 152 | } |
153 | 153 | ||
154 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) | 154 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) |
155 | { | 155 | { |
156 | struct gfs2_revoke *rv; | 156 | struct gfs2_bufdata *bd; |
157 | int found = 0; | 157 | int found = 0; |
158 | 158 | ||
159 | gfs2_log_lock(sdp); | 159 | gfs2_log_lock(sdp); |
160 | 160 | ||
161 | list_for_each_entry(rv, &sdp->sd_log_le_revoke, rv_le.le_list) { | 161 | list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) { |
162 | if (rv->rv_blkno == blkno) { | 162 | if (bd->bd_blkno == blkno) { |
163 | list_del(&rv->rv_le.le_list); | 163 | list_del_init(&bd->bd_le.le_list); |
164 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); | 164 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); |
165 | sdp->sd_log_num_revoke--; | 165 | sdp->sd_log_num_revoke--; |
166 | found = 1; | 166 | found = 1; |
@@ -172,7 +172,7 @@ void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) | |||
172 | 172 | ||
173 | if (found) { | 173 | if (found) { |
174 | struct gfs2_trans *tr = current->journal_info; | 174 | struct gfs2_trans *tr = current->journal_info; |
175 | kfree(rv); | 175 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
176 | tr->tr_num_revoke_rm++; | 176 | tr->tr_num_revoke_rm++; |
177 | } | 177 | } |
178 | } | 178 | } |
diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h index 23d4cbe1de5b..043d5f4b9c4c 100644 --- a/fs/gfs2/trans.h +++ b/fs/gfs2/trans.h | |||
@@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp); | |||
32 | 32 | ||
33 | void gfs2_trans_add_gl(struct gfs2_glock *gl); | 33 | void gfs2_trans_add_gl(struct gfs2_glock *gl); |
34 | void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); | 34 | void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); |
35 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, u64 blkno); | 35 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); |
36 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno); | 36 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno); |
37 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd); | 37 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd); |
38 | 38 | ||
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index af4ef808fa94..345798ebd366 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -17,6 +17,18 @@ ToDo/Notes: | |||
17 | happen is unclear however so it is worth waiting until someone hits | 17 | happen is unclear however so it is worth waiting until someone hits |
18 | the problem. | 18 | the problem. |
19 | 19 | ||
20 | 2.1.29 - Fix a deadlock at mount time. | ||
21 | |||
22 | - During mount the VFS holds s_umount lock on the superblock. So when | ||
23 | we try to empty the journal $LogFile contents by calling | ||
24 | ntfs_attr_set() when the machine does not have much memory and the | ||
25 | journal is large ntfs_attr_set() results in the VM trying to balance | ||
26 | dirty pages which in turn tries to that the s_umount lock and thus we | ||
27 | get a deadlock. The solution is to not use ntfs_attr_set() and | ||
28 | instead do the zeroing by hand at the block level rather than page | ||
29 | cache level. | ||
30 | - Fix sparse warnings. | ||
31 | |||
20 | 2.1.28 - Fix a deadlock. | 32 | 2.1.28 - Fix a deadlock. |
21 | 33 | ||
22 | - Fix deadlock in fs/ntfs/inode.c::ntfs_put_inode(). Thanks to Sergey | 34 | - Fix deadlock in fs/ntfs/inode.c::ntfs_put_inode(). Thanks to Sergey |
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 825508385565..58b6be992544 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile | |||
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ | |||
6 | index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ | 6 | index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ |
7 | unistr.o upcase.o | 7 | unistr.o upcase.o |
8 | 8 | ||
9 | EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.28\" | 9 | EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.29\" |
10 | 10 | ||
11 | ifeq ($(CONFIG_NTFS_DEBUG),y) | 11 | ifeq ($(CONFIG_NTFS_DEBUG),y) |
12 | EXTRA_CFLAGS += -DDEBUG | 12 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 6e5c2534f4bc..cfdc7900d271 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * aops.c - NTFS kernel address space operations and page cache handling. | 2 | * aops.c - NTFS kernel address space operations and page cache handling. |
3 | * Part of the Linux-NTFS project. | 3 | * Part of the Linux-NTFS project. |
4 | * | 4 | * |
5 | * Copyright (c) 2001-2006 Anton Altaparmakov | 5 | * Copyright (c) 2001-2007 Anton Altaparmakov |
6 | * Copyright (c) 2002 Richard Russon | 6 | * Copyright (c) 2002 Richard Russon |
7 | * | 7 | * |
8 | * This program/include file is free software; you can redistribute it and/or | 8 | * This program/include file is free software; you can redistribute it and/or |
@@ -396,7 +396,7 @@ static int ntfs_readpage(struct file *file, struct page *page) | |||
396 | loff_t i_size; | 396 | loff_t i_size; |
397 | struct inode *vi; | 397 | struct inode *vi; |
398 | ntfs_inode *ni, *base_ni; | 398 | ntfs_inode *ni, *base_ni; |
399 | u8 *kaddr; | 399 | u8 *addr; |
400 | ntfs_attr_search_ctx *ctx; | 400 | ntfs_attr_search_ctx *ctx; |
401 | MFT_RECORD *mrec; | 401 | MFT_RECORD *mrec; |
402 | unsigned long flags; | 402 | unsigned long flags; |
@@ -491,15 +491,15 @@ retry_readpage: | |||
491 | /* Race with shrinking truncate. */ | 491 | /* Race with shrinking truncate. */ |
492 | attr_len = i_size; | 492 | attr_len = i_size; |
493 | } | 493 | } |
494 | kaddr = kmap_atomic(page, KM_USER0); | 494 | addr = kmap_atomic(page, KM_USER0); |
495 | /* Copy the data to the page. */ | 495 | /* Copy the data to the page. */ |
496 | memcpy(kaddr, (u8*)ctx->attr + | 496 | memcpy(addr, (u8*)ctx->attr + |
497 | le16_to_cpu(ctx->attr->data.resident.value_offset), | 497 | le16_to_cpu(ctx->attr->data.resident.value_offset), |
498 | attr_len); | 498 | attr_len); |
499 | /* Zero the remainder of the page. */ | 499 | /* Zero the remainder of the page. */ |
500 | memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); | 500 | memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); |
501 | flush_dcache_page(page); | 501 | flush_dcache_page(page); |
502 | kunmap_atomic(kaddr, KM_USER0); | 502 | kunmap_atomic(addr, KM_USER0); |
503 | put_unm_err_out: | 503 | put_unm_err_out: |
504 | ntfs_attr_put_search_ctx(ctx); | 504 | ntfs_attr_put_search_ctx(ctx); |
505 | unm_err_out: | 505 | unm_err_out: |
@@ -1344,7 +1344,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) | |||
1344 | loff_t i_size; | 1344 | loff_t i_size; |
1345 | struct inode *vi = page->mapping->host; | 1345 | struct inode *vi = page->mapping->host; |
1346 | ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi); | 1346 | ntfs_inode *base_ni = NULL, *ni = NTFS_I(vi); |
1347 | char *kaddr; | 1347 | char *addr; |
1348 | ntfs_attr_search_ctx *ctx = NULL; | 1348 | ntfs_attr_search_ctx *ctx = NULL; |
1349 | MFT_RECORD *m = NULL; | 1349 | MFT_RECORD *m = NULL; |
1350 | u32 attr_len; | 1350 | u32 attr_len; |
@@ -1484,14 +1484,14 @@ retry_writepage: | |||
1484 | /* Shrinking cannot fail. */ | 1484 | /* Shrinking cannot fail. */ |
1485 | BUG_ON(err); | 1485 | BUG_ON(err); |
1486 | } | 1486 | } |
1487 | kaddr = kmap_atomic(page, KM_USER0); | 1487 | addr = kmap_atomic(page, KM_USER0); |
1488 | /* Copy the data from the page to the mft record. */ | 1488 | /* Copy the data from the page to the mft record. */ |
1489 | memcpy((u8*)ctx->attr + | 1489 | memcpy((u8*)ctx->attr + |
1490 | le16_to_cpu(ctx->attr->data.resident.value_offset), | 1490 | le16_to_cpu(ctx->attr->data.resident.value_offset), |
1491 | kaddr, attr_len); | 1491 | addr, attr_len); |
1492 | /* Zero out of bounds area in the page cache page. */ | 1492 | /* Zero out of bounds area in the page cache page. */ |
1493 | memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); | 1493 | memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); |
1494 | kunmap_atomic(kaddr, KM_USER0); | 1494 | kunmap_atomic(addr, KM_USER0); |
1495 | flush_dcache_page(page); | 1495 | flush_dcache_page(page); |
1496 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1496 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
1497 | /* We are done with the page. */ | 1497 | /* We are done with the page. */ |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1c08fefe487a..92dabdcf2b80 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. | 2 | * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2006 Anton Altaparmakov | 4 | * Copyright (c) 2001-2007 Anton Altaparmakov |
5 | * Copyright (c) 2002 Richard Russon | 5 | * Copyright (c) 2002 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
@@ -2500,7 +2500,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
2500 | struct page *page; | 2500 | struct page *page; |
2501 | u8 *kaddr; | 2501 | u8 *kaddr; |
2502 | pgoff_t idx, end; | 2502 | pgoff_t idx, end; |
2503 | unsigned int start_ofs, end_ofs, size; | 2503 | unsigned start_ofs, end_ofs, size; |
2504 | 2504 | ||
2505 | ntfs_debug("Entering for ofs 0x%llx, cnt 0x%llx, val 0x%hx.", | 2505 | ntfs_debug("Entering for ofs 0x%llx, cnt 0x%llx, val 0x%hx.", |
2506 | (long long)ofs, (long long)cnt, val); | 2506 | (long long)ofs, (long long)cnt, val); |
@@ -2548,6 +2548,8 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
2548 | kunmap_atomic(kaddr, KM_USER0); | 2548 | kunmap_atomic(kaddr, KM_USER0); |
2549 | set_page_dirty(page); | 2549 | set_page_dirty(page); |
2550 | page_cache_release(page); | 2550 | page_cache_release(page); |
2551 | balance_dirty_pages_ratelimited(mapping); | ||
2552 | cond_resched(); | ||
2551 | if (idx == end) | 2553 | if (idx == end) |
2552 | goto done; | 2554 | goto done; |
2553 | idx++; | 2555 | idx++; |
@@ -2604,6 +2606,8 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
2604 | kunmap_atomic(kaddr, KM_USER0); | 2606 | kunmap_atomic(kaddr, KM_USER0); |
2605 | set_page_dirty(page); | 2607 | set_page_dirty(page); |
2606 | page_cache_release(page); | 2608 | page_cache_release(page); |
2609 | balance_dirty_pages_ratelimited(mapping); | ||
2610 | cond_resched(); | ||
2607 | } | 2611 | } |
2608 | done: | 2612 | done: |
2609 | ntfs_debug("Done."); | 2613 | ntfs_debug("Done."); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index ffcc504a1667..c814204d4ea0 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * file.c - NTFS kernel file operations. Part of the Linux-NTFS project. | 2 | * file.c - NTFS kernel file operations. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2006 Anton Altaparmakov | 4 | * Copyright (c) 2001-2007 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/swap.h> | 26 | #include <linux/swap.h> |
27 | #include <linux/uio.h> | 27 | #include <linux/uio.h> |
28 | #include <linux/writeback.h> | 28 | #include <linux/writeback.h> |
29 | #include <linux/sched.h> | ||
30 | 29 | ||
31 | #include <asm/page.h> | 30 | #include <asm/page.h> |
32 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -362,7 +361,7 @@ static inline void ntfs_fault_in_pages_readable(const char __user *uaddr, | |||
362 | volatile char c; | 361 | volatile char c; |
363 | 362 | ||
364 | /* Set @end to the first byte outside the last page we care about. */ | 363 | /* Set @end to the first byte outside the last page we care about. */ |
365 | end = (const char __user*)PAGE_ALIGN((ptrdiff_t __user)uaddr + bytes); | 364 | end = (const char __user*)PAGE_ALIGN((unsigned long)uaddr + bytes); |
366 | 365 | ||
367 | while (!__get_user(c, uaddr) && (uaddr += PAGE_SIZE, uaddr < end)) | 366 | while (!__get_user(c, uaddr) && (uaddr += PAGE_SIZE, uaddr < end)) |
368 | ; | 367 | ; |
@@ -532,7 +531,8 @@ static int ntfs_prepare_pages_for_non_resident_write(struct page **pages, | |||
532 | blocksize_bits = vol->sb->s_blocksize_bits; | 531 | blocksize_bits = vol->sb->s_blocksize_bits; |
533 | u = 0; | 532 | u = 0; |
534 | do { | 533 | do { |
535 | struct page *page = pages[u]; | 534 | page = pages[u]; |
535 | BUG_ON(!page); | ||
536 | /* | 536 | /* |
537 | * create_empty_buffers() will create uptodate/dirty buffers if | 537 | * create_empty_buffers() will create uptodate/dirty buffers if |
538 | * the page is uptodate/dirty. | 538 | * the page is uptodate/dirty. |
@@ -1291,7 +1291,7 @@ static inline size_t ntfs_copy_from_user(struct page **pages, | |||
1291 | size_t bytes) | 1291 | size_t bytes) |
1292 | { | 1292 | { |
1293 | struct page **last_page = pages + nr_pages; | 1293 | struct page **last_page = pages + nr_pages; |
1294 | char *kaddr; | 1294 | char *addr; |
1295 | size_t total = 0; | 1295 | size_t total = 0; |
1296 | unsigned len; | 1296 | unsigned len; |
1297 | int left; | 1297 | int left; |
@@ -1300,13 +1300,13 @@ static inline size_t ntfs_copy_from_user(struct page **pages, | |||
1300 | len = PAGE_CACHE_SIZE - ofs; | 1300 | len = PAGE_CACHE_SIZE - ofs; |
1301 | if (len > bytes) | 1301 | if (len > bytes) |
1302 | len = bytes; | 1302 | len = bytes; |
1303 | kaddr = kmap_atomic(*pages, KM_USER0); | 1303 | addr = kmap_atomic(*pages, KM_USER0); |
1304 | left = __copy_from_user_inatomic(kaddr + ofs, buf, len); | 1304 | left = __copy_from_user_inatomic(addr + ofs, buf, len); |
1305 | kunmap_atomic(kaddr, KM_USER0); | 1305 | kunmap_atomic(addr, KM_USER0); |
1306 | if (unlikely(left)) { | 1306 | if (unlikely(left)) { |
1307 | /* Do it the slow way. */ | 1307 | /* Do it the slow way. */ |
1308 | kaddr = kmap(*pages); | 1308 | addr = kmap(*pages); |
1309 | left = __copy_from_user(kaddr + ofs, buf, len); | 1309 | left = __copy_from_user(addr + ofs, buf, len); |
1310 | kunmap(*pages); | 1310 | kunmap(*pages); |
1311 | if (unlikely(left)) | 1311 | if (unlikely(left)) |
1312 | goto err_out; | 1312 | goto err_out; |
@@ -1408,26 +1408,26 @@ static inline size_t ntfs_copy_from_user_iovec(struct page **pages, | |||
1408 | size_t *iov_ofs, size_t bytes) | 1408 | size_t *iov_ofs, size_t bytes) |
1409 | { | 1409 | { |
1410 | struct page **last_page = pages + nr_pages; | 1410 | struct page **last_page = pages + nr_pages; |
1411 | char *kaddr; | 1411 | char *addr; |
1412 | size_t copied, len, total = 0; | 1412 | size_t copied, len, total = 0; |
1413 | 1413 | ||
1414 | do { | 1414 | do { |
1415 | len = PAGE_CACHE_SIZE - ofs; | 1415 | len = PAGE_CACHE_SIZE - ofs; |
1416 | if (len > bytes) | 1416 | if (len > bytes) |
1417 | len = bytes; | 1417 | len = bytes; |
1418 | kaddr = kmap_atomic(*pages, KM_USER0); | 1418 | addr = kmap_atomic(*pages, KM_USER0); |
1419 | copied = __ntfs_copy_from_user_iovec_inatomic(kaddr + ofs, | 1419 | copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs, |
1420 | *iov, *iov_ofs, len); | 1420 | *iov, *iov_ofs, len); |
1421 | kunmap_atomic(kaddr, KM_USER0); | 1421 | kunmap_atomic(addr, KM_USER0); |
1422 | if (unlikely(copied != len)) { | 1422 | if (unlikely(copied != len)) { |
1423 | /* Do it the slow way. */ | 1423 | /* Do it the slow way. */ |
1424 | kaddr = kmap(*pages); | 1424 | addr = kmap(*pages); |
1425 | copied = __ntfs_copy_from_user_iovec_inatomic(kaddr + ofs, | 1425 | copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs, |
1426 | *iov, *iov_ofs, len); | 1426 | *iov, *iov_ofs, len); |
1427 | /* | 1427 | /* |
1428 | * Zero the rest of the target like __copy_from_user(). | 1428 | * Zero the rest of the target like __copy_from_user(). |
1429 | */ | 1429 | */ |
1430 | memset(kaddr + ofs + copied, 0, len - copied); | 1430 | memset(addr + ofs + copied, 0, len - copied); |
1431 | kunmap(*pages); | 1431 | kunmap(*pages); |
1432 | if (unlikely(copied != len)) | 1432 | if (unlikely(copied != len)) |
1433 | goto err_out; | 1433 | goto err_out; |
@@ -1735,8 +1735,6 @@ static int ntfs_commit_pages_after_write(struct page **pages, | |||
1735 | read_unlock_irqrestore(&ni->size_lock, flags); | 1735 | read_unlock_irqrestore(&ni->size_lock, flags); |
1736 | BUG_ON(initialized_size != i_size); | 1736 | BUG_ON(initialized_size != i_size); |
1737 | if (end > initialized_size) { | 1737 | if (end > initialized_size) { |
1738 | unsigned long flags; | ||
1739 | |||
1740 | write_lock_irqsave(&ni->size_lock, flags); | 1738 | write_lock_irqsave(&ni->size_lock, flags); |
1741 | ni->initialized_size = end; | 1739 | ni->initialized_size = end; |
1742 | i_size_write(vi, end); | 1740 | i_size_write(vi, end); |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index b532a730cec2..e9da092e2772 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "dir.h" | 34 | #include "dir.h" |
35 | #include "debug.h" | 35 | #include "debug.h" |
36 | #include "inode.h" | 36 | #include "inode.h" |
37 | #include "attrib.h" | ||
38 | #include "lcnalloc.h" | 37 | #include "lcnalloc.h" |
39 | #include "malloc.h" | 38 | #include "malloc.h" |
40 | #include "mft.h" | 39 | #include "mft.h" |
@@ -2500,8 +2499,6 @@ retry_truncate: | |||
2500 | /* Resize the attribute record to best fit the new attribute size. */ | 2499 | /* Resize the attribute record to best fit the new attribute size. */ |
2501 | if (new_size < vol->mft_record_size && | 2500 | if (new_size < vol->mft_record_size && |
2502 | !ntfs_resident_attr_value_resize(m, a, new_size)) { | 2501 | !ntfs_resident_attr_value_resize(m, a, new_size)) { |
2503 | unsigned long flags; | ||
2504 | |||
2505 | /* The resize succeeded! */ | 2502 | /* The resize succeeded! */ |
2506 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 2503 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
2507 | mark_mft_record_dirty(ctx->ntfs_ino); | 2504 | mark_mft_record_dirty(ctx->ntfs_ino); |
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index acfed325f4ec..d7932e95b1fd 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * logfile.c - NTFS kernel journal handling. Part of the Linux-NTFS project. | 2 | * logfile.c - NTFS kernel journal handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2005 Anton Altaparmakov | 4 | * Copyright (c) 2002-2007 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -724,24 +724,139 @@ bool ntfs_is_logfile_clean(struct inode *log_vi, const RESTART_PAGE_HEADER *rp) | |||
724 | */ | 724 | */ |
725 | bool ntfs_empty_logfile(struct inode *log_vi) | 725 | bool ntfs_empty_logfile(struct inode *log_vi) |
726 | { | 726 | { |
727 | ntfs_volume *vol = NTFS_SB(log_vi->i_sb); | 727 | VCN vcn, end_vcn; |
728 | ntfs_inode *log_ni = NTFS_I(log_vi); | ||
729 | ntfs_volume *vol = log_ni->vol; | ||
730 | struct super_block *sb = vol->sb; | ||
731 | runlist_element *rl; | ||
732 | unsigned long flags; | ||
733 | unsigned block_size, block_size_bits; | ||
734 | int err; | ||
735 | bool should_wait = true; | ||
728 | 736 | ||
729 | ntfs_debug("Entering."); | 737 | ntfs_debug("Entering."); |
730 | if (!NVolLogFileEmpty(vol)) { | 738 | if (NVolLogFileEmpty(vol)) { |
731 | int err; | 739 | ntfs_debug("Done."); |
732 | 740 | return true; | |
733 | err = ntfs_attr_set(NTFS_I(log_vi), 0, i_size_read(log_vi), | ||
734 | 0xff); | ||
735 | if (unlikely(err)) { | ||
736 | ntfs_error(vol->sb, "Failed to fill $LogFile with " | ||
737 | "0xff bytes (error code %i).", err); | ||
738 | return false; | ||
739 | } | ||
740 | /* Set the flag so we do not have to do it again on remount. */ | ||
741 | NVolSetLogFileEmpty(vol); | ||
742 | } | 741 | } |
742 | /* | ||
743 | * We cannot use ntfs_attr_set() because we may be still in the middle | ||
744 | * of a mount operation. Thus we do the emptying by hand by first | ||
745 | * zapping the page cache pages for the $LogFile/$DATA attribute and | ||
746 | * then emptying each of the buffers in each of the clusters specified | ||
747 | * by the runlist by hand. | ||
748 | */ | ||
749 | block_size = sb->s_blocksize; | ||
750 | block_size_bits = sb->s_blocksize_bits; | ||
751 | vcn = 0; | ||
752 | read_lock_irqsave(&log_ni->size_lock, flags); | ||
753 | end_vcn = (log_ni->initialized_size + vol->cluster_size_mask) >> | ||
754 | vol->cluster_size_bits; | ||
755 | read_unlock_irqrestore(&log_ni->size_lock, flags); | ||
756 | truncate_inode_pages(log_vi->i_mapping, 0); | ||
757 | down_write(&log_ni->runlist.lock); | ||
758 | rl = log_ni->runlist.rl; | ||
759 | if (unlikely(!rl || vcn < rl->vcn || !rl->length)) { | ||
760 | map_vcn: | ||
761 | err = ntfs_map_runlist_nolock(log_ni, vcn, NULL); | ||
762 | if (err) { | ||
763 | ntfs_error(sb, "Failed to map runlist fragment (error " | ||
764 | "%d).", -err); | ||
765 | goto err; | ||
766 | } | ||
767 | rl = log_ni->runlist.rl; | ||
768 | BUG_ON(!rl || vcn < rl->vcn || !rl->length); | ||
769 | } | ||
770 | /* Seek to the runlist element containing @vcn. */ | ||
771 | while (rl->length && vcn >= rl[1].vcn) | ||
772 | rl++; | ||
773 | do { | ||
774 | LCN lcn; | ||
775 | sector_t block, end_block; | ||
776 | s64 len; | ||
777 | |||
778 | /* | ||
779 | * If this run is not mapped map it now and start again as the | ||
780 | * runlist will have been updated. | ||
781 | */ | ||
782 | lcn = rl->lcn; | ||
783 | if (unlikely(lcn == LCN_RL_NOT_MAPPED)) { | ||
784 | vcn = rl->vcn; | ||
785 | goto map_vcn; | ||
786 | } | ||
787 | /* If this run is not valid abort with an error. */ | ||
788 | if (unlikely(!rl->length || lcn < LCN_HOLE)) | ||
789 | goto rl_err; | ||
790 | /* Skip holes. */ | ||
791 | if (lcn == LCN_HOLE) | ||
792 | continue; | ||
793 | block = lcn << vol->cluster_size_bits >> block_size_bits; | ||
794 | len = rl->length; | ||
795 | if (rl[1].vcn > end_vcn) | ||
796 | len = end_vcn - rl->vcn; | ||
797 | end_block = (lcn + len) << vol->cluster_size_bits >> | ||
798 | block_size_bits; | ||
799 | /* Iterate over the blocks in the run and empty them. */ | ||
800 | do { | ||
801 | struct buffer_head *bh; | ||
802 | |||
803 | /* Obtain the buffer, possibly not uptodate. */ | ||
804 | bh = sb_getblk(sb, block); | ||
805 | BUG_ON(!bh); | ||
806 | /* Setup buffer i/o submission. */ | ||
807 | lock_buffer(bh); | ||
808 | bh->b_end_io = end_buffer_write_sync; | ||
809 | get_bh(bh); | ||
810 | /* Set the entire contents of the buffer to 0xff. */ | ||
811 | memset(bh->b_data, -1, block_size); | ||
812 | if (!buffer_uptodate(bh)) | ||
813 | set_buffer_uptodate(bh); | ||
814 | if (buffer_dirty(bh)) | ||
815 | clear_buffer_dirty(bh); | ||
816 | /* | ||
817 | * Submit the buffer and wait for i/o to complete but | ||
818 | * only for the first buffer so we do not miss really | ||
819 | * serious i/o errors. Once the first buffer has | ||
820 | * completed ignore errors afterwards as we can assume | ||
821 | * that if one buffer worked all of them will work. | ||
822 | */ | ||
823 | submit_bh(WRITE, bh); | ||
824 | if (should_wait) { | ||
825 | should_wait = false; | ||
826 | wait_on_buffer(bh); | ||
827 | if (unlikely(!buffer_uptodate(bh))) | ||
828 | goto io_err; | ||
829 | } | ||
830 | brelse(bh); | ||
831 | } while (++block < end_block); | ||
832 | } while ((++rl)->vcn < end_vcn); | ||
833 | up_write(&log_ni->runlist.lock); | ||
834 | /* | ||
835 | * Zap the pages again just in case any got instantiated whilst we were | ||
836 | * emptying the blocks by hand. FIXME: We may not have completed | ||
837 | * writing to all the buffer heads yet so this may happen too early. | ||
838 | * We really should use a kernel thread to do the emptying | ||
839 | * asynchronously and then we can also set the volume dirty and output | ||
840 | * an error message if emptying should fail. | ||
841 | */ | ||
842 | truncate_inode_pages(log_vi->i_mapping, 0); | ||
843 | /* Set the flag so we do not have to do it again on remount. */ | ||
844 | NVolSetLogFileEmpty(vol); | ||
743 | ntfs_debug("Done."); | 845 | ntfs_debug("Done."); |
744 | return true; | 846 | return true; |
847 | io_err: | ||
848 | ntfs_error(sb, "Failed to write buffer. Unmount and run chkdsk."); | ||
849 | goto dirty_err; | ||
850 | rl_err: | ||
851 | ntfs_error(sb, "Runlist is corrupt. Unmount and run chkdsk."); | ||
852 | dirty_err: | ||
853 | NVolSetErrors(vol); | ||
854 | err = -EIO; | ||
855 | err: | ||
856 | up_write(&log_ni->runlist.lock); | ||
857 | ntfs_error(sb, "Failed to fill $LogFile with 0xff bytes (error %d).", | ||
858 | -err); | ||
859 | return false; | ||
745 | } | 860 | } |
746 | 861 | ||
747 | #endif /* NTFS_RW */ | 862 | #endif /* NTFS_RW */ |
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 9afd72c7ad0d..56a9a6d25a2a 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. | 2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2007 Anton Altaparmakov |
5 | * Copyright (c) 2002-2005 Richard Russon | 5 | * Copyright (c) 2002-2005 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
@@ -1714,7 +1714,7 @@ extend_hole: | |||
1714 | sizeof(*rl)); | 1714 | sizeof(*rl)); |
1715 | /* Adjust the beginning of the tail if necessary. */ | 1715 | /* Adjust the beginning of the tail if necessary. */ |
1716 | if (end > rl->vcn) { | 1716 | if (end > rl->vcn) { |
1717 | s64 delta = end - rl->vcn; | 1717 | delta = end - rl->vcn; |
1718 | rl->vcn = end; | 1718 | rl->vcn = end; |
1719 | rl->length -= delta; | 1719 | rl->length -= delta; |
1720 | /* Only adjust the lcn if it is real. */ | 1720 | /* Only adjust the lcn if it is real. */ |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 778a850b4634..4ba7f0bdc248 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -354,7 +354,6 @@ struct ocfs2_insert_type { | |||
354 | enum ocfs2_append_type ins_appending; | 354 | enum ocfs2_append_type ins_appending; |
355 | enum ocfs2_contig_type ins_contig; | 355 | enum ocfs2_contig_type ins_contig; |
356 | int ins_contig_index; | 356 | int ins_contig_index; |
357 | int ins_free_records; | ||
358 | int ins_tree_depth; | 357 | int ins_tree_depth; |
359 | }; | 358 | }; |
360 | 359 | ||
@@ -362,7 +361,6 @@ struct ocfs2_merge_ctxt { | |||
362 | enum ocfs2_contig_type c_contig_type; | 361 | enum ocfs2_contig_type c_contig_type; |
363 | int c_has_empty_extent; | 362 | int c_has_empty_extent; |
364 | int c_split_covers_rec; | 363 | int c_split_covers_rec; |
365 | int c_used_tail_recs; | ||
366 | }; | 364 | }; |
367 | 365 | ||
368 | /* | 366 | /* |
@@ -2808,36 +2806,28 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
2808 | struct ocfs2_merge_ctxt *ctxt) | 2806 | struct ocfs2_merge_ctxt *ctxt) |
2809 | 2807 | ||
2810 | { | 2808 | { |
2811 | int ret = 0, delete_tail_recs = 0; | 2809 | int ret = 0; |
2812 | struct ocfs2_extent_list *el = path_leaf_el(left_path); | 2810 | struct ocfs2_extent_list *el = path_leaf_el(left_path); |
2813 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; | 2811 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; |
2814 | 2812 | ||
2815 | BUG_ON(ctxt->c_contig_type == CONTIG_NONE); | 2813 | BUG_ON(ctxt->c_contig_type == CONTIG_NONE); |
2816 | 2814 | ||
2817 | if (ctxt->c_split_covers_rec) { | 2815 | if (ctxt->c_split_covers_rec && ctxt->c_has_empty_extent) { |
2818 | delete_tail_recs++; | 2816 | /* |
2819 | 2817 | * The merge code will need to create an empty | |
2820 | if (ctxt->c_contig_type == CONTIG_LEFTRIGHT || | 2818 | * extent to take the place of the newly |
2821 | ctxt->c_has_empty_extent) | 2819 | * emptied slot. Remove any pre-existing empty |
2822 | delete_tail_recs++; | 2820 | * extents - having more than one in a leaf is |
2823 | 2821 | * illegal. | |
2824 | if (ctxt->c_has_empty_extent) { | 2822 | */ |
2825 | /* | 2823 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, |
2826 | * The merge code will need to create an empty | 2824 | dealloc); |
2827 | * extent to take the place of the newly | 2825 | if (ret) { |
2828 | * emptied slot. Remove any pre-existing empty | 2826 | mlog_errno(ret); |
2829 | * extents - having more than one in a leaf is | 2827 | goto out; |
2830 | * illegal. | ||
2831 | */ | ||
2832 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, | ||
2833 | dealloc); | ||
2834 | if (ret) { | ||
2835 | mlog_errno(ret); | ||
2836 | goto out; | ||
2837 | } | ||
2838 | split_index--; | ||
2839 | rec = &el->l_recs[split_index]; | ||
2840 | } | 2828 | } |
2829 | split_index--; | ||
2830 | rec = &el->l_recs[split_index]; | ||
2841 | } | 2831 | } |
2842 | 2832 | ||
2843 | if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) { | 2833 | if (ctxt->c_contig_type == CONTIG_LEFTRIGHT) { |
@@ -3593,6 +3583,7 @@ static int ocfs2_figure_insert_type(struct inode *inode, | |||
3593 | struct buffer_head *di_bh, | 3583 | struct buffer_head *di_bh, |
3594 | struct buffer_head **last_eb_bh, | 3584 | struct buffer_head **last_eb_bh, |
3595 | struct ocfs2_extent_rec *insert_rec, | 3585 | struct ocfs2_extent_rec *insert_rec, |
3586 | int *free_records, | ||
3596 | struct ocfs2_insert_type *insert) | 3587 | struct ocfs2_insert_type *insert) |
3597 | { | 3588 | { |
3598 | int ret; | 3589 | int ret; |
@@ -3633,7 +3624,7 @@ static int ocfs2_figure_insert_type(struct inode *inode, | |||
3633 | * XXX: This test is simplistic, we can search for empty | 3624 | * XXX: This test is simplistic, we can search for empty |
3634 | * extent records too. | 3625 | * extent records too. |
3635 | */ | 3626 | */ |
3636 | insert->ins_free_records = le16_to_cpu(el->l_count) - | 3627 | *free_records = le16_to_cpu(el->l_count) - |
3637 | le16_to_cpu(el->l_next_free_rec); | 3628 | le16_to_cpu(el->l_next_free_rec); |
3638 | 3629 | ||
3639 | if (!insert->ins_tree_depth) { | 3630 | if (!insert->ins_tree_depth) { |
@@ -3730,10 +3721,13 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, | |||
3730 | struct ocfs2_alloc_context *meta_ac) | 3721 | struct ocfs2_alloc_context *meta_ac) |
3731 | { | 3722 | { |
3732 | int status; | 3723 | int status; |
3724 | int uninitialized_var(free_records); | ||
3733 | struct buffer_head *last_eb_bh = NULL; | 3725 | struct buffer_head *last_eb_bh = NULL; |
3734 | struct ocfs2_insert_type insert = {0, }; | 3726 | struct ocfs2_insert_type insert = {0, }; |
3735 | struct ocfs2_extent_rec rec; | 3727 | struct ocfs2_extent_rec rec; |
3736 | 3728 | ||
3729 | BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); | ||
3730 | |||
3737 | mlog(0, "add %u clusters at position %u to inode %llu\n", | 3731 | mlog(0, "add %u clusters at position %u to inode %llu\n", |
3738 | new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno); | 3732 | new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno); |
3739 | 3733 | ||
@@ -3752,7 +3746,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, | |||
3752 | rec.e_flags = flags; | 3746 | rec.e_flags = flags; |
3753 | 3747 | ||
3754 | status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec, | 3748 | status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec, |
3755 | &insert); | 3749 | &free_records, &insert); |
3756 | if (status < 0) { | 3750 | if (status < 0) { |
3757 | mlog_errno(status); | 3751 | mlog_errno(status); |
3758 | goto bail; | 3752 | goto bail; |
@@ -3762,9 +3756,9 @@ int ocfs2_insert_extent(struct ocfs2_super *osb, | |||
3762 | "Insert.contig_index: %d, Insert.free_records: %d, " | 3756 | "Insert.contig_index: %d, Insert.free_records: %d, " |
3763 | "Insert.tree_depth: %d\n", | 3757 | "Insert.tree_depth: %d\n", |
3764 | insert.ins_appending, insert.ins_contig, insert.ins_contig_index, | 3758 | insert.ins_appending, insert.ins_contig, insert.ins_contig_index, |
3765 | insert.ins_free_records, insert.ins_tree_depth); | 3759 | free_records, insert.ins_tree_depth); |
3766 | 3760 | ||
3767 | if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) { | 3761 | if (insert.ins_contig == CONTIG_NONE && free_records == 0) { |
3768 | status = ocfs2_grow_tree(inode, handle, fe_bh, | 3762 | status = ocfs2_grow_tree(inode, handle, fe_bh, |
3769 | &insert.ins_tree_depth, &last_eb_bh, | 3763 | &insert.ins_tree_depth, &last_eb_bh, |
3770 | meta_ac); | 3764 | meta_ac); |
@@ -3847,26 +3841,17 @@ leftright: | |||
3847 | 3841 | ||
3848 | if (le16_to_cpu(rightmost_el->l_next_free_rec) == | 3842 | if (le16_to_cpu(rightmost_el->l_next_free_rec) == |
3849 | le16_to_cpu(rightmost_el->l_count)) { | 3843 | le16_to_cpu(rightmost_el->l_count)) { |
3850 | int old_depth = depth; | ||
3851 | |||
3852 | ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh, | 3844 | ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh, |
3853 | meta_ac); | 3845 | meta_ac); |
3854 | if (ret) { | 3846 | if (ret) { |
3855 | mlog_errno(ret); | 3847 | mlog_errno(ret); |
3856 | goto out; | 3848 | goto out; |
3857 | } | 3849 | } |
3858 | |||
3859 | if (old_depth != depth) { | ||
3860 | eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data; | ||
3861 | rightmost_el = &eb->h_list; | ||
3862 | } | ||
3863 | } | 3850 | } |
3864 | 3851 | ||
3865 | memset(&insert, 0, sizeof(struct ocfs2_insert_type)); | 3852 | memset(&insert, 0, sizeof(struct ocfs2_insert_type)); |
3866 | insert.ins_appending = APPEND_NONE; | 3853 | insert.ins_appending = APPEND_NONE; |
3867 | insert.ins_contig = CONTIG_NONE; | 3854 | insert.ins_contig = CONTIG_NONE; |
3868 | insert.ins_free_records = le16_to_cpu(rightmost_el->l_count) | ||
3869 | - le16_to_cpu(rightmost_el->l_next_free_rec); | ||
3870 | insert.ins_tree_depth = depth; | 3855 | insert.ins_tree_depth = depth; |
3871 | 3856 | ||
3872 | insert_range = le32_to_cpu(split_rec.e_cpos) + | 3857 | insert_range = le32_to_cpu(split_rec.e_cpos) + |
@@ -4015,11 +4000,6 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4015 | } else | 4000 | } else |
4016 | rightmost_el = path_root_el(path); | 4001 | rightmost_el = path_root_el(path); |
4017 | 4002 | ||
4018 | ctxt.c_used_tail_recs = le16_to_cpu(rightmost_el->l_next_free_rec); | ||
4019 | if (ctxt.c_used_tail_recs > 0 && | ||
4020 | ocfs2_is_empty_extent(&rightmost_el->l_recs[0])) | ||
4021 | ctxt.c_used_tail_recs--; | ||
4022 | |||
4023 | if (rec->e_cpos == split_rec->e_cpos && | 4003 | if (rec->e_cpos == split_rec->e_cpos && |
4024 | rec->e_leaf_clusters == split_rec->e_leaf_clusters) | 4004 | rec->e_leaf_clusters == split_rec->e_leaf_clusters) |
4025 | ctxt.c_split_covers_rec = 1; | 4005 | ctxt.c_split_covers_rec = 1; |
@@ -4028,10 +4008,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4028 | 4008 | ||
4029 | ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]); | 4009 | ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]); |
4030 | 4010 | ||
4031 | mlog(0, "index: %d, contig: %u, used_tail_recs: %u, " | 4011 | mlog(0, "index: %d, contig: %u, has_empty: %u, split_covers: %u\n", |
4032 | "has_empty: %u, split_covers: %u\n", split_index, | 4012 | split_index, ctxt.c_contig_type, ctxt.c_has_empty_extent, |
4033 | ctxt.c_contig_type, ctxt.c_used_tail_recs, | 4013 | ctxt.c_split_covers_rec); |
4034 | ctxt.c_has_empty_extent, ctxt.c_split_covers_rec); | ||
4035 | 4014 | ||
4036 | if (ctxt.c_contig_type == CONTIG_NONE) { | 4015 | if (ctxt.c_contig_type == CONTIG_NONE) { |
4037 | if (ctxt.c_split_covers_rec) | 4016 | if (ctxt.c_split_covers_rec) |
@@ -4180,27 +4159,18 @@ static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh, | |||
4180 | 4159 | ||
4181 | if (le16_to_cpu(rightmost_el->l_next_free_rec) == | 4160 | if (le16_to_cpu(rightmost_el->l_next_free_rec) == |
4182 | le16_to_cpu(rightmost_el->l_count)) { | 4161 | le16_to_cpu(rightmost_el->l_count)) { |
4183 | int old_depth = depth; | ||
4184 | |||
4185 | ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh, | 4162 | ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh, |
4186 | meta_ac); | 4163 | meta_ac); |
4187 | if (ret) { | 4164 | if (ret) { |
4188 | mlog_errno(ret); | 4165 | mlog_errno(ret); |
4189 | goto out; | 4166 | goto out; |
4190 | } | 4167 | } |
4191 | |||
4192 | if (old_depth != depth) { | ||
4193 | eb = (struct ocfs2_extent_block *)last_eb_bh->b_data; | ||
4194 | rightmost_el = &eb->h_list; | ||
4195 | } | ||
4196 | } | 4168 | } |
4197 | 4169 | ||
4198 | memset(&insert, 0, sizeof(struct ocfs2_insert_type)); | 4170 | memset(&insert, 0, sizeof(struct ocfs2_insert_type)); |
4199 | insert.ins_appending = APPEND_NONE; | 4171 | insert.ins_appending = APPEND_NONE; |
4200 | insert.ins_contig = CONTIG_NONE; | 4172 | insert.ins_contig = CONTIG_NONE; |
4201 | insert.ins_split = SPLIT_RIGHT; | 4173 | insert.ins_split = SPLIT_RIGHT; |
4202 | insert.ins_free_records = le16_to_cpu(rightmost_el->l_count) | ||
4203 | - le16_to_cpu(rightmost_el->l_next_free_rec); | ||
4204 | insert.ins_tree_depth = depth; | 4174 | insert.ins_tree_depth = depth; |
4205 | 4175 | ||
4206 | ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert); | 4176 | ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert); |
@@ -5665,12 +5635,50 @@ static int ocfs2_ordered_zero_func(handle_t *handle, struct buffer_head *bh) | |||
5665 | return ocfs2_journal_dirty_data(handle, bh); | 5635 | return ocfs2_journal_dirty_data(handle, bh); |
5666 | } | 5636 | } |
5667 | 5637 | ||
5638 | static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle, | ||
5639 | unsigned int from, unsigned int to, | ||
5640 | struct page *page, int zero, u64 *phys) | ||
5641 | { | ||
5642 | int ret, partial = 0; | ||
5643 | |||
5644 | ret = ocfs2_map_page_blocks(page, phys, inode, from, to, 0); | ||
5645 | if (ret) | ||
5646 | mlog_errno(ret); | ||
5647 | |||
5648 | if (zero) | ||
5649 | zero_user_page(page, from, to - from, KM_USER0); | ||
5650 | |||
5651 | /* | ||
5652 | * Need to set the buffers we zero'd into uptodate | ||
5653 | * here if they aren't - ocfs2_map_page_blocks() | ||
5654 | * might've skipped some | ||
5655 | */ | ||
5656 | if (ocfs2_should_order_data(inode)) { | ||
5657 | ret = walk_page_buffers(handle, | ||
5658 | page_buffers(page), | ||
5659 | from, to, &partial, | ||
5660 | ocfs2_ordered_zero_func); | ||
5661 | if (ret < 0) | ||
5662 | mlog_errno(ret); | ||
5663 | } else { | ||
5664 | ret = walk_page_buffers(handle, page_buffers(page), | ||
5665 | from, to, &partial, | ||
5666 | ocfs2_writeback_zero_func); | ||
5667 | if (ret < 0) | ||
5668 | mlog_errno(ret); | ||
5669 | } | ||
5670 | |||
5671 | if (!partial) | ||
5672 | SetPageUptodate(page); | ||
5673 | |||
5674 | flush_dcache_page(page); | ||
5675 | } | ||
5676 | |||
5668 | static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start, | 5677 | static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start, |
5669 | loff_t end, struct page **pages, | 5678 | loff_t end, struct page **pages, |
5670 | int numpages, u64 phys, handle_t *handle) | 5679 | int numpages, u64 phys, handle_t *handle) |
5671 | { | 5680 | { |
5672 | int i, ret, partial = 0; | 5681 | int i; |
5673 | void *kaddr; | ||
5674 | struct page *page; | 5682 | struct page *page; |
5675 | unsigned int from, to = PAGE_CACHE_SIZE; | 5683 | unsigned int from, to = PAGE_CACHE_SIZE; |
5676 | struct super_block *sb = inode->i_sb; | 5684 | struct super_block *sb = inode->i_sb; |
@@ -5691,87 +5699,31 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start, | |||
5691 | BUG_ON(from > PAGE_CACHE_SIZE); | 5699 | BUG_ON(from > PAGE_CACHE_SIZE); |
5692 | BUG_ON(to > PAGE_CACHE_SIZE); | 5700 | BUG_ON(to > PAGE_CACHE_SIZE); |
5693 | 5701 | ||
5694 | ret = ocfs2_map_page_blocks(page, &phys, inode, from, to, 0); | 5702 | ocfs2_map_and_dirty_page(inode, handle, from, to, page, 1, |
5695 | if (ret) | 5703 | &phys); |
5696 | mlog_errno(ret); | ||
5697 | |||
5698 | kaddr = kmap_atomic(page, KM_USER0); | ||
5699 | memset(kaddr + from, 0, to - from); | ||
5700 | kunmap_atomic(kaddr, KM_USER0); | ||
5701 | |||
5702 | /* | ||
5703 | * Need to set the buffers we zero'd into uptodate | ||
5704 | * here if they aren't - ocfs2_map_page_blocks() | ||
5705 | * might've skipped some | ||
5706 | */ | ||
5707 | if (ocfs2_should_order_data(inode)) { | ||
5708 | ret = walk_page_buffers(handle, | ||
5709 | page_buffers(page), | ||
5710 | from, to, &partial, | ||
5711 | ocfs2_ordered_zero_func); | ||
5712 | if (ret < 0) | ||
5713 | mlog_errno(ret); | ||
5714 | } else { | ||
5715 | ret = walk_page_buffers(handle, page_buffers(page), | ||
5716 | from, to, &partial, | ||
5717 | ocfs2_writeback_zero_func); | ||
5718 | if (ret < 0) | ||
5719 | mlog_errno(ret); | ||
5720 | } | ||
5721 | |||
5722 | if (!partial) | ||
5723 | SetPageUptodate(page); | ||
5724 | |||
5725 | flush_dcache_page(page); | ||
5726 | 5704 | ||
5727 | start = (page->index + 1) << PAGE_CACHE_SHIFT; | 5705 | start = (page->index + 1) << PAGE_CACHE_SHIFT; |
5728 | } | 5706 | } |
5729 | out: | 5707 | out: |
5730 | if (pages) { | 5708 | if (pages) |
5731 | for (i = 0; i < numpages; i++) { | 5709 | ocfs2_unlock_and_free_pages(pages, numpages); |
5732 | page = pages[i]; | ||
5733 | unlock_page(page); | ||
5734 | mark_page_accessed(page); | ||
5735 | page_cache_release(page); | ||
5736 | } | ||
5737 | } | ||
5738 | } | 5710 | } |
5739 | 5711 | ||
5740 | static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, | 5712 | static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, |
5741 | struct page **pages, int *num, u64 *phys) | 5713 | struct page **pages, int *num) |
5742 | { | 5714 | { |
5743 | int i, numpages = 0, ret = 0; | 5715 | int numpages, ret = 0; |
5744 | unsigned int ext_flags; | ||
5745 | struct super_block *sb = inode->i_sb; | 5716 | struct super_block *sb = inode->i_sb; |
5746 | struct address_space *mapping = inode->i_mapping; | 5717 | struct address_space *mapping = inode->i_mapping; |
5747 | unsigned long index; | 5718 | unsigned long index; |
5748 | loff_t last_page_bytes; | 5719 | loff_t last_page_bytes; |
5749 | 5720 | ||
5750 | BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb))); | ||
5751 | BUG_ON(start > end); | 5721 | BUG_ON(start > end); |
5752 | 5722 | ||
5753 | if (start == end) | ||
5754 | goto out; | ||
5755 | |||
5756 | BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits != | 5723 | BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits != |
5757 | (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits); | 5724 | (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits); |
5758 | 5725 | ||
5759 | ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits, | 5726 | numpages = 0; |
5760 | phys, NULL, &ext_flags); | ||
5761 | if (ret) { | ||
5762 | mlog_errno(ret); | ||
5763 | goto out; | ||
5764 | } | ||
5765 | |||
5766 | /* Tail is a hole. */ | ||
5767 | if (*phys == 0) | ||
5768 | goto out; | ||
5769 | |||
5770 | /* Tail is marked as unwritten, we can count on write to zero | ||
5771 | * in that case. */ | ||
5772 | if (ext_flags & OCFS2_EXT_UNWRITTEN) | ||
5773 | goto out; | ||
5774 | |||
5775 | last_page_bytes = PAGE_ALIGN(end); | 5727 | last_page_bytes = PAGE_ALIGN(end); |
5776 | index = start >> PAGE_CACHE_SHIFT; | 5728 | index = start >> PAGE_CACHE_SHIFT; |
5777 | do { | 5729 | do { |
@@ -5788,14 +5740,8 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, | |||
5788 | 5740 | ||
5789 | out: | 5741 | out: |
5790 | if (ret != 0) { | 5742 | if (ret != 0) { |
5791 | if (pages) { | 5743 | if (pages) |
5792 | for (i = 0; i < numpages; i++) { | 5744 | ocfs2_unlock_and_free_pages(pages, numpages); |
5793 | if (pages[i]) { | ||
5794 | unlock_page(pages[i]); | ||
5795 | page_cache_release(pages[i]); | ||
5796 | } | ||
5797 | } | ||
5798 | } | ||
5799 | numpages = 0; | 5745 | numpages = 0; |
5800 | } | 5746 | } |
5801 | 5747 | ||
@@ -5816,18 +5762,20 @@ out: | |||
5816 | int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, | 5762 | int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, |
5817 | u64 range_start, u64 range_end) | 5763 | u64 range_start, u64 range_end) |
5818 | { | 5764 | { |
5819 | int ret, numpages; | 5765 | int ret = 0, numpages; |
5820 | struct page **pages = NULL; | 5766 | struct page **pages = NULL; |
5821 | u64 phys; | 5767 | u64 phys; |
5768 | unsigned int ext_flags; | ||
5769 | struct super_block *sb = inode->i_sb; | ||
5822 | 5770 | ||
5823 | /* | 5771 | /* |
5824 | * File systems which don't support sparse files zero on every | 5772 | * File systems which don't support sparse files zero on every |
5825 | * extend. | 5773 | * extend. |
5826 | */ | 5774 | */ |
5827 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | 5775 | if (!ocfs2_sparse_alloc(OCFS2_SB(sb))) |
5828 | return 0; | 5776 | return 0; |
5829 | 5777 | ||
5830 | pages = kcalloc(ocfs2_pages_per_cluster(inode->i_sb), | 5778 | pages = kcalloc(ocfs2_pages_per_cluster(sb), |
5831 | sizeof(struct page *), GFP_NOFS); | 5779 | sizeof(struct page *), GFP_NOFS); |
5832 | if (pages == NULL) { | 5780 | if (pages == NULL) { |
5833 | ret = -ENOMEM; | 5781 | ret = -ENOMEM; |
@@ -5835,16 +5783,31 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, | |||
5835 | goto out; | 5783 | goto out; |
5836 | } | 5784 | } |
5837 | 5785 | ||
5838 | ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages, | 5786 | if (range_start == range_end) |
5839 | &numpages, &phys); | 5787 | goto out; |
5788 | |||
5789 | ret = ocfs2_extent_map_get_blocks(inode, | ||
5790 | range_start >> sb->s_blocksize_bits, | ||
5791 | &phys, NULL, &ext_flags); | ||
5840 | if (ret) { | 5792 | if (ret) { |
5841 | mlog_errno(ret); | 5793 | mlog_errno(ret); |
5842 | goto out; | 5794 | goto out; |
5843 | } | 5795 | } |
5844 | 5796 | ||
5845 | if (numpages == 0) | 5797 | /* |
5798 | * Tail is a hole, or is marked unwritten. In either case, we | ||
5799 | * can count on read and write to return/push zero's. | ||
5800 | */ | ||
5801 | if (phys == 0 || ext_flags & OCFS2_EXT_UNWRITTEN) | ||
5846 | goto out; | 5802 | goto out; |
5847 | 5803 | ||
5804 | ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages, | ||
5805 | &numpages); | ||
5806 | if (ret) { | ||
5807 | mlog_errno(ret); | ||
5808 | goto out; | ||
5809 | } | ||
5810 | |||
5848 | ocfs2_zero_cluster_pages(inode, range_start, range_end, pages, | 5811 | ocfs2_zero_cluster_pages(inode, range_start, range_end, pages, |
5849 | numpages, phys, handle); | 5812 | numpages, phys, handle); |
5850 | 5813 | ||
@@ -5865,6 +5828,178 @@ out: | |||
5865 | return ret; | 5828 | return ret; |
5866 | } | 5829 | } |
5867 | 5830 | ||
5831 | static void ocfs2_zero_dinode_id2(struct inode *inode, struct ocfs2_dinode *di) | ||
5832 | { | ||
5833 | unsigned int blocksize = 1 << inode->i_sb->s_blocksize_bits; | ||
5834 | |||
5835 | memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2)); | ||
5836 | } | ||
5837 | |||
5838 | void ocfs2_dinode_new_extent_list(struct inode *inode, | ||
5839 | struct ocfs2_dinode *di) | ||
5840 | { | ||
5841 | ocfs2_zero_dinode_id2(inode, di); | ||
5842 | di->id2.i_list.l_tree_depth = 0; | ||
5843 | di->id2.i_list.l_next_free_rec = 0; | ||
5844 | di->id2.i_list.l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(inode->i_sb)); | ||
5845 | } | ||
5846 | |||
5847 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di) | ||
5848 | { | ||
5849 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
5850 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
5851 | |||
5852 | spin_lock(&oi->ip_lock); | ||
5853 | oi->ip_dyn_features |= OCFS2_INLINE_DATA_FL; | ||
5854 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
5855 | spin_unlock(&oi->ip_lock); | ||
5856 | |||
5857 | /* | ||
5858 | * We clear the entire i_data structure here so that all | ||
5859 | * fields can be properly initialized. | ||
5860 | */ | ||
5861 | ocfs2_zero_dinode_id2(inode, di); | ||
5862 | |||
5863 | idata->id_count = cpu_to_le16(ocfs2_max_inline_data(inode->i_sb)); | ||
5864 | } | ||
5865 | |||
5866 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, | ||
5867 | struct buffer_head *di_bh) | ||
5868 | { | ||
5869 | int ret, i, has_data, num_pages = 0; | ||
5870 | handle_t *handle; | ||
5871 | u64 uninitialized_var(block); | ||
5872 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
5873 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
5874 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
5875 | struct ocfs2_alloc_context *data_ac = NULL; | ||
5876 | struct page **pages = NULL; | ||
5877 | loff_t end = osb->s_clustersize; | ||
5878 | |||
5879 | has_data = i_size_read(inode) ? 1 : 0; | ||
5880 | |||
5881 | if (has_data) { | ||
5882 | pages = kcalloc(ocfs2_pages_per_cluster(osb->sb), | ||
5883 | sizeof(struct page *), GFP_NOFS); | ||
5884 | if (pages == NULL) { | ||
5885 | ret = -ENOMEM; | ||
5886 | mlog_errno(ret); | ||
5887 | goto out; | ||
5888 | } | ||
5889 | |||
5890 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); | ||
5891 | if (ret) { | ||
5892 | mlog_errno(ret); | ||
5893 | goto out; | ||
5894 | } | ||
5895 | } | ||
5896 | |||
5897 | handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS); | ||
5898 | if (IS_ERR(handle)) { | ||
5899 | ret = PTR_ERR(handle); | ||
5900 | mlog_errno(ret); | ||
5901 | goto out_unlock; | ||
5902 | } | ||
5903 | |||
5904 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
5905 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
5906 | if (ret) { | ||
5907 | mlog_errno(ret); | ||
5908 | goto out_commit; | ||
5909 | } | ||
5910 | |||
5911 | if (has_data) { | ||
5912 | u32 bit_off, num; | ||
5913 | unsigned int page_end; | ||
5914 | u64 phys; | ||
5915 | |||
5916 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, | ||
5917 | &num); | ||
5918 | if (ret) { | ||
5919 | mlog_errno(ret); | ||
5920 | goto out_commit; | ||
5921 | } | ||
5922 | |||
5923 | /* | ||
5924 | * Save two copies, one for insert, and one that can | ||
5925 | * be changed by ocfs2_map_and_dirty_page() below. | ||
5926 | */ | ||
5927 | block = phys = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); | ||
5928 | |||
5929 | /* | ||
5930 | * Non sparse file systems zero on extend, so no need | ||
5931 | * to do that now. | ||
5932 | */ | ||
5933 | if (!ocfs2_sparse_alloc(osb) && | ||
5934 | PAGE_CACHE_SIZE < osb->s_clustersize) | ||
5935 | end = PAGE_CACHE_SIZE; | ||
5936 | |||
5937 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); | ||
5938 | if (ret) { | ||
5939 | mlog_errno(ret); | ||
5940 | goto out_commit; | ||
5941 | } | ||
5942 | |||
5943 | /* | ||
5944 | * This should populate the 1st page for us and mark | ||
5945 | * it up to date. | ||
5946 | */ | ||
5947 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); | ||
5948 | if (ret) { | ||
5949 | mlog_errno(ret); | ||
5950 | goto out_commit; | ||
5951 | } | ||
5952 | |||
5953 | page_end = PAGE_CACHE_SIZE; | ||
5954 | if (PAGE_CACHE_SIZE > osb->s_clustersize) | ||
5955 | page_end = osb->s_clustersize; | ||
5956 | |||
5957 | for (i = 0; i < num_pages; i++) | ||
5958 | ocfs2_map_and_dirty_page(inode, handle, 0, page_end, | ||
5959 | pages[i], i > 0, &phys); | ||
5960 | } | ||
5961 | |||
5962 | spin_lock(&oi->ip_lock); | ||
5963 | oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL; | ||
5964 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
5965 | spin_unlock(&oi->ip_lock); | ||
5966 | |||
5967 | ocfs2_dinode_new_extent_list(inode, di); | ||
5968 | |||
5969 | ocfs2_journal_dirty(handle, di_bh); | ||
5970 | |||
5971 | if (has_data) { | ||
5972 | /* | ||
5973 | * An error at this point should be extremely rare. If | ||
5974 | * this proves to be false, we could always re-build | ||
5975 | * the in-inode data from our pages. | ||
5976 | */ | ||
5977 | ret = ocfs2_insert_extent(osb, handle, inode, di_bh, | ||
5978 | 0, block, 1, 0, NULL); | ||
5979 | if (ret) { | ||
5980 | mlog_errno(ret); | ||
5981 | goto out_commit; | ||
5982 | } | ||
5983 | |||
5984 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
5985 | } | ||
5986 | |||
5987 | out_commit: | ||
5988 | ocfs2_commit_trans(osb, handle); | ||
5989 | |||
5990 | out_unlock: | ||
5991 | if (data_ac) | ||
5992 | ocfs2_free_alloc_context(data_ac); | ||
5993 | |||
5994 | out: | ||
5995 | if (pages) { | ||
5996 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
5997 | kfree(pages); | ||
5998 | } | ||
5999 | |||
6000 | return ret; | ||
6001 | } | ||
6002 | |||
5868 | /* | 6003 | /* |
5869 | * It is expected, that by the time you call this function, | 6004 | * It is expected, that by the time you call this function, |
5870 | * inode->i_size and fe->i_size have been adjusted. | 6005 | * inode->i_size and fe->i_size have been adjusted. |
@@ -6090,6 +6225,81 @@ bail: | |||
6090 | return status; | 6225 | return status; |
6091 | } | 6226 | } |
6092 | 6227 | ||
6228 | /* | ||
6229 | * 'start' is inclusive, 'end' is not. | ||
6230 | */ | ||
6231 | int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | ||
6232 | unsigned int start, unsigned int end, int trunc) | ||
6233 | { | ||
6234 | int ret; | ||
6235 | unsigned int numbytes; | ||
6236 | handle_t *handle; | ||
6237 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
6238 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
6239 | struct ocfs2_inline_data *idata = &di->id2.i_data; | ||
6240 | |||
6241 | if (end > i_size_read(inode)) | ||
6242 | end = i_size_read(inode); | ||
6243 | |||
6244 | BUG_ON(start >= end); | ||
6245 | |||
6246 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || | ||
6247 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || | ||
6248 | !ocfs2_supports_inline_data(osb)) { | ||
6249 | ocfs2_error(inode->i_sb, | ||
6250 | "Inline data flags for inode %llu don't agree! " | ||
6251 | "Disk: 0x%x, Memory: 0x%x, Superblock: 0x%x\n", | ||
6252 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | ||
6253 | le16_to_cpu(di->i_dyn_features), | ||
6254 | OCFS2_I(inode)->ip_dyn_features, | ||
6255 | osb->s_feature_incompat); | ||
6256 | ret = -EROFS; | ||
6257 | goto out; | ||
6258 | } | ||
6259 | |||
6260 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
6261 | if (IS_ERR(handle)) { | ||
6262 | ret = PTR_ERR(handle); | ||
6263 | mlog_errno(ret); | ||
6264 | goto out; | ||
6265 | } | ||
6266 | |||
6267 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
6268 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
6269 | if (ret) { | ||
6270 | mlog_errno(ret); | ||
6271 | goto out_commit; | ||
6272 | } | ||
6273 | |||
6274 | numbytes = end - start; | ||
6275 | memset(idata->id_data + start, 0, numbytes); | ||
6276 | |||
6277 | /* | ||
6278 | * No need to worry about the data page here - it's been | ||
6279 | * truncated already and inline data doesn't need it for | ||
6280 | * pushing zero's to disk, so we'll let readpage pick it up | ||
6281 | * later. | ||
6282 | */ | ||
6283 | if (trunc) { | ||
6284 | i_size_write(inode, start); | ||
6285 | di->i_size = cpu_to_le64(start); | ||
6286 | } | ||
6287 | |||
6288 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
6289 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
6290 | |||
6291 | di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec); | ||
6292 | di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); | ||
6293 | |||
6294 | ocfs2_journal_dirty(handle, di_bh); | ||
6295 | |||
6296 | out_commit: | ||
6297 | ocfs2_commit_trans(osb, handle); | ||
6298 | |||
6299 | out: | ||
6300 | return ret; | ||
6301 | } | ||
6302 | |||
6093 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) | 6303 | static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc) |
6094 | { | 6304 | { |
6095 | /* | 6305 | /* |
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h index 990df48ae8d3..42ff94bd8011 100644 --- a/fs/ocfs2/alloc.h +++ b/fs/ocfs2/alloc.h | |||
@@ -62,6 +62,11 @@ static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe) | |||
62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; | 62 | return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2; |
63 | } | 63 | } |
64 | 64 | ||
65 | void ocfs2_dinode_new_extent_list(struct inode *inode, struct ocfs2_dinode *di); | ||
66 | void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di); | ||
67 | int ocfs2_convert_inline_data_to_extents(struct inode *inode, | ||
68 | struct buffer_head *di_bh); | ||
69 | |||
65 | int ocfs2_truncate_log_init(struct ocfs2_super *osb); | 70 | int ocfs2_truncate_log_init(struct ocfs2_super *osb); |
66 | void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb); | 71 | void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb); |
67 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, | 72 | void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb, |
@@ -115,6 +120,8 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, | |||
115 | struct inode *inode, | 120 | struct inode *inode, |
116 | struct buffer_head *fe_bh, | 121 | struct buffer_head *fe_bh, |
117 | struct ocfs2_truncate_context *tc); | 122 | struct ocfs2_truncate_context *tc); |
123 | int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | ||
124 | unsigned int start, unsigned int end, int trunc); | ||
118 | 125 | ||
119 | int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, | 126 | int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, |
120 | u32 cpos, struct buffer_head **leaf_bh); | 127 | u32 cpos, struct buffer_head **leaf_bh); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f37f25c931f5..34d10452c56d 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -206,9 +206,70 @@ bail: | |||
206 | return err; | 206 | return err; |
207 | } | 207 | } |
208 | 208 | ||
209 | int ocfs2_read_inline_data(struct inode *inode, struct page *page, | ||
210 | struct buffer_head *di_bh) | ||
211 | { | ||
212 | void *kaddr; | ||
213 | unsigned int size; | ||
214 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
215 | |||
216 | if (!(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)) { | ||
217 | ocfs2_error(inode->i_sb, "Inode %llu lost inline data flag", | ||
218 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
219 | return -EROFS; | ||
220 | } | ||
221 | |||
222 | size = i_size_read(inode); | ||
223 | |||
224 | if (size > PAGE_CACHE_SIZE || | ||
225 | size > ocfs2_max_inline_data(inode->i_sb)) { | ||
226 | ocfs2_error(inode->i_sb, | ||
227 | "Inode %llu has with inline data has bad size: %u", | ||
228 | (unsigned long long)OCFS2_I(inode)->ip_blkno, size); | ||
229 | return -EROFS; | ||
230 | } | ||
231 | |||
232 | kaddr = kmap_atomic(page, KM_USER0); | ||
233 | if (size) | ||
234 | memcpy(kaddr, di->id2.i_data.id_data, size); | ||
235 | /* Clear the remaining part of the page */ | ||
236 | memset(kaddr + size, 0, PAGE_CACHE_SIZE - size); | ||
237 | flush_dcache_page(page); | ||
238 | kunmap_atomic(kaddr, KM_USER0); | ||
239 | |||
240 | SetPageUptodate(page); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int ocfs2_readpage_inline(struct inode *inode, struct page *page) | ||
246 | { | ||
247 | int ret; | ||
248 | struct buffer_head *di_bh = NULL; | ||
249 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
250 | |||
251 | BUG_ON(!PageLocked(page)); | ||
252 | BUG_ON(!OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); | ||
253 | |||
254 | ret = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &di_bh, | ||
255 | OCFS2_BH_CACHED, inode); | ||
256 | if (ret) { | ||
257 | mlog_errno(ret); | ||
258 | goto out; | ||
259 | } | ||
260 | |||
261 | ret = ocfs2_read_inline_data(inode, page, di_bh); | ||
262 | out: | ||
263 | unlock_page(page); | ||
264 | |||
265 | brelse(di_bh); | ||
266 | return ret; | ||
267 | } | ||
268 | |||
209 | static int ocfs2_readpage(struct file *file, struct page *page) | 269 | static int ocfs2_readpage(struct file *file, struct page *page) |
210 | { | 270 | { |
211 | struct inode *inode = page->mapping->host; | 271 | struct inode *inode = page->mapping->host; |
272 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
212 | loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; | 273 | loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; |
213 | int ret, unlock = 1; | 274 | int ret, unlock = 1; |
214 | 275 | ||
@@ -222,7 +283,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
222 | goto out; | 283 | goto out; |
223 | } | 284 | } |
224 | 285 | ||
225 | if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) { | 286 | if (down_read_trylock(&oi->ip_alloc_sem) == 0) { |
226 | ret = AOP_TRUNCATED_PAGE; | 287 | ret = AOP_TRUNCATED_PAGE; |
227 | goto out_meta_unlock; | 288 | goto out_meta_unlock; |
228 | } | 289 | } |
@@ -252,7 +313,10 @@ static int ocfs2_readpage(struct file *file, struct page *page) | |||
252 | goto out_alloc; | 313 | goto out_alloc; |
253 | } | 314 | } |
254 | 315 | ||
255 | ret = block_read_full_page(page, ocfs2_get_block); | 316 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
317 | ret = ocfs2_readpage_inline(inode, page); | ||
318 | else | ||
319 | ret = block_read_full_page(page, ocfs2_get_block); | ||
256 | unlock = 0; | 320 | unlock = 0; |
257 | 321 | ||
258 | ocfs2_data_unlock(inode, 0); | 322 | ocfs2_data_unlock(inode, 0); |
@@ -301,12 +365,8 @@ int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page, | |||
301 | { | 365 | { |
302 | int ret; | 366 | int ret; |
303 | 367 | ||
304 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
305 | |||
306 | ret = block_prepare_write(page, from, to, ocfs2_get_block); | 368 | ret = block_prepare_write(page, from, to, ocfs2_get_block); |
307 | 369 | ||
308 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
309 | |||
310 | return ret; | 370 | return ret; |
311 | } | 371 | } |
312 | 372 | ||
@@ -401,7 +461,9 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) | |||
401 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | 461 | down_read(&OCFS2_I(inode)->ip_alloc_sem); |
402 | } | 462 | } |
403 | 463 | ||
404 | err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, NULL); | 464 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)) |
465 | err = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL, | ||
466 | NULL); | ||
405 | 467 | ||
406 | if (!INODE_JOURNAL(inode)) { | 468 | if (!INODE_JOURNAL(inode)) { |
407 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | 469 | up_read(&OCFS2_I(inode)->ip_alloc_sem); |
@@ -415,7 +477,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) | |||
415 | goto bail; | 477 | goto bail; |
416 | } | 478 | } |
417 | 479 | ||
418 | |||
419 | bail: | 480 | bail: |
420 | status = err ? 0 : p_blkno; | 481 | status = err ? 0 : p_blkno; |
421 | 482 | ||
@@ -570,6 +631,13 @@ static ssize_t ocfs2_direct_IO(int rw, | |||
570 | 631 | ||
571 | mlog_entry_void(); | 632 | mlog_entry_void(); |
572 | 633 | ||
634 | /* | ||
635 | * Fallback to buffered I/O if we see an inode without | ||
636 | * extents. | ||
637 | */ | ||
638 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
639 | return 0; | ||
640 | |||
573 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { | 641 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { |
574 | /* | 642 | /* |
575 | * We get PR data locks even for O_DIRECT. This | 643 | * We get PR data locks even for O_DIRECT. This |
@@ -834,18 +902,22 @@ struct ocfs2_write_ctxt { | |||
834 | struct ocfs2_cached_dealloc_ctxt w_dealloc; | 902 | struct ocfs2_cached_dealloc_ctxt w_dealloc; |
835 | }; | 903 | }; |
836 | 904 | ||
837 | static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) | 905 | void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) |
838 | { | 906 | { |
839 | int i; | 907 | int i; |
840 | 908 | ||
841 | for(i = 0; i < wc->w_num_pages; i++) { | 909 | for(i = 0; i < num_pages; i++) { |
842 | if (wc->w_pages[i] == NULL) | 910 | if (pages[i]) { |
843 | continue; | 911 | unlock_page(pages[i]); |
844 | 912 | mark_page_accessed(pages[i]); | |
845 | unlock_page(wc->w_pages[i]); | 913 | page_cache_release(pages[i]); |
846 | mark_page_accessed(wc->w_pages[i]); | 914 | } |
847 | page_cache_release(wc->w_pages[i]); | ||
848 | } | 915 | } |
916 | } | ||
917 | |||
918 | static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) | ||
919 | { | ||
920 | ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); | ||
849 | 921 | ||
850 | brelse(wc->w_di_bh); | 922 | brelse(wc->w_di_bh); |
851 | kfree(wc); | 923 | kfree(wc); |
@@ -1360,6 +1432,160 @@ out: | |||
1360 | return ret; | 1432 | return ret; |
1361 | } | 1433 | } |
1362 | 1434 | ||
1435 | static int ocfs2_write_begin_inline(struct address_space *mapping, | ||
1436 | struct inode *inode, | ||
1437 | struct ocfs2_write_ctxt *wc) | ||
1438 | { | ||
1439 | int ret; | ||
1440 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1441 | struct page *page; | ||
1442 | handle_t *handle; | ||
1443 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; | ||
1444 | |||
1445 | page = find_or_create_page(mapping, 0, GFP_NOFS); | ||
1446 | if (!page) { | ||
1447 | ret = -ENOMEM; | ||
1448 | mlog_errno(ret); | ||
1449 | goto out; | ||
1450 | } | ||
1451 | /* | ||
1452 | * If we don't set w_num_pages then this page won't get unlocked | ||
1453 | * and freed on cleanup of the write context. | ||
1454 | */ | ||
1455 | wc->w_pages[0] = wc->w_target_page = page; | ||
1456 | wc->w_num_pages = 1; | ||
1457 | |||
1458 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
1459 | if (IS_ERR(handle)) { | ||
1460 | ret = PTR_ERR(handle); | ||
1461 | mlog_errno(ret); | ||
1462 | goto out; | ||
1463 | } | ||
1464 | |||
1465 | ret = ocfs2_journal_access(handle, inode, wc->w_di_bh, | ||
1466 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1467 | if (ret) { | ||
1468 | ocfs2_commit_trans(osb, handle); | ||
1469 | |||
1470 | mlog_errno(ret); | ||
1471 | goto out; | ||
1472 | } | ||
1473 | |||
1474 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)) | ||
1475 | ocfs2_set_inode_data_inline(inode, di); | ||
1476 | |||
1477 | if (!PageUptodate(page)) { | ||
1478 | ret = ocfs2_read_inline_data(inode, page, wc->w_di_bh); | ||
1479 | if (ret) { | ||
1480 | ocfs2_commit_trans(osb, handle); | ||
1481 | |||
1482 | goto out; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | wc->w_handle = handle; | ||
1487 | out: | ||
1488 | return ret; | ||
1489 | } | ||
1490 | |||
1491 | int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) | ||
1492 | { | ||
1493 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1494 | |||
1495 | if (new_size < le16_to_cpu(di->id2.i_data.id_count)) | ||
1496 | return 1; | ||
1497 | return 0; | ||
1498 | } | ||
1499 | |||
1500 | static int ocfs2_try_to_write_inline_data(struct address_space *mapping, | ||
1501 | struct inode *inode, loff_t pos, | ||
1502 | unsigned len, struct page *mmap_page, | ||
1503 | struct ocfs2_write_ctxt *wc) | ||
1504 | { | ||
1505 | int ret, written = 0; | ||
1506 | loff_t end = pos + len; | ||
1507 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
1508 | |||
1509 | mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", | ||
1510 | (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, | ||
1511 | oi->ip_dyn_features); | ||
1512 | |||
1513 | /* | ||
1514 | * Handle inodes which already have inline data 1st. | ||
1515 | */ | ||
1516 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1517 | if (mmap_page == NULL && | ||
1518 | ocfs2_size_fits_inline_data(wc->w_di_bh, end)) | ||
1519 | goto do_inline_write; | ||
1520 | |||
1521 | /* | ||
1522 | * The write won't fit - we have to give this inode an | ||
1523 | * inline extent list now. | ||
1524 | */ | ||
1525 | ret = ocfs2_convert_inline_data_to_extents(inode, wc->w_di_bh); | ||
1526 | if (ret) | ||
1527 | mlog_errno(ret); | ||
1528 | goto out; | ||
1529 | } | ||
1530 | |||
1531 | /* | ||
1532 | * Check whether the inode can accept inline data. | ||
1533 | */ | ||
1534 | if (oi->ip_clusters != 0 || i_size_read(inode) != 0) | ||
1535 | return 0; | ||
1536 | |||
1537 | /* | ||
1538 | * Check whether the write can fit. | ||
1539 | */ | ||
1540 | if (mmap_page || end > ocfs2_max_inline_data(inode->i_sb)) | ||
1541 | return 0; | ||
1542 | |||
1543 | do_inline_write: | ||
1544 | ret = ocfs2_write_begin_inline(mapping, inode, wc); | ||
1545 | if (ret) { | ||
1546 | mlog_errno(ret); | ||
1547 | goto out; | ||
1548 | } | ||
1549 | |||
1550 | /* | ||
1551 | * This signals to the caller that the data can be written | ||
1552 | * inline. | ||
1553 | */ | ||
1554 | written = 1; | ||
1555 | out: | ||
1556 | return written ? written : ret; | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1560 | * This function only does anything for file systems which can't | ||
1561 | * handle sparse files. | ||
1562 | * | ||
1563 | * What we want to do here is fill in any hole between the current end | ||
1564 | * of allocation and the end of our write. That way the rest of the | ||
1565 | * write path can treat it as an non-allocating write, which has no | ||
1566 | * special case code for sparse/nonsparse files. | ||
1567 | */ | ||
1568 | static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | ||
1569 | unsigned len, | ||
1570 | struct ocfs2_write_ctxt *wc) | ||
1571 | { | ||
1572 | int ret; | ||
1573 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1574 | loff_t newsize = pos + len; | ||
1575 | |||
1576 | if (ocfs2_sparse_alloc(osb)) | ||
1577 | return 0; | ||
1578 | |||
1579 | if (newsize <= i_size_read(inode)) | ||
1580 | return 0; | ||
1581 | |||
1582 | ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); | ||
1583 | if (ret) | ||
1584 | mlog_errno(ret); | ||
1585 | |||
1586 | return ret; | ||
1587 | } | ||
1588 | |||
1363 | int ocfs2_write_begin_nolock(struct address_space *mapping, | 1589 | int ocfs2_write_begin_nolock(struct address_space *mapping, |
1364 | loff_t pos, unsigned len, unsigned flags, | 1590 | loff_t pos, unsigned len, unsigned flags, |
1365 | struct page **pagep, void **fsdata, | 1591 | struct page **pagep, void **fsdata, |
@@ -1381,6 +1607,25 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1381 | return ret; | 1607 | return ret; |
1382 | } | 1608 | } |
1383 | 1609 | ||
1610 | if (ocfs2_supports_inline_data(osb)) { | ||
1611 | ret = ocfs2_try_to_write_inline_data(mapping, inode, pos, len, | ||
1612 | mmap_page, wc); | ||
1613 | if (ret == 1) { | ||
1614 | ret = 0; | ||
1615 | goto success; | ||
1616 | } | ||
1617 | if (ret < 0) { | ||
1618 | mlog_errno(ret); | ||
1619 | goto out; | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1623 | ret = ocfs2_expand_nonsparse_inode(inode, pos, len, wc); | ||
1624 | if (ret) { | ||
1625 | mlog_errno(ret); | ||
1626 | goto out; | ||
1627 | } | ||
1628 | |||
1384 | ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc, | 1629 | ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc, |
1385 | &extents_to_split); | 1630 | &extents_to_split); |
1386 | if (ret) { | 1631 | if (ret) { |
@@ -1462,6 +1707,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1462 | if (meta_ac) | 1707 | if (meta_ac) |
1463 | ocfs2_free_alloc_context(meta_ac); | 1708 | ocfs2_free_alloc_context(meta_ac); |
1464 | 1709 | ||
1710 | success: | ||
1465 | *pagep = wc->w_target_page; | 1711 | *pagep = wc->w_target_page; |
1466 | *fsdata = wc; | 1712 | *fsdata = wc; |
1467 | return 0; | 1713 | return 0; |
@@ -1529,6 +1775,31 @@ out_fail: | |||
1529 | return ret; | 1775 | return ret; |
1530 | } | 1776 | } |
1531 | 1777 | ||
1778 | static void ocfs2_write_end_inline(struct inode *inode, loff_t pos, | ||
1779 | unsigned len, unsigned *copied, | ||
1780 | struct ocfs2_dinode *di, | ||
1781 | struct ocfs2_write_ctxt *wc) | ||
1782 | { | ||
1783 | void *kaddr; | ||
1784 | |||
1785 | if (unlikely(*copied < len)) { | ||
1786 | if (!PageUptodate(wc->w_target_page)) { | ||
1787 | *copied = 0; | ||
1788 | return; | ||
1789 | } | ||
1790 | } | ||
1791 | |||
1792 | kaddr = kmap_atomic(wc->w_target_page, KM_USER0); | ||
1793 | memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied); | ||
1794 | kunmap_atomic(kaddr, KM_USER0); | ||
1795 | |||
1796 | mlog(0, "Data written to inode at offset %llu. " | ||
1797 | "id_count = %u, copied = %u, i_dyn_features = 0x%x\n", | ||
1798 | (unsigned long long)pos, *copied, | ||
1799 | le16_to_cpu(di->id2.i_data.id_count), | ||
1800 | le16_to_cpu(di->i_dyn_features)); | ||
1801 | } | ||
1802 | |||
1532 | int ocfs2_write_end_nolock(struct address_space *mapping, | 1803 | int ocfs2_write_end_nolock(struct address_space *mapping, |
1533 | loff_t pos, unsigned len, unsigned copied, | 1804 | loff_t pos, unsigned len, unsigned copied, |
1534 | struct page *page, void *fsdata) | 1805 | struct page *page, void *fsdata) |
@@ -1542,6 +1813,11 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
1542 | handle_t *handle = wc->w_handle; | 1813 | handle_t *handle = wc->w_handle; |
1543 | struct page *tmppage; | 1814 | struct page *tmppage; |
1544 | 1815 | ||
1816 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1817 | ocfs2_write_end_inline(inode, pos, len, &copied, di, wc); | ||
1818 | goto out_write_size; | ||
1819 | } | ||
1820 | |||
1545 | if (unlikely(copied < len)) { | 1821 | if (unlikely(copied < len)) { |
1546 | if (!PageUptodate(wc->w_target_page)) | 1822 | if (!PageUptodate(wc->w_target_page)) |
1547 | copied = 0; | 1823 | copied = 0; |
@@ -1579,6 +1855,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
1579 | block_commit_write(tmppage, from, to); | 1855 | block_commit_write(tmppage, from, to); |
1580 | } | 1856 | } |
1581 | 1857 | ||
1858 | out_write_size: | ||
1582 | pos += copied; | 1859 | pos += copied; |
1583 | if (pos > inode->i_size) { | 1860 | if (pos > inode->i_size) { |
1584 | i_size_write(inode, pos); | 1861 | i_size_write(inode, pos); |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index 389579bd64e3..113560877dbb 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
@@ -34,6 +34,8 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, | |||
34 | struct inode *inode, unsigned int from, | 34 | struct inode *inode, unsigned int from, |
35 | unsigned int to, int new); | 35 | unsigned int to, int new); |
36 | 36 | ||
37 | void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages); | ||
38 | |||
37 | int walk_page_buffers( handle_t *handle, | 39 | int walk_page_buffers( handle_t *handle, |
38 | struct buffer_head *head, | 40 | struct buffer_head *head, |
39 | unsigned from, | 41 | unsigned from, |
@@ -59,6 +61,10 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
59 | struct page **pagep, void **fsdata, | 61 | struct page **pagep, void **fsdata, |
60 | struct buffer_head *di_bh, struct page *mmap_page); | 62 | struct buffer_head *di_bh, struct page *mmap_page); |
61 | 63 | ||
64 | int ocfs2_read_inline_data(struct inode *inode, struct page *page, | ||
65 | struct buffer_head *di_bh); | ||
66 | int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size); | ||
67 | |||
62 | /* all ocfs2_dio_end_io()'s fault */ | 68 | /* all ocfs2_dio_end_io()'s fault */ |
63 | #define ocfs2_iocb_is_rw_locked(iocb) \ | 69 | #define ocfs2_iocb_is_rw_locked(iocb) \ |
64 | test_bit(0, (unsigned long *)&iocb->private) | 70 | test_bit(0, (unsigned long *)&iocb->private) |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 0d5fdde959c8..7453b70c1a19 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -55,10 +55,16 @@ | |||
55 | #include "journal.h" | 55 | #include "journal.h" |
56 | #include "namei.h" | 56 | #include "namei.h" |
57 | #include "suballoc.h" | 57 | #include "suballoc.h" |
58 | #include "super.h" | ||
58 | #include "uptodate.h" | 59 | #include "uptodate.h" |
59 | 60 | ||
60 | #include "buffer_head_io.h" | 61 | #include "buffer_head_io.h" |
61 | 62 | ||
63 | #define NAMEI_RA_CHUNKS 2 | ||
64 | #define NAMEI_RA_BLOCKS 4 | ||
65 | #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) | ||
66 | #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) | ||
67 | |||
62 | static unsigned char ocfs2_filetype_table[] = { | 68 | static unsigned char ocfs2_filetype_table[] = { |
63 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | 69 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK |
64 | }; | 70 | }; |
@@ -66,12 +72,614 @@ static unsigned char ocfs2_filetype_table[] = { | |||
66 | static int ocfs2_extend_dir(struct ocfs2_super *osb, | 72 | static int ocfs2_extend_dir(struct ocfs2_super *osb, |
67 | struct inode *dir, | 73 | struct inode *dir, |
68 | struct buffer_head *parent_fe_bh, | 74 | struct buffer_head *parent_fe_bh, |
75 | unsigned int blocks_wanted, | ||
69 | struct buffer_head **new_de_bh); | 76 | struct buffer_head **new_de_bh); |
77 | static int ocfs2_do_extend_dir(struct super_block *sb, | ||
78 | handle_t *handle, | ||
79 | struct inode *dir, | ||
80 | struct buffer_head *parent_fe_bh, | ||
81 | struct ocfs2_alloc_context *data_ac, | ||
82 | struct ocfs2_alloc_context *meta_ac, | ||
83 | struct buffer_head **new_bh); | ||
84 | |||
70 | /* | 85 | /* |
71 | * ocfs2_readdir() | 86 | * bh passed here can be an inode block or a dir data block, depending |
87 | * on the inode inline data flag. | ||
88 | */ | ||
89 | static int ocfs2_check_dir_entry(struct inode * dir, | ||
90 | struct ocfs2_dir_entry * de, | ||
91 | struct buffer_head * bh, | ||
92 | unsigned long offset) | ||
93 | { | ||
94 | const char *error_msg = NULL; | ||
95 | const int rlen = le16_to_cpu(de->rec_len); | ||
96 | |||
97 | if (rlen < OCFS2_DIR_REC_LEN(1)) | ||
98 | error_msg = "rec_len is smaller than minimal"; | ||
99 | else if (rlen % 4 != 0) | ||
100 | error_msg = "rec_len % 4 != 0"; | ||
101 | else if (rlen < OCFS2_DIR_REC_LEN(de->name_len)) | ||
102 | error_msg = "rec_len is too small for name_len"; | ||
103 | else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) | ||
104 | error_msg = "directory entry across blocks"; | ||
105 | |||
106 | if (error_msg != NULL) | ||
107 | mlog(ML_ERROR, "bad entry in directory #%llu: %s - " | ||
108 | "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n", | ||
109 | (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg, | ||
110 | offset, (unsigned long long)le64_to_cpu(de->inode), rlen, | ||
111 | de->name_len); | ||
112 | return error_msg == NULL ? 1 : 0; | ||
113 | } | ||
114 | |||
115 | static inline int ocfs2_match(int len, | ||
116 | const char * const name, | ||
117 | struct ocfs2_dir_entry *de) | ||
118 | { | ||
119 | if (len != de->name_len) | ||
120 | return 0; | ||
121 | if (!de->inode) | ||
122 | return 0; | ||
123 | return !memcmp(name, de->name, len); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Returns 0 if not found, -1 on failure, and 1 on success | ||
128 | */ | ||
129 | static int inline ocfs2_search_dirblock(struct buffer_head *bh, | ||
130 | struct inode *dir, | ||
131 | const char *name, int namelen, | ||
132 | unsigned long offset, | ||
133 | char *first_de, | ||
134 | unsigned int bytes, | ||
135 | struct ocfs2_dir_entry **res_dir) | ||
136 | { | ||
137 | struct ocfs2_dir_entry *de; | ||
138 | char *dlimit, *de_buf; | ||
139 | int de_len; | ||
140 | int ret = 0; | ||
141 | |||
142 | mlog_entry_void(); | ||
143 | |||
144 | de_buf = first_de; | ||
145 | dlimit = de_buf + bytes; | ||
146 | |||
147 | while (de_buf < dlimit) { | ||
148 | /* this code is executed quadratically often */ | ||
149 | /* do minimal checking `by hand' */ | ||
150 | |||
151 | de = (struct ocfs2_dir_entry *) de_buf; | ||
152 | |||
153 | if (de_buf + namelen <= dlimit && | ||
154 | ocfs2_match(namelen, name, de)) { | ||
155 | /* found a match - just to be sure, do a full check */ | ||
156 | if (!ocfs2_check_dir_entry(dir, de, bh, offset)) { | ||
157 | ret = -1; | ||
158 | goto bail; | ||
159 | } | ||
160 | *res_dir = de; | ||
161 | ret = 1; | ||
162 | goto bail; | ||
163 | } | ||
164 | |||
165 | /* prevent looping on a bad block */ | ||
166 | de_len = le16_to_cpu(de->rec_len); | ||
167 | if (de_len <= 0) { | ||
168 | ret = -1; | ||
169 | goto bail; | ||
170 | } | ||
171 | |||
172 | de_buf += de_len; | ||
173 | offset += de_len; | ||
174 | } | ||
175 | |||
176 | bail: | ||
177 | mlog_exit(ret); | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static struct buffer_head *ocfs2_find_entry_id(const char *name, | ||
182 | int namelen, | ||
183 | struct inode *dir, | ||
184 | struct ocfs2_dir_entry **res_dir) | ||
185 | { | ||
186 | int ret, found; | ||
187 | struct buffer_head *di_bh = NULL; | ||
188 | struct ocfs2_dinode *di; | ||
189 | struct ocfs2_inline_data *data; | ||
190 | |||
191 | ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno, | ||
192 | &di_bh, OCFS2_BH_CACHED, dir); | ||
193 | if (ret) { | ||
194 | mlog_errno(ret); | ||
195 | goto out; | ||
196 | } | ||
197 | |||
198 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
199 | data = &di->id2.i_data; | ||
200 | |||
201 | found = ocfs2_search_dirblock(di_bh, dir, name, namelen, 0, | ||
202 | data->id_data, i_size_read(dir), res_dir); | ||
203 | if (found == 1) | ||
204 | return di_bh; | ||
205 | |||
206 | brelse(di_bh); | ||
207 | out: | ||
208 | return NULL; | ||
209 | } | ||
210 | |||
211 | struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, | ||
212 | struct inode *dir, | ||
213 | struct ocfs2_dir_entry **res_dir) | ||
214 | { | ||
215 | struct super_block *sb; | ||
216 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; | ||
217 | struct buffer_head *bh, *ret = NULL; | ||
218 | unsigned long start, block, b; | ||
219 | int ra_max = 0; /* Number of bh's in the readahead | ||
220 | buffer, bh_use[] */ | ||
221 | int ra_ptr = 0; /* Current index into readahead | ||
222 | buffer */ | ||
223 | int num = 0; | ||
224 | int nblocks, i, err; | ||
225 | |||
226 | mlog_entry_void(); | ||
227 | |||
228 | sb = dir->i_sb; | ||
229 | |||
230 | nblocks = i_size_read(dir) >> sb->s_blocksize_bits; | ||
231 | start = OCFS2_I(dir)->ip_dir_start_lookup; | ||
232 | if (start >= nblocks) | ||
233 | start = 0; | ||
234 | block = start; | ||
235 | |||
236 | restart: | ||
237 | do { | ||
238 | /* | ||
239 | * We deal with the read-ahead logic here. | ||
240 | */ | ||
241 | if (ra_ptr >= ra_max) { | ||
242 | /* Refill the readahead buffer */ | ||
243 | ra_ptr = 0; | ||
244 | b = block; | ||
245 | for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) { | ||
246 | /* | ||
247 | * Terminate if we reach the end of the | ||
248 | * directory and must wrap, or if our | ||
249 | * search has finished at this block. | ||
250 | */ | ||
251 | if (b >= nblocks || (num && block == start)) { | ||
252 | bh_use[ra_max] = NULL; | ||
253 | break; | ||
254 | } | ||
255 | num++; | ||
256 | |||
257 | bh = ocfs2_bread(dir, b++, &err, 1); | ||
258 | bh_use[ra_max] = bh; | ||
259 | } | ||
260 | } | ||
261 | if ((bh = bh_use[ra_ptr++]) == NULL) | ||
262 | goto next; | ||
263 | wait_on_buffer(bh); | ||
264 | if (!buffer_uptodate(bh)) { | ||
265 | /* read error, skip block & hope for the best */ | ||
266 | ocfs2_error(dir->i_sb, "reading directory %llu, " | ||
267 | "offset %lu\n", | ||
268 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | ||
269 | block); | ||
270 | brelse(bh); | ||
271 | goto next; | ||
272 | } | ||
273 | i = ocfs2_search_dirblock(bh, dir, name, namelen, | ||
274 | block << sb->s_blocksize_bits, | ||
275 | bh->b_data, sb->s_blocksize, | ||
276 | res_dir); | ||
277 | if (i == 1) { | ||
278 | OCFS2_I(dir)->ip_dir_start_lookup = block; | ||
279 | ret = bh; | ||
280 | goto cleanup_and_exit; | ||
281 | } else { | ||
282 | brelse(bh); | ||
283 | if (i < 0) | ||
284 | goto cleanup_and_exit; | ||
285 | } | ||
286 | next: | ||
287 | if (++block >= nblocks) | ||
288 | block = 0; | ||
289 | } while (block != start); | ||
290 | |||
291 | /* | ||
292 | * If the directory has grown while we were searching, then | ||
293 | * search the last part of the directory before giving up. | ||
294 | */ | ||
295 | block = nblocks; | ||
296 | nblocks = i_size_read(dir) >> sb->s_blocksize_bits; | ||
297 | if (block < nblocks) { | ||
298 | start = 0; | ||
299 | goto restart; | ||
300 | } | ||
301 | |||
302 | cleanup_and_exit: | ||
303 | /* Clean up the read-ahead blocks */ | ||
304 | for (; ra_ptr < ra_max; ra_ptr++) | ||
305 | brelse(bh_use[ra_ptr]); | ||
306 | |||
307 | mlog_exit_ptr(ret); | ||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Try to find an entry of the provided name within 'dir'. | ||
72 | * | 313 | * |
314 | * If nothing was found, NULL is returned. Otherwise, a buffer_head | ||
315 | * and pointer to the dir entry are passed back. | ||
316 | * | ||
317 | * Caller can NOT assume anything about the contents of the | ||
318 | * buffer_head - it is passed back only so that it can be passed into | ||
319 | * any one of the manipulation functions (add entry, delete entry, | ||
320 | * etc). As an example, bh in the extent directory case is a data | ||
321 | * block, in the inline-data case it actually points to an inode. | ||
73 | */ | 322 | */ |
74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 323 | struct buffer_head *ocfs2_find_entry(const char *name, int namelen, |
324 | struct inode *dir, | ||
325 | struct ocfs2_dir_entry **res_dir) | ||
326 | { | ||
327 | *res_dir = NULL; | ||
328 | |||
329 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
330 | return ocfs2_find_entry_id(name, namelen, dir, res_dir); | ||
331 | |||
332 | return ocfs2_find_entry_el(name, namelen, dir, res_dir); | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * Update inode number and type of a previously found directory entry. | ||
337 | */ | ||
338 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, | ||
339 | struct buffer_head *de_bh, struct ocfs2_dir_entry *de, | ||
340 | struct inode *new_entry_inode) | ||
341 | { | ||
342 | int ret; | ||
343 | |||
344 | /* | ||
345 | * The same code works fine for both inline-data and extent | ||
346 | * based directories, so no need to split this up. | ||
347 | */ | ||
348 | |||
349 | ret = ocfs2_journal_access(handle, dir, de_bh, | ||
350 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
351 | if (ret) { | ||
352 | mlog_errno(ret); | ||
353 | goto out; | ||
354 | } | ||
355 | |||
356 | de->inode = cpu_to_le64(OCFS2_I(new_entry_inode)->ip_blkno); | ||
357 | ocfs2_set_de_type(de, new_entry_inode->i_mode); | ||
358 | |||
359 | ocfs2_journal_dirty(handle, de_bh); | ||
360 | |||
361 | out: | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, | ||
366 | struct ocfs2_dir_entry *de_del, | ||
367 | struct buffer_head *bh, char *first_de, | ||
368 | unsigned int bytes) | ||
369 | { | ||
370 | struct ocfs2_dir_entry *de, *pde; | ||
371 | int i, status = -ENOENT; | ||
372 | |||
373 | mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); | ||
374 | |||
375 | i = 0; | ||
376 | pde = NULL; | ||
377 | de = (struct ocfs2_dir_entry *) first_de; | ||
378 | while (i < bytes) { | ||
379 | if (!ocfs2_check_dir_entry(dir, de, bh, i)) { | ||
380 | status = -EIO; | ||
381 | mlog_errno(status); | ||
382 | goto bail; | ||
383 | } | ||
384 | if (de == de_del) { | ||
385 | status = ocfs2_journal_access(handle, dir, bh, | ||
386 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
387 | if (status < 0) { | ||
388 | status = -EIO; | ||
389 | mlog_errno(status); | ||
390 | goto bail; | ||
391 | } | ||
392 | if (pde) | ||
393 | pde->rec_len = | ||
394 | cpu_to_le16(le16_to_cpu(pde->rec_len) + | ||
395 | le16_to_cpu(de->rec_len)); | ||
396 | else | ||
397 | de->inode = 0; | ||
398 | dir->i_version++; | ||
399 | status = ocfs2_journal_dirty(handle, bh); | ||
400 | goto bail; | ||
401 | } | ||
402 | i += le16_to_cpu(de->rec_len); | ||
403 | pde = de; | ||
404 | de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len)); | ||
405 | } | ||
406 | bail: | ||
407 | mlog_exit(status); | ||
408 | return status; | ||
409 | } | ||
410 | |||
411 | static inline int ocfs2_delete_entry_id(handle_t *handle, | ||
412 | struct inode *dir, | ||
413 | struct ocfs2_dir_entry *de_del, | ||
414 | struct buffer_head *bh) | ||
415 | { | ||
416 | int ret; | ||
417 | struct buffer_head *di_bh = NULL; | ||
418 | struct ocfs2_dinode *di; | ||
419 | struct ocfs2_inline_data *data; | ||
420 | |||
421 | ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno, | ||
422 | &di_bh, OCFS2_BH_CACHED, dir); | ||
423 | if (ret) { | ||
424 | mlog_errno(ret); | ||
425 | goto out; | ||
426 | } | ||
427 | |||
428 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
429 | data = &di->id2.i_data; | ||
430 | |||
431 | ret = __ocfs2_delete_entry(handle, dir, de_del, bh, data->id_data, | ||
432 | i_size_read(dir)); | ||
433 | |||
434 | brelse(di_bh); | ||
435 | out: | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | static inline int ocfs2_delete_entry_el(handle_t *handle, | ||
440 | struct inode *dir, | ||
441 | struct ocfs2_dir_entry *de_del, | ||
442 | struct buffer_head *bh) | ||
443 | { | ||
444 | return __ocfs2_delete_entry(handle, dir, de_del, bh, bh->b_data, | ||
445 | bh->b_size); | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * ocfs2_delete_entry deletes a directory entry by merging it with the | ||
450 | * previous entry | ||
451 | */ | ||
452 | int ocfs2_delete_entry(handle_t *handle, | ||
453 | struct inode *dir, | ||
454 | struct ocfs2_dir_entry *de_del, | ||
455 | struct buffer_head *bh) | ||
456 | { | ||
457 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
458 | return ocfs2_delete_entry_id(handle, dir, de_del, bh); | ||
459 | |||
460 | return ocfs2_delete_entry_el(handle, dir, de_del, bh); | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * Check whether 'de' has enough room to hold an entry of | ||
465 | * 'new_rec_len' bytes. | ||
466 | */ | ||
467 | static inline int ocfs2_dirent_would_fit(struct ocfs2_dir_entry *de, | ||
468 | unsigned int new_rec_len) | ||
469 | { | ||
470 | unsigned int de_really_used; | ||
471 | |||
472 | /* Check whether this is an empty record with enough space */ | ||
473 | if (le64_to_cpu(de->inode) == 0 && | ||
474 | le16_to_cpu(de->rec_len) >= new_rec_len) | ||
475 | return 1; | ||
476 | |||
477 | /* | ||
478 | * Record might have free space at the end which we can | ||
479 | * use. | ||
480 | */ | ||
481 | de_really_used = OCFS2_DIR_REC_LEN(de->name_len); | ||
482 | if (le16_to_cpu(de->rec_len) >= (de_really_used + new_rec_len)) | ||
483 | return 1; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* we don't always have a dentry for what we want to add, so people | ||
489 | * like orphan dir can call this instead. | ||
490 | * | ||
491 | * If you pass me insert_bh, I'll skip the search of the other dir | ||
492 | * blocks and put the record in there. | ||
493 | */ | ||
494 | int __ocfs2_add_entry(handle_t *handle, | ||
495 | struct inode *dir, | ||
496 | const char *name, int namelen, | ||
497 | struct inode *inode, u64 blkno, | ||
498 | struct buffer_head *parent_fe_bh, | ||
499 | struct buffer_head *insert_bh) | ||
500 | { | ||
501 | unsigned long offset; | ||
502 | unsigned short rec_len; | ||
503 | struct ocfs2_dir_entry *de, *de1; | ||
504 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)parent_fe_bh->b_data; | ||
505 | struct super_block *sb = dir->i_sb; | ||
506 | int retval, status; | ||
507 | unsigned int size = sb->s_blocksize; | ||
508 | char *data_start = insert_bh->b_data; | ||
509 | |||
510 | mlog_entry_void(); | ||
511 | |||
512 | if (!namelen) | ||
513 | return -EINVAL; | ||
514 | |||
515 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
516 | data_start = di->id2.i_data.id_data; | ||
517 | size = i_size_read(dir); | ||
518 | |||
519 | BUG_ON(insert_bh != parent_fe_bh); | ||
520 | } | ||
521 | |||
522 | rec_len = OCFS2_DIR_REC_LEN(namelen); | ||
523 | offset = 0; | ||
524 | de = (struct ocfs2_dir_entry *) data_start; | ||
525 | while (1) { | ||
526 | BUG_ON((char *)de >= (size + data_start)); | ||
527 | |||
528 | /* These checks should've already been passed by the | ||
529 | * prepare function, but I guess we can leave them | ||
530 | * here anyway. */ | ||
531 | if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) { | ||
532 | retval = -ENOENT; | ||
533 | goto bail; | ||
534 | } | ||
535 | if (ocfs2_match(namelen, name, de)) { | ||
536 | retval = -EEXIST; | ||
537 | goto bail; | ||
538 | } | ||
539 | |||
540 | if (ocfs2_dirent_would_fit(de, rec_len)) { | ||
541 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
542 | retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh); | ||
543 | if (retval < 0) { | ||
544 | mlog_errno(retval); | ||
545 | goto bail; | ||
546 | } | ||
547 | |||
548 | status = ocfs2_journal_access(handle, dir, insert_bh, | ||
549 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
550 | /* By now the buffer is marked for journaling */ | ||
551 | offset += le16_to_cpu(de->rec_len); | ||
552 | if (le64_to_cpu(de->inode)) { | ||
553 | de1 = (struct ocfs2_dir_entry *)((char *) de + | ||
554 | OCFS2_DIR_REC_LEN(de->name_len)); | ||
555 | de1->rec_len = | ||
556 | cpu_to_le16(le16_to_cpu(de->rec_len) - | ||
557 | OCFS2_DIR_REC_LEN(de->name_len)); | ||
558 | de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
559 | de = de1; | ||
560 | } | ||
561 | de->file_type = OCFS2_FT_UNKNOWN; | ||
562 | if (blkno) { | ||
563 | de->inode = cpu_to_le64(blkno); | ||
564 | ocfs2_set_de_type(de, inode->i_mode); | ||
565 | } else | ||
566 | de->inode = 0; | ||
567 | de->name_len = namelen; | ||
568 | memcpy(de->name, name, namelen); | ||
569 | |||
570 | dir->i_version++; | ||
571 | status = ocfs2_journal_dirty(handle, insert_bh); | ||
572 | retval = 0; | ||
573 | goto bail; | ||
574 | } | ||
575 | offset += le16_to_cpu(de->rec_len); | ||
576 | de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); | ||
577 | } | ||
578 | |||
579 | /* when you think about it, the assert above should prevent us | ||
580 | * from ever getting here. */ | ||
581 | retval = -ENOSPC; | ||
582 | bail: | ||
583 | |||
584 | mlog_exit(retval); | ||
585 | return retval; | ||
586 | } | ||
587 | |||
588 | static int ocfs2_dir_foreach_blk_id(struct inode *inode, | ||
589 | unsigned long *f_version, | ||
590 | loff_t *f_pos, void *priv, | ||
591 | filldir_t filldir, int *filldir_err) | ||
592 | { | ||
593 | int ret, i, filldir_ret; | ||
594 | unsigned long offset = *f_pos; | ||
595 | struct buffer_head *di_bh = NULL; | ||
596 | struct ocfs2_dinode *di; | ||
597 | struct ocfs2_inline_data *data; | ||
598 | struct ocfs2_dir_entry *de; | ||
599 | |||
600 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno, | ||
601 | &di_bh, OCFS2_BH_CACHED, inode); | ||
602 | if (ret) { | ||
603 | mlog(ML_ERROR, "Unable to read inode block for dir %llu\n", | ||
604 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
605 | goto out; | ||
606 | } | ||
607 | |||
608 | di = (struct ocfs2_dinode *)di_bh->b_data; | ||
609 | data = &di->id2.i_data; | ||
610 | |||
611 | while (*f_pos < i_size_read(inode)) { | ||
612 | revalidate: | ||
613 | /* If the dir block has changed since the last call to | ||
614 | * readdir(2), then we might be pointing to an invalid | ||
615 | * dirent right now. Scan from the start of the block | ||
616 | * to make sure. */ | ||
617 | if (*f_version != inode->i_version) { | ||
618 | for (i = 0; i < i_size_read(inode) && i < offset; ) { | ||
619 | de = (struct ocfs2_dir_entry *) | ||
620 | (data->id_data + i); | ||
621 | /* It's too expensive to do a full | ||
622 | * dirent test each time round this | ||
623 | * loop, but we do have to test at | ||
624 | * least that it is non-zero. A | ||
625 | * failure will be detected in the | ||
626 | * dirent test below. */ | ||
627 | if (le16_to_cpu(de->rec_len) < | ||
628 | OCFS2_DIR_REC_LEN(1)) | ||
629 | break; | ||
630 | i += le16_to_cpu(de->rec_len); | ||
631 | } | ||
632 | *f_pos = offset = i; | ||
633 | *f_version = inode->i_version; | ||
634 | } | ||
635 | |||
636 | de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos); | ||
637 | if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) { | ||
638 | /* On error, skip the f_pos to the end. */ | ||
639 | *f_pos = i_size_read(inode); | ||
640 | goto out; | ||
641 | } | ||
642 | offset += le16_to_cpu(de->rec_len); | ||
643 | if (le64_to_cpu(de->inode)) { | ||
644 | /* We might block in the next section | ||
645 | * if the data destination is | ||
646 | * currently swapped out. So, use a | ||
647 | * version stamp to detect whether or | ||
648 | * not the directory has been modified | ||
649 | * during the copy operation. | ||
650 | */ | ||
651 | unsigned long version = *f_version; | ||
652 | unsigned char d_type = DT_UNKNOWN; | ||
653 | |||
654 | if (de->file_type < OCFS2_FT_MAX) | ||
655 | d_type = ocfs2_filetype_table[de->file_type]; | ||
656 | |||
657 | filldir_ret = filldir(priv, de->name, | ||
658 | de->name_len, | ||
659 | *f_pos, | ||
660 | le64_to_cpu(de->inode), | ||
661 | d_type); | ||
662 | if (filldir_ret) { | ||
663 | if (filldir_err) | ||
664 | *filldir_err = filldir_ret; | ||
665 | break; | ||
666 | } | ||
667 | if (version != *f_version) | ||
668 | goto revalidate; | ||
669 | } | ||
670 | *f_pos += le16_to_cpu(de->rec_len); | ||
671 | } | ||
672 | |||
673 | out: | ||
674 | brelse(di_bh); | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int ocfs2_dir_foreach_blk_el(struct inode *inode, | ||
680 | unsigned long *f_version, | ||
681 | loff_t *f_pos, void *priv, | ||
682 | filldir_t filldir, int *filldir_err) | ||
75 | { | 683 | { |
76 | int error = 0; | 684 | int error = 0; |
77 | unsigned long offset, blk, last_ra_blk = 0; | 685 | unsigned long offset, blk, last_ra_blk = 0; |
@@ -79,45 +687,23 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
79 | struct buffer_head * bh, * tmp; | 687 | struct buffer_head * bh, * tmp; |
80 | struct ocfs2_dir_entry * de; | 688 | struct ocfs2_dir_entry * de; |
81 | int err; | 689 | int err; |
82 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
83 | struct super_block * sb = inode->i_sb; | 690 | struct super_block * sb = inode->i_sb; |
84 | unsigned int ra_sectors = 16; | 691 | unsigned int ra_sectors = 16; |
85 | int lock_level = 0; | ||
86 | |||
87 | mlog_entry("dirino=%llu\n", | ||
88 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
89 | 692 | ||
90 | stored = 0; | 693 | stored = 0; |
91 | bh = NULL; | 694 | bh = NULL; |
92 | 695 | ||
93 | error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); | 696 | offset = (*f_pos) & (sb->s_blocksize - 1); |
94 | if (lock_level && error >= 0) { | ||
95 | /* We release EX lock which used to update atime | ||
96 | * and get PR lock again to reduce contention | ||
97 | * on commonly accessed directories. */ | ||
98 | ocfs2_meta_unlock(inode, 1); | ||
99 | lock_level = 0; | ||
100 | error = ocfs2_meta_lock(inode, NULL, 0); | ||
101 | } | ||
102 | if (error < 0) { | ||
103 | if (error != -ENOENT) | ||
104 | mlog_errno(error); | ||
105 | /* we haven't got any yet, so propagate the error. */ | ||
106 | stored = error; | ||
107 | goto bail_nolock; | ||
108 | } | ||
109 | 697 | ||
110 | offset = filp->f_pos & (sb->s_blocksize - 1); | 698 | while (!error && !stored && *f_pos < i_size_read(inode)) { |
111 | 699 | blk = (*f_pos) >> sb->s_blocksize_bits; | |
112 | while (!error && !stored && filp->f_pos < i_size_read(inode)) { | ||
113 | blk = (filp->f_pos) >> sb->s_blocksize_bits; | ||
114 | bh = ocfs2_bread(inode, blk, &err, 0); | 700 | bh = ocfs2_bread(inode, blk, &err, 0); |
115 | if (!bh) { | 701 | if (!bh) { |
116 | mlog(ML_ERROR, | 702 | mlog(ML_ERROR, |
117 | "directory #%llu contains a hole at offset %lld\n", | 703 | "directory #%llu contains a hole at offset %lld\n", |
118 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 704 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
119 | filp->f_pos); | 705 | *f_pos); |
120 | filp->f_pos += sb->s_blocksize - offset; | 706 | *f_pos += sb->s_blocksize - offset; |
121 | continue; | 707 | continue; |
122 | } | 708 | } |
123 | 709 | ||
@@ -143,7 +729,7 @@ revalidate: | |||
143 | * readdir(2), then we might be pointing to an invalid | 729 | * readdir(2), then we might be pointing to an invalid |
144 | * dirent right now. Scan from the start of the block | 730 | * dirent right now. Scan from the start of the block |
145 | * to make sure. */ | 731 | * to make sure. */ |
146 | if (filp->f_version != inode->i_version) { | 732 | if (*f_version != inode->i_version) { |
147 | for (i = 0; i < sb->s_blocksize && i < offset; ) { | 733 | for (i = 0; i < sb->s_blocksize && i < offset; ) { |
148 | de = (struct ocfs2_dir_entry *) (bh->b_data + i); | 734 | de = (struct ocfs2_dir_entry *) (bh->b_data + i); |
149 | /* It's too expensive to do a full | 735 | /* It's too expensive to do a full |
@@ -158,21 +744,20 @@ revalidate: | |||
158 | i += le16_to_cpu(de->rec_len); | 744 | i += le16_to_cpu(de->rec_len); |
159 | } | 745 | } |
160 | offset = i; | 746 | offset = i; |
161 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 747 | *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) |
162 | | offset; | 748 | | offset; |
163 | filp->f_version = inode->i_version; | 749 | *f_version = inode->i_version; |
164 | } | 750 | } |
165 | 751 | ||
166 | while (!error && filp->f_pos < i_size_read(inode) | 752 | while (!error && *f_pos < i_size_read(inode) |
167 | && offset < sb->s_blocksize) { | 753 | && offset < sb->s_blocksize) { |
168 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); | 754 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); |
169 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { | 755 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { |
170 | /* On error, skip the f_pos to the | 756 | /* On error, skip the f_pos to the |
171 | next block. */ | 757 | next block. */ |
172 | filp->f_pos = (filp->f_pos | | 758 | *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; |
173 | (sb->s_blocksize - 1)) + 1; | ||
174 | brelse(bh); | 759 | brelse(bh); |
175 | goto bail; | 760 | goto out; |
176 | } | 761 | } |
177 | offset += le16_to_cpu(de->rec_len); | 762 | offset += le16_to_cpu(de->rec_len); |
178 | if (le64_to_cpu(de->inode)) { | 763 | if (le64_to_cpu(de->inode)) { |
@@ -183,36 +768,109 @@ revalidate: | |||
183 | * not the directory has been modified | 768 | * not the directory has been modified |
184 | * during the copy operation. | 769 | * during the copy operation. |
185 | */ | 770 | */ |
186 | unsigned long version = filp->f_version; | 771 | unsigned long version = *f_version; |
187 | unsigned char d_type = DT_UNKNOWN; | 772 | unsigned char d_type = DT_UNKNOWN; |
188 | 773 | ||
189 | if (de->file_type < OCFS2_FT_MAX) | 774 | if (de->file_type < OCFS2_FT_MAX) |
190 | d_type = ocfs2_filetype_table[de->file_type]; | 775 | d_type = ocfs2_filetype_table[de->file_type]; |
191 | error = filldir(dirent, de->name, | 776 | error = filldir(priv, de->name, |
192 | de->name_len, | 777 | de->name_len, |
193 | filp->f_pos, | 778 | *f_pos, |
194 | ino_from_blkno(sb, le64_to_cpu(de->inode)), | 779 | le64_to_cpu(de->inode), |
195 | d_type); | 780 | d_type); |
196 | if (error) | 781 | if (error) { |
782 | if (filldir_err) | ||
783 | *filldir_err = error; | ||
197 | break; | 784 | break; |
198 | if (version != filp->f_version) | 785 | } |
786 | if (version != *f_version) | ||
199 | goto revalidate; | 787 | goto revalidate; |
200 | stored ++; | 788 | stored ++; |
201 | } | 789 | } |
202 | filp->f_pos += le16_to_cpu(de->rec_len); | 790 | *f_pos += le16_to_cpu(de->rec_len); |
203 | } | 791 | } |
204 | offset = 0; | 792 | offset = 0; |
205 | brelse(bh); | 793 | brelse(bh); |
206 | } | 794 | } |
207 | 795 | ||
208 | stored = 0; | 796 | stored = 0; |
209 | bail: | 797 | out: |
798 | return stored; | ||
799 | } | ||
800 | |||
801 | static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version, | ||
802 | loff_t *f_pos, void *priv, filldir_t filldir, | ||
803 | int *filldir_err) | ||
804 | { | ||
805 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
806 | return ocfs2_dir_foreach_blk_id(inode, f_version, f_pos, priv, | ||
807 | filldir, filldir_err); | ||
808 | |||
809 | return ocfs2_dir_foreach_blk_el(inode, f_version, f_pos, priv, filldir, | ||
810 | filldir_err); | ||
811 | } | ||
812 | |||
813 | /* | ||
814 | * This is intended to be called from inside other kernel functions, | ||
815 | * so we fake some arguments. | ||
816 | */ | ||
817 | int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | ||
818 | filldir_t filldir) | ||
819 | { | ||
820 | int ret = 0, filldir_err = 0; | ||
821 | unsigned long version = inode->i_version; | ||
822 | |||
823 | while (*f_pos < i_size_read(inode)) { | ||
824 | ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv, | ||
825 | filldir, &filldir_err); | ||
826 | if (ret || filldir_err) | ||
827 | break; | ||
828 | } | ||
829 | |||
830 | if (ret > 0) | ||
831 | ret = -EIO; | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | /* | ||
837 | * ocfs2_readdir() | ||
838 | * | ||
839 | */ | ||
840 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
841 | { | ||
842 | int error = 0; | ||
843 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
844 | int lock_level = 0; | ||
845 | |||
846 | mlog_entry("dirino=%llu\n", | ||
847 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
848 | |||
849 | error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level); | ||
850 | if (lock_level && error >= 0) { | ||
851 | /* We release EX lock which used to update atime | ||
852 | * and get PR lock again to reduce contention | ||
853 | * on commonly accessed directories. */ | ||
854 | ocfs2_meta_unlock(inode, 1); | ||
855 | lock_level = 0; | ||
856 | error = ocfs2_meta_lock(inode, NULL, 0); | ||
857 | } | ||
858 | if (error < 0) { | ||
859 | if (error != -ENOENT) | ||
860 | mlog_errno(error); | ||
861 | /* we haven't got any yet, so propagate the error. */ | ||
862 | goto bail_nolock; | ||
863 | } | ||
864 | |||
865 | error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, | ||
866 | dirent, filldir, NULL); | ||
867 | |||
210 | ocfs2_meta_unlock(inode, lock_level); | 868 | ocfs2_meta_unlock(inode, lock_level); |
211 | 869 | ||
212 | bail_nolock: | 870 | bail_nolock: |
213 | mlog_exit(stored); | 871 | mlog_exit(error); |
214 | 872 | ||
215 | return stored; | 873 | return error; |
216 | } | 874 | } |
217 | 875 | ||
218 | /* | 876 | /* |
@@ -252,6 +910,23 @@ leave: | |||
252 | return status; | 910 | return status; |
253 | } | 911 | } |
254 | 912 | ||
913 | /* | ||
914 | * Convenience function for callers which just want the block number | ||
915 | * mapped to a name and don't require the full dirent info, etc. | ||
916 | */ | ||
917 | int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, | ||
918 | int namelen, u64 *blkno) | ||
919 | { | ||
920 | int ret; | ||
921 | struct buffer_head *bh = NULL; | ||
922 | struct ocfs2_dir_entry *dirent = NULL; | ||
923 | |||
924 | ret = ocfs2_find_files_on_disk(name, namelen, blkno, dir, &bh, &dirent); | ||
925 | brelse(bh); | ||
926 | |||
927 | return ret; | ||
928 | } | ||
929 | |||
255 | /* Check for a name within a directory. | 930 | /* Check for a name within a directory. |
256 | * | 931 | * |
257 | * Return 0 if the name does not exist | 932 | * Return 0 if the name does not exist |
@@ -284,77 +959,414 @@ bail: | |||
284 | return ret; | 959 | return ret; |
285 | } | 960 | } |
286 | 961 | ||
962 | struct ocfs2_empty_dir_priv { | ||
963 | unsigned seen_dot; | ||
964 | unsigned seen_dot_dot; | ||
965 | unsigned seen_other; | ||
966 | }; | ||
967 | static int ocfs2_empty_dir_filldir(void *priv, const char *name, int name_len, | ||
968 | loff_t pos, u64 ino, unsigned type) | ||
969 | { | ||
970 | struct ocfs2_empty_dir_priv *p = priv; | ||
971 | |||
972 | /* | ||
973 | * Check the positions of "." and ".." records to be sure | ||
974 | * they're in the correct place. | ||
975 | */ | ||
976 | if (name_len == 1 && !strncmp(".", name, 1) && pos == 0) { | ||
977 | p->seen_dot = 1; | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | if (name_len == 2 && !strncmp("..", name, 2) && | ||
982 | pos == OCFS2_DIR_REC_LEN(1)) { | ||
983 | p->seen_dot_dot = 1; | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | p->seen_other = 1; | ||
988 | return 1; | ||
989 | } | ||
287 | /* | 990 | /* |
288 | * routine to check that the specified directory is empty (for rmdir) | 991 | * routine to check that the specified directory is empty (for rmdir) |
992 | * | ||
993 | * Returns 1 if dir is empty, zero otherwise. | ||
289 | */ | 994 | */ |
290 | int ocfs2_empty_dir(struct inode *inode) | 995 | int ocfs2_empty_dir(struct inode *inode) |
291 | { | 996 | { |
292 | unsigned long offset; | 997 | int ret; |
293 | struct buffer_head * bh; | 998 | loff_t start = 0; |
294 | struct ocfs2_dir_entry * de, * de1; | 999 | struct ocfs2_empty_dir_priv priv; |
295 | struct super_block * sb; | 1000 | |
296 | int err; | 1001 | memset(&priv, 0, sizeof(priv)); |
1002 | |||
1003 | ret = ocfs2_dir_foreach(inode, &start, &priv, ocfs2_empty_dir_filldir); | ||
1004 | if (ret) | ||
1005 | mlog_errno(ret); | ||
297 | 1006 | ||
298 | sb = inode->i_sb; | 1007 | if (!priv.seen_dot || !priv.seen_dot_dot) { |
299 | if ((i_size_read(inode) < | 1008 | mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n", |
300 | (OCFS2_DIR_REC_LEN(1) + OCFS2_DIR_REC_LEN(2))) || | ||
301 | !(bh = ocfs2_bread(inode, 0, &err, 0))) { | ||
302 | mlog(ML_ERROR, "bad directory (dir #%llu) - no data block\n", | ||
303 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 1009 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
1010 | /* | ||
1011 | * XXX: Is it really safe to allow an unlink to continue? | ||
1012 | */ | ||
304 | return 1; | 1013 | return 1; |
305 | } | 1014 | } |
306 | 1015 | ||
307 | de = (struct ocfs2_dir_entry *) bh->b_data; | 1016 | return !priv.seen_other; |
308 | de1 = (struct ocfs2_dir_entry *) | 1017 | } |
309 | ((char *)de + le16_to_cpu(de->rec_len)); | 1018 | |
310 | if ((le64_to_cpu(de->inode) != OCFS2_I(inode)->ip_blkno) || | 1019 | static void ocfs2_fill_initial_dirents(struct inode *inode, |
311 | !le64_to_cpu(de1->inode) || | 1020 | struct inode *parent, |
312 | strcmp(".", de->name) || | 1021 | char *start, unsigned int size) |
313 | strcmp("..", de1->name)) { | 1022 | { |
314 | mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n", | 1023 | struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start; |
315 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 1024 | |
316 | brelse(bh); | 1025 | de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno); |
317 | return 1; | 1026 | de->name_len = 1; |
1027 | de->rec_len = | ||
1028 | cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
1029 | strcpy(de->name, "."); | ||
1030 | ocfs2_set_de_type(de, S_IFDIR); | ||
1031 | |||
1032 | de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); | ||
1033 | de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno); | ||
1034 | de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1)); | ||
1035 | de->name_len = 2; | ||
1036 | strcpy(de->name, ".."); | ||
1037 | ocfs2_set_de_type(de, S_IFDIR); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * This works together with code in ocfs2_mknod_locked() which sets | ||
1042 | * the inline-data flag and initializes the inline-data section. | ||
1043 | */ | ||
1044 | static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb, | ||
1045 | handle_t *handle, | ||
1046 | struct inode *parent, | ||
1047 | struct inode *inode, | ||
1048 | struct buffer_head *di_bh) | ||
1049 | { | ||
1050 | int ret; | ||
1051 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1052 | struct ocfs2_inline_data *data = &di->id2.i_data; | ||
1053 | unsigned int size = le16_to_cpu(data->id_count); | ||
1054 | |||
1055 | ret = ocfs2_journal_access(handle, inode, di_bh, | ||
1056 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1057 | if (ret) { | ||
1058 | mlog_errno(ret); | ||
1059 | goto out; | ||
318 | } | 1060 | } |
319 | offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); | 1061 | |
320 | de = (struct ocfs2_dir_entry *)((char *)de1 + le16_to_cpu(de1->rec_len)); | 1062 | ocfs2_fill_initial_dirents(inode, parent, data->id_data, size); |
321 | while (offset < i_size_read(inode) ) { | 1063 | |
322 | if (!bh || (void *)de >= (void *)(bh->b_data + sb->s_blocksize)) { | 1064 | ocfs2_journal_dirty(handle, di_bh); |
323 | brelse(bh); | 1065 | if (ret) { |
324 | bh = ocfs2_bread(inode, | 1066 | mlog_errno(ret); |
325 | offset >> sb->s_blocksize_bits, &err, 0); | 1067 | goto out; |
326 | if (!bh) { | 1068 | } |
327 | mlog(ML_ERROR, "dir %llu has a hole at %lu\n", | 1069 | |
328 | (unsigned long long)OCFS2_I(inode)->ip_blkno, offset); | 1070 | i_size_write(inode, size); |
329 | offset += sb->s_blocksize; | 1071 | inode->i_nlink = 2; |
330 | continue; | 1072 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
331 | } | 1073 | |
332 | de = (struct ocfs2_dir_entry *) bh->b_data; | 1074 | ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); |
333 | } | 1075 | if (ret < 0) |
334 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { | 1076 | mlog_errno(ret); |
335 | brelse(bh); | 1077 | |
336 | return 1; | 1078 | out: |
1079 | return ret; | ||
1080 | } | ||
1081 | |||
1082 | static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, | ||
1083 | handle_t *handle, | ||
1084 | struct inode *parent, | ||
1085 | struct inode *inode, | ||
1086 | struct buffer_head *fe_bh, | ||
1087 | struct ocfs2_alloc_context *data_ac) | ||
1088 | { | ||
1089 | int status; | ||
1090 | struct buffer_head *new_bh = NULL; | ||
1091 | |||
1092 | mlog_entry_void(); | ||
1093 | |||
1094 | status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh, | ||
1095 | data_ac, NULL, &new_bh); | ||
1096 | if (status < 0) { | ||
1097 | mlog_errno(status); | ||
1098 | goto bail; | ||
1099 | } | ||
1100 | |||
1101 | ocfs2_set_new_buffer_uptodate(inode, new_bh); | ||
1102 | |||
1103 | status = ocfs2_journal_access(handle, inode, new_bh, | ||
1104 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1105 | if (status < 0) { | ||
1106 | mlog_errno(status); | ||
1107 | goto bail; | ||
1108 | } | ||
1109 | memset(new_bh->b_data, 0, osb->sb->s_blocksize); | ||
1110 | |||
1111 | ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data, | ||
1112 | osb->sb->s_blocksize); | ||
1113 | |||
1114 | status = ocfs2_journal_dirty(handle, new_bh); | ||
1115 | if (status < 0) { | ||
1116 | mlog_errno(status); | ||
1117 | goto bail; | ||
1118 | } | ||
1119 | |||
1120 | i_size_write(inode, inode->i_sb->s_blocksize); | ||
1121 | inode->i_nlink = 2; | ||
1122 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
1123 | status = ocfs2_mark_inode_dirty(handle, inode, fe_bh); | ||
1124 | if (status < 0) { | ||
1125 | mlog_errno(status); | ||
1126 | goto bail; | ||
1127 | } | ||
1128 | |||
1129 | status = 0; | ||
1130 | bail: | ||
1131 | if (new_bh) | ||
1132 | brelse(new_bh); | ||
1133 | |||
1134 | mlog_exit(status); | ||
1135 | return status; | ||
1136 | } | ||
1137 | |||
1138 | int ocfs2_fill_new_dir(struct ocfs2_super *osb, | ||
1139 | handle_t *handle, | ||
1140 | struct inode *parent, | ||
1141 | struct inode *inode, | ||
1142 | struct buffer_head *fe_bh, | ||
1143 | struct ocfs2_alloc_context *data_ac) | ||
1144 | { | ||
1145 | BUG_ON(!ocfs2_supports_inline_data(osb) && data_ac == NULL); | ||
1146 | |||
1147 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
1148 | return ocfs2_fill_new_dir_id(osb, handle, parent, inode, fe_bh); | ||
1149 | |||
1150 | return ocfs2_fill_new_dir_el(osb, handle, parent, inode, fe_bh, | ||
1151 | data_ac); | ||
1152 | } | ||
1153 | |||
1154 | static void ocfs2_expand_last_dirent(char *start, unsigned int old_size, | ||
1155 | unsigned int new_size) | ||
1156 | { | ||
1157 | struct ocfs2_dir_entry *de; | ||
1158 | struct ocfs2_dir_entry *prev_de; | ||
1159 | char *de_buf, *limit; | ||
1160 | unsigned int bytes = new_size - old_size; | ||
1161 | |||
1162 | limit = start + old_size; | ||
1163 | de_buf = start; | ||
1164 | de = (struct ocfs2_dir_entry *)de_buf; | ||
1165 | do { | ||
1166 | prev_de = de; | ||
1167 | de_buf += le16_to_cpu(de->rec_len); | ||
1168 | de = (struct ocfs2_dir_entry *)de_buf; | ||
1169 | } while (de_buf < limit); | ||
1170 | |||
1171 | le16_add_cpu(&prev_de->rec_len, bytes); | ||
1172 | } | ||
1173 | |||
1174 | /* | ||
1175 | * We allocate enough clusters to fulfill "blocks_wanted", but set | ||
1176 | * i_size to exactly one block. Ocfs2_extend_dir() will handle the | ||
1177 | * rest automatically for us. | ||
1178 | * | ||
1179 | * *first_block_bh is a pointer to the 1st data block allocated to the | ||
1180 | * directory. | ||
1181 | */ | ||
1182 | static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | ||
1183 | unsigned int blocks_wanted, | ||
1184 | struct buffer_head **first_block_bh) | ||
1185 | { | ||
1186 | int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS; | ||
1187 | u32 alloc, bit_off, len; | ||
1188 | struct super_block *sb = dir->i_sb; | ||
1189 | u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits; | ||
1190 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | ||
1191 | struct ocfs2_inode_info *oi = OCFS2_I(dir); | ||
1192 | struct ocfs2_alloc_context *data_ac; | ||
1193 | struct buffer_head *dirdata_bh = NULL; | ||
1194 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1195 | handle_t *handle; | ||
1196 | |||
1197 | alloc = ocfs2_clusters_for_bytes(sb, bytes); | ||
1198 | |||
1199 | /* | ||
1200 | * We should never need more than 2 clusters for this - | ||
1201 | * maximum dirent size is far less than one block. In fact, | ||
1202 | * the only time we'd need more than one cluster is if | ||
1203 | * blocksize == clustersize and the dirent won't fit in the | ||
1204 | * extra space that the expansion to a single block gives. As | ||
1205 | * of today, that only happens on 4k/4k file systems. | ||
1206 | */ | ||
1207 | BUG_ON(alloc > 2); | ||
1208 | |||
1209 | ret = ocfs2_reserve_clusters(osb, alloc, &data_ac); | ||
1210 | if (ret) { | ||
1211 | mlog_errno(ret); | ||
1212 | goto out; | ||
1213 | } | ||
1214 | |||
1215 | down_write(&oi->ip_alloc_sem); | ||
1216 | |||
1217 | /* | ||
1218 | * Prepare for worst case allocation scenario of two seperate | ||
1219 | * extents. | ||
1220 | */ | ||
1221 | if (alloc == 2) | ||
1222 | credits += OCFS2_SUBALLOC_ALLOC; | ||
1223 | |||
1224 | handle = ocfs2_start_trans(osb, credits); | ||
1225 | if (IS_ERR(handle)) { | ||
1226 | ret = PTR_ERR(handle); | ||
1227 | mlog_errno(ret); | ||
1228 | goto out_sem; | ||
1229 | } | ||
1230 | |||
1231 | /* | ||
1232 | * Try to claim as many clusters as the bitmap can give though | ||
1233 | * if we only get one now, that's enough to continue. The rest | ||
1234 | * will be claimed after the conversion to extents. | ||
1235 | */ | ||
1236 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len); | ||
1237 | if (ret) { | ||
1238 | mlog_errno(ret); | ||
1239 | goto out_commit; | ||
1240 | } | ||
1241 | |||
1242 | /* | ||
1243 | * Operations are carefully ordered so that we set up the new | ||
1244 | * data block first. The conversion from inline data to | ||
1245 | * extents follows. | ||
1246 | */ | ||
1247 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); | ||
1248 | dirdata_bh = sb_getblk(sb, blkno); | ||
1249 | if (!dirdata_bh) { | ||
1250 | ret = -EIO; | ||
1251 | mlog_errno(ret); | ||
1252 | goto out_commit; | ||
1253 | } | ||
1254 | |||
1255 | ocfs2_set_new_buffer_uptodate(dir, dirdata_bh); | ||
1256 | |||
1257 | ret = ocfs2_journal_access(handle, dir, dirdata_bh, | ||
1258 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1259 | if (ret) { | ||
1260 | mlog_errno(ret); | ||
1261 | goto out_commit; | ||
1262 | } | ||
1263 | |||
1264 | memcpy(dirdata_bh->b_data, di->id2.i_data.id_data, i_size_read(dir)); | ||
1265 | memset(dirdata_bh->b_data + i_size_read(dir), 0, | ||
1266 | sb->s_blocksize - i_size_read(dir)); | ||
1267 | ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir), | ||
1268 | sb->s_blocksize); | ||
1269 | |||
1270 | ret = ocfs2_journal_dirty(handle, dirdata_bh); | ||
1271 | if (ret) { | ||
1272 | mlog_errno(ret); | ||
1273 | goto out_commit; | ||
1274 | } | ||
1275 | |||
1276 | /* | ||
1277 | * Set extent, i_size, etc on the directory. After this, the | ||
1278 | * inode should contain the same exact dirents as before and | ||
1279 | * be fully accessible from system calls. | ||
1280 | * | ||
1281 | * We let the later dirent insert modify c/mtime - to the user | ||
1282 | * the data hasn't changed. | ||
1283 | */ | ||
1284 | ret = ocfs2_journal_access(handle, dir, di_bh, | ||
1285 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1286 | if (ret) { | ||
1287 | mlog_errno(ret); | ||
1288 | goto out_commit; | ||
1289 | } | ||
1290 | |||
1291 | spin_lock(&oi->ip_lock); | ||
1292 | oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL; | ||
1293 | di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features); | ||
1294 | spin_unlock(&oi->ip_lock); | ||
1295 | |||
1296 | ocfs2_dinode_new_extent_list(dir, di); | ||
1297 | |||
1298 | i_size_write(dir, sb->s_blocksize); | ||
1299 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
1300 | |||
1301 | di->i_size = cpu_to_le64(sb->s_blocksize); | ||
1302 | di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec); | ||
1303 | di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(dir->i_ctime.tv_nsec); | ||
1304 | dir->i_blocks = ocfs2_inode_sector_count(dir); | ||
1305 | |||
1306 | /* | ||
1307 | * This should never fail as our extent list is empty and all | ||
1308 | * related blocks have been journaled already. | ||
1309 | */ | ||
1310 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0, | ||
1311 | NULL); | ||
1312 | if (ret) { | ||
1313 | mlog_errno(ret); | ||
1314 | goto out; | ||
1315 | } | ||
1316 | |||
1317 | ret = ocfs2_journal_dirty(handle, di_bh); | ||
1318 | if (ret) { | ||
1319 | mlog_errno(ret); | ||
1320 | goto out_commit; | ||
1321 | } | ||
1322 | |||
1323 | /* | ||
1324 | * We asked for two clusters, but only got one in the 1st | ||
1325 | * pass. Claim the 2nd cluster as a separate extent. | ||
1326 | */ | ||
1327 | if (alloc > len) { | ||
1328 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, | ||
1329 | &len); | ||
1330 | if (ret) { | ||
1331 | mlog_errno(ret); | ||
1332 | goto out_commit; | ||
337 | } | 1333 | } |
338 | if (le64_to_cpu(de->inode)) { | 1334 | blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); |
339 | brelse(bh); | 1335 | |
340 | return 0; | 1336 | ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno, |
1337 | len, 0, NULL); | ||
1338 | if (ret) { | ||
1339 | mlog_errno(ret); | ||
1340 | goto out; | ||
341 | } | 1341 | } |
342 | offset += le16_to_cpu(de->rec_len); | ||
343 | de = (struct ocfs2_dir_entry *) | ||
344 | ((char *)de + le16_to_cpu(de->rec_len)); | ||
345 | } | 1342 | } |
346 | brelse(bh); | 1343 | |
347 | return 1; | 1344 | *first_block_bh = dirdata_bh; |
1345 | dirdata_bh = NULL; | ||
1346 | |||
1347 | out_commit: | ||
1348 | ocfs2_commit_trans(osb, handle); | ||
1349 | |||
1350 | out_sem: | ||
1351 | up_write(&oi->ip_alloc_sem); | ||
1352 | |||
1353 | out: | ||
1354 | if (data_ac) | ||
1355 | ocfs2_free_alloc_context(data_ac); | ||
1356 | |||
1357 | brelse(dirdata_bh); | ||
1358 | |||
1359 | return ret; | ||
348 | } | 1360 | } |
349 | 1361 | ||
350 | /* returns a bh of the 1st new block in the allocation. */ | 1362 | /* returns a bh of the 1st new block in the allocation. */ |
351 | int ocfs2_do_extend_dir(struct super_block *sb, | 1363 | static int ocfs2_do_extend_dir(struct super_block *sb, |
352 | handle_t *handle, | 1364 | handle_t *handle, |
353 | struct inode *dir, | 1365 | struct inode *dir, |
354 | struct buffer_head *parent_fe_bh, | 1366 | struct buffer_head *parent_fe_bh, |
355 | struct ocfs2_alloc_context *data_ac, | 1367 | struct ocfs2_alloc_context *data_ac, |
356 | struct ocfs2_alloc_context *meta_ac, | 1368 | struct ocfs2_alloc_context *meta_ac, |
357 | struct buffer_head **new_bh) | 1369 | struct buffer_head **new_bh) |
358 | { | 1370 | { |
359 | int status; | 1371 | int status; |
360 | int extend; | 1372 | int extend; |
@@ -396,10 +1408,18 @@ bail: | |||
396 | return status; | 1408 | return status; |
397 | } | 1409 | } |
398 | 1410 | ||
399 | /* assumes you already have a cluster lock on the directory. */ | 1411 | /* |
1412 | * Assumes you already have a cluster lock on the directory. | ||
1413 | * | ||
1414 | * 'blocks_wanted' is only used if we have an inline directory which | ||
1415 | * is to be turned into an extent based one. The size of the dirent to | ||
1416 | * insert might be larger than the space gained by growing to just one | ||
1417 | * block, so we may have to grow the inode by two blocks in that case. | ||
1418 | */ | ||
400 | static int ocfs2_extend_dir(struct ocfs2_super *osb, | 1419 | static int ocfs2_extend_dir(struct ocfs2_super *osb, |
401 | struct inode *dir, | 1420 | struct inode *dir, |
402 | struct buffer_head *parent_fe_bh, | 1421 | struct buffer_head *parent_fe_bh, |
1422 | unsigned int blocks_wanted, | ||
403 | struct buffer_head **new_de_bh) | 1423 | struct buffer_head **new_de_bh) |
404 | { | 1424 | { |
405 | int status = 0; | 1425 | int status = 0; |
@@ -415,6 +1435,38 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
415 | 1435 | ||
416 | mlog_entry_void(); | 1436 | mlog_entry_void(); |
417 | 1437 | ||
1438 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1439 | status = ocfs2_expand_inline_dir(dir, parent_fe_bh, | ||
1440 | blocks_wanted, &new_bh); | ||
1441 | if (status) { | ||
1442 | mlog_errno(status); | ||
1443 | goto bail; | ||
1444 | } | ||
1445 | |||
1446 | if (blocks_wanted == 1) { | ||
1447 | /* | ||
1448 | * If the new dirent will fit inside the space | ||
1449 | * created by pushing out to one block, then | ||
1450 | * we can complete the operation | ||
1451 | * here. Otherwise we have to expand i_size | ||
1452 | * and format the 2nd block below. | ||
1453 | */ | ||
1454 | BUG_ON(new_bh == NULL); | ||
1455 | goto bail_bh; | ||
1456 | } | ||
1457 | |||
1458 | /* | ||
1459 | * Get rid of 'new_bh' - we want to format the 2nd | ||
1460 | * data block and return that instead. | ||
1461 | */ | ||
1462 | brelse(new_bh); | ||
1463 | new_bh = NULL; | ||
1464 | |||
1465 | dir_i_size = i_size_read(dir); | ||
1466 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | ||
1467 | goto do_extend; | ||
1468 | } | ||
1469 | |||
418 | dir_i_size = i_size_read(dir); | 1470 | dir_i_size = i_size_read(dir); |
419 | mlog(0, "extending dir %llu (i_size = %lld)\n", | 1471 | mlog(0, "extending dir %llu (i_size = %lld)\n", |
420 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); | 1472 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); |
@@ -452,6 +1504,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
452 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; | 1504 | credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; |
453 | } | 1505 | } |
454 | 1506 | ||
1507 | do_extend: | ||
455 | down_write(&OCFS2_I(dir)->ip_alloc_sem); | 1508 | down_write(&OCFS2_I(dir)->ip_alloc_sem); |
456 | drop_alloc_sem = 1; | 1509 | drop_alloc_sem = 1; |
457 | 1510 | ||
@@ -497,6 +1550,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
497 | goto bail; | 1550 | goto bail; |
498 | } | 1551 | } |
499 | 1552 | ||
1553 | bail_bh: | ||
500 | *new_de_bh = new_bh; | 1554 | *new_de_bh = new_bh; |
501 | get_bh(*new_de_bh); | 1555 | get_bh(*new_de_bh); |
502 | bail: | 1556 | bail: |
@@ -517,41 +1571,71 @@ bail: | |||
517 | return status; | 1571 | return status; |
518 | } | 1572 | } |
519 | 1573 | ||
520 | /* | 1574 | static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh, |
521 | * Search the dir for a good spot, extending it if necessary. The | 1575 | const char *name, int namelen, |
522 | * block containing an appropriate record is returned in ret_de_bh. | 1576 | struct buffer_head **ret_de_bh, |
523 | */ | 1577 | unsigned int *blocks_wanted) |
524 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | ||
525 | struct inode *dir, | ||
526 | struct buffer_head *parent_fe_bh, | ||
527 | const char *name, | ||
528 | int namelen, | ||
529 | struct buffer_head **ret_de_bh) | ||
530 | { | 1578 | { |
531 | unsigned long offset; | 1579 | int ret; |
532 | struct buffer_head * bh = NULL; | 1580 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
533 | unsigned short rec_len; | 1581 | struct ocfs2_dir_entry *de, *last_de = NULL; |
534 | struct ocfs2_dinode *fe; | 1582 | char *de_buf, *limit; |
535 | struct ocfs2_dir_entry *de; | 1583 | unsigned long offset = 0; |
536 | struct super_block *sb; | 1584 | unsigned int rec_len, new_rec_len; |
537 | int status; | 1585 | |
1586 | de_buf = di->id2.i_data.id_data; | ||
1587 | limit = de_buf + i_size_read(dir); | ||
1588 | rec_len = OCFS2_DIR_REC_LEN(namelen); | ||
538 | 1589 | ||
539 | mlog_entry_void(); | 1590 | while (de_buf < limit) { |
1591 | de = (struct ocfs2_dir_entry *)de_buf; | ||
540 | 1592 | ||
541 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", | 1593 | if (!ocfs2_check_dir_entry(dir, de, di_bh, offset)) { |
542 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); | 1594 | ret = -ENOENT; |
1595 | goto out; | ||
1596 | } | ||
1597 | if (ocfs2_match(namelen, name, de)) { | ||
1598 | ret = -EEXIST; | ||
1599 | goto out; | ||
1600 | } | ||
1601 | if (ocfs2_dirent_would_fit(de, rec_len)) { | ||
1602 | /* Ok, we found a spot. Return this bh and let | ||
1603 | * the caller actually fill it in. */ | ||
1604 | *ret_de_bh = di_bh; | ||
1605 | get_bh(*ret_de_bh); | ||
1606 | ret = 0; | ||
1607 | goto out; | ||
1608 | } | ||
543 | 1609 | ||
544 | BUG_ON(!S_ISDIR(dir->i_mode)); | 1610 | last_de = de; |
545 | fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 1611 | de_buf += le16_to_cpu(de->rec_len); |
546 | BUG_ON(le64_to_cpu(fe->i_size) != i_size_read(dir)); | 1612 | offset += le16_to_cpu(de->rec_len); |
1613 | } | ||
547 | 1614 | ||
548 | sb = dir->i_sb; | 1615 | /* |
1616 | * We're going to require expansion of the directory - figure | ||
1617 | * out how many blocks we'll need so that a place for the | ||
1618 | * dirent can be found. | ||
1619 | */ | ||
1620 | *blocks_wanted = 1; | ||
1621 | new_rec_len = le16_to_cpu(last_de->rec_len) + (dir->i_sb->s_blocksize - i_size_read(dir)); | ||
1622 | if (new_rec_len < (rec_len + OCFS2_DIR_REC_LEN(last_de->name_len))) | ||
1623 | *blocks_wanted = 2; | ||
1624 | |||
1625 | ret = -ENOSPC; | ||
1626 | out: | ||
1627 | return ret; | ||
1628 | } | ||
549 | 1629 | ||
550 | if (!namelen) { | 1630 | static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, |
551 | status = -EINVAL; | 1631 | int namelen, struct buffer_head **ret_de_bh) |
552 | mlog_errno(status); | 1632 | { |
553 | goto bail; | 1633 | unsigned long offset; |
554 | } | 1634 | struct buffer_head *bh = NULL; |
1635 | unsigned short rec_len; | ||
1636 | struct ocfs2_dir_entry *de; | ||
1637 | struct super_block *sb = dir->i_sb; | ||
1638 | int status; | ||
555 | 1639 | ||
556 | bh = ocfs2_bread(dir, 0, &status, 0); | 1640 | bh = ocfs2_bread(dir, 0, &status, 0); |
557 | if (!bh) { | 1641 | if (!bh) { |
@@ -568,17 +1652,11 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
568 | bh = NULL; | 1652 | bh = NULL; |
569 | 1653 | ||
570 | if (i_size_read(dir) <= offset) { | 1654 | if (i_size_read(dir) <= offset) { |
571 | status = ocfs2_extend_dir(osb, | 1655 | /* |
572 | dir, | 1656 | * Caller will have to expand this |
573 | parent_fe_bh, | 1657 | * directory. |
574 | &bh); | 1658 | */ |
575 | if (status < 0) { | 1659 | status = -ENOSPC; |
576 | mlog_errno(status); | ||
577 | goto bail; | ||
578 | } | ||
579 | BUG_ON(!bh); | ||
580 | *ret_de_bh = bh; | ||
581 | get_bh(*ret_de_bh); | ||
582 | goto bail; | 1660 | goto bail; |
583 | } | 1661 | } |
584 | bh = ocfs2_bread(dir, | 1662 | bh = ocfs2_bread(dir, |
@@ -600,10 +1678,7 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
600 | status = -EEXIST; | 1678 | status = -EEXIST; |
601 | goto bail; | 1679 | goto bail; |
602 | } | 1680 | } |
603 | if (((le64_to_cpu(de->inode) == 0) && | 1681 | if (ocfs2_dirent_would_fit(de, rec_len)) { |
604 | (le16_to_cpu(de->rec_len) >= rec_len)) || | ||
605 | (le16_to_cpu(de->rec_len) >= | ||
606 | (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) { | ||
607 | /* Ok, we found a spot. Return this bh and let | 1682 | /* Ok, we found a spot. Return this bh and let |
608 | * the caller actually fill it in. */ | 1683 | * the caller actually fill it in. */ |
609 | *ret_de_bh = bh; | 1684 | *ret_de_bh = bh; |
@@ -623,3 +1698,61 @@ bail: | |||
623 | mlog_exit(status); | 1698 | mlog_exit(status); |
624 | return status; | 1699 | return status; |
625 | } | 1700 | } |
1701 | |||
1702 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | ||
1703 | struct inode *dir, | ||
1704 | struct buffer_head *parent_fe_bh, | ||
1705 | const char *name, | ||
1706 | int namelen, | ||
1707 | struct buffer_head **ret_de_bh) | ||
1708 | { | ||
1709 | int ret; | ||
1710 | unsigned int blocks_wanted = 1; | ||
1711 | struct buffer_head *bh = NULL; | ||
1712 | |||
1713 | mlog(0, "getting ready to insert namelen %d into dir %llu\n", | ||
1714 | namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); | ||
1715 | |||
1716 | *ret_de_bh = NULL; | ||
1717 | |||
1718 | if (!namelen) { | ||
1719 | ret = -EINVAL; | ||
1720 | mlog_errno(ret); | ||
1721 | goto out; | ||
1722 | } | ||
1723 | |||
1724 | if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1725 | ret = ocfs2_find_dir_space_id(dir, parent_fe_bh, name, | ||
1726 | namelen, &bh, &blocks_wanted); | ||
1727 | } else | ||
1728 | ret = ocfs2_find_dir_space_el(dir, name, namelen, &bh); | ||
1729 | |||
1730 | if (ret && ret != -ENOSPC) { | ||
1731 | mlog_errno(ret); | ||
1732 | goto out; | ||
1733 | } | ||
1734 | |||
1735 | if (ret == -ENOSPC) { | ||
1736 | /* | ||
1737 | * We have to expand the directory to add this name. | ||
1738 | */ | ||
1739 | BUG_ON(bh); | ||
1740 | |||
1741 | ret = ocfs2_extend_dir(osb, dir, parent_fe_bh, blocks_wanted, | ||
1742 | &bh); | ||
1743 | if (ret) { | ||
1744 | if (ret != -ENOSPC) | ||
1745 | mlog_errno(ret); | ||
1746 | goto out; | ||
1747 | } | ||
1748 | |||
1749 | BUG_ON(!bh); | ||
1750 | } | ||
1751 | |||
1752 | *ret_de_bh = bh; | ||
1753 | bh = NULL; | ||
1754 | out: | ||
1755 | if (bh) | ||
1756 | brelse(bh); | ||
1757 | return ret; | ||
1758 | } | ||
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h index 3f67e146864a..ce48b9080d87 100644 --- a/fs/ocfs2/dir.h +++ b/fs/ocfs2/dir.h | |||
@@ -26,17 +26,49 @@ | |||
26 | #ifndef OCFS2_DIR_H | 26 | #ifndef OCFS2_DIR_H |
27 | #define OCFS2_DIR_H | 27 | #define OCFS2_DIR_H |
28 | 28 | ||
29 | struct buffer_head *ocfs2_find_entry(const char *name, | ||
30 | int namelen, | ||
31 | struct inode *dir, | ||
32 | struct ocfs2_dir_entry **res_dir); | ||
33 | int ocfs2_delete_entry(handle_t *handle, | ||
34 | struct inode *dir, | ||
35 | struct ocfs2_dir_entry *de_del, | ||
36 | struct buffer_head *bh); | ||
37 | int __ocfs2_add_entry(handle_t *handle, | ||
38 | struct inode *dir, | ||
39 | const char *name, int namelen, | ||
40 | struct inode *inode, u64 blkno, | ||
41 | struct buffer_head *parent_fe_bh, | ||
42 | struct buffer_head *insert_bh); | ||
43 | static inline int ocfs2_add_entry(handle_t *handle, | ||
44 | struct dentry *dentry, | ||
45 | struct inode *inode, u64 blkno, | ||
46 | struct buffer_head *parent_fe_bh, | ||
47 | struct buffer_head *insert_bh) | ||
48 | { | ||
49 | return __ocfs2_add_entry(handle, dentry->d_parent->d_inode, | ||
50 | dentry->d_name.name, dentry->d_name.len, | ||
51 | inode, blkno, parent_fe_bh, insert_bh); | ||
52 | } | ||
53 | int ocfs2_update_entry(struct inode *dir, handle_t *handle, | ||
54 | struct buffer_head *de_bh, struct ocfs2_dir_entry *de, | ||
55 | struct inode *new_entry_inode); | ||
56 | |||
29 | int ocfs2_check_dir_for_entry(struct inode *dir, | 57 | int ocfs2_check_dir_for_entry(struct inode *dir, |
30 | const char *name, | 58 | const char *name, |
31 | int namelen); | 59 | int namelen); |
32 | int ocfs2_empty_dir(struct inode *inode); /* FIXME: to namei.c */ | 60 | int ocfs2_empty_dir(struct inode *inode); |
33 | int ocfs2_find_files_on_disk(const char *name, | 61 | int ocfs2_find_files_on_disk(const char *name, |
34 | int namelen, | 62 | int namelen, |
35 | u64 *blkno, | 63 | u64 *blkno, |
36 | struct inode *inode, | 64 | struct inode *inode, |
37 | struct buffer_head **dirent_bh, | 65 | struct buffer_head **dirent_bh, |
38 | struct ocfs2_dir_entry **dirent); | 66 | struct ocfs2_dir_entry **dirent); |
67 | int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, | ||
68 | int namelen, u64 *blkno); | ||
39 | int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); | 69 | int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); |
70 | int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | ||
71 | filldir_t filldir); | ||
40 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | 72 | int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, |
41 | struct inode *dir, | 73 | struct inode *dir, |
42 | struct buffer_head *parent_fe_bh, | 74 | struct buffer_head *parent_fe_bh, |
@@ -44,11 +76,11 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, | |||
44 | int namelen, | 76 | int namelen, |
45 | struct buffer_head **ret_de_bh); | 77 | struct buffer_head **ret_de_bh); |
46 | struct ocfs2_alloc_context; | 78 | struct ocfs2_alloc_context; |
47 | int ocfs2_do_extend_dir(struct super_block *sb, | 79 | int ocfs2_fill_new_dir(struct ocfs2_super *osb, |
48 | handle_t *handle, | 80 | handle_t *handle, |
49 | struct inode *dir, | 81 | struct inode *parent, |
50 | struct buffer_head *parent_fe_bh, | 82 | struct inode *inode, |
51 | struct ocfs2_alloc_context *data_ac, | 83 | struct buffer_head *fe_bh, |
52 | struct ocfs2_alloc_context *meta_ac, | 84 | struct ocfs2_alloc_context *data_ac); |
53 | struct buffer_head **new_bh); | 85 | |
54 | #endif /* OCFS2_DIR_H */ | 86 | #endif /* OCFS2_DIR_H */ |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index f71250ed166f..41c76ff2fcfb 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -1482,6 +1482,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) | |||
1482 | lvb->lvb_imtime_packed = | 1482 | lvb->lvb_imtime_packed = |
1483 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); | 1483 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); |
1484 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); | 1484 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); |
1485 | lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features); | ||
1485 | lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); | 1486 | lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); |
1486 | 1487 | ||
1487 | out: | 1488 | out: |
@@ -1515,6 +1516,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | |||
1515 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); | 1516 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); |
1516 | 1517 | ||
1517 | oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); | 1518 | oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); |
1519 | oi->ip_dyn_features = be16_to_cpu(lvb->lvb_idynfeatures); | ||
1518 | ocfs2_set_inode_flags(inode); | 1520 | ocfs2_set_inode_flags(inode); |
1519 | 1521 | ||
1520 | /* fast-symlinks are a special case */ | 1522 | /* fast-symlinks are a special case */ |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 492bad32a8c0..87a785e41205 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
@@ -29,12 +29,12 @@ | |||
29 | 29 | ||
30 | #include "dcache.h" | 30 | #include "dcache.h" |
31 | 31 | ||
32 | #define OCFS2_LVB_VERSION 4 | 32 | #define OCFS2_LVB_VERSION 5 |
33 | 33 | ||
34 | struct ocfs2_meta_lvb { | 34 | struct ocfs2_meta_lvb { |
35 | __u8 lvb_version; | 35 | __u8 lvb_version; |
36 | __u8 lvb_reserved0; | 36 | __u8 lvb_reserved0; |
37 | __be16 lvb_reserved1; | 37 | __be16 lvb_idynfeatures; |
38 | __be32 lvb_iclusters; | 38 | __be32 lvb_iclusters; |
39 | __be32 lvb_iuid; | 39 | __be32 lvb_iuid; |
40 | __be32 lvb_igid; | 40 | __be32 lvb_igid; |
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index bc48177bd183..c3bbc198f9ce 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c | |||
@@ -88,8 +88,6 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) | |||
88 | struct dentry *parent; | 88 | struct dentry *parent; |
89 | struct inode *inode; | 89 | struct inode *inode; |
90 | struct inode *dir = child->d_inode; | 90 | struct inode *dir = child->d_inode; |
91 | struct buffer_head *dirent_bh = NULL; | ||
92 | struct ocfs2_dir_entry *dirent; | ||
93 | 91 | ||
94 | mlog_entry("(0x%p, '%.*s')\n", child, | 92 | mlog_entry("(0x%p, '%.*s')\n", child, |
95 | child->d_name.len, child->d_name.name); | 93 | child->d_name.len, child->d_name.name); |
@@ -105,8 +103,7 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) | |||
105 | goto bail; | 103 | goto bail; |
106 | } | 104 | } |
107 | 105 | ||
108 | status = ocfs2_find_files_on_disk("..", 2, &blkno, dir, &dirent_bh, | 106 | status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno); |
109 | &dirent); | ||
110 | if (status < 0) { | 107 | if (status < 0) { |
111 | parent = ERR_PTR(-ENOENT); | 108 | parent = ERR_PTR(-ENOENT); |
112 | goto bail_unlock; | 109 | goto bail_unlock; |
@@ -131,9 +128,6 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) | |||
131 | bail_unlock: | 128 | bail_unlock: |
132 | ocfs2_meta_unlock(dir, 0); | 129 | ocfs2_meta_unlock(dir, 0); |
133 | 130 | ||
134 | if (dirent_bh) | ||
135 | brelse(dirent_bh); | ||
136 | |||
137 | bail: | 131 | bail: |
138 | mlog_exit_ptr(parent); | 132 | mlog_exit_ptr(parent); |
139 | 133 | ||
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 03c1d365c78b..c58668a326fe 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c | |||
@@ -387,6 +387,12 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | |||
387 | struct ocfs2_extent_rec *rec; | 387 | struct ocfs2_extent_rec *rec; |
388 | u32 coff; | 388 | u32 coff; |
389 | 389 | ||
390 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
391 | ret = -ERANGE; | ||
392 | mlog_errno(ret); | ||
393 | goto out; | ||
394 | } | ||
395 | |||
390 | ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster, | 396 | ret = ocfs2_extent_map_lookup(inode, v_cluster, p_cluster, |
391 | num_clusters, extent_flags); | 397 | num_clusters, extent_flags); |
392 | if (ret == 0) | 398 | if (ret == 0) |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f3bc3658e7a5..a62b14eb4065 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -397,6 +397,15 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
397 | unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); | 397 | unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); |
398 | truncate_inode_pages(inode->i_mapping, new_i_size); | 398 | truncate_inode_pages(inode->i_mapping, new_i_size); |
399 | 399 | ||
400 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
401 | status = ocfs2_truncate_inline(inode, di_bh, new_i_size, | ||
402 | i_size_read(inode), 0); | ||
403 | if (status) | ||
404 | mlog_errno(status); | ||
405 | |||
406 | goto bail_unlock_data; | ||
407 | } | ||
408 | |||
400 | /* alright, we're going to need to do a full blown alloc size | 409 | /* alright, we're going to need to do a full blown alloc size |
401 | * change. Orphan the inode so that recovery can complete the | 410 | * change. Orphan the inode so that recovery can complete the |
402 | * truncate if necessary. This does the task of marking | 411 | * truncate if necessary. This does the task of marking |
@@ -779,25 +788,6 @@ leave: | |||
779 | return status; | 788 | return status; |
780 | } | 789 | } |
781 | 790 | ||
782 | static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | ||
783 | u32 clusters_to_add, int mark_unwritten) | ||
784 | { | ||
785 | int ret; | ||
786 | |||
787 | /* | ||
788 | * The alloc sem blocks peope in read/write from reading our | ||
789 | * allocation until we're done changing it. We depend on | ||
790 | * i_mutex to block other extend/truncate calls while we're | ||
791 | * here. | ||
792 | */ | ||
793 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | ||
794 | ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add, | ||
795 | mark_unwritten); | ||
796 | up_write(&OCFS2_I(inode)->ip_alloc_sem); | ||
797 | |||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | /* Some parts of this taken from generic_cont_expand, which turned out | 791 | /* Some parts of this taken from generic_cont_expand, which turned out |
802 | * to be too fragile to do exactly what we need without us having to | 792 | * to be too fragile to do exactly what we need without us having to |
803 | * worry about recursive locking in ->prepare_write() and | 793 | * worry about recursive locking in ->prepare_write() and |
@@ -889,25 +879,48 @@ out: | |||
889 | return ret; | 879 | return ret; |
890 | } | 880 | } |
891 | 881 | ||
892 | /* | 882 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, u64 zero_to) |
893 | * A tail_to_skip value > 0 indicates that we're being called from | 883 | { |
894 | * ocfs2_file_aio_write(). This has the following implications: | 884 | int ret; |
895 | * | 885 | u32 clusters_to_add; |
896 | * - we don't want to update i_size | 886 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
897 | * - di_bh will be NULL, which is fine because it's only used in the | 887 | |
898 | * case where we want to update i_size. | 888 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size); |
899 | * - ocfs2_zero_extend() will then only be filling the hole created | 889 | if (clusters_to_add < oi->ip_clusters) |
900 | * between i_size and the start of the write. | 890 | clusters_to_add = 0; |
901 | */ | 891 | else |
892 | clusters_to_add -= oi->ip_clusters; | ||
893 | |||
894 | if (clusters_to_add) { | ||
895 | ret = __ocfs2_extend_allocation(inode, oi->ip_clusters, | ||
896 | clusters_to_add, 0); | ||
897 | if (ret) { | ||
898 | mlog_errno(ret); | ||
899 | goto out; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | /* | ||
904 | * Call this even if we don't add any clusters to the tree. We | ||
905 | * still need to zero the area between the old i_size and the | ||
906 | * new i_size. | ||
907 | */ | ||
908 | ret = ocfs2_zero_extend(inode, zero_to); | ||
909 | if (ret < 0) | ||
910 | mlog_errno(ret); | ||
911 | |||
912 | out: | ||
913 | return ret; | ||
914 | } | ||
915 | |||
902 | static int ocfs2_extend_file(struct inode *inode, | 916 | static int ocfs2_extend_file(struct inode *inode, |
903 | struct buffer_head *di_bh, | 917 | struct buffer_head *di_bh, |
904 | u64 new_i_size, | 918 | u64 new_i_size) |
905 | size_t tail_to_skip) | ||
906 | { | 919 | { |
907 | int ret = 0; | 920 | int ret = 0, data_locked = 0; |
908 | u32 clusters_to_add = 0; | 921 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
909 | 922 | ||
910 | BUG_ON(!tail_to_skip && !di_bh); | 923 | BUG_ON(!di_bh); |
911 | 924 | ||
912 | /* setattr sometimes calls us like this. */ | 925 | /* setattr sometimes calls us like this. */ |
913 | if (new_i_size == 0) | 926 | if (new_i_size == 0) |
@@ -917,13 +930,18 @@ static int ocfs2_extend_file(struct inode *inode, | |||
917 | goto out; | 930 | goto out; |
918 | BUG_ON(new_i_size < i_size_read(inode)); | 931 | BUG_ON(new_i_size < i_size_read(inode)); |
919 | 932 | ||
920 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { | 933 | /* |
921 | BUG_ON(tail_to_skip != 0); | 934 | * Fall through for converting inline data, even if the fs |
935 | * supports sparse files. | ||
936 | * | ||
937 | * The check for inline data here is legal - nobody can add | ||
938 | * the feature since we have i_mutex. We must check it again | ||
939 | * after acquiring ip_alloc_sem though, as paths like mmap | ||
940 | * might have raced us to converting the inode to extents. | ||
941 | */ | ||
942 | if (!(oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
943 | && ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | ||
922 | goto out_update_size; | 944 | goto out_update_size; |
923 | } | ||
924 | |||
925 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - | ||
926 | OCFS2_I(inode)->ip_clusters; | ||
927 | 945 | ||
928 | /* | 946 | /* |
929 | * protect the pages that ocfs2_zero_extend is going to be | 947 | * protect the pages that ocfs2_zero_extend is going to be |
@@ -937,39 +955,52 @@ static int ocfs2_extend_file(struct inode *inode, | |||
937 | mlog_errno(ret); | 955 | mlog_errno(ret); |
938 | goto out; | 956 | goto out; |
939 | } | 957 | } |
958 | data_locked = 1; | ||
959 | |||
960 | /* | ||
961 | * The alloc sem blocks people in read/write from reading our | ||
962 | * allocation until we're done changing it. We depend on | ||
963 | * i_mutex to block other extend/truncate calls while we're | ||
964 | * here. | ||
965 | */ | ||
966 | down_write(&oi->ip_alloc_sem); | ||
967 | |||
968 | if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
969 | /* | ||
970 | * We can optimize small extends by keeping the inodes | ||
971 | * inline data. | ||
972 | */ | ||
973 | if (ocfs2_size_fits_inline_data(di_bh, new_i_size)) { | ||
974 | up_write(&oi->ip_alloc_sem); | ||
975 | goto out_update_size; | ||
976 | } | ||
977 | |||
978 | ret = ocfs2_convert_inline_data_to_extents(inode, di_bh); | ||
979 | if (ret) { | ||
980 | up_write(&oi->ip_alloc_sem); | ||
940 | 981 | ||
941 | if (clusters_to_add) { | ||
942 | ret = ocfs2_extend_allocation(inode, | ||
943 | OCFS2_I(inode)->ip_clusters, | ||
944 | clusters_to_add, 0); | ||
945 | if (ret < 0) { | ||
946 | mlog_errno(ret); | 982 | mlog_errno(ret); |
947 | goto out_unlock; | 983 | goto out_unlock; |
948 | } | 984 | } |
949 | } | 985 | } |
950 | 986 | ||
951 | /* | 987 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) |
952 | * Call this even if we don't add any clusters to the tree. We | 988 | ret = ocfs2_extend_no_holes(inode, new_i_size, new_i_size); |
953 | * still need to zero the area between the old i_size and the | 989 | |
954 | * new i_size. | 990 | up_write(&oi->ip_alloc_sem); |
955 | */ | 991 | |
956 | ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); | ||
957 | if (ret < 0) { | 992 | if (ret < 0) { |
958 | mlog_errno(ret); | 993 | mlog_errno(ret); |
959 | goto out_unlock; | 994 | goto out_unlock; |
960 | } | 995 | } |
961 | 996 | ||
962 | out_update_size: | 997 | out_update_size: |
963 | if (!tail_to_skip) { | 998 | ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); |
964 | /* We're being called from ocfs2_setattr() which wants | 999 | if (ret < 0) |
965 | * us to update i_size */ | 1000 | mlog_errno(ret); |
966 | ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); | ||
967 | if (ret < 0) | ||
968 | mlog_errno(ret); | ||
969 | } | ||
970 | 1001 | ||
971 | out_unlock: | 1002 | out_unlock: |
972 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | 1003 | if (data_locked) |
973 | ocfs2_data_unlock(inode, 1); | 1004 | ocfs2_data_unlock(inode, 1); |
974 | 1005 | ||
975 | out: | 1006 | out: |
@@ -1035,7 +1066,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
1035 | if (i_size_read(inode) > attr->ia_size) | 1066 | if (i_size_read(inode) > attr->ia_size) |
1036 | status = ocfs2_truncate_file(inode, bh, attr->ia_size); | 1067 | status = ocfs2_truncate_file(inode, bh, attr->ia_size); |
1037 | else | 1068 | else |
1038 | status = ocfs2_extend_file(inode, bh, attr->ia_size, 0); | 1069 | status = ocfs2_extend_file(inode, bh, attr->ia_size); |
1039 | if (status < 0) { | 1070 | if (status < 0) { |
1040 | if (status != -ENOSPC) | 1071 | if (status != -ENOSPC) |
1041 | mlog_errno(status); | 1072 | mlog_errno(status); |
@@ -1243,6 +1274,31 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode, | |||
1243 | { | 1274 | { |
1244 | int ret; | 1275 | int ret; |
1245 | u32 cpos, phys_cpos, clusters, alloc_size; | 1276 | u32 cpos, phys_cpos, clusters, alloc_size; |
1277 | u64 end = start + len; | ||
1278 | struct buffer_head *di_bh = NULL; | ||
1279 | |||
1280 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1281 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), | ||
1282 | OCFS2_I(inode)->ip_blkno, &di_bh, | ||
1283 | OCFS2_BH_CACHED, inode); | ||
1284 | if (ret) { | ||
1285 | mlog_errno(ret); | ||
1286 | goto out; | ||
1287 | } | ||
1288 | |||
1289 | /* | ||
1290 | * Nothing to do if the requested reservation range | ||
1291 | * fits within the inode. | ||
1292 | */ | ||
1293 | if (ocfs2_size_fits_inline_data(di_bh, end)) | ||
1294 | goto out; | ||
1295 | |||
1296 | ret = ocfs2_convert_inline_data_to_extents(inode, di_bh); | ||
1297 | if (ret) { | ||
1298 | mlog_errno(ret); | ||
1299 | goto out; | ||
1300 | } | ||
1301 | } | ||
1246 | 1302 | ||
1247 | /* | 1303 | /* |
1248 | * We consider both start and len to be inclusive. | 1304 | * We consider both start and len to be inclusive. |
@@ -1288,6 +1344,8 @@ next: | |||
1288 | 1344 | ||
1289 | ret = 0; | 1345 | ret = 0; |
1290 | out: | 1346 | out: |
1347 | |||
1348 | brelse(di_bh); | ||
1291 | return ret; | 1349 | return ret; |
1292 | } | 1350 | } |
1293 | 1351 | ||
@@ -1469,6 +1527,14 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1469 | if (byte_len == 0) | 1527 | if (byte_len == 0) |
1470 | return 0; | 1528 | return 0; |
1471 | 1529 | ||
1530 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | ||
1531 | ret = ocfs2_truncate_inline(inode, di_bh, byte_start, | ||
1532 | byte_start + byte_len, 1); | ||
1533 | if (ret) | ||
1534 | mlog_errno(ret); | ||
1535 | return ret; | ||
1536 | } | ||
1537 | |||
1472 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); | 1538 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); |
1473 | trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; | 1539 | trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; |
1474 | if (trunc_len >= trunc_start) | 1540 | if (trunc_len >= trunc_start) |
@@ -1713,15 +1779,13 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
1713 | int appending, | 1779 | int appending, |
1714 | int *direct_io) | 1780 | int *direct_io) |
1715 | { | 1781 | { |
1716 | int ret = 0, meta_level = appending; | 1782 | int ret = 0, meta_level = 0; |
1717 | struct inode *inode = dentry->d_inode; | 1783 | struct inode *inode = dentry->d_inode; |
1718 | u32 clusters; | 1784 | loff_t saved_pos, end; |
1719 | loff_t newsize, saved_pos; | ||
1720 | 1785 | ||
1721 | /* | 1786 | /* |
1722 | * We sample i_size under a read level meta lock to see if our write | 1787 | * We start with a read level meta lock and only jump to an ex |
1723 | * is extending the file, if it is we back off and get a write level | 1788 | * if we need to make modifications here. |
1724 | * meta lock. | ||
1725 | */ | 1789 | */ |
1726 | for(;;) { | 1790 | for(;;) { |
1727 | ret = ocfs2_meta_lock(inode, NULL, meta_level); | 1791 | ret = ocfs2_meta_lock(inode, NULL, meta_level); |
@@ -1763,87 +1827,47 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
1763 | saved_pos = *ppos; | 1827 | saved_pos = *ppos; |
1764 | } | 1828 | } |
1765 | 1829 | ||
1766 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { | 1830 | end = saved_pos + count; |
1767 | loff_t end = saved_pos + count; | ||
1768 | 1831 | ||
1769 | /* | 1832 | /* |
1770 | * Skip the O_DIRECT checks if we don't need | 1833 | * Skip the O_DIRECT checks if we don't need |
1771 | * them. | 1834 | * them. |
1772 | */ | 1835 | */ |
1773 | if (!direct_io || !(*direct_io)) | 1836 | if (!direct_io || !(*direct_io)) |
1774 | break; | ||
1775 | |||
1776 | /* | ||
1777 | * Allowing concurrent direct writes means | ||
1778 | * i_size changes wouldn't be synchronized, so | ||
1779 | * one node could wind up truncating another | ||
1780 | * nodes writes. | ||
1781 | */ | ||
1782 | if (end > i_size_read(inode)) { | ||
1783 | *direct_io = 0; | ||
1784 | break; | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | * We don't fill holes during direct io, so | ||
1789 | * check for them here. If any are found, the | ||
1790 | * caller will have to retake some cluster | ||
1791 | * locks and initiate the io as buffered. | ||
1792 | */ | ||
1793 | ret = ocfs2_check_range_for_holes(inode, saved_pos, | ||
1794 | count); | ||
1795 | if (ret == 1) { | ||
1796 | *direct_io = 0; | ||
1797 | ret = 0; | ||
1798 | } else if (ret < 0) | ||
1799 | mlog_errno(ret); | ||
1800 | break; | 1837 | break; |
1801 | } | ||
1802 | 1838 | ||
1803 | /* | 1839 | /* |
1804 | * The rest of this loop is concerned with legacy file | 1840 | * There's no sane way to do direct writes to an inode |
1805 | * systems which don't support sparse files. | 1841 | * with inline data. |
1806 | */ | 1842 | */ |
1807 | 1843 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | |
1808 | newsize = count + saved_pos; | 1844 | *direct_io = 0; |
1809 | |||
1810 | mlog(0, "pos=%lld newsize=%lld cursize=%lld\n", | ||
1811 | (long long) saved_pos, (long long) newsize, | ||
1812 | (long long) i_size_read(inode)); | ||
1813 | |||
1814 | /* No need for a higher level metadata lock if we're | ||
1815 | * never going past i_size. */ | ||
1816 | if (newsize <= i_size_read(inode)) | ||
1817 | break; | 1845 | break; |
1818 | |||
1819 | if (meta_level == 0) { | ||
1820 | ocfs2_meta_unlock(inode, meta_level); | ||
1821 | meta_level = 1; | ||
1822 | continue; | ||
1823 | } | 1846 | } |
1824 | 1847 | ||
1825 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1848 | /* |
1826 | clusters = ocfs2_clusters_for_bytes(inode->i_sb, newsize) - | 1849 | * Allowing concurrent direct writes means |
1827 | OCFS2_I(inode)->ip_clusters; | 1850 | * i_size changes wouldn't be synchronized, so |
1828 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1851 | * one node could wind up truncating another |
1829 | 1852 | * nodes writes. | |
1830 | mlog(0, "Writing at EOF, may need more allocation: " | 1853 | */ |
1831 | "i_size = %lld, newsize = %lld, need %u clusters\n", | 1854 | if (end > i_size_read(inode)) { |
1832 | (long long) i_size_read(inode), (long long) newsize, | 1855 | *direct_io = 0; |
1833 | clusters); | ||
1834 | |||
1835 | /* We only want to continue the rest of this loop if | ||
1836 | * our extend will actually require more | ||
1837 | * allocation. */ | ||
1838 | if (!clusters) | ||
1839 | break; | 1856 | break; |
1840 | |||
1841 | ret = ocfs2_extend_file(inode, NULL, newsize, count); | ||
1842 | if (ret < 0) { | ||
1843 | if (ret != -ENOSPC) | ||
1844 | mlog_errno(ret); | ||
1845 | goto out_unlock; | ||
1846 | } | 1857 | } |
1858 | |||
1859 | /* | ||
1860 | * We don't fill holes during direct io, so | ||
1861 | * check for them here. If any are found, the | ||
1862 | * caller will have to retake some cluster | ||
1863 | * locks and initiate the io as buffered. | ||
1864 | */ | ||
1865 | ret = ocfs2_check_range_for_holes(inode, saved_pos, count); | ||
1866 | if (ret == 1) { | ||
1867 | *direct_io = 0; | ||
1868 | ret = 0; | ||
1869 | } else if (ret < 0) | ||
1870 | mlog_errno(ret); | ||
1847 | break; | 1871 | break; |
1848 | } | 1872 | } |
1849 | 1873 | ||
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 36fe27f268ee..066f14add3a8 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
@@ -47,6 +47,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |||
47 | struct ocfs2_alloc_context *data_ac, | 47 | struct ocfs2_alloc_context *data_ac, |
48 | struct ocfs2_alloc_context *meta_ac, | 48 | struct ocfs2_alloc_context *meta_ac, |
49 | enum ocfs2_alloc_restarted *reason_ret); | 49 | enum ocfs2_alloc_restarted *reason_ret); |
50 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, | ||
51 | u64 zero_to); | ||
50 | int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di, | 52 | int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di, |
51 | u32 clusters_to_add, u32 extents_to_split, | 53 | u32 clusters_to_add, u32 extents_to_split, |
52 | struct ocfs2_alloc_context **data_ac, | 54 | struct ocfs2_alloc_context **data_ac, |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index c53a6763bbbe..1d5e0cb0fda1 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -241,6 +241,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
241 | 241 | ||
242 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 242 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
243 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | 243 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); |
244 | OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features); | ||
244 | 245 | ||
245 | inode->i_version = 1; | 246 | inode->i_version = 1; |
246 | inode->i_generation = le32_to_cpu(fe->i_generation); | 247 | inode->i_generation = le32_to_cpu(fe->i_generation); |
@@ -513,6 +514,10 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, | |||
513 | 514 | ||
514 | fe = (struct ocfs2_dinode *) fe_bh->b_data; | 515 | fe = (struct ocfs2_dinode *) fe_bh->b_data; |
515 | 516 | ||
517 | /* | ||
518 | * This check will also skip truncate of inodes with inline | ||
519 | * data and fast symlinks. | ||
520 | */ | ||
516 | if (fe->i_clusters) { | 521 | if (fe->i_clusters) { |
517 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 522 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); |
518 | if (IS_ERR(handle)) { | 523 | if (IS_ERR(handle)) { |
@@ -1220,6 +1225,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, | |||
1220 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); | 1225 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); |
1221 | ocfs2_get_inode_flags(OCFS2_I(inode)); | 1226 | ocfs2_get_inode_flags(OCFS2_I(inode)); |
1222 | fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); | 1227 | fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); |
1228 | fe->i_dyn_features = cpu_to_le16(OCFS2_I(inode)->ip_dyn_features); | ||
1223 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1229 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1224 | 1230 | ||
1225 | fe->i_size = cpu_to_le64(i_size_read(inode)); | 1231 | fe->i_size = cpu_to_le64(i_size_read(inode)); |
@@ -1257,6 +1263,7 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1257 | 1263 | ||
1258 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 1264 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
1259 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | 1265 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); |
1266 | OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features); | ||
1260 | ocfs2_set_inode_flags(inode); | 1267 | ocfs2_set_inode_flags(inode); |
1261 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 1268 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
1262 | inode->i_nlink = le16_to_cpu(fe->i_links_count); | 1269 | inode->i_nlink = le16_to_cpu(fe->i_links_count); |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index a41d0817121b..70e881c55536 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
@@ -51,6 +51,7 @@ struct ocfs2_inode_info | |||
51 | 51 | ||
52 | u32 ip_flags; /* see below */ | 52 | u32 ip_flags; /* see below */ |
53 | u32 ip_attr; /* inode attributes */ | 53 | u32 ip_attr; /* inode attributes */ |
54 | u16 ip_dyn_features; | ||
54 | 55 | ||
55 | /* protected by recovery_lock. */ | 56 | /* protected by recovery_lock. */ |
56 | struct inode *ip_next_orphan; | 57 | struct inode *ip_next_orphan; |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index dbfb20bb27ea..f9d01e25298d 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -35,13 +35,13 @@ | |||
35 | #include "ocfs2.h" | 35 | #include "ocfs2.h" |
36 | 36 | ||
37 | #include "alloc.h" | 37 | #include "alloc.h" |
38 | #include "dir.h" | ||
38 | #include "dlmglue.h" | 39 | #include "dlmglue.h" |
39 | #include "extent_map.h" | 40 | #include "extent_map.h" |
40 | #include "heartbeat.h" | 41 | #include "heartbeat.h" |
41 | #include "inode.h" | 42 | #include "inode.h" |
42 | #include "journal.h" | 43 | #include "journal.h" |
43 | #include "localalloc.h" | 44 | #include "localalloc.h" |
44 | #include "namei.h" | ||
45 | #include "slot_map.h" | 45 | #include "slot_map.h" |
46 | #include "super.h" | 46 | #include "super.h" |
47 | #include "vote.h" | 47 | #include "vote.h" |
@@ -1213,17 +1213,49 @@ bail: | |||
1213 | return status; | 1213 | return status; |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | struct ocfs2_orphan_filldir_priv { | ||
1217 | struct inode *head; | ||
1218 | struct ocfs2_super *osb; | ||
1219 | }; | ||
1220 | |||
1221 | static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len, | ||
1222 | loff_t pos, u64 ino, unsigned type) | ||
1223 | { | ||
1224 | struct ocfs2_orphan_filldir_priv *p = priv; | ||
1225 | struct inode *iter; | ||
1226 | |||
1227 | if (name_len == 1 && !strncmp(".", name, 1)) | ||
1228 | return 0; | ||
1229 | if (name_len == 2 && !strncmp("..", name, 2)) | ||
1230 | return 0; | ||
1231 | |||
1232 | /* Skip bad inodes so that recovery can continue */ | ||
1233 | iter = ocfs2_iget(p->osb, ino, | ||
1234 | OCFS2_FI_FLAG_ORPHAN_RECOVERY); | ||
1235 | if (IS_ERR(iter)) | ||
1236 | return 0; | ||
1237 | |||
1238 | mlog(0, "queue orphan %llu\n", | ||
1239 | (unsigned long long)OCFS2_I(iter)->ip_blkno); | ||
1240 | /* No locking is required for the next_orphan queue as there | ||
1241 | * is only ever a single process doing orphan recovery. */ | ||
1242 | OCFS2_I(iter)->ip_next_orphan = p->head; | ||
1243 | p->head = iter; | ||
1244 | |||
1245 | return 0; | ||
1246 | } | ||
1247 | |||
1216 | static int ocfs2_queue_orphans(struct ocfs2_super *osb, | 1248 | static int ocfs2_queue_orphans(struct ocfs2_super *osb, |
1217 | int slot, | 1249 | int slot, |
1218 | struct inode **head) | 1250 | struct inode **head) |
1219 | { | 1251 | { |
1220 | int status; | 1252 | int status; |
1221 | struct inode *orphan_dir_inode = NULL; | 1253 | struct inode *orphan_dir_inode = NULL; |
1222 | struct inode *iter; | 1254 | struct ocfs2_orphan_filldir_priv priv; |
1223 | unsigned long offset, blk, local; | 1255 | loff_t pos = 0; |
1224 | struct buffer_head *bh = NULL; | 1256 | |
1225 | struct ocfs2_dir_entry *de; | 1257 | priv.osb = osb; |
1226 | struct super_block *sb = osb->sb; | 1258 | priv.head = *head; |
1227 | 1259 | ||
1228 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | 1260 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, |
1229 | ORPHAN_DIR_SYSTEM_INODE, | 1261 | ORPHAN_DIR_SYSTEM_INODE, |
@@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, | |||
1241 | goto out; | 1273 | goto out; |
1242 | } | 1274 | } |
1243 | 1275 | ||
1244 | offset = 0; | 1276 | status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv, |
1245 | iter = NULL; | 1277 | ocfs2_orphan_filldir); |
1246 | while(offset < i_size_read(orphan_dir_inode)) { | 1278 | if (status) { |
1247 | blk = offset >> sb->s_blocksize_bits; | 1279 | mlog_errno(status); |
1248 | 1280 | goto out; | |
1249 | bh = ocfs2_bread(orphan_dir_inode, blk, &status, 0); | ||
1250 | if (!bh) | ||
1251 | status = -EINVAL; | ||
1252 | if (status < 0) { | ||
1253 | if (bh) | ||
1254 | brelse(bh); | ||
1255 | mlog_errno(status); | ||
1256 | goto out_unlock; | ||
1257 | } | ||
1258 | |||
1259 | local = 0; | ||
1260 | while(offset < i_size_read(orphan_dir_inode) | ||
1261 | && local < sb->s_blocksize) { | ||
1262 | de = (struct ocfs2_dir_entry *) (bh->b_data + local); | ||
1263 | |||
1264 | if (!ocfs2_check_dir_entry(orphan_dir_inode, | ||
1265 | de, bh, local)) { | ||
1266 | status = -EINVAL; | ||
1267 | mlog_errno(status); | ||
1268 | brelse(bh); | ||
1269 | goto out_unlock; | ||
1270 | } | ||
1271 | |||
1272 | local += le16_to_cpu(de->rec_len); | ||
1273 | offset += le16_to_cpu(de->rec_len); | ||
1274 | |||
1275 | /* I guess we silently fail on no inode? */ | ||
1276 | if (!le64_to_cpu(de->inode)) | ||
1277 | continue; | ||
1278 | if (de->file_type > OCFS2_FT_MAX) { | ||
1279 | mlog(ML_ERROR, | ||
1280 | "block %llu contains invalid de: " | ||
1281 | "inode = %llu, rec_len = %u, " | ||
1282 | "name_len = %u, file_type = %u, " | ||
1283 | "name='%.*s'\n", | ||
1284 | (unsigned long long)bh->b_blocknr, | ||
1285 | (unsigned long long)le64_to_cpu(de->inode), | ||
1286 | le16_to_cpu(de->rec_len), | ||
1287 | de->name_len, | ||
1288 | de->file_type, | ||
1289 | de->name_len, | ||
1290 | de->name); | ||
1291 | continue; | ||
1292 | } | ||
1293 | if (de->name_len == 1 && !strncmp(".", de->name, 1)) | ||
1294 | continue; | ||
1295 | if (de->name_len == 2 && !strncmp("..", de->name, 2)) | ||
1296 | continue; | ||
1297 | |||
1298 | iter = ocfs2_iget(osb, le64_to_cpu(de->inode), | ||
1299 | OCFS2_FI_FLAG_ORPHAN_RECOVERY); | ||
1300 | if (IS_ERR(iter)) | ||
1301 | continue; | ||
1302 | |||
1303 | mlog(0, "queue orphan %llu\n", | ||
1304 | (unsigned long long)OCFS2_I(iter)->ip_blkno); | ||
1305 | /* No locking is required for the next_orphan | ||
1306 | * queue as there is only ever a single | ||
1307 | * process doing orphan recovery. */ | ||
1308 | OCFS2_I(iter)->ip_next_orphan = *head; | ||
1309 | *head = iter; | ||
1310 | } | ||
1311 | brelse(bh); | ||
1312 | } | 1281 | } |
1313 | 1282 | ||
1314 | out_unlock: | 1283 | *head = priv.head; |
1284 | |||
1315 | ocfs2_meta_unlock(orphan_dir_inode, 0); | 1285 | ocfs2_meta_unlock(orphan_dir_inode, 0); |
1316 | out: | 1286 | out: |
1317 | mutex_unlock(&orphan_dir_inode->i_mutex); | 1287 | mutex_unlock(&orphan_dir_inode->i_mutex); |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index ce60aab013aa..4b32e0961568 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
@@ -282,6 +282,9 @@ int ocfs2_journal_dirty_data(handle_t *handle, | |||
282 | * prev. group desc. if we relink. */ | 282 | * prev. group desc. if we relink. */ |
283 | #define OCFS2_SUBALLOC_ALLOC (3) | 283 | #define OCFS2_SUBALLOC_ALLOC (3) |
284 | 284 | ||
285 | #define OCFS2_INLINE_TO_EXTENTS_CREDITS (OCFS2_SUBALLOC_ALLOC \ | ||
286 | + OCFS2_INODE_UPDATE_CREDITS) | ||
287 | |||
285 | /* dinode + group descriptor update. We don't relink on free yet. */ | 288 | /* dinode + group descriptor update. We don't relink on free yet. */ |
286 | #define OCFS2_SUBALLOC_FREE (2) | 289 | #define OCFS2_SUBALLOC_FREE (2) |
287 | 290 | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 701e6d04ed5d..729259016c18 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -64,29 +64,6 @@ | |||
64 | 64 | ||
65 | #include "buffer_head_io.h" | 65 | #include "buffer_head_io.h" |
66 | 66 | ||
67 | #define NAMEI_RA_CHUNKS 2 | ||
68 | #define NAMEI_RA_BLOCKS 4 | ||
69 | #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) | ||
70 | #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) | ||
71 | |||
72 | static int inline ocfs2_search_dirblock(struct buffer_head *bh, | ||
73 | struct inode *dir, | ||
74 | const char *name, int namelen, | ||
75 | unsigned long offset, | ||
76 | struct ocfs2_dir_entry **res_dir); | ||
77 | |||
78 | static int ocfs2_delete_entry(handle_t *handle, | ||
79 | struct inode *dir, | ||
80 | struct ocfs2_dir_entry *de_del, | ||
81 | struct buffer_head *bh); | ||
82 | |||
83 | static int __ocfs2_add_entry(handle_t *handle, | ||
84 | struct inode *dir, | ||
85 | const char *name, int namelen, | ||
86 | struct inode *inode, u64 blkno, | ||
87 | struct buffer_head *parent_fe_bh, | ||
88 | struct buffer_head *insert_bh); | ||
89 | |||
90 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, | 67 | static int ocfs2_mknod_locked(struct ocfs2_super *osb, |
91 | struct inode *dir, | 68 | struct inode *dir, |
92 | struct dentry *dentry, int mode, | 69 | struct dentry *dentry, int mode, |
@@ -97,13 +74,6 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
97 | struct inode **ret_inode, | 74 | struct inode **ret_inode, |
98 | struct ocfs2_alloc_context *inode_ac); | 75 | struct ocfs2_alloc_context *inode_ac); |
99 | 76 | ||
100 | static int ocfs2_fill_new_dir(struct ocfs2_super *osb, | ||
101 | handle_t *handle, | ||
102 | struct inode *parent, | ||
103 | struct inode *inode, | ||
104 | struct buffer_head *fe_bh, | ||
105 | struct ocfs2_alloc_context *data_ac); | ||
106 | |||
107 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, | 77 | static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, |
108 | struct inode **ret_orphan_dir, | 78 | struct inode **ret_orphan_dir, |
109 | struct inode *inode, | 79 | struct inode *inode, |
@@ -123,17 +93,6 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | |||
123 | struct inode *inode, | 93 | struct inode *inode, |
124 | const char *symname); | 94 | const char *symname); |
125 | 95 | ||
126 | static inline int ocfs2_add_entry(handle_t *handle, | ||
127 | struct dentry *dentry, | ||
128 | struct inode *inode, u64 blkno, | ||
129 | struct buffer_head *parent_fe_bh, | ||
130 | struct buffer_head *insert_bh) | ||
131 | { | ||
132 | return __ocfs2_add_entry(handle, dentry->d_parent->d_inode, | ||
133 | dentry->d_name.name, dentry->d_name.len, | ||
134 | inode, blkno, parent_fe_bh, insert_bh); | ||
135 | } | ||
136 | |||
137 | /* An orphan dir name is an 8 byte value, printed as a hex string */ | 96 | /* An orphan dir name is an 8 byte value, printed as a hex string */ |
138 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) | 97 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) |
139 | 98 | ||
@@ -142,10 +101,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | |||
142 | { | 101 | { |
143 | int status; | 102 | int status; |
144 | u64 blkno; | 103 | u64 blkno; |
145 | struct buffer_head *dirent_bh = NULL; | ||
146 | struct inode *inode = NULL; | 104 | struct inode *inode = NULL; |
147 | struct dentry *ret; | 105 | struct dentry *ret; |
148 | struct ocfs2_dir_entry *dirent; | ||
149 | struct ocfs2_inode_info *oi; | 106 | struct ocfs2_inode_info *oi; |
150 | 107 | ||
151 | mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, | 108 | mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, |
@@ -167,9 +124,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | |||
167 | goto bail; | 124 | goto bail; |
168 | } | 125 | } |
169 | 126 | ||
170 | status = ocfs2_find_files_on_disk(dentry->d_name.name, | 127 | status = ocfs2_lookup_ino_from_name(dir, dentry->d_name.name, |
171 | dentry->d_name.len, &blkno, | 128 | dentry->d_name.len, &blkno); |
172 | dir, &dirent_bh, &dirent); | ||
173 | if (status < 0) | 129 | if (status < 0) |
174 | goto bail_add; | 130 | goto bail_add; |
175 | 131 | ||
@@ -224,83 +180,12 @@ bail_unlock: | |||
224 | ocfs2_meta_unlock(dir, 0); | 180 | ocfs2_meta_unlock(dir, 0); |
225 | 181 | ||
226 | bail: | 182 | bail: |
227 | if (dirent_bh) | ||
228 | brelse(dirent_bh); | ||
229 | 183 | ||
230 | mlog_exit_ptr(ret); | 184 | mlog_exit_ptr(ret); |
231 | 185 | ||
232 | return ret; | 186 | return ret; |
233 | } | 187 | } |
234 | 188 | ||
235 | static int ocfs2_fill_new_dir(struct ocfs2_super *osb, | ||
236 | handle_t *handle, | ||
237 | struct inode *parent, | ||
238 | struct inode *inode, | ||
239 | struct buffer_head *fe_bh, | ||
240 | struct ocfs2_alloc_context *data_ac) | ||
241 | { | ||
242 | int status; | ||
243 | struct buffer_head *new_bh = NULL; | ||
244 | struct ocfs2_dir_entry *de = NULL; | ||
245 | |||
246 | mlog_entry_void(); | ||
247 | |||
248 | status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh, | ||
249 | data_ac, NULL, &new_bh); | ||
250 | if (status < 0) { | ||
251 | mlog_errno(status); | ||
252 | goto bail; | ||
253 | } | ||
254 | |||
255 | ocfs2_set_new_buffer_uptodate(inode, new_bh); | ||
256 | |||
257 | status = ocfs2_journal_access(handle, inode, new_bh, | ||
258 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
259 | if (status < 0) { | ||
260 | mlog_errno(status); | ||
261 | goto bail; | ||
262 | } | ||
263 | memset(new_bh->b_data, 0, osb->sb->s_blocksize); | ||
264 | |||
265 | de = (struct ocfs2_dir_entry *) new_bh->b_data; | ||
266 | de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno); | ||
267 | de->name_len = 1; | ||
268 | de->rec_len = | ||
269 | cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
270 | strcpy(de->name, "."); | ||
271 | ocfs2_set_de_type(de, S_IFDIR); | ||
272 | de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); | ||
273 | de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno); | ||
274 | de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - | ||
275 | OCFS2_DIR_REC_LEN(1)); | ||
276 | de->name_len = 2; | ||
277 | strcpy(de->name, ".."); | ||
278 | ocfs2_set_de_type(de, S_IFDIR); | ||
279 | |||
280 | status = ocfs2_journal_dirty(handle, new_bh); | ||
281 | if (status < 0) { | ||
282 | mlog_errno(status); | ||
283 | goto bail; | ||
284 | } | ||
285 | |||
286 | i_size_write(inode, inode->i_sb->s_blocksize); | ||
287 | inode->i_nlink = 2; | ||
288 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
289 | status = ocfs2_mark_inode_dirty(handle, inode, fe_bh); | ||
290 | if (status < 0) { | ||
291 | mlog_errno(status); | ||
292 | goto bail; | ||
293 | } | ||
294 | |||
295 | status = 0; | ||
296 | bail: | ||
297 | if (new_bh) | ||
298 | brelse(new_bh); | ||
299 | |||
300 | mlog_exit(status); | ||
301 | return status; | ||
302 | } | ||
303 | |||
304 | static int ocfs2_mknod(struct inode *dir, | 189 | static int ocfs2_mknod(struct inode *dir, |
305 | struct dentry *dentry, | 190 | struct dentry *dentry, |
306 | int mode, | 191 | int mode, |
@@ -365,9 +250,8 @@ static int ocfs2_mknod(struct inode *dir, | |||
365 | goto leave; | 250 | goto leave; |
366 | } | 251 | } |
367 | 252 | ||
368 | /* are we making a directory? If so, reserve a cluster for his | 253 | /* Reserve a cluster if creating an extent based directory. */ |
369 | * 1st extent. */ | 254 | if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { |
370 | if (S_ISDIR(mode)) { | ||
371 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); | 255 | status = ocfs2_reserve_clusters(osb, 1, &data_ac); |
372 | if (status < 0) { | 256 | if (status < 0) { |
373 | if (status != -ENOSPC) | 257 | if (status != -ENOSPC) |
@@ -564,10 +448,21 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
564 | cpu_to_le32(CURRENT_TIME.tv_nsec); | 448 | cpu_to_le32(CURRENT_TIME.tv_nsec); |
565 | fe->i_dtime = 0; | 449 | fe->i_dtime = 0; |
566 | 450 | ||
567 | fel = &fe->id2.i_list; | 451 | /* |
568 | fel->l_tree_depth = 0; | 452 | * If supported, directories start with inline data. |
569 | fel->l_next_free_rec = 0; | 453 | */ |
570 | fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); | 454 | if (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) { |
455 | u16 feat = le16_to_cpu(fe->i_dyn_features); | ||
456 | |||
457 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); | ||
458 | |||
459 | fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb)); | ||
460 | } else { | ||
461 | fel = &fe->id2.i_list; | ||
462 | fel->l_tree_depth = 0; | ||
463 | fel->l_next_free_rec = 0; | ||
464 | fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); | ||
465 | } | ||
571 | 466 | ||
572 | status = ocfs2_journal_dirty(handle, *new_fe_bh); | 467 | status = ocfs2_journal_dirty(handle, *new_fe_bh); |
573 | if (status < 0) { | 468 | if (status < 0) { |
@@ -1048,11 +943,6 @@ static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2) | |||
1048 | ocfs2_meta_unlock(inode2, 1); | 943 | ocfs2_meta_unlock(inode2, 1); |
1049 | } | 944 | } |
1050 | 945 | ||
1051 | #define PARENT_INO(buffer) \ | ||
1052 | ((struct ocfs2_dir_entry *) \ | ||
1053 | ((char *)buffer + \ | ||
1054 | le16_to_cpu(((struct ocfs2_dir_entry *)buffer)->rec_len)))->inode | ||
1055 | |||
1056 | static int ocfs2_rename(struct inode *old_dir, | 946 | static int ocfs2_rename(struct inode *old_dir, |
1057 | struct dentry *old_dentry, | 947 | struct dentry *old_dentry, |
1058 | struct inode *new_dir, | 948 | struct inode *new_dir, |
@@ -1070,12 +960,12 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1070 | struct buffer_head *old_inode_bh = NULL; | 960 | struct buffer_head *old_inode_bh = NULL; |
1071 | struct buffer_head *insert_entry_bh = NULL; | 961 | struct buffer_head *insert_entry_bh = NULL; |
1072 | struct ocfs2_super *osb = NULL; | 962 | struct ocfs2_super *osb = NULL; |
1073 | u64 newfe_blkno; | 963 | u64 newfe_blkno, old_de_ino; |
1074 | handle_t *handle = NULL; | 964 | handle_t *handle = NULL; |
1075 | struct buffer_head *old_dir_bh = NULL; | 965 | struct buffer_head *old_dir_bh = NULL; |
1076 | struct buffer_head *new_dir_bh = NULL; | 966 | struct buffer_head *new_dir_bh = NULL; |
1077 | struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry | 967 | struct ocfs2_dir_entry *old_inode_dot_dot_de = NULL, *old_de = NULL, |
1078 | // and new_dentry | 968 | *new_de = NULL; |
1079 | struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above | 969 | struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above |
1080 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, | 970 | struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir, |
1081 | // this is the 1st dirent bh | 971 | // this is the 1st dirent bh |
@@ -1159,27 +1049,35 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1159 | } | 1049 | } |
1160 | 1050 | ||
1161 | if (S_ISDIR(old_inode->i_mode)) { | 1051 | if (S_ISDIR(old_inode->i_mode)) { |
1162 | status = -EIO; | 1052 | u64 old_inode_parent; |
1163 | old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0); | 1053 | |
1164 | if (!old_inode_de_bh) | 1054 | status = ocfs2_find_files_on_disk("..", 2, &old_inode_parent, |
1055 | old_inode, &old_inode_de_bh, | ||
1056 | &old_inode_dot_dot_de); | ||
1057 | if (status) { | ||
1058 | status = -EIO; | ||
1165 | goto bail; | 1059 | goto bail; |
1060 | } | ||
1166 | 1061 | ||
1167 | status = -EIO; | 1062 | if (old_inode_parent != OCFS2_I(old_dir)->ip_blkno) { |
1168 | if (le64_to_cpu(PARENT_INO(old_inode_de_bh->b_data)) != | 1063 | status = -EIO; |
1169 | OCFS2_I(old_dir)->ip_blkno) | ||
1170 | goto bail; | 1064 | goto bail; |
1171 | status = -EMLINK; | 1065 | } |
1172 | if (!new_inode && new_dir!=old_dir && | 1066 | |
1173 | new_dir->i_nlink >= OCFS2_LINK_MAX) | 1067 | if (!new_inode && new_dir != old_dir && |
1068 | new_dir->i_nlink >= OCFS2_LINK_MAX) { | ||
1069 | status = -EMLINK; | ||
1174 | goto bail; | 1070 | goto bail; |
1071 | } | ||
1175 | } | 1072 | } |
1176 | 1073 | ||
1177 | status = -ENOENT; | 1074 | status = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, |
1178 | old_de_bh = ocfs2_find_entry(old_dentry->d_name.name, | 1075 | old_dentry->d_name.len, |
1179 | old_dentry->d_name.len, | 1076 | &old_de_ino); |
1180 | old_dir, &old_de); | 1077 | if (status) { |
1181 | if (!old_de_bh) | 1078 | status = -ENOENT; |
1182 | goto bail; | 1079 | goto bail; |
1080 | } | ||
1183 | 1081 | ||
1184 | /* | 1082 | /* |
1185 | * Check for inode number is _not_ due to possible IO errors. | 1083 | * Check for inode number is _not_ due to possible IO errors. |
@@ -1187,8 +1085,10 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1187 | * and merrily kill the link to whatever was created under the | 1085 | * and merrily kill the link to whatever was created under the |
1188 | * same name. Goodbye sticky bit ;-< | 1086 | * same name. Goodbye sticky bit ;-< |
1189 | */ | 1087 | */ |
1190 | if (le64_to_cpu(old_de->inode) != OCFS2_I(old_inode)->ip_blkno) | 1088 | if (old_de_ino != OCFS2_I(old_inode)->ip_blkno) { |
1089 | status = -ENOENT; | ||
1191 | goto bail; | 1090 | goto bail; |
1091 | } | ||
1192 | 1092 | ||
1193 | /* check if the target already exists (in which case we need | 1093 | /* check if the target already exists (in which case we need |
1194 | * to delete it */ | 1094 | * to delete it */ |
@@ -1321,20 +1221,13 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1321 | } | 1221 | } |
1322 | 1222 | ||
1323 | /* change the dirent to point to the correct inode */ | 1223 | /* change the dirent to point to the correct inode */ |
1324 | status = ocfs2_journal_access(handle, new_dir, new_de_bh, | 1224 | status = ocfs2_update_entry(new_dir, handle, new_de_bh, |
1325 | OCFS2_JOURNAL_ACCESS_WRITE); | 1225 | new_de, old_inode); |
1326 | if (status < 0) { | 1226 | if (status < 0) { |
1327 | mlog_errno(status); | 1227 | mlog_errno(status); |
1328 | goto bail; | 1228 | goto bail; |
1329 | } | 1229 | } |
1330 | new_de->inode = cpu_to_le64(OCFS2_I(old_inode)->ip_blkno); | ||
1331 | new_de->file_type = old_de->file_type; | ||
1332 | new_dir->i_version++; | 1230 | new_dir->i_version++; |
1333 | status = ocfs2_journal_dirty(handle, new_de_bh); | ||
1334 | if (status < 0) { | ||
1335 | mlog_errno(status); | ||
1336 | goto bail; | ||
1337 | } | ||
1338 | 1231 | ||
1339 | if (S_ISDIR(new_inode->i_mode)) | 1232 | if (S_ISDIR(new_inode->i_mode)) |
1340 | newfe->i_links_count = 0; | 1233 | newfe->i_links_count = 0; |
@@ -1370,7 +1263,21 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1370 | } else | 1263 | } else |
1371 | mlog_errno(status); | 1264 | mlog_errno(status); |
1372 | 1265 | ||
1373 | /* now that the name has been added to new_dir, remove the old name */ | 1266 | /* |
1267 | * Now that the name has been added to new_dir, remove the old name. | ||
1268 | * | ||
1269 | * We don't keep any directory entry context around until now | ||
1270 | * because the insert might have changed the type of directory | ||
1271 | * we're dealing with. | ||
1272 | */ | ||
1273 | old_de_bh = ocfs2_find_entry(old_dentry->d_name.name, | ||
1274 | old_dentry->d_name.len, | ||
1275 | old_dir, &old_de); | ||
1276 | if (!old_de_bh) { | ||
1277 | status = -EIO; | ||
1278 | goto bail; | ||
1279 | } | ||
1280 | |||
1374 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); | 1281 | status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh); |
1375 | if (status < 0) { | 1282 | if (status < 0) { |
1376 | mlog_errno(status); | 1283 | mlog_errno(status); |
@@ -1383,12 +1290,8 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1383 | } | 1290 | } |
1384 | old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; | 1291 | old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; |
1385 | if (old_inode_de_bh) { | 1292 | if (old_inode_de_bh) { |
1386 | status = ocfs2_journal_access(handle, old_inode, | 1293 | status = ocfs2_update_entry(old_inode, handle, old_inode_de_bh, |
1387 | old_inode_de_bh, | 1294 | old_inode_dot_dot_de, new_dir); |
1388 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1389 | PARENT_INO(old_inode_de_bh->b_data) = | ||
1390 | cpu_to_le64(OCFS2_I(new_dir)->ip_blkno); | ||
1391 | status = ocfs2_journal_dirty(handle, old_inode_de_bh); | ||
1392 | old_dir->i_nlink--; | 1295 | old_dir->i_nlink--; |
1393 | if (new_inode) { | 1296 | if (new_inode) { |
1394 | new_inode->i_nlink--; | 1297 | new_inode->i_nlink--; |
@@ -1767,329 +1670,6 @@ bail: | |||
1767 | return status; | 1670 | return status; |
1768 | } | 1671 | } |
1769 | 1672 | ||
1770 | int ocfs2_check_dir_entry(struct inode * dir, | ||
1771 | struct ocfs2_dir_entry * de, | ||
1772 | struct buffer_head * bh, | ||
1773 | unsigned long offset) | ||
1774 | { | ||
1775 | const char *error_msg = NULL; | ||
1776 | const int rlen = le16_to_cpu(de->rec_len); | ||
1777 | |||
1778 | if (rlen < OCFS2_DIR_REC_LEN(1)) | ||
1779 | error_msg = "rec_len is smaller than minimal"; | ||
1780 | else if (rlen % 4 != 0) | ||
1781 | error_msg = "rec_len % 4 != 0"; | ||
1782 | else if (rlen < OCFS2_DIR_REC_LEN(de->name_len)) | ||
1783 | error_msg = "rec_len is too small for name_len"; | ||
1784 | else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) | ||
1785 | error_msg = "directory entry across blocks"; | ||
1786 | |||
1787 | if (error_msg != NULL) | ||
1788 | mlog(ML_ERROR, "bad entry in directory #%llu: %s - " | ||
1789 | "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n", | ||
1790 | (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg, | ||
1791 | offset, (unsigned long long)le64_to_cpu(de->inode), rlen, | ||
1792 | de->name_len); | ||
1793 | return error_msg == NULL ? 1 : 0; | ||
1794 | } | ||
1795 | |||
1796 | /* we don't always have a dentry for what we want to add, so people | ||
1797 | * like orphan dir can call this instead. | ||
1798 | * | ||
1799 | * If you pass me insert_bh, I'll skip the search of the other dir | ||
1800 | * blocks and put the record in there. | ||
1801 | */ | ||
1802 | static int __ocfs2_add_entry(handle_t *handle, | ||
1803 | struct inode *dir, | ||
1804 | const char *name, int namelen, | ||
1805 | struct inode *inode, u64 blkno, | ||
1806 | struct buffer_head *parent_fe_bh, | ||
1807 | struct buffer_head *insert_bh) | ||
1808 | { | ||
1809 | unsigned long offset; | ||
1810 | unsigned short rec_len; | ||
1811 | struct ocfs2_dir_entry *de, *de1; | ||
1812 | struct super_block *sb; | ||
1813 | int retval, status; | ||
1814 | |||
1815 | mlog_entry_void(); | ||
1816 | |||
1817 | sb = dir->i_sb; | ||
1818 | |||
1819 | if (!namelen) | ||
1820 | return -EINVAL; | ||
1821 | |||
1822 | rec_len = OCFS2_DIR_REC_LEN(namelen); | ||
1823 | offset = 0; | ||
1824 | de = (struct ocfs2_dir_entry *) insert_bh->b_data; | ||
1825 | while (1) { | ||
1826 | BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data); | ||
1827 | /* These checks should've already been passed by the | ||
1828 | * prepare function, but I guess we can leave them | ||
1829 | * here anyway. */ | ||
1830 | if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) { | ||
1831 | retval = -ENOENT; | ||
1832 | goto bail; | ||
1833 | } | ||
1834 | if (ocfs2_match(namelen, name, de)) { | ||
1835 | retval = -EEXIST; | ||
1836 | goto bail; | ||
1837 | } | ||
1838 | if (((le64_to_cpu(de->inode) == 0) && | ||
1839 | (le16_to_cpu(de->rec_len) >= rec_len)) || | ||
1840 | (le16_to_cpu(de->rec_len) >= | ||
1841 | (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) { | ||
1842 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
1843 | retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh); | ||
1844 | if (retval < 0) { | ||
1845 | mlog_errno(retval); | ||
1846 | goto bail; | ||
1847 | } | ||
1848 | |||
1849 | status = ocfs2_journal_access(handle, dir, insert_bh, | ||
1850 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1851 | /* By now the buffer is marked for journaling */ | ||
1852 | offset += le16_to_cpu(de->rec_len); | ||
1853 | if (le64_to_cpu(de->inode)) { | ||
1854 | de1 = (struct ocfs2_dir_entry *)((char *) de + | ||
1855 | OCFS2_DIR_REC_LEN(de->name_len)); | ||
1856 | de1->rec_len = | ||
1857 | cpu_to_le16(le16_to_cpu(de->rec_len) - | ||
1858 | OCFS2_DIR_REC_LEN(de->name_len)); | ||
1859 | de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); | ||
1860 | de = de1; | ||
1861 | } | ||
1862 | de->file_type = OCFS2_FT_UNKNOWN; | ||
1863 | if (blkno) { | ||
1864 | de->inode = cpu_to_le64(blkno); | ||
1865 | ocfs2_set_de_type(de, inode->i_mode); | ||
1866 | } else | ||
1867 | de->inode = 0; | ||
1868 | de->name_len = namelen; | ||
1869 | memcpy(de->name, name, namelen); | ||
1870 | |||
1871 | dir->i_version++; | ||
1872 | status = ocfs2_journal_dirty(handle, insert_bh); | ||
1873 | retval = 0; | ||
1874 | goto bail; | ||
1875 | } | ||
1876 | offset += le16_to_cpu(de->rec_len); | ||
1877 | de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len)); | ||
1878 | } | ||
1879 | |||
1880 | /* when you think about it, the assert above should prevent us | ||
1881 | * from ever getting here. */ | ||
1882 | retval = -ENOSPC; | ||
1883 | bail: | ||
1884 | |||
1885 | mlog_exit(retval); | ||
1886 | return retval; | ||
1887 | } | ||
1888 | |||
1889 | |||
1890 | /* | ||
1891 | * ocfs2_delete_entry deletes a directory entry by merging it with the | ||
1892 | * previous entry | ||
1893 | */ | ||
1894 | static int ocfs2_delete_entry(handle_t *handle, | ||
1895 | struct inode *dir, | ||
1896 | struct ocfs2_dir_entry *de_del, | ||
1897 | struct buffer_head *bh) | ||
1898 | { | ||
1899 | struct ocfs2_dir_entry *de, *pde; | ||
1900 | int i, status = -ENOENT; | ||
1901 | |||
1902 | mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); | ||
1903 | |||
1904 | i = 0; | ||
1905 | pde = NULL; | ||
1906 | de = (struct ocfs2_dir_entry *) bh->b_data; | ||
1907 | while (i < bh->b_size) { | ||
1908 | if (!ocfs2_check_dir_entry(dir, de, bh, i)) { | ||
1909 | status = -EIO; | ||
1910 | mlog_errno(status); | ||
1911 | goto bail; | ||
1912 | } | ||
1913 | if (de == de_del) { | ||
1914 | status = ocfs2_journal_access(handle, dir, bh, | ||
1915 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1916 | if (status < 0) { | ||
1917 | status = -EIO; | ||
1918 | mlog_errno(status); | ||
1919 | goto bail; | ||
1920 | } | ||
1921 | if (pde) | ||
1922 | pde->rec_len = | ||
1923 | cpu_to_le16(le16_to_cpu(pde->rec_len) + | ||
1924 | le16_to_cpu(de->rec_len)); | ||
1925 | else | ||
1926 | de->inode = 0; | ||
1927 | dir->i_version++; | ||
1928 | status = ocfs2_journal_dirty(handle, bh); | ||
1929 | goto bail; | ||
1930 | } | ||
1931 | i += le16_to_cpu(de->rec_len); | ||
1932 | pde = de; | ||
1933 | de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len)); | ||
1934 | } | ||
1935 | bail: | ||
1936 | mlog_exit(status); | ||
1937 | return status; | ||
1938 | } | ||
1939 | |||
1940 | /* | ||
1941 | * Returns 0 if not found, -1 on failure, and 1 on success | ||
1942 | */ | ||
1943 | static int inline ocfs2_search_dirblock(struct buffer_head *bh, | ||
1944 | struct inode *dir, | ||
1945 | const char *name, int namelen, | ||
1946 | unsigned long offset, | ||
1947 | struct ocfs2_dir_entry **res_dir) | ||
1948 | { | ||
1949 | struct ocfs2_dir_entry *de; | ||
1950 | char *dlimit, *de_buf; | ||
1951 | int de_len; | ||
1952 | int ret = 0; | ||
1953 | |||
1954 | mlog_entry_void(); | ||
1955 | |||
1956 | de_buf = bh->b_data; | ||
1957 | dlimit = de_buf + dir->i_sb->s_blocksize; | ||
1958 | |||
1959 | while (de_buf < dlimit) { | ||
1960 | /* this code is executed quadratically often */ | ||
1961 | /* do minimal checking `by hand' */ | ||
1962 | |||
1963 | de = (struct ocfs2_dir_entry *) de_buf; | ||
1964 | |||
1965 | if (de_buf + namelen <= dlimit && | ||
1966 | ocfs2_match(namelen, name, de)) { | ||
1967 | /* found a match - just to be sure, do a full check */ | ||
1968 | if (!ocfs2_check_dir_entry(dir, de, bh, offset)) { | ||
1969 | ret = -1; | ||
1970 | goto bail; | ||
1971 | } | ||
1972 | *res_dir = de; | ||
1973 | ret = 1; | ||
1974 | goto bail; | ||
1975 | } | ||
1976 | |||
1977 | /* prevent looping on a bad block */ | ||
1978 | de_len = le16_to_cpu(de->rec_len); | ||
1979 | if (de_len <= 0) { | ||
1980 | ret = -1; | ||
1981 | goto bail; | ||
1982 | } | ||
1983 | |||
1984 | de_buf += de_len; | ||
1985 | offset += de_len; | ||
1986 | } | ||
1987 | |||
1988 | bail: | ||
1989 | mlog_exit(ret); | ||
1990 | return ret; | ||
1991 | } | ||
1992 | |||
1993 | struct buffer_head *ocfs2_find_entry(const char *name, int namelen, | ||
1994 | struct inode *dir, | ||
1995 | struct ocfs2_dir_entry **res_dir) | ||
1996 | { | ||
1997 | struct super_block *sb; | ||
1998 | struct buffer_head *bh_use[NAMEI_RA_SIZE]; | ||
1999 | struct buffer_head *bh, *ret = NULL; | ||
2000 | unsigned long start, block, b; | ||
2001 | int ra_max = 0; /* Number of bh's in the readahead | ||
2002 | buffer, bh_use[] */ | ||
2003 | int ra_ptr = 0; /* Current index into readahead | ||
2004 | buffer */ | ||
2005 | int num = 0; | ||
2006 | int nblocks, i, err; | ||
2007 | |||
2008 | mlog_entry_void(); | ||
2009 | |||
2010 | *res_dir = NULL; | ||
2011 | sb = dir->i_sb; | ||
2012 | |||
2013 | nblocks = i_size_read(dir) >> sb->s_blocksize_bits; | ||
2014 | start = OCFS2_I(dir)->ip_dir_start_lookup; | ||
2015 | if (start >= nblocks) | ||
2016 | start = 0; | ||
2017 | block = start; | ||
2018 | |||
2019 | restart: | ||
2020 | do { | ||
2021 | /* | ||
2022 | * We deal with the read-ahead logic here. | ||
2023 | */ | ||
2024 | if (ra_ptr >= ra_max) { | ||
2025 | /* Refill the readahead buffer */ | ||
2026 | ra_ptr = 0; | ||
2027 | b = block; | ||
2028 | for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) { | ||
2029 | /* | ||
2030 | * Terminate if we reach the end of the | ||
2031 | * directory and must wrap, or if our | ||
2032 | * search has finished at this block. | ||
2033 | */ | ||
2034 | if (b >= nblocks || (num && block == start)) { | ||
2035 | bh_use[ra_max] = NULL; | ||
2036 | break; | ||
2037 | } | ||
2038 | num++; | ||
2039 | |||
2040 | bh = ocfs2_bread(dir, b++, &err, 1); | ||
2041 | bh_use[ra_max] = bh; | ||
2042 | } | ||
2043 | } | ||
2044 | if ((bh = bh_use[ra_ptr++]) == NULL) | ||
2045 | goto next; | ||
2046 | wait_on_buffer(bh); | ||
2047 | if (!buffer_uptodate(bh)) { | ||
2048 | /* read error, skip block & hope for the best */ | ||
2049 | ocfs2_error(dir->i_sb, "reading directory %llu, " | ||
2050 | "offset %lu\n", | ||
2051 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | ||
2052 | block); | ||
2053 | brelse(bh); | ||
2054 | goto next; | ||
2055 | } | ||
2056 | i = ocfs2_search_dirblock(bh, dir, name, namelen, | ||
2057 | block << sb->s_blocksize_bits, | ||
2058 | res_dir); | ||
2059 | if (i == 1) { | ||
2060 | OCFS2_I(dir)->ip_dir_start_lookup = block; | ||
2061 | ret = bh; | ||
2062 | goto cleanup_and_exit; | ||
2063 | } else { | ||
2064 | brelse(bh); | ||
2065 | if (i < 0) | ||
2066 | goto cleanup_and_exit; | ||
2067 | } | ||
2068 | next: | ||
2069 | if (++block >= nblocks) | ||
2070 | block = 0; | ||
2071 | } while (block != start); | ||
2072 | |||
2073 | /* | ||
2074 | * If the directory has grown while we were searching, then | ||
2075 | * search the last part of the directory before giving up. | ||
2076 | */ | ||
2077 | block = nblocks; | ||
2078 | nblocks = i_size_read(dir) >> sb->s_blocksize_bits; | ||
2079 | if (block < nblocks) { | ||
2080 | start = 0; | ||
2081 | goto restart; | ||
2082 | } | ||
2083 | |||
2084 | cleanup_and_exit: | ||
2085 | /* Clean up the read-ahead blocks */ | ||
2086 | for (; ra_ptr < ra_max; ra_ptr++) | ||
2087 | brelse(bh_use[ra_ptr]); | ||
2088 | |||
2089 | mlog_exit_ptr(ret); | ||
2090 | return ret; | ||
2091 | } | ||
2092 | |||
2093 | static int ocfs2_blkno_stringify(u64 blkno, char *name) | 1673 | static int ocfs2_blkno_stringify(u64 blkno, char *name) |
2094 | { | 1674 | { |
2095 | int status, namelen; | 1675 | int status, namelen; |
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h index 0975c7b7212b..688aef64c879 100644 --- a/fs/ocfs2/namei.h +++ b/fs/ocfs2/namei.h | |||
@@ -30,29 +30,10 @@ extern const struct inode_operations ocfs2_dir_iops; | |||
30 | 30 | ||
31 | struct dentry *ocfs2_get_parent(struct dentry *child); | 31 | struct dentry *ocfs2_get_parent(struct dentry *child); |
32 | 32 | ||
33 | int ocfs2_check_dir_entry (struct inode *dir, | ||
34 | struct ocfs2_dir_entry *de, | ||
35 | struct buffer_head *bh, | ||
36 | unsigned long offset); | ||
37 | struct buffer_head *ocfs2_find_entry(const char *name, | ||
38 | int namelen, | ||
39 | struct inode *dir, | ||
40 | struct ocfs2_dir_entry **res_dir); | ||
41 | int ocfs2_orphan_del(struct ocfs2_super *osb, | 33 | int ocfs2_orphan_del(struct ocfs2_super *osb, |
42 | handle_t *handle, | 34 | handle_t *handle, |
43 | struct inode *orphan_dir_inode, | 35 | struct inode *orphan_dir_inode, |
44 | struct inode *inode, | 36 | struct inode *inode, |
45 | struct buffer_head *orphan_dir_bh); | 37 | struct buffer_head *orphan_dir_bh); |
46 | 38 | ||
47 | static inline int ocfs2_match(int len, | ||
48 | const char * const name, | ||
49 | struct ocfs2_dir_entry *de) | ||
50 | { | ||
51 | if (len != de->name_len) | ||
52 | return 0; | ||
53 | if (!de->inode) | ||
54 | return 0; | ||
55 | return !memcmp(name, de->name, len); | ||
56 | } | ||
57 | |||
58 | #endif /* OCFS2_NAMEI_H */ | 39 | #endif /* OCFS2_NAMEI_H */ |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 58307853fb4a..60a23e1906b0 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -319,6 +319,13 @@ static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super *osb) | |||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | static inline int ocfs2_supports_inline_data(struct ocfs2_super *osb) | ||
323 | { | ||
324 | if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA) | ||
325 | return 1; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
322 | /* set / clear functions because cluster events can make these happen | 329 | /* set / clear functions because cluster events can make these happen |
323 | * in parallel so we want the transitions to be atomic. this also | 330 | * in parallel so we want the transitions to be atomic. this also |
324 | * means that any future flags osb_flags must be protected by spinlock | 331 | * means that any future flags osb_flags must be protected by spinlock |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 82f8a75b207e..6ef876759a73 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -87,7 +87,8 @@ | |||
87 | 87 | ||
88 | #define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB | 88 | #define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB |
89 | #define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \ | 89 | #define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \ |
90 | | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC) | 90 | | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \ |
91 | | OCFS2_FEATURE_INCOMPAT_INLINE_DATA) | ||
91 | #define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN | 92 | #define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN |
92 | 93 | ||
93 | /* | 94 | /* |
@@ -111,6 +112,20 @@ | |||
111 | #define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC 0x0010 | 112 | #define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC 0x0010 |
112 | 113 | ||
113 | /* | 114 | /* |
115 | * Tunefs sets this incompat flag before starting an operation which | ||
116 | * would require cleanup on abort. This is done to protect users from | ||
117 | * inadvertently mounting the fs after an aborted run without | ||
118 | * fsck-ing. | ||
119 | * | ||
120 | * s_tunefs_flags on the super block describes precisely which | ||
121 | * operations were in progress. | ||
122 | */ | ||
123 | #define OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG 0x0020 | ||
124 | |||
125 | /* Support for data packed into inode blocks */ | ||
126 | #define OCFS2_FEATURE_INCOMPAT_INLINE_DATA 0x0040 | ||
127 | |||
128 | /* | ||
114 | * backup superblock flag is used to indicate that this volume | 129 | * backup superblock flag is used to indicate that this volume |
115 | * has backup superblocks. | 130 | * has backup superblocks. |
116 | */ | 131 | */ |
@@ -130,6 +145,11 @@ | |||
130 | #define OCFS2_MAX_BACKUP_SUPERBLOCKS 6 | 145 | #define OCFS2_MAX_BACKUP_SUPERBLOCKS 6 |
131 | 146 | ||
132 | /* | 147 | /* |
148 | * Flags on ocfs2_super_block.s_tunefs_flags | ||
149 | */ | ||
150 | #define OCFS2_TUNEFS_INPROG_REMOVE_SLOT 0x0001 /* Removing slots */ | ||
151 | |||
152 | /* | ||
133 | * Flags on ocfs2_dinode.i_flags | 153 | * Flags on ocfs2_dinode.i_flags |
134 | */ | 154 | */ |
135 | #define OCFS2_VALID_FL (0x00000001) /* Inode is valid */ | 155 | #define OCFS2_VALID_FL (0x00000001) /* Inode is valid */ |
@@ -146,6 +166,17 @@ | |||
146 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ | 166 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
147 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ | 167 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
148 | 168 | ||
169 | /* | ||
170 | * Flags on ocfs2_dinode.i_dyn_features | ||
171 | * | ||
172 | * These can change much more often than i_flags. When adding flags, | ||
173 | * keep in mind that i_dyn_features is only 16 bits wide. | ||
174 | */ | ||
175 | #define OCFS2_INLINE_DATA_FL (0x0001) /* Data stored in inode block */ | ||
176 | #define OCFS2_HAS_XATTR_FL (0x0002) | ||
177 | #define OCFS2_INLINE_XATTR_FL (0x0004) | ||
178 | #define OCFS2_INDEXED_DIR_FL (0x0008) | ||
179 | |||
149 | /* Inode attributes, keep in sync with EXT2 */ | 180 | /* Inode attributes, keep in sync with EXT2 */ |
150 | #define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ | 181 | #define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ |
151 | #define OCFS2_UNRM_FL (0x00000002) /* Undelete */ | 182 | #define OCFS2_UNRM_FL (0x00000002) /* Undelete */ |
@@ -447,8 +478,8 @@ struct ocfs2_super_block { | |||
447 | __le32 s_clustersize_bits; /* Clustersize for this fs */ | 478 | __le32 s_clustersize_bits; /* Clustersize for this fs */ |
448 | /*40*/ __le16 s_max_slots; /* Max number of simultaneous mounts | 479 | /*40*/ __le16 s_max_slots; /* Max number of simultaneous mounts |
449 | before tunefs required */ | 480 | before tunefs required */ |
450 | __le16 s_reserved1; | 481 | __le16 s_tunefs_flag; |
451 | __le32 s_reserved2; | 482 | __le32 s_reserved1; |
452 | __le64 s_first_cluster_group; /* Block offset of 1st cluster | 483 | __le64 s_first_cluster_group; /* Block offset of 1st cluster |
453 | * group header */ | 484 | * group header */ |
454 | /*50*/ __u8 s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */ | 485 | /*50*/ __u8 s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */ |
@@ -471,6 +502,19 @@ struct ocfs2_local_alloc | |||
471 | }; | 502 | }; |
472 | 503 | ||
473 | /* | 504 | /* |
505 | * Data-in-inode header. This is only used if i_dyn_features has | ||
506 | * OCFS2_INLINE_DATA_FL set. | ||
507 | */ | ||
508 | struct ocfs2_inline_data | ||
509 | { | ||
510 | /*00*/ __le16 id_count; /* Number of bytes that can be used | ||
511 | * for data, starting at id_data */ | ||
512 | __le16 id_reserved0; | ||
513 | __le32 id_reserved1; | ||
514 | __u8 id_data[0]; /* Start of user data */ | ||
515 | }; | ||
516 | |||
517 | /* | ||
474 | * On disk inode for OCFS2 | 518 | * On disk inode for OCFS2 |
475 | */ | 519 | */ |
476 | struct ocfs2_dinode { | 520 | struct ocfs2_dinode { |
@@ -502,7 +546,7 @@ struct ocfs2_dinode { | |||
502 | __le32 i_attr; | 546 | __le32 i_attr; |
503 | __le16 i_orphaned_slot; /* Only valid when OCFS2_ORPHANED_FL | 547 | __le16 i_orphaned_slot; /* Only valid when OCFS2_ORPHANED_FL |
504 | was set in i_flags */ | 548 | was set in i_flags */ |
505 | __le16 i_reserved1; | 549 | __le16 i_dyn_features; |
506 | /*70*/ __le64 i_reserved2[8]; | 550 | /*70*/ __le64 i_reserved2[8]; |
507 | /*B8*/ union { | 551 | /*B8*/ union { |
508 | __le64 i_pad1; /* Generic way to refer to this | 552 | __le64 i_pad1; /* Generic way to refer to this |
@@ -528,6 +572,7 @@ struct ocfs2_dinode { | |||
528 | struct ocfs2_chain_list i_chain; | 572 | struct ocfs2_chain_list i_chain; |
529 | struct ocfs2_extent_list i_list; | 573 | struct ocfs2_extent_list i_list; |
530 | struct ocfs2_truncate_log i_dealloc; | 574 | struct ocfs2_truncate_log i_dealloc; |
575 | struct ocfs2_inline_data i_data; | ||
531 | __u8 i_symlink[0]; | 576 | __u8 i_symlink[0]; |
532 | } id2; | 577 | } id2; |
533 | /* Actual on-disk size is one block */ | 578 | /* Actual on-disk size is one block */ |
@@ -577,6 +622,12 @@ static inline int ocfs2_fast_symlink_chars(struct super_block *sb) | |||
577 | offsetof(struct ocfs2_dinode, id2.i_symlink); | 622 | offsetof(struct ocfs2_dinode, id2.i_symlink); |
578 | } | 623 | } |
579 | 624 | ||
625 | static inline int ocfs2_max_inline_data(struct super_block *sb) | ||
626 | { | ||
627 | return sb->s_blocksize - | ||
628 | offsetof(struct ocfs2_dinode, id2.i_data.id_data); | ||
629 | } | ||
630 | |||
580 | static inline int ocfs2_extent_recs_per_inode(struct super_block *sb) | 631 | static inline int ocfs2_extent_recs_per_inode(struct super_block *sb) |
581 | { | 632 | { |
582 | int size; | 633 | int size; |
@@ -656,6 +707,11 @@ static inline int ocfs2_fast_symlink_chars(int blocksize) | |||
656 | return blocksize - offsetof(struct ocfs2_dinode, id2.i_symlink); | 707 | return blocksize - offsetof(struct ocfs2_dinode, id2.i_symlink); |
657 | } | 708 | } |
658 | 709 | ||
710 | static inline int ocfs2_max_inline_data(int blocksize) | ||
711 | { | ||
712 | return blocksize - offsetof(struct ocfs2_dinode, id2.i_data.id_data); | ||
713 | } | ||
714 | |||
659 | static inline int ocfs2_extent_recs_per_inode(int blocksize) | 715 | static inline int ocfs2_extent_recs_per_inode(int blocksize) |
660 | { | 716 | { |
661 | int size; | 717 | int size; |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index c034b5129c1e..0e2a1b45bf92 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/parser.h> | 39 | #include <linux/parser.h> |
40 | #include <linux/crc32.h> | 40 | #include <linux/crc32.h> |
41 | #include <linux/debugfs.h> | 41 | #include <linux/debugfs.h> |
42 | #include <linux/mount.h> | ||
42 | 43 | ||
43 | #include <cluster/nodemanager.h> | 44 | #include <cluster/nodemanager.h> |
44 | 45 | ||
@@ -91,6 +92,7 @@ struct mount_options | |||
91 | static int ocfs2_parse_options(struct super_block *sb, char *options, | 92 | static int ocfs2_parse_options(struct super_block *sb, char *options, |
92 | struct mount_options *mopt, | 93 | struct mount_options *mopt, |
93 | int is_remount); | 94 | int is_remount); |
95 | static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt); | ||
94 | static void ocfs2_put_super(struct super_block *sb); | 96 | static void ocfs2_put_super(struct super_block *sb); |
95 | static int ocfs2_mount_volume(struct super_block *sb); | 97 | static int ocfs2_mount_volume(struct super_block *sb); |
96 | static int ocfs2_remount(struct super_block *sb, int *flags, char *data); | 98 | static int ocfs2_remount(struct super_block *sb, int *flags, char *data); |
@@ -105,7 +107,7 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait); | |||
105 | 107 | ||
106 | static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb); | 108 | static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb); |
107 | static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb); | 109 | static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb); |
108 | static int ocfs2_release_system_inodes(struct ocfs2_super *osb); | 110 | static void ocfs2_release_system_inodes(struct ocfs2_super *osb); |
109 | static int ocfs2_fill_local_node_info(struct ocfs2_super *osb); | 111 | static int ocfs2_fill_local_node_info(struct ocfs2_super *osb); |
110 | static int ocfs2_check_volume(struct ocfs2_super *osb); | 112 | static int ocfs2_check_volume(struct ocfs2_super *osb); |
111 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 113 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
@@ -133,6 +135,7 @@ static const struct super_operations ocfs2_sops = { | |||
133 | .write_super = ocfs2_write_super, | 135 | .write_super = ocfs2_write_super, |
134 | .put_super = ocfs2_put_super, | 136 | .put_super = ocfs2_put_super, |
135 | .remount_fs = ocfs2_remount, | 137 | .remount_fs = ocfs2_remount, |
138 | .show_options = ocfs2_show_options, | ||
136 | }; | 139 | }; |
137 | 140 | ||
138 | enum { | 141 | enum { |
@@ -177,7 +180,7 @@ static void ocfs2_write_super(struct super_block *sb) | |||
177 | 180 | ||
178 | static int ocfs2_sync_fs(struct super_block *sb, int wait) | 181 | static int ocfs2_sync_fs(struct super_block *sb, int wait) |
179 | { | 182 | { |
180 | int status = 0; | 183 | int status; |
181 | tid_t target; | 184 | tid_t target; |
182 | struct ocfs2_super *osb = OCFS2_SB(sb); | 185 | struct ocfs2_super *osb = OCFS2_SB(sb); |
183 | 186 | ||
@@ -275,9 +278,9 @@ bail: | |||
275 | return status; | 278 | return status; |
276 | } | 279 | } |
277 | 280 | ||
278 | static int ocfs2_release_system_inodes(struct ocfs2_super *osb) | 281 | static void ocfs2_release_system_inodes(struct ocfs2_super *osb) |
279 | { | 282 | { |
280 | int status = 0, i; | 283 | int i; |
281 | struct inode *inode; | 284 | struct inode *inode; |
282 | 285 | ||
283 | mlog_entry_void(); | 286 | mlog_entry_void(); |
@@ -302,8 +305,7 @@ static int ocfs2_release_system_inodes(struct ocfs2_super *osb) | |||
302 | osb->root_inode = NULL; | 305 | osb->root_inode = NULL; |
303 | } | 306 | } |
304 | 307 | ||
305 | mlog_exit(status); | 308 | mlog_exit(0); |
306 | return status; | ||
307 | } | 309 | } |
308 | 310 | ||
309 | /* We're allocating fs objects, use GFP_NOFS */ | 311 | /* We're allocating fs objects, use GFP_NOFS */ |
@@ -453,7 +455,7 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
453 | struct buffer_head **bh, | 455 | struct buffer_head **bh, |
454 | int *sector_size) | 456 | int *sector_size) |
455 | { | 457 | { |
456 | int status = 0, tmpstat; | 458 | int status, tmpstat; |
457 | struct ocfs1_vol_disk_hdr *hdr; | 459 | struct ocfs1_vol_disk_hdr *hdr; |
458 | struct ocfs2_dinode *di; | 460 | struct ocfs2_dinode *di; |
459 | int blksize; | 461 | int blksize; |
@@ -830,6 +832,41 @@ bail: | |||
830 | return status; | 832 | return status; |
831 | } | 833 | } |
832 | 834 | ||
835 | static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | ||
836 | { | ||
837 | struct ocfs2_super *osb = OCFS2_SB(mnt->mnt_sb); | ||
838 | unsigned long opts = osb->s_mount_opt; | ||
839 | |||
840 | if (opts & OCFS2_MOUNT_HB_LOCAL) | ||
841 | seq_printf(s, ",_netdev,heartbeat=local"); | ||
842 | else | ||
843 | seq_printf(s, ",heartbeat=none"); | ||
844 | |||
845 | if (opts & OCFS2_MOUNT_NOINTR) | ||
846 | seq_printf(s, ",nointr"); | ||
847 | |||
848 | if (opts & OCFS2_MOUNT_DATA_WRITEBACK) | ||
849 | seq_printf(s, ",data=writeback"); | ||
850 | else | ||
851 | seq_printf(s, ",data=ordered"); | ||
852 | |||
853 | if (opts & OCFS2_MOUNT_BARRIER) | ||
854 | seq_printf(s, ",barrier=1"); | ||
855 | |||
856 | if (opts & OCFS2_MOUNT_ERRORS_PANIC) | ||
857 | seq_printf(s, ",errors=panic"); | ||
858 | else | ||
859 | seq_printf(s, ",errors=remount-ro"); | ||
860 | |||
861 | if (osb->preferred_slot != OCFS2_INVALID_SLOT) | ||
862 | seq_printf(s, ",preferred_slot=%d", osb->preferred_slot); | ||
863 | |||
864 | if (osb->s_atime_quantum != OCFS2_DEFAULT_ATIME_QUANTUM) | ||
865 | seq_printf(s, ",atime_quantum=%u", osb->s_atime_quantum); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
833 | static int __init ocfs2_init(void) | 870 | static int __init ocfs2_init(void) |
834 | { | 871 | { |
835 | int status; | 872 | int status; |
@@ -1209,12 +1246,13 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1209 | tmp = ocfs2_request_umount_vote(osb); | 1246 | tmp = ocfs2_request_umount_vote(osb); |
1210 | if (tmp < 0) | 1247 | if (tmp < 0) |
1211 | mlog_errno(tmp); | 1248 | mlog_errno(tmp); |
1249 | } | ||
1212 | 1250 | ||
1213 | if (osb->slot_num != OCFS2_INVALID_SLOT) | 1251 | if (osb->slot_num != OCFS2_INVALID_SLOT) |
1214 | ocfs2_put_slot(osb); | 1252 | ocfs2_put_slot(osb); |
1215 | 1253 | ||
1254 | if (osb->dlm) | ||
1216 | ocfs2_super_unlock(osb, 1); | 1255 | ocfs2_super_unlock(osb, 1); |
1217 | } | ||
1218 | 1256 | ||
1219 | ocfs2_release_system_inodes(osb); | 1257 | ocfs2_release_system_inodes(osb); |
1220 | 1258 | ||
@@ -1275,7 +1313,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1275 | struct buffer_head *bh, | 1313 | struct buffer_head *bh, |
1276 | int sector_size) | 1314 | int sector_size) |
1277 | { | 1315 | { |
1278 | int status = 0; | 1316 | int status; |
1279 | int i, cbits, bbits; | 1317 | int i, cbits, bbits; |
1280 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | 1318 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; |
1281 | struct inode *inode = NULL; | 1319 | struct inode *inode = NULL; |
@@ -1596,7 +1634,7 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, | |||
1596 | 1634 | ||
1597 | static int ocfs2_check_volume(struct ocfs2_super *osb) | 1635 | static int ocfs2_check_volume(struct ocfs2_super *osb) |
1598 | { | 1636 | { |
1599 | int status = 0; | 1637 | int status; |
1600 | int dirty; | 1638 | int dirty; |
1601 | int local; | 1639 | int local; |
1602 | struct ocfs2_dinode *local_alloc = NULL; /* only used if we | 1640 | struct ocfs2_dinode *local_alloc = NULL; /* only used if we |
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index 5df6e35d09b1..fd2e846e3e6f 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c | |||
@@ -100,17 +100,14 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb, | |||
100 | char namebuf[40]; | 100 | char namebuf[40]; |
101 | struct inode *inode = NULL; | 101 | struct inode *inode = NULL; |
102 | u64 blkno; | 102 | u64 blkno; |
103 | struct buffer_head *dirent_bh = NULL; | ||
104 | struct ocfs2_dir_entry *de = NULL; | ||
105 | int status = 0; | 103 | int status = 0; |
106 | 104 | ||
107 | ocfs2_sprintf_system_inode_name(namebuf, | 105 | ocfs2_sprintf_system_inode_name(namebuf, |
108 | sizeof(namebuf), | 106 | sizeof(namebuf), |
109 | type, slot); | 107 | type, slot); |
110 | 108 | ||
111 | status = ocfs2_find_files_on_disk(namebuf, strlen(namebuf), | 109 | status = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf, |
112 | &blkno, osb->sys_root_inode, | 110 | strlen(namebuf), &blkno); |
113 | &dirent_bh, &de); | ||
114 | if (status < 0) { | 111 | if (status < 0) { |
115 | goto bail; | 112 | goto bail; |
116 | } | 113 | } |
@@ -122,8 +119,7 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb, | |||
122 | goto bail; | 119 | goto bail; |
123 | } | 120 | } |
124 | bail: | 121 | bail: |
125 | if (dirent_bh) | 122 | |
126 | brelse(dirent_bh); | ||
127 | return inode; | 123 | return inode; |
128 | } | 124 | } |
129 | 125 | ||
diff --git a/include/asm-s390/cache.h b/include/asm-s390/cache.h index cdf431b061bb..9b866816863c 100644 --- a/include/asm-s390/cache.h +++ b/include/asm-s390/cache.h | |||
@@ -14,8 +14,6 @@ | |||
14 | #define L1_CACHE_BYTES 256 | 14 | #define L1_CACHE_BYTES 256 |
15 | #define L1_CACHE_SHIFT 8 | 15 | #define L1_CACHE_SHIFT 8 |
16 | 16 | ||
17 | #define ARCH_KMALLOC_MINALIGN 8 | ||
18 | |||
19 | #define __read_mostly __attribute__((__section__(".data.read_mostly"))) | 17 | #define __read_mostly __attribute__((__section__(".data.read_mostly"))) |
20 | 18 | ||
21 | #endif | 19 | #endif |
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h index 1aeda27d5a8b..066aa70518ce 100644 --- a/include/asm-s390/ccwdev.h +++ b/include/asm-s390/ccwdev.h | |||
@@ -67,36 +67,55 @@ ccw_device_id_match(const struct ccw_device_id *array, | |||
67 | return NULL; | 67 | return NULL; |
68 | } | 68 | } |
69 | 69 | ||
70 | /* The struct ccw device is our replacement for the globally accessible | 70 | /** |
71 | * ioinfo array. ioinfo will mutate into a subchannel device later. | 71 | * struct ccw_device - channel attached device |
72 | * @ccwlock: pointer to device lock | ||
73 | * @id: id of this device | ||
74 | * @drv: ccw driver for this device | ||
75 | * @dev: embedded device structure | ||
76 | * @online: online status of device | ||
77 | * @handler: interrupt handler | ||
72 | * | 78 | * |
73 | * Reference: Documentation/s390/driver-model.txt */ | 79 | * @handler is a member of the device rather than the driver since a driver |
80 | * can have different interrupt handlers for different ccw devices | ||
81 | * (multi-subchannel drivers). | ||
82 | */ | ||
74 | struct ccw_device { | 83 | struct ccw_device { |
75 | spinlock_t *ccwlock; | 84 | spinlock_t *ccwlock; |
85 | /* private: */ | ||
76 | struct ccw_device_private *private; /* cio private information */ | 86 | struct ccw_device_private *private; /* cio private information */ |
77 | struct ccw_device_id id; /* id of this device, driver_info is | 87 | /* public: */ |
78 | set by ccw_find_driver */ | 88 | struct ccw_device_id id; |
79 | struct ccw_driver *drv; /* */ | 89 | struct ccw_driver *drv; |
80 | struct device dev; /* */ | 90 | struct device dev; |
81 | int online; | 91 | int online; |
82 | /* This is sick, but a driver can have different interrupt handlers | ||
83 | for different ccw_devices (multi-subchannel drivers)... */ | ||
84 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); | 92 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); |
85 | }; | 93 | }; |
86 | 94 | ||
87 | 95 | ||
88 | /* Each ccw driver registers with the ccw root bus */ | 96 | /** |
97 | * struct ccw driver - device driver for channel attached devices | ||
98 | * @owner: owning module | ||
99 | * @ids: ids supported by this driver | ||
100 | * @probe: function called on probe | ||
101 | * @remove: function called on remove | ||
102 | * @set_online: called when setting device online | ||
103 | * @set_offline: called when setting device offline | ||
104 | * @notify: notify driver of device state changes | ||
105 | * @shutdown: called at device shutdown | ||
106 | * @driver: embedded device driver structure | ||
107 | * @name: device driver name | ||
108 | */ | ||
89 | struct ccw_driver { | 109 | struct ccw_driver { |
90 | struct module *owner; /* for automatic MOD_INC_USE_COUNT */ | 110 | struct module *owner; |
91 | struct ccw_device_id *ids; /* probe driver with these devs */ | 111 | struct ccw_device_id *ids; |
92 | int (*probe) (struct ccw_device *); /* ask driver to probe dev */ | 112 | int (*probe) (struct ccw_device *); |
93 | void (*remove) (struct ccw_device *); | 113 | void (*remove) (struct ccw_device *); |
94 | /* device is no longer available */ | ||
95 | int (*set_online) (struct ccw_device *); | 114 | int (*set_online) (struct ccw_device *); |
96 | int (*set_offline) (struct ccw_device *); | 115 | int (*set_offline) (struct ccw_device *); |
97 | int (*notify) (struct ccw_device *, int); | 116 | int (*notify) (struct ccw_device *, int); |
98 | struct device_driver driver; /* higher level structure, don't init | 117 | void (*shutdown) (struct ccw_device *); |
99 | this from your driver */ | 118 | struct device_driver driver; |
100 | char *name; | 119 | char *name; |
101 | }; | 120 | }; |
102 | 121 | ||
@@ -124,36 +143,10 @@ extern void ccw_device_clear_options(struct ccw_device *, unsigned long); | |||
124 | /* Allow forced onlining of boxed devices. */ | 143 | /* Allow forced onlining of boxed devices. */ |
125 | #define CCWDEV_ALLOW_FORCE 0x0008 | 144 | #define CCWDEV_ALLOW_FORCE 0x0008 |
126 | 145 | ||
127 | /* | ||
128 | * ccw_device_start() | ||
129 | * | ||
130 | * Start a S/390 channel program. When the interrupt arrives, the | ||
131 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
132 | * or sense required) or never (no IRQ handler registered). | ||
133 | * Depending on the action taken, ccw_device_start() returns: | ||
134 | * 0 - Success | ||
135 | * -EBUSY - Device busy, or status pending | ||
136 | * -ENODEV - Device not operational | ||
137 | * -EINVAL - Device invalid for operation | ||
138 | */ | ||
139 | extern int ccw_device_start(struct ccw_device *, struct ccw1 *, | 146 | extern int ccw_device_start(struct ccw_device *, struct ccw1 *, |
140 | unsigned long, __u8, unsigned long); | 147 | unsigned long, __u8, unsigned long); |
141 | /* | ||
142 | * ccw_device_start_timeout() | ||
143 | * | ||
144 | * This function notifies the device driver if the channel program has not | ||
145 | * completed during the specified time. If a timeout occurs, the channel | ||
146 | * program is terminated via xsch(), hsch() or csch(). | ||
147 | */ | ||
148 | extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *, | 148 | extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *, |
149 | unsigned long, __u8, unsigned long, int); | 149 | unsigned long, __u8, unsigned long, int); |
150 | /* | ||
151 | * ccw_device_start_key() | ||
152 | * ccw_device_start_key_timeout() | ||
153 | * | ||
154 | * Same as ccw_device_start() and ccw_device_start_timeout(), except a | ||
155 | * storage key != default key can be provided for the I/O. | ||
156 | */ | ||
157 | extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *, | 150 | extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *, |
158 | unsigned long, __u8, __u8, unsigned long); | 151 | unsigned long, __u8, __u8, unsigned long); |
159 | extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *, | 152 | extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *, |
diff --git a/include/asm-s390/ccwgroup.h b/include/asm-s390/ccwgroup.h index 925b3ddfa141..7109c7cab87e 100644 --- a/include/asm-s390/ccwgroup.h +++ b/include/asm-s390/ccwgroup.h | |||
@@ -4,19 +4,41 @@ | |||
4 | struct ccw_device; | 4 | struct ccw_device; |
5 | struct ccw_driver; | 5 | struct ccw_driver; |
6 | 6 | ||
7 | /** | ||
8 | * struct ccwgroup_device - ccw group device | ||
9 | * @creator_id: unique number of the driver | ||
10 | * @state: online/offline state | ||
11 | * @count: number of attached slave devices | ||
12 | * @dev: embedded device structure | ||
13 | * @cdev: variable number of slave devices, allocated as needed | ||
14 | */ | ||
7 | struct ccwgroup_device { | 15 | struct ccwgroup_device { |
8 | unsigned long creator_id; /* unique number of the driver */ | 16 | unsigned long creator_id; |
9 | enum { | 17 | enum { |
10 | CCWGROUP_OFFLINE, | 18 | CCWGROUP_OFFLINE, |
11 | CCWGROUP_ONLINE, | 19 | CCWGROUP_ONLINE, |
12 | } state; | 20 | } state; |
21 | /* private: */ | ||
13 | atomic_t onoff; | 22 | atomic_t onoff; |
14 | struct mutex reg_mutex; | 23 | struct mutex reg_mutex; |
15 | unsigned int count; /* number of attached slave devices */ | 24 | /* public: */ |
16 | struct device dev; /* master device */ | 25 | unsigned int count; |
17 | struct ccw_device *cdev[0]; /* variable number, allocate as needed */ | 26 | struct device dev; |
27 | struct ccw_device *cdev[0]; | ||
18 | }; | 28 | }; |
19 | 29 | ||
30 | /** | ||
31 | * struct ccwgroup_driver - driver for ccw group devices | ||
32 | * @owner: driver owner | ||
33 | * @name: driver name | ||
34 | * @max_slaves: maximum number of slave devices | ||
35 | * @driver_id: unique id | ||
36 | * @probe: function called on probe | ||
37 | * @remove: function called on remove | ||
38 | * @set_online: function called when device is set online | ||
39 | * @set_offline: function called when device is set offline | ||
40 | * @driver: embedded driver structure | ||
41 | */ | ||
20 | struct ccwgroup_driver { | 42 | struct ccwgroup_driver { |
21 | struct module *owner; | 43 | struct module *owner; |
22 | char *name; | 44 | char *name; |
@@ -28,7 +50,7 @@ struct ccwgroup_driver { | |||
28 | int (*set_online) (struct ccwgroup_device *); | 50 | int (*set_online) (struct ccwgroup_device *); |
29 | int (*set_offline) (struct ccwgroup_device *); | 51 | int (*set_offline) (struct ccwgroup_device *); |
30 | 52 | ||
31 | struct device_driver driver; /* this driver */ | 53 | struct device_driver driver; |
32 | }; | 54 | }; |
33 | 55 | ||
34 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); | 56 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); |
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index 1982fb344164..2f08c16e44ad 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h | |||
@@ -15,30 +15,50 @@ | |||
15 | #define LPM_ANYPATH 0xff | 15 | #define LPM_ANYPATH 0xff |
16 | #define __MAX_CSSID 0 | 16 | #define __MAX_CSSID 0 |
17 | 17 | ||
18 | /* | 18 | /** |
19 | * subchannel status word | 19 | * struct scsw - subchannel status word |
20 | * @key: subchannel key | ||
21 | * @sctl: suspend control | ||
22 | * @eswf: esw format | ||
23 | * @cc: deferred condition code | ||
24 | * @fmt: format | ||
25 | * @pfch: prefetch | ||
26 | * @isic: initial-status interruption control | ||
27 | * @alcc: adress-limit checking control | ||
28 | * @ssi: supress-suspended interruption | ||
29 | * @zcc: zero condition code | ||
30 | * @ectl: extended control | ||
31 | * @pno: path not operational | ||
32 | * @res: reserved | ||
33 | * @fctl: function control | ||
34 | * @actl: activity control | ||
35 | * @stctl: status control | ||
36 | * @cpa: channel program address | ||
37 | * @dstat: device status | ||
38 | * @cstat: subchannel status | ||
39 | * @count: residual count | ||
20 | */ | 40 | */ |
21 | struct scsw { | 41 | struct scsw { |
22 | __u32 key : 4; /* subchannel key */ | 42 | __u32 key : 4; |
23 | __u32 sctl : 1; /* suspend control */ | 43 | __u32 sctl : 1; |
24 | __u32 eswf : 1; /* ESW format */ | 44 | __u32 eswf : 1; |
25 | __u32 cc : 2; /* deferred condition code */ | 45 | __u32 cc : 2; |
26 | __u32 fmt : 1; /* format */ | 46 | __u32 fmt : 1; |
27 | __u32 pfch : 1; /* prefetch */ | 47 | __u32 pfch : 1; |
28 | __u32 isic : 1; /* initial-status interruption control */ | 48 | __u32 isic : 1; |
29 | __u32 alcc : 1; /* address-limit checking control */ | 49 | __u32 alcc : 1; |
30 | __u32 ssi : 1; /* supress-suspended interruption */ | 50 | __u32 ssi : 1; |
31 | __u32 zcc : 1; /* zero condition code */ | 51 | __u32 zcc : 1; |
32 | __u32 ectl : 1; /* extended control */ | 52 | __u32 ectl : 1; |
33 | __u32 pno : 1; /* path not operational */ | 53 | __u32 pno : 1; |
34 | __u32 res : 1; /* reserved */ | 54 | __u32 res : 1; |
35 | __u32 fctl : 3; /* function control */ | 55 | __u32 fctl : 3; |
36 | __u32 actl : 7; /* activity control */ | 56 | __u32 actl : 7; |
37 | __u32 stctl : 5; /* status control */ | 57 | __u32 stctl : 5; |
38 | __u32 cpa; /* channel program address */ | 58 | __u32 cpa; |
39 | __u32 dstat : 8; /* device status */ | 59 | __u32 dstat : 8; |
40 | __u32 cstat : 8; /* subchannel status */ | 60 | __u32 cstat : 8; |
41 | __u32 count : 16; /* residual count */ | 61 | __u32 count : 16; |
42 | } __attribute__ ((packed)); | 62 | } __attribute__ ((packed)); |
43 | 63 | ||
44 | #define SCSW_FCTL_CLEAR_FUNC 0x1 | 64 | #define SCSW_FCTL_CLEAR_FUNC 0x1 |
@@ -110,11 +130,22 @@ struct scsw { | |||
110 | #define SNS2_ENV_DATA_PRESENT 0x10 | 130 | #define SNS2_ENV_DATA_PRESENT 0x10 |
111 | #define SNS2_INPRECISE_END 0x04 | 131 | #define SNS2_INPRECISE_END 0x04 |
112 | 132 | ||
133 | /** | ||
134 | * struct ccw1 - channel command word | ||
135 | * @cmd_code: command code | ||
136 | * @flags: flags, like IDA adressing, etc. | ||
137 | * @count: byte count | ||
138 | * @cda: data address | ||
139 | * | ||
140 | * The ccw is the basic structure to build channel programs that perform | ||
141 | * operations with the device or the control unit. Only Format-1 channel | ||
142 | * command words are supported. | ||
143 | */ | ||
113 | struct ccw1 { | 144 | struct ccw1 { |
114 | __u8 cmd_code; /* command code */ | 145 | __u8 cmd_code; |
115 | __u8 flags; /* flags, like IDA addressing, etc. */ | 146 | __u8 flags; |
116 | __u16 count; /* byte count */ | 147 | __u16 count; |
117 | __u32 cda; /* data address */ | 148 | __u32 cda; |
118 | } __attribute__ ((packed,aligned(8))); | 149 | } __attribute__ ((packed,aligned(8))); |
119 | 150 | ||
120 | #define CCW_FLAG_DC 0x80 | 151 | #define CCW_FLAG_DC 0x80 |
@@ -140,102 +171,162 @@ struct ccw1 { | |||
140 | 171 | ||
141 | #define SENSE_MAX_COUNT 0x20 | 172 | #define SENSE_MAX_COUNT 0x20 |
142 | 173 | ||
174 | /** | ||
175 | * struct erw - extended report word | ||
176 | * @res0: reserved | ||
177 | * @auth: authorization check | ||
178 | * @pvrf: path-verification-required flag | ||
179 | * @cpt: channel-path timeout | ||
180 | * @fsavf: failing storage address validity flag | ||
181 | * @cons: concurrent sense | ||
182 | * @scavf: secondary ccw address validity flag | ||
183 | * @fsaf: failing storage address format | ||
184 | * @scnt: sense count, if @cons == %1 | ||
185 | * @res16: reserved | ||
186 | */ | ||
143 | struct erw { | 187 | struct erw { |
144 | __u32 res0 : 3; /* reserved */ | 188 | __u32 res0 : 3; |
145 | __u32 auth : 1; /* Authorization check */ | 189 | __u32 auth : 1; |
146 | __u32 pvrf : 1; /* path-verification-required flag */ | 190 | __u32 pvrf : 1; |
147 | __u32 cpt : 1; /* channel-path timeout */ | 191 | __u32 cpt : 1; |
148 | __u32 fsavf : 1; /* Failing storage address validity flag */ | 192 | __u32 fsavf : 1; |
149 | __u32 cons : 1; /* concurrent-sense */ | 193 | __u32 cons : 1; |
150 | __u32 scavf : 1; /* Secondary ccw address validity flag */ | 194 | __u32 scavf : 1; |
151 | __u32 fsaf : 1; /* Failing storage address format */ | 195 | __u32 fsaf : 1; |
152 | __u32 scnt : 6; /* sense count if cons == 1 */ | 196 | __u32 scnt : 6; |
153 | __u32 res16 : 16; /* reserved */ | 197 | __u32 res16 : 16; |
154 | } __attribute__ ((packed)); | 198 | } __attribute__ ((packed)); |
155 | 199 | ||
156 | /* | 200 | /** |
157 | * subchannel logout area | 201 | * struct sublog - subchannel logout area |
202 | * @res0: reserved | ||
203 | * @esf: extended status flags | ||
204 | * @lpum: last path used mask | ||
205 | * @arep: ancillary report | ||
206 | * @fvf: field-validity flags | ||
207 | * @sacc: storage access code | ||
208 | * @termc: termination code | ||
209 | * @devsc: device-status check | ||
210 | * @serr: secondary error | ||
211 | * @ioerr: i/o-error alert | ||
212 | * @seqc: sequence code | ||
158 | */ | 213 | */ |
159 | struct sublog { | 214 | struct sublog { |
160 | __u32 res0 : 1; /* reserved */ | 215 | __u32 res0 : 1; |
161 | __u32 esf : 7; /* extended status flags */ | 216 | __u32 esf : 7; |
162 | __u32 lpum : 8; /* last path used mask */ | 217 | __u32 lpum : 8; |
163 | __u32 arep : 1; /* ancillary report */ | 218 | __u32 arep : 1; |
164 | __u32 fvf : 5; /* field-validity flags */ | 219 | __u32 fvf : 5; |
165 | __u32 sacc : 2; /* storage access code */ | 220 | __u32 sacc : 2; |
166 | __u32 termc : 2; /* termination code */ | 221 | __u32 termc : 2; |
167 | __u32 devsc : 1; /* device-status check */ | 222 | __u32 devsc : 1; |
168 | __u32 serr : 1; /* secondary error */ | 223 | __u32 serr : 1; |
169 | __u32 ioerr : 1; /* i/o-error alert */ | 224 | __u32 ioerr : 1; |
170 | __u32 seqc : 3; /* sequence code */ | 225 | __u32 seqc : 3; |
171 | } __attribute__ ((packed)); | 226 | } __attribute__ ((packed)); |
172 | 227 | ||
173 | /* | 228 | /** |
174 | * Format 0 Extended Status Word (ESW) | 229 | * struct esw0 - Format 0 Extended Status Word (ESW) |
230 | * @sublog: subchannel logout | ||
231 | * @erw: extended report word | ||
232 | * @faddr: failing storage address | ||
233 | * @saddr: secondary ccw address | ||
175 | */ | 234 | */ |
176 | struct esw0 { | 235 | struct esw0 { |
177 | struct sublog sublog; /* subchannel logout */ | 236 | struct sublog sublog; |
178 | struct erw erw; /* extended report word */ | 237 | struct erw erw; |
179 | __u32 faddr[2]; /* failing storage address */ | 238 | __u32 faddr[2]; |
180 | __u32 saddr; /* secondary ccw address */ | 239 | __u32 saddr; |
181 | } __attribute__ ((packed)); | 240 | } __attribute__ ((packed)); |
182 | 241 | ||
183 | /* | 242 | /** |
184 | * Format 1 Extended Status Word (ESW) | 243 | * struct esw1 - Format 1 Extended Status Word (ESW) |
244 | * @zero0: reserved zeros | ||
245 | * @lpum: last path used mask | ||
246 | * @zero16: reserved zeros | ||
247 | * @erw: extended report word | ||
248 | * @zeros: three fullwords of zeros | ||
185 | */ | 249 | */ |
186 | struct esw1 { | 250 | struct esw1 { |
187 | __u8 zero0; /* reserved zeros */ | 251 | __u8 zero0; |
188 | __u8 lpum; /* last path used mask */ | 252 | __u8 lpum; |
189 | __u16 zero16; /* reserved zeros */ | 253 | __u16 zero16; |
190 | struct erw erw; /* extended report word */ | 254 | struct erw erw; |
191 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 255 | __u32 zeros[3]; |
192 | } __attribute__ ((packed)); | 256 | } __attribute__ ((packed)); |
193 | 257 | ||
194 | /* | 258 | /** |
195 | * Format 2 Extended Status Word (ESW) | 259 | * struct esw2 - Format 2 Extended Status Word (ESW) |
260 | * @zero0: reserved zeros | ||
261 | * @lpum: last path used mask | ||
262 | * @dcti: device-connect-time interval | ||
263 | * @erw: extended report word | ||
264 | * @zeros: three fullwords of zeros | ||
196 | */ | 265 | */ |
197 | struct esw2 { | 266 | struct esw2 { |
198 | __u8 zero0; /* reserved zeros */ | 267 | __u8 zero0; |
199 | __u8 lpum; /* last path used mask */ | 268 | __u8 lpum; |
200 | __u16 dcti; /* device-connect-time interval */ | 269 | __u16 dcti; |
201 | struct erw erw; /* extended report word */ | 270 | struct erw erw; |
202 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 271 | __u32 zeros[3]; |
203 | } __attribute__ ((packed)); | 272 | } __attribute__ ((packed)); |
204 | 273 | ||
205 | /* | 274 | /** |
206 | * Format 3 Extended Status Word (ESW) | 275 | * struct esw3 - Format 3 Extended Status Word (ESW) |
276 | * @zero0: reserved zeros | ||
277 | * @lpum: last path used mask | ||
278 | * @res: reserved | ||
279 | * @erw: extended report word | ||
280 | * @zeros: three fullwords of zeros | ||
207 | */ | 281 | */ |
208 | struct esw3 { | 282 | struct esw3 { |
209 | __u8 zero0; /* reserved zeros */ | 283 | __u8 zero0; |
210 | __u8 lpum; /* last path used mask */ | 284 | __u8 lpum; |
211 | __u16 res; /* reserved */ | 285 | __u16 res; |
212 | struct erw erw; /* extended report word */ | 286 | struct erw erw; |
213 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 287 | __u32 zeros[3]; |
214 | } __attribute__ ((packed)); | 288 | } __attribute__ ((packed)); |
215 | 289 | ||
216 | /* | 290 | /** |
217 | * interruption response block | 291 | * struct irb - interruption response block |
292 | * @scsw: subchannel status word | ||
293 | * @esw: extened status word, 4 formats | ||
294 | * @ecw: extended control word | ||
295 | * | ||
296 | * The irb that is handed to the device driver when an interrupt occurs. For | ||
297 | * solicited interrupts, the common I/O layer already performs checks whether | ||
298 | * a field is valid; a field not being valid is always passed as %0. | ||
299 | * If a unit check occured, @ecw may contain sense data; this is retrieved | ||
300 | * by the common I/O layer itself if the device doesn't support concurrent | ||
301 | * sense (so that the device driver never needs to perform basic sene itself). | ||
302 | * For unsolicited interrupts, the irb is passed as-is (expect for sense data, | ||
303 | * if applicable). | ||
218 | */ | 304 | */ |
219 | struct irb { | 305 | struct irb { |
220 | struct scsw scsw; /* subchannel status word */ | 306 | struct scsw scsw; |
221 | union { /* extended status word, 4 formats */ | 307 | union { |
222 | struct esw0 esw0; | 308 | struct esw0 esw0; |
223 | struct esw1 esw1; | 309 | struct esw1 esw1; |
224 | struct esw2 esw2; | 310 | struct esw2 esw2; |
225 | struct esw3 esw3; | 311 | struct esw3 esw3; |
226 | } esw; | 312 | } esw; |
227 | __u8 ecw[32]; /* extended control word */ | 313 | __u8 ecw[32]; |
228 | } __attribute__ ((packed,aligned(4))); | 314 | } __attribute__ ((packed,aligned(4))); |
229 | 315 | ||
230 | /* | 316 | /** |
231 | * command information word (CIW) layout | 317 | * struct ciw - command information word (CIW) layout |
318 | * @et: entry type | ||
319 | * @reserved: reserved bits | ||
320 | * @ct: command type | ||
321 | * @cmd: command code | ||
322 | * @count: command count | ||
232 | */ | 323 | */ |
233 | struct ciw { | 324 | struct ciw { |
234 | __u32 et : 2; /* entry type */ | 325 | __u32 et : 2; |
235 | __u32 reserved : 2; /* reserved */ | 326 | __u32 reserved : 2; |
236 | __u32 ct : 4; /* command type */ | 327 | __u32 ct : 4; |
237 | __u32 cmd : 8; /* command */ | 328 | __u32 cmd : 8; |
238 | __u32 count : 16; /* coun */ | 329 | __u32 count : 16; |
239 | } __attribute__ ((packed)); | 330 | } __attribute__ ((packed)); |
240 | 331 | ||
241 | #define CIW_TYPE_RCD 0x0 /* read configuration data */ | 332 | #define CIW_TYPE_RCD 0x0 /* read configuration data */ |
@@ -258,11 +349,32 @@ struct ciw { | |||
258 | /* Sick revalidation of device. */ | 349 | /* Sick revalidation of device. */ |
259 | #define CIO_REVALIDATE 0x0008 | 350 | #define CIO_REVALIDATE 0x0008 |
260 | 351 | ||
352 | /** | ||
353 | * struct ccw_dev_id - unique identifier for ccw devices | ||
354 | * @ssid: subchannel set id | ||
355 | * @devno: device number | ||
356 | * | ||
357 | * This structure is not directly based on any hardware structure. The | ||
358 | * hardware identifies a device by its device number and its subchannel, | ||
359 | * which is in turn identified by its id. In order to get a unique identifier | ||
360 | * for ccw devices across subchannel sets, @struct ccw_dev_id has been | ||
361 | * introduced. | ||
362 | */ | ||
261 | struct ccw_dev_id { | 363 | struct ccw_dev_id { |
262 | u8 ssid; | 364 | u8 ssid; |
263 | u16 devno; | 365 | u16 devno; |
264 | }; | 366 | }; |
265 | 367 | ||
368 | /** | ||
369 | * ccw_device_id_is_equal() - compare two ccw_dev_ids | ||
370 | * @dev_id1: a ccw_dev_id | ||
371 | * @dev_id2: another ccw_dev_id | ||
372 | * Returns: | ||
373 | * %1 if the two structures are equal field-by-field, | ||
374 | * %0 if not. | ||
375 | * Context: | ||
376 | * any | ||
377 | */ | ||
266 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, | 378 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, |
267 | struct ccw_dev_id *dev_id2) | 379 | struct ccw_dev_id *dev_id2) |
268 | { | 380 | { |
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h index 021e7c3223ec..50196857d27a 100644 --- a/include/asm-s390/cmb.h +++ b/include/asm-s390/cmb.h | |||
@@ -1,29 +1,29 @@ | |||
1 | #ifndef S390_CMB_H | 1 | #ifndef S390_CMB_H |
2 | #define S390_CMB_H | 2 | #define S390_CMB_H |
3 | /** | 3 | /** |
4 | * struct cmbdata -- channel measurement block data for user space | 4 | * struct cmbdata - channel measurement block data for user space |
5 | * @size: size of the stored data | ||
6 | * @elapsed_time: time since last sampling | ||
7 | * @ssch_rsch_count: number of ssch and rsch | ||
8 | * @sample_count: number of samples | ||
9 | * @device_connect_time: time of device connect | ||
10 | * @function_pending_time: time of function pending | ||
11 | * @device_disconnect_time: time of device disconnect | ||
12 | * @control_unit_queuing_time: time of control unit queuing | ||
13 | * @device_active_only_time: time of device active only | ||
14 | * @device_busy_time: time of device busy (ext. format) | ||
15 | * @initial_command_response_time: initial command response time (ext. format) | ||
5 | * | 16 | * |
6 | * @size: size of the stored data | 17 | * All values are stored as 64 bit for simplicity, especially |
7 | * @ssch_rsch_count: XXX | ||
8 | * @sample_count: | ||
9 | * @device_connect_time: | ||
10 | * @function_pending_time: | ||
11 | * @device_disconnect_time: | ||
12 | * @control_unit_queuing_time: | ||
13 | * @device_active_only_time: | ||
14 | * @device_busy_time: | ||
15 | * @initial_command_response_time: | ||
16 | * | ||
17 | * all values are stored as 64 bit for simplicity, especially | ||
18 | * in 32 bit emulation mode. All time values are normalized to | 18 | * in 32 bit emulation mode. All time values are normalized to |
19 | * nanoseconds. | 19 | * nanoseconds. |
20 | * Currently, two formats are known, which differ by the size of | 20 | * Currently, two formats are known, which differ by the size of |
21 | * this structure, i.e. the last two members are only set when | 21 | * this structure, i.e. the last two members are only set when |
22 | * the extended channel measurement facility (first shipped in | 22 | * the extended channel measurement facility (first shipped in |
23 | * z990 machines) is activated. | 23 | * z990 machines) is activated. |
24 | * Potentially, more fields could be added, which results in a | 24 | * Potentially, more fields could be added, which would result in a |
25 | * new ioctl number. | 25 | * new ioctl number. |
26 | **/ | 26 | */ |
27 | struct cmbdata { | 27 | struct cmbdata { |
28 | __u64 size; | 28 | __u64 size; |
29 | __u64 elapsed_time; | 29 | __u64 elapsed_time; |
@@ -41,53 +41,18 @@ struct cmbdata { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | /* enable channel measurement */ | 43 | /* enable channel measurement */ |
44 | #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) | 44 | #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER, 32) |
45 | /* enable channel measurement */ | 45 | /* enable channel measurement */ |
46 | #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) | 46 | #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER, 33) |
47 | /* read channel measurement data */ | 47 | /* read channel measurement data */ |
48 | #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) | 48 | #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata) |
49 | 49 | ||
50 | #ifdef __KERNEL__ | 50 | #ifdef __KERNEL__ |
51 | struct ccw_device; | 51 | struct ccw_device; |
52 | /** | ||
53 | * enable_cmf() - switch on the channel measurement for a specific device | ||
54 | * @cdev: The ccw device to be enabled | ||
55 | * returns 0 for success or a negative error value. | ||
56 | * | ||
57 | * Context: | ||
58 | * non-atomic | ||
59 | **/ | ||
60 | extern int enable_cmf(struct ccw_device *cdev); | 52 | extern int enable_cmf(struct ccw_device *cdev); |
61 | |||
62 | /** | ||
63 | * disable_cmf() - switch off the channel measurement for a specific device | ||
64 | * @cdev: The ccw device to be disabled | ||
65 | * returns 0 for success or a negative error value. | ||
66 | * | ||
67 | * Context: | ||
68 | * non-atomic | ||
69 | **/ | ||
70 | extern int disable_cmf(struct ccw_device *cdev); | 53 | extern int disable_cmf(struct ccw_device *cdev); |
71 | |||
72 | /** | ||
73 | * cmf_read() - read one value from the current channel measurement block | ||
74 | * @cmf: the channel to be read | ||
75 | * @index: the name of the value that is read | ||
76 | * | ||
77 | * Context: | ||
78 | * any | ||
79 | **/ | ||
80 | |||
81 | extern u64 cmf_read(struct ccw_device *cdev, int index); | 54 | extern u64 cmf_read(struct ccw_device *cdev, int index); |
82 | /** | 55 | extern int cmf_readall(struct ccw_device *cdev, struct cmbdata *data); |
83 | * cmf_readall() - read one value from the current channel measurement block | ||
84 | * @cmf: the channel to be read | ||
85 | * @data: a pointer to a data block that will be filled | ||
86 | * | ||
87 | * Context: | ||
88 | * any | ||
89 | **/ | ||
90 | extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data); | ||
91 | 56 | ||
92 | #endif /* __KERNEL__ */ | 57 | #endif /* __KERNEL__ */ |
93 | #endif /* S390_CMB_H */ | 58 | #endif /* S390_CMB_H */ |
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h index f326451ed6ec..ceec3826a67c 100644 --- a/include/asm-s390/page.h +++ b/include/asm-s390/page.h | |||
@@ -9,11 +9,12 @@ | |||
9 | #ifndef _S390_PAGE_H | 9 | #ifndef _S390_PAGE_H |
10 | #define _S390_PAGE_H | 10 | #define _S390_PAGE_H |
11 | 11 | ||
12 | #include <linux/const.h> | ||
12 | #include <asm/types.h> | 13 | #include <asm/types.h> |
13 | 14 | ||
14 | /* PAGE_SHIFT determines the page size */ | 15 | /* PAGE_SHIFT determines the page size */ |
15 | #define PAGE_SHIFT 12 | 16 | #define PAGE_SHIFT 12 |
16 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | 17 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) |
17 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 18 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
18 | #define PAGE_DEFAULT_ACC 0 | 19 | #define PAGE_DEFAULT_ACC 0 |
19 | #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) | 20 | #define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4) |
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 3208dc6c412c..39bb5192dc31 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h | |||
@@ -107,11 +107,18 @@ extern char empty_zero_page[PAGE_SIZE]; | |||
107 | * any out-of-bounds memory accesses will hopefully be caught. | 107 | * any out-of-bounds memory accesses will hopefully be caught. |
108 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced | 108 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced |
109 | * area for the same reason. ;) | 109 | * area for the same reason. ;) |
110 | * vmalloc area starts at 4GB to prevent syscall table entry exchanging | ||
111 | * from modules. | ||
110 | */ | 112 | */ |
111 | extern unsigned long vmalloc_end; | 113 | extern unsigned long vmalloc_end; |
112 | #define VMALLOC_OFFSET (8*1024*1024) | 114 | |
113 | #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \ | 115 | #ifdef CONFIG_64BIT |
114 | & ~(VMALLOC_OFFSET-1)) | 116 | #define VMALLOC_ADDR (max(0x100000000UL, (unsigned long) high_memory)) |
117 | #else | ||
118 | #define VMALLOC_ADDR ((unsigned long) high_memory) | ||
119 | #endif | ||
120 | #define VMALLOC_OFFSET (8*1024*1024) | ||
121 | #define VMALLOC_START ((VMALLOC_ADDR + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) | ||
115 | #define VMALLOC_END vmalloc_end | 122 | #define VMALLOC_END vmalloc_end |
116 | 123 | ||
117 | /* | 124 | /* |
diff --git a/include/asm-s390/s390_ext.h b/include/asm-s390/s390_ext.h index 1e72362cad78..2afc060266a2 100644 --- a/include/asm-s390/s390_ext.h +++ b/include/asm-s390/s390_ext.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * include/asm-s390/s390_ext.h | 5 | * include/asm-s390/s390_ext.h |
6 | * | 6 | * |
7 | * S390 version | 7 | * S390 version |
8 | * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | 8 | * Copyright IBM Corp. 1999,2007 |
9 | * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), | 9 | * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), |
10 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 10 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
11 | */ | 11 | */ |
@@ -14,15 +14,11 @@ | |||
14 | 14 | ||
15 | typedef void (*ext_int_handler_t)(__u16 code); | 15 | typedef void (*ext_int_handler_t)(__u16 code); |
16 | 16 | ||
17 | /* | ||
18 | * Warning: if you change ext_int_info_t you have to change the | ||
19 | * external interrupt handler in entry.S too. | ||
20 | */ | ||
21 | typedef struct ext_int_info_t { | 17 | typedef struct ext_int_info_t { |
22 | struct ext_int_info_t *next; | 18 | struct ext_int_info_t *next; |
23 | ext_int_handler_t handler; | 19 | ext_int_handler_t handler; |
24 | __u16 code; | 20 | __u16 code; |
25 | } __attribute__ ((packed)) ext_int_info_t; | 21 | } ext_int_info_t; |
26 | 22 | ||
27 | extern ext_int_info_t *ext_int_hash[]; | 23 | extern ext_int_info_t *ext_int_hash[]; |
28 | 24 | ||
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 64a3cd05cae1..d866d3385556 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -130,6 +130,8 @@ extern void pfault_fini(void); | |||
130 | __ret; \ | 130 | __ret; \ |
131 | }) | 131 | }) |
132 | 132 | ||
133 | extern void __xchg_called_with_bad_pointer(void); | ||
134 | |||
133 | static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | 135 | static inline unsigned long __xchg(unsigned long x, void * ptr, int size) |
134 | { | 136 | { |
135 | unsigned long addr, old; | 137 | unsigned long addr, old; |
@@ -150,8 +152,7 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | |||
150 | : "=&d" (old), "=m" (*(int *) addr) | 152 | : "=&d" (old), "=m" (*(int *) addr) |
151 | : "d" (x << shift), "d" (~(255 << shift)), "a" (addr), | 153 | : "d" (x << shift), "d" (~(255 << shift)), "a" (addr), |
152 | "m" (*(int *) addr) : "memory", "cc", "0"); | 154 | "m" (*(int *) addr) : "memory", "cc", "0"); |
153 | x = old >> shift; | 155 | return old >> shift; |
154 | break; | ||
155 | case 2: | 156 | case 2: |
156 | addr = (unsigned long) ptr; | 157 | addr = (unsigned long) ptr; |
157 | shift = (2 ^ (addr & 2)) << 3; | 158 | shift = (2 ^ (addr & 2)) << 3; |
@@ -166,8 +167,7 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | |||
166 | : "=&d" (old), "=m" (*(int *) addr) | 167 | : "=&d" (old), "=m" (*(int *) addr) |
167 | : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr), | 168 | : "d" (x << shift), "d" (~(65535 << shift)), "a" (addr), |
168 | "m" (*(int *) addr) : "memory", "cc", "0"); | 169 | "m" (*(int *) addr) : "memory", "cc", "0"); |
169 | x = old >> shift; | 170 | return old >> shift; |
170 | break; | ||
171 | case 4: | 171 | case 4: |
172 | asm volatile( | 172 | asm volatile( |
173 | " l %0,0(%3)\n" | 173 | " l %0,0(%3)\n" |
@@ -176,8 +176,7 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | |||
176 | : "=&d" (old), "=m" (*(int *) ptr) | 176 | : "=&d" (old), "=m" (*(int *) ptr) |
177 | : "d" (x), "a" (ptr), "m" (*(int *) ptr) | 177 | : "d" (x), "a" (ptr), "m" (*(int *) ptr) |
178 | : "memory", "cc"); | 178 | : "memory", "cc"); |
179 | x = old; | 179 | return old; |
180 | break; | ||
181 | #ifdef __s390x__ | 180 | #ifdef __s390x__ |
182 | case 8: | 181 | case 8: |
183 | asm volatile( | 182 | asm volatile( |
@@ -187,11 +186,11 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | |||
187 | : "=&d" (old), "=m" (*(long *) ptr) | 186 | : "=&d" (old), "=m" (*(long *) ptr) |
188 | : "d" (x), "a" (ptr), "m" (*(long *) ptr) | 187 | : "d" (x), "a" (ptr), "m" (*(long *) ptr) |
189 | : "memory", "cc"); | 188 | : "memory", "cc"); |
190 | x = old; | 189 | return old; |
191 | break; | ||
192 | #endif /* __s390x__ */ | 190 | #endif /* __s390x__ */ |
193 | } | 191 | } |
194 | return x; | 192 | __xchg_called_with_bad_pointer(); |
193 | return x; | ||
195 | } | 194 | } |
196 | 195 | ||
197 | /* | 196 | /* |
@@ -206,6 +205,8 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) | |||
206 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | 205 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ |
207 | (unsigned long)(n),sizeof(*(ptr)))) | 206 | (unsigned long)(n),sizeof(*(ptr)))) |
208 | 207 | ||
208 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
209 | |||
209 | static inline unsigned long | 210 | static inline unsigned long |
210 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | 211 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) |
211 | { | 212 | { |
@@ -270,7 +271,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
270 | return prev; | 271 | return prev; |
271 | #endif /* __s390x__ */ | 272 | #endif /* __s390x__ */ |
272 | } | 273 | } |
273 | return old; | 274 | __cmpxchg_called_with_bad_pointer(); |
275 | return old; | ||
274 | } | 276 | } |
275 | 277 | ||
276 | /* | 278 | /* |
diff --git a/include/asm-s390/zcrypt.h b/include/asm-s390/zcrypt.h index b90e55888a55..a5dada617751 100644 --- a/include/asm-s390/zcrypt.h +++ b/include/asm-s390/zcrypt.h | |||
@@ -91,7 +91,7 @@ struct ica_rsa_modexpo_crt { | |||
91 | * VUD block | 91 | * VUD block |
92 | * key block | 92 | * key block |
93 | */ | 93 | */ |
94 | struct ica_CPRBX { | 94 | struct CPRBX { |
95 | unsigned short cprb_len; /* CPRB length 220 */ | 95 | unsigned short cprb_len; /* CPRB length 220 */ |
96 | unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ | 96 | unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ |
97 | unsigned char pad_000[3]; /* Alignment pad bytes */ | 97 | unsigned char pad_000[3]; /* Alignment pad bytes */ |
@@ -130,7 +130,7 @@ struct ica_CPRBX { | |||
130 | unsigned char cntrl_domain[4];/* Control domain */ | 130 | unsigned char cntrl_domain[4];/* Control domain */ |
131 | unsigned char S390enf_mask[4];/* S/390 enforcement mask */ | 131 | unsigned char S390enf_mask[4];/* S/390 enforcement mask */ |
132 | unsigned char pad_004[36]; /* reserved */ | 132 | unsigned char pad_004[36]; /* reserved */ |
133 | }; | 133 | } __attribute__((packed)); |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * xcRB | 136 | * xcRB |
diff --git a/include/asm-x86/8253pit.h b/include/asm-x86/8253pit.h deleted file mode 100644 index d3c2b38a6618..000000000000 --- a/include/asm-x86/8253pit.h +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | #ifdef CONFIG_X86_32 | ||
2 | # include "8253pit_32.h" | ||
3 | #else | ||
4 | # include "8253pit_64.h" | ||
5 | #endif | ||
diff --git a/include/asm-x86/8253pit_32.h b/include/asm-x86/8253pit_32.h deleted file mode 100644 index 96c7c3592daf..000000000000 --- a/include/asm-x86/8253pit_32.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* | ||
2 | * 8253/8254 Programmable Interval Timer | ||
3 | */ | ||
4 | |||
5 | #ifndef _8253PIT_H | ||
6 | #define _8253PIT_H | ||
7 | |||
8 | #include <asm/timex.h> | ||
9 | |||
10 | #define PIT_TICK_RATE CLOCK_TICK_RATE | ||
11 | |||
12 | #endif | ||
diff --git a/include/asm-x86/8253pit_64.h b/include/asm-x86/8253pit_64.h deleted file mode 100644 index 285f78488ccb..000000000000 --- a/include/asm-x86/8253pit_64.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | /* | ||
2 | * 8253/8254 Programmable Interval Timer | ||
3 | */ | ||
4 | |||
5 | #ifndef _8253PIT_H | ||
6 | #define _8253PIT_H | ||
7 | |||
8 | #define PIT_TICK_RATE 1193182UL | ||
9 | |||
10 | #endif | ||
diff --git a/include/asm-x86/apic_64.h b/include/asm-x86/apic_64.h index 85125ef3c414..3c8f21eef0be 100644 --- a/include/asm-x86/apic_64.h +++ b/include/asm-x86/apic_64.h | |||
@@ -19,7 +19,7 @@ | |||
19 | extern int apic_verbosity; | 19 | extern int apic_verbosity; |
20 | extern int apic_runs_main_timer; | 20 | extern int apic_runs_main_timer; |
21 | extern int ioapic_force; | 21 | extern int ioapic_force; |
22 | extern int apic_mapped; | 22 | extern int disable_apic_timer; |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Define the default level of output to be very little | 25 | * Define the default level of output to be very little |
@@ -79,8 +79,6 @@ extern void smp_local_timer_interrupt (void); | |||
79 | extern void setup_boot_APIC_clock (void); | 79 | extern void setup_boot_APIC_clock (void); |
80 | extern void setup_secondary_APIC_clock (void); | 80 | extern void setup_secondary_APIC_clock (void); |
81 | extern int APIC_init_uniprocessor (void); | 81 | extern int APIC_init_uniprocessor (void); |
82 | extern void disable_APIC_timer(void); | ||
83 | extern void enable_APIC_timer(void); | ||
84 | extern void setup_apic_routing(void); | 82 | extern void setup_apic_routing(void); |
85 | 83 | ||
86 | extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | 84 | extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, |
@@ -95,10 +93,6 @@ extern int apic_is_clustered_box(void); | |||
95 | #define K8_APIC_EXT_INT_MSG_EXT 0x7 | 93 | #define K8_APIC_EXT_INT_MSG_EXT 0x7 |
96 | #define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 | 94 | #define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 |
97 | 95 | ||
98 | void smp_send_timer_broadcast_ipi(void); | ||
99 | void switch_APIC_timer_to_ipi(void *cpumask); | ||
100 | void switch_ipi_to_APIC_timer(void *cpumask); | ||
101 | |||
102 | #define ARCH_APICTIMER_STOPS_ON_C3 1 | 96 | #define ARCH_APICTIMER_STOPS_ON_C3 1 |
103 | 97 | ||
104 | extern unsigned boot_cpu_id; | 98 | extern unsigned boot_cpu_id; |
diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h index 6da4bbbea3dc..d94898831bac 100644 --- a/include/asm-x86/geode.h +++ b/include/asm-x86/geode.h | |||
@@ -156,4 +156,54 @@ static inline int is_geode(void) | |||
156 | return (is_geode_gx() || is_geode_lx()); | 156 | return (is_geode_gx() || is_geode_lx()); |
157 | } | 157 | } |
158 | 158 | ||
159 | /* MFGPTs */ | ||
160 | |||
161 | #define MFGPT_MAX_TIMERS 8 | ||
162 | #define MFGPT_TIMER_ANY -1 | ||
163 | |||
164 | #define MFGPT_DOMAIN_WORKING 1 | ||
165 | #define MFGPT_DOMAIN_STANDBY 2 | ||
166 | #define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY) | ||
167 | |||
168 | #define MFGPT_CMP1 0 | ||
169 | #define MFGPT_CMP2 1 | ||
170 | |||
171 | #define MFGPT_EVENT_IRQ 0 | ||
172 | #define MFGPT_EVENT_NMI 1 | ||
173 | #define MFGPT_EVENT_RESET 3 | ||
174 | |||
175 | #define MFGPT_REG_CMP1 0 | ||
176 | #define MFGPT_REG_CMP2 2 | ||
177 | #define MFGPT_REG_COUNTER 4 | ||
178 | #define MFGPT_REG_SETUP 6 | ||
179 | |||
180 | #define MFGPT_SETUP_CNTEN (1 << 15) | ||
181 | #define MFGPT_SETUP_CMP2 (1 << 14) | ||
182 | #define MFGPT_SETUP_CMP1 (1 << 13) | ||
183 | #define MFGPT_SETUP_SETUP (1 << 12) | ||
184 | #define MFGPT_SETUP_STOPEN (1 << 11) | ||
185 | #define MFGPT_SETUP_EXTEN (1 << 10) | ||
186 | #define MFGPT_SETUP_REVEN (1 << 5) | ||
187 | #define MFGPT_SETUP_CLKSEL (1 << 4) | ||
188 | |||
189 | static inline void geode_mfgpt_write(int timer, u16 reg, u16 value) | ||
190 | { | ||
191 | u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | ||
192 | outw(value, base + reg + (timer * 8)); | ||
193 | } | ||
194 | |||
195 | static inline u16 geode_mfgpt_read(int timer, u16 reg) | ||
196 | { | ||
197 | u32 base = geode_get_dev_base(GEODE_DEV_MFGPT); | ||
198 | return inw(base + reg + (timer * 8)); | ||
199 | } | ||
200 | |||
201 | extern int __init geode_mfgpt_detect(void); | ||
202 | extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable); | ||
203 | extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable); | ||
204 | extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner); | ||
205 | |||
206 | #define geode_mfgpt_setup_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 1) | ||
207 | #define geode_mfgpt_release_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 0) | ||
208 | |||
159 | #endif | 209 | #endif |
diff --git a/include/asm-x86/hardirq_32.h b/include/asm-x86/hardirq_32.h index 0e358dc405f8..34649585bb59 100644 --- a/include/asm-x86/hardirq_32.h +++ b/include/asm-x86/hardirq_32.h | |||
@@ -9,6 +9,7 @@ typedef struct { | |||
9 | unsigned long idle_timestamp; | 9 | unsigned long idle_timestamp; |
10 | unsigned int __nmi_count; /* arch dependent */ | 10 | unsigned int __nmi_count; /* arch dependent */ |
11 | unsigned int apic_timer_irqs; /* arch dependent */ | 11 | unsigned int apic_timer_irqs; /* arch dependent */ |
12 | unsigned int irq0_irqs; | ||
12 | } ____cacheline_aligned irq_cpustat_t; | 13 | } ____cacheline_aligned irq_cpustat_t; |
13 | 14 | ||
14 | DECLARE_PER_CPU(irq_cpustat_t, irq_stat); | 15 | DECLARE_PER_CPU(irq_cpustat_t, irq_stat); |
diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index 9eff48601254..d4ab6db050b6 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h | |||
@@ -1,5 +1,93 @@ | |||
1 | #ifdef CONFIG_X86_32 | 1 | #ifndef ASM_X86_HPET_H |
2 | # include "hpet_32.h" | 2 | #define ASM_X86_HPET_H |
3 | |||
4 | #ifdef CONFIG_HPET_TIMER | ||
5 | |||
6 | /* | ||
7 | * Documentation on HPET can be found at: | ||
8 | * http://www.intel.com/ial/home/sp/pcmmspec.htm | ||
9 | * ftp://download.intel.com/ial/home/sp/mmts098.pdf | ||
10 | */ | ||
11 | |||
12 | #define HPET_MMAP_SIZE 1024 | ||
13 | |||
14 | #define HPET_ID 0x000 | ||
15 | #define HPET_PERIOD 0x004 | ||
16 | #define HPET_CFG 0x010 | ||
17 | #define HPET_STATUS 0x020 | ||
18 | #define HPET_COUNTER 0x0f0 | ||
19 | #define HPET_T0_CFG 0x100 | ||
20 | #define HPET_T0_CMP 0x108 | ||
21 | #define HPET_T0_ROUTE 0x110 | ||
22 | #define HPET_T1_CFG 0x120 | ||
23 | #define HPET_T1_CMP 0x128 | ||
24 | #define HPET_T1_ROUTE 0x130 | ||
25 | #define HPET_T2_CFG 0x140 | ||
26 | #define HPET_T2_CMP 0x148 | ||
27 | #define HPET_T2_ROUTE 0x150 | ||
28 | |||
29 | #define HPET_ID_REV 0x000000ff | ||
30 | #define HPET_ID_NUMBER 0x00001f00 | ||
31 | #define HPET_ID_64BIT 0x00002000 | ||
32 | #define HPET_ID_LEGSUP 0x00008000 | ||
33 | #define HPET_ID_VENDOR 0xffff0000 | ||
34 | #define HPET_ID_NUMBER_SHIFT 8 | ||
35 | #define HPET_ID_VENDOR_SHIFT 16 | ||
36 | |||
37 | #define HPET_ID_VENDOR_8086 0x8086 | ||
38 | |||
39 | #define HPET_CFG_ENABLE 0x001 | ||
40 | #define HPET_CFG_LEGACY 0x002 | ||
41 | #define HPET_LEGACY_8254 2 | ||
42 | #define HPET_LEGACY_RTC 8 | ||
43 | |||
44 | #define HPET_TN_LEVEL 0x0002 | ||
45 | #define HPET_TN_ENABLE 0x0004 | ||
46 | #define HPET_TN_PERIODIC 0x0008 | ||
47 | #define HPET_TN_PERIODIC_CAP 0x0010 | ||
48 | #define HPET_TN_64BIT_CAP 0x0020 | ||
49 | #define HPET_TN_SETVAL 0x0040 | ||
50 | #define HPET_TN_32BIT 0x0100 | ||
51 | #define HPET_TN_ROUTE 0x3e00 | ||
52 | #define HPET_TN_FSB 0x4000 | ||
53 | #define HPET_TN_FSB_CAP 0x8000 | ||
54 | #define HPET_TN_ROUTE_SHIFT 9 | ||
55 | |||
56 | /* Max HPET Period is 10^8 femto sec as in HPET spec */ | ||
57 | #define HPET_MAX_PERIOD 100000000UL | ||
58 | /* | ||
59 | * Min HPET period is 10^5 femto sec just for safety. If it is less than this, | ||
60 | * then 32 bit HPET counter wrapsaround in less than 0.5 sec. | ||
61 | */ | ||
62 | #define HPET_MIN_PERIOD 100000UL | ||
63 | |||
64 | /* hpet memory map physical address */ | ||
65 | extern unsigned long hpet_address; | ||
66 | extern unsigned long force_hpet_address; | ||
67 | extern int is_hpet_enabled(void); | ||
68 | extern int hpet_enable(void); | ||
69 | extern unsigned long hpet_readl(unsigned long a); | ||
70 | extern void force_hpet_resume(void); | ||
71 | |||
72 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
73 | |||
74 | #include <linux/interrupt.h> | ||
75 | |||
76 | extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); | ||
77 | extern int hpet_set_rtc_irq_bit(unsigned long bit_mask); | ||
78 | extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, | ||
79 | unsigned char sec); | ||
80 | extern int hpet_set_periodic_freq(unsigned long freq); | ||
81 | extern int hpet_rtc_dropped_irq(void); | ||
82 | extern int hpet_rtc_timer_init(void); | ||
83 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
84 | |||
85 | #endif /* CONFIG_HPET_EMULATE_RTC */ | ||
86 | |||
3 | #else | 87 | #else |
4 | # include "hpet_64.h" | 88 | |
5 | #endif | 89 | static inline int hpet_enable(void) { return 0; } |
90 | static inline unsigned long hpet_readl(unsigned long a) { return 0; } | ||
91 | |||
92 | #endif /* CONFIG_HPET_TIMER */ | ||
93 | #endif /* ASM_X86_HPET_H */ | ||
diff --git a/include/asm-x86/hpet_32.h b/include/asm-x86/hpet_32.h deleted file mode 100644 index c82dc7ed96b3..000000000000 --- a/include/asm-x86/hpet_32.h +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | |||
2 | #ifndef _I386_HPET_H | ||
3 | #define _I386_HPET_H | ||
4 | |||
5 | #ifdef CONFIG_HPET_TIMER | ||
6 | |||
7 | /* | ||
8 | * Documentation on HPET can be found at: | ||
9 | * http://www.intel.com/ial/home/sp/pcmmspec.htm | ||
10 | * ftp://download.intel.com/ial/home/sp/mmts098.pdf | ||
11 | */ | ||
12 | |||
13 | #define HPET_MMAP_SIZE 1024 | ||
14 | |||
15 | #define HPET_ID 0x000 | ||
16 | #define HPET_PERIOD 0x004 | ||
17 | #define HPET_CFG 0x010 | ||
18 | #define HPET_STATUS 0x020 | ||
19 | #define HPET_COUNTER 0x0f0 | ||
20 | #define HPET_T0_CFG 0x100 | ||
21 | #define HPET_T0_CMP 0x108 | ||
22 | #define HPET_T0_ROUTE 0x110 | ||
23 | #define HPET_T1_CFG 0x120 | ||
24 | #define HPET_T1_CMP 0x128 | ||
25 | #define HPET_T1_ROUTE 0x130 | ||
26 | #define HPET_T2_CFG 0x140 | ||
27 | #define HPET_T2_CMP 0x148 | ||
28 | #define HPET_T2_ROUTE 0x150 | ||
29 | |||
30 | #define HPET_ID_REV 0x000000ff | ||
31 | #define HPET_ID_NUMBER 0x00001f00 | ||
32 | #define HPET_ID_64BIT 0x00002000 | ||
33 | #define HPET_ID_LEGSUP 0x00008000 | ||
34 | #define HPET_ID_VENDOR 0xffff0000 | ||
35 | #define HPET_ID_NUMBER_SHIFT 8 | ||
36 | #define HPET_ID_VENDOR_SHIFT 16 | ||
37 | |||
38 | #define HPET_ID_VENDOR_8086 0x8086 | ||
39 | |||
40 | #define HPET_CFG_ENABLE 0x001 | ||
41 | #define HPET_CFG_LEGACY 0x002 | ||
42 | #define HPET_LEGACY_8254 2 | ||
43 | #define HPET_LEGACY_RTC 8 | ||
44 | |||
45 | #define HPET_TN_LEVEL 0x0002 | ||
46 | #define HPET_TN_ENABLE 0x0004 | ||
47 | #define HPET_TN_PERIODIC 0x0008 | ||
48 | #define HPET_TN_PERIODIC_CAP 0x0010 | ||
49 | #define HPET_TN_64BIT_CAP 0x0020 | ||
50 | #define HPET_TN_SETVAL 0x0040 | ||
51 | #define HPET_TN_32BIT 0x0100 | ||
52 | #define HPET_TN_ROUTE 0x3e00 | ||
53 | #define HPET_TN_FSB 0x4000 | ||
54 | #define HPET_TN_FSB_CAP 0x8000 | ||
55 | #define HPET_TN_ROUTE_SHIFT 9 | ||
56 | |||
57 | /* Max HPET Period is 10^8 femto sec as in HPET spec */ | ||
58 | #define HPET_MAX_PERIOD 100000000UL | ||
59 | /* | ||
60 | * Min HPET period is 10^5 femto sec just for safety. If it is less than this, | ||
61 | * then 32 bit HPET counter wrapsaround in less than 0.5 sec. | ||
62 | */ | ||
63 | #define HPET_MIN_PERIOD 100000UL | ||
64 | |||
65 | /* hpet memory map physical address */ | ||
66 | extern unsigned long hpet_address; | ||
67 | extern int is_hpet_enabled(void); | ||
68 | extern int hpet_enable(void); | ||
69 | |||
70 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
71 | |||
72 | #include <linux/interrupt.h> | ||
73 | |||
74 | extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); | ||
75 | extern int hpet_set_rtc_irq_bit(unsigned long bit_mask); | ||
76 | extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, | ||
77 | unsigned char sec); | ||
78 | extern int hpet_set_periodic_freq(unsigned long freq); | ||
79 | extern int hpet_rtc_dropped_irq(void); | ||
80 | extern int hpet_rtc_timer_init(void); | ||
81 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
82 | |||
83 | #endif /* CONFIG_HPET_EMULATE_RTC */ | ||
84 | |||
85 | #else | ||
86 | |||
87 | static inline int hpet_enable(void) { return 0; } | ||
88 | |||
89 | #endif /* CONFIG_HPET_TIMER */ | ||
90 | #endif /* _I386_HPET_H */ | ||
diff --git a/include/asm-x86/hpet_64.h b/include/asm-x86/hpet_64.h deleted file mode 100644 index fd4decac93a8..000000000000 --- a/include/asm-x86/hpet_64.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | #ifndef _ASM_X8664_HPET_H | ||
2 | #define _ASM_X8664_HPET_H 1 | ||
3 | |||
4 | #include <asm/hpet_32.h> | ||
5 | |||
6 | #define HPET_TICK_RATE (HZ * 100000UL) | ||
7 | |||
8 | extern int hpet_rtc_timer_init(void); | ||
9 | extern int hpet_arch_init(void); | ||
10 | extern int hpet_timer_stop_set_go(unsigned long tick); | ||
11 | extern int hpet_reenable(void); | ||
12 | extern unsigned int hpet_calibrate_tsc(void); | ||
13 | |||
14 | extern int hpet_use_timer; | ||
15 | extern unsigned long hpet_period; | ||
16 | extern unsigned long hpet_tick; | ||
17 | |||
18 | #endif | ||
diff --git a/include/asm-x86/i8253.h b/include/asm-x86/i8253.h index b2a4f995a33f..747548ec5d1d 100644 --- a/include/asm-x86/i8253.h +++ b/include/asm-x86/i8253.h | |||
@@ -1,5 +1,15 @@ | |||
1 | #ifdef CONFIG_X86_32 | 1 | #ifndef __ASM_I8253_H__ |
2 | # include "i8253_32.h" | 2 | #define __ASM_I8253_H__ |
3 | #else | 3 | |
4 | # include "i8253_64.h" | 4 | /* i8253A PIT registers */ |
5 | #endif | 5 | #define PIT_MODE 0x43 |
6 | #define PIT_CH0 0x40 | ||
7 | #define PIT_CH2 0x42 | ||
8 | |||
9 | extern spinlock_t i8253_lock; | ||
10 | |||
11 | extern struct clock_event_device *global_clock_event; | ||
12 | |||
13 | extern void setup_pit_timer(void); | ||
14 | |||
15 | #endif /* __ASM_I8253_H__ */ | ||
diff --git a/include/asm-x86/i8253_32.h b/include/asm-x86/i8253_32.h deleted file mode 100644 index 7577d058d86e..000000000000 --- a/include/asm-x86/i8253_32.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #ifndef __ASM_I8253_H__ | ||
2 | #define __ASM_I8253_H__ | ||
3 | |||
4 | #include <linux/clockchips.h> | ||
5 | |||
6 | /* i8253A PIT registers */ | ||
7 | #define PIT_MODE 0x43 | ||
8 | #define PIT_CH0 0x40 | ||
9 | #define PIT_CH2 0x42 | ||
10 | |||
11 | extern spinlock_t i8253_lock; | ||
12 | |||
13 | extern struct clock_event_device *global_clock_event; | ||
14 | |||
15 | extern void setup_pit_timer(void); | ||
16 | |||
17 | #endif /* __ASM_I8253_H__ */ | ||
diff --git a/include/asm-x86/i8253_64.h b/include/asm-x86/i8253_64.h deleted file mode 100644 index 015d8df07690..000000000000 --- a/include/asm-x86/i8253_64.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __ASM_I8253_H__ | ||
2 | #define __ASM_I8253_H__ | ||
3 | |||
4 | extern spinlock_t i8253_lock; | ||
5 | |||
6 | #endif /* __ASM_I8253_H__ */ | ||
diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h index 5642634843c4..fb49f80eb94f 100644 --- a/include/asm-x86/pda.h +++ b/include/asm-x86/pda.h | |||
@@ -29,6 +29,7 @@ struct x8664_pda { | |||
29 | short isidle; | 29 | short isidle; |
30 | struct mm_struct *active_mm; | 30 | struct mm_struct *active_mm; |
31 | unsigned apic_timer_irqs; | 31 | unsigned apic_timer_irqs; |
32 | unsigned irq0_irqs; | ||
32 | } ____cacheline_aligned_in_smp; | 33 | } ____cacheline_aligned_in_smp; |
33 | 34 | ||
34 | extern struct x8664_pda *_cpu_pda[]; | 35 | extern struct x8664_pda *_cpu_pda[]; |
diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h index 31f20ad65876..c44a3a93b5a4 100644 --- a/include/asm-x86/proto.h +++ b/include/asm-x86/proto.h | |||
@@ -51,9 +51,6 @@ extern void reserve_bootmem_generic(unsigned long phys, unsigned len); | |||
51 | 51 | ||
52 | extern void load_gs_index(unsigned gs); | 52 | extern void load_gs_index(unsigned gs); |
53 | 53 | ||
54 | extern void stop_timer_interrupt(void); | ||
55 | extern void main_timer_handler(void); | ||
56 | |||
57 | extern unsigned long end_pfn_map; | 54 | extern unsigned long end_pfn_map; |
58 | 55 | ||
59 | extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long * rsp); | 56 | extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long * rsp); |
@@ -90,14 +87,10 @@ extern int timer_over_8254; | |||
90 | 87 | ||
91 | extern int gsi_irq_sharing(int gsi); | 88 | extern int gsi_irq_sharing(int gsi); |
92 | 89 | ||
93 | extern void smp_local_timer_interrupt(void); | ||
94 | |||
95 | extern int force_mwait; | 90 | extern int force_mwait; |
96 | 91 | ||
97 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); | 92 | long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); |
98 | 93 | ||
99 | void i8254_timer_resume(void); | ||
100 | |||
101 | #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) | 94 | #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) |
102 | #define round_down(x,y) ((x) & ~((y)-1)) | 95 | #define round_down(x,y) ((x) & ~((y)-1)) |
103 | 96 | ||
diff --git a/include/asm-x86/timex.h b/include/asm-x86/timex.h index d01c18cfccef..39a21ab030f0 100644 --- a/include/asm-x86/timex.h +++ b/include/asm-x86/timex.h | |||
@@ -1,5 +1,18 @@ | |||
1 | #ifdef CONFIG_X86_32 | 1 | /* x86 architecture timex specifications */ |
2 | # include "timex_32.h" | 2 | #ifndef _ASM_X86_TIMEX_H |
3 | #define _ASM_X86_TIMEX_H | ||
4 | |||
5 | #include <asm/processor.h> | ||
6 | #include <asm/tsc.h> | ||
7 | |||
8 | #ifdef CONFIG_X86_ELAN | ||
9 | # define PIT_TICK_RATE 1189200 /* AMD Elan has different frequency! */ | ||
3 | #else | 10 | #else |
4 | # include "timex_64.h" | 11 | # define PIT_TICK_RATE 1193182 /* Underlying HZ */ |
12 | #endif | ||
13 | #define CLOCK_TICK_RATE PIT_TICK_RATE | ||
14 | |||
15 | extern int read_current_timer(unsigned long *timer_value); | ||
16 | #define ARCH_HAS_READ_CURRENT_TIMER 1 | ||
17 | |||
5 | #endif | 18 | #endif |
diff --git a/include/asm-x86/timex_32.h b/include/asm-x86/timex_32.h deleted file mode 100644 index 3666044409f0..000000000000 --- a/include/asm-x86/timex_32.h +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * linux/include/asm-i386/timex.h | ||
3 | * | ||
4 | * i386 architecture timex specifications | ||
5 | */ | ||
6 | #ifndef _ASMi386_TIMEX_H | ||
7 | #define _ASMi386_TIMEX_H | ||
8 | |||
9 | #include <asm/processor.h> | ||
10 | #include <asm/tsc.h> | ||
11 | |||
12 | #ifdef CONFIG_X86_ELAN | ||
13 | # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ | ||
14 | #else | ||
15 | # define CLOCK_TICK_RATE 1193182 /* Underlying HZ */ | ||
16 | #endif | ||
17 | |||
18 | |||
19 | extern int read_current_timer(unsigned long *timer_value); | ||
20 | #define ARCH_HAS_READ_CURRENT_TIMER 1 | ||
21 | |||
22 | #endif | ||
diff --git a/include/asm-x86/timex_64.h b/include/asm-x86/timex_64.h deleted file mode 100644 index 6ed21f44d308..000000000000 --- a/include/asm-x86/timex_64.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * linux/include/asm-x86_64/timex.h | ||
3 | * | ||
4 | * x86-64 architecture timex specifications | ||
5 | */ | ||
6 | #ifndef _ASMx8664_TIMEX_H | ||
7 | #define _ASMx8664_TIMEX_H | ||
8 | |||
9 | #include <asm/8253pit.h> | ||
10 | #include <asm/msr.h> | ||
11 | #include <asm/vsyscall.h> | ||
12 | #include <asm/system.h> | ||
13 | #include <asm/processor.h> | ||
14 | #include <asm/tsc.h> | ||
15 | #include <linux/compiler.h> | ||
16 | |||
17 | #define CLOCK_TICK_RATE PIT_TICK_RATE /* Underlying HZ */ | ||
18 | |||
19 | extern int read_current_timer(unsigned long *timer_value); | ||
20 | #define ARCH_HAS_READ_CURRENT_TIMER 1 | ||
21 | |||
22 | #define USEC_PER_TICK (USEC_PER_SEC / HZ) | ||
23 | #define NSEC_PER_TICK (NSEC_PER_SEC / HZ) | ||
24 | #define FSEC_PER_TICK (FSEC_PER_SEC / HZ) | ||
25 | |||
26 | #define NS_SCALE 10 /* 2^10, carefully chosen */ | ||
27 | #define US_SCALE 32 /* 2^32, arbitralrily chosen */ | ||
28 | |||
29 | extern void mark_tsc_unstable(char *msg); | ||
30 | extern void set_cyc2ns_scale(unsigned long khz); | ||
31 | #endif | ||
diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h index a4d806610b7f..6baab30dc2c8 100644 --- a/include/asm-x86/tsc.h +++ b/include/asm-x86/tsc.h | |||
@@ -1,13 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * linux/include/asm-i386/tsc.h | 2 | * x86 TSC related functions |
3 | * | ||
4 | * i386 TSC related functions | ||
5 | */ | 3 | */ |
6 | #ifndef _ASM_i386_TSC_H | 4 | #ifndef _ASM_X86_TSC_H |
7 | #define _ASM_i386_TSC_H | 5 | #define _ASM_X86_TSC_H |
8 | 6 | ||
9 | #include <asm/processor.h> | 7 | #include <asm/processor.h> |
10 | 8 | ||
9 | #define NS_SCALE 10 /* 2^10, carefully chosen */ | ||
10 | #define US_SCALE 32 /* 2^32, arbitralrily chosen */ | ||
11 | |||
11 | /* | 12 | /* |
12 | * Standard way to access the cycle counter. | 13 | * Standard way to access the cycle counter. |
13 | */ | 14 | */ |
@@ -72,4 +73,8 @@ int check_tsc_unstable(void); | |||
72 | extern void check_tsc_sync_source(int cpu); | 73 | extern void check_tsc_sync_source(int cpu); |
73 | extern void check_tsc_sync_target(void); | 74 | extern void check_tsc_sync_target(void); |
74 | 75 | ||
76 | #ifdef CONFIG_X86_64 | ||
77 | extern void tsc_calibrate(void); | ||
78 | #endif | ||
79 | |||
75 | #endif | 80 | #endif |
diff --git a/include/asm-x86/vsyscall.h b/include/asm-x86/vsyscall.h index 3b8ceb4af2cf..f01c49f5d108 100644 --- a/include/asm-x86/vsyscall.h +++ b/include/asm-x86/vsyscall.h | |||
@@ -29,9 +29,6 @@ enum vsyscall_num { | |||
29 | #define VGETCPU_RDTSCP 1 | 29 | #define VGETCPU_RDTSCP 1 |
30 | #define VGETCPU_LSL 2 | 30 | #define VGETCPU_LSL 2 |
31 | 31 | ||
32 | #define hpet_readl(a) readl((const void __iomem *)fix_to_virt(FIX_HPET_BASE) + a) | ||
33 | #define hpet_writel(d,a) writel(d, (void __iomem *)fix_to_virt(FIX_HPET_BASE) + a) | ||
34 | |||
35 | extern int __vgetcpu_mode; | 32 | extern int __vgetcpu_mode; |
36 | extern volatile unsigned long __jiffies; | 33 | extern volatile unsigned long __jiffies; |
37 | 34 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 95be0ac57e76..5ed888b04b29 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -20,20 +20,6 @@ | |||
20 | 20 | ||
21 | #include <asm/scatterlist.h> | 21 | #include <asm/scatterlist.h> |
22 | 22 | ||
23 | #ifdef CONFIG_LBD | ||
24 | # include <asm/div64.h> | ||
25 | # define sector_div(a, b) do_div(a, b) | ||
26 | #else | ||
27 | # define sector_div(n, b)( \ | ||
28 | { \ | ||
29 | int _res; \ | ||
30 | _res = (n) % (b); \ | ||
31 | (n) /= (b); \ | ||
32 | _res; \ | ||
33 | } \ | ||
34 | ) | ||
35 | #endif | ||
36 | |||
37 | struct scsi_ioctl_command; | 23 | struct scsi_ioctl_command; |
38 | 24 | ||
39 | struct request_queue; | 25 | struct request_queue; |
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 2e105a12fe29..7e11d23ac36a 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h | |||
@@ -290,12 +290,7 @@ static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio, | |||
290 | #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) | 290 | #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) |
291 | #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) | 291 | #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) |
292 | #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) | 292 | #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) |
293 | static inline int do_blk_trace_setup(struct request_queue *q, | 293 | #define do_blk_trace_setup(q, bdev, buts) (-ENOTTY) |
294 | struct block_device *bdev, | ||
295 | struct blk_user_trace_setup *buts) | ||
296 | { | ||
297 | return 0; | ||
298 | } | ||
299 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ | 294 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ |
300 | #endif /* __KERNEL__ */ | 295 | #endif /* __KERNEL__ */ |
301 | #endif | 296 | #endif |
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index def5a659b8a5..d2ddea926895 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #ifndef _LINUX_CLOCKCHIPS_H | 8 | #ifndef _LINUX_CLOCKCHIPS_H |
9 | #define _LINUX_CLOCKCHIPS_H | 9 | #define _LINUX_CLOCKCHIPS_H |
10 | 10 | ||
11 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | 11 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD |
12 | 12 | ||
13 | #include <linux/clocksource.h> | 13 | #include <linux/clocksource.h> |
14 | #include <linux/cpumask.h> | 14 | #include <linux/cpumask.h> |
@@ -126,11 +126,14 @@ extern int clockevents_register_notifier(struct notifier_block *nb); | |||
126 | extern int clockevents_program_event(struct clock_event_device *dev, | 126 | extern int clockevents_program_event(struct clock_event_device *dev, |
127 | ktime_t expires, ktime_t now); | 127 | ktime_t expires, ktime_t now); |
128 | 128 | ||
129 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
129 | extern void clockevents_notify(unsigned long reason, void *arg); | 130 | extern void clockevents_notify(unsigned long reason, void *arg); |
130 | |||
131 | #else | 131 | #else |
132 | # define clockevents_notify(reason, arg) do { } while (0) | ||
133 | #endif | ||
134 | |||
135 | #else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */ | ||
132 | 136 | ||
133 | static inline void clockevents_resume_events(void) { } | ||
134 | #define clockevents_notify(reason, arg) do { } while (0) | 137 | #define clockevents_notify(reason, arg) do { } while (0) |
135 | 138 | ||
136 | #endif | 139 | #endif |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 3ec6e7ff5fbd..23932d7741a9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -32,12 +32,24 @@ | |||
32 | * CPUFREQ NOTIFIER INTERFACE * | 32 | * CPUFREQ NOTIFIER INTERFACE * |
33 | *********************************************************************/ | 33 | *********************************************************************/ |
34 | 34 | ||
35 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); | ||
36 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); | ||
37 | |||
38 | #define CPUFREQ_TRANSITION_NOTIFIER (0) | 35 | #define CPUFREQ_TRANSITION_NOTIFIER (0) |
39 | #define CPUFREQ_POLICY_NOTIFIER (1) | 36 | #define CPUFREQ_POLICY_NOTIFIER (1) |
40 | 37 | ||
38 | #ifdef CONFIG_CPU_FREQ | ||
39 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); | ||
40 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); | ||
41 | #else /* CONFIG_CPU_FREQ */ | ||
42 | static inline int cpufreq_register_notifier(struct notifier_block *nb, | ||
43 | unsigned int list) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | static inline int cpufreq_unregister_notifier(struct notifier_block *nb, | ||
48 | unsigned int list) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | #endif /* CONFIG_CPU_FREQ */ | ||
41 | 53 | ||
42 | /* if (cpufreq_driver->target) exists, the ->governor decides what frequency | 54 | /* if (cpufreq_driver->target) exists, the ->governor decides what frequency |
43 | * within the limits is used. If (cpufreq_driver->setpolicy> exists, these | 55 | * within the limits is used. If (cpufreq_driver->setpolicy> exists, these |
@@ -155,6 +167,9 @@ struct cpufreq_governor { | |||
155 | char name[CPUFREQ_NAME_LEN]; | 167 | char name[CPUFREQ_NAME_LEN]; |
156 | int (*governor) (struct cpufreq_policy *policy, | 168 | int (*governor) (struct cpufreq_policy *policy, |
157 | unsigned int event); | 169 | unsigned int event); |
170 | unsigned int max_transition_latency; /* HW must be able to switch to | ||
171 | next freq faster than this value in nano secs or we | ||
172 | will fallback to performance governor */ | ||
158 | struct list_head governor_list; | 173 | struct list_head governor_list; |
159 | struct module *owner; | 174 | struct module *owner; |
160 | }; | 175 | }; |
@@ -279,12 +294,24 @@ static inline unsigned int cpufreq_quick_get(unsigned int cpu) | |||
279 | *********************************************************************/ | 294 | *********************************************************************/ |
280 | 295 | ||
281 | 296 | ||
282 | #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE | 297 | /* |
298 | Performance governor is fallback governor if any other gov failed to | ||
299 | auto load due latency restrictions | ||
300 | */ | ||
301 | #ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE | ||
283 | extern struct cpufreq_governor cpufreq_gov_performance; | 302 | extern struct cpufreq_governor cpufreq_gov_performance; |
284 | #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance | 303 | #endif |
304 | #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE | ||
305 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance) | ||
285 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) | 306 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) |
286 | extern struct cpufreq_governor cpufreq_gov_userspace; | 307 | extern struct cpufreq_governor cpufreq_gov_userspace; |
287 | #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace | 308 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace) |
309 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) | ||
310 | extern struct cpufreq_governor cpufreq_gov_ondemand; | ||
311 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand) | ||
312 | #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) | ||
313 | extern struct cpufreq_governor cpufreq_gov_conservative; | ||
314 | #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) | ||
288 | #endif | 315 | #endif |
289 | 316 | ||
290 | 317 | ||
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index a44a6a078f0a..c3c19f926e6f 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h | |||
@@ -170,6 +170,33 @@ struct gfs2_rgrp { | |||
170 | }; | 170 | }; |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * quota linked list: user quotas and group quotas form two separate | ||
174 | * singly linked lists. ll_next stores uids or gids of next quotas in the | ||
175 | * linked list. | ||
176 | |||
177 | Given the uid/gid, how to calculate the quota file offsets for the corresponding | ||
178 | gfs2_quota structures on disk: | ||
179 | |||
180 | for user quotas, given uid, | ||
181 | offset = uid * sizeof(struct gfs2_quota); | ||
182 | |||
183 | for group quotas, given gid, | ||
184 | offset = (gid * sizeof(struct gfs2_quota)) + sizeof(struct gfs2_quota); | ||
185 | |||
186 | |||
187 | uid:0 gid:0 uid:12 gid:12 uid:17 gid:17 uid:5142 gid:5142 | ||
188 | +-------+-------+ +-------+-------+ +-------+- - - -+ +- - - -+-------+ | ||
189 | | valid | valid | :: | valid | valid | :: | valid | inval | :: | inval | valid | | ||
190 | +-------+-------+ +-------+-------+ +-------+- - - -+ +- - - -+-------+ | ||
191 | next:12 next:12 next:17 next:5142 next:NULL next:NULL | ||
192 | | | | | |<-- user quota list | | ||
193 | \______|___________/ \______|___________/ group quota list -->| | ||
194 | | | | | ||
195 | \__________________/ \_______________________________________/ | ||
196 | |||
197 | */ | ||
198 | |||
199 | /* | ||
173 | * quota structure | 200 | * quota structure |
174 | */ | 201 | */ |
175 | 202 | ||
@@ -177,7 +204,8 @@ struct gfs2_quota { | |||
177 | __be64 qu_limit; | 204 | __be64 qu_limit; |
178 | __be64 qu_warn; | 205 | __be64 qu_warn; |
179 | __be64 qu_value; | 206 | __be64 qu_value; |
180 | __u8 qu_reserved[64]; | 207 | __be32 qu_ll_next; /* location of next quota in list */ |
208 | __u8 qu_reserved[60]; | ||
181 | }; | 209 | }; |
182 | 210 | ||
183 | /* | 211 | /* |
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index c080f61fb024..d7a5e034c3a2 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
@@ -36,8 +36,6 @@ | |||
36 | /* LATCH is used in the interval timer and ftape setup. */ | 36 | /* LATCH is used in the interval timer and ftape setup. */ |
37 | #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ | 37 | #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ |
38 | 38 | ||
39 | #define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ) | ||
40 | |||
41 | /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can | 39 | /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can |
42 | * improve accuracy by shifting LSH bits, hence calculating: | 40 | * improve accuracy by shifting LSH bits, hence calculating: |
43 | * (NOM << LSH) / DEN | 41 | * (NOM << LSH) / DEN |
@@ -53,13 +51,9 @@ | |||
53 | /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ | 51 | /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ |
54 | #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) | 52 | #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) |
55 | 53 | ||
56 | #define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8)) | ||
57 | |||
58 | /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ | 54 | /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ |
59 | #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) | 55 | #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) |
60 | 56 | ||
61 | #define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8)) | ||
62 | |||
63 | /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ | 57 | /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ |
64 | #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) | 58 | #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) |
65 | 59 | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 47160fe378c9..d9725a28a265 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -42,6 +42,20 @@ extern const char linux_proc_banner[]; | |||
42 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) | 42 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) |
43 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) | 43 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) |
44 | 44 | ||
45 | #ifdef CONFIG_LBD | ||
46 | # include <asm/div64.h> | ||
47 | # define sector_div(a, b) do_div(a, b) | ||
48 | #else | ||
49 | # define sector_div(n, b)( \ | ||
50 | { \ | ||
51 | int _res; \ | ||
52 | _res = (n) % (b); \ | ||
53 | (n) /= (b); \ | ||
54 | _res; \ | ||
55 | } \ | ||
56 | ) | ||
57 | #endif | ||
58 | |||
45 | /** | 59 | /** |
46 | * upper_32_bits - return bits 32-63 of a number | 60 | * upper_32_bits - return bits 32-63 of a number |
47 | * @n: the number we're accessing | 61 | * @n: the number we're accessing |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3948708c42ca..584741bb73b3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2242,6 +2242,7 @@ | |||
2242 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 | 2242 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 |
2243 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 | 2243 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 |
2244 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db | 2244 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db |
2245 | #define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc | ||
2245 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd | 2246 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd |
2246 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 | 2247 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 |
2247 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 | 2248 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 4f33a58fa9d1..c5c8f169d3cf 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -52,6 +52,7 @@ struct ep_device; | |||
52 | * @ep_dev: ep_device for sysfs info | 52 | * @ep_dev: ep_device for sysfs info |
53 | * @extra: descriptors following this endpoint in the configuration | 53 | * @extra: descriptors following this endpoint in the configuration |
54 | * @extralen: how many bytes of "extra" are valid | 54 | * @extralen: how many bytes of "extra" are valid |
55 | * @enabled: URBs may be submitted to this endpoint | ||
55 | * | 56 | * |
56 | * USB requests are always queued to a given endpoint, identified by a | 57 | * USB requests are always queued to a given endpoint, identified by a |
57 | * descriptor within an active interface in a given USB configuration. | 58 | * descriptor within an active interface in a given USB configuration. |
@@ -64,6 +65,7 @@ struct usb_host_endpoint { | |||
64 | 65 | ||
65 | unsigned char *extra; /* Extra descriptors */ | 66 | unsigned char *extra; /* Extra descriptors */ |
66 | int extralen; | 67 | int extralen; |
68 | int enabled; | ||
67 | }; | 69 | }; |
68 | 70 | ||
69 | /* host-side wrapper for one interface setting's parsed descriptors */ | 71 | /* host-side wrapper for one interface setting's parsed descriptors */ |
@@ -344,6 +346,11 @@ struct usb_tt; | |||
344 | * | 346 | * |
345 | * Usbcore drivers should not set usbdev->state directly. Instead use | 347 | * Usbcore drivers should not set usbdev->state directly. Instead use |
346 | * usb_set_device_state(). | 348 | * usb_set_device_state(). |
349 | * | ||
350 | * @authorized: (user space) policy determines if we authorize this | ||
351 | * device to be used or not. By default, wired USB | ||
352 | * devices are authorized. WUSB devices are not, until we | ||
353 | * authorize them from user space. FIXME -- complete doc | ||
347 | */ | 354 | */ |
348 | struct usb_device { | 355 | struct usb_device { |
349 | int devnum; /* Address on USB bus */ | 356 | int devnum; /* Address on USB bus */ |
@@ -376,8 +383,11 @@ struct usb_device { | |||
376 | u8 portnum; /* Parent port number (origin 1) */ | 383 | u8 portnum; /* Parent port number (origin 1) */ |
377 | u8 level; /* Number of USB hub ancestors */ | 384 | u8 level; /* Number of USB hub ancestors */ |
378 | 385 | ||
386 | unsigned can_submit:1; /* URBs may be submitted */ | ||
379 | unsigned discon_suspended:1; /* Disconnected while suspended */ | 387 | unsigned discon_suspended:1; /* Disconnected while suspended */ |
380 | unsigned have_langid:1; /* whether string_langid is valid */ | 388 | unsigned have_langid:1; /* whether string_langid is valid */ |
389 | unsigned authorized:1; /* Policy has determined we can use it */ | ||
390 | unsigned wusb:1; /* Device is Wireless USB */ | ||
381 | int string_langid; /* language ID for strings */ | 391 | int string_langid; /* language ID for strings */ |
382 | 392 | ||
383 | /* static strings from the device */ | 393 | /* static strings from the device */ |
@@ -405,6 +415,7 @@ struct usb_device { | |||
405 | 415 | ||
406 | int pm_usage_cnt; /* usage counter for autosuspend */ | 416 | int pm_usage_cnt; /* usage counter for autosuspend */ |
407 | u32 quirks; /* quirks of the whole device */ | 417 | u32 quirks; /* quirks of the whole device */ |
418 | atomic_t urbnum; /* number of URBs submitted for the whole device */ | ||
408 | 419 | ||
409 | #ifdef CONFIG_PM | 420 | #ifdef CONFIG_PM |
410 | struct delayed_work autosuspend; /* for delayed autosuspends */ | 421 | struct delayed_work autosuspend; /* for delayed autosuspends */ |
@@ -419,6 +430,7 @@ struct usb_device { | |||
419 | unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */ | 430 | unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */ |
420 | unsigned autosuspend_disabled:1; /* autosuspend and autoresume */ | 431 | unsigned autosuspend_disabled:1; /* autosuspend and autoresume */ |
421 | unsigned autoresume_disabled:1; /* disabled by the user */ | 432 | unsigned autoresume_disabled:1; /* disabled by the user */ |
433 | unsigned skip_sys_resume:1; /* skip the next system resume */ | ||
422 | #endif | 434 | #endif |
423 | }; | 435 | }; |
424 | #define to_usb_device(d) container_of(d, struct usb_device, dev) | 436 | #define to_usb_device(d) container_of(d, struct usb_device, dev) |
@@ -555,6 +567,29 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, | |||
555 | /*-------------------------------------------------------------------------*/ | 567 | /*-------------------------------------------------------------------------*/ |
556 | 568 | ||
557 | /** | 569 | /** |
570 | * usb_endpoint_num - get the endpoint's number | ||
571 | * @epd: endpoint to be checked | ||
572 | * | ||
573 | * Returns @epd's number: 0 to 15. | ||
574 | */ | ||
575 | static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) | ||
576 | { | ||
577 | return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * usb_endpoint_type - get the endpoint's transfer type | ||
582 | * @epd: endpoint to be checked | ||
583 | * | ||
584 | * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according | ||
585 | * to @epd's transfer type. | ||
586 | */ | ||
587 | static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) | ||
588 | { | ||
589 | return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
590 | } | ||
591 | |||
592 | /** | ||
558 | * usb_endpoint_dir_in - check if the endpoint has IN direction | 593 | * usb_endpoint_dir_in - check if the endpoint has IN direction |
559 | * @epd: endpoint to be checked | 594 | * @epd: endpoint to be checked |
560 | * | 595 | * |
@@ -996,6 +1031,8 @@ extern int usb_disabled(void); | |||
996 | 1031 | ||
997 | /* | 1032 | /* |
998 | * urb->transfer_flags: | 1033 | * urb->transfer_flags: |
1034 | * | ||
1035 | * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb(). | ||
999 | */ | 1036 | */ |
1000 | #define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ | 1037 | #define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ |
1001 | #define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame | 1038 | #define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame |
@@ -1008,6 +1045,10 @@ extern int usb_disabled(void); | |||
1008 | * needed */ | 1045 | * needed */ |
1009 | #define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */ | 1046 | #define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */ |
1010 | 1047 | ||
1048 | #define URB_DIR_IN 0x0200 /* Transfer from device to host */ | ||
1049 | #define URB_DIR_OUT 0 | ||
1050 | #define URB_DIR_MASK URB_DIR_IN | ||
1051 | |||
1011 | struct usb_iso_packet_descriptor { | 1052 | struct usb_iso_packet_descriptor { |
1012 | unsigned int offset; | 1053 | unsigned int offset; |
1013 | unsigned int length; /* expected length */ | 1054 | unsigned int length; /* expected length */ |
@@ -1037,6 +1078,8 @@ typedef void (*usb_complete_t)(struct urb *); | |||
1037 | * @urb_list: For use by current owner of the URB. | 1078 | * @urb_list: For use by current owner of the URB. |
1038 | * @anchor_list: membership in the list of an anchor | 1079 | * @anchor_list: membership in the list of an anchor |
1039 | * @anchor: to anchor URBs to a common mooring | 1080 | * @anchor: to anchor URBs to a common mooring |
1081 | * @ep: Points to the endpoint's data structure. Will eventually | ||
1082 | * replace @pipe. | ||
1040 | * @pipe: Holds endpoint number, direction, type, and more. | 1083 | * @pipe: Holds endpoint number, direction, type, and more. |
1041 | * Create these values with the eight macros available; | 1084 | * Create these values with the eight macros available; |
1042 | * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl" | 1085 | * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl" |
@@ -1201,10 +1244,10 @@ struct urb | |||
1201 | { | 1244 | { |
1202 | /* private: usb core and host controller only fields in the urb */ | 1245 | /* private: usb core and host controller only fields in the urb */ |
1203 | struct kref kref; /* reference count of the URB */ | 1246 | struct kref kref; /* reference count of the URB */ |
1204 | spinlock_t lock; /* lock for the URB */ | ||
1205 | void *hcpriv; /* private data for host controller */ | 1247 | void *hcpriv; /* private data for host controller */ |
1206 | atomic_t use_count; /* concurrent submissions counter */ | 1248 | atomic_t use_count; /* concurrent submissions counter */ |
1207 | u8 reject; /* submissions will fail */ | 1249 | u8 reject; /* submissions will fail */ |
1250 | int unlinked; /* unlink error code */ | ||
1208 | 1251 | ||
1209 | /* public: documented fields in the urb that can be used by drivers */ | 1252 | /* public: documented fields in the urb that can be used by drivers */ |
1210 | struct list_head urb_list; /* list head for use by the urb's | 1253 | struct list_head urb_list; /* list head for use by the urb's |
@@ -1212,6 +1255,7 @@ struct urb | |||
1212 | struct list_head anchor_list; /* the URB may be anchored by the driver */ | 1255 | struct list_head anchor_list; /* the URB may be anchored by the driver */ |
1213 | struct usb_anchor *anchor; | 1256 | struct usb_anchor *anchor; |
1214 | struct usb_device *dev; /* (in) pointer to associated device */ | 1257 | struct usb_device *dev; /* (in) pointer to associated device */ |
1258 | struct usb_host_endpoint *ep; /* (internal) pointer to endpoint struct */ | ||
1215 | unsigned int pipe; /* (in) pipe information */ | 1259 | unsigned int pipe; /* (in) pipe information */ |
1216 | int status; /* (return) non-ISO status */ | 1260 | int status; /* (return) non-ISO status */ |
1217 | unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ | 1261 | unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ |
@@ -1257,7 +1301,6 @@ static inline void usb_fill_control_urb (struct urb *urb, | |||
1257 | usb_complete_t complete_fn, | 1301 | usb_complete_t complete_fn, |
1258 | void *context) | 1302 | void *context) |
1259 | { | 1303 | { |
1260 | spin_lock_init(&urb->lock); | ||
1261 | urb->dev = dev; | 1304 | urb->dev = dev; |
1262 | urb->pipe = pipe; | 1305 | urb->pipe = pipe; |
1263 | urb->setup_packet = setup_packet; | 1306 | urb->setup_packet = setup_packet; |
@@ -1288,7 +1331,6 @@ static inline void usb_fill_bulk_urb (struct urb *urb, | |||
1288 | usb_complete_t complete_fn, | 1331 | usb_complete_t complete_fn, |
1289 | void *context) | 1332 | void *context) |
1290 | { | 1333 | { |
1291 | spin_lock_init(&urb->lock); | ||
1292 | urb->dev = dev; | 1334 | urb->dev = dev; |
1293 | urb->pipe = pipe; | 1335 | urb->pipe = pipe; |
1294 | urb->transfer_buffer = transfer_buffer; | 1336 | urb->transfer_buffer = transfer_buffer; |
@@ -1324,7 +1366,6 @@ static inline void usb_fill_int_urb (struct urb *urb, | |||
1324 | void *context, | 1366 | void *context, |
1325 | int interval) | 1367 | int interval) |
1326 | { | 1368 | { |
1327 | spin_lock_init(&urb->lock); | ||
1328 | urb->dev = dev; | 1369 | urb->dev = dev; |
1329 | urb->pipe = pipe; | 1370 | urb->pipe = pipe; |
1330 | urb->transfer_buffer = transfer_buffer; | 1371 | urb->transfer_buffer = transfer_buffer; |
@@ -1352,6 +1393,30 @@ extern void usb_unanchor_urb(struct urb *urb); | |||
1352 | extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, | 1393 | extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, |
1353 | unsigned int timeout); | 1394 | unsigned int timeout); |
1354 | 1395 | ||
1396 | /** | ||
1397 | * usb_urb_dir_in - check if an URB describes an IN transfer | ||
1398 | * @urb: URB to be checked | ||
1399 | * | ||
1400 | * Returns 1 if @urb describes an IN transfer (device-to-host), | ||
1401 | * otherwise 0. | ||
1402 | */ | ||
1403 | static inline int usb_urb_dir_in(struct urb *urb) | ||
1404 | { | ||
1405 | return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN; | ||
1406 | } | ||
1407 | |||
1408 | /** | ||
1409 | * usb_urb_dir_out - check if an URB describes an OUT transfer | ||
1410 | * @urb: URB to be checked | ||
1411 | * | ||
1412 | * Returns 1 if @urb describes an OUT transfer (host-to-device), | ||
1413 | * otherwise 0. | ||
1414 | */ | ||
1415 | static inline int usb_urb_dir_out(struct urb *urb) | ||
1416 | { | ||
1417 | return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT; | ||
1418 | } | ||
1419 | |||
1355 | void *usb_buffer_alloc (struct usb_device *dev, size_t size, | 1420 | void *usb_buffer_alloc (struct usb_device *dev, size_t size, |
1356 | gfp_t mem_flags, dma_addr_t *dma); | 1421 | gfp_t mem_flags, dma_addr_t *dma); |
1357 | void usb_buffer_free (struct usb_device *dev, size_t size, | 1422 | void usb_buffer_free (struct usb_device *dev, size_t size, |
@@ -1364,13 +1429,13 @@ void usb_buffer_unmap (struct urb *urb); | |||
1364 | #endif | 1429 | #endif |
1365 | 1430 | ||
1366 | struct scatterlist; | 1431 | struct scatterlist; |
1367 | int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, | 1432 | int usb_buffer_map_sg(const struct usb_device *dev, int is_in, |
1368 | struct scatterlist *sg, int nents); | 1433 | struct scatterlist *sg, int nents); |
1369 | #if 0 | 1434 | #if 0 |
1370 | void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, | 1435 | void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in, |
1371 | struct scatterlist *sg, int n_hw_ents); | 1436 | struct scatterlist *sg, int n_hw_ents); |
1372 | #endif | 1437 | #endif |
1373 | void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, | 1438 | void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in, |
1374 | struct scatterlist *sg, int n_hw_ents); | 1439 | struct scatterlist *sg, int n_hw_ents); |
1375 | 1440 | ||
1376 | /*-------------------------------------------------------------------* | 1441 | /*-------------------------------------------------------------------* |
diff --git a/include/linux/usb_gadget.h b/include/linux/usb/gadget.h index 4f59b2aa8a9e..46705e91573d 100644 --- a/include/linux/usb_gadget.h +++ b/include/linux/usb/gadget.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * <linux/usb_gadget.h> | 2 | * <linux/usb/gadget.h> |
3 | * | 3 | * |
4 | * We call the USB code inside a Linux-based peripheral device a "gadget" | 4 | * We call the USB code inside a Linux-based peripheral device a "gadget" |
5 | * driver, except for the hardware-specific bus glue. One USB host can | 5 | * driver, except for the hardware-specific bus glue. One USB host can |
@@ -22,10 +22,10 @@ struct usb_ep; | |||
22 | /** | 22 | /** |
23 | * struct usb_request - describes one i/o request | 23 | * struct usb_request - describes one i/o request |
24 | * @buf: Buffer used for data. Always provide this; some controllers | 24 | * @buf: Buffer used for data. Always provide this; some controllers |
25 | * only use PIO, or don't use DMA for some endpoints. | 25 | * only use PIO, or don't use DMA for some endpoints. |
26 | * @dma: DMA address corresponding to 'buf'. If you don't set this | 26 | * @dma: DMA address corresponding to 'buf'. If you don't set this |
27 | * field, and the usb controller needs one, it is responsible | 27 | * field, and the usb controller needs one, it is responsible |
28 | * for mapping and unmapping the buffer. | 28 | * for mapping and unmapping the buffer. |
29 | * @length: Length of that data | 29 | * @length: Length of that data |
30 | * @no_interrupt: If true, hints that no completion irq is needed. | 30 | * @no_interrupt: If true, hints that no completion irq is needed. |
31 | * Helpful sometimes with deep request queues that are handled | 31 | * Helpful sometimes with deep request queues that are handled |
@@ -45,16 +45,16 @@ struct usb_ep; | |||
45 | * @context: For use by the completion callback | 45 | * @context: For use by the completion callback |
46 | * @list: For use by the gadget driver. | 46 | * @list: For use by the gadget driver. |
47 | * @status: Reports completion code, zero or a negative errno. | 47 | * @status: Reports completion code, zero or a negative errno. |
48 | * Normally, faults block the transfer queue from advancing until | 48 | * Normally, faults block the transfer queue from advancing until |
49 | * the completion callback returns. | 49 | * the completion callback returns. |
50 | * Code "-ESHUTDOWN" indicates completion caused by device disconnect, | 50 | * Code "-ESHUTDOWN" indicates completion caused by device disconnect, |
51 | * or when the driver disabled the endpoint. | 51 | * or when the driver disabled the endpoint. |
52 | * @actual: Reports bytes transferred to/from the buffer. For reads (OUT | 52 | * @actual: Reports bytes transferred to/from the buffer. For reads (OUT |
53 | * transfers) this may be less than the requested length. If the | 53 | * transfers) this may be less than the requested length. If the |
54 | * short_not_ok flag is set, short reads are treated as errors | 54 | * short_not_ok flag is set, short reads are treated as errors |
55 | * even when status otherwise indicates successful completion. | 55 | * even when status otherwise indicates successful completion. |
56 | * Note that for writes (IN transfers) some data bytes may still | 56 | * Note that for writes (IN transfers) some data bytes may still |
57 | * reside in a device-side FIFO when the request is reported as | 57 | * reside in a device-side FIFO when the request is reported as |
58 | * complete. | 58 | * complete. |
59 | * | 59 | * |
60 | * These are allocated/freed through the endpoint they're used with. The | 60 | * These are allocated/freed through the endpoint they're used with. The |
@@ -128,7 +128,7 @@ struct usb_ep_ops { | |||
128 | * value can sometimes be reduced (hardware allowing), according to | 128 | * value can sometimes be reduced (hardware allowing), according to |
129 | * the endpoint descriptor used to configure the endpoint. | 129 | * the endpoint descriptor used to configure the endpoint. |
130 | * @driver_data:for use by the gadget driver. all other fields are | 130 | * @driver_data:for use by the gadget driver. all other fields are |
131 | * read-only to gadget drivers. | 131 | * read-only to gadget drivers. |
132 | * | 132 | * |
133 | * the bus controller driver lists all the general purpose endpoints in | 133 | * the bus controller driver lists all the general purpose endpoints in |
134 | * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list, | 134 | * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list, |
@@ -148,10 +148,10 @@ struct usb_ep { | |||
148 | /** | 148 | /** |
149 | * usb_ep_enable - configure endpoint, making it usable | 149 | * usb_ep_enable - configure endpoint, making it usable |
150 | * @ep:the endpoint being configured. may not be the endpoint named "ep0". | 150 | * @ep:the endpoint being configured. may not be the endpoint named "ep0". |
151 | * drivers discover endpoints through the ep_list of a usb_gadget. | 151 | * drivers discover endpoints through the ep_list of a usb_gadget. |
152 | * @desc:descriptor for desired behavior. caller guarantees this pointer | 152 | * @desc:descriptor for desired behavior. caller guarantees this pointer |
153 | * remains valid until the endpoint is disabled; the data byte order | 153 | * remains valid until the endpoint is disabled; the data byte order |
154 | * is little-endian (usb-standard). | 154 | * is little-endian (usb-standard). |
155 | * | 155 | * |
156 | * when configurations are set, or when interface settings change, the driver | 156 | * when configurations are set, or when interface settings change, the driver |
157 | * will enable or disable the relevant endpoints. while it is enabled, an | 157 | * will enable or disable the relevant endpoints. while it is enabled, an |
@@ -232,7 +232,7 @@ usb_ep_free_request (struct usb_ep *ep, struct usb_request *req) | |||
232 | * @ep:the endpoint associated with the request | 232 | * @ep:the endpoint associated with the request |
233 | * @req:the request being submitted | 233 | * @req:the request being submitted |
234 | * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't | 234 | * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't |
235 | * pre-allocate all necessary memory with the request. | 235 | * pre-allocate all necessary memory with the request. |
236 | * | 236 | * |
237 | * This tells the device controller to perform the specified request through | 237 | * This tells the device controller to perform the specified request through |
238 | * that endpoint (reading or writing a buffer). When the request completes, | 238 | * that endpoint (reading or writing a buffer). When the request completes, |
@@ -415,7 +415,7 @@ struct usb_gadget_ops { | |||
415 | * struct usb_gadget - represents a usb slave device | 415 | * struct usb_gadget - represents a usb slave device |
416 | * @ops: Function pointers used to access hardware-specific operations. | 416 | * @ops: Function pointers used to access hardware-specific operations. |
417 | * @ep0: Endpoint zero, used when reading or writing responses to | 417 | * @ep0: Endpoint zero, used when reading or writing responses to |
418 | * driver setup() requests | 418 | * driver setup() requests |
419 | * @ep_list: List of other endpoints supported by the device. | 419 | * @ep_list: List of other endpoints supported by the device. |
420 | * @speed: Speed of current connection to USB host. | 420 | * @speed: Speed of current connection to USB host. |
421 | * @is_dualspeed: True if the controller supports both high and full speed | 421 | * @is_dualspeed: True if the controller supports both high and full speed |
@@ -432,7 +432,7 @@ struct usb_gadget_ops { | |||
432 | * @b_hnp_enable: OTG device feature flag, indicating that the A-Host | 432 | * @b_hnp_enable: OTG device feature flag, indicating that the A-Host |
433 | * enabled HNP support. | 433 | * enabled HNP support. |
434 | * @name: Identifies the controller hardware type. Used in diagnostics | 434 | * @name: Identifies the controller hardware type. Used in diagnostics |
435 | * and sometimes configuration. | 435 | * and sometimes configuration. |
436 | * @dev: Driver model state for this abstract device. | 436 | * @dev: Driver model state for this abstract device. |
437 | * | 437 | * |
438 | * Gadgets have a mostly-portable "gadget driver" implementing device | 438 | * Gadgets have a mostly-portable "gadget driver" implementing device |
@@ -480,6 +480,39 @@ static inline void *get_gadget_data (struct usb_gadget *gadget) | |||
480 | 480 | ||
481 | 481 | ||
482 | /** | 482 | /** |
483 | * gadget_is_dualspeed - return true iff the hardware handles high speed | ||
484 | * @gadget: controller that might support both high and full speeds | ||
485 | */ | ||
486 | static inline int gadget_is_dualspeed(struct usb_gadget *g) | ||
487 | { | ||
488 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
489 | /* runtime test would check "g->is_dualspeed" ... that might be | ||
490 | * useful to work around hardware bugs, but is mostly pointless | ||
491 | */ | ||
492 | return 1; | ||
493 | #else | ||
494 | return 0; | ||
495 | #endif | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * gadget_is_otg - return true iff the hardware is OTG-ready | ||
500 | * @gadget: controller that might have a Mini-AB connector | ||
501 | * | ||
502 | * This is a runtime test, since kernels with a USB-OTG stack sometimes | ||
503 | * run on boards which only have a Mini-B (or Mini-A) connector. | ||
504 | */ | ||
505 | static inline int gadget_is_otg(struct usb_gadget *g) | ||
506 | { | ||
507 | #ifdef CONFIG_USB_OTG | ||
508 | return g->is_otg; | ||
509 | #else | ||
510 | return 0; | ||
511 | #endif | ||
512 | } | ||
513 | |||
514 | |||
515 | /** | ||
483 | * usb_gadget_frame_number - returns the current frame number | 516 | * usb_gadget_frame_number - returns the current frame number |
484 | * @gadget: controller that reports the frame number | 517 | * @gadget: controller that reports the frame number |
485 | * | 518 | * |
@@ -655,23 +688,23 @@ usb_gadget_disconnect (struct usb_gadget *gadget) | |||
655 | * @function: String describing the gadget's function | 688 | * @function: String describing the gadget's function |
656 | * @speed: Highest speed the driver handles. | 689 | * @speed: Highest speed the driver handles. |
657 | * @bind: Invoked when the driver is bound to a gadget, usually | 690 | * @bind: Invoked when the driver is bound to a gadget, usually |
658 | * after registering the driver. | 691 | * after registering the driver. |
659 | * At that point, ep0 is fully initialized, and ep_list holds | 692 | * At that point, ep0 is fully initialized, and ep_list holds |
660 | * the currently-available endpoints. | 693 | * the currently-available endpoints. |
661 | * Called in a context that permits sleeping. | 694 | * Called in a context that permits sleeping. |
662 | * @setup: Invoked for ep0 control requests that aren't handled by | 695 | * @setup: Invoked for ep0 control requests that aren't handled by |
663 | * the hardware level driver. Most calls must be handled by | 696 | * the hardware level driver. Most calls must be handled by |
664 | * the gadget driver, including descriptor and configuration | 697 | * the gadget driver, including descriptor and configuration |
665 | * management. The 16 bit members of the setup data are in | 698 | * management. The 16 bit members of the setup data are in |
666 | * USB byte order. Called in_interrupt; this may not sleep. Driver | 699 | * USB byte order. Called in_interrupt; this may not sleep. Driver |
667 | * queues a response to ep0, or returns negative to stall. | 700 | * queues a response to ep0, or returns negative to stall. |
668 | * @disconnect: Invoked after all transfers have been stopped, | 701 | * @disconnect: Invoked after all transfers have been stopped, |
669 | * when the host is disconnected. May be called in_interrupt; this | 702 | * when the host is disconnected. May be called in_interrupt; this |
670 | * may not sleep. Some devices can't detect disconnect, so this might | 703 | * may not sleep. Some devices can't detect disconnect, so this might |
671 | * not be called except as part of controller shutdown. | 704 | * not be called except as part of controller shutdown. |
672 | * @unbind: Invoked when the driver is unbound from a gadget, | 705 | * @unbind: Invoked when the driver is unbound from a gadget, |
673 | * usually from rmmod (after a disconnect is reported). | 706 | * usually from rmmod (after a disconnect is reported). |
674 | * Called in a context that permits sleeping. | 707 | * Called in a context that permits sleeping. |
675 | * @suspend: Invoked on USB suspend. May be called in_interrupt. | 708 | * @suspend: Invoked on USB suspend. May be called in_interrupt. |
676 | * @resume: Invoked on USB resume. May be called in_interrupt. | 709 | * @resume: Invoked on USB resume. May be called in_interrupt. |
677 | * @driver: Driver model state for this driver. | 710 | * @driver: Driver model state for this driver. |
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 8da374caf582..2692ec9389ca 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h | |||
@@ -4,11 +4,8 @@ | |||
4 | * belong here. | 4 | * belong here. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | /* device must not be autosuspended */ | ||
8 | #define USB_QUIRK_NO_AUTOSUSPEND 0x00000001 | ||
9 | |||
10 | /* string descriptors must not be fetched using a 255-byte read */ | 7 | /* string descriptors must not be fetched using a 255-byte read */ |
11 | #define USB_QUIRK_STRING_FETCH_255 0x00000002 | 8 | #define USB_QUIRK_STRING_FETCH_255 0x00000001 |
12 | 9 | ||
13 | /* device can't resume correctly so reset it instead */ | 10 | /* device can't resume correctly so reset it instead */ |
14 | #define USB_QUIRK_RESET_RESUME 0x00000004 | 11 | #define USB_QUIRK_RESET_RESUME 0x00000002 |
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index e8b8928232c8..488ce128885c 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
@@ -141,7 +141,7 @@ struct usb_serial { | |||
141 | }; | 141 | }; |
142 | #define to_usb_serial(d) container_of(d, struct usb_serial, kref) | 142 | #define to_usb_serial(d) container_of(d, struct usb_serial, kref) |
143 | 143 | ||
144 | #define NUM_DONT_CARE (-1) | 144 | #define NUM_DONT_CARE 99 |
145 | 145 | ||
146 | /* get and set the serial private data pointer helper functions */ | 146 | /* get and set the serial private data pointer helper functions */ |
147 | static inline void *usb_get_serial_data (struct usb_serial *serial) | 147 | static inline void *usb_get_serial_data (struct usb_serial *serial) |
@@ -160,12 +160,18 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data) | |||
160 | * in the syslog messages when a device is inserted or removed. | 160 | * in the syslog messages when a device is inserted or removed. |
161 | * @id_table: pointer to a list of usb_device_id structures that define all | 161 | * @id_table: pointer to a list of usb_device_id structures that define all |
162 | * of the devices this structure can support. | 162 | * of the devices this structure can support. |
163 | * @num_interrupt_in: the number of interrupt in endpoints this device will | 163 | * @num_interrupt_in: If a device doesn't have this many interrupt-in |
164 | * have. | 164 | * endpoints, it won't be sent to the driver's attach() method. |
165 | * @num_interrupt_out: the number of interrupt out endpoints this device will | 165 | * (But it might still be sent to the probe() method.) |
166 | * have. | 166 | * @num_interrupt_out: If a device doesn't have this many interrupt-out |
167 | * @num_bulk_in: the number of bulk in endpoints this device will have. | 167 | * endpoints, it won't be sent to the driver's attach() method. |
168 | * @num_bulk_out: the number of bulk out endpoints this device will have. | 168 | * (But it might still be sent to the probe() method.) |
169 | * @num_bulk_in: If a device doesn't have this many bulk-in | ||
170 | * endpoints, it won't be sent to the driver's attach() method. | ||
171 | * (But it might still be sent to the probe() method.) | ||
172 | * @num_bulk_out: If a device doesn't have this many bulk-out | ||
173 | * endpoints, it won't be sent to the driver's attach() method. | ||
174 | * (But it might still be sent to the probe() method.) | ||
169 | * @num_ports: the number of different ports this device will have. | 175 | * @num_ports: the number of different ports this device will have. |
170 | * @calc_num_ports: pointer to a function to determine how many ports this | 176 | * @calc_num_ports: pointer to a function to determine how many ports this |
171 | * device has dynamically. It will be called after the probe() | 177 | * device has dynamically. It will be called after the probe() |
diff --git a/include/linux/usb_sl811.h b/include/linux/usb_sl811.h deleted file mode 100644 index 4f2d012d7309..000000000000 --- a/include/linux/usb_sl811.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | * board initialization should put one of these into dev->platform_data | ||
4 | * and place the sl811hs onto platform_bus named "sl811-hcd". | ||
5 | */ | ||
6 | |||
7 | struct sl811_platform_data { | ||
8 | unsigned can_wakeup:1; | ||
9 | |||
10 | /* given port_power, msec/2 after power on till power good */ | ||
11 | u8 potpg; | ||
12 | |||
13 | /* mA/2 power supplied on this port (max = default = 250) */ | ||
14 | u8 power; | ||
15 | |||
16 | /* sl811 relies on an external source of VBUS current */ | ||
17 | void (*port_power)(struct device *dev, int is_on); | ||
18 | |||
19 | /* pulse sl811 nRST (probably with a GPIO) */ | ||
20 | void (*reset)(struct device *dev); | ||
21 | |||
22 | // some boards need something like these: | ||
23 | // int (*check_overcurrent)(struct device *dev); | ||
24 | // void (*clock_enable)(struct device *dev, int is_on); | ||
25 | }; | ||
26 | |||
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index f66351126544..8d53106a0a92 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig | |||
@@ -23,3 +23,8 @@ config HIGH_RES_TIMERS | |||
23 | hardware is not capable then this option only increases | 23 | hardware is not capable then this option only increases |
24 | the size of the kernel image. | 24 | the size of the kernel image. |
25 | 25 | ||
26 | config GENERIC_CLOCKEVENTS_BUILD | ||
27 | bool | ||
28 | default y | ||
29 | depends on GENERIC_CLOCKEVENTS || GENERIC_CLOCKEVENTS_MIGR | ||
30 | |||
diff --git a/kernel/time/Makefile b/kernel/time/Makefile index 99b6034fc86b..905b0b50792d 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o | 1 | obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o |
2 | 2 | ||
3 | obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o | 3 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o |
4 | obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o | 4 | obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o |
5 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o | 5 | obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += tick-broadcast.o |
6 | obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o | 6 | obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 41dd3105ce7f..822beebe664a 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
@@ -194,6 +194,7 @@ void clockevents_exchange_device(struct clock_event_device *old, | |||
194 | local_irq_restore(flags); | 194 | local_irq_restore(flags); |
195 | } | 195 | } |
196 | 196 | ||
197 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
197 | /** | 198 | /** |
198 | * clockevents_notify - notification about relevant events | 199 | * clockevents_notify - notification about relevant events |
199 | */ | 200 | */ |
@@ -222,4 +223,4 @@ void clockevents_notify(unsigned long reason, void *arg) | |||
222 | spin_unlock(&clockevents_lock); | 223 | spin_unlock(&clockevents_lock); |
223 | } | 224 | } |
224 | EXPORT_SYMBOL_GPL(clockevents_notify); | 225 | EXPORT_SYMBOL_GPL(clockevents_notify); |
225 | 226 | #endif | |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 0962e0577660..298bc7c6f09f 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -64,8 +64,9 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) | |||
64 | */ | 64 | */ |
65 | int tick_check_broadcast_device(struct clock_event_device *dev) | 65 | int tick_check_broadcast_device(struct clock_event_device *dev) |
66 | { | 66 | { |
67 | if (tick_broadcast_device.evtdev || | 67 | if ((tick_broadcast_device.evtdev && |
68 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) | 68 | tick_broadcast_device.evtdev->rating >= dev->rating) || |
69 | (dev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
69 | return 0; | 70 | return 0; |
70 | 71 | ||
71 | clockevents_exchange_device(NULL, dev); | 72 | clockevents_exchange_device(NULL, dev); |
@@ -176,8 +177,6 @@ static void tick_do_periodic_broadcast(void) | |||
176 | */ | 177 | */ |
177 | static void tick_handle_periodic_broadcast(struct clock_event_device *dev) | 178 | static void tick_handle_periodic_broadcast(struct clock_event_device *dev) |
178 | { | 179 | { |
179 | dev->next_event.tv64 = KTIME_MAX; | ||
180 | |||
181 | tick_do_periodic_broadcast(); | 180 | tick_do_periodic_broadcast(); |
182 | 181 | ||
183 | /* | 182 | /* |
@@ -515,11 +514,9 @@ static void tick_broadcast_clear_oneshot(int cpu) | |||
515 | */ | 514 | */ |
516 | void tick_broadcast_setup_oneshot(struct clock_event_device *bc) | 515 | void tick_broadcast_setup_oneshot(struct clock_event_device *bc) |
517 | { | 516 | { |
518 | if (bc->mode != CLOCK_EVT_MODE_ONESHOT) { | 517 | bc->event_handler = tick_handle_oneshot_broadcast; |
519 | bc->event_handler = tick_handle_oneshot_broadcast; | 518 | clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); |
520 | clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); | 519 | bc->next_event.tv64 = KTIME_MAX; |
521 | bc->next_event.tv64 = KTIME_MAX; | ||
522 | } | ||
523 | } | 520 | } |
524 | 521 | ||
525 | /* | 522 | /* |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 77a21abc8716..3f3ae3907830 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -200,7 +200,7 @@ static int tick_check_new_device(struct clock_event_device *newdev) | |||
200 | 200 | ||
201 | cpu = smp_processor_id(); | 201 | cpu = smp_processor_id(); |
202 | if (!cpu_isset(cpu, newdev->cpumask)) | 202 | if (!cpu_isset(cpu, newdev->cpumask)) |
203 | goto out; | 203 | goto out_bc; |
204 | 204 | ||
205 | td = &per_cpu(tick_cpu_device, cpu); | 205 | td = &per_cpu(tick_cpu_device, cpu); |
206 | curdev = td->evtdev; | 206 | curdev = td->evtdev; |
@@ -265,7 +265,7 @@ out_bc: | |||
265 | */ | 265 | */ |
266 | if (tick_check_broadcast_device(newdev)) | 266 | if (tick_check_broadcast_device(newdev)) |
267 | ret = NOTIFY_STOP; | 267 | ret = NOTIFY_STOP; |
268 | out: | 268 | |
269 | spin_unlock_irqrestore(&tick_device_lock, flags); | 269 | spin_unlock_irqrestore(&tick_device_lock, flags); |
270 | 270 | ||
271 | return ret; | 271 | return ret; |