From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v2] USB: serial: cp210x: Implement GPIO support for CP2102N From: Johan Hovold Message-Id: <20180720104442.GC19245@localhost> Date: Fri, 20 Jul 2018 12:44:42 +0200 To: Karoly Pados Cc: Johan Hovold , Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org List-ID: T24gV2VkLCBKdWwgMTgsIDIwMTggYXQgMTE6MjA6MDRQTSArMDIwMCwgS2Fyb2x5IFBhZG9zIHdy b3RlOgo+IFRoaXMgaXMgdjIgb2YgdGhlIHBhdGNoIGFuZCBhZGRyZXNzZXMgYWxsIGZlZWRiYWNr IHByZXZpb3VzbHkKPiByZWNlaXZlZCBmcm9tIHRoZSBtYWludGFpbmVyLiBOZXcgaW5wdXQvb3V0 cHV0IHN1cHBvcnQgc3RheWVkCj4gYXMgZGlzY3Vzc2VkIG9uIHRoZSBlLW1haWwgbGlzdHMgc2Vw YXJhdGVseS4gQ1AyMTA1IGlzIGFsc28KPiB1c2luZyB0aGUgbmV3IGNvZGUgc3RydWN0dXJlLCBi dXQgZHVlIHRvIG1pc3Npbmcgd2F5IHRvIGdldAo+IGRlZmF1bHQgcGluIHN0YXRlcyBhZnRlciBy ZXNldCBmcm9tIHRoZSBkZXZpY2UsIHN1cHBvcnQKPiBmb3IgdGhpcyBkZXZpY2UgaXMgYmFzaWNh bGx5IHN0aWxsIG91dHB1dC1vbmx5IGFzIGJlZm9yZSwgYXQKPiBsZWFzdCBpbiBuYW1lLiBCdXQg Q1AyMTA1IGFuZCBDUDIxMDJOIHBhdGhzIGFyZSB1bmlmaWVkLgoKVGhpcyByZWFkcyBsaWtlIGEg cGF0Y2ggY2hhbmdlbG9nIHJhdGhlciB0aGFuIGEgY29tbWl0IG1lc3NhZ2UuIFBsZWFzZQp0cnkg dG8gcmVwaHJhc2UgdGhpcyBzbyB0aGF0IGl0J3Mgc2VsZi1jb250YWluZWQgYW5kIG5vdCByZWx5 aW5nIG9uCmhhdmluZyByZWFkIHRoZSBtYWlsIHRocmVhZCBmb3IgdjEuCgpJbiB0aGUgZnV0dXJl IHlvdSBzaG91bGQgaW5jbHVkZSBhIGNoYW5nZWxvZyBmcm9tIHdoYXQgY2hhbmdlZCBmcm9tIG9u ZQpyZXZpc2lvbiB0byBhbm90aGVyIGJlbG93IHRoZSBjdXQtb2ZmIGxpbmUgKC0tLSkgaW5zdGVh ZC4KCj4gVGhpcyBwYXRjaCBpcyBiYXNlZCBvbiB0aGUgbGF0ZXN0IHBhdGNoIHNlcmllcyBieSBK b2hhbiBqdXN0Cj4gc3VibWl0dGVkIHRvZGF5LgoKU2hvdWxkIGFsc28gZ28gYmVsb3cgdGhlIGN1 dC1vZmYgbGluZS4KCj4gU2lnbmVkLW9mZi1ieTogS2Fyb2x5IFBhZG9zIDxwYWRvc0BwYWRvcy5o dT4KCk9oLCBhbmQgeW91IHNob3VsZCBoYXZlIGluY2x1ZGVkIE1hcnR5biB3aG8gY29udHJpYnV0 ZWQgdG8gdGhlCmRpc2N1c3Npb24gYWJvdXQgaG93IHRvIGhhbmRsZSBpbnB1dCBtb2RlIG9uIEND LgoKPiAtLS0KPiAgZHJpdmVycy91c2Ivc2VyaWFsL2NwMjEweC5jIHwgMjc0ICsrKysrKysrKysr KysrKysrKysrKysrKysrKysrKy0tLS0tLQo+ICAxIGZpbGUgY2hhbmdlZCwgMjMyIGluc2VydGlv bnMoKyksIDQyIGRlbGV0aW9ucygtKQo+IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9zZXJp YWwvY3AyMTB4LmMgYi9kcml2ZXJzL3VzYi9zZXJpYWwvY3AyMTB4LmMKPiBpbmRleCA0YTExOGVi MTM1OTAuLjgxZjlkM2UxODNjNiAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9zZXJpYWwvY3Ay MTB4LmMKPiArKysgYi9kcml2ZXJzL3VzYi9zZXJpYWwvY3AyMTB4LmMKPiBAQCAtMjI0LDkgKzIy NCwxOSBAQCBNT0RVTEVfREVWSUNFX1RBQkxFKHVzYiwgaWRfdGFibGUpOwo+ICBzdHJ1Y3QgY3Ay MTB4X3NlcmlhbF9wcml2YXRlIHsKPiAgI2lmZGVmIENPTkZJR19HUElPTElCCj4gIAlzdHJ1Y3Qg Z3Bpb19jaGlwCWdjOwo+IC0JdTgJCQljb25maWc7Cj4gLQl1OAkJCWdwaW9fbW9kZTsKPiAgCWJv b2wJCQlncGlvX3JlZ2lzdGVyZWQ7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZSBmb2xsb3dpbmcgdGhy ZWUgZmllbGRzIGFyZSBmb3IgZGV2aWNlcyB0aGF0Cj4gKwkgKiBlbXVsYXRlIGlucHV0L291dHB1 dCBwaW5zIHVzaW5nIG9wZW4tZHJhaW4vcHVzaHB1bGwKPiArCSAqIGRyaXZlIG1vZGVzLgo+ICsJ ICovCj4gKwkvKiBPbmUgYml0IGZvciBlYWNoIEdQSU8sIDEgaWYgcGluIGlzIHB1c2hwdWxsICov Cj4gKwl1OAkJCWdwaW9fcHVzaHB1bGw7Cj4gKwkvKiBPbmUgYml0IGZvciBlYWNoIEdQSU8sIDEg aWYgcGluIGlzIG5vdCBpbiBHUElPIG1vZGUgKi8KPiArCXU4CQkJZ3Bpb19hbHRmdW5jOwo+ICsJ LyogT25lIGJpdCBmb3IgZWFjaCBHUElPLCAxIGlmIHBpbiBkaXJlY3Rpb24gaXMgaW5wdXQgKi8K PiArCXU4CQkJZ3Bpb19pbnB1dDsKCllvdXIgY29kZSBpcyBjbGVhbiwgYnV0IHlvdSdyZSByZWx5 aW5nIGEgYml0IHRvbyBtdWNoIG9uIGNvbW1lbnRzIGluIG15Cm9waW5pb24uIFRoZSBjb2RlIHNo b3VsZCBiZSBzZWxmLWV4cGxhbmF0b3J5IGFuZCBub3QgcmVseSBvbiBpbi1mdW5jdGlvbgpjb21t ZW50cywgdW5sZXNzIHlvdSB3YW50IHRvIGhpZ2hsaWdodCBzb21ldGhpbmcgcGFydGljdWxhcmx5 IGltcG9ydGFudApvciBjbGV2ZXIuCgpJJ3ZlIGRyb3BwZWQgc29tZSBleGFtcGxlcyBvZiB0aGlz IGluIG15IHJld29ya2VkIHZlcnNpb24gb2YgdGhlIHBhdGNoLgoKPiAgI2VuZGlmCj4gIAl1OAkJ CXBhcnRudW07Cj4gIAlzcGVlZF90CQkJbWF4X3NwZWVkOwo+IEBAIC0zNDMsNiArMzUzLDcgQEAg c3RhdGljIHN0cnVjdCB1c2Jfc2VyaWFsX2RyaXZlciAqIGNvbnN0IHNlcmlhbF9kcml2ZXJzW10g PSB7Cj4gICNkZWZpbmUgQ09OVFJPTF9XUklURV9SVFMJMHgwMjAwCj4gIAo+ICAvKiBDUDIxMFhf VkVORE9SX1NQRUNJRklDIHZhbHVlcyAqLwo+ICsjZGVmaW5lIENQMjEwWF9SRUFEXzJOQ09ORklH CTB4MDAwRQo+ICAjZGVmaW5lIENQMjEwWF9SRUFEX0xBVENICTB4MDBDMgo+ICAjZGVmaW5lIENQ MjEwWF9HRVRfUEFSVE5VTQkweDM3MEIKPiAgI2RlZmluZSBDUDIxMFhfR0VUX1BPUlRDT05GSUcJ MHgzNzBDCj4gQEAgLTQ1Miw2ICs0NjMsMTIgQEAgc3RydWN0IGNwMjEweF9jb25maWcgewo+ICAj ZGVmaW5lIENQMjEwNV9HUElPMV9SWExFRF9NT0RFCQlCSVQoMSkKPiAgI2RlZmluZSBDUDIxMDVf R1BJTzFfUlM0ODVfTU9ERQkJQklUKDIpCj4gIAo+ICsvKiBDUDIxMDJOIGNvbmZpZ3VyYXRpb24g YXJyYXkgaW5kaWNlcyAqLwo+ICsjZGVmaW5lIENQMjEwWF8yTkNPTkZJR19DT05GSUdfVkVSU0lP Tl9JRFgJMgo+ICsjZGVmaW5lIENQMjEwWF8yTkNPTkZJR19HUElPX01PREVfSURYCQk1ODEKPiAr I2RlZmluZSBDUDIxMFhfMk5DT05GSUdfR1BJT19SU1RMQVRDSF9JRFgJNTg3Cj4gKyNkZWZpbmUg Q1AyMTBYXzJOQ09ORklHX0dQSU9fQ09OVFJPTF9JRFgJNjAwCj4gKwo+ICAvKiBDUDIxMFhfVkVO RE9SX1NQRUNJRklDLCBDUDIxMFhfV1JJVEVfTEFUQ0ggY2FsbCB3cml0ZXMgdGhlc2UgMHgyIGJ5 dGVzLiAqLwo+ICBzdHJ1Y3QgY3AyMTB4X2dwaW9fd3JpdGUgewo+ICAJdTgJbWFzazsKPiBAQCAt MTMwOCwyMSArMTMyNSwyOSBAQCBzdGF0aWMgdm9pZCBjcDIxMHhfYnJlYWtfY3RsKHN0cnVjdCB0 dHlfc3RydWN0ICp0dHksIGludCBicmVha19zdGF0ZSkKPiAgfQo+ICAKPiAgI2lmZGVmIENPTkZJ R19HUElPTElCCj4gKwo+ICsvKgo+ICsgKiBIZWxwZXIgdG8gZGV0ZXJtaW5lIGlmIGEgc3BlY2lm aWMgc2VyaWFsIGRldmljZSBiZWxvbmdzIHRvIHRoZSBjcDIxMDJuCj4gKyAqIGZhbWlseSBvZiBk ZXZpY2VzLgo+ICsgKi8KPiArc3RhdGljIGJvb2wgY3AyMTB4X2lzX2NwMjEwMm4oc3RydWN0IHVz Yl9zZXJpYWwgKnNlcmlhbCkKPiArewo+ICsJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAq cHJpdiA9IHVzYl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFsKTsKPiArCj4gKwlyZXR1cm4gIChwcml2 LT5wYXJ0bnVtID09IENQMjEwWF9QQVJUTlVNX0NQMjEwMk5fUUZOMjgpIHx8Cj4gKwkJKHByaXYt PnBhcnRudW0gPT0gQ1AyMTBYX1BBUlROVU1fQ1AyMTAyTl9RRk4yNCkgfHwKPiArCQkocHJpdi0+ cGFydG51bSA9PSBDUDIxMFhfUEFSVE5VTV9DUDIxMDJOX1FGTjIwKTsKPiArfQoKSSBhbHNvIGRp ZCBhd2F5IHdpdGggdGhpcyBvbmUgKGFnYWluKS4gVGhlIGNwMjEwMm4gd2F5IG9mIGRlYWxpbmcg d2l0aApncGlvcyBhcHBlYXIgdG8gYmUgdGhlIHN0YW5kYXJkIHdheTsgd2hpbGUgY3AyMTA1IGFu ZCBjcDIxMDggYXJlIHRoZSBvZGQKYmlyZHMuCgo+ICsKPiAgc3RhdGljIGludCBjcDIxMHhfZ3Bp b19yZXF1ZXN0KHN0cnVjdCBncGlvX2NoaXAgKmdjLCB1bnNpZ25lZCBpbnQgb2Zmc2V0KQo+ICB7 Cj4gIAlzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsID0gZ3Bpb2NoaXBfZ2V0X2RhdGEoZ2MpOwo+ ICAJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJpdiA9IHVzYl9nZXRfc2VyaWFsX2Rh dGEoc2VyaWFsKTsKPiAgCj4gLQlzd2l0Y2ggKG9mZnNldCkgewo+IC0JY2FzZSAwOgo+IC0JCWlm IChwcml2LT5jb25maWcgJiBDUDIxMDVfR1BJTzBfVFhMRURfTU9ERSkKPiAtCQkJcmV0dXJuIC1F Tk9ERVY7Cj4gLQkJYnJlYWs7Cj4gLQljYXNlIDE6Cj4gLQkJaWYgKHByaXYtPmNvbmZpZyAmIChD UDIxMDVfR1BJTzFfUlhMRURfTU9ERSB8Cj4gLQkJCQkgICAgQ1AyMTA1X0dQSU8xX1JTNDg1X01P REUpKQo+IC0JCQlyZXR1cm4gLUVOT0RFVjsKPiAtCQlicmVhazsKPiArCWlmIChwcml2LT5ncGlv X2FsdGZ1bmMgJiBCSVQob2Zmc2V0KSkgewo+ICsJCWRldl93YXJuKCZzZXJpYWwtPmludGVyZmFj ZS0+ZGV2LAo+ICsJCQkgIkNhbm5vdCBjb250cm9sIEdQSU8gd2l0aCBhY3RpdmUgYWx0ZXJuYXRl IGZ1bmN0aW9uLlxuIik7CgpJIGRyb3BwZWQgdGhlIHdhcm5pbmcsIHlvdSdyZSBhbHJlYWR5IHJl dHVybmluZyBhbiBlcnJubyBhcyBiZWZvcmUuCgo+ICsJCXJldHVybiAtRU5PREVWOwo+ICAJfQo+ ICAKPiAgCXJldHVybiAwOwo+IEBAIC0xMzMxLDEwICsxMzU2LDE1IEBAIHN0YXRpYyBpbnQgY3Ay MTB4X2dwaW9fcmVxdWVzdChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IG9mZnNl dCkKPiAgc3RhdGljIGludCBjcDIxMHhfZ3Bpb19nZXQoc3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVu c2lnbmVkIGludCBncGlvKQo+ICB7Cj4gIAlzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsID0gZ3Bp b2NoaXBfZ2V0X2RhdGEoZ2MpOwo+ICsJc3RydWN0IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJp diA9IHVzYl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFsKTsKPiArCXU4IHJlcV90eXBlID0gUkVRVFlQ RV9ERVZJQ0VfVE9fSE9TVDsKPiAgCWludCByZXN1bHQ7Cj4gIAl1OCBidWY7Cj4gIAo+IC0JcmVz dWx0ID0gY3AyMTB4X3JlYWRfdmVuZG9yX2Jsb2NrKHNlcmlhbCwgUkVRVFlQRV9JTlRFUkZBQ0Vf VE9fSE9TVCwKPiArCWlmIChwcml2LT5wYXJ0bnVtID09IENQMjEwWF9QQVJUTlVNX0NQMjEwNSkK PiArCQlyZXFfdHlwZSA9IFJFUVRZUEVfSU5URVJGQUNFX1RPX0hPU1Q7Cj4gKwo+ICsJcmVzdWx0 ID0gY3AyMTB4X3JlYWRfdmVuZG9yX2Jsb2NrKHNlcmlhbCwgcmVxX3R5cGUsCj4gIAkJCQkJICBD UDIxMFhfUkVBRF9MQVRDSCwgJmJ1Ziwgc2l6ZW9mKGJ1ZikpOwo+ICAJaWYgKHJlc3VsdCA8IDAp Cj4gIAkJcmV0dXJuIHJlc3VsdDsKPiBAQCAtMTM0NSwzNCArMTM3NSw4MiBAQCBzdGF0aWMgaW50 IGNwMjEweF9ncGlvX2dldChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IGdwaW8p Cj4gIHN0YXRpYyB2b2lkIGNwMjEweF9ncGlvX3NldChzdHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5z aWduZWQgaW50IGdwaW8sIGludCB2YWx1ZSkKPiAgewo+ICAJc3RydWN0IHVzYl9zZXJpYWwgKnNl cmlhbCA9IGdwaW9jaGlwX2dldF9kYXRhKGdjKTsKPiArCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3By aXZhdGUgKnByaXYgPSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7Cj4gIAlzdHJ1Y3QgY3Ay MTB4X2dwaW9fd3JpdGUgYnVmOwo+ICsJaW50IHJlc3VsdCA9IDA7Cj4gIAo+IC0JaWYgKHZhbHVl ID09IDEpCj4gLQkJYnVmLnN0YXRlID0gQklUKGdwaW8pOwo+IC0JZWxzZQo+IC0JCWJ1Zi5zdGF0 ZSA9IDA7Cj4gLQo+ICsJYnVmLnN0YXRlID0gKHZhbHVlID09IDEpID8gQklUKGdwaW8pIDogMDsK Ck5vIG5lZWQgdG8gY2hhbmdlIHRoaXMsIGFuZCBnZW5lcmFsbHkgdHJ5IHRvIGF2b2lkIHRoZSB0 ZXJuYXJ5Cm9wZXJhdG9yIHdoaWNoIG9mdGVuIGp1c3QgbWFrZXMgY29kZSBoYXJkZXIgdG8gcmVh ZC4KCj4gIAlidWYubWFzayA9IEJJVChncGlvKTsKPiAgCj4gLQljcDIxMHhfd3JpdGVfdmVuZG9y X2Jsb2NrKHNlcmlhbCwgUkVRVFlQRV9IT1NUX1RPX0lOVEVSRkFDRSwKPiAtCQkJCSAgQ1AyMTBY X1dSSVRFX0xBVENILCAmYnVmLCBzaXplb2YoYnVmKSk7Cj4gKwlpZiAocHJpdi0+cGFydG51bSA9 PSBDUDIxMFhfUEFSVE5VTV9DUDIxMDUpIHsKPiArCQlyZXN1bHQgPSBjcDIxMHhfd3JpdGVfdmVu ZG9yX2Jsb2NrKHNlcmlhbCwKPiArCQkJCQkJICAgUkVRVFlQRV9IT1NUX1RPX0lOVEVSRkFDRSwK PiArCQkJCQkJICAgQ1AyMTBYX1dSSVRFX0xBVENILCAmYnVmLAo+ICsJCQkJCQkgICBzaXplb2Yo YnVmKSk7Cj4gKwl9IGVsc2UgaWYgKGNwMjEweF9pc19jcDIxMDJuKHNlcmlhbCkpIHsKClNvIEkg anVzdCBtYWRlIHRoaXMgdGhlIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gYnkgZHJvcHBpbmcgdGhl CmNvbmRpdGlvbmFsLgoKPiArCQl1MTYgd0luZGV4ID0gYnVmLnN0YXRlIDw8IDggfCBidWYubWFz azsKPiArCj4gKwkJcmVzdWx0ID0gdXNiX2NvbnRyb2xfbXNnKHNlcmlhbC0+ZGV2LAo+ICsJCQkJ CSB1c2Jfc25kY3RybHBpcGUoc2VyaWFsLT5kZXYsIDApLAo+ICsJCQkJCSBDUDIxMFhfVkVORE9S X1NQRUNJRklDLAo+ICsJCQkJCSBSRVFUWVBFX0hPU1RfVE9fREVWSUNFLAo+ICsJCQkJCSBDUDIx MFhfV1JJVEVfTEFUQ0gsCj4gKwkJCQkJIHdJbmRleCwKPiArCQkJCQkgTlVMTCwgMCwgVVNCX0NU UkxfU0VUX1RJTUVPVVQpOwo+ICsJfQo+ICsKPiArCWlmIChyZXN1bHQgPCAwKQo+ICsJCWRldl9l cnIoJnNlcmlhbC0+aW50ZXJmYWNlLT5kZXYsICJGYWlsZWQgdG8gc2V0IEdQSU8gdmFsdWUuXG4i KTsKClRoaXMgY291bGQgaW5jbHVkZSB0aGUgZXJybm8uCgo+ICB9Cj4gIAo+ICBzdGF0aWMgaW50 IGNwMjEweF9ncGlvX2RpcmVjdGlvbl9nZXQoc3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVuc2lnbmVk IGludCBncGlvKQo+ICB7Cj4gLQkvKiBIYXJkd2FyZSBkb2VzIG5vdCBzdXBwb3J0IGFuIGlucHV0 IG1vZGUgKi8KPiAtCXJldHVybiAwOwo+ICsJc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCA9IGdw aW9jaGlwX2dldF9kYXRhKGdjKTsKPiArCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3ByaXZhdGUgKnBy aXYgPSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7Cj4gKwo+ICsJcmV0dXJuIHByaXYtPmdw aW9faW5wdXQgJiBCSVQoZ3Bpbyk7Cj4gIH0KPiAgCj4gIHN0YXRpYyBpbnQgY3AyMTB4X2dwaW9f ZGlyZWN0aW9uX2lucHV0KHN0cnVjdCBncGlvX2NoaXAgKmdjLCB1bnNpZ25lZCBpbnQgZ3BpbykK PiAgewo+IC0JLyogSGFyZHdhcmUgZG9lcyBub3Qgc3VwcG9ydCBhbiBpbnB1dCBtb2RlICovCj4g LQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsJc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCA9IGdwaW9j aGlwX2dldF9kYXRhKGdjKTsKPiArCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3ByaXZhdGUgKnByaXYg PSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7Cj4gKwo+ICsJaWYgKHByaXYtPnBhcnRudW0g PT0gQ1AyMTBYX1BBUlROVU1fQ1AyMTA1KSB7Cj4gKwkJLyogSGFyZHdhcmUgZG9lcyBub3Qgc3Vw cG9ydCBhbiBpbnB1dCBtb2RlICovCj4gKwkJcmV0dXJuIC1FTk9UU1VQUDsKPiArCX0gZWxzZSBp ZiAoY3AyMTB4X2lzX2NwMjEwMm4oc2VyaWFsKSkgewoKVGhpcyBzaG91bGQgYmUgdGhlIGRlZmF1 bHQgaW1wbGVtZW50YXRpb24uCgo+ICsJCS8qIFB1c2gtcHVsbCBwaW5zIGNhbm5vdCBiZSBjaGFu Z2VkIHRvIGJlIGlucHV0cyAqLwo+ICsJCWlmIChwcml2LT5ncGlvX3B1c2hwdWxsICYgQklUKGdw aW8pKSB7Cj4gKwkJCWRldl93YXJuKCZzZXJpYWwtPmludGVyZmFjZS0+ZGV2LAo+ICsJCQkJICJD YW5ub3QgY2hhbmdlIGRpcmVjdGlvbiBvZiBhIHB1c2gtcHVsbCBHUElPIHRvIGlucHV0LlxuIik7 CgpObyBuZWVkIHRvIHdhcm4sIGFzIHlvdSdyZSByZXR1cm5pbmcgYW4gZXJyb3IuCgo+ICsJCQly ZXR1cm4gLUVQRVJNOwoKQW5kIHRoaXMgaXNuJ3QgcmVhbGx5IGEgcGVybWlzc2lvbiBpc3N1ZTsg LUVJTlZBTCBpcyBtb3JlIGFwcHJvcHJpYXRlLgoKCj4gKwkJfQo+ICsKPiArCQkvKiBNYWtlIHN1 cmUgdG8gcmVsZWFzZSBwaW4gaWYgaXQgaXMgYmVpbmcgZHJpdmVuIGxvdyAqLwo+ICsJCWNwMjEw eF9ncGlvX3NldChnYywgZ3BpbywgMSk7Cj4gKwo+ICsJCS8qIE5vdGUgcGluIGRpcmVjdGlvbiB0 byBvdXJzZWx2ZXMgKi8KPiArCQlwcml2LT5ncGlvX2lucHV0IHw9IEJJVChncGlvKTsKPiArCj4g KwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIC1FUEVSTTsKPiAgfQo+ICAKPiAgc3Rh dGljIGludCBjcDIxMHhfZ3Bpb19kaXJlY3Rpb25fb3V0cHV0KHN0cnVjdCBncGlvX2NoaXAgKmdj LCB1bnNpZ25lZCBpbnQgZ3BpbywKPiAgCQkJCQlpbnQgdmFsdWUpCj4gIHsKPiArCXN0cnVjdCB1 c2Jfc2VyaWFsICpzZXJpYWwgPSBncGlvY2hpcF9nZXRfZGF0YShnYyk7Cj4gKwlzdHJ1Y3QgY3Ay MTB4X3NlcmlhbF9wcml2YXRlICpwcml2ID0gdXNiX2dldF9zZXJpYWxfZGF0YShzZXJpYWwpOwo+ ICsKPiArCS8qIE5vdGUgcGluIGRpcmVjdGlvbiB0byBvdXJzZWx2ZXMgKi8KPiArCXByaXYtPmdw aW9faW5wdXQgJj0gfkJJVChncGlvKTsKPiArCj4gKwkvKiBTZXQgcmVxdWVzdGVkIGluaXRpYWwg b3V0cHV0IHZhbHVlICovCgpJJ2QgZHJvcCB0aGVzZSBjb21tZW50cyBmb3IgZXhhbXBsZS4KCj4g KwljcDIxMHhfZ3Bpb19zZXQoZ2MsIGdwaW8sIHZhbHVlKTsKPiArCj4gIAlyZXR1cm4gMDsKPiAg fQo+ICAKPiBAQCAtMTM4NSwxMSArMTQ2MywxMSBAQCBzdGF0aWMgaW50IGNwMjEweF9ncGlvX3Nl dF9jb25maWcoc3RydWN0IGdwaW9fY2hpcCAqZ2MsIHVuc2lnbmVkIGludCBncGlvLAo+ICAKPiAg CS8qIFN1Y2NlZWQgb25seSBpZiBpbiBjb3JyZWN0IG1vZGUgKHRoaXMgY2FuJ3QgYmUgc2V0IGF0 IHJ1bnRpbWUpICovCj4gIAlpZiAoKHBhcmFtID09IFBJTl9DT05GSUdfRFJJVkVfUFVTSF9QVUxM KSAmJgo+IC0JICAgIChwcml2LT5ncGlvX21vZGUgJiBCSVQoZ3BpbykpKQo+ICsJICAgIChwcml2 LT5ncGlvX3B1c2hwdWxsICYgQklUKGdwaW8pKSkKPiAgCQlyZXR1cm4gMDsKPiAgCj4gIAlpZiAo KHBhcmFtID09IFBJTl9DT05GSUdfRFJJVkVfT1BFTl9EUkFJTikgJiYKPiAtCSAgICAhKHByaXYt PmdwaW9fbW9kZSAmIEJJVChncGlvKSkpCj4gKwkgICAgIShwcml2LT5ncGlvX3B1c2hwdWxsICYg QklUKGdwaW8pKSkKPiAgCQlyZXR1cm4gMDsKPiAgCj4gIAlyZXR1cm4gLUVOT1RTVVBQOwo+IEBA IC0xNDAyLDEzICsxNDgwLDE0IEBAIHN0YXRpYyBpbnQgY3AyMTB4X2dwaW9fc2V0X2NvbmZpZyhz dHJ1Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgaW50IGdwaW8sCj4gICAqIHRoaXMgZHJpdmVy IHRoYXQgcHJvdmlkZSBHUElPIGRvIHNvIGluIGEgd2F5IHRoYXQgZG9lcyBub3QgaW1wYWN0IG90 aGVyCj4gICAqIHNpZ25hbHMgYW5kIGFyZSB0aHVzIGV4cGVjdGVkIHRvIGhhdmUgdmVyeSBkaWZm ZXJlbnQgaW5pdGlhbGlzYXRpb24uCj4gICAqLwo+IC1zdGF0aWMgaW50IGNwMjEwNV9zaGFyZWRf Z3Bpb19pbml0KHN0cnVjdCB1c2Jfc2VyaWFsICpzZXJpYWwpCj4gK3N0YXRpYyBpbnQgY3AyMTA1 X2dwaW9jb25mX2luaXQoc3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCkKPiAgewo+ICAJc3RydWN0 IGNwMjEweF9zZXJpYWxfcHJpdmF0ZSAqcHJpdiA9IHVzYl9nZXRfc2VyaWFsX2RhdGEoc2VyaWFs KTsKPiAgCXN0cnVjdCBjcDIxMHhfcGluX21vZGUgbW9kZTsKPiAgCXN0cnVjdCBjcDIxMHhfY29u ZmlnIGNvbmZpZzsKPiAgCXU4IGludGZfbnVtID0gY3AyMTB4X2ludGVyZmFjZV9udW0oc2VyaWFs KTsKPiAgCWludCByZXN1bHQ7Cj4gKwl1OCBpZmFjZV9jb25maWc7Cj4gIAo+ICAJcmVzdWx0ID0g Y3AyMTB4X3JlYWRfdmVuZG9yX2Jsb2NrKHNlcmlhbCwgUkVRVFlQRV9ERVZJQ0VfVE9fSE9TVCwK PiAgCQkJCQkgIENQMjEwWF9HRVRfREVWSUNFTU9ERSwgJm1vZGUsCj4gQEAgLTE0MjQsMjAgKzE1 MDMsMjUgQEAgc3RhdGljIGludCBjcDIxMDVfc2hhcmVkX2dwaW9faW5pdChzdHJ1Y3QgdXNiX3Nl cmlhbCAqc2VyaWFsKQo+ICAKPiAgCS8qICAyIGJhbmtzIG9mIEdQSU8gLSBPbmUgZm9yIHRoZSBw aW5zIHRha2VuIGZyb20gZWFjaCBzZXJpYWwgcG9ydCAqLwo+ICAJaWYgKGludGZfbnVtID09IDAp IHsKPiAtCQlpZiAobW9kZS5lY2kgPT0gQ1AyMTBYX1BJTl9NT0RFX01PREVNKQo+ICsJCWlmICht b2RlLmVjaSA9PSBDUDIxMFhfUElOX01PREVfTU9ERU0pIHsKPiArCQkJLyogTWFyayBhbGwgR1BJ T3Mgb2YgdGhpcyBpbnRlcmZhY2UgYXMgcmVzZXJ2ZWQgKi8KPiArCQkJcHJpdi0+Z3Bpb19hbHRm dW5jID0gMHhGRjsKPiAgCQkJcmV0dXJuIDA7Cj4gKwkJfQo+ICAKPiAtCQlwcml2LT5jb25maWcg PSBjb25maWcuZWNpX2NmZzsKPiAtCQlwcml2LT5ncGlvX21vZGUgPSAodTgpKChsZTE2X3RvX2Nw dShjb25maWcuZ3Bpb19tb2RlKSAmCj4gKwkJaWZhY2VfY29uZmlnID0gY29uZmlnLmVjaV9jZmc7 Cj4gKwkJcHJpdi0+Z3Bpb19wdXNocHVsbCA9ICh1OCkoKGxlMTZfdG9fY3B1KGNvbmZpZy5ncGlv X21vZGUpICYKPiAgCQkJCQkJQ1AyMTBYX0VDSV9HUElPX01PREVfTUFTSykgPj4KPiAgCQkJCQkJ Q1AyMTBYX0VDSV9HUElPX01PREVfT0ZGU0VUKTsKPiAgCQlwcml2LT5nYy5uZ3BpbyA9IDI7Cj4g IAl9IGVsc2UgaWYgKGludGZfbnVtID09IDEpIHsKPiAtCQlpZiAobW9kZS5zY2kgPT0gQ1AyMTBY X1BJTl9NT0RFX01PREVNKQo+IC0JCQlyZXR1cm4gMDsKPiArCQlpZiAobW9kZS5zY2kgPT0gQ1Ay MTBYX1BJTl9NT0RFX01PREVNKSB7Cj4gKwkJCS8qIE1hcmsgYWxsIEdQSU9zIG9mIHRoaXMgaW50 ZXJmYWNlIGFzIHJlc2VydmVkICovCj4gKwkJCXByaXYtPmdwaW9fYWx0ZnVuYyA9IDB4RkY7CgpI ZXJlIHRoZSByZXR1cm4gMCBmZWxsIG91dCwgd2hpY2ggY291bGQgbGVhZCB0byB0aGUgcGlucyBi ZWluZwpjb25zaWRlcmVkIGF2YWlsYWJsZS4KCj4gKwkJfQo+ICAKPiAtCQlwcml2LT5jb25maWcg PSBjb25maWcuc2NpX2NmZzsKPiAtCQlwcml2LT5ncGlvX21vZGUgPSAodTgpKChsZTE2X3RvX2Nw dShjb25maWcuZ3Bpb19tb2RlKSAmCj4gKwkJaWZhY2VfY29uZmlnID0gY29uZmlnLnNjaV9jZmc7 Cj4gKwkJcHJpdi0+Z3Bpb19wdXNocHVsbCA9ICh1OCkoKGxlMTZfdG9fY3B1KGNvbmZpZy5ncGlv X21vZGUpICYKPiAgCQkJCQkJQ1AyMTBYX1NDSV9HUElPX01PREVfTUFTSykgPj4KPiAgCQkJCQkJ Q1AyMTBYX1NDSV9HUElPX01PREVfT0ZGU0VUKTsKPiAgCQlwcml2LT5nYy5uZ3BpbyA9IDM7Cj4g QEAgLTE0NDUsNiArMTUyOSwxMTggQEAgc3RhdGljIGludCBjcDIxMDVfc2hhcmVkX2dwaW9faW5p dChzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsKQo+ICAJCXJldHVybiAtRU5PREVWOwo+ICAJfQo+ ICAKPiArCS8qIE1hcmsgYWxsIHBpbnMgd2hpY2ggYXJlIG5vdCBpbiBHUElPIG1vZGUgKi8KPiAr CXByaXYtPmdwaW9fYWx0ZnVuYyA9IDA7Cj4gKwlpZiAoaWZhY2VfY29uZmlnICYgQ1AyMTA1X0dQ SU8wX1RYTEVEX01PREUpCS8qIEdQSU8gMCAqLwo+ICsJCXByaXYtPmdwaW9fYWx0ZnVuYyB8PSBC SVQoMCk7Cj4gKwlpZiAoaWZhY2VfY29uZmlnICYgKENQMjEwNV9HUElPMV9SWExFRF9NT0RFIHwJ LyogR1BJTyAxICovCj4gKwkJCUNQMjEwNV9HUElPMV9SUzQ4NV9NT0RFKSkKPiArCQlwcml2LT5n cGlvX2FsdGZ1bmMgfD0gQklUKDEpOwo+ICsKPiArCS8qIERyaXZlciBpbXBsZW1lbnRhdGlvbiBm b3IgQ1AyMTA1IG9ubHkgc3VwcG9ydHMgb3V0cHV0cyAqLwo+ICsJcHJpdi0+Z3Bpb19pbnB1dCA9 IDA7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY3AyMTAybl9ncGlv Y29uZl9pbml0KHN0cnVjdCB1c2Jfc2VyaWFsICpzZXJpYWwpCj4gK3sKPiArCXN0cnVjdCBjcDIx MHhfc2VyaWFsX3ByaXZhdGUgKnByaXYgPSB1c2JfZ2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7Cj4g Kwljb25zdCB1MTYgQ09ORklHX1NJWkUgPSAweDAyQTY7CgpMb3dlciBjYXNlIHZhcmlhYmxlIG5h bWVzLCBhbmQgSSdkIHVzZSBsb3dlci1jYXNlIGZvciBoZXggY29uc3RhbnRzIGFzCndlbGwuCgo+ ICsJdTggZ3Bpb19yc3RfbGF0Y2g7Cj4gKwl1OCBjb25maWdfdmVyc2lvbjsKPiArCXU4IGdwaW9f cHVzaHB1bGw7Cj4gKwl1OCAqY29uZmlnX2J1ZjsKPiArCXU4IGdwaW9fbGF0Y2g7Cj4gKwl1OCBn cGlvX2N0cmw7Cj4gKwlpbnQgcmVzdWx0Owo+ICsJdTggaTsKPiArCj4gKwkvKiBSZXRyaWV2ZSBk ZXZpY2UgY29uZmlndXJhdGlvbiBmcm9tIHRoZSBkZXZpY2UuCj4gKwkgKiBUaGUgYXJyYXkgcmVj ZWl2ZWQgY29udGFpbnMgYWxsIGN1c3RvbWl6YXRpb24gc2V0dGluZ3MKPiArCSAqIGRvbmUgYXQg dGhlIGZhY3RvcnkvbWFudWZhY3R1cmVyLgo+ICsJICogRm9ybWF0IG9mIHRoZSBhcnJheSBpcyBk b2N1bWVudGVkIGF0IHRoZSB0aW1lIG9mIHdyaXRpbmcgYXQKPiArCSAqIGh0dHBzOi8vd3d3LnNp bGFicy5jb20vY29tbXVuaXR5L2ludGVyZmFjZS9rbm93bGVkZ2UtYmFzZS5lbnRyeS5odG1sLzIw MTcvMDMvMzEvY3AyMTAybl9zZXRjb25maWcteHNmYQo+ICsJICovCgpNdWx0aS1saW5lIGNvbW1l bnQgc3R5bGUgaXMKCgkvKgoJICogYmxhaC4uLgoJICovCgphcyBJIGFscmVhZHkgbWVudGlvbmVk IGluIGNvbW1lbnRzIHRvIHYxLgoKPiArCWNvbmZpZ19idWYgPSBrbWFsbG9jKENPTkZJR19TSVpF LCBHRlBfS0VSTkVMKTsKPiArCWlmICghY29uZmlnX2J1ZikKPiArCQlyZXR1cm4gLUVOT01FTTsK PiArCj4gKwlyZXN1bHQgPSBjcDIxMHhfcmVhZF92ZW5kb3JfYmxvY2soc2VyaWFsLAo+ICsJCQkJ CSAgUkVRVFlQRV9ERVZJQ0VfVE9fSE9TVCwKPiArCQkJCQkgIENQMjEwWF9SRUFEXzJOQ09ORklH LAo+ICsJCQkJCSAgY29uZmlnX2J1ZiwKPiArCQkJCQkgIENPTkZJR19TSVpFKTsKPiArCWlmIChy ZXN1bHQgPCAwKSB7Cj4gKwkJa2ZyZWUoY29uZmlnX2J1Zik7Cj4gKwkJcmV0dXJuIC1FSU87CgpS ZXR1cm4gcmVzdWx0LgoKPiArCX0KPiArCj4gKwljb25maWdfdmVyc2lvbiA9IGNvbmZpZ19idWZb Q1AyMTBYXzJOQ09ORklHX0NPTkZJR19WRVJTSU9OX0lEWF07Cj4gKwlncGlvX3B1c2hwdWxsID0g Y29uZmlnX2J1ZltDUDIxMFhfMk5DT05GSUdfR1BJT19NT0RFX0lEWF07Cj4gKwlncGlvX2N0cmwg PSBjb25maWdfYnVmW0NQMjEwWF8yTkNPTkZJR19HUElPX0NPTlRST0xfSURYXTsKPiArCWdwaW9f cnN0X2xhdGNoID0gY29uZmlnX2J1ZltDUDIxMFhfMk5DT05GSUdfR1BJT19SU1RMQVRDSF9JRFhd Owo+ICsKPiArCWtmcmVlKGNvbmZpZ19idWYpOwo+ICsKPiArCS8qIE1ha2Ugc3VyZSB0aGlzIGlz IGEgY29uZmlnIGZvcm1hdCB3ZSB1bmRlcnN0YW5kICovCj4gKwlpZiAoY29uZmlnX3ZlcnNpb24g IT0gMHgwMSkKPiArCQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsKPiArCS8qIFdlIG9ubHkgc3VwcG9y dCA0IEdQSU9zIGV2ZW4gb24gdGhlIFFGTjI4IHBhY2thZ2UsIGJlY2F1c2UKPiArCSAqIGNvbmZp ZyBsb2NhdGlvbnMgb2YgR1BJT3MgNC02IGRldGVybWluZWQgdXNpbmcgcmV2ZXJzZQo+ICsJICog ZW5naW5lZXJpbmcgcmV2ZWFsZWQgY29uZmxpY3Rpbmcgb2Zmc2V0cyB3aXRoIG90aGVyCj4gKwkg KiBkb2N1bWVudGVkIGZ1bmN0aW9ucy4gU28gd2UnbGwganVzdCBwbGF5IGl0IHNhZmUgZm9yIG5v dy4KPiArCSAqLwo+ICsJcHJpdi0+Z2MubmdwaW8gPSA0Owo+ICsKPiArCS8qIEdldCBkZWZhdWx0 IHBpbiBzdGF0ZXMgYWZ0ZXIgcmVzZXQuIE5lZWRlZCBzbyB3ZSBjYW4gZGV0ZXJtaW5lCj4gKwkg KiB0aGUgZGlyZWN0aW9uIG9mIGFuIG9wZW4tZHJhaW4gcGluLgo+ICsJICovCj4gKwlncGlvX2xh dGNoID0gKGdwaW9fcnN0X2xhdGNoID4+IDMpICYgMHgwRjsKPiArCj4gKwkvKiAwIGluZGljYXRl cyBvcGVuLWRyYWluIG1vZGUsIDEgaXMgcHVzaC1wdWxsICovCj4gKwlwcml2LT5ncGlvX3B1c2hw dWxsID0gKGdwaW9fcHVzaHB1bGwgPj4gMykgJiAweDBGOwo+ICsKPiArCS8qIDAgaW5kaWNhdGVz IEdQSU8gbW9kZSwgMSBpcyBhbHRlcm5hdGUgZnVuY3Rpb24gKi8KPiArCXByaXYtPmdwaW9fYWx0 ZnVuYyA9IChncGlvX2N0cmwgPj4gMikgJiAweDBGOwo+ICsKPiArCS8qIFRoZSBDUDIxMDJOIGRv ZXMgbm90IHN0cmljdGx5IGhhcyBpbnB1dCBhbmQgb3V0cHV0IHBpbiBtb2RlcywKPiArCSAqIGl0 IG9ubHkga25vd3Mgb3Blbi1kcmFpbiBhbmQgcHVzaC1wdWxsIG1vZGVzIHdoaWNoIGlzIHNldCBh dAo+ICsJICogZmFjdG9yeS4gQW4gb3Blbi1kcmFpbiBwaW4gY2FuIGZ1bmN0aW9uIGJvdGggYXMg YW4KPiArCSAqIGlucHV0IG9yIGFuIG91dHB1dC4gV2UgZW11bGF0ZSBpbnB1dCBtb2RlIGZvciBv cGVuLWRyYWluIHBpbnMKPiArCSAqIGJ5IG1ha2luZyBzdXJlIHRoZXkgYXJlIG5vdCBkcml2ZW4g bG93LCBhbmQgd2UgZG8gbm90IGFsbG93Cj4gKwkgKiBwdXNoLXB1bGwgcGlucyB0byBiZSBzZXQg YXMgYW4gaW5wdXQuCj4gKwkgKi8KPiArCWZvciAoaSA9IDA7IGkgPCBwcml2LT5nYy5uZ3Bpbzsg KytpKSB7Cj4gKwkJLyogU2V0IGRpcmVjdGlvbiB0byAiaW5wdXQiIGlmZgo+ICsJCSAqIHBpbiBp cyBvcGVuLWRyYWluIGFuZCByZXNldCB2YWx1ZSBpcyAxCj4gKwkJICovCj4gKwkJaWYgKCEocHJp di0+Z3Bpb19wdXNocHVsbCAmIEJJVChpKSkgJiYgKGdwaW9fbGF0Y2ggJiBCSVQoaSkpKQo+ICsJ CQlwcml2LT5ncGlvX2lucHV0IHw9IEJJVChpKTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiAr fQo+ICsKPiArc3RhdGljIGludCBjcDIxMHhfZ3Bpb19pbml0KHN0cnVjdCB1c2Jfc2VyaWFsICpz ZXJpYWwpCj4gK3sKPiArCXN0cnVjdCBjcDIxMHhfc2VyaWFsX3ByaXZhdGUgKnByaXYgPSB1c2Jf Z2V0X3NlcmlhbF9kYXRhKHNlcmlhbCk7Cj4gKwlpbnQgcmVzdWx0ID0gMDsKPiArCj4gKwlpZiAo Y3AyMTB4X2lzX2NwMjEwMm4oc2VyaWFsKSkKPiArCQlyZXN1bHQgPSBjcDIxMDJuX2dwaW9jb25m X2luaXQoc2VyaWFsKTsKPiArCWVsc2UgaWYgKHByaXYtPnBhcnRudW0gPT0gQ1AyMTBYX1BBUlRO VU1fQ1AyMTA1KQo+ICsJCXJlc3VsdCA9IGNwMjEwNV9ncGlvY29uZl9pbml0KHNlcmlhbCk7Cj4g KwllbHNlCj4gKwkJcmV0dXJuIDA7CgpUaGlzIGNvdWxkIGJlIGEgc3dpdGNoLXN0YXRlbWVudC4K Cj4gKwo+ICsJaWYgKHJlc3VsdCA8IDApIHsKPiArCQlkZXZfZXJyKCZzZXJpYWwtPmludGVyZmFj ZS0+ZGV2LAo+ICsJCQkiR1BJTyBpbml0aWFsaXNhdGlvbiBmYWlsZWQsIGNvbnRpbnVpbmcgd2l0 aG91dCBHUElPIHN1cHBvcnRcbiIpOwo+ICsJCXJldHVybiByZXN1bHQ7Cj4gKwl9CgpCeSBtb3Zp bmcgdGhlIGVycm9yIG1lc3NhZ2UgaW50byBjcDIxMHhfZ3Bpb19pbml0LCB3ZSdkIG5vIGxvbmdl ciBsb2cKYW55IHJlZ2lzdHJhdGlvbiBlcnJvcnMgYmVsb3cuCgo+ICsKPiAgCXByaXYtPmdjLmxh YmVsID0gImNwMjEweCI7Cj4gIAlwcml2LT5nYy5yZXF1ZXN0ID0gY3AyMTB4X2dwaW9fcmVxdWVz dDsKPiAgCXByaXYtPmdjLmdldF9kaXJlY3Rpb24gPSBjcDIxMHhfZ3Bpb19kaXJlY3Rpb25fZ2V0 Owo+IEBAIC0xNDc3LDcgKzE2NzMsNyBAQCBzdGF0aWMgdm9pZCBjcDIxMHhfZ3Bpb19yZW1vdmUo c3RydWN0IHVzYl9zZXJpYWwgKnNlcmlhbCkKPiAgCj4gICNlbHNlCj4gIAo+IC1zdGF0aWMgaW50 IGNwMjEwNV9zaGFyZWRfZ3Bpb19pbml0KHN0cnVjdCB1c2Jfc2VyaWFsICpzZXJpYWwpCj4gK3N0 YXRpYyBpbnQgY3AyMTB4X2dwaW9faW5pdChzdHJ1Y3QgdXNiX3NlcmlhbCAqc2VyaWFsKQo+ICB7 Cj4gIAlyZXR1cm4gMDsKPiAgfQo+IEBAIC0xNTg4LDEzICsxNzg0LDcgQEAgc3RhdGljIGludCBj cDIxMHhfYXR0YWNoKHN0cnVjdCB1c2Jfc2VyaWFsICpzZXJpYWwpCj4gIAo+ICAJY3AyMTB4X2lu aXRfbWF4X3NwZWVkKHNlcmlhbCk7Cj4gIAo+IC0JaWYgKHByaXYtPnBhcnRudW0gPT0gQ1AyMTBY X1BBUlROVU1fQ1AyMTA1KSB7Cj4gLQkJcmVzdWx0ID0gY3AyMTA1X3NoYXJlZF9ncGlvX2luaXQo c2VyaWFsKTsKPiAtCQlpZiAocmVzdWx0IDwgMCkgewo+IC0JCQlkZXZfZXJyKCZzZXJpYWwtPmlu dGVyZmFjZS0+ZGV2LAo+IC0JCQkJIkdQSU8gaW5pdGlhbGlzYXRpb24gZmFpbGVkLCBjb250aW51 aW5nIHdpdGhvdXQgR1BJTyBzdXBwb3J0XG4iKTsKPiAtCQl9Cj4gLQl9Cj4gKwljcDIxMHhfZ3Bp b19pbml0KHNlcmlhbCk7Cj4gIAo+ICAJcmV0dXJuIDA7Cj4gIH0KClNvLCBtb3N0bHkgbWlub3Ig dGhpbmdzIHRoYXQgSSd2ZSBub3cgZml4ZWQgdXAuCgpOaWNlIGFuZCBjbGVhbiBqb2Igb3ZlcmFs bC4KClBvc3QgYSBuZXcgY29tbWl0IG1lc3NhZ2UsIGFuZCB3ZSdsbCBnZXQgdGhpcyBpbmNsdWRl ZCBpbiA0LjE5LgoKVGhhbmtzLApKb2hhbgotLS0KVG8gdW5zdWJzY3JpYmUgZnJvbSB0aGlzIGxp c3Q6IHNlbmQgdGhlIGxpbmUgInVuc3Vic2NyaWJlIGxpbnV4LXVzYiIgaW4KdGhlIGJvZHkgb2Yg YSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcKTW9yZSBtYWpvcmRvbW8gaW5m byBhdCAgaHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW5mby5odG1sCg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.4 required=3.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,SPF_PASS,T_DKIM_INVALID,URIBL_BLOCKED,USER_AGENT_MUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 73045ECDFB8 for ; Fri, 20 Jul 2018 10:45:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CEEEB20661 for ; Fri, 20 Jul 2018 10:45:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RVTRWxcU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CEEEB20661 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728700AbeGTLck (ORCPT ); Fri, 20 Jul 2018 07:32:40 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:41500 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728335AbeGTLcj (ORCPT ); Fri, 20 Jul 2018 07:32:39 -0400 Received: by mail-lf1-f66.google.com with SMTP id v22-v6so1481365lfe.8; Fri, 20 Jul 2018 03:44:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=U+Apa7wET5EWT8KQIL90gFcvmhItnMKavJu3l3sEzt0=; b=RVTRWxcU62By9Tgx2NuPOilaPf18Mv55e/5TphQG7Suf8Cs62KR2sM/3x4yaOHd7cP WPfNOWROSfF2ibVbDU8aY+EsWVVGuorQNG3c1Hunkv3Rfnug/GtL3i9lLm4HI2x9j0Ai IfIGwuHEz+u5iropDy5cSGbz21Rx2HftygAt1Ji6OuclKal6ACVI8+KPTEqksdyMDGoJ ArBtSDfqkBH+7zt6fK8xITNaM/jVaVxmU7ms6MhjqNncA/BcIPmzq93TPwZT1L7rnzcO U0EPbcOsoPt1Ezxvjdp5HB5GnXpxifvsNH8RmjMq1pS5++SoUQuJEV0ks+F8LG8vAe6d s0CQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition:in-reply-to:user-agent; bh=U+Apa7wET5EWT8KQIL90gFcvmhItnMKavJu3l3sEzt0=; b=o09wNEjhVmrDS1BKAZGAlqGzXkq6JJ4doMUMNK33hLe6+znnASQGTCzheOF1wK3pdE ehuW8+jYS7wlMreNGU2w0pb5omlkegMRCN0ozI43L0EkXAfFld0O0lB2A28elAw/3XML GohbQ6AD50fHrSDp5jbSg1LnSMiM1O5a0UBM4lcIwW4wZGPmmKIgX5+VBRimxo5F5GHp Oj2P7KrFW4iE4XmVpdiVFGjhzkLeomNyKm8XUdGVfyAiFt0DIO1DWhbY/InHzHXgKRxu wAYxLNuSB1ZJlNs2IdGQ/gnHdNv4at1K9t9zTpOygbF8uw0gMFxo9xCb2S4qkwcXthDJ 159w== X-Gm-Message-State: AOUpUlEASodFgoNA0j/fvKtTYuoQ9BleqxbgWLdkAa8cus+iHf++blcq dYBpJxdTMGi2yUgunCsa0FE= X-Google-Smtp-Source: AAOMgpdLxPtgu80fj9gvi7N29SPlr4VnSTpeZOhCSKnY2H/+MmB8LEw4vK91o9iOe1ANVVNdS/LCPg== X-Received: by 2002:a19:a705:: with SMTP id q5-v6mr1154208lfe.148.1532083497917; Fri, 20 Jul 2018 03:44:57 -0700 (PDT) Received: from xi.terra (c-8bb2e655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.178.139]) by smtp.gmail.com with ESMTPSA id q4-v6sm300101ljh.36.2018.07.20.03.44.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Jul 2018 03:44:56 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1fgStu-0005Ln-TO; Fri, 20 Jul 2018 12:44:42 +0200 Date: Fri, 20 Jul 2018 12:44:42 +0200 From: Johan Hovold To: Karoly Pados Cc: Johan Hovold , Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2] USB: serial: cp210x: Implement GPIO support for CP2102N Message-ID: <20180720104442.GC19245@localhost> References: <20180718212004.11852-1-pados@pados.hu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180718212004.11852-1-pados@pados.hu> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Jul 18, 2018 at 11:20:04PM +0200, Karoly Pados wrote: > This is v2 of the patch and addresses all feedback previously > received from the maintainer. New input/output support stayed > as discussed on the e-mail lists separately. CP2105 is also > using the new code structure, but due to missing way to get > default pin states after reset from the device, support > for this device is basically still output-only as before, at > least in name. But CP2105 and CP2102N paths are unified. This reads like a patch changelog rather than a commit message. Please try to rephrase this so that it's self-contained and not relying on having read the mail thread for v1. In the future you should include a changelog from what changed from one revision to another below the cut-off line (---) instead. > This patch is based on the latest patch series by Johan just > submitted today. Should also go below the cut-off line. > Signed-off-by: Karoly Pados Oh, and you should have included Martyn who contributed to the discussion about how to handle input mode on CC. > --- > drivers/usb/serial/cp210x.c | 274 ++++++++++++++++++++++++++++++------ > 1 file changed, 232 insertions(+), 42 deletions(-) > > diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c > index 4a118eb13590..81f9d3e183c6 100644 > --- a/drivers/usb/serial/cp210x.c > +++ b/drivers/usb/serial/cp210x.c > @@ -224,9 +224,19 @@ MODULE_DEVICE_TABLE(usb, id_table); > struct cp210x_serial_private { > #ifdef CONFIG_GPIOLIB > struct gpio_chip gc; > - u8 config; > - u8 gpio_mode; > bool gpio_registered; > + > + /* > + * The following three fields are for devices that > + * emulate input/output pins using open-drain/pushpull > + * drive modes. > + */ > + /* One bit for each GPIO, 1 if pin is pushpull */ > + u8 gpio_pushpull; > + /* One bit for each GPIO, 1 if pin is not in GPIO mode */ > + u8 gpio_altfunc; > + /* One bit for each GPIO, 1 if pin direction is input */ > + u8 gpio_input; Your code is clean, but you're relying a bit too much on comments in my opinion. The code should be self-explanatory and not rely on in-function comments, unless you want to highlight something particularly important or clever. I've dropped some examples of this in my reworked version of the patch. > #endif > u8 partnum; > speed_t max_speed; > @@ -343,6 +353,7 @@ static struct usb_serial_driver * const serial_drivers[] = { > #define CONTROL_WRITE_RTS 0x0200 > > /* CP210X_VENDOR_SPECIFIC values */ > +#define CP210X_READ_2NCONFIG 0x000E > #define CP210X_READ_LATCH 0x00C2 > #define CP210X_GET_PARTNUM 0x370B > #define CP210X_GET_PORTCONFIG 0x370C > @@ -452,6 +463,12 @@ struct cp210x_config { > #define CP2105_GPIO1_RXLED_MODE BIT(1) > #define CP2105_GPIO1_RS485_MODE BIT(2) > > +/* CP2102N configuration array indices */ > +#define CP210X_2NCONFIG_CONFIG_VERSION_IDX 2 > +#define CP210X_2NCONFIG_GPIO_MODE_IDX 581 > +#define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587 > +#define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600 > + > /* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */ > struct cp210x_gpio_write { > u8 mask; > @@ -1308,21 +1325,29 @@ static void cp210x_break_ctl(struct tty_struct *tty, int break_state) > } > > #ifdef CONFIG_GPIOLIB > + > +/* > + * Helper to determine if a specific serial device belongs to the cp2102n > + * family of devices. > + */ > +static bool cp210x_is_cp2102n(struct usb_serial *serial) > +{ > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + > + return (priv->partnum == CP210X_PARTNUM_CP2102N_QFN28) || > + (priv->partnum == CP210X_PARTNUM_CP2102N_QFN24) || > + (priv->partnum == CP210X_PARTNUM_CP2102N_QFN20); > +} I also did away with this one (again). The cp2102n way of dealing with gpios appear to be the standard way; while cp2105 and cp2108 are the odd birds. > + > static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset) > { > struct usb_serial *serial = gpiochip_get_data(gc); > struct cp210x_serial_private *priv = usb_get_serial_data(serial); > > - switch (offset) { > - case 0: > - if (priv->config & CP2105_GPIO0_TXLED_MODE) > - return -ENODEV; > - break; > - case 1: > - if (priv->config & (CP2105_GPIO1_RXLED_MODE | > - CP2105_GPIO1_RS485_MODE)) > - return -ENODEV; > - break; > + if (priv->gpio_altfunc & BIT(offset)) { > + dev_warn(&serial->interface->dev, > + "Cannot control GPIO with active alternate function.\n"); I dropped the warning, you're already returning an errno as before. > + return -ENODEV; > } > > return 0; > @@ -1331,10 +1356,15 @@ static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset) > static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) > { > struct usb_serial *serial = gpiochip_get_data(gc); > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + u8 req_type = REQTYPE_DEVICE_TO_HOST; > int result; > u8 buf; > > - result = cp210x_read_vendor_block(serial, REQTYPE_INTERFACE_TO_HOST, > + if (priv->partnum == CP210X_PARTNUM_CP2105) > + req_type = REQTYPE_INTERFACE_TO_HOST; > + > + result = cp210x_read_vendor_block(serial, req_type, > CP210X_READ_LATCH, &buf, sizeof(buf)); > if (result < 0) > return result; > @@ -1345,34 +1375,82 @@ static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio) > static void cp210x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) > { > struct usb_serial *serial = gpiochip_get_data(gc); > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > struct cp210x_gpio_write buf; > + int result = 0; > > - if (value == 1) > - buf.state = BIT(gpio); > - else > - buf.state = 0; > - > + buf.state = (value == 1) ? BIT(gpio) : 0; No need to change this, and generally try to avoid the ternary operator which often just makes code harder to read. > buf.mask = BIT(gpio); > > - cp210x_write_vendor_block(serial, REQTYPE_HOST_TO_INTERFACE, > - CP210X_WRITE_LATCH, &buf, sizeof(buf)); > + if (priv->partnum == CP210X_PARTNUM_CP2105) { > + result = cp210x_write_vendor_block(serial, > + REQTYPE_HOST_TO_INTERFACE, > + CP210X_WRITE_LATCH, &buf, > + sizeof(buf)); > + } else if (cp210x_is_cp2102n(serial)) { So I just made this the default implementation by dropping the conditional. > + u16 wIndex = buf.state << 8 | buf.mask; > + > + result = usb_control_msg(serial->dev, > + usb_sndctrlpipe(serial->dev, 0), > + CP210X_VENDOR_SPECIFIC, > + REQTYPE_HOST_TO_DEVICE, > + CP210X_WRITE_LATCH, > + wIndex, > + NULL, 0, USB_CTRL_SET_TIMEOUT); > + } > + > + if (result < 0) > + dev_err(&serial->interface->dev, "Failed to set GPIO value.\n"); This could include the errno. > } > > static int cp210x_gpio_direction_get(struct gpio_chip *gc, unsigned int gpio) > { > - /* Hardware does not support an input mode */ > - return 0; > + struct usb_serial *serial = gpiochip_get_data(gc); > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + > + return priv->gpio_input & BIT(gpio); > } > > static int cp210x_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) > { > - /* Hardware does not support an input mode */ > - return -ENOTSUPP; > + struct usb_serial *serial = gpiochip_get_data(gc); > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + > + if (priv->partnum == CP210X_PARTNUM_CP2105) { > + /* Hardware does not support an input mode */ > + return -ENOTSUPP; > + } else if (cp210x_is_cp2102n(serial)) { This should be the default implementation. > + /* Push-pull pins cannot be changed to be inputs */ > + if (priv->gpio_pushpull & BIT(gpio)) { > + dev_warn(&serial->interface->dev, > + "Cannot change direction of a push-pull GPIO to input.\n"); No need to warn, as you're returning an error. > + return -EPERM; And this isn't really a permission issue; -EINVAL is more appropriate. > + } > + > + /* Make sure to release pin if it is being driven low */ > + cp210x_gpio_set(gc, gpio, 1); > + > + /* Note pin direction to ourselves */ > + priv->gpio_input |= BIT(gpio); > + > + return 0; > + } > + > + return -EPERM; > } > > static int cp210x_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, > int value) > { > + struct usb_serial *serial = gpiochip_get_data(gc); > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + > + /* Note pin direction to ourselves */ > + priv->gpio_input &= ~BIT(gpio); > + > + /* Set requested initial output value */ I'd drop these comments for example. > + cp210x_gpio_set(gc, gpio, value); > + > return 0; > } > > @@ -1385,11 +1463,11 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio, > > /* Succeed only if in correct mode (this can't be set at runtime) */ > if ((param == PIN_CONFIG_DRIVE_PUSH_PULL) && > - (priv->gpio_mode & BIT(gpio))) > + (priv->gpio_pushpull & BIT(gpio))) > return 0; > > if ((param == PIN_CONFIG_DRIVE_OPEN_DRAIN) && > - !(priv->gpio_mode & BIT(gpio))) > + !(priv->gpio_pushpull & BIT(gpio))) > return 0; > > return -ENOTSUPP; > @@ -1402,13 +1480,14 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio, > * this driver that provide GPIO do so in a way that does not impact other > * signals and are thus expected to have very different initialisation. > */ > -static int cp2105_shared_gpio_init(struct usb_serial *serial) > +static int cp2105_gpioconf_init(struct usb_serial *serial) > { > struct cp210x_serial_private *priv = usb_get_serial_data(serial); > struct cp210x_pin_mode mode; > struct cp210x_config config; > u8 intf_num = cp210x_interface_num(serial); > int result; > + u8 iface_config; > > result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, > CP210X_GET_DEVICEMODE, &mode, > @@ -1424,20 +1503,25 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial) > > /* 2 banks of GPIO - One for the pins taken from each serial port */ > if (intf_num == 0) { > - if (mode.eci == CP210X_PIN_MODE_MODEM) > + if (mode.eci == CP210X_PIN_MODE_MODEM) { > + /* Mark all GPIOs of this interface as reserved */ > + priv->gpio_altfunc = 0xFF; > return 0; > + } > > - priv->config = config.eci_cfg; > - priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & > + iface_config = config.eci_cfg; > + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & > CP210X_ECI_GPIO_MODE_MASK) >> > CP210X_ECI_GPIO_MODE_OFFSET); > priv->gc.ngpio = 2; > } else if (intf_num == 1) { > - if (mode.sci == CP210X_PIN_MODE_MODEM) > - return 0; > + if (mode.sci == CP210X_PIN_MODE_MODEM) { > + /* Mark all GPIOs of this interface as reserved */ > + priv->gpio_altfunc = 0xFF; Here the return 0 fell out, which could lead to the pins being considered available. > + } > > - priv->config = config.sci_cfg; > - priv->gpio_mode = (u8)((le16_to_cpu(config.gpio_mode) & > + iface_config = config.sci_cfg; > + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & > CP210X_SCI_GPIO_MODE_MASK) >> > CP210X_SCI_GPIO_MODE_OFFSET); > priv->gc.ngpio = 3; > @@ -1445,6 +1529,118 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial) > return -ENODEV; > } > > + /* Mark all pins which are not in GPIO mode */ > + priv->gpio_altfunc = 0; > + if (iface_config & CP2105_GPIO0_TXLED_MODE) /* GPIO 0 */ > + priv->gpio_altfunc |= BIT(0); > + if (iface_config & (CP2105_GPIO1_RXLED_MODE | /* GPIO 1 */ > + CP2105_GPIO1_RS485_MODE)) > + priv->gpio_altfunc |= BIT(1); > + > + /* Driver implementation for CP2105 only supports outputs */ > + priv->gpio_input = 0; > + > + return 0; > +} > + > +static int cp2102n_gpioconf_init(struct usb_serial *serial) > +{ > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + const u16 CONFIG_SIZE = 0x02A6; Lower case variable names, and I'd use lower-case for hex constants as well. > + u8 gpio_rst_latch; > + u8 config_version; > + u8 gpio_pushpull; > + u8 *config_buf; > + u8 gpio_latch; > + u8 gpio_ctrl; > + int result; > + u8 i; > + > + /* Retrieve device configuration from the device. > + * The array received contains all customization settings > + * done at the factory/manufacturer. > + * Format of the array is documented at the time of writing at > + * https://www.silabs.com/community/interface/knowledge-base.entry.html/2017/03/31/cp2102n_setconfig-xsfa > + */ Multi-line comment style is /* * blah... */ as I already mentioned in comments to v1. > + config_buf = kmalloc(CONFIG_SIZE, GFP_KERNEL); > + if (!config_buf) > + return -ENOMEM; > + > + result = cp210x_read_vendor_block(serial, > + REQTYPE_DEVICE_TO_HOST, > + CP210X_READ_2NCONFIG, > + config_buf, > + CONFIG_SIZE); > + if (result < 0) { > + kfree(config_buf); > + return -EIO; Return result. > + } > + > + config_version = config_buf[CP210X_2NCONFIG_CONFIG_VERSION_IDX]; > + gpio_pushpull = config_buf[CP210X_2NCONFIG_GPIO_MODE_IDX]; > + gpio_ctrl = config_buf[CP210X_2NCONFIG_GPIO_CONTROL_IDX]; > + gpio_rst_latch = config_buf[CP210X_2NCONFIG_GPIO_RSTLATCH_IDX]; > + > + kfree(config_buf); > + > + /* Make sure this is a config format we understand */ > + if (config_version != 0x01) > + return -ENOTSUPP; > + > + /* We only support 4 GPIOs even on the QFN28 package, because > + * config locations of GPIOs 4-6 determined using reverse > + * engineering revealed conflicting offsets with other > + * documented functions. So we'll just play it safe for now. > + */ > + priv->gc.ngpio = 4; > + > + /* Get default pin states after reset. Needed so we can determine > + * the direction of an open-drain pin. > + */ > + gpio_latch = (gpio_rst_latch >> 3) & 0x0F; > + > + /* 0 indicates open-drain mode, 1 is push-pull */ > + priv->gpio_pushpull = (gpio_pushpull >> 3) & 0x0F; > + > + /* 0 indicates GPIO mode, 1 is alternate function */ > + priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0F; > + > + /* The CP2102N does not strictly has input and output pin modes, > + * it only knows open-drain and push-pull modes which is set at > + * factory. An open-drain pin can function both as an > + * input or an output. We emulate input mode for open-drain pins > + * by making sure they are not driven low, and we do not allow > + * push-pull pins to be set as an input. > + */ > + for (i = 0; i < priv->gc.ngpio; ++i) { > + /* Set direction to "input" iff > + * pin is open-drain and reset value is 1 > + */ > + if (!(priv->gpio_pushpull & BIT(i)) && (gpio_latch & BIT(i))) > + priv->gpio_input |= BIT(i); > + } > + > + return 0; > +} > + > +static int cp210x_gpio_init(struct usb_serial *serial) > +{ > + struct cp210x_serial_private *priv = usb_get_serial_data(serial); > + int result = 0; > + > + if (cp210x_is_cp2102n(serial)) > + result = cp2102n_gpioconf_init(serial); > + else if (priv->partnum == CP210X_PARTNUM_CP2105) > + result = cp2105_gpioconf_init(serial); > + else > + return 0; This could be a switch-statement. > + > + if (result < 0) { > + dev_err(&serial->interface->dev, > + "GPIO initialisation failed, continuing without GPIO support\n"); > + return result; > + } By moving the error message into cp210x_gpio_init, we'd no longer log any registration errors below. > + > priv->gc.label = "cp210x"; > priv->gc.request = cp210x_gpio_request; > priv->gc.get_direction = cp210x_gpio_direction_get; > @@ -1477,7 +1673,7 @@ static void cp210x_gpio_remove(struct usb_serial *serial) > > #else > > -static int cp2105_shared_gpio_init(struct usb_serial *serial) > +static int cp210x_gpio_init(struct usb_serial *serial) > { > return 0; > } > @@ -1588,13 +1784,7 @@ static int cp210x_attach(struct usb_serial *serial) > > cp210x_init_max_speed(serial); > > - if (priv->partnum == CP210X_PARTNUM_CP2105) { > - result = cp2105_shared_gpio_init(serial); > - if (result < 0) { > - dev_err(&serial->interface->dev, > - "GPIO initialisation failed, continuing without GPIO support\n"); > - } > - } > + cp210x_gpio_init(serial); > > return 0; > } So, mostly minor things that I've now fixed up. Nice and clean job overall. Post a new commit message, and we'll get this included in 4.19. Thanks, Johan