Re: GPMC in device tree
On Wed, Aug 5, 2015 at 6:56 AM, Ran Shalit ransha...@gmail.com wrote: On Wed, Aug 5, 2015 at 12:25 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 00:22 +0300, Ran Shalit wrote: On Tue, Aug 4, 2015 at 11:31 PM, Scott Wood scottw...@freescale.com wrote: On Tue, 2015-08-04 at 23:26 +0300, Ran Shalit wrote: On Tue, Aug 4, 2015 at 9:54 PM, Scott Wood scottw...@freescale.com wrote: On Tue, 2015-08-04 at 18:29 +0300, Ran Shalit wrote: Hello, I would please like to ask if describing flash nor used with GPMC, whould be done as described in: https://www.kernel.org/doc/Documentation/devicetree/bindings/mtd/gpmc-nor.txt It is described in the above link as TI's GPMC, so I'm not sure if it is relevent for powerpc too. That binding is for TI GPMC. Are you saying you have some PPC chip that has a flash controller called GPMC? -Scott Hi Scott, Thanks, I've worked with TI's chips, so I now understand that I made here some confusion... It is GPCM , not GPMC, my mistake. We already configured it in u-boot, but on doing read/write from kernel it doesn not work. It seems that for the linux to use the correct driver, we need to define the nor in the device tree. Is there any example how to define nor GPCM in device tree ? Is it possible not to override the existing GPCM configuration ? Pretty much all of the mpc8xxx/qoriq device trees have GPCM NOR defined. See Documentation/devicetree/bindings/powerpc/fsl/lbc.txt and examples such as arch/powerpc/boot/dts/p4080ds.dts (part of the lbc node is in arch/powerpc/boot/dts/fsl/p4080si-post.dtsi). Linux will not change the GPCM configuration. -Scott On more thing, if I may. The localbus is also connected to nvram cpld. I've noticed that read/write works well, even though I didn't define anything in device tree. Is there any reasom to add these devices into device tree, or can we use the cpld and nvram without the definition in device tree ? I don't know what you're doing in your kernel to access devices that aren't in the device tree. You should add the devices to the device tree, and have the kernel use it rather than hardcoded info. -Scott Hi, Yes I understand. But It is worse noting that I have no localbus entry in the device tree. Yes, The nvram, cpld which are both connected to device tree, seems to work without any issues. Thanks, Ran I apologyze for the bad english, I meant it worth to note that there is no localbus entry at all in the device tree. So I wander how the nvram and cpld worked... If I may please ask, what should be the compatible for generic devices such as nvram/cpld ? I assume that if they worked without any entry, it means that there is no need for specific driver. Regards, Ran ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: powerpc: Add an inline function to update HID0
Hi Segher, Thanks for the suggestions. I will rename the function to update_power8_hid0() and use asm volatile. On Tue, Aug 04, 2015 at 09:30:57PM -0500, Segher Boessenkool wrote: On Tue, Aug 04, 2015 at 08:08:58PM +1000, Michael Ellerman wrote: +static inline void update_hid0(unsigned long hid0) +{ + /* + * The HID0 update should at the very least be preceded by a + * a SYNC instruction followed by an ISYNC instruction + */ + mb(); + mtspr(SPRN_HID0, hid0); + isync(); That's going to turn into three separate inline asm blocks, which is maybe a bit unfortunate. Have you checked the generated code is what we want, ie. just sync, mtspr, isync ? The mb() is not such a great name anyway: you don't want a memory barrier, you want an actual sync instruction (sync 0, hwsync, whatever the currently preferred spelling is). The function name should also say this is for POWER8 (the required sequences are different for some other processors; and some others might not even _have_ a HID0, or not at 1008). power8_write_hid0 or such? For writing it as one asm, why not just asm volatile(sync ; mtspr %0,%1 ; isync : : i(SPRN_HID0), r(hid0)); instead of the stringify stuff? Segher -- Thanks and Regards gautham. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3] powerpc: Add an inline function to update POWER8 HID0
Section 3.7 of Version 1.2 of the Power8 Processor User's Manual prescribes that updates to HID0 be preceded by a SYNC instruction and followed by an ISYNC instruction (Page 91). Create an inline function name update_power8_hid0() which follows this recipe and invoke it from the static split core path. Signed-off-by: Gautham R. Shenoy e...@linux.vnet.ibm.com --- [v1 -- v2: Moved defn of update_hid0 to reg.h from kvm_ppc.h] [v2 -- v3: Renamed to update_power8_hid0 and used asm volatile] arch/powerpc/include/asm/reg.h | 9 + arch/powerpc/platforms/powernv/subcore.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index af56b5c..1245d99 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1281,6 +1281,15 @@ struct pt_regs; extern void ppc_save_regs(struct pt_regs *regs); +static inline void update_power8_hid0(unsigned long hid0) +{ + /* +* The HID0 update on Power8 should at the very least be +* preceded by a a SYNC instruction followed by an ISYNC +* instruction +*/ + asm volatile(sync; mtspr %0,%1; isync:: i(SPRN_HID0), r(hid0)); +} #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_REG_H */ diff --git a/arch/powerpc/platforms/powernv/subcore.c b/arch/powerpc/platforms/powernv/subcore.c index f60f80a..503a73f 100644 --- a/arch/powerpc/platforms/powernv/subcore.c +++ b/arch/powerpc/platforms/powernv/subcore.c @@ -190,7 +190,7 @@ static void unsplit_core(void) hid0 = mfspr(SPRN_HID0); hid0 = ~HID0_POWER8_DYNLPARDIS; - mtspr(SPRN_HID0, hid0); + update_power8_hid0(hid0); update_hid_in_slw(hid0); while (mfspr(SPRN_HID0) mask) @@ -227,7 +227,7 @@ static void split_core(int new_mode) /* Write new mode */ hid0 = mfspr(SPRN_HID0); hid0 |= HID0_POWER8_DYNLPARDIS | split_parms[i].value; - mtspr(SPRN_HID0, hid0); + update_power8_hid0(hid0); update_hid_in_slw(hid0); /* Wait for it to happen */ -- 1.9.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC v4] genalloc:support memory-allocation with bytes-alignment to genalloc
Bytes alignment is required to manage some special RAM, so add gen_pool_first_fit_align to genalloc, meanwhile add gen_pool_alloc_data to pass data to gen_pool_first_fit_align(modify gen_pool_alloc as a wrapper) Signed-off-by: Zhao Qiang qiang.z...@freescale.com --- *v2: changes: title has been modified, original patch link: http://patchwork.ozlabs.org/patch/493297/ original patch add a func gen_pool_alloc_align, then pass alignment to it as an parameter. after discussing with lauraa and scott, they recommend to pass alignment as part of data based on commit message for ca279cf1065fb689abea1dc7d8c11787729bb185 which adds data: As I can't predict all the possible requirements/needs for all allocation uses cases, I add a free field 'void *data' to pass any needed information to the allocation function. For example 'data' could be used to handle a structure where you store the alignment, the expected memory bank, the requester device, or any information that could influence the allocation algorithm. *v3: changes: title has been modified, original patch link: http://patchwork.ozlabs.org/patch/500317/ according to the comments, add gen_pool_alloc_data, modify gen_pool_alloc as a wrapper, define struct data_align for gen_pool_first_fit_align algorithm. add parameter pointer pool to algorithm. *v4: changes: v3 link: http://patchwork.ozlabs.org/patch/500317/ There are comments for v3, according to the comments, modify the patch for v4. such as modifying annotations, removing unnecessary chek, removing unnecessary cast and so on. include/linux/genalloc.h | 23 +++ lib/genalloc.c | 58 +++- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 1ccaab4..55da07e 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -34,6 +34,7 @@ struct device; struct device_node; +struct gen_pool; /** * Allocation callback function type definition @@ -47,7 +48,7 @@ typedef unsigned long (*genpool_algo_t)(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data); + void *data, struct gen_pool *pool); /* * General purpose special memory pool descriptor. @@ -73,6 +74,13 @@ struct gen_pool_chunk { unsigned long bits[0]; /* bitmap for allocating memory chunk */ }; +/* + * gen_pool data descriptor for gen_pool_first_fit_align. + */ +struct genpool_data_align { + int align; /* alignment by bytes for starting address */ +}; + extern struct gen_pool *gen_pool_create(int, int); extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t, @@ -96,6 +104,7 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr, } extern void gen_pool_destroy(struct gen_pool *); extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); +extern unsigned long gen_pool_alloc_data(struct gen_pool *, size_t, void *data); extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); @@ -108,14 +117,20 @@ extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, void *data); extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, - unsigned long start, unsigned int nr, void *data); + unsigned long start, unsigned int nr, void *data, + struct gen_pool *pool); + +extern unsigned long gen_pool_first_fit_align(unsigned long *map, + unsigned long size, unsigned long start, unsigned int nr, + void *data, struct gen_pool *pool); extern unsigned long gen_pool_first_fit_order_align(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, - void *data); + void *data, struct gen_pool *pool); extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, - unsigned long start, unsigned int nr, void *data); + unsigned long start, unsigned int nr, void *data, + struct gen_pool *pool); extern struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order, int nid); diff --git a/lib/genalloc.c b/lib/genalloc.c index d214866..fe11a00 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -269,6 +269,24 @@ EXPORT_SYMBOL(gen_pool_destroy); */ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) { + return gen_pool_alloc_data(pool, size, pool-data); +} +EXPORT_SYMBOL(gen_pool_alloc); + +/** + * gen_pool_alloc_data - allocate special memory from the pool
[v4, 2/2] powerpc/mpc85xx: Add FSL QorIQ DPAA FMan support to the SoC device tree(s)
From: Igal Liberman igal.liber...@freescale.com Based on prior work by Andy Fleming aflem...@freescale.com Signed-off-by: Shruti Kanetkar shr...@freescale.com Signed-off-by: Emil Medve emilian.me...@freescale.com Signed-off-by: Igal Liberman igal.liber...@freescale.com --- v3 --- v4: - No changes in this patch v2 --- v3: - Removed P1023 support v1 --- v2: - Added T1024 support arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi |9 ++- arch/powerpc/boot/dts/fsl/b4860si-post.dtsi | 20 +- arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi | 12 +++- arch/powerpc/boot/dts/fsl/b4si-post.dtsi| 31 +- arch/powerpc/boot/dts/fsl/p2041si-post.dtsi | 29 - arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi | 10 ++- arch/powerpc/boot/dts/fsl/p3041si-post.dtsi | 29 - arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi | 10 ++- arch/powerpc/boot/dts/fsl/p4080si-post.dtsi | 48 ++- arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi | 15 - arch/powerpc/boot/dts/fsl/p5020si-post.dtsi | 29 - arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi | 10 ++- arch/powerpc/boot/dts/fsl/p5040si-post.dtsi | 56 - arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi | 17 +- arch/powerpc/boot/dts/fsl/t1023si-post.dtsi | 19 ++ arch/powerpc/boot/dts/fsl/t102xsi-pre.dtsi |6 ++ arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | 31 ++ arch/powerpc/boot/dts/fsl/t104xsi-pre.dtsi |9 ++- arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | 43 + arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi | 11 arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | 88 ++- arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi | 22 ++- 22 files changed, 536 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi index 9cfeaef..5d54ec7 100644 --- a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi @@ -1,7 +1,7 @@ /* * B4420 Silicon/SoC Device Tree Source (pre include) * - * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 - 2015 Freescale Semiconductor, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -54,8 +54,13 @@ dma0 = dma0; dma1 = dma1; sdhc = sdhc; - }; + fman0 = fman0; + ethernet0 = enet0; + ethernet1 = enet1; + ethernet2 = enet2; + ethernet3 = enet3; + }; cpus { #address-cells = 1; diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi index 26585d6..3065833 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi @@ -1,7 +1,7 @@ /* * B4860 Silicon/SoC Device Tree Source (post include) * - * Copyright 2012 - 2014 Freescale Semiconductor Inc. + * Copyright 2012 - 2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -271,6 +271,24 @@ compatible = fsl,b4860-rcpm, fsl,qoriq-rcpm-2.0; }; +/include/ qoriq-fman3-0-1g-4.dtsi +/include/ qoriq-fman3-0-1g-5.dtsi +/include/ qoriq-fman3-0-10g-0.dtsi +/include/ qoriq-fman3-0-10g-1.dtsi + fman@40 { + enet4: ethernet@e8000 { + }; + + enet5: ethernet@ea000 { + }; + + enet6: ethernet@f { + }; + + enet7: ethernet@f2000 { + }; + }; + L2: l2-cache-controller@c2 { compatible = fsl,b4860-l2-cache-controller; }; diff --git a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi index bc914f2..a738f7c 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi @@ -1,7 +1,7 @@ /* * B4860 Silicon/SoC Device Tree Source (pre include) * - * Copyright 2012 Freescale Semiconductor Inc. + * Copyright 2012 - 2015 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -54,6 +54,16 @@ dma0 = dma0; dma1 = dma1; sdhc = sdhc; + + fman0 = fman0; + ethernet0 = enet0; + ethernet1 = enet1; + ethernet2 = enet2; + ethernet3 = enet3; + ethernet4 = enet4; + ethernet5 = enet5; + ethernet6 = enet6; + ethernet7 = enet7; }; diff --git
Re: [PATCH 1/8] misc: cxl: clean up afu_read_config()
On Mon, 2015-07-27 at 00:18 +0300, Vladimir Zapolskiy wrote: The sanity checks for overflow are not needed, because this is done on caller side in fs/sysfs/file.c Signed-off-by: Vladimir Zapolskiy v...@mleia.com Cc: linuxppc-dev@lists.ozlabs.org Cc: Ian Munsie imun...@au1.ibm.com Cc: Michael Neuling mi...@neuling.org Acked-by: Michael Neuling mi...@neuling.org --- drivers/misc/cxl/sysfs.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 31f38bc..87cd747 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -443,12 +443,7 @@ static ssize_t afu_read_config(struct file *filp, struct kobject *kobj, struct afu_config_record *cr = to_cr(kobj); struct cxl_afu *afu = to_cxl_afu(container_of(kobj-parent, struct device, kobj)); - u64 i, j, val, size = afu-crs_len; - - if (off size) - return 0; - if (off + count size) - count = size - off; + u64 i, j, val; for (i = 0; i count;) { val = cxl_afu_cr_read64(afu, cr-cr, off ~0x7); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] cxl: Don't ignore add_process_element result when attaching context
On Wed, 2015-07-29 at 14:40 +1000, Daniel Axtens wrote: On Wed, 2015-07-29 at 14:25 +1000, Michael Ellerman wrote: On Wed, 2015-07-29 at 14:07 +1000, Daniel Axtens wrote: Previously, when attaching a context in dedicated mode, we ignored Previously? You mean currently? Now is before this patch is applied. I do mean currently. Apologies for the temporal confusion :) the result of add_process_element, which could potentially fail. If add_process_element returns and error, pass it back to the caller. ^ I can fix. Many thanks: it's good to know that my spelling mistakes will only be immortalised in the list archives rather than in the kernel's git history. :p Not to mention the double negative in the patch subject! Don't ignore... come on!?!? :-P Mikey ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3] powerpc32: rearrange instructions order in ip_fast_csum()
On PPC_8xx, lwz has a 2 cycles latency, and branching also takes 2 cycles. On some other powerpc, lwz has 3 cycles. As the size of the header is minimum 5 words, we can unroll the loop for the first words to reduce number of branching, and we can re-order the instructions to limit loading latency. Signed-off-by: Christophe Leroy christophe.le...@c-s.fr --- v3: Only use lwzu for the last load as lwzu has undocumented additional latency arch/powerpc/lib/checksum_32.S | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S index 9c48ee0..3ef6e3f 100644 --- a/arch/powerpc/lib/checksum_32.S +++ b/arch/powerpc/lib/checksum_32.S @@ -26,14 +26,17 @@ */ _GLOBAL(ip_fast_csum) lwz r0,0(r3) - lwzur5,4(r3) - addic. r4,r4,-2 + lwz r5,4(r3) + lwz r6,8(r3) + lwzur7,12(r3) + addir4,r4,-4 addcr0,r0,r5 mtctr r4 - blelr- -1: lwzur4,4(r3) - adder0,r0,r4 + adder0,r0,r6 +1: adder0,r0,r7 + lwzur7,4(r3) bdnz1b + adder0,r0,r7 addze r0,r0 /* add in final carry */ rlwinm r3,r0,16,0,31 /* fold two halves together */ add r3,r0,r3 -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/5] powerpc/pseries: extract of_helpers module
On Wed, 2015-08-05 at 00:20 -0500, Segher Boessenkool wrote: Hi Andy, On Tue, Aug 04, 2015 at 05:36:45PM +0300, Andy Shevchenko wrote: +struct device_node *pseries_of_derive_parent(const char *path) +{ + struct device_node *parent = NULL; + char *parent_path = /; + size_t parent_path_len = strrchr(path, '/') - path + 1; + + /* reject if path is / */ + if (!strcmp(path, /)) + return ERR_PTR(-EINVAL); + + if (strrchr(path, '/') != path) { + parent_path = kmalloc(parent_path_len, GFP_KERNEL); If path doesn't contain any slash this will do interesting things; you might want to fix that too while you're at it :-) No problem, though it is in the original code. I would do as a separate patch on top of the series. Will be okay for you? Segher -- Andy Shevchenko andriy.shevche...@linux.intel.com Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On Tue, 4 Aug 2015, Boris Ostrovsky wrote: On 08/04/2015 02:12 PM, Julien Grall wrote: /* * We detect special mappings in one of two ways: @@ -217,9 +232,13 @@ static inline unsigned long bfn_to_local_pfn(unsigned long mfn) /* VIRT - MACHINE conversion */ #define virt_to_machine(v)(phys_to_machine(XPADDR(__pa(v -#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) #define virt_to_mfn(v)(pfn_to_mfn(virt_to_pfn(v))) #define mfn_to_virt(m)(__va(mfn_to_pfn(m) PAGE_SHIFT)) +#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) This looks like unnecessary change. diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc447..25e3cce 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { - return pfn_to_mfn(vmalloc_to_pfn(address)); + return pfn_to_gfn(vmalloc_to_pfn(address)); } Are you sure? This will return vmalloc_to_pfn(address)). I think that is OK: there is no behavioural change here. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On Tue, 4 Aug 2015, Julien Grall wrote: Based on include/xen/mm.h [1], Linux is mistakenly using MFN when GFN is meant, I suspect this is because the first support for Xen was for PV. This resulted in some misimplementation of helpers on ARM and confused developers about the expected behavior. For instance, with pfn_to_mfn, we expect to get an MFN based on the name. Although, if we look at the implementation on x86, it's returning a GFN. For clarity and avoid new confusion, replace any reference to mfn with gfn in any helpers used by PV drivers. The x86 code will still keep some reference of pfn_to_mfn but exclusively for PV (a BUG_ON has been added to ensure this). No changes as been made in the hypercall field, even though they may be invalid, in order to keep the same as the defintion in xen repo. Take also the opportunity to simplify simple construction such as pfn_to_mfn(page_to_pfn(page)) into page_to_gfn. More complex clean up will come in follow-up patches. [1] http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=e758ed14f390342513405dd766e874934573e6cb Signed-off-by: Julien Grall julien.gr...@citrix.com Cc: Stefano Stabellini stefano.stabell...@eu.citrix.com Cc: Russell King li...@arm.linux.org.uk Cc: Konrad Rzeszutek Wilk konrad.w...@oracle.com Cc: Boris Ostrovsky boris.ostrov...@oracle.com Cc: David Vrabel david.vra...@citrix.com Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: Roger Pau Monné roger@citrix.com Cc: Dmitry Torokhov dmitry.torok...@gmail.com Cc: Ian Campbell ian.campb...@citrix.com Cc: Wei Liu wei.l...@citrix.com Cc: Juergen Gross jgr...@suse.com Cc: James E.J. Bottomley jbottom...@odin.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: Jiri Slaby jsl...@suse.com Cc: Jean-Christophe Plagniol-Villard plagn...@jcrosoft.com Cc: Tomi Valkeinen tomi.valkei...@ti.com Cc: linux-in...@vger.kernel.org Cc: net...@vger.kernel.org Cc: linux-s...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-fb...@vger.kernel.org Cc: linux-arm-ker...@lists.infradead.org Aside from the x86 bits: Reviewed-by: Stefano Stabellini stefano.stabell...@eu.citrix.com Note that I've re-introduced mfn_to_pfn co only for x86 PV code. The helpers contain a BUG_ON to ensure that it's never called for auto-translated guests. I did as best as my can to determine whether mfn or gfn helpers should be used. Although, I haven't tried to boot it. It may be possible to do further cleanup in the mmu.c where I found some check to auto-translated. I'm not sure why given that the pvmmu callback are only used for non-auto translated guest. Finally, given those changes, I didn't retain the Reviewed-by/Acked-by. Changes in v2: - Give directly the URL to the commit rather than the commit ID - xenstored_local_init: keep the cast to void * - Typoes - Keep pfn_to_mfn for x86 and PV-only. The *mfn* helpers are used in arch/x86/xen for enlighten.c, mmu.c, p2m.c, setup.c, smp.c and mm.c --- arch/arm/include/asm/xen/page.h | 13 +++-- arch/x86/include/asm/xen/page.h | 33 ++--- arch/x86/xen/smp.c | 2 +- drivers/block/xen-blkfront.c| 6 +++--- drivers/input/misc/xen-kbdfront.c | 4 ++-- drivers/net/xen-netback/netback.c | 4 ++-- drivers/net/xen-netfront.c | 8 drivers/scsi/xen-scsifront.c| 8 +++- drivers/tty/hvc/hvc_xen.c | 5 +++-- drivers/video/fbdev/xen-fbfront.c | 4 ++-- drivers/xen/balloon.c | 2 +- drivers/xen/events/events_base.c| 2 +- drivers/xen/events/events_fifo.c| 4 ++-- drivers/xen/gntalloc.c | 3 ++- drivers/xen/manage.c| 2 +- drivers/xen/tmem.c | 4 ++-- drivers/xen/xenbus/xenbus_client.c | 2 +- drivers/xen/xenbus/xenbus_dev_backend.c | 2 +- drivers/xen/xenbus/xenbus_probe.c | 8 +++- include/xen/page.h | 4 ++-- 20 files changed, 69 insertions(+), 51 deletions(-) diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 087d86e..51e5bf1 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h @@ -34,14 +34,15 @@ typedef struct xpaddr { unsigned long __pfn_to_mfn(unsigned long pfn); extern struct rb_root phys_to_mach; -static inline unsigned long pfn_to_mfn(unsigned long pfn) +/* Pseudo-physical - Guest conversion */ +static inline unsigned long pfn_to_gfn(unsigned long pfn) { return pfn; } -static inline unsigned long mfn_to_pfn(unsigned long mfn) +static inline unsigned long gfn_to_pfn(unsigned long gfn) { - return mfn; + return gfn;
Re: [PATCH 2/3] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores
On Tue, Aug 4, 2015 at 5:18 AM, Scott Wood scottw...@freescale.com wrote: [Added linuxppc-dev@lists.ozlabs.org. Besides that list being required for review of PPC patches, it feeds the patchwork that I use to track and apply patches.] On Mon, 2015-08-03 at 19:52 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:14 AM, Scott Wood scottw...@freescale.com wrote: On Fri, 2015-07-31 at 17:20 +0800, b29983@freescale.comwrote: From: Tang Yuantian yuantian.t...@freescale.com Freescale E500MC and E5500 core-based platforms, like P4080, T1040, support disabling/enabling CPU dynamically. This patch adds this feature on those platforms. Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com Signed-off-by: Tang Yuantian yuantian.t...@feescale.com +{ + int i; + + for (i = 0; i 5; i++) { + if (generic_check_cpu_dead(cpu)) { + qoriq_pm_ops-cpu_die(cpu); +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif + return; + } + udelay(10); + } + pr_err(%s: CPU%d didn't die...\n, __func__, cpu); +} Only 500ms timeout, versus 10sec in generic_cpu_die()? The process is fast. Maybe 10 second is too large. Is it fast 100% of the time? What if the CPU you intend to die is in a long critical section? What harm is there to having a longer timeout, similar to what other platforms use? Will change the max timeout to 10 seconds. #endif static inline void flush_spin_table(void *spin_table) @@ -246,11 +267,7 @@ static int smp_85xx_kick_cpu(int nr) spin_table = phys_to_virt(*cpu_rel_addr); local_irq_save(flags); -#ifdef CONFIG_PPC32 #ifdef CONFIG_HOTPLUG_CPU - /* Corresponding to generic_set_cpu_dead() */ - generic_set_cpu_up(nr); - if (system_state == SYSTEM_RUNNING) { /* * To keep it compatible with old boot program which uses @@ -263,6 +280,7 @@ static int smp_85xx_kick_cpu(int nr) out_be32(spin_table-addr_l, 0); flush_spin_table(spin_table); + qoriq_pm_ops-cpu_up(nr); Again, is it possible to get here without a valid qoriq_pm_ops (i.e. is there anything stopping the user from trying to initiate CPU hotplug)? -Scott For every platform running this code, should has a valid qoriq_pm_ops. If not valid, it's a bug. How do you prevent this code from running when there is no valid qoriq_pm_ops? -Scott Will check if qoriq_pm_ops is valid. -Chenhui ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
Hi Boris, On 05/08/15 00:16, Boris Ostrovsky wrote: On 08/04/2015 02:12 PM, Julien Grall wrote: /* * We detect special mappings in one of two ways: @@ -217,9 +232,13 @@ static inline unsigned long bfn_to_local_pfn(unsigned long mfn) /* VIRT - MACHINE conversion */ #define virt_to_machine(v)(phys_to_machine(XPADDR(__pa(v -#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) #define virt_to_mfn(v)(pfn_to_mfn(virt_to_pfn(v))) #define mfn_to_virt(m)(__va(mfn_to_pfn(m) PAGE_SHIFT)) +#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) This looks like unnecessary change. Right, I made the mistake when I re-introduced virt_to_mfn in this version. It was dropped in the previous one. diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc447..25e3cce 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { -return pfn_to_mfn(vmalloc_to_pfn(address)); +return pfn_to_gfn(vmalloc_to_pfn(address)); } Are you sure? This will return vmalloc_to_pfn(address)). I guess you mean vmalloc_to_mfn will return vmalloc_to_pfn? If so, it will be only the case on auto-translated case (because pfn == gfn). In the case of PV, the mfn will be returned. Although, this function is misnamed. It's fixed in a follow-up patch (see #6) because it's required more renaming than this function. I didn't want to add such changes within this patch. Regards, -- Julien Grall ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On 08/05/2015 06:51 AM, Julien Grall wrote: diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc447..25e3cce 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { -return pfn_to_mfn(vmalloc_to_pfn(address)); +return pfn_to_gfn(vmalloc_to_pfn(address)); } Are you sure? This will return vmalloc_to_pfn(address)). I guess you mean vmalloc_to_mfn will return vmalloc_to_pfn? If so, it will be only the case on auto-translated case (because pfn == gfn). In the case of PV, the mfn will be returned. How will mfn be returned on PV when pfn_to_gfn() is an identity function? static inline unsigned long pfn_to_gfn(unsigned long pfn) { return pfn; } -boris Although, this function is misnamed. It's fixed in a follow-up patch (see #6) because it's required more renaming than this function. I didn't want to add such changes within this patch. Regards, ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [Xen-devel] [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On 05/08/15 13:19, Boris Ostrovsky wrote: On 08/05/2015 06:51 AM, Julien Grall wrote: diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc447..25e3cce 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { -return pfn_to_mfn(vmalloc_to_pfn(address)); +return pfn_to_gfn(vmalloc_to_pfn(address)); } Are you sure? This will return vmalloc_to_pfn(address)). I guess you mean vmalloc_to_mfn will return vmalloc_to_pfn? If so, it will be only the case on auto-translated case (because pfn == gfn). In the case of PV, the mfn will be returned. How will mfn be returned on PV when pfn_to_gfn() is an identity function? static inline unsigned long pfn_to_gfn(unsigned long pfn) { return pfn; } The identity function is only for ARM guest which are always auto-translated (arch/arm/include/asm/xen/page.h). The x86 version contains a check if the guest is auto-translated or not (arch/x86/include/asm/xen/page.): static inline unsigned long pfn_to_gfn(unsigned long pfn) { if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn; else return pfn_to_mfn(pfn); } Regards, -- Julien Grall ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [Xen-devel] [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On 08/05/2015 08:33 AM, Julien Grall wrote: On 05/08/15 13:19, Boris Ostrovsky wrote: On 08/05/2015 06:51 AM, Julien Grall wrote: diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 09dc447..25e3cce 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -539,7 +539,7 @@ static int xenfb_remove(struct xenbus_device *dev) static unsigned long vmalloc_to_mfn(void *address) { -return pfn_to_mfn(vmalloc_to_pfn(address)); +return pfn_to_gfn(vmalloc_to_pfn(address)); } Are you sure? This will return vmalloc_to_pfn(address)). I guess you mean vmalloc_to_mfn will return vmalloc_to_pfn? If so, it will be only the case on auto-translated case (because pfn == gfn). In the case of PV, the mfn will be returned. How will mfn be returned on PV when pfn_to_gfn() is an identity function? static inline unsigned long pfn_to_gfn(unsigned long pfn) { return pfn; } The identity function is only for ARM guest which are always auto-translated (arch/arm/include/asm/xen/page.h). The x86 version contains a check if the guest is auto-translated or not (arch/x86/include/asm/xen/page.): static inline unsigned long pfn_to_gfn(unsigned long pfn) { if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn; else return pfn_to_mfn(pfn); } Of course --- I was looking at the top of the patch and didn't realize it was ARM changes. Sorry for the noise. -boris ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v4, 0/9] Freescale DPAA FMan
From: Igal Liberman igal.liber...@freescale.com The Freescale Data Path Acceleration Architecture (DPAA) is a set of hardware components on specific QorIQ multicore processors. This architecture provides the infrastructure to support simplified sharing of networking interfaces and accelerators by multiple CPU cores and the accelerators. One of the DPAA accelerators is the Frame Manager (FMan) which contains a series of hardware blocks: ports, Ethernet MACs, a multi user RAM (MURAM) and Storage Profile (SP). This patch set introduce the FMan drivers. Each driver configures and initializes the corresponding FMan hardware module (described above). The MAC driver offers support for three different types of MACs (eTSEC, TGEC, MEMAC). The driver structure and a hint on file naming: -- | FMan driver/MAC driver | fm_drv*, mac* files -- | FMan | Port | MAC | MURAM | SP | fm_* files -- | FLib | fman_*.c, fsl_fman_.*h files -- The first 3 patches present the FMan Foundation Libraries (FLIBs). The FLIBs provide basic internal API for the FMan hardware configuration and control. Header files are located in fman/flib directory. Source files are located in each module directory. The upper layer of the FMan driver makes use of the basic API which is provided by the Flibs. The remaining patches present the required FMan hardware module drivers. v3 -- v4: - Remove device_initcall call in driver registration (redundant) - Remove hot/cold labels - Minor update in FMan Clock read from device-tree - Update fixed-link support - Addressed feedback from Stephen Hemminger - Remove bogus blank line v2 -- v3: - Addressed feedback from Scott: - Remove typedefs - Remove unnecessary memory barriers - Remove unnecessary casting - Remove KConfig options - Remove early_params - Remove Hungarian notation - Remove __packed__ attribute and padding from structures - Remove unlikely attribute (where it's not needed) - Use proper error codes and remove unnecessary prints - Use proper values for sleep routines - Replace complex Macros with functions - Improve device tree processing code - Use symbolic defines - Add time-out in busy-wait loops - Removed exit code (loadable module support will be added later) - Fixed fixed-link issue raised by Joakim Tjernlund v1 -- v2: - Addressed feedback from Paul Bolle: - General feedback of FMan Driver layer - Remove Errata defines - Aligned comments to Kernel Doc - Remove Loadable Module support (not yet supported) - Removed not needed KConfig dependencies - Addressed feedback from Scott Wood - Use Kernel ioread/iowrite services - Squash FLIB source and header patches together This submission is based on the prior Freescale DPAA FMan V3,RFC submission. Several issues addresses in this submission: - Reduced MAC layering and complexity - Reduced code base - T1024/T2080 10G best effort support Igal Liberman (9): fsl/fman: Add the FMan FLIB fsl/fman: Add the FMan port FLIB fsl/fman: Add the FMan MAC FLIB fsl/fman: Add FMan MURAM support fsl/fman: Add Frame Manager support fsl/fman: Add FMan MAC support fsl/fman: Add FMan SP support fsl/fman: Add FMan Port Support fsl/fman: Add FMan MAC driver drivers/net/ethernet/freescale/Kconfig |1 + drivers/net/ethernet/freescale/Makefile|2 + drivers/net/ethernet/freescale/fman/Kconfig|8 + drivers/net/ethernet/freescale/fman/Makefile | 12 + .../net/ethernet/freescale/fman/flib/fsl_enet.h| 135 ++ .../net/ethernet/freescale/fman/flib/fsl_fman.h| 590 + .../ethernet/freescale/fman/flib/fsl_fman_dtsec.h | 809 .../freescale/fman/flib/fsl_fman_dtsec_mii_acc.h | 89 ++ .../ethernet/freescale/fman/flib/fsl_fman_memac.h | 429 ++ .../freescale/fman/flib/fsl_fman_memac_mii_acc.h | 72 ++ .../ethernet/freescale/fman/flib/fsl_fman_port.h | 409 ++ .../net/ethernet/freescale/fman/flib/fsl_fman_sp.h | 53 + .../ethernet/freescale/fman/flib/fsl_fman_tgec.h | 393 ++ drivers/net/ethernet/freescale/fman/fm.c | 1366 drivers/net/ethernet/freescale/fman/fm.h | 279 drivers/net/ethernet/freescale/fman/fm_common.h| 178 +++ drivers/net/ethernet/freescale/fman/fm_drv.c | 621 + drivers/net/ethernet/freescale/fman/fm_drv.h | 111 ++
[v4, 1/9] fsl/fman: Add the FMan FLIB
From: Igal Liberman igal.liber...@freescale.com The FMan FLib provides the basic API used by the FMan drivers to configure and control the FMan hardware. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/Kconfig |1 + drivers/net/ethernet/freescale/Makefile|2 + drivers/net/ethernet/freescale/fman/Kconfig|7 + drivers/net/ethernet/freescale/fman/Makefile |5 + .../net/ethernet/freescale/fman/flib/fsl_fman.h| 590 + drivers/net/ethernet/freescale/fman/fman.c | 911 6 files changed, 1516 insertions(+) create mode 100644 drivers/net/ethernet/freescale/fman/Kconfig create mode 100644 drivers/net/ethernet/freescale/fman/Makefile create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman.h create mode 100644 drivers/net/ethernet/freescale/fman/fman.c diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index ff76d4e..f3f89cc 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -53,6 +53,7 @@ config FEC_MPC52xx_MDIO If compiled as module, it will be called fec_mpc52xx_phy. source drivers/net/ethernet/freescale/fs_enet/Kconfig +source drivers/net/ethernet/freescale/fman/Kconfig config FSL_PQ_MDIO tristate Freescale PQ MDIO diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 71debd1..4097c58 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -17,3 +17,5 @@ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o + +obj-$(CONFIG_FSL_FMAN) += fman/ diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig new file mode 100644 index 000..8aeae29 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/Kconfig @@ -0,0 +1,7 @@ +config FSL_FMAN + bool FMan support + depends on FSL_SOC || COMPILE_TEST + default n + help + Freescale Data-Path Acceleration Architecture Frame Manager + (FMan) support diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile new file mode 100644 index 000..2799c6f --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -0,0 +1,5 @@ +subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib + +obj-y += fsl_fman.o + +fsl_fman-objs := fman.o diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h new file mode 100644 index 000..7bd5ca6 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h @@ -0,0 +1,590 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FSL_FMAN_H +#define __FSL_FMAN_H + +#include linux/delay.h + +struct fman_revision_info { + u8 major_rev; /* Major revision */ + u8 minor_rev; /* Minor revision */ +}; + +/* sizes */
[v4, 2/9] fsl/fman: Add the FMan port FLIB
From: Igal Liberman igal.liber...@freescale.com The FMan Port FLib provides basic API used by the drivers to configure and control the FMan Port hardware. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/fman/Makefile |2 + .../ethernet/freescale/fman/flib/fsl_fman_port.h | 409 .../net/ethernet/freescale/fman/flib/fsl_fman_sp.h | 53 ++ drivers/net/ethernet/freescale/fman/port/Makefile |3 + .../net/ethernet/freescale/fman/port/fman_port.c | 510 5 files changed, 977 insertions(+) create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h create mode 100644 drivers/net/ethernet/freescale/fman/port/Makefile create mode 100644 drivers/net/ethernet/freescale/fman/port/fman_port.c diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index 2799c6f..50a4de2 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -3,3 +3,5 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib obj-y += fsl_fman.o fsl_fman-objs := fman.o + +obj-y += port/ diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h new file mode 100644 index 000..6de0719 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h @@ -0,0 +1,409 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FSL_FMAN_PORT_H +#define __FSL_FMAN_PORT_H + +#include linux/io.h + +#include fsl_fman_sp.h + +/* Registers bit fields */ + +/* BMI defines */ +#define BMI_EBD_EN 0x8000 + +#define BMI_PORT_CFG_EN0x8000 +#define BMI_PORT_CFG_FDOVR 0x0200 + +#define BMI_PORT_STATUS_BSY0x8000 + +#define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT +#define BMI_DMA_ATTR_IC_STASH_ON 0x1000 +#define BMI_DMA_ATTR_HDR_STASH_ON 0x0400 +#define BMI_DMA_ATTR_SG_STASH_ON 0x0100 +#define BMI_DMA_ATTR_WRITE_OPTIMIZEFMAN_SP_DMA_ATTR_WRITE_OPTIMIZE + +#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT16 +#define BMI_RX_FIFO_THRESHOLD_ETHE 0x8000 + +#define BMI_FRAME_END_CS_IGNORE_SHIFT 24 +#define BMI_FRAME_END_CS_IGNORE_MASK 0x001f + +#define BMI_RX_FRAME_END_CUT_SHIFT 16 +#define BMI_RX_FRAME_END_CUT_MASK 0x001f + +#define BMI_IC_TO_EXT_SHIFTFMAN_SP_IC_TO_EXT_SHIFT +#define BMI_IC_TO_EXT_MASK 0x001f +#define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT +#define BMI_IC_FROM_INT_MASK 0x000f +#define BMI_IC_SIZE_MASK 0x001f + +#define BMI_INT_BUF_MARG_SHIFT 28 +#define BMI_INT_BUF_MARG_MASK 0x000f +#define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT +#define
[PATCH v2 0/2] powerpc32: Optimise csum_partial()
The purpose of this patchset is to optimise csum_partial() on powerpc32. In the first part, we remove some unneccessary instructions In the second part, we partially unloop the main loop Christophe Leroy (2): Optimise a few instructions in csum_partial() Optimise csum_partial() loop arch/powerpc/lib/checksum_32.S | 53 +- 1 file changed, 32 insertions(+), 21 deletions(-) -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 1/2] powerpc32: optimise a few instructions in csum_partial()
r5 does contain the value to be updated, so lets use r5 all way long for that. It makes the code more readable. To avoid confusion, it is better to use adde instead of addc The first addition is useless. Its only purpose is to clear carry. As r4 is a signed int that is always positive, this can be done by using srawi instead of srwi Let's also remove the comment about dcbz having no overhead as it is not correct on all powerpc, at least on MPC8xx In the last part, in our situation, the remaining quantity of bytes to be proceeded is between 0 and 3. Therefore, we can base that part on the value of bit 31 and bit 30 of r4 instead of anding r4 with 3 then proceding on comparisons and substractions. Signed-off-by: Christophe Leroy christophe.le...@c-s.fr --- arch/powerpc/lib/checksum_32.S | 37 + 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S index 7b95a68..2e4879c 100644 --- a/arch/powerpc/lib/checksum_32.S +++ b/arch/powerpc/lib/checksum_32.S @@ -64,35 +64,32 @@ _GLOBAL(csum_tcpudp_magic) * csum_partial(buff, len, sum) */ _GLOBAL(csum_partial) - addic r0,r5,0 subir3,r3,4 - srwi. r6,r4,2 + srawi. r6,r4,2 /* Divide len by 4 and also clear carry */ beq 3f /* if we're doing 4 bytes */ - andi. r5,r3,2 /* Align buffer to longword boundary */ + andi. r0,r3,2 /* Align buffer to longword boundary */ beq+1f - lhz r5,4(r3)/* do 2 bytes to get aligned */ - addir3,r3,2 + lhz r0,4(r3)/* do 2 bytes to get aligned */ subir4,r4,2 - addcr0,r0,r5 + addir3,r3,2 srwi. r6,r4,2 /* # words to do */ + adder5,r5,r0 beq 3f 1: mtctr r6 -2: lwzur5,4(r3)/* the bdnz has zero overhead, so it should */ - adder0,r0,r5/* be unnecessary to unroll this loop */ +2: lwzur0,4(r3) + adder5,r5,r0 bdnz2b - andi. r4,r4,3 -3: cmpwi 0,r4,2 - blt+4f - lhz r5,4(r3) +3: andi. r0,r4,2 + beq+4f + lhz r0,4(r3) addir3,r3,2 - subir4,r4,2 - adder0,r0,r5 -4: cmpwi 0,r4,1 - bne+5f - lbz r5,4(r3) - slwir5,r5,8 /* Upper byte of word */ - adder0,r0,r5 -5: addze r3,r0 /* add in final carry */ + adder5,r5,r0 +4: andi. r0,r4,1 + beq+5f + lbz r0,4(r3) + slwir0,r0,8 /* Upper byte of word */ + adder5,r5,r0 +5: addze r3,r5 /* add in final carry */ blr /* -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v4, 4/9] fsl/fman: Add FMan MURAM support
From: Igal Liberman igal.liber...@freescale.com Add Frame Manager Multi-User RAM support. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/fman/Kconfig|1 + drivers/net/ethernet/freescale/fman/Makefile |6 +- drivers/net/ethernet/freescale/fman/fm_muram.c | 115 .../net/ethernet/freescale/fman/inc/fm_muram_ext.h | 102 + 4 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/freescale/fman/fm_muram.c create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig index 8aeae29..66b7296 100644 --- a/drivers/net/ethernet/freescale/fman/Kconfig +++ b/drivers/net/ethernet/freescale/fman/Kconfig @@ -1,6 +1,7 @@ config FSL_FMAN bool FMan support depends on FSL_SOC || COMPILE_TEST + select GENERIC_ALLOCATOR default n help Freescale Data-Path Acceleration Architecture Frame Manager diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index 1841b03..55c91bd 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -1,8 +1,10 @@ -subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib +subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \ + -I$(srctree)/drivers/net/ethernet/freescale/fman/inc \ + -I$(srctree)/drivers/net/ethernet/freescale/fman obj-y += fsl_fman.o -fsl_fman-objs := fman.o +fsl_fman-objs := fman.o fm_muram.o obj-y += port/ obj-y += mac/ diff --git a/drivers/net/ethernet/freescale/fman/fm_muram.c b/drivers/net/ethernet/freescale/fman/fm_muram.c new file mode 100644 index 000..9d74bd9 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/fm_muram.c @@ -0,0 +1,115 @@ +/* + * Copyright 2008-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include fm_muram_ext.h + +#include linux/io.h +#include linux/string.h +#include linux/slab.h +#include linux/genalloc.h + +struct muram_info { + struct gen_pool *pool; + void __iomem *vbase; + size_t size; + phys_addr_t pbase; +}; + +struct muram_info *fm_muram_init(phys_addr_t base, size_t size) +{ + struct muram_info *muram; + void __iomem *vaddr; + int ret; + + muram = kzalloc(sizeof(*muram), GFP_KERNEL); + if (!muram) + return NULL; + + muram-pool = gen_pool_create(ilog2(64), -1); + if (!muram-pool) { + pr_err(%s(): MURAM pool create failed\n, __func__); + return NULL; + } + + vaddr = ioremap(base, size); + if (!vaddr) { + pr_err(%s(): MURAM ioremap failed\n, __func__); + return NULL; + } + + ret = gen_pool_add_virt(muram-pool, (unsigned long)vaddr, + base, size, -1); + if (ret 0) { + pr_err(%s(): MURAM pool add failed\n, __func__); +
[PATCH v2 2/2] powerpc32: optimise csum_partial() loop
On the 8xx, load latency is 2 cycles and taking branches also takes 2 cycles. So let's unroll the loop. Signed-off-by: Christophe Leroy christophe.le...@c-s.fr --- v2: Only use lwzu for the last load as lwzu has undocumented additional latency arch/powerpc/lib/checksum_32.S | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S index 2e4879c..9c48ee0 100644 --- a/arch/powerpc/lib/checksum_32.S +++ b/arch/powerpc/lib/checksum_32.S @@ -75,10 +75,24 @@ _GLOBAL(csum_partial) srwi. r6,r4,2 /* # words to do */ adder5,r5,r0 beq 3f -1: mtctr r6 +1: andi. r6,r6,3 /* Prepare to handle words 4 by 4 */ + beq 21f + mtctr r6 2: lwzur0,4(r3) adder5,r5,r0 bdnz2b +21:srwi. r6,r4,4 /* # blocks of 4 words to do */ + beq 3f + mtctr r6 +22:lwz r0,4(r3) + lwz r6,8(r3) + lwz r7,12(r3) + lwzur8,16(r3) + adder5,r5,r0 + adder5,r5,r6 + adder5,r5,r7 + adder5,r5,r8 + bdnz22b 3: andi. r0,r4,2 beq+4f lhz r0,4(r3) -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v4, 6/9] fsl/fman: Add FMan MAC support
From: Igal Liberman igal.liber...@freescale.com Add Frame Manger MAC Driver support. This patch adds The FMan MAC configuration, initialization and runtime control routines. This patch contains support for these types of MACs: tGEC, dTSEC and mEMAC Signed-off-by: Igal Liberman igal.liber...@freescale.com --- .../ethernet/freescale/fman/flib/fsl_fman_memac.h |1 + drivers/net/ethernet/freescale/fman/fm.c | 41 + drivers/net/ethernet/freescale/fman/fm.h |3 + drivers/net/ethernet/freescale/fman/fm_common.h| 29 + .../ethernet/freescale/fman/inc/crc_mac_addr_ext.h | 314 ++ drivers/net/ethernet/freescale/fman/mac/Makefile |4 +- drivers/net/ethernet/freescale/fman/mac/fm_dtsec.c | 1012 drivers/net/ethernet/freescale/fman/mac/fm_dtsec.h | 207 drivers/net/ethernet/freescale/fman/mac/fm_mac.h | 259 + drivers/net/ethernet/freescale/fman/mac/fm_memac.c | 700 ++ drivers/net/ethernet/freescale/fman/mac/fm_memac.h | 122 +++ drivers/net/ethernet/freescale/fman/mac/fm_tgec.c | 552 +++ drivers/net/ethernet/freescale/fman/mac/fm_tgec.h | 124 +++ 13 files changed, 3367 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_dtsec.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_dtsec.h create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.h create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_memac.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_memac.h create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_tgec.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_tgec.h diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h index f8641d4..ebf7989 100644 --- a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h +++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h @@ -373,6 +373,7 @@ struct memac_cfg { bool tx_pbl_fwd; bool debug_mode; bool wake_on_lan; + bool fixed_link; u16 max_frame_length; u16 pause_quanta; u32 tx_ipg_length; diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c index 7e5fa53..450ee6b 100644 --- a/drivers/net/ethernet/freescale/fman/fm.c +++ b/drivers/net/ethernet/freescale/fman/fm.c @@ -587,6 +587,47 @@ u8 fm_get_id(struct fm_t *fm) return fm-fm_state-fm_id; } +int fm_reset_mac(struct fm_t *fm, u8 mac_id) +{ + int err; + struct fman_fpm_regs __iomem *fpm_rg = fm-fpm_regs; + + if (fm-fm_state-rev_info.major_rev = 6) { + pr_warn(FMan MAC reset!\n); + return -EINVAL; + } + if (!fm-base_addr) { + pr_warn('base_address' is required!\n); + return -EINVAL; + } + err = fman_reset_mac(fpm_rg, mac_id); + + if (err == -EINVAL) { + pr_warn(Illegal MAC Id\n); + return -EINVAL; + } else if (err == EINVAL) { + return -EINVAL; + } + return 0; +} + +int fm_set_mac_max_frame(struct fm_t *fm, enum fm_mac_type type, +u8 mac_id, u16 mtu) +{ + /* if port is already initialized, check that MaxFrameLength is smaller +* or equal to the port's max +*/ + if ((!fm-fm_state-port_mfl[mac_id]) || + (fm-fm_state-port_mfl[mac_id] + (mtu = fm-fm_state-port_mfl[mac_id]))) { + fm-fm_state-mac_mfl[mac_id] = mtu; + } else { + pr_warn(MAC max_frame_length is larger than Port max_frame_length\n); + return -EINVAL; + } + return 0; +} + u16 fm_get_clock_freq(struct fm_t *fm) { return fm-fm_state-fm_clk_freq; diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h index d7eca90..c205357 100644 --- a/drivers/net/ethernet/freescale/fman/fm.h +++ b/drivers/net/ethernet/freescale/fman/fm.h @@ -164,6 +164,7 @@ struct fm_iram_regs_t { struct fm_state_struct_t { u8 fm_id; + enum fm_port_type ports_types[FM_MAX_NUM_OF_HW_PORT_IDS]; u16 fm_clk_freq; struct fm_revision_info_t rev_info; bool enabled_time_stamp; @@ -183,6 +184,8 @@ struct fm_state_struct_t { u32 extra_fifo_pool_size; u8 extra_tasks_pool_size; u8 extra_open_dmas_pool_size; + u16 port_mfl[FM_MAX_NUM_OF_MACS]; + u16 mac_mfl[FM_MAX_NUM_OF_MACS]; }; struct fm_intg_t { diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h index 1cde270..abe89a7 100644 --- a/drivers/net/ethernet/freescale/fman/fm_common.h +++ b/drivers/net/ethernet/freescale/fman/fm_common.h @@ -86,6 +86,26 @@ enum fm_inter_module_event
[v4, 7/9] fsl/fman: Add FMan SP support
From: Igal Liberman igal.liber...@freescale.com Add Storage Profiles support. The Storage Profiles contain parameters that are used by the FMan in order to store frames being received on the Rx ports, or to determine the parameters that affect writing the Internal Context in the frame margin on Tx. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/fman/Makefile |2 + drivers/net/ethernet/freescale/fman/fm_sp_common.h | 105 ++ drivers/net/ethernet/freescale/fman/sp/Makefile|3 + drivers/net/ethernet/freescale/fman/sp/fm_sp.c | 371 4 files changed, 481 insertions(+) create mode 100644 drivers/net/ethernet/freescale/fman/fm_sp_common.h create mode 100644 drivers/net/ethernet/freescale/fman/sp/Makefile create mode 100644 drivers/net/ethernet/freescale/fman/sp/fm_sp.c diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index f61d3a6..c6c3e24 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -8,3 +8,5 @@ fsl_fman-objs := fman.o fm_muram.o fm.o fm_drv.o obj-y += port/ obj-y += mac/ +obj-y += sp/ + diff --git a/drivers/net/ethernet/freescale/fman/fm_sp_common.h b/drivers/net/ethernet/freescale/fman/fm_sp_common.h new file mode 100644 index 000..56bd749 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/fm_sp_common.h @@ -0,0 +1,105 @@ +/* + * Copyright 2008-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* FM SP ... */ +#ifndef __FM_SP_COMMON_H +#define __FM_SP_COMMON_H + +#include fm_ext.h +#include fsl_fman.h + +#define ILLEGAL_BASE(~0) + +/* defaults */ +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE 0 +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_PASS_PRS_RESULT false +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_PASS_TIME_STAMP false +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN 64 + +/* structure for defining internal context copying */ +struct fm_sp_int_context_data_copy_t { + /* Offset in External buffer to which internal +* context is copied to (Rx) or taken from (Tx, Op). +*/ + u16 ext_buf_offset; + /* Offset within internal context to copy from +* (Rx) or to copy to (Tx, Op). +*/ + u8 int_context_offset; + /* Internal offset size to be copied */ + u16 size; +}; + +/* struct for defining external buffer margins */ +struct fm_sp_buf_margins_t { + /* Number of bytes to be left at the beginning +* of the external buffer (must be divisible by 16) +*/ + u16 start_margins; + /* number of bytes to be left at the end +* of the external buffer(must be divisible by 16) +*/ + u16 end_margins; +}; + +struct fm_sp_buffer_offsets_t { + u32 data_offset; + u32 prs_result_offset; + u32 time_stamp_offset; + u32 hash_result_offset; +}; + +int fm_sp_build_buffer_structure(struct fm_sp_int_context_data_copy_t +*fm_port_int_context_data_copy, +struct fm_buffer_prefix_content_t +
[v4, 9/9] fsl/fman: Add FMan MAC driver
From: Igal Liberman igal.liber...@freescale.com This patch adds the Ethernet MAC driver support. Signed-off-by: Igal Liberman igal.liber...@freescale.com Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/fman/inc/mac.h | 135 drivers/net/ethernet/freescale/fman/mac/Makefile |3 +- drivers/net/ethernet/freescale/fman/mac/mac-api.c | 688 + drivers/net/ethernet/freescale/fman/mac/mac.c | 445 + 4 files changed, 1270 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/fman/inc/mac.h create mode 100644 drivers/net/ethernet/freescale/fman/mac/mac-api.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/mac.c diff --git a/drivers/net/ethernet/freescale/fman/inc/mac.h b/drivers/net/ethernet/freescale/fman/inc/mac.h new file mode 100644 index 000..f86d0bc --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/inc/mac.h @@ -0,0 +1,135 @@ +/* Copyright 2008-2015 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MAC_H +#define __MAC_H + +#include linux/device.h /* struct device, BUS_ID_SIZE */ +#include linux/if_ether.h/* ETH_ALEN */ +#include linux/phy.h /* phy_interface_t, struct phy_device */ +#include linux/list.h + +#include enet_ext.h + +#include fsl_fman_drv.h /* struct port_device */ +#include fm_port_ext.h + +struct fm_mac_dev; +enum fm_mac_exceptions; + +enum {DTSEC, XGMAC, MEMAC}; + +struct mac_device { + struct device *dev; + void*priv; + u8 cell_index; + struct resource *res; + void __iomem*vaddr; + u8 addr[ETH_ALEN]; + bool promisc; + + struct fm *fm_dev; + struct fm_port_drv_t*port_dev[2]; + + phy_interface_t phy_if; + u32 if_support; + bool link; + bool fixed_link; + u16 speed; + u16 max_speed; + struct device_node *phy_node; + struct device_node *tbi_node; + struct phy_device *phy_dev; + void*fm; + /* List of multicast addresses */ + struct list_head mc_addr_list; + struct platform_device *eth_dev; + + bool autoneg_pause; + bool rx_pause_req; + bool tx_pause_req; + bool rx_pause_active; + bool tx_pause_active; + + int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev); + int (*init)(struct mac_device *mac_dev); + int (*start)(struct mac_device *mac_dev); + int (*stop)(struct mac_device *mac_dev); + int (*set_promisc)(struct fm_mac_dev *fm_mac_dev, bool enable); + int (*change_addr)(struct fm_mac_dev *fm_mac_dev, + enet_addr_t *p_enet_addr); + int (*set_multi)(struct net_device *net_dev, +struct mac_device *mac_dev); + int (*set_rx_pause)(struct fm_mac_dev *fm_mac_dev, bool en); + int (*set_tx_pause)(struct fm_mac_dev *fm_mac_dev, u8 priority, +
[v4, 8/9] fsl/fman: Add FMan Port Support
From: Igal Liberman igal.liber...@freescale.com This patch adds The FMan Port configuration, initialization and runtime control routines. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/fman/Makefile |2 +- drivers/net/ethernet/freescale/fman/fm.c | 251 - drivers/net/ethernet/freescale/fman/fm_common.h| 35 + drivers/net/ethernet/freescale/fman/fm_drv.c | 72 +- drivers/net/ethernet/freescale/fman/fm_drv.h |2 + drivers/net/ethernet/freescale/fman/fm_port_drv.c | 372 +++ .../net/ethernet/freescale/fman/inc/fm_port_ext.h | 340 ++ .../net/ethernet/freescale/fman/inc/fsl_fman_drv.h | 104 ++ drivers/net/ethernet/freescale/fman/port/Makefile |2 +- drivers/net/ethernet/freescale/fman/port/fm_port.c | 1081 drivers/net/ethernet/freescale/fman/port/fm_port.h | 502 + 11 files changed, 2759 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/freescale/fman/fm_port_drv.c create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_port_ext.h create mode 100644 drivers/net/ethernet/freescale/fman/port/fm_port.c create mode 100644 drivers/net/ethernet/freescale/fman/port/fm_port.h diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index c6c3e24..8d637e2 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -4,7 +4,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \ obj-y += fsl_fman.o -fsl_fman-objs := fman.o fm_muram.o fm.o fm_drv.o +fsl_fman-objs := fman.o fm_muram.o fm.o fm_drv.o fm_port_drv.o obj-y += port/ obj-y += mac/ diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c index 450ee6b..a8ecf0b 100644 --- a/drivers/net/ethernet/freescale/fman/fm.c +++ b/drivers/net/ethernet/freescale/fman/fm.c @@ -376,11 +376,29 @@ static void qmi_err_event(struct fm_t *fm) static void dma_err_event(struct fm_t *fm) { - u32 status; + u32 status, com_id; + u8 tnum, port_id, relative_port_id; + u16 liodn; struct fman_dma_regs __iomem *dma_rg = fm-dma_regs; status = fman_get_dma_err_event(dma_rg); + if (status DMA_STATUS_BUS_ERR) { + com_id = fman_get_dma_com_id(dma_rg); + port_id = (u8)(((com_id DMA_TRANSFER_PORTID_MASK) + DMA_TRANSFER_PORTID_SHIFT)); + relative_port_id = + hw_port_id_to_sw_port_id(fm-fm_state-rev_info.major_rev, +port_id); + tnum = (u8)((com_id DMA_TRANSFER_TNUM_MASK) + DMA_TRANSFER_TNUM_SHIFT); + liodn = (u16)(com_id DMA_TRANSFER_LIODN_MASK); + WARN_ON(fm-fm_state-ports_types[port_id] == + FM_PORT_TYPE_DUMMY); + fm-bus_error_cb(fm-dev_id, fm-fm_state-ports_types[port_id], +relative_port_id, +fman_get_dma_addr(dma_rg), tnum, liodn); + } if (status DMA_STATUS_FM_SPDAT_ECC) fm-exception_cb(fm-dev_id, FM_EX_DMA_SINGLE_PORT_ECC); if (status DMA_STATUS_READ_ECC) @@ -587,6 +605,233 @@ u8 fm_get_id(struct fm_t *fm) return fm-fm_state-fm_id; } +int fm_get_set_port_params(struct fm_t *fm, + struct fm_inter_module_port_init_params_t + *port_params) +{ + int err; + unsigned long int_flags; + u8 port_id = port_params-port_id, mac_id; + struct fman_rg fman_rg; + + fman_rg.bmi_rg = fm-bmi_regs; + fman_rg.qmi_rg = fm-qmi_regs; + fman_rg.fpm_rg = fm-fpm_regs; + fman_rg.dma_rg = fm-dma_regs; + + spin_lock_irqsave(fm-spinlock, int_flags); + + fm-fm_state-ports_types[port_id] = port_params-port_type; + + err = fm_set_num_of_tasks(fm, port_params-port_id, + port_params-num_of_tasks, + port_params-num_of_extra_tasks); + if (err) { + spin_unlock_irqrestore(fm-spinlock, int_flags); + return err; + } + + /* TX Ports */ + if (port_params-port_type != FM_PORT_TYPE_RX) { + u32 enq_th; + u32 deq_th; + + /* update qmi ENQ/DEQ threshold */ + fm-fm_state-accumulated_num_of_deq_tnums += + port_params-deq_pipeline_depth; + enq_th = fman_get_qmi_enq_th(fman_rg.qmi_rg); + /* if enq_th is too big, we reduce it to the max value +* that is still 0 +*/ + if (enq_th = (fm-intg-qmi_max_num_of_tnums - + fm-fm_state-accumulated_num_of_deq_tnums)) { + enq_th = +
[v4, 5/9] fsl/fman: Add Frame Manager support
From: Igal Liberman igal.liber...@freescale.com Add Frame Manger Driver support. This patch adds The FMan configuration, initialization and runtime control routines. Signed-off-by: Igal Liberman igal.liber...@freescale.com --- drivers/net/ethernet/freescale/fman/Makefile |2 +- drivers/net/ethernet/freescale/fman/fm.c | 1076 drivers/net/ethernet/freescale/fman/fm.h | 276 + drivers/net/ethernet/freescale/fman/fm_common.h| 114 +++ drivers/net/ethernet/freescale/fman/fm_drv.c | 551 ++ drivers/net/ethernet/freescale/fman/fm_drv.h | 109 ++ drivers/net/ethernet/freescale/fman/inc/enet_ext.h | 199 drivers/net/ethernet/freescale/fman/inc/fm_ext.h | 446 .../net/ethernet/freescale/fman/inc/fsl_fman_drv.h | 99 ++ 9 files changed, 2871 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/fman/fm.c create mode 100644 drivers/net/ethernet/freescale/fman/fm.h create mode 100644 drivers/net/ethernet/freescale/fman/fm_common.h create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.c create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.h create mode 100644 drivers/net/ethernet/freescale/fman/inc/enet_ext.h create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_ext.h create mode 100644 drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index 55c91bd..f61d3a6 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -4,7 +4,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \ obj-y += fsl_fman.o -fsl_fman-objs := fman.o fm_muram.o +fsl_fman-objs := fman.o fm_muram.o fm.o fm_drv.o obj-y += port/ obj-y += mac/ diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c new file mode 100644 index 000..7e5fa53 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/fm.c @@ -0,0 +1,1076 @@ +/* + * Copyright 2008-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME : fmt + +#include fm_common.h +#include fm.h +#include fm_muram_ext.h +#include asm/mpc85xx.h +#include fsl_fman.h + +#include linux/string.h +#include linux/slab.h + +static struct fm_intg_t *fill_intg_params(u8 major, u8 minor) +{ + struct fm_intg_t *intg; + + intg = kzalloc(sizeof(*intg), GFP_KERNEL); + if (!intg) + return NULL; + + /* P1023 - Major 4 +* P4080 - Major 2 +* P2041/P3041/P5020/P5040 - Major 3 +* Tx/Bx - Major 6 +*/ + + switch (major) { + case FM_IP_BLOCK_P2_P3_P5: + intg-fm_muram_size = 160 * 1024; + intg-fm_iram_size = 64 * 1024; + intg-fm_num_of_ctrl= 2; + + intg-dma_thresh_max_commq = 31; + intg-dma_thresh_max_buf= 127; + + intg-qmi_max_num_of_tnums = 64; + intg-qmi_def_tnums_thresh = 48; + +
Re: GPMC in device tree
On Wed, Aug 5, 2015 at 9:11 AM, Ran Shalit ransha...@gmail.com wrote: On Wed, Aug 5, 2015 at 6:56 AM, Ran Shalit ransha...@gmail.com wrote: On Wed, Aug 5, 2015 at 12:25 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 00:22 +0300, Ran Shalit wrote: On Tue, Aug 4, 2015 at 11:31 PM, Scott Wood scottw...@freescale.com wrote: On Tue, 2015-08-04 at 23:26 +0300, Ran Shalit wrote: On Tue, Aug 4, 2015 at 9:54 PM, Scott Wood scottw...@freescale.com wrote: On Tue, 2015-08-04 at 18:29 +0300, Ran Shalit wrote: Hello, I would please like to ask if describing flash nor used with GPMC, whould be done as described in: https://www.kernel.org/doc/Documentation/devicetree/bindings/mtd/gpmc-nor.txt It is described in the above link as TI's GPMC, so I'm not sure if it is relevent for powerpc too. That binding is for TI GPMC. Are you saying you have some PPC chip that has a flash controller called GPMC? -Scott Hi Scott, Thanks, I've worked with TI's chips, so I now understand that I made here some confusion... It is GPCM , not GPMC, my mistake. We already configured it in u-boot, but on doing read/write from kernel it doesn not work. It seems that for the linux to use the correct driver, we need to define the nor in the device tree. Is there any example how to define nor GPCM in device tree ? Is it possible not to override the existing GPCM configuration ? Pretty much all of the mpc8xxx/qoriq device trees have GPCM NOR defined. See Documentation/devicetree/bindings/powerpc/fsl/lbc.txt and examples such as arch/powerpc/boot/dts/p4080ds.dts (part of the lbc node is in arch/powerpc/boot/dts/fsl/p4080si-post.dtsi). Linux will not change the GPCM configuration. -Scott On more thing, if I may. The localbus is also connected to nvram cpld. I've noticed that read/write works well, even though I didn't define anything in device tree. Is there any reasom to add these devices into device tree, or can we use the cpld and nvram without the definition in device tree ? I don't know what you're doing in your kernel to access devices that aren't in the device tree. You should add the devices to the device tree, and have the kernel use it rather than hardcoded info. -Scott Hi, Yes I understand. But It is worse noting that I have no localbus entry in the device tree. Yes, The nvram, cpld which are both connected to device tree, seems to work without any issues. Thanks, Ran I apologyze for the bad english, I meant it worth to note that there is no localbus entry at all in the device tree. So I wander how the nvram and cpld worked... If I may please ask, what should be the compatible for generic devices such as nvram/cpld ? I assume that if they worked without any entry, it means that there is no need for specific driver. Regards, Ran Hi, After studing the localbus configuration as should be configured in device tree for powerpc, I think I have come with the following configuration, (not yet tested on board): localbus@e0005000 { #address-cells = 2; #size-cells = 1; compatible = fsl,mpc8349-localbus, simple-bus; reg = 0xe0005000 0x1000; interrupts = 77 0x8; interrupt-parent = ipic; /* NOR and NAND Flashes */ ranges = 0x0 0x0 0xff80 0x0080 /* 8MB NOR Flash */ 0x1 0x0 0xF800 0x0800 /* User flash (same nor, in burst mode) 128M */ 0x2 0x0 0xf7e0 0x0020;/*NVRAM/CPLD C2 is selected in CPLD , */ /*nvram 0xf7e0 1MB */ /*cpld 0xf7f0 1M (- different address!)*/ nor@0,0 { #address-cells = 1; #size-cells = 1; compatible = cfi-flash; reg = 0x0 0x0 0x100; #bank-width = 1; device-width = 4; }; }; I have some isssue I'm not sure about, and wanted a second opinion: 1. I have not added entry for NVRAM/CPLD (8 bit width interfaces) , but only specifies it in ranges , I assume it is not required becuase it is probably can be treated as simple ram. Is this assumption correct ? 2. The NVRAM/CPLD is using CS2 , which is configured for 2 MB space. The 2 MB is divided to two 1 MB slices. 1 MB is dedicated for NVRAM (though the NVRAM is only 128 KB) and 1 MB is dedicated for CPLD. The division of CS2 into two regions is done in CPLD. 0xf7e0 - for NVRAM , 0x0010 0xf7f0 - for CPLD , 0x0010 Is it correct to be configured as one range as done above (0x2 0x0 0xf7e0 0x0020) ? Thank you very much, Ran ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/6][RESEND] ASoC: fsl_ssi: enable IPG clock during AC'97 reg access
IPG clock have to be enabled during AC'97 CODEC register access in fsl_ssi driver. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- This is a resend without changes, to keep the whole series together. sound/soc/fsl/fsl_ssi.c | 19 +++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 484ff20..8185edc 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1127,10 +1127,17 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, struct regmap *regs = fsl_ac97_data-regs; unsigned int lreg; unsigned int lval; + int ret; if (reg 0x7f) return; + ret = clk_prepare_enable(fsl_ac97_data-clk); + if (ret) { + pr_err(ac97 write clk_prepare_enable failed: %d\n, + ret); + return; + } lreg = reg 12; regmap_write(regs, CCSR_SSI_SACADD, lreg); @@ -1141,6 +1148,8 @@ static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, regmap_update_bits(regs, CCSR_SSI_SACNT, CCSR_SSI_SACNT_RDWR_MASK, CCSR_SSI_SACNT_WR); udelay(100); + + clk_disable_unprepare(fsl_ac97_data-clk); } static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, @@ -1151,6 +1160,14 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, unsigned short val = -1; u32 reg_val; unsigned int lreg; + int ret; + + ret = clk_prepare_enable(fsl_ac97_data-clk); + if (ret) { + pr_err(ac97 read clk_prepare_enable failed: %d\n, + ret); + return -1; + } lreg = (reg 0x7f) 12; regmap_write(regs, CCSR_SSI_SACADD, lreg); @@ -1162,6 +1179,8 @@ static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97, regmap_read(regs, CCSR_SSI_SACDAT, reg_val); val = (reg_val 4) 0x; + clk_disable_unprepare(fsl_ac97_data-clk); + return val; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/6][RESEND] ASoC: fsl_ssi: AC'97 DAI driver needs probe method too
AC'97 DAI driver struct need the same probe method as I2S one to setup DMA params in fsl_ssi driver. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- This is a resend without changes, to keep the whole series together. sound/soc/fsl/fsl_ssi.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 8185edc..a83b900 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1101,6 +1101,7 @@ static const struct snd_soc_component_driver fsl_ssi_component = { static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { .bus_control = true, + .probe = fsl_ssi_dai_probe, .playback = { .stream_name = AC97 Playback, .channels_min = 2, ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/6][RESEND] ASoC: fsl_ssi: enable AC'97 asymmetric rates
AC'97 bus can support asymmetric playback/capture rates so enable them in this case in fsl_ssi driver. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- This is a resend without changes, to keep the whole series together. sound/soc/fsl/fsl_ssi.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index a83b900..7f4f0b9 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1377,7 +1377,9 @@ static int fsl_ssi_probe(struct platform_device *pdev) /* Are the RX and the TX clocks locked? */ if (!of_find_property(np, fsl,ssi-asynchronous, NULL)) { - ssi_private-cpu_dai_drv.symmetric_rates = 1; + if (!fsl_ssi_is_ac97(ssi_private)) + ssi_private-cpu_dai_drv.symmetric_rates = 1; + ssi_private-cpu_dai_drv.symmetric_channels = 1; ssi_private-cpu_dai_drv.symmetric_samplebits = 1; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 5/6][RESEND] ASoC: fsl_ssi: instantiate AC'97 CODEC
Instantiate AC'97 CODEC in fsl_ssi driver AC'97 mode. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- This is a resend without changes, to keep the whole series together. sound/soc/fsl/fsl_ssi.c | 21 + 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 154bcf6..8e5ff5e 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1460,6 +1460,27 @@ done: _fsl_ssi_set_dai_fmt(pdev-dev, ssi_private, ssi_private-dai_fmt); + if (fsl_ssi_is_ac97(ssi_private)) { + u32 ssi_idx; + + ret = of_property_read_u32(np, cell-index, ssi_idx); + if (ret) { + dev_err(pdev-dev, cannot get SSI index property\n); + goto error_sound_card; + } + + ssi_private-pdev = + platform_device_register_data(NULL, + ac97-codec, ssi_idx, NULL, 0); + if (IS_ERR(ssi_private-pdev)) { + ret = PTR_ERR(ssi_private-pdev); + dev_err(pdev-dev, + failed to register AC97 codec platform: %d\n, + ret); + goto error_sound_card; + } + } + return 0; error_sound_card: ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 6/6 v2][RESEND] ASoC: fsl_ssi: adjust set DAI format in AC'97 mode
Adjust set DAI format function in fsl_ssi driver so it doesn't fail and clears RXDIR in AC'97 mode. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- Changes from v1: fix indentation to be consistent with rest of the driver. sound/soc/fsl/fsl_ssi.c |8 +--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 8e5ff5e..1ba63bd 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -900,14 +900,16 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, scr = ~CCSR_SSI_SCR_SYS_CLK_EN; break; default: - return -EINVAL; + if (!fsl_ssi_is_ac97(ssi_private)) + return -EINVAL; } stcr |= strcr; srcr |= strcr; - if (ssi_private-cpu_dai_drv.symmetric_rates) { - /* Need to clear RXDIR when using SYNC mode */ + if (ssi_private-cpu_dai_drv.symmetric_rates + || fsl_ssi_is_ac97(ssi_private)) { + /* Need to clear RXDIR when using SYNC or AC97 mode */ srcr = ~CCSR_SSI_SRCR_RXDIR; scr |= CCSR_SSI_SCR_SYN; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/6][RESEND] ASoC: fsl_ssi: add AC'97 ops setting check and cleanup
Check whether setting AC'97 ops succeeded and clean them on removal so the fsl_ssi driver can be reloaded. Signed-off-by: Maciej Szmigiero m...@maciej.szmigiero.name --- This is a resend without changes, to keep the whole series together. sound/soc/fsl/fsl_ssi.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 7f4f0b9..154bcf6 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1340,7 +1340,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) fsl_ac97_data = ssi_private; - snd_soc_set_ac97_ops_of_reset(fsl_ssi_ac97_ops, pdev); + ret = snd_soc_set_ac97_ops_of_reset(fsl_ssi_ac97_ops, pdev); + if (ret) { + dev_err(pdev-dev, could not set AC'97 ops\n); + return ret; + } } else { /* Initialize this copy of the CPU DAI driver structure */ memcpy(ssi_private-cpu_dai_drv, fsl_ssi_dai_template, @@ -1480,6 +1484,9 @@ static int fsl_ssi_remove(struct platform_device *pdev) if (ssi_private-soc-imx) fsl_ssi_imx_clean(pdev, ssi_private); + if (fsl_ssi_is_ac97(ssi_private)) + snd_soc_set_ac97_ops(NULL); + return 0; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v2 0/9] dpaa_eth: Add the Freescale DPAA Ethernet driver
This patch series adds the Ethernet driver for the Freescale QorIQ Data Path Acceleration Architecture (DPAA). This version includes changes following the feedback received on previous versions from Eric Dumazet, Bob Cochran, Joe Perches, Paul Bolle, Joakim Tjernlund, Scott Wood, David Miller - thanks! Together with the driver a managed version of alloc_percpu is provided that simplifies the release of percpu memory. The Freescale DPAA architecture consists in a series of hardware blocks that support the Ethernet connectivity. The Ethernet driver depends upon the following drivers that are currently in the Linux kernel or in review: - Peripheral Access Memory Unit (PAMU) drivers/iommu/fsl_* - Frame Manager (FMan) drivers/net/ethernet/freescale/fman - Queue Manager (QMan), Buffer Manager (BMan) drivers/soc/fsl/qbman The latest FMan driver patches were submitted by Igal Liberman: https://patchwork.ozlabs.org/project/netdev/list/?submitter=64715state=*q=[v4, The latest Q/BMan drivers were submitted by Roy Pledge: https://patchwork.ozlabs.org/project/linuxppc-dev/list/?submitter=66331state=* Changes from v1: - bpool level Kconfig options removed - print format using pr_fmt, cleaned up prints - __hot/__cold removed - gratuitous unlikely() removed - code style aligned, consistent spacing for declarations - comment formatting The complete patch set based on the v4.2-rc5 kernel can be found in the public git http://git.freescale.com/git/cgit.cgi/ppc/upstream/linux.git under the tag ldup_public_git_20150805: http://git.freescale.com/git/cgit.cgi/ppc/upstream/linux.git/log/?h=ldup_public_git_20150805 There is one patch that needs to be applied to u-boot to align it to the latest device tree binding document specification used by the FMan driver. The patch is under the ldup_public_git_20150410 tag in the public git at: http://git.freescale.com/git/cgit.cgi/ppc/upstream/u-boot.git/log/?h=ldup_public_git_20150410 Madalin Bucur (9): devres: add devm_alloc_percpu() dpaa_eth: add support for DPAA Ethernet dpaa_eth: add support for S/G frames dpaa_eth: add driver's Tx queue selection mechanism dpaa_eth: add ethtool functionality dpaa_eth: add sysfs exports dpaa_eth: add debugfs counters dpaa_eth: add debugfs entries dpaa_eth: add trace points Documentation/driver-model/devres.txt |4 + drivers/base/devres.c | 64 + drivers/net/ethernet/freescale/Kconfig |2 + drivers/net/ethernet/freescale/Makefile|1 + drivers/net/ethernet/freescale/dpaa/Kconfig| 63 + drivers/net/ethernet/freescale/dpaa/Makefile | 17 + drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c | 272 drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.h | 43 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 860 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 489 +++ .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 1358 .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 129 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c | 704 ++ .../net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c | 167 +++ .../net/ethernet/freescale/dpaa/dpaa_eth_trace.h | 141 ++ drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 230 include/linux/device.h | 19 + 17 files changed, 4563 insertions(+) create mode 100644 drivers/net/ethernet/freescale/dpaa/Kconfig create mode 100644 drivers/net/ethernet/freescale/dpaa/Makefile create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v2 1/9] devres: add devm_alloc_percpu()
Introduce managed counterparts for alloc_percpu() and free_percpu(). Add devm_alloc_percpu() and devm_free_percpu() into the managed interfaces list. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- Documentation/driver-model/devres.txt | 4 +++ drivers/base/devres.c | 64 +++ include/linux/device.h| 19 +++ 3 files changed, 87 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 831a536..595fd1b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -312,6 +312,10 @@ MEM devm_kvasprintf() devm_kzalloc() +PER-CPU MEM + devm_alloc_percpu() + devm_free_percpu() + PCI pcim_enable_device() : after success, all PCI ops become managed pcim_pin_device(): keep PCI device enabled after release diff --git a/drivers/base/devres.c b/drivers/base/devres.c index c8a53d1..deb2ea0 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -10,6 +10,7 @@ #include linux/device.h #include linux/module.h #include linux/slab.h +#include linux/percpu.h #include base.h @@ -984,3 +985,66 @@ void devm_free_pages(struct device *dev, unsigned long addr) devres)); } EXPORT_SYMBOL_GPL(devm_free_pages); + +static void devm_percpu_release(struct device *dev, void *pdata) +{ + void __percpu *p; + + p = *(void __percpu **)pdata; + free_percpu(p); +} + +static int devm_percpu_match(struct device *dev, void *data, void *p) +{ + struct devres *devr = container_of(data, struct devres, data); + + return *(void **)devr-data == p; +} + +/** + * __devm_alloc_percpu - Resource-managed alloc_percpu + * @dev: Device to allocate per-cpu memory for + * @size: Size of per-cpu memory to allocate + * @align: Alignement of per-cpu memory to allocate + * + * Managed alloc_percpu. Per-cpu memory allocated with this function is + * automatically freed on driver detach. + * + * RETURNS: + * Pointer to allocated memory on success, NULL on failure. + */ +void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, + size_t align) +{ + void *p; + void __percpu *pcpu; + + pcpu = __alloc_percpu(size, align); + if (!pcpu) + return NULL; + + p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL); + if (!p) + return NULL; + + *(void __percpu **)p = pcpu; + + devres_add(dev, p); + + return pcpu; +} +EXPORT_SYMBOL_GPL(__devm_alloc_percpu); + +/** + * devm_free_percpu - Resource-managed free_percpu + * @dev: Device this memory belongs to + * @pdata: Per-cpu memory to free + * + * Free memory allocated with devm_alloc_percpu(). + */ +void devm_free_percpu(struct device *dev, void __percpu *pdata) +{ + WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match, + (void *)pdata)); +} +EXPORT_SYMBOL_GPL(devm_free_percpu); diff --git a/include/linux/device.h b/include/linux/device.h index a2b4ea7..126c25b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -673,6 +673,25 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); int devm_add_action(struct device *dev, void (*action)(void *), void *data); void devm_remove_action(struct device *dev, void (*action)(void *), void *data); +/** + * devm_alloc_percpu - Resource-managed alloc_percpu + * @dev: Device to allocate per-cpu memory for + * @type: Type to allocate per-cpu memory for + * + * Managed alloc_percpu. Per-cpu memory allocated with this function is + * automatically freed on driver detach. + * + * RETURNS: + * Pointer to allocated memory on success, NULL on failure. + */ +#define devm_alloc_percpu(dev, type) \ + (typeof(type) __percpu *)__devm_alloc_percpu(dev, sizeof(type), \ +__alignof__(type)) + +void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, + size_t align); +void devm_free_percpu(struct device *dev, void __percpu *pdata); + struct device_dma_parameters { /* * a low level driver may set these to teach IOMMU code about -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v2 3/9] dpaa_eth: add support for S/G frames
Add support for Scater/Gather (S/G) frames. The FMan can place the frame content into multiple buffers and provide a S/G Table (SGT) into one first buffer with references to the others. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 6 + .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 47 ++- .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 2 + drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c | 335 +++-- 4 files changed, 370 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 9e83bd1..53c37cd 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -460,6 +460,12 @@ static int dpa_private_netdev_init(struct net_device *net_dev) net_dev-hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_LLTX); + /* Advertise S/G and HIGHDMA support for private interfaces */ + net_dev-hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA; + /* Recent kernels enable GSO automatically, if +* we declare NETIF_F_SG. For conformity, we'll +* still declare GSO explicitly. +*/ net_dev-features |= NETIF_F_GSO; return dpa_netdev_init(net_dev, mac_addr, tx_timeout); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index 10f08f7..7e4b9bd 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c @@ -1122,6 +1122,35 @@ void dpaa_eth_init_ports(struct mac_device *mac_dev, port_fqs-rx_defq, buf_layout[RX]); } +void dpa_release_sgt(struct qm_sg_entry *sgt) +{ + struct dpa_bp *dpa_bp; + struct bm_buffer bmb[DPA_BUFF_RELEASE_MAX]; + u8 i = 0, j; + + memset(bmb, 0, sizeof(bmb)); + + do { + dpa_bp = dpa_bpid2pool(sgt[i].bpid); + DPA_ERR_ON(!dpa_bp); + + j = 0; + do { + DPA_ERR_ON(sgt[i].extension); + + bmb[j].hi = sgt[i].addr_hi; + bmb[j].lo = sgt[i].addr_lo; + + j++; i++; + } while (j ARRAY_SIZE(bmb) + !sgt[i - 1].final + sgt[i - 1].bpid == sgt[i].bpid); + + while (bman_release(dpa_bp-pool, bmb, j, 0)) + cpu_relax(); + } while (!sgt[i - 1].final); +} + void __attribute__((nonnull)) dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) { @@ -1137,7 +1166,23 @@ dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) dpa_bp = dpa_bpid2pool(fd-bpid); DPA_ERR_ON(!dpa_bp); - DPA_ERR_ON(fd-format == qm_fd_sg); + if (fd-format == qm_fd_sg) { + vaddr = phys_to_virt(fd-addr); + sgt = vaddr + dpa_fd_offset(fd); + + dma_unmap_single(dpa_bp-dev, qm_fd_addr(fd), dpa_bp-size, +DMA_BIDIRECTIONAL); + + dpa_release_sgt(sgt); + + addr = dma_map_single(dpa_bp-dev, vaddr, dpa_bp-size, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dpa_bp-dev, addr)) { + dev_err(dpa_bp-dev, DMA mapping failed); + return; + } + bm_buffer_set64(bmb, addr); + } while (bman_release(dpa_bp-pool, bmb, 1, 0)) cpu_relax(); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h index 93fcf82..bd88dda 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h @@ -52,6 +52,7 @@ fm_set_##type##_port_params(port, param); \ } +#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ #define DPA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */ /* used in napi related functions */ @@ -109,6 +110,7 @@ void dpaa_eth_init_ports(struct mac_device *mac_dev, struct fm_port_fqs *port_fqs, struct dpa_buffer_layout_s *buf_layout, struct device *dev); +void dpa_release_sgt(struct qm_sg_entry *sgt); void __attribute__((nonnull)) dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd); int dpa_enable_tx_csum(struct dpa_priv_s *priv, diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c index 15713a6..6050448 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c @@ -53,6 +53,31 @@
[v2 2/9] dpaa_eth: add support for DPAA Ethernet
This introduces the Freescale Data Path Acceleration Architecture (DPAA) Ethernet driver (dpaa_eth) that builds upon the DPAA QMan, BMan, PAMU and FMan drivers to deliver Ethernet connectivity on the Freescale DPAA QorIQ platforms. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/Kconfig |2 + drivers/net/ethernet/freescale/Makefile|1 + drivers/net/ethernet/freescale/dpaa/Kconfig| 46 + drivers/net/ethernet/freescale/dpaa/Makefile | 13 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 814 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 442 +++ .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 1248 .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 118 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c | 406 +++ 9 files changed, 3090 insertions(+) create mode 100644 drivers/net/ethernet/freescale/dpaa/Kconfig create mode 100644 drivers/net/ethernet/freescale/dpaa/Makefile create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index f3f89cc..92198be 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -92,4 +92,6 @@ config GIANFAR and MPC86xx family of chips, the eTSEC on LS1021A and the FEC on the 8540. +source drivers/net/ethernet/freescale/dpaa/Kconfig + endif # NET_VENDOR_FREESCALE diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 4097c58..ae13dc5 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet/ obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o obj-$(CONFIG_GIANFAR) += gianfar_driver.o +obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/ obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig new file mode 100644 index 000..1f3a203 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/Kconfig @@ -0,0 +1,46 @@ +menuconfig FSL_DPAA_ETH + tristate DPAA Ethernet + depends on FSL_SOC FSL_BMAN FSL_QMAN FSL_FMAN + select PHYLIB + select FSL_FMAN_MAC + ---help--- + Data Path Acceleration Architecture Ethernet driver, + supporting the Freescale QorIQ chips. + Depends on Freescale Buffer Manager and Queue Manager + driver and Frame Manager Driver. + +if FSL_DPAA_ETH + +config FSL_DPAA_CS_THRESHOLD_1G + hex Egress congestion threshold on 1G ports + range 0x1000 0x1000 + default 0x0600 + ---help--- + The size in bytes of the egress Congestion State notification threshold on 1G ports. + The 1G dTSECs can quite easily be flooded by cores doing Tx in a tight loop + (e.g. by sending UDP datagrams at while(1) speed), + and the larger the frame size, the more acute the problem. + So we have to find a balance between these factors: + - avoiding the device staying congested for a prolonged time (risking + the netdev watchdog to fire - see also the tx_timeout module param); + - affecting performance of protocols such as TCP, which otherwise +behave well under the congestion notification mechanism; + - preventing the Tx cores from tightly-looping (as if the congestion +threshold was too low to be effective); + - running out of memory if the CS threshold is set too high. + +config FSL_DPAA_CS_THRESHOLD_10G + hex Egress congestion threshold on 10G ports + range 0x1000 0x2000 + default 0x1000 + ---help --- + The size in bytes of the egress Congestion State notification threshold on 10G ports. + +config FSL_DPAA_INGRESS_CS_THRESHOLD + hex Ingress congestion threshold on FMan ports + default 0x1000 + ---help--- + The size in bytes of the ingress tail-drop threshold on FMan ports. + Traffic piling up above this value will be rejected by QMan and discarded by FMan. + +endif # FSL_DPAA_ETH diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile new file mode 100644 index 000..cf126dd --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for the
[v2 4/9] dpaa_eth: add driver's Tx queue selection mechanism
Allow the selection of the transmission queue based on the CPU id. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/Kconfig | 10 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth.c| 3 +++ drivers/net/ethernet/freescale/dpaa/dpaa_eth.h| 6 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c | 8 drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h | 4 5 files changed, 31 insertions(+) diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig index 1f3a203..6147403 100644 --- a/drivers/net/ethernet/freescale/dpaa/Kconfig +++ b/drivers/net/ethernet/freescale/dpaa/Kconfig @@ -11,6 +11,16 @@ menuconfig FSL_DPAA_ETH if FSL_DPAA_ETH +config FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE + bool Use driver's Tx queue selection mechanism + default y + ---help--- + The DPAA-Ethernet driver defines a ndo_select_queue() callback for optimal selection + of the egress FQ. That will override the XPS support for this netdevice. + If for whatever reason you want to be in control of the egress FQ-to-CPU selection and mapping, + or simply don't want to use the driver's ndo_select_queue() callback, then unselect this + and use the standard XPS support instead. + config FSL_DPAA_CS_THRESHOLD_1G hex Egress congestion threshold on 1G ports range 0x1000 0x1000 diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 53c37cd..264945c 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -387,6 +387,9 @@ static const struct net_device_ops dpa_private_ops = { .ndo_get_stats64 = dpa_get_stats64, .ndo_set_mac_address = dpa_set_mac_address, .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE + .ndo_select_queue = dpa_select_queue, +#endif .ndo_change_mtu = dpa_change_mtu, .ndo_set_rx_mode = dpa_set_rx_mode, .ndo_init = dpa_ndo_init, diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index d337dcc..55c1106 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -430,9 +430,15 @@ static inline void _dpa_assign_wq(struct dpa_fq *fq) } } +#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE +/* Use in lieu of skb_get_queue_mapping() */ +#define dpa_get_queue_mapping(skb) \ + raw_smp_processor_id() +#else /* Use the queue selected by XPS */ #define dpa_get_queue_mapping(skb) \ skb_get_queue_mapping(skb) +#endif static inline void _dpa_bp_free_pf(void *addr) { diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index 7e4b9bd..1258683 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c @@ -586,6 +586,14 @@ bool dpa_bpid2pool_use(int bpid) return false; } +#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE +u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb, +void *accel_priv, select_queue_fallback_t fallback) +{ + return dpa_get_queue_mapping(skb); +} +#endif + struct dpa_fq *dpa_fq_alloc(struct device *dev, const struct fqid_cell *fqids, struct list_head *list, diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h index bd88dda..4581bfc 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h @@ -88,6 +88,10 @@ struct dpa_bp *dpa_bpid2pool(int bpid); void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp); bool dpa_bpid2pool_use(int bpid); void dpa_bp_drain(struct dpa_bp *bp); +#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE +u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb, +void *accel_priv, select_queue_fallback_t fallback); +#endif struct dpa_fq *dpa_fq_alloc(struct device *dev, const struct fqid_cell *fqids, struct list_head *list, -- 1.7.11.7 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[v2 6/9] dpaa_eth: add sysfs exports
Export Frame Queue and Buffer Pool IDs through sysfs. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/Makefile | 2 +- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 3 + .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 2 + .../net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c | 167 + 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile index e137146..3a276d5 100644 --- a/drivers/net/ethernet/freescale/dpaa/Makefile +++ b/drivers/net/ethernet/freescale/dpaa/Makefile @@ -10,4 +10,4 @@ ccflags-y += -I$(FMAN)/flib obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o -fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o dpaa_ethtool.o +fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o dpaa_ethtool.o dpaa_eth_sysfs.o diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 264945c..a1183f4 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -739,6 +739,8 @@ dpaa_eth_priv_probe(struct platform_device *pdev) if (err 0) goto netdev_init_failed; + dpaa_eth_sysfs_init(net_dev-dev); + pr_info(Probed interface %s\n, net_dev-name); return 0; diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index 55c1106..2a0ecf3 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -344,6 +344,9 @@ static inline u16 dpa_get_headroom(struct dpa_buffer_layout_s *bl) return bl-data_align ? ALIGN(headroom, bl-data_align) : headroom; } +void dpaa_eth_sysfs_remove(struct device *dev); +void dpaa_eth_sysfs_init(struct device *dev); + void dpa_private_napi_del(struct net_device *net_dev); static inline void clear_fd(struct qm_fd *fd) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index ca6831a..1e43fe5 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c @@ -279,6 +279,8 @@ int dpa_remove(struct platform_device *pdev) priv = netdev_priv(net_dev); + dpaa_eth_sysfs_remove(dev); + dev_set_drvdata(dev, NULL); unregister_netdev(net_dev); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c new file mode 100644 index 000..a6c71b1 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c @@ -0,0 +1,167 @@ +/* Copyright 2008-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include linux/init.h +#include linux/module.h +#include linux/kthread.h +#include linux/io.h +#include linux/of_net.h +#include dpaa_eth.h +#include mac.h + +static ssize_t dpaa_eth_show_addr(struct device *dev, +
[v2 8/9] dpaa_eth: add debugfs entries
Export per CPU counters through debugfs. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/Kconfig| 7 + drivers/net/ethernet/freescale/dpaa/Makefile | 3 + drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c | 272 + drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.h | 43 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 11 + .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 17 ++ 6 files changed, 353 insertions(+) create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.h diff --git a/drivers/net/ethernet/freescale/dpaa/Kconfig b/drivers/net/ethernet/freescale/dpaa/Kconfig index 6147403..98c6328 100644 --- a/drivers/net/ethernet/freescale/dpaa/Kconfig +++ b/drivers/net/ethernet/freescale/dpaa/Kconfig @@ -53,4 +53,11 @@ config FSL_DPAA_INGRESS_CS_THRESHOLD The size in bytes of the ingress tail-drop threshold on FMan ports. Traffic piling up above this value will be rejected by QMan and discarded by FMan. +config FSL_DPAA_ETH_DEBUGFS + bool DPAA Ethernet debugfs interface + depends on DEBUG_FS + default y + ---help--- + This option compiles debugfs code for the DPAA Ethernet driver. + endif # FSL_DPAA_ETH diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile index 3a276d5..3427de4 100644 --- a/drivers/net/ethernet/freescale/dpaa/Makefile +++ b/drivers/net/ethernet/freescale/dpaa/Makefile @@ -11,3 +11,6 @@ ccflags-y += -I$(FMAN)/flib obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o dpaa_ethtool.o dpaa_eth_sysfs.o +ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) +fsl_dpa-objs += dpaa_debugfs.o +endif diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c b/drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c new file mode 100644 index 000..bd426f0 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_debugfs.c @@ -0,0 +1,272 @@ +/* Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME : fmt + +#include linux/module.h +#include soc/fsl/qman.h +#include linux/debugfs.h +#include asm/debug.h +#include dpaa_debugfs.h +#include dpaa_eth.h + +#define DPA_DEBUGFS_DESCRIPTION FSL DPAA Ethernet debugfs entries +#define DPA_ETH_DEBUGFS_ROOT fsl_dpa + +static int dpa_debugfs_open(struct inode *inode, struct file *file); + +static struct dentry *dpa_debugfs_root; +static const struct file_operations dpa_debugfs_fops = { + .open = dpa_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release= single_release, +}; + +static int dpa_debugfs_show(struct seq_file *file, void *offset) +{ + int i; + struct dpa_priv_s *priv; + struct dpa_percpu_priv_s *percpu_priv, total; + struct dpa_bp *dpa_bp; + unsigned int dpa_bp_count = 0; + unsigned int count_total = 0; + struct qm_mcr_querycgr query_cgr; + + BUG_ON(!offset); + + priv = netdev_priv((struct net_device *)file-private); + +
[v2 5/9] dpaa_eth: add ethtool functionality
Add support for basic ethtool operations. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/Makefile | 2 +- .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 2 + .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 3 + drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 230 + 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile index cf126dd..e137146 100644 --- a/drivers/net/ethernet/freescale/dpaa/Makefile +++ b/drivers/net/ethernet/freescale/dpaa/Makefile @@ -10,4 +10,4 @@ ccflags-y += -I$(FMAN)/flib obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o -fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o +fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o dpaa_ethtool.o diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index 1258683..ca6831a 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c @@ -81,6 +81,8 @@ int dpa_netdev_init(struct net_device *net_dev, memcpy(net_dev-perm_addr, mac_addr, net_dev-addr_len); memcpy(net_dev-dev_addr, mac_addr, net_dev-addr_len); + net_dev-ethtool_ops = dpa_ethtool_ops; + net_dev-needed_headroom = priv-tx_headroom; net_dev-watchdog_timeo = msecs_to_jiffies(tx_timeout); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h index 4581bfc..a940561 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.h @@ -58,6 +58,9 @@ /* used in napi related functions */ extern u16 qman_portal_max; +/* from dpa_ethtool.c */ +extern const struct ethtool_ops dpa_ethtool_ops; + int dpa_netdev_init(struct net_device *net_dev, const u8 *mac_addr, u16 tx_timeout); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c new file mode 100644 index 000..069fcf1 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -0,0 +1,230 @@ +/* Copyright 2008-2015 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME : fmt + +#include linux/string.h + +#include dpaa_eth.h +#include mac.h +#include dpaa_eth_common.h + +static int dpa_get_settings(struct net_device *net_dev, + struct ethtool_cmd *et_cmd) +{ + int err; + struct dpa_priv_s *priv; + + priv = netdev_priv(net_dev); + + if (!priv-mac_dev-phy_dev) { + netdev_dbg(net_dev, phy device not initialized\n); + return 0; + } + + err = phy_ethtool_gset(priv-mac_dev-phy_dev, et_cmd); + + return err; +} + +static int dpa_set_settings(struct net_device *net_dev, + struct ethtool_cmd *et_cmd) +{ + int err; + struct dpa_priv_s *priv; + + priv =
[v2 7/9] dpaa_eth: add debugfs counters
Add a series of counters to be exported through debugfs: - add detailed counters for reception errors; - add detailed counters for QMan enqueue reject events; - count the number of fragmented skbs received from the stack; - count all frames received on the Tx confirmation path; - add congestion group statistics; - count the number of interrupts for each CPU. Signed-off-by: Madalin Bucur madalin.bu...@freescale.com --- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 12 +++ drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 34 ++ .../net/ethernet/freescale/dpaa/dpaa_eth_common.c | 40 -- .../net/ethernet/freescale/dpaa/dpaa_eth_common.h | 2 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth_sg.c | 1 + 5 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index a1183f4..008562b 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -98,6 +98,15 @@ static void _dpa_rx_error(struct net_device *net_dev, percpu_priv-stats.rx_errors++; + if (fd-status FM_PORT_FRM_ERR_DMA) + percpu_priv-rx_errors.dme++; + if (fd-status FM_PORT_FRM_ERR_PHYSICAL) + percpu_priv-rx_errors.fpe++; + if (fd-status FM_PORT_FRM_ERR_SIZE) + percpu_priv-rx_errors.fse++; + if (fd-status FM_PORT_FRM_ERR_PRS_HDR_ERR) + percpu_priv-rx_errors.phe++; + dpa_fd_release(net_dev, fd); } @@ -161,6 +170,8 @@ static void _dpa_tx_conf(struct net_device *net_dev, percpu_priv-stats.tx_errors++; } + percpu_priv-tx_confirm++; + skb = _dpa_cleanup_tx_fd(priv, fd); dev_kfree_skb(skb); @@ -296,6 +307,7 @@ static void priv_ern(struct qman_portal *portal, percpu_priv-stats.tx_dropped++; percpu_priv-stats.tx_fifo_errors++; + count_ern(percpu_priv, msg); /* If we intended this buffer to go into the pool * when the FM was done, we need to put it in diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index 2a0ecf3..c66140e 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -194,6 +194,25 @@ struct dpa_bp { void (*free_buf_cb)(void *addr); }; +struct dpa_rx_errors { + u64 dme;/* DMA Error */ + u64 fpe;/* Frame Physical Error */ + u64 fse;/* Frame Size Error */ + u64 phe;/* Header Error */ +}; + +/* Counters for QMan ERN frames - one counter per rejection code */ +struct dpa_ern_cnt { + u64 cg_tdrop; /* Congestion group taildrop */ + u64 wred; /* WRED congestion */ + u64 err_cond; /* Error condition */ + u64 early_window; /* Order restoration, frame too early */ + u64 late_window;/* Order restoration, frame too late */ + u64 fq_tdrop; /* FQ taildrop */ + u64 fq_retired; /* FQ is retired */ + u64 orp_zero; /* ORP disabled */ +}; + struct dpa_napi_portal { struct napi_struct napi; struct qman_portal *p; @@ -202,7 +221,13 @@ struct dpa_napi_portal { struct dpa_percpu_priv_s { struct net_device *net_dev; struct dpa_napi_portal *np; + u64 in_interrupt; + u64 tx_confirm; + /* fragmented (non-linear) skbuffs received from the stack */ + u64 tx_frag_skbuffs; struct rtnl_link_stats64 stats; + struct dpa_rx_errors rx_errors; + struct dpa_ern_cnt ern_cnt; }; struct dpa_priv_s { @@ -233,6 +258,14 @@ struct dpa_priv_s { * (and the same) congestion group. */ struct qman_cgr cgr; + /* If congested, when it began. Used for performance stats. */ + u32 congestion_start_jiffies; + /* Number of jiffies the Tx port was congested. */ + u32 congested_jiffies; + /* Counter for the number of times the CGR +* entered congestion state +*/ + u32 cgr_congested_count; } cgr_data; /* Use a per-port CGR for ingress traffic. */ bool use_ingress_cgr; @@ -294,6 +327,7 @@ static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv, np-p = portal; napi_schedule(np-napi); + percpu_priv-in_interrupt++; return 1; } } diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c index 1e43fe5..459132b 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_common.c +++
[v2 9/9] dpaa_eth: add trace points
Add trace points on the hot processing path. Signed-off-by: Ruxandra Ioana Radulescu ruxandra.radule...@freescale.com --- drivers/net/ethernet/freescale/dpaa/Makefile | 1 + drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 12 ++ drivers/net/ethernet/freescale/dpaa/dpaa_eth.h | 4 + .../net/ethernet/freescale/dpaa/dpaa_eth_trace.h | 141 + 4 files changed, 158 insertions(+) create mode 100644 drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h diff --git a/drivers/net/ethernet/freescale/dpaa/Makefile b/drivers/net/ethernet/freescale/dpaa/Makefile index 3427de4..bf7248a 100644 --- a/drivers/net/ethernet/freescale/dpaa/Makefile +++ b/drivers/net/ethernet/freescale/dpaa/Makefile @@ -11,6 +11,7 @@ ccflags-y += -I$(FMAN)/flib obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o fsl_dpa-objs += dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o dpaa_ethtool.o dpaa_eth_sysfs.o +CFLAGS_dpaa_eth.o := -I$(src) ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) fsl_dpa-objs += dpaa_debugfs.o endif diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index ea25bf1..7f2413b 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -61,6 +61,12 @@ #include dpaa_debugfs.h #endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ +/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files + * using trace events only need to #include trace/events/sched.h + */ +#define CREATE_TRACE_POINTS +#include dpaa_eth_trace.h + #define DPA_NAPI_WEIGHT64 /* Valid checksum indication */ @@ -226,6 +232,9 @@ priv_rx_default_dqrr(struct qman_portal *portal, priv = netdev_priv(net_dev); dpa_bp = priv-dpa_bp; + /* Trace the Rx fd */ + trace_dpa_rx_fd(net_dev, fq, dq-fd); + /* IRQ handler, non-migratable; safe to use raw_cpu_ptr here */ percpu_priv = raw_cpu_ptr(priv-percpu_priv); count_ptr = raw_cpu_ptr(dpa_bp-percpu_count); @@ -282,6 +291,9 @@ priv_tx_conf_default_dqrr(struct qman_portal *portal, net_dev = ((struct dpa_fq *)fq)-net_dev; priv = netdev_priv(net_dev); + /* Trace the fd */ + trace_dpa_tx_conf_fd(net_dev, fq, dq-fd); + /* Non-migratable context, safe to use raw_cpu_ptr */ percpu_priv = raw_cpu_ptr(priv-percpu_priv); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h index c66140e..4ac917a 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h @@ -36,6 +36,7 @@ #include fm_ext.h #include mac.h +#include dpaa_eth_trace.h extern int dpa_rx_extra_headroom; extern int dpa_max_frm; @@ -417,6 +418,9 @@ static inline int dpa_xmit(struct dpa_priv_s *priv, _dpa_get_tx_conf_queue(priv, egress_fq) ); + /* Trace this Tx fd */ + trace_dpa_tx_fd(priv-net_dev, egress_fq, fd); + for (i = 0; i 10; i++) { err = qman_enqueue(egress_fq, fd, 0); if (err != -EBUSY) diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h new file mode 100644 index 000..3b67477 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h @@ -0,0 +1,141 @@ +/* Copyright 2013-2015 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License (GPL) as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On Wed, Aug 05, 2015 at 11:08:55AM +0100, Stefano Stabellini wrote: On Tue, 4 Aug 2015, Julien Grall wrote: Based on include/xen/mm.h [1], Linux is mistakenly using MFN when GFN is meant, I suspect this is because the first support for Xen was for PV. This resulted in some misimplementation of helpers on ARM and confused developers about the expected behavior. For instance, with pfn_to_mfn, we expect to get an MFN based on the name. Although, if we look at the implementation on x86, it's returning a GFN. For clarity and avoid new confusion, replace any reference to mfn with gfn in any helpers used by PV drivers. The x86 code will still keep some reference of pfn_to_mfn but exclusively for PV (a BUG_ON has been added to ensure this). No changes as been made in the hypercall field, even though they may be invalid, in order to keep the same as the defintion in xen repo. Take also the opportunity to simplify simple construction such as pfn_to_mfn(page_to_pfn(page)) into page_to_gfn. More complex clean up will come in follow-up patches. [1] http://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=e758ed14f390342513405dd766e874934573e6cb Signed-off-by: Julien Grall julien.gr...@citrix.com Cc: Stefano Stabellini stefano.stabell...@eu.citrix.com Cc: Russell King li...@arm.linux.org.uk Cc: Konrad Rzeszutek Wilk konrad.w...@oracle.com Cc: Boris Ostrovsky boris.ostrov...@oracle.com Cc: David Vrabel david.vra...@citrix.com Cc: Thomas Gleixner t...@linutronix.de Cc: Ingo Molnar mi...@redhat.com Cc: H. Peter Anvin h...@zytor.com Cc: x...@kernel.org Cc: Roger Pau Monné roger@citrix.com Cc: Dmitry Torokhov dmitry.torok...@gmail.com Cc: Ian Campbell ian.campb...@citrix.com Cc: Wei Liu wei.l...@citrix.com Cc: Juergen Gross jgr...@suse.com Cc: James E.J. Bottomley jbottom...@odin.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: Jiri Slaby jsl...@suse.com Cc: Jean-Christophe Plagniol-Villard plagn...@jcrosoft.com Cc: Tomi Valkeinen tomi.valkei...@ti.com Cc: linux-in...@vger.kernel.org Cc: net...@vger.kernel.org Cc: linux-s...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-fb...@vger.kernel.org Cc: linux-arm-ker...@lists.infradead.org Aside from the x86 bits: Reviewed-by: Stefano Stabellini stefano.stabell...@eu.citrix.com Not really important, but just in case anyone waits for my ack on input bits: Acked-by: Dmitry Torokhov dmitry.torok...@gmail.com Thanks. -- Dmitry ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/8] xen: Use the correctly the Xen memory terminologies
On Tue, Aug 04, 2015 at 07:12:48PM +0100, Julien Grall wrote: [...] diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 7d50711..3b7b7c3 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -314,7 +314,7 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb } else { copy_gop-source.domid = DOMID_SELF; copy_gop-source.u.gmfn = - virt_to_mfn(page_address(page)); + virt_to_gfn(page_address(page)); } copy_gop-source.offset = offset; @@ -1284,7 +1284,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, queue-tx_copy_ops[*copy_ops].source.offset = txreq.offset; queue-tx_copy_ops[*copy_ops].dest.u.gmfn = - virt_to_mfn(skb-data); + virt_to_gfn(skb-data); queue-tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF; queue-tx_copy_ops[*copy_ops].dest.offset = offset_in_page(skb-data); Acked-by: Wei Liu wei.l...@citrix.com ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/5] powerpc/pseries: extract of_helpers module
On Wed, Aug 05, 2015 at 12:32:55PM +0300, Andy Shevchenko wrote: If path doesn't contain any slash this will do interesting things; you might want to fix that too while you're at it :-) No problem, though it is in the original code. I would do as a separate patch on top of the series. Will be okay for you? Of course -- you're fixing other problems here as well (memory leak or what was it), that's why I asked. Segher ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU
On Thu, Jul 30, 2015 at 08:13:09AM +, Hongtao Jia wrote: - Any specific reason why not using OF thermal? - No, actually. I'd like to use OF thermal after some clarification. Regarding to cooling-maps. For some cases there should be more than one cpus as cooling device and they are independent. 1. Let's say 4. So we need to provide 4 maps like map0-map3. Right? That would depend on the amount of sensors you have. Do you have one sensor per cpu? if the answer is yes, then you probably want to have four different map entries, yes, but one on each thermal zone of each cpu temperature sensor. if the answer is no, then you would need to have all the maps in the same thermal zone. 2. cooling-max-level may vary depend on switch settings or firmware. Is that OK if I do not provide cooling-min-level and cooling-max-level property? That is already achievable by using the cooling-device property of a cooling map. Please have a look in the example section of the Documentation/devicetree/bindings/thermal/thermal.txt Let me know if you need further clarification. BR, Eduardo Valentin Thanks. -Hongtao -Original Message- From: Eduardo Valentin [mailto:edubez...@gmail.com] Sent: Thursday, July 30, 2015 2:56 PM To: Jia Hongtao-B38951 Cc: linux...@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; Wood Scott- B07421 Subject: Re: [PATCH V2] QorIQ/TMU: add thermal management support based on TMU On Wed, Jul 29, 2015 at 02:19:39PM +0800, Jia Hongtao wrote: It supports one critical trip point and one passive trip point. The cpufreq is used as the cooling device to throttle CPUs when the passive trip is crossed. Signed-off-by: Jia Hongtao hongtao@freescale.com --- This patch based on: http://patchwork.ozlabs.org/patch/482987/ Changes for V2: * Add tmu-range parse. * Use default trend hook. * Using latest thermal_zone_bind_cooling_device API. * Add calibration check during initialization. * Disable/enalbe device when suspend/resume. drivers/thermal/Kconfig | 11 ++ drivers/thermal/Makefile| 1 + drivers/thermal/qoriq_thermal.c | 406 3 files changed, 418 insertions(+) create mode 100644 drivers/thermal/qoriq_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 118938e..a200745 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -180,6 +180,17 @@ config IMX_THERMAL cpufreq is used as the cooling device to throttle CPUs when the passive trip is crossed. +config QORIQ_THERMAL + tristate Freescale QorIQ Thermal Monitoring Unit + depends on CPU_THERMAL + depends on OF + default n + help + Enable thermal management based on Freescale QorIQ Thermal Monitoring + Unit (TMU). It supports one critical trip point and one passive trip + point. The cpufreq is used as the cooling device to throttle CPUs when + the passive trip is crossed. + config SPEAR_THERMAL bool SPEAr thermal sensor driver depends on PLAT_SPEAR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 535dfee..8c25859 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o obj-$(CONFIG_IMX_THERMAL)+= imx_thermal.o +obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c new file mode 100644 index 000..0694f42 --- /dev/null +++ b/drivers/thermal/qoriq_thermal.c @@ -0,0 +1,406 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or +modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + */ + +/* + * Based on Freescale QorIQ Thermal Monitoring Unit (TMU) */ +#include linux/cpufreq.h #include linux/cpu_cooling.h #include +linux/module.h #include linux/platform_device.h #include +linux/err.h #include linux/io.h #include linux/of.h #include +linux/of_address.h #include linux/thermal.h + +#define SITES_MAX16 +
Re: [PATCH v2 2/2] powerpc32: optimise csum_partial() loop
On Wed, 2015-08-05 at 19:30 -0500, Segher Boessenkool wrote: On Wed, Aug 05, 2015 at 03:29:35PM +0200, Christophe Leroy wrote: On the 8xx, load latency is 2 cycles and taking branches also takes 2 cycles. So let's unroll the loop. This is not true for most other 32-bit PowerPC; this patch makes performance worse on e.g. 6xx/7xx/7xxx. Let's not! Chips with a load latency greater than 2 cycles should also benefit from the unrolling. Have you benchmarked this somewhere and seen it reduce performance? Do you know of any 32-bit PPC chips with a load latency less than 2 cycles? -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 10/42] powerpc/powernv: pnv_ioda_setup_dma() configure one PE only
The original implementation of pnv_ioda_setup_dma() iterates the list of PEs and configures the DMA32 space for them one by one. The function was designed to be called during PHB fixup time. When configuring PE's DMA32 space in pcibios_setup_bridge(), in order to support PCI hotplug, we have to have the function PE oriented. This renames pnv_ioda_setup_dma() to pnv_ioda1_setup_dma() and adds one more argument struct pnv_ioda_pe *pe to it. The caller, pnv_pci_ioda_setup_DMA(), gets PE from the list and passes to it or pnv_pci_ioda2_setup_dma_pe(). The patch shouldn't cause behavioral changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 75 +++ 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 8456f37..cd22002 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2443,52 +2443,29 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, pnv_ioda_setup_bus_dma(pe, pe-pbus); } -static void pnv_ioda_setup_dma(struct pnv_phb *phb) +static unsigned int pnv_ioda1_setup_dma(struct pnv_phb *phb, + struct pnv_ioda_pe *pe, + unsigned int base) { struct pci_controller *hose = phb-hose; - struct pnv_ioda_pe *pe; - unsigned int dma_weight; + unsigned int dma_weight, segs; /* Calculate the PHB's DMA weight */ dma_weight = pnv_ioda_phb_dma_weight(phb); pr_info(PCI%04x has %ld DMA32 segments, total weight %d\n, hose-global_number, phb-ioda.dma32_segcount, dma_weight); - pnv_pci_ioda_setup_opal_tce_kill(phb); - - /* Walk our PE list and configure their DMA segments, hand them -* out one base segment plus any residual segments based on -* weight -*/ - list_for_each_entry(pe, phb-ioda.pe_dma_list, dma_link) { - if (!pe-dma32_weight) - continue; - - /* -* For IODA2 compliant PHB3, we needn't care about the weight. -* The all available 32-bits DMA space will be assigned to -* the specific PE. -*/ - if (phb-type == PNV_PHB_IODA1) { - unsigned int segs, base = 0; - - if (pe-dma32_weight - dma_weight / phb-ioda.dma32_segcount) - segs = 1; - else - segs = (pe-dma32_weight * - phb-ioda.dma32_segcount) / dma_weight; - - pe_info(pe, DMA32 weight %d, assigned %d segments\n, - pe-dma32_weight, segs); - pnv_pci_ioda_setup_dma_pe(phb, pe, base, segs); + if (pe-dma32_weight + dma_weight / phb-ioda.dma32_segcount) + segs = 1; + else + segs = (pe-dma32_weight * + phb-ioda.dma32_segcount) / dma_weight; + pe_info(pe, DMA weight %d, assigned %d segments\n, + pe-dma32_weight, segs); + pnv_pci_ioda_setup_dma_pe(phb, pe, base, segs); - base += segs; - } else { - pe_info(pe, Assign DMA32 space\n); - pnv_pci_ioda2_setup_dma_pe(phb, pe); - } - } + return segs; } #ifdef CONFIG_PCI_MSI @@ -2955,12 +2932,32 @@ static void pnv_pci_ioda_setup_DMA(void) { struct pci_controller *hose, *tmp; struct pnv_phb *phb; + struct pnv_ioda_pe *pe; + unsigned int base; list_for_each_entry_safe(hose, tmp, hose_list, list_node) { - pnv_ioda_setup_dma(hose-private_data); + phb = hose-private_data; + pnv_pci_ioda_setup_opal_tce_kill(phb); + + base = 0; + list_for_each_entry(pe, phb-ioda.pe_dma_list, dma_link) { + if (!pe-dma32_weight) + continue; + + switch (phb-type) { + case PNV_PHB_IODA1: + base += pnv_ioda1_setup_dma(phb, pe, base); + break; + case PNV_PHB_IODA2: + pnv_pci_ioda2_setup_dma_pe(phb, pe); + break; + default: + pr_warn(%s: No DMA for PHB type %d\n, + __func__, phb-type); + } + } /* Mark the PHB initialization done */ - phb = hose-private_data; phb-initialized = 1; } } -- 2.1.0
[PATCH v6 38/42] drivers/of: Unflatten subordinate nodes after specified level
unflatten_dt_node() is called recursively to unflatten FDT nodes with the assumption that FDT blob has only one root node, which isn't true when the FDT blob represents device sub-tree. This improves the function to supporting device sub-tree that have multiple nodes in the first level: * Rename original unflatten_dt_node() to __unflatten_dt_node(). * Wrapper unflatten_dt_node() calls __unflatten_dt_node() with adjusted current node depth to 1 to avoid underflow. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- drivers/of/fdt.c | 53 - 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 0749656..a18a2ce 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -161,7 +161,7 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, } /** - * unflatten_dt_node - Alloc and populate a device_node from the flat tree + * __unflatten_dt_node - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties * @poffset: pointer to node in flat tree @@ -171,20 +171,20 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size, * @dryrun: If true, do not allocate device nodes but still calculate needed * memory size */ -static void * unflatten_dt_node(const void *blob, +static void *__unflatten_dt_node(const void *blob, void *mem, int *poffset, struct device_node *dad, struct device_node **nodepp, unsigned long fpsize, - bool dryrun) + bool dryrun, + int *depth) { const __be32 *p; struct device_node *np; struct property *pp, **prev_pp = NULL; const char *pathp; unsigned int l, allocl; - static int depth = 0; int old_depth; int offset; int has_name = 0; @@ -337,13 +337,25 @@ static void * unflatten_dt_node(const void *blob, np-type = NULL; } - old_depth = depth; - *poffset = fdt_next_node(blob, *poffset, depth); - if (depth 0) - depth = 0; - while (*poffset 0 depth old_depth) - mem = unflatten_dt_node(blob, mem, poffset, np, NULL, - fpsize, dryrun); + /* Multiple nodes might be in the first depth level if +* the device tree is sub-tree. All nodes in current +* or deeper depth are unflattened after it returns. +*/ + old_depth = *depth; + *poffset = fdt_next_node(blob, *poffset, depth); + while (*poffset 0) { + if (*depth old_depth) + break; + + if (*depth == old_depth) + mem = __unflatten_dt_node(blob, mem, poffset, + dad, NULL, fpsize, + dryrun, depth); + else if (*depth old_depth) + mem = __unflatten_dt_node(blob, mem, poffset, + np, NULL, fpsize, + dryrun, depth); + } if (*poffset 0 *poffset != -FDT_ERR_NOTFOUND) pr_err(unflatten: error %d processing FDT\n, *poffset); @@ -369,6 +381,20 @@ static void * unflatten_dt_node(const void *blob, return mem; } +static void *unflatten_dt_node(const void *blob, + void *mem, + int *poffset, + struct device_node *dad, + struct device_node **nodepp, + bool dryrun) +{ + int depth = 1; + + return __unflatten_dt_node(blob, mem, poffset, + dad, nodepp, 0, + dryrun, depth); +} + /** * __unflatten_device_tree - create tree of device_nodes from flat blob * @@ -408,7 +434,8 @@ static void __unflatten_device_tree(const void *blob, /* First pass, scan for size */ start = 0; - size = (unsigned long)unflatten_dt_node(blob, NULL, start, NULL, NULL, 0, true); + size = (unsigned long)unflatten_dt_node(blob, NULL, start, + NULL, NULL, true); size = ALIGN(size, 4); pr_debug( size is %lx, allocating...\n, size); @@ -423,7 +450,7 @@ static void __unflatten_device_tree(const void *blob, /* Second pass, do actual unflattening */ start = 0; - unflatten_dt_node(blob, mem, start, NULL, mynodes, 0, false); + unflatten_dt_node(blob, mem, start, NULL, mynodes, false); if
[PATCH v6 19/42] powerpc/powernv: Reserve PE# for root bus
pcibios_setup_bridge() is normally called to update PCI bridge windows. It allocates PE for PCI buses. However it is not called on a root bus which does not have an upstream bridge. This reserves PE# for a root bus in advance. This will be used in the subsequent patch to do setup. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 30 +- arch/powerpc/platforms/powernv/pci.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 1c950e8..8aa6ab8 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -236,6 +236,13 @@ static int pnv_ioda1_init_m64(struct pnv_phb *phb) pr_warn( Cannot strip M64 segment for reserved PE#%d\n, phb-ioda.reserved_pe_idx); + /* Strip off the M64 segment corresponding to the PE# +* for PCI root bus, which is last supported PE# or +* (reserved PE# - 1). +*/ + if (phb-ioda.root_pe_idx != IODA_INVALID_PE) + r-end -= phb-ioda.m64_segsize; + return 0; fail: @@ -293,6 +300,13 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb) pr_warn( Cannot strip M64 segment for reserved PE#%d\n, phb-ioda.reserved_pe_idx); + /* Strip off the M64 segment corresponding to the PE# +* for PCI root bus, which is last supported PE# or +* (reserved PE# - 1). +*/ + if (phb-ioda.root_pe_idx != IODA_INVALID_PE) + r-end -= phb-ioda.m64_segsize; + return 0; fail: @@ -3237,7 +3251,21 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, aux = memblock_virt_alloc(size, 0); phb-ioda.pe_alloc = aux; phb-ioda.pe_array = aux + pemap_off; - set_bit(phb-ioda.reserved_pe_idx, phb-ioda.pe_alloc); + + /* Choose number of PE for root bus, which shouldn't consume +* any M64 resource. So we avoid picking low-end PE#, which +* is usually bound with M64 resources closely. +*/ + pnv_ioda_reserve_pe(phb, phb-ioda.reserved_pe_idx); + if (phb-ioda.reserved_pe_idx == 0) { + phb-ioda.root_pe_idx = phb-ioda.total_pe_num - 1; + pnv_ioda_reserve_pe(phb, phb-ioda.root_pe_idx); + } else if (phb-ioda.reserved_pe_idx == (phb-ioda.total_pe_num - 1)) { + phb-ioda.root_pe_idx = phb-ioda.reserved_pe_idx - 1; + pnv_ioda_reserve_pe(phb, phb-ioda.root_pe_idx); + } else { + phb-ioda.root_pe_idx = IODA_INVALID_PE; + } INIT_LIST_HEAD(phb-ioda.pe_dma_list); INIT_LIST_HEAD(phb-ioda.pe_list); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index fc899cd..e93a489 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -135,6 +135,7 @@ struct pnv_phb { struct { /* Global bridge info */ unsigned inttotal_pe_num; + unsigned introot_pe_idx; unsigned intreserved_pe_idx; /* 32-bit MMIO window */ -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 39/42] drivers/of: Allow to specify root node in of_fdt_unflatten_tree()
This introduces one more argument to of_fdt_unflatten_tree() to specify the root node for the FDT blob, which is going to be unflattened. In the result, the function can be used to unflatten FDT blob, which represents device sub-tree in PowerNV hotplug driver. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- drivers/of/fdt.c | 13 - drivers/of/unittest.c | 2 +- include/linux/of_fdt.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a18a2ce..074870a 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -388,10 +388,11 @@ static void *unflatten_dt_node(const void *blob, struct device_node **nodepp, bool dryrun) { + unsigned long fpsize = dad ? strlen(of_node_full_name(dad)) : 0; int depth = 1; return __unflatten_dt_node(blob, mem, poffset, - dad, nodepp, 0, + dad, nodepp, fpsize, dryrun, depth); } @@ -408,6 +409,7 @@ static void *unflatten_dt_node(const void *blob, * for the resulting tree */ static void __unflatten_device_tree(const void *blob, +struct device_node *dad, struct device_node **mynodes, void * (*dt_alloc)(u64 size, u64 align)) { @@ -435,7 +437,7 @@ static void __unflatten_device_tree(const void *blob, /* First pass, scan for size */ start = 0; size = (unsigned long)unflatten_dt_node(blob, NULL, start, - NULL, NULL, true); + dad, NULL, true); size = ALIGN(size, 4); pr_debug( size is %lx, allocating...\n, size); @@ -450,7 +452,7 @@ static void __unflatten_device_tree(const void *blob, /* Second pass, do actual unflattening */ start = 0; - unflatten_dt_node(blob, mem, start, NULL, mynodes, false); + unflatten_dt_node(blob, mem, start, dad, mynodes, false); if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning(End of tree marker overwritten: %08x\n, be32_to_cpup(mem + size)); @@ -472,9 +474,10 @@ static void *kernel_tree_alloc(u64 size, u64 align) * can be used. */ void of_fdt_unflatten_tree(const unsigned long *blob, + struct device_node *dad, struct device_node **mynodes) { - __unflatten_device_tree(blob, mynodes, kernel_tree_alloc); + __unflatten_device_tree(blob, dad, mynodes, kernel_tree_alloc); } EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); @@ -1125,7 +1128,7 @@ bool __init early_init_dt_scan(void *params) */ void __init unflatten_device_tree(void) { - __unflatten_device_tree(initial_boot_params, of_root, + __unflatten_device_tree(initial_boot_params, NULL, of_root, early_init_dt_alloc_memory_arch); /* Get pointer to /chosen and /aliases nodes for use everywhere */ diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 1801634..2270830 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -907,7 +907,7 @@ static int __init unittest_data_add(void) not running tests\n, __func__); return -ENOMEM; } - of_fdt_unflatten_tree(unittest_data, unittest_data_node); + of_fdt_unflatten_tree(unittest_data, NULL, unittest_data_node); if (!unittest_data_node) { pr_warn(%s: No tree to attach; not running tests\n, __func__); return -ENODATA; diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index df9ef38..3644960 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -38,6 +38,7 @@ extern bool of_fdt_is_big_endian(const void *blob, extern int of_fdt_match(const void *blob, unsigned long node, const char *const *compat); extern void of_fdt_unflatten_tree(const unsigned long *blob, + struct device_node *dad, struct device_node **mynodes); /* TBD: Temporary export of fdt globals - remove when code fully merged */ -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 32/42] powerpc/powernv: Introduce pnv_pci_poll()
This converts pnv_eeh_poll() to pnv_pci_poll() in order to: * Return linux error code other than OPAL error code. * The return value from last OPAL call, requested delay, is passed to pnv_pci_poll() and delay accordingly. Thus one call to opal_pci_poll() is saved. * More information (e.g. PCI slot power status) is returned if the last argument isn't NULL. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/eeh-powernv.c | 47 ++-- arch/powerpc/platforms/powernv/pci.c | 21 + arch/powerpc/platforms/powernv/pci.h | 1 + 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 4ae48ff..e664542 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -745,28 +745,11 @@ static int pnv_eeh_get_state(struct eeh_pe *pe, int *delay) return ret; } -static s64 pnv_eeh_poll(uint64_t id) -{ - s64 rc = OPAL_HARDWARE; - - while (1) { - rc = opal_pci_poll(id, NULL); - if (rc = 0) - break; - - if (system_state SYSTEM_RUNNING) - udelay(1000 * rc); - else - msleep(rc); - } - - return rc; -} - int pnv_eeh_phb_reset(struct pci_controller *hose, int option) { struct pnv_phb *phb = hose-private_data; s64 rc = OPAL_HARDWARE; + int ret; pr_debug(%s: Reset PHB#%x, option=%d\n, __func__, hose-global_number, option); @@ -781,8 +764,6 @@ int pnv_eeh_phb_reset(struct pci_controller *hose, int option) rc = opal_pci_reset(phb-opal_id, OPAL_RESET_PHB_COMPLETE, OPAL_DEASSERT_RESET); - if (rc 0) - goto out; /* * Poll state of the PHB until the request is done @@ -790,24 +771,22 @@ int pnv_eeh_phb_reset(struct pci_controller *hose, int option) * reset followed by hot reset on root bus. So we also * need the PCI bus settlement delay. */ - rc = pnv_eeh_poll(phb-opal_id); - if (option == EEH_RESET_DEACTIVATE) { + ret = pnv_pci_poll(phb-opal_id, rc, NULL); + if (option == EEH_RESET_DEACTIVATE !ret) { if (system_state SYSTEM_RUNNING) udelay(1000 * EEH_PE_RST_SETTLE_TIME); else msleep(EEH_PE_RST_SETTLE_TIME); } -out: - if (rc != OPAL_SUCCESS) - return -EIO; - return 0; + return ret; } static int pnv_eeh_root_reset(struct pci_controller *hose, int option) { struct pnv_phb *phb = hose-private_data; s64 rc = OPAL_HARDWARE; + int ret; pr_debug(%s: Reset PHB#%x, option=%d\n, __func__, hose-global_number, option); @@ -829,18 +808,13 @@ static int pnv_eeh_root_reset(struct pci_controller *hose, int option) rc = opal_pci_reset(phb-opal_id, OPAL_RESET_PCI_HOT, OPAL_DEASSERT_RESET); - if (rc 0) - goto out; /* Poll state of the PHB until the request is done */ - rc = pnv_eeh_poll(phb-opal_id); - if (option == EEH_RESET_DEACTIVATE) + ret = pnv_pci_poll(phb-opal_id, rc, NULL); + if (option == EEH_RESET_DEACTIVATE !ret) msleep(EEH_PE_RST_SETTLE_TIME); -out: - if (rc != OPAL_SUCCESS) - return -EIO; - return 0; + return ret; } static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option) @@ -930,10 +904,7 @@ static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option) phb = hose-private_data; id |= (pdev-bus-number 24) | (pdev-devfn 16) | phb-opal_id; rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET); - if (rc 0) - rc = pnv_eeh_poll(id); - - return (rc == OPAL_SUCCESS) ? 0 : -EIO; + return pnv_pci_poll(id, rc, NULL); } static void pnv_eeh_wait_for_pending(struct pci_dn *pdn, int pos, diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 6c350a2..801e3e8 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -44,6 +44,27 @@ #define cfg_dbg(fmt...)do { } while(0) //#define cfg_dbg(fmt...) printk(fmt) +int pnv_pci_poll(uint64_t id, int64_t rval, uint8_t *pval) +{ + while (rval 0) { + if (system_state SYSTEM_RUNNING) + udelay(1000 * rval); + else + msleep(rval); + + rval = opal_pci_poll(id, pval); + } + + /* +* The caller expects to retrieve additional
Re: [PATCH 3/3] PowerPC/mpc85xx: Add hotplug support on E6500 cores
On Thu, Aug 6, 2015 at 11:16 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 19:08 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood scottw...@freescale.com wrote: On Fri, 2015-07-31 at 17:20 +0800, b29983@freescale.comwrote: + /* + * If both threads are offline, reset core to start. + * When core is up, Thread 0 always gets up first, + * so bind the current logical cpu with Thread 0. + */ + if (hw_cpu != cpu_first_thread_sibling(hw_cpu)) { + int hw_cpu1, hw_cpu2; + + hw_cpu1 = get_hard_smp_processor_id(primary); + hw_cpu2 = get_hard_smp_processor_id(primary + 1); + set_hard_smp_processor_id(primary, hw_cpu2); + set_hard_smp_processor_id(primary + 1, hw_cpu1); + /* get new physical cpu id */ + hw_cpu = get_hard_smp_processor_id(nr); NACK as discussed in http://patchwork.ozlabs.org/patch/454944/ -Scott You said, There's no need for this. I have booting from a thread1, and having it kick its thread0, working locally without messing with the hwid/cpu mapping. I still have questions here. After a core reset, how can you boot Thread1 of the core first. As I know, Thread0 boots up first by default. So the issue isn't that thread1 comes up first, but that you *want* thread1 to come up first and it won't. I don't think this remapping is an acceptable answer, though. Instead, if you need only thread1 to come up, start the core, have thread0 start thread1, and then send thread0 into whatever waiting state it would be in if thread1 had never been offlined. -Scott Remapping is a concise solution. what's the harm of it? Keeping things simple is good in my opinion. -Chenhui ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 2/2] powerpc32: optimise csum_partial() loop
On Wed, Aug 05, 2015 at 09:31:41PM -0500, Scott Wood wrote: On Wed, 2015-08-05 at 19:30 -0500, Segher Boessenkool wrote: On Wed, Aug 05, 2015 at 03:29:35PM +0200, Christophe Leroy wrote: On the 8xx, load latency is 2 cycles and taking branches also takes 2 cycles. So let's unroll the loop. This is not true for most other 32-bit PowerPC; this patch makes performance worse on e.g. 6xx/7xx/7xxx. Let's not! Chips with a load latency greater than 2 cycles should also benefit from the unrolling. Have you benchmarked this somewhere and seen it reduce performance? Do you know of any 32-bit PPC chips with a load latency less than 2 cycles? The original loop was already optimal, as the comment said. The new code adds extra instructions and a mispredicted branch. You also might get less overlap between the loads and adde (I didn't check if there is any originally): those instructions are no longer interleaved. I think it is a stupid idea to optimise code for all 32-bit PowerPC CPUs based on solely what is best for a particularly simple, slow implementation; and that is what this patch is doing. Segher ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC v4] genalloc:support memory-allocation with bytes-alignment to genalloc
On Wed, 2015-08-05 at 14:50 +0800, Zhao Qiang wrote: Bytes alignment is required to manage some special RAM, so add gen_pool_first_fit_align to genalloc, meanwhile add gen_pool_alloc_data to pass data to gen_pool_first_fit_align(modify gen_pool_alloc as a wrapper) Signed-off-by: Zhao Qiang qiang.z...@freescale.com --- *v2: changes: title has been modified, original patch link: http://patchwork.ozlabs.org/patch/493297/ original patch add a func gen_pool_alloc_align, then pass alignment to it as an parameter. after discussing with lauraa and scott, they recommend to pass alignment as part of data based on commit message for ca279cf1065fb689abea1dc7d8c11787729bb185 which adds data: As I can't predict all the possible requirements/needs for all allocation uses cases, I add a free field 'void *data' to pass any needed information to the allocation function. For example 'data' could be used to handle a structure where you store the alignment, the expected memory bank, the requester device, or any information that could influence the allocation algorithm. *v3: changes: title has been modified, original patch link: http://patchwork.ozlabs.org/patch/500317/ according to the comments, add gen_pool_alloc_data, modify gen_pool_alloc as a wrapper, define struct data_align for gen_pool_first_fit_align algorithm. add parameter pointer pool to algorithm. *v4: changes: v3 link: http://patchwork.ozlabs.org/patch/500317/ There are comments for v3, according to the comments, modify the patch for v4. such as modifying annotations, removing unnecessary chek, removing unnecessary cast and so on. include/linux/genalloc.h | 23 +++ lib/genalloc.c | 58 +++-- --- 2 files changed, 72 insertions(+), 9 deletions(-) Looks good to me (except a minor change to the comments described below); send a non-RFC patch with the patches that use it. @@ -500,15 +518,42 @@ EXPORT_SYMBOL(gen_pool_set_algo); * @start: The bitnumber to start searching at * @nr: The number of zeroed bits we're looking for * @data: additional data - unused + * @pool: unused, but the algorithm functions have same format. */ Describe what pool actually is. Whether it's used is irrelevant (and you can assume the reader knows that all algorithm functions have the same signature). @data is different because it's defined per-algorithm and thus unused means no definition. In other words, the purpose of these headers is to be a guide to the caller of the function, describing the API, not the function internals. -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 02/42] powerpc/powernv: Drop pnv_ioda_setup_dev_PE()
Nobody is using the this function. The patch drops it. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com Reviewed-by: Alexey Kardashevskiy a...@ozlabs.ru --- arch/powerpc/platforms/powernv/pci-ioda.c | 71 --- 1 file changed, 71 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 07666ec..38b5405 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -923,77 +923,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) } #endif /* CONFIG_PCI_IOV */ -#if 0 -static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev) -{ - struct pci_controller *hose = pci_bus_to_host(dev-bus); - struct pnv_phb *phb = hose-private_data; - struct pci_dn *pdn = pci_get_pdn(dev); - struct pnv_ioda_pe *pe; - int pe_num; - - if (!pdn) { - pr_err(%s: Device tree node not associated properly\n, - pci_name(dev)); - return NULL; - } - if (pdn-pe_number != IODA_INVALID_PE) - return NULL; - - /* PE#0 has been pre-set */ - if (dev-bus-number == 0) - pe_num = 0; - else - pe_num = pnv_ioda_alloc_pe(phb); - if (pe_num == IODA_INVALID_PE) { - pr_warning(%s: Not enough PE# available, disabling device\n, - pci_name(dev)); - return NULL; - } - - /* NOTE: We get only one ref to the pci_dev for the pdn, not for the -* pointer in the PE data structure, both should be destroyed at the -* same time. However, this needs to be looked at more closely again -* once we actually start removing things (Hotplug, SR-IOV, ...) -* -* At some point we want to remove the PDN completely anyways -*/ - pe = phb-ioda.pe_array[pe_num]; - pci_dev_get(dev); - pdn-pcidev = dev; - pdn-pe_number = pe_num; - pe-pdev = dev; - pe-pbus = NULL; - pe-tce32_seg = -1; - pe-mve_number = -1; - pe-rid = dev-bus-number 8 | pdn-devfn; - - pe_info(pe, Associated device to PE\n); - - if (pnv_ioda_configure_pe(phb, pe)) { - /* XXX What do we do here ? */ - if (pe_num) - pnv_ioda_free_pe(phb, pe_num); - pdn-pe_number = IODA_INVALID_PE; - pe-pdev = NULL; - pci_dev_put(dev); - return NULL; - } - - /* Assign a DMA weight to the device */ - pe-dma_weight = pnv_ioda_dma_weight(dev); - if (pe-dma_weight != 0) { - phb-ioda.dma_weight += pe-dma_weight; - phb-ioda.dma_pe_count++; - } - - /* Link the PE */ - pnv_ioda_link_pe_by_weight(phb, pe); - - return pe; -} -#endif /* Useful for SRIOV case */ - static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) { struct pci_dev *dev; -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 11/42] powerpc/powernv: Trace DMA32 segments consumed by PE
On P7IOC, the whole DMA32 space is divided evenly to 256MB segments. Each PE can consume one or multiple DMA32 segments. Current code doesn't trace the available DMA32 segments and those consumed by one particular PE. It's conflicting with PCI hotplug. The patch introduces one bitmap to PHB to trace the available DMA32 segments for allocation, more fields to struct pnv_ioda_pe to trace the consumed DMA32 segments by the PE, which is going to be released when the PE is destroyed at PCI unplugging time. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 40 +++ arch/powerpc/platforms/powernv/pci.h | 4 +++- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index cd22002..57ba8fd 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1946,6 +1946,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, /* Grab a 32-bit TCE table */ pe-dma32_seg = base; + pe-dma32_segcount = segs; pe_info(pe, Setting up 32-bit TCE table at %08x..%08x\n, (base 28), ((base + segs) 28) - 1); @@ -2006,8 +2007,13 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, return; fail: /* XXX Failure: Try to fallback to 64-bit only ? */ - if (pe-dma32_seg = 0) + if (pe-dma32_seg = 0) { + bitmap_clear(phb-ioda.dma32_segmap, +pe-dma32_seg, pe-dma32_segcount); pe-dma32_seg = -1; + pe-dma32_segcount = 0; + } + if (tce_mem) __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs)); if (tbl) { @@ -2443,12 +2449,11 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, pnv_ioda_setup_bus_dma(pe, pe-pbus); } -static unsigned int pnv_ioda1_setup_dma(struct pnv_phb *phb, - struct pnv_ioda_pe *pe, - unsigned int base) +static void pnv_ioda1_setup_dma(struct pnv_phb *phb, + struct pnv_ioda_pe *pe) { struct pci_controller *hose = phb-hose; - unsigned int dma_weight, segs; + unsigned int dma_weight, base, segs; /* Calculate the PHB's DMA weight */ dma_weight = pnv_ioda_phb_dma_weight(phb); @@ -2461,11 +2466,28 @@ static unsigned int pnv_ioda1_setup_dma(struct pnv_phb *phb, else segs = (pe-dma32_weight * phb-ioda.dma32_segcount) / dma_weight; + + /* +* Allocate DMA32 segments. We might not have enough +* resources available. However we expect at least one +* to be available. +*/ + do { + base = bitmap_find_next_zero_area(phb-ioda.dma32_segmap, + phb-ioda.dma32_segcount, + 0, segs, 0); + if (base phb-ioda.dma32_segcount) { + bitmap_set(phb-ioda.dma32_segmap, base, segs); + break; + } + } while (--segs); + + if (WARN_ON(!segs)) + return; + pe_info(pe, DMA weight %d, assigned %d segments\n, pe-dma32_weight, segs); pnv_pci_ioda_setup_dma_pe(phb, pe, base, segs); - - return segs; } #ifdef CONFIG_PCI_MSI @@ -2933,20 +2955,18 @@ static void pnv_pci_ioda_setup_DMA(void) struct pci_controller *hose, *tmp; struct pnv_phb *phb; struct pnv_ioda_pe *pe; - unsigned int base; list_for_each_entry_safe(hose, tmp, hose_list, list_node) { phb = hose-private_data; pnv_pci_ioda_setup_opal_tce_kill(phb); - base = 0; list_for_each_entry(pe, phb-ioda.pe_dma_list, dma_link) { if (!pe-dma32_weight) continue; switch (phb-type) { case PNV_PHB_IODA1: - base += pnv_ioda1_setup_dma(phb, pe, base); + pnv_ioda1_setup_dma(phb, pe); break; case PNV_PHB_IODA2: pnv_pci_ioda2_setup_dma_pe(phb, pe); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 574fe43..1dc9578 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -65,6 +65,7 @@ struct pnv_ioda_pe { /* Base iommu table, ie, 4K TCEs, 32-bit DMA */ int dma32_seg; + int dma32_segcount; struct iommu_table_group table_group; /* 64-bit TCE bypass region */ @@ -153,10
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Thu, Aug 6, 2015 at 1:46 PM, Scott Wood scottw...@freescale.com wrote: On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote: On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood scottw...@freescale.com wrote: On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood scottw...@freescale.com wrote: Could you explain irq_mask()? Why would there still be IRQs destined for this CPU at this point? This function just masks irq by setting the registers in RCPM (for example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU have been migrated to other CPUs. So why do we need to set those bits in RCPM? Is it just caution? Setting these bits can mask interrupts signalled to RCPM from MPIC as a means of waking up from a lower power state. So, cores will not be waked up unexpectedly. Why would the MPIC be signalling those interrupts if they've been masked at the MPIC? -Scott The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and Critical interrupts. Some of them didn't be masked in MPIC. What interrupt could actually happen to a sleeping cpu that this protects against? -Scott Not sure. Maybe spurious interrupts or hardware exceptions. However, setting them make sure dead cpus can not be waked up unexpectedly. -Chenhui ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 05/42] powerpc/powernv: Track IO/M32/M64 segments from PE
The patch is adding 6 bitmaps, three to PE and three to PHB, to track the consumed by one particular PE, which can be released once the PE is destroyed during PCI unplugging time. Also, we're using fixed quantity of bits to trace the used IO, M32 and M64 segments by PEs in one particular PHB. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 29 +++-- arch/powerpc/platforms/powernv/pci.h | 18 ++ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index e4ac703..78b49a1 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -388,6 +388,12 @@ static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) list_add_tail(pe-list, master_pe-slaves); } + /* M64 segments consumed by slave PEs are tracked +* by master PE +*/ + set_bit(pe-pe_number, master_pe-m64_segmap); + set_bit(pe-pe_number, phb-ioda.m64_segmap); + /* P7IOC supports M64DT, which helps mapping M64 segment * to one particular PE#. However, PHB3 has fixed mapping * between M64 segment and PE#. In order to have same logic @@ -2871,9 +2877,11 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, while (index phb-ioda.total_pe region.start = region.end) { - phb-ioda.io_segmap[index] = pe-pe_number; + set_bit(index, pe-io_segmap); + set_bit(index, phb-ioda.io_segmap); rc = opal_pci_map_pe_mmio_window(phb-opal_id, - pe-pe_number, OPAL_IO_WINDOW_TYPE, 0, index); + pe-pe_number, OPAL_IO_WINDOW_TYPE, + 0, index); if (rc != OPAL_SUCCESS) { pr_err(%s: OPAL error %d when mapping IO segment #%d to PE#%d\n, @@ -2896,9 +2904,11 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, while (index phb-ioda.total_pe region.start = region.end) { - phb-ioda.m32_segmap[index] = pe-pe_number; + set_bit(index, pe-m32_segmap); + set_bit(index, phb-ioda.m32_segmap); rc = opal_pci_map_pe_mmio_window(phb-opal_id, - pe-pe_number, OPAL_M32_WINDOW_TYPE, 0, index); + pe-pe_number, OPAL_M32_WINDOW_TYPE, + 0, index); if (rc != OPAL_SUCCESS) { pr_err(%s: OPAL error %d when mapping M32 segment#%d to PE#%d, @@ -3090,7 +3100,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, { struct pci_controller *hose; struct pnv_phb *phb; - unsigned long size, m32map_off, pemap_off, iomap_off = 0; + unsigned long size, pemap_off; const __be64 *prop64; const __be32 *prop32; int len; @@ -3175,19 +3185,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, /* Allocate aux data arrays. We don't have IO ports on PHB3 */ size = _ALIGN_UP(phb-ioda.total_pe / 8, sizeof(unsigned long)); - m32map_off = size; - size += phb-ioda.total_pe * sizeof(phb-ioda.m32_segmap[0]); - if (phb-type == PNV_PHB_IODA1) { - iomap_off = size; - size += phb-ioda.total_pe * sizeof(phb-ioda.io_segmap[0]); - } pemap_off = size; size += phb-ioda.total_pe * sizeof(struct pnv_ioda_pe); aux = memblock_virt_alloc(size, 0); phb-ioda.pe_alloc = aux; - phb-ioda.m32_segmap = aux + m32map_off; - if (phb-type == PNV_PHB_IODA1) - phb-ioda.io_segmap = aux + iomap_off; phb-ioda.pe_array = aux + pemap_off; set_bit(phb-ioda.reserved_pe, phb-ioda.pe_alloc); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 62239b1..08a4e57 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -49,6 +49,15 @@ struct pnv_ioda_pe { /* PE number */ unsigned intpe_number; + /* IO/M32/M64 segments consumed by the PE. Each PE can +* have one M64 segment at most, but M64 segments consumed +* by slave PEs will be contributed to the master PE. One +
[PATCH v6 07/42] powerpc/powernv: Improve IO and M32 mapping
There're 3 windows (IO, M32 and M64) for PHB, root port and upstream port of the PCIE switch behind root port. In order to support PCI hotplug, we extend the start/end address of those 3 windows of root port or upstream port to the start/end address of the 3 PHB's windows. The current implementation, assigning IO or M32 segment based on the bridge's windows, isn't reliable. The patch fixes above issue by calculating PE's consumed IO or M32 segments from its contained devices, no PCI bridge windows involved if the PE doesn't contain all the subordinate PCI buses. Otherwise, the PCI bridge windows still contribute to PE's consumed IO or M32 segments. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 136 +- 1 file changed, 79 insertions(+), 57 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 488a53e..713f4b4 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2844,75 +2844,97 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) } #endif /* CONFIG_PCI_IOV */ -/* - * This function is supposed to be called on basis of PE from top - * to bottom style. So the the I/O or MMIO segment assigned to - * parent PE could be overrided by its child PEs if necessary. - */ -static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, - struct pnv_ioda_pe *pe) +static int pnv_ioda_setup_one_res(struct pci_controller *hose, + struct pnv_ioda_pe *pe, + struct resource *res) { struct pnv_phb *phb = hose-private_data; struct pci_bus_region region; - struct resource *res; - int i, index; - unsigned int segsize; + unsigned int index, segsize; unsigned long *segmap, *pe_segmap; uint16_t win; int64_t rc; - /* -* NOTE: We only care PCI bus based PE for now. For PCI -* device based PE, for example SRIOV sensitive VF should -* be figured out later. -*/ - BUG_ON(!(pe-flags (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))); + /* Check if we need map the resource */ + if (!res-parent || !res-flags || res-start res-end) + return 0; - pci_bus_for_each_resource(pe-pbus, res, i) { - if (!res || !res-flags || - res-start res-end) - continue; + if (res-flags IORESOURCE_IO) { + region.start = res-start - phb-ioda.io_pci_base; + region.end = res-end - phb-ioda.io_pci_base; + segsize = phb-ioda.io_segsize; + segmap = phb-ioda.io_segmap; + pe_segmap= pe-io_segmap; + win = OPAL_IO_WINDOW_TYPE; + } else if ((res-flags IORESOURCE_MEM) + !pnv_pci_is_mem_pref_64(res-flags)) { + region.start = res-start - + hose-mem_offset[0] - + phb-ioda.m32_pci_base; + region.end = res-end - + hose-mem_offset[0] - + phb-ioda.m32_pci_base; + segsize = phb-ioda.m32_segsize; + segmap = phb-ioda.m32_segmap; + pe_segmap= pe-m32_segmap; + win = OPAL_M32_WINDOW_TYPE; + } else { + return 0; + } - if (res-flags IORESOURCE_IO) { - region.start = res-start - phb-ioda.io_pci_base; - region.end = res-end - phb-ioda.io_pci_base; - segsize = phb-ioda.io_segsize; - segmap = phb-ioda.io_segmap; - pe_segmap= pe-io_segmap; - win = OPAL_IO_WINDOW_TYPE; - } else if ((res-flags IORESOURCE_MEM) - !pnv_pci_is_mem_pref_64(res-flags)) { - region.start = res-start - - hose-mem_offset[0] - - phb-ioda.m32_pci_base; - region.end = res-end - - hose-mem_offset[0] - - phb-ioda.m32_pci_base; - segsize = phb-ioda.m32_segsize; - segmap = phb-ioda.m32_segmap; - pe_segmap= pe-m32_segmap; - win = OPAL_M32_WINDOW_TYPE; - } else { - continue; + region.start = _ALIGN_DOWN(region.start, segsize); + region.end = _ALIGN_UP(region.end, segsize); + index = region.start / segsize; + while (index phb-ioda.total_pe + region.start
[PATCH v6 14/42] powerpc/pci: Override pcibios_setup_bridge()
The patch overrides pcibios_setup_bridge(), called to update PCI bridge windows at completion of PCI resource assignment, to assign PE and setup various (resource) mapping in next patch. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/include/asm/pci-bridge.h | 2 ++ arch/powerpc/kernel/pci-common.c | 8 2 files changed, 10 insertions(+) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index d627abf..65357a9 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -34,6 +34,8 @@ struct pci_controller_ops { /* Called during PCI resource reassignment */ resource_size_t (*window_alignment)(struct pci_bus *bus, unsigned long type); + void(*setup_bridge)(struct pci_bus *bus, + unsigned long type); void(*reset_secondary_bus)(struct pci_dev *dev); #ifdef CONFIG_PCI_MSI diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index b9de34d..9c88dcd1 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -123,6 +123,14 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus, return 1; } +void pcibios_setup_bridge(struct pci_bus *bus, unsigned long type) +{ + struct pci_controller *hose = pci_bus_to_host(bus); + + if (hose-controller_ops.setup_bridge) + hose-controller_ops.setup_bridge(bus, type); +} + void pcibios_reset_secondary_bus(struct pci_dev *dev) { struct pci_controller *phb = pci_bus_to_host(dev-bus); -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 33/42] powerpc/powernv: Functions to get/reset PCI slot status
The patch exports 4 functions, which base on corresponding OPAL APIs to get or set PCI slot status. Those functions are going to be used by PCI hotplug module in subsequent patches: pnv_pci_get_device_tree() opal_get_device_tree() pnv_pci_get_presence_status() opal_pci_get_presence_status() pnv_pci_get_power_status() opal_pci_get_power_status() pnv_pci_set_power_status() opal_pci_set_power_status() Besides, the patch also exports pnv_pci_hotplug_notifier_{register, unregister}() to allow registration and unregistration of PCI hotplug notifier, which will be used to receive PCI hotplug message from skiboot firmware. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/include/asm/opal-api.h| 8 +++- arch/powerpc/include/asm/opal.h| 5 ++ arch/powerpc/include/asm/pnv-pci.h | 7 +++ arch/powerpc/platforms/powernv/opal-wrappers.S | 4 ++ arch/powerpc/platforms/powernv/pci.c | 66 ++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 442995b..33c67ee 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -154,7 +154,11 @@ #define OPAL_FLASH_WRITE 111 #define OPAL_FLASH_ERASE 112 #define OPAL_PRD_MSG 113 -#define OPAL_LAST 113 +#define OPAL_GET_DEVICE_TREE 117 +#define OPAL_PCI_GET_PRESENCE_STATUS 118 +#define OPAL_PCI_GET_POWER_STATUS 119 +#define OPAL_PCI_SET_POWER_STATUS 120 +#define OPAL_LAST 120 /* Device tree flags */ @@ -361,6 +365,8 @@ enum opal_msg_type { OPAL_MSG_HMI_EVT, OPAL_MSG_DPO, OPAL_MSG_PRD, + OPAL_MSG_OCC, + OPAL_MSG_PCI_HOTPLUG, OPAL_MSG_TYPE_MAX, }; diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index bbb3aa6..53b8528 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -203,6 +203,11 @@ int64_t opal_flash_write(uint64_t id, uint64_t offset, uint64_t buf, uint64_t size, uint64_t token); int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size, uint64_t token); +int64_t opal_get_device_tree(uint32_t phandle, uint64_t buf, uint64_t len); +int64_t opal_pci_get_presence_status(uint64_t id, uint8_t *status); +int64_t opal_pci_get_power_status(uint64_t id, uint8_t *status); +int64_t opal_pci_set_power_status(uint64_t id, uint8_t status); + /* Internal functions */ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 6f77f71..7efa87f 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -13,6 +13,13 @@ #include linux/pci.h #include misc/cxl-base.h +extern int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len); +extern int pnv_pci_get_presence_status(uint64_t id, uint8_t *status); +extern int pnv_pci_get_power_status(uint64_t id, uint8_t *status); +extern int pnv_pci_set_power_status(uint64_t id, uint8_t status); +extern int pnv_pci_hotplug_notifier_register(struct notifier_block *nb); +extern int pnv_pci_hotplug_notifier_unregister(struct notifier_block *nb); + int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, unsigned int virq); diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 88e4333..804f8cc 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -298,3 +298,7 @@ OPAL_CALL(opal_flash_read, OPAL_FLASH_READ); OPAL_CALL(opal_flash_write,OPAL_FLASH_WRITE); OPAL_CALL(opal_flash_erase,OPAL_FLASH_ERASE); OPAL_CALL(opal_prd_msg,OPAL_PRD_MSG); +OPAL_CALL(opal_get_device_tree,OPAL_GET_DEVICE_TREE); +OPAL_CALL(opal_pci_get_presence_status, OPAL_PCI_GET_PRESENCE_STATUS); +OPAL_CALL(opal_pci_get_power_status, OPAL_PCI_GET_POWER_STATUS); +OPAL_CALL(opal_pci_set_power_status, OPAL_PCI_SET_POWER_STATUS); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 801e3e8..5982110 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -65,6 +65,72 @@ int pnv_pci_poll(uint64_t id, int64_t rval, uint8_t *pval) return rval ? -EIO : 0; } +int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len) +{ + int64_t rc; + + if (!opal_check_token(OPAL_GET_DEVICE_TREE))
[PATCH v6 20/42] powerpc/powernv: Create PEs dynamically
Currently, the PEs and their associated resources are assigned in ppc_md.pcibios_fixup() except those consumed by SRIOV VFs. The function is called for once after PCI probing and resources assignment is finished which isn't hotplug friendly. The patch creates PEs dynamically by ppc_md.pcibios_setup_bridge(), which is called on the event during system bootup and PCI hotplug: updating PCI bridge's windows after resource assignment/reassignment are finished. For partial hotplug case, where not all PCI devices belonging to the PE are unplugged and plugged again, we just need unbinding/binding the affected PCI devices with the corresponding PE without creating new one. Besides, it might require additional resources (e.g. M32) to the windows of the PCI bridge when unplugging current adapter, and insert a different adapter if there is one PCI slot, which is assumed behind root port, or the downstream bridge of the PCIE switch behind root port. The parent bridge of the newly plugged adapter would reject the request to add more resources, leading to hotplug failure. For the issue, the patch extends the windows of root port, or the upstream port of the PCIe switch behind root port to PHB's windows when ppc_md.pcibios_setup_bridge() is called. There is no upstream bridge for root bus, so we have to fix it up before any PE is created because the root bus PE is the ancestor to anyone else. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 226 ++ arch/powerpc/platforms/powernv/pci.h | 1 + 2 files changed, 137 insertions(+), 90 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 8aa6ab8..37847a3 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1083,6 +1083,13 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) pci_name(dev)); continue; } + + /* The PCI device might be not detached from the +* PE in partial hotplug case. +*/ + if (pdn-pe_number != IODA_INVALID_PE) + continue; + pdn-pe_number = pe-pe_number; pe-dma32_weight += pnv_ioda_dma_weight(dev); if ((pe-flags PNV_IODA_PE_BUS_ALL) dev-subordinate) @@ -1101,9 +1108,27 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) struct pci_controller *hose = pci_bus_to_host(bus); struct pnv_phb *phb = hose-private_data; struct pnv_ioda_pe *pe = NULL; + int pe_num; + + /* For partial hotplug case, the PE instance hasn't been destroyed +* yet. We shouldn't allocated a new one and assign resources to +* it. The existing PE instance should be reused, but we should +* associate the devices to the PE. +*/ + pe_num = phb-ioda.pe_rmap[bus-number 8]; + if (pe_num != IODA_INVALID_PE) { + pe = phb-ioda.pe_array[pe_num]; + pnv_ioda_setup_same_PE(bus, pe); + return NULL; + } + + /* PE number for root bus should have been reserved */ + if (pci_is_root_bus(bus) + phb-ioda.root_pe_idx != IODA_INVALID_PE) + pe = phb-ioda.pe_array[phb-ioda.root_pe_idx]; /* Check if PE is determined by M64 */ - if (phb-pick_m64_pe) + if (!pe phb-pick_m64_pe) pe = phb-pick_m64_pe(bus, all); /* The PE number isn't pinned by M64 */ @@ -1150,46 +1175,6 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) return pe; } -static void pnv_ioda_setup_PEs(struct pci_bus *bus) -{ - struct pci_dev *dev; - - pnv_ioda_setup_bus_PE(bus, false); - - list_for_each_entry(dev, bus-devices, bus_list) { - if (dev-subordinate) { - if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) - pnv_ioda_setup_bus_PE(dev-subordinate, true); - else - pnv_ioda_setup_PEs(dev-subordinate); - } - } -} - -/* - * Configure PEs so that the downstream PCI buses and devices - * could have their associated PE#. Unfortunately, we didn't - * figure out the way to identify the PLX bridge yet. So we - * simply put the PCI bus and the subordinate behind the root - * port to PE# here. The game rule here is expected to be changed - * as soon as we can detected PLX bridge correctly. - */ -static void pnv_pci_ioda_setup_PEs(void) -{ - struct pci_controller *hose, *tmp; - struct pnv_phb *phb; - - list_for_each_entry_safe(hose, tmp, hose_list, list_node) { - phb = hose-private_data; - - /* M64 layout might affect PE allocation */ -
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood scottw...@freescale.com wrote: On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood scottw...@freescale.com wrote: Could you explain irq_mask()? Why would there still be IRQs destined for this CPU at this point? This function just masks irq by setting the registers in RCPM (for example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU have been migrated to other CPUs. So why do we need to set those bits in RCPM? Is it just caution? Setting these bits can mask interrupts signalled to RCPM from MPIC as a means of waking up from a lower power state. So, cores will not be waked up unexpectedly. Why would the MPIC be signalling those interrupts if they've been masked at the MPIC? -Scott The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and Critical interrupts. Some of them didn't be masked in MPIC. -Chenhui ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2 1/6] powerpc/powernv: don't enable SRIOV when VF BAR contains non M64 BAR
On Wed, Aug 05, 2015 at 09:24:58AM +0800, Wei Yang wrote: On PHB_IODA2, we enable SRIOV devices by mapping IOV BAR with M64 BARs. If a SRIOV device's BAR is not 64-bit prefetchable, this is not assigned from M64 windwo, which means M64 BAR can't work on it. s/PHB_IODA2/PHB3 s/windwo/window This patch makes this explicit. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com The idea sounds right, but there is one question as below. --- arch/powerpc/platforms/powernv/pci-ioda.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 5738d31..9b41dba 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -908,9 +908,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) if (!res-flags || !res-parent) continue; - if (!pnv_pci_is_mem_pref_64(res-flags)) - continue; - /* * The actual IOV BAR range is determined by the start address * and the actual size for num_vfs VFs BAR. This check is to @@ -939,9 +936,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) if (!res-flags || !res-parent) continue; - if (!pnv_pci_is_mem_pref_64(res-flags)) - continue; - size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); res2 = *res; res-start += size * offset; @@ -1221,9 +1215,6 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs) if (!res-flags || !res-parent) continue; - if (!pnv_pci_is_mem_pref_64(res-flags)) - continue; - for (j = 0; j vf_groups; j++) { do { win = find_next_zero_bit(phb-ioda.m64_bar_alloc, @@ -1510,6 +1501,12 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) pdn = pci_get_pdn(pdev); if (phb-type == PNV_PHB_IODA2) { + if (!pdn-vfs_expanded) { + dev_info(pdev-dev, don't support this SRIOV device + with non M64 VF BAR\n); + return -EBUSY; + } + It would be -ENOSPC since -EBUSY indicates the devices (VFs) are temparily unavailable. For this case, the VFs are permanently unavailable because of running out of space to accomodate M64 and non-M64 VF BARs. The error message could be printed with dev_warn() and it would be precise as below or something else you prefer: dev_warn(pdev-dev, SRIOV not supported because of non-M64 VF BAR\n); /* Calculate available PE for required VFs */ mutex_lock(phb-ioda.pe_alloc_mutex); pdn-offset = bitmap_find_next_zero_area( @@ -2774,9 +2771,10 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) if (!res-flags || res-parent) continue; if (!pnv_pci_is_mem_pref_64(res-flags)) { - dev_warn(pdev-dev, non M64 VF BAR%d: %pR\n, + dev_warn(pdev-dev, Don't support SR-IOV with + non M64 VF BAR%d: %pR. \n, i, res); - continue; + return; } size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); @@ -2795,11 +2793,6 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) res = pdev-resource[i + PCI_IOV_RESOURCES]; if (!res-flags || res-parent) continue; - if (!pnv_pci_is_mem_pref_64(res-flags)) { - dev_warn(pdev-dev, Skipping expanding VF BAR%d: %pR\n, - i, res); - continue; - } When any one IOV BAR on the PF is non-M64, none of the VFs can be enabled. Will we still allocate/assign M64 or M32 resources for the IOV BARs? If so, I think it can be avoided. dev_dbg(pdev-dev, Fixing VF BAR%d: %pR to\n, i, res); size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote: On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood scottw...@freescale.com wrote: On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood scottw...@freescale.com wrote: Could you explain irq_mask()? Why would there still be IRQs destined for this CPU at this point? This function just masks irq by setting the registers in RCPM (for example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU have been migrated to other CPUs. So why do we need to set those bits in RCPM? Is it just caution? Setting these bits can mask interrupts signalled to RCPM from MPIC as a means of waking up from a lower power state. So, cores will not be waked up unexpectedly. Why would the MPIC be signalling those interrupts if they've been masked at the MPIC? -Scott The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and Critical interrupts. Some of them didn't be masked in MPIC. What interrupt could actually happen to a sleeping cpu that this protects against? -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 01/42] PCI: Add pcibios_setup_bridge()
Currently, PowerPC PowerNV platform utilizes ppc_md.pcibios_fixup(), which is called for once after PCI probing and resource assignment are completed, to allocate platform required resources for PCI devices: PE#, IO and MMIO mapping, DMA address translation (TCE) table etc. Obviously, it's not hotplug friendly. The patch adds weak function pcibios_setup_bridge(), which is called by pci_setup_bridge(). PowerPC PowerNV platform will reuse the function to assign above platform required resources to newly added PCI devices, in order to support PCI hotplug in subsequent patches. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com Acked-by: Bjorn Helgaas bhelg...@google.com --- drivers/pci/setup-bus.c | 5 + include/linux/pci.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 508cc56..a69eae1 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -696,11 +696,16 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus-bridge_ctl); } +void __weak pcibios_setup_bridge(struct pci_bus *bus, unsigned long type) +{ +} + void pci_setup_bridge(struct pci_bus *bus) { unsigned long type = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; + pcibios_setup_bridge(bus, type); __pci_setup_bridge(bus, type); } diff --git a/include/linux/pci.h b/include/linux/pci.h index 3fed437..0fa9712 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -816,6 +816,7 @@ void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev); void pci_stop_root_bus(struct pci_bus *bus); void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); +void pcibios_setup_bridge(struct pci_bus *bus, unsigned long type); void pci_sort_breadthfirst(void); #define dev_is_pci(d) ((d)-bus == pci_bus_type) #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)-is_physfn : false)) -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 15/42] powerpc/powernv: PE oriented during configuration
Several functions used to configure PE take pe_number to indentify PE instance. As the pe_number is included in PE instance after it is reserved or allocated. It's convienent for those functions to return PE instance which includes the required pe_number. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 51 --- arch/powerpc/platforms/powernv/pci.h | 2 +- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3094c61..9f53682 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -132,12 +132,12 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); } -static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) +static struct pnv_ioda_pe *pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) { if (!(pe_no = 0 pe_no phb-ioda.total_pe)) { pr_warn(%s: Invalid PE %d on PHB#%x\n, __func__, pe_no, phb-hose-global_number); - return; + return NULL; } if (test_and_set_bit(pe_no, phb-ioda.pe_alloc)) @@ -146,9 +146,11 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) phb-ioda.pe_array[pe_no].phb = phb; phb-ioda.pe_array[pe_no].pe_number = pe_no; + + return phb-ioda.pe_array[pe_no]; } -static int pnv_ioda_alloc_pe(struct pnv_phb *phb) +static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) { unsigned long pe; @@ -156,12 +158,12 @@ static int pnv_ioda_alloc_pe(struct pnv_phb *phb) pe = find_next_zero_bit(phb-ioda.pe_alloc, phb-ioda.total_pe, 0); if (pe = phb-ioda.total_pe) - return IODA_INVALID_PE; + return NULL; } while(test_and_set_bit(pe, phb-ioda.pe_alloc)); phb-ioda.pe_array[pe].phb = phb; phb-ioda.pe_array[pe].pe_number = pe; - return pe; + return phb-ioda.pe_array[pe]; } static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe) @@ -334,7 +336,7 @@ static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus, } } -static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) +static struct pnv_ioda_pe *pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) { struct pci_controller *hose = pci_bus_to_host(bus); struct pnv_phb *phb = hose-private_data; @@ -344,7 +346,7 @@ static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) /* Root bus shouldn't use M64 */ if (pci_is_root_bus(bus)) - return IODA_INVALID_PE; + return NULL; /* Allocate bitmap */ size = _ALIGN_UP(phb-ioda.total_pe / 8, sizeof(unsigned long)); @@ -352,7 +354,7 @@ static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) if (!pe_alloc) { pr_warn(%s: Out of memory !\n, __func__); - return IODA_INVALID_PE; + return NULL; } /* Figure out reserved PE numbers by the PE */ @@ -365,7 +367,7 @@ static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) */ if (bitmap_empty(pe_alloc, phb-ioda.total_pe)) { kfree(pe_alloc); - return IODA_INVALID_PE; + return NULL; } /* @@ -416,7 +418,7 @@ static int pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) } kfree(pe_alloc); - return master_pe-pe_number; + return master_pe; } static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) @@ -1069,28 +1071,26 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) * subordinate PCI devices and buses. The second type of PE is normally * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports. */ -static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) +static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) { struct pci_controller *hose = pci_bus_to_host(bus); struct pnv_phb *phb = hose-private_data; - struct pnv_ioda_pe *pe; - int pe_num = IODA_INVALID_PE; + struct pnv_ioda_pe *pe = NULL; /* Check if PE is determined by M64 */ if (phb-pick_m64_pe) - pe_num = phb-pick_m64_pe(bus, all); + pe = phb-pick_m64_pe(bus, all); /* The PE number isn't pinned by M64 */ - if (pe_num == IODA_INVALID_PE) - pe_num = pnv_ioda_alloc_pe(phb); + if (!pe) + pe = pnv_ioda_alloc_pe(phb); - if (pe_num == IODA_INVALID_PE) { - pr_warning(%s: Not enough PE# available for PCI bus %04x:%02x\n, + if (!pe) { +
[PATCH v6 41/42] drivers/of: Export OF changeset functions
The PowerNV PCI hotplug driver is going to use the OF changeset to manage the changed device sub-tree, which requires those OF changeset functions are exported. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- drivers/of/dynamic.c | 65 --- drivers/of/overlay.c | 8 +++ drivers/of/unittest.c | 4 ++-- include/linux/of.h| 2 ++ 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 53826b8..af65b5b 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -646,6 +646,7 @@ void of_changeset_init(struct of_changeset *ocs) memset(ocs, 0, sizeof(*ocs)); INIT_LIST_HEAD(ocs-entries); } +EXPORT_SYMBOL(of_changeset_init); /** * of_changeset_destroy - Destroy a changeset @@ -662,20 +663,9 @@ void of_changeset_destroy(struct of_changeset *ocs) list_for_each_entry_safe_reverse(ce, cen, ocs-entries, node) __of_changeset_entry_destroy(ce); } +EXPORT_SYMBOL(of_changeset_destroy); -/** - * of_changeset_apply - Applies a changeset - * - * @ocs: changeset pointer - * - * Applies a changeset to the live tree. - * Any side-effects of live tree state changes are applied here on - * sucess, like creation/destruction of devices and side-effects - * like creation of sysfs properties and directories. - * Returns 0 on success, a negative error value in case of an error. - * On error the partially applied effects are reverted. - */ -int of_changeset_apply(struct of_changeset *ocs) +int __of_changeset_apply(struct of_changeset *ocs) { struct of_changeset_entry *ce; int ret; @@ -704,17 +694,30 @@ int of_changeset_apply(struct of_changeset *ocs) } /** - * of_changeset_revert - Reverts an applied changeset + * of_changeset_apply - Applies a changeset * * @ocs: changeset pointer * - * Reverts a changeset returning the state of the tree to what it - * was before the application. - * Any side-effects like creation/destruction of devices and - * removal of sysfs properties and directories are applied. + * Applies a changeset to the live tree. + * Any side-effects of live tree state changes are applied here on + * sucess, like creation/destruction of devices and side-effects + * like creation of sysfs properties and directories. * Returns 0 on success, a negative error value in case of an error. + * On error the partially applied effects are reverted. */ -int of_changeset_revert(struct of_changeset *ocs) +int of_changeset_apply(struct of_changeset *ocs) +{ + int ret; + + mutex_lock(of_mutex); + ret = __of_changeset_apply(ocs); + mutex_unlock(of_mutex); + + return ret; +} +EXPORT_SYMBOL(of_changeset_apply); + +int __of_changeset_revert(struct of_changeset *ocs) { struct of_changeset_entry *ce; int ret; @@ -742,6 +745,29 @@ int of_changeset_revert(struct of_changeset *ocs) } /** + * of_changeset_revert - Reverts an applied changeset + * + * @ocs: changeset pointer + * + * Reverts a changeset returning the state of the tree to what it + * was before the application. + * Any side-effects like creation/destruction of devices and + * removal of sysfs properties and directories are applied. + * Returns 0 on success, a negative error value in case of an error. + */ +int of_changeset_revert(struct of_changeset *ocs) +{ + int ret; + + mutex_lock(of_mutex); + ret = __of_changeset_revert(ocs); + mutex_unlock(of_mutex); + + return ret; +} +EXPORT_SYMBOL(of_changeset_revert); + +/** * of_changeset_action - Perform a changeset action * * @ocs: changeset pointer @@ -779,3 +805,4 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action, list_add_tail(ce-node, ocs-entries); return 0; } +EXPORT_SYMBOL(of_changeset_action); diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 24e025f..804ea33 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -378,9 +378,9 @@ int of_overlay_create(struct device_node *tree) } /* apply the changeset */ - err = of_changeset_apply(ov-cset); + err = __of_changeset_apply(ov-cset); if (err) { - pr_err(%s: of_changeset_apply() failed for tree@%s\n, + pr_err(%s: __of_changeset_apply() failed for tree@%s\n, __func__, tree-full_name); goto err_revert_overlay; } @@ -508,7 +508,7 @@ int of_overlay_destroy(int id) list_del(ov-node); - of_changeset_revert(ov-cset); + __of_changeset_revert(ov-cset); of_free_overlay_info(ov); idr_remove(ov_idr, id); of_changeset_destroy(ov-cset); @@ -539,7 +539,7 @@ int of_overlay_destroy_all(void) /* the tail of list is guaranteed to be safe to remove */ list_for_each_entry_safe_reverse(ov, ovn, ov_list, node) { list_del(ov-node); -
Re: [PATCH V2 5/6] powerpc/powernv: boundary the total vf bar size instead of the individual one
On Wed, Aug 05, 2015 at 09:25:02AM +0800, Wei Yang wrote: Each VF could have 6 BARs at most. When the total BAR size exceeds the gate, after expanding it will also exhaust the M64 Window. This patch limits the boundary by checking the total VF BAR size instead of the individual BAR. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com Ok. I didn't look at this when giving comments to last patch. It turns you have the change in this patch. Please merge it with the previous patch. --- arch/powerpc/platforms/powernv/pci-ioda.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 31dcedc..4042303 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2702,7 +2702,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) struct pnv_phb *phb; struct resource *res; int i; - resource_size_t size, gate; + resource_size_t size, gate, total_vf_bar_sz; struct pci_dn *pdn; int mul, total_vfs; @@ -2729,6 +2729,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) * Window and limit the system flexibility. */ gate = phb-ioda.m64_segsize 1; + total_vf_bar_sz = 0; for (i = 0; i PCI_SRIOV_NUM_BARS; i++) { res = pdev-resource[i + PCI_IOV_RESOURCES]; @@ -2741,13 +2742,13 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) return; } - size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); + total_vf_bar_sz += pci_iov_resource_size(pdev, + i + PCI_IOV_RESOURCES); /* bigger than or equal to gate */ - if (size = gate) { - dev_info(pdev-dev, PowerNV: VF BAR%d: %pR IOV size - is bigger than %lld, roundup power2\n, - i, res, gate); + if (total_vf_bar_sz = gate) { + dev_info(pdev-dev, PowerNV: VF BAR Total IOV size + is bigger than %lld, roundup power2\n, gate); mul = roundup_pow_of_two(total_vfs); pdn-m64_single_mode = true; break; -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2 6/6] powerpc/powernv: allocate discrete PE# when using M64 BAR in Single PE mode
On Wed, Aug 05, 2015 at 09:25:03AM +0800, Wei Yang wrote: When M64 BAR is set to Single PE mode, the PE# assigned to VF could be discrete. This patch restructures the patch to allocate discrete PE# for VFs when M64 BAR is set to Single PE mode. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com --- arch/powerpc/include/asm/pci-bridge.h |2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 69 + 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 8aeba4c..72415c7 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -213,7 +213,7 @@ struct pci_dn { #ifdef CONFIG_PCI_IOV u16 vfs_expanded; /* number of VFs IOV BAR expanded */ u16 num_vfs;/* number of VFs enabled*/ - int offset; /* PE# for the first VF PE */ + int *offset;/* PE# for the first VF PE or array */ boolm64_single_mode;/* Use M64 BAR in Single Mode */ #define IODA_INVALID_M64(-1) int (*m64_map)[PCI_SRIOV_NUM_BARS]; how about renaming offset to pe_num_map, or pe_map ? Similar to the comments I gave to the m64_bar_map, num_of_max_vfs entries can be allocated. Though not all of them will be used, not too much memory will be wasted. diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 4042303..9953829 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1243,7 +1243,7 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs) /* Map the M64 here */ if (pdn-m64_single_mode) { - pe_num = pdn-offset + j; + pe_num = pdn-offset[j]; rc = opal_pci_map_pe_mmio_window(phb-opal_id, pe_num, OPAL_M64_WINDOW_TYPE, pdn-m64_map[j][i], 0); @@ -1347,7 +1347,7 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev) struct pnv_phb*phb; struct pci_dn *pdn; struct pci_sriov *iov; - u16 num_vfs; + u16num_vfs, i; bus = pdev-bus; hose = pci_bus_to_host(bus); @@ -1361,14 +1361,18 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev) if (phb-type == PNV_PHB_IODA2) { if (!pdn-m64_single_mode) - pnv_pci_vf_resource_shift(pdev, -pdn-offset); + pnv_pci_vf_resource_shift(pdev, -*pdn-offset); /* Release M64 windows */ pnv_pci_vf_release_m64(pdev, num_vfs); /* Release PE numbers */ - bitmap_clear(phb-ioda.pe_alloc, pdn-offset, num_vfs); - pdn-offset = 0; + if (pdn-m64_single_mode) { + for (i = 0; i num_vfs; i++) + pnv_ioda_free_pe(phb, pdn-offset[i]); + } else + bitmap_clear(phb-ioda.pe_alloc, *pdn-offset, num_vfs); + kfree(pdn-offset); Can pnv_ioda_free_pe() be reused to release PE ? } } @@ -1394,7 +1398,10 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) /* Reserve PE for each VF */ for (vf_index = 0; vf_index num_vfs; vf_index++) { - pe_num = pdn-offset + vf_index; + if (pdn-m64_single_mode) + pe_num = pdn-offset[vf_index]; + else + pe_num = *pdn-offset + vf_index; pe = phb-ioda.pe_array[pe_num]; pe-pe_number = pe_num; @@ -1436,6 +1443,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) struct pnv_phb*phb; struct pci_dn *pdn; intret; + u16i; bus = pdev-bus; hose = pci_bus_to_host(bus); @@ -1462,19 +1470,38 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) } /* Calculate available PE for required VFs */ - mutex_lock(phb-ioda.pe_alloc_mutex); - pdn-offset = bitmap_find_next_zero_area( - phb-ioda.pe_alloc, phb-ioda.total_pe, - 0, num_vfs, 0); - if (pdn-offset = phb-ioda.total_pe) { + if (pdn-m64_single_mode) { + pdn-offset = kmalloc(sizeof(*pdn-offset) * num_vfs, + GFP_KERNEL); + if (!pdn-offset) + return -ENOMEM; + for (i = 0; i num_vfs; i++) + pdn-offset[i] = IODA_INVALID_PE; + for (i = 0; i num_vfs; i++) { +
[PATCH v6 08/42] powerpc/powernv: Calculate PHB's DMA weight dynamically
For P7IOC, the whole available DMA32 space, which is below the MEM32 space, is divided evenly into 256MB segments. The number of continuous segments assigned to one particular PE depends on the PE's DMA weight that is calculated based on the type of each PCI devices contained in the PE, and PHB's DMA weight which is accumulative DMA weight of PEs contained in the PHB. It means that the PHB's DMA weight calculation depends on existing PEs, which works perfectly now, but not hotplug friendly. As the whole available DMA32 space can be assigned to one PE on PHB3, so we don't have the issue on PHB3. The patch calculates PHB's DMA weight based on the PCI devices contained in the PHB dynamically so that it's hotplug friendly. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 88 +++ arch/powerpc/platforms/powernv/pci.h | 6 --- 2 files changed, 43 insertions(+), 51 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 713f4b4..7342cfd 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -927,6 +927,9 @@ static void pnv_ioda_link_pe_by_weight(struct pnv_phb *phb, static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev) { + struct pci_controller *hose = pci_bus_to_host(dev-bus); + struct pnv_phb *phb = hose-private_data; + /* This is quite simplistic. The base weight of a device * is 10. 0 means no DMA is to be accounted for it. */ @@ -939,14 +942,34 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev) if (dev-class == PCI_CLASS_SERIAL_USB_UHCI || dev-class == PCI_CLASS_SERIAL_USB_OHCI || dev-class == PCI_CLASS_SERIAL_USB_EHCI) - return 3; + return 3 * phb-ioda.tce32_count; /* Increase the weight of RAID (includes Obsidian) */ if ((dev-class 8) == PCI_CLASS_STORAGE_RAID) - return 15; + return 15 * phb-ioda.tce32_count; /* Default */ - return 10; + return 10 * phb-ioda.tce32_count; +} + +static int __pnv_ioda_phb_dma_weight(struct pci_dev *pdev, void *data) +{ + unsigned int *dma_weight = data; + + *dma_weight += pnv_ioda_dma_weight(pdev); + return 0; +} + +static unsigned int pnv_ioda_phb_dma_weight(struct pnv_phb *phb) +{ + unsigned int dma_weight = 0; + + if (!phb-hose-bus) + return 0; + + pci_walk_bus(phb-hose-bus, +__pnv_ioda_phb_dma_weight, dma_weight); + return dma_weight; } #ifdef CONFIG_PCI_IOV @@ -1097,14 +1120,6 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) /* Put PE to the list */ list_add_tail(pe-list, phb-ioda.pe_list); - /* Account for one DMA PE if at least one DMA capable device exist -* below the bridge -*/ - if (pe-dma_weight != 0) { - phb-ioda.dma_weight += pe-dma_weight; - phb-ioda.dma_pe_count++; - } - /* Link the PE */ pnv_ioda_link_pe_by_weight(phb, pe); } @@ -2431,24 +2446,13 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, static void pnv_ioda_setup_dma(struct pnv_phb *phb) { struct pci_controller *hose = phb-hose; - unsigned int residual, remaining, segs, tw, base; struct pnv_ioda_pe *pe; + unsigned int dma_weight; - /* If we have more PE# than segments available, hand out one -* per PE until we run out and let the rest fail. If not, -* then we assign at least one segment per PE, plus more based -* on the amount of devices under that PE -*/ - if (phb-ioda.dma_pe_count phb-ioda.tce32_count) - residual = 0; - else - residual = phb-ioda.tce32_count - - phb-ioda.dma_pe_count; - - pr_info(PCI: Domain %04x has %ld available 32-bit DMA segments\n, - hose-global_number, phb-ioda.tce32_count); - pr_info(PCI: %d PE# for a total weight of %d\n, - phb-ioda.dma_pe_count, phb-ioda.dma_weight); + /* Calculate the PHB's DMA weight */ + dma_weight = pnv_ioda_phb_dma_weight(phb); + pr_info(PCI%04x has %ld DMA32 segments, total weight %d\n, + hose-global_number, phb-ioda.tce32_count, dma_weight); pnv_pci_ioda_setup_opal_tce_kill(phb); @@ -2456,22 +2460,9 @@ static void pnv_ioda_setup_dma(struct pnv_phb *phb) * out one base segment plus any residual segments based on * weight */ - remaining = phb-ioda.tce32_count; - tw = phb-ioda.dma_weight; - base = 0; list_for_each_entry(pe, phb-ioda.pe_dma_list, dma_link) { if (!pe-dma_weight) continue; - if (!remaining) { - pe_warn(pe,
[PATCH v6 03/42] powerpc/powernv: Enable M64 on P7IOC
The patch enables M64 window on P7IOC, which has been enabled on PHB3. Different from PHB3 where 16 M64 BARs are supported and each of them can be owned by one particular PE# exclusively or divided evenly to 256 segments, each P7IOC PHB has 16 M64 BARs and each of them are divided into 8 segments. So each P7IOC PHB can support 128 M64 segments only. Also, P7IOC has M64DT, which helps mapping one particular M64 segment# to arbitrary PE#. PHB3 doesn't have M64DT, indicating that one M64 segment can only be pinned to the fixed PE#. In order to have similar logic to support M64 for PHB3 and P7IOC, we just provide 128 M64 (16 BARs) segments and fixed mapping between PE# and M64 segment# on P7IOC. In turn, we just need different phb-init_m64() hooks for P7IOC and PHB3 to support M64. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 116 ++ 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 38b5405..e4ac703 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -172,6 +172,69 @@ static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe) clear_bit(pe, phb-ioda.pe_alloc); } +static int pnv_ioda1_init_m64(struct pnv_phb *phb) +{ + struct resource *r; + int seg; + + /* There are as many M64 segments as the maximum number +* of PEs, which is 128. +*/ + for (seg = 0; seg phb-ioda.total_pe; seg += 8) { + unsigned long base; + int64_t rc; + + base = phb-ioda.m64_base + seg * phb-ioda.m64_segsize; + rc = opal_pci_set_phb_mem_window(phb-opal_id, +OPAL_M64_WINDOW_TYPE, +seg / 8, +base, +0, /* unused */ +8 * phb-ioda.m64_segsize); + if (rc != OPAL_SUCCESS) { + pr_warn( Error %lld setting M64 PHB#%d-BAR#%d\n, + rc, phb-hose-global_number, seg / 8); + goto fail; + } + + rc = opal_pci_phb_mmio_enable(phb-opal_id, + OPAL_M64_WINDOW_TYPE, + seg / 8, + OPAL_ENABLE_M64_SPLIT); + if (rc != OPAL_SUCCESS) { + pr_warn( Error %lld enabling M64 PHB#%d-BAR#%d\n, + rc, phb-hose-global_number, seg / 8); + goto fail; + } + } + + /* Strip off the segment used by the reserved PE, which +* is expected to be 0 or last supported PE#. The PHB's +* first memory window traces the 32-bits MMIO range +* while the second one traces the 64-bits prefetchable +* MMIO range that the PHB supports. +*/ + r = phb-hose-mem_resources[1]; + if (phb-ioda.reserved_pe == 0) + r-start += phb-ioda.m64_segsize; + else if (phb-ioda.reserved_pe == (phb-ioda.total_pe - 1)) + r-end -= phb-ioda.m64_segsize; + else + pr_warn( Cannot strip M64 segment for reserved PE#%d\n, + phb-ioda.reserved_pe); + + return 0; + +fail: + for ( ; seg = 0; seg -= 8) + opal_pci_phb_mmio_enable(phb-opal_id, +OPAL_M64_WINDOW_TYPE, +seg / 8, +OPAL_DISABLE_M64); + + return -EIO; +} + /* The default M64 BAR is shared by all PEs */ static int pnv_ioda2_init_m64(struct pnv_phb *phb) { @@ -256,9 +319,9 @@ static void pnv_ioda2_reserve_dev_m64_pe(struct pci_dev *pdev, } } -static void pnv_ioda2_reserve_m64_pe(struct pci_bus *bus, -unsigned long *pe_bitmap, -bool all) +static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus, + unsigned long *pe_bitmap, + bool all) { struct pci_dev *pdev; @@ -266,12 +329,12 @@ static void pnv_ioda2_reserve_m64_pe(struct pci_bus *bus, pnv_ioda2_reserve_dev_m64_pe(pdev, pe_bitmap); if (all pdev-subordinate) - pnv_ioda2_reserve_m64_pe(pdev-subordinate, -pe_bitmap, all); + pnv_ioda_reserve_m64_pe(pdev-subordinate, + pe_bitmap, all); } } -static int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all) +static int
[PATCH v6 31/42] powerpc/pci: Rename pcibios_{add, remove}_pci_devices
This renames pcibios_{add,remove}_pci_devices to avoid conflicts with names of weak functions in PCI subsystem. This doesn't introduce logicial changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/include/asm/pci-bridge.h | 4 ++-- arch/powerpc/kernel/eeh_driver.c | 12 ++-- arch/powerpc/kernel/pci-hotplug.c | 15 +++ drivers/pci/hotplug/rpadlpar_core.c | 2 +- drivers/pci/hotplug/rpaphp_core.c | 4 ++-- drivers/pci/hotplug/rpaphp_pci.c | 2 +- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 84dee1e..787a879 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -262,10 +262,10 @@ static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) extern struct pci_bus *of_node_to_pci_bus(struct device_node *dn); /** Remove all of the PCI devices under this bus */ -extern void pcibios_remove_pci_devices(struct pci_bus *bus); +extern void pci_remove_pci_devices(struct pci_bus *bus); /** Discover new pci devices under this bus, and add them */ -extern void pcibios_add_pci_devices(struct pci_bus *bus); +extern void pci_add_pci_devices(struct pci_bus *bus); extern void isa_bridge_find_early(struct pci_controller *hose); diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 99868e2..290a9df 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -600,7 +600,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) * We don't remove the corresponding PE instances because * we need the information afterwords. The attached EEH * devices are expected to be attached soon when calling -* into pcibios_add_pci_devices(). +* into pci_add_pci_devices(). */ eeh_pe_state_mark(pe, EEH_PE_KEEP); if (bus) { @@ -608,7 +608,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); else { pci_lock_rescan_remove(); - pcibios_remove_pci_devices(bus); + pci_remove_pci_devices(bus); pci_unlock_rescan_remove(); } } else if (frozen_bus) @@ -658,7 +658,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) if (pe-type EEH_PE_VF) eeh_add_virt_device(edev, NULL); else - pcibios_add_pci_devices(bus); + pci_add_pci_devices(bus); } else if (frozen_bus removed) { pr_info(EEH: Sleep 5s ahead of partial hotplug\n); ssleep(5); @@ -668,7 +668,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) if (pe-type EEH_PE_VF) eeh_add_virt_device(edev, NULL); else - pcibios_add_pci_devices(frozen_bus); + pci_add_pci_devices(frozen_bus); } eeh_pe_state_clear(pe, EEH_PE_KEEP); @@ -852,7 +852,7 @@ perm_error: } else { eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); pci_lock_rescan_remove(); - pcibios_remove_pci_devices(frozen_bus); + pci_remove_pci_devices(frozen_bus); pci_unlock_rescan_remove(); } } @@ -936,7 +936,7 @@ static void eeh_handle_special_event(void) bus = eeh_pe_bus_get(phb_pe); eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); - pcibios_remove_pci_devices(bus); + pci_remove_pci_devices(bus); } pci_unlock_rescan_remove(); } diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 692beca..00f193b 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -68,20 +68,20 @@ void pcibios_release_device(struct pci_dev *dev) } /** - * pcibios_remove_pci_devices - remove all devices under this bus + * pci_remove_pci_devices - remove all devices under this bus * @bus: the indicated PCI bus * * Remove all of the PCI devices under this bus both from the * linux pci device tree, and from the powerpc EEH address cache. */ -void pcibios_remove_pci_devices(struct pci_bus *bus) +void pci_remove_pci_devices(struct pci_bus *bus) { struct pci_dev *dev, *tmp; struct pci_bus *child_bus; /* First go down child busses */ list_for_each_entry(child_bus, bus-children, node) -
[PATCH v6 17/42] powerpc/powernv: Rename PE# fields in PHB
This renames the fields related to PE# in struct pnv_phb for better reflecting of their usages as Alexey suggested. It doesn't introduce behavioural changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/eeh-powernv.c | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c| 58 ++-- arch/powerpc/platforms/powernv/pci.c | 2 +- arch/powerpc/platforms/powernv/pci.h | 4 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index e5e0d0b..347b1cf 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -81,7 +81,7 @@ static int pnv_eeh_init(void) * and P7IOC separately. So we should regard * PE#0 as valid for P7IOC. */ - if (phb-ioda.reserved_pe != 0) + if (phb-ioda.reserved_pe_idx != 0) eeh_add_flag(EEH_VALID_PE_ZERO); break; diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9cccf2d5..56b058c 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -145,7 +145,7 @@ static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no) static struct pnv_ioda_pe *pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) { - if (!(pe_no = 0 pe_no phb-ioda.total_pe)) { + if (!(pe_no = 0 pe_no phb-ioda.total_pe_num)) { pr_warn(%s: Invalid PE %d on PHB#%x\n, __func__, pe_no, phb-hose-global_number); return NULL; @@ -164,8 +164,8 @@ static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) do { pe = find_next_zero_bit(phb-ioda.pe_alloc, - phb-ioda.total_pe, 0); - if (pe = phb-ioda.total_pe) + phb-ioda.total_pe_num, 0); + if (pe = phb-ioda.total_pe_num) return NULL; } while(test_and_set_bit(pe, phb-ioda.pe_alloc)); @@ -188,7 +188,7 @@ static int pnv_ioda1_init_m64(struct pnv_phb *phb) /* There are as many M64 segments as the maximum number * of PEs, which is 128. */ - for (seg = 0; seg phb-ioda.total_pe; seg += 8) { + for (seg = 0; seg phb-ioda.total_pe_num; seg += 8) { unsigned long base; int64_t rc; @@ -223,13 +223,13 @@ static int pnv_ioda1_init_m64(struct pnv_phb *phb) * MMIO range that the PHB supports. */ r = phb-hose-mem_resources[1]; - if (phb-ioda.reserved_pe == 0) + if (phb-ioda.reserved_pe_idx == 0) r-start += phb-ioda.m64_segsize; - else if (phb-ioda.reserved_pe == (phb-ioda.total_pe - 1)) + else if (phb-ioda.reserved_pe_idx == (phb-ioda.total_pe_num - 1)) r-end -= phb-ioda.m64_segsize; else pr_warn( Cannot strip M64 segment for reserved PE#%d\n, - phb-ioda.reserved_pe); + phb-ioda.reserved_pe_idx); return 0; @@ -280,13 +280,13 @@ static int pnv_ioda2_init_m64(struct pnv_phb *phb) * expected to be 0 or last one of PE capabicity. */ r = phb-hose-mem_resources[1]; - if (phb-ioda.reserved_pe == 0) + if (phb-ioda.reserved_pe_idx == 0) r-start += phb-ioda.m64_segsize; - else if (phb-ioda.reserved_pe == (phb-ioda.total_pe - 1)) + else if (phb-ioda.reserved_pe_idx == (phb-ioda.total_pe_num - 1)) r-end -= phb-ioda.m64_segsize; else pr_warn( Cannot strip M64 segment for reserved PE#%d\n, - phb-ioda.reserved_pe); + phb-ioda.reserved_pe_idx); return 0; @@ -355,7 +355,7 @@ static struct pnv_ioda_pe *pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) return NULL; /* Allocate bitmap */ - size = _ALIGN_UP(phb-ioda.total_pe / 8, sizeof(unsigned long)); + size = _ALIGN_UP(phb-ioda.total_pe_num / 8, sizeof(unsigned long)); pe_alloc = kzalloc(size, GFP_KERNEL); if (!pe_alloc) { pr_warn(%s: Out of memory !\n, @@ -371,7 +371,7 @@ static struct pnv_ioda_pe *pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) * contributed by its child buses. For the case, we needn't * pick M64 dependent PE#. */ - if (bitmap_empty(pe_alloc, phb-ioda.total_pe)) { + if (bitmap_empty(pe_alloc, phb-ioda.total_pe_num)) { kfree(pe_alloc); return NULL; } @@ -382,8 +382,8 @@ static struct pnv_ioda_pe *pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all) */ master_pe = NULL; i =
Re: GPMC in device tree
On Wed, 2015-08-05 at 17:27 +0300, Ran Shalit wrote: On Wed, Aug 5, 2015 at 9:11 AM, Ran Shalit ransha...@gmail.com wrote: On Wed, Aug 5, 2015 at 6:56 AM, Ran Shalit ransha...@gmail.com wrote: On Wed, Aug 5, 2015 at 12:25 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 00:22 +0300, Ran Shalit wrote: On more thing, if I may. The localbus is also connected to nvram cpld. I've noticed that read/write works well, even though I didn't define anything in device tree. Is there any reasom to add these devices into device tree, or can we use the cpld and nvram without the definition in device tree ? I don't know what you're doing in your kernel to access devices that aren't in the device tree. You should add the devices to the device tree, and have the kernel use it rather than hardcoded info. -Scott Hi, Yes I understand. But It is worse noting that I have no localbus entry in the device tree. Yes, The nvram, cpld which are both connected to device tree, seems to work without any issues. Thanks, Ran I apologyze for the bad english, I meant it worth to note that there is no localbus entry at all in the device tree. So I wander how the nvram and cpld worked... I don't know how it worked -- presumably there's something in your kernel that hardcodes knowledge of those devices. If I may please ask, what should be the compatible for generic devices such as nvram/cpld ? CPLD is not a generic device. The compatible should describe the logic that has been programmed into the CPLD. I assume that if they worked without any entry, it means that there is no need for specific driver. Regards, Ran Hi, After studing the localbus configuration as should be configured in device tree for powerpc, I think I have come with the following configuration, (not yet tested on board): localbus@e0005000{ #address-cells = 2; #size-cells = 1; compatible = fsl,mpc8349-localbus, simple-bus; reg = 0xe0005000 0x1000; interrupts = 77 0x8; interrupt-parent = ipic; /* NOR and NAND Flashes */ ranges = 0x0 0x0 0xff80 0x0080 /* 8MB NOR Flash */ 0x1 0x0 0xF800 0x0800 /* User flash (same nor, in burst mode) 128M */ 0x2 0x0 0xf7e0 0x0020;/*NVRAM/CPLD C2 is selected in CPLD , */ /*nvram 0xf7e0 1MB */ /*cpld 0xf7f0 1M (- different address!)*/ nor@0,0 { #address-cells = 1; #size-cells = 1; compatible = cfi-flash; reg = 0x0 0x0 0x100; #bank-width = 1; device-width = 4; }; }; Where are the nodes for cs1 and cs2? Why does the node for cs0 have a reg length of 0x0100 when the ranges entry has a size of only 0x0080? I have some isssue I'm not sure about, and wanted a second opinion: 1. I have not added entry for NVRAM/CPLD (8 bit width interfaces) , but only specifies it in ranges , I assume it is not required becuase it is probably can be treated as simple ram. Is this assumption correct ? No. Even if it does work like simple ram (which is not what I'd expect for the cpld, especially since you describe nvram as being something separate), you need something to indicate that the ram is there, and what (if anything) its dedicated hardware purpose is. 2. The NVRAM/CPLD is using CS2 , which is configured for 2 MB space. The 2 MB is divided to two 1 MB slices. 1 MB is dedicated for NVRAM (though the NVRAM is only 128 KB) and 1 MB is dedicated for CPLD. The division of CS2 into two regions is done in CPLD. 0xf7e0 - for NVRAM , 0x0010 0xf7f0 - for CPLD , 0x0010 Is it correct to be configured as one range as done above (0x2 0x0 0xf7e0 0x0020) ? If they are both using the same chipselect then they should use the same ranges entry. -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 12/42] powerpc/powernv: Increase PE# capacity
Each PHB maintains an array helping to translate RID (Request ID) to PE# with the assumption that PE# takes 8 bits, indicating that we can't have more than 256 PEs. However, pci_dn-pe_number already had 4-bytes for the PE#. The patch extends the PE# capacity so that each of them will be 4-bytes long. Then we can use IODA_INVALID_PE to check one entry in phb-pe_rmap[] is valid or not. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 8 ++-- arch/powerpc/platforms/powernv/pci.h | 7 +++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 57ba8fd..3094c61 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -786,7 +786,7 @@ static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) /* Clear the reverse map */ for (rid = pe-rid; rid rid_end; rid++) - phb-ioda.pe_rmap[rid] = 0; + phb-ioda.pe_rmap[rid] = IODA_INVALID_PE; /* Release from all parents PELT-V */ while (parent) { @@ -3134,7 +3134,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, unsigned long size, pemap_off; const __be64 *prop64; const __be32 *prop32; - int len; + int len, i; u64 phb_id; void *aux; long rc; @@ -3201,6 +3201,10 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, if (prop32) phb-ioda.reserved_pe = be32_to_cpup(prop32); + /* Invalidate RID to PE# mapping */ + for (i = 0; i ARRAY_SIZE(phb-ioda.pe_rmap); ++i) + phb-ioda.pe_rmap[i] = IODA_INVALID_PE; + /* Parse 64-bit MMIO range */ pnv_ioda_parse_m64_window(phb); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 1dc9578..6f8568e 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -175,11 +175,10 @@ struct pnv_phb { struct list_headpe_list; struct mutexpe_list_mutex; - /* Reverse map of PEs, will have to extend if -* we are to support more than 256 PEs, indexed -* bus { bus, devfn } + /* Reverse map of PEs, indexed by +* { bus, devfn } */ - unsigned char pe_rmap[0x1]; + int pe_rmap[0x1]; /* 32-bit TCE tables allocation */ unsigned long dma32_segcount; -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 21/42] powerpc/powernv: Remove DMA32 list of PEs
Every PHB maintains a list of PEs based on their DMA32 weight. After patch powerpc/powernv: Create PEs dynamically, the list is useless and it's safe to remove it. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 18 -- arch/powerpc/platforms/powernv/pci.h | 6 -- 2 files changed, 24 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 37847a3..84b771e 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -938,20 +938,6 @@ out: return 0; } -static void pnv_ioda_link_pe_by_weight(struct pnv_phb *phb, - struct pnv_ioda_pe *pe) -{ - struct pnv_ioda_pe *lpe; - - list_for_each_entry(lpe, phb-ioda.pe_dma_list, dma_link) { - if (lpe-dma32_weight pe-dma32_weight) { - list_add_tail(pe-dma_link, lpe-dma_link); - return; - } - } - list_add_tail(pe-dma_link, phb-ioda.pe_dma_list); -} - static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev-bus); @@ -1169,9 +1155,6 @@ static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all) /* Put PE to the list */ list_add_tail(pe-list, phb-ioda.pe_list); - /* Link the PE */ - pnv_ioda_link_pe_by_weight(phb, pe); - return pe; } @@ -3313,7 +3296,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb-ioda.root_pe_idx = IODA_INVALID_PE; } - INIT_LIST_HEAD(phb-ioda.pe_dma_list); INIT_LIST_HEAD(phb-ioda.pe_list); mutex_init(phb-ioda.pe_list_mutex); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index a160491..f8e6022 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -83,7 +83,6 @@ struct pnv_ioda_pe { struct list_headslaves; /* Link in list of PE#s */ - struct list_headdma_link; struct list_headlist; }; @@ -185,11 +184,6 @@ struct pnv_phb { /* 32-bit TCE tables allocation */ unsigned long dma32_segcount; - /* Sorted list of used PE's, sorted at -* boot for resource allocation purposes -*/ - struct list_headpe_dma_list; - /* TCE cache invalidate registers (physical and * remapped) */ -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 37/42] powerpc/powernv: Select OF_DYNAMIC
The device tree nodes will be changed dynamically on PCI hotplug events on PowerNV platform. This enables CONFIG_OF_DYNAMIC on PowerNV platform to support that. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig index 604190c..e7b1ad7 100644 --- a/arch/powerpc/platforms/powernv/Kconfig +++ b/arch/powerpc/platforms/powernv/Kconfig @@ -18,6 +18,7 @@ config PPC_POWERNV select CPU_FREQ_GOV_ONDEMAND select CPU_FREQ_GOV_CONSERVATIVE select PPC_DOORBELL + select OF_DYNAMIC default y config OPAL_PRD -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 26/42] powerpc/powernv: Simplify pnv_eeh_reset()
This simplifies pnv_eeh_reset() by avoiding the unnecessary nested if statement. No logicial changes introduced by this. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/eeh-powernv.c | 65 +--- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 7be2ebf..95332e9 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -1086,7 +1086,9 @@ void pnv_pci_reset_secondary_bus(struct pci_dev *dev) static int pnv_eeh_reset(struct eeh_pe *pe, int option) { struct pci_controller *hose = pe-phb; + struct pnv_phb *phb = hose-private_data; struct pci_bus *bus; + int64_t rc; int ret; /* @@ -1103,44 +1105,39 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option) * reset. The side effect is that EEH core has to clear the frozen * state explicitly after BAR restore. */ - if (pe-type EEH_PE_PHB) { - ret = pnv_eeh_phb_reset(hose, option); - } else { - struct pnv_phb *phb; - s64 rc; + if (pe-type EEH_PE_PHB) + return pnv_eeh_phb_reset(hose, option); - /* -* The frozen PE might be caused by PAPR error injection -* registers, which are expected to be cleared after hitting -* frozen PE as stated in the hardware spec. Unfortunately, -* that's not true on P7IOC. So we have to clear it manually -* to avoid recursive EEH errors during recovery. -*/ - phb = hose-private_data; - if (phb-model == PNV_PHB_MODEL_P7IOC - (option == EEH_RESET_HOT || - option == EEH_RESET_FUNDAMENTAL)) { - rc = opal_pci_reset(phb-opal_id, - OPAL_RESET_PHB_ERROR, - OPAL_ASSERT_RESET); - if (rc != OPAL_SUCCESS) { - pr_warn(%s: Failure %lld clearing - error injection registers\n, - __func__, rc); - return -EIO; - } + /* +* The frozen PE might be caused by PAPR error injection +* registers, which are expected to be cleared after hitting +* frozen PE as stated in the hardware spec. Unfortunately, +* that's not true on P7IOC. So we have to clear it manually +* to avoid recursive EEH errors during recovery. +*/ + phb = hose-private_data; + if (phb-model == PNV_PHB_MODEL_P7IOC + (option == EEH_RESET_HOT || + option == EEH_RESET_FUNDAMENTAL)) { + rc = opal_pci_reset(phb-opal_id, + OPAL_RESET_PHB_ERROR, + OPAL_ASSERT_RESET); + if (rc != OPAL_SUCCESS) { + pr_warn(%s: Error %lld clearing errinjct registers\n, + __func__, rc); + return -EIO; } - - bus = eeh_pe_bus_get(pe); - if (pe-type EEH_PE_VF) - ret = pnv_eeh_vf_pe_reset(pe, option); - else if (pci_is_root_bus(bus) || - pci_is_root_bus(bus-parent)) - ret = pnv_eeh_root_reset(hose, option); - else - ret = pnv_eeh_bridge_reset(bus-self, option); } + bus = eeh_pe_bus_get(pe); + if (pe-type EEH_PE_VF) + ret = pnv_eeh_vf_pe_reset(pe, option); + else if (pci_is_root_bus(bus) || +pci_is_root_bus(bus-parent)) + ret = pnv_eeh_root_reset(hose, option); + else + ret = pnv_eeh_bridge_reset(bus-self, option); + return ret; } -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 29/42] powerpc/pci: Don't scan empty slot
In hotplug case, function pcibios_add_pci_devices() is called to rescan the specified PCI bus, which might not have any child devices. Access to the PCI bus's child device node will cause kernel crash without exception. This adds condition of skipping scanning PCI bus without child devices in order to avoid kernel crash. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/kernel/pci-hotplug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 59c4361..c307d9a 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -92,7 +92,8 @@ void pcibios_add_pci_devices(struct pci_bus * bus) if (mode == PCI_PROBE_DEVTREE) { /* use ofdt-based probe */ of_rescan_bus(dn, bus); - } else if (mode == PCI_PROBE_NORMAL) { + } else if (mode == PCI_PROBE_NORMAL + dn-child PCI_DN(dn-child)) { /* * Use legacy probe. In the partial hotplug case, we * probably have grandchildren devices unplugged. So -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2 4/6] powerpc/powernv: replace the hard coded boundary with gate
On Wed, Aug 05, 2015 at 09:25:01AM +0800, Wei Yang wrote: Based on the limitation of M64 Window size, when VF BAR size is bigger than 64MB, IOV BAR just round up power of 2 of the total_vfs. While the 64MB is a magic boundary in code, which is hard to maintain. This patch replaces the hard coded boundary with gate, which is calculated from m64_segsize and adds comment to explain the reason for it. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 22 +- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index f5d110c..31dcedc 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2702,7 +2702,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) struct pnv_phb *phb; struct resource *res; int i; - resource_size_t size; + resource_size_t size, gate; struct pci_dn *pdn; int mul, total_vfs; @@ -2718,6 +2718,17 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) total_vfs = pci_sriov_get_totalvfs(pdev); mul = phb-ioda.total_pe; + /* + * If bigger than or equal to half of m64_segsize, just round up power + * of two. + * + * Generally, one M64 BAR maps one IOV BAR. To avoid conflict with + * other devices, IOV BAR size is expanded to be (total_pe * VF size). + * When VF size is half of m64_segsize , the expanded size would equal + * to half of the whole M64 Window size, which will exhaust the M64 + * Window and limit the system flexibility. + */ s/VF size/VF BAR size s/m64_segsize/M64 segment size s/M64 Window/M64 space + gate = phb-ioda.m64_segsize 1; for (i = 0; i PCI_SRIOV_NUM_BARS; i++) { res = pdev-resource[i + PCI_IOV_RESOURCES]; @@ -2732,10 +2743,11 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); - /* bigger than 64M */ - if (size (1 26)) { - dev_info(pdev-dev, PowerNV: VF BAR%d: %pR IOV size is bigger than 64M, roundup power2\n, - i, res); + /* bigger than or equal to gate */ + if (size = gate) { + dev_info(pdev-dev, PowerNV: VF BAR%d: %pR IOV size + is bigger than %lld, roundup power2\n, + i, res, gate); If I understand the changes correctly, single VF BAR size is still checked against the gate (128MB), not the total VF BAR size. Recap the comments I gave last time: I mean to check the sum of all VF BARs. For example, the VFs attached to its PF has two VF BARs and each of them is 64MB. For this case, the MMIO resource can't be allocated once extending them to 256 VFs. So we have to try single-pe-mode for this situation. So the check becomes as below: struct pci_controller *hose = pci_bus_to_host(pdev-bus); struct pnv_phb *phb = hose-private_data; resource_size_t total_vf_bar_sz = 0; resource_size_t gate; /* Some comments to explain the gate */ gate = phb-m64_segsize / 2; for (i = 0; i PCI_SRIOV_NUM_BARS; i++) { total_vf_bar_sz += pci_iov_resource_size(pdev, PCI_IOV_RESOURCES + i); if (total_vf_bar_sz = gate) /* single-pe-mode */ else /* shared-mode */ mul = roundup_pow_of_two(total_vfs); pdn-m64_single_mode = true; break; -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v3 1/1] KVM: PPC: Book3S: correct width in XER handling
Ping? I think I've addressed all the comments in this version. Is there anything else I need to look at? Cheers, Sam. On Wed, May 27, 2015 at 09:56:57AM +1000, Sam Bobroff wrote: In 64 bit kernels, the Fixed Point Exception Register (XER) is a 64 bit field (e.g. in kvm_regs and kvm_vcpu_arch) and in most places it is accessed as such. This patch corrects places where it is accessed as a 32 bit field by a 64 bit kernel. In some cases this is via a 32 bit load or store instruction which, depending on endianness, will cause either the lower or upper 32 bits to be missed. In another case it is cast as a u32, causing the upper 32 bits to be cleared. This patch corrects those places by extending the access methods to 64 bits. Signed-off-by: Sam Bobroff sam.bobr...@au1.ibm.com --- v3: Adjust booke set/get xer to match book3s. v2: Also extend kvmppc_book3s_shadow_vcpu.xer to 64 bit. arch/powerpc/include/asm/kvm_book3s.h |4 ++-- arch/powerpc/include/asm/kvm_book3s_asm.h |2 +- arch/powerpc/include/asm/kvm_booke.h |4 ++-- arch/powerpc/kvm/book3s_hv_rmhandlers.S |6 +++--- arch/powerpc/kvm/book3s_segment.S |4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index b91e74a..05a875a 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -225,12 +225,12 @@ static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) return vcpu-arch.cr; } -static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) +static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) { vcpu-arch.xer = val; } -static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) +static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu) { return vcpu-arch.xer; } diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 5bdfb5d..c4ccd2d 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -112,7 +112,7 @@ struct kvmppc_book3s_shadow_vcpu { bool in_use; ulong gpr[14]; u32 cr; - u32 xer; + ulong xer; ulong ctr; ulong lr; ulong pc; diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h index 3286f0d..bc6e29e 100644 --- a/arch/powerpc/include/asm/kvm_booke.h +++ b/arch/powerpc/include/asm/kvm_booke.h @@ -54,12 +54,12 @@ static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) return vcpu-arch.cr; } -static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) +static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) { vcpu-arch.xer = val; } -static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) +static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu) { return vcpu-arch.xer; } diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 4d70df2..d75be59 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -870,7 +870,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) blt hdec_soon ld r6, VCPU_CTR(r4) - lwz r7, VCPU_XER(r4) + ld r7, VCPU_XER(r4) mtctr r6 mtxer r7 @@ -1103,7 +1103,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) mfctr r3 mfxer r4 std r3, VCPU_CTR(r9) - stw r4, VCPU_XER(r9) + std r4, VCPU_XER(r9) /* If this is a page table miss then see if it's theirs or ours */ cmpwi r12, BOOK3S_INTERRUPT_H_DATA_STORAGE @@ -1675,7 +1675,7 @@ kvmppc_hdsi: bl kvmppc_msr_interrupt fast_interrupt_c_return: 6: ld r7, VCPU_CTR(r9) - lwz r8, VCPU_XER(r9) + ld r8, VCPU_XER(r9) mtctr r7 mtxer r8 mr r4, r9 diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S index acee37c..ca8f174 100644 --- a/arch/powerpc/kvm/book3s_segment.S +++ b/arch/powerpc/kvm/book3s_segment.S @@ -123,7 +123,7 @@ no_dcbz32_on: PPC_LL r8, SVCPU_CTR(r3) PPC_LL r9, SVCPU_LR(r3) lwz r10, SVCPU_CR(r3) - lwz r11, SVCPU_XER(r3) + PPC_LL r11, SVCPU_XER(r3) mtctr r8 mtlrr9 @@ -237,7 +237,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) mfctr r8 mflrr9 - stw r5, SVCPU_XER(r13) + PPC_STL r5, SVCPU_XER(r13) PPC_STL r6, SVCPU_FAULT_DAR(r13) stw r7, SVCPU_FAULT_DSISR(r13) PPC_STL r8, SVCPU_CTR(r13) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe kvm-ppc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 18/42] powerpc/powernv: Allocate PE# in deasending order
The available PE#, represented by a bitmap in the PHB, is allocated in ascending order. It conflicts with the fact that M64 segments are assigned in same order. In order to avoid the conflict, the patch allocates PE# in descending order. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 56b058c..1c950e8 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -161,13 +161,18 @@ static struct pnv_ioda_pe *pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) { unsigned long pe; + unsigned long limit = phb-ioda.total_pe_num - 1; do { pe = find_next_zero_bit(phb-ioda.pe_alloc, - phb-ioda.total_pe_num, 0); - if (pe = phb-ioda.total_pe_num) + phb-ioda.total_pe_num, limit); + if (pe phb-ioda.total_pe_num + !test_and_set_bit(pe, phb-ioda.pe_alloc)) + break; + + if (--limit = phb-ioda.total_pe_num) return NULL; - } while(test_and_set_bit(pe, phb-ioda.pe_alloc)); + } while (1); return pnv_ioda_init_pe(phb, pe); } -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 42/42] pci/hotplug: PowerPC PowerNV PCI hotplug driver
The patch intends to add standalone driver to support PCI hotplug for PowerPC PowerNV platform, which runs on top of skiboot firmware. The firmware identified hotpluggable slots and marked their device tree node with proper ibm,slot-pluggable and ibm,reset-by-firmware. The driver simply scans device-tree to create/register PCI hotplug slot accordingly. If the skiboot firmware doesn't support slot status retrieval, the PCI slot device node shouldn't have property ibm,reset-by-firmware. In that case, none of valid PCI slots will be detected from device tree. The skiboot firmware doesn't export the capability to access attention LEDs yet and it's something for TBD. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com Acked-by: Bjorn Helgaas bhelg...@google.com --- MAINTAINERS| 6 + drivers/pci/hotplug/Kconfig| 12 + drivers/pci/hotplug/Makefile | 4 + drivers/pci/hotplug/powernv_php.c | 140 +++ drivers/pci/hotplug/powernv_php.h | 92 + drivers/pci/hotplug/powernv_php_slot.c | 722 + 6 files changed, 976 insertions(+) create mode 100644 drivers/pci/hotplug/powernv_php.c create mode 100644 drivers/pci/hotplug/powernv_php.h create mode 100644 drivers/pci/hotplug/powernv_php_slot.c diff --git a/MAINTAINERS b/MAINTAINERS index fd60784..3b75c92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7747,6 +7747,12 @@ L: linux-...@vger.kernel.org S: Supported F: Documentation/PCI/pci-error-recovery.txt +PCI HOTPLUG DRIVER FOR POWERNV PLATFORM +M: Gavin Shan gws...@linux.vnet.ibm.com +L: linux-...@vger.kernel.org +S: Supported +F: drivers/pci/hotplug/powernv_php* + PCI SUBSYSTEM M: Bjorn Helgaas bhelg...@google.com L: linux-...@vger.kernel.org diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index df8caec..ef55dae 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -113,6 +113,18 @@ config HOTPLUG_PCI_SHPC When in doubt, say N. +config HOTPLUG_PCI_POWERNV + tristate PowerPC PowerNV PCI Hotplug driver + depends on PPC_POWERNV EEH + help + Say Y here if you run PowerPC PowerNV platform that supports + PCI Hotplug + + To compile this driver as a module, choose M here: the + module will be called powernv-php. + + When in doubt, say N. + config HOTPLUG_PCI_RPA tristate RPA PCI Hotplug driver depends on PPC_PSERIES EEH diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index b616e75..fd51d65 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_HOTPLUG_PCI_PCIE)+= pciehp.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o +obj-$(CONFIG_HOTPLUG_PCI_POWERNV) += powernv-php.o obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)+= rpadlpar_io.o obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o @@ -50,6 +51,9 @@ ibmphp-objs := ibmphp_core.o \ acpiphp-objs := acpiphp_core.o \ acpiphp_glue.o +powernv-php-objs := powernv_php.o \ + powernv_php_slot.o + rpaphp-objs:= rpaphp_core.o \ rpaphp_pci.o\ rpaphp_slot.o diff --git a/drivers/pci/hotplug/powernv_php.c b/drivers/pci/hotplug/powernv_php.c new file mode 100644 index 000..4cbff7a --- /dev/null +++ b/drivers/pci/hotplug/powernv_php.c @@ -0,0 +1,140 @@ +/* + * PCI Hotplug Driver for PowerPC PowerNV platform. + * + * Copyright Gavin Shan, IBM Corporation 2015. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include linux/module.h + +#include asm/opal.h +#include asm/pnv-pci.h + +#include powernv_php.h + +#define DRIVER_VERSION 0.1 +#define DRIVER_AUTHOR Gavin Shan, IBM Corporation +#define DRIVER_DESCPowerPC PowerNV PCI Hotplug Driver + +static struct notifier_block php_msg_nb = { + .notifier_call = powernv_php_msg_handler, + .next = NULL, + .priority = 0, +}; + +static int powernv_php_register_one(struct device_node *dn) +{ + struct powernv_php_slot *slot; + const __be32 *prop32; + int ret; + + /* Check if it's hotpluggable slot */ + prop32 = of_get_property(dn, ibm,slot-pluggable, NULL); + if (!prop32 || !of_read_number(prop32, 1)) + return -ENXIO; + + prop32 = of_get_property(dn, ibm,reset-by-firmware, NULL); + if
[PATCH v6 34/42] powerpc/pci: Delay creating pci_dn
The pci_dn instances are allocated from memblock or bootmem when creating PCI controller (hoses) in setup_arch(). The PCI hotplug, which will be supported by proceeding patches, will release PCI device nodes and their corresponding pci_dn on unplugging event. The pci_dn instance memory chunks alloed from memblock or bootmem are hard to reused after being released. This delays creating pci_dn using core_initcall() so that they can be allocated from slab. In turn, the memory chunks for them can be reused after being released without problem. Since the pci_dn and eeh_dev has same life cycle, the eeh_dev is created when pci_dn is populated. We needn't create eeh_dev with another initcall. The time to create PHB PEs is delayed a bit from core_initcall() to core_initcall_sync(). Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/include/asm/eeh.h | 2 +- arch/powerpc/include/asm/ppc-pci.h | 1 - arch/powerpc/kernel/eeh_dev.c | 19 arch/powerpc/kernel/pci_dn.c | 20 +++-- arch/powerpc/platforms/maple/pci.c | 34 ++--- arch/powerpc/platforms/pasemi/pci.c| 3 --- arch/powerpc/platforms/powermac/pci.c | 40 -- arch/powerpc/platforms/powernv/pci.c | 3 --- arch/powerpc/platforms/pseries/setup.c | 7 +- 9 files changed, 69 insertions(+), 60 deletions(-) diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index ea1f13c4..19b6050 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -272,7 +272,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe); const char *eeh_pe_loc_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); -void *eeh_dev_init(struct pci_dn *pdn, void *data); +struct eeh_dev *eeh_dev_init(struct pci_dn *pdn, struct pci_controller *phb); void eeh_dev_phb_init_dynamic(struct pci_controller *phb); int eeh_init(void); int __init eeh_ops_register(struct eeh_ops *ops); diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index ca0c5bf..916775d 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -40,7 +40,6 @@ void *traverse_pci_dn(struct pci_dn *root, void *(*fn)(struct pci_dn *, void *), void *data); -extern void pci_devs_phb_init(void); extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); /* From rtas_pci.h */ diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index aabba94..7a135c1 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c @@ -44,14 +44,13 @@ /** * eeh_dev_init - Create EEH device according to OF node * @pdn: PCI device node - * @data: PHB + * @phb: PCI controller * * It will create EEH device according to the given OF node. The function * might be called by PCI emunation, DR, PHB hotplug. */ -void *eeh_dev_init(struct pci_dn *pdn, void *data) +struct eeh_dev *eeh_dev_init(struct pci_dn *pdn, struct pci_controller *phb) { - struct pci_controller *phb = data; struct eeh_dev *edev; /* Allocate EEH device */ @@ -68,7 +67,7 @@ void *eeh_dev_init(struct pci_dn *pdn, void *data) edev-phb = phb; INIT_LIST_HEAD(edev-list); - return NULL; + return edev; } /** @@ -80,16 +79,8 @@ void *eeh_dev_init(struct pci_dn *pdn, void *data) */ void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { - struct pci_dn *root = phb-pci_data; - /* EEH PE for PHB */ eeh_phb_pe_create(phb); - - /* EEH device for PHB */ - eeh_dev_init(root, phb); - - /* EEH devices for children OF nodes */ - traverse_pci_dn(root, eeh_dev_init, phb); } /** @@ -105,9 +96,7 @@ static int __init eeh_dev_phb_init(void) list_for_each_entry_safe(phb, tmp, hose_list, list_node) eeh_dev_phb_init_dynamic(phb); - pr_info(EEH: devices created\n); - return 0; } -core_initcall(eeh_dev_phb_init); +core_initcall_sync(eeh_dev_phb_init); diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index f0ddde7..53a11e9 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -290,8 +290,11 @@ void *update_dn_pci_info(struct device_node *dn, void *data) const __be32 *regs; struct device_node *parent; struct pci_dn *pdn; +#ifdef CONFIG_EEH + struct eeh_dev *edev; +#endif - pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL); + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) return NULL; dn-data = pdn; @@ -320,6 +323,15 @@ void *update_dn_pci_info(struct device_node *dn, void *data) /* Extended config space */ pdn-pci_ext_config_space = (type of_read_number(type, 1) == 1); + /* Initialize EEH device */ +#ifdef CONFIG_EEH +
[PATCH v6 06/42] powerpc/powernv: Simplify pnv_ioda_setup_pe_seg()
The original implementation of pnv_ioda_setup_pe_seg() configures IO and M32 segments by separate logics, which can be merged by by caching @seg_bitmap, @seg_size, @win in advance. The patch shouldn't cause any behavioural changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 68 ++- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 78b49a1..488a53e 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2856,7 +2856,10 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, struct pci_bus_region region; struct resource *res; int i, index; - int rc; + unsigned int segsize; + unsigned long *segmap, *pe_segmap; + uint16_t win; + int64_t rc; /* * NOTE: We only care PCI bus based PE for now. For PCI @@ -2873,25 +2876,10 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, if (res-flags IORESOURCE_IO) { region.start = res-start - phb-ioda.io_pci_base; region.end = res-end - phb-ioda.io_pci_base; - index = region.start / phb-ioda.io_segsize; - - while (index phb-ioda.total_pe - region.start = region.end) { - set_bit(index, pe-io_segmap); - set_bit(index, phb-ioda.io_segmap); - rc = opal_pci_map_pe_mmio_window(phb-opal_id, - pe-pe_number, OPAL_IO_WINDOW_TYPE, - 0, index); - if (rc != OPAL_SUCCESS) { - pr_err(%s: OPAL error %d when mapping IO - segment #%d to PE#%d\n, - __func__, rc, index, pe-pe_number); - break; - } - - region.start += phb-ioda.io_segsize; - index++; - } + segsize = phb-ioda.io_segsize; + segmap = phb-ioda.io_segmap; + pe_segmap= pe-io_segmap; + win = OPAL_IO_WINDOW_TYPE; } else if ((res-flags IORESOURCE_MEM) !pnv_pci_is_mem_pref_64(res-flags)) { region.start = res-start - @@ -2900,25 +2888,31 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, region.end = res-end - hose-mem_offset[0] - phb-ioda.m32_pci_base; - index = region.start / phb-ioda.m32_segsize; - - while (index phb-ioda.total_pe - region.start = region.end) { - set_bit(index, pe-m32_segmap); - set_bit(index, phb-ioda.m32_segmap); - rc = opal_pci_map_pe_mmio_window(phb-opal_id, - pe-pe_number, OPAL_M32_WINDOW_TYPE, - 0, index); - if (rc != OPAL_SUCCESS) { - pr_err(%s: OPAL error %d when mapping M32 - segment#%d to PE#%d, - __func__, rc, index, pe-pe_number); - break; - } + segsize = phb-ioda.m32_segsize; + segmap = phb-ioda.m32_segmap; + pe_segmap= pe-m32_segmap; + win = OPAL_M32_WINDOW_TYPE; + } else { + continue; + } - region.start += phb-ioda.m32_segsize; - index++; + index = region.start / phb-ioda.io_segsize; + while (index phb-ioda.total_pe + region.start = region.end) { + set_bit(index, segmap); + set_bit(index, pe_segmap); + rc = opal_pci_map_pe_mmio_window(phb-opal_id, + pe-pe_number, win, 0, index); + if (rc != OPAL_SUCCESS) { + pr_warn(%s: Error %lld mapping (%d) seg#%d to PHB#%d-PE#%d\n, + __func__, rc, win, index, +
[PATCH v6 22/42] powerpc/powernv: Move functions around
The patch moves functions related to releasing PE around so that we don't need extra declaration for them in subsequent patches. Also, it fixes warnings from scripts/checkpatch.pl. It doesn't introduce any behavioural changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 743 +++--- 1 file changed, 377 insertions(+), 366 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 84b771e..d2697a3 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -132,6 +132,295 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); } +static inline void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_ioda_pe *pe) +{ + /* 01xb - invalidate TCEs that match the specified PE# */ + unsigned long val = (0x4ull 60) | (pe-pe_number 0xFF); + struct pnv_phb *phb = pe-phb; + + if (!phb-ioda.tce_inval_reg) + return; + + mb(); /* Ensure above stores are visible */ + __raw_writeq(cpu_to_be64(val), phb-ioda.tce_inval_reg); +} + +#if defined(CONFIG_IOMMU_API) || defined(CONFIG_PCI_IOV) +static long pnv_pci_ioda2_unset_window(struct iommu_table_group *table_group, + int num) +{ + struct pnv_ioda_pe *pe = container_of(table_group, struct pnv_ioda_pe, + table_group); + struct pnv_phb *phb = pe-phb; + long ret; + + pe_info(pe, Removing DMA window #%d\n, num); + + ret = opal_pci_map_pe_dma_window(phb-opal_id, pe-pe_number, + (pe-pe_number 1) + num, + 0/* levels */, 0/* table address */, + 0/* table size */, 0/* page size */); + if (ret) + pe_warn(pe, Unmapping failed, ret = %ld\n, ret); + else + pnv_pci_ioda2_tce_invalidate_entire(pe); + + pnv_pci_unlink_table_and_group(table_group-tables[num], table_group); + + return ret; +} +#endif /* CONFIG_IOMMU_API || CONFIG_PCI_IOV */ + +static void pnv_pci_ioda2_set_bypass(struct pnv_ioda_pe *pe, bool enable) +{ + uint16_t window_id = (pe-pe_number 1) + 1; + int64_t rc; + + pe_info(pe, %sabling 64-bit DMA bypass\n, enable ? En : Dis); + if (enable) { + phys_addr_t top = memblock_end_of_DRAM(); + + top = roundup_pow_of_two(top); + rc = opal_pci_map_pe_dma_window_real(pe-phb-opal_id, +pe-pe_number, +window_id, +pe-tce_bypass_base, +top); + } else { + rc = opal_pci_map_pe_dma_window_real(pe-phb-opal_id, +pe-pe_number, +window_id, +pe-tce_bypass_base, +0); + } + if (rc) + pe_err(pe, OPAL error %lld configuring bypass window\n, rc); + else + pe-tce_bypass_enabled = enable; +} + +#ifdef CONFIG_PCI_IOV +static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, +struct pnv_ioda_pe *pe) +{ + struct iommu_table*tbl; + int64_t rc; + + tbl = pe-table_group.tables[0]; + rc = pnv_pci_ioda2_unset_window(pe-table_group, 0); + if (rc) + pe_warn(pe, OPAL error %ld release DMA window\n, rc); + + pnv_pci_ioda2_set_bypass(pe, false); + if (pe-table_group.group) { + iommu_group_put(pe-table_group.group); + BUG_ON(pe-table_group.group); + } + pnv_pci_ioda2_table_free_pages(tbl); + iommu_free_table(tbl, of_node_full_name(dev-dev.of_node)); +} +#endif /* CONFIG_PCI_IOV */ + +static int pnv_ioda_set_one_peltv(struct pnv_phb *phb, + struct pnv_ioda_pe *parent, + struct pnv_ioda_pe *child, + bool is_add) +{ + const char *desc = is_add ? adding : removing; + uint8_t op = is_add ? OPAL_ADD_PE_TO_DOMAIN : + OPAL_REMOVE_PE_FROM_DOMAIN; + struct pnv_ioda_pe *slave; + long rc; + + /* Parent PE affects child PE */ + rc = opal_pci_set_peltv(phb-opal_id, parent-pe_number, + child-pe_number, op); + if (rc != OPAL_SUCCESS) { + pe_warn(child, OPAL error %ld %s to parent PELTV\n, + rc, desc); + return -ENXIO; + } + + if (!(child-flags PNV_IODA_PE_MASTER)) + return 0; + +
[PATCH v6 35/42] powerpc/pci: Export traverse_pci_device_nodes()
Previously we wouldn't remove pdn because PCI hotplug isn't supported. update_dn_pci_info() is called at system booting time to create pdn for PCI device nodes. However, it's going to be changed later because of PCI hotplug. This converts update_dn_pci_info() to add_pci_device_node_info(), traverse_pci_devices() to traverse_pci_device_nodes(). This also adds remove_pci_device_node_info() which will be used in subsequent patch at the moment of unplugging PCI devices. All those functions are exported for PowerNV hotplug driver to use. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/include/asm/pci-bridge.h | 4 ++- arch/powerpc/include/asm/ppc-pci.h | 8 -- arch/powerpc/kernel/pci_dn.c | 51 +- arch/powerpc/platforms/pseries/setup.c | 2 +- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 787a879..010eb54 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -237,7 +237,9 @@ extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev); extern void remove_dev_pci_data(struct pci_dev *pdev); -extern void *update_dn_pci_info(struct device_node *dn, void *data); +extern void *add_pci_device_node_info(struct device_node *dn, + struct pci_controller *phb); +extern void remove_pci_device_node_info(struct device_node *np); static inline int pci_device_from_OF_node(struct device_node *np, u8 *bus, u8 *devfn) diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 916775d..c87ed42 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -33,9 +33,11 @@ extern struct pci_dev *isa_bridge_pcidev;/* may be NULL if no ISA bus */ struct device_node; struct pci_dn; -typedef void *(*traverse_func)(struct device_node *me, void *data); -void *traverse_pci_devices(struct device_node *start, traverse_func pre, - void *data); +typedef void *(*traverse_func)(struct device_node *me, + struct pci_controller *phb); +void *traverse_pci_device_nodes(struct device_node *start, + traverse_func pre, + struct pci_controller *phb); void *traverse_pci_dn(struct pci_dn *root, void *(*fn)(struct pci_dn *, void *), void *data); diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 53a11e9..3a38a55 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -283,9 +283,9 @@ void remove_dev_pci_data(struct pci_dev *pdev) * Traverse_func that inits the PCI fields of the device node. * NOTE: this *must* be done before read/write config to the device. */ -void *update_dn_pci_info(struct device_node *dn, void *data) +void *add_pci_device_node_info(struct device_node *dn, + struct pci_controller *phb) { - struct pci_controller *phb = data; const __be32 *type = of_get_property(dn, ibm,pci-config-space-type, NULL); const __be32 *regs; struct device_node *parent; @@ -342,6 +342,42 @@ void *update_dn_pci_info(struct device_node *dn, void *data) return NULL; } +EXPORT_SYMBOL(add_pci_device_node_info); + +/** + * remove_pci_device_node_info - Remove pci_dn from PCI device node + * @dn: PCI device node + * + * Remove pci_dn from PCI device node. The pci_dn is also removed + * from the child list of the parent pci_dn. + */ +void remove_pci_device_node_info(struct device_node *np) +{ + struct pci_dn *pdn = np ? PCI_DN(np) : NULL; +#ifdef CONFIG_EEH + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); +#endif + + if (!pdn) + return; + +#ifdef CONFIG_EEH + if (edev) { + pdn-edev = NULL; + kfree(edev); + } +#endif + + BUG_ON(!list_empty(pdn-child_list)); + list_del(pdn-list); + if (pdn-parent) + of_node_put(pdn-parent-node); + + np-data = NULL; + kfree(pdn); +} +EXPORT_SYMBOL(remove_pci_device_node_info); + /* * Traverse a device tree stopping each PCI device in the tree. @@ -361,8 +397,8 @@ void *update_dn_pci_info(struct device_node *dn, void *data) * one of these nodes we also assume its siblings are non-pci for * performance. */ -void *traverse_pci_devices(struct device_node *start, traverse_func pre, - void *data) +void *traverse_pci_device_nodes(struct device_node *start, traverse_func pre, + struct pci_controller *phb) { struct device_node *dn, *nextdn; void *ret; @@ -377,7 +413,7 @@ void
Re: [PATCH V2 3/6] powerpc/powernv: use one M64 BAR in Single PE mode for one VF BAR
On Wed, Aug 05, 2015 at 09:25:00AM +0800, Wei Yang wrote: In current implementation, when VF BAR is bigger than 64MB, it uses 4 M64 BAR in Single PE mode to cover the number of VFs required to be enabled. By doing so, several VFs would be in one VF Group and leads to interference between VFs in the same group. This patch changes the design by using one M64 BAR in Single PE mode for one VF BAR. This gives absolute isolation for VFs. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com --- arch/powerpc/include/asm/pci-bridge.h |5 +- arch/powerpc/platforms/powernv/pci-ioda.c | 180 - 2 files changed, 76 insertions(+), 109 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 712add5..8aeba4c 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -214,10 +214,9 @@ struct pci_dn { u16 vfs_expanded; /* number of VFs IOV BAR expanded */ u16 num_vfs;/* number of VFs enabled*/ int offset; /* PE# for the first VF PE */ -#define M64_PER_IOV 4 - int m64_per_iov; + boolm64_single_mode;/* Use M64 BAR in Single Mode */ #define IODA_INVALID_M64(-1) - int m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV]; + int (*m64_map)[PCI_SRIOV_NUM_BARS]; It can be explicit? For example: int *m64_map; /* Initialization */ size_t size = sizeof(*pdn-m64_map) * PCI_SRIOV_NUM_BARS * num_of_max_VFs; pdn-m64_map = kmalloc(size, GFP_KERNEL); for (i = 0; i PCI_SRIOV_NUM_BARS; i++) for (j = 0; j num_of_max_VFs; j++) pdn-m64_map[i * PCI_SRIOV_NUM_BARS + j] = PNV_INVALID_M64; /* Destroy */ int step = 1; if (!pdn-m64_single_mode) step = phb-ioda.total_pe; for (i = 0; i PCI_SRIOV_NUM_BARS * num_of_max_VFs; i += step) if (pdn-m64_map[i] == PNV_INVALID_M64) continue; /* Unmap the window */ #endif /* CONFIG_PCI_IOV */ #endif struct list_head child_list; diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7192e62..f5d110c 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1148,29 +1148,36 @@ static void pnv_pci_ioda_setup_PEs(void) } #ifdef CONFIG_PCI_IOV -static int pnv_pci_vf_release_m64(struct pci_dev *pdev) +static int pnv_pci_vf_release_m64(struct pci_dev *pdev, u16 num_vfs) { struct pci_bus*bus; struct pci_controller *hose; struct pnv_phb*phb; struct pci_dn *pdn; inti, j; + intm64_bars; bus = pdev-bus; hose = pci_bus_to_host(bus); phb = hose-private_data; pdn = pci_get_pdn(pdev); + if (pdn-m64_single_mode) + m64_bars = num_vfs; + else + m64_bars = 1; + for (i = 0; i PCI_SRIOV_NUM_BARS; i++) - for (j = 0; j M64_PER_IOV; j++) { - if (pdn-m64_wins[i][j] == IODA_INVALID_M64) + for (j = 0; j m64_bars; j++) { + if (pdn-m64_map[j][i] == IODA_INVALID_M64) continue; opal_pci_phb_mmio_enable(phb-opal_id, - OPAL_M64_WINDOW_TYPE, pdn-m64_wins[i][j], 0); - clear_bit(pdn-m64_wins[i][j], phb-ioda.m64_bar_alloc); - pdn-m64_wins[i][j] = IODA_INVALID_M64; + OPAL_M64_WINDOW_TYPE, pdn-m64_map[j][i], 0); + clear_bit(pdn-m64_map[j][i], phb-ioda.m64_bar_alloc); + pdn-m64_map[j][i] = IODA_INVALID_M64; } + kfree(pdn-m64_map); return 0; } @@ -1187,8 +1194,7 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs) inttotal_vfs; resource_size_tsize, start; intpe_num; - intvf_groups; - intvf_per_group; + intm64_bars; bus = pdev-bus; hose = pci_bus_to_host(bus); @@ -1196,26 +1202,26 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs) pdn = pci_get_pdn(pdev); total_vfs = pci_sriov_get_totalvfs(pdev); - /* Initialize the m64_wins to IODA_INVALID_M64 */ - for (i = 0; i PCI_SRIOV_NUM_BARS; i++) - for (j = 0; j M64_PER_IOV; j++) - pdn-m64_wins[i][j] = IODA_INVALID_M64; + if (pdn-m64_single_mode) + m64_bars = num_vfs; + else + m64_bars = 1; + + pdn-m64_map = kmalloc(sizeof(*pdn-m64_map) * m64_bars, GFP_KERNEL); + if (!pdn-m64_map) +
[PATCH v6 40/42] drivers/of: Return allocated memory chunk from of_fdt_unflatten_tree()
This changes of_fdt_unflatten_tree() so that it returns the allocated memory chunk for unflattened device-tree, which can be released once it's obsoleted. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- drivers/of/fdt.c | 11 ++- include/linux/of_fdt.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 074870a..8e1ba7e 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -408,7 +408,7 @@ static void *unflatten_dt_node(const void *blob, * @dt_alloc: An allocator that provides a virtual address to memory * for the resulting tree */ -static void __unflatten_device_tree(const void *blob, +static void *__unflatten_device_tree(const void *blob, struct device_node *dad, struct device_node **mynodes, void * (*dt_alloc)(u64 size, u64 align)) @@ -421,7 +421,7 @@ static void __unflatten_device_tree(const void *blob, if (!blob) { pr_debug(No device tree pointer\n); - return; + return NULL; } pr_debug(Unflattening device tree:\n); @@ -431,7 +431,7 @@ static void __unflatten_device_tree(const void *blob, if (fdt_check_header(blob)) { pr_err(Invalid device tree blob header\n); - return; + return NULL; } /* First pass, scan for size */ @@ -458,6 +458,7 @@ static void __unflatten_device_tree(const void *blob, be32_to_cpup(mem + size)); pr_debug( - unflatten_device_tree()\n); + return mem; } static void *kernel_tree_alloc(u64 size, u64 align) @@ -473,11 +474,11 @@ static void *kernel_tree_alloc(u64 size, u64 align) * pointers of the nodes so the normal device-tree walking functions * can be used. */ -void of_fdt_unflatten_tree(const unsigned long *blob, +void *of_fdt_unflatten_tree(const unsigned long *blob, struct device_node *dad, struct device_node **mynodes) { - __unflatten_device_tree(blob, dad, mynodes, kernel_tree_alloc); + return __unflatten_device_tree(blob, dad, mynodes, kernel_tree_alloc); } EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree); diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 3644960..00db279 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -37,7 +37,7 @@ extern bool of_fdt_is_big_endian(const void *blob, unsigned long node); extern int of_fdt_match(const void *blob, unsigned long node, const char *const *compat); -extern void of_fdt_unflatten_tree(const unsigned long *blob, +extern void *of_fdt_unflatten_tree(const unsigned long *blob, struct device_node *dad, struct device_node **mynodes); -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 25/42] powerpc/powernv: Use PCI slot reset infrastructure
The skiboot firmware might provide the capability of resetting PCI slot by property ibm,reset-by-firmware on the PCI slot associated device node. The patch checks on the property and route the reset to firmware if the property exists. Otherwise, we fail back to the old path as before. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/eeh-powernv.c | 44 +++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 0350dab..7be2ebf 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -843,7 +843,7 @@ out: return 0; } -static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) +static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option) { struct pci_dn *pdn = pci_get_pdn_by_devfn(dev-bus, dev-devfn); struct eeh_dev *edev = pdn_to_eeh_dev(pdn); @@ -894,6 +894,48 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) return 0; } +static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option) +{ + struct pci_controller *hose; + struct pnv_phb *phb; + struct device_node *dn = pdev ? pci_device_to_OF_node(pdev) : NULL; + uint64_t id = (0x1ul 60); + uint8_t scope; + int64_t rc; + + /* +* If the firmware can't handle it, we will issue hot reset +* on the secondary bus despite the requested reset type. +*/ + if (!dn || !of_get_property(dn, ibm,reset-by-firmware, NULL)) + return __pnv_eeh_bridge_reset(pdev, option); + + /* The firmware can handle the request */ + switch (option) { + case EEH_RESET_HOT: + scope = OPAL_RESET_PCI_HOT; + break; + case EEH_RESET_FUNDAMENTAL: + scope = OPAL_RESET_PCI_FUNDAMENTAL; + break; + case EEH_RESET_DEACTIVATE: + return 0; + default: + dev_warn(pdev-dev, %s: Unsupported reset %d\n, +__func__, option); + return -EINVAL; + } + + hose = pci_bus_to_host(pdev-bus); + phb = hose-private_data; + id |= (pdev-bus-number 24) | (pdev-devfn 16) | phb-opal_id; + rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET); + if (rc 0) + rc = pnv_eeh_poll(id); + + return (rc == OPAL_SUCCESS) ? 0 : -EIO; +} + static void pnv_eeh_wait_for_pending(struct pci_dn *pdn, int pos, u16 mask, bool af_flr_rst) { -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 27/42] powerpc/powernv: Don't cover root bus in pnv_pci_reset_secondary_bus()
pnv_pci_reset_secondary_bus(), invoked by pcibios_reset_secondary_bus() on PowerNV platform. The latter can't be called on root bus. So the former needn't cover root bus as well. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/eeh-powernv.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 95332e9..19cb947 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -1059,16 +1059,8 @@ static int pnv_eeh_vf_pe_reset(struct eeh_pe *pe, int option) void pnv_pci_reset_secondary_bus(struct pci_dev *dev) { - struct pci_controller *hose; - - if (pci_is_root_bus(dev-bus)) { - hose = pci_bus_to_host(dev-bus); - pnv_eeh_root_reset(hose, EEH_RESET_HOT); - pnv_eeh_root_reset(hose, EEH_RESET_DEACTIVATE); - } else { - pnv_eeh_bridge_reset(dev, EEH_RESET_HOT); - pnv_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE); - } + pnv_eeh_bridge_reset(dev, EEH_RESET_HOT); + pnv_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE); } /** -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 16/42] powerpc/powernv: Helper function pnv_ioda_init_pe()
The patch introduces helper function pnv_ioda_init_pe(), which initialize PE instance after reserving or allocating PE#, to simplify the code. The patch doesn't introduce behavioural changes. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9f53682..9cccf2d5 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -132,6 +132,17 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); } +static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no) +{ + struct pnv_ioda_pe *pe = phb-ioda.pe_array[pe_no]; + + pe-phb = phb; + pe-pe_number = pe_no; + INIT_LIST_HEAD(pe-list); + + return pe; +} + static struct pnv_ioda_pe *pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) { if (!(pe_no = 0 pe_no phb-ioda.total_pe)) { @@ -144,10 +155,7 @@ static struct pnv_ioda_pe *pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) pr_debug(%s: PE %d was reserved on PHB#%x\n, __func__, pe_no, phb-hose-global_number); - phb-ioda.pe_array[pe_no].phb = phb; - phb-ioda.pe_array[pe_no].pe_number = pe_no; - - return phb-ioda.pe_array[pe_no]; + return pnv_ioda_init_pe(phb, pe_no); } static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) @@ -161,9 +169,7 @@ static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb) return NULL; } while(test_and_set_bit(pe, phb-ioda.pe_alloc)); - phb-ioda.pe_array[pe].phb = phb; - phb-ioda.pe_array[pe].pe_number = pe; - return phb-ioda.pe_array[pe]; + return pnv_ioda_init_pe(phb, pe); } static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe) -- 2.1.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v6 23/42] powerpc/powernv: Release PEs dynamically
This adds the refcount to PE, which represents number of PCI devices contained in the PE. When last device leaves from the PE, the PE together with its consumed resources (IO, DMA, PELTM, PELTV) are released, to support PCI hotplug. Signed-off-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 233 +++--- arch/powerpc/platforms/powernv/pci.h | 3 + 2 files changed, 217 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index d2697a3..13d8a5b 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -132,6 +132,53 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); } +static void pnv_pci_ioda_release_pe_dma(struct pnv_ioda_pe *pe) +{ + struct pnv_phb *phb = pe-phb; + struct iommu_table *tbl; + int seg; + int64_t rc; + + /* No DMA32 segments allocated */ + if (pe-dma32_seg == PNV_INVALID_SEGMENT || + pe-dma32_segcount = 0) { + pe-dma32_seg = PNV_INVALID_SEGMENT; + pe-dma32_segcount = 0; + return; + } + + /* Unlink IOMMU table from group */ + tbl = pe-table_group.tables[0]; + pnv_pci_unlink_table_and_group(tbl, pe-table_group); + if (pe-table_group.group) { + iommu_group_put(pe-table_group.group); + BUG_ON(pe-table_group.group); + } + + /* Release IOMMU table */ + free_pages(tbl-it_base, + get_order(TCE32_TABLE_SIZE * pe-dma32_segcount)); + iommu_free_table(tbl, + of_node_full_name(pci_bus_to_OF_node(pe-pbus))); + + /* Disable TVE */ + for (seg = pe-dma32_seg; +seg pe-dma32_seg + pe-dma32_segcount; +seg++) { + rc = opal_pci_map_pe_dma_window(phb-opal_id, + pe-pe_number, seg, 0, 0ul, 0ul, 0ul); + if (rc) + pe_warn(pe, Error %ld unmapping DMA32 seg#%d\n, + rc, seg); + } + + /* Free the DMA32 segments */ + bitmap_clear(phb-ioda.dma32_segmap, + pe-dma32_seg, pe-dma32_segcount); + pe-dma32_seg = PNV_INVALID_SEGMENT; + pe-dma32_segcount = 0; +} + static inline void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_ioda_pe *pe) { /* 01xb - invalidate TCEs that match the specified PE# */ @@ -199,13 +246,15 @@ static void pnv_pci_ioda2_set_bypass(struct pnv_ioda_pe *pe, bool enable) pe-tce_bypass_enabled = enable; } -#ifdef CONFIG_PCI_IOV -static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, -struct pnv_ioda_pe *pe) +static void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe) { struct iommu_table*tbl; + struct device_node*dn; int64_t rc; + if (pe-dma32_seg == PNV_INVALID_SEGMENT) + return; + tbl = pe-table_group.tables[0]; rc = pnv_pci_ioda2_unset_window(pe-table_group, 0); if (rc) @@ -216,10 +265,91 @@ static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, iommu_group_put(pe-table_group.group); BUG_ON(pe-table_group.group); } + + if (pe-flags (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) + dn = pci_bus_to_OF_node(pe-pbus); + else if (pe-flags PNV_IODA_PE_DEV) + dn = pci_device_to_OF_node(pe-pdev); +#ifdef CONFIG_PCI_IOV + else if (pe-flags PNV_IODA_PE_VF) + dn = pci_device_to_OF_node(pe-parent_dev); +#endif + else + dn = NULL; + pnv_pci_ioda2_table_free_pages(tbl); - iommu_free_table(tbl, of_node_full_name(dev-dev.of_node)); + iommu_free_table(tbl, of_node_full_name(dn)); + pe-dma32_seg = PNV_INVALID_SEGMENT; +} + +static void pnv_ioda_release_pe_dma(struct pnv_ioda_pe *pe) +{ + struct pnv_phb *phb = pe-phb; + + switch (phb-type) { + case PNV_PHB_IODA1: + pnv_pci_ioda_release_pe_dma(pe); + break; + case PNV_PHB_IODA2: + pnv_pci_ioda2_release_pe_dma(pe); + break; + default: + pr_warn(%s: Cannot release DMA for PHB type %d\n, + __func__, phb-type); + } +} + +static void pnv_ioda_release_pe_one_seg(struct pnv_ioda_pe *pe, int win) +{ + struct pnv_phb *phb = pe-phb; + unsigned long *segmap = NULL; + unsigned long *pe_segmap = NULL; + int segno, limit, mod = 0; + + switch (win) { + case OPAL_IO_WINDOW_TYPE: + segmap = phb-ioda.io_segmap; + pe_segmap = pe-io_segmap; + break; + case OPAL_M32_WINDOW_TYPE: + segmap =
Re: [PATCH V2 2/6] powerpc/powernv: simplify the calculation of iov resource
On Wed, Aug 05, 2015 at 09:24:59AM +0800, Wei Yang wrote: The alignment of IOV BAR on PowerNV platform is the total size of the IOV BAR. No matter whether the IOV BAR is truncated or not, the total size could be calculated by (vfs_expanded * VF size). s/VF size/VF BAR size I think the changelog would be more explicit: The alignment of IOV BAR on PowerNV platform is the total size of the IOV BAR, no matter whether the IOV BAR is extended with number of max VFs or number of max PE number (256). The alignment can be calculated by (vfs_expaned * VF_BAR_size). This patch simplifies the pnv_pci_iov_resource_alignment() by removing the first case. Signed-off-by: Wei Yang weiy...@linux.vnet.ibm.com Reviewed-by: Gavin Shan gws...@linux.vnet.ibm.com --- arch/powerpc/platforms/powernv/pci-ioda.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9b41dba..7192e62 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2987,12 +2987,16 @@ static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev, int resno) { struct pci_dn *pdn = pci_get_pdn(pdev); - resource_size_t align, iov_align; - - iov_align = resource_size(pdev-resource[resno]); - if (iov_align) - return iov_align; + resource_size_t align; + /* + * On PowerNV platform, IOV BAR is mapped by M64 BAR to enable the + * SR-IOV. While from hardware perspective, the range mapped by M64 + * BAR should be size aligned. + * + * This function return the total IOV BAR size if expanded or just the + * individual size if not. + */ align = pci_iov_resource_size(pdev, resno); if (pdn-vfs_expanded) return pdn-vfs_expanded * align; -- 1.7.9.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 3/3] PowerPC/mpc85xx: Add hotplug support on E6500 cores
On Thu, 2015-08-06 at 12:32 +0800, Chenhui Zhao wrote: On Thu, Aug 6, 2015 at 11:16 AM, Scott Wood scottw...@freescale.com wrote: On Wed, 2015-08-05 at 19:08 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood scottw...@freescale.com wrote: On Fri, 2015-07-31 at 17:20 +0800, b29983@freescale.comwrote: + /* + * If both threads are offline, reset core to start. + * When core is up, Thread 0 always gets up first, + * so bind the current logical cpu with Thread 0. + */ + if (hw_cpu != cpu_first_thread_sibling(hw_cpu)) { + int hw_cpu1, hw_cpu2; + + hw_cpu1 = get_hard_smp_processor_id(primary); + hw_cpu2 = get_hard_smp_processor_id(primary + 1); + set_hard_smp_processor_id(primary, hw_cpu2); + set_hard_smp_processor_id(primary + 1, hw_cpu1); + /* get new physical cpu id */ + hw_cpu = get_hard_smp_processor_id(nr); NACK as discussed in http://patchwork.ozlabs.org/patch/454944/ -Scott You said, There's no need for this. I have booting from a thread1, and having it kick its thread0, working locally without messing with the hwid/cpu mapping. I still have questions here. After a core reset, how can you boot Thread1 of the core first. As I know, Thread0 boots up first by default. So the issue isn't that thread1 comes up first, but that you *want* thread1 to come up first and it won't. I don't think this remapping is an acceptable answer, though. Instead, if you need only thread1 to come up, start the core, have thread0 start thread1, and then send thread0 into whatever waiting state it would be in if thread1 had never been offlined. -Scott Remapping is a concise solution. what's the harm of it? Keeping things simple is good in my opinion. Remapping is not simple. Remapping will make debugging more complicated (I see an oops on CPU n, which CPU's registers do I dump in the debugger?), could expose bugs where smp_processor_id() is used where hard_smp_processor_id() is needed, etc. Having thread0 start thread1 and then go wherever it would have gone if thread1 were up the whole time is much more straightforward. -Scott ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev