* Re: [PATCH 3/3] powerpc/kvm: remove redundant assignment
From: Paul Mackerras @ 2013-11-06 5:04 UTC (permalink / raw)
To: Liu Ping Fan; +Cc: linuxppc-dev, Alexander Graf, kvm-ppc
In-Reply-To: <1383637364-14691-3-git-send-email-pingfank@linux.vnet.ibm.com>
On Tue, Nov 05, 2013 at 03:42:44PM +0800, Liu Ping Fan wrote:
> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
> ---
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index 28160ac..7682837 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -731,7 +731,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
> lock_rmap(rmap);
>
> /* Check if we might have been invalidated; let the guest retry if so */
> - ret = RESUME_GUEST;
> if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) {
> unlock_rmap(rmap);
> goto out_unlock;
Acked-by: Paul Mackerras <paulus@samba.org>
^ permalink raw reply
* RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Bharat Bhushan @ 2013-11-06 5:25 UTC (permalink / raw)
To: Dongsheng Wang, Scott Wood; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <ABB05CD9C9F68C46A5CEDC7F15439259010BC83B@039-SN2MPN1-021.039d.mgd.msft.net>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogV2FuZyBEb25nc2hlbmct
QjQwNTM0DQo+IFNlbnQ6IFR1ZXNkYXksIE5vdmVtYmVyIDA1LCAyMDEzIDg6NDAgQU0NCj4gVG86
IFdvb2QgU2NvdHQtQjA3NDIxDQo+IENjOiBCaHVzaGFuIEJoYXJhdC1SNjU3Nzc7IGxpbnV4cHBj
LWRldkBsaXN0cy5vemxhYnMub3JnDQo+IFN1YmplY3Q6IFJFOiBbUEFUQ0ggdjUgNC80XSBwb3dl
cnBjLzg1eHg6IGFkZCBzeXNmcyBmb3IgcHcyMCBzdGF0ZSBhbmQgYWx0aXZlYw0KPiBpZGxlDQo+
IA0KPiANCj4gDQo+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiBGcm9tOiBXb29k
IFNjb3R0LUIwNzQyMQ0KPiA+IFNlbnQ6IFR1ZXNkYXksIE5vdmVtYmVyIDA1LCAyMDEzIDU6NTIg
QU0NCj4gPiBUbzogV2FuZyBEb25nc2hlbmctQjQwNTM0DQo+ID4gQ2M6IFdvb2QgU2NvdHQtQjA3
NDIxOyBCaHVzaGFuIEJoYXJhdC1SNjU3Nzc7IGxpbnV4cHBjLQ0KPiA+IGRldkBsaXN0cy5vemxh
YnMub3JnDQo+ID4gU3ViamVjdDogUmU6IFtQQVRDSCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRk
IHN5c2ZzIGZvciBwdzIwIHN0YXRlIGFuZA0KPiA+IGFsdGl2ZWMgaWRsZQ0KPiA+DQo+ID4gT24g
U3VuLCAyMDEzLTExLTAzIGF0IDIyOjA0IC0wNjAwLCBXYW5nIERvbmdzaGVuZy1CNDA1MzQgd3Jv
dGU6DQo+ID4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+IEZyb206IFdh
bmcgRG9uZ3NoZW5nLUI0MDUzNA0KPiA+ID4gPiBTZW50OiBNb25kYXksIE9jdG9iZXIgMjEsIDIw
MTMgMTE6MTEgQU0NCj4gPiA+ID4gVG86IFdvb2QgU2NvdHQtQjA3NDIxDQo+ID4gPiA+IENjOiBC
aHVzaGFuIEJoYXJhdC1SNjU3Nzc7IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnDQo+ID4g
PiA+IFN1YmplY3Q6IFJFOiBbUEFUQ0ggdjUgNC80XSBwb3dlcnBjLzg1eHg6IGFkZCBzeXNmcyBm
b3IgcHcyMCBzdGF0ZQ0KPiA+ID4gPiBhbmQgYWx0aXZlYyBpZGxlDQo+ID4gPiA+DQo+ID4gPiA+
DQo+ID4gPiA+DQo+ID4gPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+ID4g
PiBGcm9tOiBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4gPiA+IFNlbnQ6IFNhdHVyZGF5LCBPY3Rv
YmVyIDE5LCAyMDEzIDM6MjIgQU0NCj4gPiA+ID4gPiBUbzogV2FuZyBEb25nc2hlbmctQjQwNTM0
DQo+ID4gPiA+ID4gQ2M6IEJodXNoYW4gQmhhcmF0LVI2NTc3NzsgV29vZCBTY290dC1CMDc0MjE7
IGxpbnV4cHBjLQ0KPiA+ID4gPiA+IGRldkBsaXN0cy5vemxhYnMub3JnDQo+ID4gPiA+ID4gU3Vi
amVjdDogUmU6IFtQQVRDSCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRkIHN5c2ZzIGZvciBwdzIw
DQo+ID4gPiA+ID4gc3RhdGUgYW5kIGFsdGl2ZWMgaWRsZQ0KPiA+ID4gPiA+DQo+ID4gPiA+ID4g
T24gVGh1LCAyMDEzLTEwLTE3IGF0IDIyOjAyIC0wNTAwLCBXYW5nIERvbmdzaGVuZy1CNDA1MzQg
d3JvdGU6DQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2Ut
LS0tLQ0KPiA+ID4gPiA+ID4gPiBGcm9tOiBCaHVzaGFuIEJoYXJhdC1SNjU3NzcNCj4gPiA+ID4g
PiA+ID4gU2VudDogVGh1cnNkYXksIE9jdG9iZXIgMTcsIDIwMTMgMjo0NiBQTQ0KPiA+ID4gPiA+
ID4gPiBUbzogV2FuZyBEb25nc2hlbmctQjQwNTM0OyBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4g
PiA+ID4gPiBDYzogbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gPiA+ID4gPiA+ID4g
U3ViamVjdDogUkU6IFtQQVRDSCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRkIHN5c2ZzIGZvciBw
dzIwDQo+ID4gPiA+ID4gPiA+IHN0YXRlIGFuZCBhbHRpdmVjIGlkbGUNCj4gPiA+ID4gPiA+ID4N
Cj4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gLS0tLS1P
cmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gRnJvbTogV2FuZyBEb25n
c2hlbmctQjQwNTM0DQo+ID4gPiA+ID4gPiA+ID4gPiA+IFNlbnQ6IFRodXJzZGF5LCBPY3RvYmVy
IDE3LCAyMDEzIDExOjIyIEFNDQo+ID4gPiA+ID4gPiA+ID4gPiA+IFRvOiBCaHVzaGFuIEJoYXJh
dC1SNjU3Nzc7IFdvb2QgU2NvdHQtQjA3NDIxDQo+ID4gPiA+ID4gPiA+ID4gPiA+IENjOiBsaW51
eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZw0KPiA+ID4gPiA+ID4gPiA+ID4gPiBTdWJqZWN0OiBS
RTogW1BBVENIIHY1IDQvNF0gcG93ZXJwYy84NXh4OiBhZGQgc3lzZnMNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gZm9yDQo+ID4gPiA+ID4gPiA+ID4gPiA+IHB3MjAgc3RhdGUgYW5kIGFsdGl2ZWMgaWRs
ZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4g
PiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0t
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gRnJvbTogQmh1c2hhbiBCaGFyYXQtUjY1Nzc3DQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gU2VudDogVGh1cnNkYXksIE9jdG9iZXIgMTcsIDIwMTMgMTE6MjAg
QU0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBUbzogV2FuZyBEb25nc2hlbmctQjQwNTM0OyBXb29k
IFNjb3R0LUIwNzQyMQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IENjOiBsaW51eHBwYy1kZXZAbGlz
dHMub3psYWJzLm9yZw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFN1YmplY3Q6IFJFOiBbUEFUQ0gg
djUgNC80XSBwb3dlcnBjLzg1eHg6IGFkZCBzeXNmcw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IGZv
cg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IHB3MjAgc3RhdGUgYW5kIGFsdGl2ZWMgaWRsZQ0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0t
LS0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IEZyb206IFdhbmcgRG9uZ3NoZW5nLUI0MDUzNA0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU2VudDogVGh1cnNkYXksIE9jdG9iZXIgMTcsIDIwMTMg
ODoxNiBBTQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gVG86IEJodXNoYW4gQmhhcmF0LVI2NTc3
NzsgV29vZCBTY290dC1CMDc0MjENCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IENjOiBsaW51eHBw
Yy1kZXZAbGlzdHMub3psYWJzLm9yZw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU3ViamVjdDog
UkU6IFtQQVRDSCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRkDQo+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBzeXNmcyBmb3INCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IHB3MjAgc3RhdGUgYW5kIGFs
dGl2ZWMgaWRsZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAt
LS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBGcm9t
OiBCaHVzaGFuIEJoYXJhdC1SNjU3NzcNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU2VudDog
VGh1cnNkYXksIE9jdG9iZXIgMTcsIDIwMTMgMTowMSBBTQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBUbzogV2FuZyBEb25nc2hlbmctQjQwNTM0OyBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiBDYzogbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU3ViamVjdDogUkU6IFtQQVRDSCB2NSA0LzRdIHBvd2Vy
cGMvODV4eDogYWRkDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IHN5c2ZzIGZvcg0KPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiBwdzIwIHN0YXRlIGFuZCBhbHRpdmVjIGlkbGUNCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFs
IE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IEZyb206IFdhbmcgRG9u
Z3NoZW5nLUI0MDUzNA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFNlbnQ6IFR1ZXNkYXks
IE9jdG9iZXIgMTUsIDIwMTMgMjo1MSBQTQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFRv
OiBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IENjOiBCaHVz
aGFuIEJoYXJhdC1SNjU3Nzc7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gbGludXhwcGMt
ZGV2QGxpc3RzLm96bGFicy5vcmc7IFdhbmcNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gRG9u
Z3NoZW5nLUI0MDUzNA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFN1YmplY3Q6IFtQQVRD
SCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRkDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
c3lzZnMgZm9yDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gcHcyMCBzdGF0ZSBhbmQNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gYWx0aXZlYyBpZGxlDQo+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBGcm9tOiBXYW5nIERvbmdzaGVu
Zw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IDxkb25nc2hlbmcud2FuZ0BmcmVlc2NhbGUu
Y29tPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gQWRkIGEgc3lzIGludGVyZmFjZSB0byBlbmFibGUvZGlhYmxlIHB3MjANCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiBzdGF0ZSBvciBhbHRpdmVjIGlkbGUsIGFuZA0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiBjb250cm9sIHRoZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
IHdhaXQgZW50cnkgdGltZS4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+IEVuYWJsZS9EaXNhYmxlIGludGVyZmFjZToNCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiAwLCBkaXNhYmxlLiAxLCBlbmFibGUuDQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gL3N5cy9kZXZpY2VzL3N5c3RlbS9jcHUvY3B1WC9wdzIwX3N0YXRlDQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gL3N5cy9kZXZpY2VzL3N5c3RlbS9jcHUvY3B1WC9hbHRp
dmVjX2lkbGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+IFNldCB3YWl0IHRpbWUgaW50ZXJmYWNlOihOYW5vc2Vjb25kKQ0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+IC9zeXMvZGV2aWNlcy9zeXN0ZW0vY3B1L2NwdVgvcHcyMF93YWl0
X3RpbWUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAvc3lzL2RldmljZXMvc3lzdGVtL2Nw
dS9jcHVYL2FsdGl2ZWNfaWRsZV93YWl0DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gX3QN
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBpbWUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBFeGFtcGxlOiBCYXNlIG9uIFRCZnJlcSBpcyA0MU1IWi4NCj4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiAxfjQ4KG5zKTogVEJbNjNdDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
NDl+OTcobnMpOiBUQls2Ml0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA5OH4xOTUobnMp
OiBUQls2MV0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAxOTZ+MzkwKG5zKTogVEJbNjBd
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gMzkxfjc4MChucyk6IFRCWzU5XQ0KPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+IDc4MX4xNTYwKG5zKTogVEJbNThdIC4uLg0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU2lnbmVkLW9m
Zi1ieTogV2FuZyBEb25nc2hlbmcNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA8ZG9uZ3No
ZW5nLndhbmdAZnJlZXNjYWxlLmNvbT4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAtLS0N
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAqdjU6DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gQ2hhbmdlIGdldF9pZGxlX3RpY2tzX2JpdCBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbi4N
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ICp2NDoNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBNb3ZlIGNvZGUgZnJvbSA4NXh4L2Nv
bW1vbi5jIHRvIGtlcm5lbC9zeXNmcy5jLg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gUmVtb3ZlIGhhc19wdzIwX2FsdGl2ZWNfaWRsZSBm
dW5jdGlvbi4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+IENoYW5nZSB3YWl0ICJlbnRyeV9iaXQiIHRvIHdhaXQgdGltZS4NCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IGRpZmYgLS1n
aXQgYS9hcmNoL3Bvd2VycGMva2VybmVsL3N5c2ZzLmMNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBiL2FyY2gvcG93ZXJwYy9rZXJuZWwvc3lzZnMuYw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBpbmRleA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IDI3YTkwYjkuLjEwZDExMjgg
MTAwNjQ0DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gLS0tIGEvYXJjaC9wb3dlcnBjL2tl
cm5lbC9zeXNmcy5jDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKysrIGIvYXJjaC9wb3dl
cnBjL2tlcm5lbC9zeXNmcy5jDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gQEAgLTg1LDYg
Kzg1LDI4NCBAQA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IF9fc2V0dXAoInNtdC1zbm9v
emUtZGVsYXk9IiwNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gc2V0dXBfc210X3Nub296ZV9k
ZWxheSk7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiAgI2VuZGlmIC8qIENPTkZJR19QUEM2NCAqLw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKyNpZmRlZiBDT05GSUdfRlNMX1NP
Qw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsjZGVmaW5lIE1BWF9CSVQJCQkJNjMNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
K3N0YXRpYyB1NjQgcHcyMF93dDsgc3RhdGljIHU2NA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICthbHRpdmVjX2lkbGVfd3Q7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IGdldF9pZGxlX3Rp
Y2tzX2JpdCh1NjQgbnMpIHsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXU2NCBjeWNs
ZTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gKwlpZiAobnMgPj0gMTAwMDApDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJ
Y3ljbGUgPSBkaXZfdTY0KG5zICsgNTAwLCAxMDAwKSAqDQo+ID4gPiA+ID4gPiA+IHRiX3RpY2tz
X3Blcl91c2VjOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJZWxzZQ0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ICsJCWN5Y2xlID0gZGl2X3U2NChucyAqDQo+ID4gdGJfdGlja3Nf
cGVyX3VzZWMsDQo+ID4gPiA+ID4gMTAwMCk7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
Kw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJaWYgKCFjeWNsZSkNCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiArCQlyZXR1cm4gMDsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwlyZXR1cm4gaWxvZzIoY3ljbGUpOyB9
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICtzdGF0aWMgdm9pZCBkb19zaG93X3B3cm1ndGNyMCh2b2lkICp2YWwpIHsNCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiArCXUzMiAqdmFsdWUgPSB2YWw7DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJKnZhbHVlID0gbWZz
cHIoU1BSTl9QV1JNR1RDUjApOyB9DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtzdGF0aWMgc3NpemVfdCBzaG93X3B3MjBfc3RhdGUo
c3RydWN0IGRldmljZQ0KPiA+ICpkZXYsDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJ
CQlzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZQ0KPiA+ICphdHRyLA0KPiA+ID4gPiA+IGNoYXINCj4g
PiA+ID4gPiA+ID4gKmJ1Zikgew0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdTMyIHZh
bHVlOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdW5zaWduZWQgaW50IGNwdSA9IGRl
di0+aWQ7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ICsJc21wX2NhbGxfZnVuY3Rpb25fc2luZ2xlKGNwdSwNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiArZG9fc2hvd19wd3JtZ3RjcjAsICZ2YWx1ZSwgMSk7DQo+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdmFsdWUg
Jj0gUFdSTUdUQ1IwX1BXMjBfV0FJVDsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwlyZXR1cm4gc3ByaW50ZihidWYsICIldVxuIiwg
dmFsdWUgPyAxIDoNCj4gPiAwKTsgfQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArc3RhdGljIHZvaWQgZG9fc3RvcmVfcHcyMF9zdGF0
ZSh2b2lkICp2YWwpIHsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXUzMiAqdmFsdWUg
PSB2YWw7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwl1MzIgcHcyMF9zdGF0ZTsNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
KwlwdzIwX3N0YXRlID0gbWZzcHIoU1BSTl9QV1JNR1RDUjApOw0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCWlmICgqdmFsdWUpDQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJcHcyMF9zdGF0ZSB8PSBQV1JNR1RDUjBfUFcy
MF9XQUlUOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJZWxzZQ0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ICsJCXB3MjBfc3RhdGUgJj0gflBXUk1HVENSMF9QVzIwX1dBSVQ7DQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ICsJbXRzcHIoU1BSTl9QV1JNR1RDUjAsIHB3MjBfc3RhdGUpOyB9DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtzdGF0aWMgc3NpemVf
dCBzdG9yZV9wdzIwX3N0YXRlKHN0cnVjdCBkZXZpY2UNCj4gPiAqZGV2LA0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ICsJCQkJc3RydWN0IGRldmljZV9hdHRyaWJ1dGUNCj4gPiAqYXR0ciwN
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCQkJCWNvbnN0IGNoYXIgKmJ1Ziwgc2l6ZV90
DQo+ID4gY291bnQpDQo+ID4gPiA+ID4gew0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJ
dTMyIHZhbHVlOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdW5zaWduZWQgaW50IGNw
dSA9IGRldi0+aWQ7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ICsJaWYgKGtzdHJ0b3UzMihidWYsIDAsICZ2YWx1ZSkpDQo+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJaWYgKHZhbHVlID4g
MSkNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwlz
bXBfY2FsbF9mdW5jdGlvbl9zaW5nbGUoY3B1LA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ICtkb19zdG9yZV9wdzIwX3N0YXRlLCAmdmFsdWUsIDEpOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXJldHVybiBjb3VudDsgfQ0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiArc3RhdGljIHNzaXplX3Qgc2hvd19wdzIwX3dhaXRfdGltZShzdHJ1Y3QNCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiArZGV2aWNlDQo+ID4gPiA+ICpkZXYsDQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKwkJCQlzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZQ0KPiA+ICphdHRyLA0KPiA+
ID4gPiA+IGNoYXINCj4gPiA+ID4gPiA+ID4gKmJ1Zikgew0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ICsJdTMyIHZhbHVlOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdTY0IHRi
X2N5Y2xlOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJczY0IHRpbWU7DQo+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdW5z
aWduZWQgaW50IGNwdSA9IGRldi0+aWQ7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJaWYgKCFwdzIwX3d0KSB7DQo+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gKwkJc21wX2NhbGxfZnVuY3Rpb25fc2luZ2xlKGNwdSwNCj4gPiA+
ID4gPiBkb19zaG93X3B3cm1ndGNyMCwNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArJnZh
bHVlLA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IDEpOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICsJCXZhbHVlID0gKHZhbHVlICYNCj4gPiBQV1JNR1RDUjBfUFcyMF9FTlQpID4+DQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+IAlQV1JNR1RDUjBfUFcyMF9FTlRfU0hJRlQ7
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICsJCXRiX2N5Y2xlID0gKDEgPDwgKE1BWF9CSVQgLSB2YWx1ZSkpICoNCj4gPiAyOw0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBJcyB2YWx1
ZSA9IDAgYW5kIHZhbHVlID0gMSBsZWdhbD8gVGhlc2Ugd2lsbA0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiBtYWtlIHRiX2N5Y2xlID0gMCwNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCQl0aW1lID0gZGl2X3U2NCh0Yl9jeWNsZSAqIDEw
MDAsDQo+ID4gPiA+ID4gdGJfdGlja3NfcGVyX3VzZWMpDQo+ID4gPiA+ID4gPiA+IC0gMTsNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gQW5kIHRp
bWUgPSAtMTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+IFBsZWFzZSBsb29rIGF0IHRoZSBlbmQgb2YgdGhlIGZ1bmN0aW9uLCA6KQ0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICJyZXR1cm4gc3ByaW50Zihi
dWYsICIlbGx1XG4iLCB0aW1lID4gMCA/IHRpbWUgOiAwKTsiDQo+ID4gPiA+ID4gPiA+ID4gPiA+
ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBJIGtub3cgeW91IHJldHVybiAwIGlmIHZhbHVlID0g
MC8xLCBteSBxdWVzdGlvbiB3YXMNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiB0aGF0LCBpcyB0aGlz
IGNvcnJlY3QgYXMgcGVyIHNwZWNpZmljYXRpb24/DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiBBaGgsIGFsc28gZm9yICJ2YWx1ZSIgdXB0byA3IHlvdSB3aWxs
IHJldHVybiAwLCBubz8NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4g
PiBJZiB2YWx1ZSA9IDAsIE1BWF9CSVQgLSB2YWx1ZSA9IDYzIHRiX2N5Y2xlID0NCj4gPiA+ID4g
PiA+ID4gPiA+ID4gMHhmZmZmZmZmZl9mZmZmZmZmZiwgdGJfY3ljbGUgKiAxMDAwIHdpbGwgb3Zl
cmZsb3csDQo+ID4gPiA+ID4gPiA+ID4gPiA+IGJ1dCB0aGlzDQo+ID4gPiA+ID4gc2l0dWF0aW9u
IGlzIG5vdCBwb3NzaWJsZS4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gQmVjYXVzZSBpZiB0aGUgInZh
bHVlID0gMCIgbWVhbnMgdGhpcyBmZWF0dXJlIHdpbGwgYmUNCj4gPiA+ID4gImRpc2FibGUiLg0K
PiA+ID4gPiA+ID4gPiA+ID4gPiBOb3cgVGhlIGRlZmF1bHQgd2FpdCBiaXQgaXMgNTAoTUFYX0JJ
VCAtIHZhbHVlLCB2YWx1ZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA9IDEzKSwgdGhlIFBXMjAvQWx0
aXZlYyBJZGxlIHdhaXQgZW50cnkgdGltZSBpcyBhYm91dA0KPiA+ID4gPiA+ID4gPiA+ID4gPiAx
bXMsIHRoaXMgdGltZSBpcyB2ZXJ5IGxvbmcgZm9yIHdhaXQgaWRsZSB0aW1lLCBhbmQNCj4gPiA+
ID4gPiA+ID4gPiA+ID4gaXQncyBjYW5ub3QgYmUgaW5jcmVhc2VkKG1lYW5zIChNQVhfQklUDQo+
ID4gPiA+ID4gPiA+ID4gPiA+IC0gdmFsdWUpDQo+ID4gPiA+ID4gPiA+ID4gPiBjYW5ub3QgZ3Jl
YXRlciB0aGFuIDUwKS4NCj4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiBXaGF0
IHlvdSBzYWlkIGlzIG5vdCBvYnZpb3VzIGZyb20gY29kZSBhbmQgc28gYXQgbGVhc3QNCj4gPiA+
ID4gPiA+ID4gPiA+IHdyaXRlIGEgY29tbWVudCB0aGF0IHZhbHVlIHdpbGwgYmUgYWx3YXlzID49
IDEzIG9yIHZhbHVlDQo+ID4gPiA+ID4gPiA+ID4gPiB3aWxsIG5ldmVyIGJlIGxlc3MgdGhhbiA8
IDggYW5kIGJlbG93IGNhbGN1bGF0aW9uIHdpbGwNCj4gPiA+ID4gPiA+ID4gPiA+IG5vdCBvdmVy
Zmxvdy4gbWF5IGJlIGVycm9yIG91dCBpZiB2YWx1ZSBpcyBsZXNzIHRoYW4gOC4NCj4gPiA+ID4g
PiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gVGhlICJ2YWx1ZSIgbGVzcyB0aGFuIDEwLCB0aGlz
IHdpbGwgb3ZlcmZsb3cuDQo+ID4gPiA+ID4gPiA+ID4gVGhlcmUgaXMgbm90IGVycm9yLCBUaGUg
Y29kZSBJIGtuZXcgaXQgY291bGQgbm90IGJlIGxlc3MNCj4gPiA+ID4gPiA+ID4gPiB0aGFuIDEw
LCB0aGF0J3Mgd2h5IEkgdXNlIHRoZSBmb2xsb3dpbmcgY29kZS4gOikNCj4gPiA+ID4gPiA+ID4N
Cj4gPiA+ID4gPiA+ID4gSSBhbSBzb3JyeSB0byBwZXJzaXN0IGJ1dCB0aGlzIGlzIG5vdCBhYm91
dCB3aGF0IHlvdSBrbm93LA0KPiA+ID4gPiA+ID4gPiB0aGlzIGlzIGFib3V0IGhvdyBjb2RlIGlz
IHJlYWQgYW5kIGNvZGUgZG9lcyBub3Qgc2F5IHdoYXQNCj4gPiA+ID4gPiA+ID4geW91IGtub3cs
IHNvIGFkZCBhIGNvbW1lbnQgYXQgbGVhc3QgYW5kIGVycm9yIG91dC93YXJuIHdoZW4NCj4gPiA+
ID4gPiA+ID4gInZhbHVlIiBpcyBsZXNzIHRoYW4gYQ0KPiA+ID4gPiA+IGNlcnRhaW4gbnVtYmVy
Lg0KPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gU29ycnkgZm9yIHRoZSBsYXRlIHRvIHJlc3Bv
bnNlIHRoZSBtYWlsLiBJZiBpdCBjYXVzZWQNCj4gPiA+ID4gPiA+IGNvbmZ1c2lvbiwgd2UgY2Fu
DQo+ID4gPiA+ID4gYWRkIGEgY29tbWVudC4NCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBIb3cg
YWJvdXQgdGhlIGZvbGxvd2luZyBjb21tZW50Pw0KPiA+ID4gPiA+ID4gLyoNCj4gPiA+ID4gPiA+
ICAqIElmIHRoZSAidmFsdWUiIGxlc3MgdGhhbiAxMCwgdGhpcyB3aWxsIG92ZXJmbG93Lg0KPiA+
ID4gPiA+ID4gICogRnJvbSBiZW5jaG1hcmsgdGVzdCwgdGhlIGRlZmF1bHQgd2FpdCBiaXQgd2ls
bCBub3QgYmUgc2V0DQo+ID4gPiA+ID4gPiBsZXNzIHRoYW4NCj4gPiA+ID4gPiAxMGJpdC4NCj4g
PiA+ID4gPiA+ICAqIEJlY2F1c2UgMTAgYml0IGNvcnJlc3BvbmRzIHRvIHRoZSB3YWl0IGVudHJ5
IHRpbWUgaXMNCj4gPiA+ID4gPiA+IDQzOTM3NTU3MzQwMTk5OTYwOShucyksDQo+ID4gPiA+ID4g
PiAgKiBmb3Igd2FpdC1lbnRyeS1pZGxlIHRpbWUgdGhpcyB2YWx1ZSBsb29rcyB0b28gbG9uZywg
YW5kIHdlDQo+ID4gPiA+ID4gPiBjYW5ub3QgdXNlIHRob3NlDQo+ID4gPiA+ID4gPiAgKiAibG9u
ZyIgdGltZSBhcyBhIGRlZmF1bHQgd2FpdC1lbnRyeSB0aW1lLiBTbyBvdmVyZmxvdyBjb3VsZA0K
PiA+ID4gPiA+ID4gbm90IGhhdmUgaGFwcGVuZWQNCj4gPiA+ID4gPiA+ICAqIGFuZCB3ZSB1c2Ug
dGhpcyBjYWxjdWxhdGlvbiBtZXRob2QgdG8gZ2V0IHdhaXQtZW50cnktaWRsZSB0aW1lLg0KPiA+
ID4gPiA+ID4gICovDQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBJZiB0aGVyZSdzIHRvIGJlIGEgbGlt
aXQgb24gdGhlIHRpbWVzIHdlIGFjY2VwdCwgbWFrZSBpdCBleHBsaWNpdC4NCj4gPiA+ID4gPiBD
aGVjayBmb3IgaXQgYmVmb3JlIGRvaW5nIGFueSBjb252ZXJzaW9ucywgYW5kIHJldHVybiBhbiBl
cnJvcg0KPiA+ID4gPiA+IGlmIHVzZXJzcGFjZSB0cmllcyB0byBzZXQgaXQuDQo+ID4gPiA+ID4N
Cj4gPiA+ID4gVGhlIGJyYW5jaCBvbmx5IHVzZSB0byByZWFkIGRlZmF1bHQgd2FpdC1lbnRyeS10
aW1lLg0KPiA+ID4gPiBXZSBoYXZlIG5vIGxpbWl0IHRoZSB1c2VyJ3MgaW5wdXQsIGFuZCB3ZSBj
YW4ndCByZXN0cmljdC4gT25jZSB0aGUNCj4gPiA+ID4gdXNlciBzZXQgdGhlIHdhaXQtZW50cnkt
dGltZSwgdGhlIGNvZGUgd2lsbCBkbyBhbm90aGVyIGJyYW5jaC4NCj4gPiA+ID4NCj4gPiA+DQo+
ID4gPiBIaSBzY290dCwNCj4gPiA+IERvIHlvdSBoYXZlIGFueSBjb21tZW50cyBhYm91dCB0aGlz
IHBhdGNoPw0KPiA+ID4gSSB3aWxsIGFkZCB0aGUgY29tbWVudCBhbmQgc2VuZCB0aGlzIHBhdGNo
IGFnYWluLg0KPiA+DQo+ID4gV2hhdCBkbyB5b3UgbWVhbiBieSAiYW5kIHdlIGNhbid0IHJlc3Ry
aWN0Ij8gIFdoeSBub3Q/DQo+ID4NCj4gPiBXaHkgaXMgaXQgb25seSB1c2VkIHRvIHJlYWQgdGhl
IGRlZmF1bHQsIGFuZCBub3QgdGhlIGN1cnJlbnQgdmFsdWU/DQo+ID4NCj4gV2UgYWxyZWFkeSBo
YXZlIGEgdmFyaWFibGUgd2hpY2ggdmFsdWUgaXMgc2V0IGJ5IHRoZSB1c2VyLCBhcyB3ZSBoYXZl
IGRpc2N1c3NlZA0KPiBiZWZvcmUuDQo+IA0KPiBXaGVuIHRoZSBzeXN0ZW0gYm9vdC11cC4gQmVm
b3JlIHVzZXIgc2V0IHRoZSB3YWl0LWVudHJ5LXRpbWUsIHdlIG5lZWQgdG8gcmV0dXJuDQo+IGEg
ZGVmYXVsdCB3YWl0LWVudHJ5LXRpbWUsIGlmIHRoZSB1c2VyIHJlYWQgdGhpcyBzeXMtaW50ZXJm
YWNlLiBUaGUgZGVmYXVsdA0KPiB3YWl0LWVudHJ5LXRpbWUgaXMgY29udmVydGVkIGJ5IHdhaXQt
Yml0Lg0KPiANCj4gT25jZSB0aGUgdXNlciBzZXQgdGhlIHN5cy1pbnRlcmZhY2UsIGEgdmFyaWFi
bGUgd2lsbCBiZSB1c2VkIHRvIHNhdmUgaXQuIEFuZA0KPiB3aGVuIHRoZSB1c2VyIHJlYWQgc3lz
LWludGVyZmFjZSB3ZSB3aWxsIHJldHVybiBiYWNrIHRoZSB2YXJpYWJsZS4NCg0KV2hpbGUgd2Ug
YXJlIG5vdCAicmVzdHJpY3RpbmcgdXNlciBkZWZpbmVkIHZhbHVlIiBvciAiZGVmaW5lIHNhbWUg
cmVzdHJpY3Rpb24gZm9yIHVzZXIgZGVmaW5lZCBhbmQgZGVmYXVsdCIsIGNhbiB3ZSBoYXZlIG9u
bHkgb25lIGZsb3cgb2YgY2FsY3VsYXRpb24gYW5kIHNldHRpbmcgcmF0aGVyIHRoYW4gY29uZGl0
aW9uYWwgYmFzZWQgb24gdXNlciBoYXZlIHNldCBvciBub3Qgc2V0PyANCg0KLUJoYXJhdA0KDQo+
IA0KPiAtZG9uZ3NoZW5nDQoNCg==
^ permalink raw reply
* Re: [PATCH 2/3] powerpc/kvm: fix rare but potential deadlock scene
From: Liu ping fan @ 2013-11-06 6:02 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Alexander Graf, kvm-ppc
In-Reply-To: <20131106050418.GD14842@drongo>
On Wed, Nov 6, 2013 at 1:04 PM, Paul Mackerras <paulus@samba.org> wrote:
> On Tue, Nov 05, 2013 at 03:42:43PM +0800, Liu Ping Fan wrote:
>> Since kvmppc_hv_find_lock_hpte() is called from both virtmode and
>> realmode, so it can trigger the deadlock.
>
> Good catch, we should have preemption disabled while ever we have a
> HPTE locked.
>
>> @@ -474,8 +474,10 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
>> }
>>
>> /* Find the HPTE in the hash table */
>> + preempt_disable();
>> index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
>> HPTE_V_VALID | HPTE_V_ABSENT);
>> + preempt_enable();
>
> Which means we need to add the preempt_enable after unlocking the
> HPTE, not here.
>
Yes. Sorry, but I am not sure about whether we can call
preempt_disable/enable() in realmode. I think since thread_info is
allocated with linear address, so we can use preempt_disable/enable()
inside kvmppc_hv_find_lock_hpte(), right?
Thanks and regards,
Pingfan
> Regards,
> Paul.
^ permalink raw reply
* Re: [PATCH] powerpc: memcpy optimization for 64bit LE
From: Michael Neuling @ 2013-11-06 6:22 UTC (permalink / raw)
To: Philippe Bergheaud; +Cc: Linuxppc-dev
In-Reply-To: <1383640732-21449-1-git-send-email-felix@linux.vnet.ibm.com>
Philippe Bergheaud <felix@linux.vnet.ibm.com> wrote:
> Unaligned stores take alignment exceptions on POWER7 running in little-endian.
> This is a dumb little-endian base memcpy that prevents unaligned stores.
> It is replaced by the VMX memcpy at boot.
Is this any faster than the generic version?
Mikey
>
> Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/string.h | 4 ----
> arch/powerpc/kernel/ppc_ksyms.c | 2 --
> arch/powerpc/lib/Makefile | 2 --
> arch/powerpc/lib/memcpy_64.S | 19 +++++++++++++++++++
> 4 files changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h
> index 0dffad6..e40010a 100644
> --- a/arch/powerpc/include/asm/string.h
> +++ b/arch/powerpc/include/asm/string.h
> @@ -10,9 +10,7 @@
> #define __HAVE_ARCH_STRNCMP
> #define __HAVE_ARCH_STRCAT
> #define __HAVE_ARCH_MEMSET
> -#ifdef __BIG_ENDIAN__
> #define __HAVE_ARCH_MEMCPY
> -#endif
> #define __HAVE_ARCH_MEMMOVE
> #define __HAVE_ARCH_MEMCMP
> #define __HAVE_ARCH_MEMCHR
> @@ -24,9 +22,7 @@ extern int strcmp(const char *,const char *);
> extern int strncmp(const char *, const char *, __kernel_size_t);
> extern char * strcat(char *, const char *);
> extern void * memset(void *,int,__kernel_size_t);
> -#ifdef __BIG_ENDIAN__
> extern void * memcpy(void *,const void *,__kernel_size_t);
> -#endif
> extern void * memmove(void *,const void *,__kernel_size_t);
> extern int memcmp(const void *,const void *,__kernel_size_t);
> extern void * memchr(const void *,int,__kernel_size_t);
> diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
> index 526ad5c..0c2dd60 100644
> --- a/arch/powerpc/kernel/ppc_ksyms.c
> +++ b/arch/powerpc/kernel/ppc_ksyms.c
> @@ -147,9 +147,7 @@ EXPORT_SYMBOL(__ucmpdi2);
> #endif
> long long __bswapdi2(long long);
> EXPORT_SYMBOL(__bswapdi2);
> -#ifdef __BIG_ENDIAN__
> EXPORT_SYMBOL(memcpy);
> -#endif
> EXPORT_SYMBOL(memset);
> EXPORT_SYMBOL(memmove);
> EXPORT_SYMBOL(memcmp);
> diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
> index 5310132..6670361 100644
> --- a/arch/powerpc/lib/Makefile
> +++ b/arch/powerpc/lib/Makefile
> @@ -23,9 +23,7 @@ obj-y += checksum_$(CONFIG_WORD_SIZE).o
> obj-$(CONFIG_PPC64) += checksum_wrappers_64.o
> endif
>
> -ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),)
> obj-$(CONFIG_PPC64) += memcpy_power7.o memcpy_64.o
> -endif
>
> obj-$(CONFIG_PPC_EMULATE_SSTEP) += sstep.o ldstfp.o
>
> diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
> index d2bbbc8..358cf74 100644
> --- a/arch/powerpc/lib/memcpy_64.S
> +++ b/arch/powerpc/lib/memcpy_64.S
> @@ -12,10 +12,28 @@
> .align 7
> _GLOBAL(memcpy)
> BEGIN_FTR_SECTION
> +#ifdef __LITTLE_ENDIAN__
> + cmpdi cr7,r5,0 /* dumb little-endian memcpy */
> +#else
> std r3,48(r1) /* save destination pointer for return value */
> +#endif
> FTR_SECTION_ELSE
> b memcpy_power7
> ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
> +#ifdef __LITTLE_ENDIAN__
> + addi r5,r5,-1
> + addi r9,r3,-1
> + add r5,r3,r5
> + subf r5,r9,r5
> + addi r4,r4,-1
> + mtctr r5
> + beqlr cr7
> +1:
> + lbzu r10,1(r4)
> + stbu r10,1(r9)
> + bdnz 1b
> + blr
> +#else
> PPC_MTOCRF(0x01,r5)
> cmpldi cr1,r5,16
> neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
> @@ -201,3 +219,4 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
> stb r0,0(r3)
> 4: ld r3,48(r1) /* return dest pointer */
> blr
> +#endif
> --
> 1.7.10.4
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Re: [PATCH 1/3] powerpc/kvm: simplify the entering logic for secondary thread
From: Liu ping fan @ 2013-11-06 7:26 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Alexander Graf, kvm-ppc
In-Reply-To: <20131106050100.GC14842@drongo>
On Wed, Nov 6, 2013 at 1:01 PM, Paul Mackerras <paulus@samba.org> wrote:
> On Tue, Nov 05, 2013 at 03:42:42PM +0800, Liu Ping Fan wrote:
>> After the primary vcpu changes vcore_state to VCORE_RUNNING, there is
>> very little chance to schedule to secondary vcpu. So if we change the
>
> Why do you say there is very little chance to run the secondary vcpu?
>
>> code sequence around set vcore_state to VCORE_RUNNING and disable
>> preemption, we lost little. But we simplify the entering logi, based on
>> the fact that if primary vcpu runs, the secondary vcpu can not be scheduled.
>
> If a vcpu does a hypercall or something else that requires the host
> (kernel or userspace) to do something, that can happen in the context
> of the vcpu task for that vcpu. That vcpu task can run on another
> core (unless it has been pinned). When it is finished we would like
> the vcpu to continue executing in the guest as soon as possible. The
> code that you remove in this patch enables that to happen without
> having to wait until the other threads exit the guest. So I don't
> think it is a good idea to remove this code.
>
Yes, you are right.
Thanks and regards,
Pingfan
> Regards,
> Paul.
^ permalink raw reply
* [RFC PATCH] ehci-platform: Merge ppc-of EHCI driver into the ehci-platform driver
From: Alistair Popple @ 2013-11-06 7:39 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-usb, Alan Stern
In-Reply-To: <1383710296.4776.119.camel@pasglop>
Currently the ppc-of driver uses the compatibility string
"usb-ehci". This means platforms that use device-tree and implement an
EHCI compatible interface have to either use the ppc-of driver or add
a compatible line to the ehci-platform driver. It would be more
appropriate for the platform driver to be compatible with "usb-ehci"
as non-powerpc platforms are also beginning to utilise device-tree.
This patch merges the device tree property parsing from ehci-ppc-of
into the platform driver and adds a "usb-ehci" compatibility
string. The existing ehci-ppc-of driver is renamed to ehci-440epx as
it contains platform specific work arounds for the 440EPX SoC.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
So I could submit something like this that essentially merges the ppc-of
driver into the platform driver instead of adding the "ibm,akebono-ehci"
compatible line to the platform driver.
However I'm still fairly new to device-tree so I'm not sure what (if any) the
broader impact would be. A quick grep for "usb-ehci" turned up a couple of ARM
device tree's using it however they all provided their own drivers and don't
select CONFIG_USB_EHCI_HCD_PLATFORM so I'm guess they shouldn't be impacted.
I have attempted to fix up any PowerPC device trees/configs, although I wasn't
sure if "usb-ehci" should remain in sequoia.dts or not given that it needs to
use the 440EPX specific driver.
Also this hasn't been tested (beyond compilation) yet.
arch/powerpc/boot/dts/sequoia.dts | 2 +-
arch/powerpc/configs/44x/canyonlands_defconfig | 1 +
drivers/usb/host/Kconfig | 8 +-
drivers/usb/host/ehci-440epx.c | 236
++++++++++++++++++++++++
drivers/usb/host/ehci-hcd.c | 6 +-
drivers/usb/host/ehci-platform.c | 18 +-
drivers/usb/host/ehci-ppc-of.c | 236
------------------------
7 files changed, 261 insertions(+), 246 deletions(-)
create mode 100644 drivers/usb/host/ehci-440epx.c
delete mode 100644 drivers/usb/host/ehci-ppc-of.c
diff --git a/arch/powerpc/boot/dts/sequoia.dts
b/arch/powerpc/boot/dts/sequoia.dts
index b1d3292..e28371e 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -153,7 +153,7 @@
};
USB0: ehci@e0000300 {
- compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+ compatible = "ibm,usb-ehci-440epx";
interrupt-parent = <&UIC0>;
interrupts = <0x1a 0x4>;
reg = <0x00000000 0xe0000300 0x00000090 0x00000000
0xe0000390 0x00000070>;
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig
b/arch/powerpc/configs/44x/canyonlands_defconfig
index d5be93e..16dc37f 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -75,6 +75,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b3f20d7..b8d7c24 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -188,13 +188,13 @@ config USB_EHCI_TEGRA
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
-config USB_EHCI_HCD_PPC_OF
- bool "EHCI support for PPC USB controller on OF platform bus"
- depends on PPC_OF
+config USB_EHCI_HCD_440EPX
+ bool "EHCI support for PPC USB controller on 440EPX"
+ depends on PPC_OF && 440EPX
default y
---help---
Enables support for the USB controller present on the PowerPC
- OpenFirmware platform bus.
+ 440EPX SoC.
config USB_EHCI_SH
bool "EHCI support for SuperH USB controller"
diff --git a/drivers/usb/host/ehci-440epx.c b/drivers/usb/host/ehci-440epx.c
new file mode 100644
index 0000000..4223700
--- /dev/null
+++ b/drivers/usb/host/ehci-440epx.c
@@ -0,0 +1,236 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
+ * Tested on AMCC PPC 440EPx
+ *
+ * Valentine Barshak <vbarshak@ru.mvista.com>
+ *
+ * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
+ * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/err.h>
+#include <linux/signal.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+
+static const struct hc_driver ehci_440epx_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "OF EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_setup,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+#endif
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+
+/*
+ * 440EPx Errata USBH_3
+ * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+ */
+#define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0)
+static int
+ppc44x_enable_bmt(struct device_node *dn)
+{
+ __iomem u32 *insreg_virt;
+
+ insreg_virt = of_iomap(dn, 1);
+ if (!insreg_virt)
+ return -EINVAL;
+
+ out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
+
+ iounmap(insreg_virt);
+ return 0;
+}
+
+
+static int ehci_hcd_440epx_probe(struct platform_device *op)
+{
+ struct device_node *dn = op->dev.of_node;
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci = NULL;
+ struct resource res;
+ int irq;
+ int rv;
+
+ struct device_node *np;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+ rv = of_address_to_resource(dn, 0, &res);
+ if (rv)
+ return rv;
+
+ hcd = usb_create_hcd(&ehci_440epx_hc_driver, &op->dev, "PPC-OF USB");
+ if (!hcd)
+ return -ENOMEM;
+
+ hcd->rsrc_start = res.start;
+ hcd->rsrc_len = resource_size(&res);
+
+ irq = irq_of_parse_and_map(dn, 0);
+ if (irq == NO_IRQ) {
+ printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
+ rv = -EBUSY;
+ goto err_irq;
+ }
+
+ hcd->regs = devm_ioremap_resource(&op->dev, &res);
+ if (IS_ERR(hcd->regs)) {
+ rv = PTR_ERR(hcd->regs);
+ goto err_ioremap;
+ }
+
+ ehci = hcd_to_ehci(hcd);
+ np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
+ if (np != NULL) {
+ /* claim we really affected by usb23 erratum */
+ if (!of_address_to_resource(np, 0, &res))
+ ehci->ohci_hcctrl_reg =
+ devm_ioremap(&op->dev,
+ res.start + OHCI_HCCTRL_OFFSET,
+ OHCI_HCCTRL_LEN);
+ else
+ pr_debug("%s: no ohci offset in fdt\n", __FILE__);
+ if (!ehci->ohci_hcctrl_reg) {
+ pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
+ } else {
+ ehci->has_amcc_usb23 = 1;
+ }
+ }
+
+ if (of_get_property(dn, "big-endian", NULL)) {
+ ehci->big_endian_mmio = 1;
+ ehci->big_endian_desc = 1;
+ }
+ if (of_get_property(dn, "big-endian-regs", NULL))
+ ehci->big_endian_mmio = 1;
+ if (of_get_property(dn, "big-endian-desc", NULL))
+ ehci->big_endian_desc = 1;
+
+ ehci->caps = hcd->regs;
+
+ if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
+ rv = ppc44x_enable_bmt(dn);
+ ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
+ rv ? "NOT ": "");
+ }
+
+ rv = usb_add_hcd(hcd, irq, 0);
+ if (rv)
+ goto err_ioremap;
+
+ return 0;
+
+err_ioremap:
+ irq_dispose_mapping(irq);
+err_irq:
+ usb_put_hcd(hcd);
+
+ return rv;
+}
+
+
+static int ehci_hcd_440epx_remove(struct platform_device *op)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(op);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ struct device_node *np;
+ struct resource res;
+
+ dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+ usb_remove_hcd(hcd);
+
+ irq_dispose_mapping(hcd->irq);
+
+ /* use request_mem_region to test if the ohci driver is loaded. if so
+ * ensure the ohci core is operational.
+ */
+ if (ehci->has_amcc_usb23) {
+ np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
+ if (np != NULL) {
+ if (!of_address_to_resource(np, 0, &res))
+ if (!request_mem_region(res.start,
+ 0x4, hcd_name))
+ set_ohci_hcfs(ehci, 1);
+ else
+ release_mem_region(res.start, 0x4);
+ else
+ pr_debug("%s: no ohci offset in fdt\n", __FILE__);
+ of_node_put(np);
+ }
+ }
+ usb_put_hcd(hcd);
+
+ return 0;
+}
+
+
+static const struct of_device_id ehci_hcd_440epx_match[] = {
+ {
+ .compatible = "ibm,usb-ehci-440epx",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ehci_hcd_440epx_match);
+
+
+static struct platform_driver ehci_hcd_440epx_driver = {
+ .probe = ehci_hcd_440epx_probe,
+ .remove = ehci_hcd_440epx_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "ppc-of-ehci",
+ .owner = THIS_MODULE,
+ .of_match_table = ehci_hcd_440epx_match,
+ },
+};
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 86ab9fd..3b04f25 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1228,9 +1228,9 @@ MODULE_LICENSE ("GPL");
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
#endif
-#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
-#include "ehci-ppc-of.c"
-#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
+#ifdef CONFIG_USB_EHCI_HCD_440EPX
+#include "ehci-440epx.c"
+#define OF_PLATFORM_DRIVER ehci_hcd_440epx_driver
#endif
#ifdef CONFIG_XPS_USB_HCD_XILINX
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-
platform.c
index f6b790c..027f368 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -77,6 +77,7 @@ static int ehci_platform_probe(struct platform_device *dev)
struct usb_hcd *hcd;
struct resource *res_mem;
struct usb_ehci_pdata *pdata;
+ struct device_node *dn = dev->dev.of_node;
int irq;
int err = -ENOMEM;
@@ -96,6 +97,18 @@ static int ehci_platform_probe(struct platform_device *dev)
pdata = dev_get_platdata(&dev->dev);
+ /* Initialise platform data from device tree if available. */
+ if (!dn) {
+ if (of_get_property(dn, "big-endian", NULL)) {
+ pdata->big_endian_mmio = 1;
+ pdata->big_endian_desc = 1;
+ }
+ if (of_get_property(dn, "big-endian-regs", NULL))
+ pdata->big_endian_mmio = 1;
+ if (of_get_property(dn, "big-endian-desc", NULL))
+ pdata->big_endian_desc = 1;
+ }
+
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -203,9 +216,10 @@ static int ehci_platform_resume(struct device *dev)
#define ehci_platform_resume NULL
#endif /* CONFIG_PM */
-static const struct of_device_id vt8500_ehci_ids[] = {
+static const struct of_device_id ehci_platform_ids[] = {
{ .compatible = "via,vt8500-ehci", },
{ .compatible = "wm,prizm-ehci", },
+ { .compatible = "usb-ehci", },
{}
};
@@ -229,7 +243,7 @@ static struct platform_driver ehci_platform_driver = {
.owner = THIS_MODULE,
.name = "ehci-platform",
.pm = &ehci_platform_pm_ops,
- .of_match_table = vt8500_ehci_ids,
+ .of_match_table = ehci_platform_ids,
}
};
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
deleted file mode 100644
index 932293f..0000000
--- a/drivers/usb/host/ehci-ppc-of.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * EHCI HCD (Host Controller Driver) for USB.
- *
- * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
- * Tested on AMCC PPC 440EPx
- *
- * Valentine Barshak <vbarshak@ru.mvista.com>
- *
- * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
- * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/err.h>
-#include <linux/signal.h>
-
-#include <linux/of.h>
-#include <linux/of_platform.h>
-
-
-static const struct hc_driver ehci_ppc_of_hc_driver = {
- .description = hcd_name,
- .product_desc = "OF EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-
-/*
- * 440EPx Errata USBH_3
- * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
- */
-#define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0)
-static int
-ppc44x_enable_bmt(struct device_node *dn)
-{
- __iomem u32 *insreg_virt;
-
- insreg_virt = of_iomap(dn, 1);
- if (!insreg_virt)
- return -EINVAL;
-
- out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
-
- iounmap(insreg_virt);
- return 0;
-}
-
-
-static int ehci_hcd_ppc_of_probe(struct platform_device *op)
-{
- struct device_node *dn = op->dev.of_node;
- struct usb_hcd *hcd;
- struct ehci_hcd *ehci = NULL;
- struct resource res;
- int irq;
- int rv;
-
- struct device_node *np;
-
- if (usb_disabled())
- return -ENODEV;
-
- dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
-
- rv = of_address_to_resource(dn, 0, &res);
- if (rv)
- return rv;
-
- hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
- if (!hcd)
- return -ENOMEM;
-
- hcd->rsrc_start = res.start;
- hcd->rsrc_len = resource_size(&res);
-
- irq = irq_of_parse_and_map(dn, 0);
- if (irq == NO_IRQ) {
- printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
- rv = -EBUSY;
- goto err_irq;
- }
-
- hcd->regs = devm_ioremap_resource(&op->dev, &res);
- if (IS_ERR(hcd->regs)) {
- rv = PTR_ERR(hcd->regs);
- goto err_ioremap;
- }
-
- ehci = hcd_to_ehci(hcd);
- np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
- if (np != NULL) {
- /* claim we really affected by usb23 erratum */
- if (!of_address_to_resource(np, 0, &res))
- ehci->ohci_hcctrl_reg =
- devm_ioremap(&op->dev,
- res.start + OHCI_HCCTRL_OFFSET,
- OHCI_HCCTRL_LEN);
- else
- pr_debug("%s: no ohci offset in fdt\n", __FILE__);
- if (!ehci->ohci_hcctrl_reg) {
- pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
- } else {
- ehci->has_amcc_usb23 = 1;
- }
- }
-
- if (of_get_property(dn, "big-endian", NULL)) {
- ehci->big_endian_mmio = 1;
- ehci->big_endian_desc = 1;
- }
- if (of_get_property(dn, "big-endian-regs", NULL))
- ehci->big_endian_mmio = 1;
- if (of_get_property(dn, "big-endian-desc", NULL))
- ehci->big_endian_desc = 1;
-
- ehci->caps = hcd->regs;
-
- if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
- rv = ppc44x_enable_bmt(dn);
- ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
- rv ? "NOT ": "");
- }
-
- rv = usb_add_hcd(hcd, irq, 0);
- if (rv)
- goto err_ioremap;
-
- return 0;
-
-err_ioremap:
- irq_dispose_mapping(irq);
-err_irq:
- usb_put_hcd(hcd);
-
- return rv;
-}
-
-
-static int ehci_hcd_ppc_of_remove(struct platform_device *op)
-{
- struct usb_hcd *hcd = platform_get_drvdata(op);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
- struct device_node *np;
- struct resource res;
-
- dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
-
- usb_remove_hcd(hcd);
-
- irq_dispose_mapping(hcd->irq);
-
- /* use request_mem_region to test if the ohci driver is loaded. if so
- * ensure the ohci core is operational.
- */
- if (ehci->has_amcc_usb23) {
- np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
- if (np != NULL) {
- if (!of_address_to_resource(np, 0, &res))
- if (!request_mem_region(res.start,
- 0x4, hcd_name))
- set_ohci_hcfs(ehci, 1);
- else
- release_mem_region(res.start, 0x4);
- else
- pr_debug("%s: no ohci offset in fdt\n", __FILE__);
- of_node_put(np);
- }
- }
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-
-static const struct of_device_id ehci_hcd_ppc_of_match[] = {
- {
- .compatible = "usb-ehci",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
-
-
-static struct platform_driver ehci_hcd_ppc_of_driver = {
- .probe = ehci_hcd_ppc_of_probe,
- .remove = ehci_hcd_ppc_of_remove,
- .shutdown = usb_hcd_platform_shutdown,
- .driver = {
- .name = "ppc-of-ehci",
- .owner = THIS_MODULE,
- .of_match_table = ehci_hcd_ppc_of_match,
- },
-};
--
1.7.10.4
^ permalink raw reply related
* RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Dongsheng Wang @ 2013-11-06 7:50 UTC (permalink / raw)
To: Bharat Bhushan, Scott Wood; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <6A3DF150A5B70D4F9B66A25E3F7C888D071E442A@039-SN2MPN1-013.039d.mgd.msft.net>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQmh1c2hhbiBCaGFyYXQt
UjY1Nzc3DQo+IFNlbnQ6IFdlZG5lc2RheSwgTm92ZW1iZXIgMDYsIDIwMTMgMToyNSBQTQ0KPiBU
bzogV2FuZyBEb25nc2hlbmctQjQwNTM0OyBXb29kIFNjb3R0LUIwNzQyMQ0KPiBDYzogbGludXhw
cGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gU3ViamVjdDogUkU6IFtQQVRDSCB2NSA0LzRdIHBv
d2VycGMvODV4eDogYWRkIHN5c2ZzIGZvciBwdzIwIHN0YXRlIGFuZA0KPiBhbHRpdmVjIGlkbGUN
Cj4gDQo+IA0KPiANCj4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+IEZyb206IFdh
bmcgRG9uZ3NoZW5nLUI0MDUzNA0KPiA+IFNlbnQ6IFR1ZXNkYXksIE5vdmVtYmVyIDA1LCAyMDEz
IDg6NDAgQU0NCj4gPiBUbzogV29vZCBTY290dC1CMDc0MjENCj4gPiBDYzogQmh1c2hhbiBCaGFy
YXQtUjY1Nzc3OyBsaW51eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZw0KPiA+IFN1YmplY3Q6IFJF
OiBbUEFUQ0ggdjUgNC80XSBwb3dlcnBjLzg1eHg6IGFkZCBzeXNmcyBmb3IgcHcyMCBzdGF0ZSBh
bmQNCj4gPiBhbHRpdmVjIGlkbGUNCj4gPg0KPiA+DQo+ID4NCj4gPiA+IC0tLS0tT3JpZ2luYWwg
TWVzc2FnZS0tLS0tDQo+ID4gPiBGcm9tOiBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4gU2VudDog
VHVlc2RheSwgTm92ZW1iZXIgMDUsIDIwMTMgNTo1MiBBTQ0KPiA+ID4gVG86IFdhbmcgRG9uZ3No
ZW5nLUI0MDUzNA0KPiA+ID4gQ2M6IFdvb2QgU2NvdHQtQjA3NDIxOyBCaHVzaGFuIEJoYXJhdC1S
NjU3Nzc7IGxpbnV4cHBjLQ0KPiA+ID4gZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gPiA+IFN1Ympl
Y3Q6IFJlOiBbUEFUQ0ggdjUgNC80XSBwb3dlcnBjLzg1eHg6IGFkZCBzeXNmcyBmb3IgcHcyMCBz
dGF0ZQ0KPiA+ID4gYW5kIGFsdGl2ZWMgaWRsZQ0KPiA+ID4NCj4gPiA+IE9uIFN1biwgMjAxMy0x
MS0wMyBhdCAyMjowNCAtMDYwMCwgV2FuZyBEb25nc2hlbmctQjQwNTM0IHdyb3RlOg0KPiA+ID4g
PiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+ID4gRnJvbTogV2FuZyBEb25n
c2hlbmctQjQwNTM0DQo+ID4gPiA+ID4gU2VudDogTW9uZGF5LCBPY3RvYmVyIDIxLCAyMDEzIDEx
OjExIEFNDQo+ID4gPiA+ID4gVG86IFdvb2QgU2NvdHQtQjA3NDIxDQo+ID4gPiA+ID4gQ2M6IEJo
dXNoYW4gQmhhcmF0LVI2NTc3NzsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gPiA+
ID4gPiBTdWJqZWN0OiBSRTogW1BBVENIIHY1IDQvNF0gcG93ZXJwYy84NXh4OiBhZGQgc3lzZnMg
Zm9yIHB3MjANCj4gPiA+ID4gPiBzdGF0ZSBhbmQgYWx0aXZlYyBpZGxlDQo+ID4gPiA+ID4NCj4g
PiA+ID4gPg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0t
LQ0KPiA+ID4gPiA+ID4gRnJvbTogV29vZCBTY290dC1CMDc0MjENCj4gPiA+ID4gPiA+IFNlbnQ6
IFNhdHVyZGF5LCBPY3RvYmVyIDE5LCAyMDEzIDM6MjIgQU0NCj4gPiA+ID4gPiA+IFRvOiBXYW5n
IERvbmdzaGVuZy1CNDA1MzQNCj4gPiA+ID4gPiA+IENjOiBCaHVzaGFuIEJoYXJhdC1SNjU3Nzc7
IFdvb2QgU2NvdHQtQjA3NDIxOyBsaW51eHBwYy0NCj4gPiA+ID4gPiA+IGRldkBsaXN0cy5vemxh
YnMub3JnDQo+ID4gPiA+ID4gPiBTdWJqZWN0OiBSZTogW1BBVENIIHY1IDQvNF0gcG93ZXJwYy84
NXh4OiBhZGQgc3lzZnMgZm9yIHB3MjANCj4gPiA+ID4gPiA+IHN0YXRlIGFuZCBhbHRpdmVjIGlk
bGUNCj4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiBPbiBUaHUsIDIwMTMtMTAtMTcgYXQgMjI6MDIg
LTA1MDAsIFdhbmcgRG9uZ3NoZW5nLUI0MDUzNCB3cm90ZToNCj4gPiA+ID4gPiA+ID4NCj4gPiA+
ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+IEZy
b206IEJodXNoYW4gQmhhcmF0LVI2NTc3Nw0KPiA+ID4gPiA+ID4gPiA+IFNlbnQ6IFRodXJzZGF5
LCBPY3RvYmVyIDE3LCAyMDEzIDI6NDYgUE0NCj4gPiA+ID4gPiA+ID4gPiBUbzogV2FuZyBEb25n
c2hlbmctQjQwNTM0OyBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4gPiA+ID4gPiA+IENjOiBsaW51
eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZw0KPiA+ID4gPiA+ID4gPiA+IFN1YmplY3Q6IFJFOiBb
UEFUQ0ggdjUgNC80XSBwb3dlcnBjLzg1eHg6IGFkZCBzeXNmcyBmb3INCj4gPiA+ID4gPiA+ID4g
PiBwdzIwIHN0YXRlIGFuZCBhbHRpdmVjIGlkbGUNCj4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+
ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiAtLS0tLU9yaWdp
bmFsIE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IEZyb206IFdhbmcgRG9uZ3No
ZW5nLUI0MDUzNA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFNlbnQ6IFRodXJzZGF5LCBPY3RvYmVy
IDE3LCAyMDEzIDExOjIyIEFNDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gVG86IEJodXNoYW4gQmhh
cmF0LVI2NTc3NzsgV29vZCBTY290dC1CMDc0MjENCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBDYzog
bGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBTdWJq
ZWN0OiBSRTogW1BBVENIIHY1IDQvNF0gcG93ZXJwYy84NXh4OiBhZGQgc3lzZnMNCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiBmb3INCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBwdzIwIHN0YXRlIGFuZCBh
bHRpdmVjIGlkbGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IC0tLS0tT3Jp
Z2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBGcm9tOiBCaHVzaGFu
IEJoYXJhdC1SNjU3NzcNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFNlbnQ6IFRodXJzZGF5LCBP
Y3RvYmVyIDE3LCAyMDEzIDExOjIwIEFNDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBUbzogV2Fu
ZyBEb25nc2hlbmctQjQwNTM0OyBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gQ2M6IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnDQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiBTdWJqZWN0OiBSRTogW1BBVENIIHY1IDQvNF0gcG93ZXJwYy84NXh4OiBhZGQNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+IHN5c2ZzIGZvcg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
cHcyMCBzdGF0ZSBhbmQgYWx0aXZlYyBpZGxlDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+IEZyb206IFdhbmcgRG9uZ3NoZW5nLUI0MDUzNA0KPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiBTZW50OiBUaHVyc2RheSwgT2N0b2JlciAxNywgMjAxMyA4OjE2IEFNDQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+IFRvOiBCaHVzaGFuIEJoYXJhdC1SNjU3Nzc7IFdvb2QgU2Nv
dHQtQjA3NDIxDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IENjOiBsaW51eHBwYy1kZXZAbGlz
dHMub3psYWJzLm9yZw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBTdWJqZWN0OiBSRTogW1BB
VENIIHY1IDQvNF0gcG93ZXJwYy84NXh4OiBhZGQNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
c3lzZnMgZm9yDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IHB3MjAgc3RhdGUgYW5kIGFsdGl2
ZWMgaWRsZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gRnJvbTogQmh1c2hhbiBCaGFyYXQtUjY1Nzc3DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gU2VudDogVGh1cnNkYXksIE9jdG9iZXIgMTcsIDIwMTMgMTowMSBBTQ0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+IFRvOiBXYW5nIERvbmdzaGVuZy1CNDA1MzQ7IFdvb2QgU2NvdHQtQjA3
NDIxDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gQ2M6IGxpbnV4cHBjLWRldkBsaXN0cy5v
emxhYnMub3JnDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU3ViamVjdDogUkU6IFtQQVRD
SCB2NSA0LzRdIHBvd2VycGMvODV4eDogYWRkDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
c3lzZnMgZm9yDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gcHcyMCBzdGF0ZSBhbmQgYWx0
aXZlYyBpZGxlDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gRnJvbTogV2FuZyBEb25nc2hlbmctQjQwNTM0DQo+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiBTZW50OiBUdWVzZGF5LCBPY3RvYmVyIDE1LCAyMDEzIDI6NTEgUE0N
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IFRvOiBXb29kIFNjb3R0LUIwNzQyMQ0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gQ2M6IEJodXNoYW4gQmhhcmF0LVI2NTc3NzsNCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3Jn
OyBXYW5nDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gRG9uZ3NoZW5nLUI0MDUzNA0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU3ViamVjdDogW1BBVENIIHY1IDQvNF0gcG93ZXJw
Yy84NXh4OiBhZGQNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IHN5c2ZzIGZvcg0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gcHcyMCBzdGF0ZSBhbmQNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiBhbHRpdmVjIGlkbGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBGcm9tOiBXYW5nIERvbmdzaGVuZw0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPGRvbmdzaGVuZy53YW5nQGZyZWVzY2FsZS5jb20+
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gQWRkIGEgc3lzIGludGVyZmFjZSB0byBlbmFibGUvZGlhYmxlIHB3MjANCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+IHN0YXRlIG9yIGFsdGl2ZWMgaWRsZSwgYW5kDQo+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gY29udHJvbCB0aGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+IHdhaXQgZW50cnkgdGltZS4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBFbmFibGUvRGlzYWJsZSBpbnRlcmZhY2U6DQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAwLCBkaXNhYmxlLiAxLCBlbmFibGUuDQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAvc3lzL2RldmljZXMvc3lzdGVtL2NwdS9jcHVYL3B3
MjBfc3RhdGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IC9zeXMvZGV2aWNlcy9zeXN0
ZW0vY3B1L2NwdVgvYWx0aXZlY19pZGxlDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gU2V0IHdhaXQgdGltZSBpbnRlcmZhY2U6KE5h
bm9zZWNvbmQpDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAvc3lzL2RldmljZXMvc3lz
dGVtL2NwdS9jcHVYL3B3MjBfd2FpdF90aW1lDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiAvc3lzL2RldmljZXMvc3lzdGVtL2NwdS9jcHVYL2FsdGl2ZWNfaWRsZV93YQ0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gaXQNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IF90
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBpbWUNCj4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+IEV4YW1wbGU6IEJhc2Ugb24gVEJmcmVxIGlzIDQxTUhaLg0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gMX40OChucyk6IFRCWzYzXQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gNDl+OTcobnMpOiBUQls2Ml0NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
IDk4fjE5NShucyk6IFRCWzYxXQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gMTk2fjM5
MChucyk6IFRCWzYwXQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gMzkxfjc4MChucyk6
IFRCWzU5XQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gNzgxfjE1NjAobnMpOiBUQls1
OF0gLi4uDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gU2lnbmVkLW9mZi1ieTogV2FuZyBEb25nc2hlbmcNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+IDxkb25nc2hlbmcud2FuZ0BmcmVlc2NhbGUuY29tPg0KPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gLS0tDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAq
djU6DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBDaGFuZ2UgZ2V0X2lkbGVfdGlja3Nf
Yml0IGZ1bmN0aW9uDQo+IGltcGxlbWVudGF0aW9uLg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICp2NDoNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+IE1vdmUgY29kZSBmcm9tIDg1eHgvY29tbW9uLmMgdG8NCj4ga2VybmVs
L3N5c2ZzLmMuDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gUmVtb3ZlIGhhc19wdzIwX2FsdGl2ZWNfaWRsZSBmdW5jdGlvbi4NCj4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiBDaGFuZ2Ugd2FpdCAiZW50cnlfYml0IiB0byB3YWl0IHRpbWUuDQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gZGlmZiAtLWdpdCBh
L2FyY2gvcG93ZXJwYy9rZXJuZWwvc3lzZnMuYw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gYi9hcmNoL3Bvd2VycGMva2VybmVsL3N5c2ZzLmMNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiBpbmRleA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gMjdhOTBiOS4uMTBkMTEy
OCAxMDA2NDQNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+IC0tLSBhL2FyY2gvcG93ZXJw
Yy9rZXJuZWwvc3lzZnMuYw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKysrIGIvYXJj
aC9wb3dlcnBjL2tlcm5lbC9zeXNmcy5jDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBA
QCAtODUsNiArODUsMjg0IEBADQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBfX3NldHVw
KCJzbXQtc25vb3plLWRlbGF5PSIsDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gc2V0dXBf
c210X3Nub296ZV9kZWxheSk7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPg0KPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gICNlbmRpZiAvKiBDT05GSUdfUFBDNjQgKi8NCj4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAr
I2lmZGVmIENPTkZJR19GU0xfU09DDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArI2Rl
ZmluZSBNQVhfQklUCQkJCTYzDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArc3RhdGljIHU2NCBwdzIwX3d0OyBzdGF0aWMgdTY0
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArYWx0aXZlY19pZGxlX3d0Ow0KPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
K3N0YXRpYyB1bnNpZ25lZCBpbnQgZ2V0X2lkbGVfdGlja3NfYml0KHU2NA0KPiBucykgew0KPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwl1NjQgY3ljbGU7DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCWlmIChucyA+
PSAxMDAwMCkNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJCWN5Y2xlID0gZGl2X3U2
NChucyArIDUwMCwgMTAwMCkgKg0KPiA+ID4gPiA+ID4gPiA+IHRiX3RpY2tzX3Blcl91c2VjOw0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwllbHNlDQo+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiArCQljeWNsZSA9IGRpdl91NjQobnMgKg0KPiA+ID4gdGJfdGlja3NfcGVyX3Vz
ZWMsDQo+ID4gPiA+ID4gPiAxMDAwKTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsN
Cj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJaWYgKCFjeWNsZSkNCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ICsJCXJldHVybiAwOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwlyZXR1cm4gaWxvZzIoY3lj
bGUpOyB9DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiArc3RhdGljIHZvaWQgZG9fc2hvd19wd3JtZ3RjcjAodm9pZCAqdmFsKSB7
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXUzMiAqdmFsdWUgPSB2YWw7DQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiArCSp2YWx1ZSA9IG1mc3ByKFNQUk5fUFdSTUdUQ1IwKTsgfQ0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gK3N0YXRpYyBzc2l6
ZV90IHNob3dfcHcyMF9zdGF0ZShzdHJ1Y3QNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ICtkZXZpY2UNCj4gPiA+ICpkZXYsDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCQkJ
CXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlDQo+ID4gPiAqYXR0ciwNCj4gPiA+ID4gPiA+IGNoYXIN
Cj4gPiA+ID4gPiA+ID4gPiAqYnVmKSB7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAr
CXUzMiB2YWx1ZTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJdW5zaWduZWQgaW50
IGNwdSA9IGRldi0+aWQ7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXNtcF9jYWxsX2Z1bmN0aW9uX3NpbmdsZShjcHUsDQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArZG9fc2hvd19wd3JtZ3RjcjAsICZ2YWx1ZSwg
MSk7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiArCXZhbHVlICY9IFBXUk1HVENSMF9QVzIwX1dBSVQ7DQo+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXJldHVy
biBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB2YWx1ZSA/IDEgOg0KPiA+ID4gMCk7IH0NCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtz
dGF0aWMgdm9pZCBkb19zdG9yZV9wdzIwX3N0YXRlKHZvaWQgKnZhbCkgew0KPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gKwl1MzIgKnZhbHVlID0gdmFsOw0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKwl1MzIgcHcyMF9zdGF0ZTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJcHcyMF9zdGF0ZSA9IG1mc3By
KFNQUk5fUFdSTUdUQ1IwKTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJaWYgKCp2YWx1ZSkNCj4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ICsJCXB3MjBfc3RhdGUgfD0gUFdSTUdUQ1IwX1BXMjBfV0FJVDsNCj4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJZWxzZQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gKwkJcHcyMF9zdGF0ZSAmPSB+UFdSTUdUQ1IwX1BXMjBfV0FJVDsNCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJbXRz
cHIoU1BSTl9QV1JNR1RDUjAsIHB3MjBfc3RhdGUpOyB9DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArc3RhdGljIHNzaXplX3Qg
c3RvcmVfcHcyMF9zdGF0ZShzdHJ1Y3QNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtk
ZXZpY2UNCj4gPiA+ICpkZXYsDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCQkJCXN0
cnVjdCBkZXZpY2VfYXR0cmlidXRlDQo+ID4gPiAqYXR0ciwNCj4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ICsJCQkJY29uc3QgY2hhciAqYnVmLCBzaXplX3QNCj4gPiA+IGNvdW50KQ0KPiA+
ID4gPiA+ID4gew0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwl1MzIgdmFsdWU7DQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXVuc2lnbmVkIGludCBjcHUgPSBkZXYtPmlk
Ow0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMCwgJnZhbHVlKSkNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwlpZiAodmFsdWUgPiAx
KQ0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiArCXNtcF9jYWxsX2Z1bmN0aW9uX3NpbmdsZShjcHUsDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiArZG9fc3RvcmVfcHcyMF9zdGF0ZSwgJnZhbHVlLCAxKTsNCj4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJcmV0dXJu
IGNvdW50OyB9DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiArc3RhdGljIHNzaXplX3Qgc2hvd19wdzIwX3dhaXRfdGltZShzdHJ1
Y3QNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICtkZXZpY2UNCj4gPiA+ID4gPiAqZGV2
LA0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJCQlzdHJ1Y3QgZGV2aWNlX2F0dHJp
YnV0ZQ0KPiA+ID4gKmF0dHIsDQo+ID4gPiA+ID4gPiBjaGFyDQo+ID4gPiA+ID4gPiA+ID4gKmJ1
Zikgew0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwl1MzIgdmFsdWU7DQo+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXU2NCB0Yl9jeWNsZTsNCj4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ICsJczY0IHRpbWU7DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiAr
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArCXVuc2lnbmVkIGludCBjcHUgPSBkZXYt
PmlkOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gKwlpZiAoIXB3MjBfd3QpIHsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ICsJCXNtcF9jYWxsX2Z1bmN0aW9uX3NpbmdsZShjcHUsDQo+ID4gPiA+ID4gPiBkb19zaG93
X3B3cm1ndGNyMCwNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsmdmFsdWUsDQo+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiAxKTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsJ
CXZhbHVlID0gKHZhbHVlICYNCj4gPiA+IFBXUk1HVENSMF9QVzIwX0VOVCkgPj4NCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ICsNCj4gPiA+IAlQV1JNR1RDUjBfUFcyMF9FTlRfU0hJRlQ7
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiArDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiArCQl0Yl9jeWNsZSA9ICgxIDw8IChNQVhfQklUIC0gdmFsdWUpKSAqDQo+ID4gPiAy
Ow0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gSXMgdmFsdWUgPSAwIGFuZCB2YWx1ZSA9IDEgbGVnYWw/IFRoZXNlIHdpbGwNCj4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gPiBtYWtlIHRiX2N5Y2xlID0gMCwNCj4gPiA+ID4gPiA+ID4gPiA+
ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gKwkJdGltZSA9IGRpdl91
NjQodGJfY3ljbGUgKiAxMDAwLA0KPiA+ID4gPiA+ID4gdGJfdGlja3NfcGVyX3VzZWMpDQo+ID4g
PiA+ID4gPiA+ID4gLSAxOw0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4g
PiA+ID4gPiA+ID4gPiA+ID4gQW5kIHRpbWUgPSAtMTsNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+
ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gPiBQbGVhc2UgbG9vayBhdCB0aGUgZW5kIG9m
IHRoZSBmdW5jdGlvbiwgOikNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4NCj4gPiA+ID4gPiA+
ID4gPiA+ID4gPiA+ID4gInJldHVybiBzcHJpbnRmKGJ1ZiwgIiVsbHVcbiIsIHRpbWUgPiAwID8g
dGltZSA6DQo+IDApOyINCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiBJIGtub3cgeW91IHJldHVybiAwIGlmIHZhbHVlID0gMC8xLCBteSBxdWVzdGlvbg0K
PiA+ID4gPiA+ID4gPiA+ID4gPiA+ID4gd2FzIHRoYXQsIGlzIHRoaXMgY29ycmVjdCBhcyBwZXIg
c3BlY2lmaWNhdGlvbj8NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gPiBBaGgsIGFsc28gZm9yICJ2YWx1ZSIgdXB0byA3IHlvdSB3aWxsIHJldHVybiAwLCBu
bz8NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gSWYgdmFs
dWUgPSAwLCBNQVhfQklUIC0gdmFsdWUgPSA2MyB0Yl9jeWNsZSA9DQo+ID4gPiA+ID4gPiA+ID4g
PiA+ID4gMHhmZmZmZmZmZl9mZmZmZmZmZiwgdGJfY3ljbGUgKiAxMDAwIHdpbGwgb3ZlcmZsb3cs
DQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gYnV0IHRoaXMNCj4gPiA+ID4gPiA+IHNpdHVhdGlvbiBp
cyBub3QgcG9zc2libGUuDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gQmVjYXVzZSBpZiB0aGUgInZh
bHVlID0gMCIgbWVhbnMgdGhpcyBmZWF0dXJlIHdpbGwNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBi
ZQ0KPiA+ID4gPiA+ICJkaXNhYmxlIi4NCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiBOb3cgVGhlIGRl
ZmF1bHQgd2FpdCBiaXQgaXMgNTAoTUFYX0JJVCAtIHZhbHVlLA0KPiA+ID4gPiA+ID4gPiA+ID4g
PiA+IHZhbHVlID0gMTMpLCB0aGUgUFcyMC9BbHRpdmVjIElkbGUgd2FpdCBlbnRyeSB0aW1lDQo+
ID4gPiA+ID4gPiA+ID4gPiA+ID4gaXMgYWJvdXQgMW1zLCB0aGlzIHRpbWUgaXMgdmVyeSBsb25n
IGZvciB3YWl0IGlkbGUNCj4gPiA+ID4gPiA+ID4gPiA+ID4gPiB0aW1lLCBhbmQgaXQncyBjYW5u
b3QgYmUgaW5jcmVhc2VkKG1lYW5zIChNQVhfQklUDQo+ID4gPiA+ID4gPiA+ID4gPiA+ID4gLSB2
YWx1ZSkNCj4gPiA+ID4gPiA+ID4gPiA+ID4gY2Fubm90IGdyZWF0ZXIgdGhhbiA1MCkuDQo+ID4g
PiA+ID4gPiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+ID4gPiA+IFdoYXQgeW91IHNhaWQgaXMgbm90
IG9idmlvdXMgZnJvbSBjb2RlIGFuZCBzbyBhdCBsZWFzdA0KPiA+ID4gPiA+ID4gPiA+ID4gPiB3
cml0ZSBhIGNvbW1lbnQgdGhhdCB2YWx1ZSB3aWxsIGJlIGFsd2F5cyA+PSAxMyBvcg0KPiA+ID4g
PiA+ID4gPiA+ID4gPiB2YWx1ZSB3aWxsIG5ldmVyIGJlIGxlc3MgdGhhbiA8IDggYW5kIGJlbG93
DQo+ID4gPiA+ID4gPiA+ID4gPiA+IGNhbGN1bGF0aW9uIHdpbGwgbm90IG92ZXJmbG93LiBtYXkg
YmUgZXJyb3Igb3V0IGlmDQo+IHZhbHVlIGlzIGxlc3MgdGhhbiA4Lg0KPiA+ID4gPiA+ID4gPiA+
ID4gPg0KPiA+ID4gPiA+ID4gPiA+ID4gVGhlICJ2YWx1ZSIgbGVzcyB0aGFuIDEwLCB0aGlzIHdp
bGwgb3ZlcmZsb3cuDQo+ID4gPiA+ID4gPiA+ID4gPiBUaGVyZSBpcyBub3QgZXJyb3IsIFRoZSBj
b2RlIEkga25ldyBpdCBjb3VsZCBub3QgYmUgbGVzcw0KPiA+ID4gPiA+ID4gPiA+ID4gdGhhbiAx
MCwgdGhhdCdzIHdoeSBJIHVzZSB0aGUgZm9sbG93aW5nIGNvZGUuIDopDQo+ID4gPiA+ID4gPiA+
ID4NCj4gPiA+ID4gPiA+ID4gPiBJIGFtIHNvcnJ5IHRvIHBlcnNpc3QgYnV0IHRoaXMgaXMgbm90
IGFib3V0IHdoYXQgeW91IGtub3csDQo+ID4gPiA+ID4gPiA+ID4gdGhpcyBpcyBhYm91dCBob3cg
Y29kZSBpcyByZWFkIGFuZCBjb2RlIGRvZXMgbm90IHNheSB3aGF0DQo+ID4gPiA+ID4gPiA+ID4g
eW91IGtub3csIHNvIGFkZCBhIGNvbW1lbnQgYXQgbGVhc3QgYW5kIGVycm9yIG91dC93YXJuDQo+
ID4gPiA+ID4gPiA+ID4gd2hlbiAidmFsdWUiIGlzIGxlc3MgdGhhbiBhDQo+ID4gPiA+ID4gPiBj
ZXJ0YWluIG51bWJlci4NCj4gPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiBTb3JyeSBmb3Ig
dGhlIGxhdGUgdG8gcmVzcG9uc2UgdGhlIG1haWwuIElmIGl0IGNhdXNlZA0KPiA+ID4gPiA+ID4g
PiBjb25mdXNpb24sIHdlIGNhbg0KPiA+ID4gPiA+ID4gYWRkIGEgY29tbWVudC4NCj4gPiA+ID4g
PiA+ID4NCj4gPiA+ID4gPiA+ID4gSG93IGFib3V0IHRoZSBmb2xsb3dpbmcgY29tbWVudD8NCj4g
PiA+ID4gPiA+ID4gLyoNCj4gPiA+ID4gPiA+ID4gICogSWYgdGhlICJ2YWx1ZSIgbGVzcyB0aGFu
IDEwLCB0aGlzIHdpbGwgb3ZlcmZsb3cuDQo+ID4gPiA+ID4gPiA+ICAqIEZyb20gYmVuY2htYXJr
IHRlc3QsIHRoZSBkZWZhdWx0IHdhaXQgYml0IHdpbGwgbm90IGJlIHNldA0KPiA+ID4gPiA+ID4g
PiBsZXNzIHRoYW4NCj4gPiA+ID4gPiA+IDEwYml0Lg0KPiA+ID4gPiA+ID4gPiAgKiBCZWNhdXNl
IDEwIGJpdCBjb3JyZXNwb25kcyB0byB0aGUgd2FpdCBlbnRyeSB0aW1lIGlzDQo+ID4gPiA+ID4g
PiA+IDQzOTM3NTU3MzQwMTk5OTYwOShucyksDQo+ID4gPiA+ID4gPiA+ICAqIGZvciB3YWl0LWVu
dHJ5LWlkbGUgdGltZSB0aGlzIHZhbHVlIGxvb2tzIHRvbyBsb25nLCBhbmQNCj4gPiA+ID4gPiA+
ID4gd2UgY2Fubm90IHVzZSB0aG9zZQ0KPiA+ID4gPiA+ID4gPiAgKiAibG9uZyIgdGltZSBhcyBh
IGRlZmF1bHQgd2FpdC1lbnRyeSB0aW1lLiBTbyBvdmVyZmxvdw0KPiA+ID4gPiA+ID4gPiBjb3Vs
ZCBub3QgaGF2ZSBoYXBwZW5lZA0KPiA+ID4gPiA+ID4gPiAgKiBhbmQgd2UgdXNlIHRoaXMgY2Fs
Y3VsYXRpb24gbWV0aG9kIHRvIGdldCB3YWl0LWVudHJ5LWlkbGUNCj4gdGltZS4NCj4gPiA+ID4g
PiA+ID4gICovDQo+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gSWYgdGhlcmUncyB0byBiZSBhIGxp
bWl0IG9uIHRoZSB0aW1lcyB3ZSBhY2NlcHQsIG1ha2UgaXQNCj4gZXhwbGljaXQuDQo+ID4gPiA+
ID4gPiBDaGVjayBmb3IgaXQgYmVmb3JlIGRvaW5nIGFueSBjb252ZXJzaW9ucywgYW5kIHJldHVy
biBhbiBlcnJvcg0KPiA+ID4gPiA+ID4gaWYgdXNlcnNwYWNlIHRyaWVzIHRvIHNldCBpdC4NCj4g
PiA+ID4gPiA+DQo+ID4gPiA+ID4gVGhlIGJyYW5jaCBvbmx5IHVzZSB0byByZWFkIGRlZmF1bHQg
d2FpdC1lbnRyeS10aW1lLg0KPiA+ID4gPiA+IFdlIGhhdmUgbm8gbGltaXQgdGhlIHVzZXIncyBp
bnB1dCwgYW5kIHdlIGNhbid0IHJlc3RyaWN0LiBPbmNlDQo+ID4gPiA+ID4gdGhlIHVzZXIgc2V0
IHRoZSB3YWl0LWVudHJ5LXRpbWUsIHRoZSBjb2RlIHdpbGwgZG8gYW5vdGhlciBicmFuY2guDQo+
ID4gPiA+ID4NCj4gPiA+ID4NCj4gPiA+ID4gSGkgc2NvdHQsDQo+ID4gPiA+IERvIHlvdSBoYXZl
IGFueSBjb21tZW50cyBhYm91dCB0aGlzIHBhdGNoPw0KPiA+ID4gPiBJIHdpbGwgYWRkIHRoZSBj
b21tZW50IGFuZCBzZW5kIHRoaXMgcGF0Y2ggYWdhaW4uDQo+ID4gPg0KPiA+ID4gV2hhdCBkbyB5
b3UgbWVhbiBieSAiYW5kIHdlIGNhbid0IHJlc3RyaWN0Ij8gIFdoeSBub3Q/DQo+ID4gPg0KPiA+
ID4gV2h5IGlzIGl0IG9ubHkgdXNlZCB0byByZWFkIHRoZSBkZWZhdWx0LCBhbmQgbm90IHRoZSBj
dXJyZW50IHZhbHVlPw0KPiA+ID4NCj4gPiBXZSBhbHJlYWR5IGhhdmUgYSB2YXJpYWJsZSB3aGlj
aCB2YWx1ZSBpcyBzZXQgYnkgdGhlIHVzZXIsIGFzIHdlIGhhdmUNCj4gPiBkaXNjdXNzZWQgYmVm
b3JlLg0KPiA+DQo+ID4gV2hlbiB0aGUgc3lzdGVtIGJvb3QtdXAuIEJlZm9yZSB1c2VyIHNldCB0
aGUgd2FpdC1lbnRyeS10aW1lLCB3ZSBuZWVkDQo+ID4gdG8gcmV0dXJuIGEgZGVmYXVsdCB3YWl0
LWVudHJ5LXRpbWUsIGlmIHRoZSB1c2VyIHJlYWQgdGhpcw0KPiA+IHN5cy1pbnRlcmZhY2UuIFRo
ZSBkZWZhdWx0IHdhaXQtZW50cnktdGltZSBpcyBjb252ZXJ0ZWQgYnkgd2FpdC1iaXQuDQo+ID4N
Cj4gPiBPbmNlIHRoZSB1c2VyIHNldCB0aGUgc3lzLWludGVyZmFjZSwgYSB2YXJpYWJsZSB3aWxs
IGJlIHVzZWQgdG8gc2F2ZQ0KPiA+IGl0LiBBbmQgd2hlbiB0aGUgdXNlciByZWFkIHN5cy1pbnRl
cmZhY2Ugd2Ugd2lsbCByZXR1cm4gYmFjayB0aGUNCj4gdmFyaWFibGUuDQo+IA0KPiBXaGlsZSB3
ZSBhcmUgbm90ICJyZXN0cmljdGluZyB1c2VyIGRlZmluZWQgdmFsdWUiIG9yICJkZWZpbmUgc2Ft
ZQ0KPiByZXN0cmljdGlvbiBmb3IgdXNlciBkZWZpbmVkIGFuZCBkZWZhdWx0IiwgY2FuIHdlIGhh
dmUgb25seSBvbmUgZmxvdyBvZg0KPiBjYWxjdWxhdGlvbiBhbmQgc2V0dGluZyByYXRoZXIgdGhh
biBjb25kaXRpb25hbCBiYXNlZCBvbiB1c2VyIGhhdmUgc2V0IG9yDQo+IG5vdCBzZXQ/DQo+IA0K
WWVzLCB3ZSBjYW4gZG8gdGhhdC4NCklmIHdlIHdhbnQgdG8gdXNlIG9uZSBmbG93IHRvIGhhbmRs
ZSBpdC4gV2Ugc2hvdWxkIGRvIHRoZSBmb2xsb3dpbmcgY2hhbmdlczoNCg0KI2lmZGVmIENPTkZJ
R19GU0xfU09DDQojaW5jbHVkZSA8bGludXgvc2xhYi5oPg0KI2VuZGlmDQoNCnN0YXRpYyB1NjQg
KnB3MjBfd3Q7DQpzdGF0aWMgdTY0ICphbHRpdmVjX2lkbGVfd3Q7DQoNCnN0YXRpYyBzc2l6ZV90
IHNob3dfcHcyMF93YWl0X3RpbWUoc3RydWN0IGRldmljZSAqZGV2LA0KICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqYXR0ciwgY2hhciAqYnVm
KQ0Kew0KCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVsbHVcbiIsIHB3MjBfd3RbZGV2LT5pZF0pOw0K
fQ0KDQpzdGF0aWMgc3NpemVfdCBzdG9yZV9wdzIwX3dhaXRfdGltZShzdHJ1Y3QgZGV2aWNlICpk
ZXYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2VfYXR0cmli
dXRlICphdHRyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyICpi
dWYsIHNpemVfdCBjb3VudCkNCnsNCi4uLg0KcHcyMF93dFtjcHVdID0gdmFsdWU7DQouLi4NCn0N
Cg0Kc3RhdGljIHNzaXplX3Qgc2hvd19hbHRpdmVjX2lkbGVfd2FpdF90aW1lKHN0cnVjdCBkZXZp
Y2UgKmRldiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGRldmljZV9h
dHRyaWJ1dGUgKmF0dHIsIGNoYXIgKmJ1ZikNCnsNCglyZXR1cm4gc3ByaW50ZihidWYsICIlbGx1
XG4iLCBhbHRpdmVjX2lkbGVfd3RbZGV2LT5pZF0pOw0KfQ0KDQpzdGF0aWMgc3NpemVfdCBzdG9y
ZV9hbHRpdmVjX2lkbGVfd2FpdF90aW1lKHN0cnVjdCBkZXZpY2UgKmRldiwNCiAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmF0dHIsDQogICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXIgKmJ1Ziwgc2l6ZV90IGNvdW50
KQ0Kew0KLi4uDQphbHRpdmVjX2lkbGVfd3RbY3B1XSA9IHZhbHVlOw0KLi4uDQp9DQoNCnN0YXRp
YyB2b2lkIHJlZ2lzdGVyX2NwdV9vbmxpbmUodW5zaWduZWQgaW50IGNwdSkNCnsNCi4uLg0KI2lm
ZGVmIENPTkZJR19GU0xfU09DDQogICAgICAgIHUzMiB2YWx1ZSwgcHcyMF92YWx1ZSwgYWx0aXZl
Y192YWx1ZTsNCiAgICAgICAgdTY0IHRiX2N5Y2xlOw0KI2VuZGlmDQouLi4NCiNpZmRlZiBDT05G
SUdfRlNMX1NPQw0KICAgICAgICBpZiAoUFZSX1ZFUihjdXJfY3B1X3NwZWMtPnB2cl92YWx1ZSkg
PT0gUFZSX1ZFUl9FNjUwMCkgew0KICAgICAgICAgICAgICAgIGRldmljZV9jcmVhdGVfZmlsZShz
LCAmZGV2X2F0dHJfcHcyMF9zdGF0ZSk7DQogICAgICAgICAgICAgICAgZGV2aWNlX2NyZWF0ZV9m
aWxlKHMsICZkZXZfYXR0cl9wdzIwX3dhaXRfdGltZSk7DQoNCiAgICAgICAgICAgICAgICBkZXZp
Y2VfY3JlYXRlX2ZpbGUocywgJmRldl9hdHRyX2FsdGl2ZWNfaWRsZSk7DQogICAgICAgICAgICAg
ICAgZGV2aWNlX2NyZWF0ZV9maWxlKHMsICZkZXZfYXR0cl9hbHRpdmVjX2lkbGVfd2FpdF90aW1l
KTsNCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghcHcyMF93dCkNCiAgICAgICAgICAgICAgICBw
dzIwX3d0ID0ga3phbGxvYyhucl9jcHVfaWRzICogc2l6ZW9mKCpwdzIwX3d0KSwgR0ZQX0tFUk5F
TCk7DQoNCgkgIGlmICghYWx0aXZlY19pZGxlX3d0KQ0KCQkgICAgYWx0aXZlY19pZGxlX3d0ID0g
a3phbGxvYyhucl9jcHVfaWRzICogc2l6ZW9mKCphbHRpdmVjX2lkbGVfd3QpLCBHRlBfS0VSTkVM
KTsNCg0KICAgICAgICBzbXBfY2FsbF9mdW5jdGlvbl9zaW5nbGUoY3B1LCBkb19zaG93X3B3cm1n
dGNyMCwgJnZhbHVlLCAxKTsNCg0KICAgICAgICBwdzIwX3ZhbHVlID0gKHZhbHVlICYgUFdSTUdU
Q1IwX1BXMjBfRU5UKSA+PiBQV1JNR1RDUjBfUFcyMF9FTlRfU0hJRlQ7DQogICAgICAgIHRiX2N5
Y2xlID0gKDEgPDwgKE1BWF9CSVQgLSBwdzIwX3ZhbHVlKSkgKiAyOw0KICAgICAgICBwdzIwX3d0
W2NwdV0gPSBkaXZfdTY0KHRiX2N5Y2xlICogMTAwMCwgdGJfdGlja3NfcGVyX3VzZWMpIC0gMTsN
Cg0KICAgICAgICBhbHRpdmVjX3ZhbHVlID0gKHZhbHVlICYgUFdSTUdUQ1IwX0FWX0lETEVfQ05U
KSA+PiBQV1JNR1RDUjBfQVZfSURMRV9DTlRfU0hJRlQ7DQogICAgICAgIHRiX2N5Y2xlID0gKDEg
PDwgKE1BWF9CSVQgLSBhbHRpdmVjX3ZhbHVlKSkgKiAyOw0KICAgICAgICBhbHRpdmVjX2lkbGVf
d3RbY3B1XSA9IGRpdl91NjQodGJfY3ljbGUgKiAxMDAwLCB0Yl90aWNrc19wZXJfdXNlYykgLSAx
Ow0KI2VuZGlmDQouLi4NCn0NCg0K
^ permalink raw reply
* Re: [PATCHv2 1/8] ALSA: Add SAI SoC Digital Audio Interface driver.
From: Shawn Guo @ 2013-11-06 8:12 UTC (permalink / raw)
To: Li Xiubo
Cc: mark.rutland@arm.com, alsa-devel@alsa-project.org,
linux-doc@vger.kernel.org, tiwai@suse.de, Huan Wang, Timur Tabi,
perex@perex.cz, Shawn Guo, LW@KARO-electronics.de,
linux@arm.linux.org.uk, Guangyu Chen,
linux-arm-kernel@lists.infradead.org, grant.likely@linaro.org,
devicetree@vger.kernel.org, ian.campbell@citrix.com,
pawel.moll@arm.com, swarren@wwwdotorg.org,
rob.herring@calxeda.com, broonie@kernel.org, oskar@scara.com,
Fabio Estevam, lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
rob@landley.net, Zhengxiong Jin, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1DD289F6464F0949A2FCA5AA6DC23F82876B08@039-SN2MPN1-013.039d.mgd.msft.net>
On Wed, Nov 06, 2013 at 03:53:24AM +0000, Li Xiubo wrote:
> > >> If there are any comments that say PPC but are not PPC-specific, that
> > >> >should be fixed.
> > > Yes, find it.
> > >
> > > The comments is in "sound/soc/fsl/Makefile" :
> > > +++++++++++
> > > "# Freescale PowerPC SSI/DMA Platform Support"
> > > -----------
> > >
> > > But fsl-spdif.o is also under it.
> > > And this is also support ARM and PowerPC platforms at the same time ?
> > > If so, the comments should be modified to :
> > > +++++++++++
> > > "# Freescale PowerPC and ARM SSI/DMA Platform Support"
> > > -----------
> >
> > Yes, this should be changed.
> >
>
> How about :
> +++++++++
> "# Freescale PowerPC and ARM SSI/DMA/SAI/SPDIF Platform Support"
> ---------
> ?
Or we can just drop 'PowerPC and ARM'?
Shawn
^ permalink raw reply
* RE: [PATCHv2 5/8] ASoC: SGTL5000: Enhance the SGTL5000 codec driver about regulator.
From: Li Xiubo @ 2013-11-06 8:59 UTC (permalink / raw)
To: Mark Brown
Cc: mark.rutland@arm.com, alsa-devel@alsa-project.org,
linux-doc@vger.kernel.org, tiwai@suse.de, Huan Wang,
timur@tabi.org, perex@perex.cz, Shawn Guo, LW@KARO-electronics.de,
linux@arm.linux.org.uk, Guangyu Chen,
linux-arm-kernel@lists.infradead.org, grant.likely@linaro.org,
devicetree@vger.kernel.org, ian.campbell@citrix.com,
pawel.moll@arm.com, swarren@wwwdotorg.org,
rob.herring@calxeda.com, oskar@scara.com, Fabio Estevam,
lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
rob@landley.net, Zhengxiong Jin, shawn.guo@linaro.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20131101185045.GG2493@sirena.org.uk>
> > On VF610 series there are no regulators used, and now whether the
> > CONFIG_REGULATOR mirco is enabled or not, for the VF610 audio patch
> > series, the board cannot be probe successfully.
> > And this patch will solve this issue.
>=20
> I don't understand what this is for at all, you're just saying there is a
> problem you're trying to solve but you don't explain anything about what
> the problem is or how your changes address it.
>=20
Sorry for confusing.
The SGTL5000 is based on regulators and when it is disabled, there will be =
an error returns directly while the SGTL5000 codec is probing.
But on VF610 boards there has no regulators or needn't configure them, so t=
he CONFIG_REGULATOR is disabled, and then the error is returned causing
to the SGTL5000 probe broken.=20
Has I make it clear?
> > +#ifndef CONFIG_SND_SOC_FSL_SGTL5000_VF610
> > static int ldo_regulator_register(struct snd_soc_codec *codec,
>=20
> This is definitely broken, it won't work with multi-platform kernels, and
> I don't understand what this is supposed to do - what is the reason for
> making this change?
>
Yes, it is.
How about adding one node properties like : "regulator-exist", which will b=
e controlled by platform data ?
^ permalink raw reply
* RE: [PATCHv2 1/8] ALSA: Add SAI SoC Digital Audio Interface driver.
From: Li Xiubo @ 2013-11-06 9:38 UTC (permalink / raw)
To: Shawn Guo
Cc: mark.rutland@arm.com, alsa-devel@alsa-project.org,
linux-doc@vger.kernel.org, tiwai@suse.de, Huan Wang, Timur Tabi,
perex@perex.cz, Shawn Guo, LW@KARO-electronics.de,
linux@arm.linux.org.uk, Guangyu Chen,
linux-arm-kernel@lists.infradead.org, grant.likely@linaro.org,
devicetree@vger.kernel.org, ian.campbell@citrix.com,
pawel.moll@arm.com, swarren@wwwdotorg.org,
rob.herring@calxeda.com, broonie@kernel.org, oskar@scara.com,
Fabio Estevam, lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
rob@landley.net, Zhengxiong Jin, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20131106081257.GR19770@S2101-09.ap.freescale.net>
> > > >> If there are any comments that say PPC but are not PPC-specific,
> that
> > > >> >should be fixed.
> > > > Yes, find it.
> > > >
> > > > The comments is in "sound/soc/fsl/Makefile" :
> > > > +++++++++++
> > > > "# Freescale PowerPC SSI/DMA Platform Support"
> > > > -----------
> > > >
> > > > But fsl-spdif.o is also under it.
> > > > And this is also support ARM and PowerPC platforms at the same
> time ?
> > > > If so, the comments should be modified to :
> > > > +++++++++++
> > > > "# Freescale PowerPC and ARM SSI/DMA Platform Support"
> > > > -----------
> > >
> > > Yes, this should be changed.
> > >
> >
> > How about :
> > +++++++++
> > "# Freescale PowerPC and ARM SSI/DMA/SAI/SPDIF Platform Support"
> > ---------
> > ?
>=20
> Or we can just drop 'PowerPC and ARM'?
>=20
Yes, this will be better.
Best Regards,
Xiubo
^ permalink raw reply
* [PATCH V6 1/2] powerpc/85xx: Add QE common init function
From: Xie Xiaobo @ 2013-11-06 9:08 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: Xie Xiaobo
Define a QE init function in common file, and avoid
the same codes being duplicated in board files.
Signed-off-by: Xie Xiaobo <X.Xie@freescale.com>
---
V6 -> V5: add of_device_is_available check.
V5 -> V4: add the board files modification, remove the qe_pic_init.
V4 -> V3: Nochange
arch/powerpc/platforms/85xx/common.c | 38 +++++++++++++++++++++++++++++++
arch/powerpc/platforms/85xx/mpc85xx.h | 6 +++++
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 29 ++---------------------
arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 25 ++------------------
4 files changed, 48 insertions(+), 50 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index d0861a0..970576b 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -7,6 +7,7 @@
*/
#include <linux/of_platform.h>
+#include <asm/qe.h>
#include <sysdev/cpm2_pic.h>
#include "mpc85xx.h"
@@ -80,3 +81,40 @@ void __init mpc85xx_cpm2_pic_init(void)
irq_set_chained_handler(irq, cpm2_cascade);
}
#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+void __init mpc85xx_qe_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!np) {
+ np = of_find_node_by_name(NULL, "qe");
+ if (!np) {
+ pr_err("%s: Could not find Quicc Engine node\n",
+ __func__);
+ return;
+ }
+ }
+
+ if (!of_device_is_available(np)) {
+ of_node_put(np);
+ return;
+ }
+
+ qe_reset();
+ of_node_put(np);
+
+ np = of_find_node_by_name(NULL, "par_io");
+ if (np) {
+ struct device_node *ucc;
+
+ par_io_init(np);
+ of_node_put(np);
+
+ for_each_node_by_name(ucc, "ucc")
+ par_io_of_config(ucc);
+
+ }
+}
+#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index 2aa7c5d..fc51dd4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -8,4 +8,10 @@ extern void mpc85xx_cpm2_pic_init(void);
static inline void __init mpc85xx_cpm2_pic_init(void) {}
#endif /* CONFIG_CPM2 */
+#ifdef CONFIG_QUICC_ENGINE
+extern void mpc85xx_qe_init(void);
+#else
+static inline void __init mpc85xx_qe_init(void) {}
+#endif
+
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index a7b3621..34f3c5e 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2010, 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006-2010, 2012-2013 Freescale Semiconductor, Inc.
* All rights reserved.
*
* Author: Andy Fleming <afleming@freescale.com>
@@ -238,32 +238,7 @@ static void __init mpc85xx_mds_qe_init(void)
{
struct device_node *np;
- np = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!np) {
- np = of_find_node_by_name(NULL, "qe");
- if (!np)
- return;
- }
-
- if (!of_device_is_available(np)) {
- of_node_put(np);
- return;
- }
-
- qe_reset();
- of_node_put(np);
-
- np = of_find_node_by_name(NULL, "par_io");
- if (np) {
- struct device_node *ucc;
-
- par_io_init(np);
- of_node_put(np);
-
- for_each_node_by_name(ucc, "ucc")
- par_io_of_config(ucc);
- }
-
+ mpc85xx_qe_init();
mpc85xx_mds_reset_ucc_phys();
if (machine_is(p1021_mds)) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 53b6fb0..e15bdd1 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -1,7 +1,7 @@
/*
* MPC85xx RDB Board Setup
*
- * Copyright 2009,2012 Freescale Semiconductor Inc.
+ * Copyright 2009,2012-2013 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
@@ -98,26 +98,7 @@ static void __init mpc85xx_rdb_setup_arch(void)
fsl_pci_assign_primary();
#ifdef CONFIG_QUICC_ENGINE
- np = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!np) {
- pr_err("%s: Could not find Quicc Engine node\n", __func__);
- goto qe_fail;
- }
-
- qe_reset();
- of_node_put(np);
-
- np = of_find_node_by_name(NULL, "par_io");
- if (np) {
- struct device_node *ucc;
-
- par_io_init(np);
- of_node_put(np);
-
- for_each_node_by_name(ucc, "ucc")
- par_io_of_config(ucc);
-
- }
+ mpc85xx_qe_init();
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
if (machine_is(p1025_rdb)) {
@@ -148,8 +129,6 @@ static void __init mpc85xx_rdb_setup_arch(void)
}
#endif
-
-qe_fail:
#endif /* CONFIG_QUICC_ENGINE */
printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
--
1.8.4
^ permalink raw reply related
* [PATCH V6 2/2] powerpc/85xx: Add TWR-P1025 board support
From: Xie Xiaobo @ 2013-11-06 9:08 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: Michael Johnston, Xie Xiaobo
In-Reply-To: <1383728883-25561-1-git-send-email-X.Xie@freescale.com>
TWR-P1025 Overview
-----------------
512Mbyte DDR3 (on board DDR)
64MB Nor Flash
eTSEC1: Connected to RGMII PHY AR8035
eTSEC3: Connected to RGMII PHY AR8035
Two USB2.0 Type A
One microSD Card slot
One mini-PCIe slot
One mini-USB TypeB dual UART
Signed-off-by: Michael Johnston <michael.johnston@freescale.com>
Signed-off-by: Xie Xiaobo <X.Xie@freescale.com>
---
Patch V6: Add a binding doc for ssd1289 device.
Patch V5: Miscellaneous modification. e.g. move the qe ucc node into dtsi.
Patch V4: Fix the mdio phy interrupt issue in dts
Patch V3: fix pcie range issue in dts
Patch V2: QE related init codes were factored out to a common file
.../devicetree/bindings/video/ssd1289fb.txt | 13 +
arch/powerpc/boot/dts/p1025twr.dts | 95 +++++++
arch/powerpc/boot/dts/p1025twr.dtsi | 280 +++++++++++++++++++++
arch/powerpc/platforms/85xx/Kconfig | 6 +
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/twr_p102x.c | 147 +++++++++++
6 files changed, 542 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/ssd1289fb.txt
create mode 100644 arch/powerpc/boot/dts/p1025twr.dts
create mode 100644 arch/powerpc/boot/dts/p1025twr.dtsi
create mode 100644 arch/powerpc/platforms/85xx/twr_p102x.c
diff --git a/Documentation/devicetree/bindings/video/ssd1289fb.txt b/Documentation/devicetree/bindings/video/ssd1289fb.txt
new file mode 100644
index 0000000..4fcd5e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/ssd1289fb.txt
@@ -0,0 +1,13 @@
+* Solomon SSD1289 Framebuffer Driver
+
+Required properties:
+ - compatible: Should be "solomon,ssd1289fb". The only supported bus for
+ now is lbc.
+ - reg: Should contain address of the controller on the LBC bus. The detail
+ was described in Documentation/devicetree/bindings/powerpc/fsl/lbc.txt
+
+Examples:
+display@2,0 {
+ compatible = "solomon,ssd1289fb";
+ reg = <0x2 0x0000 0x0004>;
+};
diff --git a/arch/powerpc/boot/dts/p1025twr.dts b/arch/powerpc/boot/dts/p1025twr.dts
new file mode 100644
index 0000000..9036a49
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1025twr.dts
@@ -0,0 +1,95 @@
+/*
+ * P1025 TWR Device Tree Source (32-bit address map)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1021si-pre.dtsi"
+/ {
+ model = "fsl,P1025";
+ compatible = "fsl,TWR-P1025";
+
+ memory {
+ device_type = "memory";
+ };
+
+ lbc: localbus@ffe05000 {
+ reg = <0 0xffe05000 0 0x1000>;
+
+ /* NOR Flash and SSD1289 */
+ ranges = <0x0 0x0 0x0 0xec000000 0x04000000
+ 0x2 0x0 0x0 0xe0000000 0x00020000>;
+ };
+
+ soc: soc@ffe00000 {
+ ranges = <0x0 0x0 0xffe00000 0x100000>;
+ };
+
+ pci0: pcie@ffe09000 {
+ ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+ reg = <0 0xffe09000 0 0x1000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xa0000000
+ 0x2000000 0x0 0xa0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ffe0a000 {
+ reg = <0 0xffe0a000 0 0x1000>;
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ qe: qe@ffe80000 {
+ ranges = <0x0 0x0 0xffe80000 0x40000>;
+ reg = <0 0xffe80000 0 0x480>;
+ brg-frequency = <0>;
+ bus-frequency = <0>;
+ };
+};
+
+/include/ "p1025twr.dtsi"
+/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1025twr.dtsi b/arch/powerpc/boot/dts/p1025twr.dtsi
new file mode 100644
index 0000000..8453501
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1025twr.dtsi
@@ -0,0 +1,280 @@
+/*
+ * P1025 TWR Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/{
+ aliases {
+ ethernet3 = &enet3;
+ ethernet4 = &enet4;
+ };
+};
+
+&lbc {
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ partition@0 {
+ /* This location must not be altered */
+ /* 256KB for Vitesse 7385 Switch firmware */
+ reg = <0x0 0x00040000>;
+ label = "NOR Vitesse-7385 Firmware";
+ read-only;
+ };
+
+ partition@40000 {
+ /* 256KB for DTB Image */
+ reg = <0x00040000 0x00040000>;
+ label = "NOR DTB Image";
+ };
+
+ partition@80000 {
+ /* 5.5 MB for Linux Kernel Image */
+ reg = <0x00080000 0x00580000>;
+ label = "NOR Linux Kernel Image";
+ };
+
+ partition@400000 {
+ /* 56.75MB for Root file System */
+ reg = <0x00600000 0x038c0000>;
+ label = "NOR Root File System";
+ };
+
+ partition@ec0000 {
+ /* This location must not be altered */
+ /* 256KB for QE ucode firmware*/
+ reg = <0x03ec0000 0x00040000>;
+ label = "NOR QE microcode firmware";
+ read-only;
+ };
+
+ partition@f00000 {
+ /* This location must not be altered */
+ /* 512KB for u-boot Bootloader Image */
+ /* 512KB for u-boot Environment Variables */
+ reg = <0x03f00000 0x00100000>;
+ label = "NOR U-Boot Image";
+ read-only;
+ };
+ };
+
+ /* CS2 for Display */
+ display@2,0 {
+ compatible = "solomon,ssd1289fb";
+ reg = <0x2 0x0000 0x0004>;
+ };
+
+};
+
+&soc {
+ usb@22000 {
+ phy_type = "ulpi";
+ };
+
+ mdio@24000 {
+ phy0: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1 0 0>;
+ reg = <0x2>;
+ };
+
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1 0 0>;
+ reg = <0x1>;
+ };
+
+ tbi0: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@25000 {
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@26000 {
+ tbi2: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet0: ethernet@b0000 {
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+
+ };
+
+ enet1: ethernet@b1000 {
+ status = "disabled";
+ };
+
+ enet2: ethernet@b2000 {
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ par_io@e0100 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xe0100 0x60>;
+ ranges = <0x0 0xe0100 0x60>;
+ device_type = "par_io";
+ num-ports = <3>;
+ pio1: ucc_pin@01 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
+ 0x0 0x17 0x2 0x0 0x2 0x0 /* CLK12 */
+ 0x0 0x18 0x2 0x0 0x1 0x0 /* CLK9 */
+ 0x0 0x7 0x1 0x0 0x2 0x0 /* ENET1_TXD0_SER1_TXD0 */
+ 0x0 0x9 0x1 0x0 0x2 0x0 /* ENET1_TXD1_SER1_TXD1 */
+ 0x0 0xb 0x1 0x0 0x2 0x0 /* ENET1_TXD2_SER1_TXD2 */
+ 0x0 0xc 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */
+ 0x0 0x6 0x2 0x0 0x2 0x0 /* ENET1_RXD0_SER1_RXD0 */
+ 0x0 0xa 0x2 0x0 0x2 0x0 /* ENET1_RXD1_SER1_RXD1 */
+ 0x0 0xe 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */
+ 0x0 0xf 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */
+ 0x0 0x5 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */
+ 0x0 0xd 0x1 0x0 0x2 0x0 /* ENET1_TX_ER */
+ 0x0 0x4 0x2 0x0 0x2 0x0 /* ENET1_RX_DV_SER1_CTS_B */
+ 0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RX_ER_SER1_CD_B */
+ 0x0 0x11 0x2 0x0 0x2 0x0 /* ENET1_CRS */
+ 0x0 0x10 0x2 0x0 0x2 0x0>; /* ENET1_COL */
+ };
+
+ pio2: ucc_pin@02 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
+ 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
+ 0x1 0xb 0x2 0x0 0x1 0x0 /* CLK13 */
+ 0x1 0x7 0x1 0x0 0x2 0x0 /* ENET5_TXD0_SER5_TXD0 */
+ 0x1 0xa 0x1 0x0 0x2 0x0 /* ENET5_TXD1_SER5_TXD1 */
+ 0x1 0x6 0x2 0x0 0x2 0x0 /* ENET5_RXD0_SER5_RXD0 */
+ 0x1 0x9 0x2 0x0 0x2 0x0 /* ENET5_RXD1_SER5_RXD1 */
+ 0x1 0x5 0x1 0x0 0x2 0x0 /* ENET5_TX_EN_SER5_RTS_B */
+ 0x1 0x4 0x2 0x0 0x2 0x0 /* ENET5_RX_DV_SER5_CTS_B */
+ 0x1 0x8 0x2 0x0 0x2 0x0>; /* ENET5_RX_ER_SER5_CD_B */
+ };
+
+ pio3: ucc_pin@03 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x0 0x16 0x2 0x0 0x2 0x0 /* SER7_CD_B*/
+ 0x0 0x12 0x2 0x0 0x2 0x0 /* SER7_CTS_B*/
+ 0x0 0x13 0x1 0x0 0x2 0x0 /* SER7_RTS_B*/
+ 0x0 0x14 0x2 0x0 0x2 0x0 /* SER7_RXD0*/
+ 0x0 0x15 0x1 0x0 0x2 0x0>; /* SER7_TXD0*/
+ };
+
+ pio4: ucc_pin@04 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+ 0x1 0x0 0x2 0x0 0x2 0x0 /* SER3_CD_B*/
+ 0x0 0x1c 0x2 0x0 0x2 0x0 /* SER3_CTS_B*/
+ 0x0 0x1d 0x1 0x0 0x2 0x0 /* SER3_RTS_B*/
+ 0x0 0x1e 0x2 0x0 0x2 0x0 /* SER3_RXD0*/
+ 0x0 0x1f 0x1 0x0 0x2 0x0>; /* SER3_TXD0*/
+ };
+ };
+};
+
+&qe {
+ enet3: ucc@2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ rx-clock-name = "clk12";
+ tx-clock-name = "clk9";
+ pio-handle = <&pio1>;
+ phy-handle = <&qe_phy0>;
+ phy-connection-type = "mii";
+ };
+
+ mdio@2120 {
+ qe_phy0: ethernet-phy@18 {
+ interrupt-parent = <&mpic>;
+ interrupts = <4 1 0 0>;
+ reg = <0x18>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy1: ethernet-phy@19 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1 0 0>;
+ reg = <0x19>;
+ device_type = "ethernet-phy";
+ };
+ tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet4: ucc@2400 {
+ device_type = "network";
+ compatible = "ucc_geth";
+ rx-clock-name = "none";
+ tx-clock-name = "clk13";
+ pio-handle = <&pio2>;
+ phy-handle = <&qe_phy1>;
+ phy-connection-type = "rmii";
+ };
+
+ serial2: ucc@2600 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+ port-number = <0>;
+ rx-clock-name = "brg6";
+ tx-clock-name = "brg6";
+ pio-handle = <&pio3>;
+ };
+
+ serial3: ucc@2200 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+ port-number = <1>;
+ rx-clock-name = "brg2";
+ tx-clock-name = "brg2";
+ pio-handle = <&pio4>;
+ };
+};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 4d46349..c17aae8 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -123,6 +123,12 @@ config P1023_RDS
help
This option enables support for the P1023 RDS and RDB boards
+config TWR_P102x
+ bool "Freescale TWR-P102x"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the TWR-P1025 board.
+
config SOCRATES
bool "Socrates"
select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index dd4c0b5..25cebe7 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_P1010_RDB) += p1010rdb.o
obj-$(CONFIG_P1022_DS) += p1022_ds.o
obj-$(CONFIG_P1022_RDK) += p1022_rdk.o
obj-$(CONFIG_P1023_RDS) += p1023_rds.o
+obj-$(CONFIG_TWR_P102x) += twr_p102x.o
obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o
obj-$(CONFIG_STX_GP3) += stx_gp3.o
obj-$(CONFIG_TQM85xx) += tqm85xx.o
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
new file mode 100644
index 0000000..4d264e3
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2010-2011, 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Michael Johnston <michael.johnston@freescale.com>
+ *
+ * Description:
+ * TWR-P102x Board Setup
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/of_platform.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/fsl_guts.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include "smp.h"
+
+#include "mpc85xx.h"
+
+static void __init twr_p1025_pic_init(void)
+{
+ struct mpic *mpic;
+
+#ifdef CONFIG_QUICC_ENGINE
+ struct device_node *np;
+#endif
+
+ mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+ MPIC_SINGLE_DEST_CPU,
+ 0, 256, " OpenPIC ");
+
+ BUG_ON(mpic == NULL);
+ mpic_init(mpic);
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+ if (np) {
+ qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+ qe_ic_cascade_high_mpic);
+ of_node_put(np);
+ } else
+ pr_err("Could not find qe-ic node\n");
+#endif
+}
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init twr_p1025_setup_arch(void)
+{
+#ifdef CONFIG_QUICC_ENGINE
+ struct device_node *np;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("twr_p1025_setup_arch()", 0);
+
+ mpc85xx_smp_init();
+
+ fsl_pci_assign_primary();
+
+#ifdef CONFIG_QUICC_ENGINE
+ mpc85xx_qe_init();
+
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
+ if (machine_is(twr_p1025)) {
+ struct ccsr_guts __iomem *guts;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,p1021-guts");
+ if (np) {
+ guts = of_iomap(np, 0);
+ if (!guts)
+ pr_err("twr_p1025: could not map global utilities register\n");
+ else {
+ /* P1025 has pins muxed for QE and other functions. To
+ * enable QE UEC mode, we need to set bit QE0 for UCC1
+ * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
+ * and QE12 for QE MII management signals in PMUXCR
+ * register.
+ * Set QE mux bits in PMUXCR */
+ setbits32(&guts->pmuxcr, MPC85xx_PMUXCR_QE(0) |
+ MPC85xx_PMUXCR_QE(3) |
+ MPC85xx_PMUXCR_QE(9) |
+ MPC85xx_PMUXCR_QE(12));
+ iounmap(guts);
+
+#if defined(CONFIG_SERIAL_QE)
+ /* On P1025TWR board, the UCC7 acted as UART port.
+ * However, The UCC7's CTS pin is low level in default,
+ * it will impact the transmission in full duplex
+ * communication. So disable the Flow control pin PA18.
+ * The UCC7 UART just can use RXD and TXD pins.
+ */
+ par_io_config_pin(0, 18, 0, 0, 0, 0);
+#endif
+ /* Drive PB29 to CPLD low - CPLD will then change
+ * muxing from LBC to QE */
+ par_io_config_pin(1, 29, 1, 0, 0, 0);
+ par_io_data_set(1, 29, 0);
+ }
+ of_node_put(np);
+ }
+ }
+#endif
+#endif /* CONFIG_QUICC_ENGINE */
+
+ printk(KERN_INFO "TWR-P1025 board from Freescale Semiconductor\n");
+}
+
+machine_arch_initcall(twr_p1025, mpc85xx_common_publish_devices);
+
+static int __init twr_p1025_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,TWR-P1025");
+}
+
+define_machine(twr_p1025) {
+ .name = "TWR-P1025",
+ .probe = twr_p1025_probe,
+ .setup_arch = twr_p1025_setup_arch,
+ .init_IRQ = twr_p1025_pic_init,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
--
1.8.4
^ permalink raw reply related
* Re: [PATCHv2 1/8] ALSA: Add SAI SoC Digital Audio Interface driver.
From: Mark Brown @ 2013-11-06 9:53 UTC (permalink / raw)
To: Li Xiubo
Cc: mark.rutland@arm.com, alsa-devel@alsa-project.org,
linux-doc@vger.kernel.org, tiwai@suse.de, Huan Wang,
timur@tabi.org, perex@perex.cz, Shawn Guo, LW@KARO-electronics.de,
linux@arm.linux.org.uk, Guangyu Chen,
linux-arm-kernel@lists.infradead.org, grant.likely@linaro.org,
devicetree@vger.kernel.org, ian.campbell@citrix.com,
pawel.moll@arm.com, swarren@wwwdotorg.org,
rob.herring@calxeda.com, oskar@scara.com, Fabio Estevam,
lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
rob@landley.net, Zhengxiong Jin, shawn.guo@linaro.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1DD289F6464F0949A2FCA5AA6DC23F82875482@039-SN2MPN1-013.039d.mgd.msft.net>
[-- Attachment #1: Type: text/plain, Size: 316 bytes --]
On Tue, Nov 05, 2013 at 03:21:49AM +0000, Li Xiubo wrote:
> As your opinions, should I move the four register writing operations to .set_sysclk/set_clkdiv/... functions too ?
> Or just add a clk_disable_unprepare() after them here, and then add clk_prepare_enable in one of .set_sysclk/set_clkdiv/...?
The latter.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCHv2 5/8] ASoC: SGTL5000: Enhance the SGTL5000 codec driver about regulator.
From: Mark Brown @ 2013-11-06 10:03 UTC (permalink / raw)
To: Li Xiubo
Cc: mark.rutland@arm.com, alsa-devel@alsa-project.org,
linux-doc@vger.kernel.org, tiwai@suse.de, Huan Wang,
timur@tabi.org, perex@perex.cz, Shawn Guo, LW@KARO-electronics.de,
linux@arm.linux.org.uk, Guangyu Chen,
linux-arm-kernel@lists.infradead.org, grant.likely@linaro.org,
devicetree@vger.kernel.org, ian.campbell@citrix.com,
pawel.moll@arm.com, swarren@wwwdotorg.org,
rob.herring@calxeda.com, oskar@scara.com, Fabio Estevam,
lgirdwood@gmail.com, linux-kernel@vger.kernel.org,
rob@landley.net, Zhengxiong Jin, shawn.guo@linaro.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1DD289F6464F0949A2FCA5AA6DC23F82876EFF@039-SN2MPN1-013.039d.mgd.msft.net>
[-- Attachment #1: Type: text/plain, Size: 362 bytes --]
On Wed, Nov 06, 2013 at 08:59:53AM +0000, Li Xiubo wrote:
Please fix your mailer to word wrap within paragraphs.
> The SGTL5000 is based on regulators and when it is disabled, there
> will be an error returns directly while the SGTL5000 codec is probing.
What makes you say this? That's not how the regulator API works. Have
you actually seen any problems?
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: memcpy optimization for 64bit LE
From: Philippe Bergheaud @ 2013-11-06 10:21 UTC (permalink / raw)
To: Michael Neuling; +Cc: Linuxppc-dev
In-Reply-To: <11438.1383718966@ale.ozlabs.ibm.com>
Michael Neuling wrote:
> Philippe Bergheaud <felix@linux.vnet.ibm.com> wrote:
>
>
>>Unaligned stores take alignment exceptions on POWER7 running in little-endian.
>>This is a dumb little-endian base memcpy that prevents unaligned stores.
>>It is replaced by the VMX memcpy at boot.
>
>
> Is this any faster than the generic version?
The little-endian assembly code of the base memcpy is similar to the code emitted by gcc when compiling the generic memcpy in lib/string.c, and runs at the same speed.
However, a little-endian assembly version of the base memcpy is required (as opposed to a C version), in order to use the self-modifying code instrumentation system.
After the cpu feature CPU_FTR_ALTIVEC is detected at boot, the slow base memcpy is nop'ed out, and the fast memcpy_power7 is used instead.
Philippe
^ permalink raw reply
* Re: [RFC] arch: Introduce new TSO memory barrier smp_tmb()
From: Will Deacon @ 2013-11-06 11:00 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Michael Neuling, Mathieu Desnoyers, heiko.carstens@de.ibm.com,
Oleg Nesterov, LKML, Linux PPC dev, Anton Blanchard,
Frederic Weisbecker, Victor Kaplansky, linux@arm.linux.org.uk,
Paul E. McKenney, Linus Torvalds, schwidefsky@de.ibm.com
In-Reply-To: <20131105184943.GY16117@laptop.programming.kicks-ass.net>
On Tue, Nov 05, 2013 at 06:49:43PM +0000, Peter Zijlstra wrote:
> On Tue, Nov 05, 2013 at 02:05:48PM +0000, Will Deacon wrote:
> > > > +
> > > > +#define smp_store_release(p, v) \
> > > > +do { \
> > > > + smp_mb(); \
> > > > + ACCESS_ONCE(p) = (v); \
> > > > +} while (0)
> > > > +
> > > > +#define smp_load_acquire(p, v) \
> > > > +do { \
> > > > + typeof(p) ___p1 = ACCESS_ONCE(p); \
> > > > + smp_mb(); \
> > > > + return ___p1; \
> > > > +} while (0)
> >
> > What data sizes do these accessors operate on? Assuming that we want
> > single-copy atomicity (with respect to interrupts in the UP case), we
> > probably want a check to stop people passing in things like structs.
>
> Fair enough; I think we should restrict to native word sizes same as we
> do for atomics.
>
> Something like so perhaps:
>
> #ifdef CONFIG_64BIT
> #define __check_native_word(t) (sizeof(t) == 4 || sizeof(t) == 8)
Ok, if we want to support 32-bit accesses on 64-bit machines, that will
complicate some of your assembly (more below).
> #else
> #define __check_native_word(t) (sizeof(t) == 4)
> #endif
>
> #define smp_store_release(p, v) \
> do { \
> BUILD_BUG_ON(!__check_native_word(p)); \
> smp_mb(); \
> ACCESS_ONCE(p) = (v); \
> } while (0)
>
> > > > +#define smp_store_release(p, v) \
> > > > +do { \
> > > > + asm volatile ("stlr %w0 [%1]" : : "r" (v), "r" (&p) : "memory");\
> >
> > Missing comma between the operands. Also, that 'w' output modifier enforces
> > a 32-bit store (same early question about sizes). Finally, it might be more
> > efficient to use "=Q" for the addressing mode, rather than take the address
> > of p manually.
>
> so something like:
>
> asm volatile ("stlr %0, [%1]" : : "r" (v), "=Q" (p) : "memory");
>
> ?
>
> My inline asm foo is horrid and I mostly get by with copy paste from a
> semi similar existing form :/
Almost: you just need to drop the square brackets and make the memory
location an output operand:
asm volatile("stlr %1, %0" : "=Q" (p) : "r" (v) : "memory");
however, for a 32-bit access, you need to use an output modifier:
asm volatile("stlr %w1, %0" : "=Q" (p) : "r" (v) : "memory");
so I guess a switch on sizeof(p) is required.
> > Random other question: have you considered how these accessors should behave
> > when presented with __iomem pointers?
>
> A what? ;-)
Then let's go with Paul's suggestion of mandating __kernel, or the like
(unless we need to worry about __user addresses for things like futexes?).
Will
^ permalink raw reply
* Re: [PATCH 2/3] powerpc/kvm: fix rare but potential deadlock scene
From: Paul Mackerras @ 2013-11-06 11:18 UTC (permalink / raw)
To: Liu ping fan; +Cc: linuxppc-dev, Alexander Graf, kvm-ppc
In-Reply-To: <CAFgQCTsxEAqMDt=zfFMhEG2CZ6G=QpH+OsPvJkvjFU7GkDOcXQ@mail.gmail.com>
On Wed, Nov 06, 2013 at 02:02:07PM +0800, Liu ping fan wrote:
> On Wed, Nov 6, 2013 at 1:04 PM, Paul Mackerras <paulus@samba.org> wrote:
> > On Tue, Nov 05, 2013 at 03:42:43PM +0800, Liu Ping Fan wrote:
> >> Since kvmppc_hv_find_lock_hpte() is called from both virtmode and
> >> realmode, so it can trigger the deadlock.
> >
> > Good catch, we should have preemption disabled while ever we have a
> > HPTE locked.
> >
> >> @@ -474,8 +474,10 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
> >> }
> >>
> >> /* Find the HPTE in the hash table */
> >> + preempt_disable();
> >> index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
> >> HPTE_V_VALID | HPTE_V_ABSENT);
> >> + preempt_enable();
> >
> > Which means we need to add the preempt_enable after unlocking the
> > HPTE, not here.
> >
> Yes. Sorry, but I am not sure about whether we can call
> preempt_disable/enable() in realmode. I think since thread_info is
> allocated with linear address, so we can use preempt_disable/enable()
> inside kvmppc_hv_find_lock_hpte(), right?
Your analysis correctly pointed out that we can get a deadlock if we
can be preempted while holding a lock on a HPTE. That means that we
have to disable preemption before taking an HPTE lock and keep it
disabled until after we unlock the HPTE. Since the point of
kvmppc_hv_find_lock_hpte() is to lock the HPTE and return with it
locked, we can't have the preempt_enable() inside it. The
preempt_enable() has to come after we have unlocked the HPTE. That is
also why we can't have the preempt_enable() where your patch put it;
it needs to be about 9 lines further down, after the statement
hptep[0] = v. (We also need to make sure to re-enable preemption in
the index < 0 case.)
Regards,
Paul.
^ permalink raw reply
* Re: [PATCH 3/3] powerpc/kvm: remove redundant assignment
From: Alexander Graf @ 2013-11-06 11:24 UTC (permalink / raw)
To: Liu Ping Fan; +Cc: Paul Mackerras, linuxppc-dev, kvm-ppc
In-Reply-To: <1383637364-14691-3-git-send-email-pingfank@linux.vnet.ibm.com>
On 05.11.2013, at 08:42, Liu Ping Fan <kernelfans@gmail.com> wrote:
> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
Patch description missing.
Please add Paul's ack in the next revision of this patch :).
Alex
> ---
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 1 -
> 1 file changed, 1 deletion(-)
>=20
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c =
b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> index 28160ac..7682837 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
> @@ -731,7 +731,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run =
*run, struct kvm_vcpu *vcpu,
> lock_rmap(rmap);
>=20
> /* Check if we might have been invalidated; let the guest retry =
if so */
> - ret =3D RESUME_GUEST;
> if (mmu_notifier_retry(vcpu->kvm, mmu_seq)) {
> unlock_rmap(rmap);
> goto out_unlock;
> --=20
> 1.8.1.4
>=20
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC] arch: Introduce new TSO memory barrier smp_tmb()
From: Peter Zijlstra @ 2013-11-06 12:39 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Michael Neuling, tony.luck, Mathieu Desnoyers, heiko.carstens,
Oleg Nesterov, LKML, Linux PPC dev, Anton Blanchard,
Frederic Weisbecker, Victor Kaplansky, linux, Linus Torvalds,
schwidefsky
In-Reply-To: <20131104205344.GW3947@linux.vnet.ibm.com>
Subject: arch: Introduce smp_load_acquire(), smp_store_release()
From: Peter Zijlstra <peterz@infradead.org>
Date: Mon, 4 Nov 2013 20:18:11 +0100
A number of situations currently require the heavyweight smp_mb(),
even though there is no need to order prior stores against later
loads. Many architectures have much cheaper ways to handle these
situations, but the Linux kernel currently has no portable way
to make use of them.
This commit therefore supplies smp_load_acquire() and
smp_store_release() to remedy this situation. The new
smp_load_acquire() primitive orders the specified load against
any subsequent reads or writes, while the new smp_store_release()
primitive orders the specifed store against any prior reads or
writes. These primitives allow array-based circular FIFOs to be
implemented without an smp_mb(), and also allow a theoretical
hole in rcu_assign_pointer() to be closed at no additional
expense on most architectures.
In addition, the RCU experience transitioning from explicit
smp_read_barrier_depends() and smp_wmb() to rcu_dereference()
and rcu_assign_pointer(), respectively resulted in substantial
improvements in readability. It therefore seems likely that
replacing other explicit barriers with smp_load_acquire() and
smp_store_release() will provide similar benefits. It appears
that roughly half of the explicit barriers in core kernel code
might be so replaced.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Michael Ellerman <michael@ellerman.id.au>
Cc: Michael Neuling <mikey@neuling.org>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Victor Kaplansky <VICTORK@il.ibm.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
---
Documentation/memory-barriers.txt | 157 +++++++++++++++++-----------------
arch/alpha/include/asm/barrier.h | 15 +++
arch/arc/include/asm/barrier.h | 15 +++
arch/arm/include/asm/barrier.h | 15 +++
arch/arm64/include/asm/barrier.h | 50 ++++++++++
arch/avr32/include/asm/barrier.h | 14 +++
arch/blackfin/include/asm/barrier.h | 15 +++
arch/cris/include/asm/barrier.h | 15 +++
arch/frv/include/asm/barrier.h | 15 +++
arch/h8300/include/asm/barrier.h | 15 +++
arch/hexagon/include/asm/barrier.h | 15 +++
arch/ia64/include/asm/barrier.h | 49 ++++++++++
arch/m32r/include/asm/barrier.h | 15 +++
arch/m68k/include/asm/barrier.h | 15 +++
arch/metag/include/asm/barrier.h | 15 +++
arch/microblaze/include/asm/barrier.h | 15 +++
arch/mips/include/asm/barrier.h | 15 +++
arch/mn10300/include/asm/barrier.h | 15 +++
arch/parisc/include/asm/barrier.h | 15 +++
arch/powerpc/include/asm/barrier.h | 21 ++++
arch/s390/include/asm/barrier.h | 15 +++
arch/score/include/asm/barrier.h | 15 +++
arch/sh/include/asm/barrier.h | 15 +++
arch/sparc/include/asm/barrier_32.h | 15 +++
arch/sparc/include/asm/barrier_64.h | 15 +++
arch/tile/include/asm/barrier.h | 15 +++
arch/unicore32/include/asm/barrier.h | 15 +++
arch/x86/include/asm/barrier.h | 15 +++
arch/xtensa/include/asm/barrier.h | 15 +++
include/linux/compiler.h | 9 +
30 files changed, 581 insertions(+), 79 deletions(-)
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -371,33 +371,35 @@ VARIETIES OF MEMORY BARRIER
And a couple of implicit varieties:
- (5) LOCK operations.
+ (5) ACQUIRE operations.
This acts as a one-way permeable barrier. It guarantees that all memory
- operations after the LOCK operation will appear to happen after the LOCK
- operation with respect to the other components of the system.
+ operations after the ACQUIRE operation will appear to happen after the
+ ACQUIRE operation with respect to the other components of the system.
- Memory operations that occur before a LOCK operation may appear to happen
- after it completes.
+ Memory operations that occur before a ACQUIRE operation may appear to
+ happen after it completes.
- A LOCK operation should almost always be paired with an UNLOCK operation.
+ A ACQUIRE operation should almost always be paired with an RELEASE
+ operation.
- (6) UNLOCK operations.
+ (6) RELEASE operations.
This also acts as a one-way permeable barrier. It guarantees that all
- memory operations before the UNLOCK operation will appear to happen before
- the UNLOCK operation with respect to the other components of the system.
+ memory operations before the RELEASE operation will appear to happen
+ before the RELEASE operation with respect to the other components of the
+ system.
- Memory operations that occur after an UNLOCK operation may appear to
+ Memory operations that occur after an RELEASE operation may appear to
happen before it completes.
- LOCK and UNLOCK operations are guaranteed to appear with respect to each
- other strictly in the order specified.
+ ACQUIRE and RELEASE operations are guaranteed to appear with respect to
+ each other strictly in the order specified.
- The use of LOCK and UNLOCK operations generally precludes the need for
- other sorts of memory barrier (but note the exceptions mentioned in the
- subsection "MMIO write barrier").
+ The use of ACQUIRE and RELEASE operations generally precludes the need
+ for other sorts of memory barrier (but note the exceptions mentioned in
+ the subsection "MMIO write barrier").
Memory barriers are only required where there's a possibility of interaction
@@ -1135,7 +1137,7 @@ CPU from reordering them.
clear_bit( ... );
This prevents memory operations before the clear leaking to after it. See
- the subsection on "Locking Functions" with reference to UNLOCK operation
+ the subsection on "Locking Functions" with reference to RELEASE operation
implications.
See Documentation/atomic_ops.txt for more information. See the "Atomic
@@ -1181,65 +1183,66 @@ LOCKING FUNCTIONS
(*) R/W semaphores
(*) RCU
-In all cases there are variants on "LOCK" operations and "UNLOCK" operations
+In all cases there are variants on "ACQUIRE" operations and "RELEASE" operations
for each construct. These operations all imply certain barriers:
- (1) LOCK operation implication:
+ (1) ACQUIRE operation implication:
- Memory operations issued after the LOCK will be completed after the LOCK
- operation has completed.
+ Memory operations issued after the ACQUIRE will be completed after the
+ ACQUIRE operation has completed.
- Memory operations issued before the LOCK may be completed after the LOCK
- operation has completed.
+ Memory operations issued before the ACQUIRE may be completed after the
+ ACQUIRE operation has completed.
- (2) UNLOCK operation implication:
+ (2) RELEASE operation implication:
- Memory operations issued before the UNLOCK will be completed before the
- UNLOCK operation has completed.
+ Memory operations issued before the RELEASE will be completed before the
+ RELEASE operation has completed.
- Memory operations issued after the UNLOCK may be completed before the
- UNLOCK operation has completed.
+ Memory operations issued after the RELEASE may be completed before the
+ RELEASE operation has completed.
- (3) LOCK vs LOCK implication:
+ (3) ACQUIRE vs ACQUIRE implication:
- All LOCK operations issued before another LOCK operation will be completed
- before that LOCK operation.
+ All ACQUIRE operations issued before another ACQUIRE operation will be
+ completed before that ACQUIRE operation.
- (4) LOCK vs UNLOCK implication:
+ (4) ACQUIRE vs RELEASE implication:
- All LOCK operations issued before an UNLOCK operation will be completed
- before the UNLOCK operation.
+ All ACQUIRE operations issued before an RELEASE operation will be
+ completed before the RELEASE operation.
- All UNLOCK operations issued before a LOCK operation will be completed
- before the LOCK operation.
+ All RELEASE operations issued before a ACQUIRE operation will be
+ completed before the ACQUIRE operation.
- (5) Failed conditional LOCK implication:
+ (5) Failed conditional ACQUIRE implication:
- Certain variants of the LOCK operation may fail, either due to being
+ Certain variants of the ACQUIRE operation may fail, either due to being
unable to get the lock immediately, or due to receiving an unblocked
signal whilst asleep waiting for the lock to become available. Failed
locks do not imply any sort of barrier.
-Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
-equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
+Therefore, from (1), (2) and (4) an RELEASE followed by an unconditional
+ACQUIRE is equivalent to a full barrier, but a ACQUIRE followed by an RELEASE
+is not.
[!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
barriers is that the effects of instructions outside of a critical section
may seep into the inside of the critical section.
-A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
-because it is possible for an access preceding the LOCK to happen after the
-LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
-two accesses can themselves then cross:
+A ACQUIRE followed by an RELEASE may not be assumed to be full memory barrier
+because it is possible for an access preceding the ACQUIRE to happen after the
+ACQUIRE, and an access following the RELEASE to happen before the RELEASE, and
+the two accesses can themselves then cross:
*A = a;
- LOCK
- UNLOCK
+ ACQUIRE
+ RELEASE
*B = b;
may occur as:
- LOCK, STORE *B, STORE *A, UNLOCK
+ ACQUIRE, STORE *B, STORE *A, RELEASE
Locks and semaphores may not provide any guarantee of ordering on UP compiled
systems, and so cannot be counted on in such a situation to actually achieve
@@ -1253,33 +1256,33 @@ See also the section on "Inter-CPU locki
*A = a;
*B = b;
- LOCK
+ ACQUIRE
*C = c;
*D = d;
- UNLOCK
+ RELEASE
*E = e;
*F = f;
The following sequence of events is acceptable:
- LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
+ ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
[+] Note that {*F,*A} indicates a combined access.
But none of the following are:
- {*F,*A}, *B, LOCK, *C, *D, UNLOCK, *E
- *A, *B, *C, LOCK, *D, UNLOCK, *E, *F
- *A, *B, LOCK, *C, UNLOCK, *D, *E, *F
- *B, LOCK, *C, *D, UNLOCK, {*F,*A}, *E
+ {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E
+ *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F
+ *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F
+ *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E
INTERRUPT DISABLING FUNCTIONS
-----------------------------
-Functions that disable interrupts (LOCK equivalent) and enable interrupts
-(UNLOCK equivalent) will act as compiler barriers only. So if memory or I/O
+Functions that disable interrupts (ACQUIRE equivalent) and enable interrupts
+(RELEASE equivalent) will act as compiler barriers only. So if memory or I/O
barriers are required in such a situation, they must be provided from some
other means.
@@ -1436,24 +1439,24 @@ Consider the following: the system has a
CPU 1 CPU 2
=============================== ===============================
*A = a; *E = e;
- LOCK M LOCK Q
+ ACQUIRE M ACQUIRE Q
*B = b; *F = f;
*C = c; *G = g;
- UNLOCK M UNLOCK Q
+ RELEASE M RELEASE Q
*D = d; *H = h;
Then there is no guarantee as to what order CPU 3 will see the accesses to *A
through *H occur in, other than the constraints imposed by the separate locks
on the separate CPUs. It might, for example, see:
- *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
+ *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
But it won't see any of:
- *B, *C or *D preceding LOCK M
- *A, *B or *C following UNLOCK M
- *F, *G or *H preceding LOCK Q
- *E, *F or *G following UNLOCK Q
+ *B, *C or *D preceding ACQUIRE M
+ *A, *B or *C following RELEASE M
+ *F, *G or *H preceding ACQUIRE Q
+ *E, *F or *G following RELEASE Q
However, if the following occurs:
@@ -1461,28 +1464,28 @@ through *H occur in, other than the cons
CPU 1 CPU 2
=============================== ===============================
*A = a;
- LOCK M [1]
+ ACQUIRE M [1]
*B = b;
*C = c;
- UNLOCK M [1]
+ RELEASE M [1]
*D = d; *E = e;
- LOCK M [2]
+ ACQUIRE M [2]
*F = f;
*G = g;
- UNLOCK M [2]
+ RELEASE M [2]
*H = h;
CPU 3 might see:
- *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
- LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
+ *E, ACQUIRE M [1], *C, *B, *A, RELEASE M [1],
+ ACQUIRE M [2], *H, *F, *G, RELEASE M [2], *D
But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
- *B, *C, *D, *F, *G or *H preceding LOCK M [1]
- *A, *B or *C following UNLOCK M [1]
- *F, *G or *H preceding LOCK M [2]
- *A, *B, *C, *E, *F or *G following UNLOCK M [2]
+ *B, *C, *D, *F, *G or *H preceding ACQUIRE M [1]
+ *A, *B or *C following RELEASE M [1]
+ *F, *G or *H preceding ACQUIRE M [2]
+ *A, *B, *C, *E, *F or *G following RELEASE M [2]
LOCKS VS I/O ACCESSES
@@ -1702,13 +1705,13 @@ about the state (old or new) implies an
test_and_clear_bit();
test_and_change_bit();
-These are used for such things as implementing LOCK-class and UNLOCK-class
+These are used for such things as implementing ACQUIRE-class and RELEASE-class
operations and adjusting reference counters towards object destruction, and as
such the implicit memory barrier effects are necessary.
The following operations are potential problems as they do _not_ imply memory
-barriers, but might be used for implementing such things as UNLOCK-class
+barriers, but might be used for implementing such things as RELEASE-class
operations:
atomic_set();
@@ -1750,9 +1753,9 @@ barriers are needed or not.
clear_bit_unlock();
__clear_bit_unlock();
-These implement LOCK-class and UNLOCK-class operations. These should be used in
-preference to other operations when implementing locking primitives, because
-their implementations can be optimised on many architectures.
+These implement ACQUIRE-class and RELEASE-class operations. These should be
+used in preference to other operations when implementing locking primitives,
+because their implementations can be optimised on many architectures.
[!] Note that special memory barrier primitives are available for these
situations because on some CPUs the atomic instructions used imply full memory
--- a/arch/alpha/include/asm/barrier.h
+++ b/arch/alpha/include/asm/barrier.h
@@ -29,6 +29,21 @@ __asm__ __volatile__("mb": : :"memory")
#define smp_read_barrier_depends() do { } while (0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#define set_mb(var, value) \
do { var = value; mb(); } while (0)
--- a/arch/arc/include/asm/barrier.h
+++ b/arch/arc/include/asm/barrier.h
@@ -30,6 +30,21 @@
#define smp_wmb() barrier()
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
#define smp_mb__before_atomic_inc() barrier()
--- a/arch/arm/include/asm/barrier.h
+++ b/arch/arm/include/asm/barrier.h
@@ -59,6 +59,21 @@
#define smp_wmb() dmb(ishst)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -35,11 +35,59 @@
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#else
+
#define smp_mb() asm volatile("dmb ish" : : : "memory")
#define smp_rmb() asm volatile("dmb ishld" : : : "memory")
#define smp_wmb() asm volatile("dmb ishst" : : : "memory")
-#endif
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("stlr %w1, [%0]" \
+ : "=Q" (*p) : "r" (v) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("stlr %1, [%0]" \
+ : "=Q" (*p) : "r" (v) : "memory"); \
+ break; \
+ } \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1; \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("ldar %w0, [%1]" \
+ : "=r" (___p1) : "Q" (*p) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("ldar %0, [%1]" \
+ : "=r" (___p1) : "Q" (*p) : "memory"); \
+ break; \
+ } \
+ ___p1; \
+})
#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)
--- a/arch/avr32/include/asm/barrier.h
+++ b/arch/avr32/include/asm/barrier.h
@@ -25,5 +25,19 @@
# define smp_read_barrier_depends() do { } while(0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
#endif /* __ASM_AVR32_BARRIER_H */
--- a/arch/blackfin/include/asm/barrier.h
+++ b/arch/blackfin/include/asm/barrier.h
@@ -45,4 +45,19 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define smp_read_barrier_depends() read_barrier_depends()
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _BLACKFIN_BARRIER_H */
--- a/arch/cris/include/asm/barrier.h
+++ b/arch/cris/include/asm/barrier.h
@@ -22,4 +22,19 @@
#define smp_read_barrier_depends() do { } while(0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __ASM_CRIS_BARRIER_H */
--- a/arch/frv/include/asm/barrier.h
+++ b/arch/frv/include/asm/barrier.h
@@ -26,4 +26,19 @@
#define set_mb(var, value) \
do { var = (value); barrier(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_BARRIER_H */
--- a/arch/h8300/include/asm/barrier.h
+++ b/arch/h8300/include/asm/barrier.h
@@ -26,4 +26,19 @@
#define smp_read_barrier_depends() do { } while(0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _H8300_BARRIER_H */
--- a/arch/hexagon/include/asm/barrier.h
+++ b/arch/hexagon/include/asm/barrier.h
@@ -38,4 +38,19 @@
#define set_mb(var, value) \
do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_BARRIER_H */
--- a/arch/ia64/include/asm/barrier.h
+++ b/arch/ia64/include/asm/barrier.h
@@ -45,11 +45,60 @@
# define smp_rmb() rmb()
# define smp_wmb() wmb()
# define smp_read_barrier_depends() read_barrier_depends()
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("st4.rel [%0]=%1" \
+ : "=r" (p) : "r" (v) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("st8.rel [%0]=%1" \
+ : "=r" (p) : "r" (v) : "memory"); \
+ break; \
+ } \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1; \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("ld4.acq %0=[%1]" \
+ : "=r" (___p1) : "r" (p) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("ld8.acq %0=[%1]" \
+ : "=r" (___p1) : "r" (p) : "memory"); \
+ break; \
+ } \
+ ___p1; \
+})
+
#else
+
# define smp_mb() barrier()
# define smp_rmb() barrier()
# define smp_wmb() barrier()
# define smp_read_barrier_depends() do { } while(0)
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
#endif
/*
--- a/arch/m32r/include/asm/barrier.h
+++ b/arch/m32r/include/asm/barrier.h
@@ -91,4 +91,19 @@
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_M32R_BARRIER_H */
--- a/arch/m68k/include/asm/barrier.h
+++ b/arch/m68k/include/asm/barrier.h
@@ -17,4 +17,19 @@
#define smp_wmb() barrier()
#define smp_read_barrier_depends() ((void)0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _M68K_BARRIER_H */
--- a/arch/metag/include/asm/barrier.h
+++ b/arch/metag/include/asm/barrier.h
@@ -82,4 +82,19 @@ static inline void fence(void)
#define smp_read_barrier_depends() do { } while (0)
#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_METAG_BARRIER_H */
--- a/arch/microblaze/include/asm/barrier.h
+++ b/arch/microblaze/include/asm/barrier.h
@@ -24,4 +24,19 @@
#define smp_rmb() rmb()
#define smp_wmb() wmb()
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_MICROBLAZE_BARRIER_H */
--- a/arch/mips/include/asm/barrier.h
+++ b/arch/mips/include/asm/barrier.h
@@ -180,4 +180,19 @@
#define nudge_writes() mb()
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __ASM_BARRIER_H */
--- a/arch/mn10300/include/asm/barrier.h
+++ b/arch/mn10300/include/asm/barrier.h
@@ -34,4 +34,19 @@
#define read_barrier_depends() do {} while (0)
#define smp_read_barrier_depends() do {} while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_BARRIER_H */
--- a/arch/parisc/include/asm/barrier.h
+++ b/arch/parisc/include/asm/barrier.h
@@ -32,4 +32,19 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __PARISC_BARRIER_H */
--- a/arch/powerpc/include/asm/barrier.h
+++ b/arch/powerpc/include/asm/barrier.h
@@ -45,11 +45,15 @@
# define SMPWMB eieio
#endif
+#define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+
#define smp_mb() mb()
-#define smp_rmb() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_rmb() __lwsync()
#define smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
#define smp_read_barrier_depends() read_barrier_depends()
#else
+#define __lwsync() barrier()
+
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
@@ -65,4 +69,19 @@
#define data_barrier(x) \
asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ __lwsync(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ __lwsync(); \
+ ___p1; \
+})
+
#endif /* _ASM_POWERPC_BARRIER_H */
--- a/arch/s390/include/asm/barrier.h
+++ b/arch/s390/include/asm/barrier.h
@@ -32,4 +32,19 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
#endif /* __ASM_BARRIER_H */
--- a/arch/score/include/asm/barrier.h
+++ b/arch/score/include/asm/barrier.h
@@ -13,4 +13,19 @@
#define set_mb(var, value) do {var = value; wmb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_SCORE_BARRIER_H */
--- a/arch/sh/include/asm/barrier.h
+++ b/arch/sh/include/asm/barrier.h
@@ -51,4 +51,19 @@
#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __ASM_SH_BARRIER_H */
--- a/arch/sparc/include/asm/barrier_32.h
+++ b/arch/sparc/include/asm/barrier_32.h
@@ -12,4 +12,19 @@
#define smp_wmb() __asm__ __volatile__("":::"memory")
#define smp_read_barrier_depends() do { } while(0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* !(__SPARC_BARRIER_H) */
--- a/arch/sparc/include/asm/barrier_64.h
+++ b/arch/sparc/include/asm/barrier_64.h
@@ -53,4 +53,19 @@ do { __asm__ __volatile__("ba,pt %%xcc,
#define smp_read_barrier_depends() do { } while(0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
#endif /* !(__SPARC64_BARRIER_H) */
--- a/arch/tile/include/asm/barrier.h
+++ b/arch/tile/include/asm/barrier.h
@@ -140,5 +140,20 @@ mb_incoherent(void)
#define set_mb(var, value) \
do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_TILE_BARRIER_H */
--- a/arch/unicore32/include/asm/barrier.h
+++ b/arch/unicore32/include/asm/barrier.h
@@ -25,4 +25,19 @@
#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __UNICORE_BARRIER_H__ */
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -100,6 +100,21 @@
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
/*
* Stop RDTSC speculation. This is needed when you need to use RDTSC
* (or get_cycles or vread that possibly accesses the TSC) in a defined
--- a/arch/xtensa/include/asm/barrier.h
+++ b/arch/xtensa/include/asm/barrier.h
@@ -26,4 +26,19 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _XTENSA_SYSTEM_H */
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -298,6 +298,11 @@ void ftrace_likely_update(struct ftrace_
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
+/* Is this type a native word size -- useful for atomic operations */
+#ifndef __native_word
+# define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+#endif
+
/* Compile time object size, -1 for unknown */
#ifndef __compiletime_object_size
# define __compiletime_object_size(obj) -1
@@ -337,6 +342,10 @@ void ftrace_likely_update(struct ftrace_
#define compiletime_assert(condition, msg) \
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
+#define compiletime_assert_atomic_type(t) \
+ compiletime_assert(__native_word(t), \
+ "Need native word sized stores/loads for atomicity.")
+
/*
* Prevent the compiler from merging or refetching accesses. The compiler
* is also forbidden from reordering successive instances of ACCESS_ONCE(),
^ permalink raw reply
* Re: [RFC] arch: Introduce new TSO memory barrier smp_tmb()
From: Geert Uytterhoeven @ 2013-11-06 12:51 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Michael Neuling, Tony Luck, Mathieu Desnoyers, Heiko Carstens,
Oleg Nesterov, LKML, Linux PPC dev, Anton Blanchard,
Frederic Weisbecker, Victor Kaplansky, Russell King,
Paul E. McKenney, Linus Torvalds, Martin Schwidefsky
In-Reply-To: <20131106123946.GJ10651@twins.programming.kicks-ass.net>
On Wed, Nov 6, 2013 at 1:39 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> Documentation/memory-barriers.txt | 157 +++++++++++++++++-----------------
> arch/alpha/include/asm/barrier.h | 15 +++
> arch/arc/include/asm/barrier.h | 15 +++
> arch/arm/include/asm/barrier.h | 15 +++
> arch/arm64/include/asm/barrier.h | 50 ++++++++++
> arch/avr32/include/asm/barrier.h | 14 +++
> arch/blackfin/include/asm/barrier.h | 15 +++
> arch/cris/include/asm/barrier.h | 15 +++
> arch/frv/include/asm/barrier.h | 15 +++
> arch/h8300/include/asm/barrier.h | 15 +++
> arch/hexagon/include/asm/barrier.h | 15 +++
> arch/ia64/include/asm/barrier.h | 49 ++++++++++
> arch/m32r/include/asm/barrier.h | 15 +++
> arch/m68k/include/asm/barrier.h | 15 +++
> arch/metag/include/asm/barrier.h | 15 +++
> arch/microblaze/include/asm/barrier.h | 15 +++
> arch/mips/include/asm/barrier.h | 15 +++
> arch/mn10300/include/asm/barrier.h | 15 +++
> arch/parisc/include/asm/barrier.h | 15 +++
> arch/powerpc/include/asm/barrier.h | 21 ++++
> arch/s390/include/asm/barrier.h | 15 +++
> arch/score/include/asm/barrier.h | 15 +++
> arch/sh/include/asm/barrier.h | 15 +++
> arch/sparc/include/asm/barrier_32.h | 15 +++
> arch/sparc/include/asm/barrier_64.h | 15 +++
> arch/tile/include/asm/barrier.h | 15 +++
> arch/unicore32/include/asm/barrier.h | 15 +++
> arch/x86/include/asm/barrier.h | 15 +++
> arch/xtensa/include/asm/barrier.h | 15 +++
> include/linux/compiler.h | 9 +
> 30 files changed, 581 insertions(+), 79 deletions(-)
This is screaming for a default implementation in asm-generic.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [RFC] arch: Introduce new TSO memory barrier smp_tmb()
From: Peter Zijlstra @ 2013-11-06 13:57 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michael Neuling, Tony Luck, Mathieu Desnoyers, Heiko Carstens,
Oleg Nesterov, LKML, Linux PPC dev, Anton Blanchard,
Frederic Weisbecker, Victor Kaplansky, Russell King,
Paul E. McKenney, Linus Torvalds, Martin Schwidefsky
In-Reply-To: <CAMuHMdXZjQJvT7R4ODbDNBgAVwPUBPjB6UoR66_sNuFx7opUDw@mail.gmail.com>
On Wed, Nov 06, 2013 at 01:51:10PM +0100, Geert Uytterhoeven wrote:
> This is screaming for a default implementation in asm-generic.
Right you are... how about a little something like this?
There's a few archs I didn't fully merge with the generic one because of
weird nop implementations.
asm volatile ("nop" :: ) vs asm volatile ("nop" ::: "memory") and the
like. They probably can (and should) use the regular asm volatile
("nop") but I misplaced the toolchains for many of the weird archs so I
didn't attempt.
Also fixed a silly mistake in the return type definition for most
smp_load_acquire() implementions: typeof(p) vs typeof(*p).
---
Subject: arch: Introduce smp_load_acquire(), smp_store_release()
From: Peter Zijlstra <peterz@infradead.org>
Date: Mon, 4 Nov 2013 20:18:11 +0100
A number of situations currently require the heavyweight smp_mb(),
even though there is no need to order prior stores against later
loads. Many architectures have much cheaper ways to handle these
situations, but the Linux kernel currently has no portable way
to make use of them.
This commit therefore supplies smp_load_acquire() and
smp_store_release() to remedy this situation. The new
smp_load_acquire() primitive orders the specified load against
any subsequent reads or writes, while the new smp_store_release()
primitive orders the specifed store against any prior reads or
writes. These primitives allow array-based circular FIFOs to be
implemented without an smp_mb(), and also allow a theoretical
hole in rcu_assign_pointer() to be closed at no additional
expense on most architectures.
In addition, the RCU experience transitioning from explicit
smp_read_barrier_depends() and smp_wmb() to rcu_dereference()
and rcu_assign_pointer(), respectively resulted in substantial
improvements in readability. It therefore seems likely that
replacing other explicit barriers with smp_load_acquire() and
smp_store_release() will provide similar benefits. It appears
that roughly half of the explicit barriers in core kernel code
might be so replaced.
Cc: Michael Ellerman <michael@ellerman.id.au>
Cc: Michael Neuling <mikey@neuling.org>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Victor Kaplansky <VICTORK@il.ibm.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
---
Documentation/memory-barriers.txt | 157 +++++++++++++++++-----------------
arch/alpha/include/asm/barrier.h | 25 +----
arch/arc/include/asm/Kbuild | 1
arch/arc/include/asm/atomic.h | 5 +
arch/arc/include/asm/barrier.h | 42 ---------
arch/arm/include/asm/barrier.h | 15 +++
arch/arm64/include/asm/barrier.h | 50 ++++++++++
arch/avr32/include/asm/barrier.h | 17 +--
arch/blackfin/include/asm/barrier.h | 18 ---
arch/cris/include/asm/Kbuild | 1
arch/cris/include/asm/barrier.h | 25 -----
arch/frv/include/asm/barrier.h | 8 -
arch/h8300/include/asm/barrier.h | 21 ----
arch/hexagon/include/asm/Kbuild | 1
arch/hexagon/include/asm/barrier.h | 41 --------
arch/ia64/include/asm/barrier.h | 49 ++++++++++
arch/m32r/include/asm/barrier.h | 80 -----------------
arch/m68k/include/asm/barrier.h | 14 ---
arch/metag/include/asm/barrier.h | 15 +++
arch/microblaze/include/asm/Kbuild | 1
arch/microblaze/include/asm/barrier.h | 27 -----
arch/mips/include/asm/barrier.h | 15 +++
arch/mn10300/include/asm/Kbuild | 1
arch/mn10300/include/asm/barrier.h | 37 --------
arch/parisc/include/asm/Kbuild | 1
arch/parisc/include/asm/barrier.h | 35 -------
arch/powerpc/include/asm/barrier.h | 21 ++++
arch/s390/include/asm/barrier.h | 15 +++
arch/score/include/asm/Kbuild | 1
arch/score/include/asm/barrier.h | 16 ---
arch/sh/include/asm/barrier.h | 21 ----
arch/sparc/include/asm/barrier_32.h | 11 --
arch/sparc/include/asm/barrier_64.h | 15 +++
arch/tile/include/asm/barrier.h | 68 --------------
arch/unicore32/include/asm/barrier.h | 11 --
arch/x86/include/asm/barrier.h | 15 +++
arch/xtensa/include/asm/barrier.h | 9 -
include/asm-generic/barrier.h | 55 +++++++++--
include/linux/compiler.h | 9 +
39 files changed, 375 insertions(+), 594 deletions(-)
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -371,33 +371,35 @@ VARIETIES OF MEMORY BARRIER
And a couple of implicit varieties:
- (5) LOCK operations.
+ (5) ACQUIRE operations.
This acts as a one-way permeable barrier. It guarantees that all memory
- operations after the LOCK operation will appear to happen after the LOCK
- operation with respect to the other components of the system.
+ operations after the ACQUIRE operation will appear to happen after the
+ ACQUIRE operation with respect to the other components of the system.
- Memory operations that occur before a LOCK operation may appear to happen
- after it completes.
+ Memory operations that occur before a ACQUIRE operation may appear to
+ happen after it completes.
- A LOCK operation should almost always be paired with an UNLOCK operation.
+ A ACQUIRE operation should almost always be paired with an RELEASE
+ operation.
- (6) UNLOCK operations.
+ (6) RELEASE operations.
This also acts as a one-way permeable barrier. It guarantees that all
- memory operations before the UNLOCK operation will appear to happen before
- the UNLOCK operation with respect to the other components of the system.
+ memory operations before the RELEASE operation will appear to happen
+ before the RELEASE operation with respect to the other components of the
+ system.
- Memory operations that occur after an UNLOCK operation may appear to
+ Memory operations that occur after an RELEASE operation may appear to
happen before it completes.
- LOCK and UNLOCK operations are guaranteed to appear with respect to each
- other strictly in the order specified.
+ ACQUIRE and RELEASE operations are guaranteed to appear with respect to
+ each other strictly in the order specified.
- The use of LOCK and UNLOCK operations generally precludes the need for
- other sorts of memory barrier (but note the exceptions mentioned in the
- subsection "MMIO write barrier").
+ The use of ACQUIRE and RELEASE operations generally precludes the need
+ for other sorts of memory barrier (but note the exceptions mentioned in
+ the subsection "MMIO write barrier").
Memory barriers are only required where there's a possibility of interaction
@@ -1135,7 +1137,7 @@ CPU from reordering them.
clear_bit( ... );
This prevents memory operations before the clear leaking to after it. See
- the subsection on "Locking Functions" with reference to UNLOCK operation
+ the subsection on "Locking Functions" with reference to RELEASE operation
implications.
See Documentation/atomic_ops.txt for more information. See the "Atomic
@@ -1181,65 +1183,66 @@ LOCKING FUNCTIONS
(*) R/W semaphores
(*) RCU
-In all cases there are variants on "LOCK" operations and "UNLOCK" operations
+In all cases there are variants on "ACQUIRE" operations and "RELEASE" operations
for each construct. These operations all imply certain barriers:
- (1) LOCK operation implication:
+ (1) ACQUIRE operation implication:
- Memory operations issued after the LOCK will be completed after the LOCK
- operation has completed.
+ Memory operations issued after the ACQUIRE will be completed after the
+ ACQUIRE operation has completed.
- Memory operations issued before the LOCK may be completed after the LOCK
- operation has completed.
+ Memory operations issued before the ACQUIRE may be completed after the
+ ACQUIRE operation has completed.
- (2) UNLOCK operation implication:
+ (2) RELEASE operation implication:
- Memory operations issued before the UNLOCK will be completed before the
- UNLOCK operation has completed.
+ Memory operations issued before the RELEASE will be completed before the
+ RELEASE operation has completed.
- Memory operations issued after the UNLOCK may be completed before the
- UNLOCK operation has completed.
+ Memory operations issued after the RELEASE may be completed before the
+ RELEASE operation has completed.
- (3) LOCK vs LOCK implication:
+ (3) ACQUIRE vs ACQUIRE implication:
- All LOCK operations issued before another LOCK operation will be completed
- before that LOCK operation.
+ All ACQUIRE operations issued before another ACQUIRE operation will be
+ completed before that ACQUIRE operation.
- (4) LOCK vs UNLOCK implication:
+ (4) ACQUIRE vs RELEASE implication:
- All LOCK operations issued before an UNLOCK operation will be completed
- before the UNLOCK operation.
+ All ACQUIRE operations issued before an RELEASE operation will be
+ completed before the RELEASE operation.
- All UNLOCK operations issued before a LOCK operation will be completed
- before the LOCK operation.
+ All RELEASE operations issued before a ACQUIRE operation will be
+ completed before the ACQUIRE operation.
- (5) Failed conditional LOCK implication:
+ (5) Failed conditional ACQUIRE implication:
- Certain variants of the LOCK operation may fail, either due to being
+ Certain variants of the ACQUIRE operation may fail, either due to being
unable to get the lock immediately, or due to receiving an unblocked
signal whilst asleep waiting for the lock to become available. Failed
locks do not imply any sort of barrier.
-Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
-equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
+Therefore, from (1), (2) and (4) an RELEASE followed by an unconditional
+ACQUIRE is equivalent to a full barrier, but a ACQUIRE followed by an RELEASE
+is not.
[!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
barriers is that the effects of instructions outside of a critical section
may seep into the inside of the critical section.
-A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
-because it is possible for an access preceding the LOCK to happen after the
-LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
-two accesses can themselves then cross:
+A ACQUIRE followed by an RELEASE may not be assumed to be full memory barrier
+because it is possible for an access preceding the ACQUIRE to happen after the
+ACQUIRE, and an access following the RELEASE to happen before the RELEASE, and
+the two accesses can themselves then cross:
*A = a;
- LOCK
- UNLOCK
+ ACQUIRE
+ RELEASE
*B = b;
may occur as:
- LOCK, STORE *B, STORE *A, UNLOCK
+ ACQUIRE, STORE *B, STORE *A, RELEASE
Locks and semaphores may not provide any guarantee of ordering on UP compiled
systems, and so cannot be counted on in such a situation to actually achieve
@@ -1253,33 +1256,33 @@ See also the section on "Inter-CPU locki
*A = a;
*B = b;
- LOCK
+ ACQUIRE
*C = c;
*D = d;
- UNLOCK
+ RELEASE
*E = e;
*F = f;
The following sequence of events is acceptable:
- LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
+ ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
[+] Note that {*F,*A} indicates a combined access.
But none of the following are:
- {*F,*A}, *B, LOCK, *C, *D, UNLOCK, *E
- *A, *B, *C, LOCK, *D, UNLOCK, *E, *F
- *A, *B, LOCK, *C, UNLOCK, *D, *E, *F
- *B, LOCK, *C, *D, UNLOCK, {*F,*A}, *E
+ {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E
+ *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F
+ *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F
+ *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E
INTERRUPT DISABLING FUNCTIONS
-----------------------------
-Functions that disable interrupts (LOCK equivalent) and enable interrupts
-(UNLOCK equivalent) will act as compiler barriers only. So if memory or I/O
+Functions that disable interrupts (ACQUIRE equivalent) and enable interrupts
+(RELEASE equivalent) will act as compiler barriers only. So if memory or I/O
barriers are required in such a situation, they must be provided from some
other means.
@@ -1436,24 +1439,24 @@ Consider the following: the system has a
CPU 1 CPU 2
=============================== ===============================
*A = a; *E = e;
- LOCK M LOCK Q
+ ACQUIRE M ACQUIRE Q
*B = b; *F = f;
*C = c; *G = g;
- UNLOCK M UNLOCK Q
+ RELEASE M RELEASE Q
*D = d; *H = h;
Then there is no guarantee as to what order CPU 3 will see the accesses to *A
through *H occur in, other than the constraints imposed by the separate locks
on the separate CPUs. It might, for example, see:
- *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
+ *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
But it won't see any of:
- *B, *C or *D preceding LOCK M
- *A, *B or *C following UNLOCK M
- *F, *G or *H preceding LOCK Q
- *E, *F or *G following UNLOCK Q
+ *B, *C or *D preceding ACQUIRE M
+ *A, *B or *C following RELEASE M
+ *F, *G or *H preceding ACQUIRE Q
+ *E, *F or *G following RELEASE Q
However, if the following occurs:
@@ -1461,28 +1464,28 @@ through *H occur in, other than the cons
CPU 1 CPU 2
=============================== ===============================
*A = a;
- LOCK M [1]
+ ACQUIRE M [1]
*B = b;
*C = c;
- UNLOCK M [1]
+ RELEASE M [1]
*D = d; *E = e;
- LOCK M [2]
+ ACQUIRE M [2]
*F = f;
*G = g;
- UNLOCK M [2]
+ RELEASE M [2]
*H = h;
CPU 3 might see:
- *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
- LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
+ *E, ACQUIRE M [1], *C, *B, *A, RELEASE M [1],
+ ACQUIRE M [2], *H, *F, *G, RELEASE M [2], *D
But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
- *B, *C, *D, *F, *G or *H preceding LOCK M [1]
- *A, *B or *C following UNLOCK M [1]
- *F, *G or *H preceding LOCK M [2]
- *A, *B, *C, *E, *F or *G following UNLOCK M [2]
+ *B, *C, *D, *F, *G or *H preceding ACQUIRE M [1]
+ *A, *B or *C following RELEASE M [1]
+ *F, *G or *H preceding ACQUIRE M [2]
+ *A, *B, *C, *E, *F or *G following RELEASE M [2]
LOCKS VS I/O ACCESSES
@@ -1702,13 +1705,13 @@ about the state (old or new) implies an
test_and_clear_bit();
test_and_change_bit();
-These are used for such things as implementing LOCK-class and UNLOCK-class
+These are used for such things as implementing ACQUIRE-class and RELEASE-class
operations and adjusting reference counters towards object destruction, and as
such the implicit memory barrier effects are necessary.
The following operations are potential problems as they do _not_ imply memory
-barriers, but might be used for implementing such things as UNLOCK-class
+barriers, but might be used for implementing such things as RELEASE-class
operations:
atomic_set();
@@ -1750,9 +1753,9 @@ barriers are needed or not.
clear_bit_unlock();
__clear_bit_unlock();
-These implement LOCK-class and UNLOCK-class operations. These should be used in
-preference to other operations when implementing locking primitives, because
-their implementations can be optimised on many architectures.
+These implement ACQUIRE-class and RELEASE-class operations. These should be
+used in preference to other operations when implementing locking primitives,
+because their implementations can be optimised on many architectures.
[!] Note that special memory barrier primitives are available for these
situations because on some CPUs the atomic instructions used imply full memory
--- a/arch/alpha/include/asm/barrier.h
+++ b/arch/alpha/include/asm/barrier.h
@@ -3,33 +3,18 @@
#include <asm/compiler.h>
-#define mb() \
-__asm__ __volatile__("mb": : :"memory")
+#define mb() __asm__ __volatile__("mb": : :"memory")
+#define rmb() __asm__ __volatile__("mb": : :"memory")
+#define wmb() __asm__ __volatile__("wmb": : :"memory")
-#define rmb() \
-__asm__ __volatile__("mb": : :"memory")
-
-#define wmb() \
-__asm__ __volatile__("wmb": : :"memory")
-
-#define read_barrier_depends() \
-__asm__ __volatile__("mb": : :"memory")
+#define read_barrier_depends() __asm__ __volatile__("mb": : :"memory")
#ifdef CONFIG_SMP
#define __ASM_SMP_MB "\tmb\n"
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
#else
#define __ASM_SMP_MB
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
#endif
-#define set_mb(var, value) \
-do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
#endif /* __BARRIER_H */
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += user.h
generic-y += vga.h
generic-y += xor.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -190,6 +190,11 @@ static inline void atomic_clear_mask(uns
#endif /* !CONFIG_ARC_HAS_LLSC */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
/**
* __atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
--- a/arch/arc/include/asm/barrier.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * 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.
- */
-
-#ifndef __ASM_BARRIER_H
-#define __ASM_BARRIER_H
-
-#ifndef __ASSEMBLY__
-
-/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#define rmb() mb()
-#define wmb() mb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-#define read_barrier_depends() mb()
-
-/* TODO-vineetg verify the correctness of macros here */
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#endif
-
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#define smp_read_barrier_depends() do { } while (0)
-
-#endif
-
-#endif
--- a/arch/arm/include/asm/barrier.h
+++ b/arch/arm/include/asm/barrier.h
@@ -59,6 +59,21 @@
#define smp_wmb() dmb(ishst)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -35,11 +35,59 @@
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#else
+
#define smp_mb() asm volatile("dmb ish" : : : "memory")
#define smp_rmb() asm volatile("dmb ishld" : : : "memory")
#define smp_wmb() asm volatile("dmb ishst" : : : "memory")
-#endif
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("stlr %w1, [%0]" \
+ : "=Q" (*p) : "r" (v) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("stlr %1, [%0]" \
+ : "=Q" (*p) : "r" (v) : "memory"); \
+ break; \
+ } \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1; \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("ldar %w0, [%1]" \
+ : "=r" (___p1) : "Q" (*p) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("ldar %0, [%1]" \
+ : "=r" (___p1) : "Q" (*p) : "memory"); \
+ break; \
+ } \
+ ___p1; \
+})
#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)
--- a/arch/avr32/include/asm/barrier.h
+++ b/arch/avr32/include/asm/barrier.h
@@ -8,22 +8,15 @@
#ifndef __ASM_AVR32_BARRIER_H
#define __ASM_AVR32_BARRIER_H
-#define nop() asm volatile("nop")
-
-#define mb() asm volatile("" : : : "memory")
-#define rmb() mb()
-#define wmb() asm volatile("sync 0" : : : "memory")
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value) do { var = value; mb(); } while(0)
+/*
+ * Weirdest thing ever.. no full barrier, but it has a write barrier!
+ */
+#define wmb() asm volatile("sync 0" : : : "memory")
#ifdef CONFIG_SMP
# error "The AVR32 port does not support SMP"
-#else
-# define smp_mb() barrier()
-# define smp_rmb() barrier()
-# define smp_wmb() barrier()
-# define smp_read_barrier_depends() do { } while(0)
#endif
+#include <asm-generic/barrier.h>
#endif /* __ASM_AVR32_BARRIER_H */
--- a/arch/blackfin/include/asm/barrier.h
+++ b/arch/blackfin/include/asm/barrier.h
@@ -23,26 +23,10 @@
# define rmb() do { barrier(); smp_check_barrier(); } while (0)
# define wmb() do { barrier(); smp_mark_barrier(); } while (0)
# define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0)
-#else
-# define mb() barrier()
-# define rmb() barrier()
-# define wmb() barrier()
-# define read_barrier_depends() do { } while (0)
#endif
-#else /* !CONFIG_SMP */
-
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define read_barrier_depends() do { } while (0)
-
#endif /* !CONFIG_SMP */
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define smp_read_barrier_depends() read_barrier_depends()
+#include <asm-generic/barrier.h>
#endif /* _BLACKFIN_BARRIER_H */
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += trace_clock.h
generic-y += vga.h
generic-y += xor.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/cris/include/asm/barrier.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __ASM_CRIS_BARRIER_H
-#define __ASM_CRIS_BARRIER_H
-
-#define nop() __asm__ __volatile__ ("nop");
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#endif /* __ASM_CRIS_BARRIER_H */
--- a/arch/frv/include/asm/barrier.h
+++ b/arch/frv/include/asm/barrier.h
@@ -17,13 +17,7 @@
#define mb() asm volatile ("membar" : : :"memory")
#define rmb() asm volatile ("membar" : : :"memory")
#define wmb() asm volatile ("membar" : : :"memory")
-#define read_barrier_depends() do { } while (0)
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do {} while(0)
-#define set_mb(var, value) \
- do { var = (value); barrier(); } while (0)
+#include <asm-generic/barrier.h>
#endif /* _ASM_BARRIER_H */
--- a/arch/h8300/include/asm/barrier.h
+++ b/arch/h8300/include/asm/barrier.h
@@ -3,27 +3,8 @@
#define nop() asm volatile ("nop"::)
-/*
- * Force strict CPU ordering.
- * Not really required on H8...
- */
-#define mb() asm volatile ("" : : :"memory")
-#define rmb() asm volatile ("" : : :"memory")
-#define wmb() asm volatile ("" : : :"memory")
#define set_mb(var, value) do { xchg(&var, value); } while (0)
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
-#endif
+#include <asm-generic/barrier.h>
#endif /* _H8300_BARRIER_H */
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -54,3 +54,4 @@ generic-y += ucontext.h
generic-y += unaligned.h
generic-y += xor.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/hexagon/include/asm/barrier.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Memory barrier definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, The Linux Foundation. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_BARRIER_H
-#define _ASM_BARRIER_H
-
-#define rmb() barrier()
-#define read_barrier_depends() barrier()
-#define wmb() barrier()
-#define mb() barrier()
-#define smp_rmb() barrier()
-#define smp_read_barrier_depends() barrier()
-#define smp_wmb() barrier()
-#define smp_mb() barrier()
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-/* Set a value and use a memory barrier. Used by the scheduler somewhere. */
-#define set_mb(var, value) \
- do { var = value; mb(); } while (0)
-
-#endif /* _ASM_BARRIER_H */
--- a/arch/ia64/include/asm/barrier.h
+++ b/arch/ia64/include/asm/barrier.h
@@ -45,11 +45,60 @@
# define smp_rmb() rmb()
# define smp_wmb() wmb()
# define smp_read_barrier_depends() read_barrier_depends()
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("st4.rel [%0]=%1" \
+ : "=r" (p) : "r" (v) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("st8.rel [%0]=%1" \
+ : "=r" (p) : "r" (v) : "memory"); \
+ break; \
+ } \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1; \
+ compiletime_assert_atomic_type(*p); \
+ switch (sizeof(*p)) { \
+ case 4: \
+ asm volatile ("ld4.acq %0=[%1]" \
+ : "=r" (___p1) : "r" (p) : "memory"); \
+ break; \
+ case 8: \
+ asm volatile ("ld8.acq %0=[%1]" \
+ : "=r" (___p1) : "r" (p) : "memory"); \
+ break; \
+ } \
+ ___p1; \
+})
+
#else
+
# define smp_mb() barrier()
# define smp_rmb() barrier()
# define smp_wmb() barrier()
# define smp_read_barrier_depends() do { } while(0)
+
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
#endif
/*
--- a/arch/m32r/include/asm/barrier.h
+++ b/arch/m32r/include/asm/barrier.h
@@ -11,84 +11,6 @@
#define nop() __asm__ __volatile__ ("nop" : : )
-/*
- * Memory barrier.
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- */
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier. All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads. This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies. See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * b = 2;
- * memory_barrier();
- * p = &b; q = p;
- * read_barrier_depends();
- * d = *q;
- * </programlisting>
- *
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends(). However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * a = 2;
- * memory_barrier();
- * b = 3; y = b;
- * read_barrier_depends();
- * x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b". Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
+#include <asm-generic/barrier.h>
#endif /* _ASM_M32R_BARRIER_H */
--- a/arch/m68k/include/asm/barrier.h
+++ b/arch/m68k/include/asm/barrier.h
@@ -1,20 +1,8 @@
#ifndef _M68K_BARRIER_H
#define _M68K_BARRIER_H
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
#define nop() do { asm volatile ("nop"); barrier(); } while (0)
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value) ({ (var) = (value); wmb(); })
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() ((void)0)
+#include <asm-generic/barrier.h>
#endif /* _M68K_BARRIER_H */
--- a/arch/metag/include/asm/barrier.h
+++ b/arch/metag/include/asm/barrier.h
@@ -82,4 +82,19 @@ static inline void fence(void)
#define smp_read_barrier_depends() do { } while (0)
#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* _ASM_METAG_BARRIER_H */
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -4,3 +4,4 @@ generic-y += exec.h
generic-y += trace_clock.h
generic-y += syscalls.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/microblaze/include/asm/barrier.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_BARRIER_H
-#define _ASM_MICROBLAZE_BARRIER_H
-
-#define nop() asm volatile ("nop")
-
-#define smp_read_barrier_depends() do {} while (0)
-#define read_barrier_depends() do {} while (0)
-
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-
-#endif /* _ASM_MICROBLAZE_BARRIER_H */
--- a/arch/mips/include/asm/barrier.h
+++ b/arch/mips/include/asm/barrier.h
@@ -180,4 +180,19 @@
#define nudge_writes() mb()
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
+
#endif /* __ASM_BARRIER_H */
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/mn10300/include/asm/barrier.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* MN10300 memory barrier definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_BARRIER_H
-#define _ASM_BARRIER_H
-
-#define nop() asm volatile ("nop")
-
-#define mb() asm volatile ("": : :"memory")
-#define rmb() mb()
-#define wmb() asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-#else /* CONFIG_SMP */
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#endif /* CONFIG_SMP */
-
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends() do {} while (0)
-#define smp_read_barrier_depends() do {} while (0)
-
-#endif /* _ASM_BARRIER_H */
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -5,3 +5,4 @@ generic-y += word-at-a-time.h auxvec.h u
poll.h xor.h clkdev.h exec.h
generic-y += trace_clock.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/parisc/include/asm/barrier.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __PARISC_BARRIER_H
-#define __PARISC_BARRIER_H
-
-/*
-** This is simply the barrier() macro from linux/kernel.h but when serial.c
-** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
-** hasn't yet been included yet so it fails, thus repeating the macro here.
-**
-** PA-RISC architecture allows for weakly ordered memory accesses although
-** none of the processors use it. There is a strong ordered bit that is
-** set in the O-bit of the page directory entry. Operating systems that
-** can not tolerate out of order accesses should set this bit when mapping
-** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
-** of the processor implemented the PSW O-bit). The PCX-W ERS states that
-** the TLB O-bit is not implemented so the page directory does not need to
-** have the O-bit set when mapping pages (section 3.1). This section also
-** states that the PSW Y, Z, G, and O bits are not implemented.
-** So it looks like nothing needs to be done for parisc-linux (yet).
-** (thanks to chada for the above comment -ggg)
-**
-** The __asm__ op below simple prevents gcc/ld from reordering
-** instructions across the mb() "call".
-*/
-#define mb() __asm__ __volatile__("":::"memory") /* barrier() */
-#define rmb() mb()
-#define wmb() mb()
-#define smp_mb() mb()
-#define smp_rmb() mb()
-#define smp_wmb() mb()
-#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-
-#endif /* __PARISC_BARRIER_H */
--- a/arch/powerpc/include/asm/barrier.h
+++ b/arch/powerpc/include/asm/barrier.h
@@ -45,11 +45,15 @@
# define SMPWMB eieio
#endif
+#define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+
#define smp_mb() mb()
-#define smp_rmb() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_rmb() __lwsync()
#define smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
#define smp_read_barrier_depends() read_barrier_depends()
#else
+#define __lwsync() barrier()
+
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
@@ -65,4 +69,19 @@
#define data_barrier(x) \
asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ __lwsync(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ __lwsync(); \
+ ___p1; \
+})
+
#endif /* _ASM_POWERPC_BARRIER_H */
--- a/arch/s390/include/asm/barrier.h
+++ b/arch/s390/include/asm/barrier.h
@@ -32,4 +32,19 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
#endif /* __ASM_BARRIER_H */
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -5,3 +5,4 @@ generic-y += clkdev.h
generic-y += trace_clock.h
generic-y += xor.h
generic-y += preempt.h
+generic-y += barrier.h
--- a/arch/score/include/asm/barrier.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_SCORE_BARRIER_H
-#define _ASM_SCORE_BARRIER_H
-
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-
-#define read_barrier_depends() do {} while (0)
-#define smp_read_barrier_depends() do {} while (0)
-
-#define set_mb(var, value) do {var = value; wmb(); } while (0)
-
-#endif /* _ASM_SCORE_BARRIER_H */
--- a/arch/sh/include/asm/barrier.h
+++ b/arch/sh/include/asm/barrier.h
@@ -26,29 +26,14 @@
#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
#define mb() __asm__ __volatile__ ("synco": : :"memory")
#define rmb() mb()
-#define wmb() __asm__ __volatile__ ("synco": : :"memory")
+#define wmb() mb()
#define ctrl_barrier() __icbi(PAGE_OFFSET)
-#define read_barrier_depends() do { } while(0)
#else
-#define mb() __asm__ __volatile__ ("": : :"memory")
-#define rmb() mb()
-#define wmb() __asm__ __volatile__ ("": : :"memory")
#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
-#define read_barrier_depends() do { } while(0)
-#endif
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
#endif
#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#include <asm-generic/barrier.h>
+
#endif /* __ASM_SH_BARRIER_H */
--- a/arch/sparc/include/asm/barrier_32.h
+++ b/arch/sparc/include/asm/barrier_32.h
@@ -1,15 +1,6 @@
#ifndef __SPARC_BARRIER_H
#define __SPARC_BARRIER_H
-/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(__var, __value) do { __var = __value; mb(); } while(0)
-#define smp_mb() __asm__ __volatile__("":::"memory")
-#define smp_rmb() __asm__ __volatile__("":::"memory")
-#define smp_wmb() __asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends() do { } while(0)
+#include <asm-generic/barrier.h>
#endif /* !(__SPARC_BARRIER_H) */
--- a/arch/sparc/include/asm/barrier_64.h
+++ b/arch/sparc/include/asm/barrier_64.h
@@ -53,4 +53,19 @@ do { __asm__ __volatile__("ba,pt %%xcc,
#define smp_read_barrier_depends() do { } while(0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
#endif /* !(__SPARC64_BARRIER_H) */
--- a/arch/tile/include/asm/barrier.h
+++ b/arch/tile/include/asm/barrier.h
@@ -22,59 +22,6 @@
#include <arch/spr_def.h>
#include <asm/timex.h>
-/*
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier. All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads. This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies. See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * b = 2;
- * memory_barrier();
- * p = &b; q = p;
- * read_barrier_depends();
- * d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends(). However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * a = 2;
- * memory_barrier();
- * b = 3; y = b;
- * read_barrier_depends();
- * x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b". Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
- * in cases like this where there are no data dependencies.
- */
-#define read_barrier_depends() do { } while (0)
-
#define __sync() __insn_mf()
#include <hv/syscall_public.h>
@@ -125,20 +72,7 @@ mb_incoherent(void)
#define mb() fast_mb()
#define iob() fast_iob()
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
-#endif
-
-#define set_mb(var, value) \
- do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_TILE_BARRIER_H */
--- a/arch/unicore32/include/asm/barrier.h
+++ b/arch/unicore32/include/asm/barrier.h
@@ -14,15 +14,6 @@
#define dsb() __asm__ __volatile__ ("" : : : "memory")
#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define read_barrier_depends() do { } while (0)
-#define smp_read_barrier_depends() do { } while (0)
-
-#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
+#include <asm-generic/barrier.h>
#endif /* __UNICORE_BARRIER_H__ */
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -100,6 +100,21 @@
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
/*
* Stop RDTSC speculation. This is needed when you need to use RDTSC
* (or get_cycles or vread that possibly accesses the TSC) in a defined
--- a/arch/xtensa/include/asm/barrier.h
+++ b/arch/xtensa/include/asm/barrier.h
@@ -9,21 +9,14 @@
#ifndef _XTENSA_SYSTEM_H
#define _XTENSA_SYSTEM_H
-#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
#define mb() ({ __asm__ __volatile__("memw" : : : "memory"); })
#define rmb() barrier()
#define wmb() mb()
#ifdef CONFIG_SMP
#error smp_* not defined
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
#endif
-#define set_mb(var, value) do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
#endif /* _XTENSA_SYSTEM_H */
--- a/include/asm-generic/barrier.h
+++ b/include/asm-generic/barrier.h
@@ -1,4 +1,5 @@
-/* Generic barrier definitions, based on MN10300 definitions.
+/*
+ * Generic barrier definitions, based on MN10300 definitions.
*
* It should be possible to use these on really simple architectures,
* but it serves more as a starting point for new ports.
@@ -16,35 +17,67 @@
#ifndef __ASSEMBLY__
-#define nop() asm volatile ("nop")
+#include <asm/compiler.h>
+
+#ifndef nop
+#define nop() asm volatile ("nop")
+#endif
/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
+ * Force strict CPU ordering. And yes, this is required on UP too when we're
+ * talking to devices.
*
- * This implementation only contains a compiler barrier.
+ * Fall back to compiler barriers if nothing better is provided.
*/
-#define mb() asm volatile ("": : :"memory")
-#define rmb() mb()
-#define wmb() asm volatile ("": : :"memory")
+#ifndef mb
+#define mb() barrier()
+#endif
+
+#ifndef rmb
+#define rmb() barrier()
+#endif
+
+#ifndef wmb
+#define wmb() barrier()
+#endif
+
+#ifndef read_barrier_depends
+#define read_barrier_depends() do {} while (0)
+#endif
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
+#define smp_read_barrier_depends() read_barrier_depends()
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
+#define smp_read_barrier_depends() do {} while (0)
#endif
+#ifndef set_mb
#define set_mb(var, value) do { var = value; mb(); } while (0)
+#endif
+
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-#define read_barrier_depends() do {} while (0)
-#define smp_read_barrier_depends() do {} while (0)
+#define smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ACCESS_ONCE(*p) = (v); \
+} while (0)
+
+#define smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = ACCESS_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ smp_mb(); \
+ ___p1; \
+})
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_GENERIC_BARRIER_H */
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -298,6 +298,11 @@ void ftrace_likely_update(struct ftrace_
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
+/* Is this type a native word size -- useful for atomic operations */
+#ifndef __native_word
+# define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+#endif
+
/* Compile time object size, -1 for unknown */
#ifndef __compiletime_object_size
# define __compiletime_object_size(obj) -1
@@ -337,6 +342,10 @@ void ftrace_likely_update(struct ftrace_
#define compiletime_assert(condition, msg) \
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
+#define compiletime_assert_atomic_type(t) \
+ compiletime_assert(__native_word(t), \
+ "Need native word sized stores/loads for atomicity.")
+
/*
* Prevent the compiler from merging or refetching accesses. The compiler
* is also forbidden from reordering successive instances of ACCESS_ONCE(),
^ permalink raw reply
* Re: [RFC PATCH] ehci-platform: Merge ppc-of EHCI driver into the ehci-platform driver
From: Alan Stern @ 2013-11-06 16:14 UTC (permalink / raw)
To: Alistair Popple; +Cc: linux-usb, linuxppc-dev
In-Reply-To: <1690980.YlPWToa1rW@mexican>
On Wed, 6 Nov 2013, Alistair Popple wrote:
> Currently the ppc-of driver uses the compatibility string
> "usb-ehci". This means platforms that use device-tree and implement an
> EHCI compatible interface have to either use the ppc-of driver or add
> a compatible line to the ehci-platform driver. It would be more
> appropriate for the platform driver to be compatible with "usb-ehci"
> as non-powerpc platforms are also beginning to utilise device-tree.
>
> This patch merges the device tree property parsing from ehci-ppc-of
> into the platform driver and adds a "usb-ehci" compatibility
> string. The existing ehci-ppc-of driver is renamed to ehci-440epx as
> it contains platform specific work arounds for the 440EPX SoC.
>
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> ---
>
> So I could submit something like this that essentially merges the ppc-of
> driver into the platform driver instead of adding the "ibm,akebono-ehci"
> compatible line to the platform driver.
>
> However I'm still fairly new to device-tree so I'm not sure what (if any) the
> broader impact would be. A quick grep for "usb-ehci" turned up a couple of ARM
> device tree's using it however they all provided their own drivers and don't
> select CONFIG_USB_EHCI_HCD_PLATFORM so I'm guess they shouldn't be impacted.
>
> I have attempted to fix up any PowerPC device trees/configs, although I wasn't
> sure if "usb-ehci" should remain in sequoia.dts or not given that it needs to
> use the 440EPX specific driver.
>
> Also this hasn't been tested (beyond compilation) yet.
> diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-
> platform.c
> index f6b790c..027f368 100644
> --- a/drivers/usb/host/ehci-platform.c
> +++ b/drivers/usb/host/ehci-platform.c
> @@ -77,6 +77,7 @@ static int ehci_platform_probe(struct platform_device *dev)
> struct usb_hcd *hcd;
> struct resource *res_mem;
> struct usb_ehci_pdata *pdata;
> + struct device_node *dn = dev->dev.of_node;
> int irq;
> int err = -ENOMEM;
>
> @@ -96,6 +97,18 @@ static int ehci_platform_probe(struct platform_device *dev)
>
> pdata = dev_get_platdata(&dev->dev);
>
> + /* Initialise platform data from device tree if available. */
> + if (!dn) {
Shouldn't this be "if (dn)"?
> + if (of_get_property(dn, "big-endian", NULL)) {
> + pdata->big_endian_mmio = 1;
> + pdata->big_endian_desc = 1;
> + }
> + if (of_get_property(dn, "big-endian-regs", NULL))
> + pdata->big_endian_mmio = 1;
> + if (of_get_property(dn, "big-endian-desc", NULL))
> + pdata->big_endian_desc = 1;
> + }
> +
This isn't good if there is more than one EHCI controller using
ehci-platform. To accomodate such cases, it would be necessary to
allocate a separate copy of ehci_platform_defaults for each controller.
Alan Stern
^ permalink raw reply
* Re: [PATCH 3/7] IBM Akebono: Add support for a new PHY to the IBM emac driver
From: Ben Hutchings @ 2013-11-06 16:40 UTC (permalink / raw)
To: Alistair Popple; +Cc: linuxppc-dev, David S. Miller, netdev
In-Reply-To: <3555701.fBbreSn0Lp@mexican>
On Wed, 2013-11-06 at 12:34 +1100, Alistair Popple wrote:
> On Tue, 5 Nov 2013 23:11:50 Ben Hutchings wrote:
> > On Wed, 2013-11-06 at 06:54 +1100, Benjamin Herrenschmidt wrote:
>
> [snip]
>
> > > It's an SoC bit so there's little point making it generally
> > > selectable by the user.
> >
> > I think a better way to do this is:
> >
> > config IBM_EMAC_RGMII_WOL
> > bool "IBM EMAC RGMII wake-on-LAN support"
> > depends on MY_WONDERFUL_NEW_SOC || COMPILE_TEST
> > default y if MY_WONDERFUL_NEW_SOC
> >
> > Then anyone making an API change that affects this driver can check that
> > it still complies.
>
> The method used in this patch is the same as what is currently used by the
> other IBM EMAC PHY interfaces (eg. config IBM_EMAC_ZMII etc). I'm happy to
> send a patch to update all of those as well for consistency but that would
> mean adding what each platform requires into EMACS Kconfig as well.
>
> Personally I think it is nicer to keep the definitions of what each platform
> requires in one place (ie. arch/powerpc/platforms/44x/Kconfig) as it is
> consistent with what we do for other 44x drivers, however I am happy to use
> the above method if people think it's better.
Yes, I see your point.
> Alternatively we could do something like this:
>
> config IBM_EMAC_RGMII_WOL
> bool
> default y if COMPILE_TEST
> default n
>
> This would leave the platform dependencies as they are currently but still
> allow compile testing.
It still shouldn't default to y in that case. Instead you can make the
symbol conditionally configurable:
config IBM_EMAC_RGMII_WOL
bool "IBM EMAC RGMII wake-on-LAN support" if COMPILE_TEST
and then select this from your platform Kconfig as you intended.
(There is no need to put 'default n' as that's implicit for a
configurable symbol. But it doesn't hurt either.)
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH v3 1/1] powerpc/embedded6xx: Add support for Motorola/Emerson MVME5100
From: Alessio Igor Bogani @ 2013-11-06 15:49 UTC (permalink / raw)
To: Stephen Chivers; +Cc: linuxppc-dev
In-Reply-To: <20131103210748.E74FAE06C0@canberra.localdomain>
On lun, 2013-11-04 at 08:07 +1100, Stephen Chivers wrote:
> Add support for the Motorola/Emerson MVME5100 Single Board Computer.
>
> The MVME5100 is a 6U form factor VME64 computer with:
>
> - A single MPC7410 or MPC750 CPU
> - A HAWK Processor Host Bridge (CPU to PCI) and
> MultiProcessor Interrupt Controller (MPIC)
> - Up to 500Mb of onboard memory
> - A M48T37 Real Time Clock (RTC) and Non-Volatile Memory chip
> - Two 16550 compatible UARTS
> - Two Intel E100 Fast Ethernets
> - Two PCI Mezzanine Card (PMC) Slots
> - PPCBug Firmware
>
> The HAWK PHB/MPIC is compatible with the MPC10x devices.
>
> There is no onboard disk support. This is usually provided by
> installing a PMC in the first PMC slot.
>
> This patch revives the board support, it was present in early 2.6
> series kernels. The board support in those days was by Matt Porter of
> MontaVista Software.
>
> CSC Australia has around 31 of these boards in service. The kernel in use
> for the boards is based on 2.6.31. The boards are operated without disks
> from a file server.
>
> This patch is based on linux-3.12-rc7 and has been boot tested.
>
> V1->V2:
> Address comments by Kular Gama and Scott Wood.
> Minor adjustment to platforms/embedded6xx/Kconfig to ensure
> correct indentation where possible.
>
> V2->V3:
> Address comments by Scott Wood and Ben Herrenschmidt.
> Address errors reported by checkpatch.
>
> Signed-off-by: Stephen Chivers <schivers@csc.com>A
Tested-by: Alessio Igor Bogani <alessio.bogani@elettra.eu>
> ---
> arch/powerpc/boot/Makefile | 3 +-
> arch/powerpc/boot/dts/mvme5100.dts | 185 +++++++++++++++++++++
> arch/powerpc/boot/mvme5100.c | 27 +++
> arch/powerpc/boot/wrapper | 4 +
> arch/powerpc/configs/mvme5100_defconfig | 144 ++++++++++++++++
> arch/powerpc/platforms/embedded6xx/Kconfig | 13 ++-
> arch/powerpc/platforms/embedded6xx/Makefile | 1 +
> arch/powerpc/platforms/embedded6xx/mvme5100.c | 221 +++++++++++++++++++++++++
> 8 files changed, 596 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
> index 15ca225..a1c9c86 100644
> --- a/arch/powerpc/boot/Makefile
> +++ b/arch/powerpc/boot/Makefile
> @@ -94,7 +94,7 @@ src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c
> src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \
> cuboot-c2k.c gamecube-head.S \
> gamecube.c wii-head.S wii.c holly.c \
> - prpmc2800.c
> + prpmc2800.c fixed-head.S mvme5100.c
> src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
> src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
> src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c
> @@ -285,6 +285,7 @@ image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2
> image-$(CONFIG_PPC_C2K) += cuImage.c2k
> image-$(CONFIG_GAMECUBE) += dtbImage.gamecube
> image-$(CONFIG_WII) += dtbImage.wii
> +image-$(CONFIG_MVME5100) += dtbImage.mvme5100
>
> # Board port in arch/powerpc/platform/amigaone/Kconfig
> image-$(CONFIG_AMIGAONE) += cuImage.amigaone
> diff --git a/arch/powerpc/boot/dts/mvme5100.dts b/arch/powerpc/boot/dts/mvme5100.dts
> new file mode 100644
> index 0000000..4cb2f05
> --- /dev/null
> +++ b/arch/powerpc/boot/dts/mvme5100.dts
> @@ -0,0 +1,185 @@
> +/*
> + * Device Tree Souce for Motorola/Emerson MVME5100.
> + *
> + * Copyright 2013 CSC Australia Pty. Ltd.
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without
> + * any warranty of any kind, whether express or implied.
> + */
> +
> +/dts-v1/;
> +
> +/ {
> + model = "MVME5100";
> + compatible = "MVME5100";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + aliases {
> + serial0 = &serial0;
> + pci0 = &pci0;
> + };
> +
> + cpus {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + PowerPC,7410 {
> + device_type = "cpu";
> + reg = <0x0>;
> + /* Following required by dtc but not used */
> + d-cache-line-size = <32>;
> + i-cache-line-size = <32>;
> + i-cache-size = <32768>;
> + d-cache-size = <32768>;
> + timebase-frequency = <25000000>;
> + clock-frequency = <500000000>;
> + bus-frequency = <100000000>;
> + };
> + };
> +
> + memory {
> + device_type = "memory";
> + reg = <0x0 0x20000000>;
> + };
> +
> + hawk@fef80000 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "hawk-bridge", "simple-bus";
> + ranges = <0x0 0xfef80000 0x10000>;
> + reg = <0xfef80000 0x10000>;
> +
> + serial0: serial@8000 {
> + device_type = "serial";
> + compatible = "ns16550";
> + reg = <0x8000 0x80>;
> + reg-shift = <4>;
> + clock-frequency = <1843200>;
> + current-speed = <9600>;
> + interrupts = <1 1>; // IRQ1 Level Active Low.
> + interrupt-parent = <&mpic>;
> + };
> +
> + serial1: serial@8200 {
> + device_type = "serial";
> + compatible = "ns16550";
> + reg = <0x8200 0x80>;
> + reg-shift = <4>;
> + clock-frequency = <1843200>;
> + current-speed = <9600>;
> + interrupts = <1 1>; // IRQ1 Level Active Low.
> + interrupt-parent = <&mpic>;
> + };
> +
> + mpic: interrupt-controller@f3f80000 {
> + #interrupt-cells = <2>;
> + #address-cells = <0>;
> + device_type = "open-pic";
> + compatible = "chrp,open-pic";
> + interrupt-controller;
> + reg = <0xf3f80000 0x40000>;
> + };
> + };
> +
> + pci0: pci@feff0000 {
> + #address-cells = <3>;
> + #size-cells = <2>;
> + #interrupt-cells = <1>;
> + device_type = "pci";
> + compatible = "hawk-pci";
> + reg = <0xfec00000 0x400000>;
> + 8259-interrupt-acknowledge = <0xfeff0030>;
> + ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0x800000
> + 0x2000000 0x0 0x80000000 0x80000000 0x0 0x74000000>;
> + bus-range = <0 255>;
> + clock-frequency = <33333333>;
> + interrupt-parent = <&mpic>;
> + interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
> + interrupt-map = <
> +
> + /*
> + * This definition (IDSEL 11) duplicates the
> + * interrupts definition in the i8259
> + * interrupt controller below.
> + *
> + * Do not change the interrupt sense/polarity from
> + * 0x2 to anything else, doing so will cause endless
> + * "spurious" i8259 interrupts to be fielded.
> + */
> + // IDSEL 11 - iPMC712 PCI/ISA Bridge
> + 0x5800 0x0 0x0 0x1 &mpic 0x0 0x2
> + 0x5800 0x0 0x0 0x2 &mpic 0x0 0x2
> + 0x5800 0x0 0x0 0x3 &mpic 0x0 0x2
> + 0x5800 0x0 0x0 0x4 &mpic 0x0 0x2
> +
> + /* IDSEL 12 - Not Used */
> +
> + /* IDSEL 13 - Universe VME Bridge */
> + 0x6800 0x0 0x0 0x1 &mpic 0x5 0x1
> + 0x6800 0x0 0x0 0x2 &mpic 0x6 0x1
> + 0x6800 0x0 0x0 0x3 &mpic 0x7 0x1
> + 0x6800 0x0 0x0 0x4 &mpic 0x8 0x1
> +
> + /* IDSEL 14 - ENET 1 */
> + 0x7000 0x0 0x0 0x1 &mpic 0x2 0x1
> +
> + /* IDSEL 15 - Not Used */
> +
> + /* IDSEL 16 - PMC Slot 1 */
> + 0x8000 0x0 0x0 0x1 &mpic 0x9 0x1
> + 0x8000 0x0 0x0 0x2 &mpic 0xa 0x1
> + 0x8000 0x0 0x0 0x3 &mpic 0xb 0x1
> + 0x8000 0x0 0x0 0x4 &mpic 0xc 0x1
> +
> + /* IDSEL 17 - PMC Slot 2 */
> + 0x8800 0x0 0x0 0x1 &mpic 0xc 0x1
> + 0x8800 0x0 0x0 0x2 &mpic 0x9 0x1
> + 0x8800 0x0 0x0 0x3 &mpic 0xa 0x1
> + 0x8800 0x0 0x0 0x4 &mpic 0xb 0x1
> +
> + /* IDSEL 18 - Not Used */
> +
> + /* IDSEL 19 - ENET 2 */
> + 0x9800 0x0 0x0 0x1 &mpic 0xd 0x1
> +
> + /* IDSEL 20 - PMCSPAN (PCI-X) */
> + 0xa000 0x0 0x0 0x1 &mpic 0x9 0x1
> + 0xa000 0x0 0x0 0x2 &mpic 0xa 0x1
> + 0xa000 0x0 0x0 0x3 &mpic 0xb 0x1
> + 0xa000 0x0 0x0 0x4 &mpic 0xc 0x1
> +
> + >;
> +
> + isa {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + #interrupt-cells = <2>;
> + device_type = "isa";
> + compatible = "isa";
> + ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>;
> + interrupt-parent = <&i8259>;
> +
> + i8259: interrupt-controller@20 {
> + #interrupt-cells = <2>;
> + #address-cells = <0>;
> + interrupts = <0 2>;
> + device_type = "interrupt-controller";
> + compatible = "chrp,iic";
> + interrupt-controller;
> + reg = <1 0x00000020 0x00000002
> + 1 0x000000a0 0x00000002
> + 1 0x000004d0 0x00000002>;
> + interrupt-parent = <&mpic>;
> + };
> +
> + };
> +
> + };
> +
> + chosen {
> + linux,stdout-path = &serial0;
> + };
> +
> +};
> diff --git a/arch/powerpc/boot/mvme5100.c b/arch/powerpc/boot/mvme5100.c
> new file mode 100644
> index 0000000..cb865f8
> --- /dev/null
> +++ b/arch/powerpc/boot/mvme5100.c
> @@ -0,0 +1,27 @@
> +/*
> + * Motorola/Emerson MVME5100 with PPCBug firmware.
> + *
> + * Author: Stephen Chivers <schivers@csc.com>
> + *
> + * Copyright 2013 CSC Australia Pty. Ltd.
> + *
> + * 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 "types.h"
> +#include "ops.h"
> +#include "io.h"
> +
> +BSS_STACK(4096);
> +
> +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
> +{
> + u32 heapsize;
> +
> + heapsize = 0x8000000 - (u32)_end; /* 128M */
> + simple_alloc_init(_end, heapsize, 32, 64);
> + fdt_init(_dtb_start);
> + serial_console_init();
> +}
> diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
> index cd7af84..401c6a1 100755
> --- a/arch/powerpc/boot/wrapper
> +++ b/arch/powerpc/boot/wrapper
> @@ -257,6 +257,10 @@ epapr)
> link_address='0x20000000'
> pie=-pie
> ;;
> +mvme5100)
> + platformo="$object/fixed-head.o $object/mvme5100.o"
> + binary=y
> + ;;
> esac
>
> vmz="$tmpdir/`basename \"$kernel\"`.$ext"
> diff --git a/arch/powerpc/configs/mvme5100_defconfig b/arch/powerpc/configs/mvme5100_defconfig
> new file mode 100644
> index 0000000..93c7752
> --- /dev/null
> +++ b/arch/powerpc/configs/mvme5100_defconfig
> @@ -0,0 +1,144 @@
> +CONFIG_SYSVIPC=y
> +CONFIG_POSIX_MQUEUE=y
> +CONFIG_NO_HZ=y
> +CONFIG_HIGH_RES_TIMERS=y
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=14
> +# CONFIG_UTS_NS is not set
> +# CONFIG_IPC_NS is not set
> +# CONFIG_PID_NS is not set
> +# CONFIG_NET_NS is not set
> +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
> +# CONFIG_COMPAT_BRK is not set
> +CONFIG_MODULES=y
> +CONFIG_MODULE_UNLOAD=y
> +# CONFIG_BLK_DEV_BSG is not set
> +# CONFIG_PPC_CHRP is not set
> +# CONFIG_PPC_PMAC is not set
> +CONFIG_EMBEDDED6xx=y
> +CONFIG_MVME5100=y
> +CONFIG_KVM_GUEST=y
> +CONFIG_HZ_100=y
> +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> +# CONFIG_COMPACTION is not set
> +CONFIG_CMDLINE_BOOL=y
> +CONFIG_CMDLINE="console=ttyS0,9600 ip=dhcp root=/dev/nfs"
> +CONFIG_NET=y
> +CONFIG_PACKET=y
> +CONFIG_UNIX=y
> +CONFIG_INET=y
> +CONFIG_IP_MULTICAST=y
> +CONFIG_IP_PNP=y
> +CONFIG_IP_PNP_DHCP=y
> +CONFIG_IP_PNP_BOOTP=y
> +# CONFIG_INET_LRO is not set
> +# CONFIG_IPV6 is not set
> +CONFIG_NETFILTER=y
> +CONFIG_NF_CONNTRACK=m
> +CONFIG_NF_CT_PROTO_SCTP=m
> +CONFIG_NF_CONNTRACK_AMANDA=m
> +CONFIG_NF_CONNTRACK_FTP=m
> +CONFIG_NF_CONNTRACK_H323=m
> +CONFIG_NF_CONNTRACK_IRC=m
> +CONFIG_NF_CONNTRACK_NETBIOS_NS=m
> +CONFIG_NF_CONNTRACK_PPTP=m
> +CONFIG_NF_CONNTRACK_SIP=m
> +CONFIG_NF_CONNTRACK_TFTP=m
> +CONFIG_NETFILTER_XT_MATCH_MAC=m
> +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
> +CONFIG_NETFILTER_XT_MATCH_STATE=m
> +CONFIG_NF_CONNTRACK_IPV4=m
> +CONFIG_IP_NF_IPTABLES=m
> +CONFIG_IP_NF_FILTER=m
> +CONFIG_IP_NF_TARGET_REJECT=m
> +CONFIG_IP_NF_MANGLE=m
> +CONFIG_IP_NF_TARGET_ECN=m
> +CONFIG_IP_NF_TARGET_TTL=m
> +CONFIG_IP_NF_RAW=m
> +CONFIG_IP_NF_ARPTABLES=m
> +CONFIG_IP_NF_ARPFILTER=m
> +CONFIG_IP_NF_ARP_MANGLE=m
> +CONFIG_LAPB=m
> +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> +CONFIG_PROC_DEVICETREE=y
> +CONFIG_BLK_DEV_LOOP=y
> +CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_RAM_COUNT=2
> +CONFIG_BLK_DEV_RAM_SIZE=8192
> +CONFIG_EEPROM_LEGACY=m
> +CONFIG_NETDEVICES=y
> +CONFIG_TUN=m
> +# CONFIG_NET_VENDOR_3COM is not set
> +CONFIG_E100=y
> +# CONFIG_WLAN is not set
> +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
> +# CONFIG_INPUT_KEYBOARD is not set
> +# CONFIG_INPUT_MOUSE is not set
> +# CONFIG_SERIO is not set
> +CONFIG_SERIAL_8250=y
> +CONFIG_SERIAL_8250_CONSOLE=y
> +CONFIG_SERIAL_8250_NR_UARTS=10
> +CONFIG_SERIAL_8250_EXTENDED=y
> +CONFIG_SERIAL_8250_MANY_PORTS=y
> +CONFIG_SERIAL_8250_SHARE_IRQ=y
> +CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_HW_RANDOM=y
> +CONFIG_I2C=y
> +CONFIG_I2C_CHARDEV=y
> +CONFIG_I2C_MPC=y
> +# CONFIG_HWMON is not set
> +CONFIG_VIDEO_OUTPUT_CONTROL=m
> +# CONFIG_VGA_CONSOLE is not set
> +# CONFIG_HID is not set
> +# CONFIG_USB_SUPPORT is not set
> +# CONFIG_IOMMU_SUPPORT is not set
> +CONFIG_VME_BUS=m
> +CONFIG_VME_CA91CX42=m
> +CONFIG_EXT2_FS=m
> +CONFIG_EXT3_FS=m
> +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
> +CONFIG_XFS_FS=m
> +CONFIG_ISO9660_FS=m
> +CONFIG_JOLIET=y
> +CONFIG_ZISOFS=y
> +CONFIG_UDF_FS=m
> +CONFIG_MSDOS_FS=m
> +CONFIG_VFAT_FS=m
> +CONFIG_PROC_KCORE=y
> +CONFIG_TMPFS=y
> +CONFIG_NFS_FS=y
> +CONFIG_NFS_V3_ACL=y
> +CONFIG_NFS_V4=y
> +CONFIG_ROOT_NFS=y
> +CONFIG_NFSD=m
> +CONFIG_NFSD_V3=y
> +CONFIG_CIFS=m
> +CONFIG_NLS=y
> +CONFIG_NLS_CODEPAGE_437=m
> +CONFIG_NLS_CODEPAGE_932=m
> +CONFIG_NLS_ISO8859_1=m
> +CONFIG_NLS_UTF8=m
> +CONFIG_CRC_CCITT=m
> +CONFIG_CRC_T10DIF=y
> +CONFIG_XZ_DEC=y
> +CONFIG_XZ_DEC_X86=y
> +CONFIG_XZ_DEC_IA64=y
> +CONFIG_XZ_DEC_ARM=y
> +CONFIG_XZ_DEC_ARMTHUMB=y
> +CONFIG_XZ_DEC_SPARC=y
> +CONFIG_MAGIC_SYSRQ=y
> +CONFIG_DEBUG_KERNEL=y
> +CONFIG_DETECT_HUNG_TASK=y
> +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20
> +CONFIG_CRYPTO_CBC=y
> +CONFIG_CRYPTO_PCBC=m
> +CONFIG_CRYPTO_MD5=y
> +CONFIG_CRYPTO_MICHAEL_MIC=m
> +CONFIG_CRYPTO_SHA1=m
> +CONFIG_CRYPTO_BLOWFISH=m
> +CONFIG_CRYPTO_DES=y
> +CONFIG_CRYPTO_SERPENT=m
> +CONFIG_CRYPTO_TWOFISH=m
> +CONFIG_CRYPTO_DEFLATE=m
> +# CONFIG_CRYPTO_ANSI_CPRNG is not set
> diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
> index 302ba43..6d3c7a9 100644
> --- a/arch/powerpc/platforms/embedded6xx/Kconfig
> +++ b/arch/powerpc/platforms/embedded6xx/Kconfig
> @@ -67,6 +67,18 @@ config PPC_C2K
> This option enables support for the GE Fanuc C2K board (formerly
> an SBS board).
>
> +config MVME5100
> + bool "Motorola/Emerson MVME5100"
> + depends on EMBEDDED6xx
> + select MPIC
> + select PCI
> + select PPC_INDIRECT_PCI
> + select PPC_I8259
> + select PPC_NATIVE
> + help
> + This option enables support for the Motorola (now Emerson) MVME5100
> + board.
> +
> config TSI108_BRIDGE
> bool
> select PCI
> @@ -113,4 +125,3 @@ config WII
> help
> Select WII if configuring for the Nintendo Wii.
> More information at: <http://gc-linux.sourceforge.net/>
> -
> diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
> index 66c23e4..cdd48d4 100644
> --- a/arch/powerpc/platforms/embedded6xx/Makefile
> +++ b/arch/powerpc/platforms/embedded6xx/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_USBGECKO_UDBG) += usbgecko_udbg.o
> obj-$(CONFIG_GAMECUBE_COMMON) += flipper-pic.o
> obj-$(CONFIG_GAMECUBE) += gamecube.o
> obj-$(CONFIG_WII) += wii.o hlwd-pic.o
> +obj-$(CONFIG_MVME5100) += mvme5100.o
> diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c
> new file mode 100644
> index 0000000..25e3bfb
> --- /dev/null
> +++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c
> @@ -0,0 +1,221 @@
> +/*
> + * Board setup routines for the Motorola/Emerson MVME5100.
> + *
> + * Copyright 2013 CSC Australia Pty. Ltd.
> + *
> + * Based on earlier code by:
> + *
> + * Matt Porter, MontaVista Software Inc.
> + * Copyright 2001 MontaVista Software 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
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * Author: Stephen Chivers <schivers@csc.com>
> + *
> + */
> +
> +#include <linux/of_platform.h>
> +
> +#include <asm/i8259.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/mpic.h>
> +#include <asm/prom.h>
> +#include <mm/mmu_decl.h>
> +#include <asm/udbg.h>
> +
> +#define HAWK_MPIC_SIZE 0x00040000U
> +#define MVME5100_PCI_MEM_OFFSET 0x00000000
> +
> +/* Board register addresses. */
> +#define BOARD_STATUS_REG 0xfef88080
> +#define BOARD_MODFAIL_REG 0xfef88090
> +#define BOARD_MODRST_REG 0xfef880a0
> +#define BOARD_TBEN_REG 0xfef880c0
> +#define BOARD_SW_READ_REG 0xfef880e0
> +#define BOARD_GEO_ADDR_REG 0xfef880e8
> +#define BOARD_EXT_FEATURE1_REG 0xfef880f0
> +#define BOARD_EXT_FEATURE2_REG 0xfef88100
> +
> +static phys_addr_t pci_membase;
> +static u_char *restart;
> +
> +static void mvme5100_8259_cascade(unsigned int irq, struct irq_desc *desc)
> +{
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + unsigned int cascade_irq = i8259_irq();
> +
> + if (cascade_irq != NO_IRQ)
> + generic_handle_irq(cascade_irq);
> +
> + chip->irq_eoi(&desc->irq_data);
> +}
> +
> +static void __init mvme5100_pic_init(void)
> +{
> + struct mpic *mpic;
> + struct device_node *np;
> + struct device_node *cp = NULL;
> + unsigned int cirq;
> + unsigned long intack = 0;
> + const u32 *prop = NULL;
> +
> + np = of_find_node_by_type(NULL, "open-pic");
> + if (!np) {
> + pr_err("Could not find open-pic node\n");
> + return;
> + }
> +
> + mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC ");
> +
> + BUG_ON(mpic == NULL);
> + of_node_put(np);
> +
> + mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
> +
> + mpic_init(mpic);
> +
> + cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
> + if (cp == NULL) {
> + pr_warn("mvme5100_pic_init: couldn't find i8259\n");
> + return;
> + }
> +
> + cirq = irq_of_parse_and_map(cp, 0);
> + if (cirq == NO_IRQ) {
> + pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
> + return;
> + }
> +
> + np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
> + if (np) {
> + prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
> +
> + if (prop)
> + intack = prop[0];
> +
> + of_node_put(np);
> + }
> +
> + if (intack)
> + pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
> + intack);
> +
> + i8259_init(cp, intack);
> + of_node_put(cp);
> + irq_set_chained_handler(cirq, mvme5100_8259_cascade);
> +}
> +
> +static int __init mvme5100_add_bridge(struct device_node *dev)
> +{
> + const int *bus_range;
> + int len;
> + struct pci_controller *hose;
> + unsigned short devid;
> +
> + pr_info("Adding PCI host bridge %s\n", dev->full_name);
> +
> + bus_range = of_get_property(dev, "bus-range", &len);
> +
> + hose = pcibios_alloc_controller(dev);
> + if (hose == NULL)
> + return -ENOMEM;
> +
> + hose->first_busno = bus_range ? bus_range[0] : 0;
> + hose->last_busno = bus_range ? bus_range[1] : 0xff;
> +
> + setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
> +
> + pci_process_bridge_OF_ranges(hose, dev, 1);
> +
> + early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
> +
> + if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
> + pr_err("HAWK PHB not present?\n");
> + return 0;
> + }
> +
> + early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
> +
> + if (pci_membase == 0) {
> + pr_err("HAWK PHB mibar not correctly set?\n");
> + return 0;
> + }
> +
> + pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
> +
> + return 0;
> +}
> +
> +static struct of_device_id mvme5100_of_bus_ids[] __initdata = {
> + { .compatible = "hawk-bridge", },
> + {},
> +};
> +
> +/*
> + * Setup the architecture
> + */
> +static void __init mvme5100_setup_arch(void)
> +{
> + struct device_node *np;
> +
> + if (ppc_md.progress)
> + ppc_md.progress("mvme5100_setup_arch()", 0);
> +
> + for_each_compatible_node(np, "pci", "hawk-pci")
> + mvme5100_add_bridge(np);
> +
> + restart = ioremap(BOARD_MODRST_REG, 4);
> +}
> +
> +
> +static void mvme5100_show_cpuinfo(struct seq_file *m)
> +{
> + seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
> + seq_puts(m, "Machine\t\t: MVME5100\n");
> +}
> +
> +static void mvme5100_restart(char *cmd)
> +{
> +
> + local_irq_disable();
> + mtmsr(mfmsr() | MSR_IP);
> +
> + out_8((u_char *) restart, 0x01);
> +
> + while (1)
> + ;
> +}
> +
> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +static int __init mvme5100_probe(void)
> +{
> + unsigned long root = of_get_flat_dt_root();
> +
> + return of_flat_dt_is_compatible(root, "MVME5100");
> +}
> +
> +static int __init probe_of_platform_devices(void)
> +{
> +
> + of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
> + return 0;
> +}
> +
> +machine_device_initcall(mvme5100, probe_of_platform_devices);
> +
> +define_machine(mvme5100) {
> + .name = "MVME5100",
> + .probe = mvme5100_probe,
> + .setup_arch = mvme5100_setup_arch,
> + .init_IRQ = mvme5100_pic_init,
> + .show_cpuinfo = mvme5100_show_cpuinfo,
> + .get_irq = mpic_get_irq,
> + .restart = mvme5100_restart,
> + .calibrate_decr = generic_calibrate_decr,
> + .progress = udbg_progress,
> +};
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [RFC] arch: Introduce new TSO memory barrier smp_tmb()
From: Paul E. McKenney @ 2013-11-06 18:48 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Michael Neuling, Tony Luck, Mathieu Desnoyers, Heiko Carstens,
Oleg Nesterov, LKML, Linux PPC dev, Geert Uytterhoeven,
Anton Blanchard, Frederic Weisbecker, Victor Kaplansky,
Russell King, Linus Torvalds, Martin Schwidefsky
In-Reply-To: <20131106135736.GK10651@twins.programming.kicks-ass.net>
On Wed, Nov 06, 2013 at 02:57:36PM +0100, Peter Zijlstra wrote:
> On Wed, Nov 06, 2013 at 01:51:10PM +0100, Geert Uytterhoeven wrote:
> > This is screaming for a default implementation in asm-generic.
>
> Right you are... how about a little something like this?
>
> There's a few archs I didn't fully merge with the generic one because of
> weird nop implementations.
>
> asm volatile ("nop" :: ) vs asm volatile ("nop" ::: "memory") and the
> like. They probably can (and should) use the regular asm volatile
> ("nop") but I misplaced the toolchains for many of the weird archs so I
> didn't attempt.
>
> Also fixed a silly mistake in the return type definition for most
> smp_load_acquire() implementions: typeof(p) vs typeof(*p).
>
> ---
> Subject: arch: Introduce smp_load_acquire(), smp_store_release()
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Mon, 4 Nov 2013 20:18:11 +0100
>
> A number of situations currently require the heavyweight smp_mb(),
> even though there is no need to order prior stores against later
> loads. Many architectures have much cheaper ways to handle these
> situations, but the Linux kernel currently has no portable way
> to make use of them.
>
> This commit therefore supplies smp_load_acquire() and
> smp_store_release() to remedy this situation. The new
> smp_load_acquire() primitive orders the specified load against
> any subsequent reads or writes, while the new smp_store_release()
> primitive orders the specifed store against any prior reads or
> writes. These primitives allow array-based circular FIFOs to be
> implemented without an smp_mb(), and also allow a theoretical
> hole in rcu_assign_pointer() to be closed at no additional
> expense on most architectures.
>
> In addition, the RCU experience transitioning from explicit
> smp_read_barrier_depends() and smp_wmb() to rcu_dereference()
> and rcu_assign_pointer(), respectively resulted in substantial
> improvements in readability. It therefore seems likely that
> replacing other explicit barriers with smp_load_acquire() and
> smp_store_release() will provide similar benefits. It appears
> that roughly half of the explicit barriers in core kernel code
> might be so replaced.
>
>
> Cc: Michael Ellerman <michael@ellerman.id.au>
> Cc: Michael Neuling <mikey@neuling.org>
> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Victor Kaplansky <VICTORK@il.ibm.com>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Cc: Anton Blanchard <anton@samba.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
> Signed-off-by: Peter Zijlstra <peterz@infradead.org>
A few nits on Documentation/memory-barriers.txt and some pointless
comments elsewhere. With the suggested Documentation/memory-barriers.txt
fixes:
Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> ---
> Documentation/memory-barriers.txt | 157 +++++++++++++++++-----------------
> arch/alpha/include/asm/barrier.h | 25 +----
> arch/arc/include/asm/Kbuild | 1
> arch/arc/include/asm/atomic.h | 5 +
> arch/arc/include/asm/barrier.h | 42 ---------
> arch/arm/include/asm/barrier.h | 15 +++
> arch/arm64/include/asm/barrier.h | 50 ++++++++++
> arch/avr32/include/asm/barrier.h | 17 +--
> arch/blackfin/include/asm/barrier.h | 18 ---
> arch/cris/include/asm/Kbuild | 1
> arch/cris/include/asm/barrier.h | 25 -----
> arch/frv/include/asm/barrier.h | 8 -
> arch/h8300/include/asm/barrier.h | 21 ----
> arch/hexagon/include/asm/Kbuild | 1
> arch/hexagon/include/asm/barrier.h | 41 --------
> arch/ia64/include/asm/barrier.h | 49 ++++++++++
> arch/m32r/include/asm/barrier.h | 80 -----------------
> arch/m68k/include/asm/barrier.h | 14 ---
> arch/metag/include/asm/barrier.h | 15 +++
> arch/microblaze/include/asm/Kbuild | 1
> arch/microblaze/include/asm/barrier.h | 27 -----
> arch/mips/include/asm/barrier.h | 15 +++
> arch/mn10300/include/asm/Kbuild | 1
> arch/mn10300/include/asm/barrier.h | 37 --------
> arch/parisc/include/asm/Kbuild | 1
> arch/parisc/include/asm/barrier.h | 35 -------
> arch/powerpc/include/asm/barrier.h | 21 ++++
> arch/s390/include/asm/barrier.h | 15 +++
> arch/score/include/asm/Kbuild | 1
> arch/score/include/asm/barrier.h | 16 ---
> arch/sh/include/asm/barrier.h | 21 ----
> arch/sparc/include/asm/barrier_32.h | 11 --
> arch/sparc/include/asm/barrier_64.h | 15 +++
> arch/tile/include/asm/barrier.h | 68 --------------
> arch/unicore32/include/asm/barrier.h | 11 --
> arch/x86/include/asm/barrier.h | 15 +++
> arch/xtensa/include/asm/barrier.h | 9 -
> include/asm-generic/barrier.h | 55 +++++++++--
> include/linux/compiler.h | 9 +
> 39 files changed, 375 insertions(+), 594 deletions(-)
>
> --- a/Documentation/memory-barriers.txt
> +++ b/Documentation/memory-barriers.txt
> @@ -371,33 +371,35 @@ VARIETIES OF MEMORY BARRIER
>
> And a couple of implicit varieties:
>
> - (5) LOCK operations.
> + (5) ACQUIRE operations.
>
> This acts as a one-way permeable barrier. It guarantees that all memory
> - operations after the LOCK operation will appear to happen after the LOCK
> - operation with respect to the other components of the system.
> + operations after the ACQUIRE operation will appear to happen after the
> + ACQUIRE operation with respect to the other components of the system.
ACQUIRE operations include LOCK operations and smp_load_acquire()
operations.
>
> - Memory operations that occur before a LOCK operation may appear to happen
> - after it completes.
> + Memory operations that occur before a ACQUIRE operation may appear to
> + happen after it completes.
>
> - A LOCK operation should almost always be paired with an UNLOCK operation.
> + A ACQUIRE operation should almost always be paired with an RELEASE
> + operation.
>
>
> - (6) UNLOCK operations.
> + (6) RELEASE operations.
>
> This also acts as a one-way permeable barrier. It guarantees that all
> - memory operations before the UNLOCK operation will appear to happen before
> - the UNLOCK operation with respect to the other components of the system.
> + memory operations before the RELEASE operation will appear to happen
> + before the RELEASE operation with respect to the other components of the
> + system. Release operations include UNLOCK operations and
smp_store_release() operations.
> - Memory operations that occur after an UNLOCK operation may appear to
> + Memory operations that occur after an RELEASE operation may appear to
> happen before it completes.
>
> - LOCK and UNLOCK operations are guaranteed to appear with respect to each
> - other strictly in the order specified.
> + ACQUIRE and RELEASE operations are guaranteed to appear with respect to
> + each other strictly in the order specified.
>
> - The use of LOCK and UNLOCK operations generally precludes the need for
> - other sorts of memory barrier (but note the exceptions mentioned in the
> - subsection "MMIO write barrier").
> + The use of ACQUIRE and RELEASE operations generally precludes the need
> + for other sorts of memory barrier (but note the exceptions mentioned in
> + the subsection "MMIO write barrier").
>
>
> Memory barriers are only required where there's a possibility of interaction
> @@ -1135,7 +1137,7 @@ CPU from reordering them.
> clear_bit( ... );
>
> This prevents memory operations before the clear leaking to after it. See
> - the subsection on "Locking Functions" with reference to UNLOCK operation
> + the subsection on "Locking Functions" with reference to RELEASE operation
> implications.
>
> See Documentation/atomic_ops.txt for more information. See the "Atomic
> @@ -1181,65 +1183,66 @@ LOCKING FUNCTIONS
> (*) R/W semaphores
> (*) RCU
>
> -In all cases there are variants on "LOCK" operations and "UNLOCK" operations
> +In all cases there are variants on "ACQUIRE" operations and "RELEASE" operations
> for each construct. These operations all imply certain barriers:
>
> - (1) LOCK operation implication:
> + (1) ACQUIRE operation implication:
>
> - Memory operations issued after the LOCK will be completed after the LOCK
> - operation has completed.
> + Memory operations issued after the ACQUIRE will be completed after the
> + ACQUIRE operation has completed.
>
> - Memory operations issued before the LOCK may be completed after the LOCK
> - operation has completed.
> + Memory operations issued before the ACQUIRE may be completed after the
> + ACQUIRE operation has completed.
>
> - (2) UNLOCK operation implication:
> + (2) RELEASE operation implication:
>
> - Memory operations issued before the UNLOCK will be completed before the
> - UNLOCK operation has completed.
> + Memory operations issued before the RELEASE will be completed before the
> + RELEASE operation has completed.
>
> - Memory operations issued after the UNLOCK may be completed before the
> - UNLOCK operation has completed.
> + Memory operations issued after the RELEASE may be completed before the
> + RELEASE operation has completed.
>
> - (3) LOCK vs LOCK implication:
> + (3) ACQUIRE vs ACQUIRE implication:
>
> - All LOCK operations issued before another LOCK operation will be completed
> - before that LOCK operation.
> + All ACQUIRE operations issued before another ACQUIRE operation will be
> + completed before that ACQUIRE operation.
>
> - (4) LOCK vs UNLOCK implication:
> + (4) ACQUIRE vs RELEASE implication:
>
> - All LOCK operations issued before an UNLOCK operation will be completed
> - before the UNLOCK operation.
> + All ACQUIRE operations issued before an RELEASE operation will be
> + completed before the RELEASE operation.
>
> - All UNLOCK operations issued before a LOCK operation will be completed
> - before the LOCK operation.
> + All RELEASE operations issued before a ACQUIRE operation will be
> + completed before the ACQUIRE operation.
>
> - (5) Failed conditional LOCK implication:
> + (5) Failed conditional ACQUIRE implication:
>
> - Certain variants of the LOCK operation may fail, either due to being
> + Certain variants of the ACQUIRE operation may fail, either due to being
> unable to get the lock immediately, or due to receiving an unblocked
> signal whilst asleep waiting for the lock to become available. Failed
> locks do not imply any sort of barrier.
I suggest adding "For example" to the beginning of the last sentence:
For example, failed lock acquisitions do not imply any sort of
barrier.
Otherwise, the transition from ACQUIRE to lock is strange.
> -Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
> -equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
> +Therefore, from (1), (2) and (4) an RELEASE followed by an unconditional
> +ACQUIRE is equivalent to a full barrier, but a ACQUIRE followed by an RELEASE
> +is not.
>
> [!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
> barriers is that the effects of instructions outside of a critical section
> may seep into the inside of the critical section.
>
> -A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
> -because it is possible for an access preceding the LOCK to happen after the
> -LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
> -two accesses can themselves then cross:
> +A ACQUIRE followed by an RELEASE may not be assumed to be full memory barrier
> +because it is possible for an access preceding the ACQUIRE to happen after the
> +ACQUIRE, and an access following the RELEASE to happen before the RELEASE, and
> +the two accesses can themselves then cross:
>
> *A = a;
> - LOCK
> - UNLOCK
> + ACQUIRE
> + RELEASE
> *B = b;
>
> may occur as:
>
> - LOCK, STORE *B, STORE *A, UNLOCK
> + ACQUIRE, STORE *B, STORE *A, RELEASE
>
> Locks and semaphores may not provide any guarantee of ordering on UP compiled
> systems, and so cannot be counted on in such a situation to actually achieve
> @@ -1253,33 +1256,33 @@ See also the section on "Inter-CPU locki
>
> *A = a;
> *B = b;
> - LOCK
> + ACQUIRE
> *C = c;
> *D = d;
> - UNLOCK
> + RELEASE
> *E = e;
> *F = f;
>
> The following sequence of events is acceptable:
>
> - LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
> + ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
>
> [+] Note that {*F,*A} indicates a combined access.
>
> But none of the following are:
>
> - {*F,*A}, *B, LOCK, *C, *D, UNLOCK, *E
> - *A, *B, *C, LOCK, *D, UNLOCK, *E, *F
> - *A, *B, LOCK, *C, UNLOCK, *D, *E, *F
> - *B, LOCK, *C, *D, UNLOCK, {*F,*A}, *E
> + {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E
> + *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F
> + *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F
> + *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E
>
>
>
> INTERRUPT DISABLING FUNCTIONS
> -----------------------------
>
> -Functions that disable interrupts (LOCK equivalent) and enable interrupts
> -(UNLOCK equivalent) will act as compiler barriers only. So if memory or I/O
> +Functions that disable interrupts (ACQUIRE equivalent) and enable interrupts
> +(RELEASE equivalent) will act as compiler barriers only. So if memory or I/O
> barriers are required in such a situation, they must be provided from some
> other means.
>
> @@ -1436,24 +1439,24 @@ Consider the following: the system has a
> CPU 1 CPU 2
> =============================== ===============================
> *A = a; *E = e;
> - LOCK M LOCK Q
> + ACQUIRE M ACQUIRE Q
> *B = b; *F = f;
> *C = c; *G = g;
> - UNLOCK M UNLOCK Q
> + RELEASE M RELEASE Q
> *D = d; *H = h;
>
> Then there is no guarantee as to what order CPU 3 will see the accesses to *A
> through *H occur in, other than the constraints imposed by the separate locks
> on the separate CPUs. It might, for example, see:
>
> - *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
> + *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
>
> But it won't see any of:
>
> - *B, *C or *D preceding LOCK M
> - *A, *B or *C following UNLOCK M
> - *F, *G or *H preceding LOCK Q
> - *E, *F or *G following UNLOCK Q
> + *B, *C or *D preceding ACQUIRE M
> + *A, *B or *C following RELEASE M
> + *F, *G or *H preceding ACQUIRE Q
> + *E, *F or *G following RELEASE Q
>
>
> However, if the following occurs:
> @@ -1461,28 +1464,28 @@ through *H occur in, other than the cons
> CPU 1 CPU 2
> =============================== ===============================
> *A = a;
> - LOCK M [1]
> + ACQUIRE M [1]
> *B = b;
> *C = c;
> - UNLOCK M [1]
> + RELEASE M [1]
> *D = d; *E = e;
> - LOCK M [2]
> + ACQUIRE M [2]
> *F = f;
> *G = g;
> - UNLOCK M [2]
> + RELEASE M [2]
> *H = h;
>
> CPU 3 might see:
>
> - *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
> - LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
> + *E, ACQUIRE M [1], *C, *B, *A, RELEASE M [1],
> + ACQUIRE M [2], *H, *F, *G, RELEASE M [2], *D
>
> But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
>
> - *B, *C, *D, *F, *G or *H preceding LOCK M [1]
> - *A, *B or *C following UNLOCK M [1]
> - *F, *G or *H preceding LOCK M [2]
> - *A, *B, *C, *E, *F or *G following UNLOCK M [2]
> + *B, *C, *D, *F, *G or *H preceding ACQUIRE M [1]
> + *A, *B or *C following RELEASE M [1]
> + *F, *G or *H preceding ACQUIRE M [2]
> + *A, *B, *C, *E, *F or *G following RELEASE M [2]
>
>
> LOCKS VS I/O ACCESSES
> @@ -1702,13 +1705,13 @@ about the state (old or new) implies an
> test_and_clear_bit();
> test_and_change_bit();
>
> -These are used for such things as implementing LOCK-class and UNLOCK-class
> +These are used for such things as implementing ACQUIRE-class and RELEASE-class
> operations and adjusting reference counters towards object destruction, and as
> such the implicit memory barrier effects are necessary.
>
>
> The following operations are potential problems as they do _not_ imply memory
> -barriers, but might be used for implementing such things as UNLOCK-class
> +barriers, but might be used for implementing such things as RELEASE-class
> operations:
>
> atomic_set();
> @@ -1750,9 +1753,9 @@ barriers are needed or not.
> clear_bit_unlock();
> __clear_bit_unlock();
>
> -These implement LOCK-class and UNLOCK-class operations. These should be used in
> -preference to other operations when implementing locking primitives, because
> -their implementations can be optimised on many architectures.
> +These implement ACQUIRE-class and RELEASE-class operations. These should be
> +used in preference to other operations when implementing locking primitives,
> +because their implementations can be optimised on many architectures.
>
> [!] Note that special memory barrier primitives are available for these
> situations because on some CPUs the atomic instructions used imply full memory
> --- a/arch/alpha/include/asm/barrier.h
> +++ b/arch/alpha/include/asm/barrier.h
> @@ -3,33 +3,18 @@
>
> #include <asm/compiler.h>
>
> -#define mb() \
> -__asm__ __volatile__("mb": : :"memory")
> +#define mb() __asm__ __volatile__("mb": : :"memory")
> +#define rmb() __asm__ __volatile__("mb": : :"memory")
> +#define wmb() __asm__ __volatile__("wmb": : :"memory")
>
> -#define rmb() \
> -__asm__ __volatile__("mb": : :"memory")
> -
> -#define wmb() \
> -__asm__ __volatile__("wmb": : :"memory")
> -
> -#define read_barrier_depends() \
> -__asm__ __volatile__("mb": : :"memory")
> +#define read_barrier_depends() __asm__ __volatile__("mb": : :"memory")
>
> #ifdef CONFIG_SMP
> #define __ASM_SMP_MB "\tmb\n"
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> #else
> #define __ASM_SMP_MB
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while (0)
> #endif
>
> -#define set_mb(var, value) \
> -do { var = value; mb(); } while (0)
> +#include <asm-generic/barrier.h>
>
> #endif /* __BARRIER_H */
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -47,3 +47,4 @@ generic-y += user.h
> generic-y += vga.h
> generic-y += xor.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/arc/include/asm/atomic.h
> +++ b/arch/arc/include/asm/atomic.h
> @@ -190,6 +190,11 @@ static inline void atomic_clear_mask(uns
>
> #endif /* !CONFIG_ARC_HAS_LLSC */
>
> +#define smp_mb__before_atomic_dec() barrier()
> +#define smp_mb__after_atomic_dec() barrier()
> +#define smp_mb__before_atomic_inc() barrier()
> +#define smp_mb__after_atomic_inc() barrier()
> +
> /**
> * __atomic_add_unless - add unless the number is a given value
> * @v: pointer of type atomic_t
> --- a/arch/arc/include/asm/barrier.h
> +++ /dev/null
> @@ -1,42 +0,0 @@
> -/*
> - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
> - *
> - * 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.
> - */
> -
> -#ifndef __ASM_BARRIER_H
> -#define __ASM_BARRIER_H
> -
> -#ifndef __ASSEMBLY__
> -
> -/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */
> -#define mb() __asm__ __volatile__ ("" : : : "memory")
> -#define rmb() mb()
> -#define wmb() mb()
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -#define set_wmb(var, value) do { var = value; wmb(); } while (0)
> -#define read_barrier_depends() mb()
> -
> -/* TODO-vineetg verify the correctness of macros here */
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#endif
> -
> -#define smp_mb__before_atomic_dec() barrier()
> -#define smp_mb__after_atomic_dec() barrier()
> -#define smp_mb__before_atomic_inc() barrier()
> -#define smp_mb__after_atomic_inc() barrier()
> -
> -#define smp_read_barrier_depends() do { } while (0)
> -
> -#endif
> -
> -#endif
I do like this take-no-prisoners approach! ;-)
> --- a/arch/arm/include/asm/barrier.h
> +++ b/arch/arm/include/asm/barrier.h
> @@ -59,6 +59,21 @@
> #define smp_wmb() dmb(ishst)
> #endif
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
> +
> #define read_barrier_depends() do { } while(0)
> #define smp_read_barrier_depends() do { } while(0)
>
> --- a/arch/arm64/include/asm/barrier.h
> +++ b/arch/arm64/include/asm/barrier.h
> @@ -35,11 +35,59 @@
> #define smp_mb() barrier()
> #define smp_rmb() barrier()
> #define smp_wmb() barrier()
> +
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
> +
> #else
> +
> #define smp_mb() asm volatile("dmb ish" : : : "memory")
> #define smp_rmb() asm volatile("dmb ishld" : : : "memory")
> #define smp_wmb() asm volatile("dmb ishst" : : : "memory")
> -#endif
> +
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + switch (sizeof(*p)) { \
> + case 4: \
> + asm volatile ("stlr %w1, [%0]" \
> + : "=Q" (*p) : "r" (v) : "memory"); \
> + break; \
> + case 8: \
> + asm volatile ("stlr %1, [%0]" \
> + : "=Q" (*p) : "r" (v) : "memory"); \
> + break; \
> + } \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1; \
> + compiletime_assert_atomic_type(*p); \
> + switch (sizeof(*p)) { \
> + case 4: \
> + asm volatile ("ldar %w0, [%1]" \
> + : "=r" (___p1) : "Q" (*p) : "memory"); \
> + break; \
> + case 8: \
> + asm volatile ("ldar %0, [%1]" \
> + : "=r" (___p1) : "Q" (*p) : "memory"); \
> + break; \
> + } \
> + ___p1; \
> +})
>
> #define read_barrier_depends() do { } while(0)
> #define smp_read_barrier_depends() do { } while(0)
> --- a/arch/avr32/include/asm/barrier.h
> +++ b/arch/avr32/include/asm/barrier.h
> @@ -8,22 +8,15 @@
> #ifndef __ASM_AVR32_BARRIER_H
> #define __ASM_AVR32_BARRIER_H
>
> -#define nop() asm volatile("nop")
> -
> -#define mb() asm volatile("" : : : "memory")
> -#define rmb() mb()
> -#define wmb() asm volatile("sync 0" : : : "memory")
> -#define read_barrier_depends() do { } while(0)
> -#define set_mb(var, value) do { var = value; mb(); } while(0)
> +/*
> + * Weirdest thing ever.. no full barrier, but it has a write barrier!
> + */
> +#define wmb() asm volatile("sync 0" : : : "memory")
Doesn't this mean that asm-generic/barrier.h needs to check for
definitions? Ah, I see below that you added these checks.
> #ifdef CONFIG_SMP
> # error "The AVR32 port does not support SMP"
> -#else
> -# define smp_mb() barrier()
> -# define smp_rmb() barrier()
> -# define smp_wmb() barrier()
> -# define smp_read_barrier_depends() do { } while(0)
> #endif
>
> +#include <asm-generic/barrier.h>
>
> #endif /* __ASM_AVR32_BARRIER_H */
> --- a/arch/blackfin/include/asm/barrier.h
> +++ b/arch/blackfin/include/asm/barrier.h
> @@ -23,26 +23,10 @@
> # define rmb() do { barrier(); smp_check_barrier(); } while (0)
> # define wmb() do { barrier(); smp_mark_barrier(); } while (0)
> # define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0)
> -#else
> -# define mb() barrier()
> -# define rmb() barrier()
> -# define wmb() barrier()
> -# define read_barrier_depends() do { } while (0)
> #endif
>
> -#else /* !CONFIG_SMP */
> -
> -#define mb() barrier()
> -#define rmb() barrier()
> -#define wmb() barrier()
> -#define read_barrier_depends() do { } while (0)
> -
> #endif /* !CONFIG_SMP */
>
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -#define smp_read_barrier_depends() read_barrier_depends()
> +#include <asm-generic/barrier.h>
>
> #endif /* _BLACKFIN_BARRIER_H */
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += trace_clock.h
> generic-y += vga.h
> generic-y += xor.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/cris/include/asm/barrier.h
> +++ /dev/null
> @@ -1,25 +0,0 @@
> -#ifndef __ASM_CRIS_BARRIER_H
> -#define __ASM_CRIS_BARRIER_H
> -
> -#define nop() __asm__ __volatile__ ("nop");
> -
> -#define barrier() __asm__ __volatile__("": : :"memory")
> -#define mb() barrier()
> -#define rmb() mb()
> -#define wmb() mb()
> -#define read_barrier_depends() do { } while(0)
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while(0)
> -#endif
> -
> -#endif /* __ASM_CRIS_BARRIER_H */
> --- a/arch/frv/include/asm/barrier.h
> +++ b/arch/frv/include/asm/barrier.h
> @@ -17,13 +17,7 @@
> #define mb() asm volatile ("membar" : : :"memory")
> #define rmb() asm volatile ("membar" : : :"memory")
> #define wmb() asm volatile ("membar" : : :"memory")
> -#define read_barrier_depends() do { } while (0)
>
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do {} while(0)
> -#define set_mb(var, value) \
> - do { var = (value); barrier(); } while (0)
> +#include <asm-generic/barrier.h>
>
> #endif /* _ASM_BARRIER_H */
> --- a/arch/h8300/include/asm/barrier.h
> +++ b/arch/h8300/include/asm/barrier.h
> @@ -3,27 +3,8 @@
>
> #define nop() asm volatile ("nop"::)
>
> -/*
> - * Force strict CPU ordering.
> - * Not really required on H8...
> - */
> -#define mb() asm volatile ("" : : :"memory")
> -#define rmb() asm volatile ("" : : :"memory")
> -#define wmb() asm volatile ("" : : :"memory")
> #define set_mb(var, value) do { xchg(&var, value); } while (0)
>
> -#define read_barrier_depends() do { } while (0)
> -
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while(0)
> -#endif
> +#include <asm-generic/barrier.h>
>
> #endif /* _H8300_BARRIER_H */
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -54,3 +54,4 @@ generic-y += ucontext.h
> generic-y += unaligned.h
> generic-y += xor.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/hexagon/include/asm/barrier.h
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/*
> - * Memory barrier definitions for the Hexagon architecture
> - *
> - * Copyright (c) 2010-2011, The Linux Foundation. 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 and
> - * only version 2 as published by the Free Software Foundation.
> - *
> - * 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., 51 Franklin Street, Fifth Floor, Boston, MA
> - * 02110-1301, USA.
> - */
> -
> -#ifndef _ASM_BARRIER_H
> -#define _ASM_BARRIER_H
> -
> -#define rmb() barrier()
> -#define read_barrier_depends() barrier()
> -#define wmb() barrier()
> -#define mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_read_barrier_depends() barrier()
> -#define smp_wmb() barrier()
> -#define smp_mb() barrier()
> -#define smp_mb__before_atomic_dec() barrier()
> -#define smp_mb__after_atomic_dec() barrier()
> -#define smp_mb__before_atomic_inc() barrier()
> -#define smp_mb__after_atomic_inc() barrier()
> -
> -/* Set a value and use a memory barrier. Used by the scheduler somewhere. */
> -#define set_mb(var, value) \
> - do { var = value; mb(); } while (0)
> -
> -#endif /* _ASM_BARRIER_H */
> --- a/arch/ia64/include/asm/barrier.h
> +++ b/arch/ia64/include/asm/barrier.h
> @@ -45,11 +45,60 @@
> # define smp_rmb() rmb()
> # define smp_wmb() wmb()
> # define smp_read_barrier_depends() read_barrier_depends()
> +
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + switch (sizeof(*p)) { \
> + case 4: \
> + asm volatile ("st4.rel [%0]=%1" \
> + : "=r" (p) : "r" (v) : "memory"); \
> + break; \
> + case 8: \
> + asm volatile ("st8.rel [%0]=%1" \
> + : "=r" (p) : "r" (v) : "memory"); \
> + break; \
> + } \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1; \
> + compiletime_assert_atomic_type(*p); \
> + switch (sizeof(*p)) { \
> + case 4: \
> + asm volatile ("ld4.acq %0=[%1]" \
> + : "=r" (___p1) : "r" (p) : "memory"); \
> + break; \
> + case 8: \
> + asm volatile ("ld8.acq %0=[%1]" \
> + : "=r" (___p1) : "r" (p) : "memory"); \
> + break; \
> + } \
> + ___p1; \
> +})
> +
> #else
> +
> # define smp_mb() barrier()
> # define smp_rmb() barrier()
> # define smp_wmb() barrier()
> # define smp_read_barrier_depends() do { } while(0)
> +
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
> #endif
>
> /*
> --- a/arch/m32r/include/asm/barrier.h
> +++ b/arch/m32r/include/asm/barrier.h
> @@ -11,84 +11,6 @@
>
> #define nop() __asm__ __volatile__ ("nop" : : )
>
> -/*
> - * Memory barrier.
> - *
> - * mb() prevents loads and stores being reordered across this point.
> - * rmb() prevents loads being reordered across this point.
> - * wmb() prevents stores being reordered across this point.
> - */
> -#define mb() barrier()
> -#define rmb() mb()
> -#define wmb() mb()
> -
> -/**
> - * read_barrier_depends - Flush all pending reads that subsequents reads
> - * depend on.
> - *
> - * No data-dependent reads from memory-like regions are ever reordered
> - * over this barrier. All reads preceding this primitive are guaranteed
> - * to access memory (but not necessarily other CPUs' caches) before any
> - * reads following this primitive that depend on the data return by
> - * any of the preceding reads. This primitive is much lighter weight than
> - * rmb() on most CPUs, and is never heavier weight than is
> - * rmb().
> - *
> - * These ordering constraints are respected by both the local CPU
> - * and the compiler.
> - *
> - * Ordering is not guaranteed by anything other than these primitives,
> - * not even by data dependencies. See the documentation for
> - * memory_barrier() for examples and URLs to more information.
> - *
> - * For example, the following code would force ordering (the initial
> - * value of "a" is zero, "b" is one, and "p" is "&a"):
> - *
> - * <programlisting>
> - * CPU 0 CPU 1
> - *
> - * b = 2;
> - * memory_barrier();
> - * p = &b; q = p;
> - * read_barrier_depends();
> - * d = *q;
> - * </programlisting>
> - *
> - *
> - * because the read of "*q" depends on the read of "p" and these
> - * two reads are separated by a read_barrier_depends(). However,
> - * the following code, with the same initial values for "a" and "b":
> - *
> - * <programlisting>
> - * CPU 0 CPU 1
> - *
> - * a = 2;
> - * memory_barrier();
> - * b = 3; y = b;
> - * read_barrier_depends();
> - * x = a;
> - * </programlisting>
> - *
> - * does not enforce ordering, since there is no data dependency between
> - * the read of "a" and the read of "b". Therefore, on some CPUs, such
> - * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
> - * in cases like this where there are no data dependencies.
> - **/
> -
> -#define read_barrier_depends() do { } while (0)
> -
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> -#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while (0)
> -#define set_mb(var, value) do { var = value; barrier(); } while (0)
> -#endif
> +#include <asm-generic/barrier.h>
>
> #endif /* _ASM_M32R_BARRIER_H */
> --- a/arch/m68k/include/asm/barrier.h
> +++ b/arch/m68k/include/asm/barrier.h
> @@ -1,20 +1,8 @@
> #ifndef _M68K_BARRIER_H
> #define _M68K_BARRIER_H
>
> -/*
> - * Force strict CPU ordering.
> - * Not really required on m68k...
> - */
> #define nop() do { asm volatile ("nop"); barrier(); } while (0)
> -#define mb() barrier()
> -#define rmb() barrier()
> -#define wmb() barrier()
> -#define read_barrier_depends() ((void)0)
> -#define set_mb(var, value) ({ (var) = (value); wmb(); })
>
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() ((void)0)
> +#include <asm-generic/barrier.h>
>
> #endif /* _M68K_BARRIER_H */
> --- a/arch/metag/include/asm/barrier.h
> +++ b/arch/metag/include/asm/barrier.h
> @@ -82,4 +82,19 @@ static inline void fence(void)
> #define smp_read_barrier_depends() do { } while (0)
> #define set_mb(var, value) do { var = value; smp_mb(); } while (0)
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
> +
> #endif /* _ASM_METAG_BARRIER_H */
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -4,3 +4,4 @@ generic-y += exec.h
> generic-y += trace_clock.h
> generic-y += syscalls.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/microblaze/include/asm/barrier.h
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -/*
> - * Copyright (C) 2006 Atmark Techno, Inc.
> - *
> - * This file is subject to the terms and conditions of the GNU General Public
> - * License. See the file "COPYING" in the main directory of this archive
> - * for more details.
> - */
> -
> -#ifndef _ASM_MICROBLAZE_BARRIER_H
> -#define _ASM_MICROBLAZE_BARRIER_H
> -
> -#define nop() asm volatile ("nop")
> -
> -#define smp_read_barrier_depends() do {} while (0)
> -#define read_barrier_depends() do {} while (0)
> -
> -#define mb() barrier()
> -#define rmb() mb()
> -#define wmb() mb()
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -#define set_wmb(var, value) do { var = value; wmb(); } while (0)
> -
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -
> -#endif /* _ASM_MICROBLAZE_BARRIER_H */
> --- a/arch/mips/include/asm/barrier.h
> +++ b/arch/mips/include/asm/barrier.h
> @@ -180,4 +180,19 @@
> #define nudge_writes() mb()
> #endif
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
> +
> #endif /* __ASM_BARRIER_H */
> --- a/arch/mn10300/include/asm/Kbuild
> +++ b/arch/mn10300/include/asm/Kbuild
> @@ -3,3 +3,4 @@ generic-y += clkdev.h
> generic-y += exec.h
> generic-y += trace_clock.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/mn10300/include/asm/barrier.h
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -/* MN10300 memory barrier definitions
> - *
> - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
> - * Written by David Howells (dhowells@redhat.com)
> - *
> - * This program is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU General Public Licence
> - * as published by the Free Software Foundation; either version
> - * 2 of the Licence, or (at your option) any later version.
> - */
> -#ifndef _ASM_BARRIER_H
> -#define _ASM_BARRIER_H
> -
> -#define nop() asm volatile ("nop")
> -
> -#define mb() asm volatile ("": : :"memory")
> -#define rmb() mb()
> -#define wmb() asm volatile ("": : :"memory")
> -
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define set_mb(var, value) do { xchg(&var, value); } while (0)
> -#else /* CONFIG_SMP */
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -#endif /* CONFIG_SMP */
> -
> -#define set_wmb(var, value) do { var = value; wmb(); } while (0)
> -
> -#define read_barrier_depends() do {} while (0)
> -#define smp_read_barrier_depends() do {} while (0)
> -
> -#endif /* _ASM_BARRIER_H */
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -5,3 +5,4 @@ generic-y += word-at-a-time.h auxvec.h u
> poll.h xor.h clkdev.h exec.h
> generic-y += trace_clock.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/parisc/include/asm/barrier.h
> +++ /dev/null
> @@ -1,35 +0,0 @@
> -#ifndef __PARISC_BARRIER_H
> -#define __PARISC_BARRIER_H
> -
> -/*
> -** This is simply the barrier() macro from linux/kernel.h but when serial.c
> -** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
> -** hasn't yet been included yet so it fails, thus repeating the macro here.
> -**
> -** PA-RISC architecture allows for weakly ordered memory accesses although
> -** none of the processors use it. There is a strong ordered bit that is
> -** set in the O-bit of the page directory entry. Operating systems that
> -** can not tolerate out of order accesses should set this bit when mapping
> -** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
> -** of the processor implemented the PSW O-bit). The PCX-W ERS states that
> -** the TLB O-bit is not implemented so the page directory does not need to
> -** have the O-bit set when mapping pages (section 3.1). This section also
> -** states that the PSW Y, Z, G, and O bits are not implemented.
> -** So it looks like nothing needs to be done for parisc-linux (yet).
> -** (thanks to chada for the above comment -ggg)
> -**
> -** The __asm__ op below simple prevents gcc/ld from reordering
> -** instructions across the mb() "call".
> -*/
> -#define mb() __asm__ __volatile__("":::"memory") /* barrier() */
> -#define rmb() mb()
> -#define wmb() mb()
> -#define smp_mb() mb()
> -#define smp_rmb() mb()
> -#define smp_wmb() mb()
> -#define smp_read_barrier_depends() do { } while(0)
> -#define read_barrier_depends() do { } while(0)
> -
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> -
> -#endif /* __PARISC_BARRIER_H */
> --- a/arch/powerpc/include/asm/barrier.h
> +++ b/arch/powerpc/include/asm/barrier.h
> @@ -45,11 +45,15 @@
> # define SMPWMB eieio
> #endif
>
> +#define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
> +
> #define smp_mb() mb()
> -#define smp_rmb() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
> +#define smp_rmb() __lwsync()
> #define smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
> #define smp_read_barrier_depends() read_barrier_depends()
> #else
> +#define __lwsync() barrier()
> +
> #define smp_mb() barrier()
> #define smp_rmb() barrier()
> #define smp_wmb() barrier()
> @@ -65,4 +69,19 @@
> #define data_barrier(x) \
> asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + __lwsync(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + __lwsync(); \
> + ___p1; \
> +})
> +
> #endif /* _ASM_POWERPC_BARRIER_H */
> --- a/arch/s390/include/asm/barrier.h
> +++ b/arch/s390/include/asm/barrier.h
> @@ -32,4 +32,19 @@
>
> #define set_mb(var, value) do { var = value; mb(); } while (0)
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ___p1; \
> +})
> +
> #endif /* __ASM_BARRIER_H */
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -5,3 +5,4 @@ generic-y += clkdev.h
> generic-y += trace_clock.h
> generic-y += xor.h
> generic-y += preempt.h
> +generic-y += barrier.h
> --- a/arch/score/include/asm/barrier.h
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -#ifndef _ASM_SCORE_BARRIER_H
> -#define _ASM_SCORE_BARRIER_H
> -
> -#define mb() barrier()
> -#define rmb() barrier()
> -#define wmb() barrier()
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -
> -#define read_barrier_depends() do {} while (0)
> -#define smp_read_barrier_depends() do {} while (0)
> -
> -#define set_mb(var, value) do {var = value; wmb(); } while (0)
> -
> -#endif /* _ASM_SCORE_BARRIER_H */
> --- a/arch/sh/include/asm/barrier.h
> +++ b/arch/sh/include/asm/barrier.h
> @@ -26,29 +26,14 @@
> #if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
> #define mb() __asm__ __volatile__ ("synco": : :"memory")
> #define rmb() mb()
> -#define wmb() __asm__ __volatile__ ("synco": : :"memory")
> +#define wmb() mb()
> #define ctrl_barrier() __icbi(PAGE_OFFSET)
> -#define read_barrier_depends() do { } while(0)
> #else
> -#define mb() __asm__ __volatile__ ("": : :"memory")
> -#define rmb() mb()
> -#define wmb() __asm__ __volatile__ ("": : :"memory")
> #define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
> -#define read_barrier_depends() do { } while(0)
> -#endif
> -
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while(0)
> #endif
>
> #define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
>
> +#include <asm-generic/barrier.h>
> +
> #endif /* __ASM_SH_BARRIER_H */
> --- a/arch/sparc/include/asm/barrier_32.h
> +++ b/arch/sparc/include/asm/barrier_32.h
> @@ -1,15 +1,6 @@
> #ifndef __SPARC_BARRIER_H
> #define __SPARC_BARRIER_H
>
> -/* XXX Change this if we ever use a PSO mode kernel. */
> -#define mb() __asm__ __volatile__ ("" : : : "memory")
> -#define rmb() mb()
> -#define wmb() mb()
> -#define read_barrier_depends() do { } while(0)
> -#define set_mb(__var, __value) do { __var = __value; mb(); } while(0)
> -#define smp_mb() __asm__ __volatile__("":::"memory")
> -#define smp_rmb() __asm__ __volatile__("":::"memory")
> -#define smp_wmb() __asm__ __volatile__("":::"memory")
> -#define smp_read_barrier_depends() do { } while(0)
> +#include <asm-generic/barrier.h>
>
> #endif /* !(__SPARC_BARRIER_H) */
> --- a/arch/sparc/include/asm/barrier_64.h
> +++ b/arch/sparc/include/asm/barrier_64.h
> @@ -53,4 +53,19 @@ do { __asm__ __volatile__("ba,pt %%xcc,
>
> #define smp_read_barrier_depends() do { } while(0)
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ___p1; \
> +})
> +
> #endif /* !(__SPARC64_BARRIER_H) */
> --- a/arch/tile/include/asm/barrier.h
> +++ b/arch/tile/include/asm/barrier.h
> @@ -22,59 +22,6 @@
> #include <arch/spr_def.h>
> #include <asm/timex.h>
>
> -/*
> - * read_barrier_depends - Flush all pending reads that subsequents reads
> - * depend on.
> - *
> - * No data-dependent reads from memory-like regions are ever reordered
> - * over this barrier. All reads preceding this primitive are guaranteed
> - * to access memory (but not necessarily other CPUs' caches) before any
> - * reads following this primitive that depend on the data return by
> - * any of the preceding reads. This primitive is much lighter weight than
> - * rmb() on most CPUs, and is never heavier weight than is
> - * rmb().
> - *
> - * These ordering constraints are respected by both the local CPU
> - * and the compiler.
> - *
> - * Ordering is not guaranteed by anything other than these primitives,
> - * not even by data dependencies. See the documentation for
> - * memory_barrier() for examples and URLs to more information.
> - *
> - * For example, the following code would force ordering (the initial
> - * value of "a" is zero, "b" is one, and "p" is "&a"):
> - *
> - * <programlisting>
> - * CPU 0 CPU 1
> - *
> - * b = 2;
> - * memory_barrier();
> - * p = &b; q = p;
> - * read_barrier_depends();
> - * d = *q;
> - * </programlisting>
> - *
> - * because the read of "*q" depends on the read of "p" and these
> - * two reads are separated by a read_barrier_depends(). However,
> - * the following code, with the same initial values for "a" and "b":
> - *
> - * <programlisting>
> - * CPU 0 CPU 1
> - *
> - * a = 2;
> - * memory_barrier();
> - * b = 3; y = b;
> - * read_barrier_depends();
> - * x = a;
> - * </programlisting>
> - *
> - * does not enforce ordering, since there is no data dependency between
> - * the read of "a" and the read of "b". Therefore, on some CPUs, such
> - * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
> - * in cases like this where there are no data dependencies.
> - */
> -#define read_barrier_depends() do { } while (0)
> -
> #define __sync() __insn_mf()
>
> #include <hv/syscall_public.h>
> @@ -125,20 +72,7 @@ mb_incoherent(void)
> #define mb() fast_mb()
> #define iob() fast_iob()
>
> -#ifdef CONFIG_SMP
> -#define smp_mb() mb()
> -#define smp_rmb() rmb()
> -#define smp_wmb() wmb()
> -#define smp_read_barrier_depends() read_barrier_depends()
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define smp_read_barrier_depends() do { } while (0)
> -#endif
> -
> -#define set_mb(var, value) \
> - do { var = value; mb(); } while (0)
> +#include <asm-generic/barrier.h>
>
> #endif /* !__ASSEMBLY__ */
> #endif /* _ASM_TILE_BARRIER_H */
> --- a/arch/unicore32/include/asm/barrier.h
> +++ b/arch/unicore32/include/asm/barrier.h
> @@ -14,15 +14,6 @@
> #define dsb() __asm__ __volatile__ ("" : : : "memory")
> #define dmb() __asm__ __volatile__ ("" : : : "memory")
>
> -#define mb() barrier()
> -#define rmb() barrier()
> -#define wmb() barrier()
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> -#define read_barrier_depends() do { } while (0)
> -#define smp_read_barrier_depends() do { } while (0)
> -
> -#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
> +#include <asm-generic/barrier.h>
>
> #endif /* __UNICORE_BARRIER_H__ */
> --- a/arch/x86/include/asm/barrier.h
> +++ b/arch/x86/include/asm/barrier.h
> @@ -100,6 +100,21 @@
> #define set_mb(var, value) do { var = value; barrier(); } while (0)
> #endif
>
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + barrier(); \
> + ___p1; \
> +})
> +
> /*
> * Stop RDTSC speculation. This is needed when you need to use RDTSC
> * (or get_cycles or vread that possibly accesses the TSC) in a defined
> --- a/arch/xtensa/include/asm/barrier.h
> +++ b/arch/xtensa/include/asm/barrier.h
> @@ -9,21 +9,14 @@
> #ifndef _XTENSA_SYSTEM_H
> #define _XTENSA_SYSTEM_H
>
> -#define smp_read_barrier_depends() do { } while(0)
> -#define read_barrier_depends() do { } while(0)
> -
> #define mb() ({ __asm__ __volatile__("memw" : : : "memory"); })
> #define rmb() barrier()
> #define wmb() mb()
>
> #ifdef CONFIG_SMP
> #error smp_* not defined
> -#else
> -#define smp_mb() barrier()
> -#define smp_rmb() barrier()
> -#define smp_wmb() barrier()
> #endif
>
> -#define set_mb(var, value) do { var = value; mb(); } while (0)
> +#include <asm-generic/barrier.h>
>
> #endif /* _XTENSA_SYSTEM_H */
> --- a/include/asm-generic/barrier.h
> +++ b/include/asm-generic/barrier.h
> @@ -1,4 +1,5 @@
> -/* Generic barrier definitions, based on MN10300 definitions.
> +/*
> + * Generic barrier definitions, based on MN10300 definitions.
> *
> * It should be possible to use these on really simple architectures,
> * but it serves more as a starting point for new ports.
> @@ -16,35 +17,67 @@
>
> #ifndef __ASSEMBLY__
>
> -#define nop() asm volatile ("nop")
> +#include <asm/compiler.h>
> +
> +#ifndef nop
> +#define nop() asm volatile ("nop")
> +#endif
>
> /*
> - * Force strict CPU ordering.
> - * And yes, this is required on UP too when we're talking
> - * to devices.
> + * Force strict CPU ordering. And yes, this is required on UP too when we're
> + * talking to devices.
> *
> - * This implementation only contains a compiler barrier.
> + * Fall back to compiler barriers if nothing better is provided.
> */
>
> -#define mb() asm volatile ("": : :"memory")
> -#define rmb() mb()
> -#define wmb() asm volatile ("": : :"memory")
> +#ifndef mb
> +#define mb() barrier()
> +#endif
> +
> +#ifndef rmb
> +#define rmb() barrier()
> +#endif
> +
> +#ifndef wmb
> +#define wmb() barrier()
> +#endif
> +
> +#ifndef read_barrier_depends
> +#define read_barrier_depends() do {} while (0)
> +#endif
>
> #ifdef CONFIG_SMP
> #define smp_mb() mb()
> #define smp_rmb() rmb()
> #define smp_wmb() wmb()
> +#define smp_read_barrier_depends() read_barrier_depends()
> #else
> #define smp_mb() barrier()
> #define smp_rmb() barrier()
> #define smp_wmb() barrier()
> +#define smp_read_barrier_depends() do {} while (0)
> #endif
>
> +#ifndef set_mb
> #define set_mb(var, value) do { var = value; mb(); } while (0)
> +#endif
> +
> #define set_wmb(var, value) do { var = value; wmb(); } while (0)
>
> -#define read_barrier_depends() do {} while (0)
> -#define smp_read_barrier_depends() do {} while (0)
> +#define smp_store_release(p, v) \
> +do { \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ACCESS_ONCE(*p) = (v); \
> +} while (0)
> +
> +#define smp_load_acquire(p) \
> +({ \
> + typeof(*p) ___p1 = ACCESS_ONCE(*p); \
> + compiletime_assert_atomic_type(*p); \
> + smp_mb(); \
> + ___p1; \
> +})
>
> #endif /* !__ASSEMBLY__ */
> #endif /* __ASM_GENERIC_BARRIER_H */
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -298,6 +298,11 @@ void ftrace_likely_update(struct ftrace_
> # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
> #endif
>
> +/* Is this type a native word size -- useful for atomic operations */
> +#ifndef __native_word
> +# define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
> +#endif
> +
> /* Compile time object size, -1 for unknown */
> #ifndef __compiletime_object_size
> # define __compiletime_object_size(obj) -1
> @@ -337,6 +342,10 @@ void ftrace_likely_update(struct ftrace_
> #define compiletime_assert(condition, msg) \
> _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
>
> +#define compiletime_assert_atomic_type(t) \
> + compiletime_assert(__native_word(t), \
> + "Need native word sized stores/loads for atomicity.")
> +
> /*
> * Prevent the compiler from merging or refetching accesses. The compiler
> * is also forbidden from reordering successive instances of ACCESS_ONCE(),
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox