diff options
451 files changed, 17990 insertions, 11483 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/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 9f08dab1e75b..d9d832c010ef 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | NOTE: | 1 | NOTE: |
| 2 | This is a version of Documentation/HOWTO translated into Japanese. | 2 | This is a version of Documentation/HOWTO translated into Japanese. |
| 3 | This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com> | 3 | This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com> |
| 4 | and the JF Project team <www.linux.or.jp/JF>. | 4 | and the JF Project team <www.linux.or.jp/JF>. |
| @@ -11,14 +11,14 @@ for non English (read: Japanese) speakers and is not intended as a | |||
| 11 | fork. So if you have any comments or updates for this file, please try | 11 | fork. So if you have any comments or updates for this file, please try |
| 12 | to update the original English file first. | 12 | to update the original English file first. |
| 13 | 13 | ||
| 14 | Last Updated: 2007/07/18 | 14 | Last Updated: 2007/09/23 |
| 15 | ================================== | 15 | ================================== |
| 16 | ã“れã¯ã€ | 16 | ã“れã¯ã€ |
| 17 | linux-2.6.22/Documentation/HOWTO | 17 | linux-2.6.23/Documentation/HOWTO |
| 18 | ã®å’Œè¨³ã§ã™ã€‚ | 18 | ã®å’Œè¨³ã§ã™ã€‚ |
| 19 | 19 | ||
| 20 | 翻訳団体: JF プãƒã‚¸ã‚§ã‚¯ãƒˆ < http://www.linux.or.jp/JF/ > | 20 | 翻訳団体: JF プãƒã‚¸ã‚§ã‚¯ãƒˆ < http://www.linux.or.jp/JF/ > |
| 21 | 翻訳日: 2007/07/16 | 21 | 翻訳日: 2007/09/19 |
| 22 | 翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com> | 22 | 翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com> |
| 23 | æ ¡æ£è€…: æ¾å€‰ã•ã‚“ <nbh--mats at nifty dot com> | 23 | æ ¡æ£è€…: æ¾å€‰ã•ã‚“ <nbh--mats at nifty dot com> |
| 24 | å°æž— é›…å…¸ã•ã‚“ (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp> | 24 | å°æž— é›…å…¸ã•ã‚“ (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp> |
| @@ -27,6 +27,7 @@ linux-2.6.22/Documentation/HOWTO | |||
| 27 | 野å£ã•ã‚“ (Kenji Noguchi) <tokyo246 at gmail dot com> | 27 | 野å£ã•ã‚“ (Kenji Noguchi) <tokyo246 at gmail dot com> |
| 28 | 河内ã•ã‚“ (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com> | 28 | 河内ã•ã‚“ (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com> |
| 29 | 岩本ã•ã‚“ (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp> | 29 | 岩本ã•ã‚“ (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp> |
| 30 | 内田ã•ã‚“ (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com> | ||
| 30 | ================================== | 31 | ================================== |
| 31 | 32 | ||
| 32 | Linux カーãƒãƒ«é–‹ç™ºã®ã‚„り方 | 33 | Linux カーãƒãƒ«é–‹ç™ºã®ã‚„り方 |
| @@ -40,7 +41,7 @@ Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«æ´»å‹•ã™ã‚‹ã‚„り方をå¦ã | |||
| 40 | 手助ã‘ã«ãªã‚Šã¾ã™ã€‚ | 41 | 手助ã‘ã«ãªã‚Šã¾ã™ã€‚ |
| 41 | 42 | ||
| 42 | ã‚‚ã—ã€ã“ã®ãƒ‰ã‚ュメントã®ã©ã“ã‹ãŒå¤ããªã£ã¦ã„ãŸå ´åˆã«ã¯ã€ã“ã®ãƒ‰ã‚ュメン | 43 | ã‚‚ã—ã€ã“ã®ãƒ‰ã‚ュメントã®ã©ã“ã‹ãŒå¤ããªã£ã¦ã„ãŸå ´åˆã«ã¯ã€ã“ã®ãƒ‰ã‚ュメン |
| 43 | ãƒˆã®æœ€å¾Œã«ãƒªã‚¹ãƒˆã—ãŸãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼ã«ãƒ‘ッãƒã‚’é€ã£ã¦ãã ã•ã„。 | 44 | ãƒˆã®æœ€å¾Œã«ãƒªã‚¹ãƒˆã—ãŸãƒ¡ãƒ³ãƒ†ãƒŠã«ãƒ‘ッãƒã‚’é€ã£ã¦ãã ã•ã„。 |
| 44 | 45 | ||
| 45 | ã¯ã˜ã‚ã« | 46 | ã¯ã˜ã‚ã« |
| 46 | --------- | 47 | --------- |
| @@ -59,7 +60,7 @@ Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«æ´»å‹•ã™ã‚‹ã‚„り方をå¦ã | |||
| 59 | ãƒãƒ«é–‹ç™ºè€…ã«ã¯å¿…è¦ã§ã™ã€‚アーã‚テクãƒãƒ£å‘ã‘ã®ä½Žãƒ¬ãƒ™ãƒ«éƒ¨åˆ†ã®é–‹ç™ºã‚’ã™ã‚‹ã® | 60 | ãƒãƒ«é–‹ç™ºè€…ã«ã¯å¿…è¦ã§ã™ã€‚アーã‚テクãƒãƒ£å‘ã‘ã®ä½Žãƒ¬ãƒ™ãƒ«éƒ¨åˆ†ã®é–‹ç™ºã‚’ã™ã‚‹ã® |
| 60 | ã§ãªã‘れã°ã€(ã©ã‚“ãªã‚¢ãƒ¼ã‚テクãƒãƒ£ã§ã‚‚)アセンブリ(訳注: 言語)ã¯å¿…è¦ã‚り | 61 | ã§ãªã‘れã°ã€(ã©ã‚“ãªã‚¢ãƒ¼ã‚テクãƒãƒ£ã§ã‚‚)アセンブリ(訳注: 言語)ã¯å¿…è¦ã‚り |
| 61 | ã¾ã›ã‚“ã€‚ä»¥ä¸‹ã®æœ¬ã¯ã€C 言語ã®å分ãªçŸ¥è˜ã‚„何年もã®çµŒé¨“ã«å–ã£ã¦ä»£ã‚ã‚‹ã‚‚ã® | 62 | ã¾ã›ã‚“ã€‚ä»¥ä¸‹ã®æœ¬ã¯ã€C 言語ã®å分ãªçŸ¥è˜ã‚„何年もã®çµŒé¨“ã«å–ã£ã¦ä»£ã‚ã‚‹ã‚‚ã® |
| 62 | ã§ã¯ã‚りã¾ã›ã‚“ãŒã€å°‘ãªãã¨ã‚‚リファレンスã¨ã—ã¦ã¯ã„ã„æœ¬ã§ã™ã€‚ | 63 | ã§ã¯ã‚りã¾ã›ã‚“ãŒã€å°‘ãªãã¨ã‚‚リファレンスã¨ã—ã¦ã¯è‰¯ã„本ã§ã™ã€‚ |
| 63 | - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall] | 64 | - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall] |
| 64 | -『プãƒã‚°ãƒ©ãƒŸãƒ³ã‚°è¨€èªžï¼£ç¬¬2版ã€(B.W. カーニãƒãƒ³/D.M. リッãƒãƒ¼è‘— 石田晴久訳) [共立出版] | 65 | -『プãƒã‚°ãƒ©ãƒŸãƒ³ã‚°è¨€èªžï¼£ç¬¬2版ã€(B.W. カーニãƒãƒ³/D.M. リッãƒãƒ¼è‘— 石田晴久訳) [共立出版] |
| 65 | - "Practical C Programming" by Steve Oualline [O'Reilly] | 66 | - "Practical C Programming" by Steve Oualline [O'Reilly] |
| @@ -76,7 +77,7 @@ Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«æ´»å‹•ã™ã‚‹ã‚„り方をå¦ã | |||
| 76 | ã¨ãã©ãã€ã‚«ãƒ¼ãƒãƒ«ãŒãƒ„ールãƒã‚§ã‚¤ãƒ³ã‚„ C 言語拡張ã«ç½®ã„ã¦ã„ã‚‹å‰æãŒã©ã† | 77 | ã¨ãã©ãã€ã‚«ãƒ¼ãƒãƒ«ãŒãƒ„ールãƒã‚§ã‚¤ãƒ³ã‚„ C 言語拡張ã«ç½®ã„ã¦ã„ã‚‹å‰æãŒã©ã† |
| 77 | ãªã£ã¦ã„ã‚‹ã®ã‹ã‚ã‹ã‚Šã«ãã„ã“ã¨ãŒã‚りã€ã¾ãŸã€æ®‹å¿µãªã“ã¨ã«æ±ºå®šçš„ãªãƒªãƒ•ã‚¡ | 78 | ãªã£ã¦ã„ã‚‹ã®ã‹ã‚ã‹ã‚Šã«ãã„ã“ã¨ãŒã‚りã€ã¾ãŸã€æ®‹å¿µãªã“ã¨ã«æ±ºå®šçš„ãªãƒªãƒ•ã‚¡ |
| 78 | レンスã¯å˜åœ¨ã—ã¾ã›ã‚“ã€‚æƒ…å ±ã‚’å¾—ã‚‹ã«ã¯ã€gcc ã® info ページ( info gcc )ã‚’ | 79 | レンスã¯å˜åœ¨ã—ã¾ã›ã‚“ã€‚æƒ…å ±ã‚’å¾—ã‚‹ã«ã¯ã€gcc ã® info ページ( info gcc )ã‚’ |
| 79 | ã¿ã¦ãã ã•ã„。 | 80 | 見ã¦ãã ã•ã„。 |
| 80 | 81 | ||
| 81 | ã‚ãªãŸã¯æ—¢å˜ã®é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨ä¸€ç·’ã«ä½œæ¥ã™ã‚‹æ–¹æ³•ã‚’å¦ã¼ã†ã¨ã—ã¦ã„ã‚‹ã“ | 82 | ã‚ãªãŸã¯æ—¢å˜ã®é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨ä¸€ç·’ã«ä½œæ¥ã™ã‚‹æ–¹æ³•ã‚’å¦ã¼ã†ã¨ã—ã¦ã„ã‚‹ã“ |
| 82 | ã¨ã«ç•™æ„ã—ã¦ãã ã•ã„。ãã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã€ã‚¹ã‚¿ã‚¤ãƒ«ã€ | 83 | ã¨ã«ç•™æ„ã—ã¦ãã ã•ã„。ãã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã€ã‚¹ã‚¿ã‚¤ãƒ«ã€ |
| @@ -92,7 +93,7 @@ Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«æ´»å‹•ã™ã‚‹ã‚„り方をå¦ã | |||
| 92 | 93 | ||
| 93 | Linux カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ GPL ライセンスã®ä¸‹ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ | 94 | Linux カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ GPL ライセンスã®ä¸‹ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾ |
| 94 | ã™ã€‚ライセンスã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ã‚½ãƒ¼ã‚¹ãƒ„リーã®ãƒ¡ã‚¤ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å˜åœ¨ | 95 | ã™ã€‚ライセンスã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ã‚½ãƒ¼ã‚¹ãƒ„リーã®ãƒ¡ã‚¤ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å˜åœ¨ |
| 95 | ã™ã‚‹ã€COPYING ã®ãƒ•ァイルをã¿ã¦ãã ã•ã„。もã—ライセンスã«ã¤ã„ã¦ã•らã«è³ª | 96 | ã™ã‚‹ã€COPYING ã®ãƒ•ァイルを見ã¦ãã ã•ã„。もã—ライセンスã«ã¤ã„ã¦ã•らã«è³ª |
| 96 | å•ãŒã‚れã°ã€Linux Kernel メーリングリストã«è³ªå•ã™ã‚‹ã®ã§ã¯ãªãã€ã©ã†ãž | 97 | å•ãŒã‚れã°ã€Linux Kernel メーリングリストã«è³ªå•ã™ã‚‹ã®ã§ã¯ãªãã€ã©ã†ãž |
| 97 | 法律家ã«ç›¸è«‡ã—ã¦ãã ã•ã„。メーリングリストã®äººé”ã¯æ³•律家ã§ã¯ãªãã€æ³•çš„ | 98 | 法律家ã«ç›¸è«‡ã—ã¦ãã ã•ã„。メーリングリストã®äººé”ã¯æ³•律家ã§ã¯ãªãã€æ³•çš„ |
| 98 | å•題ã«ã¤ã„ã¦ã¯å½¼ã‚‰ã®å£°æ˜Žã¯ã‚ã¦ã«ã™ã‚‹ã¹ãã§ã¯ã‚りã¾ã›ã‚“。 | 99 | å•題ã«ã¤ã„ã¦ã¯å½¼ã‚‰ã®å£°æ˜Žã¯ã‚ã¦ã«ã™ã‚‹ã¹ãã§ã¯ã‚りã¾ã›ã‚“。 |
| @@ -109,7 +110,8 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã¯å¹…広ã„範囲ã®ãƒ‰ã‚ュメントをå | |||
| 109 | æ–°ã—ã„ドã‚ãƒ¥ãƒ¡ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚‚è¿½åŠ ã™ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ã™ã€‚ | 110 | æ–°ã—ã„ドã‚ãƒ¥ãƒ¡ãƒ³ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚‚è¿½åŠ ã™ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ã™ã€‚ |
| 110 | カーãƒãƒ«ã®å¤‰æ›´ãŒã€ã‚«ãƒ¼ãƒãƒ«ãŒãƒ¦ãƒ¼ã‚¶ç©ºé–“ã«å…¬é–‹ã—ã¦ã„るインターフェイス㮠| 111 | カーãƒãƒ«ã®å¤‰æ›´ãŒã€ã‚«ãƒ¼ãƒãƒ«ãŒãƒ¦ãƒ¼ã‚¶ç©ºé–“ã«å…¬é–‹ã—ã¦ã„るインターフェイス㮠|
| 111 | 変更を引ãèµ·ã“ã™å ´åˆã€ãã®å¤‰æ›´ã‚’説明ã™ã‚‹ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãƒšãƒ¼ã‚¸ã®ãƒ‘ッãƒã‚„æƒ…å ± | 112 | 変更を引ãèµ·ã“ã™å ´åˆã€ãã®å¤‰æ›´ã‚’説明ã™ã‚‹ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãƒšãƒ¼ã‚¸ã®ãƒ‘ッãƒã‚„æƒ…å ± |
| 112 | をマニュアルページã®ãƒ¡ãƒ³ãƒ†ãƒŠ mtk-manpages@gmx.net ã«é€ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ã™ã€‚ | 113 | をマニュアルページã®ãƒ¡ãƒ³ãƒ†ãƒŠ mtk-manpages@gmx.net ã«é€ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ |
| 114 | ã™ã€‚ | ||
| 113 | 115 | ||
| 114 | 以下ã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã«å«ã¾ã‚Œã¦ã„ã‚‹èªã‚“ã§ãŠãã¹ãファイルã®ä¸€è¦§ã§ | 116 | 以下ã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã«å«ã¾ã‚Œã¦ã„ã‚‹èªã‚“ã§ãŠãã¹ãファイルã®ä¸€è¦§ã§ |
| 115 | ã™- | 117 | ã™- |
| @@ -117,7 +119,7 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã¯å¹…広ã„範囲ã®ãƒ‰ã‚ュメントをå | |||
| 117 | README | 119 | README |
| 118 | ã“ã®ãƒ•ァイル㯠Linuxカーãƒãƒ«ã®ç°¡å˜ãªèƒŒæ™¯ã¨ã‚«ãƒ¼ãƒãƒ«ã‚’è¨å®š(訳注 | 120 | ã“ã®ãƒ•ァイル㯠Linuxカーãƒãƒ«ã®ç°¡å˜ãªèƒŒæ™¯ã¨ã‚«ãƒ¼ãƒãƒ«ã‚’è¨å®š(訳注 |
| 119 | configure )ã—ã€ç”Ÿæˆ(訳注 build )ã™ã‚‹ãŸã‚ã«å¿…è¦ãªã“ã¨ã¯ä½•ã‹ãŒæ›¸ã‹ã‚Œ | 121 | configure )ã—ã€ç”Ÿæˆ(訳注 build )ã™ã‚‹ãŸã‚ã«å¿…è¦ãªã“ã¨ã¯ä½•ã‹ãŒæ›¸ã‹ã‚Œ |
| 120 | ã¦ã„ã¾ã™ã€‚カーãƒãƒ«ã«é–¢ã—ã¦åˆã‚ã¦ã®äººã¯ã“ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆã™ã‚‹ã¨ã‚ˆã„ã§ | 122 | ã¦ã„ã¾ã™ã€‚カーãƒãƒ«ã«é–¢ã—ã¦åˆã‚ã¦ã®äººã¯ã“ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆã™ã‚‹ã¨è‰¯ã„ã§ |
| 121 | ã—ょã†ã€‚ | 123 | ã—ょã†ã€‚ |
| 122 | 124 | ||
| 123 | Documentation/Changes | 125 | Documentation/Changes |
| @@ -128,7 +130,7 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã¯å¹…広ã„範囲ã®ãƒ‰ã‚ュメントをå | |||
| 128 | Documentation/CodingStyle | 130 | Documentation/CodingStyle |
| 129 | ã“れ㯠Linux カーãƒãƒ«ã®ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã¨èƒŒæ™¯ã«ã‚ã‚‹ç†ç”±ã‚’記述 | 131 | ã“れ㯠Linux カーãƒãƒ«ã®ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã¨èƒŒæ™¯ã«ã‚ã‚‹ç†ç”±ã‚’記述 |
| 130 | ã—ã¦ã„ã¾ã™ã€‚å…¨ã¦ã®æ–°ã—ã„コードã¯ã“ã®ãƒ‰ã‚ュメントã«ã‚るガイドライン | 132 | ã—ã¦ã„ã¾ã™ã€‚å…¨ã¦ã®æ–°ã—ã„コードã¯ã“ã®ãƒ‰ã‚ュメントã«ã‚るガイドライン |
| 131 | ã«å¾“ã£ã¦ã„ã‚‹ã“ã¨ã‚’期待ã•れã¦ã„ã¾ã™ã€‚大部分ã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼ã¯ã“れらã®ãƒ«ãƒ¼ | 133 | ã«å¾“ã£ã¦ã„ã‚‹ã“ã¨ã‚’期待ã•れã¦ã„ã¾ã™ã€‚大部分ã®ãƒ¡ãƒ³ãƒ†ãƒŠã¯ã“れらã®ãƒ«ãƒ¼ |
| 132 | ルã«å¾“ã£ã¦ã„ã‚‹ã‚‚ã®ã ã‘ã‚’å—ã‘付ã‘ã€å¤šãã®äººã¯æ£ã—ã„スタイルã®ã‚³ãƒ¼ãƒ‰ | 134 | ルã«å¾“ã£ã¦ã„ã‚‹ã‚‚ã®ã ã‘ã‚’å—ã‘付ã‘ã€å¤šãã®äººã¯æ£ã—ã„スタイルã®ã‚³ãƒ¼ãƒ‰ |
| 133 | ã ã‘をレビューã—ã¾ã™ã€‚ | 135 | ã ã‘をレビューã—ã¾ã™ã€‚ |
| 134 | 136 | ||
| @@ -168,16 +170,16 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã¯å¹…広ã„範囲ã®ãƒ‰ã‚ュメントをå | |||
| 168 | 支æ´ã—ã¦ãã ã•ã„。 | 170 | 支æ´ã—ã¦ãã ã•ã„。 |
| 169 | 171 | ||
| 170 | Documentation/ManagementStyle | 172 | Documentation/ManagementStyle |
| 171 | ã“ã®ãƒ‰ã‚ュメント㯠Linux カーãƒãƒ«ã®ãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼é”ãŒã©ã†è¡Œå‹•ã™ã‚‹ã‹ã€ | 173 | ã“ã®ãƒ‰ã‚ュメント㯠Linux カーãƒãƒ«ã®ãƒ¡ãƒ³ãƒ†ãƒŠé”ãŒã©ã†è¡Œå‹•ã™ã‚‹ã‹ã€ |
| 172 | å½¼ã‚‰ã®æ‰‹æ³•ã®èƒŒæ™¯ã«ã‚る共有ã•れã¦ã„る精神ã«ã¤ã„ã¦è¨˜è¿°ã—ã¦ã„ã¾ã™ã€‚ã“ | 174 | å½¼ã‚‰ã®æ‰‹æ³•ã®èƒŒæ™¯ã«ã‚る共有ã•れã¦ã„る精神ã«ã¤ã„ã¦è¨˜è¿°ã—ã¦ã„ã¾ã™ã€‚ã“ |
| 173 | れã¯ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºã®åˆå¿ƒè€…ãªã‚‰ï¼ˆã‚‚ã—ãã¯ã€å˜ã«èˆˆå‘³ãŒã‚ã‚‹ã ã‘ã®äººã§ã‚‚) | 175 | れã¯ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºã®åˆå¿ƒè€…ãªã‚‰ï¼ˆã‚‚ã—ãã¯ã€å˜ã«èˆˆå‘³ãŒã‚ã‚‹ã ã‘ã®äººã§ã‚‚) |
| 174 | é‡è¦ã§ã™ã€‚ãªãœãªã‚‰ã“ã®ãƒ‰ã‚ュメントã¯ã€ã‚«ãƒ¼ãƒãƒ«ãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼é”ã®ç‹¬ç‰¹ãª | 176 | é‡è¦ã§ã™ã€‚ãªãœãªã‚‰ã“ã®ãƒ‰ã‚ュメントã¯ã€ã‚«ãƒ¼ãƒãƒ«ãƒ¡ãƒ³ãƒ†ãƒŠé”ã®ç‹¬ç‰¹ãª |
| 175 | 行動ã«ã¤ã„ã¦ã®å¤šãã®èª¤è§£ã‚„混乱を解消ã™ã‚‹ã‹ã‚‰ã§ã™ã€‚ | 177 | 行動ã«ã¤ã„ã¦ã®å¤šãã®èª¤è§£ã‚„混乱を解消ã™ã‚‹ã‹ã‚‰ã§ã™ã€‚ |
| 176 | 178 | ||
| 177 | Documentation/stable_kernel_rules.txt | 179 | Documentation/stable_kernel_rules.txt |
| 178 | ã“ã®ãƒ•ァイルã¯ã©ã®ã‚ˆã†ã« stable カーãƒãƒ«ã®ãƒªãƒªãƒ¼ã‚¹ãŒè¡Œã‚れるã‹ã®ãƒ«ãƒ¼ | 180 | ã“ã®ãƒ•ァイルã¯ã©ã®ã‚ˆã†ã« stable カーãƒãƒ«ã®ãƒªãƒªãƒ¼ã‚¹ãŒè¡Œã‚れるã‹ã®ãƒ«ãƒ¼ |
| 179 | ルãŒè¨˜è¿°ã•れã¦ã„ã¾ã™ã€‚ãã—ã¦ã“れらã®ãƒªãƒªãƒ¼ã‚¹ã®ä¸ã®ã©ã“ã‹ã§å¤‰æ›´ã‚’å– | 181 | ルãŒè¨˜è¿°ã•れã¦ã„ã¾ã™ã€‚ãã—ã¦ã“れらã®ãƒªãƒªãƒ¼ã‚¹ã®ä¸ã®ã©ã“ã‹ã§å¤‰æ›´ã‚’å– |
| 180 | り入れã¦ã‚‚らã„ãŸã„å ´åˆã«ä½•ã‚’ã™ã‚Œã°ã„ã„ã‹ãŒç¤ºã•れã¦ã„ã¾ã™ã€‚ | 182 | り入れã¦ã‚‚らã„ãŸã„å ´åˆã«ä½•ã‚’ã™ã‚Œã°è‰¯ã„ã‹ãŒç¤ºã•れã¦ã„ã¾ã™ã€‚ |
| 181 | 183 | ||
| 182 | Documentation/kernel-docs.txt | 184 | Documentation/kernel-docs.txt |
| 183 |   カーãƒãƒ«é–‹ç™ºã«ä»˜éšã™ã‚‹å¤–部ドã‚ュメントã®ãƒªã‚¹ãƒˆã§ã™ã€‚ã‚‚ã—ã‚ãªãŸãŒ | 185 |   カーãƒãƒ«é–‹ç™ºã«ä»˜éšã™ã‚‹å¤–部ドã‚ュメントã®ãƒªã‚¹ãƒˆã§ã™ã€‚ã‚‚ã—ã‚ãªãŸãŒ |
| @@ -218,9 +220,9 @@ web サイトã«ã¯ã€ã‚³ãƒ¼ãƒ‰ã®æ§‹æˆã€ã‚µãƒ–システムã€ç¾åœ¨å˜åœ¨ã™ã | |||
| 218 | ã“ã“ã«ã¯ã€ã¾ãŸã€ã‚«ãƒ¼ãƒãƒ«ã®ã‚³ãƒ³ãƒ‘イルã®ã‚„り方やパッãƒã®å½“ã¦æ–¹ãªã©ã®é–“接 | 220 | ã“ã“ã«ã¯ã€ã¾ãŸã€ã‚«ãƒ¼ãƒãƒ«ã®ã‚³ãƒ³ãƒ‘イルã®ã‚„り方やパッãƒã®å½“ã¦æ–¹ãªã©ã®é–“接 |
| 219 | çš„ãªåŸºæœ¬æƒ…å ±ã‚‚è¨˜è¿°ã•れã¦ã„ã¾ã™ã€‚ | 221 | çš„ãªåŸºæœ¬æƒ…å ±ã‚‚è¨˜è¿°ã•れã¦ã„ã¾ã™ã€‚ |
| 220 | 222 | ||
| 221 | ã‚ãªãŸãŒã©ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆã—ã¦ã‚ˆã„ã‹ã‚ã‹ã‚‰ãªã„ãŒã€Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ | 223 | ã‚ãªãŸãŒã©ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆã—ã¦è‰¯ã„ã‹ã‚ã‹ã‚‰ãªã„ãŒã€Linux カーãƒãƒ«é–‹ç™ºã‚³ãƒŸãƒ¥ |
| 222 | ニティã«å‚åŠ ã—ã¦ä½•ã‹ã™ã‚‹ã“ã¨ã‚’ã•ãŒã—ã¦ã„ã‚‹å ´åˆã«ã¯ã€Linux kernel | 224 | ニティã«å‚åŠ ã—ã¦ä½•ã‹ã™ã‚‹ã“ã¨ã‚’ã•ãŒã—ã¦ã„ã‚‹å ´åˆã«ã¯ã€Linux kernel |
| 223 | Janitor's プãƒã‚¸ã‚§ã‚¯ãƒˆã«ã„ã‘ã°ã‚ˆã„ã§ã—ょㆠ- | 225 | Janitor's プãƒã‚¸ã‚§ã‚¯ãƒˆã«ã„ã‘ã°è‰¯ã„ã§ã—ょㆠ- |
| 224 | http://janitor.kernelnewbies.org/ | 226 | http://janitor.kernelnewbies.org/ |
| 225 | ã“ã“ã¯ãã®ã‚ˆã†ãªã‚¹ã‚¿ãƒ¼ãƒˆã‚’ã™ã‚‹ã®ã«ã†ã£ã¦ã¤ã‘ã®å ´æ‰€ã§ã™ã€‚ã“ã“ã«ã¯ã€ | 227 | ã“ã“ã¯ãã®ã‚ˆã†ãªã‚¹ã‚¿ãƒ¼ãƒˆã‚’ã™ã‚‹ã®ã«ã†ã£ã¦ã¤ã‘ã®å ´æ‰€ã§ã™ã€‚ã“ã“ã«ã¯ã€ |
| 226 | Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã®ä¸ã«å«ã¾ã‚Œã‚‹ã€ãれã„ã«ã—ã€ä¿®æ£ã—ãªã‘れã°ãª | 228 | Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã®ä¸ã«å«ã¾ã‚Œã‚‹ã€ãれã„ã«ã—ã€ä¿®æ£ã—ãªã‘れã°ãª |
| @@ -243,7 +245,7 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã®ä¸ã«å«ã¾ã‚Œã‚‹ã€ãれã„ã«ã—ã€ä¿ | |||
| 243 | 自己å‚ç…§æ–¹å¼ã§ã€ç´¢å¼•ãŒã¤ã„㟠web å½¢å¼ã§ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒ | 245 | 自己å‚ç…§æ–¹å¼ã§ã€ç´¢å¼•ãŒã¤ã„㟠web å½¢å¼ã§ã€ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒ |
| 244 | ã§ãã¾ã™ã€‚ã“ã®æœ€æ–°ã®ç´ æ™´ã—ã„カーãƒãƒ«ã‚³ãƒ¼ãƒ‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ä»¥ä¸‹ã§è¦‹ã¤ã‹ã‚Š | 246 | ã§ãã¾ã™ã€‚ã“ã®æœ€æ–°ã®ç´ æ™´ã—ã„カーãƒãƒ«ã‚³ãƒ¼ãƒ‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ä»¥ä¸‹ã§è¦‹ã¤ã‹ã‚Š |
| 245 | ã¾ã™- | 247 | ã¾ã™- |
| 246 | http://sosdg.org/~coywolf/lxr/ | 248 | http://sosdg.org/~qiyong/lxr/ |
| 247 | 249 | ||
| 248 | 開発プãƒã‚»ã‚¹ | 250 | 開発プãƒã‚»ã‚¹ |
| 249 | ----------------------- | 251 | ----------------------- |
| @@ -265,9 +267,9 @@ Linux カーãƒãƒ«ã®é–‹ç™ºãƒ—ãƒã‚»ã‚¹ã¯ç¾åœ¨å¹¾ã¤ã‹ã®ç•°ãªã‚‹ãƒ¡ã‚¤ãƒ³ã‚ | |||
| 265 | 以下ã®ã¨ãŠã‚Š- | 267 | 以下ã®ã¨ãŠã‚Š- |
| 266 | 268 | ||
| 267 | - æ–°ã—ã„カーãƒãƒ«ãŒãƒªãƒªãƒ¼ã‚¹ã•れãŸç›´å¾Œã«ã€2週間ã®ç‰¹åˆ¥æœŸé–“ãŒè¨ã‘られ〠| 269 | - æ–°ã—ã„カーãƒãƒ«ãŒãƒªãƒªãƒ¼ã‚¹ã•れãŸç›´å¾Œã«ã€2週間ã®ç‰¹åˆ¥æœŸé–“ãŒè¨ã‘られ〠|
| 268 | ã“ã®æœŸé–“ä¸ã«ã€ãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼é”㯠Linus ã«å¤§ããªå·®åˆ†ã‚’é€ã‚‹ã“ã¨ãŒã§ãã¾ | 270 | ã“ã®æœŸé–“ä¸ã«ã€ãƒ¡ãƒ³ãƒ†ãƒŠé”㯠Linus ã«å¤§ããªå·®åˆ†ã‚’é€ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ |
| 269 | ã™ã€‚ã“ã®ã‚ˆã†ãªå·®åˆ†ã¯é€šå¸¸ -mm カーãƒãƒ«ã«æ•°é€±é–“å«ã¾ã‚Œã¦ããŸãƒ‘ッãƒã§ | 271 | ã“ã®ã‚ˆã†ãªå·®åˆ†ã¯é€šå¸¸ -mm カーãƒãƒ«ã«æ•°é€±é–“å«ã¾ã‚Œã¦ããŸãƒ‘ッãƒã§ã™ã€‚ |
| 270 | ã™ã€‚ 大ããªå¤‰æ›´ã¯ git(カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ç®¡ç†ãƒ„ールã€è©³ç´°ã¯ | 272 | 大ããªå¤‰æ›´ã¯ git(カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ç®¡ç†ãƒ„ールã€è©³ç´°ã¯ |
| 271 | http://git.or.cz/ å‚ç…§) を使ã£ã¦é€ã‚‹ã®ãŒå¥½ã¾ã—ã„やり方ã§ã™ãŒã€ãƒ‘ッ | 273 | http://git.or.cz/ å‚ç…§) を使ã£ã¦é€ã‚‹ã®ãŒå¥½ã¾ã—ã„やり方ã§ã™ãŒã€ãƒ‘ッ |
| 272 | ãƒãƒ•ァイルã®å½¢å¼ã®ã¾ã¾é€ã‚‹ã®ã§ã‚‚å分ã§ã™ã€‚ | 274 | ãƒãƒ•ァイルã®å½¢å¼ã®ã¾ã¾é€ã‚‹ã®ã§ã‚‚å分ã§ã™ã€‚ |
| 273 | 275 | ||
| @@ -285,6 +287,10 @@ Linux カーãƒãƒ«ã®é–‹ç™ºãƒ—ãƒã‚»ã‚¹ã¯ç¾åœ¨å¹¾ã¤ã‹ã®ç•°ãªã‚‹ãƒ¡ã‚¤ãƒ³ã‚ | |||
| 285 | ã«å®‰å®šã—ãŸçŠ¶æ…‹ã«ã‚ã‚‹ã¨åˆ¤æ–ã—ãŸã¨ãã«ãƒªãƒªãƒ¼ã‚¹ã•れã¾ã™ã€‚ç›®æ¨™ã¯æ¯Žé€±æ–° | 287 | ã«å®‰å®šã—ãŸçŠ¶æ…‹ã«ã‚ã‚‹ã¨åˆ¤æ–ã—ãŸã¨ãã«ãƒªãƒªãƒ¼ã‚¹ã•れã¾ã™ã€‚ç›®æ¨™ã¯æ¯Žé€±æ–° |
| 286 | ã—ã„ -rc カーãƒãƒ«ã‚’リリースã™ã‚‹ã“ã¨ã§ã™ã€‚ | 288 | ã—ã„ -rc カーãƒãƒ«ã‚’リリースã™ã‚‹ã“ã¨ã§ã™ã€‚ |
| 287 | 289 | ||
| 290 | - 以下㮠URL ã§å„ -rc リリースã«å˜åœ¨ã™ã‚‹æ—¢çŸ¥ã®å¾Œæˆ»ã‚Šå•題ã®ãƒªã‚¹ãƒˆ | ||
| 291 | ãŒè¿½è·¡ã•れã¾ã™- | ||
| 292 | http://kernelnewbies.org/known_regressions | ||
| 293 | |||
| 288 | - ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã‚«ãƒ¼ãƒãƒ«ãŒ 「準備ãŒã§ããŸã€ã¨è€ƒãˆã‚‰ã‚Œã‚‹ã¾ã§ç¶™ç¶šã—ã¾ | 294 | - ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã‚«ãƒ¼ãƒãƒ«ãŒ 「準備ãŒã§ããŸã€ã¨è€ƒãˆã‚‰ã‚Œã‚‹ã¾ã§ç¶™ç¶šã—ã¾ |
| 289 | ã™ã€‚ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã ã„ãŸã„ 6週間継続ã—ã¾ã™ã€‚ | 295 | ã™ã€‚ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã ã„ãŸã„ 6週間継続ã—ã¾ã™ã€‚ |
| 290 | 296 | ||
| @@ -331,8 +337,8 @@ Andrew ã¯å€‹åˆ¥ã®ã‚µãƒ–システムカーãƒãƒ«ãƒ„リーã¨ãƒ‘ッãƒã‚’å…¨ã¦é | |||
| 331 | linux-kernel メーリングリストã§åŽé›†ã•れãŸå¤šæ•°ã®ãƒ‘ッãƒã¨åŒæ™‚ã«ä¸€ã¤ã«ã¾ | 337 | linux-kernel メーリングリストã§åŽé›†ã•れãŸå¤šæ•°ã®ãƒ‘ッãƒã¨åŒæ™‚ã«ä¸€ã¤ã«ã¾ |
| 332 | ã¨ã‚ã¾ã™ã€‚ | 338 | ã¨ã‚ã¾ã™ã€‚ |
| 333 | ã“ã®ãƒ„ãƒªãƒ¼ã¯æ–°æ©Ÿèƒ½ã¨ãƒ‘ッãƒãŒæ¤œè¨¼ã•ã‚Œã‚‹å ´ã¨ãªã‚Šã¾ã™ã€‚ã‚る期間ã®é–“パッム| 339 | ã“ã®ãƒ„ãƒªãƒ¼ã¯æ–°æ©Ÿèƒ½ã¨ãƒ‘ッãƒãŒæ¤œè¨¼ã•ã‚Œã‚‹å ´ã¨ãªã‚Šã¾ã™ã€‚ã‚る期間ã®é–“パッム|
| 334 | ㌠-mm ã«å…¥ã£ã¦ä¾¡å€¤ã‚’証明ã•れãŸã‚‰ã€Andrew やサブシステムメンテナãŒã€ãƒ¡ | 340 | ㌠-mm ã«å…¥ã£ã¦ä¾¡å€¤ã‚’証明ã•れãŸã‚‰ã€Andrew やサブシステムメンテナãŒã€ |
| 335 | インラインã¸å…¥ã‚Œã‚‹ã‚ˆã†ã« Linus ã«ãƒ—ッシュã—ã¾ã™ã€‚ | 341 | メインラインã¸å…¥ã‚Œã‚‹ã‚ˆã†ã« Linus ã«ãƒ—ッシュã—ã¾ã™ã€‚ |
| 336 | 342 | ||
| 337 | メインカーãƒãƒ«ãƒ„リーã«å«ã‚ã‚‹ãŸã‚ã« Linus ã«é€ã‚‹å‰ã«ã€ã™ã¹ã¦ã®æ–°ã—ã„パッ | 343 | メインカーãƒãƒ«ãƒ„リーã«å«ã‚ã‚‹ãŸã‚ã« Linus ã«é€ã‚‹å‰ã«ã€ã™ã¹ã¦ã®æ–°ã—ã„パッ |
| 338 | ãƒãŒ -mm ツリーã§ãƒ†ã‚¹ãƒˆã•れるã“ã¨ãŒå¼·ã推奨ã•れã¾ã™ã€‚ | 344 | ãƒãŒ -mm ツリーã§ãƒ†ã‚¹ãƒˆã•れるã“ã¨ãŒå¼·ã推奨ã•れã¾ã™ã€‚ |
| @@ -460,7 +466,7 @@ MAINTAINERS ファイルã«ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ã®ã§å‚ç…§ã—ã¦ãã ã•ã | |||
| 460 | ã›ã‚“- | 466 | ã›ã‚“- |
| 461 | 彼らã¯ã‚ãªãŸã®ãƒ‘ッãƒã®è¡Œæ¯Žã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’入れãŸã„ã®ã§ã€ãã®ãŸã‚ã«ã¯ãã†ã™ | 467 | 彼らã¯ã‚ãªãŸã®ãƒ‘ッãƒã®è¡Œæ¯Žã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’入れãŸã„ã®ã§ã€ãã®ãŸã‚ã«ã¯ãã†ã™ |
| 462 | ã‚‹ã—ã‹ã‚りã¾ã›ã‚“。ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒã‚°ãƒ©ãƒ ãŒç©ºç™½ã‚„タブを圧縮ã—ãªã„よㆠ| 468 | ã‚‹ã—ã‹ã‚りã¾ã›ã‚“。ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒã‚°ãƒ©ãƒ ãŒç©ºç™½ã‚„タブを圧縮ã—ãªã„よㆠ|
| 463 | ã«ç¢ºèªã—ãŸæ–¹ãŒã„ã„ã§ã™ã€‚最åˆã®è‰¯ã„テストã¨ã—ã¦ã¯ã€è‡ªåˆ†ã«ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ | 469 | ã«ç¢ºèªã—ãŸæ–¹ãŒè‰¯ã„ã§ã™ã€‚最åˆã®è‰¯ã„テストã¨ã—ã¦ã¯ã€è‡ªåˆ†ã«ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ |
| 464 | ã¿ã¦ã€ãã®ãƒ‘ッãƒã‚’自分ã§å½“ã¦ã¦ã¿ã‚‹ã“ã¨ã§ã™ã€‚ã‚‚ã—ãれãŒã†ã¾ã行ã‹ãªã„㪠| 470 | ã¿ã¦ã€ãã®ãƒ‘ッãƒã‚’自分ã§å½“ã¦ã¦ã¿ã‚‹ã“ã¨ã§ã™ã€‚ã‚‚ã—ãれãŒã†ã¾ã行ã‹ãªã„㪠|
| 465 | らã€ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒã‚°ãƒ©ãƒ ã‚’ç›´ã—ã¦ã‚‚らã†ã‹ã€æ£ã—ãå‹•ãよã†ã«å¤‰ãˆã‚‹ã¹ | 471 | らã€ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒã‚°ãƒ©ãƒ ã‚’ç›´ã—ã¦ã‚‚らã†ã‹ã€æ£ã—ãå‹•ãよã†ã«å¤‰ãˆã‚‹ã¹ |
| 466 | ãã§ã™ã€‚ | 472 | ãã§ã™ã€‚ |
| @@ -507,14 +513,14 @@ MAINTAINERS ファイルã«ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ã®ã§å‚ç…§ã—ã¦ãã ã•ã | |||
| 507 | ã¨ã‚‚普通ã®ã“ã¨ã§ã™ã€‚ã“れã¯ã‚ãªãŸã®ãƒ‘ッãƒãŒå—ã‘入れられãªã„ã¨ã„ã†ã“ã¨ã§ | 513 | ã¨ã‚‚普通ã®ã“ã¨ã§ã™ã€‚ã“れã¯ã‚ãªãŸã®ãƒ‘ッãƒãŒå—ã‘入れられãªã„ã¨ã„ã†ã“ã¨ã§ |
| 508 | 㯠*ã‚りã¾ã›ã‚“*ã€ãã—ã¦ã‚ãªãŸè‡ªèº«ã«å対ã™ã‚‹ã“ã¨ã‚’æ„味ã™ã‚‹ã®ã§ã‚‚ *ã‚り㾠| 514 | 㯠*ã‚りã¾ã›ã‚“*ã€ãã—ã¦ã‚ãªãŸè‡ªèº«ã«å対ã™ã‚‹ã“ã¨ã‚’æ„味ã™ã‚‹ã®ã§ã‚‚ *ã‚り㾠|
| 509 | ã›ã‚“*。å˜ã«è‡ªåˆ†ã®ãƒ‘ッãƒã«å¯¾ã—ã¦æŒ‡æ‘˜ã•れãŸå•題を全ã¦ä¿®æ£ã—ã¦å†é€ã™ã‚Œã° | 515 | ã›ã‚“*。å˜ã«è‡ªåˆ†ã®ãƒ‘ッãƒã«å¯¾ã—ã¦æŒ‡æ‘˜ã•れãŸå•題を全ã¦ä¿®æ£ã—ã¦å†é€ã™ã‚Œã° |
| 510 | ã„ã„ã®ã§ã™ã€‚ | 516 | 良ã„ã®ã§ã™ã€‚ |
| 511 | 517 | ||
| 512 | 518 | ||
| 513 | カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨ä¼æ¥çµ„ç¹”ã®ã¡ãŒã„ | 519 | カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨ä¼æ¥çµ„ç¹”ã®ã¡ãŒã„ |
| 514 | ----------------------------------------------------------------- | 520 | ----------------------------------------------------------------- |
| 515 | 521 | ||
| 516 | カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯å¤§éƒ¨åˆ†ã®ä¼çµ±çš„ãªä¼šç¤¾ã®é–‹ç™ºç’°å¢ƒã¨ã¯ç•°ã£ãŸã‚„り方㧠| 522 | カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯å¤§éƒ¨åˆ†ã®ä¼çµ±çš„ãªä¼šç¤¾ã®é–‹ç™ºç’°å¢ƒã¨ã¯ç•°ã£ãŸã‚„り方㧠|
| 517 | å‹•ã„ã¦ã„ã¾ã™ã€‚以下ã¯å•題をé¿ã‘ã‚‹ãŸã‚ã«ã§ãã‚‹ã¨ã‚ˆã„ã“ã¨ã®ã®ãƒªã‚¹ãƒˆã§ã™- | 523 | å‹•ã„ã¦ã„ã¾ã™ã€‚以下ã¯å•題をé¿ã‘ã‚‹ãŸã‚ã«ã§ãã‚‹ã¨è‰¯ã„ã“ã¨ã®ãƒªã‚¹ãƒˆã§ã™- |
| 518 | 524 | ||
| 519 | ã‚ãªãŸã®ææ¡ˆã™ã‚‹å¤‰æ›´ã«ã¤ã„ã¦è¨€ã†ã¨ãã®ã†ã¾ã„è¨€ã„æ–¹ï¼š | 525 | ã‚ãªãŸã®ææ¡ˆã™ã‚‹å¤‰æ›´ã«ã¤ã„ã¦è¨€ã†ã¨ãã®ã†ã¾ã„è¨€ã„æ–¹ï¼š |
| 520 | 526 | ||
| @@ -525,7 +531,7 @@ MAINTAINERS ファイルã«ãƒªã‚¹ãƒˆãŒã‚りã¾ã™ã®ã§å‚ç…§ã—ã¦ãã ã•ã | |||
| 525 | - "以下ã¯ä¸€é€£ã®å°ã•ãªãƒ‘ッãƒç¾¤ã§ã™ãŒ..." | 531 | - "以下ã¯ä¸€é€£ã®å°ã•ãªãƒ‘ッãƒç¾¤ã§ã™ãŒ..." |
| 526 | - "ã“れã¯å…¸åž‹çš„ãªãƒžã‚·ãƒ³ã§ã®æ€§èƒ½ã‚’å‘上ã•ã›ã¾ã™.." | 532 | - "ã“れã¯å…¸åž‹çš„ãªãƒžã‚·ãƒ³ã§ã®æ€§èƒ½ã‚’å‘上ã•ã›ã¾ã™.." |
| 527 | 533 | ||
| 528 | ã‚„ã‚ãŸæ–¹ãŒã„ã„æ‚ªã„è¨€ã„æ–¹ï¼š | 534 | ã‚„ã‚ãŸæ–¹ãŒè‰¯ã„悪ã„è¨€ã„æ–¹ï¼š |
| 529 | 535 | ||
| 530 | - ã“ã®ã‚„り方㧠AIX/ptx/Solaris ã§ã¯ã§ããŸã®ã§ã€ã§ãã‚‹ã¯ãšã | 536 | - ã“ã®ã‚„り方㧠AIX/ptx/Solaris ã§ã¯ã§ããŸã®ã§ã€ã§ãã‚‹ã¯ãšã |
| 531 | - ç§ã¯ã“れを20å¹´ã‚‚ã®é–“ã‚„ã£ã¦ããŸã€ã ã‹ã‚‰ | 537 | - ç§ã¯ã“れを20å¹´ã‚‚ã®é–“ã‚„ã£ã¦ããŸã€ã ã‹ã‚‰ |
| @@ -575,10 +581,10 @@ Linux カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ä¸€åº¦ã«å¤§é‡ã®ã‚³ãƒ¼ãƒ‰ã®å¡Šã‚’å– | |||
| 575 | 581 | ||
| 576 | 1) å°ã•ã„パッãƒã¯ã‚ãªãŸã®ãƒ‘ッãƒãŒé©ç”¨ã•れる見込ã¿ã‚’大ããã—ã¾ã™ã€ã‚«ãƒ¼ | 582 | 1) å°ã•ã„パッãƒã¯ã‚ãªãŸã®ãƒ‘ッãƒãŒé©ç”¨ã•れる見込ã¿ã‚’大ããã—ã¾ã™ã€ã‚«ãƒ¼ |
| 577 | ãƒãƒ«ã®äººé”ã¯ãƒ‘ッãƒãŒæ£ã—ã„ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹æ™‚間や労力をã‹ã‘ãªã„ã‹ | 583 | ãƒãƒ«ã®äººé”ã¯ãƒ‘ッãƒãŒæ£ã—ã„ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹æ™‚間や労力をã‹ã‘ãªã„ã‹ |
| 578 | らã§ã™ã€‚5行ã®ãƒ‘ッãƒã¯ãƒ¡ãƒ³ãƒ†ãƒŠãŒãŸã£ãŸ1秒見るã ã‘ã§é©ç”¨ã§ãã¾ã™ã€‚ã— | 584 | らã§ã™ã€‚5行ã®ãƒ‘ッãƒã¯ãƒ¡ãƒ³ãƒ†ãƒŠãŒãŸã£ãŸ1秒見るã ã‘ã§é©ç”¨ã§ãã¾ã™ã€‚ |
| 579 | ã‹ã—ã€500行ã®ãƒ‘ッãƒã¯ã€æ£ã—ã„ã“ã¨ã‚’レビューã™ã‚‹ã®ã«æ•°æ™‚é–“ã‹ã‹ã‚‹ã‹ã‚‚ | 585 | ã—ã‹ã—ã€500行ã®ãƒ‘ッãƒã¯ã€æ£ã—ã„ã“ã¨ã‚’レビューã™ã‚‹ã®ã«æ•°æ™‚é–“ã‹ã‹ã‚‹ã‹ |
| 580 | ã—れã¾ã›ã‚“(時間ã¯ãƒ‘ッãƒã®ã‚µã‚¤ã‚ºãªã©ã«ã‚ˆã‚ŠæŒ‡æ•°é–¢æ•°ã«æ¯”例ã—ã¦ã‹ã‹ã‚Šã¾ | 586 | ã‚‚ã—れã¾ã›ã‚“(時間ã¯ãƒ‘ッãƒã®ã‚µã‚¤ã‚ºãªã©ã«ã‚ˆã‚ŠæŒ‡æ•°é–¢æ•°ã«æ¯”例ã—ã¦ã‹ã‹ã‚Š |
| 581 | ã™) | 587 | ã¾ã™) |
| 582 | 588 | ||
| 583 | å°ã•ã„パッãƒã¯ä½•ã‹ã‚ã£ãŸã¨ãã«ãƒ‡ãƒãƒƒã‚°ã‚‚ã¨ã¦ã‚‚ç°¡å˜ã«ãªã‚Šã¾ã™ã€‚パッ | 589 | å°ã•ã„パッãƒã¯ä½•ã‹ã‚ã£ãŸã¨ãã«ãƒ‡ãƒãƒƒã‚°ã‚‚ã¨ã¦ã‚‚ç°¡å˜ã«ãªã‚Šã¾ã™ã€‚パッ |
| 584 | ãƒã‚’1個1個å–り除ãã®ã¯ã€ã¨ã¦ã‚‚大ããªãƒ‘ッãƒã‚’当ã¦ãŸå¾Œã«(ã‹ã¤ã€ä½•ã‹ãŠ | 590 | ãƒã‚’1個1個å–り除ãã®ã¯ã€ã¨ã¦ã‚‚大ããªãƒ‘ッãƒã‚’当ã¦ãŸå¾Œã«(ã‹ã¤ã€ä½•ã‹ãŠ |
| @@ -587,23 +593,23 @@ Linux カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ä¸€åº¦ã«å¤§é‡ã®ã‚³ãƒ¼ãƒ‰ã®å¡Šã‚’å– | |||
| 587 | 2) å°ã•ã„パッãƒã‚’é€ã‚‹ã ã‘ã§ãªãã€é€ã‚‹ã¾ãˆã«ã€æ›¸ãç›´ã—ã¦ã€ã‚·ãƒ³ãƒ—ルã«ã™ | 593 | 2) å°ã•ã„パッãƒã‚’é€ã‚‹ã ã‘ã§ãªãã€é€ã‚‹ã¾ãˆã«ã€æ›¸ãç›´ã—ã¦ã€ã‚·ãƒ³ãƒ—ルã«ã™ |
| 588 | ã‚‹(ã‚‚ã—ãã¯ã€å˜ã«é †ç•ªã‚’変ãˆã‚‹ã ã‘ã§ã‚‚)ã“ã¨ã‚‚ã€ã¨ã¦ã‚‚é‡è¦ã§ã™ã€‚ | 594 | ã‚‹(ã‚‚ã—ãã¯ã€å˜ã«é †ç•ªã‚’変ãˆã‚‹ã ã‘ã§ã‚‚)ã“ã¨ã‚‚ã€ã¨ã¦ã‚‚é‡è¦ã§ã™ã€‚ |
| 589 | 595 | ||
| 590 | 以下ã¯ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã® Al Viro ã®ãŸã¨ãˆè©±ã—ã§ã™ï¼š | 596 | 以下ã¯ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã® Al Viro ã®ãŸã¨ãˆè©±ã§ã™ï¼š |
| 591 | 597 | ||
| 592 | "ç”Ÿå¾’ã®æ•°å¦ã®å®¿é¡Œã‚’採点ã™ã‚‹å…ˆç”Ÿã®ã“ã¨ã‚’考ãˆã¦ã¿ã¦ãã ã•ã„ã€å…ˆ | 598 | "ç”Ÿå¾’ã®æ•°å¦ã®å®¿é¡Œã‚’採点ã™ã‚‹å…ˆç”Ÿã®ã“ã¨ã‚’考ãˆã¦ã¿ã¦ãã ã•ã„ã€å…ˆ |
| 593 | 生ã¯ç”Ÿå¾’ãŒè§£ã«åˆ°é”ã™ã‚‹ã¾ã§ã®è©¦è¡ŒéŒ¯èª¤ã‚’ã¿ãŸã„ã¨ã¯æ€ã‚ãªã„ã§ã—ょ | 599 | 生ã¯ç”Ÿå¾’ãŒè§£ã«åˆ°é”ã™ã‚‹ã¾ã§ã®è©¦è¡ŒéŒ¯èª¤ã‚’見ãŸã„ã¨ã¯æ€ã‚ãªã„ã§ã—ょ |
| 594 | ã†ã€‚先生ã¯ç°¡æ½”ãªæœ€é«˜ã®è§£ã‚’ã¿ãŸã„ã®ã§ã™ã€‚良ã„生徒ã¯ã“れを知ã£ã¦ | 600 | ã†ã€‚先生ã¯ç°¡æ½”ãªæœ€é«˜ã®è§£ã‚’見ãŸã„ã®ã§ã™ã€‚良ã„生徒ã¯ã“れを知ã£ã¦ |
| 595 | ãŠã‚Šã€ãã—ã¦æœ€çµ‚è§£ã®å‰ã®ä¸é–“作æ¥ã‚’æå‡ºã™ã‚‹ã“ã¨ã¯æ±ºã—ã¦ãªã„ã®ã§ | 601 | ãŠã‚Šã€ãã—ã¦æœ€çµ‚è§£ã®å‰ã®ä¸é–“作æ¥ã‚’æå‡ºã™ã‚‹ã“ã¨ã¯æ±ºã—ã¦ãªã„ã®ã§ |
| 596 | ã™" | 602 | ã™" |
| 597 | 603 | ||
| 598 | カーãƒãƒ«é–‹ç™ºã§ã‚‚ã“れã¯åŒã˜ã§ã™ã€‚メンテナーé”ã¨ãƒ¬ãƒ“ューアé”ã¯ã€ | 604 | カーãƒãƒ«é–‹ç™ºã§ã‚‚ã“れã¯åŒã˜ã§ã™ã€‚メンテナé”ã¨ãƒ¬ãƒ“ューアé”ã¯ã€ |
| 599 | å•題を解決ã™ã‚‹è§£ã®èƒŒå¾Œã«ãªã‚‹æ€è€ƒãƒ—ãƒã‚»ã‚¹ã‚’ã¿ãŸã„ã¨ã¯æ€ã„ã¾ã›ã‚“。 | 605 | å•題を解決ã™ã‚‹è§£ã®èƒŒå¾Œã«ãªã‚‹æ€è€ƒãƒ—ãƒã‚»ã‚¹ã‚’見ãŸã„ã¨ã¯æ€ã„ã¾ã›ã‚“。 |
| 600 | 彼らã¯å˜ç´”ã§ã‚ã–ã‚„ã‹ãªè§£æ±ºæ–¹æ³•ã‚’ã¿ãŸã„ã®ã§ã™ã€‚ | 606 | 彼らã¯å˜ç´”ã§ã‚ã–ã‚„ã‹ãªè§£æ±ºæ–¹æ³•を見ãŸã„ã®ã§ã™ã€‚ |
| 601 | 607 | ||
| 602 | ã‚ã–ã‚„ã‹ãªè§£ã‚’説明ã™ã‚‹ã®ã¨ã€ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«ä»•事をã—ã€æœªè§£æ±ºã®ä»•事を | 608 | ã‚ã–ã‚„ã‹ãªè§£ã‚’説明ã™ã‚‹ã®ã¨ã€ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¨å…±ã«ä»•事をã—ã€æœªè§£æ±ºã®ä»•事を |
| 603 | è°è«–ã™ã‚‹ã“ã¨ã®ãƒãƒ©ãƒ³ã‚¹ã‚’ã‚ープã™ã‚‹ã®ã¯é›£ã—ã„ã‹ã‚‚ã—れã¾ã›ã‚“。 | 609 | è°è«–ã™ã‚‹ã“ã¨ã®ãƒãƒ©ãƒ³ã‚¹ã‚’ã‚ープã™ã‚‹ã®ã¯é›£ã—ã„ã‹ã‚‚ã—れã¾ã›ã‚“。 |
| 604 | ã§ã™ã‹ã‚‰ã€é–‹ç™ºãƒ—ãƒã‚»ã‚¹ã®æ—©æœŸæ®µéšŽã§æ”¹å–„ã®ãŸã‚ã®ãƒ•ィードãƒãƒƒã‚¯ã‚’もらã†ã‚ˆ | 610 | ã§ã™ã‹ã‚‰ã€é–‹ç™ºãƒ—ãƒã‚»ã‚¹ã®æ—©æœŸæ®µéšŽã§æ”¹å–„ã®ãŸã‚ã®ãƒ•ィードãƒãƒƒã‚¯ã‚’もらã†ã‚ˆ |
| 605 | ã†ã«ã™ã‚‹ã®ã‚‚ã„ã„ã§ã™ãŒã€å¤‰æ›´ç‚¹ã‚’å°ã•ã„部分ã«åˆ†å‰²ã—ã¦å…¨ä½“ã§ã¯ã¾ã 完æˆã— | 611 | ã†ã«ã™ã‚‹ã®ã‚‚良ã„ã§ã™ãŒã€å¤‰æ›´ç‚¹ã‚’å°ã•ã„部分ã«åˆ†å‰²ã—ã¦å…¨ä½“ã§ã¯ã¾ã 完æˆã— |
| 606 | ã¦ã„ãªã„仕事を(部分的ã«)å–り込んã§ã‚‚らãˆã‚‹ã‚ˆã†ã«ã™ã‚‹ã“ã¨ã‚‚ã„ã„ã“ã¨ã§ã™ã€‚ | 612 | ã¦ã„ãªã„仕事を(部分的ã«)å–り込んã§ã‚‚らãˆã‚‹ã‚ˆã†ã«ã™ã‚‹ã“ã¨ã‚‚良ã„ã“ã¨ã§ã™ã€‚ |
| 607 | 613 | ||
| 608 | ã¾ãŸã€ã§ã上ãŒã£ã¦ã„ãªã„ã‚‚ã®ã‚„ã€"å°†æ¥ç›´ã™" よã†ãªãƒ‘ッãƒã‚’ã€æœ¬æµã«å«ã‚ | 614 | ã¾ãŸã€ã§ã上ãŒã£ã¦ã„ãªã„ã‚‚ã®ã‚„ã€"å°†æ¥ç›´ã™" よã†ãªãƒ‘ッãƒã‚’ã€æœ¬æµã«å«ã‚ |
| 609 | ã¦ã‚‚らã†ã‚ˆã†ã«é€ã£ã¦ã‚‚ã€ãれã¯å—ã‘付ã‘られãªã„ã“ã¨ã‚’ç†è§£ã—ã¦ãã ã•ã„。 | 615 | ã¦ã‚‚らã†ã‚ˆã†ã«é€ã£ã¦ã‚‚ã€ãれã¯å—ã‘付ã‘られãªã„ã“ã¨ã‚’ç†è§£ã—ã¦ãã ã•ã„。 |
| @@ -629,7 +635,7 @@ Linux カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ä¸€åº¦ã«å¤§é‡ã®ã‚³ãƒ¼ãƒ‰ã®å¡Šã‚’å– | |||
| 629 | - ãƒ†ã‚¹ãƒˆçµæžœ | 635 | - ãƒ†ã‚¹ãƒˆçµæžœ |
| 630 | 636 | ||
| 631 | ã“れã«ã¤ã„ã¦å…¨ã¦ãŒã©ã®ã‚ˆã†ã«ã‚ã‚‹ã¹ãã‹ã«ã¤ã„ã¦ã®è©³ç´°ã¯ã€ä»¥ä¸‹ã®ãƒ‰ã‚ュメ | 637 | ã“れã«ã¤ã„ã¦å…¨ã¦ãŒã©ã®ã‚ˆã†ã«ã‚ã‚‹ã¹ãã‹ã«ã¤ã„ã¦ã®è©³ç´°ã¯ã€ä»¥ä¸‹ã®ãƒ‰ã‚ュメ |
| 632 | ント㮠ChangeLog セクションをã¿ã¦ãã ã•ã„- | 638 | ント㮠ChangeLog セクションを見ã¦ãã ã•ã„- |
| 633 | "The Perfect Patch" | 639 | "The Perfect Patch" |
| 634 | http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt | 640 | http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt |
| 635 | 641 | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d006e8b66ffa..9cbc82e37ed0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1010,6 +1010,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1010 | meye.*= [HW] Set MotionEye Camera parameters | 1010 | meye.*= [HW] Set MotionEye Camera parameters |
| 1011 | See Documentation/video4linux/meye.txt. | 1011 | See Documentation/video4linux/meye.txt. |
| 1012 | 1012 | ||
| 1013 | mfgpt_irq= [IA-32] Specify the IRQ to use for the | ||
| 1014 | Multi-Function General Purpose Timers on AMD Geode | ||
| 1015 | platforms. | ||
| 1016 | |||
| 1013 | mga= [HW,DRM] | 1017 | mga= [HW,DRM] |
| 1014 | 1018 | ||
| 1015 | mousedev.tap_time= | 1019 | mousedev.tap_time= |
| @@ -1161,6 +1165,9 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1161 | 1165 | ||
| 1162 | nomce [X86-32] Machine Check Exception | 1166 | nomce [X86-32] Machine Check Exception |
| 1163 | 1167 | ||
| 1168 | nomfgpt [X86-32] Disable Multi-Function General Purpose | ||
| 1169 | Timer usage (for AMD Geode machines). | ||
| 1170 | |||
| 1164 | noreplace-paravirt [X86-32,PV_OPS] Don't patch paravirt_ops | 1171 | noreplace-paravirt [X86-32,PV_OPS] Don't patch paravirt_ops |
| 1165 | 1172 | ||
| 1166 | noreplace-smp [X86-32,SMP] Don't replace SMP instructions | 1173 | noreplace-smp [X86-32,SMP] Don't replace SMP instructions |
| @@ -1438,6 +1445,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1438 | pt. [PARIDE] | 1445 | pt. [PARIDE] |
| 1439 | See Documentation/paride.txt. | 1446 | See Documentation/paride.txt. |
| 1440 | 1447 | ||
| 1448 | pty.legacy_count= | ||
| 1449 | [KNL] Number of legacy pty's. Overwrites compiled-in | ||
| 1450 | default number. | ||
| 1451 | |||
| 1441 | quiet [KNL] Disable most log messages | 1452 | quiet [KNL] Disable most log messages |
| 1442 | 1453 | ||
| 1443 | r128= [HW,DRM] | 1454 | r128= [HW,DRM] |
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index 8ee49ee7c963..ca86a885ad8f 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt | |||
| @@ -54,7 +54,6 @@ embedded in larger data structures and replace fields they duplicate. | |||
| 54 | 54 | ||
| 55 | struct kobject { | 55 | struct kobject { |
| 56 | const char * k_name; | 56 | const char * k_name; |
| 57 | char name[KOBJ_NAME_LEN]; | ||
| 58 | struct kref kref; | 57 | struct kref kref; |
| 59 | struct list_head entry; | 58 | struct list_head entry; |
| 60 | struct kobject * parent; | 59 | struct kobject * parent; |
| @@ -223,18 +222,15 @@ decl_subsys(devices, &ktype_device, &device_uevent_ops); | |||
| 223 | is equivalent to doing: | 222 | is equivalent to doing: |
| 224 | 223 | ||
| 225 | struct kset devices_subsys = { | 224 | struct kset devices_subsys = { |
| 226 | .kobj = { | ||
| 227 | .name = "devices", | ||
| 228 | }, | ||
| 229 | .ktype = &ktype_devices, | 225 | .ktype = &ktype_devices, |
| 230 | .uevent_ops = &device_uevent_ops, | 226 | .uevent_ops = &device_uevent_ops, |
| 231 | }; | 227 | }; |
| 232 | 228 | kobject_set_name(&devices_subsys, name); | |
| 233 | 229 | ||
| 234 | The objects that are registered with a subsystem that use the | 230 | The objects that are registered with a subsystem that use the |
| 235 | subsystem's default list must have their kset ptr set properly. These | 231 | subsystem's default list must have their kset ptr set properly. These |
| 236 | objects may have embedded kobjects or ksets. The | 232 | objects may have embedded kobjects or ksets. The |
| 237 | following helpers make setting the kset easier: | 233 | following helper makes setting the kset easier: |
| 238 | 234 | ||
| 239 | 235 | ||
| 240 | kobj_set_kset_s(obj,subsys) | 236 | kobj_set_kset_s(obj,subsys) |
| @@ -242,22 +238,8 @@ kobj_set_kset_s(obj,subsys) | |||
| 242 | - Assumes that obj->kobj exists, and is a struct kobject. | 238 | - Assumes that obj->kobj exists, and is a struct kobject. |
| 243 | - Sets the kset of that kobject to the kset <subsys>. | 239 | - Sets the kset of that kobject to the kset <subsys>. |
| 244 | 240 | ||
| 245 | |||
| 246 | kset_set_kset_s(obj,subsys) | ||
| 247 | |||
| 248 | - Assumes that obj->kset exists, and is a struct kset. | ||
| 249 | - Sets the kset of the embedded kobject to the kset <subsys>. | ||
| 250 | |||
| 251 | subsys_set_kset(obj,subsys) | ||
| 252 | |||
| 253 | - Assumes obj->subsys exists, and is a struct subsystem. | ||
| 254 | - Sets obj->subsys.kset.kobj.kset to the subsystem's embedded kset. | ||
| 255 | |||
| 256 | void subsystem_init(struct kset *s); | ||
| 257 | int subsystem_register(struct kset *s); | 241 | int subsystem_register(struct kset *s); |
| 258 | void subsystem_unregister(struct kset *s); | 242 | void subsystem_unregister(struct kset *s); |
| 259 | struct kset *subsys_get(struct kset *s); | ||
| 260 | void kset_put(struct kset *s); | ||
| 261 | 243 | ||
| 262 | These are just wrappers around the respective kset_* functions. | 244 | These are just wrappers around the respective kset_* functions. |
| 263 | 245 | ||
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 515abb98d41d..f1486f8a3e6d 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
| @@ -1211,6 +1211,16 @@ config SCx200HR_TIMER | |||
| 1211 | processor goes idle (as is done by the scheduler). The | 1211 | processor goes idle (as is done by the scheduler). The |
| 1212 | other workaround is idle=poll boot option. | 1212 | other workaround is idle=poll boot option. |
| 1213 | 1213 | ||
| 1214 | config GEODE_MFGPT_TIMER | ||
| 1215 | bool "Geode Multi-Function General Purpose Timer (MFGPT) events" | ||
| 1216 | depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS | ||
| 1217 | default y | ||
| 1218 | help | ||
| 1219 | This driver provides a clock event source based on the MFGPT | ||
| 1220 | timer(s) in the CS5535 and CS5536 companion chip for the geode. | ||
| 1221 | MFGPTs have a better resolution and max interval than the | ||
| 1222 | generic PIT, and are suitable for use as high-res timers. | ||
| 1223 | |||
| 1214 | config K8_NB | 1224 | config K8_NB |
| 1215 | def_bool y | 1225 | def_bool y |
| 1216 | depends on AGP_AMD64 | 1226 | 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/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 5a289e4de838..a88eba3314d7 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
| @@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv) | |||
| 66 | 66 | ||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static int tiocx_uevent(struct device *dev, char **envp, int num_envp, | 69 | static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 70 | char *buffer, int buffer_size) | ||
| 71 | { | 70 | { |
| 72 | return -ENODEV; | 71 | return -ENODEV; |
| 73 | } | 72 | } |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 89b911e83c04..8f3db32fac8b 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
| @@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev, | |||
| 57 | return tsize; | 57 | return tsize; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | int of_device_uevent(struct device *dev, | 60 | int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 61 | char **envp, int num_envp, char *buffer, int buffer_size) | ||
| 62 | { | 61 | { |
| 63 | struct of_device *ofdev; | 62 | struct of_device *ofdev; |
| 64 | const char *compat; | 63 | const char *compat; |
| 65 | int i = 0, length = 0, seen = 0, cplen, sl; | 64 | int seen = 0, cplen, sl; |
| 66 | 65 | ||
| 67 | if (!dev) | 66 | if (!dev) |
| 68 | return -ENODEV; | 67 | return -ENODEV; |
| 69 | 68 | ||
| 70 | ofdev = to_of_device(dev); | 69 | ofdev = to_of_device(dev); |
| 71 | 70 | ||
| 72 | if (add_uevent_var(envp, num_envp, &i, | 71 | if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name)) |
| 73 | buffer, buffer_size, &length, | ||
| 74 | "OF_NAME=%s", ofdev->node->name)) | ||
| 75 | return -ENOMEM; | 72 | return -ENOMEM; |
| 76 | 73 | ||
| 77 | if (add_uevent_var(envp, num_envp, &i, | 74 | if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type)) |
| 78 | buffer, buffer_size, &length, | ||
| 79 | "OF_TYPE=%s", ofdev->node->type)) | ||
| 80 | return -ENOMEM; | 75 | return -ENOMEM; |
| 81 | 76 | ||
| 82 | /* Since the compatible field can contain pretty much anything | 77 | /* Since the compatible field can contain pretty much anything |
| @@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev, | |||
| 85 | 80 | ||
| 86 | compat = of_get_property(ofdev->node, "compatible", &cplen); | 81 | compat = of_get_property(ofdev->node, "compatible", &cplen); |
| 87 | while (compat && *compat && cplen > 0) { | 82 | while (compat && *compat && cplen > 0) { |
| 88 | if (add_uevent_var(envp, num_envp, &i, | 83 | if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) |
| 89 | buffer, buffer_size, &length, | ||
| 90 | "OF_COMPATIBLE_%d=%s", seen, compat)) | ||
| 91 | return -ENOMEM; | 84 | return -ENOMEM; |
| 92 | 85 | ||
| 93 | sl = strlen (compat) + 1; | 86 | sl = strlen (compat) + 1; |
| @@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev, | |||
| 96 | seen++; | 89 | seen++; |
| 97 | } | 90 | } |
| 98 | 91 | ||
| 99 | if (add_uevent_var(envp, num_envp, &i, | 92 | if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) |
| 100 | buffer, buffer_size, &length, | ||
| 101 | "OF_COMPATIBLE_N=%d", seen)) | ||
| 102 | return -ENOMEM; | 93 | return -ENOMEM; |
| 103 | 94 | ||
| 104 | /* modalias is trickier, we add it in 2 steps */ | 95 | /* modalias is trickier, we add it in 2 steps */ |
| 105 | if (add_uevent_var(envp, num_envp, &i, | 96 | if (add_uevent_var(env, "MODALIAS=")) |
| 106 | buffer, buffer_size, &length, | ||
| 107 | "MODALIAS=")) | ||
| 108 | return -ENOMEM; | 97 | return -ENOMEM; |
| 109 | 98 | sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], | |
| 110 | sl = of_device_get_modalias(ofdev, &buffer[length-1], | 99 | sizeof(env->buf) - env->buflen); |
| 111 | buffer_size-length); | 100 | if (sl >= (sizeof(env->buf) - env->buflen)) |
| 112 | if (sl >= (buffer_size-length)) | ||
| 113 | return -ENOMEM; | 101 | return -ENOMEM; |
| 114 | 102 | env->buflen += sl; | |
| 115 | length += sl; | ||
| 116 | |||
| 117 | envp[i] = NULL; | ||
| 118 | 103 | ||
| 119 | return 0; | 104 | return 0; |
| 120 | } | 105 | } |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb22a3557c4e..19a5656001c0 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) | |||
| 317 | return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); | 317 | return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int vio_hotplug(struct device *dev, char **envp, int num_envp, | 320 | static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env) |
| 321 | char *buffer, int buffer_size) | ||
| 322 | { | 321 | { |
| 323 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 322 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
| 324 | struct device_node *dn; | 323 | struct device_node *dn; |
| 325 | const char *cp; | 324 | const char *cp; |
| 326 | int length; | ||
| 327 | |||
| 328 | if (!num_envp) | ||
| 329 | return -ENOMEM; | ||
| 330 | 325 | ||
| 331 | dn = dev->archdata.of_node; | 326 | dn = dev->archdata.of_node; |
| 332 | if (!dn) | 327 | if (!dn) |
| 333 | return -ENODEV; | 328 | return -ENODEV; |
| 334 | cp = of_get_property(dn, "compatible", &length); | 329 | cp = of_get_property(dn, "compatible", NULL); |
| 335 | if (!cp) | 330 | if (!cp) |
| 336 | return -ENODEV; | 331 | return -ENODEV; |
| 337 | 332 | ||
| 338 | envp[0] = buffer; | 333 | add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp); |
| 339 | length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", | ||
| 340 | vio_dev->type, cp); | ||
| 341 | if ((buffer_size - length) <= 0) | ||
| 342 | return -ENOMEM; | ||
| 343 | envp[1] = NULL; | ||
| 344 | return 0; | 334 | return 0; |
| 345 | } | 335 | } |
| 346 | 336 | ||
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/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 4bb634a17e43..ea0b2c790412 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
| @@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev) | |||
| 437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | static int ps3_system_bus_uevent(struct device *_dev, char **envp, | 440 | static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) |
| 441 | int num_envp, char *buffer, int buffer_size) | ||
| 442 | { | 441 | { |
| 443 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | 442 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 444 | int i = 0, length = 0; | 443 | int i = 0, length = 0; |
| 445 | 444 | ||
| 446 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 445 | if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id)) |
| 447 | &length, "MODALIAS=ps3:%d", | ||
| 448 | dev->match_id)) | ||
| 449 | return -ENOMEM; | 446 | return -ENOMEM; |
| 450 | |||
| 451 | envp[i] = NULL; | ||
| 452 | return 0; | 447 | return 0; |
| 453 | } | 448 | } |
| 454 | 449 | ||
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 04d324cc72d8..cf013cb85ea4 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/block/bsg.c b/block/bsg.c index ed2646827234..b8ddfc66f210 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
| @@ -1010,10 +1010,7 @@ unlock: | |||
| 1010 | } | 1010 | } |
| 1011 | EXPORT_SYMBOL_GPL(bsg_register_queue); | 1011 | EXPORT_SYMBOL_GPL(bsg_register_queue); |
| 1012 | 1012 | ||
| 1013 | static struct cdev bsg_cdev = { | 1013 | static struct cdev bsg_cdev; |
| 1014 | .kobj = {.name = "bsg", }, | ||
| 1015 | .owner = THIS_MODULE, | ||
| 1016 | }; | ||
| 1017 | 1014 | ||
| 1018 | static int __init bsg_init(void) | 1015 | static int __init bsg_init(void) |
| 1019 | { | 1016 | { |
diff --git a/block/elevator.c b/block/elevator.c index c6d153de9fd6..b9c518afe1f8 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -186,7 +186,7 @@ static elevator_t *elevator_alloc(struct request_queue *q, | |||
| 186 | eq->ops = &e->ops; | 186 | eq->ops = &e->ops; |
| 187 | eq->elevator_type = e; | 187 | eq->elevator_type = e; |
| 188 | kobject_init(&eq->kobj); | 188 | kobject_init(&eq->kobj); |
| 189 | snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); | 189 | kobject_set_name(&eq->kobj, "%s", "iosched"); |
| 190 | eq->kobj.ktype = &elv_ktype; | 190 | eq->kobj.ktype = &elv_ktype; |
| 191 | mutex_init(&eq->sysfs_lock); | 191 | mutex_init(&eq->sysfs_lock); |
| 192 | 192 | ||
diff --git a/block/genhd.c b/block/genhd.c index 3af1e7a378d4..e609996f2e76 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -540,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
| 540 | return ((ktype == &ktype_block) || (ktype == &ktype_part)); | 540 | return ((ktype == &ktype_block) || (ktype == &ktype_part)); |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 543 | static int block_uevent(struct kset *kset, struct kobject *kobj, |
| 544 | int num_envp, char *buffer, int buffer_size) | 544 | struct kobj_uevent_env *env) |
| 545 | { | 545 | { |
| 546 | struct kobj_type *ktype = get_ktype(kobj); | 546 | struct kobj_type *ktype = get_ktype(kobj); |
| 547 | struct device *physdev; | 547 | struct device *physdev; |
| 548 | struct gendisk *disk; | 548 | struct gendisk *disk; |
| 549 | struct hd_struct *part; | 549 | struct hd_struct *part; |
| 550 | int length = 0; | ||
| 551 | int i = 0; | ||
| 552 | 550 | ||
| 553 | if (ktype == &ktype_block) { | 551 | if (ktype == &ktype_block) { |
| 554 | disk = container_of(kobj, struct gendisk, kobj); | 552 | disk = container_of(kobj, struct gendisk, kobj); |
| 555 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 553 | add_uevent_var(env, "MINOR=%u", disk->first_minor); |
| 556 | &length, "MINOR=%u", disk->first_minor); | ||
| 557 | } else if (ktype == &ktype_part) { | 554 | } else if (ktype == &ktype_part) { |
| 558 | disk = container_of(kobj->parent, struct gendisk, kobj); | 555 | disk = container_of(kobj->parent, struct gendisk, kobj); |
| 559 | part = container_of(kobj, struct hd_struct, kobj); | 556 | part = container_of(kobj, struct hd_struct, kobj); |
| 560 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 557 | add_uevent_var(env, "MINOR=%u", |
| 561 | &length, "MINOR=%u", | ||
| 562 | disk->first_minor + part->partno); | 558 | disk->first_minor + part->partno); |
| 563 | } else | 559 | } else |
| 564 | return 0; | 560 | return 0; |
| 565 | 561 | ||
| 566 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 562 | add_uevent_var(env, "MAJOR=%u", disk->major); |
| 567 | "MAJOR=%u", disk->major); | ||
| 568 | 563 | ||
| 569 | /* add physical device, backing this device */ | 564 | /* add physical device, backing this device */ |
| 570 | physdev = disk->driverfs_dev; | 565 | physdev = disk->driverfs_dev; |
| 571 | if (physdev) { | 566 | if (physdev) { |
| 572 | char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); | 567 | char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); |
| 573 | 568 | ||
| 574 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 569 | add_uevent_var(env, "PHYSDEVPATH=%s", path); |
| 575 | &length, "PHYSDEVPATH=%s", path); | ||
| 576 | kfree(path); | 570 | kfree(path); |
| 577 | 571 | ||
| 578 | if (physdev->bus) | 572 | if (physdev->bus) |
| 579 | add_uevent_var(envp, num_envp, &i, | 573 | add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name); |
| 580 | buffer, buffer_size, &length, | ||
| 581 | "PHYSDEVBUS=%s", | ||
| 582 | physdev->bus->name); | ||
| 583 | 574 | ||
| 584 | if (physdev->driver) | 575 | if (physdev->driver) |
| 585 | add_uevent_var(envp, num_envp, &i, | 576 | add_uevent_var(env, physdev->driver->name); |
| 586 | buffer, buffer_size, &length, | ||
| 587 | "PHYSDEVDRIVER=%s", | ||
| 588 | physdev->driver->name); | ||
| 589 | } | 577 | } |
| 590 | 578 | ||
| 591 | /* terminate, set to next free slot, shrink available space */ | ||
| 592 | envp[i] = NULL; | ||
| 593 | envp = &envp[i]; | ||
| 594 | num_envp -= i; | ||
| 595 | buffer = &buffer[length]; | ||
| 596 | buffer_size -= length; | ||
| 597 | |||
| 598 | return 0; | 579 | return 0; |
| 599 | } | 580 | } |
| 600 | 581 | ||
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index cd9d2c5d91ae..d875673e76cd 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -1854,7 +1854,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | |||
| 1854 | 1854 | ||
| 1855 | init_timer(&q->unplug_timer); | 1855 | init_timer(&q->unplug_timer); |
| 1856 | 1856 | ||
| 1857 | snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); | 1857 | kobject_set_name(&q->kobj, "%s", "queue"); |
| 1858 | q->kobj.ktype = &queue_ktype; | 1858 | q->kobj.ktype = &queue_ktype; |
| 1859 | kobject_init(&q->kobj); | 1859 | kobject_init(&q->kobj); |
| 1860 | 1860 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index feab124d8e05..cbfc81579c9a 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -194,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) | |||
| 194 | 194 | ||
| 195 | if (!device->flags.power_manageable) { | 195 | if (!device->flags.power_manageable) { |
| 196 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", | 196 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", |
| 197 | device->dev.kobj.name)); | 197 | kobject_name(&device->dev.kobj))); |
| 198 | return -ENODEV; | 198 | return -ENODEV; |
| 199 | } | 199 | } |
| 200 | /* | 200 | /* |
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/acpi/scan.c b/drivers/acpi/scan.c index 64620d668742..5b4d462117cf 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -319,16 +319,18 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) | |||
| 319 | return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); | 319 | return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | static int acpi_device_uevent(struct device *dev, char **envp, int num_envp, | 322 | static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 323 | char *buffer, int buffer_size) | ||
| 324 | { | 323 | { |
| 325 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 324 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
| 325 | int len; | ||
| 326 | 326 | ||
| 327 | strcpy(buffer, "MODALIAS="); | 327 | if (add_uevent_var(env, "MODALIAS=")) |
| 328 | if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) { | 328 | return -ENOMEM; |
| 329 | envp[0] = buffer; | 329 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], |
| 330 | envp[1] = NULL; | 330 | sizeof(env->buf) - env->buflen); |
| 331 | } | 331 | if (len >= (sizeof(env->buf) - env->buflen)) |
| 332 | return -ENOMEM; | ||
| 333 | env->buflen += len; | ||
| 332 | return 0; | 334 | return 0; |
| 333 | } | 335 | } |
| 334 | 336 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d05891f16282..b8a2095cb5ee 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -316,7 +316,7 @@ static int acpi_video_output_get(struct output_device *od) | |||
| 316 | { | 316 | { |
| 317 | unsigned long state; | 317 | unsigned long state; |
| 318 | struct acpi_video_device *vd = | 318 | struct acpi_video_device *vd = |
| 319 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | 319 | (struct acpi_video_device *)dev_get_drvdata(&od->dev); |
| 320 | acpi_video_device_get_state(vd, &state); | 320 | acpi_video_device_get_state(vd, &state); |
| 321 | return (int)state; | 321 | return (int)state; |
| 322 | } | 322 | } |
| @@ -325,7 +325,7 @@ static int acpi_video_output_set(struct output_device *od) | |||
| 325 | { | 325 | { |
| 326 | unsigned long state = od->request_state; | 326 | unsigned long state = od->request_state; |
| 327 | struct acpi_video_device *vd= | 327 | struct acpi_video_device *vd= |
| 328 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | 328 | (struct acpi_video_device *)dev_get_drvdata(&od->dev); |
| 329 | return acpi_video_device_set_state(vd, state); | 329 | return acpi_video_device_set_state(vd, state); |
| 330 | } | 330 | } |
| 331 | 331 | ||
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 268e301775fc..6b94fb7be5f2 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
| @@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv) | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #ifdef CONFIG_HOTPLUG | 46 | #ifdef CONFIG_HOTPLUG |
| 47 | static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz) | 47 | static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 48 | { | 48 | { |
| 49 | struct amba_device *pcdev = to_amba_device(dev); | 49 | struct amba_device *pcdev = to_amba_device(dev); |
| 50 | int retval = 0, i = 0, len = 0; | 50 | int retval = 0; |
| 51 | 51 | ||
| 52 | retval = add_uevent_var(envp, nr_env, &i, | 52 | retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); |
| 53 | buf, bufsz, &len, | ||
| 54 | "AMBA_ID=%08x", pcdev->periphid); | ||
| 55 | envp[i] = NULL; | ||
| 56 | return retval; | 53 | return retval; |
| 57 | } | 54 | } |
| 58 | #else | 55 | #else |
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 5d6312e33490..d7da109c24fd 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | menu "Generic Driver Options" | 1 | menu "Generic Driver Options" |
| 2 | 2 | ||
| 3 | config UEVENT_HELPER_PATH | ||
| 4 | string "path to uevent helper" | ||
| 5 | depends on HOTPLUG | ||
| 6 | default "/sbin/hotplug" | ||
| 7 | help | ||
| 8 | Path to uevent helper program forked by the kernel for | ||
| 9 | every uevent. | ||
| 10 | |||
| 3 | config STANDALONE | 11 | config STANDALONE |
| 4 | bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL | 12 | bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL |
| 5 | default y | 13 | default y |
diff --git a/drivers/base/base.h b/drivers/base/base.h index 47eb02d9f1af..10b2fb6c9ce6 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
| @@ -18,8 +18,6 @@ extern int attribute_container_init(void); | |||
| 18 | extern int bus_add_device(struct device * dev); | 18 | extern int bus_add_device(struct device * dev); |
| 19 | extern void bus_attach_device(struct device * dev); | 19 | extern void bus_attach_device(struct device * dev); |
| 20 | extern void bus_remove_device(struct device * dev); | 20 | extern void bus_remove_device(struct device * dev); |
| 21 | extern struct bus_type *get_bus(struct bus_type * bus); | ||
| 22 | extern void put_bus(struct bus_type * bus); | ||
| 23 | 21 | ||
| 24 | extern int bus_add_driver(struct device_driver *); | 22 | extern int bus_add_driver(struct device_driver *); |
| 25 | extern void bus_remove_driver(struct device_driver *); | 23 | extern void bus_remove_driver(struct device_driver *); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 61c67526a656..9a19b071c573 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -30,6 +30,17 @@ | |||
| 30 | static int __must_check bus_rescan_devices_helper(struct device *dev, | 30 | static int __must_check bus_rescan_devices_helper(struct device *dev, |
| 31 | void *data); | 31 | void *data); |
| 32 | 32 | ||
| 33 | static struct bus_type *bus_get(struct bus_type *bus) | ||
| 34 | { | ||
| 35 | return bus ? container_of(kset_get(&bus->subsys), | ||
| 36 | struct bus_type, subsys) : NULL; | ||
| 37 | } | ||
| 38 | |||
| 39 | static void bus_put(struct bus_type *bus) | ||
| 40 | { | ||
| 41 | kset_put(&bus->subsys); | ||
| 42 | } | ||
| 43 | |||
| 33 | static ssize_t | 44 | static ssize_t |
| 34 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 45 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
| 35 | { | 46 | { |
| @@ -78,7 +89,7 @@ static void driver_release(struct kobject * kobj) | |||
| 78 | */ | 89 | */ |
| 79 | } | 90 | } |
| 80 | 91 | ||
| 81 | static struct kobj_type ktype_driver = { | 92 | static struct kobj_type driver_ktype = { |
| 82 | .sysfs_ops = &driver_sysfs_ops, | 93 | .sysfs_ops = &driver_sysfs_ops, |
| 83 | .release = driver_release, | 94 | .release = driver_release, |
| 84 | }; | 95 | }; |
| @@ -122,9 +133,9 @@ static struct sysfs_ops bus_sysfs_ops = { | |||
| 122 | int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) | 133 | int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) |
| 123 | { | 134 | { |
| 124 | int error; | 135 | int error; |
| 125 | if (get_bus(bus)) { | 136 | if (bus_get(bus)) { |
| 126 | error = sysfs_create_file(&bus->subsys.kobj, &attr->attr); | 137 | error = sysfs_create_file(&bus->subsys.kobj, &attr->attr); |
| 127 | put_bus(bus); | 138 | bus_put(bus); |
| 128 | } else | 139 | } else |
| 129 | error = -EINVAL; | 140 | error = -EINVAL; |
| 130 | return error; | 141 | return error; |
| @@ -132,9 +143,9 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr) | |||
| 132 | 143 | ||
| 133 | void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) | 144 | void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) |
| 134 | { | 145 | { |
| 135 | if (get_bus(bus)) { | 146 | if (bus_get(bus)) { |
| 136 | sysfs_remove_file(&bus->subsys.kobj, &attr->attr); | 147 | sysfs_remove_file(&bus->subsys.kobj, &attr->attr); |
| 137 | put_bus(bus); | 148 | bus_put(bus); |
| 138 | } | 149 | } |
| 139 | } | 150 | } |
| 140 | 151 | ||
| @@ -172,7 +183,7 @@ static int driver_helper(struct device *dev, void *data) | |||
| 172 | static ssize_t driver_unbind(struct device_driver *drv, | 183 | static ssize_t driver_unbind(struct device_driver *drv, |
| 173 | const char *buf, size_t count) | 184 | const char *buf, size_t count) |
| 174 | { | 185 | { |
| 175 | struct bus_type *bus = get_bus(drv->bus); | 186 | struct bus_type *bus = bus_get(drv->bus); |
| 176 | struct device *dev; | 187 | struct device *dev; |
| 177 | int err = -ENODEV; | 188 | int err = -ENODEV; |
| 178 | 189 | ||
| @@ -186,7 +197,7 @@ static ssize_t driver_unbind(struct device_driver *drv, | |||
| 186 | err = count; | 197 | err = count; |
| 187 | } | 198 | } |
| 188 | put_device(dev); | 199 | put_device(dev); |
| 189 | put_bus(bus); | 200 | bus_put(bus); |
| 190 | return err; | 201 | return err; |
| 191 | } | 202 | } |
| 192 | static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); | 203 | static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); |
| @@ -199,7 +210,7 @@ static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); | |||
| 199 | static ssize_t driver_bind(struct device_driver *drv, | 210 | static ssize_t driver_bind(struct device_driver *drv, |
| 200 | const char *buf, size_t count) | 211 | const char *buf, size_t count) |
| 201 | { | 212 | { |
| 202 | struct bus_type *bus = get_bus(drv->bus); | 213 | struct bus_type *bus = bus_get(drv->bus); |
| 203 | struct device *dev; | 214 | struct device *dev; |
| 204 | int err = -ENODEV; | 215 | int err = -ENODEV; |
| 205 | 216 | ||
| @@ -219,7 +230,7 @@ static ssize_t driver_bind(struct device_driver *drv, | |||
| 219 | err = -ENODEV; | 230 | err = -ENODEV; |
| 220 | } | 231 | } |
| 221 | put_device(dev); | 232 | put_device(dev); |
| 222 | put_bus(bus); | 233 | bus_put(bus); |
| 223 | return err; | 234 | return err; |
| 224 | } | 235 | } |
| 225 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); | 236 | static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); |
| @@ -430,7 +441,7 @@ static inline void remove_deprecated_bus_links(struct device *dev) { } | |||
| 430 | */ | 441 | */ |
| 431 | int bus_add_device(struct device * dev) | 442 | int bus_add_device(struct device * dev) |
| 432 | { | 443 | { |
| 433 | struct bus_type * bus = get_bus(dev->bus); | 444 | struct bus_type * bus = bus_get(dev->bus); |
| 434 | int error = 0; | 445 | int error = 0; |
| 435 | 446 | ||
| 436 | if (bus) { | 447 | if (bus) { |
| @@ -459,7 +470,7 @@ out_subsys: | |||
| 459 | out_id: | 470 | out_id: |
| 460 | device_remove_attrs(bus, dev); | 471 | device_remove_attrs(bus, dev); |
| 461 | out_put: | 472 | out_put: |
| 462 | put_bus(dev->bus); | 473 | bus_put(dev->bus); |
| 463 | return error; | 474 | return error; |
| 464 | } | 475 | } |
| 465 | 476 | ||
| @@ -509,7 +520,7 @@ void bus_remove_device(struct device * dev) | |||
| 509 | } | 520 | } |
| 510 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 521 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
| 511 | device_release_driver(dev); | 522 | device_release_driver(dev); |
| 512 | put_bus(dev->bus); | 523 | bus_put(dev->bus); |
| 513 | } | 524 | } |
| 514 | } | 525 | } |
| 515 | 526 | ||
| @@ -568,32 +579,29 @@ static void remove_bind_files(struct device_driver *drv) | |||
| 568 | driver_remove_file(drv, &driver_attr_unbind); | 579 | driver_remove_file(drv, &driver_attr_unbind); |
| 569 | } | 580 | } |
| 570 | 581 | ||
| 582 | static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe); | ||
| 583 | static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO, | ||
| 584 | show_drivers_autoprobe, store_drivers_autoprobe); | ||
| 585 | |||
| 571 | static int add_probe_files(struct bus_type *bus) | 586 | static int add_probe_files(struct bus_type *bus) |
| 572 | { | 587 | { |
| 573 | int retval; | 588 | int retval; |
| 574 | 589 | ||
| 575 | bus->drivers_probe_attr.attr.name = "drivers_probe"; | 590 | retval = bus_create_file(bus, &bus_attr_drivers_probe); |
| 576 | bus->drivers_probe_attr.attr.mode = S_IWUSR; | ||
| 577 | bus->drivers_probe_attr.store = store_drivers_probe; | ||
| 578 | retval = bus_create_file(bus, &bus->drivers_probe_attr); | ||
| 579 | if (retval) | 591 | if (retval) |
| 580 | goto out; | 592 | goto out; |
| 581 | 593 | ||
| 582 | bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; | 594 | retval = bus_create_file(bus, &bus_attr_drivers_autoprobe); |
| 583 | bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; | ||
| 584 | bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; | ||
| 585 | bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; | ||
| 586 | retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); | ||
| 587 | if (retval) | 595 | if (retval) |
| 588 | bus_remove_file(bus, &bus->drivers_probe_attr); | 596 | bus_remove_file(bus, &bus_attr_drivers_probe); |
| 589 | out: | 597 | out: |
| 590 | return retval; | 598 | return retval; |
| 591 | } | 599 | } |
| 592 | 600 | ||
| 593 | static void remove_probe_files(struct bus_type *bus) | 601 | static void remove_probe_files(struct bus_type *bus) |
| 594 | { | 602 | { |
| 595 | bus_remove_file(bus, &bus->drivers_autoprobe_attr); | 603 | bus_remove_file(bus, &bus_attr_drivers_autoprobe); |
| 596 | bus_remove_file(bus, &bus->drivers_probe_attr); | 604 | bus_remove_file(bus, &bus_attr_drivers_probe); |
| 597 | } | 605 | } |
| 598 | #else | 606 | #else |
| 599 | static inline int add_bind_files(struct device_driver *drv) { return 0; } | 607 | static inline int add_bind_files(struct device_driver *drv) { return 0; } |
| @@ -602,6 +610,17 @@ static inline int add_probe_files(struct bus_type *bus) { return 0; } | |||
| 602 | static inline void remove_probe_files(struct bus_type *bus) {} | 610 | static inline void remove_probe_files(struct bus_type *bus) {} |
| 603 | #endif | 611 | #endif |
| 604 | 612 | ||
| 613 | static ssize_t driver_uevent_store(struct device_driver *drv, | ||
| 614 | const char *buf, size_t count) | ||
| 615 | { | ||
| 616 | enum kobject_action action; | ||
| 617 | |||
| 618 | if (kobject_action_type(buf, count, &action) == 0) | ||
| 619 | kobject_uevent(&drv->kobj, action); | ||
| 620 | return count; | ||
| 621 | } | ||
| 622 | static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); | ||
| 623 | |||
| 605 | /** | 624 | /** |
| 606 | * bus_add_driver - Add a driver to the bus. | 625 | * bus_add_driver - Add a driver to the bus. |
| 607 | * @drv: driver. | 626 | * @drv: driver. |
| @@ -609,7 +628,7 @@ static inline void remove_probe_files(struct bus_type *bus) {} | |||
| 609 | */ | 628 | */ |
| 610 | int bus_add_driver(struct device_driver *drv) | 629 | int bus_add_driver(struct device_driver *drv) |
| 611 | { | 630 | { |
| 612 | struct bus_type * bus = get_bus(drv->bus); | 631 | struct bus_type * bus = bus_get(drv->bus); |
| 613 | int error = 0; | 632 | int error = 0; |
| 614 | 633 | ||
| 615 | if (!bus) | 634 | if (!bus) |
| @@ -632,6 +651,11 @@ int bus_add_driver(struct device_driver *drv) | |||
| 632 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); | 651 | klist_add_tail(&drv->knode_bus, &bus->klist_drivers); |
| 633 | module_add_driver(drv->owner, drv); | 652 | module_add_driver(drv->owner, drv); |
| 634 | 653 | ||
| 654 | error = driver_create_file(drv, &driver_attr_uevent); | ||
| 655 | if (error) { | ||
| 656 | printk(KERN_ERR "%s: uevent attr (%s) failed\n", | ||
| 657 | __FUNCTION__, drv->name); | ||
| 658 | } | ||
| 635 | error = driver_add_attrs(bus, drv); | 659 | error = driver_add_attrs(bus, drv); |
| 636 | if (error) { | 660 | if (error) { |
| 637 | /* How the hell do we get out of this pickle? Give up */ | 661 | /* How the hell do we get out of this pickle? Give up */ |
| @@ -649,7 +673,7 @@ int bus_add_driver(struct device_driver *drv) | |||
| 649 | out_unregister: | 673 | out_unregister: |
| 650 | kobject_unregister(&drv->kobj); | 674 | kobject_unregister(&drv->kobj); |
| 651 | out_put_bus: | 675 | out_put_bus: |
| 652 | put_bus(bus); | 676 | bus_put(bus); |
| 653 | return error; | 677 | return error; |
| 654 | } | 678 | } |
| 655 | 679 | ||
| @@ -669,12 +693,13 @@ void bus_remove_driver(struct device_driver * drv) | |||
| 669 | 693 | ||
| 670 | remove_bind_files(drv); | 694 | remove_bind_files(drv); |
| 671 | driver_remove_attrs(drv->bus, drv); | 695 | driver_remove_attrs(drv->bus, drv); |
| 696 | driver_remove_file(drv, &driver_attr_uevent); | ||
| 672 | klist_remove(&drv->knode_bus); | 697 | klist_remove(&drv->knode_bus); |
| 673 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 698 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
| 674 | driver_detach(drv); | 699 | driver_detach(drv); |
| 675 | module_remove_driver(drv); | 700 | module_remove_driver(drv); |
| 676 | kobject_unregister(&drv->kobj); | 701 | kobject_unregister(&drv->kobj); |
| 677 | put_bus(drv->bus); | 702 | bus_put(drv->bus); |
| 678 | } | 703 | } |
| 679 | 704 | ||
| 680 | 705 | ||
| @@ -729,18 +754,6 @@ int device_reprobe(struct device *dev) | |||
| 729 | } | 754 | } |
| 730 | EXPORT_SYMBOL_GPL(device_reprobe); | 755 | EXPORT_SYMBOL_GPL(device_reprobe); |
| 731 | 756 | ||
| 732 | struct bus_type *get_bus(struct bus_type *bus) | ||
| 733 | { | ||
| 734 | return bus ? container_of(subsys_get(&bus->subsys), | ||
| 735 | struct bus_type, subsys) : NULL; | ||
| 736 | } | ||
| 737 | |||
| 738 | void put_bus(struct bus_type * bus) | ||
| 739 | { | ||
| 740 | subsys_put(&bus->subsys); | ||
| 741 | } | ||
| 742 | |||
| 743 | |||
| 744 | /** | 757 | /** |
| 745 | * find_bus - locate bus by name. | 758 | * find_bus - locate bus by name. |
| 746 | * @name: name of bus. | 759 | * @name: name of bus. |
| @@ -808,6 +821,17 @@ static void klist_devices_put(struct klist_node *n) | |||
| 808 | put_device(dev); | 821 | put_device(dev); |
| 809 | } | 822 | } |
| 810 | 823 | ||
| 824 | static ssize_t bus_uevent_store(struct bus_type *bus, | ||
| 825 | const char *buf, size_t count) | ||
| 826 | { | ||
| 827 | enum kobject_action action; | ||
| 828 | |||
| 829 | if (kobject_action_type(buf, count, &action) == 0) | ||
| 830 | kobject_uevent(&bus->subsys.kobj, action); | ||
| 831 | return count; | ||
| 832 | } | ||
| 833 | static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); | ||
| 834 | |||
| 811 | /** | 835 | /** |
| 812 | * bus_register - register a bus with the system. | 836 | * bus_register - register a bus with the system. |
| 813 | * @bus: bus. | 837 | * @bus: bus. |
| @@ -826,11 +850,16 @@ int bus_register(struct bus_type * bus) | |||
| 826 | if (retval) | 850 | if (retval) |
| 827 | goto out; | 851 | goto out; |
| 828 | 852 | ||
| 829 | subsys_set_kset(bus, bus_subsys); | 853 | bus->subsys.kobj.kset = &bus_subsys; |
| 854 | |||
| 830 | retval = subsystem_register(&bus->subsys); | 855 | retval = subsystem_register(&bus->subsys); |
| 831 | if (retval) | 856 | if (retval) |
| 832 | goto out; | 857 | goto out; |
| 833 | 858 | ||
| 859 | retval = bus_create_file(bus, &bus_attr_uevent); | ||
| 860 | if (retval) | ||
| 861 | goto bus_uevent_fail; | ||
| 862 | |||
| 834 | kobject_set_name(&bus->devices.kobj, "devices"); | 863 | kobject_set_name(&bus->devices.kobj, "devices"); |
| 835 | bus->devices.kobj.parent = &bus->subsys.kobj; | 864 | bus->devices.kobj.parent = &bus->subsys.kobj; |
| 836 | retval = kset_register(&bus->devices); | 865 | retval = kset_register(&bus->devices); |
| @@ -839,7 +868,7 @@ int bus_register(struct bus_type * bus) | |||
| 839 | 868 | ||
| 840 | kobject_set_name(&bus->drivers.kobj, "drivers"); | 869 | kobject_set_name(&bus->drivers.kobj, "drivers"); |
| 841 | bus->drivers.kobj.parent = &bus->subsys.kobj; | 870 | bus->drivers.kobj.parent = &bus->subsys.kobj; |
| 842 | bus->drivers.ktype = &ktype_driver; | 871 | bus->drivers.ktype = &driver_ktype; |
| 843 | retval = kset_register(&bus->drivers); | 872 | retval = kset_register(&bus->drivers); |
| 844 | if (retval) | 873 | if (retval) |
| 845 | goto bus_drivers_fail; | 874 | goto bus_drivers_fail; |
| @@ -866,6 +895,8 @@ bus_probe_files_fail: | |||
| 866 | bus_drivers_fail: | 895 | bus_drivers_fail: |
| 867 | kset_unregister(&bus->devices); | 896 | kset_unregister(&bus->devices); |
| 868 | bus_devices_fail: | 897 | bus_devices_fail: |
| 898 | bus_remove_file(bus, &bus_attr_uevent); | ||
| 899 | bus_uevent_fail: | ||
| 869 | subsystem_unregister(&bus->subsys); | 900 | subsystem_unregister(&bus->subsys); |
| 870 | out: | 901 | out: |
| 871 | return retval; | 902 | return retval; |
| @@ -876,7 +907,7 @@ out: | |||
| 876 | * @bus: bus. | 907 | * @bus: bus. |
| 877 | * | 908 | * |
| 878 | * Unregister the child subsystems and the bus itself. | 909 | * Unregister the child subsystems and the bus itself. |
| 879 | * Finally, we call put_bus() to release the refcount | 910 | * Finally, we call bus_put() to release the refcount |
| 880 | */ | 911 | */ |
| 881 | void bus_unregister(struct bus_type * bus) | 912 | void bus_unregister(struct bus_type * bus) |
| 882 | { | 913 | { |
| @@ -885,6 +916,7 @@ void bus_unregister(struct bus_type * bus) | |||
| 885 | remove_probe_files(bus); | 916 | remove_probe_files(bus); |
| 886 | kset_unregister(&bus->drivers); | 917 | kset_unregister(&bus->drivers); |
| 887 | kset_unregister(&bus->devices); | 918 | kset_unregister(&bus->devices); |
| 919 | bus_remove_file(bus, &bus_attr_uevent); | ||
| 888 | subsystem_unregister(&bus->subsys); | 920 | subsystem_unregister(&bus->subsys); |
| 889 | } | 921 | } |
| 890 | 922 | ||
diff --git a/drivers/base/class.c b/drivers/base/class.c index 4d2222618b78..a863bb091e11 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
| @@ -65,13 +65,13 @@ static struct sysfs_ops class_sysfs_ops = { | |||
| 65 | .store = class_attr_store, | 65 | .store = class_attr_store, |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | static struct kobj_type ktype_class = { | 68 | static struct kobj_type class_ktype = { |
| 69 | .sysfs_ops = &class_sysfs_ops, | 69 | .sysfs_ops = &class_sysfs_ops, |
| 70 | .release = class_release, | 70 | .release = class_release, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | /* Hotplug events for classes go to the class_obj subsys */ | 73 | /* Hotplug events for classes go to the class_obj subsys */ |
| 74 | static decl_subsys(class, &ktype_class, NULL); | 74 | static decl_subsys(class, &class_ktype, NULL); |
| 75 | 75 | ||
| 76 | 76 | ||
| 77 | int class_create_file(struct class * cls, const struct class_attribute * attr) | 77 | int class_create_file(struct class * cls, const struct class_attribute * attr) |
| @@ -93,14 +93,14 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr) | |||
| 93 | static struct class *class_get(struct class *cls) | 93 | static struct class *class_get(struct class *cls) |
| 94 | { | 94 | { |
| 95 | if (cls) | 95 | if (cls) |
| 96 | return container_of(subsys_get(&cls->subsys), struct class, subsys); | 96 | return container_of(kset_get(&cls->subsys), struct class, subsys); |
| 97 | return NULL; | 97 | return NULL; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static void class_put(struct class * cls) | 100 | static void class_put(struct class * cls) |
| 101 | { | 101 | { |
| 102 | if (cls) | 102 | if (cls) |
| 103 | subsys_put(&cls->subsys); | 103 | kset_put(&cls->subsys); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | 106 | ||
| @@ -149,7 +149,7 @@ int class_register(struct class * cls) | |||
| 149 | if (error) | 149 | if (error) |
| 150 | return error; | 150 | return error; |
| 151 | 151 | ||
| 152 | subsys_set_kset(cls, class_subsys); | 152 | cls->subsys.kobj.kset = &class_subsys; |
| 153 | 153 | ||
| 154 | error = subsystem_register(&cls->subsys); | 154 | error = subsystem_register(&cls->subsys); |
| 155 | if (!error) { | 155 | if (!error) { |
| @@ -180,8 +180,7 @@ static void class_device_create_release(struct class_device *class_dev) | |||
| 180 | 180 | ||
| 181 | /* needed to allow these devices to have parent class devices */ | 181 | /* needed to allow these devices to have parent class devices */ |
| 182 | static int class_device_create_uevent(struct class_device *class_dev, | 182 | static int class_device_create_uevent(struct class_device *class_dev, |
| 183 | char **envp, int num_envp, | 183 | struct kobj_uevent_env *env) |
| 184 | char *buffer, int buffer_size) | ||
| 185 | { | 184 | { |
| 186 | pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); | 185 | pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id); |
| 187 | return 0; | 186 | return 0; |
| @@ -324,7 +323,7 @@ static void class_dev_release(struct kobject * kobj) | |||
| 324 | } | 323 | } |
| 325 | } | 324 | } |
| 326 | 325 | ||
| 327 | static struct kobj_type ktype_class_device = { | 326 | static struct kobj_type class_device_ktype = { |
| 328 | .sysfs_ops = &class_dev_sysfs_ops, | 327 | .sysfs_ops = &class_dev_sysfs_ops, |
| 329 | .release = class_dev_release, | 328 | .release = class_dev_release, |
| 330 | }; | 329 | }; |
| @@ -333,7 +332,7 @@ static int class_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
| 333 | { | 332 | { |
| 334 | struct kobj_type *ktype = get_ktype(kobj); | 333 | struct kobj_type *ktype = get_ktype(kobj); |
| 335 | 334 | ||
| 336 | if (ktype == &ktype_class_device) { | 335 | if (ktype == &class_device_ktype) { |
| 337 | struct class_device *class_dev = to_class_dev(kobj); | 336 | struct class_device *class_dev = to_class_dev(kobj); |
| 338 | if (class_dev->class) | 337 | if (class_dev->class) |
| 339 | return 1; | 338 | return 1; |
| @@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd) | |||
| 403 | { } | 402 | { } |
| 404 | #endif | 403 | #endif |
| 405 | 404 | ||
| 406 | static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 405 | static int class_uevent(struct kset *kset, struct kobject *kobj, |
| 407 | int num_envp, char *buffer, int buffer_size) | 406 | struct kobj_uevent_env *env) |
| 408 | { | 407 | { |
| 409 | struct class_device *class_dev = to_class_dev(kobj); | 408 | struct class_device *class_dev = to_class_dev(kobj); |
| 410 | struct device *dev = class_dev->dev; | 409 | struct device *dev = class_dev->dev; |
| 411 | int i = 0; | ||
| 412 | int length = 0; | ||
| 413 | int retval = 0; | 410 | int retval = 0; |
| 414 | 411 | ||
| 415 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); | 412 | pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); |
| 416 | 413 | ||
| 417 | if (MAJOR(class_dev->devt)) { | 414 | if (MAJOR(class_dev->devt)) { |
| 418 | add_uevent_var(envp, num_envp, &i, | 415 | add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt)); |
| 419 | buffer, buffer_size, &length, | ||
| 420 | "MAJOR=%u", MAJOR(class_dev->devt)); | ||
| 421 | 416 | ||
| 422 | add_uevent_var(envp, num_envp, &i, | 417 | add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt)); |
| 423 | buffer, buffer_size, &length, | ||
| 424 | "MINOR=%u", MINOR(class_dev->devt)); | ||
| 425 | } | 418 | } |
| 426 | 419 | ||
| 427 | if (dev) { | 420 | if (dev) { |
| 428 | const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); | 421 | const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); |
| 429 | if (path) { | 422 | if (path) { |
| 430 | add_uevent_var(envp, num_envp, &i, | 423 | add_uevent_var(env, "PHYSDEVPATH=%s", path); |
| 431 | buffer, buffer_size, &length, | ||
| 432 | "PHYSDEVPATH=%s", path); | ||
| 433 | kfree(path); | 424 | kfree(path); |
| 434 | } | 425 | } |
| 435 | 426 | ||
| 436 | if (dev->bus) | 427 | if (dev->bus) |
| 437 | add_uevent_var(envp, num_envp, &i, | 428 | add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); |
| 438 | buffer, buffer_size, &length, | ||
| 439 | "PHYSDEVBUS=%s", dev->bus->name); | ||
| 440 | 429 | ||
| 441 | if (dev->driver) | 430 | if (dev->driver) |
| 442 | add_uevent_var(envp, num_envp, &i, | 431 | add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); |
| 443 | buffer, buffer_size, &length, | ||
| 444 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
| 445 | } | 432 | } |
| 446 | 433 | ||
| 447 | /* terminate, set to next free slot, shrink available space */ | ||
| 448 | envp[i] = NULL; | ||
| 449 | envp = &envp[i]; | ||
| 450 | num_envp -= i; | ||
| 451 | buffer = &buffer[length]; | ||
| 452 | buffer_size -= length; | ||
| 453 | |||
| 454 | if (class_dev->uevent) { | 434 | if (class_dev->uevent) { |
| 455 | /* have the class device specific function add its stuff */ | 435 | /* have the class device specific function add its stuff */ |
| 456 | retval = class_dev->uevent(class_dev, envp, num_envp, | 436 | retval = class_dev->uevent(class_dev, env); |
| 457 | buffer, buffer_size); | ||
| 458 | if (retval) | 437 | if (retval) |
| 459 | pr_debug("class_dev->uevent() returned %d\n", retval); | 438 | pr_debug("class_dev->uevent() returned %d\n", retval); |
| 460 | } else if (class_dev->class->uevent) { | 439 | } else if (class_dev->class->uevent) { |
| 461 | /* have the class specific function add its stuff */ | 440 | /* have the class specific function add its stuff */ |
| 462 | retval = class_dev->class->uevent(class_dev, envp, num_envp, | 441 | retval = class_dev->class->uevent(class_dev, env); |
| 463 | buffer, buffer_size); | ||
| 464 | if (retval) | 442 | if (retval) |
| 465 | pr_debug("class->uevent() returned %d\n", retval); | 443 | pr_debug("class->uevent() returned %d\n", retval); |
| 466 | } | 444 | } |
| @@ -474,7 +452,7 @@ static struct kset_uevent_ops class_uevent_ops = { | |||
| 474 | .uevent = class_uevent, | 452 | .uevent = class_uevent, |
| 475 | }; | 453 | }; |
| 476 | 454 | ||
| 477 | static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops); | 455 | static decl_subsys(class_obj, &class_device_ktype, &class_uevent_ops); |
| 478 | 456 | ||
| 479 | 457 | ||
| 480 | static int class_device_add_attrs(struct class_device * cd) | 458 | static int class_device_add_attrs(struct class_device * cd) |
| @@ -883,7 +861,7 @@ int __init classes_init(void) | |||
| 883 | 861 | ||
| 884 | /* ick, this is ugly, the things we go through to keep from showing up | 862 | /* ick, this is ugly, the things we go through to keep from showing up |
| 885 | * in sysfs... */ | 863 | * in sysfs... */ |
| 886 | subsystem_init(&class_obj_subsys); | 864 | kset_init(&class_obj_subsys); |
| 887 | if (!class_obj_subsys.kobj.parent) | 865 | if (!class_obj_subsys.kobj.parent) |
| 888 | class_obj_subsys.kobj.parent = &class_obj_subsys.kobj; | 866 | class_obj_subsys.kobj.parent = &class_obj_subsys.kobj; |
| 889 | return 0; | 867 | return 0; |
diff --git a/drivers/base/core.c b/drivers/base/core.c index ec86d6fc2360..c1343414d285 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -108,7 +108,7 @@ static void device_release(struct kobject * kobj) | |||
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static struct kobj_type ktype_device = { | 111 | static struct kobj_type device_ktype = { |
| 112 | .release = device_release, | 112 | .release = device_release, |
| 113 | .sysfs_ops = &dev_sysfs_ops, | 113 | .sysfs_ops = &dev_sysfs_ops, |
| 114 | }; | 114 | }; |
| @@ -118,7 +118,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) | |||
| 118 | { | 118 | { |
| 119 | struct kobj_type *ktype = get_ktype(kobj); | 119 | struct kobj_type *ktype = get_ktype(kobj); |
| 120 | 120 | ||
| 121 | if (ktype == &ktype_device) { | 121 | if (ktype == &device_ktype) { |
| 122 | struct device *dev = to_dev(kobj); | 122 | struct device *dev = to_dev(kobj); |
| 123 | if (dev->uevent_suppress) | 123 | if (dev->uevent_suppress) |
| 124 | return 0; | 124 | return 0; |
| @@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj) | |||
| 141 | return NULL; | 141 | return NULL; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 144 | static int dev_uevent(struct kset *kset, struct kobject *kobj, |
| 145 | int num_envp, char *buffer, int buffer_size) | 145 | struct kobj_uevent_env *env) |
| 146 | { | 146 | { |
| 147 | struct device *dev = to_dev(kobj); | 147 | struct device *dev = to_dev(kobj); |
| 148 | int i = 0; | ||
| 149 | int length = 0; | ||
| 150 | int retval = 0; | 148 | int retval = 0; |
| 151 | 149 | ||
| 152 | /* add the major/minor if present */ | 150 | /* add the major/minor if present */ |
| 153 | if (MAJOR(dev->devt)) { | 151 | if (MAJOR(dev->devt)) { |
| 154 | add_uevent_var(envp, num_envp, &i, | 152 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); |
| 155 | buffer, buffer_size, &length, | 153 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); |
| 156 | "MAJOR=%u", MAJOR(dev->devt)); | ||
| 157 | add_uevent_var(envp, num_envp, &i, | ||
| 158 | buffer, buffer_size, &length, | ||
| 159 | "MINOR=%u", MINOR(dev->devt)); | ||
| 160 | } | 154 | } |
| 161 | 155 | ||
| 162 | if (dev->type && dev->type->name) | 156 | if (dev->type && dev->type->name) |
| 163 | add_uevent_var(envp, num_envp, &i, | 157 | add_uevent_var(env, "DEVTYPE=%s", dev->type->name); |
| 164 | buffer, buffer_size, &length, | ||
| 165 | "DEVTYPE=%s", dev->type->name); | ||
| 166 | 158 | ||
| 167 | if (dev->driver) | 159 | if (dev->driver) |
| 168 | add_uevent_var(envp, num_envp, &i, | 160 | add_uevent_var(env, "DRIVER=%s", dev->driver->name); |
| 169 | buffer, buffer_size, &length, | ||
| 170 | "DRIVER=%s", dev->driver->name); | ||
| 171 | 161 | ||
| 172 | #ifdef CONFIG_SYSFS_DEPRECATED | 162 | #ifdef CONFIG_SYSFS_DEPRECATED |
| 173 | if (dev->class) { | 163 | if (dev->class) { |
| @@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, | |||
| 181 | 171 | ||
| 182 | path = kobject_get_path(&parent->kobj, GFP_KERNEL); | 172 | path = kobject_get_path(&parent->kobj, GFP_KERNEL); |
| 183 | if (path) { | 173 | if (path) { |
| 184 | add_uevent_var(envp, num_envp, &i, | 174 | add_uevent_var(env, "PHYSDEVPATH=%s", path); |
| 185 | buffer, buffer_size, &length, | ||
| 186 | "PHYSDEVPATH=%s", path); | ||
| 187 | kfree(path); | 175 | kfree(path); |
| 188 | } | 176 | } |
| 189 | 177 | ||
| 190 | add_uevent_var(envp, num_envp, &i, | 178 | add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name); |
| 191 | buffer, buffer_size, &length, | ||
| 192 | "PHYSDEVBUS=%s", parent->bus->name); | ||
| 193 | 179 | ||
| 194 | if (parent->driver) | 180 | if (parent->driver) |
| 195 | add_uevent_var(envp, num_envp, &i, | 181 | add_uevent_var(env, "PHYSDEVDRIVER=%s", |
| 196 | buffer, buffer_size, &length, | 182 | parent->driver->name); |
| 197 | "PHYSDEVDRIVER=%s", parent->driver->name); | ||
| 198 | } | 183 | } |
| 199 | } else if (dev->bus) { | 184 | } else if (dev->bus) { |
| 200 | add_uevent_var(envp, num_envp, &i, | 185 | add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name); |
| 201 | buffer, buffer_size, &length, | ||
| 202 | "PHYSDEVBUS=%s", dev->bus->name); | ||
| 203 | 186 | ||
| 204 | if (dev->driver) | 187 | if (dev->driver) |
| 205 | add_uevent_var(envp, num_envp, &i, | 188 | add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name); |
| 206 | buffer, buffer_size, &length, | ||
| 207 | "PHYSDEVDRIVER=%s", dev->driver->name); | ||
| 208 | } | 189 | } |
| 209 | #endif | 190 | #endif |
| 210 | 191 | ||
| 211 | /* terminate, set to next free slot, shrink available space */ | 192 | /* have the bus specific function add its stuff */ |
| 212 | envp[i] = NULL; | ||
| 213 | envp = &envp[i]; | ||
| 214 | num_envp -= i; | ||
| 215 | buffer = &buffer[length]; | ||
| 216 | buffer_size -= length; | ||
| 217 | |||
| 218 | if (dev->bus && dev->bus->uevent) { | 193 | if (dev->bus && dev->bus->uevent) { |
| 219 | /* have the bus specific function add its stuff */ | 194 | retval = dev->bus->uevent(dev, env); |
| 220 | retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); | ||
| 221 | if (retval) | 195 | if (retval) |
| 222 | pr_debug ("%s: bus uevent() returned %d\n", | 196 | pr_debug ("%s: bus uevent() returned %d\n", |
| 223 | __FUNCTION__, retval); | 197 | __FUNCTION__, retval); |
| 224 | } | 198 | } |
| 225 | 199 | ||
| 200 | /* have the class specific function add its stuff */ | ||
| 226 | if (dev->class && dev->class->dev_uevent) { | 201 | if (dev->class && dev->class->dev_uevent) { |
| 227 | /* have the class specific function add its stuff */ | 202 | retval = dev->class->dev_uevent(dev, env); |
| 228 | retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); | ||
| 229 | if (retval) | 203 | if (retval) |
| 230 | pr_debug("%s: class uevent() returned %d\n", | 204 | pr_debug("%s: class uevent() returned %d\n", |
| 231 | __FUNCTION__, retval); | 205 | __FUNCTION__, retval); |
| 232 | } | 206 | } |
| 233 | 207 | ||
| 208 | /* have the device type specific fuction add its stuff */ | ||
| 234 | if (dev->type && dev->type->uevent) { | 209 | if (dev->type && dev->type->uevent) { |
| 235 | /* have the device type specific fuction add its stuff */ | 210 | retval = dev->type->uevent(dev, env); |
| 236 | retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); | ||
| 237 | if (retval) | 211 | if (retval) |
| 238 | pr_debug("%s: dev_type uevent() returned %d\n", | 212 | pr_debug("%s: dev_type uevent() returned %d\n", |
| 239 | __FUNCTION__, retval); | 213 | __FUNCTION__, retval); |
| @@ -253,22 +227,18 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, | |||
| 253 | { | 227 | { |
| 254 | struct kobject *top_kobj; | 228 | struct kobject *top_kobj; |
| 255 | struct kset *kset; | 229 | struct kset *kset; |
| 256 | char *envp[32]; | 230 | struct kobj_uevent_env *env = NULL; |
| 257 | char *data = NULL; | ||
| 258 | char *pos; | ||
| 259 | int i; | 231 | int i; |
| 260 | size_t count = 0; | 232 | size_t count = 0; |
| 261 | int retval; | 233 | int retval; |
| 262 | 234 | ||
| 263 | /* search the kset, the device belongs to */ | 235 | /* search the kset, the device belongs to */ |
| 264 | top_kobj = &dev->kobj; | 236 | top_kobj = &dev->kobj; |
| 265 | if (!top_kobj->kset && top_kobj->parent) { | 237 | while (!top_kobj->kset && top_kobj->parent) |
| 266 | do { | 238 | top_kobj = top_kobj->parent; |
| 267 | top_kobj = top_kobj->parent; | ||
| 268 | } while (!top_kobj->kset && top_kobj->parent); | ||
| 269 | } | ||
| 270 | if (!top_kobj->kset) | 239 | if (!top_kobj->kset) |
| 271 | goto out; | 240 | goto out; |
| 241 | |||
| 272 | kset = top_kobj->kset; | 242 | kset = top_kobj->kset; |
| 273 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) | 243 | if (!kset->uevent_ops || !kset->uevent_ops->uevent) |
| 274 | goto out; | 244 | goto out; |
| @@ -278,43 +248,29 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, | |||
| 278 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) | 248 | if (!kset->uevent_ops->filter(kset, &dev->kobj)) |
| 279 | goto out; | 249 | goto out; |
| 280 | 250 | ||
| 281 | data = (char *)get_zeroed_page(GFP_KERNEL); | 251 | env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); |
| 282 | if (!data) | 252 | if (!env) |
| 283 | return -ENOMEM; | 253 | return -ENOMEM; |
| 284 | 254 | ||
| 285 | /* let the kset specific function add its keys */ | 255 | /* let the kset specific function add its keys */ |
| 286 | pos = data; | 256 | retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); |
| 287 | memset(envp, 0, sizeof(envp)); | ||
| 288 | retval = kset->uevent_ops->uevent(kset, &dev->kobj, | ||
| 289 | envp, ARRAY_SIZE(envp), | ||
| 290 | pos, PAGE_SIZE); | ||
| 291 | if (retval) | 257 | if (retval) |
| 292 | goto out; | 258 | goto out; |
| 293 | 259 | ||
| 294 | /* copy keys to file */ | 260 | /* copy keys to file */ |
| 295 | for (i = 0; envp[i]; i++) { | 261 | for (i = 0; i < env->envp_idx; i++) |
| 296 | pos = &buf[count]; | 262 | count += sprintf(&buf[count], "%s\n", env->envp[i]); |
| 297 | count += sprintf(pos, "%s\n", envp[i]); | ||
| 298 | } | ||
| 299 | out: | 263 | out: |
| 300 | free_page((unsigned long)data); | 264 | kfree(env); |
| 301 | return count; | 265 | return count; |
| 302 | } | 266 | } |
| 303 | 267 | ||
| 304 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | 268 | static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, |
| 305 | const char *buf, size_t count) | 269 | const char *buf, size_t count) |
| 306 | { | 270 | { |
| 307 | size_t len = count; | ||
| 308 | enum kobject_action action; | 271 | enum kobject_action action; |
| 309 | 272 | ||
| 310 | if (len && buf[len-1] == '\n') | 273 | if (kobject_action_type(buf, count, &action) == 0) { |
| 311 | len--; | ||
| 312 | |||
| 313 | for (action = 0; action < KOBJ_MAX; action++) { | ||
| 314 | if (strncmp(kobject_actions[action], buf, len) != 0) | ||
| 315 | continue; | ||
| 316 | if (kobject_actions[action][len] != '\0') | ||
| 317 | continue; | ||
| 318 | kobject_uevent(&dev->kobj, action); | 274 | kobject_uevent(&dev->kobj, action); |
| 319 | goto out; | 275 | goto out; |
| 320 | } | 276 | } |
| @@ -449,7 +405,7 @@ static struct device_attribute devt_attr = | |||
| 449 | * devices_subsys - structure to be registered with kobject core. | 405 | * devices_subsys - structure to be registered with kobject core. |
| 450 | */ | 406 | */ |
| 451 | 407 | ||
| 452 | decl_subsys(devices, &ktype_device, &device_uevent_ops); | 408 | decl_subsys(devices, &device_ktype, &device_uevent_ops); |
| 453 | 409 | ||
| 454 | 410 | ||
| 455 | /** | 411 | /** |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b24efd4e3e3d..0295855a3eef 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -88,19 +88,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); | |||
| 88 | 88 | ||
| 89 | static void fw_dev_release(struct device *dev); | 89 | static void fw_dev_release(struct device *dev); |
| 90 | 90 | ||
| 91 | static int firmware_uevent(struct device *dev, char **envp, int num_envp, | 91 | static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 92 | char *buffer, int buffer_size) | ||
| 93 | { | 92 | { |
| 94 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); | 93 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
| 95 | int i = 0, len = 0; | ||
| 96 | 94 | ||
| 97 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 95 | if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) |
| 98 | "FIRMWARE=%s", fw_priv->fw_id)) | ||
| 99 | return -ENOMEM; | 96 | return -ENOMEM; |
| 100 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 97 | if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) |
| 101 | "TIMEOUT=%i", loading_timeout)) | ||
| 102 | return -ENOMEM; | 98 | return -ENOMEM; |
| 103 | envp[i] = NULL; | ||
| 104 | 99 | ||
| 105 | return 0; | 100 | return 0; |
| 106 | } | 101 | } |
| @@ -297,8 +292,7 @@ firmware_class_timeout(u_long data) | |||
| 297 | 292 | ||
| 298 | static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) | 293 | static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) |
| 299 | { | 294 | { |
| 300 | /* XXX warning we should watch out for name collisions */ | 295 | snprintf(f_dev->bus_id, BUS_ID_SIZE, "firmware-%s", dev->bus_id); |
| 301 | strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE); | ||
| 302 | } | 296 | } |
| 303 | 297 | ||
| 304 | static int fw_register_device(struct device **dev_p, const char *fw_name, | 298 | static int fw_register_device(struct device **dev_p, const char *fw_name, |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 74b96795d2f5..cb99daeae936 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
| @@ -34,8 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj) | |||
| 34 | return MEMORY_CLASS_NAME; | 34 | return MEMORY_CLASS_NAME; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp, | 37 | static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env) |
| 38 | int num_envp, char *buffer, int buffer_size) | ||
| 39 | { | 38 | { |
| 40 | int retval = 0; | 39 | int retval = 0; |
| 41 | 40 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 869ff8c00146..fb5609241482 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -160,13 +160,8 @@ static void platform_device_release(struct device *dev) | |||
| 160 | * | 160 | * |
| 161 | * Create a platform device object which can have other objects attached | 161 | * Create a platform device object which can have other objects attached |
| 162 | * to it, and which will have attached objects freed when it is released. | 162 | * to it, and which will have attached objects freed when it is released. |
| 163 | * | ||
| 164 | * This device will be marked as not supporting hotpluggable drivers; no | ||
| 165 | * device add/remove uevents will be generated. In the unusual case that | ||
| 166 | * the device isn't being dynamically allocated as a legacy "probe the | ||
| 167 | * hardware" driver, infrastructure code should reverse this marking. | ||
| 168 | */ | 163 | */ |
| 169 | struct platform_device *platform_device_alloc(const char *name, unsigned int id) | 164 | struct platform_device *platform_device_alloc(const char *name, int id) |
| 170 | { | 165 | { |
| 171 | struct platform_object *pa; | 166 | struct platform_object *pa; |
| 172 | 167 | ||
| @@ -177,12 +172,6 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id) | |||
| 177 | pa->pdev.id = id; | 172 | pa->pdev.id = id; |
| 178 | device_initialize(&pa->pdev.dev); | 173 | device_initialize(&pa->pdev.dev); |
| 179 | pa->pdev.dev.release = platform_device_release; | 174 | pa->pdev.dev.release = platform_device_release; |
| 180 | |||
| 181 | /* prevent hotplug "modprobe $(MODALIAS)" from causing trouble in | ||
| 182 | * legacy probe-the-hardware drivers, which don't properly split | ||
| 183 | * out device enumeration logic from drivers. | ||
| 184 | */ | ||
| 185 | pa->pdev.dev.uevent_suppress = 1; | ||
| 186 | } | 175 | } |
| 187 | 176 | ||
| 188 | return pa ? &pa->pdev : NULL; | 177 | return pa ? &pa->pdev : NULL; |
| @@ -256,7 +245,8 @@ int platform_device_add(struct platform_device *pdev) | |||
| 256 | pdev->dev.bus = &platform_bus_type; | 245 | pdev->dev.bus = &platform_bus_type; |
| 257 | 246 | ||
| 258 | if (pdev->id != -1) | 247 | if (pdev->id != -1) |
| 259 | snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id); | 248 | snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name, |
| 249 | pdev->id); | ||
| 260 | else | 250 | else |
| 261 | strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); | 251 | strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); |
| 262 | 252 | ||
| @@ -370,7 +360,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); | |||
| 370 | * the Linux driver model. In particular, when such drivers are built | 360 | * the Linux driver model. In particular, when such drivers are built |
| 371 | * as modules, they can't be "hotplugged". | 361 | * as modules, they can't be "hotplugged". |
| 372 | */ | 362 | */ |
| 373 | struct platform_device *platform_device_register_simple(char *name, unsigned int id, | 363 | struct platform_device *platform_device_register_simple(char *name, int id, |
| 374 | struct resource *res, unsigned int num) | 364 | struct resource *res, unsigned int num) |
| 375 | { | 365 | { |
| 376 | struct platform_device *pdev; | 366 | struct platform_device *pdev; |
| @@ -530,7 +520,7 @@ static ssize_t | |||
| 530 | modalias_show(struct device *dev, struct device_attribute *a, char *buf) | 520 | modalias_show(struct device *dev, struct device_attribute *a, char *buf) |
| 531 | { | 521 | { |
| 532 | struct platform_device *pdev = to_platform_device(dev); | 522 | struct platform_device *pdev = to_platform_device(dev); |
| 533 | int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name); | 523 | int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name); |
| 534 | 524 | ||
| 535 | return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; | 525 | return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; |
| 536 | } | 526 | } |
| @@ -540,13 +530,11 @@ static struct device_attribute platform_dev_attrs[] = { | |||
| 540 | __ATTR_NULL, | 530 | __ATTR_NULL, |
| 541 | }; | 531 | }; |
| 542 | 532 | ||
| 543 | static int platform_uevent(struct device *dev, char **envp, int num_envp, | 533 | static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 544 | char *buffer, int buffer_size) | ||
| 545 | { | 534 | { |
| 546 | struct platform_device *pdev = to_platform_device(dev); | 535 | struct platform_device *pdev = to_platform_device(dev); |
| 547 | 536 | ||
| 548 | envp[0] = buffer; | 537 | add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); |
| 549 | snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name); | ||
| 550 | return 0; | 538 | return 0; |
| 551 | } | 539 | } |
| 552 | 540 | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 9caeaea753a3..a803733c839e 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | obj-y := shutdown.o | 1 | obj-y := shutdown.o |
| 2 | obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o |
| 3 | obj-$(CONFIG_PM_TRACE) += trace.o | 3 | obj-$(CONFIG_PM_TRACE) += trace.o |
| 4 | 4 | ||
| 5 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 5 | ifeq ($(CONFIG_DEBUG_DRIVER),y) |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index eb9f38d0aa58..0ab4ab21f564 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -20,19 +20,24 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 23 | #include <linux/kallsyms.h> | ||
| 23 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
| 25 | #include <linux/pm.h> | ||
| 26 | #include <linux/resume-trace.h> | ||
| 24 | 27 | ||
| 28 | #include "../base.h" | ||
| 25 | #include "power.h" | 29 | #include "power.h" |
| 26 | 30 | ||
| 27 | LIST_HEAD(dpm_active); | 31 | LIST_HEAD(dpm_active); |
| 28 | LIST_HEAD(dpm_off); | 32 | static LIST_HEAD(dpm_off); |
| 29 | LIST_HEAD(dpm_off_irq); | 33 | static LIST_HEAD(dpm_off_irq); |
| 30 | 34 | ||
| 31 | DEFINE_MUTEX(dpm_mtx); | 35 | static DEFINE_MUTEX(dpm_mtx); |
| 32 | DEFINE_MUTEX(dpm_list_mtx); | 36 | static DEFINE_MUTEX(dpm_list_mtx); |
| 33 | 37 | ||
| 34 | int (*platform_enable_wakeup)(struct device *dev, int is_on); | 38 | int (*platform_enable_wakeup)(struct device *dev, int is_on); |
| 35 | 39 | ||
| 40 | |||
| 36 | int device_pm_add(struct device *dev) | 41 | int device_pm_add(struct device *dev) |
| 37 | { | 42 | { |
| 38 | int error; | 43 | int error; |
| @@ -61,3 +66,334 @@ void device_pm_remove(struct device *dev) | |||
| 61 | } | 66 | } |
| 62 | 67 | ||
| 63 | 68 | ||
| 69 | /*------------------------- Resume routines -------------------------*/ | ||
| 70 | |||
| 71 | /** | ||
| 72 | * resume_device - Restore state for one device. | ||
| 73 | * @dev: Device. | ||
| 74 | * | ||
| 75 | */ | ||
| 76 | |||
| 77 | static int resume_device(struct device * dev) | ||
| 78 | { | ||
| 79 | int error = 0; | ||
| 80 | |||
| 81 | TRACE_DEVICE(dev); | ||
| 82 | TRACE_RESUME(0); | ||
| 83 | |||
| 84 | down(&dev->sem); | ||
| 85 | |||
| 86 | if (dev->bus && dev->bus->resume) { | ||
| 87 | dev_dbg(dev,"resuming\n"); | ||
| 88 | error = dev->bus->resume(dev); | ||
| 89 | } | ||
| 90 | |||
| 91 | if (!error && dev->type && dev->type->resume) { | ||
| 92 | dev_dbg(dev,"resuming\n"); | ||
| 93 | error = dev->type->resume(dev); | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!error && dev->class && dev->class->resume) { | ||
| 97 | dev_dbg(dev,"class resume\n"); | ||
| 98 | error = dev->class->resume(dev); | ||
| 99 | } | ||
| 100 | |||
| 101 | up(&dev->sem); | ||
| 102 | |||
| 103 | TRACE_RESUME(error); | ||
| 104 | return error; | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | static int resume_device_early(struct device * dev) | ||
| 109 | { | ||
| 110 | int error = 0; | ||
| 111 | |||
| 112 | TRACE_DEVICE(dev); | ||
| 113 | TRACE_RESUME(0); | ||
| 114 | if (dev->bus && dev->bus->resume_early) { | ||
| 115 | dev_dbg(dev,"EARLY resume\n"); | ||
| 116 | error = dev->bus->resume_early(dev); | ||
| 117 | } | ||
| 118 | TRACE_RESUME(error); | ||
| 119 | return error; | ||
| 120 | } | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Resume the devices that have either not gone through | ||
| 124 | * the late suspend, or that did go through it but also | ||
| 125 | * went through the early resume | ||
| 126 | */ | ||
| 127 | static void dpm_resume(void) | ||
| 128 | { | ||
| 129 | mutex_lock(&dpm_list_mtx); | ||
| 130 | while(!list_empty(&dpm_off)) { | ||
| 131 | struct list_head * entry = dpm_off.next; | ||
| 132 | struct device * dev = to_device(entry); | ||
| 133 | |||
| 134 | get_device(dev); | ||
| 135 | list_move_tail(entry, &dpm_active); | ||
| 136 | |||
| 137 | mutex_unlock(&dpm_list_mtx); | ||
| 138 | resume_device(dev); | ||
| 139 | mutex_lock(&dpm_list_mtx); | ||
| 140 | put_device(dev); | ||
| 141 | } | ||
| 142 | mutex_unlock(&dpm_list_mtx); | ||
| 143 | } | ||
| 144 | |||
| 145 | |||
| 146 | /** | ||
| 147 | * device_resume - Restore state of each device in system. | ||
| 148 | * | ||
| 149 | * Walk the dpm_off list, remove each entry, resume the device, | ||
| 150 | * then add it to the dpm_active list. | ||
| 151 | */ | ||
| 152 | |||
| 153 | void device_resume(void) | ||
| 154 | { | ||
| 155 | might_sleep(); | ||
| 156 | mutex_lock(&dpm_mtx); | ||
| 157 | dpm_resume(); | ||
| 158 | mutex_unlock(&dpm_mtx); | ||
| 159 | } | ||
| 160 | |||
| 161 | EXPORT_SYMBOL_GPL(device_resume); | ||
| 162 | |||
| 163 | |||
| 164 | /** | ||
| 165 | * dpm_power_up - Power on some devices. | ||
| 166 | * | ||
| 167 | * Walk the dpm_off_irq list and power each device up. This | ||
| 168 | * is used for devices that required they be powered down with | ||
| 169 | * interrupts disabled. As devices are powered on, they are moved | ||
| 170 | * to the dpm_active list. | ||
| 171 | * | ||
| 172 | * Interrupts must be disabled when calling this. | ||
| 173 | */ | ||
| 174 | |||
| 175 | static void dpm_power_up(void) | ||
| 176 | { | ||
| 177 | while(!list_empty(&dpm_off_irq)) { | ||
| 178 | struct list_head * entry = dpm_off_irq.next; | ||
| 179 | struct device * dev = to_device(entry); | ||
| 180 | |||
| 181 | list_move_tail(entry, &dpm_off); | ||
| 182 | resume_device_early(dev); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | |||
| 187 | /** | ||
| 188 | * device_power_up - Turn on all devices that need special attention. | ||
| 189 | * | ||
| 190 | * Power on system devices then devices that required we shut them down | ||
| 191 | * with interrupts disabled. | ||
| 192 | * Called with interrupts disabled. | ||
| 193 | */ | ||
| 194 | |||
| 195 | void device_power_up(void) | ||
| 196 | { | ||
| 197 | sysdev_resume(); | ||
| 198 | dpm_power_up(); | ||
| 199 | } | ||
| 200 | |||
| 201 | EXPORT_SYMBOL_GPL(device_power_up); | ||
| 202 | |||
| 203 | |||
| 204 | /*------------------------- Suspend routines -------------------------*/ | ||
| 205 | |||
| 206 | /* | ||
| 207 | * The entries in the dpm_active list are in a depth first order, simply | ||
| 208 | * because children are guaranteed to be discovered after parents, and | ||
| 209 | * are inserted at the back of the list on discovery. | ||
| 210 | * | ||
| 211 | * All list on the suspend path are done in reverse order, so we operate | ||
| 212 | * on the leaves of the device tree (or forests, depending on how you want | ||
| 213 | * to look at it ;) first. As nodes are removed from the back of the list, | ||
| 214 | * they are inserted into the front of their destintation lists. | ||
| 215 | * | ||
| 216 | * Things are the reverse on the resume path - iterations are done in | ||
| 217 | * forward order, and nodes are inserted at the back of their destination | ||
| 218 | * lists. This way, the ancestors will be accessed before their descendents. | ||
| 219 | */ | ||
| 220 | |||
| 221 | static inline char *suspend_verb(u32 event) | ||
| 222 | { | ||
| 223 | switch (event) { | ||
| 224 | case PM_EVENT_SUSPEND: return "suspend"; | ||
| 225 | case PM_EVENT_FREEZE: return "freeze"; | ||
| 226 | case PM_EVENT_PRETHAW: return "prethaw"; | ||
| 227 | default: return "(unknown suspend event)"; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | |||
| 232 | static void | ||
| 233 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | ||
| 234 | { | ||
| 235 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | ||
| 236 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | ||
| 237 | ", may wakeup" : ""); | ||
| 238 | } | ||
| 239 | |||
| 240 | /** | ||
| 241 | * suspend_device - Save state of one device. | ||
| 242 | * @dev: Device. | ||
| 243 | * @state: Power state device is entering. | ||
| 244 | */ | ||
| 245 | |||
| 246 | static int suspend_device(struct device * dev, pm_message_t state) | ||
| 247 | { | ||
| 248 | int error = 0; | ||
| 249 | |||
| 250 | down(&dev->sem); | ||
| 251 | if (dev->power.power_state.event) { | ||
| 252 | dev_dbg(dev, "PM: suspend %d-->%d\n", | ||
| 253 | dev->power.power_state.event, state.event); | ||
| 254 | } | ||
| 255 | |||
| 256 | if (dev->class && dev->class->suspend) { | ||
| 257 | suspend_device_dbg(dev, state, "class "); | ||
| 258 | error = dev->class->suspend(dev, state); | ||
| 259 | suspend_report_result(dev->class->suspend, error); | ||
| 260 | } | ||
| 261 | |||
| 262 | if (!error && dev->type && dev->type->suspend) { | ||
| 263 | suspend_device_dbg(dev, state, "type "); | ||
| 264 | error = dev->type->suspend(dev, state); | ||
| 265 | suspend_report_result(dev->type->suspend, error); | ||
| 266 | } | ||
| 267 | |||
| 268 | if (!error && dev->bus && dev->bus->suspend) { | ||
| 269 | suspend_device_dbg(dev, state, ""); | ||
| 270 | error = dev->bus->suspend(dev, state); | ||
| 271 | suspend_report_result(dev->bus->suspend, error); | ||
| 272 | } | ||
| 273 | up(&dev->sem); | ||
| 274 | return error; | ||
| 275 | } | ||
| 276 | |||
| 277 | |||
| 278 | /* | ||
| 279 | * This is called with interrupts off, only a single CPU | ||
| 280 | * running. We can't acquire a mutex or semaphore (and we don't | ||
| 281 | * need the protection) | ||
| 282 | */ | ||
| 283 | static int suspend_device_late(struct device *dev, pm_message_t state) | ||
| 284 | { | ||
| 285 | int error = 0; | ||
| 286 | |||
| 287 | if (dev->bus && dev->bus->suspend_late) { | ||
| 288 | suspend_device_dbg(dev, state, "LATE "); | ||
| 289 | error = dev->bus->suspend_late(dev, state); | ||
| 290 | suspend_report_result(dev->bus->suspend_late, error); | ||
| 291 | } | ||
| 292 | return error; | ||
| 293 | } | ||
| 294 | |||
| 295 | /** | ||
| 296 | * device_suspend - Save state and stop all devices in system. | ||
| 297 | * @state: Power state to put each device in. | ||
| 298 | * | ||
| 299 | * Walk the dpm_active list, call ->suspend() for each device, and move | ||
| 300 | * it to the dpm_off list. | ||
| 301 | * | ||
| 302 | * (For historical reasons, if it returns -EAGAIN, that used to mean | ||
| 303 | * that the device would be called again with interrupts disabled. | ||
| 304 | * These days, we use the "suspend_late()" callback for that, so we | ||
| 305 | * print a warning and consider it an error). | ||
| 306 | * | ||
| 307 | * If we get a different error, try and back out. | ||
| 308 | * | ||
| 309 | * If we hit a failure with any of the devices, call device_resume() | ||
| 310 | * above to bring the suspended devices back to life. | ||
| 311 | * | ||
| 312 | */ | ||
| 313 | |||
| 314 | int device_suspend(pm_message_t state) | ||
| 315 | { | ||
| 316 | int error = 0; | ||
| 317 | |||
| 318 | might_sleep(); | ||
| 319 | mutex_lock(&dpm_mtx); | ||
| 320 | mutex_lock(&dpm_list_mtx); | ||
| 321 | while (!list_empty(&dpm_active) && error == 0) { | ||
| 322 | struct list_head * entry = dpm_active.prev; | ||
| 323 | struct device * dev = to_device(entry); | ||
| 324 | |||
| 325 | get_device(dev); | ||
| 326 | mutex_unlock(&dpm_list_mtx); | ||
| 327 | |||
| 328 | error = suspend_device(dev, state); | ||
| 329 | |||
| 330 | mutex_lock(&dpm_list_mtx); | ||
| 331 | |||
| 332 | /* Check if the device got removed */ | ||
| 333 | if (!list_empty(&dev->power.entry)) { | ||
| 334 | /* Move it to the dpm_off list */ | ||
| 335 | if (!error) | ||
| 336 | list_move(&dev->power.entry, &dpm_off); | ||
| 337 | } | ||
| 338 | if (error) | ||
| 339 | printk(KERN_ERR "Could not suspend device %s: " | ||
| 340 | "error %d%s\n", | ||
| 341 | kobject_name(&dev->kobj), error, | ||
| 342 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); | ||
| 343 | put_device(dev); | ||
| 344 | } | ||
| 345 | mutex_unlock(&dpm_list_mtx); | ||
| 346 | if (error) | ||
| 347 | dpm_resume(); | ||
| 348 | |||
| 349 | mutex_unlock(&dpm_mtx); | ||
| 350 | return error; | ||
| 351 | } | ||
| 352 | |||
| 353 | EXPORT_SYMBOL_GPL(device_suspend); | ||
| 354 | |||
| 355 | /** | ||
| 356 | * device_power_down - Shut down special devices. | ||
| 357 | * @state: Power state to enter. | ||
| 358 | * | ||
| 359 | * Walk the dpm_off_irq list, calling ->power_down() for each device that | ||
| 360 | * couldn't power down the device with interrupts enabled. When we're | ||
| 361 | * done, power down system devices. | ||
| 362 | */ | ||
| 363 | |||
| 364 | int device_power_down(pm_message_t state) | ||
| 365 | { | ||
| 366 | int error = 0; | ||
| 367 | struct device * dev; | ||
| 368 | |||
| 369 | while (!list_empty(&dpm_off)) { | ||
| 370 | struct list_head * entry = dpm_off.prev; | ||
| 371 | |||
| 372 | dev = to_device(entry); | ||
| 373 | error = suspend_device_late(dev, state); | ||
| 374 | if (error) | ||
| 375 | goto Error; | ||
| 376 | list_move(&dev->power.entry, &dpm_off_irq); | ||
| 377 | } | ||
| 378 | |||
| 379 | error = sysdev_suspend(state); | ||
| 380 | Done: | ||
| 381 | return error; | ||
| 382 | Error: | ||
| 383 | printk(KERN_ERR "Could not power down device %s: " | ||
| 384 | "error %d\n", kobject_name(&dev->kobj), error); | ||
| 385 | dpm_power_up(); | ||
| 386 | goto Done; | ||
| 387 | } | ||
| 388 | |||
| 389 | EXPORT_SYMBOL_GPL(device_power_down); | ||
| 390 | |||
| 391 | void __suspend_report_result(const char *function, void *fn, int ret) | ||
| 392 | { | ||
| 393 | if (ret) { | ||
| 394 | printk(KERN_ERR "%s(): ", function); | ||
| 395 | print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); | ||
| 396 | printk("%d\n", ret); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | EXPORT_SYMBOL_GPL(__suspend_report_result); | ||
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 8ba0830cbc03..5c4efd493fa5 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
| @@ -11,32 +11,11 @@ extern void device_shutdown(void); | |||
| 11 | * main.c | 11 | * main.c |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | /* | 14 | extern struct list_head dpm_active; /* The active device list */ |
| 15 | * Used to synchronize global power management operations. | ||
| 16 | */ | ||
| 17 | extern struct mutex dpm_mtx; | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Used to serialize changes to the dpm_* lists. | ||
| 21 | */ | ||
| 22 | extern struct mutex dpm_list_mtx; | ||
| 23 | |||
| 24 | /* | ||
| 25 | * The PM lists. | ||
| 26 | */ | ||
| 27 | extern struct list_head dpm_active; | ||
| 28 | extern struct list_head dpm_off; | ||
| 29 | extern struct list_head dpm_off_irq; | ||
| 30 | |||
| 31 | |||
| 32 | static inline struct dev_pm_info * to_pm_info(struct list_head * entry) | ||
| 33 | { | ||
| 34 | return container_of(entry, struct dev_pm_info, entry); | ||
| 35 | } | ||
| 36 | 15 | ||
| 37 | static inline struct device * to_device(struct list_head * entry) | 16 | static inline struct device * to_device(struct list_head * entry) |
| 38 | { | 17 | { |
| 39 | return container_of(to_pm_info(entry), struct device, power); | 18 | return container_of(entry, struct device, power.entry); |
| 40 | } | 19 | } |
| 41 | 20 | ||
| 42 | extern int device_pm_add(struct device *); | 21 | extern int device_pm_add(struct device *); |
| @@ -49,19 +28,6 @@ extern void device_pm_remove(struct device *); | |||
| 49 | extern int dpm_sysfs_add(struct device *); | 28 | extern int dpm_sysfs_add(struct device *); |
| 50 | extern void dpm_sysfs_remove(struct device *); | 29 | extern void dpm_sysfs_remove(struct device *); |
| 51 | 30 | ||
| 52 | /* | ||
| 53 | * resume.c | ||
| 54 | */ | ||
| 55 | |||
| 56 | extern void dpm_resume(void); | ||
| 57 | extern void dpm_power_up(void); | ||
| 58 | extern int resume_device(struct device *); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * suspend.c | ||
| 62 | */ | ||
| 63 | extern int suspend_device(struct device *, pm_message_t); | ||
| 64 | |||
| 65 | #else /* CONFIG_PM_SLEEP */ | 31 | #else /* CONFIG_PM_SLEEP */ |
| 66 | 32 | ||
| 67 | 33 | ||
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c deleted file mode 100644 index 00fd84ae6e66..000000000000 --- a/drivers/base/power/resume.c +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * resume.c - Functions for waking devices up. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003 Patrick Mochel | ||
| 5 | * Copyright (c) 2003 Open Source Development Labs | ||
| 6 | * | ||
| 7 | * This file is released under the GPLv2 | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/device.h> | ||
| 12 | #include <linux/resume-trace.h> | ||
| 13 | #include "../base.h" | ||
| 14 | #include "power.h" | ||
| 15 | |||
| 16 | |||
| 17 | /** | ||
| 18 | * resume_device - Restore state for one device. | ||
| 19 | * @dev: Device. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | int resume_device(struct device * dev) | ||
| 24 | { | ||
| 25 | int error = 0; | ||
| 26 | |||
| 27 | TRACE_DEVICE(dev); | ||
| 28 | TRACE_RESUME(0); | ||
| 29 | |||
| 30 | down(&dev->sem); | ||
| 31 | |||
| 32 | if (dev->bus && dev->bus->resume) { | ||
| 33 | dev_dbg(dev,"resuming\n"); | ||
| 34 | error = dev->bus->resume(dev); | ||
| 35 | } | ||
| 36 | |||
| 37 | if (!error && dev->type && dev->type->resume) { | ||
| 38 | dev_dbg(dev,"resuming\n"); | ||
| 39 | error = dev->type->resume(dev); | ||
| 40 | } | ||
| 41 | |||
| 42 | if (!error && dev->class && dev->class->resume) { | ||
| 43 | dev_dbg(dev,"class resume\n"); | ||
| 44 | error = dev->class->resume(dev); | ||
| 45 | } | ||
| 46 | |||
| 47 | up(&dev->sem); | ||
| 48 | |||
| 49 | TRACE_RESUME(error); | ||
| 50 | return error; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | static int resume_device_early(struct device * dev) | ||
| 55 | { | ||
| 56 | int error = 0; | ||
| 57 | |||
| 58 | TRACE_DEVICE(dev); | ||
| 59 | TRACE_RESUME(0); | ||
| 60 | if (dev->bus && dev->bus->resume_early) { | ||
| 61 | dev_dbg(dev,"EARLY resume\n"); | ||
| 62 | error = dev->bus->resume_early(dev); | ||
| 63 | } | ||
| 64 | TRACE_RESUME(error); | ||
| 65 | return error; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Resume the devices that have either not gone through | ||
| 70 | * the late suspend, or that did go through it but also | ||
| 71 | * went through the early resume | ||
| 72 | */ | ||
| 73 | void dpm_resume(void) | ||
| 74 | { | ||
| 75 | mutex_lock(&dpm_list_mtx); | ||
| 76 | while(!list_empty(&dpm_off)) { | ||
| 77 | struct list_head * entry = dpm_off.next; | ||
| 78 | struct device * dev = to_device(entry); | ||
| 79 | |||
| 80 | get_device(dev); | ||
| 81 | list_move_tail(entry, &dpm_active); | ||
| 82 | |||
| 83 | mutex_unlock(&dpm_list_mtx); | ||
| 84 | resume_device(dev); | ||
| 85 | mutex_lock(&dpm_list_mtx); | ||
| 86 | put_device(dev); | ||
| 87 | } | ||
| 88 | mutex_unlock(&dpm_list_mtx); | ||
| 89 | } | ||
| 90 | |||
| 91 | |||
| 92 | /** | ||
| 93 | * device_resume - Restore state of each device in system. | ||
| 94 | * | ||
| 95 | * Walk the dpm_off list, remove each entry, resume the device, | ||
| 96 | * then add it to the dpm_active list. | ||
| 97 | */ | ||
| 98 | |||
| 99 | void device_resume(void) | ||
| 100 | { | ||
| 101 | might_sleep(); | ||
| 102 | mutex_lock(&dpm_mtx); | ||
| 103 | dpm_resume(); | ||
| 104 | mutex_unlock(&dpm_mtx); | ||
| 105 | } | ||
| 106 | |||
| 107 | EXPORT_SYMBOL_GPL(device_resume); | ||
| 108 | |||
| 109 | |||
| 110 | /** | ||
| 111 | * dpm_power_up - Power on some devices. | ||
| 112 | * | ||
| 113 | * Walk the dpm_off_irq list and power each device up. This | ||
| 114 | * is used for devices that required they be powered down with | ||
| 115 | * interrupts disabled. As devices are powered on, they are moved | ||
| 116 | * to the dpm_active list. | ||
| 117 | * | ||
| 118 | * Interrupts must be disabled when calling this. | ||
| 119 | */ | ||
| 120 | |||
| 121 | void dpm_power_up(void) | ||
| 122 | { | ||
| 123 | while(!list_empty(&dpm_off_irq)) { | ||
| 124 | struct list_head * entry = dpm_off_irq.next; | ||
| 125 | struct device * dev = to_device(entry); | ||
| 126 | |||
| 127 | list_move_tail(entry, &dpm_off); | ||
| 128 | resume_device_early(dev); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | |||
| 133 | /** | ||
| 134 | * device_power_up - Turn on all devices that need special attention. | ||
| 135 | * | ||
| 136 | * Power on system devices then devices that required we shut them down | ||
| 137 | * with interrupts disabled. | ||
| 138 | * Called with interrupts disabled. | ||
| 139 | */ | ||
| 140 | |||
| 141 | void device_power_up(void) | ||
| 142 | { | ||
| 143 | sysdev_resume(); | ||
| 144 | dpm_power_up(); | ||
| 145 | } | ||
| 146 | |||
| 147 | EXPORT_SYMBOL_GPL(device_power_up); | ||
| 148 | |||
| 149 | |||
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c deleted file mode 100644 index 26df9b231737..000000000000 --- a/drivers/base/power/suspend.c +++ /dev/null | |||
| @@ -1,210 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * suspend.c - Functions for putting devices to sleep. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003 Patrick Mochel | ||
| 5 | * Copyright (c) 2003 Open Source Development Labs | ||
| 6 | * | ||
| 7 | * This file is released under the GPLv2 | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/device.h> | ||
| 12 | #include <linux/kallsyms.h> | ||
| 13 | #include <linux/pm.h> | ||
| 14 | #include "../base.h" | ||
| 15 | #include "power.h" | ||
| 16 | |||
| 17 | /* | ||
| 18 | * The entries in the dpm_active list are in a depth first order, simply | ||
| 19 | * because children are guaranteed to be discovered after parents, and | ||
| 20 | * are inserted at the back of the list on discovery. | ||
| 21 | * | ||
| 22 | * All list on the suspend path are done in reverse order, so we operate | ||
| 23 | * on the leaves of the device tree (or forests, depending on how you want | ||
| 24 | * to look at it ;) first. As nodes are removed from the back of the list, | ||
| 25 | * they are inserted into the front of their destintation lists. | ||
| 26 | * | ||
| 27 | * Things are the reverse on the resume path - iterations are done in | ||
| 28 | * forward order, and nodes are inserted at the back of their destination | ||
| 29 | * lists. This way, the ancestors will be accessed before their descendents. | ||
| 30 | */ | ||
| 31 | |||
| 32 | static inline char *suspend_verb(u32 event) | ||
| 33 | { | ||
| 34 | switch (event) { | ||
| 35 | case PM_EVENT_SUSPEND: return "suspend"; | ||
| 36 | case PM_EVENT_FREEZE: return "freeze"; | ||
| 37 | case PM_EVENT_PRETHAW: return "prethaw"; | ||
| 38 | default: return "(unknown suspend event)"; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
| 43 | static void | ||
| 44 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | ||
| 45 | { | ||
| 46 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | ||
| 47 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | ||
| 48 | ", may wakeup" : ""); | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | ||
| 52 | * suspend_device - Save state of one device. | ||
| 53 | * @dev: Device. | ||
| 54 | * @state: Power state device is entering. | ||
| 55 | */ | ||
| 56 | |||
| 57 | int suspend_device(struct device * dev, pm_message_t state) | ||
| 58 | { | ||
| 59 | int error = 0; | ||
| 60 | |||
| 61 | down(&dev->sem); | ||
| 62 | if (dev->power.power_state.event) { | ||
| 63 | dev_dbg(dev, "PM: suspend %d-->%d\n", | ||
| 64 | dev->power.power_state.event, state.event); | ||
| 65 | } | ||
| 66 | |||
| 67 | if (dev->class && dev->class->suspend) { | ||
| 68 | suspend_device_dbg(dev, state, "class "); | ||
| 69 | error = dev->class->suspend(dev, state); | ||
| 70 | suspend_report_result(dev->class->suspend, error); | ||
| 71 | } | ||
| 72 | |||
| 73 | if (!error && dev->type && dev->type->suspend) { | ||
| 74 | suspend_device_dbg(dev, state, "type "); | ||
| 75 | error = dev->type->suspend(dev, state); | ||
| 76 | suspend_report_result(dev->type->suspend, error); | ||
| 77 | } | ||
| 78 | |||
| 79 | if (!error && dev->bus && dev->bus->suspend) { | ||
| 80 | suspend_device_dbg(dev, state, ""); | ||
| 81 | error = dev->bus->suspend(dev, state); | ||
| 82 | suspend_report_result(dev->bus->suspend, error); | ||
| 83 | } | ||
| 84 | up(&dev->sem); | ||
| 85 | return error; | ||
| 86 | } | ||
| 87 | |||
| 88 | |||
| 89 | /* | ||
| 90 | * This is called with interrupts off, only a single CPU | ||
| 91 | * running. We can't acquire a mutex or semaphore (and we don't | ||
| 92 | * need the protection) | ||
| 93 | */ | ||
| 94 | static int suspend_device_late(struct device *dev, pm_message_t state) | ||
| 95 | { | ||
| 96 | int error = 0; | ||
| 97 | |||
| 98 | if (dev->bus && dev->bus->suspend_late) { | ||
| 99 | suspend_device_dbg(dev, state, "LATE "); | ||
| 100 | error = dev->bus->suspend_late(dev, state); | ||
| 101 | suspend_report_result(dev->bus->suspend_late, error); | ||
| 102 | } | ||
| 103 | return error; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * device_suspend - Save state and stop all devices in system. | ||
| 108 | * @state: Power state to put each device in. | ||
| 109 | * | ||
| 110 | * Walk the dpm_active list, call ->suspend() for each device, and move | ||
| 111 | * it to the dpm_off list. | ||
| 112 | * | ||
| 113 | * (For historical reasons, if it returns -EAGAIN, that used to mean | ||
| 114 | * that the device would be called again with interrupts disabled. | ||
| 115 | * These days, we use the "suspend_late()" callback for that, so we | ||
| 116 | * print a warning and consider it an error). | ||
| 117 | * | ||
| 118 | * If we get a different error, try and back out. | ||
| 119 | * | ||
| 120 | * If we hit a failure with any of the devices, call device_resume() | ||
| 121 | * above to bring the suspended devices back to life. | ||
| 122 | * | ||
| 123 | */ | ||
| 124 | |||
| 125 | int device_suspend(pm_message_t state) | ||
| 126 | { | ||
| 127 | int error = 0; | ||
| 128 | |||
| 129 | might_sleep(); | ||
| 130 | mutex_lock(&dpm_mtx); | ||
| 131 | mutex_lock(&dpm_list_mtx); | ||
| 132 | while (!list_empty(&dpm_active) && error == 0) { | ||
| 133 | struct list_head * entry = dpm_active.prev; | ||
| 134 | struct device * dev = to_device(entry); | ||
| 135 | |||
| 136 | get_device(dev); | ||
| 137 | mutex_unlock(&dpm_list_mtx); | ||
| 138 | |||
| 139 | error = suspend_device(dev, state); | ||
| 140 | |||
| 141 | mutex_lock(&dpm_list_mtx); | ||
| 142 | |||
| 143 | /* Check if the device got removed */ | ||
| 144 | if (!list_empty(&dev->power.entry)) { | ||
| 145 | /* Move it to the dpm_off list */ | ||
| 146 | if (!error) | ||
| 147 | list_move(&dev->power.entry, &dpm_off); | ||
| 148 | } | ||
| 149 | if (error) | ||
| 150 | printk(KERN_ERR "Could not suspend device %s: " | ||
| 151 | "error %d%s\n", | ||
| 152 | kobject_name(&dev->kobj), error, | ||
| 153 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); | ||
| 154 | put_device(dev); | ||
| 155 | } | ||
| 156 | mutex_unlock(&dpm_list_mtx); | ||
| 157 | if (error) | ||
| 158 | dpm_resume(); | ||
| 159 | |||
| 160 | mutex_unlock(&dpm_mtx); | ||
| 161 | return error; | ||
| 162 | } | ||
| 163 | |||
| 164 | EXPORT_SYMBOL_GPL(device_suspend); | ||
| 165 | |||
| 166 | /** | ||
| 167 | * device_power_down - Shut down special devices. | ||
| 168 | * @state: Power state to enter. | ||
| 169 | * | ||
| 170 | * Walk the dpm_off_irq list, calling ->power_down() for each device that | ||
| 171 | * couldn't power down the device with interrupts enabled. When we're | ||
| 172 | * done, power down system devices. | ||
| 173 | */ | ||
| 174 | |||
| 175 | int device_power_down(pm_message_t state) | ||
| 176 | { | ||
| 177 | int error = 0; | ||
| 178 | struct device * dev; | ||
| 179 | |||
| 180 | while (!list_empty(&dpm_off)) { | ||
| 181 | struct list_head * entry = dpm_off.prev; | ||
| 182 | |||
| 183 | dev = to_device(entry); | ||
| 184 | error = suspend_device_late(dev, state); | ||
| 185 | if (error) | ||
| 186 | goto Error; | ||
| 187 | list_move(&dev->power.entry, &dpm_off_irq); | ||
| 188 | } | ||
| 189 | |||
| 190 | error = sysdev_suspend(state); | ||
| 191 | Done: | ||
| 192 | return error; | ||
| 193 | Error: | ||
| 194 | printk(KERN_ERR "Could not power down device %s: " | ||
| 195 | "error %d\n", kobject_name(&dev->kobj), error); | ||
| 196 | dpm_power_up(); | ||
| 197 | goto Done; | ||
| 198 | } | ||
| 199 | |||
| 200 | EXPORT_SYMBOL_GPL(device_power_down); | ||
| 201 | |||
| 202 | void __suspend_report_result(const char *function, void *fn, int ret) | ||
| 203 | { | ||
| 204 | if (ret) { | ||
| 205 | printk(KERN_ERR "%s(): ", function); | ||
| 206 | print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); | ||
| 207 | printk("%d\n", ret); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | EXPORT_SYMBOL_GPL(__suspend_report_result); | ||
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 18febe26caa1..ac7ff6d0c6e5 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
| @@ -139,7 +139,7 @@ int sysdev_class_register(struct sysdev_class * cls) | |||
| 139 | kobject_name(&cls->kset.kobj)); | 139 | kobject_name(&cls->kset.kobj)); |
| 140 | INIT_LIST_HEAD(&cls->drivers); | 140 | INIT_LIST_HEAD(&cls->drivers); |
| 141 | cls->kset.kobj.parent = &system_subsys.kobj; | 141 | cls->kset.kobj.parent = &system_subsys.kobj; |
| 142 | kset_set_kset_s(cls, system_subsys); | 142 | cls->kset.kobj.kset = &system_subsys; |
| 143 | return kset_register(&cls->kset); | 143 | return kset_register(&cls->kset); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -153,25 +153,22 @@ void sysdev_class_unregister(struct sysdev_class * cls) | |||
| 153 | EXPORT_SYMBOL_GPL(sysdev_class_register); | 153 | EXPORT_SYMBOL_GPL(sysdev_class_register); |
| 154 | EXPORT_SYMBOL_GPL(sysdev_class_unregister); | 154 | EXPORT_SYMBOL_GPL(sysdev_class_unregister); |
| 155 | 155 | ||
| 156 | |||
| 157 | static LIST_HEAD(sysdev_drivers); | ||
| 158 | static DEFINE_MUTEX(sysdev_drivers_lock); | 156 | static DEFINE_MUTEX(sysdev_drivers_lock); |
| 159 | 157 | ||
| 160 | /** | 158 | /** |
| 161 | * sysdev_driver_register - Register auxillary driver | 159 | * sysdev_driver_register - Register auxillary driver |
| 162 | * @cls: Device class driver belongs to. | 160 | * @cls: Device class driver belongs to. |
| 163 | * @drv: Driver. | 161 | * @drv: Driver. |
| 164 | * | 162 | * |
| 165 | * If @cls is valid, then @drv is inserted into @cls->drivers to be | 163 | * @drv is inserted into @cls->drivers to be |
| 166 | * called on each operation on devices of that class. The refcount | 164 | * called on each operation on devices of that class. The refcount |
| 167 | * of @cls is incremented. | 165 | * of @cls is incremented. |
| 168 | * Otherwise, @drv is inserted into sysdev_drivers, and called for | ||
| 169 | * each device. | ||
| 170 | */ | 166 | */ |
| 171 | 167 | ||
| 172 | int sysdev_driver_register(struct sysdev_class * cls, | 168 | int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) |
| 173 | struct sysdev_driver * drv) | ||
| 174 | { | 169 | { |
| 170 | int err = 0; | ||
| 171 | |||
| 175 | mutex_lock(&sysdev_drivers_lock); | 172 | mutex_lock(&sysdev_drivers_lock); |
| 176 | if (cls && kset_get(&cls->kset)) { | 173 | if (cls && kset_get(&cls->kset)) { |
| 177 | list_add_tail(&drv->entry, &cls->drivers); | 174 | list_add_tail(&drv->entry, &cls->drivers); |
| @@ -182,10 +179,13 @@ int sysdev_driver_register(struct sysdev_class * cls, | |||
| 182 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) | 179 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) |
| 183 | drv->add(dev); | 180 | drv->add(dev); |
| 184 | } | 181 | } |
| 185 | } else | 182 | } else { |
| 186 | list_add_tail(&drv->entry, &sysdev_drivers); | 183 | err = -EINVAL; |
| 184 | printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__); | ||
| 185 | WARN_ON(1); | ||
| 186 | } | ||
| 187 | mutex_unlock(&sysdev_drivers_lock); | 187 | mutex_unlock(&sysdev_drivers_lock); |
| 188 | return 0; | 188 | return err; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | 191 | ||
| @@ -251,12 +251,6 @@ int sysdev_register(struct sys_device * sysdev) | |||
| 251 | * code that should have called us. | 251 | * code that should have called us. |
| 252 | */ | 252 | */ |
| 253 | 253 | ||
| 254 | /* Notify global drivers */ | ||
| 255 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 256 | if (drv->add) | ||
| 257 | drv->add(sysdev); | ||
| 258 | } | ||
| 259 | |||
| 260 | /* Notify class auxillary drivers */ | 254 | /* Notify class auxillary drivers */ |
| 261 | list_for_each_entry(drv, &cls->drivers, entry) { | 255 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 262 | if (drv->add) | 256 | if (drv->add) |
| @@ -272,11 +266,6 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 272 | struct sysdev_driver * drv; | 266 | struct sysdev_driver * drv; |
| 273 | 267 | ||
| 274 | mutex_lock(&sysdev_drivers_lock); | 268 | mutex_lock(&sysdev_drivers_lock); |
| 275 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 276 | if (drv->remove) | ||
| 277 | drv->remove(sysdev); | ||
| 278 | } | ||
| 279 | |||
| 280 | list_for_each_entry(drv, &sysdev->cls->drivers, entry) { | 269 | list_for_each_entry(drv, &sysdev->cls->drivers, entry) { |
| 281 | if (drv->remove) | 270 | if (drv->remove) |
| 282 | drv->remove(sysdev); | 271 | drv->remove(sysdev); |
| @@ -293,7 +282,7 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 293 | * | 282 | * |
| 294 | * Loop over each class of system devices, and the devices in each | 283 | * Loop over each class of system devices, and the devices in each |
| 295 | * of those classes. For each device, we call the shutdown method for | 284 | * of those classes. For each device, we call the shutdown method for |
| 296 | * each driver registered for the device - the globals, the auxillaries, | 285 | * each driver registered for the device - the auxillaries, |
| 297 | * and the class driver. | 286 | * and the class driver. |
| 298 | * | 287 | * |
| 299 | * Note: The list is iterated in reverse order, so that we shut down | 288 | * Note: The list is iterated in reverse order, so that we shut down |
| @@ -320,13 +309,7 @@ void sysdev_shutdown(void) | |||
| 320 | struct sysdev_driver * drv; | 309 | struct sysdev_driver * drv; |
| 321 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | 310 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); |
| 322 | 311 | ||
| 323 | /* Call global drivers first. */ | 312 | /* Call auxillary drivers first */ |
| 324 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 325 | if (drv->shutdown) | ||
| 326 | drv->shutdown(sysdev); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* Call auxillary drivers next. */ | ||
| 330 | list_for_each_entry(drv, &cls->drivers, entry) { | 313 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 331 | if (drv->shutdown) | 314 | if (drv->shutdown) |
| 332 | drv->shutdown(sysdev); | 315 | drv->shutdown(sysdev); |
| @@ -354,12 +337,6 @@ static void __sysdev_resume(struct sys_device *dev) | |||
| 354 | if (drv->resume) | 337 | if (drv->resume) |
| 355 | drv->resume(dev); | 338 | drv->resume(dev); |
| 356 | } | 339 | } |
| 357 | |||
| 358 | /* Call global drivers. */ | ||
| 359 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 360 | if (drv->resume) | ||
| 361 | drv->resume(dev); | ||
| 362 | } | ||
| 363 | } | 340 | } |
| 364 | 341 | ||
| 365 | /** | 342 | /** |
| @@ -393,16 +370,7 @@ int sysdev_suspend(pm_message_t state) | |||
| 393 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { | 370 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { |
| 394 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | 371 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); |
| 395 | 372 | ||
| 396 | /* Call global drivers first. */ | 373 | /* Call auxillary drivers first */ |
| 397 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 398 | if (drv->suspend) { | ||
| 399 | ret = drv->suspend(sysdev, state); | ||
| 400 | if (ret) | ||
| 401 | goto gbl_driver; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Call auxillary drivers next. */ | ||
| 406 | list_for_each_entry(drv, &cls->drivers, entry) { | 374 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 407 | if (drv->suspend) { | 375 | if (drv->suspend) { |
| 408 | ret = drv->suspend(sysdev, state); | 376 | ret = drv->suspend(sysdev, state); |
| @@ -436,18 +404,7 @@ aux_driver: | |||
| 436 | if (err_drv->resume) | 404 | if (err_drv->resume) |
| 437 | err_drv->resume(sysdev); | 405 | err_drv->resume(sysdev); |
| 438 | } | 406 | } |
| 439 | drv = NULL; | ||
| 440 | 407 | ||
| 441 | gbl_driver: | ||
| 442 | if (drv) | ||
| 443 | printk(KERN_ERR "sysdev driver suspend failed for %s\n", | ||
| 444 | kobject_name(&sysdev->kobj)); | ||
| 445 | list_for_each_entry(err_drv, &sysdev_drivers, entry) { | ||
| 446 | if (err_drv == drv) | ||
| 447 | break; | ||
| 448 | if (err_drv->resume) | ||
| 449 | err_drv->resume(sysdev); | ||
| 450 | } | ||
| 451 | /* resume other sysdevs in current class */ | 408 | /* resume other sysdevs in current class */ |
| 452 | list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) { | 409 | list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) { |
| 453 | if (err_dev == sysdev) | 410 | if (err_dev == sysdev) |
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/char/dsp56k.c b/drivers/char/dsp56k.c index 9b8278e1f4f8..acbfe1c49b4d 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
| @@ -513,7 +513,7 @@ static int __init dsp56k_init_driver(void) | |||
| 513 | err = PTR_ERR(dsp56k_class); | 513 | err = PTR_ERR(dsp56k_class); |
| 514 | goto out_chrdev; | 514 | goto out_chrdev; |
| 515 | } | 515 | } |
| 516 | class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k"); | 516 | device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k"); |
| 517 | 517 | ||
| 518 | printk(banner); | 518 | printk(banner); |
| 519 | goto out; | 519 | goto out; |
| @@ -527,7 +527,7 @@ module_init(dsp56k_init_driver); | |||
| 527 | 527 | ||
| 528 | static void __exit dsp56k_cleanup_driver(void) | 528 | static void __exit dsp56k_cleanup_driver(void) |
| 529 | { | 529 | { |
| 530 | class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); | 530 | device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0)); |
| 531 | class_destroy(dsp56k_class); | 531 | class_destroy(dsp56k_class); |
| 532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); | 532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); |
| 533 | } | 533 | } |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 8d74b8745e60..bd94d5f9e62b 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
| @@ -411,8 +411,8 @@ cleanup_module(void) | |||
| 411 | iiResetDelay( i2BoardPtrTable[i] ); | 411 | iiResetDelay( i2BoardPtrTable[i] ); |
| 412 | /* free io addresses and Tibet */ | 412 | /* free io addresses and Tibet */ |
| 413 | release_region( ip2config.addr[i], 8 ); | 413 | release_region( ip2config.addr[i], 8 ); |
| 414 | class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | 414 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); |
| 415 | class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); | 415 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); |
| 416 | } | 416 | } |
| 417 | /* Disable and remove interrupt handler. */ | 417 | /* Disable and remove interrupt handler. */ |
| 418 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { | 418 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { |
| @@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) | |||
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { | 720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { |
| 721 | class_device_create(ip2_class, NULL, | 721 | device_create(ip2_class, NULL, |
| 722 | MKDEV(IP2_IPL_MAJOR, 4 * i), | 722 | MKDEV(IP2_IPL_MAJOR, 4 * i), |
| 723 | NULL, "ipl%d", i); | 723 | "ipl%d", i); |
| 724 | class_device_create(ip2_class, NULL, | 724 | device_create(ip2_class, NULL, |
| 725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | 725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), |
| 726 | NULL, "stat%d", i); | 726 | "stat%d", i); |
| 727 | 727 | ||
| 728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
| 729 | { | 729 | { |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index c2aa44ee6eb6..0246a2b8ce48 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
| @@ -865,7 +865,7 @@ static void ipmi_new_smi(int if_num, struct device *device) | |||
| 865 | entry->dev = dev; | 865 | entry->dev = dev; |
| 866 | 866 | ||
| 867 | mutex_lock(®_list_mutex); | 867 | mutex_lock(®_list_mutex); |
| 868 | class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num); | 868 | device_create(ipmi_class, device, dev, "ipmi%d", if_num); |
| 869 | list_add(&entry->link, ®_list); | 869 | list_add(&entry->link, ®_list); |
| 870 | mutex_unlock(®_list_mutex); | 870 | mutex_unlock(®_list_mutex); |
| 871 | } | 871 | } |
| @@ -883,7 +883,7 @@ static void ipmi_smi_gone(int if_num) | |||
| 883 | break; | 883 | break; |
| 884 | } | 884 | } |
| 885 | } | 885 | } |
| 886 | class_device_destroy(ipmi_class, dev); | 886 | device_destroy(ipmi_class, dev); |
| 887 | mutex_unlock(®_list_mutex); | 887 | mutex_unlock(®_list_mutex); |
| 888 | } | 888 | } |
| 889 | 889 | ||
| @@ -938,7 +938,7 @@ static __exit void cleanup_ipmi(void) | |||
| 938 | mutex_lock(®_list_mutex); | 938 | mutex_lock(®_list_mutex); |
| 939 | list_for_each_entry_safe(entry, entry2, ®_list, link) { | 939 | list_for_each_entry_safe(entry, entry2, ®_list, link) { |
| 940 | list_del(&entry->link); | 940 | list_del(&entry->link); |
| 941 | class_device_destroy(ipmi_class, entry->dev); | 941 | device_destroy(ipmi_class, entry->dev); |
| 942 | kfree(entry); | 942 | kfree(entry); |
| 943 | } | 943 | } |
| 944 | mutex_unlock(®_list_mutex); | 944 | mutex_unlock(®_list_mutex); |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 3c66f402f9d7..1f27be1ec3d4 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
| @@ -4624,9 +4624,8 @@ static int __init istallion_module_init(void) | |||
| 4624 | 4624 | ||
| 4625 | istallion_class = class_create(THIS_MODULE, "staliomem"); | 4625 | istallion_class = class_create(THIS_MODULE, "staliomem"); |
| 4626 | for (i = 0; i < 4; i++) | 4626 | for (i = 0; i < 4; i++) |
| 4627 | class_device_create(istallion_class, NULL, | 4627 | device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), |
| 4628 | MKDEV(STL_SIOMEMMAJOR, i), | 4628 | "staliomem%d", i); |
| 4629 | NULL, "staliomem%d", i); | ||
| 4630 | 4629 | ||
| 4631 | return 0; | 4630 | return 0; |
| 4632 | err_deinit: | 4631 | err_deinit: |
| @@ -4659,8 +4658,7 @@ static void __exit istallion_module_exit(void) | |||
| 4659 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | 4658 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); |
| 4660 | 4659 | ||
| 4661 | for (j = 0; j < 4; j++) | 4660 | for (j = 0; j < 4; j++) |
| 4662 | class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, | 4661 | device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); |
| 4663 | j)); | ||
| 4664 | class_destroy(istallion_class); | 4662 | class_destroy(istallion_class); |
| 4665 | 4663 | ||
| 4666 | pci_unregister_driver(&stli_pcidriver); | 4664 | pci_unregister_driver(&stli_pcidriver); |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 62051f8b0910..c59e2a0996cc 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
| @@ -799,8 +799,7 @@ static int lp_register(int nr, struct parport *port) | |||
| 799 | if (reset) | 799 | if (reset) |
| 800 | lp_reset(nr); | 800 | lp_reset(nr); |
| 801 | 801 | ||
| 802 | class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev, | 802 | device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr); |
| 803 | "lp%d", nr); | ||
| 804 | 803 | ||
| 805 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, | 804 | printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, |
| 806 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); | 805 | (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); |
| @@ -971,7 +970,7 @@ static void lp_cleanup_module (void) | |||
| 971 | if (lp_table[offset].dev == NULL) | 970 | if (lp_table[offset].dev == NULL) |
| 972 | continue; | 971 | continue; |
| 973 | parport_unregister_device(lp_table[offset].dev); | 972 | parport_unregister_device(lp_table[offset].dev); |
| 974 | class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset)); | 973 | device_destroy(lp_class, MKDEV(LP_MAJOR, offset)); |
| 975 | } | 974 | } |
| 976 | class_destroy(lp_class); | 975 | class_destroy(lp_class); |
| 977 | } | 976 | } |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 4177f6db83e9..cc5d77797def 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
| @@ -1863,8 +1863,7 @@ static int cm4000_probe(struct pcmcia_device *link) | |||
| 1863 | return ret; | 1863 | return ret; |
| 1864 | } | 1864 | } |
| 1865 | 1865 | ||
| 1866 | class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, | 1866 | device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i); |
| 1867 | "cmm%d", i); | ||
| 1868 | 1867 | ||
| 1869 | return 0; | 1868 | return 0; |
| 1870 | } | 1869 | } |
| @@ -1888,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link) | |||
| 1888 | dev_table[devno] = NULL; | 1887 | dev_table[devno] = NULL; |
| 1889 | kfree(dev); | 1888 | kfree(dev); |
| 1890 | 1889 | ||
| 1891 | class_device_destroy(cmm_class, MKDEV(major, devno)); | 1890 | device_destroy(cmm_class, MKDEV(major, devno)); |
| 1892 | 1891 | ||
| 1893 | return; | 1892 | return; |
| 1894 | } | 1893 | } |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index b24a3e7bbb9f..a0b9c8728d56 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
| @@ -642,8 +642,7 @@ static int reader_probe(struct pcmcia_device *link) | |||
| 642 | return ret; | 642 | return ret; |
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, | 645 | device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i); |
| 646 | "cmx%d", i); | ||
| 647 | 646 | ||
| 648 | return 0; | 647 | return 0; |
| 649 | } | 648 | } |
| @@ -666,7 +665,7 @@ static void reader_detach(struct pcmcia_device *link) | |||
| 666 | dev_table[devno] = NULL; | 665 | dev_table[devno] = NULL; |
| 667 | kfree(dev); | 666 | kfree(dev); |
| 668 | 667 | ||
| 669 | class_device_destroy(cmx_class, MKDEV(major, devno)); | 668 | device_destroy(cmx_class, MKDEV(major, devno)); |
| 670 | 669 | ||
| 671 | return; | 670 | return; |
| 672 | } | 671 | } |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index de14aea34e11..73de77105fea 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
| @@ -248,14 +248,19 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
| 248 | return -ENOIOCTLCMD; | 248 | return -ENOIOCTLCMD; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | static int legacy_count = CONFIG_LEGACY_PTY_COUNT; | ||
| 252 | module_param(legacy_count, int, 0); | ||
| 253 | |||
| 251 | static void __init legacy_pty_init(void) | 254 | static void __init legacy_pty_init(void) |
| 252 | { | 255 | { |
| 256 | if (legacy_count <= 0) | ||
| 257 | return; | ||
| 253 | 258 | ||
| 254 | pty_driver = alloc_tty_driver(NR_PTYS); | 259 | pty_driver = alloc_tty_driver(legacy_count); |
| 255 | if (!pty_driver) | 260 | if (!pty_driver) |
| 256 | panic("Couldn't allocate pty driver"); | 261 | panic("Couldn't allocate pty driver"); |
| 257 | 262 | ||
| 258 | pty_slave_driver = alloc_tty_driver(NR_PTYS); | 263 | pty_slave_driver = alloc_tty_driver(legacy_count); |
| 259 | if (!pty_slave_driver) | 264 | if (!pty_slave_driver) |
| 260 | panic("Couldn't allocate pty slave driver"); | 265 | panic("Couldn't allocate pty slave driver"); |
| 261 | 266 | ||
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 1f0d7c60c944..bbfa0e241cba 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
| @@ -255,10 +255,7 @@ static const struct file_operations raw_ctl_fops = { | |||
| 255 | .owner = THIS_MODULE, | 255 | .owner = THIS_MODULE, |
| 256 | }; | 256 | }; |
| 257 | 257 | ||
| 258 | static struct cdev raw_cdev = { | 258 | static struct cdev raw_cdev; |
| 259 | .kobj = {.name = "raw", }, | ||
| 260 | .owner = THIS_MODULE, | ||
| 261 | }; | ||
| 262 | 259 | ||
| 263 | static int __init raw_init(void) | 260 | static int __init raw_init(void) |
| 264 | { | 261 | { |
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 52753e723eaa..b9c1dba6bd01 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
| @@ -441,8 +441,7 @@ scdrv_init(void) | |||
| 441 | continue; | 441 | continue; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | class_device_create(snsc_class, NULL, dev, NULL, | 444 | device_create(snsc_class, NULL, dev, "%s", devname); |
| 445 | "%s", devname); | ||
| 446 | 445 | ||
| 447 | ia64_sn_irtr_intr_enable(scd->scd_nasid, | 446 | ia64_sn_irtr_intr_enable(scd->scd_nasid, |
| 448 | 0 /*ignored */ , | 447 | 0 /*ignored */ , |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 4a80b2f864e0..45758d5b56ef 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
| @@ -4778,9 +4778,8 @@ static int __init stallion_module_init(void) | |||
| 4778 | if (IS_ERR(stallion_class)) | 4778 | if (IS_ERR(stallion_class)) |
| 4779 | printk("STALLION: failed to create class\n"); | 4779 | printk("STALLION: failed to create class\n"); |
| 4780 | for (i = 0; i < 4; i++) | 4780 | for (i = 0; i < 4; i++) |
| 4781 | class_device_create(stallion_class, NULL, | 4781 | device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), |
| 4782 | MKDEV(STL_SIOMEMMAJOR, i), NULL, | 4782 | "staliomem%d", i); |
| 4783 | "staliomem%d", i); | ||
| 4784 | 4783 | ||
| 4785 | return 0; | 4784 | return 0; |
| 4786 | err_unrtty: | 4785 | err_unrtty: |
| @@ -4816,7 +4815,7 @@ static void __exit stallion_module_exit(void) | |||
| 4816 | } | 4815 | } |
| 4817 | 4816 | ||
| 4818 | for (i = 0; i < 4; i++) | 4817 | for (i = 0; i < 4; i++) |
| 4819 | class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); | 4818 | device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); |
| 4820 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | 4819 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); |
| 4821 | class_destroy(stallion_class); | 4820 | class_destroy(stallion_class); |
| 4822 | 4821 | ||
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 35b40b996534..cef55c40654f 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c | |||
| @@ -441,8 +441,8 @@ tipar_register(int nr, struct parport *port) | |||
| 441 | goto out; | 441 | goto out; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, | 444 | device_create(tipar_class, port->dev, MKDEV(TIPAR_MAJOR, |
| 445 | TIPAR_MINOR + nr), port->dev, "par%d", nr); | 445 | TIPAR_MINOR + nr), "par%d", nr); |
| 446 | 446 | ||
| 447 | /* Display informations */ | 447 | /* Display informations */ |
| 448 | pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == | 448 | pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == |
| @@ -534,7 +534,7 @@ tipar_cleanup_module(void) | |||
| 534 | if (table[i].dev == NULL) | 534 | if (table[i].dev == NULL) |
| 535 | continue; | 535 | continue; |
| 536 | parport_unregister_device(table[i].dev); | 536 | parport_unregister_device(table[i].dev); |
| 537 | class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); | 537 | device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); |
| 538 | } | 538 | } |
| 539 | class_destroy(tipar_class); | 539 | class_destroy(tipar_class); |
| 540 | 540 | ||
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index f1d60f0cef8f..db7a731e2362 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
| @@ -871,10 +871,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
| 871 | state[i].cur_part = 0; | 871 | state[i].cur_part = 0; |
| 872 | for (j = 0; j < MAX_PARTITIONS; ++j) | 872 | for (j = 0; j < MAX_PARTITIONS; ++j) |
| 873 | state[i].part_stat_rwi[j] = VIOT_IDLE; | 873 | state[i].part_stat_rwi[j] = VIOT_IDLE; |
| 874 | class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL, | 874 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), |
| 875 | "iseries!vt%d", i); | 875 | "iseries!vt%d", i); |
| 876 | class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), | 876 | device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), |
| 877 | NULL, "iseries!nvt%d", i); | 877 | "iseries!nvt%d", i); |
| 878 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " | 878 | printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " |
| 879 | "resource %10.10s type %4.4s, model %3.3s\n", | 879 | "resource %10.10s type %4.4s, model %3.3s\n", |
| 880 | i, viotape_unitinfo[i].rsrcname, | 880 | i, viotape_unitinfo[i].rsrcname, |
| @@ -886,8 +886,8 @@ static int viotape_remove(struct vio_dev *vdev) | |||
| 886 | { | 886 | { |
| 887 | int i = vdev->unit_address; | 887 | int i = vdev->unit_address; |
| 888 | 888 | ||
| 889 | class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80)); | 889 | device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80)); |
| 890 | class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i)); | 890 | device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i)); |
| 891 | return 0; | 891 | return 0; |
| 892 | } | 892 | } |
| 893 | 893 | ||
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 2f6a73c01b71..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 | */ |
| @@ -828,7 +830,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
| 828 | /* prepare interface data */ | 830 | /* prepare interface data */ |
| 829 | policy->kobj.parent = &sys_dev->kobj; | 831 | policy->kobj.parent = &sys_dev->kobj; |
| 830 | policy->kobj.ktype = &ktype_cpufreq; | 832 | policy->kobj.ktype = &ktype_cpufreq; |
| 831 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); | 833 | kobject_set_name(&policy->kobj, "cpufreq"); |
| 832 | 834 | ||
| 833 | ret = kobject_register(&policy->kobj); | 835 | ret = kobject_register(&policy->kobj); |
| 834 | if (ret) { | 836 | if (ret) { |
| @@ -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/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 4a0576bd06fc..3706b2bc0987 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -743,7 +743,7 @@ static struct kobj_type ktype_mc_set_attribs = { | |||
| 743 | * /sys/devices/system/edac/mc | 743 | * /sys/devices/system/edac/mc |
| 744 | */ | 744 | */ |
| 745 | static struct kset mc_kset = { | 745 | static struct kset mc_kset = { |
| 746 | .kobj = {.name = "mc", .ktype = &ktype_mc_set_attribs }, | 746 | .kobj = {.ktype = &ktype_mc_set_attribs }, |
| 747 | .ktype = &ktype_mci, | 747 | .ktype = &ktype_mci, |
| 748 | }; | 748 | }; |
| 749 | 749 | ||
| @@ -1010,6 +1010,7 @@ int edac_sysfs_setup_mc_kset(void) | |||
| 1010 | } | 1010 | } |
| 1011 | 1011 | ||
| 1012 | /* Init the MC's kobject */ | 1012 | /* Init the MC's kobject */ |
| 1013 | kobject_set_name(&mc_kset.kobj, "mc"); | ||
| 1013 | mc_kset.kobj.parent = &edac_class->kset.kobj; | 1014 | mc_kset.kobj.parent = &edac_class->kset.kobj; |
| 1014 | 1015 | ||
| 1015 | /* register the mc_kset */ | 1016 | /* register the mc_kset */ |
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index d944647c82c2..4d4a47393909 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c | |||
| @@ -128,16 +128,11 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv) | |||
| 128 | return 0; | 128 | return 0; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp, | 131 | static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 132 | char *buffer, int buffer_size) | ||
| 133 | { | 132 | { |
| 134 | struct eisa_device *edev = to_eisa_device(dev); | 133 | struct eisa_device *edev = to_eisa_device(dev); |
| 135 | int i = 0; | ||
| 136 | int length = 0; | ||
| 137 | 134 | ||
| 138 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 135 | add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); |
| 139 | "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig); | ||
| 140 | envp[i] = NULL; | ||
| 141 | return 0; | 136 | return 0; |
| 142 | } | 137 | } |
| 143 | 138 | ||
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2b6586341635..56681b3b297b 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
| @@ -130,23 +130,16 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) | |||
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static int | 132 | static int |
| 133 | fw_unit_uevent(struct device *dev, char **envp, int num_envp, | 133 | fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 134 | char *buffer, int buffer_size) | ||
| 135 | { | 134 | { |
| 136 | struct fw_unit *unit = fw_unit(dev); | 135 | struct fw_unit *unit = fw_unit(dev); |
| 137 | char modalias[64]; | 136 | char modalias[64]; |
| 138 | int length = 0; | ||
| 139 | int i = 0; | ||
| 140 | 137 | ||
| 141 | get_modalias(unit, modalias, sizeof(modalias)); | 138 | get_modalias(unit, modalias, sizeof(modalias)); |
| 142 | 139 | ||
| 143 | if (add_uevent_var(envp, num_envp, &i, | 140 | if (add_uevent_var(env, "MODALIAS=%s", modalias)) |
| 144 | buffer, buffer_size, &length, | ||
| 145 | "MODALIAS=%s", modalias)) | ||
| 146 | return -ENOMEM; | 141 | return -ENOMEM; |
| 147 | 142 | ||
| 148 | envp[i] = NULL; | ||
| 149 | |||
| 150 | return 0; | 143 | return 0; |
| 151 | } | 144 | } |
| 152 | 145 | ||
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 59c3b5aa89f4..b6e1eb77d148 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c | |||
| @@ -13,21 +13,31 @@ | |||
| 13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 14 | #include <linux/autoconf.h> | 14 | #include <linux/autoconf.h> |
| 15 | 15 | ||
| 16 | #define DEFINE_DMI_ATTR(_name, _mode, _show) \ | 16 | struct dmi_device_attribute{ |
| 17 | static struct device_attribute sys_dmi_##_name##_attr = \ | 17 | struct device_attribute dev_attr; |
| 18 | __ATTR(_name, _mode, _show, NULL); | 18 | int field; |
| 19 | 19 | }; | |
| 20 | #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \ | 20 | #define to_dmi_dev_attr(_dev_attr) \ |
| 21 | static ssize_t sys_dmi_##_name##_show(struct device *dev, \ | 21 | container_of(_dev_attr, struct dmi_device_attribute, dev_attr) |
| 22 | struct device_attribute *attr, \ | 22 | |
| 23 | char *page) \ | 23 | static ssize_t sys_dmi_field_show(struct device *dev, |
| 24 | { \ | 24 | struct device_attribute *attr, |
| 25 | ssize_t len; \ | 25 | char *page) |
| 26 | len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \ | 26 | { |
| 27 | page[len-1] = '\n'; \ | 27 | int field = to_dmi_dev_attr(attr)->field; |
| 28 | return len; \ | 28 | ssize_t len; |
| 29 | } \ | 29 | len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(field)); |
| 30 | DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show); | 30 | page[len-1] = '\n'; |
| 31 | return len; | ||
| 32 | } | ||
| 33 | |||
| 34 | #define DMI_ATTR(_name, _mode, _show, _field) \ | ||
| 35 | { .dev_attr = __ATTR(_name, _mode, _show, NULL), \ | ||
| 36 | .field = _field } | ||
| 37 | |||
| 38 | #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \ | ||
| 39 | static struct dmi_device_attribute sys_dmi_##_name##_attr = \ | ||
| 40 | DMI_ATTR(_name, _mode, sys_dmi_field_show, _field); | ||
| 31 | 41 | ||
| 32 | DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR); | 42 | DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR); |
| 33 | DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION); | 43 | DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION); |
| @@ -121,7 +131,8 @@ static ssize_t sys_dmi_modalias_show(struct device *dev, | |||
| 121 | return r+1; | 131 | return r+1; |
| 122 | } | 132 | } |
| 123 | 133 | ||
| 124 | DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show); | 134 | static struct device_attribute sys_dmi_modalias_attr = |
| 135 | __ATTR(modalias, 0444, sys_dmi_modalias_show, NULL); | ||
| 125 | 136 | ||
| 126 | static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2]; | 137 | static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2]; |
| 127 | 138 | ||
| @@ -134,14 +145,17 @@ static struct attribute_group* sys_dmi_attribute_groups[] = { | |||
| 134 | NULL | 145 | NULL |
| 135 | }; | 146 | }; |
| 136 | 147 | ||
| 137 | static int dmi_dev_uevent(struct device *dev, char **envp, | 148 | static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 138 | int num_envp, char *buffer, int buffer_size) | ||
| 139 | { | 149 | { |
| 140 | strcpy(buffer, "MODALIAS="); | 150 | ssize_t len; |
| 141 | get_modalias(buffer+9, buffer_size-9); | 151 | |
| 142 | envp[0] = buffer; | 152 | if (add_uevent_var(env, "MODALIAS=")) |
| 143 | envp[1] = NULL; | 153 | return -ENOMEM; |
| 144 | 154 | len = get_modalias(&env->buf[env->buflen - 1], | |
| 155 | sizeof(env->buf) - env->buflen); | ||
| 156 | if (len >= (sizeof(env->buf) - env->buflen)) | ||
| 157 | return -ENOMEM; | ||
| 158 | env->buflen += len; | ||
| 145 | return 0; | 159 | return 0; |
| 146 | } | 160 | } |
| 147 | 161 | ||
| @@ -157,7 +171,7 @@ static struct device *dmi_dev; | |||
| 157 | 171 | ||
| 158 | #define ADD_DMI_ATTR(_name, _field) \ | 172 | #define ADD_DMI_ATTR(_name, _field) \ |
| 159 | if (dmi_get_system_info(_field)) \ | 173 | if (dmi_get_system_info(_field)) \ |
| 160 | sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr; | 174 | sys_dmi_attributes[i++] = &sys_dmi_##_name##_attr.dev_attr.attr; |
| 161 | 175 | ||
| 162 | extern int dmi_available; | 176 | extern int dmi_available; |
| 163 | 177 | ||
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 0fb730ee1da8..6942e065e609 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c | |||
| @@ -625,13 +625,13 @@ static void edd_release(struct kobject * kobj) | |||
| 625 | kfree(dev); | 625 | kfree(dev); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | static struct kobj_type ktype_edd = { | 628 | static struct kobj_type edd_ktype = { |
| 629 | .release = edd_release, | 629 | .release = edd_release, |
| 630 | .sysfs_ops = &edd_attr_ops, | 630 | .sysfs_ops = &edd_attr_ops, |
| 631 | .default_attrs = def_attrs, | 631 | .default_attrs = def_attrs, |
| 632 | }; | 632 | }; |
| 633 | 633 | ||
| 634 | static decl_subsys(edd,&ktype_edd,NULL); | 634 | static decl_subsys(edd, &edd_ktype, NULL); |
| 635 | 635 | ||
| 636 | 636 | ||
| 637 | /** | 637 | /** |
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index bfd2d67df689..858a7b95933b 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
| @@ -402,7 +402,7 @@ static struct attribute *def_attrs[] = { | |||
| 402 | NULL, | 402 | NULL, |
| 403 | }; | 403 | }; |
| 404 | 404 | ||
| 405 | static struct kobj_type ktype_efivar = { | 405 | static struct kobj_type efivar_ktype = { |
| 406 | .release = efivar_release, | 406 | .release = efivar_release, |
| 407 | .sysfs_ops = &efivar_attr_ops, | 407 | .sysfs_ops = &efivar_attr_ops, |
| 408 | .default_attrs = def_attrs, | 408 | .default_attrs = def_attrs, |
| @@ -583,7 +583,7 @@ static struct subsys_attribute *efi_subsys_attrs[] = { | |||
| 583 | NULL, /* maybe more in the future? */ | 583 | NULL, /* maybe more in the future? */ |
| 584 | }; | 584 | }; |
| 585 | 585 | ||
| 586 | static decl_subsys(vars, &ktype_efivar, NULL); | 586 | static decl_subsys(vars, &efivar_ktype, NULL); |
| 587 | static decl_subsys(efi, NULL, NULL); | 587 | static decl_subsys(efi, NULL, NULL); |
| 588 | 588 | ||
| 589 | /* | 589 | /* |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d663e6960d93..910a62de190d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -67,20 +67,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) | |||
| 67 | #ifdef CONFIG_HOTPLUG | 67 | #ifdef CONFIG_HOTPLUG |
| 68 | 68 | ||
| 69 | /* uevent helps with hotplug: modprobe -q $(MODALIAS) */ | 69 | /* uevent helps with hotplug: modprobe -q $(MODALIAS) */ |
| 70 | static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, | 70 | static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 71 | char *buffer, int buffer_size) | ||
| 72 | { | 71 | { |
| 73 | struct i2c_client *client = to_i2c_client(dev); | 72 | struct i2c_client *client = to_i2c_client(dev); |
| 74 | int i = 0, length = 0; | ||
| 75 | 73 | ||
| 76 | /* by definition, legacy drivers can't hotplug */ | 74 | /* by definition, legacy drivers can't hotplug */ |
| 77 | if (dev->driver || !client->driver_name) | 75 | if (dev->driver || !client->driver_name) |
| 78 | return 0; | 76 | return 0; |
| 79 | 77 | ||
| 80 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 78 | if (add_uevent_var(env, "MODALIAS=%s", client->driver_name)) |
| 81 | "MODALIAS=%s", client->driver_name)) | ||
| 82 | return -ENOMEM; | 79 | return -ENOMEM; |
| 83 | envp[i] = NULL; | ||
| 84 | dev_dbg(dev, "uevent\n"); | 80 | dev_dbg(dev, "uevent\n"); |
| 85 | return 0; | 81 | return 0; |
| 86 | } | 82 | } |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index e96212ce5729..a96a8b1b3539 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
| @@ -1663,20 +1663,13 @@ static struct device_attribute ide_dev_attrs[] = { | |||
| 1663 | __ATTR_NULL | 1663 | __ATTR_NULL |
| 1664 | }; | 1664 | }; |
| 1665 | 1665 | ||
| 1666 | static int ide_uevent(struct device *dev, char **envp, int num_envp, | 1666 | static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1667 | char *buffer, int buffer_size) | ||
| 1668 | { | 1667 | { |
| 1669 | ide_drive_t *drive = to_ide_device(dev); | 1668 | ide_drive_t *drive = to_ide_device(dev); |
| 1670 | int i = 0; | 1669 | |
| 1671 | int length = 0; | 1670 | add_uevent_var(env, "MEDIA=%s", media_string(drive)); |
| 1672 | 1671 | add_uevent_var(env, "DRIVENAME=%s", drive->name); | |
| 1673 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 1672 | add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); |
| 1674 | "MEDIA=%s", media_string(drive)); | ||
| 1675 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | ||
| 1676 | "DRIVENAME=%s", drive->name); | ||
| 1677 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | ||
| 1678 | "MODALIAS=ide:m-%s", media_string(drive)); | ||
| 1679 | envp[i] = NULL; | ||
| 1680 | return 0; | 1673 | return 0; |
| 1681 | } | 1674 | } |
| 1682 | 1675 | ||
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2ffd53461db6..1939fee616ec 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
| @@ -153,8 +153,7 @@ struct host_info { | |||
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); | 155 | static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); |
| 156 | static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, | 156 | static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); |
| 157 | char *buffer, int buffer_size); | ||
| 158 | static void nodemgr_resume_ne(struct node_entry *ne); | 157 | static void nodemgr_resume_ne(struct node_entry *ne); |
| 159 | static void nodemgr_remove_ne(struct node_entry *ne); | 158 | static void nodemgr_remove_ne(struct node_entry *ne); |
| 160 | static struct node_entry *find_entry_by_guid(u64 guid); | 159 | static struct node_entry *find_entry_by_guid(u64 guid); |
| @@ -1160,12 +1159,9 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent | |||
| 1160 | 1159 | ||
| 1161 | #ifdef CONFIG_HOTPLUG | 1160 | #ifdef CONFIG_HOTPLUG |
| 1162 | 1161 | ||
| 1163 | static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, | 1162 | static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1164 | char *buffer, int buffer_size) | ||
| 1165 | { | 1163 | { |
| 1166 | struct unit_directory *ud; | 1164 | struct unit_directory *ud; |
| 1167 | int i = 0; | ||
| 1168 | int length = 0; | ||
| 1169 | int retval = 0; | 1165 | int retval = 0; |
| 1170 | /* ieee1394:venNmoNspNverN */ | 1166 | /* ieee1394:venNmoNspNverN */ |
| 1171 | char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; | 1167 | char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; |
| @@ -1180,9 +1176,7 @@ static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1180 | 1176 | ||
| 1181 | #define PUT_ENVP(fmt,val) \ | 1177 | #define PUT_ENVP(fmt,val) \ |
| 1182 | do { \ | 1178 | do { \ |
| 1183 | retval = add_uevent_var(envp, num_envp, &i, \ | 1179 | retval = add_uevent_var(env, fmt, val); \ |
| 1184 | buffer, buffer_size, &length, \ | ||
| 1185 | fmt, val); \ | ||
| 1186 | if (retval) \ | 1180 | if (retval) \ |
| 1187 | return retval; \ | 1181 | return retval; \ |
| 1188 | } while (0) | 1182 | } while (0) |
| @@ -1201,15 +1195,12 @@ do { \ | |||
| 1201 | 1195 | ||
| 1202 | #undef PUT_ENVP | 1196 | #undef PUT_ENVP |
| 1203 | 1197 | ||
| 1204 | envp[i] = NULL; | ||
| 1205 | |||
| 1206 | return 0; | 1198 | return 0; |
| 1207 | } | 1199 | } |
| 1208 | 1200 | ||
| 1209 | #else | 1201 | #else |
| 1210 | 1202 | ||
| 1211 | static int nodemgr_uevent(struct device *dev, char **envp, int num_envp, | 1203 | static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1212 | char *buffer, int buffer_size) | ||
| 1213 | { | 1204 | { |
| 1214 | return -ENODEV; | 1205 | return -ENODEV; |
| 1215 | } | 1206 | } |
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 70b77ae67422..3d4050681325 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
| @@ -434,21 +434,18 @@ static void ib_device_release(struct class_device *cdev) | |||
| 434 | kfree(dev); | 434 | kfree(dev); |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | static int ib_device_uevent(struct class_device *cdev, char **envp, | 437 | static int ib_device_uevent(struct class_device *cdev, |
| 438 | int num_envp, char *buf, int size) | 438 | struct kobj_uevent_env *env) |
| 439 | { | 439 | { |
| 440 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); | 440 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); |
| 441 | int i = 0, len = 0; | ||
| 442 | 441 | ||
| 443 | if (add_uevent_var(envp, num_envp, &i, buf, size, &len, | 442 | if (add_uevent_var(env, "NAME=%s", dev->name)) |
| 444 | "NAME=%s", dev->name)) | ||
| 445 | return -ENOMEM; | 443 | return -ENOMEM; |
| 446 | 444 | ||
| 447 | /* | 445 | /* |
| 448 | * It would be nice to pass the node GUID with the event... | 446 | * It would be nice to pass the node GUID with the event... |
| 449 | */ | 447 | */ |
| 450 | 448 | ||
| 451 | envp[i] = NULL; | ||
| 452 | return 0; | 449 | return 0; |
| 453 | } | 450 | } |
| 454 | 451 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5fe755586623..5dc361c954e2 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -859,87 +859,66 @@ static void input_dev_release(struct device *device) | |||
| 859 | * Input uevent interface - loading event handlers based on | 859 | * Input uevent interface - loading event handlers based on |
| 860 | * device bitfields. | 860 | * device bitfields. |
| 861 | */ | 861 | */ |
| 862 | static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, | 862 | static int input_add_uevent_bm_var(struct kobj_uevent_env *env, |
| 863 | char *buffer, int buffer_size, int *cur_len, | ||
| 864 | const char *name, unsigned long *bitmap, int max) | 863 | const char *name, unsigned long *bitmap, int max) |
| 865 | { | 864 | { |
| 866 | if (*cur_index >= num_envp - 1) | 865 | int len; |
| 867 | return -ENOMEM; | ||
| 868 | |||
| 869 | envp[*cur_index] = buffer + *cur_len; | ||
| 870 | 866 | ||
| 871 | *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); | 867 | if (add_uevent_var(env, "%s=", name)) |
| 872 | if (*cur_len >= buffer_size) | ||
| 873 | return -ENOMEM; | 868 | return -ENOMEM; |
| 874 | 869 | ||
| 875 | *cur_len += input_print_bitmap(buffer + *cur_len, | 870 | len = input_print_bitmap(&env->buf[env->buflen - 1], |
| 876 | max(buffer_size - *cur_len, 0), | 871 | sizeof(env->buf) - env->buflen, |
| 877 | bitmap, max, 0) + 1; | 872 | bitmap, max, 0); |
| 878 | if (*cur_len > buffer_size) | 873 | if (len >= (sizeof(env->buf) - env->buflen)) |
| 879 | return -ENOMEM; | 874 | return -ENOMEM; |
| 880 | 875 | ||
| 881 | (*cur_index)++; | 876 | env->buflen += len; |
| 882 | return 0; | 877 | return 0; |
| 883 | } | 878 | } |
| 884 | 879 | ||
| 885 | static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, | 880 | static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, |
| 886 | char *buffer, int buffer_size, int *cur_len, | ||
| 887 | struct input_dev *dev) | 881 | struct input_dev *dev) |
| 888 | { | 882 | { |
| 889 | if (*cur_index >= num_envp - 1) | 883 | int len; |
| 890 | return -ENOMEM; | ||
| 891 | |||
| 892 | envp[*cur_index] = buffer + *cur_len; | ||
| 893 | 884 | ||
| 894 | *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), | 885 | if (add_uevent_var(env, "MODALIAS=")) |
| 895 | "MODALIAS="); | ||
| 896 | if (*cur_len >= buffer_size) | ||
| 897 | return -ENOMEM; | 886 | return -ENOMEM; |
| 898 | 887 | ||
| 899 | *cur_len += input_print_modalias(buffer + *cur_len, | 888 | len = input_print_modalias(&env->buf[env->buflen - 1], |
| 900 | max(buffer_size - *cur_len, 0), | 889 | sizeof(env->buf) - env->buflen, |
| 901 | dev, 0) + 1; | 890 | dev, 0); |
| 902 | if (*cur_len > buffer_size) | 891 | if (len >= (sizeof(env->buf) - env->buflen)) |
| 903 | return -ENOMEM; | 892 | return -ENOMEM; |
| 904 | 893 | ||
| 905 | (*cur_index)++; | 894 | env->buflen += len; |
| 906 | return 0; | 895 | return 0; |
| 907 | } | 896 | } |
| 908 | 897 | ||
| 909 | #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ | 898 | #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ |
| 910 | do { \ | 899 | do { \ |
| 911 | int err = add_uevent_var(envp, num_envp, &i, \ | 900 | int err = add_uevent_var(env, fmt, val); \ |
| 912 | buffer, buffer_size, &len, \ | ||
| 913 | fmt, val); \ | ||
| 914 | if (err) \ | 901 | if (err) \ |
| 915 | return err; \ | 902 | return err; \ |
| 916 | } while (0) | 903 | } while (0) |
| 917 | 904 | ||
| 918 | #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ | 905 | #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ |
| 919 | do { \ | 906 | do { \ |
| 920 | int err = input_add_uevent_bm_var(envp, num_envp, &i, \ | 907 | int err = input_add_uevent_bm_var(env, name, bm, max); \ |
| 921 | buffer, buffer_size, &len, \ | ||
| 922 | name, bm, max); \ | ||
| 923 | if (err) \ | 908 | if (err) \ |
| 924 | return err; \ | 909 | return err; \ |
| 925 | } while (0) | 910 | } while (0) |
| 926 | 911 | ||
| 927 | #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ | 912 | #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ |
| 928 | do { \ | 913 | do { \ |
| 929 | int err = input_add_uevent_modalias_var(envp, \ | 914 | int err = input_add_uevent_modalias_var(env, dev); \ |
| 930 | num_envp, &i, \ | ||
| 931 | buffer, buffer_size, &len, \ | ||
| 932 | dev); \ | ||
| 933 | if (err) \ | 915 | if (err) \ |
| 934 | return err; \ | 916 | return err; \ |
| 935 | } while (0) | 917 | } while (0) |
| 936 | 918 | ||
| 937 | static int input_dev_uevent(struct device *device, char **envp, | 919 | static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) |
| 938 | int num_envp, char *buffer, int buffer_size) | ||
| 939 | { | 920 | { |
| 940 | struct input_dev *dev = to_input_dev(device); | 921 | struct input_dev *dev = to_input_dev(device); |
| 941 | int i = 0; | ||
| 942 | int len = 0; | ||
| 943 | 922 | ||
| 944 | INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", | 923 | INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", |
| 945 | dev->id.bustype, dev->id.vendor, | 924 | dev->id.bustype, dev->id.vendor, |
| @@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp, | |||
| 971 | 950 | ||
| 972 | INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); | 951 | INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); |
| 973 | 952 | ||
| 974 | envp[i] = NULL; | ||
| 975 | return 0; | 953 | return 0; |
| 976 | } | 954 | } |
| 977 | 955 | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 906bf5e8de89..c19f77fbaf2a 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -17,17 +17,18 @@ | |||
| 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>"); |
| 24 | MODULE_DESCRIPTION("PC Speaker beeper driver"); | 23 | MODULE_DESCRIPTION("PC Speaker beeper driver"); |
| 25 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
| 25 | MODULE_ALIAS("platform:pcspkr"); | ||
| 26 | 26 | ||
| 27 | #ifdef CONFIG_X86 | 27 | #ifdef CONFIG_X86 |
| 28 | /* Use the global PIT lock ! */ | 28 | /* Use the global PIT lock ! */ |
| 29 | #include <asm/i8253.h> | 29 | #include <asm/i8253.h> |
| 30 | #else | 30 | #else |
| 31 | #include <asm/8253pit.h> | ||
| 31 | static DEFINE_SPINLOCK(i8253_lock); | 32 | static DEFINE_SPINLOCK(i8253_lock); |
| 32 | #endif | 33 | #endif |
| 33 | 34 | ||
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 372ca4931194..b3bc15acd3f5 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -876,18 +876,14 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) | |||
| 876 | 876 | ||
| 877 | #define SERIO_ADD_UEVENT_VAR(fmt, val...) \ | 877 | #define SERIO_ADD_UEVENT_VAR(fmt, val...) \ |
| 878 | do { \ | 878 | do { \ |
| 879 | int err = add_uevent_var(envp, num_envp, &i, \ | 879 | int err = add_uevent_var(env, fmt, val); \ |
| 880 | buffer, buffer_size, &len, \ | ||
| 881 | fmt, val); \ | ||
| 882 | if (err) \ | 880 | if (err) \ |
| 883 | return err; \ | 881 | return err; \ |
| 884 | } while (0) | 882 | } while (0) |
| 885 | 883 | ||
| 886 | static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) | 884 | static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 887 | { | 885 | { |
| 888 | struct serio *serio; | 886 | struct serio *serio; |
| 889 | int i = 0; | ||
| 890 | int len = 0; | ||
| 891 | 887 | ||
| 892 | if (!dev) | 888 | if (!dev) |
| 893 | return -ENODEV; | 889 | return -ENODEV; |
| @@ -900,7 +896,6 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf | |||
| 900 | SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); | 896 | SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra); |
| 901 | SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", | 897 | SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X", |
| 902 | serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); | 898 | serio->id.type, serio->id.proto, serio->id.id, serio->id.extra); |
| 903 | envp[i] = NULL; | ||
| 904 | 899 | ||
| 905 | return 0; | 900 | return 0; |
| 906 | } | 901 | } |
| @@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf | |||
| 908 | 903 | ||
| 909 | #else | 904 | #else |
| 910 | 905 | ||
| 911 | static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) | 906 | static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 912 | { | 907 | { |
| 913 | return -ENODEV; | 908 | return -ENODEV; |
| 914 | } | 909 | } |
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/md/md.c b/drivers/md/md.c index e8f102ea9b03..acf1b81b47cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -3076,8 +3076,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
| 3076 | mddev->gendisk = disk; | 3076 | mddev->gendisk = disk; |
| 3077 | mutex_unlock(&disks_mutex); | 3077 | mutex_unlock(&disks_mutex); |
| 3078 | mddev->kobj.parent = &disk->kobj; | 3078 | mddev->kobj.parent = &disk->kobj; |
| 3079 | mddev->kobj.k_name = NULL; | 3079 | kobject_set_name(&mddev->kobj, "%s", "md"); |
| 3080 | snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); | ||
| 3081 | mddev->kobj.ktype = &md_ktype; | 3080 | mddev->kobj.ktype = &md_ktype; |
| 3082 | if (kobject_register(&mddev->kobj)) | 3081 | if (kobject_register(&mddev->kobj)) |
| 3083 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", | 3082 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", |
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 56231d8edc07..18738faecbbc 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c | |||
| @@ -103,10 +103,7 @@ static struct file_operations dvb_device_fops = | |||
| 103 | .open = dvb_device_open, | 103 | .open = dvb_device_open, |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | static struct cdev dvb_device_cdev = { | 106 | static struct cdev dvb_device_cdev; |
| 107 | .kobj = {.name = "dvb", }, | ||
| 108 | .owner = THIS_MODULE, | ||
| 109 | }; | ||
| 110 | 107 | ||
| 111 | int dvb_generic_open(struct inode *inode, struct file *file) | 108 | int dvb_generic_open(struct inode *inode, struct file *file) |
| 112 | { | 109 | { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7a78d6b34738..2ee3c3049e8f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
| @@ -905,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, | |||
| 905 | } | 905 | } |
| 906 | 906 | ||
| 907 | 907 | ||
| 908 | static int pvr2_sysfs_hotplug(struct device *cd,char **envp, | 908 | static int pvr2_sysfs_hotplug(struct device *d, |
| 909 | int numenvp,char *buf,int size) | 909 | struct kobj_uevent_env *env) |
| 910 | { | 910 | { |
| 911 | /* Even though we don't do anything here, we still need this function | 911 | /* Even though we don't do anything here, we still need this function |
| 912 | because sysfs will still try to call it. */ | 912 | because sysfs will still try to call it. */ |
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index d195fb088f4a..8f77949f93dd 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c | |||
| @@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv) | |||
| 57 | return 0; | 57 | return 0; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static int tifm_uevent(struct device *dev, char **envp, int num_envp, | 60 | static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 61 | char *buffer, int buffer_size) | ||
| 62 | { | 61 | { |
| 63 | struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); | 62 | struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); |
| 64 | int i = 0; | ||
| 65 | int length = 0; | ||
| 66 | 63 | ||
| 67 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 64 | if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1))) |
| 68 | "TIFM_CARD_TYPE=%s", | ||
| 69 | tifm_media_type_name(sock->type, 1))) | ||
| 70 | return -ENOMEM; | 65 | return -ENOMEM; |
| 71 | 66 | ||
| 72 | return 0; | 67 | return 0; |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 8d6f6014870f..b0c22cad9423 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -58,12 +58,11 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv) | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static int | 60 | static int |
| 61 | mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, | 61 | mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 62 | int buf_size) | ||
| 63 | { | 62 | { |
| 64 | struct mmc_card *card = dev_to_mmc_card(dev); | 63 | struct mmc_card *card = dev_to_mmc_card(dev); |
| 65 | const char *type; | 64 | const char *type; |
| 66 | int i = 0, length = 0; | 65 | int retval = 0; |
| 67 | 66 | ||
| 68 | switch (card->type) { | 67 | switch (card->type) { |
| 69 | case MMC_TYPE_MMC: | 68 | case MMC_TYPE_MMC: |
| @@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, | |||
| 80 | } | 79 | } |
| 81 | 80 | ||
| 82 | if (type) { | 81 | if (type) { |
| 83 | if (add_uevent_var(envp, num_envp, &i, | 82 | retval = add_uevent_var(env, "MMC_TYPE=%s", type); |
| 84 | buf, buf_size, &length, | 83 | if (retval) |
| 85 | "MMC_TYPE=%s", type)) | 84 | return retval; |
| 86 | return -ENOMEM; | ||
| 87 | } | 85 | } |
| 88 | 86 | ||
| 89 | if (add_uevent_var(envp, num_envp, &i, | 87 | retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); |
| 90 | buf, buf_size, &length, | ||
| 91 | "MMC_NAME=%s", mmc_card_name(card))) | ||
| 92 | return -ENOMEM; | ||
| 93 | 88 | ||
| 94 | envp[i] = NULL; | 89 | return retval; |
| 95 | |||
| 96 | return 0; | ||
| 97 | } | 90 | } |
| 98 | 91 | ||
| 99 | static int mmc_bus_probe(struct device *dev) | 92 | static int mmc_bus_probe(struct device *dev) |
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/ibmveth.c b/drivers/net/ibmveth.c index 4ac161e1ca12..7d7758f3ad8c 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
| @@ -1183,7 +1183,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ | |||
| 1183 | pool_count[i], pool_size[i], | 1183 | pool_count[i], pool_size[i], |
| 1184 | pool_active[i]); | 1184 | pool_active[i]); |
| 1185 | kobj->parent = &dev->dev.kobj; | 1185 | kobj->parent = &dev->dev.kobj; |
| 1186 | sprintf(kobj->name, "pool%d", i); | 1186 | kobject_set_name(kobj, "pool%d", i); |
| 1187 | kobj->ktype = &ktype_veth_pool; | 1187 | kobj->ktype = &ktype_veth_pool; |
| 1188 | kobject_register(kobj); | 1188 | kobject_register(kobj); |
| 1189 | } | 1189 | } |
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/pci/hotplug.c b/drivers/pci/hotplug.c index 1c97e7dd130b..2b5352a7dffc 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c | |||
| @@ -3,12 +3,9 @@ | |||
| 3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 4 | #include "pci.h" | 4 | #include "pci.h" |
| 5 | 5 | ||
| 6 | int pci_uevent(struct device *dev, char **envp, int num_envp, | 6 | int pci_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 7 | char *buffer, int buffer_size) | ||
| 8 | { | 7 | { |
| 9 | struct pci_dev *pdev; | 8 | struct pci_dev *pdev; |
| 10 | int i = 0; | ||
| 11 | int length = 0; | ||
| 12 | 9 | ||
| 13 | if (!dev) | 10 | if (!dev) |
| 14 | return -ENODEV; | 11 | return -ENODEV; |
| @@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp, | |||
| 17 | if (!pdev) | 14 | if (!pdev) |
| 18 | return -ENODEV; | 15 | return -ENODEV; |
| 19 | 16 | ||
| 20 | if (add_uevent_var(envp, num_envp, &i, | 17 | if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) |
| 21 | buffer, buffer_size, &length, | ||
| 22 | "PCI_CLASS=%04X", pdev->class)) | ||
| 23 | return -ENOMEM; | 18 | return -ENOMEM; |
| 24 | 19 | ||
| 25 | if (add_uevent_var(envp, num_envp, &i, | 20 | if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) |
| 26 | buffer, buffer_size, &length, | ||
| 27 | "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) | ||
| 28 | return -ENOMEM; | 21 | return -ENOMEM; |
| 29 | 22 | ||
| 30 | if (add_uevent_var(envp, num_envp, &i, | 23 | if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, |
| 31 | buffer, buffer_size, &length, | ||
| 32 | "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, | ||
| 33 | pdev->subsystem_device)) | 24 | pdev->subsystem_device)) |
| 34 | return -ENOMEM; | 25 | return -ENOMEM; |
| 35 | 26 | ||
| 36 | if (add_uevent_var(envp, num_envp, &i, | 27 | if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) |
| 37 | buffer, buffer_size, &length, | ||
| 38 | "PCI_SLOT_NAME=%s", pci_name(pdev))) | ||
| 39 | return -ENOMEM; | 28 | return -ENOMEM; |
| 40 | 29 | ||
| 41 | if (add_uevent_var(envp, num_envp, &i, | 30 | if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", |
| 42 | buffer, buffer_size, &length, | ||
| 43 | "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", | ||
| 44 | pdev->vendor, pdev->device, | 31 | pdev->vendor, pdev->device, |
| 45 | pdev->subsystem_vendor, pdev->subsystem_device, | 32 | pdev->subsystem_vendor, pdev->subsystem_device, |
| 46 | (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), | 33 | (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), |
| 47 | (u8)(pdev->class))) | 34 | (u8)(pdev->class))) |
| 48 | return -ENOMEM; | 35 | return -ENOMEM; |
| 49 | |||
| 50 | envp[i] = NULL; | ||
| 51 | |||
| 52 | return 0; | 36 | return 0; |
| 53 | } | 37 | } |
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index bd433ef6bfc6..f0eba534f805 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -694,66 +694,6 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, | |||
| 694 | if ((slot == NULL) || (info == NULL)) | 694 | if ((slot == NULL) || (info == NULL)) |
| 695 | return -ENODEV; | 695 | return -ENODEV; |
| 696 | 696 | ||
| 697 | /* | ||
| 698 | * check all fields in the info structure, and update timestamps | ||
| 699 | * for the files referring to the fields that have now changed. | ||
| 700 | */ | ||
| 701 | if ((has_power_file(slot) == 0) && | ||
| 702 | (slot->info->power_status != info->power_status)) { | ||
| 703 | retval = sysfs_update_file(&slot->kobj, | ||
| 704 | &hotplug_slot_attr_power.attr); | ||
| 705 | if (retval) | ||
| 706 | return retval; | ||
| 707 | } | ||
| 708 | |||
| 709 | if ((has_attention_file(slot) == 0) && | ||
| 710 | (slot->info->attention_status != info->attention_status)) { | ||
| 711 | retval = sysfs_update_file(&slot->kobj, | ||
| 712 | &hotplug_slot_attr_attention.attr); | ||
| 713 | if (retval) | ||
| 714 | return retval; | ||
| 715 | } | ||
| 716 | |||
| 717 | if ((has_latch_file(slot) == 0) && | ||
| 718 | (slot->info->latch_status != info->latch_status)) { | ||
| 719 | retval = sysfs_update_file(&slot->kobj, | ||
| 720 | &hotplug_slot_attr_latch.attr); | ||
| 721 | if (retval) | ||
| 722 | return retval; | ||
| 723 | } | ||
| 724 | |||
| 725 | if ((has_adapter_file(slot) == 0) && | ||
| 726 | (slot->info->adapter_status != info->adapter_status)) { | ||
| 727 | retval = sysfs_update_file(&slot->kobj, | ||
| 728 | &hotplug_slot_attr_presence.attr); | ||
| 729 | if (retval) | ||
| 730 | return retval; | ||
| 731 | } | ||
| 732 | |||
| 733 | if ((has_address_file(slot) == 0) && | ||
| 734 | (slot->info->address != info->address)) { | ||
| 735 | retval = sysfs_update_file(&slot->kobj, | ||
| 736 | &hotplug_slot_attr_address.attr); | ||
| 737 | if (retval) | ||
| 738 | return retval; | ||
| 739 | } | ||
| 740 | |||
| 741 | if ((has_max_bus_speed_file(slot) == 0) && | ||
| 742 | (slot->info->max_bus_speed != info->max_bus_speed)) { | ||
| 743 | retval = sysfs_update_file(&slot->kobj, | ||
| 744 | &hotplug_slot_attr_max_bus_speed.attr); | ||
| 745 | if (retval) | ||
| 746 | return retval; | ||
| 747 | } | ||
| 748 | |||
| 749 | if ((has_cur_bus_speed_file(slot) == 0) && | ||
| 750 | (slot->info->cur_bus_speed != info->cur_bus_speed)) { | ||
| 751 | retval = sysfs_update_file(&slot->kobj, | ||
| 752 | &hotplug_slot_attr_cur_bus_speed.attr); | ||
| 753 | if (retval) | ||
| 754 | return retval; | ||
| 755 | } | ||
| 756 | |||
| 757 | memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); | 697 | memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); |
| 758 | 698 | ||
| 759 | return 0; | 699 | return 0; |
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index df076064a3e0..a080fedf0332 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c | |||
| @@ -129,17 +129,17 @@ struct kobj_type ktype_dlpar_io = { | |||
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | struct kset dlpar_io_kset = { | 131 | struct kset dlpar_io_kset = { |
| 132 | .kobj = {.name = DLPAR_KOBJ_NAME, | 132 | .kobj = {.ktype = &ktype_dlpar_io, |
| 133 | .ktype = &ktype_dlpar_io, | ||
| 134 | .parent = &pci_hotplug_slots_subsys.kobj}, | 133 | .parent = &pci_hotplug_slots_subsys.kobj}, |
| 135 | .ktype = &ktype_dlpar_io, | 134 | .ktype = &ktype_dlpar_io, |
| 136 | }; | 135 | }; |
| 137 | 136 | ||
| 138 | int dlpar_sysfs_init(void) | 137 | int dlpar_sysfs_init(void) |
| 139 | { | 138 | { |
| 139 | kobject_set_name(&dlpar_io_kset.kobj, DLPAR_KOBJ_NAME); | ||
| 140 | if (kset_register(&dlpar_io_kset)) { | 140 | if (kset_register(&dlpar_io_kset)) { |
| 141 | printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n", | 141 | printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n", |
| 142 | dlpar_io_kset.kobj.name); | 142 | kobject_name(&dlpar_io_kset.kobj)); |
| 143 | return -EINVAL; | 143 | return -EINVAL; |
| 144 | } | 144 | } |
| 145 | 145 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index c43ecedce673..6e2760b6c20a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -531,8 +531,7 @@ void pci_dev_put(struct pci_dev *dev) | |||
| 531 | } | 531 | } |
| 532 | 532 | ||
| 533 | #ifndef CONFIG_HOTPLUG | 533 | #ifndef CONFIG_HOTPLUG |
| 534 | int pci_uevent(struct device *dev, char **envp, int num_envp, | 534 | int pci_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 535 | char *buffer, int buffer_size) | ||
| 536 | { | 535 | { |
| 537 | return -ENODEV; | 536 | return -ENODEV; |
| 538 | } | 537 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5360d73d4941..6fda33de84e8 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | /* Functions internal to the PCI core code */ | 1 | /* Functions internal to the PCI core code */ |
| 2 | 2 | ||
| 3 | extern int pci_uevent(struct device *dev, char **envp, int num_envp, | 3 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); |
| 4 | char *buffer, int buffer_size); | ||
| 5 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 4 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
| 6 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); | 5 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); |
| 7 | extern void pci_cleanup_rom(struct pci_dev *dev); | 6 | extern void pci_cleanup_rom(struct pci_dev *dev); |
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c index 568f1877315c..05ca2ed9eb51 100644 --- a/drivers/pci/setup-irq.c +++ b/drivers/pci/setup-irq.c | |||
| @@ -48,7 +48,7 @@ pdev_fixup_irq(struct pci_dev *dev, | |||
| 48 | dev->irq = irq; | 48 | dev->irq = irq; |
| 49 | 49 | ||
| 50 | pr_debug("PCI: fixup irq: (%s) got %d\n", | 50 | pr_debug("PCI: fixup irq: (%s) got %d\n", |
| 51 | dev->dev.kobj.name, dev->irq); | 51 | kobject_name(&dev->dev.kobj), dev->irq); |
| 52 | 52 | ||
| 53 | /* Always tell the device, so the driver knows what is | 53 | /* Always tell the device, so the driver knows what is |
| 54 | the real IRQ to use; the device does not use it. */ | 54 | the real IRQ to use; the device does not use it. */ |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f8b13f0270d7..a0aca46ce877 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
| @@ -907,18 +907,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) | |||
| 907 | EXPORT_SYMBOL(pcmcia_insert_card); | 907 | EXPORT_SYMBOL(pcmcia_insert_card); |
| 908 | 908 | ||
| 909 | 909 | ||
| 910 | static int pcmcia_socket_uevent(struct device *dev, char **envp, | 910 | static int pcmcia_socket_uevent(struct device *dev, |
| 911 | int num_envp, char *buffer, int buffer_size) | 911 | struct kobj_uevent_env *env) |
| 912 | { | 912 | { |
| 913 | struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); | 913 | struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); |
| 914 | int i = 0, length = 0; | ||
| 915 | 914 | ||
| 916 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 915 | if (add_uevent_var(env, "SOCKET_NO=%u", s->sock)) |
| 917 | &length, "SOCKET_NO=%u", s->sock)) | ||
| 918 | return -ENOMEM; | 916 | return -ENOMEM; |
| 919 | 917 | ||
| 920 | envp[i] = NULL; | ||
| 921 | |||
| 922 | return 0; | 918 | return 0; |
| 923 | } | 919 | } |
| 924 | 920 | ||
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a99607142fc8..55baa1f0fcbb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -1064,11 +1064,10 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { | |||
| 1064 | 1064 | ||
| 1065 | #ifdef CONFIG_HOTPLUG | 1065 | #ifdef CONFIG_HOTPLUG |
| 1066 | 1066 | ||
| 1067 | static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, | 1067 | static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1068 | char *buffer, int buffer_size) | ||
| 1069 | { | 1068 | { |
| 1070 | struct pcmcia_device *p_dev; | 1069 | struct pcmcia_device *p_dev; |
| 1071 | int i, length = 0; | 1070 | int i; |
| 1072 | u32 hash[4] = { 0, 0, 0, 0}; | 1071 | u32 hash[4] = { 0, 0, 0, 0}; |
| 1073 | 1072 | ||
| 1074 | if (!dev) | 1073 | if (!dev) |
| @@ -1083,23 +1082,13 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1083 | hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); | 1082 | hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); |
| 1084 | } | 1083 | } |
| 1085 | 1084 | ||
| 1086 | i = 0; | 1085 | if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock)) |
| 1087 | |||
| 1088 | if (add_uevent_var(envp, num_envp, &i, | ||
| 1089 | buffer, buffer_size, &length, | ||
| 1090 | "SOCKET_NO=%u", | ||
| 1091 | p_dev->socket->sock)) | ||
| 1092 | return -ENOMEM; | 1086 | return -ENOMEM; |
| 1093 | 1087 | ||
| 1094 | if (add_uevent_var(envp, num_envp, &i, | 1088 | if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no)) |
| 1095 | buffer, buffer_size, &length, | ||
| 1096 | "DEVICE_NO=%02X", | ||
| 1097 | p_dev->device_no)) | ||
| 1098 | return -ENOMEM; | 1089 | return -ENOMEM; |
| 1099 | 1090 | ||
| 1100 | if (add_uevent_var(envp, num_envp, &i, | 1091 | if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" |
| 1101 | buffer, buffer_size, &length, | ||
| 1102 | "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" | ||
| 1103 | "pa%08Xpb%08Xpc%08Xpd%08X", | 1092 | "pa%08Xpb%08Xpc%08Xpd%08X", |
| 1104 | p_dev->has_manf_id ? p_dev->manf_id : 0, | 1093 | p_dev->has_manf_id ? p_dev->manf_id : 0, |
| 1105 | p_dev->has_card_id ? p_dev->card_id : 0, | 1094 | p_dev->has_card_id ? p_dev->card_id : 0, |
| @@ -1112,15 +1101,12 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1112 | hash[3])) | 1101 | hash[3])) |
| 1113 | return -ENOMEM; | 1102 | return -ENOMEM; |
| 1114 | 1103 | ||
| 1115 | envp[i] = NULL; | ||
| 1116 | |||
| 1117 | return 0; | 1104 | return 0; |
| 1118 | } | 1105 | } |
| 1119 | 1106 | ||
| 1120 | #else | 1107 | #else |
| 1121 | 1108 | ||
| 1122 | static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, | 1109 | static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1123 | char *buffer, int buffer_size) | ||
| 1124 | { | 1110 | { |
| 1125 | return -ENODEV; | 1111 | return -ENODEV; |
| 1126 | } | 1112 | } |
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 383107ba4bd3..f6722ba0dd1e 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c | |||
| @@ -175,7 +175,6 @@ static int __init mst_pcmcia_init(void) | |||
| 175 | if (!mst_pcmcia_device) | 175 | if (!mst_pcmcia_device) |
| 176 | return -ENOMEM; | 176 | return -ENOMEM; |
| 177 | 177 | ||
| 178 | mst_pcmcia_device->dev.uevent_suppress = 0; | ||
| 179 | mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; | 178 | mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; |
| 180 | 179 | ||
| 181 | ret = platform_device_add(mst_pcmcia_device); | 180 | ret = platform_device_add(mst_pcmcia_device); |
| @@ -195,3 +194,4 @@ fs_initcall(mst_pcmcia_init); | |||
| 195 | module_exit(mst_pcmcia_exit); | 194 | module_exit(mst_pcmcia_exit); |
| 196 | 195 | ||
| 197 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
| 197 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index a2daa3f531b2..d5c33bd78d68 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c | |||
| @@ -261,7 +261,6 @@ static int __init sharpsl_pcmcia_init(void) | |||
| 261 | if (!sharpsl_pcmcia_device) | 261 | if (!sharpsl_pcmcia_device) |
| 262 | return -ENOMEM; | 262 | return -ENOMEM; |
| 263 | 263 | ||
| 264 | sharpsl_pcmcia_device->dev.uevent_suppress = 0; | ||
| 265 | sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; | 264 | sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; |
| 266 | sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; | 265 | sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; |
| 267 | 266 | ||
| @@ -284,3 +283,4 @@ module_exit(sharpsl_pcmcia_exit); | |||
| 284 | 283 | ||
| 285 | MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); | 284 | MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); |
| 286 | MODULE_LICENSE("GPL"); | 285 | MODULE_LICENSE("GPL"); |
| 286 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h index a9880d468ee4..f38ba482be75 100644 --- a/drivers/power/power_supply.h +++ b/drivers/power/power_supply.h | |||
| @@ -14,8 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | extern int power_supply_create_attrs(struct power_supply *psy); | 15 | extern int power_supply_create_attrs(struct power_supply *psy); |
| 16 | extern void power_supply_remove_attrs(struct power_supply *psy); | 16 | extern void power_supply_remove_attrs(struct power_supply *psy); |
| 17 | extern int power_supply_uevent(struct device *dev, char **envp, int num_envp, | 17 | extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env); |
| 18 | char *buffer, int buffer_size); | ||
| 19 | 18 | ||
| 20 | #else | 19 | #else |
| 21 | 20 | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index de3155b21285..249f61bae639 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
| @@ -195,11 +195,10 @@ static char *kstruprdup(const char *str, gfp_t gfp) | |||
| 195 | return ret; | 195 | return ret; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | int power_supply_uevent(struct device *dev, char **envp, int num_envp, | 198 | int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 199 | char *buffer, int buffer_size) | ||
| 200 | { | 199 | { |
| 201 | struct power_supply *psy = dev_get_drvdata(dev); | 200 | struct power_supply *psy = dev_get_drvdata(dev); |
| 202 | int i = 0, length = 0, ret = 0, j; | 201 | int ret = 0, j; |
| 203 | char *prop_buf; | 202 | char *prop_buf; |
| 204 | char *attrname; | 203 | char *attrname; |
| 205 | 204 | ||
| @@ -212,8 +211,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, | |||
| 212 | 211 | ||
| 213 | dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name); | 212 | dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name); |
| 214 | 213 | ||
| 215 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 214 | ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name); |
| 216 | &length, "POWER_SUPPLY_NAME=%s", psy->name); | ||
| 217 | if (ret) | 215 | if (ret) |
| 218 | return ret; | 216 | return ret; |
| 219 | 217 | ||
| @@ -243,9 +241,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, | |||
| 243 | 241 | ||
| 244 | dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf); | 242 | dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf); |
| 245 | 243 | ||
| 246 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 244 | ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); |
| 247 | &length, "POWER_SUPPLY_%s=%s", | ||
| 248 | attrname, prop_buf); | ||
| 249 | kfree(attrname); | 245 | kfree(attrname); |
| 250 | if (ret) | 246 | if (ret) |
| 251 | goto out; | 247 | goto out; |
| @@ -282,14 +278,11 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, | |||
| 282 | 278 | ||
| 283 | dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); | 279 | dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); |
| 284 | 280 | ||
| 285 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 281 | ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); |
| 286 | &length, "POWER_SUPPLY_%s=%s", | ||
| 287 | attrname, prop_buf); | ||
| 288 | kfree(attrname); | 282 | kfree(attrname); |
| 289 | if (ret) | 283 | if (ret) |
| 290 | goto out; | 284 | goto out; |
| 291 | } | 285 | } |
| 292 | envp[i] = NULL; | ||
| 293 | 286 | ||
| 294 | out: | 287 | out: |
| 295 | free_page((unsigned long)prop_buf); | 288 | free_page((unsigned long)prop_buf); |
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 b0a18f5176aa..5baa517c3b66 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
| @@ -44,8 +44,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv) | |||
| 44 | return 0; | 44 | return 0; |
| 45 | } | 45 | } |
| 46 | static int | 46 | static int |
| 47 | ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, | 47 | ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env) |
| 48 | int buffer_size) | ||
| 49 | { | 48 | { |
| 50 | /* TODO */ | 49 | /* TODO */ |
| 51 | return 0; | 50 | return 0; |
| @@ -152,16 +151,24 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | |||
| 152 | return 0; | 151 | return 0; |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | /* | 154 | /** |
| 156 | * try to add a new ccwgroup device for one driver | 155 | * ccwgroup_create() - create and register a ccw group device |
| 157 | * argc and argv[] are a list of bus_id's of devices | 156 | * @root: parent device for the new device |
| 158 | * 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 | ||
| 159 | */ | 169 | */ |
| 160 | int | 170 | int ccwgroup_create(struct device *root, unsigned int creator_id, |
| 161 | ccwgroup_create(struct device *root, | 171 | struct ccw_driver *cdrv, int argc, char *argv[]) |
| 162 | unsigned int creator_id, | ||
| 163 | struct ccw_driver *cdrv, | ||
| 164 | int argc, char *argv[]) | ||
| 165 | { | 172 | { |
| 166 | struct ccwgroup_device *gdev; | 173 | struct ccwgroup_device *gdev; |
| 167 | int i; | 174 | int i; |
| @@ -390,8 +397,13 @@ static struct bus_type ccwgroup_bus_type = { | |||
| 390 | .remove = ccwgroup_remove, | 397 | .remove = ccwgroup_remove, |
| 391 | }; | 398 | }; |
| 392 | 399 | ||
| 393 | int | 400 | /** |
| 394 | 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) | ||
| 395 | { | 407 | { |
| 396 | /* register our new driver with the core */ | 408 | /* register our new driver with the core */ |
| 397 | cdriver->driver.bus = &ccwgroup_bus_type; | 409 | cdriver->driver.bus = &ccwgroup_bus_type; |
| @@ -406,8 +418,13 @@ __ccwgroup_match_all(struct device *dev, void *data) | |||
| 406 | return 1; | 418 | return 1; |
| 407 | } | 419 | } |
| 408 | 420 | ||
| 409 | void | 421 | /** |
| 410 | 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) | ||
| 411 | { | 428 | { |
| 412 | struct device *dev; | 429 | struct device *dev; |
| 413 | 430 | ||
| @@ -427,8 +444,16 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | |||
| 427 | driver_unregister(&cdriver->driver); | 444 | driver_unregister(&cdriver->driver); |
| 428 | } | 445 | } |
| 429 | 446 | ||
| 430 | int | 447 | /** |
| 431 | 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) | ||
| 432 | { | 457 | { |
| 433 | return 0; | 458 | return 0; |
| 434 | } | 459 | } |
| @@ -452,8 +477,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) | |||
| 452 | return NULL; | 477 | return NULL; |
| 453 | } | 478 | } |
| 454 | 479 | ||
| 455 | void | 480 | /** |
| 456 | 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) | ||
| 457 | { | 489 | { |
| 458 | struct ccwgroup_device *gdev; | 490 | struct ccwgroup_device *gdev; |
| 459 | 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 e44d92eac8e9..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" |
| @@ -78,49 +79,38 @@ static int snprint_alias(char *buf, size_t size, | |||
| 78 | 79 | ||
| 79 | /* Set up environment variables for ccw device uevent. Return 0 on success, | 80 | /* Set up environment variables for ccw device uevent. Return 0 on success, |
| 80 | * non-zero otherwise. */ | 81 | * non-zero otherwise. */ |
| 81 | static int ccw_uevent(struct device *dev, char **envp, int num_envp, | 82 | static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 82 | char *buffer, int buffer_size) | ||
| 83 | { | 83 | { |
| 84 | struct ccw_device *cdev = to_ccwdev(dev); | 84 | struct ccw_device *cdev = to_ccwdev(dev); |
| 85 | struct ccw_device_id *id = &(cdev->id); | 85 | struct ccw_device_id *id = &(cdev->id); |
| 86 | int i = 0; | ||
| 87 | int len = 0; | ||
| 88 | int ret; | 86 | int ret; |
| 89 | char modalias_buf[30]; | 87 | char modalias_buf[30]; |
| 90 | 88 | ||
| 91 | /* CU_TYPE= */ | 89 | /* CU_TYPE= */ |
| 92 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 90 | ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type); |
| 93 | "CU_TYPE=%04X", id->cu_type); | ||
| 94 | if (ret) | 91 | if (ret) |
| 95 | return ret; | 92 | return ret; |
| 96 | 93 | ||
| 97 | /* CU_MODEL= */ | 94 | /* CU_MODEL= */ |
| 98 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 95 | ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model); |
| 99 | "CU_MODEL=%02X", id->cu_model); | ||
| 100 | if (ret) | 96 | if (ret) |
| 101 | return ret; | 97 | return ret; |
| 102 | 98 | ||
| 103 | /* The next two can be zero, that's ok for us */ | 99 | /* The next two can be zero, that's ok for us */ |
| 104 | /* DEV_TYPE= */ | 100 | /* DEV_TYPE= */ |
| 105 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 101 | ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type); |
| 106 | "DEV_TYPE=%04X", id->dev_type); | ||
| 107 | if (ret) | 102 | if (ret) |
| 108 | return ret; | 103 | return ret; |
| 109 | 104 | ||
| 110 | /* DEV_MODEL= */ | 105 | /* DEV_MODEL= */ |
| 111 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 106 | ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model); |
| 112 | "DEV_MODEL=%02X", id->dev_model); | ||
| 113 | if (ret) | 107 | if (ret) |
| 114 | return ret; | 108 | return ret; |
| 115 | 109 | ||
| 116 | /* MODALIAS= */ | 110 | /* MODALIAS= */ |
| 117 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); | 111 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); |
| 118 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 112 | ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf); |
| 119 | "MODALIAS=%s", modalias_buf); | 113 | return ret; |
| 120 | if (ret) | ||
| 121 | return ret; | ||
| 122 | envp[i] = NULL; | ||
| 123 | return 0; | ||
| 124 | } | 114 | } |
| 125 | 115 | ||
| 126 | struct bus_type ccw_bus_type; | 116 | struct bus_type ccw_bus_type; |
| @@ -357,8 +347,18 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
| 357 | cdev->private->dev_id.devno); | 347 | cdev->private->dev_id.devno); |
| 358 | } | 348 | } |
| 359 | 349 | ||
| 360 | int | 350 | /** |
| 361 | 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) | ||
| 362 | { | 362 | { |
| 363 | int ret; | 363 | int ret; |
| 364 | 364 | ||
| @@ -396,8 +396,19 @@ ccw_device_set_offline(struct ccw_device *cdev) | |||
| 396 | return ret; | 396 | return ret; |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | int | 399 | /** |
| 400 | 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) | ||
| 401 | { | 412 | { |
| 402 | int ret; | 413 | int ret; |
| 403 | 414 | ||
| @@ -947,8 +958,7 @@ out: | |||
| 947 | wake_up(&ccw_device_init_wq); | 958 | wake_up(&ccw_device_init_wq); |
| 948 | } | 959 | } |
| 949 | 960 | ||
| 950 | void | 961 | static void ccw_device_call_sch_unregister(struct work_struct *work) |
| 951 | ccw_device_call_sch_unregister(struct work_struct *work) | ||
| 952 | { | 962 | { |
| 953 | struct ccw_device_private *priv; | 963 | struct ccw_device_private *priv; |
| 954 | struct ccw_device *cdev; | 964 | struct ccw_device *cdev; |
| @@ -1101,6 +1111,7 @@ io_subchannel_probe (struct subchannel *sch) | |||
| 1101 | * device, e.g. the console. | 1111 | * device, e.g. the console. |
| 1102 | */ | 1112 | */ |
| 1103 | cdev = sch->dev.driver_data; | 1113 | cdev = sch->dev.driver_data; |
| 1114 | cdev->dev.groups = ccwdev_attr_groups; | ||
| 1104 | device_initialize(&cdev->dev); | 1115 | device_initialize(&cdev->dev); |
| 1105 | ccw_device_register(cdev); | 1116 | ccw_device_register(cdev); |
| 1106 | /* | 1117 | /* |
| @@ -1326,8 +1337,19 @@ __ccwdev_check_busid(struct device *dev, void *id) | |||
| 1326 | } | 1337 | } |
| 1327 | 1338 | ||
| 1328 | 1339 | ||
| 1329 | struct ccw_device * | 1340 | /** |
| 1330 | 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) | ||
| 1331 | { | 1353 | { |
| 1332 | struct device *dev; | 1354 | struct device *dev; |
| 1333 | struct device_driver *drv; | 1355 | struct device_driver *drv; |
| @@ -1401,16 +1423,34 @@ ccw_device_remove (struct device *dev) | |||
| 1401 | return 0; | 1423 | return 0; |
| 1402 | } | 1424 | } |
| 1403 | 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 | |||
| 1404 | struct bus_type ccw_bus_type = { | 1436 | struct bus_type ccw_bus_type = { |
| 1405 | .name = "ccw", | 1437 | .name = "ccw", |
| 1406 | .match = ccw_bus_match, | 1438 | .match = ccw_bus_match, |
| 1407 | .uevent = ccw_uevent, | 1439 | .uevent = ccw_uevent, |
| 1408 | .probe = ccw_device_probe, | 1440 | .probe = ccw_device_probe, |
| 1409 | .remove = ccw_device_remove, | 1441 | .remove = ccw_device_remove, |
| 1442 | .shutdown = ccw_device_shutdown, | ||
| 1410 | }; | 1443 | }; |
| 1411 | 1444 | ||
| 1412 | int | 1445 | /** |
| 1413 | 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) | ||
| 1414 | { | 1454 | { |
| 1415 | struct device_driver *drv = &cdriver->driver; | 1455 | struct device_driver *drv = &cdriver->driver; |
| 1416 | 1456 | ||
| @@ -1420,8 +1460,13 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
| 1420 | return driver_register(drv); | 1460 | return driver_register(drv); |
| 1421 | } | 1461 | } |
| 1422 | 1462 | ||
| 1423 | void | 1463 | /** |
| 1424 | 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) | ||
| 1425 | { | 1470 | { |
| 1426 | driver_unregister(&cdriver->driver); | 1471 | driver_unregister(&cdriver->driver); |
| 1427 | } | 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 90bd22014513..67aaff3e668d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -458,28 +458,22 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) | |||
| 458 | * uevent function for AP devices. It sets up a single environment | 458 | * uevent function for AP devices. It sets up a single environment |
| 459 | * variable DEV_TYPE which contains the hardware device type. | 459 | * variable DEV_TYPE which contains the hardware device type. |
| 460 | */ | 460 | */ |
| 461 | static int ap_uevent (struct device *dev, char **envp, int num_envp, | 461 | static int ap_uevent (struct device *dev, struct kobj_uevent_env *env) |
| 462 | char *buffer, int buffer_size) | ||
| 463 | { | 462 | { |
| 464 | struct ap_device *ap_dev = to_ap_dev(dev); | 463 | struct ap_device *ap_dev = to_ap_dev(dev); |
| 465 | int retval = 0, length = 0, i = 0; | 464 | int retval = 0; |
| 466 | 465 | ||
| 467 | if (!ap_dev) | 466 | if (!ap_dev) |
| 468 | return -ENODEV; | 467 | return -ENODEV; |
| 469 | 468 | ||
| 470 | /* Set up DEV_TYPE environment variable. */ | 469 | /* Set up DEV_TYPE environment variable. */ |
| 471 | retval = add_uevent_var(envp, num_envp, &i, | 470 | retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); |
| 472 | buffer, buffer_size, &length, | ||
| 473 | "DEV_TYPE=%04X", ap_dev->device_type); | ||
| 474 | if (retval) | 471 | if (retval) |
| 475 | return retval; | 472 | return retval; |
| 476 | 473 | ||
| 477 | /* Add MODALIAS= */ | 474 | /* Add MODALIAS= */ |
| 478 | retval = add_uevent_var(envp, num_envp, &i, | 475 | retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); |
| 479 | buffer, buffer_size, &length, | ||
| 480 | "MODALIAS=ap:t%02X", ap_dev->device_type); | ||
| 481 | 476 | ||
| 482 | envp[i] = NULL; | ||
| 483 | return retval; | 477 | return retval; |
| 484 | } | 478 | } |
| 485 | 479 | ||
| @@ -1231,8 +1225,9 @@ static void ap_reset_domain(void) | |||
| 1231 | { | 1225 | { |
| 1232 | int i; | 1226 | int i; |
| 1233 | 1227 | ||
| 1234 | for (i = 0; i < AP_DEVICES; i++) | 1228 | if (ap_domain_index != -1) |
| 1235 | 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)); | ||
| 1236 | } | 1231 | } |
| 1237 | 1232 | ||
| 1238 | 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/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 34cdce6738a6..ede9986d349a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -277,16 +277,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) | |||
| 277 | return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; | 277 | return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, | 280 | static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 281 | char *buffer, int buffer_size) | ||
| 282 | { | 281 | { |
| 283 | struct scsi_device *sdev = to_scsi_device(dev); | 282 | struct scsi_device *sdev = to_scsi_device(dev); |
| 284 | int i = 0; | ||
| 285 | int length = 0; | ||
| 286 | 283 | ||
| 287 | add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | 284 | add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); |
| 288 | "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); | ||
| 289 | envp[i] = NULL; | ||
| 290 | return 0; | 285 | return 0; |
| 291 | } | 286 | } |
| 292 | 287 | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e84d21597943..bcb8dd5fb0b4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) | |||
| 67 | return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; | 67 | return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static int spi_uevent(struct device *dev, char **envp, int num_envp, | 70 | static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 71 | char *buffer, int buffer_size) | ||
| 72 | { | 71 | { |
| 73 | const struct spi_device *spi = to_spi_device(dev); | 72 | const struct spi_device *spi = to_spi_device(dev); |
| 74 | 73 | ||
| 75 | envp[0] = buffer; | 74 | add_uevent_var(env, "MODALIAS=%s", spi->modalias); |
| 76 | snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); | ||
| 77 | envp[1] = NULL; | ||
| 78 | return 0; | 75 | return 0; |
| 79 | } | 76 | } |
| 80 | 77 | ||
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 927a181120a9..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)) |
| @@ -1576,6 +1591,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai | |||
| 1576 | } | 1591 | } |
| 1577 | 1592 | ||
| 1578 | const struct file_operations usbdev_file_operations = { | 1593 | const struct file_operations usbdev_file_operations = { |
| 1594 | .owner = THIS_MODULE, | ||
| 1579 | .llseek = usbdev_lseek, | 1595 | .llseek = usbdev_lseek, |
| 1580 | .read = usbdev_read, | 1596 | .read = usbdev_read, |
| 1581 | .poll = usbdev_poll, | 1597 | .poll = usbdev_poll, |
| @@ -1625,10 +1641,7 @@ static struct notifier_block usbdev_nb = { | |||
| 1625 | }; | 1641 | }; |
| 1626 | #endif | 1642 | #endif |
| 1627 | 1643 | ||
| 1628 | static struct cdev usb_device_cdev = { | 1644 | static struct cdev usb_device_cdev; |
| 1629 | .kobj = {.name = "usb_device", }, | ||
| 1630 | .owner = THIS_MODULE, | ||
| 1631 | }; | ||
| 1632 | 1645 | ||
| 1633 | int __init usb_devio_init(void) | 1646 | int __init usb_devio_init(void) |
| 1634 | { | 1647 | { |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 63b1243a9139..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); |
| @@ -576,12 +581,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) | |||
| 576 | } | 581 | } |
| 577 | 582 | ||
| 578 | #ifdef CONFIG_HOTPLUG | 583 | #ifdef CONFIG_HOTPLUG |
| 579 | static int usb_uevent(struct device *dev, char **envp, int num_envp, | 584 | static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 580 | char *buffer, int buffer_size) | ||
| 581 | { | 585 | { |
| 582 | struct usb_device *usb_dev; | 586 | struct usb_device *usb_dev; |
| 583 | int i = 0; | ||
| 584 | int length = 0; | ||
| 585 | 587 | ||
| 586 | if (!dev) | 588 | if (!dev) |
| 587 | return -ENODEV; | 589 | return -ENODEV; |
| @@ -610,51 +612,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
| 610 | * all the device descriptors we don't tell them about. Or | 612 | * all the device descriptors we don't tell them about. Or |
| 611 | * act as usermode drivers. | 613 | * act as usermode drivers. |
| 612 | */ | 614 | */ |
| 613 | if (add_uevent_var(envp, num_envp, &i, | 615 | if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", |
| 614 | buffer, buffer_size, &length, | ||
| 615 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
| 616 | usb_dev->bus->busnum, usb_dev->devnum)) | 616 | usb_dev->bus->busnum, usb_dev->devnum)) |
| 617 | return -ENOMEM; | 617 | return -ENOMEM; |
| 618 | #endif | 618 | #endif |
| 619 | 619 | ||
| 620 | /* per-device configurations are common */ | 620 | /* per-device configurations are common */ |
| 621 | if (add_uevent_var(envp, num_envp, &i, | 621 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", |
| 622 | buffer, buffer_size, &length, | ||
| 623 | "PRODUCT=%x/%x/%x", | ||
| 624 | le16_to_cpu(usb_dev->descriptor.idVendor), | 622 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 625 | le16_to_cpu(usb_dev->descriptor.idProduct), | 623 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| 626 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | 624 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) |
| 627 | return -ENOMEM; | 625 | return -ENOMEM; |
| 628 | 626 | ||
| 629 | /* class-based driver binding models */ | 627 | /* class-based driver binding models */ |
| 630 | if (add_uevent_var(envp, num_envp, &i, | 628 | if (add_uevent_var(env, "TYPE=%d/%d/%d", |
| 631 | buffer, buffer_size, &length, | ||
| 632 | "TYPE=%d/%d/%d", | ||
| 633 | usb_dev->descriptor.bDeviceClass, | 629 | usb_dev->descriptor.bDeviceClass, |
| 634 | usb_dev->descriptor.bDeviceSubClass, | 630 | usb_dev->descriptor.bDeviceSubClass, |
| 635 | usb_dev->descriptor.bDeviceProtocol)) | 631 | usb_dev->descriptor.bDeviceProtocol)) |
| 636 | return -ENOMEM; | 632 | return -ENOMEM; |
| 637 | 633 | ||
| 638 | if (add_uevent_var(envp, num_envp, &i, | 634 | if (add_uevent_var(env, "BUSNUM=%03d", |
| 639 | buffer, buffer_size, &length, | ||
| 640 | "BUSNUM=%03d", | ||
| 641 | usb_dev->bus->busnum)) | 635 | usb_dev->bus->busnum)) |
| 642 | return -ENOMEM; | 636 | return -ENOMEM; |
| 643 | 637 | ||
| 644 | if (add_uevent_var(envp, num_envp, &i, | 638 | if (add_uevent_var(env, "DEVNUM=%03d", |
| 645 | buffer, buffer_size, &length, | ||
| 646 | "DEVNUM=%03d", | ||
| 647 | usb_dev->devnum)) | 639 | usb_dev->devnum)) |
| 648 | return -ENOMEM; | 640 | return -ENOMEM; |
| 649 | 641 | ||
| 650 | envp[i] = NULL; | ||
| 651 | return 0; | 642 | return 0; |
| 652 | } | 643 | } |
| 653 | 644 | ||
| 654 | #else | 645 | #else |
| 655 | 646 | ||
| 656 | static int usb_uevent(struct device *dev, char **envp, | 647 | static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 657 | int num_envp, char *buffer, int buffer_size) | ||
| 658 | { | 648 | { |
| 659 | return -ENODEV; | 649 | return -ENODEV; |
| 660 | } | 650 | } |
| @@ -945,11 +935,11 @@ done: | |||
| 945 | #ifdef CONFIG_USB_SUSPEND | 935 | #ifdef CONFIG_USB_SUSPEND |
| 946 | 936 | ||
| 947 | /* Internal routine to check whether we may autosuspend a device. */ | 937 | /* Internal routine to check whether we may autosuspend a device. */ |
| 948 | static int autosuspend_check(struct usb_device *udev) | 938 | static int autosuspend_check(struct usb_device *udev, int reschedule) |
| 949 | { | 939 | { |
| 950 | int i; | 940 | int i; |
| 951 | struct usb_interface *intf; | 941 | struct usb_interface *intf; |
| 952 | unsigned long suspend_time; | 942 | unsigned long suspend_time, j; |
| 953 | 943 | ||
| 954 | /* For autosuspend, fail fast if anything is in use or autosuspend | 944 | /* For autosuspend, fail fast if anything is in use or autosuspend |
| 955 | * is disabled. Also fail if any interfaces require remote wakeup | 945 | * is disabled. Also fail if any interfaces require remote wakeup |
| @@ -991,20 +981,20 @@ static int autosuspend_check(struct usb_device *udev) | |||
| 991 | } | 981 | } |
| 992 | 982 | ||
| 993 | /* 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 |
| 994 | * 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. | ||
| 995 | */ | 987 | */ |
| 996 | 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) { | ||
| 997 | if (!timer_pending(&udev->autosuspend.timer)) { | 994 | if (!timer_pending(&udev->autosuspend.timer)) { |
| 998 | |||
| 999 | /* The value of jiffies may change between the | ||
| 1000 | * time_after() comparison above and the subtraction | ||
| 1001 | * below. That's okay; the system behaves sanely | ||
| 1002 | * when a timer is registered for the present moment | ||
| 1003 | * or for the past. | ||
| 1004 | */ | ||
| 1005 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 995 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
| 1006 | round_jiffies_relative(suspend_time - jiffies)); | 996 | round_jiffies_relative(suspend_time - j)); |
| 1007 | } | 997 | } |
| 1008 | return -EAGAIN; | 998 | return -EAGAIN; |
| 1009 | } | 999 | } |
| 1010 | return 0; | 1000 | return 0; |
| @@ -1012,7 +1002,7 @@ static int autosuspend_check(struct usb_device *udev) | |||
| 1012 | 1002 | ||
| 1013 | #else | 1003 | #else |
| 1014 | 1004 | ||
| 1015 | static inline int autosuspend_check(struct usb_device *udev) | 1005 | static inline int autosuspend_check(struct usb_device *udev, int reschedule) |
| 1016 | { | 1006 | { |
| 1017 | return 0; | 1007 | return 0; |
| 1018 | } | 1008 | } |
| @@ -1069,7 +1059,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
| 1069 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 1059 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); |
| 1070 | 1060 | ||
| 1071 | if (udev->auto_pm) { | 1061 | if (udev->auto_pm) { |
| 1072 | status = autosuspend_check(udev); | 1062 | status = autosuspend_check(udev, 0); |
| 1073 | if (status < 0) | 1063 | if (status < 0) |
| 1074 | goto done; | 1064 | goto done; |
| 1075 | } | 1065 | } |
| @@ -1083,15 +1073,8 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
| 1083 | break; | 1073 | break; |
| 1084 | } | 1074 | } |
| 1085 | } | 1075 | } |
| 1086 | if (status == 0) { | 1076 | if (status == 0) |
| 1087 | |||
| 1088 | /* Non-root devices don't need to do anything for FREEZE | ||
| 1089 | * or PRETHAW. */ | ||
| 1090 | if (udev->parent && (msg.event == PM_EVENT_FREEZE || | ||
| 1091 | msg.event == PM_EVENT_PRETHAW)) | ||
| 1092 | goto done; | ||
| 1093 | status = usb_suspend_device(udev, msg); | 1077 | status = usb_suspend_device(udev, msg); |
| 1094 | } | ||
| 1095 | 1078 | ||
| 1096 | /* If the suspend failed, resume interfaces that did get suspended */ | 1079 | /* If the suspend failed, resume interfaces that did get suspended */ |
| 1097 | if (status != 0) { | 1080 | if (status != 0) { |
| @@ -1102,12 +1085,24 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
| 1102 | 1085 | ||
| 1103 | /* Try another autosuspend when the interfaces aren't busy */ | 1086 | /* Try another autosuspend when the interfaces aren't busy */ |
| 1104 | if (udev->auto_pm) | 1087 | if (udev->auto_pm) |
| 1105 | autosuspend_check(udev); | 1088 | autosuspend_check(udev, status == -EBUSY); |
| 1106 | 1089 | ||
| 1107 | /* 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 | */ | ||
| 1108 | } else { | 1093 | } else { |
| 1109 | cancel_delayed_work(&udev->autosuspend); | 1094 | cancel_delayed_work(&udev->autosuspend); |
| 1110 | 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) | ||
| 1111 | usb_autosuspend_device(parent); | 1106 | usb_autosuspend_device(parent); |
| 1112 | } | 1107 | } |
| 1113 | 1108 | ||
| @@ -1156,6 +1151,7 @@ static int usb_resume_both(struct usb_device *udev) | |||
| 1156 | status = -ENODEV; | 1151 | status = -ENODEV; |
| 1157 | goto done; | 1152 | goto done; |
| 1158 | } | 1153 | } |
| 1154 | udev->can_submit = 1; | ||
| 1159 | 1155 | ||
| 1160 | /* Propagate the resume up the tree, if necessary */ | 1156 | /* Propagate the resume up the tree, if necessary */ |
| 1161 | if (udev->state == USB_STATE_SUSPENDED) { | 1157 | if (udev->state == USB_STATE_SUSPENDED) { |
| @@ -1529,9 +1525,21 @@ int usb_external_resume_device(struct usb_device *udev) | |||
| 1529 | 1525 | ||
| 1530 | static int usb_suspend(struct device *dev, pm_message_t message) | 1526 | static int usb_suspend(struct device *dev, pm_message_t message) |
| 1531 | { | 1527 | { |
| 1528 | struct usb_device *udev; | ||
| 1529 | |||
| 1532 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ | 1530 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ |
| 1533 | return 0; | 1531 | return 0; |
| 1534 | 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); | ||
| 1535 | } | 1543 | } |
| 1536 | 1544 | ||
| 1537 | static int usb_resume(struct device *dev) | 1545 | static int usb_resume(struct device *dev) |
| @@ -1542,13 +1550,14 @@ static int usb_resume(struct device *dev) | |||
| 1542 | return 0; | 1550 | return 0; |
| 1543 | udev = to_usb_device(dev); | 1551 | udev = to_usb_device(dev); |
| 1544 | 1552 | ||
| 1545 | /* If autoresume is disabled then we also want to prevent resume | 1553 | /* If udev->skip_sys_resume is set then udev was already suspended |
| 1546 | * during system wakeup. However, a "persistent-device" reset-resume | 1554 | * when the system suspend started, so we don't want to resume |
| 1547 | * after power loss counts as a wakeup event. So allow a | 1555 | * udev during this system wakeup. However a reset-resume counts |
| 1548 | * reset-resume to occur if remote wakeup is enabled. */ | 1556 | * as a wakeup event, so allow a reset-resume to occur if remote |
| 1549 | if (udev->autoresume_disabled) { | 1557 | * wakeup is enabled. */ |
| 1558 | if (udev->skip_sys_resume) { | ||
| 1550 | if (!(udev->reset_resume && udev->do_remote_wakeup)) | 1559 | if (!(udev->reset_resume && udev->do_remote_wakeup)) |
| 1551 | return -EPERM; | 1560 | return -EHOSTUNREACH; |
| 1552 | } | 1561 | } |
| 1553 | return usb_external_resume_device(udev); | 1562 | return usb_external_resume_device(udev); |
| 1554 | } | 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 d8f7b089a8f0..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 = |
| @@ -1339,14 +1344,11 @@ void usb_release_interface(struct device *dev) | |||
| 1339 | } | 1344 | } |
| 1340 | 1345 | ||
| 1341 | #ifdef CONFIG_HOTPLUG | 1346 | #ifdef CONFIG_HOTPLUG |
| 1342 | static int usb_if_uevent(struct device *dev, char **envp, int num_envp, | 1347 | static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1343 | char *buffer, int buffer_size) | ||
| 1344 | { | 1348 | { |
| 1345 | struct usb_device *usb_dev; | 1349 | struct usb_device *usb_dev; |
| 1346 | struct usb_interface *intf; | 1350 | struct usb_interface *intf; |
| 1347 | struct usb_host_interface *alt; | 1351 | struct usb_host_interface *alt; |
| 1348 | int i = 0; | ||
| 1349 | int length = 0; | ||
| 1350 | 1352 | ||
| 1351 | if (!dev) | 1353 | if (!dev) |
| 1352 | return -ENODEV; | 1354 | return -ENODEV; |
| @@ -1359,39 +1361,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1359 | alt = intf->cur_altsetting; | 1361 | alt = intf->cur_altsetting; |
| 1360 | 1362 | ||
| 1361 | #ifdef CONFIG_USB_DEVICEFS | 1363 | #ifdef CONFIG_USB_DEVICEFS |
| 1362 | if (add_uevent_var(envp, num_envp, &i, | 1364 | if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", |
| 1363 | buffer, buffer_size, &length, | ||
| 1364 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
| 1365 | usb_dev->bus->busnum, usb_dev->devnum)) | 1365 | usb_dev->bus->busnum, usb_dev->devnum)) |
| 1366 | return -ENOMEM; | 1366 | return -ENOMEM; |
| 1367 | #endif | 1367 | #endif |
| 1368 | 1368 | ||
| 1369 | if (add_uevent_var(envp, num_envp, &i, | 1369 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", |
| 1370 | buffer, buffer_size, &length, | ||
| 1371 | "PRODUCT=%x/%x/%x", | ||
| 1372 | le16_to_cpu(usb_dev->descriptor.idVendor), | 1370 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 1373 | le16_to_cpu(usb_dev->descriptor.idProduct), | 1371 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| 1374 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | 1372 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) |
| 1375 | return -ENOMEM; | 1373 | return -ENOMEM; |
| 1376 | 1374 | ||
| 1377 | if (add_uevent_var(envp, num_envp, &i, | 1375 | if (add_uevent_var(env, "TYPE=%d/%d/%d", |
| 1378 | buffer, buffer_size, &length, | ||
| 1379 | "TYPE=%d/%d/%d", | ||
| 1380 | usb_dev->descriptor.bDeviceClass, | 1376 | usb_dev->descriptor.bDeviceClass, |
| 1381 | usb_dev->descriptor.bDeviceSubClass, | 1377 | usb_dev->descriptor.bDeviceSubClass, |
| 1382 | usb_dev->descriptor.bDeviceProtocol)) | 1378 | usb_dev->descriptor.bDeviceProtocol)) |
| 1383 | return -ENOMEM; | 1379 | return -ENOMEM; |
| 1384 | 1380 | ||
| 1385 | if (add_uevent_var(envp, num_envp, &i, | 1381 | if (add_uevent_var(env, "INTERFACE=%d/%d/%d", |
| 1386 | buffer, buffer_size, &length, | ||
| 1387 | "INTERFACE=%d/%d/%d", | ||
| 1388 | alt->desc.bInterfaceClass, | 1382 | alt->desc.bInterfaceClass, |
| 1389 | alt->desc.bInterfaceSubClass, | 1383 | alt->desc.bInterfaceSubClass, |
| 1390 | alt->desc.bInterfaceProtocol)) | 1384 | alt->desc.bInterfaceProtocol)) |
| 1391 | return -ENOMEM; | 1385 | return -ENOMEM; |
| 1392 | 1386 | ||
| 1393 | if (add_uevent_var(envp, num_envp, &i, | 1387 | if (add_uevent_var(env, |
| 1394 | buffer, buffer_size, &length, | ||
| 1395 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", | 1388 | "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", |
| 1396 | le16_to_cpu(usb_dev->descriptor.idVendor), | 1389 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 1397 | le16_to_cpu(usb_dev->descriptor.idProduct), | 1390 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| @@ -1404,14 +1397,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1404 | alt->desc.bInterfaceProtocol)) | 1397 | alt->desc.bInterfaceProtocol)) |
| 1405 | return -ENOMEM; | 1398 | return -ENOMEM; |
| 1406 | 1399 | ||
| 1407 | envp[i] = NULL; | ||
| 1408 | return 0; | 1400 | return 0; |
| 1409 | } | 1401 | } |
| 1410 | 1402 | ||
| 1411 | #else | 1403 | #else |
| 1412 | 1404 | ||
| 1413 | static int usb_if_uevent(struct device *dev, char **envp, | 1405 | static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1414 | int num_envp, char *buffer, int buffer_size) | ||
| 1415 | { | 1406 | { |
| 1416 | return -ENODEV; | 1407 | return -ENODEV; |
| 1417 | } | 1408 | } |
| @@ -1481,6 +1472,9 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, | |||
| 1481 | * channels are available independently; and choosing between open | 1472 | * channels are available independently; and choosing between open |
| 1482 | * standard device protocols (like CDC) or proprietary ones. | 1473 | * standard device protocols (like CDC) or proprietary ones. |
| 1483 | * | 1474 | * |
| 1475 | * Note that a non-authorized device (dev->authorized == 0) will only | ||
| 1476 | * be put in unconfigured mode. | ||
| 1477 | * | ||
| 1484 | * Note that USB has an additional level of device configurability, | 1478 | * Note that USB has an additional level of device configurability, |
| 1485 | * associated with interfaces. That configurability is accessed using | 1479 | * associated with interfaces. That configurability is accessed using |
| 1486 | * usb_set_interface(). | 1480 | * usb_set_interface(). |
| @@ -1502,7 +1496,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) | |||
| 1502 | struct usb_interface **new_interfaces = NULL; | 1496 | struct usb_interface **new_interfaces = NULL; |
| 1503 | int n, nintf; | 1497 | int n, nintf; |
| 1504 | 1498 | ||
| 1505 | if (configuration == -1) | 1499 | if (dev->authorized == 0 || configuration == -1) |
| 1506 | configuration = 0; | 1500 | configuration = 0; |
| 1507 | else { | 1501 | else { |
| 1508 | 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/drivers/video/output.c b/drivers/video/output.c index 1473f2c892d2..f2df5519c9c4 100644 --- a/drivers/video/output.c +++ b/drivers/video/output.c | |||
| @@ -31,7 +31,8 @@ MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction"); | |||
| 31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 32 | MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>"); | 32 | MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>"); |
| 33 | 33 | ||
| 34 | static ssize_t video_output_show_state(struct class_device *dev,char *buf) | 34 | static ssize_t video_output_show_state(struct device *dev, |
| 35 | struct device_attribute *attr, char *buf) | ||
| 35 | { | 36 | { |
| 36 | ssize_t ret_size = 0; | 37 | ssize_t ret_size = 0; |
| 37 | struct output_device *od = to_output_device(dev); | 38 | struct output_device *od = to_output_device(dev); |
| @@ -40,8 +41,9 @@ static ssize_t video_output_show_state(struct class_device *dev,char *buf) | |||
| 40 | return ret_size; | 41 | return ret_size; |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | static ssize_t video_output_store_state(struct class_device *dev, | 44 | static ssize_t video_output_store_state(struct device *dev, |
| 44 | const char *buf,size_t count) | 45 | struct device_attribute *attr, |
| 46 | const char *buf,size_t count) | ||
| 45 | { | 47 | { |
| 46 | char *endp; | 48 | char *endp; |
| 47 | struct output_device *od = to_output_device(dev); | 49 | struct output_device *od = to_output_device(dev); |
| @@ -60,21 +62,22 @@ static ssize_t video_output_store_state(struct class_device *dev, | |||
| 60 | return count; | 62 | return count; |
| 61 | } | 63 | } |
| 62 | 64 | ||
| 63 | static void video_output_class_release(struct class_device *dev) | 65 | static void video_output_release(struct device *dev) |
| 64 | { | 66 | { |
| 65 | struct output_device *od = to_output_device(dev); | 67 | struct output_device *od = to_output_device(dev); |
| 66 | kfree(od); | 68 | kfree(od); |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | static struct class_device_attribute video_output_attributes[] = { | 71 | static struct device_attribute video_output_attributes[] = { |
| 70 | __ATTR(state, 0644, video_output_show_state, video_output_store_state), | 72 | __ATTR(state, 0644, video_output_show_state, video_output_store_state), |
| 71 | __ATTR_NULL, | 73 | __ATTR_NULL, |
| 72 | }; | 74 | }; |
| 73 | 75 | ||
| 76 | |||
| 74 | static struct class video_output_class = { | 77 | static struct class video_output_class = { |
| 75 | .name = "video_output", | 78 | .name = "video_output", |
| 76 | .release = video_output_class_release, | 79 | .dev_release = video_output_release, |
| 77 | .class_dev_attrs = video_output_attributes, | 80 | .dev_attrs = video_output_attributes, |
| 78 | }; | 81 | }; |
| 79 | 82 | ||
| 80 | struct output_device *video_output_register(const char *name, | 83 | struct output_device *video_output_register(const char *name, |
| @@ -91,11 +94,11 @@ struct output_device *video_output_register(const char *name, | |||
| 91 | goto error_return; | 94 | goto error_return; |
| 92 | } | 95 | } |
| 93 | new_dev->props = op; | 96 | new_dev->props = op; |
| 94 | new_dev->class_dev.class = &video_output_class; | 97 | new_dev->dev.class = &video_output_class; |
| 95 | new_dev->class_dev.dev = dev; | 98 | new_dev->dev.parent = dev; |
| 96 | strlcpy(new_dev->class_dev.class_id,name,KOBJ_NAME_LEN); | 99 | strlcpy(new_dev->dev.bus_id,name, BUS_ID_SIZE); |
| 97 | class_set_devdata(&new_dev->class_dev,devdata); | 100 | dev_set_drvdata(&new_dev->dev, devdata); |
| 98 | ret_code = class_device_register(&new_dev->class_dev); | 101 | ret_code = device_register(&new_dev->dev); |
| 99 | if (ret_code) { | 102 | if (ret_code) { |
| 100 | kfree(new_dev); | 103 | kfree(new_dev); |
| 101 | goto error_return; | 104 | goto error_return; |
| @@ -111,7 +114,7 @@ void video_output_unregister(struct output_device *dev) | |||
| 111 | { | 114 | { |
| 112 | if (!dev) | 115 | if (!dev) |
| 113 | return; | 116 | return; |
| 114 | class_device_unregister(&dev->class_dev); | 117 | device_unregister(&dev->dev); |
| 115 | } | 118 | } |
| 116 | EXPORT_SYMBOL(video_output_unregister); | 119 | EXPORT_SYMBOL(video_output_unregister); |
| 117 | 120 | ||
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index a593f900eff4..070217322c9f 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -197,7 +197,7 @@ static struct w1_family w1_default_family = { | |||
| 197 | .fops = &w1_default_fops, | 197 | .fops = &w1_default_fops, |
| 198 | }; | 198 | }; |
| 199 | 199 | ||
| 200 | static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); | 200 | static int w1_uevent(struct device *dev, struct kobj_uevent_env *env); |
| 201 | 201 | ||
| 202 | static struct bus_type w1_bus_type = { | 202 | static struct bus_type w1_bus_type = { |
| 203 | .name = "w1", | 203 | .name = "w1", |
| @@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master) | |||
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | #ifdef CONFIG_HOTPLUG | 398 | #ifdef CONFIG_HOTPLUG |
| 399 | static int w1_uevent(struct device *dev, char **envp, int num_envp, | 399 | static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 400 | char *buffer, int buffer_size) | ||
| 401 | { | 400 | { |
| 402 | struct w1_master *md = NULL; | 401 | struct w1_master *md = NULL; |
| 403 | struct w1_slave *sl = NULL; | 402 | struct w1_slave *sl = NULL; |
| 404 | char *event_owner, *name; | 403 | char *event_owner, *name; |
| 405 | int err, cur_index=0, cur_len=0; | 404 | int err; |
| 406 | 405 | ||
| 407 | if (dev->driver == &w1_master_driver) { | 406 | if (dev->driver == &w1_master_driver) { |
| 408 | md = container_of(dev, struct w1_master, dev); | 407 | md = container_of(dev, struct w1_master, dev); |
| @@ -423,23 +422,19 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, | |||
| 423 | if (dev->driver != &w1_slave_driver || !sl) | 422 | if (dev->driver != &w1_slave_driver || !sl) |
| 424 | return 0; | 423 | return 0; |
| 425 | 424 | ||
| 426 | err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, | 425 | err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family); |
| 427 | &cur_len, "W1_FID=%02X", sl->reg_num.family); | ||
| 428 | if (err) | 426 | if (err) |
| 429 | return err; | 427 | return err; |
| 430 | 428 | ||
| 431 | err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, | 429 | err = add_uevent_var(env, "W1_SLAVE_ID=%024LX", |
| 432 | &cur_len, "W1_SLAVE_ID=%024LX", | 430 | (unsigned long long)sl->reg_num.id); |
| 433 | (unsigned long long)sl->reg_num.id); | ||
| 434 | envp[cur_index] = NULL; | ||
| 435 | if (err) | 431 | if (err) |
| 436 | return err; | 432 | return err; |
| 437 | 433 | ||
| 438 | return 0; | 434 | return 0; |
| 439 | }; | 435 | }; |
| 440 | #else | 436 | #else |
| 441 | static int w1_uevent(struct device *dev, char **envp, int num_envp, | 437 | static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 442 | char *buffer, int buffer_size) | ||
| 443 | { | 438 | { |
| 444 | return 0; | 439 | return 0; |
| 445 | } | 440 | } |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 2e124e0075c5..a9b99c0dc2e7 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
| @@ -221,6 +221,42 @@ struct dentry *debugfs_create_u64(const char *name, mode_t mode, | |||
| 221 | } | 221 | } |
| 222 | EXPORT_SYMBOL_GPL(debugfs_create_u64); | 222 | EXPORT_SYMBOL_GPL(debugfs_create_u64); |
| 223 | 223 | ||
| 224 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); | ||
| 225 | |||
| 226 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); | ||
| 227 | |||
| 228 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); | ||
| 229 | |||
| 230 | /** | ||
| 231 | * debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value | ||
| 232 | * debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value | ||
| 233 | * debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value | ||
| 234 | * | ||
| 235 | * These functions are exactly the same as the above functions, (but use a hex | ||
| 236 | * output for the decimal challenged) for details look at the above unsigned | ||
| 237 | * decimal functions. | ||
| 238 | */ | ||
| 239 | struct dentry *debugfs_create_x8(const char *name, mode_t mode, | ||
| 240 | struct dentry *parent, u8 *value) | ||
| 241 | { | ||
| 242 | return debugfs_create_file(name, mode, parent, value, &fops_x8); | ||
| 243 | } | ||
| 244 | EXPORT_SYMBOL_GPL(debugfs_create_x8); | ||
| 245 | |||
| 246 | struct dentry *debugfs_create_x16(const char *name, mode_t mode, | ||
| 247 | struct dentry *parent, u16 *value) | ||
| 248 | { | ||
| 249 | return debugfs_create_file(name, mode, parent, value, &fops_x16); | ||
| 250 | } | ||
| 251 | EXPORT_SYMBOL_GPL(debugfs_create_x16); | ||
| 252 | |||
| 253 | struct dentry *debugfs_create_x32(const char *name, mode_t mode, | ||
| 254 | struct dentry *parent, u32 *value) | ||
| 255 | { | ||
| 256 | return debugfs_create_file(name, mode, parent, value, &fops_x32); | ||
| 257 | } | ||
| 258 | EXPORT_SYMBOL_GPL(debugfs_create_x32); | ||
| 259 | |||
| 224 | static ssize_t read_file_bool(struct file *file, char __user *user_buf, | 260 | static ssize_t read_file_bool(struct file *file, char __user *user_buf, |
| 225 | size_t count, loff_t *ppos) | 261 | size_t count, loff_t *ppos) |
| 226 | { | 262 | { |
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 1dc72105ab12..6353a8384520 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
| @@ -167,7 +167,6 @@ static struct kobj_type dlm_ktype = { | |||
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 169 | static struct kset dlm_kset = { | 169 | static struct kset dlm_kset = { |
| 170 | .kobj = {.name = "dlm",}, | ||
| 171 | .ktype = &dlm_ktype, | 170 | .ktype = &dlm_ktype, |
| 172 | }; | 171 | }; |
| 173 | 172 | ||
| @@ -228,6 +227,7 @@ int dlm_lockspace_init(void) | |||
| 228 | INIT_LIST_HEAD(&lslist); | 227 | INIT_LIST_HEAD(&lslist); |
| 229 | spin_lock_init(&lslist_lock); | 228 | spin_lock_init(&lslist_lock); |
| 230 | 229 | ||
| 230 | kobject_set_name(&dlm_kset.kobj, "dlm"); | ||
| 231 | kobj_set_kset_s(&dlm_kset, kernel_subsys); | 231 | kobj_set_kset_s(&dlm_kset, kernel_subsys); |
| 232 | error = kset_register(&dlm_kset); | 232 | error = kset_register(&dlm_kset); |
| 233 | if (error) | 233 | if (error) |
| @@ -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/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c index d9fe3ca40e18..ae9e6a25fe2b 100644 --- a/fs/gfs2/locking/dlm/sysfs.c +++ b/fs/gfs2/locking/dlm/sysfs.c | |||
| @@ -190,7 +190,6 @@ static struct kobj_type gdlm_ktype = { | |||
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | static struct kset gdlm_kset = { | 192 | static struct kset gdlm_kset = { |
| 193 | .kobj = {.name = "lock_dlm",}, | ||
| 194 | .ktype = &gdlm_ktype, | 193 | .ktype = &gdlm_ktype, |
| 195 | }; | 194 | }; |
| 196 | 195 | ||
| @@ -224,6 +223,7 @@ int gdlm_sysfs_init(void) | |||
| 224 | { | 223 | { |
| 225 | int error; | 224 | int error; |
| 226 | 225 | ||
| 226 | kobject_set_name(&gdlm_kset.kobj, "lock_dlm"); | ||
| 227 | kobj_set_kset_s(&gdlm_kset, kernel_subsys); | 227 | kobj_set_kset_s(&gdlm_kset, kernel_subsys); |
| 228 | error = kset_register(&gdlm_kset); | 228 | error = kset_register(&gdlm_kset); |
| 229 | if (error) | 229 | if (error) |
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 c26c21b53c19..06e0b7768d97 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
| @@ -222,7 +222,6 @@ static struct kobj_type gfs2_ktype = { | |||
| 222 | }; | 222 | }; |
| 223 | 223 | ||
| 224 | static struct kset gfs2_kset = { | 224 | static struct kset gfs2_kset = { |
| 225 | .kobj = {.name = "gfs2"}, | ||
| 226 | .ktype = &gfs2_ktype, | 225 | .ktype = &gfs2_ktype, |
| 227 | }; | 226 | }; |
| 228 | 227 | ||
| @@ -442,7 +441,6 @@ TUNE_ATTR(quota_simul_sync, 1); | |||
| 442 | TUNE_ATTR(quota_cache_secs, 1); | 441 | TUNE_ATTR(quota_cache_secs, 1); |
| 443 | TUNE_ATTR(stall_secs, 1); | 442 | TUNE_ATTR(stall_secs, 1); |
| 444 | TUNE_ATTR(statfs_quantum, 1); | 443 | TUNE_ATTR(statfs_quantum, 1); |
| 445 | TUNE_ATTR_DAEMON(scand_secs, scand_process); | ||
| 446 | TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); | 444 | TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); |
| 447 | TUNE_ATTR_DAEMON(logd_secs, logd_process); | 445 | TUNE_ATTR_DAEMON(logd_secs, logd_process); |
| 448 | TUNE_ATTR_DAEMON(quotad_secs, quotad_process); | 446 | TUNE_ATTR_DAEMON(quotad_secs, quotad_process); |
| @@ -464,7 +462,6 @@ static struct attribute *tune_attrs[] = { | |||
| 464 | &tune_attr_quota_cache_secs.attr, | 462 | &tune_attr_quota_cache_secs.attr, |
| 465 | &tune_attr_stall_secs.attr, | 463 | &tune_attr_stall_secs.attr, |
| 466 | &tune_attr_statfs_quantum.attr, | 464 | &tune_attr_statfs_quantum.attr, |
| 467 | &tune_attr_scand_secs.attr, | ||
| 468 | &tune_attr_recoverd_secs.attr, | 465 | &tune_attr_recoverd_secs.attr, |
| 469 | &tune_attr_logd_secs.attr, | 466 | &tune_attr_logd_secs.attr, |
| 470 | &tune_attr_quotad_secs.attr, | 467 | &tune_attr_quotad_secs.attr, |
| @@ -553,6 +550,7 @@ int gfs2_sys_init(void) | |||
| 553 | { | 550 | { |
| 554 | gfs2_sys_margs = NULL; | 551 | gfs2_sys_margs = NULL; |
| 555 | spin_lock_init(&gfs2_sys_margs_lock); | 552 | spin_lock_init(&gfs2_sys_margs_lock); |
| 553 | kobject_set_name(&gfs2_kset.kobj, "gfs2"); | ||
| 556 | kobj_set_kset_s(&gfs2_kset, fs_subsys); | 554 | kobj_set_kset_s(&gfs2_kset, fs_subsys); |
| 557 | return kset_register(&gfs2_kset); | 555 | return kset_register(&gfs2_kset); |
| 558 | } | 556 | } |
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/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index e9e042b93dbf..a4882c8df945 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c | |||
| @@ -143,7 +143,7 @@ static struct kobj_type mlog_ktype = { | |||
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | static struct kset mlog_kset = { | 145 | static struct kset mlog_kset = { |
| 146 | .kobj = {.name = "logmask", .ktype = &mlog_ktype}, | 146 | .kobj = {.ktype = &mlog_ktype}, |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | int mlog_sys_init(struct kset *o2cb_subsys) | 149 | int mlog_sys_init(struct kset *o2cb_subsys) |
| @@ -156,6 +156,7 @@ int mlog_sys_init(struct kset *o2cb_subsys) | |||
| 156 | } | 156 | } |
| 157 | mlog_attr_ptrs[i] = NULL; | 157 | mlog_attr_ptrs[i] = NULL; |
| 158 | 158 | ||
| 159 | kobject_set_name(&mlog_kset.kobj, "logmask"); | ||
| 159 | kobj_set_kset_s(&mlog_kset, *o2cb_subsys); | 160 | kobj_set_kset_s(&mlog_kset, *o2cb_subsys); |
| 160 | return kset_register(&mlog_kset); | 161 | return kset_register(&mlog_kset); |
| 161 | } | 162 | } |
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/fs/partitions/check.c b/fs/partitions/check.c index 783c57ec07d3..722e12e5acc7 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -381,10 +381,12 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, | |||
| 381 | p->partno = part; | 381 | p->partno = part; |
| 382 | p->policy = disk->policy; | 382 | p->policy = disk->policy; |
| 383 | 383 | ||
| 384 | if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1])) | 384 | if (isdigit(disk->kobj.k_name[strlen(disk->kobj.k_name)-1])) |
| 385 | snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part); | 385 | kobject_set_name(&p->kobj, "%sp%d", |
| 386 | kobject_name(&disk->kobj), part); | ||
| 386 | else | 387 | else |
| 387 | snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); | 388 | kobject_set_name(&p->kobj, "%s%d", |
| 389 | kobject_name(&disk->kobj),part); | ||
| 388 | p->kobj.parent = &disk->kobj; | 390 | p->kobj.parent = &disk->kobj; |
| 389 | p->kobj.ktype = &ktype_part; | 391 | p->kobj.ktype = &ktype_part; |
| 390 | kobject_init(&p->kobj); | 392 | kobject_init(&p->kobj); |
| @@ -477,9 +479,9 @@ void register_disk(struct gendisk *disk) | |||
| 477 | struct hd_struct *p; | 479 | struct hd_struct *p; |
| 478 | int err; | 480 | int err; |
| 479 | 481 | ||
| 480 | strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN); | 482 | kobject_set_name(&disk->kobj, "%s", disk->disk_name); |
| 481 | /* ewww... some of these buggers have / in name... */ | 483 | /* ewww... some of these buggers have / in name... */ |
| 482 | s = strchr(disk->kobj.name, '/'); | 484 | s = strchr(disk->kobj.k_name, '/'); |
| 483 | if (s) | 485 | if (s) |
| 484 | *s = '!'; | 486 | *s = '!'; |
| 485 | if ((err = kobject_add(&disk->kobj))) | 487 | if ((err = kobject_add(&disk->kobj))) |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 5afe2a26f5d8..006fc64227dd 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -1,9 +1,15 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * bin.c - binary file operations for sysfs. | 2 | * fs/sysfs/bin.c - sysfs binary file implementation |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2003 Patrick Mochel | 4 | * Copyright (c) 2003 Patrick Mochel |
| 5 | * Copyright (c) 2003 Matthew Wilcox | 5 | * Copyright (c) 2003 Matthew Wilcox |
| 6 | * Copyright (c) 2004 Silicon Graphics, Inc. | 6 | * Copyright (c) 2004 Silicon Graphics, Inc. |
| 7 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 8 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 9 | * | ||
| 10 | * This file is released under the GPLv2. | ||
| 11 | * | ||
| 12 | * Please see Documentation/filesystems/sysfs.txt for more information. | ||
| 7 | */ | 13 | */ |
| 8 | 14 | ||
| 9 | #undef DEBUG | 15 | #undef DEBUG |
| @@ -14,9 +20,9 @@ | |||
| 14 | #include <linux/kobject.h> | 20 | #include <linux/kobject.h> |
| 15 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 16 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/mutex.h> | ||
| 17 | 24 | ||
| 18 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
| 19 | #include <asm/semaphore.h> | ||
| 20 | 26 | ||
| 21 | #include "sysfs.h" | 27 | #include "sysfs.h" |
| 22 | 28 | ||
| @@ -30,8 +36,8 @@ static int | |||
| 30 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | 36 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) |
| 31 | { | 37 | { |
| 32 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 38 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 33 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | 39 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 34 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 40 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 35 | int rc; | 41 | int rc; |
| 36 | 42 | ||
| 37 | /* need attr_sd for attr, its parent for kobj */ | 43 | /* need attr_sd for attr, its parent for kobj */ |
| @@ -87,8 +93,8 @@ static int | |||
| 87 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | 93 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) |
| 88 | { | 94 | { |
| 89 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 95 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 90 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | 96 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 91 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 97 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 92 | int rc; | 98 | int rc; |
| 93 | 99 | ||
| 94 | /* need attr_sd for attr, its parent for kobj */ | 100 | /* need attr_sd for attr, its parent for kobj */ |
| @@ -140,8 +146,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
| 140 | { | 146 | { |
| 141 | struct bin_buffer *bb = file->private_data; | 147 | struct bin_buffer *bb = file->private_data; |
| 142 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 148 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 143 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | 149 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 144 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 150 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 145 | int rc; | 151 | int rc; |
| 146 | 152 | ||
| 147 | mutex_lock(&bb->mutex); | 153 | mutex_lock(&bb->mutex); |
| @@ -167,12 +173,12 @@ static int mmap(struct file *file, struct vm_area_struct *vma) | |||
| 167 | static int open(struct inode * inode, struct file * file) | 173 | static int open(struct inode * inode, struct file * file) |
| 168 | { | 174 | { |
| 169 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 175 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 170 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; | 176 | struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; |
| 171 | struct bin_buffer *bb = NULL; | 177 | struct bin_buffer *bb = NULL; |
| 172 | int error; | 178 | int error; |
| 173 | 179 | ||
| 174 | /* need attr_sd for attr */ | 180 | /* binary file operations requires both @sd and its parent */ |
| 175 | if (!sysfs_get_active(attr_sd)) | 181 | if (!sysfs_get_active_two(attr_sd)) |
| 176 | return -ENODEV; | 182 | return -ENODEV; |
| 177 | 183 | ||
| 178 | error = -EACCES; | 184 | error = -EACCES; |
| @@ -193,13 +199,12 @@ static int open(struct inode * inode, struct file * file) | |||
| 193 | mutex_init(&bb->mutex); | 199 | mutex_init(&bb->mutex); |
| 194 | file->private_data = bb; | 200 | file->private_data = bb; |
| 195 | 201 | ||
| 196 | /* open succeeded, put active reference and pin attr_sd */ | 202 | /* open succeeded, put active references */ |
| 197 | sysfs_put_active(attr_sd); | 203 | sysfs_put_active_two(attr_sd); |
| 198 | sysfs_get(attr_sd); | ||
| 199 | return 0; | 204 | return 0; |
| 200 | 205 | ||
| 201 | err_out: | 206 | err_out: |
| 202 | sysfs_put_active(attr_sd); | 207 | sysfs_put_active_two(attr_sd); |
| 203 | kfree(bb); | 208 | kfree(bb); |
| 204 | return error; | 209 | return error; |
| 205 | } | 210 | } |
| @@ -211,7 +216,6 @@ static int release(struct inode * inode, struct file * file) | |||
| 211 | 216 | ||
| 212 | if (bb->mmapped) | 217 | if (bb->mmapped) |
| 213 | sysfs_put_active_two(attr_sd); | 218 | sysfs_put_active_two(attr_sd); |
| 214 | sysfs_put(attr_sd); | ||
| 215 | kfree(bb->buffer); | 219 | kfree(bb->buffer); |
| 216 | kfree(bb); | 220 | kfree(bb); |
| 217 | return 0; | 221 | return 0; |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 83e76b3813c9..9161db4d6b5c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * dir.c - Operations for sysfs directories. | 2 | * fs/sysfs/dir.c - sysfs core and dir operation implementation |
| 3 | * | ||
| 4 | * Copyright (c) 2001-3 Patrick Mochel | ||
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 9 | * | ||
| 10 | * Please see Documentation/filesystems/sysfs.txt for more information. | ||
| 3 | */ | 11 | */ |
| 4 | 12 | ||
| 5 | #undef DEBUG | 13 | #undef DEBUG |
| @@ -11,10 +19,11 @@ | |||
| 11 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
| 12 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
| 13 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
| 14 | #include <asm/semaphore.h> | 22 | #include <linux/mutex.h> |
| 15 | #include "sysfs.h" | 23 | #include "sysfs.h" |
| 16 | 24 | ||
| 17 | DEFINE_MUTEX(sysfs_mutex); | 25 | DEFINE_MUTEX(sysfs_mutex); |
| 26 | DEFINE_MUTEX(sysfs_rename_mutex); | ||
| 18 | spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; | 27 | spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; |
| 19 | 28 | ||
| 20 | static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; | 29 | static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; |
| @@ -25,18 +34,28 @@ static DEFINE_IDA(sysfs_ino_ida); | |||
| 25 | * @sd: sysfs_dirent of interest | 34 | * @sd: sysfs_dirent of interest |
| 26 | * | 35 | * |
| 27 | * Link @sd into its sibling list which starts from | 36 | * Link @sd into its sibling list which starts from |
| 28 | * sd->s_parent->s_children. | 37 | * sd->s_parent->s_dir.children. |
| 29 | * | 38 | * |
| 30 | * Locking: | 39 | * Locking: |
| 31 | * mutex_lock(sysfs_mutex) | 40 | * mutex_lock(sysfs_mutex) |
| 32 | */ | 41 | */ |
| 33 | void sysfs_link_sibling(struct sysfs_dirent *sd) | 42 | static void sysfs_link_sibling(struct sysfs_dirent *sd) |
| 34 | { | 43 | { |
| 35 | struct sysfs_dirent *parent_sd = sd->s_parent; | 44 | struct sysfs_dirent *parent_sd = sd->s_parent; |
| 45 | struct sysfs_dirent **pos; | ||
| 36 | 46 | ||
| 37 | BUG_ON(sd->s_sibling); | 47 | BUG_ON(sd->s_sibling); |
| 38 | sd->s_sibling = parent_sd->s_children; | 48 | |
| 39 | parent_sd->s_children = sd; | 49 | /* Store directory entries in order by ino. This allows |
| 50 | * readdir to properly restart without having to add a | ||
| 51 | * cursor into the s_dir.children list. | ||
| 52 | */ | ||
| 53 | for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { | ||
| 54 | if (sd->s_ino < (*pos)->s_ino) | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | sd->s_sibling = *pos; | ||
| 58 | *pos = sd; | ||
| 40 | } | 59 | } |
| 41 | 60 | ||
| 42 | /** | 61 | /** |
| @@ -44,16 +63,17 @@ void sysfs_link_sibling(struct sysfs_dirent *sd) | |||
| 44 | * @sd: sysfs_dirent of interest | 63 | * @sd: sysfs_dirent of interest |
| 45 | * | 64 | * |
| 46 | * Unlink @sd from its sibling list which starts from | 65 | * Unlink @sd from its sibling list which starts from |
| 47 | * sd->s_parent->s_children. | 66 | * sd->s_parent->s_dir.children. |
| 48 | * | 67 | * |
| 49 | * Locking: | 68 | * Locking: |
| 50 | * mutex_lock(sysfs_mutex) | 69 | * mutex_lock(sysfs_mutex) |
| 51 | */ | 70 | */ |
| 52 | void sysfs_unlink_sibling(struct sysfs_dirent *sd) | 71 | static void sysfs_unlink_sibling(struct sysfs_dirent *sd) |
| 53 | { | 72 | { |
| 54 | struct sysfs_dirent **pos; | 73 | struct sysfs_dirent **pos; |
| 55 | 74 | ||
| 56 | for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) { | 75 | for (pos = &sd->s_parent->s_dir.children; *pos; |
| 76 | pos = &(*pos)->s_sibling) { | ||
| 57 | if (*pos == sd) { | 77 | if (*pos == sd) { |
| 58 | *pos = sd->s_sibling; | 78 | *pos = sd->s_sibling; |
| 59 | sd->s_sibling = NULL; | 79 | sd->s_sibling = NULL; |
| @@ -67,96 +87,39 @@ void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
| 67 | * @sd: sysfs_dirent of interest | 87 | * @sd: sysfs_dirent of interest |
| 68 | * | 88 | * |
| 69 | * Get dentry for @sd. Dentry is looked up if currently not | 89 | * Get dentry for @sd. Dentry is looked up if currently not |
| 70 | * present. This function climbs sysfs_dirent tree till it | 90 | * present. This function descends from the root looking up |
| 71 | * reaches a sysfs_dirent with valid dentry attached and descends | 91 | * dentry for each step. |
| 72 | * down from there looking up dentry for each step. | ||
| 73 | * | 92 | * |
| 74 | * LOCKING: | 93 | * LOCKING: |
| 75 | * Kernel thread context (may sleep) | 94 | * mutex_lock(sysfs_rename_mutex) |
| 76 | * | 95 | * |
| 77 | * RETURNS: | 96 | * RETURNS: |
| 78 | * Pointer to found dentry on success, ERR_PTR() value on error. | 97 | * Pointer to found dentry on success, ERR_PTR() value on error. |
| 79 | */ | 98 | */ |
| 80 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) | 99 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) |
| 81 | { | 100 | { |
| 82 | struct sysfs_dirent *cur; | 101 | struct dentry *dentry = dget(sysfs_sb->s_root); |
| 83 | struct dentry *parent_dentry, *dentry; | ||
| 84 | int i, depth; | ||
| 85 | |||
| 86 | /* Find the first parent which has valid s_dentry and get the | ||
| 87 | * dentry. | ||
| 88 | */ | ||
| 89 | mutex_lock(&sysfs_mutex); | ||
| 90 | restart0: | ||
| 91 | spin_lock(&sysfs_assoc_lock); | ||
| 92 | restart1: | ||
| 93 | spin_lock(&dcache_lock); | ||
| 94 | 102 | ||
| 95 | dentry = NULL; | 103 | while (dentry->d_fsdata != sd) { |
| 96 | depth = 0; | 104 | struct sysfs_dirent *cur; |
| 97 | cur = sd; | 105 | struct dentry *parent; |
| 98 | while (!cur->s_dentry || !cur->s_dentry->d_inode) { | ||
| 99 | if (cur->s_flags & SYSFS_FLAG_REMOVED) { | ||
| 100 | dentry = ERR_PTR(-ENOENT); | ||
| 101 | depth = 0; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | cur = cur->s_parent; | ||
| 105 | depth++; | ||
| 106 | } | ||
| 107 | if (!IS_ERR(dentry)) | ||
| 108 | dentry = dget_locked(cur->s_dentry); | ||
| 109 | 106 | ||
| 110 | spin_unlock(&dcache_lock); | 107 | /* find the first ancestor which hasn't been looked up */ |
| 111 | spin_unlock(&sysfs_assoc_lock); | 108 | cur = sd; |
| 112 | 109 | while (cur->s_parent != dentry->d_fsdata) | |
| 113 | /* from the found dentry, look up depth times */ | ||
| 114 | while (depth--) { | ||
| 115 | /* find and get depth'th ancestor */ | ||
| 116 | for (cur = sd, i = 0; cur && i < depth; i++) | ||
| 117 | cur = cur->s_parent; | 110 | cur = cur->s_parent; |
| 118 | 111 | ||
| 119 | /* This can happen if tree structure was modified due | ||
| 120 | * to move/rename. Restart. | ||
| 121 | */ | ||
| 122 | if (i != depth) { | ||
| 123 | dput(dentry); | ||
| 124 | goto restart0; | ||
| 125 | } | ||
| 126 | |||
| 127 | sysfs_get(cur); | ||
| 128 | |||
| 129 | mutex_unlock(&sysfs_mutex); | ||
| 130 | |||
| 131 | /* look it up */ | 112 | /* look it up */ |
| 132 | parent_dentry = dentry; | 113 | parent = dentry; |
| 133 | dentry = lookup_one_len_kern(cur->s_name, parent_dentry, | 114 | mutex_lock(&parent->d_inode->i_mutex); |
| 115 | dentry = lookup_one_len_kern(cur->s_name, parent, | ||
| 134 | strlen(cur->s_name)); | 116 | strlen(cur->s_name)); |
| 135 | dput(parent_dentry); | 117 | mutex_unlock(&parent->d_inode->i_mutex); |
| 136 | 118 | dput(parent); | |
| 137 | if (IS_ERR(dentry)) { | ||
| 138 | sysfs_put(cur); | ||
| 139 | return dentry; | ||
| 140 | } | ||
| 141 | 119 | ||
| 142 | mutex_lock(&sysfs_mutex); | 120 | if (IS_ERR(dentry)) |
| 143 | spin_lock(&sysfs_assoc_lock); | 121 | break; |
| 144 | |||
| 145 | /* This, again, can happen if tree structure has | ||
| 146 | * changed and we looked up the wrong thing. Restart. | ||
| 147 | */ | ||
| 148 | if (cur->s_dentry != dentry) { | ||
| 149 | dput(dentry); | ||
| 150 | sysfs_put(cur); | ||
| 151 | goto restart1; | ||
| 152 | } | ||
| 153 | |||
| 154 | spin_unlock(&sysfs_assoc_lock); | ||
| 155 | |||
| 156 | sysfs_put(cur); | ||
| 157 | } | 122 | } |
| 158 | |||
| 159 | mutex_unlock(&sysfs_mutex); | ||
| 160 | return dentry; | 123 | return dentry; |
| 161 | } | 124 | } |
| 162 | 125 | ||
| @@ -319,7 +282,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
| 319 | parent_sd = sd->s_parent; | 282 | parent_sd = sd->s_parent; |
| 320 | 283 | ||
| 321 | if (sysfs_type(sd) == SYSFS_KOBJ_LINK) | 284 | if (sysfs_type(sd) == SYSFS_KOBJ_LINK) |
| 322 | sysfs_put(sd->s_elem.symlink.target_sd); | 285 | sysfs_put(sd->s_symlink.target_sd); |
| 323 | if (sysfs_type(sd) & SYSFS_COPY_NAME) | 286 | if (sysfs_type(sd) & SYSFS_COPY_NAME) |
| 324 | kfree(sd->s_name); | 287 | kfree(sd->s_name); |
| 325 | kfree(sd->s_iattr); | 288 | kfree(sd->s_iattr); |
| @@ -335,22 +298,7 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) | |||
| 335 | { | 298 | { |
| 336 | struct sysfs_dirent * sd = dentry->d_fsdata; | 299 | struct sysfs_dirent * sd = dentry->d_fsdata; |
| 337 | 300 | ||
| 338 | if (sd) { | 301 | sysfs_put(sd); |
| 339 | /* sd->s_dentry is protected with sysfs_assoc_lock. | ||
| 340 | * This allows sysfs_drop_dentry() to dereference it. | ||
| 341 | */ | ||
| 342 | spin_lock(&sysfs_assoc_lock); | ||
| 343 | |||
| 344 | /* The dentry might have been deleted or another | ||
| 345 | * lookup could have happened updating sd->s_dentry to | ||
| 346 | * point the new dentry. Ignore if it isn't pointing | ||
| 347 | * to this dentry. | ||
| 348 | */ | ||
| 349 | if (sd->s_dentry == dentry) | ||
| 350 | sd->s_dentry = NULL; | ||
| 351 | spin_unlock(&sysfs_assoc_lock); | ||
| 352 | sysfs_put(sd); | ||
| 353 | } | ||
| 354 | iput(inode); | 302 | iput(inode); |
| 355 | } | 303 | } |
| 356 | 304 | ||
| @@ -378,7 +326,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
| 378 | 326 | ||
| 379 | atomic_set(&sd->s_count, 1); | 327 | atomic_set(&sd->s_count, 1); |
| 380 | atomic_set(&sd->s_active, 0); | 328 | atomic_set(&sd->s_active, 0); |
| 381 | atomic_set(&sd->s_event, 1); | ||
| 382 | 329 | ||
| 383 | sd->s_name = name; | 330 | sd->s_name = name; |
| 384 | sd->s_mode = mode; | 331 | sd->s_mode = mode; |
| @@ -393,30 +340,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
| 393 | return NULL; | 340 | return NULL; |
| 394 | } | 341 | } |
| 395 | 342 | ||
| 396 | /** | ||
| 397 | * sysfs_attach_dentry - associate sysfs_dirent with dentry | ||
| 398 | * @sd: target sysfs_dirent | ||
| 399 | * @dentry: dentry to associate | ||
| 400 | * | ||
| 401 | * Associate @sd with @dentry. This is protected by | ||
| 402 | * sysfs_assoc_lock to avoid race with sysfs_d_iput(). | ||
| 403 | * | ||
| 404 | * LOCKING: | ||
| 405 | * mutex_lock(sysfs_mutex) | ||
| 406 | */ | ||
| 407 | static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) | ||
| 408 | { | ||
| 409 | dentry->d_op = &sysfs_dentry_ops; | ||
| 410 | dentry->d_fsdata = sysfs_get(sd); | ||
| 411 | |||
| 412 | /* protect sd->s_dentry against sysfs_d_iput */ | ||
| 413 | spin_lock(&sysfs_assoc_lock); | ||
| 414 | sd->s_dentry = dentry; | ||
| 415 | spin_unlock(&sysfs_assoc_lock); | ||
| 416 | |||
| 417 | d_rehash(dentry); | ||
| 418 | } | ||
| 419 | |||
| 420 | static int sysfs_ilookup_test(struct inode *inode, void *arg) | 343 | static int sysfs_ilookup_test(struct inode *inode, void *arg) |
| 421 | { | 344 | { |
| 422 | struct sysfs_dirent *sd = arg; | 345 | struct sysfs_dirent *sd = arg; |
| @@ -480,10 +403,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
| 480 | * @sd: sysfs_dirent to be added | 403 | * @sd: sysfs_dirent to be added |
| 481 | * | 404 | * |
| 482 | * Get @acxt->parent_sd and set sd->s_parent to it and increment | 405 | * Get @acxt->parent_sd and set sd->s_parent to it and increment |
| 483 | * nlink of parent inode if @sd is a directory. @sd is NOT | 406 | * nlink of parent inode if @sd is a directory and link into the |
| 484 | * linked into the children list of the parent. The caller | 407 | * children list of the parent. |
| 485 | * should invoke sysfs_link_sibling() after this function | ||
| 486 | * completes if @sd needs to be on the children list. | ||
| 487 | * | 408 | * |
| 488 | * This function should be called between calls to | 409 | * This function should be called between calls to |
| 489 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | 410 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be |
| @@ -491,15 +412,30 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
| 491 | * | 412 | * |
| 492 | * LOCKING: | 413 | * LOCKING: |
| 493 | * Determined by sysfs_addrm_start(). | 414 | * Determined by sysfs_addrm_start(). |
| 415 | * | ||
| 416 | * RETURNS: | ||
| 417 | * 0 on success, -EEXIST if entry with the given name already | ||
| 418 | * exists. | ||
| 494 | */ | 419 | */ |
| 495 | void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 420 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) |
| 496 | { | 421 | { |
| 422 | if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) { | ||
| 423 | printk(KERN_WARNING "sysfs: duplicate filename '%s' " | ||
| 424 | "can not be created\n", sd->s_name); | ||
| 425 | WARN_ON(1); | ||
| 426 | return -EEXIST; | ||
| 427 | } | ||
| 428 | |||
| 497 | sd->s_parent = sysfs_get(acxt->parent_sd); | 429 | sd->s_parent = sysfs_get(acxt->parent_sd); |
| 498 | 430 | ||
| 499 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) | 431 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) |
| 500 | inc_nlink(acxt->parent_inode); | 432 | inc_nlink(acxt->parent_inode); |
| 501 | 433 | ||
| 502 | acxt->cnt++; | 434 | acxt->cnt++; |
| 435 | |||
| 436 | sysfs_link_sibling(sd); | ||
| 437 | |||
| 438 | return 0; | ||
| 503 | } | 439 | } |
| 504 | 440 | ||
| 505 | /** | 441 | /** |
| @@ -508,9 +444,7 @@ void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 508 | * @sd: sysfs_dirent to be added | 444 | * @sd: sysfs_dirent to be added |
| 509 | * | 445 | * |
| 510 | * Mark @sd removed and drop nlink of parent inode if @sd is a | 446 | * Mark @sd removed and drop nlink of parent inode if @sd is a |
| 511 | * directory. @sd is NOT unlinked from the children list of the | 447 | * directory. @sd is unlinked from the children list. |
| 512 | * parent. The caller is repsonsible for removing @sd from the | ||
| 513 | * children list before calling this function. | ||
| 514 | * | 448 | * |
| 515 | * This function should be called between calls to | 449 | * This function should be called between calls to |
| 516 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | 450 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be |
| @@ -521,7 +455,9 @@ void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 521 | */ | 455 | */ |
| 522 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 456 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) |
| 523 | { | 457 | { |
| 524 | BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED)); | 458 | BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); |
| 459 | |||
| 460 | sysfs_unlink_sibling(sd); | ||
| 525 | 461 | ||
| 526 | sd->s_flags |= SYSFS_FLAG_REMOVED; | 462 | sd->s_flags |= SYSFS_FLAG_REMOVED; |
| 527 | sd->s_sibling = acxt->removed; | 463 | sd->s_sibling = acxt->removed; |
| @@ -540,53 +476,49 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 540 | * Drop dentry for @sd. @sd must have been unlinked from its | 476 | * Drop dentry for @sd. @sd must have been unlinked from its |
| 541 | * parent on entry to this function such that it can't be looked | 477 | * parent on entry to this function such that it can't be looked |
| 542 | * up anymore. | 478 | * up anymore. |
| 543 | * | ||
| 544 | * @sd->s_dentry which is protected with sysfs_assoc_lock points | ||
| 545 | * to the currently associated dentry but we're not holding a | ||
| 546 | * reference to it and racing with dput(). Grab dcache_lock and | ||
| 547 | * verify dentry before dropping it. If @sd->s_dentry is NULL or | ||
| 548 | * dput() beats us, no need to bother. | ||
| 549 | */ | 479 | */ |
| 550 | static void sysfs_drop_dentry(struct sysfs_dirent *sd) | 480 | static void sysfs_drop_dentry(struct sysfs_dirent *sd) |
| 551 | { | 481 | { |
| 552 | struct dentry *dentry = NULL; | ||
| 553 | struct inode *inode; | 482 | struct inode *inode; |
| 483 | struct dentry *dentry; | ||
| 554 | 484 | ||
| 555 | /* We're not holding a reference to ->s_dentry dentry but the | 485 | inode = ilookup(sysfs_sb, sd->s_ino); |
| 556 | * field will stay valid as long as sysfs_assoc_lock is held. | 486 | if (!inode) |
| 487 | return; | ||
| 488 | |||
| 489 | /* Drop any existing dentries associated with sd. | ||
| 490 | * | ||
| 491 | * For the dentry to be properly freed we need to grab a | ||
| 492 | * reference to the dentry under the dcache lock, unhash it, | ||
| 493 | * and then put it. The playing with the dentry count allows | ||
| 494 | * dput to immediately free the dentry if it is not in use. | ||
| 557 | */ | 495 | */ |
| 558 | spin_lock(&sysfs_assoc_lock); | 496 | repeat: |
| 559 | spin_lock(&dcache_lock); | 497 | spin_lock(&dcache_lock); |
| 560 | 498 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | |
| 561 | /* drop dentry if it's there and dput() didn't kill it yet */ | 499 | if (d_unhashed(dentry)) |
| 562 | if (sd->s_dentry && sd->s_dentry->d_inode) { | 500 | continue; |
| 563 | dentry = dget_locked(sd->s_dentry); | 501 | dget_locked(dentry); |
| 564 | spin_lock(&dentry->d_lock); | 502 | spin_lock(&dentry->d_lock); |
| 565 | __d_drop(dentry); | 503 | __d_drop(dentry); |
| 566 | spin_unlock(&dentry->d_lock); | 504 | spin_unlock(&dentry->d_lock); |
| 505 | spin_unlock(&dcache_lock); | ||
| 506 | dput(dentry); | ||
| 507 | goto repeat; | ||
| 567 | } | 508 | } |
| 568 | |||
| 569 | spin_unlock(&dcache_lock); | 509 | spin_unlock(&dcache_lock); |
| 570 | spin_unlock(&sysfs_assoc_lock); | ||
| 571 | |||
| 572 | /* dentries for shadowed inodes are pinned, unpin */ | ||
| 573 | if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) | ||
| 574 | dput(dentry); | ||
| 575 | dput(dentry); | ||
| 576 | 510 | ||
| 577 | /* adjust nlink and update timestamp */ | 511 | /* adjust nlink and update timestamp */ |
| 578 | inode = ilookup(sysfs_sb, sd->s_ino); | 512 | mutex_lock(&inode->i_mutex); |
| 579 | if (inode) { | ||
| 580 | mutex_lock(&inode->i_mutex); | ||
| 581 | 513 | ||
| 582 | inode->i_ctime = CURRENT_TIME; | 514 | inode->i_ctime = CURRENT_TIME; |
| 515 | drop_nlink(inode); | ||
| 516 | if (sysfs_type(sd) == SYSFS_DIR) | ||
| 583 | drop_nlink(inode); | 517 | drop_nlink(inode); |
| 584 | if (sysfs_type(sd) == SYSFS_DIR) | ||
| 585 | drop_nlink(inode); | ||
| 586 | 518 | ||
| 587 | mutex_unlock(&inode->i_mutex); | 519 | mutex_unlock(&inode->i_mutex); |
| 588 | iput(inode); | 520 | |
| 589 | } | 521 | iput(inode); |
| 590 | } | 522 | } |
| 591 | 523 | ||
| 592 | /** | 524 | /** |
| @@ -599,11 +531,8 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) | |||
| 599 | * | 531 | * |
| 600 | * LOCKING: | 532 | * LOCKING: |
| 601 | * All mutexes acquired by sysfs_addrm_start() are released. | 533 | * All mutexes acquired by sysfs_addrm_start() are released. |
| 602 | * | ||
| 603 | * RETURNS: | ||
| 604 | * Number of added/removed sysfs_dirents since sysfs_addrm_start(). | ||
| 605 | */ | 534 | */ |
| 606 | int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | 535 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) |
| 607 | { | 536 | { |
| 608 | /* release resources acquired by sysfs_addrm_start() */ | 537 | /* release resources acquired by sysfs_addrm_start() */ |
| 609 | mutex_unlock(&sysfs_mutex); | 538 | mutex_unlock(&sysfs_mutex); |
| @@ -629,8 +558,6 @@ int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | |||
| 629 | sysfs_deactivate(sd); | 558 | sysfs_deactivate(sd); |
| 630 | sysfs_put(sd); | 559 | sysfs_put(sd); |
| 631 | } | 560 | } |
| 632 | |||
| 633 | return acxt->cnt; | ||
| 634 | } | 561 | } |
| 635 | 562 | ||
| 636 | /** | 563 | /** |
| @@ -651,8 +578,8 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | |||
| 651 | { | 578 | { |
| 652 | struct sysfs_dirent *sd; | 579 | struct sysfs_dirent *sd; |
| 653 | 580 | ||
| 654 | for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) | 581 | for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) |
| 655 | if (sysfs_type(sd) && !strcmp(sd->s_name, name)) | 582 | if (!strcmp(sd->s_name, name)) |
| 656 | return sd; | 583 | return sd; |
| 657 | return NULL; | 584 | return NULL; |
| 658 | } | 585 | } |
| @@ -690,28 +617,25 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
| 690 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 617 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
| 691 | struct sysfs_addrm_cxt acxt; | 618 | struct sysfs_addrm_cxt acxt; |
| 692 | struct sysfs_dirent *sd; | 619 | struct sysfs_dirent *sd; |
| 620 | int rc; | ||
| 693 | 621 | ||
| 694 | /* allocate */ | 622 | /* allocate */ |
| 695 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); | 623 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); |
| 696 | if (!sd) | 624 | if (!sd) |
| 697 | return -ENOMEM; | 625 | return -ENOMEM; |
| 698 | sd->s_elem.dir.kobj = kobj; | 626 | sd->s_dir.kobj = kobj; |
| 699 | 627 | ||
| 700 | /* link in */ | 628 | /* link in */ |
| 701 | sysfs_addrm_start(&acxt, parent_sd); | 629 | sysfs_addrm_start(&acxt, parent_sd); |
| 630 | rc = sysfs_add_one(&acxt, sd); | ||
| 631 | sysfs_addrm_finish(&acxt); | ||
| 702 | 632 | ||
| 703 | if (!sysfs_find_dirent(parent_sd, name)) { | 633 | if (rc == 0) |
| 704 | sysfs_add_one(&acxt, sd); | 634 | *p_sd = sd; |
| 705 | sysfs_link_sibling(sd); | 635 | else |
| 706 | } | ||
| 707 | |||
| 708 | if (!sysfs_addrm_finish(&acxt)) { | ||
| 709 | sysfs_put(sd); | 636 | sysfs_put(sd); |
| 710 | return -EEXIST; | ||
| 711 | } | ||
| 712 | 637 | ||
| 713 | *p_sd = sd; | 638 | return rc; |
| 714 | return 0; | ||
| 715 | } | 639 | } |
| 716 | 640 | ||
| 717 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | 641 | int sysfs_create_subdir(struct kobject *kobj, const char *name, |
| @@ -723,24 +647,18 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, | |||
| 723 | /** | 647 | /** |
| 724 | * sysfs_create_dir - create a directory for an object. | 648 | * sysfs_create_dir - create a directory for an object. |
| 725 | * @kobj: object we're creating directory for. | 649 | * @kobj: object we're creating directory for. |
| 726 | * @shadow_parent: parent object. | ||
| 727 | */ | 650 | */ |
| 728 | int sysfs_create_dir(struct kobject *kobj, | 651 | int sysfs_create_dir(struct kobject * kobj) |
| 729 | struct sysfs_dirent *shadow_parent_sd) | ||
| 730 | { | 652 | { |
| 731 | struct sysfs_dirent *parent_sd, *sd; | 653 | struct sysfs_dirent *parent_sd, *sd; |
| 732 | int error = 0; | 654 | int error = 0; |
| 733 | 655 | ||
| 734 | BUG_ON(!kobj); | 656 | BUG_ON(!kobj); |
| 735 | 657 | ||
| 736 | if (shadow_parent_sd) | 658 | if (kobj->parent) |
| 737 | parent_sd = shadow_parent_sd; | ||
| 738 | else if (kobj->parent) | ||
| 739 | parent_sd = kobj->parent->sd; | 659 | parent_sd = kobj->parent->sd; |
| 740 | else if (sysfs_mount && sysfs_mount->mnt_sb) | ||
| 741 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; | ||
| 742 | else | 660 | else |
| 743 | return -EFAULT; | 661 | parent_sd = &sysfs_root; |
| 744 | 662 | ||
| 745 | error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); | 663 | error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); |
| 746 | if (!error) | 664 | if (!error) |
| @@ -748,39 +666,20 @@ int sysfs_create_dir(struct kobject *kobj, | |||
| 748 | return error; | 666 | return error; |
| 749 | } | 667 | } |
| 750 | 668 | ||
| 751 | static int sysfs_count_nlink(struct sysfs_dirent *sd) | ||
| 752 | { | ||
| 753 | struct sysfs_dirent *child; | ||
| 754 | int nr = 0; | ||
| 755 | |||
| 756 | for (child = sd->s_children; child; child = child->s_sibling) | ||
| 757 | if (sysfs_type(child) == SYSFS_DIR) | ||
| 758 | nr++; | ||
| 759 | return nr + 2; | ||
| 760 | } | ||
| 761 | |||
| 762 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | 669 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, |
| 763 | struct nameidata *nd) | 670 | struct nameidata *nd) |
| 764 | { | 671 | { |
| 765 | struct dentry *ret = NULL; | 672 | struct dentry *ret = NULL; |
| 766 | struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; | 673 | struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; |
| 767 | struct sysfs_dirent * sd; | 674 | struct sysfs_dirent *sd; |
| 768 | struct bin_attribute *bin_attr; | ||
| 769 | struct inode *inode; | 675 | struct inode *inode; |
| 770 | int found = 0; | ||
| 771 | 676 | ||
| 772 | mutex_lock(&sysfs_mutex); | 677 | mutex_lock(&sysfs_mutex); |
| 773 | 678 | ||
| 774 | for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { | 679 | sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); |
| 775 | if (sysfs_type(sd) && | ||
| 776 | !strcmp(sd->s_name, dentry->d_name.name)) { | ||
| 777 | found = 1; | ||
| 778 | break; | ||
| 779 | } | ||
| 780 | } | ||
| 781 | 680 | ||
| 782 | /* no such entry */ | 681 | /* no such entry */ |
| 783 | if (!found) | 682 | if (!sd) |
| 784 | goto out_unlock; | 683 | goto out_unlock; |
| 785 | 684 | ||
| 786 | /* attach dentry and inode */ | 685 | /* attach dentry and inode */ |
| @@ -790,33 +689,11 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 790 | goto out_unlock; | 689 | goto out_unlock; |
| 791 | } | 690 | } |
| 792 | 691 | ||
| 793 | if (inode->i_state & I_NEW) { | 692 | /* instantiate and hash dentry */ |
| 794 | /* initialize inode according to type */ | 693 | dentry->d_op = &sysfs_dentry_ops; |
| 795 | switch (sysfs_type(sd)) { | 694 | dentry->d_fsdata = sysfs_get(sd); |
| 796 | case SYSFS_DIR: | 695 | d_instantiate(dentry, inode); |
| 797 | inode->i_op = &sysfs_dir_inode_operations; | 696 | d_rehash(dentry); |
| 798 | inode->i_fop = &sysfs_dir_operations; | ||
| 799 | inode->i_nlink = sysfs_count_nlink(sd); | ||
| 800 | break; | ||
| 801 | case SYSFS_KOBJ_ATTR: | ||
| 802 | inode->i_size = PAGE_SIZE; | ||
| 803 | inode->i_fop = &sysfs_file_operations; | ||
| 804 | break; | ||
| 805 | case SYSFS_KOBJ_BIN_ATTR: | ||
| 806 | bin_attr = sd->s_elem.bin_attr.bin_attr; | ||
| 807 | inode->i_size = bin_attr->size; | ||
| 808 | inode->i_fop = &bin_fops; | ||
| 809 | break; | ||
| 810 | case SYSFS_KOBJ_LINK: | ||
| 811 | inode->i_op = &sysfs_symlink_inode_operations; | ||
| 812 | break; | ||
| 813 | default: | ||
| 814 | BUG(); | ||
| 815 | } | ||
| 816 | } | ||
| 817 | |||
| 818 | sysfs_instantiate(dentry, inode); | ||
| 819 | sysfs_attach_dentry(sd, dentry); | ||
| 820 | 697 | ||
| 821 | out_unlock: | 698 | out_unlock: |
| 822 | mutex_unlock(&sysfs_mutex); | 699 | mutex_unlock(&sysfs_mutex); |
| @@ -833,7 +710,6 @@ static void remove_dir(struct sysfs_dirent *sd) | |||
| 833 | struct sysfs_addrm_cxt acxt; | 710 | struct sysfs_addrm_cxt acxt; |
| 834 | 711 | ||
| 835 | sysfs_addrm_start(&acxt, sd->s_parent); | 712 | sysfs_addrm_start(&acxt, sd->s_parent); |
| 836 | sysfs_unlink_sibling(sd); | ||
| 837 | sysfs_remove_one(&acxt, sd); | 713 | sysfs_remove_one(&acxt, sd); |
| 838 | sysfs_addrm_finish(&acxt); | 714 | sysfs_addrm_finish(&acxt); |
| 839 | } | 715 | } |
| @@ -854,15 +730,13 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) | |||
| 854 | 730 | ||
| 855 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); | 731 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); |
| 856 | sysfs_addrm_start(&acxt, dir_sd); | 732 | sysfs_addrm_start(&acxt, dir_sd); |
| 857 | pos = &dir_sd->s_children; | 733 | pos = &dir_sd->s_dir.children; |
| 858 | while (*pos) { | 734 | while (*pos) { |
| 859 | struct sysfs_dirent *sd = *pos; | 735 | struct sysfs_dirent *sd = *pos; |
| 860 | 736 | ||
| 861 | if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) { | 737 | if (sysfs_type(sd) != SYSFS_DIR) |
| 862 | *pos = sd->s_sibling; | ||
| 863 | sd->s_sibling = NULL; | ||
| 864 | sysfs_remove_one(&acxt, sd); | 738 | sysfs_remove_one(&acxt, sd); |
| 865 | } else | 739 | else |
| 866 | pos = &(*pos)->s_sibling; | 740 | pos = &(*pos)->s_sibling; |
| 867 | } | 741 | } |
| 868 | sysfs_addrm_finish(&acxt); | 742 | sysfs_addrm_finish(&acxt); |
| @@ -890,90 +764,68 @@ void sysfs_remove_dir(struct kobject * kobj) | |||
| 890 | __sysfs_remove_dir(sd); | 764 | __sysfs_remove_dir(sd); |
| 891 | } | 765 | } |
| 892 | 766 | ||
| 893 | int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, | 767 | int sysfs_rename_dir(struct kobject * kobj, const char *new_name) |
| 894 | const char *new_name) | ||
| 895 | { | 768 | { |
| 896 | struct sysfs_dirent *sd = kobj->sd; | 769 | struct sysfs_dirent *sd = kobj->sd; |
| 897 | struct dentry *new_parent = NULL; | 770 | struct dentry *parent = NULL; |
| 898 | struct dentry *old_dentry = NULL, *new_dentry = NULL; | 771 | struct dentry *old_dentry = NULL, *new_dentry = NULL; |
| 899 | const char *dup_name = NULL; | 772 | const char *dup_name = NULL; |
| 900 | int error; | 773 | int error; |
| 901 | 774 | ||
| 902 | /* get dentries */ | 775 | mutex_lock(&sysfs_rename_mutex); |
| 776 | |||
| 777 | error = 0; | ||
| 778 | if (strcmp(sd->s_name, new_name) == 0) | ||
| 779 | goto out; /* nothing to rename */ | ||
| 780 | |||
| 781 | /* get the original dentry */ | ||
| 903 | old_dentry = sysfs_get_dentry(sd); | 782 | old_dentry = sysfs_get_dentry(sd); |
| 904 | if (IS_ERR(old_dentry)) { | 783 | if (IS_ERR(old_dentry)) { |
| 905 | error = PTR_ERR(old_dentry); | 784 | error = PTR_ERR(old_dentry); |
| 906 | goto out_dput; | 785 | goto out; |
| 907 | } | ||
| 908 | |||
| 909 | new_parent = sysfs_get_dentry(new_parent_sd); | ||
| 910 | if (IS_ERR(new_parent)) { | ||
| 911 | error = PTR_ERR(new_parent); | ||
| 912 | goto out_dput; | ||
| 913 | } | 786 | } |
| 914 | 787 | ||
| 915 | /* lock new_parent and get dentry for new name */ | 788 | parent = old_dentry->d_parent; |
| 916 | mutex_lock(&new_parent->d_inode->i_mutex); | ||
| 917 | 789 | ||
| 918 | new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); | 790 | /* lock parent and get dentry for new name */ |
| 919 | if (IS_ERR(new_dentry)) { | 791 | mutex_lock(&parent->d_inode->i_mutex); |
| 920 | error = PTR_ERR(new_dentry); | 792 | mutex_lock(&sysfs_mutex); |
| 921 | goto out_unlock; | ||
| 922 | } | ||
| 923 | 793 | ||
| 924 | /* By allowing two different directories with the same | 794 | error = -EEXIST; |
| 925 | * d_parent we allow this routine to move between different | 795 | if (sysfs_find_dirent(sd->s_parent, new_name)) |
| 926 | * shadows of the same directory | ||
| 927 | */ | ||
| 928 | error = -EINVAL; | ||
| 929 | if (old_dentry->d_parent->d_inode != new_parent->d_inode || | ||
| 930 | new_dentry->d_parent->d_inode != new_parent->d_inode || | ||
| 931 | old_dentry == new_dentry) | ||
| 932 | goto out_unlock; | 796 | goto out_unlock; |
| 933 | 797 | ||
| 934 | error = -EEXIST; | 798 | error = -ENOMEM; |
| 935 | if (new_dentry->d_inode) | 799 | new_dentry = d_alloc_name(parent, new_name); |
| 800 | if (!new_dentry) | ||
| 936 | goto out_unlock; | 801 | goto out_unlock; |
| 937 | 802 | ||
| 938 | /* rename kobject and sysfs_dirent */ | 803 | /* rename kobject and sysfs_dirent */ |
| 939 | error = -ENOMEM; | 804 | error = -ENOMEM; |
| 940 | new_name = dup_name = kstrdup(new_name, GFP_KERNEL); | 805 | new_name = dup_name = kstrdup(new_name, GFP_KERNEL); |
| 941 | if (!new_name) | 806 | if (!new_name) |
| 942 | goto out_drop; | 807 | goto out_unlock; |
| 943 | 808 | ||
| 944 | error = kobject_set_name(kobj, "%s", new_name); | 809 | error = kobject_set_name(kobj, "%s", new_name); |
| 945 | if (error) | 810 | if (error) |
| 946 | goto out_drop; | 811 | goto out_unlock; |
| 947 | |||
| 948 | mutex_lock(&sysfs_mutex); | ||
| 949 | 812 | ||
| 950 | dup_name = sd->s_name; | 813 | dup_name = sd->s_name; |
| 951 | sd->s_name = new_name; | 814 | sd->s_name = new_name; |
| 952 | 815 | ||
| 953 | /* move under the new parent */ | 816 | /* rename */ |
| 954 | d_add(new_dentry, NULL); | 817 | d_add(new_dentry, NULL); |
| 955 | d_move(sd->s_dentry, new_dentry); | 818 | d_move(old_dentry, new_dentry); |
| 956 | |||
| 957 | sysfs_unlink_sibling(sd); | ||
| 958 | sysfs_get(new_parent_sd); | ||
| 959 | sysfs_put(sd->s_parent); | ||
| 960 | sd->s_parent = new_parent_sd; | ||
| 961 | sysfs_link_sibling(sd); | ||
| 962 | |||
| 963 | mutex_unlock(&sysfs_mutex); | ||
| 964 | 819 | ||
| 965 | error = 0; | 820 | error = 0; |
| 966 | goto out_unlock; | ||
| 967 | |||
| 968 | out_drop: | ||
| 969 | d_drop(new_dentry); | ||
| 970 | out_unlock: | 821 | out_unlock: |
| 971 | mutex_unlock(&new_parent->d_inode->i_mutex); | 822 | mutex_unlock(&sysfs_mutex); |
| 972 | out_dput: | 823 | mutex_unlock(&parent->d_inode->i_mutex); |
| 973 | kfree(dup_name); | 824 | kfree(dup_name); |
| 974 | dput(new_parent); | ||
| 975 | dput(old_dentry); | 825 | dput(old_dentry); |
| 976 | dput(new_dentry); | 826 | dput(new_dentry); |
| 827 | out: | ||
| 828 | mutex_unlock(&sysfs_rename_mutex); | ||
| 977 | return error; | 829 | return error; |
| 978 | } | 830 | } |
| 979 | 831 | ||
| @@ -985,96 +837,69 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) | |||
| 985 | struct dentry *old_dentry = NULL, *new_dentry = NULL; | 837 | struct dentry *old_dentry = NULL, *new_dentry = NULL; |
| 986 | int error; | 838 | int error; |
| 987 | 839 | ||
| 840 | mutex_lock(&sysfs_rename_mutex); | ||
| 988 | BUG_ON(!sd->s_parent); | 841 | BUG_ON(!sd->s_parent); |
| 989 | new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; | 842 | new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; |
| 990 | 843 | ||
| 844 | error = 0; | ||
| 845 | if (sd->s_parent == new_parent_sd) | ||
| 846 | goto out; /* nothing to move */ | ||
| 847 | |||
| 991 | /* get dentries */ | 848 | /* get dentries */ |
| 992 | old_dentry = sysfs_get_dentry(sd); | 849 | old_dentry = sysfs_get_dentry(sd); |
| 993 | if (IS_ERR(old_dentry)) { | 850 | if (IS_ERR(old_dentry)) { |
| 994 | error = PTR_ERR(old_dentry); | 851 | error = PTR_ERR(old_dentry); |
| 995 | goto out_dput; | 852 | goto out; |
| 996 | } | 853 | } |
| 997 | old_parent = sd->s_parent->s_dentry; | 854 | old_parent = old_dentry->d_parent; |
| 998 | 855 | ||
| 999 | new_parent = sysfs_get_dentry(new_parent_sd); | 856 | new_parent = sysfs_get_dentry(new_parent_sd); |
| 1000 | if (IS_ERR(new_parent)) { | 857 | if (IS_ERR(new_parent)) { |
| 1001 | error = PTR_ERR(new_parent); | 858 | error = PTR_ERR(new_parent); |
| 1002 | goto out_dput; | 859 | goto out; |
| 1003 | } | 860 | } |
| 1004 | 861 | ||
| 1005 | if (old_parent->d_inode == new_parent->d_inode) { | ||
| 1006 | error = 0; | ||
| 1007 | goto out_dput; /* nothing to move */ | ||
| 1008 | } | ||
| 1009 | again: | 862 | again: |
| 1010 | mutex_lock(&old_parent->d_inode->i_mutex); | 863 | mutex_lock(&old_parent->d_inode->i_mutex); |
| 1011 | if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { | 864 | if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { |
| 1012 | mutex_unlock(&old_parent->d_inode->i_mutex); | 865 | mutex_unlock(&old_parent->d_inode->i_mutex); |
| 1013 | goto again; | 866 | goto again; |
| 1014 | } | 867 | } |
| 868 | mutex_lock(&sysfs_mutex); | ||
| 1015 | 869 | ||
| 1016 | new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name)); | 870 | error = -EEXIST; |
| 1017 | if (IS_ERR(new_dentry)) { | 871 | if (sysfs_find_dirent(new_parent_sd, sd->s_name)) |
| 1018 | error = PTR_ERR(new_dentry); | ||
| 1019 | goto out_unlock; | 872 | goto out_unlock; |
| 1020 | } else | 873 | |
| 1021 | error = 0; | 874 | error = -ENOMEM; |
| 875 | new_dentry = d_alloc_name(new_parent, sd->s_name); | ||
| 876 | if (!new_dentry) | ||
| 877 | goto out_unlock; | ||
| 878 | |||
| 879 | error = 0; | ||
| 1022 | d_add(new_dentry, NULL); | 880 | d_add(new_dentry, NULL); |
| 1023 | d_move(sd->s_dentry, new_dentry); | 881 | d_move(old_dentry, new_dentry); |
| 1024 | dput(new_dentry); | 882 | dput(new_dentry); |
| 1025 | 883 | ||
| 1026 | /* Remove from old parent's list and insert into new parent's list. */ | 884 | /* Remove from old parent's list and insert into new parent's list. */ |
| 1027 | mutex_lock(&sysfs_mutex); | ||
| 1028 | |||
| 1029 | sysfs_unlink_sibling(sd); | 885 | sysfs_unlink_sibling(sd); |
| 1030 | sysfs_get(new_parent_sd); | 886 | sysfs_get(new_parent_sd); |
| 1031 | sysfs_put(sd->s_parent); | 887 | sysfs_put(sd->s_parent); |
| 1032 | sd->s_parent = new_parent_sd; | 888 | sd->s_parent = new_parent_sd; |
| 1033 | sysfs_link_sibling(sd); | 889 | sysfs_link_sibling(sd); |
| 1034 | 890 | ||
| 1035 | mutex_unlock(&sysfs_mutex); | ||
| 1036 | |||
| 1037 | out_unlock: | 891 | out_unlock: |
| 892 | mutex_unlock(&sysfs_mutex); | ||
| 1038 | mutex_unlock(&new_parent->d_inode->i_mutex); | 893 | mutex_unlock(&new_parent->d_inode->i_mutex); |
| 1039 | mutex_unlock(&old_parent->d_inode->i_mutex); | 894 | mutex_unlock(&old_parent->d_inode->i_mutex); |
| 1040 | out_dput: | 895 | out: |
| 1041 | dput(new_parent); | 896 | dput(new_parent); |
| 1042 | dput(old_dentry); | 897 | dput(old_dentry); |
| 1043 | dput(new_dentry); | 898 | dput(new_dentry); |
| 899 | mutex_unlock(&sysfs_rename_mutex); | ||
| 1044 | return error; | 900 | return error; |
| 1045 | } | 901 | } |
| 1046 | 902 | ||
| 1047 | static int sysfs_dir_open(struct inode *inode, struct file *file) | ||
| 1048 | { | ||
| 1049 | struct dentry * dentry = file->f_path.dentry; | ||
| 1050 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | ||
| 1051 | struct sysfs_dirent * sd; | ||
| 1052 | |||
| 1053 | sd = sysfs_new_dirent("_DIR_", 0, 0); | ||
| 1054 | if (sd) { | ||
| 1055 | mutex_lock(&sysfs_mutex); | ||
| 1056 | sd->s_parent = sysfs_get(parent_sd); | ||
| 1057 | sysfs_link_sibling(sd); | ||
| 1058 | mutex_unlock(&sysfs_mutex); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | file->private_data = sd; | ||
| 1062 | return sd ? 0 : -ENOMEM; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | static int sysfs_dir_close(struct inode *inode, struct file *file) | ||
| 1066 | { | ||
| 1067 | struct sysfs_dirent * cursor = file->private_data; | ||
| 1068 | |||
| 1069 | mutex_lock(&sysfs_mutex); | ||
| 1070 | sysfs_unlink_sibling(cursor); | ||
| 1071 | mutex_unlock(&sysfs_mutex); | ||
| 1072 | |||
| 1073 | release_sysfs_dirent(cursor); | ||
| 1074 | |||
| 1075 | return 0; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | /* Relationship between s_mode and the DT_xxx types */ | 903 | /* Relationship between s_mode and the DT_xxx types */ |
| 1079 | static inline unsigned char dt_type(struct sysfs_dirent *sd) | 904 | static inline unsigned char dt_type(struct sysfs_dirent *sd) |
| 1080 | { | 905 | { |
| @@ -1085,232 +910,51 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 1085 | { | 910 | { |
| 1086 | struct dentry *dentry = filp->f_path.dentry; | 911 | struct dentry *dentry = filp->f_path.dentry; |
| 1087 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 912 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
| 1088 | struct sysfs_dirent *cursor = filp->private_data; | 913 | struct sysfs_dirent *pos; |
| 1089 | struct sysfs_dirent **pos; | ||
| 1090 | ino_t ino; | 914 | ino_t ino; |
| 1091 | int i = filp->f_pos; | ||
| 1092 | 915 | ||
| 1093 | switch (i) { | 916 | if (filp->f_pos == 0) { |
| 1094 | case 0: | 917 | ino = parent_sd->s_ino; |
| 1095 | ino = parent_sd->s_ino; | 918 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) |
| 1096 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | ||
| 1097 | break; | ||
| 1098 | filp->f_pos++; | 919 | filp->f_pos++; |
| 1099 | i++; | 920 | } |
| 1100 | /* fallthrough */ | 921 | if (filp->f_pos == 1) { |
| 1101 | case 1: | 922 | if (parent_sd->s_parent) |
| 1102 | if (parent_sd->s_parent) | 923 | ino = parent_sd->s_parent->s_ino; |
| 1103 | ino = parent_sd->s_parent->s_ino; | 924 | else |
| 1104 | else | 925 | ino = parent_sd->s_ino; |
| 1105 | ino = parent_sd->s_ino; | 926 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) |
| 1106 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | ||
| 1107 | break; | ||
| 1108 | filp->f_pos++; | 927 | filp->f_pos++; |
| 1109 | i++; | 928 | } |
| 1110 | /* fallthrough */ | 929 | if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { |
| 1111 | default: | 930 | mutex_lock(&sysfs_mutex); |
| 1112 | mutex_lock(&sysfs_mutex); | ||
| 1113 | |||
| 1114 | pos = &parent_sd->s_children; | ||
| 1115 | while (*pos != cursor) | ||
| 1116 | pos = &(*pos)->s_sibling; | ||
| 1117 | |||
| 1118 | /* unlink cursor */ | ||
| 1119 | *pos = cursor->s_sibling; | ||
| 1120 | |||
| 1121 | if (filp->f_pos == 2) | ||
| 1122 | pos = &parent_sd->s_children; | ||
| 1123 | |||
| 1124 | for ( ; *pos; pos = &(*pos)->s_sibling) { | ||
| 1125 | struct sysfs_dirent *next = *pos; | ||
| 1126 | const char * name; | ||
| 1127 | int len; | ||
| 1128 | |||
| 1129 | if (!sysfs_type(next)) | ||
| 1130 | continue; | ||
| 1131 | |||
| 1132 | name = next->s_name; | ||
| 1133 | len = strlen(name); | ||
| 1134 | ino = next->s_ino; | ||
| 1135 | |||
| 1136 | if (filldir(dirent, name, len, filp->f_pos, ino, | ||
| 1137 | dt_type(next)) < 0) | ||
| 1138 | break; | ||
| 1139 | 931 | ||
| 1140 | filp->f_pos++; | 932 | /* Skip the dentries we have already reported */ |
| 1141 | } | 933 | pos = parent_sd->s_dir.children; |
| 934 | while (pos && (filp->f_pos > pos->s_ino)) | ||
| 935 | pos = pos->s_sibling; | ||
| 1142 | 936 | ||
| 1143 | /* put cursor back in */ | 937 | for ( ; pos; pos = pos->s_sibling) { |
| 1144 | cursor->s_sibling = *pos; | 938 | const char * name; |
| 1145 | *pos = cursor; | 939 | int len; |
| 1146 | 940 | ||
| 1147 | mutex_unlock(&sysfs_mutex); | 941 | name = pos->s_name; |
| 1148 | } | 942 | len = strlen(name); |
| 1149 | return 0; | 943 | filp->f_pos = ino = pos->s_ino; |
| 1150 | } | ||
| 1151 | |||
| 1152 | static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | ||
| 1153 | { | ||
| 1154 | struct dentry * dentry = file->f_path.dentry; | ||
| 1155 | 944 | ||
| 1156 | switch (origin) { | 945 | if (filldir(dirent, name, len, filp->f_pos, ino, |
| 1157 | case 1: | 946 | dt_type(pos)) < 0) |
| 1158 | offset += file->f_pos; | ||
| 1159 | case 0: | ||
| 1160 | if (offset >= 0) | ||
| 1161 | break; | 947 | break; |
| 1162 | default: | ||
| 1163 | return -EINVAL; | ||
| 1164 | } | ||
| 1165 | if (offset != file->f_pos) { | ||
| 1166 | mutex_lock(&sysfs_mutex); | ||
| 1167 | |||
| 1168 | file->f_pos = offset; | ||
| 1169 | if (file->f_pos >= 2) { | ||
| 1170 | struct sysfs_dirent *sd = dentry->d_fsdata; | ||
| 1171 | struct sysfs_dirent *cursor = file->private_data; | ||
| 1172 | struct sysfs_dirent **pos; | ||
| 1173 | loff_t n = file->f_pos - 2; | ||
| 1174 | |||
| 1175 | sysfs_unlink_sibling(cursor); | ||
| 1176 | |||
| 1177 | pos = &sd->s_children; | ||
| 1178 | while (n && *pos) { | ||
| 1179 | struct sysfs_dirent *next = *pos; | ||
| 1180 | if (sysfs_type(next)) | ||
| 1181 | n--; | ||
| 1182 | pos = &(*pos)->s_sibling; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | cursor->s_sibling = *pos; | ||
| 1186 | *pos = cursor; | ||
| 1187 | } | 948 | } |
| 1188 | 949 | if (!pos) | |
| 950 | filp->f_pos = INT_MAX; | ||
| 1189 | mutex_unlock(&sysfs_mutex); | 951 | mutex_unlock(&sysfs_mutex); |
| 1190 | } | 952 | } |
| 1191 | |||
| 1192 | return offset; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | |||
| 1196 | /** | ||
| 1197 | * sysfs_make_shadowed_dir - Setup so a directory can be shadowed | ||
| 1198 | * @kobj: object we're creating shadow of. | ||
| 1199 | */ | ||
| 1200 | |||
| 1201 | int sysfs_make_shadowed_dir(struct kobject *kobj, | ||
| 1202 | void * (*follow_link)(struct dentry *, struct nameidata *)) | ||
| 1203 | { | ||
| 1204 | struct dentry *dentry; | ||
| 1205 | struct inode *inode; | ||
| 1206 | struct inode_operations *i_op; | ||
| 1207 | |||
| 1208 | /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */ | ||
| 1209 | dentry = sysfs_get_dentry(kobj->sd); | ||
| 1210 | if (IS_ERR(dentry)) | ||
| 1211 | return PTR_ERR(dentry); | ||
| 1212 | |||
| 1213 | inode = dentry->d_inode; | ||
| 1214 | if (inode->i_op != &sysfs_dir_inode_operations) { | ||
| 1215 | dput(dentry); | ||
| 1216 | return -EINVAL; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); | ||
| 1220 | if (!i_op) | ||
| 1221 | return -ENOMEM; | ||
| 1222 | |||
| 1223 | memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); | ||
| 1224 | i_op->follow_link = follow_link; | ||
| 1225 | |||
| 1226 | /* Locking of inode->i_op? | ||
| 1227 | * Since setting i_op is a single word write and they | ||
| 1228 | * are atomic we should be ok here. | ||
| 1229 | */ | ||
| 1230 | inode->i_op = i_op; | ||
| 1231 | return 0; | 953 | return 0; |
| 1232 | } | 954 | } |
| 1233 | 955 | ||
| 1234 | /** | ||
| 1235 | * sysfs_create_shadow_dir - create a shadow directory for an object. | ||
| 1236 | * @kobj: object we're creating directory for. | ||
| 1237 | * | ||
| 1238 | * sysfs_make_shadowed_dir must already have been called on this | ||
| 1239 | * directory. | ||
| 1240 | */ | ||
| 1241 | |||
| 1242 | struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) | ||
| 1243 | { | ||
| 1244 | struct sysfs_dirent *parent_sd = kobj->sd->s_parent; | ||
| 1245 | struct dentry *dir, *parent, *shadow; | ||
| 1246 | struct inode *inode; | ||
| 1247 | struct sysfs_dirent *sd; | ||
| 1248 | struct sysfs_addrm_cxt acxt; | ||
| 1249 | |||
| 1250 | dir = sysfs_get_dentry(kobj->sd); | ||
| 1251 | if (IS_ERR(dir)) { | ||
| 1252 | sd = (void *)dir; | ||
| 1253 | goto out; | ||
| 1254 | } | ||
| 1255 | parent = dir->d_parent; | ||
| 1256 | |||
| 1257 | inode = dir->d_inode; | ||
| 1258 | sd = ERR_PTR(-EINVAL); | ||
| 1259 | if (!sysfs_is_shadowed_inode(inode)) | ||
| 1260 | goto out_dput; | ||
| 1261 | |||
| 1262 | shadow = d_alloc(parent, &dir->d_name); | ||
| 1263 | if (!shadow) | ||
| 1264 | goto nomem; | ||
| 1265 | |||
| 1266 | sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); | ||
| 1267 | if (!sd) | ||
| 1268 | goto nomem; | ||
| 1269 | sd->s_elem.dir.kobj = kobj; | ||
| 1270 | |||
| 1271 | sysfs_addrm_start(&acxt, parent_sd); | ||
| 1272 | |||
| 1273 | /* add but don't link into children list */ | ||
| 1274 | sysfs_add_one(&acxt, sd); | ||
| 1275 | |||
| 1276 | /* attach and instantiate dentry */ | ||
| 1277 | sysfs_attach_dentry(sd, shadow); | ||
| 1278 | d_instantiate(shadow, igrab(inode)); | ||
| 1279 | inc_nlink(inode); /* tj: synchronization? */ | ||
| 1280 | |||
| 1281 | sysfs_addrm_finish(&acxt); | ||
| 1282 | |||
| 1283 | dget(shadow); /* Extra count - pin the dentry in core */ | ||
| 1284 | |||
| 1285 | goto out_dput; | ||
| 1286 | |||
| 1287 | nomem: | ||
| 1288 | dput(shadow); | ||
| 1289 | sd = ERR_PTR(-ENOMEM); | ||
| 1290 | out_dput: | ||
| 1291 | dput(dir); | ||
| 1292 | out: | ||
| 1293 | return sd; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | /** | ||
| 1297 | * sysfs_remove_shadow_dir - remove an object's directory. | ||
| 1298 | * @shadow_sd: sysfs_dirent of shadow directory | ||
| 1299 | * | ||
| 1300 | * The only thing special about this is that we remove any files in | ||
| 1301 | * the directory before we remove the directory, and we've inlined | ||
| 1302 | * what used to be sysfs_rmdir() below, instead of calling separately. | ||
| 1303 | */ | ||
| 1304 | |||
| 1305 | void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) | ||
| 1306 | { | ||
| 1307 | __sysfs_remove_dir(shadow_sd); | ||
| 1308 | } | ||
| 1309 | 956 | ||
| 1310 | const struct file_operations sysfs_dir_operations = { | 957 | const struct file_operations sysfs_dir_operations = { |
| 1311 | .open = sysfs_dir_open, | ||
| 1312 | .release = sysfs_dir_close, | ||
| 1313 | .llseek = sysfs_dir_lseek, | ||
| 1314 | .read = generic_read_dir, | 958 | .read = generic_read_dir, |
| 1315 | .readdir = sysfs_readdir, | 959 | .readdir = sysfs_readdir, |
| 1316 | }; | 960 | }; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 3e1cc062a740..d3be1e7fb48b 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -1,15 +1,22 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * file.c - operations for regular (text) files. | 2 | * fs/sysfs/file.c - sysfs regular (text) file implementation |
| 3 | * | ||
| 4 | * Copyright (c) 2001-3 Patrick Mochel | ||
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 9 | * | ||
| 10 | * Please see Documentation/filesystems/sysfs.txt for more information. | ||
| 3 | */ | 11 | */ |
| 4 | 12 | ||
| 5 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 6 | #include <linux/fsnotify.h> | ||
| 7 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
| 8 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
| 9 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
| 10 | #include <linux/list.h> | 17 | #include <linux/list.h> |
| 18 | #include <linux/mutex.h> | ||
| 11 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
| 12 | #include <asm/semaphore.h> | ||
| 13 | 20 | ||
| 14 | #include "sysfs.h" | 21 | #include "sysfs.h" |
| 15 | 22 | ||
| @@ -50,14 +57,33 @@ static struct sysfs_ops subsys_sysfs_ops = { | |||
| 50 | .store = subsys_attr_store, | 57 | .store = subsys_attr_store, |
| 51 | }; | 58 | }; |
| 52 | 59 | ||
| 60 | /* | ||
| 61 | * There's one sysfs_buffer for each open file and one | ||
| 62 | * sysfs_open_dirent for each sysfs_dirent with one or more open | ||
| 63 | * files. | ||
| 64 | * | ||
| 65 | * filp->private_data points to sysfs_buffer and | ||
| 66 | * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open | ||
| 67 | * is protected by sysfs_open_dirent_lock. | ||
| 68 | */ | ||
| 69 | static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED; | ||
| 70 | |||
| 71 | struct sysfs_open_dirent { | ||
| 72 | atomic_t refcnt; | ||
| 73 | atomic_t event; | ||
| 74 | wait_queue_head_t poll; | ||
| 75 | struct list_head buffers; /* goes through sysfs_buffer.list */ | ||
| 76 | }; | ||
| 77 | |||
| 53 | struct sysfs_buffer { | 78 | struct sysfs_buffer { |
| 54 | size_t count; | 79 | size_t count; |
| 55 | loff_t pos; | 80 | loff_t pos; |
| 56 | char * page; | 81 | char * page; |
| 57 | struct sysfs_ops * ops; | 82 | struct sysfs_ops * ops; |
| 58 | struct semaphore sem; | 83 | struct mutex mutex; |
| 59 | int needs_read_fill; | 84 | int needs_read_fill; |
| 60 | int event; | 85 | int event; |
| 86 | struct list_head list; | ||
| 61 | }; | 87 | }; |
| 62 | 88 | ||
| 63 | /** | 89 | /** |
| @@ -74,7 +100,7 @@ struct sysfs_buffer { | |||
| 74 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) | 100 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) |
| 75 | { | 101 | { |
| 76 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 102 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 77 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 103 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 78 | struct sysfs_ops * ops = buffer->ops; | 104 | struct sysfs_ops * ops = buffer->ops; |
| 79 | int ret = 0; | 105 | int ret = 0; |
| 80 | ssize_t count; | 106 | ssize_t count; |
| @@ -88,8 +114,8 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
| 88 | if (!sysfs_get_active_two(attr_sd)) | 114 | if (!sysfs_get_active_two(attr_sd)) |
| 89 | return -ENODEV; | 115 | return -ENODEV; |
| 90 | 116 | ||
| 91 | buffer->event = atomic_read(&attr_sd->s_event); | 117 | buffer->event = atomic_read(&attr_sd->s_attr.open->event); |
| 92 | count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page); | 118 | count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page); |
| 93 | 119 | ||
| 94 | sysfs_put_active_two(attr_sd); | 120 | sysfs_put_active_two(attr_sd); |
| 95 | 121 | ||
| @@ -128,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 128 | struct sysfs_buffer * buffer = file->private_data; | 154 | struct sysfs_buffer * buffer = file->private_data; |
| 129 | ssize_t retval = 0; | 155 | ssize_t retval = 0; |
| 130 | 156 | ||
| 131 | down(&buffer->sem); | 157 | mutex_lock(&buffer->mutex); |
| 132 | if (buffer->needs_read_fill) { | 158 | if (buffer->needs_read_fill) { |
| 133 | retval = fill_read_buffer(file->f_path.dentry,buffer); | 159 | retval = fill_read_buffer(file->f_path.dentry,buffer); |
| 134 | if (retval) | 160 | if (retval) |
| @@ -139,7 +165,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 139 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, | 165 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, |
| 140 | buffer->count); | 166 | buffer->count); |
| 141 | out: | 167 | out: |
| 142 | up(&buffer->sem); | 168 | mutex_unlock(&buffer->mutex); |
| 143 | return retval; | 169 | return retval; |
| 144 | } | 170 | } |
| 145 | 171 | ||
| @@ -189,7 +215,7 @@ static int | |||
| 189 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) | 215 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) |
| 190 | { | 216 | { |
| 191 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; | 217 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 192 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 218 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 193 | struct sysfs_ops * ops = buffer->ops; | 219 | struct sysfs_ops * ops = buffer->ops; |
| 194 | int rc; | 220 | int rc; |
| 195 | 221 | ||
| @@ -197,7 +223,7 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t | |||
| 197 | if (!sysfs_get_active_two(attr_sd)) | 223 | if (!sysfs_get_active_two(attr_sd)) |
| 198 | return -ENODEV; | 224 | return -ENODEV; |
| 199 | 225 | ||
| 200 | rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); | 226 | rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count); |
| 201 | 227 | ||
| 202 | sysfs_put_active_two(attr_sd); | 228 | sysfs_put_active_two(attr_sd); |
| 203 | 229 | ||
| @@ -228,20 +254,102 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t | |||
| 228 | struct sysfs_buffer * buffer = file->private_data; | 254 | struct sysfs_buffer * buffer = file->private_data; |
| 229 | ssize_t len; | 255 | ssize_t len; |
| 230 | 256 | ||
| 231 | down(&buffer->sem); | 257 | mutex_lock(&buffer->mutex); |
| 232 | len = fill_write_buffer(buffer, buf, count); | 258 | len = fill_write_buffer(buffer, buf, count); |
| 233 | if (len > 0) | 259 | if (len > 0) |
| 234 | len = flush_write_buffer(file->f_path.dentry, buffer, len); | 260 | len = flush_write_buffer(file->f_path.dentry, buffer, len); |
| 235 | if (len > 0) | 261 | if (len > 0) |
| 236 | *ppos += len; | 262 | *ppos += len; |
| 237 | up(&buffer->sem); | 263 | mutex_unlock(&buffer->mutex); |
| 238 | return len; | 264 | return len; |
| 239 | } | 265 | } |
| 240 | 266 | ||
| 267 | /** | ||
| 268 | * sysfs_get_open_dirent - get or create sysfs_open_dirent | ||
| 269 | * @sd: target sysfs_dirent | ||
| 270 | * @buffer: sysfs_buffer for this instance of open | ||
| 271 | * | ||
| 272 | * If @sd->s_attr.open exists, increment its reference count; | ||
| 273 | * otherwise, create one. @buffer is chained to the buffers | ||
| 274 | * list. | ||
| 275 | * | ||
| 276 | * LOCKING: | ||
| 277 | * Kernel thread context (may sleep). | ||
| 278 | * | ||
| 279 | * RETURNS: | ||
| 280 | * 0 on success, -errno on failure. | ||
| 281 | */ | ||
| 282 | static int sysfs_get_open_dirent(struct sysfs_dirent *sd, | ||
| 283 | struct sysfs_buffer *buffer) | ||
| 284 | { | ||
| 285 | struct sysfs_open_dirent *od, *new_od = NULL; | ||
| 286 | |||
| 287 | retry: | ||
| 288 | spin_lock(&sysfs_open_dirent_lock); | ||
| 289 | |||
| 290 | if (!sd->s_attr.open && new_od) { | ||
| 291 | sd->s_attr.open = new_od; | ||
| 292 | new_od = NULL; | ||
| 293 | } | ||
| 294 | |||
| 295 | od = sd->s_attr.open; | ||
| 296 | if (od) { | ||
| 297 | atomic_inc(&od->refcnt); | ||
| 298 | list_add_tail(&buffer->list, &od->buffers); | ||
| 299 | } | ||
| 300 | |||
| 301 | spin_unlock(&sysfs_open_dirent_lock); | ||
| 302 | |||
| 303 | if (od) { | ||
| 304 | kfree(new_od); | ||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* not there, initialize a new one and retry */ | ||
| 309 | new_od = kmalloc(sizeof(*new_od), GFP_KERNEL); | ||
| 310 | if (!new_od) | ||
| 311 | return -ENOMEM; | ||
| 312 | |||
| 313 | atomic_set(&new_od->refcnt, 0); | ||
| 314 | atomic_set(&new_od->event, 1); | ||
| 315 | init_waitqueue_head(&new_od->poll); | ||
| 316 | INIT_LIST_HEAD(&new_od->buffers); | ||
| 317 | goto retry; | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * sysfs_put_open_dirent - put sysfs_open_dirent | ||
| 322 | * @sd: target sysfs_dirent | ||
| 323 | * @buffer: associated sysfs_buffer | ||
| 324 | * | ||
| 325 | * Put @sd->s_attr.open and unlink @buffer from the buffers list. | ||
| 326 | * If reference count reaches zero, disassociate and free it. | ||
| 327 | * | ||
| 328 | * LOCKING: | ||
| 329 | * None. | ||
| 330 | */ | ||
| 331 | static void sysfs_put_open_dirent(struct sysfs_dirent *sd, | ||
| 332 | struct sysfs_buffer *buffer) | ||
| 333 | { | ||
| 334 | struct sysfs_open_dirent *od = sd->s_attr.open; | ||
| 335 | |||
| 336 | spin_lock(&sysfs_open_dirent_lock); | ||
| 337 | |||
| 338 | list_del(&buffer->list); | ||
| 339 | if (atomic_dec_and_test(&od->refcnt)) | ||
| 340 | sd->s_attr.open = NULL; | ||
| 341 | else | ||
| 342 | od = NULL; | ||
| 343 | |||
| 344 | spin_unlock(&sysfs_open_dirent_lock); | ||
| 345 | |||
| 346 | kfree(od); | ||
| 347 | } | ||
| 348 | |||
| 241 | static int sysfs_open_file(struct inode *inode, struct file *file) | 349 | static int sysfs_open_file(struct inode *inode, struct file *file) |
| 242 | { | 350 | { |
| 243 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 351 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 244 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 352 | struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; |
| 245 | struct sysfs_buffer * buffer; | 353 | struct sysfs_buffer * buffer; |
| 246 | struct sysfs_ops * ops = NULL; | 354 | struct sysfs_ops * ops = NULL; |
| 247 | int error; | 355 | int error; |
| @@ -294,33 +402,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
| 294 | if (!buffer) | 402 | if (!buffer) |
| 295 | goto err_out; | 403 | goto err_out; |
| 296 | 404 | ||
| 297 | init_MUTEX(&buffer->sem); | 405 | mutex_init(&buffer->mutex); |
| 298 | buffer->needs_read_fill = 1; | 406 | buffer->needs_read_fill = 1; |
| 299 | buffer->ops = ops; | 407 | buffer->ops = ops; |
| 300 | file->private_data = buffer; | 408 | file->private_data = buffer; |
| 301 | 409 | ||
| 302 | /* open succeeded, put active references and pin attr_sd */ | 410 | /* make sure we have open dirent struct */ |
| 411 | error = sysfs_get_open_dirent(attr_sd, buffer); | ||
| 412 | if (error) | ||
| 413 | goto err_free; | ||
| 414 | |||
| 415 | /* open succeeded, put active references */ | ||
| 303 | sysfs_put_active_two(attr_sd); | 416 | sysfs_put_active_two(attr_sd); |
| 304 | sysfs_get(attr_sd); | ||
| 305 | return 0; | 417 | return 0; |
| 306 | 418 | ||
| 419 | err_free: | ||
| 420 | kfree(buffer); | ||
| 307 | err_out: | 421 | err_out: |
| 308 | sysfs_put_active_two(attr_sd); | 422 | sysfs_put_active_two(attr_sd); |
| 309 | return error; | 423 | return error; |
| 310 | } | 424 | } |
| 311 | 425 | ||
| 312 | static int sysfs_release(struct inode * inode, struct file * filp) | 426 | static int sysfs_release(struct inode *inode, struct file *filp) |
| 313 | { | 427 | { |
| 314 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; | 428 | struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata; |
| 315 | struct sysfs_buffer *buffer = filp->private_data; | 429 | struct sysfs_buffer *buffer = filp->private_data; |
| 316 | 430 | ||
| 317 | sysfs_put(attr_sd); | 431 | sysfs_put_open_dirent(sd, buffer); |
| 432 | |||
| 433 | if (buffer->page) | ||
| 434 | free_page((unsigned long)buffer->page); | ||
| 435 | kfree(buffer); | ||
| 318 | 436 | ||
| 319 | if (buffer) { | ||
| 320 | if (buffer->page) | ||
| 321 | free_page((unsigned long)buffer->page); | ||
| 322 | kfree(buffer); | ||
| 323 | } | ||
| 324 | return 0; | 437 | return 0; |
| 325 | } | 438 | } |
| 326 | 439 | ||
| @@ -335,24 +448,24 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
| 335 | * again will not get new data, or reset the state of 'poll'. | 448 | * again will not get new data, or reset the state of 'poll'. |
| 336 | * Reminder: this only works for attributes which actively support | 449 | * Reminder: this only works for attributes which actively support |
| 337 | * it, and it is not possible to test an attribute from userspace | 450 | * it, and it is not possible to test an attribute from userspace |
| 338 | * to see if it supports poll (Nether 'poll' or 'select' return | 451 | * to see if it supports poll (Neither 'poll' nor 'select' return |
| 339 | * an appropriate error code). When in doubt, set a suitable timeout value. | 452 | * an appropriate error code). When in doubt, set a suitable timeout value. |
| 340 | */ | 453 | */ |
| 341 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | 454 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) |
| 342 | { | 455 | { |
| 343 | struct sysfs_buffer * buffer = filp->private_data; | 456 | struct sysfs_buffer * buffer = filp->private_data; |
| 344 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; | 457 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
| 345 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 458 | struct sysfs_open_dirent *od = attr_sd->s_attr.open; |
| 346 | 459 | ||
| 347 | /* need parent for the kobj, grab both */ | 460 | /* need parent for the kobj, grab both */ |
| 348 | if (!sysfs_get_active_two(attr_sd)) | 461 | if (!sysfs_get_active_two(attr_sd)) |
| 349 | goto trigger; | 462 | goto trigger; |
| 350 | 463 | ||
| 351 | poll_wait(filp, &kobj->poll, wait); | 464 | poll_wait(filp, &od->poll, wait); |
| 352 | 465 | ||
| 353 | sysfs_put_active_two(attr_sd); | 466 | sysfs_put_active_two(attr_sd); |
| 354 | 467 | ||
| 355 | if (buffer->event != atomic_read(&attr_sd->s_event)) | 468 | if (buffer->event != atomic_read(&od->event)) |
| 356 | goto trigger; | 469 | goto trigger; |
| 357 | 470 | ||
| 358 | return 0; | 471 | return 0; |
| @@ -373,8 +486,17 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr) | |||
| 373 | if (sd && attr) | 486 | if (sd && attr) |
| 374 | sd = sysfs_find_dirent(sd, attr); | 487 | sd = sysfs_find_dirent(sd, attr); |
| 375 | if (sd) { | 488 | if (sd) { |
| 376 | atomic_inc(&sd->s_event); | 489 | struct sysfs_open_dirent *od; |
| 377 | wake_up_interruptible(&k->poll); | 490 | |
| 491 | spin_lock(&sysfs_open_dirent_lock); | ||
| 492 | |||
| 493 | od = sd->s_attr.open; | ||
| 494 | if (od) { | ||
| 495 | atomic_inc(&od->event); | ||
| 496 | wake_up_interruptible(&od->poll); | ||
| 497 | } | ||
| 498 | |||
| 499 | spin_unlock(&sysfs_open_dirent_lock); | ||
| 378 | } | 500 | } |
| 379 | 501 | ||
| 380 | mutex_unlock(&sysfs_mutex); | 502 | mutex_unlock(&sysfs_mutex); |
| @@ -397,25 +519,21 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | |||
| 397 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 519 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; |
| 398 | struct sysfs_addrm_cxt acxt; | 520 | struct sysfs_addrm_cxt acxt; |
| 399 | struct sysfs_dirent *sd; | 521 | struct sysfs_dirent *sd; |
| 522 | int rc; | ||
| 400 | 523 | ||
| 401 | sd = sysfs_new_dirent(attr->name, mode, type); | 524 | sd = sysfs_new_dirent(attr->name, mode, type); |
| 402 | if (!sd) | 525 | if (!sd) |
| 403 | return -ENOMEM; | 526 | return -ENOMEM; |
| 404 | sd->s_elem.attr.attr = (void *)attr; | 527 | sd->s_attr.attr = (void *)attr; |
| 405 | 528 | ||
| 406 | sysfs_addrm_start(&acxt, dir_sd); | 529 | sysfs_addrm_start(&acxt, dir_sd); |
| 530 | rc = sysfs_add_one(&acxt, sd); | ||
| 531 | sysfs_addrm_finish(&acxt); | ||
| 407 | 532 | ||
| 408 | if (!sysfs_find_dirent(dir_sd, attr->name)) { | 533 | if (rc) |
| 409 | sysfs_add_one(&acxt, sd); | ||
| 410 | sysfs_link_sibling(sd); | ||
| 411 | } | ||
| 412 | |||
| 413 | if (!sysfs_addrm_finish(&acxt)) { | ||
| 414 | sysfs_put(sd); | 534 | sysfs_put(sd); |
| 415 | return -EEXIST; | ||
| 416 | } | ||
| 417 | 535 | ||
| 418 | return 0; | 536 | return rc; |
| 419 | } | 537 | } |
| 420 | 538 | ||
| 421 | 539 | ||
| @@ -457,42 +575,6 @@ int sysfs_add_file_to_group(struct kobject *kobj, | |||
| 457 | } | 575 | } |
| 458 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | 576 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); |
| 459 | 577 | ||
| 460 | |||
| 461 | /** | ||
| 462 | * sysfs_update_file - update the modified timestamp on an object attribute. | ||
| 463 | * @kobj: object we're acting for. | ||
| 464 | * @attr: attribute descriptor. | ||
| 465 | */ | ||
| 466 | int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) | ||
| 467 | { | ||
| 468 | struct sysfs_dirent *victim_sd = NULL; | ||
| 469 | struct dentry *victim = NULL; | ||
| 470 | int rc; | ||
| 471 | |||
| 472 | rc = -ENOENT; | ||
| 473 | victim_sd = sysfs_get_dirent(kobj->sd, attr->name); | ||
| 474 | if (!victim_sd) | ||
| 475 | goto out; | ||
| 476 | |||
| 477 | victim = sysfs_get_dentry(victim_sd); | ||
| 478 | if (IS_ERR(victim)) { | ||
| 479 | rc = PTR_ERR(victim); | ||
| 480 | victim = NULL; | ||
| 481 | goto out; | ||
| 482 | } | ||
| 483 | |||
| 484 | mutex_lock(&victim->d_inode->i_mutex); | ||
| 485 | victim->d_inode->i_mtime = CURRENT_TIME; | ||
| 486 | fsnotify_modify(victim); | ||
| 487 | mutex_unlock(&victim->d_inode->i_mutex); | ||
| 488 | rc = 0; | ||
| 489 | out: | ||
| 490 | dput(victim); | ||
| 491 | sysfs_put(victim_sd); | ||
| 492 | return rc; | ||
| 493 | } | ||
| 494 | |||
| 495 | |||
| 496 | /** | 578 | /** |
| 497 | * sysfs_chmod_file - update the modified mode value on an object attribute. | 579 | * sysfs_chmod_file - update the modified mode value on an object attribute. |
| 498 | * @kobj: object we're acting for. | 580 | * @kobj: object we're acting for. |
| @@ -513,7 +595,9 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | |||
| 513 | if (!victim_sd) | 595 | if (!victim_sd) |
| 514 | goto out; | 596 | goto out; |
| 515 | 597 | ||
| 598 | mutex_lock(&sysfs_rename_mutex); | ||
| 516 | victim = sysfs_get_dentry(victim_sd); | 599 | victim = sysfs_get_dentry(victim_sd); |
| 600 | mutex_unlock(&sysfs_rename_mutex); | ||
| 517 | if (IS_ERR(victim)) { | 601 | if (IS_ERR(victim)) { |
| 518 | rc = PTR_ERR(victim); | 602 | rc = PTR_ERR(victim); |
| 519 | victim = NULL; | 603 | victim = NULL; |
| @@ -521,10 +605,19 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | |||
| 521 | } | 605 | } |
| 522 | 606 | ||
| 523 | inode = victim->d_inode; | 607 | inode = victim->d_inode; |
| 608 | |||
| 524 | mutex_lock(&inode->i_mutex); | 609 | mutex_lock(&inode->i_mutex); |
| 610 | |||
| 525 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 611 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 526 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 612 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 527 | rc = notify_change(victim, &newattrs); | 613 | rc = notify_change(victim, &newattrs); |
| 614 | |||
| 615 | if (rc == 0) { | ||
| 616 | mutex_lock(&sysfs_mutex); | ||
| 617 | victim_sd->s_mode = newattrs.ia_mode; | ||
| 618 | mutex_unlock(&sysfs_mutex); | ||
| 619 | } | ||
| 620 | |||
| 528 | mutex_unlock(&inode->i_mutex); | 621 | mutex_unlock(&inode->i_mutex); |
| 529 | out: | 622 | out: |
| 530 | dput(victim); | 623 | dput(victim); |
| @@ -632,4 +725,3 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback); | |||
| 632 | 725 | ||
| 633 | EXPORT_SYMBOL_GPL(sysfs_create_file); | 726 | EXPORT_SYMBOL_GPL(sysfs_create_file); |
| 634 | EXPORT_SYMBOL_GPL(sysfs_remove_file); | 727 | EXPORT_SYMBOL_GPL(sysfs_remove_file); |
| 635 | EXPORT_SYMBOL_GPL(sysfs_update_file); | ||
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index f318b73c790c..d1972374655a 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -13,8 +13,6 @@ | |||
| 13 | #include <linux/dcache.h> | 13 | #include <linux/dcache.h> |
| 14 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/fs.h> | ||
| 17 | #include <asm/semaphore.h> | ||
| 18 | #include "sysfs.h" | 16 | #include "sysfs.h" |
| 19 | 17 | ||
| 20 | 18 | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 10d1b52899f1..9236635111f4 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -1,7 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * inode.c - basic inode and dentry operations. | 2 | * fs/sysfs/inode.c - basic sysfs inode and dentry operations |
| 3 | * | 3 | * |
| 4 | * sysfs is Copyright (c) 2001-3 Patrick Mochel | 4 | * Copyright (c) 2001-3 Patrick Mochel |
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 5 | * | 9 | * |
| 6 | * Please see Documentation/filesystems/sysfs.txt for more information. | 10 | * Please see Documentation/filesystems/sysfs.txt for more information. |
| 7 | */ | 11 | */ |
| @@ -14,7 +18,6 @@ | |||
| 14 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
| 15 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
| 16 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 17 | #include <asm/semaphore.h> | ||
| 18 | #include "sysfs.h" | 21 | #include "sysfs.h" |
| 19 | 22 | ||
| 20 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
| @@ -34,16 +37,6 @@ static const struct inode_operations sysfs_inode_operations ={ | |||
| 34 | .setattr = sysfs_setattr, | 37 | .setattr = sysfs_setattr, |
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| 37 | void sysfs_delete_inode(struct inode *inode) | ||
| 38 | { | ||
| 39 | /* Free the shadowed directory inode operations */ | ||
| 40 | if (sysfs_is_shadowed_inode(inode)) { | ||
| 41 | kfree(inode->i_op); | ||
| 42 | inode->i_op = NULL; | ||
| 43 | } | ||
| 44 | return generic_delete_inode(inode); | ||
| 45 | } | ||
| 46 | |||
| 47 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | 40 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) |
| 48 | { | 41 | { |
| 49 | struct inode * inode = dentry->d_inode; | 42 | struct inode * inode = dentry->d_inode; |
| @@ -133,8 +126,22 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | |||
| 133 | */ | 126 | */ |
| 134 | static struct lock_class_key sysfs_inode_imutex_key; | 127 | static struct lock_class_key sysfs_inode_imutex_key; |
| 135 | 128 | ||
| 129 | static int sysfs_count_nlink(struct sysfs_dirent *sd) | ||
| 130 | { | ||
| 131 | struct sysfs_dirent *child; | ||
| 132 | int nr = 0; | ||
| 133 | |||
| 134 | for (child = sd->s_dir.children; child; child = child->s_sibling) | ||
| 135 | if (sysfs_type(child) == SYSFS_DIR) | ||
| 136 | nr++; | ||
| 137 | |||
| 138 | return nr + 2; | ||
| 139 | } | ||
| 140 | |||
| 136 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | 141 | static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
| 137 | { | 142 | { |
| 143 | struct bin_attribute *bin_attr; | ||
| 144 | |||
| 138 | inode->i_blocks = 0; | 145 | inode->i_blocks = 0; |
| 139 | inode->i_mapping->a_ops = &sysfs_aops; | 146 | inode->i_mapping->a_ops = &sysfs_aops; |
| 140 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 147 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
| @@ -150,6 +157,32 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
| 150 | set_inode_attr(inode, sd->s_iattr); | 157 | set_inode_attr(inode, sd->s_iattr); |
| 151 | } else | 158 | } else |
| 152 | set_default_inode_attr(inode, sd->s_mode); | 159 | set_default_inode_attr(inode, sd->s_mode); |
| 160 | |||
| 161 | |||
| 162 | /* initialize inode according to type */ | ||
| 163 | switch (sysfs_type(sd)) { | ||
| 164 | case SYSFS_DIR: | ||
| 165 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 166 | inode->i_fop = &sysfs_dir_operations; | ||
| 167 | inode->i_nlink = sysfs_count_nlink(sd); | ||
| 168 | break; | ||
| 169 | case SYSFS_KOBJ_ATTR: | ||
| 170 | inode->i_size = PAGE_SIZE; | ||
| 171 | inode->i_fop = &sysfs_file_operations; | ||
| 172 | break; | ||
| 173 | case SYSFS_KOBJ_BIN_ATTR: | ||
| 174 | bin_attr = sd->s_bin_attr.bin_attr; | ||
| 175 | inode->i_size = bin_attr->size; | ||
| 176 | inode->i_fop = &bin_fops; | ||
| 177 | break; | ||
| 178 | case SYSFS_KOBJ_LINK: | ||
| 179 | inode->i_op = &sysfs_symlink_inode_operations; | ||
| 180 | break; | ||
| 181 | default: | ||
| 182 | BUG(); | ||
| 183 | } | ||
| 184 | |||
| 185 | unlock_new_inode(inode); | ||
| 153 | } | 186 | } |
| 154 | 187 | ||
| 155 | /** | 188 | /** |
| @@ -177,50 +210,24 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd) | |||
| 177 | return inode; | 210 | return inode; |
| 178 | } | 211 | } |
| 179 | 212 | ||
| 180 | /** | ||
| 181 | * sysfs_instantiate - instantiate dentry | ||
| 182 | * @dentry: dentry to be instantiated | ||
| 183 | * @inode: inode associated with @sd | ||
| 184 | * | ||
| 185 | * Unlock @inode if locked and instantiate @dentry with @inode. | ||
| 186 | * | ||
| 187 | * LOCKING: | ||
| 188 | * None. | ||
| 189 | */ | ||
| 190 | void sysfs_instantiate(struct dentry *dentry, struct inode *inode) | ||
| 191 | { | ||
| 192 | BUG_ON(!dentry || dentry->d_inode); | ||
| 193 | |||
| 194 | if (inode->i_state & I_NEW) | ||
| 195 | unlock_new_inode(inode); | ||
| 196 | |||
| 197 | d_instantiate(dentry, inode); | ||
| 198 | } | ||
| 199 | |||
| 200 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) | 213 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) |
| 201 | { | 214 | { |
| 202 | struct sysfs_addrm_cxt acxt; | 215 | struct sysfs_addrm_cxt acxt; |
| 203 | struct sysfs_dirent **pos, *sd; | 216 | struct sysfs_dirent *sd; |
| 204 | 217 | ||
| 205 | if (!dir_sd) | 218 | if (!dir_sd) |
| 206 | return -ENOENT; | 219 | return -ENOENT; |
| 207 | 220 | ||
| 208 | sysfs_addrm_start(&acxt, dir_sd); | 221 | sysfs_addrm_start(&acxt, dir_sd); |
| 209 | 222 | ||
| 210 | for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { | 223 | sd = sysfs_find_dirent(dir_sd, name); |
| 211 | sd = *pos; | 224 | if (sd) |
| 212 | 225 | sysfs_remove_one(&acxt, sd); | |
| 213 | if (!sysfs_type(sd)) | 226 | |
| 214 | continue; | 227 | sysfs_addrm_finish(&acxt); |
| 215 | if (!strcmp(sd->s_name, name)) { | ||
| 216 | *pos = sd->s_sibling; | ||
| 217 | sd->s_sibling = NULL; | ||
| 218 | sysfs_remove_one(&acxt, sd); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | 228 | ||
| 223 | if (sysfs_addrm_finish(&acxt)) | 229 | if (sd) |
| 224 | return 0; | 230 | return 0; |
| 225 | return -ENOENT; | 231 | else |
| 232 | return -ENOENT; | ||
| 226 | } | 233 | } |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index fbc7b65fe262..c76c540be3c8 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * mount.c - operations for initializing and mounting sysfs. | 2 | * fs/sysfs/symlink.c - operations for initializing and mounting sysfs |
| 3 | * | ||
| 4 | * Copyright (c) 2001-3 Patrick Mochel | ||
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 9 | * | ||
| 10 | * Please see Documentation/filesystems/sysfs.txt for more information. | ||
| 3 | */ | 11 | */ |
| 4 | 12 | ||
| 5 | #define DEBUG | 13 | #define DEBUG |
| @@ -8,25 +16,25 @@ | |||
| 8 | #include <linux/mount.h> | 16 | #include <linux/mount.h> |
| 9 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
| 10 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 11 | #include <asm/semaphore.h> | ||
| 12 | 19 | ||
| 13 | #include "sysfs.h" | 20 | #include "sysfs.h" |
| 14 | 21 | ||
| 15 | /* Random magic number */ | 22 | /* Random magic number */ |
| 16 | #define SYSFS_MAGIC 0x62656572 | 23 | #define SYSFS_MAGIC 0x62656572 |
| 17 | 24 | ||
| 18 | struct vfsmount *sysfs_mount; | 25 | static struct vfsmount *sysfs_mount; |
| 19 | struct super_block * sysfs_sb = NULL; | 26 | struct super_block * sysfs_sb = NULL; |
| 20 | struct kmem_cache *sysfs_dir_cachep; | 27 | struct kmem_cache *sysfs_dir_cachep; |
| 21 | 28 | ||
| 22 | static const struct super_operations sysfs_ops = { | 29 | static const struct super_operations sysfs_ops = { |
| 23 | .statfs = simple_statfs, | 30 | .statfs = simple_statfs, |
| 24 | .drop_inode = sysfs_delete_inode, | 31 | .drop_inode = generic_delete_inode, |
| 25 | }; | 32 | }; |
| 26 | 33 | ||
| 27 | struct sysfs_dirent sysfs_root = { | 34 | struct sysfs_dirent sysfs_root = { |
| 35 | .s_name = "", | ||
| 28 | .s_count = ATOMIC_INIT(1), | 36 | .s_count = ATOMIC_INIT(1), |
| 29 | .s_flags = SYSFS_ROOT, | 37 | .s_flags = SYSFS_DIR, |
| 30 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 38 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
| 31 | .s_ino = 1, | 39 | .s_ino = 1, |
| 32 | }; | 40 | }; |
| @@ -50,11 +58,6 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 50 | return -ENOMEM; | 58 | return -ENOMEM; |
| 51 | } | 59 | } |
| 52 | 60 | ||
| 53 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 54 | inode->i_fop = &sysfs_dir_operations; | ||
| 55 | inc_nlink(inode); /* directory, account for "." */ | ||
| 56 | unlock_new_inode(inode); | ||
| 57 | |||
| 58 | /* instantiate and link root dentry */ | 61 | /* instantiate and link root dentry */ |
| 59 | root = d_alloc_root(inode); | 62 | root = d_alloc_root(inode); |
| 60 | if (!root) { | 63 | if (!root) { |
| @@ -62,7 +65,6 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 62 | iput(inode); | 65 | iput(inode); |
| 63 | return -ENOMEM; | 66 | return -ENOMEM; |
| 64 | } | 67 | } |
| 65 | sysfs_root.s_dentry = root; | ||
| 66 | root->d_fsdata = &sysfs_root; | 68 | root->d_fsdata = &sysfs_root; |
| 67 | sb->s_root = root; | 69 | sb->s_root = root; |
| 68 | return 0; | 70 | return 0; |
| @@ -77,7 +79,7 @@ static int sysfs_get_sb(struct file_system_type *fs_type, | |||
| 77 | static struct file_system_type sysfs_fs_type = { | 79 | static struct file_system_type sysfs_fs_type = { |
| 78 | .name = "sysfs", | 80 | .name = "sysfs", |
| 79 | .get_sb = sysfs_get_sb, | 81 | .get_sb = sysfs_get_sb, |
| 80 | .kill_sb = kill_litter_super, | 82 | .kill_sb = kill_anon_super, |
| 81 | }; | 83 | }; |
| 82 | 84 | ||
| 83 | int __init sysfs_init(void) | 85 | int __init sysfs_init(void) |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 4ce687f0b5d0..3eac20c63c41 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * symlink.c - operations for sysfs symlinks. | 2 | * fs/sysfs/symlink.c - sysfs symlink implementation |
| 3 | * | ||
| 4 | * Copyright (c) 2001-3 Patrick Mochel | ||
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 9 | * | ||
| 10 | * Please see Documentation/filesystems/sysfs.txt for more information. | ||
| 3 | */ | 11 | */ |
| 4 | 12 | ||
| 5 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| @@ -7,7 +15,7 @@ | |||
| 7 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 8 | #include <linux/kobject.h> | 16 | #include <linux/kobject.h> |
| 9 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
| 10 | #include <asm/semaphore.h> | 18 | #include <linux/mutex.h> |
| 11 | 19 | ||
| 12 | #include "sysfs.h" | 20 | #include "sysfs.h" |
| 13 | 21 | ||
| @@ -60,10 +68,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char | |||
| 60 | 68 | ||
| 61 | BUG_ON(!name); | 69 | BUG_ON(!name); |
| 62 | 70 | ||
| 63 | if (!kobj) { | 71 | if (!kobj) |
| 64 | if (sysfs_mount && sysfs_mount->mnt_sb) | 72 | parent_sd = &sysfs_root; |
| 65 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; | 73 | else |
| 66 | } else | ||
| 67 | parent_sd = kobj->sd; | 74 | parent_sd = kobj->sd; |
| 68 | 75 | ||
| 69 | error = -EFAULT; | 76 | error = -EFAULT; |
| @@ -87,20 +94,15 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char | |||
| 87 | if (!sd) | 94 | if (!sd) |
| 88 | goto out_put; | 95 | goto out_put; |
| 89 | 96 | ||
| 90 | sd->s_elem.symlink.target_sd = target_sd; | 97 | sd->s_symlink.target_sd = target_sd; |
| 91 | target_sd = NULL; /* reference is now owned by the symlink */ | 98 | target_sd = NULL; /* reference is now owned by the symlink */ |
| 92 | 99 | ||
| 93 | sysfs_addrm_start(&acxt, parent_sd); | 100 | sysfs_addrm_start(&acxt, parent_sd); |
| 101 | error = sysfs_add_one(&acxt, sd); | ||
| 102 | sysfs_addrm_finish(&acxt); | ||
| 94 | 103 | ||
| 95 | if (!sysfs_find_dirent(parent_sd, name)) { | 104 | if (error) |
| 96 | sysfs_add_one(&acxt, sd); | ||
| 97 | sysfs_link_sibling(sd); | ||
| 98 | } | ||
| 99 | |||
| 100 | if (!sysfs_addrm_finish(&acxt)) { | ||
| 101 | error = -EEXIST; | ||
| 102 | goto out_put; | 105 | goto out_put; |
| 103 | } | ||
| 104 | 106 | ||
| 105 | return 0; | 107 | return 0; |
| 106 | 108 | ||
| @@ -148,7 +150,7 @@ static int sysfs_getlink(struct dentry *dentry, char * path) | |||
| 148 | { | 150 | { |
| 149 | struct sysfs_dirent *sd = dentry->d_fsdata; | 151 | struct sysfs_dirent *sd = dentry->d_fsdata; |
| 150 | struct sysfs_dirent *parent_sd = sd->s_parent; | 152 | struct sysfs_dirent *parent_sd = sd->s_parent; |
| 151 | struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd; | 153 | struct sysfs_dirent *target_sd = sd->s_symlink.target_sd; |
| 152 | int error; | 154 | int error; |
| 153 | 155 | ||
| 154 | mutex_lock(&sysfs_mutex); | 156 | mutex_lock(&sysfs_mutex); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6b8c8d76d308..f0326f281d1c 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -1,20 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * fs/sysfs/sysfs.h - sysfs internal header file | ||
| 3 | * | ||
| 4 | * Copyright (c) 2001-3 Patrick Mochel | ||
| 5 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 6 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 7 | * | ||
| 8 | * This file is released under the GPLv2. | ||
| 9 | */ | ||
| 10 | |||
| 11 | struct sysfs_open_dirent; | ||
| 12 | |||
| 13 | /* type-specific structures for sysfs_dirent->s_* union members */ | ||
| 1 | struct sysfs_elem_dir { | 14 | struct sysfs_elem_dir { |
| 2 | struct kobject * kobj; | 15 | struct kobject *kobj; |
| 16 | /* children list starts here and goes through sd->s_sibling */ | ||
| 17 | struct sysfs_dirent *children; | ||
| 3 | }; | 18 | }; |
| 4 | 19 | ||
| 5 | struct sysfs_elem_symlink { | 20 | struct sysfs_elem_symlink { |
| 6 | struct sysfs_dirent * target_sd; | 21 | struct sysfs_dirent *target_sd; |
| 7 | }; | 22 | }; |
| 8 | 23 | ||
| 9 | struct sysfs_elem_attr { | 24 | struct sysfs_elem_attr { |
| 10 | struct attribute * attr; | 25 | struct attribute *attr; |
| 26 | struct sysfs_open_dirent *open; | ||
| 11 | }; | 27 | }; |
| 12 | 28 | ||
| 13 | struct sysfs_elem_bin_attr { | 29 | struct sysfs_elem_bin_attr { |
| 14 | struct bin_attribute * bin_attr; | 30 | struct bin_attribute *bin_attr; |
| 15 | }; | 31 | }; |
| 16 | 32 | ||
| 17 | /* | 33 | /* |
| 34 | * sysfs_dirent - the building block of sysfs hierarchy. Each and | ||
| 35 | * every sysfs node is represented by single sysfs_dirent. | ||
| 36 | * | ||
| 18 | * As long as s_count reference is held, the sysfs_dirent itself is | 37 | * As long as s_count reference is held, the sysfs_dirent itself is |
| 19 | * accessible. Dereferencing s_elem or any other outer entity | 38 | * accessible. Dereferencing s_elem or any other outer entity |
| 20 | * requires s_active reference. | 39 | * requires s_active reference. |
| @@ -22,28 +41,43 @@ struct sysfs_elem_bin_attr { | |||
| 22 | struct sysfs_dirent { | 41 | struct sysfs_dirent { |
| 23 | atomic_t s_count; | 42 | atomic_t s_count; |
| 24 | atomic_t s_active; | 43 | atomic_t s_active; |
| 25 | struct sysfs_dirent * s_parent; | 44 | struct sysfs_dirent *s_parent; |
| 26 | struct sysfs_dirent * s_sibling; | 45 | struct sysfs_dirent *s_sibling; |
| 27 | struct sysfs_dirent * s_children; | 46 | const char *s_name; |
| 28 | const char * s_name; | ||
| 29 | 47 | ||
| 30 | union { | 48 | union { |
| 31 | struct sysfs_elem_dir dir; | 49 | struct sysfs_elem_dir s_dir; |
| 32 | struct sysfs_elem_symlink symlink; | 50 | struct sysfs_elem_symlink s_symlink; |
| 33 | struct sysfs_elem_attr attr; | 51 | struct sysfs_elem_attr s_attr; |
| 34 | struct sysfs_elem_bin_attr bin_attr; | 52 | struct sysfs_elem_bin_attr s_bin_attr; |
| 35 | } s_elem; | 53 | }; |
| 36 | 54 | ||
| 37 | unsigned int s_flags; | 55 | unsigned int s_flags; |
| 38 | umode_t s_mode; | ||
| 39 | ino_t s_ino; | 56 | ino_t s_ino; |
| 40 | struct dentry * s_dentry; | 57 | umode_t s_mode; |
| 41 | struct iattr * s_iattr; | 58 | struct iattr *s_iattr; |
| 42 | atomic_t s_event; | ||
| 43 | }; | 59 | }; |
| 44 | 60 | ||
| 45 | #define SD_DEACTIVATED_BIAS INT_MIN | 61 | #define SD_DEACTIVATED_BIAS INT_MIN |
| 62 | |||
| 63 | #define SYSFS_TYPE_MASK 0x00ff | ||
| 64 | #define SYSFS_DIR 0x0001 | ||
| 65 | #define SYSFS_KOBJ_ATTR 0x0002 | ||
| 66 | #define SYSFS_KOBJ_BIN_ATTR 0x0004 | ||
| 67 | #define SYSFS_KOBJ_LINK 0x0008 | ||
| 68 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | ||
| 69 | |||
| 70 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | ||
| 71 | #define SYSFS_FLAG_REMOVED 0x0200 | ||
| 72 | |||
| 73 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | ||
| 74 | { | ||
| 75 | return sd->s_flags & SYSFS_TYPE_MASK; | ||
| 76 | } | ||
| 46 | 77 | ||
| 78 | /* | ||
| 79 | * Context structure to be used while adding/removing nodes. | ||
| 80 | */ | ||
| 47 | struct sysfs_addrm_cxt { | 81 | struct sysfs_addrm_cxt { |
| 48 | struct sysfs_dirent *parent_sd; | 82 | struct sysfs_dirent *parent_sd; |
| 49 | struct inode *parent_inode; | 83 | struct inode *parent_inode; |
| @@ -51,63 +85,47 @@ struct sysfs_addrm_cxt { | |||
| 51 | int cnt; | 85 | int cnt; |
| 52 | }; | 86 | }; |
| 53 | 87 | ||
| 54 | extern struct vfsmount * sysfs_mount; | 88 | /* |
| 89 | * mount.c | ||
| 90 | */ | ||
| 55 | extern struct sysfs_dirent sysfs_root; | 91 | extern struct sysfs_dirent sysfs_root; |
| 92 | extern struct super_block *sysfs_sb; | ||
| 56 | extern struct kmem_cache *sysfs_dir_cachep; | 93 | extern struct kmem_cache *sysfs_dir_cachep; |
| 57 | 94 | ||
| 58 | extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); | 95 | /* |
| 59 | extern void sysfs_link_sibling(struct sysfs_dirent *sd); | 96 | * dir.c |
| 60 | extern void sysfs_unlink_sibling(struct sysfs_dirent *sd); | 97 | */ |
| 61 | extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | ||
| 62 | extern void sysfs_put_active(struct sysfs_dirent *sd); | ||
| 63 | extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | ||
| 64 | extern void sysfs_put_active_two(struct sysfs_dirent *sd); | ||
| 65 | extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | ||
| 66 | struct sysfs_dirent *parent_sd); | ||
| 67 | extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt, | ||
| 68 | struct sysfs_dirent *sd); | ||
| 69 | extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, | ||
| 70 | struct sysfs_dirent *sd); | ||
| 71 | extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | ||
| 72 | |||
| 73 | extern void sysfs_delete_inode(struct inode *inode); | ||
| 74 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); | ||
| 75 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); | ||
| 76 | |||
| 77 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | ||
| 78 | extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | ||
| 79 | const unsigned char *name); | ||
| 80 | extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
| 81 | const unsigned char *name); | ||
| 82 | extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, | ||
| 83 | int type); | ||
| 84 | |||
| 85 | extern int sysfs_add_file(struct sysfs_dirent *dir_sd, | ||
| 86 | const struct attribute *attr, int type); | ||
| 87 | extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); | ||
| 88 | extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); | ||
| 89 | |||
| 90 | extern int sysfs_create_subdir(struct kobject *kobj, const char *name, | ||
| 91 | struct sysfs_dirent **p_sd); | ||
| 92 | extern void sysfs_remove_subdir(struct sysfs_dirent *sd); | ||
| 93 | |||
| 94 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | ||
| 95 | |||
| 96 | extern spinlock_t sysfs_assoc_lock; | ||
| 97 | extern struct mutex sysfs_mutex; | 98 | extern struct mutex sysfs_mutex; |
| 98 | extern struct super_block * sysfs_sb; | 99 | extern struct mutex sysfs_rename_mutex; |
| 100 | extern spinlock_t sysfs_assoc_lock; | ||
| 101 | |||
| 99 | extern const struct file_operations sysfs_dir_operations; | 102 | extern const struct file_operations sysfs_dir_operations; |
| 100 | extern const struct file_operations sysfs_file_operations; | ||
| 101 | extern const struct file_operations bin_fops; | ||
| 102 | extern const struct inode_operations sysfs_dir_inode_operations; | 103 | extern const struct inode_operations sysfs_dir_inode_operations; |
| 103 | extern const struct inode_operations sysfs_symlink_inode_operations; | ||
| 104 | |||
| 105 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | ||
| 106 | { | ||
| 107 | return sd->s_flags & SYSFS_TYPE_MASK; | ||
| 108 | } | ||
| 109 | 104 | ||
| 110 | static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) | 105 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
| 106 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | ||
| 107 | void sysfs_put_active(struct sysfs_dirent *sd); | ||
| 108 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | ||
| 109 | void sysfs_put_active_two(struct sysfs_dirent *sd); | ||
| 110 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | ||
| 111 | struct sysfs_dirent *parent_sd); | ||
| 112 | int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | ||
| 113 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd); | ||
| 114 | void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | ||
| 115 | |||
| 116 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | ||
| 117 | const unsigned char *name); | ||
| 118 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
| 119 | const unsigned char *name); | ||
| 120 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); | ||
| 121 | |||
| 122 | void release_sysfs_dirent(struct sysfs_dirent *sd); | ||
| 123 | |||
| 124 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | ||
| 125 | struct sysfs_dirent **p_sd); | ||
| 126 | void sysfs_remove_subdir(struct sysfs_dirent *sd); | ||
| 127 | |||
| 128 | static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd) | ||
| 111 | { | 129 | { |
| 112 | if (sd) { | 130 | if (sd) { |
| 113 | WARN_ON(!atomic_read(&sd->s_count)); | 131 | WARN_ON(!atomic_read(&sd->s_count)); |
| @@ -116,13 +134,33 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) | |||
| 116 | return sd; | 134 | return sd; |
| 117 | } | 135 | } |
| 118 | 136 | ||
| 119 | static inline void sysfs_put(struct sysfs_dirent * sd) | 137 | static inline void sysfs_put(struct sysfs_dirent *sd) |
| 120 | { | 138 | { |
| 121 | if (sd && atomic_dec_and_test(&sd->s_count)) | 139 | if (sd && atomic_dec_and_test(&sd->s_count)) |
| 122 | release_sysfs_dirent(sd); | 140 | release_sysfs_dirent(sd); |
| 123 | } | 141 | } |
| 124 | 142 | ||
| 125 | static inline int sysfs_is_shadowed_inode(struct inode *inode) | 143 | /* |
| 126 | { | 144 | * inode.c |
| 127 | return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; | 145 | */ |
| 128 | } | 146 | struct inode *sysfs_get_inode(struct sysfs_dirent *sd); |
| 147 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | ||
| 148 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); | ||
| 149 | |||
| 150 | /* | ||
| 151 | * file.c | ||
| 152 | */ | ||
| 153 | extern const struct file_operations sysfs_file_operations; | ||
| 154 | |||
| 155 | int sysfs_add_file(struct sysfs_dirent *dir_sd, | ||
| 156 | const struct attribute *attr, int type); | ||
| 157 | |||
| 158 | /* | ||
| 159 | * bin.c | ||
| 160 | */ | ||
| 161 | extern const struct file_operations bin_fops; | ||
| 162 | |||
| 163 | /* | ||
| 164 | * symlink.c | ||
| 165 | */ | ||
| 166 | extern const struct inode_operations sysfs_symlink_inode_operations; | ||
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index ec2a8a2c737c..93262f2546ad 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h | |||
| @@ -20,7 +20,7 @@ struct of_device | |||
| 20 | extern ssize_t of_device_get_modalias(struct of_device *ofdev, | 20 | extern ssize_t of_device_get_modalias(struct of_device *ofdev, |
| 21 | char *str, ssize_t len); | 21 | char *str, ssize_t len); |
| 22 | extern int of_device_uevent(struct device *dev, | 22 | extern int of_device_uevent(struct device *dev, |
| 23 | char **envp, int num_envp, char *buffer, int buffer_size); | 23 | struct kobj_uevent_env *env); |
| 24 | 24 | ||
| 25 | /* This is just here during the transition */ | 25 | /* This is just here during the transition */ |
| 26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
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/debugfs.h b/include/linux/debugfs.h index 104e51e20e14..f592d6de3b97 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
| @@ -49,6 +49,12 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode, | |||
| 49 | struct dentry *parent, u32 *value); | 49 | struct dentry *parent, u32 *value); |
| 50 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, | 50 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, |
| 51 | struct dentry *parent, u64 *value); | 51 | struct dentry *parent, u64 *value); |
| 52 | struct dentry *debugfs_create_x8(const char *name, mode_t mode, | ||
| 53 | struct dentry *parent, u8 *value); | ||
| 54 | struct dentry *debugfs_create_x16(const char *name, mode_t mode, | ||
| 55 | struct dentry *parent, u16 *value); | ||
| 56 | struct dentry *debugfs_create_x32(const char *name, mode_t mode, | ||
| 57 | struct dentry *parent, u32 *value); | ||
| 52 | struct dentry *debugfs_create_bool(const char *name, mode_t mode, | 58 | struct dentry *debugfs_create_bool(const char *name, mode_t mode, |
| 53 | struct dentry *parent, u32 *value); | 59 | struct dentry *parent, u32 *value); |
| 54 | 60 | ||
| @@ -122,6 +128,27 @@ static inline struct dentry *debugfs_create_u64(const char *name, mode_t mode, | |||
| 122 | return ERR_PTR(-ENODEV); | 128 | return ERR_PTR(-ENODEV); |
| 123 | } | 129 | } |
| 124 | 130 | ||
| 131 | static inline struct dentry *debugfs_create_x8(const char *name, mode_t mode, | ||
| 132 | struct dentry *parent, | ||
| 133 | u8 *value) | ||
| 134 | { | ||
| 135 | return ERR_PTR(-ENODEV); | ||
| 136 | } | ||
| 137 | |||
| 138 | static inline struct dentry *debugfs_create_x16(const char *name, mode_t mode, | ||
| 139 | struct dentry *parent, | ||
| 140 | u16 *value) | ||
| 141 | { | ||
| 142 | return ERR_PTR(-ENODEV); | ||
| 143 | } | ||
| 144 | |||
| 145 | static inline struct dentry *debugfs_create_x32(const char *name, mode_t mode, | ||
| 146 | struct dentry *parent, | ||
| 147 | u32 *value) | ||
| 148 | { | ||
| 149 | return ERR_PTR(-ENODEV); | ||
| 150 | } | ||
| 151 | |||
| 125 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, | 152 | static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode, |
| 126 | struct dentry *parent, | 153 | struct dentry *parent, |
| 127 | u32 *value) | 154 | u32 *value) |
diff --git a/include/linux/device.h b/include/linux/device.h index 3a38d1f70cb7..2e15822fe409 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -64,12 +64,9 @@ struct bus_type { | |||
| 64 | struct bus_attribute * bus_attrs; | 64 | struct bus_attribute * bus_attrs; |
| 65 | struct device_attribute * dev_attrs; | 65 | struct device_attribute * dev_attrs; |
| 66 | struct driver_attribute * drv_attrs; | 66 | struct driver_attribute * drv_attrs; |
| 67 | struct bus_attribute drivers_autoprobe_attr; | ||
| 68 | struct bus_attribute drivers_probe_attr; | ||
| 69 | 67 | ||
| 70 | int (*match)(struct device * dev, struct device_driver * drv); | 68 | int (*match)(struct device * dev, struct device_driver * drv); |
| 71 | int (*uevent)(struct device *dev, char **envp, | 69 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); |
| 72 | int num_envp, char *buffer, int buffer_size); | ||
| 73 | int (*probe)(struct device * dev); | 70 | int (*probe)(struct device * dev); |
| 74 | int (*remove)(struct device * dev); | 71 | int (*remove)(struct device * dev); |
| 75 | void (*shutdown)(struct device * dev); | 72 | void (*shutdown)(struct device * dev); |
| @@ -189,10 +186,8 @@ struct class { | |||
| 189 | struct class_device_attribute * class_dev_attrs; | 186 | struct class_device_attribute * class_dev_attrs; |
| 190 | struct device_attribute * dev_attrs; | 187 | struct device_attribute * dev_attrs; |
| 191 | 188 | ||
| 192 | int (*uevent)(struct class_device *dev, char **envp, | 189 | int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env); |
| 193 | int num_envp, char *buffer, int buffer_size); | 190 | int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); |
| 194 | int (*dev_uevent)(struct device *dev, char **envp, int num_envp, | ||
| 195 | char *buffer, int buffer_size); | ||
| 196 | 191 | ||
| 197 | void (*release)(struct class_device *dev); | 192 | void (*release)(struct class_device *dev); |
| 198 | void (*class_release)(struct class *class); | 193 | void (*class_release)(struct class *class); |
| @@ -268,8 +263,7 @@ struct class_device { | |||
| 268 | struct attribute_group ** groups; /* optional groups */ | 263 | struct attribute_group ** groups; /* optional groups */ |
| 269 | 264 | ||
| 270 | void (*release)(struct class_device *dev); | 265 | void (*release)(struct class_device *dev); |
| 271 | int (*uevent)(struct class_device *dev, char **envp, | 266 | int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env); |
| 272 | int num_envp, char *buffer, int buffer_size); | ||
| 273 | char class_id[BUS_ID_SIZE]; /* unique to this class */ | 267 | char class_id[BUS_ID_SIZE]; /* unique to this class */ |
| 274 | }; | 268 | }; |
| 275 | 269 | ||
| @@ -337,8 +331,7 @@ extern void class_device_destroy(struct class *cls, dev_t devt); | |||
| 337 | struct device_type { | 331 | struct device_type { |
| 338 | const char *name; | 332 | const char *name; |
| 339 | struct attribute_group **groups; | 333 | struct attribute_group **groups; |
| 340 | int (*uevent)(struct device *dev, char **envp, int num_envp, | 334 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); |
| 341 | char *buffer, int buffer_size); | ||
| 342 | void (*release)(struct device *dev); | 335 | void (*release)(struct device *dev); |
| 343 | int (*suspend)(struct device * dev, pm_message_t state); | 336 | int (*suspend)(struct device * dev, pm_message_t state); |
| 344 | int (*resume)(struct device * dev); | 337 | int (*resume)(struct device * dev); |
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/kobject.h b/include/linux/kobject.h index 949706c33622..4a0d27f475d7 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h | |||
| @@ -1,8 +1,10 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * kobject.h - generic kernel object infrastructure. | 2 | * kobject.h - generic kernel object infrastructure. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002-2003 Patrick Mochel | 4 | * Copyright (c) 2002-2003 Patrick Mochel |
| 5 | * Copyright (c) 2002-2003 Open Source Development Labs | 5 | * Copyright (c) 2002-2003 Open Source Development Labs |
| 6 | * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com> | ||
| 7 | * Copyright (c) 2006-2007 Novell Inc. | ||
| 6 | * | 8 | * |
| 7 | * This file is released under the GPLv2. | 9 | * This file is released under the GPLv2. |
| 8 | * | 10 | * |
| @@ -29,6 +31,8 @@ | |||
| 29 | 31 | ||
| 30 | #define KOBJ_NAME_LEN 20 | 32 | #define KOBJ_NAME_LEN 20 |
| 31 | #define UEVENT_HELPER_PATH_LEN 256 | 33 | #define UEVENT_HELPER_PATH_LEN 256 |
| 34 | #define UEVENT_NUM_ENVP 32 /* number of env pointers */ | ||
| 35 | #define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */ | ||
| 32 | 36 | ||
| 33 | /* path to the userspace helper executed on an event */ | 37 | /* path to the userspace helper executed on an event */ |
| 34 | extern char uevent_helper[]; | 38 | extern char uevent_helper[]; |
| @@ -56,19 +60,14 @@ enum kobject_action { | |||
| 56 | KOBJ_MAX | 60 | KOBJ_MAX |
| 57 | }; | 61 | }; |
| 58 | 62 | ||
| 59 | /* The list of strings defining the valid kobject actions as specified above */ | ||
| 60 | extern const char *kobject_actions[]; | ||
| 61 | |||
| 62 | struct kobject { | 63 | struct kobject { |
| 63 | const char * k_name; | 64 | const char * k_name; |
| 64 | char name[KOBJ_NAME_LEN]; | ||
| 65 | struct kref kref; | 65 | struct kref kref; |
| 66 | struct list_head entry; | 66 | struct list_head entry; |
| 67 | struct kobject * parent; | 67 | struct kobject * parent; |
| 68 | struct kset * kset; | 68 | struct kset * kset; |
| 69 | struct kobj_type * ktype; | 69 | struct kobj_type * ktype; |
| 70 | struct sysfs_dirent * sd; | 70 | struct sysfs_dirent * sd; |
| 71 | wait_queue_head_t poll; | ||
| 72 | }; | 71 | }; |
| 73 | 72 | ||
| 74 | extern int kobject_set_name(struct kobject *, const char *, ...) | 73 | extern int kobject_set_name(struct kobject *, const char *, ...) |
| @@ -83,14 +82,9 @@ extern void kobject_init(struct kobject *); | |||
| 83 | extern void kobject_cleanup(struct kobject *); | 82 | extern void kobject_cleanup(struct kobject *); |
| 84 | 83 | ||
| 85 | extern int __must_check kobject_add(struct kobject *); | 84 | extern int __must_check kobject_add(struct kobject *); |
| 86 | extern int __must_check kobject_shadow_add(struct kobject *kobj, | ||
| 87 | struct sysfs_dirent *shadow_parent); | ||
| 88 | extern void kobject_del(struct kobject *); | 85 | extern void kobject_del(struct kobject *); |
| 89 | 86 | ||
| 90 | extern int __must_check kobject_rename(struct kobject *, const char *new_name); | 87 | extern int __must_check kobject_rename(struct kobject *, const char *new_name); |
| 91 | extern int __must_check kobject_shadow_rename(struct kobject *kobj, | ||
| 92 | struct sysfs_dirent *new_parent, | ||
| 93 | const char *new_name); | ||
| 94 | extern int __must_check kobject_move(struct kobject *, struct kobject *); | 88 | extern int __must_check kobject_move(struct kobject *, struct kobject *); |
| 95 | 89 | ||
| 96 | extern int __must_check kobject_register(struct kobject *); | 90 | extern int __must_check kobject_register(struct kobject *); |
| @@ -111,36 +105,44 @@ struct kobj_type { | |||
| 111 | struct attribute ** default_attrs; | 105 | struct attribute ** default_attrs; |
| 112 | }; | 106 | }; |
| 113 | 107 | ||
| 108 | struct kobj_uevent_env { | ||
| 109 | char *envp[UEVENT_NUM_ENVP]; | ||
| 110 | int envp_idx; | ||
| 111 | char buf[UEVENT_BUFFER_SIZE]; | ||
| 112 | int buflen; | ||
| 113 | }; | ||
| 114 | |||
| 114 | struct kset_uevent_ops { | 115 | struct kset_uevent_ops { |
| 115 | int (*filter)(struct kset *kset, struct kobject *kobj); | 116 | int (*filter)(struct kset *kset, struct kobject *kobj); |
| 116 | const char *(*name)(struct kset *kset, struct kobject *kobj); | 117 | const char *(*name)(struct kset *kset, struct kobject *kobj); |
| 117 | int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp, | 118 | int (*uevent)(struct kset *kset, struct kobject *kobj, |
| 118 | int num_envp, char *buffer, int buffer_size); | 119 | struct kobj_uevent_env *env); |
| 119 | }; | 120 | }; |
| 120 | 121 | ||
| 121 | /* | 122 | /** |
| 122 | * struct kset - a set of kobjects of a specific type, belonging | 123 | * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem. |
| 123 | * to a specific subsystem. | ||
| 124 | * | ||
| 125 | * All kobjects of a kset should be embedded in an identical | ||
| 126 | * type. This type may have a descriptor, which the kset points | ||
| 127 | * to. This allows there to exist sets of objects of the same | ||
| 128 | * type in different subsystems. | ||
| 129 | * | 124 | * |
| 130 | * A subsystem does not have to be a list of only one type | 125 | * A kset defines a group of kobjects. They can be individually |
| 131 | * of object; multiple ksets can belong to one subsystem. All | 126 | * different "types" but overall these kobjects all want to be grouped |
| 132 | * ksets of a subsystem share the subsystem's lock. | 127 | * together and operated on in the same manner. ksets are used to |
| 128 | * define the attribute callbacks and other common events that happen to | ||
| 129 | * a kobject. | ||
| 133 | * | 130 | * |
| 134 | * Each kset can support specific event variables; it can | 131 | * @ktype: the struct kobj_type for this specific kset |
| 135 | * supress the event generation or add subsystem specific | 132 | * @list: the list of all kobjects for this kset |
| 136 | * variables carried with the event. | 133 | * @list_lock: a lock for iterating over the kobjects |
| 134 | * @kobj: the embedded kobject for this kset (recursion, isn't it fun...) | ||
| 135 | * @uevent_ops: the set of uevent operations for this kset. These are | ||
| 136 | * called whenever a kobject has something happen to it so that the kset | ||
| 137 | * can add new environment variables, or filter out the uevents if so | ||
| 138 | * desired. | ||
| 137 | */ | 139 | */ |
| 138 | struct kset { | 140 | struct kset { |
| 139 | struct kobj_type * ktype; | 141 | struct kobj_type *ktype; |
| 140 | struct list_head list; | 142 | struct list_head list; |
| 141 | spinlock_t list_lock; | 143 | spinlock_t list_lock; |
| 142 | struct kobject kobj; | 144 | struct kobject kobj; |
| 143 | struct kset_uevent_ops * uevent_ops; | 145 | struct kset_uevent_ops *uevent_ops; |
| 144 | }; | 146 | }; |
| 145 | 147 | ||
| 146 | 148 | ||
| @@ -179,18 +181,18 @@ extern struct kobject * kset_find_obj(struct kset *, const char *); | |||
| 179 | * Use this when initializing an embedded kset with no other | 181 | * Use this when initializing an embedded kset with no other |
| 180 | * fields to initialize. | 182 | * fields to initialize. |
| 181 | */ | 183 | */ |
| 182 | #define set_kset_name(str) .kset = { .kobj = { .name = str } } | 184 | #define set_kset_name(str) .kset = { .kobj = { .k_name = str } } |
| 183 | 185 | ||
| 184 | 186 | ||
| 185 | #define decl_subsys(_name,_type,_uevent_ops) \ | 187 | #define decl_subsys(_name,_type,_uevent_ops) \ |
| 186 | struct kset _name##_subsys = { \ | 188 | struct kset _name##_subsys = { \ |
| 187 | .kobj = { .name = __stringify(_name) }, \ | 189 | .kobj = { .k_name = __stringify(_name) }, \ |
| 188 | .ktype = _type, \ | 190 | .ktype = _type, \ |
| 189 | .uevent_ops =_uevent_ops, \ | 191 | .uevent_ops =_uevent_ops, \ |
| 190 | } | 192 | } |
| 191 | #define decl_subsys_name(_varname,_name,_type,_uevent_ops) \ | 193 | #define decl_subsys_name(_varname,_name,_type,_uevent_ops) \ |
| 192 | struct kset _varname##_subsys = { \ | 194 | struct kset _varname##_subsys = { \ |
| 193 | .kobj = { .name = __stringify(_name) }, \ | 195 | .kobj = { .k_name = __stringify(_name) }, \ |
| 194 | .ktype = _type, \ | 196 | .ktype = _type, \ |
| 195 | .uevent_ops =_uevent_ops, \ | 197 | .uevent_ops =_uevent_ops, \ |
| 196 | } | 198 | } |
| @@ -218,49 +220,9 @@ extern struct kset hypervisor_subsys; | |||
| 218 | #define kobj_set_kset_s(obj,subsys) \ | 220 | #define kobj_set_kset_s(obj,subsys) \ |
| 219 | (obj)->kobj.kset = &(subsys) | 221 | (obj)->kobj.kset = &(subsys) |
| 220 | 222 | ||
| 221 | /** | ||
| 222 | * kset_set_kset_s(obj,subsys) - set kset for embedded kset. | ||
| 223 | * @obj: ptr to some object type. | ||
| 224 | * @subsys: a subsystem object (not a ptr). | ||
| 225 | * | ||
| 226 | * Can be used for any object type with an embedded ->kset. | ||
| 227 | * Sets the kset of @obj's embedded kobject (via its embedded | ||
| 228 | * kset) to @subsys.kset. This makes @obj a member of that | ||
| 229 | * kset. | ||
| 230 | */ | ||
| 231 | |||
| 232 | #define kset_set_kset_s(obj,subsys) \ | ||
| 233 | (obj)->kset.kobj.kset = &(subsys) | ||
| 234 | |||
| 235 | /** | ||
| 236 | * subsys_set_kset(obj,subsys) - set kset for subsystem | ||
| 237 | * @obj: ptr to some object type. | ||
| 238 | * @_subsys: a subsystem object (not a ptr). | ||
| 239 | * | ||
| 240 | * Can be used for any object type with an embedded ->subsys. | ||
| 241 | * Sets the kset of @obj's kobject to @subsys.kset. This makes | ||
| 242 | * the object a member of that kset. | ||
| 243 | */ | ||
| 244 | |||
| 245 | #define subsys_set_kset(obj,_subsys) \ | ||
| 246 | (obj)->subsys.kobj.kset = &(_subsys) | ||
| 247 | |||
| 248 | extern void subsystem_init(struct kset *); | ||
| 249 | extern int __must_check subsystem_register(struct kset *); | 223 | extern int __must_check subsystem_register(struct kset *); |
| 250 | extern void subsystem_unregister(struct kset *); | 224 | extern void subsystem_unregister(struct kset *); |
| 251 | 225 | ||
| 252 | static inline struct kset *subsys_get(struct kset *s) | ||
| 253 | { | ||
| 254 | if (s) | ||
| 255 | return kset_get(s); | ||
| 256 | return NULL; | ||
| 257 | } | ||
| 258 | |||
| 259 | static inline void subsys_put(struct kset *s) | ||
| 260 | { | ||
| 261 | kset_put(s); | ||
| 262 | } | ||
| 263 | |||
| 264 | struct subsys_attribute { | 226 | struct subsys_attribute { |
| 265 | struct attribute attr; | 227 | struct attribute attr; |
| 266 | ssize_t (*show)(struct kset *, char *); | 228 | ssize_t (*show)(struct kset *, char *); |
| @@ -275,10 +237,11 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action); | |||
| 275 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | 237 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, |
| 276 | char *envp[]); | 238 | char *envp[]); |
| 277 | 239 | ||
| 278 | int add_uevent_var(char **envp, int num_envp, int *cur_index, | 240 | int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) |
| 279 | char *buffer, int buffer_size, int *cur_len, | 241 | __attribute__((format (printf, 2, 3))); |
| 280 | const char *format, ...) | 242 | |
| 281 | __attribute__((format (printf, 7, 8))); | 243 | int kobject_action_type(const char *buf, size_t count, |
| 244 | enum kobject_action *type); | ||
| 282 | #else | 245 | #else |
| 283 | static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) | 246 | static inline int kobject_uevent(struct kobject *kobj, enum kobject_action action) |
| 284 | { return 0; } | 247 | { return 0; } |
| @@ -287,10 +250,12 @@ static inline int kobject_uevent_env(struct kobject *kobj, | |||
| 287 | char *envp[]) | 250 | char *envp[]) |
| 288 | { return 0; } | 251 | { return 0; } |
| 289 | 252 | ||
| 290 | static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, | 253 | static inline int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) |
| 291 | char *buffer, int buffer_size, int *cur_len, | ||
| 292 | const char *format, ...) | ||
| 293 | { return 0; } | 254 | { return 0; } |
| 255 | |||
| 256 | static inline int kobject_action_type(const char *buf, size_t count, | ||
| 257 | enum kobject_action *type) | ||
| 258 | { return -EINVAL; } | ||
| 294 | #endif | 259 | #endif |
| 295 | 260 | ||
| 296 | #endif /* __KERNEL__ */ | 261 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c88234d46506..87439ad94685 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2245,6 +2245,7 @@ | |||
| 2245 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 | 2245 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 |
| 2246 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 | 2246 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 |
| 2247 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db | 2247 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db |
| 2248 | #define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc | ||
| 2248 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd | 2249 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd |
| 2249 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 | 2250 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 |
| 2250 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 | 2251 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 8bbd459eafdc..e80804316cdb 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | struct platform_device { | 16 | struct platform_device { |
| 17 | const char * name; | 17 | const char * name; |
| 18 | u32 id; | 18 | int id; |
| 19 | struct device dev; | 19 | struct device dev; |
| 20 | u32 num_resources; | 20 | u32 num_resources; |
| 21 | struct resource * resource; | 21 | struct resource * resource; |
| @@ -35,9 +35,10 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u | |||
| 35 | extern int platform_get_irq_byname(struct platform_device *, char *); | 35 | extern int platform_get_irq_byname(struct platform_device *, char *); |
| 36 | extern int platform_add_devices(struct platform_device **, int); | 36 | extern int platform_add_devices(struct platform_device **, int); |
| 37 | 37 | ||
| 38 | extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int); | 38 | extern struct platform_device *platform_device_register_simple(char *, int id, |
| 39 | struct resource *, unsigned int); | ||
| 39 | 40 | ||
| 40 | extern struct platform_device *platform_device_alloc(const char *name, unsigned int id); | 41 | extern struct platform_device *platform_device_alloc(const char *name, int id); |
| 41 | extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); | 42 | extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); |
| 42 | extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); | 43 | extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); |
| 43 | extern int platform_device_add(struct platform_device *pdev); | 44 | extern int platform_device_add(struct platform_device *pdev); |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index be8228e50a27..149ab62329e2 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2001,2002 Patrick Mochel | 4 | * Copyright (c) 2001,2002 Patrick Mochel |
| 5 | * Copyright (c) 2004 Silicon Graphics, Inc. | 5 | * Copyright (c) 2004 Silicon Graphics, Inc. |
| 6 | * Copyright (c) 2007 SUSE Linux Products GmbH | ||
| 7 | * Copyright (c) 2007 Tejun Heo <teheo@suse.de> | ||
| 6 | * | 8 | * |
| 7 | * Please see Documentation/filesystems/sysfs.txt for more information. | 9 | * Please see Documentation/filesystems/sysfs.txt for more information. |
| 8 | */ | 10 | */ |
| @@ -17,23 +19,20 @@ | |||
| 17 | 19 | ||
| 18 | struct kobject; | 20 | struct kobject; |
| 19 | struct module; | 21 | struct module; |
| 20 | struct nameidata; | ||
| 21 | struct dentry; | ||
| 22 | struct sysfs_dirent; | ||
| 23 | 22 | ||
| 24 | /* FIXME | 23 | /* FIXME |
| 25 | * The *owner field is no longer used, but leave around | 24 | * The *owner field is no longer used, but leave around |
| 26 | * until the tree gets cleaned up fully. | 25 | * until the tree gets cleaned up fully. |
| 27 | */ | 26 | */ |
| 28 | struct attribute { | 27 | struct attribute { |
| 29 | const char * name; | 28 | const char *name; |
| 30 | struct module * owner; | 29 | struct module *owner; |
| 31 | mode_t mode; | 30 | mode_t mode; |
| 32 | }; | 31 | }; |
| 33 | 32 | ||
| 34 | struct attribute_group { | 33 | struct attribute_group { |
| 35 | const char * name; | 34 | const char *name; |
| 36 | struct attribute ** attrs; | 35 | struct attribute **attrs; |
| 37 | }; | 36 | }; |
| 38 | 37 | ||
| 39 | 38 | ||
| @@ -77,72 +76,41 @@ struct sysfs_ops { | |||
| 77 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); | 76 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |
| 78 | }; | 77 | }; |
| 79 | 78 | ||
| 80 | #define SYSFS_TYPE_MASK 0x00ff | ||
| 81 | #define SYSFS_ROOT 0x0001 | ||
| 82 | #define SYSFS_DIR 0x0002 | ||
| 83 | #define SYSFS_KOBJ_ATTR 0x0004 | ||
| 84 | #define SYSFS_KOBJ_BIN_ATTR 0x0008 | ||
| 85 | #define SYSFS_KOBJ_LINK 0x0020 | ||
| 86 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | ||
| 87 | |||
| 88 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | ||
| 89 | #define SYSFS_FLAG_REMOVED 0x0100 | ||
| 90 | |||
| 91 | #ifdef CONFIG_SYSFS | 79 | #ifdef CONFIG_SYSFS |
| 92 | 80 | ||
| 93 | extern int sysfs_schedule_callback(struct kobject *kobj, | 81 | int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), |
| 94 | void (*func)(void *), void *data, struct module *owner); | 82 | void *data, struct module *owner); |
| 95 | |||
| 96 | extern int __must_check | ||
| 97 | sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd); | ||
| 98 | |||
| 99 | extern void | ||
| 100 | sysfs_remove_dir(struct kobject *); | ||
| 101 | |||
| 102 | extern int __must_check | ||
| 103 | sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, | ||
| 104 | const char *new_name); | ||
| 105 | |||
| 106 | extern int __must_check | ||
| 107 | sysfs_move_dir(struct kobject *, struct kobject *); | ||
| 108 | |||
| 109 | extern int __must_check | ||
| 110 | sysfs_create_file(struct kobject *, const struct attribute *); | ||
| 111 | 83 | ||
| 112 | extern int __must_check | 84 | int __must_check sysfs_create_dir(struct kobject *kobj); |
| 113 | sysfs_update_file(struct kobject *, const struct attribute *); | 85 | void sysfs_remove_dir(struct kobject *kobj); |
| 86 | int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); | ||
| 87 | int __must_check sysfs_move_dir(struct kobject *kobj, | ||
| 88 | struct kobject *new_parent_kobj); | ||
| 114 | 89 | ||
| 115 | extern int __must_check | 90 | int __must_check sysfs_create_file(struct kobject *kobj, |
| 116 | sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode); | 91 | const struct attribute *attr); |
| 117 | 92 | int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, | |
| 118 | extern void | 93 | mode_t mode); |
| 119 | sysfs_remove_file(struct kobject *, const struct attribute *); | 94 | void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); |
| 120 | |||
| 121 | extern int __must_check | ||
| 122 | sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name); | ||
| 123 | |||
| 124 | extern void | ||
| 125 | sysfs_remove_link(struct kobject *, const char * name); | ||
| 126 | 95 | ||
| 127 | int __must_check sysfs_create_bin_file(struct kobject *kobj, | 96 | int __must_check sysfs_create_bin_file(struct kobject *kobj, |
| 128 | struct bin_attribute *attr); | 97 | struct bin_attribute *attr); |
| 129 | void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); | 98 | void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); |
| 130 | 99 | ||
| 131 | int __must_check sysfs_create_group(struct kobject *, | 100 | int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, |
| 132 | const struct attribute_group *); | 101 | const char *name); |
| 133 | void sysfs_remove_group(struct kobject *, const struct attribute_group *); | 102 | void sysfs_remove_link(struct kobject *kobj, const char *name); |
| 103 | |||
| 104 | int __must_check sysfs_create_group(struct kobject *kobj, | ||
| 105 | const struct attribute_group *grp); | ||
| 106 | void sysfs_remove_group(struct kobject *kobj, | ||
| 107 | const struct attribute_group *grp); | ||
| 134 | int sysfs_add_file_to_group(struct kobject *kobj, | 108 | int sysfs_add_file_to_group(struct kobject *kobj, |
| 135 | const struct attribute *attr, const char *group); | 109 | const struct attribute *attr, const char *group); |
| 136 | void sysfs_remove_file_from_group(struct kobject *kobj, | 110 | void sysfs_remove_file_from_group(struct kobject *kobj, |
| 137 | const struct attribute *attr, const char *group); | 111 | const struct attribute *attr, const char *group); |
| 138 | |||
| 139 | void sysfs_notify(struct kobject * k, char *dir, char *attr); | ||
| 140 | |||
| 141 | 112 | ||
| 142 | extern int sysfs_make_shadowed_dir(struct kobject *kobj, | 113 | void sysfs_notify(struct kobject *kobj, char *dir, char *attr); |
| 143 | void * (*follow_link)(struct dentry *, struct nameidata *)); | ||
| 144 | extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj); | ||
| 145 | extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd); | ||
| 146 | 114 | ||
| 147 | extern int __must_check sysfs_init(void); | 115 | extern int __must_check sysfs_init(void); |
| 148 | 116 | ||
| @@ -154,75 +122,76 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, | |||
| 154 | return -ENOSYS; | 122 | return -ENOSYS; |
| 155 | } | 123 | } |
| 156 | 124 | ||
| 157 | static inline int sysfs_create_dir(struct kobject *kobj, | 125 | static inline int sysfs_create_dir(struct kobject *kobj) |
| 158 | struct sysfs_dirent *shadow_parent_sd) | ||
| 159 | { | 126 | { |
| 160 | return 0; | 127 | return 0; |
| 161 | } | 128 | } |
| 162 | 129 | ||
| 163 | static inline void sysfs_remove_dir(struct kobject * k) | 130 | static inline void sysfs_remove_dir(struct kobject *kobj) |
| 164 | { | 131 | { |
| 165 | ; | 132 | ; |
| 166 | } | 133 | } |
| 167 | 134 | ||
| 168 | static inline int sysfs_rename_dir(struct kobject *kobj, | 135 | static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) |
| 169 | struct sysfs_dirent *new_parent_sd, | ||
| 170 | const char *new_name) | ||
| 171 | { | 136 | { |
| 172 | return 0; | 137 | return 0; |
| 173 | } | 138 | } |
| 174 | 139 | ||
| 175 | static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent) | 140 | static inline int sysfs_move_dir(struct kobject *kobj, |
| 141 | struct kobject *new_parent_kobj) | ||
| 176 | { | 142 | { |
| 177 | return 0; | 143 | return 0; |
| 178 | } | 144 | } |
| 179 | 145 | ||
| 180 | static inline int sysfs_create_file(struct kobject * k, const struct attribute * a) | 146 | static inline int sysfs_create_file(struct kobject *kobj, |
| 147 | const struct attribute *attr) | ||
| 181 | { | 148 | { |
| 182 | return 0; | 149 | return 0; |
| 183 | } | 150 | } |
| 184 | 151 | ||
| 185 | static inline int sysfs_update_file(struct kobject * k, const struct attribute * a) | 152 | static inline int sysfs_chmod_file(struct kobject *kobj, |
| 186 | { | 153 | struct attribute *attr, mode_t mode) |
| 187 | return 0; | ||
| 188 | } | ||
| 189 | static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | ||
| 190 | { | 154 | { |
| 191 | return 0; | 155 | return 0; |
| 192 | } | 156 | } |
| 193 | 157 | ||
| 194 | static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a) | 158 | static inline void sysfs_remove_file(struct kobject *kobj, |
| 159 | const struct attribute *attr) | ||
| 195 | { | 160 | { |
| 196 | ; | 161 | ; |
| 197 | } | 162 | } |
| 198 | 163 | ||
| 199 | static inline int sysfs_create_link(struct kobject * k, struct kobject * t, const char * n) | 164 | static inline int sysfs_create_bin_file(struct kobject *kobj, |
| 165 | struct bin_attribute *attr) | ||
| 200 | { | 166 | { |
| 201 | return 0; | 167 | return 0; |
| 202 | } | 168 | } |
| 203 | 169 | ||
| 204 | static inline void sysfs_remove_link(struct kobject * k, const char * name) | 170 | static inline int sysfs_remove_bin_file(struct kobject *kobj, |
| 171 | struct bin_attribute *attr) | ||
| 205 | { | 172 | { |
| 206 | ; | 173 | return 0; |
| 207 | } | 174 | } |
| 208 | 175 | ||
| 209 | 176 | static inline int sysfs_create_link(struct kobject *kobj, | |
| 210 | static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a) | 177 | struct kobject *target, const char *name) |
| 211 | { | 178 | { |
| 212 | return 0; | 179 | return 0; |
| 213 | } | 180 | } |
| 214 | 181 | ||
| 215 | static inline int sysfs_remove_bin_file(struct kobject * k, struct bin_attribute * a) | 182 | static inline void sysfs_remove_link(struct kobject *kobj, const char *name) |
| 216 | { | 183 | { |
| 217 | return 0; | 184 | ; |
| 218 | } | 185 | } |
| 219 | 186 | ||
| 220 | static inline int sysfs_create_group(struct kobject * k, const struct attribute_group *g) | 187 | static inline int sysfs_create_group(struct kobject *kobj, |
| 188 | const struct attribute_group *grp) | ||
| 221 | { | 189 | { |
| 222 | return 0; | 190 | return 0; |
| 223 | } | 191 | } |
| 224 | 192 | ||
| 225 | static inline void sysfs_remove_group(struct kobject * k, const struct attribute_group * g) | 193 | static inline void sysfs_remove_group(struct kobject *kobj, |
| 194 | const struct attribute_group *grp) | ||
| 226 | { | 195 | { |
| 227 | ; | 196 | ; |
| 228 | } | 197 | } |
| @@ -238,14 +207,8 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj, | |||
| 238 | { | 207 | { |
| 239 | } | 208 | } |
| 240 | 209 | ||
| 241 | static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) | 210 | static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr) |
| 242 | { | ||
| 243 | } | ||
| 244 | |||
| 245 | static inline int sysfs_make_shadowed_dir(struct kobject *kobj, | ||
| 246 | void * (*follow_link)(struct dentry *, struct nameidata *)) | ||
| 247 | { | 211 | { |
| 248 | return 0; | ||
| 249 | } | 212 | } |
| 250 | 213 | ||
| 251 | static inline int __must_check sysfs_init(void) | 214 | static inline int __must_check sysfs_init(void) |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 6570719eafdf..60478f6e5dc6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | * (Note: the *_driver.minor_start values 1, 64, 128, 192 are | 21 | * (Note: the *_driver.minor_start values 1, 64, 128, 192 are |
| 22 | * hardcoded at present.) | 22 | * hardcoded at present.) |
| 23 | */ | 23 | */ |
| 24 | #define NR_PTYS CONFIG_LEGACY_PTY_COUNT /* Number of legacy ptys */ | ||
| 25 | #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ | 24 | #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ |
| 26 | #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ | 25 | #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ |
| 27 | #define NR_LDISCS 17 | 26 | #define NR_LDISCS 17 |
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/include/linux/video_output.h b/include/linux/video_output.h index e63e0c03ee0d..2fb46bc9340d 100644 --- a/include/linux/video_output.h +++ b/include/linux/video_output.h | |||
| @@ -31,9 +31,9 @@ struct output_properties { | |||
| 31 | struct output_device { | 31 | struct output_device { |
| 32 | int request_state; | 32 | int request_state; |
| 33 | struct output_properties *props; | 33 | struct output_properties *props; |
| 34 | struct class_device class_dev; | 34 | struct device dev; |
| 35 | }; | 35 | }; |
| 36 | #define to_output_device(obj) container_of(obj, struct output_device, class_dev) | 36 | #define to_output_device(obj) container_of(obj, struct output_device, dev) |
| 37 | struct output_device *video_output_register(const char *name, | 37 | struct output_device *video_output_register(const char *name, |
| 38 | struct device *dev, | 38 | struct device *dev, |
| 39 | void *devdata, | 39 | void *devdata, |
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; |
diff --git a/lib/Makefile b/lib/Makefile index 4f3f3e256501..6c4ea33bb2cb 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -10,7 +10,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ | |||
| 10 | lib-$(CONFIG_MMU) += ioremap.o | 10 | lib-$(CONFIG_MMU) += ioremap.o |
| 11 | lib-$(CONFIG_SMP) += cpumask.o | 11 | lib-$(CONFIG_SMP) += cpumask.o |
| 12 | 12 | ||
| 13 | lib-y += kobject.o kref.o kobject_uevent.o klist.o | 13 | lib-y += kobject.o kref.o klist.o |
| 14 | 14 | ||
| 15 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 15 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
| 16 | bust_spinlocks.o hexdump.o kasprintf.o | 16 | bust_spinlocks.o hexdump.o kasprintf.o |
| @@ -20,6 +20,7 @@ CFLAGS_kobject.o += -DDEBUG | |||
| 20 | CFLAGS_kobject_uevent.o += -DDEBUG | 20 | CFLAGS_kobject_uevent.o += -DDEBUG |
| 21 | endif | 21 | endif |
| 22 | 22 | ||
| 23 | lib-$(CONFIG_HOTPLUG) += kobject_uevent.o | ||
| 23 | obj-$(CONFIG_GENERIC_IOMAP) += iomap.o | 24 | obj-$(CONFIG_GENERIC_IOMAP) += iomap.o |
| 24 | obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o | 25 | obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o |
| 25 | obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o | 26 | obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o |
diff --git a/lib/kobject.c b/lib/kobject.c index 4b08e0ff95c8..03d40360ff1b 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | * kobject.c - library routines for handling generic kernel objects | 2 | * kobject.c - library routines for handling generic kernel objects |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org> | 4 | * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org> |
| 5 | * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com> | ||
| 6 | * Copyright (c) 2006-2007 Novell Inc. | ||
| 5 | * | 7 | * |
| 6 | * This file is released under the GPLv2. | 8 | * This file is released under the GPLv2. |
| 7 | * | 9 | * |
| @@ -44,11 +46,11 @@ static int populate_dir(struct kobject * kobj) | |||
| 44 | return error; | 46 | return error; |
| 45 | } | 47 | } |
| 46 | 48 | ||
| 47 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | 49 | static int create_dir(struct kobject * kobj) |
| 48 | { | 50 | { |
| 49 | int error = 0; | 51 | int error = 0; |
| 50 | if (kobject_name(kobj)) { | 52 | if (kobject_name(kobj)) { |
| 51 | error = sysfs_create_dir(kobj, shadow_parent); | 53 | error = sysfs_create_dir(kobj); |
| 52 | if (!error) { | 54 | if (!error) { |
| 53 | if ((error = populate_dir(kobj))) | 55 | if ((error = populate_dir(kobj))) |
| 54 | sysfs_remove_dir(kobj); | 56 | sysfs_remove_dir(kobj); |
| @@ -131,7 +133,6 @@ void kobject_init(struct kobject * kobj) | |||
| 131 | return; | 133 | return; |
| 132 | kref_init(&kobj->kref); | 134 | kref_init(&kobj->kref); |
| 133 | INIT_LIST_HEAD(&kobj->entry); | 135 | INIT_LIST_HEAD(&kobj->entry); |
| 134 | init_waitqueue_head(&kobj->poll); | ||
| 135 | kobj->kset = kset_get(kobj->kset); | 136 | kobj->kset = kset_get(kobj->kset); |
| 136 | } | 137 | } |
| 137 | 138 | ||
| @@ -157,12 +158,11 @@ static void unlink(struct kobject * kobj) | |||
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | /** | 160 | /** |
| 160 | * kobject_shadow_add - add an object to the hierarchy. | 161 | * kobject_add - add an object to the hierarchy. |
| 161 | * @kobj: object. | 162 | * @kobj: object. |
| 162 | * @shadow_parent: sysfs directory to add to. | ||
| 163 | */ | 163 | */ |
| 164 | 164 | ||
| 165 | int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | 165 | int kobject_add(struct kobject * kobj) |
| 166 | { | 166 | { |
| 167 | int error = 0; | 167 | int error = 0; |
| 168 | struct kobject * parent; | 168 | struct kobject * parent; |
| @@ -170,7 +170,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | |||
| 170 | if (!(kobj = kobject_get(kobj))) | 170 | if (!(kobj = kobject_get(kobj))) |
| 171 | return -ENOENT; | 171 | return -ENOENT; |
| 172 | if (!kobj->k_name) | 172 | if (!kobj->k_name) |
| 173 | kobj->k_name = kobj->name; | 173 | kobject_set_name(kobj, "NO_NAME"); |
| 174 | if (!*kobj->k_name) { | 174 | if (!*kobj->k_name) { |
| 175 | pr_debug("kobject attempted to be registered with no name!\n"); | 175 | pr_debug("kobject attempted to be registered with no name!\n"); |
| 176 | WARN_ON(1); | 176 | WARN_ON(1); |
| @@ -181,7 +181,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | |||
| 181 | 181 | ||
| 182 | pr_debug("kobject %s: registering. parent: %s, set: %s\n", | 182 | pr_debug("kobject %s: registering. parent: %s, set: %s\n", |
| 183 | kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", | 183 | kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", |
| 184 | kobj->kset ? kobj->kset->kobj.name : "<NULL>" ); | 184 | kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" ); |
| 185 | 185 | ||
| 186 | if (kobj->kset) { | 186 | if (kobj->kset) { |
| 187 | spin_lock(&kobj->kset->list_lock); | 187 | spin_lock(&kobj->kset->list_lock); |
| @@ -194,7 +194,7 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | |||
| 194 | kobj->parent = parent; | 194 | kobj->parent = parent; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | error = create_dir(kobj, shadow_parent); | 197 | error = create_dir(kobj); |
| 198 | if (error) { | 198 | if (error) { |
| 199 | /* unlink does the kobject_put() for us */ | 199 | /* unlink does the kobject_put() for us */ |
| 200 | unlink(kobj); | 200 | unlink(kobj); |
| @@ -216,16 +216,6 @@ int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) | |||
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | /** | 218 | /** |
| 219 | * kobject_add - add an object to the hierarchy. | ||
| 220 | * @kobj: object. | ||
| 221 | */ | ||
| 222 | int kobject_add(struct kobject * kobj) | ||
| 223 | { | ||
| 224 | return kobject_shadow_add(kobj, NULL); | ||
| 225 | } | ||
| 226 | |||
| 227 | |||
| 228 | /** | ||
| 229 | * kobject_register - initialize and add an object. | 219 | * kobject_register - initialize and add an object. |
| 230 | * @kobj: object in question. | 220 | * @kobj: object in question. |
| 231 | */ | 221 | */ |
| @@ -255,54 +245,50 @@ int kobject_register(struct kobject * kobj) | |||
| 255 | int kobject_set_name(struct kobject * kobj, const char * fmt, ...) | 245 | int kobject_set_name(struct kobject * kobj, const char * fmt, ...) |
| 256 | { | 246 | { |
| 257 | int error = 0; | 247 | int error = 0; |
| 258 | int limit = KOBJ_NAME_LEN; | 248 | int limit; |
| 259 | int need; | 249 | int need; |
| 260 | va_list args; | 250 | va_list args; |
| 261 | char * name; | 251 | char *name; |
| 262 | 252 | ||
| 263 | /* | 253 | /* find out how big a buffer we need */ |
| 264 | * First, try the static array | 254 | name = kmalloc(1024, GFP_KERNEL); |
| 265 | */ | 255 | if (!name) { |
| 266 | va_start(args,fmt); | 256 | error = -ENOMEM; |
| 267 | need = vsnprintf(kobj->name,limit,fmt,args); | 257 | goto done; |
| 258 | } | ||
| 259 | va_start(args, fmt); | ||
| 260 | need = vsnprintf(name, 1024, fmt, args); | ||
| 268 | va_end(args); | 261 | va_end(args); |
| 269 | if (need < limit) | 262 | kfree(name); |
| 270 | name = kobj->name; | 263 | |
| 271 | else { | 264 | /* Allocate the new space and copy the string in */ |
| 272 | /* | 265 | limit = need + 1; |
| 273 | * Need more space? Allocate it and try again | 266 | name = kmalloc(limit, GFP_KERNEL); |
| 274 | */ | 267 | if (!name) { |
| 275 | limit = need + 1; | 268 | error = -ENOMEM; |
| 276 | name = kmalloc(limit,GFP_KERNEL); | 269 | goto done; |
| 277 | if (!name) { | 270 | } |
| 278 | error = -ENOMEM; | 271 | va_start(args, fmt); |
| 279 | goto Done; | 272 | need = vsnprintf(name, limit, fmt, args); |
| 280 | } | 273 | va_end(args); |
| 281 | va_start(args,fmt); | 274 | |
| 282 | need = vsnprintf(name,limit,fmt,args); | 275 | /* something wrong with the string we copied? */ |
| 283 | va_end(args); | 276 | if (need >= limit) { |
| 284 | 277 | kfree(name); | |
| 285 | /* Still? Give up. */ | 278 | error = -EFAULT; |
| 286 | if (need >= limit) { | 279 | goto done; |
| 287 | kfree(name); | ||
| 288 | error = -EFAULT; | ||
| 289 | goto Done; | ||
| 290 | } | ||
| 291 | } | 280 | } |
| 292 | 281 | ||
| 293 | /* Free the old name, if necessary. */ | 282 | /* Free the old name, if necessary. */ |
| 294 | if (kobj->k_name && kobj->k_name != kobj->name) | 283 | kfree(kobj->k_name); |
| 295 | kfree(kobj->k_name); | ||
| 296 | 284 | ||
| 297 | /* Now, set the new name */ | 285 | /* Now, set the new name */ |
| 298 | kobj->k_name = name; | 286 | kobj->k_name = name; |
| 299 | Done: | 287 | done: |
| 300 | return error; | 288 | return error; |
| 301 | } | 289 | } |
| 302 | |||
| 303 | EXPORT_SYMBOL(kobject_set_name); | 290 | EXPORT_SYMBOL(kobject_set_name); |
| 304 | 291 | ||
| 305 | |||
| 306 | /** | 292 | /** |
| 307 | * kobject_rename - change the name of an object | 293 | * kobject_rename - change the name of an object |
| 308 | * @kobj: object in question. | 294 | * @kobj: object in question. |
| @@ -338,7 +324,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name) | |||
| 338 | /* Note : if we want to send the new name alone, not the full path, | 324 | /* Note : if we want to send the new name alone, not the full path, |
| 339 | * we could probably use kobject_name(kobj); */ | 325 | * we could probably use kobject_name(kobj); */ |
| 340 | 326 | ||
| 341 | error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name); | 327 | error = sysfs_rename_dir(kobj, new_name); |
| 342 | 328 | ||
| 343 | /* This function is mostly/only used for network interface. | 329 | /* This function is mostly/only used for network interface. |
| 344 | * Some hotplug package track interfaces by their name and | 330 | * Some hotplug package track interfaces by their name and |
| @@ -355,27 +341,6 @@ out: | |||
| 355 | } | 341 | } |
| 356 | 342 | ||
| 357 | /** | 343 | /** |
| 358 | * kobject_rename - change the name of an object | ||
| 359 | * @kobj: object in question. | ||
| 360 | * @new_parent: object's new parent | ||
| 361 | * @new_name: object's new name | ||
| 362 | */ | ||
| 363 | |||
| 364 | int kobject_shadow_rename(struct kobject *kobj, | ||
| 365 | struct sysfs_dirent *new_parent, const char *new_name) | ||
| 366 | { | ||
| 367 | int error = 0; | ||
| 368 | |||
| 369 | kobj = kobject_get(kobj); | ||
| 370 | if (!kobj) | ||
| 371 | return -EINVAL; | ||
| 372 | error = sysfs_rename_dir(kobj, new_parent, new_name); | ||
| 373 | kobject_put(kobj); | ||
| 374 | |||
| 375 | return error; | ||
| 376 | } | ||
| 377 | |||
| 378 | /** | ||
| 379 | * kobject_move - move object to another parent | 344 | * kobject_move - move object to another parent |
| 380 | * @kobj: object in question. | 345 | * @kobj: object in question. |
| 381 | * @new_parent: object's new parent (can be NULL) | 346 | * @new_parent: object's new parent (can be NULL) |
| @@ -477,13 +442,16 @@ void kobject_cleanup(struct kobject * kobj) | |||
| 477 | struct kobj_type * t = get_ktype(kobj); | 442 | struct kobj_type * t = get_ktype(kobj); |
| 478 | struct kset * s = kobj->kset; | 443 | struct kset * s = kobj->kset; |
| 479 | struct kobject * parent = kobj->parent; | 444 | struct kobject * parent = kobj->parent; |
| 445 | const char *name = kobj->k_name; | ||
| 480 | 446 | ||
| 481 | pr_debug("kobject %s: cleaning up\n",kobject_name(kobj)); | 447 | pr_debug("kobject %s: cleaning up\n",kobject_name(kobj)); |
| 482 | if (kobj->k_name != kobj->name) | 448 | if (t && t->release) { |
| 483 | kfree(kobj->k_name); | ||
| 484 | kobj->k_name = NULL; | ||
| 485 | if (t && t->release) | ||
| 486 | t->release(kobj); | 449 | t->release(kobj); |
| 450 | /* If we have a release function, we can guess that this was | ||
| 451 | * not a statically allocated kobject, so we should be safe to | ||
| 452 | * free the name */ | ||
| 453 | kfree(name); | ||
| 454 | } | ||
| 487 | if (s) | 455 | if (s) |
| 488 | kset_put(s); | 456 | kset_put(s); |
| 489 | kobject_put(parent); | 457 | kobject_put(parent); |
| @@ -651,11 +619,6 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name) | |||
| 651 | return ret; | 619 | return ret; |
| 652 | } | 620 | } |
| 653 | 621 | ||
| 654 | void subsystem_init(struct kset *s) | ||
| 655 | { | ||
| 656 | kset_init(s); | ||
| 657 | } | ||
| 658 | |||
| 659 | int subsystem_register(struct kset *s) | 622 | int subsystem_register(struct kset *s) |
| 660 | { | 623 | { |
| 661 | return kset_register(s); | 624 | return kset_register(s); |
| @@ -679,9 +642,9 @@ int subsys_create_file(struct kset *s, struct subsys_attribute *a) | |||
| 679 | if (!s || !a) | 642 | if (!s || !a) |
| 680 | return -EINVAL; | 643 | return -EINVAL; |
| 681 | 644 | ||
| 682 | if (subsys_get(s)) { | 645 | if (kset_get(s)) { |
| 683 | error = sysfs_create_file(&s->kobj, &a->attr); | 646 | error = sysfs_create_file(&s->kobj, &a->attr); |
| 684 | subsys_put(s); | 647 | kset_put(s); |
| 685 | } | 648 | } |
| 686 | return error; | 649 | return error; |
| 687 | } | 650 | } |
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index e06a8dcec0f0..2e4eae5b0824 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c | |||
| @@ -22,31 +22,62 @@ | |||
| 22 | #include <linux/kobject.h> | 22 | #include <linux/kobject.h> |
| 23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
| 24 | 24 | ||
| 25 | #define BUFFER_SIZE 2048 /* buffer for the variables */ | ||
| 26 | #define NUM_ENVP 32 /* number of env pointers */ | ||
| 27 | 25 | ||
| 28 | /* the strings here must match the enum in include/linux/kobject.h */ | ||
| 29 | const char *kobject_actions[] = { | ||
| 30 | "add", | ||
| 31 | "remove", | ||
| 32 | "change", | ||
| 33 | "move", | ||
| 34 | "online", | ||
| 35 | "offline", | ||
| 36 | }; | ||
| 37 | |||
| 38 | #if defined(CONFIG_HOTPLUG) | ||
| 39 | u64 uevent_seqnum; | 26 | u64 uevent_seqnum; |
| 40 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug"; | 27 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; |
| 41 | static DEFINE_SPINLOCK(sequence_lock); | 28 | static DEFINE_SPINLOCK(sequence_lock); |
| 42 | #if defined(CONFIG_NET) | 29 | #if defined(CONFIG_NET) |
| 43 | static struct sock *uevent_sock; | 30 | static struct sock *uevent_sock; |
| 44 | #endif | 31 | #endif |
| 45 | 32 | ||
| 33 | /* the strings here must match the enum in include/linux/kobject.h */ | ||
| 34 | static const char *kobject_actions[] = { | ||
| 35 | [KOBJ_ADD] = "add", | ||
| 36 | [KOBJ_REMOVE] = "remove", | ||
| 37 | [KOBJ_CHANGE] = "change", | ||
| 38 | [KOBJ_MOVE] = "move", | ||
| 39 | [KOBJ_ONLINE] = "online", | ||
| 40 | [KOBJ_OFFLINE] = "offline", | ||
| 41 | }; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * kobject_action_type - translate action string to numeric type | ||
| 45 | * | ||
| 46 | * @buf: buffer containing the action string, newline is ignored | ||
| 47 | * @len: length of buffer | ||
| 48 | * @type: pointer to the location to store the action type | ||
| 49 | * | ||
| 50 | * Returns 0 if the action string was recognized. | ||
| 51 | */ | ||
| 52 | int kobject_action_type(const char *buf, size_t count, | ||
| 53 | enum kobject_action *type) | ||
| 54 | { | ||
| 55 | enum kobject_action action; | ||
| 56 | int ret = -EINVAL; | ||
| 57 | |||
| 58 | if (count && buf[count-1] == '\n') | ||
| 59 | count--; | ||
| 60 | |||
| 61 | if (!count) | ||
| 62 | goto out; | ||
| 63 | |||
| 64 | for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { | ||
| 65 | if (strncmp(kobject_actions[action], buf, count) != 0) | ||
| 66 | continue; | ||
| 67 | if (kobject_actions[action][count] != '\0') | ||
| 68 | continue; | ||
| 69 | *type = action; | ||
| 70 | ret = 0; | ||
| 71 | break; | ||
| 72 | } | ||
| 73 | out: | ||
| 74 | return ret; | ||
| 75 | } | ||
| 76 | |||
| 46 | /** | 77 | /** |
| 47 | * kobject_uevent_env - send an uevent with environmental data | 78 | * kobject_uevent_env - send an uevent with environmental data |
| 48 | * | 79 | * |
| 49 | * @action: action that is happening (usually KOBJ_MOVE) | 80 | * @action: action that is happening |
| 50 | * @kobj: struct kobject that the action is happening to | 81 | * @kobj: struct kobject that the action is happening to |
| 51 | * @envp_ext: pointer to environmental data | 82 | * @envp_ext: pointer to environmental data |
| 52 | * | 83 | * |
| @@ -54,36 +85,26 @@ static struct sock *uevent_sock; | |||
| 54 | * corresponding error when it fails. | 85 | * corresponding error when it fails. |
| 55 | */ | 86 | */ |
| 56 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | 87 | int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, |
| 57 | char *envp_ext[]) | 88 | char *envp_ext[]) |
| 58 | { | 89 | { |
| 59 | char **envp; | 90 | struct kobj_uevent_env *env; |
| 60 | char *buffer; | 91 | const char *action_string = kobject_actions[action]; |
| 61 | char *scratch; | ||
| 62 | const char *action_string; | ||
| 63 | const char *devpath = NULL; | 92 | const char *devpath = NULL; |
| 64 | const char *subsystem; | 93 | const char *subsystem; |
| 65 | struct kobject *top_kobj; | 94 | struct kobject *top_kobj; |
| 66 | struct kset *kset; | 95 | struct kset *kset; |
| 67 | struct kset_uevent_ops *uevent_ops; | 96 | struct kset_uevent_ops *uevent_ops; |
| 68 | u64 seq; | 97 | u64 seq; |
| 69 | char *seq_buff; | ||
| 70 | int i = 0; | 98 | int i = 0; |
| 71 | int retval = 0; | 99 | int retval = 0; |
| 72 | int j; | ||
| 73 | 100 | ||
| 74 | pr_debug("%s\n", __FUNCTION__); | 101 | pr_debug("%s\n", __FUNCTION__); |
| 75 | 102 | ||
| 76 | action_string = kobject_actions[action]; | ||
| 77 | if (!action_string) { | ||
| 78 | pr_debug("kobject attempted to send uevent without action_string!\n"); | ||
| 79 | return -EINVAL; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* search the kset we belong to */ | 103 | /* search the kset we belong to */ |
| 83 | top_kobj = kobj; | 104 | top_kobj = kobj; |
| 84 | while (!top_kobj->kset && top_kobj->parent) { | 105 | while (!top_kobj->kset && top_kobj->parent) |
| 85 | top_kobj = top_kobj->parent; | 106 | top_kobj = top_kobj->parent; |
| 86 | } | 107 | |
| 87 | if (!top_kobj->kset) { | 108 | if (!top_kobj->kset) { |
| 88 | pr_debug("kobject attempted to send uevent without kset!\n"); | 109 | pr_debug("kobject attempted to send uevent without kset!\n"); |
| 89 | return -EINVAL; | 110 | return -EINVAL; |
| @@ -92,7 +113,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 92 | kset = top_kobj->kset; | 113 | kset = top_kobj->kset; |
| 93 | uevent_ops = kset->uevent_ops; | 114 | uevent_ops = kset->uevent_ops; |
| 94 | 115 | ||
| 95 | /* skip the event, if the filter returns zero. */ | 116 | /* skip the event, if the filter returns zero. */ |
| 96 | if (uevent_ops && uevent_ops->filter) | 117 | if (uevent_ops && uevent_ops->filter) |
| 97 | if (!uevent_ops->filter(kset, kobj)) { | 118 | if (!uevent_ops->filter(kset, kobj)) { |
| 98 | pr_debug("kobject filter function caused the event to drop!\n"); | 119 | pr_debug("kobject filter function caused the event to drop!\n"); |
| @@ -109,18 +130,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 109 | return 0; | 130 | return 0; |
| 110 | } | 131 | } |
| 111 | 132 | ||
| 112 | /* environment index */ | 133 | /* environment buffer */ |
| 113 | envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); | 134 | env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); |
| 114 | if (!envp) | 135 | if (!env) |
| 115 | return -ENOMEM; | 136 | return -ENOMEM; |
| 116 | 137 | ||
| 117 | /* environment values */ | ||
| 118 | buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); | ||
| 119 | if (!buffer) { | ||
| 120 | retval = -ENOMEM; | ||
| 121 | goto exit; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* complete object path */ | 138 | /* complete object path */ |
| 125 | devpath = kobject_get_path(kobj, GFP_KERNEL); | 139 | devpath = kobject_get_path(kobj, GFP_KERNEL); |
| 126 | if (!devpath) { | 140 | if (!devpath) { |
| @@ -128,29 +142,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 128 | goto exit; | 142 | goto exit; |
| 129 | } | 143 | } |
| 130 | 144 | ||
| 131 | /* event environemnt for helper process only */ | ||
| 132 | envp[i++] = "HOME=/"; | ||
| 133 | envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | ||
| 134 | |||
| 135 | /* default keys */ | 145 | /* default keys */ |
| 136 | scratch = buffer; | 146 | retval = add_uevent_var(env, "ACTION=%s", action_string); |
| 137 | envp [i++] = scratch; | 147 | if (retval) |
| 138 | scratch += sprintf(scratch, "ACTION=%s", action_string) + 1; | 148 | goto exit; |
| 139 | envp [i++] = scratch; | 149 | retval = add_uevent_var(env, "DEVPATH=%s", devpath); |
| 140 | scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; | 150 | if (retval) |
| 141 | envp [i++] = scratch; | 151 | goto exit; |
| 142 | scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; | 152 | retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); |
| 143 | for (j = 0; envp_ext && envp_ext[j]; j++) | 153 | if (retval) |
| 144 | envp[i++] = envp_ext[j]; | 154 | goto exit; |
| 145 | /* just reserve the space, overwrite it after kset call has returned */ | 155 | |
| 146 | envp[i++] = seq_buff = scratch; | 156 | /* keys passed in from the caller */ |
| 147 | scratch += strlen("SEQNUM=18446744073709551616") + 1; | 157 | if (envp_ext) { |
| 158 | for (i = 0; envp_ext[i]; i++) { | ||
| 159 | retval = add_uevent_var(env, envp_ext[i]); | ||
| 160 | if (retval) | ||
| 161 | goto exit; | ||
| 162 | } | ||
| 163 | } | ||
| 148 | 164 | ||
| 149 | /* let the kset specific function add its stuff */ | 165 | /* let the kset specific function add its stuff */ |
| 150 | if (uevent_ops && uevent_ops->uevent) { | 166 | if (uevent_ops && uevent_ops->uevent) { |
| 151 | retval = uevent_ops->uevent(kset, kobj, | 167 | retval = uevent_ops->uevent(kset, kobj, env); |
| 152 | &envp[i], NUM_ENVP - i, scratch, | ||
| 153 | BUFFER_SIZE - (scratch - buffer)); | ||
| 154 | if (retval) { | 168 | if (retval) { |
| 155 | pr_debug ("%s - uevent() returned %d\n", | 169 | pr_debug ("%s - uevent() returned %d\n", |
| 156 | __FUNCTION__, retval); | 170 | __FUNCTION__, retval); |
| @@ -158,11 +172,13 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 158 | } | 172 | } |
| 159 | } | 173 | } |
| 160 | 174 | ||
| 161 | /* we will send an event, request a new sequence number */ | 175 | /* we will send an event, so request a new sequence number */ |
| 162 | spin_lock(&sequence_lock); | 176 | spin_lock(&sequence_lock); |
| 163 | seq = ++uevent_seqnum; | 177 | seq = ++uevent_seqnum; |
| 164 | spin_unlock(&sequence_lock); | 178 | spin_unlock(&sequence_lock); |
| 165 | sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq); | 179 | retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); |
| 180 | if (retval) | ||
| 181 | goto exit; | ||
| 166 | 182 | ||
| 167 | #if defined(CONFIG_NET) | 183 | #if defined(CONFIG_NET) |
| 168 | /* send netlink message */ | 184 | /* send netlink message */ |
| @@ -172,17 +188,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 172 | 188 | ||
| 173 | /* allocate message with the maximum possible size */ | 189 | /* allocate message with the maximum possible size */ |
| 174 | len = strlen(action_string) + strlen(devpath) + 2; | 190 | len = strlen(action_string) + strlen(devpath) + 2; |
| 175 | skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL); | 191 | skb = alloc_skb(len + env->buflen, GFP_KERNEL); |
| 176 | if (skb) { | 192 | if (skb) { |
| 193 | char *scratch; | ||
| 194 | |||
| 177 | /* add header */ | 195 | /* add header */ |
| 178 | scratch = skb_put(skb, len); | 196 | scratch = skb_put(skb, len); |
| 179 | sprintf(scratch, "%s@%s", action_string, devpath); | 197 | sprintf(scratch, "%s@%s", action_string, devpath); |
| 180 | 198 | ||
| 181 | /* copy keys to our continuous event payload buffer */ | 199 | /* copy keys to our continuous event payload buffer */ |
| 182 | for (i = 2; envp[i]; i++) { | 200 | for (i = 0; i < env->envp_idx; i++) { |
| 183 | len = strlen(envp[i]) + 1; | 201 | len = strlen(env->envp[i]) + 1; |
| 184 | scratch = skb_put(skb, len); | 202 | scratch = skb_put(skb, len); |
| 185 | strcpy(scratch, envp[i]); | 203 | strcpy(scratch, env->envp[i]); |
| 186 | } | 204 | } |
| 187 | 205 | ||
| 188 | NETLINK_CB(skb).dst_group = 1; | 206 | NETLINK_CB(skb).dst_group = 1; |
| @@ -198,13 +216,19 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, | |||
| 198 | argv [0] = uevent_helper; | 216 | argv [0] = uevent_helper; |
| 199 | argv [1] = (char *)subsystem; | 217 | argv [1] = (char *)subsystem; |
| 200 | argv [2] = NULL; | 218 | argv [2] = NULL; |
| 201 | call_usermodehelper (argv[0], argv, envp, UMH_WAIT_EXEC); | 219 | retval = add_uevent_var(env, "HOME=/"); |
| 220 | if (retval) | ||
| 221 | goto exit; | ||
| 222 | retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); | ||
| 223 | if (retval) | ||
| 224 | goto exit; | ||
| 225 | |||
| 226 | call_usermodehelper (argv[0], argv, env->envp, UMH_WAIT_EXEC); | ||
| 202 | } | 227 | } |
| 203 | 228 | ||
| 204 | exit: | 229 | exit: |
| 205 | kfree(devpath); | 230 | kfree(devpath); |
| 206 | kfree(buffer); | 231 | kfree(env); |
| 207 | kfree(envp); | ||
| 208 | return retval; | 232 | return retval; |
| 209 | } | 233 | } |
| 210 | 234 | ||
| @@ -213,7 +237,7 @@ EXPORT_SYMBOL_GPL(kobject_uevent_env); | |||
| 213 | /** | 237 | /** |
| 214 | * kobject_uevent - notify userspace by ending an uevent | 238 | * kobject_uevent - notify userspace by ending an uevent |
| 215 | * | 239 | * |
| 216 | * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) | 240 | * @action: action that is happening |
| 217 | * @kobj: struct kobject that the action is happening to | 241 | * @kobj: struct kobject that the action is happening to |
| 218 | * | 242 | * |
| 219 | * Returns 0 if kobject_uevent() is completed with success or the | 243 | * Returns 0 if kobject_uevent() is completed with success or the |
| @@ -227,52 +251,38 @@ int kobject_uevent(struct kobject *kobj, enum kobject_action action) | |||
| 227 | EXPORT_SYMBOL_GPL(kobject_uevent); | 251 | EXPORT_SYMBOL_GPL(kobject_uevent); |
| 228 | 252 | ||
| 229 | /** | 253 | /** |
| 230 | * add_uevent_var - helper for creating event variables | 254 | * add_uevent_var - add key value string to the environment buffer |
| 231 | * @envp: Pointer to table of environment variables, as passed into | 255 | * @env: environment buffer structure |
| 232 | * uevent() method. | 256 | * @format: printf format for the key=value pair |
| 233 | * @num_envp: Number of environment variable slots available, as | ||
| 234 | * passed into uevent() method. | ||
| 235 | * @cur_index: Pointer to current index into @envp. It should be | ||
| 236 | * initialized to 0 before the first call to add_uevent_var(), | ||
| 237 | * and will be incremented on success. | ||
| 238 | * @buffer: Pointer to buffer for environment variables, as passed | ||
| 239 | * into uevent() method. | ||
| 240 | * @buffer_size: Length of @buffer, as passed into uevent() method. | ||
| 241 | * @cur_len: Pointer to current length of space used in @buffer. | ||
| 242 | * Should be initialized to 0 before the first call to | ||
| 243 | * add_uevent_var(), and will be incremented on success. | ||
| 244 | * @format: Format for creating environment variable (of the form | ||
| 245 | * "XXX=%x") for snprintf(). | ||
| 246 | * | 257 | * |
| 247 | * Returns 0 if environment variable was added successfully or -ENOMEM | 258 | * Returns 0 if environment variable was added successfully or -ENOMEM |
| 248 | * if no space was available. | 259 | * if no space was available. |
| 249 | */ | 260 | */ |
| 250 | int add_uevent_var(char **envp, int num_envp, int *cur_index, | 261 | int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) |
| 251 | char *buffer, int buffer_size, int *cur_len, | ||
| 252 | const char *format, ...) | ||
| 253 | { | 262 | { |
| 254 | va_list args; | 263 | va_list args; |
| 264 | int len; | ||
| 255 | 265 | ||
| 256 | /* | 266 | if (env->envp_idx >= ARRAY_SIZE(env->envp)) { |
| 257 | * We check against num_envp - 1 to make sure there is at | 267 | printk(KERN_ERR "add_uevent_var: too many keys\n"); |
| 258 | * least one slot left after we return, since kobject_uevent() | 268 | WARN_ON(1); |
| 259 | * needs to set the last slot to NULL. | ||
| 260 | */ | ||
| 261 | if (*cur_index >= num_envp - 1) | ||
| 262 | return -ENOMEM; | 269 | return -ENOMEM; |
| 263 | 270 | } | |
| 264 | envp[*cur_index] = buffer + *cur_len; | ||
| 265 | 271 | ||
| 266 | va_start(args, format); | 272 | va_start(args, format); |
| 267 | *cur_len += vsnprintf(envp[*cur_index], | 273 | len = vsnprintf(&env->buf[env->buflen], |
| 268 | max(buffer_size - *cur_len, 0), | 274 | sizeof(env->buf) - env->buflen, |
| 269 | format, args) + 1; | 275 | format, args); |
| 270 | va_end(args); | 276 | va_end(args); |
| 271 | 277 | ||
| 272 | if (*cur_len > buffer_size) | 278 | if (len >= (sizeof(env->buf) - env->buflen)) { |
| 279 | printk(KERN_ERR "add_uevent_var: buffer size too small\n"); | ||
| 280 | WARN_ON(1); | ||
| 273 | return -ENOMEM; | 281 | return -ENOMEM; |
| 282 | } | ||
| 274 | 283 | ||
| 275 | (*cur_index)++; | 284 | env->envp[env->envp_idx++] = &env->buf[env->buflen]; |
| 285 | env->buflen += len + 1; | ||
| 276 | return 0; | 286 | return 0; |
| 277 | } | 287 | } |
| 278 | EXPORT_SYMBOL_GPL(add_uevent_var); | 288 | EXPORT_SYMBOL_GPL(add_uevent_var); |
| @@ -293,5 +303,3 @@ static int __init kobject_uevent_init(void) | |||
| 293 | 303 | ||
| 294 | postcore_initcall(kobject_uevent_init); | 304 | postcore_initcall(kobject_uevent_init); |
| 295 | #endif | 305 | #endif |
| 296 | |||
| 297 | #endif /* CONFIG_HOTPLUG */ | ||
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index f094a0879c16..9ef07eda2c43 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c | |||
| @@ -105,10 +105,9 @@ static struct class_device_attribute *atm_attrs[] = { | |||
| 105 | NULL | 105 | NULL |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) | 108 | static int atm_uevent(struct class_device *cdev, struct kobj_uevent_env *env) |
| 109 | { | 109 | { |
| 110 | struct atm_dev *adev; | 110 | struct atm_dev *adev; |
| 111 | int i = 0, len = 0; | ||
| 112 | 111 | ||
| 113 | if (!cdev) | 112 | if (!cdev) |
| 114 | return -ENODEV; | 113 | return -ENODEV; |
| @@ -117,11 +116,9 @@ static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char | |||
| 117 | if (!adev) | 116 | if (!adev) |
| 118 | return -ENODEV; | 117 | return -ENODEV; |
| 119 | 118 | ||
| 120 | if (add_uevent_var(envp, num_envp, &i, buf, size, &len, | 119 | if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number)) |
| 121 | "NAME=%s%d", adev->type, adev->number)) | ||
| 122 | return -ENOMEM; | 120 | return -ENOMEM; |
| 123 | 121 | ||
| 124 | envp[i] = NULL; | ||
| 125 | return 0; | 122 | return 0; |
| 126 | } | 123 | } |
| 127 | 124 | ||
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index c65f54e0e27f..3312e8f2abe4 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
| @@ -435,7 +435,7 @@ int br_sysfs_addbr(struct net_device *dev) | |||
| 435 | err = kobject_register(&br->ifobj); | 435 | err = kobject_register(&br->ifobj); |
| 436 | if (err) { | 436 | if (err) { |
| 437 | pr_info("%s: can't add kobject (directory) %s/%s\n", | 437 | pr_info("%s: can't add kobject (directory) %s/%s\n", |
| 438 | __FUNCTION__, dev->name, br->ifobj.name); | 438 | __FUNCTION__, dev->name, kobject_name(&br->ifobj)); |
| 439 | goto out3; | 439 | goto out3; |
| 440 | } | 440 | } |
| 441 | return 0; | 441 | return 0; |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 909a03d6c0e9..6628e457ddc0 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
| @@ -396,28 +396,22 @@ static struct attribute_group wireless_group = { | |||
| 396 | #endif /* CONFIG_SYSFS */ | 396 | #endif /* CONFIG_SYSFS */ |
| 397 | 397 | ||
| 398 | #ifdef CONFIG_HOTPLUG | 398 | #ifdef CONFIG_HOTPLUG |
| 399 | static int netdev_uevent(struct device *d, char **envp, | 399 | static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) |
| 400 | int num_envp, char *buf, int size) | ||
| 401 | { | 400 | { |
| 402 | struct net_device *dev = to_net_dev(d); | 401 | struct net_device *dev = to_net_dev(d); |
| 403 | int retval, len = 0, i = 0; | 402 | int retval; |
| 404 | 403 | ||
| 405 | /* pass interface to uevent. */ | 404 | /* pass interface to uevent. */ |
| 406 | retval = add_uevent_var(envp, num_envp, &i, | 405 | retval = add_uevent_var(env, "INTERFACE=%s", dev->name); |
| 407 | buf, size, &len, | ||
| 408 | "INTERFACE=%s", dev->name); | ||
| 409 | if (retval) | 406 | if (retval) |
| 410 | goto exit; | 407 | goto exit; |
| 411 | 408 | ||
| 412 | /* pass ifindex to uevent. | 409 | /* pass ifindex to uevent. |
| 413 | * ifindex is useful as it won't change (interface name may change) | 410 | * ifindex is useful as it won't change (interface name may change) |
| 414 | * and is what RtNetlink uses natively. */ | 411 | * and is what RtNetlink uses natively. */ |
| 415 | retval = add_uevent_var(envp, num_envp, &i, | 412 | retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex); |
| 416 | buf, size, &len, | ||
| 417 | "IFINDEX=%d", dev->ifindex); | ||
| 418 | 413 | ||
| 419 | exit: | 414 | exit: |
| 420 | envp[i] = NULL; | ||
| 421 | return retval; | 415 | return retval; |
| 422 | } | 416 | } |
| 423 | #endif | 417 | #endif |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 2d5d2255a27c..29f820e18251 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
| @@ -53,8 +53,7 @@ static void wiphy_dev_release(struct device *dev) | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #ifdef CONFIG_HOTPLUG | 55 | #ifdef CONFIG_HOTPLUG |
| 56 | static int wiphy_uevent(struct device *dev, char **envp, | 56 | static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 57 | int num_envp, char *buf, int size) | ||
| 58 | { | 57 | { |
| 59 | /* TODO, we probably need stuff here */ | 58 | /* TODO, we probably need stuff here */ |
| 60 | return 0; | 59 | return 0; |
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 64d163914335..f84f3e505788 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c | |||
| @@ -56,13 +56,12 @@ static int soundbus_probe(struct device *dev) | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | 59 | static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 60 | char *buffer, int buffer_size) | ||
| 61 | { | 60 | { |
| 62 | struct soundbus_dev * soundbus_dev; | 61 | struct soundbus_dev * soundbus_dev; |
| 63 | struct of_device * of; | 62 | struct of_device * of; |
| 64 | const char *compat; | 63 | const char *compat; |
| 65 | int retval = 0, i = 0, length = 0; | 64 | int retval = 0; |
| 66 | int cplen, seen = 0; | 65 | int cplen, seen = 0; |
| 67 | 66 | ||
| 68 | if (!dev) | 67 | if (!dev) |
| @@ -75,15 +74,11 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | |||
| 75 | of = &soundbus_dev->ofdev; | 74 | of = &soundbus_dev->ofdev; |
| 76 | 75 | ||
| 77 | /* stuff we want to pass to /sbin/hotplug */ | 76 | /* stuff we want to pass to /sbin/hotplug */ |
| 78 | retval = add_uevent_var(envp, num_envp, &i, | 77 | retval = add_uevent_var(env, "OF_NAME=%s", of->node->name); |
| 79 | buffer, buffer_size, &length, | ||
| 80 | "OF_NAME=%s", of->node->name); | ||
| 81 | if (retval) | 78 | if (retval) |
| 82 | return retval; | 79 | return retval; |
| 83 | 80 | ||
| 84 | retval = add_uevent_var(envp, num_envp, &i, | 81 | retval = add_uevent_var(env, "OF_TYPE=%s", of->node->type); |
| 85 | buffer, buffer_size, &length, | ||
| 86 | "OF_TYPE=%s", of->node->type); | ||
| 87 | if (retval) | 82 | if (retval) |
| 88 | return retval; | 83 | return retval; |
| 89 | 84 | ||
| @@ -93,27 +88,19 @@ static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | |||
| 93 | 88 | ||
| 94 | compat = of_get_property(of->node, "compatible", &cplen); | 89 | compat = of_get_property(of->node, "compatible", &cplen); |
| 95 | while (compat && cplen > 0) { | 90 | while (compat && cplen > 0) { |
| 96 | int tmp = length; | 91 | int tmp = env->buflen; |
| 97 | retval = add_uevent_var(envp, num_envp, &i, | 92 | retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat); |
| 98 | buffer, buffer_size, &length, | ||
| 99 | "OF_COMPATIBLE_%d=%s", seen, compat); | ||
| 100 | if (retval) | 93 | if (retval) |
| 101 | return retval; | 94 | return retval; |
| 102 | compat += length - tmp; | 95 | compat += env->buflen - tmp; |
| 103 | cplen -= length - tmp; | 96 | cplen -= env->buflen - tmp; |
| 104 | seen += 1; | 97 | seen += 1; |
| 105 | } | 98 | } |
| 106 | 99 | ||
| 107 | retval = add_uevent_var(envp, num_envp, &i, | 100 | retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); |
| 108 | buffer, buffer_size, &length, | ||
| 109 | "OF_COMPATIBLE_N=%d", seen); | ||
| 110 | if (retval) | 101 | if (retval) |
| 111 | return retval; | 102 | return retval; |
| 112 | retval = add_uevent_var(envp, num_envp, &i, | 103 | retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias); |
| 113 | buffer, buffer_size, &length, | ||
| 114 | "MODALIAS=%s", soundbus_dev->modalias); | ||
| 115 | |||
| 116 | envp[i] = NULL; | ||
| 117 | 104 | ||
| 118 | return retval; | 105 | return retval; |
| 119 | } | 106 | } |
