Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* arm64: Question about warnings due to unspecified ASM operand width
From: Ard Biesheuvel @ 2017-04-18 19:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170418192317.GC128305@google.com>

On 18 April 2017 at 20:23, Matthias Kaehlcke <mka@chromium.org> wrote:
> Hoi Ard,
>
> Thanks for your reply!
>
> El Tue, Apr 18, 2017 at 03:29:39PM +0100 Ard Biesheuvel ha dit:
>
>> On 18 April 2017 at 02:31, Matthias Kaehlcke <mka@chromium.org> wrote:
>> > Hi,
>> >
>> > During my work on improving support for kernel builds with clang I
>> > came across a bunch of warnings on arm64 builds about the width of
>> > operands in assembly not being specified:
>> >
>> > arch/arm64/include/asm/arch_timer.h:92:46: error: value size does
>> >       not match register size specified by the constraint and modifier [-Werror,-Wasm-operand-widths]
>> >         asm volatile("mrs %0,   cntfrq_el0" : "=r" (val));
>> >
>> > I understand that this is usually not a problem and might even be
>> > desired to give the compiler more flexiblity in the use of the
>> > available registers.
>> >
>> > My goal is to eventually build the kernel without warnings, not
>> > necessarily fixing all of them, warnings can also be disabled, e.g.
>> > in case of spurious warnings or a high number of occurrences that is
>> > too expensive to fix.
>> >
>> > Before delving into 'fixing' these 'asm-operand-widths' warnings I'd
>> > be interested to know if this is actually desirable or if it is
>> > preferred to keep the operand width unspecified in certain cases.
>> >
>>
>>
>> The root cause is that Clang infers the size of the register from the
>> size of the operand, while GCC always uses an xN register for a %
>> placeholder.
>>
>> With msr/mrs instructions, we can only use xN registers
>
> Good to know, thanks!
>
>> and so the only way to fix this is to ensure that we always use
>> 64-bit operands even for 32-bit system registers. This may be
>> possible in most cases, but assigning 32-bit struct fields becomes a
>> bit painful this way, and 'fixing' what is arguably not broken to
>> begin with may not be something Catalin is eager to accept.
>
> I'm not sure this would be an issue. Clang does not warn about 32-bit
> operands used with 64-bit registers, but about the register type not
> being specified at all. I think we should be fine with specifying xN
> registers for msr/mrs instructions.
>

It appears this was actually fixed in Clang. Formerly, it would
implicitly use %w for 32-bit operands, which breaks if the
instructions (such as msr/mrs, but there are more) don't support it.

Now it uses x registers for unqualified placeholders, and only issues a warning.

So we'd need to update all templates to use explicit qualifiers. I
don't think that should be a problem for anyone.

^ permalink raw reply

* [PATCH 0/7] regulator: arizona: Prepare for sharing with Madera codecs
From: Mark Brown @ 2017-04-18 19:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492512234-19210-1-git-send-email-rf@opensource.wolfsonmicro.com>

On Tue, Apr 18, 2017 at 11:43:46AM +0100, Richard Fitzgerald wrote:
> These patches make various changes to the Arizona regulators so that they
> can be re-used for the Cirrus Madera codecs:

This all looks good to me but needs review from Lee for the MFD overlap.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170418/497281d0/attachment.sig>

^ permalink raw reply

* [PATCH] arm64: dts: allwinner: a64: Add UART2 pin nodes
From: Andreas Färber @ 2017-04-18 19:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170418053458.phcbp4da3vatejpg@lukather>

Am 18.04.2017 um 07:34 schrieb Maxime Ripard:
> On Fri, Apr 14, 2017 at 07:13:20PM +0200, Andreas F?rber wrote:
>> UART2 is exposed on the Pi connector of Pine64. Make a pinctrl node
>> available at the SoC level, to simplify enabling UART2 via DT overlay.
>>
>> Signed-off-by: Andreas F?rber <afaerber@suse.de>
> 
> Applied, thanks!

Thanks, that was fast.

> Could you also create the node in the pine64 DTS (with an explicit
> status = "disabled" in there) so that the overlay would be even easier
> to make ?

Makes sense. I went ahead and did it for all UART nodes then - careful,
final patch is neither build- nor runtime-tested yet.

Cheers,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton
HRB 21284 (AG N?rnberg)

^ permalink raw reply

* [PATCH v3] arm64: dts: rk3399: add support for firefly-rk3399 board
From: Marc Zyngier @ 2017-04-18 19:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1491796213-4115-1-git-send-email-kever.yang@rock-chips.com>

On Mon, 10 Apr 2017 11:50:13 +0800
Kever Yang <kever.yang@rock-chips.com> wrote:

> Firefly-rk3399 is a bord from T-Firefly, you can find detail about
> it here:
> http://en.t-firefly.com/en/firenow/Firefly_RK3399/
> 
> This patch add basic node for the board and make it able to bring
> up.
> 
> Peripheral works:
> - usb hub which connect to ehci controller;
> - UART2 debug
> - eMMC
> - PCIe
> 
> Not work:
> - USB 3.0 HOST, type-C port
> - sdio, sd-card
> 
> Not test for other peripheral:

[...]

> - Ethernet

[...]

FWIW, I've tested the Ethernet port, which seems to work nicely.

Thanks,

	M.
-- 
Without deviation from the norm, progress is not possible.

^ permalink raw reply

* [PATCH] arm64: dts: allwinner: pine64: Prepare optional UART nodes with pinctrl
From: Andreas Färber @ 2017-04-18 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170418053458.phcbp4da3vatejpg@lukather>

Pine64 exposes all A64 UARTs, not just UART0.

Since the pins can be used as GPIO, don't enable the new UART nodes by
default, but prepare the pinctrl settings to aid in activating them via
overlays, i.e., overriding the status property of &uartX nodes.

For UART4 (Euler) the safer route of not including RTS/CTS pins is chosen,
whereas for UART1 (Bluetooth) they are included.

Add the corresponding pinctrl nodes where missing.

Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Andreas F?rber <afaerber@suse.de>
---
 .../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 29 ++++++++++++++++++++++
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi      | 15 +++++++++++
 2 files changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index db6c0f36999e..260fb12ac3fc 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -99,12 +99,41 @@
 	status = "okay";
 };
 
+/* On Exp and Euler connectors */
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
 	status = "okay";
 };
 
+/* On Wifi/BT connector, with RTS/CTS */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+	status = "disabled";
+};
+
+/* On Pi-2 connector */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	status = "disabled";
+};
+
+/* On Euler connector */
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	status = "disabled";
+};
+
+/* On Euler connector, RTS/CTS optional */
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins>;
+	status = "disabled";
+};
+
 &usb_otg {
 	dr_mode = "host";
 	status = "okay";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 133810df06b9..c172c62447e8 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -292,6 +292,21 @@
 				pins = "PB0", "PB1";
 				function = "uart2";
 			};
+
+			uart3_pins: uart3-pins {
+				pins = "PD0", "PD1";
+				function = "uart3";
+			};
+
+			uart4_pins: uart4-pins {
+				pins = "PD2", "PD3";
+				function = "uart4";
+			};
+
+			uart4_rts_cts_pins: uart4-rts-cts-pins {
+				pins = "PD4", "PD5";
+				function = "uart4";
+			};
 		};
 
 		uart0: serial at 1c28000 {
-- 
2.10.2

^ permalink raw reply related

* arm64: Question about warnings due to unspecified ASM operand width
From: Matthias Kaehlcke @ 2017-04-18 19:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-ThWK_OCO6A9+6wi3b52_UT5_Da3juO3N2f1PqrHDjFw@mail.gmail.com>

Hoi Ard,

Thanks for your reply!

El Tue, Apr 18, 2017 at 03:29:39PM +0100 Ard Biesheuvel ha dit:

> On 18 April 2017 at 02:31, Matthias Kaehlcke <mka@chromium.org> wrote:
> > Hi,
> >
> > During my work on improving support for kernel builds with clang I
> > came across a bunch of warnings on arm64 builds about the width of
> > operands in assembly not being specified:
> >
> > arch/arm64/include/asm/arch_timer.h:92:46: error: value size does
> >       not match register size specified by the constraint and modifier [-Werror,-Wasm-operand-widths]
> >         asm volatile("mrs %0,   cntfrq_el0" : "=r" (val));
> >
> > I understand that this is usually not a problem and might even be
> > desired to give the compiler more flexiblity in the use of the
> > available registers.
> >
> > My goal is to eventually build the kernel without warnings, not
> > necessarily fixing all of them, warnings can also be disabled, e.g.
> > in case of spurious warnings or a high number of occurrences that is
> > too expensive to fix.
> >
> > Before delving into 'fixing' these 'asm-operand-widths' warnings I'd
> > be interested to know if this is actually desirable or if it is
> > preferred to keep the operand width unspecified in certain cases.
> >
> 
>
> The root cause is that Clang infers the size of the register from the
> size of the operand, while GCC always uses an xN register for a %
> placeholder.
> 
> With msr/mrs instructions, we can only use xN registers

Good to know, thanks!

> and so the only way to fix this is to ensure that we always use
> 64-bit operands even for 32-bit system registers. This may be
> possible in most cases, but assigning 32-bit struct fields becomes a
> bit painful this way, and 'fixing' what is arguably not broken to
> begin with may not be something Catalin is eager to accept.

I'm not sure this would be an issue. Clang does not warn about 32-bit
operands used with 64-bit registers, but about the register type not
being specified at all. I think we should be fine with specifying xN
registers for msr/mrs instructions.

> Do you know if there is a rationale behind this disparity?

No, I don't know the rationale behind the register allocation for %
placeholders. I tend to see it as an 'implementation' detail as long
as it doesn't cause trouble.

Cheers

Matthias

^ permalink raw reply

* [PATCHv3 08/14] drivers/perf: arm_pmu: split cpu-local irq request/free
From: Geert Uytterhoeven @ 2017-04-18 18:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170418183316.GM17866@leverpostej>

Hi Mark,

On Tue, Apr 18, 2017 at 8:33 PM, Mark Rutland <mark.rutland@arm.com> wrote:
>> On Tue, Apr 11, 2017 at 10:39 AM, Mark Rutland <mark.rutland@arm.com> wrote:
>> > Currently we have functions to request/free all IRQs for a given PMU.
>> > While this works today, this won't work for ACPI, where we don't know
>> > the full set of IRQs up front, and need to request them separately.
>> >
>> > To enable supporting ACPI, this patch splits out the cpu-local
>> > request/free into new functions, allowing us to request/free individual
>> > IRQs.
>> >
>> > As this makes it possible/necessary to request a PPI once per cpu, an
>> > additional check is added to detect mismatched PPIs. This shouldn't
>> > matter for the DT / platform case, as we check this when parsing.
>> >
>> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
>> > Tested-by: Jeremy Linton <jeremy.linton@arm.com>
>> > Cc: Will Deacon <will.deacon@arm.com>
>>
>> This patch causes warnings during PSCI system suspend on R-Car Gen3.
>>
>> On R-Car M3-W (Dual CA57):
>>
>>     Disabling non-boot CPUs ...
>>    +IRQ15 no longer affine to CPU1
>>     CPU1: shutdown
>>     psci: CPU1 killed.
>>
>> On R-Car H3 (Quad CA57):
>>
>>     Disabling non-boot CPUs ...
>>    +IRQ15 no longer affine to CPU1
>>     CPU1: shutdown
>>     psci: CPU1 killed.
>>    +IRQ16 no longer affine to CPU2
>>     CPU2: shutdown
>>     psci: CPU2 killed.
>>    +IRQ17 no longer affine to CPU3
>>     CPU3: shutdown
>>     psci: CPU3 killed.
>>
>> Unfortunately it can't be reverted easily.
>>
>> Do you have any clue?
>
> Not presently. I'm somewhat surprised that this patch would have that
> effect -- I would imagine that the rework this is based on is more
> likely to. e.g. commit:
>
>   c09adab01e4aeecf ("drivers/perf: arm_pmu: split irq request from enable")

Bummer. You're right. It's actually due to that commit.

I searched in my gmail for a patch with the specific title, and blindly
replied to the first match, not noticing that was not the right patch.
Sorry for that.

> Just to check, you definitely don't see these warnings immediately prior
> to applying this patch?
>
> My best guess otherwise is that prior to this patch, the PMU IRQ
> request was failing earlier, and we bailed out.
>
> Can you dump a dmesg before and after this patch, and see if the arm_pmu
> driver dumps anything?

On R-Car Gen3, there's no change in PMU related messages.
Actual PMU messages are:

    hw perfevents: enabled with armv8_cortex_a57 PMU driver, 7
counters available
    hw perfevents: /soc/pmu_a53: failed to probe PMU!
    hw perfevents: /soc/pmu_a53: failed to register PMU devices!

The last two are due to the CA53 cores being described in DT, but not
enabled in the firmware.

On SH-Mobile AG5 (sh73a0/kzm9g), it recently (not due to the bad commit)
started printing:

   +hw perfevents: no interrupt-affinity property for /pmu, guessing.
    hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available

which looks related.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH] arm64: xen: Implement EFI reset_system callback
From: Juergen Gross @ 2017-04-18 18:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.10.1704181145420.31486@sstabellini-ThinkPad-X260>

On 18/04/17 20:46, Stefano Stabellini wrote:
> On Tue, 18 Apr 2017, Juergen Gross wrote:
>> On 18/04/17 20:37, Stefano Stabellini wrote:
>>> On Thu, 6 Apr 2017, Juergen Gross wrote:
>>>> On 06/04/17 18:43, Daniel Kiper wrote:
>>>>> On Thu, Apr 06, 2017 at 06:22:44PM +0200, Juergen Gross wrote:
>>>>>> On 06/04/17 18:06, Daniel Kiper wrote:
>>>>>>> Hi Julien,
>>>>>>>
>>>>>>> On Thu, Apr 06, 2017 at 04:39:13PM +0100, Julien Grall wrote:
>>>>>>>> Hi Daniel,
>>>>>>>>
>>>>>>>> On 06/04/17 16:20, Daniel Kiper wrote:
>>>>>>>>> On Thu, Apr 06, 2017 at 04:38:24PM +0200, Juergen Gross wrote:
>>>>>>>>>> On 06/04/17 16:27, Daniel Kiper wrote:
>>>>>>>>>>> On Thu, Apr 06, 2017 at 09:32:32AM +0100, Julien Grall wrote:
>>>>>>>>>>>> Hi Juergen,
>>>>>>>>>>>>
>>>>>>>>>>>> On 06/04/17 07:23, Juergen Gross wrote:
>>>>>>>>>>>>> On 05/04/17 21:49, Boris Ostrovsky wrote:
>>>>>>>>>>>>>> On 04/05/2017 02:14 PM, Julien Grall wrote:
>>>>>>>>>>>>>>> The x86 code has theoritically a similar issue, altought EFI does not
>>>>>>>>>>>>>>> seem to be the preferred method. I have left it unimplemented on x86 and
>>>>>>>>>>>>>>> CCed Linux Xen x86 maintainers to know their view here.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> (+Daniel)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This could be a problem for x86 as well, at least theoretically.
>>>>>>>>>>>>>> xen_machine_power_off() may call pm_power_off(), which is efi.reset_system.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> So I think we should have a similar routine there.
>>>>>>>>>>>>>
>>>>>>>>>>>>> +1
>>>>>>>>>>>>>
>>>>>>>>>>>>> I don't see any problem with such a routine added, in contrast to
>>>>>>>>>>>>> potential "reboots" instead of power off without it.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So I think this dummy xen_efi_reset_system() should be added to
>>>>>>>>>>>>> drivers/xen/efi.c instead.
>>>>>>>>>>>>
>>>>>>>>>>>> I will resend the patch during day with xen_efi_reset_system moved
>>>>>>>>>>>> to common code and implement the x86 counterpart (thought, I will
>>>>>>>>>>>> not be able to test it).
>>>>>>>>>>>
>>>>>>>>>>> I think that this is ARM specific issue. On x86 machine_restart() calls
>>>>>>>>>>> xen_restart(). Hence, everything works. So, I think that it should be
>>>>>>>>>>> fixed only for ARM. Anyway, please CC me when you send a patch.
>>>>>>>>>>
>>>>>>>>>> What about xen_machine_power_off() (as stated in Boris' mail)?
>>>>>>>>>
>>>>>>>>> Guys what do you think about that:
>>>>>>>>>
>>>>>>>>> --- a/drivers/firmware/efi/reboot.c
>>>>>>>>> +++ b/drivers/firmware/efi/reboot.c
>>>>>>>>> @@ -55,7 +55,7 @@ static void efi_power_off(void)
>>>>>>>>>
>>>>>>>>> static int __init efi_shutdown_init(void)
>>>>>>>>> {
>>>>>>>>> -       if (!efi_enabled(EFI_RUNTIME_SERVICES))
>>>>>>>>> +       if (!efi_enabled(EFI_RUNTIME_SERVICES) || efi_enabled(EFI_PARAVIRT))
>>>>>>>>>                return -ENODEV;
>>>>>>>>>
>>>>>>>>>        if (efi_poweroff_required())
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Julien, for ARM64 please take a look at arch/arm64/kernel/efi.c:efi_poweroff_required(void).
>>>>>>>>>
>>>>>>>>> I hope that tweaks for both files should solve our problem.
>>>>>>>>
>>>>>>>> This sounds good for power off (I haven't tried to power off DOM0
>>>>>>>> yet). But this will not solve the restart problem (see
>>>>>>>> machine_restart in arch/arm64/kernel/process.c) which call directly
>>>>>>>> efi_reboot.
>>>>>>>
>>>>>>> Hmmm... It seems to me that efi.reset_system override with empty function
>>>>>>> in arch/arm/xen/efi.c is the best solution. So, I see three patches here.
>>>>>>> One for drivers/firmware/efi/reboot.c, one for arch/arm/xen/efi.c and one
>>>>>>> for arch/arm64/kernel/efi.c. Does it make sense?
>>>>>>
>>>>>> I still think the empty function should be in drivers/xen/efi.c and we
>>>>>> should use it in arch/x86/xen/efi.c, too.
>>>>>
>>>>> If you wish we can go that way too. Though I thing that we should fix
>>>>> drivers/firmware/efi/reboot.c:efi_shutdown_init() too. Just in case.
>>>>
>>>> Sure, go ahead. I won't object.
>>>
>>> For the Xen on ARM side, the original patch that started this thread
>>> (20170405181417.15985-1-julien.grall at arm.com) is good to go, right?
>>>
>>
>> As I said: the dummy xen_efi_reset_system() should be in
>> drivers/xen/efi.c
> 
> OK. Who is working on it?

Didn't Julien say he would do it?


Juergen

^ permalink raw reply

* [PATCH 4/5] Hot-remove implementation for arm64
From: Ard Biesheuvel @ 2017-04-18 18:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170418182125.GL17866@leverpostej>

On 18 April 2017 at 19:21, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Apr 14, 2017 at 03:01:58PM +0100, Andrea Reale wrote:
>> I guess it is likely that I might have made assumptions that are true
>> for x86_64 but do not hold for arm64. Whenever you feel this is the
>> case, I would be really grateful if you could help identify them.
>
> Sure thing.
>
>> On Tue, Apr 11, 2017 at 06:12:11PM +0100, Mark Rutland wrote:
>> > On Tue, Apr 11, 2017 at 03:55:42PM +0100, Andrea Reale wrote:
>
>> > > +static void  free_pagetable(struct page *page, int order, bool direct)
>> >
>> > This "direct" parameter needs a better name, and a description in a
>> > comment block above this function.
>>
>> The name direct is inherited directly from the x86_64 hot remove code.
>> It serves to distinguish if we are removing either a pagetable page that
>> is mapping to the direct mapping space (I think it is called also linear
>> mapping area somewhere else) or a pagetable page or a data page
>> from vmemmap.
>
> FWIW, I've largely heard the folk call that the "linear mapping", and
> x86 folk call that the "direct mapping". The two are interchangeable.
>
>> In this specific set of functions, the flag is needed because the various
>> alloc_init_p*d used for allocating entries for direct memory mapping
>> rely on pgd_pgtable_alloc, which in its turn calls  pgtable_page_ctor;
>> hence, we need to call the dtor.
>
> AFAICT, that's not true for the arm64 linear map, since that's created
> with our early_pgtable_alloc(), which doesn't call pgtable_page_ctor().
>
> Judging by commit:
>
>   1378dc3d4ba07ccd ("arm64: mm: run pgtable_page_ctor() on non-swapper
>                      translation table pages")
>
> ... we only do this for non-swapper page tables.
>
>> On the contrary, vmemmap entries are created using vmemmap_alloc_block
>> (from within vmemmap_populate), which does not call pgtable_page_ctor
>> when allocating pages.
>>
>> I am not sure I understand why the pgtable_page_ctor is not called when
>> allocating vmemmap page tables, but that's the current situation.
>
> From a quick scan, I see that it's necessary to use pgtable_page_ctor()
> for pages that will be used for userspace page tables, but it's not
> clear to me if it's ever necessary for pages used for kernel page
> tables.
>
> If it is, we appear to have a bug on arm64.
>
> Laura, Ard, thoughts?
>

The generic apply_to_page_range() will expect the PTE lock to be
initialized for page table pages that are not part of init_mm. For
arm64, that is precisely efi_mm as far as I am aware. For EFI, the
locking is unnecessary but does no harm (the permissions are set once
via apply_to_page_range() at boot), so I added this call when adding
support for strict permissions in EFI rt services mappings.

So I think it is appropriate for create_pgd_mapping() to be in charge
of calling the ctor(). We simply have no destroy_pgd_mapping()
counterpart that would be the place for the dtor() call, given that we
never take down EFI rt services mappings.

Whether it makes sense or not to lock/unlock in apply_to_page_range()
is something I did not spend any brain cycles on at the time.

-- 
Ard.

^ permalink raw reply

* [PATCH] arm64: xen: Implement EFI reset_system callback
From: Stefano Stabellini @ 2017-04-18 18:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <fcc5ac4b-ed82-b5dd-a848-9ac9a3572853@suse.com>

On Tue, 18 Apr 2017, Juergen Gross wrote:
> On 18/04/17 20:37, Stefano Stabellini wrote:
> > On Thu, 6 Apr 2017, Juergen Gross wrote:
> >> On 06/04/17 18:43, Daniel Kiper wrote:
> >>> On Thu, Apr 06, 2017 at 06:22:44PM +0200, Juergen Gross wrote:
> >>>> On 06/04/17 18:06, Daniel Kiper wrote:
> >>>>> Hi Julien,
> >>>>>
> >>>>> On Thu, Apr 06, 2017 at 04:39:13PM +0100, Julien Grall wrote:
> >>>>>> Hi Daniel,
> >>>>>>
> >>>>>> On 06/04/17 16:20, Daniel Kiper wrote:
> >>>>>>> On Thu, Apr 06, 2017 at 04:38:24PM +0200, Juergen Gross wrote:
> >>>>>>>> On 06/04/17 16:27, Daniel Kiper wrote:
> >>>>>>>>> On Thu, Apr 06, 2017 at 09:32:32AM +0100, Julien Grall wrote:
> >>>>>>>>>> Hi Juergen,
> >>>>>>>>>>
> >>>>>>>>>> On 06/04/17 07:23, Juergen Gross wrote:
> >>>>>>>>>>> On 05/04/17 21:49, Boris Ostrovsky wrote:
> >>>>>>>>>>>> On 04/05/2017 02:14 PM, Julien Grall wrote:
> >>>>>>>>>>>>> The x86 code has theoritically a similar issue, altought EFI does not
> >>>>>>>>>>>>> seem to be the preferred method. I have left it unimplemented on x86 and
> >>>>>>>>>>>>> CCed Linux Xen x86 maintainers to know their view here.
> >>>>>>>>>>>>
> >>>>>>>>>>>> (+Daniel)
> >>>>>>>>>>>>
> >>>>>>>>>>>> This could be a problem for x86 as well, at least theoretically.
> >>>>>>>>>>>> xen_machine_power_off() may call pm_power_off(), which is efi.reset_system.
> >>>>>>>>>>>>
> >>>>>>>>>>>> So I think we should have a similar routine there.
> >>>>>>>>>>>
> >>>>>>>>>>> +1
> >>>>>>>>>>>
> >>>>>>>>>>> I don't see any problem with such a routine added, in contrast to
> >>>>>>>>>>> potential "reboots" instead of power off without it.
> >>>>>>>>>>>
> >>>>>>>>>>> So I think this dummy xen_efi_reset_system() should be added to
> >>>>>>>>>>> drivers/xen/efi.c instead.
> >>>>>>>>>>
> >>>>>>>>>> I will resend the patch during day with xen_efi_reset_system moved
> >>>>>>>>>> to common code and implement the x86 counterpart (thought, I will
> >>>>>>>>>> not be able to test it).
> >>>>>>>>>
> >>>>>>>>> I think that this is ARM specific issue. On x86 machine_restart() calls
> >>>>>>>>> xen_restart(). Hence, everything works. So, I think that it should be
> >>>>>>>>> fixed only for ARM. Anyway, please CC me when you send a patch.
> >>>>>>>>
> >>>>>>>> What about xen_machine_power_off() (as stated in Boris' mail)?
> >>>>>>>
> >>>>>>> Guys what do you think about that:
> >>>>>>>
> >>>>>>> --- a/drivers/firmware/efi/reboot.c
> >>>>>>> +++ b/drivers/firmware/efi/reboot.c
> >>>>>>> @@ -55,7 +55,7 @@ static void efi_power_off(void)
> >>>>>>>
> >>>>>>> static int __init efi_shutdown_init(void)
> >>>>>>> {
> >>>>>>> -       if (!efi_enabled(EFI_RUNTIME_SERVICES))
> >>>>>>> +       if (!efi_enabled(EFI_RUNTIME_SERVICES) || efi_enabled(EFI_PARAVIRT))
> >>>>>>>                return -ENODEV;
> >>>>>>>
> >>>>>>>        if (efi_poweroff_required())
> >>>>>>>
> >>>>>>>
> >>>>>>> Julien, for ARM64 please take a look at arch/arm64/kernel/efi.c:efi_poweroff_required(void).
> >>>>>>>
> >>>>>>> I hope that tweaks for both files should solve our problem.
> >>>>>>
> >>>>>> This sounds good for power off (I haven't tried to power off DOM0
> >>>>>> yet). But this will not solve the restart problem (see
> >>>>>> machine_restart in arch/arm64/kernel/process.c) which call directly
> >>>>>> efi_reboot.
> >>>>>
> >>>>> Hmmm... It seems to me that efi.reset_system override with empty function
> >>>>> in arch/arm/xen/efi.c is the best solution. So, I see three patches here.
> >>>>> One for drivers/firmware/efi/reboot.c, one for arch/arm/xen/efi.c and one
> >>>>> for arch/arm64/kernel/efi.c. Does it make sense?
> >>>>
> >>>> I still think the empty function should be in drivers/xen/efi.c and we
> >>>> should use it in arch/x86/xen/efi.c, too.
> >>>
> >>> If you wish we can go that way too. Though I thing that we should fix
> >>> drivers/firmware/efi/reboot.c:efi_shutdown_init() too. Just in case.
> >>
> >> Sure, go ahead. I won't object.
> > 
> > For the Xen on ARM side, the original patch that started this thread
> > (20170405181417.15985-1-julien.grall at arm.com) is good to go, right?
> > 
> 
> As I said: the dummy xen_efi_reset_system() should be in
> drivers/xen/efi.c

OK. Who is working on it?

^ permalink raw reply

* [PATCH] arm64: xen: Implement EFI reset_system callback
From: Juergen Gross @ 2017-04-18 18:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.10.1704181135580.31486@sstabellini-ThinkPad-X260>

On 18/04/17 20:37, Stefano Stabellini wrote:
> On Thu, 6 Apr 2017, Juergen Gross wrote:
>> On 06/04/17 18:43, Daniel Kiper wrote:
>>> On Thu, Apr 06, 2017 at 06:22:44PM +0200, Juergen Gross wrote:
>>>> On 06/04/17 18:06, Daniel Kiper wrote:
>>>>> Hi Julien,
>>>>>
>>>>> On Thu, Apr 06, 2017 at 04:39:13PM +0100, Julien Grall wrote:
>>>>>> Hi Daniel,
>>>>>>
>>>>>> On 06/04/17 16:20, Daniel Kiper wrote:
>>>>>>> On Thu, Apr 06, 2017 at 04:38:24PM +0200, Juergen Gross wrote:
>>>>>>>> On 06/04/17 16:27, Daniel Kiper wrote:
>>>>>>>>> On Thu, Apr 06, 2017 at 09:32:32AM +0100, Julien Grall wrote:
>>>>>>>>>> Hi Juergen,
>>>>>>>>>>
>>>>>>>>>> On 06/04/17 07:23, Juergen Gross wrote:
>>>>>>>>>>> On 05/04/17 21:49, Boris Ostrovsky wrote:
>>>>>>>>>>>> On 04/05/2017 02:14 PM, Julien Grall wrote:
>>>>>>>>>>>>> The x86 code has theoritically a similar issue, altought EFI does not
>>>>>>>>>>>>> seem to be the preferred method. I have left it unimplemented on x86 and
>>>>>>>>>>>>> CCed Linux Xen x86 maintainers to know their view here.
>>>>>>>>>>>>
>>>>>>>>>>>> (+Daniel)
>>>>>>>>>>>>
>>>>>>>>>>>> This could be a problem for x86 as well, at least theoretically.
>>>>>>>>>>>> xen_machine_power_off() may call pm_power_off(), which is efi.reset_system.
>>>>>>>>>>>>
>>>>>>>>>>>> So I think we should have a similar routine there.
>>>>>>>>>>>
>>>>>>>>>>> +1
>>>>>>>>>>>
>>>>>>>>>>> I don't see any problem with such a routine added, in contrast to
>>>>>>>>>>> potential "reboots" instead of power off without it.
>>>>>>>>>>>
>>>>>>>>>>> So I think this dummy xen_efi_reset_system() should be added to
>>>>>>>>>>> drivers/xen/efi.c instead.
>>>>>>>>>>
>>>>>>>>>> I will resend the patch during day with xen_efi_reset_system moved
>>>>>>>>>> to common code and implement the x86 counterpart (thought, I will
>>>>>>>>>> not be able to test it).
>>>>>>>>>
>>>>>>>>> I think that this is ARM specific issue. On x86 machine_restart() calls
>>>>>>>>> xen_restart(). Hence, everything works. So, I think that it should be
>>>>>>>>> fixed only for ARM. Anyway, please CC me when you send a patch.
>>>>>>>>
>>>>>>>> What about xen_machine_power_off() (as stated in Boris' mail)?
>>>>>>>
>>>>>>> Guys what do you think about that:
>>>>>>>
>>>>>>> --- a/drivers/firmware/efi/reboot.c
>>>>>>> +++ b/drivers/firmware/efi/reboot.c
>>>>>>> @@ -55,7 +55,7 @@ static void efi_power_off(void)
>>>>>>>
>>>>>>> static int __init efi_shutdown_init(void)
>>>>>>> {
>>>>>>> -       if (!efi_enabled(EFI_RUNTIME_SERVICES))
>>>>>>> +       if (!efi_enabled(EFI_RUNTIME_SERVICES) || efi_enabled(EFI_PARAVIRT))
>>>>>>>                return -ENODEV;
>>>>>>>
>>>>>>>        if (efi_poweroff_required())
>>>>>>>
>>>>>>>
>>>>>>> Julien, for ARM64 please take a look at arch/arm64/kernel/efi.c:efi_poweroff_required(void).
>>>>>>>
>>>>>>> I hope that tweaks for both files should solve our problem.
>>>>>>
>>>>>> This sounds good for power off (I haven't tried to power off DOM0
>>>>>> yet). But this will not solve the restart problem (see
>>>>>> machine_restart in arch/arm64/kernel/process.c) which call directly
>>>>>> efi_reboot.
>>>>>
>>>>> Hmmm... It seems to me that efi.reset_system override with empty function
>>>>> in arch/arm/xen/efi.c is the best solution. So, I see three patches here.
>>>>> One for drivers/firmware/efi/reboot.c, one for arch/arm/xen/efi.c and one
>>>>> for arch/arm64/kernel/efi.c. Does it make sense?
>>>>
>>>> I still think the empty function should be in drivers/xen/efi.c and we
>>>> should use it in arch/x86/xen/efi.c, too.
>>>
>>> If you wish we can go that way too. Though I thing that we should fix
>>> drivers/firmware/efi/reboot.c:efi_shutdown_init() too. Just in case.
>>
>> Sure, go ahead. I won't object.
> 
> For the Xen on ARM side, the original patch that started this thread
> (20170405181417.15985-1-julien.grall at arm.com) is good to go, right?
> 

As I said: the dummy xen_efi_reset_system() should be in
drivers/xen/efi.c


Juergen

^ permalink raw reply

* [PATCH] arm64: xen: Implement EFI reset_system callback
From: Stefano Stabellini @ 2017-04-18 18:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b6cd0d59-9569-2958-9cc7-c971139881f4@suse.com>

On Thu, 6 Apr 2017, Juergen Gross wrote:
> On 06/04/17 18:43, Daniel Kiper wrote:
> > On Thu, Apr 06, 2017 at 06:22:44PM +0200, Juergen Gross wrote:
> >> On 06/04/17 18:06, Daniel Kiper wrote:
> >>> Hi Julien,
> >>>
> >>> On Thu, Apr 06, 2017 at 04:39:13PM +0100, Julien Grall wrote:
> >>>> Hi Daniel,
> >>>>
> >>>> On 06/04/17 16:20, Daniel Kiper wrote:
> >>>>> On Thu, Apr 06, 2017 at 04:38:24PM +0200, Juergen Gross wrote:
> >>>>>> On 06/04/17 16:27, Daniel Kiper wrote:
> >>>>>>> On Thu, Apr 06, 2017 at 09:32:32AM +0100, Julien Grall wrote:
> >>>>>>>> Hi Juergen,
> >>>>>>>>
> >>>>>>>> On 06/04/17 07:23, Juergen Gross wrote:
> >>>>>>>>> On 05/04/17 21:49, Boris Ostrovsky wrote:
> >>>>>>>>>> On 04/05/2017 02:14 PM, Julien Grall wrote:
> >>>>>>>>>>> The x86 code has theoritically a similar issue, altought EFI does not
> >>>>>>>>>>> seem to be the preferred method. I have left it unimplemented on x86 and
> >>>>>>>>>>> CCed Linux Xen x86 maintainers to know their view here.
> >>>>>>>>>>
> >>>>>>>>>> (+Daniel)
> >>>>>>>>>>
> >>>>>>>>>> This could be a problem for x86 as well, at least theoretically.
> >>>>>>>>>> xen_machine_power_off() may call pm_power_off(), which is efi.reset_system.
> >>>>>>>>>>
> >>>>>>>>>> So I think we should have a similar routine there.
> >>>>>>>>>
> >>>>>>>>> +1
> >>>>>>>>>
> >>>>>>>>> I don't see any problem with such a routine added, in contrast to
> >>>>>>>>> potential "reboots" instead of power off without it.
> >>>>>>>>>
> >>>>>>>>> So I think this dummy xen_efi_reset_system() should be added to
> >>>>>>>>> drivers/xen/efi.c instead.
> >>>>>>>>
> >>>>>>>> I will resend the patch during day with xen_efi_reset_system moved
> >>>>>>>> to common code and implement the x86 counterpart (thought, I will
> >>>>>>>> not be able to test it).
> >>>>>>>
> >>>>>>> I think that this is ARM specific issue. On x86 machine_restart() calls
> >>>>>>> xen_restart(). Hence, everything works. So, I think that it should be
> >>>>>>> fixed only for ARM. Anyway, please CC me when you send a patch.
> >>>>>>
> >>>>>> What about xen_machine_power_off() (as stated in Boris' mail)?
> >>>>>
> >>>>> Guys what do you think about that:
> >>>>>
> >>>>> --- a/drivers/firmware/efi/reboot.c
> >>>>> +++ b/drivers/firmware/efi/reboot.c
> >>>>> @@ -55,7 +55,7 @@ static void efi_power_off(void)
> >>>>>
> >>>>> static int __init efi_shutdown_init(void)
> >>>>> {
> >>>>> -       if (!efi_enabled(EFI_RUNTIME_SERVICES))
> >>>>> +       if (!efi_enabled(EFI_RUNTIME_SERVICES) || efi_enabled(EFI_PARAVIRT))
> >>>>>                return -ENODEV;
> >>>>>
> >>>>>        if (efi_poweroff_required())
> >>>>>
> >>>>>
> >>>>> Julien, for ARM64 please take a look at arch/arm64/kernel/efi.c:efi_poweroff_required(void).
> >>>>>
> >>>>> I hope that tweaks for both files should solve our problem.
> >>>>
> >>>> This sounds good for power off (I haven't tried to power off DOM0
> >>>> yet). But this will not solve the restart problem (see
> >>>> machine_restart in arch/arm64/kernel/process.c) which call directly
> >>>> efi_reboot.
> >>>
> >>> Hmmm... It seems to me that efi.reset_system override with empty function
> >>> in arch/arm/xen/efi.c is the best solution. So, I see three patches here.
> >>> One for drivers/firmware/efi/reboot.c, one for arch/arm/xen/efi.c and one
> >>> for arch/arm64/kernel/efi.c. Does it make sense?
> >>
> >> I still think the empty function should be in drivers/xen/efi.c and we
> >> should use it in arch/x86/xen/efi.c, too.
> > 
> > If you wish we can go that way too. Though I thing that we should fix
> > drivers/firmware/efi/reboot.c:efi_shutdown_init() too. Just in case.
> 
> Sure, go ahead. I won't object.

For the Xen on ARM side, the original patch that started this thread
(20170405181417.15985-1-julien.grall at arm.com) is good to go, right?

^ permalink raw reply

* [PATCHv3 08/14] drivers/perf: arm_pmu: split cpu-local irq request/free
From: Mark Rutland @ 2017-04-18 18:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdVV4qMyYTYN92TE4fsrxo66WK-Gd001YbJZok2txOH4ig@mail.gmail.com>

On Tue, Apr 18, 2017 at 07:25:28PM +0200, Geert Uytterhoeven wrote:
> Hi Mark,

Hi Geert,

> On Tue, Apr 11, 2017 at 10:39 AM, Mark Rutland <mark.rutland@arm.com> wrote:
> > Currently we have functions to request/free all IRQs for a given PMU.
> > While this works today, this won't work for ACPI, where we don't know
> > the full set of IRQs up front, and need to request them separately.
> >
> > To enable supporting ACPI, this patch splits out the cpu-local
> > request/free into new functions, allowing us to request/free individual
> > IRQs.
> >
> > As this makes it possible/necessary to request a PPI once per cpu, an
> > additional check is added to detect mismatched PPIs. This shouldn't
> > matter for the DT / platform case, as we check this when parsing.
> >
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Tested-by: Jeremy Linton <jeremy.linton@arm.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> 
> This patch causes warnings during PSCI system suspend on R-Car Gen3.
> 
> On R-Car M3-W (Dual CA57):
> 
>     Disabling non-boot CPUs ...
>    +IRQ15 no longer affine to CPU1
>     CPU1: shutdown
>     psci: CPU1 killed.
> 
> On R-Car H3 (Quad CA57):
> 
>     Disabling non-boot CPUs ...
>    +IRQ15 no longer affine to CPU1
>     CPU1: shutdown
>     psci: CPU1 killed.
>    +IRQ16 no longer affine to CPU2
>     CPU2: shutdown
>     psci: CPU2 killed.
>    +IRQ17 no longer affine to CPU3
>     CPU3: shutdown
>     psci: CPU3 killed.
> 
> Unfortunately it can't be reverted easily.
> 
> Do you have any clue?

Not presently. I'm somewhat surprised that this patch would have that
effect -- I would imagine that the rework this is based on is more
likely to. e.g. commit:

  c09adab01e4aeecf ("drivers/perf: arm_pmu: split irq request from enable")

Just to check, you definitely don't see these warnings immediately prior
to applying this patch?

My best guess otherwise is that prior to this patch, the PMU IRQ
request was failing earlier, and we bailed out.

Can you dump a dmesg before and after this patch, and see if the arm_pmu
driver dumps anything?

Thanks,
Mark.

^ permalink raw reply

* [PATCHv4 12/12] staging/android: Update Ion TODO list
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Most of the items have been taken care of by a clean up series. Remove
the completed items and add a few new ones.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/TODO | 21 ++++-----------------
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO
index 8f3ac37..5f14247 100644
--- a/drivers/staging/android/TODO
+++ b/drivers/staging/android/TODO
@@ -7,23 +7,10 @@ TODO:
 
 
 ion/
- - Remove ION_IOC_SYNC: Flushing for devices should be purely a kernel internal
-   interface on top of dma-buf. flush_for_device needs to be added to dma-buf
-   first.
- - Remove ION_IOC_CUSTOM: Atm used for cache flushing for cpu access in some
-   vendor trees. Should be replaced with an ioctl on the dma-buf to expose the
-   begin/end_cpu_access hooks to userspace.
- - Clarify the tricks ion plays with explicitly managing coherency behind the
-   dma api's back (this is absolutely needed for high-perf gpu drivers): Add an
-   explicit coherency management mode to flush_for_device to be used by drivers
-   which want to manage caches themselves and which indicates whether cpu caches
-   need flushing.
- - With those removed there's probably no use for ION_IOC_IMPORT anymore either
-   since ion would just be the central allocator for shared buffers.
- - Add dt-binding to expose cma regions as ion heaps, with the rule that any
-   such cma regions must already be used by some device for dma. I.e. ion only
-   exposes existing cma regions and doesn't reserve unecessarily memory when
-   booting a system which doesn't use ion.
+ - Add dt-bindings for remaining heaps (chunk and carveout heaps). This would
+   involve putting appropriate bindings in a memory node for Ion to find.
+ - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0)
+ - Better test framework (integration with VGEM was suggested)
 
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
 Arve Hj?nnev?g <arve@android.com> and Riley Andrews <riandrews@android.com>
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 11/12] staging: android: ion: Set query return value
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

This never got set in the ioctl. Properly set a return value of 0 on
success.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/ion.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9eeb06f..d6fd350 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -498,6 +498,7 @@ int ion_query_heaps(struct ion_heap_query *query)
 	}
 
 	query->cnt = cnt;
+	ret = 0;
 out:
 	up_read(&dev->lock);
 	return ret;
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 10/12] staging: android: ion: Remove ion_handle and ion_client
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

ion_handle was introduced as an abstraction to represent a reference to
a buffer via an ion_client. As frameworks outside of Ion evolved, the dmabuf
emerged as the preferred standard for use in the kernel. This has made
the ion_handle an unnecessary abstraction and prone to race
conditions. ion_client is also now only used internally. We have enough
mechanisms for race conditions and leaks already so just drop ion_handle
and ion_client. This also includes ripping out most of the debugfs
infrastructure since much of that was tied to clients and handles.
The debugfs infrastructure was prone to give confusing data (orphaned
allocations) so it can be replaced with something better if people
actually want it.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/ion-ioctl.c |  53 +--
 drivers/staging/android/ion/ion.c       | 701 ++------------------------------
 drivers/staging/android/ion/ion.h       |  77 +---
 drivers/staging/android/uapi/ion.h      |  25 +-
 4 files changed, 51 insertions(+), 805 deletions(-)

diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c
index 4e7bf16..76427e4 100644
--- a/drivers/staging/android/ion/ion-ioctl.c
+++ b/drivers/staging/android/ion/ion-ioctl.c
@@ -21,9 +21,7 @@
 #include "ion.h"
 
 union ion_ioctl_arg {
-	struct ion_fd_data fd;
 	struct ion_allocation_data allocation;
-	struct ion_handle_data handle;
 	struct ion_heap_query query;
 };
 
@@ -48,8 +46,6 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg)
 static unsigned int ion_ioctl_dir(unsigned int cmd)
 {
 	switch (cmd) {
-	case ION_IOC_FREE:
-		return _IOC_WRITE;
 	default:
 		return _IOC_DIR(cmd);
 	}
@@ -57,8 +53,6 @@ static unsigned int ion_ioctl_dir(unsigned int cmd)
 
 long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct ion_client *client = filp->private_data;
-	struct ion_handle *cleanup_handle = NULL;
 	int ret = 0;
 	unsigned int dir;
 	union ion_ioctl_arg data;
@@ -86,61 +80,28 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	switch (cmd) {
 	case ION_IOC_ALLOC:
 	{
-		struct ion_handle *handle;
+		int fd;
 
-		handle = ion_alloc(client, data.allocation.len,
+		fd = ion_alloc(data.allocation.len,
 						data.allocation.heap_id_mask,
 						data.allocation.flags);
-		if (IS_ERR(handle))
-			return PTR_ERR(handle);
+		if (fd < 0)
+			return fd;
 
-		data.allocation.handle = handle->id;
+		data.allocation.fd = fd;
 
-		cleanup_handle = handle;
-		break;
-	}
-	case ION_IOC_FREE:
-	{
-		struct ion_handle *handle;
-
-		mutex_lock(&client->lock);
-		handle = ion_handle_get_by_id_nolock(client,
-						     data.handle.handle);
-		if (IS_ERR(handle)) {
-			mutex_unlock(&client->lock);
-			return PTR_ERR(handle);
-		}
-		ion_free_nolock(client, handle);
-		ion_handle_put_nolock(handle);
-		mutex_unlock(&client->lock);
-		break;
-	}
-	case ION_IOC_SHARE:
-	{
-		struct ion_handle *handle;
-
-		handle = ion_handle_get_by_id(client, data.handle.handle);
-		if (IS_ERR(handle))
-			return PTR_ERR(handle);
-		data.fd.fd = ion_share_dma_buf_fd(client, handle);
-		ion_handle_put(handle);
-		if (data.fd.fd < 0)
-			ret = data.fd.fd;
 		break;
 	}
 	case ION_IOC_HEAP_QUERY:
-		ret = ion_query_heaps(client, &data.query);
+		ret = ion_query_heaps(&data.query);
 		break;
 	default:
 		return -ENOTTY;
 	}
 
 	if (dir & _IOC_READ) {
-		if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) {
-			if (cleanup_handle)
-				ion_free(client, cleanup_handle);
+		if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd)))
 			return -EFAULT;
-		}
 	}
 	return ret;
 }
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 5a82bea..9eeb06f 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -90,7 +90,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
 
 	buffer->heap = heap;
 	buffer->flags = flags;
-	kref_init(&buffer->ref);
 
 	ret = heap->ops->allocate(heap, buffer, len, flags);
 
@@ -140,9 +139,8 @@ void ion_buffer_destroy(struct ion_buffer *buffer)
 	kfree(buffer);
 }
 
-static void _ion_buffer_destroy(struct kref *kref)
+static void _ion_buffer_destroy(struct ion_buffer *buffer)
 {
-	struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref);
 	struct ion_heap *heap = buffer->heap;
 	struct ion_device *dev = buffer->dev;
 
@@ -156,255 +154,6 @@ static void _ion_buffer_destroy(struct kref *kref)
 		ion_buffer_destroy(buffer);
 }
 
-static void ion_buffer_get(struct ion_buffer *buffer)
-{
-	kref_get(&buffer->ref);
-}
-
-static int ion_buffer_put(struct ion_buffer *buffer)
-{
-	return kref_put(&buffer->ref, _ion_buffer_destroy);
-}
-
-static void ion_buffer_add_to_handle(struct ion_buffer *buffer)
-{
-	mutex_lock(&buffer->lock);
-	buffer->handle_count++;
-	mutex_unlock(&buffer->lock);
-}
-
-static void ion_buffer_remove_from_handle(struct ion_buffer *buffer)
-{
-	/*
-	 * when a buffer is removed from a handle, if it is not in
-	 * any other handles, copy the taskcomm and the pid of the
-	 * process it's being removed from into the buffer.  At this
-	 * point there will be no way to track what processes this buffer is
-	 * being used by, it only exists as a dma_buf file descriptor.
-	 * The taskcomm and pid can provide a debug hint as to where this fd
-	 * is in the system
-	 */
-	mutex_lock(&buffer->lock);
-	buffer->handle_count--;
-	BUG_ON(buffer->handle_count < 0);
-	if (!buffer->handle_count) {
-		struct task_struct *task;
-
-		task = current->group_leader;
-		get_task_comm(buffer->task_comm, task);
-		buffer->pid = task_pid_nr(task);
-	}
-	mutex_unlock(&buffer->lock);
-}
-
-static struct ion_handle *ion_handle_create(struct ion_client *client,
-					    struct ion_buffer *buffer)
-{
-	struct ion_handle *handle;
-
-	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
-	if (!handle)
-		return ERR_PTR(-ENOMEM);
-	kref_init(&handle->ref);
-	RB_CLEAR_NODE(&handle->node);
-	handle->client = client;
-	ion_buffer_get(buffer);
-	ion_buffer_add_to_handle(buffer);
-	handle->buffer = buffer;
-
-	return handle;
-}
-
-static void ion_handle_kmap_put(struct ion_handle *);
-
-static void ion_handle_destroy(struct kref *kref)
-{
-	struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
-	struct ion_client *client = handle->client;
-	struct ion_buffer *buffer = handle->buffer;
-
-	mutex_lock(&buffer->lock);
-	while (handle->kmap_cnt)
-		ion_handle_kmap_put(handle);
-	mutex_unlock(&buffer->lock);
-
-	idr_remove(&client->idr, handle->id);
-	if (!RB_EMPTY_NODE(&handle->node))
-		rb_erase(&handle->node, &client->handles);
-
-	ion_buffer_remove_from_handle(buffer);
-	ion_buffer_put(buffer);
-
-	kfree(handle);
-}
-
-static void ion_handle_get(struct ion_handle *handle)
-{
-	kref_get(&handle->ref);
-}
-
-int ion_handle_put_nolock(struct ion_handle *handle)
-{
-	return kref_put(&handle->ref, ion_handle_destroy);
-}
-
-int ion_handle_put(struct ion_handle *handle)
-{
-	struct ion_client *client = handle->client;
-	int ret;
-
-	mutex_lock(&client->lock);
-	ret = ion_handle_put_nolock(handle);
-	mutex_unlock(&client->lock);
-
-	return ret;
-}
-
-struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
-					       int id)
-{
-	struct ion_handle *handle;
-
-	handle = idr_find(&client->idr, id);
-	if (handle)
-		ion_handle_get(handle);
-
-	return handle ? handle : ERR_PTR(-EINVAL);
-}
-
-struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
-					       int id)
-{
-	struct ion_handle *handle;
-
-	mutex_lock(&client->lock);
-	handle = ion_handle_get_by_id_nolock(client, id);
-	mutex_unlock(&client->lock);
-
-	return handle;
-}
-
-static bool ion_handle_validate(struct ion_client *client,
-				struct ion_handle *handle)
-{
-	WARN_ON(!mutex_is_locked(&client->lock));
-	return idr_find(&client->idr, handle->id) == handle;
-}
-
-static int ion_handle_add(struct ion_client *client, struct ion_handle *handle)
-{
-	int id;
-	struct rb_node **p = &client->handles.rb_node;
-	struct rb_node *parent = NULL;
-	struct ion_handle *entry;
-
-	id = idr_alloc(&client->idr, handle, 1, 0, GFP_KERNEL);
-	if (id < 0)
-		return id;
-
-	handle->id = id;
-
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct ion_handle, node);
-
-		if (handle->buffer < entry->buffer)
-			p = &(*p)->rb_left;
-		else if (handle->buffer > entry->buffer)
-			p = &(*p)->rb_right;
-		else
-			WARN(1, "%s: buffer already found.", __func__);
-	}
-
-	rb_link_node(&handle->node, parent, p);
-	rb_insert_color(&handle->node, &client->handles);
-
-	return 0;
-}
-
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
-			     unsigned int heap_id_mask,
-			     unsigned int flags)
-{
-	struct ion_handle *handle;
-	struct ion_device *dev = client->dev;
-	struct ion_buffer *buffer = NULL;
-	struct ion_heap *heap;
-	int ret;
-
-	pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__,
-		 len, heap_id_mask, flags);
-	/*
-	 * traverse the list of heaps available in this system in priority
-	 * order.  If the heap type is supported by the client, and matches the
-	 * request of the caller allocate from it.  Repeat until allocate has
-	 * succeeded or all heaps have been tried
-	 */
-	len = PAGE_ALIGN(len);
-
-	if (!len)
-		return ERR_PTR(-EINVAL);
-
-	down_read(&dev->lock);
-	plist_for_each_entry(heap, &dev->heaps, node) {
-		/* if the caller didn't specify this heap id */
-		if (!((1 << heap->id) & heap_id_mask))
-			continue;
-		buffer = ion_buffer_create(heap, dev, len, flags);
-		if (!IS_ERR(buffer))
-			break;
-	}
-	up_read(&dev->lock);
-
-	if (buffer == NULL)
-		return ERR_PTR(-ENODEV);
-
-	if (IS_ERR(buffer))
-		return ERR_CAST(buffer);
-
-	handle = ion_handle_create(client, buffer);
-
-	/*
-	 * ion_buffer_create will create a buffer with a ref_cnt of 1,
-	 * and ion_handle_create will take a second reference, drop one here
-	 */
-	ion_buffer_put(buffer);
-
-	if (IS_ERR(handle))
-		return handle;
-
-	mutex_lock(&client->lock);
-	ret = ion_handle_add(client, handle);
-	mutex_unlock(&client->lock);
-	if (ret) {
-		ion_handle_put(handle);
-		handle = ERR_PTR(ret);
-	}
-
-	return handle;
-}
-EXPORT_SYMBOL(ion_alloc);
-
-void ion_free_nolock(struct ion_client *client,
-		     struct ion_handle *handle)
-{
-	if (!ion_handle_validate(client, handle)) {
-		WARN(1, "%s: invalid handle passed to free.\n", __func__);
-		return;
-	}
-	ion_handle_put_nolock(handle);
-}
-
-void ion_free(struct ion_client *client, struct ion_handle *handle)
-{
-	BUG_ON(client != handle->client);
-
-	mutex_lock(&client->lock);
-	ion_free_nolock(client, handle);
-	mutex_unlock(&client->lock);
-}
-EXPORT_SYMBOL(ion_free);
-
 static void *ion_buffer_kmap_get(struct ion_buffer *buffer)
 {
 	void *vaddr;
@@ -433,234 +182,6 @@ static void ion_buffer_kmap_put(struct ion_buffer *buffer)
 	}
 }
 
