* [PATCH 18/18] powerpc: enforce usage of RA 0-R31 where possible
From: Michael Neuling @ 2012-06-25 23:33 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: mikey, matt, linuxppc-dev, schwab, Anton Blanchard,
Olof Johannsson
In-Reply-To: <1340667187.357853.615199632713.qpush@ale>
Some macros use RA where when RA=R0 the values is 0, so make this
the enforced mnemonic in the macro.
Idea suggested by Andreas Schwab.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
---
Index: b/arch/powerpc/include/asm/ppc-opcode.h
===================================================================
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -231,7 +231,7 @@
#define PPC_RFDI stringify_in_c(.long PPC_INST_RFDI)
#define PPC_RFMCI stringify_in_c(.long PPC_INST_RFMCI)
#define PPC_TLBILX(t, a, b) stringify_in_c(.long PPC_INST_TLBILX | \
- __PPC_T_TLB(t) | __PPC_RA(a) | __PPC_RB(b))
+ __PPC_T_TLB(t) | __PPC_RA0(a) | __PPC_RB(b))
#define PPC_TLBILX_ALL(a, b) PPC_TLBILX(0, a, b)
#define PPC_TLBILX_PID(a, b) PPC_TLBILX(1, a, b)
#define PPC_TLBILX_VA(a, b) PPC_TLBILX(3, a, b)
@@ -240,23 +240,23 @@
#define PPC_TLBIE(lp,a) stringify_in_c(.long PPC_INST_TLBIE | \
___PPC_RB(a) | ___PPC_RS(lp))
#define PPC_TLBSRX_DOT(a,b) stringify_in_c(.long PPC_INST_TLBSRX_DOT | \
- __PPC_RA(a) | __PPC_RB(b))
+ __PPC_RA0(a) | __PPC_RB(b))
#define PPC_TLBIVAX(a,b) stringify_in_c(.long PPC_INST_TLBIVAX | \
- __PPC_RA(a) | __PPC_RB(b))
+ __PPC_RA0(a) | __PPC_RB(b))
#define PPC_ERATWE(s, a, w) stringify_in_c(.long PPC_INST_ERATWE | \
__PPC_RS(s) | __PPC_RA(a) | __PPC_WS(w))
#define PPC_ERATRE(s, a, w) stringify_in_c(.long PPC_INST_ERATRE | \
__PPC_RS(s) | __PPC_RA(a) | __PPC_WS(w))
#define PPC_ERATILX(t, a, b) stringify_in_c(.long PPC_INST_ERATILX | \
- __PPC_T_TLB(t) | __PPC_RA(a) | \
+ __PPC_T_TLB(t) | __PPC_RA0(a) | \
__PPC_RB(b))
#define PPC_ERATIVAX(s, a, b) stringify_in_c(.long PPC_INST_ERATIVAX | \
- __PPC_RS(s) | __PPC_RA(a) | __PPC_RB(b))
+ __PPC_RS(s) | __PPC_RA0(a) | __PPC_RB(b))
#define PPC_ERATSX(t, a, w) stringify_in_c(.long PPC_INST_ERATSX | \
- __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
+ __PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
#define PPC_ERATSX_DOT(t, a, w) stringify_in_c(.long PPC_INST_ERATSX_DOT | \
- __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
+ __PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
#define PPC_SLBFEE_DOT(t, b) stringify_in_c(.long PPC_INST_SLBFEE | \
__PPC_RT(t) | __PPC_RB(b))
/* PASemi instructions */
Index: b/arch/powerpc/kernel/cpu_setup_a2.S
===================================================================
--- a/arch/powerpc/kernel/cpu_setup_a2.S
+++ b/arch/powerpc/kernel/cpu_setup_a2.S
@@ -112,7 +112,7 @@ _icswx_skip_guest:
* a bolted entry though it will be in LRU and so will go away eventually
* but let's not bother for now
*/
- PPC_ERATILX(0,R0,R0)
+ PPC_ERATILX(0,0,R0)
1:
blr
Index: b/arch/powerpc/kernel/exceptions-64e.S
===================================================================
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -903,7 +903,7 @@ skpinv: addi r6,r6,1 /* Increment */
bne 1b /* If not, repeat */
/* Invalidate all TLBs */
- PPC_TLBILX_ALL(R0,R0)
+ PPC_TLBILX_ALL(0,R0)
sync
isync
@@ -961,7 +961,7 @@ skpinv: addi r6,r6,1 /* Increment */
tlbwe
/* Invalidate TLB1 */
- PPC_TLBILX_ALL(R0,R0)
+ PPC_TLBILX_ALL(0,R0)
sync
isync
@@ -1020,7 +1020,7 @@ skpinv: addi r6,r6,1 /* Increment */
tlbwe
/* Invalidate TLB1 */
- PPC_TLBILX_ALL(R0,R0)
+ PPC_TLBILX_ALL(0,R0)
sync
isync
@@ -1138,7 +1138,7 @@ a2_tlbinit_after_iprot_flush:
tlbwe
#endif /* CONFIG_PPC_EARLY_DEBUG_WSP */
- PPC_TLBILX(0,R0,R0)
+ PPC_TLBILX(0,0,R0)
sync
isync
Index: b/arch/powerpc/mm/tlb_low_64e.S
===================================================================
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -126,7 +126,7 @@ BEGIN_MMU_FTR_SECTION
/* Set the TLB reservation and search for existing entry. Then load
* the entry.
*/
- PPC_TLBSRX_DOT(R0,R16)
+ PPC_TLBSRX_DOT(0,R16)
ldx r14,r14,r15 /* grab pgd entry */
beq normal_tlb_miss_done /* tlb exists already, bail */
MMU_FTR_SECTION_ELSE
@@ -395,7 +395,7 @@ BEGIN_MMU_FTR_SECTION
/* Set the TLB reservation and search for existing entry. Then load
* the entry.
*/
- PPC_TLBSRX_DOT(R0,R16)
+ PPC_TLBSRX_DOT(0,R16)
ld r14,0(r10)
beq normal_tlb_miss_done
MMU_FTR_SECTION_ELSE
@@ -528,7 +528,7 @@ BEGIN_MMU_FTR_SECTION
/* Search if we already have a TLB entry for that virtual address, and
* if we do, bail out.
*/
- PPC_TLBSRX_DOT(R0,R16)
+ PPC_TLBSRX_DOT(0,R16)
beq virt_page_table_tlb_miss_done
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TLBRSRV)
@@ -779,7 +779,7 @@ htw_tlb_miss:
*
* MAS1:IND should be already set based on MAS4
*/
- PPC_TLBSRX_DOT(R0,R16)
+ PPC_TLBSRX_DOT(0,R16)
beq htw_tlb_miss_done
/* Now, we need to walk the page tables. First check if we are in
@@ -919,7 +919,7 @@ tlb_load_linear:
mtspr SPRN_MAS1,r15
/* Already somebody there ? */
- PPC_TLBSRX_DOT(R0,R16)
+ PPC_TLBSRX_DOT(0,R16)
beq tlb_load_linear_done
/* Now we build the remaining MAS. MAS0 and 2 should be fine
Index: b/arch/powerpc/mm/tlb_nohash_low.S
===================================================================
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -266,7 +266,7 @@ BEGIN_MMU_FTR_SECTION
andi. r3,r3,MMUCSR0_TLBFI@l
bne 1b
MMU_FTR_SECTION_ELSE
- PPC_TLBILX_ALL(R0,R0)
+ PPC_TLBILX_ALL(0,R0)
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
msync
isync
@@ -279,7 +279,7 @@ BEGIN_MMU_FTR_SECTION
wrteei 0
mfspr r4,SPRN_MAS6 /* save MAS6 */
mtspr SPRN_MAS6,r3
- PPC_TLBILX_PID(R0,R0)
+ PPC_TLBILX_PID(0,R0)
mtspr SPRN_MAS6,r4 /* restore MAS6 */
wrtee r10
MMU_FTR_SECTION_ELSE
@@ -313,7 +313,7 @@ BEGIN_MMU_FTR_SECTION
mtspr SPRN_MAS1,r4
tlbwe
MMU_FTR_SECTION_ELSE
- PPC_TLBILX_VA(R0,R3)
+ PPC_TLBILX_VA(0,R3)
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
msync
isync
@@ -331,7 +331,7 @@ _GLOBAL(_tlbil_pid)
mfmsr r10
wrteei 0
mtspr SPRN_MAS6,r4
- PPC_TLBILX_PID(R0,R0)
+ PPC_TLBILX_PID(0,R0)
wrtee r10
msync
isync
@@ -343,14 +343,14 @@ _GLOBAL(_tlbil_pid_noind)
ori r4,r4,MAS6_SIND
wrteei 0
mtspr SPRN_MAS6,r4
- PPC_TLBILX_PID(R0,R0)
+ PPC_TLBILX_PID(0,R0)
wrtee r10
msync
isync
blr
_GLOBAL(_tlbil_all)
- PPC_TLBILX_ALL(R0,R0)
+ PPC_TLBILX_ALL(0,R0)
msync
isync
blr
@@ -364,7 +364,7 @@ _GLOBAL(_tlbil_va)
beq 1f
rlwimi r4,r6,MAS6_SIND_SHIFT,MAS6_SIND
1: mtspr SPRN_MAS6,r4 /* assume AS=0 for now */
- PPC_TLBILX_VA(R0,R3)
+ PPC_TLBILX_VA(0,R3)
msync
isync
wrtee r10
@@ -379,7 +379,7 @@ _GLOBAL(_tlbivax_bcast)
beq 1f
rlwimi r4,r6,MAS6_SIND_SHIFT,MAS6_SIND
1: mtspr SPRN_MAS6,r4 /* assume AS=0 for now */
- PPC_TLBIVAX(R0,R3)
+ PPC_TLBIVAX(0,R3)
eieio
tlbsync
sync
^ permalink raw reply
* Re: [PATCH v2 1/1] of: reform prom_update_property function
From: Rob Herring @ 2012-06-25 23:40 UTC (permalink / raw)
To: Dong Aisheng, Benjamin Herrenschmidt
Cc: linuxppc-dev, devicetree-discuss, paulus, linux-kernel
In-Reply-To: <1340605714-25206-1-git-send-email-b29396@freescale.com>
On 06/25/2012 01:28 AM, Dong Aisheng wrote:
> From: Dong Aisheng <dong.aisheng@linaro.org>
>
> prom_update_property() currently fails if the property doesn't
> actually exist yet which isn't what we want. Change to add-or-update
> instead of update-only, then we can remove a lot duplicated lines.
>
> Suggested-by: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
Acked-by: Rob Herring <rob.herring@calxeda.com>
Ben, you can merge this via powerpc.
Rob
> ---
> ChangeLog v1->v2:
> * keep reconfig.c behavior the same as before after changes
> ---
> arch/powerpc/platforms/85xx/p1022_ds.c | 8 +-------
> arch/powerpc/platforms/pseries/mobility.c | 8 +-------
> arch/powerpc/platforms/pseries/reconfig.c | 16 ++++++----------
> drivers/of/base.c | 15 +++++++++++----
> fs/proc/proc_devtree.c | 5 +++++
> include/linux/of.h | 3 +--
> 6 files changed, 25 insertions(+), 30 deletions(-)
>
> diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
> index f700c81..d66631c 100644
> --- a/arch/powerpc/platforms/85xx/p1022_ds.c
> +++ b/arch/powerpc/platforms/85xx/p1022_ds.c
> @@ -348,13 +348,7 @@ void __init p1022_ds_pic_init(void)
> */
> static void __init disable_one_node(struct device_node *np, struct property *new)
> {
> - struct property *old;
> -
> - old = of_find_property(np, new->name, NULL);
> - if (old)
> - prom_update_property(np, new, old);
> - else
> - prom_add_property(np, new);
> + prom_update_property(np, new);
> }
>
> /* TRUE if there is a "video=fslfb" command-line parameter. */
> diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
> index 029a562..dd30b12 100644
> --- a/arch/powerpc/platforms/pseries/mobility.c
> +++ b/arch/powerpc/platforms/pseries/mobility.c
> @@ -67,7 +67,6 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
> const char *name, u32 vd, char *value)
> {
> struct property *new_prop = *prop;
> - struct property *old_prop;
> int more = 0;
>
> /* A negative 'vd' value indicates that only part of the new property
> @@ -117,12 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
> }
>
> if (!more) {
> - old_prop = of_find_property(dn, new_prop->name, NULL);
> - if (old_prop)
> - prom_update_property(dn, new_prop, old_prop);
> - else
> - prom_add_property(dn, new_prop);
> -
> + prom_update_property(dn, new_prop);
> new_prop = NULL;
> }
>
> diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
> index 7b3bf76..db1b7b1 100644
> --- a/arch/powerpc/platforms/pseries/reconfig.c
> +++ b/arch/powerpc/platforms/pseries/reconfig.c
> @@ -432,7 +432,7 @@ static int do_update_property(char *buf, size_t bufsize)
> unsigned char *value;
> char *name, *end, *next_prop;
> int rc, length;
> - struct property *newprop, *oldprop;
> + struct property *newprop;
> buf = parse_node(buf, bufsize, &np);
> end = buf + bufsize;
>
> @@ -443,6 +443,9 @@ static int do_update_property(char *buf, size_t bufsize)
> if (!next_prop)
> return -EINVAL;
>
> + if (!strlen(name)
> + return -ENODEV;
> +
> newprop = new_property(name, length, value, NULL);
> if (!newprop)
> return -ENOMEM;
> @@ -450,18 +453,11 @@ static int do_update_property(char *buf, size_t bufsize)
> if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
> slb_set_size(*(int *)value);
>
> - oldprop = of_find_property(np, name,NULL);
> - if (!oldprop) {
> - if (strlen(name))
> - return prom_add_property(np, newprop);
> - return -ENODEV;
> - }
> -
> upd_value.node = np;
> upd_value.property = newprop;
> pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
>
> - rc = prom_update_property(np, newprop, oldprop);
> + rc = prom_update_property(np, newprop);
> if (rc)
> return rc;
>
> @@ -486,7 +482,7 @@ static int do_update_property(char *buf, size_t bufsize)
>
> rc = pSeries_reconfig_notify(action, value);
> if (rc) {
> - prom_update_property(np, oldprop, newprop);
> + prom_update_property(np, newprop);
> return rc;
> }
> }
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d9bfd49..a14f109 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -1051,7 +1051,8 @@ int prom_remove_property(struct device_node *np, struct property *prop)
> }
>
> /*
> - * prom_update_property - Update a property in a node.
> + * prom_update_property - Update a property in a node, if the property does
> + * not exist, add it.
> *
> * Note that we don't actually remove it, since we have given out
> * who-knows-how-many pointers to the data using get-property.
> @@ -1059,13 +1060,19 @@ int prom_remove_property(struct device_node *np, struct property *prop)
> * and add the new property to the property list
> */
> int prom_update_property(struct device_node *np,
> - struct property *newprop,
> - struct property *oldprop)
> + struct property *newprop)
> {
> - struct property **next;
> + struct property **next, *oldprop;
> unsigned long flags;
> int found = 0;
>
> + if (!newprop->name)
> + return -EINVAL;
> +
> + oldprop = of_find_property(np, newprop->name, NULL);
> + if (!oldprop)
> + return prom_add_property(np, newprop);
> +
> write_lock_irqsave(&devtree_lock, flags);
> next = &np->properties;
> while (*next) {
> diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
> index 927cbd1..df7dd08 100644
> --- a/fs/proc/proc_devtree.c
> +++ b/fs/proc/proc_devtree.c
> @@ -101,6 +101,11 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
> {
> struct proc_dir_entry *ent;
>
> + if (!oldprop) {
> + proc_device_tree_add_prop(pde, newprop);
> + return;
> + }
> +
> for (ent = pde->subdir; ent != NULL; ent = ent->next)
> if (ent->data == oldprop)
> break;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 2ec1083..b27c871 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -260,8 +260,7 @@ extern int of_machine_is_compatible(const char *compat);
> extern int prom_add_property(struct device_node* np, struct property* prop);
> extern int prom_remove_property(struct device_node *np, struct property *prop);
> extern int prom_update_property(struct device_node *np,
> - struct property *newprop,
> - struct property *oldprop);
> + struct property *newprop);
>
> #if defined(CONFIG_OF_DYNAMIC)
> /* For updating the device tree at runtime */
^ permalink raw reply
* Re: [PATCH V3 1/2] PCI: retrieve host bridge by PCI bus
From: Gavin Shan @ 2012-06-26 0:30 UTC (permalink / raw)
To: Yinghai Lu; +Cc: bhelgaas, linux-pci, Gavin Shan, linuxppc-dev
In-Reply-To: <CAE9FiQUE0_niTRmvZ=ROSFKB4HKDFFLjfJC+QeQkTKLMyvxv4g@mail.gmail.com>
>> With current implementation, there is one function to retrieve
>> the corresponding host bridge (struct pci_host_bridge) according
>> to the given PCI device (struct pci_dev) and that function has
>> been declared as "static". Further, we don't have the public
>> function to retrieve host bridge from PCI bus yet. The function
>> is useful somewhere.
>>
>> The additional information like minimal resource alignment for I/O
>> and MMIO bars of p2p bridges will be put into the PCI host bridge.
>> The patch introduces the public function pci_bus_host_bridge() to
>> retrieve the corresponding PCI host bridge according to the specified
>> PCI bus, then accessing the information regarding the minimal resource
>> alignment for I/O and MMIO bars of p2p bridges.
>>
>> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>> Reviewed-by: Ram Pai <linuxram@us.ibm.com>
>> Reviewed-by: Richard Yang <weiyang@linux.vnet.ibm.com>
>> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> ---
>> drivers/pci/host-bridge.c | 13 +++++++++++++
>> include/linux/pci.h | 2 +-
>> 2 files changed, 14 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
>> index a68dc61..b95f0ce 100644
>> --- a/drivers/pci/host-bridge.c
>> +++ b/drivers/pci/host-bridge.c
>> @@ -27,6 +27,19 @@ static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
>> return to_pci_host_bridge(bus->bridge);
>> }
>>
>> +struct pci_host_bridge *pci_bus_host_bridge(struct pci_bus *bus)
>> +{
>> + struct pci_bus *b = bus;
>> +
>> + /* Find the PCI root bus */
>> + while (b->parent)
>> + b = b->parent;
>> +
>> + return to_pci_host_bridge(b->bridge);
>> +}
>> +
>> +EXPORT_SYMBOL(pci_bus_host_bridge);
Yinghai, thanks for your time on this :-)
>
>why do you need to export it?
>
The reason is that we have introduced extra fields to "struct pci_host_bridge"
in [PATCH 2/2] and platform want to access those extra fields.
int io_align_shift; /* P2P I/O bar minimal alignment shift */
int mem_align_shift; /* P2P MMIO bar minimal alignment shift */
int pmem_align_shift; /* P2P prefetchable MMIO bar minimal alignment shift */
>> +
>> void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
>> void (*release_fn)(struct pci_host_bridge *),
>> void *release_data)
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index fefb4e1..6d5bb1c 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -656,7 +656,7 @@ void pcibios_update_irq(struct pci_dev *, int irq);
>> void pci_fixup_cardbus(struct pci_bus *);
>>
>> /* Generic PCI functions used internally */
>> -
>> +struct pci_host_bridge *pci_bus_host_bridge(struct pci_bus *bus);
>> void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
>> struct resource *res);
>> void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
>
>have one patch will change parameter all to bus instead of bridge.
>
>http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=3dc90c8f31e5e6153e1ac9a903189d3013690e80
>
>in that case, we can just make find_pci_host_bridge() global.
>
Yeah, I think your patch meets the requirement: access "struct pci_host_bridge",
and when will you merge your patch into mainline?
By the way, could you please take your a litle bit time to review [PATCH 2/2]?
>Thanks
>
>Yinghai
>
Thanks,
Gavin
^ permalink raw reply
* RE: [PATCH 0/6] Description for PCI patches using platform driver
From: Jia Hongtao-B38951 @ 2012-06-26 2:33 UTC (permalink / raw)
To: Bhushan Bharat-R65777, linuxppc-dev@lists.ozlabs.org,
galak@kernel.crashing.org, benh@kernel.crashing.org
Cc: Wood Scott-B07421, Li Yang-R58472, Jia Hongtao-B38951
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D01A0C2DA@039-SN1MPN1-002.039d.mgd.msft.net>
Hello Ben and Kumar,
Do you have any concerns or comments on these series of patches?
Would you please have a review?
Thanks.
-Jia Hongtao.
> -----Original Message-----
> From: Linuxppc-dev [mailto:linuxppc-dev-
> bounces+b38951=3Dfreescale.com@lists.ozlabs.org] On Behalf Of Jia Hongtao=
-
> B38951
> Sent: Wednesday, June 20, 2012 10:34 AM
> To: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org;
> galak@kernel.crashing.org; benh@kernel.crashing.org
> Cc: Wood Scott-B07421; Li Yang-R58472
> Subject: RE: [PATCH 0/6] Description for PCI patches using platform
> driver
>=20
> Hello Ben, Kumar, others:
>=20
> This series of patches had been pending for a long time on upstream.
> We fixed some issues we found and there still some issues should be
> discussed like swiotlb init thing. Do you have time for a review?
>=20
> Thanks.
> -Jia Hongtao.
>=20
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Thursday, June 14, 2012 5:52 PM
> > To: Jia Hongtao-B38951; linuxppc-dev@lists.ozlabs.org;
> > galak@kernel.crashing.org; benh@kernel.crashing.org
> > Cc: Li Yang-R58472; Wood Scott-B07421
> > Subject: RE: [PATCH 0/6] Description for PCI patches using platform
> > driver
> >
> > Hello Ben, Kumar, others
> >
> > Please provide your comments/thoughts on this ?
> >
> > Thanks
> > -Bharat
> >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Jia Hongtao-B38951
> > > > > > > Sent: Friday, June 08, 2012 3:12 PM
> > > > > > > To: linuxppc-dev@lists.ozlabs.org; galak@kernel.crashing.org
> > > > > > > Cc: Li Yang-R58472; benh@kernel.crashing.org; Wood Scott-
> B07421;
> > > > > > Bhushan Bharat-
> > > > > > > R65777; Jia Hongtao-B38951
> > > > > > > Subject: [PATCH 0/6] Description for PCI patches using
> platform
> > > > > > > driver
> > > > > > >
> > > > > > > This series of patches are to unify pci initialization code
> and
> > > > > > > add PM
> > > > > > support
> > > > > > > for all 85xx/86xx powerpc boards. But two side effects are
> > > > > > > introduced
> > > > > > by this
> > > > > > > mechanism which listed below:
> > > > > > >
> > > > > > > 1. of_platform_bus_probe() will be called twice but in some
> > > > > > > cases
> > > > > > duplication
> > > > > > > warning occured. We fix this in [PATCH 5/6].
> > > > > > >
> > > > > > > 2. Edac driver failed to register pci nodes as platform
> devices.
> > > > > > > We fix
> > > > > > this
> > > > > > > in [PATCH 6/6].
> > > > > >
> > > > > > With these patches will not the SWIOTLB will not be initialized
> > > > > > even if PCI/PCIe demanded?
> > > > > >
> > > > > > Thanks
> > > > > > -Bharat
> > > > > >
> > > > >
> > > > > These patches still have the swiotlb init problem if
> > > > "ppc_swiotlb_enable" is
> > > > > only demanded by PCI/PCIe. One of the purposes of sending out
> these
> > > > patches is
> > > > > to let us start a discussion for this problem in upstream.
> > > >
> > > > Ok, I did not find any mention of that, so I thought that you have
> > > > resolved the issue by some means in these patches which I did not
> > catch.
> > > >
> > > > So, these patches introduces the issue, that SWIOTLB will not be
> > > > initialized if requested by pci/pcie. The request is raised by
> > setting
> > > > the flag ppc_swiotlb_enable. The swiotlb_init() will be called in
> > > > mem_init() if ppc_swiotlb_enable is set. Now with these patches,
> the
> > > > request is raised after mem_init() is called. So request not
> > handled :).
> > > >
> > > > Following are the solutions we have thought of during our internal
> > > > discussions (if I did not missed any):
> > > >
> > > > 1. These patches move the code from platform init to device init
> > > > (arch_initcall()). Rather than moving the whole code, let us divide
> > > > the code into two. First, which is needed to raise the swiotlb init
> > > > request and second the rest. Define this first as an function in
> > > > arch/powerpc/sysdev/fsl_pci.c and call this from platform init code
> > of
> > > > the SOCs.
> > > >
> > > > 2. All known devices, the lowest PCIe outbound range starts at
> > > > 0x80000000, but there's nothing above 0xc0000000. So the inbound of
> > > > size 0x8000_0000 is always availbe on all devices. Hardcode the
> check
> > > > in platform code to check memblock_end_of_DRAM() to 0x80000000.
> > > >
> > > > Something like this:
> > > >
> > > > diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > b/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > index 1f7028e..ef4e215 100644
> > > > --- a/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > +++ b/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > @@ -79,7 +79,7 @@ void __init corenet_ds_setup_arch(void) #endif
> > > >
> > > > #ifdef CONFIG_SWIOTLB
> > > > - if (memblock_end_of_DRAM() > 0xffffffff)
> > > > + if (memblock_end_of_DRAM() > 0xff000000)
> > > > ppc_swiotlb_enable =3D 1; #endif
> > > > pr_info("%s board from Freescale Semiconductor\n",
> > > > ppc_md.name);
> > > >
> > > > -------------
> > > >
> > > > 3. Always do swiotlb_init() in mem_init() and later after PCI init,
> > if
> > > > the swiotlb is not needed then free it (swiotlb_free()).
> > > >
> > > > 4. etc, please provide some other better way.
> > > >
> > > > Thanks
> > > > -Bharat
> > >
> > > Thanks.
> > > In my point of view the 2nd solution is better for it does not treat
> > PCI/PCIe as
> > > the special kind of devices from others.
> > >
> > > -Jia Hongtao.
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* RE: [PATCH 0/6] Description for PCI patches using platform driver
From: Benjamin Herrenschmidt @ 2012-06-26 2:46 UTC (permalink / raw)
To: Jia Hongtao-B38951
Cc: Wood Scott-B07421, Li Yang-R58472, linuxppc-dev@lists.ozlabs.org,
Bhushan Bharat-R65777
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D01A0EA1F@039-SN1MPN1-002.039d.mgd.msft.net>
On Tue, 2012-06-26 at 02:33 +0000, Jia Hongtao-B38951 wrote:
> Hello Ben and Kumar,
>
> Do you have any concerns or comments on these series of patches?
> Would you please have a review?
My main concern is that currently the PCI code has some assumptions
about ordering of things that will get violated.
For example, the pci final fixups are an fs_initcall iirc, or something
like that. There's other similar oddities that might become problematic.
In addition, there might be locking issues if you start doing multiple
PHBs in parallel.
Now we do want to fix all that long run but it might take a while.
Cheers,
Ben.
> Thanks.
> -Jia Hongtao.
>
> > -----Original Message-----
> > From: Linuxppc-dev [mailto:linuxppc-dev-
> > bounces+b38951=freescale.com@lists.ozlabs.org] On Behalf Of Jia Hongtao-
> > B38951
> > Sent: Wednesday, June 20, 2012 10:34 AM
> > To: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org;
> > galak@kernel.crashing.org; benh@kernel.crashing.org
> > Cc: Wood Scott-B07421; Li Yang-R58472
> > Subject: RE: [PATCH 0/6] Description for PCI patches using platform
> > driver
> >
> > Hello Ben, Kumar, others:
> >
> > This series of patches had been pending for a long time on upstream.
> > We fixed some issues we found and there still some issues should be
> > discussed like swiotlb init thing. Do you have time for a review?
> >
> > Thanks.
> > -Jia Hongtao.
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, June 14, 2012 5:52 PM
> > > To: Jia Hongtao-B38951; linuxppc-dev@lists.ozlabs.org;
> > > galak@kernel.crashing.org; benh@kernel.crashing.org
> > > Cc: Li Yang-R58472; Wood Scott-B07421
> > > Subject: RE: [PATCH 0/6] Description for PCI patches using platform
> > > driver
> > >
> > > Hello Ben, Kumar, others
> > >
> > > Please provide your comments/thoughts on this ?
> > >
> > > Thanks
> > > -Bharat
> > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Jia Hongtao-B38951
> > > > > > > > Sent: Friday, June 08, 2012 3:12 PM
> > > > > > > > To: linuxppc-dev@lists.ozlabs.org; galak@kernel.crashing.org
> > > > > > > > Cc: Li Yang-R58472; benh@kernel.crashing.org; Wood Scott-
> > B07421;
> > > > > > > Bhushan Bharat-
> > > > > > > > R65777; Jia Hongtao-B38951
> > > > > > > > Subject: [PATCH 0/6] Description for PCI patches using
> > platform
> > > > > > > > driver
> > > > > > > >
> > > > > > > > This series of patches are to unify pci initialization code
> > and
> > > > > > > > add PM
> > > > > > > support
> > > > > > > > for all 85xx/86xx powerpc boards. But two side effects are
> > > > > > > > introduced
> > > > > > > by this
> > > > > > > > mechanism which listed below:
> > > > > > > >
> > > > > > > > 1. of_platform_bus_probe() will be called twice but in some
> > > > > > > > cases
> > > > > > > duplication
> > > > > > > > warning occured. We fix this in [PATCH 5/6].
> > > > > > > >
> > > > > > > > 2. Edac driver failed to register pci nodes as platform
> > devices.
> > > > > > > > We fix
> > > > > > > this
> > > > > > > > in [PATCH 6/6].
> > > > > > >
> > > > > > > With these patches will not the SWIOTLB will not be initialized
> > > > > > > even if PCI/PCIe demanded?
> > > > > > >
> > > > > > > Thanks
> > > > > > > -Bharat
> > > > > > >
> > > > > >
> > > > > > These patches still have the swiotlb init problem if
> > > > > "ppc_swiotlb_enable" is
> > > > > > only demanded by PCI/PCIe. One of the purposes of sending out
> > these
> > > > > patches is
> > > > > > to let us start a discussion for this problem in upstream.
> > > > >
> > > > > Ok, I did not find any mention of that, so I thought that you have
> > > > > resolved the issue by some means in these patches which I did not
> > > catch.
> > > > >
> > > > > So, these patches introduces the issue, that SWIOTLB will not be
> > > > > initialized if requested by pci/pcie. The request is raised by
> > > setting
> > > > > the flag ppc_swiotlb_enable. The swiotlb_init() will be called in
> > > > > mem_init() if ppc_swiotlb_enable is set. Now with these patches,
> > the
> > > > > request is raised after mem_init() is called. So request not
> > > handled :).
> > > > >
> > > > > Following are the solutions we have thought of during our internal
> > > > > discussions (if I did not missed any):
> > > > >
> > > > > 1. These patches move the code from platform init to device init
> > > > > (arch_initcall()). Rather than moving the whole code, let us divide
> > > > > the code into two. First, which is needed to raise the swiotlb init
> > > > > request and second the rest. Define this first as an function in
> > > > > arch/powerpc/sysdev/fsl_pci.c and call this from platform init code
> > > of
> > > > > the SOCs.
> > > > >
> > > > > 2. All known devices, the lowest PCIe outbound range starts at
> > > > > 0x80000000, but there's nothing above 0xc0000000. So the inbound of
> > > > > size 0x8000_0000 is always availbe on all devices. Hardcode the
> > check
> > > > > in platform code to check memblock_end_of_DRAM() to 0x80000000.
> > > > >
> > > > > Something like this:
> > > > >
> > > > > diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > > b/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > > index 1f7028e..ef4e215 100644
> > > > > --- a/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > > +++ b/arch/powerpc/platforms/85xx/corenet_ds.c
> > > > > @@ -79,7 +79,7 @@ void __init corenet_ds_setup_arch(void) #endif
> > > > >
> > > > > #ifdef CONFIG_SWIOTLB
> > > > > - if (memblock_end_of_DRAM() > 0xffffffff)
> > > > > + if (memblock_end_of_DRAM() > 0xff000000)
> > > > > ppc_swiotlb_enable = 1; #endif
> > > > > pr_info("%s board from Freescale Semiconductor\n",
> > > > > ppc_md.name);
> > > > >
> > > > > -------------
> > > > >
> > > > > 3. Always do swiotlb_init() in mem_init() and later after PCI init,
> > > if
> > > > > the swiotlb is not needed then free it (swiotlb_free()).
> > > > >
> > > > > 4. etc, please provide some other better way.
> > > > >
> > > > > Thanks
> > > > > -Bharat
> > > >
> > > > Thanks.
> > > > In my point of view the 2nd solution is better for it does not treat
> > > PCI/PCIe as
> > > > the special kind of devices from others.
> > > >
> > > > -Jia Hongtao.
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH SLUB 1/2] duplicate the cache name in saved_alias list
From: Li Zhong @ 2012-06-26 2:49 UTC (permalink / raw)
To: gaowanlong
Cc: Christoph Lameter, LKML, Pekka Enberg, linux-mm, Paul Mackerras,
Matt Mackall, PowerPC email list
In-Reply-To: <4FE84352.8090303@cn.fujitsu.com>
On Mon, 2012-06-25 at 18:54 +0800, Wanlong Gao wrote:
> On 06/25/2012 05:53 PM, Li Zhong wrote:
> > SLUB duplicates the cache name in kmem_cache_create(). However if the
> > cache could be merged to others during early booting, the name pointer
> > is saved in saved_alias list, and the string needs to be kept valid
> > before slab_sysfs_init() is called.
> >
> > This patch tries to duplicate the cache name in saved_alias list, so
> > that the cache name could be safely kfreed after calling
> > kmem_cache_create(), if that name is kmalloced.
> >
> > Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
> > ---
> > mm/slub.c | 6 ++++++
> > 1 files changed, 6 insertions(+), 0 deletions(-)
> >
> > diff --git a/mm/slub.c b/mm/slub.c
> > index 8c691fa..3dc8ed5 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -5373,6 +5373,11 @@ static int sysfs_slab_alias(struct kmem_cache *s,
> > const char *name)
> >
> > al->s = s;
> > al->name = name;
> > + al->name = kstrdup(name, GFP_KERNEL);
>
> dup assigned the al->name ?
>
Ah, yes, there should be a '-' before the line al->name = name;
Thank you, I will update it.
> Thanks,
> Wanlong Gao
>
> > + if (!al->name) {
> > + kfree(al);
> > + return -ENOMEM;
> > + }
> > al->next = alias_list;
> > alias_list = al;
> > return 0;
> > @@ -5409,6 +5414,7 @@ static int __init slab_sysfs_init(void)
> > if (err)
> > printk(KERN_ERR "SLUB: Unable to add boot slab alias"
> > " %s to sysfs\n", s->name);
> > + kfree(al->name);
> > kfree(al);
> > }
> >
> >
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
^ permalink raw reply
* Re: [PATCH V3 1/2] PCI: retrieve host bridge by PCI bus
From: Benjamin Herrenschmidt @ 2012-06-26 2:50 UTC (permalink / raw)
To: Gavin Shan; +Cc: bhelgaas, linux-pci, Yinghai Lu, linuxppc-dev
In-Reply-To: <20120626003020.GA6307@shangw>
On Tue, 2012-06-26 at 08:30 +0800, Gavin Shan wrote:
> >> +EXPORT_SYMBOL(pci_bus_host_bridge);
>
> Yinghai, thanks for your time on this :-)
>
> >
> >why do you need to export it?
> >
>
> The reason is that we have introduced extra fields to "struct
> pci_host_bridge"
> in [PATCH 2/2] and platform want to access those extra fields.
But the platform code is built-in, not modular, so it doesn't need
EXPORT_SYMBOL (additionally even if we wanted to export it we probably
also want it _GPL only, so EXPORT_SYMBOL_GPL, but I don't think we need
to).
Cheers,
Ben.
^ permalink raw reply
* RE: [PATCH 0/6] Description for PCI patches using platform driver
From: Jia Hongtao-B38951 @ 2012-06-26 2:54 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Wood Scott-B07421, Li Yang-R58472, linuxppc-dev@lists.ozlabs.org,
Bhushan Bharat-R65777
In-Reply-To: <1340678813.3732.1.camel@pasglop>
PiBNeSBtYWluIGNvbmNlcm4gaXMgdGhhdCBjdXJyZW50bHkgdGhlIFBDSSBjb2RlIGhhcyBzb21l
IGFzc3VtcHRpb25zDQo+IGFib3V0IG9yZGVyaW5nIG9mIHRoaW5ncyB0aGF0IHdpbGwgZ2V0IHZp
b2xhdGVkLg0KPiANCj4gRm9yIGV4YW1wbGUsIHRoZSBwY2kgZmluYWwgZml4dXBzIGFyZSBhbiBm
c19pbml0Y2FsbCBpaXJjLCBvciBzb21ldGhpbmcNCj4gbGlrZSB0aGF0LiBUaGVyZSdzIG90aGVy
IHNpbWlsYXIgb2RkaXRpZXMgdGhhdCBtaWdodCBiZWNvbWUgcHJvYmxlbWF0aWMuDQo+IEluIGFk
ZGl0aW9uLCB0aGVyZSBtaWdodCBiZSBsb2NraW5nIGlzc3VlcyBpZiB5b3Ugc3RhcnQgZG9pbmcg
bXVsdGlwbGUNCj4gUEhCcyBpbiBwYXJhbGxlbC4NCj4gDQo+IE5vdyB3ZSBkbyB3YW50IHRvIGZp
eCBhbGwgdGhhdCBsb25nIHJ1biBidXQgaXQgbWlnaHQgdGFrZSBhIHdoaWxlLg0KPiANCj4gQ2hl
ZXJzLA0KPiBCZW4uDQo+IA0KDQpUaGFua3MgZm9yIHlvdXIgYWR2aWNlLiBJIHdpbGwgZG8gc29t
ZSBpbnZlc3RpZ2F0aW9ucyBvbiB3aGF0IHlvdSBzYWlkLg0KDQotSmlhIEhvbmd0YW8uDQoNCg0K
DQo+ID4gVGhhbmtzLg0KPiA+IC1KaWEgSG9uZ3Rhby4NCj4gPg0KPiA+ID4gLS0tLS1PcmlnaW5h
bCBNZXNzYWdlLS0tLS0NCj4gPiA+IEZyb206IExpbnV4cHBjLWRldiBbbWFpbHRvOmxpbnV4cHBj
LWRldi0NCj4gPiA+IGJvdW5jZXMrYjM4OTUxPWZyZWVzY2FsZS5jb21AbGlzdHMub3psYWJzLm9y
Z10gT24gQmVoYWxmIE9mIEppYQ0KPiBIb25ndGFvLQ0KPiA+ID4gQjM4OTUxDQo+ID4gPiBTZW50
OiBXZWRuZXNkYXksIEp1bmUgMjAsIDIwMTIgMTA6MzQgQU0NCj4gPiA+IFRvOiBCaHVzaGFuIEJo
YXJhdC1SNjU3Nzc7IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnOw0KPiA+ID4gZ2FsYWtA
a2VybmVsLmNyYXNoaW5nLm9yZzsgYmVuaEBrZXJuZWwuY3Jhc2hpbmcub3JnDQo+ID4gPiBDYzog
V29vZCBTY290dC1CMDc0MjE7IExpIFlhbmctUjU4NDcyDQo+ID4gPiBTdWJqZWN0OiBSRTogW1BB
VENIIDAvNl0gRGVzY3JpcHRpb24gZm9yIFBDSSBwYXRjaGVzIHVzaW5nIHBsYXRmb3JtDQo+ID4g
PiBkcml2ZXINCj4gPiA+DQo+ID4gPiBIZWxsbyBCZW4sIEt1bWFyLCBvdGhlcnM6DQo+ID4gPg0K
PiA+ID4gVGhpcyBzZXJpZXMgb2YgcGF0Y2hlcyBoYWQgYmVlbiBwZW5kaW5nIGZvciBhIGxvbmcg
dGltZSBvbiB1cHN0cmVhbS4NCj4gPiA+IFdlIGZpeGVkIHNvbWUgaXNzdWVzIHdlIGZvdW5kIGFu
ZCB0aGVyZSBzdGlsbCBzb21lIGlzc3VlcyBzaG91bGQgYmUNCj4gPiA+IGRpc2N1c3NlZCBsaWtl
IHN3aW90bGIgaW5pdCB0aGluZy4gRG8geW91IGhhdmUgdGltZSBmb3IgYSByZXZpZXc/DQo+ID4g
Pg0KPiA+ID4gVGhhbmtzLg0KPiA+ID4gLUppYSBIb25ndGFvLg0KPiA+ID4NCj4gPiA+ID4gLS0t
LS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+ID4gRnJvbTogQmh1c2hhbiBCaGFyYXQtUjY1
Nzc3DQo+ID4gPiA+IFNlbnQ6IFRodXJzZGF5LCBKdW5lIDE0LCAyMDEyIDU6NTIgUE0NCj4gPiA+
ID4gVG86IEppYSBIb25ndGFvLUIzODk1MTsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7
DQo+ID4gPiA+IGdhbGFrQGtlcm5lbC5jcmFzaGluZy5vcmc7IGJlbmhAa2VybmVsLmNyYXNoaW5n
Lm9yZw0KPiA+ID4gPiBDYzogTGkgWWFuZy1SNTg0NzI7IFdvb2QgU2NvdHQtQjA3NDIxDQo+ID4g
PiA+IFN1YmplY3Q6IFJFOiBbUEFUQ0ggMC82XSBEZXNjcmlwdGlvbiBmb3IgUENJIHBhdGNoZXMg
dXNpbmcgcGxhdGZvcm0NCj4gPiA+ID4gZHJpdmVyDQo+ID4gPiA+DQo+ID4gPiA+IEhlbGxvIEJl
biwgS3VtYXIsIG90aGVycw0KPiA+ID4gPg0KPiA+ID4gPiBQbGVhc2UgcHJvdmlkZSB5b3VyIGNv
bW1lbnRzL3Rob3VnaHRzIG9uIHRoaXMgPw0KPiA+ID4gPg0KPiA+ID4gPiBUaGFua3MNCj4gPiA+
ID4gLUJoYXJhdA0KPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiAt
LS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+ID4gRnJvbTogSmlhIEhv
bmd0YW8tQjM4OTUxDQo+ID4gPiA+ID4gPiA+ID4gPiBTZW50OiBGcmlkYXksIEp1bmUgMDgsIDIw
MTIgMzoxMiBQTQ0KPiA+ID4gPiA+ID4gPiA+ID4gVG86IGxpbnV4cHBjLWRldkBsaXN0cy5vemxh
YnMub3JnOw0KPiBnYWxha0BrZXJuZWwuY3Jhc2hpbmcub3JnDQo+ID4gPiA+ID4gPiA+ID4gPiBD
YzogTGkgWWFuZy1SNTg0NzI7IGJlbmhAa2VybmVsLmNyYXNoaW5nLm9yZzsgV29vZCBTY290dC0N
Cj4gPiA+IEIwNzQyMTsNCj4gPiA+ID4gPiA+ID4gPiBCaHVzaGFuIEJoYXJhdC0NCj4gPiA+ID4g
PiA+ID4gPiA+IFI2NTc3NzsgSmlhIEhvbmd0YW8tQjM4OTUxDQo+ID4gPiA+ID4gPiA+ID4gPiBT
dWJqZWN0OiBbUEFUQ0ggMC82XSBEZXNjcmlwdGlvbiBmb3IgUENJIHBhdGNoZXMgdXNpbmcNCj4g
PiA+IHBsYXRmb3JtDQo+ID4gPiA+ID4gPiA+ID4gPiBkcml2ZXINCj4gPiA+ID4gPiA+ID4gPiA+
DQo+ID4gPiA+ID4gPiA+ID4gPiBUaGlzIHNlcmllcyBvZiBwYXRjaGVzIGFyZSB0byB1bmlmeSBw
Y2kgaW5pdGlhbGl6YXRpb24NCj4gY29kZQ0KPiA+ID4gYW5kDQo+ID4gPiA+ID4gPiA+ID4gPiBh
ZGQgUE0NCj4gPiA+ID4gPiA+ID4gPiBzdXBwb3J0DQo+ID4gPiA+ID4gPiA+ID4gPiBmb3IgYWxs
IDg1eHgvODZ4eCBwb3dlcnBjIGJvYXJkcy4gQnV0IHR3byBzaWRlIGVmZmVjdHMNCj4gYXJlDQo+
ID4gPiA+ID4gPiA+ID4gPiBpbnRyb2R1Y2VkDQo+ID4gPiA+ID4gPiA+ID4gYnkgdGhpcw0KPiA+
ID4gPiA+ID4gPiA+ID4gbWVjaGFuaXNtIHdoaWNoIGxpc3RlZCBiZWxvdzoNCj4gPiA+ID4gPiA+
ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiAxLiBvZl9wbGF0Zm9ybV9idXNfcHJvYmUoKSB3aWxs
IGJlIGNhbGxlZCB0d2ljZSBidXQgaW4NCj4gc29tZQ0KPiA+ID4gPiA+ID4gPiA+ID4gY2FzZXMN
Cj4gPiA+ID4gPiA+ID4gPiBkdXBsaWNhdGlvbg0KPiA+ID4gPiA+ID4gPiA+ID4gICAgd2Fybmlu
ZyBvY2N1cmVkLiBXZSBmaXggdGhpcyBpbiBbUEFUQ0ggNS82XS4NCj4gPiA+ID4gPiA+ID4gPiA+
DQo+ID4gPiA+ID4gPiA+ID4gPiAyLiBFZGFjIGRyaXZlciBmYWlsZWQgdG8gcmVnaXN0ZXIgcGNp
IG5vZGVzIGFzIHBsYXRmb3JtDQo+ID4gPiBkZXZpY2VzLg0KPiA+ID4gPiA+ID4gPiA+ID4gV2Ug
Zml4DQo+ID4gPiA+ID4gPiA+ID4gdGhpcw0KPiA+ID4gPiA+ID4gPiA+ID4gICAgaW4gW1BBVENI
IDYvNl0uDQo+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiBXaXRoIHRoZXNlIHBhdGNo
ZXMgd2lsbCBub3QgdGhlIFNXSU9UTEIgd2lsbCBub3QgYmUNCj4gaW5pdGlhbGl6ZWQNCj4gPiA+
ID4gPiA+ID4gPiBldmVuIGlmIFBDSS9QQ0llIGRlbWFuZGVkPw0KPiA+ID4gPiA+ID4gPiA+DQo+
ID4gPiA+ID4gPiA+ID4gVGhhbmtzDQo+ID4gPiA+ID4gPiA+ID4gLUJoYXJhdA0KPiA+ID4gPiA+
ID4gPiA+DQo+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+IFRoZXNlIHBhdGNoZXMgc3RpbGwg
aGF2ZSB0aGUgc3dpb3RsYiBpbml0IHByb2JsZW0gaWYNCj4gPiA+ID4gPiA+ICJwcGNfc3dpb3Rs
Yl9lbmFibGUiIGlzDQo+ID4gPiA+ID4gPiA+IG9ubHkgZGVtYW5kZWQgYnkgUENJL1BDSWUuIE9u
ZSBvZiB0aGUgcHVycG9zZXMgb2Ygc2VuZGluZyBvdXQNCj4gPiA+IHRoZXNlDQo+ID4gPiA+ID4g
PiBwYXRjaGVzIGlzDQo+ID4gPiA+ID4gPiA+IHRvIGxldCB1cyBzdGFydCBhIGRpc2N1c3Npb24g
Zm9yIHRoaXMgcHJvYmxlbSBpbiB1cHN0cmVhbS4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBP
aywgSSBkaWQgbm90IGZpbmQgYW55IG1lbnRpb24gb2YgdGhhdCwgc28gSSB0aG91Z2h0IHRoYXQg
eW91DQo+IGhhdmUNCj4gPiA+ID4gPiA+IHJlc29sdmVkIHRoZSBpc3N1ZSBieSBzb21lIG1lYW5z
IGluIHRoZXNlIHBhdGNoZXMgd2hpY2ggSSBkaWQNCj4gbm90DQo+ID4gPiA+IGNhdGNoLg0KPiA+
ID4gPiA+ID4NCj4gPiA+ID4gPiA+IFNvLCB0aGVzZSBwYXRjaGVzIGludHJvZHVjZXMgdGhlIGlz
c3VlLCB0aGF0IFNXSU9UTEIgd2lsbCBub3QNCj4gYmUNCj4gPiA+ID4gPiA+IGluaXRpYWxpemVk
IGlmIHJlcXVlc3RlZCBieSBwY2kvcGNpZS4gVGhlIHJlcXVlc3QgaXMgcmFpc2VkIGJ5DQo+ID4g
PiA+IHNldHRpbmcNCj4gPiA+ID4gPiA+IHRoZSBmbGFnIHBwY19zd2lvdGxiX2VuYWJsZS4gVGhl
IHN3aW90bGJfaW5pdCgpIHdpbGwgYmUgY2FsbGVkDQo+IGluDQo+ID4gPiA+ID4gPiBtZW1faW5p
dCgpIGlmIHBwY19zd2lvdGxiX2VuYWJsZSBpcyBzZXQuIE5vdyB3aXRoIHRoZXNlIHBhdGNoZXMs
DQo+ID4gPiB0aGUNCj4gPiA+ID4gPiA+IHJlcXVlc3QgaXMgcmFpc2VkIGFmdGVyIG1lbV9pbml0
KCkgaXMgY2FsbGVkLiBTbyByZXF1ZXN0IG5vdA0KPiA+ID4gPiBoYW5kbGVkIDopLg0KPiA+ID4g
PiA+ID4NCj4gPiA+ID4gPiA+IEZvbGxvd2luZyBhcmUgdGhlIHNvbHV0aW9ucyB3ZSBoYXZlIHRo
b3VnaHQgb2YgZHVyaW5nIG91cg0KPiBpbnRlcm5hbA0KPiA+ID4gPiA+ID4gZGlzY3Vzc2lvbnMg
KGlmIEkgZGlkIG5vdCBtaXNzZWQgYW55KToNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiAxLiBU
aGVzZSBwYXRjaGVzIG1vdmUgdGhlIGNvZGUgZnJvbSBwbGF0Zm9ybSBpbml0IHRvIGRldmljZQ0K
PiBpbml0DQo+ID4gPiA+ID4gPiAoYXJjaF9pbml0Y2FsbCgpKS4gUmF0aGVyIHRoYW4gbW92aW5n
IHRoZSB3aG9sZSBjb2RlLCBsZXQgdXMNCj4gZGl2aWRlDQo+ID4gPiA+ID4gPiB0aGUgY29kZSBp
bnRvIHR3by4gRmlyc3QsIHdoaWNoIGlzIG5lZWRlZCB0byByYWlzZSB0aGUgc3dpb3RsYg0KPiBp
bml0DQo+ID4gPiA+ID4gPiByZXF1ZXN0IGFuZCBzZWNvbmQgdGhlIHJlc3QuIERlZmluZSB0aGlz
IGZpcnN0IGFzIGFuIGZ1bmN0aW9uDQo+IGluDQo+ID4gPiA+ID4gPiBhcmNoL3Bvd2VycGMvc3lz
ZGV2L2ZzbF9wY2kuYyBhbmQgY2FsbCB0aGlzIGZyb20gcGxhdGZvcm0gaW5pdA0KPiBjb2RlDQo+
ID4gPiA+IG9mDQo+ID4gPiA+ID4gPiB0aGUgU09Dcy4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4g
PiAyLiBBbGwga25vd24gZGV2aWNlcywgdGhlIGxvd2VzdCBQQ0llIG91dGJvdW5kIHJhbmdlIHN0
YXJ0cyBhdA0KPiA+ID4gPiA+ID4gMHg4MDAwMDAwMCwgYnV0IHRoZXJlJ3Mgbm90aGluZyBhYm92
ZSAweGMwMDAwMDAwLiBTbyB0aGUNCj4gaW5ib3VuZCBvZg0KPiA+ID4gPiA+ID4gc2l6ZSAweDgw
MDBfMDAwMCBpcyBhbHdheXMgYXZhaWxiZSBvbiBhbGwgZGV2aWNlcy4gSGFyZGNvZGUgdGhlDQo+
ID4gPiBjaGVjaw0KPiA+ID4gPiA+ID4gaW4gcGxhdGZvcm0gY29kZSB0byBjaGVjayBtZW1ibG9j
a19lbmRfb2ZfRFJBTSgpIHRvIDB4ODAwMDAwMDAuDQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4g
U29tZXRoaW5nIGxpa2UgdGhpczoNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBkaWZmIC0tZ2l0
IGEvYXJjaC9wb3dlcnBjL3BsYXRmb3Jtcy84NXh4L2NvcmVuZXRfZHMuYw0KPiA+ID4gPiA+ID4g
Yi9hcmNoL3Bvd2VycGMvcGxhdGZvcm1zLzg1eHgvY29yZW5ldF9kcy5jDQo+ID4gPiA+ID4gPiBp
bmRleCAxZjcwMjhlLi5lZjRlMjE1IDEwMDY0NA0KPiA+ID4gPiA+ID4gLS0tIGEvYXJjaC9wb3dl
cnBjL3BsYXRmb3Jtcy84NXh4L2NvcmVuZXRfZHMuYw0KPiA+ID4gPiA+ID4gKysrIGIvYXJjaC9w
b3dlcnBjL3BsYXRmb3Jtcy84NXh4L2NvcmVuZXRfZHMuYw0KPiA+ID4gPiA+ID4gQEAgLTc5LDcg
Kzc5LDcgQEAgdm9pZCBfX2luaXQgY29yZW5ldF9kc19zZXR1cF9hcmNoKHZvaWQpDQo+ICNlbmRp
Zg0KPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ICNpZmRlZiBDT05GSUdfU1dJT1RMQg0KPiA+ID4g
PiA+ID4gLSAgICAgICBpZiAobWVtYmxvY2tfZW5kX29mX0RSQU0oKSA+IDB4ZmZmZmZmZmYpDQo+
ID4gPiA+ID4gPiArICAgICAgIGlmIChtZW1ibG9ja19lbmRfb2ZfRFJBTSgpID4gMHhmZjAwMDAw
MCkNCj4gPiA+ID4gPiA+ICAgICAgICAgICAgICAgICAgcHBjX3N3aW90bGJfZW5hYmxlID0gMTsg
ICNlbmRpZg0KPiA+ID4gPiA+ID4gICAgICAgICAgcHJfaW5mbygiJXMgYm9hcmQgZnJvbSBGcmVl
c2NhbGUgU2VtaWNvbmR1Y3RvclxuIiwNCj4gPiA+ID4gPiA+IHBwY19tZC5uYW1lKTsNCj4gPiA+
ID4gPiA+DQo+ID4gPiA+ID4gPiAtLS0tLS0tLS0tLS0tDQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+
ID4gMy4gQWx3YXlzIGRvIHN3aW90bGJfaW5pdCgpIGluIG1lbV9pbml0KCkgYW5kIGxhdGVyIGFm
dGVyIFBDSQ0KPiBpbml0LA0KPiA+ID4gPiBpZg0KPiA+ID4gPiA+ID4gdGhlIHN3aW90bGIgaXMg
bm90IG5lZWRlZCB0aGVuIGZyZWUgaXQgKHN3aW90bGJfZnJlZSgpKS4NCj4gPiA+ID4gPiA+DQo+
ID4gPiA+ID4gPiA0LiBldGMsIHBsZWFzZSBwcm92aWRlIHNvbWUgb3RoZXIgYmV0dGVyIHdheS4N
Cj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBUaGFua3MNCj4gPiA+ID4gPiA+IC1CaGFyYXQNCj4g
PiA+ID4gPg0KPiA+ID4gPiA+IFRoYW5rcy4NCj4gPiA+ID4gPiBJbiBteSBwb2ludCBvZiB2aWV3
IHRoZSAybmQgc29sdXRpb24gaXMgYmV0dGVyIGZvciBpdCBkb2VzIG5vdA0KPiB0cmVhdA0KPiA+
ID4gPiBQQ0kvUENJZSBhcw0KPiA+ID4gPiA+IHRoZSBzcGVjaWFsIGtpbmQgb2YgZGV2aWNlcyBm
cm9tIG90aGVycy4NCj4gPiA+ID4gPg0KPiA+ID4gPiA+IC1KaWEgSG9uZ3Rhby4NCj4gPiA+DQo+
ID4gPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KPiA+
ID4gTGludXhwcGMtZGV2IG1haWxpbmcgbGlzdA0KPiA+ID4gTGludXhwcGMtZGV2QGxpc3RzLm96
bGFicy5vcmcNCj4gPiA+IGh0dHBzOi8vbGlzdHMub3psYWJzLm9yZy9saXN0aW5mby9saW51eHBw
Yy1kZXYNCj4gPg0KPiANCj4gDQoNCg==
^ permalink raw reply
* Re: [PATCH SLUB 1/2] duplicate the cache name in saved_alias list
From: Li Zhong @ 2012-06-26 2:58 UTC (permalink / raw)
To: Glauber Costa
Cc: Christoph Lameter, LKML, Pekka Enberg, linux-mm, Paul Mackerras,
Matt Mackall, PowerPC email list
In-Reply-To: <4FE84741.9000703@parallels.com>
On Mon, 2012-06-25 at 15:10 +0400, Glauber Costa wrote:
> On 06/25/2012 01:53 PM, Li Zhong wrote:
> > SLUB duplicates the cache name in kmem_cache_create(). However if the
> > cache could be merged to others during early booting, the name pointer
> > is saved in saved_alias list, and the string needs to be kept valid
> > before slab_sysfs_init() is called.
> >
> > This patch tries to duplicate the cache name in saved_alias list, so
> > that the cache name could be safely kfreed after calling
> > kmem_cache_create(), if that name is kmalloced.
> >
> > Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
> > ---
> > mm/slub.c | 6 ++++++
> > 1 files changed, 6 insertions(+), 0 deletions(-)
> >
> > diff --git a/mm/slub.c b/mm/slub.c
> > index 8c691fa..3dc8ed5 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -5373,6 +5373,11 @@ static int sysfs_slab_alias(struct kmem_cache *s,
> > const char *name)
> >
> > al->s = s;
> > al->name = name;
> > + al->name = kstrdup(name, GFP_KERNEL);
> > + if (!al->name) {
> > + kfree(al);
> > + return -ENOMEM;
> > + }
> > al->next = alias_list;
> > alias_list = al;
> > return 0;
> > @@ -5409,6 +5414,7 @@ static int __init slab_sysfs_init(void)
> > if (err)
> > printk(KERN_ERR "SLUB: Unable to add boot slab alias"
> > " %s to sysfs\n", s->name);
> > + kfree(al->name);
> > kfree(al);
> > }
> >
> >
>
> What's unsafe about the current state of affairs ?
> Whenever we alias, we'll increase the reference counter.
> kmem_cache_destroy will only actually destroy the structure whenever
> that refcnt reaches zero.
>
> This means that kfree shouldn't happen until then. So what is exactly
> that you are seeing?
Maybe I didn't describe it clearly ... It is only about the name string
passed into kmem_cache_create() during early boot.
kmem_cache_create() checks whether it is mergeable before creating one.
If not mergeable, the name is duplicated: n = kstrdup(name, GFP_KERNEL);
If it is mergeable, it calls sysfs_slab_alias(). If the sysfs is ready
(slab_state == SYSFS ), then the name is duplicated (or dropped if no
SYSFS support ) in sysfs_create_link() for use.
For the above cases, we could safely kfree the name string after calling
cache create.
However, During early boot, before sysfs is ready ( slab_state <
SYSFS ), the sysfs_slab_alias() saves the pointer of name in the
alias_list. And those entries in the list are added to sysfs later after
slab_sysfs_init() is called. So we need to keep the name string valid
until slab_sysfs_init() is called to set up the sysfs stuff. By
duplicating the name string here also, we are able to kfree the name
string after calling the cache create.
>
> Now, if you ask me, keeping the name around in user-visible files like
> /proc/slabinfo for caches that are removed already can be a bit
> confusing (that is because we don't add aliases to the slab_cache list)
>
> If you want to touch this, one thing you can do is to keep a list of
> names bundled in an alias. If an alias is removed, you free that name.
> If that name is the representative name of the bundle, you move to the
> next one.
>
^ permalink raw reply
* Re: [PATCH V3 1/2] PCI: retrieve host bridge by PCI bus
From: Gavin Shan @ 2012-06-26 3:01 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: bhelgaas, linux-pci, Yinghai Lu, Gavin Shan, linuxppc-dev
In-Reply-To: <1340679045.3732.3.camel@pasglop>
>> >> +EXPORT_SYMBOL(pci_bus_host_bridge);
>>
>> Yinghai, thanks for your time on this :-)
>>
>> >
>> >why do you need to export it?
>> >
>>
>> The reason is that we have introduced extra fields to "struct
>> pci_host_bridge"
>> in [PATCH 2/2] and platform want to access those extra fields.
>
>But the platform code is built-in, not modular, so it doesn't need
>EXPORT_SYMBOL (additionally even if we wanted to export it we probably
>also want it _GPL only, so EXPORT_SYMBOL_GPL, but I don't think we need
>to).
>
Ben, thanks for correcting me :-)
Let me remove EXPORT_SYMBOL() is next revision.
>Cheers,
>Ben.
>
>
Thanks,
Gavin
^ permalink raw reply
* RE: [PATCH 0/6] Description for PCI patches using platform driver
From: Jia Hongtao-B38951 @ 2012-06-26 10:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Wood Scott-B07421, Li Yang-R58472, linuxppc-dev@lists.ozlabs.org,
Bhushan Bharat-R65777
In-Reply-To: <1340678813.3732.1.camel@pasglop>
PiANCj4gTXkgbWFpbiBjb25jZXJuIGlzIHRoYXQgY3VycmVudGx5IHRoZSBQQ0kgY29kZSBoYXMg
c29tZSBhc3N1bXB0aW9ucw0KPiBhYm91dCBvcmRlcmluZyBvZiB0aGluZ3MgdGhhdCB3aWxsIGdl
dCB2aW9sYXRlZC4NCj4gDQo+IEZvciBleGFtcGxlLCB0aGUgcGNpIGZpbmFsIGZpeHVwcyBhcmUg
YW4gZnNfaW5pdGNhbGwgaWlyYywgb3Igc29tZXRoaW5nDQo+IGxpa2UgdGhhdC4gVGhlcmUncyBv
dGhlciBzaW1pbGFyIG9kZGl0aWVzIHRoYXQgbWlnaHQgYmVjb21lIHByb2JsZW1hdGljLg0KPiBJ
biBhZGRpdGlvbiwgdGhlcmUgbWlnaHQgYmUgbG9ja2luZyBpc3N1ZXMgaWYgeW91IHN0YXJ0IGRv
aW5nIG11bHRpcGxlDQo+IFBIQnMgaW4gcGFyYWxsZWwuDQo+IA0KPiBOb3cgd2UgZG8gd2FudCB0
byBmaXggYWxsIHRoYXQgbG9uZyBydW4gYnV0IGl0IG1pZ2h0IHRha2UgYSB3aGlsZS4NCj4gDQo+
IENoZWVycywNCj4gQmVuLg0KPiANCg0KSGkgQmVuLA0KDQpUaGUgb3JkZXJpbmcgb2YgdGhpbmdz
IGlzIGFsc28gdGhlIG1haW4gY29uY2VybnMgb2Ygb3VyIHNlbGYuIFdlIGFsc28NCmRpZCBzb21l
IHJlc2VhcmNoZXMgYW5kIHRyaWVkIG91ciBiZXN0IHRvIG1ha2Ugb3JkZXJpbmdzIHJpZ2h0LiBZ
ZXMsDQpwY2kgZmluYWwgZml4dXBzIGFyZSBhbiBmc19pbml0Y2FsbCBidXQgSSBkb24ndCB0aGlu
ayBpdCdzIGEgcHJvYmxlbQ0KY2F1c2Ugd2UgZGlkIG5vdCBjaGFuZ2UgdGhlIHBjaSBpbml0IHBh
cnQgYWZ0ZXIgdGhpcy4NCg0KLUppYSBIb25ndGFvLg0KDQo+ID4gVGhhbmtzLg0KPiA+IC1KaWEg
SG9uZ3Rhby4NCj4gPg0KPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+IEZy
b206IExpbnV4cHBjLWRldiBbbWFpbHRvOmxpbnV4cHBjLWRldi0NCj4gPiA+IGJvdW5jZXMrYjM4
OTUxPWZyZWVzY2FsZS5jb21AbGlzdHMub3psYWJzLm9yZ10gT24gQmVoYWxmIE9mIEppYQ0KPiBI
b25ndGFvLQ0KPiA+ID4gQjM4OTUxDQo+ID4gPiBTZW50OiBXZWRuZXNkYXksIEp1bmUgMjAsIDIw
MTIgMTA6MzQgQU0NCj4gPiA+IFRvOiBCaHVzaGFuIEJoYXJhdC1SNjU3Nzc7IGxpbnV4cHBjLWRl
dkBsaXN0cy5vemxhYnMub3JnOw0KPiA+ID4gZ2FsYWtAa2VybmVsLmNyYXNoaW5nLm9yZzsgYmVu
aEBrZXJuZWwuY3Jhc2hpbmcub3JnDQo+ID4gPiBDYzogV29vZCBTY290dC1CMDc0MjE7IExpIFlh
bmctUjU4NDcyDQo+ID4gPiBTdWJqZWN0OiBSRTogW1BBVENIIDAvNl0gRGVzY3JpcHRpb24gZm9y
IFBDSSBwYXRjaGVzIHVzaW5nIHBsYXRmb3JtDQo+ID4gPiBkcml2ZXINCj4gPiA+DQo+ID4gPiBI
ZWxsbyBCZW4sIEt1bWFyLCBvdGhlcnM6DQo+ID4gPg0KPiA+ID4gVGhpcyBzZXJpZXMgb2YgcGF0
Y2hlcyBoYWQgYmVlbiBwZW5kaW5nIGZvciBhIGxvbmcgdGltZSBvbiB1cHN0cmVhbS4NCj4gPiA+
IFdlIGZpeGVkIHNvbWUgaXNzdWVzIHdlIGZvdW5kIGFuZCB0aGVyZSBzdGlsbCBzb21lIGlzc3Vl
cyBzaG91bGQgYmUNCj4gPiA+IGRpc2N1c3NlZCBsaWtlIHN3aW90bGIgaW5pdCB0aGluZy4gRG8g
eW91IGhhdmUgdGltZSBmb3IgYSByZXZpZXc/DQo+ID4gPg0KPiA+ID4gVGhhbmtzLg0KPiA+ID4g
LUppYSBIb25ndGFvLg0KPiA+ID4NCj4gPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0N
Cj4gPiA+ID4gRnJvbTogQmh1c2hhbiBCaGFyYXQtUjY1Nzc3DQo+ID4gPiA+IFNlbnQ6IFRodXJz
ZGF5LCBKdW5lIDE0LCAyMDEyIDU6NTIgUE0NCj4gPiA+ID4gVG86IEppYSBIb25ndGFvLUIzODk1
MTsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7DQo+ID4gPiA+IGdhbGFrQGtlcm5lbC5j
cmFzaGluZy5vcmc7IGJlbmhAa2VybmVsLmNyYXNoaW5nLm9yZw0KPiA+ID4gPiBDYzogTGkgWWFu
Zy1SNTg0NzI7IFdvb2QgU2NvdHQtQjA3NDIxDQo+ID4gPiA+IFN1YmplY3Q6IFJFOiBbUEFUQ0gg
MC82XSBEZXNjcmlwdGlvbiBmb3IgUENJIHBhdGNoZXMgdXNpbmcgcGxhdGZvcm0NCj4gPiA+ID4g
ZHJpdmVyDQo+ID4gPiA+DQo+ID4gPiA+IEhlbGxvIEJlbiwgS3VtYXIsIG90aGVycw0KPiA+ID4g
Pg0KPiA+ID4gPiBQbGVhc2UgcHJvdmlkZSB5b3VyIGNvbW1lbnRzL3Rob3VnaHRzIG9uIHRoaXMg
Pw0KPiA+ID4gPg0KPiA+ID4gPiBUaGFua3MNCj4gPiA+ID4gLUJoYXJhdA0KPiA+ID4gPg0KPiA+
ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0t
LQ0KPiA+ID4gPiA+ID4gPiA+ID4gRnJvbTogSmlhIEhvbmd0YW8tQjM4OTUxDQo+ID4gPiA+ID4g
PiA+ID4gPiBTZW50OiBGcmlkYXksIEp1bmUgMDgsIDIwMTIgMzoxMiBQTQ0KPiA+ID4gPiA+ID4g
PiA+ID4gVG86IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnOw0KPiBnYWxha0BrZXJuZWwu
Y3Jhc2hpbmcub3JnDQo+ID4gPiA+ID4gPiA+ID4gPiBDYzogTGkgWWFuZy1SNTg0NzI7IGJlbmhA
a2VybmVsLmNyYXNoaW5nLm9yZzsgV29vZCBTY290dC0NCj4gPiA+IEIwNzQyMTsNCj4gPiA+ID4g
PiA+ID4gPiBCaHVzaGFuIEJoYXJhdC0NCj4gPiA+ID4gPiA+ID4gPiA+IFI2NTc3NzsgSmlhIEhv
bmd0YW8tQjM4OTUxDQo+ID4gPiA+ID4gPiA+ID4gPiBTdWJqZWN0OiBbUEFUQ0ggMC82XSBEZXNj
cmlwdGlvbiBmb3IgUENJIHBhdGNoZXMgdXNpbmcNCj4gPiA+IHBsYXRmb3JtDQo+ID4gPiA+ID4g
PiA+ID4gPiBkcml2ZXINCj4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiBUaGlz
IHNlcmllcyBvZiBwYXRjaGVzIGFyZSB0byB1bmlmeSBwY2kgaW5pdGlhbGl6YXRpb24NCj4gY29k
ZQ0KPiA+ID4gYW5kDQo+ID4gPiA+ID4gPiA+ID4gPiBhZGQgUE0NCj4gPiA+ID4gPiA+ID4gPiBz
dXBwb3J0DQo+ID4gPiA+ID4gPiA+ID4gPiBmb3IgYWxsIDg1eHgvODZ4eCBwb3dlcnBjIGJvYXJk
cy4gQnV0IHR3byBzaWRlIGVmZmVjdHMNCj4gYXJlDQo+ID4gPiA+ID4gPiA+ID4gPiBpbnRyb2R1
Y2VkDQo+ID4gPiA+ID4gPiA+ID4gYnkgdGhpcw0KPiA+ID4gPiA+ID4gPiA+ID4gbWVjaGFuaXNt
IHdoaWNoIGxpc3RlZCBiZWxvdzoNCj4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4g
PiAxLiBvZl9wbGF0Zm9ybV9idXNfcHJvYmUoKSB3aWxsIGJlIGNhbGxlZCB0d2ljZSBidXQgaW4N
Cj4gc29tZQ0KPiA+ID4gPiA+ID4gPiA+ID4gY2FzZXMNCj4gPiA+ID4gPiA+ID4gPiBkdXBsaWNh
dGlvbg0KPiA+ID4gPiA+ID4gPiA+ID4gICAgd2FybmluZyBvY2N1cmVkLiBXZSBmaXggdGhpcyBp
biBbUEFUQ0ggNS82XS4NCj4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiAyLiBF
ZGFjIGRyaXZlciBmYWlsZWQgdG8gcmVnaXN0ZXIgcGNpIG5vZGVzIGFzIHBsYXRmb3JtDQo+ID4g
PiBkZXZpY2VzLg0KPiA+ID4gPiA+ID4gPiA+ID4gV2UgZml4DQo+ID4gPiA+ID4gPiA+ID4gdGhp
cw0KPiA+ID4gPiA+ID4gPiA+ID4gICAgaW4gW1BBVENIIDYvNl0uDQo+ID4gPiA+ID4gPiA+ID4N
Cj4gPiA+ID4gPiA+ID4gPiBXaXRoIHRoZXNlIHBhdGNoZXMgd2lsbCBub3QgdGhlIFNXSU9UTEIg
d2lsbCBub3QgYmUNCj4gaW5pdGlhbGl6ZWQNCj4gPiA+ID4gPiA+ID4gPiBldmVuIGlmIFBDSS9Q
Q0llIGRlbWFuZGVkPw0KPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gVGhhbmtzDQo+
ID4gPiA+ID4gPiA+ID4gLUJoYXJhdA0KPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+DQo+
ID4gPiA+ID4gPiA+IFRoZXNlIHBhdGNoZXMgc3RpbGwgaGF2ZSB0aGUgc3dpb3RsYiBpbml0IHBy
b2JsZW0gaWYNCj4gPiA+ID4gPiA+ICJwcGNfc3dpb3RsYl9lbmFibGUiIGlzDQo+ID4gPiA+ID4g
PiA+IG9ubHkgZGVtYW5kZWQgYnkgUENJL1BDSWUuIE9uZSBvZiB0aGUgcHVycG9zZXMgb2Ygc2Vu
ZGluZyBvdXQNCj4gPiA+IHRoZXNlDQo+ID4gPiA+ID4gPiBwYXRjaGVzIGlzDQo+ID4gPiA+ID4g
PiA+IHRvIGxldCB1cyBzdGFydCBhIGRpc2N1c3Npb24gZm9yIHRoaXMgcHJvYmxlbSBpbiB1cHN0
cmVhbS4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBPaywgSSBkaWQgbm90IGZpbmQgYW55IG1l
bnRpb24gb2YgdGhhdCwgc28gSSB0aG91Z2h0IHRoYXQgeW91DQo+IGhhdmUNCj4gPiA+ID4gPiA+
IHJlc29sdmVkIHRoZSBpc3N1ZSBieSBzb21lIG1lYW5zIGluIHRoZXNlIHBhdGNoZXMgd2hpY2gg
SSBkaWQNCj4gbm90DQo+ID4gPiA+IGNhdGNoLg0KPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+IFNv
LCB0aGVzZSBwYXRjaGVzIGludHJvZHVjZXMgdGhlIGlzc3VlLCB0aGF0IFNXSU9UTEIgd2lsbCBu
b3QNCj4gYmUNCj4gPiA+ID4gPiA+IGluaXRpYWxpemVkIGlmIHJlcXVlc3RlZCBieSBwY2kvcGNp
ZS4gVGhlIHJlcXVlc3QgaXMgcmFpc2VkIGJ5DQo+ID4gPiA+IHNldHRpbmcNCj4gPiA+ID4gPiA+
IHRoZSBmbGFnIHBwY19zd2lvdGxiX2VuYWJsZS4gVGhlIHN3aW90bGJfaW5pdCgpIHdpbGwgYmUg
Y2FsbGVkDQo+IGluDQo+ID4gPiA+ID4gPiBtZW1faW5pdCgpIGlmIHBwY19zd2lvdGxiX2VuYWJs
ZSBpcyBzZXQuIE5vdyB3aXRoIHRoZXNlIHBhdGNoZXMsDQo+ID4gPiB0aGUNCj4gPiA+ID4gPiA+
IHJlcXVlc3QgaXMgcmFpc2VkIGFmdGVyIG1lbV9pbml0KCkgaXMgY2FsbGVkLiBTbyByZXF1ZXN0
IG5vdA0KPiA+ID4gPiBoYW5kbGVkIDopLg0KPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+IEZvbGxv
d2luZyBhcmUgdGhlIHNvbHV0aW9ucyB3ZSBoYXZlIHRob3VnaHQgb2YgZHVyaW5nIG91cg0KPiBp
bnRlcm5hbA0KPiA+ID4gPiA+ID4gZGlzY3Vzc2lvbnMgKGlmIEkgZGlkIG5vdCBtaXNzZWQgYW55
KToNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiAxLiBUaGVzZSBwYXRjaGVzIG1vdmUgdGhlIGNv
ZGUgZnJvbSBwbGF0Zm9ybSBpbml0IHRvIGRldmljZQ0KPiBpbml0DQo+ID4gPiA+ID4gPiAoYXJj
aF9pbml0Y2FsbCgpKS4gUmF0aGVyIHRoYW4gbW92aW5nIHRoZSB3aG9sZSBjb2RlLCBsZXQgdXMN
Cj4gZGl2aWRlDQo+ID4gPiA+ID4gPiB0aGUgY29kZSBpbnRvIHR3by4gRmlyc3QsIHdoaWNoIGlz
IG5lZWRlZCB0byByYWlzZSB0aGUgc3dpb3RsYg0KPiBpbml0DQo+ID4gPiA+ID4gPiByZXF1ZXN0
IGFuZCBzZWNvbmQgdGhlIHJlc3QuIERlZmluZSB0aGlzIGZpcnN0IGFzIGFuIGZ1bmN0aW9uDQo+
IGluDQo+ID4gPiA+ID4gPiBhcmNoL3Bvd2VycGMvc3lzZGV2L2ZzbF9wY2kuYyBhbmQgY2FsbCB0
aGlzIGZyb20gcGxhdGZvcm0gaW5pdA0KPiBjb2RlDQo+ID4gPiA+IG9mDQo+ID4gPiA+ID4gPiB0
aGUgU09Dcy4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiAyLiBBbGwga25vd24gZGV2aWNlcywg
dGhlIGxvd2VzdCBQQ0llIG91dGJvdW5kIHJhbmdlIHN0YXJ0cyBhdA0KPiA+ID4gPiA+ID4gMHg4
MDAwMDAwMCwgYnV0IHRoZXJlJ3Mgbm90aGluZyBhYm92ZSAweGMwMDAwMDAwLiBTbyB0aGUNCj4g
aW5ib3VuZCBvZg0KPiA+ID4gPiA+ID4gc2l6ZSAweDgwMDBfMDAwMCBpcyBhbHdheXMgYXZhaWxi
ZSBvbiBhbGwgZGV2aWNlcy4gSGFyZGNvZGUgdGhlDQo+ID4gPiBjaGVjaw0KPiA+ID4gPiA+ID4g
aW4gcGxhdGZvcm0gY29kZSB0byBjaGVjayBtZW1ibG9ja19lbmRfb2ZfRFJBTSgpIHRvIDB4ODAw
MDAwMDAuDQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gU29tZXRoaW5nIGxpa2UgdGhpczoNCj4g
PiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBkaWZmIC0tZ2l0IGEvYXJjaC9wb3dlcnBjL3BsYXRmb3Jt
cy84NXh4L2NvcmVuZXRfZHMuYw0KPiA+ID4gPiA+ID4gYi9hcmNoL3Bvd2VycGMvcGxhdGZvcm1z
Lzg1eHgvY29yZW5ldF9kcy5jDQo+ID4gPiA+ID4gPiBpbmRleCAxZjcwMjhlLi5lZjRlMjE1IDEw
MDY0NA0KPiA+ID4gPiA+ID4gLS0tIGEvYXJjaC9wb3dlcnBjL3BsYXRmb3Jtcy84NXh4L2NvcmVu
ZXRfZHMuYw0KPiA+ID4gPiA+ID4gKysrIGIvYXJjaC9wb3dlcnBjL3BsYXRmb3Jtcy84NXh4L2Nv
cmVuZXRfZHMuYw0KPiA+ID4gPiA+ID4gQEAgLTc5LDcgKzc5LDcgQEAgdm9pZCBfX2luaXQgY29y
ZW5ldF9kc19zZXR1cF9hcmNoKHZvaWQpDQo+ICNlbmRpZg0KPiA+ID4gPiA+ID4NCj4gPiA+ID4g
PiA+ICNpZmRlZiBDT05GSUdfU1dJT1RMQg0KPiA+ID4gPiA+ID4gLSAgICAgICBpZiAobWVtYmxv
Y2tfZW5kX29mX0RSQU0oKSA+IDB4ZmZmZmZmZmYpDQo+ID4gPiA+ID4gPiArICAgICAgIGlmICht
ZW1ibG9ja19lbmRfb2ZfRFJBTSgpID4gMHhmZjAwMDAwMCkNCj4gPiA+ID4gPiA+ICAgICAgICAg
ICAgICAgICAgcHBjX3N3aW90bGJfZW5hYmxlID0gMTsgICNlbmRpZg0KPiA+ID4gPiA+ID4gICAg
ICAgICAgcHJfaW5mbygiJXMgYm9hcmQgZnJvbSBGcmVlc2NhbGUgU2VtaWNvbmR1Y3RvclxuIiwN
Cj4gPiA+ID4gPiA+IHBwY19tZC5uYW1lKTsNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiAtLS0t
LS0tLS0tLS0tDQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gMy4gQWx3YXlzIGRvIHN3aW90bGJf
aW5pdCgpIGluIG1lbV9pbml0KCkgYW5kIGxhdGVyIGFmdGVyIFBDSQ0KPiBpbml0LA0KPiA+ID4g
PiBpZg0KPiA+ID4gPiA+ID4gdGhlIHN3aW90bGIgaXMgbm90IG5lZWRlZCB0aGVuIGZyZWUgaXQg
KHN3aW90bGJfZnJlZSgpKS4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA0LiBldGMsIHBsZWFz
ZSBwcm92aWRlIHNvbWUgb3RoZXIgYmV0dGVyIHdheS4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4g
PiBUaGFua3MNCj4gPiA+ID4gPiA+IC1CaGFyYXQNCj4gPiA+ID4gPg0KPiA+ID4gPiA+IFRoYW5r
cy4NCj4gPiA+ID4gPiBJbiBteSBwb2ludCBvZiB2aWV3IHRoZSAybmQgc29sdXRpb24gaXMgYmV0
dGVyIGZvciBpdCBkb2VzIG5vdA0KPiB0cmVhdA0KPiA+ID4gPiBQQ0kvUENJZSBhcw0KPiA+ID4g
PiA+IHRoZSBzcGVjaWFsIGtpbmQgb2YgZGV2aWNlcyBmcm9tIG90aGVycy4NCj4gPiA+ID4gPg0K
PiA+ID4gPiA+IC1KaWEgSG9uZ3Rhby4NCj4gPiA+DQo+ID4gPiBfX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KPiA+ID4gTGludXhwcGMtZGV2IG1haWxpbmcg
bGlzdA0KPiA+ID4gTGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gPiA+IGh0dHBzOi8v
bGlzdHMub3psYWJzLm9yZy9saXN0aW5mby9saW51eHBwYy1kZXYNCj4gPg0KPiANCj4gDQoNCg==
^ permalink raw reply
* [PATCH v6 1/5] powerpc/85xx: implement hardware timebase sync
From: Zhao Chenhui @ 2012-06-26 10:25 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: linux-kernel
Do hardware timebase sync. Firstly, stop all timebases, and transfer
the timebase value of the boot core to the other core. Finally,
start all timebases.
Only apply to dual-core chips, such as MPC8572, P2020, etc.
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
Changes for v6:
* added 85xx_TB_SYNC
* added isync() after set_tb()
* removed extra entries from mpc85xx_smp_guts_ids
arch/powerpc/include/asm/fsl_guts.h | 2 +
arch/powerpc/platforms/85xx/Kconfig | 5 ++
arch/powerpc/platforms/85xx/smp.c | 84 +++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index aa4c488..dd5ba2c 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -48,6 +48,8 @@ struct ccsr_guts {
__be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */
u8 res06c[0x70 - 0x6c];
__be32 devdisr; /* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1 0x00001000
+#define CCSR_GUTS_DEVDISR_TB0 0x00004000
__be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */
u8 res078[0x7c - 0x78];
__be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index f000d81..8dd7147 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
select FSL_PCI if PCI
select SERIAL_8250_EXTENDED if SERIAL_8250
select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+ select 85xx_TB_SYNC if KEXEC
default y
if FSL_SOC_BOOKE
@@ -267,3 +268,7 @@ endif # FSL_SOC_BOOKE
config TQM85xx
bool
+
+config 85xx_TB_SYNC
+ bool
+ default n
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index ff42490..edb0cad 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -24,6 +24,7 @@
#include <asm/mpic.h>
#include <asm/cacheflush.h>
#include <asm/dbell.h>
+#include <asm/fsl_guts.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
@@ -42,6 +43,69 @@ extern void __early_start(void);
#define NUM_BOOT_ENTRY 8
#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
+#ifdef CONFIG_85xx_TB_SYNC
+static struct ccsr_guts __iomem *guts;
+static u64 timebase;
+static int tb_req;
+static int tb_valid;
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+ unsigned int mask;
+
+ if (!guts)
+ return;
+
+ mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
+ if (freeze)
+ setbits32(&guts->devdisr, mask);
+ else
+ clrbits32(&guts->devdisr, mask);
+
+ in_be32(&guts->devdisr);
+}
+
+static void mpc85xx_give_timebase(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ while (!tb_req)
+ barrier();
+ tb_req = 0;
+
+ mpc85xx_timebase_freeze(1);
+ timebase = get_tb();
+ mb();
+ tb_valid = 1;
+
+ while (tb_valid)
+ barrier();
+
+ mpc85xx_timebase_freeze(0);
+
+ local_irq_restore(flags);
+}
+
+static void mpc85xx_take_timebase(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ tb_req = 1;
+ while (!tb_valid)
+ barrier();
+
+ set_tb(timebase >> 32, timebase & 0xffffffff);
+ isync();
+ tb_valid = 0;
+
+ local_irq_restore(flags);
+}
+#endif
+
static int __init
smp_85xx_kick_cpu(int nr)
{
@@ -228,6 +292,16 @@ smp_85xx_setup_cpu(int cpu_nr)
doorbell_setup_this_cpu();
}
+static const struct of_device_id mpc85xx_smp_guts_ids[] = {
+ { .compatible = "fsl,mpc8572-guts", },
+ { .compatible = "fsl,p1020-guts", },
+ { .compatible = "fsl,p1021-guts", },
+ { .compatible = "fsl,p1022-guts", },
+ { .compatible = "fsl,p1023-guts", },
+ { .compatible = "fsl,p2020-guts", },
+ {},
+};
+
void __init mpc85xx_smp_init(void)
{
struct device_node *np;
@@ -249,6 +323,16 @@ void __init mpc85xx_smp_init(void)
smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
}
+ np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
+ if (np) {
+#ifdef CONFIG_85xx_TB_SYNC
+ guts = of_iomap(np, 0);
+ smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
+ smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
+#endif
+ of_node_put(np);
+ }
+
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC
--
1.6.4.1
^ permalink raw reply related
* [PATCH v6 2/5] powerpc/85xx: add HOTPLUG_CPU support
From: Zhao Chenhui @ 2012-06-26 10:25 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: linux-kernel
In-Reply-To: <1340706359-9455-1-git-send-email-chenhui.zhao@freescale.com>
From: Li Yang <leoli@freescale.com>
Add support to disable and re-enable individual cores at runtime
on MPC85xx/QorIQ SMP machines. Currently support e500v1/e500v2 core.
MPC85xx machines use ePAPR spin-table in boot page for CPU kick-off.
This patch uses the boot page from bootloader to boot core at runtime.
It supports 32-bit and 36-bit physical address.
Add generic_set_cpu_up() to set cpu_state as CPU_UP_PREPARE in kick_cpu().
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
Changes for v6:
* do not guard __flush_disable_L1() by ifdefs
* added isync() after mtspr()
arch/powerpc/Kconfig | 6 +-
arch/powerpc/include/asm/cacheflush.h | 2 +
arch/powerpc/include/asm/smp.h | 2 +
arch/powerpc/kernel/head_fsl_booke.S | 28 +++++++
arch/powerpc/kernel/smp.c | 10 +++
arch/powerpc/platforms/85xx/Kconfig | 2 +-
arch/powerpc/platforms/85xx/smp.c | 137 ++++++++++++++++++++++++---------
7 files changed, 147 insertions(+), 40 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 38786c8..d6bacbe 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -220,7 +220,8 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
- (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
+ (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+ || 44x || 40x
config PPC_DCR_NATIVE
bool
@@ -331,7 +332,8 @@ config SWIOTLB
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
- depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
+ depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || \
+ PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
---help---
Say Y here to be able to disable and re-enable individual
CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index ab9e402..b843e35 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -30,6 +30,8 @@ extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+extern void __flush_disable_L1(void);
+
extern void __flush_icache_range(unsigned long, unsigned long);
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index ebc24dc..e807e9d 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
void generic_cpu_die(unsigned int cpu);
void generic_mach_cpu_die(void);
void generic_set_cpu_dead(unsigned int cpu);
+void generic_set_cpu_up(unsigned int cpu);
int generic_check_cpu_restart(unsigned int cpu);
#endif
@@ -190,6 +191,7 @@ extern unsigned long __secondary_hold_spinloop;
extern unsigned long __secondary_hold_acknowledge;
extern char __secondary_hold;
+extern void __early_start(void);
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index de80e0f..be0261b 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -996,6 +996,34 @@ _GLOBAL(flush_dcache_L1)
blr
+/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
+_GLOBAL(__flush_disable_L1)
+ mflr r10
+ bl flush_dcache_L1 /* Flush L1 d-cache */
+ mtlr r10
+
+ mfspr r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
+ li r5, 2
+ rlwimi r4, r5, 0, 3
+
+ msync
+ isync
+ mtspr SPRN_L1CSR0, r4
+ isync
+
+1: mfspr r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
+ andi. r4, r4, 2
+ bne 1b
+
+ mfspr r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
+ li r5, 2
+ rlwimi r4, r5, 0, 3
+
+ mtspr SPRN_L1CSR1, r4
+ isync
+
+ blr
+
#ifdef CONFIG_SMP
/* When we get here, r24 needs to hold the CPU # */
.globl __secondary_start
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index d9f9441..e0ffe03 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -423,6 +423,16 @@ void generic_set_cpu_dead(unsigned int cpu)
per_cpu(cpu_state, cpu) = CPU_DEAD;
}
+/*
+ * The cpu_state should be set to CPU_UP_PREPARE in kick_cpu(), otherwise
+ * the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(),
+ * which makes the delay in generic_cpu_die() not happen.
+ */
+void generic_set_cpu_up(unsigned int cpu)
+{
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+}
+
int generic_check_cpu_restart(unsigned int cpu)
{
return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 8dd7147..e4beb34 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,7 +8,7 @@ menuconfig FSL_SOC_BOOKE
select FSL_PCI if PCI
select SERIAL_8250_EXTENDED if SERIAL_8250
select SERIAL_8250_SHARE_IRQ if SERIAL_8250
- select 85xx_TB_SYNC if KEXEC
+ select 85xx_TB_SYNC if KEXEC || HOTPLUG_CPU
default y
if FSL_SOC_BOOKE
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index edb0cad..2854bfa 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -2,7 +2,7 @@
* Author: Andy Fleming <afleming@freescale.com>
* Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2006-2008, 2011 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
*
* 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
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/kexec.h>
#include <linux/highmem.h>
+#include <linux/cpu.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
@@ -30,18 +31,14 @@
#include <sysdev/mpic.h>
#include "smp.h"
-extern void __early_start(void);
-
-#define BOOT_ENTRY_ADDR_UPPER 0
-#define BOOT_ENTRY_ADDR_LOWER 1
-#define BOOT_ENTRY_R3_UPPER 2
-#define BOOT_ENTRY_R3_LOWER 3
-#define BOOT_ENTRY_RESV 4
-#define BOOT_ENTRY_PIR 5
-#define BOOT_ENTRY_R6_UPPER 6
-#define BOOT_ENTRY_R6_LOWER 7
-#define NUM_BOOT_ENTRY 8
-#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
+struct epapr_spin_table {
+ u32 addr_h;
+ u32 addr_l;
+ u32 r3_h;
+ u32 r3_l;
+ u32 reserved;
+ u32 pir;
+};
#ifdef CONFIG_85xx_TB_SYNC
static struct ccsr_guts __iomem *guts;
@@ -106,15 +103,45 @@ static void mpc85xx_take_timebase(void)
}
#endif
-static int __init
-smp_85xx_kick_cpu(int nr)
+#ifdef CONFIG_HOTPLUG_CPU
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+ unsigned int cpu = smp_processor_id();
+ u32 tmp;
+
+ local_irq_disable();
+ idle_task_exit();
+ generic_set_cpu_dead(cpu);
+ mb();
+
+ mtspr(SPRN_TCR, 0);
+
+ __flush_disable_L1();
+ tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
+ mtspr(SPRN_HID0, tmp);
+ isync();
+
+ /* Enter NAP mode. */
+ tmp = mfmsr();
+ tmp |= MSR_WE;
+ mb();
+ mtmsr(tmp);
+ isync();
+
+ while (1)
+ ;
+}
+#endif
+
+static int __cpuinit smp_85xx_kick_cpu(int nr)
{
unsigned long flags;
const u64 *cpu_rel_addr;
- __iomem u32 *bptr_vaddr;
+ __iomem struct epapr_spin_table *spin_table;
struct device_node *np;
- int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
+ int hw_cpu = get_hard_smp_processor_id(nr);
int ioremappable;
+ int ret = 0;
WARN_ON(nr < 0 || nr >= NR_CPUS);
WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
@@ -139,46 +166,80 @@ smp_85xx_kick_cpu(int nr)
/* Map the spin table */
if (ioremappable)
- bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
+ spin_table = ioremap(*cpu_rel_addr,
+ sizeof(struct epapr_spin_table));
else
- bptr_vaddr = phys_to_virt(*cpu_rel_addr);
+ spin_table = phys_to_virt(*cpu_rel_addr);
local_irq_save(flags);
-
- out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
#ifdef CONFIG_PPC32
- out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Corresponding to generic_set_cpu_dead() */
+ generic_set_cpu_up(nr);
+
+ if (system_state == SYSTEM_RUNNING) {
+ out_be32(&spin_table->addr_l, 0);
+
+ /*
+ * We don't set the BPTR register here since it already points
+ * to the boot page properly.
+ */
+ mpic_reset_core(hw_cpu);
+
+ /* wait until core is ready... */
+ if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1,
+ 10000, 100)) {
+ pr_err("%s: timeout waiting for core %d to reset\n",
+ __func__, hw_cpu);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ /* clear the acknowledge status */
+ __secondary_hold_acknowledge = -1;
+ }
+#endif
+ out_be32(&spin_table->pir, hw_cpu);
+ out_be32(&spin_table->addr_l, __pa(__early_start));
if (!ioremappable)
- flush_dcache_range((ulong)bptr_vaddr,
- (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+ flush_dcache_range((ulong)spin_table,
+ (ulong)spin_table + sizeof(struct epapr_spin_table));
/* Wait a bit for the CPU to ack. */
- while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
- mdelay(1);
+ if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
+ 10000, 100)) {
+ pr_err("%s: timeout waiting for core %d to ack\n",
+ __func__, hw_cpu);
+ ret = -ENOENT;
+ goto out;
+ }
+out:
#else
smp_generic_kick_cpu(nr);
- out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
- __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+ out_be32(&spin_table->pir, hw_cpu);
+ out_be64((u64 *)(&spin_table->addr_h),
+ __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
if (!ioremappable)
- flush_dcache_range((ulong)bptr_vaddr,
- (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+ flush_dcache_range((ulong)spin_table,
+ (ulong)spin_table + sizeof(struct epapr_spin_table));
#endif
-
local_irq_restore(flags);
if (ioremappable)
- iounmap(bptr_vaddr);
+ iounmap(spin_table);
- pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
-
- return 0;
+ return ret;
}
struct smp_ops_t smp_85xx_ops = {
.kick_cpu = smp_85xx_kick_cpu,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = generic_cpu_disable,
+ .cpu_die = generic_cpu_die,
+#endif
#ifdef CONFIG_KEXEC
.give_timebase = smp_generic_give_timebase,
.take_timebase = smp_generic_take_timebase,
@@ -282,8 +343,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
}
#endif /* CONFIG_KEXEC */
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
+static void __cpuinit smp_85xx_setup_cpu(int cpu_nr)
{
if (smp_85xx_ops.probe == smp_mpic_probe)
mpic_setup_this_cpu();
@@ -330,6 +390,9 @@ void __init mpc85xx_smp_init(void)
smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
#endif
+#ifdef CONFIG_HOTPLUG_CPU
+ ppc_md.cpu_die = smp_85xx_mach_cpu_die;
+#endif
of_node_put(np);
}
--
1.6.4.1
^ permalink raw reply related
* [PATCH v6 4/5] fsl_pmc: Add API to enable device as wakeup event source
From: Zhao Chenhui @ 2012-06-26 10:25 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: linux-kernel
In-Reply-To: <1340706359-9455-1-git-send-email-chenhui.zhao@freescale.com>
Add APIs for setting wakeup source and lossless Ethernet in low power modes.
These APIs can be used by wake-on-packet feature.
Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
Changes for v6:
* changed the parameter of mpc85xx_pmc_set_wake()
* set an initial value to PMCDR register
arch/powerpc/sysdev/fsl_pmc.c | 77 ++++++++++++++++++++++++++++++++++++++++-
arch/powerpc/sysdev/fsl_soc.h | 12 ++++++
2 files changed, 88 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 45718c5..b6c8c8f 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -38,6 +38,7 @@ struct pmc_regs {
__be32 powmgtcsr;
#define POWMGTCSR_SLP 0x00020000
#define POWMGTCSR_DPSLP 0x00100000
+#define POWMGTCSR_LOSSLESS 0x00400000
__be32 res3[2];
/* 0xe008c: Power management clock disable register */
__be32 pmcdr;
@@ -48,6 +49,77 @@ static unsigned int pmc_flag;
#define PMC_SLEEP 0x1
#define PMC_DEEP_SLEEP 0x2
+#define PMC_LOSSLESS 0x4
+
+#define PMCDR_MASK_INIT 0x00e008e0
+
+/**
+ * mpc85xx_pmc_set_wake - enable devices as wakeup event source
+ * @dev: a device affected
+ * @enable: True to enable event generation; false to disable
+ *
+ * This enables the device as a wakeup event source, or disables it.
+ *
+ * RETURN VALUE:
+ * 0 is returned on success.
+ * -EINVAL is returned if device is not supposed to wake up the system.
+ * -ENODEV is returned if PMC is unavailable.
+ * Error code depending on the platform is returned if both the platform and
+ * the native mechanism fail to enable the generation of wake-up events
+ */
+int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+ int ret = 0;
+ struct device_node *clk_np;
+ const u32 *prop;
+ u32 pmcdr_mask;
+
+ if (!pmc_regs) {
+ pr_err("%s: PMC is unavailable\n", __func__);
+ return -ENODEV;
+ }
+
+ if (enable && !device_may_wakeup(dev))
+ return -EINVAL;
+
+ clk_np = of_parse_phandle(dev->of_node, "fsl,pmc-handle", 0);
+ if (!clk_np)
+ return -EINVAL;
+
+ prop = of_get_property(clk_np, "fsl,pmcdr-mask", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ goto out;
+ }
+ pmcdr_mask = be32_to_cpup(prop);
+
+ if (enable)
+ /* clear to enable clock in low power mode */
+ clrbits32(&pmc_regs->pmcdr, pmcdr_mask);
+ else
+ setbits32(&pmc_regs->pmcdr, pmcdr_mask);
+
+out:
+ of_node_put(clk_np);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_wake);
+
+/**
+ * mpc85xx_pmc_set_lossless_ethernet - enable lossless ethernet
+ * in (deep) sleep mode
+ * @enable: True to enable event generation; false to disable
+ */
+void mpc85xx_pmc_set_lossless_ethernet(int enable)
+{
+ if (pmc_flag & PMC_LOSSLESS) {
+ if (enable)
+ setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
+ else
+ clrbits32(&pmc_regs->powmgtcsr, POWMGTCSR_LOSSLESS);
+ }
+}
+EXPORT_SYMBOL_GPL(mpc85xx_pmc_set_lossless_ethernet);
static int pmc_suspend_enter(suspend_state_t state)
{
@@ -123,7 +195,10 @@ static int pmc_probe(struct platform_device *pdev)
pmc_flag |= PMC_DEEP_SLEEP;
if (of_device_is_compatible(np, "fsl,p1022-pmc"))
- pmc_flag |= PMC_DEEP_SLEEP;
+ pmc_flag |= PMC_DEEP_SLEEP | PMC_LOSSLESS;
+
+ /* Init the Power Management Clock Disable Register. */
+ setbits32(&pmc_regs->pmcdr, PMCDR_MASK_INIT);
suspend_set_ops(&pmc_suspend_ops);
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 11d9f94..b1510ef 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -3,6 +3,7 @@
#ifdef __KERNEL__
#include <asm/mmu.h>
+#include <linux/platform_device.h>
struct spi_device;
@@ -21,6 +22,17 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
+#ifdef CONFIG_FSL_PMC
+extern int mpc85xx_pmc_set_wake(struct device *dev, bool enable);
+extern void mpc85xx_pmc_set_lossless_ethernet(int enable);
+#else
+static inline int mpc85xx_pmc_set_wake(struct device *dev, bool enable)
+{
+ return -ENODEV;
+}
+#define mpc85xx_pmc_set_lossless_ethernet(enable) do { } while (0)
+#endif
+
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
/* The different ports that the DIU can be connected to */
--
1.6.4.1
^ permalink raw reply related
* [PATCH v6 5/5] powerpc/85xx: add support to JOG feature using cpufreq interface
From: Zhao Chenhui @ 2012-06-26 10:25 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: linux-kernel
In-Reply-To: <1340706359-9455-1-git-send-email-chenhui.zhao@freescale.com>
Some 85xx silicons like MPC8536 and P1022 have a JOG feature, which provides
a dynamic mechanism to lower or raise the CPU core clock at runtime.
This patch adds the support to change CPU frequency using the standard
cpufreq interface. The ratio CORE to CCB can be 1:1(except MPC8536), 3:2,
2:1, 5:2, 3:1, 7:2 and 4:1.
Two CPU cores on P1022 must not in the low power state during the frequency
transition. The driver uses a atomic counter to meet the requirement.
The jog mode frequency transition process on the MPC8536 is similar to
the deep sleep process. The driver need save the CPU state and restore
it after CPU warm reset.
Note:
* The I/O peripherals such as PCIe and eTSEC may lose packets during
the jog mode frequency transition.
* The driver doesn't support MPC8536 Rev 1.0 due to a JOG erratum.
Subsequent revisions of MPC8536 have corrected the erratum.
Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
CC: Scott Wood <scottwood@freescale.com>
---
Changes for v6:
* changed mpc85xx_jog_probe()
* call mpc85xx_jog_probe() in arch/powerpc/sysdev/fsl_pmc.c
* removed changes of kernel/cpu.c
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/cpufreq-jog.c | 388 +++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig | 11 +
arch/powerpc/sysdev/fsl_pmc.c | 3 +
arch/powerpc/sysdev/fsl_soc.h | 2 +
include/linux/cpu.h | 4 +
6 files changed, 409 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/85xx/cpufreq-jog.c
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index d154e39..8681a5c 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_SMP) += smp.o
obj-y += common.o sleep.o
+obj-$(CONFIG_MPC85xx_CPUFREQ) += cpufreq-jog.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/cpufreq-jog.c b/arch/powerpc/platforms/85xx/cpufreq-jog.c
new file mode 100644
index 0000000..ccc0c33
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/cpufreq-jog.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu <daveliu@freescale.com>
+ * Modifier: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ * Christian Krafft <krafft@de.ibm.com>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+#include <linux/suspend.h>
+#include <linux/cpu.h>
+
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/smp.h>
+
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+ {3, 0},
+ {4, 0},
+ {5, 0},
+ {6, 0},
+ {7, 0},
+ {8, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+ {2, 0},
+ {3, 0},
+ {4, 0},
+ {5, 0},
+ {6, 0},
+ {7, 0},
+ {8, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz 500000000
+#define FREQ_800MHz 800000000
+
+#define CORE_RATIO_STRIDE 8
+#define CORE_RATIO_MASK 0x3f
+#define CORE_RATIO_SHIFT 16
+
+#define PORPLLSR 0x0 /* Power-On Reset PLL ratio status register */
+
+#define PMJCR 0x7c /* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD 0x00001000
+#define PMJCR_CORE_SPD 0x00002000
+
+#define POWMGTCSR 0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG 0x00200000
+#define POWMGTCSR_INT_MASK 0x00000f00
+
+static void spin_while_jogging(void *dummy)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ atomic_inc(&in_jog_process);
+
+ while (atomic_read(&in_jog_process) != 0)
+ barrier();
+
+ local_irq_restore(flags);
+}
+
+static int get_pll(int hw_cpu)
+{
+ int shift;
+ u32 val = in_be32(guts + PORPLLSR);
+
+ shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+
+ return (val >> shift) & CORE_RATIO_MASK;
+}
+
+static int mpc8536_set_pll(unsigned int cpu, unsigned int pll)
+{
+ u32 corefreq, val, mask;
+ unsigned int cur_pll = get_pll(0);
+ unsigned long flags;
+
+ if (pll == cur_pll)
+ return 0;
+
+ val = (pll & CORE_RATIO_MASK) << CORE_RATIO_SHIFT;
+
+ corefreq = sysfreq * pll / 2;
+ /*
+ * Set the COREx_SPD bit if the requested core frequency
+ * is larger than the threshold frequency.
+ */
+ if (corefreq > FREQ_800MHz)
+ val |= PMJCR_CORE_SPD;
+
+ mask = (CORE_RATIO_MASK << CORE_RATIO_SHIFT) | PMJCR_CORE_SPD;
+ clrsetbits_be32(guts + PMJCR, mask, val);
+
+ /* readback to sync write */
+ in_be32(guts + PMJCR);
+
+ local_irq_save(flags);
+ mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_JOG);
+ local_irq_restore(flags);
+
+ /* verify */
+ cur_pll = get_pll(0);
+ if (cur_pll != pll) {
+ pr_err("%s: error. The current PLL is %d instead of %d.\n",
+ __func__, cur_pll, pll);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int p1022_set_pll(unsigned int cpu, unsigned int pll)
+{
+ int index, hw_cpu = get_hard_smp_processor_id(cpu);
+ int shift;
+ u32 corefreq, val, mask = 0;
+ unsigned int cur_pll = get_pll(hw_cpu);
+ unsigned long flags;
+ int ret = 0;
+
+ if (pll == cur_pll)
+ return 0;
+
+ shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+ val = (pll & CORE_RATIO_MASK) << shift;
+
+ corefreq = sysfreq * pll / 2;
+ /*
+ * Set the COREx_SPD bit if the requested core frequency
+ * is larger than the threshold frequency.
+ */
+ if (corefreq > FREQ_500MHz)
+ val |= PMJCR_CORE0_SPD << hw_cpu;
+
+ mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD << hw_cpu);
+ clrsetbits_be32(guts + PMJCR, mask, val);
+
+ /* readback to sync write */
+ in_be32(guts + PMJCR);
+
+ cpu_hotplug_disable_before_freeze();
+ /*
+ * A Jog request can not be asserted when any core is in a low
+ * power state on P1022. Before executing a jog request, any
+ * core which is in a low power state must be waked by a
+ * interrupt, and keep waking up until the sequence is
+ * finished.
+ */
+ for_each_present_cpu(index) {
+ if (!cpu_online(index)) {
+ cpu_hotplug_enable_after_thaw();
+ pr_err("%s: error, core%d is down.\n", __func__, index);
+ return -1;
+ }
+ }
+
+ atomic_set(&in_jog_process, 0);
+ smp_call_function(spin_while_jogging, NULL, 0);
+
+ local_irq_save(flags);
+
+ /* Wait for the other core to wake. */
+ if (!spin_event_timeout(atomic_read(&in_jog_process) == 1, 1000, 100)) {
+ pr_err("%s: timeout, the other core is not at running state.\n",
+ __func__);
+ ret = -1;
+ goto err;
+ }
+
+ out_be32(guts + POWMGTCSR, POWMGTCSR_JOG | POWMGTCSR_INT_MASK);
+
+ if (!spin_event_timeout(
+ (in_be32(guts + POWMGTCSR) & POWMGTCSR_JOG) == 0, 1000, 100)) {
+ pr_err("%s: timeout, fail to switch the core frequency.\n",
+ __func__);
+ ret = -1;
+ goto err;
+ }
+
+ clrbits32(guts + POWMGTCSR, POWMGTCSR_INT_MASK);
+ in_be32(guts + POWMGTCSR);
+
+ atomic_set(&in_jog_process, 0);
+err:
+ local_irq_restore(flags);
+ cpu_hotplug_enable_after_thaw();
+
+ /* verify */
+ cur_pll = get_pll(hw_cpu);
+ if (cur_pll != pll) {
+ pr_err("%s: error, the current PLL of core %d is %d instead of %d.\n",
+ __func__, hw_cpu, cur_pll, pll);
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * cpufreq functions
+ */
+static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ unsigned int i, cur_pll;
+ int hw_cpu = get_hard_smp_processor_id(policy->cpu);
+
+ if (!cpu_present(policy->cpu))
+ return -ENODEV;
+
+ /* the latency of a transition, the unit is ns */
+ policy->cpuinfo.transition_latency = 2000;
+
+ cur_pll = get_pll(hw_cpu);
+
+ /* initialize frequency table */
+ pr_debug("core%d frequency table:\n", hw_cpu);
+ for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
+ if (mpc85xx_freqs[i].index <= max_pll[hw_cpu]) {
+ /* The frequency unit is kHz. */
+ mpc85xx_freqs[i].frequency =
+ (sysfreq * mpc85xx_freqs[i].index / 2) / 1000;
+ } else {
+ mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
+ }
+
+ pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
+
+ if (mpc85xx_freqs[i].index == cur_pll)
+ policy->cur = mpc85xx_freqs[i].frequency;
+ }
+ pr_debug("current pll is at %d, and core freq is%d\n",
+ cur_pll, policy->cur);
+
+ cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
+
+ /*
+ * This ensures that policy->cpuinfo_min
+ * and policy->cpuinfo_max are set correctly.
+ */
+ return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+
+ return 0;
+}
+
+static int mpc85xx_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ unsigned int new;
+ int ret = 0;
+
+ if (!set_pll)
+ return -ENODEV;
+
+ cpufreq_frequency_table_target(policy,
+ mpc85xx_freqs,
+ target_freq,
+ relation,
+ &new);
+
+ freqs.old = policy->cur;
+ freqs.new = mpc85xx_freqs[new].frequency;
+ freqs.cpu = policy->cpu;
+
+ mutex_lock(&mpc85xx_switch_mutex);
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ ret = set_pll(policy->cpu, mpc85xx_freqs[new].index);
+ if (!ret) {
+ pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
+ policy->cpu, mpc85xx_freqs[new].frequency,
+ mpc85xx_freqs[new].index);
+
+ ppc_proc_freq = freqs.new * 1000ul;
+ }
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ mutex_unlock(&mpc85xx_switch_mutex);
+
+ return ret;
+}
+
+static struct cpufreq_driver mpc85xx_cpufreq_driver = {
+ .verify = mpc85xx_cpufreq_verify,
+ .target = mpc85xx_cpufreq_target,
+ .init = mpc85xx_cpufreq_cpu_init,
+ .exit = mpc85xx_cpufreq_cpu_exit,
+ .name = "mpc85xx-JOG",
+ .owner = THIS_MODULE,
+ .flags = CPUFREQ_CONST_LOOPS,
+};
+
+static struct of_device_id mpc85xx_jog_ids[] = {
+ { .compatible = "fsl,mpc8536-guts", },
+ { .compatible = "fsl,p1022-guts", },
+ {}
+};
+
+int mpc85xx_jog_probe(void)
+{
+ struct device_node *np;
+ unsigned int svr;
+
+ np = of_find_matching_node(NULL, mpc85xx_jog_ids);
+ if (!np)
+ return -ENODEV;
+
+ guts = of_iomap(np, 0);
+ if (!guts) {
+ of_node_put(np);
+ return -ENODEV;
+ }
+
+ sysfreq = fsl_get_sys_freq();
+
+ if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
+ svr = mfspr(SPRN_SVR);
+ if ((svr & 0x7fff) == 0x10) {
+ pr_err("MPC8536 Rev 1.0 does not support cpufreq(JOG).\n");
+ of_node_put(np);
+ return -ENODEV;
+ }
+ mpc85xx_freqs = mpc8536_freqs_table;
+ set_pll = mpc8536_set_pll;
+ max_pll[0] = get_pll(0);
+
+ } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
+ mpc85xx_freqs = p1022_freqs_table;
+ set_pll = p1022_set_pll;
+ max_pll[0] = get_pll(0);
+ max_pll[1] = get_pll(1);
+ }
+
+ pr_info("Freescale MPC85xx cpufreq(JOG) driver\n");
+
+ of_node_put(np);
+ return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
+}
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index a35ca44..7dbd239 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -204,6 +204,17 @@ config CPU_FREQ_PMAC64
This adds support for frequency switching on Apple iMac G5,
and some of the more recent desktop G5 machines as well.
+config MPC85xx_CPUFREQ
+ bool "Support for Freescale MPC85xx CPU freq"
+ depends on PPC_85xx && FSL_PMC
+ default n
+ select CPU_FREQ_TABLE
+ help
+ This adds support for dynamic frequency switching on
+ Freescale MPC85xx by cpufreq interface. MPC8536 and P1022
+ have a JOG feature, which provides a dynamic mechanism
+ to lower or raise the CPU core clock at runtime.
+
config PPC_PASEMI_CPUFREQ
bool "Support for PA Semi PWRficient"
depends on PPC_PASEMI
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index b6c8c8f..b809a1b 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -202,6 +202,9 @@ static int pmc_probe(struct platform_device *pdev)
suspend_set_ops(&pmc_suspend_ops);
+#ifdef CONFIG_MPC85xx_CPUFREQ
+ mpc85xx_jog_probe();
+#endif
pr_info("Freescale PMC driver: sleep(standby)%s\n",
(pmc_flag & PMC_DEEP_SLEEP) ? ", deep sleep(mem)" : "");
return 0;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index b1510ef..25be25c 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -65,5 +65,7 @@ void fsl_hv_halt(void);
* code can be compatible with both 32-bit & 36-bit.
*/
extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
+
+extern int mpc85xx_jog_probe(void);
#endif
#endif
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index ee28844..eceb399 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -147,6 +147,8 @@ void notify_cpu_starting(unsigned int cpu);
extern void cpu_maps_update_begin(void);
extern void cpu_maps_update_done(void);
+extern void cpu_hotplug_disable_before_freeze(void);
+extern void cpu_hotplug_enable_after_thaw(void);
#else /* CONFIG_SMP */
#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
@@ -168,6 +170,8 @@ static inline void cpu_maps_update_done(void)
{
}
+static inline void cpu_hotplug_disable_before_freeze(void) {}
+static inline void cpu_hotplug_enable_after_thaw(void) {}
#endif /* CONFIG_SMP */
extern struct bus_type cpu_subsys;
--
1.6.4.1
^ permalink raw reply related
* [PATCH v6 3/5] powerpc/85xx: add sleep and deep sleep support
From: Zhao Chenhui @ 2012-06-26 10:25 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: linux-kernel
In-Reply-To: <1340706359-9455-1-git-send-email-chenhui.zhao@freescale.com>
From: Li Yang <leoli@freescale.com>
In sleep PM mode, the clocks of e500 core and unused IP blocks is
turned off. IP blocks which are allowed to wake up the processor
are still running.
Some Freescale chips like MPC8536 and P1022 has deep sleep PM mode
in addtion to the sleep PM mode.
While in deep sleep PM mode, additionally, the power supply is
removed from e500 core and most IP blocks. Only the blocks needed
to wake up the chip out of deep sleep are ON.
This patch supports 32-bit and 36-bit address space.
The sleep mode is equal to the Standby state in Linux. The deep sleep
mode is equal to the Suspend-to-RAM state of Linux Power Management.
Command to enter sleep mode.
echo standby > /sys/power/state
Command to enter deep sleep mode.
echo mem > /sys/power/state
Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Cc: Scott Wood <scottwood@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
Changes for v6:
* changed the declaration of flush_dcache_L1()
* some minor changes
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/cacheflush.h | 2 +
arch/powerpc/kernel/Makefile | 3 +
arch/powerpc/kernel/l2cache_85xx.S | 53 +++
arch/powerpc/platforms/85xx/Makefile | 2 +-
arch/powerpc/platforms/85xx/sleep.S | 609 +++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pmc.c | 98 +++++-
arch/powerpc/sysdev/fsl_soc.h | 5 +
8 files changed, 754 insertions(+), 20 deletions(-)
create mode 100644 arch/powerpc/kernel/l2cache_85xx.S
create mode 100644 arch/powerpc/platforms/85xx/sleep.S
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d6bacbe..6883769 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -673,7 +673,7 @@ config FSL_PCI
config FSL_PMC
bool
default y
- depends on SUSPEND && (PPC_85xx || PPC_86xx)
+ depends on SUSPEND && (PPC_85xx || PPC_86xx) && !PPC_E500MC
help
Freescale MPC85xx/MPC86xx power management controller support
(suspend/resume). For MPC83xx see platforms/83xx/suspend.c
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index b843e35..6c5f1c2 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -58,6 +58,8 @@ extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
extern void flush_dcache_phys_range(unsigned long start, unsigned long stop);
#endif
+extern void flush_dcache_L1(void);
+
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
memcpy(dst, src, len); \
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f5808a3..cb70dba 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -64,6 +64,9 @@ obj-$(CONFIG_FA_DUMP) += fadump.o
ifeq ($(CONFIG_PPC32),y)
obj-$(CONFIG_E500) += idle_e500.o
endif
+ifneq ($(CONFIG_PPC_E500MC),y)
+obj-$(CONFIG_PPC_85xx) += l2cache_85xx.o
+endif
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
diff --git a/arch/powerpc/kernel/l2cache_85xx.S b/arch/powerpc/kernel/l2cache_85xx.S
new file mode 100644
index 0000000..b0b7d1c
--- /dev/null
+++ b/arch/powerpc/kernel/l2cache_85xx.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009-2012 Freescale Semiconductor, Inc. All rights reserved.
+ * Scott Wood <scottwood@freescale.com>
+ * Dave Liu <daveliu@freescale.com>
+ * implement the L2 cache operations of e500 based L2 controller
+ *
+ * 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 <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+ .section .text
+
+ /* r3 = virtual address of L2 controller, WIMG = 01xx */
+_GLOBAL(flush_disable_L2)
+ /* It's a write-through cache, so only invalidation is needed. */
+ mbar
+ isync
+ lwz r4, 0(r3)
+ li r5, 1
+ rlwimi r4, r5, 30, 0xc0000000
+ stw r4, 0(r3)
+
+ /* Wait for the invalidate to finish */
+1: lwz r4, 0(r3)
+ andis. r4, r4, 0x4000
+ bne 1b
+ mbar
+
+ blr
+
+ /* r3 = virtual address of L2 controller, WIMG = 01xx */
+_GLOBAL(invalidate_enable_L2)
+ mbar
+ isync
+ lwz r4, 0(r3)
+ li r5, 3
+ rlwimi r4, r5, 30, 0xc0000000
+ stw r4, 0(r3)
+
+ /* Wait for the invalidate to finish */
+1: lwz r4, 0(r3)
+ andis. r4, r4, 0x4000
+ bne 1b
+ mbar
+
+ blr
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 2125d4c..d154e39 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,7 +3,7 @@
#
obj-$(CONFIG_SMP) += smp.o
-obj-y += common.o
+obj-y += common.o sleep.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
diff --git a/arch/powerpc/platforms/85xx/sleep.S b/arch/powerpc/platforms/85xx/sleep.S
new file mode 100644
index 0000000..b272f0c
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/sleep.S
@@ -0,0 +1,609 @@
+/*
+ * Enter and leave deep sleep/sleep state on MPC85xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (C) 2006-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+
+#define SS_TB 0x00
+#define SS_HID 0x08 /* 2 HIDs */
+#define SS_IAC 0x10 /* 2 IACs */
+#define SS_DAC 0x18 /* 2 DACs */
+#define SS_DBCR 0x20 /* 3 DBCRs */
+#define SS_PID 0x2c /* 3 PIDs */
+#define SS_SPRG 0x38 /* 8 SPRGs */
+#define SS_IVOR 0x58 /* 20 interrupt vectors */
+#define SS_TCR 0xa8
+#define SS_BUCSR 0xac
+#define SS_L1CSR 0xb0 /* 2 L1CSRs */
+#define SS_MSR 0xb8
+#define SS_USPRG 0xbc
+#define SS_GPREG 0xc0 /* r12-r31 */
+#define SS_LR 0x110
+#define SS_CR 0x114
+#define SS_SP 0x118
+#define SS_CURRENT 0x11c
+#define SS_IVPR 0x120
+#define SS_BPTR 0x124
+
+
+#define STATE_SAVE_SIZE 0x128
+
+ .section .data
+ .align 5
+mpc85xx_sleep_save_area:
+ .space STATE_SAVE_SIZE
+ccsrbase_low:
+ .long 0
+ccsrbase_high:
+ .long 0
+powmgtreq:
+ .long 0
+
+ .section .text
+ .align 12
+
+ /*
+ * r3 = high word of physical address of CCSR
+ * r4 = low word of physical address of CCSR
+ * r5 = JOG or deep sleep request
+ * JOG-0x00200000, deep sleep-0x00100000
+ */
+_GLOBAL(mpc85xx_enter_deep_sleep)
+ lis r6, ccsrbase_low@ha
+ stw r4, ccsrbase_low@l(r6)
+ lis r6, ccsrbase_high@ha
+ stw r3, ccsrbase_high@l(r6)
+
+ lis r6, powmgtreq@ha
+ stw r5, powmgtreq@l(r6)
+
+ lis r10, mpc85xx_sleep_save_area@h
+ ori r10, r10, mpc85xx_sleep_save_area@l
+
+ mfspr r5, SPRN_HID0
+ mfspr r6, SPRN_HID1
+
+ stw r5, SS_HID+0(r10)
+ stw r6, SS_HID+4(r10)
+
+ mfspr r4, SPRN_IAC1
+ mfspr r5, SPRN_IAC2
+ mfspr r6, SPRN_DAC1
+ mfspr r7, SPRN_DAC2
+
+ stw r4, SS_IAC+0(r10)
+ stw r5, SS_IAC+4(r10)
+ stw r6, SS_DAC+0(r10)
+ stw r7, SS_DAC+4(r10)
+
+ mfspr r4, SPRN_DBCR0
+ mfspr r5, SPRN_DBCR1
+ mfspr r6, SPRN_DBCR2
+
+ stw r4, SS_DBCR+0(r10)
+ stw r5, SS_DBCR+4(r10)
+ stw r6, SS_DBCR+8(r10)
+
+ mfspr r4, SPRN_PID0
+ mfspr r5, SPRN_PID1
+ mfspr r6, SPRN_PID2
+
+ stw r4, SS_PID+0(r10)
+ stw r5, SS_PID+4(r10)
+ stw r6, SS_PID+8(r10)
+
+ mfspr r4, SPRN_SPRG0
+ mfspr r5, SPRN_SPRG1
+ mfspr r6, SPRN_SPRG2
+ mfspr r7, SPRN_SPRG3
+
+ stw r4, SS_SPRG+0x00(r10)
+ stw r5, SS_SPRG+0x04(r10)
+ stw r6, SS_SPRG+0x08(r10)
+ stw r7, SS_SPRG+0x0c(r10)
+
+ mfspr r4, SPRN_SPRG4
+ mfspr r5, SPRN_SPRG5
+ mfspr r6, SPRN_SPRG6
+ mfspr r7, SPRN_SPRG7
+
+ stw r4, SS_SPRG+0x10(r10)
+ stw r5, SS_SPRG+0x14(r10)
+ stw r6, SS_SPRG+0x18(r10)
+ stw r7, SS_SPRG+0x1c(r10)
+
+ mfspr r4, SPRN_IVPR
+ stw r4, SS_IVPR(r10)
+
+ mfspr r4, SPRN_IVOR0
+ mfspr r5, SPRN_IVOR1
+ mfspr r6, SPRN_IVOR2
+ mfspr r7, SPRN_IVOR3
+
+ stw r4, SS_IVOR+0x00(r10)
+ stw r5, SS_IVOR+0x04(r10)
+ stw r6, SS_IVOR+0x08(r10)
+ stw r7, SS_IVOR+0x0c(r10)
+
+ mfspr r4, SPRN_IVOR4
+ mfspr r5, SPRN_IVOR5
+ mfspr r6, SPRN_IVOR6
+ mfspr r7, SPRN_IVOR7
+
+ stw r4, SS_IVOR+0x10(r10)
+ stw r5, SS_IVOR+0x14(r10)
+ stw r6, SS_IVOR+0x18(r10)
+ stw r7, SS_IVOR+0x1c(r10)
+
+ mfspr r4, SPRN_IVOR8
+ mfspr r5, SPRN_IVOR9
+ mfspr r6, SPRN_IVOR10
+ mfspr r7, SPRN_IVOR11
+
+ stw r4, SS_IVOR+0x20(r10)
+ stw r5, SS_IVOR+0x24(r10)
+ stw r6, SS_IVOR+0x28(r10)
+ stw r7, SS_IVOR+0x2c(r10)
+
+ mfspr r4, SPRN_IVOR12
+ mfspr r5, SPRN_IVOR13
+ mfspr r6, SPRN_IVOR14
+ mfspr r7, SPRN_IVOR15
+
+ stw r4, SS_IVOR+0x30(r10)
+ stw r5, SS_IVOR+0x34(r10)
+ stw r6, SS_IVOR+0x38(r10)
+ stw r7, SS_IVOR+0x3c(r10)
+
+ mfspr r4, SPRN_IVOR32
+ mfspr r5, SPRN_IVOR33
+ mfspr r6, SPRN_IVOR34
+ mfspr r7, SPRN_IVOR35
+
+ stw r4, SS_IVOR+0x40(r10)
+ stw r5, SS_IVOR+0x44(r10)
+ stw r6, SS_IVOR+0x48(r10)
+ stw r7, SS_IVOR+0x4c(r10)
+
+ mfspr r4, SPRN_TCR
+ mfspr r5, SPRN_BUCSR
+ mfspr r6, SPRN_L1CSR0
+ mfspr r7, SPRN_L1CSR1
+ mfspr r8, SPRN_USPRG0
+
+ stw r4, SS_TCR(r10)
+ stw r5, SS_BUCSR(r10)
+ stw r6, SS_L1CSR+0(r10)
+ stw r7, SS_L1CSR+4(r10)
+ stw r8, SS_USPRG+0(r10)
+
+ stmw r12, SS_GPREG(r10)
+
+ mfmsr r4
+ mflr r5
+ mfcr r6
+
+ stw r4, SS_MSR(r10)
+ stw r5, SS_LR(r10)
+ stw r6, SS_CR(r10)
+ stw r1, SS_SP(r10)
+ stw r2, SS_CURRENT(r10)
+
+1: mftbu r4
+ mftb r5
+ mftbu r6
+ cmpw r4, r6
+ bne 1b
+
+ stw r4, SS_TB+0(r10)
+ stw r5, SS_TB+4(r10)
+
+ lis r5, ccsrbase_low@ha
+ lwz r4, ccsrbase_low@l(r5)
+ lis r5, ccsrbase_high@ha
+ lwz r3, ccsrbase_high@l(r5)
+
+ /* Disable machine checks and critical exceptions */
+ mfmsr r5
+ rlwinm r5, r5, 0, ~MSR_CE
+ rlwinm r5, r5, 0, ~MSR_ME
+ mtmsr r5
+ isync
+
+ /* Use TLB1[15] to map the CCSR at 0xf0000000 */
+ lis r5, 0x100f
+ mtspr SPRN_MAS0, r5
+ lis r5, 0xc000
+ ori r5, r5, 0x0500
+ mtspr SPRN_MAS1, r5
+ lis r5, 0xf000
+ ori r5, r5, 0x000a
+ mtspr SPRN_MAS2, r5
+ rlwinm r5, r4, 0, 0xfffff000
+ ori r5, r5, 0x0005
+ mtspr SPRN_MAS3, r5
+ mtspr SPRN_MAS7, r3
+ isync
+ tlbwe
+ isync
+
+ lis r3, 0xf000
+ lwz r4, 0x20(r3)
+ stw r4, SS_BPTR(r10)
+
+ lis r3, 0xf002 /* L2 cache controller at CCSR+0x20000 */
+ bl flush_disable_L2
+ bl __flush_disable_L1
+
+ /* Enable I-cache, so as not to upset the bus
+ * with our loop.
+ */
+
+ mfspr r4, SPRN_L1CSR1
+ ori r4, r4, 1
+ mtspr SPRN_L1CSR1, r4
+ isync
+
+ /* Set boot page translation */
+ lis r3, 0xf000
+ lis r4, (mpc85xx_deep_resume - PAGE_OFFSET)@h
+ ori r4, r4, (mpc85xx_deep_resume - PAGE_OFFSET)@l
+ rlwinm r4, r4, 20, 0x000fffff
+ oris r4, r4, 0x8000
+ stw r4, 0x20(r3)
+ lwz r4, 0x20(r3) /* read-back to flush write */
+ twi 0, r4, 0
+ isync
+
+ /* Disable the decrementer */
+ mfspr r4, SPRN_TCR
+ rlwinm r4, r4, 0, ~TCR_DIE
+ mtspr SPRN_TCR, r4
+
+ mfspr r4, SPRN_TSR
+ oris r4, r4, TSR_DIS@h
+ mtspr SPRN_TSR, r4
+
+ /* set PMRCCR[VRCNT] to wait power stable for 40ms */
+ lis r3, 0xf00e
+ lwz r4, 0x84(r3)
+ clrlwi r4, r4, 16
+ oris r4, r4, 0x12a3
+ stw r4, 0x84(r3)
+ lwz r4, 0x84(r3)
+
+ /* set deep sleep bit in POWMGTSCR */
+ lis r3, powmgtreq@ha
+ lwz r8, powmgtreq@l(r3)
+
+ lis r3, 0xf00e
+ lwz r4, 0x80(r3)
+ or r4, r4, r8
+ stw r4, 0x80(r3)
+ lwz r4, 0x80(r3) /* read-back to flush write */
+ twi 0, r4, 0
+ isync
+
+ mftb r5
+1: /* spin until either we enter deep sleep, or the sleep process is
+ * aborted due to a pending wakeup event. Wait some time between
+ * accesses, so we don't flood the bus and prevent the pmc from
+ * detecting an idle system.
+ */
+
+ mftb r4
+ subf r7, r5, r4
+ cmpwi r7, 1000
+ blt 1b
+ mr r5, r4
+
+ lwz r6, 0x80(r3)
+ andis. r6, r6, 0x0010
+ bne 1b
+ b 2f
+
+2: mfspr r4, SPRN_PIR
+ andi. r4, r4, 1
+99: bne 99b
+
+ /* Establish a temporary 64MB 0->0 mapping in TLB1[1]. */
+ lis r4, 0x1001
+ mtspr SPRN_MAS0, r4
+ lis r4, 0xc000
+ ori r4, r4, 0x0800
+ mtspr SPRN_MAS1, r4
+ li r4, 0
+ mtspr SPRN_MAS2, r4
+ li r4, 0x0015
+ mtspr SPRN_MAS3, r4
+ li r4, 0
+ mtspr SPRN_MAS7, r4
+ isync
+ tlbwe
+ isync
+
+ lis r3, (3f - PAGE_OFFSET)@h
+ ori r3, r3, (3f - PAGE_OFFSET)@l
+ mtctr r3
+ bctr
+
+ /* Locate the resume vector in the last word of the current page. */
+ . = mpc85xx_enter_deep_sleep + 0xffc
+mpc85xx_deep_resume:
+ b 2b
+
+3:
+ /* Restore the contents of TLB1[0]. It is assumed that it covers
+ * the currently executing code and the sleep save area, and that
+ * it does not alias our temporary mapping (which is at virtual zero).
+ */
+ lis r3, (TLBCAM - PAGE_OFFSET)@h
+ ori r3, r3, (TLBCAM - PAGE_OFFSET)@l
+
+ lwz r4, 0(r3)
+ lwz r5, 4(r3)
+ lwz r6, 8(r3)
+ lwz r7, 12(r3)
+ lwz r8, 16(r3)
+
+ mtspr SPRN_MAS0, r4
+ mtspr SPRN_MAS1, r5
+ mtspr SPRN_MAS2, r6
+ mtspr SPRN_MAS3, r7
+ mtspr SPRN_MAS7, r8
+
+ isync
+ tlbwe
+ isync
+
+ /* Access the ccsrbase address with TLB1[0] */
+ lis r5, ccsrbase_low@ha
+ lwz r4, ccsrbase_low@l(r5)
+ lis r5, ccsrbase_high@ha
+ lwz r3, ccsrbase_high@l(r5)
+
+ /* Use TLB1[15] to map the CCSR at 0xf0000000 */
+ lis r5, 0x100f
+ mtspr SPRN_MAS0, r5
+ lis r5, 0xc000
+ ori r5, r5, 0x0500
+ mtspr SPRN_MAS1, r5
+ lis r5, 0xf000
+ ori r5, r5, 0x000a
+ mtspr SPRN_MAS2, r5
+ rlwinm r5, r4, 0, 0xfffff000
+ ori r5, r5, 0x0005
+ mtspr SPRN_MAS3, r5
+ mtspr SPRN_MAS7, r3
+ isync
+ tlbwe
+ isync
+
+ lis r3, 0xf002 /* L2 cache controller at CCSR+0x20000 */
+ bl invalidate_enable_L2
+
+ /* Access the MEM(r10) with TLB1[0] */
+ lis r10, mpc85xx_sleep_save_area@h
+ ori r10, r10, mpc85xx_sleep_save_area@l
+
+ lis r3, 0xf000
+ lwz r4, SS_BPTR(r10)
+ stw r4, 0x20(r3) /* restore BPTR */
+
+ /* Program shift running space to PAGE_OFFSET */
+ mfmsr r3
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+
+ mtsrr1 r3
+ mtsrr0 r4
+ rfi
+
+1: /* Restore the rest of TLB1, in ascending order so that
+ * the TLB1[1] gets invalidated first.
+ *
+ * XXX: It's better to invalidate the temporary mapping
+ * TLB1[15] for CCSR before restore any TLB1 entry include 0.
+ */
+ lis r4, 0x100f
+ mtspr SPRN_MAS0, r4
+ lis r4, 0
+ mtspr SPRN_MAS1, r4
+ isync
+ tlbwe
+ isync
+
+ lis r3, (TLBCAM + 5*4 - 4)@h
+ ori r3, r3, (TLBCAM + 5*4 - 4)@l
+ li r4, 15
+ mtctr r4
+
+2:
+ lwz r5, 4(r3)
+ lwz r6, 8(r3)
+ lwz r7, 12(r3)
+ lwz r8, 16(r3)
+ lwzu r9, 20(r3)
+
+ mtspr SPRN_MAS0, r5
+ mtspr SPRN_MAS1, r6
+ mtspr SPRN_MAS2, r7
+ mtspr SPRN_MAS3, r8
+ mtspr SPRN_MAS7, r9
+
+ isync
+ tlbwe
+ isync
+ bdnz 2b
+
+ lis r10, mpc85xx_sleep_save_area@h
+ ori r10, r10, mpc85xx_sleep_save_area@l
+
+ lwz r5, SS_HID+0(r10)
+ lwz r6, SS_HID+4(r10)
+
+ isync
+ mtspr SPRN_HID0, r5
+ isync
+
+ msync
+ mtspr SPRN_HID1, r6
+ isync
+
+ lwz r4, SS_IAC+0(r10)
+ lwz r5, SS_IAC+4(r10)
+ lwz r6, SS_DAC+0(r10)
+ lwz r7, SS_DAC+4(r10)
+
+ mtspr SPRN_IAC1, r4
+ mtspr SPRN_IAC2, r5
+ mtspr SPRN_DAC1, r6
+ mtspr SPRN_DAC2, r7
+
+ lwz r4, SS_DBCR+0(r10)
+ lwz r5, SS_DBCR+4(r10)
+ lwz r6, SS_DBCR+8(r10)
+
+ mtspr SPRN_DBCR0, r4
+ mtspr SPRN_DBCR1, r5
+ mtspr SPRN_DBCR2, r6
+
+ lwz r4, SS_PID+0(r10)
+ lwz r5, SS_PID+4(r10)
+ lwz r6, SS_PID+8(r10)
+
+ mtspr SPRN_PID0, r4
+ mtspr SPRN_PID1, r5
+ mtspr SPRN_PID2, r6
+
+ lwz r4, SS_SPRG+0x00(r10)
+ lwz r5, SS_SPRG+0x04(r10)
+ lwz r6, SS_SPRG+0x08(r10)
+ lwz r7, SS_SPRG+0x0c(r10)
+
+ mtspr SPRN_SPRG0, r4
+ mtspr SPRN_SPRG1, r5
+ mtspr SPRN_SPRG2, r6
+ mtspr SPRN_SPRG3, r7
+
+ lwz r4, SS_SPRG+0x10(r10)
+ lwz r5, SS_SPRG+0x14(r10)
+ lwz r6, SS_SPRG+0x18(r10)
+ lwz r7, SS_SPRG+0x1c(r10)
+
+ mtspr SPRN_SPRG4, r4
+ mtspr SPRN_SPRG5, r5
+ mtspr SPRN_SPRG6, r6
+ mtspr SPRN_SPRG7, r7
+
+ lwz r4, SS_IVPR(r10)
+ mtspr SPRN_IVPR, r4
+
+ lwz r4, SS_IVOR+0x00(r10)
+ lwz r5, SS_IVOR+0x04(r10)
+ lwz r6, SS_IVOR+0x08(r10)
+ lwz r7, SS_IVOR+0x0c(r10)
+
+ mtspr SPRN_IVOR0, r4
+ mtspr SPRN_IVOR1, r5
+ mtspr SPRN_IVOR2, r6
+ mtspr SPRN_IVOR3, r7
+
+ lwz r4, SS_IVOR+0x10(r10)
+ lwz r5, SS_IVOR+0x14(r10)
+ lwz r6, SS_IVOR+0x18(r10)
+ lwz r7, SS_IVOR+0x1c(r10)
+
+ mtspr SPRN_IVOR4, r4
+ mtspr SPRN_IVOR5, r5
+ mtspr SPRN_IVOR6, r6
+ mtspr SPRN_IVOR7, r7
+
+ lwz r4, SS_IVOR+0x20(r10)
+ lwz r5, SS_IVOR+0x24(r10)
+ lwz r6, SS_IVOR+0x28(r10)
+ lwz r7, SS_IVOR+0x2c(r10)
+
+ mtspr SPRN_IVOR8, r4
+ mtspr SPRN_IVOR9, r5
+ mtspr SPRN_IVOR10, r6
+ mtspr SPRN_IVOR11, r7
+
+ lwz r4, SS_IVOR+0x30(r10)
+ lwz r5, SS_IVOR+0x34(r10)
+ lwz r6, SS_IVOR+0x38(r10)
+ lwz r7, SS_IVOR+0x3c(r10)
+
+ mtspr SPRN_IVOR12, r4
+ mtspr SPRN_IVOR13, r5
+ mtspr SPRN_IVOR14, r6
+ mtspr SPRN_IVOR15, r7
+
+ lwz r4, SS_IVOR+0x40(r10)
+ lwz r5, SS_IVOR+0x44(r10)
+ lwz r6, SS_IVOR+0x48(r10)
+ lwz r7, SS_IVOR+0x4c(r10)
+
+ mtspr SPRN_IVOR32, r4
+ mtspr SPRN_IVOR33, r5
+ mtspr SPRN_IVOR34, r6
+ mtspr SPRN_IVOR35, r7
+
+ lwz r4, SS_TCR(r10)
+ lwz r5, SS_BUCSR(r10)
+ lwz r6, SS_L1CSR+0(r10)
+ lwz r7, SS_L1CSR+4(r10)
+ lwz r8, SS_USPRG+0(r10)
+
+ mtspr SPRN_TCR, r4
+ mtspr SPRN_BUCSR, r5
+
+ msync
+ isync
+ mtspr SPRN_L1CSR0, r6
+ isync
+
+ mtspr SPRN_L1CSR1, r7
+ isync
+
+ mtspr SPRN_USPRG0, r8
+
+ lmw r12, SS_GPREG(r10)
+
+ lwz r1, SS_SP(r10)
+ lwz r2, SS_CURRENT(r10)
+ lwz r4, SS_MSR(r10)
+ lwz r5, SS_LR(r10)
+ lwz r6, SS_CR(r10)
+
+ msync
+ mtmsr r4
+ isync
+
+ mtlr r5
+ mtcr r6
+
+ li r4, 0
+ mtspr SPRN_TBWL, r4
+
+ lwz r4, SS_TB+0(r10)
+ lwz r5, SS_TB+4(r10)
+
+ mtspr SPRN_TBWU, r4
+ mtspr SPRN_TBWL, r5
+
+ lis r3, 1
+ mtdec r3
+
+ blr
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8..45718c5 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -2,6 +2,7 @@
* Suspend/resume support
*
* Copyright 2009 MontaVista Software, Inc.
+ * Copyright 2010-2012 Freescale Semiconductor Inc.
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
@@ -19,39 +20,89 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/of_platform.h>
+#include <linux/pm.h>
+#include <asm/cacheflush.h>
+#include <asm/switch_to.h>
+
+#include <sysdev/fsl_soc.h>
struct pmc_regs {
+ /* 0xe0070: Device disable control register */
__be32 devdisr;
+ /* 0xe0074: 2nd Device disable control register */
__be32 devdisr2;
- __be32 :32;
- __be32 :32;
- __be32 pmcsr;
-#define PMCSR_SLP (1 << 17)
+ __be32 res1;
+ /* 0xe007c: Power Management Jog Control Register */
+ __be32 pmjcr;
+ /* 0xe0080: Power management control and status register */
+ __be32 powmgtcsr;
+#define POWMGTCSR_SLP 0x00020000
+#define POWMGTCSR_DPSLP 0x00100000
+ __be32 res3[2];
+ /* 0xe008c: Power management clock disable register */
+ __be32 pmcdr;
};
-static struct device *pmc_dev;
static struct pmc_regs __iomem *pmc_regs;
+static unsigned int pmc_flag;
+
+#define PMC_SLEEP 0x1
+#define PMC_DEEP_SLEEP 0x2
static int pmc_suspend_enter(suspend_state_t state)
{
- int ret;
+ int ret = 0;
+
+ switch (state) {
+#ifdef CONFIG_PPC_85xx
+ case PM_SUSPEND_MEM:
+#ifdef CONFIG_SPE
+ enable_kernel_spe();
+#endif
+ enable_kernel_fp();
+
+ pr_debug("%s: Entering deep sleep\n", __func__);
+
+ local_irq_disable();
+ mpc85xx_enter_deep_sleep(get_immrbase(), POWMGTCSR_DPSLP);
+
+ pr_debug("%s: Resumed from deep sleep\n", __func__);
+ break;
+#endif
- setbits32(&pmc_regs->pmcsr, PMCSR_SLP);
- /* At this point, the CPU is asleep. */
+ case PM_SUSPEND_STANDBY:
+ local_irq_disable();
+#ifdef CONFIG_PPC_85xx
+ flush_dcache_L1();
+#endif
+ setbits32(&pmc_regs->powmgtcsr, POWMGTCSR_SLP);
+ /* At this point, the CPU is asleep. */
- /* Upon resume, wait for SLP bit to be clear. */
- ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0,
- 10000, 10) ? 0 : -ETIMEDOUT;
- if (ret)
- dev_err(pmc_dev, "tired waiting for SLP bit to clear\n");
+ /* Upon resume, wait for SLP bit to be clear. */
+ ret = spin_event_timeout(
+ (in_be32(&pmc_regs->powmgtcsr) & POWMGTCSR_SLP) == 0,
+ 10000, 10);
+ if (!ret) {
+ pr_err("%s: timeout waiting for SLP bit "
+ "to be cleared\n", __func__);
+ ret = -EINVAL;
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+
+ }
return ret;
}
static int pmc_suspend_valid(suspend_state_t state)
{
- if (state != PM_SUSPEND_STANDBY)
+ if (((pmc_flag & PMC_SLEEP) && (state == PM_SUSPEND_STANDBY)) ||
+ ((pmc_flag & PMC_DEEP_SLEEP) && (state == PM_SUSPEND_MEM)))
+ return 1;
+ else
return 0;
- return 1;
}
static const struct platform_suspend_ops pmc_suspend_ops = {
@@ -59,14 +110,25 @@ static const struct platform_suspend_ops pmc_suspend_ops = {
.enter = pmc_suspend_enter,
};
-static int pmc_probe(struct platform_device *ofdev)
+static int pmc_probe(struct platform_device *pdev)
{
- pmc_regs = of_iomap(ofdev->dev.of_node, 0);
+ struct device_node *np = pdev->dev.of_node;
+
+ pmc_regs = of_iomap(np, 0);
if (!pmc_regs)
return -ENOMEM;
- pmc_dev = &ofdev->dev;
+ pmc_flag = PMC_SLEEP;
+ if (of_device_is_compatible(np, "fsl,mpc8536-pmc"))
+ pmc_flag |= PMC_DEEP_SLEEP;
+
+ if (of_device_is_compatible(np, "fsl,p1022-pmc"))
+ pmc_flag |= PMC_DEEP_SLEEP;
+
suspend_set_ops(&pmc_suspend_ops);
+
+ pr_info("Freescale PMC driver: sleep(standby)%s\n",
+ (pmc_flag & PMC_DEEP_SLEEP) ? ", deep sleep(mem)" : "");
return 0;
}
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d0073..11d9f94 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -48,5 +48,10 @@ extern struct platform_diu_data_ops diu_ops;
void fsl_hv_restart(char *cmd);
void fsl_hv_halt(void);
+/*
+ * ccsrbar is u64 rather than phys_addr_t so that the assembly
+ * code can be compatible with both 32-bit & 36-bit.
+ */
+extern void mpc85xx_enter_deep_sleep(u64 ccsrbar, u32 powmgtreq);
#endif
#endif
--
1.6.4.1
^ permalink raw reply related
* [PATCH 1/4] powerpc/perf: Create mmcra_sihv/mmcra_sipv helpers
From: Anton Blanchard @ 2012-06-26 11:00 UTC (permalink / raw)
To: benh, paulus, sukadev; +Cc: linuxppc-dev
We want to access the MMCRA_SIHV and MMCRA_SIPR bits elsewhere so
create mmcra_sihv and mmcra_sipr which hide the differences between
the old and new layout of the bits.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-build/arch/powerpc/perf/core-book3s.c
===================================================================
--- linux-build.orig/arch/powerpc/perf/core-book3s.c 2012-06-26 10:26:40.695707845 +1000
+++ linux-build/arch/powerpc/perf/core-book3s.c 2012-06-26 10:28:53.325958826 +1000
@@ -116,6 +116,26 @@ static inline void perf_get_data_addr(st
*addrp = mfspr(SPRN_SDAR);
}
+static bool mmcra_sihv(unsigned long mmcra)
+{
+ unsigned long sihv = MMCRA_SIHV;
+
+ if (ppmu->flags & PPMU_ALT_SIPR)
+ sihv = POWER6_MMCRA_SIHV;
+
+ return !!(mmcra & sihv);
+}
+
+static bool mmcra_sipr(unsigned long mmcra)
+{
+ unsigned long sipr = MMCRA_SIPR;
+
+ if (ppmu->flags & PPMU_ALT_SIPR)
+ sipr = POWER6_MMCRA_SIPR;
+
+ return !!(mmcra & sipr);
+}
+
static inline u32 perf_flags_from_msr(struct pt_regs *regs)
{
if (regs->msr & MSR_PR)
@@ -128,8 +148,6 @@ static inline u32 perf_flags_from_msr(st
static inline u32 perf_get_misc_flags(struct pt_regs *regs)
{
unsigned long mmcra = regs->dsisr;
- unsigned long sihv = MMCRA_SIHV;
- unsigned long sipr = MMCRA_SIPR;
/* Not a PMU interrupt: Make up flags from regs->msr */
if (TRAP(regs) != 0xf00)
@@ -156,15 +174,10 @@ static inline u32 perf_get_misc_flags(st
return PERF_RECORD_MISC_USER;
}
- if (ppmu->flags & PPMU_ALT_SIPR) {
- sihv = POWER6_MMCRA_SIHV;
- sipr = POWER6_MMCRA_SIPR;
- }
-
/* PR has priority over HV, so order below is important */
- if (mmcra & sipr)
+ if (mmcra_sipr(mmcra))
return PERF_RECORD_MISC_USER;
- if ((mmcra & sihv) && (freeze_events_kernel != MMCR0_FCHV))
+ if (mmcra_sihv(mmcra) && (freeze_events_kernel != MMCR0_FCHV))
return PERF_RECORD_MISC_HYPERVISOR;
return PERF_RECORD_MISC_KERNEL;
}
^ permalink raw reply
* [PATCH 2/4] powerpc/perf: Move code to select SIAR or pt_regs into perf_read_regs
From: Anton Blanchard @ 2012-06-26 11:01 UTC (permalink / raw)
To: benh, paulus, sukadev; +Cc: linuxppc-dev
In-Reply-To: <20120626210013.2fbb9044@kryten>
The logic to choose whether to use the SIAR or get the information
out of pt_regs is going to get more complicated, so do it once in
perf_read_regs.
We overload regs->result which is gross but we are already doing it
with regs->dsisr.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Other architectures appear to be playing similar overloading tricks
so we should probably solve this in a nicer way.
Index: linux-build/arch/powerpc/include/asm/perf_event.h
===================================================================
--- linux-build.orig/arch/powerpc/include/asm/perf_event.h 2012-06-26 10:26:40.000000000 +1000
+++ linux-build/arch/powerpc/include/asm/perf_event.h 2012-06-26 10:31:02.132149613 +1000
@@ -26,8 +26,13 @@
#include <asm/ptrace.h>
#include <asm/reg.h>
+/*
+ * Overload regs->result to specify whether we should use the MSR (result
+ * is zero) or the SIAR (result is non zero).
+ */
#define perf_arch_fetch_caller_regs(regs, __ip) \
do { \
+ (regs)->result = 0; \
(regs)->nip = __ip; \
(regs)->gpr[1] = *(unsigned long *)__get_SP(); \
asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \
Index: linux-build/arch/powerpc/perf/core-book3s.c
===================================================================
--- linux-build.orig/arch/powerpc/perf/core-book3s.c 2012-06-26 10:28:53.000000000 +1000
+++ linux-build/arch/powerpc/perf/core-book3s.c 2012-06-26 10:35:40.560886839 +1000
@@ -73,7 +73,10 @@ static inline u32 perf_get_misc_flags(st
{
return 0;
}
-static inline void perf_read_regs(struct pt_regs *regs) { }
+static inline void perf_read_regs(struct pt_regs *regs)
+{
+ regs->result = 0;
+}
static inline int perf_intr_is_nmi(struct pt_regs *regs)
{
return 0;
@@ -148,17 +151,9 @@ static inline u32 perf_flags_from_msr(st
static inline u32 perf_get_misc_flags(struct pt_regs *regs)
{
unsigned long mmcra = regs->dsisr;
+ unsigned long use_siar = regs->result;
- /* Not a PMU interrupt: Make up flags from regs->msr */
- if (TRAP(regs) != 0xf00)
- return perf_flags_from_msr(regs);
-
- /*
- * If we don't support continuous sampling and this
- * is not a marked event, same deal
- */
- if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
- !(mmcra & MMCRA_SAMPLE_ENABLE))
+ if (!use_siar)
return perf_flags_from_msr(regs);
/*
@@ -185,10 +180,24 @@ static inline u32 perf_get_misc_flags(st
/*
* Overload regs->dsisr to store MMCRA so we only need to read it once
* on each interrupt.
+ * Overload regs->result to specify whether we should use the MSR (result
+ * is zero) or the SIAR (result is non zero).
*/
static inline void perf_read_regs(struct pt_regs *regs)
{
- regs->dsisr = mfspr(SPRN_MMCRA);
+ unsigned long mmcra = mfspr(SPRN_MMCRA);
+ int marked = mmcra & MMCRA_SAMPLE_ENABLE;
+ int use_siar;
+
+ if (TRAP(regs) != 0xf00)
+ use_siar = 0;
+ else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && !marked)
+ use_siar = 0;
+ else
+ use_siar = 1;
+
+ regs->dsisr = mmcra;
+ regs->result = use_siar;
}
/*
@@ -1342,18 +1351,12 @@ unsigned long perf_misc_flags(struct pt_
*/
unsigned long perf_instruction_pointer(struct pt_regs *regs)
{
- unsigned long mmcra = regs->dsisr;
+ unsigned long use_siar = regs->result;
- /* Not a PMU interrupt */
- if (TRAP(regs) != 0xf00)
- return regs->nip;
-
- /* Processor doesn't support sampling non marked events */
- if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
- !(mmcra & MMCRA_SAMPLE_ENABLE))
+ if (use_siar)
+ return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
+ else
return regs->nip;
-
- return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
}
static bool pmc_overflow(unsigned long val)
^ permalink raw reply
* [PATCH 3/4] powerpc/perf: Always use pt_regs for userspace samples
From: Anton Blanchard @ 2012-06-26 11:02 UTC (permalink / raw)
To: benh, paulus, sukadev; +Cc: linuxppc-dev
In-Reply-To: <20120626210013.2fbb9044@kryten>
At the moment we always use the SIAR if the PMU supports continuous
sampling. Unfortunately the SIAR and the PMU exception are not
synchronised for non marked events so we can end up with callchains
that dont make sense.
The following patch checks the HV and PR bits for samples coming from
userspace and always uses pt_regs for them. Userspace will never have
interrupts off so there is no real advantage to using the SIAR for
non marked events in userspace.
I had experimented with a patch that did a similar thing for kernel
samples but we lost a significant amount of information. I was
unable to profile any of our early exception code for example.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-build/arch/powerpc/perf/core-book3s.c
===================================================================
--- linux-build.orig/arch/powerpc/perf/core-book3s.c 2012-06-26 10:45:12.402615339 +1000
+++ linux-build/arch/powerpc/perf/core-book3s.c 2012-06-26 10:51:25.465039364 +1000
@@ -189,9 +189,30 @@ static inline void perf_read_regs(struct
int marked = mmcra & MMCRA_SAMPLE_ENABLE;
int use_siar;
+ /*
+ * If this isn't a PMU exception (eg a software event) the SIAR is
+ * not valid. Use pt_regs.
+ *
+ * If it is a marked event use the SIAR.
+ *
+ * If the PMU doesn't update the SIAR for non marked events use
+ * pt_regs.
+ *
+ * If the PMU has HV/PR flags then check to see if they
+ * place the exception in userspace. If so, use pt_regs. In
+ * continuous sampling mode the SIAR and the PMU exception are
+ * not synchronised, so they may be many instructions apart.
+ * This can result in confusing backtraces. We still want
+ * hypervisor samples as well as samples in the kernel with
+ * interrupts off hence the userspace check.
+ */
if (TRAP(regs) != 0xf00)
use_siar = 0;
- else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && !marked)
+ else if (marked)
+ use_siar = 1;
+ else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
+ use_siar = 0;
+ else if (!(ppmu->flags & PPMU_NO_SIPR) && mmcra_sipr(mmcra))
use_siar = 0;
else
use_siar = 1;
^ permalink raw reply
* [PATCH 4/4] powerpc/perf: Use perf_instruction_pointer in callchains
From: Anton Blanchard @ 2012-06-26 11:04 UTC (permalink / raw)
To: benh, paulus, sukadev; +Cc: linuxppc-dev
In-Reply-To: <20120626210013.2fbb9044@kryten>
We use SIAR or regs->nip for the instruction pointer depending on
the PMU configuration, but we always use regs->nip in the callchain.
Use perf_instruction_pointer so the backtrace is consistent.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-build/arch/powerpc/perf/callchain.c
===================================================================
--- linux-build.orig/arch/powerpc/perf/callchain.c 2012-04-12 11:36:26.236223786 +1000
+++ linux-build/arch/powerpc/perf/callchain.c 2012-06-26 12:49:28.944202712 +1000
@@ -57,7 +57,7 @@ perf_callchain_kernel(struct perf_callch
lr = regs->link;
sp = regs->gpr[1];
- perf_callchain_store(entry, regs->nip);
+ perf_callchain_store(entry, perf_instruction_pointer(regs));
if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
return;
@@ -238,7 +238,7 @@ static void perf_callchain_user_64(struc
struct signal_frame_64 __user *sigframe;
unsigned long __user *fp, *uregs;
- next_ip = regs->nip;
+ next_ip = perf_instruction_pointer(regs);
lr = regs->link;
sp = regs->gpr[1];
perf_callchain_store(entry, next_ip);
@@ -444,7 +444,7 @@ static void perf_callchain_user_32(struc
long level = 0;
unsigned int __user *fp, *uregs;
- next_ip = regs->nip;
+ next_ip = perf_instruction_pointer(regs);
lr = regs->link;
sp = regs->gpr[1];
perf_callchain_store(entry, next_ip);
^ permalink raw reply
* [PATCH] drivers: usb/power: fix return value check of usb_get_phy
From: Kishon Vijay Abraham I @ 2012-06-26 12:10 UTC (permalink / raw)
To: cbou, dwmw2, alexander.shishkin, gregkh, leoli, balbi,
eric.y.miao, linux, haojian.zhuang, stern, linux-kernel,
linux-usb, linuxppc-dev, linux-omap, linux-arm-kernel
Cc: Kishon Vijay Abraham I
usb_get_phy will return -ENODEV if it's not able to find the phy. Hence
fixed all the callers of usb_get_phy to check for this error condition
instead of relying on a non-zero value as success condition.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Developed on
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git xceiv
Compile tested only for omap2plus_defconfig.
drivers/power/ab8500_charger.c | 2 +-
drivers/power/isp1704_charger.c | 2 +-
drivers/power/pda_power.c | 16 ++++++++--------
drivers/power/twl4030_charger.c | 7 ++++---
drivers/usb/chipidea/udc.c | 9 +++++----
drivers/usb/gadget/fsl_udc_core.c | 15 ++++++++-------
drivers/usb/gadget/mv_udc_core.c | 13 +++++++------
drivers/usb/gadget/omap_udc.c | 25 +++++++++++++------------
drivers/usb/gadget/pxa25x_udc.c | 11 ++++++-----
drivers/usb/gadget/pxa27x_udc.c | 11 ++++++-----
drivers/usb/gadget/s3c-hsudc.c | 9 +++++----
drivers/usb/host/ehci-fsl.c | 5 +++--
drivers/usb/host/ehci-msm.c | 2 +-
drivers/usb/host/ehci-mv.c | 7 ++++---
drivers/usb/host/ehci-tegra.c | 7 ++++---
drivers/usb/host/ohci-omap.c | 5 +++--
drivers/usb/musb/am35x.c | 3 ++-
drivers/usb/musb/blackfin.c | 3 ++-
drivers/usb/musb/da8xx.c | 3 ++-
drivers/usb/musb/davinci.c | 3 ++-
drivers/usb/musb/musb_dsps.c | 3 ++-
drivers/usb/musb/omap2430.c | 2 +-
drivers/usb/musb/tusb6010.c | 3 ++-
drivers/usb/musb/ux500.c | 3 ++-
drivers/usb/otg/otg.c | 4 ++--
25 files changed, 96 insertions(+), 77 deletions(-)
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 6bd6f1c..d4f0c98 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2689,7 +2689,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
}
di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!di->usb_phy) {
+ if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(di->dev, "failed to get usb transceiver\n");
ret = -EINVAL;
goto free_usb;
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 090e5f9..1229119 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -416,7 +416,7 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev)
return -ENOMEM;
isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!isp->phy)
+ if (IS_ERR_OR_NULL(isp->phy))
goto fail0;
isp->dev = &pdev->dev;
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 7602d49..8dbcd53 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -322,11 +322,11 @@ static int pda_power_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG_UTILS
transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- if (transceiver && !pdata->is_usb_online) {
- pdata->is_usb_online = otg_is_usb_online;
- }
- if (transceiver && !pdata->is_ac_online) {
- pdata->is_ac_online = otg_is_ac_online;
+ if (!IS_ERR_OR_NULL(transceiver)) {
+ if (!pdata->is_usb_online)
+ pdata->is_usb_online = otg_is_usb_online;
+ if (!pdata->is_ac_online)
+ pdata->is_ac_online = otg_is_ac_online;
}
#endif
@@ -373,7 +373,7 @@ static int pda_power_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver && pdata->use_otg_notifier) {
+ if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
if (ret) {
@@ -408,7 +408,7 @@ usb_supply_failed:
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver)
+ if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
ac_irq_failed:
@@ -443,7 +443,7 @@ static int pda_power_remove(struct platform_device *pdev)
if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver)
+ if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
if (ac_draw) {
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 13f9db2..7cacbaa 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c/twl.h>
@@ -480,7 +481,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
INIT_WORK(&bci->work, twl4030_bci_usb_work);
bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- if (bci->transceiver != NULL) {
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
usb_register_notifier(bci->transceiver, &bci->usb_nb);
}
@@ -507,7 +508,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
return 0;
fail_unmask_interrupts:
- if (bci->transceiver != NULL) {
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_phy(bci->transceiver);
}
@@ -538,7 +539,7 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
TWL4030_INTERRUPTS_BCIIMR2A);
- if (bci->transceiver != NULL) {
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_phy(bci->transceiver);
}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index a06d28b..4688ab7 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -1712,7 +1713,7 @@ static int udc_start(struct ci13xxx *udc)
if (retval)
goto unreg_device;
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval)
@@ -1729,7 +1730,7 @@ static int udc_start(struct ci13xxx *udc)
return retval;
remove_trans:
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
usb_put_phy(udc->transceiver);
}
@@ -1740,7 +1741,7 @@ remove_dbg:
unreg_device:
device_unregister(&udc->gadget.dev);
put_transceiver:
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_put_phy(udc->transceiver);
free_pools:
dma_pool_destroy(udc->td_pool);
@@ -1772,7 +1773,7 @@ static void udc_stop(struct ci13xxx *udc)
dma_pool_destroy(udc->td_pool);
dma_pool_destroy(udc->qh_pool);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, NULL);
usb_put_phy(udc->transceiver);
}
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 0808820..8d8fca6 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -1229,7 +1230,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -ENOTSUPP;
}
@@ -1983,13 +1984,13 @@ static int fsl_start(struct usb_gadget_driver *driver,
goto out;
}
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* Suspend the controller until OTG enable it */
udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
/* connect to bus through transceiver */
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
retval = otg_set_peripheral(
udc_controller->transceiver->otg,
&udc_controller->gadget);
@@ -2030,7 +2031,7 @@ static int fsl_stop(struct usb_gadget_driver *driver)
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
otg_set_peripheral(udc_controller->transceiver->otg, NULL);
/* stop DR, disable intr */
@@ -2456,7 +2457,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!udc_controller->transceiver) {
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
ERR("Can't find OTG driver!\n");
ret = -ENODEV;
goto err_kfree;
@@ -2540,7 +2541,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err_free_irq;
}
- if (!udc_controller->transceiver) {
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup(udc_controller);
@@ -2564,7 +2565,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_free_irq;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
/* setup QH and epctrl for ep0 */
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 75ff41a..9305de4 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
@@ -1381,7 +1382,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
return retval;
}
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@@ -2107,7 +2108,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
* then vbus irq will not be requested in udc driver.
*/
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(udc->pdata->vbus->irq, &dev->dev);
/* free memory allocated in probe */
@@ -2325,7 +2326,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
udc->clock_gating = 1;
else if (pdata->vbus) {
udc->clock_gating = 1;
@@ -2369,7 +2370,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
err_unregister:
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(pdata->vbus->irq, &dev->dev);
device_unregister(&udc->gadget.dev);
err_free_irq:
@@ -2404,7 +2405,7 @@ static int mv_udc_suspend(struct device *_dev)
struct mv_udc *udc = the_controller;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (udc->pdata->vbus && udc->pdata->vbus->poll)
@@ -2437,7 +2438,7 @@ static int mv_udc_resume(struct device *_dev)
int retval;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (!udc->clock_gating) {
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index cf8bf26..7b71295 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -35,6 +35,7 @@
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h>
@@ -1211,7 +1212,7 @@ static int omap_wakeup(struct usb_gadget *gadget)
/* NOTE: non-OTG systems may use SRP TOO... */
} else if (!(udc->devstat & UDC_ATT)) {
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
retval = otg_start_srp(udc->transceiver->otg);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1343,7 +1344,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct omap_udc *udc;
udc = container_of(gadget, struct omap_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1792,12 +1793,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
if (devstat & UDC_ATT) {
udc->gadget.speed = USB_SPEED_FULL;
VDBG("connect\n");
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_enable(udc);
// if (driver->connect) call it
} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_disable(udc);
DBG("disconnect, gadget %s\n",
udc->driver->driver.name);
@@ -1837,12 +1838,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
udc->driver->suspend(&udc->gadget);
spin_lock(&udc->lock);
}
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 1);
} else {
VDBG("resume\n");
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 0);
if (udc->gadget.speed == USB_SPEED_FULL
@@ -2154,7 +2155,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
/* connect to bus through transceiver */
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
status = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (status < 0) {
@@ -2201,7 +2202,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 0);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
(void) otg_set_peripheral(udc->transceiver->otg, NULL);
else
pullup_disable(udc);
@@ -2866,7 +2867,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
* but not having one probably means no VBUS detection.
*/
xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (xceiv)
+ if (!IS_ERR_OR_NULL(xceiv))
type = xceiv->label;
else if (config->otg) {
DBG("OTG requires external transceiver!\n");
@@ -2898,7 +2899,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
case 16:
case 19:
case 25:
- if (!xceiv) {
+ if (IS_ERR_OR_NULL(xceiv)) {
DBG("external transceiver not registered!\n");
type = "unknown";
}
@@ -3010,7 +3011,7 @@ cleanup1:
udc = NULL;
cleanup0:
- if (xceiv)
+ if (!IS_ERR_OR_NULL(xceiv))
usb_put_phy(xceiv);
if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) {
@@ -3040,7 +3041,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
udc->done = &done;
pullup_disable(udc);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
}
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index cc0b1e6..fa8e93c 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -993,7 +994,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
udc = container_of(_gadget, struct pxa25x_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1299,7 +1300,7 @@ fail:
DMSG("registered gadget driver '%s'\n", driver->driver.name);
/* connect to bus through transceiver */
- if (dev->transceiver) {
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
retval = otg_set_peripheral(dev->transceiver->otg,
&dev->gadget);
if (retval) {
@@ -1359,7 +1360,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
stop_activity(dev, driver);
local_irq_enable();
- if (dev->transceiver)
+ if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
driver->unbind(&dev->gadget);
@@ -2237,7 +2238,7 @@ lubbock_fail0:
if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup);
err_gpio_pullup:
- if (dev->transceiver) {
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
@@ -2279,7 +2280,7 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
clk_put(dev->clk);
- if (dev->transceiver) {
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 8f744aa..644b430 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/list.h>
@@ -1573,7 +1574,7 @@ static int should_enable_udc(struct pxa_udc *udc)
int put_on;
put_on = ((udc->pullup_on) && (udc->driver));
- put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
+ put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
return put_on;
}
@@ -1594,7 +1595,7 @@ static int should_disable_udc(struct pxa_udc *udc)
int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver));
- put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
+ put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
return put_off;
}
@@ -1665,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
struct pxa_udc *udc;
udc = to_gadget_udc(_gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@@ -1834,7 +1835,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
}
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 22326f2..7c91562 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
@@ -1165,7 +1166,7 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
}
/* connect to bus through transceiver */
- if (hsudc->transceiver) {
+ if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
ret = otg_set_peripheral(hsudc->transceiver->otg,
&hsudc->gadget);
if (ret) {
@@ -1220,7 +1221,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
s3c_hsudc_stop_activity(hsudc);
spin_unlock_irqrestore(&hsudc->lock, flags);
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
disable_irq(hsudc->irq);
@@ -1249,7 +1250,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
if (!hsudc)
return -ENODEV;
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
return usb_phy_set_power(hsudc->transceiver, mA);
return -EOPNOTSUPP;
@@ -1385,7 +1386,7 @@ err_irq:
err_remap:
release_mem_region(res->start, resource_size(res));
err_res:
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
usb_put_phy(hsudc->transceiver);
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index ba29058..32865a7 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
@@ -146,7 +147,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n",
hcd, ehci, ehci->transceiver);
- if (ehci->transceiver) {
+ if (!IS_ERR_OR_NULL(ehci->transceiver)) {
retval = otg_set_host(ehci->transceiver->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
@@ -192,7 +193,7 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- if (ehci->transceiver) {
+ if (!IS_ERR_OR_NULL(ehci->transceiver)) {
otg_set_host(ehci->transceiver->otg, NULL);
usb_put_phy(ehci->transceiver);
}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index c7615fb..6b4ffb5 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -146,7 +146,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
* management.
*/
phy = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!phy) {
+ if (IS_ERR_OR_NULL(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto unmap;
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index ef7aa0d..0e8c168 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>
@@ -254,7 +255,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!ehci_mv->otg) {
+ if (IS_ERR_OR_NULL(ehci_mv->otg)) {
dev_err(&pdev->dev,
"unable to find transceiver\n");
retval = -ENODEV;
@@ -302,7 +303,7 @@ err_set_vbus:
pdata->set_vbus(0);
#ifdef CONFIG_USB_OTG_UTILS
err_put_transceiver:
- if (ehci_mv->otg)
+ if (!IS_ERR_OR_NULL(ehci_mv->otg))
usb_put_phy(ehci_mv->otg);
#endif
err_disable_clk:
@@ -331,7 +332,7 @@ static int mv_ehci_remove(struct platform_device *pdev)
if (hcd->rh_registered)
usb_remove_hcd(hcd);
- if (ehci_mv->otg) {
+ if (!IS_ERR_OR_NULL(ehci_mv->otg)) {
otg_set_host(ehci_mv->otg->otg, NULL);
usb_put_phy(ehci_mv->otg);
}
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 14df2f5..477ecfa 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -17,6 +17,7 @@
*/
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/irq.h>
@@ -750,7 +751,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- if (tegra->transceiver)
+ if (!IS_ERR_OR_NULL(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
}
#endif
@@ -773,7 +774,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
fail:
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
usb_put_phy(tegra->transceiver);
}
@@ -808,7 +809,7 @@ static int tegra_ehci_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
usb_put_phy(tegra->transceiver);
}
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 92a77df..c7b06f5 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -18,6 +18,7 @@
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
@@ -212,7 +213,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
ohci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
- if (ohci->transceiver) {
+ if (!IS_ERR_OR_NULL(ohci->transceiver)) {
int status = otg_set_host(ohci->transceiver->otg,
&ohci_to_hcd(ohci)->self);
dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
@@ -403,7 +404,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
usb_remove_hcd(hcd);
- if (ohci->transceiver) {
+ if (!IS_ERR_OR_NULL(ohci->transceiver)) {
(void) otg_set_host(ohci->transceiver->otg, 0);
usb_put_phy(ohci->transceiver);
}
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 4a8cbf0..7a95ab8 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -365,7 +366,7 @@ static int am35x_musb_init(struct musb *musb)
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv)
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
if (is_host_enabled(musb))
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 4529409..428e6aa 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/gpio.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
@@ -416,7 +417,7 @@ static int bfin_musb_init(struct musb *musb)
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv) {
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index d731c80..0f9fcec 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -426,7 +427,7 @@ static int da8xx_musb_init(struct musb *musb)
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv)
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto fail;
if (is_host_enabled(musb))
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 582268d..f649204 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -28,6 +28,7 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
@@ -385,7 +386,7 @@ static int davinci_musb_init(struct musb *musb)
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv)
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto unregister;
musb->mregs += DAVINCI_BASE_OFFSET;
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 92603e4..217808d 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
@@ -377,7 +378,7 @@ static int dsps_musb_init(struct musb *musb)
/* NOP driver needs change if supporting dual instance */
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv)
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
/* Returns zero if e.g. not clocked */
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2813490..5fdb9da 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -320,7 +320,7 @@ static int omap2430_musb_init(struct musb *musb)
* which needs a driver, drivers aren't always needed.
*/
musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- if (!musb->xceiv) {
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 8ddf3d5..1a1bd9c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/prefetch.h>
#include <linux/usb.h>
@@ -1079,7 +1080,7 @@ static int tusb_musb_init(struct musb *musb)
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv)
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
pdev = to_platform_device(musb->controller);
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 46cf80a..a8c0fad 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -38,7 +39,7 @@ struct ux500_glue {
static int ux500_musb_init(struct musb *musb)
{
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
- if (!musb->xceiv) {
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 0fa4d8c..88d62b1 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -67,7 +67,7 @@ struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
return NULL;
phy = usb_get_phy(type);
- if (phy) {
+ if (!IS_ERR(phy)) {
*ptr = phy;
devres_add(dev, ptr);
} else
@@ -82,7 +82,7 @@ EXPORT_SYMBOL(devm_usb_get_phy);
* @type - the type of the phy the controller requires
*
* Returns the phy driver, after getting a refcount to it; or
- * null if there is no such phy. The caller is responsible for
+ * -ENODEV if there is no such phy. The caller is responsible for
* calling usb_put_phy() to release that count.
*
* For use by USB host and peripheral drivers.
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH v6 1/5] powerpc/85xx: implement hardware timebase sync
From: Kumar Gala @ 2012-06-26 14:03 UTC (permalink / raw)
To: Zhao Chenhui; +Cc: scottwood, linuxppc-dev, linux-kernel
In-Reply-To: <1340706359-9455-1-git-send-email-chenhui.zhao@freescale.com>
On Jun 26, 2012, at 5:25 AM, Zhao Chenhui wrote:
> Do hardware timebase sync. Firstly, stop all timebases, and transfer
> the timebase value of the boot core to the other core. Finally,
> start all timebases.
>=20
> Only apply to dual-core chips, such as MPC8572, P2020, etc.
>=20
> Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> Changes for v6:
> * added 85xx_TB_SYNC
> * added isync() after set_tb()
> * removed extra entries from mpc85xx_smp_guts_ids
Why only on dual-core chips? Is this because of something related to 2 =
cores, or related to corenet vs non-corenet SoCs and how turning on/off =
the timebase works in the SOC?
- k=
^ permalink raw reply
* [PATCH 0/5] Usb gadget devicetree bindings
From: Alexandre Pereira da Silva @ 2012-06-26 14:27 UTC (permalink / raw)
To: Grant Likely, Rob Herring, Rob Landley, Felipe Balbi,
Greg Kroah-Hartman, Li Yang, Alexandre Pereira da Silva,
devicetree-discuss, linux-doc, linux-kernel, linux-usb,
linuxppc-dev, Roland Stigge
This patch series adds support to set basic usb gadget properties via
devicetree.
I takes into account the sugestions from Rob Herring and Mitch Bradley.
This was only tested on ARM LPC32XX SOC. I'm including patches to other soc's as
an reference.
Alexandre Pereira da Silva (5):
usb: gadget: lpc32xx_udc: Propagate devicetree to gadget drivers
usb: gadget: s3c-hsotg: Propagate devicetree to gadget drivers
usb: gadget: fsl_udc: Propagate devicetree to gadget drivers
usb: gadget: at91_udc: Propagate devicetree to gadget drivers
usb: gadget: composite: parse dt overrides
Documentation/devicetree/bindings/usb/gadget.txt | 20 +++++++++++
drivers/usb/gadget/at91_udc.c | 1 +
drivers/usb/gadget/composite.c | 39 ++++++++++++++++++++++
drivers/usb/gadget/fsl_udc_core.c | 1 +
drivers/usb/gadget/lpc32xx_udc.c | 1 +
drivers/usb/gadget/s3c-hsotg.c | 1 +
6 files changed, 63 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/gadget.txt
--
1.7.10
^ permalink raw reply
* [PATCH 1/5] usb: gadget: lpc32xx_udc: Propagate devicetree to gadget drivers
From: Alexandre Pereira da Silva @ 2012-06-26 14:27 UTC (permalink / raw)
To: Grant Likely, Rob Herring, Rob Landley, Felipe Balbi,
Greg Kroah-Hartman, Li Yang, Alexandre Pereira da Silva,
devicetree-discuss, linux-doc, linux-kernel, linux-usb,
linuxppc-dev, Roland Stigge
In-Reply-To: <1340720833-781-1-git-send-email-aletes.xgr@gmail.com>
Fill dev.of_node of gadget drivers, so they can use devicetree
Signed-off-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
---
drivers/usb/gadget/lpc32xx_udc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c
index 93a901b..551c0e9 100644
--- a/drivers/usb/gadget/lpc32xx_udc.c
+++ b/drivers/usb/gadget/lpc32xx_udc.c
@@ -3005,6 +3005,7 @@ static int lpc32xx_start(struct usb_gadget_driver *driver,
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
+ udc->gadget.dev.of_node = udc->dev->of_node;
udc->enabled = 1;
udc->selfpowered = 1;
udc->vbus = 0;
--
1.7.10
^ permalink raw reply related
* [PATCH 2/5] usb: gadget: s3c-hsotg: Propagate devicetree to gadget drivers
From: Alexandre Pereira da Silva @ 2012-06-26 14:27 UTC (permalink / raw)
To: Grant Likely, Rob Herring, Rob Landley, Felipe Balbi,
Greg Kroah-Hartman, Li Yang, Alexandre Pereira da Silva,
devicetree-discuss, linux-doc, linux-kernel, linux-usb,
linuxppc-dev, Roland Stigge
In-Reply-To: <1340720833-781-1-git-send-email-aletes.xgr@gmail.com>
Fill dev.of_node of gadget drivers, so they can use devicetree
Signed-off-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
---
drivers/usb/gadget/s3c-hsotg.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index f4abb0e..fed2f28 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -2954,6 +2954,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
driver->driver.bus = NULL;
hsotg->driver = driver;
hsotg->gadget.dev.driver = &driver->driver;
+ hsotg->gadget.dev.of_node = hsotg->dev->of_node;
hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
--
1.7.10
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox