mirror of https://gitee.com/openkylin/linux.git
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (75 commits) PM: merge device power-management source files sysfs: add copyrights kobject: update the copyrights kset: add some kerneldoc to help describe what these strange things are Driver core: rename ktype_edd and ktype_efivar Driver core: rename ktype_driver Driver core: rename ktype_device Driver core: rename ktype_class driver core: remove subsystem_init() sysfs: move sysfs file poll implementation to sysfs_open_dirent sysfs: implement sysfs_open_dirent sysfs: move sysfs_dirent->s_children into sysfs_dirent->s_dir sysfs: make sysfs_root a regular directory dirent sysfs: open code sysfs_attach_dentry() sysfs: make s_elem an anonymous union sysfs: make bin attr open get active reference of parent too sysfs: kill unnecessary NULL pointer check in sysfs_release() sysfs: kill unnecessary sysfs_get() in open paths sysfs: reposition sysfs_dirent->s_mode. sysfs: kill sysfs_update_file() ...
This commit is contained in:
commit
efefc6eb38
|
@ -1,4 +1,4 @@
|
||||||
NOTE:
|
NOTE:
|
||||||
This is a version of Documentation/HOWTO translated into Japanese.
|
This is a version of Documentation/HOWTO translated into Japanese.
|
||||||
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
|
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
|
||||||
and the JF Project team <www.linux.or.jp/JF>.
|
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
|
||||||
fork. So if you have any comments or updates for this file, please try
|
fork. So if you have any comments or updates for this file, please try
|
||||||
to update the original English file first.
|
to update the original English file first.
|
||||||
|
|
||||||
Last Updated: 2007/07/18
|
Last Updated: 2007/09/23
|
||||||
==================================
|
==================================
|
||||||
これは、
|
これは、
|
||||||
linux-2.6.22/Documentation/HOWTO
|
linux-2.6.23/Documentation/HOWTO
|
||||||
の和訳です。
|
の和訳です。
|
||||||
|
|
||||||
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
|
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
|
||||||
翻訳日: 2007/07/16
|
翻訳日: 2007/09/19
|
||||||
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
||||||
校正者: 松倉さん <nbh--mats at nifty dot com>
|
校正者: 松倉さん <nbh--mats at nifty dot com>
|
||||||
小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
|
小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
|
||||||
|
@ -27,6 +27,7 @@ linux-2.6.22/Documentation/HOWTO
|
||||||
野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
|
野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
|
||||||
河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
|
河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
|
||||||
岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
|
岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
|
||||||
|
内田さん (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com>
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
Linux カーネル開発のやり方
|
Linux カーネル開発のやり方
|
||||||
|
@ -40,7 +41,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||||
手助けになります。
|
手助けになります。
|
||||||
|
|
||||||
もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
|
もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
|
||||||
トの最後にリストしたメンテナーにパッチを送ってください。
|
トの最後にリストしたメンテナにパッチを送ってください。
|
||||||
|
|
||||||
はじめに
|
はじめに
|
||||||
---------
|
---------
|
||||||
|
@ -59,7 +60,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||||
ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
|
ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
|
||||||
でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
|
でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
|
||||||
ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
|
ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
|
||||||
ではありませんが、少なくともリファレンスとしてはいい本です。
|
ではありませんが、少なくともリファレンスとしては良い本です。
|
||||||
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
||||||
-『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
|
-『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
|
||||||
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
||||||
|
@ -76,7 +77,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||||
ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
|
ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
|
||||||
なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
|
なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
|
||||||
レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
|
レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
|
||||||
みてください。
|
見てください。
|
||||||
|
|
||||||
あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
|
あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
|
||||||
とに留意してください。そのコミュニティは、コーディング、スタイル、
|
とに留意してください。そのコミュニティは、コーディング、スタイル、
|
||||||
|
@ -92,7 +93,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||||
|
|
||||||
Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
|
Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
|
||||||
す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
|
す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
|
||||||
する、COPYING のファイルをみてください。もしライセンスについてさらに質
|
する、COPYING のファイルを見てください。もしライセンスについてさらに質
|
||||||
問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
|
問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
|
||||||
法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
|
法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
|
||||||
問題については彼らの声明はあてにするべきではありません。
|
問題については彼らの声明はあてにするべきではありません。
|
||||||
|
@ -109,7 +110,8 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||||
新しいドキュメントファイルも追加することを勧めます。
|
新しいドキュメントファイルも追加することを勧めます。
|
||||||
カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
|
カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
|
||||||
変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
|
変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
|
||||||
をマニュアルページのメンテナ mtk-manpages@gmx.net に送ることを勧めます。
|
をマニュアルページのメンテナ mtk-manpages@gmx.net に送ることを勧めま
|
||||||
|
す。
|
||||||
|
|
||||||
以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
|
以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
|
||||||
す-
|
す-
|
||||||
|
@ -117,7 +119,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||||
README
|
README
|
||||||
このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
|
このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
|
||||||
configure )し、生成(訳注 build )するために必要なことは何かが書かれ
|
configure )し、生成(訳注 build )するために必要なことは何かが書かれ
|
||||||
ています。カーネルに関して初めての人はここからスタートするとよいで
|
ています。カーネルに関して初めての人はここからスタートすると良いで
|
||||||
しょう。
|
しょう。
|
||||||
|
|
||||||
Documentation/Changes
|
Documentation/Changes
|
||||||
|
@ -128,7 +130,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||||
Documentation/CodingStyle
|
Documentation/CodingStyle
|
||||||
これは Linux カーネルのコーディングスタイルと背景にある理由を記述
|
これは Linux カーネルのコーディングスタイルと背景にある理由を記述
|
||||||
しています。全ての新しいコードはこのドキュメントにあるガイドライン
|
しています。全ての新しいコードはこのドキュメントにあるガイドライン
|
||||||
に従っていることを期待されています。大部分のメンテナーはこれらのルー
|
に従っていることを期待されています。大部分のメンテナはこれらのルー
|
||||||
ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
|
ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
|
||||||
だけをレビューします。
|
だけをレビューします。
|
||||||
|
|
||||||
|
@ -168,16 +170,16 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||||
支援してください。
|
支援してください。
|
||||||
|
|
||||||
Documentation/ManagementStyle
|
Documentation/ManagementStyle
|
||||||
このドキュメントは Linux カーネルのメンテナー達がどう行動するか、
|
このドキュメントは Linux カーネルのメンテナ達がどう行動するか、
|
||||||
彼らの手法の背景にある共有されている精神について記述しています。こ
|
彼らの手法の背景にある共有されている精神について記述しています。こ
|
||||||
れはカーネル開発の初心者なら(もしくは、単に興味があるだけの人でも)
|
れはカーネル開発の初心者なら(もしくは、単に興味があるだけの人でも)
|
||||||
重要です。なぜならこのドキュメントは、カーネルメンテナー達の独特な
|
重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な
|
||||||
行動についての多くの誤解や混乱を解消するからです。
|
行動についての多くの誤解や混乱を解消するからです。
|
||||||
|
|
||||||
Documentation/stable_kernel_rules.txt
|
Documentation/stable_kernel_rules.txt
|
||||||
このファイルはどのように stable カーネルのリリースが行われるかのルー
|
このファイルはどのように stable カーネルのリリースが行われるかのルー
|
||||||
ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
|
ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
|
||||||
り入れてもらいたい場合に何をすればいいかが示されています。
|
り入れてもらいたい場合に何をすれば良いかが示されています。
|
||||||
|
|
||||||
Documentation/kernel-docs.txt
|
Documentation/kernel-docs.txt
|
||||||
カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
|
カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
|
||||||
|
@ -218,9 +220,9 @@ web サイトには、コードの構成、サブシステム、現在存在す
|
||||||
ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
|
ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
|
||||||
的な基本情報も記述されています。
|
的な基本情報も記述されています。
|
||||||
|
|
||||||
あなたがどこからスタートしてよいかわからないが、Linux カーネル開発コミュ
|
あなたがどこからスタートして良いかわからないが、Linux カーネル開発コミュ
|
||||||
ニティに参加して何かすることをさがしている場合には、Linux kernel
|
ニティに参加して何かすることをさがしている場合には、Linux kernel
|
||||||
Janitor's プロジェクトにいけばよいでしょう -
|
Janitor's プロジェクトにいけば良いでしょう -
|
||||||
http://janitor.kernelnewbies.org/
|
http://janitor.kernelnewbies.org/
|
||||||
ここはそのようなスタートをするのにうってつけの場所です。ここには、
|
ここはそのようなスタートをするのにうってつけの場所です。ここには、
|
||||||
Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
|
Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
|
||||||
|
@ -243,7 +245,7 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
|
||||||
自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
|
自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
|
||||||
できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
|
できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
|
||||||
ます-
|
ます-
|
||||||
http://sosdg.org/~coywolf/lxr/
|
http://sosdg.org/~qiyong/lxr/
|
||||||
|
|
||||||
開発プロセス
|
開発プロセス
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -265,9 +267,9 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
||||||
以下のとおり-
|
以下のとおり-
|
||||||
|
|
||||||
- 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
|
- 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
|
||||||
この期間中に、メンテナー達は Linus に大きな差分を送ることができま
|
この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
|
||||||
す。このような差分は通常 -mm カーネルに数週間含まれてきたパッチで
|
このような差分は通常 -mm カーネルに数週間含まれてきたパッチです。
|
||||||
す。 大きな変更は git(カーネルのソース管理ツール、詳細は
|
大きな変更は git(カーネルのソース管理ツール、詳細は
|
||||||
http://git.or.cz/ 参照) を使って送るのが好ましいやり方ですが、パッ
|
http://git.or.cz/ 参照) を使って送るのが好ましいやり方ですが、パッ
|
||||||
チファイルの形式のまま送るのでも十分です。
|
チファイルの形式のまま送るのでも十分です。
|
||||||
|
|
||||||
|
@ -285,6 +287,10 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
||||||
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
||||||
しい -rc カーネルをリリースすることです。
|
しい -rc カーネルをリリースすることです。
|
||||||
|
|
||||||
|
- 以下の URL で各 -rc リリースに存在する既知の後戻り問題のリスト
|
||||||
|
が追跡されます-
|
||||||
|
http://kernelnewbies.org/known_regressions
|
||||||
|
|
||||||
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
||||||
す。このプロセスはだいたい 6週間継続します。
|
す。このプロセスはだいたい 6週間継続します。
|
||||||
|
|
||||||
|
@ -331,8 +337,8 @@ Andrew は個別のサブシステムカーネルツリーとパッチを全て
|
||||||
linux-kernel メーリングリストで収集された多数のパッチと同時に一つにま
|
linux-kernel メーリングリストで収集された多数のパッチと同時に一つにま
|
||||||
とめます。
|
とめます。
|
||||||
このツリーは新機能とパッチが検証される場となります。ある期間の間パッチ
|
このツリーは新機能とパッチが検証される場となります。ある期間の間パッチ
|
||||||
が -mm に入って価値を証明されたら、Andrew やサブシステムメンテナが、メ
|
が -mm に入って価値を証明されたら、Andrew やサブシステムメンテナが、
|
||||||
インラインへ入れるように Linus にプッシュします。
|
メインラインへ入れるように Linus にプッシュします。
|
||||||
|
|
||||||
メインカーネルツリーに含めるために Linus に送る前に、すべての新しいパッ
|
メインカーネルツリーに含めるために Linus に送る前に、すべての新しいパッ
|
||||||
チが -mm ツリーでテストされることが強く推奨されます。
|
チが -mm ツリーでテストされることが強く推奨されます。
|
||||||
|
@ -460,7 +466,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||||
せん-
|
せん-
|
||||||
彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
|
彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
|
||||||
るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
|
るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
|
||||||
に確認した方がいいです。最初の良いテストとしては、自分にメールを送って
|
に確認した方が良いです。最初の良いテストとしては、自分にメールを送って
|
||||||
みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
|
みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
|
||||||
ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
|
ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
|
||||||
きです。
|
きです。
|
||||||
|
@ -507,14 +513,14 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||||
とも普通のことです。これはあなたのパッチが受け入れられないということで
|
とも普通のことです。これはあなたのパッチが受け入れられないということで
|
||||||
は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
|
は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
|
||||||
せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
|
せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
|
||||||
いいのです。
|
良いのです。
|
||||||
|
|
||||||
|
|
||||||
カーネルコミュニティと企業組織のちがい
|
カーネルコミュニティと企業組織のちがい
|
||||||
-----------------------------------------------------------------
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
|
カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
|
||||||
動いています。以下は問題を避けるためにできるとよいことののリストです-
|
動いています。以下は問題を避けるためにできると良いことのリストです-
|
||||||
|
|
||||||
あなたの提案する変更について言うときのうまい言い方:
|
あなたの提案する変更について言うときのうまい言い方:
|
||||||
|
|
||||||
|
@ -525,7 +531,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||||
- "以下は一連の小さなパッチ群ですが..."
|
- "以下は一連の小さなパッチ群ですが..."
|
||||||
- "これは典型的なマシンでの性能を向上させます.."
|
- "これは典型的なマシンでの性能を向上させます.."
|
||||||
|
|
||||||
やめた方がいい悪い言い方:
|
やめた方が良い悪い言い方:
|
||||||
|
|
||||||
- このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
|
- このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
|
||||||
- 私はこれを20年もの間やってきた、だから
|
- 私はこれを20年もの間やってきた、だから
|
||||||
|
@ -575,10 +581,10 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||||
|
|
||||||
1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
|
1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
|
||||||
ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
|
ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
|
||||||
らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。し
|
らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。
|
||||||
かし、500行のパッチは、正しいことをレビューするのに数時間かかるかも
|
しかし、500行のパッチは、正しいことをレビューするのに数時間かかるか
|
||||||
しれません(時間はパッチのサイズなどにより指数関数に比例してかかりま
|
もしれません(時間はパッチのサイズなどにより指数関数に比例してかかり
|
||||||
す)
|
ます)
|
||||||
|
|
||||||
小さいパッチは何かあったときにデバッグもとても簡単になります。パッ
|
小さいパッチは何かあったときにデバッグもとても簡単になります。パッ
|
||||||
チを1個1個取り除くのは、とても大きなパッチを当てた後に(かつ、何かお
|
チを1個1個取り除くのは、とても大きなパッチを当てた後に(かつ、何かお
|
||||||
|
@ -587,23 +593,23 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||||
2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
|
2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
|
||||||
る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
|
る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
|
||||||
|
|
||||||
以下はカーネル開発者の Al Viro のたとえ話しです:
|
以下はカーネル開発者の Al Viro のたとえ話です:
|
||||||
|
|
||||||
"生徒の数学の宿題を採点する先生のことを考えてみてください、先
|
"生徒の数学の宿題を採点する先生のことを考えてみてください、先
|
||||||
生は生徒が解に到達するまでの試行錯誤をみたいとは思わないでしょ
|
生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでしょ
|
||||||
う。先生は簡潔な最高の解をみたいのです。良い生徒はこれを知って
|
う。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知って
|
||||||
おり、そして最終解の前の中間作業を提出することは決してないので
|
おり、そして最終解の前の中間作業を提出することは決してないので
|
||||||
す"
|
す"
|
||||||
|
|
||||||
カーネル開発でもこれは同じです。メンテナー達とレビューア達は、
|
カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
|
||||||
問題を解決する解の背後になる思考プロセスをみたいとは思いません。
|
問題を解決する解の背後になる思考プロセスを見たいとは思いません。
|
||||||
彼らは単純であざやかな解決方法をみたいのです。
|
彼らは単純であざやかな解決方法を見たいのです。
|
||||||
|
|
||||||
あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
|
あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
|
||||||
議論することのバランスをキープするのは難しいかもしれません。
|
議論することのバランスをキープするのは難しいかもしれません。
|
||||||
ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
|
ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
|
||||||
うにするのもいいですが、変更点を小さい部分に分割して全体ではまだ完成し
|
うにするのも良いですが、変更点を小さい部分に分割して全体ではまだ完成し
|
||||||
ていない仕事を(部分的に)取り込んでもらえるようにすることもいいことです。
|
ていない仕事を(部分的に)取り込んでもらえるようにすることも良いことです。
|
||||||
|
|
||||||
また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
|
また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
|
||||||
てもらうように送っても、それは受け付けられないことを理解してください。
|
てもらうように送っても、それは受け付けられないことを理解してください。
|
||||||
|
@ -629,7 +635,7 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||||
- テスト結果
|
- テスト結果
|
||||||
|
|
||||||
これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
|
これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
|
||||||
ントの ChangeLog セクションをみてください-
|
ントの ChangeLog セクションを見てください-
|
||||||
"The Perfect Patch"
|
"The Perfect Patch"
|
||||||
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
|
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
|
||||||
|
|
||||||
|
|
|
@ -1437,6 +1437,10 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
pt. [PARIDE]
|
pt. [PARIDE]
|
||||||
See Documentation/paride.txt.
|
See Documentation/paride.txt.
|
||||||
|
|
||||||
|
pty.legacy_count=
|
||||||
|
[KNL] Number of legacy pty's. Overwrites compiled-in
|
||||||
|
default number.
|
||||||
|
|
||||||
quiet [KNL] Disable most log messages
|
quiet [KNL] Disable most log messages
|
||||||
|
|
||||||
r128= [HW,DRM]
|
r128= [HW,DRM]
|
||||||
|
|
|
@ -54,7 +54,6 @@ embedded in larger data structures and replace fields they duplicate.
|
||||||
|
|
||||||
struct kobject {
|
struct kobject {
|
||||||
const char * k_name;
|
const char * k_name;
|
||||||
char name[KOBJ_NAME_LEN];
|
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
struct list_head entry;
|
struct list_head entry;
|
||||||
struct kobject * parent;
|
struct kobject * parent;
|
||||||
|
@ -223,18 +222,15 @@ decl_subsys(devices, &ktype_device, &device_uevent_ops);
|
||||||
is equivalent to doing:
|
is equivalent to doing:
|
||||||
|
|
||||||
struct kset devices_subsys = {
|
struct kset devices_subsys = {
|
||||||
.kobj = {
|
|
||||||
.name = "devices",
|
|
||||||
},
|
|
||||||
.ktype = &ktype_devices,
|
.ktype = &ktype_devices,
|
||||||
.uevent_ops = &device_uevent_ops,
|
.uevent_ops = &device_uevent_ops,
|
||||||
};
|
};
|
||||||
|
kobject_set_name(&devices_subsys, name);
|
||||||
|
|
||||||
The objects that are registered with a subsystem that use the
|
The objects that are registered with a subsystem that use the
|
||||||
subsystem's default list must have their kset ptr set properly. These
|
subsystem's default list must have their kset ptr set properly. These
|
||||||
objects may have embedded kobjects or ksets. The
|
objects may have embedded kobjects or ksets. The
|
||||||
following helpers make setting the kset easier:
|
following helper makes setting the kset easier:
|
||||||
|
|
||||||
|
|
||||||
kobj_set_kset_s(obj,subsys)
|
kobj_set_kset_s(obj,subsys)
|
||||||
|
@ -242,22 +238,8 @@ kobj_set_kset_s(obj,subsys)
|
||||||
- Assumes that obj->kobj exists, and is a struct kobject.
|
- Assumes that obj->kobj exists, and is a struct kobject.
|
||||||
- Sets the kset of that kobject to the kset <subsys>.
|
- Sets the kset of that kobject to the kset <subsys>.
|
||||||
|
|
||||||
|
|
||||||
kset_set_kset_s(obj,subsys)
|
|
||||||
|
|
||||||
- Assumes that obj->kset exists, and is a struct kset.
|
|
||||||
- Sets the kset of the embedded kobject to the kset <subsys>.
|
|
||||||
|
|
||||||
subsys_set_kset(obj,subsys)
|
|
||||||
|
|
||||||
- Assumes obj->subsys exists, and is a struct subsystem.
|
|
||||||
- Sets obj->subsys.kset.kobj.kset to the subsystem's embedded kset.
|
|
||||||
|
|
||||||
void subsystem_init(struct kset *s);
|
|
||||||
int subsystem_register(struct kset *s);
|
int subsystem_register(struct kset *s);
|
||||||
void subsystem_unregister(struct kset *s);
|
void subsystem_unregister(struct kset *s);
|
||||||
struct kset *subsys_get(struct kset *s);
|
|
||||||
void kset_put(struct kset *s);
|
|
||||||
|
|
||||||
These are just wrappers around the respective kset_* functions.
|
These are just wrappers around the respective kset_* functions.
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
|
static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev,
|
||||||
return tsize;
|
return tsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int of_device_uevent(struct device *dev,
|
int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char **envp, int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct of_device *ofdev;
|
struct of_device *ofdev;
|
||||||
const char *compat;
|
const char *compat;
|
||||||
int i = 0, length = 0, seen = 0, cplen, sl;
|
int seen = 0, cplen, sl;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ofdev = to_of_device(dev);
|
ofdev = to_of_device(dev);
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"OF_NAME=%s", ofdev->node->name))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"OF_TYPE=%s", ofdev->node->type))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Since the compatible field can contain pretty much anything
|
/* Since the compatible field can contain pretty much anything
|
||||||
|
@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev,
|
||||||
|
|
||||||
compat = of_get_property(ofdev->node, "compatible", &cplen);
|
compat = of_get_property(ofdev->node, "compatible", &cplen);
|
||||||
while (compat && *compat && cplen > 0) {
|
while (compat && *compat && cplen > 0) {
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"OF_COMPATIBLE_%d=%s", seen, compat))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
sl = strlen (compat) + 1;
|
sl = strlen (compat) + 1;
|
||||||
|
@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev,
|
||||||
seen++;
|
seen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"OF_COMPATIBLE_N=%d", seen))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* modalias is trickier, we add it in 2 steps */
|
/* modalias is trickier, we add it in 2 steps */
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "MODALIAS="))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS="))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
|
||||||
sl = of_device_get_modalias(ofdev, &buffer[length-1],
|
sizeof(env->buf) - env->buflen);
|
||||||
buffer_size-length);
|
if (sl >= (sizeof(env->buf) - env->buflen))
|
||||||
if (sl >= (buffer_size-length))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
env->buflen += sl;
|
||||||
length += sl;
|
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
|
return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
const struct vio_dev *vio_dev = to_vio_dev(dev);
|
const struct vio_dev *vio_dev = to_vio_dev(dev);
|
||||||
struct device_node *dn;
|
struct device_node *dn;
|
||||||
const char *cp;
|
const char *cp;
|
||||||
int length;
|
|
||||||
|
|
||||||
if (!num_envp)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
dn = dev->archdata.of_node;
|
dn = dev->archdata.of_node;
|
||||||
if (!dn)
|
if (!dn)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
cp = of_get_property(dn, "compatible", &length);
|
cp = of_get_property(dn, "compatible", NULL);
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
envp[0] = buffer;
|
add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
|
||||||
length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
|
|
||||||
vio_dev->type, cp);
|
|
||||||
if ((buffer_size - length) <= 0)
|
|
||||||
return -ENOMEM;
|
|
||||||
envp[1] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev)
|
||||||
dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
|
dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ps3_system_bus_uevent(struct device *_dev, char **envp,
|
static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
|
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
|
||||||
int i = 0, length = 0;
|
int i = 0, length = 0;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
|
||||||
&length, "MODALIAS=ps3:%d",
|
|
||||||
dev->match_id))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1010,10 +1010,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bsg_register_queue);
|
EXPORT_SYMBOL_GPL(bsg_register_queue);
|
||||||
|
|
||||||
static struct cdev bsg_cdev = {
|
static struct cdev bsg_cdev;
|
||||||
.kobj = {.name = "bsg", },
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init bsg_init(void)
|
static int __init bsg_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,7 +186,7 @@ static elevator_t *elevator_alloc(struct request_queue *q,
|
||||||
eq->ops = &e->ops;
|
eq->ops = &e->ops;
|
||||||
eq->elevator_type = e;
|
eq->elevator_type = e;
|
||||||
kobject_init(&eq->kobj);
|
kobject_init(&eq->kobj);
|
||||||
snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
|
kobject_set_name(&eq->kobj, "%s", "iosched");
|
||||||
eq->kobj.ktype = &elv_ktype;
|
eq->kobj.ktype = &elv_ktype;
|
||||||
mutex_init(&eq->sysfs_lock);
|
mutex_init(&eq->sysfs_lock);
|
||||||
|
|
||||||
|
|
|
@ -540,61 +540,42 @@ static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
return ((ktype == &ktype_block) || (ktype == &ktype_part));
|
return ((ktype == &ktype_block) || (ktype == &ktype_part));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
static int block_uevent(struct kset *kset, struct kobject *kobj,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
struct device *physdev;
|
struct device *physdev;
|
||||||
struct gendisk *disk;
|
struct gendisk *disk;
|
||||||
struct hd_struct *part;
|
struct hd_struct *part;
|
||||||
int length = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (ktype == &ktype_block) {
|
if (ktype == &ktype_block) {
|
||||||
disk = container_of(kobj, struct gendisk, kobj);
|
disk = container_of(kobj, struct gendisk, kobj);
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(env, "MINOR=%u", disk->first_minor);
|
||||||
&length, "MINOR=%u", disk->first_minor);
|
|
||||||
} else if (ktype == &ktype_part) {
|
} else if (ktype == &ktype_part) {
|
||||||
disk = container_of(kobj->parent, struct gendisk, kobj);
|
disk = container_of(kobj->parent, struct gendisk, kobj);
|
||||||
part = container_of(kobj, struct hd_struct, kobj);
|
part = container_of(kobj, struct hd_struct, kobj);
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(env, "MINOR=%u",
|
||||||
&length, "MINOR=%u",
|
|
||||||
disk->first_minor + part->partno);
|
disk->first_minor + part->partno);
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(env, "MAJOR=%u", disk->major);
|
||||||
"MAJOR=%u", disk->major);
|
|
||||||
|
|
||||||
/* add physical device, backing this device */
|
/* add physical device, backing this device */
|
||||||
physdev = disk->driverfs_dev;
|
physdev = disk->driverfs_dev;
|
||||||
if (physdev) {
|
if (physdev) {
|
||||||
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||||
&length, "PHYSDEVPATH=%s", path);
|
|
||||||
kfree(path);
|
kfree(path);
|
||||||
|
|
||||||
if (physdev->bus)
|
if (physdev->bus)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVBUS=%s",
|
|
||||||
physdev->bus->name);
|
|
||||||
|
|
||||||
if (physdev->driver)
|
if (physdev->driver)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, physdev->driver->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVDRIVER=%s",
|
|
||||||
physdev->driver->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
|
||||||
envp[i] = NULL;
|
|
||||||
envp = &envp[i];
|
|
||||||
num_envp -= i;
|
|
||||||
buffer = &buffer[length];
|
|
||||||
buffer_size -= length;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1854,7 +1854,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
||||||
|
|
||||||
init_timer(&q->unplug_timer);
|
init_timer(&q->unplug_timer);
|
||||||
|
|
||||||
snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
|
kobject_set_name(&q->kobj, "%s", "queue");
|
||||||
q->kobj.ktype = &queue_ktype;
|
q->kobj.ktype = &queue_ktype;
|
||||||
kobject_init(&q->kobj);
|
kobject_init(&q->kobj);
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
|
||||||
|
|
||||||
if (!device->flags.power_manageable) {
|
if (!device->flags.power_manageable) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
|
||||||
device->dev.kobj.name));
|
kobject_name(&device->dev.kobj)));
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -319,16 +319,18 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
|
return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
|
static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||||
|
int len;
|
||||||
|
|
||||||
strcpy(buffer, "MODALIAS=");
|
if (add_uevent_var(env, "MODALIAS="))
|
||||||
if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) {
|
return -ENOMEM;
|
||||||
envp[0] = buffer;
|
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
|
||||||
envp[1] = NULL;
|
sizeof(env->buf) - env->buflen);
|
||||||
}
|
if (len >= (sizeof(env->buf) - env->buflen))
|
||||||
|
return -ENOMEM;
|
||||||
|
env->buflen += len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,7 @@ static int acpi_video_output_get(struct output_device *od)
|
||||||
{
|
{
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
struct acpi_video_device *vd =
|
struct acpi_video_device *vd =
|
||||||
(struct acpi_video_device *)class_get_devdata(&od->class_dev);
|
(struct acpi_video_device *)dev_get_drvdata(&od->dev);
|
||||||
acpi_video_device_get_state(vd, &state);
|
acpi_video_device_get_state(vd, &state);
|
||||||
return (int)state;
|
return (int)state;
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ static int acpi_video_output_set(struct output_device *od)
|
||||||
{
|
{
|
||||||
unsigned long state = od->request_state;
|
unsigned long state = od->request_state;
|
||||||
struct acpi_video_device *vd=
|
struct acpi_video_device *vd=
|
||||||
(struct acpi_video_device *)class_get_devdata(&od->class_dev);
|
(struct acpi_video_device *)dev_get_drvdata(&od->dev);
|
||||||
return acpi_video_device_set_state(vd, state);
|
return acpi_video_device_set_state(vd, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct amba_device *pcdev = to_amba_device(dev);
|
struct amba_device *pcdev = to_amba_device(dev);
|
||||||
int retval = 0, i = 0, len = 0;
|
int retval = 0;
|
||||||
|
|
||||||
retval = add_uevent_var(envp, nr_env, &i,
|
retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
|
||||||
buf, bufsz, &len,
|
|
||||||
"AMBA_ID=%08x", pcdev->periphid);
|
|
||||||
envp[i] = NULL;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
menu "Generic Driver Options"
|
menu "Generic Driver Options"
|
||||||
|
|
||||||
|
config UEVENT_HELPER_PATH
|
||||||
|
string "path to uevent helper"
|
||||||
|
depends on HOTPLUG
|
||||||
|
default "/sbin/hotplug"
|
||||||
|
help
|
||||||
|
Path to uevent helper program forked by the kernel for
|
||||||
|
every uevent.
|
||||||
|
|
||||||
config STANDALONE
|
config STANDALONE
|
||||||
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
|
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -18,8 +18,6 @@ extern int attribute_container_init(void);
|
||||||
extern int bus_add_device(struct device * dev);
|
extern int bus_add_device(struct device * dev);
|
||||||
extern void bus_attach_device(struct device * dev);
|
extern void bus_attach_device(struct device * dev);
|
||||||
extern void bus_remove_device(struct device * dev);
|
extern void bus_remove_device(struct device * dev);
|
||||||
extern struct bus_type *get_bus(struct bus_type * bus);
|
|
||||||
extern void put_bus(struct bus_type * bus);
|
|
||||||
|
|
||||||
extern int bus_add_driver(struct device_driver *);
|
extern int bus_add_driver(struct device_driver *);
|
||||||
extern void bus_remove_driver(struct device_driver *);
|
extern void bus_remove_driver(struct device_driver *);
|
||||||
|
|
|
@ -30,6 +30,17 @@
|
||||||
static int __must_check bus_rescan_devices_helper(struct device *dev,
|
static int __must_check bus_rescan_devices_helper(struct device *dev,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
static struct bus_type *bus_get(struct bus_type *bus)
|
||||||
|
{
|
||||||
|
return bus ? container_of(kset_get(&bus->subsys),
|
||||||
|
struct bus_type, subsys) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bus_put(struct bus_type *bus)
|
||||||
|
{
|
||||||
|
kset_put(&bus->subsys);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +89,7 @@ static void driver_release(struct kobject * kobj)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kobj_type ktype_driver = {
|
static struct kobj_type driver_ktype = {
|
||||||
.sysfs_ops = &driver_sysfs_ops,
|
.sysfs_ops = &driver_sysfs_ops,
|
||||||
.release = driver_release,
|
.release = driver_release,
|
||||||
};
|
};
|
||||||
|
@ -122,9 +133,9 @@ static struct sysfs_ops bus_sysfs_ops = {
|
||||||
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
|
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
if (get_bus(bus)) {
|
if (bus_get(bus)) {
|
||||||
error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
|
error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
|
||||||
put_bus(bus);
|
bus_put(bus);
|
||||||
} else
|
} else
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
return error;
|
return error;
|
||||||
|
@ -132,9 +143,9 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
|
||||||
|
|
||||||
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
|
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
|
||||||
{
|
{
|
||||||
if (get_bus(bus)) {
|
if (bus_get(bus)) {
|
||||||
sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
|
sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
|
||||||
put_bus(bus);
|
bus_put(bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +183,7 @@ static int driver_helper(struct device *dev, void *data)
|
||||||
static ssize_t driver_unbind(struct device_driver *drv,
|
static ssize_t driver_unbind(struct device_driver *drv,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct bus_type *bus = get_bus(drv->bus);
|
struct bus_type *bus = bus_get(drv->bus);
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int err = -ENODEV;
|
int err = -ENODEV;
|
||||||
|
|
||||||
|
@ -186,7 +197,7 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
||||||
err = count;
|
err = count;
|
||||||
}
|
}
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
put_bus(bus);
|
bus_put(bus);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
||||||
|
@ -199,7 +210,7 @@ static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
|
||||||
static ssize_t driver_bind(struct device_driver *drv,
|
static ssize_t driver_bind(struct device_driver *drv,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct bus_type *bus = get_bus(drv->bus);
|
struct bus_type *bus = bus_get(drv->bus);
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int err = -ENODEV;
|
int err = -ENODEV;
|
||||||
|
|
||||||
|
@ -219,7 +230,7 @@ static ssize_t driver_bind(struct device_driver *drv,
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
}
|
}
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
put_bus(bus);
|
bus_put(bus);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
|
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
|
||||||
|
@ -430,7 +441,7 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
|
||||||
*/
|
*/
|
||||||
int bus_add_device(struct device * dev)
|
int bus_add_device(struct device * dev)
|
||||||
{
|
{
|
||||||
struct bus_type * bus = get_bus(dev->bus);
|
struct bus_type * bus = bus_get(dev->bus);
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (bus) {
|
if (bus) {
|
||||||
|
@ -459,7 +470,7 @@ int bus_add_device(struct device * dev)
|
||||||
out_id:
|
out_id:
|
||||||
device_remove_attrs(bus, dev);
|
device_remove_attrs(bus, dev);
|
||||||
out_put:
|
out_put:
|
||||||
put_bus(dev->bus);
|
bus_put(dev->bus);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,7 +520,7 @@ void bus_remove_device(struct device * dev)
|
||||||
}
|
}
|
||||||
pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
|
pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
|
||||||
device_release_driver(dev);
|
device_release_driver(dev);
|
||||||
put_bus(dev->bus);
|
bus_put(dev->bus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,32 +579,29 @@ static void remove_bind_files(struct device_driver *drv)
|
||||||
driver_remove_file(drv, &driver_attr_unbind);
|
driver_remove_file(drv, &driver_attr_unbind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
|
||||||
|
static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
|
||||||
|
show_drivers_autoprobe, store_drivers_autoprobe);
|
||||||
|
|
||||||
static int add_probe_files(struct bus_type *bus)
|
static int add_probe_files(struct bus_type *bus)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
bus->drivers_probe_attr.attr.name = "drivers_probe";
|
retval = bus_create_file(bus, &bus_attr_drivers_probe);
|
||||||
bus->drivers_probe_attr.attr.mode = S_IWUSR;
|
|
||||||
bus->drivers_probe_attr.store = store_drivers_probe;
|
|
||||||
retval = bus_create_file(bus, &bus->drivers_probe_attr);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
|
retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
|
||||||
bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
|
|
||||||
bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
|
|
||||||
bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
|
|
||||||
retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
bus_remove_file(bus, &bus->drivers_probe_attr);
|
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_probe_files(struct bus_type *bus)
|
static void remove_probe_files(struct bus_type *bus)
|
||||||
{
|
{
|
||||||
bus_remove_file(bus, &bus->drivers_autoprobe_attr);
|
bus_remove_file(bus, &bus_attr_drivers_autoprobe);
|
||||||
bus_remove_file(bus, &bus->drivers_probe_attr);
|
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline int add_bind_files(struct device_driver *drv) { return 0; }
|
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; }
|
||||||
static inline void remove_probe_files(struct bus_type *bus) {}
|
static inline void remove_probe_files(struct bus_type *bus) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static ssize_t driver_uevent_store(struct device_driver *drv,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
enum kobject_action action;
|
||||||
|
|
||||||
|
if (kobject_action_type(buf, count, &action) == 0)
|
||||||
|
kobject_uevent(&drv->kobj, action);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bus_add_driver - Add a driver to the bus.
|
* bus_add_driver - Add a driver to the bus.
|
||||||
* @drv: driver.
|
* @drv: driver.
|
||||||
|
@ -609,7 +628,7 @@ static inline void remove_probe_files(struct bus_type *bus) {}
|
||||||
*/
|
*/
|
||||||
int bus_add_driver(struct device_driver *drv)
|
int bus_add_driver(struct device_driver *drv)
|
||||||
{
|
{
|
||||||
struct bus_type * bus = get_bus(drv->bus);
|
struct bus_type * bus = bus_get(drv->bus);
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!bus)
|
if (!bus)
|
||||||
|
@ -632,6 +651,11 @@ int bus_add_driver(struct device_driver *drv)
|
||||||
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
|
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
|
||||||
module_add_driver(drv->owner, drv);
|
module_add_driver(drv->owner, drv);
|
||||||
|
|
||||||
|
error = driver_create_file(drv, &driver_attr_uevent);
|
||||||
|
if (error) {
|
||||||
|
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
|
||||||
|
__FUNCTION__, drv->name);
|
||||||
|
}
|
||||||
error = driver_add_attrs(bus, drv);
|
error = driver_add_attrs(bus, drv);
|
||||||
if (error) {
|
if (error) {
|
||||||
/* How the hell do we get out of this pickle? Give up */
|
/* How the hell do we get out of this pickle? Give up */
|
||||||
|
@ -649,7 +673,7 @@ int bus_add_driver(struct device_driver *drv)
|
||||||
out_unregister:
|
out_unregister:
|
||||||
kobject_unregister(&drv->kobj);
|
kobject_unregister(&drv->kobj);
|
||||||
out_put_bus:
|
out_put_bus:
|
||||||
put_bus(bus);
|
bus_put(bus);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,12 +693,13 @@ void bus_remove_driver(struct device_driver * drv)
|
||||||
|
|
||||||
remove_bind_files(drv);
|
remove_bind_files(drv);
|
||||||
driver_remove_attrs(drv->bus, drv);
|
driver_remove_attrs(drv->bus, drv);
|
||||||
|
driver_remove_file(drv, &driver_attr_uevent);
|
||||||
klist_remove(&drv->knode_bus);
|
klist_remove(&drv->knode_bus);
|
||||||
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
|
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
|
||||||
driver_detach(drv);
|
driver_detach(drv);
|
||||||
module_remove_driver(drv);
|
module_remove_driver(drv);
|
||||||
kobject_unregister(&drv->kobj);
|
kobject_unregister(&drv->kobj);
|
||||||
put_bus(drv->bus);
|
bus_put(drv->bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -729,18 +754,6 @@ int device_reprobe(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_reprobe);
|
EXPORT_SYMBOL_GPL(device_reprobe);
|
||||||
|
|
||||||
struct bus_type *get_bus(struct bus_type *bus)
|
|
||||||
{
|
|
||||||
return bus ? container_of(subsys_get(&bus->subsys),
|
|
||||||
struct bus_type, subsys) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void put_bus(struct bus_type * bus)
|
|
||||||
{
|
|
||||||
subsys_put(&bus->subsys);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_bus - locate bus by name.
|
* find_bus - locate bus by name.
|
||||||
* @name: name of bus.
|
* @name: name of bus.
|
||||||
|
@ -808,6 +821,17 @@ static void klist_devices_put(struct klist_node *n)
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t bus_uevent_store(struct bus_type *bus,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
enum kobject_action action;
|
||||||
|
|
||||||
|
if (kobject_action_type(buf, count, &action) == 0)
|
||||||
|
kobject_uevent(&bus->subsys.kobj, action);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bus_register - register a bus with the system.
|
* bus_register - register a bus with the system.
|
||||||
* @bus: bus.
|
* @bus: bus.
|
||||||
|
@ -826,11 +850,16 @@ int bus_register(struct bus_type * bus)
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
subsys_set_kset(bus, bus_subsys);
|
bus->subsys.kobj.kset = &bus_subsys;
|
||||||
|
|
||||||
retval = subsystem_register(&bus->subsys);
|
retval = subsystem_register(&bus->subsys);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
retval = bus_create_file(bus, &bus_attr_uevent);
|
||||||
|
if (retval)
|
||||||
|
goto bus_uevent_fail;
|
||||||
|
|
||||||
kobject_set_name(&bus->devices.kobj, "devices");
|
kobject_set_name(&bus->devices.kobj, "devices");
|
||||||
bus->devices.kobj.parent = &bus->subsys.kobj;
|
bus->devices.kobj.parent = &bus->subsys.kobj;
|
||||||
retval = kset_register(&bus->devices);
|
retval = kset_register(&bus->devices);
|
||||||
|
@ -839,7 +868,7 @@ int bus_register(struct bus_type * bus)
|
||||||
|
|
||||||
kobject_set_name(&bus->drivers.kobj, "drivers");
|
kobject_set_name(&bus->drivers.kobj, "drivers");
|
||||||
bus->drivers.kobj.parent = &bus->subsys.kobj;
|
bus->drivers.kobj.parent = &bus->subsys.kobj;
|
||||||
bus->drivers.ktype = &ktype_driver;
|
bus->drivers.ktype = &driver_ktype;
|
||||||
retval = kset_register(&bus->drivers);
|
retval = kset_register(&bus->drivers);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto bus_drivers_fail;
|
goto bus_drivers_fail;
|
||||||
|
@ -866,6 +895,8 @@ int bus_register(struct bus_type * bus)
|
||||||
bus_drivers_fail:
|
bus_drivers_fail:
|
||||||
kset_unregister(&bus->devices);
|
kset_unregister(&bus->devices);
|
||||||
bus_devices_fail:
|
bus_devices_fail:
|
||||||
|
bus_remove_file(bus, &bus_attr_uevent);
|
||||||
|
bus_uevent_fail:
|
||||||
subsystem_unregister(&bus->subsys);
|
subsystem_unregister(&bus->subsys);
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -876,7 +907,7 @@ int bus_register(struct bus_type * bus)
|
||||||
* @bus: bus.
|
* @bus: bus.
|
||||||
*
|
*
|
||||||
* Unregister the child subsystems and the bus itself.
|
* Unregister the child subsystems and the bus itself.
|
||||||
* Finally, we call put_bus() to release the refcount
|
* Finally, we call bus_put() to release the refcount
|
||||||
*/
|
*/
|
||||||
void bus_unregister(struct bus_type * bus)
|
void bus_unregister(struct bus_type * bus)
|
||||||
{
|
{
|
||||||
|
@ -885,6 +916,7 @@ void bus_unregister(struct bus_type * bus)
|
||||||
remove_probe_files(bus);
|
remove_probe_files(bus);
|
||||||
kset_unregister(&bus->drivers);
|
kset_unregister(&bus->drivers);
|
||||||
kset_unregister(&bus->devices);
|
kset_unregister(&bus->devices);
|
||||||
|
bus_remove_file(bus, &bus_attr_uevent);
|
||||||
subsystem_unregister(&bus->subsys);
|
subsystem_unregister(&bus->subsys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,13 +65,13 @@ static struct sysfs_ops class_sysfs_ops = {
|
||||||
.store = class_attr_store,
|
.store = class_attr_store,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kobj_type ktype_class = {
|
static struct kobj_type class_ktype = {
|
||||||
.sysfs_ops = &class_sysfs_ops,
|
.sysfs_ops = &class_sysfs_ops,
|
||||||
.release = class_release,
|
.release = class_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Hotplug events for classes go to the class_obj subsys */
|
/* Hotplug events for classes go to the class_obj subsys */
|
||||||
static decl_subsys(class, &ktype_class, NULL);
|
static decl_subsys(class, &class_ktype, NULL);
|
||||||
|
|
||||||
|
|
||||||
int class_create_file(struct class * cls, const struct class_attribute * attr)
|
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)
|
||||||
static struct class *class_get(struct class *cls)
|
static struct class *class_get(struct class *cls)
|
||||||
{
|
{
|
||||||
if (cls)
|
if (cls)
|
||||||
return container_of(subsys_get(&cls->subsys), struct class, subsys);
|
return container_of(kset_get(&cls->subsys), struct class, subsys);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void class_put(struct class * cls)
|
static void class_put(struct class * cls)
|
||||||
{
|
{
|
||||||
if (cls)
|
if (cls)
|
||||||
subsys_put(&cls->subsys);
|
kset_put(&cls->subsys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ int class_register(struct class * cls)
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
subsys_set_kset(cls, class_subsys);
|
cls->subsys.kobj.kset = &class_subsys;
|
||||||
|
|
||||||
error = subsystem_register(&cls->subsys);
|
error = subsystem_register(&cls->subsys);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
@ -180,8 +180,7 @@ static void class_device_create_release(struct class_device *class_dev)
|
||||||
|
|
||||||
/* needed to allow these devices to have parent class devices */
|
/* needed to allow these devices to have parent class devices */
|
||||||
static int class_device_create_uevent(struct class_device *class_dev,
|
static int class_device_create_uevent(struct class_device *class_dev,
|
||||||
char **envp, int num_envp,
|
struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -324,7 +323,7 @@ static void class_dev_release(struct kobject * kobj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kobj_type ktype_class_device = {
|
static struct kobj_type class_device_ktype = {
|
||||||
.sysfs_ops = &class_dev_sysfs_ops,
|
.sysfs_ops = &class_dev_sysfs_ops,
|
||||||
.release = class_dev_release,
|
.release = class_dev_release,
|
||||||
};
|
};
|
||||||
|
@ -333,7 +332,7 @@ static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
|
||||||
if (ktype == &ktype_class_device) {
|
if (ktype == &class_device_ktype) {
|
||||||
struct class_device *class_dev = to_class_dev(kobj);
|
struct class_device *class_dev = to_class_dev(kobj);
|
||||||
if (class_dev->class)
|
if (class_dev->class)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd)
|
||||||
{ }
|
{ }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
static int class_uevent(struct kset *kset, struct kobject *kobj,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev = to_class_dev(kobj);
|
struct class_device *class_dev = to_class_dev(kobj);
|
||||||
struct device *dev = class_dev->dev;
|
struct device *dev = class_dev->dev;
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
|
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
|
||||||
|
|
||||||
if (MAJOR(class_dev->devt)) {
|
if (MAJOR(class_dev->devt)) {
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MAJOR=%u", MAJOR(class_dev->devt));
|
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MINOR=%u", MINOR(class_dev->devt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
||||||
if (path) {
|
if (path) {
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVPATH=%s", path);
|
|
||||||
kfree(path);
|
kfree(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->bus)
|
if (dev->bus)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVBUS=%s", dev->bus->name);
|
|
||||||
|
|
||||||
if (dev->driver)
|
if (dev->driver)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
|
||||||
envp[i] = NULL;
|
|
||||||
envp = &envp[i];
|
|
||||||
num_envp -= i;
|
|
||||||
buffer = &buffer[length];
|
|
||||||
buffer_size -= length;
|
|
||||||
|
|
||||||
if (class_dev->uevent) {
|
if (class_dev->uevent) {
|
||||||
/* have the class device specific function add its stuff */
|
/* have the class device specific function add its stuff */
|
||||||
retval = class_dev->uevent(class_dev, envp, num_envp,
|
retval = class_dev->uevent(class_dev, env);
|
||||||
buffer, buffer_size);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("class_dev->uevent() returned %d\n", retval);
|
pr_debug("class_dev->uevent() returned %d\n", retval);
|
||||||
} else if (class_dev->class->uevent) {
|
} else if (class_dev->class->uevent) {
|
||||||
/* have the class specific function add its stuff */
|
/* have the class specific function add its stuff */
|
||||||
retval = class_dev->class->uevent(class_dev, envp, num_envp,
|
retval = class_dev->class->uevent(class_dev, env);
|
||||||
buffer, buffer_size);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("class->uevent() returned %d\n", retval);
|
pr_debug("class->uevent() returned %d\n", retval);
|
||||||
}
|
}
|
||||||
|
@ -474,7 +452,7 @@ static struct kset_uevent_ops class_uevent_ops = {
|
||||||
.uevent = class_uevent,
|
.uevent = class_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
|
static decl_subsys(class_obj, &class_device_ktype, &class_uevent_ops);
|
||||||
|
|
||||||
|
|
||||||
static int class_device_add_attrs(struct class_device * cd)
|
static int class_device_add_attrs(struct class_device * cd)
|
||||||
|
@ -883,7 +861,7 @@ int __init classes_init(void)
|
||||||
|
|
||||||
/* ick, this is ugly, the things we go through to keep from showing up
|
/* ick, this is ugly, the things we go through to keep from showing up
|
||||||
* in sysfs... */
|
* in sysfs... */
|
||||||
subsystem_init(&class_obj_subsys);
|
kset_init(&class_obj_subsys);
|
||||||
if (!class_obj_subsys.kobj.parent)
|
if (!class_obj_subsys.kobj.parent)
|
||||||
class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
|
class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -108,7 +108,7 @@ static void device_release(struct kobject * kobj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kobj_type ktype_device = {
|
static struct kobj_type device_ktype = {
|
||||||
.release = device_release,
|
.release = device_release,
|
||||||
.sysfs_ops = &dev_sysfs_ops,
|
.sysfs_ops = &dev_sysfs_ops,
|
||||||
};
|
};
|
||||||
|
@ -118,7 +118,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
|
||||||
if (ktype == &ktype_device) {
|
if (ktype == &device_ktype) {
|
||||||
struct device *dev = to_dev(kobj);
|
struct device *dev = to_dev(kobj);
|
||||||
if (dev->uevent_suppress)
|
if (dev->uevent_suppress)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct device *dev = to_dev(kobj);
|
struct device *dev = to_dev(kobj);
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
/* add the major/minor if present */
|
/* add the major/minor if present */
|
||||||
if (MAJOR(dev->devt)) {
|
if (MAJOR(dev->devt)) {
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
|
||||||
buffer, buffer_size, &length,
|
add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
|
||||||
"MAJOR=%u", MAJOR(dev->devt));
|
|
||||||
add_uevent_var(envp, num_envp, &i,
|
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MINOR=%u", MINOR(dev->devt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->type && dev->type->name)
|
if (dev->type && dev->type->name)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEVTYPE=%s", dev->type->name);
|
|
||||||
|
|
||||||
if (dev->driver)
|
if (dev->driver)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DRIVER=%s", dev->driver->name);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||||
if (dev->class) {
|
if (dev->class) {
|
||||||
|
@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
|
|
||||||
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
|
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
|
||||||
if (path) {
|
if (path) {
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVPATH=%s", path);
|
|
||||||
kfree(path);
|
kfree(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVBUS=%s", parent->bus->name);
|
|
||||||
|
|
||||||
if (parent->driver)
|
if (parent->driver)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVDRIVER=%s",
|
||||||
buffer, buffer_size, &length,
|
parent->driver->name);
|
||||||
"PHYSDEVDRIVER=%s", parent->driver->name);
|
|
||||||
}
|
}
|
||||||
} else if (dev->bus) {
|
} else if (dev->bus) {
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVBUS=%s", dev->bus->name);
|
|
||||||
|
|
||||||
if (dev->driver)
|
if (dev->driver)
|
||||||
add_uevent_var(envp, num_envp, &i,
|
add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
/* have the bus specific function add its stuff */
|
||||||
envp[i] = NULL;
|
|
||||||
envp = &envp[i];
|
|
||||||
num_envp -= i;
|
|
||||||
buffer = &buffer[length];
|
|
||||||
buffer_size -= length;
|
|
||||||
|
|
||||||
if (dev->bus && dev->bus->uevent) {
|
if (dev->bus && dev->bus->uevent) {
|
||||||
/* have the bus specific function add its stuff */
|
retval = dev->bus->uevent(dev, env);
|
||||||
retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug ("%s: bus uevent() returned %d\n",
|
pr_debug ("%s: bus uevent() returned %d\n",
|
||||||
__FUNCTION__, retval);
|
__FUNCTION__, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* have the class specific function add its stuff */
|
||||||
if (dev->class && dev->class->dev_uevent) {
|
if (dev->class && dev->class->dev_uevent) {
|
||||||
/* have the class specific function add its stuff */
|
retval = dev->class->dev_uevent(dev, env);
|
||||||
retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("%s: class uevent() returned %d\n",
|
pr_debug("%s: class uevent() returned %d\n",
|
||||||
__FUNCTION__, retval);
|
__FUNCTION__, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* have the device type specific fuction add its stuff */
|
||||||
if (dev->type && dev->type->uevent) {
|
if (dev->type && dev->type->uevent) {
|
||||||
/* have the device type specific fuction add its stuff */
|
retval = dev->type->uevent(dev, env);
|
||||||
retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("%s: dev_type uevent() returned %d\n",
|
pr_debug("%s: dev_type uevent() returned %d\n",
|
||||||
__FUNCTION__, retval);
|
__FUNCTION__, retval);
|
||||||
|
@ -253,22 +227,18 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
|
||||||
{
|
{
|
||||||
struct kobject *top_kobj;
|
struct kobject *top_kobj;
|
||||||
struct kset *kset;
|
struct kset *kset;
|
||||||
char *envp[32];
|
struct kobj_uevent_env *env = NULL;
|
||||||
char *data = NULL;
|
|
||||||
char *pos;
|
|
||||||
int i;
|
int i;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* search the kset, the device belongs to */
|
/* search the kset, the device belongs to */
|
||||||
top_kobj = &dev->kobj;
|
top_kobj = &dev->kobj;
|
||||||
if (!top_kobj->kset && top_kobj->parent) {
|
while (!top_kobj->kset && top_kobj->parent)
|
||||||
do {
|
top_kobj = top_kobj->parent;
|
||||||
top_kobj = top_kobj->parent;
|
|
||||||
} while (!top_kobj->kset && top_kobj->parent);
|
|
||||||
}
|
|
||||||
if (!top_kobj->kset)
|
if (!top_kobj->kset)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
kset = top_kobj->kset;
|
kset = top_kobj->kset;
|
||||||
if (!kset->uevent_ops || !kset->uevent_ops->uevent)
|
if (!kset->uevent_ops || !kset->uevent_ops->uevent)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -278,43 +248,29 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
|
||||||
if (!kset->uevent_ops->filter(kset, &dev->kobj))
|
if (!kset->uevent_ops->filter(kset, &dev->kobj))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
data = (char *)get_zeroed_page(GFP_KERNEL);
|
env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
|
||||||
if (!data)
|
if (!env)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* let the kset specific function add its keys */
|
/* let the kset specific function add its keys */
|
||||||
pos = data;
|
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
|
||||||
memset(envp, 0, sizeof(envp));
|
|
||||||
retval = kset->uevent_ops->uevent(kset, &dev->kobj,
|
|
||||||
envp, ARRAY_SIZE(envp),
|
|
||||||
pos, PAGE_SIZE);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* copy keys to file */
|
/* copy keys to file */
|
||||||
for (i = 0; envp[i]; i++) {
|
for (i = 0; i < env->envp_idx; i++)
|
||||||
pos = &buf[count];
|
count += sprintf(&buf[count], "%s\n", env->envp[i]);
|
||||||
count += sprintf(pos, "%s\n", envp[i]);
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
free_page((unsigned long)data);
|
kfree(env);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
size_t len = count;
|
|
||||||
enum kobject_action action;
|
enum kobject_action action;
|
||||||
|
|
||||||
if (len && buf[len-1] == '\n')
|
if (kobject_action_type(buf, count, &action) == 0) {
|
||||||
len--;
|
|
||||||
|
|
||||||
for (action = 0; action < KOBJ_MAX; action++) {
|
|
||||||
if (strncmp(kobject_actions[action], buf, len) != 0)
|
|
||||||
continue;
|
|
||||||
if (kobject_actions[action][len] != '\0')
|
|
||||||
continue;
|
|
||||||
kobject_uevent(&dev->kobj, action);
|
kobject_uevent(&dev->kobj, action);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +405,7 @@ static struct device_attribute devt_attr =
|
||||||
* devices_subsys - structure to be registered with kobject core.
|
* devices_subsys - structure to be registered with kobject core.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
decl_subsys(devices, &ktype_device, &device_uevent_ops);
|
decl_subsys(devices, &device_ktype, &device_uevent_ops);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -88,19 +88,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
|
||||||
|
|
||||||
static void fw_dev_release(struct device *dev);
|
static void fw_dev_release(struct device *dev);
|
||||||
|
|
||||||
static int firmware_uevent(struct device *dev, char **envp, int num_envp,
|
static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||||
int i = 0, len = 0;
|
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
|
||||||
"FIRMWARE=%s", fw_priv->fw_id))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
|
||||||
"TIMEOUT=%i", loading_timeout))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -297,8 +292,7 @@ firmware_class_timeout(u_long data)
|
||||||
|
|
||||||
static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
|
static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
|
||||||
{
|
{
|
||||||
/* XXX warning we should watch out for name collisions */
|
snprintf(f_dev->bus_id, BUS_ID_SIZE, "firmware-%s", dev->bus_id);
|
||||||
strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fw_register_device(struct device **dev_p, const char *fw_name,
|
static int fw_register_device(struct device **dev_p, const char *fw_name,
|
||||||
|
|
|
@ -34,8 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||||
return MEMORY_CLASS_NAME;
|
return MEMORY_CLASS_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
|
|
|
@ -160,13 +160,8 @@ static void platform_device_release(struct device *dev)
|
||||||
*
|
*
|
||||||
* Create a platform device object which can have other objects attached
|
* Create a platform device object which can have other objects attached
|
||||||
* to it, and which will have attached objects freed when it is released.
|
* to it, and which will have attached objects freed when it is released.
|
||||||
*
|
|
||||||
* This device will be marked as not supporting hotpluggable drivers; no
|
|
||||||
* device add/remove uevents will be generated. In the unusual case that
|
|
||||||
* the device isn't being dynamically allocated as a legacy "probe the
|
|
||||||
* hardware" driver, infrastructure code should reverse this marking.
|
|
||||||
*/
|
*/
|
||||||
struct platform_device *platform_device_alloc(const char *name, unsigned int id)
|
struct platform_device *platform_device_alloc(const char *name, int id)
|
||||||
{
|
{
|
||||||
struct platform_object *pa;
|
struct platform_object *pa;
|
||||||
|
|
||||||
|
@ -177,12 +172,6 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
|
||||||
pa->pdev.id = id;
|
pa->pdev.id = id;
|
||||||
device_initialize(&pa->pdev.dev);
|
device_initialize(&pa->pdev.dev);
|
||||||
pa->pdev.dev.release = platform_device_release;
|
pa->pdev.dev.release = platform_device_release;
|
||||||
|
|
||||||
/* prevent hotplug "modprobe $(MODALIAS)" from causing trouble in
|
|
||||||
* legacy probe-the-hardware drivers, which don't properly split
|
|
||||||
* out device enumeration logic from drivers.
|
|
||||||
*/
|
|
||||||
pa->pdev.dev.uevent_suppress = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pa ? &pa->pdev : NULL;
|
return pa ? &pa->pdev : NULL;
|
||||||
|
@ -256,7 +245,8 @@ int platform_device_add(struct platform_device *pdev)
|
||||||
pdev->dev.bus = &platform_bus_type;
|
pdev->dev.bus = &platform_bus_type;
|
||||||
|
|
||||||
if (pdev->id != -1)
|
if (pdev->id != -1)
|
||||||
snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
|
snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
|
||||||
|
pdev->id);
|
||||||
else
|
else
|
||||||
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
|
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
|
||||||
|
|
||||||
|
@ -370,7 +360,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
|
||||||
* the Linux driver model. In particular, when such drivers are built
|
* the Linux driver model. In particular, when such drivers are built
|
||||||
* as modules, they can't be "hotplugged".
|
* as modules, they can't be "hotplugged".
|
||||||
*/
|
*/
|
||||||
struct platform_device *platform_device_register_simple(char *name, unsigned int id,
|
struct platform_device *platform_device_register_simple(char *name, int id,
|
||||||
struct resource *res, unsigned int num)
|
struct resource *res, unsigned int num)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
@ -530,7 +520,7 @@ static ssize_t
|
||||||
modalias_show(struct device *dev, struct device_attribute *a, char *buf)
|
modalias_show(struct device *dev, struct device_attribute *a, char *buf)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name);
|
int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
|
||||||
|
|
||||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||||
}
|
}
|
||||||
|
@ -540,13 +530,11 @@ static struct device_attribute platform_dev_attrs[] = {
|
||||||
__ATTR_NULL,
|
__ATTR_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int platform_uevent(struct device *dev, char **envp, int num_envp,
|
static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
|
||||||
envp[0] = buffer;
|
add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
|
||||||
snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
obj-y := shutdown.o
|
obj-y := shutdown.o
|
||||||
obj-$(CONFIG_PM_SLEEP) += main.o suspend.o resume.o sysfs.o
|
obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o
|
||||||
obj-$(CONFIG_PM_TRACE) += trace.o
|
obj-$(CONFIG_PM_TRACE) += trace.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
||||||
|
|
|
@ -20,19 +20,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/resume-trace.h>
|
||||||
|
|
||||||
|
#include "../base.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
LIST_HEAD(dpm_active);
|
LIST_HEAD(dpm_active);
|
||||||
LIST_HEAD(dpm_off);
|
static LIST_HEAD(dpm_off);
|
||||||
LIST_HEAD(dpm_off_irq);
|
static LIST_HEAD(dpm_off_irq);
|
||||||
|
|
||||||
DEFINE_MUTEX(dpm_mtx);
|
static DEFINE_MUTEX(dpm_mtx);
|
||||||
DEFINE_MUTEX(dpm_list_mtx);
|
static DEFINE_MUTEX(dpm_list_mtx);
|
||||||
|
|
||||||
int (*platform_enable_wakeup)(struct device *dev, int is_on);
|
int (*platform_enable_wakeup)(struct device *dev, int is_on);
|
||||||
|
|
||||||
|
|
||||||
int device_pm_add(struct device *dev)
|
int device_pm_add(struct device *dev)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
@ -61,3 +66,334 @@ void device_pm_remove(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------- Resume routines -------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resume_device - Restore state for one device.
|
||||||
|
* @dev: Device.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int resume_device(struct device * dev)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
TRACE_DEVICE(dev);
|
||||||
|
TRACE_RESUME(0);
|
||||||
|
|
||||||
|
down(&dev->sem);
|
||||||
|
|
||||||
|
if (dev->bus && dev->bus->resume) {
|
||||||
|
dev_dbg(dev,"resuming\n");
|
||||||
|
error = dev->bus->resume(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && dev->type && dev->type->resume) {
|
||||||
|
dev_dbg(dev,"resuming\n");
|
||||||
|
error = dev->type->resume(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && dev->class && dev->class->resume) {
|
||||||
|
dev_dbg(dev,"class resume\n");
|
||||||
|
error = dev->class->resume(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
up(&dev->sem);
|
||||||
|
|
||||||
|
TRACE_RESUME(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int resume_device_early(struct device * dev)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
TRACE_DEVICE(dev);
|
||||||
|
TRACE_RESUME(0);
|
||||||
|
if (dev->bus && dev->bus->resume_early) {
|
||||||
|
dev_dbg(dev,"EARLY resume\n");
|
||||||
|
error = dev->bus->resume_early(dev);
|
||||||
|
}
|
||||||
|
TRACE_RESUME(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resume the devices that have either not gone through
|
||||||
|
* the late suspend, or that did go through it but also
|
||||||
|
* went through the early resume
|
||||||
|
*/
|
||||||
|
static void dpm_resume(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&dpm_list_mtx);
|
||||||
|
while(!list_empty(&dpm_off)) {
|
||||||
|
struct list_head * entry = dpm_off.next;
|
||||||
|
struct device * dev = to_device(entry);
|
||||||
|
|
||||||
|
get_device(dev);
|
||||||
|
list_move_tail(entry, &dpm_active);
|
||||||
|
|
||||||
|
mutex_unlock(&dpm_list_mtx);
|
||||||
|
resume_device(dev);
|
||||||
|
mutex_lock(&dpm_list_mtx);
|
||||||
|
put_device(dev);
|
||||||
|
}
|
||||||
|
mutex_unlock(&dpm_list_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_resume - Restore state of each device in system.
|
||||||
|
*
|
||||||
|
* Walk the dpm_off list, remove each entry, resume the device,
|
||||||
|
* then add it to the dpm_active list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void device_resume(void)
|
||||||
|
{
|
||||||
|
might_sleep();
|
||||||
|
mutex_lock(&dpm_mtx);
|
||||||
|
dpm_resume();
|
||||||
|
mutex_unlock(&dpm_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(device_resume);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dpm_power_up - Power on some devices.
|
||||||
|
*
|
||||||
|
* Walk the dpm_off_irq list and power each device up. This
|
||||||
|
* is used for devices that required they be powered down with
|
||||||
|
* interrupts disabled. As devices are powered on, they are moved
|
||||||
|
* to the dpm_active list.
|
||||||
|
*
|
||||||
|
* Interrupts must be disabled when calling this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void dpm_power_up(void)
|
||||||
|
{
|
||||||
|
while(!list_empty(&dpm_off_irq)) {
|
||||||
|
struct list_head * entry = dpm_off_irq.next;
|
||||||
|
struct device * dev = to_device(entry);
|
||||||
|
|
||||||
|
list_move_tail(entry, &dpm_off);
|
||||||
|
resume_device_early(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_power_up - Turn on all devices that need special attention.
|
||||||
|
*
|
||||||
|
* Power on system devices then devices that required we shut them down
|
||||||
|
* with interrupts disabled.
|
||||||
|
* Called with interrupts disabled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void device_power_up(void)
|
||||||
|
{
|
||||||
|
sysdev_resume();
|
||||||
|
dpm_power_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(device_power_up);
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------- Suspend routines -------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The entries in the dpm_active list are in a depth first order, simply
|
||||||
|
* because children are guaranteed to be discovered after parents, and
|
||||||
|
* are inserted at the back of the list on discovery.
|
||||||
|
*
|
||||||
|
* All list on the suspend path are done in reverse order, so we operate
|
||||||
|
* on the leaves of the device tree (or forests, depending on how you want
|
||||||
|
* to look at it ;) first. As nodes are removed from the back of the list,
|
||||||
|
* they are inserted into the front of their destintation lists.
|
||||||
|
*
|
||||||
|
* Things are the reverse on the resume path - iterations are done in
|
||||||
|
* forward order, and nodes are inserted at the back of their destination
|
||||||
|
* lists. This way, the ancestors will be accessed before their descendents.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline char *suspend_verb(u32 event)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case PM_EVENT_SUSPEND: return "suspend";
|
||||||
|
case PM_EVENT_FREEZE: return "freeze";
|
||||||
|
case PM_EVENT_PRETHAW: return "prethaw";
|
||||||
|
default: return "(unknown suspend event)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
|
||||||
|
{
|
||||||
|
dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
|
||||||
|
((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
|
||||||
|
", may wakeup" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* suspend_device - Save state of one device.
|
||||||
|
* @dev: Device.
|
||||||
|
* @state: Power state device is entering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int suspend_device(struct device * dev, pm_message_t state)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
down(&dev->sem);
|
||||||
|
if (dev->power.power_state.event) {
|
||||||
|
dev_dbg(dev, "PM: suspend %d-->%d\n",
|
||||||
|
dev->power.power_state.event, state.event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->class && dev->class->suspend) {
|
||||||
|
suspend_device_dbg(dev, state, "class ");
|
||||||
|
error = dev->class->suspend(dev, state);
|
||||||
|
suspend_report_result(dev->class->suspend, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && dev->type && dev->type->suspend) {
|
||||||
|
suspend_device_dbg(dev, state, "type ");
|
||||||
|
error = dev->type->suspend(dev, state);
|
||||||
|
suspend_report_result(dev->type->suspend, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && dev->bus && dev->bus->suspend) {
|
||||||
|
suspend_device_dbg(dev, state, "");
|
||||||
|
error = dev->bus->suspend(dev, state);
|
||||||
|
suspend_report_result(dev->bus->suspend, error);
|
||||||
|
}
|
||||||
|
up(&dev->sem);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is called with interrupts off, only a single CPU
|
||||||
|
* running. We can't acquire a mutex or semaphore (and we don't
|
||||||
|
* need the protection)
|
||||||
|
*/
|
||||||
|
static int suspend_device_late(struct device *dev, pm_message_t state)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (dev->bus && dev->bus->suspend_late) {
|
||||||
|
suspend_device_dbg(dev, state, "LATE ");
|
||||||
|
error = dev->bus->suspend_late(dev, state);
|
||||||
|
suspend_report_result(dev->bus->suspend_late, error);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_suspend - Save state and stop all devices in system.
|
||||||
|
* @state: Power state to put each device in.
|
||||||
|
*
|
||||||
|
* Walk the dpm_active list, call ->suspend() for each device, and move
|
||||||
|
* it to the dpm_off list.
|
||||||
|
*
|
||||||
|
* (For historical reasons, if it returns -EAGAIN, that used to mean
|
||||||
|
* that the device would be called again with interrupts disabled.
|
||||||
|
* These days, we use the "suspend_late()" callback for that, so we
|
||||||
|
* print a warning and consider it an error).
|
||||||
|
*
|
||||||
|
* If we get a different error, try and back out.
|
||||||
|
*
|
||||||
|
* If we hit a failure with any of the devices, call device_resume()
|
||||||
|
* above to bring the suspended devices back to life.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int device_suspend(pm_message_t state)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
mutex_lock(&dpm_mtx);
|
||||||
|
mutex_lock(&dpm_list_mtx);
|
||||||
|
while (!list_empty(&dpm_active) && error == 0) {
|
||||||
|
struct list_head * entry = dpm_active.prev;
|
||||||
|
struct device * dev = to_device(entry);
|
||||||
|
|
||||||
|
get_device(dev);
|
||||||
|
mutex_unlock(&dpm_list_mtx);
|
||||||
|
|
||||||
|
error = suspend_device(dev, state);
|
||||||
|
|
||||||
|
mutex_lock(&dpm_list_mtx);
|
||||||
|
|
||||||
|
/* Check if the device got removed */
|
||||||
|
if (!list_empty(&dev->power.entry)) {
|
||||||
|
/* Move it to the dpm_off list */
|
||||||
|
if (!error)
|
||||||
|
list_move(&dev->power.entry, &dpm_off);
|
||||||
|
}
|
||||||
|
if (error)
|
||||||
|
printk(KERN_ERR "Could not suspend device %s: "
|
||||||
|
"error %d%s\n",
|
||||||
|
kobject_name(&dev->kobj), error,
|
||||||
|
error == -EAGAIN ? " (please convert to suspend_late)" : "");
|
||||||
|
put_device(dev);
|
||||||
|
}
|
||||||
|
mutex_unlock(&dpm_list_mtx);
|
||||||
|
if (error)
|
||||||
|
dpm_resume();
|
||||||
|
|
||||||
|
mutex_unlock(&dpm_mtx);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(device_suspend);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* device_power_down - Shut down special devices.
|
||||||
|
* @state: Power state to enter.
|
||||||
|
*
|
||||||
|
* Walk the dpm_off_irq list, calling ->power_down() for each device that
|
||||||
|
* couldn't power down the device with interrupts enabled. When we're
|
||||||
|
* done, power down system devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int device_power_down(pm_message_t state)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
struct device * dev;
|
||||||
|
|
||||||
|
while (!list_empty(&dpm_off)) {
|
||||||
|
struct list_head * entry = dpm_off.prev;
|
||||||
|
|
||||||
|
dev = to_device(entry);
|
||||||
|
error = suspend_device_late(dev, state);
|
||||||
|
if (error)
|
||||||
|
goto Error;
|
||||||
|
list_move(&dev->power.entry, &dpm_off_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sysdev_suspend(state);
|
||||||
|
Done:
|
||||||
|
return error;
|
||||||
|
Error:
|
||||||
|
printk(KERN_ERR "Could not power down device %s: "
|
||||||
|
"error %d\n", kobject_name(&dev->kobj), error);
|
||||||
|
dpm_power_up();
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(device_power_down);
|
||||||
|
|
||||||
|
void __suspend_report_result(const char *function, void *fn, int ret)
|
||||||
|
{
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "%s(): ", function);
|
||||||
|
print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
|
||||||
|
printk("%d\n", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__suspend_report_result);
|
||||||
|
|
|
@ -11,32 +11,11 @@ extern void device_shutdown(void);
|
||||||
* main.c
|
* main.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
extern struct list_head dpm_active; /* The active device list */
|
||||||
* Used to synchronize global power management operations.
|
|
||||||
*/
|
|
||||||
extern struct mutex dpm_mtx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Used to serialize changes to the dpm_* lists.
|
|
||||||
*/
|
|
||||||
extern struct mutex dpm_list_mtx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The PM lists.
|
|
||||||
*/
|
|
||||||
extern struct list_head dpm_active;
|
|
||||||
extern struct list_head dpm_off;
|
|
||||||
extern struct list_head dpm_off_irq;
|
|
||||||
|
|
||||||
|
|
||||||
static inline struct dev_pm_info * to_pm_info(struct list_head * entry)
|
|
||||||
{
|
|
||||||
return container_of(entry, struct dev_pm_info, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct device * to_device(struct list_head * entry)
|
static inline struct device * to_device(struct list_head * entry)
|
||||||
{
|
{
|
||||||
return container_of(to_pm_info(entry), struct device, power);
|
return container_of(entry, struct device, power.entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int device_pm_add(struct device *);
|
extern int device_pm_add(struct device *);
|
||||||
|
@ -49,19 +28,6 @@ extern void device_pm_remove(struct device *);
|
||||||
extern int dpm_sysfs_add(struct device *);
|
extern int dpm_sysfs_add(struct device *);
|
||||||
extern void dpm_sysfs_remove(struct device *);
|
extern void dpm_sysfs_remove(struct device *);
|
||||||
|
|
||||||
/*
|
|
||||||
* resume.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void dpm_resume(void);
|
|
||||||
extern void dpm_power_up(void);
|
|
||||||
extern int resume_device(struct device *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* suspend.c
|
|
||||||
*/
|
|
||||||
extern int suspend_device(struct device *, pm_message_t);
|
|
||||||
|
|
||||||
#else /* CONFIG_PM_SLEEP */
|
#else /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* resume.c - Functions for waking devices up.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2003 Patrick Mochel
|
|
||||||
* Copyright (c) 2003 Open Source Development Labs
|
|
||||||
*
|
|
||||||
* This file is released under the GPLv2
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/resume-trace.h>
|
|
||||||
#include "../base.h"
|
|
||||||
#include "power.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* resume_device - Restore state for one device.
|
|
||||||
* @dev: Device.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
int resume_device(struct device * dev)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
TRACE_DEVICE(dev);
|
|
||||||
TRACE_RESUME(0);
|
|
||||||
|
|
||||||
down(&dev->sem);
|
|
||||||
|
|
||||||
if (dev->bus && dev->bus->resume) {
|
|
||||||
dev_dbg(dev,"resuming\n");
|
|
||||||
error = dev->bus->resume(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error && dev->type && dev->type->resume) {
|
|
||||||
dev_dbg(dev,"resuming\n");
|
|
||||||
error = dev->type->resume(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error && dev->class && dev->class->resume) {
|
|
||||||
dev_dbg(dev,"class resume\n");
|
|
||||||
error = dev->class->resume(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
up(&dev->sem);
|
|
||||||
|
|
||||||
TRACE_RESUME(error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int resume_device_early(struct device * dev)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
TRACE_DEVICE(dev);
|
|
||||||
TRACE_RESUME(0);
|
|
||||||
if (dev->bus && dev->bus->resume_early) {
|
|
||||||
dev_dbg(dev,"EARLY resume\n");
|
|
||||||
error = dev->bus->resume_early(dev);
|
|
||||||
}
|
|
||||||
TRACE_RESUME(error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Resume the devices that have either not gone through
|
|
||||||
* the late suspend, or that did go through it but also
|
|
||||||
* went through the early resume
|
|
||||||
*/
|
|
||||||
void dpm_resume(void)
|
|
||||||
{
|
|
||||||
mutex_lock(&dpm_list_mtx);
|
|
||||||
while(!list_empty(&dpm_off)) {
|
|
||||||
struct list_head * entry = dpm_off.next;
|
|
||||||
struct device * dev = to_device(entry);
|
|
||||||
|
|
||||||
get_device(dev);
|
|
||||||
list_move_tail(entry, &dpm_active);
|
|
||||||
|
|
||||||
mutex_unlock(&dpm_list_mtx);
|
|
||||||
resume_device(dev);
|
|
||||||
mutex_lock(&dpm_list_mtx);
|
|
||||||
put_device(dev);
|
|
||||||
}
|
|
||||||
mutex_unlock(&dpm_list_mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* device_resume - Restore state of each device in system.
|
|
||||||
*
|
|
||||||
* Walk the dpm_off list, remove each entry, resume the device,
|
|
||||||
* then add it to the dpm_active list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void device_resume(void)
|
|
||||||
{
|
|
||||||
might_sleep();
|
|
||||||
mutex_lock(&dpm_mtx);
|
|
||||||
dpm_resume();
|
|
||||||
mutex_unlock(&dpm_mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(device_resume);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* dpm_power_up - Power on some devices.
|
|
||||||
*
|
|
||||||
* Walk the dpm_off_irq list and power each device up. This
|
|
||||||
* is used for devices that required they be powered down with
|
|
||||||
* interrupts disabled. As devices are powered on, they are moved
|
|
||||||
* to the dpm_active list.
|
|
||||||
*
|
|
||||||
* Interrupts must be disabled when calling this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void dpm_power_up(void)
|
|
||||||
{
|
|
||||||
while(!list_empty(&dpm_off_irq)) {
|
|
||||||
struct list_head * entry = dpm_off_irq.next;
|
|
||||||
struct device * dev = to_device(entry);
|
|
||||||
|
|
||||||
list_move_tail(entry, &dpm_off);
|
|
||||||
resume_device_early(dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* device_power_up - Turn on all devices that need special attention.
|
|
||||||
*
|
|
||||||
* Power on system devices then devices that required we shut them down
|
|
||||||
* with interrupts disabled.
|
|
||||||
* Called with interrupts disabled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void device_power_up(void)
|
|
||||||
{
|
|
||||||
sysdev_resume();
|
|
||||||
dpm_power_up();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(device_power_up);
|
|
||||||
|
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
* suspend.c - Functions for putting devices to sleep.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2003 Patrick Mochel
|
|
||||||
* Copyright (c) 2003 Open Source Development Labs
|
|
||||||
*
|
|
||||||
* This file is released under the GPLv2
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/kallsyms.h>
|
|
||||||
#include <linux/pm.h>
|
|
||||||
#include "../base.h"
|
|
||||||
#include "power.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The entries in the dpm_active list are in a depth first order, simply
|
|
||||||
* because children are guaranteed to be discovered after parents, and
|
|
||||||
* are inserted at the back of the list on discovery.
|
|
||||||
*
|
|
||||||
* All list on the suspend path are done in reverse order, so we operate
|
|
||||||
* on the leaves of the device tree (or forests, depending on how you want
|
|
||||||
* to look at it ;) first. As nodes are removed from the back of the list,
|
|
||||||
* they are inserted into the front of their destintation lists.
|
|
||||||
*
|
|
||||||
* Things are the reverse on the resume path - iterations are done in
|
|
||||||
* forward order, and nodes are inserted at the back of their destination
|
|
||||||
* lists. This way, the ancestors will be accessed before their descendents.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline char *suspend_verb(u32 event)
|
|
||||||
{
|
|
||||||
switch (event) {
|
|
||||||
case PM_EVENT_SUSPEND: return "suspend";
|
|
||||||
case PM_EVENT_FREEZE: return "freeze";
|
|
||||||
case PM_EVENT_PRETHAW: return "prethaw";
|
|
||||||
default: return "(unknown suspend event)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
|
|
||||||
{
|
|
||||||
dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
|
|
||||||
((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
|
|
||||||
", may wakeup" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* suspend_device - Save state of one device.
|
|
||||||
* @dev: Device.
|
|
||||||
* @state: Power state device is entering.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int suspend_device(struct device * dev, pm_message_t state)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
down(&dev->sem);
|
|
||||||
if (dev->power.power_state.event) {
|
|
||||||
dev_dbg(dev, "PM: suspend %d-->%d\n",
|
|
||||||
dev->power.power_state.event, state.event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev->class && dev->class->suspend) {
|
|
||||||
suspend_device_dbg(dev, state, "class ");
|
|
||||||
error = dev->class->suspend(dev, state);
|
|
||||||
suspend_report_result(dev->class->suspend, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error && dev->type && dev->type->suspend) {
|
|
||||||
suspend_device_dbg(dev, state, "type ");
|
|
||||||
error = dev->type->suspend(dev, state);
|
|
||||||
suspend_report_result(dev->type->suspend, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error && dev->bus && dev->bus->suspend) {
|
|
||||||
suspend_device_dbg(dev, state, "");
|
|
||||||
error = dev->bus->suspend(dev, state);
|
|
||||||
suspend_report_result(dev->bus->suspend, error);
|
|
||||||
}
|
|
||||||
up(&dev->sem);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is called with interrupts off, only a single CPU
|
|
||||||
* running. We can't acquire a mutex or semaphore (and we don't
|
|
||||||
* need the protection)
|
|
||||||
*/
|
|
||||||
static int suspend_device_late(struct device *dev, pm_message_t state)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (dev->bus && dev->bus->suspend_late) {
|
|
||||||
suspend_device_dbg(dev, state, "LATE ");
|
|
||||||
error = dev->bus->suspend_late(dev, state);
|
|
||||||
suspend_report_result(dev->bus->suspend_late, error);
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* device_suspend - Save state and stop all devices in system.
|
|
||||||
* @state: Power state to put each device in.
|
|
||||||
*
|
|
||||||
* Walk the dpm_active list, call ->suspend() for each device, and move
|
|
||||||
* it to the dpm_off list.
|
|
||||||
*
|
|
||||||
* (For historical reasons, if it returns -EAGAIN, that used to mean
|
|
||||||
* that the device would be called again with interrupts disabled.
|
|
||||||
* These days, we use the "suspend_late()" callback for that, so we
|
|
||||||
* print a warning and consider it an error).
|
|
||||||
*
|
|
||||||
* If we get a different error, try and back out.
|
|
||||||
*
|
|
||||||
* If we hit a failure with any of the devices, call device_resume()
|
|
||||||
* above to bring the suspended devices back to life.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
int device_suspend(pm_message_t state)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
might_sleep();
|
|
||||||
mutex_lock(&dpm_mtx);
|
|
||||||
mutex_lock(&dpm_list_mtx);
|
|
||||||
while (!list_empty(&dpm_active) && error == 0) {
|
|
||||||
struct list_head * entry = dpm_active.prev;
|
|
||||||
struct device * dev = to_device(entry);
|
|
||||||
|
|
||||||
get_device(dev);
|
|
||||||
mutex_unlock(&dpm_list_mtx);
|
|
||||||
|
|
||||||
error = suspend_device(dev, state);
|
|
||||||
|
|
||||||
mutex_lock(&dpm_list_mtx);
|
|
||||||
|
|
||||||
/* Check if the device got removed */
|
|
||||||
if (!list_empty(&dev->power.entry)) {
|
|
||||||
/* Move it to the dpm_off list */
|
|
||||||
if (!error)
|
|
||||||
list_move(&dev->power.entry, &dpm_off);
|
|
||||||
}
|
|
||||||
if (error)
|
|
||||||
printk(KERN_ERR "Could not suspend device %s: "
|
|
||||||
"error %d%s\n",
|
|
||||||
kobject_name(&dev->kobj), error,
|
|
||||||
error == -EAGAIN ? " (please convert to suspend_late)" : "");
|
|
||||||
put_device(dev);
|
|
||||||
}
|
|
||||||
mutex_unlock(&dpm_list_mtx);
|
|
||||||
if (error)
|
|
||||||
dpm_resume();
|
|
||||||
|
|
||||||
mutex_unlock(&dpm_mtx);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(device_suspend);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* device_power_down - Shut down special devices.
|
|
||||||
* @state: Power state to enter.
|
|
||||||
*
|
|
||||||
* Walk the dpm_off_irq list, calling ->power_down() for each device that
|
|
||||||
* couldn't power down the device with interrupts enabled. When we're
|
|
||||||
* done, power down system devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int device_power_down(pm_message_t state)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
struct device * dev;
|
|
||||||
|
|
||||||
while (!list_empty(&dpm_off)) {
|
|
||||||
struct list_head * entry = dpm_off.prev;
|
|
||||||
|
|
||||||
dev = to_device(entry);
|
|
||||||
error = suspend_device_late(dev, state);
|
|
||||||
if (error)
|
|
||||||
goto Error;
|
|
||||||
list_move(&dev->power.entry, &dpm_off_irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = sysdev_suspend(state);
|
|
||||||
Done:
|
|
||||||
return error;
|
|
||||||
Error:
|
|
||||||
printk(KERN_ERR "Could not power down device %s: "
|
|
||||||
"error %d\n", kobject_name(&dev->kobj), error);
|
|
||||||
dpm_power_up();
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(device_power_down);
|
|
||||||
|
|
||||||
void __suspend_report_result(const char *function, void *fn, int ret)
|
|
||||||
{
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "%s(): ", function);
|
|
||||||
print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
|
|
||||||
printk("%d\n", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(__suspend_report_result);
|
|
|
@ -139,7 +139,7 @@ int sysdev_class_register(struct sysdev_class * cls)
|
||||||
kobject_name(&cls->kset.kobj));
|
kobject_name(&cls->kset.kobj));
|
||||||
INIT_LIST_HEAD(&cls->drivers);
|
INIT_LIST_HEAD(&cls->drivers);
|
||||||
cls->kset.kobj.parent = &system_subsys.kobj;
|
cls->kset.kobj.parent = &system_subsys.kobj;
|
||||||
kset_set_kset_s(cls, system_subsys);
|
cls->kset.kobj.kset = &system_subsys;
|
||||||
return kset_register(&cls->kset);
|
return kset_register(&cls->kset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,25 +153,22 @@ void sysdev_class_unregister(struct sysdev_class * cls)
|
||||||
EXPORT_SYMBOL_GPL(sysdev_class_register);
|
EXPORT_SYMBOL_GPL(sysdev_class_register);
|
||||||
EXPORT_SYMBOL_GPL(sysdev_class_unregister);
|
EXPORT_SYMBOL_GPL(sysdev_class_unregister);
|
||||||
|
|
||||||
|
|
||||||
static LIST_HEAD(sysdev_drivers);
|
|
||||||
static DEFINE_MUTEX(sysdev_drivers_lock);
|
static DEFINE_MUTEX(sysdev_drivers_lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysdev_driver_register - Register auxillary driver
|
* sysdev_driver_register - Register auxillary driver
|
||||||
* @cls: Device class driver belongs to.
|
* @cls: Device class driver belongs to.
|
||||||
* @drv: Driver.
|
* @drv: Driver.
|
||||||
*
|
*
|
||||||
* If @cls is valid, then @drv is inserted into @cls->drivers to be
|
* @drv is inserted into @cls->drivers to be
|
||||||
* called on each operation on devices of that class. The refcount
|
* called on each operation on devices of that class. The refcount
|
||||||
* of @cls is incremented.
|
* of @cls is incremented.
|
||||||
* Otherwise, @drv is inserted into sysdev_drivers, and called for
|
|
||||||
* each device.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int sysdev_driver_register(struct sysdev_class * cls,
|
int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
|
||||||
struct sysdev_driver * drv)
|
|
||||||
{
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
mutex_lock(&sysdev_drivers_lock);
|
mutex_lock(&sysdev_drivers_lock);
|
||||||
if (cls && kset_get(&cls->kset)) {
|
if (cls && kset_get(&cls->kset)) {
|
||||||
list_add_tail(&drv->entry, &cls->drivers);
|
list_add_tail(&drv->entry, &cls->drivers);
|
||||||
|
@ -182,10 +179,13 @@ int sysdev_driver_register(struct sysdev_class * cls,
|
||||||
list_for_each_entry(dev, &cls->kset.list, kobj.entry)
|
list_for_each_entry(dev, &cls->kset.list, kobj.entry)
|
||||||
drv->add(dev);
|
drv->add(dev);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
list_add_tail(&drv->entry, &sysdev_drivers);
|
err = -EINVAL;
|
||||||
|
printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__);
|
||||||
|
WARN_ON(1);
|
||||||
|
}
|
||||||
mutex_unlock(&sysdev_drivers_lock);
|
mutex_unlock(&sysdev_drivers_lock);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,12 +251,6 @@ int sysdev_register(struct sys_device * sysdev)
|
||||||
* code that should have called us.
|
* code that should have called us.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Notify global drivers */
|
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->add)
|
|
||||||
drv->add(sysdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify class auxillary drivers */
|
/* Notify class auxillary drivers */
|
||||||
list_for_each_entry(drv, &cls->drivers, entry) {
|
list_for_each_entry(drv, &cls->drivers, entry) {
|
||||||
if (drv->add)
|
if (drv->add)
|
||||||
|
@ -272,11 +266,6 @@ void sysdev_unregister(struct sys_device * sysdev)
|
||||||
struct sysdev_driver * drv;
|
struct sysdev_driver * drv;
|
||||||
|
|
||||||
mutex_lock(&sysdev_drivers_lock);
|
mutex_lock(&sysdev_drivers_lock);
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->remove)
|
|
||||||
drv->remove(sysdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
|
list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
|
||||||
if (drv->remove)
|
if (drv->remove)
|
||||||
drv->remove(sysdev);
|
drv->remove(sysdev);
|
||||||
|
@ -293,7 +282,7 @@ void sysdev_unregister(struct sys_device * sysdev)
|
||||||
*
|
*
|
||||||
* Loop over each class of system devices, and the devices in each
|
* Loop over each class of system devices, and the devices in each
|
||||||
* of those classes. For each device, we call the shutdown method for
|
* of those classes. For each device, we call the shutdown method for
|
||||||
* each driver registered for the device - the globals, the auxillaries,
|
* each driver registered for the device - the auxillaries,
|
||||||
* and the class driver.
|
* and the class driver.
|
||||||
*
|
*
|
||||||
* Note: The list is iterated in reverse order, so that we shut down
|
* Note: The list is iterated in reverse order, so that we shut down
|
||||||
|
@ -320,13 +309,7 @@ void sysdev_shutdown(void)
|
||||||
struct sysdev_driver * drv;
|
struct sysdev_driver * drv;
|
||||||
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
||||||
|
|
||||||
/* Call global drivers first. */
|
/* Call auxillary drivers first */
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->shutdown)
|
|
||||||
drv->shutdown(sysdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call auxillary drivers next. */
|
|
||||||
list_for_each_entry(drv, &cls->drivers, entry) {
|
list_for_each_entry(drv, &cls->drivers, entry) {
|
||||||
if (drv->shutdown)
|
if (drv->shutdown)
|
||||||
drv->shutdown(sysdev);
|
drv->shutdown(sysdev);
|
||||||
|
@ -354,12 +337,6 @@ static void __sysdev_resume(struct sys_device *dev)
|
||||||
if (drv->resume)
|
if (drv->resume)
|
||||||
drv->resume(dev);
|
drv->resume(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call global drivers. */
|
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->resume)
|
|
||||||
drv->resume(dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,16 +370,7 @@ int sysdev_suspend(pm_message_t state)
|
||||||
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
||||||
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
||||||
|
|
||||||
/* Call global drivers first. */
|
/* Call auxillary drivers first */
|
||||||
list_for_each_entry(drv, &sysdev_drivers, entry) {
|
|
||||||
if (drv->suspend) {
|
|
||||||
ret = drv->suspend(sysdev, state);
|
|
||||||
if (ret)
|
|
||||||
goto gbl_driver;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call auxillary drivers next. */
|
|
||||||
list_for_each_entry(drv, &cls->drivers, entry) {
|
list_for_each_entry(drv, &cls->drivers, entry) {
|
||||||
if (drv->suspend) {
|
if (drv->suspend) {
|
||||||
ret = drv->suspend(sysdev, state);
|
ret = drv->suspend(sysdev, state);
|
||||||
|
@ -436,18 +404,7 @@ int sysdev_suspend(pm_message_t state)
|
||||||
if (err_drv->resume)
|
if (err_drv->resume)
|
||||||
err_drv->resume(sysdev);
|
err_drv->resume(sysdev);
|
||||||
}
|
}
|
||||||
drv = NULL;
|
|
||||||
|
|
||||||
gbl_driver:
|
|
||||||
if (drv)
|
|
||||||
printk(KERN_ERR "sysdev driver suspend failed for %s\n",
|
|
||||||
kobject_name(&sysdev->kobj));
|
|
||||||
list_for_each_entry(err_drv, &sysdev_drivers, entry) {
|
|
||||||
if (err_drv == drv)
|
|
||||||
break;
|
|
||||||
if (err_drv->resume)
|
|
||||||
err_drv->resume(sysdev);
|
|
||||||
}
|
|
||||||
/* resume other sysdevs in current class */
|
/* resume other sysdevs in current class */
|
||||||
list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
|
list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
|
||||||
if (err_dev == sysdev)
|
if (err_dev == sysdev)
|
||||||
|
|
|
@ -513,7 +513,7 @@ static int __init dsp56k_init_driver(void)
|
||||||
err = PTR_ERR(dsp56k_class);
|
err = PTR_ERR(dsp56k_class);
|
||||||
goto out_chrdev;
|
goto out_chrdev;
|
||||||
}
|
}
|
||||||
class_device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
|
device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
|
||||||
|
|
||||||
printk(banner);
|
printk(banner);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -527,7 +527,7 @@ module_init(dsp56k_init_driver);
|
||||||
|
|
||||||
static void __exit dsp56k_cleanup_driver(void)
|
static void __exit dsp56k_cleanup_driver(void)
|
||||||
{
|
{
|
||||||
class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
||||||
class_destroy(dsp56k_class);
|
class_destroy(dsp56k_class);
|
||||||
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
|
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,8 +411,8 @@ cleanup_module(void)
|
||||||
iiResetDelay( i2BoardPtrTable[i] );
|
iiResetDelay( i2BoardPtrTable[i] );
|
||||||
/* free io addresses and Tibet */
|
/* free io addresses and Tibet */
|
||||||
release_region( ip2config.addr[i], 8 );
|
release_region( ip2config.addr[i], 8 );
|
||||||
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
|
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
|
||||||
class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
|
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
|
||||||
}
|
}
|
||||||
/* Disable and remove interrupt handler. */
|
/* Disable and remove interrupt handler. */
|
||||||
if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
|
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
|
||||||
class_device_create(ip2_class, NULL,
|
device_create(ip2_class, NULL,
|
||||||
MKDEV(IP2_IPL_MAJOR, 4 * i),
|
MKDEV(IP2_IPL_MAJOR, 4 * i),
|
||||||
NULL, "ipl%d", i);
|
"ipl%d", i);
|
||||||
class_device_create(ip2_class, NULL,
|
device_create(ip2_class, NULL,
|
||||||
MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
|
MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
|
||||||
NULL, "stat%d", i);
|
"stat%d", i);
|
||||||
|
|
||||||
for ( box = 0; box < ABS_MAX_BOXES; ++box )
|
for ( box = 0; box < ABS_MAX_BOXES; ++box )
|
||||||
{
|
{
|
||||||
|
|
|
@ -865,7 +865,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
|
||||||
entry->dev = dev;
|
entry->dev = dev;
|
||||||
|
|
||||||
mutex_lock(®_list_mutex);
|
mutex_lock(®_list_mutex);
|
||||||
class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
|
device_create(ipmi_class, device, dev, "ipmi%d", if_num);
|
||||||
list_add(&entry->link, ®_list);
|
list_add(&entry->link, ®_list);
|
||||||
mutex_unlock(®_list_mutex);
|
mutex_unlock(®_list_mutex);
|
||||||
}
|
}
|
||||||
|
@ -883,7 +883,7 @@ static void ipmi_smi_gone(int if_num)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class_device_destroy(ipmi_class, dev);
|
device_destroy(ipmi_class, dev);
|
||||||
mutex_unlock(®_list_mutex);
|
mutex_unlock(®_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,7 +938,7 @@ static __exit void cleanup_ipmi(void)
|
||||||
mutex_lock(®_list_mutex);
|
mutex_lock(®_list_mutex);
|
||||||
list_for_each_entry_safe(entry, entry2, ®_list, link) {
|
list_for_each_entry_safe(entry, entry2, ®_list, link) {
|
||||||
list_del(&entry->link);
|
list_del(&entry->link);
|
||||||
class_device_destroy(ipmi_class, entry->dev);
|
device_destroy(ipmi_class, entry->dev);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
}
|
}
|
||||||
mutex_unlock(®_list_mutex);
|
mutex_unlock(®_list_mutex);
|
||||||
|
|
|
@ -4624,9 +4624,8 @@ static int __init istallion_module_init(void)
|
||||||
|
|
||||||
istallion_class = class_create(THIS_MODULE, "staliomem");
|
istallion_class = class_create(THIS_MODULE, "staliomem");
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
class_device_create(istallion_class, NULL,
|
device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
|
||||||
MKDEV(STL_SIOMEMMAJOR, i),
|
"staliomem%d", i);
|
||||||
NULL, "staliomem%d", i);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_deinit:
|
err_deinit:
|
||||||
|
@ -4659,8 +4658,7 @@ static void __exit istallion_module_exit(void)
|
||||||
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR,
|
device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
|
||||||
j));
|
|
||||||
class_destroy(istallion_class);
|
class_destroy(istallion_class);
|
||||||
|
|
||||||
pci_unregister_driver(&stli_pcidriver);
|
pci_unregister_driver(&stli_pcidriver);
|
||||||
|
|
|
@ -799,8 +799,7 @@ static int lp_register(int nr, struct parport *port)
|
||||||
if (reset)
|
if (reset)
|
||||||
lp_reset(nr);
|
lp_reset(nr);
|
||||||
|
|
||||||
class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev,
|
device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);
|
||||||
"lp%d", nr);
|
|
||||||
|
|
||||||
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
|
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
|
||||||
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
|
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
|
||||||
|
@ -971,7 +970,7 @@ static void lp_cleanup_module (void)
|
||||||
if (lp_table[offset].dev == NULL)
|
if (lp_table[offset].dev == NULL)
|
||||||
continue;
|
continue;
|
||||||
parport_unregister_device(lp_table[offset].dev);
|
parport_unregister_device(lp_table[offset].dev);
|
||||||
class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
|
device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
|
||||||
}
|
}
|
||||||
class_destroy(lp_class);
|
class_destroy(lp_class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1863,8 +1863,7 @@ static int cm4000_probe(struct pcmcia_device *link)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
|
device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i);
|
||||||
"cmm%d", i);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1888,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link)
|
||||||
dev_table[devno] = NULL;
|
dev_table[devno] = NULL;
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
|
|
||||||
class_device_destroy(cmm_class, MKDEV(major, devno));
|
device_destroy(cmm_class, MKDEV(major, devno));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -642,8 +642,7 @@ static int reader_probe(struct pcmcia_device *link)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
|
device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i);
|
||||||
"cmx%d", i);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -666,7 +665,7 @@ static void reader_detach(struct pcmcia_device *link)
|
||||||
dev_table[devno] = NULL;
|
dev_table[devno] = NULL;
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
|
|
||||||
class_device_destroy(cmx_class, MKDEV(major, devno));
|
device_destroy(cmx_class, MKDEV(major, devno));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,14 +248,19 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
|
||||||
|
module_param(legacy_count, int, 0);
|
||||||
|
|
||||||
static void __init legacy_pty_init(void)
|
static void __init legacy_pty_init(void)
|
||||||
{
|
{
|
||||||
|
if (legacy_count <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
pty_driver = alloc_tty_driver(NR_PTYS);
|
pty_driver = alloc_tty_driver(legacy_count);
|
||||||
if (!pty_driver)
|
if (!pty_driver)
|
||||||
panic("Couldn't allocate pty driver");
|
panic("Couldn't allocate pty driver");
|
||||||
|
|
||||||
pty_slave_driver = alloc_tty_driver(NR_PTYS);
|
pty_slave_driver = alloc_tty_driver(legacy_count);
|
||||||
if (!pty_slave_driver)
|
if (!pty_slave_driver)
|
||||||
panic("Couldn't allocate pty slave driver");
|
panic("Couldn't allocate pty slave driver");
|
||||||
|
|
||||||
|
|
|
@ -255,10 +255,7 @@ static const struct file_operations raw_ctl_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cdev raw_cdev = {
|
static struct cdev raw_cdev;
|
||||||
.kobj = {.name = "raw", },
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init raw_init(void)
|
static int __init raw_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -441,8 +441,7 @@ scdrv_init(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_device_create(snsc_class, NULL, dev, NULL,
|
device_create(snsc_class, NULL, dev, "%s", devname);
|
||||||
"%s", devname);
|
|
||||||
|
|
||||||
ia64_sn_irtr_intr_enable(scd->scd_nasid,
|
ia64_sn_irtr_intr_enable(scd->scd_nasid,
|
||||||
0 /*ignored */ ,
|
0 /*ignored */ ,
|
||||||
|
|
|
@ -4778,9 +4778,8 @@ static int __init stallion_module_init(void)
|
||||||
if (IS_ERR(stallion_class))
|
if (IS_ERR(stallion_class))
|
||||||
printk("STALLION: failed to create class\n");
|
printk("STALLION: failed to create class\n");
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
class_device_create(stallion_class, NULL,
|
device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
|
||||||
MKDEV(STL_SIOMEMMAJOR, i), NULL,
|
"staliomem%d", i);
|
||||||
"staliomem%d", i);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_unrtty:
|
err_unrtty:
|
||||||
|
@ -4816,7 +4815,7 @@ static void __exit stallion_module_exit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
|
device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
|
||||||
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
|
||||||
class_destroy(stallion_class);
|
class_destroy(stallion_class);
|
||||||
|
|
||||||
|
|
|
@ -441,8 +441,8 @@ tipar_register(int nr, struct parport *port)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR,
|
device_create(tipar_class, port->dev, MKDEV(TIPAR_MAJOR,
|
||||||
TIPAR_MINOR + nr), port->dev, "par%d", nr);
|
TIPAR_MINOR + nr), "par%d", nr);
|
||||||
|
|
||||||
/* Display informations */
|
/* Display informations */
|
||||||
pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq ==
|
pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq ==
|
||||||
|
@ -534,7 +534,7 @@ tipar_cleanup_module(void)
|
||||||
if (table[i].dev == NULL)
|
if (table[i].dev == NULL)
|
||||||
continue;
|
continue;
|
||||||
parport_unregister_device(table[i].dev);
|
parport_unregister_device(table[i].dev);
|
||||||
class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
|
device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
|
||||||
}
|
}
|
||||||
class_destroy(tipar_class);
|
class_destroy(tipar_class);
|
||||||
|
|
||||||
|
|
|
@ -871,10 +871,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
||||||
state[i].cur_part = 0;
|
state[i].cur_part = 0;
|
||||||
for (j = 0; j < MAX_PARTITIONS; ++j)
|
for (j = 0; j < MAX_PARTITIONS; ++j)
|
||||||
state[i].part_stat_rwi[j] = VIOT_IDLE;
|
state[i].part_stat_rwi[j] = VIOT_IDLE;
|
||||||
class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
|
device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
|
||||||
"iseries!vt%d", i);
|
"iseries!vt%d", i);
|
||||||
class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
|
device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
|
||||||
NULL, "iseries!nvt%d", i);
|
"iseries!nvt%d", i);
|
||||||
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
|
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
|
||||||
"resource %10.10s type %4.4s, model %3.3s\n",
|
"resource %10.10s type %4.4s, model %3.3s\n",
|
||||||
i, viotape_unitinfo[i].rsrcname,
|
i, viotape_unitinfo[i].rsrcname,
|
||||||
|
@ -886,8 +886,8 @@ static int viotape_remove(struct vio_dev *vdev)
|
||||||
{
|
{
|
||||||
int i = vdev->unit_address;
|
int i = vdev->unit_address;
|
||||||
|
|
||||||
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
|
device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
|
||||||
class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
|
device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -830,7 +830,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
||||||
/* prepare interface data */
|
/* prepare interface data */
|
||||||
policy->kobj.parent = &sys_dev->kobj;
|
policy->kobj.parent = &sys_dev->kobj;
|
||||||
policy->kobj.ktype = &ktype_cpufreq;
|
policy->kobj.ktype = &ktype_cpufreq;
|
||||||
strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
|
kobject_set_name(&policy->kobj, "cpufreq");
|
||||||
|
|
||||||
ret = kobject_register(&policy->kobj);
|
ret = kobject_register(&policy->kobj);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -743,7 +743,7 @@ static struct kobj_type ktype_mc_set_attribs = {
|
||||||
* /sys/devices/system/edac/mc
|
* /sys/devices/system/edac/mc
|
||||||
*/
|
*/
|
||||||
static struct kset mc_kset = {
|
static struct kset mc_kset = {
|
||||||
.kobj = {.name = "mc", .ktype = &ktype_mc_set_attribs },
|
.kobj = {.ktype = &ktype_mc_set_attribs },
|
||||||
.ktype = &ktype_mci,
|
.ktype = &ktype_mci,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1010,6 +1010,7 @@ int edac_sysfs_setup_mc_kset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init the MC's kobject */
|
/* Init the MC's kobject */
|
||||||
|
kobject_set_name(&mc_kset.kobj, "mc");
|
||||||
mc_kset.kobj.parent = &edac_class->kset.kobj;
|
mc_kset.kobj.parent = &edac_class->kset.kobj;
|
||||||
|
|
||||||
/* register the mc_kset */
|
/* register the mc_kset */
|
||||||
|
|
|
@ -128,16 +128,11 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp,
|
static int eisa_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct eisa_device *edev = to_eisa_device(dev);
|
struct eisa_device *edev = to_eisa_device(dev);
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(env, "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
|
||||||
"MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,23 +130,16 @@ static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fw_unit_uevent(struct device *dev, char **envp, int num_envp,
|
fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct fw_unit *unit = fw_unit(dev);
|
struct fw_unit *unit = fw_unit(dev);
|
||||||
char modalias[64];
|
char modalias[64];
|
||||||
int length = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
get_modalias(unit, modalias, sizeof(modalias));
|
get_modalias(unit, modalias, sizeof(modalias));
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "MODALIAS=%s", modalias))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=%s", modalias))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,21 +13,31 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/autoconf.h>
|
#include <linux/autoconf.h>
|
||||||
|
|
||||||
#define DEFINE_DMI_ATTR(_name, _mode, _show) \
|
struct dmi_device_attribute{
|
||||||
static struct device_attribute sys_dmi_##_name##_attr = \
|
struct device_attribute dev_attr;
|
||||||
__ATTR(_name, _mode, _show, NULL);
|
int field;
|
||||||
|
};
|
||||||
|
#define to_dmi_dev_attr(_dev_attr) \
|
||||||
|
container_of(_dev_attr, struct dmi_device_attribute, dev_attr)
|
||||||
|
|
||||||
#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
|
static ssize_t sys_dmi_field_show(struct device *dev,
|
||||||
static ssize_t sys_dmi_##_name##_show(struct device *dev, \
|
struct device_attribute *attr,
|
||||||
struct device_attribute *attr, \
|
char *page)
|
||||||
char *page) \
|
{
|
||||||
{ \
|
int field = to_dmi_dev_attr(attr)->field;
|
||||||
ssize_t len; \
|
ssize_t len;
|
||||||
len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
|
len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(field));
|
||||||
page[len-1] = '\n'; \
|
page[len-1] = '\n';
|
||||||
return len; \
|
return len;
|
||||||
} \
|
}
|
||||||
DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
|
|
||||||
|
#define DMI_ATTR(_name, _mode, _show, _field) \
|
||||||
|
{ .dev_attr = __ATTR(_name, _mode, _show, NULL), \
|
||||||
|
.field = _field }
|
||||||
|
|
||||||
|
#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
|
||||||
|
static struct dmi_device_attribute sys_dmi_##_name##_attr = \
|
||||||
|
DMI_ATTR(_name, _mode, sys_dmi_field_show, _field);
|
||||||
|
|
||||||
DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR);
|
DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR);
|
||||||
DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION);
|
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,
|
||||||
return r+1;
|
return r+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show);
|
static struct device_attribute sys_dmi_modalias_attr =
|
||||||
|
__ATTR(modalias, 0444, sys_dmi_modalias_show, NULL);
|
||||||
|
|
||||||
static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
|
static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
|
||||||
|
|
||||||
|
@ -134,14 +145,17 @@ static struct attribute_group* sys_dmi_attribute_groups[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dmi_dev_uevent(struct device *dev, char **envp,
|
static int dmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
strcpy(buffer, "MODALIAS=");
|
ssize_t len;
|
||||||
get_modalias(buffer+9, buffer_size-9);
|
|
||||||
envp[0] = buffer;
|
|
||||||
envp[1] = NULL;
|
|
||||||
|
|
||||||
|
if (add_uevent_var(env, "MODALIAS="))
|
||||||
|
return -ENOMEM;
|
||||||
|
len = get_modalias(&env->buf[env->buflen - 1],
|
||||||
|
sizeof(env->buf) - env->buflen);
|
||||||
|
if (len >= (sizeof(env->buf) - env->buflen))
|
||||||
|
return -ENOMEM;
|
||||||
|
env->buflen += len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +171,7 @@ static struct device *dmi_dev;
|
||||||
|
|
||||||
#define ADD_DMI_ATTR(_name, _field) \
|
#define ADD_DMI_ATTR(_name, _field) \
|
||||||
if (dmi_get_system_info(_field)) \
|
if (dmi_get_system_info(_field)) \
|
||||||
sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
|
sys_dmi_attributes[i++] = &sys_dmi_##_name##_attr.dev_attr.attr;
|
||||||
|
|
||||||
extern int dmi_available;
|
extern int dmi_available;
|
||||||
|
|
||||||
|
|
|
@ -625,13 +625,13 @@ static void edd_release(struct kobject * kobj)
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kobj_type ktype_edd = {
|
static struct kobj_type edd_ktype = {
|
||||||
.release = edd_release,
|
.release = edd_release,
|
||||||
.sysfs_ops = &edd_attr_ops,
|
.sysfs_ops = &edd_attr_ops,
|
||||||
.default_attrs = def_attrs,
|
.default_attrs = def_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static decl_subsys(edd,&ktype_edd,NULL);
|
static decl_subsys(edd, &edd_ktype, NULL);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -402,7 +402,7 @@ static struct attribute *def_attrs[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kobj_type ktype_efivar = {
|
static struct kobj_type efivar_ktype = {
|
||||||
.release = efivar_release,
|
.release = efivar_release,
|
||||||
.sysfs_ops = &efivar_attr_ops,
|
.sysfs_ops = &efivar_attr_ops,
|
||||||
.default_attrs = def_attrs,
|
.default_attrs = def_attrs,
|
||||||
|
@ -583,7 +583,7 @@ static struct subsys_attribute *efi_subsys_attrs[] = {
|
||||||
NULL, /* maybe more in the future? */
|
NULL, /* maybe more in the future? */
|
||||||
};
|
};
|
||||||
|
|
||||||
static decl_subsys(vars, &ktype_efivar, NULL);
|
static decl_subsys(vars, &efivar_ktype, NULL);
|
||||||
static decl_subsys(efi, NULL, NULL);
|
static decl_subsys(efi, NULL, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -67,20 +67,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
|
/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
|
||||||
static int i2c_device_uevent(struct device *dev, char **envp, int num_envp,
|
static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
int i = 0, length = 0;
|
|
||||||
|
|
||||||
/* by definition, legacy drivers can't hotplug */
|
/* by definition, legacy drivers can't hotplug */
|
||||||
if (dev->driver || !client->driver_name)
|
if (dev->driver || !client->driver_name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
|
||||||
"MODALIAS=%s", client->driver_name))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
envp[i] = NULL;
|
|
||||||
dev_dbg(dev, "uevent\n");
|
dev_dbg(dev, "uevent\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1663,20 +1663,13 @@ static struct device_attribute ide_dev_attrs[] = {
|
||||||
__ATTR_NULL
|
__ATTR_NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ide_uevent(struct device *dev, char **envp, int num_envp,
|
static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
ide_drive_t *drive = to_ide_device(dev);
|
ide_drive_t *drive = to_ide_device(dev);
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(env, "MEDIA=%s", media_string(drive));
|
||||||
"MEDIA=%s", media_string(drive));
|
add_uevent_var(env, "DRIVENAME=%s", drive->name);
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
|
||||||
"DRIVENAME=%s", drive->name);
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=ide:m-%s", media_string(drive));
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,8 +153,7 @@ struct host_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
|
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
|
||||||
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||||
char *buffer, int buffer_size);
|
|
||||||
static void nodemgr_resume_ne(struct node_entry *ne);
|
static void nodemgr_resume_ne(struct node_entry *ne);
|
||||||
static void nodemgr_remove_ne(struct node_entry *ne);
|
static void nodemgr_remove_ne(struct node_entry *ne);
|
||||||
static struct node_entry *find_entry_by_guid(u64 guid);
|
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
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct unit_directory *ud;
|
struct unit_directory *ud;
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
/* ieee1394:venNmoNspNverN */
|
/* ieee1394:venNmoNspNverN */
|
||||||
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
|
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,
|
||||||
|
|
||||||
#define PUT_ENVP(fmt,val) \
|
#define PUT_ENVP(fmt,val) \
|
||||||
do { \
|
do { \
|
||||||
retval = add_uevent_var(envp, num_envp, &i, \
|
retval = add_uevent_var(env, fmt, val); \
|
||||||
buffer, buffer_size, &length, \
|
|
||||||
fmt, val); \
|
|
||||||
if (retval) \
|
if (retval) \
|
||||||
return retval; \
|
return retval; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -1201,15 +1195,12 @@ do { \
|
||||||
|
|
||||||
#undef PUT_ENVP
|
#undef PUT_ENVP
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,21 +434,18 @@ static void ib_device_release(struct class_device *cdev)
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ib_device_uevent(struct class_device *cdev, char **envp,
|
static int ib_device_uevent(struct class_device *cdev,
|
||||||
int num_envp, char *buf, int size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
|
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
|
||||||
int i = 0, len = 0;
|
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
|
if (add_uevent_var(env, "NAME=%s", dev->name))
|
||||||
"NAME=%s", dev->name))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It would be nice to pass the node GUID with the event...
|
* It would be nice to pass the node GUID with the event...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -859,87 +859,66 @@ static void input_dev_release(struct device *device)
|
||||||
* Input uevent interface - loading event handlers based on
|
* Input uevent interface - loading event handlers based on
|
||||||
* device bitfields.
|
* device bitfields.
|
||||||
*/
|
*/
|
||||||
static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
|
static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
|
||||||
char *buffer, int buffer_size, int *cur_len,
|
|
||||||
const char *name, unsigned long *bitmap, int max)
|
const char *name, unsigned long *bitmap, int max)
|
||||||
{
|
{
|
||||||
if (*cur_index >= num_envp - 1)
|
int len;
|
||||||
|
|
||||||
|
if (add_uevent_var(env, "%s=", name))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[*cur_index] = buffer + *cur_len;
|
len = input_print_bitmap(&env->buf[env->buflen - 1],
|
||||||
|
sizeof(env->buf) - env->buflen,
|
||||||
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name);
|
bitmap, max, 0);
|
||||||
if (*cur_len >= buffer_size)
|
if (len >= (sizeof(env->buf) - env->buflen))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*cur_len += input_print_bitmap(buffer + *cur_len,
|
env->buflen += len;
|
||||||
max(buffer_size - *cur_len, 0),
|
|
||||||
bitmap, max, 0) + 1;
|
|
||||||
if (*cur_len > buffer_size)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
(*cur_index)++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index,
|
static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
|
||||||
char *buffer, int buffer_size, int *cur_len,
|
|
||||||
struct input_dev *dev)
|
struct input_dev *dev)
|
||||||
{
|
{
|
||||||
if (*cur_index >= num_envp - 1)
|
int len;
|
||||||
|
|
||||||
|
if (add_uevent_var(env, "MODALIAS="))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[*cur_index] = buffer + *cur_len;
|
len = input_print_modalias(&env->buf[env->buflen - 1],
|
||||||
|
sizeof(env->buf) - env->buflen,
|
||||||
*cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0),
|
dev, 0);
|
||||||
"MODALIAS=");
|
if (len >= (sizeof(env->buf) - env->buflen))
|
||||||
if (*cur_len >= buffer_size)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*cur_len += input_print_modalias(buffer + *cur_len,
|
env->buflen += len;
|
||||||
max(buffer_size - *cur_len, 0),
|
|
||||||
dev, 0) + 1;
|
|
||||||
if (*cur_len > buffer_size)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
(*cur_index)++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
|
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
|
||||||
do { \
|
do { \
|
||||||
int err = add_uevent_var(envp, num_envp, &i, \
|
int err = add_uevent_var(env, fmt, val); \
|
||||||
buffer, buffer_size, &len, \
|
|
||||||
fmt, val); \
|
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
|
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
|
||||||
do { \
|
do { \
|
||||||
int err = input_add_uevent_bm_var(envp, num_envp, &i, \
|
int err = input_add_uevent_bm_var(env, name, bm, max); \
|
||||||
buffer, buffer_size, &len, \
|
|
||||||
name, bm, max); \
|
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
|
#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \
|
||||||
do { \
|
do { \
|
||||||
int err = input_add_uevent_modalias_var(envp, \
|
int err = input_add_uevent_modalias_var(env, dev); \
|
||||||
num_envp, &i, \
|
|
||||||
buffer, buffer_size, &len, \
|
|
||||||
dev); \
|
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int input_dev_uevent(struct device *device, char **envp,
|
static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct input_dev *dev = to_input_dev(device);
|
struct input_dev *dev = to_input_dev(device);
|
||||||
int i = 0;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
|
INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",
|
||||||
dev->id.bustype, dev->id.vendor,
|
dev->id.bustype, dev->id.vendor,
|
||||||
|
@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp,
|
||||||
|
|
||||||
INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
|
INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||||
MODULE_DESCRIPTION("PC Speaker beeper driver");
|
MODULE_DESCRIPTION("PC Speaker beeper driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:pcspkr");
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
/* Use the global PIT lock ! */
|
/* Use the global PIT lock ! */
|
||||||
|
|
|
@ -876,18 +876,14 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
|
|
||||||
#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
|
#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
|
||||||
do { \
|
do { \
|
||||||
int err = add_uevent_var(envp, num_envp, &i, \
|
int err = add_uevent_var(env, fmt, val); \
|
||||||
buffer, buffer_size, &len, \
|
|
||||||
fmt, val); \
|
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct serio *serio;
|
struct serio *serio;
|
||||||
int i = 0;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -900,7 +896,6 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
|
||||||
SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
|
SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
|
||||||
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
|
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
|
||||||
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
|
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -908,7 +903,7 @@ static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buf
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int serio_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3076,8 +3076,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
|
||||||
mddev->gendisk = disk;
|
mddev->gendisk = disk;
|
||||||
mutex_unlock(&disks_mutex);
|
mutex_unlock(&disks_mutex);
|
||||||
mddev->kobj.parent = &disk->kobj;
|
mddev->kobj.parent = &disk->kobj;
|
||||||
mddev->kobj.k_name = NULL;
|
kobject_set_name(&mddev->kobj, "%s", "md");
|
||||||
snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md");
|
|
||||||
mddev->kobj.ktype = &md_ktype;
|
mddev->kobj.ktype = &md_ktype;
|
||||||
if (kobject_register(&mddev->kobj))
|
if (kobject_register(&mddev->kobj))
|
||||||
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
|
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
|
||||||
|
|
|
@ -103,10 +103,7 @@ static struct file_operations dvb_device_fops =
|
||||||
.open = dvb_device_open,
|
.open = dvb_device_open,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cdev dvb_device_cdev = {
|
static struct cdev dvb_device_cdev;
|
||||||
.kobj = {.name = "dvb", },
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
int dvb_generic_open(struct inode *inode, struct file *file)
|
int dvb_generic_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
|
|
|
@ -905,8 +905,8 @@ struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pvr2_sysfs_hotplug(struct device *cd,char **envp,
|
static int pvr2_sysfs_hotplug(struct device *d,
|
||||||
int numenvp,char *buf,int size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
/* Even though we don't do anything here, we still need this function
|
/* Even though we don't do anything here, we still need this function
|
||||||
because sysfs will still try to call it. */
|
because sysfs will still try to call it. */
|
||||||
|
|
|
@ -57,16 +57,11 @@ static int tifm_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tifm_uevent(struct device *dev, char **envp, int num_envp,
|
static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
|
struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
|
||||||
"TIFM_CARD_TYPE=%s",
|
|
||||||
tifm_media_type_name(sock->type, 1)))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -58,12 +58,11 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
|
mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
int buf_size)
|
|
||||||
{
|
{
|
||||||
struct mmc_card *card = dev_to_mmc_card(dev);
|
struct mmc_card *card = dev_to_mmc_card(dev);
|
||||||
const char *type;
|
const char *type;
|
||||||
int i = 0, length = 0;
|
int retval = 0;
|
||||||
|
|
||||||
switch (card->type) {
|
switch (card->type) {
|
||||||
case MMC_TYPE_MMC:
|
case MMC_TYPE_MMC:
|
||||||
|
@ -80,20 +79,14 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
retval = add_uevent_var(env, "MMC_TYPE=%s", type);
|
||||||
buf, buf_size, &length,
|
if (retval)
|
||||||
"MMC_TYPE=%s", type))
|
return retval;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
|
||||||
buf, buf_size, &length,
|
|
||||||
"MMC_NAME=%s", mmc_card_name(card)))
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
envp[i] = NULL;
|
return retval;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmc_bus_probe(struct device *dev)
|
static int mmc_bus_probe(struct device *dev)
|
||||||
|
|
|
@ -1183,7 +1183,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
|
||||||
pool_count[i], pool_size[i],
|
pool_count[i], pool_size[i],
|
||||||
pool_active[i]);
|
pool_active[i]);
|
||||||
kobj->parent = &dev->dev.kobj;
|
kobj->parent = &dev->dev.kobj;
|
||||||
sprintf(kobj->name, "pool%d", i);
|
kobject_set_name(kobj, "pool%d", i);
|
||||||
kobj->ktype = &ktype_veth_pool;
|
kobj->ktype = &ktype_veth_pool;
|
||||||
kobject_register(kobj);
|
kobject_register(kobj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,9 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
int pci_uevent(struct device *dev, char **envp, int num_envp,
|
int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -17,37 +14,24 @@ int pci_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PCI_CLASS=%04X", pdev->class))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
|
|
||||||
pdev->subsystem_device))
|
pdev->subsystem_device))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PCI_SLOT_NAME=%s", pci_name(pdev)))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
|
|
||||||
pdev->vendor, pdev->device,
|
pdev->vendor, pdev->device,
|
||||||
pdev->subsystem_vendor, pdev->subsystem_device,
|
pdev->subsystem_vendor, pdev->subsystem_device,
|
||||||
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
|
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
|
||||||
(u8)(pdev->class)))
|
(u8)(pdev->class)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -694,66 +694,6 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
|
||||||
if ((slot == NULL) || (info == NULL))
|
if ((slot == NULL) || (info == NULL))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
|
||||||
* check all fields in the info structure, and update timestamps
|
|
||||||
* for the files referring to the fields that have now changed.
|
|
||||||
*/
|
|
||||||
if ((has_power_file(slot) == 0) &&
|
|
||||||
(slot->info->power_status != info->power_status)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_power.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_attention_file(slot) == 0) &&
|
|
||||||
(slot->info->attention_status != info->attention_status)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_attention.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_latch_file(slot) == 0) &&
|
|
||||||
(slot->info->latch_status != info->latch_status)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_latch.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_adapter_file(slot) == 0) &&
|
|
||||||
(slot->info->adapter_status != info->adapter_status)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_presence.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_address_file(slot) == 0) &&
|
|
||||||
(slot->info->address != info->address)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_address.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_max_bus_speed_file(slot) == 0) &&
|
|
||||||
(slot->info->max_bus_speed != info->max_bus_speed)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_max_bus_speed.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((has_cur_bus_speed_file(slot) == 0) &&
|
|
||||||
(slot->info->cur_bus_speed != info->cur_bus_speed)) {
|
|
||||||
retval = sysfs_update_file(&slot->kobj,
|
|
||||||
&hotplug_slot_attr_cur_bus_speed.attr);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
|
memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -129,17 +129,17 @@ struct kobj_type ktype_dlpar_io = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kset dlpar_io_kset = {
|
struct kset dlpar_io_kset = {
|
||||||
.kobj = {.name = DLPAR_KOBJ_NAME,
|
.kobj = {.ktype = &ktype_dlpar_io,
|
||||||
.ktype = &ktype_dlpar_io,
|
|
||||||
.parent = &pci_hotplug_slots_subsys.kobj},
|
.parent = &pci_hotplug_slots_subsys.kobj},
|
||||||
.ktype = &ktype_dlpar_io,
|
.ktype = &ktype_dlpar_io,
|
||||||
};
|
};
|
||||||
|
|
||||||
int dlpar_sysfs_init(void)
|
int dlpar_sysfs_init(void)
|
||||||
{
|
{
|
||||||
|
kobject_set_name(&dlpar_io_kset.kobj, DLPAR_KOBJ_NAME);
|
||||||
if (kset_register(&dlpar_io_kset)) {
|
if (kset_register(&dlpar_io_kset)) {
|
||||||
printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n",
|
printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n",
|
||||||
dlpar_io_kset.kobj.name);
|
kobject_name(&dlpar_io_kset.kobj));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -532,8 +532,7 @@ void pci_dev_put(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_HOTPLUG
|
#ifndef CONFIG_HOTPLUG
|
||||||
int pci_uevent(struct device *dev, char **envp, int num_envp,
|
int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* Functions internal to the PCI core code */
|
/* Functions internal to the PCI core code */
|
||||||
|
|
||||||
extern int pci_uevent(struct device *dev, char **envp, int num_envp,
|
extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||||
char *buffer, int buffer_size);
|
|
||||||
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
||||||
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||||
extern void pci_cleanup_rom(struct pci_dev *dev);
|
extern void pci_cleanup_rom(struct pci_dev *dev);
|
||||||
|
|
|
@ -48,7 +48,7 @@ pdev_fixup_irq(struct pci_dev *dev,
|
||||||
dev->irq = irq;
|
dev->irq = irq;
|
||||||
|
|
||||||
pr_debug("PCI: fixup irq: (%s) got %d\n",
|
pr_debug("PCI: fixup irq: (%s) got %d\n",
|
||||||
dev->dev.kobj.name, dev->irq);
|
kobject_name(&dev->dev.kobj), dev->irq);
|
||||||
|
|
||||||
/* Always tell the device, so the driver knows what is
|
/* Always tell the device, so the driver knows what is
|
||||||
the real IRQ to use; the device does not use it. */
|
the real IRQ to use; the device does not use it. */
|
||||||
|
|
|
@ -907,18 +907,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
|
||||||
EXPORT_SYMBOL(pcmcia_insert_card);
|
EXPORT_SYMBOL(pcmcia_insert_card);
|
||||||
|
|
||||||
|
|
||||||
static int pcmcia_socket_uevent(struct device *dev, char **envp,
|
static int pcmcia_socket_uevent(struct device *dev,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
|
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
|
||||||
int i = 0, length = 0;
|
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
if (add_uevent_var(env, "SOCKET_NO=%u", s->sock))
|
||||||
&length, "SOCKET_NO=%u", s->sock))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1064,11 +1064,10 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct pcmcia_device *p_dev;
|
struct pcmcia_device *p_dev;
|
||||||
int i, length = 0;
|
int i;
|
||||||
u32 hash[4] = { 0, 0, 0, 0};
|
u32 hash[4] = { 0, 0, 0, 0};
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
@ -1083,23 +1082,13 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
|
hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock))
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"SOCKET_NO=%u",
|
|
||||||
p_dev->socket->sock))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEVICE_NO=%02X",
|
|
||||||
p_dev->device_no))
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
|
|
||||||
"pa%08Xpb%08Xpc%08Xpd%08X",
|
"pa%08Xpb%08Xpc%08Xpd%08X",
|
||||||
p_dev->has_manf_id ? p_dev->manf_id : 0,
|
p_dev->has_manf_id ? p_dev->manf_id : 0,
|
||||||
p_dev->has_card_id ? p_dev->card_id : 0,
|
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,
|
||||||
hash[3]))
|
hash[3]))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,6 @@ static int __init mst_pcmcia_init(void)
|
||||||
if (!mst_pcmcia_device)
|
if (!mst_pcmcia_device)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mst_pcmcia_device->dev.uevent_suppress = 0;
|
|
||||||
mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
|
mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
|
||||||
|
|
||||||
ret = platform_device_add(mst_pcmcia_device);
|
ret = platform_device_add(mst_pcmcia_device);
|
||||||
|
@ -195,3 +194,4 @@ fs_initcall(mst_pcmcia_init);
|
||||||
module_exit(mst_pcmcia_exit);
|
module_exit(mst_pcmcia_exit);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:pxa2xx-pcmcia");
|
||||||
|
|
|
@ -261,7 +261,6 @@ static int __init sharpsl_pcmcia_init(void)
|
||||||
if (!sharpsl_pcmcia_device)
|
if (!sharpsl_pcmcia_device)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
sharpsl_pcmcia_device->dev.uevent_suppress = 0;
|
|
||||||
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
|
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
|
||||||
sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
|
sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
|
||||||
|
|
||||||
|
@ -284,3 +283,4 @@ module_exit(sharpsl_pcmcia_exit);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
|
MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:pxa2xx-pcmcia");
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
|
|
||||||
extern int power_supply_create_attrs(struct power_supply *psy);
|
extern int power_supply_create_attrs(struct power_supply *psy);
|
||||||
extern void power_supply_remove_attrs(struct power_supply *psy);
|
extern void power_supply_remove_attrs(struct power_supply *psy);
|
||||||
extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
|
extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||||
char *buffer, int buffer_size);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -195,11 +195,10 @@ static char *kstruprdup(const char *str, gfp_t gfp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int power_supply_uevent(struct device *dev, char **envp, int num_envp,
|
int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct power_supply *psy = dev_get_drvdata(dev);
|
struct power_supply *psy = dev_get_drvdata(dev);
|
||||||
int i = 0, length = 0, ret = 0, j;
|
int ret = 0, j;
|
||||||
char *prop_buf;
|
char *prop_buf;
|
||||||
char *attrname;
|
char *attrname;
|
||||||
|
|
||||||
|
@ -212,8 +211,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
|
dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
|
||||||
|
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
ret = add_uevent_var(env, "POWER_SUPPLY_NAME=%s", psy->name);
|
||||||
&length, "POWER_SUPPLY_NAME=%s", psy->name);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -243,9 +241,7 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
|
dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
|
||||||
|
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
|
||||||
&length, "POWER_SUPPLY_%s=%s",
|
|
||||||
attrname, prop_buf);
|
|
||||||
kfree(attrname);
|
kfree(attrname);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -282,14 +278,11 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
|
dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
|
||||||
|
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf);
|
||||||
&length, "POWER_SUPPLY_%s=%s",
|
|
||||||
attrname, prop_buf);
|
|
||||||
kfree(attrname);
|
kfree(attrname);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
envp[i] = NULL;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free_page((unsigned long)prop_buf);
|
free_page((unsigned long)prop_buf);
|
||||||
|
|
|
@ -44,8 +44,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
|
ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
|
||||||
int buffer_size)
|
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -79,49 +79,38 @@ static int snprint_alias(char *buf, size_t size,
|
||||||
|
|
||||||
/* Set up environment variables for ccw device uevent. Return 0 on success,
|
/* Set up environment variables for ccw device uevent. Return 0 on success,
|
||||||
* non-zero otherwise. */
|
* non-zero otherwise. */
|
||||||
static int ccw_uevent(struct device *dev, char **envp, int num_envp,
|
static int ccw_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct ccw_device *cdev = to_ccwdev(dev);
|
struct ccw_device *cdev = to_ccwdev(dev);
|
||||||
struct ccw_device_id *id = &(cdev->id);
|
struct ccw_device_id *id = &(cdev->id);
|
||||||
int i = 0;
|
|
||||||
int len = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
char modalias_buf[30];
|
char modalias_buf[30];
|
||||||
|
|
||||||
/* CU_TYPE= */
|
/* CU_TYPE= */
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
ret = add_uevent_var(env, "CU_TYPE=%04X", id->cu_type);
|
||||||
"CU_TYPE=%04X", id->cu_type);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* CU_MODEL= */
|
/* CU_MODEL= */
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
ret = add_uevent_var(env, "CU_MODEL=%02X", id->cu_model);
|
||||||
"CU_MODEL=%02X", id->cu_model);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* The next two can be zero, that's ok for us */
|
/* The next two can be zero, that's ok for us */
|
||||||
/* DEV_TYPE= */
|
/* DEV_TYPE= */
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
ret = add_uevent_var(env, "DEV_TYPE=%04X", id->dev_type);
|
||||||
"DEV_TYPE=%04X", id->dev_type);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* DEV_MODEL= */
|
/* DEV_MODEL= */
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
ret = add_uevent_var(env, "DEV_MODEL=%02X", id->dev_model);
|
||||||
"DEV_MODEL=%02X", id->dev_model);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* MODALIAS= */
|
/* MODALIAS= */
|
||||||
snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
|
snprint_alias(modalias_buf, sizeof(modalias_buf), id, "");
|
||||||
ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
ret = add_uevent_var(env, "MODALIAS=%s", modalias_buf);
|
||||||
"MODALIAS=%s", modalias_buf);
|
return ret;
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bus_type ccw_bus_type;
|
struct bus_type ccw_bus_type;
|
||||||
|
|
|
@ -458,28 +458,22 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
* uevent function for AP devices. It sets up a single environment
|
* uevent function for AP devices. It sets up a single environment
|
||||||
* variable DEV_TYPE which contains the hardware device type.
|
* variable DEV_TYPE which contains the hardware device type.
|
||||||
*/
|
*/
|
||||||
static int ap_uevent (struct device *dev, char **envp, int num_envp,
|
static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct ap_device *ap_dev = to_ap_dev(dev);
|
struct ap_device *ap_dev = to_ap_dev(dev);
|
||||||
int retval = 0, length = 0, i = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (!ap_dev)
|
if (!ap_dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* Set up DEV_TYPE environment variable. */
|
/* Set up DEV_TYPE environment variable. */
|
||||||
retval = add_uevent_var(envp, num_envp, &i,
|
retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEV_TYPE=%04X", ap_dev->device_type);
|
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Add MODALIAS= */
|
/* Add MODALIAS= */
|
||||||
retval = add_uevent_var(envp, num_envp, &i,
|
retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=ap:t%02X", ap_dev->device_type);
|
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,16 +277,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
|
||||||
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
|
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp,
|
static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct scsi_device *sdev = to_scsi_device(dev);
|
struct scsi_device *sdev = to_scsi_device(dev);
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
|
||||||
"MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
|
||||||
return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
|
return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spi_uevent(struct device *dev, char **envp, int num_envp,
|
static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
const struct spi_device *spi = to_spi_device(dev);
|
const struct spi_device *spi = to_spi_device(dev);
|
||||||
|
|
||||||
envp[0] = buffer;
|
add_uevent_var(env, "MODALIAS=%s", spi->modalias);
|
||||||
snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
|
|
||||||
envp[1] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1591,6 +1591,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct file_operations usbdev_file_operations = {
|
const struct file_operations usbdev_file_operations = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.llseek = usbdev_lseek,
|
.llseek = usbdev_lseek,
|
||||||
.read = usbdev_read,
|
.read = usbdev_read,
|
||||||
.poll = usbdev_poll,
|
.poll = usbdev_poll,
|
||||||
|
@ -1640,10 +1641,7 @@ static struct notifier_block usbdev_nb = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct cdev usb_device_cdev = {
|
static struct cdev usb_device_cdev;
|
||||||
.kobj = {.name = "usb_device", },
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
int __init usb_devio_init(void)
|
int __init usb_devio_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -581,12 +581,9 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct usb_device *usb_dev;
|
struct usb_device *usb_dev;
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -615,51 +612,39 @@ static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
* all the device descriptors we don't tell them about. Or
|
* all the device descriptors we don't tell them about. Or
|
||||||
* act as usermode drivers.
|
* act as usermode drivers.
|
||||||
*/
|
*/
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEVICE=/proc/bus/usb/%03d/%03d",
|
|
||||||
usb_dev->bus->busnum, usb_dev->devnum))
|
usb_dev->bus->busnum, usb_dev->devnum))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* per-device configurations are common */
|
/* per-device configurations are common */
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PRODUCT=%x/%x/%x",
|
|
||||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* class-based driver binding models */
|
/* class-based driver binding models */
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "TYPE=%d/%d/%d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"TYPE=%d/%d/%d",
|
|
||||||
usb_dev->descriptor.bDeviceClass,
|
usb_dev->descriptor.bDeviceClass,
|
||||||
usb_dev->descriptor.bDeviceSubClass,
|
usb_dev->descriptor.bDeviceSubClass,
|
||||||
usb_dev->descriptor.bDeviceProtocol))
|
usb_dev->descriptor.bDeviceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "BUSNUM=%03d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"BUSNUM=%03d",
|
|
||||||
usb_dev->bus->busnum))
|
usb_dev->bus->busnum))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "DEVNUM=%03d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEVNUM=%03d",
|
|
||||||
usb_dev->devnum))
|
usb_dev->devnum))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int usb_uevent(struct device *dev, char **envp,
|
static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1344,14 +1344,11 @@ static void usb_release_interface(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
|
static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct usb_device *usb_dev;
|
struct usb_device *usb_dev;
|
||||||
struct usb_interface *intf;
|
struct usb_interface *intf;
|
||||||
struct usb_host_interface *alt;
|
struct usb_host_interface *alt;
|
||||||
int i = 0;
|
|
||||||
int length = 0;
|
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1364,39 +1361,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
alt = intf->cur_altsetting;
|
alt = intf->cur_altsetting;
|
||||||
|
|
||||||
#ifdef CONFIG_USB_DEVICEFS
|
#ifdef CONFIG_USB_DEVICEFS
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"DEVICE=/proc/bus/usb/%03d/%03d",
|
|
||||||
usb_dev->bus->busnum, usb_dev->devnum))
|
usb_dev->bus->busnum, usb_dev->devnum))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"PRODUCT=%x/%x/%x",
|
|
||||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "TYPE=%d/%d/%d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"TYPE=%d/%d/%d",
|
|
||||||
usb_dev->descriptor.bDeviceClass,
|
usb_dev->descriptor.bDeviceClass,
|
||||||
usb_dev->descriptor.bDeviceSubClass,
|
usb_dev->descriptor.bDeviceSubClass,
|
||||||
usb_dev->descriptor.bDeviceProtocol))
|
usb_dev->descriptor.bDeviceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"INTERFACE=%d/%d/%d",
|
|
||||||
alt->desc.bInterfaceClass,
|
alt->desc.bInterfaceClass,
|
||||||
alt->desc.bInterfaceSubClass,
|
alt->desc.bInterfaceSubClass,
|
||||||
alt->desc.bInterfaceProtocol))
|
alt->desc.bInterfaceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_uevent_var(envp, num_envp, &i,
|
if (add_uevent_var(env,
|
||||||
buffer, buffer_size, &length,
|
|
||||||
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
||||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
|
@ -1409,14 +1397,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
alt->desc.bInterfaceProtocol))
|
alt->desc.bInterfaceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int usb_if_uevent(struct device *dev, char **envp,
|
static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
int num_envp, char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>");
|
MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>");
|
||||||
|
|
||||||
static ssize_t video_output_show_state(struct class_device *dev,char *buf)
|
static ssize_t video_output_show_state(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
ssize_t ret_size = 0;
|
ssize_t ret_size = 0;
|
||||||
struct output_device *od = to_output_device(dev);
|
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)
|
||||||
return ret_size;
|
return ret_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t video_output_store_state(struct class_device *dev,
|
static ssize_t video_output_store_state(struct device *dev,
|
||||||
const char *buf,size_t count)
|
struct device_attribute *attr,
|
||||||
|
const char *buf,size_t count)
|
||||||
{
|
{
|
||||||
char *endp;
|
char *endp;
|
||||||
struct output_device *od = to_output_device(dev);
|
struct output_device *od = to_output_device(dev);
|
||||||
|
@ -60,21 +62,22 @@ static ssize_t video_output_store_state(struct class_device *dev,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_output_class_release(struct class_device *dev)
|
static void video_output_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct output_device *od = to_output_device(dev);
|
struct output_device *od = to_output_device(dev);
|
||||||
kfree(od);
|
kfree(od);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct class_device_attribute video_output_attributes[] = {
|
static struct device_attribute video_output_attributes[] = {
|
||||||
__ATTR(state, 0644, video_output_show_state, video_output_store_state),
|
__ATTR(state, 0644, video_output_show_state, video_output_store_state),
|
||||||
__ATTR_NULL,
|
__ATTR_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct class video_output_class = {
|
static struct class video_output_class = {
|
||||||
.name = "video_output",
|
.name = "video_output",
|
||||||
.release = video_output_class_release,
|
.dev_release = video_output_release,
|
||||||
.class_dev_attrs = video_output_attributes,
|
.dev_attrs = video_output_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct output_device *video_output_register(const char *name,
|
struct output_device *video_output_register(const char *name,
|
||||||
|
@ -91,11 +94,11 @@ struct output_device *video_output_register(const char *name,
|
||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
new_dev->props = op;
|
new_dev->props = op;
|
||||||
new_dev->class_dev.class = &video_output_class;
|
new_dev->dev.class = &video_output_class;
|
||||||
new_dev->class_dev.dev = dev;
|
new_dev->dev.parent = dev;
|
||||||
strlcpy(new_dev->class_dev.class_id,name,KOBJ_NAME_LEN);
|
strlcpy(new_dev->dev.bus_id,name, BUS_ID_SIZE);
|
||||||
class_set_devdata(&new_dev->class_dev,devdata);
|
dev_set_drvdata(&new_dev->dev, devdata);
|
||||||
ret_code = class_device_register(&new_dev->class_dev);
|
ret_code = device_register(&new_dev->dev);
|
||||||
if (ret_code) {
|
if (ret_code) {
|
||||||
kfree(new_dev);
|
kfree(new_dev);
|
||||||
goto error_return;
|
goto error_return;
|
||||||
|
@ -111,7 +114,7 @@ void video_output_unregister(struct output_device *dev)
|
||||||
{
|
{
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return;
|
||||||
class_device_unregister(&dev->class_dev);
|
device_unregister(&dev->dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(video_output_unregister);
|
EXPORT_SYMBOL(video_output_unregister);
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ static struct w1_family w1_default_family = {
|
||||||
.fops = &w1_default_fops,
|
.fops = &w1_default_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
|
static int w1_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||||
|
|
||||||
static struct bus_type w1_bus_type = {
|
static struct bus_type w1_bus_type = {
|
||||||
.name = "w1",
|
.name = "w1",
|
||||||
|
@ -396,13 +396,12 @@ static void w1_destroy_master_attributes(struct w1_master *master)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int w1_uevent(struct device *dev, char **envp, int num_envp,
|
static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
struct w1_master *md = NULL;
|
struct w1_master *md = NULL;
|
||||||
struct w1_slave *sl = NULL;
|
struct w1_slave *sl = NULL;
|
||||||
char *event_owner, *name;
|
char *event_owner, *name;
|
||||||
int err, cur_index=0, cur_len=0;
|
int err;
|
||||||
|
|
||||||
if (dev->driver == &w1_master_driver) {
|
if (dev->driver == &w1_master_driver) {
|
||||||
md = container_of(dev, struct w1_master, dev);
|
md = container_of(dev, struct w1_master, dev);
|
||||||
|
@ -423,23 +422,19 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
if (dev->driver != &w1_slave_driver || !sl)
|
if (dev->driver != &w1_slave_driver || !sl)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size,
|
err = add_uevent_var(env, "W1_FID=%02X", sl->reg_num.family);
|
||||||
&cur_len, "W1_FID=%02X", sl->reg_num.family);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size,
|
err = add_uevent_var(env, "W1_SLAVE_ID=%024LX",
|
||||||
&cur_len, "W1_SLAVE_ID=%024LX",
|
(unsigned long long)sl->reg_num.id);
|
||||||
(unsigned long long)sl->reg_num.id);
|
|
||||||
envp[cur_index] = NULL;
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
static int w1_uevent(struct device *dev, char **envp, int num_envp,
|
static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
char *buffer, int buffer_size)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,6 +221,42 @@ struct dentry *debugfs_create_u64(const char *name, mode_t mode,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_create_u64);
|
EXPORT_SYMBOL_GPL(debugfs_create_u64);
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n");
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n");
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* debugfs_create_x8 - create a debugfs file that is used to read and write an unsigned 8-bit value
|
||||||
|
* debugfs_create_x16 - create a debugfs file that is used to read and write an unsigned 16-bit value
|
||||||
|
* debugfs_create_x32 - create a debugfs file that is used to read and write an unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* These functions are exactly the same as the above functions, (but use a hex
|
||||||
|
* output for the decimal challenged) for details look at the above unsigned
|
||||||
|
* decimal functions.
|
||||||
|
*/
|
||||||
|
struct dentry *debugfs_create_x8(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u8 *value)
|
||||||
|
{
|
||||||
|
return debugfs_create_file(name, mode, parent, value, &fops_x8);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_create_x8);
|
||||||
|
|
||||||
|
struct dentry *debugfs_create_x16(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u16 *value)
|
||||||
|
{
|
||||||
|
return debugfs_create_file(name, mode, parent, value, &fops_x16);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_create_x16);
|
||||||
|
|
||||||
|
struct dentry *debugfs_create_x32(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u32 *value)
|
||||||
|
{
|
||||||
|
return debugfs_create_file(name, mode, parent, value, &fops_x32);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_create_x32);
|
||||||
|
|
||||||
static ssize_t read_file_bool(struct file *file, char __user *user_buf,
|
static ssize_t read_file_bool(struct file *file, char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
|
|
@ -167,7 +167,6 @@ static struct kobj_type dlm_ktype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kset dlm_kset = {
|
static struct kset dlm_kset = {
|
||||||
.kobj = {.name = "dlm",},
|
|
||||||
.ktype = &dlm_ktype,
|
.ktype = &dlm_ktype,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -228,6 +227,7 @@ int dlm_lockspace_init(void)
|
||||||
INIT_LIST_HEAD(&lslist);
|
INIT_LIST_HEAD(&lslist);
|
||||||
spin_lock_init(&lslist_lock);
|
spin_lock_init(&lslist_lock);
|
||||||
|
|
||||||
|
kobject_set_name(&dlm_kset.kobj, "dlm");
|
||||||
kobj_set_kset_s(&dlm_kset, kernel_subsys);
|
kobj_set_kset_s(&dlm_kset, kernel_subsys);
|
||||||
error = kset_register(&dlm_kset);
|
error = kset_register(&dlm_kset);
|
||||||
if (error)
|
if (error)
|
||||||
|
|
|
@ -190,7 +190,6 @@ static struct kobj_type gdlm_ktype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kset gdlm_kset = {
|
static struct kset gdlm_kset = {
|
||||||
.kobj = {.name = "lock_dlm",},
|
|
||||||
.ktype = &gdlm_ktype,
|
.ktype = &gdlm_ktype,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -224,6 +223,7 @@ int gdlm_sysfs_init(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
kobject_set_name(&gdlm_kset.kobj, "lock_dlm");
|
||||||
kobj_set_kset_s(&gdlm_kset, kernel_subsys);
|
kobj_set_kset_s(&gdlm_kset, kernel_subsys);
|
||||||
error = kset_register(&gdlm_kset);
|
error = kset_register(&gdlm_kset);
|
||||||
if (error)
|
if (error)
|
||||||
|
|
|
@ -222,7 +222,6 @@ static struct kobj_type gfs2_ktype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kset gfs2_kset = {
|
static struct kset gfs2_kset = {
|
||||||
.kobj = {.name = "gfs2"},
|
|
||||||
.ktype = &gfs2_ktype,
|
.ktype = &gfs2_ktype,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -551,6 +550,7 @@ int gfs2_sys_init(void)
|
||||||
{
|
{
|
||||||
gfs2_sys_margs = NULL;
|
gfs2_sys_margs = NULL;
|
||||||
spin_lock_init(&gfs2_sys_margs_lock);
|
spin_lock_init(&gfs2_sys_margs_lock);
|
||||||
|
kobject_set_name(&gfs2_kset.kobj, "gfs2");
|
||||||
kobj_set_kset_s(&gfs2_kset, fs_subsys);
|
kobj_set_kset_s(&gfs2_kset, fs_subsys);
|
||||||
return kset_register(&gfs2_kset);
|
return kset_register(&gfs2_kset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ static struct kobj_type mlog_ktype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kset mlog_kset = {
|
static struct kset mlog_kset = {
|
||||||
.kobj = {.name = "logmask", .ktype = &mlog_ktype},
|
.kobj = {.ktype = &mlog_ktype},
|
||||||
};
|
};
|
||||||
|
|
||||||
int mlog_sys_init(struct kset *o2cb_subsys)
|
int mlog_sys_init(struct kset *o2cb_subsys)
|
||||||
|
@ -156,6 +156,7 @@ int mlog_sys_init(struct kset *o2cb_subsys)
|
||||||
}
|
}
|
||||||
mlog_attr_ptrs[i] = NULL;
|
mlog_attr_ptrs[i] = NULL;
|
||||||
|
|
||||||
|
kobject_set_name(&mlog_kset.kobj, "logmask");
|
||||||
kobj_set_kset_s(&mlog_kset, *o2cb_subsys);
|
kobj_set_kset_s(&mlog_kset, *o2cb_subsys);
|
||||||
return kset_register(&mlog_kset);
|
return kset_register(&mlog_kset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,10 +381,12 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
|
||||||
p->partno = part;
|
p->partno = part;
|
||||||
p->policy = disk->policy;
|
p->policy = disk->policy;
|
||||||
|
|
||||||
if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1]))
|
if (isdigit(disk->kobj.k_name[strlen(disk->kobj.k_name)-1]))
|
||||||
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part);
|
kobject_set_name(&p->kobj, "%sp%d",
|
||||||
|
kobject_name(&disk->kobj), part);
|
||||||
else
|
else
|
||||||
snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
|
kobject_set_name(&p->kobj, "%s%d",
|
||||||
|
kobject_name(&disk->kobj),part);
|
||||||
p->kobj.parent = &disk->kobj;
|
p->kobj.parent = &disk->kobj;
|
||||||
p->kobj.ktype = &ktype_part;
|
p->kobj.ktype = &ktype_part;
|
||||||
kobject_init(&p->kobj);
|
kobject_init(&p->kobj);
|
||||||
|
@ -477,9 +479,9 @@ void register_disk(struct gendisk *disk)
|
||||||
struct hd_struct *p;
|
struct hd_struct *p;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
|
kobject_set_name(&disk->kobj, "%s", disk->disk_name);
|
||||||
/* ewww... some of these buggers have / in name... */
|
/* ewww... some of these buggers have / in name... */
|
||||||
s = strchr(disk->kobj.name, '/');
|
s = strchr(disk->kobj.k_name, '/');
|
||||||
if (s)
|
if (s)
|
||||||
*s = '!';
|
*s = '!';
|
||||||
if ((err = kobject_add(&disk->kobj)))
|
if ((err = kobject_add(&disk->kobj)))
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
/*
|
/*
|
||||||
* bin.c - binary file operations for sysfs.
|
* fs/sysfs/bin.c - sysfs binary file implementation
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003 Patrick Mochel
|
* Copyright (c) 2003 Patrick Mochel
|
||||||
* Copyright (c) 2003 Matthew Wilcox
|
* Copyright (c) 2003 Matthew Wilcox
|
||||||
* Copyright (c) 2004 Silicon Graphics, Inc.
|
* Copyright (c) 2004 Silicon Graphics, Inc.
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*
|
||||||
|
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
@ -14,9 +20,9 @@
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/semaphore.h>
|
|
||||||
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
|
@ -30,8 +36,8 @@ static int
|
||||||
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
|
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||||
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
|
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* need attr_sd for attr, its parent for kobj */
|
/* need attr_sd for attr, its parent for kobj */
|
||||||
|
@ -87,8 +93,8 @@ static int
|
||||||
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
|
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||||
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
|
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* need attr_sd for attr, its parent for kobj */
|
/* need attr_sd for attr, its parent for kobj */
|
||||||
|
@ -140,8 +146,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct bin_buffer *bb = file->private_data;
|
struct bin_buffer *bb = file->private_data;
|
||||||
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
||||||
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
|
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
mutex_lock(&bb->mutex);
|
mutex_lock(&bb->mutex);
|
||||||
|
@ -167,12 +173,12 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
static int open(struct inode * inode, struct file * file)
|
static int open(struct inode * inode, struct file * file)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
||||||
struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
|
struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
|
||||||
struct bin_buffer *bb = NULL;
|
struct bin_buffer *bb = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* need attr_sd for attr */
|
/* binary file operations requires both @sd and its parent */
|
||||||
if (!sysfs_get_active(attr_sd))
|
if (!sysfs_get_active_two(attr_sd))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
error = -EACCES;
|
error = -EACCES;
|
||||||
|
@ -193,13 +199,12 @@ static int open(struct inode * inode, struct file * file)
|
||||||
mutex_init(&bb->mutex);
|
mutex_init(&bb->mutex);
|
||||||
file->private_data = bb;
|
file->private_data = bb;
|
||||||
|
|
||||||
/* open succeeded, put active reference and pin attr_sd */
|
/* open succeeded, put active references */
|
||||||
sysfs_put_active(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
sysfs_get(attr_sd);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
sysfs_put_active(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
kfree(bb);
|
kfree(bb);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +216,6 @@ static int release(struct inode * inode, struct file * file)
|
||||||
|
|
||||||
if (bb->mmapped)
|
if (bb->mmapped)
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
sysfs_put(attr_sd);
|
|
||||||
kfree(bb->buffer);
|
kfree(bb->buffer);
|
||||||
kfree(bb);
|
kfree(bb);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
756
fs/sysfs/dir.c
756
fs/sysfs/dir.c
File diff suppressed because it is too large
Load Diff
248
fs/sysfs/file.c
248
fs/sysfs/file.c
|
@ -1,15 +1,22 @@
|
||||||
/*
|
/*
|
||||||
* file.c - operations for regular (text) files.
|
* fs/sysfs/file.c - sysfs regular (text) file implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-3 Patrick Mochel
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*
|
||||||
|
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/fsnotify.h>
|
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/semaphore.h>
|
|
||||||
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
|
@ -50,14 +57,33 @@ static struct sysfs_ops subsys_sysfs_ops = {
|
||||||
.store = subsys_attr_store,
|
.store = subsys_attr_store,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There's one sysfs_buffer for each open file and one
|
||||||
|
* sysfs_open_dirent for each sysfs_dirent with one or more open
|
||||||
|
* files.
|
||||||
|
*
|
||||||
|
* filp->private_data points to sysfs_buffer and
|
||||||
|
* sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open
|
||||||
|
* is protected by sysfs_open_dirent_lock.
|
||||||
|
*/
|
||||||
|
static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
|
||||||
|
struct sysfs_open_dirent {
|
||||||
|
atomic_t refcnt;
|
||||||
|
atomic_t event;
|
||||||
|
wait_queue_head_t poll;
|
||||||
|
struct list_head buffers; /* goes through sysfs_buffer.list */
|
||||||
|
};
|
||||||
|
|
||||||
struct sysfs_buffer {
|
struct sysfs_buffer {
|
||||||
size_t count;
|
size_t count;
|
||||||
loff_t pos;
|
loff_t pos;
|
||||||
char * page;
|
char * page;
|
||||||
struct sysfs_ops * ops;
|
struct sysfs_ops * ops;
|
||||||
struct semaphore sem;
|
struct mutex mutex;
|
||||||
int needs_read_fill;
|
int needs_read_fill;
|
||||||
int event;
|
int event;
|
||||||
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +100,7 @@ struct sysfs_buffer {
|
||||||
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
|
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
struct sysfs_ops * ops = buffer->ops;
|
struct sysfs_ops * ops = buffer->ops;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
@ -88,8 +114,8 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
|
||||||
if (!sysfs_get_active_two(attr_sd))
|
if (!sysfs_get_active_two(attr_sd))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
buffer->event = atomic_read(&attr_sd->s_event);
|
buffer->event = atomic_read(&attr_sd->s_attr.open->event);
|
||||||
count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
|
count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
|
||||||
|
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
|
|
||||||
|
@ -128,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||||
struct sysfs_buffer * buffer = file->private_data;
|
struct sysfs_buffer * buffer = file->private_data;
|
||||||
ssize_t retval = 0;
|
ssize_t retval = 0;
|
||||||
|
|
||||||
down(&buffer->sem);
|
mutex_lock(&buffer->mutex);
|
||||||
if (buffer->needs_read_fill) {
|
if (buffer->needs_read_fill) {
|
||||||
retval = fill_read_buffer(file->f_path.dentry,buffer);
|
retval = fill_read_buffer(file->f_path.dentry,buffer);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -139,7 +165,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||||
retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
|
retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
|
||||||
buffer->count);
|
buffer->count);
|
||||||
out:
|
out:
|
||||||
up(&buffer->sem);
|
mutex_unlock(&buffer->mutex);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +215,7 @@ static int
|
||||||
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
|
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
struct sysfs_ops * ops = buffer->ops;
|
struct sysfs_ops * ops = buffer->ops;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -197,7 +223,7 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
|
||||||
if (!sysfs_get_active_two(attr_sd))
|
if (!sysfs_get_active_two(attr_sd))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
|
rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
|
||||||
|
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
|
|
||||||
|
@ -228,20 +254,102 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
|
||||||
struct sysfs_buffer * buffer = file->private_data;
|
struct sysfs_buffer * buffer = file->private_data;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
down(&buffer->sem);
|
mutex_lock(&buffer->mutex);
|
||||||
len = fill_write_buffer(buffer, buf, count);
|
len = fill_write_buffer(buffer, buf, count);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
len = flush_write_buffer(file->f_path.dentry, buffer, len);
|
len = flush_write_buffer(file->f_path.dentry, buffer, len);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
*ppos += len;
|
*ppos += len;
|
||||||
up(&buffer->sem);
|
mutex_unlock(&buffer->mutex);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_get_open_dirent - get or create sysfs_open_dirent
|
||||||
|
* @sd: target sysfs_dirent
|
||||||
|
* @buffer: sysfs_buffer for this instance of open
|
||||||
|
*
|
||||||
|
* If @sd->s_attr.open exists, increment its reference count;
|
||||||
|
* otherwise, create one. @buffer is chained to the buffers
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Kernel thread context (may sleep).
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0 on success, -errno on failure.
|
||||||
|
*/
|
||||||
|
static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
|
||||||
|
struct sysfs_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct sysfs_open_dirent *od, *new_od = NULL;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
spin_lock(&sysfs_open_dirent_lock);
|
||||||
|
|
||||||
|
if (!sd->s_attr.open && new_od) {
|
||||||
|
sd->s_attr.open = new_od;
|
||||||
|
new_od = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
od = sd->s_attr.open;
|
||||||
|
if (od) {
|
||||||
|
atomic_inc(&od->refcnt);
|
||||||
|
list_add_tail(&buffer->list, &od->buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&sysfs_open_dirent_lock);
|
||||||
|
|
||||||
|
if (od) {
|
||||||
|
kfree(new_od);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not there, initialize a new one and retry */
|
||||||
|
new_od = kmalloc(sizeof(*new_od), GFP_KERNEL);
|
||||||
|
if (!new_od)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
atomic_set(&new_od->refcnt, 0);
|
||||||
|
atomic_set(&new_od->event, 1);
|
||||||
|
init_waitqueue_head(&new_od->poll);
|
||||||
|
INIT_LIST_HEAD(&new_od->buffers);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_put_open_dirent - put sysfs_open_dirent
|
||||||
|
* @sd: target sysfs_dirent
|
||||||
|
* @buffer: associated sysfs_buffer
|
||||||
|
*
|
||||||
|
* Put @sd->s_attr.open and unlink @buffer from the buffers list.
|
||||||
|
* If reference count reaches zero, disassociate and free it.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* None.
|
||||||
|
*/
|
||||||
|
static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
|
||||||
|
struct sysfs_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct sysfs_open_dirent *od = sd->s_attr.open;
|
||||||
|
|
||||||
|
spin_lock(&sysfs_open_dirent_lock);
|
||||||
|
|
||||||
|
list_del(&buffer->list);
|
||||||
|
if (atomic_dec_and_test(&od->refcnt))
|
||||||
|
sd->s_attr.open = NULL;
|
||||||
|
else
|
||||||
|
od = NULL;
|
||||||
|
|
||||||
|
spin_unlock(&sysfs_open_dirent_lock);
|
||||||
|
|
||||||
|
kfree(od);
|
||||||
|
}
|
||||||
|
|
||||||
static int sysfs_open_file(struct inode *inode, struct file *file)
|
static int sysfs_open_file(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
|
||||||
struct sysfs_buffer * buffer;
|
struct sysfs_buffer * buffer;
|
||||||
struct sysfs_ops * ops = NULL;
|
struct sysfs_ops * ops = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
@ -294,33 +402,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
init_MUTEX(&buffer->sem);
|
mutex_init(&buffer->mutex);
|
||||||
buffer->needs_read_fill = 1;
|
buffer->needs_read_fill = 1;
|
||||||
buffer->ops = ops;
|
buffer->ops = ops;
|
||||||
file->private_data = buffer;
|
file->private_data = buffer;
|
||||||
|
|
||||||
/* open succeeded, put active references and pin attr_sd */
|
/* make sure we have open dirent struct */
|
||||||
|
error = sysfs_get_open_dirent(attr_sd, buffer);
|
||||||
|
if (error)
|
||||||
|
goto err_free;
|
||||||
|
|
||||||
|
/* open succeeded, put active references */
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
sysfs_get(attr_sd);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
kfree(buffer);
|
||||||
err_out:
|
err_out:
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sysfs_release(struct inode * inode, struct file * filp)
|
static int sysfs_release(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
|
struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata;
|
||||||
struct sysfs_buffer *buffer = filp->private_data;
|
struct sysfs_buffer *buffer = filp->private_data;
|
||||||
|
|
||||||
sysfs_put(attr_sd);
|
sysfs_put_open_dirent(sd, buffer);
|
||||||
|
|
||||||
|
if (buffer->page)
|
||||||
|
free_page((unsigned long)buffer->page);
|
||||||
|
kfree(buffer);
|
||||||
|
|
||||||
if (buffer) {
|
|
||||||
if (buffer->page)
|
|
||||||
free_page((unsigned long)buffer->page);
|
|
||||||
kfree(buffer);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,24 +448,24 @@ static int sysfs_release(struct inode * inode, struct file * filp)
|
||||||
* again will not get new data, or reset the state of 'poll'.
|
* again will not get new data, or reset the state of 'poll'.
|
||||||
* Reminder: this only works for attributes which actively support
|
* Reminder: this only works for attributes which actively support
|
||||||
* it, and it is not possible to test an attribute from userspace
|
* it, and it is not possible to test an attribute from userspace
|
||||||
* to see if it supports poll (Nether 'poll' or 'select' return
|
* to see if it supports poll (Neither 'poll' nor 'select' return
|
||||||
* an appropriate error code). When in doubt, set a suitable timeout value.
|
* an appropriate error code). When in doubt, set a suitable timeout value.
|
||||||
*/
|
*/
|
||||||
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
||||||
{
|
{
|
||||||
struct sysfs_buffer * buffer = filp->private_data;
|
struct sysfs_buffer * buffer = filp->private_data;
|
||||||
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
|
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
|
||||||
struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
|
struct sysfs_open_dirent *od = attr_sd->s_attr.open;
|
||||||
|
|
||||||
/* need parent for the kobj, grab both */
|
/* need parent for the kobj, grab both */
|
||||||
if (!sysfs_get_active_two(attr_sd))
|
if (!sysfs_get_active_two(attr_sd))
|
||||||
goto trigger;
|
goto trigger;
|
||||||
|
|
||||||
poll_wait(filp, &kobj->poll, wait);
|
poll_wait(filp, &od->poll, wait);
|
||||||
|
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
|
|
||||||
if (buffer->event != atomic_read(&attr_sd->s_event))
|
if (buffer->event != atomic_read(&od->event))
|
||||||
goto trigger;
|
goto trigger;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -373,8 +486,17 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
|
||||||
if (sd && attr)
|
if (sd && attr)
|
||||||
sd = sysfs_find_dirent(sd, attr);
|
sd = sysfs_find_dirent(sd, attr);
|
||||||
if (sd) {
|
if (sd) {
|
||||||
atomic_inc(&sd->s_event);
|
struct sysfs_open_dirent *od;
|
||||||
wake_up_interruptible(&k->poll);
|
|
||||||
|
spin_lock(&sysfs_open_dirent_lock);
|
||||||
|
|
||||||
|
od = sd->s_attr.open;
|
||||||
|
if (od) {
|
||||||
|
atomic_inc(&od->event);
|
||||||
|
wake_up_interruptible(&od->poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&sysfs_open_dirent_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&sysfs_mutex);
|
mutex_unlock(&sysfs_mutex);
|
||||||
|
@ -397,25 +519,21 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
|
||||||
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
|
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
|
||||||
struct sysfs_addrm_cxt acxt;
|
struct sysfs_addrm_cxt acxt;
|
||||||
struct sysfs_dirent *sd;
|
struct sysfs_dirent *sd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
sd = sysfs_new_dirent(attr->name, mode, type);
|
sd = sysfs_new_dirent(attr->name, mode, type);
|
||||||
if (!sd)
|
if (!sd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
sd->s_elem.attr.attr = (void *)attr;
|
sd->s_attr.attr = (void *)attr;
|
||||||
|
|
||||||
sysfs_addrm_start(&acxt, dir_sd);
|
sysfs_addrm_start(&acxt, dir_sd);
|
||||||
|
rc = sysfs_add_one(&acxt, sd);
|
||||||
|
sysfs_addrm_finish(&acxt);
|
||||||
|
|
||||||
if (!sysfs_find_dirent(dir_sd, attr->name)) {
|
if (rc)
|
||||||
sysfs_add_one(&acxt, sd);
|
|
||||||
sysfs_link_sibling(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sysfs_addrm_finish(&acxt)) {
|
|
||||||
sysfs_put(sd);
|
sysfs_put(sd);
|
||||||
return -EEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,42 +575,6 @@ int sysfs_add_file_to_group(struct kobject *kobj,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
|
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sysfs_update_file - update the modified timestamp on an object attribute.
|
|
||||||
* @kobj: object we're acting for.
|
|
||||||
* @attr: attribute descriptor.
|
|
||||||
*/
|
|
||||||
int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
|
|
||||||
{
|
|
||||||
struct sysfs_dirent *victim_sd = NULL;
|
|
||||||
struct dentry *victim = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = -ENOENT;
|
|
||||||
victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
|
|
||||||
if (!victim_sd)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
victim = sysfs_get_dentry(victim_sd);
|
|
||||||
if (IS_ERR(victim)) {
|
|
||||||
rc = PTR_ERR(victim);
|
|
||||||
victim = NULL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&victim->d_inode->i_mutex);
|
|
||||||
victim->d_inode->i_mtime = CURRENT_TIME;
|
|
||||||
fsnotify_modify(victim);
|
|
||||||
mutex_unlock(&victim->d_inode->i_mutex);
|
|
||||||
rc = 0;
|
|
||||||
out:
|
|
||||||
dput(victim);
|
|
||||||
sysfs_put(victim_sd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_chmod_file - update the modified mode value on an object attribute.
|
* sysfs_chmod_file - update the modified mode value on an object attribute.
|
||||||
* @kobj: object we're acting for.
|
* @kobj: object we're acting for.
|
||||||
|
@ -513,7 +595,9 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
|
||||||
if (!victim_sd)
|
if (!victim_sd)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
mutex_lock(&sysfs_rename_mutex);
|
||||||
victim = sysfs_get_dentry(victim_sd);
|
victim = sysfs_get_dentry(victim_sd);
|
||||||
|
mutex_unlock(&sysfs_rename_mutex);
|
||||||
if (IS_ERR(victim)) {
|
if (IS_ERR(victim)) {
|
||||||
rc = PTR_ERR(victim);
|
rc = PTR_ERR(victim);
|
||||||
victim = NULL;
|
victim = NULL;
|
||||||
|
@ -521,10 +605,19 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = victim->d_inode;
|
inode = victim->d_inode;
|
||||||
|
|
||||||
mutex_lock(&inode->i_mutex);
|
mutex_lock(&inode->i_mutex);
|
||||||
|
|
||||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||||
rc = notify_change(victim, &newattrs);
|
rc = notify_change(victim, &newattrs);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
mutex_lock(&sysfs_mutex);
|
||||||
|
victim_sd->s_mode = newattrs.ia_mode;
|
||||||
|
mutex_unlock(&sysfs_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
out:
|
out:
|
||||||
dput(victim);
|
dput(victim);
|
||||||
|
@ -632,4 +725,3 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(sysfs_create_file);
|
EXPORT_SYMBOL_GPL(sysfs_create_file);
|
||||||
EXPORT_SYMBOL_GPL(sysfs_remove_file);
|
EXPORT_SYMBOL_GPL(sysfs_remove_file);
|
||||||
EXPORT_SYMBOL_GPL(sysfs_update_file);
|
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
#include <linux/dcache.h>
|
#include <linux/dcache.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <asm/semaphore.h>
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
101
fs/sysfs/inode.c
101
fs/sysfs/inode.c
|
@ -1,7 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* inode.c - basic inode and dentry operations.
|
* fs/sysfs/inode.c - basic sysfs inode and dentry operations
|
||||||
*
|
*
|
||||||
* sysfs is Copyright (c) 2001-3 Patrick Mochel
|
* Copyright (c) 2001-3 Patrick Mochel
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
*
|
*
|
||||||
* Please see Documentation/filesystems/sysfs.txt for more information.
|
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +18,6 @@
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <asm/semaphore.h>
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
extern struct super_block * sysfs_sb;
|
extern struct super_block * sysfs_sb;
|
||||||
|
@ -34,16 +37,6 @@ static const struct inode_operations sysfs_inode_operations ={
|
||||||
.setattr = sysfs_setattr,
|
.setattr = sysfs_setattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
void sysfs_delete_inode(struct inode *inode)
|
|
||||||
{
|
|
||||||
/* Free the shadowed directory inode operations */
|
|
||||||
if (sysfs_is_shadowed_inode(inode)) {
|
|
||||||
kfree(inode->i_op);
|
|
||||||
inode->i_op = NULL;
|
|
||||||
}
|
|
||||||
return generic_delete_inode(inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
|
int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
|
||||||
{
|
{
|
||||||
struct inode * inode = dentry->d_inode;
|
struct inode * inode = dentry->d_inode;
|
||||||
|
@ -133,8 +126,22 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
|
||||||
*/
|
*/
|
||||||
static struct lock_class_key sysfs_inode_imutex_key;
|
static struct lock_class_key sysfs_inode_imutex_key;
|
||||||
|
|
||||||
|
static int sysfs_count_nlink(struct sysfs_dirent *sd)
|
||||||
|
{
|
||||||
|
struct sysfs_dirent *child;
|
||||||
|
int nr = 0;
|
||||||
|
|
||||||
|
for (child = sd->s_dir.children; child; child = child->s_sibling)
|
||||||
|
if (sysfs_type(child) == SYSFS_DIR)
|
||||||
|
nr++;
|
||||||
|
|
||||||
|
return nr + 2;
|
||||||
|
}
|
||||||
|
|
||||||
static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
|
static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
|
||||||
{
|
{
|
||||||
|
struct bin_attribute *bin_attr;
|
||||||
|
|
||||||
inode->i_blocks = 0;
|
inode->i_blocks = 0;
|
||||||
inode->i_mapping->a_ops = &sysfs_aops;
|
inode->i_mapping->a_ops = &sysfs_aops;
|
||||||
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
|
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)
|
||||||
set_inode_attr(inode, sd->s_iattr);
|
set_inode_attr(inode, sd->s_iattr);
|
||||||
} else
|
} else
|
||||||
set_default_inode_attr(inode, sd->s_mode);
|
set_default_inode_attr(inode, sd->s_mode);
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize inode according to type */
|
||||||
|
switch (sysfs_type(sd)) {
|
||||||
|
case SYSFS_DIR:
|
||||||
|
inode->i_op = &sysfs_dir_inode_operations;
|
||||||
|
inode->i_fop = &sysfs_dir_operations;
|
||||||
|
inode->i_nlink = sysfs_count_nlink(sd);
|
||||||
|
break;
|
||||||
|
case SYSFS_KOBJ_ATTR:
|
||||||
|
inode->i_size = PAGE_SIZE;
|
||||||
|
inode->i_fop = &sysfs_file_operations;
|
||||||
|
break;
|
||||||
|
case SYSFS_KOBJ_BIN_ATTR:
|
||||||
|
bin_attr = sd->s_bin_attr.bin_attr;
|
||||||
|
inode->i_size = bin_attr->size;
|
||||||
|
inode->i_fop = &bin_fops;
|
||||||
|
break;
|
||||||
|
case SYSFS_KOBJ_LINK:
|
||||||
|
inode->i_op = &sysfs_symlink_inode_operations;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_new_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,50 +210,24 @@ struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* sysfs_instantiate - instantiate dentry
|
|
||||||
* @dentry: dentry to be instantiated
|
|
||||||
* @inode: inode associated with @sd
|
|
||||||
*
|
|
||||||
* Unlock @inode if locked and instantiate @dentry with @inode.
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
* None.
|
|
||||||
*/
|
|
||||||
void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
|
|
||||||
{
|
|
||||||
BUG_ON(!dentry || dentry->d_inode);
|
|
||||||
|
|
||||||
if (inode->i_state & I_NEW)
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
|
|
||||||
d_instantiate(dentry, inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
|
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
|
||||||
{
|
{
|
||||||
struct sysfs_addrm_cxt acxt;
|
struct sysfs_addrm_cxt acxt;
|
||||||
struct sysfs_dirent **pos, *sd;
|
struct sysfs_dirent *sd;
|
||||||
|
|
||||||
if (!dir_sd)
|
if (!dir_sd)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
sysfs_addrm_start(&acxt, dir_sd);
|
sysfs_addrm_start(&acxt, dir_sd);
|
||||||
|
|
||||||
for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
|
sd = sysfs_find_dirent(dir_sd, name);
|
||||||
sd = *pos;
|
if (sd)
|
||||||
|
sysfs_remove_one(&acxt, sd);
|
||||||
|
|
||||||
if (!sysfs_type(sd))
|
sysfs_addrm_finish(&acxt);
|
||||||
continue;
|
|
||||||
if (!strcmp(sd->s_name, name)) {
|
|
||||||
*pos = sd->s_sibling;
|
|
||||||
sd->s_sibling = NULL;
|
|
||||||
sysfs_remove_one(&acxt, sd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sysfs_addrm_finish(&acxt))
|
if (sd)
|
||||||
return 0;
|
return 0;
|
||||||
return -ENOENT;
|
else
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* mount.c - operations for initializing and mounting sysfs.
|
* fs/sysfs/symlink.c - operations for initializing and mounting sysfs
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-3 Patrick Mochel
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*
|
||||||
|
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
@ -8,25 +16,25 @@
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <asm/semaphore.h>
|
|
||||||
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
/* Random magic number */
|
/* Random magic number */
|
||||||
#define SYSFS_MAGIC 0x62656572
|
#define SYSFS_MAGIC 0x62656572
|
||||||
|
|
||||||
struct vfsmount *sysfs_mount;
|
static struct vfsmount *sysfs_mount;
|
||||||
struct super_block * sysfs_sb = NULL;
|
struct super_block * sysfs_sb = NULL;
|
||||||
struct kmem_cache *sysfs_dir_cachep;
|
struct kmem_cache *sysfs_dir_cachep;
|
||||||
|
|
||||||
static const struct super_operations sysfs_ops = {
|
static const struct super_operations sysfs_ops = {
|
||||||
.statfs = simple_statfs,
|
.statfs = simple_statfs,
|
||||||
.drop_inode = sysfs_delete_inode,
|
.drop_inode = generic_delete_inode,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_dirent sysfs_root = {
|
struct sysfs_dirent sysfs_root = {
|
||||||
|
.s_name = "",
|
||||||
.s_count = ATOMIC_INIT(1),
|
.s_count = ATOMIC_INIT(1),
|
||||||
.s_flags = SYSFS_ROOT,
|
.s_flags = SYSFS_DIR,
|
||||||
.s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
|
.s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
|
||||||
.s_ino = 1,
|
.s_ino = 1,
|
||||||
};
|
};
|
||||||
|
@ -50,11 +58,6 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode->i_op = &sysfs_dir_inode_operations;
|
|
||||||
inode->i_fop = &sysfs_dir_operations;
|
|
||||||
inc_nlink(inode); /* directory, account for "." */
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
|
|
||||||
/* instantiate and link root dentry */
|
/* instantiate and link root dentry */
|
||||||
root = d_alloc_root(inode);
|
root = d_alloc_root(inode);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
|
@ -62,7 +65,6 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
sysfs_root.s_dentry = root;
|
|
||||||
root->d_fsdata = &sysfs_root;
|
root->d_fsdata = &sysfs_root;
|
||||||
sb->s_root = root;
|
sb->s_root = root;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -77,7 +79,7 @@ static int sysfs_get_sb(struct file_system_type *fs_type,
|
||||||
static struct file_system_type sysfs_fs_type = {
|
static struct file_system_type sysfs_fs_type = {
|
||||||
.name = "sysfs",
|
.name = "sysfs",
|
||||||
.get_sb = sysfs_get_sb,
|
.get_sb = sysfs_get_sb,
|
||||||
.kill_sb = kill_litter_super,
|
.kill_sb = kill_anon_super,
|
||||||
};
|
};
|
||||||
|
|
||||||
int __init sysfs_init(void)
|
int __init sysfs_init(void)
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* symlink.c - operations for sysfs symlinks.
|
* fs/sysfs/symlink.c - sysfs symlink implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-3 Patrick Mochel
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*
|
||||||
|
* Please see Documentation/filesystems/sysfs.txt for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -7,7 +15,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <asm/semaphore.h>
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
|
@ -60,10 +68,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
|
||||||
|
|
||||||
BUG_ON(!name);
|
BUG_ON(!name);
|
||||||
|
|
||||||
if (!kobj) {
|
if (!kobj)
|
||||||
if (sysfs_mount && sysfs_mount->mnt_sb)
|
parent_sd = &sysfs_root;
|
||||||
parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
|
else
|
||||||
} else
|
|
||||||
parent_sd = kobj->sd;
|
parent_sd = kobj->sd;
|
||||||
|
|
||||||
error = -EFAULT;
|
error = -EFAULT;
|
||||||
|
@ -87,20 +94,15 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
|
||||||
if (!sd)
|
if (!sd)
|
||||||
goto out_put;
|
goto out_put;
|
||||||
|
|
||||||
sd->s_elem.symlink.target_sd = target_sd;
|
sd->s_symlink.target_sd = target_sd;
|
||||||
target_sd = NULL; /* reference is now owned by the symlink */
|
target_sd = NULL; /* reference is now owned by the symlink */
|
||||||
|
|
||||||
sysfs_addrm_start(&acxt, parent_sd);
|
sysfs_addrm_start(&acxt, parent_sd);
|
||||||
|
error = sysfs_add_one(&acxt, sd);
|
||||||
|
sysfs_addrm_finish(&acxt);
|
||||||
|
|
||||||
if (!sysfs_find_dirent(parent_sd, name)) {
|
if (error)
|
||||||
sysfs_add_one(&acxt, sd);
|
|
||||||
sysfs_link_sibling(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sysfs_addrm_finish(&acxt)) {
|
|
||||||
error = -EEXIST;
|
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -148,7 +150,7 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
|
||||||
{
|
{
|
||||||
struct sysfs_dirent *sd = dentry->d_fsdata;
|
struct sysfs_dirent *sd = dentry->d_fsdata;
|
||||||
struct sysfs_dirent *parent_sd = sd->s_parent;
|
struct sysfs_dirent *parent_sd = sd->s_parent;
|
||||||
struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
|
struct sysfs_dirent *target_sd = sd->s_symlink.target_sd;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
mutex_lock(&sysfs_mutex);
|
mutex_lock(&sysfs_mutex);
|
||||||
|
|
182
fs/sysfs/sysfs.h
182
fs/sysfs/sysfs.h
|
@ -1,20 +1,39 @@
|
||||||
|
/*
|
||||||
|
* fs/sysfs/sysfs.h - sysfs internal header file
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-3 Patrick Mochel
|
||||||
|
* Copyright (c) 2007 SUSE Linux Products GmbH
|
||||||
|
* Copyright (c) 2007 Tejun Heo <teheo@suse.de>
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct sysfs_open_dirent;
|
||||||
|
|
||||||
|
/* type-specific structures for sysfs_dirent->s_* union members */
|
||||||
struct sysfs_elem_dir {
|
struct sysfs_elem_dir {
|
||||||
struct kobject * kobj;
|
struct kobject *kobj;
|
||||||
|
/* children list starts here and goes through sd->s_sibling */
|
||||||
|
struct sysfs_dirent *children;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_elem_symlink {
|
struct sysfs_elem_symlink {
|
||||||
struct sysfs_dirent * target_sd;
|
struct sysfs_dirent *target_sd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_elem_attr {
|
struct sysfs_elem_attr {
|
||||||
struct attribute * attr;
|
struct attribute *attr;
|
||||||
|
struct sysfs_open_dirent *open;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_elem_bin_attr {
|
struct sysfs_elem_bin_attr {
|
||||||
struct bin_attribute * bin_attr;
|
struct bin_attribute *bin_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* sysfs_dirent - the building block of sysfs hierarchy. Each and
|
||||||
|
* every sysfs node is represented by single sysfs_dirent.
|
||||||
|
*
|
||||||
* As long as s_count reference is held, the sysfs_dirent itself is
|
* As long as s_count reference is held, the sysfs_dirent itself is
|
||||||
* accessible. Dereferencing s_elem or any other outer entity
|
* accessible. Dereferencing s_elem or any other outer entity
|
||||||
* requires s_active reference.
|
* requires s_active reference.
|
||||||
|
@ -22,28 +41,43 @@ struct sysfs_elem_bin_attr {
|
||||||
struct sysfs_dirent {
|
struct sysfs_dirent {
|
||||||
atomic_t s_count;
|
atomic_t s_count;
|
||||||
atomic_t s_active;
|
atomic_t s_active;
|
||||||
struct sysfs_dirent * s_parent;
|
struct sysfs_dirent *s_parent;
|
||||||
struct sysfs_dirent * s_sibling;
|
struct sysfs_dirent *s_sibling;
|
||||||
struct sysfs_dirent * s_children;
|
const char *s_name;
|
||||||
const char * s_name;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct sysfs_elem_dir dir;
|
struct sysfs_elem_dir s_dir;
|
||||||
struct sysfs_elem_symlink symlink;
|
struct sysfs_elem_symlink s_symlink;
|
||||||
struct sysfs_elem_attr attr;
|
struct sysfs_elem_attr s_attr;
|
||||||
struct sysfs_elem_bin_attr bin_attr;
|
struct sysfs_elem_bin_attr s_bin_attr;
|
||||||
} s_elem;
|
};
|
||||||
|
|
||||||
unsigned int s_flags;
|
unsigned int s_flags;
|
||||||
umode_t s_mode;
|
|
||||||
ino_t s_ino;
|
ino_t s_ino;
|
||||||
struct dentry * s_dentry;
|
umode_t s_mode;
|
||||||
struct iattr * s_iattr;
|
struct iattr *s_iattr;
|
||||||
atomic_t s_event;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SD_DEACTIVATED_BIAS INT_MIN
|
#define SD_DEACTIVATED_BIAS INT_MIN
|
||||||
|
|
||||||
|
#define SYSFS_TYPE_MASK 0x00ff
|
||||||
|
#define SYSFS_DIR 0x0001
|
||||||
|
#define SYSFS_KOBJ_ATTR 0x0002
|
||||||
|
#define SYSFS_KOBJ_BIN_ATTR 0x0004
|
||||||
|
#define SYSFS_KOBJ_LINK 0x0008
|
||||||
|
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
|
||||||
|
|
||||||
|
#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
|
||||||
|
#define SYSFS_FLAG_REMOVED 0x0200
|
||||||
|
|
||||||
|
static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
|
||||||
|
{
|
||||||
|
return sd->s_flags & SYSFS_TYPE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context structure to be used while adding/removing nodes.
|
||||||
|
*/
|
||||||
struct sysfs_addrm_cxt {
|
struct sysfs_addrm_cxt {
|
||||||
struct sysfs_dirent *parent_sd;
|
struct sysfs_dirent *parent_sd;
|
||||||
struct inode *parent_inode;
|
struct inode *parent_inode;
|
||||||
|
@ -51,63 +85,47 @@ struct sysfs_addrm_cxt {
|
||||||
int cnt;
|
int cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct vfsmount * sysfs_mount;
|
/*
|
||||||
|
* mount.c
|
||||||
|
*/
|
||||||
extern struct sysfs_dirent sysfs_root;
|
extern struct sysfs_dirent sysfs_root;
|
||||||
|
extern struct super_block *sysfs_sb;
|
||||||
extern struct kmem_cache *sysfs_dir_cachep;
|
extern struct kmem_cache *sysfs_dir_cachep;
|
||||||
|
|
||||||
extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
|
/*
|
||||||
extern void sysfs_link_sibling(struct sysfs_dirent *sd);
|
* dir.c
|
||||||
extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
|
*/
|
||||||
extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
|
|
||||||
extern void sysfs_put_active(struct sysfs_dirent *sd);
|
|
||||||
extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
|
|
||||||
extern void sysfs_put_active_two(struct sysfs_dirent *sd);
|
|
||||||
extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
|
|
||||||
struct sysfs_dirent *parent_sd);
|
|
||||||
extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
|
|
||||||
struct sysfs_dirent *sd);
|
|
||||||
extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
|
|
||||||
struct sysfs_dirent *sd);
|
|
||||||
extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
|
|
||||||
|
|
||||||
extern void sysfs_delete_inode(struct inode *inode);
|
|
||||||
extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
|
|
||||||
extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
|
|
||||||
|
|
||||||
extern void release_sysfs_dirent(struct sysfs_dirent * sd);
|
|
||||||
extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
|
|
||||||
const unsigned char *name);
|
|
||||||
extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
|
|
||||||
const unsigned char *name);
|
|
||||||
extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
|
|
||||||
int type);
|
|
||||||
|
|
||||||
extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
|
|
||||||
const struct attribute *attr, int type);
|
|
||||||
extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
|
|
||||||
extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
|
|
||||||
|
|
||||||
extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
|
|
||||||
struct sysfs_dirent **p_sd);
|
|
||||||
extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
|
|
||||||
|
|
||||||
extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
|
|
||||||
|
|
||||||
extern spinlock_t sysfs_assoc_lock;
|
|
||||||
extern struct mutex sysfs_mutex;
|
extern struct mutex sysfs_mutex;
|
||||||
extern struct super_block * sysfs_sb;
|
extern struct mutex sysfs_rename_mutex;
|
||||||
|
extern spinlock_t sysfs_assoc_lock;
|
||||||
|
|
||||||
extern const struct file_operations sysfs_dir_operations;
|
extern const struct file_operations sysfs_dir_operations;
|
||||||
extern const struct file_operations sysfs_file_operations;
|
|
||||||
extern const struct file_operations bin_fops;
|
|
||||||
extern const struct inode_operations sysfs_dir_inode_operations;
|
extern const struct inode_operations sysfs_dir_inode_operations;
|
||||||
extern const struct inode_operations sysfs_symlink_inode_operations;
|
|
||||||
|
|
||||||
static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
|
struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
|
||||||
{
|
struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
|
||||||
return sd->s_flags & SYSFS_TYPE_MASK;
|
void sysfs_put_active(struct sysfs_dirent *sd);
|
||||||
}
|
struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
|
||||||
|
void sysfs_put_active_two(struct sysfs_dirent *sd);
|
||||||
|
void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
|
||||||
|
struct sysfs_dirent *parent_sd);
|
||||||
|
int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
|
||||||
|
void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
|
||||||
|
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
|
||||||
|
|
||||||
static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
|
struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
|
||||||
|
const unsigned char *name);
|
||||||
|
struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
|
||||||
|
const unsigned char *name);
|
||||||
|
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
|
||||||
|
|
||||||
|
void release_sysfs_dirent(struct sysfs_dirent *sd);
|
||||||
|
|
||||||
|
int sysfs_create_subdir(struct kobject *kobj, const char *name,
|
||||||
|
struct sysfs_dirent **p_sd);
|
||||||
|
void sysfs_remove_subdir(struct sysfs_dirent *sd);
|
||||||
|
|
||||||
|
static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
|
||||||
{
|
{
|
||||||
if (sd) {
|
if (sd) {
|
||||||
WARN_ON(!atomic_read(&sd->s_count));
|
WARN_ON(!atomic_read(&sd->s_count));
|
||||||
|
@ -116,13 +134,33 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sysfs_put(struct sysfs_dirent * sd)
|
static inline void sysfs_put(struct sysfs_dirent *sd)
|
||||||
{
|
{
|
||||||
if (sd && atomic_dec_and_test(&sd->s_count))
|
if (sd && atomic_dec_and_test(&sd->s_count))
|
||||||
release_sysfs_dirent(sd);
|
release_sysfs_dirent(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int sysfs_is_shadowed_inode(struct inode *inode)
|
/*
|
||||||
{
|
* inode.c
|
||||||
return S_ISDIR(inode->i_mode) && inode->i_op->follow_link;
|
*/
|
||||||
}
|
struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
|
||||||
|
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||||
|
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* file.c
|
||||||
|
*/
|
||||||
|
extern const struct file_operations sysfs_file_operations;
|
||||||
|
|
||||||
|
int sysfs_add_file(struct sysfs_dirent *dir_sd,
|
||||||
|
const struct attribute *attr, int type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bin.c
|
||||||
|
*/
|
||||||
|
extern const struct file_operations bin_fops;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* symlink.c
|
||||||
|
*/
|
||||||
|
extern const struct inode_operations sysfs_symlink_inode_operations;
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct of_device
|
||||||
extern ssize_t of_device_get_modalias(struct of_device *ofdev,
|
extern ssize_t of_device_get_modalias(struct of_device *ofdev,
|
||||||
char *str, ssize_t len);
|
char *str, ssize_t len);
|
||||||
extern int of_device_uevent(struct device *dev,
|
extern int of_device_uevent(struct device *dev,
|
||||||
char **envp, int num_envp, char *buffer, int buffer_size);
|
struct kobj_uevent_env *env);
|
||||||
|
|
||||||
/* This is just here during the transition */
|
/* This is just here during the transition */
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
|
|
@ -49,6 +49,12 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode,
|
||||||
struct dentry *parent, u32 *value);
|
struct dentry *parent, u32 *value);
|
||||||
struct dentry *debugfs_create_u64(const char *name, mode_t mode,
|
struct dentry *debugfs_create_u64(const char *name, mode_t mode,
|
||||||
struct dentry *parent, u64 *value);
|
struct dentry *parent, u64 *value);
|
||||||
|
struct dentry *debugfs_create_x8(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u8 *value);
|
||||||
|
struct dentry *debugfs_create_x16(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u16 *value);
|
||||||
|
struct dentry *debugfs_create_x32(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent, u32 *value);
|
||||||
struct dentry *debugfs_create_bool(const char *name, mode_t mode,
|
struct dentry *debugfs_create_bool(const char *name, mode_t mode,
|
||||||
struct dentry *parent, u32 *value);
|
struct dentry *parent, u32 *value);
|
||||||
|
|
||||||
|
@ -122,6 +128,27 @@ static inline struct dentry *debugfs_create_u64(const char *name, mode_t mode,
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct dentry *debugfs_create_x8(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent,
|
||||||
|
u8 *value)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct dentry *debugfs_create_x16(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent,
|
||||||
|
u16 *value)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct dentry *debugfs_create_x32(const char *name, mode_t mode,
|
||||||
|
struct dentry *parent,
|
||||||
|
u32 *value)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode,
|
static inline struct dentry *debugfs_create_bool(const char *name, mode_t mode,
|
||||||
struct dentry *parent,
|
struct dentry *parent,
|
||||||
u32 *value)
|
u32 *value)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue