diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 22:45:37 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 22:45:37 -0700 |
commit | 94d4ac2f4a58c6e37876827c6688c61cef21290c (patch) | |
tree | 732f4e4794f3c116041242f69754637f75c0dd57 | |
parent | ed21763e7b0b3fb50e4efd9d4bc17ef5b035d304 (diff) | |
parent | 08970fc4e0385790a7b093adfaa4165a189f9eb0 (diff) | |
download | kernel_goldelico_gta04-94d4ac2f4a58c6e37876827c6688c61cef21290c.zip kernel_goldelico_gta04-94d4ac2f4a58c6e37876827c6688c61cef21290c.tar.gz kernel_goldelico_gta04-94d4ac2f4a58c6e37876827c6688c61cef21290c.tar.bz2 |
Merge branch 'x86/urgent' into x86/cleanups
406 files changed, 4395 insertions, 3155 deletions
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 80e193d..0d53949 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt @@ -26,6 +26,12 @@ Mailing list: linux-ext4@vger.kernel.org git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git + - Note that it is highly important to install the mke2fs.conf file + that comes with the e2fsprogs 1.41.x sources in /etc/mke2fs.conf. If + you have edited the /etc/mke2fs.conf file installed on your system, + you will need to merge your changes with the version from e2fsprogs + 1.41.x. + - Create a new filesystem using the ext4dev filesystem type: # mke2fs -t ext4dev /dev/hda1 diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 488c77f..0775cf4 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO @@ -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/11/16 +Last Updated: 2008/08/21 ================================== ã“ã‚Œã¯ã€ -linux-2.6.24/Documentation/HOWTO +linux-2.6.27/Documentation/HOWTO ã®å’Œè¨³ã§ã™ã€‚ 翻訳団体: JF プãƒã‚¸ã‚§ã‚¯ãƒˆ < http://www.linux.or.jp/JF/ > -翻訳日: 2007/11/10 +翻訳日: 2008/8/5 翻訳者: 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> @@ -287,13 +287,15 @@ Linux カーãƒãƒ«ã®é–‹ç™ºãƒ—ãƒã‚»ã‚¹ã¯ç¾åœ¨å¹¾ã¤ã‹ã®ç•°ãªã‚‹ãƒ¡ã‚¤ãƒ³ã‚ ã«å®‰å®šã—ãŸçŠ¶æ…‹ã«ã‚ã‚‹ã¨åˆ¤æ–ã—ãŸã¨ãã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¾ã™ã€‚目標ã¯æ¯Žé€±æ–° ã—ã„ -rc カーãƒãƒ«ã‚’リリースã™ã‚‹ã“ã¨ã§ã™ã€‚ - - 以下㮠URL ã§å„ -rc リリースã«å˜åœ¨ã™ã‚‹æ—¢çŸ¥ã®å¾Œæˆ»ã‚Šå•é¡Œã®ãƒªã‚¹ãƒˆ - ãŒè¿½è·¡ã•ã‚Œã¾ã™- - http://kernelnewbies.org/known_regressions - - ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã‚«ãƒ¼ãƒãƒ«ãŒ 「準備ãŒã§ããŸã€ã¨è€ƒãˆã‚‰ã‚Œã‚‹ã¾ã§ç¶™ç¶šã—ã¾ ã™ã€‚ã“ã®ãƒ—ãƒã‚»ã‚¹ã¯ã ã„ãŸã„ 6週間継続ã—ã¾ã™ã€‚ + - å„リリースã§ã®æ—¢çŸ¥ã®å¾Œæˆ»ã‚Šå•é¡Œ(regression: ã“ã®ãƒªãƒªãƒ¼ã‚¹ã®ä¸ã§æ–°è¦ + ã«ä½œã‚Šè¾¼ã¾ã‚ŒãŸå•é¡Œã‚’指ã™) ã¯ãã®éƒ½åº¦ Linux-kernel メーリングリスト + ã«æŠ•ç¨¿ã•ã‚Œã¾ã™ã€‚ゴールã¨ã—ã¦ã¯ã€ã‚«ãƒ¼ãƒãƒ«ãŒ 「準備ãŒã§ããŸã€ã¨å®£è¨€ + ã™ã‚‹å‰ã«ã“ã®ãƒªã‚¹ãƒˆã®é•·ã•ã‚’ゼãƒã«æ¸›ã‚‰ã™ã“ã¨ã§ã™ãŒã€ç¾å®Ÿã«ã¯ã€æ•°å€‹ã® + 後戻りå•é¡ŒãŒãƒªãƒªãƒ¼ã‚¹æ™‚ã«ãŸã³ãŸã³æ®‹ã£ã¦ã—ã¾ã„ã¾ã™ã€‚ + Andrew Morton ㌠Linux-kernel メーリングリストã«ã‚«ãƒ¼ãƒãƒ«ãƒªãƒªãƒ¼ã‚¹ã«ã¤ã„ ã¦æ›¸ã„ãŸã“ã¨ã‚’ã“ã“ã§è¨€ã£ã¦ãŠãã“ã¨ã¯ä¾¡å€¤ãŒã‚ã‚Šã¾ã™- 「カーãƒãƒ«ãŒã„ã¤ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹ã‹ã¯èª°ã‚‚知りã¾ã›ã‚“。ãªãœãªã‚‰ã€ã“ã‚Œã¯ç¾ @@ -303,18 +305,20 @@ Andrew Morton ㌠Linux-kernel メーリングリストã«ã‚«ãƒ¼ãƒãƒ«ãƒªãƒªãƒ¼ã 2.6.x.y -stable カーãƒãƒ«ãƒ„リー --------------------------- -ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«4ã¤ç›®ã®æ•°å—ãŒã¤ã„ãŸã‚«ãƒ¼ãƒãƒ«ã¯ -stable カーãƒãƒ«ã§ã™ã€‚ã“れ㫠-ã¯ã€2.6.x カーãƒãƒ«ã§è¦‹ã¤ã‹ã£ãŸã‚»ã‚ュリティå•é¡Œã‚„é‡å¤§ãªå¾Œæˆ»ã‚Šã«å¯¾ã™ã‚‹æ¯” -較的å°ã•ã„é‡è¦ãªä¿®æ£ãŒå«ã¾ã‚Œã¾ã™ã€‚ +ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒ4ã¤ã®æ•°å—ã«åˆ†ã‹ã‚Œã¦ã„るカーãƒãƒ«ã¯ -stable カーãƒãƒ«ã§ã™ã€‚ +ã“ã‚Œã«ã¯ã€2.6.x カーãƒãƒ«ã§è¦‹ã¤ã‹ã£ãŸã‚»ã‚ュリティå•é¡Œã‚„é‡å¤§ãªå¾Œæˆ»ã‚Šã«å¯¾ +ã™ã‚‹æ¯”較的å°ã•ã„é‡è¦ãªä¿®æ£ãŒå«ã¾ã‚Œã¾ã™ã€‚ ã“ã‚Œã¯ã€é–‹ç™º/実験的ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ†ã‚¹ãƒˆã«å”力ã™ã‚‹ã“ã¨ã«èˆˆå‘³ãŒç„¡ã〠最新ã®å®‰å®šã—ãŸã‚«ãƒ¼ãƒãƒ«ã‚’使ã„ãŸã„ユーザã«æŽ¨å¥¨ã™ã‚‹ãƒ–ランãƒã§ã™ã€‚ -ã‚‚ã—ã€2.6.x.y カーãƒãƒ«ãŒå˜åœ¨ã—ãªã„å ´åˆã«ã¯ã€ç•ªå·ãŒä¸€ç•ªå¤§ãã„ 2.6.x -ãŒæœ€æ–°ã®å®‰å®šç‰ˆã‚«ãƒ¼ãƒãƒ«ã§ã™ã€‚ +ã‚‚ã—ã€2.6.x.y カーãƒãƒ«ãŒå˜åœ¨ã—ãªã„å ´åˆã«ã¯ã€ç•ªå·ãŒä¸€ç•ªå¤§ãã„ 2.6.x ㌠+最新ã®å®‰å®šç‰ˆã‚«ãƒ¼ãƒãƒ«ã§ã™ã€‚ -2.6.x.y 㯠"stable" ãƒãƒ¼ãƒ <stable@kernel.org> ã§ãƒ¡ãƒ³ãƒ†ã•ã‚Œã¦ãŠã‚Šã€ã -ã„ãŸã„隔週ã§ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¦ã„ã¾ã™ã€‚ +2.6.x.y 㯠"stable" ãƒãƒ¼ãƒ <stable@kernel.org> ã§ãƒ¡ãƒ³ãƒ†ã•ã‚Œã¦ãŠã‚Šã€å¿… +è¦ã«å¿œã˜ã¦ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã¾ã™ã€‚通常ã®ãƒªãƒªãƒ¼ã‚¹æœŸé–“㯠2週間毎ã§ã™ãŒã€å·®ã—迫㣠+ãŸå•é¡ŒãŒãªã‘ã‚Œã°ã‚‚ã†å°‘ã—é•·ããªã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚ã‚»ã‚ュリティ関連ã®å•é¡Œ +ã®å ´åˆã¯ã“ã‚Œã«å¯¾ã—ã¦ã ã„ãŸã„ã®å ´åˆã€ã™ãã«ãƒªãƒªãƒ¼ã‚¹ãŒã•ã‚Œã¾ã™ã€‚ カーãƒãƒ«ãƒ„リーã«å…¥ã£ã¦ã„ã‚‹ã€Documentation/stable_kernel_rules.txt ファ イルã«ã¯ã©ã®ã‚ˆã†ãªç¨®é¡žã®å¤‰æ›´ãŒ -stable ツリーã«å—ã‘入れå¯èƒ½ã‹ã€ã¾ãŸãƒª @@ -341,7 +345,9 @@ linux-kernel メーリングリストã§åŽé›†ã•ã‚ŒãŸå¤šæ•°ã®ãƒ‘ッãƒã¨åŒæ メインラインã¸å…¥ã‚Œã‚‹ã‚ˆã†ã« Linus ã«ãƒ—ッシュã—ã¾ã™ã€‚ メインカーãƒãƒ«ãƒ„リーã«å«ã‚ã‚‹ãŸã‚ã« Linus ã«é€ã‚‹å‰ã«ã€ã™ã¹ã¦ã®æ–°ã—ã„パッ -ãƒãŒ -mm ツリーã§ãƒ†ã‚¹ãƒˆã•ã‚Œã‚‹ã“ã¨ãŒå¼·ã推奨ã•ã‚Œã¾ã™ã€‚ +ãƒãŒ -mm ツリーã§ãƒ†ã‚¹ãƒˆã•ã‚Œã‚‹ã“ã¨ãŒå¼·ã推奨ã•ã‚Œã¦ã„ã¾ã™ã€‚マージウィン +ドウãŒé–‹ãå‰ã« -mm ツリーã«ç¾ã‚Œãªã‹ã£ãŸãƒ‘ッãƒã¯ãƒ¡ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³ã«ãƒžãƒ¼ã‚¸ã• +れるã“ã¨ã¯å›°é›£ã«ãªã‚Šã¾ã™ã€‚ ã“れらã®ã‚«ãƒ¼ãƒãƒ«ã¯å®‰å®šã—ã¦å‹•ä½œã™ã¹ãシステムã¨ã—ã¦ä½¿ã†ã®ã«ã¯é©åˆ‡ã§ã¯ã‚ ã‚Šã¾ã›ã‚“ã—ã€ã‚«ãƒ¼ãƒãƒ«ãƒ–ランãƒã®ä¸ã§ã‚‚ã‚‚ã£ã¨ã‚‚動作ã«ãƒªã‚¹ã‚¯ãŒé«˜ã„ã‚‚ã®ã§ã™ã€‚ @@ -395,13 +401,15 @@ linux-kernel メーリングリストã§åŽé›†ã•ã‚ŒãŸå¤šæ•°ã®ãƒ‘ッãƒã¨åŒæ - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net> git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git - - SCSI, James Bottomley <James.Bottomley@SteelEye.com> + - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com> git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git + - x86, Ingo Molnar <mingo@elte.hu> + git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git + quilt ツリー- - - USB, PCI ドライãƒã‚³ã‚¢ã¨ I2C, Greg Kroah-Hartman <gregkh@suse.de> + - USB, ドライãƒã‚³ã‚¢ã¨ I2C, Greg Kroah-Hartman <gregkh@suse.de> kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ - - x86-64 㨠i386 ã®ä»²é–“ Andi Kleen <ak@suse.de> ãã®ä»–ã®ã‚«ãƒ¼ãƒãƒ«ãƒ„リー㯠http://git.kernel.org/ 㨠MAINTAINERS ファ イルã«ä¸€è¦§è¡¨ãŒã‚ã‚Šã¾ã™ã€‚ @@ -412,13 +420,32 @@ linux-kernel メーリングリストã§åŽé›†ã•ã‚ŒãŸå¤šæ•°ã®ãƒ‘ッãƒã¨åŒæ bugzilla.kernel.org 㯠Linux カーãƒãƒ«é–‹ç™ºè€…ãŒã‚«ãƒ¼ãƒãƒ«ã®ãƒã‚°ã‚’追跡ã™ã‚‹ å ´æ‰€ã§ã™ã€‚ユーザã¯è¦‹ã¤ã‘ãŸãƒã‚°ã®å…¨ã¦ã‚’ã“ã®ãƒ„ールã§å ±å‘Šã™ã¹ãã§ã™ã€‚ ã©ã† kernel bugzilla を使ã†ã‹ã®è©³ç´°ã¯ã€ä»¥ä¸‹ã‚’å‚ç…§ã—ã¦ãã ã•ã„- - http://test.kernel.org/bugzilla/faq.html - + http://bugzilla.kernel.org/page.cgi?id=faq.html メインカーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚るファイル REPORTING-BUGS ã¯ã‚«ãƒ¼ãƒ ルãƒã‚°ã‚‰ã—ã„ã‚‚ã®ã«ã¤ã„ã¦ã©ã†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹ã‹ã®è‰¯ã„テンプレートã§ã‚ã‚Šã€å• é¡Œã®è¿½è·¡ã‚’助ã‘ã‚‹ãŸã‚ã«ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ã«ã¨ã£ã¦ã©ã‚“ãªæƒ…å ±ãŒå¿…è¦ãªã®ã‹ã®è©³ ç´°ãŒæ›¸ã‹ã‚Œã¦ã„ã¾ã™ã€‚ +ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã®ç®¡ç† +------------------- + +ã‚ãªãŸã®ãƒãƒƒã‚ングã®ã‚¹ã‚ルを訓練ã™ã‚‹æœ€é«˜ã®æ–¹æ³•ã®ã²ã¨ã¤ã«ã€ä»–人ãŒãƒ¬ãƒãƒ¼ +トã—ãŸãƒã‚°ã‚’ä¿®æ£ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ã‚ãªãŸãŒã‚«ãƒ¼ãƒãƒ«ã‚’より安定化ã•ã›ã‚‹ +ã“ã«å¯„与ã™ã‚‹ã¨ã„ã†ã“ã¨ã ã‘ã§ãªãã€ã‚ãªãŸã¯ ç¾å®Ÿã®å•é¡Œã‚’ä¿®æ£ã™ã‚‹ã“ã¨ã‚’ +å¦ã³ã€è‡ªåˆ†ã®ã‚¹ã‚ルも強化ã§ãã€ã¾ãŸä»–ã®é–‹ç™ºè€…ãŒã‚ãªãŸã®å˜åœ¨ã«æ°—ãŒã¤ã +ã¾ã™ã€‚ãƒã‚°ã‚’ä¿®æ£ã™ã‚‹ã“ã¨ã¯ã€å¤šãã®é–‹ç™ºè€…ã®ä¸ã‹ã‚‰è‡ªåˆ†ãŒåŠŸç¸¾ã‚’ã‚ã’る最善 +ã®é“ã§ã™ã€ãªãœãªã‚‰å¤šãã®äººã¯ä»–人ã®ãƒã‚°ã®ä¿®æ£ã«æ™‚間を浪費ã™ã‚‹ã“ã¨ã‚’好㾠+ãªã„ã‹ã‚‰ã§ã™ã€‚ + +ã™ã§ã«ãƒ¬ãƒãƒ¼ãƒˆã•ã‚ŒãŸãƒã‚°ã®ãŸã‚ã«ä»•äº‹ã‚’ã™ã‚‹ãŸã‚ã«ã¯ã€ +http://bugzilla.kernel.org ã«è¡Œã£ã¦ãã ã•ã„。もã—今後ã®ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã« +ã¤ã„ã¦ã‚¢ãƒ‰ãƒã‚¤ã‚¹ã‚’å—ã‘ãŸã„ã®ã§ã‚ã‚Œã°ã€bugme-new メーリングリスト(æ–°ã— +ã„ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã ã‘ãŒã“ã“ã«ãƒ¡ãƒ¼ãƒ«ã•ã‚Œã‚‹) ã¾ãŸã¯ bugme-janitor メーリン +グリスト(bugzilla ã®å¤‰æ›´æ¯Žã«ã“ã“ã«ãƒ¡ãƒ¼ãƒ«ã•ã‚Œã‚‹)ã‚’è³¼èªã§ãã¾ã™ã€‚ + + http://lists.linux-foundation.org/mailman/listinfo/bugme-new + http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors + メーリングリスト ------------- diff --git a/Documentation/ja_JP/SubmitChecklist b/Documentation/ja_JP/SubmitChecklist new file mode 100644 index 0000000..6c42e07 --- /dev/null +++ b/Documentation/ja_JP/SubmitChecklist @@ -0,0 +1,111 @@ +NOTE: +This is a version of Documentation/SubmitChecklist into Japanese. +This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com> +and the JF Project team <http://www.linux.or.jp/JF/>. +If you find any difference between this document and the original file +or a problem with the translation, +please contact the maintainer of this file or JF project. + +Please also note that the purpose of this file is to be easier to read +for non English (read: Japanese) speakers and is not intended as a +fork. So if you have any comments or updates of this file, please try +to update the original English file first. + +Last Updated: 2008/07/14 +================================== +ã“ã‚Œã¯ã€ +linux-2.6.26/Documentation/SubmitChecklist ã®å’Œè¨³ã§ã™ã€‚ + +翻訳団体: JF プãƒã‚¸ã‚§ã‚¯ãƒˆ < http://www.linux.or.jp/JF/ > +翻訳日: 2008/07/14 +翻訳者: Takenori Nagano <t-nagano at ah dot jp dot nec dot com> +æ ¡æ£è€…: Masanori Kobayashi ã•ã‚“ <zap03216 at nifty dot ne dot jp> +================================== + + +Linux カーãƒãƒ«ãƒ‘ッãƒæŠ•ç¨¿è€…å‘ã‘ãƒã‚§ãƒƒã‚¯ãƒªã‚¹ãƒˆ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +本書ã§ã¯ã€ãƒ‘ッãƒã‚’ã‚ˆã‚Šç´ æ—©ãå–り込んã§ã‚‚らã„ãŸã„開発者ãŒå®Ÿè·µã™ã¹ã基本的ãªäº‹æŸ„ +ã‚’ã„ãã¤ã‹ç´¹ä»‹ã—ã¾ã™ã€‚ã“ã“ã«ã‚ã‚‹å…¨ã¦ã®äº‹æŸ„ã¯ã€Documentation/SubmittingPatches +ãªã©ã®Linuxカーãƒãƒ«ãƒ‘ッãƒæŠ•ç¨¿ã«éš›ã—ã¦ã®å¿ƒå¾—を補足ã™ã‚‹ã‚‚ã®ã§ã™ã€‚ + + 1: 妥当ãªCONFIGオプションや変更ã•ã‚ŒãŸCONFIGオプションã€ã¤ã¾ã‚Š =y, =m, =n + å…¨ã¦ã§æ£ã—ãビルドã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。ãã®éš›ã€gccåŠã³ãƒªãƒ³ã‚«ãŒ + warningã‚„errorを出ã—ã¦ã„ãªã„ã“ã¨ã‚‚確èªã—ã¦ãã ã•ã„。 + + 2: allnoconfig, allmodconfig オプションを用ã„ã¦æ£ã—ãビルドã§ãã‚‹ã“ã¨ã‚’ + 確èªã—ã¦ãã ã•ã„。 + + 3: 手許ã®ã‚¯ãƒã‚¹ã‚³ãƒ³ãƒ‘イルツールやOSDLã®PLMã®ã‚ˆã†ãªã‚‚ã®ã‚’用ã„ã¦ã€è¤‡æ•°ã® + アーã‚テクãƒãƒ£ã«ãŠã„ã¦ã‚‚æ£ã—ãビルドã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 + + 4: 64bité•·ã®'unsigned long'を使用ã—ã¦ã„ã‚‹ppc64ã¯ã€ã‚¯ãƒã‚¹ã‚³ãƒ³ãƒ‘イルã§ã® + ãƒã‚§ãƒƒã‚¯ã«é©å½“ãªã‚¢ãƒ¼ã‚テクãƒãƒ£ã§ã™ã€‚ + + 5: カーãƒãƒ«ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¹ã‚¿ã‚¤ãƒ«ã«æº–æ‹ ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ç¢ºèªã—ã¦ãã ã•ã„(!) + + 6: CONFIGオプションã®è¿½åŠ ・変更をã—ãŸå ´åˆã«ã¯ã€CONFIGメニューãŒå£Šã‚Œã¦ã„ãªã„ + ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 + + 7: æ–°ã—ãKconfigã®ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã‚’è¿½åŠ ã™ã‚‹éš›ã«ã¯ã€å¿…ãšãã®helpも記述ã—ã¦ãã ã•ã„。 + + 8: é©åˆ‡ãªKconfigã®ä¾å˜é–¢ä¿‚を考ãˆãªãŒã‚‰æ…Žé‡ã«ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。 + ãŸã ã—ã€ã“ã®ä½œæ¥ã¯ãƒžã‚·ãƒ³ã‚’使ã£ãŸãƒ†ã‚¹ãƒˆã§ãã¡ã‚“ã¨è¡Œã†ã®ãŒã¨ã¦ã‚‚困難ã§ã™ã€‚ + ã†ã¾ãã‚„ã‚‹ã«ã¯ã€è‡ªåˆ†ã®é ã§è€ƒãˆã‚‹ã“ã¨ã§ã™ã€‚ + + 9: sparseを利用ã—ã¦ã¡ã‚ƒã‚“ã¨ã—ãŸã‚³ãƒ¼ãƒ‰ãƒã‚§ãƒƒã‚¯ã‚’ã—ã¦ãã ã•ã„。 + +10: 'make checkstack' 㨠'make namespacecheck' を利用ã—ã€å•é¡ŒãŒç™ºè¦‹ã•ã‚ŒãŸã‚‰ + ä¿®æ£ã—ã¦ãã ã•ã„。'make checkstack' ã¯æ˜Žç¤ºçš„ã«å•é¡Œã‚’示ã—ã¾ã›ã‚“ãŒã€ã©ã‚Œã‹ + 1ã¤ã®é–¢æ•°ãŒ512ãƒã‚¤ãƒˆã‚ˆã‚Šå¤§ãã„スタックを使ã£ã¦ã„ã‚Œã°ã€ä¿®æ£ã™ã¹ã候補㨠+ ãªã‚Šã¾ã™ã€‚ + +11: ã‚°ãƒãƒ¼ãƒãƒ«ãªkernel API を説明ã™ã‚‹ kernel-doc をソースã®ä¸ã«å«ã‚ã¦ãã ã•ã„。 + ( staticãªé–¢æ•°ã«ãŠã„ã¦ã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€å«ã‚ã¦ã‚‚らã£ã¦ã‚‚çµæ§‹ã§ã™ ) + ãã—ã¦ã€'make htmldocs' ã‚‚ã—ã㯠'make mandocs' を利用ã—ã¦è¿½è¨˜ã—㟠+ ドã‚ュメントã®ãƒã‚§ãƒƒã‚¯ã‚’è¡Œã„ã€å•é¡ŒãŒè¦‹ã¤ã‹ã£ãŸå ´åˆã«ã¯ä¿®æ£ã‚’è¡Œã£ã¦ãã ã•ã„。 + +12: CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB, + CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK, + CONFIG_DEBUG_SPINLOCK_SLEEP ã“れら全ã¦ã‚’åŒæ™‚ã«æœ‰åŠ¹ã«ã—ã¦å‹•ä½œç¢ºèªã‚’ + è¡Œã£ã¦ãã ã•ã„。 + +13: CONFIG_SMP, CONFIG_PREEMPT を有効ã«ã—ãŸå ´åˆã¨ç„¡åŠ¹ã«ã—ãŸå ´åˆã®ä¸¡æ–¹ã§ + ビルドã—ãŸä¸Šã€å‹•ä½œç¢ºèªã‚’è¡Œã£ã¦ãã ã•ã„。 + +14: ã‚‚ã—パッãƒãŒãƒ‡ã‚£ã‚¹ã‚¯ã®I/O性能ãªã©ã«å½±éŸ¿ã‚’与ãˆã‚‹ã‚ˆã†ã§ã‚ã‚Œã°ã€ + 'CONFIG_LBD'オプションを有効ã«ã—ãŸå ´åˆã¨ç„¡åŠ¹ã«ã—ãŸå ´åˆã®ä¸¡æ–¹ã§ + テストを実施ã—ã¦ã¿ã¦ãã ã•ã„。 + +15: lockdepã®æ©Ÿèƒ½ã‚’å…¨ã¦æœ‰åŠ¹ã«ã—ãŸä¸Šã§ã€å…¨ã¦ã®ã‚³ãƒ¼ãƒ‰ãƒ‘スを評価ã—ã¦ãã ã•ã„。 + +16: /proc ã«æ–°ã—ã„ã‚¨ãƒ³ãƒˆãƒªã‚’è¿½åŠ ã—ãŸå ´åˆã«ã¯ã€Documentation/ é…下㫠+ å¿…ãšãƒ‰ã‚ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 + +17: æ–°ã—ã„ãƒ–ãƒ¼ãƒˆãƒ‘ãƒ©ãƒ¡ãƒ¼ã‚¿ã‚’è¿½åŠ ã—ãŸå ´åˆã«ã¯ã€ + å¿…ãšDocumentation/kernel-parameters.txt ã«èª¬æ˜Žã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 + +18: æ–°ã—ãmoduleã«ãƒ‘ãƒ©ãƒ¡ãƒ¼ã‚¿ã‚’è¿½åŠ ã—ãŸå ´åˆã«ã¯ã€MODULE_PARM_DESC()ã‚’ + 利用ã—ã¦å¿…ãšãã®èª¬æ˜Žã‚’記述ã—ã¦ãã ã•ã„。 + +19: æ–°ã—ã„userspaceインタフェースを作æˆã—ãŸå ´åˆã«ã¯ã€Documentation/ABI/ ã« + Documentation/ABI/README ã‚’å‚考ã«ã—ã¦å¿…ãšãƒ‰ã‚ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’è¿½åŠ ã—ã¦ãã ã•ã„。 + +20: 'make headers_check'を実行ã—ã¦å…¨ãå•é¡ŒãŒãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 + +21: å°‘ãªãã¨ã‚‚slabã‚¢ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã¨pageã‚¢ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã«å¤±æ•—ã—ãŸå ´åˆã® + 挙動ã«ã¤ã„ã¦ã€fault-injectionを利用ã—ã¦ç¢ºèªã—ã¦ãã ã•ã„。 + Documentation/fault-injection/ ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + + è¿½åŠ ã—ãŸã‚³ãƒ¼ãƒ‰ãŒã‹ãªã‚Šã®é‡ã§ã‚ã£ãŸãªã‚‰ã°ã€ã‚µãƒ–システム特有㮠+ fault-injectionã‚’è¿½åŠ ã—ãŸã»ã†ãŒè‰¯ã„ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。 + +22: æ–°ãŸã«è¿½åŠ ã—ãŸã‚³ãƒ¼ãƒ‰ã¯ã€`gcc -W'ã§ã‚³ãƒ³ãƒ‘イルã—ã¦ãã ã•ã„。 + ã“ã®ã‚ªãƒ—ションã¯å¤§é‡ã®ä¸è¦ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’出力ã—ã¾ã™ãŒã€ + "warning: comparison between signed and unsigned" ã®ã‚ˆã†ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯ã€ + ãƒã‚°ã‚’見ã¤ã‘ã‚‹ã®ã«å½¹ã«ç«‹ã¡ã¾ã™ã€‚ + +23: 投稿ã—ãŸãƒ‘ッãƒãŒ -mm パッãƒã‚»ãƒƒãƒˆã«ãƒžãƒ¼ã‚¸ã•ã‚ŒãŸå¾Œã€å…¨ã¦ã®æ—¢å˜ã®ãƒ‘ッãƒã‚„ + VM, VFS ãŠã‚ˆã³ãã®ä»–ã®ã‚µãƒ–システムã«é–¢ã™ã‚‹æ§˜ã€…ãªå¤‰æ›´ã¨ã€ç¾æ™‚点ã§ã‚‚å…±å˜ + ã§ãã‚‹ã“ã¨ã‚’確èªã™ã‚‹ãƒ†ã‚¹ãƒˆã‚’è¡Œã£ã¦ãã ã•ã„。 diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e7bea3e..1150444 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -365,6 +365,8 @@ and is between 256 and 4096 characters. It is defined in the file no delay (0). Format: integer + bootmem_debug [KNL] Enable bootmem allocator debug messages. + bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards) bttv.radio= Most important insmod options are available as kernel args too. @@ -1072,6 +1074,9 @@ and is between 256 and 4096 characters. It is defined in the file * [no]ncq: Turn on or off NCQ. + * nohrst, nosrst, norst: suppress hard, soft + and both resets. + If there are multiple matching configurations changing the same attribute, the last one is used. diff --git a/Documentation/rfkill.txt b/Documentation/rfkill.txt index 28b6ec8..6fcb306 100644 --- a/Documentation/rfkill.txt +++ b/Documentation/rfkill.txt @@ -363,6 +363,11 @@ This rule exists because users of the rfkill subsystem expect to get (and set, when possible) the overall transmitter rfkill state, not of a particular rfkill line. +5. During suspend, the rfkill class will attempt to soft-block the radio +through a call to rfkill->toggle_radio, and will try to restore its previous +state during resume. After a rfkill class is suspended, it will *not* call +rfkill->toggle_radio until it is resumed. + Example of a WLAN wireless driver connected to the rfkill subsystem: -------------------------------------------------------------------- diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 716fcc1..c851ef4 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -1,3 +1,26 @@ + +1 Release Date : Thur.July. 24 11:41:51 PST 2008 - + (emaild-id:megaraidlinux@lsi.com) + Sumant Patro + Bo Yang + +2 Current Version : 00.00.04.01 +3 Older Version : 00.00.03.22 + +1. Add the new controller (0078, 0079) support to the driver + Those controllers are LSI's next generatation(gen2) SAS controllers. + +1 Release Date : Mon.June. 23 10:12:45 PST 2008 - + (emaild-id:megaraidlinux@lsi.com) + Sumant Patro + Bo Yang + +2 Current Version : 00.00.03.22 +3 Older Version : 00.00.03.20 + +1. Add shutdown DCMD cmd to the shutdown routine to make FW shutdown proper. +2. Unexpected interrupt occurs in HWR Linux driver, add the dumy readl pci flush will fix this issue. + 1 Release Date : Mon. March 10 11:02:31 PDT 2008 - (emaild-id:megaraidlinux@lsi.com) Sumant Patro diff --git a/MAINTAINERS b/MAINTAINERS index 663485b..28c69aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -942,94 +942,19 @@ M: joern@lazybastard.org L: linux-mtd@lists.infradead.org S: Maintained -BLUETOOTH SUBSYSTEM +BLUETOOTH DRIVERS P: Marcel Holtmann M: marcel@holtmann.org -P: Maxim Krasnyansky -M: maxk@qualcomm.com L: linux-bluetooth@vger.kernel.org -W: http://bluez.sf.net -W: http://www.bluez.org -W: http://www.holtmann.org/linux/bluetooth/ -T: git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git -S: Maintained - -BLUETOOTH RFCOMM LAYER -P: Marcel Holtmann -M: marcel@holtmann.org -P: Maxim Krasnyansky -M: maxk@qualcomm.com -S: Maintained - -BLUETOOTH BNEP LAYER -P: Marcel Holtmann -M: marcel@holtmann.org -P: Maxim Krasnyansky -M: maxk@qualcomm.com -S: Maintained - -BLUETOOTH CMTP LAYER -P: Marcel Holtmann -M: marcel@holtmann.org +W: http://www.bluez.org/ S: Maintained -BLUETOOTH HIDP LAYER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI UART DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -P: Maxim Krasnyansky -M: maxk@qualcomm.com -S: Maintained - -BLUETOOTH HCI USB DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -P: Maxim Krasnyansky -M: maxk@qualcomm.com -S: Maintained - -BLUETOOTH HCI BCM203X DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI BPA10X DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI BFUSB DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI DTL1 DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI BLUECARD DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI BT3C DRIVER -P: Marcel Holtmann -M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI BTUART DRIVER +BLUETOOTH SUBSYSTEM P: Marcel Holtmann M: marcel@holtmann.org -S: Maintained - -BLUETOOTH HCI VHCI DRIVER -P: Maxim Krasnyansky -M: maxk@qualcomm.com +L: linux-bluetooth@vger.kernel.org +W: http://www.bluez.org/ +T: git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git S: Maintained BONDING DRIVER @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Rotary Wombat # *DOCUMENTATION* diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 0a7b326..3c8383d 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -405,7 +405,7 @@ static int impd1_probe(struct lm_device *dev) ret = amba_device_register(d, &dev->resource); if (ret) { - dev_err(&d->dev, "unable to register device: %d\n"); + dev_err(&d->dev, "unable to register device: %d\n", ret); kfree(d); } } diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c index 0db3a90..501dfdc 100644 --- a/arch/arm/mach-ixp4xx/fsg-setup.c +++ b/arch/arm/mach-ixp4xx/fsg-setup.c @@ -64,7 +64,7 @@ static struct platform_device fsg_i2c_gpio = { static struct i2c_board_info __initdata fsg_i2c_board_info [] = { { - I2C_BOARD_INFO("rtc-isl1208", 0x6f), + I2C_BOARD_INFO("isl1208", 0x6f), }, }; @@ -179,7 +179,6 @@ static void __init fsg_init(void) { DECLARE_MAC_BUF(mac_buf); uint8_t __iomem *f; - int i; ixp4xx_sys_init(); @@ -228,6 +227,7 @@ static void __init fsg_init(void) f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x400000); if (f) { #ifdef __ARMEB__ + int i; for (i = 0; i < 6; i++) { fsg_plat_eth[0].hwaddr[i] = readb(f + 0x3C0422 + i); fsg_plat_eth[1].hwaddr[i] = readb(f + 0x3C043B + i); diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index c01eea8..ca8e205 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -125,3 +125,28 @@ void clks_register(struct clk *clks, size_t num) list_add(&clks[i].node, &clocks); mutex_unlock(&clocks_mutex); } + +int clk_add_alias(char *alias, struct device *alias_dev, char *id, + struct device *dev) +{ + struct clk *r = clk_lookup(dev, id); + struct clk *new; + + if (!r) + return -ENODEV; + + new = kzalloc(sizeof(struct clk), GFP_KERNEL); + + if (!new) + return -ENOMEM; + + new->name = alias; + new->dev = alias_dev; + new->other = r; + + mutex_lock(&clocks_mutex); + list_add(&new->node, &clocks); + mutex_unlock(&clocks_mutex); + + return 0; +} diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index 1ec8f91..73be795 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h @@ -1,3 +1,5 @@ +#include <linux/list.h> + struct clk; struct clkops { @@ -86,3 +88,6 @@ extern void clk_pxa3xx_cken_disable(struct clk *); #endif void clks_register(struct clk *clks, size_t num); +int clk_add_alias(char *alias, struct device *alias_dev, char *id, + struct device *dev); + diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index 0394245..001a252 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -10,18 +10,78 @@ * */ +#include <linux/kernel.h> #include <linux/init.h> #include <asm/setup.h> #include <asm/mach/arch.h> -#include <mach/hardware.h> #include <asm/mach-types.h> +#include <mach/mfp-pxa25x.h> +#include <mach/hardware.h> + #include "generic.h" +static unsigned long e740_pin_config[] __initdata = { + /* Chip selects */ + GPIO15_nCS_1, /* CS1 - Flash */ + GPIO79_nCS_3, /* CS3 - IMAGEON */ + GPIO80_nCS_4, /* CS4 - TMIO */ + + /* Clocks */ + GPIO12_32KHz, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* PC Card */ + GPIO8_GPIO, /* CD0 */ + GPIO44_GPIO, /* CD1 */ + GPIO11_GPIO, /* IRQ0 */ + GPIO6_GPIO, /* IRQ1 */ + GPIO27_GPIO, /* RST0 */ + GPIO24_GPIO, /* RST1 */ + GPIO20_GPIO, /* PWR0 */ + GPIO23_GPIO, /* PWR1 */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO52_nPCE_1, + GPIO53_nPCE_2, + GPIO54_nPSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + + /* wakeup */ + GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, +}; + +static unsigned long e400_pin_config[] __initdata = { + /* Chip selects */ + GPIO15_nCS_1, /* CS1 - Flash */ + GPIO80_nCS_4, /* CS4 - TMIO */ + + /* Clocks */ + GPIO12_32KHz, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_GPIO, /* Used by TMIO for #SUSPEND */ + + /* wakeup */ + GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, +}; + /* Only e800 has 128MB RAM */ static void __init eseries_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) + struct tag *tags, char **cmdline, struct meminfo *mi) { mi->nr_banks=1; mi->bank[0].start = 0xa0000000; @@ -32,83 +92,95 @@ static void __init eseries_fixup(struct machine_desc *desc, mi->bank[0].size = (64*1024*1024); } +static void __init e740_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config)); +} + +static void __init e400_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(e400_pin_config)); +} + /* e-series machine definitions */ #ifdef CONFIG_MACH_E330 MACHINE_START(E330, "Toshiba e330") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, MACHINE_END #endif #ifdef CONFIG_MACH_E350 MACHINE_START(E350, "Toshiba e350") /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, MACHINE_END #endif #ifdef CONFIG_MACH_E740 MACHINE_START(E740, "Toshiba e740") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .init_machine = e740_init, + .timer = &pxa_timer, MACHINE_END #endif #ifdef CONFIG_MACH_E750 MACHINE_START(E750, "Toshiba e750") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, MACHINE_END #endif #ifdef CONFIG_MACH_E400 MACHINE_START(E400, "Toshiba e400") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .init_machine = e400_init, + .timer = &pxa_timer, MACHINE_END #endif #ifdef CONFIG_MACH_E800 MACHINE_START(E800, "Toshiba e800") - /* Maintainer: Ian Molton (spyro@f2s.com) */ - .phys_io = 0x40000000, - .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, - .boot_params = 0xa0000100, - .map_io = pxa_map_io, - .init_irq = pxa25x_init_irq, - .fixup = eseries_fixup, - .timer = &pxa_timer, + /* Maintainer: Ian Molton (spyro@f2s.com) */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa25x_init_irq, + .fixup = eseries_fixup, + .timer = &pxa_timer, MACHINE_END #endif diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index 32772bc..108b5db 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -183,6 +183,7 @@ defined(CONFIG_MACH_TOSA) || \ defined(CONFIG_MACH_MAINSTONE) || \ defined(CONFIG_MACH_PCM027) || \ + defined(CONFIG_ARCH_PXA_ESERIES) || \ defined(CONFIG_MACH_MAGICIAN) #define NR_IRQS (IRQ_BOARD_END) #elif defined(CONFIG_MACH_ZYLONITE) diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index bb9e092..4ffdff2 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -52,6 +52,7 @@ #include <mach/mmc.h> #include "generic.h" +#include "clock.h" #include "devices.h" static unsigned long lubbock_pin_config[] __initdata = { @@ -485,6 +486,7 @@ static void __init lubbock_init(void) pxa2xx_mfp_config(ARRAY_AND_SIZE(lubbock_pin_config)); + clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL); pxa_set_udc_info(&udc_info); set_pxa_fb_info(&sharp_lm8v31); pxa_set_mci_info(&lubbock_mci_platform_data); diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 9e5d8a8..305452b 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -166,8 +166,7 @@ static struct clk pxa25x_hwuart_clk = ; /* - * PXA 2xx clock declarations. Order is important (see aliases below) - * Please be careful not to disrupt the ordering. + * PXA 2xx clock declarations. */ static struct clk pxa25x_clks[] = { INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev), @@ -194,11 +193,6 @@ static struct clk pxa25x_clks[] = { INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), }; -static struct clk pxa2xx_clk_aliases[] = { - INIT_CKOTHER("GPIO7_CLK", &pxa25x_clks[4], NULL), - INIT_CKOTHER("SA1111_CLK", &pxa25x_clks[5], NULL), -}; - #ifdef CONFIG_PM #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x @@ -375,8 +369,6 @@ static int __init pxa25x_init(void) if (cpu_is_pxa255()) ret = platform_device_register(&pxa_device_hwuart); - clks_register(pxa2xx_clk_aliases, ARRAY_SIZE(pxa2xx_clk_aliases)); - return ret; } diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 494fc1f..9adc7fc 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -90,7 +90,9 @@ static struct clk common_clks[] = { }; static struct clk pxa310_clks[] = { +#ifdef CONFIG_CPU_PXA310 PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev), +#endif }; static int __init pxa300_init(void) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 23a0705..197974d 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -10,7 +10,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c index 2de9d58..111caa1 100644 --- a/arch/cris/arch-v32/kernel/fasttimer.c +++ b/arch/cris/arch-v32/kernel/fasttimer.c @@ -19,8 +19,6 @@ #include <asm/irq.h> #include <asm/system.h> -#include <linux/version.h> - #include <hwregs/reg_map.h> #include <hwregs/reg_rdwr.h> #include <hwregs/timer_defs.h> diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index 8b054e7..aa07d0c 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c @@ -17,7 +17,6 @@ static const char serial_revdate[] = "2007-11-06"; #define SUPPORT_SYSRQ #endif -#include <linux/version.h> #include <linux/module.h> #include <linux/serial.h> #include <linux/circ_buf.h> diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index e0debcc..a323c9b 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -86,6 +86,19 @@ static int __init parse_savemaxmem(char *p) } __setup("savemaxmem=", parse_savemaxmem); + +static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize, + unsigned long offset, int userbuf) +{ + if (userbuf) { + if (copy_to_user((char __user *)buf, (vaddr + offset), csize)) + return -EFAULT; + } else + memcpy(buf, (vaddr + offset), csize); + + return csize; +} + /** * copy_oldmem_page - copy one page from "oldmem" * @pfn: page frame number to be copied @@ -107,16 +120,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, if (!csize) return 0; - vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0); + csize = min(csize, PAGE_SIZE); - if (userbuf) { - if (copy_to_user((char __user *)buf, (vaddr + offset), csize)) { - iounmap(vaddr); - return -EFAULT; - } - } else - memcpy(buf, (vaddr + offset), csize); + if (pfn < max_pfn) { + vaddr = __va(pfn << PAGE_SHIFT); + csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); + } else { + vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0); + csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); + iounmap(vaddr); + } - iounmap(vaddr); return csize; } diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 9d42eb5..a063622 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -233,17 +233,6 @@ void ibmebus_free_irq(u32 ist, void *dev_id) } EXPORT_SYMBOL(ibmebus_free_irq); -static ssize_t name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", to_of_device(dev)->node->name); -} - -static struct device_attribute ibmebus_dev_attrs[] = { - __ATTR_RO(name), - __ATTR_NULL -}; - static char *ibmebus_chomp(const char *in, size_t count) { char *out = kmalloc(count + 1, GFP_KERNEL); @@ -327,7 +316,6 @@ static struct bus_attribute ibmebus_bus_attrs[] = { struct bus_type ibmebus_bus_type = { .uevent = of_device_uevent, - .dev_attrs = ibmebus_dev_attrs, .bus_attrs = ibmebus_bus_attrs }; EXPORT_SYMBOL(ibmebus_bus_type); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 22a3c33..2750fba 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1113,7 +1113,7 @@ static int vio_bus_probe(struct device *dev) return error; } error = viodrv->probe(viodev, id); - if (error) + if (error && firmware_has_feature(FW_FEATURE_CMO)) vio_cmo_bus_remove(viodev); } diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index f7edba6..c9bb7cf 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -206,11 +206,6 @@ static int spu_run_init(struct spu_context *ctx, u32 *npc) (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); if (runcntl == 0) runcntl = SPU_RUNCNTL_RUNNABLE; - } - - if (ctx->flags & SPU_CREATE_NOSCHED) { - spuctx_switch_state(ctx, SPU_UTIL_USER); - ctx->ops->runcntl_write(ctx, runcntl); } else { unsigned long privcntl; @@ -219,9 +214,15 @@ static int spu_run_init(struct spu_context *ctx, u32 *npc) else privcntl = SPU_PRIVCNTL_MODE_NORMAL; - ctx->ops->npc_write(ctx, *npc); ctx->ops->privcntl_write(ctx, privcntl); - ctx->ops->runcntl_write(ctx, runcntl); + ctx->ops->npc_write(ctx, *npc); + } + + ctx->ops->runcntl_write(ctx, runcntl); + + if (ctx->flags & SPU_CREATE_NOSCHED) { + spuctx_switch_state(ctx, SPU_UTIL_USER); + } else { if (ctx->state == SPU_STATE_SAVED) { ret = spu_activate(ctx, 0); diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 2deeeba..1c1b627 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -641,8 +641,10 @@ static struct spu *find_victim(struct spu_context *ctx) if (tmp && tmp->prio > ctx->prio && !(tmp->flags & SPU_CREATE_NOSCHED) && - (!victim || tmp->prio > victim->prio)) + (!victim || tmp->prio > victim->prio)) { victim = spu->ctx; + get_spu_context(victim); + } } mutex_unlock(&cbe_spu_info[node].list_mutex); @@ -658,6 +660,7 @@ static struct spu *find_victim(struct spu_context *ctx) * look at another context or give up after X retries. */ if (!mutex_trylock(&victim->state_mutex)) { + put_spu_context(victim); victim = NULL; goto restart; } @@ -670,6 +673,7 @@ static struct spu *find_victim(struct spu_context *ctx) * restart the search. */ mutex_unlock(&victim->state_mutex); + put_spu_context(victim); victim = NULL; goto restart; } @@ -687,6 +691,7 @@ static struct spu *find_victim(struct spu_context *ctx) spu_add_to_rq(victim); mutex_unlock(&victim->state_mutex); + put_spu_context(victim); return spu; } @@ -985,9 +990,11 @@ static int spusched_thread(void *unused) struct spu_context *ctx = spu->ctx; if (ctx) { + get_spu_context(ctx); mutex_unlock(mtx); spusched_tick(ctx); mutex_lock(mtx); + put_spu_context(ctx); } } mutex_unlock(mtx); @@ -1030,7 +1037,7 @@ void spuctx_switch_state(struct spu_context *ctx, node = spu->node; if (old_state == SPU_UTIL_USER) atomic_dec(&cbe_spu_info[node].busy_spus); - if (new_state == SPU_UTIL_USER); + if (new_state == SPU_UTIL_USER) atomic_inc(&cbe_spu_info[node].busy_spus); } } diff --git a/arch/powerpc/sysdev/bestcomm/gen_bd.c b/arch/powerpc/sysdev/bestcomm/gen_bd.c index a3a134c..e0a53e3 100644 --- a/arch/powerpc/sysdev/bestcomm/gen_bd.c +++ b/arch/powerpc/sysdev/bestcomm/gen_bd.c @@ -11,7 +11,6 @@ * */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> diff --git a/arch/s390/defconfig b/arch/s390/defconfig index c5cdb97..9b0bc2c 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Fri May 30 09:49:33 2008 +# Linux kernel version: 2.6.27-rc4 +# Thu Aug 21 19:43:29 2008 # CONFIG_SCHED_MC=y CONFIG_MMU=y @@ -68,7 +68,6 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -93,11 +92,17 @@ CONFIG_SLAB=y # CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set CONFIG_KRETPROBES=y +# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +# CONFIG_HAVE_CLK is not set CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -113,6 +118,7 @@ CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set CONFIG_BLOCK_COMPAT=y # @@ -175,6 +181,8 @@ CONFIG_PREEMPT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -185,8 +193,12 @@ CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTPLUG_SPARSE=y +CONFIG_MEMORY_HOTREMOVE=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y @@ -198,6 +210,7 @@ CONFIG_VIRT_TO_BUS=y CONFIG_MACHCHK_WARNING=y CONFIG_QDIO=y # CONFIG_QDIO_DEBUG is not set +CONFIG_CHSC_SCH=m # # Misc @@ -206,6 +219,7 @@ CONFIG_IPL=y # CONFIG_IPL_TAPE is not set CONFIG_IPL_VM=y CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=9 # CONFIG_PROCESS_DEBUG is not set @@ -226,10 +240,6 @@ CONFIG_S390_HYPFS_FS=y CONFIG_KEXEC=y # CONFIG_ZFCPDUMP is not set CONFIG_S390_GUEST=y - -# -# Networking -# CONFIG_NET=y # @@ -364,7 +374,6 @@ CONFIG_NET_SCH_CBQ=m # CONFIG_NET_SCH_HTB is not set # CONFIG_NET_SCH_HFSC is not set CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RR=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m @@ -430,7 +439,9 @@ CONFIG_CCW=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set CONFIG_SYS_HYPERVISOR=y @@ -507,6 +518,11 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y +CONFIG_SCSI_DH=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=m @@ -522,14 +538,10 @@ CONFIG_DM_CRYPT=y CONFIG_DM_SNAPSHOT=y CONFIG_DM_MIRROR=y CONFIG_DM_ZERO=y -CONFIG_DM_MULTIPATH=y -# CONFIG_DM_MULTIPATH_EMC is not set -# CONFIG_DM_MULTIPATH_RDAC is not set -# CONFIG_DM_MULTIPATH_HP is not set +CONFIG_DM_MULTIPATH=m # CONFIG_DM_DELAY is not set # CONFIG_DM_UEVENT is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_IFB is not set CONFIG_DUMMY=m CONFIG_BONDING=m @@ -544,7 +556,6 @@ CONFIG_NET_ETHERNET=y # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NETDEV_1000=y -# CONFIG_E1000E_ENABLED is not set CONFIG_NETDEV_10000=y # CONFIG_TR is not set # CONFIG_WAN is not set @@ -576,7 +587,10 @@ CONFIG_DEVKMEM=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_HVC_DRIVER=y +CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM=m +CONFIG_HW_RANDOM_VIRTIO=m # CONFIG_R3964 is not set CONFIG_RAW_DRIVER=m CONFIG_MAX_RAW_DEVS=256 @@ -616,6 +630,7 @@ CONFIG_MONWRITER=m CONFIG_S390_VMUR=m # CONFIG_POWER_SUPPLY is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -693,6 +708,7 @@ CONFIG_CONFIGFS_FS=m # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -712,7 +728,6 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -780,6 +795,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_FRAME_POINTER is not set @@ -789,6 +805,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_SAMPLES=y # CONFIG_SAMPLE_KOBJECT is not set # CONFIG_SAMPLE_KPROBES is not set @@ -847,6 +864,10 @@ CONFIG_CRYPTO_HMAC=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -895,6 +916,7 @@ CONFIG_BITREVERSE=m # CONFIG_GENERIC_FIND_NEXT_BIT is not set # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=m CONFIG_CRC7=m diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index b4eb24a..8e9243a 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -709,7 +709,7 @@ static inline int find_next_zero_bit (const unsigned long * addr, * __ffz_word returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = __ffz_word(0, *p >> bit) + bit; + set = __ffz_word(bit, *p >> bit); if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) @@ -824,7 +824,7 @@ static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, * s390 version of ffz returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = ffz(__load_ulong_le(p, 0) >> bit) + bit; + set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit); if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) @@ -865,7 +865,7 @@ static inline int ext2_find_next_bit(void *vaddr, unsigned long size, * s390 version of ffz returns __BITOPS_WORDSIZE * if no zero bit is present in the word. */ - set = ffs(__load_ulong_le(p, 0) >> bit) + bit; + set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit)); if (set >= size) return size + offset; if (set < __BITOPS_WORDSIZE) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 9839767..3e2c05c 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -75,7 +75,9 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return sf->gprs[8]; } -DEFINE_PER_CPU(struct s390_idle_data, s390_idle); +DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { + .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) +}; static int s390_idle_enter(void) { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b795b3e..00b9b4d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -610,7 +610,6 @@ static void __init smp_create_idle(unsigned int cpu) if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); current_set[cpu] = p; - spin_lock_init(&(&per_cpu(s390_idle, cpu))->lock); } static int __cpuinit smp_alloc_lowcore(int cpu) @@ -845,7 +844,6 @@ void __init smp_prepare_boot_cpu(void) current_set[0] = current; smp_cpu_state[0] = CPU_STATE_CONFIGURED; smp_cpu_polarization[0] = POLARIZATION_UNKNWN; - spin_lock_init(&(&__get_cpu_var(s390_idle))->lock); } void __init smp_cpus_done(unsigned int max_cpus) diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 025d4fe..fd16125 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -140,6 +140,10 @@ static struct sh_mobile_lcdc_info lcdc_info = { .vsync_len = 1, .sync = 0, /* hsync and vsync are active low */ }, + .lcd_size_cfg = { /* 7.0 inch */ + .width = 152, + .height = 91, + }, .board_cfg = { .display_on = ap320_wvga_power_on, }, diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index e499ee3..714dce9 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -224,6 +224,10 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { .vsync_len = 2, .sync = 0, }, + .lcd_size_cfg = { /* 7.0 inch */ + .width = 152, + .height = 91, + }, } #endif #ifdef CONFIG_SH_MIGOR_QVGA @@ -245,6 +249,10 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { .vsync_len = 2, .sync = FB_SYNC_HOR_HIGH_ACT, }, + .lcd_size_cfg = { /* 2.4 inch */ + .width = 49, + .height = 37, + }, .board_cfg = { .setup_sys = migor_lcd_qvga_setup, }, diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c index 925f16a..23850da 100644 --- a/arch/sh/boards/mach-sh7763rdp/setup.c +++ b/arch/sh/boards/mach-sh7763rdp/setup.c @@ -15,8 +15,11 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/mtd/physmap.h> -#include <asm/io.h> +#include <linux/fb.h> +#include <linux/io.h> #include <asm/sh7763rdp.h> +#include <asm/sh_eth.h> +#include <asm/sh7760fb.h> /* NOR Flash */ static struct mtd_partition sh7763rdp_nor_flash_partitions[] = { @@ -60,8 +63,85 @@ static struct platform_device sh7763rdp_nor_flash_device = { }, }; +/* SH-Ether */ +static struct resource sh_eth_resources[] = { + { + .start = 0xFEE00800, /* use eth1 */ + .end = 0xFEE00F7C - 1, + .flags = IORESOURCE_MEM, + }, { + .start = 58, /* irq number */ + .end = 58, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sh_eth_plat_data sh7763_eth_pdata = { + .phy = 1, + .edmac_endian = EDMAC_LITTLE_ENDIAN, +}; + +static struct platform_device sh7763rdp_eth_device = { + .name = "sh-eth", + .resource = sh_eth_resources, + .num_resources = ARRAY_SIZE(sh_eth_resources), + .dev = { + .platform_data = &sh7763_eth_pdata, + }, +}; + +/* SH7763 LCDC */ +static struct resource sh7763rdp_fb_resources[] = { + { + .start = 0xFFE80000, + .end = 0xFFE80442 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct fb_videomode sh7763fb_videomode = { + .refresh = 60, + .name = "VGA Monitor", + .xres = 640, + .yres = 480, + .pixclock = 10000, + .left_margin = 80, + .right_margin = 24, + .upper_margin = 30, + .lower_margin = 1, + .hsync_len = 96, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = FBINFO_FLAG_DEFAULT, +}; + +static struct sh7760fb_platdata sh7763fb_def_pdata = { + .def_mode = &sh7763fb_videomode, + .ldmtr = (LDMTR_TFT_COLOR_16|LDMTR_MCNT), + .lddfr = LDDFR_16BPP_RGB565, + .ldpmmr = 0x0000, + .ldpspr = 0xFFFF, + .ldaclnr = 0x0001, + .ldickr = 0x1102, + .rotate = 0, + .novsync = 0, + .blank = NULL, +}; + +static struct platform_device sh7763rdp_fb_device = { + .name = "sh7760-lcdc", + .resource = sh7763rdp_fb_resources, + .num_resources = ARRAY_SIZE(sh7763rdp_fb_resources), + .dev = { + .platform_data = &sh7763fb_def_pdata, + }, +}; + static struct platform_device *sh7763rdp_devices[] __initdata = { &sh7763rdp_nor_flash_device, + &sh7763rdp_eth_device, + &sh7763rdp_fb_device, }; static int __init sh7763rdp_devices_setup(void) @@ -69,7 +149,7 @@ static int __init sh7763rdp_devices_setup(void) return platform_add_devices(sh7763rdp_devices, ARRAY_SIZE(sh7763rdp_devices)); } -__initcall(sh7763rdp_devices_setup); +device_initcall(sh7763rdp_devices_setup); static void __init sh7763rdp_setup(char **cmdline_p) { diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c index abc5b6d..a70d23b 100644 --- a/arch/sh/boards/mach-x3proto/setup.c +++ b/arch/sh/boards/mach-x3proto/setup.c @@ -3,7 +3,7 @@ * * Renesas SH-X3 Prototype Board Support. * - * Copyright (C) 2007 Paul Mundt + * Copyright (C) 2007 - 2008 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -13,6 +13,7 @@ #include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/io.h> +#include <linux/smc91x.h> #include <asm/ilsel.h> static struct resource heartbeat_resources[] = { @@ -30,6 +31,10 @@ static struct platform_device heartbeat_device = { .resource = heartbeat_resources, }; +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, +}; + static struct resource smc91x_resources[] = { [0] = { .start = 0x18000300, @@ -47,6 +52,9 @@ static struct platform_device smc91x_device = { .id = -1, .resource = smc91x_resources, .num_resources = ARRAY_SIZE(smc91x_resources), + .dev = { + .platform_data = &smc91x_info, + }, }; static struct resource r8a66597_usb_host_resources[] = { diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig index 83f3fe5..baf830c 100644 --- a/arch/sh/configs/sh7763rdp_defconfig +++ b/arch/sh/configs/sh7763rdp_defconfig @@ -1,15 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc4 -# Fri Jun 6 12:20:17 2008 +# Linux kernel version: 2.6.27-rc2 +# Fri Aug 8 13:44:20 2008 # CONFIG_SUPERH=y CONFIG_SUPERH32=y +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y @@ -19,7 +21,6 @@ CONFIG_LOCKDEP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -83,10 +84,16 @@ CONFIG_PROFILING=y # CONFIG_MARKERS is not set CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_IOREMAP_PROT is not set # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set +# CONFIG_HAVE_ARCH_TRACEHOOK is not set # CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_USE_GENERIC_SMP_HELPERS is not set +CONFIG_HAVE_CLK=y CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -96,12 +103,13 @@ CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD is not set +CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -177,6 +185,7 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set +CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -258,6 +267,7 @@ CONFIG_HZ=250 # CONFIG_SCHED_HRTICK is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set +CONFIG_SECCOMP=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -282,10 +292,6 @@ CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/sda1 rootdelay=10" # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # @@ -361,6 +367,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_CFG80211 is not set CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set # CONFIG_RFKILL is not set @@ -377,6 +384,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y @@ -471,6 +480,7 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set # CONFIG_MISC_DEVICES is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -515,10 +525,10 @@ CONFIG_SCSI_WAIT_SCAN=m CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -546,7 +556,9 @@ CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set # CONFIG_STNIC is not set +CONFIG_SH_ETH=y # CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set @@ -613,7 +625,11 @@ CONFIG_INPUT=y # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set @@ -644,6 +660,7 @@ CONFIG_HW_RANDOM=y # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set # @@ -655,6 +672,7 @@ CONFIG_SSB_POSSIBLE=y # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set @@ -679,7 +697,34 @@ CONFIG_SSB_POSSIBLE=y # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +CONFIG_FB_FOREIGN_ENDIAN=y +CONFIG_FB_BOTH_ENDIAN=y +# CONFIG_FB_BIG_ENDIAN is not set +# CONFIG_FB_LITTLE_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SH_MOBILE_LCDC is not set +CONFIG_FB_SH7760=y +# CONFIG_FB_VIRTUAL is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -688,8 +733,22 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_DISPLAY_SUPPORT is not set # -# Sound -# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_SUPERH_MONO=y +CONFIG_LOGO_SUPERH_VGA16=y +CONFIG_LOGO_SUPERH_CLUT224=y # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set CONFIG_USB_SUPPORT=y @@ -788,11 +847,27 @@ CONFIG_USB_MON=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_GADGET is not set -# CONFIG_MMC is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # @@ -865,6 +940,7 @@ CONFIG_TMPFS_POSIX_ACL=y # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set @@ -874,12 +950,11 @@ CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -949,6 +1024,7 @@ CONFIG_FRAME_WARN=1024 # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_SAMPLES is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set @@ -1003,6 +1079,10 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -1042,6 +1122,7 @@ CONFIG_BITREVERSE=y # CONFIG_GENERIC_FIND_FIRST_BIT is not set # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/sh/include/asm/flat.h b/arch/sh/include/asm/flat.h index 0cc8002..d3b2b4f 100644 --- a/arch/sh/include/asm/flat.h +++ b/arch/sh/include/asm/flat.h @@ -21,4 +21,11 @@ #define flat_get_relocate_addr(rel) (rel) #define flat_set_persistent(relval, p) ({ (void)p; 0; }) +#define FLAT_PLAT_INIT(_r) \ + do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \ + _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \ + _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ + _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \ + _r->sr = SR_FD; } while (0) + #endif /* __ASM_SH_FLAT_H */ diff --git a/arch/sh/include/asm/migor.h b/arch/sh/include/asm/migor.h index 10016e0..c12b632 100644 --- a/arch/sh/include/asm/migor.h +++ b/arch/sh/include/asm/migor.h @@ -42,9 +42,6 @@ #define PORT_MSELCRB 0xa4050182 -#define MSTPCR1 0xa4150034 -#define MSTPCR2 0xa4150038 - #define PORT_PSELA 0xa405014e #define PORT_PSELB 0xa4050150 #define PORT_PSELC 0xa4050152 diff --git a/arch/sh/include/asm/sh_mobile_lcdc.h b/arch/sh/include/asm/sh_mobile_lcdc.h index 27677727..130102f 100644 --- a/arch/sh/include/asm/sh_mobile_lcdc.h +++ b/arch/sh/include/asm/sh_mobile_lcdc.h @@ -47,12 +47,18 @@ struct sh_mobile_lcdc_board_cfg { void (*display_off)(void *board_data); }; +struct sh_mobile_lcdc_lcd_size_cfg { /* width and height of panel in mm */ + unsigned long width; + unsigned long height; +}; + struct sh_mobile_lcdc_chan_cfg { int chan; int bpp; int interface_type; /* selects RGBn or SYSn I/F, see above */ int clock_divider; struct fb_videomode lcd_cfg; + struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; struct sh_mobile_lcdc_board_cfg board_cfg; struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ }; diff --git a/arch/sh/include/cpu-sh3/cpu/cacheflush.h b/arch/sh/include/cpu-sh3/cpu/cacheflush.h index abc9098..1ac27aa 100644 --- a/arch/sh/include/cpu-sh3/cpu/cacheflush.h +++ b/arch/sh/include/cpu-sh3/cpu/cacheflush.h @@ -29,6 +29,16 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned l void flush_dcache_page(struct page *pg); void flush_icache_range(unsigned long start, unsigned long end); void flush_icache_page(struct vm_area_struct *vma, struct page *page); + +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +/* SH3 has unified cache so no special action needed here */ +#define flush_cache_sigtramp(vaddr) do { } while (0) +#define flush_icache_user_range(vma,pg,adr,len) do { } while (0) + +#define p3_cache_init() do { } while (0) + #else #include <cpu-common/cpu/cacheflush.h> #endif diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index cd6baff..a7412ce 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -45,7 +45,7 @@ static struct platform_device vpu_device = { }; static struct uio_info veu0_platform_data = { - .name = "VEU", + .name = "VEU2H", .version = "0", .irq = 54, }; @@ -73,7 +73,7 @@ static struct platform_device veu0_device = { }; static struct uio_info veu1_platform_data = { - .name = "VEU", + .name = "VEU2H", .version = "0", .irq = 27, }; diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 8f91653..6e1b1c2 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -107,10 +107,12 @@ DECLARE_EXPORT(__movmemSI12_i4); * GCC >= 4.2 emits these for division, as do GCC 4.1.x versions of the ST * compiler which include backported patches. */ -DECLARE_EXPORT(__sdivsi3_i4i); DECLARE_EXPORT(__udiv_qrnnd_16); +#if !defined(CONFIG_CPU_SH2) +DECLARE_EXPORT(__sdivsi3_i4i); DECLARE_EXPORT(__udivsi3_i4i); #endif +#endif #else /* GCC 3.x */ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 9c131ca..8a03926 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -181,10 +181,12 @@ config ENTRY_OFFSET choice prompt "HugeTLB page size" depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU + default HUGETLB_PAGE_SIZE_1MB if PAGE_SIZE_64KB default HUGETLB_PAGE_SIZE_64K config HUGETLB_PAGE_SIZE_64K bool "64kB" + depends on !PAGE_SIZE_64KB config HUGETLB_PAGE_SIZE_256K bool "256kB" diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index b2ce014..895bb3f 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -95,6 +95,29 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, } EXPORT_SYMBOL(dma_cache_sync); +static int __init memchunk_setup(char *str) +{ + return 1; /* accept anything that begins with "memchunk." */ +} +__setup("memchunk.", memchunk_setup); + +static void memchunk_cmdline_override(char *name, unsigned long *sizep) +{ + char *p = boot_command_line; + int k = strlen(name); + + while ((p = strstr(p, "memchunk."))) { + p += 9; /* strlen("memchunk.") */ + if (!strncmp(name, p, k) && p[k] == '=') { + p += k + 1; + *sizep = memparse(p, NULL); + pr_info("%s: forcing memory chunk size to 0x%08lx\n", + name, *sizep); + break; + } + } +} + int platform_resource_setup_memory(struct platform_device *pdev, char *name, unsigned long memsize) { @@ -109,6 +132,10 @@ int platform_resource_setup_memory(struct platform_device *pdev, return -EINVAL; } + memchunk_cmdline_override(name, &memsize); + if (!memsize) + return 0; + buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL); if (!buf) { pr_warning("%s: unable to allocate memory\n", name); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 4e72719..84bb395 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -737,63 +737,44 @@ static int find_psb_table(struct powernow_k8_data *data) #ifdef CONFIG_X86_POWERNOW_K8_ACPI static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { - if (!data->acpi_data->state_count || (cpu_family == CPU_HW_PSTATE)) + if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) return; - data->irt = (data->acpi_data->states[index].control >> IRT_SHIFT) & IRT_MASK; - data->rvo = (data->acpi_data->states[index].control >> RVO_SHIFT) & RVO_MASK; - data->exttype = (data->acpi_data->states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; - data->plllock = (data->acpi_data->states[index].control >> PLL_L_SHIFT) & PLL_L_MASK; - data->vidmvs = 1 << ((data->acpi_data->states[index].control >> MVS_SHIFT) & MVS_MASK); - data->vstable = (data->acpi_data->states[index].control >> VST_SHIFT) & VST_MASK; -} - - -static struct acpi_processor_performance *acpi_perf_data; -static int preregister_valid; - -static int powernow_k8_cpu_preinit_acpi(void) -{ - acpi_perf_data = alloc_percpu(struct acpi_processor_performance); - if (!acpi_perf_data) - return -ENODEV; - - if (acpi_processor_preregister_performance(acpi_perf_data)) - return -ENODEV; - else - preregister_valid = 1; - return 0; + data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; + data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & RVO_MASK; + data->exttype = (data->acpi_data.states[index].control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; + data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) & PLL_L_MASK; + data->vidmvs = 1 << ((data->acpi_data.states[index].control >> MVS_SHIFT) & MVS_MASK); + data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & VST_MASK; } static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { struct cpufreq_frequency_table *powernow_table; int ret_val; - int cpu = 0; - data->acpi_data = percpu_ptr(acpi_perf_data, cpu); - if (acpi_processor_register_performance(data->acpi_data, data->cpu)) { + if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { dprintk("register performance failed: bad ACPI data\n"); return -EIO; } /* verify the data contained in the ACPI structures */ - if (data->acpi_data->state_count <= 1) { + if (data->acpi_data.state_count <= 1) { dprintk("No ACPI P-States\n"); goto err_out; } - if ((data->acpi_data->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || - (data->acpi_data->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { + if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || + (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { dprintk("Invalid control/status registers (%x - %x)\n", - data->acpi_data->control_register.space_id, - data->acpi_data->status_register.space_id); + data->acpi_data.control_register.space_id, + data->acpi_data.status_register.space_id); goto err_out; } /* fill in data->powernow_table */ powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) - * (data->acpi_data->state_count + 1)), GFP_KERNEL); + * (data->acpi_data.state_count + 1)), GFP_KERNEL); if (!powernow_table) { dprintk("powernow_table memory alloc failure\n"); goto err_out; @@ -806,12 +787,12 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) if (ret_val) goto err_out_mem; - powernow_table[data->acpi_data->state_count].frequency = CPUFREQ_TABLE_END; - powernow_table[data->acpi_data->state_count].index = 0; + powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END; + powernow_table[data->acpi_data.state_count].index = 0; data->powernow_table = powernow_table; /* fill in data */ - data->numps = data->acpi_data->state_count; + data->numps = data->acpi_data.state_count; if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) print_basics(data); powernow_k8_acpi_pst_values(data, 0); @@ -819,31 +800,16 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - /* determine affinity, from ACPI if available */ - if (preregister_valid) { - if ((data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ALL) || - (data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ANY)) - data->starting_core_affinity = data->acpi_data->shared_cpu_map; - else - data->starting_core_affinity = cpumask_of_cpu(data->cpu); - } else { - /* best guess from family if not */ - if (cpu_family == CPU_HW_PSTATE) - data->starting_core_affinity = cpumask_of_cpu(data->cpu); - else - data->starting_core_affinity = per_cpu(cpu_core_map, data->cpu); - } - return 0; err_out_mem: kfree(powernow_table); err_out: - acpi_processor_unregister_performance(data->acpi_data, data->cpu); + acpi_processor_unregister_performance(&data->acpi_data, data->cpu); /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ - data->acpi_data->state_count = 0; + data->acpi_data.state_count = 0; return -ENODEV; } @@ -855,10 +821,10 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo); data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT; - for (i = 0; i < data->acpi_data->state_count; i++) { + for (i = 0; i < data->acpi_data.state_count; i++) { u32 index; - index = data->acpi_data->states[i].control & HW_PSTATE_MASK; + index = data->acpi_data.states[i].control & HW_PSTATE_MASK; if (index > data->max_hw_pstate) { printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); @@ -874,7 +840,7 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf powernow_table[i].index = index; - powernow_table[i].frequency = data->acpi_data->states[i].core_frequency * 1000; + powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; } return 0; } @@ -883,16 +849,16 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf { int i; int cntlofreq = 0; - for (i = 0; i < data->acpi_data->state_count; i++) { + for (i = 0; i < data->acpi_data.state_count; i++) { u32 fid; u32 vid; if (data->exttype) { - fid = data->acpi_data->states[i].status & EXT_FID_MASK; - vid = (data->acpi_data->states[i].status >> VID_SHIFT) & EXT_VID_MASK; + fid = data->acpi_data.states[i].status & EXT_FID_MASK; + vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK; } else { - fid = data->acpi_data->states[i].control & FID_MASK; - vid = (data->acpi_data->states[i].control >> VID_SHIFT) & VID_MASK; + fid = data->acpi_data.states[i].control & FID_MASK; + vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; } dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); @@ -933,10 +899,10 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf cntlofreq = i; } - if (powernow_table[i].frequency != (data->acpi_data->states[i].core_frequency * 1000)) { + if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", powernow_table[i].frequency, - (unsigned int) (data->acpi_data->states[i].core_frequency * 1000)); + (unsigned int) (data->acpi_data.states[i].core_frequency * 1000)); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; } @@ -946,12 +912,11 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { - if (data->acpi_data->state_count) - acpi_processor_unregister_performance(data->acpi_data, data->cpu); + if (data->acpi_data.state_count) + acpi_processor_unregister_performance(&data->acpi_data, data->cpu); } #else -static int powernow_k8_cpu_preinit_acpi(void) { return -ENODEV; } static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return -ENODEV; } static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; } static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { return; } @@ -1136,7 +1101,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol) static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; - cpumask_t oldmask = CPU_MASK_ALL; + cpumask_t oldmask; int rc; if (!cpu_online(pol->cpu)) @@ -1209,7 +1174,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) /* run on any CPU again */ set_cpus_allowed_ptr(current, &oldmask); - pol->cpus = data->starting_core_affinity; + if (cpu_family == CPU_HW_PSTATE) + pol->cpus = cpumask_of_cpu(pol->cpu); + else + pol->cpus = per_cpu(cpu_core_map, pol->cpu); data->available_cores = &(pol->cpus); /* Take a crude guess here. @@ -1332,7 +1300,6 @@ static int __cpuinit powernowk8_init(void) } if (supported_cpus == num_online_cpus()) { - powernow_k8_cpu_preinit_acpi(); printk(KERN_INFO PFX "Found %d %s " "processors (%d cpu cores) (" VERSION ")\n", num_online_nodes(), @@ -1349,10 +1316,6 @@ static void __exit powernowk8_exit(void) dprintk("exit\n"); cpufreq_unregister_driver(&cpufreq_amd64_driver); - -#ifdef CONFIG_X86_POWERNOW_K8_ACPI - free_percpu(acpi_perf_data); -#endif } MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>"); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index a62612c..ab48cfe 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -33,13 +33,12 @@ struct powernow_k8_data { #ifdef CONFIG_X86_POWERNOW_K8_ACPI /* the acpi table needs to be kept. it's only available if ACPI was * used to determine valid frequency/vid/fid states */ - struct acpi_processor_performance *acpi_data; + struct acpi_processor_performance acpi_data; #endif /* we need to keep track of associated cores, but let cpufreq * handle hotplug events - so just point at cpufreq pol->cpus * structure */ cpumask_t *available_cores; - cpumask_t starting_core_affinity; }; diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 3fa4e92..6a44d64 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -88,6 +88,8 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, struct cpuid_regs cmd; int cpu = iminor(file->f_path.dentry->d_inode); u64 pos = *ppos; + ssize_t bytes = 0; + int err = 0; if (count % 16) return -EINVAL; /* Invalid chunk size */ @@ -95,14 +97,19 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, for (; count; count -= 16) { cmd.eax = pos; cmd.ecx = pos >> 32; - smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1); - if (copy_to_user(tmp, &cmd, 16)) - return -EFAULT; + err = smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1); + if (err) + break; + if (copy_to_user(tmp, &cmd, 16)) { + err = -EFAULT; + break; + } tmp += 16; + bytes += 16; *ppos = ++pos; } - return tmp - buf; + return bytes ? bytes : err; } static int cpuid_open(struct inode *inode, struct file *file) diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index e439380..2e2af5d 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -72,21 +72,28 @@ static ssize_t msr_read(struct file *file, char __user *buf, u32 data[2]; u32 reg = *ppos; int cpu = iminor(file->f_path.dentry->d_inode); - int err; + int err = 0; + ssize_t bytes = 0; if (count % 8) return -EINVAL; /* Invalid chunk size */ for (; count; count -= 8) { err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]); - if (err) - return -EIO; - if (copy_to_user(tmp, &data, 8)) - return -EFAULT; + if (err) { + if (err == -EFAULT) /* Fix idiotic error code */ + err = -EIO; + break; + } + if (copy_to_user(tmp, &data, 8)) { + err = -EFAULT; + break; + } tmp += 2; + bytes += 8; } - return ((char __user *)tmp) - buf; + return bytes ? bytes : err; } static ssize_t msr_write(struct file *file, const char __user *buf, @@ -96,21 +103,28 @@ static ssize_t msr_write(struct file *file, const char __user *buf, u32 data[2]; u32 reg = *ppos; int cpu = iminor(file->f_path.dentry->d_inode); - int err; + int err = 0; + ssize_t bytes = 0; if (count % 8) return -EINVAL; /* Invalid chunk size */ for (; count; count -= 8) { - if (copy_from_user(&data, tmp, 8)) - return -EFAULT; + if (copy_from_user(&data, tmp, 8)) { + err = -EFAULT; + break; + } err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); - if (err) - return -EIO; + if (err) { + if (err == -EFAULT) /* Fix idiotic error code */ + err = -EIO; + break; + } tmp += 2; + bytes += 8; } - return ((char __user *)tmp) - buf; + return bytes ? bytes : err; } static int msr_open(struct inode *inode, struct file *file) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 9bed5ca..8e786b0 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -314,7 +314,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, mark_tsc_unstable("cpufreq changes"); } - set_cyc2ns_scale(tsc_khz_ref, freq->cpu); + set_cyc2ns_scale(tsc_khz, freq->cpu); return 0; } diff --git a/arch/x86/lib/msr-on-cpu.c b/arch/x86/lib/msr-on-cpu.c index d5a2b39..01b868b 100644 --- a/arch/x86/lib/msr-on-cpu.c +++ b/arch/x86/lib/msr-on-cpu.c @@ -30,10 +30,11 @@ static int _rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h, int safe) rv.msr_no = msr_no; if (safe) { - smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); - err = rv.err; + err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, + &rv, 1); + err = err ? err : rv.err; } else { - smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); + err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1); } *l = rv.l; *h = rv.h; @@ -64,23 +65,24 @@ static int _wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h, int safe) rv.l = l; rv.h = h; if (safe) { - smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1); - err = rv.err; + err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, + &rv, 1); + err = err ? err : rv.err; } else { - smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); + err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1); } return err; } -void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { - _wrmsr_on_cpu(cpu, msr_no, l, h, 0); + return _wrmsr_on_cpu(cpu, msr_no, l, h, 0); } -void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { - _rdmsr_on_cpu(cpu, msr_no, l, h, 0); + return _rdmsr_on_cpu(cpu, msr_no, l, h, 0); } /* These "safe" variants are slower and should be used when the target MSR diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c index a037041..4f4e50c 100644 --- a/arch/x86/mach-rdc321x/platform.c +++ b/arch/x86/mach-rdc321x/platform.c @@ -25,7 +25,6 @@ #include <linux/list.h> #include <linux/device.h> #include <linux/platform_device.h> -#include <linux/version.h> #include <linux/leds.h> #include <asm/gpio.h> diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index d781cc4..006599d 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -590,6 +590,8 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH10_1: case PCI_DEVICE_ID_INTEL_ICH10_2: case PCI_DEVICE_ID_INTEL_ICH10_3: + case PCI_DEVICE_ID_INTEL_PCH_0: + case PCI_DEVICE_ID_INTEL_PCH_1: r->name = "PIIX/ICH"; r->get = pirq_piix_get; r->set = pirq_piix_set; diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index ec9ce35..b722dd4 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -14,7 +14,7 @@ static void __devinit pcibios_fixup_peer_bridges(void) int n, devfn; long node; - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) + if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff) return; DBG("PCI: Peer bridge fixup\n"); diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 2bd5c53..d963576 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -293,7 +293,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, return AE_OK; } -static int __init is_acpi_reserved(unsigned long start, unsigned long end) +static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used) { struct resource mcfg_res; @@ -310,6 +310,41 @@ static int __init is_acpi_reserved(unsigned long start, unsigned long end) return mcfg_res.flags; } +typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type); + +static int __init is_mmconf_reserved(check_reserved_t is_reserved, + u64 addr, u64 size, int i, + typeof(pci_mmcfg_config[0]) *cfg, int with_e820) +{ + u64 old_size = size; + int valid = 0; + + while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) { + size >>= 1; + if (size < (16UL<<20)) + break; + } + + if (size >= (16UL<<20) || size == old_size) { + printk(KERN_NOTICE + "PCI: MCFG area at %Lx reserved in %s\n", + addr, with_e820?"E820":"ACPI motherboard resources"); + valid = 1; + + if (old_size != size) { + /* update end_bus_number */ + cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1); + printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx " + "segment %hu buses %u - %u\n", + i, (unsigned long)cfg->address, cfg->pci_segment, + (unsigned int)cfg->start_bus_number, + (unsigned int)cfg->end_bus_number); + } + } + + return valid; +} + static void __init pci_mmcfg_reject_broken(int early) { typeof(pci_mmcfg_config[0]) *cfg; @@ -324,21 +359,22 @@ static void __init pci_mmcfg_reject_broken(int early) for (i = 0; i < pci_mmcfg_config_num; i++) { int valid = 0; - u32 size = (cfg->end_bus_number + 1) << 20; + u64 addr, size; + cfg = &pci_mmcfg_config[i]; + addr = cfg->start_bus_number; + addr <<= 20; + addr += cfg->address; + size = cfg->end_bus_number + 1 - cfg->start_bus_number; + size <<= 20; printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " "segment %hu buses %u - %u\n", i, (unsigned long)cfg->address, cfg->pci_segment, (unsigned int)cfg->start_bus_number, (unsigned int)cfg->end_bus_number); - if (!early && - is_acpi_reserved(cfg->address, cfg->address + size - 1)) { - printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " - "in ACPI motherboard resources\n", - cfg->address); - valid = 1; - } + if (!early) + valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); if (valid) continue; @@ -347,16 +383,11 @@ static void __init pci_mmcfg_reject_broken(int early) printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" " reserved in ACPI motherboard resources\n", cfg->address); + /* Don't try to do this check unless configuration type 1 is available. how about type 2 ?*/ - if (raw_pci_ops && e820_all_mapped(cfg->address, - cfg->address + size - 1, - E820_RESERVED)) { - printk(KERN_NOTICE - "PCI: MCFG area at %Lx reserved in E820\n", - cfg->address); - valid = 1; - } + if (raw_pci_ops) + valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1); if (!valid) goto reject; diff --git a/block/genhd.c b/block/genhd.c index c13cc77..656c2c7 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -293,27 +293,30 @@ void __init printk_all_partitions(void) /* iterator */ static int find_start(struct device *dev, void *data) { - loff_t k = *(loff_t *)data; + loff_t *k = data; if (dev->type != &disk_type) return 0; - if (!k--) + if (!*k) return 1; + (*k)--; return 0; } static void *part_start(struct seq_file *part, loff_t *pos) { struct device *dev; - loff_t n = *pos; + loff_t k = *pos; - if (!n) + if (!k) seq_puts(part, "major minor #blocks name\n\n"); mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, (void *)pos, find_start); - if (dev) + dev = class_find_device(&block_class, NULL, &k, find_start); + if (dev) { + put_device(dev); return dev_to_disk(dev); + } return NULL; } @@ -330,8 +333,10 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos) struct device *dev; ++*pos; dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) + if (dev) { + put_device(dev); return dev_to_disk(dev); + } return NULL; } @@ -568,11 +573,14 @@ static struct device_type disk_type = { static void *diskstats_start(struct seq_file *part, loff_t *pos) { struct device *dev; + loff_t k = *pos; mutex_lock(&block_class_lock); - dev = class_find_device(&block_class, NULL, (void *)pos, find_start); - if (dev) + dev = class_find_device(&block_class, NULL, &k, find_start); + if (dev) { + put_device(dev); return dev_to_disk(dev); + } return NULL; } @@ -583,8 +591,10 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) ++*pos; dev = class_find_device(&block_class, &gp->dev, NULL, find_next); - if (dev) + if (dev) { + put_device(dev); return dev_to_disk(dev); + } return NULL; } @@ -712,10 +722,12 @@ dev_t blk_lookup_devt(const char *name, int part) mutex_lock(&block_class_lock); find.name = name; find.part = part; - dev = class_find_device(&block_class, NULL, (void *)&find, match_id); - if (dev) + dev = class_find_device(&block_class, NULL, &find, match_id); + if (dev) { + put_device(dev); devt = MKDEV(MAJOR(dev->devt), MINOR(dev->devt) + part); + } mutex_unlock(&block_class_lock); return devt; diff --git a/crypto/authenc.c b/crypto/authenc.c index 4b22676..fd9f06c 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -174,8 +174,9 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, static void crypto_authenc_encrypt_done(struct crypto_async_request *req, int err) { + struct aead_request *areq = req->data; + if (!err) { - struct aead_request *areq = req->data; struct crypto_aead *authenc = crypto_aead_reqtfm(areq); struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); struct ablkcipher_request *abreq = aead_request_ctx(areq); @@ -185,7 +186,7 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, err = crypto_authenc_genicv(areq, iv, 0); } - aead_request_complete(req->data, err); + aead_request_complete(areq, err); } static int crypto_authenc_encrypt(struct aead_request *req) @@ -216,14 +217,15 @@ static int crypto_authenc_encrypt(struct aead_request *req) static void crypto_authenc_givencrypt_done(struct crypto_async_request *req, int err) { + struct aead_request *areq = req->data; + if (!err) { - struct aead_request *areq = req->data; struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); err = crypto_authenc_genicv(areq, greq->giv, 0); } - aead_request_complete(req->data, err); + aead_request_complete(areq, err); } static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ef3e552..c729e69 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -486,6 +486,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -575,9 +577,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ /* SiS */ - { PCI_VDEVICE(SI, 0x1184), board_ahci_nopmp }, /* SiS 966 */ - { PCI_VDEVICE(SI, 0x1185), board_ahci_nopmp }, /* SiS 968 */ - { PCI_VDEVICE(SI, 0x0186), board_ahci_nopmp }, /* SiS 968 */ + { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ + { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ + { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index c294121..b1d08a8 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -275,6 +275,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (ICH10) */ { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, { } /* terminate list */ }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5ba96c5..79e3a8e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -104,6 +104,7 @@ struct ata_force_param { unsigned long xfer_mask; unsigned int horkage_on; unsigned int horkage_off; + unsigned int lflags; }; struct ata_force_ent { @@ -196,22 +197,23 @@ void ata_force_cbl(struct ata_port *ap) } /** - * ata_force_spd_limit - force SATA spd limit according to libata.force + * ata_force_link_limits - force link limits according to libata.force * @link: ATA link of interest * - * Force SATA spd limit according to libata.force and whine about - * it. When only the port part is specified (e.g. 1:), the limit - * applies to all links connected to both the host link and all - * fan-out ports connected via PMP. If the device part is - * specified as 0 (e.g. 1.00:), it specifies the first fan-out - * link not the host link. Device number 15 always points to the - * host link whether PMP is attached or not. + * Force link flags and SATA spd limit according to libata.force + * and whine about it. When only the port part is specified + * (e.g. 1:), the limit applies to all links connected to both + * the host link and all fan-out ports connected via PMP. If the + * device part is specified as 0 (e.g. 1.00:), it specifies the + * first fan-out link not the host link. Device number 15 always + * points to the host link whether PMP is attached or not. * * LOCKING: * EH context. */ -static void ata_force_spd_limit(struct ata_link *link) +static void ata_force_link_limits(struct ata_link *link) { + bool did_spd = false; int linkno, i; if (ata_is_host_link(link)) @@ -228,13 +230,22 @@ static void ata_force_spd_limit(struct ata_link *link) if (fe->device != -1 && fe->device != linkno) continue; - if (!fe->param.spd_limit) - continue; + /* only honor the first spd limit */ + if (!did_spd && fe->param.spd_limit) { + link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; + ata_link_printk(link, KERN_NOTICE, + "FORCE: PHY spd limit set to %s\n", + fe->param.name); + did_spd = true; + } - link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; - ata_link_printk(link, KERN_NOTICE, - "FORCE: PHY spd limit set to %s\n", fe->param.name); - return; + /* let lflags stack */ + if (fe->param.lflags) { + link->flags |= fe->param.lflags; + ata_link_printk(link, KERN_NOTICE, + "FORCE: link flag 0x%x forced -> 0x%x\n", + fe->param.lflags, link->flags); + } } } @@ -3277,7 +3288,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) dev->dma_mode = ata_xfer_mask2mode(dma_mask); found = 1; - if (dev->dma_mode != 0xff) + if (ata_dma_enabled(dev)) used_dma = 1; } if (!found) @@ -3302,7 +3313,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) /* step 3: set host DMA timings */ ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff) + if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev)) continue; dev->xfer_mode = dev->dma_mode; @@ -5188,19 +5199,18 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) */ int sata_link_init_spd(struct ata_link *link) { - u32 scontrol; u8 spd; int rc; - rc = sata_scr_read(link, SCR_CONTROL, &scontrol); + rc = sata_scr_read(link, SCR_CONTROL, &link->saved_scontrol); if (rc) return rc; - spd = (scontrol >> 4) & 0xf; + spd = (link->saved_scontrol >> 4) & 0xf; if (spd) link->hw_sata_spd_limit &= (1 << spd) - 1; - ata_force_spd_limit(link); + ata_force_link_limits(link); link->sata_spd_limit = link->hw_sata_spd_limit; @@ -5783,9 +5793,10 @@ static void ata_port_detach(struct ata_port *ap) ata_port_wait_eh(ap); /* EH is now guaranteed to see UNLOADING - EH context belongs - * to us. Disable all existing devices. + * to us. Restore SControl and disable all existing devices. */ - ata_port_for_each_link(link, ap) { + __ata_port_for_each_link(link, ap) { + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol); ata_link_for_each_dev(dev, link) ata_dev_disable(dev); } @@ -5991,6 +6002,9 @@ static int __init ata_parse_force_one(char **cur, { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) }, + { "nohrst", .lflags = ATA_LFLAG_NO_HRST }, + { "nosrst", .lflags = ATA_LFLAG_NO_SRST }, + { "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST }, }; char *start = *cur, *p = *cur; char *id, *val, *endp; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 58bdc53..c1db2f2 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2040,7 +2040,7 @@ static void ata_eh_link_report(struct ata_link *link) } if (ehc->i.serror) - ata_port_printk(ap, KERN_ERR, + ata_link_printk(link, KERN_ERR, "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n", ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "", ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "", @@ -2171,18 +2171,12 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, } static int ata_eh_followup_srst_needed(struct ata_link *link, - int rc, int classify, - const unsigned int *classes) + int rc, const unsigned int *classes) { if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link)) return 0; - if (rc == -EAGAIN) { - if (classify) - return 1; - rc = 0; - } - if (rc != 0) - return 0; + if (rc == -EAGAIN) + return 1; if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) return 1; return 0; @@ -2210,6 +2204,10 @@ int ata_eh_reset(struct ata_link *link, int classify, */ while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX) max_tries++; + if (link->flags & ATA_LFLAG_NO_HRST) + hardreset = NULL; + if (link->flags & ATA_LFLAG_NO_SRST) + softreset = NULL; now = jiffies; deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); @@ -2247,10 +2245,10 @@ int ata_eh_reset(struct ata_link *link, int classify, ehc->i.action &= ~ATA_EH_RESET; if (hardreset) { reset = hardreset; - ehc->i.action = ATA_EH_HARDRESET; + ehc->i.action |= ATA_EH_HARDRESET; } else if (softreset) { reset = softreset; - ehc->i.action = ATA_EH_SOFTRESET; + ehc->i.action |= ATA_EH_SOFTRESET; } if (prereset) { @@ -2305,9 +2303,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ehc->i.flags |= ATA_EHI_DID_SOFTRESET; rc = ata_do_reset(link, reset, classes, deadline); + if (rc && rc != -EAGAIN) + goto fail; if (reset == hardreset && - ata_eh_followup_srst_needed(link, rc, classify, classes)) { + ata_eh_followup_srst_needed(link, rc, classes)) { /* okay, let's do follow-up softreset */ reset = softreset; @@ -2322,10 +2322,6 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ATA_EH_RESET); rc = ata_do_reset(link, reset, classes, deadline); } - - /* -EAGAIN can happen if we skipped followup SRST */ - if (rc && rc != -EAGAIN) - goto fail; } else { if (verbose) ata_link_printk(link, KERN_INFO, "no reset method " diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index fbe6057..eb919c1 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -181,7 +181,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc) if (adev != acpi->last) { pacpi_set_piomode(ap, adev); - if (adev->dma_mode) + if (ata_dma_enabled(adev)) pacpi_set_dmamode(ap, adev); acpi->last = adev; } diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index d7de7ba..e8a0d99 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -183,7 +183,7 @@ static void atiixp_bmdma_start(struct ata_queued_cmd *qc) u16 tmp16; pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - if (adev->dma_mode >= XFER_UDMA_0) + if (ata_using_udma(adev)) tmp16 |= (1 << dn); else tmp16 &= ~(1 << dn); diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 744beeb..0c4b271 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -149,10 +149,10 @@ static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc) struct ata_device *prev = ap->private_data; /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { + if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) + if ((ata_using_udma(adev) && !ata_using_udma(prev)) || + (ata_using_udma(prev) && !ata_using_udma(adev))) /* Switch the mode bits */ cs5530_set_dmamode(ap, adev); } diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 27843c7..0221c9a 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -606,7 +606,7 @@ static void it821x_display_disk(int n, u8 *buf) { unsigned char id[41]; int mode = 0; - char *mtype; + char *mtype = ""; char mbuf[8]; char *cbl = "(40 wire cable)"; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index e678af3..df64f24 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -198,7 +198,7 @@ static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc) if (adev != ap->private_data) { oldpiix_set_piomode(ap, adev); - if (adev->dma_mode) + if (ata_dma_enabled(adev)) oldpiix_set_dmamode(ap, adev); } return ata_sff_qc_issue(qc); diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index cbab397..0278fd2 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -167,10 +167,10 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc) struct ata_device *prev = ap->private_data; /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { + if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) + if ((ata_using_udma(adev) && !ata_using_udma(prev)) || + (ata_using_udma(prev) && !ata_using_udma(adev))) /* Switch the mode bits */ sc1200_set_dmamode(ap, adev); } diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 57d951b..8fdb2ce 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -324,62 +324,26 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) } /** - * via_ata_sff_tf_load - send taskfile registers to host controller + * via_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set * * Outputs ATA taskfile to standard ATA host controller. * * Note: This is to fix the internal bug of via chipsets, which - * will reset the device register after changing the IEN bit on - * ctl register + * will reset the device register after changing the IEN bit on + * ctl register */ -static void via_ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) +static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { - struct ata_ioports *ioaddr = &ap->ioaddr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - iowrite8(tf->ctl, ioaddr->ctl_addr); - iowrite8(tf->device, ioaddr->device_addr); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - - if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - iowrite8(tf->hob_feature, ioaddr->feature_addr); - iowrite8(tf->hob_nsect, ioaddr->nsect_addr); - iowrite8(tf->hob_lbal, ioaddr->lbal_addr); - iowrite8(tf->hob_lbam, ioaddr->lbam_addr); - iowrite8(tf->hob_lbah, ioaddr->lbah_addr); - VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", - tf->hob_feature, - tf->hob_nsect, - tf->hob_lbal, - tf->hob_lbam, - tf->hob_lbah); - } + struct ata_taskfile tmp_tf; - if (is_addr) { - iowrite8(tf->feature, ioaddr->feature_addr); - iowrite8(tf->nsect, ioaddr->nsect_addr); - iowrite8(tf->lbal, ioaddr->lbal_addr); - iowrite8(tf->lbam, ioaddr->lbam_addr); - iowrite8(tf->lbah, ioaddr->lbah_addr); - VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", - tf->feature, - tf->nsect, - tf->lbal, - tf->lbam, - tf->lbah); + if (ap->ctl != ap->last_ctl && !(tf->flags & ATA_TFLAG_DEVICE)) { + tmp_tf = *tf; + tmp_tf.flags |= ATA_TFLAG_DEVICE; + tf = &tmp_tf; } - - if (tf->flags & ATA_TFLAG_DEVICE) { - iowrite8(tf->device, ioaddr->device_addr); - VPRINTK("device 0x%X\n", tf->device); - } - - ata_wait_idle(ap); + ata_sff_tf_load(ap, tf); } static struct scsi_host_template via_sht = { @@ -392,13 +356,12 @@ static struct ata_port_operations via_port_ops = { .set_piomode = via_set_piomode, .set_dmamode = via_set_dmamode, .prereset = via_pre_reset, - .sff_tf_load = via_ata_tf_load, + .sff_tf_load = via_tf_load, }; static struct ata_port_operations via_port_ops_noirq = { .inherits = &via_port_ops, .sff_data_xfer = ata_sff_data_xfer_noirq, - .sff_tf_load = via_ata_tf_load, }; /** diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index ad169ff..13c1d2a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1134,30 +1134,16 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) if (ap->nr_active_links == 0) return 0; - if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { - /* - * The port is operating in host queuing mode (EDMA). - * It can accomodate a new qc if the qc protocol - * is compatible with the current host queue mode. - */ - if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) { - /* - * The host queue (EDMA) is in NCQ mode. - * If the new qc is also an NCQ command, - * then allow the new qc. - */ - if (qc->tf.protocol == ATA_PROT_NCQ) - return 0; - } else { - /* - * The host queue (EDMA) is in non-NCQ, DMA mode. - * If the new qc is also a non-NCQ, DMA command, - * then allow the new qc. - */ - if (qc->tf.protocol == ATA_PROT_DMA) - return 0; - } - } + /* + * The port is operating in host queuing mode (EDMA) with NCQ + * enabled, allow multiple NCQ commands. EDMA also allows + * queueing multiple DMA commands but libata core currently + * doesn't allow it. + */ + if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) && + (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol)) + return 0; + return ATA_DEFER_PORT; } @@ -3036,7 +3022,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_soc: hpriv->ops = &mv_soc_ops; - hp_flags |= MV_HP_FLAG_SOC | MV_HP_ERRATA_60X1C0; + hp_flags |= MV_HP_FLAG_SOC | MV_HP_GEN_IIE | + MV_HP_ERRATA_60X1C0; break; default: diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 2ebd07f..5effec6 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c @@ -3,7 +3,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/errno.h> diff --git a/drivers/base/class.c b/drivers/base/class.c index 5667c2f..cc5e28c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -295,6 +295,12 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return -EINVAL; + } + mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { @@ -344,6 +350,11 @@ struct device *class_find_device(struct class *class, struct device *start, if (!class) return NULL; + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return NULL; + } mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { diff --git a/drivers/base/core.c b/drivers/base/core.c index 068aa1c..d021c98 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -53,7 +53,7 @@ static inline int device_is_not_partition(struct device *dev) * it is attached to. If it is not attached to a bus either, an empty * string will be returned. */ -const char *dev_driver_string(struct device *dev) +const char *dev_driver_string(const struct device *dev) { return dev->driver ? dev->driver->name : (dev->bus ? dev->bus->name : @@ -541,6 +541,7 @@ void device_initialize(struct device *dev) spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_init_wakeup(dev, 0); + device_pm_init(dev); set_dev_node(dev, -1); } @@ -843,13 +844,19 @@ int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; - int error; + int error = -EINVAL; dev = get_device(dev); - if (!dev || !strlen(dev->bus_id)) { - error = -EINVAL; - goto Done; - } + if (!dev) + goto done; + + /* Temporarily support init_name if it is set. + * It will override bus_id for now */ + if (dev->init_name) + dev_set_name(dev, "%s", dev->init_name); + + if (!strlen(dev->bus_id)) + goto done; pr_debug("device: '%s': %s\n", dev->bus_id, __func__); @@ -897,9 +904,10 @@ int device_add(struct device *dev) error = bus_add_device(dev); if (error) goto BusError; - error = device_pm_add(dev); + error = dpm_sysfs_add(dev); if (error) - goto PMError; + goto DPMError; + device_pm_add(dev); kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) @@ -917,10 +925,10 @@ int device_add(struct device *dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->class_mutex); } - Done: +done: put_device(dev); return error; - PMError: + DPMError: bus_remove_device(dev); BusError: if (dev->bus) @@ -944,7 +952,7 @@ int device_add(struct device *dev) cleanup_device_parent(dev); if (parent) put_device(parent); - goto Done; + goto done; } /** @@ -1007,6 +1015,7 @@ void device_del(struct device *dev) struct class_interface *class_intf; device_pm_remove(dev); + dpm_sysfs_remove(dev); if (parent) klist_del(&dev->knode_parent); if (MAJOR(dev->devt)) { diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 2ef5acf..1e2bda7 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -16,9 +16,6 @@ #include <linux/string.h> #include "base.h" -#define to_dev(node) container_of(node, struct device, driver_list) - - static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3250c52..273a944 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -67,20 +67,16 @@ void device_pm_unlock(void) * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -int device_pm_add(struct device *dev) +void device_pm_add(struct device *dev) { - int error; - pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); if (dev->parent) { - if (dev->parent->power.status >= DPM_SUSPENDING) { - dev_warn(dev, "parent %s is sleeping, will not add\n", + if (dev->parent->power.status >= DPM_SUSPENDING) + dev_warn(dev, "parent %s should not be sleeping\n", dev->parent->bus_id); - WARN_ON(true); - } } else if (transition_started) { /* * We refuse to register parentless devices while a PM @@ -89,13 +85,9 @@ int device_pm_add(struct device *dev) */ WARN_ON(true); } - error = dpm_sysfs_add(dev); - if (!error) { - dev->power.status = DPM_ON; - list_add_tail(&dev->power.entry, &dpm_list); - } + + list_add_tail(&dev->power.entry, &dpm_list); mutex_unlock(&dpm_list_mtx); - return error; } /** @@ -110,7 +102,6 @@ void device_pm_remove(struct device *dev) dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - dpm_sysfs_remove(dev); list_del_init(&dev->power.entry); mutex_unlock(&dpm_list_mtx); } diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index a3252c0..41f51fa 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -1,3 +1,8 @@ +static inline void device_pm_init(struct device *dev) +{ + dev->power.status = DPM_ON; +} + #ifdef CONFIG_PM_SLEEP /* @@ -11,12 +16,12 @@ static inline struct device *to_device(struct list_head *entry) return container_of(entry, struct device, power.entry); } -extern int device_pm_add(struct device *); +extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); #else /* CONFIG_PM_SLEEP */ -static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_add(struct device *dev) {} static inline void device_pm_remove(struct device *dev) {} #endif diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 24b97b0..d070d49 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -571,8 +571,8 @@ out_free: list_del(&brd->brd_list); brd_free(brd); } + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); - unregister_blkdev(RAMDISK_MAJOR, "brd"); return -ENOMEM; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index ad98dda..1778e4a 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -707,15 +707,15 @@ static int __init nbd_init(void) BUILD_BUG_ON(sizeof(struct nbd_request) != 28); - nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); - if (!nbd_dev) - return -ENOMEM; - if (max_part < 0) { printk(KERN_CRIT "nbd: max_part must be >= 0\n"); return -EINVAL; } + nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); + if (!nbd_dev) + return -ENOMEM; + part_shift = 0; if (max_part > 0) part_shift = fls(max_part); @@ -779,6 +779,7 @@ out: blk_cleanup_queue(nbd_dev[i].disk->queue); put_disk(nbd_dev[i].disk); } + kfree(nbd_dev); return err; } @@ -795,6 +796,7 @@ static void __exit nbd_cleanup(void) } } unregister_blkdev(NBD_MAJOR, "nbd"); + kfree(nbd_dev); printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR); } diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index a235ca7..7cb4029 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -3,8 +3,8 @@ menu "Bluetooth device drivers" depends on BT config BT_HCIUSB - tristate "HCI USB driver" - depends on USB + tristate "HCI USB driver (old version)" + depends on USB && BT_HCIBTUSB=n help Bluetooth HCI USB driver. This driver is required if you want to use Bluetooth devices with @@ -23,15 +23,13 @@ config BT_HCIUSB_SCO Say Y here to compile support for SCO over HCI USB. config BT_HCIBTUSB - tristate "HCI USB driver (alternate version)" - depends on USB && EXPERIMENTAL && BT_HCIUSB=n + tristate "HCI USB driver" + depends on USB help Bluetooth HCI USB driver. This driver is required if you want to use Bluetooth devices with USB interface. - This driver is still experimental and has no SCO support. - Say Y here to compile support for Bluetooth USB devices into the kernel or say M to compile it as module (btusb). diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 593b7c5..2705847 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -60,7 +60,7 @@ /* ======================== Module parameters ======================== */ -MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("BT3CPCC.bin"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 95ae9ba..6a01068 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2,7 +2,7 @@ * * Generic Bluetooth USB driver * - * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org> + * Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ #define BT_DBG(D...) #endif -#define VERSION "0.2" +#define VERSION "0.3" static int ignore_dga; static int ignore_csr; @@ -160,12 +160,16 @@ static struct usb_device_id blacklist_table[] = { { } /* Terminating entry */ }; +#define BTUSB_MAX_ISOC_FRAMES 10 + #define BTUSB_INTR_RUNNING 0 #define BTUSB_BULK_RUNNING 1 +#define BTUSB_ISOC_RUNNING 2 struct btusb_data { struct hci_dev *hdev; struct usb_device *udev; + struct usb_interface *isoc; spinlock_t lock; @@ -176,10 +180,15 @@ struct btusb_data { struct usb_anchor tx_anchor; struct usb_anchor intr_anchor; struct usb_anchor bulk_anchor; + struct usb_anchor isoc_anchor; struct usb_endpoint_descriptor *intr_ep; struct usb_endpoint_descriptor *bulk_tx_ep; struct usb_endpoint_descriptor *bulk_rx_ep; + struct usb_endpoint_descriptor *isoc_tx_ep; + struct usb_endpoint_descriptor *isoc_rx_ep; + + int isoc_altsetting; }; static void btusb_intr_complete(struct urb *urb) @@ -195,6 +204,8 @@ static void btusb_intr_complete(struct urb *urb) return; if (urb->status == 0) { + hdev->stat.byte_rx += urb->actual_length; + if (hci_recv_fragment(hdev, HCI_EVENT_PKT, urb->transfer_buffer, urb->actual_length) < 0) { @@ -216,7 +227,7 @@ static void btusb_intr_complete(struct urb *urb) } } -static inline int btusb_submit_intr_urb(struct hci_dev *hdev) +static int btusb_submit_intr_urb(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; struct urb *urb; @@ -226,6 +237,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + if (!data->intr_ep) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; @@ -274,6 +288,8 @@ static void btusb_bulk_complete(struct urb *urb) return; if (urb->status == 0) { + hdev->stat.byte_rx += urb->actual_length; + if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, urb->transfer_buffer, urb->actual_length) < 0) { @@ -295,7 +311,7 @@ static void btusb_bulk_complete(struct urb *urb) } } -static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) +static int btusb_submit_bulk_urb(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; struct urb *urb; @@ -305,6 +321,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + if (!data->bulk_rx_ep) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; @@ -339,6 +358,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) return err; } +static void btusb_isoc_complete(struct urb *urb) +{ + struct hci_dev *hdev = urb->context; + struct btusb_data *data = hdev->driver_data; + int i, err; + + BT_DBG("%s urb %p status %d count %d", hdev->name, + urb, urb->status, urb->actual_length); + + if (!test_bit(HCI_RUNNING, &hdev->flags)) + return; + + if (urb->status == 0) { + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int offset = urb->iso_frame_desc[i].offset; + unsigned int length = urb->iso_frame_desc[i].actual_length; + + if (urb->iso_frame_desc[i].status) + continue; + + hdev->stat.byte_rx += length; + + if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, + urb->transfer_buffer + offset, + length) < 0) { + BT_ERR("%s corrupted SCO packet", hdev->name); + hdev->stat.err_rx++; + } + } + } + + if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) + return; + + usb_anchor_urb(urb, &data->isoc_anchor); + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { + BT_ERR("%s urb %p failed to resubmit (%d)", + hdev->name, urb, -err); + usb_unanchor_urb(urb); + } +} + +static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu) +{ + int i, offset = 0; + + BT_DBG("len %d mtu %d", len, mtu); + + for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu; + i++, offset += mtu, len -= mtu) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = mtu; + } + + if (len && i < BTUSB_MAX_ISOC_FRAMES) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = len; + i++; + } + + urb->number_of_packets = i; +} + +static int btusb_submit_isoc_urb(struct hci_dev *hdev) +{ + struct btusb_data *data = hdev->driver_data; + struct urb *urb; + unsigned char *buf; + unsigned int pipe; + int err, size; + + BT_DBG("%s", hdev->name); + + if (!data->isoc_rx_ep) + return -ENODEV; + + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) * + BTUSB_MAX_ISOC_FRAMES; + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) { + usb_free_urb(urb); + return -ENOMEM; + } + + pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); + + urb->dev = data->udev; + urb->pipe = pipe; + urb->context = hdev; + urb->complete = btusb_isoc_complete; + urb->interval = data->isoc_rx_ep->bInterval; + + urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; + urb->transfer_buffer = buf; + urb->transfer_buffer_length = size; + + __fill_isoc_descriptor(urb, size, + le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); + + usb_anchor_urb(urb, &data->isoc_anchor); + + err = usb_submit_urb(urb, GFP_KERNEL); + if (err < 0) { + BT_ERR("%s urb %p submission failed (%d)", + hdev->name, urb, -err); + usb_unanchor_urb(urb); + kfree(buf); + } + + usb_free_urb(urb); + + return err; +} + static void btusb_tx_complete(struct urb *urb) { struct sk_buff *skb = urb->context; @@ -392,6 +532,9 @@ static int btusb_close(struct hci_dev *hdev) if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->intr_anchor); + clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); @@ -453,6 +596,9 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_ACLDATA_PKT: + if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; @@ -467,9 +613,31 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_SCODATA_PKT: + if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) + return -ENODEV; + + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + pipe = usb_sndisocpipe(data->udev, + data->isoc_tx_ep->bEndpointAddress); + + urb->dev = data->udev; + urb->pipe = pipe; + urb->context = skb; + urb->complete = btusb_tx_complete; + urb->interval = data->isoc_tx_ep->bInterval; + + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = skb->data; + urb->transfer_buffer_length = skb->len; + + __fill_isoc_descriptor(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); + hdev->stat.sco_tx++; - kfree_skb(skb); - return 0; + break; default: return -EILSEQ; @@ -508,22 +676,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) schedule_work(&data->work); } +static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting) +{ + struct btusb_data *data = hdev->driver_data; + struct usb_interface *intf = data->isoc; + struct usb_endpoint_descriptor *ep_desc; + int i, err; + + if (!data->isoc) + return -ENODEV; + + err = usb_set_interface(data->udev, 1, altsetting); + if (err < 0) { + BT_ERR("%s setting interface failed (%d)", hdev->name, -err); + return err; + } + + data->isoc_altsetting = altsetting; + + data->isoc_tx_ep = NULL; + data->isoc_rx_ep = NULL; + + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { + ep_desc = &intf->cur_altsetting->endpoint[i].desc; + + if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) { + data->isoc_tx_ep = ep_desc; + continue; + } + + if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) { + data->isoc_rx_ep = ep_desc; + continue; + } + } + + if (!data->isoc_tx_ep || !data->isoc_rx_ep) { + BT_ERR("%s invalid SCO descriptors", hdev->name); + return -ENODEV; + } + + return 0; +} + static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; - if (hdev->conn_hash.acl_num == 0) { + if (hdev->conn_hash.acl_num > 0) { + if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { + if (btusb_submit_bulk_urb(hdev) < 0) + clear_bit(BTUSB_BULK_RUNNING, &data->flags); + else + btusb_submit_bulk_urb(hdev); + } + } else { clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); - return; } - if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { - if (btusb_submit_bulk_urb(hdev) < 0) - clear_bit(BTUSB_BULK_RUNNING, &data->flags); - else - btusb_submit_bulk_urb(hdev); + if (hdev->conn_hash.sco_num > 0) { + if (data->isoc_altsetting != 2) { + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + if (__set_isoc_interface(hdev, 2) < 0) + return; + } + + if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { + if (btusb_submit_isoc_urb(hdev) < 0) + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + else + btusb_submit_isoc_urb(hdev); + } + } else { + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + __set_isoc_interface(hdev, 0); } } @@ -597,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->intr_anchor); init_usb_anchor(&data->bulk_anchor); + init_usb_anchor(&data->isoc_anchor); hdev = hci_alloc_dev(); if (!hdev) { @@ -620,6 +853,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->owner = THIS_MODULE; + /* interface numbers are hardcoded in the spec */ + data->isoc = usb_ifnum_to_if(data->udev, 1); + if (reset || id->driver_info & BTUSB_RESET) set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); @@ -628,11 +864,16 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); } + if (id->driver_info & BTUSB_BROKEN_ISOC) + data->isoc = NULL; + if (id->driver_info & BTUSB_SNIFFER) { - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = data->udev; if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + + data->isoc = NULL; } if (id->driver_info & BTUSB_BCM92035) { @@ -646,6 +887,16 @@ static int btusb_probe(struct usb_interface *intf, } } + if (data->isoc) { + err = usb_driver_claim_interface(&btusb_driver, + data->isoc, NULL); + if (err < 0) { + hci_free_dev(hdev); + kfree(data); + return err; + } + } + err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); @@ -670,6 +921,9 @@ static void btusb_disconnect(struct usb_interface *intf) hdev = data->hdev; + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); + usb_set_intfdata(intf, NULL); hci_unregister_dev(hdev); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 69df187..8dfcf77 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -577,7 +577,7 @@ module_exit(hci_uart_exit); module_param(reset, bool, 0644); MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index e397572..3c45392 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -1130,7 +1130,7 @@ module_param(isoc, int, 0644); MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support"); #endif -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index d97700a..7320a71 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -377,7 +377,7 @@ module_exit(vhci_exit); module_param(minor, int, 0444); MODULE_PARM_DESC(minor, "Miscellaneous minor device number"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f52931e..8e8afb6 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2695,15 +2695,13 @@ static __devinit void default_find_bmc(void) for (i = 0; ; i++) { if (!ipmi_defaults[i].port) break; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return; - #ifdef CONFIG_PPC_MERGE if (check_legacy_ioport(ipmi_defaults[i].port)) continue; #endif + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; info->addr_source = NULL; diff --git a/drivers/char/random.c b/drivers/char/random.c index e0d0e37..1838aa3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1571,6 +1571,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) return half_md4_transform(hash, keyptr->secret); } +EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index c5b1840..8b0252b 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index ffabd3b..62bda45 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 1f9c8b0..24d0d9b 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/cdev.h> -#include <linux/version.h> #include <linux/platform_device.h> #include <asm/io.h> diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index b27b13c..4b55ec6 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -34,7 +34,6 @@ #include <linux/platform_device.h> #include <linux/sysdev.h> #include <linux/workqueue.h> -#include <linux/version.h> #define EDAC_MC_LABEL_LEN 31 #define EDAC_DEVICE_NAME_LEN 31 diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index fa6d6ab..4509024 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -12,8 +12,8 @@ config FIREWIRE This is the "Juju" FireWire stack, a new alternative implementation designed for robustness and simplicity. You can build either this stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both. - Please read http://wiki.linux1394.org/JujuMigration before you - enable the new stack. + Please read http://ieee1394.wiki.kernel.org/index.php/Juju_Migration + before you enable the new stack. To compile this driver as a module, say M here: the module will be called firewire-core. diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index c1adcdb..9efb021 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/slab.h> diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 994a21e..16240a7 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -844,7 +844,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ne->host = host; ne->nodeid = nodeid; ne->generation = generation; - ne->needs_probe = 1; + ne->needs_probe = true; ne->guid = guid; ne->guid_vendor_id = (guid >> 40) & 0xffffff; @@ -1144,7 +1144,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent struct csr1212_keyval *kv, *vendor_name_kv = NULL; u8 last_key_id = 0; - ne->needs_probe = 0; + ne->needs_probe = false; csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) { switch (kv->key.id) { @@ -1295,7 +1295,7 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, nodemgr_update_bus_options(ne); /* Mark the node as new, so it gets re-probed */ - ne->needs_probe = 1; + ne->needs_probe = true; } else { /* old cache is valid, so update its generation */ struct nodemgr_csr_info *ci = ne->csr->private; @@ -1566,57 +1566,60 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge struct probe_param { struct host_info *hi; int generation; + bool probe_now; }; -static int __nodemgr_node_probe(struct device *dev, void *data) +static int node_probe(struct device *dev, void *data) { - struct probe_param *param = (struct probe_param *)data; + struct probe_param *p = data; struct node_entry *ne; + if (p->generation != get_hpsb_generation(p->hi->host)) + return -EAGAIN; + ne = container_of(dev, struct node_entry, node_dev); - if (!ne->needs_probe) - nodemgr_probe_ne(param->hi, ne, param->generation); - if (ne->needs_probe) - nodemgr_probe_ne(param->hi, ne, param->generation); + if (ne->needs_probe == p->probe_now) + nodemgr_probe_ne(p->hi, ne, p->generation); return 0; } static void nodemgr_node_probe(struct host_info *hi, int generation) { - struct hpsb_host *host = hi->host; - struct probe_param param; + struct probe_param p; - param.hi = hi; - param.generation = generation; - /* Do some processing of the nodes we've probed. This pulls them + p.hi = hi; + p.generation = generation; + /* + * Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's * unit-directories. * * Run updates before probes. Usually, updates are time-critical - * while probes are time-consuming. (Well, those probes need some - * improvement...) */ - - class_for_each_device(&nodemgr_ne_class, NULL, ¶m, - __nodemgr_node_probe); - - /* If we had a bus reset while we were scanning the bus, it is - * possible that we did not probe all nodes. In that case, we - * skip the clean up for now, since we could remove nodes that - * were still on the bus. Another bus scan is pending which will - * do the clean up eventually. + * while probes are time-consuming. * + * Meanwhile, another bus reset may have happened. In this case we + * skip everything here and let the next bus scan handle it. + * Otherwise we may prematurely remove nodes which are still there. + */ + p.probe_now = false; + if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) + return; + + p.probe_now = true; + if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) + return; + /* * Now let's tell the bus to rescan our devices. This may seem * like overhead, but the driver-model core will only scan a * device for a driver when either the device is added, or when a * new driver is added. A bus reset is a good reason to rescan * devices that were there before. For example, an sbp2 device * may become available for login, if the host that held it was - * just removed. */ - - if (generation == get_hpsb_generation(host)) - if (bus_rescan_devices(&ieee1394_bus_type)) - HPSB_DEBUG("bus_rescan_devices had an error"); + * just removed. + */ + if (bus_rescan_devices(&ieee1394_bus_type) != 0) + HPSB_DEBUG("bus_rescan_devices had an error"); } static int nodemgr_send_resume_packet(struct hpsb_host *host) diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 919e92e..6eb2646 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -97,7 +97,7 @@ struct node_entry { struct hpsb_host *host; /* Host this node is attached to */ nodeid_t nodeid; /* NodeID */ struct bus_options busopt; /* Bus Options */ - int needs_probe; + bool needs_probe; unsigned int generation; /* Synced with hpsb generation */ /* The following is read from the config rom */ diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 9cbf315..1d6ad34 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -731,15 +731,26 @@ static int sbp2_update(struct unit_directory *ud) { struct sbp2_lu *lu = ud->device.driver_data; - if (sbp2_reconnect_device(lu)) { - /* Reconnect has failed. Perhaps we didn't reconnect fast - * enough. Try a regular login, but first log out just in - * case of any weirdness. */ + if (sbp2_reconnect_device(lu) != 0) { + /* + * Reconnect failed. If another bus reset happened, + * let nodemgr proceed and call sbp2_update again later + * (or sbp2_remove if this node went away). + */ + if (!hpsb_node_entry_valid(lu->ne)) + return 0; + /* + * Or the target rejected the reconnect because we weren't + * fast enough. Try a regular login, but first log out + * just in case of any weirdness. + */ sbp2_logout_device(lu); - if (sbp2_login_device(lu)) { - /* Login failed too, just fail, and the backend - * will call our sbp2_remove for us */ + if (sbp2_login_device(lu) != 0) { + if (!hpsb_node_entry_valid(lu->ne)) + return 0; + + /* Maybe another initiator won the login. */ SBP2_ERR("Failed to reconnect to sbp2 device!"); return -EBUSY; } diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index ec950bf..21f7d06 100644 --- a/drivers/infiniband/hw/ehca/ehca_tools.h +++ b/drivers/infiniband/hw/ehca/ehca_tools.h @@ -54,7 +54,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/vmalloc.h> -#include <linux/version.h> #include <linux/notifier.h> #include <linux/cpu.h> #include <linux/device.h> diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 23faba9..8bb5170 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/mount.h> diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c index d90f5e9..9839e20 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba7220.c +++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c @@ -1720,7 +1720,7 @@ static void ipath_7220_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr, "not 2KB aligned!\n", pa); return; } - if (pa >= (1UL << IBA7220_TID_SZ_SHIFT)) { + if (chippa >= (1UL << IBA7220_TID_SZ_SHIFT)) { ipath_dev_err(dd, "BUG: Physical page address 0x%lx " "larger than supported\n", pa); diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 36aa242..729446f 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c @@ -267,6 +267,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) u16 lrh0; u16 lid; int ret = 0; + int next_cur; spin_lock_irqsave(&qp->s_lock, flags); @@ -290,8 +291,9 @@ int ipath_make_ud_req(struct ipath_qp *qp) goto bail; wqe = get_swqe_ptr(qp, qp->s_cur); - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; + next_cur = qp->s_cur + 1; + if (next_cur >= qp->s_size) + next_cur = 0; /* Construct the header. */ ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr; @@ -315,6 +317,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) qp->s_flags |= IPATH_S_WAIT_DMA; goto bail; } + qp->s_cur = next_cur; spin_unlock_irqrestore(&qp->s_lock, flags); ipath_ud_loopback(qp, wqe); spin_lock_irqsave(&qp->s_lock, flags); @@ -323,6 +326,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) } } + qp->s_cur = next_cur; extra_bytes = -wqe->length & 3; nwords = (wqe->length + extra_bytes) >> 2; diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 39bd897..8eb7ae9 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -43,7 +43,6 @@ #include <linux/dma-mapping.h> #include <linux/workqueue.h> #include <linux/slab.h> -#include <linux/version.h> #include <asm/io.h> #include <linux/crc32c.h> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index f51201b..7e9e218 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -156,14 +156,8 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - /* - * Now flush workqueue to make sure a scheduled task doesn't - * bring our internal state back up. - */ - flush_workqueue(ipoib_workqueue); - - ipoib_ib_dev_down(dev, 1); - ipoib_ib_dev_stop(dev, 1); + ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_stop(dev, 0); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { struct ipoib_dev_priv *cpriv; @@ -1314,7 +1308,7 @@ sysfs_failed: register_failed: ib_unregister_event_handler(&priv->event_handler); - flush_scheduled_work(); + flush_workqueue(ipoib_workqueue); event_failed: ipoib_dev_cleanup(priv->dev); @@ -1373,7 +1367,12 @@ static void ipoib_remove_one(struct ib_device *device) list_for_each_entry_safe(priv, tmp, dev_list, list) { ib_unregister_event_handler(&priv->event_handler); - flush_scheduled_work(); + + rtnl_lock(); + dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); + rtnl_unlock(); + + flush_workqueue(ipoib_workqueue); unregister_netdev(priv->dev); ipoib_dev_cleanup(priv->dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 8950e95..ac33c8f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -392,8 +392,16 @@ static int ipoib_mcast_join_complete(int status, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); - if (mcast == priv->broadcast) + if (mcast == priv->broadcast) { + /* + * Take RTNL lock here to avoid racing with + * ipoib_stop() and turning the carrier back + * on while a device is being removed. + */ + rtnl_lock(); netif_carrier_on(dev); + rtnl_unlock(); + } return 0; } diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 63462ec..26ff621 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -33,7 +33,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/version.h> #include "iscsi_iser.h" diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a92d815..3524bef 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -677,8 +677,8 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user len = OLD_KEY_MAX; if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) printk(KERN_WARNING - "evdev.c(EVIOCGBIT): Suspicious buffer size %d, " - "limiting output to %d bytes. See " + "evdev.c(EVIOCGBIT): Suspicious buffer size %u, " + "limiting output to %zu bytes. See " "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", OLD_KEY_MAX, BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 54ed8e2..6f227d3 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -29,7 +29,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/fs.h> diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 3f48279..ec96b36 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -9,7 +9,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/fs.h> diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 6a1f48b..2adf9cb 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) return 0; } +MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); +MODULE_DESCRIPTION("Cobalt button interface driver"); +MODULE_LICENSE("GPL"); /* work with hotplug and coldplug */ MODULE_ALIAS("platform:Cobalt buttons"); diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 3392901..72cf5e3 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -9,7 +9,6 @@ */ #include <linux/init.h> -#include <linux/version.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/input-polldev.h> diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index b9b7a98..7df0228 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -64,7 +64,6 @@ Scott Hill shill@gtcocalcomp.com #include <asm/byteorder.h> -#include <linux/version.h> #include <linux/usb/input.h> /* Version with a Major number of 2 is for kernel inclusion only. */ diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 283f93a..37a555f 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -25,7 +25,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index c1cd99d..504ca11 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -173,7 +173,7 @@ static int migor_ts_probe(struct i2c_client *client, input_set_abs_params(input, ABS_X, 95, 955, 0, 0); input_set_abs_params(input, ABS_Y, 85, 935, 0, 0); - input->name = client->driver_name; + input->name = client->name; input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; @@ -192,7 +192,7 @@ static int migor_ts_probe(struct i2c_client *client, goto err1; error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW, - client->driver_name, priv); + client->name, priv); if (error) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); goto err2; @@ -224,12 +224,19 @@ static int migor_ts_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id migor_ts_id[] = { + { "migor_ts", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, migor_ts); + static struct i2c_driver migor_ts_driver = { .driver = { .name = "migor_ts", }, .probe = migor_ts_probe, .remove = migor_ts_remove, + .id_table = migor_ts_id, }; static int __init migor_ts_init(void) diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 978e1a1..372efbc 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/input.h> #include <linux/delay.h> diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 4c5d85a..c8bb1e7 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/input.h> #include <linux/delay.h> diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 8384587..781ee83 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -17,7 +17,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/input.h> #include <linux/delay.h> diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index cdc24ad..d589ab0 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -37,7 +37,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c6408a6..bc2a807 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -16,7 +16,6 @@ * */ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/irq.h> #include <linux/gpio.h> diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index b2d9878..c6c77a5 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -192,6 +192,9 @@ static struct quirk_entry *quirks; static void set_quirks(void) { + if (!interface) + return; + if (quirks->mailled) interface->capability |= ACER_CAP_MAILLED; @@ -1237,6 +1240,8 @@ static int __init acer_wmi_init(void) return -ENODEV; } + set_quirks(); + if (platform_driver_register(&acer_platform_driver)) { printk(ACER_ERR "Unable to register platform driver.\n"); goto error_platform_register; diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 9e8d79e..facdb98 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -553,9 +553,9 @@ static void eeepc_hwmon_exit(void) hwmon = eeepc_hwmon_device; if (!hwmon) return ; - hwmon_device_unregister(hwmon); sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group); + hwmon_device_unregister(hwmon); eeepc_hwmon_device = NULL; } diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c index ea55654..15b1780 100644 --- a/drivers/misc/eeprom_93cx6.c +++ b/drivers/misc/eeprom_93cx6.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/delay.h> #include <linux/eeprom_93cx6.h> diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 948b86f3..d1eec7d 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index effaf7c..1a6feb4 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index aa64a47..bbbcdd4 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 761946e..92c334f 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -16,7 +16,6 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> -#include <linux/version.h> #include <asm/io.h> #include <asm/mach-au1x00/au1xxx.h> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4b4cb2b..a5c141c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1172,7 +1172,7 @@ config ETH16I config NE2000 tristate "NE2000/NE1000 support" - depends on NET_ISA || (Q40 && m) || M32R || TOSHIBA_RBTX4927 || TOSHIBA_RBTX4938 + depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index e4483de..66de80b 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -52,7 +52,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/ioport.h> diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 020771b..e2d702b 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -551,7 +551,7 @@ static int eth_poll(struct napi_struct *napi, int budget) if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) { phys = dma_map_single(&dev->dev, skb->data, RX_BUFF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(phys)) { + if (dma_mapping_error(&dev->dev, phys)) { dev_kfree_skb(skb); skb = NULL; } @@ -698,7 +698,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) #endif phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); - if (dma_mapping_error(phys)) { + if (dma_mapping_error(&dev->dev, phys)) { #ifdef __ARMEB__ dev_kfree_skb(skb); #else @@ -883,7 +883,7 @@ static int init_queues(struct port *port) desc->buf_len = MAX_MRU; desc->data = dma_map_single(&port->netdev->dev, data, RX_BUFF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(desc->data)) { + if (dma_mapping_error(&port->netdev->dev, desc->data)) { free_buffer(buff); return -EIO; } diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index cdc3b85..619c658 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c @@ -355,7 +355,7 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct atl1e_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_MCAST | WAKE_BCAST | WAKE_MCAST)) + WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) return -EOPNOTSUPP; /* these settings will always override what we currently have */ adapter->wol = 0; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index cb8be49..5ee1b05 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -807,7 +807,7 @@ err_out: static int au1000_init(struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; - u32 flags; + unsigned long flags; int i; u32 control; diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 0b4adf4..a886a4b 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -554,7 +554,7 @@ static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irqsave(&ax->mii_lock, flags); mii_ethtool_gset(&ax->mii, cmd); - spin_lock_irqsave(&ax->mii_lock, flags); + spin_unlock_irqrestore(&ax->mii_lock, flags); return 0; } @@ -567,7 +567,7 @@ static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irqsave(&ax->mii_lock, flags); rc = mii_ethtool_sset(&ax->mii, cmd); - spin_lock_irqsave(&ax->mii_lock, flags); + spin_unlock_irqrestore(&ax->mii_lock, flags); return rc; } diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5ebde67..2486a65 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -35,8 +35,8 @@ #include <linux/time.h> #include <linux/ethtool.h> #include <linux/mii.h> -#ifdef NETIF_F_HW_VLAN_TX #include <linux/if_vlan.h> +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define BCM_VLAN 1 #endif #include <net/ip.h> @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.7.9" -#define DRV_MODULE_RELDATE "July 18, 2008" +#define DRV_MODULE_VERSION "1.8.0" +#define DRV_MODULE_RELDATE "Aug 14, 2008" #define RUN_AT(x) (jiffies + (x)) @@ -2876,6 +2876,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) struct sw_bd *rx_buf; struct sk_buff *skb; dma_addr_t dma_addr; + u16 vtag = 0; + int hw_vlan __maybe_unused = 0; sw_ring_cons = RX_RING_IDX(sw_cons); sw_ring_prod = RX_RING_IDX(sw_prod); @@ -2919,7 +2921,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) if (len <= bp->rx_copy_thresh) { struct sk_buff *new_skb; - new_skb = netdev_alloc_skb(bp->dev, len + 2); + new_skb = netdev_alloc_skb(bp->dev, len + 6); if (new_skb == NULL) { bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons, sw_ring_prod); @@ -2928,9 +2930,9 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) /* aligned copy */ skb_copy_from_linear_data_offset(skb, - BNX2_RX_OFFSET - 2, - new_skb->data, len + 2); - skb_reserve(new_skb, 2); + BNX2_RX_OFFSET - 6, + new_skb->data, len + 6); + skb_reserve(new_skb, 6); skb_put(new_skb, len); bnx2_reuse_rx_skb(bp, rxr, skb, @@ -2941,6 +2943,25 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) dma_addr, (sw_ring_cons << 16) | sw_ring_prod))) goto next_rx; + if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && + !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) { + vtag = rx_hdr->l2_fhdr_vlan_tag; +#ifdef BCM_VLAN + if (bp->vlgrp) + hw_vlan = 1; + else +#endif + { + struct vlan_ethhdr *ve = (struct vlan_ethhdr *) + __skb_push(skb, 4); + + memmove(ve, skb->data + 4, ETH_ALEN * 2); + ve->h_vlan_proto = htons(ETH_P_8021Q); + ve->h_vlan_TCI = htons(vtag); + len += 4; + } + } + skb->protocol = eth_type_trans(skb, bp->dev); if ((len > (bp->dev->mtu + ETH_HLEN)) && @@ -2962,10 +2983,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) } #ifdef BCM_VLAN - if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && bp->vlgrp) { - vlan_hwaccel_receive_skb(skb, bp->vlgrp, - rx_hdr->l2_fhdr_vlan_tag); - } + if (hw_vlan) + vlan_hwaccel_receive_skb(skb, bp->vlgrp, vtag); else #endif netif_receive_skb(skb); @@ -3237,10 +3256,10 @@ bnx2_set_rx_mode(struct net_device *dev) BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG); sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN; #ifdef BCM_VLAN - if (!bp->vlgrp && !(bp->flags & BNX2_FLAG_ASF_ENABLE)) + if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; #else - if (!(bp->flags & BNX2_FLAG_ASF_ENABLE)) + if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; #endif if (dev->flags & IFF_PROMISC) { @@ -5963,10 +5982,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; } +#ifdef BCM_VLAN if (bp->vlgrp && vlan_tx_tag_present(skb)) { vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } +#endif if ((mss = skb_shinfo(skb)->gso_size)) { u32 tcp_opt_len, ip_tcp_len; struct iphdr *iph; diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 8b92c6a..4ce7fe9 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -21,7 +21,6 @@ #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mutex.h> -#include <linux/version.h> #include "bnx2x_reg.h" #include "bnx2x_fw_defs.h" diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 3e7dc17..971576b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -44,7 +44,6 @@ #include <net/ip.h> #include <net/tcp.h> #include <net/checksum.h> -#include <linux/version.h> #include <net/ip6_checksum.h> #include <linux/workqueue.h> #include <linux/crc32.h> diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index a7800e5..ec6b0af 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -26,7 +26,6 @@ #include <linux/errno.h> #include <linux/types.h> #include <linux/delay.h> -#include <linux/version.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index f823b8b..14b0e6c 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -389,7 +389,7 @@ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ /* Transmit Descriptor Control */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cf57050..ac4e506 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -326,6 +326,7 @@ struct e1000_info { #define FLAG_RX_CSUM_ENABLED (1 << 28) #define FLAG_TSO_FORCE (1 << 29) #define FLAG_RX_RESTART_NOW (1 << 30) +#define FLAG_MSI_TEST_FAILED (1 << 31) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index cf9679f..e21c9e0 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -177,7 +177,7 @@ static u32 e1000_get_link(struct net_device *netdev) u32 status; status = er32(STATUS); - return (status & E1000_STATUS_LU); + return (status & E1000_STATUS_LU) ? 1 : 0; } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 05b0b2f..d266510 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -510,9 +510,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, netdev_alloc_skb(netdev, length + NET_IP_ALIGN); if (new_skb) { skb_reserve(new_skb, NET_IP_ALIGN); - memcpy(new_skb->data - NET_IP_ALIGN, - skb->data - NET_IP_ALIGN, - length + NET_IP_ALIGN); + skb_copy_to_linear_data_offset(new_skb, + -NET_IP_ALIGN, + (skb->data - + NET_IP_ALIGN), + (length + + NET_IP_ALIGN)); /* save the skb in buffer_info as good */ buffer_info->skb = skb; skb = new_skb; @@ -1233,26 +1236,36 @@ static irqreturn_t e1000_intr(int irq, void *data) return IRQ_HANDLED; } +/** + * e1000_request_irq - initialize interrupts + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ static int e1000_request_irq(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - irq_handler_t handler = e1000_intr; int irq_flags = IRQF_SHARED; int err; - if (!pci_enable_msi(adapter->pdev)) { - adapter->flags |= FLAG_MSI_ENABLED; - handler = e1000_intr_msi; - irq_flags = 0; + if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) { + err = pci_enable_msi(adapter->pdev); + if (!err) { + adapter->flags |= FLAG_MSI_ENABLED; + irq_flags = 0; + } } - err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, - netdev); + err = request_irq(adapter->pdev->irq, + ((adapter->flags & FLAG_MSI_ENABLED) ? + &e1000_intr_msi : &e1000_intr), + irq_flags, netdev->name, netdev); if (err) { - e_err("Unable to allocate %s interrupt (return: %d)\n", - adapter->flags & FLAG_MSI_ENABLED ? "MSI":"INTx", err); - if (adapter->flags & FLAG_MSI_ENABLED) + if (adapter->flags & FLAG_MSI_ENABLED) { pci_disable_msi(adapter->pdev); + adapter->flags &= ~FLAG_MSI_ENABLED; + } + e_err("Unable to allocate interrupt, Error: %d\n", err); } return err; @@ -2592,6 +2605,135 @@ err: } /** + * e1000_intr_msi_test - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +static irqreturn_t e1000_intr_msi_test(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + + e_dbg("%s: icr is %08X\n", netdev->name, icr); + if (icr & E1000_ICR_RXSEQ) { + adapter->flags &= ~FLAG_MSI_TEST_FAILED; + wmb(); + } + + return IRQ_HANDLED; +} + +/** + * e1000_test_msi_interrupt - Returns 0 for successful test + * @adapter: board private struct + * + * code flow taken from tg3.c + **/ +static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + int err; + + /* poll_enable hasn't been called yet, so don't need disable */ + /* clear any pending events */ + er32(ICR); + + /* free the real vector and request a test handler */ + e1000_free_irq(adapter); + + /* Assume that the test fails, if it succeeds then the test + * MSI irq handler will unset this flag */ + adapter->flags |= FLAG_MSI_TEST_FAILED; + + err = pci_enable_msi(adapter->pdev); + if (err) + goto msi_test_failed; + + err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0, + netdev->name, netdev); + if (err) { + pci_disable_msi(adapter->pdev); + goto msi_test_failed; + } + + wmb(); + + e1000_irq_enable(adapter); + + /* fire an unusual interrupt on the test handler */ + ew32(ICS, E1000_ICS_RXSEQ); + e1e_flush(); + msleep(50); + + e1000_irq_disable(adapter); + + rmb(); + + if (adapter->flags & FLAG_MSI_TEST_FAILED) { + err = -EIO; + e_info("MSI interrupt test failed!\n"); + } + + free_irq(adapter->pdev->irq, netdev); + pci_disable_msi(adapter->pdev); + + if (err == -EIO) + goto msi_test_failed; + + /* okay so the test worked, restore settings */ + e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name); +msi_test_failed: + /* restore the original vector, even if it failed */ + e1000_request_irq(adapter); + return err; +} + +/** + * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored + * @adapter: board private struct + * + * code flow taken from tg3.c, called with e1000 interrupts disabled. + **/ +static int e1000_test_msi(struct e1000_adapter *adapter) +{ + int err; + u16 pci_cmd; + + if (!(adapter->flags & FLAG_MSI_ENABLED)) + return 0; + + /* disable SERR in case the MSI write causes a master abort */ + pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); + pci_write_config_word(adapter->pdev, PCI_COMMAND, + pci_cmd & ~PCI_COMMAND_SERR); + + err = e1000_test_msi_interrupt(adapter); + + /* restore previous setting of command word */ + pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); + + /* success ! */ + if (!err) + return 0; + + /* EIO means MSI test failed */ + if (err != -EIO) + return err; + + /* back to INTx mode */ + e_warn("MSI interrupt test failed, using legacy interrupt.\n"); + + e1000_free_irq(adapter); + + err = e1000_request_irq(adapter); + + return err; +} + +/** * e1000_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -2649,6 +2791,19 @@ static int e1000_open(struct net_device *netdev) if (err) goto err_req_irq; + /* + * Work around PCIe errata with MSI interrupts causing some chipsets to + * ignore e1000e MSI messages, which means we need to test our MSI + * interrupt now + */ + { + err = e1000_test_msi(adapter); + if (err) { + e_err("Interrupt allocation failed\n"); + goto err_req_irq; + } + } + /* From here on the code is the same as e1000e_up() */ clear_bit(__E1000_DOWN, &adapter->state); @@ -3055,7 +3210,7 @@ static void e1000_watchdog_task(struct work_struct *work) case SPEED_10: txb2b = 0; netdev->tx_queue_len = 10; - adapter->tx_timeout_factor = 14; + adapter->tx_timeout_factor = 16; break; case SPEED_100: txb2b = 0; @@ -3721,7 +3876,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || + if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { e_err("Invalid MTU setting\n"); return -EINVAL; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index 8effc31..ed912e0 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -324,14 +324,27 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) adapter->itr = 20000; break; default: - e1000_validate_option(&adapter->itr, &opt, - adapter); /* - * save the setting, because the dynamic bits - * change itr. clear the lower two bits - * because they are used as control + * Save the setting, because the dynamic bits + * change itr. */ - adapter->itr_setting = adapter->itr & ~3; + if (e1000_validate_option(&adapter->itr, &opt, + adapter) && + (adapter->itr == 3)) { + /* + * In case of invalid user value, + * default to conservative mode. + */ + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + } else { + /* + * Clear the lower two bits because + * they are used as control. + */ + adapter->itr_setting = + adapter->itr & ~3; + } break; } } else { diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ca6cf6e..999d691 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -134,9 +134,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l static void gfar_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); void gfar_halt(struct net_device *dev); -#ifdef CONFIG_PM static void gfar_halt_nodisable(struct net_device *dev); -#endif void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); @@ -631,7 +629,6 @@ static void init_registers(struct net_device *dev) } -#ifdef CONFIG_PM /* Halt the receive and transmit queues */ static void gfar_halt_nodisable(struct net_device *dev) { @@ -657,7 +654,6 @@ static void gfar_halt_nodisable(struct net_device *dev) cpu_relax(); } } -#endif /* Halt the receive and transmit queues */ void gfar_halt(struct net_device *dev) @@ -666,6 +662,8 @@ void gfar_halt(struct net_device *dev) struct gfar __iomem *regs = priv->regs; u32 tempval; + gfar_halt_nodisable(dev); + /* Disable Rx and Tx */ tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 5116f68..782c201 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c @@ -33,7 +33,6 @@ #include <asm/uaccess.h> #include <linux/module.h> -#include <linux/version.h> #include "gianfar.h" diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h index e0e718a..dd9318f 100644 --- a/drivers/net/ipg.h +++ b/drivers/net/ipg.h @@ -7,7 +7,6 @@ #ifndef __LINUX_IPG_H #define __LINUX_IPG_H -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> @@ -21,7 +20,6 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/skbuff.h> -#include <linux/version.h> #include <asm/bitops.h> /* diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 2f38e84..f96358b 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -190,6 +190,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82598AT_DUAL_PORT: diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e5f3da8..34bca16 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "1.3.18-k2" +#define DRV_VERSION "1.3.18-k4" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; @@ -72,6 +72,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), + board_82598 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 1ad7cb9..c0282a2 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -39,6 +39,7 @@ #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD +#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC /* General Registers */ #define IXGBE_CTRL 0x00000 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 49f6bc0..3b43bfd 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -64,68 +64,6 @@ struct pcpu_lstats { unsigned long bytes; }; -/* KISS: just allocate small chunks and copy bits. - * - * So, in fact, this is documentation, explaining what we expect - * of largesending device modulo TCP checksum, which is ignored for loopback. - */ - -#ifdef LOOPBACK_TSO -static void emulate_large_send_offload(struct sk_buff *skb) -{ - struct iphdr *iph = ip_hdr(skb); - struct tcphdr *th = (struct tcphdr *)(skb_network_header(skb) + - (iph->ihl * 4)); - unsigned int doffset = (iph->ihl + th->doff) * 4; - unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; - unsigned int offset = 0; - u32 seq = ntohl(th->seq); - u16 id = ntohs(iph->id); - - while (offset + doffset < skb->len) { - unsigned int frag_size = min(mtu, skb->len - offset) - doffset; - struct sk_buff *nskb = alloc_skb(mtu + 32, GFP_ATOMIC); - - if (!nskb) - break; - skb_reserve(nskb, 32); - skb_set_mac_header(nskb, -ETH_HLEN); - skb_reset_network_header(nskb); - iph = ip_hdr(nskb); - skb_copy_to_linear_data(nskb, skb_network_header(skb), - doffset); - if (skb_copy_bits(skb, - doffset + offset, - nskb->data + doffset, - frag_size)) - BUG(); - skb_put(nskb, doffset + frag_size); - nskb->ip_summed = CHECKSUM_UNNECESSARY; - nskb->dev = skb->dev; - nskb->priority = skb->priority; - nskb->protocol = skb->protocol; - nskb->dst = dst_clone(skb->dst); - memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); - nskb->pkt_type = skb->pkt_type; - - th = (struct tcphdr *)(skb_network_header(nskb) + iph->ihl * 4); - iph->tot_len = htons(frag_size + doffset); - iph->id = htons(id); - iph->check = 0; - iph->check = ip_fast_csum((unsigned char *) iph, iph->ihl); - th->seq = htonl(seq); - if (offset + doffset + frag_size < skb->len) - th->fin = th->psh = 0; - netif_rx(nskb); - offset += frag_size; - seq += frag_size; - id++; - } - - dev_kfree_skb(skb); -} -#endif /* LOOPBACK_TSO */ - /* * The higher levels take care of making this non-reentrant (it's * called with bh's disabled). @@ -137,9 +75,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) skb_orphan(skb); skb->protocol = eth_type_trans(skb,dev); -#ifndef LOOPBACK_MUST_CHECKSUM - skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif #ifdef LOOPBACK_TSO if (skb_is_gso(skb)) { @@ -234,9 +169,7 @@ static void loopback_setup(struct net_device *dev) dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ dev->flags = IFF_LOOPBACK; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST -#ifdef LOOPBACK_TSO | NETIF_F_TSO -#endif | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f1de38f..54cd89c 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -56,7 +56,6 @@ #include <linux/ethtool.h> #include <linux/firmware.h> #include <linux/delay.h> -#include <linux/version.h> #include <linux/timer.h> #include <linux/vmalloc.h> #include <linux/crc32.h> @@ -3548,7 +3547,11 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) /* try to load the slice aware rss firmware */ old_fw = mgp->fw_name; - if (old_fw == myri10ge_fw_aligned) + if (myri10ge_fw_name != NULL) { + dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", + myri10ge_fw_name); + mgp->fw_name = myri10ge_fw_name; + } else if (old_fw == myri10ge_fw_aligned) mgp->fw_name = myri10ge_fw_rss_aligned; else mgp->fw_name = myri10ge_fw_rss_unaligned; diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 42443d6..fa3ceca 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -118,7 +118,7 @@ bad_clone_list[] __initdata = { {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */ {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */ -#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) +#ifdef CONFIG_MACH_TX49XX {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */ #endif {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */ @@ -142,7 +142,7 @@ bad_clone_list[] __initdata = { #if defined(CONFIG_PLAT_MAPPI) # define DCR_VAL 0x4b #elif defined(CONFIG_PLAT_OAKS32R) || \ - defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) + defined(CONFIG_MACH_TX49XX) # define DCR_VAL 0x48 /* 8-bit mode */ #else # define DCR_VAL 0x49 diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 93a7b9b..244ab49 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -45,7 +45,6 @@ #include <linux/in.h> #include <linux/tcp.h> #include <linux/skbuff.h> -#include <linux/version.h> #include <linux/ethtool.h> #include <linux/mii.h> @@ -66,8 +65,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 0 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.0" +#define _NETXEN_NIC_LINUX_SUBVERSION 11 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.11" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) @@ -1615,7 +1614,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) int netxen_is_flash_supported(struct netxen_adapter *adapter); -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]); +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 4ad3e08..b974ca0 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -38,7 +38,6 @@ #include <asm/io.h> #include <linux/netdevice.h> #include <linux/ethtool.h> -#include <linux/version.h> #include "netxen_nic.h" #include "netxen_nic_hw.h" diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index e8e8d73..e80f9e3 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -32,8 +32,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/version.h> - #include <linux/spinlock.h> #include <asm/irq.h> #include <linux/init.h> diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9aa20f9..84978f8 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -733,31 +733,56 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, return 0; } -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]) +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) { - __le32 *pmac = (__le32 *) & mac[0]; + __le32 *pmac = (__le32 *) mac; + u32 offset; - if (netxen_get_flash_block(adapter, - NETXEN_USER_START + - offsetof(struct netxen_new_user_info, - mac_addr), - FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) { + offset = NETXEN_USER_START + + offsetof(struct netxen_new_user_info, mac_addr) + + adapter->portnum * sizeof(u64); + + if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) return -1; - } + if (*mac == cpu_to_le64(~0ULL)) { + + offset = NETXEN_USER_START_OLD + + offsetof(struct netxen_user_old_info, mac_addr) + + adapter->portnum * sizeof(u64); + if (netxen_get_flash_block(adapter, - NETXEN_USER_START_OLD + - offsetof(struct netxen_user_old_info, - mac_addr), - FLASH_NUM_PORTS * sizeof(u64), - pmac) == -1) + offset, sizeof(u64), pmac) == -1) return -1; + if (*mac == cpu_to_le64(~0ULL)) return -1; } return 0; } +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) +{ + uint32_t crbaddr, mac_hi, mac_lo; + int pci_func = adapter->ahw.pci_func; + + crbaddr = CRB_MAC_BLOCK_START + + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); + + adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); + adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); + + mac_hi = cpu_to_le32(mac_hi); + mac_lo = cpu_to_le32(mac_lo); + + if (pci_func & 1) + *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16)); + else + *mac = ((mac_lo) | ((u64)mac_hi << 32)); + + return 0; +} + #define CRB_WIN_LOCK_TIMEOUT 100000000 static int crb_win_lock(struct netxen_adapter *adapter) @@ -2183,10 +2208,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) if (adapter->portnum == 0) { get_brd_name_by_type(board_info->board_type, brd_name); - printk("NetXen %s Board S/N %s Chip id 0x%x\n", - brd_name, serial_num, board_info->chip_id); - printk("NetXen Firmware version %d.%d.%d\n", fw_major, - fw_minor, fw_build); + printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", + brd_name, serial_num, adapter->ahw.revision_id); + printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n", + fw_major, fw_minor, fw_build); } if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) < diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 519fc86..5bba675 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1079,10 +1079,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) void netxen_free_adapter_offload(struct netxen_adapter *adapter) { - int i; + int i = 100; + + if (!adapter->dummy_dma.addr) + return; - if (adapter->dummy_dma.addr) { - i = 100; + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { do { if (dma_watchdog_shutdown_request(adapter) == 1) break; @@ -1090,17 +1092,17 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) if (dma_watchdog_shutdown_poll_result(adapter) == 1) break; } while (--i); + } - if (i) { - pci_free_consistent(adapter->pdev, - NETXEN_HOST_DUMMY_DMA_SIZE, - adapter->dummy_dma.addr, - adapter->dummy_dma.phys_addr); - adapter->dummy_dma.addr = NULL; - } else { - printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", - adapter->netdev->name); - } + if (i) { + pci_free_consistent(adapter->pdev, + NETXEN_HOST_DUMMY_DMA_SIZE, + adapter->dummy_dma.addr, + adapter->dummy_dma.phys_addr); + adapter->dummy_dma.addr = NULL; + } else { + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + adapter->netdev->name); } } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 7615c71..32bb47a 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -149,76 +149,18 @@ static uint32_t msi_tgt_status[8] = { static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; -static void netxen_nic_disable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) { - u32 mask = 0x7ff; - int retries = 32; - int pci_fn = adapter->ahw.pci_func; - - if (adapter->msi_mode != MSI_MODE_MULTIFUNC) - adapter->pci_write_normalize(adapter, - adapter->crb_intr_mask, 0); - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) - adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask); - - if (!NETXEN_IS_MSI_FAMILY(adapter)) { - do { - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_status_reg, - 0xffffffff); - mask = adapter->pci_read_immediate(adapter, - ISR_INT_VECTOR); - if (!(mask & 0x80)) - break; - udelay(10); - } while (--retries); - - if (!retries) { - printk(KERN_NOTICE "%s: Failed to disable interrupt\n", - netxen_nic_driver_name); - } - } else { - if (adapter->msi_mode == MSI_MODE_MULTIFUNC) { - adapter->pci_write_immediate(adapter, - msi_tgt_status[pci_fn], 0xffffffff); - } - } + adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0); } -static void netxen_nic_enable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) { - u32 mask; - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) { - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - mask = 0x77b; - break; - case NETXEN_NIC_XGBE: - mask = 0x77f; - break; - default: - mask = 0x7ff; - break; - } - - adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask); - } - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1); - if (!NETXEN_IS_MSI_FAMILY(adapter)) { - mask = 0xbff; - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_mask_reg, mask); - else - adapter->pci_write_normalize(adapter, - CRB_INT_VECTOR, 0); - } + if (!NETXEN_IS_MSI_FAMILY(adapter)) + adapter->pci_write_immediate(adapter, + adapter->legacy_intr.tgt_mask_reg, 0xfbff); } static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id) @@ -501,6 +443,44 @@ static void netxen_init_msix_entries(struct netxen_adapter *adapter) adapter->msix_entries[i].entry = i; } +static int +netxen_read_mac_addr(struct netxen_adapter *adapter) +{ + int i; + unsigned char *p; + __le64 mac_addr; + DECLARE_MAC_BUF(mac); + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + + if (netxen_is_flash_supported(adapter) != 0) + return -EIO; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0) + return -EIO; + } else { + if (netxen_get_flash_mac_addr(adapter, &mac_addr) != 0) + return -EIO; + } + + p = (unsigned char *)&mac_addr; + for (i = 0; i < 6; i++) + netdev->dev_addr[i] = *(p + 5 - i); + + memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); + + /* set station address */ + + if (!is_valid_ether_addr(netdev->perm_addr)) { + dev_warn(&pdev->dev, "Bad MAC address %s.\n", + print_mac(mac, netdev->dev_addr)); + } else + adapter->macaddr_set(adapter, netdev->dev_addr); + + return 0; +} + /* * netxen_nic_probe() * @@ -529,10 +509,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0; int i = 0, err; int first_driver, first_boot; - __le64 mac_addr[FLASH_NUM_PORTS + 1]; u32 val; int pci_func_id = PCI_FUNC(pdev->devfn); - DECLARE_MAC_BUF(mac); struct netxen_legacy_intr_set *legacy_intrp; uint8_t revision_id; @@ -545,6 +523,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) { + printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x" + "will not be enabled.\n", + NX_P3_A0, NX_P3_B1); + return -ENODEV; + } + if ((err = pci_enable_device(pdev))) return err; @@ -898,34 +883,14 @@ request_msi: goto err_out_disable_msi; init_timer(&adapter->watchdog_timer); - adapter->ahw.linkup = 0; adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); - if (netxen_is_flash_supported(adapter) == 0 && - netxen_get_flash_mac_addr(adapter, mac_addr) == 0) { - unsigned char *p; - - p = (unsigned char *)&mac_addr[adapter->portnum]; - netdev->dev_addr[0] = *(p + 5); - netdev->dev_addr[1] = *(p + 4); - netdev->dev_addr[2] = *(p + 3); - netdev->dev_addr[3] = *(p + 2); - netdev->dev_addr[4] = *(p + 1); - netdev->dev_addr[5] = *(p + 0); - - memcpy(netdev->perm_addr, netdev->dev_addr, - netdev->addr_len); - if (!is_valid_ether_addr(netdev->perm_addr)) { - printk(KERN_ERR "%s: Bad MAC address %s.\n", - netxen_nic_driver_name, - print_mac(mac, netdev->dev_addr)); - } else { - adapter->macaddr_set(adapter, netdev->dev_addr); - } - } + err = netxen_read_mac_addr(adapter); + if (err) + dev_warn(&pdev->dev, "failed to read mac addr\n"); netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -1000,6 +965,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { netxen_free_hw_resources(adapter); + netxen_release_rx_buffers(adapter); netxen_free_sw_resources(adapter); } @@ -1069,6 +1035,15 @@ static int netxen_nic_open(struct net_device *netdev) goto err_out_free_sw; } + if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || + (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { + printk(KERN_ERR "%s: Firmware interrupt scheme is " + "incompatible with driver\n", + netdev->name); + adapter->driver_mismatch = 1; + goto err_out_free_hw; + } + if (adapter->fw_major < 4) { adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum]; @@ -1094,7 +1069,7 @@ static int netxen_nic_open(struct net_device *netdev) flags, netdev->name, adapter); if (err) { printk(KERN_ERR "request_irq failed with: %d\n", err); - goto err_out_free_hw; + goto err_out_free_rxbuf; } adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; @@ -1116,6 +1091,7 @@ static int netxen_nic_open(struct net_device *netdev) if (adapter->set_mtu) adapter->set_mtu(adapter, netdev->mtu); + adapter->ahw.linkup = 0; mod_timer(&adapter->watchdog_timer, jiffies); napi_enable(&adapter->napi); @@ -1127,6 +1103,8 @@ static int netxen_nic_open(struct net_device *netdev) err_out_free_irq: free_irq(adapter->irq, adapter); +err_out_free_rxbuf: + netxen_release_rx_buffers(adapter); err_out_free_hw: netxen_free_hw_resources(adapter); err_out_free_sw: @@ -1152,10 +1130,8 @@ static int netxen_nic_close(struct net_device *netdev) netxen_release_tx_buffers(adapter); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); - } + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); return 0; } @@ -1458,7 +1434,8 @@ void netxen_watchdog_task(struct work_struct *work) netxen_nic_handle_phy_intr(adapter); - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); + if (netif_running(adapter->netdev)) + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } static void netxen_tx_timeout(struct net_device *netdev) @@ -1518,18 +1495,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) return stats; } -static inline void -netxen_handle_int(struct netxen_adapter *adapter) -{ - netxen_nic_disable_int(adapter); - napi_schedule(&adapter->napi); -} - static irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter = data; - u32 our_int = 0; - u32 status = 0; status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); @@ -1544,22 +1512,32 @@ static irqreturn_t netxen_intr(int irq, void *data) if (!ISR_LEGACY_INT_TRIGGERED(status)) return IRQ_NONE; - } else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + } else { + unsigned long our_int = 0; our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR); + /* not our interrupt */ - if ((our_int & (0x80 << adapter->portnum)) == 0) + if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { - /* claim interrupt */ - adapter->pci_write_normalize(adapter, - CRB_INT_VECTOR, - our_int & ~((u32)(0x80 << adapter->portnum))); - } + /* claim interrupt */ + adapter->pci_write_normalize(adapter, + CRB_INT_VECTOR, (our_int & 0xffffffff)); } - netxen_handle_int(adapter); + /* clear interrupt */ + if (adapter->fw_major < 4) + netxen_nic_disable_int(adapter); + + adapter->pci_write_immediate(adapter, + adapter->legacy_intr.tgt_status_reg, + 0xffffffff); + /* read twice to ensure write is flushed */ + adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + + napi_schedule(&adapter->napi); return IRQ_HANDLED; } @@ -1568,7 +1546,11 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) { struct netxen_adapter *adapter = data; - netxen_handle_int(adapter); + /* clear interrupt */ + adapter->pci_write_immediate(adapter, + msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); + + napi_schedule(&adapter->napi); return IRQ_HANDLED; } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 83e5ee5..b293adc 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -125,6 +125,8 @@ #define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) #define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) +#define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0) + /* * capabilities register, can be used to selectively enable/disable features * for backward compability diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c index b35d794..88f03c9 100644 --- a/drivers/net/ppp_mppe.c +++ b/drivers/net/ppp_mppe.c @@ -46,7 +46,6 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/types.h> #include <linux/slab.h> diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f929882..ff175e8 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -61,7 +61,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/string.h> #include <linux/list.h> #include <asm/uaccess.h> diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 6531ff5..5d86281 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -24,7 +24,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/moduleparam.h> #include <linux/string.h> #include <linux/timer.h> diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 25e62cf..1c370e6 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -20,7 +20,6 @@ * the file called "COPYING". */ -#include <linux/version.h> #include <linux/init.h> #include <linux/dma-mapping.h> #include <linux/etherdevice.h> diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7d29edc..e24b25c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -24,7 +24,6 @@ #include <linux/crc32.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/dma-mapping.h> @@ -666,11 +665,16 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) if (hw->chip_id != CHIP_ID_YUKON_EC) { if (hw->chip_id == CHIP_ID_YUKON_EC_U) { - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + /* select page 2 to access MAC control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); /* enable Power Down */ ctrl |= PHY_M_PC_POW_D_ENA; gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set page register back to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); } /* set IEEE compatible Power Down Mode (dev. #4.99) */ diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index c66dfc9..7db48f1 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -27,7 +27,6 @@ #include <linux/sched.h> #include <linux/tty.h> #include <linux/if_vlan.h> -#include <linux/version.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> #include <asm/byteorder.h> diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d2439b8..71d2c5c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.93" -#define DRV_MODULE_RELDATE "May 22, 2008" +#define DRV_MODULE_VERSION "3.94" +#define DRV_MODULE_RELDATE "August 14, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -536,6 +536,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) return 0; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -573,6 +574,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) return; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -1018,15 +1020,43 @@ static void tg3_mdio_fini(struct tg3 *tp) } /* tp->lock is held. */ +static inline void tg3_generate_fw_event(struct tg3 *tp) +{ + u32 val; + + val = tr32(GRC_RX_CPU_EVENT); + val |= GRC_RX_CPU_DRIVER_EVENT; + tw32_f(GRC_RX_CPU_EVENT, val); + + tp->last_event_jiffies = jiffies; +} + +#define TG3_FW_EVENT_TIMEOUT_USEC 2500 + +/* tp->lock is held. */ static void tg3_wait_for_event_ack(struct tg3 *tp) { int i; + unsigned int delay_cnt; + long time_remain; + + /* If enough time has passed, no wait is necessary. */ + time_remain = (long)(tp->last_event_jiffies + 1 + + usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) - + (long)jiffies; + if (time_remain < 0) + return; - /* Wait for up to 2.5 milliseconds */ - for (i = 0; i < 250000; i++) { + /* Check if we can shorten the wait time. */ + delay_cnt = jiffies_to_usecs(time_remain); + if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC) + delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC; + delay_cnt = (delay_cnt >> 3) + 1; + + for (i = 0; i < delay_cnt; i++) { if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) break; - udelay(10); + udelay(8); } } @@ -1075,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp) val = 0; tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32_f(GRC_RX_CPU_EVENT, val); + tg3_generate_fw_event(tp); } static void tg3_link_report(struct tg3 *tp) @@ -2124,6 +2152,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + mac_mode |= tp->mac_mode & + (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (mac_mode & MAC_MODE_APE_TX_EN) + mac_mode |= MAC_MODE_TDE_ENABLE; + } + tw32_f(MAC_MODE, mac_mode); udelay(100); @@ -5493,7 +5528,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event) return; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); - if (apedata != APE_FW_STATUS_READY) + if (!(apedata & APE_FW_STATUS_READY)) return; /* Wait for up to 1 millisecond for APE to service previous event. */ @@ -5760,6 +5795,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_mdio_stop(tp); + tg3_ape_lock(tp, TG3_APE_LOCK_GRC); + /* No matching tg3_nvram_unlock() after this because * chip reset below will undo the nvram lock. */ @@ -5908,12 +5945,19 @@ static int tg3_chip_reset(struct tg3 *tp) } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); + } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (tp->mac_mode & MAC_MODE_APE_TX_EN) + tp->mac_mode |= MAC_MODE_TDE_ENABLE; + tw32_f(MAC_MODE, tp->mac_mode); } else tw32_f(MAC_MODE, 0); udelay(40); tg3_mdio_start(tp); + tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); + err = tg3_poll_fw(tp); if (err) return err; @@ -5935,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; + tp->last_event_jiffies = jiffies; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } @@ -5948,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp) { if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { - u32 val; - /* Wait for RX cpu to ACK the previous event. */ tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32(GRC_RX_CPU_EVENT, val); + + tg3_generate_fw_event(tp); /* Wait for RX cpu to ACK this event. */ tg3_wait_for_event_ack(tp); @@ -7406,7 +7448,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); } - tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = 0; + tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && @@ -7840,9 +7886,8 @@ static void tg3_timer(unsigned long __opaque) * resets. */ if (!--tp->asf_counter) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { - u32 val; - + if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && + !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, @@ -7850,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque) tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32_f(GRC_RX_CPU_EVENT, val); + + tg3_generate_fw_event(tp); } tp->asf_counter = tp->asf_multiplier; } @@ -8422,6 +8466,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val) return ret; } +static inline u64 get_estat64(tg3_stat64_t *val) +{ + return ((u64)val->high << 32) | ((u64)val->low); +} + static unsigned long calc_crc_errors(struct tg3 *tp) { struct tg3_hw_stats *hw_stats = tp->hw_stats; @@ -8450,7 +8499,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp) #define ESTAT_ADD(member) \ estats->member = old_estats->member + \ - get_stat64(&hw_stats->member) + get_estat64(&hw_stats->member) static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp) { @@ -12416,6 +12465,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->misc_host_ctrl); } + /* Preserve the APE MAC_MODE bits */ + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + tp->mac_mode = tr32(MAC_MODE) | + MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = TG3_DEF_MAC_MODE; + /* these are limited to 10/100 only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || @@ -13275,7 +13331,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pdev = pdev; tp->dev = dev; tp->pm_cap = pm_cap; - tp->mac_mode = TG3_DEF_MAC_MODE; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index df07842..f5b8cab 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -325,6 +325,8 @@ #define MAC_MODE_TDE_ENABLE 0x00200000 #define MAC_MODE_RDE_ENABLE 0x00400000 #define MAC_MODE_FHDE_ENABLE 0x00800000 +#define MAC_MODE_APE_RX_EN 0x08000000 +#define MAC_MODE_APE_TX_EN 0x10000000 #define MAC_STATUS 0x00000404 #define MAC_STATUS_PCS_SYNCED 0x00000001 #define MAC_STATUS_SIGNAL_DET 0x00000002 @@ -1889,6 +1891,7 @@ #define APE_EVENT_STATUS_EVENT_PENDING 0x80000000 /* APE convenience enumerations. */ +#define TG3_APE_LOCK_GRC 1 #define TG3_APE_LOCK_MEM 4 #define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 @@ -2429,7 +2432,10 @@ struct tg3 { struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; + union { unsigned long phy_crc_errors; + unsigned long last_event_jiffies; + }; u32 rx_offset; u32 tg3_flags; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 85246ed..ec871f6 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -360,8 +360,8 @@ TLan_GetSKB( const struct tlan_list_tag *tag) { unsigned long addr; - addr = tag->buffer[8].address; - addr |= (tag->buffer[9].address << 16) << 16; + addr = tag->buffer[9].address; + addr |= (tag->buffer[8].address << 16) << 16; return (struct sk_buff *) addr; } @@ -1984,7 +1984,6 @@ static void TLan_ResetLists( struct net_device *dev ) TLanList *list; dma_addr_t list_phys; struct sk_buff *skb; - void *t = NULL; priv->txHead = 0; priv->txTail = 0; @@ -2022,7 +2021,8 @@ static void TLan_ResetLists( struct net_device *dev ) } skb_reserve( skb, NET_IP_ALIGN ); - list->buffer[0].address = pci_map_single(priv->pciDev, t, + list->buffer[0].address = pci_map_single(priv->pciDev, + skb->data, TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE); TLan_StoreSKB(list, skb); diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 47d84cd..59d1673 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -119,7 +119,6 @@ #include <linux/pci.h> #include <linux/dma-mapping.h> #include <linux/spinlock.h> -#include <linux/version.h> #include <linux/bitops.h> #include <linux/jiffies.h> diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h index e7bb349..13ccee6 100644 --- a/drivers/net/tokenring/lanstreamer.h +++ b/drivers/net/tokenring/lanstreamer.h @@ -60,8 +60,6 @@ * */ -#include <linux/version.h> - /* MAX_INTR - the maximum number of times we can loop * inside the interrupt function before returning * control to the OS (maximum value is 256) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index e6bbc63..6daea0c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -358,6 +358,66 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) return mask; } +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear, + gfp_t gfp) +{ + struct sk_buff *skb; + unsigned int i; + + skb = alloc_skb(prepad + len, gfp|__GFP_NOWARN); + if (skb) { + skb_reserve(skb, prepad); + skb_put(skb, len); + return skb; + } + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE) + return NULL; + + /* Start with a normal skb, and add pages. */ + skb = alloc_skb(prepad + linear, gfp); + if (!skb) + return NULL; + + skb_reserve(skb, prepad); + skb_put(skb, linear); + + len -= linear; + + for (i = 0; i < MAX_SKB_FRAGS; i++) { + skb_frag_t *f = &skb_shinfo(skb)->frags[i]; + + f->page = alloc_page(gfp|__GFP_ZERO); + if (!f->page) + break; + + f->page_offset = 0; + f->size = PAGE_SIZE; + + skb->data_len += PAGE_SIZE; + skb->len += PAGE_SIZE; + skb->truesize += PAGE_SIZE; + skb_shinfo(skb)->nr_frags++; + + if (len < PAGE_SIZE) { + len = 0; + break; + } + len -= PAGE_SIZE; + } + + /* Too large, or alloc fail? */ + if (unlikely(len)) { + kfree_skb(skb); + skb = NULL; + } + + return skb; +} + /* Get packet from user space buffer */ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count) { @@ -391,14 +451,12 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EINVAL; } - if (!(skb = alloc_skb(len + align, GFP_KERNEL))) { + if (!(skb = tun_alloc_skb(align, len, gso.hdr_len, GFP_KERNEL))) { tun->dev->stats.rx_dropped++; return -ENOMEM; } - if (align) - skb_reserve(skb, align); - if (memcpy_fromiovec(skb_put(skb, len), iv, len)) { + if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) { tun->dev->stats.rx_dropped++; kfree_skb(skb); return -EFAULT; @@ -748,6 +806,36 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return err; } +static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun = file->private_data; + + if (!tun) + return -EBADFD; + + DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = 0; + + if (ifr->ifr_flags & TUN_TUN_DEV) + ifr->ifr_flags |= IFF_TUN; + else + ifr->ifr_flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + ifr->ifr_flags |= IFF_NO_PI; + + if (tun->flags & TUN_ONE_QUEUE) + ifr->ifr_flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + ifr->ifr_flags |= IFF_VNET_HDR; + + return 0; +} + /* This is like a cut-down ethtool ops, except done via tun fd so no * privs required. */ static int set_offload(struct net_device *dev, unsigned long arg) @@ -833,6 +921,15 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); switch (cmd) { + case TUNGETIFF: + ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); + if (ret) + return ret; + + if (copy_to_user(argp, &ifr, sizeof(ifr))) + return -EFAULT; + break; + case TUNSETNOCSUM: /* Disable/Enable checksum */ if (arg) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 8549f11..734ce09 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -128,7 +128,6 @@ static const int multicast_filter_limit = 32; #include <asm/io.h> #include <asm/uaccess.h> #include <linux/in6.h> -#include <linux/version.h> #include <linux/dma-mapping.h> #include "typhoon.h" diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 68e198b..0973b6e 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -154,17 +154,6 @@ config USB_NET_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. -config USB_HSO - tristate "Option USB High Speed Mobile Devices" - depends on USB && RFKILL - default n - help - Choose this option if you have an Option HSDPA/HSUPA card. - These cards support downlink speeds of 7.2Mbps or greater. - - To compile this driver as a module, choose M here: the - module will be called hso. - config USB_NET_CDCETHER tristate "CDC Ethernet support (smart devices such as cable modems)" depends on USB_USBNET @@ -337,5 +326,15 @@ config USB_NET_ZAURUS really need this non-conformant variant of CDC Ethernet (or in some cases CDC MDLM) protocol, not "g_ether". +config USB_HSO + tristate "Option USB High Speed Mobile Devices" + depends on USB && RFKILL + default n + help + Choose this option if you have an Option HSDPA/HSUPA card. + These cards support downlink speeds of 7.2Mbps or greater. + + To compile this driver as a module, choose M here: the + module will be called hso. endmenu diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 031d07b..1b7cac7 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -102,8 +102,12 @@ #define MAX_RX_URBS 2 -#define get_serial_by_tty(x) \ - (x ? (struct hso_serial *)x->driver_data : NULL) +static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty) +{ + if (tty) + return tty->driver_data; + return NULL; +} /*****************************************************************************/ /* Debugging functions */ @@ -294,24 +298,25 @@ static int hso_get_activity(struct hso_device *hso_dev); /* #define DEBUG */ -#define dev2net(x) (x->port_data.dev_net) -#define dev2ser(x) (x->port_data.dev_serial) +static inline struct hso_net *dev2net(struct hso_device *hso_dev) +{ + return hso_dev->port_data.dev_net; +} + +static inline struct hso_serial *dev2ser(struct hso_device *hso_dev) +{ + return hso_dev->port_data.dev_serial; +} /* Debugging functions */ #ifdef DEBUG static void dbg_dump(int line_count, const char *func_name, unsigned char *buf, unsigned int len) { - u8 i = 0; + static char name[255]; - printk(KERN_DEBUG "[%d:%s]: len %d", line_count, func_name, len); - - for (i = 0; i < len; i++) { - if (!(i % 16)) - printk("\n 0x%03x: ", i); - printk("%02x ", (unsigned char)buf[i]); - } - printk("\n"); + sprintf(name, "hso[%d:%s]", line_count, func_name); + print_hex_dump_bytes(name, DUMP_PREFIX_NONE, buf, len); } #define DUMP(buf_, len_) \ @@ -528,13 +533,12 @@ static struct hso_serial *get_serial_by_shared_int_and_type( static struct hso_serial *get_serial_by_index(unsigned index) { - struct hso_serial *serial; + struct hso_serial *serial = NULL; unsigned long flags; - if (!serial_table[index]) - return NULL; spin_lock_irqsave(&serial_table_lock, flags); - serial = dev2ser(serial_table[index]); + if (serial_table[index]) + serial = dev2ser(serial_table[index]); spin_unlock_irqrestore(&serial_table_lock, flags); return serial; @@ -561,6 +565,7 @@ static int get_free_serial_index(void) static void set_serial_by_index(unsigned index, struct hso_serial *serial) { unsigned long flags; + spin_lock_irqsave(&serial_table_lock, flags); if (serial) serial_table[index] = serial->parent; @@ -569,7 +574,7 @@ static void set_serial_by_index(unsigned index, struct hso_serial *serial) spin_unlock_irqrestore(&serial_table_lock, flags); } -/* log a meaningfull explanation of an USB status */ +/* log a meaningful explanation of an USB status */ static void log_usb_status(int status, const char *function) { char *explanation; @@ -1103,8 +1108,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) /* reset the rts and dtr */ /* do the actual close */ serial->open_count--; + kref_put(&serial->parent->ref, hso_serial_ref_free); if (serial->open_count <= 0) { - kref_put(&serial->parent->ref, hso_serial_ref_free); serial->open_count = 0; if (serial->tty) { serial->tty->driver_data = NULL; @@ -1467,7 +1472,8 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) return; } hso_put_activity(serial->parent); - tty_wakeup(serial->tty); + if (serial->tty) + tty_wakeup(serial->tty); hso_kick_transmit(serial); D1(" "); @@ -1538,7 +1544,8 @@ static void ctrl_callback(struct urb *urb) clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags); } else { hso_put_activity(serial->parent); - tty_wakeup(serial->tty); + if (serial->tty) + tty_wakeup(serial->tty); /* response to a write command */ hso_kick_transmit(serial); } @@ -2652,7 +2659,7 @@ static void hso_free_interface(struct usb_interface *interface) hso_stop_net_device(network_table[i]); cancel_work_sync(&network_table[i]->async_put_intf); cancel_work_sync(&network_table[i]->async_get_intf); - if(rfk) + if (rfk) rfkill_unregister(rfk); hso_free_net_device(network_table[i]); } @@ -2723,7 +2730,7 @@ static int hso_mux_submit_intr_urb(struct hso_shared_int *shared_int, } /* operations setup of the serial interface */ -static struct tty_operations hso_serial_ops = { +static const struct tty_operations hso_serial_ops = { .open = hso_serial_open, .close = hso_serial_close, .write = hso_serial_write, diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 2028866..b20a45a 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -40,7 +40,6 @@ * */ -#include <linux/version.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/hardirq.h> @@ -587,7 +586,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_stop_hw(sc); free_irq(pdev->irq, sc); - pci_disable_msi(pdev); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); @@ -616,12 +614,10 @@ ath5k_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, 0x41, 0); - pci_enable_msi(pdev); - err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (err) { ATH5K_ERR(sc, "request_irq failed\n"); - goto err_msi; + goto err_no_irq; } err = ath5k_init(sc); @@ -642,8 +638,7 @@ ath5k_pci_resume(struct pci_dev *pdev) return 0; err_irq: free_irq(pdev->irq, sc); -err_msi: - pci_disable_msi(pdev); +err_no_irq: pci_disable_device(pdev); return err; } diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index bde162f..a17eb13 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -5017,7 +5017,11 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, for (i = 0; i < 123; i++) { if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - if ((abs(cur_vit_mask - bin)) < 75) + + /* workaround for gcc bug #37014 */ + volatile int tmp = abs(cur_vit_mask - bin); + + if (tmp < 75) mask_amt = 1; else mask_amt = 0; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3bf3a86..7205a93 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -33,7 +33,6 @@ #include <linux/moduleparam.h> #include <linux/if_arp.h> #include <linux/etherdevice.h> -#include <linux/version.h> #include <linux/firmware.h> #include <linux/wireless.h> #include <linux/workqueue.h> @@ -4615,7 +4614,9 @@ static void b43_sprom_fixup(struct ssb_bus *bus) if (bus->bustype == SSB_BUSTYPE_PCI) { pdev = bus->host_pci; if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || + IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; } diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 2541c81..1cb77db 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -34,7 +34,6 @@ #include <linux/moduleparam.h> #include <linux/if_arp.h> #include <linux/etherdevice.h> -#include <linux/version.h> #include <linux/firmware.h> #include <linux/wireless.h> #include <linux/workqueue.h> diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index c6f886e..19a401c 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -157,7 +157,6 @@ that only one external action is invoked at a time. #include <linux/stringify.h> #include <linux/tcp.h> #include <linux/types.h> -#include <linux/version.h> #include <linux/time.h> #include <linux/firmware.h> #include <linux/acpi.h> diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 36e8d2f..dcce3542 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -31,7 +31,6 @@ ******************************************************************************/ #include "ipw2200.h" -#include <linux/version.h> #ifndef KBUILD_EXTMOD diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index d333696..705c65b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b3931f6..3f51f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 22bb269..e258122 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -967,7 +966,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, s = iwl4965_get_sub_band(priv, channel); if (s >= EEPROM_TX_POWER_BANDS) { - IWL_ERROR("Tx Power can not find channel %d ", channel); + IWL_ERROR("Tx Power can not find channel %d\n", channel); return -1; } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f3d139b..cbc01a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -25,7 +25,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ed09e48..061ffba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9bd6180..c72f725 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <net/mac80211.h> struct iwl_priv; /* FIXME: remove */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index bce5383..3715575 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -63,7 +63,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> @@ -146,7 +145,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } return 0; @@ -227,7 +226,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; goto err; } @@ -254,7 +253,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); ret = -ETIMEDOUT; goto done; } diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 6512834..2eb03ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <net/mac80211.h> #include "iwl-dev.h" /* FIXME: remove */ diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index cb11c4a..4eee1b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 028e305..a099c9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index e5e5846..5d64229 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -27,7 +27,6 @@ *****************************************************************************/ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <net/mac80211.h> diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 60a6e01..6283a3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -207,7 +207,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, case WLAN_HT_CAP_MIMO_PS_DISABLED: break; default: - IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode); + IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode); break; } @@ -969,7 +969,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return priv->hw_params.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_params.bcast_sta_id; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 4108c7c..d82823b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -493,7 +493,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) /* Alloc keep-warm buffer */ ret = iwl_kw_alloc(priv); if (ret) { - IWL_ERROR("Keep Warm allocation failed"); + IWL_ERROR("Keep Warm allocation failed\n"); goto error_kw; } spin_lock_irqsave(&priv->lock, flags); @@ -1463,7 +1463,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); + IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 444847a..b775d5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -29,7 +29,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -1558,7 +1557,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } @@ -1583,7 +1582,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); return -ETIMEDOUT; } e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); @@ -2507,7 +2506,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h return priv->hw_setting.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_setting.bcast_sta_id; } } diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 83cd85e..29be3dc 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -413,12 +413,12 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) last_addr = range->end_addr; __skb_unlink(entry, &priv->tx_queue); memset(&info->status, 0, sizeof(info->status)); - priv->tx_stats[skb_get_queue_mapping(skb)].len--; entry_hdr = (struct p54_control_hdr *) entry->data; entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) pad = entry_data->align[0]; + priv->tx_stats[entry_data->hw_queue - 4].len--; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (!(payload->status & 0x01)) info->flags |= IEEE80211_TX_STAT_ACK; @@ -557,6 +557,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_control_allocdata *txhdr; size_t padding, len; u8 rate; + u8 cts_rate = 0x20; current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)]; if (unlikely(current_queue->len > current_queue->limit)) @@ -581,28 +582,28 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); hdr->retry1 = hdr->retry2 = info->control.retry_limit; - memset(txhdr->wep_key, 0x0, 16); - txhdr->padding = 0; - txhdr->padding2 = 0; - /* TODO: add support for alternate retry TX rates */ rate = ieee80211_get_tx_rate(dev, info)->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { rate |= 0x10; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + cts_rate |= 0x10; + } + if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { rate |= 0x40; - else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; + } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { rate |= 0x20; + cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; + } memset(txhdr->rateset, rate, 8); - txhdr->wep_key_present = 0; - txhdr->wep_key_len = 0; - txhdr->frame_type = cpu_to_le32(skb_get_queue_mapping(skb) + 4); - txhdr->magic4 = 0; - txhdr->antenna = (info->antenna_sel_tx == 0) ? + txhdr->key_type = 0; + txhdr->key_len = 0; + txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; + txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? 2 : info->antenna_sel_tx - 1; txhdr->output_power = 0x7f; // HW Maximum - txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? - 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); + txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? + 0 : cts_rate; if (padding) txhdr->align[0] = padding; @@ -836,10 +837,21 @@ static int p54_start(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; int err; + if (!priv->cached_vdcf) { + priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf)+ + priv->tx_hdr_len + sizeof(struct p54_control_hdr), + GFP_KERNEL); + + if (!priv->cached_vdcf) + return -ENOMEM; + } + err = priv->open(dev); if (!err) priv->mode = IEEE80211_IF_TYPE_MNTR; + p54_init_vdcf(dev); + return err; } @@ -1019,15 +1031,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + sizeof(struct p54_tx_control_allocdata); - priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) + - priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL); - - if (!priv->cached_vdcf) { - ieee80211_free_hw(dev); - return NULL; - } - - p54_init_vdcf(dev); mutex_init(&priv->conf_mutex); return dev; diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 2245fcc..8db6c0e 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -183,16 +183,16 @@ struct p54_frame_sent_hdr { struct p54_tx_control_allocdata { u8 rateset[8]; - u16 padding; - u8 wep_key_present; - u8 wep_key_len; - u8 wep_key[16]; - __le32 frame_type; - u32 padding2; - __le16 magic4; - u8 antenna; + u8 unalloc0[2]; + u8 key_type; + u8 key_len; + u8 key[16]; + u8 hw_queue; + u8 unalloc1[9]; + u8 tx_antenna; u8 output_power; - __le32 magic5; + u8 cts_rate; + u8 unalloc2[3]; u8 align[0]; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 815c095..cbaca23 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -109,7 +109,17 @@ static void p54u_rx_cb(struct urb *urb) urb->context = skb; skb_queue_tail(&priv->rx_queue, skb); } else { + if (!priv->hw_type) + skb_push(skb, sizeof(struct net2280_tx_hdr)); + + skb_reset_tail_pointer(skb); skb_trim(skb, 0); + if (urb->transfer_buffer != skb_tail_pointer(skb)) { + /* this should not happen */ + WARN_ON(1); + urb->transfer_buffer = skb_tail_pointer(skb); + } + skb_queue_tail(&priv->rx_queue, skb); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index a4a8c57..ff78e52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -173,10 +173,10 @@ struct rxdone_entry_desc { * frame transmission failed due to excessive retries. */ enum txdone_entry_desc_flags { - TXDONE_UNKNOWN = 1 << 0, - TXDONE_SUCCESS = 1 << 1, - TXDONE_FAILURE = 1 << 2, - TXDONE_EXCESSIVE_RETRY = 1 << 3, + TXDONE_UNKNOWN, + TXDONE_SUCCESS, + TXDONE_FAILURE, + TXDONE_EXCESSIVE_RETRY, }; /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 8d76bb2..2050227 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -181,6 +181,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * (Only indirectly by looking at the failed TX counters * in the register). */ + txdesc.flags = 0; if (!urb->status) __set_bit(TXDONE_UNKNOWN, &txdesc.flags); else diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 57376fb..ca5deb6 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -40,6 +40,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Netgear */ {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B}, /* HP */ {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ diff --git a/drivers/of/device.c b/drivers/of/device.c index 8a1d93a..51e5214 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -57,6 +57,15 @@ static ssize_t devspec_show(struct device *dev, return sprintf(buf, "%s\n", ofdev->node->full_name); } +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s\n", ofdev->node->name); +} + static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -71,6 +80,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute of_platform_device_attrs[] = { __ATTR_RO(devspec), + __ATTR_RO(name), __ATTR_RO(modalias), __ATTR_NULL }; diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 93e37f0..e17ef54 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) { acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + acpi_handle chandle, handle; struct pci_dev *pdev = dev; struct pci_bus *parent; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -399,10 +399,25 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) * Per PCI firmware specification, we should run the ACPI _OSC * method to get control of hotplug hardware before using it. If * an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, + * To handle different BIOS behavior, we look for _OSC on a root + * bridge preferentially (according to PCI fw spec). Later for + * OSHP within the scope of the hotplug controller and its parents, * upto the host bridge under which this controller exists. */ + handle = acpi_find_root_bridge_handle(pdev); + if (handle) { + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s\n", + (char *)string.pointer); + status = pci_osc_control_set(handle, flags); + if (ACPI_SUCCESS(status)) + goto got_one; + kfree(string.pointer); + string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; + } + + pdev = dev; + handle = DEVICE_ACPI_HANDLE(&dev->dev); while (!handle) { /* * This hotplug controller was not listed in the ACPI name @@ -427,15 +442,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); dbg("Trying to get hotplug control for %s \n", (char *)string.pointer); - status = pci_osc_control_set(handle, flags); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), (char *)string.pointer); - kfree(string.pointer); - return 0; - } + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) + goto got_one; if (acpi_root_bridge(handle)) break; chandle = handle; @@ -449,6 +458,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) kfree(string.pointer); return -ENODEV; +got_one: + dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), + (char *)string.pointer); + kfree(string.pointer); + return 0; } EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 30f581b..6dd7b13 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -36,12 +36,7 @@ int aer_osc_setup(struct pcie_device *pciedev) if (acpi_pci_disabled) return -1; - /* Find root host bridge */ - while (pdev->bus->self) - pdev = pdev->bus->self; - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(pdev->bus), pdev->bus->number); - + handle = acpi_find_root_bridge_handle(pdev); if (handle) { pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT); status = pci_osc_control_set(handle, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a04498d..cce2f4c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -383,6 +383,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->start = base; if (!res->end) res->end = limit + 0xfff; + printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), res->start, res->end); } res = child->resource[1]; @@ -394,6 +395,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; + printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), res->start, res->end); } res = child->resource[2]; @@ -429,6 +431,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->start = base; res->end = limit + 0xfffff; + printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64)?"64":"32",res->start, res->end); } } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 827c0a5..82634a2 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -530,6 +530,36 @@ void __ref pci_bus_assign_resources(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_assign_resources); +static void pci_bus_dump_res(struct pci_bus *bus) +{ + int i; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *res = bus->resource[i]; + if (!res) + continue; + + printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", bus->number, i, (res->flags & IORESOURCE_IO)? "io port":"mmio", res->start, res->end); + } +} + +static void pci_bus_dump_resources(struct pci_bus *bus) +{ + struct pci_bus *b; + struct pci_dev *dev; + + + pci_bus_dump_res(bus); + + list_for_each_entry(dev, &bus->devices, bus_list) { + b = dev->subordinate; + if (!b) + continue; + + pci_bus_dump_resources(b); + } +} + void __init pci_assign_unassigned_resources(void) { @@ -545,4 +575,9 @@ pci_assign_unassigned_resources(void) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } + + /* dump the resource on buses */ + list_for_each_entry(bus, &pci_root_buses, node) { + pci_bus_dump_resources(bus); + } } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 90ab738..9a9755c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -561,7 +561,7 @@ config RTC_DRV_AT91SAM9_GPBR config RTC_DRV_BFIN tristate "Blackfin On-Chip RTC" - depends on BLACKFIN + depends on BLACKFIN && !BF561 help If you say yes here you will get support for the Blackfin On-Chip Real Time Clock. diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index a1af4c2..34439ce 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -218,26 +218,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) return IRQ_NONE; } -static int bfin_rtc_open(struct device *dev) -{ - int ret; - - dev_dbg_stamp(dev); - - ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); - if (!ret) - bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); - - return ret; -} - -static void bfin_rtc_release(struct device *dev) -{ - dev_dbg_stamp(dev); - bfin_rtc_reset(dev, 0); - free_irq(IRQ_RTC, dev); -} - static void bfin_rtc_int_set(u16 rtc_int) { bfin_write_RTC_ISTAT(rtc_int); @@ -370,8 +350,6 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) } static struct rtc_class_ops bfin_rtc_ops = { - .open = bfin_rtc_open, - .release = bfin_rtc_release, .ioctl = bfin_rtc_ioctl, .read_time = bfin_rtc_read_time, .set_time = bfin_rtc_set_time, @@ -383,29 +361,44 @@ static struct rtc_class_ops bfin_rtc_ops = { static int __devinit bfin_rtc_probe(struct platform_device *pdev) { struct bfin_rtc *rtc; + struct device *dev = &pdev->dev; int ret = 0; + unsigned long timeout; - dev_dbg_stamp(&pdev->dev); + dev_dbg_stamp(dev); + /* Allocate memory for our RTC struct */ rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (unlikely(!rtc)) return -ENOMEM; + platform_set_drvdata(pdev, rtc); + device_init_wakeup(dev, 1); - rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - ret = PTR_ERR(rtc->rtc_dev); + /* Grab the IRQ and init the hardware */ + ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); + if (unlikely(ret)) goto err; - } - - /* see comment at top of file about stopwatch/PIE */ + /* sometimes the bootloader touched things, but the write complete was not + * enabled, so let's just do a quick timeout here since the IRQ will not fire ... + */ + timeout = jiffies + HZ; + while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) + if (time_after(jiffies, timeout)) + break; + bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); bfin_write_RTC_SWCNT(0); - platform_set_drvdata(pdev, rtc); - - device_init_wakeup(&pdev->dev, 1); + /* Register our RTC with the RTC framework */ + rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); + if (unlikely(IS_ERR(rtc))) { + ret = PTR_ERR(rtc->rtc_dev); + goto err_irq; + } return 0; + err_irq: + free_irq(IRQ_RTC, dev); err: kfree(rtc); return ret; @@ -414,7 +407,10 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) static int __devexit bfin_rtc_remove(struct platform_device *pdev) { struct bfin_rtc *rtc = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + bfin_rtc_reset(dev, 0); + free_irq(IRQ_RTC, dev); rtc_device_unregister(rtc->rtc_dev); platform_set_drvdata(pdev, NULL); kfree(rtc); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 35dcc06..f118252 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -403,11 +403,14 @@ static long rtc_dev_ioctl(struct file *file, #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL case RTC_UIE_OFF: + mutex_unlock(&rtc->ops_lock); clear_uie(rtc); - break; + return 0; case RTC_UIE_ON: + mutex_unlock(&rtc->ops_lock); err = set_uie(rtc); + return err; #endif default: err = -ENOTTY; diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 640acd2..a150418 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -173,7 +173,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) int cr, sr; int ret = 0; - if (client->irq < 0) + if (client->irq <= 0) return -EINVAL; mutex_lock(&ds1374->mutex); @@ -212,7 +212,7 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) int cr; int ret = 0; - if (client->irq < 0) + if (client->irq <= 0) return -EINVAL; ret = ds1374_read_time(dev, &now); @@ -381,7 +381,7 @@ static int ds1374_probe(struct i2c_client *client, if (ret) goto out_free; - if (client->irq >= 0) { + if (client->irq > 0) { ret = request_irq(client->irq, ds1374_irq, 0, "ds1374", client); if (ret) { @@ -401,7 +401,7 @@ static int ds1374_probe(struct i2c_client *client, return 0; out_irq: - if (client->irq >= 0) + if (client->irq > 0) free_irq(client->irq, client); out_free: @@ -414,7 +414,7 @@ static int __devexit ds1374_remove(struct i2c_client *client) { struct ds1374 *ds1374 = i2c_get_clientdata(client); - if (client->irq >= 0) { + if (client->irq > 0) { mutex_lock(&ds1374->mutex); ds1374->exiting = 1; mutex_unlock(&ds1374->mutex); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 12f0310..78b2551 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -20,8 +20,6 @@ */ #include <linux/module.h> -#include <linux/version.h> - #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/init.h> diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index b35f9bf..395985b 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/device.h> diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1b6c52e..acb7801 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2333,13 +2333,11 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) { struct dasd_device *device; struct dasd_ccw_req *cqr; - unsigned long flags; int ret; - device = dasd_device_from_cdev(cdev); + device = dasd_device_from_cdev_locked(cdev); if (IS_ERR(device)) return 0; - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); ret = 0; switch (event) { case CIO_GONE: @@ -2369,7 +2367,6 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) ret = 1; break; } - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); dasd_put_device(device); return ret; } diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 4bf0aa5..2476f87 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -308,7 +308,7 @@ struct dasd_psf_prssd_data { unsigned char flags; unsigned char reserved[4]; unsigned char suborder; - unsigned char varies[9]; + unsigned char varies[5]; } __attribute__ ((packed)); /* diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 29da441..bf512ac 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -16,6 +16,7 @@ #include <linux/poll.h> #include <linux/mutex.h> #include <linux/smp_lock.h> +#include <linux/err.h> #include <asm/uaccess.h> #include <asm/atomic.h> @@ -457,7 +458,7 @@ int dasd_eer_enable(struct dasd_device *device) cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */, SNSS_DATA_SIZE, device); - if (!cqr) + if (IS_ERR(cqr)) return -ENOMEM; cqr->startdev = device; diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 01fcdd9..db85f1f 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -384,6 +384,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char * get minor, add to list */ down_write(&dcssblk_devices_sem); + if (dcssblk_get_segment_by_name(local_buf)) { + rc = -EEXIST; + goto release_gd; + } rc = dcssblk_assign_free_minor(dev_info); if (rc) { up_write(&dcssblk_devices_sem); diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 687720b..be0ce22 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -109,7 +109,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) /* The current idal buffer is not correct. Allocate a new one. */ new = idal_buffer_alloc(block_size, 0); - if (new == NULL) + if (IS_ERR(new)) return -ENOMEM; if (device->char_data.idal_buf != NULL) diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 2a1af4e..cc8fd78 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -248,7 +248,7 @@ tape_std_mtsetblk(struct tape_device *device, int count) /* Allocate a new idal buffer. */ new = idal_buffer_alloc(count, 0); - if (new == NULL) + if (IS_ERR(new)) return -ENOMEM; if (device->char_data.idal_buf != NULL) idal_buffer_free(device->char_data.idal_buf); diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 26a930e..e0ce65f 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -112,8 +112,10 @@ ccwgroup_release (struct device *dev) gdev = to_ccwgroupdev(dev); for (i = 0; i < gdev->count; i++) { - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); - put_device(&gdev->cdev[i]->dev); + if (gdev->cdev[i]) { + dev_set_drvdata(&gdev->cdev[i]->dev, NULL); + put_device(&gdev->cdev[i]->dev); + } } kfree(gdev); } @@ -221,6 +223,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); + gdev->creator_id = creator_id; + gdev->count = num_devices; + gdev->dev.bus = &ccwgroup_bus_type; + gdev->dev.parent = root; + gdev->dev.release = ccwgroup_release; + device_initialize(&gdev->dev); + curr_buf = buf; for (i = 0; i < num_devices && curr_buf; i++) { rc = __get_next_bus_id(&curr_buf, tmp_bus_id); @@ -258,16 +267,11 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, rc = -EINVAL; goto error; } - gdev->creator_id = creator_id; - gdev->count = num_devices; - gdev->dev.bus = &ccwgroup_bus_type; - gdev->dev.parent = root; - gdev->dev.release = ccwgroup_release; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", gdev->cdev[0]->dev.bus_id); - rc = device_register(&gdev->dev); + rc = device_add(&gdev->dev); if (rc) goto error; get_device(&gdev->dev); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 46c021d..51489ef 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -477,7 +477,6 @@ void css_schedule_eval_all(void) void css_wait_for_slow_path(void) { - flush_workqueue(ccw_device_notify_work); flush_workqueue(slow_path_wq); } diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e818d0c..2822103 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -150,7 +150,6 @@ static struct css_driver io_subchannel_driver = { }; struct workqueue_struct *ccw_device_work; -struct workqueue_struct *ccw_device_notify_work; wait_queue_head_t ccw_device_init_wq; atomic_t ccw_device_init_count; @@ -168,11 +167,6 @@ init_ccw_bus_type (void) ccw_device_work = create_singlethread_workqueue("cio"); if (!ccw_device_work) return -ENOMEM; /* FIXME: better errno ? */ - ccw_device_notify_work = create_singlethread_workqueue("cio_notify"); - if (!ccw_device_notify_work) { - ret = -ENOMEM; /* FIXME: better errno ? */ - goto out_err; - } slow_path_wq = create_singlethread_workqueue("kslowcrw"); if (!slow_path_wq) { ret = -ENOMEM; /* FIXME: better errno ? */ @@ -192,8 +186,6 @@ init_ccw_bus_type (void) out_err: if (ccw_device_work) destroy_workqueue(ccw_device_work); - if (ccw_device_notify_work) - destroy_workqueue(ccw_device_notify_work); if (slow_path_wq) destroy_workqueue(slow_path_wq); return ret; @@ -204,7 +196,6 @@ cleanup_ccw_bus_type (void) { css_driver_unregister(&io_subchannel_driver); bus_unregister(&ccw_bus_type); - destroy_workqueue(ccw_device_notify_work); destroy_workqueue(ccw_device_work); } @@ -1496,11 +1487,22 @@ static void device_set_disconnected(struct ccw_device *cdev) ccw_device_schedule_recovery(); } +void ccw_device_set_notoper(struct ccw_device *cdev) +{ + struct subchannel *sch = to_subchannel(cdev->dev.parent); + + CIO_TRACE_EVENT(2, "notoper"); + CIO_TRACE_EVENT(2, sch->dev.bus_id); + ccw_device_set_timeout(cdev, 0); + cio_disable_subchannel(sch); + cdev->private->state = DEV_STATE_NOT_OPER; +} + static int io_subchannel_sch_event(struct subchannel *sch, int slow) { int event, ret, disc; unsigned long flags; - enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; + enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE, DISC } action; struct ccw_device *cdev; spin_lock_irqsave(sch->lock, flags); @@ -1535,16 +1537,11 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) } /* fall through */ case CIO_GONE: - /* Prevent unwanted effects when opening lock. */ - cio_disable_subchannel(sch); - device_set_disconnected(cdev); /* Ask driver what to do with device. */ - action = UNREGISTER; - spin_unlock_irqrestore(sch->lock, flags); - ret = io_subchannel_notify(sch, event); - spin_lock_irqsave(sch->lock, flags); - if (ret) - action = NONE; + if (io_subchannel_notify(sch, event)) + action = DISC; + else + action = UNREGISTER; break; case CIO_REVALIDATE: /* Device will be removed, so no notify necessary. */ @@ -1565,6 +1562,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) switch (action) { case UNREGISTER: case UNREGISTER_PROBE: + ccw_device_set_notoper(cdev); /* Unregister device (will use subchannel lock). */ spin_unlock_irqrestore(sch->lock, flags); css_sch_device_unregister(sch); @@ -1577,6 +1575,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) case REPROBE: ccw_device_trigger_reprobe(cdev); break; + case DISC: + device_set_disconnected(cdev); + break; default: break; } @@ -1828,5 +1829,4 @@ EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL(ccw_device_work); -EXPORT_SYMBOL(ccw_device_notify_work); EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 9800a83..6f5c3f2 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -72,7 +72,6 @@ dev_fsm_final_state(struct ccw_device *cdev) } extern struct workqueue_struct *ccw_device_work; -extern struct workqueue_struct *ccw_device_notify_work; extern wait_queue_head_t ccw_device_init_wq; extern atomic_t ccw_device_init_count; @@ -120,6 +119,7 @@ int ccw_device_stlck(struct ccw_device *); void ccw_device_trigger_reprobe(struct ccw_device *); void ccw_device_kill_io(struct ccw_device *); int ccw_device_notify(struct ccw_device *, int); +void ccw_device_set_notoper(struct ccw_device *cdev); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8b5fe57..550508d 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -337,26 +337,34 @@ int ccw_device_notify(struct ccw_device *cdev, int event) return 0; if (!cdev->online) return 0; + CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", + cdev->private->dev_id.ssid, cdev->private->dev_id.devno, + event); return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; } -static void -ccw_device_oper_notify(struct work_struct *work) +static void cmf_reenable_delayed(struct work_struct *work) { struct ccw_device_private *priv; struct ccw_device *cdev; - int ret; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; - ret = ccw_device_notify(cdev, CIO_OPER); - if (ret) { + cmf_reenable(cdev); +} + +static void ccw_device_oper_notify(struct ccw_device *cdev) +{ + if (ccw_device_notify(cdev, CIO_OPER)) { /* Reenable channel measurements, if needed. */ - cmf_reenable(cdev); - wake_up(&cdev->private->wait_q); - } else - /* Driver doesn't want device back. */ - ccw_device_do_unreg_rereg(work); + PREPARE_WORK(&cdev->private->kick_work, cmf_reenable_delayed); + queue_work(ccw_device_work, &cdev->private->kick_work); + return; + } + /* Driver doesn't want device back. */ + ccw_device_set_notoper(cdev); + PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); + queue_work(ccw_device_work, &cdev->private->kick_work); } /* @@ -386,8 +394,7 @@ ccw_device_done(struct ccw_device *cdev, int state) if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; - PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify); - queue_work(ccw_device_notify_work, &cdev->private->kick_work); + ccw_device_oper_notify(cdev); } wake_up(&cdev->private->wait_q); diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h index 8484b83..5a4d85b 100644 --- a/drivers/s390/cio/qdio_debug.h +++ b/drivers/s390/cio/qdio_debug.h @@ -61,18 +61,18 @@ /* s390dbf views */ #define QDIO_DBF_SETUP_LEN 8 -#define QDIO_DBF_SETUP_PAGES 4 +#define QDIO_DBF_SETUP_PAGES 8 #define QDIO_DBF_SETUP_NR_AREAS 1 #define QDIO_DBF_TRACE_LEN 8 #define QDIO_DBF_TRACE_NR_AREAS 2 #ifdef CONFIG_QDIO_DEBUG -#define QDIO_DBF_TRACE_PAGES 16 +#define QDIO_DBF_TRACE_PAGES 32 #define QDIO_DBF_SETUP_LEVEL 6 #define QDIO_DBF_TRACE_LEVEL 4 #else /* !CONFIG_QDIO_DEBUG */ -#define QDIO_DBF_TRACE_PAGES 4 +#define QDIO_DBF_TRACE_PAGES 8 #define QDIO_DBF_SETUP_LEVEL 2 #define QDIO_DBF_TRACE_LEVEL 2 #endif /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index d156485..e6eabc8 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -330,6 +330,7 @@ static int qdio_siga_output(struct qdio_q *q) int cc; u32 busy_bit; u64 start_time = 0; + char dbf_text[15]; QDIO_DBF_TEXT5(0, trace, "sigaout"); QDIO_DBF_HEX5(0, trace, &q, sizeof(void *)); @@ -338,6 +339,9 @@ static int qdio_siga_output(struct qdio_q *q) again: cc = qdio_do_siga_output(q, &busy_bit); if (queue_type(q) == QDIO_IQDIO_QFMT && cc == 2 && busy_bit) { + sprintf(dbf_text, "bb%4x%2x", q->irq_ptr->schid.sch_no, q->nr); + QDIO_DBF_TEXT3(0, trace, dbf_text); + if (!start_time) start_time = get_usecs(); else if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) @@ -748,16 +752,18 @@ static void qdio_kick_outbound_q(struct qdio_q *q) rc = qdio_siga_output(q); switch (rc) { case 0: - /* went smooth this time, reset timestamp */ - q->u.out.timestamp = 0; - /* TODO: improve error handling for CC=0 case */ #ifdef CONFIG_QDIO_DEBUG - QDIO_DBF_TEXT3(0, trace, "cc2reslv"); - sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, q->nr, - atomic_read(&q->u.out.busy_siga_counter)); - QDIO_DBF_TEXT3(0, trace, dbf_text); + if (q->u.out.timestamp) { + QDIO_DBF_TEXT3(0, trace, "cc2reslv"); + sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, + q->nr, + atomic_read(&q->u.out.busy_siga_counter)); + QDIO_DBF_TEXT3(0, trace, dbf_text); + } #endif /* CONFIG_QDIO_DEBUG */ + /* went smooth this time, reset timestamp */ + q->u.out.timestamp = 0; break; /* cc=2 and busy bit */ case (2 | QDIO_ERROR_SIGA_BUSY): @@ -1066,14 +1072,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, if (IS_ERR(irb)) { switch (PTR_ERR(irb)) { case -EIO: - sprintf(dbf_text, "ierr%4x", - cdev->private->schid.sch_no); + sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; case -ETIMEDOUT: - sprintf(dbf_text, "qtoh%4x", - cdev->private->schid.sch_no); + sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; @@ -1124,8 +1128,10 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, struct qdio_ssqd_desc *qdio_get_ssqd_desc(struct ccw_device *cdev) { struct qdio_irq *irq_ptr; + char dbf_text[15]; - QDIO_DBF_TEXT0(0, setup, "getssqd"); + sprintf(dbf_text, "qssq%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); irq_ptr = cdev->private->qdio_data; if (!irq_ptr) @@ -1149,14 +1155,13 @@ int qdio_cleanup(struct ccw_device *cdev, int how) char dbf_text[15]; int rc; + sprintf(dbf_text, "qcln%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; - sprintf(dbf_text, "qcln%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - rc = qdio_shutdown(cdev, how); if (rc == 0) rc = qdio_free(cdev); @@ -1191,6 +1196,9 @@ int qdio_shutdown(struct ccw_device *cdev, int how) unsigned long flags; char dbf_text[15]; + sprintf(dbf_text, "qshu%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1205,10 +1213,6 @@ int qdio_shutdown(struct ccw_device *cdev, int how) return 0; } - sprintf(dbf_text, "qsqs%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - tiqdio_remove_input_queues(irq_ptr); qdio_shutdown_queues(cdev); qdio_shutdown_debug_entries(irq_ptr, cdev); @@ -1247,7 +1251,6 @@ no_cleanup: qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); mutex_unlock(&irq_ptr->setup_mutex); - module_put(THIS_MODULE); if (rc) return rc; return 0; @@ -1263,16 +1266,14 @@ int qdio_free(struct ccw_device *cdev) struct qdio_irq *irq_ptr; char dbf_text[15]; + sprintf(dbf_text, "qfre%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; mutex_lock(&irq_ptr->setup_mutex); - - sprintf(dbf_text, "qfqs%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - cdev->private->qdio_data = NULL; mutex_unlock(&irq_ptr->setup_mutex); @@ -1295,7 +1296,6 @@ int qdio_initialize(struct qdio_initialize *init_data) sprintf(dbf_text, "qini%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); rc = qdio_allocate(init_data); if (rc) @@ -1319,7 +1319,6 @@ int qdio_allocate(struct qdio_initialize *init_data) sprintf(dbf_text, "qalc%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); if ((init_data->no_input_qs && !init_data->input_handler) || (init_data->no_output_qs && !init_data->output_handler)) @@ -1389,6 +1388,9 @@ int qdio_establish(struct qdio_initialize *init_data) unsigned long saveflags; int rc; + sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1396,13 +1398,6 @@ int qdio_establish(struct qdio_initialize *init_data) if (cdev->private->state != DEV_STATE_ONLINE) return -EINVAL; - if (!try_module_get(THIS_MODULE)) - return -EINVAL; - - sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); - mutex_lock(&irq_ptr->setup_mutex); qdio_setup_irq(init_data); @@ -1472,6 +1467,9 @@ int qdio_activate(struct ccw_device *cdev) unsigned long saveflags; char dbf_text[20]; + sprintf(dbf_text, "qact%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1485,10 +1483,6 @@ int qdio_activate(struct ccw_device *cdev) goto out; } - sprintf(dbf_text, "qact%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT2(0, setup, dbf_text); - QDIO_DBF_TEXT2(0, trace, dbf_text); - irq_ptr->ccw.cmd_code = irq_ptr->aqueue.cmd; irq_ptr->ccw.flags = CCW_FLAG_SLI; irq_ptr->ccw.count = irq_ptr->aqueue.count; @@ -1663,7 +1657,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text, "doQD%04x", cdev->private->schid.sch_no); + sprintf(dbf_text, "doQD%4x", cdev->private->schid.sch_no); QDIO_DBF_TEXT3(0, trace, dbf_text); #endif /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 1bd2a20..1679e2f 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -165,7 +165,7 @@ static void setup_queues(struct qdio_irq *irq_ptr, void **output_sbal_array = qdio_init->output_sbal_addr_array; int i; - sprintf(dbf_text, "qfqs%4x", qdio_init->cdev->private->schid.sch_no); + sprintf(dbf_text, "qset%4x", qdio_init->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); for_each_input_queue(irq_ptr, q, i) { @@ -285,7 +285,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr) rc = __get_ssqd_info(irq_ptr); if (rc) { QDIO_DBF_TEXT2(0, setup, "ssqdasig"); - sprintf(dbf_text, "schno%x", irq_ptr->schid.sch_no); + sprintf(dbf_text, "schn%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(0, setup, dbf_text); sprintf(dbf_text, "rc:%d", rc); QDIO_DBF_TEXT2(0, setup, dbf_text); @@ -447,7 +447,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, { char s[80]; - sprintf(s, "%s ", cdev->dev.bus_id); + sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no); switch (irq_ptr->qib.qfmt) { case QDIO_QETH_QFMT: diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 9291a77..ea7f614 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -113,7 +113,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) struct qdio_q *q; int i; - for_each_input_queue(irq_ptr, q, i) { + for (i = 0; i < irq_ptr->nr_input_qs; i++) { + q = irq_ptr->input_qs[i]; + /* if establish triggered an error */ + if (!q || !q->entry.prev || !q->entry.next) + continue; list_del_rcu(&q->entry); synchronize_rcu(); } diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 49ae1cd..2de1e2f 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -19,7 +19,6 @@ #undef DEBUGDATA #undef DEBUGCCW -#include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index e7c7b4e..2dee69d 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -376,7 +376,7 @@ static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h) if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' || inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd') return SCSI_DH_NOSYS; - h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun); + h->lun = inqp->lun[7]; /* Uses only the last byte */ } return err; } @@ -386,6 +386,7 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) int err; struct c9_inquiry *inqp; + h->lun_state = RDAC_LUN_UNOWNED; err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h); if (err == SCSI_DH_OK) { inqp = &h->inq.c9; diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h index 19406ce..179ad77 100644 --- a/drivers/scsi/dpt/dpti_i2o.h +++ b/drivers/scsi/dpt/dpti_i2o.h @@ -21,7 +21,6 @@ #include <linux/i2o-dev.h> -#include <linux/version.h> #include <linux/notifier.h> #include <asm/atomic.h> diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ae560bc..4e0b7c8 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -556,11 +556,12 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, /** * ibmvfc_init_host - Start host initialization * @vhost: ibmvfc host struct + * @relogin: is this a re-login? * * Return value: * nothing **/ -static void ibmvfc_init_host(struct ibmvfc_host *vhost) +static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin) { struct ibmvfc_target *tgt; @@ -574,6 +575,11 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) } if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { + if (!relogin) { + memset(vhost->async_crq.msgs, 0, PAGE_SIZE); + vhost->async_crq.cur = 0; + } + list_for_each_entry(tgt, &vhost->targets, queue) tgt->need_login = 1; scsi_block_requests(vhost->host); @@ -1059,9 +1065,10 @@ static void ibmvfc_get_starget_port_id(struct scsi_target *starget) static int ibmvfc_wait_while_resetting(struct ibmvfc_host *vhost) { long timeout = wait_event_timeout(vhost->init_wait_q, - (vhost->state == IBMVFC_ACTIVE || - vhost->state == IBMVFC_HOST_OFFLINE || - vhost->state == IBMVFC_LINK_DEAD), + ((vhost->state == IBMVFC_ACTIVE || + vhost->state == IBMVFC_HOST_OFFLINE || + vhost->state == IBMVFC_LINK_DEAD) && + vhost->action == IBMVFC_HOST_ACTION_NONE), (init_timeout * HZ)); return timeout ? 0 : -EIO; @@ -1450,8 +1457,8 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; - int rsp_len = 0; - int sense_len = rsp->fcp_sense_len; + u32 rsp_len = 0; + u32 sense_len = rsp->fcp_sense_len; if (cmnd) { if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID) @@ -1468,7 +1475,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) rsp_len = rsp->fcp_rsp_len; if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE) sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; - if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len) + if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); ibmvfc_log_error(evt); @@ -2077,17 +2084,18 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, { const char *desc = ibmvfc_get_ae_desc(crq->event); - ibmvfc_log(vhost, 3, "%s event received\n", desc); + ibmvfc_log(vhost, 3, "%s event received. scsi_id: %lx, wwpn: %lx," + " node_name: %lx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name); switch (crq->event) { case IBMVFC_AE_LINK_UP: case IBMVFC_AE_RESUME: vhost->events_to_log |= IBMVFC_AE_LINKUP; - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 1); break; case IBMVFC_AE_SCN_FABRIC: vhost->events_to_log |= IBMVFC_AE_RSCN; - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 1); break; case IBMVFC_AE_SCN_NPORT: case IBMVFC_AE_SCN_GROUP: @@ -2133,13 +2141,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) /* Send back a response */ rc = ibmvfc_send_crq_init_complete(vhost); if (rc == 0) - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 0); else dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc); break; case IBMVFC_CRQ_INIT_COMPLETE: dev_info(vhost->dev, "Partner initialization complete\n"); - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 0); break; default: dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format); @@ -3357,8 +3365,6 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) mad->buffer.va = vhost->login_buf_dma; mad->buffer.len = sizeof(*vhost->login_buf); - memset(vhost->async_crq.msgs, 0, PAGE_SIZE); - vhost->async_crq.cur = 0; ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); if (!ibmvfc_send_event(evt, vhost, default_timeout)) @@ -3601,8 +3607,9 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) } } - if (vhost->reinit) { + if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { vhost->reinit = 0; + scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); } else { ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 4bf6e37..fb3177a 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -29,8 +29,8 @@ #include "viosrp.h" #define IBMVFC_NAME "ibmvfc" -#define IBMVFC_DRIVER_VERSION "1.0.1" -#define IBMVFC_DRIVER_DATE "(July 11, 2008)" +#define IBMVFC_DRIVER_VERSION "1.0.2" +#define IBMVFC_DRIVER_DATE "(August 14, 2008)" #define IBMVFC_DEFAULT_TIMEOUT 15 #define IBMVFC_INIT_TIMEOUT 30 diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 6b24b9c..7b1502c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1636,7 +1636,7 @@ static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) unsigned long desired_io = max_requests * sizeof(union viosrp_iu); /* add io space for sg data */ - desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * + desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 * IBMVSCSI_CMDS_PER_LUN_DEFAULT); return desired_io; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 7c615c7..bc9e6dd 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -165,7 +165,6 @@ #include <asm/byteorder.h> #include <asm/page.h> #include <linux/stddef.h> -#include <linux/version.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/kernel.h> diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index e0657b6..4e49fbc 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -50,7 +50,6 @@ #ifndef _IPS_H_ #define _IPS_H_ -#include <linux/version.h> #include <linux/nmi.h> #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 90272e6..094b47e 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -27,7 +27,6 @@ #include <linux/pci.h> #include <linux/spinlock.h> #include <linux/ctype.h> -#include <linux/version.h> #include <scsi/scsi.h> #include <scsi/scsi_device.h> diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index fc7ac15..97b7633 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_sas.c - * Version : v00.00.03.20-rc1 + * Version : v00.00.04.01-rc1 * * Authors: * (email-id : megaraidlinux@lsi.com) @@ -71,6 +71,10 @@ static struct pci_device_id megasas_pci_table[] = { /* ppc IOP */ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)}, /* ppc IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)}, + /* gen2*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, + /* gen2*/ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, /* xscale IOP, vega */ {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, @@ -198,6 +202,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) */ writel(status, ®s->outbound_intr_status); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + return 0; } @@ -293,6 +300,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) */ writel(status, ®s->outbound_doorbell_clear); + /* Dummy readl to force pci flush */ + readl(®s->outbound_doorbell_clear); + return 0; } /** @@ -318,6 +328,99 @@ static struct megasas_instance_template megasas_instance_template_ppc = { }; /** +* The following functions are defined for gen2 (deviceid : 0x78 0x79) +* controllers +*/ + +/** + * megasas_enable_intr_gen2 - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + /* write ~0x00000005 (4 & 1) to the intr mask*/ + writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_gen2 - Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_gen2 - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_gen2 - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK)) + return 1; + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_doorbell_clear); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + + return 0; +} +/** + * megasas_fire_cmd_gen2 - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_gen2 = { + + .fire_cmd = megasas_fire_cmd_gen2, + .enable_intr = megasas_enable_intr_gen2, + .disable_intr = megasas_disable_intr_gen2, + .clear_intr = megasas_clear_intr_gen2, + .read_fw_status_reg = megasas_read_fw_status_reg_gen2, +}; + +/** * This is the end of set of functions & definitions * specific to ppc (deviceid : 0x60) controllers */ @@ -1976,7 +2079,12 @@ static int megasas_init_mfi(struct megasas_instance *instance) /* * Map the message registers */ - instance->base_addr = pci_resource_start(instance->pdev, 0); + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { + instance->base_addr = pci_resource_start(instance->pdev, 1); + } else { + instance->base_addr = pci_resource_start(instance->pdev, 0); + } if (pci_request_regions(instance->pdev, "megasas: LSI")) { printk(KERN_DEBUG "megasas: IO memory region busy!\n"); @@ -1998,6 +2106,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) case PCI_DEVICE_ID_LSI_SAS1078DE: instance->instancet = &megasas_instance_template_ppc; break; + case PCI_DEVICE_ID_LSI_SAS1078GEN2: + case PCI_DEVICE_ID_LSI_SAS0079GEN2: + instance->instancet = &megasas_instance_template_gen2; + break; case PCI_DEVICE_ID_LSI_SAS1064R: case PCI_DEVICE_ID_DELL_PERC5: default: @@ -2857,6 +2969,7 @@ static void megasas_shutdown(struct pci_dev *pdev) { struct megasas_instance *instance = pci_get_drvdata(pdev); megasas_flush_cache(instance); + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); } /** @@ -3292,7 +3405,7 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun return retval; } -static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, megasas_sysfs_set_dbg_lvl); static ssize_t diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index b0c41e6..0d03324 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -18,9 +18,9 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.03.20-rc1" -#define MEGASAS_RELDATE "March 10, 2008" -#define MEGASAS_EXT_VERSION "Mon. March 10 11:02:31 PDT 2008" +#define MEGASAS_VERSION "00.00.04.01" +#define MEGASAS_RELDATE "July 24, 2008" +#define MEGASAS_EXT_VERSION "Thu July 24 11:41:51 PST 2008" /* * Device IDs @@ -28,6 +28,8 @@ #define PCI_DEVICE_ID_LSI_SAS1078R 0x0060 #define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 +#define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078 +#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 /* * ===================================== @@ -580,6 +582,8 @@ struct megasas_ctrl_info { #define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10) #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 +#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 +#define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) /* * register set for both 1068 and 1078 controllers diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index edf9fdb..22052bb 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -23,7 +23,6 @@ * 1.2: PowerPC (big endian) support. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 6715ecb..9565acf 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -16,7 +16,6 @@ #ifndef _NSP32_H #define _NSP32_H -#include <linux/version.h> //#define NSP32_DEBUG 9 /* diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index a221b6e..24e6cb8 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -25,7 +25,6 @@ ***********************************************************************/ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index a319a20..45e7dcb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -993,6 +993,17 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + /* + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). + */ + if (fcport->loop_id != FC_NO_LOOP_ID) { + fcport->ha->isp_ops->fabric_logout(fcport->ha, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa); + fcport->loop_id = FC_NO_LOOP_ID; + } + qla2x00_abort_fcport_cmds(fcport); scsi_target_unblock(&rport->dev); } diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6da31ba..94a720e 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2237,6 +2237,7 @@ typedef struct scsi_qla_host { #define REGISTER_FDMI_NEEDED 26 #define FCPORT_UPDATE_NEEDED 27 #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ +#define UNLOADING 29 uint32_t device_flags; #define DFLG_LOCAL_DEVICES BIT_0 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 601a6b2..ee89ddd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -976,8 +976,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; - if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) && - (ha->fw_attributes & BIT_2)) { + if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || + IS_QLA84XX(ha)) && + (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; if ((!ha->max_npiv_vports) || ((ha->max_npiv_vports + 1) % @@ -3251,6 +3252,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) { int rval; uint8_t status = 0; + scsi_qla_host_t *vha; if (ha->flags.online) { ha->flags.online = 0; @@ -3265,6 +3267,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(ha, 0); + list_for_each_entry(vha, &ha->vp_list, vp_list) + qla2x00_mark_all_devices_lost(vha, 0); } else { if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 874d802..45a3b93 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -879,11 +879,12 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len) sp->request_sense_ptr += sense_len; sp->request_sense_length -= sense_len; if (sp->request_sense_length != 0) - sp->ha->status_srb = sp; + sp->fcport->ha->status_srb = sp; DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) " - "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, cp, cp->serial_number)); + "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no, + cp->device->channel, cp->device->id, cp->device->lun, cp, + cp->serial_number)); if (sense_len) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); @@ -1184,9 +1185,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) atomic_read(&fcport->state))); cp->result = DID_BUS_BUSY << 16; - if (atomic_read(&fcport->state) == FCS_ONLINE) { - qla2x00_mark_device_lost(ha, fcport, 1, 1); - } + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; case CS_RESET: @@ -1229,7 +1229,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) - qla2x00_mark_device_lost(ha, fcport, 1, 1); + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; default: diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index bc90d6b..813bc77 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2686,7 +2686,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha, set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); set_bit(VP_DPC_NEEDED, &ha->dpc_flags); - wake_up_process(ha->dpc_thread); + qla2xxx_wake_dpc(ha); } } diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 50baf6a..93560cd 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -6,7 +6,6 @@ */ #include "qla_def.h" -#include <linux/version.h> #include <linux/moduleparam.h> #include <linux/vmalloc.h> #include <linux/smp_lock.h> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7c8af7e..26afe44 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -780,7 +780,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t, sp = pha->outstanding_cmds[cnt]; if (!sp) continue; - if (ha->vp_idx != sp->ha->vp_idx) + + if (ha->vp_idx != sp->fcport->ha->vp_idx) continue; match = 0; switch (type) { @@ -1080,9 +1081,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res) sp = ha->outstanding_cmds[cnt]; if (sp) { ha->outstanding_cmds[cnt] = NULL; - sp->flags = 0; sp->cmd->result = res; - sp->cmd->host_scribble = (unsigned char *)NULL; qla2x00_sp_compl(ha, sp); } } @@ -1776,10 +1775,15 @@ probe_out: static void qla2x00_remove_one(struct pci_dev *pdev) { - scsi_qla_host_t *ha; + scsi_qla_host_t *ha, *vha, *temp; ha = pci_get_drvdata(pdev); + list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list) + fc_vport_terminate(vha->fc_vport); + + set_bit(UNLOADING, &ha->dpc_flags); + qla2x00_dfs_remove(ha); qla84xx_put_chip(ha); @@ -2451,8 +2455,10 @@ qla2x00_do_dpc(void *data) void qla2xxx_wake_dpc(scsi_qla_host_t *ha) { - if (ha->dpc_thread) - wake_up_process(ha->dpc_thread); + struct task_struct *t = ha->dpc_thread; + + if (!test_bit(UNLOADING, &ha->dpc_flags) && t) + wake_up_process(t); } /* diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 676c390..4160e4c 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k6" +#define QLA2XXX_VERSION "8.02.01-k7" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index d831a2b..87ab244 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1165,15 +1165,19 @@ EXPORT_SYMBOL(ssb_dma_translation); int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) { +#ifdef CONFIG_SSB_PCIHOST int err; +#endif switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST err = pci_set_dma_mask(dev->bus->host_pci, mask); if (err) return err; err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); return err; +#endif case SSB_BUSTYPE_SSB: return dma_set_mask(dev->dev, mask); default: @@ -1188,6 +1192,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, { switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST if (gfp_flags & GFP_DMA) { /* Workaround: The PCI API does not support passing * a GFP flag. */ @@ -1195,6 +1200,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, size, dma_handle, gfp_flags); } return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); +#endif case SSB_BUSTYPE_SSB: return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); default: @@ -1210,6 +1216,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, { switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST if (gfp_flags & GFP_DMA) { /* Workaround: The PCI API does not support passing * a GFP flag. */ @@ -1220,6 +1227,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, pci_free_consistent(dev->bus->host_pci, size, vaddr, dma_handle); return; +#endif case SSB_BUSTYPE_SSB: dma_free_coherent(dev->dev, size, vaddr, dma_handle); return; diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 2e9079d..4190be6 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -33,6 +33,19 @@ config UIO_PDRV If you don't know what to do here, say N. +config UIO_PDRV_GENIRQ + tristate "Userspace I/O platform driver with generic IRQ handling" + help + Platform driver for Userspace I/O devices, including generic + interrupt handling code. Shared interrupts are not supported. + + This kernel driver requires that the matching userspace driver + handles interrupts in a special way. Userspace is responsible + for acknowledging the hardware device if needed, and re-enabling + interrupts in the interrupt controller using the write() syscall. + + If you don't know what to do here, say N. + config UIO_SMX tristate "SMX cryptengine UIO interface" default n diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index e00ce0d..8667bbd 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_UIO) += uio.o obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o +obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o obj-$(CONFIG_UIO_SMX) += uio_smx.o diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c index 5d0d2e8..0b4ef39 100644 --- a/drivers/uio/uio_pdrv.c +++ b/drivers/uio/uio_pdrv.c @@ -88,6 +88,8 @@ static int uio_pdrv_remove(struct platform_device *pdev) uio_unregister_device(pdata->uioinfo); + kfree(pdata); + return 0; } @@ -114,5 +116,5 @@ module_exit(uio_pdrv_exit); MODULE_AUTHOR("Uwe Kleine-Koenig"); MODULE_DESCRIPTION("Userspace I/O platform driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c new file mode 100644 index 0000000..1f82c83 --- /dev/null +++ b/drivers/uio/uio_pdrv_genirq.c @@ -0,0 +1,188 @@ +/* + * drivers/uio/uio_pdrv_genirq.c + * + * Userspace I/O platform driver with generic IRQ handling code. + * + * Copyright (C) 2008 Magnus Damm + * + * Based on uio_pdrv.c by Uwe Kleine-Koenig, + * Copyright (C) 2008 by Digi International Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include <linux/platform_device.h> +#include <linux/uio_driver.h> +#include <linux/spinlock.h> +#include <linux/bitops.h> +#include <linux/interrupt.h> +#include <linux/stringify.h> + +#define DRIVER_NAME "uio_pdrv_genirq" + +struct uio_pdrv_genirq_platdata { + struct uio_info *uioinfo; + spinlock_t lock; + unsigned long flags; +}; + +static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info) +{ + struct uio_pdrv_genirq_platdata *priv = dev_info->priv; + + /* Just disable the interrupt in the interrupt controller, and + * remember the state so we can allow user space to enable it later. + */ + + if (!test_and_set_bit(0, &priv->flags)) + disable_irq_nosync(irq); + + return IRQ_HANDLED; +} + +static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) +{ + struct uio_pdrv_genirq_platdata *priv = dev_info->priv; + unsigned long flags; + + /* Allow user space to enable and disable the interrupt + * in the interrupt controller, but keep track of the + * state to prevent per-irq depth damage. + * + * Serialize this operation to support multiple tasks. + */ + + spin_lock_irqsave(&priv->lock, flags); + if (irq_on) { + if (test_and_clear_bit(0, &priv->flags)) + enable_irq(dev_info->irq); + } else { + if (!test_and_set_bit(0, &priv->flags)) + disable_irq(dev_info->irq); + } + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int uio_pdrv_genirq_probe(struct platform_device *pdev) +{ + struct uio_info *uioinfo = pdev->dev.platform_data; + struct uio_pdrv_genirq_platdata *priv; + struct uio_mem *uiomem; + int ret = -EINVAL; + int i; + + if (!uioinfo || !uioinfo->name || !uioinfo->version) { + dev_err(&pdev->dev, "missing platform_data\n"); + goto bad0; + } + + if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags) { + dev_err(&pdev->dev, "interrupt configuration error\n"); + goto bad0; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(&pdev->dev, "unable to kmalloc\n"); + goto bad0; + } + + priv->uioinfo = uioinfo; + spin_lock_init(&priv->lock); + priv->flags = 0; /* interrupt is enabled to begin with */ + + uiomem = &uioinfo->mem[0]; + + for (i = 0; i < pdev->num_resources; ++i) { + struct resource *r = &pdev->resource[i]; + + if (r->flags != IORESOURCE_MEM) + continue; + + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { + dev_warn(&pdev->dev, "device has more than " + __stringify(MAX_UIO_MAPS) + " I/O memory resources.\n"); + break; + } + + uiomem->memtype = UIO_MEM_PHYS; + uiomem->addr = r->start; + uiomem->size = r->end - r->start + 1; + ++uiomem; + } + + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { + uiomem->size = 0; + ++uiomem; + } + + /* This driver requires no hardware specific kernel code to handle + * interrupts. Instead, the interrupt handler simply disables the + * interrupt in the interrupt controller. User space is responsible + * for performing hardware specific acknowledge and re-enabling of + * the interrupt in the interrupt controller. + * + * Interrupt sharing is not supported. + */ + + uioinfo->irq_flags = IRQF_DISABLED; + uioinfo->handler = uio_pdrv_genirq_handler; + uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; + uioinfo->priv = priv; + + ret = uio_register_device(&pdev->dev, priv->uioinfo); + if (ret) { + dev_err(&pdev->dev, "unable to register uio device\n"); + goto bad1; + } + + platform_set_drvdata(pdev, priv); + return 0; + bad1: + kfree(priv); + bad0: + return ret; +} + +static int uio_pdrv_genirq_remove(struct platform_device *pdev) +{ + struct uio_pdrv_genirq_platdata *priv = platform_get_drvdata(pdev); + + uio_unregister_device(priv->uioinfo); + kfree(priv); + return 0; +} + +static struct platform_driver uio_pdrv_genirq = { + .probe = uio_pdrv_genirq_probe, + .remove = uio_pdrv_genirq_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init uio_pdrv_genirq_init(void) +{ + return platform_driver_register(&uio_pdrv_genirq); +} + +static void __exit uio_pdrv_genirq_exit(void) +{ + platform_driver_unregister(&uio_pdrv_genirq); +} + +module_init(uio_pdrv_genirq_init); +module_exit(uio_pdrv_genirq_exit); + +MODULE_AUTHOR("Magnus Damm"); +MODULE_DESCRIPTION("Userspace I/O platform driver with generic IRQ handling"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index cb01b51..b6483dd 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -64,7 +64,6 @@ #include <linux/ctype.h> #include <linux/sched.h> #include <linux/kthread.h> -#include <linux/version.h> #include <linux/mutex.h> #include <linux/freezer.h> diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index efc4373..c257453 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -589,8 +589,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) tasklet_schedule(&acm->urb_task); done: -err_out: mutex_unlock(&acm->mutex); +err_out: mutex_unlock(&open_mutex); return rv; @@ -1362,6 +1362,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2be37fe..5a7fa6f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev) */ intf->pm_usage_cnt = !(driver->supports_autosuspend); + /* Carry out a deferred switch to altsetting 0 */ + if (intf->needs_altsetting0) { + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + intf->needs_altsetting0 = 0; + } + error = driver->probe(intf, id); if (error) { mark_quiesced(intf); @@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev) driver->disconnect(intf); - /* reset other interface state */ - usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); + /* Reset other interface state. + * We cannot do a Set-Interface if the device is suspended or + * if it is prepared for a system sleep (since installing a new + * altsetting means creating new endpoint device entries). + * When either of these happens, defer the Set-Interface. + */ + if (!error && intf->dev.power.status == DPM_ON) + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + else + intf->needs_altsetting0 = 1; usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; @@ -798,7 +814,8 @@ void usb_forced_unbind_intf(struct usb_interface *intf) * The caller must hold @intf's device's lock, but not its pm_mutex * and not @intf->dev.sem. * - * FIXME: The caller must block system sleep transitions. + * Note: Rebinds will be skipped if a system sleep transition is in + * progress and the PM "complete" callback hasn't occurred yet. */ void usb_rebind_intf(struct usb_interface *intf) { @@ -814,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf) } /* Try to rebind the interface */ - intf->needs_binding = 0; - rc = device_attach(&intf->dev); - if (rc < 0) - dev_warn(&intf->dev, "rebind failed: %d\n", rc); + if (intf->dev.power.status == DPM_ON) { + intf->needs_binding = 0; + rc = device_attach(&intf->dev); + if (rc < 0) + dev_warn(&intf->dev, "rebind failed: %d\n", rc); + } } #ifdef CONFIG_PM @@ -829,7 +848,6 @@ void usb_rebind_intf(struct usb_interface *intf) * or rebind interfaces that have been unbound, according to @action. * * The caller must hold @udev's device lock. - * FIXME: For rebinds, the caller must block system sleep transitions. */ static void do_unbind_rebind(struct usb_device *udev, int action) { @@ -851,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action) } break; case DO_REBIND: - if (intf->needs_binding) { - - /* FIXME: The next line is needed because we are going to probe - * the interface, but as far as the PM core is concerned the - * interface is still suspended. The problem wouldn't exist - * if we could rebind the interface during the interface's own - * resume() call, but at the time the usb_device isn't locked! - * - * The real solution will be to carry this out during the device's - * complete() callback. Until that is implemented, we have to - * use this hack. - */ -// intf->dev.power.sleeping = 0; - + if (intf->needs_binding) usb_rebind_intf(intf); - } break; } } @@ -926,14 +930,14 @@ static int usb_resume_device(struct usb_device *udev) } /* Caller has locked intf's usb_device's pm mutex */ -static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) +static int usb_suspend_interface(struct usb_device *udev, + struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; int status = 0; /* with no hardware, USB interfaces only use FREEZE and ON states */ - if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || - !is_active(intf)) + if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) goto done; if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ @@ -944,7 +948,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) status = driver->suspend(intf, msg); if (status == 0) mark_quiesced(intf); - else if (!interface_to_usbdev(intf)->auto_pm) + else if (!udev->auto_pm) dev_err(&intf->dev, "%s error %d\n", "suspend", status); } else { @@ -961,13 +965,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) } /* Caller has locked intf's usb_device's pm_mutex */ -static int usb_resume_interface(struct usb_interface *intf, int reset_resume) +static int usb_resume_interface(struct usb_device *udev, + struct usb_interface *intf, int reset_resume) { struct usb_driver *driver; int status = 0; - if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || - is_active(intf)) + if (udev->state == USB_STATE_NOTATTACHED || is_active(intf)) goto done; /* Don't let autoresume interfere with unbinding */ @@ -975,8 +979,17 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) goto done; /* Can't resume it if it doesn't have a driver. */ - if (intf->condition == USB_INTERFACE_UNBOUND) + if (intf->condition == USB_INTERFACE_UNBOUND) { + + /* Carry out a deferred switch to altsetting 0 */ + if (intf->needs_altsetting0 && + intf->dev.power.status == DPM_ON) { + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + intf->needs_altsetting0 = 0; + } goto done; + } /* Don't resume if the interface is marked for rebinding */ if (intf->needs_binding) @@ -1151,7 +1164,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (udev->actconfig) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - status = usb_suspend_interface(intf, msg); + status = usb_suspend_interface(udev, intf, msg); if (status != 0) break; } @@ -1163,7 +1176,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (status != 0) { while (--i >= 0) { intf = udev->actconfig->interface[i]; - usb_resume_interface(intf, 0); + usb_resume_interface(udev, intf, 0); } /* Try another autosuspend when the interfaces aren't busy */ @@ -1276,7 +1289,7 @@ static int usb_resume_both(struct usb_device *udev) if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - usb_resume_interface(intf, udev->reset_resume); + usb_resume_interface(udev, intf, udev->reset_resume); } } @@ -1605,12 +1618,10 @@ int usb_external_resume_device(struct usb_device *udev) return status; } -static int usb_suspend(struct device *dev, pm_message_t message) +int usb_suspend(struct device *dev, pm_message_t message) { struct usb_device *udev; - if (!is_usb_device(dev)) /* Ignore PM for interfaces */ - return 0; udev = to_usb_device(dev); /* If udev is already suspended, we can skip this suspend and @@ -1629,12 +1640,10 @@ static int usb_suspend(struct device *dev, pm_message_t message) return usb_external_suspend_device(udev, message); } -static int usb_resume(struct device *dev) +int usb_resume(struct device *dev) { struct usb_device *udev; - if (!is_usb_device(dev)) /* Ignore PM for interfaces */ - return 0; udev = to_usb_device(dev); /* If udev->skip_sys_resume is set then udev was already suspended @@ -1646,17 +1655,10 @@ static int usb_resume(struct device *dev) return usb_external_resume_device(udev); } -#else - -#define usb_suspend NULL -#define usb_resume NULL - #endif /* CONFIG_PM */ struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, - .suspend = usb_suspend, - .resume = usb_resume, }; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f7bfd72..8abd4e5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd) return retval; } -void usb_enable_root_hub_irq (struct usb_bus *bus) -{ - struct usb_hcd *hcd; - - hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) - hcd->driver->hub_irq_enable (hcd); -} - /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 5b0b59b..e710ce0 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -212,8 +212,6 @@ struct hc_driver { int (*bus_suspend)(struct usb_hcd *); int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); - void (*hub_irq_enable)(struct usb_hcd *); - /* Needed only if port-change IRQs are level-triggered */ /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); @@ -379,8 +377,6 @@ extern struct list_head usb_bus_list; extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; -extern void usb_enable_root_hub_irq(struct usb_bus *bus); - extern int usb_find_interface_driver(struct usb_device *dev, struct usb_interface *interface); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 107e1d2..6a5cb01 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *udev) } clear_bit(port1, hub->busy_bits); - if (!hub->hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hub->hdev->bus); status = check_port_resume_type(udev, hub, port1, status, portchange, portstatus); @@ -3081,11 +3079,6 @@ static void hub_events(void) } } - /* If this is a root hub, tell the HCD it's okay to - * re-enable port-change interrupts now. */ - if (!hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hdev->bus); - loop_autopm: /* Allow autosuspend if we're not going to run again */ if (list_empty(&hub->event_list)) @@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) break; } clear_bit(port1, parent_hub->busy_bits); - if (!parent_hdev->parent && !parent_hub->busy_bits[0]) - usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index c0b1ae2..47111e8 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -601,15 +601,20 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { struct urb *victim; + unsigned long flags; - spin_lock_irq(&anchor->lock); + spin_lock_irqsave(&anchor->lock, flags); while (!list_empty(&anchor->urb_list)) { victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); /* this will unanchor the URB */ usb_unlink_urb(victim); + usb_put_urb(victim); + spin_lock_irqsave(&anchor->lock, flags); } - spin_unlock_irq(&anchor->lock); + spin_unlock_irqrestore(&anchor->lock, flags); } EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 84fcaa6..be1fa07 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif /* CONFIG_HOTPLUG */ -struct device_type usb_device_type = { - .name = "usb_device", - .release = usb_release_dev, - .uevent = usb_dev_uevent, -}; - #ifdef CONFIG_PM static int ksuspend_usb_init(void) @@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void) destroy_workqueue(ksuspend_usb_wq); } +/* USB device Power-Management thunks. + * There's no need to distinguish here between quiescing a USB device + * and powering it down; the generic_suspend() routine takes care of + * it by skipping the usb_port_suspend() call for a quiesce. And for + * USB interfaces there's no difference at all. + */ + +static int usb_dev_prepare(struct device *dev) +{ + return 0; /* Implement eventually? */ +} + +static void usb_dev_complete(struct device *dev) +{ + /* Currently used only for rebinding interfaces */ + usb_resume(dev); /* Implement eventually? */ +} + +static int usb_dev_suspend(struct device *dev) +{ + return usb_suspend(dev, PMSG_SUSPEND); +} + +static int usb_dev_resume(struct device *dev) +{ + return usb_resume(dev); +} + +static int usb_dev_freeze(struct device *dev) +{ + return usb_suspend(dev, PMSG_FREEZE); +} + +static int usb_dev_thaw(struct device *dev) +{ + return usb_resume(dev); +} + +static int usb_dev_poweroff(struct device *dev) +{ + return usb_suspend(dev, PMSG_HIBERNATE); +} + +static int usb_dev_restore(struct device *dev) +{ + return usb_resume(dev); +} + +static struct pm_ops usb_device_pm_ops = { + .prepare = usb_dev_prepare, + .complete = usb_dev_complete, + .suspend = usb_dev_suspend, + .resume = usb_dev_resume, + .freeze = usb_dev_freeze, + .thaw = usb_dev_thaw, + .poweroff = usb_dev_poweroff, + .restore = usb_dev_restore, +}; + #else #define ksuspend_usb_init() 0 #define ksuspend_usb_cleanup() do {} while (0) +#define usb_device_pm_ops (*(struct pm_ops *)0) #endif /* CONFIG_PM */ +struct device_type usb_device_type = { + .name = "usb_device", + .release = usb_release_dev, + .uevent = usb_dev_uevent, + .pm = &usb_device_pm_ops, +}; + /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ static unsigned usb_bus_is_wusb(struct usb_bus *bus) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index d9a6e16..9a1a45a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -41,6 +41,9 @@ extern void usb_host_cleanup(void); #ifdef CONFIG_PM +extern int usb_suspend(struct device *dev, pm_message_t msg); +extern int usb_resume(struct device *dev); + extern void usb_autosuspend_work(struct work_struct *work); extern int usb_port_suspend(struct usb_device *dev); extern int usb_port_resume(struct usb_device *dev); diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 1500e1b..abf8192 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -44,7 +44,6 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/sched.h> diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index a28513e..7cbc78a 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1622,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) struct pxa_udc *udc = the_controller; int retval; - if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind + if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->disconnect || !driver->setup) return -EINVAL; if (!udc) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 5388073..29d13eb 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -35,7 +35,6 @@ #include <linux/list.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/version.h> #include <linux/clk.h> #include <linux/debugfs.h> diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index d22a84f..8017f1c 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) /* * write bank1 address twice to ensure the 90ns delay (time * between BANK0 write and the priv_read_copy() call is at - * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) + * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns) */ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + HC_MEMORY_REG); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 6db7a28..4ed228a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index c094800..2ac4e02 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index cb0b506..fb3055f 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 439beb7..7ea9a7b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -36,18 +36,6 @@ /*-------------------------------------------------------------------------*/ -/* hcd->hub_irq_enable() */ -static void ohci_rhsc_enable (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - spin_lock_irq(&ohci->lock); - if (!ohci->autostop) - del_timer(&hcd->rh_timer); /* Prevent next poll */ - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - spin_unlock_irq(&ohci->lock); -} - #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { int poll_rh = 1; + int rhsc; + rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* keep on polling until we know a device is connected - * and RHSC is enabled */ + /* If no status changes are pending, enable status-change + * interrupts. + */ + if (!rhsc && !changed) { + rhsc = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc, &ohci->regs->intrenable); + } + + /* Keep on polling until we know a device is connected + * and RHSC is enabled, or until we autostop. + */ if (!ohci->autostop) { if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (ohci_readl(ohci, &ohci->regs->intrenable) & - OHCI_INTR_RHSC) + if (rhsc) poll_rh = 0; } else { ohci->autostop = 1; @@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (time_after_eq(jiffies, + } else if (rhsc && time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); + poll_rh = 0; } } break; @@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); } else { + if (!rhsc && (ohci->autostop || + ohci_to_hcd(ohci)->self.root_hub-> + do_remote_wakeup)) + ohci_writel(ohci, OHCI_INTR_RHSC, + &ohci->regs->intrenable); + /* everything is idle, no need for polling */ poll_rh = 0; } @@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { - int poll_rh = 1; - - /* keep on polling until RHSC is enabled */ + /* If RHSC is enabled, don't poll */ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) - poll_rh = 0; - return poll_rh; + return 0; + + /* If no status changes are pending, enable status-change interrupts */ + if (!changed) { + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + return 0; + } + return 1; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 9e31d44..de42283 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 3d532b7..1eb64d0 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 083e8df..a9c2ae3 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index b02cd07..658a2a9 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c index 605d59c..28467e2 100644 --- a/drivers/usb/host/ohci-pnx8550.c +++ b/drivers/usb/host/ohci-pnx8550.c @@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 91e6e10..7ac5326 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 523c301..cd3398b 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 55c9564..2089d8a 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, .start_port_reset = ohci_start_port_reset, #if defined(CONFIG_PM) .bus_suspend = ohci_bus_suspend, diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 8c9c484..7f0f35c 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 9e3dc40..f46af7a 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 4626b00..e4bbe8e 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index e7ee607..60f03cc 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 21b164e..cff2363 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index 3660c83..23fd6a8 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 20ad3c4..228f2b0 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) return 0; } -static void u132_hub_irq_enable(struct usb_hcd *hcd) -{ - struct u132 *u132 = hcd_to_u132(hcd); - if (u132->going > 1) { - dev_err(&u132->platform_dev->dev, "device has been removed %d\n" - , u132->going); - } else if (u132->going > 0) - dev_err(&u132->platform_dev->dev, "device is being removed\n"); -} - #ifdef CONFIG_PM static int u132_bus_suspend(struct usb_hcd *hcd) @@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = { .bus_suspend = u132_bus_suspend, .bus_resume = u132_bus_resume, .start_port_reset = u132_start_port_reset, - .hub_irq_enable = u132_hub_irq_enable, }; /* diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index e6ca997..a4ef77e 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -19,7 +19,6 @@ #include <linux/slab.h> #include <linux/sched.h> #include <linux/poll.h> -#include <linux/version.h> #include <linux/usb/iowarrior.h> /* Version Information */ diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index fbace41..69c34a5 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = { { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, { USB_DEVICE(0x0711, 0x0902) }, + { USB_DEVICE(0x0711, 0x0918) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index faca433..a001748 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -165,12 +165,11 @@ config USB_TUSB_OMAP_DMA help Enable DMA transfers on TUSB 6010 when OMAP DMA is available. -config USB_MUSB_LOGLEVEL +config USB_MUSB_DEBUG depends on USB_MUSB_HDRC - int 'Logging Level (0 - none / 3 - annoying / ... )' - default 0 + bool "Enable debugging messages" + default n help - Set the logging level. 0 disables the debugging altogether, - although when USB_DEBUG is set the value is at least 1. - Starting at level 3, per-transfer (urb, usb_request, packet, - or dma transfer) tracing may kick in. + This enables musb debugging. To set the logging level use the debug + module parameter. Starting at level 3, per-transfer (urb, usb_request, + packet, or dma transfer) tracing may kick in. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 88eb67d..b6af0d6 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -64,23 +64,6 @@ endif # Debugging -MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL) - -ifeq ("$(strip $(MUSB_DEBUG))","") - ifdef CONFIG_USB_DEBUG - MUSB_DEBUG:=1 - else - MUSB_DEBUG:=0 - endif +ifeq ($(CONFIG_USB_MUSB_DEBUG),y) + EXTRA_CFLAGS += -DDEBUG endif - -ifneq ($(MUSB_DEBUG),0) - EXTRA_CFLAGS += -DDEBUG - - ifeq ($(CONFIG_PROC_FS),y) - musb_hdrc-objs += musb_procfs.o - endif - -endif - -EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d68ec6d..c5b8f02 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -114,23 +114,14 @@ -#if MUSB_DEBUG > 0 -unsigned debug = MUSB_DEBUG; -module_param(debug, uint, 0); -MODULE_PARM_DESC(debug, "initial debug message level"); - -#define MUSB_VERSION_SUFFIX "/dbg" -#endif +unsigned debug; +module_param(debug, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" -#define MUSB_VERSION_BASE "6.0" - -#ifndef MUSB_VERSION_SUFFIX -#define MUSB_VERSION_SUFFIX "" -#endif -#define MUSB_VERSION MUSB_VERSION_BASE MUSB_VERSION_SUFFIX +#define MUSB_VERSION "6.0" #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION @@ -2037,6 +2028,8 @@ bad_config: musb->xceiv.state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); + if (status) + goto fail; DBG(1, "%s mode, status %d, devctl %02x %c\n", "HOST", status, @@ -2051,6 +2044,8 @@ bad_config: musb->xceiv.state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); + if (status) + goto fail; DBG(1, "%s mode, status %d, dev%02x\n", is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", @@ -2059,16 +2054,14 @@ bad_config: } - if (status == 0) - musb_debug_create("driver/musb_hdrc", musb); - else { + return 0; + fail: - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - return status; - } + if (musb->clock) + clk_put(musb->clock); + device_init_wakeup(dev, 0); + musb_free(musb); + return status; #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); @@ -2131,7 +2124,6 @@ static int __devexit musb_remove(struct platform_device *pdev) * - OTG mode: both roles are deactivated (or never-activated) */ musb_shutdown(pdev); - musb_debug_delete("driver/musb_hdrc", musb); #ifdef CONFIG_USB_MUSB_HDRC_HCD if (musb->board_mode == MUSB_HOST) usb_remove_hcd(musb_to_hcd(musb)); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index eade46d..8222725 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -485,23 +485,4 @@ extern int musb_platform_get_vbus_status(struct musb *musb); extern int __init musb_platform_init(struct musb *musb); extern int musb_platform_exit(struct musb *musb); -/*-------------------------- ProcFS definitions ---------------------*/ - -struct proc_dir_entry; - -#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS) -extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data); -extern void musb_debug_delete(char *name, struct musb *data); - -#else -static inline struct proc_dir_entry * -musb_debug_create(char *name, struct musb *data) -{ - return NULL; -} -static inline void musb_debug_delete(char *name, struct musb *data) -{ -} -#endif - #endif /* __MUSB_CORE_H__ */ diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 3bdb311..4d27944 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -48,11 +48,7 @@ __func__, __LINE__ , ## args); \ } } while (0) -#if MUSB_DEBUG > 0 extern unsigned debug; -#else -#define debug 0 -#endif static inline int _dbg_level(unsigned l) { diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 48d7d3c..a57652f 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -476,6 +476,7 @@ static void ep0_rxstate(struct musb *musb) return; musb->ackpend = 0; } + musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, tmp); } @@ -528,6 +529,7 @@ static void ep0_txstate(struct musb *musb) } /* send it out, triggering a "txpktrdy cleared" irq */ + musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, csr); } diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c deleted file mode 100644 index 55e6b78..0000000 --- a/drivers/usb/musb/musb_procfs.c +++ /dev/null @@ -1,830 +0,0 @@ -/* - * MUSB OTG driver debug support - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <linux/kernel.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/uaccess.h> /* FIXME remove procfs writes */ -#include <asm/arch/hardware.h> - -#include "musb_core.h" - -#include "davinci.h" - -#ifdef CONFIG_USB_MUSB_HDRC_HCD - -static int dump_qh(struct musb_qh *qh, char *buf, unsigned max) -{ - int count; - int tmp; - struct usb_host_endpoint *hep = qh->hep; - struct urb *urb; - - count = snprintf(buf, max, " qh %p dev%d ep%d%s max%d\n", - qh, qh->dev->devnum, qh->epnum, - ({ char *s; switch (qh->type) { - case USB_ENDPOINT_XFER_BULK: - s = "-bulk"; break; - case USB_ENDPOINT_XFER_INT: - s = "-int"; break; - case USB_ENDPOINT_XFER_CONTROL: - s = ""; break; - default: - s = "iso"; break; - }; s; }), - qh->maxpacket); - if (count <= 0) - return 0; - buf += count; - max -= count; - - list_for_each_entry(urb, &hep->urb_list, urb_list) { - tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n", - usb_pipein(urb->pipe) ? "in" : "out", - urb, urb->actual_length, - urb->transfer_buffer_length); - if (tmp <= 0) - break; - tmp = min(tmp, (int)max); - count += tmp; - buf += tmp; - max -= tmp; - } - return count; -} - -static int -dump_queue(struct list_head *q, char *buf, unsigned max) -{ - int count = 0; - struct musb_qh *qh; - - list_for_each_entry(qh, q, ring) { - int tmp; - - tmp = dump_qh(qh, buf, max); - if (tmp <= 0) - break; - tmp = min(tmp, (int)max); - count += tmp; - buf += tmp; - max -= tmp; - } - return count; -} - -#endif /* HCD */ - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC -static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max) -{ - char *buf = buffer; - int code = 0; - void __iomem *regs = ep->hw_ep->regs; - char *mode = "1buf"; - - if (ep->is_in) { - if (ep->hw_ep->tx_double_buffered) - mode = "2buf"; - } else { - if (ep->hw_ep->rx_double_buffered) - mode = "2buf"; - } - - do { - struct usb_request *req; - - code = snprintf(buf, max, - "\n%s (hw%d): %s%s, csr %04x maxp %04x\n", - ep->name, ep->current_epnum, - mode, ep->dma ? " dma" : "", - musb_readw(regs, - (ep->is_in || !ep->current_epnum) - ? MUSB_TXCSR - : MUSB_RXCSR), - musb_readw(regs, ep->is_in - ? MUSB_TXMAXP - : MUSB_RXMAXP) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() && ep->current_epnum) { - unsigned cppi = ep->current_epnum - 1; - void __iomem *base = ep->musb->ctrl_base; - unsigned off1 = cppi << 2; - void __iomem *ram = base; - char tmp[16]; - - if (ep->is_in) { - ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi); - tmp[0] = 0; - } else { - ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi); - snprintf(tmp, sizeof tmp, "%d left, ", - musb_readl(base, - DAVINCI_RXCPPI_BUFCNT0_REG + off1)); - } - - code = snprintf(buf, max, "%cX DMA%d: %s" - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - ep->is_in ? 'T' : 'R', - ep->current_epnum - 1, tmp, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (list_empty(&ep->req_list)) { - code = snprintf(buf, max, "\t(queue empty)\n"); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - break; - } - list_for_each_entry(req, &ep->req_list, list) { - code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n", - req, - req->zero ? "zero, " : "", - req->short_not_ok ? "!short, " : "", - req->actual, req->length); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } while (0); - return buf - buffer; -} -#endif - -static int -dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max) -{ - int code = 0; - char *buf = aBuffer; - struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; - - do { - musb_ep_select(musb->mregs, epnum); -#ifdef CONFIG_USB_MUSB_HDRC_HCD - if (is_host_active(musb)) { - int dump_rx, dump_tx; - void __iomem *regs = hw_ep->regs; - - /* TEMPORARY (!) until we have a real periodic - * schedule tree ... - */ - if (!epnum) { - /* control is shared, uses RX queue - * but (mostly) shadowed tx registers - */ - dump_tx = !list_empty(&musb->control); - dump_rx = 0; - } else if (hw_ep == musb->bulk_ep) { - dump_tx = !list_empty(&musb->out_bulk); - dump_rx = !list_empty(&musb->in_bulk); - } else if (musb->periodic[epnum]) { - struct usb_host_endpoint *hep; - - hep = musb->periodic[epnum]->hep; - dump_rx = hep->desc.bEndpointAddress - & USB_ENDPOINT_DIR_MASK; - dump_tx = !dump_rx; - } else - break; - /* END TEMPORARY */ - - - if (dump_rx) { - code = snprintf(buf, max, - "\nRX%d: %s rxcsr %04x interval %02x " - "max %04x type %02x; " - "dev %d hub %d port %d" - "\n", - epnum, - hw_ep->rx_double_buffered - ? "2buf" : "1buf", - musb_readw(regs, MUSB_RXCSR), - musb_readb(regs, MUSB_RXINTERVAL), - musb_readw(regs, MUSB_RXMAXP), - musb_readb(regs, MUSB_RXTYPE), - /* FIXME: assumes multipoint */ - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXFUNCADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXHUBADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXHUBPORT)) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() - && epnum - && hw_ep->rx_channel) { - unsigned cppi = epnum - 1; - unsigned off1 = cppi << 2; - void __iomem *base; - void __iomem *ram; - char tmp[16]; - - base = musb->ctrl_base; - ram = DAVINCI_RXCPPI_STATERAM_OFFSET( - cppi) + base; - snprintf(tmp, sizeof tmp, "%d left, ", - musb_readl(base, - DAVINCI_RXCPPI_BUFCNT0_REG - + off1)); - - code = snprintf(buf, max, - " rx dma%d: %s" - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - cppi, tmp, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (hw_ep == musb->bulk_ep - && !list_empty( - &musb->in_bulk)) { - code = dump_queue(&musb->in_bulk, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (musb->periodic[epnum]) { - code = dump_qh(musb->periodic[epnum], - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } - - if (dump_tx) { - code = snprintf(buf, max, - "\nTX%d: %s txcsr %04x interval %02x " - "max %04x type %02x; " - "dev %d hub %d port %d" - "\n", - epnum, - hw_ep->tx_double_buffered - ? "2buf" : "1buf", - musb_readw(regs, MUSB_TXCSR), - musb_readb(regs, MUSB_TXINTERVAL), - musb_readw(regs, MUSB_TXMAXP), - musb_readb(regs, MUSB_TXTYPE), - /* FIXME: assumes multipoint */ - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXFUNCADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXHUBADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXHUBPORT)) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() - && epnum - && hw_ep->tx_channel) { - unsigned cppi = epnum - 1; - void __iomem *base; - void __iomem *ram; - - base = musb->ctrl_base; - ram = DAVINCI_RXCPPI_STATERAM_OFFSET( - cppi) + base; - code = snprintf(buf, max, - " tx dma%d: " - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - cppi, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (hw_ep == musb->control_ep - && !list_empty( - &musb->control)) { - code = dump_queue(&musb->control, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (hw_ep == musb->bulk_ep - && !list_empty( - &musb->out_bulk)) { - code = dump_queue(&musb->out_bulk, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (musb->periodic[epnum]) { - code = dump_qh(musb->periodic[epnum], - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } - } -#endif -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - if (is_peripheral_active(musb)) { - code = 0; - - if (hw_ep->ep_in.desc || !epnum) { - code = dump_ep(&hw_ep->ep_in, buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - if (hw_ep->ep_out.desc) { - code = dump_ep(&hw_ep->ep_out, buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } -#endif - } while (0); - - return buf - aBuffer; -} - -/* Dump the current status and compile options. - * @param musb the device driver instance - * @param buffer where to dump the status; it must be big enough to hold the - * result otherwise "BAD THINGS HAPPENS(TM)". - */ -static int dump_header_stats(struct musb *musb, char *buffer) -{ - int code, count = 0; - const void __iomem *mbase = musb->mregs; - - *buffer = 0; - count = sprintf(buffer, "Status: %sHDRC, Mode=%s " - "(Power=%02x, DevCtl=%02x)\n", - (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb), - musb_readb(mbase, MUSB_POWER), - musb_readb(mbase, MUSB_DEVCTL)); - if (count <= 0) - return 0; - buffer += count; - - code = sprintf(buffer, "OTG state: %s; %sactive\n", - otg_state_string(musb), - musb->is_active ? "" : "in"); - if (code <= 0) - goto done; - buffer += code; - count += code; - - code = sprintf(buffer, - "Options: " -#ifdef CONFIG_MUSB_PIO_ONLY - "pio" -#elif defined(CONFIG_USB_TI_CPPI_DMA) - "cppi-dma" -#elif defined(CONFIG_USB_INVENTRA_DMA) - "musb-dma" -#elif defined(CONFIG_USB_TUSB_OMAP_DMA) - "tusb-omap-dma" -#else - "?dma?" -#endif - ", " -#ifdef CONFIG_USB_MUSB_OTG - "otg (peripheral+host)" -#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) - "peripheral" -#elif defined(CONFIG_USB_MUSB_HDRC_HCD) - "host" -#endif - ", debug=%d [eps=%d]\n", - debug, - musb->nr_endpoints); - if (code <= 0) - goto done; - count += code; - buffer += code; - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - code = sprintf(buffer, "Peripheral address: %02x\n", - musb_readb(musb->ctrl_base, MUSB_FADDR)); - if (code <= 0) - goto done; - buffer += code; - count += code; -#endif - -#ifdef CONFIG_USB_MUSB_HDRC_HCD - code = sprintf(buffer, "Root port status: %08x\n", - musb->port1_status); - if (code <= 0) - goto done; - buffer += code; - count += code; -#endif - -#ifdef CONFIG_ARCH_DAVINCI - code = sprintf(buffer, - "DaVinci: ctrl=%02x stat=%1x phy=%03x\n" - "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x" - "\n", - musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG), - musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG), - __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), - musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG), - musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG), - musb_readl(musb->ctrl_base, - DAVINCI_USB_INT_SOURCE_REG), - musb_readl(musb->ctrl_base, - DAVINCI_USB_INT_MASK_REG)); - if (code <= 0) - goto done; - count += code; - buffer += code; -#endif /* DAVINCI */ - -#ifdef CONFIG_USB_TUSB6010 - code = sprintf(buffer, - "TUSB6010: devconf %08x, phy enable %08x drive %08x" - "\n\totg %03x timer %08x" - "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x" - "\n", - musb_readl(musb->ctrl_base, TUSB_DEV_CONF), - musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE), - musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL), - musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT), - musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER), - musb_readl(musb->ctrl_base, TUSB_PRCM_CONF), - musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT), - musb_readl(musb->ctrl_base, TUSB_INT_SRC), - musb_readl(musb->ctrl_base, TUSB_INT_MASK)); - if (code <= 0) - goto done; - count += code; - buffer += code; -#endif /* DAVINCI */ - - if (is_cppi_enabled() && musb->dma_controller) { - code = sprintf(buffer, - "CPPI: txcr=%d txsrc=%01x txena=%01x; " - "rxcr=%d rxsrc=%01x rxena=%01x " - "\n", - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_CTRL_REG), - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_RAW_REG), - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_INTENAB_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_CTRL_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_RAW_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_INTENAB_REG)); - if (code <= 0) - goto done; - count += code; - buffer += code; - } - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - if (is_peripheral_enabled(musb)) { - code = sprintf(buffer, "Gadget driver: %s\n", - musb->gadget_driver - ? musb->gadget_driver->driver.name - : "(none)"); - if (code <= 0) - goto done; - count += code; - buffer += code; - } -#endif - -done: - return count; -} - -/* Write to ProcFS - * - * C soft-connect - * c soft-disconnect - * I enable HS - * i disable HS - * s stop session - * F force session (OTG-unfriendly) - * E rElinquish bus (OTG) - * H request host mode - * h cancel host request - * T start sending TEST_PACKET - * D<num> set/query the debug level - */ -static int musb_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - char cmd; - u8 reg; - struct musb *musb = (struct musb *)data; - void __iomem *mbase = musb->mregs; - - /* MOD_INC_USE_COUNT; */ - - if (unlikely(copy_from_user(&cmd, buffer, 1))) - return -EFAULT; - - switch (cmd) { - case 'C': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - | MUSB_POWER_SOFTCONN; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'c': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - & ~MUSB_POWER_SOFTCONN; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'I': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - | MUSB_POWER_HSENAB; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'i': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - & ~MUSB_POWER_HSENAB; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'F': - reg = musb_readb(mbase, MUSB_DEVCTL); - reg |= MUSB_DEVCTL_SESSION; - musb_writeb(mbase, MUSB_DEVCTL, reg); - break; - - case 'H': - if (mbase) { - reg = musb_readb(mbase, MUSB_DEVCTL); - reg |= MUSB_DEVCTL_HR; - musb_writeb(mbase, MUSB_DEVCTL, reg); - /* MUSB_HST_MODE( ((struct musb*)data) ); */ - /* WARNING("Host Mode\n"); */ - } - break; - - case 'h': - if (mbase) { - reg = musb_readb(mbase, MUSB_DEVCTL); - reg &= ~MUSB_DEVCTL_HR; - musb_writeb(mbase, MUSB_DEVCTL, reg); - } - break; - - case 'T': - if (mbase) { - musb_load_testpacket(musb); - musb_writeb(mbase, MUSB_TESTMODE, - MUSB_TEST_PACKET); - } - break; - -#if (MUSB_DEBUG > 0) - /* set/read debug level */ - case 'D':{ - if (count > 1) { - char digits[8], *p = digits; - int i = 0, level = 0, sign = 1; - int len = min(count - 1, (unsigned long)8); - - if (copy_from_user(&digits, &buffer[1], len)) - return -EFAULT; - - /* optional sign */ - if (*p == '-') { - len -= 1; - sign = -sign; - p++; - } - - /* read it */ - while (i++ < len && *p > '0' && *p < '9') { - level = level * 10 + (*p - '0'); - p++; - } - - level *= sign; - DBG(1, "debug level %d\n", level); - debug = level; - } - } - break; - - - case '?': - INFO("?: you are seeing it\n"); - INFO("C/c: soft connect enable/disable\n"); - INFO("I/i: hispeed enable/disable\n"); - INFO("F: force session start\n"); - INFO("H: host mode\n"); - INFO("T: start sending TEST_PACKET\n"); - INFO("D: set/read dbug level\n"); - break; -#endif - - default: - ERR("Command %c not implemented\n", cmd); - break; - } - - musb_platform_try_idle(musb, 0); - - return count; -} - -static int musb_proc_read(char *page, char **start, - off_t off, int count, int *eof, void *data) -{ - char *buffer = page; - int code = 0; - unsigned long flags; - struct musb *musb = data; - unsigned epnum; - - count -= off; - count -= 1; /* for NUL at end */ - if (count <= 0) - return -EINVAL; - - spin_lock_irqsave(&musb->lock, flags); - - code = dump_header_stats(musb, buffer); - if (code > 0) { - buffer += code; - count -= code; - } - - /* generate the report for the end points */ - /* REVISIT ... not unless something's connected! */ - for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints; - epnum++) { - code = dump_end_info(musb, epnum, buffer, count); - if (code > 0) { - buffer += code; - count -= code; - } - } - - musb_platform_try_idle(musb, 0); - - spin_unlock_irqrestore(&musb->lock, flags); - *eof = 1; - - return buffer - page; -} - -void __devexit musb_debug_delete(char *name, struct musb *musb) -{ - if (musb->proc_entry) - remove_proc_entry(name, NULL); -} - -struct proc_dir_entry *__init -musb_debug_create(char *name, struct musb *data) -{ - struct proc_dir_entry *pde; - - /* FIXME convert everything to seq_file; then later, debugfs */ - - if (!name) - return NULL; - - pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL); - data->proc_entry = pde; - if (pde) { - pde->data = data; - /* pde->owner = THIS_MODULE; */ - - pde->read_proc = musb_proc_read; - pde->write_proc = musb_proc_write; - - pde->size = 0; - - pr_debug("Registered /proc/%s\n", name); - } else { - pr_debug("Cannot create a valid proc file entry"); - } - - return pde; -} diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 2e663f1..d953820 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -38,8 +38,6 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -#include <linux/version.h> - /* the mode to be set when the port ist opened */ static int initial_mode = 1; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e143198..9f9cd36 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -173,6 +173,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define KYOCERA_PRODUCT_KPC680 0x180a #define ANYDATA_VENDOR_ID 0x16d5 +#define ANYDATA_PRODUCT_ADU_620UW 0x6202 #define ANYDATA_PRODUCT_ADU_E100A 0x6501 #define ANYDATA_PRODUCT_ADU_500A 0x6502 @@ -318,6 +319,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 4bd569e..314d186 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c @@ -11,7 +11,6 @@ * Code is based on s3fb */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 940467a..6d5aa80 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -733,7 +733,6 @@ static int bfin_bf54x_remove(struct platform_device *pdev) static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) { struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_bf54xfb_info *info = fbinfo->par; bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); disable_dma(CH_EPPI0); @@ -747,8 +746,18 @@ static int bfin_bf54x_resume(struct platform_device *pdev) struct fb_info *fbinfo = platform_get_drvdata(pdev); struct bfin_bf54xfb_info *info = fbinfo->par; - enable_dma(CH_EPPI0); - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); + if (info->lq043_open_cnt) { + + bfin_write_EPPI0_CONTROL(0); + SSYNC(); + + config_dma(info); + config_ppi(info); + + /* start dma */ + enable_dma(CH_EPPI0); + bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); + } return 0; } diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 59df132..4835bdc 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = { .page_mkwrite = fb_deferred_io_mkwrite, }; +static int fb_deferred_io_set_page_dirty(struct page *page) +{ + if (!PageDirty(page)) + SetPageDirty(page); + return 0; +} + +static const struct address_space_operations fb_deferred_io_aops = { + .set_page_dirty = fb_deferred_io_set_page_dirty, +}; + static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) { vma->vm_ops = &fb_deferred_io_vm_ops; @@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info) } EXPORT_SYMBOL_GPL(fb_deferred_io_init); +void fb_deferred_io_open(struct fb_info *info, + struct inode *inode, + struct file *file) +{ + file->f_mapping->a_ops = &fb_deferred_io_aops; +} +EXPORT_SYMBOL_GPL(fb_deferred_io_open); + void fb_deferred_io_cleanup(struct fb_info *info) { void *screen_base = (void __force *) info->screen_base; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6b48780..98843c2 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1344,6 +1344,10 @@ fb_open(struct inode *inode, struct file *file) if (res) module_put(info->fbops->owner); } +#ifdef CONFIG_FB_DEFERRED_IO + if (info->fbdefio) + fb_deferred_io_open(info, inode, file); +#endif out: unlock_kernel(); return res; diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 3f1ca2a..c6dd924 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1746,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev) release_mem_region(fix->mmio_start, fix->mmio_len); pci_set_drvdata(pdev, NULL); + fb_dealloc_cmap(&info->cmap); kfree(info->pixmap.addr); kfree(info); } diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 8361bd0..4dcec48 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -11,7 +11,6 @@ * which is based on the code of neofb. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index f6ef6cc..4c32c06 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -595,6 +595,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) info->fbops = &sh_mobile_lcdc_ops; info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; + info->var.width = cfg->lcd_size_cfg.width; + info->var.height = cfg->lcd_size_cfg.height; info->var.activate = FB_ACTIVATE_NOW; error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); if (error) diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h index c4aba59..7491abf 100644 --- a/drivers/video/vermilion/vermilion.h +++ b/drivers/video/vermilion/vermilion.h @@ -30,7 +30,6 @@ #define _VERMILION_H_ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/pci.h> #include <asm/atomic.h> #include <linux/mutex.h> diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index 34aae7a..3df17dc 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c @@ -12,7 +12,6 @@ * (http://davesdomain.org.uk/viafb/) */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 7b3a842..5da3d24 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -24,7 +24,6 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/version.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 56372ec..dfc0197 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -914,7 +914,9 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* Stash our initial stack pointer into the mm structure */ current->mm->start_stack = (unsigned long )sp; - +#ifdef FLAT_PLAT_INIT + FLAT_PLAT_INIT(regs); +#endif DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n", (int)regs, (int)start_addr, (int)current->mm->start_stack); diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 7562053..8d7e88e 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -120,8 +120,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (bprm->misc_bang) goto _ret; - bprm->misc_bang = 1; - /* to keep locking time low, we copy the interpreter string */ read_lock(&entries_lock); fmt = check_file(bprm); @@ -199,6 +197,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval < 0) goto _error; + bprm->misc_bang = 1; + retval = search_binary_handler (bprm, regs); if (retval < 0) goto _error; diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 0c3b618..f40423e 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -43,58 +43,13 @@ static DEFINE_MUTEX(read_mutex); static int cramfs_iget5_test(struct inode *inode, void *opaque) { struct cramfs_inode *cramfs_inode = opaque; - - if (inode->i_ino != CRAMINO(cramfs_inode)) - return 0; /* does not match */ - - if (inode->i_ino != 1) - return 1; - - /* all empty directories, char, block, pipe, and sock, share inode #1 */ - - if ((inode->i_mode != cramfs_inode->mode) || - (inode->i_gid != cramfs_inode->gid) || - (inode->i_uid != cramfs_inode->uid)) - return 0; /* does not match */ - - if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && - (inode->i_rdev != old_decode_dev(cramfs_inode->size))) - return 0; /* does not match */ - - return 1; /* matches */ + return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; } static int cramfs_iget5_set(struct inode *inode, void *opaque) { - static struct timespec zerotime; struct cramfs_inode *cramfs_inode = opaque; - inode->i_mode = cramfs_inode->mode; - inode->i_uid = cramfs_inode->uid; - inode->i_size = cramfs_inode->size; - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; - inode->i_gid = cramfs_inode->gid; - /* Struct copy intentional */ - inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); - /* inode->i_nlink is left 1 - arguably wrong for directories, - but it's the best we can do without reading the directory - contents. 1 yields the right result in GNU find, even - without -noleaf option. */ - if (S_ISREG(inode->i_mode)) { - inode->i_fop = &generic_ro_fops; - inode->i_data.a_ops = &cramfs_aops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &cramfs_dir_inode_operations; - inode->i_fop = &cramfs_directory_operations; - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_data.a_ops = &cramfs_aops; - } else { - inode->i_size = 0; - inode->i_blocks = 0; - init_special_inode(inode, inode->i_mode, - old_decode_dev(cramfs_inode->size)); - } return 0; } @@ -104,12 +59,48 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), cramfs_iget5_test, cramfs_iget5_set, cramfs_inode); + static struct timespec zerotime; + if (inode && (inode->i_state & I_NEW)) { + inode->i_mode = cramfs_inode->mode; + inode->i_uid = cramfs_inode->uid; + inode->i_size = cramfs_inode->size; + inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; + inode->i_gid = cramfs_inode->gid; + /* Struct copy intentional */ + inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; + /* inode->i_nlink is left 1 - arguably wrong for directories, + but it's the best we can do without reading the directory + contents. 1 yields the right result in GNU find, even + without -noleaf option. */ + if (S_ISREG(inode->i_mode)) { + inode->i_fop = &generic_ro_fops; + inode->i_data.a_ops = &cramfs_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &cramfs_dir_inode_operations; + inode->i_fop = &cramfs_directory_operations; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &cramfs_aops; + } else { + inode->i_size = 0; + inode->i_blocks = 0; + init_special_inode(inode, inode->i_mode, + old_decode_dev(cramfs_inode->size)); + } unlock_new_inode(inode); } return inode; } +static void cramfs_drop_inode(struct inode *inode) +{ + if (inode->i_ino == 1) + generic_delete_inode(inode); + else + generic_drop_inode(inode); +} + /* * We have our own block cache: don't fill up the buffer cache * with the rom-image, because the way the filesystem is set @@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = { .put_super = cramfs_put_super, .remount_fs = cramfs_remount, .statfs = cramfs_statfs, + .drop_inode = cramfs_drop_inode, }; static int cramfs_get_sb(struct file_system_type *fs_type, diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1ae5004..e9fa960 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -1626,6 +1626,9 @@ ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, free_blocks = percpu_counter_sum_and_set(&sbi->s_freeblocks_counter); #endif + if (free_blocks <= root_blocks) + /* we don't have free space */ + return 0; if (free_blocks - root_blocks < nblocks) return free_blocks - root_blocks; return nblocks; diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index d3d23d7..ec8e33b 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -411,7 +411,7 @@ static int call_filldir(struct file * filp, void * dirent, get_dtype(sb, fname->file_type)); if (error) { filp->f_pos = curr_pos; - info->extra_fname = fname->next; + info->extra_fname = fname; return error; } fname = fname->next; @@ -450,11 +450,21 @@ static int ext4_dx_readdir(struct file * filp, * If there are any leftover names on the hash collision * chain, return them first. */ - if (info->extra_fname && - call_filldir(filp, dirent, filldir, info->extra_fname)) - goto finished; + if (info->extra_fname) { + if (call_filldir(filp, dirent, filldir, info->extra_fname)) + goto finished; - if (!info->curr_node) + info->extra_fname = NULL; + info->curr_node = rb_next(info->curr_node); + if (!info->curr_node) { + if (info->next_hash == ~0) { + filp->f_pos = EXT4_HTREE_EOF; + goto finished; + } + info->curr_hash = info->next_hash; + info->curr_minor_hash = 0; + } + } else if (!info->curr_node) info->curr_node = rb_first(&info->root); while (1) { diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6c7924d..2950032 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1072,6 +1072,8 @@ extern void ext4_set_inode_flags(struct inode *); extern void ext4_get_inode_flags(struct ext4_inode_info *); extern void ext4_set_aops(struct inode *inode); extern int ext4_writepage_trans_blocks(struct inode *); +extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks); +extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); extern int ext4_block_truncate_page(handle_t *handle, struct address_space *mapping, loff_t from); extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); @@ -1227,6 +1229,8 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations; /* extents.c */ extern int ext4_ext_tree_init(handle_t *handle, struct inode *); extern int ext4_ext_writepage_trans_blocks(struct inode *, int); +extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, + int chunk); extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, ext4_lblk_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 6c166c0..d33dc56 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h @@ -216,7 +216,9 @@ extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks); extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *); extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t); extern int ext4_extent_tree_init(handle_t *, struct inode *); -extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *); +extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode, + int num, + struct ext4_ext_path *path); extern int ext4_ext_try_to_merge(struct inode *inode, struct ext4_ext_path *path, struct ext4_extent *); diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index eb8bc3a..b455c68 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -51,6 +51,14 @@ EXT4_XATTR_TRANS_BLOCKS - 2 + \ 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) +/* + * Define the number of metadata blocks we need to account to modify data. + * + * This include super block, inode block, quota blocks and xattr blocks + */ +#define EXT4_META_TRANS_BLOCKS(sb) (EXT4_XATTR_TRANS_BLOCKS + \ + 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) + /* Delete operations potentially hit one directory's namespace plus an * entire inode, plus arbitrary amounts of bitmap/indirection data. Be * generous. We can grow the delete transaction later if necessary. */ diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 612c3d2..b24d3c5 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1747,54 +1747,61 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, } /* - * ext4_ext_calc_credits_for_insert: - * This routine returns max. credits that the extent tree can consume. - * It should be OK for low-performance paths like ->writepage() - * To allow many writing processes to fit into a single transaction, - * the caller should calculate credits under i_data_sem and - * pass the actual path. + * ext4_ext_calc_credits_for_single_extent: + * This routine returns max. credits that needed to insert an extent + * to the extent tree. + * When pass the actual path, the caller should calculate credits + * under i_data_sem. */ -int ext4_ext_calc_credits_for_insert(struct inode *inode, +int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks, struct ext4_ext_path *path) { - int depth, needed; - if (path) { + int depth = ext_depth(inode); + int ret = 0; + /* probably there is space in leaf? */ - depth = ext_depth(inode); if (le16_to_cpu(path[depth].p_hdr->eh_entries) - < le16_to_cpu(path[depth].p_hdr->eh_max)) - return 1; - } + < le16_to_cpu(path[depth].p_hdr->eh_max)) { - /* - * given 32-bit logical block (4294967296 blocks), max. tree - * can be 4 levels in depth -- 4 * 340^4 == 53453440000. - * Let's also add one more level for imbalance. - */ - depth = 5; - - /* allocation of new data block(s) */ - needed = 2; + /* + * There are some space in the leaf tree, no + * need to account for leaf block credit + * + * bitmaps and block group descriptor blocks + * and other metadat blocks still need to be + * accounted. + */ + /* 1 bitmap, 1 block group descriptor */ + ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb); + } + } - /* - * tree can be full, so it would need to grow in depth: - * we need one credit to modify old root, credits for - * new root will be added in split accounting - */ - needed += 1; + return ext4_chunk_trans_blocks(inode, nrblocks); +} - /* - * Index split can happen, we would need: - * allocate intermediate indexes (bitmap + group) - * + change two blocks at each level, but root (already included) - */ - needed += (depth * 2) + (depth * 2); +/* + * How many index/leaf blocks need to change/allocate to modify nrblocks? + * + * if nrblocks are fit in a single extent (chunk flag is 1), then + * in the worse case, each tree level index/leaf need to be changed + * if the tree split due to insert a new extent, then the old tree + * index/leaf need to be updated too + * + * If the nrblocks are discontiguous, they could cause + * the whole tree split more than once, but this is really rare. + */ +int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) +{ + int index; + int depth = ext_depth(inode); - /* any allocation modifies superblock */ - needed += 1; + if (chunk) + index = depth * 2; + else + index = depth * 3; - return needed; + return index; } static int ext4_remove_blocks(handle_t *handle, struct inode *inode, @@ -1921,9 +1928,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, correct_index = 1; credits += (ext_depth(inode)) + 1; } -#ifdef CONFIG_QUOTA credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif err = ext4_ext_journal_restart(handle, credits); if (err) @@ -2805,7 +2810,7 @@ void ext4_ext_truncate(struct inode *inode) /* * probably first extent we're gonna free will be last in block */ - err = ext4_writepage_trans_blocks(inode) + 3; + err = ext4_writepage_trans_blocks(inode); handle = ext4_journal_start(inode, err); if (IS_ERR(handle)) return; @@ -2819,7 +2824,7 @@ void ext4_ext_truncate(struct inode *inode) down_write(&EXT4_I(inode)->i_data_sem); ext4_ext_invalidate_cache(inode); - ext4_mb_discard_inode_preallocations(inode); + ext4_discard_reservation(inode); /* * TODO: optimization is possible here. @@ -2858,27 +2863,6 @@ out_stop: ext4_journal_stop(handle); } -/* - * ext4_ext_writepage_trans_blocks: - * calculate max number of blocks we could modify - * in order to allocate new block for an inode - */ -int ext4_ext_writepage_trans_blocks(struct inode *inode, int num) -{ - int needed; - - needed = ext4_ext_calc_credits_for_insert(inode, NULL); - - /* caller wants to allocate num blocks, but note it includes sb */ - needed = needed * num - (num - 1); - -#ifdef CONFIG_QUOTA - needed += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif - - return needed; -} - static void ext4_falloc_update_inode(struct inode *inode, int mode, loff_t new_size, int update_ctime) { @@ -2939,10 +2923,9 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) - block; /* - * credits to insert 1 extent into extent tree + buffers to be able to - * modify 1 super block, 1 block bitmap and 1 group descriptor. + * credits to insert 1 extent into extent tree */ - credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; + credits = ext4_chunk_trans_blocks(inode, max_blocks); mutex_lock(&inode->i_mutex); retry: while (ret >= 0 && ret < max_blocks) { diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 655e760..f344834 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -351,7 +351,7 @@ find_close_to_parent: goto found_flexbg; } - if (best_flex < 0 || + if (flex_group[best_flex].free_inodes == 0 || (flex_group[i].free_blocks > flex_group[best_flex].free_blocks && flex_group[i].free_inodes)) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 59fbbe8..7e91913e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -41,6 +41,8 @@ #include "acl.h" #include "ext4_extents.h" +#define MPAGE_DA_EXTENT_TAIL 0x01 + static inline int ext4_begin_ordered_truncate(struct inode *inode, loff_t new_size) { @@ -1005,6 +1007,9 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) */ static int ext4_calc_metadata_amount(struct inode *inode, int blocks) { + if (!blocks) + return 0; + if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) return ext4_ext_calc_metadata_amount(inode, blocks); @@ -1041,18 +1046,6 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used) spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); } -/* Maximum number of blocks we map for direct IO at once. */ -#define DIO_MAX_BLOCKS 4096 -/* - * Number of credits we need for writing DIO_MAX_BLOCKS: - * We need sb + group descriptor + bitmap + inode -> 4 - * For B blocks with A block pointers per block we need: - * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect). - * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25. - */ -#define DIO_CREDITS 25 - - /* * The ext4_get_blocks_wrap() function try to look up the requested blocks, * and returns if the blocks are already mapped. @@ -1164,19 +1157,23 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, return retval; } +/* Maximum number of blocks we map for direct IO at once. */ +#define DIO_MAX_BLOCKS 4096 + static int ext4_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { handle_t *handle = ext4_journal_current_handle(); int ret = 0, started = 0; unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; + int dio_credits; if (create && !handle) { /* Direct IO write... */ if (max_blocks > DIO_MAX_BLOCKS) max_blocks = DIO_MAX_BLOCKS; - handle = ext4_journal_start(inode, DIO_CREDITS + - 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)); + dio_credits = ext4_chunk_trans_blocks(inode, max_blocks); + handle = ext4_journal_start(inode, dio_credits); if (IS_ERR(handle)) { ret = PTR_ERR(handle); goto out; @@ -1559,7 +1556,25 @@ static void ext4_da_release_space(struct inode *inode, int to_free) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); int total, mdb, mdb_free, release; + if (!to_free) + return; /* Nothing to release, exit */ + spin_lock(&EXT4_I(inode)->i_block_reservation_lock); + + if (!EXT4_I(inode)->i_reserved_data_blocks) { + /* + * if there is no reserved blocks, but we try to free some + * then the counter is messed up somewhere. + * but since this function is called from invalidate + * page, it's harmless to return without any action + */ + printk(KERN_INFO "ext4 delalloc try to release %d reserved " + "blocks for inode %lu, but there is no reserved " + "data blocks\n", to_free, inode->i_ino); + spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + return; + } + /* recalculate the number of metablocks still need to be reserved */ total = EXT4_I(inode)->i_reserved_data_blocks - to_free; mdb = ext4_calc_metadata_amount(inode, total); @@ -1613,11 +1628,13 @@ struct mpage_da_data { unsigned long first_page, next_page; /* extent of pages */ get_block_t *get_block; struct writeback_control *wbc; + int io_done; + long pages_written; }; /* * mpage_da_submit_io - walks through extent of pages and try to write - * them with __mpage_writepage() + * them with writepage() call back * * @mpd->inode: inode * @mpd->first_page: first page of the extent @@ -1632,18 +1649,11 @@ struct mpage_da_data { static int mpage_da_submit_io(struct mpage_da_data *mpd) { struct address_space *mapping = mpd->inode->i_mapping; - struct mpage_data mpd_pp = { - .bio = NULL, - .last_block_in_bio = 0, - .get_block = mpd->get_block, - .use_writepage = 1, - }; int ret = 0, err, nr_pages, i; unsigned long index, end; struct pagevec pvec; BUG_ON(mpd->next_page <= mpd->first_page); - pagevec_init(&pvec, 0); index = mpd->first_page; end = mpd->next_page - 1; @@ -1661,8 +1671,9 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) break; index++; - err = __mpage_writepage(page, mpd->wbc, &mpd_pp); - + err = mapping->a_ops->writepage(page, mpd->wbc); + if (!err) + mpd->pages_written++; /* * In error case, we have to continue because * remaining pages are still locked @@ -1673,9 +1684,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) } pagevec_release(&pvec); } - if (mpd_pp.bio) - mpage_bio_submit(WRITE, mpd_pp.bio); - return ret; } @@ -1698,7 +1706,7 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, int blocks = exbh->b_size >> inode->i_blkbits; sector_t pblock = exbh->b_blocknr, cur_logical; struct buffer_head *head, *bh; - unsigned long index, end; + pgoff_t index, end; struct pagevec pvec; int nr_pages, i; @@ -1741,6 +1749,13 @@ static void mpage_put_bnr_to_bhs(struct mpage_da_data *mpd, sector_t logical, if (buffer_delay(bh)) { bh->b_blocknr = pblock; clear_buffer_delay(bh); + bh->b_bdev = inode->i_sb->s_bdev; + } else if (buffer_unwritten(bh)) { + bh->b_blocknr = pblock; + clear_buffer_unwritten(bh); + set_buffer_mapped(bh); + set_buffer_new(bh); + bh->b_bdev = inode->i_sb->s_bdev; } else if (buffer_mapped(bh)) BUG_ON(bh->b_blocknr != pblock); @@ -1776,13 +1791,11 @@ static inline void __unmap_underlying_blocks(struct inode *inode, * * The function skips space we know is already mapped to disk blocks. * - * The function ignores errors ->get_block() returns, thus real - * error handling is postponed to __mpage_writepage() */ static void mpage_da_map_blocks(struct mpage_da_data *mpd) { + int err = 0; struct buffer_head *lbh = &mpd->lbh; - int err = 0, remain = lbh->b_size; sector_t next = lbh->b_blocknr; struct buffer_head new; @@ -1792,38 +1805,36 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) if (buffer_mapped(lbh) && !buffer_delay(lbh)) return; - while (remain) { - new.b_state = lbh->b_state; - new.b_blocknr = 0; - new.b_size = remain; - err = mpd->get_block(mpd->inode, next, &new, 1); - if (err) { - /* - * Rather than implement own error handling - * here, we just leave remaining blocks - * unallocated and try again with ->writepage() - */ - break; - } - BUG_ON(new.b_size == 0); + new.b_state = lbh->b_state; + new.b_blocknr = 0; + new.b_size = lbh->b_size; - if (buffer_new(&new)) - __unmap_underlying_blocks(mpd->inode, &new); + /* + * If we didn't accumulate anything + * to write simply return + */ + if (!new.b_size) + return; + err = mpd->get_block(mpd->inode, next, &new, 1); + if (err) + return; + BUG_ON(new.b_size == 0); - /* - * If blocks are delayed marked, we need to - * put actual blocknr and drop delayed bit - */ - if (buffer_delay(lbh)) - mpage_put_bnr_to_bhs(mpd, next, &new); + if (buffer_new(&new)) + __unmap_underlying_blocks(mpd->inode, &new); - /* go for the remaining blocks */ - next += new.b_size >> mpd->inode->i_blkbits; - remain -= new.b_size; - } + /* + * If blocks are delayed marked, we need to + * put actual blocknr and drop delayed bit + */ + if (buffer_delay(lbh) || buffer_unwritten(lbh)) + mpage_put_bnr_to_bhs(mpd, next, &new); + + return; } -#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | (1 << BH_Delay)) +#define BH_FLAGS ((1 << BH_Uptodate) | (1 << BH_Mapped) | \ + (1 << BH_Delay) | (1 << BH_Unwritten)) /* * mpage_add_bh_to_extent - try to add one more block to extent of blocks @@ -1837,41 +1848,61 @@ static void mpage_da_map_blocks(struct mpage_da_data *mpd) static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, sector_t logical, struct buffer_head *bh) { - struct buffer_head *lbh = &mpd->lbh; sector_t next; + size_t b_size = bh->b_size; + struct buffer_head *lbh = &mpd->lbh; + int nrblocks = lbh->b_size >> mpd->inode->i_blkbits; - next = lbh->b_blocknr + (lbh->b_size >> mpd->inode->i_blkbits); - + /* check if thereserved journal credits might overflow */ + if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) { + if (nrblocks >= EXT4_MAX_TRANS_DATA) { + /* + * With non-extent format we are limited by the journal + * credit available. Total credit needed to insert + * nrblocks contiguous blocks is dependent on the + * nrblocks. So limit nrblocks. + */ + goto flush_it; + } else if ((nrblocks + (b_size >> mpd->inode->i_blkbits)) > + EXT4_MAX_TRANS_DATA) { + /* + * Adding the new buffer_head would make it cross the + * allowed limit for which we have journal credit + * reserved. So limit the new bh->b_size + */ + b_size = (EXT4_MAX_TRANS_DATA - nrblocks) << + mpd->inode->i_blkbits; + /* we will do mpage_da_submit_io in the next loop */ + } + } /* * First block in the extent */ if (lbh->b_size == 0) { lbh->b_blocknr = logical; - lbh->b_size = bh->b_size; + lbh->b_size = b_size; lbh->b_state = bh->b_state & BH_FLAGS; return; } + next = lbh->b_blocknr + nrblocks; /* * Can we merge the block to our big extent? */ if (logical == next && (bh->b_state & BH_FLAGS) == lbh->b_state) { - lbh->b_size += bh->b_size; + lbh->b_size += b_size; return; } +flush_it: /* * We couldn't merge the block to our extent, so we * need to flush current extent and start new one */ mpage_da_map_blocks(mpd); - - /* - * Now start a new extent - */ - lbh->b_size = bh->b_size; - lbh->b_state = bh->b_state & BH_FLAGS; - lbh->b_blocknr = logical; + mpage_da_submit_io(mpd); + mpd->io_done = 1; + return; } /* @@ -1891,17 +1922,35 @@ static int __mpage_da_writepage(struct page *page, struct buffer_head *bh, *head, fake; sector_t logical; + if (mpd->io_done) { + /* + * Rest of the page in the page_vec + * redirty then and skip then. We will + * try to to write them again after + * starting a new transaction + */ + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return MPAGE_DA_EXTENT_TAIL; + } /* * Can we merge this page to current extent? */ if (mpd->next_page != page->index) { /* * Nope, we can't. So, we map non-allocated blocks - * and start IO on them using __mpage_writepage() + * and start IO on them using writepage() */ if (mpd->next_page != mpd->first_page) { mpage_da_map_blocks(mpd); mpage_da_submit_io(mpd); + /* + * skip rest of the page in the page_vec + */ + mpd->io_done = 1; + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return MPAGE_DA_EXTENT_TAIL; } /* @@ -1932,6 +1981,8 @@ static int __mpage_da_writepage(struct page *page, set_buffer_dirty(bh); set_buffer_uptodate(bh); mpage_add_bh_to_extent(mpd, logical, bh); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; } else { /* * Page with regular buffer heads, just add all dirty ones @@ -1940,8 +1991,12 @@ static int __mpage_da_writepage(struct page *page, bh = head; do { BUG_ON(buffer_locked(bh)); - if (buffer_dirty(bh)) + if (buffer_dirty(bh) && + (!buffer_mapped(bh) || buffer_delay(bh))) { mpage_add_bh_to_extent(mpd, logical, bh); + if (mpd->io_done) + return MPAGE_DA_EXTENT_TAIL; + } logical++; } while ((bh = bh->b_this_page) != head); } @@ -1960,22 +2015,13 @@ static int __mpage_da_writepage(struct page *page, * * This is a library function, which implements the writepages() * address_space_operation. - * - * In order to avoid duplication of logic that deals with partial pages, - * multiple bio per page, etc, we find non-allocated blocks, allocate - * them with minimal calls to ->get_block() and re-use __mpage_writepage() - * - * It's important that we call __mpage_writepage() only once for each - * involved page, otherwise we'd have to implement more complicated logic - * to deal with pages w/o PG_lock or w/ PG_writeback and so on. - * - * See comments to mpage_writepages() */ static int mpage_da_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { struct mpage_da_data mpd; + long to_write; int ret; if (!get_block) @@ -1989,17 +2035,22 @@ static int mpage_da_writepages(struct address_space *mapping, mpd.first_page = 0; mpd.next_page = 0; mpd.get_block = get_block; + mpd.io_done = 0; + mpd.pages_written = 0; + + to_write = wbc->nr_to_write; ret = write_cache_pages(mapping, wbc, __mpage_da_writepage, &mpd); /* * Handle last extent of pages */ - if (mpd.next_page != mpd.first_page) { + if (!mpd.io_done && mpd.next_page != mpd.first_page) { mpage_da_map_blocks(&mpd); mpage_da_submit_io(&mpd); } + wbc->nr_to_write = to_write - mpd.pages_written; return ret; } @@ -2204,63 +2255,95 @@ static int ext4_da_writepage(struct page *page, } /* - * For now just follow the DIO way to estimate the max credits - * needed to write out EXT4_MAX_WRITEBACK_PAGES. - * todo: need to calculate the max credits need for - * extent based files, currently the DIO credits is based on - * indirect-blocks mapping way. - * - * Probably should have a generic way to calculate credits - * for DIO, writepages, and truncate + * This is called via ext4_da_writepages() to + * calulate the total number of credits to reserve to fit + * a single extent allocation into a single transaction, + * ext4_da_writpeages() will loop calling this before + * the block allocation. */ -#define EXT4_MAX_WRITEBACK_PAGES DIO_MAX_BLOCKS -#define EXT4_MAX_WRITEBACK_CREDITS DIO_CREDITS + +static int ext4_da_writepages_trans_blocks(struct inode *inode) +{ + int max_blocks = EXT4_I(inode)->i_reserved_data_blocks; + + /* + * With non-extent format the journal credit needed to + * insert nrblocks contiguous block is dependent on + * number of contiguous block. So we will limit + * number of contiguous block to a sane value + */ + if (!(inode->i_flags & EXT4_EXTENTS_FL) && + (max_blocks > EXT4_MAX_TRANS_DATA)) + max_blocks = EXT4_MAX_TRANS_DATA; + + return ext4_chunk_trans_blocks(inode, max_blocks); +} static int ext4_da_writepages(struct address_space *mapping, - struct writeback_control *wbc) + struct writeback_control *wbc) { - struct inode *inode = mapping->host; handle_t *handle = NULL; - int needed_blocks; - int ret = 0; - long to_write; loff_t range_start = 0; + struct inode *inode = mapping->host; + int needed_blocks, ret = 0, nr_to_writebump = 0; + long to_write, pages_skipped = 0; + struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb); /* * No pages to write? This is mainly a kludge to avoid starting * a transaction for special inodes like journal inode on last iput() * because that could violate lock ordering on umount */ - if (!mapping->nrpages) + if (!mapping->nrpages || !mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) return 0; - /* - * Estimate the worse case needed credits to write out - * EXT4_MAX_BUF_BLOCKS pages + * Make sure nr_to_write is >= sbi->s_mb_stream_request + * This make sure small files blocks are allocated in + * single attempt. This ensure that small files + * get less fragmented. */ - needed_blocks = EXT4_MAX_WRITEBACK_CREDITS; + if (wbc->nr_to_write < sbi->s_mb_stream_request) { + nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write; + wbc->nr_to_write = sbi->s_mb_stream_request; + } - to_write = wbc->nr_to_write; - if (!wbc->range_cyclic) { + if (!wbc->range_cyclic) /* * If range_cyclic is not set force range_cont * and save the old writeback_index */ wbc->range_cont = 1; - range_start = wbc->range_start; - } - while (!ret && to_write) { + range_start = wbc->range_start; + pages_skipped = wbc->pages_skipped; + +restart_loop: + to_write = wbc->nr_to_write; + while (!ret && to_write > 0) { + + /* + * we insert one extent at a time. So we need + * credit needed for single extent allocation. + * journalled mode is currently not supported + * by delalloc + */ + BUG_ON(ext4_should_journal_data(inode)); + needed_blocks = ext4_da_writepages_trans_blocks(inode); + /* start a new transaction*/ handle = ext4_journal_start(inode, needed_blocks); if (IS_ERR(handle)) { ret = PTR_ERR(handle); + printk(KERN_EMERG "%s: jbd2_start: " + "%ld pages, ino %lu; err %d\n", __func__, + wbc->nr_to_write, inode->i_ino, ret); + dump_stack(); goto out_writepages; } if (ext4_should_order_data(inode)) { /* * With ordered mode we need to add - * the inode to the journal handle + * the inode to the journal handl * when we do block allocation. */ ret = ext4_jbd2_file_inode(handle, inode); @@ -2268,20 +2351,20 @@ static int ext4_da_writepages(struct address_space *mapping, ext4_journal_stop(handle); goto out_writepages; } - } - /* - * set the max dirty pages could be write at a time - * to fit into the reserved transaction credits - */ - if (wbc->nr_to_write > EXT4_MAX_WRITEBACK_PAGES) - wbc->nr_to_write = EXT4_MAX_WRITEBACK_PAGES; to_write -= wbc->nr_to_write; ret = mpage_da_writepages(mapping, wbc, - ext4_da_get_block_write); + ext4_da_get_block_write); ext4_journal_stop(handle); - if (wbc->nr_to_write) { + if (ret == MPAGE_DA_EXTENT_TAIL) { + /* + * got one extent now try with + * rest of the pages + */ + to_write += wbc->nr_to_write; + ret = 0; + } else if (wbc->nr_to_write) { /* * There is no more writeout needed * or we requested for a noblocking writeout @@ -2293,10 +2376,18 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->nr_to_write = to_write; } -out_writepages: - wbc->nr_to_write = to_write; - if (range_start) + if (wbc->range_cont && (pages_skipped != wbc->pages_skipped)) { + /* We skipped pages in this loop */ wbc->range_start = range_start; + wbc->nr_to_write = to_write + + wbc->pages_skipped - pages_skipped; + wbc->pages_skipped = pages_skipped; + goto restart_loop; + } + +out_writepages: + wbc->nr_to_write = to_write - nr_to_writebump; + wbc->range_start = range_start; return ret; } @@ -3486,6 +3577,9 @@ void ext4_truncate(struct inode *inode) * modify the block allocation tree. */ down_write(&ei->i_data_sem); + + ext4_discard_reservation(inode); + /* * The orphan list entry will now protect us from any crash which * occurs before the truncate completes, so it is now safe to propagate @@ -3555,8 +3649,6 @@ do_indirects: ; } - ext4_discard_reservation(inode); - up_write(&ei->i_data_sem); inode->i_mtime = inode->i_ctime = ext4_current_time(inode); ext4_mark_inode_dirty(handle, inode); @@ -4324,57 +4416,129 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } +static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, + int chunk) +{ + int indirects; + + /* if nrblocks are contiguous */ + if (chunk) { + /* + * With N contiguous data blocks, it need at most + * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks + * 2 dindirect blocks + * 1 tindirect block + */ + indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb); + return indirects + 3; + } + /* + * if nrblocks are not contiguous, worse case, each block touch + * a indirect block, and each indirect block touch a double indirect + * block, plus a triple indirect block + */ + indirects = nrblocks * 2 + 1; + return indirects; +} + +static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) +{ + if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) + return ext4_indirect_trans_blocks(inode, nrblocks, 0); + return ext4_ext_index_trans_blocks(inode, nrblocks, 0); +} /* - * How many blocks doth make a writepage()? - * - * With N blocks per page, it may be: - * N data blocks - * 2 indirect block - * 2 dindirect - * 1 tindirect - * N+5 bitmap blocks (from the above) - * N+5 group descriptor summary blocks - * 1 inode block - * 1 superblock. - * 2 * EXT4_SINGLEDATA_TRANS_BLOCKS for the quote files + * Account for index blocks, block groups bitmaps and block group + * descriptor blocks if modify datablocks and index blocks + * worse case, the indexs blocks spread over different block groups * - * 3 * (N + 5) + 2 + 2 * EXT4_SINGLEDATA_TRANS_BLOCKS + * If datablocks are discontiguous, they are possible to spread over + * different block groups too. If they are contiugous, with flexbg, + * they could still across block group boundary. * - * With ordered or writeback data it's the same, less the N data blocks. + * Also account for superblock, inode, quota and xattr blocks + */ +int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) +{ + int groups, gdpblocks; + int idxblocks; + int ret = 0; + + /* + * How many index blocks need to touch to modify nrblocks? + * The "Chunk" flag indicating whether the nrblocks is + * physically contiguous on disk + * + * For Direct IO and fallocate, they calls get_block to allocate + * one single extent at a time, so they could set the "Chunk" flag + */ + idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk); + + ret = idxblocks; + + /* + * Now let's see how many group bitmaps and group descriptors need + * to account + */ + groups = idxblocks; + if (chunk) + groups += 1; + else + groups += nrblocks; + + gdpblocks = groups; + if (groups > EXT4_SB(inode->i_sb)->s_groups_count) + groups = EXT4_SB(inode->i_sb)->s_groups_count; + if (groups > EXT4_SB(inode->i_sb)->s_gdb_count) + gdpblocks = EXT4_SB(inode->i_sb)->s_gdb_count; + + /* bitmaps and block group descriptor blocks */ + ret += groups + gdpblocks; + + /* Blocks for super block, inode, quota and xattr blocks */ + ret += EXT4_META_TRANS_BLOCKS(inode->i_sb); + + return ret; +} + +/* + * Calulate the total number of credits to reserve to fit + * the modification of a single pages into a single transaction, + * which may include multiple chunks of block allocations. * - * If the inode's direct blocks can hold an integral number of pages then a - * page cannot straddle two indirect blocks, and we can only touch one indirect - * and dindirect block, and the "5" above becomes "3". + * This could be called via ext4_write_begin() * - * This still overestimates under most circumstances. If we were to pass the - * start and end offsets in here as well we could do block_to_path() on each - * block and work out the exact number of indirects which are touched. Pah. + * We need to consider the worse case, when + * one new block per extent. */ - int ext4_writepage_trans_blocks(struct inode *inode) { int bpp = ext4_journal_blocks_per_page(inode); - int indirects = (EXT4_NDIR_BLOCKS % bpp) ? 5 : 3; int ret; - if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) - return ext4_ext_writepage_trans_blocks(inode, bpp); + ret = ext4_meta_trans_blocks(inode, bpp, 0); + /* Account for data blocks for journalled mode */ if (ext4_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else - ret = 2 * (bpp + indirects) + 2; - -#ifdef CONFIG_QUOTA - /* We know that structure was already allocated during DQUOT_INIT so - * we will be updating only the data blocks + inodes */ - ret += 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); -#endif - + ret += bpp; return ret; } /* + * Calculate the journal credits for a chunk of data modification. + * + * This is called from DIO, fallocate or whoever calling + * ext4_get_blocks_wrap() to map/allocate a chunk of contigous disk blocks. + * + * journal buffers for data blocks are not included here, as DIO + * and fallocate do no need to journal data buffers. + */ +int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks) +{ + return ext4_meta_trans_blocks(inode, nrblocks, 1); +} + +/* * The caller must have previously called ext4_reserve_inode_write(). * Give this, we know that the caller already has write access to iloc->bh. */ diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 865e9dd..e0e3a5e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3282,6 +3282,35 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, } /* + * Return the prealloc space that have minimal distance + * from the goal block. @cpa is the prealloc + * space that is having currently known minimal distance + * from the goal block. + */ +static struct ext4_prealloc_space * +ext4_mb_check_group_pa(ext4_fsblk_t goal_block, + struct ext4_prealloc_space *pa, + struct ext4_prealloc_space *cpa) +{ + ext4_fsblk_t cur_distance, new_distance; + + if (cpa == NULL) { + atomic_inc(&pa->pa_count); + return pa; + } + cur_distance = abs(goal_block - cpa->pa_pstart); + new_distance = abs(goal_block - pa->pa_pstart); + + if (cur_distance < new_distance) + return cpa; + + /* drop the previous reference */ + atomic_dec(&cpa->pa_count); + atomic_inc(&pa->pa_count); + return pa; +} + +/* * search goal blocks in preallocated space */ static noinline_for_stack int @@ -3290,7 +3319,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) int order, i; struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); struct ext4_locality_group *lg; - struct ext4_prealloc_space *pa; + struct ext4_prealloc_space *pa, *cpa = NULL; + ext4_fsblk_t goal_block; /* only data can be preallocated */ if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) @@ -3333,6 +3363,13 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) /* The max size of hash table is PREALLOC_TB_SIZE */ order = PREALLOC_TB_SIZE - 1; + goal_block = ac->ac_g_ex.fe_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb) + + ac->ac_g_ex.fe_start + + le32_to_cpu(EXT4_SB(ac->ac_sb)->s_es->s_first_data_block); + /* + * search for the prealloc space that is having + * minimal distance from the goal block. + */ for (i = order; i < PREALLOC_TB_SIZE; i++) { rcu_read_lock(); list_for_each_entry_rcu(pa, &lg->lg_prealloc_list[i], @@ -3340,17 +3377,19 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) spin_lock(&pa->pa_lock); if (pa->pa_deleted == 0 && pa->pa_free >= ac->ac_o_ex.fe_len) { - atomic_inc(&pa->pa_count); - ext4_mb_use_group_pa(ac, pa); - spin_unlock(&pa->pa_lock); - ac->ac_criteria = 20; - rcu_read_unlock(); - return 1; + + cpa = ext4_mb_check_group_pa(goal_block, + pa, cpa); } spin_unlock(&pa->pa_lock); } rcu_read_unlock(); } + if (cpa) { + ext4_mb_use_group_pa(ac, cpa); + ac->ac_criteria = 20; + return 1; + } return 0; } diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b9e077b..46fc0b5 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -53,7 +53,8 @@ static int finish_range(handle_t *handle, struct inode *inode, * credit. But below we try to not accumalate too much * of them by restarting the journal. */ - needed = ext4_ext_calc_credits_for_insert(inode, path); + needed = ext4_ext_calc_credits_for_single_extent(inode, + lb->last_block - lb->first_block + 1, path); /* * Make sure the credit we accumalated is not really high diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 0a92651..b3d3560 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -773,7 +773,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) if (reserved_gdb || gdb_off == 0) { if (!EXT4_HAS_COMPAT_FEATURE(sb, - EXT4_FEATURE_COMPAT_RESIZE_INODE)){ + EXT4_FEATURE_COMPAT_RESIZE_INODE) + || !le16_to_cpu(es->s_reserved_gdt_blocks)) { ext4_warning(sb, __func__, "No reserved GDT blocks, can't resize"); return -EPERM; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d5d7795..566344b 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -568,6 +568,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) #endif ei->i_block_alloc_info = NULL; ei->vfs_inode.i_version = 1; + ei->vfs_inode.i_data.writeback_index = 0; memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); INIT_LIST_HEAD(&ei->i_prealloc_list); spin_lock_init(&ei->i_prealloc_lock); diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 6d266d7..80ff338 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -562,26 +562,23 @@ static int fat_write_inode(struct inode *inode, int wait) struct buffer_head *bh; struct msdos_dir_entry *raw_entry; loff_t i_pos; - int err = 0; + int err; retry: i_pos = MSDOS_I(inode)->i_pos; if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) return 0; - lock_super(sb); bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); if (!bh) { printk(KERN_ERR "FAT: unable to read inode block " "for updating (i_pos %lld)\n", i_pos); - err = -EIO; - goto out; + return -EIO; } spin_lock(&sbi->inode_hash_lock); if (i_pos != MSDOS_I(inode)->i_pos) { spin_unlock(&sbi->inode_hash_lock); brelse(bh); - unlock_super(sb); goto retry; } @@ -607,11 +604,10 @@ retry: } spin_unlock(&sbi->inode_hash_lock); mark_buffer_dirty(bh); + err = 0; if (wait) err = sync_dirty_buffer(bh); brelse(bh); -out: - unlock_super(sb); return err; } diff --git a/fs/ioprio.c b/fs/ioprio.c index c4a1c3c..da3cc46 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -115,11 +115,11 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) pgrp = task_pgrp(current); else pgrp = find_vpid(who); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { ret = set_task_ioprio(p, ioprio); if (ret) break; - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) @@ -204,7 +204,7 @@ asmlinkage long sys_ioprio_get(int which, int who) pgrp = task_pgrp(current); else pgrp = find_vpid(who); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { tmpio = get_task_ioprio(p); if (tmpio < 0) continue; @@ -212,7 +212,7 @@ asmlinkage long sys_ioprio_get(int which, int who) ret = tmpio; else ret = ioprio_best(ret, tmpio); - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 31559f4..4c41db9 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -12,7 +12,6 @@ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I -#include <linux/version.h> #include <linux/rbtree.h> #include <linux/posix_acl.h> #include <linux/mutex.h> diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 79ecd28..3f87d26 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -52,14 +52,14 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) } seq_printf(m, - "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", vma->vm_start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p', - vma->vm_pgoff << PAGE_SHIFT, + ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, MAJOR(dev), MINOR(dev), ino, &len); if (file) { diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7546a91..73d1891 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -219,14 +219,14 @@ static int show_map(struct seq_file *m, void *v) ino = inode->i_ino; } - seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", vma->vm_start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? 's' : 'p', - vma->vm_pgoff << PAGE_SHIFT, + ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, MAJOR(dev), MINOR(dev), ino, &len); /* diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index cdc2d34..2813cdd 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -18,7 +18,6 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ -#include <linux/version.h> /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * diff --git a/include/asm-cris/Kbuild b/include/asm-cris/Kbuild index b7037d8..d5b6319 100644 --- a/include/asm-cris/Kbuild +++ b/include/asm-cris/Kbuild @@ -1,6 +1,5 @@ include include/asm-generic/Kbuild.asm -header-y += arch/ header-y += arch-v10/ header-y += arch-v32/ diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h index 20e44fe0..ca7475e 100644 --- a/include/asm-frv/io.h +++ b/include/asm-frv/io.h @@ -271,6 +271,8 @@ static inline void __iomem *ioremap_fullcache(unsigned long physaddr, unsigned l return __ioremap(physaddr, size, IOMAP_FULL_CACHING); } +#define ioremap_wc ioremap_nocache + extern void iounmap(void volatile __iomem *addr); static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) diff --git a/include/asm-mn10300/io.h b/include/asm-mn10300/io.h index b8b6dc8..c1a4119 100644 --- a/include/asm-mn10300/io.h +++ b/include/asm-mn10300/io.h @@ -259,6 +259,8 @@ static inline void *ioremap_nocache(unsigned long offset, unsigned long size) return (void *) (offset | 0x20000000); } +#define ioremap_wc ioremap_nocache + static inline void iounmap(void *addr) { } diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 2f5a792..762f6a6 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -91,6 +91,7 @@ #define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ #define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_XMM4_2 (4*32+20) /* Streaming SIMD Extensions-4.2 */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ @@ -189,6 +190,7 @@ extern const char * const x86_power_flags[32]; #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) +#define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) # define cpu_has_invlpg 1 diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h index ca110ee..2362cfd 100644 --- a/include/asm-x86/msr.h +++ b/include/asm-x86/msr.h @@ -52,14 +52,14 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, { DECLARE_ARGS(val, low, high); - asm volatile("2: rdmsr ; xor %0,%0\n" + asm volatile("2: rdmsr ; xor %[err],%[err]\n" "1:\n\t" ".section .fixup,\"ax\"\n\t" - "3: mov %3,%0 ; jmp 1b\n\t" + "3: mov %[fault],%[err] ; jmp 1b\n\t" ".previous\n\t" _ASM_EXTABLE(2b, 3b) - : "=r" (*err), EAX_EDX_RET(val, low, high) - : "c" (msr), "i" (-EFAULT)); + : [err] "=r" (*err), EAX_EDX_RET(val, low, high) + : "c" (msr), [fault] "i" (-EFAULT)); return EAX_EDX_VAL(val, low, high); } @@ -73,15 +73,15 @@ static inline int native_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int err; - asm volatile("2: wrmsr ; xor %0,%0\n" + asm volatile("2: wrmsr ; xor %[err],%[err]\n" "1:\n\t" ".section .fixup,\"ax\"\n\t" - "3: mov %4,%0 ; jmp 1b\n\t" + "3: mov %[fault],%[err] ; jmp 1b\n\t" ".previous\n\t" _ASM_EXTABLE(2b, 3b) - : "=a" (err) + : [err] "=a" (err) : "c" (msr), "0" (low), "d" (high), - "i" (-EFAULT) + [fault] "i" (-EFAULT) : "memory"); return err; } @@ -192,19 +192,20 @@ do { \ #define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0) #ifdef CONFIG_SMP -void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); -void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); - int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); #else /* CONFIG_SMP */ -static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) +static inline int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) { rdmsr(msr_no, *l, *h); + return 0; } -static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) +static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h) { wrmsr(msr_no, l, h); + return 0; } static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) diff --git a/include/asm-x86/xen/hypervisor.h b/include/asm-x86/xen/hypervisor.h index 8e15dd2..04ee061 100644 --- a/include/asm-x86/xen/hypervisor.h +++ b/include/asm-x86/xen/hypervisor.h @@ -35,7 +35,6 @@ #include <linux/types.h> #include <linux/kernel.h> -#include <linux/version.h> #include <xen/interface/xen.h> #include <xen/interface/version.h> diff --git a/include/linux/device.h b/include/linux/device.h index d24a47f..4d8372d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -358,6 +358,7 @@ struct device { struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ + const char *init_name; /* initial name of the device */ struct device_type *type; unsigned uevent_suppress:1; @@ -406,7 +407,7 @@ struct device { /* Get the wakeup routines, which depend on struct device */ #include <linux/pm_wakeup.h> -static inline const char *dev_name(struct device *dev) +static inline const char *dev_name(const struct device *dev) { /* will be changed into kobject_name(&dev->kobj) in the near future */ return dev->bus_id; @@ -518,7 +519,7 @@ extern void device_shutdown(void); extern void sysdev_shutdown(void); /* debugging and troubleshooting/diagnostic helpers. */ -extern const char *dev_driver_string(struct device *dev); +extern const char *dev_driver_string(const struct device *dev); #define dev_printk(level, dev, format, arg...) \ printk(level "%s %s: " format , dev_driver_string(dev) , \ dev_name(dev) , ## arg) diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index f5abd13..27e772c 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -35,6 +35,27 @@ enum fid_type { FILEID_INO32_GEN_PARENT = 2, /* + * 64 bit object ID, 64 bit root object ID, + * 32 bit generation number. + */ + FILEID_BTRFS_WITHOUT_PARENT = 0x4d, + + /* + * 64 bit object ID, 64 bit root object ID, + * 32 bit generation number, + * 64 bit parent object ID, 32 bit parent generation. + */ + FILEID_BTRFS_WITH_PARENT = 0x4e, + + /* + * 64 bit object ID, 64 bit root object ID, + * 32 bit generation number, + * 64 bit parent object ID, 32 bit parent generation, + * 64 bit parent root object ID. + */ + FILEID_BTRFS_WITH_PARENT_ROOT = 0x4f, + + /* * 32 bit block number, 16 bit partition reference, * 16 bit unused, 32 bit generation number. */ diff --git a/include/linux/fb.h b/include/linux/fb.h index 3b8870e..531ccd5 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -976,6 +976,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, /* drivers/video/fb_defio.c */ extern void fb_deferred_io_init(struct fb_info *info); +extern void fb_deferred_io_open(struct fb_info *info, + struct inode *inode, + struct file *file); extern void fb_deferred_io_cleanup(struct fb_info *info); extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync); diff --git a/include/linux/fs_uart_pd.h b/include/linux/fs_uart_pd.h index 809bb9f..36b61ff 100644 --- a/include/linux/fs_uart_pd.h +++ b/include/linux/fs_uart_pd.h @@ -12,7 +12,6 @@ #ifndef FS_UART_PD_H #define FS_UART_PD_H -#include <linux/version.h> #include <asm/types.h> enum fs_uart_id { diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 4c6307a..8529f57 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -45,6 +45,7 @@ #define TUNGETFEATURES _IOR('T', 207, unsigned int) #define TUNSETOFFLOAD _IOW('T', 208, unsigned int) #define TUNSETTXFILTER _IOW('T', 209, unsigned int) +#define TUNGETIFF _IOR('T', 210, unsigned int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 diff --git a/include/linux/libata.h b/include/linux/libata.h index 06b8033..225bfc5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -163,6 +163,7 @@ enum { ATA_DEV_NONE = 9, /* no device */ /* struct ata_link flags */ + ATA_LFLAG_NO_HRST = (1 << 1), /* avoid hardreset */ ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */ ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */ ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ @@ -646,6 +647,7 @@ struct ata_link { unsigned int flags; /* ATA_LFLAG_xxx */ + u32 saved_scontrol; /* SControl on probe */ unsigned int hw_sata_spd_limit; unsigned int sata_spd_limit; unsigned int sata_spd; /* current SATA PHY speed */ @@ -1427,6 +1429,28 @@ static inline unsigned long ata_deadline(unsigned long from_jiffies, return from_jiffies + msecs_to_jiffies(timeout_msecs); } +/* Don't open code these in drivers as there are traps. Firstly the range may + change in future hardware and specs, secondly 0xFF means 'no DMA' but is + > UDMA_0. Dyma ddreigiau */ + +static inline int ata_using_mwdma(struct ata_device *adev) +{ + if (adev->dma_mode >= XFER_MW_DMA_0 && adev->dma_mode <= XFER_MW_DMA_4) + return 1; + return 0; +} + +static inline int ata_using_udma(struct ata_device *adev) +{ + if (adev->dma_mode >= XFER_UDMA_0 && adev->dma_mode <= XFER_UDMA_7) + return 1; + return 0; +} + +static inline int ata_dma_enabled(struct ata_device *adev) +{ + return (adev->dma_mode == 0xFF ? 0 : 1); +} /************************************************************************** * PMP - drivers/ata/libata-pmp.c diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 3ba2506..8837928 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -57,6 +57,15 @@ static inline acpi_status pcie_osc_support_set(u32 flags) { return __pci_osc_support_set(flags, PCI_EXPRESS_ROOT_HID_STRING); } +static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) +{ + /* Find root host bridge */ + while (pdev->bus->self) + pdev = pdev->bus->self; + + return acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus), + pdev->bus->number); +} #else #if !defined(AE_ERROR) typedef u32 acpi_status; @@ -66,6 +75,8 @@ static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) {return AE_ERROR;} static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;} static inline acpi_status pcie_osc_support_set(u32 flags) {return AE_ERROR;} +static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) +{ return NULL; } #endif #endif /* _PCI_ACPI_H_ */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9ec2bcc..f1624b3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2428,6 +2428,9 @@ #define PCI_DEVICE_ID_INTEL_ICH10_3 0x3a1a #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 +#define PCI_DEVICE_ID_INTEL_PCH_0 0x3b10 +#define PCI_DEVICE_ID_INTEL_PCH_1 0x3b11 +#define PCI_DEVICE_ID_INTEL_PCH_2 0x3b30 #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 diff --git a/include/linux/pid.h b/include/linux/pid.h index 22921ac..d7e98ff 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -161,4 +161,13 @@ pid_t pid_vnr(struct pid *pid); } \ } while (0) +#define do_each_pid_thread(pid, type, task) \ + do_each_pid_task(pid, type, task) { \ + struct task_struct *tg___ = task; \ + do { + +#define while_each_pid_thread(pid, type, task) \ + } while_each_thread(tg___, task); \ + task = tg___; \ + } while_each_pid_task(pid, type, task) #endif /* _LINUX_PID_H */ diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 69407f8..fed6f5e 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -102,7 +102,7 @@ int try_to_unmap(struct page *, int ignore_refs); * Called from mm/filemap_xip.c to unmap empty zero page */ pte_t *page_check_address(struct page *, struct mm_struct *, - unsigned long, spinlock_t **); + unsigned long, spinlock_t **, int); /* * Used by swapoff to help locate where page is expected in vma. diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 358661c..9099237 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1452,6 +1452,10 @@ extern int skb_copy_datagram_iovec(const struct sk_buff *from, extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, struct iovec *iov); +extern int skb_copy_datagram_from_iovec(struct sk_buff *skb, + int offset, + struct iovec *from, + int len); extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); diff --git a/include/linux/tick.h b/include/linux/tick.h index d3c0269..8cf8cfe 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -74,10 +74,13 @@ extern struct tick_device *tick_get_device(int cpu); extern int tick_init_highres(void); extern int tick_program_event(ktime_t expires, int force); extern void tick_setup_sched_timer(void); +# endif + +# if defined CONFIG_NO_HZ || defined CONFIG_HIGH_RES_TIMERS extern void tick_cancel_sched_timer(int cpu); # else static inline void tick_cancel_sched_timer(int cpu) { } -# endif /* HIGHRES */ +# endif # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST extern struct tick_device *tick_get_broadcast_device(void); diff --git a/include/linux/usb.h b/include/linux/usb.h index 0924cd9..94ac74a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -110,6 +110,8 @@ enum usb_interface_condition { * @sysfs_files_created: sysfs attributes exist * @needs_remote_wakeup: flag set when the driver requires remote-wakeup * capability during autosuspend. + * @needs_altsetting0: flag set when a set-interface request for altsetting 0 + * has been deferred. * @needs_binding: flag set when the driver should be re-probed or unbound * following a reset or suspend operation it doesn't support. * @dev: driver model's view of this device @@ -162,6 +164,7 @@ struct usb_interface { unsigned is_active:1; /* the interface is not suspended */ unsigned sysfs_files_created:1; /* the sysfs attributes exist */ unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ + unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */ unsigned needs_binding:1; /* needs delayed unbind/rebind */ struct device dev; /* interface specific device info */ diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 06b2814..c216de5 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -80,7 +80,8 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct net_device *dev, int strict); -extern int ipv6_dev_get_saddr(struct net_device *dev, +extern int ipv6_dev_get_saddr(struct net *net, + struct net_device *dev, const struct in6_addr *daddr, unsigned int srcprefs, struct in6_addr *saddr); diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index bc391ba..5f53db7 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -107,6 +107,7 @@ struct rt6_rtnl_dump_arg { struct sk_buff *skb; struct netlink_callback *cb; + struct net *net; }; extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b397e4d..ff137fd 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -708,10 +708,7 @@ enum ieee80211_tkip_key_type { * rely on the host system for such buffering. This option is used * to configure the IEEE 802.11 upper layer to buffer broadcast and * multicast frames when there are power saving stations so that - * the driver can fetch them with ieee80211_get_buffered_bc(). Note - * that not setting this flag works properly only when the - * %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because - * otherwise the stack will not know when the DTIM beacon was sent. + * the driver can fetch them with ieee80211_get_buffered_bc(). * * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE: * Hardware is not capable of short slot operation on the 2.4 GHz band. @@ -1099,10 +1096,8 @@ enum ieee80211_ampdu_mlme_action { * See the section "Frame filtering" for more information. * This callback must be implemented and atomic. * - * @set_tim: Set TIM bit. If the hardware/firmware takes care of beacon - * generation (that is, %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is set) - * mac80211 calls this function when a TIM bit must be set or cleared - * for a given AID. Must be atomic. + * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit + * must be set or cleared for a given AID. Must be atomic. * * @set_key: See the section "Hardware crypto acceleration" * This callback can sleep, and is only called between add_interface diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 853fe83..b786a5b 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -78,6 +78,7 @@ extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, extern int register_qdisc(struct Qdisc_ops *qops); extern int unregister_qdisc(struct Qdisc_ops *qops); +extern void qdisc_list_del(struct Qdisc *q); extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle); extern struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle); extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a7abfda..b1d2cfe 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -27,6 +27,7 @@ enum qdisc_state_t { __QDISC_STATE_RUNNING, __QDISC_STATE_SCHED, + __QDISC_STATE_DEACTIVATED, }; struct qdisc_size_table { @@ -60,7 +61,6 @@ struct Qdisc struct gnet_stats_basic bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; - struct rcu_head q_rcu; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); @@ -193,6 +193,11 @@ static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc) return qdisc->dev_queue->qdisc; } +static inline struct Qdisc *qdisc_root_sleeping(struct Qdisc *qdisc) +{ + return qdisc->dev_queue->qdisc_sleeping; +} + /* The qdisc root lock is a mechanism by which to top level * of a qdisc tree can be locked from any qdisc node in the * forest. This allows changing the configuration of some diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 291d56a..80b2e93 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -6,6 +6,7 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/blkdev.h> +#include <scsi/scsi.h> #include <asm/atomic.h> struct request_queue; @@ -426,7 +427,7 @@ static inline int scsi_device_enclosure(struct scsi_device *sdev) static inline int scsi_device_protection(struct scsi_device *sdev) { - return sdev->inquiry[5] & (1<<0); + return sdev->scsi_level > SCSI_2 && sdev->inquiry[5] & (1<<0); } #define MODULE_ALIAS_SCSI_DEVICE(type) \ diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 21575fc..1d3ef29 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -14,7 +14,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/nsproxy.h> #include <linux/init_task.h> #include <linux/mnt_namespace.h> diff --git a/kernel/power/swap.c b/kernel/power/swap.c index a0abf9a..80ccac8 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/file.h> #include <linux/utsname.h> -#include <linux/version.h> #include <linux/delay.h> #include <linux/bitops.h> #include <linux/genhd.h> diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index f14f372..467d594 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -77,6 +77,7 @@ void wakeme_after_rcu(struct rcu_head *head) * sections are delimited by rcu_read_lock() and rcu_read_unlock(), * and may be nested. */ +void synchronize_rcu(void); /* Makes kernel-doc tools happy */ synchronize_rcu_xxx(synchronize_rcu, call_rcu) EXPORT_SYMBOL_GPL(synchronize_rcu); diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 862b06b..9353ca7 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -8,6 +8,6 @@ SCHED_FEAT(SYNC_WAKEUPS, 1) SCHED_FEAT(HRTICK, 1) SCHED_FEAT(DOUBLE_TICK, 0) SCHED_FEAT(ASYM_GRAN, 1) -SCHED_FEAT(LB_BIAS, 0) +SCHED_FEAT(LB_BIAS, 1) SCHED_FEAT(LB_WAKEUP_UPDATE, 1) SCHED_FEAT(ASYM_EFF_LOAD, 1) diff --git a/kernel/signal.c b/kernel/signal.c index c539f60..e661b01 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1338,6 +1338,7 @@ int do_notify_parent(struct task_struct *tsk, int sig) struct siginfo info; unsigned long flags; struct sighand_struct *psig; + int ret = sig; BUG_ON(sig == -1); @@ -1402,7 +1403,7 @@ int do_notify_parent(struct task_struct *tsk, int sig) * is implementation-defined: we do (if you don't want * it, just use SIG_IGN instead). */ - tsk->exit_signal = -1; + ret = tsk->exit_signal = -1; if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) sig = -1; } @@ -1411,7 +1412,7 @@ int do_notify_parent(struct task_struct *tsk, int sig) __wake_up_parent(tsk, tsk->parent); spin_unlock_irqrestore(&psig->siglock, flags); - return sig; + return ret; } static void do_notify_parent_cldstop(struct task_struct *tsk, int why) diff --git a/kernel/smp.c b/kernel/smp.c index 782e2b9..f362a85 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -210,8 +210,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, { struct call_single_data d; unsigned long flags; - /* prevent preemption and reschedule on another processor */ + /* prevent preemption and reschedule on another processor, + as well as CPU removal */ int me = get_cpu(); + int err = 0; /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); @@ -220,7 +222,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, local_irq_save(flags); func(info); local_irq_restore(flags); - } else { + } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) { struct call_single_data *data = NULL; if (!wait) { @@ -236,10 +238,12 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, data->func = func; data->info = info; generic_exec_single(cpu, data); + } else { + err = -ENXIO; /* CPU not online */ } put_cpu(); - return 0; + return err; } EXPORT_SYMBOL(smp_call_function_single); diff --git a/kernel/sys.c b/kernel/sys.c index 3dacb00..038a7bc 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -169,9 +169,9 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) pgrp = find_vpid(who); else pgrp = task_pgrp(current); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { error = set_one_prio(p, niceval, error); - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case PRIO_USER: user = current->user; @@ -229,11 +229,11 @@ asmlinkage long sys_getpriority(int which, int who) pgrp = find_vpid(who); else pgrp = task_pgrp(current); - do_each_pid_task(pgrp, PIDTYPE_PGID, p) { + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { niceval = 20 - task_nice(p); if (niceval > retval) retval = niceval; - } while_each_pid_task(pgrp, PIDTYPE_PGID, p); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); break; case PRIO_USER: user = current->user; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f5da526..7a46bde 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -643,17 +643,21 @@ void tick_setup_sched_timer(void) ts->nohz_mode = NOHZ_MODE_HIGHRES; #endif } +#endif /* HIGH_RES_TIMERS */ +#if defined CONFIG_NO_HZ || defined CONFIG_HIGH_RES_TIMERS void tick_cancel_sched_timer(int cpu) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); +# ifdef CONFIG_HIGH_RES_TIMERS if (ts->sched_timer.base) hrtimer_cancel(&ts->sched_timer); +# endif ts->nohz_mode = NOHZ_MODE_INACTIVE; } -#endif /* HIGH_RES_TIMERS */ +#endif /** * Async notification about clocksource changes diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index a9ab059..532858f 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -6,7 +6,6 @@ */ #include <linux/module.h> -#include <linux/version.h> #include <linux/nsproxy.h> #include <linux/slab.h> #include <linux/user_namespace.h> diff --git a/kernel/utsname.c b/kernel/utsname.c index 64d398f..815237a 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/uts.h> #include <linux/utsname.h> -#include <linux/version.h> #include <linux/err.h> #include <linux/slab.h> diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c index fe3a56c..4ab9659 100644 --- a/kernel/utsname_sysctl.c +++ b/kernel/utsname_sysctl.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/uts.h> #include <linux/utsname.h> -#include <linux/version.h> #include <linux/sysctl.h> static void *get_uts(ctl_table *table, int write) diff --git a/lib/kobject.c b/lib/kobject.c index bd732ff..fbf0ae2 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -223,8 +223,7 @@ static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, return -ENOMEM; /* ewww... some of these buggers have '/' in the name ... */ - s = strchr(kobj->name, '/'); - if (s) + while ((s = strchr(kobj->name, '/'))) s[0] = '!'; kfree(old_name); diff --git a/mm/bootmem.c b/mm/bootmem.c index e023c68..ad8eec6 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -405,6 +405,29 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, } #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ +static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, + unsigned long step) +{ + unsigned long base = bdata->node_min_pfn; + + /* + * Align the index with respect to the node start so that the + * combination of both satisfies the requested alignment. + */ + + return ALIGN(base + idx, step) - base; +} + +static unsigned long align_off(struct bootmem_data *bdata, unsigned long off, + unsigned long align) +{ + unsigned long base = PFN_PHYS(bdata->node_min_pfn); + + /* Same as align_idx for byte offsets */ + + return ALIGN(base + off, align) - base; +} + static void * __init alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) @@ -441,7 +464,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, else start = ALIGN(min, step); - sidx = start - bdata->node_min_pfn;; + sidx = start - bdata->node_min_pfn; midx = max - bdata->node_min_pfn; if (bdata->hint_idx > sidx) { @@ -450,7 +473,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, * catch the fallback below. */ fallback = sidx + 1; - sidx = ALIGN(bdata->hint_idx, step); + sidx = align_idx(bdata, bdata->hint_idx, step); } while (1) { @@ -459,7 +482,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, unsigned long eidx, i, start_off, end_off; find_block: sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx); - sidx = ALIGN(sidx, step); + sidx = align_idx(bdata, sidx, step); eidx = sidx + PFN_UP(size); if (sidx >= midx || eidx > midx) @@ -467,7 +490,7 @@ find_block: for (i = sidx; i < eidx; i++) if (test_bit(i, bdata->node_bootmem_map)) { - sidx = ALIGN(i, step); + sidx = align_idx(bdata, i, step); if (sidx == i) sidx += step; goto find_block; @@ -475,7 +498,7 @@ find_block: if (bdata->last_end_off & (PAGE_SIZE - 1) && PFN_DOWN(bdata->last_end_off) + 1 == sidx) - start_off = ALIGN(bdata->last_end_off, align); + start_off = align_off(bdata, bdata->last_end_off, align); else start_off = PFN_PHYS(sidx); @@ -499,7 +522,7 @@ find_block: } if (fallback) { - sidx = ALIGN(fallback - 1, step); + sidx = align_idx(bdata, fallback - 1, step); fallback = 0; goto find_block; } diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 380ab40..b5167df 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -15,6 +15,8 @@ #include <linux/rmap.h> #include <linux/mmu_notifier.h> #include <linux/sched.h> +#include <linux/seqlock.h> +#include <linux/mutex.h> #include <asm/tlbflush.h> #include <asm/io.h> @@ -22,22 +24,18 @@ * We do use our own empty page to avoid interference with other users * of ZERO_PAGE(), such as /dev/zero */ +static DEFINE_MUTEX(xip_sparse_mutex); +static seqcount_t xip_sparse_seq = SEQCNT_ZERO; static struct page *__xip_sparse_page; +/* called under xip_sparse_mutex */ static struct page *xip_sparse_page(void) { if (!__xip_sparse_page) { struct page *page = alloc_page(GFP_HIGHUSER | __GFP_ZERO); - if (page) { - static DEFINE_SPINLOCK(xip_alloc_lock); - spin_lock(&xip_alloc_lock); - if (!__xip_sparse_page) - __xip_sparse_page = page; - else - __free_page(page); - spin_unlock(&xip_alloc_lock); - } + if (page) + __xip_sparse_page = page; } return __xip_sparse_page; } @@ -174,18 +172,23 @@ __xip_unmap (struct address_space * mapping, pte_t pteval; spinlock_t *ptl; struct page *page; + unsigned count; + int locked = 0; + + count = read_seqcount_begin(&xip_sparse_seq); page = __xip_sparse_page; if (!page) return; +retry: spin_lock(&mapping->i_mmap_lock); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { mm = vma->vm_mm; address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); BUG_ON(address < vma->vm_start || address >= vma->vm_end); - pte = page_check_address(page, mm, address, &ptl); + pte = page_check_address(page, mm, address, &ptl, 1); if (pte) { /* Nuke the page table entry. */ flush_cache_page(vma, address, pte_pfn(*pte)); @@ -198,6 +201,14 @@ __xip_unmap (struct address_space * mapping, } } spin_unlock(&mapping->i_mmap_lock); + + if (locked) { + mutex_unlock(&xip_sparse_mutex); + } else if (read_seqcount_retry(&xip_sparse_seq, count)) { + mutex_lock(&xip_sparse_mutex); + locked = 1; + goto retry; + } } /* @@ -218,7 +229,7 @@ static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf) int error; /* XXX: are VM_FAULT_ codes OK? */ - +again: size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (vmf->pgoff >= size) return VM_FAULT_SIGBUS; @@ -237,8 +248,10 @@ static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf) int err; /* maybe shared writable, allocate new block */ + mutex_lock(&xip_sparse_mutex); error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 1, &xip_mem, &xip_pfn); + mutex_unlock(&xip_sparse_mutex); if (error) return VM_FAULT_SIGBUS; /* unmap sparse mappings at pgoff from all other vmas */ @@ -252,14 +265,34 @@ found: BUG_ON(err); return VM_FAULT_NOPAGE; } else { + int err, ret = VM_FAULT_OOM; + + mutex_lock(&xip_sparse_mutex); + write_seqcount_begin(&xip_sparse_seq); + error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 0, + &xip_mem, &xip_pfn); + if (unlikely(!error)) { + write_seqcount_end(&xip_sparse_seq); + mutex_unlock(&xip_sparse_mutex); + goto again; + } + if (error != -ENODATA) + goto out; /* not shared and writable, use xip_sparse_page() */ page = xip_sparse_page(); if (!page) - return VM_FAULT_OOM; + goto out; + err = vm_insert_page(vma, (unsigned long)vmf->virtual_address, + page); + if (err == -ENOMEM) + goto out; - page_cache_get(page); - vmf->page = page; - return 0; + ret = VM_FAULT_NOPAGE; +out: + write_seqcount_end(&xip_sparse_seq); + mutex_unlock(&xip_sparse_mutex); + + return ret; } } @@ -308,8 +341,10 @@ __xip_file_write(struct file *filp, const char __user *buf, &xip_mem, &xip_pfn); if (status == -ENODATA) { /* we allocate a new page unmap it */ + mutex_lock(&xip_sparse_mutex); status = a_ops->get_xip_mem(mapping, index, 1, &xip_mem, &xip_pfn); + mutex_unlock(&xip_sparse_mutex); if (!status) /* unmap page at pgoff from all other vmas */ __xip_unmap(mapping, index); diff --git a/mm/mm_init.c b/mm/mm_init.c index 936ef2e..4e0e265 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -12,7 +12,7 @@ #include "internal.h" #ifdef CONFIG_DEBUG_MEMORY_INIT -int __meminitdata mminit_loglevel; +int mminit_loglevel; #ifndef SECTIONS_SHIFT #define SECTIONS_SHIFT 0 @@ -224,10 +224,14 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) /* * Check that @page is mapped at @address into @mm. * + * If @sync is false, page_check_address may perform a racy check to avoid + * the page table lock when the pte is not present (helpful when reclaiming + * highly shared pages). + * * On success returns with pte mapped and locked. */ pte_t *page_check_address(struct page *page, struct mm_struct *mm, - unsigned long address, spinlock_t **ptlp) + unsigned long address, spinlock_t **ptlp, int sync) { pgd_t *pgd; pud_t *pud; @@ -249,7 +253,7 @@ pte_t *page_check_address(struct page *page, struct mm_struct *mm, pte = pte_offset_map(pmd, address); /* Make a quick check before getting the lock */ - if (!pte_present(*pte)) { + if (!sync && !pte_present(*pte)) { pte_unmap(pte); return NULL; } @@ -281,7 +285,7 @@ static int page_referenced_one(struct page *page, if (address == -EFAULT) goto out; - pte = page_check_address(page, mm, address, &ptl); + pte = page_check_address(page, mm, address, &ptl, 0); if (!pte) goto out; @@ -450,7 +454,7 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma) if (address == -EFAULT) goto out; - pte = page_check_address(page, mm, address, &ptl); + pte = page_check_address(page, mm, address, &ptl, 1); if (!pte) goto out; @@ -659,23 +663,30 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma) } /* - * It would be tidy to reset the PageAnon mapping here, - * but that might overwrite a racing page_add_anon_rmap - * which increments mapcount after us but sets mapping - * before us: so leave the reset to free_hot_cold_page, - * and remember that it's only reliable while mapped. - * Leaving it set also helps swapoff to reinstate ptes - * faster for those pages still in swapcache. + * Now that the last pte has gone, s390 must transfer dirty + * flag from storage key to struct page. We can usually skip + * this if the page is anon, so about to be freed; but perhaps + * not if it's in swapcache - there might be another pte slot + * containing the swap entry, but page not yet written to swap. */ if ((!PageAnon(page) || PageSwapCache(page)) && page_test_dirty(page)) { page_clear_dirty(page); set_page_dirty(page); } - mem_cgroup_uncharge_page(page); + mem_cgroup_uncharge_page(page); __dec_zone_page_state(page, - PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); + PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); + /* + * It would be tidy to reset the PageAnon mapping here, + * but that might overwrite a racing page_add_anon_rmap + * which increments mapcount after us but sets mapping + * before us: so leave the reset to free_hot_cold_page, + * and remember that it's only reliable while mapped. + * Leaving it set also helps swapoff to reinstate ptes + * faster for those pages still in swapcache. + */ } } @@ -697,7 +708,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, if (address == -EFAULT) goto out; - pte = page_check_address(page, mm, address, &ptl); + pte = page_check_address(page, mm, address, &ptl, 0); if (!pte) goto out; diff --git a/mm/swap_state.c b/mm/swap_state.c index 167cf2d..797c383 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -60,7 +60,7 @@ void show_swap_cache_info(void) printk("Swap cache stats: add %lu, delete %lu, find %lu/%lu\n", swap_cache_info.add_total, swap_cache_info.del_total, swap_cache_info.find_success, swap_cache_info.find_total); - printk("Free swap = %lukB\n", nr_swap_pages << (PAGE_SHIFT - 10)); + printk("Free swap = %ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10)); printk("Total swap = %lukB\n", total_swap_pages << (PAGE_SHIFT - 10)); } diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 4e59df5..1edfdf4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -456,7 +456,7 @@ static void __exit bt_exit(void) subsys_initcall(bt_init); module_exit(bt_exit); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth Core ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 12bba62..80ba30c 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -736,7 +736,7 @@ MODULE_PARM_DESC(compress_src, "Compress sources headers"); module_param(compress_dst, bool, 0644); MODULE_PARM_DESC(compress_dst, "Compress destination headers"); -MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index c85bf8f..f4f6615 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -3,8 +3,6 @@ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/platform_device.h> - #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -12,10 +10,164 @@ #undef BT_DBG #define BT_DBG(D...) #endif + +struct class *bt_class = NULL; +EXPORT_SYMBOL_GPL(bt_class); + static struct workqueue_struct *btaddconn; static struct workqueue_struct *btdelconn; -static inline char *typetostr(int type) +static inline char *link_typetostr(int type) +{ + switch (type) { + case ACL_LINK: + return "ACL"; + case SCO_LINK: + return "SCO"; + case ESCO_LINK: + return "eSCO"; + default: + return "UNKNOWN"; + } +} + +static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", link_typetostr(conn->type)); +} + +static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + bdaddr_t bdaddr; + baswap(&bdaddr, &conn->dst); + return sprintf(buf, "%s\n", batostr(&bdaddr)); +} + +static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_conn *conn = dev_get_drvdata(dev); + + return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + conn->features[0], conn->features[1], + conn->features[2], conn->features[3], + conn->features[4], conn->features[5], + conn->features[6], conn->features[7]); +} + +#define LINK_ATTR(_name,_mode,_show,_store) \ +struct device_attribute link_attr_##_name = __ATTR(_name,_mode,_show,_store) + +static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); +static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); +static LINK_ATTR(features, S_IRUGO, show_link_features, NULL); + +static struct attribute *bt_link_attrs[] = { + &link_attr_type.attr, + &link_attr_address.attr, + &link_attr_features.attr, + NULL +}; + +static struct attribute_group bt_link_group = { + .attrs = bt_link_attrs, +}; + +static struct attribute_group *bt_link_groups[] = { + &bt_link_group, + NULL +}; + +static void bt_link_release(struct device *dev) +{ + void *data = dev_get_drvdata(dev); + kfree(data); +} + +static struct device_type bt_link = { + .name = "link", + .groups = bt_link_groups, + .release = bt_link_release, +}; + +static void add_conn(struct work_struct *work) +{ + struct hci_conn *conn = container_of(work, struct hci_conn, work); + + flush_workqueue(btdelconn); + + if (device_add(&conn->dev) < 0) { + BT_ERR("Failed to register connection device"); + return; + } +} + +void hci_conn_add_sysfs(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + + BT_DBG("conn %p", conn); + + conn->dev.type = &bt_link; + conn->dev.class = bt_class; + conn->dev.parent = &hdev->dev; + + snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", + hdev->name, conn->handle); + + dev_set_drvdata(&conn->dev, conn); + + device_initialize(&conn->dev); + + INIT_WORK(&conn->work, add_conn); + + queue_work(btaddconn, &conn->work); +} + +/* + * The rfcomm tty device will possibly retain even when conn + * is down, and sysfs doesn't support move zombie device, + * so we should move the device before conn device is destroyed. + */ +static int __match_tty(struct device *dev, void *data) +{ + return !strncmp(dev->bus_id, "rfcomm", 6); +} + +static void del_conn(struct work_struct *work) +{ + struct hci_conn *conn = container_of(work, struct hci_conn, work); + struct hci_dev *hdev = conn->hdev; + + while (1) { + struct device *dev; + + dev = device_find_child(&conn->dev, NULL, __match_tty); + if (!dev) + break; + device_move(dev, NULL); + put_device(dev); + } + + device_del(&conn->dev); + put_device(&conn->dev); + hci_dev_put(hdev); +} + +void hci_conn_del_sysfs(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + if (!device_is_registered(&conn->dev)) + return; + + INIT_WORK(&conn->work, del_conn); + + queue_work(btdelconn, &conn->work); +} + +static inline char *host_typetostr(int type) { switch (type) { case HCI_VIRTUAL: @@ -40,7 +192,7 @@ static inline char *typetostr(int type) static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", typetostr(hdev->type)); + return sprintf(buf, "%s\n", host_typetostr(hdev->type)); } static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -221,183 +373,62 @@ static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, show_sniff_min_interval, store_sniff_min_interval); -static struct device_attribute *bt_attrs[] = { - &dev_attr_type, - &dev_attr_name, - &dev_attr_class, - &dev_attr_address, - &dev_attr_features, - &dev_attr_manufacturer, - &dev_attr_hci_version, - &dev_attr_hci_revision, - &dev_attr_inquiry_cache, - &dev_attr_idle_timeout, - &dev_attr_sniff_max_interval, - &dev_attr_sniff_min_interval, +static struct attribute *bt_host_attrs[] = { + &dev_attr_type.attr, + &dev_attr_name.attr, + &dev_attr_class.attr, + &dev_attr_address.attr, + &dev_attr_features.attr, + &dev_attr_manufacturer.attr, + &dev_attr_hci_version.attr, + &dev_attr_hci_revision.attr, + &dev_attr_inquiry_cache.attr, + &dev_attr_idle_timeout.attr, + &dev_attr_sniff_max_interval.attr, + &dev_attr_sniff_min_interval.attr, NULL }; -static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO"); -} - -static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - bdaddr_t bdaddr; - baswap(&bdaddr, &conn->dst); - return sprintf(buf, "%s\n", batostr(&bdaddr)); -} - -static ssize_t show_conn_features(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_conn *conn = dev_get_drvdata(dev); - - return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", - conn->features[0], conn->features[1], - conn->features[2], conn->features[3], - conn->features[4], conn->features[5], - conn->features[6], conn->features[7]); -} - -#define CONN_ATTR(_name,_mode,_show,_store) \ -struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store) - -static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL); -static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL); -static CONN_ATTR(features, S_IRUGO, show_conn_features, NULL); - -static struct device_attribute *conn_attrs[] = { - &conn_attr_type, - &conn_attr_address, - &conn_attr_features, - NULL +static struct attribute_group bt_host_group = { + .attrs = bt_host_attrs, }; -struct class *bt_class = NULL; -EXPORT_SYMBOL_GPL(bt_class); - -static struct bus_type bt_bus = { - .name = "bluetooth", +static struct attribute_group *bt_host_groups[] = { + &bt_host_group, + NULL }; -static struct platform_device *bt_platform; - -static void bt_release(struct device *dev) +static void bt_host_release(struct device *dev) { void *data = dev_get_drvdata(dev); kfree(data); } -static void add_conn(struct work_struct *work) -{ - struct hci_conn *conn = container_of(work, struct hci_conn, work); - int i; - - flush_workqueue(btdelconn); - - if (device_add(&conn->dev) < 0) { - BT_ERR("Failed to register connection device"); - return; - } - - for (i = 0; conn_attrs[i]; i++) - if (device_create_file(&conn->dev, conn_attrs[i]) < 0) - BT_ERR("Failed to create connection attribute"); -} - -void hci_conn_add_sysfs(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - - BT_DBG("conn %p", conn); - - conn->dev.bus = &bt_bus; - conn->dev.parent = &hdev->dev; - - conn->dev.release = bt_release; - - snprintf(conn->dev.bus_id, BUS_ID_SIZE, "%s:%d", - hdev->name, conn->handle); - - dev_set_drvdata(&conn->dev, conn); - - device_initialize(&conn->dev); - - INIT_WORK(&conn->work, add_conn); - - queue_work(btaddconn, &conn->work); -} - -/* - * The rfcomm tty device will possibly retain even when conn - * is down, and sysfs doesn't support move zombie device, - * so we should move the device before conn device is destroyed. - */ -static int __match_tty(struct device *dev, void *data) -{ - return !strncmp(dev->bus_id, "rfcomm", 6); -} - -static void del_conn(struct work_struct *work) -{ - struct hci_conn *conn = container_of(work, struct hci_conn, work); - struct hci_dev *hdev = conn->hdev; - - while (1) { - struct device *dev; - - dev = device_find_child(&conn->dev, NULL, __match_tty); - if (!dev) - break; - device_move(dev, NULL); - put_device(dev); - } - - device_del(&conn->dev); - put_device(&conn->dev); - hci_dev_put(hdev); -} - -void hci_conn_del_sysfs(struct hci_conn *conn) -{ - BT_DBG("conn %p", conn); - - if (!device_is_registered(&conn->dev)) - return; - - INIT_WORK(&conn->work, del_conn); - - queue_work(btdelconn, &conn->work); -} +static struct device_type bt_host = { + .name = "host", + .groups = bt_host_groups, + .release = bt_host_release, +}; int hci_register_sysfs(struct hci_dev *hdev) { struct device *dev = &hdev->dev; - unsigned int i; int err; BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); - dev->bus = &bt_bus; + dev->type = &bt_host; + dev->class = bt_class; dev->parent = hdev->parent; strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); - dev->release = bt_release; - dev_set_drvdata(dev, hdev); err = device_register(dev); if (err < 0) return err; - for (i = 0; bt_attrs[i]; i++) - if (device_create_file(dev, bt_attrs[i]) < 0) - BT_ERR("Failed to create device attribute"); - return 0; } @@ -410,59 +441,30 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - int err; - btaddconn = create_singlethread_workqueue("btaddconn"); - if (!btaddconn) { - err = -ENOMEM; - goto out; - } + if (!btaddconn) + return -ENOMEM; btdelconn = create_singlethread_workqueue("btdelconn"); if (!btdelconn) { - err = -ENOMEM; - goto out_del; - } - - bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); - if (IS_ERR(bt_platform)) { - err = PTR_ERR(bt_platform); - goto out_platform; + destroy_workqueue(btaddconn); + return -ENOMEM; } - err = bus_register(&bt_bus); - if (err < 0) - goto out_bus; - bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { - err = PTR_ERR(bt_class); - goto out_class; + destroy_workqueue(btdelconn); + destroy_workqueue(btaddconn); + return PTR_ERR(bt_class); } return 0; - -out_class: - bus_unregister(&bt_bus); -out_bus: - platform_device_unregister(bt_platform); -out_platform: - destroy_workqueue(btdelconn); -out_del: - destroy_workqueue(btaddconn); -out: - return err; } void bt_sysfs_cleanup(void) { destroy_workqueue(btaddconn); - destroy_workqueue(btdelconn); class_destroy(bt_class); - - bus_unregister(&bt_bus); - - platform_device_unregister(bt_platform); } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index c123985..3396d5b 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2516,7 +2516,7 @@ EXPORT_SYMBOL(l2cap_load); module_init(l2cap_init); module_exit(l2cap_exit); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 6cfc7ba..ba537fa 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2115,7 +2115,7 @@ MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel"); module_param(l2cap_mtu, uint, 0644); MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8cda498..a16011f 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1002,7 +1002,7 @@ module_exit(sco_exit); module_param(disable_esco, bool, 0644); MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation"); -MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 9b58d70..4f52c3d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -148,11 +148,16 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) } static struct ethtool_ops br_ethtool_ops = { - .get_drvinfo = br_getinfo, - .get_link = ethtool_op_get_link, - .set_sg = br_set_sg, - .set_tx_csum = br_set_tx_csum, - .set_tso = br_set_tso, + .get_drvinfo = br_getinfo, + .get_link = ethtool_op_get_link, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = br_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = br_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = br_set_tso, + .get_ufo = ethtool_op_get_ufo, + .get_flags = ethtool_op_get_flags, }; void br_dev_setup(struct net_device *dev) diff --git a/net/core/datagram.c b/net/core/datagram.c index dd61dca..52f577a 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -339,6 +339,93 @@ fault: return -EFAULT; } +/** + * skb_copy_datagram_from_iovec - Copy a datagram from an iovec. + * @skb: buffer to copy + * @offset: offset in the buffer to start copying to + * @from: io vector to copy to + * @len: amount of data to copy to buffer from iovec + * + * Returns 0 or -EFAULT. + * Note: the iovec is modified during the copy. + */ +int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, + struct iovec *from, int len) +{ + int start = skb_headlen(skb); + int i, copy = start - offset; + + /* Copy header. */ + if (copy > 0) { + if (copy > len) + copy = len; + if (memcpy_fromiovec(skb->data + offset, from, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + } + + /* Copy paged appendix. Hmm... why does this look so complicated? */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + WARN_ON(start > offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + int err; + u8 *vaddr; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + + if (copy > len) + copy = len; + vaddr = kmap(page); + err = memcpy_fromiovec(vaddr + frag->page_offset + + offset - start, from, copy); + kunmap(page); + if (err) + goto fault; + + if (!(len -= copy)) + return 0; + offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + WARN_ON(start > offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + if (skb_copy_datagram_from_iovec(list, + offset - start, + from, copy)) + goto fault; + if ((len -= copy) == 0) + return 0; + offset += copy; + } + start = end; + } + } + if (!len) + return 0; + +fault: + return -EFAULT; +} +EXPORT_SYMBOL(skb_copy_datagram_from_iovec); + static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 __user *to, int len, __wsum *csump) diff --git a/net/core/dev.c b/net/core/dev.c index 600bb23..60c51f7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1339,19 +1339,23 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) } -void __netif_schedule(struct Qdisc *q) +static inline void __netif_reschedule(struct Qdisc *q) { - if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) { - struct softnet_data *sd; - unsigned long flags; + struct softnet_data *sd; + unsigned long flags; - local_irq_save(flags); - sd = &__get_cpu_var(softnet_data); - q->next_sched = sd->output_queue; - sd->output_queue = q; - raise_softirq_irqoff(NET_TX_SOFTIRQ); - local_irq_restore(flags); - } + local_irq_save(flags); + sd = &__get_cpu_var(softnet_data); + q->next_sched = sd->output_queue; + sd->output_queue = q; + raise_softirq_irqoff(NET_TX_SOFTIRQ); + local_irq_restore(flags); +} + +void __netif_schedule(struct Qdisc *q) +{ + if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) + __netif_reschedule(q); } EXPORT_SYMBOL(__netif_schedule); @@ -1800,9 +1804,13 @@ gso: spin_lock(root_lock); - rc = qdisc_enqueue_root(skb, q); - qdisc_run(q); - + if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) { + kfree_skb(skb); + rc = NET_XMIT_DROP; + } else { + rc = qdisc_enqueue_root(skb, q); + qdisc_run(q); + } spin_unlock(root_lock); goto out; @@ -1974,15 +1982,17 @@ static void net_tx_action(struct softirq_action *h) head = head->next_sched; - smp_mb__before_clear_bit(); - clear_bit(__QDISC_STATE_SCHED, &q->state); - root_lock = qdisc_lock(q); if (spin_trylock(root_lock)) { + smp_mb__before_clear_bit(); + clear_bit(__QDISC_STATE_SCHED, + &q->state); qdisc_run(q); spin_unlock(root_lock); } else { - __netif_schedule(q); + if (!test_bit(__QDISC_STATE_DEACTIVATED, + &q->state)) + __netif_reschedule(q); } } } @@ -2084,7 +2094,8 @@ static int ing_filter(struct sk_buff *skb) q = rxq->qdisc; if (q != &noop_qdisc) { spin_lock(qdisc_lock(q)); - result = qdisc_enqueue_root(skb, q); + if (likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) + result = qdisc_enqueue_root(skb, q); spin_unlock(qdisc_lock(q)); } diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index a89f32f..57abe82 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -99,7 +99,7 @@ struct gen_estimator_head static struct gen_estimator_head elist[EST_MAX_INTERVAL+1]; -/* Protects against NULL dereference and RCU write-side */ +/* Protects against NULL dereference */ static DEFINE_RWLOCK(est_lock); static void est_timer(unsigned long arg) @@ -185,7 +185,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; - write_lock_bh(&est_lock); if (!elist[idx].timer.function) { INIT_LIST_HEAD(&elist[idx].list); setup_timer(&elist[idx].timer, est_timer, idx); @@ -195,7 +194,6 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx)); list_add_rcu(&est->list, &elist[idx].list); - write_unlock_bh(&est_lock); return 0; } @@ -214,6 +212,7 @@ static void __gen_kill_estimator(struct rcu_head *head) * Removes the rate estimator specified by &bstats and &rate_est * and deletes the timer. * + * NOTE: Called under rtnl_mutex */ void gen_kill_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est) @@ -227,17 +226,17 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats, if (!elist[idx].timer.function) continue; - write_lock_bh(&est_lock); list_for_each_entry_safe(e, n, &elist[idx].list, list) { if (e->rate_est != rate_est || e->bstats != bstats) continue; + write_lock_bh(&est_lock); e->bstats = NULL; + write_unlock_bh(&est_lock); list_del_rcu(&e->list); call_rcu(&e->e_rcu, __gen_kill_estimator); } - write_unlock_bh(&est_lock); } } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 8464017..ca1ccdf 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2256,14 +2256,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) segs = nskb; tail = nskb; - nskb->dev = skb->dev; - skb_copy_queue_mapping(nskb, skb); - nskb->priority = skb->priority; - nskb->protocol = skb->protocol; - nskb->vlan_tci = skb->vlan_tci; - nskb->dst = dst_clone(skb->dst); - memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); - nskb->pkt_type = skb->pkt_type; + __copy_skb_header(nskb, skb); nskb->mac_len = skb->mac_len; skb_reserve(nskb, headroom); @@ -2274,6 +2267,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) skb_copy_from_linear_data(skb, skb_put(nskb, doffset), doffset); if (!sg) { + nskb->ip_summed = CHECKSUM_NONE; nskb->csum = skb_copy_and_csum_bits(skb, offset, skb_put(nskb, len), len, 0); @@ -2283,8 +2277,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) frag = skb_shinfo(nskb)->frags; k = 0; - nskb->ip_summed = CHECKSUM_PARTIAL; - nskb->csum = skb->csum; skb_copy_from_linear_data_offset(skb, offset, skb_put(nskb, hsize), hsize); diff --git a/net/dccp/input.c b/net/dccp/input.c index df2f110..803933a 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -411,12 +411,6 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, struct dccp_sock *dp = dccp_sk(sk); long tstamp = dccp_timestamp(); - /* Stop the REQUEST timer */ - inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); - WARN_ON(sk->sk_send_head == NULL); - __kfree_skb(sk->sk_send_head); - sk->sk_send_head = NULL; - if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, dp->dccps_awl, dp->dccps_awh)) { dccp_pr_debug("invalid ackno: S.AWL=%llu, " @@ -441,6 +435,12 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, DCCP_ACKVEC_STATE_RECEIVED)) goto out_invalid_packet; /* FIXME: change error code */ + /* Stop the REQUEST timer */ + inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); + WARN_ON(sk->sk_send_head == NULL); + kfree_skb(sk->sk_send_head); + sk->sk_send_head = NULL; + dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; dccp_update_gsr(sk, dp->dccps_isr); /* diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 8605586..55c355e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -204,18 +204,22 @@ static struct sock *icmp_sk(struct net *net) return net->ipv4.icmp_sk[smp_processor_id()]; } -static inline int icmp_xmit_lock(struct sock *sk) +static inline struct sock *icmp_xmit_lock(struct net *net) { + struct sock *sk; + local_bh_disable(); + sk = icmp_sk(net); + if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { /* This can happen if the output path signals a * dst_link_failure() for an outgoing ICMP packet. */ local_bh_enable(); - return 1; + return NULL; } - return 0; + return sk; } static inline void icmp_xmit_unlock(struct sock *sk) @@ -354,15 +358,17 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) struct ipcm_cookie ipc; struct rtable *rt = skb->rtable; struct net *net = dev_net(rt->u.dst.dev); - struct sock *sk = icmp_sk(net); - struct inet_sock *inet = inet_sk(sk); + struct sock *sk; + struct inet_sock *inet; __be32 daddr; if (ip_options_echo(&icmp_param->replyopts, skb)) return; - if (icmp_xmit_lock(sk)) + sk = icmp_xmit_lock(net); + if (sk == NULL) return; + inet = inet_sk(sk); icmp_param->data.icmph.checksum = 0; @@ -419,7 +425,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) if (!rt) goto out; net = dev_net(rt->u.dst.dev); - sk = icmp_sk(net); /* * Find the original header. It is expected to be valid, of course. @@ -483,7 +488,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } } - if (icmp_xmit_lock(sk)) + sk = icmp_xmit_lock(net); + if (sk == NULL) return; /* diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index 49587a4..462a22c 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -70,7 +70,7 @@ addrtype_mt_v1(const struct sk_buff *skb, const struct net_device *in, (info->flags & IPT_ADDRTYPE_INVERT_SOURCE); if (ret && info->dest) ret &= match_type(dev, iph->daddr, info->dest) ^ - (info->flags & IPT_ADDRTYPE_INVERT_DEST); + !!(info->flags & IPT_ADDRTYPE_INVERT_DEST); return ret; } diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c index 91537f1..6c4f11f 100644 --- a/net/ipv4/netfilter/nf_nat_proto_common.c +++ b/net/ipv4/netfilter/nf_nat_proto_common.c @@ -73,9 +73,13 @@ bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, range_size = ntohs(range->max.all) - min + 1; } - off = *rover; if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) - off = net_random(); + off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, + maniptype == IP_NAT_MANIP_SRC + ? tuple->dst.u.all + : tuple->src.u.all); + else + off = *rover; for (i = 0; i < range_size; i++, off++) { *portptr = htons(min + off % range_size); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 16fc6f4..cca921e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2914,6 +2914,68 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, return 0; } +static void rt_secret_reschedule(int old) +{ + struct net *net; + int new = ip_rt_secret_interval; + int diff = new - old; + + if (!diff) + return; + + rtnl_lock(); + for_each_net(net) { + int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); + + if (!new) + continue; + + if (deleted) { + long time = net->ipv4.rt_secret_timer.expires - jiffies; + + if (time <= 0 || (time += diff) <= 0) + time = 0; + + net->ipv4.rt_secret_timer.expires = time; + } else + net->ipv4.rt_secret_timer.expires = new; + + net->ipv4.rt_secret_timer.expires += jiffies; + add_timer(&net->ipv4.rt_secret_timer); + } + rtnl_unlock(); +} + +static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write, + struct file *filp, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int old = ip_rt_secret_interval; + int ret = proc_dointvec_jiffies(ctl, write, filp, buffer, lenp, ppos); + + rt_secret_reschedule(old); + + return ret; +} + +static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table, + int __user *name, + int nlen, + void __user *oldval, + size_t __user *oldlenp, + void __user *newval, + size_t newlen) +{ + int old = ip_rt_secret_interval; + int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval, + newlen); + + rt_secret_reschedule(old); + + return ret; +} + static ctl_table ipv4_route_table[] = { { .ctl_name = NET_IPV4_ROUTE_GC_THRESH, @@ -3048,8 +3110,8 @@ static ctl_table ipv4_route_table[] = { .data = &ip_rt_secret_interval, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies, + .proc_handler = &ipv4_sysctl_rt_secret_interval, + .strategy = &ipv4_sysctl_rt_secret_interval_strategy, }, { .ctl_name = 0 } }; @@ -3126,10 +3188,12 @@ static __net_init int rt_secret_timer_init(struct net *net) net->ipv4.rt_secret_timer.data = (unsigned long)net; init_timer_deferrable(&net->ipv4.rt_secret_timer); - net->ipv4.rt_secret_timer.expires = - jiffies + net_random() % ip_rt_secret_interval + - ip_rt_secret_interval; - add_timer(&net->ipv4.rt_secret_timer); + if (ip_rt_secret_interval) { + net->ipv4.rt_secret_timer.expires = + jiffies + net_random() % ip_rt_secret_interval + + ip_rt_secret_interval; + add_timer(&net->ipv4.rt_secret_timer); + } return 0; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a7842c5..7b6a584 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1106,13 +1106,12 @@ out: return ret; } -int ipv6_dev_get_saddr(struct net_device *dst_dev, +int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, const struct in6_addr *daddr, unsigned int prefs, struct in6_addr *saddr) { struct ipv6_saddr_score scores[2], *score = &scores[0], *hiscore = &scores[1]; - struct net *net = dev_net(dst_dev); struct ipv6_saddr_dst dst; struct net_device *dev; int dst_type; @@ -1689,6 +1688,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, .fc_dst_len = plen, .fc_flags = RTF_UP | flags, .fc_nlinfo.nl_net = dev_net(dev), + .fc_protocol = RTPROT_KERNEL, }; ipv6_addr_copy(&cfg.fc_dst, pfx); diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 8d05527..f5de3f9 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -93,7 +93,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, if (flags & RT6_LOOKUP_F_SRCPREF_COA) srcprefs |= IPV6_PREFER_SRC_COA; - if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, + if (ipv6_dev_get_saddr(net, + ip6_dst_idev(&rt->u.dst)->dev, &flp->fl6_dst, srcprefs, &saddr)) goto again; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index abedf95..b3157a0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -91,19 +91,22 @@ static struct inet6_protocol icmpv6_protocol = { .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; -static __inline__ int icmpv6_xmit_lock(struct sock *sk) +static __inline__ struct sock *icmpv6_xmit_lock(struct net *net) { + struct sock *sk; + local_bh_disable(); + sk = icmpv6_sk(net); if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { /* This can happen if the output path (f.e. SIT or * ip6ip6 tunnel) signals dst_link_failure() for an * outgoing ICMP6 packet. */ local_bh_enable(); - return 1; + return NULL; } - return 0; + return sk; } static __inline__ void icmpv6_xmit_unlock(struct sock *sk) @@ -392,11 +395,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, fl.fl_icmp_code = code; security_skb_classify_flow(skb, &fl); - sk = icmpv6_sk(net); - np = inet6_sk(sk); - - if (icmpv6_xmit_lock(sk)) + sk = icmpv6_xmit_lock(net); + if (sk == NULL) return; + np = inet6_sk(sk); if (!icmpv6_xrlim_allow(sk, type, &fl)) goto out; @@ -539,11 +541,10 @@ static void icmpv6_echo_reply(struct sk_buff *skb) fl.fl_icmp_type = ICMPV6_ECHO_REPLY; security_skb_classify_flow(skb, &fl); - sk = icmpv6_sk(net); - np = inet6_sk(sk); - - if (icmpv6_xmit_lock(sk)) + sk = icmpv6_xmit_lock(net); + if (sk == NULL) return; + np = inet6_sk(sk); if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 52dddc2..29c7c99 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -378,6 +378,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) arg.skb = skb; arg.cb = cb; + arg.net = net; w->args = &arg; for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index a4402de..0e844c2 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -934,7 +934,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, goto out_err_release; if (ipv6_addr_any(&fl->fl6_src)) { - err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev, + err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, &fl->fl6_dst, sk ? inet6_sk(sk)->srcprefs : 0, &fl->fl6_src); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 741cfcd..4e5eac3 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -911,7 +911,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, } else { if (np->rxopt.bits.rxinfo) { struct in6_pktinfo src_info; - src_info.ipi6_ifindex = np->mcast_oif; + src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if; ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); } @@ -921,7 +921,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, } if (np->rxopt.bits.rxoinfo) { struct in6_pktinfo src_info; - src_info.ipi6_ifindex = np->mcast_oif; + src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : sk->sk_bound_dev_if; ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index beb48e3..f1c62ba 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -549,7 +549,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, override = 0; in6_ifa_put(ifp); } else { - if (ipv6_dev_get_saddr(dev, daddr, + if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr, inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs, &tmpaddr)) return; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 41b165f..9af6115 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2106,7 +2106,8 @@ static inline size_t rt6_nlmsg_size(void) + nla_total_size(sizeof(struct rta_cacheinfo)); } -static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, +static int rt6_fill_node(struct net *net, + struct sk_buff *skb, struct rt6_info *rt, struct in6_addr *dst, struct in6_addr *src, int iif, int type, u32 pid, u32 seq, int prefix, int nowait, unsigned int flags) @@ -2189,7 +2190,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, } else if (dst) { struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst); struct in6_addr saddr_buf; - if (ipv6_dev_get_saddr(idev ? idev->dev : NULL, + if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, dst, 0, &saddr_buf) == 0) NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } @@ -2234,7 +2235,8 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) } else prefix = 0; - return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, + return rt6_fill_node(arg->net, + arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, prefix, 0, NLM_F_MULTI); } @@ -2300,7 +2302,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); skb->dst = &rt->u.dst; - err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, + err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 0, 0, 0); if (err < 0) { @@ -2327,7 +2329,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) if (skb == NULL) goto errout; - err = rt6_fill_node(skb, rt, NULL, NULL, 0, + err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, event, info->pid, seq, 0, 0, 0); if (err < 0) { /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 8f1e054..08e4cbb 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -52,12 +52,14 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr, static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) { struct dst_entry *dst; + struct net_device *dev; dst = xfrm6_dst_lookup(0, NULL, daddr); if (IS_ERR(dst)) return -EHOSTUNREACH; - ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev, + dev = ip6_dst_idev(dst)->dev; + ipv6_dev_get_saddr(dev_net(dev), dev, (struct in6_addr *)&daddr->a6, 0, (struct in6_addr *)&saddr->a6); dst_release(dst); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e1d11c9..1e97fb9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2103,6 +2103,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); return; } + /* update new sta with its last rx activity */ + sta->last_rx = jiffies; } /* diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 105a616..a875203 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -968,7 +968,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[]) /* need to zero data of old helper */ memset(&help->help, 0, sizeof(help->help)); } else { - help = nf_ct_helper_ext_add(ct, GFP_KERNEL); + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); if (help == NULL) return -ENOMEM; } @@ -1136,16 +1136,33 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ct->timeout.expires = jiffies + ct->timeout.expires * HZ; ct->status |= IPS_CONFIRMED; + rcu_read_lock(); + helper = __nf_ct_helper_find(rtuple); + if (helper) { + help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); + if (help == NULL) { + rcu_read_unlock(); + err = -ENOMEM; + goto err; + } + /* not in hash table yet so not strictly necessary */ + rcu_assign_pointer(help->helper, helper); + } + if (cda[CTA_STATUS]) { err = ctnetlink_change_status(ct, cda); - if (err < 0) + if (err < 0) { + rcu_read_unlock(); goto err; + } } if (cda[CTA_PROTOINFO]) { err = ctnetlink_change_protoinfo(ct, cda); - if (err < 0) + if (err < 0) { + rcu_read_unlock(); goto err; + } } nf_ct_acct_ext_add(ct, GFP_KERNEL); @@ -1155,19 +1172,6 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); #endif - rcu_read_lock(); - helper = __nf_ct_helper_find(rtuple); - if (helper) { - help = nf_ct_helper_ext_add(ct, GFP_KERNEL); - if (help == NULL) { - rcu_read_unlock(); - err = -ENOMEM; - goto err; - } - /* not in hash table yet so not strictly necessary */ - rcu_assign_pointer(help->helper, helper); - } - /* setup master conntrack: this is a confirmed expectation */ if (master_ct) { __set_bit(IPS_EXPECTED_BIT, &ct->status); diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index d2d4565..35a9994 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -150,6 +150,8 @@ static void update_rfkill_state(struct rfkill *rfkill) * calls and handling all the red tape such as issuing notifications * if the call is successful. * + * Suspended devices are not touched at all, and -EAGAIN is returned. + * * Note that the @force parameter cannot override a (possibly cached) * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of * RFKILL_STATE_HARD_BLOCKED implements either get_state() or @@ -168,6 +170,9 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, int retval = 0; enum rfkill_state oldstate, newstate; + if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) + return -EBUSY; + oldstate = rfkill->state; if (rfkill->get_state && !force && @@ -214,7 +219,7 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, * * This function toggles the state of all switches of given type, * unless a specific switch is claimed by userspace (in which case, - * that switch is left alone). + * that switch is left alone) or suspended. */ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) { @@ -239,8 +244,8 @@ EXPORT_SYMBOL(rfkill_switch_all); /** * rfkill_epo - emergency power off all transmitters * - * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring - * everything in its path but rfkill_mutex and rfkill->mutex. + * This kicks all non-suspended rfkill devices to RFKILL_STATE_SOFT_BLOCKED, + * ignoring everything in its path but rfkill_mutex and rfkill->mutex. */ void rfkill_epo(void) { @@ -458,13 +463,14 @@ static int rfkill_resume(struct device *dev) if (dev->power.power_state.event != PM_EVENT_ON) { mutex_lock(&rfkill->mutex); + dev->power.power_state.event = PM_EVENT_ON; + /* restore radio state AND notify everybody */ rfkill_toggle_radio(rfkill, rfkill->state, 1); mutex_unlock(&rfkill->mutex); } - dev->power.power_state = PMSG_ON; return 0; } #else diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index d2b6f54..5cafdd4 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -280,7 +280,7 @@ replay: if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { spin_lock_bh(root_lock); *back = tp->next; - spin_lock_bh(root_lock); + spin_unlock_bh(root_lock); tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); tcf_destroy(tp); diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index c25465e..e7fb9e0 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -27,6 +27,7 @@ #include <linux/kmod.h> #include <linux/list.h> #include <linux/hrtimer.h> +#include <linux/lockdep.h> #include <net/net_namespace.h> #include <net/sock.h> @@ -198,19 +199,53 @@ struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle) return NULL; } +/* + * This lock is needed until some qdiscs stop calling qdisc_tree_decrease_qlen() + * without rtnl_lock(); currently hfsc_dequeue(), netem_dequeue(), tbf_dequeue() + */ +static DEFINE_SPINLOCK(qdisc_list_lock); + +static void qdisc_list_add(struct Qdisc *q) +{ + if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { + spin_lock_bh(&qdisc_list_lock); + list_add_tail(&q->list, &qdisc_root_sleeping(q)->list); + spin_unlock_bh(&qdisc_list_lock); + } +} + +void qdisc_list_del(struct Qdisc *q) +{ + if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) { + spin_lock_bh(&qdisc_list_lock); + list_del(&q->list); + spin_unlock_bh(&qdisc_list_lock); + } +} +EXPORT_SYMBOL(qdisc_list_del); + struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) { unsigned int i; + struct Qdisc *q; + + spin_lock_bh(&qdisc_list_lock); for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *txq = netdev_get_tx_queue(dev, i); - struct Qdisc *q, *txq_root = txq->qdisc_sleeping; + struct Qdisc *txq_root = txq->qdisc_sleeping; q = qdisc_match_from_root(txq_root, handle); if (q) - return q; + goto unlock; } - return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle); + + q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle); + +unlock: + spin_unlock_bh(&qdisc_list_lock); + + return q; } static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) @@ -331,7 +366,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (!s || tsize != s->tsize || (!tab && tsize > 0)) return ERR_PTR(-EINVAL); - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); list_for_each_entry(stab, &qdisc_stab_list, list) { if (memcmp(&stab->szopts, s, sizeof(*s))) @@ -339,11 +374,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16))) continue; stab->refcnt++; - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); return stab; } - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); if (!stab) @@ -354,9 +389,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt) if (tsize > 0) memcpy(stab->data, tab, tsize * sizeof(u16)); - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); list_add_tail(&stab->list, &qdisc_stab_list); - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); return stab; } @@ -366,14 +401,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab) if (!tab) return; - spin_lock_bh(&qdisc_stab_lock); + spin_lock(&qdisc_stab_lock); if (--tab->refcnt == 0) { list_del(&tab->list); kfree(tab); } - spin_unlock_bh(&qdisc_stab_lock); + spin_unlock(&qdisc_stab_lock); } EXPORT_SYMBOL(qdisc_put_stab); @@ -426,7 +461,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) wd->qdisc->flags &= ~TCQ_F_THROTTLED; smp_wmb(); - __netif_schedule(wd->qdisc); + __netif_schedule(qdisc_root(wd->qdisc)); return HRTIMER_NORESTART; } @@ -443,6 +478,10 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) { ktime_t time; + if (test_bit(__QDISC_STATE_DEACTIVATED, + &qdisc_root_sleeping(wd->qdisc)->state)) + return; + wd->qdisc->flags |= TCQ_F_THROTTLED; time = ktime_set(0, 0); time = ktime_add_ns(time, PSCHED_US2NS(expires)); @@ -637,11 +676,8 @@ static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid if (new || old) qdisc_notify(skb, n, clid, old, new); - if (old) { - spin_lock_bh(&old->q.lock); + if (old) qdisc_destroy(old); - spin_unlock_bh(&old->q.lock); - } } /* Graft qdisc "new" to class "classid" of qdisc "parent" or @@ -707,6 +743,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, return err; } +/* lockdep annotation is needed for ingress; egress gets it only for name */ +static struct lock_class_key qdisc_tx_lock; +static struct lock_class_key qdisc_rx_lock; + /* Allocate and initialize new qdisc. @@ -767,6 +807,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, if (handle == TC_H_INGRESS) { sch->flags |= TCQ_F_INGRESS; handle = TC_H_MAKE(TC_H_INGRESS, 0); + lockdep_set_class(qdisc_lock(sch), &qdisc_rx_lock); } else { if (handle == 0) { handle = qdisc_alloc_handle(dev); @@ -774,6 +815,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, if (handle == 0) goto err_out3; } + lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock); } sch->handle = handle; @@ -802,8 +844,8 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, goto err_out3; } } - if ((parent != TC_H_ROOT) && !(sch->flags & TCQ_F_INGRESS)) - list_add_tail(&sch->list, &dev_queue->qdisc_sleeping->list); + + qdisc_list_add(sch); return sch; } @@ -1084,20 +1126,13 @@ create_n_graft: } graft: - if (1) { - spinlock_t *root_lock; - - err = qdisc_graft(dev, p, skb, n, clid, q, NULL); - if (err) { - if (q) { - root_lock = qdisc_root_lock(q); - spin_lock_bh(root_lock); - qdisc_destroy(q); - spin_unlock_bh(root_lock); - } - return err; - } + err = qdisc_graft(dev, p, skb, n, clid, q, NULL); + if (err) { + if (q) + qdisc_destroy(q); + return err; } + return 0; } diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 4e261ce..8fa90d6 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -521,6 +521,10 @@ static void cbq_ovl_delay(struct cbq_class *cl) struct cbq_sched_data *q = qdisc_priv(cl->qdisc); psched_tdiff_t delay = cl->undertime - q->now; + if (test_bit(__QDISC_STATE_DEACTIVATED, + &qdisc_root_sleeping(cl->qdisc)->state)) + return; + if (!cl->delayed) { psched_time_t sched = q->now; ktime_t expires; @@ -654,7 +658,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) } sch->flags &= ~TCQ_F_THROTTLED; - __netif_schedule(sch); + __netif_schedule(qdisc_root(sch)); return HRTIMER_NORESTART; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 4685746..5f0ade7 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -518,15 +518,17 @@ void qdisc_reset(struct Qdisc *qdisc) } EXPORT_SYMBOL(qdisc_reset); -/* this is the rcu callback function to clean up a qdisc when there - * are no further references to it */ - -static void __qdisc_destroy(struct rcu_head *head) +void qdisc_destroy(struct Qdisc *qdisc) { - struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu); const struct Qdisc_ops *ops = qdisc->ops; + if (qdisc->flags & TCQ_F_BUILTIN || + !atomic_dec_and_test(&qdisc->refcnt)) + return; + #ifdef CONFIG_NET_SCHED + qdisc_list_del(qdisc); + qdisc_put_stab(qdisc->stab); #endif gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); @@ -542,20 +544,6 @@ static void __qdisc_destroy(struct rcu_head *head) kfree((char *) qdisc - qdisc->padded); } - -/* Under qdisc_lock(qdisc) and BH! */ - -void qdisc_destroy(struct Qdisc *qdisc) -{ - if (qdisc->flags & TCQ_F_BUILTIN || - !atomic_dec_and_test(&qdisc->refcnt)) - return; - - if (qdisc->parent) - list_del(&qdisc->list); - - call_rcu(&qdisc->q_rcu, __qdisc_destroy); -} EXPORT_SYMBOL(qdisc_destroy); static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) @@ -597,6 +585,9 @@ static void transition_one_qdisc(struct net_device *dev, struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping; int *need_watchdog_p = _need_watchdog; + if (!(new_qdisc->flags & TCQ_F_BUILTIN)) + clear_bit(__QDISC_STATE_DEACTIVATED, &new_qdisc->state); + rcu_assign_pointer(dev_queue->qdisc, new_qdisc); if (need_watchdog_p && new_qdisc != &noqueue_qdisc) *need_watchdog_p = 1; @@ -640,6 +631,9 @@ static void dev_deactivate_queue(struct net_device *dev, if (qdisc) { spin_lock_bh(qdisc_lock(qdisc)); + if (!(qdisc->flags & TCQ_F_BUILTIN)) + set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state); + dev_queue->qdisc = qdisc_default; qdisc_reset(qdisc); @@ -647,7 +641,7 @@ static void dev_deactivate_queue(struct net_device *dev, } } -static bool some_qdisc_is_busy(struct net_device *dev, int lock) +static bool some_qdisc_is_busy(struct net_device *dev) { unsigned int i; @@ -661,14 +655,12 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock) q = dev_queue->qdisc_sleeping; root_lock = qdisc_lock(q); - if (lock) - spin_lock_bh(root_lock); + spin_lock_bh(root_lock); val = (test_bit(__QDISC_STATE_RUNNING, &q->state) || test_bit(__QDISC_STATE_SCHED, &q->state)); - if (lock) - spin_unlock_bh(root_lock); + spin_unlock_bh(root_lock); if (val) return true; @@ -678,8 +670,6 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock) void dev_deactivate(struct net_device *dev) { - bool running; - netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc); @@ -689,25 +679,8 @@ void dev_deactivate(struct net_device *dev) synchronize_rcu(); /* Wait for outstanding qdisc_run calls. */ - do { - while (some_qdisc_is_busy(dev, 0)) - yield(); - - /* - * Double-check inside queue lock to ensure that all effects - * of the queue run are visible when we return. - */ - running = some_qdisc_is_busy(dev, 1); - - /* - * The running flag should never be set at this point because - * we've already set dev->qdisc to noop_qdisc *inside* the same - * pair of spin locks. That is, if any qdisc_run starts after - * our initial test it should see the noop_qdisc and then - * clear the RUNNING bit before dropping the queue lock. So - * if it is set here then we've found a bug. - */ - } while (WARN_ON_ONCE(running)); + while (some_qdisc_is_busy(dev)) + yield(); } static void dev_init_scheduler_queue(struct net_device *dev, @@ -736,14 +709,10 @@ static void shutdown_scheduler_queue(struct net_device *dev, struct Qdisc *qdisc_default = _qdisc_default; if (qdisc) { - spinlock_t *root_lock = qdisc_lock(qdisc); - dev_queue->qdisc = qdisc_default; dev_queue->qdisc_sleeping = qdisc_default; - spin_lock_bh(root_lock); qdisc_destroy(qdisc); - spin_unlock_bh(root_lock); } } diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 6febd24..0df0df2 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -577,7 +577,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) sch->qstats.drops++; cl->qstats.drops++; } - return NET_XMIT_DROP; + return ret; } else { cl->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; @@ -623,7 +623,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) sch->qstats.drops++; cl->qstats.drops++; } - return NET_XMIT_DROP; + return ret; } else htb_activate(q, cl); diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index eac1976..a6697c6 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -113,11 +113,11 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch) if ((ret = qdisc->ops->requeue(skb, qdisc)) == NET_XMIT_SUCCESS) { sch->q.qlen++; sch->qstats.requeues++; - return 0; + return NET_XMIT_SUCCESS; } if (net_xmit_drop_count(ret)) sch->qstats.drops++; - return NET_XMIT_DROP; + return ret; } diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 7d3b7ff..94c6159 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -123,15 +123,8 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) struct tbf_sched_data *q = qdisc_priv(sch); int ret; - if (qdisc_pkt_len(skb) > q->max_size) { - sch->qstats.drops++; -#ifdef CONFIG_NET_CLS_ACT - if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) -#endif - kfree_skb(skb); - - return NET_XMIT_DROP; - } + if (qdisc_pkt_len(skb) > q->max_size) + return qdisc_reshape_fail(skb, sch); ret = qdisc_enqueue(skb, q->qdisc); if (ret != 0) { diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index e39a0cd..4c8d9f4 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -103,6 +103,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, /* Initialize the CHUNKS parameter */ auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; + auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t)); /* If the Add-IP functionality is enabled, we must * authenticate, ASCONF and ASCONF-ACK chunks @@ -110,8 +111,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, if (sctp_addip_enable) { auth_chunks->chunks[0] = SCTP_CID_ASCONF; auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; - auth_chunks->param_hdr.length = - htons(sizeof(sctp_paramhdr_t) + 2); + auth_chunks->param_hdr.length += htons(2); } } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 483a01d..47f91af 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -319,7 +319,8 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, __func__, asoc, dst, NIP6(daddr->v6.sin6_addr)); if (!asoc) { - ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, + ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), + dst ? ip6_dst_idev(dst)->dev : NULL, &daddr->v6.sin6_addr, inet6_sk(&sk->inet.sk)->srcprefs, &saddr->v6.sin6_addr); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index dbb79ad..bb5c9ef 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3055,6 +3055,9 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, { struct sctp_authchunk val; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authchunk)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -3085,6 +3088,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, struct sctp_hmacalgo *hmacs; int err; + if (!sctp_auth_enable) + return -EACCES; + if (optlen < sizeof(struct sctp_hmacalgo)) return -EINVAL; @@ -3123,6 +3129,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, struct sctp_association *asoc; int ret; + if (!sctp_auth_enable) + return -EACCES; + if (optlen <= sizeof(struct sctp_authkey)) return -EINVAL; @@ -3160,6 +3169,9 @@ static int sctp_setsockopt_active_key(struct sock *sk, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -3185,6 +3197,9 @@ static int sctp_setsockopt_del_key(struct sock *sk, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (optlen != sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, optlen)) @@ -5197,19 +5212,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, char __user *optval, int __user *optlen) { + struct sctp_hmacalgo __user *p = (void __user *)optval; struct sctp_hmac_algo_param *hmacs; - __u16 param_len; + __u16 data_len = 0; + u32 num_idents; + + if (!sctp_auth_enable) + return -EACCES; hmacs = sctp_sk(sk)->ep->auth_hmacs_list; - param_len = ntohs(hmacs->param_hdr.length); + data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); - if (len < param_len) + if (len < sizeof(struct sctp_hmacalgo) + data_len) return -EINVAL; + + len = sizeof(struct sctp_hmacalgo) + data_len; + num_idents = data_len / sizeof(u16); + if (put_user(len, optlen)) return -EFAULT; - if (copy_to_user(optval, hmacs->hmac_ids, len)) + if (put_user(num_idents, &p->shmac_num_idents)) + return -EFAULT; + if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) return -EFAULT; - return 0; } @@ -5219,6 +5244,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, struct sctp_authkeyid val; struct sctp_association *asoc; + if (!sctp_auth_enable) + return -EACCES; + if (len < sizeof(struct sctp_authkeyid)) return -EINVAL; if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) @@ -5233,6 +5261,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, else val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; + len = sizeof(struct sctp_authkeyid); + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + return 0; } @@ -5243,13 +5277,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; - u32 num_chunks; + u32 num_chunks = 0; char __user *to; - if (len <= sizeof(struct sctp_authchunks)) + if (!sctp_auth_enable) + return -EACCES; + + if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -5258,20 +5295,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, return -EINVAL; ch = asoc->peer.peer_chunks; + if (!ch) + goto num; /* See if the user provided enough room for all the data */ num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); if (len < num_chunks) return -EINVAL; - len = num_chunks; - if (put_user(len, optlen)) + if (copy_to_user(to, ch->chunks, num_chunks)) return -EFAULT; +num: + len = sizeof(struct sctp_authchunks) + num_chunks; + if (put_user(len, optlen)) return -EFAULT; if (put_user(num_chunks, &p->gauth_number_of_chunks)) return -EFAULT; - if (copy_to_user(to, ch->chunks, len)) - return -EFAULT; - return 0; } @@ -5282,13 +5320,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, struct sctp_authchunks val; struct sctp_association *asoc; struct sctp_chunks_param *ch; - u32 num_chunks; + u32 num_chunks = 0; char __user *to; - if (len <= sizeof(struct sctp_authchunks)) + if (!sctp_auth_enable) + return -EACCES; + + if (len < sizeof(struct sctp_authchunks)) return -EINVAL; - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) return -EFAULT; to = p->gauth_chunks; @@ -5301,17 +5342,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, else ch = sctp_sk(sk)->ep->auth_chunk_list; + if (!ch) + goto num; + num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); - if (len < num_chunks) + if (len < sizeof(struct sctp_authchunks) + num_chunks) return -EINVAL; - len = num_chunks; + if (copy_to_user(to, ch->chunks, num_chunks)) + return -EFAULT; +num: + len = sizeof(struct sctp_authchunks) + num_chunks; if (put_user(len, optlen)) return -EFAULT; if (put_user(num_chunks, &p->gauth_number_of_chunks)) return -EFAULT; - if (copy_to_user(to, ch->chunks, len)) - return -EFAULT; return 0; } diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 4fa1f3a..4c9890e 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -344,14 +344,20 @@ static void do_pnp_device_entry(void *symval, unsigned long size, struct module *mod) { const unsigned long id_size = sizeof(struct pnp_device_id); - const struct pnp_device_id *id = symval; + const unsigned int count = (size / id_size)-1; + const struct pnp_device_id *devs = symval; + unsigned int i; device_id_check(mod->name, "pnp", size, id_size, symval); - buf_printf(&mod->dev_table_buf, - "MODULE_ALIAS(\"pnp:d%s*\");\n", id->id); - buf_printf(&mod->dev_table_buf, - "MODULE_ALIAS(\"acpi*:%s:*\");\n", id->id); + for (i = 0; i < count; i++) { + const char *id = (char *)devs[i].id; + + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"pnp:d%s*\");\n", id); + buf_printf(&mod->dev_table_buf, + "MODULE_ALIAS(\"acpi*:%s:*\");\n", id); + } } /* looks like: "pnp:dD" for every device of the card */ diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index ee0741f..fbef38a 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -38,7 +38,6 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/version.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/pcm.h> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a73d6ca..1c53e33 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -278,6 +278,9 @@ enum { /* Defines for Nvidia HDA support */ #define NVIDIA_HDA_TRANSREG_ADDR 0x4e #define NVIDIA_HDA_ENABLE_COHBITS 0x0f +#define NVIDIA_HDA_ISTRM_COH 0x4d +#define NVIDIA_HDA_OSTRM_COH 0x4c +#define NVIDIA_HDA_ENABLE_COHBIT 0x01 /* Defines for Intel SCH HDA snoop control */ #define INTEL_SCH_HDA_DEVC 0x78 @@ -900,6 +903,12 @@ static void azx_init_pci(struct azx *chip) update_pci_byte(chip->pci, NVIDIA_HDA_TRANSREG_ADDR, 0x0f, NVIDIA_HDA_ENABLE_COHBITS); + update_pci_byte(chip->pci, + NVIDIA_HDA_ISTRM_COH, + 0x01, NVIDIA_HDA_ENABLE_COHBIT); + update_pci_byte(chip->pci, + NVIDIA_HDA_OSTRM_COH, + 0x01, NVIDIA_HDA_ENABLE_COHBIT); break; case AZX_DRIVER_SCH: pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b80e725..909f1c1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -952,7 +952,7 @@ do_sku: tmp | 0x2010); break; case 0x10ec0888: - alc888_coef_init(codec); + /*alc888_coef_init(codec);*/ /* called in alc_init() */ break; case 0x10ec0267: case 0x10ec0268: @@ -2439,6 +2439,8 @@ static int alc_init(struct hda_codec *codec) unsigned int i; alc_fix_pll(codec); + if (codec->vendor_id == 0x10ec0888) + alc888_coef_init(codec); for (i = 0; i < spec->num_init_verbs; i++) snd_hda_sequence_write(codec, spec->init_verbs[i]); @@ -8426,8 +8428,6 @@ static int patch_alc883(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; if (board_config == ALC883_AUTO) spec->init_hook = alc883_auto_init; - else if (codec->vendor_id == 0x10ec0888) - spec->init_hook = alc888_coef_init; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c index b081e83..b81d6b2 100644 --- a/sound/soc/at91/eti_b1_wm8731.c +++ b/sound/soc/at91/eti_b1_wm8731.c @@ -22,7 +22,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/clk.h> #include <linux/timer.h> diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8604809..dc7b18f 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 1fb7f9a..2f1c91b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -13,7 +13,6 @@ #include <linux/init.h> #include <linux/module.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/device.h> #include <sound/core.h> |