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,4/7] usb: typec: ucsi: Preliminary support for alternate modes From: Heikki Krogerus Message-Id: <20190415120931.61328-5-heikki.krogerus@linux.intel.com> Date: Mon, 15 Apr 2019 15:09:28 +0300 To: Greg Kroah-Hartman Cc: Ajay Gupta , linux-usb@vger.kernel.org List-ID: V2l0aCBVQ1NJIHRoZSBhbHRlcm5hdGUgbW9kZXMsIGp1c3QgbGlrZSBldmVyeXRoaW5nIGVsc2UK cmVsYXRlZCB0byBVU0IgVHlwZS1DIGNvbm5lY3RvcnMsIGFyZSBoYW5kbGVkIGluIGZpcm13YXJl LgpUaGUgb3BlcmF0aW5nIHN5c3RlbSBjYW4gc2VlIHRoZSBzdGF0dXMgYW5kIGlzIGFsbG93ZWQg dG8KcmVxdWVzdCBjZXJ0YWluIHRoaW5ncywgZm9yIGV4YW1wbGUgZW50ZXJpbmcgYW5kIGV4aXRp bmcgdGhlCm1vZGVzLCBidXQgdGhlIHN1cHBvcnQgZm9yIGFsdGVybmF0ZSBtb2RlcyBpcyB2ZXJ5 IGxpbWl0ZWQKaW4gVUNTSS4gVGhlIGZlYXR1cmUgaXMgYWxzbyBvcHRpb25hbCwgd2hpY2ggbWVh bnMgdGhhdCBldmVuCndoZW4gdGhlIHBsYXRmb3JtIHN1cHBvcnRzIGFsdGVybmF0ZSBtb2Rlcywg dGhlIG9wZXJhdGluZwpzeXN0ZW0gbWF5IG5vdCBiZSBldmVuIG1hZGUgYXdhcmUgb2YgdGhlbS4K ClVDU0kgZG9lcyBub3Qgc3VwcG9ydCBkaXJlY3QgVkRNIHJlYWRpbmcgb3Igd3JpdGluZy4KSW5z dGVhZCwgYWx0ZXJuYXRlIG1vZGVzIGNhbiBiZSBlbnRlcmVkIGFuZCBleGl0ZWQgdXNpbmcgYQpz aW5nbGUgY3VzdG9tIGNvbW1hbmQgd2hpY2ggdGFrZXMgYWxzbyBhbiBvcHRpb25hbCBTVklECnNw ZWNpZmljIGNvbmZpZ3VyYXRpb24gdmFsdWUgYXMgcGFyYW1ldGVyLiBUaGF0IG1lYW5zIGV2ZXJ5 CnN1cHBvcnRlZCBhbHRlcm5hdGUgbW9kZSBoYXMgdG8gYmUgaGFuZGxlZCBzZXBhcmF0ZWx5IGlu ClVDU0kgZHJpdmVyLgoKVGhpcyBjb21taXQgZG9lcyBub3QgaW5jbHVkZSBzdXBwb3J0IGZvciBh bnkgc3BlY2lmaWMKYWx0ZXJuYXRlIG1vZGUuIFRoZSBkaXNjb3ZlcmVkIGFsdGVybmF0ZSBtb2Rl cyBhcmUgbm93CnJlZ2lzdGVyZWQsIGJ1dCBiaW5kaW5nIGEgZHJpdmVyIHRvIGFuIGFsdGVybmF0 ZSBtb2RlIHdpbGwKbm90IGJlIHBvc3NpYmxlIHVudGlsIHN1cHBvcnQgZm9yIHRoYXQgYWx0ZXJu YXRlIG1vZGUgaXMKYWRkZWQgdG8gdGhlIFVDU0kgZHJpdmVyLgoKVGVzdGVkLWJ5OiBBamF5IEd1 cHRhIDxhamF5Z0BudmlkaWEuY29tPgpTaWduZWQtb2ZmLWJ5OiBIZWlra2kgS3JvZ2VydXMgPGhl aWtraS5rcm9nZXJ1c0BsaW51eC5pbnRlbC5jb20+Ci0tLQogZHJpdmVycy91c2IvdHlwZWMvdWNz aS90cmFjZS5jIHwgIDEyICsrCiBkcml2ZXJzL3VzYi90eXBlYy91Y3NpL3RyYWNlLmggfCAgMjYg KysrCiBkcml2ZXJzL3VzYi90eXBlYy91Y3NpL3Vjc2kuYyAgfCAzNTggKysrKysrKysrKysrKysr KysrKysrKysrKysrLS0tLS0tCiBkcml2ZXJzL3VzYi90eXBlYy91Y3NpL3Vjc2kuaCAgfCAgNzIg KysrKysrKwogNCBmaWxlcyBjaGFuZ2VkLCA0MDMgaW5zZXJ0aW9ucygrKSwgNjUgZGVsZXRpb25z KC0pCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvdHlwZWMvdWNzaS90cmFjZS5jIGIvZHJpdmVy cy91c2IvdHlwZWMvdWNzaS90cmFjZS5jCmluZGV4IGZmYTNiNGMzZjMzOC4uMWRhYmFmYjc0MzIw IDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi90eXBlYy91Y3NpL3RyYWNlLmMKKysrIGIvZHJpdmVy cy91c2IvdHlwZWMvdWNzaS90cmFjZS5jCkBAIC02MCwzICs2MCwxNSBAQCBjb25zdCBjaGFyICp1 Y3NpX2NjaV9zdHIodTMyIGNjaSkKIAogCXJldHVybiAiIjsKIH0KKworc3RhdGljIGNvbnN0IGNo YXIgKiBjb25zdCB1Y3NpX3JlY2lwaWVudF9zdHJzW10gPSB7CisJW1VDU0lfUkVDSVBJRU5UX0NP Tl0JCT0gInBvcnQiLAorCVtVQ1NJX1JFQ0lQSUVOVF9TT1BdCQk9ICJwYXJ0bmVyIiwKKwlbVUNT SV9SRUNJUElFTlRfU09QX1BdCQk9ICJwbHVnIChwcmltZSkiLAorCVtVQ1NJX1JFQ0lQSUVOVF9T T1BfUFBdCQk9ICJwbHVnIChkb3VibGUgcHJpbWUpIiwKK307CisKK2NvbnN0IGNoYXIgKnVjc2lf cmVjaXBpZW50X3N0cih1OCByZWNpcGllbnQpCit7CisJcmV0dXJuIHVjc2lfcmVjaXBpZW50X3N0 cnNbcmVjaXBpZW50XTsKK30KZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdHJh Y2UuaCBiL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdHJhY2UuaAppbmRleCA1ZTI5MDZkZjJkYjcu Ljc4M2VjOWM3MjA1NSAxMDA2NDQKLS0tIGEvZHJpdmVycy91c2IvdHlwZWMvdWNzaS90cmFjZS5o CisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdHJhY2UuaApAQCAtNyw2ICs3LDcgQEAKICNk ZWZpbmUgX19VQ1NJX1RSQUNFX0gKIAogI2luY2x1ZGUgPGxpbnV4L3RyYWNlcG9pbnQuaD4KKyNp bmNsdWRlIDxsaW51eC91c2IvdHlwZWNfYWx0bW9kZS5oPgogCiBjb25zdCBjaGFyICp1Y3NpX2Nt ZF9zdHIodTY0IHJhd19jbWQpOwogY29uc3QgY2hhciAqdWNzaV9hY2tfc3RyKHU4IGFjayk7CkBA IC0xMzQsNiArMTM1LDMxIEBAIERFRklORV9FVkVOVCh1Y3NpX2xvZ19jb25uZWN0b3Jfc3RhdHVz LCB1Y3NpX3JlZ2lzdGVyX3BvcnQsCiAJVFBfQVJHUyhwb3J0LCBzdGF0dXMpCiApOwogCitERUNM QVJFX0VWRU5UX0NMQVNTKHVjc2lfbG9nX3JlZ2lzdGVyX2FsdG1vZGUsCisJVFBfUFJPVE8odTgg cmVjaXBpZW50LCBzdHJ1Y3QgdHlwZWNfYWx0bW9kZSAqYWx0KSwKKwlUUF9BUkdTKHJlY2lwaWVu dCwgYWx0KSwKKwlUUF9TVFJVQ1RfX2VudHJ5KAorCQlfX2ZpZWxkKHU4LCByZWNpcGllbnQpCisJ CV9fZmllbGQodTE2LCBzdmlkKQorCQlfX2ZpZWxkKHU4LCBtb2RlKQorCQlfX2ZpZWxkKHUzMiwg dmRvKQorCSksCisJVFBfZmFzdF9hc3NpZ24oCisJCV9fZW50cnktPnJlY2lwaWVudCA9IHJlY2lw aWVudDsKKwkJX19lbnRyeS0+c3ZpZCA9IGFsdC0+c3ZpZDsKKwkJX19lbnRyeS0+bW9kZSA9IGFs dC0+bW9kZTsKKwkJX19lbnRyeS0+dmRvID0gYWx0LT52ZG87CisJKSwKKwlUUF9wcmludGsoIiVz IGFsdCBtb2RlOiBzdmlkICUwNHgsIG1vZGUgJWQgdmRvICV4IiwKKwkJICB1Y3NpX3JlY2lwaWVu dF9zdHIoX19lbnRyeS0+cmVjaXBpZW50KSwgX19lbnRyeS0+c3ZpZCwKKwkJICBfX2VudHJ5LT5t b2RlLCBfX2VudHJ5LT52ZG8pCispOworCitERUZJTkVfRVZFTlQodWNzaV9sb2dfcmVnaXN0ZXJf YWx0bW9kZSwgdWNzaV9yZWdpc3Rlcl9hbHRtb2RlLAorCVRQX1BST1RPKHU4IHJlY2lwaWVudCwg c3RydWN0IHR5cGVjX2FsdG1vZGUgKmFsdCksCisJVFBfQVJHUyhyZWNpcGllbnQsIGFsdCkKKyk7 CisKICNlbmRpZiAvKiBfX1VDU0lfVFJBQ0VfSCAqLwogCiAvKiBUaGlzIHBhcnQgbXVzdCBiZSBv dXRzaWRlIHByb3RlY3Rpb24gKi8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kv dWNzaS5jIGIvZHJpdmVycy91c2IvdHlwZWMvdWNzaS91Y3NpLmMKaW5kZXggOGQwYTZmZTc0OGJk Li41ODVhYjA0YmU5NDAgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdWNzaS5j CisrKyBiL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdWNzaS5jCkBAIC0xMiw3ICsxMiw3IEBACiAj aW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CiAjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KICNpbmNs dWRlIDxsaW51eC9zbGFiLmg+Ci0jaW5jbHVkZSA8bGludXgvdXNiL3R5cGVjLmg+CisjaW5jbHVk ZSA8bGludXgvdXNiL3R5cGVjX2FsdG1vZGUuaD4KIAogI2luY2x1ZGUgInVjc2kuaCIKICNpbmNs dWRlICJ0cmFjZS5oIgpAQCAtNDUsMjIgKzQ1LDYgQEAgZW51bSB1Y3NpX3N0YXR1cyB7CiAJVUNT SV9FUlJPUiwKIH07CiAKLXN0cnVjdCB1Y3NpX2Nvbm5lY3RvciB7Ci0JaW50IG51bTsKLQotCXN0 cnVjdCB1Y3NpICp1Y3NpOwotCXN0cnVjdCB3b3JrX3N0cnVjdCB3b3JrOwotCXN0cnVjdCBjb21w bGV0aW9uIGNvbXBsZXRlOwotCi0Jc3RydWN0IHR5cGVjX3BvcnQgKnBvcnQ7Ci0Jc3RydWN0IHR5 cGVjX3BhcnRuZXIgKnBhcnRuZXI7Ci0KLQlzdHJ1Y3QgdHlwZWNfY2FwYWJpbGl0eSB0eXBlY19j YXA7Ci0KLQlzdHJ1Y3QgdWNzaV9jb25uZWN0b3Jfc3RhdHVzIHN0YXR1czsKLQlzdHJ1Y3QgdWNz aV9jb25uZWN0b3JfY2FwYWJpbGl0eSBjYXA7Ci19OwotCiBzdHJ1Y3QgdWNzaSB7CiAJc3RydWN0 IGRldmljZSAqZGV2OwogCXN0cnVjdCB1Y3NpX3BwbSAqcHBtOwpAQCAtMjM4LDggKzIyMiwyMDQg QEAgc3RhdGljIGludCB1Y3NpX3J1bl9jb21tYW5kKHN0cnVjdCB1Y3NpICp1Y3NpLCBzdHJ1Y3Qg dWNzaV9jb250cm9sICpjdHJsLAogCXJldHVybiByZXQ7CiB9CiAKK2ludCB1Y3NpX3NlbmRfY29t bWFuZChzdHJ1Y3QgdWNzaSAqdWNzaSwgc3RydWN0IHVjc2lfY29udHJvbCAqY3RybCwKKwkJICAg ICAgdm9pZCAqcmV0dmFsLCBzaXplX3Qgc2l6ZSkKK3sKKwlpbnQgcmV0OworCisJbXV0ZXhfbG9j aygmdWNzaS0+cHBtX2xvY2spOworCXJldCA9IHVjc2lfcnVuX2NvbW1hbmQodWNzaSwgY3RybCwg cmV0dmFsLCBzaXplKTsKKwltdXRleF91bmxvY2soJnVjc2ktPnBwbV9sb2NrKTsKKworCXJldHVy biByZXQ7Cit9CisKIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCiAKK3ZvaWQgdWNzaV9hbHRtb2Rl X3VwZGF0ZV9hY3RpdmUoc3RydWN0IHVjc2lfY29ubmVjdG9yICpjb24pCit7CisJY29uc3Qgc3Ry dWN0IHR5cGVjX2FsdG1vZGUgKmFsdG1vZGUgPSBOVUxMOworCXN0cnVjdCB1Y3NpX2NvbnRyb2wg Y3RybDsKKwlpbnQgcmV0OworCXU4IGN1cjsKKwlpbnQgaTsKKworCVVDU0lfQ01EX0dFVF9DVVJS RU5UX0NBTShjdHJsLCBjb24tPm51bSk7CisJcmV0ID0gdWNzaV9ydW5fY29tbWFuZChjb24tPnVj c2ksICZjdHJsLCAmY3VyLCBzaXplb2YoY3VyKSk7CisJaWYgKHJldCA8IDApIHsKKwkJaWYgKGNv bi0+dWNzaS0+cHBtLT5kYXRhLT52ZXJzaW9uID4gMHgwMTAwKSB7CisJCQlkZXZfZXJyKGNvbi0+ dWNzaS0+ZGV2LAorCQkJCSJHRVRfQ1VSUkVOVF9DQU0gY29tbWFuZCBmYWlsZWRcbiIpOworCQkJ cmV0dXJuOworCQl9CisJCWN1ciA9IDB4ZmY7CisJfQorCisJaWYgKGN1ciA8IFVDU0lfTUFYX0FM VE1PREVTKQorCQlhbHRtb2RlID0gdHlwZWNfYWx0bW9kZV9nZXRfcGFydG5lcihjb24tPnBvcnRf YWx0bW9kZVtjdXJdKTsKKworCWZvciAoaSA9IDA7IGNvbi0+cGFydG5lcl9hbHRtb2RlW2ldOyBp KyspCisJCXR5cGVjX2FsdG1vZGVfdXBkYXRlX2FjdGl2ZShjb24tPnBhcnRuZXJfYWx0bW9kZVtp XSwKKwkJCQkJICAgIGNvbi0+cGFydG5lcl9hbHRtb2RlW2ldID09IGFsdG1vZGUpOworfQorCitz dGF0aWMgdTggdWNzaV9hbHRtb2RlX25leHRfbW9kZShzdHJ1Y3QgdHlwZWNfYWx0bW9kZSAqKmFs dCwgdTE2IHN2aWQpCit7CisJdTggbW9kZSA9IDE7CisJaW50IGk7CisKKwlmb3IgKGkgPSAwOyBh bHRbaV07IGkrKykKKwkJaWYgKGFsdFtpXS0+c3ZpZCA9PSBzdmlkKQorCQkJbW9kZSsrOworCisJ cmV0dXJuIG1vZGU7Cit9CisKK3N0YXRpYyBpbnQgdWNzaV9uZXh0X2FsdG1vZGUoc3RydWN0IHR5 cGVjX2FsdG1vZGUgKiphbHQpCit7CisJaW50IGkgPSAwOworCisJZm9yIChpID0gMDsgaSA8IFVD U0lfTUFYX0FMVE1PREVTOyBpKyspCisJCWlmICghYWx0W2ldKQorCQkJcmV0dXJuIGk7CisKKwly ZXR1cm4gLUVOT0VOVDsKK30KKworc3RhdGljIGludCB1Y3NpX3JlZ2lzdGVyX2FsdG1vZGUoc3Ry dWN0IHVjc2lfY29ubmVjdG9yICpjb24sCisJCQkJIHN0cnVjdCB0eXBlY19hbHRtb2RlX2Rlc2Mg KmRlc2MsCisJCQkJIHU4IHJlY2lwaWVudCkKK3sKKwlzdHJ1Y3QgdHlwZWNfYWx0bW9kZSAqYWx0 OworCWludCByZXQ7CisJaW50IGk7CisKKwlzd2l0Y2ggKHJlY2lwaWVudCkgeworCWNhc2UgVUNT SV9SRUNJUElFTlRfQ09OOgorCQlpID0gdWNzaV9uZXh0X2FsdG1vZGUoY29uLT5wb3J0X2FsdG1v ZGUpOworCQlpZiAoaSA8IDApIHsKKwkJCXJldCA9IGk7CisJCQlnb3RvIGVycjsKKwkJfQorCisJ CWRlc2MtPm1vZGUgPSB1Y3NpX2FsdG1vZGVfbmV4dF9tb2RlKGNvbi0+cG9ydF9hbHRtb2RlLAor CQkJCQkJICAgIGRlc2MtPnN2aWQpOworCisJCWFsdCA9IHR5cGVjX3BvcnRfcmVnaXN0ZXJfYWx0 bW9kZShjb24tPnBvcnQsIGRlc2MpOworCQlpZiAoSVNfRVJSKGFsdCkpIHsKKwkJCXJldCA9IFBU Ul9FUlIoYWx0KTsKKwkJCWdvdG8gZXJyOworCQl9CisKKwkJY29uLT5wb3J0X2FsdG1vZGVbaV0g PSBhbHQ7CisJCWJyZWFrOworCWNhc2UgVUNTSV9SRUNJUElFTlRfU09QOgorCQlpID0gdWNzaV9u ZXh0X2FsdG1vZGUoY29uLT5wYXJ0bmVyX2FsdG1vZGUpOworCQlpZiAoaSA8IDApIHsKKwkJCXJl dCA9IGk7CisJCQlnb3RvIGVycjsKKwkJfQorCisJCWRlc2MtPm1vZGUgPSB1Y3NpX2FsdG1vZGVf bmV4dF9tb2RlKGNvbi0+cGFydG5lcl9hbHRtb2RlLAorCQkJCQkJICAgIGRlc2MtPnN2aWQpOwor CisJCWFsdCA9IHR5cGVjX3BhcnRuZXJfcmVnaXN0ZXJfYWx0bW9kZShjb24tPnBhcnRuZXIsIGRl c2MpOworCQlpZiAoSVNfRVJSKGFsdCkpIHsKKwkJCXJldCA9IFBUUl9FUlIoYWx0KTsKKwkJCWdv dG8gZXJyOworCQl9CisKKwkJY29uLT5wYXJ0bmVyX2FsdG1vZGVbaV0gPSBhbHQ7CisJCWJyZWFr OworCWRlZmF1bHQ6CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCXRyYWNlX3Vjc2lfcmVnaXN0 ZXJfYWx0bW9kZShyZWNpcGllbnQsIGFsdCk7CisKKwlyZXR1cm4gMDsKKworZXJyOgorCWRldl9l cnIoY29uLT51Y3NpLT5kZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXJzIHN2aWQgMHglMDR4IG1vZGUg JWRcbiIsCisJCWRlc2MtPnN2aWQsIGRlc2MtPm1vZGUpOworCisJcmV0dXJuIHJldDsKK30KKwor c3RhdGljIGludCB1Y3NpX3JlZ2lzdGVyX2FsdG1vZGVzKHN0cnVjdCB1Y3NpX2Nvbm5lY3RvciAq Y29uLCB1OCByZWNpcGllbnQpCit7CisJaW50IG1heF9hbHRtb2RlcyA9IFVDU0lfTUFYX0FMVE1P REVTOworCXN0cnVjdCB0eXBlY19hbHRtb2RlX2Rlc2MgZGVzYzsKKwlzdHJ1Y3QgdWNzaV9hbHRt b2RlIGFsdFsyXTsKKwlzdHJ1Y3QgdWNzaV9jb250cm9sIGN0cmw7CisJaW50IG51bSA9IDE7CisJ aW50IHJldDsKKwlpbnQgbGVuOworCWludCBqOworCWludCBpOworCisJaWYgKCEoY29uLT51Y3Np LT5jYXAuZmVhdHVyZXMgJiBVQ1NJX0NBUF9BTFRfTU9ERV9ERVRBSUxTKSkKKwkJcmV0dXJuIDA7 CisKKwlpZiAocmVjaXBpZW50ID09IFVDU0lfUkVDSVBJRU5UX0NPTikKKwkJbWF4X2FsdG1vZGVz ID0gY29uLT51Y3NpLT5jYXAubnVtX2FsdF9tb2RlczsKKworCWZvciAoaSA9IDA7IGkgPCBtYXhf YWx0bW9kZXM7KSB7CisJCW1lbXNldChhbHQsIDAsIHNpemVvZihhbHQpKTsKKwkJVUNTSV9DTURf R0VUX0FMVEVSTkFURV9NT0RFUyhjdHJsLCByZWNpcGllbnQsIGNvbi0+bnVtLCBpLCAxKTsKKwkJ bGVuID0gdWNzaV9ydW5fY29tbWFuZChjb24tPnVjc2ksICZjdHJsLCBhbHQsIHNpemVvZihhbHQp KTsKKwkJaWYgKGxlbiA8PSAwKQorCQkJcmV0dXJuIGxlbjsKKworCQkvKgorCQkgKiBUaGlzIGNv ZGUgaXMgcmVxdWVzdGluZyBvbmUgYWx0IG1vZGUgYXQgYSB0aW1lLCBidXQgc29tZSBQUE1zCisJ CSAqIG1heSBzdGlsbCByZXR1cm4gdHdvLiBJZiB0aGF0IGhhcHBlbnMgYm90aCBhbHQgbW9kZXMg bmVlZCBiZQorCQkgKiByZWdpc3RlcmVkIGFuZCB0aGUgb2Zmc2V0IGZvciB0aGUgbmV4dCBhbHQg bW9kZSBoYXMgdG8gYmUKKwkJICogaW5jcmVtZW50ZWQuCisJCSAqLworCQludW0gPSBsZW4gLyBz aXplb2YoYWx0WzBdKTsKKwkJaSArPSBudW07CisKKwkJZm9yIChqID0gMDsgaiA8IG51bTsgaisr KSB7CisJCQlpZiAoIWFsdFtqXS5zdmlkKQorCQkJCXJldHVybiAwOworCisJCQltZW1zZXQoJmRl c2MsIDAsIHNpemVvZihkZXNjKSk7CisJCQlkZXNjLnZkbyA9IGFsdFtqXS5taWQ7CisJCQlkZXNj LnN2aWQgPSBhbHRbal0uc3ZpZDsKKwkJCWRlc2Mucm9sZXMgPSBUWVBFQ19QT1JUX0RSRDsKKwor CQkJcmV0ID0gdWNzaV9yZWdpc3Rlcl9hbHRtb2RlKGNvbiwgJmRlc2MsIHJlY2lwaWVudCk7CisJ CQlpZiAocmV0KQorCQkJCXJldHVybiByZXQ7CisJCX0KKwl9CisKKwlyZXR1cm4gMDsKK30KKwor c3RhdGljIHZvaWQgdWNzaV91bnJlZ2lzdGVyX2FsdG1vZGVzKHN0cnVjdCB1Y3NpX2Nvbm5lY3Rv ciAqY29uLCB1OCByZWNpcGllbnQpCit7CisJc3RydWN0IHR5cGVjX2FsdG1vZGUgKiphZGV2Owor CWludCBpID0gMDsKKworCXN3aXRjaCAocmVjaXBpZW50KSB7CisJY2FzZSBVQ1NJX1JFQ0lQSUVO VF9DT046CisJCWFkZXYgPSBjb24tPnBvcnRfYWx0bW9kZTsKKwkJYnJlYWs7CisJY2FzZSBVQ1NJ X1JFQ0lQSUVOVF9TT1A6CisJCWFkZXYgPSBjb24tPnBhcnRuZXJfYWx0bW9kZTsKKwkJYnJlYWs7 CisJZGVmYXVsdDoKKwkJcmV0dXJuOworCX0KKworCXdoaWxlIChhZGV2W2ldKSB7CisJCXR5cGVj X3VucmVnaXN0ZXJfYWx0bW9kZShhZGV2W2ldKTsKKwkJYWRldltpKytdID0gTlVMTDsKKwl9Cit9 CisKIHN0YXRpYyB2b2lkIHVjc2lfcHdyX29wbW9kZV9jaGFuZ2Uoc3RydWN0IHVjc2lfY29ubmVj dG9yICpjb24pCiB7CiAJc3dpdGNoIChjb24tPnN0YXR1cy5wd3Jfb3BfbW9kZSkgewpAQCAtMjk5 LDEwICs0NzksNDYgQEAgc3RhdGljIHZvaWQgdWNzaV91bnJlZ2lzdGVyX3BhcnRuZXIoc3RydWN0 IHVjc2lfY29ubmVjdG9yICpjb24pCiAJaWYgKCFjb24tPnBhcnRuZXIpCiAJCXJldHVybjsKIAor CXVjc2lfdW5yZWdpc3Rlcl9hbHRtb2Rlcyhjb24sIFVDU0lfUkVDSVBJRU5UX1NPUCk7CiAJdHlw ZWNfdW5yZWdpc3Rlcl9wYXJ0bmVyKGNvbi0+cGFydG5lcik7CiAJY29uLT5wYXJ0bmVyID0gTlVM TDsKIH0KIAorc3RhdGljIHZvaWQgdWNzaV9wYXJ0bmVyX2NoYW5nZShzdHJ1Y3QgdWNzaV9jb25u ZWN0b3IgKmNvbikKK3sKKwlpbnQgcmV0OworCisJaWYgKCFjb24tPnBhcnRuZXIpCisJCXJldHVy bjsKKworCXN3aXRjaCAoY29uLT5zdGF0dXMucGFydG5lcl90eXBlKSB7CisJY2FzZSBVQ1NJX0NP TlNUQVRfUEFSVE5FUl9UWVBFX1VGUDoKKwkJdHlwZWNfc2V0X2RhdGFfcm9sZShjb24tPnBvcnQs IFRZUEVDX0hPU1QpOworCQlicmVhazsKKwljYXNlIFVDU0lfQ09OU1RBVF9QQVJUTkVSX1RZUEVf REZQOgorCQl0eXBlY19zZXRfZGF0YV9yb2xlKGNvbi0+cG9ydCwgVFlQRUNfREVWSUNFKTsKKwkJ YnJlYWs7CisJZGVmYXVsdDoKKwkJYnJlYWs7CisJfQorCisJLyogQ29tcGxldGUgcGVuZGluZyBk YXRhIHJvbGUgc3dhcCAqLworCWlmICghY29tcGxldGlvbl9kb25lKCZjb24tPmNvbXBsZXRlKSkK KwkJY29tcGxldGUoJmNvbi0+Y29tcGxldGUpOworCisJaWYgKGNvbi0+cGFydG5lcl9hbHRtb2Rl WzBdKQorCQlyZXR1cm47CisKKwkvKiBDYW4ndCByZWx5IG9uIFBhcnRuZXIgRmxhZ3MgZmllbGQu IEFsd2F5cyBjaGVja2luZyB0aGUgYWx0IG1vZGVzLiAqLworCXJldCA9IHVjc2lfcmVnaXN0ZXJf YWx0bW9kZXMoY29uLCBVQ1NJX1JFQ0lQSUVOVF9TT1ApOworCWlmIChyZXQpCisJCWRldl9lcnIo Y29uLT51Y3NpLT5kZXYsCisJCQkiY29uJWQ6IGZhaWxlZCB0byByZWdpc3RlciBwYXJ0bmVyIGFs dGVybmF0ZSBtb2Rlc1xuIiwKKwkJCWNvbi0+bnVtKTsKKwllbHNlCisJCXVjc2lfYWx0bW9kZV91 cGRhdGVfYWN0aXZlKGNvbik7Cit9CisKIHN0YXRpYyB2b2lkIHVjc2lfY29ubmVjdG9yX2NoYW5n ZShzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspCiB7CiAJc3RydWN0IHVjc2lfY29ubmVjdG9yICpj b24gPSBjb250YWluZXJfb2Yod29yaywgc3RydWN0IHVjc2lfY29ubmVjdG9yLApAQCAtMzExLDEw ICs1MjcsMTAgQEAgc3RhdGljIHZvaWQgdWNzaV9jb25uZWN0b3JfY2hhbmdlKHN0cnVjdCB3b3Jr X3N0cnVjdCAqd29yaykKIAlzdHJ1Y3QgdWNzaV9jb250cm9sIGN0cmw7CiAJaW50IHJldDsKIAot CW11dGV4X2xvY2soJnVjc2ktPnBwbV9sb2NrKTsKKwltdXRleF9sb2NrKCZjb24tPmxvY2spOwog CiAJVUNTSV9DTURfR0VUX0NPTk5FQ1RPUl9TVEFUVVMoY3RybCwgY29uLT5udW0pOwotCXJldCA9 IHVjc2lfcnVuX2NvbW1hbmQodWNzaSwgJmN0cmwsICZjb24tPnN0YXR1cywgc2l6ZW9mKGNvbi0+ c3RhdHVzKSk7CisJcmV0ID0gdWNzaV9zZW5kX2NvbW1hbmQodWNzaSwgJmN0cmwsICZjb24tPnN0 YXR1cywgc2l6ZW9mKGNvbi0+c3RhdHVzKSk7CiAJaWYgKHJldCA8IDApIHsKIAkJZGV2X2Vycih1 Y3NpLT5kZXYsICIlczogR0VUX0NPTk5FQ1RPUl9TVEFUVVMgZmFpbGVkICglZClcbiIsCiAJCQlf X2Z1bmNfXywgcmV0KTsKQEAgLTMzMiwyMyArNTQ4LDYgQEAgc3RhdGljIHZvaWQgdWNzaV9jb25u ZWN0b3JfY2hhbmdlKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKIAkJCWNvbXBsZXRlKCZjb24t PmNvbXBsZXRlKTsKIAl9CiAKLQlpZiAoY29uLT5zdGF0dXMuY2hhbmdlICYgVUNTSV9DT05TVEFU X1BBUlRORVJfQ0hBTkdFKSB7Ci0JCXN3aXRjaCAoY29uLT5zdGF0dXMucGFydG5lcl90eXBlKSB7 Ci0JCWNhc2UgVUNTSV9DT05TVEFUX1BBUlRORVJfVFlQRV9VRlA6Ci0JCQl0eXBlY19zZXRfZGF0 YV9yb2xlKGNvbi0+cG9ydCwgVFlQRUNfSE9TVCk7Ci0JCQlicmVhazsKLQkJY2FzZSBVQ1NJX0NP TlNUQVRfUEFSVE5FUl9UWVBFX0RGUDoKLQkJCXR5cGVjX3NldF9kYXRhX3JvbGUoY29uLT5wb3J0 LCBUWVBFQ19ERVZJQ0UpOwotCQkJYnJlYWs7Ci0JCWRlZmF1bHQ6Ci0JCQlicmVhazsKLQkJfQot Ci0JCS8qIENvbXBsZXRlIHBlbmRpbmcgZGF0YSByb2xlIHN3YXAgKi8KLQkJaWYgKCFjb21wbGV0 aW9uX2RvbmUoJmNvbi0+Y29tcGxldGUpKQotCQkJY29tcGxldGUoJmNvbi0+Y29tcGxldGUpOwot CX0KLQogCWlmIChjb24tPnN0YXR1cy5jaGFuZ2UgJiBVQ1NJX0NPTlNUQVRfQ09OTkVDVF9DSEFO R0UpIHsKIAkJdHlwZWNfc2V0X3B3cl9yb2xlKGNvbi0+cG9ydCwgY29uLT5zdGF0dXMucHdyX2Rp cik7CiAKQEAgLTM2OSw2ICs1NjgsMTkgQEAgc3RhdGljIHZvaWQgdWNzaV9jb25uZWN0b3JfY2hh bmdlKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKIAkJCXVjc2lfdW5yZWdpc3Rlcl9wYXJ0bmVy KGNvbik7CiAJfQogCisJaWYgKGNvbi0+c3RhdHVzLmNoYW5nZSAmIFVDU0lfQ09OU1RBVF9DQU1f Q0hBTkdFKSB7CisJCS8qCisJCSAqIFdlIGRvbid0IG5lZWQgdG8ga25vdyB0aGUgY3VycmVudGx5 IHN1cHBvcnRlZCBhbHQgbW9kZXMgaGVyZS4KKwkJICogUnVubmluZyBHRVRfQ0FNX1NVUFBPUlRF RCBjb21tYW5kIGp1c3QgdG8gbWFrZSBzdXJlIHRoZSBQUE0KKwkJICogZG9lcyBub3QgZ2V0IHN0 dWNrIGluIGNhc2UgaXQgYXNzdW1lcyB3ZSBkbyBzby4KKwkJICovCisJCVVDU0lfQ01EX0dFVF9D QU1fU1VQUE9SVEVEKGN0cmwsIGNvbi0+bnVtKTsKKwkJdWNzaV9ydW5fY29tbWFuZChjb24tPnVj c2ksICZjdHJsLCBOVUxMLCAwKTsKKwl9CisKKwlpZiAoY29uLT5zdGF0dXMuY2hhbmdlICYgVUNT SV9DT05TVEFUX1BBUlRORVJfQ0hBTkdFKQorCQl1Y3NpX3BhcnRuZXJfY2hhbmdlKGNvbik7CisK IAlyZXQgPSB1Y3NpX2Fjayh1Y3NpLCBVQ1NJX0FDS19FVkVOVCk7CiAJaWYgKHJldCkKIAkJZGV2 X2Vycih1Y3NpLT5kZXYsICIlczogQUNLIGZhaWxlZCAoJWQpIiwgX19mdW5jX18sIHJldCk7CkBA IC0zNzcsNyArNTg5LDcgQEAgc3RhdGljIHZvaWQgdWNzaV9jb25uZWN0b3JfY2hhbmdlKHN0cnVj dCB3b3JrX3N0cnVjdCAqd29yaykKIAogb3V0X3VubG9jazoKIAljbGVhcl9iaXQoRVZFTlRfUEVO RElORywgJnVjc2ktPmZsYWdzKTsKLQltdXRleF91bmxvY2soJnVjc2ktPnBwbV9sb2NrKTsKKwlt dXRleF91bmxvY2soJmNvbi0+bG9jayk7CiB9CiAKIC8qKgpAQCAtNDI3LDcgKzYzOSw3IEBAIHN0 YXRpYyBpbnQgdWNzaV9yZXNldF9jb25uZWN0b3Ioc3RydWN0IHVjc2lfY29ubmVjdG9yICpjb24s IGJvb2wgaGFyZCkKIAogCVVDU0lfQ01EX0NPTk5FQ1RPUl9SRVNFVChjdHJsLCBjb24sIGhhcmQp OwogCi0JcmV0dXJuIHVjc2lfcnVuX2NvbW1hbmQoY29uLT51Y3NpLCAmY3RybCwgTlVMTCwgMCk7 CisJcmV0dXJuIHVjc2lfc2VuZF9jb21tYW5kKGNvbi0+dWNzaSwgJmN0cmwsIE5VTEwsIDApOwog fQogCiBzdGF0aWMgaW50IHVjc2lfcmVzZXRfcHBtKHN0cnVjdCB1Y3NpICp1Y3NpKQpAQCAtNDgx LDE1ICs2OTMsMTcgQEAgc3RhdGljIGludCB1Y3NpX3JvbGVfY21kKHN0cnVjdCB1Y3NpX2Nvbm5l Y3RvciAqY29uLCBzdHJ1Y3QgdWNzaV9jb250cm9sICpjdHJsKQogewogCWludCByZXQ7CiAKLQly ZXQgPSB1Y3NpX3J1bl9jb21tYW5kKGNvbi0+dWNzaSwgY3RybCwgTlVMTCwgMCk7CisJcmV0ID0g dWNzaV9zZW5kX2NvbW1hbmQoY29uLT51Y3NpLCBjdHJsLCBOVUxMLCAwKTsKIAlpZiAocmV0ID09 IC1FVElNRURPVVQpIHsKIAkJc3RydWN0IHVjc2lfY29udHJvbCBjOwogCiAJCS8qIFBQTSBtb3N0 IGxpa2VseSBzdG9wcGVkIHJlc3BvbmRpbmcuIFJlc2V0dGluZyBldmVyeXRoaW5nLiAqLworCQlt dXRleF9sb2NrKCZjb24tPnVjc2ktPnBwbV9sb2NrKTsKIAkJdWNzaV9yZXNldF9wcG0oY29uLT51 Y3NpKTsKKwkJbXV0ZXhfdW5sb2NrKCZjb24tPnVjc2ktPnBwbV9sb2NrKTsKIAogCQlVQ1NJX0NN RF9TRVRfTlRGWV9FTkFCTEUoYywgVUNTSV9FTkFCTEVfTlRGWV9BTEwpOwotCQl1Y3NpX3J1bl9j b21tYW5kKGNvbi0+dWNzaSwgJmMsIE5VTEwsIDApOworCQl1Y3NpX3NlbmRfY29tbWFuZChjb24t PnVjc2ksICZjLCBOVUxMLCAwKTsKIAogCQl1Y3NpX3Jlc2V0X2Nvbm5lY3Rvcihjb24sIHRydWUp OwogCX0KQEAgLTUwNCwxMCArNzE4LDEyIEBAIHVjc2lfZHJfc3dhcChjb25zdCBzdHJ1Y3QgdHlw ZWNfY2FwYWJpbGl0eSAqY2FwLCBlbnVtIHR5cGVjX2RhdGFfcm9sZSByb2xlKQogCXN0cnVjdCB1 Y3NpX2NvbnRyb2wgY3RybDsKIAlpbnQgcmV0ID0gMDsKIAotCWlmICghY29uLT5wYXJ0bmVyKQot CQlyZXR1cm4gLUVOT1RDT05OOworCW11dGV4X2xvY2soJmNvbi0+bG9jayk7CiAKLQltdXRleF9s b2NrKCZjb24tPnVjc2ktPnBwbV9sb2NrKTsKKwlpZiAoIWNvbi0+cGFydG5lcikgeworCQlyZXQg PSAtRU5PVENPTk47CisJCWdvdG8gb3V0X3VubG9jazsKKwl9CiAKIAlpZiAoKGNvbi0+c3RhdHVz LnBhcnRuZXJfdHlwZSA9PSBVQ1NJX0NPTlNUQVRfUEFSVE5FUl9UWVBFX0RGUCAmJgogCSAgICAg cm9sZSA9PSBUWVBFQ19ERVZJQ0UpIHx8CkBAIC01MjAsMTggKzczNiwxNCBAQCB1Y3NpX2RyX3N3 YXAoY29uc3Qgc3RydWN0IHR5cGVjX2NhcGFiaWxpdHkgKmNhcCwgZW51bSB0eXBlY19kYXRhX3Jv bGUgcm9sZSkKIAlpZiAocmV0IDwgMCkKIAkJZ290byBvdXRfdW5sb2NrOwogCi0JbXV0ZXhfdW5s b2NrKCZjb24tPnVjc2ktPnBwbV9sb2NrKTsKLQogCWlmICghd2FpdF9mb3JfY29tcGxldGlvbl90 aW1lb3V0KCZjb24tPmNvbXBsZXRlLAogCQkJCQltc2Vjc190b19qaWZmaWVzKFVDU0lfU1dBUF9U SU1FT1VUX01TKSkpCi0JCXJldHVybiAtRVRJTUVET1VUOwotCi0JcmV0dXJuIDA7CisJCXJldCA9 IC1FVElNRURPVVQ7CiAKIG91dF91bmxvY2s6Ci0JbXV0ZXhfdW5sb2NrKCZjb24tPnVjc2ktPnBw bV9sb2NrKTsKKwltdXRleF91bmxvY2soJmNvbi0+bG9jayk7CiAKLQlyZXR1cm4gcmV0OworCXJl dHVybiByZXQgPCAwID8gcmV0IDogMDsKIH0KIAogc3RhdGljIGludApAQCAtNTQxLDEwICs3NTMs MTIgQEAgdWNzaV9wcl9zd2FwKGNvbnN0IHN0cnVjdCB0eXBlY19jYXBhYmlsaXR5ICpjYXAsIGVu dW0gdHlwZWNfcm9sZSByb2xlKQogCXN0cnVjdCB1Y3NpX2NvbnRyb2wgY3RybDsKIAlpbnQgcmV0 ID0gMDsKIAotCWlmICghY29uLT5wYXJ0bmVyKQotCQlyZXR1cm4gLUVOT1RDT05OOworCW11dGV4 X2xvY2soJmNvbi0+bG9jayk7CiAKLQltdXRleF9sb2NrKCZjb24tPnVjc2ktPnBwbV9sb2NrKTsK KwlpZiAoIWNvbi0+cGFydG5lcikgeworCQlyZXQgPSAtRU5PVENPTk47CisJCWdvdG8gb3V0X3Vu bG9jazsKKwl9CiAKIAlpZiAoY29uLT5zdGF0dXMucHdyX2RpciA9PSByb2xlKQogCQlnb3RvIG91 dF91bmxvY2s7CkBAIC01NTQsMTMgKzc2OCwxMSBAQCB1Y3NpX3ByX3N3YXAoY29uc3Qgc3RydWN0 IHR5cGVjX2NhcGFiaWxpdHkgKmNhcCwgZW51bSB0eXBlY19yb2xlIHJvbGUpCiAJaWYgKHJldCA8 IDApCiAJCWdvdG8gb3V0X3VubG9jazsKIAotCW11dGV4X3VubG9jaygmY29uLT51Y3NpLT5wcG1f bG9jayk7Ci0KIAlpZiAoIXdhaXRfZm9yX2NvbXBsZXRpb25fdGltZW91dCgmY29uLT5jb21wbGV0 ZSwKLQkJCQkJbXNlY3NfdG9famlmZmllcyhVQ1NJX1NXQVBfVElNRU9VVF9NUykpKQotCQlyZXR1 cm4gLUVUSU1FRE9VVDsKLQotCW11dGV4X2xvY2soJmNvbi0+dWNzaS0+cHBtX2xvY2spOworCQkJ CW1zZWNzX3RvX2ppZmZpZXMoVUNTSV9TV0FQX1RJTUVPVVRfTVMpKSkgeworCQlyZXQgPSAtRVRJ TUVET1VUOworCQlnb3RvIG91dF91bmxvY2s7CisJfQogCiAJLyogU29tZXRoaW5nIGhhcyBnb25l IHdyb25nIHdoaWxlIHN3YXBwaW5nIHRoZSByb2xlICovCiAJaWYgKGNvbi0+c3RhdHVzLnB3cl9v cF9tb2RlICE9IFVDU0lfQ09OU1RBVF9QV1JfT1BNT0RFX1BEKSB7CkBAIC01NjksNyArNzgxLDcg QEAgdWNzaV9wcl9zd2FwKGNvbnN0IHN0cnVjdCB0eXBlY19jYXBhYmlsaXR5ICpjYXAsIGVudW0g dHlwZWNfcm9sZSByb2xlKQogCX0KIAogb3V0X3VubG9jazoKLQltdXRleF91bmxvY2soJmNvbi0+ dWNzaS0+cHBtX2xvY2spOworCW11dGV4X3VubG9jaygmY29uLT5sb2NrKTsKIAogCXJldHVybiBy ZXQ7CiB9CkBAIC01OTUsNiArODA3LDcgQEAgc3RhdGljIGludCB1Y3NpX3JlZ2lzdGVyX3BvcnQo c3RydWN0IHVjc2kgKnVjc2ksIGludCBpbmRleCkKIAogCUlOSVRfV09SSygmY29uLT53b3JrLCB1 Y3NpX2Nvbm5lY3Rvcl9jaGFuZ2UpOwogCWluaXRfY29tcGxldGlvbigmY29uLT5jb21wbGV0ZSk7 CisJbXV0ZXhfaW5pdCgmY29uLT5sb2NrKTsKIAljb24tPm51bSA9IGluZGV4ICsgMTsKIAljb24t PnVjc2kgPSB1Y3NpOwogCkBAIC02MzYsNiArODQ5LDEyIEBAIHN0YXRpYyBpbnQgdWNzaV9yZWdp c3Rlcl9wb3J0KHN0cnVjdCB1Y3NpICp1Y3NpLCBpbnQgaW5kZXgpCiAJaWYgKElTX0VSUihjb24t PnBvcnQpKQogCQlyZXR1cm4gUFRSX0VSUihjb24tPnBvcnQpOwogCisJLyogQWx0ZXJuYXRlIG1v ZGVzICovCisJcmV0ID0gdWNzaV9yZWdpc3Rlcl9hbHRtb2Rlcyhjb24sIFVDU0lfUkVDSVBJRU5U X0NPTik7CisJaWYgKHJldCkKKwkJZGV2X2Vycih1Y3NpLT5kZXYsICJjb24lZDogZmFpbGVkIHRv IHJlZ2lzdGVyIGFsdCBtb2Rlc1xuIiwKKwkJCWNvbi0+bnVtKTsKKwogCS8qIEdldCB0aGUgc3Rh dHVzICovCiAJVUNTSV9DTURfR0VUX0NPTk5FQ1RPUl9TVEFUVVMoY3RybCwgY29uLT5udW0pOwog CXJldCA9IHVjc2lfcnVuX2NvbW1hbmQodWNzaSwgJmN0cmwsICZjb24tPnN0YXR1cywgc2l6ZW9m KGNvbi0+c3RhdHVzKSk7CkBAIC02NjIsNiArODgxLDE2IEBAIHN0YXRpYyBpbnQgdWNzaV9yZWdp c3Rlcl9wb3J0KHN0cnVjdCB1Y3NpICp1Y3NpLCBpbnQgaW5kZXgpCiAJaWYgKGNvbi0+c3RhdHVz LmNvbm5lY3RlZCkKIAkJdWNzaV9yZWdpc3Rlcl9wYXJ0bmVyKGNvbik7CiAKKwlpZiAoY29uLT5w YXJ0bmVyKSB7CisJCXJldCA9IHVjc2lfcmVnaXN0ZXJfYWx0bW9kZXMoY29uLCBVQ1NJX1JFQ0lQ SUVOVF9TT1ApOworCQlpZiAocmV0KQorCQkJZGV2X2Vycih1Y3NpLT5kZXYsCisJCQkJImNvbiVk OiBmYWlsZWQgdG8gcmVnaXN0ZXIgYWx0ZXJuYXRlIG1vZGVzXG4iLAorCQkJCWNvbi0+bnVtKTsK KwkJZWxzZQorCQkJdWNzaV9hbHRtb2RlX3VwZGF0ZV9hY3RpdmUoY29uKTsKKwl9CisKIAl0cmFj ZV91Y3NpX3JlZ2lzdGVyX3BvcnQoY29uLT5udW0sICZjb24tPnN0YXR1cyk7CiAKIAlyZXR1cm4g MDsKQEAgLTczMCw2ICs5NTksNyBAQCBzdGF0aWMgdm9pZCB1Y3NpX2luaXQoc3RydWN0IHdvcmtf c3RydWN0ICp3b3JrKQogZXJyX3VucmVnaXN0ZXI6CiAJZm9yIChjb24gPSB1Y3NpLT5jb25uZWN0 b3I7IGNvbi0+cG9ydDsgY29uKyspIHsKIAkJdWNzaV91bnJlZ2lzdGVyX3BhcnRuZXIoY29uKTsK KwkJdWNzaV91bnJlZ2lzdGVyX2FsdG1vZGVzKGNvbiwgVUNTSV9SRUNJUElFTlRfQ09OKTsKIAkJ dHlwZWNfdW5yZWdpc3Rlcl9wb3J0KGNvbi0+cG9ydCk7CiAJCWNvbi0+cG9ydCA9IE5VTEw7CiAJ fQpAQCAtNzg4LDE3ICsxMDE4LDE1IEBAIHZvaWQgdWNzaV91bnJlZ2lzdGVyX3BwbShzdHJ1Y3Qg dWNzaSAqdWNzaSkKIAkvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhcmUgbm90IGluIHRoZSBtaWRkbGUg b2YgZHJpdmVyIGluaXRpYWxpemF0aW9uICovCiAJY2FuY2VsX3dvcmtfc3luYygmdWNzaS0+d29y ayk7CiAKLQltdXRleF9sb2NrKCZ1Y3NpLT5wcG1fbG9jayk7Ci0KIAkvKiBEaXNhYmxlIGV2ZXJ5 dGhpbmcgZXhjZXB0IGNvbW1hbmQgY29tcGxldGUgbm90aWZpY2F0aW9uICovCiAJVUNTSV9DTURf U0VUX05URllfRU5BQkxFKGN0cmwsIFVDU0lfRU5BQkxFX05URllfQ01EX0NPTVBMRVRFKQotCXVj c2lfcnVuX2NvbW1hbmQodWNzaSwgJmN0cmwsIE5VTEwsIDApOwotCi0JbXV0ZXhfdW5sb2NrKCZ1 Y3NpLT5wcG1fbG9jayk7CisJdWNzaV9zZW5kX2NvbW1hbmQodWNzaSwgJmN0cmwsIE5VTEwsIDAp OwogCiAJZm9yIChpID0gMDsgaSA8IHVjc2ktPmNhcC5udW1fY29ubmVjdG9yczsgaSsrKSB7CiAJ CWNhbmNlbF93b3JrX3N5bmMoJnVjc2ktPmNvbm5lY3RvcltpXS53b3JrKTsKIAkJdWNzaV91bnJl Z2lzdGVyX3BhcnRuZXIoJnVjc2ktPmNvbm5lY3RvcltpXSk7CisJCXVjc2lfdW5yZWdpc3Rlcl9h bHRtb2RlcygmdWNzaS0+Y29ubmVjdG9yW2ldLAorCQkJCQkgVUNTSV9SRUNJUElFTlRfQ09OKTsK IAkJdHlwZWNfdW5yZWdpc3Rlcl9wb3J0KHVjc2ktPmNvbm5lY3RvcltpXS5wb3J0KTsKIAl9CiAK ZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdWNzaS5oIGIvZHJpdmVycy91c2Iv dHlwZWMvdWNzaS91Y3NpLmgKaW5kZXggNTNiODBmNDBhOTA4Li5jNDE2YmFlNGI1Y2EgMTAwNjQ0 Ci0tLSBhL2RyaXZlcnMvdXNiL3R5cGVjL3Vjc2kvdWNzaS5oCisrKyBiL2RyaXZlcnMvdXNiL3R5 cGVjL3Vjc2kvdWNzaS5oCkBAIC02LDYgKzYsNyBAQAogI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5o PgogI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgogI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+Cisj aW5jbHVkZSA8bGludXgvdXNiL3R5cGVjLmg+CiAKIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCiAK QEAgLTYwLDYgKzYxLDIwIEBAIHN0cnVjdCB1Y3NpX3Vvcl9jbWQgewogCXUxNjo2OyAvKiByZXNl cnZlZCAqLwogfSBfX3BhY2tlZDsKIAorLyogR2V0IEFsdGVybmF0ZSBNb2RlcyBDb21tYW5kIHN0 cnVjdHVyZSAqLworc3RydWN0IHVjc2lfYWx0bW9kZV9jbWQgeworCXU4IGNtZDsKKwl1OCBsZW5n dGg7CisJdTggcmVjaXBpZW50OworI2RlZmluZSBVQ1NJX1JFQ0lQSUVOVF9DT04JCQkwCisjZGVm aW5lIFVDU0lfUkVDSVBJRU5UX1NPUAkJCTEKKyNkZWZpbmUgVUNTSV9SRUNJUElFTlRfU09QX1AJ CQkyCisjZGVmaW5lIFVDU0lfUkVDSVBJRU5UX1NPUF9QUAkJCTMKKwl1OCBjb25fbnVtOworCXU4 IG9mZnNldDsKKwl1OCBudW1fYWx0bW9kZXM7Cit9IF9fcGFja2VkOworCiBzdHJ1Y3QgdWNzaV9j b250cm9sIHsKIAl1bmlvbiB7CiAJCXU2NCByYXdfY21kOwpAQCAtNjcsNiArODIsNyBAQCBzdHJ1 Y3QgdWNzaV9jb250cm9sIHsKIAkJc3RydWN0IHVjc2lfdW9yX2NtZCB1b3I7CiAJCXN0cnVjdCB1 Y3NpX2Fja19jbWQgYWNrOwogCQlzdHJ1Y3QgdWNzaV9jb25fcnN0IGNvbl9yc3Q7CisJCXN0cnVj dCB1Y3NpX2FsdG1vZGVfY21kIGFsdDsKIAl9OwogfTsKIApAQCAtMTEyLDYgKzEyOCwzMCBAQCBz dHJ1Y3QgdWNzaV9jb250cm9sIHsKIAkoX2N0cmxfKS5jbWQuZGF0YSA9IF9jb25fOwkJCQkJXAog fQogCisvKiBIZWxwZXIgZm9yIHByZXBhcmluZyB1Y3NpX2NvbnRyb2wgZm9yIEdFVF9BTFRFUk5B VEVfTU9ERVMgY29tbWFuZC4gKi8KKyNkZWZpbmUgVUNTSV9DTURfR0VUX0FMVEVSTkFURV9NT0RF UyhfY3RybF8sIF9yXywgX2Nvbl9udW1fLCBfb18sIF9udW1fKVwKK3sJCQkJCQkJCQlcCisJX19V Q1NJX0NNRCgoX2N0cmxfKSwgVUNTSV9HRVRfQUxURVJOQVRFX01PREVTKQkJCVwKKwlfY3RybF8u YWx0LnJlY2lwaWVudCA9IChfcl8pOwkJCQkJXAorCV9jdHJsXy5hbHQuY29uX251bSA9IChfY29u X251bV8pOwkJCQlcCisJX2N0cmxfLmFsdC5vZmZzZXQgPSAoX29fKTsJCQkJCVwKKwlfY3RybF8u YWx0Lm51bV9hbHRtb2RlcyA9IChfbnVtXykgLSAxOwkJCQlcCit9CisKKy8qIEhlbHBlciBmb3Ig cHJlcGFyaW5nIHVjc2lfY29udHJvbCBmb3IgR0VUX0NBTV9TVVBQT1JURUQgY29tbWFuZC4gKi8K KyNkZWZpbmUgVUNTSV9DTURfR0VUX0NBTV9TVVBQT1JURUQoX2N0cmxfLCBfY29uXykJCQlcCit7 CQkJCQkJCQkJXAorCV9fVUNTSV9DTUQoKF9jdHJsXyksIFVDU0lfR0VUX0NBTV9TVVBQT1JURUQp CQkJXAorCV9jdHJsXy5jbWQuZGF0YSA9IChfY29uXyk7CQkJCQlcCit9CisKKy8qIEhlbHBlciBm b3IgcHJlcGFyaW5nIHVjc2lfY29udHJvbCBmb3IgR0VUX0NBTV9TVVBQT1JURUQgY29tbWFuZC4g Ki8KKyNkZWZpbmUgVUNTSV9DTURfR0VUX0NVUlJFTlRfQ0FNKF9jdHJsXywgX2Nvbl8pCQkJXAor ewkJCQkJCQkJCVwKKwlfX1VDU0lfQ01EKChfY3RybF8pLCBVQ1NJX0dFVF9DVVJSRU5UX0NBTSkJ CQlcCisJX2N0cmxfLmNtZC5kYXRhID0gKF9jb25fKTsJCQkJCVwKK30KKwogLyogSGVscGVyIGZv ciBwcmVwYXJpbmcgdWNzaV9jb250cm9sIGZvciBHRVRfQ09OTkVDVE9SX1NUQVRVUyBjb21tYW5k LiAqLwogI2RlZmluZSBVQ1NJX0NNRF9HRVRfQ09OTkVDVE9SX1NUQVRVUyhfY3RybF8sIF9jb25f KQkJCVwKIHsJCQkJCQkJCQlcCkBAIC0zMzQsNCArMzc0LDM2IEBAIHN0cnVjdCB1Y3NpICp1Y3Np X3JlZ2lzdGVyX3BwbShzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCB1Y3NpX3BwbSAqcHBtKTsK IHZvaWQgdWNzaV91bnJlZ2lzdGVyX3BwbShzdHJ1Y3QgdWNzaSAqdWNzaSk7CiB2b2lkIHVjc2lf bm90aWZ5KHN0cnVjdCB1Y3NpICp1Y3NpKTsKIAorLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KKwor c3RydWN0IHVjc2k7CisKKyNkZWZpbmUgVUNTSV9NQVhfU1ZJRAkJNQorI2RlZmluZSBVQ1NJX01B WF9BTFRNT0RFUwkoVUNTSV9NQVhfU1ZJRCAqIDYpCisKK3N0cnVjdCB1Y3NpX2Nvbm5lY3RvciB7 CisJaW50IG51bTsKKworCXN0cnVjdCB1Y3NpICp1Y3NpOworCXN0cnVjdCBtdXRleCBsb2NrOyAv KiBwb3J0IGxvY2sgKi8KKwlzdHJ1Y3Qgd29ya19zdHJ1Y3Qgd29yazsKKwlzdHJ1Y3QgY29tcGxl dGlvbiBjb21wbGV0ZTsKKworCXN0cnVjdCB0eXBlY19wb3J0ICpwb3J0OworCXN0cnVjdCB0eXBl Y19wYXJ0bmVyICpwYXJ0bmVyOworCisJc3RydWN0IHR5cGVjX2FsdG1vZGUgKnBvcnRfYWx0bW9k ZVtVQ1NJX01BWF9BTFRNT0RFU107CisJc3RydWN0IHR5cGVjX2FsdG1vZGUgKnBhcnRuZXJfYWx0 bW9kZVtVQ1NJX01BWF9BTFRNT0RFU107CisKKwlzdHJ1Y3QgdHlwZWNfY2FwYWJpbGl0eSB0eXBl Y19jYXA7CisKKwlzdHJ1Y3QgdWNzaV9jb25uZWN0b3Jfc3RhdHVzIHN0YXR1czsKKwlzdHJ1Y3Qg dWNzaV9jb25uZWN0b3JfY2FwYWJpbGl0eSBjYXA7Cit9OworCitpbnQgdWNzaV9zZW5kX2NvbW1h bmQoc3RydWN0IHVjc2kgKnVjc2ksIHN0cnVjdCB1Y3NpX2NvbnRyb2wgKmN0cmwsCisJCSAgICAg IHZvaWQgKnJldHZhbCwgc2l6ZV90IHNpemUpOworCit2b2lkIHVjc2lfYWx0bW9kZV91cGRhdGVf YWN0aXZlKHN0cnVjdCB1Y3NpX2Nvbm5lY3RvciAqY29uKTsKKwogI2VuZGlmIC8qIF9fRFJJVkVS X1VTQl9UWVBFQ19VQ1NJX0ggKi8K 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=-8.9 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,USER_AGENT_GIT 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 333CBC10F12 for ; Mon, 15 Apr 2019 12:09:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ECE8A2075B for ; Mon, 15 Apr 2019 12:09:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727316AbfDOMJl (ORCPT ); Mon, 15 Apr 2019 08:09:41 -0400 Received: from mga12.intel.com ([192.55.52.136]:10510 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726042AbfDOMJl (ORCPT ); Mon, 15 Apr 2019 08:09:41 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Apr 2019 05:09:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,353,1549958400"; d="scan'208";a="164850776" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 15 Apr 2019 05:09:39 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: Ajay Gupta , linux-usb@vger.kernel.org Subject: [PATCH v2 4/7] usb: typec: ucsi: Preliminary support for alternate modes Date: Mon, 15 Apr 2019 15:09:28 +0300 Message-Id: <20190415120931.61328-5-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190415120931.61328-1-heikki.krogerus@linux.intel.com> References: <20190415120931.61328-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Message-ID: <20190415120928.oeFwdh0NSeW-fGE2gox3awaz6ukjGm-CIB6QbR8Vduc@z> With UCSI the alternate modes, just like everything else related to USB Type-C connectors, are handled in firmware. The operating system can see the status and is allowed to request certain things, for example entering and exiting the modes, but the support for alternate modes is very limited in UCSI. The feature is also optional, which means that even when the platform supports alternate modes, the operating system may not be even made aware of them. UCSI does not support direct VDM reading or writing. Instead, alternate modes can be entered and exited using a single custom command which takes also an optional SVID specific configuration value as parameter. That means every supported alternate mode has to be handled separately in UCSI driver. This commit does not include support for any specific alternate mode. The discovered alternate modes are now registered, but binding a driver to an alternate mode will not be possible until support for that alternate mode is added to the UCSI driver. Tested-by: Ajay Gupta Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/trace.c | 12 ++ drivers/usb/typec/ucsi/trace.h | 26 +++ drivers/usb/typec/ucsi/ucsi.c | 358 +++++++++++++++++++++++++++------ drivers/usb/typec/ucsi/ucsi.h | 72 +++++++ 4 files changed, 403 insertions(+), 65 deletions(-) diff --git a/drivers/usb/typec/ucsi/trace.c b/drivers/usb/typec/ucsi/trace.c index ffa3b4c3f338..1dabafb74320 100644 --- a/drivers/usb/typec/ucsi/trace.c +++ b/drivers/usb/typec/ucsi/trace.c @@ -60,3 +60,15 @@ const char *ucsi_cci_str(u32 cci) return ""; } + +static const char * const ucsi_recipient_strs[] = { + [UCSI_RECIPIENT_CON] = "port", + [UCSI_RECIPIENT_SOP] = "partner", + [UCSI_RECIPIENT_SOP_P] = "plug (prime)", + [UCSI_RECIPIENT_SOP_PP] = "plug (double prime)", +}; + +const char *ucsi_recipient_str(u8 recipient) +{ + return ucsi_recipient_strs[recipient]; +} diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h index 5e2906df2db7..783ec9c72055 100644 --- a/drivers/usb/typec/ucsi/trace.h +++ b/drivers/usb/typec/ucsi/trace.h @@ -7,6 +7,7 @@ #define __UCSI_TRACE_H #include +#include const char *ucsi_cmd_str(u64 raw_cmd); const char *ucsi_ack_str(u8 ack); @@ -134,6 +135,31 @@ DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port, TP_ARGS(port, status) ); +DECLARE_EVENT_CLASS(ucsi_log_register_altmode, + TP_PROTO(u8 recipient, struct typec_altmode *alt), + TP_ARGS(recipient, alt), + TP_STRUCT__entry( + __field(u8, recipient) + __field(u16, svid) + __field(u8, mode) + __field(u32, vdo) + ), + TP_fast_assign( + __entry->recipient = recipient; + __entry->svid = alt->svid; + __entry->mode = alt->mode; + __entry->vdo = alt->vdo; + ), + TP_printk("%s alt mode: svid %04x, mode %d vdo %x", + ucsi_recipient_str(__entry->recipient), __entry->svid, + __entry->mode, __entry->vdo) +); + +DEFINE_EVENT(ucsi_log_register_altmode, ucsi_register_altmode, + TP_PROTO(u8 recipient, struct typec_altmode *alt), + TP_ARGS(recipient, alt) +); + #endif /* __UCSI_TRACE_H */ /* This part must be outside protection */ diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 8d0a6fe748bd..585ab04be940 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "ucsi.h" #include "trace.h" @@ -45,22 +45,6 @@ enum ucsi_status { UCSI_ERROR, }; -struct ucsi_connector { - int num; - - struct ucsi *ucsi; - struct work_struct work; - struct completion complete; - - struct typec_port *port; - struct typec_partner *partner; - - struct typec_capability typec_cap; - - struct ucsi_connector_status status; - struct ucsi_connector_capability cap; -}; - struct ucsi { struct device *dev; struct ucsi_ppm *ppm; @@ -238,8 +222,204 @@ static int ucsi_run_command(struct ucsi *ucsi, struct ucsi_control *ctrl, return ret; } +int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl, + void *retval, size_t size) +{ + int ret; + + mutex_lock(&ucsi->ppm_lock); + ret = ucsi_run_command(ucsi, ctrl, retval, size); + mutex_unlock(&ucsi->ppm_lock); + + return ret; +} + /* -------------------------------------------------------------------------- */ +void ucsi_altmode_update_active(struct ucsi_connector *con) +{ + const struct typec_altmode *altmode = NULL; + struct ucsi_control ctrl; + int ret; + u8 cur; + int i; + + UCSI_CMD_GET_CURRENT_CAM(ctrl, con->num); + ret = ucsi_run_command(con->ucsi, &ctrl, &cur, sizeof(cur)); + if (ret < 0) { + if (con->ucsi->ppm->data->version > 0x0100) { + dev_err(con->ucsi->dev, + "GET_CURRENT_CAM command failed\n"); + return; + } + cur = 0xff; + } + + if (cur < UCSI_MAX_ALTMODES) + altmode = typec_altmode_get_partner(con->port_altmode[cur]); + + for (i = 0; con->partner_altmode[i]; i++) + typec_altmode_update_active(con->partner_altmode[i], + con->partner_altmode[i] == altmode); +} + +static u8 ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid) +{ + u8 mode = 1; + int i; + + for (i = 0; alt[i]; i++) + if (alt[i]->svid == svid) + mode++; + + return mode; +} + +static int ucsi_next_altmode(struct typec_altmode **alt) +{ + int i = 0; + + for (i = 0; i < UCSI_MAX_ALTMODES; i++) + if (!alt[i]) + return i; + + return -ENOENT; +} + +static int ucsi_register_altmode(struct ucsi_connector *con, + struct typec_altmode_desc *desc, + u8 recipient) +{ + struct typec_altmode *alt; + int ret; + int i; + + switch (recipient) { + case UCSI_RECIPIENT_CON: + i = ucsi_next_altmode(con->port_altmode); + if (i < 0) { + ret = i; + goto err; + } + + desc->mode = ucsi_altmode_next_mode(con->port_altmode, + desc->svid); + + alt = typec_port_register_altmode(con->port, desc); + if (IS_ERR(alt)) { + ret = PTR_ERR(alt); + goto err; + } + + con->port_altmode[i] = alt; + break; + case UCSI_RECIPIENT_SOP: + i = ucsi_next_altmode(con->partner_altmode); + if (i < 0) { + ret = i; + goto err; + } + + desc->mode = ucsi_altmode_next_mode(con->partner_altmode, + desc->svid); + + alt = typec_partner_register_altmode(con->partner, desc); + if (IS_ERR(alt)) { + ret = PTR_ERR(alt); + goto err; + } + + con->partner_altmode[i] = alt; + break; + default: + return -EINVAL; + } + + trace_ucsi_register_altmode(recipient, alt); + + return 0; + +err: + dev_err(con->ucsi->dev, "failed to registers svid 0x%04x mode %d\n", + desc->svid, desc->mode); + + return ret; +} + +static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient) +{ + int max_altmodes = UCSI_MAX_ALTMODES; + struct typec_altmode_desc desc; + struct ucsi_altmode alt[2]; + struct ucsi_control ctrl; + int num = 1; + int ret; + int len; + int j; + int i; + + if (!(con->ucsi->cap.features & UCSI_CAP_ALT_MODE_DETAILS)) + return 0; + + if (recipient == UCSI_RECIPIENT_CON) + max_altmodes = con->ucsi->cap.num_alt_modes; + + for (i = 0; i < max_altmodes;) { + memset(alt, 0, sizeof(alt)); + UCSI_CMD_GET_ALTERNATE_MODES(ctrl, recipient, con->num, i, 1); + len = ucsi_run_command(con->ucsi, &ctrl, alt, sizeof(alt)); + if (len <= 0) + return len; + + /* + * This code is requesting one alt mode at a time, but some PPMs + * may still return two. If that happens both alt modes need be + * registered and the offset for the next alt mode has to be + * incremented. + */ + num = len / sizeof(alt[0]); + i += num; + + for (j = 0; j < num; j++) { + if (!alt[j].svid) + return 0; + + memset(&desc, 0, sizeof(desc)); + desc.vdo = alt[j].mid; + desc.svid = alt[j].svid; + desc.roles = TYPEC_PORT_DRD; + + ret = ucsi_register_altmode(con, &desc, recipient); + if (ret) + return ret; + } + } + + return 0; +} + +static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient) +{ + struct typec_altmode **adev; + int i = 0; + + switch (recipient) { + case UCSI_RECIPIENT_CON: + adev = con->port_altmode; + break; + case UCSI_RECIPIENT_SOP: + adev = con->partner_altmode; + break; + default: + return; + } + + while (adev[i]) { + typec_unregister_altmode(adev[i]); + adev[i++] = NULL; + } +} + static void ucsi_pwr_opmode_change(struct ucsi_connector *con) { switch (con->status.pwr_op_mode) { @@ -299,10 +479,46 @@ static void ucsi_unregister_partner(struct ucsi_connector *con) if (!con->partner) return; + ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); typec_unregister_partner(con->partner); con->partner = NULL; } +static void ucsi_partner_change(struct ucsi_connector *con) +{ + int ret; + + if (!con->partner) + return; + + switch (con->status.partner_type) { + case UCSI_CONSTAT_PARTNER_TYPE_UFP: + typec_set_data_role(con->port, TYPEC_HOST); + break; + case UCSI_CONSTAT_PARTNER_TYPE_DFP: + typec_set_data_role(con->port, TYPEC_DEVICE); + break; + default: + break; + } + + /* Complete pending data role swap */ + if (!completion_done(&con->complete)) + complete(&con->complete); + + if (con->partner_altmode[0]) + return; + + /* Can't rely on Partner Flags field. Always checking the alt modes. */ + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); + if (ret) + dev_err(con->ucsi->dev, + "con%d: failed to register partner alternate modes\n", + con->num); + else + ucsi_altmode_update_active(con); +} + static void ucsi_connector_change(struct work_struct *work) { struct ucsi_connector *con = container_of(work, struct ucsi_connector, @@ -311,10 +527,10 @@ static void ucsi_connector_change(struct work_struct *work) struct ucsi_control ctrl; int ret; - mutex_lock(&ucsi->ppm_lock); + mutex_lock(&con->lock); UCSI_CMD_GET_CONNECTOR_STATUS(ctrl, con->num); - ret = ucsi_run_command(ucsi, &ctrl, &con->status, sizeof(con->status)); + ret = ucsi_send_command(ucsi, &ctrl, &con->status, sizeof(con->status)); if (ret < 0) { dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", __func__, ret); @@ -332,23 +548,6 @@ static void ucsi_connector_change(struct work_struct *work) complete(&con->complete); } - if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) { - switch (con->status.partner_type) { - case UCSI_CONSTAT_PARTNER_TYPE_UFP: - typec_set_data_role(con->port, TYPEC_HOST); - break; - case UCSI_CONSTAT_PARTNER_TYPE_DFP: - typec_set_data_role(con->port, TYPEC_DEVICE); - break; - default: - break; - } - - /* Complete pending data role swap */ - if (!completion_done(&con->complete)) - complete(&con->complete); - } - if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) { typec_set_pwr_role(con->port, con->status.pwr_dir); @@ -369,6 +568,19 @@ static void ucsi_connector_change(struct work_struct *work) ucsi_unregister_partner(con); } + if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) { + /* + * We don't need to know the currently supported alt modes here. + * Running GET_CAM_SUPPORTED command just to make sure the PPM + * does not get stuck in case it assumes we do so. + */ + UCSI_CMD_GET_CAM_SUPPORTED(ctrl, con->num); + ucsi_run_command(con->ucsi, &ctrl, NULL, 0); + } + + if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) + ucsi_partner_change(con); + ret = ucsi_ack(ucsi, UCSI_ACK_EVENT); if (ret) dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); @@ -377,7 +589,7 @@ static void ucsi_connector_change(struct work_struct *work) out_unlock: clear_bit(EVENT_PENDING, &ucsi->flags); - mutex_unlock(&ucsi->ppm_lock); + mutex_unlock(&con->lock); } /** @@ -427,7 +639,7 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard) UCSI_CMD_CONNECTOR_RESET(ctrl, con, hard); - return ucsi_run_command(con->ucsi, &ctrl, NULL, 0); + return ucsi_send_command(con->ucsi, &ctrl, NULL, 0); } static int ucsi_reset_ppm(struct ucsi *ucsi) @@ -481,15 +693,17 @@ static int ucsi_role_cmd(struct ucsi_connector *con, struct ucsi_control *ctrl) { int ret; - ret = ucsi_run_command(con->ucsi, ctrl, NULL, 0); + ret = ucsi_send_command(con->ucsi, ctrl, NULL, 0); if (ret == -ETIMEDOUT) { struct ucsi_control c; /* PPM most likely stopped responding. Resetting everything. */ + mutex_lock(&con->ucsi->ppm_lock); ucsi_reset_ppm(con->ucsi); + mutex_unlock(&con->ucsi->ppm_lock); UCSI_CMD_SET_NTFY_ENABLE(c, UCSI_ENABLE_NTFY_ALL); - ucsi_run_command(con->ucsi, &c, NULL, 0); + ucsi_send_command(con->ucsi, &c, NULL, 0); ucsi_reset_connector(con, true); } @@ -504,10 +718,12 @@ ucsi_dr_swap(const struct typec_capability *cap, enum typec_data_role role) struct ucsi_control ctrl; int ret = 0; - if (!con->partner) - return -ENOTCONN; + mutex_lock(&con->lock); - mutex_lock(&con->ucsi->ppm_lock); + if (!con->partner) { + ret = -ENOTCONN; + goto out_unlock; + } if ((con->status.partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP && role == TYPEC_DEVICE) || @@ -520,18 +736,14 @@ ucsi_dr_swap(const struct typec_capability *cap, enum typec_data_role role) if (ret < 0) goto out_unlock; - mutex_unlock(&con->ucsi->ppm_lock); - if (!wait_for_completion_timeout(&con->complete, msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) - return -ETIMEDOUT; - - return 0; + ret = -ETIMEDOUT; out_unlock: - mutex_unlock(&con->ucsi->ppm_lock); + mutex_unlock(&con->lock); - return ret; + return ret < 0 ? ret : 0; } static int @@ -541,10 +753,12 @@ ucsi_pr_swap(const struct typec_capability *cap, enum typec_role role) struct ucsi_control ctrl; int ret = 0; - if (!con->partner) - return -ENOTCONN; + mutex_lock(&con->lock); - mutex_lock(&con->ucsi->ppm_lock); + if (!con->partner) { + ret = -ENOTCONN; + goto out_unlock; + } if (con->status.pwr_dir == role) goto out_unlock; @@ -554,13 +768,11 @@ ucsi_pr_swap(const struct typec_capability *cap, enum typec_role role) if (ret < 0) goto out_unlock; - mutex_unlock(&con->ucsi->ppm_lock); - if (!wait_for_completion_timeout(&con->complete, - msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) - return -ETIMEDOUT; - - mutex_lock(&con->ucsi->ppm_lock); + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) { + ret = -ETIMEDOUT; + goto out_unlock; + } /* Something has gone wrong while swapping the role */ if (con->status.pwr_op_mode != UCSI_CONSTAT_PWR_OPMODE_PD) { @@ -569,7 +781,7 @@ ucsi_pr_swap(const struct typec_capability *cap, enum typec_role role) } out_unlock: - mutex_unlock(&con->ucsi->ppm_lock); + mutex_unlock(&con->lock); return ret; } @@ -595,6 +807,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) INIT_WORK(&con->work, ucsi_connector_change); init_completion(&con->complete); + mutex_init(&con->lock); con->num = index + 1; con->ucsi = ucsi; @@ -636,6 +849,12 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) if (IS_ERR(con->port)) return PTR_ERR(con->port); + /* Alternate modes */ + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON); + if (ret) + dev_err(ucsi->dev, "con%d: failed to register alt modes\n", + con->num); + /* Get the status */ UCSI_CMD_GET_CONNECTOR_STATUS(ctrl, con->num); ret = ucsi_run_command(ucsi, &ctrl, &con->status, sizeof(con->status)); @@ -662,6 +881,16 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) if (con->status.connected) ucsi_register_partner(con); + if (con->partner) { + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); + if (ret) + dev_err(ucsi->dev, + "con%d: failed to register alternate modes\n", + con->num); + else + ucsi_altmode_update_active(con); + } + trace_ucsi_register_port(con->num, &con->status); return 0; @@ -730,6 +959,7 @@ static void ucsi_init(struct work_struct *work) err_unregister: for (con = ucsi->connector; con->port; con++) { ucsi_unregister_partner(con); + ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); typec_unregister_port(con->port); con->port = NULL; } @@ -788,17 +1018,15 @@ void ucsi_unregister_ppm(struct ucsi *ucsi) /* Make sure that we are not in the middle of driver initialization */ cancel_work_sync(&ucsi->work); - mutex_lock(&ucsi->ppm_lock); - /* Disable everything except command complete notification */ UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_CMD_COMPLETE) - ucsi_run_command(ucsi, &ctrl, NULL, 0); - - mutex_unlock(&ucsi->ppm_lock); + ucsi_send_command(ucsi, &ctrl, NULL, 0); for (i = 0; i < ucsi->cap.num_connectors; i++) { cancel_work_sync(&ucsi->connector[i].work); ucsi_unregister_partner(&ucsi->connector[i]); + ucsi_unregister_altmodes(&ucsi->connector[i], + UCSI_RECIPIENT_CON); typec_unregister_port(ucsi->connector[i].port); } diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 53b80f40a908..c416bae4b5ca 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -6,6 +6,7 @@ #include #include #include +#include /* -------------------------------------------------------------------------- */ @@ -60,6 +61,20 @@ struct ucsi_uor_cmd { u16:6; /* reserved */ } __packed; +/* Get Alternate Modes Command structure */ +struct ucsi_altmode_cmd { + u8 cmd; + u8 length; + u8 recipient; +#define UCSI_RECIPIENT_CON 0 +#define UCSI_RECIPIENT_SOP 1 +#define UCSI_RECIPIENT_SOP_P 2 +#define UCSI_RECIPIENT_SOP_PP 3 + u8 con_num; + u8 offset; + u8 num_altmodes; +} __packed; + struct ucsi_control { union { u64 raw_cmd; @@ -67,6 +82,7 @@ struct ucsi_control { struct ucsi_uor_cmd uor; struct ucsi_ack_cmd ack; struct ucsi_con_rst con_rst; + struct ucsi_altmode_cmd alt; }; }; @@ -112,6 +128,30 @@ struct ucsi_control { (_ctrl_).cmd.data = _con_; \ } +/* Helper for preparing ucsi_control for GET_ALTERNATE_MODES command. */ +#define UCSI_CMD_GET_ALTERNATE_MODES(_ctrl_, _r_, _con_num_, _o_, _num_)\ +{ \ + __UCSI_CMD((_ctrl_), UCSI_GET_ALTERNATE_MODES) \ + _ctrl_.alt.recipient = (_r_); \ + _ctrl_.alt.con_num = (_con_num_); \ + _ctrl_.alt.offset = (_o_); \ + _ctrl_.alt.num_altmodes = (_num_) - 1; \ +} + +/* Helper for preparing ucsi_control for GET_CAM_SUPPORTED command. */ +#define UCSI_CMD_GET_CAM_SUPPORTED(_ctrl_, _con_) \ +{ \ + __UCSI_CMD((_ctrl_), UCSI_GET_CAM_SUPPORTED) \ + _ctrl_.cmd.data = (_con_); \ +} + +/* Helper for preparing ucsi_control for GET_CAM_SUPPORTED command. */ +#define UCSI_CMD_GET_CURRENT_CAM(_ctrl_, _con_) \ +{ \ + __UCSI_CMD((_ctrl_), UCSI_GET_CURRENT_CAM) \ + _ctrl_.cmd.data = (_con_); \ +} + /* Helper for preparing ucsi_control for GET_CONNECTOR_STATUS command. */ #define UCSI_CMD_GET_CONNECTOR_STATUS(_ctrl_, _con_) \ { \ @@ -334,4 +374,36 @@ struct ucsi *ucsi_register_ppm(struct device *dev, struct ucsi_ppm *ppm); void ucsi_unregister_ppm(struct ucsi *ucsi); void ucsi_notify(struct ucsi *ucsi); +/* -------------------------------------------------------------------------- */ + +struct ucsi; + +#define UCSI_MAX_SVID 5 +#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) + +struct ucsi_connector { + int num; + + struct ucsi *ucsi; + struct mutex lock; /* port lock */ + struct work_struct work; + struct completion complete; + + struct typec_port *port; + struct typec_partner *partner; + + struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES]; + struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES]; + + struct typec_capability typec_cap; + + struct ucsi_connector_status status; + struct ucsi_connector_capability cap; +}; + +int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl, + void *retval, size_t size); + +void ucsi_altmode_update_active(struct ucsi_connector *con); + #endif /* __DRIVER_USB_TYPEC_UCSI_H */ -- 2.20.1