Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/5] mvebu cleanups and preparation for Armada 7k/8k
From: Russell King - ARM Linux @ 2017-01-13 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

(Resend including linux-arm-kernel)

This patch series cleans up the mvebu pin controller implementation
such that we can support multiple pin controllers as found in Armada
7k and 8k SoCs.

Currently, in order to do that, we would have to have static variables
and multiple implementations of functions whose only purpose is to
read from the correct static variable.  This is caused by a lack of
driver private data passed into the mvebu pin controller's methods.

Most mvebu pin controllers methods are performing exactly the same
action, so it makes sense to generalise the methods, which in turn
lets us come up with a fairly standardised set of methods.

Another important side effect of these changes is that the structures
with function pointers are now marked const - as they should be in
today's security concious kernel programming environment.

I've included everything except the 7k and 8k drivers, which, before
Thomas went away, he suggested changes to these, so they aren't ready
for submission yet.  However, the rest of the ground work is, and I'd
like users of this code to test it - I don't have all these platforms!

I'm aware of other mvebu SoC support, so I think it's probably a good
idea to get these patches out there and known about, so folk can
consider how they'd like to order merging the changes - obviously new
SoCs with new pinctrl files will need updates somewhere...

The cleanup side of these patches (without the last adding the regmap
support) shows a reduction in code size:

 drivers/pinctrl/mvebu/pinctrl-armada-370.c | 24 +-------
 drivers/pinctrl/mvebu/pinctrl-armada-375.c | 24 +-------
 drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 24 +-------
 drivers/pinctrl/mvebu/pinctrl-armada-39x.c | 24 +-------
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c  | 35 +++--------
 drivers/pinctrl/mvebu/pinctrl-dove.c       | 96 +++++++++++++++++-------------
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c   | 32 +++-------
 drivers/pinctrl/mvebu/pinctrl-mvebu.c      | 77 +++++++++++++++++++++---
 drivers/pinctrl/mvebu/pinctrl-mvebu.h      | 51 +++++++---------
 drivers/pinctrl/mvebu/pinctrl-orion.c      |  8 ++-
 10 files changed, 183 insertions(+), 212 deletions(-)

Adding regmap support increases the code size again:

 drivers/pinctrl/mvebu/pinctrl-armada-370.c |  24 +----
 drivers/pinctrl/mvebu/pinctrl-armada-375.c |  24 +----
 drivers/pinctrl/mvebu/pinctrl-armada-38x.c |  24 +----
 drivers/pinctrl/mvebu/pinctrl-armada-39x.c |  24 +----
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c  |  35 ++------
 drivers/pinctrl/mvebu/pinctrl-dove.c       |  96 +++++++++++---------
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c   |  32 ++-----
 drivers/pinctrl/mvebu/pinctrl-mvebu.c      | 137 +++++++++++++++++++++++++++--
 drivers/pinctrl/mvebu/pinctrl-mvebu.h      |  65 ++++++++------
 drivers/pinctrl/mvebu/pinctrl-orion.c      |   8 +-
 10 files changed, 257 insertions(+), 212 deletions(-)

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* [RFC] Kernel panic down to swiotlb when doing insmod a simple driver
From: Robin Murphy @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d64931b6-8875-51ea-06a0-e0981e12f859@rock-chips.com>

On 13/01/17 10:00, Shawn Lin wrote:
> Hi,
> 
> Sorry for sending this RFC for help as I couldn't find some useful hint
> to slove my issue by git-log the swiotlb commit from kernel v4.4 to
> v4.9 and I'm also not familar with these stuff. So could you kindly
> point me to the right direction to debug it? Thanks. :)
> 
> --------------------------------------
> We just have a very simple wifi driver *built as ko module* which only
> have a probe function to do the basic init work and call SDIO API to
> transfer some bytes.
> 
> Env: kernel 4.4 stable tree, ARM64(rk3399)
> 
> Two cases are included:

And they are both wrong :)

> The crash case:
> 
> u8 __aligned(32) buf[PAGE_SIZE]; //global here in ko driver file

It is only valid to do DMA from linear map addresses - I'm not sure if
the modules area was in the linear map before, but either way it
probably isn't now (Ard, Mark?). Either way, I don't believe static data
honours ARCH_DMA_MINALIGN in general, so it's still highly inadvisable.

> static int wifi_probe(struct sdio_func *func, const struct
> sdio_device_id *id)
> {
>   // prepare some SDIO work before
>   printk("wifi_probe: buf = 0x%x\n", buf);
>   sdio_memcpy_toio(func, 0, buf, 200);
> }
> 
> The workable case:
> 
> static int wifi_probe(struct sdio_func *func, const struct
> sdio_device_id *id)
> {
> 
>    u8 __aligned(32) buf[PAGE_SIZE]; //move inside the probe function

No. DMA from the stack is right out, both for the aforementioned
alignment reasons, and the fact that we now have (or will have)
virtually-mapped stacks. One of the benefits of the latter is that it
catches bugs like this ;)

Get your buffer from kmalloc() or a page allocation, and everything
should be correct.

Robin.

>   // prepare some SDIO work before
>   printk("wifi_probe: buf = 0x%x\n", buf);
>   sdio_memcpy_toio(func, 0, buf, 200);
> }
> 
> -------------
> How to repro it:
> insmod the KO module, then kernel panic when trying to bounce a buffer
> in swiotlb but the workable case I didn't see kernel did that memcpy
> by adding some log, strange?
> 
> parsing vmlinux, it locates to arch/arm64/lib/copy_template.S:167
> 
> 165 .Lcpy_body_large:
> 166         /* pre-get 64 bytes data. */
> 167         ldp1    A_l, A_h, src, #16
> 168         ldp1    B_l, B_h, src, #16
> 169         ldp1    C_l, C_h, src, #16
> 170         ldp1    D_l, D_h, src, #16
> 
> --------------------------------------------------------------
> 
> The full crash log looks like
> 
> [  236.748210] wifi_probe: buf = 0xffffff8000a40b80
> [  236.748258] swiotlb_tbl_map_single: orig_addr = 0xfffffffff8c40b80,
> tlb_addr = 0xf7eae000 //I added log here
> [  236.748276] Unable to handle kernel paging request at virtual address
> fffffffff8c40b80
> [  236.776486] pgd = ffffffc0b3417000
> [  236.776789] [fffffffff8c40b80] *pgd=00000000b3427003,
> *pud=00000000b3427003, *pmd=0000000000000000
> [  236.777601] Internal error: Oops: 96000005 [#1] PREEMPT SMP
> [  236.778093] Modules linked in: drvtst(O+)
> [  236.778463] CPU: 0 PID: 1918 Comm: insmod Tainted: G           O
> 4.4.36 #25
> [  236.779096] Hardware name: Rockchip RK3399 Evaluation Board v3 edp
> (Android) (DT)
> [  236.779753] task: ffffffc0e3db0c40 ti: ffffffc0b342c000 task.ti:
> ffffffc0b342c000
> [  236.780418] PC is at __memcpy+0x100/0x180
> [  236.780777] LR is at swiotlb_tbl_map_single+0x254/0x274
> [  236.781237] pc : [<ffffff80083579c0>] lr : [<ffffff800837cf70>]
> pstate: 20000145
> [  236.781885] sp : ffffffc0b342f530
> [  236.782178] x29: ffffffc0b342f530 x28: 0000000000000001
> [  236.782653] x27: 0000000000200000 x26: ffffffc0e8874810
> [  236.783127] x25: 0000000000000001 x24: 00000000000000c8
> [  236.783601] x23: fffffffff8c40b80 x22: ffffff8009158480
> [  236.784075] x21: 00000000f7eae000 x20: ffffff8009158000
> [  236.784550] x19: 00000000f7eae000 x18: 00000000004ff888
> [  236.785023] x17: 0000000000000000 x16: ffffff80081bbc74
> [  236.785498] x15: 0b030f0000000000 x14: 3034633866666666
> [  236.785972] x13: 6666666666783020 x12: 3d20726464615f67
> [  236.786446] x11: 69726f20656c676e x10: 69735f70616d5f6c
> [  236.786919] x9 : 62745f626c746f69 x8 : ffffff80082e8c1c
> [  236.787392] x7 : 0000000000000000 x6 : ffffffc0f7eae000
> [  236.787866] x5 : 0000000000000001 x4 : 0000000000000000
> [  236.788340] x3 : 0000000000000007 x2 : 0000000000000048
> [  236.788815] x1 : fffffffff8c40b80 x0 : ffffffc0f7eae000
> [  236.789291]
> [  236.789291] PC: 0xffffff8008357940:
> [  236.789728] 7940  36180062 f8408423 f80084c3 36100062 b8404423
> b80044c3 36080062 78402423
> [  236.790484] 7960  780024c3 36000562 38401423 380014c3 14000028
> f1020042 5400024a a8c12027
> [  236.791236] 7980  a88120c7 a8c12829 a8c1302b a88128c9 a88130cb
> a8c1382d a88138cd f240145f
> [  236.791988] 79a0  54fffba1 1400001b d503201f d503201f d503201f
> d503201f d503201f d503201f
> [  236.792739] 79c0  a8c12027 a8c12829 a8c1302b a8c1382d a88120c7
> a8c12027 a88128c9 a8c12829
> [  236.793490] 79e0  a88130cb a8c1302b a88138cd a8c1382d f1010042
> 54fffeea a88120c7 a88128c9
> [  236.794243] 7a00  a88130cb a88138cd f240145f 54fff841 d65f03c0
> d503201f d503201f d503201f
> [  236.794995] 7a20  d503201f d503201f d503201f d503201f d503201f
> d503201f d503201f d503201f
> [  236.795748]
> [  236.795748] LR: 0xffffff800837cef0:
> [  236.796186] cef0  d0004f81 aa1a03e0 912ad821 aa1803e2 9404fda9
> 1400001b 6b19001f 540000e2
> [  236.796939] cf10  0b130003 53155001 11000400 8b21c2e1 f8237841
> 17fffff9 d0004f80 b0003821
> [  236.797694] cf30  912b7800 91344021 aa1703e2 aa1503e3 aa1503f3
> 97f784ba 7100079f 54000128
> [  236.798445] cf50  d0005fc0 aa1803e2 f9453c01 cb0102a0 cb0102e1
> b25a6400 b25a6421 97ff6a55
> [  236.799197] cf70  aa1303e0 a94153f3 a9425bf5 a94363f7 a9446bf9
> a94573fb a8c77bfd d65f03c0
> [  236.799949] cf90  d4210000 90006ee5 911200a5 a9bf7bfd 910003fd
> f94018a0 f9401ca5 cb000020
> [  236.800703] cfb0  934ba800 f86078a5 b10004bf 540003e0 92402820
> 8b0000a5 34000084 7100049f
> [  236.801455] cfd0  54000180 14000018 721e787f 540000c1 d0005fc0
> f9453c03 cb0300a0 cb030021
> [  236.802209]
> [  236.802209] SP: 0xffffffc0b342f4b0:
> [  236.802647] f4b0  09158480 ffffff80 f8c40b80 ffffffff 000000c8
> 00000000 00000001 00000000
> [  236.803400] f4d0  e8874810 ffffffc0 00200000 00000000 00000001
> 00000000 b342f530 ffffffc0
> [  236.804152] f4f0  0837cf70 ffffff80 b342f530 ffffffc0 083579c0
> ffffff80 20000145 00000000
> [  236.804903] f510  ffffffff 00000000 00000140 00000000 00000000
> 00000080 00000000 00000000
> [  236.805654] f530  b342f5a0 ffffffc0 0837dc18 ffffff80 00000001
> 00000000 b342f890 ffffffc0
> [  236.806405] f550  00000001 00000000 00000000 00000000 00000000
> 00000000 09158000 ffffff80
> [  236.807157] f570  08f76000 ffffff80 09158000 ffffff80 b342f890
> ffffffc0 e8874810 ffffffc0
> [  236.807909] f590  00000140 00000000 001efd5c 00000000 b342f600
> ffffffc0 0809359c ffffff80
> [  236.808662]
> [  236.808662] X0: 0xffffffc0f7eadf80:
> [  236.809099] df80  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.809852] dfa0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.810603] dfc0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.811355] dfe0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.812106] e000  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.812858] e020  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.813608] e040  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.814360] e060  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.815114]
> [  236.815114] X1: 0xfffffffff8c40b00:
> [  236.815552] 0b00  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.816309] 0b20  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.817065] 0b40  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.817820] 0b60  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.818575] 0b80  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.819328] 0ba0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.820082] 0bc0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.820836] 0be0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.821595]
> [  236.821595] X6: 0xffffffc0f7eadf80:
> [  236.822032] df80  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.822785] dfa0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.823537] dfc0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.824289] dfe0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.825040] e000  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.825792] e020  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.826543] e040  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.827295] e060  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.828049]
> [  236.828049] X8: 0xffffff80082e8b9c:
> [  236.828487] 8b9c  14000006 f9400453 14000004 f9400853 14000002
> f9400c53 aa1303e0 94000529
> [  236.829239] 8bbc  aa1303e0 94000532 52800000 14000002 128002a0
> f9400bf3 a8c27bfd d65f03c0
> [  236.829993] 8bdc  a9bf7bfd 71001c1f aa0403e1 910003fd 128002a3
> 54000101 f94048e0 12800163
> [  236.830746] 8bfc  f9400c00 b4000080 2a0603e2 9400049e 2a0003e3
> 2a0303e0 a8c17bfd d65f03c0
> [  236.831497] 8c1c  a9b97bfd 7100081f 910003fd a90363f7 d0006477
> f90023f9 a9025bf5 a90153f3
> [  236.832249] 8c3c  f9452ae2 aa0403f6 f90037a2 53001cb4 aa0603f5
> f94048f3 54000061 f9400660
> [  236.833002] 8c5c  14000008 71000c1f 54000061 f9400a60 14000004
> 71001c1f 54000101 f9400e60
> [  236.833754] 8c7c  12800167 b40008a0 aa1603e1 2a1503e2 94000426
> 14000040 128002a7 350007e0
> [  236.834510]
> [  236.834510] X16: 0xffffff80081bbbf4:
> [  236.834955] bbf4  2a1503e1 97fffec4 3100101f 54000261 d5384100
> f9400800 90000002 912c4042
> [  236.835708] bc14  91102003 f9020402 f9000476 b9001075 37f80114
> f9401fa0 f9000c60 f94023a0
> [  236.836460] bc34  f9001060 52800020 b9001460 14000002 b900147f
> 12804060 f94027a2 93407c00
> [  236.837212] bc54  f9452a61 eb01005f 54000040 97fb80af a94153f3
> a9425bf5 a8c57bfd d65f03c0
> [  236.837964] bc74  a9b67bfd 910003fd a9025bf5 f0006dd6 f90023f9
> a90363f7 aa0003f8 aa0103f7
> [  236.838716] bc94  f9452ac0 aa0403f9 a90153f3 f9004fa0 aa0203f3
> aa0303f4 b4000302 d5384100
> [  236.839466] bcb4  f9400400 aa0203e3 b1004063 fa403062 9a9f87e1
> 9101e3a0 b40000c1 aa0203e1
> [  236.840218] bcd4  d2800202 94066c4a b4000080 1400001d a9007c1f
> 1400001b f9403fa1 910223a0
> [  236.840973]
> [  236.840973] X20: 0xffffff8009157f80:
> [  236.841418] 7f80  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.842169] 7fa0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.842920] 7fc0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.843672] 7fe0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.844422] 8000  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.845174] 8020  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.845925] 8040  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.846677] 8060  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.847431]
> [  236.847431] X22: 0xffffff8009158400:
> [  236.847876] 8400  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.848628] 8420  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.849379] 8440  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.850130] 8460  00000000 00000000 00000000 00000000 00030003
> 00000000 00f100f1 00000000
> [  236.850882] 8480  00000080 00000000 f7ea6000 00000000 f7eee000
> 00000000 00000000 00000000
> [  236.851633] 84a0  00010001 00000001 f7f75000 ffffffc0 f7eae000
> 00000000 f7ea5000 ffffffc0
> [  236.852388] 84c0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.853139] 84e0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.853892]
> [  236.853892] X23: 0xfffffffff8c40b00:
> [  236.854338] 0b00  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.855093] 0b20  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.855846] 0b40  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.856601] 0b60  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.857356] 0b80  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.858109] 0ba0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.858864] 0bc0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.859620] 0be0  ******** ******** ******** ******** ********
> ******** ******** ********
> [  236.860377]
> [  236.860377] X26: 0xffffffc0e8874790:
> [  236.860822] 4790  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.861573] 47b0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.862324] 47d0  00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [  236.863075] 47f0  00000000 00000000 00000000 00000000 e885d140
> ffffffc0 ffffffff 00000000
> [  236.863828] 4810  08fefcc0 ffffff80 e933b480 ffffffc0 e885d140
> ffffffc0 e5b7c020 ffffffc0
> [  236.864581] 4830  e5b24430 ffffffc0 08fefcd0 ffffff80 e929d480
> ffffffc0 08fef9d0 ffffff80
> [  236.865335] 4850  e88999d8 ffffffc0 00000005 00000007 00000000
> 00000000 00000000 00000000
> [  236.866087] 4870  00000001 00000000 e8874878 ffffffc0 e8874878
> ffffffc0 00000000 00000000
> [  236.866843]
> [  236.866843] X29: 0xffffffc0b342f4b0:
> [  236.867288] f4b0  09158480 ffffff80 f8c40b80 ffffffff 000000c8
> 00000000 00000001 00000000
> [  236.868041] f4d0  e8874810 ffffffc0 00200000 00000000 00000001
> 00000000 b342f530 ffffffc0
> [  236.868794] f4f0  0837cf70 ffffff80 b342f530 ffffffc0 083579c0
> ffffff80 20000145 00000000
> [  236.869547] f510  ffffffff 00000000 00000140 00000000 00000000
> 00000080 00000000 00000000
> [  236.870297] f530  b342f5a0 ffffffc0 0837dc18 ffffff80 00000001
> 00000000 b342f890 ffffffc0
> [  236.871049] f550  00000001 00000000 00000000 00000000 00000000
> 00000000 09158000 ffffff80
> [  236.871800] f570  08f76000 ffffff80 09158000 ffffff80 b342f890
> ffffffc0 e8874810 ffffffc0
> [  236.872552] f590  00000140 00000000 001efd5c 00000000 b342f600
> ffffffc0 0809359c ffffff80
> [  236.873304]
> [  236.873442] Process insmod (pid: 1918, stack limit = 0xffffffc0b342c020)
> [  236.874031] Stack: (0xffffffc0b342f530 to 0xffffffc0b3430000)
> [  236.874539] f520:                                   ffffffc0b342f5a0
> ffffff800837dc18
> [  236.875226] f540: 0000000000000001 ffffffc0b342f890 0000000000000001
> 0000000000000000
> [  236.875915] f560: 0000000000000000 ffffff8009158000 ffffff8008f76000
> ffffff8009158000
> [  236.876605] f580: ffffffc0b342f890 ffffffc0e8874810 0000000000000140
> 00000000001efd5c
> [  236.877293] f5a0: ffffffc0b342f600 ffffff800809359c ffffffc0b342f890
> ffffffc0e8874810
> [  236.877981] f5c0: 0000000000000000 0000000000000001 0000000000000001
> ffffffc0b342f938
> [  236.878670] f5e0: ffffffc0b342f8f0 ffffffc0e5b7c738 0000000000001000
> 0000000000000000
> [  236.879358] f600: ffffffc0b342f640 ffffff800871113c ffffffc0b342f8f0
> ffffff8008f88b60
> [  236.880047] f620: 0000000000000000 ffffffc0e8874810 0000000000000001
> ffffff8000a40b80
> [  236.880735] f640: ffffffc0b342f6a0 ffffff80087129cc ffffffc0e5b45018
> ffffffc0b342f8b0
> [  236.881423] f660: ffffff8008f76000 0000000020002775 ffffffc0e5b7c700
> ffffffc0b342f8b0
> [  236.882112] f680: ffffff8008f76000 0000000000000001 ffffffc0b342f890
> 0000000000000001
> [  236.882800] f6a0: ffffffc0b342f730 ffffff80087132e0 ffffffc0e5b45018
> ffffffc0e5b7c000
> [  236.883489] f6c0: ffffffc0e5b7c700 ffffff8000a40b80 ffffff8008f76000
> ffffffc0b342f8b0
> [  236.884178] f6e0: ffffffc0b342f938 ffffffc0b342f8f0 0000000000001000
> ffffff800871325c
> [  236.884867] f700: ffffffc0e5b45018 ffffffc0e5b7c000 ffffffc0e5b7c700
> ffffff8000a40b80
> [  236.885555] f720: ffffff8008f76000 cb88537fdc8ba624 ffffffc0b342f770
> ffffff80086f8b44
> [  236.886243] f740: ffffffc0e5b7c000 00000000000001f4 00000000ffffff85
> ffffff80086f8ac0
> [  236.886931] f760: ffffffc0e5b7c000 ffffffc0b342f938 ffffffc0b342f7a0
> ffffff80087ae0e8
> [  236.887619] f780: ffffffc0b342f938 ffffffc0e5b7c000 00000000ffffff85
> ffffffc0b342f938
> [  236.888308] f7a0: ffffffc0b342f7c0 ffffff80086f9c74 ffffffc0e5b7c000
> ffffffc0b342f938
> [  236.888996] f7c0: ffffffc0b342f800 ffffff800870421c 00000000000000c8
> 0000000000000001
> [  236.889685] f7e0: ffffffc0e5b7c800 ffffff8000a40b80 ffffff8008f76000
> ffffffc0b342f8b0
> [  236.890372] f800: ffffffc0b342f9a0 ffffff8008705800 00000000000000c8
> 0000000000000000
> [  236.891061] f820: ffffff8000a40b80 0000000000000001 ffffff8008dfdc48
> ffffff8008dfdc81
> [  236.891748] f840: ffffff8008dfdcdb 0000000000000001 ffffffc0e5b44c00
> 00000000000000c8
> [  236.892436] f860: ffffffc0e5b44c00 00000000000000c8 000000000000002a
> ffffff800911d000
> [  236.893125] f880: 0000000000000140 ffffff8000000000 03ffffbdbfe31002
> 000000c800000b80
> [  236.893813] f8a0: 0000000000000000 0000000000000000 940000c800000035
> 0000000000000000
> [  236.894501] f8c0: 0000000000000000 00000000000001b5 00000000ffffff8d
> 0000000000000000
> [  236.895190] f8e0: ffffffc0b342f8f0 ffffffc0b342f938 000000003b9aca00
> 00000001000000c8
> [  236.895878] f900: 00000100ffffff8d 0000000000000000 0000000000000000
> ffffffc0b342f938
> [  236.896566] f920: 0000000000000001 ffffffc0b342f890 0000000000000000
> 0000000000000000
> [  236.897254] f940: ffffffc0b342f8b0 ffffffc0b342f8f0 0000000000000000
> 0000000000000000
> [  236.897942] f960: 0000000000000000 ffffffc0b342f968 ffffffc0b342f968
> ffffff80086f8b98
> [  236.898630] f980: 0000000000000000 0000000000000000 0000000000000000
> cb88537fdc8ba624
> [  236.899319] f9a0: ffffffc0b342fa00 ffffff8008705954 ffffffc0e5b44c00
> 00000000000000c8
> [  236.900007] f9c0: ffffff8000a40b80 ffffff8000a410a0 ffffff8000a407d8
> 0000000000000029
> [  236.900695] f9e0: 0000000000000000 ffffffc0e926a480 0000000000000001
> 0000000000000038
> [  236.901384] fa00: ffffffc0b342fa10 ffffff8000a40108 ffffffc0b342fa60
> ffffff8008704734
> [  236.902072] fa20: ffffffc0e5b44c08 0000000000000000 ffffffc0e5b44c00
> ffffff8000a40410
> [  236.902760] fa40: ffffff8000a407d8 0000000000000029 0000000000000000
> ffffff8008704704
> [  236.903447] fa60: ffffffc0b342faa0 ffffff80084bfd6c ffffffc0e5b44c08
> 0000000000000000
> [  236.904136] fa80: ffffff800915d000 ffffff8008fef000 ffffff8000a407d8
> 0000000000000000
> [  236.904824] faa0: ffffffc0b342faf0 ffffff80084bff68 ffffffc0e5b44c08
> ffffffc0e5b44c68
> [  236.905512] fac0: ffffff8000a407d8 ffffff80084bff04 ffffff8009028a38
> 0000000000000000
> [  236.906201] fae0: 0000000000000000 ffffff80084bff40 ffffffc0b342fb20
> ffffff80084bee18
> [  236.906889] fb00: 0000000000000000 ffffff8008f76000 ffffff8000a407d8
> ffffff80084bff04
> [  236.907577] fb20: ffffffc0b342fb70 ffffff80084bf8ac ffffff8000a407d8
> 0000000000000000
> [  236.908265] fb40: ffffffc0f6e996c0 ffffff8008fef000 ffffffc0b342fb60
> ffffffc0e8b8f4a8
> [  236.908953] fb60: ffffffc0e5486ea8 cb88537fdc8ba624 ffffffc0b342fb80
> ffffff80084bf45c
> [  236.909641] fb80: ffffffc0b342fbc0 ffffff80084c0afc ffffff8000a407d8
> ffffff8008f84b20
> [  236.910329] fba0: 0000000000000000 ffffff8008f76000 ffffff8008f84b20
> cb88537fdc8ba624
> [  236.911017] fbc0: ffffffc0b342fbf0 ffffff8008704580 ffffff8000a44000
> ffffff8008f84b20
> [  236.911706] fbe0: ffffffc0f6dda1c0 ffffff8008f76000 ffffffc0b342fc00
> ffffff8000a40228
> [  236.912394] fc00: ffffffc0b342fc10 ffffff8000a4400c ffffffc0b342fc20
> ffffff8008082ba4
> [  236.913082] fc20: ffffffc0b342fcb0 ffffff800815e564 ffffff8000a40880
> ffffff8008f96000
> [  236.913770] fc40: 0000000000000001 ffffffc0d58a1e40 ffffff8008a4a2d0
> 0000000000000000
> [  236.914458] fc60: 0000000000000001 ffffff8008f96000 ffffff8008a4a2d0
> 0000000000000000
> [  236.915146] fc80: 0000000000000000 ffffffc0e926a480 0000000000000001
> ffffffc0b342fe50
> [  236.915835] fca0: 0000000000000001 cb88537fdc8ba624 ffffffc0b342fce0
> ffffff80081150f0
> [  236.916523] fcc0: ffffff8000a40880 ffffffc0b342fe50 0000000000000001
> ffffff8008f96000
> [  236.917212] fce0: ffffffc0b342fe00 ffffff800811562c 00000000000014d8
> ffffff800ca364d8
> [  236.917900] fd00: 0000007f922804e8 0000000000000000 ffffff8008f76000
> 000000555bb25d20
> [  236.918588] fd20: 0000000000010000 ffffffc0b342c000 ffffff8008a42000
> ffffffc0b342c000
> [  236.919275] fd40: 0000000000000077 0000000000000076 0000000000000064
> 0000000000000072
> [  236.919963] fd60: 000000000000006e 0000000000000018 0000000000000040
> 0000000000000040
> [  236.920652] fd80: ffffff8000a42500 ffffff8008f76000 0000000000000124
> ffffff8008112064
> [  236.921340] fda0: ffffff8008f76000 000000555bb25d20 000000000000011d
> 0000000000000069
> [  236.922028] fdc0: ffffffc0b342fe00 0000000000000000 0000000000000000
> 0000000000000000
> [  236.922716] fde0: 0000007f00000000 0000000000000000 ffffffc000000000
> cb88537fdc8ba624
> [  236.923405] fe00: 0000000000000000 ffffff80080826f0 0000000000000000
> 0000007f9223f010
> [  236.924092] fe20: ffffffffffffffff 0000007f9235e904 0000000060000000
> 0000000000000015
> [  236.924780] fe40: 000000000000011d 0000000000000069 ffffff800c9f5000
> 00000000000414d8
> [  236.925469] fe60: ffffff800ca35bd8 ffffff800ca1711f ffffff800ca17d08
> 0000000000002500
> [  236.926157] fe80: 0000000000002b00 0000000000000000 0000000000000000
> 0000000000000dd8
> [  236.926844] fea0: 0000002300000022 000000000000000d 0000000000000009
> cb88537fdc8ba624
> [  236.927532] fec0: 0000007f9223f010 00000000000414d8 000000555bb25d20
> 0000000000000000
> [  236.928220] fee0: 0000000000000001 0000000000000000 0000000000000000
> 0000007f9223f000
> [  236.928909] ff00: 0000000000000069 0000007f9223f010 0000000000042000
> 0000000000000001
> [  236.929597] ff20: 0000007f92280fe0 0000007f92281000 0000007f923f4a70
> 0000000000002000
> [  236.930285] ff40: 000000555bb23ae0 0000007f9235e8e4 0000000000000f00
> 00000000000414d8
> [  236.930972] ff60: 0000007f9223f010 0000000000000003 00000000000414d8
> 0000000000000000
> [  236.931660] ff80: 0000000000000000 000000555bb26d20 0000000000000010
> 0000000000000000
> [  236.932348] ffa0: 0000000000000000 0000007fe750e100 000000555bade83c
> 0000007fe750e0b0
> [  236.933036] ffc0: 0000007f9235e904 0000000060000000 0000007f9223f010
> 0000000000000069
> [  236.933725] ffe0: 0000000000000000 0000000000000000 3420320216190109
> 7375020101333632
> [  236.934409] Call trace:
> [  236.934632] Exception stack(0xffffffc0b342f340 to 0xffffffc0b342f470)
> [  236.935200] f340: 00000000f7eae000 0000008000000000 ffffffc0b342f530
> ffffff80083579c0
> [  236.935888] f360: 0000000020000145 0000000000000053 ffffff8008f93688
> 000000000007e7b8
> [  236.936577] f380: 0000000000000002 ffffff8008f93688 0000000000000063
> 000000000909b7e8
> [  236.937266] f3a0: ffffffc0b342f440 ffffff80080e8d08 ffffff8008f76000
> ffffff80080e8cd4
> [  236.937953] f3c0: 00000000f7eae000 ffffff8009158480 fffffffff8c40b80
> 00000000000000c8
> [  236.938641] f3e0: 0000000000000001 ffffffc0e8874810 0000000000200000
> cb88537fdc8ba624
> [  236.939329] f400: ffffffc0f7eae000 fffffffff8c40b80 0000000000000048
> 0000000000000007
> [  236.940017] f420: 0000000000000000 0000000000000001 ffffffc0f7eae000
> 0000000000000000
> [  236.940705] f440: ffffff80082e8c1c 62745f626c746f69 69735f70616d5f6c
> 69726f20656c676e
> [  236.941392] f460: 3d20726464615f67 6666666666783020
> [  236.941826] [<ffffff80083579c0>] __memcpy+0x100/0x180
> [  236.942274] [<ffffff800837dc18>] swiotlb_map_sg_attrs+0xa8/0x170
> [  236.942810] [<ffffff800809359c>] __swiotlb_map_sg_attrs+0x24/0x8c
> [  236.943353] [<ffffff800871113c>]
> dw_mci_pre_dma_transfer.isra.16+0xf0/0x11c
> [  236.943967] [<ffffff80087129cc>] __dw_mci_start_request+0x17c/0x4d0
> [  236.944520] [<ffffff80087132e0>] dw_mci_request+0xb8/0xf0
> [  236.945002] [<ffffff80086f8b44>] __mmc_start_request+0x9c/0xc0
> [  236.945520] [<ffffff80087ae0e8>] mmc_start_request.part.17+0x100/0x11c
> [  236.946097] [<ffffff80086f9c74>] mmc_wait_for_req+0x78/0x1a8
> [  236.946600] [<ffffff800870421c>] mmc_io_rw_extended+0x27c/0x2fc
> [  236.947124] [<ffffff8008705800>] sdio_io_rw_ext_helper+0x1e4/0x238
> [  236.947670] [<ffffff8008705954>] sdio_memcpy_toio+0x24/0x2c
> [  236.948169] [<ffffff8000a40108>] wifi_probe+0xa8/0x198 [drvtst]
> [  236.948708] [<ffffff8008704734>] sdio_bus_probe+0xb0/0x140
> [  236.949195] [<ffffff80084bfd6c>] driver_probe_device+0x118/0x2b0
> [  236.949724] [<ffffff80084bff68>] __driver_attach+0x64/0x90
> [  236.950212] [<ffffff80084bee18>] bus_for_each_dev+0x80/0xb0
> [  236.950706] [<ffffff80084bf8ac>] driver_attach+0x20/0x28
> [  236.951176] [<ffffff80084bf45c>] bus_add_driver+0xe8/0x1ec
> [  236.951661] [<ffffff80084c0afc>] driver_register+0x98/0xe4
> [  236.952147] [<ffffff8008704580>] sdio_register_driver+0x24/0x2c
> [  236.952675] [<ffffff8000a40228>] wifi_sdio_init+0x30/0x68 [drvtst]
> [  236.953241] [<ffffff8000a4400c>] wifi_drv_init+0xc/0x38 [drvtst]
> [  236.953789] [<ffffff8008082ba4>] do_one_initcall+0x17c/0x198
> [  236.954293] [<ffffff800815e564>] do_init_module+0x60/0x1b8
> [  236.954779] [<ffffff80081150f0>] load_module+0x1660/0x1a50
> [  236.955264] [<ffffff800811562c>] SyS_init_module+0x14c/0x180
> [  236.955765] [<ffffff80080826f0>] el0_svc_naked+0x24/0x28
> [  236.956237] Code: d503201f d503201f d503201f d503201f (a8c12027)
> [  236.956794] ---[ end trace 2030cf6e7c948d05 ]---
> [  236.984113] Kernel panic - not syncing: Fatal exception in interrupt
> 

^ permalink raw reply

* [PATCH RFC 1/5] pinctrl: mvebu: constify mvebu_mpp_ctrl structures
From: Russell King @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

As the mvebu_mpp_ctrl structures contain function pointers, it is
preferable for these to be made read-only to prevent the function
pointers being modified.  So make these const.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/pinctrl/mvebu/pinctrl-armada-370.c | 2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-375.c | 2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-39x.c | 2 +-
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c  | 6 +++---
 drivers/pinctrl/mvebu/pinctrl-dove.c       | 2 +-
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c   | 6 +++---
 drivers/pinctrl/mvebu/pinctrl-mvebu.c      | 6 +++---
 drivers/pinctrl/mvebu/pinctrl-mvebu.h      | 2 +-
 drivers/pinctrl/mvebu/pinctrl-orion.c      | 2 +-
 10 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index 9cc1cc3f5c34..3cb6b4ea0118 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -384,7 +384,7 @@ static const struct of_device_id armada_370_pinctrl_of_match[] = {
 	{ },
 };
 
-static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-375.c b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
index 070651431ca4..c9dba08780c5 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-375.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
@@ -402,7 +402,7 @@ static const struct of_device_id armada_375_pinctrl_of_match[] = {
 	{ },
 };
 
-static struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 69, NULL, armada_375_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
index 4e84c8e4938c..52f2ab82901a 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
@@ -409,7 +409,7 @@ static const struct of_device_id armada_38x_pinctrl_of_match[] = {
 	{ },
 };
 
-static struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 59, NULL, armada_38x_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
index e288f8ba0bf1..8ebc28ac289e 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
@@ -391,7 +391,7 @@ static const struct of_device_id armada_39x_pinctrl_of_match[] = {
 	{ },
 };
 
-static struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 59, NULL, armada_39x_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index e4ea71a9d985..cec3fef6f77f 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -378,7 +378,7 @@ static const struct of_device_id armada_xp_pinctrl_of_match[] = {
 	{ },
 };
 
-static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
 };
 
@@ -387,7 +387,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
 	MPP_GPIO_RANGE(1,  32, 32, 17),
 };
 
-static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
 };
 
@@ -397,7 +397,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
 	MPP_GPIO_RANGE(2,  64, 64,  3),
 };
 
-static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index f93ae0dcef9c..745421496f6b 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -354,7 +354,7 @@ static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
 	return 0;
 }
 
-static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl dove_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
 	MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
 	MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 5f89c26f3292..a331bb13a984 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -370,7 +370,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
 		MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1, 0))),
 };
 
-static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 44, NULL, kirkwood_mpp_ctrl),
 };
 
@@ -379,7 +379,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
 	MPP_GPIO_RANGE(1, 35, 35, 10),
 };
 
-static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
 };
 
@@ -388,7 +388,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
 	MPP_GPIO_RANGE(1, 32, 32,  4),
 };
 
-static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
 };
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index b6ec6db78351..a073d67f03e3 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -38,7 +38,7 @@ struct mvebu_pinctrl_function {
 
 struct mvebu_pinctrl_group {
 	const char *name;
-	struct mvebu_mpp_ctrl *ctrl;
+	const struct mvebu_mpp_ctrl *ctrl;
 	struct mvebu_mpp_ctrl_setting *settings;
 	unsigned num_settings;
 	unsigned gid;
@@ -582,7 +582,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	pctl->num_groups = 0;
 	pctl->desc.npins = 0;
 	for (n = 0; n < soc->ncontrols; n++) {
-		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+		const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
 
 		pctl->desc.npins += ctrl->npins;
 		/* initialize control's pins[] array */
@@ -628,7 +628,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	/* assign mpp controls to groups */
 	gid = 0;
 	for (n = 0; n < soc->ncontrols; n++) {
-		struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+		const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
 		pctl->groups[gid].gid = gid;
 		pctl->groups[gid].ctrl = ctrl;
 		pctl->groups[gid].name = ctrl->name;
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index b75a5f4adf3b..7f7c24ac49e3 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -105,7 +105,7 @@ struct mvebu_mpp_mode {
  */
 struct mvebu_pinctrl_soc_info {
 	u8 variant;
-	struct mvebu_mpp_ctrl *controls;
+	const struct mvebu_mpp_ctrl *controls;
 	int ncontrols;
 	struct mvebu_mpp_mode *modes;
 	int nmodes;
diff --git a/drivers/pinctrl/mvebu/pinctrl-orion.c b/drivers/pinctrl/mvebu/pinctrl-orion.c
index 84e144167b44..18c83b0a5a7c 100644
--- a/drivers/pinctrl/mvebu/pinctrl-orion.c
+++ b/drivers/pinctrl/mvebu/pinctrl-orion.c
@@ -161,7 +161,7 @@ static struct mvebu_mpp_mode orion_mpp_modes[] = {
 		 MPP_VAR_FUNCTION(0x5, "gpio", NULL,        V_5182)),
 };
 
-static struct mvebu_mpp_ctrl orion_mpp_controls[] = {
+static const struct mvebu_mpp_ctrl orion_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 19, NULL, orion_mpp_ctrl),
 };
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC 2/5] pinctrl: mvebu: provide per-control private data
From: Russell King @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

Provide per-control private data into each mvebu pinctrl method, which
will allow us to provide some completely generic helpers without the
global variable and per-instance function definitions that would be
required when we have multiple pin controllers on a SoC.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/pinctrl/mvebu/pinctrl-armada-370.c |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-armada-375.c |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-armada-38x.c |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-armada-39x.c |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c  |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-dove.c       | 50 ++++++++++++++++++++----------
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c   |  6 ++--
 drivers/pinctrl/mvebu/pinctrl-mvebu.c      | 14 ++++++---
 drivers/pinctrl/mvebu/pinctrl-mvebu.h      | 21 ++++++++++---
 drivers/pinctrl/mvebu/pinctrl-orion.c      |  6 ++--
 10 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index 3cb6b4ea0118..4dc083ffd561 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -25,12 +25,14 @@
 
 static void __iomem *mpp_base;
 
-static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int armada_370_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int armada_370_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-375.c b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
index c9dba08780c5..c6168102bd17 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-375.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
@@ -25,12 +25,14 @@
 
 static void __iomem *mpp_base;
 
-static int armada_375_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int armada_375_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int armada_375_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int armada_375_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
index 52f2ab82901a..98aee37effef 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
@@ -24,12 +24,14 @@
 
 static void __iomem *mpp_base;
 
-static int armada_38x_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int armada_38x_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int armada_38x_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int armada_38x_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
index 8ebc28ac289e..4b1ba4424e0a 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
@@ -24,12 +24,14 @@
 
 static void __iomem *mpp_base;
 
-static int armada_39x_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int armada_39x_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int armada_39x_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int armada_39x_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				   unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index cec3fef6f77f..a777925e0f34 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -33,12 +33,14 @@
 static void __iomem *mpp_base;
 static u32 *mpp_saved_regs;
 
-static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int armada_xp_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				  unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int armada_xp_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				  unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index 745421496f6b..fb0b42c24405 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -66,17 +66,20 @@ static void __iomem *mpp4_base;
 static void __iomem *pmu_base;
 static struct regmap *gconfmap;
 
-static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			     unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int dove_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int dove_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			     unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
 
-static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				 unsigned pid, unsigned long *config)
 {
 	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
@@ -93,7 +96,8 @@ static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				 unsigned pid, unsigned long config)
 {
 	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
@@ -114,7 +118,8 @@ static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
 	return 0;
 }
 
-static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long *config)
 {
 	unsigned long mpp4 = readl(mpp4_base);
 	unsigned long mask;
@@ -144,7 +149,8 @@ static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
+static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long config)
 {
 	unsigned long mpp4 = readl(mpp4_base);
 	unsigned long mask;
@@ -178,7 +184,8 @@ static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
 	return 0;
 }
 
-static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long *config)
 {
 	unsigned int gmpp;
 
@@ -188,7 +195,8 @@ static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
+static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long config)
 {
 	regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
 			   NAND_GPIO_EN,
@@ -196,7 +204,8 @@ static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
 	return 0;
 }
 
-static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+				unsigned long *config)
 {
 	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 
@@ -205,7 +214,8 @@ static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
+static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+				unsigned long config)
 {
 	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
 
@@ -217,7 +227,8 @@ static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
 	return 0;
 }
 
-static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+				unsigned long *config)
 {
 	unsigned int mpp4 = readl(mpp4_base);
 	unsigned int sspc1;
@@ -247,7 +258,8 @@ static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
+static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+				unsigned long config)
 {
 	unsigned int mpp4 = readl(mpp4_base);
 
@@ -274,11 +286,12 @@ static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
  * break other functions. If you require all mpps as gpio
  * enforce gpio setting by pinctrl mapping.
  */
-static int dove_audio1_ctrl_gpio_req(unsigned pid)
+static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl_data *data,
+				     unsigned pid)
 {
 	unsigned long config;
 
-	dove_audio1_ctrl_get(pid, &config);
+	dove_audio1_ctrl_get(data, pid, &config);
 
 	switch (config) {
 	case 0x02: /* i2s1 : gpio[56:57] */
@@ -301,14 +314,16 @@ static int dove_audio1_ctrl_gpio_req(unsigned pid)
 }
 
 /* mpp[52:57] has gpio pins capable of in and out */
-static int dove_audio1_ctrl_gpio_dir(unsigned pid, bool input)
+static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl_data *data,
+				     unsigned pid, bool input)
 {
 	if (pid < 52 || pid > 57)
 		return -ENOTSUPP;
 	return 0;
 }
 
-static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
+static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long *config)
 {
 	unsigned int gcfg1;
 	unsigned int gcfg2;
@@ -327,7 +342,8 @@ static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
+static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long config)
 {
 	unsigned int gcfg1 = 0;
 	unsigned int gcfg2 = 0;
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index a331bb13a984..89101f36f5d0 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -23,12 +23,14 @@
 
 static void __iomem *mpp_base;
 
-static int kirkwood_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int kirkwood_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+				 unsigned pid, unsigned long *config)
 {
 	return default_mpp_ctrl_get(mpp_base, pid, config);
 }
 
-static int kirkwood_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int kirkwood_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+				 unsigned pid, unsigned long config)
 {
 	return default_mpp_ctrl_set(mpp_base, pid, config);
 }
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index a073d67f03e3..c2e35da9bbd7 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -39,6 +39,7 @@ struct mvebu_pinctrl_function {
 struct mvebu_pinctrl_group {
 	const char *name;
 	const struct mvebu_mpp_ctrl *ctrl;
+	struct mvebu_mpp_ctrl_data *data;
 	struct mvebu_mpp_ctrl_setting *settings;
 	unsigned num_settings;
 	unsigned gid;
@@ -146,7 +147,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
 	if (!grp->ctrl)
 		return -EINVAL;
 
-	return grp->ctrl->mpp_get(grp->pins[0], config);
+	return grp->ctrl->mpp_get(grp->data, grp->pins[0], config);
 }
 
 static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
@@ -161,7 +162,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	for (i = 0; i < num_configs; i++) {
-		ret = grp->ctrl->mpp_set(grp->pins[0], configs[i]);
+		ret = grp->ctrl->mpp_set(grp->data, grp->pins[0], configs[i]);
 		if (ret)
 			return ret;
 	} /* for each config */
@@ -302,7 +303,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	if (grp->ctrl->mpp_gpio_req)
-		return grp->ctrl->mpp_gpio_req(offset);
+		return grp->ctrl->mpp_gpio_req(grp->data, offset);
 
 	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
 	if (!setting)
@@ -325,7 +326,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	if (grp->ctrl->mpp_gpio_dir)
-		return grp->ctrl->mpp_gpio_dir(offset, input);
+		return grp->ctrl->mpp_gpio_dir(grp->data, offset, input);
 
 	setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
 	if (!setting)
@@ -629,8 +630,12 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	gid = 0;
 	for (n = 0; n < soc->ncontrols; n++) {
 		const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+		struct mvebu_mpp_ctrl_data *data = soc->control_data ?
+						   &soc->control_data[n] : NULL;
+
 		pctl->groups[gid].gid = gid;
 		pctl->groups[gid].ctrl = ctrl;
+		pctl->groups[gid].data = data;
 		pctl->groups[gid].name = ctrl->name;
 		pctl->groups[gid].pins = ctrl->pins;
 		pctl->groups[gid].npins = ctrl->npins;
@@ -650,6 +655,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 				gid++;
 				pctl->groups[gid].gid = gid;
 				pctl->groups[gid].ctrl = ctrl;
+				pctl->groups[gid].data = data;
 				pctl->groups[gid].name = noname_buf;
 				pctl->groups[gid].pins = &ctrl->pins[k];
 				pctl->groups[gid].npins = 1;
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index 7f7c24ac49e3..37bfa3bb56f0 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -14,6 +14,14 @@
 #define __PINCTRL_MVEBU_H__
 
 /**
+ * struct mvebu_mpp_ctrl_data - private data for the mpp ctrl operations
+ * @base: base address of pinctrl hardware
+ */
+struct mvebu_mpp_ctrl_data {
+	void __iomem *base;
+};
+
+/**
  * struct mvebu_mpp_ctrl - describe a mpp control
  * @name: name of the control group
  * @pid: first pin id handled by this control
@@ -37,10 +45,13 @@ struct mvebu_mpp_ctrl {
 	u8 pid;
 	u8 npins;
 	unsigned *pins;
-	int (*mpp_get)(unsigned pid, unsigned long *config);
-	int (*mpp_set)(unsigned pid, unsigned long config);
-	int (*mpp_gpio_req)(unsigned pid);
-	int (*mpp_gpio_dir)(unsigned pid, bool input);
+	int (*mpp_get)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+		       unsigned long *config);
+	int (*mpp_set)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+		       unsigned long config);
+	int (*mpp_gpio_req)(struct mvebu_mpp_ctrl_data *data, unsigned pid);
+	int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			    bool input);
 };
 
 /**
@@ -93,6 +104,7 @@ struct mvebu_mpp_mode {
  * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
  * @variant: variant mask of soc_info
  * @controls: list of available mvebu_mpp_ctrls
+ * @control_data: optional array, one entry for each control
  * @ncontrols: number of available mvebu_mpp_ctrls
  * @modes: list of available mvebu_mpp_modes
  * @nmodes: number of available mvebu_mpp_modes
@@ -106,6 +118,7 @@ struct mvebu_mpp_mode {
 struct mvebu_pinctrl_soc_info {
 	u8 variant;
 	const struct mvebu_mpp_ctrl *controls;
+	struct mvebu_mpp_ctrl_data *control_data;
 	int ncontrols;
 	struct mvebu_mpp_mode *modes;
 	int nmodes;
diff --git a/drivers/pinctrl/mvebu/pinctrl-orion.c b/drivers/pinctrl/mvebu/pinctrl-orion.c
index 18c83b0a5a7c..c2e0c16cf9b3 100644
--- a/drivers/pinctrl/mvebu/pinctrl-orion.c
+++ b/drivers/pinctrl/mvebu/pinctrl-orion.c
@@ -32,7 +32,8 @@
 static void __iomem *mpp_base;
 static void __iomem *high_mpp_base;
 
-static int orion_mpp_ctrl_get(unsigned pid, unsigned long *config)
+static int orion_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+			      unsigned pid, unsigned long *config)
 {
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 
@@ -47,7 +48,8 @@ static int orion_mpp_ctrl_get(unsigned pid, unsigned long *config)
 	return 0;
 }
 
-static int orion_mpp_ctrl_set(unsigned pid, unsigned long config)
+static int orion_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+			      unsigned pid, unsigned long config)
 {
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC 3/5] pinctrl: mvebu: provide generic simple mmio-based implementation
From: Russell King @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

Provide a generic simple mmio-based probe function and methods, which
pinctrl drivers can use to initialise the mvebu pinctrl subsystem.
Most mvebu pinctrl drivers can use this.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/pinctrl/mvebu/pinctrl-mvebu.c | 57 +++++++++++++++++++++++++++++++++++
 drivers/pinctrl/mvebu/pinctrl-mvebu.h |  6 ++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index c2e35da9bbd7..9c6736d0595d 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -58,6 +58,30 @@ struct mvebu_pinctrl {
 	u8 variant;
 };
 
+int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+			     unsigned int pid, unsigned long *config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+
+	*config = (readl(data->base + off) >> shift) & MVEBU_MPP_MASK;
+
+	return 0;
+}
+
+int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+			     unsigned int pid, unsigned long config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned long reg;
+
+	reg = readl(data->base + off) & ~(MVEBU_MPP_MASK << shift);
+	writel(reg | (config << shift), data->base + off);
+
+	return 0;
+}
+
 static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
 	struct mvebu_pinctrl *pctl, unsigned pid)
 {
@@ -731,3 +755,36 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 
 	return 0;
 }
+
+/*
+ * mvebu_pinctrl_simple_mmio_probe - probe a simple mmio pinctrl
+ * @pdev: platform device (with platform data already attached)
+ *
+ * Initialise a simple (single base address) mmio pinctrl driver,
+ * assigning the MMIO base address to all mvebu mpp ctrl instances.
+ */
+int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev)
+{
+	struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+	struct mvebu_mpp_ctrl_data *mpp_data;
+	struct resource *res;
+	void __iomem *base;
+	int i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),
+				GFP_KERNEL);
+	if (!mpp_data)
+		return -ENOMEM;
+
+	for (i = 0; i < soc->ncontrols; i++)
+		mpp_data[i].base = base;
+
+	soc->control_data = mpp_data;
+
+	return mvebu_pinctrl_probe(pdev);
+}
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index 37bfa3bb56f0..c055581cf887 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -214,6 +214,12 @@ static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
 	return 0;
 }
 
+int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			       unsigned long *config);
+int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			       unsigned long config);
+
 int mvebu_pinctrl_probe(struct platform_device *pdev);
+int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev);
 
 #endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC 4/5] pinctrl: mvebu: switch drivers to generic simple mmio
From: Russell King @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

Move the mvebu pinctrl drivers over to the generic simple mmio
implementation, saving a substantial number of lines of code in
the process.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/pinctrl/mvebu/pinctrl-armada-370.c | 24 ++------------
 drivers/pinctrl/mvebu/pinctrl-armada-375.c | 24 ++------------
 drivers/pinctrl/mvebu/pinctrl-armada-38x.c | 24 ++------------
 drivers/pinctrl/mvebu/pinctrl-armada-39x.c | 24 ++------------
 drivers/pinctrl/mvebu/pinctrl-armada-xp.c  | 31 ++++--------------
 drivers/pinctrl/mvebu/pinctrl-dove.c       | 52 +++++++++++++++---------------
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c   | 28 +++-------------
 drivers/pinctrl/mvebu/pinctrl-mvebu.h      | 24 --------------
 8 files changed, 45 insertions(+), 186 deletions(-)

diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index 4dc083ffd561..c2de4f8ee488 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -23,20 +23,6 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
-
-static int armada_370_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int armada_370_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
 	MPP_MODE(0,
 	   MPP_FUNCTION(0x0, "gpio", NULL),
@@ -387,7 +373,7 @@ static const struct of_device_id armada_370_pinctrl_of_match[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 65, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
@@ -399,12 +385,6 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
 static int armada_370_pinctrl_probe(struct platform_device *pdev)
 {
 	struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
 
 	soc->variant = 0; /* no variants for Armada 370 */
 	soc->controls = mv88f6710_mpp_controls;
@@ -416,7 +396,7 @@ static int armada_370_pinctrl_probe(struct platform_device *pdev)
 
 	pdev->dev.platform_data = soc;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver armada_370_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-375.c b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
index c6168102bd17..30cbf23b0b03 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-375.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-375.c
@@ -23,20 +23,6 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
-
-static int armada_375_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int armada_375_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 static struct mvebu_mpp_mode mv88f6720_mpp_modes[] = {
 	MPP_MODE(0,
 		 MPP_FUNCTION(0x0, "gpio", NULL),
@@ -405,7 +391,7 @@ static const struct of_device_id armada_375_pinctrl_of_match[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 69, NULL, armada_375_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 69, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
@@ -417,12 +403,6 @@ static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
 static int armada_375_pinctrl_probe(struct platform_device *pdev)
 {
 	struct mvebu_pinctrl_soc_info *soc = &armada_375_pinctrl_info;
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
 
 	soc->variant = 0; /* no variants for Armada 375 */
 	soc->controls = mv88f6720_mpp_controls;
@@ -434,7 +414,7 @@ static int armada_375_pinctrl_probe(struct platform_device *pdev)
 
 	pdev->dev.platform_data = soc;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver armada_375_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
index 98aee37effef..e66ed239522e 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
@@ -22,20 +22,6 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
-
-static int armada_38x_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int armada_38x_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 enum {
 	V_88F6810 = BIT(0),
 	V_88F6820 = BIT(1),
@@ -412,7 +398,7 @@ static const struct of_device_id armada_38x_pinctrl_of_match[] = {
 };
 
 static const struct mvebu_mpp_ctrl armada_38x_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 59, NULL, armada_38x_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 59, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range armada_38x_mpp_gpio_ranges[] = {
@@ -425,16 +411,10 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev)
 	struct mvebu_pinctrl_soc_info *soc = &armada_38x_pinctrl_info;
 	const struct of_device_id *match =
 		of_match_device(armada_38x_pinctrl_of_match, &pdev->dev);
-	struct resource *res;
 
 	if (!match)
 		return -ENODEV;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
-
 	soc->variant = (unsigned) match->data & 0xff;
 	soc->controls = armada_38x_mpp_controls;
 	soc->ncontrols = ARRAY_SIZE(armada_38x_mpp_controls);
@@ -445,7 +425,7 @@ static int armada_38x_pinctrl_probe(struct platform_device *pdev)
 
 	pdev->dev.platform_data = soc;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver armada_38x_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
index 4b1ba4424e0a..697c8774a4da 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-39x.c
@@ -22,20 +22,6 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
-
-static int armada_39x_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int armada_39x_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				   unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 enum {
 	V_88F6920 = BIT(0),
 	V_88F6925 = BIT(1),
@@ -394,7 +380,7 @@ static const struct of_device_id armada_39x_pinctrl_of_match[] = {
 };
 
 static const struct mvebu_mpp_ctrl armada_39x_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 59, NULL, armada_39x_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 59, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range armada_39x_mpp_gpio_ranges[] = {
@@ -407,16 +393,10 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev)
 	struct mvebu_pinctrl_soc_info *soc = &armada_39x_pinctrl_info;
 	const struct of_device_id *match =
 		of_match_device(armada_39x_pinctrl_of_match, &pdev->dev);
-	struct resource *res;
 
 	if (!match)
 		return -ENODEV;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
-
 	soc->variant = (unsigned) match->data & 0xff;
 	soc->controls = armada_39x_mpp_controls;
 	soc->ncontrols = ARRAY_SIZE(armada_39x_mpp_controls);
@@ -427,7 +407,7 @@ static int armada_39x_pinctrl_probe(struct platform_device *pdev)
 
 	pdev->dev.platform_data = soc;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver armada_39x_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index a777925e0f34..63e1bd506983 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -30,21 +30,8 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
 static u32 *mpp_saved_regs;
 
-static int armada_xp_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				  unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int armada_xp_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				  unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 enum armada_xp_variant {
 	V_MV78230	= BIT(0),
 	V_MV78260	= BIT(1),
@@ -381,7 +368,7 @@ static const struct of_device_id armada_xp_pinctrl_of_match[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 48, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
@@ -390,7 +377,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 66, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
@@ -400,7 +387,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 66, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
@@ -419,7 +406,7 @@ static int armada_xp_pinctrl_suspend(struct platform_device *pdev,
 	nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
 
 	for (i = 0; i < nregs; i++)
-		mpp_saved_regs[i] = readl(mpp_base + i * 4);
+		mpp_saved_regs[i] = readl(soc->control_data[0].base + i * 4);
 
 	return 0;
 }
@@ -433,7 +420,7 @@ static int armada_xp_pinctrl_resume(struct platform_device *pdev)
 	nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
 
 	for (i = 0; i < nregs; i++)
-		writel(mpp_saved_regs[i], mpp_base + i * 4);
+		writel(mpp_saved_regs[i], soc->control_data[0].base + i * 4);
 
 	return 0;
 }
@@ -443,17 +430,11 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 	struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
 	const struct of_device_id *match =
 		of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
-	struct resource *res;
 	int nregs;
 
 	if (!match)
 		return -ENODEV;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
-
 	soc->variant = (unsigned) match->data & 0xff;
 
 	switch (soc->variant) {
@@ -501,7 +482,7 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
 
 	pdev->dev.platform_data = soc;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver armada_xp_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index fb0b42c24405..89ae93c49f2f 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -61,33 +61,20 @@
 
 #define CONFIG_PMU	BIT(4)
 
-static void __iomem *mpp_base;
 static void __iomem *mpp4_base;
 static void __iomem *pmu_base;
 static struct regmap *gconfmap;
 
-static int dove_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
-			     unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int dove_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
-			     unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
 				 unsigned pid, unsigned long *config)
 {
 	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
 	unsigned long func;
 
 	if ((pmu & BIT(pid)) == 0)
-		return default_mpp_ctrl_get(mpp_base, pid, config);
+		return mvebu_mmio_mpp_ctrl_get(data, pid, config);
 
 	func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
 	*config = (func >> shift) & MVEBU_MPP_MASK;
@@ -101,15 +88,15 @@ static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
 {
 	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
 	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
 	unsigned long func;
 
 	if ((config & CONFIG_PMU) == 0) {
-		writel(pmu & ~BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
-		return default_mpp_ctrl_set(mpp_base, pid, config);
+		writel(pmu & ~BIT(pid), data->base + PMU_MPP_GENERAL_CTRL);
+		return mvebu_mmio_mpp_ctrl_set(data, pid, config);
 	}
 
-	writel(pmu | BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
+	writel(pmu | BIT(pid), data->base + PMU_MPP_GENERAL_CTRL);
 	func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
 	func &= ~(MVEBU_MPP_MASK << shift);
 	func |= (config & MVEBU_MPP_MASK) << shift;
@@ -207,7 +194,7 @@ static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 				unsigned long *config)
 {
-	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
 
 	*config = ((pmu & AU0_AC97_SEL) != 0);
 
@@ -217,12 +204,12 @@ static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 				unsigned long config)
 {
-	unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
+	unsigned long pmu = readl(data->base + PMU_MPP_GENERAL_CTRL);
 
 	pmu &= ~AU0_AC97_SEL;
 	if (config)
 		pmu |= AU0_AC97_SEL;
-	writel(pmu, mpp_base + PMU_MPP_GENERAL_CTRL);
+	writel(pmu, data->base + PMU_MPP_GENERAL_CTRL);
 
 	return 0;
 }
@@ -372,7 +359,7 @@ static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 
 static const struct mvebu_mpp_ctrl dove_mpp_controls[] = {
 	MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
-	MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
+	MPP_FUNC_CTRL(16, 23, NULL, mvebu_mmio_mpp_ctrl),
 	MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
 	MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
 	MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
@@ -785,6 +772,10 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
 	struct resource fb_res;
 	const struct of_device_id *match =
 		of_match_device(dove_pinctrl_of_match, &pdev->dev);
+	struct mvebu_mpp_ctrl_data *mpp_data;
+	void __iomem *base;
+	int i;
+
 	pdev->dev.platform_data = (void *)match->data;
 
 	/*
@@ -799,9 +790,18 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
 	clk_prepare_enable(clk);
 
 	mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, mpp_res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
+	base = devm_ioremap_resource(&pdev->dev, mpp_res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	mpp_data = devm_kcalloc(&pdev->dev, dove_pinctrl_info.ncontrols,
+				sizeof(*mpp_data), GFP_KERNEL);
+	if (!mpp_data)
+		return -ENOMEM;
+
+	dove_pinctrl_info.control_data = mpp_data;
+	for (i = 0; i < ARRAY_SIZE(dove_mpp_controls); i++)
+		mpp_data[i].base = base;
 
 	/* prepare fallback resource */
 	memcpy(&fb_res, mpp_res, sizeof(struct resource));
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 89101f36f5d0..dad38d6dc646 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -21,20 +21,6 @@
 
 #include "pinctrl-mvebu.h"
 
-static void __iomem *mpp_base;
-
-static int kirkwood_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
-				 unsigned pid, unsigned long *config)
-{
-	return default_mpp_ctrl_get(mpp_base, pid, config);
-}
-
-static int kirkwood_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
-				 unsigned pid, unsigned long config)
-{
-	return default_mpp_ctrl_set(mpp_base, pid, config);
-}
-
 #define V(f6180, f6190, f6192, f6281, f6282, dx4122)	\
 	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
 	 (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
@@ -373,7 +359,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 44, NULL, kirkwood_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 44, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
@@ -382,7 +368,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 35, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
@@ -391,7 +377,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
 };
 
 static const struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
-	MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
+	MPP_FUNC_CTRL(0, 49, NULL, mvebu_mmio_mpp_ctrl),
 };
 
 static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
@@ -474,14 +460,10 @@ static int kirkwood_pinctrl_probe(struct platform_device *pdev)
 	struct resource *res;
 	const struct of_device_id *match =
 		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
-	pdev->dev.platform_data = (void *)match->data;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mpp_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp_base))
-		return PTR_ERR(mpp_base);
+	pdev->dev.platform_data = (void *)match->data;
 
-	return mvebu_pinctrl_probe(pdev);
+	return mvebu_pinctrl_simple_mmio_probe(pdev);
 }
 
 static struct platform_driver kirkwood_pinctrl_driver = {
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index c055581cf887..a9304cdc23e2 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -190,30 +190,6 @@ struct mvebu_pinctrl_soc_info {
 #define MVEBU_MPP_BITS		4
 #define MVEBU_MPP_MASK		0xf
 
-static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
-				       unsigned long *config)
-{
-	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-
-	*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;
-
-	return 0;
-}
-
-static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
-				       unsigned long config)
-{
-	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
-	unsigned long reg;
-
-	reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
-	writel(reg | (config << shift), base + off);
-
-	return 0;
-}
-
 int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 			       unsigned long *config);
 int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
-- 
2.7.4

^ permalink raw reply related

* [PATCH RFC 5/5] pinctrl: mvebu: add simple regmap based pinctrl implementation
From: Russell King @ 2017-01-13 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

Add a simple regmap based pinctrl implementation for mvebu, for syscon
based regmap drivers.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/pinctrl/mvebu/pinctrl-mvebu.c | 60 +++++++++++++++++++++++++++++++++++
 drivers/pinctrl/mvebu/pinctrl-mvebu.h | 16 +++++++++-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 9c6736d0595d..2f9a4e3e1ff1 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -23,6 +23,8 @@
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pinctrl-mvebu.h"
 
@@ -788,3 +790,61 @@ int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev)
 
 	return mvebu_pinctrl_probe(pdev);
 }
+
+int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
+			      unsigned int pid, unsigned long *config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned int val;
+	int err;
+
+	err = regmap_read(data->regmap.map, data->regmap.offset + off, &val);
+	if (err)
+		return err;
+
+	*config = (val >> shift) & MVEBU_MPP_MASK;
+
+	return 0;
+}
+
+int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
+			      unsigned int pid, unsigned long config)
+{
+	unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
+
+	return regmap_update_bits(data->regmap.map, data->regmap.offset + off,
+				  MVEBU_MPP_MASK << shift, config << shift);
+}
+
+int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
+				      struct device *syscon_dev)
+{
+	struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+	struct mvebu_mpp_ctrl_data *mpp_data;
+	struct regmap *regmap;
+	u32 offset;
+	int i;
+
+	regmap = syscon_node_to_regmap(syscon_dev->of_node);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	if (of_property_read_u32(pdev->dev.of_node, "offset", &offset))
+		return -EINVAL;
+
+	mpp_data = devm_kcalloc(&pdev->dev, soc->ncontrols, sizeof(*mpp_data),
+				GFP_KERNEL);
+	if (!mpp_data)
+		return -ENOMEM;
+
+	for (i = 0; i < soc->ncontrols; i++) {
+		mpp_data[i].regmap.map = regmap;
+		mpp_data[i].regmap.offset = offset;
+	}
+
+	soc->control_data = mpp_data;
+
+	return mvebu_pinctrl_probe(pdev);
+}
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index a9304cdc23e2..c90704e74884 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -16,9 +16,17 @@
 /**
  * struct mvebu_mpp_ctrl_data - private data for the mpp ctrl operations
  * @base: base address of pinctrl hardware
+ * @regmap.map: regmap structure
+ * @regmap.offset: regmap offset
  */
 struct mvebu_mpp_ctrl_data {
-	void __iomem *base;
+	union {
+		void __iomem *base;
+		struct {
+			struct regmap *map;
+			u32 offset;
+		} regmap;
+	};
 };
 
 /**
@@ -194,8 +202,14 @@ int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 			       unsigned long *config);
 int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
 			       unsigned long config);
+int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long *config);
+int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid,
+			      unsigned long config);
 
 int mvebu_pinctrl_probe(struct platform_device *pdev);
 int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev);
+int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev,
+				      struct device *syscon_dev);
 
 #endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH] iommu/dma: Add support for DMA_ATTR_FORCE_CONTIGUOUS
From: Geert Uytterhoeven @ 2017-01-13 11:07 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for DMA_ATTR_FORCE_CONTIGUOUS to the generic IOMMU DMA code.
This allows to allocate physically contiguous DMA buffers on arm64
systems with an IOMMU.

Note that as this uses the CMA allocator, setting this attribute has a
runtime-dependency on CONFIG_DMA_CMA, just like on arm32.

For arm64 systems using swiotlb, no changes are needed to support the
allocation of physically contiguous DMA buffers:
  - swiotlb always uses physically contiguous buffers (up to
    IO_TLB_SEGSIZE = 128 pages),
  - arm64's __dma_alloc_coherent() already calls
    dma_alloc_from_contiguous() when CMA is available.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 arch/arm64/mm/dma-mapping.c |  4 ++--
 drivers/iommu/dma-iommu.c   | 44 ++++++++++++++++++++++++++++++++++----------
 include/linux/dma-iommu.h   |  2 +-
 3 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 1d7d5d2881db7c19..5fba14a21163e41f 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -589,7 +589,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 		addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot,
 					      __builtin_return_address(0));
 		if (!addr)
-			iommu_dma_free(dev, pages, iosize, handle);
+			iommu_dma_free(dev, pages, iosize, handle, attrs);
 	} else {
 		struct page *page;
 		/*
@@ -642,7 +642,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 
 		if (WARN_ON(!area || !area->pages))
 			return;
-		iommu_dma_free(dev, area->pages, iosize, &handle);
+		iommu_dma_free(dev, area->pages, iosize, &handle, attrs);
 		dma_common_free_remap(cpu_addr, size, VM_USERMAP);
 	} else {
 		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 2db0d641cf4505b5..b991e8dcbbbb35c5 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -30,6 +30,7 @@
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/vmalloc.h>
+#include <linux/dma-contiguous.h>
 
 struct iommu_dma_msi_page {
 	struct list_head	list;
@@ -238,15 +239,21 @@ static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr)
 	__free_iova(iovad, iova);
 }
 
-static void __iommu_dma_free_pages(struct page **pages, int count)
+static void __iommu_dma_free_pages(struct device *dev, struct page **pages,
+				   int count, unsigned long attrs)
 {
-	while (count--)
-		__free_page(pages[count]);
+	if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
+		dma_release_from_contiguous(dev, pages[0], count);
+	} else {
+		while (count--)
+			__free_page(pages[count]);
+	}
 	kvfree(pages);
 }
 
-static struct page **__iommu_dma_alloc_pages(unsigned int count,
-		unsigned long order_mask, gfp_t gfp)
+static struct page **__iommu_dma_alloc_pages(struct device *dev,
+		unsigned int count, unsigned long order_mask, gfp_t gfp,
+		unsigned long attrs)
 {
 	struct page **pages;
 	unsigned int i = 0, array_size = count * sizeof(*pages);
@@ -265,6 +272,20 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
 	/* IOMMU can map any pages, so himem can also be used here */
 	gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
 
+	if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
+		int order = get_order(count << PAGE_SHIFT);
+		struct page *page;
+
+		page = dma_alloc_from_contiguous(dev, count, order);
+		if (!page)
+			return NULL;
+
+		while (count--)
+			pages[i++] = page++;
+
+		return pages;
+	}
+
 	while (count) {
 		struct page *page = NULL;
 		unsigned int order_size;
@@ -294,7 +315,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
 			__free_pages(page, order);
 		}
 		if (!page) {
-			__iommu_dma_free_pages(pages, i);
+			__iommu_dma_free_pages(dev, pages, i, attrs);
 			return NULL;
 		}
 		count -= order_size;
@@ -310,15 +331,17 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
  * @pages: Array of buffer pages as returned by iommu_dma_alloc()
  * @size: Size of buffer in bytes
  * @handle: DMA address of buffer
+ * @attrs: DMA attributes used for allocation of this buffer
  *
  * Frees both the pages associated with the buffer, and the array
  * describing them
  */
 void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
-		dma_addr_t *handle)
+		dma_addr_t *handle, unsigned long attrs)
 {
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle);
-	__iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
+	__iommu_dma_free_pages(dev, pages, PAGE_ALIGN(size) >> PAGE_SHIFT,
+			       attrs);
 	*handle = DMA_ERROR_CODE;
 }
 
@@ -365,7 +388,8 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
 		alloc_sizes = min_size;
 
 	count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	pages = __iommu_dma_alloc_pages(count, alloc_sizes >> PAGE_SHIFT, gfp);
+	pages = __iommu_dma_alloc_pages(dev, count, alloc_sizes >> PAGE_SHIFT,
+					gfp, attrs);
 	if (!pages)
 		return NULL;
 
@@ -403,7 +427,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
 out_free_iova:
 	__free_iova(iovad, iova);
 out_free_pages:
-	__iommu_dma_free_pages(pages, count);
+	__iommu_dma_free_pages(dev, pages, count, attrs);
 	return NULL;
 }
 
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 7f7e9a7e3839966c..35fa6b7f9bac9b35 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -44,7 +44,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
 		unsigned long attrs, int prot, dma_addr_t *handle,
 		void (*flush_page)(struct device *, const void *, phys_addr_t));
 void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
-		dma_addr_t *handle);
+		dma_addr_t *handle, unsigned long attrs);
 
 int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma);
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/4] video: ARM CLCD: add support of an optional GPIO to enable panel
From: Bartlomiej Zolnierkiewicz @ 2017-01-13 11:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d1534f4b-e564-d87e-b408-9b7215a90de2@mleia.com>


Hi,

On Thursday, January 12, 2017 11:26:14 PM Vladimir Zapolskiy wrote:
> On 01/12/2017 10:27 AM, Linus Walleij wrote:
> > On Thu, Jan 12, 2017 at 1:05 AM, Vladimir Zapolskiy <vz@mleia.com> wrote:
> >> On 01/11/2017 05:16 PM, Linus Walleij wrote:
> >>> On Tue, Jan 10, 2017 at 2:47 PM, Vladimir Murzin
> >>> <vladimir.murzin@arm.com> wrote:
> >>>
> >>>> In another thread Benjamin pointed at patch [1] in drm/kms part for noMMU.
> >>>>
> >>>> [1] https://cgit.freedesktop.org/drm/drm-misc/commit/?id=62a0d98a188cc4ebd8ea54b37d274ec20465e464
> >>>
> >>> Problem solved?
> >>>
> >>> Vladimir: I do not require in any way that you create a CLCD driver for DRM,
> >>> I just think it would be very very nice...
> >>>
> >>
> >> I have no other option, this series is unreviewed and thus unlikely it will
> >> be applied, still a panel PCB on my board needs power management support.
> > 
> > Hm I can ACK it I guess, but mergeing it into an unmaintained subsystem
> > is another issue, just not very optimal. 
> 
> + Bartlomiej
> 
> Linus, your ack is always more than appreciated.

+1

> To all appearance Bartlomiej is a new honoured framebuffer layer maintainer.
> 
> Bartlomiej, do you have the changes under discussion in your mailbox or
> should I resend them to you directly for review?

No need for resend, I picked them from the list and they are on TODO.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> > If you get it working on your system I can look into migrating all the old
> > users to DRM as well.
> > 
> 
> Sure, I started development of a simple CLCD DRM driver as an own attractive
> exercise, I'll keep you informed of the progress.
> 
> --
> With best wishes,
> Vladimir

^ permalink raw reply

* [PATCH v2] KVM: arm/arm64: Fix occasional warning from the timer work function
From: Marc Zyngier @ 2017-01-13 11:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170109111856.8439-1-christoffer.dall@linaro.org>

On 09/01/17 11:18, Christoffer Dall wrote:
> When a VCPU blocks (WFI) and has programmed the vtimer, we program a
> soft timer to expire in the future to wake up the vcpu thread when
> appropriate.  Because such as wake up involves a vcpu kick, and the
> timer expire function can get called from interrupt context, and the
> kick may sleep, we have to schedule the kick in the work function.
> 
> The work function currently has a warning that gets raised if it turns
> out that the timer shouldn't fire when it's run, which was added because
> the idea was that in that case the work should never have been cancelled.
> 
> However, it turns out that this whole thing is racy and we can get
> spurious warnings.  The problem is that we clear the armed flag in the
> work function, which may run in parallel with the
> kvm_timer_unschedule->timer_disarm() call.  This results in a possible
> situation where the timer_disarm() call does not call
> cancel_work_sync(), which effectively synchronizes the completion of the
> work function with running the VCPU.  As a result, the VCPU thread
> proceeds before the work function completees, causing changes to the
> timer state such that kvm_timer_should_fire(vcpu) returns false in the
> work function.
> 
> All we do in the work function is to kick the VCPU, and an occasional
> rare extra kick never harmed anyone.  Since the race above is extremely
> rare, we don't bother checking if the race happens but simply remove the
> check and the clearing of the armed flag from the work function.
> 
> Reported-by: Matthias Brugger <mbrugger@suse.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH v3 0/3] arm64: dts: juno: CoreSight support updates
From: Sudeep Holla @ 2017-01-13 11:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJ9a7Vha=GiyEcVkzh-N9s7XN8N94KAiM=iY2W4MyLqLWRe-2w@mail.gmail.com>



On 13/01/17 11:09, Mike Leach wrote:
> Hi Sudeep,
> 
> 
> Patchset tested successfully on juno-r1
> 

Thanks and I did a quick test on Juno R2. I have pushed the branch [1]
with minor comment change as pointed out my Mathieu.

-- 
Regards,
Sudeep

[1]
git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git
for-next/updates/juno

^ permalink raw reply

* [PATCH v29 9/9] Documentation: dt: chosen properties for arm64 kdump
From: Mark Rutland @ 2017-01-13 11:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113091339.GK20972@linaro.org>

On Fri, Jan 13, 2017 at 06:13:49PM +0900, AKASHI Takahiro wrote:
> On Thu, Jan 12, 2017 at 03:39:45PM +0000, Mark Rutland wrote:
> > On Wed, Dec 28, 2016 at 01:37:34PM +0900, AKASHI Takahiro wrote:
> > > +linux,crashkernel-base
> > > +linux,crashkernel-size
> > > +----------------------
> > > +
> > > +These properties (currently used on PowerPC and arm64) indicates
> > > +the base address and the size, respectively, of the reserved memory
> > > +range for crash dump kernel.
> > 
> > From this description, it's not clear to me what the (expected)
> > consumers of this property are, nor what is expected to provide it.
> > 
> > In previous rounds of review, I had assumed that this was used to
> > describe a preference to the first kernel as to what region of memory
> > should be used for a subsequent kdump kernel. Looking around, I'm not
> > sure if I was correct in that assessment.
> > 
> > I see that arch/powerpc seems to consume this property to configure
> > crashk_res, but it also rewrites it based on crashk_res, presumably for
> > the benefit of userspace. It's not clear to me how on powerpc the kdump
> > kernel knows its memory range -- is more DT modification done in the
> > kernel and/or userspace?
> 
> I don't believe that powerpc will rewrite the property any way.
> As far as I know from *the source code*, powerpc kernel retrieves
> the memory range for crash dump kernel from a kernel command line, i.e.
> crashkernel=, and then exposes it through DT to userspace (assuming
> kexec-tools).

The rewriting I describe is in export_crashk_values() in
arch/powerpc/kernel/machine_kexec.c, where the code deletes existing the
properties, and adds new ones, to the DT exposed to userspace.

So I think we're just quibbling over the definition of "rewrite".

> > arm64 we should either ensure that /proc/iomem is consistently usable
> > (and have userspace consistently use it), or we should expose a new file
> > specifically to expose this information.
> 
> The thing that I had in my mind when adding this property is that
> /proc/iomem would be obsolete in the future, then we should have
> an alternative in hand.

Ok.

My disagreement is with using the DT as a channel to convey information
from the kernel to userspace.

I'm more than happy for a new file or other mechanism to express this
information. For example, we could add
/sys/kernel/kexec_crash_{base,size} or similar.


> > Further, I do not think we need this property. It makes more sense to me
> > for the preference of a a region to be described to the *first* kernel
> > using the command line consistently.
> > 
> > So I think we should drop this property, and not use it on arm64. Please
> > document this as powerpc only.
> 
> OK, but if we drop the property from arm64 code, we have no reason
> to leave its description in this patch.
> (In fact, there are a few more (undocumented) properties that only ppc
> uses for kdump.)

I'm happy to drop it, then.

> > > +linux,usable-memory-range
> > > +-------------------------
> > > +
> > > +This property (currently used only on arm64) holds the memory range,
> > > +the base address and the size, which can be used as system ram on
> > > +the *current* kernel. Note that, if this property is present, any memory
> > > +regions under "memory" nodes in DT blob or ones marked as "conventional
> > > +memory" in EFI memory map should be ignored.
> > 
> > Could you please replace this with:
> > 
> >   This property (arm64 only) holds a base address and size, describing a
> >   limited region in which memory may be considered available for use by
> >   the kernel. Memory outside of this range is not available for use.
> >   
> >   This property describes a limitation: memory within this range is only
> >   valid when also described through another mechanism that the kernel
> >   would otherwise use to determine available memory (e.g. memory nodes
> >   or the EFI memory map). Valid memory may be sparse within the range.
> 
> Sure.

Cheers!

Thanks,
Mark.

^ permalink raw reply

* [PATCH] arm64/mm: use phys_addr_t
From: Catalin Marinas @ 2017-01-13 11:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484287175-14342-1-git-send-email-miles.chen@mediatek.com>

On Fri, Jan 13, 2017 at 01:59:35PM +0800, miles.chen at mediatek.com wrote:
> From: Miles Chen <miles.chen@mediatek.com>
> 
> Use phys_addr_t instead of unsigned long for the
> return value of __pa(), make code easy to understand.
> 
> Signed-off-by: Miles Chen <miles.chen@mediatek.com>
> ---
>  arch/arm64/mm/mmu.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 17243e4..7eb7c21 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -359,8 +359,8 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
>  
>  static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
>  {
> -	unsigned long kernel_start = __pa(_text);
> -	unsigned long kernel_end = __pa(__init_begin);
> +	phys_addr_t kernel_start = __pa(_text);
> +	phys_addr_t kernel_end = __pa(__init_begin);

Looks fine.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH] arm64/mm: use phys_addr_t
From: Mark Rutland @ 2017-01-13 11:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484287175-14342-1-git-send-email-miles.chen@mediatek.com>

On Fri, Jan 13, 2017 at 01:59:35PM +0800, miles.chen at mediatek.com wrote:
> From: Miles Chen <miles.chen@mediatek.com>
> 
> Use phys_addr_t instead of unsigned long for the
> return value of __pa(), make code easy to understand.
> 
> Signed-off-by: Miles Chen <miles.chen@mediatek.com>

This looks sensible to me. It's consistent with the types these
variables are compared against, and with the types of function
parameters these are passed as.

Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks,
Mark.

