diff options
114 files changed, 1777 insertions, 2493 deletions
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 | -『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版] | 65 | -『プログラミング言語C第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 f27cdd7125f2..912c57c2334e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1437,6 +1437,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1437 | pt. [PARIDE] | 1437 | pt. [PARIDE] |
| 1438 | See Documentation/paride.txt. | 1438 | See Documentation/paride.txt. |
| 1439 | 1439 | ||
| 1440 | pty.legacy_count= | ||
| 1441 | [KNL] Number of legacy pty's. Overwrites compiled-in | ||
| 1442 | default number. | ||
| 1443 | |||
| 1440 | quiet [KNL] Disable most log messages | 1444 | quiet [KNL] Disable most log messages |
| 1441 | 1445 | ||
| 1442 | r128= [HW,DRM] | 1446 | 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/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/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/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/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/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/cpufreq.c b/drivers/cpufreq/cpufreq.c index f7b9d6fce123..5e626b12b97e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -830,7 +830,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
| 830 | /* prepare interface data */ | 830 | /* prepare interface data */ |
| 831 | policy->kobj.parent = &sys_dev->kobj; | 831 | policy->kobj.parent = &sys_dev->kobj; |
| 832 | policy->kobj.ktype = &ktype_cpufreq; | 832 | policy->kobj.ktype = &ktype_cpufreq; |
| 833 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); | 833 | kobject_set_name(&policy->kobj, "cpufreq"); |
| 834 | 834 | ||
| 835 | ret = kobject_register(&policy->kobj); | 835 | ret = kobject_register(&policy->kobj); |
| 836 | if (ret) { | 836 | if (ret) { |
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 4e2ca6f0ab18..c19f77fbaf2a 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 22 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 23 | MODULE_DESCRIPTION("PC Speaker beeper driver"); | 23 | MODULE_DESCRIPTION("PC Speaker beeper driver"); |
| 24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
| 25 | MODULE_ALIAS("platform:pcspkr"); | ||
| 25 | 26 | ||
| 26 | #ifdef CONFIG_X86 | 27 | #ifdef CONFIG_X86 |
| 27 | /* Use the global PIT lock ! */ | 28 | /* Use the global PIT lock ! */ |
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/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/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/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 004bc2487270..f61be3abfdca 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -532,8 +532,7 @@ void pci_dev_put(struct pci_dev *dev) | |||
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | #ifndef CONFIG_HOTPLUG | 534 | #ifndef CONFIG_HOTPLUG |
| 535 | int pci_uevent(struct device *dev, char **envp, int num_envp, | 535 | int pci_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 536 | char *buffer, int buffer_size) | ||
| 537 | { | 536 | { |
| 538 | return -ENODEV; | 537 | return -ENODEV; |
| 539 | } | 538 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4c36e80f6d26..b3a7d5b0f936 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/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 9c3b9ea1e66f..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; |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 39f02b48e4c7..7ee57f084a89 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -79,49 +79,38 @@ static int snprint_alias(char *buf, size_t size, | |||
| 79 | 79 | ||
| 80 | /* 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, |
| 81 | * non-zero otherwise. */ | 81 | * non-zero otherwise. */ |
| 82 | 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) |
| 83 | char *buffer, int buffer_size) | ||
| 84 | { | 83 | { |
| 85 | struct ccw_device *cdev = to_ccwdev(dev); | 84 | struct ccw_device *cdev = to_ccwdev(dev); |
| 86 | struct ccw_device_id *id = &(cdev->id); | 85 | struct ccw_device_id *id = &(cdev->id); |
| 87 | int i = 0; | ||
| 88 | int len = 0; | ||
| 89 | int ret; | 86 | int ret; |
| 90 | char modalias_buf[30]; | 87 | char modalias_buf[30]; |
| 91 | 88 | ||
| 92 | /* CU_TYPE= */ | 89 | /* CU_TYPE= */ |
| 93 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 90 | ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type); |
| 94 | "CU_TYPE=%04X", id->cu_type); | ||
| 95 | if (ret) | 91 | if (ret) |
| 96 | return ret; | 92 | return ret; |
| 97 | 93 | ||
| 98 | /* CU_MODEL= */ | 94 | /* CU_MODEL= */ |
| 99 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 95 | ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model); |
| 100 | "CU_MODEL=%02X", id->cu_model); | ||
| 101 | if (ret) | 96 | if (ret) |
| 102 | return ret; | 97 | return ret; |
| 103 | 98 | ||
| 104 | /* The next two can be zero, that's ok for us */ | 99 | /* The next two can be zero, that's ok for us */ |
| 105 | /* DEV_TYPE= */ | 100 | /* DEV_TYPE= */ |
| 106 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 101 | ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type); |
| 107 | "DEV_TYPE=%04X", id->dev_type); | ||
| 108 | if (ret) | 102 | if (ret) |
| 109 | return ret; | 103 | return ret; |
| 110 | 104 | ||
| 111 | /* DEV_MODEL= */ | 105 | /* DEV_MODEL= */ |
| 112 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 106 | ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model); |
| 113 | "DEV_MODEL=%02X", id->dev_model); | ||
| 114 | if (ret) | 107 | if (ret) |
| 115 | return ret; | 108 | return ret; |
| 116 | 109 | ||
| 117 | /* MODALIAS= */ | 110 | /* MODALIAS= */ |
| 118 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); | 111 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); |
| 119 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 112 | ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf); |
| 120 | "MODALIAS=%s", modalias_buf); | 113 | return ret; |
| 121 | if (ret) | ||
| 122 | return ret; | ||
| 123 | envp[i] = NULL; | ||
| 124 | return 0; | ||
| 125 | } | 114 | } |
| 126 | 115 | ||
| 127 | struct bus_type ccw_bus_type; | 116 | struct bus_type ccw_bus_type; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index d334b0f7a1ec..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 | ||
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/core/devio.c b/drivers/usb/core/devio.c index e5ad76b4a738..f013b4012c9a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -1591,6 +1591,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai | |||
| 1591 | } | 1591 | } |
| 1592 | 1592 | ||
| 1593 | const struct file_operations usbdev_file_operations = { | 1593 | const struct file_operations usbdev_file_operations = { |
| 1594 | .owner = THIS_MODULE, | ||
| 1594 | .llseek = usbdev_lseek, | 1595 | .llseek = usbdev_lseek, |
| 1595 | .read = usbdev_read, | 1596 | .read = usbdev_read, |
| 1596 | .poll = usbdev_poll, | 1597 | .poll = usbdev_poll, |
| @@ -1640,10 +1641,7 @@ static struct notifier_block usbdev_nb = { | |||
| 1640 | }; | 1641 | }; |
| 1641 | #endif | 1642 | #endif |
| 1642 | 1643 | ||
| 1643 | static struct cdev usb_device_cdev = { | 1644 | static struct cdev usb_device_cdev; |
| 1644 | .kobj = {.name = "usb_device", }, | ||
| 1645 | .owner = THIS_MODULE, | ||
| 1646 | }; | ||
| 1647 | 1645 | ||
| 1648 | int __init usb_devio_init(void) | 1646 | int __init usb_devio_init(void) |
| 1649 | { | 1647 | { |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index c27bc080d84e..8586817698ad 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
| @@ -581,12 +581,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) | |||
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | #ifdef CONFIG_HOTPLUG | 583 | #ifdef CONFIG_HOTPLUG |
| 584 | 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) |
| 585 | char *buffer, int buffer_size) | ||
| 586 | { | 585 | { |
| 587 | struct usb_device *usb_dev; | 586 | struct usb_device *usb_dev; |
| 588 | int i = 0; | ||
| 589 | int length = 0; | ||
| 590 | 587 | ||
| 591 | if (!dev) | 588 | if (!dev) |
| 592 | return -ENODEV; | 589 | return -ENODEV; |
| @@ -615,51 +612,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp, | |||
| 615 | * all the device descriptors we don't tell them about. Or | 612 | * all the device descriptors we don't tell them about. Or |
| 616 | * act as usermode drivers. | 613 | * act as usermode drivers. |
| 617 | */ | 614 | */ |
| 618 | if (add_uevent_var(envp, num_envp, &i, | 615 | if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", |
| 619 | buffer, buffer_size, &length, | ||
| 620 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
| 621 | usb_dev->bus->busnum, usb_dev->devnum)) | 616 | usb_dev->bus->busnum, usb_dev->devnum)) |
| 622 | return -ENOMEM; | 617 | return -ENOMEM; |
| 623 | #endif | 618 | #endif |
| 624 | 619 | ||
| 625 | /* per-device configurations are common */ | 620 | /* per-device configurations are common */ |
| 626 | if (add_uevent_var(envp, num_envp, &i, | 621 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", |
| 627 | buffer, buffer_size, &length, | ||
| 628 | "PRODUCT=%x/%x/%x", | ||
| 629 | le16_to_cpu(usb_dev->descriptor.idVendor), | 622 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 630 | le16_to_cpu(usb_dev->descriptor.idProduct), | 623 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| 631 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | 624 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) |
| 632 | return -ENOMEM; | 625 | return -ENOMEM; |
| 633 | 626 | ||
| 634 | /* class-based driver binding models */ | 627 | /* class-based driver binding models */ |
| 635 | if (add_uevent_var(envp, num_envp, &i, | 628 | if (add_uevent_var(env, "TYPE=%d/%d/%d", |
| 636 | buffer, buffer_size, &length, | ||
| 637 | "TYPE=%d/%d/%d", | ||
| 638 | usb_dev->descriptor.bDeviceClass, | 629 | usb_dev->descriptor.bDeviceClass, |
| 639 | usb_dev->descriptor.bDeviceSubClass, | 630 | usb_dev->descriptor.bDeviceSubClass, |
| 640 | usb_dev->descriptor.bDeviceProtocol)) | 631 | usb_dev->descriptor.bDeviceProtocol)) |
| 641 | return -ENOMEM; | 632 | return -ENOMEM; |
| 642 | 633 | ||
| 643 | if (add_uevent_var(envp, num_envp, &i, | 634 | if (add_uevent_var(env, "BUSNUM=%03d", |
| 644 | buffer, buffer_size, &length, | ||
| 645 | "BUSNUM=%03d", | ||
| 646 | usb_dev->bus->busnum)) | 635 | usb_dev->bus->busnum)) |
| 647 | return -ENOMEM; | 636 | return -ENOMEM; |
| 648 | 637 | ||
| 649 | if (add_uevent_var(envp, num_envp, &i, | 638 | if (add_uevent_var(env, "DEVNUM=%03d", |
| 650 | buffer, buffer_size, &length, | ||
| 651 | "DEVNUM=%03d", | ||
| 652 | usb_dev->devnum)) | 639 | usb_dev->devnum)) |
| 653 | return -ENOMEM; | 640 | return -ENOMEM; |
| 654 | 641 | ||
| 655 | envp[i] = NULL; | ||
| 656 | return 0; | 642 | return 0; |
| 657 | } | 643 | } |
| 658 | 644 | ||
| 659 | #else | 645 | #else |
| 660 | 646 | ||
| 661 | static int usb_uevent(struct device *dev, char **envp, | 647 | static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 662 | int num_envp, char *buffer, int buffer_size) | ||
| 663 | { | 648 | { |
| 664 | return -ENODEV; | 649 | return -ENODEV; |
| 665 | } | 650 | } |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 98fcddba6908..c021af390372 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1344,14 +1344,11 @@ static void usb_release_interface(struct device *dev) | |||
| 1344 | } | 1344 | } |
| 1345 | 1345 | ||
| 1346 | #ifdef CONFIG_HOTPLUG | 1346 | #ifdef CONFIG_HOTPLUG |
| 1347 | 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) |
| 1348 | char *buffer, int buffer_size) | ||
| 1349 | { | 1348 | { |
| 1350 | struct usb_device *usb_dev; | 1349 | struct usb_device *usb_dev; |
| 1351 | struct usb_interface *intf; | 1350 | struct usb_interface *intf; |
| 1352 | struct usb_host_interface *alt; | 1351 | struct usb_host_interface *alt; |
| 1353 | int i = 0; | ||
| 1354 | int length = 0; | ||
| 1355 | 1352 | ||
| 1356 | if (!dev) | 1353 | if (!dev) |
| 1357 | return -ENODEV; | 1354 | return -ENODEV; |
| @@ -1364,39 +1361,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1364 | alt = intf->cur_altsetting; | 1361 | alt = intf->cur_altsetting; |
| 1365 | 1362 | ||
| 1366 | #ifdef CONFIG_USB_DEVICEFS | 1363 | #ifdef CONFIG_USB_DEVICEFS |
| 1367 | if (add_uevent_var(envp, num_envp, &i, | 1364 | if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", |
| 1368 | buffer, buffer_size, &length, | ||
| 1369 | "DEVICE=/proc/bus/usb/%03d/%03d", | ||
| 1370 | usb_dev->bus->busnum, usb_dev->devnum)) | 1365 | usb_dev->bus->busnum, usb_dev->devnum)) |
| 1371 | return -ENOMEM; | 1366 | return -ENOMEM; |
| 1372 | #endif | 1367 | #endif |
| 1373 | 1368 | ||
| 1374 | if (add_uevent_var(envp, num_envp, &i, | 1369 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", |
| 1375 | buffer, buffer_size, &length, | ||
| 1376 | "PRODUCT=%x/%x/%x", | ||
| 1377 | le16_to_cpu(usb_dev->descriptor.idVendor), | 1370 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 1378 | le16_to_cpu(usb_dev->descriptor.idProduct), | 1371 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| 1379 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) | 1372 | le16_to_cpu(usb_dev->descriptor.bcdDevice))) |
| 1380 | return -ENOMEM; | 1373 | return -ENOMEM; |
| 1381 | 1374 | ||
| 1382 | if (add_uevent_var(envp, num_envp, &i, | 1375 | if (add_uevent_var(env, "TYPE=%d/%d/%d", |
| 1383 | buffer, buffer_size, &length, | ||
| 1384 | "TYPE=%d/%d/%d", | ||
| 1385 | usb_dev->descriptor.bDeviceClass, | 1376 | usb_dev->descriptor.bDeviceClass, |
| 1386 | usb_dev->descriptor.bDeviceSubClass, | 1377 | usb_dev->descriptor.bDeviceSubClass, |
| 1387 | usb_dev->descriptor.bDeviceProtocol)) | 1378 | usb_dev->descriptor.bDeviceProtocol)) |
| 1388 | return -ENOMEM; | 1379 | return -ENOMEM; |
| 1389 | 1380 | ||
| 1390 | if (add_uevent_var(envp, num_envp, &i, | 1381 | if (add_uevent_var(env, "INTERFACE=%d/%d/%d", |
| 1391 | buffer, buffer_size, &length, | ||
| 1392 | "INTERFACE=%d/%d/%d", | ||
| 1393 | alt->desc.bInterfaceClass, | 1382 | alt->desc.bInterfaceClass, |
| 1394 | alt->desc.bInterfaceSubClass, | 1383 | alt->desc.bInterfaceSubClass, |
| 1395 | alt->desc.bInterfaceProtocol)) | 1384 | alt->desc.bInterfaceProtocol)) |
| 1396 | return -ENOMEM; | 1385 | return -ENOMEM; |
| 1397 | 1386 | ||
| 1398 | if (add_uevent_var(envp, num_envp, &i, | 1387 | if (add_uevent_var(env, |
| 1399 | buffer, buffer_size, &length, | ||
| 1400 | "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", |
| 1401 | le16_to_cpu(usb_dev->descriptor.idVendor), | 1389 | le16_to_cpu(usb_dev->descriptor.idVendor), |
| 1402 | le16_to_cpu(usb_dev->descriptor.idProduct), | 1390 | le16_to_cpu(usb_dev->descriptor.idProduct), |
| @@ -1409,14 +1397,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp, | |||
| 1409 | alt->desc.bInterfaceProtocol)) | 1397 | alt->desc.bInterfaceProtocol)) |
| 1410 | return -ENOMEM; | 1398 | return -ENOMEM; |
| 1411 | 1399 | ||
| 1412 | envp[i] = NULL; | ||
| 1413 | return 0; | 1400 | return 0; |
| 1414 | } | 1401 | } |
| 1415 | 1402 | ||
| 1416 | #else | 1403 | #else |
| 1417 | 1404 | ||
| 1418 | static int usb_if_uevent(struct device *dev, char **envp, | 1405 | static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1419 | int num_envp, char *buffer, int buffer_size) | ||
| 1420 | { | 1406 | { |
| 1421 | return -ENODEV; | 1407 | return -ENODEV; |
| 1422 | } | 1408 | } |
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/lockspace.c b/fs/dlm/lockspace.c index 628eaa669e68..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) |
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/sys.c b/fs/gfs2/sys.c index ba3a1729cc1a..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 | ||
| @@ -551,6 +550,7 @@ int gfs2_sys_init(void) | |||
| 551 | { | 550 | { |
| 552 | gfs2_sys_margs = NULL; | 551 | gfs2_sys_margs = NULL; |
| 553 | spin_lock_init(&gfs2_sys_margs_lock); | 552 | spin_lock_init(&gfs2_sys_margs_lock); |
| 553 | kobject_set_name(&gfs2_kset.kobj, "gfs2"); | ||
| 554 | kobj_set_kset_s(&gfs2_kset, fs_subsys); | 554 | kobj_set_kset_s(&gfs2_kset, fs_subsys); |
| 555 | return kset_register(&gfs2_kset); | 555 | return kset_register(&gfs2_kset); |
| 556 | } | 556 | } |
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/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/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/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/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/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/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 | } |