-static void ion_handle_kmap_put(struct ion_handle *handle)
-{
-	struct ion_buffer *buffer = handle->buffer;
-
-	if (!handle->kmap_cnt) {
-		WARN(1, "%s: Double unmap detected! bailing...\n", __func__);
-		return;
-	}
-	handle->kmap_cnt--;
-	if (!handle->kmap_cnt)
-		ion_buffer_kmap_put(buffer);
-}
-
-static struct mutex debugfs_mutex;
-static struct rb_root *ion_root_client;
-static int is_client_alive(struct ion_client *client)
-{
-	struct rb_node *node;
-	struct ion_client *tmp;
-	struct ion_device *dev;
-
-	node = ion_root_client->rb_node;
-	dev = container_of(ion_root_client, struct ion_device, clients);
-
-	down_read(&dev->lock);
-	while (node) {
-		tmp = rb_entry(node, struct ion_client, node);
-		if (client < tmp) {
-			node = node->rb_left;
-		} else if (client > tmp) {
-			node = node->rb_right;
-		} else {
-			up_read(&dev->lock);
-			return 1;
-		}
-	}
-
-	up_read(&dev->lock);
-	return 0;
-}
-
-static int ion_debug_client_show(struct seq_file *s, void *unused)
-{
-	struct ion_client *client = s->private;
-	struct rb_node *n;
-	size_t sizes[ION_NUM_HEAP_IDS] = {0};
-	const char *names[ION_NUM_HEAP_IDS] = {NULL};
-	int i;
-
-	mutex_lock(&debugfs_mutex);
-	if (!is_client_alive(client)) {
-		seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n",
-			   client);
-		mutex_unlock(&debugfs_mutex);
-		return 0;
-	}
-
-	mutex_lock(&client->lock);
-	for (n = rb_first(&client->handles); n; n = rb_next(n)) {
-		struct ion_handle *handle = rb_entry(n, struct ion_handle,
-						     node);
-		unsigned int id = handle->buffer->heap->id;
-
-		if (!names[id])
-			names[id] = handle->buffer->heap->name;
-		sizes[id] += handle->buffer->size;
-	}
-	mutex_unlock(&client->lock);
-	mutex_unlock(&debugfs_mutex);
-
-	seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes");
-	for (i = 0; i < ION_NUM_HEAP_IDS; i++) {
-		if (!names[i])
-			continue;
-		seq_printf(s, "%16.16s: %16zu\n", names[i], sizes[i]);
-	}
-	return 0;
-}
-
-static int ion_debug_client_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ion_debug_client_show, inode->i_private);
-}
-
-static const struct file_operations debug_client_fops = {
-	.open = ion_debug_client_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int ion_get_client_serial(const struct rb_root *root,
-				 const unsigned char *name)
-{
-	int serial = -1;
-	struct rb_node *node;
-
-	for (node = rb_first(root); node; node = rb_next(node)) {
-		struct ion_client *client = rb_entry(node, struct ion_client,
-						     node);
-
-		if (strcmp(client->name, name))
-			continue;
-		serial = max(serial, client->display_serial);
-	}
-	return serial + 1;
-}
-
-struct ion_client *ion_client_create(struct ion_device *dev,
-				     const char *name)
-{
-	struct ion_client *client;
-	struct task_struct *task;
-	struct rb_node **p;
-	struct rb_node *parent = NULL;
-	struct ion_client *entry;
-	pid_t pid;
-
-	if (!name) {
-		pr_err("%s: Name cannot be null\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	get_task_struct(current->group_leader);
-	task_lock(current->group_leader);
-	pid = task_pid_nr(current->group_leader);
-	/*
-	 * don't bother to store task struct for kernel threads,
-	 * they can't be killed anyway
-	 */
-	if (current->group_leader->flags & PF_KTHREAD) {
-		put_task_struct(current->group_leader);
-		task = NULL;
-	} else {
-		task = current->group_leader;
-	}
-	task_unlock(current->group_leader);
-
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (!client)
-		goto err_put_task_struct;
-
-	client->dev = dev;
-	client->handles = RB_ROOT;
-	idr_init(&client->idr);
-	mutex_init(&client->lock);
-	client->task = task;
-	client->pid = pid;
-	client->name = kstrdup(name, GFP_KERNEL);
-	if (!client->name)
-		goto err_free_client;
-
-	down_write(&dev->lock);
-	client->display_serial = ion_get_client_serial(&dev->clients, name);
-	client->display_name = kasprintf(
-		GFP_KERNEL, "%s-%d", name, client->display_serial);
-	if (!client->display_name) {
-		up_write(&dev->lock);
-		goto err_free_client_name;
-	}
-	p = &dev->clients.rb_node;
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct ion_client, node);
-
-		if (client < entry)
-			p = &(*p)->rb_left;
-		else if (client > entry)
-			p = &(*p)->rb_right;
-	}
-	rb_link_node(&client->node, parent, p);
-	rb_insert_color(&client->node, &dev->clients);
-
-	client->debug_root = debugfs_create_file(client->display_name, 0664,
-						 dev->clients_debug_root,
-						 client, &debug_client_fops);
-	if (!client->debug_root) {
-		char buf[256], *path;
-
-		path = dentry_path(dev->clients_debug_root, buf, 256);
-		pr_err("Failed to create client debugfs at %s/%s\n",
-		       path, client->display_name);
-	}
-
-	up_write(&dev->lock);
-
-	return client;
-
-err_free_client_name:
-	kfree(client->name);
-err_free_client:
-	kfree(client);
-err_put_task_struct:
-	if (task)
-		put_task_struct(current->group_leader);
-	return ERR_PTR(-ENOMEM);
-}
-EXPORT_SYMBOL(ion_client_create);
-
-void ion_client_destroy(struct ion_client *client)
-{
-	struct ion_device *dev = client->dev;
-	struct rb_node *n;
-
-	pr_debug("%s: %d\n", __func__, __LINE__);
-	mutex_lock(&debugfs_mutex);
-	while ((n = rb_first(&client->handles))) {
-		struct ion_handle *handle = rb_entry(n, struct ion_handle,
-						     node);
-		ion_handle_destroy(&handle->ref);
-	}
-
-	idr_destroy(&client->idr);
-
-	down_write(&dev->lock);
-	if (client->task)
-		put_task_struct(client->task);
-	rb_erase(&client->node, &dev->clients);
-	debugfs_remove_recursive(client->debug_root);
-	up_write(&dev->lock);
-
-	kfree(client->display_name);
-	kfree(client->name);
-	kfree(client);
-	mutex_unlock(&debugfs_mutex);
-}
-EXPORT_SYMBOL(ion_client_destroy);
-
 static struct sg_table *dup_sg_table(struct sg_table *table)
 {
 	struct sg_table *new_table;
@@ -802,7 +323,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf)
 {
 	struct ion_buffer *buffer = dmabuf->priv;
 
-	ion_buffer_put(buffer);
+	_ion_buffer_destroy(buffer);
 }
 
 static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
@@ -881,24 +402,44 @@ static const struct dma_buf_ops dma_buf_ops = {
 	.kunmap = ion_dma_buf_kunmap,
 };
 
-struct dma_buf *ion_share_dma_buf(struct ion_client *client,
-				  struct ion_handle *handle)
+int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
 {
+	struct ion_device *dev = internal_dev;
+	struct ion_buffer *buffer = NULL;
+	struct ion_heap *heap;
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-	struct ion_buffer *buffer;
+	int fd;
 	struct dma_buf *dmabuf;
-	bool valid_handle;
 
-	mutex_lock(&client->lock);
-	valid_handle = ion_handle_validate(client, handle);
-	if (!valid_handle) {
-		WARN(1, "%s: invalid handle passed to share.\n", __func__);
-		mutex_unlock(&client->lock);
-		return ERR_PTR(-EINVAL);
+	pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__,
+		 len, heap_id_mask, flags);
+	/*
+	 * traverse the list of heaps available in this system in priority
+	 * order.  If the heap type is supported by the client, and matches the
+	 * request of the caller allocate from it.  Repeat until allocate has
+	 * succeeded or all heaps have been tried
+	 */
+	len = PAGE_ALIGN(len);
+
+	if (!len)
+		return -EINVAL;
+
+	down_read(&dev->lock);
+	plist_for_each_entry(heap, &dev->heaps, node) {
+		/* if the caller didn't specify this heap id */
+		if (!((1 << heap->id) & heap_id_mask))
+			continue;
+		buffer = ion_buffer_create(heap, dev, len, flags);
+		if (!IS_ERR(buffer))
+			break;
 	}
-	buffer = handle->buffer;
-	ion_buffer_get(buffer);
-	mutex_unlock(&client->lock);
+	up_read(&dev->lock);
+
+	if (buffer == NULL)
+		return -ENODEV;
+
+	if (IS_ERR(buffer))
+		return PTR_ERR(buffer);
 
 	exp_info.ops = &dma_buf_ops;
 	exp_info.size = buffer->size;
@@ -907,22 +448,9 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
 
 	dmabuf = dma_buf_export(&exp_info);
 	if (IS_ERR(dmabuf)) {
-		ion_buffer_put(buffer);
-		return dmabuf;
-	}
-
-	return dmabuf;
-}
-EXPORT_SYMBOL(ion_share_dma_buf);
-
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
-{
-	struct dma_buf *dmabuf;
-	int fd;
-
-	dmabuf = ion_share_dma_buf(client, handle);
-	if (IS_ERR(dmabuf))
+		_ion_buffer_destroy(buffer);
 		return PTR_ERR(dmabuf);
+	}
 
 	fd = dma_buf_fd(dmabuf, O_CLOEXEC);
 	if (fd < 0)
@@ -930,11 +458,10 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
 
 	return fd;
 }
-EXPORT_SYMBOL(ion_share_dma_buf_fd);
 
-int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query)
+int ion_query_heaps(struct ion_heap_query *query)
 {
-	struct ion_device *dev = client->dev;
+	struct ion_device *dev = internal_dev;
 	struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps);
 	int ret = -EINVAL, cnt = 0, max_cnt;
 	struct ion_heap *heap;
@@ -976,137 +503,14 @@ int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query)
 	return ret;
 }
 
-static int ion_release(struct inode *inode, struct file *file)
-{
-	struct ion_client *client = file->private_data;
-
-	pr_debug("%s: %d\n", __func__, __LINE__);
-	ion_client_destroy(client);
-	return 0;
-}
-
-static int ion_open(struct inode *inode, struct file *file)
-{
-	struct miscdevice *miscdev = file->private_data;
-	struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
-	struct ion_client *client;
-	char debug_name[64];
-
-	pr_debug("%s: %d\n", __func__, __LINE__);
-	snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
-	client = ion_client_create(dev, debug_name);
-	if (IS_ERR(client))
-		return PTR_ERR(client);
-	file->private_data = client;
-
-	return 0;
-}
-
 static const struct file_operations ion_fops = {
 	.owner          = THIS_MODULE,
-	.open           = ion_open,
-	.release        = ion_release,
 	.unlocked_ioctl = ion_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ion_ioctl,
 #endif
 };
 
-static size_t ion_debug_heap_total(struct ion_client *client,
-				   unsigned int id)
-{
-	size_t size = 0;
-	struct rb_node *n;
-
-	mutex_lock(&client->lock);
-	for (n = rb_first(&client->handles); n; n = rb_next(n)) {
-		struct ion_handle *handle = rb_entry(n,
-						     struct ion_handle,
-						     node);
-		if (handle->buffer->heap->id == id)
-			size += handle->buffer->size;
-	}
-	mutex_unlock(&client->lock);
-	return size;
-}
-
-static int ion_debug_heap_show(struct seq_file *s, void *unused)
-{
-	struct ion_heap *heap = s->private;
-	struct ion_device *dev = heap->dev;
-	struct rb_node *n;
-	size_t total_size = 0;
-	size_t total_orphaned_size = 0;
-
-	seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
-	seq_puts(s, "----------------------------------------------------\n");
-
-	mutex_lock(&debugfs_mutex);
-	for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
-		struct ion_client *client = rb_entry(n, struct ion_client,
-						     node);
-		size_t size = ion_debug_heap_total(client, heap->id);
-
-		if (!size)
-			continue;
-		if (client->task) {
-			char task_comm[TASK_COMM_LEN];
-
-			get_task_comm(task_comm, client->task);
-			seq_printf(s, "%16s %16u %16zu\n", task_comm,
-				   client->pid, size);
-		} else {
-			seq_printf(s, "%16s %16u %16zu\n", client->name,
-				   client->pid, size);
-		}
-	}
-	mutex_unlock(&debugfs_mutex);
-
-	seq_puts(s, "----------------------------------------------------\n");
-	seq_puts(s, "orphaned allocations (info is from last known client):\n");
-	mutex_lock(&dev->buffer_lock);
-	for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
-		struct ion_buffer *buffer = rb_entry(n, struct ion_buffer,
-						     node);
-		if (buffer->heap->id != heap->id)
-			continue;
-		total_size += buffer->size;
-		if (!buffer->handle_count) {
-			seq_printf(s, "%16s %16u %16zu %d %d\n",
-				   buffer->task_comm, buffer->pid,
-				   buffer->size, buffer->kmap_cnt,
-				   kref_read(&buffer->ref));
-			total_orphaned_size += buffer->size;
-		}
-	}
-	mutex_unlock(&dev->buffer_lock);
-	seq_puts(s, "----------------------------------------------------\n");
-	seq_printf(s, "%16s %16zu\n", "total orphaned",
-		   total_orphaned_size);
-	seq_printf(s, "%16s %16zu\n", "total ", total_size);
-	if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
-		seq_printf(s, "%16s %16zu\n", "deferred free",
-			   heap->free_list_size);
-	seq_puts(s, "----------------------------------------------------\n");
-
-	if (heap->debug_show)
-		heap->debug_show(heap, s, unused);
-
-	return 0;
-}
-
-static int ion_debug_heap_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ion_debug_heap_show, inode->i_private);
-}
-
-static const struct file_operations debug_heap_fops = {
-	.open = ion_debug_heap_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
 static int debug_shrink_set(void *data, u64 val)
 {
 	struct ion_heap *heap = data;
@@ -1169,29 +573,18 @@ void ion_device_add_heap(struct ion_heap *heap)
 	 */
 	plist_node_init(&heap->node, -heap->id);
 	plist_add(&heap->node, &dev->heaps);
-	debug_file = debugfs_create_file(heap->name, 0664,
-					 dev->heaps_debug_root, heap,
-					 &debug_heap_fops);
-
-	if (!debug_file) {
-		char buf[256], *path;
-
-		path = dentry_path(dev->heaps_debug_root, buf, 256);
-		pr_err("Failed to create heap debugfs at %s/%s\n",
-		       path, heap->name);
-	}
 
 	if (heap->shrinker.count_objects && heap->shrinker.scan_objects) {
 		char debug_name[64];
 
 		snprintf(debug_name, 64, "%s_shrink", heap->name);
 		debug_file = debugfs_create_file(
-			debug_name, 0644, dev->heaps_debug_root, heap,
+			debug_name, 0644, dev->debug_root, heap,
 			&debug_shrink_fops);
 		if (!debug_file) {
 			char buf[256], *path;
 
-			path = dentry_path(dev->heaps_debug_root, buf, 256);
+			path = dentry_path(dev->debug_root, buf, 256);
 			pr_err("Failed to create heap shrinker debugfs at %s/%s\n",
 			       path, debug_name);
 		}
@@ -1227,24 +620,12 @@ int ion_device_create(void)
 		pr_err("ion: failed to create debugfs root directory.\n");
 		goto debugfs_done;
 	}
-	idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root);
-	if (!idev->heaps_debug_root) {
-		pr_err("ion: failed to create debugfs heaps directory.\n");
-		goto debugfs_done;
-	}
-	idev->clients_debug_root = debugfs_create_dir("clients",
-						idev->debug_root);
-	if (!idev->clients_debug_root)
-		pr_err("ion: failed to create debugfs clients directory.\n");
 
 debugfs_done:
 	idev->buffers = RB_ROOT;
 	mutex_init(&idev->buffer_lock);
 	init_rwsem(&idev->lock);
 	plist_head_init(&idev->heaps);
-	idev->clients = RB_ROOT;
-	ion_root_client = &idev->clients;
-	mutex_init(&debugfs_mutex);
 	internal_dev = idev;
 	return 0;
 }
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index 36a1587..ace8416 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -78,7 +78,6 @@ struct ion_platform_heap {
  *			handle, used for debugging
  */
 struct ion_buffer {
-	struct kref ref;
 	union {
 		struct rb_node node;
 		struct list_head list;
@@ -109,8 +108,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer);
  * @buffers:		an rb tree of all the existing buffers
  * @buffer_lock:	lock protecting the tree of buffers
  * @lock:		rwsem protecting the tree of heaps and clients
- * @heaps:		list of all the heaps in the system
- * @user_clients:	list of all the clients created from userspace
  */
 struct ion_device {
 	struct miscdevice dev;
@@ -118,65 +115,11 @@ struct ion_device {
 	struct mutex buffer_lock;
 	struct rw_semaphore lock;
 	struct plist_head heaps;
-	struct rb_root clients;
 	struct dentry *debug_root;
-	struct dentry *heaps_debug_root;
-	struct dentry *clients_debug_root;
 	int heap_cnt;
 };
 
 /**
- * struct ion_client - a process/hw block local address space
- * @node:		node in the tree of all clients
- * @dev:		backpointer to ion device
- * @handles:		an rb tree of all the handles in this client
- * @idr:		an idr space for allocating handle ids
- * @lock:		lock protecting the tree of handles
- * @name:		used for debugging
- * @display_name:	used for debugging (unique version of @name)
- * @display_serial:	used for debugging (to make display_name unique)
- * @task:		used for debugging
- *
- * A client represents a list of buffers this client may access.
- * The mutex stored here is used to protect both handles tree
- * as well as the handles themselves, and should be held while modifying either.
- */
-struct ion_client {
-	struct rb_node node;
-	struct ion_device *dev;
-	struct rb_root handles;
-	struct idr idr;
-	struct mutex lock;
-	const char *name;
-	char *display_name;
-	int display_serial;
-	struct task_struct *task;
-	pid_t pid;
-	struct dentry *debug_root;
-};
-
-/**
- * ion_handle - a client local reference to a buffer
- * @ref:		reference count
- * @client:		back pointer to the client the buffer resides in
- * @buffer:		pointer to the buffer
- * @node:		node in the client's handle rbtree
- * @kmap_cnt:		count of times this client has mapped to kernel
- * @id:			client-unique id allocated by client->idr
- *
- * Modifications to node, map_cnt or mapping should be protected by the
- * lock in the client.  Other fields are never changed after initialization.
- */
-struct ion_handle {
-	struct kref ref;
-	struct ion_client *client;
-	struct ion_buffer *buffer;
-	struct rb_node node;
-	unsigned int kmap_cnt;
-	int id;
-};
-
-/**
  * struct ion_heap_ops - ops to operate on a given heap
  * @allocate:		allocate memory
  * @free:		free memory
@@ -296,14 +239,10 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
 int ion_heap_buffer_zero(struct ion_buffer *buffer);
 int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
 
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
+int ion_alloc(size_t len,
 				unsigned int heap_id_mask,
 				unsigned int flags);
 
-void ion_free(struct ion_client *client, struct ion_handle *handle);
-
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
-
 /**
  * ion_heap_init_shrinker
  * @heap:		the heap
@@ -431,18 +370,6 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
 
 long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
-struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
-						int id);
-
-void ion_free_nolock(struct ion_client *client, struct ion_handle *handle);
-
-int ion_handle_put_nolock(struct ion_handle *handle);
-
-struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
-						int id);
-
-int ion_handle_put(struct ion_handle *handle);
-
-int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
+int ion_query_heaps(struct ion_heap_query *query);
 
 #endif /* _ION_H */
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index bba1c47..b76db1b 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -85,31 +85,8 @@ struct ion_allocation_data {
 	__u64 len;
 	__u32 heap_id_mask;
 	__u32 flags;
-	__u32 handle;
-	__u32 unused;
-};
-
-/**
- * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair
- * @handle:	a handle
- * @fd:		a file descriptor representing that handle
- *
- * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with
- * the handle returned from ion alloc, and the kernel returns the file
- * descriptor to share or map in the fd field.  For ION_IOC_IMPORT, userspace
- * provides the file descriptor and the kernel returns the handle.
- */
-struct ion_fd_data {
-	__u32 handle;
 	__u32 fd;
-};
-
-/**
- * struct ion_handle_data - a handle passed to/from the kernel
- * @handle:	a handle
- */
-struct ion_handle_data {
-	__u32 handle;
+	__u32 unused;
 };
 
 #define MAX_HEAP_NAME			32
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 09/12] staging: android: ion: Drop ion_map_kernel interface
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Nobody uses this interface externally. Drop it.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/ion.c | 59 ---------------------------------------
 1 file changed, 59 deletions(-)

diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 7d40233..5a82bea 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -424,22 +424,6 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer)
 	return vaddr;
 }
 
-static void *ion_handle_kmap_get(struct ion_handle *handle)
-{
-	struct ion_buffer *buffer = handle->buffer;
-	void *vaddr;
-
-	if (handle->kmap_cnt) {
-		handle->kmap_cnt++;
-		return buffer->vaddr;
-	}
-	vaddr = ion_buffer_kmap_get(buffer);
-	if (IS_ERR(vaddr))
-		return vaddr;
-	handle->kmap_cnt++;
-	return vaddr;
-}
-
 static void ion_buffer_kmap_put(struct ion_buffer *buffer)
 {
 	buffer->kmap_cnt--;
@@ -462,49 +446,6 @@ static void ion_handle_kmap_put(struct ion_handle *handle)
 		ion_buffer_kmap_put(buffer);
 }
 
-void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
-{
-	struct ion_buffer *buffer;
-	void *vaddr;
-
-	mutex_lock(&client->lock);
-	if (!ion_handle_validate(client, handle)) {
-		pr_err("%s: invalid handle passed to map_kernel.\n",
-		       __func__);
-		mutex_unlock(&client->lock);
-		return ERR_PTR(-EINVAL);
-	}
-
-	buffer = handle->buffer;
-
-	if (!handle->buffer->heap->ops->map_kernel) {
-		pr_err("%s: map_kernel is not implemented by this heap.\n",
-		       __func__);
-		mutex_unlock(&client->lock);
-		return ERR_PTR(-ENODEV);
-	}
-
-	mutex_lock(&buffer->lock);
-	vaddr = ion_handle_kmap_get(handle);
-	mutex_unlock(&buffer->lock);
-	mutex_unlock(&client->lock);
-	return vaddr;
-}
-EXPORT_SYMBOL(ion_map_kernel);
-
-void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
-{
-	struct ion_buffer *buffer;
-
-	mutex_lock(&client->lock);
-	buffer = handle->buffer;
-	mutex_lock(&buffer->lock);
-	ion_handle_kmap_put(handle);
-	mutex_unlock(&buffer->lock);
-	mutex_unlock(&client->lock);
-}
-EXPORT_SYMBOL(ion_unmap_kernel);
-
 static struct mutex debugfs_mutex;
 static struct rb_root *ion_root_client;
 static int is_client_alive(struct ion_client *client)
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 08/12] staging: android: ion: Rework heap registration/enumeration
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

The current model of Ion heap registration  is based on the outdated
model of board files. The replacement for board files (devicetree)
isn't a good replacement for what Ion wants to do. In actuality, Ion
wants to show what memory is available in the system for something else
to figure out what to use. Switch to a model where Ion creates its
device unconditionally and heaps are registed as available regions.
Currently, only system and CMA heaps are converted over to the new
model. Carveout and chunk heaps can be converted over when someone wants
to figure out how.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/Kconfig             | 25 +++++++++
 drivers/staging/android/ion/Makefile            |  7 +--
 drivers/staging/android/ion/ion.c               | 28 +++++-----
 drivers/staging/android/ion/ion.h               | 40 +-------------
 drivers/staging/android/ion/ion_carveout_heap.c | 10 ----
 drivers/staging/android/ion/ion_chunk_heap.c    |  9 ----
 drivers/staging/android/ion/ion_cma_heap.c      | 24 +++++++--
 drivers/staging/android/ion/ion_heap.c          | 71 -------------------------
 drivers/staging/android/ion/ion_system_heap.c   | 38 ++++++++-----
 9 files changed, 85 insertions(+), 167 deletions(-)

diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 15108c4..a517b2d 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -10,6 +10,31 @@ menuconfig ION
 	  If you're not using Android its probably safe to
 	  say N here.
 
+config ION_SYSTEM_HEAP
+	bool "Ion system heap"
+	depends on ION
+	help
+	  Choose this option to enable the Ion system heap. The system heap
+	  is backed by pages from the buddy allocator. If in doubt, say Y.
+
+config ION_CARVEOUT_HEAP
+	bool "Ion carveout heap support"
+	depends on ION
+	help
+	  Choose this option to enable carveout heaps with Ion. Carveout heaps
+	  are backed by memory reserved from the system. Allocation times are
+	  typically faster at the cost of memory not being used. Unless you
+	  know your system has these regions, you should say N here.
+
+config ION_CHUNK_HEAP
+	bool "Ion chunk heap support"
+	depends on ION
+	help
+          Choose this option to enable chunk heaps with Ion. This heap is
+	  similar in function the carveout heap but memory is broken down
+	  into smaller chunk sizes, typically corresponding to a TLB size.
+	  Unless you know your system has these regions, you should say N here.
+
 config ION_CMA_HEAP
 	bool "Ion CMA heap support"
 	depends on ION && CMA
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index a892afa..eb7eeed 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -1,4 +1,5 @@
-obj-$(CONFIG_ION) +=	ion.o ion-ioctl.o ion_heap.o \
-			ion_page_pool.o ion_system_heap.o \
-			ion_carveout_heap.o ion_chunk_heap.o
+obj-$(CONFIG_ION) +=	ion.o ion-ioctl.o ion_heap.o
+obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o
+obj-$(CONFIG_ION_CARVEOUT_HEAP) += ion_carveout_heap.o
+obj-$(CONFIG_ION_CHUNK_HEAP) += ion_chunk_heap.o
 obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index e1fb865..7d40233 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -40,6 +40,9 @@
 
 #include "ion.h"
 
+static struct ion_device *internal_dev;
+static int heap_id = 0;
+
 bool ion_buffer_cached(struct ion_buffer *buffer)
 {
 	return !!(buffer->flags & ION_FLAG_CACHED);
@@ -1198,9 +1201,10 @@ static int debug_shrink_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get,
 			debug_shrink_set, "%llu\n");
 
-void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
+void ion_device_add_heap(struct ion_heap *heap)
 {
 	struct dentry *debug_file;
+	struct ion_device *dev = internal_dev;
 
 	if (!heap->ops->allocate || !heap->ops->free)
 		pr_err("%s: can not add heap with invalid ops struct.\n",
@@ -1217,6 +1221,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
 
 	heap->dev = dev;
 	down_write(&dev->lock);
+	heap->id = heap_id++;
 	/*
 	 * use negative heap->id to reverse the priority -- when traversing
 	 * the list later attempt higher id numbers first
@@ -1256,14 +1261,14 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
 }
 EXPORT_SYMBOL(ion_device_add_heap);
 
-struct ion_device *ion_device_create(void)
+int ion_device_create(void)
 {
 	struct ion_device *idev;
 	int ret;
 
 	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
 	if (!idev)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	idev->dev.minor = MISC_DYNAMIC_MINOR;
 	idev->dev.name = "ion";
@@ -1273,7 +1278,7 @@ struct ion_device *ion_device_create(void)
 	if (ret) {
 		pr_err("ion: failed to register misc device.\n");
 		kfree(idev);
-		return ERR_PTR(ret);
+		return ret;
 	}
 
 	idev->debug_root = debugfs_create_dir("ion", NULL);
@@ -1292,7 +1297,6 @@ struct ion_device *ion_device_create(void)
 		pr_err("ion: failed to create debugfs clients directory.\n");
 
 debugfs_done:
-
 	idev->buffers = RB_ROOT;
 	mutex_init(&idev->buffer_lock);
 	init_rwsem(&idev->lock);
@@ -1300,15 +1304,7 @@ struct ion_device *ion_device_create(void)
 	idev->clients = RB_ROOT;
 	ion_root_client = &idev->clients;
 	mutex_init(&debugfs_mutex);
-	return idev;
-}
-EXPORT_SYMBOL(ion_device_create);
-
-void ion_device_destroy(struct ion_device *dev)
-{
-	misc_deregister(&dev->dev);
-	debugfs_remove_recursive(dev->debug_root);
-	/* XXX need to free the heaps and clients ? */
-	kfree(dev);
+	internal_dev = idev;
+	return 0;
 }
-EXPORT_SYMBOL(ion_device_destroy);
+subsys_initcall(ion_device_create);
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index fd49403..36a1587 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -280,24 +280,10 @@ bool ion_buffer_cached(struct ion_buffer *buffer);
 bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
 
 /**
- * ion_device_create - allocates and returns an ion device
- *
- * returns a valid device or -PTR_ERR
- */
-struct ion_device *ion_device_create(void);
-
-/**
- * ion_device_destroy - free and device and it's resource
- * @dev:		the device
- */
-void ion_device_destroy(struct ion_device *dev);
-
-/**
  * ion_device_add_heap - adds a heap to the ion device
- * @dev:		the device
  * @heap:		the heap to add
  */
-void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap);
+void ion_device_add_heap(struct ion_heap *heap);
 
 /**
  * some helpers for common operations on buffers using the sg_table
@@ -390,30 +376,6 @@ size_t ion_heap_freelist_size(struct ion_heap *heap);
 
 
 /**
- * functions for creating and destroying the built in ion heaps.
- * architectures can add their own custom architecture specific
- * heaps as appropriate.
- */
-
-
-struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data);
-void ion_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused);
-void ion_system_heap_destroy(struct ion_heap *heap);
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap);
-void ion_system_contig_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data);
-void ion_carveout_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data);
-void ion_chunk_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data);
-void ion_cma_heap_destroy(struct ion_heap *heap);
-
-/**
  * functions for creating and destroying a heap pool -- allows you
  * to keep a pool of pre allocated memory to use from your heap.  Keeping
  * a pool of memory that is ready for dma, ie any cached mapping have been
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index 7287279..5fdc1f3 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -145,13 +145,3 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
 
 	return &carveout_heap->heap;
 }
-
-void ion_carveout_heap_destroy(struct ion_heap *heap)
-{
-	struct ion_carveout_heap *carveout_heap =
-	     container_of(heap, struct  ion_carveout_heap, heap);
-
-	gen_pool_destroy(carveout_heap->pool);
-	kfree(carveout_heap);
-	carveout_heap = NULL;
-}
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 9210bfe..9c257c7 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -160,12 +160,3 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
 	return ERR_PTR(ret);
 }
 
-void ion_chunk_heap_destroy(struct ion_heap *heap)
-{
-	struct ion_chunk_heap *chunk_heap =
-	     container_of(heap, struct  ion_chunk_heap, heap);
-
-	gen_pool_destroy(chunk_heap->pool);
-	kfree(chunk_heap);
-	chunk_heap = NULL;
-}
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index e67e78d..dc2a913 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -87,7 +87,7 @@ static struct ion_heap_ops ion_cma_ops = {
 	.unmap_kernel = ion_heap_unmap_kernel,
 };
 
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
+static struct ion_heap *__ion_cma_heap_create(struct cma *cma)
 {
 	struct ion_cma_heap *cma_heap;
 
@@ -101,14 +101,28 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
 	 * get device from private heaps data, later it will be
 	 * used to make the link with reserved CMA memory
 	 */
-	cma_heap->cma = data->priv;
+	cma_heap->cma = cma;
 	cma_heap->heap.type = ION_HEAP_TYPE_DMA;
 	return &cma_heap->heap;
 }
 
-void ion_cma_heap_destroy(struct ion_heap *heap)
+int __ion_add_cma_heaps(struct cma *cma, void *data)
 {
-	struct ion_cma_heap *cma_heap = to_cma_heap(heap);
+        struct ion_heap *heap;
+
+	heap = __ion_cma_heap_create(cma);
+	if (IS_ERR(heap))
+		return PTR_ERR(heap);
 
-	kfree(cma_heap);
+	heap->name = cma_get_name(cma);
+
+        ion_device_add_heap(heap);
+        return 0;
+}
+
+static int ion_add_cma_heaps(void)
+{
+	cma_for_each_area(__ion_add_cma_heaps, NULL);
+	return 0;
 }
+device_initcall(ion_add_cma_heaps);
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index d8d057c..91faa7f 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -314,74 +314,3 @@ void ion_heap_init_shrinker(struct ion_heap *heap)
 	heap->shrinker.batch = 0;
 	register_shrinker(&heap->shrinker);
 }
-
-struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
-{
-	struct ion_heap *heap = NULL;
-
-	switch (heap_data->type) {
-	case ION_HEAP_TYPE_SYSTEM_CONTIG:
-		heap = ion_system_contig_heap_create(heap_data);
-		break;
-	case ION_HEAP_TYPE_SYSTEM:
-		heap = ion_system_heap_create(heap_data);
-		break;
-	case ION_HEAP_TYPE_CARVEOUT:
-		heap = ion_carveout_heap_create(heap_data);
-		break;
-	case ION_HEAP_TYPE_CHUNK:
-		heap = ion_chunk_heap_create(heap_data);
-		break;
-#ifdef CONFIG_ION_CMA_HEAP
-	case ION_HEAP_TYPE_DMA:
-		heap = ion_cma_heap_create(heap_data);
-		break;
-#endif
-	default:
-		pr_err("%s: Invalid heap type %d\n", __func__,
-		       heap_data->type);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (IS_ERR_OR_NULL(heap)) {
-		pr_err("%s: error creating heap %s type %d base %pa size %zu\n",
-		       __func__, heap_data->name, heap_data->type,
-		       &heap_data->base, heap_data->size);
-		return ERR_PTR(-EINVAL);
-	}
-
-	heap->name = heap_data->name;
-	heap->id = heap_data->id;
-	return heap;
-}
-EXPORT_SYMBOL(ion_heap_create);
-
-void ion_heap_destroy(struct ion_heap *heap)
-{
-	if (!heap)
-		return;
-
-	switch (heap->type) {
-	case ION_HEAP_TYPE_SYSTEM_CONTIG:
-		ion_system_contig_heap_destroy(heap);
-		break;
-	case ION_HEAP_TYPE_SYSTEM:
-		ion_system_heap_destroy(heap);
-		break;
-	case ION_HEAP_TYPE_CARVEOUT:
-		ion_carveout_heap_destroy(heap);
-		break;
-	case ION_HEAP_TYPE_CHUNK:
-		ion_chunk_heap_destroy(heap);
-		break;
-#ifdef CONFIG_ION_CMA_HEAP
-	case ION_HEAP_TYPE_DMA:
-		ion_cma_heap_destroy(heap);
-		break;
-#endif
-	default:
-		pr_err("%s: Invalid heap type %d\n", __func__,
-		       heap->type);
-	}
-}
-EXPORT_SYMBOL(ion_heap_destroy);
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 4e6fe37..c50f2d9 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -320,7 +320,7 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools,
 	return -ENOMEM;
 }
 
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
+static struct ion_heap *__ion_system_heap_create(void)
 {
 	struct ion_system_heap *heap;
 
@@ -348,19 +348,19 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
 	return ERR_PTR(-ENOMEM);
 }
 
-void ion_system_heap_destroy(struct ion_heap *heap)
+static int ion_system_heap_create(void)
 {
-	struct ion_system_heap *sys_heap = container_of(heap,
-							struct ion_system_heap,
-							heap);
-	int i;
+	struct ion_heap *heap;
 
-	for (i = 0; i < NUM_ORDERS; i++) {
-		ion_page_pool_destroy(sys_heap->uncached_pools[i]);
-		ion_page_pool_destroy(sys_heap->cached_pools[i]);
-	}
-	kfree(sys_heap);
+	heap = __ion_system_heap_create();
+	if (IS_ERR(heap))
+		return PTR_ERR(heap);
+	heap->name = "ion_system_heap";
+
+	ion_device_add_heap(heap);
+	return 0;
 }
+device_initcall(ion_system_heap_create);
 
 static int ion_system_contig_heap_allocate(struct ion_heap *heap,
 					   struct ion_buffer *buffer,
@@ -429,7 +429,7 @@ static struct ion_heap_ops kmalloc_ops = {
 	.map_user = ion_heap_map_user,
 };
 
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
+static struct ion_heap *__ion_system_contig_heap_create(void)
 {
 	struct ion_heap *heap;
 
@@ -438,10 +438,20 @@ struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
 		return ERR_PTR(-ENOMEM);
 	heap->ops = &kmalloc_ops;
 	heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
+	heap->name = "ion_system_contig_heap";
 	return heap;
 }
 
-void ion_system_contig_heap_destroy(struct ion_heap *heap)
+static int ion_system_contig_heap_create(void)
 {
-	kfree(heap);
+	struct ion_heap *heap;
+
+	heap = __ion_system_contig_heap_create();
+	if (IS_ERR(heap))
+		return PTR_ERR(heap);
+
+	ion_device_add_heap(heap);
+	return 0;
 }
+device_initcall(ion_system_contig_heap_create);
+
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 07/12] staging: android: ion: Collapse internal header files
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Ion current has ion_priv.h and ion.h as header files. ion.h was intended
to be used for public APIs but Ion never ended up really having anything
public. Combine the two headers so there is only one internal header.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
v4: minor cleanup suggested by Emil Velikov
---
 drivers/staging/android/ion/ion-ioctl.c         |   1 -
 drivers/staging/android/ion/ion.c               |   1 -
 drivers/staging/android/ion/ion.h               | 479 ++++++++++++++++++++----
 drivers/staging/android/ion/ion_carveout_heap.c |   1 -
 drivers/staging/android/ion/ion_chunk_heap.c    |   1 -
 drivers/staging/android/ion/ion_cma_heap.c      |   1 -
 drivers/staging/android/ion/ion_heap.c          |   1 -
 drivers/staging/android/ion/ion_page_pool.c     |   3 +-
 drivers/staging/android/ion/ion_priv.h          | 453 ----------------------
 drivers/staging/android/ion/ion_system_heap.c   |   1 -
 10 files changed, 402 insertions(+), 540 deletions(-)
 delete mode 100644 drivers/staging/android/ion/ion_priv.h

diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c
index 91b5c2b..4e7bf16 100644
--- a/drivers/staging/android/ion/ion-ioctl.c
+++ b/drivers/staging/android/ion/ion-ioctl.c
@@ -19,7 +19,6 @@
 #include <linux/uaccess.h>
 
 #include "ion.h"
-#include "ion_priv.h"
 
 union ion_ioctl_arg {
 	struct ion_fd_data fd;
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index fbab1e3..e1fb865 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -39,7 +39,6 @@
 #include <linux/sched/task.h>
 
 #include "ion.h"
-#include "ion_priv.h"
 
 bool ion_buffer_cached(struct ion_buffer *buffer)
 {
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index e8a6ffe..fd49403 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -14,24 +14,26 @@
  *
  */
 
-#ifndef _LINUX_ION_H
-#define _LINUX_ION_H
+#ifndef _ION_H
+#define _ION_H
 
+#include <linux/device.h>
+#include <linux/dma-direction.h>
+#include <linux/kref.h>
+#include <linux/mm_types.h>
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/shrinker.h>
 #include <linux/types.h>
+#include <linux/miscdevice.h>
 
 #include "../uapi/ion.h"
 
-struct ion_handle;
-struct ion_device;
-struct ion_heap;
-struct ion_mapper;
-struct ion_client;
-struct ion_buffer;
-
 /**
  * struct ion_platform_heap - defines a heap in the given platform
  * @type:	type of the heap from ion_heap_type enum
- * @id:		unique identifier for heap.  When allocating higher numbers
+ * @id:		unique identifier for heap.  When allocating higher numb ers
  *		will be allocated from first.  At allocation these are passed
  *		as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS.
  * @name:	used for debug purposes
@@ -52,114 +54,433 @@ struct ion_platform_heap {
 };
 
 /**
- * struct ion_platform_data - array of platform heaps passed from board file
- * @nr:		number of structures in the array
- * @heaps:	array of platform_heap structions
+ * struct ion_buffer - metadata for a particular buffer
+ * @ref:		reference count
+ * @node:		node in the ion_device buffers tree
+ * @dev:		back pointer to the ion_device
+ * @heap:		back pointer to the heap the buffer came from
+ * @flags:		buffer specific flags
+ * @private_flags:	internal buffer specific flags
+ * @size:		size of the buffer
+ * @priv_virt:		private data to the buffer representable as
+ *			a void *
+ * @lock:		protects the buffers cnt fields
+ * @kmap_cnt:		number of times the buffer is mapped to the kernel
+ * @vaddr:		the kernel mapping if kmap_cnt is not zero
+ * @sg_table:		the sg table for the buffer if dmap_cnt is not zero
+ * @pages:		flat array of pages in the buffer -- used by fault
+ *			handler and only valid for buffers that are faulted in
+ * @vmas:		list of vma's mapping this buffer
+ * @handle_count:	count of handles referencing this buffer
+ * @task_comm:		taskcomm of last client to reference this buffer in a
+ *			handle, used for debugging
+ * @pid:		pid of last client to reference this buffer in a
+ *			handle, used for debugging
+ */
+struct ion_buffer {
+	struct kref ref;
+	union {
+		struct rb_node node;
+		struct list_head list;
+	};
+	struct ion_device *dev;
+	struct ion_heap *heap;
+	unsigned long flags;
+	unsigned long private_flags;
+	size_t size;
+	void *priv_virt;
+	struct mutex lock;
+	int kmap_cnt;
+	void *vaddr;
+	struct sg_table *sg_table;
+	struct page **pages;
+	struct list_head vmas;
+	struct list_head attachments;
+	/* used to track orphaned buffers */
+	int handle_count;
+	char task_comm[TASK_COMM_LEN];
+	pid_t pid;
+};
+void ion_buffer_destroy(struct ion_buffer *buffer);
+
+/**
+ * struct ion_device - the metadata of the ion device node
+ * @dev:		the actual misc device
+ * @buffers:		an rb tree of all the existing buffers
+ * @buffer_lock:	lock protecting the tree of buffers
+ * @lock:		rwsem protecting the tree of heaps and clients
+ * @heaps:		list of all the heaps in the system
+ * @user_clients:	list of all the clients created from userspace
+ */
+struct ion_device {
+	struct miscdevice dev;
+	struct rb_root buffers;
+	struct mutex buffer_lock;
+	struct rw_semaphore lock;
+	struct plist_head heaps;
+	struct rb_root clients;
+	struct dentry *debug_root;
+	struct dentry *heaps_debug_root;
+	struct dentry *clients_debug_root;
+	int heap_cnt;
+};
+
+/**
+ * struct ion_client - a process/hw block local address space
+ * @node:		node in the tree of all clients
+ * @dev:		backpointer to ion device
+ * @handles:		an rb tree of all the handles in this client
+ * @idr:		an idr space for allocating handle ids
+ * @lock:		lock protecting the tree of handles
+ * @name:		used for debugging
+ * @display_name:	used for debugging (unique version of @name)
+ * @display_serial:	used for debugging (to make display_name unique)
+ * @task:		used for debugging
+ *
+ * A client represents a list of buffers this client may access.
+ * The mutex stored here is used to protect both handles tree
+ * as well as the handles themselves, and should be held while modifying either.
+ */
+struct ion_client {
+	struct rb_node node;
+	struct ion_device *dev;
+	struct rb_root handles;
+	struct idr idr;
+	struct mutex lock;
+	const char *name;
+	char *display_name;
+	int display_serial;
+	struct task_struct *task;
+	pid_t pid;
+	struct dentry *debug_root;
+};
+
+/**
+ * ion_handle - a client local reference to a buffer
+ * @ref:		reference count
+ * @client:		back pointer to the client the buffer resides in
+ * @buffer:		pointer to the buffer
+ * @node:		node in the client's handle rbtree
+ * @kmap_cnt:		count of times this client has mapped to kernel
+ * @id:			client-unique id allocated by client->idr
+ *
+ * Modifications to node, map_cnt or mapping should be protected by the
+ * lock in the client.  Other fields are never changed after initialization.
+ */
+struct ion_handle {
+	struct kref ref;
+	struct ion_client *client;
+	struct ion_buffer *buffer;
+	struct rb_node node;
+	unsigned int kmap_cnt;
+	int id;
+};
+
+/**
+ * struct ion_heap_ops - ops to operate on a given heap
+ * @allocate:		allocate memory
+ * @free:		free memory
+ * @map_kernel		map memory to the kernel
+ * @unmap_kernel	unmap memory to the kernel
+ * @map_user		map memory to userspace
  *
- * Provided by the board file in the form of platform data to a platform device.
+ * allocate, phys, and map_user return 0 on success, -errno on error.
+ * map_dma and map_kernel return pointer on success, ERR_PTR on
+ * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in
+ * the buffer's private_flags when called from a shrinker. In that
+ * case, the pages being free'd must be truly free'd back to the
+ * system, not put in a page pool or otherwise cached.
  */
-struct ion_platform_data {
-	int nr;
-	struct ion_platform_heap *heaps;
+struct ion_heap_ops {
+	int (*allocate)(struct ion_heap *heap,
+			struct ion_buffer *buffer, unsigned long len,
+			unsigned long flags);
+	void (*free)(struct ion_buffer *buffer);
+	void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
+	void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
+	int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer,
+			struct vm_area_struct *vma);
+	int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan);
 };
 
 /**
- * ion_client_create() -  allocate a client and returns it
- * @dev:		the global ion device
+ * heap flags - flags between the heaps and core ion code
+ */
+#define ION_HEAP_FLAG_DEFER_FREE (1 << 0)
+
+/**
+ * private flags - flags internal to ion
+ */
+/*
+ * Buffer is being freed from a shrinker function. Skip any possible
+ * heap-specific caching mechanism (e.g. page pools). Guarantees that
+ * any buffer storage that came from the system allocator will be
+ * returned to the system allocator.
+ */
+#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0)
+
+/**
+ * struct ion_heap - represents a heap in the system
+ * @node:		rb node to put the heap on the device's tree of heaps
+ * @dev:		back pointer to the ion_device
+ * @type:		type of heap
+ * @ops:		ops struct as above
+ * @flags:		flags
+ * @id:			id of heap, also indicates priority of this heap when
+ *			allocating.  These are specified by platform data and
+ *			MUST be unique
  * @name:		used for debugging
+ * @shrinker:		a shrinker for the heap
+ * @free_list:		free list head if deferred free is used
+ * @free_list_size	size of the deferred free list in bytes
+ * @lock:		protects the free list
+ * @waitqueue:		queue to wait on from deferred free thread
+ * @task:		task struct of deferred free thread
+ * @debug_show:		called when heap debug file is read to add any
+ *			heap specific debug info to output
+ *
+ * Represents a pool of memory from which buffers can be made.  In some
+ * systems the only heap is regular system memory allocated via vmalloc.
+ * On others, some blocks might require large physically contiguous buffers
+ * that are allocated from a specially reserved heap.
  */
-struct ion_client *ion_client_create(struct ion_device *dev,
-				     const char *name);
+struct ion_heap {
+	struct plist_node node;
+	struct ion_device *dev;
+	enum ion_heap_type type;
+	struct ion_heap_ops *ops;
+	unsigned long flags;
+	unsigned int id;
+	const char *name;
+	struct shrinker shrinker;
+	struct list_head free_list;
+	size_t free_list_size;
+	spinlock_t free_lock;
+	wait_queue_head_t waitqueue;
+	struct task_struct *task;
+
+	int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
+};
 
 /**
- * ion_client_destroy() -  free's a client and all it's handles
- * @client:	the client
+ * ion_buffer_cached - this ion buffer is cached
+ * @buffer:		buffer
  *
- * Free the provided client and all it's resources including
- * any handles it is holding.
+ * indicates whether this ion buffer is cached
  */
-void ion_client_destroy(struct ion_client *client);
+bool ion_buffer_cached(struct ion_buffer *buffer);
 
 /**
- * ion_alloc - allocate ion memory
- * @client:		the client
- * @len:		size of the allocation
- * @heap_id_mask:	mask of heaps to allocate from, if multiple bits are set
- *			heaps will be tried in order from highest to lowest
- *			id
- * @flags:		heap flags, the low 16 bits are consumed by ion, the
- *			high 16 bits are passed on to the respective heap and
- *			can be heap custom
+ * ion_buffer_fault_user_mappings - fault in user mappings of this buffer
+ * @buffer:		buffer
  *
- * Allocate memory in one of the heaps provided in heap mask and return
- * an opaque handle to it.
+ * indicates whether userspace mappings of this buffer will be faulted
+ * in, this can affect how buffers are allocated from the heap.
  */
-struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
-			     unsigned int heap_id_mask,
-			     unsigned int flags);
+bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
 
 /**
- * ion_free - free a handle
- * @client:	the client
- * @handle:	the handle to free
+ * ion_device_create - allocates and returns an ion device
  *
- * Free the provided handle.
+ * returns a valid device or -PTR_ERR
+ */
+struct ion_device *ion_device_create(void);
+
+/**
+ * ion_device_destroy - free and device and it's resource
+ * @dev:		the device
+ */
+void ion_device_destroy(struct ion_device *dev);
+
+/**
+ * ion_device_add_heap - adds a heap to the ion device
+ * @dev:		the device
+ * @heap:		the heap to add
  */
+void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap);
+
+/**
+ * some helpers for common operations on buffers using the sg_table
+ * and vaddr fields
+ */
+void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
+void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
+int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
+		      struct vm_area_struct *vma);
+int ion_heap_buffer_zero(struct ion_buffer *buffer);
+int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
+
+struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
+				unsigned int heap_id_mask,
+				unsigned int flags);
+
 void ion_free(struct ion_client *client, struct ion_handle *handle);
 
+int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
+
 /**
- * ion_map_kernel - create mapping for the given handle
- * @client:	the client
- * @handle:	handle to map
+ * ion_heap_init_shrinker
+ * @heap:		the heap
  *
- * Map the given handle into the kernel and return a kernel address that
- * can be used to access this address.
+ * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op
+ * this function will be called to setup a shrinker to shrink the freelists
+ * and call the heap's shrink op.
  */
-void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle);
+void ion_heap_init_shrinker(struct ion_heap *heap);
 
 /**
- * ion_unmap_kernel() - destroy a kernel mapping for a handle
- * @client:	the client
- * @handle:	handle to unmap
+ * ion_heap_init_deferred_free -- initialize deferred free functionality
+ * @heap:		the heap
+ *
+ * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will
+ * be called to setup deferred frees. Calls to free the buffer will
+ * return immediately and the actual free will occur some time later
  */
-void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle);
+int ion_heap_init_deferred_free(struct ion_heap *heap);
 
 /**
- * ion_share_dma_buf() - share buffer as dma-buf
- * @client:	the client
- * @handle:	the handle
+ * ion_heap_freelist_add - add a buffer to the deferred free list
+ * @heap:		the heap
+ * @buffer:		the buffer
+ *
+ * Adds an item to the deferred freelist.
  */
-struct dma_buf *ion_share_dma_buf(struct ion_client *client,
-						struct ion_handle *handle);
+void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer);
 
 /**
- * ion_share_dma_buf_fd() - given an ion client, create a dma-buf fd
- * @client:	the client
- * @handle:	the handle
+ * ion_heap_freelist_drain - drain the deferred free list
+ * @heap:		the heap
+ * @size:		amount of memory to drain in bytes
+ *
+ * Drains the indicated amount of memory from the deferred freelist immediately.
+ * Returns the total amount freed.  The total freed may be higher depending
+ * on the size of the items in the list, or lower if there is insufficient
+ * total memory on the freelist.
  */
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
+size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size);
 
 /**
- * ion_import_dma_buf() - get ion_handle from dma-buf
- * @client:	the client
- * @dmabuf:	the dma-buf
+ * ion_heap_freelist_shrink - drain the deferred free
+ *				list, skipping any heap-specific
+ *				pooling or caching mechanisms
+ *
+ * @heap:		the heap
+ * @size:		amount of memory to drain in bytes
+ *
+ * Drains the indicated amount of memory from the deferred freelist immediately.
+ * Returns the total amount freed.  The total freed may be higher depending
+ * on the size of the items in the list, or lower if there is insufficient
+ * total memory on the freelist.
  *
- * Get the ion_buffer associated with the dma-buf and return the ion_handle.
- * If no ion_handle exists for this buffer, return newly created ion_handle.
- * If dma-buf from another exporter is passed, return ERR_PTR(-EINVAL)
+ * Unlike with @ion_heap_freelist_drain, don't put any pages back into
+ * page pools or otherwise cache the pages. Everything must be
+ * genuinely free'd back to the system. If you're free'ing from a
+ * shrinker you probably want to use this. Note that this relies on
+ * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE
+ * flag.
+ */
+size_t ion_heap_freelist_shrink(struct ion_heap *heap,
+					size_t size);
+
+/**
+ * ion_heap_freelist_size - returns the size of the freelist in bytes
+ * @heap:		the heap
+ */
+size_t ion_heap_freelist_size(struct ion_heap *heap);
+
+
+/**
+ * functions for creating and destroying the built in ion heaps.
+ * architectures can add their own custom architecture specific
+ * heaps as appropriate.
  */
-struct ion_handle *ion_import_dma_buf(struct ion_client *client,
-				      struct dma_buf *dmabuf);
+
+
+struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data);
+void ion_heap_destroy(struct ion_heap *heap);
+
+struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused);
+void ion_system_heap_destroy(struct ion_heap *heap);
+struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap);
+void ion_system_contig_heap_destroy(struct ion_heap *heap);
+
+struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data);
+void ion_carveout_heap_destroy(struct ion_heap *heap);
+
+struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data);
+void ion_chunk_heap_destroy(struct ion_heap *heap);
+
+struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data);
+void ion_cma_heap_destroy(struct ion_heap *heap);
 
 /**
- * ion_import_dma_buf_fd() - given a dma-buf fd from the ion exporter get handle
- * @client:	the client
- * @fd:		the dma-buf fd
+ * functions for creating and destroying a heap pool -- allows you
+ * to keep a pool of pre allocated memory to use from your heap.  Keeping
+ * a pool of memory that is ready for dma, ie any cached mapping have been
+ * invalidated from the cache, provides a significant performance benefit on
+ * many systems
+ */
+
+/**
+ * struct ion_page_pool - pagepool struct
+ * @high_count:		number of highmem items in the pool
+ * @low_count:		number of lowmem items in the pool
+ * @high_items:		list of highmem items
+ * @low_items:		list of lowmem items
+ * @mutex:		lock protecting this struct and especially the count
+ *			item list
+ * @gfp_mask:		gfp_mask to use from alloc
+ * @order:		order of pages in the pool
+ * @list:		plist node for list of pools
+ * @cached:		it's cached pool or not
  *
- * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf_fd,
- * import that fd and return a handle representing it. If a dma-buf from
- * another exporter is passed in this function will return ERR_PTR(-EINVAL)
+ * Allows you to keep a pool of pre allocated pages to use from your heap.
+ * Keeping a pool of pages that is ready for dma, ie any cached mapping have
+ * been invalidated from the cache, provides a significant performance benefit
+ * on many systems
  */
-struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd);
+struct ion_page_pool {
+	int high_count;
+	int low_count;
+	bool cached;
+	struct list_head high_items;
+	struct list_head low_items;
+	struct mutex mutex;
+	gfp_t gfp_mask;
+	unsigned int order;
+	struct plist_node list;
+};
+
+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
+					   bool cached);
+void ion_page_pool_destroy(struct ion_page_pool *pool);
+struct page *ion_page_pool_alloc(struct ion_page_pool *pool);
+void ion_page_pool_free(struct ion_page_pool *pool, struct page *page);
+
+/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool
+ * @pool:		the pool
+ * @gfp_mask:		the memory type to reclaim
+ * @nr_to_scan:		number of items to shrink in pages
+ *
+ * returns the number of items freed in pages
+ */
+int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
+			  int nr_to_scan);
+
+long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+
+struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
+						int id);
+
+void ion_free_nolock(struct ion_client *client, struct ion_handle *handle);
+
+int ion_handle_put_nolock(struct ion_handle *handle);
+
+struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
+						int id);
+
+int ion_handle_put(struct ion_handle *handle);
+
+int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
 
-#endif /* _LINUX_ION_H */
+#endif /* _ION_H */
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index 1419a89..7287279 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -23,7 +23,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include "ion.h"
-#include "ion_priv.h"
 
 #define ION_CARVEOUT_ALLOCATE_FAIL	-1
 
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 606f25f..9210bfe 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include "ion.h"
-#include "ion_priv.h"
 
 struct ion_chunk_heap {
 	struct ion_heap heap;
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index f3e0f59..e67e78d 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -23,7 +23,6 @@
 #include <linux/scatterlist.h>
 
 #include "ion.h"
-#include "ion_priv.h"
 
 struct ion_cma_heap {
 	struct ion_heap heap;
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index c974623..d8d057c 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -24,7 +24,6 @@
 #include <linux/scatterlist.h>
 #include <linux/vmalloc.h>
 #include "ion.h"
-#include "ion_priv.h"
 
 void *ion_heap_map_kernel(struct ion_heap *heap,
 			  struct ion_buffer *buffer)
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index 532eda7..817849d 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -22,7 +22,8 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
-#include "ion_priv.h"
+
+#include "ion.h"
 
 static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
 {
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
deleted file mode 100644
index a86866a..0000000
--- a/drivers/staging/android/ion/ion_priv.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * drivers/staging/android/ion/ion_priv.h
- *
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _ION_PRIV_H
-#define _ION_PRIV_H
-
-#include <linux/device.h>
-#include <linux/dma-direction.h>
-#include <linux/kref.h>
-#include <linux/mm_types.h>
-#include <linux/mutex.h>
-#include <linux/rbtree.h>
-#include <linux/sched.h>
-#include <linux/shrinker.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-
-#include "ion.h"
-
-/**
- * struct ion_buffer - metadata for a particular buffer
- * @ref:		reference count
- * @node:		node in the ion_device buffers tree
- * @dev:		back pointer to the ion_device
- * @heap:		back pointer to the heap the buffer came from
- * @flags:		buffer specific flags
- * @private_flags:	internal buffer specific flags
- * @size:		size of the buffer
- * @priv_virt:		private data to the buffer representable as
- *			a void *
- * @lock:		protects the buffers cnt fields
- * @kmap_cnt:		number of times the buffer is mapped to the kernel
- * @vaddr:		the kernel mapping if kmap_cnt is not zero
- * @sg_table:		the sg table for the buffer if dmap_cnt is not zero
- * @pages:		flat array of pages in the buffer -- used by fault
- *			handler and only valid for buffers that are faulted in
- * @vmas:		list of vma's mapping this buffer
- * @handle_count:	count of handles referencing this buffer
- * @task_comm:		taskcomm of last client to reference this buffer in a
- *			handle, used for debugging
- * @pid:		pid of last client to reference this buffer in a
- *			handle, used for debugging
- */
-struct ion_buffer {
-	struct kref ref;
-	union {
-		struct rb_node node;
-		struct list_head list;
-	};
-	struct ion_device *dev;
-	struct ion_heap *heap;
-	unsigned long flags;
-	unsigned long private_flags;
-	size_t size;
-	void *priv_virt;
-	struct mutex lock;
-	int kmap_cnt;
-	void *vaddr;
-	struct sg_table *sg_table;
-	struct page **pages;
-	struct list_head vmas;
-	struct list_head attachments;
-	/* used to track orphaned buffers */
-	int handle_count;
-	char task_comm[TASK_COMM_LEN];
-	pid_t pid;
-};
-void ion_buffer_destroy(struct ion_buffer *buffer);
-
-/**
- * struct ion_device - the metadata of the ion device node
- * @dev:		the actual misc device
- * @buffers:		an rb tree of all the existing buffers
- * @buffer_lock:	lock protecting the tree of buffers
- * @lock:		rwsem protecting the tree of heaps and clients
- * @heaps:		list of all the heaps in the system
- * @user_clients:	list of all the clients created from userspace
- */
-struct ion_device {
-	struct miscdevice dev;
-	struct rb_root buffers;
-	struct mutex buffer_lock;
-	struct rw_semaphore lock;
-	struct plist_head heaps;
-	struct rb_root clients;
-	struct dentry *debug_root;
-	struct dentry *heaps_debug_root;
-	struct dentry *clients_debug_root;
-	int heap_cnt;
-};
-
-/**
- * struct ion_client - a process/hw block local address space
- * @node:		node in the tree of all clients
- * @dev:		backpointer to ion device
- * @handles:		an rb tree of all the handles in this client
- * @idr:		an idr space for allocating handle ids
- * @lock:		lock protecting the tree of handles
- * @name:		used for debugging
- * @display_name:	used for debugging (unique version of @name)
- * @display_serial:	used for debugging (to make display_name unique)
- * @task:		used for debugging
- *
- * A client represents a list of buffers this client may access.
- * The mutex stored here is used to protect both handles tree
- * as well as the handles themselves, and should be held while modifying either.
- */
-struct ion_client {
-	struct rb_node node;
-	struct ion_device *dev;
-	struct rb_root handles;
-	struct idr idr;
-	struct mutex lock;
-	const char *name;
-	char *display_name;
-	int display_serial;
-	struct task_struct *task;
-	pid_t pid;
-	struct dentry *debug_root;
-};
-
-/**
- * ion_handle - a client local reference to a buffer
- * @ref:		reference count
- * @client:		back pointer to the client the buffer resides in
- * @buffer:		pointer to the buffer
- * @node:		node in the client's handle rbtree
- * @kmap_cnt:		count of times this client has mapped to kernel
- * @id:			client-unique id allocated by client->idr
- *
- * Modifications to node, map_cnt or mapping should be protected by the
- * lock in the client.  Other fields are never changed after initialization.
- */
-struct ion_handle {
-	struct kref ref;
-	struct ion_client *client;
-	struct ion_buffer *buffer;
-	struct rb_node node;
-	unsigned int kmap_cnt;
-	int id;
-};
-
-/**
- * struct ion_heap_ops - ops to operate on a given heap
- * @allocate:		allocate memory
- * @free:		free memory
- * @map_kernel		map memory to the kernel
- * @unmap_kernel	unmap memory to the kernel
- * @map_user		map memory to userspace
- *
- * allocate, phys, and map_user return 0 on success, -errno on error.
- * map_dma and map_kernel return pointer on success, ERR_PTR on
- * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in
- * the buffer's private_flags when called from a shrinker. In that
- * case, the pages being free'd must be truly free'd back to the
- * system, not put in a page pool or otherwise cached.
- */
-struct ion_heap_ops {
-	int (*allocate)(struct ion_heap *heap,
-			struct ion_buffer *buffer, unsigned long len,
-			unsigned long flags);
-	void (*free)(struct ion_buffer *buffer);
-	void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
-	void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer);
-	int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer,
-			struct vm_area_struct *vma);
-	int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan);
-};
-
-/**
- * heap flags - flags between the heaps and core ion code
- */
-#define ION_HEAP_FLAG_DEFER_FREE (1 << 0)
-
-/**
- * private flags - flags internal to ion
- */
-/*
- * Buffer is being freed from a shrinker function. Skip any possible
- * heap-specific caching mechanism (e.g. page pools). Guarantees that
- * any buffer storage that came from the system allocator will be
- * returned to the system allocator.
- */
-#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0)
-
-/**
- * struct ion_heap - represents a heap in the system
- * @node:		rb node to put the heap on the device's tree of heaps
- * @dev:		back pointer to the ion_device
- * @type:		type of heap
- * @ops:		ops struct as above
- * @flags:		flags
- * @id:			id of heap, also indicates priority of this heap when
- *			allocating.  These are specified by platform data and
- *			MUST be unique
- * @name:		used for debugging
- * @shrinker:		a shrinker for the heap
- * @free_list:		free list head if deferred free is used
- * @free_list_size	size of the deferred free list in bytes
- * @lock:		protects the free list
- * @waitqueue:		queue to wait on from deferred free thread
- * @task:		task struct of deferred free thread
- * @debug_show:		called when heap debug file is read to add any
- *			heap specific debug info to output
- *
- * Represents a pool of memory from which buffers can be made.  In some
- * systems the only heap is regular system memory allocated via vmalloc.
- * On others, some blocks might require large physically contiguous buffers
- * that are allocated from a specially reserved heap.
- */
-struct ion_heap {
-	struct plist_node node;
-	struct ion_device *dev;
-	enum ion_heap_type type;
-	struct ion_heap_ops *ops;
-	unsigned long flags;
-	unsigned int id;
-	const char *name;
-	struct shrinker shrinker;
-	struct list_head free_list;
-	size_t free_list_size;
-	spinlock_t free_lock;
-	wait_queue_head_t waitqueue;
-	struct task_struct *task;
-
-	int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
-};
-
-/**
- * ion_buffer_cached - this ion buffer is cached
- * @buffer:		buffer
- *
- * indicates whether this ion buffer is cached
- */
-bool ion_buffer_cached(struct ion_buffer *buffer);
-
-/**
- * ion_buffer_fault_user_mappings - fault in user mappings of this buffer
- * @buffer:		buffer
- *
- * indicates whether userspace mappings of this buffer will be faulted
- * in, this can affect how buffers are allocated from the heap.
- */
-bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
-
-/**
- * ion_device_create - allocates and returns an ion device
- *
- * returns a valid device or -PTR_ERR
- */
-struct ion_device *ion_device_create(void);
-
-/**
- * ion_device_destroy - free and device and it's resource
- * @dev:		the device
- */
-void ion_device_destroy(struct ion_device *dev);
-
-/**
- * ion_device_add_heap - adds a heap to the ion device
- * @dev:		the device
- * @heap:		the heap to add
- */
-void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap);
-
-/**
- * some helpers for common operations on buffers using the sg_table
- * and vaddr fields
- */
-void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
-void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer);
-int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
-		      struct vm_area_struct *vma);
-int ion_heap_buffer_zero(struct ion_buffer *buffer);
-int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);
-
-/**
- * ion_heap_init_shrinker
- * @heap:		the heap
- *
- * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op
- * this function will be called to setup a shrinker to shrink the freelists
- * and call the heap's shrink op.
- */
-void ion_heap_init_shrinker(struct ion_heap *heap);
-
-/**
- * ion_heap_init_deferred_free -- initialize deferred free functionality
- * @heap:		the heap
- *
- * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will
- * be called to setup deferred frees. Calls to free the buffer will
- * return immediately and the actual free will occur some time later
- */
-int ion_heap_init_deferred_free(struct ion_heap *heap);
-
-/**
- * ion_heap_freelist_add - add a buffer to the deferred free list
- * @heap:		the heap
- * @buffer:		the buffer
- *
- * Adds an item to the deferred freelist.
- */
-void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer);
-
-/**
- * ion_heap_freelist_drain - drain the deferred free list
- * @heap:		the heap
- * @size:		amount of memory to drain in bytes
- *
- * Drains the indicated amount of memory from the deferred freelist immediately.
- * Returns the total amount freed.  The total freed may be higher depending
- * on the size of the items in the list, or lower if there is insufficient
- * total memory on the freelist.
- */
-size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size);
-
-/**
- * ion_heap_freelist_shrink - drain the deferred free
- *				list, skipping any heap-specific
- *				pooling or caching mechanisms
- *
- * @heap:		the heap
- * @size:		amount of memory to drain in bytes
- *
- * Drains the indicated amount of memory from the deferred freelist immediately.
- * Returns the total amount freed.  The total freed may be higher depending
- * on the size of the items in the list, or lower if there is insufficient
- * total memory on the freelist.
- *
- * Unlike with @ion_heap_freelist_drain, don't put any pages back into
- * page pools or otherwise cache the pages. Everything must be
- * genuinely free'd back to the system. If you're free'ing from a
- * shrinker you probably want to use this. Note that this relies on
- * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE
- * flag.
- */
-size_t ion_heap_freelist_shrink(struct ion_heap *heap,
-					size_t size);
-
-/**
- * ion_heap_freelist_size - returns the size of the freelist in bytes
- * @heap:		the heap
- */
-size_t ion_heap_freelist_size(struct ion_heap *heap);
-
-
-/**
- * functions for creating and destroying the built in ion heaps.
- * architectures can add their own custom architecture specific
- * heaps as appropriate.
- */
-
-struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data);
-void ion_heap_destroy(struct ion_heap *heap);
-struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused);
-void ion_system_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *heap);
-void ion_system_contig_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data);
-void ion_carveout_heap_destroy(struct ion_heap *heap);
-
-struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data);
-void ion_chunk_heap_destroy(struct ion_heap *heap);
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data);
-void ion_cma_heap_destroy(struct ion_heap *heap);
-
-/**
- * functions for creating and destroying a heap pool -- allows you
- * to keep a pool of pre allocated memory to use from your heap.  Keeping
- * a pool of memory that is ready for dma, ie any cached mapping have been
- * invalidated from the cache, provides a significant performance benefit on
- * many systems
- */
-
-/**
- * struct ion_page_pool - pagepool struct
- * @high_count:		number of highmem items in the pool
- * @low_count:		number of lowmem items in the pool
- * @high_items:		list of highmem items
- * @low_items:		list of lowmem items
- * @mutex:		lock protecting this struct and especially the count
- *			item list
- * @gfp_mask:		gfp_mask to use from alloc
- * @order:		order of pages in the pool
- * @list:		plist node for list of pools
- * @cached:		it's cached pool or not
- *
- * Allows you to keep a pool of pre allocated pages to use from your heap.
- * Keeping a pool of pages that is ready for dma, ie any cached mapping have
- * been invalidated from the cache, provides a significant performance benefit
- * on many systems
- */
-struct ion_page_pool {
-	int high_count;
-	int low_count;
-	bool cached;
-	struct list_head high_items;
-	struct list_head low_items;
-	struct mutex mutex;
-	gfp_t gfp_mask;
-	unsigned int order;
-	struct plist_node list;
-};
-
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
-					   bool cached);
-void ion_page_pool_destroy(struct ion_page_pool *pool);
-struct page *ion_page_pool_alloc(struct ion_page_pool *pool);
-void ion_page_pool_free(struct ion_page_pool *pool, struct page *page);
-
-/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool
- * @pool:		the pool
- * @gfp_mask:		the memory type to reclaim
- * @nr_to_scan:		number of items to shrink in pages
- *
- * returns the number of items freed in pages
- */
-int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
-			  int nr_to_scan);
-
-long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-
-struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client,
-						int id);
-
-void ion_free_nolock(struct ion_client *client, struct ion_handle *handle);
-
-int ion_handle_put_nolock(struct ion_handle *handle);
-
-struct ion_handle *ion_handle_get_by_id(struct ion_client *client,
-						int id);
-
-int ion_handle_put(struct ion_handle *handle);
-
-int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query);
-
-#endif /* _ION_PRIV_H */
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index a33331b..4e6fe37 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include "ion.h"
-#include "ion_priv.h"
 
 #define NUM_ORDERS ARRAY_SIZE(orders)
 
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 06/12] staging: android: ion: Get rid of ion_phys_addr_t
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Once upon a time, phys_addr_t was not everywhere in the kernel. These
days it is used enough places that having a separate Ion type doesn't
make sense. Remove the extra type and just use phys_addr_t directly.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/ion.h               | 12 ++----------
 drivers/staging/android/ion/ion_carveout_heap.c | 10 +++++-----
 drivers/staging/android/ion/ion_chunk_heap.c    |  6 +++---
 drivers/staging/android/ion/ion_heap.c          |  4 ++--
 4 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index 3b4bff5..e8a6ffe 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -28,14 +28,6 @@ struct ion_mapper;
 struct ion_client;
 struct ion_buffer;
 
-/*
- * This should be removed some day when phys_addr_t's are fully
- * plumbed in the kernel, and all instances of ion_phys_addr_t should
- * be converted to phys_addr_t.  For the time being many kernel interfaces
- * do not accept phys_addr_t's that would have to
- */
-#define ion_phys_addr_t unsigned long
-
 /**
  * struct ion_platform_heap - defines a heap in the given platform
  * @type:	type of the heap from ion_heap_type enum
@@ -53,9 +45,9 @@ struct ion_platform_heap {
 	enum ion_heap_type type;
 	unsigned int id;
 	const char *name;
-	ion_phys_addr_t base;
+	phys_addr_t base;
 	size_t size;
-	ion_phys_addr_t align;
+	phys_addr_t align;
 	void *priv;
 };
 
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index e0e360f..1419a89 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -30,10 +30,10 @@
 struct ion_carveout_heap {
 	struct ion_heap heap;
 	struct gen_pool *pool;
-	ion_phys_addr_t base;
+	phys_addr_t base;
 };
 
-static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
+static phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
 					     unsigned long size)
 {
 	struct ion_carveout_heap *carveout_heap =
@@ -46,7 +46,7 @@ static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
 	return offset;
 }
 
-static void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
+static void ion_carveout_free(struct ion_heap *heap, phys_addr_t addr,
 			      unsigned long size)
 {
 	struct ion_carveout_heap *carveout_heap =
@@ -63,7 +63,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap,
 				      unsigned long flags)
 {
 	struct sg_table *table;
-	ion_phys_addr_t paddr;
+	phys_addr_t paddr;
 	int ret;
 
 	table = kmalloc(sizeof(*table), GFP_KERNEL);
@@ -96,7 +96,7 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer)
 	struct ion_heap *heap = buffer->heap;
 	struct sg_table *table = buffer->sg_table;
 	struct page *page = sg_page(table->sgl);
-	ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+	phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
 
 	ion_heap_buffer_zero(buffer);
 
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 46e13f6..606f25f 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -27,7 +27,7 @@
 struct ion_chunk_heap {
 	struct ion_heap heap;
 	struct gen_pool *pool;
-	ion_phys_addr_t base;
+	phys_addr_t base;
 	unsigned long chunk_size;
 	unsigned long size;
 	unsigned long allocated;
@@ -151,8 +151,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
 	chunk_heap->heap.ops = &chunk_heap_ops;
 	chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
 	chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
-	pr_debug("%s: base %lu size %zu \n", __func__,
-		 chunk_heap->base, heap_data->size);
+	pr_debug("%s: base %pa size %zu \n", __func__,
+		 &chunk_heap->base, heap_data->size);
 
 	return &chunk_heap->heap;
 
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index 66f8fc5..c974623 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -345,9 +345,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
 	}
 
 	if (IS_ERR_OR_NULL(heap)) {
-		pr_err("%s: error creating heap %s type %d base %lu size %zu\n",
+		pr_err("%s: error creating heap %s type %d base %pa size %zu\n",
 		       __func__, heap_data->name, heap_data->type,
-		       heap_data->base, heap_data->size);
+		       &heap_data->base, heap_data->size);
 		return ERR_PTR(-EINVAL);
 	}
 
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 05/12] staging: android: ion: Break the ABI in the name of forward progress
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Several of the Ion ioctls were designed in such a way that they
necessitate compat ioctls. We're breaking a bunch of other ABIs and
cleaning stuff up anyway so let's follow the ioctl guidelines and clean
things up while everyone is busy converting things over anyway. As part
of this, also remove the useless alignment field from the allocation
structure.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/Makefile     |   3 -
 drivers/staging/android/ion/compat_ion.c | 152 -------------------------------
 drivers/staging/android/ion/compat_ion.h |  29 ------
 drivers/staging/android/ion/ion-ioctl.c  |   1 -
 drivers/staging/android/ion/ion.c        |   5 +-
 drivers/staging/android/uapi/ion.h       |  19 ++--
 6 files changed, 11 insertions(+), 198 deletions(-)
 delete mode 100644 drivers/staging/android/ion/compat_ion.c
 delete mode 100644 drivers/staging/android/ion/compat_ion.h

diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 66d0c4a..a892afa 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -2,6 +2,3 @@ obj-$(CONFIG_ION) +=	ion.o ion-ioctl.o ion_heap.o \
 			ion_page_pool.o ion_system_heap.o \
 			ion_carveout_heap.o ion_chunk_heap.o
 obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
-ifdef CONFIG_COMPAT
-obj-$(CONFIG_ION) += compat_ion.o
-endif
diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c
deleted file mode 100644
index 5037ddd..0000000
--- a/drivers/staging/android/ion/compat_ion.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * drivers/staging/android/ion/compat_ion.c
- *
- * Copyright (C) 2013 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/compat.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-
-#include "ion.h"
-#include "compat_ion.h"
-
-/* See drivers/staging/android/uapi/ion.h for the definition of these structs */
-struct compat_ion_allocation_data {
-	compat_size_t len;
-	compat_size_t align;
-	compat_uint_t heap_id_mask;
-	compat_uint_t flags;
-	compat_int_t handle;
-};
-
-struct compat_ion_handle_data {
-	compat_int_t handle;
-};
-
-#define COMPAT_ION_IOC_ALLOC	_IOWR(ION_IOC_MAGIC, 0, \
-				      struct compat_ion_allocation_data)
-#define COMPAT_ION_IOC_FREE	_IOWR(ION_IOC_MAGIC, 1, \
-				      struct compat_ion_handle_data)
-
-static int compat_get_ion_allocation_data(
-			struct compat_ion_allocation_data __user *data32,
-			struct ion_allocation_data __user *data)
-{
-	compat_size_t s;
-	compat_uint_t u;
-	compat_int_t i;
-	int err;
-
-	err = get_user(s, &data32->len);
-	err |= put_user(s, &data->len);
-	err |= get_user(s, &data32->align);
-	err |= put_user(s, &data->align);
-	err |= get_user(u, &data32->heap_id_mask);
-	err |= put_user(u, &data->heap_id_mask);
-	err |= get_user(u, &data32->flags);
-	err |= put_user(u, &data->flags);
-	err |= get_user(i, &data32->handle);
-	err |= put_user(i, &data->handle);
-
-	return err;
-}
-
-static int compat_get_ion_handle_data(
-			struct compat_ion_handle_data __user *data32,
-			struct ion_handle_data __user *data)
-{
-	compat_int_t i;
-	int err;
-
-	err = get_user(i, &data32->handle);
-	err |= put_user(i, &data->handle);
-
-	return err;
-}
-
-static int compat_put_ion_allocation_data(
-			struct compat_ion_allocation_data __user *data32,
-			struct ion_allocation_data __user *data)
-{
-	compat_size_t s;
-	compat_uint_t u;
-	compat_int_t i;
-	int err;
-
-	err = get_user(s, &data->len);
-	err |= put_user(s, &data32->len);
-	err |= get_user(s, &data->align);
-	err |= put_user(s, &data32->align);
-	err |= get_user(u, &data->heap_id_mask);
-	err |= put_user(u, &data32->heap_id_mask);
-	err |= get_user(u, &data->flags);
-	err |= put_user(u, &data32->flags);
-	err |= get_user(i, &data->handle);
-	err |= put_user(i, &data32->handle);
-
-	return err;
-}
-
-long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	long ret;
-
-	if (!filp->f_op->unlocked_ioctl)
-		return -ENOTTY;
-
-	switch (cmd) {
-	case COMPAT_ION_IOC_ALLOC:
-	{
-		struct compat_ion_allocation_data __user *data32;
-		struct ion_allocation_data __user *data;
-		int err;
-
-		data32 = compat_ptr(arg);
-		data = compat_alloc_user_space(sizeof(*data));
-		if (!data)
-			return -EFAULT;
-
-		err = compat_get_ion_allocation_data(data32, data);
-		if (err)
-			return err;
-		ret = filp->f_op->unlocked_ioctl(filp, ION_IOC_ALLOC,
-							(unsigned long)data);
-		err = compat_put_ion_allocation_data(data32, data);
-		return ret ? ret : err;
-	}
-	case COMPAT_ION_IOC_FREE:
-	{
-		struct compat_ion_handle_data __user *data32;
-		struct ion_handle_data __user *data;
-		int err;
-
-		data32 = compat_ptr(arg);
-		data = compat_alloc_user_space(sizeof(*data));
-		if (!data)
-			return -EFAULT;
-
-		err = compat_get_ion_handle_data(data32, data);
-		if (err)
-			return err;
-
-		return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE,
-							(unsigned long)data);
-	}
-	case ION_IOC_SHARE:
-		return filp->f_op->unlocked_ioctl(filp, cmd,
-						(unsigned long)compat_ptr(arg));
-	default:
-		return -ENOIOCTLCMD;
-	}
-}
diff --git a/drivers/staging/android/ion/compat_ion.h b/drivers/staging/android/ion/compat_ion.h
deleted file mode 100644
index 9da8f91..0000000
--- a/drivers/staging/android/ion/compat_ion.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * drivers/staging/android/ion/compat_ion.h
- *
- * Copyright (C) 2013 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _LINUX_COMPAT_ION_H
-#define _LINUX_COMPAT_ION_H
-
-#if IS_ENABLED(CONFIG_COMPAT)
-
-long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-
-#else
-
-#define compat_ion_ioctl  NULL
-
-#endif /* CONFIG_COMPAT */
-#endif /* _LINUX_COMPAT_ION_H */
diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c
index a361724..91b5c2b 100644
--- a/drivers/staging/android/ion/ion-ioctl.c
+++ b/drivers/staging/android/ion/ion-ioctl.c
@@ -20,7 +20,6 @@
 
 #include "ion.h"
 #include "ion_priv.h"
-#include "compat_ion.h"
 
 union ion_ioctl_arg {
 	struct ion_fd_data fd;
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 65638f5..fbab1e3 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -40,7 +40,6 @@
 
 #include "ion.h"
 #include "ion_priv.h"
-#include "compat_ion.h"
 
 bool ion_buffer_cached(struct ion_buffer *buffer)
 {
@@ -1065,7 +1064,9 @@ static const struct file_operations ion_fops = {
 	.open           = ion_open,
 	.release        = ion_release,
 	.unlocked_ioctl = ion_ioctl,
-	.compat_ioctl   = compat_ion_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ion_ioctl,
+#endif
 };
 
 static size_t ion_debug_heap_total(struct ion_client *client,
diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h
index abd72fd..bba1c47 100644
--- a/drivers/staging/android/uapi/ion.h
+++ b/drivers/staging/android/uapi/ion.h
@@ -20,8 +20,6 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-typedef int ion_user_handle_t;
-
 /**
  * enum ion_heap_types - list of all possible types of heaps
  * @ION_HEAP_TYPE_SYSTEM:	 memory allocated via vmalloc
@@ -76,7 +74,6 @@ enum ion_heap_type {
 /**
  * struct ion_allocation_data - metadata passed from userspace for allocations
  * @len:		size of the allocation
- * @align:		required alignment of the allocation
  * @heap_id_mask:	mask of heap ids to allocate from
  * @flags:		flags passed to heap
  * @handle:		pointer that will be populated with a cookie to use to
@@ -85,11 +82,11 @@ enum ion_heap_type {
  * Provided by userspace as an argument to the ioctl
  */
 struct ion_allocation_data {
-	size_t len;
-	size_t align;
-	unsigned int heap_id_mask;
-	unsigned int flags;
-	ion_user_handle_t handle;
+	__u64 len;
+	__u32 heap_id_mask;
+	__u32 flags;
+	__u32 handle;
+	__u32 unused;
 };
 
 /**
@@ -103,8 +100,8 @@ struct ion_allocation_data {
  * provides the file descriptor and the kernel returns the handle.
  */
 struct ion_fd_data {
-	ion_user_handle_t handle;
-	int fd;
+	__u32 handle;
+	__u32 fd;
 };
 
 /**
@@ -112,7 +109,7 @@ struct ion_fd_data {
  * @handle:	a handle
  */
 struct ion_handle_data {
-	ion_user_handle_t handle;
+	__u32 handle;
 };
 
 #define MAX_HEAP_NAME			32
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 04/12] staging: android: ion: Stop butchering the DMA address
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Now that we have proper caching, stop setting the DMA address manually.
It should be set after properly calling dma_map.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 drivers/staging/android/ion/ion.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 3d979ef5..65638f5 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -81,8 +81,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
 {
 	struct ion_buffer *buffer;
 	struct sg_table *table;
-	struct scatterlist *sg;
-	int i, ret;
+	int ret;
 
 	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
 	if (!buffer)
@@ -119,20 +118,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
 	INIT_LIST_HEAD(&buffer->vmas);
 	INIT_LIST_HEAD(&buffer->attachments);
 	mutex_init(&buffer->lock);
-	/*
-	 * this will set up dma addresses for the sglist -- it is not
-	 * technically correct as per the dma api -- a specific
-	 * device isn't really taking ownership here.  However, in practice on
-	 * our systems the only dma_address space is physical addresses.
-	 * Additionally, we can't afford the overhead of invalidating every
-	 * allocation via dma_map_sg. The implicit contract here is that
-	 * memory coming from the heaps is ready for dma, ie if it has a
-	 * cached mapping that mapping has been invalidated
-	 */
-	for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) {
-		sg_dma_address(sg) = sg_phys(sg);
-		sg_dma_len(sg) = sg->length;
-	}
 	mutex_lock(&dev->buffer_lock);
 	ion_buffer_add(dev, buffer);
 	mutex_unlock(&dev->buffer_lock);
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 03/12] staging: android: ion: Use CMA APIs directly
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

When CMA was first introduced, its primary use was for DMA allocation
and the only way to get CMA memory was to call dma_alloc_coherent. This
put Ion in an awkward position since there was no device structure
readily available and setting one up messed up the coherency model.
These days, CMA can be allocated directly from the APIs. Switch to using
this model to avoid needing a dummy device. This also mitigates some of
the caching problems (e.g. dma_alloc_coherent only returning uncached
memory).

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
v4: Put some #ifdef around CMA heap functions. This is ugly but gets removed
a few patches later.
---
 drivers/staging/android/ion/Kconfig        |  7 +++
 drivers/staging/android/ion/Makefile       |  3 +-
 drivers/staging/android/ion/ion_cma_heap.c | 97 ++++++++----------------------
 drivers/staging/android/ion/ion_heap.c     |  4 ++
 4 files changed, 39 insertions(+), 72 deletions(-)

diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 206c4de..15108c4 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -10,3 +10,10 @@ menuconfig ION
 	  If you're not using Android its probably safe to
 	  say N here.
 
+config ION_CMA_HEAP
+	bool "Ion CMA heap support"
+	depends on ION && CMA
+	help
+	  Choose this option to enable CMA heaps with Ion. This heap is backed
+	  by the Contiguous Memory Allocator (CMA). If your system has these
+	  regions, you should say Y here.
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 26672a0..66d0c4a 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_ION) +=	ion.o ion-ioctl.o ion_heap.o \
 			ion_page_pool.o ion_system_heap.o \
-			ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o
+			ion_carveout_heap.o ion_chunk_heap.o
+obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
 ifdef CONFIG_COMPAT
 obj-$(CONFIG_ION) += compat_ion.o
 endif
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index d562fd7..f3e0f59 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -19,24 +19,19 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/dma-mapping.h>
+#include <linux/cma.h>
+#include <linux/scatterlist.h>
 
 #include "ion.h"
 #include "ion_priv.h"
 
 struct ion_cma_heap {
 	struct ion_heap heap;
-	struct device *dev;
+	struct cma *cma;
 };
 
 #define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap)
 
-struct ion_cma_buffer_info {
-	void *cpu_addr;
-	dma_addr_t handle;
-	struct sg_table *table;
-};
-
 
 /* ION CMA heap operations functions */
 static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
@@ -44,93 +39,53 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
 			    unsigned long flags)
 {
 	struct ion_cma_heap *cma_heap = to_cma_heap(heap);
-	struct device *dev = cma_heap->dev;
-	struct ion_cma_buffer_info *info;
-
-	dev_dbg(dev, "Request buffer allocation len %ld\n", len);
-
-	if (buffer->flags & ION_FLAG_CACHED)
-		return -EINVAL;
+	struct sg_table *table;
+	struct page *pages;
+	int ret;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info)
+	pages = cma_alloc(cma_heap->cma, len, 0, GFP_KERNEL);
+	if (!pages)
 		return -ENOMEM;
 
-	info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle),
-						GFP_HIGHUSER | __GFP_ZERO);
-
-	if (!info->cpu_addr) {
-		dev_err(dev, "Fail to allocate buffer\n");
+	table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+	if (!table)
 		goto err;
-	}
 
-	info->table = kmalloc(sizeof(*info->table), GFP_KERNEL);
-	if (!info->table)
+	ret = sg_alloc_table(table, 1, GFP_KERNEL);
+	if (ret)
 		goto free_mem;
 
-	if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle,
-			    len))
-		goto free_table;
-	/* keep this for memory release */
-	buffer->priv_virt = info;
-	buffer->sg_table = info->table;
-	dev_dbg(dev, "Allocate buffer %p\n", buffer);
+	sg_set_page(table->sgl, pages, len, 0);
+
+	buffer->priv_virt = pages;
+	buffer->sg_table = table;
 	return 0;
 
-free_table:
-	kfree(info->table);
 free_mem:
-	dma_free_coherent(dev, len, info->cpu_addr, info->handle);
+	kfree(table);
 err:
-	kfree(info);
+	cma_release(cma_heap->cma, pages, buffer->size);
 	return -ENOMEM;
 }
 
 static void ion_cma_free(struct ion_buffer *buffer)
 {
 	struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
-	struct device *dev = cma_heap->dev;
-	struct ion_cma_buffer_info *info = buffer->priv_virt;
+	struct page *pages = buffer->priv_virt;
 
-	dev_dbg(dev, "Release buffer %p\n", buffer);
 	/* release memory */
-	dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
+	cma_release(cma_heap->cma, pages, buffer->size);
 	/* release sg table */
-	sg_free_table(info->table);
-	kfree(info->table);
-	kfree(info);
-}
-
-static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
-			struct vm_area_struct *vma)
-{
-	struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
-	struct device *dev = cma_heap->dev;
-	struct ion_cma_buffer_info *info = buffer->priv_virt;
-
-	return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle,
-				 buffer->size);
-}
-
-static void *ion_cma_map_kernel(struct ion_heap *heap,
-				struct ion_buffer *buffer)
-{
-	struct ion_cma_buffer_info *info = buffer->priv_virt;
-	/* kernel memory mapping has been done at allocation time */
-	return info->cpu_addr;
-}
-
-static void ion_cma_unmap_kernel(struct ion_heap *heap,
-				 struct ion_buffer *buffer)
-{
+	sg_free_table(buffer->sg_table);
+	kfree(buffer->sg_table);
 }
 
 static struct ion_heap_ops ion_cma_ops = {
 	.allocate = ion_cma_allocate,
 	.free = ion_cma_free,
-	.map_user = ion_cma_mmap,
-	.map_kernel = ion_cma_map_kernel,
-	.unmap_kernel = ion_cma_unmap_kernel,
+	.map_user = ion_heap_map_user,
+	.map_kernel = ion_heap_map_kernel,
+	.unmap_kernel = ion_heap_unmap_kernel,
 };
 
 struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
@@ -147,7 +102,7 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
 	 * get device from private heaps data, later it will be
 	 * used to make the link with reserved CMA memory
 	 */
-	cma_heap->dev = data->priv;
+	cma_heap->cma = data->priv;
 	cma_heap->heap.type = ION_HEAP_TYPE_DMA;
 	return &cma_heap->heap;
 }
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index c69d0bd..66f8fc5 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -333,9 +333,11 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
 	case ION_HEAP_TYPE_CHUNK:
 		heap = ion_chunk_heap_create(heap_data);
 		break;
+#ifdef CONFIG_ION_CMA_HEAP
 	case ION_HEAP_TYPE_DMA:
 		heap = ion_cma_heap_create(heap_data);
 		break;
+#endif
 	default:
 		pr_err("%s: Invalid heap type %d\n", __func__,
 		       heap_data->type);
@@ -373,9 +375,11 @@ void ion_heap_destroy(struct ion_heap *heap)
 	case ION_HEAP_TYPE_CHUNK:
 		ion_chunk_heap_destroy(heap);
 		break;
+#ifdef CONFIG_ION_CMA_HEAP
 	case ION_HEAP_TYPE_DMA:
 		ion_cma_heap_destroy(heap);
 		break;
+#endif
 	default:
 		pr_err("%s: Invalid heap type %d\n", __func__,
 		       heap->type);
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 02/12] cma: Introduce cma_for_each_area
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Frameworks (e.g. Ion) may want to iterate over each possible CMA area to
allow for enumeration. Introduce a function to allow a callback.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 include/linux/cma.h |  2 ++
 mm/cma.c            | 14 ++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/include/linux/cma.h b/include/linux/cma.h
index d41d1f8..3e8fbf5 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -34,4 +34,6 @@ extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
 			      gfp_t gfp_mask);
 extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
+
+extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data);
 #endif
diff --git a/mm/cma.c b/mm/cma.c
index 43c1b2c..978b4a1 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -504,3 +504,17 @@ bool cma_release(struct cma *cma, const struct page *pages, unsigned int count)
 
 	return true;
 }
+
+int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data)
+{
+	int i;
+
+	for (i = 0; i < cma_area_count; i++) {
+		int ret = it(&cma_areas[i], data);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
-- 
2.7.4

^ permalink raw reply related

* [PATCHv4 01/12] cma: Store a name in the cma structure
From: Laura Abbott @ 2017-04-18 18:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492540034-5466-1-git-send-email-labbott@redhat.com>

Frameworks that may want to enumerate CMA heaps (e.g. Ion) will find it
useful to have an explicit name attached to each region. Store the name
in each CMA structure.

Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 arch/powerpc/kvm/book3s_hv_builtin.c |  3 ++-
 drivers/base/dma-contiguous.c        |  5 +++--
 include/linux/cma.h                  |  4 +++-
 mm/cma.c                             | 17 +++++++++++++++--
 mm/cma.h                             |  1 +
 mm/cma_debug.c                       |  2 +-
 6 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 4d6c64b..b739ff8 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -100,7 +100,8 @@ void __init kvm_cma_reserve(void)
 			 (unsigned long)selected_size / SZ_1M);
 		align_size = HPT_ALIGN_PAGES << PAGE_SHIFT;
 		cma_declare_contiguous(0, selected_size, 0, align_size,
-			KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma);
+			KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, "kvm_cma",
+			&kvm_cma);
 	}
 }
 
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index b55804c..ea9726e 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -165,7 +165,8 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
 {
 	int ret;
 
-	ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
+	ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed,
+					"reserved", res_cma);
 	if (ret)
 		return ret;
 
@@ -258,7 +259,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
 		return -EINVAL;
 	}
 
-	err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
+	err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma);
 	if (err) {
 		pr_err("Reserved memory: unable to setup CMA region\n");
 		return err;
diff --git a/include/linux/cma.h b/include/linux/cma.h
index 03f32d0..d41d1f8 100644
--- a/include/linux/cma.h
+++ b/include/linux/cma.h
@@ -21,13 +21,15 @@ struct cma;
 extern unsigned long totalcma_pages;
 extern phys_addr_t cma_get_base(const struct cma *cma);
 extern unsigned long cma_get_size(const struct cma *cma);
+extern const char *cma_get_name(const struct cma *cma);
 
 extern int __init cma_declare_contiguous(phys_addr_t base,
 			phys_addr_t size, phys_addr_t limit,
 			phys_addr_t alignment, unsigned int order_per_bit,
-			bool fixed, struct cma **res_cma);
+			bool fixed, const char *name, struct cma **res_cma);
 extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 					unsigned int order_per_bit,
+					const char *name,
 					struct cma **res_cma);
 extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
 			      gfp_t gfp_mask);
diff --git a/mm/cma.c b/mm/cma.c
index a6033e3..43c1b2c 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -53,6 +53,11 @@ unsigned long cma_get_size(const struct cma *cma)
 	return cma->count << PAGE_SHIFT;
 }
 
+const char *cma_get_name(const struct cma *cma)
+{
+	return cma->name ? cma->name : "(undefined)";
+}
+
 static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
 					     int align_order)
 {
@@ -168,6 +173,7 @@ core_initcall(cma_init_reserved_areas);
  */
 int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 				 unsigned int order_per_bit,
+				 const char *name,
 				 struct cma **res_cma)
 {
 	struct cma *cma;
@@ -198,6 +204,13 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 	 * subsystems (like slab allocator) are available.
 	 */
 	cma = &cma_areas[cma_area_count];
+	if (name) {
+		cma->name = name;
+	} else {
+		cma->name = kasprintf(GFP_KERNEL, "cma%d\n", cma_area_count);
+		if (!cma->name)
+			return -ENOMEM;
+	}
 	cma->base_pfn = PFN_DOWN(base);
 	cma->count = size >> PAGE_SHIFT;
 	cma->order_per_bit = order_per_bit;
@@ -229,7 +242,7 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
 int __init cma_declare_contiguous(phys_addr_t base,
 			phys_addr_t size, phys_addr_t limit,
 			phys_addr_t alignment, unsigned int order_per_bit,
-			bool fixed, struct cma **res_cma)
+			bool fixed, const char *name, struct cma **res_cma)
 {
 	phys_addr_t memblock_end = memblock_end_of_DRAM();
 	phys_addr_t highmem_start;
@@ -335,7 +348,7 @@ int __init cma_declare_contiguous(phys_addr_t base,
 		base = addr;
 	}
 
-	ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma);
+	ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma);
 	if (ret)
 		goto err;
 
diff --git a/mm/cma.h b/mm/cma.h
index 17c75a4..4986128 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -11,6 +11,7 @@ struct cma {
 	struct hlist_head mem_head;
 	spinlock_t mem_head_lock;
 #endif
+	const char *name;
 };
 
 extern struct cma cma_areas[MAX_CMA_AREAS];
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
index ffc0c3d..595b757 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -167,7 +167,7 @@ static void cma_debugfs_add_one(struct cma *cma, int idx)
 	char name[16];
 	int u32s;
 
-	sprintf(name, "cma-%d", idx);
+	sprintf(name, "cma-%s", cma->name);
 
 	tmp = debugfs_create_dir(name, cma_debugfs_root);
 
-- 
2.7.4

^ permalink raw reply related


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