]> err.no Git - linux-2.6/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Aug 2008 15:38:00 +0000 (08:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 Aug 2008 15:38:00 +0000 (08:38 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: authenc - Avoid using clobbered request pointer

169 files changed:
Documentation/filesystems/ext4.txt
Documentation/ja_JP/HOWTO
Documentation/ja_JP/SubmitChecklist [new file with mode: 0644]
Documentation/kernel-parameters.txt
Makefile
arch/arm/mach-integrator/impd1.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa300.c
arch/s390/defconfig
arch/s390/include/asm/bitops.h
arch/s390/kernel/process.c
arch/s390/kernel/smp.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/cpu/addon_cpuid_features.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/genx2apic_uv_x.c
arch/x86/kernel/numaq_32.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tlb_uv.c
arch/x86/kernel/tsc_sync.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/mmio-mod.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/oprofile/nmi_int.c
block/genhd.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_acpi.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_it821x.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_via.c
drivers/ata/sata_mv.c
drivers/base/class.c
drivers/base/core.c
drivers/base/driver.c
drivers/base/power/main.c
drivers/base/power/power.h
drivers/block/brd.c
drivers/block/nbd.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/infiniband/hw/ipath/ipath_iba7220.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/misc/eeepc-laptop.c
drivers/rtc/Kconfig
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1374.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_eer.c
drivers/s390/block/dcssblk.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_std.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/qdio_debug.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/qdio_thinint.c
drivers/uio/Kconfig
drivers/uio/Makefile
drivers/uio/uio_pdrv.c
drivers/uio/uio_pdrv_genirq.c [new file with mode: 0644]
drivers/usb/class/cdc-acm.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/pxa27x_udc.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/ohci-pnx8550.c
drivers/usb/host/ohci-ppc-of.c
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sh.c
drivers/usb/host/ohci-sm501.c
drivers/usb/host/ohci-ssb.c
drivers/usb/host/u132-hcd.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/musb/Kconfig
drivers/usb/musb/Makefile
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_debug.h
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_procfs.c [deleted file]
drivers/usb/serial/option.c
drivers/video/bf54x-lq043fb.c
drivers/video/fb_defio.c
drivers/video/fbmem.c
drivers/video/pm2fb.c
fs/binfmt_misc.c
fs/cramfs/inode.c
fs/ext4/balloc.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/ext4_extents.h
fs/ext4/ext4_jbd2.h
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ioprio.c
fs/proc/nommu.c
fs/proc/task_mmu.c
include/asm-x86/genapic_32.h
include/asm-x86/genapic_64.h
include/asm-x86/irq_vectors.h
include/asm-x86/uv/uv_bau.h
include/linux/device.h
include/linux/fb.h
include/linux/libata.h
include/linux/pid.h
include/linux/rmap.h
include/linux/tick.h
include/linux/usb.h
kernel/rcupdate.c
kernel/sched_features.h
kernel/sys.c
kernel/time/tick-sched.c
lib/kobject.c
mm/bootmem.c
mm/filemap_xip.c
mm/mm_init.c
mm/rmap.c
mm/swap_state.c
scripts/mod/file2alias.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c

index 80e193d82e2e10415cc828124cec296855398aeb..0d5394920a31c146ef85cc4df64107e37a6ae386 100644 (file)
@@ -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
index 488c77fa3aae138c41168408d983791819f5a7fb..0775cf4798b22f89d484f171f3a79726712ed695 100644 (file)
@@ -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 カーネルです。これに
\81¯ã\80\812.6.x ã\82«ã\83¼ã\83\8dã\83«ã\81§è¦\8bã\81¤ã\81\8bã\81£ã\81\9fã\82»ã\82­ã\83¥ã\83ªã\83\86ã\82£å\95\8fé¡\8cã\82\84é\87\8d大ã\81ªå¾\8cæ\88»ã\82\8aã\81«å¯¾ã\81\99ã\82\8bæ¯\94
-較的小さい重要な修正が含まれます。
+バージョン番号が4つの数字に分かれているカーネルは -stable カーネルです。
\81\93ã\82\8cã\81«ã\81¯ã\80\812.6.x ã\82«ã\83¼ã\83\8dã\83«ã\81§è¦\8bã\81¤ã\81\8bã\81£ã\81\9fã\82»ã\82­ã\83¥ã\83ªã\83\86ã\82£å\95\8fé¡\8cã\82\84é\87\8d大ã\81ªå¾\8cæ\88»ã\82\8aã\81«å¯¾
+する比較的小さい重要な修正が含まれます。
 
 これは、開発/実験的バージョンのテストに協力することに興味が無く、
 最新の安定したカーネルを使いたいユーザに推奨するブランチです。
 
-もし、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 (file)
index 0000000..6c42e07
--- /dev/null
@@ -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 およびその他のサブシステムに関する様々な変更と、現時点でも共存
+    できることを確認するテストを行ってください。
index e7bea3e853044e54f3ee863ad3d295b0df84a522..1150444a21ab64140f13e706797f16664e28244f 100644 (file)
@@ -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.
 
index 53bf6ec1af9d29fac6682fb6cd4c2e5dbcb84490..2e15e0b4483d68a2bfb37bc8cdca42fe86e12195 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 27
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*
index 0a7b3267c8d8302c3cf84e4392d23d87020444f1..3c8383dbe9e6fac52652215dba190667a610ad4b 100644 (file)
@@ -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);
                }
        }
index 0db3a909ae616310e1406f76ca177222b3a0d7cc..501dfdcc39fe996c86bc87ffb2289c3ae14f4925 100644 (file)
@@ -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);
index c01eea88f7874e702ffa50af37b9d56e67d4cb63..ca8e205381577ab07f05fec6e573f77554672c3c 100644 (file)
@@ -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;
+}
index 1ec8f9178aaf48e41cde86c1c534d76f51283422..73be795fe3bfe5dcb04a25fa95c2488910efa20c 100644 (file)
@@ -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);
+
index 03942450885b14a94bf0dfa33e7c757a13544280..001a252bd514379e677edb0d247b8ac542005b28 100644 (file)
  *
  */
 
+#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
 
index 32772bc6925c93e699471c4f0903647d2f8806e4..108b5db9b2af67c3d96ef9810184410332bffda4 100644 (file)
       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)
index bb9e09208b9f48057713608a8a62df476ecbd1ef..4ffdff2d9ff1e188b142816a6f87cd5ee0ffda1c 100644 (file)
@@ -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);
index 9e5d8a8c6424f64a0d3bdead6622373f57a6603e..305452b56e91dfcda49e81c5876c0ed0ca935583 100644 (file)
@@ -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;
 }
 
index 494fc1f032dbc1da8e35842a04ae038caef4181e..9adc7fc4618aacb561ca6fe9a5ab02df5c942086 100644 (file)
@@ -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)
index c5cdb975d590a0eef102d9b7c277082d9661b42f..9b0bc2c9fba05e17de7730b209ad68c2d0638549 100644 (file)
@@ -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
index b4eb24ab5af97811e5a0ca1845607de238210863..8e9243ae0c19d13524a700c3ffea8aa4961665c8 100644 (file)
@@ -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)
index 9839767d0842e5d065524181db75aa075c154798..3e2c05cb6a8733683c57d2935536ee936cc52059 100644 (file)
@@ -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)
 {
index b795b3e24afde40a4a0f24b36e26d1759adfb905..00b9b4dec5eb0850aeda9a373227b190a42e8caf 100644 (file)
@@ -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)
index de39e1f2ede5f1c820f4abe9fa4f9ec07948419b..69b4d060b21c4c32e8e40b45c9dc2171c1b56505 100644 (file)
@@ -65,7 +65,7 @@ static int __iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
        u8 *target;
 
        tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
-       target = (iommu->cmd_buf + tail);
+       target = iommu->cmd_buf + tail;
        memcpy_toio(target, cmd, sizeof(*cmd));
        tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
        head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
index 84a8220a6072c0425b9da95fbb28b5a309cbfda1..a6ef672adbbae01e8da2abb5bf2ae1cb32c091be 100644 (file)
@@ -56,9 +56,22 @@ void __cpuinit validate_pat_support(struct cpuinfo_x86 *c)
 
        switch (c->x86_vendor) {
        case X86_VENDOR_INTEL:
-               if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
+               /*
+                * There is a known erratum on Pentium III and Core Solo
+                * and Core Duo CPUs.
+                * " Page with PAT set to WC while associated MTRR is UC
+                *   may consolidate to UC "
+                * Because of this erratum, it is better to stick with
+                * setting WC in MTRR rather than using PAT on these CPUs.
+                *
+                * Enable PAT WC only on P4, Core 2 or later CPUs.
+                */
+               if (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 15))
                        return;
-               break;
+
+               pat_disable("PAT WC disabled due to known CPU erratum.");
+               return;
+
        case X86_VENDOR_AMD:
        case X86_VENDOR_CENTAUR:
        case X86_VENDOR_TRANSMETA:
index 3fd7a67bb06aa7db7f9350e2a34203cb94c3240a..e710a21bb6e8dc0dd9d83a7bd49df69135cbcf7b 100644 (file)
@@ -134,23 +134,6 @@ static void __cpuinit set_cx86_memwb(void)
        setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14);
 }
 
-static void __cpuinit set_cx86_inc(void)
-{
-       unsigned char ccr3;
-
-       printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
-
-       ccr3 = getCx86(CX86_CCR3);
-       setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
-       /* PCR1 -- Performance Control */
-       /* Incrementor on, whatever that is */
-       setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
-       /* PCR0 -- Performance Control */
-       /* Incrementor Margin 10 */
-       setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
-       setCx86(CX86_CCR3, ccr3);       /* disable MAPEN */
-}
-
 /*
  *     Configure later MediaGX and/or Geode processor.
  */
@@ -174,7 +157,6 @@ static void __cpuinit geode_configure(void)
 
        set_cx86_memwb();
        set_cx86_reorder();
-       set_cx86_inc();
 
        local_irq_restore(flags);
 }
index 509bd3d9eacd28da737ade7a365f1a17acf71a11..cb7d3b6a80eb879670bd8a74864d01b587561dec 100644 (file)
@@ -379,6 +379,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
                             unsigned long *size, mtrr_type *type)
 {
        unsigned int mask_lo, mask_hi, base_lo, base_hi;
+       unsigned int tmp, hi;
 
        rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
        if ((mask_lo & 0x800) == 0) {
@@ -392,8 +393,23 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
        rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
 
        /* Work out the shifted address mask. */
-       mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT)
-           | mask_lo >> PAGE_SHIFT;
+       tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
+       mask_lo = size_or_mask | tmp;
+       /* Expand tmp with high bits to all 1s*/
+       hi = fls(tmp);
+       if (hi > 0) {
+               tmp |= ~((1<<(hi - 1)) - 1);
+
+               if (tmp != mask_lo) {
+                       static int once = 1;
+
+                       if (once) {
+                               printk(KERN_INFO "mtrr: your BIOS has set up an incorrect mask, fixing it up.\n");
+                               once = 0;
+                       }
+                       mask_lo = tmp;
+               }
+       }
 
        /* This works correctly if size is a power of two, i.e. a
           contiguous range. */
index 6f23969c8fafe4f1dd2b4304a910c11483833f2d..b117d7f8a5640fe51091f46247671dff5d61524e 100644 (file)
@@ -1496,11 +1496,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
 
        /* kvm/qemu doesn't have mtrr set right, don't trim them all */
        if (!highest_pfn) {
-               if (!kvm_para_available()) {
-                       printk(KERN_WARNING
+               WARN(!kvm_para_available(), KERN_WARNING
                                "WARNING: strange, CPU MTRRs all blank?\n");
-                       WARN_ON(1);
-               }
                return 0;
        }
 
index 2d7e307c7779c98ea412b67faa1b1dbddc7303f6..bfa837cb16be83799fa1ee7e28bedca5dbe38e40 100644 (file)
@@ -293,7 +293,9 @@ static __init void uv_rtc_init(void)
                sn_rtc_cycles_per_second = ticks_per_sec;
 }
 
-static __init void uv_system_init(void)
+static bool uv_system_inited;
+
+void __init uv_system_init(void)
 {
        union uvh_si_addr_map_config_u m_n_config;
        union uvh_node_id_u node_id;
@@ -383,6 +385,7 @@ static __init void uv_system_init(void)
        map_mmr_high(max_pnode);
        map_config_high(max_pnode);
        map_mmioh_high(max_pnode);
+       uv_system_inited = true;
 }
 
 /*
@@ -391,8 +394,7 @@ static __init void uv_system_init(void)
  */
 void __cpuinit uv_cpu_init(void)
 {
-       if (!uv_node_to_blade)
-               uv_system_init();
+       BUG_ON(!uv_system_inited);
 
        uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
 
index b8c45610b20a89a6f52f9b266d68de042d688168..eecc8c18f01016a502edf711df6e9ebff61dde8f 100644 (file)
@@ -73,7 +73,7 @@ static void __init smp_dump_qct(void)
 }
 
 
-void __init numaq_tsc_disable(void)
+void __cpuinit numaq_tsc_disable(void)
 {
        if (!found_numaq)
                return;
index 94da4d52d798e8490f21c59c777df72d6bba86d5..300da17e61cbef997d527031a49bb1e81addf897 100644 (file)
@@ -471,7 +471,7 @@ struct pv_lock_ops pv_lock_ops = {
        .spin_unlock = __ticket_spin_unlock,
 #endif
 };
-EXPORT_SYMBOL_GPL(pv_lock_ops);
+EXPORT_SYMBOL(pv_lock_ops);
 
 EXPORT_SYMBOL_GPL(pv_time_ops);
 EXPORT_SYMBOL    (pv_cpu_ops);
index 218d783ed7a8969bae11bd86750a8121e8030fdd..dcdac6c826e98047138f1e915e2d6b6ffbaf5ddd 100644 (file)
@@ -343,9 +343,8 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
        /* were we called with bad_dma_address? */
        badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE);
        if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) {
-               printk(KERN_ERR "Calgary: driver tried unmapping bad DMA "
+               WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
                       "address 0x%Lx\n", dma_addr);
-               WARN_ON(1);
                return;
        }
 
@@ -1269,13 +1268,15 @@ static inline int __init determine_tce_table_size(u64 ram)
 static int __init build_detail_arrays(void)
 {
        unsigned long ptr;
-       int i, scal_detail_size, rio_detail_size;
+       unsigned numnodes, i;
+       int scal_detail_size, rio_detail_size;
 
-       if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
+       numnodes = rio_table_hdr->num_scal_dev;
+       if (numnodes > MAX_NUMNODES){
                printk(KERN_WARNING
                        "Calgary: MAX_NUMNODES too low! Defined as %d, "
                        "but system has %d nodes.\n",
-                       MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+                       MAX_NUMNODES, numnodes);
                return -ENODEV;
        }
 
@@ -1296,8 +1297,7 @@ static int __init build_detail_arrays(void)
        }
 
        ptr = ((unsigned long)rio_table_hdr) + 3;
-       for (i = 0; i < rio_table_hdr->num_scal_dev;
-                   i++, ptr += scal_detail_size)
+       for (i = 0; i < numnodes; i++, ptr += scal_detail_size)
                scal_devs[i] = (struct scal_detail *)ptr;
 
        for (i = 0; i < rio_table_hdr->num_rio_dev;
index a4656adab53b356d36d787b9c2067af703ff0b36..362d4e7f2d389b81e345fa27b13db78e80c5980a 100644 (file)
@@ -604,14 +604,6 @@ void __init setup_arch(char **cmdline_p)
        early_cpu_init();
        early_ioremap_init();
 
-#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
-       /*
-        * Must be before kernel pagetables are setup
-        * or fixmap area is touched.
-        */
-       vmi_init();
-#endif
-
        ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
        screen_info = boot_params.screen_info;
        edid_info = boot_params.edid_info;
@@ -678,6 +670,14 @@ void __init setup_arch(char **cmdline_p)
 
        parse_early_param();
 
+#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
+       /*
+        * Must be before kernel pagetables are setup
+        * or fixmap area is touched.
+        */
+       vmi_init();
+#endif
+
        /* after early param, so could get panic from serial */
        reserve_early_setup_data();
 
index e139e617f422a932238393b7c5d180f289cd268e..7985c5b3f9162ba14c0817ce25f1297b34a87a5c 100644 (file)
@@ -1221,6 +1221,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
        printk(KERN_INFO "CPU%d: ", 0);
        print_cpu_info(&cpu_data(0));
        setup_boot_clock();
+
+       if (is_uv_system())
+               uv_system_init();
 out:
        preempt_enable();
 }
index d0fbb7712ab05d5ae0359c0b10db4287db742d9f..8b8c0d6640fa9ba9ca7da73fac2cb4ee52e7be26 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/genapic.h>
 #include <asm/idle.h>
 #include <asm/tsc.h>
+#include <asm/irq_vectors.h>
 
 #include <mach_apic.h>
 
@@ -783,7 +784,7 @@ static int __init uv_bau_init(void)
                uv_init_blade(blade, node, cur_cpu);
                cur_cpu += uv_blade_nr_possible_cpus(blade);
        }
-       set_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
+       alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
        uv_enable_timeouts();
 
        return 0;
index 0577825cf89bad5ecdac456fa13d12f4b8e2fa0e..9ffb01c31c40a8c9083e9949d065a442a62f46b7 100644 (file)
@@ -88,11 +88,9 @@ static __cpuinit void check_tsc_warp(void)
                        __raw_spin_unlock(&sync_lock);
                }
        }
-       if (!(now-start)) {
-               printk("Warning: zero tsc calibration delta: %Ld [max: %Ld]\n",
+       WARN(!(now-start),
+               "Warning: zero tsc calibration delta: %Ld [max: %Ld]\n",
                        now-start, end-start);
-               WARN_ON(1);
-       }
 }
 
 /*
index a87ea0e4b3dca3e7149aa03321af508cc1216b0d..d3746efb060d1602a9de63d3be955522f0cd2a5d 100644 (file)
@@ -241,7 +241,7 @@ static unsigned long __initdata table_start;
 static unsigned long __meminitdata table_end;
 static unsigned long __meminitdata table_top;
 
-static __meminit void *alloc_low_page(unsigned long *phys)
+static __ref void *alloc_low_page(unsigned long *phys)
 {
        unsigned long pfn = table_end++;
        void *adr;
@@ -262,7 +262,7 @@ static __meminit void *alloc_low_page(unsigned long *phys)
        return adr;
 }
 
-static __meminit void unmap_low_page(void *adr)
+static __ref void unmap_low_page(void *adr)
 {
        if (after_bootmem)
                return;
@@ -336,9 +336,12 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                }
 
                if (pmd_val(*pmd)) {
-                       if (!pmd_large(*pmd))
+                       if (!pmd_large(*pmd)) {
+                               spin_lock(&init_mm.page_table_lock);
                                last_map_addr = phys_pte_update(pmd, address,
-                                                                end);
+                                                               end);
+                               spin_unlock(&init_mm.page_table_lock);
+                       }
                        /* Count entries we're using from level2_ident_pgt */
                        if (start == 0)
                                pages++;
@@ -347,8 +350,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
 
                if (page_size_mask & (1<<PG_LEVEL_2M)) {
                        pages++;
+                       spin_lock(&init_mm.page_table_lock);
                        set_pte((pte_t *)pmd,
                                pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
+                       spin_unlock(&init_mm.page_table_lock);
                        last_map_addr = (address & PMD_MASK) + PMD_SIZE;
                        continue;
                }
@@ -357,7 +362,9 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                last_map_addr = phys_pte_init(pte, address, end);
                unmap_low_page(pte);
 
+               spin_lock(&init_mm.page_table_lock);
                pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
+               spin_unlock(&init_mm.page_table_lock);
        }
        update_page_count(PG_LEVEL_2M, pages);
        return last_map_addr;
@@ -370,9 +377,7 @@ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
        pmd_t *pmd = pmd_offset(pud, 0);
        unsigned long last_map_addr;
 
-       spin_lock(&init_mm.page_table_lock);
        last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask);
-       spin_unlock(&init_mm.page_table_lock);
        __flush_tlb_all();
        return last_map_addr;
 }
@@ -408,20 +413,21 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
 
                if (page_size_mask & (1<<PG_LEVEL_1G)) {
                        pages++;
+                       spin_lock(&init_mm.page_table_lock);
                        set_pte((pte_t *)pud,
                                pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
+                       spin_unlock(&init_mm.page_table_lock);
                        last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
                        continue;
                }
 
                pmd = alloc_low_page(&pmd_phys);
-
-               spin_lock(&init_mm.page_table_lock);
                last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask);
                unmap_low_page(pmd);
+
+               spin_lock(&init_mm.page_table_lock);
                pud_populate(&init_mm, pud, __va(pmd_phys));
                spin_unlock(&init_mm.page_table_lock);
-
        }
        __flush_tlb_all();
        update_page_count(PG_LEVEL_1G, pages);
@@ -513,16 +519,14 @@ static unsigned long __init kernel_physical_mapping_init(unsigned long start,
                        continue;
                }
 
-               if (after_bootmem)
-                       pud = pud_offset(pgd, start & PGDIR_MASK);
-               else
-                       pud = alloc_low_page(&pud_phys);
-
+               pud = alloc_low_page(&pud_phys);
                last_map_addr = phys_pud_init(pud, __pa(start), __pa(next),
                                                 page_size_mask);
                unmap_low_page(pud);
-               pgd_populate(&init_mm, pgd_offset_k(start),
-                            __va(pud_phys));
+
+               spin_lock(&init_mm.page_table_lock);
+               pgd_populate(&init_mm, pgd, __va(pud_phys));
+               spin_unlock(&init_mm.page_table_lock);
        }
 
        return last_map_addr;
index 6ba6f889c79da6f7c0370df17ef529cf5dd16a93..d4b6e6a29ae3597c45071805f734a502a12d6ab2 100644 (file)
@@ -553,13 +553,11 @@ static int __init check_early_ioremap_leak(void)
 {
        if (!early_ioremap_nested)
                return 0;
-
-       printk(KERN_WARNING
+       WARN(1, KERN_WARNING
               "Debug warning: early ioremap leak of %d areas detected.\n",
-              early_ioremap_nested);
+               early_ioremap_nested);
        printk(KERN_WARNING
-              "please boot with early_ioremap_debug and report the dmesg.\n");
-       WARN_ON(1);
+               "please boot with early_ioremap_debug and report the dmesg.\n");
 
        return 1;
 }
index e7397e108beb2d55c192eee9413a28468ac66fb6..635b50e85581de29bc4a9d32ffbd82da6612838c 100644 (file)
@@ -430,7 +430,9 @@ static void enter_uniprocessor(void)
                                                "may miss events.\n");
 }
 
-static void leave_uniprocessor(void)
+/* __ref because leave_uniprocessor calls cpu_up which is __cpuinit,
+   but this whole function is ifdefed CONFIG_HOTPLUG_CPU */
+static void __ref leave_uniprocessor(void)
 {
        int cpu;
        int err;
index f5f5154ea11e4b788d98a9a12e4d23ddd28e4525..43e2f8483e4f59c33559263c0011e1e5bf041f9d 100644 (file)
@@ -849,7 +849,7 @@ int set_memory_uc(unsigned long addr, int numpages)
        /*
         * for now UC MINUS. see comments in ioremap_nocache()
         */
-       if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
+       if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
                            _PAGE_CACHE_UC_MINUS, NULL))
                return -EINVAL;
 
@@ -868,7 +868,7 @@ int set_memory_wc(unsigned long addr, int numpages)
        if (!pat_enabled)
                return set_memory_uc(addr, numpages);
 
-       if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
+       if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
                _PAGE_CACHE_WC, NULL))
                return -EINVAL;
 
@@ -884,7 +884,7 @@ int _set_memory_wb(unsigned long addr, int numpages)
 
 int set_memory_wb(unsigned long addr, int numpages)
 {
-       free_memtype(addr, addr + numpages * PAGE_SIZE);
+       free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
 
        return _set_memory_wb(addr, numpages);
 }
index 2fe30916d4b66aba6ea1121a9d5bfadb60f1c82f..2a50e0fa64a53290726e9eb1d1b4252afcce1fc8 100644 (file)
@@ -207,6 +207,9 @@ static int chk_conflict(struct memtype *new, struct memtype *entry,
        return -EBUSY;
 }
 
+static struct memtype *cached_entry;
+static u64 cached_start;
+
 /*
  * req_type typically has one of the:
  * - _PAGE_CACHE_WB
@@ -280,11 +283,17 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
 
        spin_lock(&memtype_lock);
 
+       if (cached_entry && start >= cached_start)
+               entry = cached_entry;
+       else
+               entry = list_entry(&memtype_list, struct memtype, nd);
+
        /* Search for existing mapping that overlaps the current range */
        where = NULL;
-       list_for_each_entry(entry, &memtype_list, nd) {
+       list_for_each_entry_continue(entry, &memtype_list, nd) {
                if (end <= entry->start) {
                        where = entry->nd.prev;
+                       cached_entry = list_entry(where, struct memtype, nd);
                        break;
                } else if (start <= entry->start) { /* end > entry->start */
                        err = chk_conflict(new, entry, new_type);
@@ -292,6 +301,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                                dprintk("Overlap at 0x%Lx-0x%Lx\n",
                                        entry->start, entry->end);
                                where = entry->nd.prev;
+                               cached_entry = list_entry(where,
+                                                       struct memtype, nd);
                        }
                        break;
                } else if (start < entry->end) { /* start > entry->start */
@@ -299,7 +310,20 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                        if (!err) {
                                dprintk("Overlap at 0x%Lx-0x%Lx\n",
                                        entry->start, entry->end);
-                               where = &entry->nd;
+                               cached_entry = list_entry(entry->nd.prev,
+                                                       struct memtype, nd);
+
+                               /*
+                                * Move to right position in the linked
+                                * list to add this new entry
+                                */
+                               list_for_each_entry_continue(entry,
+                                                       &memtype_list, nd) {
+                                       if (start <= entry->start) {
+                                               where = entry->nd.prev;
+                                               break;
+                                       }
+                               }
                        }
                        break;
                }
@@ -314,6 +338,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                return err;
        }
 
+       cached_start = start;
+
        if (where)
                list_add(&new->nd, where);
        else
@@ -343,6 +369,9 @@ int free_memtype(u64 start, u64 end)
        spin_lock(&memtype_lock);
        list_for_each_entry(entry, &memtype_list, nd) {
                if (entry->start == start && entry->end == end) {
+                       if (cached_entry == entry || cached_start == start)
+                               cached_entry = NULL;
+
                        list_del(&entry->nd);
                        kfree(entry);
                        err = 0;
@@ -361,14 +390,6 @@ int free_memtype(u64 start, u64 end)
 }
 
 
-/*
- * /dev/mem mmap interface. The memtype used for mapping varies:
- * - Use UC for mappings with O_SYNC flag
- * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
- *   inherit the memtype from existing mapping.
- * - Else use UC_MINUS memtype (for backward compatibility with existing
- *   X drivers.
- */
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                unsigned long size, pgprot_t vma_prot)
 {
@@ -406,14 +427,14 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
                                unsigned long size, pgprot_t *vma_prot)
 {
        u64 offset = ((u64) pfn) << PAGE_SHIFT;
-       unsigned long flags = _PAGE_CACHE_UC_MINUS;
+       unsigned long flags = -1;
        int retval;
 
        if (!range_is_allowed(pfn, size))
                return 0;
 
        if (file->f_flags & O_SYNC) {
-               flags = _PAGE_CACHE_UC;
+               flags = _PAGE_CACHE_UC_MINUS;
        }
 
 #ifdef CONFIG_X86_32
@@ -436,13 +457,14 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
 #endif
 
        /*
-        * With O_SYNC, we can only take UC mapping. Fail if we cannot.
+        * With O_SYNC, we can only take UC_MINUS mapping. Fail if we cannot.
+        *
         * Without O_SYNC, we want to get
         * - WB for WB-able memory and no other conflicting mappings
         * - UC_MINUS for non-WB-able memory with no other conflicting mappings
         * - Inherit from confliting mappings otherwise
         */
-       if (flags != _PAGE_CACHE_UC_MINUS) {
+       if (flags != -1) {
                retval = reserve_memtype(offset, offset + size, flags, NULL);
        } else {
                retval = reserve_memtype(offset, offset + size, -1, &flags);
index 3f90289410e6fbfc81fa1b350f7d6fdce4ecd18c..0227694f7dab9b156350eaef0e90f79e8ec2ecc4 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <linux/kdebug.h>
+#include <linux/cpu.h>
 #include <asm/nmi.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
@@ -28,23 +29,48 @@ static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
 
 static int nmi_start(void);
 static void nmi_stop(void);
+static void nmi_cpu_start(void *dummy);
+static void nmi_cpu_stop(void *dummy);
 
 /* 0 == registered but off, 1 == registered and on */
 static int nmi_enabled = 0;
 
+#ifdef CONFIG_SMP
+static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
+                                void *data)
+{
+       int cpu = (unsigned long)data;
+       switch (action) {
+       case CPU_DOWN_FAILED:
+       case CPU_ONLINE:
+               smp_call_function_single(cpu, nmi_cpu_start, NULL, 0);
+               break;
+       case CPU_DOWN_PREPARE:
+               smp_call_function_single(cpu, nmi_cpu_stop, NULL, 1);
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block oprofile_cpu_nb = {
+       .notifier_call = oprofile_cpu_notifier
+};
+#endif
+
 #ifdef CONFIG_PM
 
 static int nmi_suspend(struct sys_device *dev, pm_message_t state)
 {
+       /* Only one CPU left, just stop that one */
        if (nmi_enabled == 1)
-               nmi_stop();
+               nmi_cpu_stop(NULL);
        return 0;
 }
 
 static int nmi_resume(struct sys_device *dev)
 {
        if (nmi_enabled == 1)
-               nmi_start();
+               nmi_cpu_start(NULL);
        return 0;
 }
 
@@ -463,6 +489,9 @@ int __init op_nmi_init(struct oprofile_operations *ops)
        }
 
        init_sysfs();
+#ifdef CONFIG_SMP
+       register_cpu_notifier(&oprofile_cpu_nb);
+#endif
        using_nmi = 1;
        ops->create_files = nmi_create_files;
        ops->setup = nmi_setup;
@@ -476,6 +505,10 @@ int __init op_nmi_init(struct oprofile_operations *ops)
 
 void op_nmi_exit(void)
 {
-       if (using_nmi)
+       if (using_nmi) {
                exit_sysfs();
+#ifdef CONFIG_SMP
+               unregister_cpu_notifier(&oprofile_cpu_nb);
+#endif
+       }
 }
index c13cc77291af7d1c26378051f7fa1b9770d0f81d..656c2c7abf999628e1232024b71c4af2f22a1ac9 100644 (file)
@@ -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;
index ef3e5522e1a4a41979ff5ec56b72ed860d004275..c729e6988bbb17db928de1cd903682cfc3dc2802 100644 (file)
@@ -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 */
index c294121fd69e71e68e84a328c8d8ed63f6e7a65e..b1d08a8f50030da3bb5d6a74726b5a72fdffe24b 100644 (file)
@@ -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 */
 };
index 5ba96c5052c8c737bf8e07d8968affb334636ccd..79e3a8e7a84a36de25dea2bcb7161b7bcdcc6fd5 100644 (file)
@@ -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;
index 58bdc538d229d400b78fd2c0a46317c1a84d943c..c1db2f234d2e409d21851c91c77a292cc631406e 100644 (file)
@@ -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 "
index fbe605711554a24dd1ae23be66d02128c8193b18..eb919c16a03e67f25042da2756f274821b549ee8 100644 (file)
@@ -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;
        }
index d7de7baf58a8ccb8551a8685167410b60ddf031d..e8a0d99d7356baaf0afba8c9c348ff5adb45b828 100644 (file)
@@ -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);
index 744beebaaf494f17603b3750036da58cc0242cdf..0c4b271a9d5a372c07a80ded36566b40e831bcb5 100644 (file)
@@ -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);
        }
index 27843c70eb9dc64e8d6292e2dc7fe2ee425bae40..0221c9a46769ad5e826485691d2718f863795eeb 100644 (file)
@@ -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)";
 
index e678af383d13283dc578c875580cead05c37623c..df64f24430018674f527bfe1bb26d49a73b3ea05 100644 (file)
@@ -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);
index cbab397e3db7a1cc5893d40de3d99d524d563383..0278fd2b8fb1cc8c80ba05bc1e638027a22d3a95 100644 (file)
@@ -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);
        }
