* [PATCH v6 00/22] OMAP USB Host cleanup
From: Roger Quadros @ 2013-01-16 14:43 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This patchset addresses the following
- Consolidate USB Host platform data.
- Avoid addressing clocks one by one by name and use a for loop + bunch
of cleanups.
- Get number of channels/ports dynamically either from revision register
or from platform data. Avoids getting clocks that are not present.
- Add OMAP5 and HSIC mode (Not tested)
v6:
- Added USB Host platform data consolidation patch as the first patch
based on request from Tony.
- Rebased on v3.8-rc3
v5:
- Rebased on top of todays arm-soc/for-next
- Removed the clock merging patch from the list.
- Updated patches 14, 19 and 20 to accomodate the above change.
- Added patch 22 to fix a build warning.
v4:
- Added appropriate maintainers in to/cc
- minor print message fix in patch 23 to maintain consistency
v3:
- Rebased on arm-soc/for-next commit f979306c4d38d213c6977aaf3b1115e8ded71e3a
- Rearranged patch that get rids of cpu_is_omap..() macros
- Coding style fixes
v2:
- Clocks are allocated dynamically based on number of ports available
on the platform
- Reduced console spam if non critical clocks are not found on the platform.
- Get rid of cpu_is_.. macros from USB host driver.
cheers,
-roger
The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:
Linux 3.8-rc3 (2013-01-09 18:59:55 -0800)
are available in the git repository at:
git at github.com:rogerq/linux.git linux-usbhost11-part
Roger Quadros (22):
mfd: omap-usb-host: Consolidate OMAP USB-HS platform data
mfd: omap-usb-tll: Fix channel count detection
mfd: omap-usb-tll: Use devm_kzalloc/ioremap and clean up error path
mfd: omap-usb-tll: Clean up clock handling
mfd: omap-usb-tll: introduce and use mode_needs_tll()
mfd: omap-usb-tll: Check for missing platform data in probe
mfd: omap-usb-tll: Fix error message
mfd: omap-usb-tll: serialize access to TLL device
mfd: omap-usb-tll: Add OMAP5 revision and HSIC support
mfd: omap_usb_host: Avoid missing platform data checks in
suspend/resume
mfd: omap-usb-host: Use devm_kzalloc() and devm_request_and_ioremap()
mfd: omap-usb-host: know about number of ports from revision register
mfd: omap-usb-host: override number of ports from platform data
mfd: omap-usb-host: cleanup clock management code
mfd: omap-usb-host: Manage HSIC clocks for HSIC mode
mfd: omap-usb-host: Get rid of unnecessary spinlock
mfd: omap-usb-host: clean up omap_usbhs_init()
USB: ehci-omap: Don't free gpios that we didn't request
ARM: OMAP3: clock data: get rid of unused USB host clock aliases and
dummies
ARM: OMAP4: clock data: get rid of unused USB host clock aliases
mfd: omap-usb-host: Don't spam console on clk_set_parent failure
mdf: omap-usb-host: get rid of build warning
arch/arm/mach-omap2/board-3430sdp.c | 2 +-
arch/arm/mach-omap2/board-3630sdp.c | 2 +-
arch/arm/mach-omap2/board-am3517crane.c | 2 +-
arch/arm/mach-omap2/board-am3517evm.c | 2 +-
arch/arm/mach-omap2/board-cm-t35.c | 2 +-
arch/arm/mach-omap2/board-cm-t3517.c | 2 +-
arch/arm/mach-omap2/board-devkit8000.c | 2 +-
arch/arm/mach-omap2/board-igep0020.c | 4 +-
arch/arm/mach-omap2/board-omap3beagle.c | 2 +-
arch/arm/mach-omap2/board-omap3evm.c | 2 +-
arch/arm/mach-omap2/board-omap3pandora.c | 2 +-
arch/arm/mach-omap2/board-omap3stalker.c | 2 +-
arch/arm/mach-omap2/board-omap3touchbook.c | 2 +-
arch/arm/mach-omap2/board-omap4panda.c | 2 +-
arch/arm/mach-omap2/board-overo.c | 2 +-
arch/arm/mach-omap2/board-zoom.c | 2 +-
arch/arm/mach-omap2/cclock3xxx_data.c | 11 -
arch/arm/mach-omap2/cclock44xx_data.c | 7 -
arch/arm/mach-omap2/usb-host.c | 29 +--
arch/arm/mach-omap2/usb.h | 20 +-
drivers/mfd/omap-usb-host.c | 543 ++++++++++++++++------------
drivers/mfd/omap-usb-tll.c | 243 +++++++------
drivers/usb/host/ehci-omap.c | 14 +-
include/linux/platform_data/usb-omap.h | 24 +-
24 files changed, 484 insertions(+), 441 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [RFC PATCH 3/4] ARM: bL_entry: Match memory barriers to architectural requirements
From: Santosh Shilimkar @ 2013-01-16 14:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130116124718.GC1963@linaro.org>
On Wednesday 16 January 2013 06:17 PM, Dave Martin wrote:
> On Wed, Jan 16, 2013 at 05:41:00PM +0530, Santosh Shilimkar wrote:
>> On Wednesday 16 January 2013 05:19 PM, Dave Martin wrote:
>>> On Wed, Jan 16, 2013 at 12:20:47PM +0530, Santosh Shilimkar wrote:
>>>> + Catalin, RMK
>>>>
>>>> Dave,
>>>>
>>>> On Tuesday 15 January 2013 10:18 PM, Dave Martin wrote:
>>>>> For architectural correctness even Strongly-Ordered memory accesses
>>>>> require barriers in order to guarantee that multiple CPUs have a
>>>>> coherent view of the ordering of memory accesses.
>>>>>
>>>>> Virtually everything done by this early code is done via explicit
>>>>> memory access only, so DSBs are seldom required. Existing barriers
>>>>> are demoted to DMB, except where a DSB is needed to synchronise
>>>>> non-memory signalling (i.e., before a SEV). If a particular
>>>>> platform performs cache maintenance in its power_up_setup function,
>>>>> it should force it to complete explicitly including a DSB, instead
>>>>> of relying on the bL_head framework code to do it.
>>>>>
>>>>> Some additional DMBs are added to ensure all the memory ordering
>>>>> properties required by the race avoidance algorithm. DMBs are also
>>>>> moved out of loops, and for clarity some are moved so that most
>>>>> directly follow the memory operation which needs to be
>>>>> synchronised.
>>>>>
>>>>> The setting of a CPU's bL_entry_vectors[] entry is also required to
>>>>> act as a synchronisation point, so a DMB is added after checking
>>>>> that entry to ensure that other CPUs do not observe gated
>>>>> operations leaking across the opening of the gate.
>>>>>
>>>>> Signed-off-by: Dave Martin <dave.martin@linaro.org>
>>>>> ---
>>>>
>>>> Sorry to pick on this again but I am not able to understand why
>>>> the strongly ordered access needs barriers. At least from the
>>>> ARM point of view, a strongly ordered write will be more of blocking
>>>> write and the further interconnect also is suppose to respect that
>>>
>>> This is what I originally assumed (hence the absence of barriers in
>>> the initial patch).
>>>
>>>> rule. SO read writes are like adding barrier after every load store
>>>
>>> This assumption turns out to be wrong, unfortunately, although in
>>> a uniprocessor scenario is makes no difference. A SO memory access
>>> does block the CPU making the access, but explicitly does not
>>> block the interconnect.
>>>
>> I suspected the interconnect part when you described the barrier
>> need for SO memory region.
>>
>>> In a typical boot scenario for example, all secondary CPUs are
>>> quiescent or powered down, so there's no problem. But we can't make
>>> the same assumptions when we're trying to coordinate between
>>> multiple active CPUs.
>>>
>>>> so adding explicit barriers doesn't make sense. Is this a side
>>>> effect of some "write early response" kind of optimizations at
>>>> interconnect level ?
>>>
>>> Strongly-Ordered accesses are always non-shareable, so there is
>>> no explicit guarantee of coherency between multiple masters.
>>>
>> This is where probably issue then. My understanding is exactly
>> opposite here and hence I wasn't worried about multi-master
>> CPU scenario since sharable attributes would be taking care of it
>> considering the same page tables being used in SMP system.
>>
>> ARM documentation says -
>> ------------
>> Shareability and the S bit, with TEX remap
>> The memory type of a region, as indicated in the Memory type column
>> of Table B3-12 on page B3-1350, provides
>> the first level of control of whether the region is shareable:
>> ? If the memory type is Strongly-ordered then the region is Shareable
>> ------------------------------------------------------------
>
> Hmmm, it looks like you're right here. My assumption that SO implies
> non-shareable is wrong. This is backed up by:
>
> A3.5.6 Device and Strongly-ordered memory
>
> "Address locations marked as Strongly-ordered [...] are always treated
> as Shareable."
>
>
> I think this is sufficient to ensure that if two CPUs access the same
> location with SO accesses, each will see an access order to any single
> location which is consistent with the program order of the accesses on
> the other CPUs. (This comes from the glossary definition of Coherent.)
>
> However, I can't see any general guarantee for accesses to _different_
> locations, beyond the guarantees for certain special cases given in
> A3.8.2 Ordering requirements for memory accesses (address and control
> dependencies etc.)
>
> This may make some of the dmbs unnecessary, but it is not clear whether
> they are all unnecessary.
>
>
> I'll need to follow up on this and see if we can get an answer.
>
Thanks David. I am looking forward to hear more on this.
Regards,
Santosh
^ permalink raw reply
* [PATCH] [RFC] ARM: compile fix for DEBUG_LL=y && MMU=n
From: Uwe Kleine-König @ 2013-01-16 14:32 UTC (permalink / raw)
To: linux-arm-kernel
debug_ll_addr is only used on machines with an MMU so it can be #ifdef'ed
out safely. This fixes:
arch/arm/kernel/debug.S: Assembler messages:
arch/arm/kernel/debug.S:104: Error: too many positional arguments
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Olof Johansson <olof@lixom.net>
---
The obvious alternative fix is to make addruart on !MMU take 3
arguments, too.
The problem was introduced in
e5c5f2a (ARM: implement debug_ll_io_init())
which appeared in v3.8-rc1.
---
arch/arm/kernel/debug.S | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 6809200..14f7c3b 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -100,12 +100,14 @@ ENTRY(printch)
b 1b
ENDPROC(printch)
+#ifdef CONFIG_MMU
ENTRY(debug_ll_addr)
addruart r2, r3, ip
str r2, [r0]
str r3, [r1]
mov pc, lr
ENDPROC(debug_ll_addr)
+#endif
#else
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/5] W1: Support onewire master on i.MX53
From: Evgeniy Polyakov @ 2013-01-16 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130116094821.9660.18278.stgit@localhost>
Hi
On Wed, Jan 16, 2013 at 10:48:21AM +0100, Martin Fuzzey (mfuzzey at parkeon.com) wrote:
> W1: Support onewire master on i.MX53
> * Add device tree and pinctrl support to the MXC master driver
> * Add i.MX53 clocks
> * Add i.MX53 device tree entries
>
> The final patch converts the driver to use devm_
Looks good to me, thank you
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
--
Evgeniy Polyakov
^ permalink raw reply
* [PATCH 4/4] ARM: uncompress: support uncompress debug for multiplatform build
From: Shawn Guo @ 2013-01-16 14:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130115190401.GA28333@quad.lixom.net>
On Tue, Jan 15, 2013 at 11:04:01AM -0800, Olof Johansson wrote:
> Most functionality to deal with this already exist in the
> include/debug/*.S files files, you just need to instantiate the macros
> somewhere (compressed/head.S, or a separate file), and wrap the calls
> to those instantiated assembly functions in a generic header file.
>
> That way, every platform that has a DEBUG_LL implementation should be able to
> reuse that, and no need to enable every platform one by one.
>
Ok, got your point. I'm working on a solution as what you suggest here.
So please ignore that pull request I sent.
Shawn
^ permalink raw reply
* [PATCH 10/14] PCI: tegra: Move PCIe driver to drivers/pci/host
From: Arnd Bergmann @ 2013-01-16 14:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130115211441.GA13139@avionic-0098.adnet.avionic-design.de>
On Tuesday 15 January 2013, Thierry Reding wrote:
> Is there actually hardware that supports this? I assumed that the MSI
> controller would have to be tightly coupled to the PCI host bridge in
> order to raise an interrupt when an MSI is received via PCI.
No, as long as it's guaranteed that the MSI notification won't arrive
at the CPU before any inbound DMA data before it, the MSI controller
can be anywhere. Typically, the MSI controller is actually closer to
the CPU core than to the PCI bridge. On X86, I believe the MSI address
is on normally on the the "local APIC" on each CPU.
Arnd
^ permalink raw reply
* [PATCH v5 1/9] ARM: davinci: da850 board: change pr_warning() to pr_warn()
From: Sekhar Nori @ 2013-01-16 13:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357863807-380-2-git-send-email-rtivy@ti.com>
On 1/11/2013 5:53 AM, Robert Tivy wrote:
> Changed all pr_warning() calls to pr_warn(), as advised by checkpatch.pl.
>
> Also, while modifying those pr_warning() calls I changed hardcoded
> function names to use '"%s:", __func__' instead, and converted acronym
> usage to upper case
>
> Signed-off-by: Robert Tivy <rtivy@ti.com>
Applying this patch for v3.9. While committing I updated the commit
message to change past tense to present and also removed the first
person reference.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 3/3] can: c_can: Enable clock before first use
From: Rafael J. Wysocki @ 2013-01-16 13:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <331ABD5ECB02734CA317220B2BBEABC13EAED247@DBDE01.ent.ti.com>
On Wednesday, January 16, 2013 09:54:38 AM AnilKumar, Chimata wrote:
> +Rafael +arm list
>
> On Wed, Jan 16, 2013 at 13:33:27, Amit Virdi wrote:
> > On 12/20/2012 7:37 PM, Marc Kleine-Budde wrote:
> > > On 12/20/2012 11:05 AM, Amit Virdi wrote:
> > >> Current implementation assumes clock to be always enabled. Instead,
> > >> explicitly enable device clock before usage.
> > >>
> > >> Signed-off-by: Amit Virdi<amit.virdi@st.com>
> > >> Reviewed-by: Shiraz Hashim<shiraz.hashim@st.com>
> > >> ---
> > >> drivers/net/can/c_can/c_can_platform.c | 8 ++++++++
> > >> 1 file changed, 8 insertions(+)
> > >>
> > >> diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
> > >> index 6e8dc56..d0bd6e6 100644
> > >> --- a/drivers/net/can/c_can/c_can_platform.c
> > >> +++ b/drivers/net/can/c_can/c_can_platform.c
> > >> @@ -194,6 +194,12 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
> > >> goto exit;
> > >> }
> > >>
> > >> + ret = clk_prepare_enable(clk);
> > >> + if (ret) {
> > >> + dev_err(&pdev->dev, "could not prepare CAN clock\n");
> > >> + goto exit_no_clk_en;
> > >> + }
> > >> +
> > >> /* get the platform data */
> > >> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > >> irq = platform_get_irq(pdev, 0);
> > >> @@ -295,6 +301,8 @@ exit_iounmap:
> > >> exit_release_mem:
> > >> release_mem_region(mem->start, resource_size(mem));
> > >> exit_free_clk:
> > >> + clk_disable_unprepare(clk);
> > >> +exit_no_clk_en:
> > >> clk_put(clk);
> > >> exit:
> > >> dev_err(&pdev->dev, "probe failed\n");
> > >
> > > Why do you have to enable the clock if the driver is loaded? What about
> > > disabling the clock on driver unload. The clock should be enabled on
> > > open and disabled on close if the network interface. If you need to
> > > access the registers of your hardware, you should enable the clock
> > > before accessing the regs and disable the clock when finished.
> > >
> >
> > Okay, I would take care of it in V2.
>
> Hi Amit,
>
> As Marc said clock enable/disable should be in sync with open/
> close functions. I think pm_runtime calls should take care of
> clock control. In your case you have to create a wrapper which
> exports runtime pm hooks, which should internally handle the
> clock enable/disable.
>
> If we add clock specific calls to the driver, then driver might
> break on the platforms which has runtime pm implemented because
> runtime pm support to the c_can driver is already added.
>
> Rafael,
>
> Do you have any suggestions here? Am I missing anything here?
No, you aren't.
Clock-specific hooks in the driver (outside of its PM callbacks) may not work
or worse yet may cause problems to happen on platforms where PM is handled
via ACPI, for example.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply
* [PATCH 2/4] serial: vt8500: ioremap'd resource is never freed
From: Sergei Shtylyov @ 2013-01-16 13:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358225886-5686-3-git-send-email-linux@prisktech.co.nz>
Hello.
On 15-01-2013 8:58, Tony Prisk wrote:
> Memory mapped via ioremap call is never released. Rather than add an
> iounmap call, change allocation function to devm_request_and_ioremap.
> Also, change the error on failure for this call to -EBUSY rather than
> -EADDRNOTAVAIL.
You meant "-EADDRNOTAVAIL rather than -ENOMEM". ;-)
> Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
> ---
> drivers/tty/serial/vt8500_serial.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
> diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
> index 4c4a58d..3e76dff 100644
> --- a/drivers/tty/serial/vt8500_serial.c
> +++ b/drivers/tty/serial/vt8500_serial.c
> @@ -615,9 +615,9 @@ static int vt8500_serial_probe(struct platform_device *pdev)
> snprintf(vt8500_port->name, sizeof(vt8500_port->name),
> "VT8500 UART%d", pdev->id);
>
> - vt8500_port->uart.membase = ioremap(mmres->start, resource_size(mmres));
> + vt8500_port->uart.membase = devm_request_and_ioremap(&pdev->dev, mmres);
> if (!vt8500_port->uart.membase) {
> - ret = -ENOMEM;
> + ret = -EADDRNOTAVAIL;
> goto err;
> }
WBR, Sergei
^ permalink raw reply
* [PATCH 3/4] Enable ecc-mode selection in the driver
From: Andrew Lunn @ 2013-01-16 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F6927D.3070303@mpl.ch>
On Wed, Jan 16, 2013 at 12:43:57PM +0100, Stefan Peter wrote:
> Hi Andrew
>
> on 15.01.2013 13:51, Andrew Lunn wrote:
> > On Tue, Jan 15, 2013 at 01:13:12PM +0100, Stefan Peter wrote:
> >> In order to be able to use the ecc-mode, add the bch module to the default
> >> settings for the kirwood boards and enable the activation in orin-nand.c
> >>
> >> Signed-off-by: Stefan Peter <s.peter@mpl.ch>
> >> ---
> >> diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
> >> index 93f3794..4a9d3f7 100644
> >> --- a/arch/arm/configs/kirkwood_defconfig
> >> +++ b/arch/arm/configs/kirkwood_defconfig
> >> @@ -84,6 +84,7 @@ CONFIG_MTD_CFI_STAA=y
> >> CONFIG_MTD_PHYSMAP=y
> >> CONFIG_MTD_M25P80=y
> >> CONFIG_MTD_NAND=y
> >> +CONFIG_MTD_NAND_ECC_BCH=y
> >> CONFIG_MTD_NAND_ORION=y
> >> CONFIG_BLK_DEV_LOOP=y
> >> # CONFIG_SCSI_PROC_FS is not set
> >> diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
> >> index cd72b92..1a35257 100644
> >> --- a/drivers/mtd/nand/orion_nand.c
> >> +++ b/drivers/mtd/nand/orion_nand.c
> >> @@ -14,6 +14,7 @@
> >> #include <linux/module.h>
> >> #include <linux/platform_device.h>
> >> #include <linux/of.h>
> >> +#include <linux/of_mtd.h>
> >> #include <linux/mtd/mtd.h>
> >> #include <linux/mtd/nand.h>
> >> #include <linux/mtd/partitions.h>
> >> @@ -130,6 +131,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
> >> if (!of_property_read_u32(pdev->dev.of_node,
> >> "chip-delay", &val))
> >> board->chip_delay = (u8)val;
> >> + board->ecc_mode = of_get_nand_ecc_mode(pdev->dev.of_node);
> >
> >> } else
> >> board = pdev->dev.platform_data;
> >>
> >> @@ -140,7 +142,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)
> >> nc->IO_ADDR_R = nc->IO_ADDR_W = io_base;
> >> nc->cmd_ctrl = orion_nand_cmd_ctrl;
> >> nc->read_buf = orion_nand_read_buf;
> >> - nc->ecc.mode = NAND_ECC_SOFT;
> >> + nc->ecc.mode = board->ecc_mode == NAND_ECC_SOFT_BCH ?
> >> + NAND_ECC_SOFT_BCH : NAND_ECC_SOFT;
> >
> > Hi Stefan
> >
> > What about a user that wants one of the other valid values?
> > NAND_ECC_OOB_FIRST, NAND_ECC_HW_SYNDROME, etc.
>
> As far as I understand, NAND_ECC_NONE, NAND_ECC_SOFT and
> NAND_ECC_SOFT_BCH are the only ECC modes that do not require
> corresponding hardware support which is missing in the marvell
> 88F6180/88F619x/88F628x. From my point of view, NAND_ECC_NONE does not
> make sense, too, because MLC NAND Flash requires ECC to be usable.
>
> >
> > Would:
> >
> > if (IS_ERR(board->ecc_mode)) {
> > nc->ecc.mode = NAND_ECC_SOFT;
> > dev_info(&pdev->dev, "Defaulting to NAND_ECC_SOFT");
> > } else
> > nc->ecc.mode = board->ecc_mode
> >
> > be better?
>
> I feel safer by limiting the modes to what I could test.
Hi Stefan
O.K, but i still think a warning message would be useful when
board->ecc_mode is an error code.
Andrew
^ permalink raw reply
* [PATCH v5 07/14] KVM: ARM: World-switch implementation
From: Russell King - ARM Linux @ 2013-01-16 13:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130116121238.GS11529@redhat.com>
If you're going to bother commenting on a big long email, please
_CHOP OUT_ content which is not relevant to your reply. I paged down 5
pages, hit end, paged up, found no comment from you, so I'm not going to
bother reading anything further in this message.
Help your readers to read your email. Don't expect them to search a
1600-line email message for a one line reply.
(This has been said many times over the history of the Internet. There's
etiquette documents on Internet mail stating it too. Please, comply
with it or you will find people will ignore your messages.)
^ permalink raw reply
* [PATCH 5/5] mmc: mvsdio: add pinctrl integration
From: Andrew Lunn @ 2013-01-16 13:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358342040-7130-1-git-send-email-andrew@lunn.ch>
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
On many Marvell SoCs, the pins used for the SDIO interface are part of
the MPP pins, that are muxable pins. In order to get the muxing of
those pins correct, this commit integrates the mvsdio driver with the
pinctrl infrastructure by calling devm_pinctrl_get_select_default()
during ->probe().
Note that we permit this function to fail because not all Marvell
platforms have yet been fully converted to using the pinctrl
infrastructure.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Stefan Peter <s.peter@mpl.ch>
Tested-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
drivers/mmc/host/mvsdio.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 5ea0b96..a8b27dd 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -25,6 +25,7 @@
#include <linux/of_irq.h>
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/sizes.h>
#include <asm/unaligned.h>
@@ -690,6 +691,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
struct resource *r;
int ret, irq;
int gpio_card_detect, gpio_write_protect;
+ struct pinctrl *pinctrl;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
@@ -706,6 +708,10 @@ static int __init mvsd_probe(struct platform_device *pdev)
host->mmc = mmc;
host->dev = &pdev->dev;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "no pins associated\n");
+
/* Some non-DT platforms do not pass a clock, and the clock
frequency is passed through platform_data. On DT platforms,
a clock must always be passed, even if there is no gatable
--
1.7.10.4
^ permalink raw reply related
* [PATCH 4/5] mmc: mvsdio: implement a Device Tree binding
From: Andrew Lunn @ 2013-01-16 13:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358342040-7130-1-git-send-email-andrew@lunn.ch>
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
This patch adds a simple Device Tree binding for the mvsdio driver, as
well as the necessary documentation for it. Compatibility with non-DT
platforms is preserved, by keeping the platform_data based
initialization.
We introduce a small difference between non-DT and DT platforms: DT
platforms are required to provide a clocks = <...> property, which the
driver uses to get the frequency of the clock that goes to the SDIO
IP. The behaviour on non-DT platforms is kept unchanged: a clock
reference is not mandatory, but the clock frequency must be passed in
the "clock" field of the mvsdio_platform_data structure.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Stefan Peter <s.peter@mpl.ch>
Tested-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
.../devicetree/bindings/mmc/orion-sdio.txt | 17 ++++++
drivers/mmc/host/mvsdio.c | 62 +++++++++++++++-----
2 files changed, 64 insertions(+), 15 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mmc/orion-sdio.txt
diff --git a/Documentation/devicetree/bindings/mmc/orion-sdio.txt b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
new file mode 100644
index 0000000..84f0ebd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
@@ -0,0 +1,17 @@
+* Marvell orion-sdio controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the orion-sdio driver.
+
+- compatible: Should be "marvell,orion-sdio"
+- clocks: reference to the clock of the SDIO interface
+
+Example:
+
+ mvsdio at d00d4000 {
+ compatible = "marvell,orion-sdio";
+ reg = <0xd00d4000 0x200>;
+ interrupts = <54>;
+ clocks = <&gateclk 17>;
+ status = "disabled";
+ };
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 704b7a3..5ea0b96 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -21,6 +21,8 @@
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
@@ -681,17 +683,17 @@ mv_conf_mbus_windows(struct mvsd_host *host,
static int __init mvsd_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct mmc_host *mmc = NULL;
struct mvsd_host *host = NULL;
- const struct mvsdio_platform_data *mvsd_data;
const struct mbus_dram_target_info *dram;
struct resource *r;
int ret, irq;
+ int gpio_card_detect, gpio_write_protect;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
- mvsd_data = pdev->dev.platform_data;
- if (!r || irq < 0 || !mvsd_data)
+ if (!r || irq < 0)
return -ENXIO;
mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
@@ -703,8 +705,37 @@ static int __init mvsd_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->mmc = mmc;
host->dev = &pdev->dev;
- host->base_clock = mvsd_data->clock / 2;
- host->clk = ERR_PTR(-EINVAL);
+
+ /* Some non-DT platforms do not pass a clock, and the clock
+ frequency is passed through platform_data. On DT platforms,
+ a clock must always be passed, even if there is no gatable
+ clock associated to the SDIO interface (it can simply be a
+ fixed rate clock). */
+ host->clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(host->clk))
+ clk_prepare_enable(host->clk);
+
+ if (np) {
+ if (IS_ERR(host->clk)) {
+ dev_err(&pdev->dev, "DT platforms must have a clock associated\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ host->base_clock = clk_get_rate(host->clk) / 2;
+ gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0);
+ gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0);
+ } else {
+ const struct mvsdio_platform_data *mvsd_data;
+ mvsd_data = pdev->dev.platform_data;
+ if (!mvsd_data) {
+ ret = -ENXIO;
+ goto out;
+ }
+ host->base_clock = mvsd_data->clock / 2;
+ gpio_card_detect = mvsd_data->gpio_card_detect;
+ gpio_write_protect = mvsd_data->gpio_write_protect;
+ }
mmc->ops = &mvsd_ops;
@@ -743,20 +774,14 @@ static int __init mvsd_probe(struct platform_device *pdev)
goto out;
}
- /* Not all platforms can gate the clock, so it is not
- an error if the clock does not exists. */
- host->clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(host->clk))
- clk_prepare_enable(host->clk);
-
- if (gpio_is_valid(mvsd_data->gpio_card_detect)) {
- ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect);
+ if (gpio_is_valid(gpio_card_detect)) {
+ ret = mmc_gpio_request_cd(mmc, gpio_card_detect);
if (ret)
goto out;
} else
mmc->caps |= MMC_CAP_NEEDS_POLL;
- mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
+ mmc_gpio_request_ro(mmc, gpio_write_protect);
setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
platform_set_drvdata(pdev, mmc);
@@ -768,7 +793,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
mmc_hostname(mmc), DRIVER_NAME);
if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
printk("using GPIO %d for card detection\n",
- mvsd_data->gpio_card_detect);
+ gpio_card_detect);
else
printk("lacking card detect (fall back to polling)\n");
return 0;
@@ -832,12 +857,19 @@ static int mvsd_resume(struct platform_device *dev)
#define mvsd_resume NULL
#endif
+static const struct of_device_id mvsdio_dt_ids[] = {
+ { .compatible = "marvell,orion-sdio" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
+
static struct platform_driver mvsd_driver = {
.remove = __exit_p(mvsd_remove),
.suspend = mvsd_suspend,
.resume = mvsd_resume,
.driver = {
.name = DRIVER_NAME,
+ .of_match_table = mvsdio_dt_ids,
},
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/5] mmc: mvsdio: use slot-gpio for card detect gpio
From: Andrew Lunn @ 2013-01-16 13:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358342040-7130-1-git-send-email-andrew@lunn.ch>
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice
set of helper functions to simplify the management of the card detect
GPIO in MMC host drivers. This patch migrates the mvsdio driver to
using those helpers, which will make the ->probe() code simpler, and
therefore ease the process of adding a Device Tree binding for this
driver.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Stefan Peter <s.peter@mpl.ch>
Tested-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
drivers/mmc/host/mvsdio.c | 39 +++++++++------------------------------
1 file changed, 9 insertions(+), 30 deletions(-)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index c6dc8fd..704b7a3 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -52,7 +52,6 @@ struct mvsd_host {
struct mmc_host *mmc;
struct device *dev;
struct clk *clk;
- int gpio_card_detect;
};
#define mvsd_write(offs, val) writel(val, iobase + (offs))
@@ -538,13 +537,6 @@ static void mvsd_timeout_timer(unsigned long data)
mmc_request_done(host->mmc, mrq);
}
-static irqreturn_t mvsd_card_detect_irq(int irq, void *dev)
-{
- struct mvsd_host *host = dev;
- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
- return IRQ_HANDLED;
-}
-
static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct mvsd_host *host = mmc_priv(mmc);
@@ -757,26 +749,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (!IS_ERR(host->clk))
clk_prepare_enable(host->clk);
- if (mvsd_data->gpio_card_detect) {
- ret = devm_gpio_request_one(&pdev->dev,
- mvsd_data->gpio_card_detect,
- GPIOF_IN, DRIVER_NAME " cd");
- if (ret == 0) {
- irq = gpio_to_irq(mvsd_data->gpio_card_detect);
- ret = devm_request_irq(&pdev->dev, irq,
- mvsd_card_detect_irq,
- IRQ_TYPE_EDGE_RISING |
- IRQ_TYPE_EDGE_FALLING,
- DRIVER_NAME " cd", host);
- if (ret == 0)
- host->gpio_card_detect =
- mvsd_data->gpio_card_detect;
- else
- devm_gpio_free(&pdev->dev,
- mvsd_data->gpio_card_detect);
- }
- }
- if (!host->gpio_card_detect)
+ if (gpio_is_valid(mvsd_data->gpio_card_detect)) {
+ ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect);
+ if (ret)
+ goto out;
+ } else
mmc->caps |= MMC_CAP_NEEDS_POLL;
mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
@@ -789,15 +766,16 @@ static int __init mvsd_probe(struct platform_device *pdev)
pr_notice("%s: %s driver initialized, ",
mmc_hostname(mmc), DRIVER_NAME);
- if (host->gpio_card_detect)
+ if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
printk("using GPIO %d for card detection\n",
- host->gpio_card_detect);
+ mvsd_data->gpio_card_detect);
else
printk("lacking card detect (fall back to polling)\n");
return 0;
out:
if (mmc) {
+ mmc_gpio_free_cd(mmc);
mmc_gpio_free_ro(mmc);
if (!IS_ERR(host->clk))
clk_disable_unprepare(host->clk);
@@ -813,6 +791,7 @@ static int __exit mvsd_remove(struct platform_device *pdev)
struct mvsd_host *host = mmc_priv(mmc);
+ mmc_gpio_free_cd(mmc);
mmc_gpio_free_ro(mmc);
mmc_remove_host(mmc);
del_timer_sync(&host->timer);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/5] mmc: mvsdio: use slot-gpio infrastructure for write protect gpio
From: Andrew Lunn @ 2013-01-16 13:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358342040-7130-1-git-send-email-andrew@lunn.ch>
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice
set of helper functions to simplify the management of the write
protect GPIO in MMC host drivers. This patch migrates the mvsdio
driver to using those helpers, which will make the ->probe() code
simpler, and therefore ease the process of adding a Device Tree
binding for this driver.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Stefan Peter <s.peter@mpl.ch>
Tested-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
drivers/mmc/host/mvsdio.c | 30 +++++-------------------------
1 file changed, 5 insertions(+), 25 deletions(-)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index f8dd361..c6dc8fd 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
#include <asm/sizes.h>
#include <asm/unaligned.h>
@@ -52,7 +53,6 @@ struct mvsd_host {
struct device *dev;
struct clk *clk;
int gpio_card_detect;
- int gpio_write_protect;
};
#define mvsd_write(offs, val) writel(val, iobase + (offs))
@@ -564,20 +564,6 @@ static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable)
spin_unlock_irqrestore(&host->lock, flags);
}
-static int mvsd_get_ro(struct mmc_host *mmc)
-{
- struct mvsd_host *host = mmc_priv(mmc);
-
- if (host->gpio_write_protect)
- return gpio_get_value(host->gpio_write_protect);
-
- /*
- * Board doesn't support read only detection; let the mmc core
- * decide what to do.
- */
- return -ENOSYS;
-}
-
static void mvsd_power_up(struct mvsd_host *host)
{
void __iomem *iobase = host->base;
@@ -674,7 +660,7 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static const struct mmc_host_ops mvsd_ops = {
.request = mvsd_request,
- .get_ro = mvsd_get_ro,
+ .get_ro = mmc_gpio_get_ro,
.set_ios = mvsd_set_ios,
.enable_sdio_irq = mvsd_enable_sdio_irq,
};
@@ -793,15 +779,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (!host->gpio_card_detect)
mmc->caps |= MMC_CAP_NEEDS_POLL;
- if (mvsd_data->gpio_write_protect) {
- ret = devm_gpio_request_one(&pdev->dev,
- mvsd_data->gpio_write_protect,
- GPIOF_IN, DRIVER_NAME " wp");
- if (ret == 0) {
- host->gpio_write_protect =
- mvsd_data->gpio_write_protect;
- }
- }
+ mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
platform_set_drvdata(pdev, mmc);
@@ -820,6 +798,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
out:
if (mmc) {
+ mmc_gpio_free_ro(mmc);
if (!IS_ERR(host->clk))
clk_disable_unprepare(host->clk);
mmc_free_host(mmc);
@@ -834,6 +813,7 @@ static int __exit mvsd_remove(struct platform_device *pdev)
struct mvsd_host *host = mmc_priv(mmc);
+ mmc_gpio_free_ro(mmc);
mmc_remove_host(mmc);
del_timer_sync(&host->timer);
mvsd_power_down(host);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 1/5] mmc: mvsdio: use devm_ API to simplify/correct error paths.
From: Andrew Lunn @ 2013-01-16 13:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358342040-7130-1-git-send-email-andrew@lunn.ch>
There are a number of bugs in the error paths of this driver. Make
use of devm_ functions to simplify the cleanup on error.
Based on a patch by Russell King.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/mmc/host/mvsdio.c | 92 +++++++++++++++------------------------------
1 file changed, 30 insertions(+), 62 deletions(-)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index de4c20b..f8dd361 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -50,8 +50,6 @@ struct mvsd_host {
struct timer_list timer;
struct mmc_host *mmc;
struct device *dev;
- struct resource *res;
- int irq;
struct clk *clk;
int gpio_card_detect;
int gpio_write_protect;
@@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev)
if (!r || irq < 0 || !mvsd_data)
return -ENXIO;
- r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
- if (!r)
- return -EBUSY;
-
mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
if (!mmc) {
ret = -ENOMEM;
@@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->mmc = mmc;
host->dev = &pdev->dev;
- host->res = r;
host->base_clock = mvsd_data->clock / 2;
+ host->clk = ERR_PTR(-EINVAL);
mmc->ops = &mvsd_ops;
@@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
spin_lock_init(&host->lock);
- host->base = ioremap(r->start, SZ_4K);
+ host->base = devm_request_and_ioremap(&pdev->dev, r);
if (!host->base) {
ret = -ENOMEM;
goto out;
@@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev)
mvsd_power_down(host);
- ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
+ ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
if (ret) {
pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
goto out;
- } else
- host->irq = irq;
+ }
/* Not all platforms can gate the clock, so it is not
an error if the clock does not exists. */
- host->clk = clk_get(&pdev->dev, NULL);
- if (!IS_ERR(host->clk)) {
+ host->clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(host->clk))
clk_prepare_enable(host->clk);
- }
if (mvsd_data->gpio_card_detect) {
- ret = gpio_request(mvsd_data->gpio_card_detect,
- DRIVER_NAME " cd");
+ ret = devm_gpio_request_one(&pdev->dev,
+ mvsd_data->gpio_card_detect,
+ GPIOF_IN, DRIVER_NAME " cd");
if (ret == 0) {
- gpio_direction_input(mvsd_data->gpio_card_detect);
irq = gpio_to_irq(mvsd_data->gpio_card_detect);
- ret = request_irq(irq, mvsd_card_detect_irq,
- IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
- DRIVER_NAME " cd", host);
+ ret = devm_request_irq(&pdev->dev, irq,
+ mvsd_card_detect_irq,
+ IRQ_TYPE_EDGE_RISING |
+ IRQ_TYPE_EDGE_FALLING,
+ DRIVER_NAME " cd", host);
if (ret == 0)
host->gpio_card_detect =
mvsd_data->gpio_card_detect;
else
- gpio_free(mvsd_data->gpio_card_detect);
+ devm_gpio_free(&pdev->dev,
+ mvsd_data->gpio_card_detect);
}
}
if (!host->gpio_card_detect)
mmc->caps |= MMC_CAP_NEEDS_POLL;
if (mvsd_data->gpio_write_protect) {
- ret = gpio_request(mvsd_data->gpio_write_protect,
- DRIVER_NAME " wp");
+ ret = devm_gpio_request_one(&pdev->dev,
+ mvsd_data->gpio_write_protect,
+ GPIOF_IN, DRIVER_NAME " wp");
if (ret == 0) {
- gpio_direction_input(mvsd_data->gpio_write_protect);
host->gpio_write_protect =
mvsd_data->gpio_write_protect;
}
@@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
return 0;
out:
- if (host) {
- if (host->irq)
- free_irq(host->irq, host);
- if (host->gpio_card_detect) {
- free_irq(gpio_to_irq(host->gpio_card_detect), host);
- gpio_free(host->gpio_card_detect);
- }
- if (host->gpio_write_protect)
- gpio_free(host->gpio_write_protect);
- if (host->base)
- iounmap(host->base);
- }
- if (r)
- release_resource(r);
- if (mmc)
- if (!IS_ERR_OR_NULL(host->clk)) {
+ if (mmc) {
+ if (!IS_ERR(host->clk))
clk_disable_unprepare(host->clk);
- clk_put(host->clk);
- }
mmc_free_host(mmc);
+ }
return ret;
}
@@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
- if (mmc) {
- struct mvsd_host *host = mmc_priv(mmc);
+ struct mvsd_host *host = mmc_priv(mmc);
- if (host->gpio_card_detect) {
- free_irq(gpio_to_irq(host->gpio_card_detect), host);
- gpio_free(host->gpio_card_detect);
- }
- mmc_remove_host(mmc);
- free_irq(host->irq, host);
- if (host->gpio_write_protect)
- gpio_free(host->gpio_write_protect);
- del_timer_sync(&host->timer);
- mvsd_power_down(host);
- iounmap(host->base);
- release_resource(host->res);
+ mmc_remove_host(mmc);
+ del_timer_sync(&host->timer);
+ mvsd_power_down(host);
+
+ if (!IS_ERR(host->clk))
+ clk_disable_unprepare(host->clk);
+ mmc_free_host(mmc);
- if (!IS_ERR(host->clk)) {
- clk_disable_unprepare(host->clk);
- clk_put(host->clk);
- }
- mmc_free_host(mmc);
- }
platform_set_drvdata(pdev, NULL);
return 0;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/5] mmc: mvsdio: use devm_ API to simplify/correct error paths.
From: Andrew Lunn @ 2013-01-16 13:13 UTC (permalink / raw)
To: linux-arm-kernel
Russell King pointed out a number of issues with the probe code in the
mvsdio driver and supplied a patch. This patchset uses a modified
version, converting resource allocations to devm API calls, and fixes
the error paths. The patches that then follow are from Thomas
Petazzoni making other cleanups and adding device tree. These patches
needed some changes after the swap to devm. The patches here replace
the earlier submitted patches with the same Subject.
Andrew Lunn (1):
mmc: mvsdio: use devm_ API to simplify/correct error paths.
Thomas Petazzoni (4):
mmc: mvsdio: use slot-gpio infrastructure for write protect gpio
mmc: mvsdio: use slot-gpio for card detect gpio
mmc: mvsdio: implement a Device Tree binding
mmc: mvsdio: add pinctrl integration
.../devicetree/bindings/mmc/orion-sdio.txt | 17 ++
drivers/mmc/host/mvsdio.c | 187 ++++++++------------
2 files changed, 93 insertions(+), 111 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mmc/orion-sdio.txt
--
1.7.10.4
^ permalink raw reply
* ARM DMA: Fix in dma_cache_maint_page
From: Russell King - ARM Linux @ 2013-01-16 13:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358340715.2384.23.camel@dabdike.int.hansenpartnership.com>
On Wed, Jan 16, 2013 at 12:51:55PM +0000, James Bottomley wrote:
> On Wed, 2013-01-16 at 18:17 +0530, Subhash Jadavani wrote:
> > Is it possible to pick up James patch below? Thread here:
> > http://comments.gmane.org/gmane.linux.kernel.mmc/18670, have the details
> > on the motivation behind this fix.
>
> Someone should also audit the arm kernel code for more of these linear
> page array assumptions. I'm guessing that when sparsemem was added to
> arm over a year ago, whoever did it either didn't audit or missed a few.
No, that's a bad assumption. We've had discontigmem for years - maybe
something like 12 years. I switched everything over to sparsemem, and
sparsemem has been used on ARM for years too:
commit 05944d74bc28fffbcce159cb915d0acff82f30a1
Author: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Thu Nov 30 20:43:51 2006 +0000
[ARM] Add initial sparsemem support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
However, there's a big problem with this: very few of the lead people
have machines which suffer from this disability, so there's very little
testing of it - and there's very little testing of new code with it.
The patch which originally introduced this code which your patch
touches was part of adding highmem support to ARM:
commit 43377453af83b8ff8c1c731da1508bd6b84ebfea
Author: Nicolas Pitre <nico@cam.org>
Date: Thu Mar 12 22:52:09 2009 -0400
[ARM] introduce dma_cache_maint_page()
This is a helper to be used by the DMA mapping API to handle cache
maintenance for memory identified by a page structure instead of a
virtual address. Those pages may or may not be highmem pages, and
when they're highmem pages, they may or may not be virtually mapped.
When they're not mapped then there is no L1 cache to worry about. But
even in that case the L2 cache must be processed since unmapped highmem
pages can still be L2 cached.
Signed-off-by: Nicolas Pitre <nico@marvell.com>
some three years later, and has been through a number of revisions since.
I'd really like to get rid of sparsemem so it's one less failure case, but
alas there's a relatively small bunch of folk who rely upon it. That
means it's always going to be more buggy.
^ permalink raw reply
* [PATCH 2/2] ARM: tegra: DTS: cardhu: register UARTC
From: Laxman Dewangan @ 2013-01-16 13:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358341572-8154-1-git-send-email-ldewangan@nvidia.com>
UARTC is used for the interfacing with bluetooth device.
Register this UART channel as high speed serial channel
so that it can use the APB DMA for data transfer.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
The driver file got applied in Greg KH's tty tree.
Tested in linux-next 20121229 with some more changes as
linux-next-20130116 is crashing in pincontrol.
arch/arm/boot/dts/tegra30-cardhu.dtsi | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index bdb2a66..ff6b68f 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -106,6 +106,15 @@
nvidia,slew-rate-rising = <1>;
nvidia,slew-rate-falling = <1>;
};
+ uart3_txd_pw6 {
+ nvidia,pins = "uart3_txd_pw6",
+ "uart3_cts_n_pa1",
+ "uart3_rts_n_pc0",
+ "uart3_rxd_pw7";
+ nvidia,function = "uartc";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
};
};
@@ -114,6 +123,12 @@
clock-frequency = <408000000>;
};
+ serial at 70006200 {
+ compatible = "nvidia,tegra30-hsuart";
+ status = "okay";
+ clock-frequency = <408000000>;
+ };
+
i2c at 7000c000 {
status = "okay";
clock-frequency = <100000>;
--
1.7.1.1
^ permalink raw reply related
* [PATCH 1/2] ARM: tegra: config: enable SERIAL_TEGRA
From: Laxman Dewangan @ 2013-01-16 13:06 UTC (permalink / raw)
To: linux-arm-kernel
Enable high speed serial driver for tegra platform.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
arch/arm/configs/tegra_defconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index a7827fd..4c5cc08 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -112,6 +112,7 @@ CONFIG_INPUT_MPU3050=y
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
--
1.7.1.1
^ permalink raw reply related
* [PATCH v4] video: imxfb: Do not crash on reboot
From: Fabio Estevam @ 2013-01-16 12:58 UTC (permalink / raw)
To: linux-arm-kernel
Issuing a "reboot" command after the LCD times out causes the following
warnings:
Requesting system reboot
------------[ cut here ]------------
WARNING: at drivers/clk/clk.c:471 clk_disable+0x24/0x50()
Modules linked in:
[<c001ad90>] (unwind_backtrace+0x0/0xf4) from [<c0025aac>] (warn_slowpath_common+0x48/0x60)
[<c0025aac>] (warn_slowpath_common+0x48/0x60) from [<c0025ae0>] (warn_slowpath_null+0x1c/0x24)
[<c0025ae0>] (warn_slowpath_null+0x1c/0x24) from [<c03960a0>] (clk_disable+0x24/0x50)
[<c03960a0>] (clk_disable+0x24/0x50) from [<c02695a0>] (imxfb_disable_controller+0x48/0x7c)
[<c02695a0>] (imxfb_disable_controller+0x48/0x7c) from [<c029d838>] (platform_drv_shutdown+0x18/0x1c)
[<c029d838>] (platform_drv_shutdown+0x18/0x1c) from [<c02990fc>] (device_shutdown+0x48/0x14c)
[<c02990fc>] (device_shutdown+0x48/0x14c) from [<c003d09c>] (kernel_restart_prepare+0x2c/0x3c)
[<c003d09c>] (kernel_restart_prepare+0x2c/0x3c) from [<c003d0e4>] (kernel_restart+0xc/0x48)
[<c003d0e4>] (kernel_restart+0xc/0x48) from [<c003d1e8>] (sys_reboot+0xc0/0x1bc)
[<c003d1e8>] (sys_reboot+0xc0/0x1bc) from [<c0014ca0>] (ret_fast_syscall+0x0/0x2c)
---[ end trace da6b502ca79c854f ]---
------------[ cut here ]------------
WARNING: at drivers/clk/clk.c:380 clk_unprepare+0x1c/0x2c()
Modules linked in:
[<c001ad90>] (unwind_backtrace+0x0/0xf4) from [<c0025aac>] (warn_slowpath_common+0x48/0x60)
[<c0025aac>] (warn_slowpath_common+0x48/0x60) from [<c0025ae0>] (warn_slowpath_null+0x1c/0x24)
[<c0025ae0>] (warn_slowpath_null+0x1c/0x24) from [<c0396338>] (clk_unprepare+0x1c/0x2c)
[<c0396338>] (clk_unprepare+0x1c/0x2c) from [<c02695a8>] (imxfb_disable_controller+0x50/0x7c)
[<c02695a8>] (imxfb_disable_controller+0x50/0x7c) from [<c029d838>] (platform_drv_shutdown+0x18/0x1c)
[<c029d838>] (platform_drv_shutdown+0x18/0x1c) from [<c02990fc>] (device_shutdown+0x48/0x14c)
[<c02990fc>] (device_shutdown+0x48/0x14c) from [<c003d09c>] (kernel_restart_prepare+0x2c/0x3c)
[<c003d09c>] (kernel_restart_prepare+0x2c/0x3c) from [<c003d0e4>] (kernel_restart+0xc/0x48)
[<c003d0e4>] (kernel_restart+0xc/0x48) from [<c003d1e8>] (sys_reboot+0xc0/0x1bc)
[<c003d1e8>] (sys_reboot+0xc0/0x1bc) from [<c0014ca0>] (ret_fast_syscall+0x0/0x2c)
---[ end trace da6b502ca79c8550 ]---
------------[ cut here ]------------
This happens because "reboot" triggers imxfb_shutdown(), which calls
imxfb_disable_controller with the clocks already disabled.
To prevent this, add a clock enabled status so that we can check if the clocks
are enabled before disabling them.
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Shawn,
Since you have taken a patch recently that touches this file and given the fact
that we have zero response from the fb maintainer, can you please apply it via
imx tree?
Changes since v3:
- Changed from 'clks_enabled' to 'enabled'
- Use bool instead of int for 'enabled'
Changes since v2:
- Use a better naming for the clk enabled variable
- Return immediately in imxfb_enable_controller/imxfb_disable_controller
if the the clocks are already enabled/disabled.
Changes since v1:
- Protect the whole function instead of only the clocks
drivers/video/imxfb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 8435c5d..609f4e9 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -139,6 +139,7 @@ struct imxfb_info {
struct clk *clk_ahb;
struct clk *clk_per;
enum imxfb_type devtype;
+ bool enabled;
/*
* These are the addresses we mapped
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
static void imxfb_enable_controller(struct imxfb_info *fbi)
{
+
+ if (fbi->enabled)
+ return;
+
pr_debug("Enabling LCD controller\n");
writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
clk_prepare_enable(fbi->clk_ipg);
clk_prepare_enable(fbi->clk_ahb);
clk_prepare_enable(fbi->clk_per);
+ fbi->enabled = true;
if (fbi->backlight_power)
fbi->backlight_power(1);
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
static void imxfb_disable_controller(struct imxfb_info *fbi)
{
+ if (!fbi->enabled)
+ return;
+
pr_debug("Disabling LCD controller\n");
if (fbi->backlight_power)
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
clk_disable_unprepare(fbi->clk_per);
clk_disable_unprepare(fbi->clk_ipg);
clk_disable_unprepare(fbi->clk_ahb);
+ fbi->enabled = false;
writel(0, fbi->regs + LCDC_RMCR);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v5 07/14] KVM: ARM: World-switch implementation
From: Gleb Natapov @ 2013-01-16 12:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANM98qJZcuF95-D=1Qu6cwXUkQrR4a12bZtrZOuP00U2HGkjMQ@mail.gmail.com>
On Tue, Jan 15, 2013 at 11:08:24PM -0500, Christoffer Dall wrote:
> On Tue, Jan 15, 2013 at 9:08 PM, Christoffer Dall
> <c.dall@virtualopensystems.com> wrote:
> > On Tue, Jan 15, 2013 at 4:43 AM, Gleb Natapov <gleb@redhat.com> wrote:
> >> On Tue, Jan 08, 2013 at 01:39:24PM -0500, Christoffer Dall wrote:
> >>> Provides complete world-switch implementation to switch to other guests
> >>> running in non-secure modes. Includes Hyp exception handlers that
> >>> capture necessary exception information and stores the information on
> >>> the VCPU and KVM structures.
> >>>
> >>> The following Hyp-ABI is also documented in the code:
> >>>
> >>> Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
> >>> Switching to Hyp mode is done through a simple HVC #0 instruction. The
> >>> exception vector code will check that the HVC comes from VMID==0 and if
> >>> so will push the necessary state (SPSR, lr_usr) on the Hyp stack.
> >>> - r0 contains a pointer to a HYP function
> >>> - r1, r2, and r3 contain arguments to the above function.
> >>> - The HYP function will be called with its arguments in r0, r1 and r2.
> >>> On HYP function return, we return directly to SVC.
> >>>
> >>> A call to a function executing in Hyp mode is performed like the following:
> >>>
> >>> <svc code>
> >>> ldr r0, =BSYM(my_hyp_fn)
> >>> ldr r1, =my_param
> >>> hvc #0 ; Call my_hyp_fn(my_param) from HYP mode
> >>> <svc code>
> >>>
> >>> Otherwise, the world-switch is pretty straight-forward. All state that
> >>> can be modified by the guest is first backed up on the Hyp stack and the
> >>> VCPU values is loaded onto the hardware. State, which is not loaded, but
> >>> theoretically modifiable by the guest is protected through the
> >>> virtualiation features to generate a trap and cause software emulation.
> >>> Upon guest returns, all state is restored from hardware onto the VCPU
> >>> struct and the original state is restored from the Hyp-stack onto the
> >>> hardware.
> >>>
> >>> SMP support using the VMPIDR calculated on the basis of the host MPIDR
> >>> and overriding the low bits with KVM vcpu_id contributed by Marc Zyngier.
> >>>
> >>> Reuse of VMIDs has been implemented by Antonios Motakis and adapated from
> >>> a separate patch into the appropriate patches introducing the
> >>> functionality. Note that the VMIDs are stored per VM as required by the ARM
> >>> architecture reference manual.
> >>>
> >>> To support VFP/NEON we trap those instructions using the HPCTR. When
> >>> we trap, we switch the FPU. After a guest exit, the VFP state is
> >>> returned to the host. When disabling access to floating point
> >>> instructions, we also mask FPEXC_EN in order to avoid the guest
> >>> receiving Undefined instruction exceptions before we have a chance to
> >>> switch back the floating point state. We are reusing vfp_hard_struct,
> >>> so we depend on VFPv3 being enabled in the host kernel, if not, we still
> >>> trap cp10 and cp11 in order to inject an undefined instruction exception
> >>> whenever the guest tries to use VFP/NEON. VFP/NEON developed by
> >>> Antionios Motakis and Rusty Russell.
> >>>
> >>> Aborts that are permission faults, and not stage-1 page table walk, do
> >>> not report the faulting address in the HPFAR. We have to resolve the
> >>> IPA, and store it just like the HPFAR register on the VCPU struct. If
> >>> the IPA cannot be resolved, it means another CPU is playing with the
> >>> page tables, and we simply restart the guest. This quirk was fixed by
> >>> Marc Zyngier.
> >>>
> >>> Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
> >>> Signed-off-by: Rusty Russell <rusty.russell@linaro.org>
> >>> Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
> >>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
> >>> ---
> >>> arch/arm/include/asm/kvm_arm.h | 51 ++++
> >>> arch/arm/include/asm/kvm_host.h | 10 +
> >>> arch/arm/kernel/asm-offsets.c | 25 ++
> >>> arch/arm/kvm/arm.c | 187 ++++++++++++++++
> >>> arch/arm/kvm/interrupts.S | 396 +++++++++++++++++++++++++++++++++++
> >>> arch/arm/kvm/interrupts_head.S | 443 +++++++++++++++++++++++++++++++++++++++
> >>> 6 files changed, 1108 insertions(+), 4 deletions(-)
> >>> create mode 100644 arch/arm/kvm/interrupts_head.S
> >>>
> >>> diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
> >>> index fb22ee8..a3262a2 100644
> >>> --- a/arch/arm/include/asm/kvm_arm.h
> >>> +++ b/arch/arm/include/asm/kvm_arm.h
> >>> @@ -98,6 +98,18 @@
> >>> #define TTBCR_T0SZ 3
> >>> #define HTCR_MASK (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
> >>>
> >>> +/* Hyp System Trap Register */
> >>> +#define HSTR_T(x) (1 << x)
> >>> +#define HSTR_TTEE (1 << 16)
> >>> +#define HSTR_TJDBX (1 << 17)
> >>> +
> >>> +/* Hyp Coprocessor Trap Register */
> >>> +#define HCPTR_TCP(x) (1 << x)
> >>> +#define HCPTR_TCP_MASK (0x3fff)
> >>> +#define HCPTR_TASE (1 << 15)
> >>> +#define HCPTR_TTA (1 << 20)
> >>> +#define HCPTR_TCPAC (1 << 31)
> >>> +
> >>> /* Hyp Debug Configuration Register bits */
> >>> #define HDCR_TDRA (1 << 11)
> >>> #define HDCR_TDOSA (1 << 10)
> >>> @@ -144,6 +156,45 @@
> >>> #else
> >>> #define VTTBR_X (5 - KVM_T0SZ)
> >>> #endif
> >>> +#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
> >>> +#define VTTBR_BADDR_MASK (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
> >>> +#define VTTBR_VMID_SHIFT (48LLU)
> >>> +#define VTTBR_VMID_MASK (0xffLLU << VTTBR_VMID_SHIFT)
> >>> +
> >>> +/* Hyp Syndrome Register (HSR) bits */
> >>> +#define HSR_EC_SHIFT (26)
> >>> +#define HSR_EC (0x3fU << HSR_EC_SHIFT)
> >>> +#define HSR_IL (1U << 25)
> >>> +#define HSR_ISS (HSR_IL - 1)
> >>> +#define HSR_ISV_SHIFT (24)
> >>> +#define HSR_ISV (1U << HSR_ISV_SHIFT)
> >>> +#define HSR_FSC (0x3f)
> >>> +#define HSR_FSC_TYPE (0x3c)
> >>> +#define HSR_WNR (1 << 6)
> >>> +
> >>> +#define FSC_FAULT (0x04)
> >>> +#define FSC_PERM (0x0c)
> >>> +
> >>> +/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
> >>> +#define HPFAR_MASK (~0xf)
> >>>
> >>> +#define HSR_EC_UNKNOWN (0x00)
> >>> +#define HSR_EC_WFI (0x01)
> >>> +#define HSR_EC_CP15_32 (0x03)
> >>> +#define HSR_EC_CP15_64 (0x04)
> >>> +#define HSR_EC_CP14_MR (0x05)
> >>> +#define HSR_EC_CP14_LS (0x06)
> >>> +#define HSR_EC_CP_0_13 (0x07)
> >>> +#define HSR_EC_CP10_ID (0x08)
> >>> +#define HSR_EC_JAZELLE (0x09)
> >>> +#define HSR_EC_BXJ (0x0A)
> >>> +#define HSR_EC_CP14_64 (0x0C)
> >>> +#define HSR_EC_SVC_HYP (0x11)
> >>> +#define HSR_EC_HVC (0x12)
> >>> +#define HSR_EC_SMC (0x13)
> >>> +#define HSR_EC_IABT (0x20)
> >>> +#define HSR_EC_IABT_HYP (0x21)
> >>> +#define HSR_EC_DABT (0x24)
> >>> +#define HSR_EC_DABT_HYP (0x25)
> >>>
> >>> #endif /* __ARM_KVM_ARM_H__ */
> >>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >>> index 1de6f0d..ddb09da 100644
> >>> --- a/arch/arm/include/asm/kvm_host.h
> >>> +++ b/arch/arm/include/asm/kvm_host.h
> >>> @@ -21,6 +21,7 @@
> >>>
> >>> #include <asm/kvm.h>
> >>> #include <asm/kvm_asm.h>
> >>> +#include <asm/fpstate.h>
> >>>
> >>> #define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
> >>> #define KVM_USER_MEM_SLOTS 32
> >>> @@ -85,6 +86,14 @@ struct kvm_vcpu_arch {
> >>> u32 hxfar; /* Hyp Data/Inst Fault Address Register */
> >>> u32 hpfar; /* Hyp IPA Fault Address Register */
> >>>
> >>> + /* Floating point registers (VFP and Advanced SIMD/NEON) */
> >>> + struct vfp_hard_struct vfp_guest;
> >>> + struct vfp_hard_struct *vfp_host;
> >>> +
> >>> + /*
> >>> + * Anything that is not used directly from assembly code goes
> >>> + * here.
> >>> + */
> >>> /* Interrupt related fields */
> >>> u32 irq_lines; /* IRQ and FIQ levels */
> >>>
> >>> @@ -112,6 +121,7 @@ struct kvm_one_reg;
> >>> int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> >>> int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
> >>> u64 kvm_call_hyp(void *hypfn, ...);
> >>> +void force_vm_exit(const cpumask_t *mask);
> >>>
> >>> #define KVM_ARCH_WANT_MMU_NOTIFIER
> >>> struct kvm;
> >>> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> >>> index c985b48..c8b3272 100644
> >>> --- a/arch/arm/kernel/asm-offsets.c
> >>> +++ b/arch/arm/kernel/asm-offsets.c
> >>> @@ -13,6 +13,9 @@
> >>> #include <linux/sched.h>
> >>> #include <linux/mm.h>
> >>> #include <linux/dma-mapping.h>
> >>> +#ifdef CONFIG_KVM_ARM_HOST
> >>> +#include <linux/kvm_host.h>
> >>> +#endif
> >>> #include <asm/cacheflush.h>
> >>> #include <asm/glue-df.h>
> >>> #include <asm/glue-pf.h>
> >>> @@ -146,5 +149,27 @@ int main(void)
> >>> DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL);
> >>> DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE);
> >>> DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
> >>> +#ifdef CONFIG_KVM_ARM_HOST
> >>> + DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
> >>> + DEFINE(VCPU_MIDR, offsetof(struct kvm_vcpu, arch.midr));
> >>> + DEFINE(VCPU_CP15, offsetof(struct kvm_vcpu, arch.cp15));
> >>> + DEFINE(VCPU_VFP_GUEST, offsetof(struct kvm_vcpu, arch.vfp_guest));
> >>> + DEFINE(VCPU_VFP_HOST, offsetof(struct kvm_vcpu, arch.vfp_host));
> >>> + DEFINE(VCPU_REGS, offsetof(struct kvm_vcpu, arch.regs));
> >>> + DEFINE(VCPU_USR_REGS, offsetof(struct kvm_vcpu, arch.regs.usr_regs));
> >>> + DEFINE(VCPU_SVC_REGS, offsetof(struct kvm_vcpu, arch.regs.svc_regs));
> >>> + DEFINE(VCPU_ABT_REGS, offsetof(struct kvm_vcpu, arch.regs.abt_regs));
> >>> + DEFINE(VCPU_UND_REGS, offsetof(struct kvm_vcpu, arch.regs.und_regs));
> >>> + DEFINE(VCPU_IRQ_REGS, offsetof(struct kvm_vcpu, arch.regs.irq_regs));
> >>> + DEFINE(VCPU_FIQ_REGS, offsetof(struct kvm_vcpu, arch.regs.fiq_regs));
> >>> + DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
> >>> + DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
> >>> + DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines));
> >>> + DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.hsr));
> >>> + DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.hxfar));
> >>> + DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.hpfar));
> >>> + DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.hyp_pc));
> >>> + DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr));
> >>> +#endif
> >>> return 0;
> >>> }
> >>> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> >>> index 9b4566e..c94d278 100644
> >>> --- a/arch/arm/kvm/arm.c
> >>> +++ b/arch/arm/kvm/arm.c
> >>> @@ -40,6 +40,7 @@
> >>> #include <asm/kvm_arm.h>
> >>> #include <asm/kvm_asm.h>
> >>> #include <asm/kvm_mmu.h>
> >>> +#include <asm/kvm_emulate.h>
> >>>
> >>> #ifdef REQUIRES_VIRT
> >>> __asm__(".arch_extension virt");
> >>> @@ -49,6 +50,10 @@ static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
> >>> static struct vfp_hard_struct __percpu *kvm_host_vfp_state;
> >>> static unsigned long hyp_default_vectors;
> >>>
> >>> +/* The VMID used in the VTTBR */
> >>> +static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
> >>> +static u8 kvm_next_vmid;
> >>> +static DEFINE_SPINLOCK(kvm_vmid_lock);
> >>>
> >>> int kvm_arch_hardware_enable(void *garbage)
> >>> {
> >>> @@ -276,6 +281,8 @@ int __attribute_const__ kvm_target_cpu(void)
> >>>
> >>> int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
> >>> {
> >>> + /* Force users to call KVM_ARM_VCPU_INIT */
> >>> + vcpu->arch.target = -1;
> >>> return 0;
> >>> }
> >>>
> >>> @@ -286,6 +293,7 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
> >>> void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
> >>> {
> >>> vcpu->cpu = cpu;
> >>> + vcpu->arch.vfp_host = this_cpu_ptr(kvm_host_vfp_state);
> >>> }
> >>>
> >>> void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> >>> @@ -318,12 +326,189 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
> >>>
> >>> int kvm_arch_vcpu_in_guest_mode(struct kvm_vcpu *v)
> >> As far as I see the function is unused.
> >>
> >>> {
> >>> + return v->mode == IN_GUEST_MODE;
> >>> +}
> >>> +
> >>> +/* Just ensure a guest exit from a particular CPU */
> >>> +static void exit_vm_noop(void *info)
> >>> +{
> >>> +}
> >>> +
> >>> +void force_vm_exit(const cpumask_t *mask)
> >>> +{
> >>> + smp_call_function_many(mask, exit_vm_noop, NULL, true);
> >>> +}
> >> There is make_all_cpus_request() for that. It actually sends IPIs only
> >> to cpus that are running vcpus.
> >>
> >>> +
> >>> +/**
> >>> + * need_new_vmid_gen - check that the VMID is still valid
> >>> + * @kvm: The VM's VMID to checkt
> >>> + *
> >>> + * return true if there is a new generation of VMIDs being used
> >>> + *
> >>> + * The hardware supports only 256 values with the value zero reserved for the
> >>> + * host, so we check if an assigned value belongs to a previous generation,
> >>> + * which which requires us to assign a new value. If we're the first to use a
> >>> + * VMID for the new generation, we must flush necessary caches and TLBs on all
> >>> + * CPUs.
> >>> + */
> >>> +static bool need_new_vmid_gen(struct kvm *kvm)
> >>> +{
> >>> + return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen));
> >>> +}
> >>> +
> >>> +/**
> >>> + * update_vttbr - Update the VTTBR with a valid VMID before the guest runs
> >>> + * @kvm The guest that we are about to run
> >>> + *
> >>> + * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the
> >>> + * VM has a valid VMID, otherwise assigns a new one and flushes corresponding
> >>> + * caches and TLBs.
> >>> + */
> >>> +static void update_vttbr(struct kvm *kvm)
> >>> +{
> >>> + phys_addr_t pgd_phys;
> >>> + u64 vmid;
> >>> +
> >>> + if (!need_new_vmid_gen(kvm))
> >>> + return;
> >>> +
> >>> + spin_lock(&kvm_vmid_lock);
> >>> +
> >>> + /*
> >>> + * We need to re-check the vmid_gen here to ensure that if another vcpu
> >>> + * already allocated a valid vmid for this vm, then this vcpu should
> >>> + * use the same vmid.
> >>> + */
> >>> + if (!need_new_vmid_gen(kvm)) {
> >>> + spin_unlock(&kvm_vmid_lock);
> >>> + return;
> >>> + }
> >>> +
> >>> + /* First user of a new VMID generation? */
> >>> + if (unlikely(kvm_next_vmid == 0)) {
> >>> + atomic64_inc(&kvm_vmid_gen);
> >>> + kvm_next_vmid = 1;
> >>> +
> >>> + /*
> >>> + * On SMP we know no other CPUs can use this CPU's or each
> >>> + * other's VMID after force_vm_exit returns since the
> >>> + * kvm_vmid_lock blocks them from reentry to the guest.
> >>> + */
> >>> + force_vm_exit(cpu_all_mask);
> >>> + /*
> >>> + * Now broadcast TLB + ICACHE invalidation over the inner
> >>> + * shareable domain to make sure all data structures are
> >>> + * clean.
> >>> + */
> >>> + kvm_call_hyp(__kvm_flush_vm_context);
> >>> + }
> >>> +
> >>> + kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen);
> >>> + kvm->arch.vmid = kvm_next_vmid;
> >>> + kvm_next_vmid++;
> >>> +
> >>> + /* update vttbr to be used with the new vmid */
> >>> + pgd_phys = virt_to_phys(kvm->arch.pgd);
> >>> + vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK;
> >>> + kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK;
> >>> + kvm->arch.vttbr |= vmid;
> >>> +
> >>> + spin_unlock(&kvm_vmid_lock);
> >>> +}
> >>> +
> >>> +/*
> >>> + * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
> >>> + * proper exit to QEMU.
> >>> + */
> >>> +static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
> >>> + int exception_index)
> >>> +{
> >>> + run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
> >>> return 0;
> >>> }
> >>>
> >>> +/**
> >>> + * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
> >>> + * @vcpu: The VCPU pointer
> >>> + * @run: The kvm_run structure pointer used for userspace state exchange
> >>> + *
> >>> + * This function is called through the VCPU_RUN ioctl called from user space. It
> >>> + * will execute VM code in a loop until the time slice for the process is used
> >>> + * or some emulation is needed from user space in which case the function will
> >>> + * return with return value 0 and with the kvm_run structure filled in with the
> >>> + * required data for the requested emulation.
> >>> + */
> >>> int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
> >>> {
> >>> - return -EINVAL;
> >>> + int ret;
> >>> + sigset_t sigsaved;
> >>> +
> >>> + /* Make sure they initialize the vcpu with KVM_ARM_VCPU_INIT */
> >>> + if (unlikely(vcpu->arch.target < 0))
> >>> + return -ENOEXEC;
> >>> +
> >>> + if (vcpu->sigset_active)
> >>> + sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
> >>> +
> >>> + ret = 1;
> >>> + run->exit_reason = KVM_EXIT_UNKNOWN;
> >>> + while (ret > 0) {
> >>> + /*
> >>> + * Check conditions before entering the guest
> >>> + */
> >>> + cond_resched();
> >>> +
> >>> + update_vttbr(vcpu->kvm);
> >>> +
> >>> + local_irq_disable();
> >>> +
> >>> + /*
> >>> + * Re-check atomic conditions
> >>> + */
> >>> + if (signal_pending(current)) {
> >>> + ret = -EINTR;
> >>> + run->exit_reason = KVM_EXIT_INTR;
> >>> + }
> >>> +
> >>> + if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
> >>> + local_irq_enable();
> >>> + continue;
> >>> + }
> >>> +
> >>> + /**************************************************************
> >>> + * Enter the guest
> >>> + */
> >>> + trace_kvm_entry(*vcpu_pc(vcpu));
> >>> + kvm_guest_enter();
> >>> + vcpu->mode = IN_GUEST_MODE;
> >> You need to set mode to IN_GUEST_MODE before disabling interrupt and
> >> check that mode != EXITING_GUEST_MODE after disabling interrupt but
> >> before entering the guest. This way you will catch kicks that were sent
> >> between setting of the mode and disabling the interrupts. Also you need
> >> to check vcpu->requests and exit if it is not empty. I see that you do
> >> not use vcpu->requests at all, but you should since common kvm code
> >> assumes that it is used. make_all_cpus_request() uses it for instance.
> >>
> >
> > I don't quite agree, but almost:
> >
> > Why would you set IN_GUEST_MODE before disabling interrupts? The only
> > reason I can see for to be a requirement is to leverage an implicit
> > memory barrier. Receiving the IPI in this little window does nothing
> > (the smp_cross_call is a noop).
> >
> > Checking that mode != EXITING_GUEST_MODE is equally useless in my
> > opinion, as I read the requests code the only reason for this mode is
> > to avoid sending an IPI twice.
> >
> > Kicks sent between setting the mode and disabling the interrupts is
> > not the point, the point is to check the requests field (which we
> > don't use at all on ARM, and generic code also doesn't use on ARM)
> > after disabling interrupts, and after setting IN_GUEST_MODE.
> >
> > The patch below fixes your issues, and while I would push back on
> > anything else than direct bug fixes at this point, the current code is
> > semantically incorrect wrt. KVM vcpu requests, so it's worth a fix,
> > and the patch itself is trivial.
> >
> [...]
>
> Actually, I take that back, the kvm_vcpu_block function does make a
> request, which we don't need to handle, so adding code that checks for
> features we don't support is useless at this point. Please ignore the
> patch I sent earlier.
>
The archs which are not interested in unhalt request just clear it after
return from kvm_vcpu_block.
> Later on we can change some of the code to use the vcpu->features map
> if there's a real benefit, but right now the priority is to merge this
> code, so anything that's not a bugfix should not go in.
>
Agree. Lets merge it and change later. The vcpu run loop is simple
enough at this point. The question of using vcpu->requests is not
the question of "real benefit" though, of course you can introduce your
own mechanism to pass requests to vcpus instead of using whatever kvm
provides you. But from maintenance and code share point of view this
is wrong thing to do. Looks at this code for instance:
/* Kick out any which are still running. */
kvm_for_each_vcpu(i, v, vcpu->kvm) {
/* Guest could exit now, making cpu wrong. That's OK. */
if (kvm_vcpu_exiting_guest_mode(v) == IN_GUEST_MODE) {
force_vm_exit(get_cpu_mask(v->cpu));
}
}
Why not make_all_cpus_request(vcpu->kvm, KVM_REQ_PAUSE)?
And I am not sure KVM_REQ_UNHALT is so useless to you in the first
place. kvm_vcpu_block() can return even when vcpu is not runnable (if
signal is pending). KVM_REQ_UNHALT is the way to check for that. Hmm
this is actually looks like a BUG in the current code.
--
Gleb.
^ permalink raw reply
* ARM DMA: Fix in dma_cache_maint_page
From: James Bottomley @ 2013-01-16 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F6A14C.6040206@codeaurora.org>
On Wed, 2013-01-16 at 18:17 +0530, Subhash Jadavani wrote:
> Is it possible to pick up James patch below? Thread here:
> http://comments.gmane.org/gmane.linux.kernel.mmc/18670, have the details
> on the motivation behind this fix.
Someone should also audit the arm kernel code for more of these linear
page array assumptions. I'm guessing that when sparsemem was added to
arm over a year ago, whoever did it either didn't audit or missed a few.
James
^ permalink raw reply
* [RFC PATCH 3/4] ARM: bL_entry: Match memory barriers to architectural requirements
From: Dave Martin @ 2013-01-16 12:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F698D4.2050702@ti.com>
On Wed, Jan 16, 2013 at 05:41:00PM +0530, Santosh Shilimkar wrote:
> On Wednesday 16 January 2013 05:19 PM, Dave Martin wrote:
> >On Wed, Jan 16, 2013 at 12:20:47PM +0530, Santosh Shilimkar wrote:
> >>+ Catalin, RMK
> >>
> >>Dave,
> >>
> >>On Tuesday 15 January 2013 10:18 PM, Dave Martin wrote:
> >>>For architectural correctness even Strongly-Ordered memory accesses
> >>>require barriers in order to guarantee that multiple CPUs have a
> >>>coherent view of the ordering of memory accesses.
> >>>
> >>>Virtually everything done by this early code is done via explicit
> >>>memory access only, so DSBs are seldom required. Existing barriers
> >>>are demoted to DMB, except where a DSB is needed to synchronise
> >>>non-memory signalling (i.e., before a SEV). If a particular
> >>>platform performs cache maintenance in its power_up_setup function,
> >>>it should force it to complete explicitly including a DSB, instead
> >>>of relying on the bL_head framework code to do it.
> >>>
> >>>Some additional DMBs are added to ensure all the memory ordering
> >>>properties required by the race avoidance algorithm. DMBs are also
> >>>moved out of loops, and for clarity some are moved so that most
> >>>directly follow the memory operation which needs to be
> >>>synchronised.
> >>>
> >>>The setting of a CPU's bL_entry_vectors[] entry is also required to
> >>>act as a synchronisation point, so a DMB is added after checking
> >>>that entry to ensure that other CPUs do not observe gated
> >>>operations leaking across the opening of the gate.
> >>>
> >>>Signed-off-by: Dave Martin <dave.martin@linaro.org>
> >>>---
> >>
> >>Sorry to pick on this again but I am not able to understand why
> >>the strongly ordered access needs barriers. At least from the
> >>ARM point of view, a strongly ordered write will be more of blocking
> >>write and the further interconnect also is suppose to respect that
> >
> >This is what I originally assumed (hence the absence of barriers in
> >the initial patch).
> >
> >>rule. SO read writes are like adding barrier after every load store
> >
> >This assumption turns out to be wrong, unfortunately, although in
> >a uniprocessor scenario is makes no difference. A SO memory access
> >does block the CPU making the access, but explicitly does not
> >block the interconnect.
> >
> I suspected the interconnect part when you described the barrier
> need for SO memory region.
>
> >In a typical boot scenario for example, all secondary CPUs are
> >quiescent or powered down, so there's no problem. But we can't make
> >the same assumptions when we're trying to coordinate between
> >multiple active CPUs.
> >
> >>so adding explicit barriers doesn't make sense. Is this a side
> >>effect of some "write early response" kind of optimizations at
> >>interconnect level ?
> >
> >Strongly-Ordered accesses are always non-shareable, so there is
> >no explicit guarantee of coherency between multiple masters.
> >
> This is where probably issue then. My understanding is exactly
> opposite here and hence I wasn't worried about multi-master
> CPU scenario since sharable attributes would be taking care of it
> considering the same page tables being used in SMP system.
>
> ARM documentation says -
> ------------
> Shareability and the S bit, with TEX remap
> The memory type of a region, as indicated in the Memory type column
> of Table B3-12 on page B3-1350, provides
> the first level of control of whether the region is shareable:
> ? If the memory type is Strongly-ordered then the region is Shareable
> ------------------------------------------------------------
Hmmm, it looks like you're right here. My assumption that SO implies
non-shareable is wrong. This is backed up by:
A3.5.6 Device and Strongly-ordered memory
"Address locations marked as Strongly-ordered [...] are always treated
as Shareable."
I think this is sufficient to ensure that if two CPUs access the same
location with SO accesses, each will see an access order to any single
location which is consistent with the program order of the accesses on
the other CPUs. (This comes from the glossary definition of Coherent.)
However, I can't see any general guarantee for accesses to _different_
locations, beyond the guarantees for certain special cases given in
A3.8.2 Ordering requirements for memory accesses (address and control
dependencies etc.)
This may make some of the dmbs unnecessary, but it is not clear whether
they are all unnecessary.
I'll need to follow up on this and see if we can get an answer.
Cheers
---Dave
^ permalink raw reply
* ARM DMA: Fix in dma_cache_maint_page
From: Subhash Jadavani @ 2013-01-16 12:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F69F72.4030807@codeaurora.org>
Hi Russell,
Is it possible to pick up James patch below? Thread here:
http://comments.gmane.org/gmane.linux.kernel.mmc/18670, have the details
on the motivation behind this fix.
Regards,
Subhash
-------- Original Message --------
Subject: Re: [PATCH v2 1/1] block: blk-merge: don't merge the pages
with non-contiguous descriptors
Date: Wed, 16 Jan 2013 18:09:14 +0530
From: Subhash Jadavani <subhashj@codeaurora.org>
To: James Bottomley <James.Bottomley@HansenPartnership.com>
CC: linux-kernel at vger.kernel.org, linux-scsi at vger.kernel.org,
linux-mmc at vger.kernel.org, linux-arm-msm at vger.kernel.org,
martin.petersen at oracle.com, asias at redhat.com, tj at kernel.org,
linux-arm-kernel at lists.infradead.org, Russell King <linux@arm.linux.org.uk>
On 1/16/2013 4:02 PM, James Bottomley wrote:
> On Wed, 2013-01-16 at 12:07 +0530, Subhash Jadavani wrote:
>
>> Now consider this call stack from MMC block driver (this is on the ARmv7
>> based board):
>> [ 98.918174] [<c001b50c>] (v7_dma_inv_range+0x30/0x48) from
>> [<c0017b8c>] (dma_cache_maint_page+0x1c4/0x24c)
>> [ 98.927819] [<c0017b8c>] (dma_cache_maint_page+0x1c4/0x24c) from
>> [<c0017c28>] (___dma_page_cpu_to_dev+0x14/0x1c)
>> [ 98.937982] [<c0017c28>] (___dma_page_cpu_to_dev+0x14/0x1c) from
>> [<c0017ff8>] (dma_map_sg+0x3c/0x114)
> OK, so this is showing that ARM itself is making the assumption that the
> pages are contiguous in the page offset map.
>
> Fix this by doing the increment via the pfn, which will do the right
> thing whatever the memory model.
>
> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Thanks James. Yes, it make sense to fix the ARM code itself if it is the
only one giving this trouble.
I have tried your change below and it also fixes this issue (without
having my blk-merge patch). I will forward your change to Russel King to
see what he thinks about it.
Regards,
Subhash
>
> ---
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 6b2fb87..ab88c5b 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -809,7 +809,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
> op(vaddr, len, dir);
> }
> offset = 0;
> - page++;
> + page = pfn_to_page(page_to_pfn(page) + 1);
> left -= len;
> } while (left);
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130116/bcc1625a/attachment-0001.html>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox