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=-15.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 B1755C433ED for ; Thu, 20 May 2021 06:10:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 95B7461186 for ; Thu, 20 May 2021 06:10:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230325AbhETGLz (ORCPT ); Thu, 20 May 2021 02:11:55 -0400 Received: from mx2.suse.de ([195.135.220.15]:55162 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230315AbhETGLy (ORCPT ); Thu, 20 May 2021 02:11:54 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8BE2DAEE7; Thu, 20 May 2021 06:10:32 +0000 (UTC) Subject: Re: [PATCH v2 10/11] dm: introduce zone append emulation To: Damien Le Moal , dm-devel@redhat.com, Mike Snitzer , linux-block@vger.kernel.org, Jens Axboe References: <20210520042228.974083-1-damien.lemoal@wdc.com> <20210520042228.974083-11-damien.lemoal@wdc.com> From: Hannes Reinecke Message-ID: <68203e46-01bc-011c-ab8e-9c94ca60adce@suse.de> Date: Thu, 20 May 2021 08:10:30 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.0 MIME-Version: 1.0 In-Reply-To: <20210520042228.974083-11-damien.lemoal@wdc.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org On 5/20/21 6:22 AM, Damien Le Moal wrote: > For zoned targets that cannot support zone append operations, implement > an emulation using regular write operations. If the original BIO > submitted by the user is a zone append operation, change its clone into > a regular write operation directed at the target zone write pointer > position. > > To do so, an array of write pointer offsets (write pointer position > relative to the start of a zone) is added to struct mapped_device. All > operations that modify a sequential zone write pointer (writes, zone > reset, zone finish and zone append) are intersepted in __map_bio() and > processed using the new functions dm_zone_map_bio(). > > Detection of the target ability to natively support zone append > operations is done from dm_table_set_restrictions() by calling the > function dm_set_zones_restrictions(). A target that does not support > zone append operation, either by explicitly declaring it using the new > struct dm_target field zone_append_not_supported, or because the device > table contains a non-zoned device, has its mapped device marked with the > new flag DMF_ZONE_APPEND_EMULATED. The helper function > dm_emulate_zone_append() is introduced to test a mapped device for this > new flag. > > Atomicity of the zones write pointer tracking and updates is done using > a zone write locking mechanism based on a bitmap. This is similar to > the block layer method but based on BIOs rather than struct request. > A zone write lock is taken in dm_zone_map_bio() for any clone BIO with > an operation type that changes the BIO target zone write pointer > position. The zone write lock is released if the clone BIO is failed > before submission or when dm_zone_endio() is called when the clone BIO > completes. > > The zone write lock bitmap of the mapped device, together with a bitmap > indicating zone types (conv_zones_bitmap) and the write pointer offset > array (zwp_offset) are allocated and initialized with a full device zone > report in dm_set_zones_restrictions() using the function > dm_revalidate_zones(). > > For failed operations that may have modified a zone write pointer, the > zone write pointer offset is marked as invalid in dm_zone_endio(). > Zones with an invalid write pointer offset are checked and the write > pointer updated using an internal report zone operation when the > faulty zone is accessed again by the user. > > All functions added for this emulation have a minimal overhead for > zoned targets natively supporting zone append operations. Regular > device targets are also not affected. The added code also does not > impact builds with CONFIG_BLK_DEV_ZONED disabled by stubbing out all > dm zone related functions. > > Signed-off-by: Damien Le Moal > --- > drivers/md/dm-core.h | 14 + > drivers/md/dm-table.c | 19 +- > drivers/md/dm-zone.c | 615 ++++++++++++++++++++++++++++++++-- > drivers/md/dm.c | 39 ++- > drivers/md/dm.h | 18 +- > include/linux/device-mapper.h | 6 + > 6 files changed, 657 insertions(+), 54 deletions(-) > > diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h > index cfabc1c91f9f..2dbb0c7ff720 100644 > --- a/drivers/md/dm-core.h > +++ b/drivers/md/dm-core.h > @@ -114,6 +114,12 @@ struct mapped_device { > bool init_tio_pdu:1; > > struct srcu_struct io_barrier; > + > +#ifdef CONFIG_BLK_DEV_ZONED > + unsigned int nr_zones; > + spinlock_t zwp_offset_lock; > + unsigned int *zwp_offset; > +#endif > }; > > /* > @@ -128,6 +134,7 @@ struct mapped_device { > #define DMF_DEFERRED_REMOVE 6 > #define DMF_SUSPENDED_INTERNALLY 7 > #define DMF_POST_SUSPENDING 8 > +#define DMF_EMULATE_ZONE_APPEND 9 > > void disable_discard(struct mapped_device *md); > void disable_write_same(struct mapped_device *md); > @@ -143,6 +150,13 @@ static inline struct dm_stats *dm_get_stats(struct mapped_device *md) > return &md->stats; > } > > +static inline bool dm_emulate_zone_append(struct mapped_device *md) > +{ > + if (blk_queue_is_zoned(md->queue)) > + return test_bit(DMF_EMULATE_ZONE_APPEND, &md->flags); > + return false; > +} > + > #define DM_TABLE_MAX_DEPTH 16 > > struct dm_table { > diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c > index dd9f648ab598..21fdccfb16cf 100644 > --- a/drivers/md/dm-table.c > +++ b/drivers/md/dm-table.c > @@ -1981,11 +1981,12 @@ static int device_requires_stable_pages(struct dm_target *ti, > return blk_queue_stable_writes(q); > } > > -void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, > - struct queue_limits *limits) > +int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, > + struct queue_limits *limits) > { > bool wc = false, fua = false; > int page_size = PAGE_SIZE; > + int r; > > /* > * Copy table's limits to the DM device's request_queue > @@ -2064,12 +2065,20 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, > dm_table_any_dev_attr(t, device_is_not_random, NULL)) > blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); > > - /* For a zoned target, setup the zones related queue attributes */ > - if (blk_queue_is_zoned(q)) > - dm_set_zones_restrictions(t, q); > + /* > + * For a zoned target, setup the zones related queue attributes > + * and resources necessary for zone append emulation if necessary. > + */ > + if (blk_queue_is_zoned(q)) { > + r = dm_set_zones_restrictions(t, q); > + if (r) > + return r; > + } > > dm_update_keyslot_manager(q, t); > blk_queue_update_readahead(q); > + > + return 0; > } > > unsigned int dm_table_get_num_targets(struct dm_table *t) > diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c > index edc3bbb45637..c298bab28390 100644 > --- a/drivers/md/dm-zone.c > +++ b/drivers/md/dm-zone.c > @@ -4,55 +4,73 @@ > */ > > #include > +#include > +#include > +#include > > #include "dm-core.h" > > +#define DM_MSG_PREFIX "zone" > + > +#define DM_ZONE_INVALID_WP_OFST UINT_MAX > +#define DM_ZONE_UPDATING_WP_OFST (DM_ZONE_INVALID_WP_OFST - 1) > + > /* > - * User facing dm device block device report zone operation. This calls the > - * report_zones operation for each target of a device table. This operation is > - * generally implemented by targets using dm_report_zones(). > + * For internal zone reports bypassing the top BIO submission path. > */ > -int dm_blk_report_zones(struct gendisk *disk, sector_t sector, > - unsigned int nr_zones, report_zones_cb cb, void *data) > +static int dm_blk_do_report_zones(struct mapped_device *md, struct dm_table *t, > + sector_t sector, unsigned int nr_zones, > + report_zones_cb cb, void *data) > { > - struct mapped_device *md = disk->private_data; > - struct dm_table *map; > - int srcu_idx, ret; > + struct gendisk *disk = md->disk; > + int ret; > struct dm_report_zones_args args = { > .next_sector = sector, > .orig_data = data, > .orig_cb = cb, > }; > > - if (dm_suspended_md(md)) > - return -EAGAIN; > - > - map = dm_get_live_table(md, &srcu_idx); > - if (!map) { > - ret = -EIO; > - goto out; > - } > - > do { > struct dm_target *tgt; > > - tgt = dm_table_find_target(map, args.next_sector); > - if (WARN_ON_ONCE(!tgt->type->report_zones)) { > - ret = -EIO; > - goto out; > - } > + tgt = dm_table_find_target(t, args.next_sector); > + if (WARN_ON_ONCE(!tgt->type->report_zones)) > + return -EIO; > > args.tgt = tgt; > ret = tgt->type->report_zones(tgt, &args, > nr_zones - args.zone_idx); > if (ret < 0) > - goto out; > + return ret; > } while (args.zone_idx < nr_zones && > args.next_sector < get_capacity(disk)); > > - ret = args.zone_idx; > -out: > + return args.zone_idx; > +} > + > +/* > + * User facing dm device block device report zone operation. This calls the > + * report_zones operation for each target of a device table. This operation is > + * generally implemented by targets using dm_report_zones(). > + */ > +int dm_blk_report_zones(struct gendisk *disk, sector_t sector, > + unsigned int nr_zones, report_zones_cb cb, void *data) > +{ > + struct mapped_device *md = disk->private_data; > + struct dm_table *map; > + int srcu_idx, ret; > + > + if (dm_suspended_md(md)) > + return -EAGAIN; > + > + map = dm_get_live_table(md, &srcu_idx); > + if (!map) > + return -EIO; > + > + ret = dm_blk_do_report_zones(md, map, sector, nr_zones, cb, data); > + > dm_put_live_table(md, srcu_idx); > + > return ret; > } > > @@ -121,16 +139,551 @@ bool dm_is_zone_write(struct mapped_device *md, struct bio *bio) > } > } > > -void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q) > +void dm_init_zoned_dev(struct mapped_device *md) > { > - if (!blk_queue_is_zoned(q)) > - return; > + spin_lock_init(&md->zwp_offset_lock); > +} > + > +void dm_cleanup_zoned_dev(struct mapped_device *md) > +{ > + struct request_queue *q = md->queue; > + > + if (q) { > + kfree(q->conv_zones_bitmap); > + q->conv_zones_bitmap = NULL; > + kfree(q->seq_zones_wlock); > + q->seq_zones_wlock = NULL; > + } > + > + kvfree(md->zwp_offset); > + md->zwp_offset = NULL; > + md->nr_zones = 0; > +} > + > +static unsigned int dm_get_zone_wp_offset(struct blk_zone *zone) > +{ > + switch (zone->cond) { > + case BLK_ZONE_COND_IMP_OPEN: > + case BLK_ZONE_COND_EXP_OPEN: > + case BLK_ZONE_COND_CLOSED: > + return zone->wp - zone->start; > + case BLK_ZONE_COND_FULL: > + return zone->len; > + case BLK_ZONE_COND_EMPTY: > + case BLK_ZONE_COND_NOT_WP: > + case BLK_ZONE_COND_OFFLINE: > + case BLK_ZONE_COND_READONLY: > + default: > + /* > + * Conventional, offline and read-only zones do not have a valid > + * write pointer. Use 0 as for an empty zone. > + */ > + return 0; > + } > +} > + > +static int dm_zone_revalidate_cb(struct blk_zone *zone, unsigned int idx, > + void *data) > +{ > + struct mapped_device *md = data; > + struct request_queue *q = md->queue; > + > + switch (zone->type) { > + case BLK_ZONE_TYPE_CONVENTIONAL: > + if (!q->conv_zones_bitmap) { > + q->conv_zones_bitmap = > + kcalloc(BITS_TO_LONGS(q->nr_zones), > + sizeof(unsigned long), GFP_NOIO); > + if (!q->conv_zones_bitmap) > + return -ENOMEM; > + } > + set_bit(idx, q->conv_zones_bitmap); > + break; > + case BLK_ZONE_TYPE_SEQWRITE_REQ: > + case BLK_ZONE_TYPE_SEQWRITE_PREF: > + if (!q->seq_zones_wlock) { > + q->seq_zones_wlock = > + kcalloc(BITS_TO_LONGS(q->nr_zones), > + sizeof(unsigned long), GFP_NOIO); > + if (!q->seq_zones_wlock) > + return -ENOMEM; > + } > + if (!md->zwp_offset) { > + md->zwp_offset = > + kvcalloc(q->nr_zones, sizeof(unsigned int), > + GFP_NOIO); > + if (!md->zwp_offset) > + return -ENOMEM; > + } > + md->zwp_offset[idx] = dm_get_zone_wp_offset(zone); > + > + break; > + default: > + DMERR("Invalid zone type 0x%x at sectors %llu", > + (int)zone->type, zone->start); > + return -ENODEV; > + } > + > + return 0; > +} > + > +/* > + * Revalidate the zones of a mapped device to initialize resource necessary > + * for zone append emulation. Note that we cannot simply use the block layer > + * blk_revalidate_disk_zones() function here as the mapped device is suspended > + * (this is called from __bind() context). > + */ > +static int dm_revalidate_zones(struct mapped_device *md, struct dm_table *t) > +{ > + struct request_queue *q = md->queue; > + int ret; > + > + /* > + * Check if something changed. If yes, cleanup the current resources > + * and reallocate everything. > + */ > + if (!q->nr_zones || q->nr_zones != md->nr_zones) > + dm_cleanup_zoned_dev(md); > + if (md->nr_zones) > + return 0; > + > + /* Scan all zones to initialize everything */ > + ret = dm_blk_do_report_zones(md, t, 0, q->nr_zones, > + dm_zone_revalidate_cb, md); > + if (ret < 0) > + goto err; > + if (ret != q->nr_zones) { > + ret = -EIO; > + goto err; > + } > + > + md->nr_zones = q->nr_zones; > + > + return 0; > + > +err: > + DMERR("Revalidate zones failed %d", ret); > + dm_cleanup_zoned_dev(md); > + return ret; > +} > + > +static int device_not_zone_append_capable(struct dm_target *ti, > + struct dm_dev *dev, sector_t start, > + sector_t len, void *data) > +{ > + return !blk_queue_is_zoned(bdev_get_queue(dev->bdev)); > +} > + > +static bool dm_table_supports_zone_append(struct dm_table *t) > +{ > + struct dm_target *ti; > + unsigned int i; > + > + for (i = 0; i < dm_table_get_num_targets(t); i++) { > + ti = dm_table_get_target(t, i); > + > + if (ti->emulate_zone_append) > + return false; > + > + if (!ti->type->iterate_devices || > + ti->type->iterate_devices(ti, device_not_zone_append_capable, NULL)) > + return false; > + } > + > + return true; > +} > + > +int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q) > +{ > + struct mapped_device *md = t->md; > > /* > * For a zoned target, the number of zones should be updated for the > - * correct value to be exposed in sysfs queue/nr_zones. For a BIO based > - * target, this is all that is needed. > + * correct value to be exposed in sysfs queue/nr_zones. > */ > WARN_ON_ONCE(queue_is_mq(q)); > - q->nr_zones = blkdev_nr_zones(t->md->disk); > + q->nr_zones = blkdev_nr_zones(md->disk); > + > + /* Check if zone append is natively supported */ > + if (dm_table_supports_zone_append(t)) { > + clear_bit(DMF_EMULATE_ZONE_APPEND, &md->flags); > + dm_cleanup_zoned_dev(md); > + return 0; > + } > + > + /* > + * Mark the mapped device as needing zone append emulation and > + * initialize the emulation resources once the capacity is set. > + */ > + set_bit(DMF_EMULATE_ZONE_APPEND, &md->flags); > + if (!get_capacity(md->disk)) > + return 0; > + > + return dm_revalidate_zones(md, t); > +} > + > +static int dm_update_zone_wp_offset_cb(struct blk_zone *zone, unsigned int idx, > + void *data) > +{ > + unsigned int *wp_offset = data; > + > + *wp_offset = dm_get_zone_wp_offset(zone); > + > + return 0; > +} > + > +static int dm_update_zone_wp_offset(struct mapped_device *md, unsigned int zno, > + unsigned int *wp_ofst) > +{ > + sector_t sector = zno * blk_queue_zone_sectors(md->queue); > + unsigned int noio_flag; > + struct dm_table *t; > + int srcu_idx, ret; > + > + t = dm_get_live_table(md, &srcu_idx); > + if (!t) > + return -EIO; > + > + /* > + * Ensure that all memory allocations in this context are done as if > + * GFP_NOIO was specified. > + */ > + noio_flag = memalloc_noio_save(); > + ret = dm_blk_do_report_zones(md, t, sector, 1, > + dm_update_zone_wp_offset_cb, wp_ofst); > + memalloc_noio_restore(noio_flag); > + > + dm_put_live_table(md, srcu_idx); > + > + if (ret != 1) > + return -EIO; > + > + return 0; > +} > + > +/* > + * First phase of BIO mapping for targets with zone append emulation: > + * check all BIO that change a zone writer pointer and change zone > + * append operations into regular write operations. > + */ > +static bool dm_zone_map_bio_begin(struct mapped_device *md, > + struct bio *orig_bio, struct bio *clone) > +{ > + sector_t zone_sectors = blk_queue_zone_sectors(md->queue); > + unsigned int zno = bio_zone_no(orig_bio); > + unsigned long flags; > + bool good_io = false; > + > + spin_lock_irqsave(&md->zwp_offset_lock, flags); > + > + /* > + * If the target zone is in an error state, recover by inspecting the > + * zone to get its current write pointer position. Note that since the > + * target zone is already locked, a BIO issuing context should never > + * see the zone write in the DM_ZONE_UPDATING_WP_OFST state. > + */ > + if (md->zwp_offset[zno] == DM_ZONE_INVALID_WP_OFST) { > + unsigned int wp_offset; > + int ret; > + > + md->zwp_offset[zno] = DM_ZONE_UPDATING_WP_OFST; > + > + spin_unlock_irqrestore(&md->zwp_offset_lock, flags); > + ret = dm_update_zone_wp_offset(md, zno, &wp_offset); > + spin_lock_irqsave(&md->zwp_offset_lock, flags); > + > + if (ret) { > + md->zwp_offset[zno] = DM_ZONE_INVALID_WP_OFST; > + goto out; > + } > + md->zwp_offset[zno] = wp_offset; > + } else if (md->zwp_offset[zno] == DM_ZONE_UPDATING_WP_OFST) { > + DMWARN_LIMIT("Invalid DM_ZONE_UPDATING_WP_OFST state"); > + goto out; > + } > + > + switch (bio_op(orig_bio)) { > + case REQ_OP_WRITE_ZEROES: > + case REQ_OP_WRITE_SAME: > + case REQ_OP_WRITE: > + break; > + case REQ_OP_ZONE_RESET: > + case REQ_OP_ZONE_FINISH: > + goto good; > + case REQ_OP_ZONE_APPEND: > + /* > + * Change zone append operations into a non-mergeable regular > + * writes directed at the current write pointer position of the > + * target zone. > + */ > + clone->bi_opf = REQ_OP_WRITE | REQ_NOMERGE | > + (orig_bio->bi_opf & (~REQ_OP_MASK)); > + clone->bi_iter.bi_sector = > + orig_bio->bi_iter.bi_sector + md->zwp_offset[zno]; > + break; > + default: > + DMWARN_LIMIT("Invalid BIO operation"); > + goto out; > + } > + > + /* Cannot write to a full zone */ > + if (md->zwp_offset[zno] >= zone_sectors) > + goto out; > + > + /* Writes must be aligned to the zone write pointer */ > + if ((clone->bi_iter.bi_sector & (zone_sectors - 1)) != md->zwp_offset[zno]) > + goto out; > + > +good: > + good_io = true; > + > +out: > + spin_unlock_irqrestore(&md->zwp_offset_lock, flags); I'm not happy with the spinlock. Can't the same effect be achieved with some clever READ_ONCE()/WRITE_ONCE/cmpexch magic? Especially as you have a separate 'zone lock' mechanism ... > + > + return good_io; > +} > + > +/* > + * Second phase of BIO mapping for targets with zone append emulation: > + * update the zone write pointer offset array to account for the additional > + * data written to a zone. Note that at this point, the remapped clone BIO > + * may already have completed, so we do not touch it. > + */ > +static blk_status_t dm_zone_map_bio_end(struct mapped_device *md, > + struct bio *orig_bio, > + unsigned int nr_sectors) > +{ > + unsigned int zno = bio_zone_no(orig_bio); > + blk_status_t sts = BLK_STS_OK; > + unsigned long flags; > + > + spin_lock_irqsave(&md->zwp_offset_lock, flags); > + > + /* Update the zone wp offset */ > + switch (bio_op(orig_bio)) { > + case REQ_OP_ZONE_RESET: > + md->zwp_offset[zno] = 0; > + break; > + case REQ_OP_ZONE_FINISH: > + md->zwp_offset[zno] = blk_queue_zone_sectors(md->queue); > + break; > + case REQ_OP_WRITE_ZEROES: > + case REQ_OP_WRITE_SAME: > + case REQ_OP_WRITE: > + md->zwp_offset[zno] += nr_sectors; > + break; > + case REQ_OP_ZONE_APPEND: > + /* > + * Check that the target did not truncate the write operation > + * emulating a zone append. > + */ > + if (nr_sectors != bio_sectors(orig_bio)) { > + DMWARN_LIMIT("Truncated write for zone append"); > + sts = BLK_STS_IOERR; > + break; > + } > + md->zwp_offset[zno] += nr_sectors; > + break; > + default: > + DMWARN_LIMIT("Invalid BIO operation"); > + sts = BLK_STS_IOERR; > + break; > + } > + > + spin_unlock_irqrestore(&md->zwp_offset_lock, flags); You don't need the spinlock here; using WRITE_ONCE() should be sufficient. > + > + return sts; > +} > + > +static inline void dm_zone_lock(struct request_queue *q, > + unsigned int zno, struct bio *clone) > +{ > + if (WARN_ON_ONCE(bio_flagged(clone, BIO_ZONE_WRITE_LOCKED))) > + return; > + > + wait_on_bit_lock_io(q->seq_zones_wlock, zno, TASK_UNINTERRUPTIBLE); > + bio_set_flag(clone, BIO_ZONE_WRITE_LOCKED); > +} > + > +static inline void dm_zone_unlock(struct request_queue *q, > + unsigned int zno, struct bio *clone) > +{ > + if (!bio_flagged(clone, BIO_ZONE_WRITE_LOCKED)) > + return; > + > + WARN_ON_ONCE(!test_bit(zno, q->seq_zones_wlock)); > + clear_bit_unlock(zno, q->seq_zones_wlock); > + smp_mb__after_atomic(); > + wake_up_bit(q->seq_zones_wlock, zno); > + > + bio_clear_flag(clone, BIO_ZONE_WRITE_LOCKED); > +} > + > +static bool dm_need_zone_wp_tracking(struct bio *orig_bio) > +{ > + /* > + * Special processing is not needed for operations that do not need the > + * zone write lock, that is, all operations that target conventional > + * zones and all operations that do not modify directly a sequential > + * zone write pointer. > + */ > + if (op_is_flush(orig_bio->bi_opf) && !bio_sectors(orig_bio)) > + return false; > + switch (bio_op(orig_bio)) { > + case REQ_OP_WRITE_ZEROES: > + case REQ_OP_WRITE_SAME: > + case REQ_OP_WRITE: > + case REQ_OP_ZONE_RESET: > + case REQ_OP_ZONE_FINISH: > + case REQ_OP_ZONE_APPEND: > + return bio_zone_is_seq(orig_bio); > + default: > + return false; > + } > +} > + > +/* > + * Special IO mapping for targets needing zone append emulation. > + */ > +int dm_zone_map_bio(struct dm_target_io *tio) > +{ > + struct dm_io *io = tio->io; > + struct dm_target *ti = tio->ti; > + struct mapped_device *md = io->md; > + struct request_queue *q = md->queue; > + struct bio *orig_bio = io->orig_bio; > + struct bio *clone = &tio->clone; > + unsigned int zno; > + blk_status_t sts; > + int r; > + > + /* > + * IOs that do not change a zone write pointer do not need > + * any additional special processing. > + */ > + if (!dm_need_zone_wp_tracking(orig_bio)) > + return ti->type->map(ti, clone); > + > + /* Lock the target zone */ > + zno = bio_zone_no(orig_bio); > + dm_zone_lock(q, zno, clone); > + > + /* > + * Check that the bio and the target zone write pointer offset are > + * both valid, and if the bio is a zone append, remap it to a write. > + */ > + if (!dm_zone_map_bio_begin(md, orig_bio, clone)) { > + dm_zone_unlock(q, zno, clone); > + return DM_MAPIO_KILL; > + } > + > + /* > + * The target map function may issue and complete the IO quickly. > + * Take an extra reference on the IO to make sure it does disappear > + * until we run dm_zone_map_bio_end(). > + */ > + dm_io_inc_pending(io); > + > + /* Let the target do its work */ > + r = ti->type->map(ti, clone); > + switch (r) { > + case DM_MAPIO_SUBMITTED: > + /* > + * The target submitted the clone BIO. The target zone will > + * be unlocked on completion of the clone. > + */ > + sts = dm_zone_map_bio_end(md, orig_bio, *tio->len_ptr); > + break; > + case DM_MAPIO_REMAPPED: > + /* > + * The target only remapped the clone BIO. In case of error, > + * unlock the target zone here as the clone will not be > + * submitted. > + */ > + sts = dm_zone_map_bio_end(md, orig_bio, *tio->len_ptr); > + if (sts != BLK_STS_OK) > + dm_zone_unlock(q, zno, clone); > + break; > + case DM_MAPIO_REQUEUE: > + case DM_MAPIO_KILL: > + default: > + dm_zone_unlock(q, zno, clone); > + sts = BLK_STS_IOERR; > + break; > + } > + > + /* Drop the extra reference on the IO */ > + dm_io_dec_pending(io, sts); > + > + if (sts != BLK_STS_OK) > + return DM_MAPIO_KILL; > + > + return r; > +} > + > +/* > + * IO completion callback called from clone_endio(). > + */ > +void dm_zone_endio(struct dm_io *io, struct bio *clone) > +{ > + struct mapped_device *md = io->md; > + struct request_queue *q = md->queue; > + struct bio *orig_bio = io->orig_bio; > + unsigned long flags; > + unsigned int zno; > + > + /* > + * For targets that do not emulate zone append, we only need to > + * handle native zone-append bios. > + */ > + if (!dm_emulate_zone_append(md)) { > + /* > + * Get the offset within the zone of the written sector > + * and add that to the original bio sector position. > + */ > + if (clone->bi_status == BLK_STS_OK && > + bio_op(clone) == REQ_OP_ZONE_APPEND) { > + sector_t mask = (sector_t)blk_queue_zone_sectors(q) - 1; > + > + orig_bio->bi_iter.bi_sector += > + clone->bi_iter.bi_sector & mask; > + } > + > + return; > + } > + > + /* > + * For targets that do emulate zone append, if the clone BIO does not > + * own the target zone write lock, we have nothing to do. > + */ > + if (!bio_flagged(clone, BIO_ZONE_WRITE_LOCKED)) > + return; > + > + zno = bio_zone_no(orig_bio); > + > + spin_lock_irqsave(&md->zwp_offset_lock, flags); > + if (clone->bi_status != BLK_STS_OK) { > + /* > + * BIOs that modify a zone write pointer may leave the zone > + * in an unknown state in case of failure (e.g. the write > + * pointer was only partially advanced). In this case, set > + * the target zone write pointer as invalid unless it is > + * already being updated. > + */ > + if (md->zwp_offset[zno] != DM_ZONE_UPDATING_WP_OFST) > + md->zwp_offset[zno] = DM_ZONE_INVALID_WP_OFST; > + } else if (bio_op(orig_bio) == REQ_OP_ZONE_APPEND) { > + /* > + * Get the written sector for zone append operation that were > + * emulated using regular write operations. > + */ > + if (WARN_ON_ONCE(md->zwp_offset[zno] < bio_sectors(orig_bio))) > + md->zwp_offset[zno] = DM_ZONE_INVALID_WP_OFST; > + else > + orig_bio->bi_iter.bi_sector += > + md->zwp_offset[zno] - bio_sectors(orig_bio); > + } > + spin_unlock_irqrestore(&md->zwp_offset_lock, flags); > + Similar comments to the spinlock here. > + dm_zone_unlock(q, zno, clone); > } > diff --git a/drivers/md/dm.c b/drivers/md/dm.c > index 563504163b74..5038bf522b0d 100644 > --- a/drivers/md/dm.c > +++ b/drivers/md/dm.c > @@ -875,7 +875,6 @@ static void clone_endio(struct bio *bio) > struct dm_io *io = tio->io; > struct mapped_device *md = tio->io->md; > dm_endio_fn endio = tio->ti->type->end_io; > - struct bio *orig_bio = io->orig_bio; > struct request_queue *q = bio->bi_bdev->bd_disk->queue; > > if (unlikely(error == BLK_STS_TARGET)) { > @@ -890,17 +889,8 @@ static void clone_endio(struct bio *bio) > disable_write_zeroes(md); > } > > - /* > - * For zone-append bios get offset in zone of the written > - * sector and add that to the original bio sector pos. > - */ > - if (bio_op(orig_bio) == REQ_OP_ZONE_APPEND) { > - sector_t written_sector = bio->bi_iter.bi_sector; > - struct request_queue *q = orig_bio->bi_bdev->bd_disk->queue; > - u64 mask = (u64)blk_queue_zone_sectors(q) - 1; > - > - orig_bio->bi_iter.bi_sector += written_sector & mask; > - } > + if (blk_queue_is_zoned(q)) > + dm_zone_endio(io, bio); > > if (endio) { > int r = endio(tio->ti, bio, &error); > @@ -1213,7 +1203,16 @@ static blk_qc_t __map_bio(struct dm_target_io *tio) > down(&md->swap_bios_semaphore); > } > > - r = ti->type->map(ti, clone); > + /* > + * Check if the IO needs a special mapping due to zone append emulation > + * on zoned target. In this case, dm_zone_map_begin() calls the target > + * map operation. > + */ > + if (dm_emulate_zone_append(io->md)) > + r = dm_zone_map_bio(tio); > + else > + r = ti->type->map(ti, clone); > + > switch (r) { > case DM_MAPIO_SUBMITTED: > break; > @@ -1757,6 +1756,7 @@ static struct mapped_device *alloc_dev(int minor) > INIT_LIST_HEAD(&md->uevent_list); > INIT_LIST_HEAD(&md->table_devices); > spin_lock_init(&md->uevent_lock); > + dm_init_zoned_dev(md); > > /* > * default to bio-based until DM table is loaded and md->type > @@ -1956,11 +1956,16 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, > goto out; > } > > + ret = dm_table_set_restrictions(t, q, limits); > + if (ret) { > + old_map = ERR_PTR(ret); > + goto out; > + } > + > old_map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock)); > rcu_assign_pointer(md->map, (void *)t); > md->immutable_target_type = dm_table_get_immutable_target_type(t); > > - dm_table_set_restrictions(t, q, limits); > if (old_map) > dm_sync_table(md); > > @@ -2079,7 +2084,10 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) > DMERR("Cannot calculate initial queue limits"); > return r; > } > - dm_table_set_restrictions(t, md->queue, &limits); > + r = dm_table_set_restrictions(t, md->queue, &limits); > + if (r) > + return r; > + > blk_register_queue(md->disk); > > return 0; > @@ -2188,6 +2196,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait) > dm_device_name(md), atomic_read(&md->holders)); > > dm_sysfs_exit(md); > + dm_cleanup_zoned_dev(md); > dm_table_destroy(__unbind(md)); > free_dev(md); > } > diff --git a/drivers/md/dm.h b/drivers/md/dm.h > index 39c243258e24..65f20d8cc415 100644 > --- a/drivers/md/dm.h > +++ b/drivers/md/dm.h > @@ -45,6 +45,8 @@ struct dm_dev_internal { > > struct dm_table; > struct dm_md_mempools; > +struct dm_target_io; > +struct dm_io; > > /*----------------------------------------------------------------- > * Internal table functions. > @@ -56,8 +58,8 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); > bool dm_table_has_no_data_devices(struct dm_table *table); > int dm_calculate_queue_limits(struct dm_table *table, > struct queue_limits *limits); > -void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, > - struct queue_limits *limits); > +int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, > + struct queue_limits *limits); > struct list_head *dm_table_get_devices(struct dm_table *t); > void dm_table_presuspend_targets(struct dm_table *t); > void dm_table_presuspend_undo_targets(struct dm_table *t); > @@ -103,17 +105,27 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t); > /* > * Zoned targets related functions. > */ > -void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q); > +int dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q); > +void dm_zone_endio(struct dm_io *io, struct bio *clone); > #ifdef CONFIG_BLK_DEV_ZONED > +void dm_init_zoned_dev(struct mapped_device *md); > +void dm_cleanup_zoned_dev(struct mapped_device *md); > int dm_blk_report_zones(struct gendisk *disk, sector_t sector, > unsigned int nr_zones, report_zones_cb cb, void *data); > bool dm_is_zone_write(struct mapped_device *md, struct bio *bio); > +int dm_zone_map_bio(struct dm_target_io *io); > #else > +static inline void dm_init_zoned_dev(struct mapped_device *md) {} > +static inline void dm_cleanup_zoned_dev(struct mapped_device *md) {} > #define dm_blk_report_zones NULL > static inline bool dm_is_zone_write(struct mapped_device *md, struct bio *bio) > { > return false; > } > +static inline int dm_zone_map_bio(struct dm_target_io *tio) > +{ > + return DM_MAPIO_KILL; > +} > #endif > > /*----------------------------------------------------------------- > diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h > index caea0a079d2d..7457d49acf9a 100644 > --- a/include/linux/device-mapper.h > +++ b/include/linux/device-mapper.h > @@ -361,6 +361,12 @@ struct dm_target { > * Set if we need to limit the number of in-flight bios when swapping. > */ > bool limit_swap_bios:1; > + > + /* > + * Set if this target implements a a zoned device and needs emulation of > + * zone append operations using regular writes. > + */ > + bool emulate_zone_append:1; > }; > > void *dm_per_bio_data(struct bio *bio, size_t data_size); > Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer 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=-15.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 1E206C433B4 for ; Thu, 20 May 2021 06:13:56 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7BC2F61184 for ; Thu, 20 May 2021 06:13:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7BC2F61184 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=tempfail smtp.mailfrom=dm-devel-bounces@redhat.com Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-530-1eGRmsFZM-epaDOD_qIIIw-1; Thu, 20 May 2021 02:13:52 -0400 X-MC-Unique: 1eGRmsFZM-epaDOD_qIIIw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 55A4F180FD6A; Thu, 20 May 2021 06:13:48 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 21FA210027C4; Thu, 20 May 2021 06:13:48 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id B679B1800BB8; Thu, 20 May 2021 06:13:47 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 14K6AgjJ016406 for ; Thu, 20 May 2021 02:10:42 -0400 Received: by smtp.corp.redhat.com (Postfix) id 07141107504; Thu, 20 May 2021 06:10:42 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast04.extmail.prod.ext.rdu2.redhat.com [10.11.55.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 01B0D10769A for ; Thu, 20 May 2021 06:10:38 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B628F101D221 for ; Thu, 20 May 2021 06:10:38 +0000 (UTC) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-232-jGWRkonfMAyYXebZF89z-g-1; Thu, 20 May 2021 02:10:34 -0400 X-MC-Unique: jGWRkonfMAyYXebZF89z-g-1 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 8BE2DAEE7; Thu, 20 May 2021 06:10:32 +0000 (UTC) To: Damien Le Moal , dm-devel@redhat.com, Mike Snitzer , linux-block@vger.kernel.org, Jens Axboe References: <20210520042228.974083-1-damien.lemoal@wdc.com> <20210520042228.974083-11-damien.lemoal@wdc.com> From: Hannes Reinecke Message-ID: <68203e46-01bc-011c-ab8e-9c94ca60adce@suse.de> Date: Thu, 20 May 2021 08:10:30 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.0 MIME-Version: 1.0 In-Reply-To: <20210520042228.974083-11-damien.lemoal@wdc.com> X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-MIME-Autoconverted: from quoted-printable to 8bit by lists01.pubmisc.prod.ext.phx2.redhat.com id 14K6AgjJ016406 X-loop: dm-devel@redhat.com Subject: Re: [dm-devel] [PATCH v2 10/11] dm: introduce zone append emulation X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=dm-devel-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" T24gNS8yMC8yMSA2OjIyIEFNLCBEYW1pZW4gTGUgTW9hbCB3cm90ZToKPiBGb3Igem9uZWQgdGFy Z2V0cyB0aGF0IGNhbm5vdCBzdXBwb3J0IHpvbmUgYXBwZW5kIG9wZXJhdGlvbnMsIGltcGxlbWVu dAo+IGFuIGVtdWxhdGlvbiB1c2luZyByZWd1bGFyIHdyaXRlIG9wZXJhdGlvbnMuIElmIHRoZSBv cmlnaW5hbCBCSU8KPiBzdWJtaXR0ZWQgYnkgdGhlIHVzZXIgaXMgYSB6b25lIGFwcGVuZCBvcGVy YXRpb24sIGNoYW5nZSBpdHMgY2xvbmUgaW50bwo+IGEgcmVndWxhciB3cml0ZSBvcGVyYXRpb24g ZGlyZWN0ZWQgYXQgdGhlIHRhcmdldCB6b25lIHdyaXRlIHBvaW50ZXIKPiBwb3NpdGlvbi4KPiAK PiBUbyBkbyBzbywgYW4gYXJyYXkgb2Ygd3JpdGUgcG9pbnRlciBvZmZzZXRzICh3cml0ZSBwb2lu dGVyIHBvc2l0aW9uCj4gcmVsYXRpdmUgdG8gdGhlIHN0YXJ0IG9mIGEgem9uZSkgaXMgYWRkZWQg dG8gc3RydWN0IG1hcHBlZF9kZXZpY2UuIEFsbAo+IG9wZXJhdGlvbnMgdGhhdCBtb2RpZnkgYSBz ZXF1ZW50aWFsIHpvbmUgd3JpdGUgcG9pbnRlciAod3JpdGVzLCB6b25lCj4gcmVzZXQsIHpvbmUg ZmluaXNoIGFuZCB6b25lIGFwcGVuZCkgYXJlIGludGVyc2VwdGVkIGluIF9fbWFwX2JpbygpIGFu ZAo+IHByb2Nlc3NlZCB1c2luZyB0aGUgbmV3IGZ1bmN0aW9ucyBkbV96b25lX21hcF9iaW8oKS4K PiAKPiBEZXRlY3Rpb24gb2YgdGhlIHRhcmdldCBhYmlsaXR5IHRvIG5hdGl2ZWx5IHN1cHBvcnQg em9uZSBhcHBlbmQKPiBvcGVyYXRpb25zIGlzIGRvbmUgZnJvbSBkbV90YWJsZV9zZXRfcmVzdHJp Y3Rpb25zKCkgYnkgY2FsbGluZyB0aGUKPiBmdW5jdGlvbiBkbV9zZXRfem9uZXNfcmVzdHJpY3Rp b25zKCkuIEEgdGFyZ2V0IHRoYXQgZG9lcyBub3Qgc3VwcG9ydAo+IHpvbmUgYXBwZW5kIG9wZXJh dGlvbiwgZWl0aGVyIGJ5IGV4cGxpY2l0bHkgZGVjbGFyaW5nIGl0IHVzaW5nIHRoZSBuZXcKPiBz dHJ1Y3QgZG1fdGFyZ2V0IGZpZWxkIHpvbmVfYXBwZW5kX25vdF9zdXBwb3J0ZWQsIG9yIGJlY2F1 c2UgdGhlIGRldmljZQo+IHRhYmxlIGNvbnRhaW5zIGEgbm9uLXpvbmVkIGRldmljZSwgaGFzIGl0 cyBtYXBwZWQgZGV2aWNlIG1hcmtlZCB3aXRoIHRoZQo+IG5ldyBmbGFnIERNRl9aT05FX0FQUEVO RF9FTVVMQVRFRC4gVGhlIGhlbHBlciBmdW5jdGlvbgo+IGRtX2VtdWxhdGVfem9uZV9hcHBlbmQo KSBpcyBpbnRyb2R1Y2VkIHRvIHRlc3QgYSBtYXBwZWQgZGV2aWNlIGZvciB0aGlzCj4gbmV3IGZs YWcuCj4gCj4gQXRvbWljaXR5IG9mIHRoZSB6b25lcyB3cml0ZSBwb2ludGVyIHRyYWNraW5nIGFu ZCB1cGRhdGVzIGlzIGRvbmUgdXNpbmcKPiBhIHpvbmUgd3JpdGUgbG9ja2luZyBtZWNoYW5pc20g YmFzZWQgb24gYSBiaXRtYXAuIFRoaXMgaXMgc2ltaWxhciB0bwo+IHRoZSBibG9jayBsYXllciBt ZXRob2QgYnV0IGJhc2VkIG9uIEJJT3MgcmF0aGVyIHRoYW4gc3RydWN0IHJlcXVlc3QuCj4gQSB6 b25lIHdyaXRlIGxvY2sgaXMgdGFrZW4gaW4gZG1fem9uZV9tYXBfYmlvKCkgZm9yIGFueSBjbG9u ZSBCSU8gd2l0aAo+IGFuIG9wZXJhdGlvbiB0eXBlIHRoYXQgY2hhbmdlcyB0aGUgQklPIHRhcmdl dCB6b25lIHdyaXRlIHBvaW50ZXIKPiBwb3NpdGlvbi4gVGhlIHpvbmUgd3JpdGUgbG9jayBpcyBy ZWxlYXNlZCBpZiB0aGUgY2xvbmUgQklPIGlzIGZhaWxlZAo+IGJlZm9yZSBzdWJtaXNzaW9uIG9y IHdoZW4gZG1fem9uZV9lbmRpbygpIGlzIGNhbGxlZCB3aGVuIHRoZSBjbG9uZSBCSU8KPiBjb21w bGV0ZXMuCj4gCj4gVGhlIHpvbmUgd3JpdGUgbG9jayBiaXRtYXAgb2YgdGhlIG1hcHBlZCBkZXZp Y2UsIHRvZ2V0aGVyIHdpdGggYSBiaXRtYXAKPiBpbmRpY2F0aW5nIHpvbmUgdHlwZXMgKGNvbnZf em9uZXNfYml0bWFwKSBhbmQgdGhlIHdyaXRlIHBvaW50ZXIgb2Zmc2V0Cj4gYXJyYXkgKHp3cF9v ZmZzZXQpIGFyZSBhbGxvY2F0ZWQgYW5kIGluaXRpYWxpemVkIHdpdGggYSBmdWxsIGRldmljZSB6 b25lCj4gcmVwb3J0IGluIGRtX3NldF96b25lc19yZXN0cmljdGlvbnMoKSB1c2luZyB0aGUgZnVu Y3Rpb24KPiBkbV9yZXZhbGlkYXRlX3pvbmVzKCkuCj4gCj4gRm9yIGZhaWxlZCBvcGVyYXRpb25z IHRoYXQgbWF5IGhhdmUgbW9kaWZpZWQgYSB6b25lIHdyaXRlIHBvaW50ZXIsIHRoZQo+IHpvbmUg d3JpdGUgcG9pbnRlciBvZmZzZXQgaXMgbWFya2VkIGFzIGludmFsaWQgaW4gZG1fem9uZV9lbmRp bygpLgo+IFpvbmVzIHdpdGggYW4gaW52YWxpZCB3cml0ZSBwb2ludGVyIG9mZnNldCBhcmUgY2hl Y2tlZCBhbmQgdGhlIHdyaXRlCj4gcG9pbnRlciB1cGRhdGVkIHVzaW5nIGFuIGludGVybmFsIHJl cG9ydCB6b25lIG9wZXJhdGlvbiB3aGVuIHRoZQo+IGZhdWx0eSB6b25lIGlzIGFjY2Vzc2VkIGFn YWluIGJ5IHRoZSB1c2VyLgo+IAo+IEFsbCBmdW5jdGlvbnMgYWRkZWQgZm9yIHRoaXMgZW11bGF0 aW9uIGhhdmUgYSBtaW5pbWFsIG92ZXJoZWFkIGZvcgo+IHpvbmVkIHRhcmdldHMgbmF0aXZlbHkg c3VwcG9ydGluZyB6b25lIGFwcGVuZCBvcGVyYXRpb25zLiBSZWd1bGFyCj4gZGV2aWNlIHRhcmdl dHMgYXJlIGFsc28gbm90IGFmZmVjdGVkLiBUaGUgYWRkZWQgY29kZSBhbHNvIGRvZXMgbm90Cj4g aW1wYWN0IGJ1aWxkcyB3aXRoIENPTkZJR19CTEtfREVWX1pPTkVEIGRpc2FibGVkIGJ5IHN0dWJi aW5nIG91dCBhbGwKPiBkbSB6b25lIHJlbGF0ZWQgZnVuY3Rpb25zLgo+IAo+IFNpZ25lZC1vZmYt Ynk6IERhbWllbiBMZSBNb2FsIDxkYW1pZW4ubGVtb2FsQHdkYy5jb20+Cj4gLS0tCj4gICBkcml2 ZXJzL21kL2RtLWNvcmUuaCAgICAgICAgICB8ICAxNCArCj4gICBkcml2ZXJzL21kL2RtLXRhYmxl LmMgICAgICAgICB8ICAxOSArLQo+ICAgZHJpdmVycy9tZC9kbS16b25lLmMgICAgICAgICAgfCA2 MTUgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKystLQo+ICAgZHJpdmVycy9tZC9kbS5j ICAgICAgICAgICAgICAgfCAgMzkgKystCj4gICBkcml2ZXJzL21kL2RtLmggICAgICAgICAgICAg ICB8ICAxOCArLQo+ICAgaW5jbHVkZS9saW51eC9kZXZpY2UtbWFwcGVyLmggfCAgIDYgKwo+ICAg NiBmaWxlcyBjaGFuZ2VkLCA2NTcgaW5zZXJ0aW9ucygrKSwgNTQgZGVsZXRpb25zKC0pCj4gCj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWQvZG0tY29yZS5oIGIvZHJpdmVycy9tZC9kbS1jb3JlLmgK PiBpbmRleCBjZmFiYzFjOTFmOWYuLjJkYmIwYzdmZjcyMCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJz L21kL2RtLWNvcmUuaAo+ICsrKyBiL2RyaXZlcnMvbWQvZG0tY29yZS5oCj4gQEAgLTExNCw2ICsx MTQsMTIgQEAgc3RydWN0IG1hcHBlZF9kZXZpY2Ugewo+ICAgCWJvb2wgaW5pdF90aW9fcGR1OjE7 Cj4gICAKPiAgIAlzdHJ1Y3Qgc3JjdV9zdHJ1Y3QgaW9fYmFycmllcjsKPiArCj4gKyNpZmRlZiBD T05GSUdfQkxLX0RFVl9aT05FRAo+ICsJdW5zaWduZWQgaW50IG5yX3pvbmVzOwo+ICsJc3Bpbmxv Y2tfdCB6d3Bfb2Zmc2V0X2xvY2s7Cj4gKwl1bnNpZ25lZCBpbnQgKnp3cF9vZmZzZXQ7Cj4gKyNl bmRpZgo+ICAgfTsKPiAgIAo+ICAgLyoKPiBAQCAtMTI4LDYgKzEzNCw3IEBAIHN0cnVjdCBtYXBw ZWRfZGV2aWNlIHsKPiAgICNkZWZpbmUgRE1GX0RFRkVSUkVEX1JFTU9WRSA2Cj4gICAjZGVmaW5l IERNRl9TVVNQRU5ERURfSU5URVJOQUxMWSA3Cj4gICAjZGVmaW5lIERNRl9QT1NUX1NVU1BFTkRJ TkcgOAo+ICsjZGVmaW5lIERNRl9FTVVMQVRFX1pPTkVfQVBQRU5EIDkKPiAgIAo+ICAgdm9pZCBk aXNhYmxlX2Rpc2NhcmQoc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kKTsKPiAgIHZvaWQgZGlzYWJs ZV93cml0ZV9zYW1lKHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCk7Cj4gQEAgLTE0Myw2ICsxNTAs MTMgQEAgc3RhdGljIGlubGluZSBzdHJ1Y3QgZG1fc3RhdHMgKmRtX2dldF9zdGF0cyhzdHJ1Y3Qg bWFwcGVkX2RldmljZSAqbWQpCj4gICAJcmV0dXJuICZtZC0+c3RhdHM7Cj4gICB9Cj4gICAKPiAr c3RhdGljIGlubGluZSBib29sIGRtX2VtdWxhdGVfem9uZV9hcHBlbmQoc3RydWN0IG1hcHBlZF9k ZXZpY2UgKm1kKQo+ICt7Cj4gKwlpZiAoYmxrX3F1ZXVlX2lzX3pvbmVkKG1kLT5xdWV1ZSkpCj4g KwkJcmV0dXJuIHRlc3RfYml0KERNRl9FTVVMQVRFX1pPTkVfQVBQRU5ELCAmbWQtPmZsYWdzKTsK PiArCXJldHVybiBmYWxzZTsKPiArfQo+ICsKPiAgICNkZWZpbmUgRE1fVEFCTEVfTUFYX0RFUFRI IDE2Cj4gICAKPiAgIHN0cnVjdCBkbV90YWJsZSB7Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWQv ZG0tdGFibGUuYyBiL2RyaXZlcnMvbWQvZG0tdGFibGUuYwo+IGluZGV4IGRkOWY2NDhhYjU5OC4u MjFmZGNjZmIxNmNmIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbWQvZG0tdGFibGUuYwo+ICsrKyBi L2RyaXZlcnMvbWQvZG0tdGFibGUuYwo+IEBAIC0xOTgxLDExICsxOTgxLDEyIEBAIHN0YXRpYyBp bnQgZGV2aWNlX3JlcXVpcmVzX3N0YWJsZV9wYWdlcyhzdHJ1Y3QgZG1fdGFyZ2V0ICp0aSwKPiAg IAlyZXR1cm4gYmxrX3F1ZXVlX3N0YWJsZV93cml0ZXMocSk7Cj4gICB9Cj4gICAKPiAtdm9pZCBk bV90YWJsZV9zZXRfcmVzdHJpY3Rpb25zKHN0cnVjdCBkbV90YWJsZSAqdCwgc3RydWN0IHJlcXVl c3RfcXVldWUgKnEsCj4gLQkJCSAgICAgICBzdHJ1Y3QgcXVldWVfbGltaXRzICpsaW1pdHMpCj4g K2ludCBkbV90YWJsZV9zZXRfcmVzdHJpY3Rpb25zKHN0cnVjdCBkbV90YWJsZSAqdCwgc3RydWN0 IHJlcXVlc3RfcXVldWUgKnEsCj4gKwkJCSAgICAgIHN0cnVjdCBxdWV1ZV9saW1pdHMgKmxpbWl0 cykKPiAgIHsKPiAgIAlib29sIHdjID0gZmFsc2UsIGZ1YSA9IGZhbHNlOwo+ICAgCWludCBwYWdl X3NpemUgPSBQQUdFX1NJWkU7Cj4gKwlpbnQgcjsKPiAgIAo+ICAgCS8qCj4gICAJICogQ29weSB0 YWJsZSdzIGxpbWl0cyB0byB0aGUgRE0gZGV2aWNlJ3MgcmVxdWVzdF9xdWV1ZQo+IEBAIC0yMDY0 LDEyICsyMDY1LDIwIEBAIHZvaWQgZG1fdGFibGVfc2V0X3Jlc3RyaWN0aW9ucyhzdHJ1Y3QgZG1f dGFibGUgKnQsIHN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxLAo+ICAgCSAgICBkbV90YWJsZV9hbnlf ZGV2X2F0dHIodCwgZGV2aWNlX2lzX25vdF9yYW5kb20sIE5VTEwpKQo+ICAgCQlibGtfcXVldWVf ZmxhZ19jbGVhcihRVUVVRV9GTEFHX0FERF9SQU5ET00sIHEpOwo+ICAgCj4gLQkvKiBGb3IgYSB6 b25lZCB0YXJnZXQsIHNldHVwIHRoZSB6b25lcyByZWxhdGVkIHF1ZXVlIGF0dHJpYnV0ZXMgKi8K PiAtCWlmIChibGtfcXVldWVfaXNfem9uZWQocSkpCj4gLQkJZG1fc2V0X3pvbmVzX3Jlc3RyaWN0 aW9ucyh0LCBxKTsKPiArCS8qCj4gKwkgKiBGb3IgYSB6b25lZCB0YXJnZXQsIHNldHVwIHRoZSB6 b25lcyByZWxhdGVkIHF1ZXVlIGF0dHJpYnV0ZXMKPiArCSAqIGFuZCByZXNvdXJjZXMgbmVjZXNz YXJ5IGZvciB6b25lIGFwcGVuZCBlbXVsYXRpb24gaWYgbmVjZXNzYXJ5Lgo+ICsJICovCj4gKwlp ZiAoYmxrX3F1ZXVlX2lzX3pvbmVkKHEpKSB7Cj4gKwkJciA9IGRtX3NldF96b25lc19yZXN0cmlj dGlvbnModCwgcSk7Cj4gKwkJaWYgKHIpCj4gKwkJCXJldHVybiByOwo+ICsJfQo+ICAgCj4gICAJ ZG1fdXBkYXRlX2tleXNsb3RfbWFuYWdlcihxLCB0KTsKPiAgIAlibGtfcXVldWVfdXBkYXRlX3Jl YWRhaGVhZChxKTsKPiArCj4gKwlyZXR1cm4gMDsKPiAgIH0KPiAgIAo+ICAgdW5zaWduZWQgaW50 IGRtX3RhYmxlX2dldF9udW1fdGFyZ2V0cyhzdHJ1Y3QgZG1fdGFibGUgKnQpCj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvbWQvZG0tem9uZS5jIGIvZHJpdmVycy9tZC9kbS16b25lLmMKPiBpbmRleCBl ZGMzYmJiNDU2MzcuLmMyOThiYWIyODM5MCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL21kL2RtLXpv bmUuYwo+ICsrKyBiL2RyaXZlcnMvbWQvZG0tem9uZS5jCj4gQEAgLTQsNTUgKzQsNzMgQEAKPiAg ICAqLwo+ICAgCj4gICAjaW5jbHVkZSA8bGludXgvYmxrZGV2Lmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9tbS5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2NoZWQvbW0uaD4KPiArI2luY2x1ZGUgPGxpbnV4 L3NsYWIuaD4KPiAgIAo+ICAgI2luY2x1ZGUgImRtLWNvcmUuaCIKPiAgIAo+ICsjZGVmaW5lIERN X01TR19QUkVGSVggInpvbmUiCj4gKwo+ICsjZGVmaW5lIERNX1pPTkVfSU5WQUxJRF9XUF9PRlNU CQlVSU5UX01BWAo+ICsjZGVmaW5lIERNX1pPTkVfVVBEQVRJTkdfV1BfT0ZTVAkoRE1fWk9ORV9J TlZBTElEX1dQX09GU1QgLSAxKQo+ICsKPiAgIC8qCj4gLSAqIFVzZXIgZmFjaW5nIGRtIGRldmlj ZSBibG9jayBkZXZpY2UgcmVwb3J0IHpvbmUgb3BlcmF0aW9uLiBUaGlzIGNhbGxzIHRoZQo+IC0g KiByZXBvcnRfem9uZXMgb3BlcmF0aW9uIGZvciBlYWNoIHRhcmdldCBvZiBhIGRldmljZSB0YWJs ZS4gVGhpcyBvcGVyYXRpb24gaXMKPiAtICogZ2VuZXJhbGx5IGltcGxlbWVudGVkIGJ5IHRhcmdl dHMgdXNpbmcgZG1fcmVwb3J0X3pvbmVzKCkuCj4gKyAqIEZvciBpbnRlcm5hbCB6b25lIHJlcG9y dHMgYnlwYXNzaW5nIHRoZSB0b3AgQklPIHN1Ym1pc3Npb24gcGF0aC4KPiAgICAqLwo+IC1pbnQg ZG1fYmxrX3JlcG9ydF96b25lcyhzdHJ1Y3QgZ2VuZGlzayAqZGlzaywgc2VjdG9yX3Qgc2VjdG9y LAo+IC0JCQl1bnNpZ25lZCBpbnQgbnJfem9uZXMsIHJlcG9ydF96b25lc19jYiBjYiwgdm9pZCAq ZGF0YSkKPiArc3RhdGljIGludCBkbV9ibGtfZG9fcmVwb3J0X3pvbmVzKHN0cnVjdCBtYXBwZWRf ZGV2aWNlICptZCwgc3RydWN0IGRtX3RhYmxlICp0LAo+ICsJCQkJICBzZWN0b3JfdCBzZWN0b3Is IHVuc2lnbmVkIGludCBucl96b25lcywKPiArCQkJCSAgcmVwb3J0X3pvbmVzX2NiIGNiLCB2b2lk ICpkYXRhKQo+ICAgewo+IC0Jc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kID0gZGlzay0+cHJpdmF0 ZV9kYXRhOwo+IC0Jc3RydWN0IGRtX3RhYmxlICptYXA7Cj4gLQlpbnQgc3JjdV9pZHgsIHJldDsK PiArCXN0cnVjdCBnZW5kaXNrICpkaXNrID0gbWQtPmRpc2s7Cj4gKwlpbnQgcmV0Owo+ICAgCXN0 cnVjdCBkbV9yZXBvcnRfem9uZXNfYXJncyBhcmdzID0gewo+ICAgCQkubmV4dF9zZWN0b3IgPSBz ZWN0b3IsCj4gICAJCS5vcmlnX2RhdGEgPSBkYXRhLAo+ICAgCQkub3JpZ19jYiA9IGNiLAo+ICAg CX07Cj4gICAKPiAtCWlmIChkbV9zdXNwZW5kZWRfbWQobWQpKQo+IC0JCXJldHVybiAtRUFHQUlO Owo+IC0KPiAtCW1hcCA9IGRtX2dldF9saXZlX3RhYmxlKG1kLCAmc3JjdV9pZHgpOwo+IC0JaWYg KCFtYXApIHsKPiAtCQlyZXQgPSAtRUlPOwo+IC0JCWdvdG8gb3V0Owo+IC0JfQo+IC0KPiAgIAlk byB7Cj4gICAJCXN0cnVjdCBkbV90YXJnZXQgKnRndDsKPiAgIAo+IC0JCXRndCA9IGRtX3RhYmxl X2ZpbmRfdGFyZ2V0KG1hcCwgYXJncy5uZXh0X3NlY3Rvcik7Cj4gLQkJaWYgKFdBUk5fT05fT05D RSghdGd0LT50eXBlLT5yZXBvcnRfem9uZXMpKSB7Cj4gLQkJCXJldCA9IC1FSU87Cj4gLQkJCWdv dG8gb3V0Owo+IC0JCX0KPiArCQl0Z3QgPSBkbV90YWJsZV9maW5kX3RhcmdldCh0LCBhcmdzLm5l eHRfc2VjdG9yKTsKPiArCQlpZiAoV0FSTl9PTl9PTkNFKCF0Z3QtPnR5cGUtPnJlcG9ydF96b25l cykpCj4gKwkJCXJldHVybiAtRUlPOwo+ICAgCj4gICAJCWFyZ3MudGd0ID0gdGd0Owo+ICAgCQly ZXQgPSB0Z3QtPnR5cGUtPnJlcG9ydF96b25lcyh0Z3QsICZhcmdzLAo+ICAgCQkJCQkgICAgICBu cl96b25lcyAtIGFyZ3Muem9uZV9pZHgpOwo+ICAgCQlpZiAocmV0IDwgMCkKPiAtCQkJZ290byBv dXQ7Cj4gKwkJCXJldHVybiByZXQ7Cj4gICAJfSB3aGlsZSAoYXJncy56b25lX2lkeCA8IG5yX3pv bmVzICYmCj4gICAJCSBhcmdzLm5leHRfc2VjdG9yIDwgZ2V0X2NhcGFjaXR5KGRpc2spKTsKPiAg IAo+IC0JcmV0ID0gYXJncy56b25lX2lkeDsKPiAtb3V0Ogo+ICsJcmV0dXJuIGFyZ3Muem9uZV9p ZHg7Cj4gK30KPiArCj4gKy8qCj4gKyAqIFVzZXIgZmFjaW5nIGRtIGRldmljZSBibG9jayBkZXZp Y2UgcmVwb3J0IHpvbmUgb3BlcmF0aW9uLiBUaGlzIGNhbGxzIHRoZQo+ICsgKiByZXBvcnRfem9u ZXMgb3BlcmF0aW9uIGZvciBlYWNoIHRhcmdldCBvZiBhIGRldmljZSB0YWJsZS4gVGhpcyBvcGVy YXRpb24gaXMKPiArICogZ2VuZXJhbGx5IGltcGxlbWVudGVkIGJ5IHRhcmdldHMgdXNpbmcgZG1f cmVwb3J0X3pvbmVzKCkuCj4gKyAqLwo+ICtpbnQgZG1fYmxrX3JlcG9ydF96b25lcyhzdHJ1Y3Qg Z2VuZGlzayAqZGlzaywgc2VjdG9yX3Qgc2VjdG9yLAo+ICsJCQl1bnNpZ25lZCBpbnQgbnJfem9u ZXMsIHJlcG9ydF96b25lc19jYiBjYiwgdm9pZCAqZGF0YSkKPiArewo+ICsJc3RydWN0IG1hcHBl ZF9kZXZpY2UgKm1kID0gZGlzay0+cHJpdmF0ZV9kYXRhOwo+ICsJc3RydWN0IGRtX3RhYmxlICpt YXA7Cj4gKwlpbnQgc3JjdV9pZHgsIHJldDsKPiArCj4gKwlpZiAoZG1fc3VzcGVuZGVkX21kKG1k KSkKPiArCQlyZXR1cm4gLUVBR0FJTjsKPiArCj4gKwltYXAgPSBkbV9nZXRfbGl2ZV90YWJsZSht ZCwgJnNyY3VfaWR4KTsKPiArCWlmICghbWFwKQo+ICsJCXJldHVybiAtRUlPOwo+ICsKPiArCXJl dCA9IGRtX2Jsa19kb19yZXBvcnRfem9uZXMobWQsIG1hcCwgc2VjdG9yLCBucl96b25lcywgY2Is IGRhdGEpOwo+ICsKPiAgIAlkbV9wdXRfbGl2ZV90YWJsZShtZCwgc3JjdV9pZHgpOwo+ICsKPiAg IAlyZXR1cm4gcmV0Owo+ICAgfQo+ICAgCj4gQEAgLTEyMSwxNiArMTM5LDU1MSBAQCBib29sIGRt X2lzX3pvbmVfd3JpdGUoc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kLCBzdHJ1Y3QgYmlvICpiaW8p Cj4gICAJfQo+ICAgfQo+ICAgCj4gLXZvaWQgZG1fc2V0X3pvbmVzX3Jlc3RyaWN0aW9ucyhzdHJ1 Y3QgZG1fdGFibGUgKnQsIHN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxKQo+ICt2b2lkIGRtX2luaXRf em9uZWRfZGV2KHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCkKPiAgIHsKPiAtCWlmICghYmxrX3F1 ZXVlX2lzX3pvbmVkKHEpKQo+IC0JCXJldHVybjsKPiArCXNwaW5fbG9ja19pbml0KCZtZC0+endw X29mZnNldF9sb2NrKTsKPiArfQo+ICsKPiArdm9pZCBkbV9jbGVhbnVwX3pvbmVkX2RldihzdHJ1 Y3QgbWFwcGVkX2RldmljZSAqbWQpCj4gK3sKPiArCXN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxID0g bWQtPnF1ZXVlOwo+ICsKPiArCWlmIChxKSB7Cj4gKwkJa2ZyZWUocS0+Y29udl96b25lc19iaXRt YXApOwo+ICsJCXEtPmNvbnZfem9uZXNfYml0bWFwID0gTlVMTDsKPiArCQlrZnJlZShxLT5zZXFf em9uZXNfd2xvY2spOwo+ICsJCXEtPnNlcV96b25lc193bG9jayA9IE5VTEw7Cj4gKwl9Cj4gKwo+ ICsJa3ZmcmVlKG1kLT56d3Bfb2Zmc2V0KTsKPiArCW1kLT56d3Bfb2Zmc2V0ID0gTlVMTDsKPiAr CW1kLT5ucl96b25lcyA9IDA7Cj4gK30KPiArCj4gK3N0YXRpYyB1bnNpZ25lZCBpbnQgZG1fZ2V0 X3pvbmVfd3Bfb2Zmc2V0KHN0cnVjdCBibGtfem9uZSAqem9uZSkKPiArewo+ICsJc3dpdGNoICh6 b25lLT5jb25kKSB7Cj4gKwljYXNlIEJMS19aT05FX0NPTkRfSU1QX09QRU46Cj4gKwljYXNlIEJM S19aT05FX0NPTkRfRVhQX09QRU46Cj4gKwljYXNlIEJMS19aT05FX0NPTkRfQ0xPU0VEOgo+ICsJ CXJldHVybiB6b25lLT53cCAtIHpvbmUtPnN0YXJ0Owo+ICsJY2FzZSBCTEtfWk9ORV9DT05EX0ZV TEw6Cj4gKwkJcmV0dXJuIHpvbmUtPmxlbjsKPiArCWNhc2UgQkxLX1pPTkVfQ09ORF9FTVBUWToK PiArCWNhc2UgQkxLX1pPTkVfQ09ORF9OT1RfV1A6Cj4gKwljYXNlIEJMS19aT05FX0NPTkRfT0ZG TElORToKPiArCWNhc2UgQkxLX1pPTkVfQ09ORF9SRUFET05MWToKPiArCWRlZmF1bHQ6Cj4gKwkJ LyoKPiArCQkgKiBDb252ZW50aW9uYWwsIG9mZmxpbmUgYW5kIHJlYWQtb25seSB6b25lcyBkbyBu b3QgaGF2ZSBhIHZhbGlkCj4gKwkJICogd3JpdGUgcG9pbnRlci4gVXNlIDAgYXMgZm9yIGFuIGVt cHR5IHpvbmUuCj4gKwkJICovCj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgZG1fem9uZV9yZXZhbGlkYXRlX2NiKHN0cnVjdCBibGtfem9uZSAqem9uZSwgdW5zaWdu ZWQgaW50IGlkeCwKPiArCQkJCSB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgbWFwcGVkX2Rl dmljZSAqbWQgPSBkYXRhOwo+ICsJc3RydWN0IHJlcXVlc3RfcXVldWUgKnEgPSBtZC0+cXVldWU7 Cj4gKwo+ICsJc3dpdGNoICh6b25lLT50eXBlKSB7Cj4gKwljYXNlIEJMS19aT05FX1RZUEVfQ09O VkVOVElPTkFMOgo+ICsJCWlmICghcS0+Y29udl96b25lc19iaXRtYXApIHsKPiArCQkJcS0+Y29u dl96b25lc19iaXRtYXAgPQo+ICsJCQkJa2NhbGxvYyhCSVRTX1RPX0xPTkdTKHEtPm5yX3pvbmVz KSwKPiArCQkJCQlzaXplb2YodW5zaWduZWQgbG9uZyksIEdGUF9OT0lPKTsKPiArCQkJaWYgKCFx LT5jb252X3pvbmVzX2JpdG1hcCkKPiArCQkJCXJldHVybiAtRU5PTUVNOwo+ICsJCX0KPiArCQlz ZXRfYml0KGlkeCwgcS0+Y29udl96b25lc19iaXRtYXApOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBC TEtfWk9ORV9UWVBFX1NFUVdSSVRFX1JFUToKPiArCWNhc2UgQkxLX1pPTkVfVFlQRV9TRVFXUklU RV9QUkVGOgo+ICsJCWlmICghcS0+c2VxX3pvbmVzX3dsb2NrKSB7Cj4gKwkJCXEtPnNlcV96b25l c193bG9jayA9Cj4gKwkJCQlrY2FsbG9jKEJJVFNfVE9fTE9OR1MocS0+bnJfem9uZXMpLAo+ICsJ CQkJCXNpemVvZih1bnNpZ25lZCBsb25nKSwgR0ZQX05PSU8pOwo+ICsJCQlpZiAoIXEtPnNlcV96 b25lc193bG9jaykKPiArCQkJCXJldHVybiAtRU5PTUVNOwo+ICsJCX0KPiArCQlpZiAoIW1kLT56 d3Bfb2Zmc2V0KSB7Cj4gKwkJCW1kLT56d3Bfb2Zmc2V0ID0KPiArCQkJCWt2Y2FsbG9jKHEtPm5y X3pvbmVzLCBzaXplb2YodW5zaWduZWQgaW50KSwKPiArCQkJCQkgR0ZQX05PSU8pOwo+ICsJCQlp ZiAoIW1kLT56d3Bfb2Zmc2V0KQo+ICsJCQkJcmV0dXJuIC1FTk9NRU07Cj4gKwkJfQo+ICsJCW1k LT56d3Bfb2Zmc2V0W2lkeF0gPSBkbV9nZXRfem9uZV93cF9vZmZzZXQoem9uZSk7Cj4gKwo+ICsJ CWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlETUVSUigiSW52YWxpZCB6b25lIHR5cGUgMHgleCBh dCBzZWN0b3JzICVsbHUiLAo+ICsJCSAgICAgIChpbnQpem9uZS0+dHlwZSwgem9uZS0+c3RhcnQp Owo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICsvKgo+ICsgKiBSZXZhbGlkYXRlIHRoZSB6b25lcyBvZiBhIG1hcHBlZCBkZXZpY2UgdG8gaW5p dGlhbGl6ZSByZXNvdXJjZSBuZWNlc3NhcnkKPiArICogZm9yIHpvbmUgYXBwZW5kIGVtdWxhdGlv bi4gTm90ZSB0aGF0IHdlIGNhbm5vdCBzaW1wbHkgdXNlIHRoZSBibG9jayBsYXllcgo+ICsgKiBi bGtfcmV2YWxpZGF0ZV9kaXNrX3pvbmVzKCkgZnVuY3Rpb24gaGVyZSBhcyB0aGUgbWFwcGVkIGRl dmljZSBpcyBzdXNwZW5kZWQKPiArICogKHRoaXMgaXMgY2FsbGVkIGZyb20gX19iaW5kKCkgY29u dGV4dCkuCj4gKyAqLwo+ICtzdGF0aWMgaW50IGRtX3JldmFsaWRhdGVfem9uZXMoc3RydWN0IG1h cHBlZF9kZXZpY2UgKm1kLCBzdHJ1Y3QgZG1fdGFibGUgKnQpCj4gK3sKPiArCXN0cnVjdCByZXF1 ZXN0X3F1ZXVlICpxID0gbWQtPnF1ZXVlOwo+ICsJaW50IHJldDsKPiArCj4gKwkvKgo+ICsJICog Q2hlY2sgaWYgc29tZXRoaW5nIGNoYW5nZWQuIElmIHllcywgY2xlYW51cCB0aGUgY3VycmVudCBy ZXNvdXJjZXMKPiArCSAqIGFuZCByZWFsbG9jYXRlIGV2ZXJ5dGhpbmcuCj4gKwkgKi8KPiArCWlm ICghcS0+bnJfem9uZXMgfHwgcS0+bnJfem9uZXMgIT0gbWQtPm5yX3pvbmVzKQo+ICsJCWRtX2Ns ZWFudXBfem9uZWRfZGV2KG1kKTsKPiArCWlmIChtZC0+bnJfem9uZXMpCj4gKwkJcmV0dXJuIDA7 Cj4gKwo+ICsJLyogU2NhbiBhbGwgem9uZXMgdG8gaW5pdGlhbGl6ZSBldmVyeXRoaW5nICovCj4g KwlyZXQgPSBkbV9ibGtfZG9fcmVwb3J0X3pvbmVzKG1kLCB0LCAwLCBxLT5ucl96b25lcywKPiAr CQkJCSAgICAgZG1fem9uZV9yZXZhbGlkYXRlX2NiLCBtZCk7Cj4gKwlpZiAocmV0IDwgMCkKPiAr CQlnb3RvIGVycjsKPiArCWlmIChyZXQgIT0gcS0+bnJfem9uZXMpIHsKPiArCQlyZXQgPSAtRUlP Owo+ICsJCWdvdG8gZXJyOwo+ICsJfQo+ICsKPiArCW1kLT5ucl96b25lcyA9IHEtPm5yX3pvbmVz Owo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXJyOgo+ICsJRE1FUlIoIlJldmFsaWRhdGUgem9u ZXMgZmFpbGVkICVkIiwgcmV0KTsKPiArCWRtX2NsZWFudXBfem9uZWRfZGV2KG1kKTsKPiArCXJl dHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZGV2aWNlX25vdF96b25lX2FwcGVuZF9j YXBhYmxlKHN0cnVjdCBkbV90YXJnZXQgKnRpLAo+ICsJCQkJCSAgc3RydWN0IGRtX2RldiAqZGV2 LCBzZWN0b3JfdCBzdGFydCwKPiArCQkJCQkgIHNlY3Rvcl90IGxlbiwgdm9pZCAqZGF0YSkKPiAr ewo+ICsJcmV0dXJuICFibGtfcXVldWVfaXNfem9uZWQoYmRldl9nZXRfcXVldWUoZGV2LT5iZGV2 KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBib29sIGRtX3RhYmxlX3N1cHBvcnRzX3pvbmVfYXBwZW5k KHN0cnVjdCBkbV90YWJsZSAqdCkKPiArewo+ICsJc3RydWN0IGRtX3RhcmdldCAqdGk7Cj4gKwl1 bnNpZ25lZCBpbnQgaTsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgZG1fdGFibGVfZ2V0X251bV90 YXJnZXRzKHQpOyBpKyspIHsKPiArCQl0aSA9IGRtX3RhYmxlX2dldF90YXJnZXQodCwgaSk7Cj4g Kwo+ICsJCWlmICh0aS0+ZW11bGF0ZV96b25lX2FwcGVuZCkKPiArCQkJcmV0dXJuIGZhbHNlOwo+ ICsKPiArCQlpZiAoIXRpLT50eXBlLT5pdGVyYXRlX2RldmljZXMgfHwKPiArCQkgICAgdGktPnR5 cGUtPml0ZXJhdGVfZGV2aWNlcyh0aSwgZGV2aWNlX25vdF96b25lX2FwcGVuZF9jYXBhYmxlLCBO VUxMKSkKPiArCQkJcmV0dXJuIGZhbHNlOwo+ICsJfQo+ICsKPiArCXJldHVybiB0cnVlOwo+ICt9 Cj4gKwo+ICtpbnQgZG1fc2V0X3pvbmVzX3Jlc3RyaWN0aW9ucyhzdHJ1Y3QgZG1fdGFibGUgKnQs IHN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxKQo+ICt7Cj4gKwlzdHJ1Y3QgbWFwcGVkX2RldmljZSAq bWQgPSB0LT5tZDsKPiAgIAo+ICAgCS8qCj4gICAJICogRm9yIGEgem9uZWQgdGFyZ2V0LCB0aGUg bnVtYmVyIG9mIHpvbmVzIHNob3VsZCBiZSB1cGRhdGVkIGZvciB0aGUKPiAtCSAqIGNvcnJlY3Qg dmFsdWUgdG8gYmUgZXhwb3NlZCBpbiBzeXNmcyBxdWV1ZS9ucl96b25lcy4gRm9yIGEgQklPIGJh c2VkCj4gLQkgKiB0YXJnZXQsIHRoaXMgaXMgYWxsIHRoYXQgaXMgbmVlZGVkLgo+ICsJICogY29y cmVjdCB2YWx1ZSB0byBiZSBleHBvc2VkIGluIHN5c2ZzIHF1ZXVlL25yX3pvbmVzLgo+ICAgCSAq Lwo+ICAgCVdBUk5fT05fT05DRShxdWV1ZV9pc19tcShxKSk7Cj4gLQlxLT5ucl96b25lcyA9IGJs a2Rldl9ucl96b25lcyh0LT5tZC0+ZGlzayk7Cj4gKwlxLT5ucl96b25lcyA9IGJsa2Rldl9ucl96 b25lcyhtZC0+ZGlzayk7Cj4gKwo+ICsJLyogQ2hlY2sgaWYgem9uZSBhcHBlbmQgaXMgbmF0aXZl bHkgc3VwcG9ydGVkICovCj4gKwlpZiAoZG1fdGFibGVfc3VwcG9ydHNfem9uZV9hcHBlbmQodCkp IHsKPiArCQljbGVhcl9iaXQoRE1GX0VNVUxBVEVfWk9ORV9BUFBFTkQsICZtZC0+ZmxhZ3MpOwo+ ICsJCWRtX2NsZWFudXBfem9uZWRfZGV2KG1kKTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4g KwkvKgo+ICsJICogTWFyayB0aGUgbWFwcGVkIGRldmljZSBhcyBuZWVkaW5nIHpvbmUgYXBwZW5k IGVtdWxhdGlvbiBhbmQKPiArCSAqIGluaXRpYWxpemUgdGhlIGVtdWxhdGlvbiByZXNvdXJjZXMg b25jZSB0aGUgY2FwYWNpdHkgaXMgc2V0Lgo+ICsJICovCj4gKwlzZXRfYml0KERNRl9FTVVMQVRF X1pPTkVfQVBQRU5ELCAmbWQtPmZsYWdzKTsKPiArCWlmICghZ2V0X2NhcGFjaXR5KG1kLT5kaXNr KSkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwlyZXR1cm4gZG1fcmV2YWxpZGF0ZV96b25lcyhtZCwg dCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZG1fdXBkYXRlX3pvbmVfd3Bfb2Zmc2V0X2NiKHN0 cnVjdCBibGtfem9uZSAqem9uZSwgdW5zaWduZWQgaW50IGlkeCwKPiArCQkJCSAgICAgICB2b2lk ICpkYXRhKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgKndwX29mZnNldCA9IGRhdGE7Cj4gKwo+ICsJ KndwX29mZnNldCA9IGRtX2dldF96b25lX3dwX29mZnNldCh6b25lKTsKPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIGludCBkbV91cGRhdGVfem9uZV93cF9vZmZzZXQoc3RydWN0 IG1hcHBlZF9kZXZpY2UgKm1kLCB1bnNpZ25lZCBpbnQgem5vLAo+ICsJCQkJICAgIHVuc2lnbmVk IGludCAqd3Bfb2ZzdCkKPiArewo+ICsJc2VjdG9yX3Qgc2VjdG9yID0gem5vICogYmxrX3F1ZXVl X3pvbmVfc2VjdG9ycyhtZC0+cXVldWUpOwo+ICsJdW5zaWduZWQgaW50IG5vaW9fZmxhZzsKPiAr CXN0cnVjdCBkbV90YWJsZSAqdDsKPiArCWludCBzcmN1X2lkeCwgcmV0Owo+ICsKPiArCXQgPSBk bV9nZXRfbGl2ZV90YWJsZShtZCwgJnNyY3VfaWR4KTsKPiArCWlmICghdCkKPiArCQlyZXR1cm4g LUVJTzsKPiArCj4gKwkvKgo+ICsJICogRW5zdXJlIHRoYXQgYWxsIG1lbW9yeSBhbGxvY2F0aW9u cyBpbiB0aGlzIGNvbnRleHQgYXJlIGRvbmUgYXMgaWYKPiArCSAqIEdGUF9OT0lPIHdhcyBzcGVj aWZpZWQuCj4gKwkgKi8KPiArCW5vaW9fZmxhZyA9IG1lbWFsbG9jX25vaW9fc2F2ZSgpOwo+ICsJ cmV0ID0gZG1fYmxrX2RvX3JlcG9ydF96b25lcyhtZCwgdCwgc2VjdG9yLCAxLAo+ICsJCQkJICAg ICBkbV91cGRhdGVfem9uZV93cF9vZmZzZXRfY2IsIHdwX29mc3QpOwo+ICsJbWVtYWxsb2Nfbm9p b19yZXN0b3JlKG5vaW9fZmxhZyk7Cj4gKwo+ICsJZG1fcHV0X2xpdmVfdGFibGUobWQsIHNyY3Vf aWR4KTsKPiArCj4gKwlpZiAocmV0ICE9IDEpCj4gKwkJcmV0dXJuIC1FSU87Cj4gKwo+ICsJcmV0 dXJuIDA7Cj4gK30KPiArCj4gKy8qCj4gKyAqIEZpcnN0IHBoYXNlIG9mIEJJTyBtYXBwaW5nIGZv ciB0YXJnZXRzIHdpdGggem9uZSBhcHBlbmQgZW11bGF0aW9uOgo+ICsgKiBjaGVjayBhbGwgQklP IHRoYXQgY2hhbmdlIGEgem9uZSB3cml0ZXIgcG9pbnRlciBhbmQgY2hhbmdlIHpvbmUKPiArICog YXBwZW5kIG9wZXJhdGlvbnMgaW50byByZWd1bGFyIHdyaXRlIG9wZXJhdGlvbnMuCj4gKyAqLwo+ ICtzdGF0aWMgYm9vbCBkbV96b25lX21hcF9iaW9fYmVnaW4oc3RydWN0IG1hcHBlZF9kZXZpY2Ug Km1kLAo+ICsJCQkJICBzdHJ1Y3QgYmlvICpvcmlnX2Jpbywgc3RydWN0IGJpbyAqY2xvbmUpCj4g K3sKPiArCXNlY3Rvcl90IHpvbmVfc2VjdG9ycyA9IGJsa19xdWV1ZV96b25lX3NlY3RvcnMobWQt PnF1ZXVlKTsKPiArCXVuc2lnbmVkIGludCB6bm8gPSBiaW9fem9uZV9ubyhvcmlnX2Jpbyk7Cj4g Kwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsJYm9vbCBnb29kX2lvID0gZmFsc2U7Cj4gKwo+ICsJ c3Bpbl9sb2NrX2lycXNhdmUoJm1kLT56d3Bfb2Zmc2V0X2xvY2ssIGZsYWdzKTsKPiArCj4gKwkv Kgo+ICsJICogSWYgdGhlIHRhcmdldCB6b25lIGlzIGluIGFuIGVycm9yIHN0YXRlLCByZWNvdmVy IGJ5IGluc3BlY3RpbmcgdGhlCj4gKwkgKiB6b25lIHRvIGdldCBpdHMgY3VycmVudCB3cml0ZSBw b2ludGVyIHBvc2l0aW9uLiBOb3RlIHRoYXQgc2luY2UgdGhlCj4gKwkgKiB0YXJnZXQgem9uZSBp cyBhbHJlYWR5IGxvY2tlZCwgYSBCSU8gaXNzdWluZyBjb250ZXh0IHNob3VsZCBuZXZlcgo+ICsJ ICogc2VlIHRoZSB6b25lIHdyaXRlIGluIHRoZSBETV9aT05FX1VQREFUSU5HX1dQX09GU1Qgc3Rh dGUuCj4gKwkgKi8KPiArCWlmIChtZC0+endwX29mZnNldFt6bm9dID09IERNX1pPTkVfSU5WQUxJ RF9XUF9PRlNUKSB7Cj4gKwkJdW5zaWduZWQgaW50IHdwX29mZnNldDsKPiArCQlpbnQgcmV0Owo+ ICsKPiArCQltZC0+endwX29mZnNldFt6bm9dID0gRE1fWk9ORV9VUERBVElOR19XUF9PRlNUOwo+ ICsKPiArCQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZtZC0+endwX29mZnNldF9sb2NrLCBmbGFn cyk7Cj4gKwkJcmV0ID0gZG1fdXBkYXRlX3pvbmVfd3Bfb2Zmc2V0KG1kLCB6bm8sICZ3cF9vZmZz ZXQpOwo+ICsJCXNwaW5fbG9ja19pcnFzYXZlKCZtZC0+endwX29mZnNldF9sb2NrLCBmbGFncyk7 Cj4gKwo+ICsJCWlmIChyZXQpIHsKPiArCQkJbWQtPnp3cF9vZmZzZXRbem5vXSA9IERNX1pPTkVf SU5WQUxJRF9XUF9PRlNUOwo+ICsJCQlnb3RvIG91dDsKPiArCQl9Cj4gKwkJbWQtPnp3cF9vZmZz ZXRbem5vXSA9IHdwX29mZnNldDsKPiArCX0gZWxzZSBpZiAobWQtPnp3cF9vZmZzZXRbem5vXSA9 PSBETV9aT05FX1VQREFUSU5HX1dQX09GU1QpIHsKPiArCQlETVdBUk5fTElNSVQoIkludmFsaWQg RE1fWk9ORV9VUERBVElOR19XUF9PRlNUIHN0YXRlIik7Cj4gKwkJZ290byBvdXQ7Cj4gKwl9Cj4g Kwo+ICsJc3dpdGNoIChiaW9fb3Aob3JpZ19iaW8pKSB7Cj4gKwljYXNlIFJFUV9PUF9XUklURV9a RVJPRVM6Cj4gKwljYXNlIFJFUV9PUF9XUklURV9TQU1FOgo+ICsJY2FzZSBSRVFfT1BfV1JJVEU6 Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFJFUV9PUF9aT05FX1JFU0VUOgo+ICsJY2FzZSBSRVFfT1Bf Wk9ORV9GSU5JU0g6Cj4gKwkJZ290byBnb29kOwo+ICsJY2FzZSBSRVFfT1BfWk9ORV9BUFBFTkQ6 Cj4gKwkJLyoKPiArCQkgKiBDaGFuZ2Ugem9uZSBhcHBlbmQgb3BlcmF0aW9ucyBpbnRvIGEgbm9u LW1lcmdlYWJsZSByZWd1bGFyCj4gKwkJICogd3JpdGVzIGRpcmVjdGVkIGF0IHRoZSBjdXJyZW50 IHdyaXRlIHBvaW50ZXIgcG9zaXRpb24gb2YgdGhlCj4gKwkJICogdGFyZ2V0IHpvbmUuCj4gKwkJ ICovCj4gKwkJY2xvbmUtPmJpX29wZiA9IFJFUV9PUF9XUklURSB8IFJFUV9OT01FUkdFIHwKPiAr CQkJKG9yaWdfYmlvLT5iaV9vcGYgJiAoflJFUV9PUF9NQVNLKSk7Cj4gKwkJY2xvbmUtPmJpX2l0 ZXIuYmlfc2VjdG9yID0KPiArCQkJb3JpZ19iaW8tPmJpX2l0ZXIuYmlfc2VjdG9yICsgbWQtPnp3 cF9vZmZzZXRbem5vXTsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJRE1XQVJOX0xJTUlU KCJJbnZhbGlkIEJJTyBvcGVyYXRpb24iKTsKPiArCQlnb3RvIG91dDsKPiArCX0KPiArCj4gKwkv KiBDYW5ub3Qgd3JpdGUgdG8gYSBmdWxsIHpvbmUgKi8KPiArCWlmIChtZC0+endwX29mZnNldFt6 bm9dID49IHpvbmVfc2VjdG9ycykKPiArCQlnb3RvIG91dDsKPiArCj4gKwkvKiBXcml0ZXMgbXVz dCBiZSBhbGlnbmVkIHRvIHRoZSB6b25lIHdyaXRlIHBvaW50ZXIgKi8KPiArCWlmICgoY2xvbmUt PmJpX2l0ZXIuYmlfc2VjdG9yICYgKHpvbmVfc2VjdG9ycyAtIDEpKSAhPSBtZC0+endwX29mZnNl dFt6bm9dKQo+ICsJCWdvdG8gb3V0Owo+ICsKPiArZ29vZDoKPiArCWdvb2RfaW8gPSB0cnVlOwo+ ICsKPiArb3V0Ogo+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmbWQtPnp3cF9vZmZzZXRfbG9j aywgZmxhZ3MpOwoKSSdtIG5vdCBoYXBweSB3aXRoIHRoZSBzcGlubG9jay4gQ2FuJ3QgdGhlIHNh bWUgZWZmZWN0IGJlIGFjaGlldmVkIHdpdGggCnNvbWUgY2xldmVyIFJFQURfT05DRSgpL1dSSVRF X09OQ0UvY21wZXhjaCBtYWdpYz8KRXNwZWNpYWxseSBhcyB5b3UgaGF2ZSBhIHNlcGFyYXRlICd6 b25lIGxvY2snIG1lY2hhbmlzbSAuLi4KCj4gKwo+ICsJcmV0dXJuIGdvb2RfaW87Cj4gK30KPiAr Cj4gKy8qCj4gKyAqIFNlY29uZCBwaGFzZSBvZiBCSU8gbWFwcGluZyBmb3IgdGFyZ2V0cyB3aXRo IHpvbmUgYXBwZW5kIGVtdWxhdGlvbjoKPiArICogdXBkYXRlIHRoZSB6b25lIHdyaXRlIHBvaW50 ZXIgb2Zmc2V0IGFycmF5IHRvIGFjY291bnQgZm9yIHRoZSBhZGRpdGlvbmFsCj4gKyAqIGRhdGEg d3JpdHRlbiB0byBhIHpvbmUuIE5vdGUgdGhhdCBhdCB0aGlzIHBvaW50LCB0aGUgcmVtYXBwZWQg Y2xvbmUgQklPCj4gKyAqIG1heSBhbHJlYWR5IGhhdmUgY29tcGxldGVkLCBzbyB3ZSBkbyBub3Qg dG91Y2ggaXQuCj4gKyAqLwo+ICtzdGF0aWMgYmxrX3N0YXR1c190IGRtX3pvbmVfbWFwX2Jpb19l bmQoc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kLAo+ICsJCQkJCXN0cnVjdCBiaW8gKm9yaWdfYmlv LAo+ICsJCQkJCXVuc2lnbmVkIGludCBucl9zZWN0b3JzKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQg em5vID0gYmlvX3pvbmVfbm8ob3JpZ19iaW8pOwo+ICsJYmxrX3N0YXR1c190IHN0cyA9IEJMS19T VFNfT0s7Cj4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsKPiArCXNwaW5fbG9ja19pcnFzYXZl KCZtZC0+endwX29mZnNldF9sb2NrLCBmbGFncyk7Cj4gKwo+ICsJLyogVXBkYXRlIHRoZSB6b25l IHdwIG9mZnNldCAqLwo+ICsJc3dpdGNoIChiaW9fb3Aob3JpZ19iaW8pKSB7Cj4gKwljYXNlIFJF UV9PUF9aT05FX1JFU0VUOgo+ICsJCW1kLT56d3Bfb2Zmc2V0W3pub10gPSAwOwo+ICsJCWJyZWFr Owo+ICsJY2FzZSBSRVFfT1BfWk9ORV9GSU5JU0g6Cj4gKwkJbWQtPnp3cF9vZmZzZXRbem5vXSA9 IGJsa19xdWV1ZV96b25lX3NlY3RvcnMobWQtPnF1ZXVlKTsKPiArCQlicmVhazsKPiArCWNhc2Ug UkVRX09QX1dSSVRFX1pFUk9FUzoKPiArCWNhc2UgUkVRX09QX1dSSVRFX1NBTUU6Cj4gKwljYXNl IFJFUV9PUF9XUklURToKPiArCQltZC0+endwX29mZnNldFt6bm9dICs9IG5yX3NlY3RvcnM7Cj4g KwkJYnJlYWs7Cj4gKwljYXNlIFJFUV9PUF9aT05FX0FQUEVORDoKPiArCQkvKgo+ICsJCSAqIENo ZWNrIHRoYXQgdGhlIHRhcmdldCBkaWQgbm90IHRydW5jYXRlIHRoZSB3cml0ZSBvcGVyYXRpb24K PiArCQkgKiBlbXVsYXRpbmcgYSB6b25lIGFwcGVuZC4KPiArCQkgKi8KPiArCQlpZiAobnJfc2Vj dG9ycyAhPSBiaW9fc2VjdG9ycyhvcmlnX2JpbykpIHsKPiArCQkJRE1XQVJOX0xJTUlUKCJUcnVu Y2F0ZWQgd3JpdGUgZm9yIHpvbmUgYXBwZW5kIik7Cj4gKwkJCXN0cyA9IEJMS19TVFNfSU9FUlI7 Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCQltZC0+endwX29mZnNldFt6bm9dICs9IG5yX3NlY3Rv cnM7Cj4gKwkJYnJlYWs7Cj4gKwlkZWZhdWx0Ogo+ICsJCURNV0FSTl9MSU1JVCgiSW52YWxpZCBC SU8gb3BlcmF0aW9uIik7Cj4gKwkJc3RzID0gQkxLX1NUU19JT0VSUjsKPiArCQlicmVhazsKPiAr CX0KPiArCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZtZC0+endwX29mZnNldF9sb2NrLCBm bGFncyk7CgpZb3UgZG9uJ3QgbmVlZCB0aGUgc3BpbmxvY2sgaGVyZTsgdXNpbmcgV1JJVEVfT05D RSgpIHNob3VsZCBiZSBzdWZmaWNpZW50LgoKPiArCj4gKwlyZXR1cm4gc3RzOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW5saW5lIHZvaWQgZG1fem9uZV9sb2NrKHN0cnVjdCByZXF1ZXN0X3F1ZXVlICpx LAo+ICsJCQkJdW5zaWduZWQgaW50IHpubywgc3RydWN0IGJpbyAqY2xvbmUpCj4gK3sKPiArCWlm IChXQVJOX09OX09OQ0UoYmlvX2ZsYWdnZWQoY2xvbmUsIEJJT19aT05FX1dSSVRFX0xPQ0tFRCkp KQo+ICsJCXJldHVybjsKPiArCj4gKwl3YWl0X29uX2JpdF9sb2NrX2lvKHEtPnNlcV96b25lc193 bG9jaywgem5vLCBUQVNLX1VOSU5URVJSVVBUSUJMRSk7Cj4gKwliaW9fc2V0X2ZsYWcoY2xvbmUs IEJJT19aT05FX1dSSVRFX0xPQ0tFRCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBk bV96b25lX3VubG9jayhzdHJ1Y3QgcmVxdWVzdF9xdWV1ZSAqcSwKPiArCQkJCSAgdW5zaWduZWQg aW50IHpubywgc3RydWN0IGJpbyAqY2xvbmUpCj4gK3sKPiArCWlmICghYmlvX2ZsYWdnZWQoY2xv bmUsIEJJT19aT05FX1dSSVRFX0xPQ0tFRCkpCj4gKwkJcmV0dXJuOwo+ICsKPiArCVdBUk5fT05f T05DRSghdGVzdF9iaXQoem5vLCBxLT5zZXFfem9uZXNfd2xvY2spKTsKPiArCWNsZWFyX2JpdF91 bmxvY2soem5vLCBxLT5zZXFfem9uZXNfd2xvY2spOwo+ICsJc21wX21iX19hZnRlcl9hdG9taWMo KTsKPiArCXdha2VfdXBfYml0KHEtPnNlcV96b25lc193bG9jaywgem5vKTsKPiArCj4gKwliaW9f Y2xlYXJfZmxhZyhjbG9uZSwgQklPX1pPTkVfV1JJVEVfTE9DS0VEKTsKPiArfQo+ICsKPiArc3Rh dGljIGJvb2wgZG1fbmVlZF96b25lX3dwX3RyYWNraW5nKHN0cnVjdCBiaW8gKm9yaWdfYmlvKQo+ ICt7Cj4gKwkvKgo+ICsJICogU3BlY2lhbCBwcm9jZXNzaW5nIGlzIG5vdCBuZWVkZWQgZm9yIG9w ZXJhdGlvbnMgdGhhdCBkbyBub3QgbmVlZCB0aGUKPiArCSAqIHpvbmUgd3JpdGUgbG9jaywgdGhh dCBpcywgYWxsIG9wZXJhdGlvbnMgdGhhdCB0YXJnZXQgY29udmVudGlvbmFsCj4gKwkgKiB6b25l cyBhbmQgYWxsIG9wZXJhdGlvbnMgdGhhdCBkbyBub3QgbW9kaWZ5IGRpcmVjdGx5IGEgc2VxdWVu dGlhbAo+ICsJICogem9uZSB3cml0ZSBwb2ludGVyLgo+ICsJICovCj4gKwlpZiAob3BfaXNfZmx1 c2gob3JpZ19iaW8tPmJpX29wZikgJiYgIWJpb19zZWN0b3JzKG9yaWdfYmlvKSkKPiArCQlyZXR1 cm4gZmFsc2U7Cj4gKwlzd2l0Y2ggKGJpb19vcChvcmlnX2JpbykpIHsKPiArCWNhc2UgUkVRX09Q X1dSSVRFX1pFUk9FUzoKPiArCWNhc2UgUkVRX09QX1dSSVRFX1NBTUU6Cj4gKwljYXNlIFJFUV9P UF9XUklURToKPiArCWNhc2UgUkVRX09QX1pPTkVfUkVTRVQ6Cj4gKwljYXNlIFJFUV9PUF9aT05F X0ZJTklTSDoKPiArCWNhc2UgUkVRX09QX1pPTkVfQVBQRU5EOgo+ICsJCXJldHVybiBiaW9fem9u ZV9pc19zZXEob3JpZ19iaW8pOwo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gZmFsc2U7Cj4gKwl9 Cj4gK30KPiArCj4gKy8qCj4gKyAqIFNwZWNpYWwgSU8gbWFwcGluZyBmb3IgdGFyZ2V0cyBuZWVk aW5nIHpvbmUgYXBwZW5kIGVtdWxhdGlvbi4KPiArICovCj4gK2ludCBkbV96b25lX21hcF9iaW8o c3RydWN0IGRtX3RhcmdldF9pbyAqdGlvKQo+ICt7Cj4gKwlzdHJ1Y3QgZG1faW8gKmlvID0gdGlv LT5pbzsKPiArCXN0cnVjdCBkbV90YXJnZXQgKnRpID0gdGlvLT50aTsKPiArCXN0cnVjdCBtYXBw ZWRfZGV2aWNlICptZCA9IGlvLT5tZDsKPiArCXN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxID0gbWQt PnF1ZXVlOwo+ICsJc3RydWN0IGJpbyAqb3JpZ19iaW8gPSBpby0+b3JpZ19iaW87Cj4gKwlzdHJ1 Y3QgYmlvICpjbG9uZSA9ICZ0aW8tPmNsb25lOwo+ICsJdW5zaWduZWQgaW50IHpubzsKPiArCWJs a19zdGF0dXNfdCBzdHM7Cj4gKwlpbnQgcjsKPiArCj4gKwkvKgo+ICsJICogSU9zIHRoYXQgZG8g bm90IGNoYW5nZSBhIHpvbmUgd3JpdGUgcG9pbnRlciBkbyBub3QgbmVlZAo+ICsJICogYW55IGFk ZGl0aW9uYWwgc3BlY2lhbCBwcm9jZXNzaW5nLgo+ICsJICovCj4gKwlpZiAoIWRtX25lZWRfem9u ZV93cF90cmFja2luZyhvcmlnX2JpbykpCj4gKwkJcmV0dXJuIHRpLT50eXBlLT5tYXAodGksIGNs b25lKTsKPiArCj4gKwkvKiBMb2NrIHRoZSB0YXJnZXQgem9uZSAqLwo+ICsJem5vID0gYmlvX3pv bmVfbm8ob3JpZ19iaW8pOwo+ICsJZG1fem9uZV9sb2NrKHEsIHpubywgY2xvbmUpOwo+ICsKPiAr CS8qCj4gKwkgKiBDaGVjayB0aGF0IHRoZSBiaW8gYW5kIHRoZSB0YXJnZXQgem9uZSB3cml0ZSBw b2ludGVyIG9mZnNldCBhcmUKPiArCSAqIGJvdGggdmFsaWQsIGFuZCBpZiB0aGUgYmlvIGlzIGEg em9uZSBhcHBlbmQsIHJlbWFwIGl0IHRvIGEgd3JpdGUuCj4gKwkgKi8KPiArCWlmICghZG1fem9u ZV9tYXBfYmlvX2JlZ2luKG1kLCBvcmlnX2JpbywgY2xvbmUpKSB7Cj4gKwkJZG1fem9uZV91bmxv Y2socSwgem5vLCBjbG9uZSk7Cj4gKwkJcmV0dXJuIERNX01BUElPX0tJTEw7Cj4gKwl9Cj4gKwo+ ICsJLyoKPiArCSAqIFRoZSB0YXJnZXQgbWFwIGZ1bmN0aW9uIG1heSBpc3N1ZSBhbmQgY29tcGxl dGUgdGhlIElPIHF1aWNrbHkuCj4gKwkgKiBUYWtlIGFuIGV4dHJhIHJlZmVyZW5jZSBvbiB0aGUg SU8gdG8gbWFrZSBzdXJlIGl0IGRvZXMgZGlzYXBwZWFyCj4gKwkgKiB1bnRpbCB3ZSBydW4gZG1f em9uZV9tYXBfYmlvX2VuZCgpLgo+ICsJICovCj4gKwlkbV9pb19pbmNfcGVuZGluZyhpbyk7Cj4g Kwo+ICsJLyogTGV0IHRoZSB0YXJnZXQgZG8gaXRzIHdvcmsgKi8KPiArCXIgPSB0aS0+dHlwZS0+ bWFwKHRpLCBjbG9uZSk7Cj4gKwlzd2l0Y2ggKHIpIHsKPiArCWNhc2UgRE1fTUFQSU9fU1VCTUlU VEVEOgo+ICsJCS8qCj4gKwkJICogVGhlIHRhcmdldCBzdWJtaXR0ZWQgdGhlIGNsb25lIEJJTy4g VGhlIHRhcmdldCB6b25lIHdpbGwKPiArCQkgKiBiZSB1bmxvY2tlZCBvbiBjb21wbGV0aW9uIG9m IHRoZSBjbG9uZS4KPiArCQkgKi8KPiArCQlzdHMgPSBkbV96b25lX21hcF9iaW9fZW5kKG1kLCBv cmlnX2JpbywgKnRpby0+bGVuX3B0cik7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIERNX01BUElPX1JF TUFQUEVEOgo+ICsJCS8qCj4gKwkJICogVGhlIHRhcmdldCBvbmx5IHJlbWFwcGVkIHRoZSBjbG9u ZSBCSU8uIEluIGNhc2Ugb2YgZXJyb3IsCj4gKwkJICogdW5sb2NrIHRoZSB0YXJnZXQgem9uZSBo ZXJlIGFzIHRoZSBjbG9uZSB3aWxsIG5vdCBiZQo+ICsJCSAqIHN1Ym1pdHRlZC4KPiArCQkgKi8K PiArCQlzdHMgPSBkbV96b25lX21hcF9iaW9fZW5kKG1kLCBvcmlnX2JpbywgKnRpby0+bGVuX3B0 cik7Cj4gKwkJaWYgKHN0cyAhPSBCTEtfU1RTX09LKQo+ICsJCQlkbV96b25lX3VubG9jayhxLCB6 bm8sIGNsb25lKTsKPiArCQlicmVhazsKPiArCWNhc2UgRE1fTUFQSU9fUkVRVUVVRToKPiArCWNh c2UgRE1fTUFQSU9fS0lMTDoKPiArCWRlZmF1bHQ6Cj4gKwkJZG1fem9uZV91bmxvY2socSwgem5v LCBjbG9uZSk7Cj4gKwkJc3RzID0gQkxLX1NUU19JT0VSUjsKPiArCQlicmVhazsKPiArCX0KPiAr Cj4gKwkvKiBEcm9wIHRoZSBleHRyYSByZWZlcmVuY2Ugb24gdGhlIElPICovCj4gKwlkbV9pb19k ZWNfcGVuZGluZyhpbywgc3RzKTsKPiArCj4gKwlpZiAoc3RzICE9IEJMS19TVFNfT0spCj4gKwkJ cmV0dXJuIERNX01BUElPX0tJTEw7Cj4gKwo+ICsJcmV0dXJuIHI7Cj4gK30KPiArCj4gKy8qCj4g KyAqIElPIGNvbXBsZXRpb24gY2FsbGJhY2sgY2FsbGVkIGZyb20gY2xvbmVfZW5kaW8oKS4KPiAr ICovCj4gK3ZvaWQgZG1fem9uZV9lbmRpbyhzdHJ1Y3QgZG1faW8gKmlvLCBzdHJ1Y3QgYmlvICpj bG9uZSkKPiArewo+ICsJc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kID0gaW8tPm1kOwo+ICsJc3Ry dWN0IHJlcXVlc3RfcXVldWUgKnEgPSBtZC0+cXVldWU7Cj4gKwlzdHJ1Y3QgYmlvICpvcmlnX2Jp byA9IGlvLT5vcmlnX2JpbzsKPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gKwl1bnNpZ25lZCBp bnQgem5vOwo+ICsKPiArCS8qCj4gKwkgKiBGb3IgdGFyZ2V0cyB0aGF0IGRvIG5vdCBlbXVsYXRl IHpvbmUgYXBwZW5kLCB3ZSBvbmx5IG5lZWQgdG8KPiArCSAqIGhhbmRsZSBuYXRpdmUgem9uZS1h cHBlbmQgYmlvcy4KPiArCSAqLwo+ICsJaWYgKCFkbV9lbXVsYXRlX3pvbmVfYXBwZW5kKG1kKSkg ewo+ICsJCS8qCj4gKwkJICogR2V0IHRoZSBvZmZzZXQgd2l0aGluIHRoZSB6b25lIG9mIHRoZSB3 cml0dGVuIHNlY3Rvcgo+ICsJCSAqIGFuZCBhZGQgdGhhdCB0byB0aGUgb3JpZ2luYWwgYmlvIHNl Y3RvciBwb3NpdGlvbi4KPiArCQkgKi8KPiArCQlpZiAoY2xvbmUtPmJpX3N0YXR1cyA9PSBCTEtf U1RTX09LICYmCj4gKwkJICAgIGJpb19vcChjbG9uZSkgPT0gUkVRX09QX1pPTkVfQVBQRU5EKSB7 Cj4gKwkJCXNlY3Rvcl90IG1hc2sgPSAoc2VjdG9yX3QpYmxrX3F1ZXVlX3pvbmVfc2VjdG9ycyhx KSAtIDE7Cj4gKwo+ICsJCQlvcmlnX2Jpby0+YmlfaXRlci5iaV9zZWN0b3IgKz0KPiArCQkJCWNs b25lLT5iaV9pdGVyLmJpX3NlY3RvciAmIG1hc2s7Cj4gKwkJfQo+ICsKPiArCQlyZXR1cm47Cj4g Kwl9Cj4gKwo+ICsJLyoKPiArCSAqIEZvciB0YXJnZXRzIHRoYXQgZG8gZW11bGF0ZSB6b25lIGFw cGVuZCwgaWYgdGhlIGNsb25lIEJJTyBkb2VzIG5vdAo+ICsJICogb3duIHRoZSB0YXJnZXQgem9u ZSB3cml0ZSBsb2NrLCB3ZSBoYXZlIG5vdGhpbmcgdG8gZG8uCj4gKwkgKi8KPiArCWlmICghYmlv X2ZsYWdnZWQoY2xvbmUsIEJJT19aT05FX1dSSVRFX0xPQ0tFRCkpCj4gKwkJcmV0dXJuOwo+ICsK PiArCXpubyA9IGJpb196b25lX25vKG9yaWdfYmlvKTsKPiArCj4gKwlzcGluX2xvY2tfaXJxc2F2 ZSgmbWQtPnp3cF9vZmZzZXRfbG9jaywgZmxhZ3MpOwo+ICsJaWYgKGNsb25lLT5iaV9zdGF0dXMg IT0gQkxLX1NUU19PSykgewo+ICsJCS8qCj4gKwkJICogQklPcyB0aGF0IG1vZGlmeSBhIHpvbmUg d3JpdGUgcG9pbnRlciBtYXkgbGVhdmUgdGhlIHpvbmUKPiArCQkgKiBpbiBhbiB1bmtub3duIHN0 YXRlIGluIGNhc2Ugb2YgZmFpbHVyZSAoZS5nLiB0aGUgd3JpdGUKPiArCQkgKiBwb2ludGVyIHdh cyBvbmx5IHBhcnRpYWxseSBhZHZhbmNlZCkuIEluIHRoaXMgY2FzZSwgc2V0Cj4gKwkJICogdGhl IHRhcmdldCB6b25lIHdyaXRlIHBvaW50ZXIgYXMgaW52YWxpZCB1bmxlc3MgaXQgaXMKPiArCQkg KiBhbHJlYWR5IGJlaW5nIHVwZGF0ZWQuCj4gKwkJICovCj4gKwkJaWYgKG1kLT56d3Bfb2Zmc2V0 W3pub10gIT0gRE1fWk9ORV9VUERBVElOR19XUF9PRlNUKQo+ICsJCQltZC0+endwX29mZnNldFt6 bm9dID0gRE1fWk9ORV9JTlZBTElEX1dQX09GU1Q7Cj4gKwl9IGVsc2UgaWYgKGJpb19vcChvcmln X2JpbykgPT0gUkVRX09QX1pPTkVfQVBQRU5EKSB7Cj4gKwkJLyoKPiArCQkgKiBHZXQgdGhlIHdy aXR0ZW4gc2VjdG9yIGZvciB6b25lIGFwcGVuZCBvcGVyYXRpb24gdGhhdCB3ZXJlCj4gKwkJICog ZW11bGF0ZWQgdXNpbmcgcmVndWxhciB3cml0ZSBvcGVyYXRpb25zLgo+ICsJCSAqLwo+ICsJCWlm IChXQVJOX09OX09OQ0UobWQtPnp3cF9vZmZzZXRbem5vXSA8IGJpb19zZWN0b3JzKG9yaWdfYmlv KSkpCj4gKwkJCW1kLT56d3Bfb2Zmc2V0W3pub10gPSBETV9aT05FX0lOVkFMSURfV1BfT0ZTVDsK PiArCQllbHNlCj4gKwkJCW9yaWdfYmlvLT5iaV9pdGVyLmJpX3NlY3RvciArPQo+ICsJCQkJbWQt Pnp3cF9vZmZzZXRbem5vXSAtIGJpb19zZWN0b3JzKG9yaWdfYmlvKTsKPiArCX0KPiArCXNwaW5f dW5sb2NrX2lycXJlc3RvcmUoJm1kLT56d3Bfb2Zmc2V0X2xvY2ssIGZsYWdzKTsKPiArCgpTaW1p bGFyIGNvbW1lbnRzIHRvIHRoZSBzcGlubG9jayBoZXJlLgoKPiArCWRtX3pvbmVfdW5sb2NrKHEs IHpubywgY2xvbmUpOwo+ICAgfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21kL2RtLmMgYi9kcml2 ZXJzL21kL2RtLmMKPiBpbmRleCA1NjM1MDQxNjNiNzQuLjUwMzhiZjUyMmIwZCAxMDA2NDQKPiAt LS0gYS9kcml2ZXJzL21kL2RtLmMKPiArKysgYi9kcml2ZXJzL21kL2RtLmMKPiBAQCAtODc1LDcg Kzg3NSw2IEBAIHN0YXRpYyB2b2lkIGNsb25lX2VuZGlvKHN0cnVjdCBiaW8gKmJpbykKPiAgIAlz dHJ1Y3QgZG1faW8gKmlvID0gdGlvLT5pbzsKPiAgIAlzdHJ1Y3QgbWFwcGVkX2RldmljZSAqbWQg PSB0aW8tPmlvLT5tZDsKPiAgIAlkbV9lbmRpb19mbiBlbmRpbyA9IHRpby0+dGktPnR5cGUtPmVu ZF9pbzsKPiAtCXN0cnVjdCBiaW8gKm9yaWdfYmlvID0gaW8tPm9yaWdfYmlvOwo+ICAgCXN0cnVj dCByZXF1ZXN0X3F1ZXVlICpxID0gYmlvLT5iaV9iZGV2LT5iZF9kaXNrLT5xdWV1ZTsKPiAgIAo+ ICAgCWlmICh1bmxpa2VseShlcnJvciA9PSBCTEtfU1RTX1RBUkdFVCkpIHsKPiBAQCAtODkwLDE3 ICs4ODksOCBAQCBzdGF0aWMgdm9pZCBjbG9uZV9lbmRpbyhzdHJ1Y3QgYmlvICpiaW8pCj4gICAJ CQlkaXNhYmxlX3dyaXRlX3plcm9lcyhtZCk7Cj4gICAJfQo+ICAgCj4gLQkvKgo+IC0JICogRm9y IHpvbmUtYXBwZW5kIGJpb3MgZ2V0IG9mZnNldCBpbiB6b25lIG9mIHRoZSB3cml0dGVuCj4gLQkg KiBzZWN0b3IgYW5kIGFkZCB0aGF0IHRvIHRoZSBvcmlnaW5hbCBiaW8gc2VjdG9yIHBvcy4KPiAt CSAqLwo+IC0JaWYgKGJpb19vcChvcmlnX2JpbykgPT0gUkVRX09QX1pPTkVfQVBQRU5EKSB7Cj4g LQkJc2VjdG9yX3Qgd3JpdHRlbl9zZWN0b3IgPSBiaW8tPmJpX2l0ZXIuYmlfc2VjdG9yOwo+IC0J CXN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxID0gb3JpZ19iaW8tPmJpX2JkZXYtPmJkX2Rpc2stPnF1 ZXVlOwo+IC0JCXU2NCBtYXNrID0gKHU2NClibGtfcXVldWVfem9uZV9zZWN0b3JzKHEpIC0gMTsK PiAtCj4gLQkJb3JpZ19iaW8tPmJpX2l0ZXIuYmlfc2VjdG9yICs9IHdyaXR0ZW5fc2VjdG9yICYg bWFzazsKPiAtCX0KPiArCWlmIChibGtfcXVldWVfaXNfem9uZWQocSkpCj4gKwkJZG1fem9uZV9l bmRpbyhpbywgYmlvKTsKPiAgIAo+ICAgCWlmIChlbmRpbykgewo+ICAgCQlpbnQgciA9IGVuZGlv KHRpby0+dGksIGJpbywgJmVycm9yKTsKPiBAQCAtMTIxMyw3ICsxMjAzLDE2IEBAIHN0YXRpYyBi bGtfcWNfdCBfX21hcF9iaW8oc3RydWN0IGRtX3RhcmdldF9pbyAqdGlvKQo+ICAgCQlkb3duKCZt ZC0+c3dhcF9iaW9zX3NlbWFwaG9yZSk7Cj4gICAJfQo+ICAgCj4gLQlyID0gdGktPnR5cGUtPm1h cCh0aSwgY2xvbmUpOwo+ICsJLyoKPiArCSAqIENoZWNrIGlmIHRoZSBJTyBuZWVkcyBhIHNwZWNp YWwgbWFwcGluZyBkdWUgdG8gem9uZSBhcHBlbmQgZW11bGF0aW9uCj4gKwkgKiBvbiB6b25lZCB0 YXJnZXQuIEluIHRoaXMgY2FzZSwgZG1fem9uZV9tYXBfYmVnaW4oKSBjYWxscyB0aGUgdGFyZ2V0 Cj4gKwkgKiBtYXAgb3BlcmF0aW9uLgo+ICsJICovCj4gKwlpZiAoZG1fZW11bGF0ZV96b25lX2Fw cGVuZChpby0+bWQpKQo+ICsJCXIgPSBkbV96b25lX21hcF9iaW8odGlvKTsKPiArCWVsc2UKPiAr CQlyID0gdGktPnR5cGUtPm1hcCh0aSwgY2xvbmUpOwo+ICsKPiAgIAlzd2l0Y2ggKHIpIHsKPiAg IAljYXNlIERNX01BUElPX1NVQk1JVFRFRDoKPiAgIAkJYnJlYWs7Cj4gQEAgLTE3NTcsNiArMTc1 Niw3IEBAIHN0YXRpYyBzdHJ1Y3QgbWFwcGVkX2RldmljZSAqYWxsb2NfZGV2KGludCBtaW5vcikK PiAgIAlJTklUX0xJU1RfSEVBRCgmbWQtPnVldmVudF9saXN0KTsKPiAgIAlJTklUX0xJU1RfSEVB RCgmbWQtPnRhYmxlX2RldmljZXMpOwo+ICAgCXNwaW5fbG9ja19pbml0KCZtZC0+dWV2ZW50X2xv Y2spOwo+ICsJZG1faW5pdF96b25lZF9kZXYobWQpOwo+ICAgCj4gICAJLyoKPiAgIAkgKiBkZWZh dWx0IHRvIGJpby1iYXNlZCB1bnRpbCBETSB0YWJsZSBpcyBsb2FkZWQgYW5kIG1kLT50eXBlCj4g QEAgLTE5NTYsMTEgKzE5NTYsMTYgQEAgc3RhdGljIHN0cnVjdCBkbV90YWJsZSAqX19iaW5kKHN0 cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgc3RydWN0IGRtX3RhYmxlICp0LAo+ICAgCQlnb3RvIG91 dDsKPiAgIAl9Cj4gICAKPiArCXJldCA9IGRtX3RhYmxlX3NldF9yZXN0cmljdGlvbnModCwgcSwg bGltaXRzKTsKPiArCWlmIChyZXQpIHsKPiArCQlvbGRfbWFwID0gRVJSX1BUUihyZXQpOwo+ICsJ CWdvdG8gb3V0Owo+ICsJfQo+ICsKPiAgIAlvbGRfbWFwID0gcmN1X2RlcmVmZXJlbmNlX3Byb3Rl Y3RlZChtZC0+bWFwLCBsb2NrZGVwX2lzX2hlbGQoJm1kLT5zdXNwZW5kX2xvY2spKTsKPiAgIAly Y3VfYXNzaWduX3BvaW50ZXIobWQtPm1hcCwgKHZvaWQgKil0KTsKPiAgIAltZC0+aW1tdXRhYmxl X3RhcmdldF90eXBlID0gZG1fdGFibGVfZ2V0X2ltbXV0YWJsZV90YXJnZXRfdHlwZSh0KTsKPiAg IAo+IC0JZG1fdGFibGVfc2V0X3Jlc3RyaWN0aW9ucyh0LCBxLCBsaW1pdHMpOwo+ICAgCWlmIChv bGRfbWFwKQo+ICAgCQlkbV9zeW5jX3RhYmxlKG1kKTsKPiAgIAo+IEBAIC0yMDc5LDcgKzIwODQs MTAgQEAgaW50IGRtX3NldHVwX21kX3F1ZXVlKHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgc3Ry dWN0IGRtX3RhYmxlICp0KQo+ICAgCQlETUVSUigiQ2Fubm90IGNhbGN1bGF0ZSBpbml0aWFsIHF1 ZXVlIGxpbWl0cyIpOwo+ICAgCQlyZXR1cm4gcjsKPiAgIAl9Cj4gLQlkbV90YWJsZV9zZXRfcmVz dHJpY3Rpb25zKHQsIG1kLT5xdWV1ZSwgJmxpbWl0cyk7Cj4gKwlyID0gZG1fdGFibGVfc2V0X3Jl c3RyaWN0aW9ucyh0LCBtZC0+cXVldWUsICZsaW1pdHMpOwo+ICsJaWYgKHIpCj4gKwkJcmV0dXJu IHI7Cj4gKwo+ICAgCWJsa19yZWdpc3Rlcl9xdWV1ZShtZC0+ZGlzayk7Cj4gICAKPiAgIAlyZXR1 cm4gMDsKPiBAQCAtMjE4OCw2ICsyMTk2LDcgQEAgc3RhdGljIHZvaWQgX19kbV9kZXN0cm95KHN0 cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgYm9vbCB3YWl0KQo+ICAgCQkgICAgICAgZG1fZGV2aWNl X25hbWUobWQpLCBhdG9taWNfcmVhZCgmbWQtPmhvbGRlcnMpKTsKPiAgIAo+ICAgCWRtX3N5c2Zz X2V4aXQobWQpOwo+ICsJZG1fY2xlYW51cF96b25lZF9kZXYobWQpOwo+ICAgCWRtX3RhYmxlX2Rl c3Ryb3koX191bmJpbmQobWQpKTsKPiAgIAlmcmVlX2RldihtZCk7Cj4gICB9Cj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvbWQvZG0uaCBiL2RyaXZlcnMvbWQvZG0uaAo+IGluZGV4IDM5YzI0MzI1OGUy NC4uNjVmMjBkOGNjNDE1IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbWQvZG0uaAo+ICsrKyBiL2Ry aXZlcnMvbWQvZG0uaAo+IEBAIC00NSw2ICs0NSw4IEBAIHN0cnVjdCBkbV9kZXZfaW50ZXJuYWwg ewo+ICAgCj4gICBzdHJ1Y3QgZG1fdGFibGU7Cj4gICBzdHJ1Y3QgZG1fbWRfbWVtcG9vbHM7Cj4g K3N0cnVjdCBkbV90YXJnZXRfaW87Cj4gK3N0cnVjdCBkbV9pbzsKPiAgIAo+ICAgLyotLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LQo+ICAgICogSW50ZXJuYWwgdGFibGUgZnVuY3Rpb25zLgo+IEBAIC01Niw4ICs1OCw4IEBAIHN0 cnVjdCBkbV90YXJnZXQgKmRtX3RhYmxlX2ZpbmRfdGFyZ2V0KHN0cnVjdCBkbV90YWJsZSAqdCwg c2VjdG9yX3Qgc2VjdG9yKTsKPiAgIGJvb2wgZG1fdGFibGVfaGFzX25vX2RhdGFfZGV2aWNlcyhz dHJ1Y3QgZG1fdGFibGUgKnRhYmxlKTsKPiAgIGludCBkbV9jYWxjdWxhdGVfcXVldWVfbGltaXRz KHN0cnVjdCBkbV90YWJsZSAqdGFibGUsCj4gICAJCQkgICAgICBzdHJ1Y3QgcXVldWVfbGltaXRz ICpsaW1pdHMpOwo+IC12b2lkIGRtX3RhYmxlX3NldF9yZXN0cmljdGlvbnMoc3RydWN0IGRtX3Rh YmxlICp0LCBzdHJ1Y3QgcmVxdWVzdF9xdWV1ZSAqcSwKPiAtCQkJICAgICAgIHN0cnVjdCBxdWV1 ZV9saW1pdHMgKmxpbWl0cyk7Cj4gK2ludCBkbV90YWJsZV9zZXRfcmVzdHJpY3Rpb25zKHN0cnVj dCBkbV90YWJsZSAqdCwgc3RydWN0IHJlcXVlc3RfcXVldWUgKnEsCj4gKwkJCSAgICAgIHN0cnVj dCBxdWV1ZV9saW1pdHMgKmxpbWl0cyk7Cj4gICBzdHJ1Y3QgbGlzdF9oZWFkICpkbV90YWJsZV9n ZXRfZGV2aWNlcyhzdHJ1Y3QgZG1fdGFibGUgKnQpOwo+ICAgdm9pZCBkbV90YWJsZV9wcmVzdXNw ZW5kX3RhcmdldHMoc3RydWN0IGRtX3RhYmxlICp0KTsKPiAgIHZvaWQgZG1fdGFibGVfcHJlc3Vz cGVuZF91bmRvX3RhcmdldHMoc3RydWN0IGRtX3RhYmxlICp0KTsKPiBAQCAtMTAzLDE3ICsxMDUs MjcgQEAgaW50IGRtX3NldHVwX21kX3F1ZXVlKHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgc3Ry dWN0IGRtX3RhYmxlICp0KTsKPiAgIC8qCj4gICAgKiBab25lZCB0YXJnZXRzIHJlbGF0ZWQgZnVu Y3Rpb25zLgo+ICAgICovCj4gLXZvaWQgZG1fc2V0X3pvbmVzX3Jlc3RyaWN0aW9ucyhzdHJ1Y3Qg ZG1fdGFibGUgKnQsIHN0cnVjdCByZXF1ZXN0X3F1ZXVlICpxKTsKPiAraW50IGRtX3NldF96b25l c19yZXN0cmljdGlvbnMoc3RydWN0IGRtX3RhYmxlICp0LCBzdHJ1Y3QgcmVxdWVzdF9xdWV1ZSAq cSk7Cj4gK3ZvaWQgZG1fem9uZV9lbmRpbyhzdHJ1Y3QgZG1faW8gKmlvLCBzdHJ1Y3QgYmlvICpj bG9uZSk7Cj4gICAjaWZkZWYgQ09ORklHX0JMS19ERVZfWk9ORUQKPiArdm9pZCBkbV9pbml0X3pv bmVkX2RldihzdHJ1Y3QgbWFwcGVkX2RldmljZSAqbWQpOwo+ICt2b2lkIGRtX2NsZWFudXBfem9u ZWRfZGV2KHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCk7Cj4gICBpbnQgZG1fYmxrX3JlcG9ydF96 b25lcyhzdHJ1Y3QgZ2VuZGlzayAqZGlzaywgc2VjdG9yX3Qgc2VjdG9yLAo+ICAgCQkJdW5zaWdu ZWQgaW50IG5yX3pvbmVzLCByZXBvcnRfem9uZXNfY2IgY2IsIHZvaWQgKmRhdGEpOwo+ICAgYm9v bCBkbV9pc196b25lX3dyaXRlKHN0cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgc3RydWN0IGJpbyAq YmlvKTsKPiAraW50IGRtX3pvbmVfbWFwX2JpbyhzdHJ1Y3QgZG1fdGFyZ2V0X2lvICppbyk7Cj4g ICAjZWxzZQo+ICtzdGF0aWMgaW5saW5lIHZvaWQgZG1faW5pdF96b25lZF9kZXYoc3RydWN0IG1h cHBlZF9kZXZpY2UgKm1kKSB7fQo+ICtzdGF0aWMgaW5saW5lIHZvaWQgZG1fY2xlYW51cF96b25l ZF9kZXYoc3RydWN0IG1hcHBlZF9kZXZpY2UgKm1kKSB7fQo+ICAgI2RlZmluZSBkbV9ibGtfcmVw b3J0X3pvbmVzCU5VTEwKPiAgIHN0YXRpYyBpbmxpbmUgYm9vbCBkbV9pc196b25lX3dyaXRlKHN0 cnVjdCBtYXBwZWRfZGV2aWNlICptZCwgc3RydWN0IGJpbyAqYmlvKQo+ICAgewo+ICAgCXJldHVy biBmYWxzZTsKPiAgIH0KPiArc3RhdGljIGlubGluZSBpbnQgZG1fem9uZV9tYXBfYmlvKHN0cnVj dCBkbV90YXJnZXRfaW8gKnRpbykKPiArewo+ICsJcmV0dXJuIERNX01BUElPX0tJTEw7Cj4gK30K PiAgICNlbmRpZgo+ICAgCj4gICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGlu dXgvZGV2aWNlLW1hcHBlci5oIGIvaW5jbHVkZS9saW51eC9kZXZpY2UtbWFwcGVyLmgKPiBpbmRl eCBjYWVhMGEwNzlkMmQuLjc0NTdkNDlhY2Y5YSAxMDA2NDQKPiAtLS0gYS9pbmNsdWRlL2xpbnV4 L2RldmljZS1tYXBwZXIuaAo+ICsrKyBiL2luY2x1ZGUvbGludXgvZGV2aWNlLW1hcHBlci5oCj4g QEAgLTM2MSw2ICszNjEsMTIgQEAgc3RydWN0IGRtX3RhcmdldCB7Cj4gICAJICogU2V0IGlmIHdl IG5lZWQgdG8gbGltaXQgdGhlIG51bWJlciBvZiBpbi1mbGlnaHQgYmlvcyB3aGVuIHN3YXBwaW5n Lgo+ICAgCSAqLwo+ICAgCWJvb2wgbGltaXRfc3dhcF9iaW9zOjE7Cj4gKwo+ICsJLyoKPiArCSAq IFNldCBpZiB0aGlzIHRhcmdldCBpbXBsZW1lbnRzIGEgYSB6b25lZCBkZXZpY2UgYW5kIG5lZWRz IGVtdWxhdGlvbiBvZgo+ICsJICogem9uZSBhcHBlbmQgb3BlcmF0aW9ucyB1c2luZyByZWd1bGFy IHdyaXRlcy4KPiArCSAqLwo+ICsJYm9vbCBlbXVsYXRlX3pvbmVfYXBwZW5kOjE7Cj4gICB9Owo+ ICAgCj4gICB2b2lkICpkbV9wZXJfYmlvX2RhdGEoc3RydWN0IGJpbyAqYmlvLCBzaXplX3QgZGF0 YV9zaXplKTsKPiAKQ2hlZXJzLAoKSGFubmVzCi0tIApEci4gSGFubmVzIFJlaW5lY2tlICAgICAg ICAgICAgICAgIEtlcm5lbCBTdG9yYWdlIEFyY2hpdGVjdApoYXJlQHN1c2UuZGUgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICArNDkgOTExIDc0MDUzIDY4OApTVVNFIFNvZnR3YXJlIFNvbHV0 aW9ucyBHbWJILCBNYXhmZWxkc3RyLiA1LCA5MDQwOSBOw7xybmJlcmcKSFJCIDM2ODA5IChBRyBO w7xybmJlcmcpLCBHZXNjaMOkZnRzZsO8aHJlcjogRmVsaXggSW1lbmTDtnJmZmVyCgoKLS0KZG0t ZGV2ZWwgbWFpbGluZyBsaXN0CmRtLWRldmVsQHJlZGhhdC5jb20KaHR0cHM6Ly9saXN0bWFuLnJl ZGhhdC5jb20vbWFpbG1hbi9saXN0aW5mby9kbS1kZXZlbA==