index 57d951b11f2d840c18d92f7ed180ef7a240a386d..8fdb2ce73210b885393dc6ec066d5f3c69185646 100644 (file)
@@ -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,
 };
 
 /**
index ad169ffbc4cb2a0ad8387c478b6a9540992f99b6..13c1d2af18ac3e0ff02ef35b926df40955ac3006 100644 (file)
@@ -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:
index 5667c2f02c51b2249fdac0d69fc7fd0a8fe4dfd0..cc5e28c8885ce1b78d2b0453e9068c8abf0dde64 100644 (file)
@@ -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) {
index 068aa1c9538c99d54a47603e25f69544f084f537..d021c98605b3a1fe7e7dcd5f61e9e456b2a16aae 100644 (file)
@@ -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)) {
index 2ef5acf4368b9e8deef4440d865a87cef8d0b0a6..1e2bda780e48268eb38b834f7078644689b5dc7b 100644 (file)
@@ -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);
index 3250c5257b748286cfec992558a7590f0ab915e9..273a944d4040e861afa6a1ea6c601264eec6c4a7 100644 (file)
@@ -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);
 }
index a3252c0e28878fde258ebac8c10ad7c10cafbb86..41f51fae042f06f06d7548f4ad10463b7b399f4f 100644 (file)
@@ -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
index 24b97b0bef994411bda31e377c041da6471ed9a2..d070d492e385b26893e34d514cbda0fa6cb5e34f 100644 (file)
@@ -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;
 }
 
index ad98dda6037dd5193baa266bf2471c52ca1b6f79..1778e4a2c672be69ce18e6a8c64e2356ceca5b92 100644 (file)
@@ -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);
 }
 
index f52931e1c16eb08d0d353a92836a6fdfe0060268..8e8afb6141f99edc8f3a38bbcad1e1b9e802961f 100644 (file)
@@ -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;
 
index d90f5e9a54faf8b16c790eab5a7af4ade2a022af..9839e20119bcfc64f483f68cf2b18d24e1786f77 100644 (file)
@@ -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);
index 36aa242c487c4d582d39d94b86e53377466455ef..729446f56aab580d2ffcd7200a124d22ea6e7c3e 100644 (file)
@@ -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;
 
index f51201b17bfd3048ddbd66fd4edadb41b310cdb0..7e9e218738fa0f4be74741266e690d7c4211e6e0 100644 (file)
@@ -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);
index 8950e9546f4eb64a33fe4dd2b7c7698382b63e37..ac33c8f3ea8580e5120dd98704cfbccb0ccd5c71 100644 (file)
@@ -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;
        }
index 9e8d79e7e9f4cb4b105840ce71420e435820edd5..facdb9893c84c322dbb65f47e2a7bf8de3c69685 100644 (file)
@@ -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;
 }
 
index 90ab73825401a0b5f4c0b7de15c5ff755a4edb7d..9a9755c92fada3268f03f69ee7270964bf322818 100644 (file)
@@ -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.
index a1af4c27939b446b0de1f43d8d61c7a51b610d21..34439ce3967e1844c552091fb72a0555b904644d 100644 (file)
@@ -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);
index 35dcc06eb3e2dab77b16e27881f2b6bd6250c372..f118252f3a9f2b921cef3fff96fd1ef890d65b3c 100644 (file)
@@ -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;
index 640acd20fdde43c2751f2be4d6d0a63198bf7b7d..a150418fba765d5db942db7bd2ffdb525716367e 100644 (file)
@@ -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);
index 1b6c52ef73391da1aff66cc1aa6bcda8c193ddd8..acb78017e7d0fd2e2988bfed85ec484e527bfcc6 100644 (file)
@@ -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;
 }
index 4bf0aa5112c10c00cc2dfeff42409244539de503..2476f87d21d0027ae61dc08e546abb15b37ec979 100644 (file)
@@ -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));
 
 /*
index 29da4413ad437b789dd78f104f894b396f99e386..bf512ac75b9e640f058cf1d1b8ddbd2d9490134a 100644 (file)
@@ -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;
index 01fcdd91b846533a920cc3076c67bf85ca3816c2..db85f1fb131e0494dfb3e7a4838b23c269d9d36b 100644 (file)
@@ -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);
index 687720b552d1c460019c8aa40a758294538195dd..be0ce2215c8de2d1214dd75d0330b850edc84885 100644 (file)
@@ -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)
index 2a1af4e60be0919226217471beec3b1ea8f2b7b7..cc8fd781ee227ce6e8f1ae38956b2fb002fe5ad6 100644 (file)
@@ -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);
index 26a930e832bdab58c7f649c866124200e1f3f8c8..e0ce65fca4e797ed2da7370093a56f1a86d04c81 100644 (file)
@@ -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);
index 46c021d880dc5ee7441cd11f8e885bf54d79b7dd..51489eff6b0b4484ad234e6b7b7a0819a6d1ddd6 100644 (file)
@@ -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);
 }
 
index e818d0c54c0949f5a21ae134ccf426da5d079d9c..28221030b886cfa5ae8d794fdf176bdbfe401845 100644 (file)
@@ -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);
index 9800a8335a3fa81a195b9c5b3ae83380c21ae5ef..6f5c3f2b3587d8f72d98aa781f9f2cbd6dfd50d3 100644 (file)
@@ -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);
index 8b5fe57fb2f31ef1684d586aca9f69c9c9e4fab3..550508df952b89693f5b13e4de5e5bec2a976ac3 100644 (file)
@@ -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);
 
index 8484b83698e11cf32ca51bedff4088930caa66f6..5a4d85b829adf11884f92cac93f9317b7ad4c064 100644 (file)
 
 /* 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 */
index d15648514a0f6dd9ef8c9db44088f238f8f377c4..e6eabc853422cc9320c7925099471ec04e48f44b 100644 (file)
@@ -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 */
 
index 1bd2a208db28a3d5a649c3d9a9ea04eebb5390e8..1679e2f91c945eb0164b3d8a813207c9cfd5efbd 100644 (file)
@@ -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:
index 9291a771d8123c8cffbb40158322713a1bba33ca..ea7f614002670024f766d887062ff4824029556d 100644 (file)
@@ -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();
        }
index 2e9079df26b3a2ebd67e633295167389d380ae81..4190be64917f416be6f4809929bf0e23b78a755d 100644 (file)
@@ -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
index e00ce0def1a02898d0b197c2c593f8344bb989b7..8667bbdef904fc3ddd2df2d1208938f5fdcc2a7e 100644 (file)
@@ -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
index 5d0d2e85d9820ed70c48b900c262d7ff1c44f393..0b4ef39cd85d289d3aee60264dd6044bee1f0b8b 100644 (file)
@@ -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 (file)
index 0000000..1f82c83
--- /dev/null
@@ -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);
index efc4373ededb4ea1f15a31f8c32716f1333be6a2..c257453fa9dec42ea864b6cbd89dbd6a3cab5781 100644 (file)
@@ -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,
index 2be37fe466f2f56d5d2adfbd94ebd3ec5ba2cd6f..5a7fa6f099584206536c40b21dde9117b79cd5e1 100644 (file)
@@ -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,
 };
index f7bfd72ef115bae2855e05c9b622ff41588477b1..8abd4e59bf4abac0bb2edcee5385894f42310e98 100644 (file)
@@ -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);
-}
-
 
 /*-------------------------------------------------------------------------*/
 
index 5b0b59b0d89b37709da23af08cf0271c193d9ebf..e710ce04e228f94647908d789500a4e2b8a646f9 100644 (file)
@@ -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);
 
index 107e1d25ddec3fbe0a485191131dad985342c8ff..6a5cb018383d538a2b504429183be99e112c6a5b 100644 (file)
@@ -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;
index c0b1ae25ae2a8923cf463bd670f3873acaf87102..47111e88f791ad748956d4cbae7317145cfd8927 100644 (file)
@@ -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);
 