> ---
>  arch/arm64/mm/mmu.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 17243e4..7eb7c21 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -359,8 +359,8 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
>  
>  static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
>  {
> -	unsigned long kernel_start = __pa(_text);
> -	unsigned long kernel_end = __pa(__init_begin);
> +	phys_addr_t kernel_start = __pa(_text);
> +	phys_addr_t kernel_end = __pa(__init_begin);
>  
>  	/*
>  	 * Take care not to create a writable alias for the
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [RFC] Kernel panic down to swiotlb when doing insmod a simple driver
From: Ard Biesheuvel @ 2017-01-13 11:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <99472068-069a-7759-8d6e-019fd875264d@arm.com>

On 13 January 2017 at 11:03, Robin Murphy <robin.murphy@arm.com> wrote:
> On 13/01/17 10:00, Shawn Lin wrote:
>> Hi,
>>
>> Sorry for sending this RFC for help as I couldn't find some useful hint
>> to slove my issue by git-log the swiotlb commit from kernel v4.4 to
>> v4.9 and I'm also not familar with these stuff. So could you kindly
>> point me to the right direction to debug it? Thanks. :)
>>
>> --------------------------------------
>> We just have a very simple wifi driver *built as ko module* which only
>> have a probe function to do the basic init work and call SDIO API to
>> transfer some bytes.
>>
>> Env: kernel 4.4 stable tree, ARM64(rk3399)
>>
>> Two cases are included:
>
> And they are both wrong :)
>
>> The crash case:
>>
>> u8 __aligned(32) buf[PAGE_SIZE]; //global here in ko driver file
>
> It is only valid to do DMA from linear map addresses - I'm not sure if
> the modules area was in the linear map before, but either way it
> probably isn't now (Ard, Mark?). Either way, I don't believe static data
> honours ARCH_DMA_MINALIGN in general, so it's still highly inadvisable.
>

The __aligned() modifier should work fine: the alignment is propagated
to the ELF section alignment, which in turn is honoured by the module
loader. The problem is that '32' is too low for non-coherent DMA to be
safe. In general, alignments up to 4 KB should work everywhere.

I am surprised though that this ever  worked as a module, given that
modules are (and have always been) loaded in the vmalloc area, which
means VA to PA translations performed in the DMA layer on the
addresses of statically allocated buffers are unlikely to return
correct values (as your panic log proves)

>> static int wifi_probe(struct sdio_func *func, const struct
>> sdio_device_id *id)
>> {
>>   // prepare some SDIO work before
>>   printk("wifi_probe: buf = 0x%x\n", buf);
>>   sdio_memcpy_toio(func, 0, buf, 200);
>> }
>>
>> The workable case:
>>
>> static int wifi_probe(struct sdio_func *func, const struct
>> sdio_device_id *id)
>> {
>>
>>    u8 __aligned(32) buf[PAGE_SIZE]; //move inside the probe function
>
> No. DMA from the stack is right out, both for the aforementioned
> alignment reasons, and the fact that we now have (or will have)
> virtually-mapped stacks. One of the benefits of the latter is that it
> catches bugs like this ;)
>

Actually, aligned stack variables also work fine. But DMA involving
the stack is not, so that is not really relevant.

> Get your buffer from kmalloc() or a page allocation, and everything
> should be correct.
>

Agreed.

^ permalink raw reply

* [PATCH] arm64/mm: use phys_addr_t
From: Ard Biesheuvel @ 2017-01-13 11:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113112205.GA26804@leverpostej>

On 13 January 2017 at 11:22, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Jan 13, 2017 at 01:59:35PM +0800, miles.chen at mediatek.com wrote:
>> From: Miles Chen <miles.chen@mediatek.com>
>>
>> Use phys_addr_t instead of unsigned long for the
>> return value of __pa(), make code easy to understand.
>>
>> Signed-off-by: Miles Chen <miles.chen@mediatek.com>
>
> This looks sensible to me. It's consistent with the types these
> variables are compared against, and with the types of function
> parameters these are passed as.
>

Indeed. But doesn't it clash with Laura's series?

> Acked-by: Mark Rutland <mark.rutland@arm.com>
>
> Thanks,
> Mark.
>
>> ---
>>  arch/arm64/mm/mmu.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 17243e4..7eb7c21 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -359,8 +359,8 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
>>
>>  static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
>>  {
>> -     unsigned long kernel_start = __pa(_text);
>> -     unsigned long kernel_end = __pa(__init_begin);
>> +     phys_addr_t kernel_start = __pa(_text);
>> +     phys_addr_t kernel_end = __pa(__init_begin);
>>
>>       /*
>>        * Take care not to create a writable alias for the
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH RFC 0/5] mvebu cleanups and preparation for Armada 7k/8k
From: Russell King - ARM Linux @ 2017-01-13 11:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113110240.GA29164@n2100.armlinux.org.uk>

On Fri, Jan 13, 2017 at 11:02:40AM +0000, Russell King - ARM Linux wrote:
> (Resend including linux-arm-kernel)

BTW, would be useful if MAINTAINERS could list maintainers for both
this code and the mvebu gpio code too.  At the moment, it seems Linus
is the person responsible for both of those - but I suspect the mvebu
people want to be copied on patches...

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* [PATCH 0/3] KVM/ARM updates for 4.10-rc4
From: Marc Zyngier @ 2017-01-13 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

Radim, Paolo,

Here's the KVM/ARM updates for 4.10-rc4. Two timer fixes, and one vgic
fix for a deadlock that's been reported this week (which should land
into stable).

Please pull.

Thanks,

	M.

The following changes since commit a121103c922847ba5010819a3f250f1f7fc84ab8:

  Linux 4.10-rc3 (2017-01-08 14:18:17 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-4.10-rc4

for you to fetch changes up to 1193e6aeecb36c74c48c7cd0f641acbbed9ddeef:

  KVM: arm/arm64: vgic: Fix deadlock on error handling (2017-01-13 11:19:35 +0000)

----------------------------------------------------------------
KVM/ARM updates for 4.10-rc4

- Fix for timer setup on VHE machines
- Drop spurious warning when the timer races against
  the vcpu running again
- Prevent a vgic deadlock when the initialization fails

----------------------------------------------------------------
Christoffer Dall (1):
      KVM: arm/arm64: Fix occasional warning from the timer work function

Jintack Lim (1):
      KVM: arm64: Access CNTHCTL_EL2 bit fields correctly on VHE systems

Marc Zyngier (1):
      KVM: arm/arm64: vgic: Fix deadlock on error handling

 arch/arm/include/asm/virt.h   |  5 +++++
 arch/arm/kvm/arm.c            |  3 +++
 arch/arm64/include/asm/virt.h |  9 +++++++++
 include/kvm/arm_arch_timer.h  |  1 +
 virt/kvm/arm/arch_timer.c     | 26 +++++++++++++++++++++++---
 virt/kvm/arm/hyp/timer-sr.c   | 33 +++++++++++++++++++++------------
 virt/kvm/arm/vgic/vgic-init.c | 18 +++++++++++++-----
 virt/kvm/arm/vgic/vgic-v2.c   |  2 --
 virt/kvm/arm/vgic/vgic-v3.c   |  2 --
 9 files changed, 75 insertions(+), 24 deletions(-)

^ permalink raw reply

* [PATCH 1/3] KVM: arm/arm64: Fix occasional warning from the timer work function
From: Marc Zyngier @ 2017-01-13 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484307093-29153-1-git-send-email-marc.zyngier@arm.com>

From: Christoffer Dall <christoffer.dall@linaro.org>

When a VCPU blocks (WFI) and has programmed the vtimer, we program a
soft timer to expire in the future to wake up the vcpu thread when
appropriate.  Because such as wake up involves a vcpu kick, and the
timer expire function can get called from interrupt context, and the
kick may sleep, we have to schedule the kick in the work function.

The work function currently has a warning that gets raised if it turns
out that the timer shouldn't fire when it's run, which was added because
the idea was that in that case the work should never have been cancelled.

However, it turns out that this whole thing is racy and we can get
spurious warnings.  The problem is that we clear the armed flag in the
work function, which may run in parallel with the
kvm_timer_unschedule->timer_disarm() call.  This results in a possible
situation where the timer_disarm() call does not call
cancel_work_sync(), which effectively synchronizes the completion of the
work function with running the VCPU.  As a result, the VCPU thread
proceeds before the work function completees, causing changes to the
timer state such that kvm_timer_should_fire(vcpu) returns false in the
work function.

All we do in the work function is to kick the VCPU, and an occasional
rare extra kick never harmed anyone.  Since the race above is extremely
rare, we don't bother checking if the race happens but simply remove the
check and the clearing of the armed flag from the work function.

Reported-by: Matthias Brugger <mbrugger@suse.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/arch_timer.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a2dbbcc..a7fe606 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -89,9 +89,6 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
 	struct kvm_vcpu *vcpu;
 
 	vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
-	vcpu->arch.timer_cpu.armed = false;
-
-	WARN_ON(!kvm_timer_should_fire(vcpu));
 
 	/*
 	 * If the vcpu is blocked we want to wake it up so that it will see
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/3] KVM: arm64: Access CNTHCTL_EL2 bit fields correctly on VHE systems
From: Marc Zyngier @ 2017-01-13 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484307093-29153-1-git-send-email-marc.zyngier@arm.com>

From: Jintack Lim <jintack@cs.columbia.edu>

Current KVM world switch code is unintentionally setting wrong bits to
CNTHCTL_EL2 when E2H == 1, which may allow guest OS to access physical
timer.  Bit positions of CNTHCTL_EL2 are changing depending on
HCR_EL2.E2H bit.  EL1PCEN and EL1PCTEN are 1st and 0th bits when E2H is
not set, but they are 11th and 10th bits respectively when E2H is set.

In fact, on VHE we only need to set those bits once, not for every world
switch. This is because the host kernel runs in EL2 with HCR_EL2.TGE ==
1, which makes those bits have no effect for the host kernel execution.
So we just set those bits once for guests, and that's it.

Signed-off-by: Jintack Lim <jintack@cs.columbia.edu>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/virt.h   |  5 +++++
 arch/arm/kvm/arm.c            |  3 +++
 arch/arm64/include/asm/virt.h |  9 +++++++++
 include/kvm/arm_arch_timer.h  |  1 +
 virt/kvm/arm/arch_timer.c     | 23 +++++++++++++++++++++++
 virt/kvm/arm/hyp/timer-sr.c   | 33 +++++++++++++++++++++------------
 6 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
index a2e75b8..6dae195 100644
--- a/arch/arm/include/asm/virt.h
+++ b/arch/arm/include/asm/virt.h
@@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void)
 	return false;
 }
 
+static inline bool has_vhe(void)
+{
+	return false;
+}
+
 /* The section containing the hypervisor idmap text */
 extern char __hyp_idmap_text_start[];
 extern char __hyp_idmap_text_end[];
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 1167678..9d74464 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy)
 	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
 	__cpu_init_stage2();
 
+	if (is_kernel_in_hyp_mode())
+		kvm_timer_init_vhe();
+
 	kvm_arm_init_debug();
 }
 
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index fea1073..439f6b5 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -47,6 +47,7 @@
 #include <asm/ptrace.h>
 #include <asm/sections.h>
 #include <asm/sysreg.h>
+#include <asm/cpufeature.h>
 
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
@@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void)
 	return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
+static inline bool has_vhe(void)
+{
+	if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
+		return true;
+
+	return false;
+}
+
 #ifdef CONFIG_ARM64_VHE
 extern void verify_cpu_run_el(void);
 #else
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b717ed9..5c970ce 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
 
 void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
 
+void kvm_timer_init_vhe(void);
 #endif
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a7fe606..6a084cd 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -24,6 +24,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_hyp.h>
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
@@ -509,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm)
 {
 	kvm->arch.timer.cntvoff = kvm_phys_timer_read();
 }
+
+/*
+ * On VHE system, we only need to configure trap on physical timer and counter
+ * accesses in EL0 and EL1 once, not for every world switch.
+ * The host kernel runs at EL2 with HCR_EL2.TGE == 1,
+ * and this makes those bits have no effect for the host kernel execution.
+ */
+void kvm_timer_init_vhe(void)
+{
+	/* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */
+	u32 cnthctl_shift = 10;
+	u64 val;
+
+	/*
+	 * Disallow physical timer access for the guest.
+	 * Physical counter access is allowed.
+	 */
+	val = read_sysreg(cnthctl_el2);
+	val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
+	val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
+	write_sysreg(val, cnthctl_el2);
+}
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index 798866a..63e28dd 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -35,10 +35,16 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
 	/* Disable the virtual timer */
 	write_sysreg_el0(0, cntv_ctl);
 
-	/* Allow physical timer/counter access for the host */
-	val = read_sysreg(cnthctl_el2);
-	val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
-	write_sysreg(val, cnthctl_el2);
+	/*
+	 * We don't need to do this for VHE since the host kernel runs in EL2
+	 * with HCR_EL2.TGE ==1, which makes those bits have no impact.
+	 */
+	if (!has_vhe()) {
+		/* Allow physical timer/counter access for the host */
+		val = read_sysreg(cnthctl_el2);
+		val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
+		write_sysreg(val, cnthctl_el2);
+	}
 
 	/* Clear cntvoff for the host */
 	write_sysreg(0, cntvoff_el2);
@@ -50,14 +56,17 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	u64 val;
 
-	/*
-	 * Disallow physical timer access for the guest
-	 * Physical counter access is allowed
-	 */
-	val = read_sysreg(cnthctl_el2);
-	val &= ~CNTHCTL_EL1PCEN;
-	val |= CNTHCTL_EL1PCTEN;
-	write_sysreg(val, cnthctl_el2);
+	/* Those bits are already configured at boot on VHE-system */
+	if (!has_vhe()) {
+		/*
+		 * Disallow physical timer access for the guest
+		 * Physical counter access is allowed
+		 */
+		val = read_sysreg(cnthctl_el2);
+		val &= ~CNTHCTL_EL1PCEN;
+		val |= CNTHCTL_EL1PCTEN;
+		write_sysreg(val, cnthctl_el2);
+	}
 
 	if (timer->enabled) {
 		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
-- 
2.1.4

^ permalink raw reply related

* [PATCH 3/3] KVM: arm/arm64: vgic: Fix deadlock on error handling
From: Marc Zyngier @ 2017-01-13 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484307093-29153-1-git-send-email-marc.zyngier@arm.com>

Dmitry Vyukov reported that the syzkaller fuzzer triggered a
deadlock in the vgic setup code when an error was detected, as
the cleanup code tries to take a lock that is already held by
the setup code.

The fix is to avoid retaking the lock when cleaning up, by
telling the cleanup function that we already hold it.

Cc: stable at vger.kernel.org
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-init.c | 18 +++++++++++++-----
 virt/kvm/arm/vgic/vgic-v2.c   |  2 --
 virt/kvm/arm/vgic/vgic-v3.c   |  2 --
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 5114391..c737ea0 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -268,15 +268,11 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
 
-	mutex_lock(&kvm->lock);
-
 	dist->ready = false;
 	dist->initialized = false;
 
 	kfree(dist->spis);
 	dist->nr_spis = 0;
-
-	mutex_unlock(&kvm->lock);
 }
 
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -286,7 +282,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
 	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
 }
 
-void kvm_vgic_destroy(struct kvm *kvm)
+/* To be called with kvm->lock held */
+static void __kvm_vgic_destroy(struct kvm *kvm)
 {
 	struct kvm_vcpu *vcpu;
 	int i;
@@ -297,6 +294,13 @@ void kvm_vgic_destroy(struct kvm *kvm)
 		kvm_vgic_vcpu_destroy(vcpu);
 }
 
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	mutex_lock(&kvm->lock);
+	__kvm_vgic_destroy(kvm);
+	mutex_unlock(&kvm->lock);
+}
+
 /**
  * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
  * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
@@ -348,6 +352,10 @@ int kvm_vgic_map_resources(struct kvm *kvm)
 		ret = vgic_v2_map_resources(kvm);
 	else
 		ret = vgic_v3_map_resources(kvm);
+
+	if (ret)
+		__kvm_vgic_destroy(kvm);
+
 out:
 	mutex_unlock(&kvm->lock);
 	return ret;
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 9bab867..834137e 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -293,8 +293,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
 	dist->ready = true;
 
 out:
-	if (ret)
-		kvm_vgic_destroy(kvm);
 	return ret;
 }
 
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 5c9f974..e6b03fd 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -302,8 +302,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
 	dist->ready = true;
 
 out:
-	if (ret)
-		kvm_vgic_destroy(kvm);
 	return ret;
 }
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH] iommu/dma: Add support for DMA_ATTR_FORCE_CONTIGUOUS
From: Robin Murphy @ 2017-01-13 11:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484305674-15018-1-git-send-email-geert+renesas@glider.be>

On 13/01/17 11:07, Geert Uytterhoeven wrote:
> Add support for DMA_ATTR_FORCE_CONTIGUOUS to the generic IOMMU DMA code.
> This allows to allocate physically contiguous DMA buffers on arm64
> systems with an IOMMU.

Can anyone explain what this attribute is actually used for? I've never
quite figured it out.

> Note that as this uses the CMA allocator, setting this attribute has a
> runtime-dependency on CONFIG_DMA_CMA, just like on arm32.
> 
> For arm64 systems using swiotlb, no changes are needed to support the
> allocation of physically contiguous DMA buffers:
>   - swiotlb always uses physically contiguous buffers (up to
>     IO_TLB_SEGSIZE = 128 pages),
>   - arm64's __dma_alloc_coherent() already calls
>     dma_alloc_from_contiguous() when CMA is available.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
>  arch/arm64/mm/dma-mapping.c |  4 ++--
>  drivers/iommu/dma-iommu.c   | 44 ++++++++++++++++++++++++++++++++++----------
>  include/linux/dma-iommu.h   |  2 +-
>  3 files changed, 37 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 1d7d5d2881db7c19..5fba14a21163e41f 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -589,7 +589,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
>  		addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot,
>  					      __builtin_return_address(0));
>  		if (!addr)
> -			iommu_dma_free(dev, pages, iosize, handle);
> +			iommu_dma_free(dev, pages, iosize, handle, attrs);
>  	} else {
>  		struct page *page;
>  		/*
> @@ -642,7 +642,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
>  
>  		if (WARN_ON(!area || !area->pages))
>  			return;
> -		iommu_dma_free(dev, area->pages, iosize, &handle);
> +		iommu_dma_free(dev, area->pages, iosize, &handle, attrs);
>  		dma_common_free_remap(cpu_addr, size, VM_USERMAP);
>  	} else {
>  		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 2db0d641cf4505b5..b991e8dcbbbb35c5 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -30,6 +30,7 @@
>  #include <linux/pci.h>
>  #include <linux/scatterlist.h>
>  #include <linux/vmalloc.h>
> +#include <linux/dma-contiguous.h>
>  
>  struct iommu_dma_msi_page {
>  	struct list_head	list;
> @@ -238,15 +239,21 @@ static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr)
>  	__free_iova(iovad, iova);
>  }
>  
> -static void __iommu_dma_free_pages(struct page **pages, int count)
> +static void __iommu_dma_free_pages(struct device *dev, struct page **pages,
> +				   int count, unsigned long attrs)
>  {
> -	while (count--)
> -		__free_page(pages[count]);
> +	if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
> +		dma_release_from_contiguous(dev, pages[0], count);
> +	} else {
> +		while (count--)
> +			__free_page(pages[count]);
> +	}
>  	kvfree(pages);
>  }
>  
> -static struct page **__iommu_dma_alloc_pages(unsigned int count,
> -		unsigned long order_mask, gfp_t gfp)
> +static struct page **__iommu_dma_alloc_pages(struct device *dev,
> +		unsigned int count, unsigned long order_mask, gfp_t gfp,
> +		unsigned long attrs)
>  {
>  	struct page **pages;
>  	unsigned int i = 0, array_size = count * sizeof(*pages);
> @@ -265,6 +272,20 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
>  	/* IOMMU can map any pages, so himem can also be used here */
>  	gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
>  
> +	if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
> +		int order = get_order(count << PAGE_SHIFT);
> +		struct page *page;
> +
> +		page = dma_alloc_from_contiguous(dev, count, order);
> +		if (!page)
> +			return NULL;
> +
> +		while (count--)
> +			pages[i++] = page++;
> +
> +		return pages;
> +	}
> +

This is really yuck. Plus it's entirely pointless to go through the
whole page array/scatterlist dance when we know the buffer is going to
be physically contiguous - it should just be allocate, map, done. I'd
much rather see standalone iommu_dma_{alloc,free}_contiguous()
functions, and let the arch code handle dispatching appropriately.

Robin.

>  	while (count) {
>  		struct page *page = NULL;
>  		unsigned int order_size;
> @@ -294,7 +315,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
>  			__free_pages(page, order);
>  		}
>  		if (!page) {
> -			__iommu_dma_free_pages(pages, i);
> +			__iommu_dma_free_pages(dev, pages, i, attrs);
>  			return NULL;
>  		}
>  		count -= order_size;
> @@ -310,15 +331,17 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
>   * @pages: Array of buffer pages as returned by iommu_dma_alloc()
>   * @size: Size of buffer in bytes
>   * @handle: DMA address of buffer
> + * @attrs: DMA attributes used for allocation of this buffer
>   *
>   * Frees both the pages associated with the buffer, and the array
>   * describing them
>   */
>  void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
> -		dma_addr_t *handle)
> +		dma_addr_t *handle, unsigned long attrs)
>  {
>  	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle);
> -	__iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
> +	__iommu_dma_free_pages(dev, pages, PAGE_ALIGN(size) >> PAGE_SHIFT,
> +			       attrs);
>  	*handle = DMA_ERROR_CODE;
>  }
>  
> @@ -365,7 +388,8 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
>  		alloc_sizes = min_size;
>  
>  	count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> -	pages = __iommu_dma_alloc_pages(count, alloc_sizes >> PAGE_SHIFT, gfp);
> +	pages = __iommu_dma_alloc_pages(dev, count, alloc_sizes >> PAGE_SHIFT,
> +					gfp, attrs);
>  	if (!pages)
>  		return NULL;
>  
> @@ -403,7 +427,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
>  out_free_iova:
>  	__free_iova(iovad, iova);
>  out_free_pages:
> -	__iommu_dma_free_pages(pages, count);
> +	__iommu_dma_free_pages(dev, pages, count, attrs);
>  	return NULL;
>  }
>  
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 7f7e9a7e3839966c..35fa6b7f9bac9b35 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -44,7 +44,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
>  		unsigned long attrs, int prot, dma_addr_t *handle,
>  		void (*flush_page)(struct device *, const void *, phys_addr_t));
>  void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
> -		dma_addr_t *handle);
> +		dma_addr_t *handle, unsigned long attrs);
>  
>  int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma);
>  
> 

^ permalink raw reply

* [PATCH] arm64: defconfig: disable CONFIG_DEVMEM
From: Leif Lindholm @ 2017-01-13 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

/dev/mem is the opposite of what an operating system is for.
Additionally, on arm* it opens up for denial-of-service attacks from
userspace. So leave it disabled by default, requiring people who need
it to enable it explicitly.

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 33b744d..55ba73a 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -210,6 +210,7 @@ CONFIG_INPUT_HISI_POWERKEY=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_DEVMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_EXTENDED=y
-- 
2.10.2

^ permalink raw reply related

* [PATCH] arm64: defconfig: disable CONFIG_DEVMEM
From: Ard Biesheuvel @ 2017-01-13 11:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113113734.16524-1-leif.lindholm@linaro.org>

On 13 January 2017 at 11:37, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> /dev/mem is the opposite of what an operating system is for.
> Additionally, on arm* it opens up for denial-of-service attacks from
> userspace. So leave it disabled by default, requiring people who need
> it to enable it explicitly.
>
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  arch/arm64/configs/defconfig | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 33b744d..55ba73a 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -210,6 +210,7 @@ CONFIG_INPUT_HISI_POWERKEY=y
>  # CONFIG_SERIO_SERPORT is not set
>  CONFIG_SERIO_AMBAKMI=y
>  CONFIG_LEGACY_PTY_COUNT=16
> +# CONFIG_DEVMEM is not set
>  CONFIG_SERIAL_8250=y
>  CONFIG_SERIAL_8250_CONSOLE=y
>  CONFIG_SERIAL_8250_EXTENDED=y
> --
> 2.10.2
>

^ permalink raw reply

* [PATCH v29 3/9] arm64: kdump: reserve memory for crash dump kernel
From: Mark Rutland @ 2017-01-13 11:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113081617.GI20972@linaro.org>

On Fri, Jan 13, 2017 at 05:16:18PM +0900, AKASHI Takahiro wrote:
> On Thu, Jan 12, 2017 at 03:09:26PM +0000, Mark Rutland wrote:
> > > +static int __init export_crashkernel(void)

> > > +	/* Add /chosen/linux,crashkernel-* properties */

> > > +	of_remove_property(node, of_find_property(node,
> > > +				"linux,crashkernel-base", NULL));
> > > +	of_remove_property(node, of_find_property(node,
> > > +				"linux,crashkernel-size", NULL));
> > > +
> > > +	ret = of_add_property(node, &crash_base_prop);
> > > +	if (ret)
> > > +		goto ret_err;
> > > +
> > > +	ret = of_add_property(node, &crash_size_prop);
> > > +	if (ret)
> > > +		goto ret_err;

> > I very much do not like this.
> > 
> > I don't think we should be modifying the DT exposed to userspace in this
> > manner, in the usual boot path, especially given that the kernel itself
> > does not appear to be a consumer of this property. I do not think that
> > it is right to use the DT exposed to userspace as a communication
> > channel solely between the kernel and userspace.
> 
> As you mentioned in your comments against my patch#9, this property
> originates from PPC implementation.
> I added it solely from the sympathy for dt-based architectures.
>
> > So I think we should drop the above, and for arm64 have userspace
> > consistently use /proc/iomem (or perhaps a new kexec-specific file) to
> > determine the region reserved for the crash kernel, if it needs to know
> > this.
> 
> As a matter of fact, my port of kexec-tools doesn't check this property
> and dropping it won't cause any problem.

Ok. It sounds like we're both happy for this to go, then.

While it's unfortunate that architectures differ, I think we have
legitimate reasons to differ, and it's preferable to do so. We have a
different set of constraints (e.g. supporting EFI memory maps), and
following the PPC approach creates longer term issues for us, making it
harder to do the right thing consistently.

> > > +/*
> > > + * reserve_crashkernel() - reserves memory for crash kernel
> > > + *
> > > + * This function reserves memory area given in "crashkernel=" kernel command
> > > + * line parameter. The memory reserved is used by dump capture kernel when
> > > + * primary kernel is crashing.
> > > + */
> > > +static void __init reserve_crashkernel(void)

> > > +	memblock_reserve(crash_base, crash_size);
> > 
> > This will mean that the crash kernel will have a permanent alias in the linear
> > map which is vulnerable to being clobbered. There could also be issues
> > with mismatched attributes in future.
> 
> Good point, I've never thought of that except making the memblock
> region "reserved."
> 
> > We're probably ok for now, but in future we'll likely want to fix this
> > up to remove the region (or mark it nomap), and only map it temporarily
> > when loading things into the region.
> 
> Well, I found that the following commit is already in:
>         commit 9b492cf58077
>         Author: Xunlei Pang <xlpang@redhat.com>
>         Date:   Mon May 23 16:24:10 2016 -0700
> 
>             kexec: introduce a protection mechanism for the crashkernel
>             reserved memory
> 
> To make best use of this framework, I'd like to re-use set_memory_ro/rx()
> instead of removing the region from linear mapping. But to do so,
> we need to
> * make memblock_isolate_range() global,
> * allow set_memory_ro/rx() to be applied to regions in linear mapping
> since set_memory_ro/rx() works only on page-level mappings.
> 
> What do you think?
> (See my tentative solution below.)

Great! I think it would be better to follow the approach of
mark_rodata_ro(), rather than opening up set_memory_*(), but otherwise,
it looks like it should work.

Either way, this still leaves us with an RO alias on crashed cores (and
potential cache attribute mismatches in future). Do we need to read from
the region later, or could we unmap it entirely?

Thanks,
Mark.

> ===8<===
> diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
> index c0fc3d458195..bb21c0473b8e 100644
> --- a/arch/arm64/kernel/machine_kexec.c
> +++ b/arch/arm64/kernel/machine_kexec.c
> @@ -211,6 +211,44 @@ void machine_kexec(struct kimage *kimage)
>  	BUG(); /* Should never get here. */
>  }
>  
> +static int kexec_mark_range(unsigned long start, unsigned long end,
> +							bool protect)
> +{
> +	unsigned int nr_pages;
> +
> +	if (!end || start >= end)
> +		return 0;
> +
> +	nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
> +
> +	if (protect)
> +		return set_memory_ro(__phys_to_virt(start), nr_pages);
> +	else
> +		return set_memory_rw(__phys_to_virt(start), nr_pages);
> +}
> +
> +static void kexec_mark_crashkres(bool protect)
> +{
> +	unsigned long control;
> +
> +	/* Don't touch the control code page used in crash_kexec().*/
> +	control = page_to_phys(kexec_crash_image->control_code_page);
> +	kexec_mark_range(crashk_res.start, control - 1, protect);
> +
> +	control += KEXEC_CONTROL_PAGE_SIZE;
> +	kexec_mark_range(control, crashk_res.end, protect);
> +}
> +
> +void arch_kexec_protect_crashkres(void)
> +{
> +	kexec_mark_crashkres(true);
> +}
> +
> +void arch_kexec_unprotect_crashkres(void)
> +{
> +	kexec_mark_crashkres(false);
> +}
> +
>  static void machine_kexec_mask_interrupts(void)
>  {
>  	unsigned int i;
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index 569ec3325bc8..764ec89c4f76 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -90,6 +90,7 @@ early_param("initrd", early_initrd);
>  static void __init reserve_crashkernel(void)
>  {
>  	unsigned long long crash_size, crash_base;
> +	int start_rgn, end_rgn;
>  	int ret;
>  
>  	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
> @@ -121,6 +122,9 @@ static void __init reserve_crashkernel(void)
>  		}
>  	}
>  	memblock_reserve(crash_base, crash_size);
> +	memblock_isolate_range(&memblock.memory, crash_base, crash_size,
> +			&start_rgn, &end_rgn);
> +
>  
>  	pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",
>  		crash_size >> 20, crash_base >> 20);
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 17243e43184e..0f60f19c287b 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -22,6 +22,7 @@
>  #include <linux/kernel.h>
>  #include <linux/errno.h>
>  #include <linux/init.h>
> +#include <linux/kexec.h>
>  #include <linux/libfdt.h>
>  #include <linux/mman.h>
>  #include <linux/nodemask.h>
> @@ -362,6 +363,17 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
>  	unsigned long kernel_start = __pa(_text);
>  	unsigned long kernel_end = __pa(__init_begin);
>  
> +#ifdef CONFIG_KEXEC_CORE
> +	if (crashk_res.end && start >= crashk_res.start &&
> +			end <= (crashk_res.end + 1)) {
> +		__create_pgd_mapping(pgd, start, __phys_to_virt(start),
> +				     end - start, PAGE_KERNEL,
> +				     early_pgtable_alloc,
> +				     true);
> +		return;
> +	}
> +#endif
> +
>  	/*
>  	 * Take care not to create a writable alias for the
>  	 * read-only text and rodata sections of the kernel image.
> ===>8===

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox