Merge branch 'akpm' (patches from Andrew Morton)

Merge first patch-bomb from Andrew Morton:
 - Some pidns/fork/exec tweaks
 - OCFS2 updates
 - Most of MM - there remain quite a few memcg parts which depend on
   pending core cgroups changes.  Which might have been already merged -
   I'll check tomorrow...
 - Various misc stuff all over the place
 - A few block bits which I never got around to sending to Jens -
   relatively minor things.
 - MAINTAINERS maintenance
 - A small number of lib/ updates
 - checkpatch updates
 - epoll
 - firmware/dmi-scan
 - Some kprobes work for S390
 - drivers/rtc updates
 - hfsplus feature work
 - vmcore feature work
 - rbtree upgrades
 - AOE updates
 - pktcdvd cleanups
 - PPS
 - memstick
 - w1
 - New "inittmpfs" feature, which does the obvious
 - More IPC work from Davidlohr.

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (303 commits)
  lz4: fix compression/decompression signedness mismatch
  ipc: drop ipc_lock_check
  ipc, shm: drop shm_lock_check
  ipc: drop ipc_lock_by_ptr
  ipc, shm: guard against non-existant vma in shmdt(2)
  ipc: document general ipc locking scheme
  ipc,msg: drop msg_unlock
  ipc: rename ids->rw_mutex
  ipc,shm: shorten critical region for shmat
  ipc,shm: cleanup do_shmat pasta
  ipc,shm: shorten critical region for shmctl
  ipc,shm: make shmctl_nolock lockless
  ipc,shm: introduce shmctl_nolock
  ipc: drop ipcctl_pre_down
  ipc,shm: shorten critical region in shmctl_down
  ipc,shm: introduce lockless functions to obtain the ipc object
  initmpfs: use initramfs if rootfstype= or root= specified
  initmpfs: make rootfs use tmpfs when CONFIG_TMPFS enabled
  initmpfs: move rootfs code from fs/ramfs/ to init/
  initmpfs: move bdi setup from init_rootfs to init_ramfs
  ...
This commit is contained in:
Linus Torvalds 2013-09-11 16:08:54 -07:00
commit c2d95729e3
247 changed files with 8829 additions and 2922 deletions

View File

@ -23,4 +23,4 @@ SUBSYSTEM=="aoe", KERNEL=="revalidate", NAME="etherd/%k", GROUP="disk", MODE="02
SUBSYSTEM=="aoe", KERNEL=="flush", NAME="etherd/%k", GROUP="disk", MODE="0220"
# aoe block devices
KERNEL=="etherd*", NAME="%k", GROUP="disk"
KERNEL=="etherd*", GROUP="disk"

View File

@ -0,0 +1,39 @@
Embedded device command line partition
=====================================================================
Read block device partition table from command line.
The partition used for fixed block device (eMMC) embedded device.
It is no MBR, save storage space. Bootloader can be easily accessed
by absolute address of data on the block device.
Users can easily change the partition.
The format for the command line is just like mtdparts:
blkdevparts=<blkdev-def>[;<blkdev-def>]
<blkdev-def> := <blkdev-id>:<partdef>[,<partdef>]
<partdef> := <size>[@<offset>](part-name)
<blkdev-id>
block device disk name, embedded device used fixed block device,
it's disk name also fixed. such as: mmcblk0, mmcblk1, mmcblk0boot0.
<size>
partition size, in bytes, such as: 512, 1m, 1G.
<offset>
partition start address, in bytes.
(part-name)
partition name, kernel send uevent with "PARTNAME". application can create
a link to block device partition with the name "PARTNAME".
user space application can access partition by partition name.
Example:
eMMC disk name is "mmcblk0" and "mmcblk0boot0"
bootargs:
'blkdevparts=mmcblk0:1G(data0),1G(data1),-;mmcblk0boot0:1m(boot),-(kernel)'
dmesg:
mmcblk0: p1(data0) p2(data1) p3()
mmcblk0boot0: p1(boot) p2(kernel)

View File

@ -0,0 +1,17 @@
MOXA ART real-time clock
Required properties:
- compatible : Should be "moxa,moxart-rtc"
- gpio-rtc-sclk : RTC sclk gpio, with zero flags
- gpio-rtc-data : RTC data gpio, with zero flags
- gpio-rtc-reset : RTC reset gpio, with zero flags
Example:
rtc: rtc {
compatible = "moxa,moxart-rtc";
gpio-rtc-sclk = <&gpio 5 0>;
gpio-rtc-data = <&gpio 6 0>;
gpio-rtc-reset = <&gpio 7 0>;
};

View File

@ -1,7 +1,11 @@
TI Real Time Clock
Required properties:
- compatible: "ti,da830-rtc"
- compatible:
- "ti,da830-rtc" - for RTC IP used similar to that on DA8xx SoC family.
- "ti,am3352-rtc" - for RTC IP used similar to that on AM335x SoC family.
This RTC IP has special WAKE-EN Register to enable
Wakeup generation for event Alarm.
- reg: Address range of rtc register set
- interrupts: rtc timer, alarm interrupts in order
- interrupt-parent: phandle for the interrupt controller

View File

@ -0,0 +1,33 @@
Palmas RTC controller bindings
Required properties:
- compatible:
- "ti,palmas-rtc" for palma series of the RTC controller
- interrupt-parent: Parent interrupt device, must be handle of palmas node.
- interrupts: Interrupt number of RTC submodule on device.
Optional properties:
- ti,backup-battery-chargeable: The Palmas series device like TPS65913 or
TPS80036 supports the backup battery for powering the RTC when main
battery is removed or in very low power state. The backup battery
can be chargeable or non-chargeable. This flag will tells whether
battery is chargeable or not. If charging battery then driver can
enable the charging.
- ti,backup-battery-charge-high-current: Enable high current charging in
backup battery. Device supports the < 100mA and > 100mA charging.
The high current will be > 100mA. Absence of this property will
charge battery to lower current i.e. < 100mA.
Example:
palmas: tps65913@58 {
...
palmas_rtc: rtc {
compatible = "ti,palmas-rtc";
interrupt-parent = <&palmas>;
interrupts = <8 0>;
ti,backup-battery-chargeable;
ti,backup-battery-charge-high-current;
};
...
};

View File

@ -854,16 +854,15 @@ Committed_AS: The amount of memory presently allocated on the system.
The committed memory is a sum of all of the memory which
has been allocated by processes, even if it has not been
"used" by them as of yet. A process which malloc()'s 1G
of memory, but only touches 300M of it will only show up
as using 300M of memory even if it has the address space
allocated for the entire 1G. This 1G is memory which has
been "committed" to by the VM and can be used at any time
by the allocating application. With strict overcommit
enabled on the system (mode 2 in 'vm.overcommit_memory'),
allocations which would exceed the CommitLimit (detailed
above) will not be permitted. This is useful if one needs
to guarantee that processes will not fail due to lack of
memory once that memory has been successfully allocated.
of memory, but only touches 300M of it will show up as
using 1G. This 1G is memory which has been "committed" to
by the VM and can be used at any time by the allocating
application. With strict overcommit enabled on the system
(mode 2 in 'vm.overcommit_memory'),allocations which would
exceed the CommitLimit (detailed above) will not be permitted.
This is useful if one needs to guarantee that processes will
not fail due to lack of memory once that memory has been
successfully allocated.
VmallocTotal: total size of vmalloc memory area
VmallocUsed: amount of vmalloc area which is used
VmallocChunk: largest contiguous block of vmalloc area which is free

View File

@ -79,6 +79,10 @@ to just make sure certain lists can't become empty.
Most systems just mount another filesystem over rootfs and ignore it. The
amount of space an empty instance of ramfs takes up is tiny.
If CONFIG_TMPFS is enabled, rootfs will use tmpfs instead of ramfs by
default. To force ramfs, add "rootfstype=ramfs" to the kernel command
line.
What is initramfs?
------------------

View File

@ -182,6 +182,7 @@ core_pattern is used to specify a core dumpfile pattern name.
%<NUL> '%' is dropped
%% output one '%'
%p pid
%P global pid (init PID namespace)
%u uid
%g gid
%d dump mode, matches PR_SET_DUMPABLE and

View File

@ -200,17 +200,25 @@ fragmentation index is <= extfrag_threshold. The default value is 500.
hugepages_treat_as_movable
This parameter is only useful when kernelcore= is specified at boot time to
create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
value written to hugepages_treat_as_movable allows huge pages to be allocated
from ZONE_MOVABLE.
This parameter controls whether we can allocate hugepages from ZONE_MOVABLE
or not. If set to non-zero, hugepages can be allocated from ZONE_MOVABLE.
ZONE_MOVABLE is created when kernel boot parameter kernelcore= is specified,
so this parameter has no effect if used without kernelcore=.
Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
pages pool can easily grow or shrink within. Assuming that applications are
not running that mlock() a lot of memory, it is likely the huge pages pool
can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
into nr_hugepages and triggering page reclaim.
Hugepage migration is now available in some situations which depend on the
architecture and/or the hugepage size. If a hugepage supports migration,
allocation from ZONE_MOVABLE is always enabled for the hugepage regardless
of the value of this parameter.
IOW, this parameter affects only non-migratable hugepages.
Assuming that hugepages are not migratable in your system, one usecase of
this parameter is that users can make hugepage pool more extensible by
enabling the allocation from ZONE_MOVABLE. This is because on ZONE_MOVABLE
page reclaim/migration/compaction work more and you can get contiguous
memory more likely. Note that using ZONE_MOVABLE for non-migratable
hugepages can do harm to other features like memory hotremove (because
memory hotremove expects that memory blocks on ZONE_MOVABLE are always
removable,) so it's a trade-off responsible for the users.
==============================================================

View File

@ -165,6 +165,7 @@ which function as described above for the default huge page-sized case.
Interaction of Task Memory Policy with Huge Page Allocation/Freeing
===================================================================
Whether huge pages are allocated and freed via the /proc interface or
the /sysfs interface using the nr_hugepages_mempolicy attribute, the NUMA
@ -229,6 +230,7 @@ resulting effect on persistent huge page allocation is as follows:
of huge pages over all on-lines nodes with memory.
Per Node Hugepages Attributes
=============================
A subset of the contents of the root huge page control directory in sysfs,
described above, will be replicated under each the system device of each
@ -258,6 +260,7 @@ applied, from which node the huge page allocation will be attempted.
Using Huge Pages
================
If the user applications are going to request huge pages using mmap system
call, then it is required that system administrator mount a file system of
@ -296,20 +299,16 @@ calls, though the mount of filesystem will be required for using mmap calls
without MAP_HUGETLB. For an example of how to use mmap with MAP_HUGETLB see
map_hugetlb.c.
*******************************************************************
Examples
========
/*
* map_hugetlb: see tools/testing/selftests/vm/map_hugetlb.c
*/
1) map_hugetlb: see tools/testing/selftests/vm/map_hugetlb.c
*******************************************************************
2) hugepage-shm: see tools/testing/selftests/vm/hugepage-shm.c
/*
* hugepage-shm: see tools/testing/selftests/vm/hugepage-shm.c
*/
3) hugepage-mmap: see tools/testing/selftests/vm/hugepage-mmap.c
*******************************************************************
/*
* hugepage-mmap: see tools/testing/selftests/vm/hugepage-mmap.c
*/
4) The libhugetlbfs (http://libhugetlbfs.sourceforge.net) library provides a
wide range of userspace tools to help with huge page usability, environment
setup, and control. Furthermore it provides useful test cases that should be
used when modifying code to ensure no regressions are introduced.

View File

@ -28,6 +28,13 @@ This is so, since the pages are still mapped to physical memory, and thus all
the kernel does is finds this fact out and puts both writable and soft-dirty
bits on the PTE.
While in most cases tracking memory changes by #PF-s is more than enough
there is still a scenario when we can lose soft dirty bits -- a task
unmaps a previously mapped memory region and then maps a new one at exactly
the same place. When unmap is called, the kernel internally clears PTE values
including soft dirty bits. To notify user space application about such
memory region renewal the kernel always marks new memory regions (and
expanded regions) as soft dirty.
This feature is actively used by the checkpoint-restore project. You
can find more details about it on http://criu.org

View File

@ -1028,7 +1028,7 @@ F: arch/arm/mach-orion5x/ts78xx-*
ARM/MICREL KS8695 ARCHITECTURE
M: Greg Ungerer <gerg@uclinux.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
F: arch/arm/mach-ks8695
F: arch/arm/mach-ks8695/
S: Odd Fixes
ARM/MIOA701 MACHINE SUPPORT
@ -1048,7 +1048,6 @@ M: STEricsson <STEricsson_nomadik_linux@list.st.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-nomadik/
F: arch/arm/plat-nomadik/
F: drivers/i2c/busses/i2c-nomadik.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
@ -1070,7 +1069,7 @@ F: drivers/mmc/host/msm_sdcc.h
F: drivers/tty/serial/msm_serial.h
F: drivers/tty/serial/msm_serial.c
F: drivers/*/pm8???-*
F: drivers/ssbi/
F: drivers/mfd/ssbi/
F: include/linux/mfd/pm8xxx/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
S: Maintained
@ -1156,7 +1155,6 @@ L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/plat-samsung/
F: arch/arm/plat-s3c24xx/
F: arch/arm/mach-s3c24*/
F: arch/arm/mach-s3c64xx/
F: drivers/*/*s3c2410*
@ -1179,8 +1177,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-s5pv210/mach-aquila.c
F: arch/arm/mach-s5pv210/mach-goni.c
F: arch/arm/mach-exynos/mach-universal_c210.c
F: arch/arm/mach-exynos/mach-nuri.c
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com>
@ -1325,7 +1321,7 @@ F: drivers/mmc/host/wmt-sdmmc.c
F: drivers/pwm/pwm-vt8500.c
F: drivers/rtc/rtc-vt8500.c
F: drivers/tty/serial/vt8500_serial.c
F: drivers/usb/host/ehci-vt8500.c
F: drivers/usb/host/ehci-platform.c
F: drivers/usb/host/uhci-platform.c
F: drivers/video/vt8500lcdfb.*
F: drivers/video/wm8505fb*
@ -1815,6 +1811,17 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/broadcom/bnx2x/
BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
M: Christian Daudt <csd@broadcom.com>
T: git git://git.github.com/broadcom/bcm11351
S: Maintained
F: arch/arm/mach-bcm/
F: arch/arm/boot/dts/bcm113*
F: arch/arm/boot/dts/bcm281*
F: arch/arm/configs/bcm_defconfig
F: drivers/mmc/host/sdhci_bcm_kona.c
F: drivers/clocksource/bcm_kona_timer.c
BROADCOM BCM2835 ARM ARCHICTURE
M: Stephen Warren <swarren@wwwdotorg.org>
L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
@ -2035,10 +2042,10 @@ W: http://ceph.com/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
S: Supported
F: Documentation/filesystems/ceph.txt
F: fs/ceph
F: net/ceph
F: include/linux/ceph
F: include/linux/crush
F: fs/ceph/
F: net/ceph/
F: include/linux/ceph/
F: include/linux/crush/
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
L: linux-usb@vger.kernel.org
@ -2335,7 +2342,7 @@ CPU POWER MONITORING SUBSYSTEM
M: Dominik Brodowski <linux@dominikbrodowski.net>
M: Thomas Renninger <trenn@suse.de>
S: Maintained
F: tools/power/cpupower
F: tools/power/cpupower/
CPUSETS
M: Li Zefan <lizefan@huawei.com>
@ -2773,7 +2780,7 @@ L: intel-gfx@lists.freedesktop.org
L: dri-devel@lists.freedesktop.org
T: git git://people.freedesktop.org/~danvet/drm-intel
S: Supported
F: drivers/gpu/drm/i915
F: drivers/gpu/drm/i915/
F: include/drm/i915*
F: include/uapi/drm/i915*
@ -2785,7 +2792,7 @@ M: Kyungmin Park <kyungmin.park@samsung.com>
L: dri-devel@lists.freedesktop.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
S: Supported
F: drivers/gpu/drm/exynos
F: drivers/gpu/drm/exynos/
F: include/drm/exynos*
F: include/uapi/drm/exynos*
@ -3038,7 +3045,7 @@ M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/ghes-edac.c
F: drivers/edac/ghes_edac.c
EDAC-I82443BXGX
M: Tim Small <tim@buttersideup.com>
@ -3644,8 +3651,8 @@ M: Arnd Bergmann <arnd@arndb.de>
L: linux-arch@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
S: Maintained
F: include/asm-generic
F: include/uapi/asm-generic
F: include/asm-generic/
F: include/uapi/asm-generic/
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
@ -3687,7 +3694,8 @@ GRE DEMULTIPLEXER DRIVER
M: Dmitry Kozlov <xeb@mail.ru>
L: netdev@vger.kernel.org
S: Maintained
F: net/ipv4/gre.c
F: net/ipv4/gre_demux.c
F: net/ipv4/gre_offload.c
F: include/net/gre.h
GRETH 10/100/1G Ethernet MAC device driver
@ -3765,7 +3773,7 @@ L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
S: Odd Fixes
F: drivers/media/usb/hdpvr
F: drivers/media/usb/hdpvr/
HWPOISON MEMORY FAILURE HANDLING
M: Andi Kleen <andi@firstfloor.org>
@ -4574,7 +4582,7 @@ S: Supported
W: http://www.openfabrics.org
W: www.open-iscsi.org
Q: http://patchwork.kernel.org/project/linux-rdma/list/
F: drivers/infiniband/ulp/iser
F: drivers/infiniband/ulp/iser/
ISDN SUBSYSTEM
M: Karsten Keil <isdn@linux-pingi.de>
@ -4628,7 +4636,7 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/tuners/it913x*
F: drivers/media/tuners/tuner_it913x*
IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
@ -5964,15 +5972,12 @@ S: Maintained
F: arch/arm/*omap*/*pm*
F: drivers/cpufreq/omap-cpufreq.c
OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT
OMAP POWERDOMAIN SOC ADAPTATION LAYER SUPPORT
M: Rajendra Nayak <rnayak@ti.com>
M: Paul Walmsley <paul@pwsan.com>
L: linux-omap@vger.kernel.org
S: Maintained
F: arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
F: arch/arm/mach-omap2/powerdomain44xx.c
F: arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
F: arch/arm/mach-omap2/clockdomain44xx.c
F: arch/arm/mach-omap2/prm*
OMAP AUDIO SUPPORT
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
@ -6138,7 +6143,7 @@ W: http://openrisc.net
L: linux@lists.openrisc.net (moderated for non-subscribers)
S: Maintained
T: git git://openrisc.net/~jonas/linux
F: arch/openrisc
F: arch/openrisc/
OPENVSWITCH
M: Jesse Gross <jesse@nicira.com>
@ -6429,7 +6434,7 @@ M: Jamie Iles <jamie@jamieiles.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://github.com/jamieiles/linux-2.6-ji.git
S: Supported
F: arch/arm/mach-picoxcell
F: arch/arm/mach-picoxcell/
F: drivers/*/picoxcell*
F: drivers/*/*/picoxcell*
@ -6702,7 +6707,7 @@ F: drivers/spi/spi-pxa2xx*
F: drivers/usb/gadget/pxa2*
F: include/sound/pxa2xx-lib.h
F: sound/arm/pxa*
F: sound/soc/pxa
F: sound/soc/pxa/
MMP SUPPORT
M: Eric Miao <eric.y.miao@gmail.com>
@ -7155,7 +7160,7 @@ SAMSUNG AUDIO (ASoC) DRIVERS
M: Sangbeom Kim <sbkim73@samsung.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/soc/samsung
F: sound/soc/samsung/
SAMSUNG FRAMEBUFFER DRIVER
M: Jingoo Han <jg1.han@samsung.com>
@ -7201,7 +7206,7 @@ SERIAL DRIVERS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org
S: Maintained
F: drivers/tty/serial
F: drivers/tty/serial/
SYNOPSYS DESIGNWARE DMAC DRIVER
M: Viresh Kumar <viresh.linux@gmail.com>
@ -7236,7 +7241,7 @@ TLG2300 VIDEO4LINUX-2 DRIVER
M: Huang Shijie <shijie8@gmail.com>
M: Hans Verkuil <hverkuil@xs4all.nl>
S: Odd Fixes
F: drivers/media/usb/tlg2300
F: drivers/media/usb/tlg2300/
SC1200 WDT DRIVER
M: Zwane Mwaikambo <zwane@arm.linux.org.uk>
@ -7497,7 +7502,7 @@ L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
S: Odd Fixes
F: drivers/media/radio/radio-si4713.h
F: drivers/media/radio/radio-si4713.c
SIANO DVB DRIVER
M: Mauro Carvalho Chehab <m.chehab@samsung.com>
@ -7506,9 +7511,9 @@ W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
S: Odd fixes
F: drivers/media/common/siano/
F: drivers/media/dvb/siano/
F: drivers/media/usb/siano/
F: drivers/media/mmc/siano
F: drivers/media/usb/siano/
F: drivers/media/mmc/siano/
SH_VEU V4L2 MEM2MEM DRIVER
M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@ -7546,9 +7551,9 @@ P: Vincent Sanders <vince@simtec.co.uk>
M: Simtec Linux Team <linux@simtec.co.uk>
W: http://www.simtec.co.uk/products/EB2410ITX/
S: Supported
F: arch/arm/mach-s3c2410/mach-bast.c
F: arch/arm/mach-s3c2410/bast-ide.c
F: arch/arm/mach-s3c2410/bast-irq.c
F: arch/arm/mach-s3c24xx/mach-bast.c
F: arch/arm/mach-s3c24xx/bast-ide.c
F: arch/arm/mach-s3c24xx/bast-irq.c
TI DAVINCI MACHINE SUPPORT
M: Sekhar Nori <nsekhar@ti.com>
@ -7557,7 +7562,7 @@ L: davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers
T: git git://gitorious.org/linux-davinci/linux-davinci.git
Q: http://patchwork.kernel.org/project/linux-davinci/list/
S: Supported
F: arch/arm/mach-davinci
F: arch/arm/mach-davinci/
F: drivers/i2c/busses/i2c-davinci.c
TI DAVINCI SERIES MEDIA DRIVER
@ -7642,7 +7647,7 @@ SMIA AND SMIA++ IMAGE SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@iki.fi>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/smiapp
F: drivers/media/i2c/smiapp/
F: include/media/smiapp.h
F: drivers/media/i2c/smiapp-pll.c
F: drivers/media/i2c/smiapp-pll.h
@ -7745,6 +7750,11 @@ W: http://tifmxx.berlios.de/
S: Maintained
F: drivers/memstick/host/tifm_ms.c
SONY MEMORYSTICK STANDARD SUPPORT
M: Maxim Levitsky <maximlevitsky@gmail.com>
S: Maintained
F: drivers/memstick/core/ms_block.*
SOUND
M: Jaroslav Kysela <perex@perex.cz>
M: Takashi Iwai <tiwai@suse.de>
@ -7821,35 +7831,7 @@ L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/plat-spear/
SPEAR13XX MACHINE SUPPORT
M: Viresh Kumar <viresh.linux@gmail.com>
M: Shiraz Hashim <shiraz.hashim@st.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/mach-spear13xx/
SPEAR3XX MACHINE SUPPORT
M: Viresh Kumar <viresh.linux@gmail.com>
M: Shiraz Hashim <shiraz.hashim@st.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/mach-spear3xx/
SPEAR6XX MACHINE SUPPORT
M: Rajeev Kumar <rajeev-dlh.kumar@st.com>
M: Shiraz Hashim <shiraz.hashim@st.com>
M: Viresh Kumar <viresh.linux@gmail.com>
L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/mach-spear6xx/
F: arch/arm/mach-spear/
SPEAR CLOCK FRAMEWORK SUPPORT
M: Viresh Kumar <viresh.linux@gmail.com>
@ -8118,7 +8100,7 @@ M: Vineet Gupta <vgupta@synopsys.com>
S: Supported
F: arch/arc/
F: Documentation/devicetree/bindings/arc/
F: drivers/tty/serial/arc-uart.c
F: drivers/tty/serial/arc_uart.c
SYSV FILESYSTEM
M: Christoph Hellwig <hch@infradead.org>
@ -8808,7 +8790,6 @@ L: linux-usb@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/phy/
F: drivers/usb/otg/
USB PRINTER DRIVER (usblp)
M: Pete Zaitcev <zaitcev@redhat.com>
@ -9339,7 +9320,7 @@ M: Matthew Garrett <matthew.garrett@nebula.com>
L: platform-driver-x86@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
S: Maintained
F: drivers/platform/x86
F: drivers/platform/x86/
X86 MCE INFRASTRUCTURE
M: Tony Luck <tony.luck@intel.com>

View File

@ -338,6 +338,11 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len,
unsigned long doff = 7 & (unsigned long) dst;
if (len) {
if (!access_ok(VERIFY_READ, src, len)) {
*errp = -EFAULT;
memset(dst, 0, len);
return sum;
}
if (!doff) {
if (!soff)
checksum = csum_partial_cfu_aligned(

View File

@ -56,3 +56,8 @@ int pmd_huge(pmd_t pmd)
{
return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT);
}
int pmd_huge_support(void)
{
return 1;
}

View File

@ -54,6 +54,11 @@ int pud_huge(pud_t pud)
return !(pud_val(pud) & PUD_TABLE_BIT);
}
int pmd_huge_support(void)
{
return 1;
}
static __init int setup_hugepagesz(char *opt)
{
unsigned long ps = memparse(opt, &opt);

View File

@ -114,6 +114,11 @@ int pud_huge(pud_t pud)
return 0;
}
int pmd_huge_support(void)
{
return 0;
}
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
{

View File

@ -110,6 +110,11 @@ int pud_huge(pud_t pud)
return 0;
}
int pmd_huge_support(void)
{
return 1;
}
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{

View File

@ -85,6 +85,11 @@ int pud_huge(pud_t pud)
return (pud_val(pud) & _PAGE_HUGE) != 0;
}
int pmd_huge_support(void)
{
return 1;
}
struct page *
follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)

View File

@ -86,6 +86,11 @@ int pgd_huge(pgd_t pgd)
*/
return ((pgd_val(pgd) & 0x3) != 0x0);
}
int pmd_huge_support(void)
{
return 1;
}
#else
int pmd_huge(pmd_t pmd)
{
@ -101,6 +106,11 @@ int pgd_huge(pgd_t pgd)
{
return 0;
}
int pmd_huge_support(void)
{
return 0;
}
#endif
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)

View File

@ -526,6 +526,7 @@ config CRASH_DUMP
bool "kernel crash dumps"
depends on 64BIT && SMP
select KEXEC
select ZFCPDUMP
help
Generate crash dump after being started by kexec.
Crash dump kernels are loaded in the main kernel with kexec-tools
@ -536,7 +537,7 @@ config CRASH_DUMP
config ZFCPDUMP
def_bool n
prompt "zfcpdump support"
select SMP
depends on SMP
help
Select this option if you want to build an zfcpdump enabled kernel.
Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.

View File

@ -31,6 +31,8 @@
#include <linux/ptrace.h>
#include <linux/percpu.h>
#define __ARCH_WANT_KPROBES_INSN_SLOT
struct pt_regs;
struct kprobe;
@ -57,7 +59,7 @@ typedef u16 kprobe_opcode_t;
/* Architecture specific copy of original instruction */
struct arch_specific_insn {
/* copy of original instruction */
kprobe_opcode_t insn[MAX_INSN_SIZE];
kprobe_opcode_t *insn;
};
struct prev_kprobe {

View File

@ -56,5 +56,6 @@ bool sclp_has_linemode(void);
bool sclp_has_vt220(void);
int sclp_pci_configure(u32 fid);
int sclp_pci_deconfigure(u32 fid);
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
#endif /* _ASM_S390_SCLP_H */

View File

@ -16,6 +16,7 @@
#include <asm/os_info.h>
#include <asm/elf.h>
#include <asm/ipl.h>
#include <asm/sclp.h>
#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
@ -64,22 +65,46 @@ static ssize_t copy_page_real(void *buf, void *src, size_t csize)
}
/*
* Copy one page from "oldmem"
* Pointer to ELF header in new kernel
*/
static void *elfcorehdr_newmem;
/*
* Copy one page from zfcpdump "oldmem"
*
* For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise
* real memory copy is used.
*/
static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
unsigned long src, int userbuf)
{
int rc;
if (src < ZFCPDUMP_HSA_SIZE) {
rc = memcpy_hsa(buf, src, csize, userbuf);
} else {
if (userbuf)
rc = copy_to_user_real((void __force __user *) buf,
(void *) src, csize);
else
rc = memcpy_real(buf, (void *) src, csize);
}
return rc ? rc : csize;
}
/*
* Copy one page from kdump "oldmem"
*
* For the kdump reserved memory this functions performs a swap operation:
* - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
* - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
*/
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
size_t csize, unsigned long offset, int userbuf)
static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
unsigned long src, int userbuf)
{
unsigned long src;
int rc;
if (!csize)
return 0;
src = (pfn << PAGE_SHIFT) + offset;
if (src < OLDMEM_SIZE)
src += OLDMEM_BASE;
else if (src > OLDMEM_BASE &&
@ -90,7 +115,88 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
(void *) src, csize);
else
rc = copy_page_real(buf, (void *) src, csize);
return (rc == 0) ? csize : rc;
return (rc == 0) ? rc : csize;
}
/*
* Copy one page from "oldmem"
*/
ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
unsigned long offset, int userbuf)
{
unsigned long src;
if (!csize)
return 0;
src = (pfn << PAGE_SHIFT) + offset;
if (OLDMEM_BASE)
return copy_oldmem_page_kdump(buf, csize, src, userbuf);
else
return copy_oldmem_page_zfcpdump(buf, csize, src, userbuf);
}
/*
* Remap "oldmem" for kdump
*
* For the kdump reserved memory this functions performs a swap operation:
* [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
*/
static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
unsigned long from, unsigned long pfn,
unsigned long size, pgprot_t prot)
{
unsigned long size_old;
int rc;
if (pfn < OLDMEM_SIZE >> PAGE_SHIFT) {
size_old = min(size, OLDMEM_SIZE - (pfn << PAGE_SHIFT));
rc = remap_pfn_range(vma, from,
pfn + (OLDMEM_BASE >> PAGE_SHIFT),
size_old, prot);
if (rc || size == size_old)
return rc;
size -= size_old;
from += size_old;
pfn += size_old >> PAGE_SHIFT;
}
return remap_pfn_range(vma, from, pfn, size, prot);
}
/*
* Remap "oldmem" for zfcpdump
*
* We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
* ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
*/
static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
unsigned long from,
unsigned long pfn,
unsigned long size, pgprot_t prot)
{
unsigned long size_hsa;
if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) {
size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT));
if (size == size_hsa)
return 0;
size -= size_hsa;
from += size_hsa;
pfn += size_hsa >> PAGE_SHIFT;
}
return remap_pfn_range(vma, from, pfn, size, prot);
}
/*
* Remap "oldmem" for kdump or zfcpdump
*/
int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
unsigned long pfn, unsigned long size, pgprot_t prot)
{
if (OLDMEM_BASE)
return remap_oldmem_pfn_range_kdump(vma, from, pfn, size, prot);
else
return remap_oldmem_pfn_range_zfcpdump(vma, from, pfn, size,
prot);
}
/*
@ -101,11 +207,21 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
unsigned long copied = 0;
int rc;
if ((unsigned long) src < OLDMEM_SIZE) {
copied = min(count, OLDMEM_SIZE - (unsigned long) src);
rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
if (rc)
return rc;
if (OLDMEM_BASE) {
if ((unsigned long) src < OLDMEM_SIZE) {
copied = min(count, OLDMEM_SIZE - (unsigned long) src);
rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
if (rc)
return rc;
}
} else {
if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) {
copied = min(count,
ZFCPDUMP_HSA_SIZE - (unsigned long) src);
rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
if (rc)
return rc;
}
}
return memcpy_real(dest + copied, src + copied, count - copied);
}
@ -367,14 +483,6 @@ static int get_mem_chunk_cnt(void)
return cnt;
}
/*
* Relocate pointer in order to allow vmcore code access the data
*/
static inline unsigned long relocate(unsigned long addr)
{
return OLDMEM_BASE + addr;
}
/*
* Initialize ELF loads (new kernel)
*/
@ -426,7 +534,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
ptr = nt_vmcoreinfo(ptr);
memset(phdr, 0, sizeof(*phdr));
phdr->p_type = PT_NOTE;
phdr->p_offset = relocate(notes_offset);
phdr->p_offset = notes_offset;
phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
phdr->p_memsz = phdr->p_filesz;
return ptr;
@ -435,7 +543,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
/*
* Create ELF core header (new kernel)
*/
static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
{
Elf64_Phdr *phdr_notes, *phdr_loads;
int mem_chunk_cnt;
@ -443,6 +551,12 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
u32 alloc_size;
u64 hdr_off;
/* If we are not in kdump or zfcpdump mode return */
if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
return 0;
/* If elfcorehdr= has been passed via cmdline, we use that one */
if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
return 0;
mem_chunk_cnt = get_mem_chunk_cnt();
alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
@ -460,27 +574,52 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
/* Init loads */
hdr_off = PTR_DIFF(ptr, hdr);
loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
*elfcorebuf_sz = hdr_off;
*elfcorebuf = (void *) relocate((unsigned long) hdr);
BUG_ON(*elfcorebuf_sz > alloc_size);
}
/*
* Create kdump ELF core header in new kernel, if it has not been passed via
* the "elfcorehdr" kernel parameter
*/
static int setup_kdump_elfcorehdr(void)
{
size_t elfcorebuf_sz;
char *elfcorebuf;
if (!OLDMEM_BASE || is_kdump_kernel())
return -EINVAL;
s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
elfcorehdr_addr = (unsigned long long) elfcorebuf;
elfcorehdr_size = elfcorebuf_sz;
loads_init(phdr_loads, hdr_off);
*addr = (unsigned long long) hdr;
elfcorehdr_newmem = hdr;
*size = (unsigned long long) hdr_off;
BUG_ON(elfcorehdr_size > alloc_size);
return 0;
}
subsys_initcall(setup_kdump_elfcorehdr);
/*
* Free ELF core header (new kernel)
*/
void elfcorehdr_free(unsigned long long addr)
{
if (!elfcorehdr_newmem)
return;
kfree((void *)(unsigned long)addr);
}
/*
* Read from ELF header
*/
ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
{
void *src = (void *)(unsigned long)*ppos;
src = elfcorehdr_newmem ? src : src - OLDMEM_BASE;
memcpy(buf, src, count);
*ppos += count;
return count;
}
/*
* Read from ELF notes data
*/
ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
{
void *src = (void *)(unsigned long)*ppos;
int rc;
if (elfcorehdr_newmem) {
memcpy(buf, src, count);
} else {
rc = copy_from_oldmem(buf, src, count);
if (rc)
return rc;
}
*ppos += count;
return count;
}

View File

@ -37,6 +37,26 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
struct kretprobe_blackpoint kretprobe_blacklist[] = { };
DEFINE_INSN_CACHE_OPS(dmainsn);
static void *alloc_dmainsn_page(void)
{
return (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
}
static void free_dmainsn_page(void *page)
{
free_page((unsigned long)page);
}
struct kprobe_insn_cache kprobe_dmainsn_slots = {
.mutex = __MUTEX_INITIALIZER(kprobe_dmainsn_slots.mutex),
.alloc = alloc_dmainsn_page,
.free = free_dmainsn_page,
.pages = LIST_HEAD_INIT(kprobe_dmainsn_slots.pages),
.insn_size = MAX_INSN_SIZE,
};
static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
{
switch (insn[0] >> 8) {
@ -100,9 +120,8 @@ static int __kprobes get_fixup_type(kprobe_opcode_t *insn)
fixup |= FIXUP_RETURN_REGISTER;
break;
case 0xc0:
if ((insn[0] & 0x0f) == 0x00 || /* larl */
(insn[0] & 0x0f) == 0x05) /* brasl */
fixup |= FIXUP_RETURN_REGISTER;
if ((insn[0] & 0x0f) == 0x05) /* brasl */
fixup |= FIXUP_RETURN_REGISTER;
break;
case 0xeb:
switch (insn[2] & 0xff) {
@ -134,18 +153,128 @@ static int __kprobes get_fixup_type(kprobe_opcode_t *insn)
return fixup;
}
static int __kprobes is_insn_relative_long(kprobe_opcode_t *insn)
{
/* Check if we have a RIL-b or RIL-c format instruction which
* we need to modify in order to avoid instruction emulation. */
switch (insn[0] >> 8) {
case 0xc0:
if ((insn[0] & 0x0f) == 0x00) /* larl */
return true;
break;
case 0xc4:
switch (insn[0] & 0x0f) {
case 0x02: /* llhrl */
case 0x04: /* lghrl */
case 0x05: /* lhrl */
case 0x06: /* llghrl */
case 0x07: /* sthrl */
case 0x08: /* lgrl */
case 0x0b: /* stgrl */
case 0x0c: /* lgfrl */
case 0x0d: /* lrl */
case 0x0e: /* llgfrl */
case 0x0f: /* strl */
return true;
}
break;
case 0xc6:
switch (insn[0] & 0x0f) {
case 0x00: /* exrl */
case 0x02: /* pfdrl */
case 0x04: /* cghrl */
case 0x05: /* chrl */
case 0x06: /* clghrl */
case 0x07: /* clhrl */
case 0x08: /* cgrl */
case 0x0a: /* clgrl */
case 0x0c: /* cgfrl */
case 0x0d: /* crl */
case 0x0e: /* clgfrl */
case 0x0f: /* clrl */
return true;
}
break;
}
return false;
}
static void __kprobes copy_instruction(struct kprobe *p)
{
s64 disp, new_disp;
u64 addr, new_addr;
memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2);
if (!is_insn_relative_long(p->ainsn.insn))
return;
/*
* For pc-relative instructions in RIL-b or RIL-c format patch the
* RI2 displacement field. We have already made sure that the insn
* slot for the patched instruction is within the same 2GB area
* as the original instruction (either kernel image or module area).
* Therefore the new displacement will always fit.
*/
disp = *(s32 *)&p->ainsn.insn[1];
addr = (u64)(unsigned long)p->addr;
new_addr = (u64)(unsigned long)p->ainsn.insn;
new_disp = ((addr + (disp * 2)) - new_addr) / 2;
*(s32 *)&p->ainsn.insn[1] = new_disp;
}
static inline int is_kernel_addr(void *addr)
{
return addr < (void *)_end;
}
static inline int is_module_addr(void *addr)
{
#ifdef CONFIG_64BIT
BUILD_BUG_ON(MODULES_LEN > (1UL << 31));
if (addr < (void *)MODULES_VADDR)
return 0;
if (addr > (void *)MODULES_END)
return 0;
#endif
return 1;
}
static int __kprobes s390_get_insn_slot(struct kprobe *p)
{
/*
* Get an insn slot that is within the same 2GB area like the original
* instruction. That way instructions with a 32bit signed displacement
* field can be patched and executed within the insn slot.
*/
p->ainsn.insn = NULL;
if (is_kernel_addr(p->addr))
p->ainsn.insn = get_dmainsn_slot();
if (is_module_addr(p->addr))
p->ainsn.insn = get_insn_slot();
return p->ainsn.insn ? 0 : -ENOMEM;
}
static void __kprobes s390_free_insn_slot(struct kprobe *p)
{
if (!p->ainsn.insn)
return;
if (is_kernel_addr(p->addr))
free_dmainsn_slot(p->ainsn.insn, 0);
else
free_insn_slot(p->ainsn.insn, 0);
p->ainsn.insn = NULL;
}
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
if ((unsigned long) p->addr & 0x01)
return -EINVAL;
/* Make sure the probe isn't going on a difficult instruction */
if (is_prohibited_opcode(p->addr))
return -EINVAL;
if (s390_get_insn_slot(p))
return -ENOMEM;
p->opcode = *p->addr;
memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2);
copy_instruction(p);
return 0;
}
@ -186,6 +315,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
s390_free_insn_slot(p);
}
static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb,

View File

@ -223,6 +223,11 @@ int pud_huge(pud_t pud)
return 0;
}
int pmd_huge_support(void)
{
return 1;
}
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmdp, int write)
{

View File

@ -83,6 +83,11 @@ int pud_huge(pud_t pud)
return 0;
}
int pmd_huge_support(void)
{
return 0;
}
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{

View File

@ -169,10 +169,10 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig,
new_ka.ka_restorer = restorer;
ret = get_user(u_handler, &act->sa_handler);
new_ka.sa.sa_handler = compat_ptr(u_handler);
ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
ret |= copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
sigset_from_compat(&new_ka.sa.sa_mask, &set32);
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
ret |= __get_user(u_restorer, &act->sa_restorer);
ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
ret |= get_user(u_restorer, &act->sa_restorer);
new_ka.sa.sa_restorer = compat_ptr(u_restorer);
if (ret)
return -EFAULT;
@ -183,9 +183,9 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig,
if (!ret && oact) {
sigset_to_compat(&set32, &old_ka.sa.sa_mask);
ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
ret |= copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
if (ret)
ret = -EFAULT;
}

View File

@ -234,6 +234,11 @@ int pud_huge(pud_t pud)
return 0;
}
int pmd_huge_support(void)
{
return 0;
}
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{

View File

@ -166,6 +166,11 @@ int pud_huge(pud_t pud)
return !!(pud_val(pud) & _PAGE_HUGE_PAGE);
}
int pmd_huge_support(void)
{
return 1;
}
struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
pmd_t *pmd, int write)
{

View File

@ -315,21 +315,6 @@ static inline pmd_t pmd_mksoft_dirty(pmd_t pmd)
return pmd_set_flags(pmd, _PAGE_SOFT_DIRTY);
}
static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
{
return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY);
}
static inline int pte_swp_soft_dirty(pte_t pte)
{
return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY;
}
static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
{
return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
}
static inline pte_t pte_file_clear_soft_dirty(pte_t pte)
{
return pte_clear_flags(pte, _PAGE_SOFT_DIRTY);
@ -446,6 +431,7 @@ pte_t *populate_extra_pte(unsigned long vaddr);
#ifndef __ASSEMBLY__
#include <linux/mm_types.h>
#include <linux/mmdebug.h>
#include <linux/log2.h>
static inline int pte_none(pte_t pte)
@ -864,6 +850,24 @@ static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
{
}
static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
{
VM_BUG_ON(pte_present(pte));
return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY);
}
static inline int pte_swp_soft_dirty(pte_t pte)
{
VM_BUG_ON(pte_present(pte));
return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY;
}
static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
{
VM_BUG_ON(pte_present(pte));
return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
}
#include <asm-generic/pgtable.h>
#endif /* __ASSEMBLY__ */

View File

@ -75,6 +75,9 @@
* with swap entry format. On x86 bits 6 and 7 are *not* involved
* into swap entry computation, but bit 6 is used for nonlinear
* file mapping, so we borrow bit 7 for soft dirty tracking.
*
* Please note that this bit must be treated as swap dirty page
* mark if and only if the PTE has present bit clear!
*/
#ifdef CONFIG_MEM_SOFT_DIRTY
#define _PAGE_SWP_SOFT_DIRTY _PAGE_PSE

View File

@ -62,6 +62,7 @@ static inline void __flush_tlb_all(void)
static inline void __flush_tlb_one(unsigned long addr)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
__flush_tlb_single(addr);
}
@ -84,14 +85,38 @@ static inline void __flush_tlb_one(unsigned long addr)
#ifndef CONFIG_SMP
#define flush_tlb() __flush_tlb()
#define flush_tlb_all() __flush_tlb_all()
#define local_flush_tlb() __flush_tlb()
/* "_up" is for UniProcessor.
*
* This is a helper for other header functions. *Not* intended to be called
* directly. All global TLB flushes need to either call this, or to bump the
* vm statistics themselves.
*/
static inline void __flush_tlb_up(void)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();
}
static inline void flush_tlb_all(void)
{
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb_all();
}
static inline void flush_tlb(void)
{
__flush_tlb_up();
}
static inline void local_flush_tlb(void)
{
__flush_tlb_up();
}
static inline void flush_tlb_mm(struct mm_struct *mm)
{
if (mm == current->active_mm)
__flush_tlb();
__flush_tlb_up();
}
static inline void flush_tlb_page(struct vm_area_struct *vma,
@ -105,14 +130,14 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
if (vma->vm_mm == current->active_mm)
__flush_tlb();
__flush_tlb_up();
}
static inline void flush_tlb_mm_range(struct mm_struct *mm,
unsigned long start, unsigned long end, unsigned long vmflag)
{
if (mm == current->active_mm)
__flush_tlb();
__flush_tlb_up();
}
static inline void native_flush_tlb_others(const struct cpumask *cpumask,

View File

@ -683,6 +683,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
}
/* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();
/* Save MTRR state */
@ -696,6 +697,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
static void post_set(void) __releases(set_atomicity_lock)
{
/* Flush TLBs (no need to flush caches - they are disabled) */
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
__flush_tlb();
/* Intel (P6) standard MTRRs */

View File

@ -59,6 +59,10 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
return NULL;
}
int pmd_huge_support(void)
{
return 0;
}
#else
struct page *
@ -77,6 +81,10 @@ int pud_huge(pud_t pud)
return !!(pud_val(pud) & _PAGE_PSE);
}
int pmd_huge_support(void)
{
return 1;
}
#endif
/* x86_64 also uses this file */

View File

@ -103,6 +103,7 @@ static void flush_tlb_func(void *info)
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
return;
count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
if (f->flush_end == TLB_FLUSH_ALL)
local_flush_tlb();
@ -130,6 +131,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
info.flush_start = start;
info.flush_end = end;
count_vm_event(NR_TLB_REMOTE_FLUSH);
if (is_uv_system()) {
unsigned int cpu;
@ -149,6 +151,7 @@ void flush_tlb_current_task(void)
preempt_disable();
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
@ -211,16 +214,19 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm;
/* tlb_flushall_shift is on balance point, details in commit log */
if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift)
if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
else {
} else {
if (has_large_page(mm, start, end)) {
local_flush_tlb();
goto flush_all;
}
/* flush range by one by one 'invlpg' */
for (addr = start; addr < end; addr += PAGE_SIZE)
for (addr = start; addr < end; addr += PAGE_SIZE) {
count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
__flush_tlb_single(addr);
}
if (cpumask_any_but(mm_cpumask(mm),
smp_processor_id()) < nr_cpu_ids)
@ -256,6 +262,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)
static void do_flush_tlb_all(void *info)
{
count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
__flush_tlb_all();
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
leave_mm(smp_processor_id());
@ -263,6 +270,7 @@ static void do_flush_tlb_all(void *info)
void flush_tlb_all(void)
{
count_vm_event(NR_TLB_REMOTE_FLUSH);
on_each_cpu(do_flush_tlb_all, NULL, 1);
}

View File

@ -99,6 +99,12 @@ config BLK_DEV_THROTTLING
See Documentation/cgroups/blkio-controller.txt for more information.
config CMDLINE_PARSER
bool "Block device command line partition parser"
default n
---help---
Parsing command line, get the partitions information.
menu "Partition Types"
source "block/partitions/Kconfig"

View File

@ -18,3 +18,4 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
obj-$(CONFIG_CMDLINE_PARSER) += cmdline-parser.o

View File

@ -367,7 +367,7 @@ struct io_cq *ioc_create_icq(struct io_context *ioc, struct request_queue *q,
if (!icq)
return NULL;
if (radix_tree_preload(gfp_mask) < 0) {
if (radix_tree_maybe_preload(gfp_mask) < 0) {
kmem_cache_free(et->icq_cache, icq);
return NULL;
}

View File

@ -29,7 +29,7 @@ queue_var_store(unsigned long *var, const char *page, size_t count)
int err;
unsigned long v;
err = strict_strtoul(page, 10, &v);
err = kstrtoul(page, 10, &v);
if (err || v > UINT_MAX)
return -EINVAL;

250
block/cmdline-parser.c Normal file
View File

@ -0,0 +1,250 @@
/*
* Parse command line, get partition information
*
* Written by Cai Zhiyong <caizhiyong@huawei.com>
*
*/
#include <linux/buffer_head.h>
#include <linux/module.h>
#include <linux/cmdline-parser.h>
static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
{
int ret = 0;
struct cmdline_subpart *new_subpart;
*subpart = NULL;
new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL);
if (!new_subpart)
return -ENOMEM;
if (*partdef == '-') {
new_subpart->size = (sector_t)(~0ULL);
partdef++;
} else {
new_subpart->size = (sector_t)memparse(partdef, &partdef);
if (new_subpart->size < (sector_t)PAGE_SIZE) {
pr_warn("cmdline partition size is invalid.");
ret = -EINVAL;
goto fail;
}
}
if (*partdef == '@') {
partdef++;
new_subpart->from = (sector_t)memparse(partdef, &partdef);
} else {
new_subpart->from = (sector_t)(~0ULL);
}
if (*partdef == '(') {
int length;
char *next = strchr(++partdef, ')');
if (!next) {
pr_warn("cmdline partition format is invalid.");
ret = -EINVAL;
goto fail;
}
length = min_t(int, next - partdef,
sizeof(new_subpart->name) - 1);
strncpy(new_subpart->name, partdef, length);
new_subpart->name[length] = '\0';
partdef = ++next;
} else
new_subpart->name[0] = '\0';
new_subpart->flags = 0;
if (!strncmp(partdef, "ro", 2)) {
new_subpart->flags |= PF_RDONLY;
partdef += 2;
}
if (!strncmp(partdef, "lk", 2)) {
new_subpart->flags |= PF_POWERUP_LOCK;
partdef += 2;
}
*subpart = new_subpart;
return 0;
fail:
kfree(new_subpart);
return ret;
}
static void free_subpart(struct cmdline_parts *parts)
{
struct cmdline_subpart *subpart;
while (parts->subpart) {
subpart = parts->subpart;
parts->subpart = subpart->next_subpart;
kfree(subpart);
}
}
static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
{
int ret = -EINVAL;
char *next;
int length;
struct cmdline_subpart **next_subpart;
struct cmdline_parts *newparts;
char buf[BDEVNAME_SIZE + 32 + 4];
*parts = NULL;
newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL);
if (!newparts)
return -ENOMEM;
next = strchr(bdevdef, ':');
if (!next) {
pr_warn("cmdline partition has no block device.");
goto fail;
}
length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
strncpy(newparts->name, bdevdef, length);
newparts->name[length] = '\0';
newparts->nr_subparts = 0;
next_subpart = &newparts->subpart;
while (next && *(++next)) {
bdevdef = next;
next = strchr(bdevdef, ',');
length = (!next) ? (sizeof(buf) - 1) :
min_t(int, next - bdevdef, sizeof(buf) - 1);
strncpy(buf, bdevdef, length);
buf[length] = '\0';
ret = parse_subpart(next_subpart, buf);
if (ret)
goto fail;
newparts->nr_subparts++;
next_subpart = &(*next_subpart)->next_subpart;
}
if (!newparts->subpart) {
pr_warn("cmdline partition has no valid partition.");
ret = -EINVAL;
goto fail;
}
*parts = newparts;
return 0;
fail:
free_subpart(newparts);
kfree(newparts);
return ret;
}
void cmdline_parts_free(struct cmdline_parts **parts)
{
struct cmdline_parts *next_parts;
while (*parts) {
next_parts = (*parts)->next_parts;
free_subpart(*parts);
kfree(*parts);
*parts = next_parts;
}
}
int cmdline_parts_parse(struct cmdline_parts **parts, const char *cmdline)
{
int ret;
char *buf;
char *pbuf;
char *next;
struct cmdline_parts **next_parts;
*parts = NULL;
next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
if (!buf)
return -ENOMEM;
next_parts = parts;
while (next && *pbuf) {
next = strchr(pbuf, ';');
if (next)
*next = '\0';
ret = parse_parts(next_parts, pbuf);
if (ret)
goto fail;
if (next)
pbuf = ++next;
next_parts = &(*next_parts)->next_parts;
}
if (!*parts) {
pr_warn("cmdline partition has no valid partition.");
ret = -EINVAL;
goto fail;
}
ret = 0;
done:
kfree(buf);
return ret;
fail:
cmdline_parts_free(parts);
goto done;
}
struct cmdline_parts *cmdline_parts_find(struct cmdline_parts *parts,
const char *bdev)
{
while (parts && strncmp(bdev, parts->name, sizeof(parts->name)))
parts = parts->next_parts;
return parts;
}
/*
* add_part()
* 0 success.
* 1 can not add so many partitions.
*/
void cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size,
int slot,
int (*add_part)(int, struct cmdline_subpart *, void *),
void *param)
{
sector_t from = 0;
struct cmdline_subpart *subpart;
for (subpart = parts->subpart; subpart;
subpart = subpart->next_subpart, slot++) {
if (subpart->from == (sector_t)(~0ULL))
subpart->from = from;
else
from = subpart->from;
if (from >= disk_size)
break;
if (subpart->size > (disk_size - from))
subpart->size = disk_size - from;
from += subpart->size;
if (add_part(slot, subpart, param))
break;
}
}

View File

@ -70,7 +70,7 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
return ret;
ret = copy_to_user(ugeo, &geo, 4);
ret |= __put_user(geo.start, &ugeo->start);
ret |= put_user(geo.start, &ugeo->start);
if (ret)
ret = -EFAULT;

View File

@ -260,3 +260,10 @@ config SYSV68_PARTITION
partition table format used by Motorola Delta machines (using
sysv68).
Otherwise, say N.
config CMDLINE_PARTITION
bool "Command line partition support" if PARTITION_ADVANCED
select CMDLINE_PARSER
help
Say Y here if you would read the partitions table from bootargs.
The format for the command line is just like mtdparts.

View File

@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o
obj-$(CONFIG_AMIGA_PARTITION) += amiga.o
obj-$(CONFIG_ATARI_PARTITION) += atari.o
obj-$(CONFIG_AIX_PARTITION) += aix.o
obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o
obj-$(CONFIG_MAC_PARTITION) += mac.o
obj-$(CONFIG_LDM_PARTITION) += ldm.o
obj-$(CONFIG_MSDOS_PARTITION) += msdos.o

View File

@ -34,6 +34,7 @@
#include "efi.h"
#include "karma.h"
#include "sysv68.h"
#include "cmdline.h"
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
@ -65,6 +66,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
adfspart_check_ADFS,
#endif
#ifdef CONFIG_CMDLINE_PARTITION
cmdline_partition,
#endif
#ifdef CONFIG_EFI_PARTITION
efi_partition, /* this must come before msdos */
#endif

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2013 HUAWEI
* Author: Cai Zhiyong <caizhiyong@huawei.com>
*
* Read block device partition table from command line.
* The partition used for fixed block device (eMMC) embedded device.
* It is no MBR, save storage space. Bootloader can be easily accessed
* by absolute address of data on the block device.
* Users can easily change the partition.
*
* The format for the command line is just like mtdparts.
*
* Verbose config please reference "Documentation/block/cmdline-partition.txt"
*
*/
#include <linux/cmdline-parser.h>
#include "check.h"
#include "cmdline.h"
static char *cmdline;
static struct cmdline_parts *bdev_parts;
static int add_part(int slot, struct cmdline_subpart *subpart, void *param)
{
int label_min;
struct partition_meta_info *info;
char tmp[sizeof(info->volname) + 4];
struct parsed_partitions *state = (struct parsed_partitions *)param;
if (slot >= state->limit)
return 1;
put_partition(state, slot, subpart->from >> 9,
subpart->size >> 9);
info = &state->parts[slot].info;
label_min = min_t(int, sizeof(info->volname) - 1,
sizeof(subpart->name));
strncpy(info->volname, subpart->name, label_min);
info->volname[label_min] = '\0';
snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
strlcat(state->pp_buf, tmp, PAGE_SIZE);
state->parts[slot].has_info = true;
return 0;
}
static int __init cmdline_parts_setup(char *s)
{
cmdline = s;
return 1;
}
__setup("blkdevparts=", cmdline_parts_setup);
/*
* Purpose: allocate cmdline partitions.
* Returns:
* -1 if unable to read the partition table
* 0 if this isn't our partition table
* 1 if successful
*/
int cmdline_partition(struct parsed_partitions *state)
{
sector_t disk_size;
char bdev[BDEVNAME_SIZE];
struct cmdline_parts *parts;
if (cmdline) {
if (bdev_parts)
cmdline_parts_free(&bdev_parts);
if (cmdline_parts_parse(&bdev_parts, cmdline)) {
cmdline = NULL;
return -1;
}
cmdline = NULL;
}
if (!bdev_parts)
return 0;
bdevname(state->bdev, bdev);
parts = cmdline_parts_find(bdev_parts, bdev);
if (!parts)
return 0;
disk_size = get_capacity(state->bdev->bd_disk) << 9;
cmdline_parts_set(parts, disk_size, 1, add_part, (void *)state);
strlcat(state->pp_buf, "\n", PAGE_SIZE);
return 1;
}

View File

@ -0,0 +1,2 @@
int cmdline_partition(struct parsed_partitions *state);

View File

@ -25,6 +25,9 @@
* TODO:
*
* Changelog:
* Mon August 5th, 2013 Davidlohr Bueso <davidlohr@hp.com>
* - detect hybrid MBRs, tighter pMBR checking & cleanups.
*
* Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com>
* - test for valid PMBR and valid PGPT before ever reading
* AGPT, allow override with 'gpt' kernel command line option.
@ -149,34 +152,80 @@ static u64 last_lba(struct block_device *bdev)
bdev_logical_block_size(bdev)) - 1ULL;
}
static inline int
pmbr_part_valid(struct partition *part)
static inline int pmbr_part_valid(gpt_mbr_record *part)
{
if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
le32_to_cpu(part->start_sect) == 1UL)
return 1;
return 0;
if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT)
goto invalid;
/* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */
if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA)
goto invalid;
return GPT_MBR_PROTECTIVE;
invalid:
return 0;
}
/**
* is_pmbr_valid(): test Protective MBR for validity
* @mbr: pointer to a legacy mbr structure
* @total_sectors: amount of sectors in the device
*
* Description: Returns 1 if PMBR is valid, 0 otherwise.
* Validity depends on two things:
* Description: Checks for a valid protective or hybrid
* master boot record (MBR). The validity of a pMBR depends
* on all of the following properties:
* 1) MSDOS signature is in the last two bytes of the MBR
* 2) One partition of type 0xEE is found
*
* In addition, a hybrid MBR will have up to three additional
* primary partitions, which point to the same space that's
* marked out by up to three GPT partitions.
*
* Returns 0 upon invalid MBR, or GPT_MBR_PROTECTIVE or
* GPT_MBR_HYBRID depending on the device layout.
*/
static int
is_pmbr_valid(legacy_mbr *mbr)
static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors)
{
int i;
int i, part = 0, ret = 0; /* invalid by default */
if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
return 0;
goto done;
for (i = 0; i < 4; i++) {
ret = pmbr_part_valid(&mbr->partition_record[i]);
if (ret == GPT_MBR_PROTECTIVE) {
part = i;
/*
* Ok, we at least know that there's a protective MBR,
* now check if there are other partition types for
* hybrid MBR.
*/
goto check_hybrid;
}
}
if (ret != GPT_MBR_PROTECTIVE)
goto done;
check_hybrid:
for (i = 0; i < 4; i++)
if (pmbr_part_valid(&mbr->partition_record[i]))
return 1;
return 0;
if ((mbr->partition_record[i].os_type !=
EFI_PMBR_OSTYPE_EFI_GPT) &&
(mbr->partition_record[i].os_type != 0x00))
ret = GPT_MBR_HYBRID;
/*
* Protective MBRs take up the lesser of the whole disk
* or 2 TiB (32bit LBA), ignoring the rest of the disk.
*
* Hybrid MBRs do not necessarily comply with this.
*/
if (ret == GPT_MBR_PROTECTIVE) {
if (le32_to_cpu(mbr->partition_record[part].size_in_lba) !=
min((uint32_t) total_sectors - 1, 0xFFFFFFFF))
ret = 0;
}
done:
return ret;
}
/**
@ -243,8 +292,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
return NULL;
if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba),
(u8 *) pte,
count) < count) {
(u8 *) pte, count) < count) {
kfree(pte);
pte=NULL;
return NULL;
@ -364,7 +412,12 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
(unsigned long long)lastlba);
goto fail;
}
if (le64_to_cpu((*gpt)->last_usable_lba) < le64_to_cpu((*gpt)->first_usable_lba)) {
pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
(unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
(unsigned long long)le64_to_cpu((*gpt)->first_usable_lba));
goto fail;
}
/* Check that sizeof_partition_entry has the correct value */
if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
pr_debug("GUID Partitition Entry Size check failed.\n");
@ -429,44 +482,42 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
if (!pgpt || !agpt)
return;
if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
printk(KERN_WARNING
"GPT:Primary header LBA != Alt. header alternate_lba\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:Primary header LBA != Alt. header alternate_lba\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(pgpt->my_lba),
(unsigned long long)le64_to_cpu(agpt->alternate_lba));
error_found++;
}
if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
printk(KERN_WARNING
"GPT:Primary header alternate_lba != Alt. header my_lba\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
(unsigned long long)le64_to_cpu(agpt->my_lba));
error_found++;
}
if (le64_to_cpu(pgpt->first_usable_lba) !=
le64_to_cpu(agpt->first_usable_lba)) {
printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:first_usable_lbas don't match.\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
(unsigned long long)le64_to_cpu(agpt->first_usable_lba));
error_found++;
}
if (le64_to_cpu(pgpt->last_usable_lba) !=
le64_to_cpu(agpt->last_usable_lba)) {
printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:last_usable_lbas don't match.\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
(unsigned long long)le64_to_cpu(agpt->last_usable_lba));
error_found++;
}
if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
printk(KERN_WARNING "GPT:disk_guids don't match.\n");
pr_warn("GPT:disk_guids don't match.\n");
error_found++;
}
if (le32_to_cpu(pgpt->num_partition_entries) !=
le32_to_cpu(agpt->num_partition_entries)) {
printk(KERN_WARNING "GPT:num_partition_entries don't match: "
pr_warn("GPT:num_partition_entries don't match: "
"0x%x != 0x%x\n",
le32_to_cpu(pgpt->num_partition_entries),
le32_to_cpu(agpt->num_partition_entries));
@ -474,8 +525,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
}
if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
le32_to_cpu(agpt->sizeof_partition_entry)) {
printk(KERN_WARNING
"GPT:sizeof_partition_entry values don't match: "
pr_warn("GPT:sizeof_partition_entry values don't match: "
"0x%x != 0x%x\n",
le32_to_cpu(pgpt->sizeof_partition_entry),
le32_to_cpu(agpt->sizeof_partition_entry));
@ -483,34 +533,30 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
}
if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
le32_to_cpu(agpt->partition_entry_array_crc32)) {
printk(KERN_WARNING
"GPT:partition_entry_array_crc32 values don't match: "
pr_warn("GPT:partition_entry_array_crc32 values don't match: "
"0x%x != 0x%x\n",
le32_to_cpu(pgpt->partition_entry_array_crc32),
le32_to_cpu(agpt->partition_entry_array_crc32));
error_found++;
}
if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
printk(KERN_WARNING
"GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(pgpt->alternate_lba),
(unsigned long long)lastlba);
error_found++;
}
if (le64_to_cpu(agpt->my_lba) != lastlba) {
printk(KERN_WARNING
"GPT:Alternate GPT header not at the end of the disk.\n");
printk(KERN_WARNING "GPT:%lld != %lld\n",
pr_warn("GPT:Alternate GPT header not at the end of the disk.\n");
pr_warn("GPT:%lld != %lld\n",
(unsigned long long)le64_to_cpu(agpt->my_lba),
(unsigned long long)lastlba);
error_found++;
}
if (error_found)
printk(KERN_WARNING
"GPT: Use GNU Parted to correct GPT errors.\n");
pr_warn("GPT: Use GNU Parted to correct GPT errors.\n");
return;
}
@ -536,6 +582,7 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
legacy_mbr *legacymbr;
sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9;
u64 lastlba;
if (!ptes)
@ -543,17 +590,22 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
lastlba = last_lba(state->bdev);
if (!force_gpt) {
/* This will be added to the EFI Spec. per Intel after v1.02. */
legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL);
if (legacymbr) {
read_lba(state, 0, (u8 *) legacymbr,
sizeof (*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr);
}
if (!good_pmbr)
goto fail;
}
/* This will be added to the EFI Spec. per Intel after v1.02. */
legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL);
if (!legacymbr)
goto fail;
read_lba(state, 0, (u8 *)legacymbr, sizeof(*legacymbr));
good_pmbr = is_pmbr_valid(legacymbr, total_sectors);
kfree(legacymbr);
if (!good_pmbr)
goto fail;
pr_debug("Device has a %s MBR\n",
good_pmbr == GPT_MBR_PROTECTIVE ?
"protective" : "hybrid");
}
good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA,
&pgpt, &pptes);
@ -576,11 +628,8 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
*ptes = pptes;
kfree(agpt);
kfree(aptes);
if (!good_agpt) {
printk(KERN_WARNING
"Alternate GPT is invalid, "
"using primary GPT.\n");
}
if (!good_agpt)
pr_warn("Alternate GPT is invalid, using primary GPT.\n");
return 1;
}
else if (good_agpt) {
@ -588,8 +637,7 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
*ptes = aptes;
kfree(pgpt);
kfree(pptes);
printk(KERN_WARNING
"Primary GPT is invalid, using alternate GPT.\n");
pr_warn("Primary GPT is invalid, using alternate GPT.\n");
return 1;
}
@ -651,8 +699,7 @@ int efi_partition(struct parsed_partitions *state)
put_partition(state, i+1, start * ssz, size * ssz);
/* If this is a RAID volume, tell md */
if (!efi_guidcmp(ptes[i].partition_type_guid,
PARTITION_LINUX_RAID_GUID))
if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID))
state->parts[i + 1].flags = ADDPART_FLAG_RAID;
info = &state->parts[i + 1].info;

View File

@ -37,6 +37,9 @@
#define EFI_PMBR_OSTYPE_EFI 0xEF
#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
#define GPT_MBR_PROTECTIVE 1
#define GPT_MBR_HYBRID 2
#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
#define GPT_HEADER_REVISION_V1 0x00010000
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
@ -101,11 +104,25 @@ typedef struct _gpt_entry {
efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
} __attribute__ ((packed)) gpt_entry;
typedef struct _gpt_mbr_record {
u8 boot_indicator; /* unused by EFI, set to 0x80 for bootable */
u8 start_head; /* unused by EFI, pt start in CHS */
u8 start_sector; /* unused by EFI, pt start in CHS */
u8 start_track;
u8 os_type; /* EFI and legacy non-EFI OS types */
u8 end_head; /* unused by EFI, pt end in CHS */
u8 end_sector; /* unused by EFI, pt end in CHS */
u8 end_track; /* unused by EFI, pt end in CHS */
__le32 starting_lba; /* used by EFI - start addr of the on disk pt */
__le32 size_in_lba; /* used by EFI - size of pt in LBA */
} __packed gpt_mbr_record;
typedef struct _legacy_mbr {
u8 boot_code[440];
__le32 unique_mbr_signature;
__le16 unknown;
struct partition partition_record[4];
gpt_mbr_record partition_record[4];
__le16 signature;
} __attribute__ ((packed)) legacy_mbr;
@ -113,22 +130,3 @@ typedef struct _legacy_mbr {
extern int efi_partition(struct parsed_partitions *state);
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* --------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */
#define VERSION "83"
#define VERSION "85"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
@ -169,6 +169,7 @@ struct aoedev {
ulong ref;
struct work_struct work;/* disk create work struct */
struct gendisk *gd;
struct dentry *debugfs;
struct request_queue *blkq;
struct hd_geometry geo;
sector_t ssize;
@ -206,6 +207,7 @@ struct ktstate {
int aoeblk_init(void);
void aoeblk_exit(void);
void aoeblk_gdalloc(void *);
void aoedisk_rm_debugfs(struct aoedev *d);
void aoedisk_rm_sysfs(struct aoedev *d);
int aoechr_init(void);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */
/* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoeblk.c
* block device routines
@ -17,11 +17,13 @@
#include <linux/mutex.h>
#include <linux/export.h>
#include <linux/moduleparam.h>
#include <linux/debugfs.h>
#include <scsi/sg.h>
#include "aoe.h"
static DEFINE_MUTEX(aoeblk_mutex);
static struct kmem_cache *buf_pool_cache;
static struct dentry *aoe_debugfs_dir;
/* GPFS needs a larger value than the default. */
static int aoe_maxsectors;
@ -108,6 +110,55 @@ static ssize_t aoedisk_show_payload(struct device *dev,
return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt);
}
static int aoedisk_debugfs_show(struct seq_file *s, void *ignored)
{
struct aoedev *d;
struct aoetgt **t, **te;
struct aoeif *ifp, *ife;
unsigned long flags;
char c;
d = s->private;
seq_printf(s, "rttavg: %d rttdev: %d\n",
d->rttavg >> RTTSCALE,
d->rttdev >> RTTDSCALE);
seq_printf(s, "nskbpool: %d\n", skb_queue_len(&d->skbpool));
seq_printf(s, "kicked: %ld\n", d->kicked);
seq_printf(s, "maxbcnt: %ld\n", d->maxbcnt);
seq_printf(s, "ref: %ld\n", d->ref);
spin_lock_irqsave(&d->lock, flags);
t = d->targets;
te = t + d->ntargets;
for (; t < te && *t; t++) {
c = '\t';
seq_printf(s, "falloc: %ld\n", (*t)->falloc);
seq_printf(s, "ffree: %p\n",
list_empty(&(*t)->ffree) ? NULL : (*t)->ffree.next);
seq_printf(s, "%pm:%d:%d:%d\n", (*t)->addr, (*t)->nout,
(*t)->maxout, (*t)->nframes);
seq_printf(s, "\tssthresh:%d\n", (*t)->ssthresh);
seq_printf(s, "\ttaint:%d\n", (*t)->taint);
seq_printf(s, "\tr:%d\n", (*t)->rpkts);
seq_printf(s, "\tw:%d\n", (*t)->wpkts);
ifp = (*t)->ifs;
ife = ifp + ARRAY_SIZE((*t)->ifs);
for (; ifp->nd && ifp < ife; ifp++) {
seq_printf(s, "%c%s", c, ifp->nd->name);
c = ',';
}
seq_puts(s, "\n");
}
spin_unlock_irqrestore(&d->lock, flags);
return 0;
}
static int aoe_debugfs_open(struct inode *inode, struct file *file)
{
return single_open(file, aoedisk_debugfs_show, inode->i_private);
}
static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
@ -130,6 +181,44 @@ static const struct attribute_group attr_group = {
.attrs = aoe_attrs,
};
static const struct file_operations aoe_debugfs_fops = {
.open = aoe_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void
aoedisk_add_debugfs(struct aoedev *d)
{
struct dentry *entry;
char *p;
if (aoe_debugfs_dir == NULL)
return;
p = strchr(d->gd->disk_name, '/');
if (p == NULL)
p = d->gd->disk_name;
else
p++;
BUG_ON(*p == '\0');
entry = debugfs_create_file(p, 0444, aoe_debugfs_dir, d,
&aoe_debugfs_fops);
if (IS_ERR_OR_NULL(entry)) {
pr_info("aoe: cannot create debugfs file for %s\n",
d->gd->disk_name);
return;
}
BUG_ON(d->debugfs);
d->debugfs = entry;
}
void
aoedisk_rm_debugfs(struct aoedev *d)
{
debugfs_remove(d->debugfs);
d->debugfs = NULL;
}
static int
aoedisk_add_sysfs(struct aoedev *d)
{
@ -330,6 +419,7 @@ aoeblk_gdalloc(void *vp)
add_disk(gd);
aoedisk_add_sysfs(d);
aoedisk_add_debugfs(d);
spin_lock_irqsave(&d->lock, flags);
WARN_ON(!(d->flags & DEVFL_GD_NOW));
@ -351,6 +441,8 @@ err:
void
aoeblk_exit(void)
{
debugfs_remove_recursive(aoe_debugfs_dir);
aoe_debugfs_dir = NULL;
kmem_cache_destroy(buf_pool_cache);
}
@ -362,7 +454,11 @@ aoeblk_init(void)
0, 0, NULL);
if (buf_pool_cache == NULL)
return -ENOMEM;
aoe_debugfs_dir = debugfs_create_dir("aoe", NULL);
if (IS_ERR_OR_NULL(aoe_debugfs_dir)) {
pr_info("aoe: cannot create debugfs directory\n");
aoe_debugfs_dir = NULL;
}
return 0;
}

View File

@ -380,7 +380,6 @@ aoecmd_ata_rw(struct aoedev *d)
{
struct frame *f;
struct buf *buf;
struct aoetgt *t;
struct sk_buff *skb;
struct sk_buff_head queue;
ulong bcnt, fbcnt;
@ -391,7 +390,6 @@ aoecmd_ata_rw(struct aoedev *d)
f = newframe(d);
if (f == NULL)
return 0;
t = *d->tgt;
bcnt = d->maxbcnt;
if (bcnt == 0)
bcnt = DEFAULTBCNT;
@ -485,7 +483,6 @@ resend(struct aoedev *d, struct frame *f)
struct sk_buff *skb;
struct sk_buff_head queue;
struct aoe_hdr *h;
struct aoe_atahdr *ah;
struct aoetgt *t;
char buf[128];
u32 n;
@ -500,7 +497,6 @@ resend(struct aoedev *d, struct frame *f)
return;
}
h = (struct aoe_hdr *) skb_mac_header(skb);
ah = (struct aoe_atahdr *) (h+1);
if (!(f->flags & FFL_PROBE)) {
snprintf(buf, sizeof(buf),

View File

@ -12,6 +12,7 @@
#include <linux/bitmap.h>
#include <linux/kdev_t.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include "aoe.h"
static void dummy_timer(ulong);
@ -241,16 +242,12 @@ aoedev_downdev(struct aoedev *d)
static int
user_req(char *s, size_t slen, struct aoedev *d)
{
char *p;
const char *p;
size_t lim;
if (!d->gd)
return 0;
p = strrchr(d->gd->disk_name, '/');
if (!p)
p = d->gd->disk_name;
else
p += 1;
p = kbasename(d->gd->disk_name);
lim = sizeof(d->gd->disk_name);
lim -= p - d->gd->disk_name;
if (slen < lim)
@ -278,6 +275,7 @@ freedev(struct aoedev *d)
del_timer_sync(&d->timer);
if (d->gd) {
aoedisk_rm_debugfs(d);
aoedisk_rm_sysfs(d);
del_gendisk(d->gd);
put_disk(d->gd);

View File

@ -4257,6 +4257,13 @@ static void cciss_find_board_params(ctlr_info_t *h)
cciss_get_max_perf_mode_cmds(h);
h->nr_cmds = h->max_commands - 4 - cciss_tape_cmds;
h->maxsgentries = readl(&(h->cfgtable->MaxSGElements));
/*
* The P600 may exhibit poor performnace under some workloads
* if we use the value in the configuration table. Limit this
* controller to MAXSGENTRIES (32) instead.
*/
if (h->board_id == 0x3225103C)
h->maxsgentries = MAXSGENTRIES;
/*
* Limit in-command s/g elements to 32 save dma'able memory.
* Howvever spec says if 0, use 31

View File

@ -636,7 +636,7 @@ ok_to_write:
mg_request(host->breq);
}
void mg_times_out(unsigned long data)
static void mg_times_out(unsigned long data)
{
struct mg_host *host = (struct mg_host *)data;
char *name;

View File

@ -598,7 +598,7 @@ static ssize_t class_osdblk_remove(struct class *c,
unsigned long ul;
struct list_head *tmp;
rc = strict_strtoul(buf, 10, &ul);
rc = kstrtoul(buf, 10, &ul);
if (rc)
return rc;

View File

@ -44,6 +44,8 @@
*
*************************************************************************/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/pktcdvd.h>
#include <linux/module.h>
#include <linux/types.h>
@ -69,23 +71,24 @@
#define DRIVER_NAME "pktcdvd"
#if PACKET_DEBUG
#define DPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
#else
#define DPRINTK(fmt, args...)
#endif
#define pkt_err(pd, fmt, ...) \
pr_err("%s: " fmt, pd->name, ##__VA_ARGS__)
#define pkt_notice(pd, fmt, ...) \
pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__)
#define pkt_info(pd, fmt, ...) \
pr_info("%s: " fmt, pd->name, ##__VA_ARGS__)
#if PACKET_DEBUG > 1
#define VPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
#else
#define VPRINTK(fmt, args...)
#endif
#define pkt_dbg(level, pd, fmt, ...) \
do { \
if (level == 2 && PACKET_DEBUG >= 2) \
pr_notice("%s: %s():" fmt, \
pd->name, __func__, ##__VA_ARGS__); \
else if (level == 1 && PACKET_DEBUG >= 1) \
pr_notice("%s: " fmt, pd->name, ##__VA_ARGS__); \
} while (0)
#define MAX_SPEED 0xffff
#define ZONE(sector, pd) (((sector) + (pd)->offset) & \
~(sector_t)((pd)->settings.size - 1))
static DEFINE_MUTEX(pktcdvd_mutex);
static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
static struct proc_dir_entry *pkt_proc;
@ -103,7 +106,10 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
static int pkt_remove_dev(dev_t pkt_dev);
static int pkt_seq_show(struct seq_file *m, void *p);
static sector_t get_zone(sector_t sector, struct pktcdvd_device *pd)
{
return (sector + pd->offset) & ~(sector_t)(pd->settings.size - 1);
}
/*
* create and register a pktcdvd kernel object.
@ -424,7 +430,7 @@ static int pkt_sysfs_init(void)
if (ret) {
kfree(class_pktcdvd);
class_pktcdvd = NULL;
printk(DRIVER_NAME": failed to create class pktcdvd\n");
pr_err("failed to create class pktcdvd\n");
return ret;
}
return 0;
@ -517,7 +523,7 @@ static void pkt_bio_finished(struct pktcdvd_device *pd)
{
BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0);
if (atomic_dec_and_test(&pd->cdrw.pending_bios)) {
VPRINTK(DRIVER_NAME": queue empty\n");
pkt_dbg(2, pd, "queue empty\n");
atomic_set(&pd->iosched.attention, 1);
wake_up(&pd->wqueue);
}
@ -734,36 +740,33 @@ out:
return ret;
}
static const char *sense_key_string(__u8 index)
{
static const char * const info[] = {
"No sense", "Recovered error", "Not ready",
"Medium error", "Hardware error", "Illegal request",
"Unit attention", "Data protect", "Blank check",
};
return index < ARRAY_SIZE(info) ? info[index] : "INVALID";
}
/*
* A generic sense dump / resolve mechanism should be implemented across
* all ATAPI + SCSI devices.
*/
static void pkt_dump_sense(struct packet_command *cgc)
static void pkt_dump_sense(struct pktcdvd_device *pd,
struct packet_command *cgc)
{
static char *info[9] = { "No sense", "Recovered error", "Not ready",
"Medium error", "Hardware error", "Illegal request",
"Unit attention", "Data protect", "Blank check" };
int i;
struct request_sense *sense = cgc->sense;
printk(DRIVER_NAME":");
for (i = 0; i < CDROM_PACKET_SIZE; i++)
printk(" %02x", cgc->cmd[i]);
printk(" - ");
if (sense == NULL) {
printk("no sense\n");
return;
}
printk("sense %02x.%02x.%02x", sense->sense_key, sense->asc, sense->ascq);
if (sense->sense_key > 8) {
printk(" (INVALID)\n");
return;
}
printk(" (%s)\n", info[sense->sense_key]);
if (sense)
pkt_err(pd, "%*ph - sense %02x.%02x.%02x (%s)\n",
CDROM_PACKET_SIZE, cgc->cmd,
sense->sense_key, sense->asc, sense->ascq,
sense_key_string(sense->sense_key));
else
pkt_err(pd, "%*ph - no sense\n", CDROM_PACKET_SIZE, cgc->cmd);
}
/*
@ -806,7 +809,7 @@ static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
cgc.cmd[5] = write_speed & 0xff;
if ((ret = pkt_generic_packet(pd, &cgc)))
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
@ -872,7 +875,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
need_write_seek = 0;
if (need_write_seek && reads_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
VPRINTK(DRIVER_NAME": write, waiting\n");
pkt_dbg(2, pd, "write, waiting\n");
break;
}
pkt_flush_cache(pd);
@ -881,7 +884,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
} else {
if (!reads_queued && writes_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
VPRINTK(DRIVER_NAME": read, waiting\n");
pkt_dbg(2, pd, "read, waiting\n");
break;
}
pd->iosched.writing = 1;
@ -943,7 +946,7 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_que
set_bit(PACKET_MERGE_SEGS, &pd->flags);
return 0;
} else {
printk(DRIVER_NAME": cdrom max_phys_segments too small\n");
pkt_err(pd, "cdrom max_phys_segments too small\n");
return -EIO;
}
}
@ -987,8 +990,9 @@ static void pkt_end_io_read(struct bio *bio, int err)
struct pktcdvd_device *pd = pkt->pd;
BUG_ON(!pd);
VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio,
(unsigned long long)pkt->sector, (unsigned long long)bio->bi_sector, err);
pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n",
bio, (unsigned long long)pkt->sector,
(unsigned long long)bio->bi_sector, err);
if (err)
atomic_inc(&pkt->io_errors);
@ -1005,7 +1009,7 @@ static void pkt_end_io_packet_write(struct bio *bio, int err)
struct pktcdvd_device *pd = pkt->pd;
BUG_ON(!pd);
VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt->id, err);
pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, err);
pd->stats.pkt_ended++;
@ -1047,7 +1051,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
spin_unlock(&pkt->lock);
if (pkt->cache_valid) {
VPRINTK("pkt_gather_data: zone %llx cached\n",
pkt_dbg(2, pd, "zone %llx cached\n",
(unsigned long long)pkt->sector);
goto out_account;
}
@ -1070,7 +1074,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
p = (f * CD_FRAMESIZE) / PAGE_SIZE;
offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
VPRINTK("pkt_gather_data: Adding frame %d, page:%p offs:%d\n",
pkt_dbg(2, pd, "Adding frame %d, page:%p offs:%d\n",
f, pkt->pages[p], offset);
if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset))
BUG();
@ -1082,7 +1086,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
}
out_account:
VPRINTK("pkt_gather_data: need %d frames for zone %llx\n",
pkt_dbg(2, pd, "need %d frames for zone %llx\n",
frames_read, (unsigned long long)pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
@ -1183,7 +1187,8 @@ static inline void pkt_set_state(struct packet_data *pkt, enum packet_data_state
"IDLE", "WAITING", "READ_WAIT", "WRITE_WAIT", "RECOVERY", "FINISHED"
};
enum packet_data_state old_state = pkt->state;
VPRINTK("pkt %2d : s=%6llx %s -> %s\n", pkt->id, (unsigned long long)pkt->sector,
pkt_dbg(2, pd, "pkt %2d : s=%6llx %s -> %s\n",
pkt->id, (unsigned long long)pkt->sector,
state_name[old_state], state_name[state]);
#endif
pkt->state = state;
@ -1202,12 +1207,10 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
struct rb_node *n;
int wakeup;
VPRINTK("handle_queue\n");
atomic_set(&pd->scan_queue, 0);
if (list_empty(&pd->cdrw.pkt_free_list)) {
VPRINTK("handle_queue: no pkt\n");
pkt_dbg(2, pd, "no pkt\n");
return 0;
}
@ -1224,7 +1227,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
node = first_node;
while (node) {
bio = node->bio;
zone = ZONE(bio->bi_sector, pd);
zone = get_zone(bio->bi_sector, pd);
list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
if (p->sector == zone) {
bio = NULL;
@ -1244,7 +1247,7 @@ try_next_bio:
}
spin_unlock(&pd->lock);
if (!bio) {
VPRINTK("handle_queue: no bio\n");
pkt_dbg(2, pd, "no bio\n");
return 0;
}
@ -1260,12 +1263,12 @@ try_next_bio:
* to this packet.
*/
spin_lock(&pd->lock);
VPRINTK("pkt_handle_queue: looking for zone %llx\n", (unsigned long long)zone);
pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone);
while ((node = pkt_rbtree_find(pd, zone)) != NULL) {
bio = node->bio;
VPRINTK("pkt_handle_queue: found zone=%llx\n",
(unsigned long long)ZONE(bio->bi_sector, pd));
if (ZONE(bio->bi_sector, pd) != zone)
pkt_dbg(2, pd, "found zone=%llx\n",
(unsigned long long)get_zone(bio->bi_sector, pd));
if (get_zone(bio->bi_sector, pd) != zone)
break;
pkt_rbtree_erase(pd, node);
spin_lock(&pkt->lock);
@ -1316,7 +1319,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
}
VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);
pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
/*
* Fill-in bvec with data from orig_bios.
@ -1327,7 +1330,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE);
spin_unlock(&pkt->lock);
VPRINTK("pkt_start_write: Writing %d frames for zone %llx\n",
pkt_dbg(2, pd, "Writing %d frames for zone %llx\n",
pkt->write_size, (unsigned long long)pkt->sector);
if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
@ -1359,7 +1362,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
{
int uptodate;
VPRINTK("run_state_machine: pkt %d\n", pkt->id);
pkt_dbg(2, pd, "pkt %d\n", pkt->id);
for (;;) {
switch (pkt->state) {
@ -1398,7 +1401,7 @@ static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data
if (pkt_start_recovery(pkt)) {
pkt_start_write(pd, pkt);
} else {
VPRINTK("No recovery possible\n");
pkt_dbg(2, pd, "No recovery possible\n");
pkt_set_state(pkt, PACKET_FINISHED_STATE);
}
break;
@ -1419,8 +1422,6 @@ static void pkt_handle_packets(struct pktcdvd_device *pd)
{
struct packet_data *pkt, *next;
VPRINTK("pkt_handle_packets\n");
/*
* Run state machine for active packets
*/
@ -1502,9 +1503,9 @@ static int kcdrwd(void *foobar)
if (PACKET_DEBUG > 1) {
int states[PACKET_NUM_STATES];
pkt_count_states(pd, states);
VPRINTK("kcdrwd: i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
states[0], states[1], states[2], states[3],
states[4], states[5]);
pkt_dbg(2, pd, "i:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
states[0], states[1], states[2],
states[3], states[4], states[5]);
}
min_sleep_time = MAX_SCHEDULE_TIMEOUT;
@ -1513,9 +1514,9 @@ static int kcdrwd(void *foobar)
min_sleep_time = pkt->sleep_time;
}
VPRINTK("kcdrwd: sleeping\n");
pkt_dbg(2, pd, "sleeping\n");
residue = schedule_timeout(min_sleep_time);
VPRINTK("kcdrwd: wake up\n");
pkt_dbg(2, pd, "wake up\n");
/* make swsusp happy with our thread */
try_to_freeze();
@ -1563,9 +1564,10 @@ work_to_do:
static void pkt_print_settings(struct pktcdvd_device *pd)
{
printk(DRIVER_NAME": %s packets, ", pd->settings.fp ? "Fixed" : "Variable");
printk("%u blocks, ", pd->settings.size >> 2);
printk("Mode-%c disc\n", pd->settings.block_mode == 8 ? '1' : '2');
pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n",
pd->settings.fp ? "Fixed" : "Variable",
pd->settings.size >> 2,
pd->settings.block_mode == 8 ? '1' : '2');
}
static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, int page_code, int page_control)
@ -1699,7 +1701,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ);
cgc.sense = &sense;
if ((ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
@ -1714,7 +1716,7 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ);
cgc.sense = &sense;
if ((ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
@ -1749,14 +1751,14 @@ static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
/*
* paranoia
*/
printk(DRIVER_NAME": write mode wrong %d\n", wp->data_block_type);
pkt_err(pd, "write mode wrong %d\n", wp->data_block_type);
return 1;
}
wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
cgc.buflen = cgc.cmd[8] = size;
if ((ret = pkt_mode_select(pd, &cgc))) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
@ -1793,7 +1795,7 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
if (ti->rt == 1 && ti->blank == 0)
return 1;
printk(DRIVER_NAME": bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
return 0;
}
@ -1811,7 +1813,8 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x12: /* DVD-RAM */
return 1;
default:
VPRINTK(DRIVER_NAME": Wrong disc profile (%x)\n", pd->mmc3_profile);
pkt_dbg(2, pd, "Wrong disc profile (%x)\n",
pd->mmc3_profile);
return 0;
}
@ -1820,22 +1823,22 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
* but i'm not sure, should we leave this to user apps? probably.
*/
if (di->disc_type == 0xff) {
printk(DRIVER_NAME": Unknown disc. No track?\n");
pkt_notice(pd, "unknown disc - no track?\n");
return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
printk(DRIVER_NAME": Wrong disc type (%x)\n", di->disc_type);
pkt_err(pd, "wrong disc type (%x)\n", di->disc_type);
return 0;
}
if (di->erasable == 0) {
printk(DRIVER_NAME": Disc not erasable\n");
pkt_notice(pd, "disc not erasable\n");
return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
printk(DRIVER_NAME": Can't write to last track (reserved)\n");
pkt_err(pd, "can't write to last track (reserved)\n");
return 0;
}
@ -1860,7 +1863,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
memset(&ti, 0, sizeof(track_information));
if ((ret = pkt_get_disc_info(pd, &di))) {
printk("failed get_disc\n");
pkt_err(pd, "failed get_disc\n");
return ret;
}
@ -1871,12 +1874,12 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
if ((ret = pkt_get_track_info(pd, track, 1, &ti))) {
printk(DRIVER_NAME": failed get_track\n");
pkt_err(pd, "failed get_track\n");
return ret;
}
if (!pkt_writable_track(pd, &ti)) {
printk(DRIVER_NAME": can't write to this track\n");
pkt_err(pd, "can't write to this track\n");
return -EROFS;
}
@ -1886,11 +1889,11 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
*/
pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
if (pd->settings.size == 0) {
printk(DRIVER_NAME": detected zero packet size!\n");
pkt_notice(pd, "detected zero packet size!\n");
return -ENXIO;
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
printk(DRIVER_NAME": packet size is too big\n");
pkt_err(pd, "packet size is too big\n");
return -EROFS;
}
pd->settings.fp = ti.fp;
@ -1932,7 +1935,7 @@ static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
pd->settings.block_mode = PACKET_BLOCK_MODE2;
break;
default:
printk(DRIVER_NAME": unknown data mode\n");
pkt_err(pd, "unknown data mode\n");
return -EROFS;
}
return 0;
@ -1966,10 +1969,10 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd,
cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
ret = pkt_mode_select(pd, &cgc);
if (ret) {
printk(DRIVER_NAME": write caching control failed\n");
pkt_dump_sense(&cgc);
pkt_err(pd, "write caching control failed\n");
pkt_dump_sense(pd, &cgc);
} else if (!ret && set)
printk(DRIVER_NAME": enabled write caching on %s\n", pd->name);
pkt_notice(pd, "enabled write caching\n");
return ret;
}
@ -2005,7 +2008,7 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd,
sizeof(struct mode_page_header);
ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
if (ret) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
}
@ -2064,7 +2067,7 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
cgc.cmd[8] = 2;
ret = pkt_generic_packet(pd, &cgc);
if (ret) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
size = ((unsigned int) buf[0]<<8) + buf[1] + 2;
@ -2079,16 +2082,16 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
cgc.cmd[8] = size;
ret = pkt_generic_packet(pd, &cgc);
if (ret) {
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
if (!(buf[6] & 0x40)) {
printk(DRIVER_NAME": Disc type is not CD-RW\n");
pkt_notice(pd, "disc type is not CD-RW\n");
return 1;
}
if (!(buf[6] & 0x4)) {
printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n");
pkt_notice(pd, "A1 values on media are not valid, maybe not CDRW?\n");
return 1;
}
@ -2108,14 +2111,14 @@ static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
*speed = us_clv_to_speed[sp];
break;
default:
printk(DRIVER_NAME": Unknown disc sub-type %d\n",st);
pkt_notice(pd, "unknown disc sub-type %d\n", st);
return 1;
}
if (*speed) {
printk(DRIVER_NAME": Max. media speed: %d\n",*speed);
pkt_info(pd, "maximum media speed: %d\n", *speed);
return 0;
} else {
printk(DRIVER_NAME": Unknown speed %d for sub-type %d\n",sp,st);
pkt_notice(pd, "unknown speed %d for sub-type %d\n", sp, st);
return 1;
}
}
@ -2126,7 +2129,7 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
struct request_sense sense;
int ret;
VPRINTK(DRIVER_NAME": Performing OPC\n");
pkt_dbg(2, pd, "Performing OPC\n");
init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
cgc.sense = &sense;
@ -2134,7 +2137,7 @@ static noinline_for_stack int pkt_perform_opc(struct pktcdvd_device *pd)
cgc.cmd[0] = GPCMD_SEND_OPC;
cgc.cmd[1] = 1;
if ((ret = pkt_generic_packet(pd, &cgc)))
pkt_dump_sense(&cgc);
pkt_dump_sense(pd, &cgc);
return ret;
}
@ -2144,12 +2147,12 @@ static int pkt_open_write(struct pktcdvd_device *pd)
unsigned int write_speed, media_write_speed, read_speed;
if ((ret = pkt_probe_settings(pd))) {
VPRINTK(DRIVER_NAME": %s failed probe\n", pd->name);
pkt_dbg(2, pd, "failed probe\n");
return ret;
}
if ((ret = pkt_set_write_settings(pd))) {
DPRINTK(DRIVER_NAME": %s failed saving write settings\n", pd->name);
pkt_dbg(1, pd, "failed saving write settings\n");
return -EIO;
}
@ -2161,26 +2164,26 @@ static int pkt_open_write(struct pktcdvd_device *pd)
case 0x13: /* DVD-RW */
case 0x1a: /* DVD+RW */
case 0x12: /* DVD-RAM */
DPRINTK(DRIVER_NAME": write speed %ukB/s\n", write_speed);
pkt_dbg(1, pd, "write speed %ukB/s\n", write_speed);
break;
default:
if ((ret = pkt_media_speed(pd, &media_write_speed)))
media_write_speed = 16;
write_speed = min(write_speed, media_write_speed * 177);
DPRINTK(DRIVER_NAME": write speed %ux\n", write_speed / 176);
pkt_dbg(1, pd, "write speed %ux\n", write_speed / 176);
break;
}
read_speed = write_speed;
if ((ret = pkt_set_speed(pd, write_speed, read_speed))) {
DPRINTK(DRIVER_NAME": %s couldn't set write speed\n", pd->name);
pkt_dbg(1, pd, "couldn't set write speed\n");
return -EIO;
}
pd->write_speed = write_speed;
pd->read_speed = read_speed;
if ((ret = pkt_perform_opc(pd))) {
DPRINTK(DRIVER_NAME": %s Optimum Power Calibration failed\n", pd->name);
pkt_dbg(1, pd, "Optimum Power Calibration failed\n");
}
return 0;
@ -2205,7 +2208,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
goto out;
if ((ret = pkt_get_last_written(pd, &lba))) {
printk(DRIVER_NAME": pkt_get_last_written failed\n");
pkt_err(pd, "pkt_get_last_written failed\n");
goto out_putdev;
}
@ -2235,11 +2238,11 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
if (write) {
if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
printk(DRIVER_NAME": not enough memory for buffers\n");
pkt_err(pd, "not enough memory for buffers\n");
ret = -ENOMEM;
goto out_putdev;
}
printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
pkt_info(pd, "%lukB available on disc\n", lba << 1);
}
return 0;
@ -2257,7 +2260,7 @@ out:
static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
{
if (flush && pkt_flush_cache(pd))
DPRINTK(DRIVER_NAME": %s not flushing cache\n", pd->name);
pkt_dbg(1, pd, "not flushing cache\n");
pkt_lock_door(pd, 0);
@ -2279,8 +2282,6 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
struct pktcdvd_device *pd = NULL;
int ret;
VPRINTK(DRIVER_NAME": entering open\n");
mutex_lock(&pktcdvd_mutex);
mutex_lock(&ctl_mutex);
pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
@ -2315,7 +2316,6 @@ static int pkt_open(struct block_device *bdev, fmode_t mode)
out_dec:
pd->refcnt--;
out:
VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
mutex_unlock(&ctl_mutex);
mutex_unlock(&pktcdvd_mutex);
return ret;
@ -2360,7 +2360,8 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
pd = q->queuedata;
if (!pd) {
printk(DRIVER_NAME": %s incorrect request queue\n", bdevname(bio->bi_bdev, b));
pr_err("%s incorrect request queue\n",
bdevname(bio->bi_bdev, b));
goto end_io;
}
@ -2382,20 +2383,20 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
}
if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
printk(DRIVER_NAME": WRITE for ro device %s (%llu)\n",
pd->name, (unsigned long long)bio->bi_sector);
pkt_notice(pd, "WRITE for ro device (%llu)\n",
(unsigned long long)bio->bi_sector);
goto end_io;
}
if (!bio->bi_size || (bio->bi_size % CD_FRAMESIZE)) {
printk(DRIVER_NAME": wrong bio size\n");
pkt_err(pd, "wrong bio size\n");
goto end_io;
}
blk_queue_bounce(q, &bio);
zone = ZONE(bio->bi_sector, pd);
VPRINTK("pkt_make_request: start = %6llx stop = %6llx\n",
zone = get_zone(bio->bi_sector, pd);
pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
(unsigned long long)bio->bi_sector,
(unsigned long long)bio_end_sector(bio));
@ -2405,7 +2406,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
sector_t last_zone;
int first_sectors;
last_zone = ZONE(bio_end_sector(bio) - 1, pd);
last_zone = get_zone(bio_end_sector(bio) - 1, pd);
if (last_zone != zone) {
BUG_ON(last_zone != zone + pd->settings.size);
first_sectors = last_zone - bio->bi_sector;
@ -2500,7 +2501,7 @@ static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
struct bio_vec *bvec)
{
struct pktcdvd_device *pd = q->queuedata;
sector_t zone = ZONE(bmd->bi_sector, pd);
sector_t zone = get_zone(bmd->bi_sector, pd);
int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size;
int remaining = (pd->settings.size << 9) - used;
int remaining2;
@ -2609,7 +2610,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
struct block_device *bdev;
if (pd->pkt_dev == dev) {
printk(DRIVER_NAME": Recursive setup not allowed\n");
pkt_err(pd, "recursive setup not allowed\n");
return -EBUSY;
}
for (i = 0; i < MAX_WRITERS; i++) {
@ -2617,11 +2618,12 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
if (!pd2)
continue;
if (pd2->bdev->bd_dev == dev) {
printk(DRIVER_NAME": %s already setup\n", bdevname(pd2->bdev, b));
pkt_err(pd, "%s already setup\n",
bdevname(pd2->bdev, b));
return -EBUSY;
}
if (pd2->pkt_dev == dev) {
printk(DRIVER_NAME": Can't chain pktcdvd devices\n");
pkt_err(pd, "can't chain pktcdvd devices\n");
return -EBUSY;
}
}
@ -2644,13 +2646,13 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
atomic_set(&pd->cdrw.pending_bios, 0);
pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name);
if (IS_ERR(pd->cdrw.thread)) {
printk(DRIVER_NAME": can't start kernel thread\n");
pkt_err(pd, "can't start kernel thread\n");
ret = -ENOMEM;
goto out_mem;
}
proc_create_data(pd->name, 0, pkt_proc, &pkt_proc_fops, pd);
DPRINTK(DRIVER_NAME": writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
pkt_dbg(1, pd, "writer mapped to %s\n", bdevname(bdev, b));
return 0;
out_mem:
@ -2665,8 +2667,8 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
struct pktcdvd_device *pd = bdev->bd_disk->private_data;
int ret;
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
pkt_dbg(2, pd, "cmd %x, dev %d:%d\n",
cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
mutex_lock(&pktcdvd_mutex);
switch (cmd) {
@ -2690,7 +2692,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
break;
default:
VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd);
ret = -ENOTTY;
}
mutex_unlock(&pktcdvd_mutex);
@ -2743,7 +2745,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
if (!pkt_devs[idx])
break;
if (idx == MAX_WRITERS) {
printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS);
pr_err("max %d writers supported\n", MAX_WRITERS);
ret = -EBUSY;
goto out_mutex;
}
@ -2818,7 +2820,7 @@ out_mem:
kfree(pd);
out_mutex:
mutex_unlock(&ctl_mutex);
printk(DRIVER_NAME": setup of pktcdvd device failed\n");
pr_err("setup of pktcdvd device failed\n");
return ret;
}
@ -2839,7 +2841,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
break;
}
if (idx == MAX_WRITERS) {
DPRINTK(DRIVER_NAME": dev not setup\n");
pr_debug("dev not setup\n");
ret = -ENXIO;
goto out;
}
@ -2859,7 +2861,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
remove_proc_entry(pd->name, pkt_proc);
DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name);
pkt_dbg(1, pd, "writer unmapped\n");
del_gendisk(pd->disk);
blk_cleanup_queue(pd->disk->queue);
@ -2969,7 +2971,7 @@ static int __init pkt_init(void)
ret = register_blkdev(pktdev_major, DRIVER_NAME);
if (ret < 0) {
printk(DRIVER_NAME": Unable to register block device\n");
pr_err("unable to register block device\n");
goto out2;
}
if (!pktdev_major)
@ -2983,7 +2985,7 @@ static int __init pkt_init(void)
ret = misc_register(&pkt_misc);
if (ret) {
printk(DRIVER_NAME": Unable to register misc device\n");
pr_err("unable to register misc device\n");
goto out_misc;
}

View File

@ -5132,7 +5132,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
bool already = false;
int ret;
ret = strict_strtoul(buf, 10, &ul);
ret = kstrtoul(buf, 10, &ul);
if (ret)
return ret;

View File

@ -924,7 +924,6 @@ static int swim_probe(struct platform_device *dev)
return 0;
out_kfree:
platform_set_drvdata(dev, NULL);
kfree(swd);
out_iounmap:
iounmap(swim_base);
@ -962,7 +961,6 @@ static int swim_remove(struct platform_device *dev)
if (res)
release_mem_region(res->start, resource_size(res));
platform_set_drvdata(dev, NULL);
kfree(swd);
return 0;

View File

@ -620,7 +620,7 @@ static void backend_changed(struct xenbus_watch *watch,
}
/* Front end dir is a number, which is used as the handle. */
err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
err = kstrtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
if (err)
return;

View File

@ -766,6 +766,25 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
}
#endif
#ifdef CONFIG_PM_SLEEP
static int tpm_tis_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
int ret;
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
ret = tpm_pm_resume(dev);
if (!ret)
tpm_do_selftest(chip);
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
#ifdef CONFIG_PNP
static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
const struct pnp_device_id *pnp_id)
@ -787,26 +806,6 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
return tpm_tis_init(&pnp_dev->dev, start, len, irq);
}
static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
{
return tpm_pm_suspend(&dev->dev);
}
static int tpm_tis_pnp_resume(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);
int ret;
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
ret = tpm_pm_resume(&dev->dev);
if (!ret)
tpm_do_selftest(chip);
return ret;
}
static struct pnp_device_id tpm_pnp_tbl[] = {
{"PNP0C31", 0}, /* TPM */
{"ATM1200", 0}, /* Atmel */
@ -835,9 +834,12 @@ static struct pnp_driver tis_pnp_driver = {
.name = "tpm_tis",
.id_table = tpm_pnp_tbl,
.probe = tpm_tis_pnp_init,
.suspend = tpm_tis_pnp_suspend,
.resume = tpm_tis_pnp_resume,
.remove = tpm_tis_pnp_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &tpm_tis_pm,
},
#endif
};
#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
@ -846,20 +848,6 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
#endif
#ifdef CONFIG_PM_SLEEP
static int tpm_tis_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
return tpm_pm_resume(dev);
}
#endif
static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
static struct platform_driver tis_drv = {
.driver = {
.name = "tpm_tis",

View File

@ -14,7 +14,7 @@
* of and an antecedent to, SMBIOS, which stands for System
* Management BIOS. See further: http://www.dmtf.org/standards
*/
static char dmi_empty_string[] = " ";
static const char dmi_empty_string[] = " ";
static u16 __initdata dmi_ver;
/*
@ -49,7 +49,7 @@ static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
return "";
}
static char * __init dmi_string(const struct dmi_header *dm, u8 s)
static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
{
const char *bp = dmi_string_nosave(dm, s);
char *str;
@ -62,8 +62,6 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
str = dmi_alloc(len);
if (str != NULL)
strcpy(str, bp);
else
printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
return str;
}
@ -133,17 +131,18 @@ static int __init dmi_checksum(const u8 *buf, u8 len)
return sum == 0;
}
static char *dmi_ident[DMI_STRING_MAX];
static const char *dmi_ident[DMI_STRING_MAX];
static LIST_HEAD(dmi_devices);
int dmi_available;
/*
* Save a DMI string
*/
static void __init dmi_save_ident(const struct dmi_header *dm, int slot, int string)
static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
int string)
{
const char *d = (const char*) dm;
char *p;
const char *d = (const char *) dm;
const char *p;
if (dmi_ident[slot])
return;
@ -155,9 +154,10 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot, int str
dmi_ident[slot] = p;
}
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int index)
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
int index)
{
const u8 *d = (u8*) dm + index;
const u8 *d = (u8 *) dm + index;
char *s;
int is_ff = 1, is_00 = 1, i;
@ -188,12 +188,13 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
else
sprintf(s, "%pUB", d);
dmi_ident[slot] = s;
dmi_ident[slot] = s;
}
static void __init dmi_save_type(const struct dmi_header *dm, int slot, int index)
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
int index)
{
const u8 *d = (u8*) dm + index;
const u8 *d = (u8 *) dm + index;
char *s;
if (dmi_ident[slot])
@ -216,10 +217,8 @@ static void __init dmi_save_one_device(int type, const char *name)
return;
dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
if (!dev) {
printk(KERN_ERR "dmi_save_one_device: out of memory.\n");
if (!dev)
return;
}
dev->type = type;
strcpy((char *)(dev + 1), name);
@ -249,17 +248,14 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
struct dmi_device *dev;
for (i = 1; i <= count; i++) {
char *devname = dmi_string(dm, i);
const char *devname = dmi_string(dm, i);
if (devname == dmi_empty_string)
continue;
dev = dmi_alloc(sizeof(*dev));
if (!dev) {
printk(KERN_ERR
"dmi_save_oem_strings_devices: out of memory.\n");
if (!dev)
break;
}
dev->type = DMI_DEV_TYPE_OEM_STRING;
dev->name = devname;
@ -272,21 +268,17 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
{
struct dmi_device *dev;
void * data;
void *data;
data = dmi_alloc(dm->length);
if (data == NULL) {
printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
if (data == NULL)
return;
}
memcpy(data, dm, dm->length);
dev = dmi_alloc(sizeof(*dev));
if (!dev) {
printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
if (!dev)
return;
}
dev->type = DMI_DEV_TYPE_IPMI;
dev->name = "IPMI controller";
@ -301,10 +293,9 @@ static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
struct dmi_dev_onboard *onboard_dev;
onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
if (!onboard_dev) {
printk(KERN_ERR "dmi_save_dev_onboard: out of memory.\n");
if (!onboard_dev)
return;
}
onboard_dev->instance = instance;
onboard_dev->segment = segment;
onboard_dev->bus = bus;
@ -320,7 +311,7 @@ static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
static void __init dmi_save_extended_devices(const struct dmi_header *dm)
{
const u8 *d = (u8*) dm + 5;
const u8 *d = (u8 *) dm + 5;
/* Skip disabled device */
if ((*d & 0x80) == 0)
@ -338,7 +329,7 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
*/
static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
{
switch(dm->type) {
switch (dm->type) {
case 0: /* BIOS Information */
dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
@ -502,13 +493,7 @@ void __init dmi_scan_machine(void)
dmi_available = 1;
goto out;
}
}
else {
/*
* no iounmap() for that ioremap(); it would be a no-op, but
* it's so early in setup that sucker gets confused into doing
* what it shouldn't if we actually call it.
*/
} else {
p = dmi_ioremap(0xF0000, 0x10000);
if (p == NULL)
goto error;
@ -533,7 +518,7 @@ void __init dmi_scan_machine(void)
dmi_iounmap(p, 0x10000);
}
error:
printk(KERN_INFO "DMI not present or invalid.\n");
pr_info("DMI not present or invalid.\n");
out:
dmi_initialized = 1;
}
@ -669,7 +654,7 @@ int dmi_name_in_serial(const char *str)
/**
* dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
* @str: Case sensitive Name
* @str: Case sensitive Name
*/
int dmi_name_in_vendors(const char *str)
{
@ -696,13 +681,13 @@ EXPORT_SYMBOL(dmi_name_in_vendors);
* A new search is initiated by passing %NULL as the @from argument.
* If @from is not %NULL, searches continue from next device.
*/
const struct dmi_device * dmi_find_device(int type, const char *name,
const struct dmi_device *dmi_find_device(int type, const char *name,
const struct dmi_device *from)
{
const struct list_head *head = from ? &from->list : &dmi_devices;
struct list_head *d;
for(d = head->next; d != &dmi_devices; d = d->next) {
for (d = head->next; d != &dmi_devices; d = d->next) {
const struct dmi_device *dev =
list_entry(d, struct dmi_device, list);

View File

@ -525,7 +525,7 @@ static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj,
u32 data_type;
} param;
rc = strict_strtoul(buf, 0, &val);
rc = kstrtoul(buf, 0, &val);
if (rc)
return rc;

View File

@ -282,7 +282,6 @@ static int msm_iommu_remove(struct platform_device *pdev)
clk_put(drv->pclk);
memset(drv, 0, sizeof(*drv));
kfree(drv);
platform_set_drvdata(pdev, NULL);
}
return 0;
}
@ -366,7 +365,6 @@ static int msm_iommu_ctx_remove(struct platform_device *pdev)
if (drv) {
memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
kfree(drv);
platform_set_drvdata(pdev, NULL);
}
return 0;
}

View File

@ -1008,8 +1008,6 @@ static int omap_iommu_remove(struct platform_device *pdev)
struct resource *res;
struct omap_iommu *obj = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
iopgtable_clear_entry_all(obj);
irq = platform_get_irq(pdev, 0);

View File

@ -24,3 +24,15 @@ config MSPRO_BLOCK
support. This provides a block device driver, which you can use
to mount the filesystem. Almost everyone wishing MemoryStick
support should say Y or M here.
config MS_BLOCK
tristate "MemoryStick Standard device driver"
depends on BLOCK
help
Say Y here to enable the MemoryStick Standard device driver
support. This provides a block device driver, which you can use
to mount the filesystem.
This driver works with old (bulky) MemoryStick and MemoryStick Duo
but not PRO. Say Y if you have such card.
Driver is new and not yet well tested, thus it can damage your card
(even permanently)

View File

@ -3,5 +3,5 @@
#
obj-$(CONFIG_MEMSTICK) += memstick.o
obj-$(CONFIG_MS_BLOCK) += ms_block.o
obj-$(CONFIG_MSPRO_BLOCK) += mspro_block.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
/*
* ms_block.h - Sony MemoryStick (legacy) storage support
* Copyright (C) 2013 Maxim Levitsky <maximlevitsky@gmail.com>
*
* 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.
*
* Minor portions of the driver are copied from mspro_block.c which is
* Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
*
* Also ms structures were copied from old broken driver by same author
* These probably come from MS spec
*
*/
#ifndef MS_BLOCK_NEW_H
#define MS_BLOCK_NEW_H
#define MS_BLOCK_MAX_SEGS 32
#define MS_BLOCK_MAX_PAGES ((2 << 16) - 1)
#define MS_BLOCK_MAX_BOOT_ADDR 0x000c
#define MS_BLOCK_BOOT_ID 0x0001
#define MS_BLOCK_INVALID 0xffff
#define MS_MAX_ZONES 16
#define MS_BLOCKS_IN_ZONE 512
#define MS_BLOCK_MAP_LINE_SZ 16
#define MS_BLOCK_PART_SHIFT 3
#define MEMSTICK_UNCORR_ERROR (MEMSTICK_STATUS1_UCFG | \
MEMSTICK_STATUS1_UCEX | MEMSTICK_STATUS1_UCDT)
#define MEMSTICK_CORR_ERROR (MEMSTICK_STATUS1_FGER | MEMSTICK_STATUS1_EXER | \
MEMSTICK_STATUS1_DTER)
#define MEMSTICK_INT_ERROR (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)
#define MEMSTICK_OVERWRITE_FLAG_NORMAL \
(MEMSTICK_OVERWRITE_PGST1 | \
MEMSTICK_OVERWRITE_PGST0 | \
MEMSTICK_OVERWRITE_BKST)
#define MEMSTICK_OV_PG_NORMAL \
(MEMSTICK_OVERWRITE_PGST1 | MEMSTICK_OVERWRITE_PGST0)
#define MEMSTICK_MANAGMENT_FLAG_NORMAL \
(MEMSTICK_MANAGEMENT_SYSFLG | \
MEMSTICK_MANAGEMENT_SCMS1 | \
MEMSTICK_MANAGEMENT_SCMS0) \
struct ms_boot_header {
unsigned short block_id;
unsigned short format_reserved;
unsigned char reserved0[184];
unsigned char data_entry;
unsigned char reserved1[179];
} __packed;
struct ms_system_item {
unsigned int start_addr;
unsigned int data_size;
unsigned char data_type_id;
unsigned char reserved[3];
} __packed;
struct ms_system_entry {
struct ms_system_item disabled_block;
struct ms_system_item cis_idi;
unsigned char reserved[24];
} __packed;
struct ms_boot_attr_info {
unsigned char memorystick_class;
unsigned char format_unique_value1;
unsigned short block_size;
unsigned short number_of_blocks;
unsigned short number_of_effective_blocks;
unsigned short page_size;
unsigned char extra_data_size;
unsigned char format_unique_value2;
unsigned char assembly_time[8];
unsigned char format_unique_value3;
unsigned char serial_number[3];
unsigned char assembly_manufacturer_code;
unsigned char assembly_model_code[3];
unsigned short memory_manufacturer_code;
unsigned short memory_device_code;
unsigned short implemented_capacity;
unsigned char format_unique_value4[2];
unsigned char vcc;
unsigned char vpp;
unsigned short controller_number;
unsigned short controller_function;
unsigned char reserved0[9];
unsigned char transfer_supporting;
unsigned short format_unique_value5;
unsigned char format_type;
unsigned char memorystick_application;
unsigned char device_type;
unsigned char reserved1[22];
unsigned char format_uniqure_value6[2];
unsigned char reserved2[15];
} __packed;
struct ms_cis_idi {
unsigned short general_config;
unsigned short logical_cylinders;
unsigned short reserved0;
unsigned short logical_heads;
unsigned short track_size;
unsigned short page_size;
unsigned short pages_per_track;
unsigned short msw;
unsigned short lsw;
unsigned short reserved1;
unsigned char serial_number[20];
unsigned short buffer_type;
unsigned short buffer_size_increments;
unsigned short long_command_ecc;
unsigned char firmware_version[28];
unsigned char model_name[18];
unsigned short reserved2[5];
unsigned short pio_mode_number;
unsigned short dma_mode_number;
unsigned short field_validity;
unsigned short current_logical_cylinders;
unsigned short current_logical_heads;
unsigned short current_pages_per_track;
unsigned int current_page_capacity;
unsigned short mutiple_page_setting;
unsigned int addressable_pages;
unsigned short single_word_dma;
unsigned short multi_word_dma;
unsigned char reserved3[128];
} __packed;
struct ms_boot_page {
struct ms_boot_header header;
struct ms_system_entry entry;
struct ms_boot_attr_info attr;
} __packed;
struct msb_data {
unsigned int usage_count;
struct memstick_dev *card;
struct gendisk *disk;
struct request_queue *queue;
spinlock_t q_lock;
struct hd_geometry geometry;
struct attribute_group attr_group;
struct request *req;
int caps;
int disk_id;
/* IO */
struct workqueue_struct *io_queue;
bool io_queue_stopped;
struct work_struct io_work;
bool card_dead;
/* Media properties */
struct ms_boot_page *boot_page;
u16 boot_block_locations[2];
int boot_block_count;
bool read_only;
unsigned short page_size;
int block_size;
int pages_in_block;
int zone_count;
int block_count;
int logical_block_count;
/* FTL tables */
unsigned long *used_blocks_bitmap;
unsigned long *erased_blocks_bitmap;
u16 *lba_to_pba_table;
int free_block_count[MS_MAX_ZONES];
bool ftl_initialized;
/* Cache */
unsigned char *cache;
unsigned long valid_cache_bitmap;
int cache_block_lba;
bool need_flush_cache;
struct timer_list cache_flush_timer;
/* Preallocated buffers */
unsigned char *block_buffer;
struct scatterlist prealloc_sg[MS_BLOCK_MAX_SEGS+1];
/* handler's local data */
struct ms_register_addr reg_addr;
bool addr_valid;
u8 command_value;
bool command_need_oob;
struct scatterlist *current_sg;
int current_sg_offset;
struct ms_register regs;
int current_page;
int state;
int exit_error;
bool int_polling;
unsigned long int_timeout;
};
enum msb_readpage_states {
MSB_RP_SEND_BLOCK_ADDRESS = 0,
MSB_RP_SEND_READ_COMMAND,
MSB_RP_SEND_INT_REQ,
MSB_RP_RECEIVE_INT_REQ_RESULT,
MSB_RP_SEND_READ_STATUS_REG,
MSB_RP_RECIVE_STATUS_REG,
MSB_RP_SEND_OOB_READ,
MSB_RP_RECEIVE_OOB_READ,
MSB_RP_SEND_READ_DATA,
MSB_RP_RECEIVE_READ_DATA,
};
enum msb_write_block_states {
MSB_WB_SEND_WRITE_PARAMS = 0,
MSB_WB_SEND_WRITE_OOB,
MSB_WB_SEND_WRITE_COMMAND,
MSB_WB_SEND_INT_REQ,
MSB_WB_RECEIVE_INT_REQ,
MSB_WB_SEND_WRITE_DATA,
MSB_WB_RECEIVE_WRITE_CONFIRMATION,
};
enum msb_send_command_states {
MSB_SC_SEND_WRITE_PARAMS,
MSB_SC_SEND_WRITE_OOB,
MSB_SC_SEND_COMMAND,
MSB_SC_SEND_INT_REQ,
MSB_SC_RECEIVE_INT_REQ,
};
enum msb_reset_states {
MSB_RS_SEND,
MSB_RS_CONFIRM,
};
enum msb_par_switch_states {
MSB_PS_SEND_SWITCH_COMMAND,
MSB_PS_SWICH_HOST,
MSB_PS_CONFIRM,
};
struct chs_entry {
unsigned long size;
unsigned char sec;
unsigned short cyl;
unsigned char head;
};
static int msb_reset(struct msb_data *msb, bool full);
static int h_msb_default_bad(struct memstick_dev *card,
struct memstick_request **mrq);
#define __dbg(level, format, ...) \
do { \
if (debug >= level) \
pr_err(format "\n", ## __VA_ARGS__); \
} while (0)
#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__)
#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__)
#endif

View File

@ -612,8 +612,6 @@ static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
memstick_remove_host(msh);
memstick_free_host(msh);
platform_set_drvdata(pdev, NULL);
dev_dbg(&(pdev->dev),
": Realtek PCI-E Memstick controller has been removed\n");

View File

@ -393,17 +393,21 @@ static void gmux_notify_handler(acpi_handle device, u32 value, void *context)
complete(&gmux_data->powerchange_done);
}
static int gmux_suspend(struct pnp_dev *pnp, pm_message_t state)
static int gmux_suspend(struct device *dev)
{
struct pnp_dev *pnp = to_pnp_dev(dev);
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
gmux_data->resume_client_id = gmux_active_client(gmux_data);
gmux_disable_interrupts(gmux_data);
return 0;
}
static int gmux_resume(struct pnp_dev *pnp)
static int gmux_resume(struct device *dev)
{
struct pnp_dev *pnp = to_pnp_dev(dev);
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
gmux_enable_interrupts(gmux_data);
gmux_switchto(gmux_data->resume_client_id);
if (gmux_data->power_state == VGA_SWITCHEROO_OFF)
@ -605,13 +609,19 @@ static const struct pnp_device_id gmux_device_ids[] = {
{"", 0}
};
static const struct dev_pm_ops gmux_dev_pm_ops = {
.suspend = gmux_suspend,
.resume = gmux_resume,
};
static struct pnp_driver gmux_pnp_driver = {
.name = "apple-gmux",
.probe = gmux_probe,
.remove = gmux_remove,
.id_table = gmux_device_ids,
.suspend = gmux_suspend,
.resume = gmux_resume
.driver = {
.pm = &gmux_dev_pm_ops,
},
};
static int __init apple_gmux_init(void)

View File

@ -163,6 +163,13 @@ static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
if (!pnp_drv)
return 0;
if (pnp_drv->driver.pm && pnp_drv->driver.pm->suspend) {
error = pnp_drv->driver.pm->suspend(dev);
suspend_report_result(pnp_drv->driver.pm->suspend, error);
if (error)
return error;
}
if (pnp_drv->suspend) {
error = pnp_drv->suspend(pnp_dev, state);
if (error)
@ -211,6 +218,12 @@ static int pnp_bus_resume(struct device *dev)
return error;
}
if (pnp_drv->driver.pm && pnp_drv->driver.pm->resume) {
error = pnp_drv->driver.pm->resume(dev);
if (error)
return error;
}
if (pnp_drv->resume) {
error = pnp_drv->resume(pnp_dev);
if (error)

View File

@ -184,7 +184,6 @@ static int pps_gpio_remove(struct platform_device *pdev)
{
struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
pps_unregister_source(data->pps);
dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
return 0;

View File

@ -1249,6 +1249,15 @@ config RTC_DRV_SIRFSOC
Say "yes" here to support the real time clock on SiRF SOC chips.
This driver can also be built as a module called rtc-sirfsoc.
config RTC_DRV_MOXART
tristate "MOXA ART RTC"
help
If you say yes here you get support for the MOXA ART
RTC module.
This driver can also be built as a module. If so, the module
will be called rtc-moxart
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME

View File

@ -130,3 +130,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o

View File

@ -1018,23 +1018,6 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
cmos_do_remove(&pnp->dev);
}
#ifdef CONFIG_PM
static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg)
{
return cmos_suspend(&pnp->dev);
}
static int cmos_pnp_resume(struct pnp_dev *pnp)
{
return cmos_resume(&pnp->dev);
}
#else
#define cmos_pnp_suspend NULL
#define cmos_pnp_resume NULL
#endif
static void cmos_pnp_shutdown(struct pnp_dev *pnp)
{
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
@ -1060,8 +1043,11 @@ static struct pnp_driver cmos_pnp_driver = {
/* flag ensures resume() gets called, and stops syslog spam */
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
.suspend = cmos_pnp_suspend,
.resume = cmos_pnp_resume,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &cmos_pm_ops,
},
#endif
};
#endif /* CONFIG_PNP */

View File

@ -89,7 +89,6 @@ enum ds1511reg {
struct rtc_plat_data {
struct rtc_device *rtc;
void __iomem *ioaddr; /* virtual base address */
int size; /* amount of memory mapped */
int irq;
unsigned int irqen;
int alrm_sec;
@ -479,20 +478,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
pdev->name))
return -EBUSY;
ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size);
if (!ds1511_base)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ds1511_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ds1511_base))
return PTR_ERR(ds1511_base);
pdata->ioaddr = ds1511_base;
pdata->irq = platform_get_irq(pdev, 0);

View File

@ -285,19 +285,14 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
pdev->name))
return -EBUSY;
ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
if (!ioaddr)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ioaddr))
return PTR_ERR(ioaddr);
pdata->ioaddr = ioaddr;
pdata->irq = platform_get_irq(pdev, 0);

