From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754750AbdCFUN0 (ORCPT ); Mon, 6 Mar 2017 15:13:26 -0500 Received: from mail.kernel.org ([198.145.29.136]:51912 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754577AbdCFULS (ORCPT ); Mon, 6 Mar 2017 15:11:18 -0500 From: Stefano Stabellini To: xen-devel@lists.xenproject.org Cc: linux-kernel@vger.kernel.org, sstabellini@kernel.org, Stefano Stabellini , boris.ostrovsky@oracle.com, jgross@suse.com, Eric Van Hensbergen , Ron Minnich , Latchesar Ionkov , v9fs-developer@lists.sourceforge.net Subject: [PATCH 4/7] xen/9pfs: connect to the backend Date: Mon, 6 Mar 2017 12:01:25 -0800 Message-Id: <1488830488-18506-4-git-send-email-sstabellini@kernel.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1488830488-18506-1-git-send-email-sstabellini@kernel.org> References: <1488830488-18506-1-git-send-email-sstabellini@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement functions to handle the xenbus handshake. Upon connection, allocate the rings according to the protocol specification. Initialize a work_struct and a wait_queue. The work_struct will be used to schedule work upon receiving an event channel notification from the backend. The wait_queue will be used to wait when the ring is full and we need to send a new request. Signed-off-by: Stefano Stabellini CC: boris.ostrovsky@oracle.com CC: jgross@suse.com CC: Eric Van Hensbergen CC: Ron Minnich CC: Latchesar Ionkov CC: v9fs-developer@lists.sourceforge.net --- net/9p/trans_xen.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index 877dfd0..9f6cf8d 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -17,6 +17,36 @@ #include #include +#define XEN_9PFS_NUM_RINGS 2 + +/* One per ring, more than one per 9pfs share */ +struct xen_9pfs_dataring { + struct xen_9pfs_front_priv *priv; + + struct xen_9pfs_data_intf *intf; + grant_ref_t ref; + int evtchn; + int irq; + spinlock_t lock; + + void *bytes; + struct xen_9pfs_data ring; + wait_queue_head_t wq; + struct work_struct work; +}; + +/* One per 9pfs share */ +struct xen_9pfs_front_priv { + struct list_head list; + struct xenbus_device *dev; + char *tag; + struct p9_client *client; + + int num_rings; + struct xen_9pfs_dataring *rings; +}; +static LIST_HEAD(xen_9pfs_devs); + static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req) { return 0; @@ -36,6 +66,21 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) return 0; } +static void p9_xen_response(struct work_struct *work) +{ +} + +static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r) +{ + struct xen_9pfs_dataring *ring = r; + BUG_ON(!ring || !ring->priv->client); + + wake_up_interruptible(&ring->wq); + schedule_work(&ring->work); + + return IRQ_HANDLED; +} + static struct p9_trans_module p9_xen_trans = { .name = "xen", .maxsize = (1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT)), @@ -52,25 +97,207 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) { "" } }; +static int xen_9pfs_front_free(struct xen_9pfs_front_priv *priv) +{ + int i, j; + + list_del(&priv->list); + + for (i = 0; i < priv->num_rings; i++) { + if (priv->rings[i].intf == NULL) + break; + if (priv->rings[i].irq > 0) + unbind_from_irqhandler(priv->rings[i].irq, priv->dev); + if (priv->rings[i].bytes != NULL) { + for (j = 0; j < (1 << XEN_9PFS_RING_ORDER); j++) + gnttab_end_foreign_access(priv->rings[i].intf->ref[j], 0, 0); + free_pages((unsigned long)priv->rings[i].bytes, XEN_9PFS_RING_ORDER); + } + gnttab_end_foreign_access(priv->rings[i].ref, 0, 0); + free_page((unsigned long)priv->rings[i].intf); + } + kfree(priv->rings); + kfree(priv); + + return 0; +} + static int xen_9pfs_front_remove(struct xenbus_device *dev) { + int ret; + struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev); + + dev_set_drvdata(&dev->dev, NULL); + ret = xen_9pfs_front_free(priv); + return ret; +} + +static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev, + struct xen_9pfs_dataring *ring) +{ + int i; + int ret = -ENOMEM; + + init_waitqueue_head(&ring->wq); + spin_lock_init(&ring->lock); + INIT_WORK(&ring->work, p9_xen_response); + + ring->intf = (struct xen_9pfs_data_intf *) __get_free_page(GFP_KERNEL | __GFP_ZERO); + if (!ring->intf) + goto error; + memset(ring->intf, 0, XEN_PAGE_SIZE); + ring->bytes = (void*)__get_free_pages(GFP_KERNEL | __GFP_ZERO, XEN_9PFS_RING_ORDER); + if (ring->bytes == NULL) + goto error; + for (i = 0; i < (1 << XEN_9PFS_RING_ORDER); i++) + ring->intf->ref[i] = gnttab_grant_foreign_access(dev->otherend_id, pfn_to_gfn(virt_to_pfn((void*)ring->bytes) + i), 0); + ring->ref = gnttab_grant_foreign_access(dev->otherend_id, pfn_to_gfn(virt_to_pfn((void*)ring->intf)), 0); + ring->ring.in = ring->bytes; + ring->ring.out = ring->bytes + XEN_9PFS_RING_SIZE; + + ret = xenbus_alloc_evtchn(dev, &ring->evtchn); + if (ret) + goto error; + ring->irq = bind_evtchn_to_irqhandler(ring->evtchn, xen_9pfs_front_event_handler, + 0, "xen_9pfs-frontend", ring); + if (ring->irq < 0) { + xenbus_free_evtchn(dev, ring->evtchn); + ret = ring->irq; + goto error; + } return 0; + +error: + if (ring->intf != NULL) + kfree(ring->intf); + if (ring->bytes != NULL) + kfree(ring->bytes); + return ret; } static int xen_9pfs_front_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { + int ret = -EFAULT, i; + struct xenbus_transaction xbt; + struct xen_9pfs_front_priv *priv = NULL; + char *versions; + unsigned int max_rings, max_ring_order, len; + + versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len); + if (!len || strcmp(versions, "1")) + return -EINVAL; + kfree(versions); + ret = xenbus_scanf(XBT_NIL, dev->otherend, "max-rings", "%u", &max_rings); + if (ret < 0 || max_rings < XEN_9PFS_NUM_RINGS) + return -EINVAL; + ret = xenbus_scanf(XBT_NIL, dev->otherend, "max-ring-page-order", "%u", &max_ring_order); + if (ret < 0|| max_ring_order < XEN_9PFS_RING_ORDER) + return -EINVAL; + + + priv = kzalloc(sizeof(struct xen_9pfs_front_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->num_rings = XEN_9PFS_NUM_RINGS; + priv->rings = kzalloc(sizeof(struct xen_9pfs_dataring) * priv->num_rings, + GFP_KERNEL); + if (!priv->rings) { + kfree(priv); + return -ENOMEM; + } + + again: + ret = xenbus_transaction_start(&xbt); + if (ret) { + xenbus_dev_fatal(dev, ret, "starting transaction"); + goto error; + } + ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1); + if (ret) + goto error_xenbus; + ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u", priv->num_rings); + if (ret) + goto error_xenbus; + for (i = 0; i < priv->num_rings; i++) { + char str[16]; + + priv->rings[i].priv = priv; + ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i]); + if (ret < 0) + goto error_xenbus; + + sprintf(str, "ring-ref%u", i); + ret = xenbus_printf(xbt, dev->nodename, str, "%d", priv->rings[i].ref); + if (ret) + goto error_xenbus; + + sprintf(str, "event-channel-%u", i); + ret = xenbus_printf(xbt, dev->nodename, str, "%u", priv->rings[i].evtchn); + if (ret) + goto error_xenbus; + } + priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL); + if (ret) + goto error_xenbus; + ret = xenbus_transaction_end(xbt, 0); + if (ret) { + if (ret == -EAGAIN) + goto again; + xenbus_dev_fatal(dev, ret, "completing transaction"); + goto error; + } + + + list_add_tail(&priv->list, &xen_9pfs_devs); + dev_set_drvdata(&dev->dev, priv); + xenbus_switch_state(dev, XenbusStateInitialised); + return 0; + + error_xenbus: + xenbus_transaction_end(xbt, 1); + xenbus_dev_fatal(dev, ret, "writing xenstore"); + error: + dev_set_drvdata(&dev->dev, NULL); + xen_9pfs_front_free(priv); + return ret; } static int xen_9pfs_front_resume(struct xenbus_device *dev) { + dev_warn(&dev->dev, "suspsend/resume unsupported\n"); return 0; } static void xen_9pfs_front_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { + switch (backend_state) { + case XenbusStateReconfiguring: + case XenbusStateReconfigured: + case XenbusStateInitialising: + case XenbusStateInitialised: + case XenbusStateUnknown: + break; + + case XenbusStateInitWait: + break; + + case XenbusStateConnected: + xenbus_switch_state(dev, XenbusStateConnected); + break; + + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ + case XenbusStateClosing: + xenbus_frontend_closed(dev); + break; + } } static struct xenbus_driver xen_9pfs_front_driver = { -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stefano Stabellini Subject: [PATCH 4/7] xen/9pfs: connect to the backend Date: Mon, 6 Mar 2017 12:01:25 -0800 Message-ID: <1488830488-18506-4-git-send-email-sstabellini@kernel.org> References: <1488830488-18506-1-git-send-email-sstabellini@kernel.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ckypB-0004Fa-G3 for xen-devel@lists.xenproject.org; Mon, 06 Mar 2017 20:01:41 +0000 In-Reply-To: <1488830488-18506-1-git-send-email-sstabellini@kernel.org> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel@lists.xenproject.org Cc: jgross@suse.com, Latchesar Ionkov , sstabellini@kernel.org, Eric Van Hensbergen , linux-kernel@vger.kernel.org, Stefano Stabellini , v9fs-developer@lists.sourceforge.net, Ron Minnich , boris.ostrovsky@oracle.com List-Id: xen-devel@lists.xenproject.org SW1wbGVtZW50IGZ1bmN0aW9ucyB0byBoYW5kbGUgdGhlIHhlbmJ1cyBoYW5kc2hha2UuIFVwb24g Y29ubmVjdGlvbiwKYWxsb2NhdGUgdGhlIHJpbmdzIGFjY29yZGluZyB0byB0aGUgcHJvdG9jb2wg c3BlY2lmaWNhdGlvbi4KCkluaXRpYWxpemUgYSB3b3JrX3N0cnVjdCBhbmQgYSB3YWl0X3F1ZXVl LiBUaGUgd29ya19zdHJ1Y3Qgd2lsbCBiZSB1c2VkCnRvIHNjaGVkdWxlIHdvcmsgdXBvbiByZWNl aXZpbmcgYW4gZXZlbnQgY2hhbm5lbCBub3RpZmljYXRpb24gZnJvbSB0aGUKYmFja2VuZC4gVGhl IHdhaXRfcXVldWUgd2lsbCBiZSB1c2VkIHRvIHdhaXQgd2hlbiB0aGUgcmluZyBpcyBmdWxsIGFu ZAp3ZSBuZWVkIHRvIHNlbmQgYSBuZXcgcmVxdWVzdC4KClNpZ25lZC1vZmYtYnk6IFN0ZWZhbm8g U3RhYmVsbGluaSA8c3RlZmFub0BhcG9yZXRvLmNvbT4KQ0M6IGJvcmlzLm9zdHJvdnNreUBvcmFj bGUuY29tCkNDOiBqZ3Jvc3NAc3VzZS5jb20KQ0M6IEVyaWMgVmFuIEhlbnNiZXJnZW4gPGVyaWN2 aEBnbWFpbC5jb20+CkNDOiBSb24gTWlubmljaCA8cm1pbm5pY2hAc2FuZGlhLmdvdj4KQ0M6IExh dGNoZXNhciBJb25rb3YgPGx1Y2hvQGlvbmtvdi5uZXQ+CkNDOiB2OWZzLWRldmVsb3BlckBsaXN0 cy5zb3VyY2Vmb3JnZS5uZXQKLS0tCiBuZXQvOXAvdHJhbnNfeGVuLmMgfCAyMjcgKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIDEgZmlsZSBjaGFu Z2VkLCAyMjcgaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdpdCBhL25ldC85cC90cmFuc194ZW4uYyBi L25ldC85cC90cmFuc194ZW4uYwppbmRleCA4NzdkZmQwLi45ZjZjZjhkIDEwMDY0NAotLS0gYS9u ZXQvOXAvdHJhbnNfeGVuLmMKKysrIGIvbmV0LzlwL3RyYW5zX3hlbi5jCkBAIC0xNyw2ICsxNywz NiBAQAogI2luY2x1ZGUgPG5ldC85cC9jbGllbnQuaD4KICNpbmNsdWRlIDxuZXQvOXAvdHJhbnNw b3J0Lmg+CiAKKyNkZWZpbmUgWEVOXzlQRlNfTlVNX1JJTkdTIDIKKworLyogT25lIHBlciByaW5n LCBtb3JlIHRoYW4gb25lIHBlciA5cGZzIHNoYXJlICovCitzdHJ1Y3QgeGVuXzlwZnNfZGF0YXJp bmcgeworCXN0cnVjdCB4ZW5fOXBmc19mcm9udF9wcml2ICpwcml2OworCisJc3RydWN0IHhlbl85 cGZzX2RhdGFfaW50ZiAqaW50ZjsKKwlncmFudF9yZWZfdCByZWY7CisJaW50IGV2dGNobjsKKwlp bnQgaXJxOworCXNwaW5sb2NrX3QgbG9jazsKKworCXZvaWQgKmJ5dGVzOworCXN0cnVjdCB4ZW5f OXBmc19kYXRhIHJpbmc7CisJd2FpdF9xdWV1ZV9oZWFkX3Qgd3E7CisJc3RydWN0IHdvcmtfc3Ry dWN0IHdvcms7Cit9OworCisvKiBPbmUgcGVyIDlwZnMgc2hhcmUgKi8KK3N0cnVjdCB4ZW5fOXBm c19mcm9udF9wcml2IHsKKwlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7CisJc3RydWN0IHhlbmJ1c19k ZXZpY2UgKmRldjsKKwljaGFyICp0YWc7CisJc3RydWN0IHA5X2NsaWVudCAqY2xpZW50OworCisJ aW50IG51bV9yaW5nczsKKwlzdHJ1Y3QgeGVuXzlwZnNfZGF0YXJpbmcgKnJpbmdzOworfTsKK3N0 YXRpYyBMSVNUX0hFQUQoeGVuXzlwZnNfZGV2cyk7CisKIHN0YXRpYyBpbnQgcDlfeGVuX2NhbmNl bChzdHJ1Y3QgcDlfY2xpZW50ICpjbGllbnQsIHN0cnVjdCBwOV9yZXFfdCAqcmVxKQogewogCXJl dHVybiAwOwpAQCAtMzYsNiArNjYsMjEgQEAgc3RhdGljIGludCBwOV94ZW5fcmVxdWVzdChzdHJ1 Y3QgcDlfY2xpZW50ICpjbGllbnQsIHN0cnVjdCBwOV9yZXFfdCAqcDlfcmVxKQogCXJldHVybiAw OwogfQogCitzdGF0aWMgdm9pZCBwOV94ZW5fcmVzcG9uc2Uoc3RydWN0IHdvcmtfc3RydWN0ICp3 b3JrKQoreworfQorCitzdGF0aWMgaXJxcmV0dXJuX3QgeGVuXzlwZnNfZnJvbnRfZXZlbnRfaGFu ZGxlcihpbnQgaXJxLCB2b2lkICpyKQoreworCXN0cnVjdCB4ZW5fOXBmc19kYXRhcmluZyAqcmlu ZyA9IHI7CisJQlVHX09OKCFyaW5nIHx8ICFyaW5nLT5wcml2LT5jbGllbnQpOworCisJd2FrZV91 cF9pbnRlcnJ1cHRpYmxlKCZyaW5nLT53cSk7CisJc2NoZWR1bGVfd29yaygmcmluZy0+d29yayk7 CisKKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cit9CisKIHN0YXRpYyBzdHJ1Y3QgcDlfdHJhbnNfbW9k dWxlIHA5X3hlbl90cmFucyA9IHsKIAkubmFtZSA9ICJ4ZW4iLAogCS5tYXhzaXplID0gKDEgPDwg KFhFTl85UEZTX1JJTkdfT1JERVIgKyBYRU5fUEFHRV9TSElGVCkpLApAQCAtNTIsMjUgKzk3LDIw NyBAQCBzdGF0aWMgaW50IHA5X3hlbl9yZXF1ZXN0KHN0cnVjdCBwOV9jbGllbnQgKmNsaWVudCwg c3RydWN0IHA5X3JlcV90ICpwOV9yZXEpCiAJeyAiIiB9CiB9OwogCitzdGF0aWMgaW50IHhlbl85 cGZzX2Zyb250X2ZyZWUoc3RydWN0IHhlbl85cGZzX2Zyb250X3ByaXYgKnByaXYpCit7CisJaW50 IGksIGo7CisKKwlsaXN0X2RlbCgmcHJpdi0+bGlzdCk7CisKKwlmb3IgKGkgPSAwOyBpIDwgcHJp di0+bnVtX3JpbmdzOyBpKyspIHsKKwkJaWYgKHByaXYtPnJpbmdzW2ldLmludGYgPT0gTlVMTCkK KwkJCWJyZWFrOworCQlpZiAocHJpdi0+cmluZ3NbaV0uaXJxID4gMCkKKwkJCXVuYmluZF9mcm9t X2lycWhhbmRsZXIocHJpdi0+cmluZ3NbaV0uaXJxLCBwcml2LT5kZXYpOworCQlpZiAocHJpdi0+ cmluZ3NbaV0uYnl0ZXMgIT0gTlVMTCkgeworCQkJZm9yIChqID0gMDsgaiA8ICgxIDw8IFhFTl85 UEZTX1JJTkdfT1JERVIpOyBqKyspCisJCQkJZ250dGFiX2VuZF9mb3JlaWduX2FjY2Vzcyhwcml2 LT5yaW5nc1tpXS5pbnRmLT5yZWZbal0sIDAsIDApOworCQkJZnJlZV9wYWdlcygodW5zaWduZWQg bG9uZylwcml2LT5yaW5nc1tpXS5ieXRlcywgWEVOXzlQRlNfUklOR19PUkRFUik7CisJCX0KKwkJ Z250dGFiX2VuZF9mb3JlaWduX2FjY2Vzcyhwcml2LT5yaW5nc1tpXS5yZWYsIDAsIDApOworCQlm cmVlX3BhZ2UoKHVuc2lnbmVkIGxvbmcpcHJpdi0+cmluZ3NbaV0uaW50Zik7CisJfQorCWtmcmVl KHByaXYtPnJpbmdzKTsKKwlrZnJlZShwcml2KTsKKworCXJldHVybiAwOworfQorCiBzdGF0aWMg aW50IHhlbl85cGZzX2Zyb250X3JlbW92ZShzdHJ1Y3QgeGVuYnVzX2RldmljZSAqZGV2KQogewor CWludCByZXQ7CisJc3RydWN0IHhlbl85cGZzX2Zyb250X3ByaXYgKnByaXYgPSBkZXZfZ2V0X2Ry dmRhdGEoJmRldi0+ZGV2KTsKKworCWRldl9zZXRfZHJ2ZGF0YSgmZGV2LT5kZXYsIE5VTEwpOwor CXJldCA9IHhlbl85cGZzX2Zyb250X2ZyZWUocHJpdik7CisJcmV0dXJuIHJldDsKK30KKworc3Rh dGljIGludCB4ZW5fOXBmc19mcm9udF9hbGxvY19kYXRhcmluZyhzdHJ1Y3QgeGVuYnVzX2Rldmlj ZSAqZGV2LAorCQlzdHJ1Y3QgeGVuXzlwZnNfZGF0YXJpbmcgKnJpbmcpCit7CisJaW50IGk7CisJ aW50IHJldCA9IC1FTk9NRU07CisKKwlpbml0X3dhaXRxdWV1ZV9oZWFkKCZyaW5nLT53cSk7CisJ c3Bpbl9sb2NrX2luaXQoJnJpbmctPmxvY2spOworCUlOSVRfV09SSygmcmluZy0+d29yaywgcDlf eGVuX3Jlc3BvbnNlKTsKKworCXJpbmctPmludGYgPSAoc3RydWN0IHhlbl85cGZzX2RhdGFfaW50 ZiAqKSBfX2dldF9mcmVlX3BhZ2UoR0ZQX0tFUk5FTCB8IF9fR0ZQX1pFUk8pOworCWlmICghcmlu Zy0+aW50ZikKKwkJZ290byBlcnJvcjsKKwltZW1zZXQocmluZy0+aW50ZiwgMCwgWEVOX1BBR0Vf U0laRSk7CisJcmluZy0+Ynl0ZXMgPSAodm9pZCopX19nZXRfZnJlZV9wYWdlcyhHRlBfS0VSTkVM IHwgX19HRlBfWkVSTywgWEVOXzlQRlNfUklOR19PUkRFUik7CisJaWYgKHJpbmctPmJ5dGVzID09 IE5VTEwpCisJCWdvdG8gZXJyb3I7CisJZm9yIChpID0gMDsgaSA8ICgxIDw8IFhFTl85UEZTX1JJ TkdfT1JERVIpOyBpKyspCisJCXJpbmctPmludGYtPnJlZltpXSA9IGdudHRhYl9ncmFudF9mb3Jl aWduX2FjY2VzcyhkZXYtPm90aGVyZW5kX2lkLCBwZm5fdG9fZ2ZuKHZpcnRfdG9fcGZuKCh2b2lk KilyaW5nLT5ieXRlcykgKyBpKSwgMCk7CisJcmluZy0+cmVmID0gZ250dGFiX2dyYW50X2ZvcmVp Z25fYWNjZXNzKGRldi0+b3RoZXJlbmRfaWQsIHBmbl90b19nZm4odmlydF90b19wZm4oKHZvaWQq KXJpbmctPmludGYpKSwgMCk7CisJcmluZy0+cmluZy5pbiA9IHJpbmctPmJ5dGVzOworCXJpbmct PnJpbmcub3V0ID0gcmluZy0+Ynl0ZXMgKyBYRU5fOVBGU19SSU5HX1NJWkU7CisKKwlyZXQgPSB4 ZW5idXNfYWxsb2NfZXZ0Y2huKGRldiwgJnJpbmctPmV2dGNobik7CisJaWYgKHJldCkKKwkJZ290 byBlcnJvcjsKKwlyaW5nLT5pcnEgPSBiaW5kX2V2dGNobl90b19pcnFoYW5kbGVyKHJpbmctPmV2 dGNobiwgeGVuXzlwZnNfZnJvbnRfZXZlbnRfaGFuZGxlciwKKwkJCQkJMCwgInhlbl85cGZzLWZy b250ZW5kIiwgcmluZyk7CisJaWYgKHJpbmctPmlycSA8IDApIHsKKwkJeGVuYnVzX2ZyZWVfZXZ0 Y2huKGRldiwgcmluZy0+ZXZ0Y2huKTsKKwkJcmV0ID0gcmluZy0+aXJxOworCQlnb3RvIGVycm9y OworCX0KIAlyZXR1cm4gMDsKKworZXJyb3I6CisJaWYgKHJpbmctPmludGYgIT0gTlVMTCkKKwkJ a2ZyZWUocmluZy0+aW50Zik7CisJaWYgKHJpbmctPmJ5dGVzICE9IE5VTEwpCisJCWtmcmVlKHJp bmctPmJ5dGVzKTsKKwlyZXR1cm4gcmV0OwogfQogCiBzdGF0aWMgaW50IHhlbl85cGZzX2Zyb250 X3Byb2JlKHN0cnVjdCB4ZW5idXNfZGV2aWNlICpkZXYsCiAJCWNvbnN0IHN0cnVjdCB4ZW5idXNf ZGV2aWNlX2lkICppZCkKIHsKKwlpbnQgcmV0ID0gLUVGQVVMVCwgaTsKKwlzdHJ1Y3QgeGVuYnVz X3RyYW5zYWN0aW9uIHhidDsKKwlzdHJ1Y3QgeGVuXzlwZnNfZnJvbnRfcHJpdiAqcHJpdiA9IE5V TEw7CisJY2hhciAqdmVyc2lvbnM7CisJdW5zaWduZWQgaW50IG1heF9yaW5ncywgbWF4X3Jpbmdf b3JkZXIsIGxlbjsKKworCXZlcnNpb25zID0geGVuYnVzX3JlYWQoWEJUX05JTCwgZGV2LT5vdGhl cmVuZCwgInZlcnNpb25zIiwgJmxlbik7CisJaWYgKCFsZW4gfHwgc3RyY21wKHZlcnNpb25zLCAi MSIpKQorCQlyZXR1cm4gLUVJTlZBTDsKKwlrZnJlZSh2ZXJzaW9ucyk7CisJcmV0ID0geGVuYnVz X3NjYW5mKFhCVF9OSUwsIGRldi0+b3RoZXJlbmQsICJtYXgtcmluZ3MiLCAiJXUiLCAmbWF4X3Jp bmdzKTsKKwlpZiAocmV0IDwgMCB8fCBtYXhfcmluZ3MgPCBYRU5fOVBGU19OVU1fUklOR1MpCisJ CXJldHVybiAtRUlOVkFMOworCXJldCA9IHhlbmJ1c19zY2FuZihYQlRfTklMLCBkZXYtPm90aGVy ZW5kLCAibWF4LXJpbmctcGFnZS1vcmRlciIsICIldSIsICZtYXhfcmluZ19vcmRlcik7CisJaWYg KHJldCA8IDB8fCBtYXhfcmluZ19vcmRlciA8IFhFTl85UEZTX1JJTkdfT1JERVIpCisJCXJldHVy biAtRUlOVkFMOworCisKKwlwcml2ID0ga3phbGxvYyhzaXplb2Yoc3RydWN0IHhlbl85cGZzX2Zy b250X3ByaXYpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXByaXYpCisJCXJldHVybiAtRU5PTUVNOwor CisJcHJpdi0+ZGV2ID0gZGV2OworCXByaXYtPm51bV9yaW5ncyA9IFhFTl85UEZTX05VTV9SSU5H UzsKKwlwcml2LT5yaW5ncyA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCB4ZW5fOXBmc19kYXRhcmlu ZykgKiBwcml2LT5udW1fcmluZ3MsCisJCQkJCQlHRlBfS0VSTkVMKTsKKwlpZiAoIXByaXYtPnJp bmdzKSB7CisJCWtmcmVlKHByaXYpOworCQlyZXR1cm4gLUVOT01FTTsKKwl9CisKKyBhZ2FpbjoK KwlyZXQgPSB4ZW5idXNfdHJhbnNhY3Rpb25fc3RhcnQoJnhidCk7CisJaWYgKHJldCkgeworCQl4 ZW5idXNfZGV2X2ZhdGFsKGRldiwgcmV0LCAic3RhcnRpbmcgdHJhbnNhY3Rpb24iKTsKKwkJZ290 byBlcnJvcjsKKwl9CisJcmV0ID0geGVuYnVzX3ByaW50Zih4YnQsIGRldi0+bm9kZW5hbWUsICJ2 ZXJzaW9uIiwgIiV1IiwgMSk7CisJaWYgKHJldCkKKwkJZ290byBlcnJvcl94ZW5idXM7CisJcmV0 ID0geGVuYnVzX3ByaW50Zih4YnQsIGRldi0+bm9kZW5hbWUsICJudW0tcmluZ3MiLCAiJXUiLCBw cml2LT5udW1fcmluZ3MpOworCWlmIChyZXQpCisJCWdvdG8gZXJyb3JfeGVuYnVzOworCWZvciAo aSA9IDA7IGkgPCBwcml2LT5udW1fcmluZ3M7IGkrKykgeworCQljaGFyIHN0clsxNl07CisKKwkJ cHJpdi0+cmluZ3NbaV0ucHJpdiA9IHByaXY7CisJCXJldCA9IHhlbl85cGZzX2Zyb250X2FsbG9j X2RhdGFyaW5nKGRldiwgJnByaXYtPnJpbmdzW2ldKTsKKwkJaWYgKHJldCA8IDApCisJCQlnb3Rv IGVycm9yX3hlbmJ1czsKKworCQlzcHJpbnRmKHN0ciwgInJpbmctcmVmJXUiLCBpKTsKKwkJcmV0 ID0geGVuYnVzX3ByaW50Zih4YnQsIGRldi0+bm9kZW5hbWUsIHN0ciwgIiVkIiwgcHJpdi0+cmlu Z3NbaV0ucmVmKTsKKwkJaWYgKHJldCkKKwkJCWdvdG8gZXJyb3JfeGVuYnVzOworCisJCXNwcmlu dGYoc3RyLCAiZXZlbnQtY2hhbm5lbC0ldSIsIGkpOworCQlyZXQgPSB4ZW5idXNfcHJpbnRmKHhi dCwgZGV2LT5ub2RlbmFtZSwgc3RyLCAiJXUiLCBwcml2LT5yaW5nc1tpXS5ldnRjaG4pOworCQlp ZiAocmV0KQorCQkJZ290byBlcnJvcl94ZW5idXM7CisJfQorCXByaXYtPnRhZyA9IHhlbmJ1c19y ZWFkKHhidCwgZGV2LT5ub2RlbmFtZSwgInRhZyIsIE5VTEwpOworCWlmIChyZXQpCisJCWdvdG8g ZXJyb3JfeGVuYnVzOworCXJldCA9IHhlbmJ1c190cmFuc2FjdGlvbl9lbmQoeGJ0LCAwKTsKKwlp ZiAocmV0KSB7CisJCWlmIChyZXQgPT0gLUVBR0FJTikKKwkJCWdvdG8gYWdhaW47CisJCXhlbmJ1 c19kZXZfZmF0YWwoZGV2LCByZXQsICJjb21wbGV0aW5nIHRyYW5zYWN0aW9uIik7CisJCWdvdG8g ZXJyb3I7CisJfQorCisKKwlsaXN0X2FkZF90YWlsKCZwcml2LT5saXN0LCAmeGVuXzlwZnNfZGV2 cyk7CisJZGV2X3NldF9kcnZkYXRhKCZkZXYtPmRldiwgcHJpdik7CisJeGVuYnVzX3N3aXRjaF9z dGF0ZShkZXYsIFhlbmJ1c1N0YXRlSW5pdGlhbGlzZWQpOworCiAJcmV0dXJuIDA7CisKKyBlcnJv cl94ZW5idXM6CisJeGVuYnVzX3RyYW5zYWN0aW9uX2VuZCh4YnQsIDEpOworCXhlbmJ1c19kZXZf ZmF0YWwoZGV2LCByZXQsICJ3cml0aW5nIHhlbnN0b3JlIik7CisgZXJyb3I6CisJZGV2X3NldF9k cnZkYXRhKCZkZXYtPmRldiwgTlVMTCk7CisJeGVuXzlwZnNfZnJvbnRfZnJlZShwcml2KTsKKwly ZXR1cm4gcmV0OwogfQogCiBzdGF0aWMgaW50IHhlbl85cGZzX2Zyb250X3Jlc3VtZShzdHJ1Y3Qg eGVuYnVzX2RldmljZSAqZGV2KQogeworCWRldl93YXJuKCZkZXYtPmRldiwgInN1c3BzZW5kL3Jl c3VtZSB1bnN1cHBvcnRlZFxuIik7CiAJcmV0dXJuIDA7CiB9CiAKIHN0YXRpYyB2b2lkIHhlbl85 cGZzX2Zyb250X2NoYW5nZWQoc3RydWN0IHhlbmJ1c19kZXZpY2UgKmRldiwKIAkJCSAgICBlbnVt IHhlbmJ1c19zdGF0ZSBiYWNrZW5kX3N0YXRlKQogeworCXN3aXRjaCAoYmFja2VuZF9zdGF0ZSkg eworCWNhc2UgWGVuYnVzU3RhdGVSZWNvbmZpZ3VyaW5nOgorCWNhc2UgWGVuYnVzU3RhdGVSZWNv bmZpZ3VyZWQ6CisJY2FzZSBYZW5idXNTdGF0ZUluaXRpYWxpc2luZzoKKwljYXNlIFhlbmJ1c1N0 YXRlSW5pdGlhbGlzZWQ6CisJY2FzZSBYZW5idXNTdGF0ZVVua25vd246CisJCWJyZWFrOworCisJ Y2FzZSBYZW5idXNTdGF0ZUluaXRXYWl0OgorCQlicmVhazsKKworCWNhc2UgWGVuYnVzU3RhdGVD b25uZWN0ZWQ6CisJCXhlbmJ1c19zd2l0Y2hfc3RhdGUoZGV2LCBYZW5idXNTdGF0ZUNvbm5lY3Rl ZCk7CisJCWJyZWFrOworCisJY2FzZSBYZW5idXNTdGF0ZUNsb3NlZDoKKwkJaWYgKGRldi0+c3Rh dGUgPT0gWGVuYnVzU3RhdGVDbG9zZWQpCisJCQlicmVhazsKKwkJLyogTWlzc2VkIHRoZSBiYWNr ZW5kJ3MgQ0xPU0lORyBzdGF0ZSAtLSBmYWxsdGhyb3VnaCAqLworCWNhc2UgWGVuYnVzU3RhdGVD bG9zaW5nOgorCQl4ZW5idXNfZnJvbnRlbmRfY2xvc2VkKGRldik7CisJCWJyZWFrOworCX0KIH0K IAogc3RhdGljIHN0cnVjdCB4ZW5idXNfZHJpdmVyIHhlbl85cGZzX2Zyb250X2RyaXZlciA9IHsK LS0gCjEuOS4xCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KWGVuLWRldmVsIG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczov L2xpc3RzLnhlbi5vcmcveGVuLWRldmVsCg==