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: [RFC,v2,12/15] usb:cdns3: Adds enumeration related function. From: Roger Quadros Message-Id: <5BFEB92C.9060903@ti.com> Date: Wed, 28 Nov 2018 17:50:04 +0200 To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, adouglas@cadence.com, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, pjez@cadence.com, kurahul@cadence.com List-ID: T24gMTgvMTEvMTggMTI6MDksIFBhd2VsIExhc3pjemFrIHdyb3RlOgo+IFBhdGNoIGltcGxlbWVu dHMgYSBzZXQgb2YgZnVuY3Rpb24gcmVsYXRlZCB0byBlbnVtZXJhdGlvbiBwcm9jZXNzLgo+IFNv bWUgc3RhbmRhcmQgcmVxdWVzdHMgYXJlIGhhbmRsZWQgb24gY29udHJvbGxlciBkcml2ZXIgbGV2 ZWwgYW5kCj4gb3RoZXIgYXJlIGRlbGVnYXRlZCB0byBnYWRnZXQgY29yZSBkcml2ZXIuCj4gQWxs IGNsYXNzIHJlcXVlc3RzIGFyZSBkZWxlZ2F0ZWQgdG8gZ2FkZ2V0IGNvcmUgZHJpdmVyLgo+IAo+ IFNpZ25lZC1vZmYtYnk6IFBhd2VsIExhc3pjemFrIDxwYXdlbGxAY2FkZW5jZS5jb20+Cj4gLS0t Cj4gIGRyaXZlcnMvdXNiL2NkbnMzL2VwMC5jICAgIHwgNDkxICsrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKy0KPiAgZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMgfCAxMTkgKysr KysrKysrCj4gIGRyaXZlcnMvdXNiL2NkbnMzL2dhZGdldC5oIHwgICA0ICsKPiAgMyBmaWxlcyBj aGFuZ2VkLCA2MTAgaW5zZXJ0aW9ucygrKSwgNCBkZWxldGlvbnMoLSkKPiAKPiBkaWZmIC0tZ2l0 IGEvZHJpdmVycy91c2IvY2RuczMvZXAwLmMgYi9kcml2ZXJzL3VzYi9jZG5zMy9lcDAuYwo+IGlu ZGV4IGViOTJmZDIzNGJkNy4uNmYzM2Q5OGY3Njg0IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvdXNi L2NkbnMzL2VwMC5jCj4gKysrIGIvZHJpdmVycy91c2IvY2RuczMvZXAwLmMKPiBAQCAtMTAsNiAr MTAsNyBAQAo+ICAgKgkgICAgUGV0ZXIgQ2hlbiA8cGV0ZXIuY2hlbkBueHAuY29tPgo+ICAgKi8K PiAgCj4gKyNpbmNsdWRlIDxsaW51eC91c2IvY29tcG9zaXRlLmg+Cj4gICNpbmNsdWRlICJnYWRn ZXQuaCIKPiAgCj4gIHN0YXRpYyBzdHJ1Y3QgdXNiX2VuZHBvaW50X2Rlc2NyaXB0b3IgY2RuczNf Z2FkZ2V0X2VwMF9kZXNjID0gewo+IEBAIC01Miw5ICs1MywzMSBAQCBzdGF0aWMgdm9pZCBjZG5z M19lcDBfcnVuX3RyYW5zZmVyKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICAJCXdy aXRlbChFUF9DTURfRVJEWSwgJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQpOwo+ICB9Cj4gIAo+ICsv KioKPiArICogY2RuczNfZXAwX2RlbGVnYXRlX3JlcSAtIFJldHVybnMgc3RhdHVzIG9mIGhhbmRs aW5nIHNldHVwIHBhY2tldAo+ICsgKiBTZXR1cCBpcyBoYW5kbGVkIGJ5IGdhZGdldCBkcml2ZXIK PiArICogQHByaXZfZGV2OiBleHRlbmRlZCBnYWRnZXQgb2JqZWN0Cj4gKyAqIEBjdHJsX3JlcTog cG9pbnRlciB0byByZWNlaXZlZCBzZXR1cCBwYWNrZXQKPiArICoKPiArICogUmV0dXJucyB6ZXJv IG9uIHN1Y2Nlc3Mgb3IgbmVnYXRpdmUgdmFsdWUgb24gZmFpbHVyZQo+ICsgKi8KPiArc3RhdGlj IGludCBjZG5zM19lcDBfZGVsZWdhdGVfcmVxKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2 LAo+ICsJCQkJICBzdHJ1Y3QgdXNiX2N0cmxyZXF1ZXN0ICpjdHJsX3JlcSkKPiArewo+ICsJaW50 IHJldDsKPiArCj4gKwlzcGluX3VubG9jaygmcHJpdl9kZXYtPmxvY2spOwo+ICsJcHJpdl9kZXYt PnNldHVwX3BlbmRpbmcgPSAxOwo+ICsJcmV0ID0gcHJpdl9kZXYtPmdhZGdldF9kcml2ZXItPnNl dHVwKCZwcml2X2Rldi0+Z2FkZ2V0LCBjdHJsX3JlcSk7Cj4gKwlwcml2X2Rldi0+c2V0dXBfcGVu ZGluZyA9IDA7CgpXaHkgaXMgc2V0dXBfcGVuZGluZyBmbGFnIGJlaW5nIHNldCBhbmQgY2xlYXJl ZD8KCj4gKwlzcGluX2xvY2soJnByaXZfZGV2LT5sb2NrKTsKPiArCXJldHVybiByZXQ7Cj4gK30K PiArCj4gIHN0YXRpYyB2b2lkIGNkbnMzX3ByZXBhcmVfc2V0dXBfcGFja2V0KHN0cnVjdCBjZG5z M19kZXZpY2UgKnByaXZfZGV2KQo+ICB7Cj4gLQkvL1RPRE86IEltcGxlbWVudHMgdGhpcyBmdW5j dGlvbgo+ICsJcHJpdl9kZXYtPmVwMF9kYXRhX2RpciA9IDA7Cj4gKwljZG5zM19lcDBfcnVuX3Ry YW5zZmVyKHByaXZfZGV2LCBwcml2X2Rldi0+c2V0dXBfZG1hLCA4LCAwKTsKCndoeSBoYXJkY29k ZSB0byA4PwpEb24ndCB2ZW5kb3Igc3BlY2lmaWMgcmVxdWVzdHMgaGF2ZSBkaWZmZXJlbnQgbGVu Z3Rocz8KCj4gIH0KPiAgCj4gIHN0YXRpYyB2b2lkIGNkbnMzX3NldF9od19jb25maWd1cmF0aW9u KHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2KQo+IEBAIC05MCw5ICsxMTMsNDMxIEBAIHN0 YXRpYyB2b2lkIGNkbnMzX3NldF9od19jb25maWd1cmF0aW9uKHN0cnVjdCBjZG5zM19kZXZpY2Ug KnByaXZfZGV2KQo+ICAJfQo+ICB9Cj4gIAo+ICsvKioKPiArICogY2RuczNfcmVxX2VwMF9zZXRf Y29uZmlndXJhdGlvbiAtIEhhbmRsaW5nIG9mIFNFVF9DT05GSUcgc3RhbmRhcmQgVVNCIHJlcXVl c3QKPiArICogQHByaXZfZGV2OiBleHRlbmRlZCBnYWRnZXQgb2JqZWN0Cj4gKyAqIEBjdHJsX3Jl cTogcG9pbnRlciB0byByZWNlaXZlZCBzZXR1cCBwYWNrZXQKPiArICoKPiArICogUmV0dXJucyAw IGlmIHN1Y2Nlc3MsIDB4N0ZGRiBvbiBkZWZlcnJlZCBzdGF0dXMgc3RhZ2UsIGVycm9yIGNvZGUg b24gZXJyb3IKCndoYXQgaXMgdGhpcyBtYWdpYyBudW1iZXIgMHg3ZmZmPwoKPiArICovCj4gK3N0 YXRpYyBpbnQgY2RuczNfcmVxX2VwMF9zZXRfY29uZmlndXJhdGlvbihzdHJ1Y3QgY2RuczNfZGV2 aWNlICpwcml2X2RldiwKPiArCQkJCQkgICBzdHJ1Y3QgdXNiX2N0cmxyZXF1ZXN0ICpjdHJsX3Jl cSkKPiArewo+ICsJZW51bSB1c2JfZGV2aWNlX3N0YXRlIGRldmljZV9zdGF0ZSA9IHByaXZfZGV2 LT5nYWRnZXQuc3RhdGU7Cj4gKwlzdHJ1Y3QgY2RuczNfZW5kcG9pbnQgKnByaXZfZXAsICp0ZW1w X2VwOwo+ICsJdTMyIGNvbmZpZyA9IGxlMTZfdG9fY3B1KGN0cmxfcmVxLT53VmFsdWUpOwo+ICsJ aW50IHJlc3VsdCA9IDA7Cj4gKwo+ICsJc3dpdGNoIChkZXZpY2Vfc3RhdGUpIHsKPiArCWNhc2Ug VVNCX1NUQVRFX0FERFJFU1M6Cj4gKwkJLyogQ29uZmlndXJlIG5vbi1jb250cm9sIEVQcyAqLwo+ ICsJCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShwcml2X2VwLCB0ZW1wX2VwLAo+ICsJCQkJCSAm cHJpdl9kZXYtPmVwX21hdGNoX2xpc3QsCj4gKwkJCQkJIGVwX21hdGNoX3BlbmRpbmdfbGlzdCkK PiArCQkJY2RuczNfZXBfY29uZmlnKHByaXZfZXApOwoKV2h5IGNvbmZpZ3VyZSBoZXJlPyBUaGV5 IHNob3VsZCBiZSBjb25maWd1cmVkIGF0IGVwX2VuYWJsZS4gbm8/CkFuZCB5b3UgZG9uJ3QgbmVl ZCB0byBtYWludGFpbiBhIGVwX21hdGNoL3BlbmRpbmdfbGlzdC4KCj4gKwo+ICsJCXJlc3VsdCA9 IGNkbnMzX2VwMF9kZWxlZ2F0ZV9yZXEocHJpdl9kZXYsIGN0cmxfcmVxKTsKPiArCj4gKwkJaWYg KHJlc3VsdCkKPiArCQkJcmV0dXJuIHJlc3VsdDsKPiArCj4gKwkJaWYgKGNvbmZpZykgewoKV2hh dCBpZiByZXN1bHQgaXMgVVNCX0dBREdFVF9ERUxBWUVEX1NUQVRVUz8KCj4gKwkJCWNkbnMzX3Nl dF9od19jb25maWd1cmF0aW9uKHByaXZfZGV2KTsKCnVzYl9nYWRnZXRfc2V0X3N0YXRlKFVTQl9T VEFURV9DT05GSUdVUkVEKSA/Cgo+ICsJCX0gZWxzZSB7Cj4gKwkJCWNkbnMzX2dhZGdldF91bmNv bmZpZyhwcml2X2Rldik7Cj4gKwkJCXVzYl9nYWRnZXRfc2V0X3N0YXRlKCZwcml2X2Rldi0+Z2Fk Z2V0LAo+ICsJCQkJCSAgICAgVVNCX1NUQVRFX0FERFJFU1MpOwo+ICsJCX0KPiArCQlicmVhazsK PiArCWNhc2UgVVNCX1NUQVRFX0NPTkZJR1VSRUQ6Cj4gKwkJcmVzdWx0ID0gY2RuczNfZXAwX2Rl bGVnYXRlX3JlcShwcml2X2RldiwgY3RybF9yZXEpOwo+ICsKPiArCQlpZiAoIWNvbmZpZyAmJiAh cmVzdWx0KSB7Cj4gKwkJCWNkbnMzX2dhZGdldF91bmNvbmZpZyhwcml2X2Rldik7Cj4gKwkJCXVz Yl9nYWRnZXRfc2V0X3N0YXRlKCZwcml2X2Rldi0+Z2FkZ2V0LAo+ICsJCQkJCSAgICAgVVNCX1NU QVRFX0FERFJFU1MpOwo+ICsJCX0KPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJcmVzdWx0 ID0gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gcmVzdWx0Owo+ICt9Cj4gKwo+ICsvKioK PiArICogY2RuczNfcmVxX2VwMF9zZXRfYWRkcmVzcyAtIEhhbmRsaW5nIG9mIFNFVF9BRERSRVNT IHN0YW5kYXJkIFVTQiByZXF1ZXN0Cj4gKyAqIEBwcml2X2RldjogZXh0ZW5kZWQgZ2FkZ2V0IG9i amVjdAo+ICsgKiBAY3RybF9yZXE6IHBvaW50ZXIgdG8gcmVjZWl2ZWQgc2V0dXAgcGFja2V0Cj4g KyAqCj4gKyAqIFJldHVybnMgMCBpZiBzdWNjZXNzLCBlcnJvciBjb2RlIG9uIGVycm9yCj4gKyAq Lwo+ICtzdGF0aWMgaW50IGNkbnMzX3JlcV9lcDBfc2V0X2FkZHJlc3Moc3RydWN0IGNkbnMzX2Rl dmljZSAqcHJpdl9kZXYsCj4gKwkJCQkgICAgIHN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmxf cmVxKQo+ICt7Cj4gKwllbnVtIHVzYl9kZXZpY2Vfc3RhdGUgZGV2aWNlX3N0YXRlID0gcHJpdl9k ZXYtPmdhZGdldC5zdGF0ZTsKPiArCXUzMiByZWc7Cj4gKwl1MzIgYWRkcjsKPiArCj4gKwlhZGRy ID0gbGUxNl90b19jcHUoY3RybF9yZXEtPndWYWx1ZSk7Cj4gKwo+ICsJaWYgKGFkZHIgPiBERVZJ Q0VfQUREUkVTU19NQVgpIHsKCklmIERFVklDRV9BRERSRVNTX01BWCBjb21lcyBmcm9tIFVTQiBz cGVjIGl0IG11c3QgYmUgaW4gY2g5LmguCk1heWJlIGFkZCBzb21ldGhpbmcgbGlrZQoKI2RlZmlu ZQlVU0JfREVWSUNFX01BWF9BRERSRVNTCTEyNwoKPiArCQlkZXZfZXJyKCZwcml2X2Rldi0+ZGV2 LAo+ICsJCQkiRGV2aWNlIGFkZHJlc3MgKCVkKSBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuICVkXG4i LAo+ICsJCQlhZGRyLCBERVZJQ0VfQUREUkVTU19NQVgpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsJfQo+ICsKPiArCWlmIChkZXZpY2Vfc3RhdGUgPT0gVVNCX1NUQVRFX0NPTkZJR1VSRUQpIHsK PiArCQlkZXZfZXJyKCZwcml2X2Rldi0+ZGV2LCAiVVNCIGRldmljZSBhbHJlYWR5IGNvbmZpZ3Vy ZWRcbiIpOwoKTWVzc2FnZSBpcyBtaXNsZWFkaW5nLiBIb3cgYWJvdXQgImNhbid0IHNldF9hZGRy ZXNzIGZyb20gY29uZmlndXJlZCBzdGF0ZSIKCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4g Kwo+ICsJcmVnID0gcmVhZGwoJnByaXZfZGV2LT5yZWdzLT51c2JfY21kKTsKPiArCj4gKwl3cml0 ZWwocmVnIHwgVVNCX0NNRF9GQUREUihhZGRyKSB8IFVTQl9DTURfU0VUX0FERFIsCj4gKwkgICAg ICAgJnByaXZfZGV2LT5yZWdzLT51c2JfY21kKTsKPiArCj4gKwl1c2JfZ2FkZ2V0X3NldF9zdGF0 ZSgmcHJpdl9kZXYtPmdhZGdldCwKPiArCQkJICAgICAoYWRkciA/IFVTQl9TVEFURV9BRERSRVNT IDogVVNCX1NUQVRFX0RFRkFVTFQpKTsKPiArCj4gKwljZG5zM19wcmVwYXJlX3NldHVwX3BhY2tl dChwcml2X2Rldik7Cgp3aHkgY2FsbCB0aGlzIGhlcmU/IFRoaXMgc2hvdWxkIGJlIGRvbmUgYWZ0 ZXIgdGhlIGN1cnJlbnQgZXAwIHJlcXVlc3QgaXMgY29tcGxldGUuCgo+ICsKPiArCXdyaXRlbChF UF9DTURfRVJEWSB8IEVQX0NNRF9SRVFfQ01QTCwgJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQpOwo+ ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKioKPiArICogY2RuczNfcmVxX2VwMF9nZXRf c3RhdHVzIC0gSGFuZGxpbmcgb2YgR0VUX1NUQVRVUyBzdGFuZGFyZCBVU0IgcmVxdWVzdAo+ICsg KiBAcHJpdl9kZXY6IGV4dGVuZGVkIGdhZGdldCBvYmplY3QKPiArICogQGN0cmxfcmVxOiBwb2lu dGVyIHRvIHJlY2VpdmVkIHNldHVwIHBhY2tldAo+ICsgKgo+ICsgKiBSZXR1cm5zIDAgaWYgc3Vj Y2VzcywgZXJyb3IgY29kZSBvbiBlcnJvcgo+ICsgKi8KPiArc3RhdGljIGludCBjZG5zM19yZXFf ZXAwX2dldF9zdGF0dXMoc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYsCj4gKwkJCQkgICAg c3RydWN0IHVzYl9jdHJscmVxdWVzdCAqY3RybCkKPiArewo+ICsJX19sZTE2ICpyZXNwb25zZV9w a3Q7Cj4gKwl1MTYgdXNiX3N0YXR1cyA9IDA7Cj4gKwl1MzIgcmVjaXA7Cj4gKwl1MzIgcmVnOwo+ ICsKPiArCXJlY2lwID0gY3RybC0+YlJlcXVlc3RUeXBlICYgVVNCX1JFQ0lQX01BU0s7Cj4gKwo+ ICsJc3dpdGNoIChyZWNpcCkgewo+ICsJY2FzZSBVU0JfUkVDSVBfREVWSUNFOgo+ICsJCS8qIHNl bGYgcG93ZXJlZCAqLwo+ICsJCXVzYl9zdGF0dXMgfD0gcHJpdl9kZXYtPmdhZGdldC5pc19zZWxm cG93ZXJlZDsKCmlmIChwcnZfZGV2Z2FkZ2V0LmlzX3NlbGZwb3dlcmVkKQoJdXNiX3N0YXRzIHw9 IEJJVChVU0JfREVWSUNFX1NFTEZfUE9XRVJFRCk7Cgo+ICsKPiArCQlpZiAocHJpdl9kZXYtPmdh ZGdldC5zcGVlZCAhPSBVU0JfU1BFRURfU1VQRVIpCgpZb3Ugc2hvdWxkIGNoZWNrIGNvbnRyb2xs ZXIgc3BlZWQgZGlyZWN0bHkgaW5zdGVhZC4KCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlyZWcgPSBy ZWFkbCgmcHJpdl9kZXYtPnJlZ3MtPnVzYl9zdHMpOwo+ICsKPiArCQlpZiAocHJpdl9kZXYtPnUx X2FsbG93ZWQpCj4gKwkJCXVzYl9zdGF0dXMgfD0gQklUKFVTQl9ERVZfU1RBVF9VMV9FTkFCTEVE KTsKPiArCj4gKwkJaWYgKHByaXZfZGV2LT51Ml9hbGxvd2VkKQo+ICsJCQl1c2Jfc3RhdHVzIHw9 IEJJVChVU0JfREVWX1NUQVRfVTJfRU5BQkxFRCk7Cj4gKwo+ICsJCWlmIChwcml2X2Rldi0+d2Fr ZV91cF9mbGFnKQo+ICsJCQl1c2Jfc3RhdHVzIHw9IEJJVChVU0JfREVWSUNFX1JFTU9URV9XQUtF VVApOwoKUmVtb3RlIHdha2V1cCBpcyBub3QgU1Mgc3BlY2lmaWMuIFNvIG5lZWRzIHRvIGdvIGJl Zm9yZSB0aGUgU1MgY2hlY2suCgo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfUkVDSVBfSU5URVJG QUNFOgo+ICsJCXJldHVybiBjZG5zM19lcDBfZGVsZWdhdGVfcmVxKHByaXZfZGV2LCBjdHJsKTsK PiArCWNhc2UgVVNCX1JFQ0lQX0VORFBPSU5UOgo+ICsJCS8qIGNoZWNrIGlmIGVuZHBvaW50IGlz IHN0YWxsZWQgKi8KPiArCQljZG5zM19zZWxlY3RfZXAocHJpdl9kZXYsIGN0cmwtPndJbmRleCk7 Cj4gKwkJaWYgKEVQX1NUU19TVEFMTChyZWFkbCgmcHJpdl9kZXYtPnJlZ3MtPmVwX3N0cykpKQo+ ICsJCQl1c2Jfc3RhdHVzID0gIEJJVChVU0JfRU5EUE9JTlRfSEFMVCk7Cj4gKwkJYnJlYWs7Cj4g KwlkZWZhdWx0Ogo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJlc3BvbnNlX3Br dCA9IChfX2xlMTYgKilwcml2X2Rldi0+c2V0dXA7Cj4gKwkqcmVzcG9uc2VfcGt0ID0gY3B1X3Rv X2xlMTYodXNiX3N0YXR1cyk7Cj4gKwo+ICsJY2RuczNfZXAwX3J1bl90cmFuc2Zlcihwcml2X2Rl diwgcHJpdl9kZXYtPnNldHVwX2RtYSwKPiArCQkJICAgICAgIHNpemVvZigqcmVzcG9uc2VfcGt0 KSwgMSk7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBjZG5zM19lcDBfZmVh dHVyZV9oYW5kbGVfZGV2aWNlKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICsJCQkJ CSAgIHN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmwsCj4gKwkJCQkJICAgaW50IHNldCkKPiAr ewo+ICsJZW51bSB1c2JfZGV2aWNlX3N0YXRlIHN0YXRlOwo+ICsJZW51bSB1c2JfZGV2aWNlX3Nw ZWVkIHNwZWVkOwo+ICsJaW50IHJldCA9IDA7Cj4gKwl1MzIgd1ZhbHVlOwo+ICsJdTMyIHdJbmRl eDsKPiArCXUxNiB0bW9kZTsKPiArCj4gKwl3VmFsdWUgPSBsZTE2X3RvX2NwdShjdHJsLT53VmFs dWUpOwo+ICsJd0luZGV4ID0gbGUxNl90b19jcHUoY3RybC0+d0luZGV4KTsKPiArCXN0YXRlID0g cHJpdl9kZXYtPmdhZGdldC5zdGF0ZTsKPiArCXNwZWVkID0gcHJpdl9kZXYtPmdhZGdldC5zcGVl ZDsKPiArCj4gKwlzd2l0Y2ggKGN0cmwtPndWYWx1ZSkgewo+ICsJY2FzZSBVU0JfREVWSUNFX1JF TU9URV9XQUtFVVA6Cj4gKwkJcHJpdl9kZXYtPndha2VfdXBfZmxhZyA9ICEhc2V0Owo+ICsJCWJy ZWFrOwo+ICsJY2FzZSBVU0JfREVWSUNFX1UxX0VOQUJMRToKPiArCQlpZiAoc3RhdGUgIT0gVVNC X1NUQVRFX0NPTkZJR1VSRUQgfHwgc3BlZWQgIT0gVVNCX1NQRUVEX1NVUEVSKQo+ICsJCQlyZXR1 cm4gLUVJTlZBTDsKPiArCj4gKwkJcHJpdl9kZXYtPnUxX2FsbG93ZWQgPSAhIXNldDsKPiArCQli cmVhazsKPiArCWNhc2UgVVNCX0RFVklDRV9VMl9FTkFCTEU6Cj4gKwkJaWYgKHN0YXRlICE9IFVT Ql9TVEFURV9DT05GSUdVUkVEIHx8IHNwZWVkICE9IFVTQl9TUEVFRF9TVVBFUikKPiArCQkJcmV0 dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXByaXZfZGV2LT51Ml9hbGxvd2VkID0gISFzZXQ7Cj4gKwkJ YnJlYWs7Cj4gKwljYXNlIFVTQl9ERVZJQ0VfTFRNX0VOQUJMRToKPiArCQlyZXQgPSAtRUlOVkFM Owo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfREVWSUNFX1RFU1RfTU9ERToKPiArCQlpZiAoc3Rh dGUgIT0gVVNCX1NUQVRFX0NPTkZJR1VSRUQgfHwgc3BlZWQgPiBVU0JfU1BFRURfSElHSCkKPiAr CQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXRtb2RlID0gbGUxNl90b19jcHUoY3RybC0+d0lu ZGV4KTsKPiArCj4gKwkJaWYgKCFzZXQgfHwgKHRtb2RlICYgMHhmZikgIT0gMCkKPiArCQkJcmV0 dXJuIC1FSU5WQUw7Cj4gKwo+ICsJCXN3aXRjaCAodG1vZGUgPj4gOCkgewo+ICsJCWNhc2UgVEVT VF9KOgo+ICsJCWNhc2UgVEVTVF9LOgo+ICsJCWNhc2UgVEVTVF9TRTBfTkFLOgo+ICsJCWNhc2Ug VEVTVF9QQUNLRVQ6Cj4gKwkJCWNkbnMzX3NldF9yZWdpc3Rlcl9iaXQoJnByaXZfZGV2LT5yZWdz LT51c2JfY21kLAo+ICsJCQkJCSAgICAgICBVU0JfQ01EX1NUTU9ERSB8Cj4gKwkJCQkJICAgICAg IFVTQl9TVFNfVE1PREVfU0VMKHRtb2RlIC0gMSkpOwo+ICsJCQlicmVhazsKPiArCQlkZWZhdWx0 Ogo+ICsJCQlyZXQgPSAtRUlOVkFMOwo+ICsJCX0KPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4g KwkJcmV0ID0gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IGNkbnMzX2VwMF9mZWF0dXJlX2hhbmRsZV9pbnRmKHN0cnVjdCBjZG5zM19kZXZp Y2UgKnByaXZfZGV2LAo+ICsJCQkJCSBzdHJ1Y3QgdXNiX2N0cmxyZXF1ZXN0ICpjdHJsLAo+ICsJ CQkJCSBpbnQgc2V0KQo+ICt7Cj4gKwl1MzIgd1ZhbHVlOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ ICsJd1ZhbHVlID0gbGUxNl90b19jcHUoY3RybC0+d1ZhbHVlKTsKPiArCj4gKwlzd2l0Y2ggKHdW YWx1ZSkgewo+ICsJY2FzZSBVU0JfSU5UUkZfRlVOQ19TVVNQRU5EOgo+ICsJCWJyZWFrOwo+ICsJ ZGVmYXVsdDoKPiArCQlyZXQgPSAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiByZXQ7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgY2RuczNfZXAwX2ZlYXR1cmVfaGFuZGxlX2VuZHBvaW50KHN0 cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICsJCQkJCSAgICAgc3RydWN0IHVzYl9jdHJs cmVxdWVzdCAqY3RybCwKPiArCQkJCQkgICAgIGludCBzZXQpCj4gK3sKPiArCXN0cnVjdCBjZG5z M19lbmRwb2ludCAqcHJpdl9lcDsKPiArCWludCByZXQgPSAwOwo+ICsJdTggaW5kZXg7Cj4gKwo+ ICsJaWYgKCEoY3RybC0+d0luZGV4ICYgIH5VU0JfRElSX0lOKSkKPiArCQlyZXR1cm4gMDsKCldo eSBpcyB0aGlzIGNoZWNrPwoKPiArCj4gKwlpbmRleCA9IGNkbnMzX2VwX2FkZHJfdG9faW5kZXgo Y3RybC0+d0luZGV4KTsKPiArCXByaXZfZXAgPSBwcml2X2Rldi0+ZXBzW2luZGV4XTsKPiArCj4g KwljZG5zM19zZWxlY3RfZXAocHJpdl9kZXYsIGN0cmwtPndJbmRleCk7Cj4gKwo+ICsJaWYgKGxl MTZfdG9fY3B1KGN0cmwtPndWYWx1ZSkgIT0gVVNCX0VORFBPSU5UX0hBTFQpCj4gKwkJcmV0dXJu IC1FSU5WQUw7CgpUaGlzIGNoZWNrIHNob3VsZCBiZSBkb25lIGZpcnN0IGJlZm9yZSB5b3UgdHJ5 IHRvIGRlY29kZSB3SW5kZXguCgo+ICsKPiArCWlmIChzZXQpIHsKPiArCQl3cml0ZWwoRVBfQ01E X1NTVEFMTCwgJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQpOwo+ICsJCXByaXZfZXAtPmZsYWdzIHw9 IEVQX1NUQUxMOwo+ICsJfSBlbHNlIHsKPiArCQlzdHJ1Y3QgdXNiX3JlcXVlc3QgKnJlcXVlc3Q7 Cj4gKwo+ICsJCWlmIChwcml2X2Rldi0+ZXBzW2luZGV4XS0+ZmxhZ3MgJiBFUF9XRURHRSkgewo+ ICsJCQljZG5zM19zZWxlY3RfZXAocHJpdl9kZXYsIDB4MDApOwo+ICsJCQlyZXR1cm4gMDsKPiAr CQl9Cj4gKwo+ICsJCXdyaXRlbChFUF9DTURfQ1NUQUxMIHwgRVBfQ01EX0VQUlNULCAmcHJpdl9k ZXYtPnJlZ3MtPmVwX2NtZCk7Cj4gKwo+ICsJCS8qIHdhaXQgZm9yIEVQUlNUIGNsZWFyZWQgKi8K PiArCQlyZXQgPSBjZG5zM19oYW5kc2hha2UoJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQsCj4gKwkJ CQkgICAgICBFUF9DTURfRVBSU1QsIDAsIDEwMCk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJu IC1FSU5WQUw7Cj4gKwo+ICsJCXByaXZfZXAtPmZsYWdzICY9IH5FUF9TVEFMTDsKPiArCj4gKwkJ cmVxdWVzdCA9IGNkbnMzX25leHRfcmVxdWVzdCgmcHJpdl9lcC0+cmVxdWVzdF9saXN0KTsKPiAr CQlpZiAocmVxdWVzdCkKPiArCQkJY2RuczNfZXBfcnVuX3RyYW5zZmVyKHByaXZfZXAsIHJlcXVl c3QpOwo+ICsJfQo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyoqCj4gKyAqIGNkbnMzX3Jl cV9lcDBfaGFuZGxlX2ZlYXR1cmUgLQo+ICsgKiBIYW5kbGluZyBvZiBHRVQvU0VUX0ZFQVRVUkUg c3RhbmRhcmQgVVNCIHJlcXVlc3QKPiArICoKPiArICogQHByaXZfZGV2OiBleHRlbmRlZCBnYWRn ZXQgb2JqZWN0Cj4gKyAqIEBjdHJsX3JlcTogcG9pbnRlciB0byByZWNlaXZlZCBzZXR1cCBwYWNr ZXQKPiArICogQHNldDogbXVzdCBiZSBzZXQgdG8gMSBmb3IgU0VUX0ZFQVRVUkUgcmVxdWVzdAo+ ICsgKgo+ICsgKiBSZXR1cm5zIDAgaWYgc3VjY2VzcywgZXJyb3IgY29kZSBvbiBlcnJvcgo+ICsg Ki8KPiArc3RhdGljIGludCBjZG5zM19yZXFfZXAwX2hhbmRsZV9mZWF0dXJlKHN0cnVjdCBjZG5z M19kZXZpY2UgKnByaXZfZGV2LAo+ICsJCQkJCXN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmws Cj4gKwkJCQkJaW50IHNldCkKPiArewo+ICsJaW50IHJldCA9IDA7Cj4gKwl1MzIgcmVjaXA7Cj4g Kwo+ICsJcmVjaXAgPSBjdHJsLT5iUmVxdWVzdFR5cGUgJiBVU0JfUkVDSVBfTUFTSzsKPiArCj4g Kwlzd2l0Y2ggKHJlY2lwKSB7Cj4gKwljYXNlIFVTQl9SRUNJUF9ERVZJQ0U6Cj4gKwkJcmV0ID0g Y2RuczNfZXAwX2ZlYXR1cmVfaGFuZGxlX2RldmljZShwcml2X2RldiwgY3RybCwgc2V0KTsKPiAr CQlicmVhazsKPiArCWNhc2UgVVNCX1JFQ0lQX0lOVEVSRkFDRToKPiArCQlyZXQgPSBjZG5zM19l cDBfZmVhdHVyZV9oYW5kbGVfaW50Zihwcml2X2RldiwgY3RybCwgc2V0KTsKPiArCQlicmVhazsK PiArCWNhc2UgVVNCX1JFQ0lQX0VORFBPSU5UOgo+ICsJCXJldCA9IGNkbnMzX2VwMF9mZWF0dXJl X2hhbmRsZV9lbmRwb2ludChwcml2X2RldiwgY3RybCwgc2V0KTsKPiArCQlicmVhazsKPiArCWRl ZmF1bHQ6Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKCFyZXQpCj4gKwkJ d3JpdGVsKEVQX0NNRF9FUkRZIHwgRVBfQ01EX1JFUV9DTVBMLCAmcHJpdl9kZXYtPnJlZ3MtPmVw X2NtZCk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyoqCj4gKyAqIGNkbnMzX3Jl cV9lcDBfc2V0X3NlbCAtIEhhbmRsaW5nIG9mIFNFVF9TRUwgc3RhbmRhcmQgVVNCIHJlcXVlc3QK PiArICogQHByaXZfZGV2OiBleHRlbmRlZCBnYWRnZXQgb2JqZWN0Cj4gKyAqIEBjdHJsX3JlcTog cG9pbnRlciB0byByZWNlaXZlZCBzZXR1cCBwYWNrZXQKPiArICoKPiArICogUmV0dXJucyAwIGlm IHN1Y2Nlc3MsIGVycm9yIGNvZGUgb24gZXJyb3IKPiArICovCj4gK3N0YXRpYyBpbnQgY2RuczNf cmVxX2VwMF9zZXRfc2VsKHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICsJCQkJIHN0 cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0cmxfcmVxKQo+ICt7Cj4gKwlpZiAocHJpdl9kZXYtPmdh ZGdldC5zdGF0ZSA8IFVTQl9TVEFURV9BRERSRVNTKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsK PiArCWlmIChjdHJsX3JlcS0+d0xlbmd0aCAhPSA2KSB7Cj4gKwkJZGV2X2VycigmcHJpdl9kZXYt PmRldiwgIlNldCBTRUwgc2hvdWxkIGJlIDYgYnl0ZXMsIGdvdCAlZFxuIiwKPiArCQkJY3RybF9y ZXEtPndMZW5ndGgpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXByaXZfZGV2 LT5lcDBfZGF0YV9kaXIgPSAwOwo+ICsJY2RuczNfZXAwX3J1bl90cmFuc2Zlcihwcml2X2Rldiwg cHJpdl9kZXYtPnNldHVwX2RtYSwgNiwgMSk7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArLyoq Cj4gKyAqIGNkbnMzX3JlcV9lcDBfc2V0X2lzb2NoX2RlbGF5IC0KPiArICogSGFuZGxpbmcgb2Yg R0VUX0lTT0NIX0RFTEFZIHN0YW5kYXJkIFVTQiByZXF1ZXN0Cj4gKyAqIEBwcml2X2RldjogZXh0 ZW5kZWQgZ2FkZ2V0IG9iamVjdAo+ICsgKiBAY3RybF9yZXE6IHBvaW50ZXIgdG8gcmVjZWl2ZWQg c2V0dXAgcGFja2V0Cj4gKyAqCj4gKyAqIFJldHVybnMgMCBpZiBzdWNjZXNzLCBlcnJvciBjb2Rl IG9uIGVycm9yCj4gKyAqLwo+ICtzdGF0aWMgaW50IGNkbnMzX3JlcV9lcDBfc2V0X2lzb2NoX2Rl bGF5KHN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2LAo+ICsJCQkJCSBzdHJ1Y3QgdXNiX2N0 cmxyZXF1ZXN0ICpjdHJsX3JlcSkKPiArewo+ICsJaWYgKGN0cmxfcmVxLT53SW5kZXggfHwgY3Ry bF9yZXEtPndMZW5ndGgpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcHJpdl9kZXYtPmlz b2NoX2RlbGF5ID0gY3RybF9yZXEtPndWYWx1ZTsKPiArCXdyaXRlbChFUF9DTURfRVJEWSB8IEVQ X0NNRF9SRVFfQ01QTCwgJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQpOwo+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gKy8qKgo+ICsgKiBjZG5zM19lcDBfc3RhbmRhcmRfcmVxdWVzdCAtIEhhbmRsaW5n IHN0YW5kYXJkIFVTQiByZXF1ZXN0cwo+ICsgKiBAcHJpdl9kZXY6IGV4dGVuZGVkIGdhZGdldCBv YmplY3QKPiArICogQGN0cmxfcmVxOiBwb2ludGVyIHRvIHJlY2VpdmVkIHNldHVwIHBhY2tldAo+ ICsgKgo+ICsgKiBSZXR1cm5zIDAgaWYgc3VjY2VzcywgZXJyb3IgY29kZSBvbiBlcnJvcgo+ICsg Ki8KPiArc3RhdGljIGludCBjZG5zM19lcDBfc3RhbmRhcmRfcmVxdWVzdChzdHJ1Y3QgY2RuczNf ZGV2aWNlICpwcml2X2RldiwKPiArCQkJCSAgICAgIHN0cnVjdCB1c2JfY3RybHJlcXVlc3QgKmN0 cmxfcmVxKQo+ICt7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXN3aXRjaCAoY3RybF9yZXEtPmJSZXF1 ZXN0KSB7Cj4gKwljYXNlIFVTQl9SRVFfU0VUX0FERFJFU1M6Cj4gKwkJcmV0ID0gY2RuczNfcmVx X2VwMF9zZXRfYWRkcmVzcyhwcml2X2RldiwgY3RybF9yZXEpOwo+ICsJCWJyZWFrOwo+ICsJY2Fz ZSBVU0JfUkVRX1NFVF9DT05GSUdVUkFUSU9OOgo+ICsJCXJldCA9IGNkbnMzX3JlcV9lcDBfc2V0 X2NvbmZpZ3VyYXRpb24ocHJpdl9kZXYsIGN0cmxfcmVxKTsKPiArCQlicmVhazsKPiArCWNhc2Ug VVNCX1JFUV9HRVRfU1RBVFVTOgo+ICsJCXJldCA9IGNkbnMzX3JlcV9lcDBfZ2V0X3N0YXR1cyhw cml2X2RldiwgY3RybF9yZXEpOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfUkVRX0NMRUFSX0ZF QVRVUkU6Cj4gKwkJcmV0ID0gY2RuczNfcmVxX2VwMF9oYW5kbGVfZmVhdHVyZShwcml2X2Rldiwg Y3RybF9yZXEsIDApOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBVU0JfUkVRX1NFVF9GRUFUVVJFOgo+ ICsJCXJldCA9IGNkbnMzX3JlcV9lcDBfaGFuZGxlX2ZlYXR1cmUocHJpdl9kZXYsIGN0cmxfcmVx LCAxKTsKPiArCQlicmVhazsKPiArCWNhc2UgVVNCX1JFUV9TRVRfU0VMOgo+ICsJCXJldCA9IGNk bnMzX3JlcV9lcDBfc2V0X3NlbChwcml2X2RldiwgY3RybF9yZXEpOwo+ICsJCWJyZWFrOwo+ICsJ Y2FzZSBVU0JfUkVRX1NFVF9JU09DSF9ERUxBWToKPiArCQlyZXQgPSBjZG5zM19yZXFfZXAwX3Nl dF9pc29jaF9kZWxheShwcml2X2RldiwgY3RybF9yZXEpOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVs dDoKPiArCQlyZXQgPSBjZG5zM19lcDBfZGVsZWdhdGVfcmVxKHByaXZfZGV2LCBjdHJsX3JlcSk7 Cj4gKwkJYnJlYWs7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiAgc3RhdGlj IHZvaWQgX19wZW5kaW5nX3NldHVwX3N0YXR1c19oYW5kbGVyKHN0cnVjdCBjZG5zM19kZXZpY2Ug KnByaXZfZGV2KQo+ICB7Cj4gLQkvL1RPRE86IEltcGxlbWVudHMgdGhpcyBmdW5jdGlvbgo+ICsJ c3RydWN0IHVzYl9yZXF1ZXN0ICpyZXF1ZXN0ID0gcHJpdl9kZXYtPnBlbmRpbmdfc3RhdHVzX3Jl cXVlc3Q7Cj4gKwo+ICsJaWYgKHByaXZfZGV2LT5zdGF0dXNfY29tcGxldGlvbl9ub19jYWxsICYm IHJlcXVlc3QgJiYKPiArCSAgICByZXF1ZXN0LT5jb21wbGV0ZSkgewo+ICsJCXJlcXVlc3QtPmNv bXBsZXRlKHByaXZfZGV2LT5nYWRnZXQuZXAwLCByZXF1ZXN0KTsKPiArCQlwcml2X2Rldi0+c3Rh dHVzX2NvbXBsZXRpb25fbm9fY2FsbCA9IDA7Cj4gKwl9Cj4gK30KPiArCj4gK3ZvaWQgY2RuczNf cGVuZGluZ19zZXR1cF9zdGF0dXNfaGFuZGxlcihzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspCj4g K3sKPiArCXN0cnVjdCBjZG5zM19kZXZpY2UgKnByaXZfZGV2ID0gY29udGFpbmVyX29mKHdvcmss IHN0cnVjdCBjZG5zM19kZXZpY2UsCj4gKwkJCXBlbmRpbmdfc3RhdHVzX3dxKTsKPiArCXVuc2ln bmVkIGxvbmcgZmxhZ3M7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJnByaXZfZGV2LT5sb2Nr LCBmbGFncyk7Cj4gKwlfX3BlbmRpbmdfc2V0dXBfc3RhdHVzX2hhbmRsZXIocHJpdl9kZXYpOwo+ ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmcHJpdl9kZXYtPmxvY2ssIGZsYWdzKTsKPiAgfQo+ ICAKPiAgLyoqCj4gQEAgLTEwMSwxMiArNTQ2LDUwIEBAIHN0YXRpYyB2b2lkIF9fcGVuZGluZ19z ZXR1cF9zdGF0dXNfaGFuZGxlcihzdHJ1Y3QgY2RuczNfZGV2aWNlICpwcml2X2RldikKPiAgICov Cj4gIHN0YXRpYyB2b2lkIGNkbnMzX2VwMF9zZXR1cF9waGFzZShzdHJ1Y3QgY2RuczNfZGV2aWNl ICpwcml2X2RldikKPiAgewo+IC0JLy9UT0RPOiBJbXBsZW1lbnRzIHRoaXMgZnVuY3Rpb24uCj4g KwlzdHJ1Y3QgdXNiX2N0cmxyZXF1ZXN0ICpjdHJsID0gcHJpdl9kZXYtPnNldHVwOwo+ICsJaW50 IHJlc3VsdDsKPiArCj4gKwlpZiAoKGN0cmwtPmJSZXF1ZXN0VHlwZSAmIFVTQl9UWVBFX01BU0sp ID09IFVTQl9UWVBFX1NUQU5EQVJEKQo+ICsJCXJlc3VsdCA9IGNkbnMzX2VwMF9zdGFuZGFyZF9y ZXF1ZXN0KHByaXZfZGV2LCBjdHJsKTsKPiArCWVsc2UKPiArCQlyZXN1bHQgPSBjZG5zM19lcDBf ZGVsZWdhdGVfcmVxKHByaXZfZGV2LCBjdHJsKTsKPiArCj4gKwlpZiAocmVzdWx0ICE9IDAgJiYg cmVzdWx0ICE9IFVTQl9HQURHRVRfREVMQVlFRF9TVEFUVVMpIHsKPiArCQlkZXZfZGJnKCZwcml2 X2Rldi0+ZGV2LCAiU1RBTEwgZm9yIGVwMFxuIik7Cj4gKwkJLyogc2V0X3N0YWxsIG9uIGVwMCAq Lwo+ICsJCWNkbnMzX3NlbGVjdF9lcChwcml2X2RldiwgMHgwMCk7Cj4gKwkJd3JpdGVsKEVQX0NN RF9TU1RBTEwsICZwcml2X2Rldi0+cmVncy0+ZXBfY21kKTsKPiArCQl3cml0ZWwoRVBfQ01EX0VS RFkgfCBFUF9DTURfUkVRX0NNUEwsICZwcml2X2Rldi0+cmVncy0+ZXBfY21kKTsKPiArCX0KPiAg fQo+ICAKPiAgc3RhdGljIHZvaWQgY2RuczNfdHJhbnNmZXJfY29tcGxldGVkKHN0cnVjdCBjZG5z M19kZXZpY2UgKnByaXZfZGV2KQo+ICB7Cj4gLQkvL1RPRE86IEltcGxlbWVudHMgdGhpcyBmdW5j dGlvbgo+ICsJaWYgKHByaXZfZGV2LT5lcDBfcmVxdWVzdCkgewo+ICsJCXVzYl9nYWRnZXRfdW5t YXBfcmVxdWVzdF9ieV9kZXYocHJpdl9kZXYtPnN5c2RldiwKPiArCQkJCQkJcHJpdl9kZXYtPmVw MF9yZXF1ZXN0LAo+ICsJCQkJCQlwcml2X2Rldi0+ZXAwX2RhdGFfZGlyKTsKPiArCj4gKwkJcHJp dl9kZXYtPmVwMF9yZXF1ZXN0LT5hY3R1YWwgPQo+ICsJCQlUUkJfTEVOKGxlMzJfdG9fY3B1KHBy aXZfZGV2LT50cmJfZXAwLT5sZW5ndGgpKTsKPiArCj4gKwkJZGV2X2RiZygmcHJpdl9kZXYtPmRl diwgIkVwMCBjb21wbGV0aW9uIGxlbmd0aCAlZFxuIiwKPiArCQkJcHJpdl9kZXYtPmVwMF9yZXF1 ZXN0LT5hY3R1YWwpOwo+ICsJCWxpc3RfZGVsX2luaXQoJnByaXZfZGV2LT5lcDBfcmVxdWVzdC0+ bGlzdCk7Cj4gKwl9Cj4gKwo+ICsJaWYgKHByaXZfZGV2LT5lcDBfcmVxdWVzdCAmJgo+ICsJICAg IHByaXZfZGV2LT5lcDBfcmVxdWVzdC0+Y29tcGxldGUpIHsKPiArCQlzcGluX3VubG9jaygmcHJp dl9kZXYtPmxvY2spOwo+ICsJCXByaXZfZGV2LT5lcDBfcmVxdWVzdC0+Y29tcGxldGUocHJpdl9k ZXYtPmdhZGdldC5lcDAsCj4gKwkJCQkJCXByaXZfZGV2LT5lcDBfcmVxdWVzdCk7Cj4gKwo+ICsJ CXByaXZfZGV2LT5lcDBfcmVxdWVzdCA9IE5VTEw7Cj4gKwkJc3Bpbl9sb2NrKCZwcml2X2Rldi0+ bG9jayk7Cj4gKwl9Cj4gKwo+ICsJY2RuczNfcHJlcGFyZV9zZXR1cF9wYWNrZXQocHJpdl9kZXYp Owo+ICsJd3JpdGVsKEVQX0NNRF9SRVFfQ01QTCwgJnByaXZfZGV2LT5yZWdzLT5lcF9jbWQpOwo+ ICB9Cj4gIAo+ICAvKioKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMg Yi9kcml2ZXJzL3VzYi9jZG5zMy9nYWRnZXQuYwo+IGluZGV4IDMwOTIwMjQ3NGU1Ny4uMDIwMmZm NWY2YzkwIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvdXNiL2NkbnMzL2dhZGdldC5jCj4gKysrIGIv ZHJpdmVycy91c2IvY2RuczMvZ2FkZ2V0LmMKPiBAQCAtNzAsNiArNzAsMzAgQEAgc3RhdGljIHU4 IGNkbnMzX2VwX3JlZ19wb3NfdG9faW5kZXgoaW50IGkpCj4gIAlyZXR1cm4gKChpIC8gMTYpICsg KCgoaSAlIDE2KSAtIDIpICogMikpOwo+ICB9Cj4gIAo+ICsvKioKPiArICogY2RuczNfZXBfYWRk cl90b19pbmRleCAtIE1hY3JvIGNvbnZlcnRzIGVuZHBvaW50IGFkZHJlc3MgdG8KPiArICogaW5k ZXggb2YgZW5kcG9pbnQgb2JqZWN0IGluIGNkbnMzX2RldmljZS5lcHNbXSBjb250YWluZXIKPiAr ICogQGVwX2FkZHI6IGVuZHBvaW50IGFkZHJlc3MgZm9yIHdoaWNoIGVuZHBvaW50IG9iamVjdCBp cyByZXF1aXJlZAo+ICsgKgo+ICsgKiBSZW1lbWJlciB0aGF0IGVuZHBvaW50IGNvbnRhaW5lciBk b2Vzbid0IGNvbnRhaW4gZGVmYXVsdCBlbmRwb2ludAo+ICsgKi8KPiArdTggY2RuczNfZXBfYWRk cl90b19pbmRleCh1OCBlcF9hZGRyKQo+ICt7Cj4gKwlyZXR1cm4gKCgoZXBfYWRkciAmIDB4N0Yp IC0gMSkgKyAoKGVwX2FkZHIgJiBVU0JfRElSX0lOKSA/IDEgOiAwKSk7Cj4gK30KPiArCj4gKy8q Kgo+ICsgKiBjZG5zM19lcF9hZGRyX3RvX2JpdF9wb3MgLSBNYWNybyBjb252ZXJ0cyBlbmRwb2lu dCBhZGRyZXNzIHRvCj4gKyAqIGJpdCBwb3NpdGlvbiBpbiBlcF9pc3RzIHJlZ2lzdGVyCj4gKyAq IEBlcF9hZGRyOiBlbmRwb2ludCBhZGRyZXNzIGZvciB3aGljaCBiaXQgcG9zaXRpb24gaXMgcmVx dWlyZWQKPiArICoKPiArICogUmVtZW1iZXIgdGhhdCBlbmRwb2ludCBjb250YWluZXIgZG9lc24n dCBjb250YWluIGRlZmF1bHQgZW5kcG9pbnQKPiArICovCj4gK3N0YXRpYyB1MzIgY2RuczNfZXBf YWRkcl90b19iaXRfcG9zKHU4IGVwX2FkZHIpCj4gK3sKPiArCXJldHVybiAoMSA8PCAoZXBfYWRk ciAmIDB4N0YpKSA8PCAoKGVwX2FkZHIgJiAweDgwKSA/IDE2IDogMCk7Cj4gK30KPiArCj4gIC8q Kgo+ICAgKiBjZG5zM19uZXh0X3JlcXVlc3QgLSByZXR1cm5zIG5leHQgcmVxdWVzdCBmcm9tIGxp c3QKPiAgICogQGxpc3Q6IGxpc3QgY29udGFpbmluZyByZXF1ZXN0cwo+IEBAIC00NjQsNiArNDg4 LDk5IEBAIHN0YXRpYyBpcnFyZXR1cm5fdCBjZG5zM19pcnFfaGFuZGxlcl90aHJlYWQoc3RydWN0 IGNkbnMzICpjZG5zKQo+ICAJcmV0dXJuIHJldDsKPiAgfQo+ICAKPiArLyoqCj4gKyAqIGNkbnMz X2VwX29uY2hpcF9idWZmZXJfYWxsb2MgLSBUcnkgdG8gYWxsb2NhdGUgb25jaGlwIGJ1ZiBmb3Ig RVAKPiArICoKPiArICogVGhlIHJlYWwgYWxsb2NhdGlvbiB3aWxsIG9jY3VyIGR1cmluZyB3cml0 ZSB0byBFUF9DRkcgcmVnaXN0ZXIsCj4gKyAqIHRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBjaGVj ayBpZiB0aGUgJ3NpemUnIGFsbG9jYXRpb24gaXMgYWxsb3dlZC4KPiArICoKPiArICogQHByaXZf ZGV2OiBleHRlbmRlZCBnYWRnZXQgb2JqZWN0Cj4gKyAqIEBzaXplOiB0aGUgc2l6ZSAoS0IpIGZv ciBFUCB3b3VsZCBsaWtlIHRvIGFsbG9jYXRlCj4gKyAqIEBpc19pbjogdGhlIGRpcmVjdGlvbiBm b3IgRVAKPiArICoKPiArICogUmV0dXJuIDAgaWYgdGhlIGxhdGVyIGFsbG9jYXRpb24gaXMgYWxs b3dlZCBvciBuZWdhdGl2ZSB2YWx1ZSBvbiBmYWlsdXJlCj4gKyAqLwo+ICtzdGF0aWMgaW50IGNk bnMzX2VwX29uY2hpcF9idWZmZXJfYWxsb2Moc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYs Cj4gKwkJCQkJaW50IHNpemUsIGludCBpc19pbikKPiArewo+ICsJaWYgKGlzX2luKSB7Cj4gKwkJ cHJpdl9kZXYtPm9uY2hpcF9tZW1fYWxsb2NhdGVkX3NpemUgKz0gc2l6ZTsKPiArCX0gZWxzZSBp ZiAoIXByaXZfZGV2LT5vdXRfbWVtX2lzX2FsbG9jYXRlZCkgewo+ICsJCSAvKiBBTEwgT1VUIEVQ cyBhcmUgc2hhcmVkIHRoZSBzYW1lIGNodW5rIG9uY2hpcCBtZW1vcnkgKi8KPiArCQlwcml2X2Rl di0+b25jaGlwX21lbV9hbGxvY2F0ZWRfc2l6ZSArPSBzaXplOwo+ICsJCXByaXZfZGV2LT5vdXRf bWVtX2lzX2FsbG9jYXRlZCA9IDE7Cj4gKwl9Cj4gKwo+ICsJaWYgKHByaXZfZGV2LT5vbmNoaXBf bWVtX2FsbG9jYXRlZF9zaXplID4gQ0ROUzNfT05DSElQX0JVRl9TSVpFKSB7Cj4gKwkJcHJpdl9k ZXYtPm9uY2hpcF9tZW1fYWxsb2NhdGVkX3NpemUgLT0gc2l6ZTsKPiArCQlyZXR1cm4gLUVQRVJN Owo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArfQo+ICsKPiArLyoqCj4gKyAq IGNkbnMzX2VwX2NvbmZpZyBDb25maWd1cmUgaGFyZHdhcmUgZW5kcG9pbnQKPiArICogQHByaXZf ZXA6IGV4dGVuZGVkIGVuZHBvaW50IG9iamVjdAo+ICsgKi8KPiArdm9pZCBjZG5zM19lcF9jb25m aWcoc3RydWN0IGNkbnMzX2VuZHBvaW50ICpwcml2X2VwKQo+ICt7Cj4gKwlib29sIGlzX2lzb19l cCA9IChwcml2X2VwLT50eXBlID09IFVTQl9FTkRQT0lOVF9YRkVSX0lTT0MpOwo+ICsJc3RydWN0 IGNkbnMzX2RldmljZSAqcHJpdl9kZXYgPSBwcml2X2VwLT5jZG5zM19kZXY7Cj4gKwl1MzIgYkVu ZHBvaW50QWRkcmVzcyA9IHByaXZfZXAtPm51bSB8IHByaXZfZXAtPmRpcjsKPiArCXUzMiBpbnRl cnJ1cHRfbWFzayA9IEVQX1NUU19FTl9UUkJFUlJFTjsKPiArCXUzMiBtYXhfcGFja2V0X3NpemUg PSAwOwo+ICsJdTMyIGVwX2NmZyA9IDA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWlmIChwcml2X2Vw LT50eXBlID09IFVTQl9FTkRQT0lOVF9YRkVSX0lOVCkgewo+ICsJCWVwX2NmZyA9IEVQX0NGR19F UFRZUEUoVVNCX0VORFBPSU5UX1hGRVJfSU5UKTsKPiArCX0gZWxzZSBpZiAocHJpdl9lcC0+dHlw ZSA9PSBVU0JfRU5EUE9JTlRfWEZFUl9CVUxLKSB7Cj4gKwkJZXBfY2ZnID0gRVBfQ0ZHX0VQVFlQ RShVU0JfRU5EUE9JTlRfWEZFUl9CVUxLKTsKPiArCX0gZWxzZSB7Cj4gKwkJZXBfY2ZnID0gRVBf Q0ZHX0VQVFlQRShVU0JfRU5EUE9JTlRfWEZFUl9JU09DKTsKPiArCQlpbnRlcnJ1cHRfbWFzayA9 IDB4RkZGRkZGRkY7Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChwcml2X2Rldi0+Z2FkZ2V0LnNwZWVk KSB7Cj4gKwljYXNlIFVTQl9TUEVFRF9GVUxMOgo+ICsJCW1heF9wYWNrZXRfc2l6ZSA9IGlzX2lz b19lcCA/IDEwMjMgOiA2NDsKPiArCQlicmVhazsKPiArCWNhc2UgVVNCX1NQRUVEX0hJR0g6Cj4g KwkJbWF4X3BhY2tldF9zaXplID0gaXNfaXNvX2VwID8gMTAyNCA6IDUxMjsKPiArCQlicmVhazsK PiArCWNhc2UgVVNCX1NQRUVEX1NVUEVSOgo+ICsJCW1heF9wYWNrZXRfc2l6ZSA9IDEwMjQ7Cj4g KwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCS8vYWxsIG90aGVyIHNwZWVkIGFyZSBub3Qgc3Vw cG9ydGVkCj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsKPiArCXJldCA9IGNkbnMzX2VwX29uY2hpcF9i dWZmZXJfYWxsb2MocHJpdl9kZXYsIENETlMzX0VQX0JVRl9TSVpFLAo+ICsJCQkJCSAgIHByaXZf ZXAtPmRpcik7Cgp3aGVyZSBkbyB5b3UgZnJlZSB0aGUgYnVmZmVyX2FsbG9jPwoKPiArCWlmIChy ZXQpIHsKPiArCQlkZXZfZXJyKCZwcml2X2Rldi0+ZGV2LCAib25jaGlwIG1lbSBpcyBmdWxsLCBl cCBpcyBpbnZhbGlkXG4iKTsKPiArCQlyZXR1cm47Cj4gKwl9Cj4gKwo+ICsJZXBfY2ZnIHw9IEVQ X0NGR19NQVhQS1RTSVpFKG1heF9wYWNrZXRfc2l6ZSkgfAo+ICsJCSAgRVBfQ0ZHX0JVRkZFUklO RyhDRE5TM19FUF9CVUZfU0laRSAtIDEpIHwKPiArCQkgIEVQX0NGR19NQVhCVVJTVChwcml2X2Vw LT5lbmRwb2ludC5tYXhidXJzdCk7Cj4gKwo+ICsJY2RuczNfc2VsZWN0X2VwKHByaXZfZGV2LCBi RW5kcG9pbnRBZGRyZXNzKTsKPiArCj4gKwl3cml0ZWwoZXBfY2ZnLCAmcHJpdl9kZXYtPnJlZ3Mt PmVwX2NmZyk7Cj4gKwl3cml0ZWwoaW50ZXJydXB0X21hc2ssICZwcml2X2Rldi0+cmVncy0+ZXBf c3RzX2VuKTsKPiArCj4gKwlkZXZfZGJnKCZwcml2X2Rldi0+ZGV2LCAiQ29uZmlndXJlICVzOiB3 aXRoIHZhbCAlMDh4XG4iLAo+ICsJCXByaXZfZXAtPm5hbWUsIGVwX2NmZyk7Cj4gKwo+ICsJLyog ZW5hYmxlIGludGVycnVwdCBmb3Igc2VsZWN0ZWQgZW5kcG9pbnQgKi8KPiArCWNkbnMzX3NldF9y ZWdpc3Rlcl9iaXQoJnByaXZfZGV2LT5yZWdzLT5lcF9pZW4sCj4gKwkJCSAgICAgICBjZG5zM19l cF9hZGRyX3RvX2JpdF9wb3MoYkVuZHBvaW50QWRkcmVzcykpOwo+ICt9Cj4gKwo+ICAvKiBGaW5k IGNvcnJlY3QgZGlyZWN0aW9uIGZvciBIVyBlbmRwb2ludCBhY2NvcmRpbmcgdG8gZGVzY3JpcHRp b24gKi8KPiAgc3RhdGljIGludCBjZG5zM19lcF9kaXJfaXNfY29ycmVjdChzdHJ1Y3QgdXNiX2Vu ZHBvaW50X2Rlc2NyaXB0b3IgKmRlc2MsCj4gIAkJCQkgICBzdHJ1Y3QgY2RuczNfZW5kcG9pbnQg KnByaXZfZXApCj4gQEAgLTExMDQsNiArMTIyMSw4IEBAIHN0YXRpYyBpbnQgX19jZG5zM19nYWRn ZXRfaW5pdChzdHJ1Y3QgY2RuczMgKmNkbnMpCj4gIAlwcml2X2Rldi0+aXNfY29ubmVjdGVkID0g MDsKPiAgCj4gIAlzcGluX2xvY2tfaW5pdCgmcHJpdl9kZXYtPmxvY2spOwo+ICsJSU5JVF9XT1JL KCZwcml2X2Rldi0+cGVuZGluZ19zdGF0dXNfd3EsCj4gKwkJICBjZG5zM19wZW5kaW5nX3NldHVw X3N0YXR1c19oYW5kbGVyKTsKPiAgCj4gIAlwcml2X2Rldi0+aW5fc3RhbmRieV9tb2RlID0gMTsK PiAgCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL2NkbnMzL2dhZGdldC5oIGIvZHJpdmVycy91 c2IvY2RuczMvZ2FkZ2V0LmgKPiBpbmRleCA4YzJmMzYzZjkzNDAuLmRiOGM2Y2I5ZjJhNSAxMDA2 NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9jZG5zMy9nYWRnZXQuaAo+ICsrKyBiL2RyaXZlcnMvdXNi L2NkbnMzL2dhZGdldC5oCj4gQEAgLTEwNzAsMTQgKzEwNzAsMTggQEAgc3RydWN0IGNkbnMzX2Rl dmljZSB7Cj4gIAo+ICBpbnQgY2RuczNfaGFuZHNoYWtlKHZvaWQgX19pb21lbSAqcHRyLCB1MzIg bWFzaywgdTMyIGRvbmUsIGludCB1c2VjKTsKPiAgdm9pZCBjZG5zM19zZXRfcmVnaXN0ZXJfYml0 KHZvaWQgX19pb21lbSAqcHRyLCB1MzIgbWFzayk7Cj4gK3ZvaWQgY2RuczNfcGVuZGluZ19zZXR1 cF9zdGF0dXNfaGFuZGxlcihzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspOwo+ICBpbnQgY2RuczNf aW5pdF9lcDAoc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYpOwo+ICB2b2lkIGNkbnMzX2Vw MF9jb25maWcoc3RydWN0IGNkbnMzX2RldmljZSAqcHJpdl9kZXYpOwo+ICt2b2lkIGNkbnMzX2Vw X2NvbmZpZyhzdHJ1Y3QgY2RuczNfZW5kcG9pbnQgKnByaXZfZXApOwo+ICB2b2lkIGNkbnMzX2No ZWNrX2VwMF9pbnRlcnJ1cHRfcHJvY2VlZChzdHJ1Y3QgY2RuczNfZGV2aWNlICpwcml2X2Rldiwg aW50IGRpcik7Cj4gIHZvaWQgY2RuczNfc2VsZWN0X2VwKHN0cnVjdCBjZG5zM19kZXZpY2UgKnBy aXZfZGV2LCB1MzIgZXApOwo+ICB2b2lkIGNkbnMzX2VuYWJsZV9sMShzdHJ1Y3QgY2RuczNfZGV2 aWNlICpwcml2X2RldiwgaW50IGVuYWJsZSk7Cj4gIHN0cnVjdCB1c2JfcmVxdWVzdCAqY2RuczNf bmV4dF9yZXF1ZXN0KHN0cnVjdCBsaXN0X2hlYWQgKmxpc3QpOwo+ICt2b2lkIGNkbnMzX2dhZGdl dF91bmNvbmZpZyhzdHJ1Y3QgY2RuczNfZGV2aWNlICpwcml2X2Rldik7Cj4gIGludCBjZG5zM19l cF9ydW5fdHJhbnNmZXIoc3RydWN0IGNkbnMzX2VuZHBvaW50ICpwcml2X2VwLAo+ICAJCQkgIHN0 cnVjdCB1c2JfcmVxdWVzdCAqcmVxdWVzdCk7Cj4gK3U4IGNkbnMzX2VwX2FkZHJfdG9faW5kZXgo dTggZXBfYWRkcik7Cj4gIGludCBjZG5zM19nYWRnZXRfZXBfc2V0X3dlZGdlKHN0cnVjdCB1c2Jf ZXAgKmVwKTsKPiAgaW50IGNkbnMzX2dhZGdldF9lcF9zZXRfaGFsdChzdHJ1Y3QgdXNiX2VwICpl cCwgaW50IHZhbHVlKTsKPiAgc3RydWN0IHVzYl9yZXF1ZXN0ICpjZG5zM19nYWRnZXRfZXBfYWxs b2NfcmVxdWVzdChzdHJ1Y3QgdXNiX2VwICplcCwKPiAKCmNoZWVycywKLXJvZ2VyCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: Roger Quadros Subject: Re: [RFC PATCH v2 12/15] usb:cdns3: Adds enumeration related function. Date: Wed, 28 Nov 2018 17:50:04 +0200 Message-ID: <5BFEB92C.9060903@ti.com> References: <1542535751-16079-1-git-send-email-pawell@cadence.com> <1542535751-16079-13-git-send-email-pawell@cadence.com> Mime-Version: 1.0 Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1542535751-16079-13-git-send-email-pawell@cadence.com> Sender: linux-kernel-owner@vger.kernel.org To: Pawel Laszczak , devicetree@vger.kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, adouglas@cadence.com, jbergsagel@ti.com, nsekhar@ti.com, nm@ti.com, sureshp@cadence.com, peter.chen@nxp.com, pjez@cadence.com, kurahul@cadence.com List-Id: devicetree@vger.kernel.org On 18/11/18 12:09, Pawel Laszczak wrote: > Patch implements a set of function related to enumeration process. > Some standard requests are handled on controller driver level and > other are delegated to gadget core driver. > All class requests are delegated to gadget core driver. > > Signed-off-by: Pawel Laszczak > --- > drivers/usb/cdns3/ep0.c | 491 ++++++++++++++++++++++++++++++++++++- > drivers/usb/cdns3/gadget.c | 119 +++++++++ > drivers/usb/cdns3/gadget.h | 4 + > 3 files changed, 610 insertions(+), 4 deletions(-) > > diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c > index eb92fd234bd7..6f33d98f7684 100644 > --- a/drivers/usb/cdns3/ep0.c > +++ b/drivers/usb/cdns3/ep0.c > @@ -10,6 +10,7 @@ > * Peter Chen > */ > > +#include > #include "gadget.h" > > static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = { > @@ -52,9 +53,31 @@ static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, > writel(EP_CMD_ERDY, &priv_dev->regs->ep_cmd); > } > > +/** > + * cdns3_ep0_delegate_req - Returns status of handling setup packet > + * Setup is handled by gadget driver > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns zero on success or negative value on failure > + */ > +static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + spin_unlock(&priv_dev->lock); > + priv_dev->setup_pending = 1; > + ret = priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); > + priv_dev->setup_pending = 0; Why is setup_pending flag being set and cleared? > + spin_lock(&priv_dev->lock); > + return ret; > +} > + > static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + priv_dev->ep0_data_dir = 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, 8, 0); why hardcode to 8? Don't vendor specific requests have different lengths? > } > > static void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) > @@ -90,9 +113,431 @@ static void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) > } > } > > +/** > + * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, 0x7FFF on deferred status stage, error code on error what is this magic number 0x7fff? > + */ > +static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state = priv_dev->gadget.state; > + struct cdns3_endpoint *priv_ep, *temp_ep; > + u32 config = le16_to_cpu(ctrl_req->wValue); > + int result = 0; > + > + switch (device_state) { > + case USB_STATE_ADDRESS: > + /* Configure non-control EPs */ > + list_for_each_entry_safe(priv_ep, temp_ep, > + &priv_dev->ep_match_list, > + ep_match_pending_list) > + cdns3_ep_config(priv_ep); Why configure here? They should be configured at ep_enable. no? And you don't need to maintain a ep_match/pending_list. > + > + result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (result) > + return result; > + > + if (config) { What if result is USB_GADGET_DELAYED_STATUS? > + cdns3_set_hw_configuration(priv_dev); usb_gadget_set_state(USB_STATE_CONFIGURED) ? > + } else { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); > + } > + break; > + case USB_STATE_CONFIGURED: > + result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (!config && !result) { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); > + } > + break; > + default: > + result = -EINVAL; > + } > + > + return result; > +} > + > +/** > + * cdns3_req_ep0_set_address - Handling of SET_ADDRESS standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_address(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state = priv_dev->gadget.state; > + u32 reg; > + u32 addr; > + > + addr = le16_to_cpu(ctrl_req->wValue); > + > + if (addr > DEVICE_ADDRESS_MAX) { If DEVICE_ADDRESS_MAX comes from USB spec it must be in ch9.h. Maybe add something like #define USB_DEVICE_MAX_ADDRESS 127 > + dev_err(&priv_dev->dev, > + "Device address (%d) cannot be greater than %d\n", > + addr, DEVICE_ADDRESS_MAX); > + return -EINVAL; > + } > + > + if (device_state == USB_STATE_CONFIGURED) { > + dev_err(&priv_dev->dev, "USB device already configured\n"); Message is misleading. How about "can't set_address from configured state" > + return -EINVAL; > + } > + > + reg = readl(&priv_dev->regs->usb_cmd); > + > + writel(reg | USB_CMD_FADDR(addr) | USB_CMD_SET_ADDR, > + &priv_dev->regs->usb_cmd); > + > + usb_gadget_set_state(&priv_dev->gadget, > + (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); > + > + cdns3_prepare_setup_packet(priv_dev); why call this here? This should be done after the current ep0 request is complete. > + > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + > + return 0; > +} > + > +/** > + * cdns3_req_ep0_get_status - Handling of GET_STATUS standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl) > +{ > + __le16 *response_pkt; > + u16 usb_status = 0; > + u32 recip; > + u32 reg; > + > + recip = ctrl->bRequestType & USB_RECIP_MASK; > + > + switch (recip) { > + case USB_RECIP_DEVICE: > + /* self powered */ > + usb_status |= priv_dev->gadget.is_selfpowered; if (prv_devgadget.is_selfpowered) usb_stats |= BIT(USB_DEVICE_SELF_POWERED); > + > + if (priv_dev->gadget.speed != USB_SPEED_SUPER) You should check controller speed directly instead. > + break; > + > + reg = readl(&priv_dev->regs->usb_sts); > + > + if (priv_dev->u1_allowed) > + usb_status |= BIT(USB_DEV_STAT_U1_ENABLED); > + > + if (priv_dev->u2_allowed) > + usb_status |= BIT(USB_DEV_STAT_U2_ENABLED); > + > + if (priv_dev->wake_up_flag) > + usb_status |= BIT(USB_DEVICE_REMOTE_WAKEUP); Remote wakeup is not SS specific. So needs to go before the SS check. > + break; > + case USB_RECIP_INTERFACE: > + return cdns3_ep0_delegate_req(priv_dev, ctrl); > + case USB_RECIP_ENDPOINT: > + /* check if endpoint is stalled */ > + cdns3_select_ep(priv_dev, ctrl->wIndex); > + if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts))) > + usb_status = BIT(USB_ENDPOINT_HALT); > + break; > + default: > + return -EINVAL; > + } > + > + response_pkt = (__le16 *)priv_dev->setup; > + *response_pkt = cpu_to_le16(usb_status); > + > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, > + sizeof(*response_pkt), 1); > + return 0; > +} > + > +static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + enum usb_device_state state; > + enum usb_device_speed speed; > + int ret = 0; > + u32 wValue; > + u32 wIndex; > + u16 tmode; > + > + wValue = le16_to_cpu(ctrl->wValue); > + wIndex = le16_to_cpu(ctrl->wIndex); > + state = priv_dev->gadget.state; > + speed = priv_dev->gadget.speed; > + > + switch (ctrl->wValue) { > + case USB_DEVICE_REMOTE_WAKEUP: > + priv_dev->wake_up_flag = !!set; > + break; > + case USB_DEVICE_U1_ENABLE: > + if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u1_allowed = !!set; > + break; > + case USB_DEVICE_U2_ENABLE: > + if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u2_allowed = !!set; > + break; > + case USB_DEVICE_LTM_ENABLE: > + ret = -EINVAL; > + break; > + case USB_DEVICE_TEST_MODE: > + if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) > + return -EINVAL; > + > + tmode = le16_to_cpu(ctrl->wIndex); > + > + if (!set || (tmode & 0xff) != 0) > + return -EINVAL; > + > + switch (tmode >> 8) { > + case TEST_J: > + case TEST_K: > + case TEST_SE0_NAK: > + case TEST_PACKET: > + cdns3_set_register_bit(&priv_dev->regs->usb_cmd, > + USB_CMD_STMODE | > + USB_STS_TMODE_SEL(tmode - 1)); > + break; > + default: > + ret = -EINVAL; > + } > + break; > + default: > + ret = -EINVAL; > + } > + > + return ret; > +} > + > +static int cdns3_ep0_feature_handle_intf(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + u32 wValue; > + int ret = 0; > + > + wValue = le16_to_cpu(ctrl->wValue); > + > + switch (wValue) { > + case USB_INTRF_FUNC_SUSPEND: > + break; > + default: > + ret = -EINVAL; > + } > + > + return ret; > +} > + > +static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + struct cdns3_endpoint *priv_ep; > + int ret = 0; > + u8 index; > + > + if (!(ctrl->wIndex & ~USB_DIR_IN)) > + return 0; Why is this check? > + > + index = cdns3_ep_addr_to_index(ctrl->wIndex); > + priv_ep = priv_dev->eps[index]; > + > + cdns3_select_ep(priv_dev, ctrl->wIndex); > + > + if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) > + return -EINVAL; This check should be done first before you try to decode wIndex. > + > + if (set) { > + writel(EP_CMD_SSTALL, &priv_dev->regs->ep_cmd); > + priv_ep->flags |= EP_STALL; > + } else { > + struct usb_request *request; > + > + if (priv_dev->eps[index]->flags & EP_WEDGE) { > + cdns3_select_ep(priv_dev, 0x00); > + return 0; > + } > + > + writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); > + > + /* wait for EPRST cleared */ > + ret = cdns3_handshake(&priv_dev->regs->ep_cmd, > + EP_CMD_EPRST, 0, 100); > + if (ret) > + return -EINVAL; > + > + priv_ep->flags &= ~EP_STALL; > + > + request = cdns3_next_request(&priv_ep->request_list); > + if (request) > + cdns3_ep_run_transfer(priv_ep, request); > + } > + return ret; > +} > + > +/** > + * cdns3_req_ep0_handle_feature - > + * Handling of GET/SET_FEATURE standard USB request > + * > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * @set: must be set to 1 for SET_FEATURE request > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_handle_feature(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + int ret = 0; > + u32 recip; > + > + recip = ctrl->bRequestType & USB_RECIP_MASK; > + > + switch (recip) { > + case USB_RECIP_DEVICE: > + ret = cdns3_ep0_feature_handle_device(priv_dev, ctrl, set); > + break; > + case USB_RECIP_INTERFACE: > + ret = cdns3_ep0_feature_handle_intf(priv_dev, ctrl, set); > + break; > + case USB_RECIP_ENDPOINT: > + ret = cdns3_ep0_feature_handle_endpoint(priv_dev, ctrl, set); > + break; > + default: > + return -EINVAL; > + } > + > + if (!ret) > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + > + return ret; > +} > + > +/** > + * cdns3_req_ep0_set_sel - Handling of SET_SEL standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + if (priv_dev->gadget.state < USB_STATE_ADDRESS) > + return -EINVAL; > + > + if (ctrl_req->wLength != 6) { > + dev_err(&priv_dev->dev, "Set SEL should be 6 bytes, got %d\n", > + ctrl_req->wLength); > + return -EINVAL; > + } > + > + priv_dev->ep0_data_dir = 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, 6, 1); > + return 0; > +} > + > +/** > + * cdns3_req_ep0_set_isoch_delay - > + * Handling of GET_ISOCH_DELAY standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + if (ctrl_req->wIndex || ctrl_req->wLength) > + return -EINVAL; > + > + priv_dev->isoch_delay = ctrl_req->wValue; > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + return 0; > +} > + > +/** > + * cdns3_ep0_standard_request - Handling standard USB requests > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_ep0_standard_request(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + switch (ctrl_req->bRequest) { > + case USB_REQ_SET_ADDRESS: > + ret = cdns3_req_ep0_set_address(priv_dev, ctrl_req); > + break; > + case USB_REQ_SET_CONFIGURATION: > + ret = cdns3_req_ep0_set_configuration(priv_dev, ctrl_req); > + break; > + case USB_REQ_GET_STATUS: > + ret = cdns3_req_ep0_get_status(priv_dev, ctrl_req); > + break; > + case USB_REQ_CLEAR_FEATURE: > + ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 0); > + break; > + case USB_REQ_SET_FEATURE: > + ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 1); > + break; > + case USB_REQ_SET_SEL: > + ret = cdns3_req_ep0_set_sel(priv_dev, ctrl_req); > + break; > + case USB_REQ_SET_ISOCH_DELAY: > + ret = cdns3_req_ep0_set_isoch_delay(priv_dev, ctrl_req); > + break; > + default: > + ret = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + break; > + } > + > + return ret; > +} > + > static void __pending_setup_status_handler(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + struct usb_request *request = priv_dev->pending_status_request; > + > + if (priv_dev->status_completion_no_call && request && > + request->complete) { > + request->complete(priv_dev->gadget.ep0, request); > + priv_dev->status_completion_no_call = 0; > + } > +} > + > +void cdns3_pending_setup_status_handler(struct work_struct *work) > +{ > + struct cdns3_device *priv_dev = container_of(work, struct cdns3_device, > + pending_status_wq); > + unsigned long flags; > + > + spin_lock_irqsave(&priv_dev->lock, flags); > + __pending_setup_status_handler(priv_dev); > + spin_unlock_irqrestore(&priv_dev->lock, flags); > } > > /** > @@ -101,12 +546,50 @@ static void __pending_setup_status_handler(struct cdns3_device *priv_dev) > */ > static void cdns3_ep0_setup_phase(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function. > + struct usb_ctrlrequest *ctrl = priv_dev->setup; > + int result; > + > + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) > + result = cdns3_ep0_standard_request(priv_dev, ctrl); > + else > + result = cdns3_ep0_delegate_req(priv_dev, ctrl); > + > + if (result != 0 && result != USB_GADGET_DELAYED_STATUS) { > + dev_dbg(&priv_dev->dev, "STALL for ep0\n"); > + /* set_stall on ep0 */ > + cdns3_select_ep(priv_dev, 0x00); > + writel(EP_CMD_SSTALL, &priv_dev->regs->ep_cmd); > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + } > } > > static void cdns3_transfer_completed(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + if (priv_dev->ep0_request) { > + usb_gadget_unmap_request_by_dev(priv_dev->sysdev, > + priv_dev->ep0_request, > + priv_dev->ep0_data_dir); > + > + priv_dev->ep0_request->actual = > + TRB_LEN(le32_to_cpu(priv_dev->trb_ep0->length)); > + > + dev_dbg(&priv_dev->dev, "Ep0 completion length %d\n", > + priv_dev->ep0_request->actual); > + list_del_init(&priv_dev->ep0_request->list); > + } > + > + if (priv_dev->ep0_request && > + priv_dev->ep0_request->complete) { > + spin_unlock(&priv_dev->lock); > + priv_dev->ep0_request->complete(priv_dev->gadget.ep0, > + priv_dev->ep0_request); > + > + priv_dev->ep0_request = NULL; > + spin_lock(&priv_dev->lock); > + } > + > + cdns3_prepare_setup_packet(priv_dev); > + writel(EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > } > > /** > diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c > index 309202474e57..0202ff5f6c90 100644 > --- a/drivers/usb/cdns3/gadget.c > +++ b/drivers/usb/cdns3/gadget.c > @@ -70,6 +70,30 @@ static u8 cdns3_ep_reg_pos_to_index(int i) > return ((i / 16) + (((i % 16) - 2) * 2)); > } > > +/** > + * cdns3_ep_addr_to_index - Macro converts endpoint address to > + * index of endpoint object in cdns3_device.eps[] container > + * @ep_addr: endpoint address for which endpoint object is required > + * > + * Remember that endpoint container doesn't contain default endpoint > + */ > +u8 cdns3_ep_addr_to_index(u8 ep_addr) > +{ > + return (((ep_addr & 0x7F) - 1) + ((ep_addr & USB_DIR_IN) ? 1 : 0)); > +} > + > +/** > + * cdns3_ep_addr_to_bit_pos - Macro converts endpoint address to > + * bit position in ep_ists register > + * @ep_addr: endpoint address for which bit position is required > + * > + * Remember that endpoint container doesn't contain default endpoint > + */ > +static u32 cdns3_ep_addr_to_bit_pos(u8 ep_addr) > +{ > + return (1 << (ep_addr & 0x7F)) << ((ep_addr & 0x80) ? 16 : 0); > +} > + > /** > * cdns3_next_request - returns next request from list > * @list: list containing requests > @@ -464,6 +488,99 @@ static irqreturn_t cdns3_irq_handler_thread(struct cdns3 *cdns) > return ret; > } > > +/** > + * cdns3_ep_onchip_buffer_alloc - Try to allocate onchip buf for EP > + * > + * The real allocation will occur during write to EP_CFG register, > + * this function is used to check if the 'size' allocation is allowed. > + * > + * @priv_dev: extended gadget object > + * @size: the size (KB) for EP would like to allocate > + * @is_in: the direction for EP > + * > + * Return 0 if the later allocation is allowed or negative value on failure > + */ > +static int cdns3_ep_onchip_buffer_alloc(struct cdns3_device *priv_dev, > + int size, int is_in) > +{ > + if (is_in) { > + priv_dev->onchip_mem_allocated_size += size; > + } else if (!priv_dev->out_mem_is_allocated) { > + /* ALL OUT EPs are shared the same chunk onchip memory */ > + priv_dev->onchip_mem_allocated_size += size; > + priv_dev->out_mem_is_allocated = 1; > + } > + > + if (priv_dev->onchip_mem_allocated_size > CDNS3_ONCHIP_BUF_SIZE) { > + priv_dev->onchip_mem_allocated_size -= size; > + return -EPERM; > + } else { > + return 0; > + } > +} > + > +/** > + * cdns3_ep_config Configure hardware endpoint > + * @priv_ep: extended endpoint object > + */ > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep) > +{ > + bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC); > + struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > + u32 bEndpointAddress = priv_ep->num | priv_ep->dir; > + u32 interrupt_mask = EP_STS_EN_TRBERREN; > + u32 max_packet_size = 0; > + u32 ep_cfg = 0; > + int ret; > + > + if (priv_ep->type == USB_ENDPOINT_XFER_INT) { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT); > + } else if (priv_ep->type == USB_ENDPOINT_XFER_BULK) { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK); > + } else { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); > + interrupt_mask = 0xFFFFFFFF; > + } > + > + switch (priv_dev->gadget.speed) { > + case USB_SPEED_FULL: > + max_packet_size = is_iso_ep ? 1023 : 64; > + break; > + case USB_SPEED_HIGH: > + max_packet_size = is_iso_ep ? 1024 : 512; > + break; > + case USB_SPEED_SUPER: > + max_packet_size = 1024; > + break; > + default: > + //all other speed are not supported > + return; > + } > + > + ret = cdns3_ep_onchip_buffer_alloc(priv_dev, CDNS3_EP_BUF_SIZE, > + priv_ep->dir); where do you free the buffer_alloc? > + if (ret) { > + dev_err(&priv_dev->dev, "onchip mem is full, ep is invalid\n"); > + return; > + } > + > + ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) | > + EP_CFG_BUFFERING(CDNS3_EP_BUF_SIZE - 1) | > + EP_CFG_MAXBURST(priv_ep->endpoint.maxburst); > + > + cdns3_select_ep(priv_dev, bEndpointAddress); > + > + writel(ep_cfg, &priv_dev->regs->ep_cfg); > + writel(interrupt_mask, &priv_dev->regs->ep_sts_en); > + > + dev_dbg(&priv_dev->dev, "Configure %s: with val %08x\n", > + priv_ep->name, ep_cfg); > + > + /* enable interrupt for selected endpoint */ > + cdns3_set_register_bit(&priv_dev->regs->ep_ien, > + cdns3_ep_addr_to_bit_pos(bEndpointAddress)); > +} > + > /* Find correct direction for HW endpoint according to description */ > static int cdns3_ep_dir_is_correct(struct usb_endpoint_descriptor *desc, > struct cdns3_endpoint *priv_ep) > @@ -1104,6 +1221,8 @@ static int __cdns3_gadget_init(struct cdns3 *cdns) > priv_dev->is_connected = 0; > > spin_lock_init(&priv_dev->lock); > + INIT_WORK(&priv_dev->pending_status_wq, > + cdns3_pending_setup_status_handler); > > priv_dev->in_standby_mode = 1; > > diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h > index 8c2f363f9340..db8c6cb9f2a5 100644 > --- a/drivers/usb/cdns3/gadget.h > +++ b/drivers/usb/cdns3/gadget.h > @@ -1070,14 +1070,18 @@ struct cdns3_device { > > int cdns3_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); > void cdns3_set_register_bit(void __iomem *ptr, u32 mask); > +void cdns3_pending_setup_status_handler(struct work_struct *work); > int cdns3_init_ep0(struct cdns3_device *priv_dev); > void cdns3_ep0_config(struct cdns3_device *priv_dev); > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep); > void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir); > void cdns3_select_ep(struct cdns3_device *priv_dev, u32 ep); > void cdns3_enable_l1(struct cdns3_device *priv_dev, int enable); > struct usb_request *cdns3_next_request(struct list_head *list); > +void cdns3_gadget_unconfig(struct cdns3_device *priv_dev); > int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, > struct usb_request *request); > +u8 cdns3_ep_addr_to_index(u8 ep_addr); > int cdns3_gadget_ep_set_wedge(struct usb_ep *ep); > int cdns3_gadget_ep_set_halt(struct usb_ep *ep, int value); > struct usb_request *cdns3_gadget_ep_alloc_request(struct usb_ep *ep, > cheers, -roger -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki 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=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED 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 B445FC43441 for ; Wed, 28 Nov 2018 15:50:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5CA952133F for ; Wed, 28 Nov 2018 15:50:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5CA952133F Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=ti.com 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 S1728735AbeK2CwU (ORCPT ); Wed, 28 Nov 2018 21:52:20 -0500 Received: from fllv0016.ext.ti.com ([198.47.19.142]:57794 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727789AbeK2CwU (ORCPT ); Wed, 28 Nov 2018 21:52:20 -0500 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id wASFo8Dn005207; Wed, 28 Nov 2018 09:50:08 -0600 Received: from DFLE106.ent.ti.com (dfle106.ent.ti.com [10.64.6.27]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id wASFo8gw086565 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 28 Nov 2018 09:50:08 -0600 Received: from DFLE101.ent.ti.com (10.64.6.22) by DFLE106.ent.ti.com (10.64.6.27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Wed, 28 Nov 2018 09:50:08 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE101.ent.ti.com (10.64.6.22) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 28 Nov 2018 09:50:08 -0600 Received: from [192.168.2.6] (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id wASFo4Gu007091; Wed, 28 Nov 2018 09:50:05 -0600 Subject: Re: [RFC PATCH v2 12/15] usb:cdns3: Adds enumeration related function. To: Pawel Laszczak , References: <1542535751-16079-1-git-send-email-pawell@cadence.com> <1542535751-16079-13-git-send-email-pawell@cadence.com> CC: , , , , , , , , , , From: Roger Quadros Message-ID: <5BFEB92C.9060903@ti.com> Date: Wed, 28 Nov 2018 17:50:04 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <1542535751-16079-13-git-send-email-pawell@cadence.com> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 18/11/18 12:09, Pawel Laszczak wrote: > Patch implements a set of function related to enumeration process. > Some standard requests are handled on controller driver level and > other are delegated to gadget core driver. > All class requests are delegated to gadget core driver. > > Signed-off-by: Pawel Laszczak > --- > drivers/usb/cdns3/ep0.c | 491 ++++++++++++++++++++++++++++++++++++- > drivers/usb/cdns3/gadget.c | 119 +++++++++ > drivers/usb/cdns3/gadget.h | 4 + > 3 files changed, 610 insertions(+), 4 deletions(-) > > diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c > index eb92fd234bd7..6f33d98f7684 100644 > --- a/drivers/usb/cdns3/ep0.c > +++ b/drivers/usb/cdns3/ep0.c > @@ -10,6 +10,7 @@ > * Peter Chen > */ > > +#include > #include "gadget.h" > > static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = { > @@ -52,9 +53,31 @@ static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, > writel(EP_CMD_ERDY, &priv_dev->regs->ep_cmd); > } > > +/** > + * cdns3_ep0_delegate_req - Returns status of handling setup packet > + * Setup is handled by gadget driver > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns zero on success or negative value on failure > + */ > +static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + spin_unlock(&priv_dev->lock); > + priv_dev->setup_pending = 1; > + ret = priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); > + priv_dev->setup_pending = 0; Why is setup_pending flag being set and cleared? > + spin_lock(&priv_dev->lock); > + return ret; > +} > + > static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + priv_dev->ep0_data_dir = 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, 8, 0); why hardcode to 8? Don't vendor specific requests have different lengths? > } > > static void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) > @@ -90,9 +113,431 @@ static void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) > } > } > > +/** > + * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, 0x7FFF on deferred status stage, error code on error what is this magic number 0x7fff? > + */ > +static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state = priv_dev->gadget.state; > + struct cdns3_endpoint *priv_ep, *temp_ep; > + u32 config = le16_to_cpu(ctrl_req->wValue); > + int result = 0; > + > + switch (device_state) { > + case USB_STATE_ADDRESS: > + /* Configure non-control EPs */ > + list_for_each_entry_safe(priv_ep, temp_ep, > + &priv_dev->ep_match_list, > + ep_match_pending_list) > + cdns3_ep_config(priv_ep); Why configure here? They should be configured at ep_enable. no? And you don't need to maintain a ep_match/pending_list. > + > + result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (result) > + return result; > + > + if (config) { What if result is USB_GADGET_DELAYED_STATUS? > + cdns3_set_hw_configuration(priv_dev); usb_gadget_set_state(USB_STATE_CONFIGURED) ? > + } else { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); > + } > + break; > + case USB_STATE_CONFIGURED: > + result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + > + if (!config && !result) { > + cdns3_gadget_unconfig(priv_dev); > + usb_gadget_set_state(&priv_dev->gadget, > + USB_STATE_ADDRESS); > + } > + break; > + default: > + result = -EINVAL; > + } > + > + return result; > +} > + > +/** > + * cdns3_req_ep0_set_address - Handling of SET_ADDRESS standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_address(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + enum usb_device_state device_state = priv_dev->gadget.state; > + u32 reg; > + u32 addr; > + > + addr = le16_to_cpu(ctrl_req->wValue); > + > + if (addr > DEVICE_ADDRESS_MAX) { If DEVICE_ADDRESS_MAX comes from USB spec it must be in ch9.h. Maybe add something like #define USB_DEVICE_MAX_ADDRESS 127 > + dev_err(&priv_dev->dev, > + "Device address (%d) cannot be greater than %d\n", > + addr, DEVICE_ADDRESS_MAX); > + return -EINVAL; > + } > + > + if (device_state == USB_STATE_CONFIGURED) { > + dev_err(&priv_dev->dev, "USB device already configured\n"); Message is misleading. How about "can't set_address from configured state" > + return -EINVAL; > + } > + > + reg = readl(&priv_dev->regs->usb_cmd); > + > + writel(reg | USB_CMD_FADDR(addr) | USB_CMD_SET_ADDR, > + &priv_dev->regs->usb_cmd); > + > + usb_gadget_set_state(&priv_dev->gadget, > + (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); > + > + cdns3_prepare_setup_packet(priv_dev); why call this here? This should be done after the current ep0 request is complete. > + > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + > + return 0; > +} > + > +/** > + * cdns3_req_ep0_get_status - Handling of GET_STATUS standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl) > +{ > + __le16 *response_pkt; > + u16 usb_status = 0; > + u32 recip; > + u32 reg; > + > + recip = ctrl->bRequestType & USB_RECIP_MASK; > + > + switch (recip) { > + case USB_RECIP_DEVICE: > + /* self powered */ > + usb_status |= priv_dev->gadget.is_selfpowered; if (prv_devgadget.is_selfpowered) usb_stats |= BIT(USB_DEVICE_SELF_POWERED); > + > + if (priv_dev->gadget.speed != USB_SPEED_SUPER) You should check controller speed directly instead. > + break; > + > + reg = readl(&priv_dev->regs->usb_sts); > + > + if (priv_dev->u1_allowed) > + usb_status |= BIT(USB_DEV_STAT_U1_ENABLED); > + > + if (priv_dev->u2_allowed) > + usb_status |= BIT(USB_DEV_STAT_U2_ENABLED); > + > + if (priv_dev->wake_up_flag) > + usb_status |= BIT(USB_DEVICE_REMOTE_WAKEUP); Remote wakeup is not SS specific. So needs to go before the SS check. > + break; > + case USB_RECIP_INTERFACE: > + return cdns3_ep0_delegate_req(priv_dev, ctrl); > + case USB_RECIP_ENDPOINT: > + /* check if endpoint is stalled */ > + cdns3_select_ep(priv_dev, ctrl->wIndex); > + if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts))) > + usb_status = BIT(USB_ENDPOINT_HALT); > + break; > + default: > + return -EINVAL; > + } > + > + response_pkt = (__le16 *)priv_dev->setup; > + *response_pkt = cpu_to_le16(usb_status); > + > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, > + sizeof(*response_pkt), 1); > + return 0; > +} > + > +static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + enum usb_device_state state; > + enum usb_device_speed speed; > + int ret = 0; > + u32 wValue; > + u32 wIndex; > + u16 tmode; > + > + wValue = le16_to_cpu(ctrl->wValue); > + wIndex = le16_to_cpu(ctrl->wIndex); > + state = priv_dev->gadget.state; > + speed = priv_dev->gadget.speed; > + > + switch (ctrl->wValue) { > + case USB_DEVICE_REMOTE_WAKEUP: > + priv_dev->wake_up_flag = !!set; > + break; > + case USB_DEVICE_U1_ENABLE: > + if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u1_allowed = !!set; > + break; > + case USB_DEVICE_U2_ENABLE: > + if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) > + return -EINVAL; > + > + priv_dev->u2_allowed = !!set; > + break; > + case USB_DEVICE_LTM_ENABLE: > + ret = -EINVAL; > + break; > + case USB_DEVICE_TEST_MODE: > + if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) > + return -EINVAL; > + > + tmode = le16_to_cpu(ctrl->wIndex); > + > + if (!set || (tmode & 0xff) != 0) > + return -EINVAL; > + > + switch (tmode >> 8) { > + case TEST_J: > + case TEST_K: > + case TEST_SE0_NAK: > + case TEST_PACKET: > + cdns3_set_register_bit(&priv_dev->regs->usb_cmd, > + USB_CMD_STMODE | > + USB_STS_TMODE_SEL(tmode - 1)); > + break; > + default: > + ret = -EINVAL; > + } > + break; > + default: > + ret = -EINVAL; > + } > + > + return ret; > +} > + > +static int cdns3_ep0_feature_handle_intf(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + u32 wValue; > + int ret = 0; > + > + wValue = le16_to_cpu(ctrl->wValue); > + > + switch (wValue) { > + case USB_INTRF_FUNC_SUSPEND: > + break; > + default: > + ret = -EINVAL; > + } > + > + return ret; > +} > + > +static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + struct cdns3_endpoint *priv_ep; > + int ret = 0; > + u8 index; > + > + if (!(ctrl->wIndex & ~USB_DIR_IN)) > + return 0; Why is this check? > + > + index = cdns3_ep_addr_to_index(ctrl->wIndex); > + priv_ep = priv_dev->eps[index]; > + > + cdns3_select_ep(priv_dev, ctrl->wIndex); > + > + if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) > + return -EINVAL; This check should be done first before you try to decode wIndex. > + > + if (set) { > + writel(EP_CMD_SSTALL, &priv_dev->regs->ep_cmd); > + priv_ep->flags |= EP_STALL; > + } else { > + struct usb_request *request; > + > + if (priv_dev->eps[index]->flags & EP_WEDGE) { > + cdns3_select_ep(priv_dev, 0x00); > + return 0; > + } > + > + writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); > + > + /* wait for EPRST cleared */ > + ret = cdns3_handshake(&priv_dev->regs->ep_cmd, > + EP_CMD_EPRST, 0, 100); > + if (ret) > + return -EINVAL; > + > + priv_ep->flags &= ~EP_STALL; > + > + request = cdns3_next_request(&priv_ep->request_list); > + if (request) > + cdns3_ep_run_transfer(priv_ep, request); > + } > + return ret; > +} > + > +/** > + * cdns3_req_ep0_handle_feature - > + * Handling of GET/SET_FEATURE standard USB request > + * > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * @set: must be set to 1 for SET_FEATURE request > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_handle_feature(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl, > + int set) > +{ > + int ret = 0; > + u32 recip; > + > + recip = ctrl->bRequestType & USB_RECIP_MASK; > + > + switch (recip) { > + case USB_RECIP_DEVICE: > + ret = cdns3_ep0_feature_handle_device(priv_dev, ctrl, set); > + break; > + case USB_RECIP_INTERFACE: > + ret = cdns3_ep0_feature_handle_intf(priv_dev, ctrl, set); > + break; > + case USB_RECIP_ENDPOINT: > + ret = cdns3_ep0_feature_handle_endpoint(priv_dev, ctrl, set); > + break; > + default: > + return -EINVAL; > + } > + > + if (!ret) > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + > + return ret; > +} > + > +/** > + * cdns3_req_ep0_set_sel - Handling of SET_SEL standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + if (priv_dev->gadget.state < USB_STATE_ADDRESS) > + return -EINVAL; > + > + if (ctrl_req->wLength != 6) { > + dev_err(&priv_dev->dev, "Set SEL should be 6 bytes, got %d\n", > + ctrl_req->wLength); > + return -EINVAL; > + } > + > + priv_dev->ep0_data_dir = 0; > + cdns3_ep0_run_transfer(priv_dev, priv_dev->setup_dma, 6, 1); > + return 0; > +} > + > +/** > + * cdns3_req_ep0_set_isoch_delay - > + * Handling of GET_ISOCH_DELAY standard USB request > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + if (ctrl_req->wIndex || ctrl_req->wLength) > + return -EINVAL; > + > + priv_dev->isoch_delay = ctrl_req->wValue; > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + return 0; > +} > + > +/** > + * cdns3_ep0_standard_request - Handling standard USB requests > + * @priv_dev: extended gadget object > + * @ctrl_req: pointer to received setup packet > + * > + * Returns 0 if success, error code on error > + */ > +static int cdns3_ep0_standard_request(struct cdns3_device *priv_dev, > + struct usb_ctrlrequest *ctrl_req) > +{ > + int ret; > + > + switch (ctrl_req->bRequest) { > + case USB_REQ_SET_ADDRESS: > + ret = cdns3_req_ep0_set_address(priv_dev, ctrl_req); > + break; > + case USB_REQ_SET_CONFIGURATION: > + ret = cdns3_req_ep0_set_configuration(priv_dev, ctrl_req); > + break; > + case USB_REQ_GET_STATUS: > + ret = cdns3_req_ep0_get_status(priv_dev, ctrl_req); > + break; > + case USB_REQ_CLEAR_FEATURE: > + ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 0); > + break; > + case USB_REQ_SET_FEATURE: > + ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl_req, 1); > + break; > + case USB_REQ_SET_SEL: > + ret = cdns3_req_ep0_set_sel(priv_dev, ctrl_req); > + break; > + case USB_REQ_SET_ISOCH_DELAY: > + ret = cdns3_req_ep0_set_isoch_delay(priv_dev, ctrl_req); > + break; > + default: > + ret = cdns3_ep0_delegate_req(priv_dev, ctrl_req); > + break; > + } > + > + return ret; > +} > + > static void __pending_setup_status_handler(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + struct usb_request *request = priv_dev->pending_status_request; > + > + if (priv_dev->status_completion_no_call && request && > + request->complete) { > + request->complete(priv_dev->gadget.ep0, request); > + priv_dev->status_completion_no_call = 0; > + } > +} > + > +void cdns3_pending_setup_status_handler(struct work_struct *work) > +{ > + struct cdns3_device *priv_dev = container_of(work, struct cdns3_device, > + pending_status_wq); > + unsigned long flags; > + > + spin_lock_irqsave(&priv_dev->lock, flags); > + __pending_setup_status_handler(priv_dev); > + spin_unlock_irqrestore(&priv_dev->lock, flags); > } > > /** > @@ -101,12 +546,50 @@ static void __pending_setup_status_handler(struct cdns3_device *priv_dev) > */ > static void cdns3_ep0_setup_phase(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function. > + struct usb_ctrlrequest *ctrl = priv_dev->setup; > + int result; > + > + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) > + result = cdns3_ep0_standard_request(priv_dev, ctrl); > + else > + result = cdns3_ep0_delegate_req(priv_dev, ctrl); > + > + if (result != 0 && result != USB_GADGET_DELAYED_STATUS) { > + dev_dbg(&priv_dev->dev, "STALL for ep0\n"); > + /* set_stall on ep0 */ > + cdns3_select_ep(priv_dev, 0x00); > + writel(EP_CMD_SSTALL, &priv_dev->regs->ep_cmd); > + writel(EP_CMD_ERDY | EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > + } > } > > static void cdns3_transfer_completed(struct cdns3_device *priv_dev) > { > - //TODO: Implements this function > + if (priv_dev->ep0_request) { > + usb_gadget_unmap_request_by_dev(priv_dev->sysdev, > + priv_dev->ep0_request, > + priv_dev->ep0_data_dir); > + > + priv_dev->ep0_request->actual = > + TRB_LEN(le32_to_cpu(priv_dev->trb_ep0->length)); > + > + dev_dbg(&priv_dev->dev, "Ep0 completion length %d\n", > + priv_dev->ep0_request->actual); > + list_del_init(&priv_dev->ep0_request->list); > + } > + > + if (priv_dev->ep0_request && > + priv_dev->ep0_request->complete) { > + spin_unlock(&priv_dev->lock); > + priv_dev->ep0_request->complete(priv_dev->gadget.ep0, > + priv_dev->ep0_request); > + > + priv_dev->ep0_request = NULL; > + spin_lock(&priv_dev->lock); > + } > + > + cdns3_prepare_setup_packet(priv_dev); > + writel(EP_CMD_REQ_CMPL, &priv_dev->regs->ep_cmd); > } > > /** > diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c > index 309202474e57..0202ff5f6c90 100644 > --- a/drivers/usb/cdns3/gadget.c > +++ b/drivers/usb/cdns3/gadget.c > @@ -70,6 +70,30 @@ static u8 cdns3_ep_reg_pos_to_index(int i) > return ((i / 16) + (((i % 16) - 2) * 2)); > } > > +/** > + * cdns3_ep_addr_to_index - Macro converts endpoint address to > + * index of endpoint object in cdns3_device.eps[] container > + * @ep_addr: endpoint address for which endpoint object is required > + * > + * Remember that endpoint container doesn't contain default endpoint > + */ > +u8 cdns3_ep_addr_to_index(u8 ep_addr) > +{ > + return (((ep_addr & 0x7F) - 1) + ((ep_addr & USB_DIR_IN) ? 1 : 0)); > +} > + > +/** > + * cdns3_ep_addr_to_bit_pos - Macro converts endpoint address to > + * bit position in ep_ists register > + * @ep_addr: endpoint address for which bit position is required > + * > + * Remember that endpoint container doesn't contain default endpoint > + */ > +static u32 cdns3_ep_addr_to_bit_pos(u8 ep_addr) > +{ > + return (1 << (ep_addr & 0x7F)) << ((ep_addr & 0x80) ? 16 : 0); > +} > + > /** > * cdns3_next_request - returns next request from list > * @list: list containing requests > @@ -464,6 +488,99 @@ static irqreturn_t cdns3_irq_handler_thread(struct cdns3 *cdns) > return ret; > } > > +/** > + * cdns3_ep_onchip_buffer_alloc - Try to allocate onchip buf for EP > + * > + * The real allocation will occur during write to EP_CFG register, > + * this function is used to check if the 'size' allocation is allowed. > + * > + * @priv_dev: extended gadget object > + * @size: the size (KB) for EP would like to allocate > + * @is_in: the direction for EP > + * > + * Return 0 if the later allocation is allowed or negative value on failure > + */ > +static int cdns3_ep_onchip_buffer_alloc(struct cdns3_device *priv_dev, > + int size, int is_in) > +{ > + if (is_in) { > + priv_dev->onchip_mem_allocated_size += size; > + } else if (!priv_dev->out_mem_is_allocated) { > + /* ALL OUT EPs are shared the same chunk onchip memory */ > + priv_dev->onchip_mem_allocated_size += size; > + priv_dev->out_mem_is_allocated = 1; > + } > + > + if (priv_dev->onchip_mem_allocated_size > CDNS3_ONCHIP_BUF_SIZE) { > + priv_dev->onchip_mem_allocated_size -= size; > + return -EPERM; > + } else { > + return 0; > + } > +} > + > +/** > + * cdns3_ep_config Configure hardware endpoint > + * @priv_ep: extended endpoint object > + */ > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep) > +{ > + bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC); > + struct cdns3_device *priv_dev = priv_ep->cdns3_dev; > + u32 bEndpointAddress = priv_ep->num | priv_ep->dir; > + u32 interrupt_mask = EP_STS_EN_TRBERREN; > + u32 max_packet_size = 0; > + u32 ep_cfg = 0; > + int ret; > + > + if (priv_ep->type == USB_ENDPOINT_XFER_INT) { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT); > + } else if (priv_ep->type == USB_ENDPOINT_XFER_BULK) { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK); > + } else { > + ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); > + interrupt_mask = 0xFFFFFFFF; > + } > + > + switch (priv_dev->gadget.speed) { > + case USB_SPEED_FULL: > + max_packet_size = is_iso_ep ? 1023 : 64; > + break; > + case USB_SPEED_HIGH: > + max_packet_size = is_iso_ep ? 1024 : 512; > + break; > + case USB_SPEED_SUPER: > + max_packet_size = 1024; > + break; > + default: > + //all other speed are not supported > + return; > + } > + > + ret = cdns3_ep_onchip_buffer_alloc(priv_dev, CDNS3_EP_BUF_SIZE, > + priv_ep->dir); where do you free the buffer_alloc? > + if (ret) { > + dev_err(&priv_dev->dev, "onchip mem is full, ep is invalid\n"); > + return; > + } > + > + ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) | > + EP_CFG_BUFFERING(CDNS3_EP_BUF_SIZE - 1) | > + EP_CFG_MAXBURST(priv_ep->endpoint.maxburst); > + > + cdns3_select_ep(priv_dev, bEndpointAddress); > + > + writel(ep_cfg, &priv_dev->regs->ep_cfg); > + writel(interrupt_mask, &priv_dev->regs->ep_sts_en); > + > + dev_dbg(&priv_dev->dev, "Configure %s: with val %08x\n", > + priv_ep->name, ep_cfg); > + > + /* enable interrupt for selected endpoint */ > + cdns3_set_register_bit(&priv_dev->regs->ep_ien, > + cdns3_ep_addr_to_bit_pos(bEndpointAddress)); > +} > + > /* Find correct direction for HW endpoint according to description */ > static int cdns3_ep_dir_is_correct(struct usb_endpoint_descriptor *desc, > struct cdns3_endpoint *priv_ep) > @@ -1104,6 +1221,8 @@ static int __cdns3_gadget_init(struct cdns3 *cdns) > priv_dev->is_connected = 0; > > spin_lock_init(&priv_dev->lock); > + INIT_WORK(&priv_dev->pending_status_wq, > + cdns3_pending_setup_status_handler); > > priv_dev->in_standby_mode = 1; > > diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h > index 8c2f363f9340..db8c6cb9f2a5 100644 > --- a/drivers/usb/cdns3/gadget.h > +++ b/drivers/usb/cdns3/gadget.h > @@ -1070,14 +1070,18 @@ struct cdns3_device { > > int cdns3_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); > void cdns3_set_register_bit(void __iomem *ptr, u32 mask); > +void cdns3_pending_setup_status_handler(struct work_struct *work); > int cdns3_init_ep0(struct cdns3_device *priv_dev); > void cdns3_ep0_config(struct cdns3_device *priv_dev); > +void cdns3_ep_config(struct cdns3_endpoint *priv_ep); > void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir); > void cdns3_select_ep(struct cdns3_device *priv_dev, u32 ep); > void cdns3_enable_l1(struct cdns3_device *priv_dev, int enable); > struct usb_request *cdns3_next_request(struct list_head *list); > +void cdns3_gadget_unconfig(struct cdns3_device *priv_dev); > int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, > struct usb_request *request); > +u8 cdns3_ep_addr_to_index(u8 ep_addr); > int cdns3_gadget_ep_set_wedge(struct usb_ep *ep); > int cdns3_gadget_ep_set_halt(struct usb_ep *ep, int value); > struct usb_request *cdns3_gadget_ep_alloc_request(struct usb_ep *ep, > cheers, -roger -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki