mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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:
@@ -1,4 +1,4 @@
|
||||
NOTE:
|
||||
NOTE:
|
||||
This is a version of Documentation/HOWTO translated into Japanese.
|
||||
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
|
||||
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
|
||||
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/ >
|
||||
翻訳日: 2007/07/16
|
||||
翻訳日: 2007/09/19
|
||||
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
||||
校正者: 松倉さん <nbh--mats at nifty dot com>
|
||||
小林 雅典さん (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>
|
||||
河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
|
||||
岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
|
||||
内田さん (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com>
|
||||
==================================
|
||||
|
||||
Linux カーネル開発のやり方
|
||||
@@ -40,7 +41,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||
手助けになります。
|
||||
|
||||
もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
|
||||
トの最後にリストしたメンテナーにパッチを送ってください。
|
||||
トの最後にリストしたメンテナにパッチを送ってください。
|
||||
|
||||
はじめに
|
||||
---------
|
||||
@@ -59,7 +60,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||
ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
|
||||
でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
|
||||
ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
|
||||
ではありませんが、少なくともリファレンスとしてはいい本です。
|
||||
ではありませんが、少なくともリファレンスとしては良い本です。
|
||||
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
||||
-『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
|
||||
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
||||
@@ -76,7 +77,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||
ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
|
||||
なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
|
||||
レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
|
||||
みてください。
|
||||
見てください。
|
||||
|
||||
あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
|
||||
とに留意してください。そのコミュニティは、コーディング、スタイル、
|
||||
@@ -92,7 +93,7 @@ Linux カーネル開発コミュニティと共に活動するやり方を学
|
||||
|
||||
Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
|
||||
す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
|
||||
する、COPYING のファイルをみてください。もしライセンスについてさらに質
|
||||
する、COPYING のファイルを見てください。もしライセンスについてさらに質
|
||||
問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
|
||||
法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
|
||||
問題については彼らの声明はあてにするべきではありません。
|
||||
@@ -109,7 +110,8 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||
新しいドキュメントファイルも追加することを勧めます。
|
||||
カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
|
||||
変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
|
||||
をマニュアルページのメンテナ mtk-manpages@gmx.net に送ることを勧めます。
|
||||
をマニュアルページのメンテナ mtk-manpages@gmx.net に送ることを勧めま
|
||||
す。
|
||||
|
||||
以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
|
||||
す-
|
||||
@@ -117,7 +119,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||
README
|
||||
このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
|
||||
configure )し、生成(訳注 build )するために必要なことは何かが書かれ
|
||||
ています。カーネルに関して初めての人はここからスタートするとよいで
|
||||
ています。カーネルに関して初めての人はここからスタートすると良いで
|
||||
しょう。
|
||||
|
||||
Documentation/Changes
|
||||
@@ -128,7 +130,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||
Documentation/CodingStyle
|
||||
これは Linux カーネルのコーディングスタイルと背景にある理由を記述
|
||||
しています。全ての新しいコードはこのドキュメントにあるガイドライン
|
||||
に従っていることを期待されています。大部分のメンテナーはこれらのルー
|
||||
に従っていることを期待されています。大部分のメンテナはこれらのルー
|
||||
ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
|
||||
だけをレビューします。
|
||||
|
||||
@@ -168,16 +170,16 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
|
||||
支援してください。
|
||||
|
||||
Documentation/ManagementStyle
|
||||
このドキュメントは Linux カーネルのメンテナー達がどう行動するか、
|
||||
このドキュメントは Linux カーネルのメンテナ達がどう行動するか、
|
||||
彼らの手法の背景にある共有されている精神について記述しています。こ
|
||||
れはカーネル開発の初心者なら(もしくは、単に興味があるだけの人でも)
|
||||
重要です。なぜならこのドキュメントは、カーネルメンテナー達の独特な
|
||||
重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な
|
||||
行動についての多くの誤解や混乱を解消するからです。
|
||||
|
||||
Documentation/stable_kernel_rules.txt
|
||||
このファイルはどのように stable カーネルのリリースが行われるかのルー
|
||||
ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
|
||||
り入れてもらいたい場合に何をすればいいかが示されています。
|
||||
り入れてもらいたい場合に何をすれば良いかが示されています。
|
||||
|
||||
Documentation/kernel-docs.txt
|
||||
カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
|
||||
@@ -218,9 +220,9 @@ web サイトには、コードの構成、サブシステム、現在存在す
|
||||
ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
|
||||
的な基本情報も記述されています。
|
||||
|
||||
あなたがどこからスタートしてよいかわからないが、Linux カーネル開発コミュ
|
||||
あなたがどこからスタートして良いかわからないが、Linux カーネル開発コミュ
|
||||
ニティに参加して何かすることをさがしている場合には、Linux kernel
|
||||
Janitor's プロジェクトにいけばよいでしょう -
|
||||
Janitor's プロジェクトにいけば良いでしょう -
|
||||
http://janitor.kernelnewbies.org/
|
||||
ここはそのようなスタートをするのにうってつけの場所です。ここには、
|
||||
Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
|
||||
@@ -243,7 +245,7 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
|
||||
自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
|
||||
できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
|
||||
ます-
|
||||
http://sosdg.org/~coywolf/lxr/
|
||||
http://sosdg.org/~qiyong/lxr/
|
||||
|
||||
開発プロセス
|
||||
-----------------------
|
||||
@@ -265,9 +267,9 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
||||
以下のとおり-
|
||||
|
||||
- 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
|
||||
この期間中に、メンテナー達は Linus に大きな差分を送ることができま
|
||||
す。このような差分は通常 -mm カーネルに数週間含まれてきたパッチで
|
||||
す。 大きな変更は git(カーネルのソース管理ツール、詳細は
|
||||
この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
|
||||
このような差分は通常 -mm カーネルに数週間含まれてきたパッチです。
|
||||
大きな変更は git(カーネルのソース管理ツール、詳細は
|
||||
http://git.or.cz/ 参照) を使って送るのが好ましいやり方ですが、パッ
|
||||
チファイルの形式のまま送るのでも十分です。
|
||||
|
||||
@@ -285,6 +287,10 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
||||
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
||||
しい -rc カーネルをリリースすることです。
|
||||
|
||||
- 以下の URL で各 -rc リリースに存在する既知の後戻り問題のリスト
|
||||
が追跡されます-
|
||||
http://kernelnewbies.org/known_regressions
|
||||
|
||||
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
||||
す。このプロセスはだいたい 6週間継続します。
|
||||
|
||||
@@ -331,8 +337,8 @@ Andrew は個別のサブシステムカーネルツリーとパッチを全て
|
||||
linux-kernel メーリングリストで収集された多数のパッチと同時に一つにま
|
||||
とめます。
|
||||
このツリーは新機能とパッチが検証される場となります。ある期間の間パッチ
|
||||
が -mm に入って価値を証明されたら、Andrew やサブシステムメンテナが、メ
|
||||
インラインへ入れるように Linus にプッシュします。
|
||||
が -mm に入って価値を証明されたら、Andrew やサブシステムメンテナが、
|
||||
メインラインへ入れるように Linus にプッシュします。
|
||||
|
||||
メインカーネルツリーに含めるために Linus に送る前に、すべての新しいパッ
|
||||
チが -mm ツリーでテストされることが強く推奨されます。
|
||||
@@ -460,7 +466,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||
せん-
|
||||
彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
|
||||
るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
|
||||
に確認した方がいいです。最初の良いテストとしては、自分にメールを送って
|
||||
に確認した方が良いです。最初の良いテストとしては、自分にメールを送って
|
||||
みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
|
||||
ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
|
||||
きです。
|
||||
@@ -507,14 +513,14 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||
とも普通のことです。これはあなたのパッチが受け入れられないということで
|
||||
は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
|
||||
せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
|
||||
いいのです。
|
||||
良いのです。
|
||||
|
||||
|
||||
カーネルコミュニティと企業組織のちがい
|
||||
-----------------------------------------------------------------
|
||||
|
||||
カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
|
||||
動いています。以下は問題を避けるためにできるとよいことののリストです-
|
||||
動いています。以下は問題を避けるためにできると良いことのリストです-
|
||||
|
||||
あなたの提案する変更について言うときのうまい言い方:
|
||||
|
||||
@@ -525,7 +531,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
||||
- "以下は一連の小さなパッチ群ですが..."
|
||||
- "これは典型的なマシンでの性能を向上させます.."
|
||||
|
||||
やめた方がいい悪い言い方:
|
||||
やめた方が良い悪い言い方:
|
||||
|
||||
- このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
|
||||
- 私はこれを20年もの間やってきた、だから
|
||||
@@ -575,10 +581,10 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||
|
||||
1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
|
||||
ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
|
||||
らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。し
|
||||
かし、500行のパッチは、正しいことをレビューするのに数時間かかるかも
|
||||
しれません(時間はパッチのサイズなどにより指数関数に比例してかかりま
|
||||
す)
|
||||
らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。
|
||||
しかし、500行のパッチは、正しいことをレビューするのに数時間かかるか
|
||||
もしれません(時間はパッチのサイズなどにより指数関数に比例してかかり
|
||||
ます)
|
||||
|
||||
小さいパッチは何かあったときにデバッグもとても簡単になります。パッ
|
||||
チを1個1個取り除くのは、とても大きなパッチを当てた後に(かつ、何かお
|
||||
@@ -587,23 +593,23 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||
2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
|
||||
る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
|
||||
|
||||
以下はカーネル開発者の Al Viro のたとえ話しです:
|
||||
以下はカーネル開発者の Al Viro のたとえ話です:
|
||||
|
||||
"生徒の数学の宿題を採点する先生のことを考えてみてください、先
|
||||
生は生徒が解に到達するまでの試行錯誤をみたいとは思わないでしょ
|
||||
う。先生は簡潔な最高の解をみたいのです。良い生徒はこれを知って
|
||||
生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでしょ
|
||||
う。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知って
|
||||
おり、そして最終解の前の中間作業を提出することは決してないので
|
||||
す"
|
||||
|
||||
カーネル開発でもこれは同じです。メンテナー達とレビューア達は、
|
||||
問題を解決する解の背後になる思考プロセスをみたいとは思いません。
|
||||
彼らは単純であざやかな解決方法をみたいのです。
|
||||
カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
|
||||
問題を解決する解の背後になる思考プロセスを見たいとは思いません。
|
||||
彼らは単純であざやかな解決方法を見たいのです。
|
||||
|
||||
あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
|
||||
議論することのバランスをキープするのは難しいかもしれません。
|
||||
ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
|
||||
うにするのもいいですが、変更点を小さい部分に分割して全体ではまだ完成し
|
||||
ていない仕事を(部分的に)取り込んでもらえるようにすることもいいことです。
|
||||
うにするのも良いですが、変更点を小さい部分に分割して全体ではまだ完成し
|
||||
ていない仕事を(部分的に)取り込んでもらえるようにすることも良いことです。
|
||||
|
||||
また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
|
||||
てもらうように送っても、それは受け付けられないことを理解してください。
|
||||
@@ -629,7 +635,7 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
||||
- テスト結果
|
||||
|
||||
これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
|
||||
ントの ChangeLog セクションをみてください-
|
||||
ントの ChangeLog セクションを見てください-
|
||||
"The Perfect Patch"
|
||||
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]
|
||||
See Documentation/paride.txt.
|
||||
|
||||
pty.legacy_count=
|
||||
[KNL] Number of legacy pty's. Overwrites compiled-in
|
||||
default number.
|
||||
|
||||
quiet [KNL] Disable most log messages
|
||||
|
||||
r128= [HW,DRM]
|
||||
|
||||
@@ -54,7 +54,6 @@ embedded in larger data structures and replace fields they duplicate.
|
||||
|
||||
struct kobject {
|
||||
const char * k_name;
|
||||
char name[KOBJ_NAME_LEN];
|
||||
struct kref kref;
|
||||
struct list_head entry;
|
||||
struct kobject * parent;
|
||||
@@ -223,18 +222,15 @@ decl_subsys(devices, &ktype_device, &device_uevent_ops);
|
||||
is equivalent to doing:
|
||||
|
||||
struct kset devices_subsys = {
|
||||
.kobj = {
|
||||
.name = "devices",
|
||||
},
|
||||
.ktype = &ktype_devices,
|
||||
.uevent_ops = &device_uevent_ops,
|
||||
};
|
||||
|
||||
kobject_set_name(&devices_subsys, name);
|
||||
|
||||
The objects that are registered with a subsystem that use the
|
||||
subsystem's default list must have their kset ptr set properly. These
|
||||
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)
|
||||
@@ -242,22 +238,8 @@ kobj_set_kset_s(obj,subsys)
|
||||
- Assumes that obj->kobj exists, and is a struct kobject.
|
||||
- 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);
|
||||
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.
|
||||
|
||||
|
||||
@@ -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,
|
||||
char *buffer, int buffer_size)
|
||||
static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev,
|
||||
return tsize;
|
||||
}
|
||||
|
||||
int of_device_uevent(struct device *dev,
|
||||
char **envp, int num_envp, char *buffer, int buffer_size)
|
||||
int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct of_device *ofdev;
|
||||
const char *compat;
|
||||
int i = 0, length = 0, seen = 0, cplen, sl;
|
||||
int seen = 0, cplen, sl;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
ofdev = to_of_device(dev);
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"OF_NAME=%s", ofdev->node->name))
|
||||
if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name))
|
||||
return -ENOMEM;
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"OF_TYPE=%s", ofdev->node->type))
|
||||
if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type))
|
||||
return -ENOMEM;
|
||||
|
||||
/* 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);
|
||||
while (compat && *compat && cplen > 0) {
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"OF_COMPATIBLE_%d=%s", seen, compat))
|
||||
if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
|
||||
return -ENOMEM;
|
||||
|
||||
sl = strlen (compat) + 1;
|
||||
@@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev,
|
||||
seen++;
|
||||
}
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"OF_COMPATIBLE_N=%d", seen))
|
||||
if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
|
||||
return -ENOMEM;
|
||||
|
||||
/* modalias is trickier, we add it in 2 steps */
|
||||
if (add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MODALIAS="))
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
sl = of_device_get_modalias(ofdev, &buffer[length-1],
|
||||
buffer_size-length);
|
||||
if (sl >= (buffer_size-length))
|
||||
sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
|
||||
sizeof(env->buf) - env->buflen);
|
||||
if (sl >= (sizeof(env->buf) - env->buflen))
|
||||
return -ENOMEM;
|
||||
|
||||
length += sl;
|
||||
|
||||
envp[i] = NULL;
|
||||
env->buflen += sl;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
const struct vio_dev *vio_dev = to_vio_dev(dev);
|
||||
struct device_node *dn;
|
||||
const char *cp;
|
||||
int length;
|
||||
|
||||
if (!num_envp)
|
||||
return -ENOMEM;
|
||||
|
||||
dn = dev->archdata.of_node;
|
||||
if (!dn)
|
||||
return -ENODEV;
|
||||
cp = of_get_property(dn, "compatible", &length);
|
||||
cp = of_get_property(dn, "compatible", NULL);
|
||||
if (!cp)
|
||||
return -ENODEV;
|
||||
|
||||
envp[0] = buffer;
|
||||
length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
|
||||
vio_dev->type, cp);
|
||||
if ((buffer_size - length) <= 0)
|
||||
return -ENOMEM;
|
||||
envp[1] = NULL;
|
||||
add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev)
|
||||
dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
static int ps3_system_bus_uevent(struct device *_dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
|
||||
int i = 0, length = 0;
|
||||
|
||||
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, "MODALIAS=ps3:%d",
|
||||
dev->match_id))
|
||||
if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
|
||||
return -ENOMEM;
|
||||
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1010,10 +1010,7 @@ unlock:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bsg_register_queue);
|
||||
|
||||
static struct cdev bsg_cdev = {
|
||||
.kobj = {.name = "bsg", },
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
static struct cdev bsg_cdev;
|
||||
|
||||
static int __init bsg_init(void)
|
||||
{
|
||||
|
||||
@@ -186,7 +186,7 @@ static elevator_t *elevator_alloc(struct request_queue *q,
|
||||
eq->ops = &e->ops;
|
||||
eq->elevator_type = e;
|
||||
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;
|
||||
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));
|
||||
}
|
||||
|
||||
static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int block_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
struct kobj_type *ktype = get_ktype(kobj);
|
||||
struct device *physdev;
|
||||
struct gendisk *disk;
|
||||
struct hd_struct *part;
|
||||
int length = 0;
|
||||
int i = 0;
|
||||
|
||||
if (ktype == &ktype_block) {
|
||||
disk = container_of(kobj, struct gendisk, kobj);
|
||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, "MINOR=%u", disk->first_minor);
|
||||
add_uevent_var(env, "MINOR=%u", disk->first_minor);
|
||||
} else if (ktype == &ktype_part) {
|
||||
disk = container_of(kobj->parent, struct gendisk, kobj);
|
||||
part = container_of(kobj, struct hd_struct, kobj);
|
||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, "MINOR=%u",
|
||||
add_uevent_var(env, "MINOR=%u",
|
||||
disk->first_minor + part->partno);
|
||||
} else
|
||||
return 0;
|
||||
|
||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
||||
"MAJOR=%u", disk->major);
|
||||
add_uevent_var(env, "MAJOR=%u", disk->major);
|
||||
|
||||
/* add physical device, backing this device */
|
||||
physdev = disk->driverfs_dev;
|
||||
if (physdev) {
|
||||
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
||||
|
||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, "PHYSDEVPATH=%s", path);
|
||||
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
|
||||
if (physdev->bus)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s",
|
||||
physdev->bus->name);
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", physdev->bus->name);
|
||||
|
||||
if (physdev->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s",
|
||||
physdev->driver->name);
|
||||
add_uevent_var(env, 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1854,7 +1854,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
|
||||
|
||||
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;
|
||||
kobject_init(&q->kobj);
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
|
||||
|
||||
if (!device->flags.power_manageable) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
|
||||
device->dev.kobj.name));
|
||||
kobject_name(&device->dev.kobj)));
|
||||
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);
|
||||
}
|
||||
|
||||
static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
int len;
|
||||
|
||||
strcpy(buffer, "MODALIAS=");
|
||||
if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) {
|
||||
envp[0] = buffer;
|
||||
envp[1] = NULL;
|
||||
}
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen);
|
||||
if (len >= (sizeof(env->buf) - env->buflen))
|
||||
return -ENOMEM;
|
||||
env->buflen += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ static int acpi_video_output_get(struct output_device *od)
|
||||
{
|
||||
unsigned long state;
|
||||
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);
|
||||
return (int)state;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ static int acpi_video_output_set(struct output_device *od)
|
||||
{
|
||||
unsigned long state = od->request_state;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,15 +44,12 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||
}
|
||||
|
||||
#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);
|
||||
int retval = 0, i = 0, len = 0;
|
||||
int retval = 0;
|
||||
|
||||
retval = add_uevent_var(envp, nr_env, &i,
|
||||
buf, bufsz, &len,
|
||||
"AMBA_ID=%08x", pcdev->periphid);
|
||||
envp[i] = NULL;
|
||||
retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
|
||||
return retval;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
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
|
||||
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
|
||||
default y
|
||||
|
||||
@@ -18,8 +18,6 @@ extern int attribute_container_init(void);
|
||||
extern int bus_add_device(struct device * dev);
|
||||
extern void bus_attach_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 void bus_remove_driver(struct device_driver *);
|
||||
|
||||
@@ -30,6 +30,17 @@
|
||||
static int __must_check bus_rescan_devices_helper(struct device *dev,
|
||||
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
|
||||
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,
|
||||
.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 error;
|
||||
if (get_bus(bus)) {
|
||||
if (bus_get(bus)) {
|
||||
error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
|
||||
put_bus(bus);
|
||||
bus_put(bus);
|
||||
} else
|
||||
error = -EINVAL;
|
||||
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)
|
||||
{
|
||||
if (get_bus(bus)) {
|
||||
if (bus_get(bus)) {
|
||||
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,
|
||||
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;
|
||||
int err = -ENODEV;
|
||||
|
||||
@@ -186,7 +197,7 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
||||
err = count;
|
||||
}
|
||||
put_device(dev);
|
||||
put_bus(bus);
|
||||
bus_put(bus);
|
||||
return err;
|
||||
}
|
||||
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,
|
||||
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;
|
||||
int err = -ENODEV;
|
||||
|
||||
@@ -219,7 +230,7 @@ static ssize_t driver_bind(struct device_driver *drv,
|
||||
err = -ENODEV;
|
||||
}
|
||||
put_device(dev);
|
||||
put_bus(bus);
|
||||
bus_put(bus);
|
||||
return err;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct bus_type * bus = get_bus(dev->bus);
|
||||
struct bus_type * bus = bus_get(dev->bus);
|
||||
int error = 0;
|
||||
|
||||
if (bus) {
|
||||
@@ -459,7 +470,7 @@ out_subsys:
|
||||
out_id:
|
||||
device_remove_attrs(bus, dev);
|
||||
out_put:
|
||||
put_bus(dev->bus);
|
||||
bus_put(dev->bus);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int retval;
|
||||
|
||||
bus->drivers_probe_attr.attr.name = "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);
|
||||
retval = bus_create_file(bus, &bus_attr_drivers_probe);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
bus->drivers_autoprobe_attr.attr.name = "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);
|
||||
retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
|
||||
if (retval)
|
||||
bus_remove_file(bus, &bus->drivers_probe_attr);
|
||||
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void remove_probe_files(struct bus_type *bus)
|
||||
{
|
||||
bus_remove_file(bus, &bus->drivers_autoprobe_attr);
|
||||
bus_remove_file(bus, &bus->drivers_probe_attr);
|
||||
bus_remove_file(bus, &bus_attr_drivers_autoprobe);
|
||||
bus_remove_file(bus, &bus_attr_drivers_probe);
|
||||
}
|
||||
#else
|
||||
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) {}
|
||||
#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.
|
||||
* @drv: driver.
|
||||
@@ -609,7 +628,7 @@ static inline void remove_probe_files(struct bus_type *bus) {}
|
||||
*/
|
||||
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;
|
||||
|
||||
if (!bus)
|
||||
@@ -632,6 +651,11 @@ int bus_add_driver(struct device_driver *drv)
|
||||
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
|
||||
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);
|
||||
if (error) {
|
||||
/* 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:
|
||||
kobject_unregister(&drv->kobj);
|
||||
out_put_bus:
|
||||
put_bus(bus);
|
||||
bus_put(bus);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -669,12 +693,13 @@ void bus_remove_driver(struct device_driver * drv)
|
||||
|
||||
remove_bind_files(drv);
|
||||
driver_remove_attrs(drv->bus, drv);
|
||||
driver_remove_file(drv, &driver_attr_uevent);
|
||||
klist_remove(&drv->knode_bus);
|
||||
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
|
||||
driver_detach(drv);
|
||||
module_remove_driver(drv);
|
||||
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);
|
||||
|
||||
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.
|
||||
* @name: name of bus.
|
||||
@@ -808,6 +821,17 @@ static void klist_devices_put(struct klist_node *n)
|
||||
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: bus.
|
||||
@@ -826,11 +850,16 @@ int bus_register(struct bus_type * bus)
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
subsys_set_kset(bus, bus_subsys);
|
||||
bus->subsys.kobj.kset = &bus_subsys;
|
||||
|
||||
retval = subsystem_register(&bus->subsys);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
retval = bus_create_file(bus, &bus_attr_uevent);
|
||||
if (retval)
|
||||
goto bus_uevent_fail;
|
||||
|
||||
kobject_set_name(&bus->devices.kobj, "devices");
|
||||
bus->devices.kobj.parent = &bus->subsys.kobj;
|
||||
retval = kset_register(&bus->devices);
|
||||
@@ -839,7 +868,7 @@ int bus_register(struct bus_type * bus)
|
||||
|
||||
kobject_set_name(&bus->drivers.kobj, "drivers");
|
||||
bus->drivers.kobj.parent = &bus->subsys.kobj;
|
||||
bus->drivers.ktype = &ktype_driver;
|
||||
bus->drivers.ktype = &driver_ktype;
|
||||
retval = kset_register(&bus->drivers);
|
||||
if (retval)
|
||||
goto bus_drivers_fail;
|
||||
@@ -866,6 +895,8 @@ bus_probe_files_fail:
|
||||
bus_drivers_fail:
|
||||
kset_unregister(&bus->devices);
|
||||
bus_devices_fail:
|
||||
bus_remove_file(bus, &bus_attr_uevent);
|
||||
bus_uevent_fail:
|
||||
subsystem_unregister(&bus->subsys);
|
||||
out:
|
||||
return retval;
|
||||
@@ -876,7 +907,7 @@ out:
|
||||
* @bus: bus.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
@@ -885,6 +916,7 @@ void bus_unregister(struct bus_type * bus)
|
||||
remove_probe_files(bus);
|
||||
kset_unregister(&bus->drivers);
|
||||
kset_unregister(&bus->devices);
|
||||
bus_remove_file(bus, &bus_attr_uevent);
|
||||
subsystem_unregister(&bus->subsys);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,13 @@ static struct sysfs_ops class_sysfs_ops = {
|
||||
.store = class_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type ktype_class = {
|
||||
static struct kobj_type class_ktype = {
|
||||
.sysfs_ops = &class_sysfs_ops,
|
||||
.release = class_release,
|
||||
};
|
||||
|
||||
/* 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)
|
||||
@@ -93,14 +93,14 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr)
|
||||
static struct class *class_get(struct class *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;
|
||||
}
|
||||
|
||||
static void class_put(struct class * cls)
|
||||
{
|
||||
if (cls)
|
||||
subsys_put(&cls->subsys);
|
||||
kset_put(&cls->subsys);
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ int class_register(struct class * cls)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
subsys_set_kset(cls, class_subsys);
|
||||
cls->subsys.kobj.kset = &class_subsys;
|
||||
|
||||
error = subsystem_register(&cls->subsys);
|
||||
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 */
|
||||
static int class_device_create_uevent(struct class_device *class_dev,
|
||||
char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||
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,
|
||||
.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);
|
||||
|
||||
if (ktype == &ktype_class_device) {
|
||||
if (ktype == &class_device_ktype) {
|
||||
struct class_device *class_dev = to_class_dev(kobj);
|
||||
if (class_dev->class)
|
||||
return 1;
|
||||
@@ -403,64 +402,43 @@ static void remove_deprecated_class_device_links(struct class_device *cd)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int class_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
struct class_device *class_dev = to_class_dev(kobj);
|
||||
struct device *dev = class_dev->dev;
|
||||
int i = 0;
|
||||
int length = 0;
|
||||
int retval = 0;
|
||||
|
||||
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
|
||||
|
||||
if (MAJOR(class_dev->devt)) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MAJOR=%u", MAJOR(class_dev->devt));
|
||||
add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
|
||||
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MINOR=%u", MINOR(class_dev->devt));
|
||||
add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
||||
if (path) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVPATH=%s", path);
|
||||
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
}
|
||||
|
||||
if (dev->bus)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s", dev->bus->name);
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
add_uevent_var(env, "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) {
|
||||
/* have the class device specific function add its stuff */
|
||||
retval = class_dev->uevent(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
retval = class_dev->uevent(class_dev, env);
|
||||
if (retval)
|
||||
pr_debug("class_dev->uevent() returned %d\n", retval);
|
||||
} else if (class_dev->class->uevent) {
|
||||
/* have the class specific function add its stuff */
|
||||
retval = class_dev->class->uevent(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
retval = class_dev->class->uevent(class_dev, env);
|
||||
if (retval)
|
||||
pr_debug("class->uevent() returned %d\n", retval);
|
||||
}
|
||||
@@ -474,7 +452,7 @@ static struct kset_uevent_ops class_uevent_ops = {
|
||||
.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)
|
||||
@@ -883,7 +861,7 @@ int __init classes_init(void)
|
||||
|
||||
/* ick, this is ugly, the things we go through to keep from showing up
|
||||
* in sysfs... */
|
||||
subsystem_init(&class_obj_subsys);
|
||||
kset_init(&class_obj_subsys);
|
||||
if (!class_obj_subsys.kobj.parent)
|
||||
class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
|
||||
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,
|
||||
.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);
|
||||
|
||||
if (ktype == &ktype_device) {
|
||||
if (ktype == &device_ktype) {
|
||||
struct device *dev = to_dev(kobj);
|
||||
if (dev->uevent_suppress)
|
||||
return 0;
|
||||
@@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct kobj_uevent_env *env)
|
||||
{
|
||||
struct device *dev = to_dev(kobj);
|
||||
int i = 0;
|
||||
int length = 0;
|
||||
int retval = 0;
|
||||
|
||||
/* add the major/minor if present */
|
||||
if (MAJOR(dev->devt)) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MAJOR=%u", MAJOR(dev->devt));
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"MINOR=%u", MINOR(dev->devt));
|
||||
add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
|
||||
add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
|
||||
}
|
||||
|
||||
if (dev->type && dev->type->name)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"DEVTYPE=%s", dev->type->name);
|
||||
add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"DRIVER=%s", dev->driver->name);
|
||||
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
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);
|
||||
if (path) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVPATH=%s", path);
|
||||
add_uevent_var(env, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
}
|
||||
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s", parent->bus->name);
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
|
||||
|
||||
if (parent->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s", parent->driver->name);
|
||||
add_uevent_var(env, "PHYSDEVDRIVER=%s",
|
||||
parent->driver->name);
|
||||
}
|
||||
} else if (dev->bus) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s", dev->bus->name);
|
||||
add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* terminate, set to next free slot, shrink available space */
|
||||
envp[i] = NULL;
|
||||
envp = &envp[i];
|
||||
num_envp -= i;
|
||||
buffer = &buffer[length];
|
||||
buffer_size -= length;
|
||||
|
||||
/* have the bus specific function add its stuff */
|
||||
if (dev->bus && dev->bus->uevent) {
|
||||
/* have the bus specific function add its stuff */
|
||||
retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
|
||||
retval = dev->bus->uevent(dev, env);
|
||||
if (retval)
|
||||
pr_debug ("%s: bus uevent() returned %d\n",
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
|
||||
/* have the class specific function add its stuff */
|
||||
if (dev->class && dev->class->dev_uevent) {
|
||||
/* have the class specific function add its stuff */
|
||||
retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
|
||||
retval = dev->class->dev_uevent(dev, env);
|
||||
if (retval)
|
||||
pr_debug("%s: class uevent() returned %d\n",
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
|
||||
/* have the device type specific fuction add its stuff */
|
||||
if (dev->type && dev->type->uevent) {
|
||||
/* have the device type specific fuction add its stuff */
|
||||
retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
|
||||
retval = dev->type->uevent(dev, env);
|
||||
if (retval)
|
||||
pr_debug("%s: dev_type uevent() returned %d\n",
|
||||
__FUNCTION__, retval);
|
||||
@@ -253,22 +227,18 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct kobject *top_kobj;
|
||||
struct kset *kset;
|
||||
char *envp[32];
|
||||
char *data = NULL;
|
||||
char *pos;
|
||||
struct kobj_uevent_env *env = NULL;
|
||||
int i;
|
||||
size_t count = 0;
|
||||
int retval;
|
||||
|
||||
/* search the kset, the device belongs to */
|
||||
top_kobj = &dev->kobj;
|
||||
if (!top_kobj->kset && top_kobj->parent) {
|
||||
do {
|
||||
top_kobj = top_kobj->parent;
|
||||
} while (!top_kobj->kset && top_kobj->parent);
|
||||
}
|
||||
while (!top_kobj->kset && top_kobj->parent)
|
||||
top_kobj = top_kobj->parent;
|
||||
if (!top_kobj->kset)
|
||||
goto out;
|
||||
|
||||
kset = top_kobj->kset;
|
||||
if (!kset->uevent_ops || !kset->uevent_ops->uevent)
|
||||
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))
|
||||
goto out;
|
||||
|
||||
data = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!data)
|
||||
env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* let the kset specific function add its keys */
|
||||
pos = data;
|
||||
memset(envp, 0, sizeof(envp));
|
||||
retval = kset->uevent_ops->uevent(kset, &dev->kobj,
|
||||
envp, ARRAY_SIZE(envp),
|
||||
pos, PAGE_SIZE);
|
||||
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
/* copy keys to file */
|
||||
for (i = 0; envp[i]; i++) {
|
||||
pos = &buf[count];
|
||||
count += sprintf(pos, "%s\n", envp[i]);
|
||||
}
|
||||
for (i = 0; i < env->envp_idx; i++)
|
||||
count += sprintf(&buf[count], "%s\n", env->envp[i]);
|
||||
out:
|
||||
free_page((unsigned long)data);
|
||||
kfree(env);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
size_t len = count;
|
||||
enum kobject_action action;
|
||||
|
||||
if (len && buf[len-1] == '\n')
|
||||
len--;
|
||||
|
||||
for (action = 0; action < KOBJ_MAX; action++) {
|
||||
if (strncmp(kobject_actions[action], buf, len) != 0)
|
||||
continue;
|
||||
if (kobject_actions[action][len] != '\0')
|
||||
continue;
|
||||
if (kobject_action_type(buf, count, &action) == 0) {
|
||||
kobject_uevent(&dev->kobj, action);
|
||||
goto out;
|
||||
}
|
||||
@@ -449,7 +405,7 @@ static struct device_attribute devt_attr =
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user