index 84fcaa6a21ec285e85ab309bfc0b4be728f62caa..be1fa0723f2c662a058040e8878e7ffb5c12c3df 100644 (file)
@@ -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)
index d9a6e16dbf842fbb645117eb57093b429ce9c6e0..9a1a45ac3add0ba9ab582d713a6341ee6df311c7 100644 (file)
@@ -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);
index a28513ecbe5bd3de7c675a6a7c9afb99246f63ec..7cbc78a6853d846689b000842cf264466a67dedc 100644 (file)
@@ -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)
index d22a84f86a33755a3749f275cd49e031ee14ac06..8017f1cf78e244b0f37c4a32d2833de3d2d2a586 100644 (file)
@@ -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);
index 6db7a2889e6648f50344d4d42e3a2c04d332a91b..4ed228a899435a91bc1428daa37a9eb54f283b14 100644 (file)
@@ -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,
index c0948008fe3d17c068c47d83b768b2e7fc365bff..2ac4e022a13f6fc68c6ea32702f1bab05713b88a 100644 (file)
@@ -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,
index cb0b506f8259b20237854bfaae4f9b290223b82a..fb3055f084b5f1a89aaf30efe19cd643b9ddef85 100644 (file)
@@ -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,
index 439beb784f3e1eb42495d4a323288a56d5eea02d..7ea9a7b311554199f4e5f97ba060cc853786f2f0 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-/* 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 */
index 9e31d440d115e7e8260476bcd81e39fd80b026e1..de42283149c7154608c30c9b1ceeec29e14b07ba 100644 (file)
@@ -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,
index 3d532b709670c9386959f1a8c84a327875790d10..1eb64d08b60a9591bd994f757c0372602b7c7ef4 100644 (file)
@@ -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,
index 083e8df0a817f83b925ac397f5e90cb43b8af1d2..a9c2ae36c7ad5ce6bf9585fc9b8e418ad10751ba 100644 (file)
@@ -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,
index b02cd0761977aed3bf6c85eda07227a6bfe8d4c1..658a2a978c32139bcf98181e9cd5fa4466f214b0 100644 (file)
@@ -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,
index 605d59cba28e79d46bbbb3215cfc9ccd1b6f6a5b..28467e288a93d54607c7cb244e1e904dc6136395 100644 (file)
@@ -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,
index 91e6e101a4cc987feae9591a4926f6a35aef95a0..7ac53264ead369b1beb9c140cd50e131a019ea40 100644 (file)
@@ -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,
index 523c30125577d39a8c24287ce30ae2b2532929e2..cd3398b675b2dea8c2402fd2178cee58c23a52e4 100644 (file)
@@ -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,
index 55c95647f008d7eec7eb6991a6a5f19212f4fd59..2089d8a46c4bbedb0cd140dc5db4d0cee4cab908 100644 (file)
@@ -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,
index 8c9c4849db6efc5fedfec17201622f60a6df9174..7f0f35c781858628a995dc85df361c6cae56b264 100644 (file)
@@ -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,
index 9e3dc4069e8bc9cb4dac244f1b8dfa5f276ff9ac..f46af7a718d416a548b565c142ccf8d229c1505f 100644 (file)
@@ -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,
index 4626b002e670f15a5a93a1f8cf1c80edf12480b9..e4bbe8e188e4653355426294e511e92588085b9a 100644 (file)
@@ -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,
index e7ee607278fece8b92570beb5b839e74ca8aa2db..60f03cc7ec4f20a4f80d228b59faebe715ae1148 100644 (file)
@@ -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,
index 21b164e4abebf8bc71d12611b4356bb97e038718..cff23637cfcc5e6cd5322d8faddd866f885b9e27 100644 (file)
@@ -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,
index 3660c83d80af44b269bfa9c32311846db1878105..23fd6a886bddb0f25d2279d3da8d11c66e5e61ad 100644 (file)
@@ -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,
index 20ad3c48fcb2966fb20e2bc36fc49971b239110b..228f2b070f2b7d558e33271827cccb3588794ebd 100644 (file)
@@ -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,
 };
 
 /*
index fbace41a7cba4418dc8602f70eae8614b0db33c7..69c34a58e2054a7c49d225164a3f1a7ead20cf5a 100644 (file)
@@ -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) },
        { }
index faca4333f27a8125a46fcbb7d32362ac56fc3524..a0017486ad4ea27f6220764ede93cb3562e59247 100644 (file)
@@ -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.
index 88eb67de08aeed097a0285026e1a08a30fec77aa..b6af0d687a73657b27fc87fd8c57153fc7f2021d 100644 (file)
@@ -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)
index d68ec6daf3350676cee67df8ed9426b724b0fa35..c5b8f0296fcf2f9f9a7ab40404d1f8324e325508 100644 (file)
 
 
 
-#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));
index eade46d817084813616c13a3a60f6951b5bd9602..82227251931b4c8c512f5d66babe9fec3fbafff2 100644 (file)
@@ -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__ */
index 3bdb311e820d454ee4e801a05247c5464ef1a839..4d2794441b153ac6c2f745b99f06c245cb56bbe5 100644 (file)
                                __func__, __LINE__ , ## args); \
        } } while (0)
 
-#if MUSB_DEBUG > 0
 extern unsigned debug;
-#else
-#define debug  0
-#endif
 
 static inline int _dbg_level(unsigned l)
 {
index 48d7d3ccb2438ecd4d70c2f317dc485ef960b72d..a57652fff39cac614b399e089fa76c8c32f38dd8 100644 (file)
@@ -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 (file)
index 55e6b78..0000000
+++ /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;
-}
index e143198aeb028e0bec63189cf8d4ace46e778a70..9f9cd36455f463423e4cbe22fd752e639415580b 100644 (file)
@@ -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) },
index 940467aed13f27864849db15ba36b70e4ad2b846..6d5aa806777e0826b187e8786ee7633d425b83f4 100644 (file)
@@ -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;
 }
index 59df132cc3756deda96bfcce5d453a309e803a15..4835bdc4e9f1819615ab2454549f9a637d01a0e1 100644 (file)
@@ -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;
index 6b487801eeaedc96e8b65a330363156e32452f6c..98843c2ecf733a17e0742109fa63009d47c9b405 100644 (file)
@@ -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;
index 3f1ca2adda3d7353fe41529bb9fa59c1085affa3..c6dd924976a4f105457bd15c205a2938a07eeee3 100644 (file)
@@ -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);
 }
index 756205314c24401fc31ebbb6eb7c479aa4c92145..8d7e88e02e0f9cc13207d86ee090a2594f79497b 100644 (file)
@@ -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;
index 0c3b618c15b3f05bd1adee50fada78b7561a36dc..f40423eb1a14e66b73693f5505a54f00b3bd6f4a 100644 (file)
@@ -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,
index 1ae5004e93fc20ffd99a652efa6be9897a0518c1..e9fa960ba6da9fa6cf573fc517d70808e519ab83 100644 (file)
@@ -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;
index d3d23d73c08b5e5e1584f16f88be892e4903ecfa..ec8e33b452198ba9ab7818884a57e27ff8a20509 100644 (file)
@@ -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) {
index 6c7924d9e358caf3c0803dc43d0d26b76dd9b620..295003241d3d7dbb3b4127dcbb7357c2327d0146 100644 (file)
@@ -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,
index 6c166c0a54b7ea24a49a90681e0284dee3d364d6..d33dc56d6986e785ea6e75f9a256cf2191fc6b74 100644 (file)
@@ -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 *);
index eb8bc3afe6e9f590f491bf9098980f39f27bf245..b455c685a98b5cb779654fa22826622899ca6133 100644 (file)
                                         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. */
index 612c3d2c38240ff59a643bcbf405c2229443a848..b24d3c53f20cd20407d5d5373c79b725d308cc45 100644 (file)
@@ -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) {
index 655e760212b871655c2fa55a0e0f1b889476ae77..f344834bbf58a4f0228b5ab85243d8bba1b1d648 100644 (file)
@@ -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))
index 59fbbe899acc24a5817befbc67fda67ba427b3d1..7e91913e325bb511086c5a2ddb0ddeda0bc28e01 100644 (file)
@@ -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,56 +4416,128 @@ 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.
index 865e9ddb44d406d298da48b0137a4f426f8d45dd..e0e3a5eb1ddba0575798cd5d561b23c25409cdb6 100644 (file)
@@ -3281,6 +3281,35 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
        mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa);
 }
 
+/*
+ * 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
  */
@@ -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;
 }
 
index b9e077ba07e94b0c979ebea4530e1fc9471e6eee..46fc0b5b12bab540cf00bb1ffb7fcec1b51854fa 100644 (file)
@@ -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
index 0a9265164265fda4be2aa94c1db1941c3bb0b247..b3d35604ea1890f3b33567658ba9827f4d2c3a98 100644 (file)
@@ -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;
index d5d77958b861b9fc29114965a566a7e2dfdd4a84..566344b926b772bb668ea62e15b3ddc641389a96 100644 (file)
@@ -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);
index c4a1c3c65aac35ba999a4739fb3ed6549b5e1b75..da3cc460d4df4d16f3afb81fea786589948a2c18 100644 (file)
@@ -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)
index 79ecd281d2cbf1e1db1484ffe4b24413bc6f9e63..3f87d2632947371b47df580c32d041fb39bb91ba 100644 (file)
@@ -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) {
index 7546a918f7907612b078c411d8eeb288b099ffc2..73d1891ee6259e41f5be2f1d8d2a16948887097d 100644 (file)
@@ -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);
 
        /*
index b02ea6e17de8b6a097c722f28d2c726f5e39514d..754d635f90ffc9514a1daae0ed560eed9d629cd9 100644 (file)
@@ -118,6 +118,7 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
 #define get_uv_system_type()           UV_NONE
 #define is_uv_system()                 0
 #define uv_wakeup_secondary(a, b)      1
+#define uv_system_init()               do {} while (0)
 
 
 #endif
index 0f8504627c41ce8c6d9f168e8ff038a8d15c3d12..a47d6312913596fbd0a8a77c54ed8b45937a5a90 100644 (file)
@@ -42,6 +42,7 @@ extern int is_uv_system(void);
 extern struct genapic apic_x2apic_uv_x;
 DECLARE_PER_CPU(int, x2apic_extra_bits);
 extern void uv_cpu_init(void);
+extern void uv_system_init(void);
 extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip);
 
 extern void setup_apic_routing(void);
index b95d167b7fb26d8697a1d1a56b2000648b042e8b..a48c7f2dbdc04b32f010fbc6267b7a479f37e578 100644 (file)
@@ -76,6 +76,7 @@
 #define CALL_FUNCTION_SINGLE_VECTOR    0xfb
 #define THERMAL_APIC_VECTOR            0xfa
 #define THRESHOLD_APIC_VECTOR          0xf9
+#define UV_BAU_MESSAGE                 0xf8
 #define INVALIDATE_TLB_VECTOR_END      0xf7
 #define INVALIDATE_TLB_VECTOR_START    0xf0    /* f0-f7 used for TLB flush */
 
index 91ac0dfb758805b052bba15f63796243fc4b9fab..610b6b308e93a005ff98753ea3d8586b131202ab 100644 (file)
 #define UV_ACTIVATION_DESCRIPTOR_SIZE  32
 #define UV_DISTRIBUTION_SIZE           256
 #define UV_SW_ACK_NPENDING             8
-#define UV_BAU_MESSAGE                 200
-/*
- * Messaging irq; see irq_64.h and include/asm-x86/hw_irq_64.h
- * To be dynamically allocated in the future
- */
 #define UV_NET_ENDPOINT_INTD           0x38
 #define UV_DESC_BASE_PNODE_SHIFT       49
 #define UV_PAYLOADQ_PNODE_SHIFT                49
index d24a47f80f9c67587df13a5a8b57282f7dd2e8dd..4d8372d135df8df6d4f648b009faaa5d4d315538 100644 (file)
@@ -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)
index 3b8870e32afdd14b8166dd876762c0986cafd4ab..531ccd5f5960b0fe5818fdb768d3beb6bd3f3ea7 100644 (file)
@@ -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);
index 06b80337303b805bffcc2920b0d8796004f902ef..225bfc5bd9ec1eb43b143d059f926918a30c2656 100644 (file)
@@ -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
index 22921ac4cfd948b88e10a06c0725b33363b38caf..d7e98ff8021eb3bfc38e4c851b425c7eac5c097f 100644 (file)
@@ -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 */
index 69407f85e10b32daa4bd8ac82f88d43e36b82f78..fed6f5e0b41139070dd9c99b84ee324e7254f63f 100644 (file)
@@ -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.
index d3c02695dc5d7e0826a7fa6ac4eb27bfbd937374..8cf8cfe2cc9712a176d7d4904107f4d30e74293f 100644 (file)
@@ -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);
index 0924cd9c30f66feae597186d2b08d67155f008ad..94ac74aba6b6644dcd70f5015082facd90824195 100644 (file)
@@ -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 */
index f14f372cf6f5e0706e1ba94490c6c57a1aaf6d41..467d5940f62406c35ab64fb7c4c88b1556154fa0 100644 (file)
@@ -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);
 
index 862b06bd560aa58df2c95b0143b7331b8db113e7..9353ca78154e880c786376108d2ef1be4335cde4 100644 (file)
@@ -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)
index 3dacb00a7f765977c92d896ca4556f93ff87616b..038a7bc0901d20f90f841c5e4326fc1f2f2b963f 100644 (file)
@@ -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;
index f5da526424a9b7c5dcaf965cbf00a49f09642eb0..7a46bde78c66f77e15ba75f8e570e4c46de274de 100644 (file)
@@ -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
index bd732ffebc85f36cfc30e70fa124f0566701ecba..fbf0ae28237672a6fafdbbf29e481d76c45ddd11 100644 (file)
@@ -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);
index e023c68b025555b6110e8d6352f9ad19e5c7f7f7..ad8eec6e44a85a9593c781ce252b127cb96992cd 100644 (file)
@@ -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;
        }
index 380ab402d71160a05d82a00598e5e35efeb5f116..b5167dfb2f2d65366004963558dfa765643423b8 100644 (file)
@@ -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>
 
  * 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);
index 936ef2efd892029b1abf1c08c860fd40991d213d..4e0e26591dfaa6f242c4514fd83bdb54f7194b43 100644 (file)
@@ -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
index 1ea4e6fcee77986f673d578a42bece82a92fb81e..0383acfcb0681a877f15f59d4d712980c37e1811 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -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;
 
index 167cf2dc8a03c16d3022c60a303b102f09732bdd..797c3831cbec7401ccfecd3ecdc98c7667c8d6bb 100644 (file)
@@ -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));
 }
 
index 4fa1f3ad251340833a3b5d4b094dbc0c05557068..4c9890ec252875500c6c35d388fdd44af9545f34 100644 (file)
@@ -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 */
index a73d6ca0a90655104c48b7ea50b4089815de5b70..1c53e337ecb2dce93b833dcce526f64288cc9136 100644 (file)
@@ -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);
index b80e725432f047aaa9ab7b3016b27454bdc2daae..909f1c101c95af5e0a1c2db614a946de1cd570be 100644 (file)
@@ -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)