From mboxrd@z Thu Jan 1 00:00:00 1970 From: rmallon@gmail.com (Ryan Mallon) Date: Tue, 02 Apr 2013 10:36:43 +1100 Subject: [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping In-Reply-To: <1364858565-17192-3-git-send-email-alex@digriz.org.uk> References: <1364858565-17192-1-git-send-email-alex@digriz.org.uk> <1364858565-17192-3-git-send-email-alex@digriz.org.uk> Message-ID: <515A1A0B.8040803@gmail.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On 02/04/13 10:22, Alexander Clouter wrote: > If platform_data is not defined (as before), then named memory io > ranges need to be defined ("rtc_index" and "rtc_data"). The driver > then maps those regions and uses them as the RTC index and data > addresses. > > Does compile with the following warnings, I cannot see the codepath > affected myself: > ---- > drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?: > drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used uninitialized in this function > drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used uninitialized in this function It is caused by the exit paths. If pdev->dev.platform_data is set, the res_index and res_data are never initialised, but in the error case you still for rtc_device_register you jump to out_io_data, which will then dereference res_index/res_data. You need to make the exit paths conditional on pdev->dev.platform_data (or init res_index/data to NULL and make the release_mem_regions conditional on that). ~Ryan > ---- > > Signed-off-by: Alexander Clouter > --- > drivers/rtc/rtc-m48t86.c | 230 ++++++++++++++++++++++++++++++++++------------ > 1 file changed, 173 insertions(+), 57 deletions(-) > > diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c > index 25e0116..6f99e64 100644 > --- a/drivers/rtc/rtc-m48t86.c > +++ b/drivers/rtc/rtc-m48t86.c > @@ -18,6 +18,8 @@ > #include > #include > #include > +#include > +#include > > #define M48T86_REG_SEC 0x00 > #define M48T86_REG_SECALRM 0x01 > @@ -41,40 +43,71 @@ > > #define DRV_VERSION "0.1" > > +struct m48t86_rtc_private_data { > + void __iomem *io_index; > + void __iomem *io_data; > + > + struct rtc_device *rtc; > + struct m48t86_ops *ops; > +}; > + > +static void m48t86_rtc_writebyte(struct device *dev, > + unsigned char value, unsigned long addr) > +{ > + struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev); > + > + if (priv->ops) { > + priv->ops->writebyte(value, addr); > + return; > + } > + > + writeb(addr, priv->io_index); > + writeb(value, priv->io_data); > +} > + > +static unsigned char m48t86_rtc_readbyte(struct device *dev, > + unsigned long addr) > +{ > + struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev); > + > + if (priv->ops) > + return priv->ops->readbyte(addr); > + > + writeb(addr, priv->io_index); > + return readb(priv->io_data); > +} > > static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) > { > unsigned char reg; > - struct platform_device *pdev = to_platform_device(dev); > - struct m48t86_ops *ops = pdev->dev.platform_data; > > - reg = ops->readbyte(M48T86_REG_B); > + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B); > > if (reg & M48T86_REG_B_DM) { > /* data (binary) mode */ > - tm->tm_sec = ops->readbyte(M48T86_REG_SEC); > - tm->tm_min = ops->readbyte(M48T86_REG_MIN); > - tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F; > - tm->tm_mday = ops->readbyte(M48T86_REG_DOM); > + tm->tm_sec = m48t86_rtc_readbyte(dev, M48T86_REG_SEC); > + tm->tm_min = m48t86_rtc_readbyte(dev, M48T86_REG_MIN); > + tm->tm_hour = m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F; > + tm->tm_mday = m48t86_rtc_readbyte(dev, M48T86_REG_DOM); > /* tm_mon is 0-11 */ > - tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1; > - tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100; > - tm->tm_wday = ops->readbyte(M48T86_REG_DOW); > + tm->tm_mon = m48t86_rtc_readbyte(dev, M48T86_REG_MONTH) - 1; > + tm->tm_year = m48t86_rtc_readbyte(dev, M48T86_REG_YEAR) + 100; > + tm->tm_wday = m48t86_rtc_readbyte(dev, M48T86_REG_DOW); > } else { > /* bcd mode */ > - tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC)); > - tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN)); > - tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F); > - tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM)); > + tm->tm_sec = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_SEC)); > + tm->tm_min = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MIN)); > + tm->tm_hour = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F); > + tm->tm_mday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOM)); > /* tm_mon is 0-11 */ > - tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1; > - tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100; > - tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW)); > + tm->tm_mon = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MONTH)) - 1; > + tm->tm_year = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_YEAR)) + 100; > + tm->tm_wday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOW)); > } > > /* correct the hour if the clock is in 12h mode */ > if (!(reg & M48T86_REG_B_H24)) > - if (ops->readbyte(M48T86_REG_HOUR) & 0x80) > + if (m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x80) > tm->tm_hour += 12; > > return rtc_valid_tm(tm); > @@ -83,38 +116,36 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) > static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) > { > unsigned char reg; > - struct platform_device *pdev = to_platform_device(dev); > - struct m48t86_ops *ops = pdev->dev.platform_data; > > - reg = ops->readbyte(M48T86_REG_B); > + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B); > > /* update flag and 24h mode */ > reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; > - ops->writebyte(reg, M48T86_REG_B); > + m48t86_rtc_writebyte(dev, reg, M48T86_REG_B); > > if (reg & M48T86_REG_B_DM) { > /* data (binary) mode */ > - ops->writebyte(tm->tm_sec, M48T86_REG_SEC); > - ops->writebyte(tm->tm_min, M48T86_REG_MIN); > - ops->writebyte(tm->tm_hour, M48T86_REG_HOUR); > - ops->writebyte(tm->tm_mday, M48T86_REG_DOM); > - ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH); > - ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR); > - ops->writebyte(tm->tm_wday, M48T86_REG_DOW); > + m48t86_rtc_writebyte(dev, tm->tm_sec, M48T86_REG_SEC); > + m48t86_rtc_writebyte(dev, tm->tm_min, M48T86_REG_MIN); > + m48t86_rtc_writebyte(dev, tm->tm_hour, M48T86_REG_HOUR); > + m48t86_rtc_writebyte(dev, tm->tm_mday, M48T86_REG_DOM); > + m48t86_rtc_writebyte(dev, tm->tm_mon + 1, M48T86_REG_MONTH); > + m48t86_rtc_writebyte(dev, tm->tm_year % 100, M48T86_REG_YEAR); > + m48t86_rtc_writebyte(dev, tm->tm_wday, M48T86_REG_DOW); > } else { > /* bcd mode */ > - ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC); > - ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN); > - ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR); > - ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM); > - ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH); > - ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR); > - ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_sec), M48T86_REG_SEC); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_min), M48T86_REG_MIN); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_hour), M48T86_REG_HOUR); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mday), M48T86_REG_DOM); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR); > + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_wday), M48T86_REG_DOW); > } > > /* update ended */ > reg &= ~M48T86_REG_B_SET; > - ops->writebyte(reg, M48T86_REG_B); > + m48t86_rtc_writebyte(dev, reg, M48T86_REG_B); > > return 0; > } > @@ -122,15 +153,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) > static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) > { > unsigned char reg; > - struct platform_device *pdev = to_platform_device(dev); > - struct m48t86_ops *ops = pdev->dev.platform_data; > > - reg = ops->readbyte(M48T86_REG_B); > + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B); > > seq_printf(seq, "mode\t\t: %s\n", > (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); > > - reg = ops->readbyte(M48T86_REG_D); > + reg = m48t86_rtc_readbyte(dev, M48T86_REG_D); > > seq_printf(seq, "battery\t\t: %s\n", > (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); > @@ -144,34 +173,121 @@ static const struct rtc_class_ops m48t86_rtc_ops = { > .proc = m48t86_rtc_proc, > }; > > -static int m48t86_rtc_probe(struct platform_device *dev) > +static int m48t86_rtc_probe(struct platform_device *pdev) > { > unsigned char reg; > - struct m48t86_ops *ops = dev->dev.platform_data; > - struct rtc_device *rtc = rtc_device_register("m48t86", > - &dev->dev, &m48t86_rtc_ops, THIS_MODULE); > - > - if (IS_ERR(rtc)) > - return PTR_ERR(rtc); > - > - platform_set_drvdata(dev, rtc); > + int err; > + struct resource *res_index, *res_data; > + struct m48t86_rtc_private_data *priv; > + > + /* Allocate memory for the device structure (and zero it) */ > + priv = kzalloc(sizeof(struct m48t86_rtc_private_data), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, priv); > + > + if (!pdev->dev.platform_data) { > + res_index = platform_get_resource_byname( > + pdev, IORESOURCE_MEM, "rtc_index"); > + if (!res_index) { > + err = -ENXIO; > + goto out_free; > + } > + > + res_data = platform_get_resource_byname( > + pdev, IORESOURCE_MEM, "rtc_data"); > + if (!res_data) { > + err = -ENXIO; > + goto out_free; > + } > + > + if (!request_mem_region(res_index->start, > + resource_size(res_index), > + dev_name(&pdev->dev))) { > + err = -EBUSY; > + goto out_free; > + } > + > + if (!request_mem_region(res_data->start, > + resource_size(res_data), > + dev_name(&pdev->dev))) { > + err = -EBUSY; > + goto out_release_index; > + } > + > + priv->io_index = ioremap(res_index->start, > + resource_size(res_index)); > + if (!priv->io_index) { > + err = -EIO; > + goto out_release_data; > + } > + > + priv->io_data = ioremap(res_data->start, > + resource_size(res_data)); > + if (!priv->io_data) { > + err = -EIO; > + goto out_io_index; > + } > + } else > + priv->ops = pdev->dev.platform_data; > + > + priv->rtc = rtc_device_register("m48t86", > + &pdev->dev, &m48t86_rtc_ops, THIS_MODULE); > + if (IS_ERR(priv->rtc)) { > + err = PTR_ERR(priv->rtc); > + if (!pdev->dev.platform_data) > + goto out_io_data; > + else > + goto out_free; > + } > > /* read battery status */ > - reg = ops->readbyte(M48T86_REG_D); > - dev_info(&dev->dev, "battery %s\n", > + reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D); > + dev_info(&pdev->dev, "battery %s\n", > (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); > > return 0; > + > +out_io_data: > + iounmap(priv->io_data); > +out_io_index: > + iounmap(priv->io_index); > +out_release_data: > + release_mem_region(res_data->start, resource_size(res_data)); > +out_release_index: > + release_mem_region(res_index->start, resource_size(res_index)); > +out_free: > + platform_set_drvdata(pdev, NULL); > + kfree(priv); > + return err; > } > > -static int m48t86_rtc_remove(struct platform_device *dev) > +static int m48t86_rtc_remove(struct platform_device *pdev) > { > - struct rtc_device *rtc = platform_get_drvdata(dev); > + struct resource *res; > + struct m48t86_rtc_private_data *priv = platform_get_drvdata(pdev); > + > + if (priv->rtc) > + rtc_device_unregister(priv->rtc); > + > + if (priv->io_data) { > + iounmap(priv->io_data); > + res = platform_get_resource_byname( > + pdev, IORESOURCE_MEM, "rtc_data"); > + release_mem_region(res->start, resource_size(res)); > + } > + > + if (priv->io_index) { > + iounmap(priv->io_index); > + res = platform_get_resource_byname( > + pdev, IORESOURCE_MEM, "rtc_index"); > + release_mem_region(res->start, resource_size(res)); > + } > > - if (rtc) > - rtc_device_unregister(rtc); > + platform_set_drvdata(pdev, NULL); > > - platform_set_drvdata(dev, NULL); > + kfree(priv); > > return 0; > } > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ryan Mallon Subject: Re: [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Date: Tue, 02 Apr 2013 10:36:43 +1100 Message-ID: <515A1A0B.8040803@gmail.com> References: <1364858565-17192-1-git-send-email-alex@digriz.org.uk> <1364858565-17192-3-git-send-email-alex@digriz.org.uk> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1364858565-17192-3-git-send-email-alex-L4GPcECwBoDe9xe1eoZjHA@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: devicetree-discuss-bounces+gldd-devicetree-discuss=m.gmane.org-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org Sender: "devicetree-discuss" To: Alexander Clouter Cc: Alessandro Zummo , Jason Cooper , rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org, Andrew Lunn , devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org, Rob Herring , Hartley Sweeten , linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org List-Id: devicetree@vger.kernel.org T24gMDIvMDQvMTMgMTA6MjIsIEFsZXhhbmRlciBDbG91dGVyIHdyb3RlOgo+IElmIHBsYXRmb3Jt X2RhdGEgaXMgbm90IGRlZmluZWQgKGFzIGJlZm9yZSksIHRoZW4gbmFtZWQgbWVtb3J5IGlvCj4g cmFuZ2VzIG5lZWQgdG8gYmUgZGVmaW5lZCAoInJ0Y19pbmRleCIgYW5kICJydGNfZGF0YSIpLiAg VGhlIGRyaXZlcgo+IHRoZW4gbWFwcyB0aG9zZSByZWdpb25zIGFuZCB1c2VzIHRoZW0gYXMgdGhl IFJUQyBpbmRleCBhbmQgZGF0YQo+IGFkZHJlc3Nlcy4KPiAKPiBEb2VzIGNvbXBpbGUgd2l0aCB0 aGUgZm9sbG93aW5nIHdhcm5pbmdzLCBJIGNhbm5vdCBzZWUgdGhlIGNvZGVwYXRoCj4gYWZmZWN0 ZWQgbXlzZWxmOgo+IC0tLS0KPiBkcml2ZXJzL3J0Yy9ydGMtbTQ4dDg2LmM6IEluIGZ1bmN0aW9u IOKAmG00OHQ4Nl9ydGNfcHJvYmXigJk6Cj4gZHJpdmVycy9ydGMvcnRjLW00OHQ4Ni5jOjE4MDog d2FybmluZzog4oCYcmVzX2luZGV44oCZIG1heSBiZSB1c2VkIHVuaW5pdGlhbGl6ZWQgaW4gdGhp cyBmdW5jdGlvbgo+IGRyaXZlcnMvcnRjL3J0Yy1tNDh0ODYuYzoxODA6IHdhcm5pbmc6IOKAmHJl c19kYXRh4oCZIG1heSBiZSB1c2VkIHVuaW5pdGlhbGl6ZWQgaW4gdGhpcyBmdW5jdGlvbgoKSXQg aXMgY2F1c2VkIGJ5IHRoZSBleGl0IHBhdGhzLiBJZiBwZGV2LT5kZXYucGxhdGZvcm1fZGF0YSBp cyBzZXQsIHRoZQpyZXNfaW5kZXggYW5kIHJlc19kYXRhIGFyZSBuZXZlciBpbml0aWFsaXNlZCwg YnV0IGluIHRoZSBlcnJvciBjYXNlIHlvdQpzdGlsbCBmb3IgcnRjX2RldmljZV9yZWdpc3RlciB5 b3UganVtcCB0byBvdXRfaW9fZGF0YSwgd2hpY2ggd2lsbCB0aGVuCmRlcmVmZXJlbmNlIHJlc19p bmRleC9yZXNfZGF0YS4gWW91IG5lZWQgdG8gbWFrZSB0aGUgZXhpdCBwYXRocwpjb25kaXRpb25h bCBvbiBwZGV2LT5kZXYucGxhdGZvcm1fZGF0YSAob3IgaW5pdCByZXNfaW5kZXgvZGF0YSB0byBO VUxMCmFuZCBtYWtlIHRoZSByZWxlYXNlX21lbV9yZWdpb25zIGNvbmRpdGlvbmFsIG9uIHRoYXQp LgoKflJ5YW4KCj4gLS0tLQo+IAo+IFNpZ25lZC1vZmYtYnk6IEFsZXhhbmRlciBDbG91dGVyIDxh bGV4QGRpZ3Jpei5vcmcudWs+Cj4gLS0tCj4gIGRyaXZlcnMvcnRjL3J0Yy1tNDh0ODYuYyB8ICAy MzAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tLS0tLS0tLS0tLQo+ICAxIGZp bGUgY2hhbmdlZCwgMTczIGluc2VydGlvbnMoKyksIDU3IGRlbGV0aW9ucygtKQo+IAo+IGRpZmYg LS1naXQgYS9kcml2ZXJzL3J0Yy9ydGMtbTQ4dDg2LmMgYi9kcml2ZXJzL3J0Yy9ydGMtbTQ4dDg2 LmMKPiBpbmRleCAyNWUwMTE2Li42Zjk5ZTY0IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvcnRjL3J0 Yy1tNDh0ODYuYwo+ICsrKyBiL2RyaXZlcnMvcnRjL3J0Yy1tNDh0ODYuYwo+IEBAIC0xOCw2ICsx OCw4IEBACj4gICNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPiAgI2luY2x1ZGUg PGxpbnV4L3BsYXRmb3JtX2RhdGEvcnRjLW00OHQ4Ni5oPgo+ICAjaW5jbHVkZSA8bGludXgvYmNk Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+ ICAKPiAgI2RlZmluZSBNNDhUODZfUkVHX1NFQwkJMHgwMAo+ICAjZGVmaW5lIE00OFQ4Nl9SRUdf U0VDQUxSTQkweDAxCj4gQEAgLTQxLDQwICs0Myw3MSBAQAo+ICAKPiAgI2RlZmluZSBEUlZfVkVS U0lPTiAiMC4xIgo+ICAKPiArc3RydWN0IG00OHQ4Nl9ydGNfcHJpdmF0ZV9kYXRhIHsKPiArCXZv aWQgX19pb21lbQkJKmlvX2luZGV4Owo+ICsJdm9pZCBfX2lvbWVtCQkqaW9fZGF0YTsKPiArCj4g KwlzdHJ1Y3QgcnRjX2RldmljZQkqcnRjOwo+ICsJc3RydWN0IG00OHQ4Nl9vcHMJKm9wczsKPiAr fTsKPiArCj4gK3N0YXRpYyB2b2lkIG00OHQ4Nl9ydGNfd3JpdGVieXRlKHN0cnVjdCBkZXZpY2Ug KmRldiwKPiArCQkJdW5zaWduZWQgY2hhciB2YWx1ZSwgdW5zaWduZWQgbG9uZyBhZGRyKQo+ICt7 Cj4gKwlzdHJ1Y3QgbTQ4dDg2X3J0Y19wcml2YXRlX2RhdGEgKnByaXYgPSBkZXZfZ2V0X2RydmRh dGEoZGV2KTsKPiArCj4gKwlpZiAocHJpdi0+b3BzKSB7Cj4gKwkJcHJpdi0+b3BzLT53cml0ZWJ5 dGUodmFsdWUsIGFkZHIpOwo+ICsJCXJldHVybjsKPiArCX0KPiArCj4gKwl3cml0ZWIoYWRkciwg cHJpdi0+aW9faW5kZXgpOwo+ICsJd3JpdGViKHZhbHVlLCBwcml2LT5pb19kYXRhKTsKPiArfQo+ ICsKPiArc3RhdGljIHVuc2lnbmVkIGNoYXIgbTQ4dDg2X3J0Y19yZWFkYnl0ZShzdHJ1Y3QgZGV2 aWNlICpkZXYsCj4gKwkJCXVuc2lnbmVkIGxvbmcgYWRkcikKPiArewo+ICsJc3RydWN0IG00OHQ4 Nl9ydGNfcHJpdmF0ZV9kYXRhICpwcml2ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsJ aWYgKHByaXYtPm9wcykKPiArCQlyZXR1cm4gcHJpdi0+b3BzLT5yZWFkYnl0ZShhZGRyKTsKPiAr Cj4gKwl3cml0ZWIoYWRkciwgcHJpdi0+aW9faW5kZXgpOwo+ICsJcmV0dXJuIHJlYWRiKHByaXYt PmlvX2RhdGEpOwo+ICt9Cj4gIAo+ICBzdGF0aWMgaW50IG00OHQ4Nl9ydGNfcmVhZF90aW1lKHN0 cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHJ0Y190aW1lICp0bSkKPiAgewo+ICAJdW5zaWduZWQg Y2hhciByZWc7Cj4gLQlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2ID0gdG9fcGxhdGZvcm1f ZGV2aWNlKGRldik7Cj4gLQlzdHJ1Y3QgbTQ4dDg2X29wcyAqb3BzID0gcGRldi0+ZGV2LnBsYXRm b3JtX2RhdGE7Cj4gIAo+IC0JcmVnID0gb3BzLT5yZWFkYnl0ZShNNDhUODZfUkVHX0IpOwo+ICsJ cmVnID0gbTQ4dDg2X3J0Y19yZWFkYnl0ZShkZXYsIE00OFQ4Nl9SRUdfQik7Cj4gIAo+ICAJaWYg KHJlZyAmIE00OFQ4Nl9SRUdfQl9ETSkgewo+ICAJCS8qIGRhdGEgKGJpbmFyeSkgbW9kZSAqLwo+ IC0JCXRtLT50bV9zZWMJPSBvcHMtPnJlYWRieXRlKE00OFQ4Nl9SRUdfU0VDKTsKPiAtCQl0bS0+ dG1fbWluCT0gb3BzLT5yZWFkYnl0ZShNNDhUODZfUkVHX01JTik7Cj4gLQkJdG0tPnRtX2hvdXIJ PSBvcHMtPnJlYWRieXRlKE00OFQ4Nl9SRUdfSE9VUikgJiAweDNGOwo+IC0JCXRtLT50bV9tZGF5 CT0gb3BzLT5yZWFkYnl0ZShNNDhUODZfUkVHX0RPTSk7Cj4gKwkJdG0tPnRtX3NlYwk9IG00OHQ4 Nl9ydGNfcmVhZGJ5dGUoZGV2LCBNNDhUODZfUkVHX1NFQyk7Cj4gKwkJdG0tPnRtX21pbgk9IG00 OHQ4Nl9ydGNfcmVhZGJ5dGUoZGV2LCBNNDhUODZfUkVHX01JTik7Cj4gKwkJdG0tPnRtX2hvdXIJ PSBtNDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4VDg2X1JFR19IT1VSKSAmIDB4M0Y7Cj4gKwkJ dG0tPnRtX21kYXkJPSBtNDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4VDg2X1JFR19ET00pOwo+ ICAJCS8qIHRtX21vbiBpcyAwLTExICovCj4gLQkJdG0tPnRtX21vbgk9IG9wcy0+cmVhZGJ5dGUo TTQ4VDg2X1JFR19NT05USCkgLSAxOwo+IC0JCXRtLT50bV95ZWFyCT0gb3BzLT5yZWFkYnl0ZShN NDhUODZfUkVHX1lFQVIpICsgMTAwOwo+IC0JCXRtLT50bV93ZGF5CT0gb3BzLT5yZWFkYnl0ZShN NDhUODZfUkVHX0RPVyk7Cj4gKwkJdG0tPnRtX21vbgk9IG00OHQ4Nl9ydGNfcmVhZGJ5dGUoZGV2 LCBNNDhUODZfUkVHX01PTlRIKSAtIDE7Cj4gKwkJdG0tPnRtX3llYXIJPSBtNDh0ODZfcnRjX3Jl YWRieXRlKGRldiwgTTQ4VDg2X1JFR19ZRUFSKSArIDEwMDsKPiArCQl0bS0+dG1fd2RheQk9IG00 OHQ4Nl9ydGNfcmVhZGJ5dGUoZGV2LCBNNDhUODZfUkVHX0RPVyk7Cj4gIAl9IGVsc2Ugewo+ICAJ CS8qIGJjZCBtb2RlICovCj4gLQkJdG0tPnRtX3NlYwk9IGJjZDJiaW4ob3BzLT5yZWFkYnl0ZShN NDhUODZfUkVHX1NFQykpOwo+IC0JCXRtLT50bV9taW4JPSBiY2QyYmluKG9wcy0+cmVhZGJ5dGUo TTQ4VDg2X1JFR19NSU4pKTsKPiAtCQl0bS0+dG1faG91cgk9IGJjZDJiaW4ob3BzLT5yZWFkYnl0 ZShNNDhUODZfUkVHX0hPVVIpICYgMHgzRik7Cj4gLQkJdG0tPnRtX21kYXkJPSBiY2QyYmluKG9w cy0+cmVhZGJ5dGUoTTQ4VDg2X1JFR19ET00pKTsKPiArCQl0bS0+dG1fc2VjCT0gYmNkMmJpbiht NDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4VDg2X1JFR19TRUMpKTsKPiArCQl0bS0+dG1fbWlu CT0gYmNkMmJpbihtNDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4VDg2X1JFR19NSU4pKTsKPiAr CQl0bS0+dG1faG91cgk9IGJjZDJiaW4obTQ4dDg2X3J0Y19yZWFkYnl0ZShkZXYsIE00OFQ4Nl9S RUdfSE9VUikgJiAweDNGKTsKPiArCQl0bS0+dG1fbWRheQk9IGJjZDJiaW4obTQ4dDg2X3J0Y19y ZWFkYnl0ZShkZXYsIE00OFQ4Nl9SRUdfRE9NKSk7Cj4gIAkJLyogdG1fbW9uIGlzIDAtMTEgKi8K PiAtCQl0bS0+dG1fbW9uCT0gYmNkMmJpbihvcHMtPnJlYWRieXRlKE00OFQ4Nl9SRUdfTU9OVEgp KSAtIDE7Cj4gLQkJdG0tPnRtX3llYXIJPSBiY2QyYmluKG9wcy0+cmVhZGJ5dGUoTTQ4VDg2X1JF R19ZRUFSKSkgKyAxMDA7Cj4gLQkJdG0tPnRtX3dkYXkJPSBiY2QyYmluKG9wcy0+cmVhZGJ5dGUo TTQ4VDg2X1JFR19ET1cpKTsKPiArCQl0bS0+dG1fbW9uCT0gYmNkMmJpbihtNDh0ODZfcnRjX3Jl YWRieXRlKGRldiwgTTQ4VDg2X1JFR19NT05USCkpIC0gMTsKPiArCQl0bS0+dG1feWVhcgk9IGJj ZDJiaW4obTQ4dDg2X3J0Y19yZWFkYnl0ZShkZXYsIE00OFQ4Nl9SRUdfWUVBUikpICsgMTAwOwo+ ICsJCXRtLT50bV93ZGF5CT0gYmNkMmJpbihtNDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4VDg2 X1JFR19ET1cpKTsKPiAgCX0KPiAgCj4gIAkvKiBjb3JyZWN0IHRoZSBob3VyIGlmIHRoZSBjbG9j ayBpcyBpbiAxMmggbW9kZSAqLwo+ICAJaWYgKCEocmVnICYgTTQ4VDg2X1JFR19CX0gyNCkpCj4g LQkJaWYgKG9wcy0+cmVhZGJ5dGUoTTQ4VDg2X1JFR19IT1VSKSAmIDB4ODApCj4gKwkJaWYgKG00 OHQ4Nl9ydGNfcmVhZGJ5dGUoZGV2LCBNNDhUODZfUkVHX0hPVVIpICYgMHg4MCkKPiAgCQkJdG0t PnRtX2hvdXIgKz0gMTI7Cj4gIAo+ICAJcmV0dXJuIHJ0Y192YWxpZF90bSh0bSk7Cj4gQEAgLTgz LDM4ICsxMTYsMzYgQEAgc3RhdGljIGludCBtNDh0ODZfcnRjX3JlYWRfdGltZShzdHJ1Y3QgZGV2 aWNlICpkZXYsIHN0cnVjdCBydGNfdGltZSAqdG0pCj4gIHN0YXRpYyBpbnQgbTQ4dDg2X3J0Y19z ZXRfdGltZShzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBydGNfdGltZSAqdG0pCj4gIHsKPiAg CXVuc2lnbmVkIGNoYXIgcmVnOwo+IC0Jc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiA9IHRv X3BsYXRmb3JtX2RldmljZShkZXYpOwo+IC0Jc3RydWN0IG00OHQ4Nl9vcHMgKm9wcyA9IHBkZXYt PmRldi5wbGF0Zm9ybV9kYXRhOwo+ICAKPiAtCXJlZyA9IG9wcy0+cmVhZGJ5dGUoTTQ4VDg2X1JF R19CKTsKPiArCXJlZyA9IG00OHQ4Nl9ydGNfcmVhZGJ5dGUoZGV2LCBNNDhUODZfUkVHX0IpOwo+ ICAKPiAgCS8qIHVwZGF0ZSBmbGFnIGFuZCAyNGggbW9kZSAqLwo+ICAJcmVnIHw9IE00OFQ4Nl9S RUdfQl9TRVQgfCBNNDhUODZfUkVHX0JfSDI0Owo+IC0Jb3BzLT53cml0ZWJ5dGUocmVnLCBNNDhU ODZfUkVHX0IpOwo+ICsJbTQ4dDg2X3J0Y193cml0ZWJ5dGUoZGV2LCByZWcsIE00OFQ4Nl9SRUdf Qik7Cj4gIAo+ICAJaWYgKHJlZyAmIE00OFQ4Nl9SRUdfQl9ETSkgewo+ICAJCS8qIGRhdGEgKGJp bmFyeSkgbW9kZSAqLwo+IC0JCW9wcy0+d3JpdGVieXRlKHRtLT50bV9zZWMsIE00OFQ4Nl9SRUdf U0VDKTsKPiAtCQlvcHMtPndyaXRlYnl0ZSh0bS0+dG1fbWluLCBNNDhUODZfUkVHX01JTik7Cj4g LQkJb3BzLT53cml0ZWJ5dGUodG0tPnRtX2hvdXIsIE00OFQ4Nl9SRUdfSE9VUik7Cj4gLQkJb3Bz LT53cml0ZWJ5dGUodG0tPnRtX21kYXksIE00OFQ4Nl9SRUdfRE9NKTsKPiAtCQlvcHMtPndyaXRl Ynl0ZSh0bS0+dG1fbW9uICsgMSwgTTQ4VDg2X1JFR19NT05USCk7Cj4gLQkJb3BzLT53cml0ZWJ5 dGUodG0tPnRtX3llYXIgJSAxMDAsIE00OFQ4Nl9SRUdfWUVBUik7Cj4gLQkJb3BzLT53cml0ZWJ5 dGUodG0tPnRtX3dkYXksIE00OFQ4Nl9SRUdfRE9XKTsKPiArCQltNDh0ODZfcnRjX3dyaXRlYnl0 ZShkZXYsIHRtLT50bV9zZWMsIE00OFQ4Nl9SRUdfU0VDKTsKPiArCQltNDh0ODZfcnRjX3dyaXRl Ynl0ZShkZXYsIHRtLT50bV9taW4sIE00OFQ4Nl9SRUdfTUlOKTsKPiArCQltNDh0ODZfcnRjX3dy aXRlYnl0ZShkZXYsIHRtLT50bV9ob3VyLCBNNDhUODZfUkVHX0hPVVIpOwo+ICsJCW00OHQ4Nl9y dGNfd3JpdGVieXRlKGRldiwgdG0tPnRtX21kYXksIE00OFQ4Nl9SRUdfRE9NKTsKPiArCQltNDh0 ODZfcnRjX3dyaXRlYnl0ZShkZXYsIHRtLT50bV9tb24gKyAxLCBNNDhUODZfUkVHX01PTlRIKTsK PiArCQltNDh0ODZfcnRjX3dyaXRlYnl0ZShkZXYsIHRtLT50bV95ZWFyICUgMTAwLCBNNDhUODZf UkVHX1lFQVIpOwo+ICsJCW00OHQ4Nl9ydGNfd3JpdGVieXRlKGRldiwgdG0tPnRtX3dkYXksIE00 OFQ4Nl9SRUdfRE9XKTsKPiAgCX0gZWxzZSB7Cj4gIAkJLyogYmNkIG1vZGUgKi8KPiAtCQlvcHMt PndyaXRlYnl0ZShiaW4yYmNkKHRtLT50bV9zZWMpLCBNNDhUODZfUkVHX1NFQyk7Cj4gLQkJb3Bz LT53cml0ZWJ5dGUoYmluMmJjZCh0bS0+dG1fbWluKSwgTTQ4VDg2X1JFR19NSU4pOwo+IC0JCW9w cy0+d3JpdGVieXRlKGJpbjJiY2QodG0tPnRtX2hvdXIpLCBNNDhUODZfUkVHX0hPVVIpOwo+IC0J CW9wcy0+d3JpdGVieXRlKGJpbjJiY2QodG0tPnRtX21kYXkpLCBNNDhUODZfUkVHX0RPTSk7Cj4g LQkJb3BzLT53cml0ZWJ5dGUoYmluMmJjZCh0bS0+dG1fbW9uICsgMSksIE00OFQ4Nl9SRUdfTU9O VEgpOwo+IC0JCW9wcy0+d3JpdGVieXRlKGJpbjJiY2QodG0tPnRtX3llYXIgJSAxMDApLCBNNDhU ODZfUkVHX1lFQVIpOwo+IC0JCW9wcy0+d3JpdGVieXRlKGJpbjJiY2QodG0tPnRtX3dkYXkpLCBN NDhUODZfUkVHX0RPVyk7Cj4gKwkJbTQ4dDg2X3J0Y193cml0ZWJ5dGUoZGV2LCBiaW4yYmNkKHRt LT50bV9zZWMpLCBNNDhUODZfUkVHX1NFQyk7Cj4gKwkJbTQ4dDg2X3J0Y193cml0ZWJ5dGUoZGV2 LCBiaW4yYmNkKHRtLT50bV9taW4pLCBNNDhUODZfUkVHX01JTik7Cj4gKwkJbTQ4dDg2X3J0Y193 cml0ZWJ5dGUoZGV2LCBiaW4yYmNkKHRtLT50bV9ob3VyKSwgTTQ4VDg2X1JFR19IT1VSKTsKPiAr CQltNDh0ODZfcnRjX3dyaXRlYnl0ZShkZXYsIGJpbjJiY2QodG0tPnRtX21kYXkpLCBNNDhUODZf UkVHX0RPTSk7Cj4gKwkJbTQ4dDg2X3J0Y193cml0ZWJ5dGUoZGV2LCBiaW4yYmNkKHRtLT50bV9t b24gKyAxKSwgTTQ4VDg2X1JFR19NT05USCk7Cj4gKwkJbTQ4dDg2X3J0Y193cml0ZWJ5dGUoZGV2 LCBiaW4yYmNkKHRtLT50bV95ZWFyICUgMTAwKSwgTTQ4VDg2X1JFR19ZRUFSKTsKPiArCQltNDh0 ODZfcnRjX3dyaXRlYnl0ZShkZXYsIGJpbjJiY2QodG0tPnRtX3dkYXkpLCBNNDhUODZfUkVHX0RP Vyk7Cj4gIAl9Cj4gIAo+ICAJLyogdXBkYXRlIGVuZGVkICovCj4gIAlyZWcgJj0gfk00OFQ4Nl9S RUdfQl9TRVQ7Cj4gLQlvcHMtPndyaXRlYnl0ZShyZWcsIE00OFQ4Nl9SRUdfQik7Cj4gKwltNDh0 ODZfcnRjX3dyaXRlYnl0ZShkZXYsIHJlZywgTTQ4VDg2X1JFR19CKTsKPiAgCj4gIAlyZXR1cm4g MDsKPiAgfQo+IEBAIC0xMjIsMTUgKzE1MywxMyBAQCBzdGF0aWMgaW50IG00OHQ4Nl9ydGNfc2V0 X3RpbWUoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgcnRjX3RpbWUgKnRtKQo+ICBzdGF0aWMg aW50IG00OHQ4Nl9ydGNfcHJvYyhzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBzZXFfZmlsZSAq c2VxKQo+ICB7Cj4gIAl1bnNpZ25lZCBjaGFyIHJlZzsKPiAtCXN0cnVjdCBwbGF0Zm9ybV9kZXZp Y2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UoZGV2KTsKPiAtCXN0cnVjdCBtNDh0ODZfb3Bz ICpvcHMgPSBwZGV2LT5kZXYucGxhdGZvcm1fZGF0YTsKPiAgCj4gLQlyZWcgPSBvcHMtPnJlYWRi eXRlKE00OFQ4Nl9SRUdfQik7Cj4gKwlyZWcgPSBtNDh0ODZfcnRjX3JlYWRieXRlKGRldiwgTTQ4 VDg2X1JFR19CKTsKPiAgCj4gIAlzZXFfcHJpbnRmKHNlcSwgIm1vZGVcdFx0OiAlc1xuIiwKPiAg CQkgKHJlZyAmIE00OFQ4Nl9SRUdfQl9ETSkgPyAiYmluYXJ5IiA6ICJiY2QiKTsKPiAgCj4gLQly ZWcgPSBvcHMtPnJlYWRieXRlKE00OFQ4Nl9SRUdfRCk7Cj4gKwlyZWcgPSBtNDh0ODZfcnRjX3Jl YWRieXRlKGRldiwgTTQ4VDg2X1JFR19EKTsKPiAgCj4gIAlzZXFfcHJpbnRmKHNlcSwgImJhdHRl cnlcdFx0OiAlc1xuIiwKPiAgCQkgKHJlZyAmIE00OFQ4Nl9SRUdfRF9WUlQpID8gIm9rIiA6ICJl eGhhdXN0ZWQiKTsKPiBAQCAtMTQ0LDM0ICsxNzMsMTIxIEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3Qg cnRjX2NsYXNzX29wcyBtNDh0ODZfcnRjX29wcyA9IHsKPiAgCS5wcm9jCQk9IG00OHQ4Nl9ydGNf cHJvYywKPiAgfTsKPiAgCj4gLXN0YXRpYyBpbnQgbTQ4dDg2X3J0Y19wcm9iZShzdHJ1Y3QgcGxh dGZvcm1fZGV2aWNlICpkZXYpCj4gK3N0YXRpYyBpbnQgbTQ4dDg2X3J0Y19wcm9iZShzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICB7Cj4gIAl1bnNpZ25lZCBjaGFyIHJlZzsKPiAtCXN0 cnVjdCBtNDh0ODZfb3BzICpvcHMgPSBkZXYtPmRldi5wbGF0Zm9ybV9kYXRhOwo+IC0Jc3RydWN0 IHJ0Y19kZXZpY2UgKnJ0YyA9IHJ0Y19kZXZpY2VfcmVnaXN0ZXIoIm00OHQ4NiIsCj4gLQkJCQkm ZGV2LT5kZXYsICZtNDh0ODZfcnRjX29wcywgVEhJU19NT0RVTEUpOwo+IC0KPiAtCWlmIChJU19F UlIocnRjKSkKPiAtCQlyZXR1cm4gUFRSX0VSUihydGMpOwo+IC0KPiAtCXBsYXRmb3JtX3NldF9k cnZkYXRhKGRldiwgcnRjKTsKPiArCWludCBlcnI7Cj4gKwlzdHJ1Y3QgcmVzb3VyY2UgKnJlc19p bmRleCwgKnJlc19kYXRhOwo+ICsJc3RydWN0IG00OHQ4Nl9ydGNfcHJpdmF0ZV9kYXRhICpwcml2 Owo+ICsKPiArCS8qIEFsbG9jYXRlIG1lbW9yeSBmb3IgdGhlIGRldmljZSBzdHJ1Y3R1cmUgKGFu ZCB6ZXJvIGl0KSAqLwo+ICsJcHJpdiA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCBtNDh0ODZfcnRj X3ByaXZhdGVfZGF0YSksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFwcml2KQo+ICsJCXJldHVybiAt RU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHByaXYpOwo+ICsKPiAr CWlmICghcGRldi0+ZGV2LnBsYXRmb3JtX2RhdGEpIHsKPiArCQlyZXNfaW5kZXggPSBwbGF0Zm9y bV9nZXRfcmVzb3VyY2VfYnluYW1lKAo+ICsJCQkJCXBkZXYsIElPUkVTT1VSQ0VfTUVNLCAicnRj X2luZGV4Iik7Cj4gKwkJaWYgKCFyZXNfaW5kZXgpIHsKPiArCQkJZXJyID0gLUVOWElPOwo+ICsJ CQlnb3RvIG91dF9mcmVlOwo+ICsJCX0KPiArCj4gKwkJcmVzX2RhdGEgPSBwbGF0Zm9ybV9nZXRf cmVzb3VyY2VfYnluYW1lKAo+ICsJCQkJCXBkZXYsIElPUkVTT1VSQ0VfTUVNLCAicnRjX2RhdGEi KTsKPiArCQlpZiAoIXJlc19kYXRhKSB7Cj4gKwkJCWVyciA9IC1FTlhJTzsKPiArCQkJZ290byBv dXRfZnJlZTsKPiArCQl9Cj4gKwo+ICsJCWlmICghcmVxdWVzdF9tZW1fcmVnaW9uKHJlc19pbmRl eC0+c3RhcnQsCj4gKwkJCQkJcmVzb3VyY2Vfc2l6ZShyZXNfaW5kZXgpLAo+ICsJCQkJCWRldl9u YW1lKCZwZGV2LT5kZXYpKSkgewo+ICsJCQllcnIgPSAtRUJVU1k7Cj4gKwkJCWdvdG8gb3V0X2Zy ZWU7Cj4gKwkJfQo+ICsKPiArCQlpZiAoIXJlcXVlc3RfbWVtX3JlZ2lvbihyZXNfZGF0YS0+c3Rh cnQsCj4gKwkJCQkJcmVzb3VyY2Vfc2l6ZShyZXNfZGF0YSksCj4gKwkJCQkJZGV2X25hbWUoJnBk ZXYtPmRldikpKSB7Cj4gKwkJCWVyciA9IC1FQlVTWTsKPiArCQkJZ290byBvdXRfcmVsZWFzZV9p bmRleDsKPiArCQl9Cj4gKwo+ICsJCXByaXYtPmlvX2luZGV4ID0gaW9yZW1hcChyZXNfaW5kZXgt PnN0YXJ0LAo+ICsJCQkJCXJlc291cmNlX3NpemUocmVzX2luZGV4KSk7Cj4gKwkJaWYgKCFwcml2 LT5pb19pbmRleCkgewo+ICsJCQllcnIgPSAtRUlPOwo+ICsJCQlnb3RvIG91dF9yZWxlYXNlX2Rh dGE7Cj4gKwkJfQo+ICsKPiArCQlwcml2LT5pb19kYXRhID0gaW9yZW1hcChyZXNfZGF0YS0+c3Rh cnQsCj4gKwkJCQkJcmVzb3VyY2Vfc2l6ZShyZXNfZGF0YSkpOwo+ICsJCWlmICghcHJpdi0+aW9f ZGF0YSkgewo+ICsJCQllcnIgPSAtRUlPOwo+ICsJCQlnb3RvIG91dF9pb19pbmRleDsKPiArCQl9 Cj4gKwl9IGVsc2UKPiArCQlwcml2LT5vcHMgPSBwZGV2LT5kZXYucGxhdGZvcm1fZGF0YTsKPiAr Cj4gKwlwcml2LT5ydGMgPSBydGNfZGV2aWNlX3JlZ2lzdGVyKCJtNDh0ODYiLAo+ICsJCQkJJnBk ZXYtPmRldiwgJm00OHQ4Nl9ydGNfb3BzLCBUSElTX01PRFVMRSk7Cj4gKwlpZiAoSVNfRVJSKHBy aXYtPnJ0YykpIHsKPiArCQllcnIgPSBQVFJfRVJSKHByaXYtPnJ0Yyk7Cj4gKwkJaWYgKCFwZGV2 LT5kZXYucGxhdGZvcm1fZGF0YSkKPiArCQkJZ290byBvdXRfaW9fZGF0YTsKPiArCQllbHNlCj4g KwkJCWdvdG8gb3V0X2ZyZWU7Cj4gKwl9Cj4gIAo+ICAJLyogcmVhZCBiYXR0ZXJ5IHN0YXR1cyAq Lwo+IC0JcmVnID0gb3BzLT5yZWFkYnl0ZShNNDhUODZfUkVHX0QpOwo+IC0JZGV2X2luZm8oJmRl di0+ZGV2LCAiYmF0dGVyeSAlc1xuIiwKPiArCXJlZyA9IG00OHQ4Nl9ydGNfcmVhZGJ5dGUoJnBk ZXYtPmRldiwgTTQ4VDg2X1JFR19EKTsKPiArCWRldl9pbmZvKCZwZGV2LT5kZXYsICJiYXR0ZXJ5 ICVzXG4iLAo+ICAJCShyZWcgJiBNNDhUODZfUkVHX0RfVlJUKSA/ICJvayIgOiAiZXhoYXVzdGVk Iik7Cj4gIAo+ICAJcmV0dXJuIDA7Cj4gKwo+ICtvdXRfaW9fZGF0YToKPiArCWlvdW5tYXAocHJp di0+aW9fZGF0YSk7Cj4gK291dF9pb19pbmRleDoKPiArCWlvdW5tYXAocHJpdi0+aW9faW5kZXgp Owo+ICtvdXRfcmVsZWFzZV9kYXRhOgo+ICsJcmVsZWFzZV9tZW1fcmVnaW9uKHJlc19kYXRhLT5z dGFydCwgcmVzb3VyY2Vfc2l6ZShyZXNfZGF0YSkpOwo+ICtvdXRfcmVsZWFzZV9pbmRleDoKPiAr CXJlbGVhc2VfbWVtX3JlZ2lvbihyZXNfaW5kZXgtPnN0YXJ0LCByZXNvdXJjZV9zaXplKHJlc19p bmRleCkpOwo+ICtvdXRfZnJlZToKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIE5VTEwp Owo+ICsJa2ZyZWUocHJpdik7Cj4gKwlyZXR1cm4gZXJyOwo+ICB9Cj4gIAo+IC1zdGF0aWMgaW50 IG00OHQ4Nl9ydGNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKmRldikKPiArc3RhdGlj IGludCBtNDh0ODZfcnRjX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICB7 Cj4gLQlzdHJ1Y3QgcnRjX2RldmljZSAqcnRjID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEoZGV2KTsK PiArCXN0cnVjdCByZXNvdXJjZSAqcmVzOwo+ICsJc3RydWN0IG00OHQ4Nl9ydGNfcHJpdmF0ZV9k YXRhICpwcml2ID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7Cj4gKwo+ICsJaWYgKHByaXYt PnJ0YykKPiArCQlydGNfZGV2aWNlX3VucmVnaXN0ZXIocHJpdi0+cnRjKTsKPiArCj4gKwlpZiAo cHJpdi0+aW9fZGF0YSkgewo+ICsJCWlvdW5tYXAocHJpdi0+aW9fZGF0YSk7Cj4gKwkJcmVzID0g cGxhdGZvcm1fZ2V0X3Jlc291cmNlX2J5bmFtZSgKPiArCQkJCQlwZGV2LCBJT1JFU09VUkNFX01F TSwgInJ0Y19kYXRhIik7Cj4gKwkJcmVsZWFzZV9tZW1fcmVnaW9uKHJlcy0+c3RhcnQsIHJlc291 cmNlX3NpemUocmVzKSk7Cj4gKwl9Cj4gKwo+ICsJaWYgKHByaXYtPmlvX2luZGV4KSB7Cj4gKwkJ aW91bm1hcChwcml2LT5pb19pbmRleCk7Cj4gKwkJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNl X2J5bmFtZSgKPiArCQkJCQlwZGV2LCBJT1JFU09VUkNFX01FTSwgInJ0Y19pbmRleCIpOwo+ICsJ CXJlbGVhc2VfbWVtX3JlZ2lvbihyZXMtPnN0YXJ0LCByZXNvdXJjZV9zaXplKHJlcykpOwo+ICsJ fQo+ICAKPiAtIAlpZiAocnRjKQo+IC0JCXJ0Y19kZXZpY2VfdW5yZWdpc3RlcihydGMpOwo+ICsJ cGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgTlVMTCk7Cj4gIAo+IC0JcGxhdGZvcm1fc2V0X2Ry dmRhdGEoZGV2LCBOVUxMKTsKPiArCWtmcmVlKHByaXYpOwo+ICAKPiAgCXJldHVybiAwOwo+ICB9 Cj4gCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkZXZp Y2V0cmVlLWRpc2N1c3MgbWFpbGluZyBsaXN0CmRldmljZXRyZWUtZGlzY3Vzc0BsaXN0cy5vemxh YnMub3JnCmh0dHBzOi8vbGlzdHMub3psYWJzLm9yZy9saXN0aW5mby9kZXZpY2V0cmVlLWRpc2N1 c3MK