View File

@ -52,11 +52,9 @@
#define RTC_BATT_FLAG 0x80
struct rtc_plat_data {
struct rtc_device *rtc;
void __iomem *ioaddr_nvram;
void __iomem *ioaddr_rtc;
size_t size_nvram;
size_t size;
unsigned long last_jiffies;
struct bin_attribute nvram_attr;
};
@ -117,11 +115,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
if (rtc_valid_tm(tm) < 0) {
dev_err(dev, "retrieved date/time is not valid.\n");
rtc_time_to_tm(0, tm);
}
return 0;
return rtc_valid_tm(tm);
}
static const struct rtc_class_ops ds1742_rtc_ops = {
@ -168,22 +162,17 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
pdev->name))
return -EBUSY;
ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size);
if (!ioaddr)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ioaddr))
return PTR_ERR(ioaddr);
pdata->ioaddr_nvram = ioaddr;
pdata->size_nvram = pdata->size - RTC_SIZE;
pdata->size_nvram = resource_size(res) - RTC_SIZE;
pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
sysfs_bin_attr_init(&pdata->nvram_attr);
@ -212,7 +201,6 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
&ds1742_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
pdata->rtc = rtc;
ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);

View File

@ -138,17 +138,9 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name))
return -EBUSY;
ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!ep93xx_rtc->mmio_base)
return -ENXIO;
ep93xx_rtc->mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ep93xx_rtc->mmio_base))
return PTR_ERR(ep93xx_rtc->mmio_base);
pdev->dev.platform_data = ep93xx_rtc;
platform_set_drvdata(pdev, ep93xx_rtc);

View File

@ -23,10 +23,6 @@
#include <linux/iio/iio.h>
#include <linux/rtc.h>
/* Format: HID-SENSOR-usage_id_in_hex */
/* Usage ID from spec for Time: 0x2000A0 */
#define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */
enum hid_time_channel {
CHANNEL_SCAN_INDEX_YEAR,
CHANNEL_SCAN_INDEX_MONTH,
@ -283,9 +279,11 @@ static int hid_time_probe(struct platform_device *pdev)
"hid-sensor-time", &hid_time_rtc_ops,
THIS_MODULE);
if (IS_ERR(time_state->rtc)) {
if (IS_ERR_OR_NULL(time_state->rtc)) {
ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
time_state->rtc = NULL;
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
dev_err(&pdev->dev, "rtc device register failed!\n");
return PTR_ERR(time_state->rtc);
}
return ret;
@ -300,9 +298,19 @@ static int hid_time_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_time_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-2000a0",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, hid_time_ids);
static struct platform_driver hid_time_platform_driver = {
.id_table = hid_time_ids,
.driver = {
.name = DRIVER_NAME,
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
.probe = hid_time_probe,

View File

@ -375,24 +375,16 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
struct imxdi_dev *imxdi;
int rc;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
if (!imxdi)
return -ENOMEM;
imxdi->pdev = pdev;
if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
pdev->name))
return -EBUSY;
imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (imxdi->ioaddr == NULL)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(imxdi->ioaddr))
return PTR_ERR(imxdi->ioaddr);
spin_lock_init(&imxdi->irq_lock);

View File

@ -201,16 +201,9 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct lpc32xx_rtc *rtc;
resource_size_t size;
int rtcirq;
u32 tmp;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Can't get memory resource\n");
return -ENOENT;
}
rtcirq = platform_get_irq(pdev, 0);
if (rtcirq < 0 || rtcirq >= NR_IRQS) {
dev_warn(&pdev->dev, "Can't get interrupt resource\n");
@ -224,19 +217,10 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
}
rtc->irq = rtcirq;
size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, size,
pdev->name)) {
dev_err(&pdev->dev, "RTC registers are not free\n");
return -EBUSY;
}
rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size);
if (!rtc->rtc_base) {
dev_err(&pdev->dev, "Can't map memory\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->rtc_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rtc->rtc_base))
return PTR_ERR(rtc->rtc_base);
spin_lock_init(&rtc->lock);

View File

@ -240,9 +240,9 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
alrm->pending = 0;
ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS1, &val);
ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}

330
drivers/rtc/rtc-moxart.c Normal file
View File

@ -0,0 +1,330 @@
/*
* MOXA ART RTC driver.
*
* Copyright (C) 2013 Jonas Jensen
*
* Jonas Jensen <jonas.jensen@gmail.com>
*
* Based on code from
* Moxa Technology Co., Ltd. <www.moxa.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#define GPIO_RTC_RESERVED 0x0C
#define GPIO_RTC_DATA_SET 0x10
#define GPIO_RTC_DATA_CLEAR 0x14
#define GPIO_RTC_PIN_PULL_ENABLE 0x18
#define GPIO_RTC_PIN_PULL_TYPE 0x1C
#define GPIO_RTC_INT_ENABLE 0x20
#define GPIO_RTC_INT_RAW_STATE 0x24
#define GPIO_RTC_INT_MASKED_STATE 0x28
#define GPIO_RTC_INT_MASK 0x2C
#define GPIO_RTC_INT_CLEAR 0x30
#define GPIO_RTC_INT_TRIGGER 0x34
#define GPIO_RTC_INT_BOTH 0x38
#define GPIO_RTC_INT_RISE_NEG 0x3C
#define GPIO_RTC_BOUNCE_ENABLE 0x40
#define GPIO_RTC_BOUNCE_PRE_SCALE 0x44
#define GPIO_RTC_PROTECT_W 0x8E
#define GPIO_RTC_PROTECT_R 0x8F
#define GPIO_RTC_YEAR_W 0x8C
#define GPIO_RTC_YEAR_R 0x8D
#define GPIO_RTC_DAY_W 0x8A
#define GPIO_RTC_DAY_R 0x8B
#define GPIO_RTC_MONTH_W 0x88
#define GPIO_RTC_MONTH_R 0x89
#define GPIO_RTC_DATE_W 0x86
#define GPIO_RTC_DATE_R 0x87
#define GPIO_RTC_HOURS_W 0x84
#define GPIO_RTC_HOURS_R 0x85
#define GPIO_RTC_MINUTES_W 0x82
#define GPIO_RTC_MINUTES_R 0x83
#define GPIO_RTC_SECONDS_W 0x80
#define GPIO_RTC_SECONDS_R 0x81
#define GPIO_RTC_DELAY_TIME 8
struct moxart_rtc {
struct rtc_device *rtc;
spinlock_t rtc_lock;
int gpio_data, gpio_sclk, gpio_reset;
};
static int day_of_year[12] = { 0, 31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334 };
static void moxart_rtc_write_byte(struct device *dev, u8 data)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
int i;
for (i = 0; i < 8; i++, data >>= 1) {
gpio_set_value(moxart_rtc->gpio_sclk, 0);
gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1));
udelay(GPIO_RTC_DELAY_TIME);
gpio_set_value(moxart_rtc->gpio_sclk, 1);
udelay(GPIO_RTC_DELAY_TIME);
}
}
static u8 moxart_rtc_read_byte(struct device *dev)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
int i;
u8 data = 0;
for (i = 0; i < 8; i++) {
gpio_set_value(moxart_rtc->gpio_sclk, 0);
udelay(GPIO_RTC_DELAY_TIME);
gpio_set_value(moxart_rtc->gpio_sclk, 1);
udelay(GPIO_RTC_DELAY_TIME);
if (gpio_get_value(moxart_rtc->gpio_data))
data |= (1 << i);
udelay(GPIO_RTC_DELAY_TIME);
}
return data;
}
static u8 moxart_rtc_read_register(struct device *dev, u8 cmd)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
u8 data;
unsigned long flags;
local_irq_save(flags);
gpio_direction_output(moxart_rtc->gpio_data, 0);
gpio_set_value(moxart_rtc->gpio_reset, 1);
udelay(GPIO_RTC_DELAY_TIME);
moxart_rtc_write_byte(dev, cmd);
gpio_direction_input(moxart_rtc->gpio_data);
udelay(GPIO_RTC_DELAY_TIME);
data = moxart_rtc_read_byte(dev);
gpio_set_value(moxart_rtc->gpio_sclk, 0);
gpio_set_value(moxart_rtc->gpio_reset, 0);
udelay(GPIO_RTC_DELAY_TIME);
local_irq_restore(flags);
return data;
}
static void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
unsigned long flags;
local_irq_save(flags);
gpio_direction_output(moxart_rtc->gpio_data, 0);
gpio_set_value(moxart_rtc->gpio_reset, 1);
udelay(GPIO_RTC_DELAY_TIME);
moxart_rtc_write_byte(dev, cmd);
moxart_rtc_write_byte(dev, data);
gpio_set_value(moxart_rtc->gpio_sclk, 0);
gpio_set_value(moxart_rtc->gpio_reset, 0);
udelay(GPIO_RTC_DELAY_TIME);
local_irq_restore(flags);
}
static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
spin_lock_irq(&moxart_rtc->rtc_lock);
moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0);
moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W,
(((tm->tm_year - 100) / 10) << 4) |
((tm->tm_year - 100) % 10));
moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W,
(((tm->tm_mon + 1) / 10) << 4) |
((tm->tm_mon + 1) % 10));
moxart_rtc_write_register(dev, GPIO_RTC_DATE_W,
((tm->tm_mday / 10) << 4) |
(tm->tm_mday % 10));
moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W,
((tm->tm_hour / 10) << 4) |
(tm->tm_hour % 10));
moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W,
((tm->tm_min / 10) << 4) |
(tm->tm_min % 10));
moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W,
((tm->tm_sec / 10) << 4) |
(tm->tm_sec % 10));
moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80);
spin_unlock_irq(&moxart_rtc->rtc_lock);
dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n"
"tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n",
__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
unsigned char v;
spin_lock_irq(&moxart_rtc->rtc_lock);
v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R);
tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R);
tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R);
if (v & 0x80) { /* 12-hour mode */
tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
if (v & 0x20) { /* PM mode */
tm->tm_hour += 12;
if (tm->tm_hour >= 24)
tm->tm_hour = 0;
}
} else { /* 24-hour mode */
tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
}
v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R);
tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R);
tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
tm->tm_mon--;
v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R);
tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F);
tm->tm_year += 100;
if (tm->tm_year <= 69)
tm->tm_year += 100;
v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R);
tm->tm_wday = (v & 0x0f) - 1;
tm->tm_yday = day_of_year[tm->tm_mon];
tm->tm_yday += (tm->tm_mday - 1);
if (tm->tm_mon >= 2) {
if (!(tm->tm_year % 4) && (tm->tm_year % 100))
tm->tm_yday++;
}
tm->tm_isdst = 0;
spin_unlock_irq(&moxart_rtc->rtc_lock);
return 0;
}
static const struct rtc_class_ops moxart_rtc_ops = {
.read_time = moxart_rtc_read_time,
.set_time = moxart_rtc_set_time,
};
static int moxart_rtc_probe(struct platform_device *pdev)
{
struct moxart_rtc *moxart_rtc;
int ret = 0;
moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL);
if (!moxart_rtc) {
dev_err(&pdev->dev, "devm_kzalloc failed\n");
return -ENOMEM;
}
moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node,
"gpio-rtc-data", 0);
if (!gpio_is_valid(moxart_rtc->gpio_data)) {
dev_err(&pdev->dev, "invalid gpio (data): %d\n",
moxart_rtc->gpio_data);
return moxart_rtc->gpio_data;
}
moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node,
"gpio-rtc-sclk", 0);
if (!gpio_is_valid(moxart_rtc->gpio_sclk)) {
dev_err(&pdev->dev, "invalid gpio (sclk): %d\n",
moxart_rtc->gpio_sclk);
return moxart_rtc->gpio_sclk;
}
moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node,
"gpio-rtc-reset", 0);
if (!gpio_is_valid(moxart_rtc->gpio_reset)) {
dev_err(&pdev->dev, "invalid gpio (reset): %d\n",
moxart_rtc->gpio_reset);
return moxart_rtc->gpio_reset;
}
spin_lock_init(&moxart_rtc->rtc_lock);
platform_set_drvdata(pdev, moxart_rtc);
ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data");
if (ret) {
dev_err(&pdev->dev, "can't get rtc_data gpio\n");
return ret;
}
ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk,
GPIOF_DIR_OUT, "rtc_sclk");
if (ret) {
dev_err(&pdev->dev, "can't get rtc_sclk gpio\n");
return ret;
}
ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset,
GPIOF_DIR_OUT, "rtc_reset");
if (ret) {
dev_err(&pdev->dev, "can't get rtc_reset gpio\n");
return ret;
}
moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&moxart_rtc_ops,
THIS_MODULE);
if (IS_ERR(moxart_rtc->rtc)) {
dev_err(&pdev->dev, "devm_rtc_device_register failed\n");
return PTR_ERR(moxart_rtc->rtc);
}
return 0;
}
static const struct of_device_id moxart_rtc_match[] = {
{ .compatible = "moxa,moxart-rtc" },
{ },
};
static struct platform_driver moxart_rtc_driver = {
.probe = moxart_rtc_probe,
.driver = {
.name = "moxart-rtc",
.owner = THIS_MODULE,
.of_match_table = moxart_rtc_match,
},
};
module_platform_driver(moxart_rtc_driver);
MODULE_DESCRIPTION("MOXART RTC driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");

View File

@ -221,26 +221,17 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct rtc_plat_data *pdata;
resource_size_t size;
u32 rtc_time;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, size,
pdev->name))
return -EBUSY;
pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
if (!pdata->ioaddr)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdata->ioaddr))
return PTR_ERR(pdata->ioaddr);
pdata->clk = devm_clk_get(&pdev->dev, NULL);
/* Not all SoCs require a clock.*/

View File

@ -377,22 +377,16 @@ static int mxc_rtc_probe(struct platform_device *pdev)
unsigned long rate;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->devtype = pdev->id_entry->driver_data;
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name))
return -EBUSY;
pdata->ioaddr = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdata->ioaddr))
return PTR_ERR(pdata->ioaddr);
pdata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pdata->clk)) {

View File

@ -99,7 +99,7 @@ static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
if (!timeout)
return ERR_PTR(-EPERM);
return 0;
return NULL;
}
static int nuc900_rtc_bcd2bin(unsigned int timereg,

View File

@ -70,6 +70,8 @@
#define OMAP_RTC_KICK0_REG 0x6c
#define OMAP_RTC_KICK1_REG 0x70
#define OMAP_RTC_IRQWAKEEN 0x7c
/* OMAP_RTC_CTRL_REG bit fields: */
#define OMAP_RTC_CTRL_SPLIT (1<<7)
#define OMAP_RTC_CTRL_DISABLE (1<<6)
@ -94,12 +96,21 @@
#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
/* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1)
/* OMAP_RTC_KICKER values */
#define KICK0_VALUE 0x83e70b13
#define KICK1_VALUE 0x95a4f1e0
#define OMAP_RTC_HAS_KICKER 0x1
/*
* Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
* generation for event Alarm.
*/
#define OMAP_RTC_HAS_IRQWAKEEN 0x2
static void __iomem *rtc_base;
#define rtc_read(addr) readb(rtc_base + (addr))
@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;
#define OMAP_RTC_DATA_DA830_IDX 1
#define OMAP_RTC_DATA_AM3352_IDX 1
#define OMAP_RTC_DATA_DA830_IDX 2
static struct platform_device_id omap_rtc_devtype[] = {
{
.name = DRIVER_NAME,
}, {
},
[OMAP_RTC_DATA_AM3352_IDX] = {
.name = "am3352-rtc",
.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
},
[OMAP_RTC_DATA_DA830_IDX] = {
.name = "da830-rtc",
.driver_data = OMAP_RTC_HAS_KICKER,
},
@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
{ .compatible = "ti,da830-rtc",
.data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
},
{ .compatible = "ti,am3352-rtc",
.data = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
},
{},
};
MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@ -464,16 +484,28 @@ static u8 irqstat;
static int omap_rtc_suspend(struct device *dev)
{
u8 irqwake_stat;
struct platform_device *pdev = to_platform_device(dev);
const struct platform_device_id *id_entry =
platform_get_device_id(pdev);
irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
/* FIXME the RTC alarm is not currently acting as a wakeup event
* source, and in fact this enable() call is just saving a flag
* that's never used...
* source on some platforms, and in fact this enable() call is just
* saving a flag that's never used...
*/
if (device_may_wakeup(dev))
if (device_may_wakeup(dev)) {
enable_irq_wake(omap_rtc_alarm);
else
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
}
} else {
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
}
/* Disable the clock/module */
pm_runtime_put_sync(dev);
@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)
static int omap_rtc_resume(struct device *dev)
{
u8 irqwake_stat;
struct platform_device *pdev = to_platform_device(dev);
const struct platform_device_id *id_entry =
platform_get_device_id(pdev);
/* Enable the clock/module so that we can access the registers */
pm_runtime_get_sync(dev);
if (device_may_wakeup(dev))
if (device_may_wakeup(dev)) {
disable_irq_wake(omap_rtc_alarm);
else
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
}
} else {
rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
}
return 0;
}
#endif

View File

@ -238,6 +238,15 @@ static int palmas_rtc_probe(struct platform_device *pdev)
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_rtc *palmas_rtc = NULL;
int ret;
bool enable_bb_charging = false;
bool high_bb_charging;
if (pdev->dev.of_node) {
enable_bb_charging = of_property_read_bool(pdev->dev.of_node,
"ti,backup-battery-chargeable");
high_bb_charging = of_property_read_bool(pdev->dev.of_node,
"ti,backup-battery-charge-high-current");
}
palmas_rtc = devm_kzalloc(&pdev->dev, sizeof(struct palmas_rtc),
GFP_KERNEL);
@ -254,6 +263,32 @@ static int palmas_rtc_probe(struct platform_device *pdev)
palmas_rtc->dev = &pdev->dev;
platform_set_drvdata(pdev, palmas_rtc);
if (enable_bb_charging) {
unsigned reg = PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG;
if (high_bb_charging)
reg = 0;
ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
PALMAS_BACKUP_BATTERY_CTRL,
PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG, reg);
if (ret < 0) {
dev_err(&pdev->dev,
"BACKUP_BATTERY_CTRL update failed, %d\n", ret);
return ret;
}
ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
PALMAS_BACKUP_BATTERY_CTRL,
PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN,
PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN);
if (ret < 0) {
dev_err(&pdev->dev,
"BACKUP_BATTERY_CTRL update failed, %d\n", ret);
return ret;
}
}
/* Start RTC */
ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
PALMAS_RTC_CTRL_REG_STOP_RTC,

View File

@ -203,11 +203,6 @@ static int pcf2127_probe(struct i2c_client *client,
return 0;
}
static int pcf2127_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id pcf2127_id[] = {
{ "pcf2127", 0 },
{ }
@ -229,7 +224,6 @@ static struct i2c_driver pcf2127_driver = {
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_probe,
.remove = pcf2127_remove,
.id_table = pcf2127_id,
};

View File

@ -44,6 +44,7 @@ struct sirfsoc_rtc_drv {
struct rtc_device *rtc;
u32 rtc_base;
u32 irq;
unsigned irq_wake;
/* Overflow for every 8 years extra time */
u32 overflow_rtc;
#ifdef CONFIG_PM
@ -355,8 +356,8 @@ static int sirfsoc_rtc_suspend(struct device *dev)
rtcdrv->saved_counter =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(rtcdrv->irq);
if (device_may_wakeup(&pdev->dev) && !enable_irq_wake(rtcdrv->irq))
rtcdrv->irq_wake = 1;
return 0;
}
@ -423,8 +424,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
sirfsoc_rtc_thaw(dev);
if (device_may_wakeup(&pdev->dev))
if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);
rtcdrv->irq_wake = 0;
}
return 0;
}
@ -434,8 +437,10 @@ static int sirfsoc_rtc_restore(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);
rtcdrv->irq_wake = 0;
}
return 0;
}

View File

@ -294,19 +294,14 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
pdev->name))
return -EBUSY;
ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
if (!ioaddr)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ioaddr))
return PTR_ERR(ioaddr);
pdata->ioaddr = ioaddr;
pdata->irq = platform_get_irq(pdev, 0);

View File

@ -244,9 +244,6 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
struct resource *res;
int irq, ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENODEV;
@ -255,13 +252,10 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, pdata);
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name))
return -EBUSY;
pdata->rtcreg = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!pdata->rtcreg)
return -EBUSY;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->rtcreg = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdata->rtcreg))
return PTR_ERR(pdata->rtcreg);
spin_lock_init(&pdata->lock);
tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);

View File

@ -30,8 +30,8 @@
#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
#define TO_USER 0
#define TO_KERNEL 1
#define TO_USER 1
#define TO_KERNEL 0
#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
enum arch_id {
@ -73,7 +73,7 @@ static struct ipl_parameter_block *ipl_block;
* @count: Size of buffer, which should be copied
* @mode: Either TO_KERNEL or TO_USER
*/
static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
{
int offs, blk_num;
static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));

View File

@ -37,14 +37,6 @@
#include "acornfb.h"
/*
* VIDC machines can't do 16 or 32BPP modes.
*/
#ifdef HAS_VIDC
#undef FBCON_HAS_CFB16
#undef FBCON_HAS_CFB32
#endif
/*
* Default resolution.
* NOTE that it has to be supported in the table towards
@ -106,238 +98,6 @@ static struct vidc_timing current_vidc;
extern unsigned int vram_size; /* set by setup.c */
#ifdef HAS_VIDC
#define MAX_SIZE 480*1024
/* CTL VIDC Actual
* 24.000 0 8.000
* 25.175 0 8.392
* 36.000 0 12.000
* 24.000 1 12.000
* 25.175 1 12.588
* 24.000 2 16.000
* 25.175 2 16.783
* 36.000 1 18.000
* 24.000 3 24.000
* 36.000 2 24.000
* 25.175 3 25.175
* 36.000 3 36.000
*/
struct pixclock {
u_long min_clock;
u_long max_clock;
u_int vidc_ctl;
u_int vid_ctl;
};
static struct pixclock arc_clocks[] = {
/* we allow +/-1% on these */
{ 123750, 126250, VIDC_CTRL_DIV3, VID_CTL_24MHz }, /* 8.000MHz */
{ 82500, 84167, VIDC_CTRL_DIV2, VID_CTL_24MHz }, /* 12.000MHz */
{ 61875, 63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz }, /* 16.000MHz */
{ 41250, 42083, VIDC_CTRL_DIV1, VID_CTL_24MHz }, /* 24.000MHz */
};
static struct pixclock *
acornfb_valid_pixrate(struct fb_var_screeninfo *var)
{
u_long pixclock = var->pixclock;
u_int i;
if (!var->pixclock)
return NULL;
for (i = 0; i < ARRAY_SIZE(arc_clocks); i++)
if (pixclock > arc_clocks[i].min_clock &&
pixclock < arc_clocks[i].max_clock)
return arc_clocks + i;
return NULL;
}
/* VIDC Rules:
* hcr : must be even (interlace, hcr/2 must be even)
* hswr : must be even
* hdsr : must be odd
* hder : must be odd
*
* vcr : must be odd
* vswr : >= 1
* vdsr : >= 1
* vder : >= vdsr
* if interlaced, then hcr/2 must be even
*/
static void
acornfb_set_timing(struct fb_var_screeninfo *var)
{
struct pixclock *pclk;
struct vidc_timing vidc;
u_int horiz_correction;
u_int sync_len, display_start, display_end, cycle;
u_int is_interlaced;
u_int vid_ctl, vidc_ctl;
u_int bandwidth;
memset(&vidc, 0, sizeof(vidc));
pclk = acornfb_valid_pixrate(var);
vidc_ctl = pclk->vidc_ctl;
vid_ctl = pclk->vid_ctl;
bandwidth = var->pixclock * 8 / var->bits_per_pixel;
/* 25.175, 4bpp = 79.444ns per byte, 317.776ns per word: fifo = 2,6 */
if (bandwidth > 143500)
vidc_ctl |= VIDC_CTRL_FIFO_3_7;
else if (bandwidth > 71750)
vidc_ctl |= VIDC_CTRL_FIFO_2_6;
else if (bandwidth > 35875)
vidc_ctl |= VIDC_CTRL_FIFO_1_5;
else
vidc_ctl |= VIDC_CTRL_FIFO_0_4;
switch (var->bits_per_pixel) {
case 1:
horiz_correction = 19;
vidc_ctl |= VIDC_CTRL_1BPP;
break;
case 2:
horiz_correction = 11;
vidc_ctl |= VIDC_CTRL_2BPP;
break;
case 4:
horiz_correction = 7;
vidc_ctl |= VIDC_CTRL_4BPP;
break;
default:
case 8:
horiz_correction = 5;
vidc_ctl |= VIDC_CTRL_8BPP;
break;
}
if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
vidc_ctl |= VIDC_CTRL_CSYNC;
else {
if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
vid_ctl |= VID_CTL_HS_NHSYNC;
if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
vid_ctl |= VID_CTL_VS_NVSYNC;
}
sync_len = var->hsync_len;
display_start = sync_len + var->left_margin;
display_end = display_start + var->xres;
cycle = display_end + var->right_margin;
/* if interlaced, then hcr/2 must be even */
is_interlaced = (var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
if (is_interlaced) {
vidc_ctl |= VIDC_CTRL_INTERLACE;
if (cycle & 2) {
cycle += 2;
var->right_margin += 2;
}
}
vidc.h_cycle = (cycle - 2) / 2;
vidc.h_sync_width = (sync_len - 2) / 2;
vidc.h_border_start = (display_start - 1) / 2;
vidc.h_display_start = (display_start - horiz_correction) / 2;
vidc.h_display_end = (display_end - horiz_correction) / 2;
vidc.h_border_end = (display_end - 1) / 2;
vidc.h_interlace = (vidc.h_cycle + 1) / 2;
sync_len = var->vsync_len;
display_start = sync_len + var->upper_margin;
display_end = display_start + var->yres;
cycle = display_end + var->lower_margin;
if (is_interlaced)
cycle = (cycle - 3) / 2;
else
cycle = cycle - 1;
vidc.v_cycle = cycle;
vidc.v_sync_width = sync_len - 1;
vidc.v_border_start = display_start - 1;
vidc.v_display_start = vidc.v_border_start;
vidc.v_display_end = display_end - 1;
vidc.v_border_end = vidc.v_display_end;
if (machine_is_a5k())
__raw_writeb(vid_ctl, IOEB_VID_CTL);
if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
current_vidc = vidc;
vidc_writel(0xe0000000 | vidc_ctl);
vidc_writel(0x80000000 | (vidc.h_cycle << 14));
vidc_writel(0x84000000 | (vidc.h_sync_width << 14));
vidc_writel(0x88000000 | (vidc.h_border_start << 14));
vidc_writel(0x8c000000 | (vidc.h_display_start << 14));
vidc_writel(0x90000000 | (vidc.h_display_end << 14));
vidc_writel(0x94000000 | (vidc.h_border_end << 14));
vidc_writel(0x98000000);
vidc_writel(0x9c000000 | (vidc.h_interlace << 14));
vidc_writel(0xa0000000 | (vidc.v_cycle << 14));
vidc_writel(0xa4000000 | (vidc.v_sync_width << 14));
vidc_writel(0xa8000000 | (vidc.v_border_start << 14));
vidc_writel(0xac000000 | (vidc.v_display_start << 14));
vidc_writel(0xb0000000 | (vidc.v_display_end << 14));
vidc_writel(0xb4000000 | (vidc.v_border_end << 14));
vidc_writel(0xb8000000);
vidc_writel(0xbc000000);
}
#ifdef DEBUG_MODE_SELECTION
printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
var->yres, var->bits_per_pixel);
printk(KERN_DEBUG " H-cycle : %d\n", vidc.h_cycle);
printk(KERN_DEBUG " H-sync-width : %d\n", vidc.h_sync_width);
printk(KERN_DEBUG " H-border-start : %d\n", vidc.h_border_start);
printk(KERN_DEBUG " H-display-start : %d\n", vidc.h_display_start);
printk(KERN_DEBUG " H-display-end : %d\n", vidc.h_display_end);
printk(KERN_DEBUG " H-border-end : %d\n", vidc.h_border_end);
printk(KERN_DEBUG " H-interlace : %d\n", vidc.h_interlace);
printk(KERN_DEBUG " V-cycle : %d\n", vidc.v_cycle);
printk(KERN_DEBUG " V-sync-width : %d\n", vidc.v_sync_width);
printk(KERN_DEBUG " V-border-start : %d\n", vidc.v_border_start);
printk(KERN_DEBUG " V-display-start : %d\n", vidc.v_display_start);
printk(KERN_DEBUG " V-display-end : %d\n", vidc.v_display_end);
printk(KERN_DEBUG " V-border-end : %d\n", vidc.v_border_end);
printk(KERN_DEBUG " VIDC Ctrl (E) : 0x%08X\n", vidc_ctl);
printk(KERN_DEBUG " IOEB Ctrl : 0x%08X\n", vid_ctl);
#endif
}
static int
acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
union palette pal;
if (regno >= current_par.palette_size)
return 1;
pal.p = 0;
pal.vidc.reg = regno;
pal.vidc.red = red >> 12;
pal.vidc.green = green >> 12;
pal.vidc.blue = blue >> 12;
current_par.palette[regno] = pal;
vidc_writel(pal.p);
return 0;
}
#endif
#ifdef HAS_VIDC20
#include <mach/acornfb.h>
@ -634,16 +394,7 @@ acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int
/* hsync_len must be even */
var->hsync_len = (var->hsync_len + 1) & ~1;
#ifdef HAS_VIDC
/* left_margin must be odd */
if ((var->left_margin & 1) == 0) {
var->left_margin -= 1;
var->right_margin += 1;
}
/* right_margin must be odd */
var->right_margin |= 1;
#elif defined(HAS_VIDC20)
#if defined(HAS_VIDC20)
/* left_margin must be even */
if (var->left_margin & 1) {
var->left_margin += 1;
@ -787,11 +538,7 @@ static int acornfb_set_par(struct fb_info *info)
break;
case 8:
current_par.palette_size = VIDC_PALETTE_SIZE;
#ifdef HAS_VIDC
info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
#else
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
#endif
break;
#ifdef HAS_VIDC20
case 16:
@ -971,9 +718,6 @@ static void acornfb_init_fbinfo(void)
#if defined(HAS_VIDC20)
fb_info.var.red.length = 8;
fb_info.var.transp.length = 4;
#elif defined(HAS_VIDC)
fb_info.var.red.length = 4;
fb_info.var.transp.length = 1;
#endif
fb_info.var.green = fb_info.var.red;
fb_info.var.blue = fb_info.var.red;
@ -1310,14 +1054,6 @@ static int acornfb_probe(struct platform_device *dev)
fb_info.fix.smem_start = handle;
}
#endif
#if defined(HAS_VIDC)
/*
* Archimedes/A5000 machines use a fixed address for their
* framebuffers. Free unused pages
*/
free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
#endif
fb_info.fix.smem_len = size;
current_par.palette_size = VIDC_PALETTE_SIZE;

View File

@ -13,10 +13,6 @@
#include <asm/hardware/iomd.h>
#define VIDC_PALETTE_SIZE 256
#define VIDC_NAME "VIDC20"
#elif defined(HAS_VIDC)
#include <asm/hardware/memc.h>
#define VIDC_PALETTE_SIZE 16
#define VIDC_NAME "VIDC"
#endif
#define EXTEND8(x) ((x)|(x)<<8)
@ -101,31 +97,6 @@ struct modex_params {
const struct modey_params *modey;
};
#ifdef HAS_VIDC
#define VID_CTL_VS_NVSYNC (1 << 3)
#define VID_CTL_HS_NHSYNC (1 << 2)
#define VID_CTL_24MHz (0)
#define VID_CTL_25MHz (1)
#define VID_CTL_36MHz (2)
#define VIDC_CTRL_CSYNC (1 << 7)
#define VIDC_CTRL_INTERLACE (1 << 6)
#define VIDC_CTRL_FIFO_0_4 (0 << 4)
#define VIDC_CTRL_FIFO_1_5 (1 << 4)
#define VIDC_CTRL_FIFO_2_6 (2 << 4)
#define VIDC_CTRL_FIFO_3_7 (3 << 4)
#define VIDC_CTRL_1BPP (0 << 2)
#define VIDC_CTRL_2BPP (1 << 2)
#define VIDC_CTRL_4BPP (2 << 2)
#define VIDC_CTRL_8BPP (3 << 2)
#define VIDC_CTRL_DIV3 (0 << 0)
#define VIDC_CTRL_DIV2 (1 << 0)
#define VIDC_CTRL_DIV1_5 (2 << 0)
#define VIDC_CTRL_DIV1 (3 << 0)
#endif
#ifdef HAS_VIDC20
/*
* VIDC20 registers

View File

@ -152,8 +152,6 @@ static int mxc_w1_remove(struct platform_device *pdev)
clk_disable_unprepare(mdev->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}

View File

@ -234,9 +234,11 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
{
long tmp;
struct w1_master *md = dev_to_w1_master(dev);
int ret;
if (strict_strtol(buf, 0, &tmp) == -EINVAL)
return -EINVAL;
ret = kstrtol(buf, 0, &tmp);
if (ret)
return ret;
mutex_lock(&md->mutex);
md->search_count = tmp;
@ -266,9 +268,11 @@ static ssize_t w1_master_attribute_store_pullup(struct device *dev,
{
long tmp;
struct w1_master *md = dev_to_w1_master(dev);
int ret;
if (strict_strtol(buf, 0, &tmp) == -EINVAL)
return -EINVAL;
ret = kstrtol(buf, 0, &tmp);
if (ret)
return ret;
mutex_lock(&md->mutex);
md->enable_pullup = tmp;

View File

@ -162,7 +162,8 @@ extern asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
#define HPWDT_ARCH 32
asm(".text \n\t"
".align 4 \n"
".align 4 \n\t"
".globl asminline_call \n"
"asminline_call: \n\t"
"pushl %ebp \n\t"
"movl %esp, %ebp \n\t"
@ -352,7 +353,8 @@ static int detect_cru_service(void)
#define HPWDT_ARCH 64
asm(".text \n\t"
".align 4 \n"
".align 4 \n\t"
".globl asminline_call \n"
"asminline_call: \n\t"
"pushq %rbp \n\t"
"movq %rsp, %rbp \n\t"

View File

@ -836,7 +836,7 @@ affs_truncate(struct inode *inode)
struct address_space *mapping = inode->i_mapping;
struct page *page;
void *fsdata;
u32 size = inode->i_size;
loff_t size = inode->i_size;
int res;
res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);

Some files were not shown because too many files have changed in this diff Show More