From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751983AbdIOXCm (ORCPT ); Fri, 15 Sep 2017 19:02:42 -0400 Received: from mail.kernel.org ([198.145.29.99]:37066 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751575AbdIOXAo (ORCPT ); Fri, 15 Sep 2017 19:00:44 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3D21422A79 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=sstabellini@kernel.org From: Stefano Stabellini To: xen-devel@lists.xen.org Cc: linux-kernel@vger.kernel.org, sstabellini@kernel.org, jgross@suse.com, boris.ostrovsky@oracle.com, Stefano Stabellini Subject: [PATCH v4 05/13] xen/pvcalls: implement connect command Date: Fri, 15 Sep 2017 16:00:32 -0700 Message-Id: <1505516440-11111-5-git-send-email-sstabellini@kernel.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1505516440-11111-1-git-send-email-sstabellini@kernel.org> References: <1505516440-11111-1-git-send-email-sstabellini@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Send PVCALLS_CONNECT to the backend. Allocate a new ring and evtchn for the active socket. Introduce fields in struct sock_mapping to keep track of active sockets. Introduce a waitqueue to allow the frontend to wait on data coming from the backend on the active socket (recvmsg command). Two mutexes (one of reads and one for writes) will be used to protect the active socket in and out rings from concurrent accesses. Signed-off-by: Stefano Stabellini CC: boris.ostrovsky@oracle.com CC: jgross@suse.com --- drivers/xen/pvcalls-front.c | 163 ++++++++++++++++++++++++++++++++++++++++++++ drivers/xen/pvcalls-front.h | 2 + 2 files changed, 165 insertions(+) diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index 1bad1b1..ef511b6 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -13,6 +13,10 @@ */ #include +#include +#include + +#include #include #include @@ -57,6 +61,18 @@ struct sock_mapping { bool active_socket; struct list_head list; struct socket *sock; + union { + struct { + int irq; + grant_ref_t ref; + struct pvcalls_data_intf *ring; + struct pvcalls_data data; + struct mutex in_mutex; + struct mutex out_mutex; + + wait_queue_head_t inflight_conn_req; + } active; + }; }; static inline int get_request(struct pvcalls_bedata *bedata, int *req_id) @@ -114,6 +130,18 @@ static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t pvcalls_front_conn_handler(int irq, void *sock_map) +{ + struct sock_mapping *map = sock_map; + + if (map == NULL) + return IRQ_HANDLED; + + wake_up_interruptible(&map->active.inflight_conn_req); + + return IRQ_HANDLED; +} + int pvcalls_front_socket(struct socket *sock) { struct pvcalls_bedata *bedata; @@ -191,6 +219,133 @@ int pvcalls_front_socket(struct socket *sock) return ret; } +static int create_active(struct sock_mapping *map, int *evtchn) +{ + void *bytes; + int ret = -ENOMEM, irq = -1, i; + + *evtchn = -1; + init_waitqueue_head(&map->active.inflight_conn_req); + + map->active.ring = (struct pvcalls_data_intf *) + __get_free_page(GFP_KERNEL | __GFP_ZERO); + if (map->active.ring == NULL) + goto out_error; + map->active.ring->ring_order = PVCALLS_RING_ORDER; + bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + PVCALLS_RING_ORDER); + if (bytes == NULL) + goto out_error; + for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) + map->active.ring->ref[i] = gnttab_grant_foreign_access( + pvcalls_front_dev->otherend_id, + pfn_to_gfn(virt_to_pfn(bytes) + i), 0); + + map->active.ref = gnttab_grant_foreign_access( + pvcalls_front_dev->otherend_id, + pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0); + + map->active.data.in = bytes; + map->active.data.out = bytes + + XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); + + ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn); + if (ret) + goto out_error; + irq = bind_evtchn_to_irqhandler(*evtchn, pvcalls_front_conn_handler, + 0, "pvcalls-frontend", map); + if (irq < 0) { + ret = irq; + goto out_error; + } + + map->active.irq = irq; + map->active_socket = true; + mutex_init(&map->active.in_mutex); + mutex_init(&map->active.out_mutex); + + return 0; + +out_error: + if (irq >= 0) + unbind_from_irqhandler(irq, map); + else if (*evtchn >= 0) + xenbus_free_evtchn(pvcalls_front_dev, *evtchn); + kfree(map->active.data.in); + kfree(map->active.ring); + return ret; +} + +int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, + int addr_len, int flags) +{ + struct pvcalls_bedata *bedata; + struct sock_mapping *map = NULL; + struct xen_pvcalls_request *req; + int notify, req_id, ret, evtchn; + + pvcalls_enter; + if (!pvcalls_front_dev) { + pvcalls_exit; + return -ENETUNREACH; + } + if (addr->sa_family != AF_INET || sock->type != SOCK_STREAM) { + pvcalls_exit; + return -ENOTSUPP; + } + + bedata = dev_get_drvdata(&pvcalls_front_dev->dev); + + map = (struct sock_mapping *) sock->sk->sk_send_head; + if (!map) { + pvcalls_exit; + return -ENOTSOCK; + } + + spin_lock(&bedata->socket_lock); + ret = get_request(bedata, &req_id); + if (ret < 0) { + spin_unlock(&bedata->socket_lock); + pvcalls_exit; + return ret; + } + ret = create_active(map, &evtchn); + if (ret < 0) { + spin_unlock(&bedata->socket_lock); + pvcalls_exit; + return ret; + } + + req = RING_GET_REQUEST(&bedata->ring, req_id); + req->req_id = req_id; + req->cmd = PVCALLS_CONNECT; + req->u.connect.id = (uint64_t)map; + memcpy(req->u.connect.addr, addr, sizeof(*addr)); + req->u.connect.len = addr_len; + req->u.connect.flags = flags; + req->u.connect.ref = map->active.ref; + req->u.connect.evtchn = evtchn; + + map->sock = sock; + + bedata->ring.req_prod_pvt++; + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify); + spin_unlock(&bedata->socket_lock); + + if (notify) + notify_remote_via_irq(bedata->irq); + + wait_event(bedata->inflight_req, + READ_ONCE(bedata->rsp[req_id].req_id) == req_id); + + ret = bedata->rsp[req_id].ret; + /* read ret, then set this rsp slot to be reused */ + smp_mb(); + WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID); + pvcalls_exit; + return ret; +} + static const struct xenbus_device_id pvcalls_front_ids[] = { { "pvcalls" }, { "" } @@ -207,6 +362,14 @@ static int pvcalls_front_remove(struct xenbus_device *dev) if (bedata->irq >= 0) unbind_from_irqhandler(bedata->irq, dev); + list_for_each_entry_safe(map, n, &bedata->socket_mappings, list) { + map->sock->sk->sk_send_head = NULL; + if (map->active_socket) { + map->active.ring->in_error = -EBADF; + wake_up_interruptible(&map->active.inflight_conn_req); + } + } + smp_mb(); while (atomic_read(&pvcalls_refcount) > 0) cpu_relax(); diff --git a/drivers/xen/pvcalls-front.h b/drivers/xen/pvcalls-front.h index b7dabed..63b0417 100644 --- a/drivers/xen/pvcalls-front.h +++ b/drivers/xen/pvcalls-front.h @@ -4,5 +4,7 @@ #include int pvcalls_front_socket(struct socket *sock); +int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, + int addr_len, int flags); #endif -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stefano Stabellini Subject: [PATCH v4 05/13] xen/pvcalls: implement connect command Date: Fri, 15 Sep 2017 16:00:32 -0700 Message-ID: <1505516440-11111-5-git-send-email-sstabellini@kernel.org> References: <1505516440-11111-1-git-send-email-sstabellini@kernel.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1505516440-11111-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.xen.org Cc: jgross@suse.com, Stefano Stabellini , boris.ostrovsky@oracle.com, sstabellini@kernel.org, linux-kernel@vger.kernel.org List-Id: xen-devel@lists.xenproject.org U2VuZCBQVkNBTExTX0NPTk5FQ1QgdG8gdGhlIGJhY2tlbmQuIEFsbG9jYXRlIGEgbmV3IHJpbmcg YW5kIGV2dGNobiBmb3IKdGhlIGFjdGl2ZSBzb2NrZXQuCgpJbnRyb2R1Y2UgZmllbGRzIGluIHN0 cnVjdCBzb2NrX21hcHBpbmcgdG8ga2VlcCB0cmFjayBvZiBhY3RpdmUgc29ja2V0cy4KSW50cm9k dWNlIGEgd2FpdHF1ZXVlIHRvIGFsbG93IHRoZSBmcm9udGVuZCB0byB3YWl0IG9uIGRhdGEgY29t aW5nIGZyb20KdGhlIGJhY2tlbmQgb24gdGhlIGFjdGl2ZSBzb2NrZXQgKHJlY3Ztc2cgY29tbWFu ZCkuCgpUd28gbXV0ZXhlcyAob25lIG9mIHJlYWRzIGFuZCBvbmUgZm9yIHdyaXRlcykgd2lsbCBi ZSB1c2VkIHRvIHByb3RlY3QKdGhlIGFjdGl2ZSBzb2NrZXQgaW4gYW5kIG91dCByaW5ncyBmcm9t IGNvbmN1cnJlbnQgYWNjZXNzZXMuCgpTaWduZWQtb2ZmLWJ5OiBTdGVmYW5vIFN0YWJlbGxpbmkg PHN0ZWZhbm9AYXBvcmV0by5jb20+CkNDOiBib3Jpcy5vc3Ryb3Zza3lAb3JhY2xlLmNvbQpDQzog amdyb3NzQHN1c2UuY29tCi0tLQogZHJpdmVycy94ZW4vcHZjYWxscy1mcm9udC5jIHwgMTYzICsr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiBkcml2ZXJzL3hlbi9w dmNhbGxzLWZyb250LmggfCAgIDIgKwogMiBmaWxlcyBjaGFuZ2VkLCAxNjUgaW5zZXJ0aW9ucygr KQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMveGVuL3B2Y2FsbHMtZnJvbnQuYyBiL2RyaXZlcnMveGVu L3B2Y2FsbHMtZnJvbnQuYwppbmRleCAxYmFkMWIxLi5lZjUxMWI2IDEwMDY0NAotLS0gYS9kcml2 ZXJzL3hlbi9wdmNhbGxzLWZyb250LmMKKysrIGIvZHJpdmVycy94ZW4vcHZjYWxscy1mcm9udC5j CkBAIC0xMyw2ICsxMywxMCBAQAogICovCiAKICNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNp bmNsdWRlIDxsaW51eC9uZXQuaD4KKyNpbmNsdWRlIDxsaW51eC9zb2NrZXQuaD4KKworI2luY2x1 ZGUgPG5ldC9zb2NrLmg+CiAKICNpbmNsdWRlIDx4ZW4vZXZlbnRzLmg+CiAjaW5jbHVkZSA8eGVu L2dyYW50X3RhYmxlLmg+CkBAIC01Nyw2ICs2MSwxOCBAQCBzdHJ1Y3Qgc29ja19tYXBwaW5nIHsK IAlib29sIGFjdGl2ZV9zb2NrZXQ7CiAJc3RydWN0IGxpc3RfaGVhZCBsaXN0OwogCXN0cnVjdCBz b2NrZXQgKnNvY2s7CisJdW5pb24geworCQlzdHJ1Y3QgeworCQkJaW50IGlycTsKKwkJCWdyYW50 X3JlZl90IHJlZjsKKwkJCXN0cnVjdCBwdmNhbGxzX2RhdGFfaW50ZiAqcmluZzsKKwkJCXN0cnVj dCBwdmNhbGxzX2RhdGEgZGF0YTsKKwkJCXN0cnVjdCBtdXRleCBpbl9tdXRleDsKKwkJCXN0cnVj dCBtdXRleCBvdXRfbXV0ZXg7CisKKwkJCXdhaXRfcXVldWVfaGVhZF90IGluZmxpZ2h0X2Nvbm5f cmVxOworCQl9IGFjdGl2ZTsKKwl9OwogfTsKIAogc3RhdGljIGlubGluZSBpbnQgZ2V0X3JlcXVl c3Qoc3RydWN0IHB2Y2FsbHNfYmVkYXRhICpiZWRhdGEsIGludCAqcmVxX2lkKQpAQCAtMTE0LDYg KzEzMCwxOCBAQCBzdGF0aWMgaXJxcmV0dXJuX3QgcHZjYWxsc19mcm9udF9ldmVudF9oYW5kbGVy KGludCBpcnEsIHZvaWQgKmRldl9pZCkKIAlyZXR1cm4gSVJRX0hBTkRMRUQ7CiB9CiAKK3N0YXRp YyBpcnFyZXR1cm5fdCBwdmNhbGxzX2Zyb250X2Nvbm5faGFuZGxlcihpbnQgaXJxLCB2b2lkICpz b2NrX21hcCkKK3sKKwlzdHJ1Y3Qgc29ja19tYXBwaW5nICptYXAgPSBzb2NrX21hcDsKKworCWlm IChtYXAgPT0gTlVMTCkKKwkJcmV0dXJuIElSUV9IQU5ETEVEOworCisJd2FrZV91cF9pbnRlcnJ1 cHRpYmxlKCZtYXAtPmFjdGl2ZS5pbmZsaWdodF9jb25uX3JlcSk7CisKKwlyZXR1cm4gSVJRX0hB TkRMRUQ7Cit9CisKIGludCBwdmNhbGxzX2Zyb250X3NvY2tldChzdHJ1Y3Qgc29ja2V0ICpzb2Nr KQogewogCXN0cnVjdCBwdmNhbGxzX2JlZGF0YSAqYmVkYXRhOwpAQCAtMTkxLDYgKzIxOSwxMzMg QEAgaW50IHB2Y2FsbHNfZnJvbnRfc29ja2V0KHN0cnVjdCBzb2NrZXQgKnNvY2spCiAJcmV0dXJu IHJldDsKIH0KIAorc3RhdGljIGludCBjcmVhdGVfYWN0aXZlKHN0cnVjdCBzb2NrX21hcHBpbmcg Km1hcCwgaW50ICpldnRjaG4pCit7CisJdm9pZCAqYnl0ZXM7CisJaW50IHJldCA9IC1FTk9NRU0s IGlycSA9IC0xLCBpOworCisJKmV2dGNobiA9IC0xOworCWluaXRfd2FpdHF1ZXVlX2hlYWQoJm1h cC0+YWN0aXZlLmluZmxpZ2h0X2Nvbm5fcmVxKTsKKworCW1hcC0+YWN0aXZlLnJpbmcgPSAoc3Ry dWN0IHB2Y2FsbHNfZGF0YV9pbnRmICopCisJCV9fZ2V0X2ZyZWVfcGFnZShHRlBfS0VSTkVMIHwg X19HRlBfWkVSTyk7CisJaWYgKG1hcC0+YWN0aXZlLnJpbmcgPT0gTlVMTCkKKwkJZ290byBvdXRf ZXJyb3I7CisJbWFwLT5hY3RpdmUucmluZy0+cmluZ19vcmRlciA9IFBWQ0FMTFNfUklOR19PUkRF UjsKKwlieXRlcyA9ICh2b2lkICopX19nZXRfZnJlZV9wYWdlcyhHRlBfS0VSTkVMIHwgX19HRlBf WkVSTywKKwkJCQkJUFZDQUxMU19SSU5HX09SREVSKTsKKwlpZiAoYnl0ZXMgPT0gTlVMTCkKKwkJ Z290byBvdXRfZXJyb3I7CisJZm9yIChpID0gMDsgaSA8ICgxIDw8IFBWQ0FMTFNfUklOR19PUkRF Uik7IGkrKykKKwkJbWFwLT5hY3RpdmUucmluZy0+cmVmW2ldID0gZ250dGFiX2dyYW50X2ZvcmVp Z25fYWNjZXNzKAorCQkJcHZjYWxsc19mcm9udF9kZXYtPm90aGVyZW5kX2lkLAorCQkJcGZuX3Rv X2dmbih2aXJ0X3RvX3BmbihieXRlcykgKyBpKSwgMCk7CisKKwltYXAtPmFjdGl2ZS5yZWYgPSBn bnR0YWJfZ3JhbnRfZm9yZWlnbl9hY2Nlc3MoCisJCXB2Y2FsbHNfZnJvbnRfZGV2LT5vdGhlcmVu ZF9pZCwKKwkJcGZuX3RvX2dmbih2aXJ0X3RvX3Bmbigodm9pZCAqKW1hcC0+YWN0aXZlLnJpbmcp KSwgMCk7CisKKwltYXAtPmFjdGl2ZS5kYXRhLmluID0gYnl0ZXM7CisJbWFwLT5hY3RpdmUuZGF0 YS5vdXQgPSBieXRlcyArCisJCVhFTl9GTEVYX1JJTkdfU0laRShQVkNBTExTX1JJTkdfT1JERVIp OworCisJcmV0ID0geGVuYnVzX2FsbG9jX2V2dGNobihwdmNhbGxzX2Zyb250X2RldiwgZXZ0Y2hu KTsKKwlpZiAocmV0KQorCQlnb3RvIG91dF9lcnJvcjsKKwlpcnEgPSBiaW5kX2V2dGNobl90b19p cnFoYW5kbGVyKCpldnRjaG4sIHB2Y2FsbHNfZnJvbnRfY29ubl9oYW5kbGVyLAorCQkJCQkwLCAi cHZjYWxscy1mcm9udGVuZCIsIG1hcCk7CisJaWYgKGlycSA8IDApIHsKKwkJcmV0ID0gaXJxOwor CQlnb3RvIG91dF9lcnJvcjsKKwl9CisKKwltYXAtPmFjdGl2ZS5pcnEgPSBpcnE7CisJbWFwLT5h Y3RpdmVfc29ja2V0ID0gdHJ1ZTsKKwltdXRleF9pbml0KCZtYXAtPmFjdGl2ZS5pbl9tdXRleCk7 CisJbXV0ZXhfaW5pdCgmbWFwLT5hY3RpdmUub3V0X211dGV4KTsKKworCXJldHVybiAwOworCitv dXRfZXJyb3I6CisJaWYgKGlycSA+PSAwKQorCQl1bmJpbmRfZnJvbV9pcnFoYW5kbGVyKGlycSwg bWFwKTsKKwllbHNlIGlmICgqZXZ0Y2huID49IDApCisJCXhlbmJ1c19mcmVlX2V2dGNobihwdmNh bGxzX2Zyb250X2RldiwgKmV2dGNobik7CisJa2ZyZWUobWFwLT5hY3RpdmUuZGF0YS5pbik7CisJ a2ZyZWUobWFwLT5hY3RpdmUucmluZyk7CisJcmV0dXJuIHJldDsKK30KKworaW50IHB2Y2FsbHNf ZnJvbnRfY29ubmVjdChzdHJ1Y3Qgc29ja2V0ICpzb2NrLCBzdHJ1Y3Qgc29ja2FkZHIgKmFkZHIs CisJCQkJaW50IGFkZHJfbGVuLCBpbnQgZmxhZ3MpCit7CisJc3RydWN0IHB2Y2FsbHNfYmVkYXRh ICpiZWRhdGE7CisJc3RydWN0IHNvY2tfbWFwcGluZyAqbWFwID0gTlVMTDsKKwlzdHJ1Y3QgeGVu X3B2Y2FsbHNfcmVxdWVzdCAqcmVxOworCWludCBub3RpZnksIHJlcV9pZCwgcmV0LCBldnRjaG47 CisKKwlwdmNhbGxzX2VudGVyOworCWlmICghcHZjYWxsc19mcm9udF9kZXYpIHsKKwkJcHZjYWxs c19leGl0OworCQlyZXR1cm4gLUVORVRVTlJFQUNIOworCX0KKwlpZiAoYWRkci0+c2FfZmFtaWx5 ICE9IEFGX0lORVQgfHwgc29jay0+dHlwZSAhPSBTT0NLX1NUUkVBTSkgeworCQlwdmNhbGxzX2V4 aXQ7CisJCXJldHVybiAtRU5PVFNVUFA7CisJfQorCisJYmVkYXRhID0gZGV2X2dldF9kcnZkYXRh KCZwdmNhbGxzX2Zyb250X2Rldi0+ZGV2KTsKKworCW1hcCA9IChzdHJ1Y3Qgc29ja19tYXBwaW5n ICopIHNvY2stPnNrLT5za19zZW5kX2hlYWQ7CisJaWYgKCFtYXApIHsKKwkJcHZjYWxsc19leGl0 OworCQlyZXR1cm4gLUVOT1RTT0NLOworCX0KKworCXNwaW5fbG9jaygmYmVkYXRhLT5zb2NrZXRf bG9jayk7CisJcmV0ID0gZ2V0X3JlcXVlc3QoYmVkYXRhLCAmcmVxX2lkKTsKKwlpZiAocmV0IDwg MCkgeworCQlzcGluX3VubG9jaygmYmVkYXRhLT5zb2NrZXRfbG9jayk7CisJCXB2Y2FsbHNfZXhp dDsKKwkJcmV0dXJuIHJldDsKKwl9CisJcmV0ID0gY3JlYXRlX2FjdGl2ZShtYXAsICZldnRjaG4p OworCWlmIChyZXQgPCAwKSB7CisJCXNwaW5fdW5sb2NrKCZiZWRhdGEtPnNvY2tldF9sb2NrKTsK KwkJcHZjYWxsc19leGl0OworCQlyZXR1cm4gcmV0OworCX0KKworCXJlcSA9IFJJTkdfR0VUX1JF UVVFU1QoJmJlZGF0YS0+cmluZywgcmVxX2lkKTsKKwlyZXEtPnJlcV9pZCA9IHJlcV9pZDsKKwly ZXEtPmNtZCA9IFBWQ0FMTFNfQ09OTkVDVDsKKwlyZXEtPnUuY29ubmVjdC5pZCA9ICh1aW50NjRf dCltYXA7CisJbWVtY3B5KHJlcS0+dS5jb25uZWN0LmFkZHIsIGFkZHIsIHNpemVvZigqYWRkcikp OworCXJlcS0+dS5jb25uZWN0LmxlbiA9IGFkZHJfbGVuOworCXJlcS0+dS5jb25uZWN0LmZsYWdz ID0gZmxhZ3M7CisJcmVxLT51LmNvbm5lY3QucmVmID0gbWFwLT5hY3RpdmUucmVmOworCXJlcS0+ dS5jb25uZWN0LmV2dGNobiA9IGV2dGNobjsKKworCW1hcC0+c29jayA9IHNvY2s7CisKKwliZWRh dGEtPnJpbmcucmVxX3Byb2RfcHZ0Kys7CisJUklOR19QVVNIX1JFUVVFU1RTX0FORF9DSEVDS19O T1RJRlkoJmJlZGF0YS0+cmluZywgbm90aWZ5KTsKKwlzcGluX3VubG9jaygmYmVkYXRhLT5zb2Nr ZXRfbG9jayk7CisKKwlpZiAobm90aWZ5KQorCQlub3RpZnlfcmVtb3RlX3ZpYV9pcnEoYmVkYXRh LT5pcnEpOworCisJd2FpdF9ldmVudChiZWRhdGEtPmluZmxpZ2h0X3JlcSwKKwkJICAgUkVBRF9P TkNFKGJlZGF0YS0+cnNwW3JlcV9pZF0ucmVxX2lkKSA9PSByZXFfaWQpOworCisJcmV0ID0gYmVk YXRhLT5yc3BbcmVxX2lkXS5yZXQ7CisJLyogcmVhZCByZXQsIHRoZW4gc2V0IHRoaXMgcnNwIHNs b3QgdG8gYmUgcmV1c2VkICovCisJc21wX21iKCk7CisJV1JJVEVfT05DRShiZWRhdGEtPnJzcFty ZXFfaWRdLnJlcV9pZCwgUFZDQUxMU19JTlZBTElEX0lEKTsKKwlwdmNhbGxzX2V4aXQ7CisJcmV0 dXJuIHJldDsKK30KKwogc3RhdGljIGNvbnN0IHN0cnVjdCB4ZW5idXNfZGV2aWNlX2lkIHB2Y2Fs bHNfZnJvbnRfaWRzW10gPSB7CiAJeyAicHZjYWxscyIgfSwKIAl7ICIiIH0KQEAgLTIwNyw2ICsz NjIsMTQgQEAgc3RhdGljIGludCBwdmNhbGxzX2Zyb250X3JlbW92ZShzdHJ1Y3QgeGVuYnVzX2Rl dmljZSAqZGV2KQogCWlmIChiZWRhdGEtPmlycSA+PSAwKQogCQl1bmJpbmRfZnJvbV9pcnFoYW5k bGVyKGJlZGF0YS0+aXJxLCBkZXYpOwogCisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKG1hcCwg biwgJmJlZGF0YS0+c29ja2V0X21hcHBpbmdzLCBsaXN0KSB7CisJCW1hcC0+c29jay0+c2stPnNr X3NlbmRfaGVhZCA9IE5VTEw7CisJCWlmIChtYXAtPmFjdGl2ZV9zb2NrZXQpIHsKKwkJCW1hcC0+ YWN0aXZlLnJpbmctPmluX2Vycm9yID0gLUVCQURGOworCQkJd2FrZV91cF9pbnRlcnJ1cHRpYmxl KCZtYXAtPmFjdGl2ZS5pbmZsaWdodF9jb25uX3JlcSk7CisJCX0KKwl9CisKIAlzbXBfbWIoKTsK IAl3aGlsZSAoYXRvbWljX3JlYWQoJnB2Y2FsbHNfcmVmY291bnQpID4gMCkKIAkJY3B1X3JlbGF4 KCk7CmRpZmYgLS1naXQgYS9kcml2ZXJzL3hlbi9wdmNhbGxzLWZyb250LmggYi9kcml2ZXJzL3hl bi9wdmNhbGxzLWZyb250LmgKaW5kZXggYjdkYWJlZC4uNjNiMDQxNyAxMDA2NDQKLS0tIGEvZHJp dmVycy94ZW4vcHZjYWxscy1mcm9udC5oCisrKyBiL2RyaXZlcnMveGVuL3B2Y2FsbHMtZnJvbnQu aApAQCAtNCw1ICs0LDcgQEAKICNpbmNsdWRlIDxsaW51eC9uZXQuaD4KIAogaW50IHB2Y2FsbHNf ZnJvbnRfc29ja2V0KHN0cnVjdCBzb2NrZXQgKnNvY2spOworaW50IHB2Y2FsbHNfZnJvbnRfY29u bmVjdChzdHJ1Y3Qgc29ja2V0ICpzb2NrLCBzdHJ1Y3Qgc29ja2FkZHIgKmFkZHIsCisJCQkgIGlu dCBhZGRyX2xlbiwgaW50IGZsYWdzKTsKIAogI2VuZGlmCi0tIAoxLjkuMQoKCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fClhlbi1kZXZlbCBtYWlsaW5nIGxp c3QKWGVuLWRldmVsQGxpc3RzLnhlbi5vcmcKaHR0cHM6Ly9saXN0cy54ZW4ub3JnL3hlbi1kZXZl bAo=