All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 7/7] sunxi: Add support for the CHIP Pro
From: Hans de Goede @ 2016-11-14 11:20 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <be13289f14a55434600bfb4a859d9a28b3c49b5b.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> The CHIP Pro is a SoM that features the GR8 SIP, an AXP209, a BT/WiFi chip
> and a 512MiB SLC NAND.
>
> This it's an SLC NAND, it doesn't suffer the same drawbacks than found on
> the MLC NANDs, and we can enable it right away.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Patch 3/3 needs a v3 before this can be merged, otherwise this
looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans

> ---
>  configs/CHIP_pro_defconfig | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+), 0 deletions(-)
>  create mode 100644 configs/CHIP_pro_defconfig
>
> diff --git a/configs/CHIP_pro_defconfig b/configs/CHIP_pro_defconfig
> new file mode 100644
> index 000000000000..6008f44f485c
> --- /dev/null
> +++ b/configs/CHIP_pro_defconfig
> @@ -0,0 +1,27 @@
> +CONFIG_ARM=y
> +CONFIG_ARCH_SUNXI=y
> +CONFIG_SPL_I2C_SUPPORT=y
> +# CONFIG_SPL_MMC_SUPPORT is not set
> +CONFIG_MACH_SUN5I=y
> +CONFIG_DRAM_TIMINGS_DDR3_800E_1066G_1333J=y
> +# CONFIG_MMC is not set
> +CONFIG_USB0_VBUS_PIN="PB10"
> +CONFIG_DEFAULT_DEVICE_TREE="ntc-gr8-chip-pro"
> +CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,SYS_NAND_BLOCK_SIZE=0x40000,SYS_NAND_PAGE_SIZE=4096,SYS_NAND_OOBSIZE=256,ENV_IS_IN_NAND"
> +CONFIG_SPL=y
> +# CONFIG_CMD_IMLS is not set
> +CONFIG_CMD_DFU=y
> +CONFIG_CMD_USB_MASS_STORAGE=y
> +CONFIG_DFU_RAM=y
> +CONFIG_AXP_ALDO3_VOLT=3300
> +CONFIG_AXP_ALDO4_VOLT=3300
> +CONFIG_USB_EHCI_HCD=y
> +CONFIG_USB_MUSB_GADGET=y
> +CONFIG_USB_GADGET=y
> +CONFIG_USB_GADGET_DOWNLOAD=y
> +CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
> +CONFIG_G_DNL_VENDOR_NUM=0x1f3a
> +CONFIG_G_DNL_PRODUCT_NUM=0x1010
> +CONFIG_NAND_SUNXI=y
> +CONFIG_SPL_NAND_SUPPORT=y
> +CONFIG_MTD_UBI=y
>

^ permalink raw reply

* RE: Kernel crashes in __migration_entry_wait
From: Odzioba, Lukasz @ 2016-11-14 11:19 UTC (permalink / raw)
  To: Dashi DS1 Cao
  Cc: 'linux-x86_64@vger.kernel.org',
	'linux-numa@vger.kernel.org'
In-Reply-To: <23B7B563BA4E9446B962B142C86EF24A3DCF87@CNMAILEX03.lenovo.com>

On Sunday, November 13, 2016 1:40 PM Dashi Cao wrote:
> A X86_64 server repeatedly dumps once a while with the following signature:
> (snip)
>
>      KERNEL: vmlinux
>    DUMPFILE: 127.0.0.1-2016-10-03-09:59:36/vmcore  [PARTIAL DUMP]
>        CPUS: 32
>        DATE: Mon Oct  3 10:13:22 2016
>     UPTIME: 4 days, 17:04:52
> LOAD AVERAGE: 0.49, 0.26, 0.24
>       TASKS: 657
>    NODENAME: node04-priv
>     RELEASE: 3.10.0-327.el7.x86_64
> (snip)
>
> It seems that this is a bug. I'm not sure if it has been identified and removed, but it cannot be found on the web. The customer was adviced to disable numa balancing to work around and I'm waiting for the latest results from them.

Hi Dashi,
Thank you for your report ,but this seems to be kernel from RedHat 7.2 not our latest one nor stable, so I am not sure how many people here may be interested in your issue. If you don't get answer you can talk to RH support. Also this kernel is not the latest  available for 7.2 so you may just try to update it.

Thanks,
Lukas

^ permalink raw reply

* [U-Boot] [PATCH 6/7] scripts: sunxi: Build an raw SPL image
From: Hans de Goede @ 2016-11-14 11:19 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <e16ddb81605d02ea3c385c1a637543e273f2d018.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> Introduce a new sunxi-spl-with-ecc.bin image with already the right header,
> ECC, randomizer and padding for the BROM to be able to read it.
>
> It needs to be flashed using a raw access to the NAND so that the
> controller doesn't change a thing to it, since we already have all the
> right parameters.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



> ---
>  Makefile             |  3 +++
>  scripts/Makefile.spl | 12 ++++++++++++
>  2 files changed, 15 insertions(+), 0 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 37cbcb28f75e..12a248e297b5 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1345,6 +1345,9 @@ spl/u-boot-spl: tools prepare \
>  spl/sunxi-spl.bin: spl/u-boot-spl
>  	@:
>
> +spl/sunxi-spl-with-ecc.bin: spl/sunxi-spl.bin
> +	@:
> +
>  spl/u-boot-spl.sfp: spl/u-boot-spl
>  	@:
>
> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> index e0b0117dc9b6..b41b4e427cc5 100644
> --- a/scripts/Makefile.spl
> +++ b/scripts/Makefile.spl
> @@ -168,6 +168,7 @@ endif
>
>  ifdef CONFIG_ARCH_SUNXI
>  ALL-y	+= $(obj)/sunxi-spl.bin
> +ALL-y	+= $(obj)/sunxi-spl-with-ecc.bin
>  endif
>
>  ifeq ($(CONFIG_SYS_SOC),"at91")
> @@ -276,6 +277,17 @@ cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
>  $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
>  	$(call if_changed,mksunxiboot)
>
> +quiet_cmd_sunxi_spl_image_builder = SUNXI_SPL_IMAGE_BUILDER $@
> +cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
> +				-c $(CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH)/$(CONFIG_NAND_SUNXI_SPL_ECC_SIZE) \
> +				-p $(CONFIG_SYS_NAND_PAGE_SIZE) \
> +				-o $(CONFIG_SYS_NAND_OOBSIZE) \
> +				-u $(CONFIG_NAND_SUNXI_SPL_USABLE_PAGE_SIZE) \
> +				-e $(CONFIG_SYS_NAND_BLOCK_SIZE) \
> +				-s -b $< $@
> +$(obj)/sunxi-spl-with-ecc.bin: $(obj)/sunxi-spl.bin
> +	$(call if_changed,sunxi_spl_image_builder)
> +
>  # Rule to link u-boot-spl
>  # May be overridden by arch/$(ARCH)/config.mk
>  quiet_cmd_u-boot-spl ?= LD      $@
>

^ permalink raw reply

* [U-Boot] [PATCH 5/7] nand: sunxi: Add options for the SPL NAND configuration
From: Hans de Goede @ 2016-11-14 11:19 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <352020a574eb12267bdaee0efa48e5b2075c9ae0.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> The SPL image needs to be built with a different ECC configuration than the
> U-Boot binary.
>
> Add Kconfig options with defaults to provide a value that should work for
> anyone, but is still configurable if needs be.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



> ---
>  drivers/mtd/nand/Kconfig | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index df154bfd32b9..a60abb625ee5 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -73,6 +73,22 @@ config NAND_SUNXI
>  	The SPL driver only supports reading from the NAND using DMA
>  	transfers.
>
> +if NAND_SUNXI
> +
> +config NAND_SUNXI_SPL_ECC_STRENGTH
> +	int "Allwinner NAND SPL ECC Strength"
> +	default 64
> +
> +config NAND_SUNXI_SPL_ECC_SIZE
> +	int "Allwinner NAND SPL ECC Step Size"
> +	default 1024
> +
> +config NAND_SUNXI_SPL_USABLE_PAGE_SIZE
> +	int "Allwinner NAND SPL Usable Page Size"
> +	default 1024
> +
> +endif
> +
>  config NAND_ARASAN
>  	bool "Configure Arasan Nand"
>  	help
>

^ permalink raw reply

* Re: [PATCH v4 1/8] media: adv7180: fix field type
From: Hans Verkuil @ 2016-11-14 11:19 UTC (permalink / raw)
  To: Steve Longerbeam, lars
  Cc: mchehab, linux-media, linux-kernel, Steve Longerbeam,
	Niklas Söderlund
In-Reply-To: <1470247430-11168-2-git-send-email-steve_longerbeam@mentor.com>

On 08/03/2016 08:03 PM, Steve Longerbeam wrote:
> From: Steve Longerbeam <slongerbeam@gmail.com>
> 
> The ADV7180 and ADV7182 transmit whole fields, bottom field followed
> by top (or vice-versa, depending on detected video standard). So
> for chips that do not have support for explicitly setting the field
> mode via I2P, set the field mode to V4L2_FIELD_ALTERNATE.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> 
> ---
> 
> v4:
> - switch V4L2_FIELD_SEQ_TB/V4L2_FIELD_SEQ_BT to V4L2_FIELD_ALTERNATE.
>   This is from Niklas Söderlund.
> - remove checks for ADV7180_FLAG_I2P when setting field mode, since I2P
>   support is planned to be removed.
> - move init of state->curr_norm back to its original location, since
>   state->field init is no longer dependent on state->curr_norm.
> 
> v3: no changes
> 
> v2:
> - the init of state->curr_norm in probe needs to be moved up, ahead
>   of the init of state->field.
> ---
>  drivers/media/i2c/adv7180.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index 95cbc85..192eeae 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -679,10 +679,10 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,
>  	switch (format->format.field) {
>  	case V4L2_FIELD_NONE:
>  		if (!(state->chip_info->flags & ADV7180_FLAG_I2P))
> -			format->format.field = V4L2_FIELD_INTERLACED;
> +			format->format.field = V4L2_FIELD_ALTERNATE;
>  		break;

I'd change this to:

  		if (state->chip_info->flags & ADV7180_FLAG_I2P)
			break;
		/* fall through */

>  	default:
> -		format->format.field = V4L2_FIELD_INTERLACED;
> +		format->format.field = V4L2_FIELD_ALTERNATE;
>  		break;
>  	}
>  
> @@ -1251,7 +1251,7 @@ static int adv7180_probe(struct i2c_client *client,
>  		return -ENOMEM;
>  
>  	state->client = client;
> -	state->field = V4L2_FIELD_INTERLACED;
> +	state->field = V4L2_FIELD_ALTERNATE;
>  	state->chip_info = (struct adv7180_chip_info *)id->driver_data;
>  
>  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
> 

Regards,

	Hans

^ permalink raw reply

* Re: [PATCH 0/2] Honey, I shrunk the EFI stub
From: Lukas Wunner @ 2016-11-14 11:19 UTC (permalink / raw)
  To: Matt Fleming; +Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Ard Biesheuvel
In-Reply-To: <20161112205514.GA2373-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>

On Sat, Nov 12, 2016 at 08:55:14PM +0000, Matt Fleming wrote:
> On Mon, 07 Nov, at 12:17:00PM, Lukas Wunner wrote:
> > Demonstrate the code reduction attainable by efi_call_proto()
> > which was proffered in a patch I've posted a few minutes ago.
> > 
> > For this to work, all three protocol variants (_32_t and _64_t for x86
> > and _t for ARM) need to be declared as typedefs.  The declaration and
> > naming of protocols in include/linux/efi.h currently isn't consistent,
> > some are declared as typedefs and some aren't, some use a "_t" suffix
> > and some don't.  These inconsistencies need to be straightened out
> > when converting to efi_call_proto().  It should be noted that checkpatch
> > complains about newly introduced typedefs.  It would be possible to
> > retool efi_call_proto() to work without typedef declarations as long
> > as it's done consistently.
>  
> This is probably v4.11 material. We *may* be able to get this into
> v4.10 if I review and merge this soon, but it definitely isn't going
> to be included in the imminent pull request.
> 
> I do like the general idea though.

Yes, this was posted quite late in the cycle so I didn't expect it
to make it into 4.10 really.  It was meant as a demonstration,
I can respin this into a series that deduplicates these redundancies
more thoroughly, but I wanted to gauge the reaction of the community
first.  Ard should probably also weigh in since it touches ARM code.

By the way, you mentioned that you have a MacBook2,1, is this the
Late 2006 version and would you be able to test changes to the
efistub on that machine?  I was thinking about obtaining such a
machine myself on ebay since right now I can only test x86_64,
not mixed mode.  If noone else is able to perform tests I might
just do that.  (Only the Late 2006 version uses mixed mode, the
Mid 2007 has a native 64-bit EFI.)


> > In __file_size32() all protocol calls are currently cast to unsigned long,
> > which is 64 bit when compiled on x86_64.  Matt has said that the register
> > needs to be loaded with a 32 bit address, so it looks to me like this is
> > currently broken for mixed-mode.  Patch [1/2] should fix this.  E.g.:
> > 
> > 	efi_file_handle_32_t *h, *fh = __fh;
> > [...]
> > 	status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
> > 				 &info_sz, NULL);
> 
> There's a subtle distinction here between 32-bit address and 32-bit
> value. A 64-bit value can be a valid 32-bit address, provided that the
> upper 32-bits are zero, e.g. 0x00000000ffffffff.
> 
> So when I say "32-bit address" I really just mean some value where
> only the lower 32-bits are important.
> 
> That is why using unsigned long in mixed-mode is OK for the early call
> code.
>  
> > Another oddity is that info_sz is declared u32 in __file_size32(),
> > yet the spec says that the third argument to EFI_FILE_PROTOCOL.GetInfo()
> > is of type UINTN, which I assume is 64 bit regardless of mixed-mode,
> > or am I missing something?  Patch [1/2] uses an unsigned long instead.
> 
> UINTN is an unsigned value of native width as seen by the firmware. On
> 32-bit firmware that's 32-bits and 64-bit firmware 64-bits.
> 
> Using 'u32' in __file_size32() is correct, unsigned long is not.

Okay since this is all little endian, it should be okay to have a
64 bit wide variable on the stack whose address is passed to GetInfo()
as BufferSize argument.  But I guess I need to initialize it to 0
upon declaration so that the upper 32 bit are zeroed out in mixed mode,
right?  That would be a bug in patch [1/2] then.

Thanks,

Lukas

^ permalink raw reply

* Re: [PATCH] f2fs: don't wait writeback for datas during checkpoint
From: Chao Yu @ 2016-11-14 11:17 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel, chao
In-Reply-To: <20161110200340.GA80797@jaegeuk>

Hi Jaegeuk,

On 2016/11/11 4:03, Jaegeuk Kim wrote:
> Hi Chao,
> 
> On Thu, Nov 10, 2016 at 07:40:03PM +0800, Chao Yu wrote:
>> Normally, while committing checkpoint, we will wait on all pages to be
>> writebacked no matter the page is data or metadata, so in scenario where
>> there are lots of data IO being submitted with metadata, we may suffer
>> long latency for waiting writeback during checkpoint.
>>
>> Indeed, we only care about persistence for pages with metadata, but not
>> pages with data, as file system consistent are only related to metadate,
>> so in order to avoid encountering long latency in above scenario, let's
>> recognize and reference metadata in submitted IOs, wait writeback only
>> for metadatas.
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>  fs/f2fs/checkpoint.c |  2 +-
>>  fs/f2fs/data.c       |  9 +++++++--
>>  fs/f2fs/debug.c      |  7 ++++---
>>  fs/f2fs/f2fs.h       | 26 +++++++++++++++++++++++---
>>  fs/f2fs/gc.c         |  2 ++
>>  fs/f2fs/node.c       |  1 +
>>  fs/f2fs/segment.c    |  2 ++
>>  7 files changed, 40 insertions(+), 9 deletions(-)
>>
>> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
>> index 7bece59..bdf8a50 100644
>> --- a/fs/f2fs/checkpoint.c
>> +++ b/fs/f2fs/checkpoint.c
>> @@ -1003,7 +1003,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
>>  	for (;;) {
>>  		prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
>>  
>> -		if (!atomic_read(&sbi->nr_wb_bios))
>> +		if (!get_pages(sbi, F2FS_WB_META))
>>  			break;
>>  
>>  		io_schedule_timeout(5*HZ);
>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>> index 66d2aee..2fb1ffd 100644
>> --- a/fs/f2fs/data.c
>> +++ b/fs/f2fs/data.c
>> @@ -73,6 +73,7 @@ static void f2fs_write_end_io(struct bio *bio)
>>  
>>  	bio_for_each_segment_all(bvec, bio, i) {
>>  		struct page *page = bvec->bv_page;
>> +		bool is_meta = f2fs_is_meta_data(page);
>>  
>>  		fscrypt_pullback_bio_page(&page, true);
>>  
>> @@ -80,9 +81,10 @@ static void f2fs_write_end_io(struct bio *bio)
>>  			mapping_set_error(page->mapping, -EIO);
>>  			f2fs_stop_checkpoint(sbi, true);
>>  		}
>> +		dec_page_count(sbi, is_meta ? F2FS_WB_META : F2FS_WB_DATA);
>>  		end_page_writeback(page);
>>  	}
>> -	if (atomic_dec_and_test(&sbi->nr_wb_bios) &&
>> +	if (!get_pages(sbi, F2FS_WB_META) &&
>>  				wq_has_sleeper(&sbi->cp_wait))
>>  		wake_up(&sbi->cp_wait);
>>  
>> @@ -111,7 +113,6 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
>>  				struct bio *bio, enum page_type type)
>>  {
>>  	if (!is_read_io(bio_op(bio))) {
>> -		atomic_inc(&sbi->nr_wb_bios);
>>  		if (f2fs_sb_mounted_blkzoned(sbi->sb) &&
>>  			current->plug && (type == DATA || type == NODE))
>>  			blk_finish_plug(current->plug);
>> @@ -272,6 +273,9 @@ void f2fs_submit_page_mbio(struct f2fs_io_info *fio)
>>  		verify_block_addr(sbi, fio->old_blkaddr);
>>  	verify_block_addr(sbi, fio->new_blkaddr);
>>  
>> +	if (!is_read)
>> +		inc_page_count(sbi, fio->is_meta ? F2FS_WB_META : F2FS_WB_DATA);
>> +
> 
> How about using f2fs_is_meta_data(page) instead of changing fio?

Yes, I've cleaned up codes as you mentioned, and also fix incorrectly handling
of GCed encrypted datas. Could you please review the following v2 patch?

Thanks,

> 
> Thanks,
> 
>>  	down_write(&io->io_rwsem);
>>  
>>  	if (io->bio && (io->last_block_in_bio != fio->new_blkaddr - 1 ||
>> @@ -1237,6 +1241,7 @@ static int f2fs_write_data_page(struct page *page,
>>  		.type = DATA,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
>> +		.is_meta = S_ISDIR(inode->i_mode),
>>  		.page = page,
>>  		.encrypted_page = NULL,
>>  	};
>> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
>> index 2fdf233..f2d87de 100644
>> --- a/fs/f2fs/debug.c
>> +++ b/fs/f2fs/debug.c
>> @@ -50,7 +50,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)
>>  	si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
>>  	si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
>>  	si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
>> -	si->wb_bios = atomic_read(&sbi->nr_wb_bios);
>> +	si->nr_wb_meta = get_pages(sbi, F2FS_WB_META);
>> +	si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA);
>>  	si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
>>  	si->rsvd_segs = reserved_segments(sbi);
>>  	si->overp_segs = overprovision_segments(sbi);
>> @@ -313,8 +314,8 @@ static int stat_show(struct seq_file *s, void *v)
>>  		seq_printf(s, "  - Inner Struct Count: tree: %d(%d), node: %d\n",
>>  				si->ext_tree, si->zombie_tree, si->ext_node);
>>  		seq_puts(s, "\nBalancing F2FS Async:\n");
>> -		seq_printf(s, "  - inmem: %4d, wb_bios: %4d\n",
>> -			   si->inmem_pages, si->wb_bios);
>> +		seq_printf(s, "  - inmem: %4d, wb_meta: %4d, wb_data: %4d\n",
>> +			   si->inmem_pages, si->nr_wb_meta, si->nr_wb_data);
>>  		seq_printf(s, "  - nodes: %4d in %4d\n",
>>  			   si->ndirty_node, si->node_pages);
>>  		seq_printf(s, "  - dents: %4d in dirs:%4d (%4d)\n",
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index 23a937f..95ad091 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -682,6 +682,8 @@ enum count_type {
>>  	F2FS_DIRTY_META,
>>  	F2FS_INMEM_PAGES,
>>  	F2FS_DIRTY_IMETA,
>> +	F2FS_WB_META,
>> +	F2FS_WB_DATA,
>>  	NR_COUNT_TYPE,
>>  };
>>  
>> @@ -715,6 +717,7 @@ struct f2fs_io_info {
>>  	enum page_type type;	/* contains DATA/NODE/META/META_FLUSH */
>>  	int op;			/* contains REQ_OP_ */
>>  	int op_flags;		/* rq_flag_bits */
>> +	bool is_meta;		/* checkpoint needs to wait its writeback */
>>  	block_t new_blkaddr;	/* new block address to be written */
>>  	block_t old_blkaddr;	/* old block address before Cow */
>>  	struct page *page;	/* page to be written */
>> @@ -849,7 +852,6 @@ struct f2fs_sb_info {
>>  	block_t discard_blks;			/* discard command candidats */
>>  	block_t last_valid_block_count;		/* for recovery */
>>  	u32 s_next_generation;			/* for NFS support */
>> -	atomic_t nr_wb_bios;			/* # of writeback bios */
>>  
>>  	/* # of pages, see count_type */
>>  	atomic_t nr_pages[NR_COUNT_TYPE];
>> @@ -1193,6 +1195,23 @@ static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
>>  	return 0;
>>  }
>>  
>> +static inline bool f2fs_is_meta_data(struct page *page)
>> +{
>> +	struct address_space *mapping = page->mapping;
>> +	struct inode *inode;
>> +
>> +	/* it is bounce page of encrypted regular inode */
>> +	if (!mapping)
>> +		return false;
>> +
>> +	inode = mapping->host;
>> +	if (inode->i_ino ==  F2FS_NODE_INO(F2FS_I_SB(inode)) ||
>> +		inode->i_ino == F2FS_META_INO(F2FS_I_SB(inode)) ||
>> +		S_ISDIR(inode->i_mode))
>> +		return true;
>> +	return false;
>> +}
>> +
>>  #define F2FS_DEFAULT_ALLOCATED_BLOCKS	1
>>  
>>  /*
>> @@ -1263,7 +1282,8 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
>>  {
>>  	atomic_inc(&sbi->nr_pages[count_type]);
>>  
>> -	if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES)
>> +	if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES ||
>> +		count_type == F2FS_WB_META || count_type == F2FS_WB_DATA)
>>  		return;
>>  
>>  	set_sbi_flag(sbi, SBI_IS_DIRTY);
>> @@ -2219,7 +2239,7 @@ struct f2fs_stat_info {
>>  	unsigned int ndirty_dirs, ndirty_files, ndirty_all;
>>  	int nats, dirty_nats, sits, dirty_sits, free_nids, alloc_nids;
>>  	int total_count, utilization;
>> -	int bg_gc, wb_bios;
>> +	int bg_gc, nr_wb_meta, nr_wb_data;
>>  	int inline_xattr, inline_inode, inline_dir, orphans;
>>  	unsigned int valid_count, valid_node_count, valid_inode_count, discard_blks;
>>  	unsigned int bimodal, avg_vblocks;
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index f8d8cc96a..6b762d4 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -554,6 +554,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>>  		.type = DATA,
>>  		.op = REQ_OP_READ,
>>  		.op_flags = READ_SYNC,
>> +		.is_meta = true,
>>  		.encrypted_page = NULL,
>>  	};
>>  	struct dnode_of_data dn;
>> @@ -674,6 +675,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
>>  			.type = DATA,
>>  			.op = REQ_OP_WRITE,
>>  			.op_flags = WRITE_SYNC,
>> +			.is_meta = S_ISDIR(inode->i_mode),
>>  			.page = page,
>>  			.encrypted_page = NULL,
>>  		};
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index d58438f..3c7e00c 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -1574,6 +1574,7 @@ static int f2fs_write_node_page(struct page *page,
>>  		.type = NODE,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
>> +		.is_meta = true,
>>  		.page = page,
>>  		.encrypted_page = NULL,
>>  	};
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 078c571..b34e20a 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -261,6 +261,7 @@ static int __commit_inmem_pages(struct inode *inode,
>>  		.type = DATA,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = WRITE_SYNC | REQ_PRIO,
>> +		.is_meta = false,
>>  		.encrypted_page = NULL,
>>  	};
>>  	bool submit_bio = false;
>> @@ -1573,6 +1574,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
>>  		.type = META,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = WRITE_SYNC | REQ_META | REQ_PRIO,
>> +		.is_meta = true,
>>  		.old_blkaddr = page->index,
>>  		.new_blkaddr = page->index,
>>  		.page = page,
>> -- 
>> 2.8.2.311.gee88674
> 
> .
> 

^ permalink raw reply

* Re: [SECILC] does not seem to filter redundant attributes and rules
From: Dominick Grift @ 2016-11-14 11:18 UTC (permalink / raw)
  To: selinux
In-Reply-To: <b7824486-d9fc-82df-2611-aff0883f1a56@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 2871 bytes --]

On 11/14/2016 11:11 AM, Dominick Grift wrote:
> On 11/09/2016 03:52 PM, James Carter wrote:
>> On 11/09/2016 07:40 AM, Dominick Grift wrote:
>>> I am in the process of a DSSP rewrite, taking a different approach this
>>> time.
>>>
>>> However I encountered something that seems suboptimal:
>>>
>>> SECILC seems to not filter redundant attributes and rules
>>>
>>> Example i have a type attribute and it has rules associated with it.
>>> However, the type attribute is not associated with any types.
>>>
>>> I was hoping that SECILC would be smart enough to determine that it
>>> might as well filter both the type attribute as well as the rules
>>> associated with it.
>>>
>>> To reproduce:
>>>
>>> git clone https://github.com/DefenSec/dssp1-base.git
>>> cd dssp1-base
>>> secilc `ls *.cil`
>>> sesearch -ASCT -s lib.ld_so.read_files_subj_type_attribute policy.30
>>> seinfo -xalib.ld_so.read_files_subj_type_attribute policy.30
>>>
>>>
>>> Am i expecting the impossible by expecting SECILC to be smart enough to
>>> determine that something is redundant, and that it can be filtered out
>>> until it becomes applicable?
>>>
>>>
>>
>> I don't think that it would be too hard to remove attributes that have
>> no types associated with them along with rules containing those
>> attributes. I have this nagging feeling, though, that there is a reason
>> that we didn't do that. I'll have to think about it a bit.
>>
>> Jim
> 
> Have you given this some thought?
> 
> I suspect this could have significant impact.
> 
> consider the following:
> 
> CIL encourages the use of attributes to the fullest extent, and with
> dssp1 i have taken this to heart.
> 
> This should make dssp1 very scale-able. The more an identifier is used
> the greater the potential benefit.
> 
> Attributes and templates are at the heart of dssp1 and if the dssp1
> model turns out to work (it is still a work in progress and I dont quite
> see where this is eventually taking me) then this would be a very
> welcome feature.
> 
> If you want to see the current state of dssp1:
> 
> git clone https://github.com/DefenSec/dssp1-base.git
> cd dssp1-base
> secilc `ls *.cil`
> seinfo policy.30

Here is a 10 minute demo that tries to explain the benefits and the
current drawbacks of this approach (for anyone interested)

https://www.youtube.com/watch?v=MdqjVgjXvM8

> 
>>
>>
>>>
>>> _______________________________________________
>>> Selinux mailing list
>>> Selinux@tycho.nsa.gov
>>> To unsubscribe, send email to Selinux-leave@tycho.nsa.gov.
>>> To get help, send an email containing "help" to
>>> Selinux-request@tycho.nsa.gov.
>>>
>>
>>
> 
> 


-- 
Key fingerprint = 5F4D 3CDB D3F8 3652 FBD8  02D5 3B6C 5F1D 2C7B 6B02
https://sks-keyservers.net/pks/lookup?op=get&search=0x3B6C5F1D2C7B6B02
Dominick Grift


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 648 bytes --]

^ permalink raw reply

* Re: [PATCH] f2fs: don't wait writeback for datas during checkpoint
From: Chao Yu @ 2016-11-14 11:17 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: chao, linux-kernel, linux-f2fs-devel
In-Reply-To: <20161110200340.GA80797@jaegeuk>

Hi Jaegeuk,

On 2016/11/11 4:03, Jaegeuk Kim wrote:
> Hi Chao,
> 
> On Thu, Nov 10, 2016 at 07:40:03PM +0800, Chao Yu wrote:
>> Normally, while committing checkpoint, we will wait on all pages to be
>> writebacked no matter the page is data or metadata, so in scenario where
>> there are lots of data IO being submitted with metadata, we may suffer
>> long latency for waiting writeback during checkpoint.
>>
>> Indeed, we only care about persistence for pages with metadata, but not
>> pages with data, as file system consistent are only related to metadate,
>> so in order to avoid encountering long latency in above scenario, let's
>> recognize and reference metadata in submitted IOs, wait writeback only
>> for metadatas.
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>>  fs/f2fs/checkpoint.c |  2 +-
>>  fs/f2fs/data.c       |  9 +++++++--
>>  fs/f2fs/debug.c      |  7 ++++---
>>  fs/f2fs/f2fs.h       | 26 +++++++++++++++++++++++---
>>  fs/f2fs/gc.c         |  2 ++
>>  fs/f2fs/node.c       |  1 +
>>  fs/f2fs/segment.c    |  2 ++
>>  7 files changed, 40 insertions(+), 9 deletions(-)
>>
>> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
>> index 7bece59..bdf8a50 100644
>> --- a/fs/f2fs/checkpoint.c
>> +++ b/fs/f2fs/checkpoint.c
>> @@ -1003,7 +1003,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
>>  	for (;;) {
>>  		prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
>>  
>> -		if (!atomic_read(&sbi->nr_wb_bios))
>> +		if (!get_pages(sbi, F2FS_WB_META))
>>  			break;
>>  
>>  		io_schedule_timeout(5*HZ);
>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>> index 66d2aee..2fb1ffd 100644
>> --- a/fs/f2fs/data.c
>> +++ b/fs/f2fs/data.c
>> @@ -73,6 +73,7 @@ static void f2fs_write_end_io(struct bio *bio)
>>  
>>  	bio_for_each_segment_all(bvec, bio, i) {
>>  		struct page *page = bvec->bv_page;
>> +		bool is_meta = f2fs_is_meta_data(page);
>>  
>>  		fscrypt_pullback_bio_page(&page, true);
>>  
>> @@ -80,9 +81,10 @@ static void f2fs_write_end_io(struct bio *bio)
>>  			mapping_set_error(page->mapping, -EIO);
>>  			f2fs_stop_checkpoint(sbi, true);
>>  		}
>> +		dec_page_count(sbi, is_meta ? F2FS_WB_META : F2FS_WB_DATA);
>>  		end_page_writeback(page);
>>  	}
>> -	if (atomic_dec_and_test(&sbi->nr_wb_bios) &&
>> +	if (!get_pages(sbi, F2FS_WB_META) &&
>>  				wq_has_sleeper(&sbi->cp_wait))
>>  		wake_up(&sbi->cp_wait);
>>  
>> @@ -111,7 +113,6 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
>>  				struct bio *bio, enum page_type type)
>>  {
>>  	if (!is_read_io(bio_op(bio))) {
>> -		atomic_inc(&sbi->nr_wb_bios);
>>  		if (f2fs_sb_mounted_blkzoned(sbi->sb) &&
>>  			current->plug && (type == DATA || type == NODE))
>>  			blk_finish_plug(current->plug);
>> @@ -272,6 +273,9 @@ void f2fs_submit_page_mbio(struct f2fs_io_info *fio)
>>  		verify_block_addr(sbi, fio->old_blkaddr);
>>  	verify_block_addr(sbi, fio->new_blkaddr);
>>  
>> +	if (!is_read)
>> +		inc_page_count(sbi, fio->is_meta ? F2FS_WB_META : F2FS_WB_DATA);
>> +
> 
> How about using f2fs_is_meta_data(page) instead of changing fio?

Yes, I've cleaned up codes as you mentioned, and also fix incorrectly handling
of GCed encrypted datas. Could you please review the following v2 patch?

Thanks,

> 
> Thanks,
> 
>>  	down_write(&io->io_rwsem);
>>  
>>  	if (io->bio && (io->last_block_in_bio != fio->new_blkaddr - 1 ||
>> @@ -1237,6 +1241,7 @@ static int f2fs_write_data_page(struct page *page,
>>  		.type = DATA,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
>> +		.is_meta = S_ISDIR(inode->i_mode),
>>  		.page = page,
>>  		.encrypted_page = NULL,
>>  	};
>> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
>> index 2fdf233..f2d87de 100644
>> --- a/fs/f2fs/debug.c
>> +++ b/fs/f2fs/debug.c
>> @@ -50,7 +50,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)
>>  	si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
>>  	si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
>>  	si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
>> -	si->wb_bios = atomic_read(&sbi->nr_wb_bios);
>> +	si->nr_wb_meta = get_pages(sbi, F2FS_WB_META);
>> +	si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA);
>>  	si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
>>  	si->rsvd_segs = reserved_segments(sbi);
>>  	si->overp_segs = overprovision_segments(sbi);
>> @@ -313,8 +314,8 @@ static int stat_show(struct seq_file *s, void *v)
>>  		seq_printf(s, "  - Inner Struct Count: tree: %d(%d), node: %d\n",
>>  				si->ext_tree, si->zombie_tree, si->ext_node);
>>  		seq_puts(s, "\nBalancing F2FS Async:\n");
>> -		seq_printf(s, "  - inmem: %4d, wb_bios: %4d\n",
>> -			   si->inmem_pages, si->wb_bios);
>> +		seq_printf(s, "  - inmem: %4d, wb_meta: %4d, wb_data: %4d\n",
>> +			   si->inmem_pages, si->nr_wb_meta, si->nr_wb_data);
>>  		seq_printf(s, "  - nodes: %4d in %4d\n",
>>  			   si->ndirty_node, si->node_pages);
>>  		seq_printf(s, "  - dents: %4d in dirs:%4d (%4d)\n",
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index 23a937f..95ad091 100644
>> --- a/fs/f2fs/f2fs.h
>> +++ b/fs/f2fs/f2fs.h
>> @@ -682,6 +682,8 @@ enum count_type {
>>  	F2FS_DIRTY_META,
>>  	F2FS_INMEM_PAGES,
>>  	F2FS_DIRTY_IMETA,
>> +	F2FS_WB_META,
>> +	F2FS_WB_DATA,
>>  	NR_COUNT_TYPE,
>>  };
>>  
>> @@ -715,6 +717,7 @@ struct f2fs_io_info {
>>  	enum page_type type;	/* contains DATA/NODE/META/META_FLUSH */
>>  	int op;			/* contains REQ_OP_ */
>>  	int op_flags;		/* rq_flag_bits */
>> +	bool is_meta;		/* checkpoint needs to wait its writeback */
>>  	block_t new_blkaddr;	/* new block address to be written */
>>  	block_t old_blkaddr;	/* old block address before Cow */
>>  	struct page *page;	/* page to be written */
>> @@ -849,7 +852,6 @@ struct f2fs_sb_info {
>>  	block_t discard_blks;			/* discard command candidats */
>>  	block_t last_valid_block_count;		/* for recovery */
>>  	u32 s_next_generation;			/* for NFS support */
>> -	atomic_t nr_wb_bios;			/* # of writeback bios */
>>  
>>  	/* # of pages, see count_type */
>>  	atomic_t nr_pages[NR_COUNT_TYPE];
>> @@ -1193,6 +1195,23 @@ static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
>>  	return 0;
>>  }
>>  
>> +static inline bool f2fs_is_meta_data(struct page *page)
>> +{
>> +	struct address_space *mapping = page->mapping;
>> +	struct inode *inode;
>> +
>> +	/* it is bounce page of encrypted regular inode */
>> +	if (!mapping)
>> +		return false;
>> +
>> +	inode = mapping->host;
>> +	if (inode->i_ino ==  F2FS_NODE_INO(F2FS_I_SB(inode)) ||
>> +		inode->i_ino == F2FS_META_INO(F2FS_I_SB(inode)) ||
>> +		S_ISDIR(inode->i_mode))
>> +		return true;
>> +	return false;
>> +}
>> +
>>  #define F2FS_DEFAULT_ALLOCATED_BLOCKS	1
>>  
>>  /*
>> @@ -1263,7 +1282,8 @@ static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
>>  {
>>  	atomic_inc(&sbi->nr_pages[count_type]);
>>  
>> -	if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES)
>> +	if (count_type == F2FS_DIRTY_DATA || count_type == F2FS_INMEM_PAGES ||
>> +		count_type == F2FS_WB_META || count_type == F2FS_WB_DATA)
>>  		return;
>>  
>>  	set_sbi_flag(sbi, SBI_IS_DIRTY);
>> @@ -2219,7 +2239,7 @@ struct f2fs_stat_info {
>>  	unsigned int ndirty_dirs, ndirty_files, ndirty_all;
>>  	int nats, dirty_nats, sits, dirty_sits, free_nids, alloc_nids;
>>  	int total_count, utilization;
>> -	int bg_gc, wb_bios;
>> +	int bg_gc, nr_wb_meta, nr_wb_data;
>>  	int inline_xattr, inline_inode, inline_dir, orphans;
>>  	unsigned int valid_count, valid_node_count, valid_inode_count, discard_blks;
>>  	unsigned int bimodal, avg_vblocks;
>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>> index f8d8cc96a..6b762d4 100644
>> --- a/fs/f2fs/gc.c
>> +++ b/fs/f2fs/gc.c
>> @@ -554,6 +554,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
>>  		.type = DATA,
>>  		.op = REQ_OP_READ,
>>  		.op_flags = READ_SYNC,
>> +		.is_meta = true,
>>  		.encrypted_page = NULL,
>>  	};
>>  	struct dnode_of_data dn;
>> @@ -674,6 +675,7 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
>>  			.type = DATA,
>>  			.op = REQ_OP_WRITE,
>>  			.op_flags = WRITE_SYNC,
>> +			.is_meta = S_ISDIR(inode->i_mode),
>>  			.page = page,
>>  			.encrypted_page = NULL,
>>  		};
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index d58438f..3c7e00c 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -1574,6 +1574,7 @@ static int f2fs_write_node_page(struct page *page,
>>  		.type = NODE,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
>> +		.is_meta = true,
>>  		.page = page,
>>  		.encrypted_page = NULL,
>>  	};
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index 078c571..b34e20a 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -261,6 +261,7 @@ static int __commit_inmem_pages(struct inode *inode,
>>  		.type = DATA,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = WRITE_SYNC | REQ_PRIO,
>> +		.is_meta = false,
>>  		.encrypted_page = NULL,
>>  	};
>>  	bool submit_bio = false;
>> @@ -1573,6 +1574,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
>>  		.type = META,
>>  		.op = REQ_OP_WRITE,
>>  		.op_flags = WRITE_SYNC | REQ_META | REQ_PRIO,
>> +		.is_meta = true,
>>  		.old_blkaddr = page->index,
>>  		.new_blkaddr = page->index,
>>  		.page = page,
>> -- 
>> 2.8.2.311.gee88674
> 
> .
> 


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

^ permalink raw reply

* [U-Boot] [PATCH 4/7] tools: sunxi: Add spl image builder
From: Hans de Goede @ 2016-11-14 11:18 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <312ad66b8bd78b877f82ebd2fb16efcbb51e0a15.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> This program generates raw SPL images that can be flashed on the NAND with
> the ECC and randomizer properly set up.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



> ---
>  tools/.gitignore                |    1 +-
>  tools/Makefile                  |    1 +-
>  tools/sunxi-spl-image-builder.c | 1113 ++++++++++++++++++++++++++++++++-
>  3 files changed, 1115 insertions(+), 0 deletions(-)
>  create mode 100644 tools/sunxi-spl-image-builder.c
>
> diff --git a/tools/.gitignore b/tools/.gitignore
> index cb1e722d4575..16574467544c 100644
> --- a/tools/.gitignore
> +++ b/tools/.gitignore
> @@ -15,6 +15,7 @@
>  /mkexynosspl
>  /mxsboot
>  /mksunxiboot
> +/sunxi-spl-image-builder
>  /ncb
>  /proftool
>  /relocate-rela
> diff --git a/tools/Makefile b/tools/Makefile
> index 400588cf0f5c..dfeeb23484ce 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -171,6 +171,7 @@ hostprogs-$(CONFIG_MX28) += mxsboot
>  HOSTCFLAGS_mxsboot.o := -pedantic
>
>  hostprogs-$(CONFIG_ARCH_SUNXI) += mksunxiboot
> +hostprogs-$(CONFIG_ARCH_SUNXI) += sunxi-spl-image-builder
>
>  hostprogs-$(CONFIG_NETCONSOLE) += ncb
>  hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1
> diff --git a/tools/sunxi-spl-image-builder.c b/tools/sunxi-spl-image-builder.c
> new file mode 100644
> index 000000000000..0f915eb2bdf5
> --- /dev/null
> +++ b/tools/sunxi-spl-image-builder.c
> @@ -0,0 +1,1113 @@
> +/*
> + * Generic binary BCH encoding/decoding library
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 51
> + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + * For the BCH implementation:
> + *
> + * Copyright ? 2011 Parrot S.A.
> + *
> + * Author: Ivan Djelic <ivan.djelic@parrot.com>
> + *
> + * See also:
> + * http://lxr.free-electrons.com/source/lib/bch.c
> + *
> + * For the randomizer and image builder implementation:
> + *
> + * Copyright ? 2016 NextThing Co.
> + * Copyright ? 2016 Free Electrons
> + *
> + * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
> + *
> + */
> +
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <asm/byteorder.h>
> +#include <endian.h>
> +#include <getopt.h>
> +#include <version.h>
> +
> +#if defined(CONFIG_BCH_CONST_PARAMS)
> +#define GF_M(_p)               (CONFIG_BCH_CONST_M)
> +#define GF_T(_p)               (CONFIG_BCH_CONST_T)
> +#define GF_N(_p)               ((1 << (CONFIG_BCH_CONST_M))-1)
> +#else
> +#define GF_M(_p)               ((_p)->m)
> +#define GF_T(_p)               ((_p)->t)
> +#define GF_N(_p)               ((_p)->n)
> +#endif
> +
> +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
> +
> +#define BCH_ECC_WORDS(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
> +#define BCH_ECC_BYTES(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
> +
> +#ifndef dbg
> +#define dbg(_fmt, args...)     do {} while (0)
> +#endif
> +
> +#define cpu_to_be32 htobe32
> +#define kfree free
> +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> +
> +#define BCH_PRIMITIVE_POLY	0x5803
> +
> +struct image_info {
> +	int ecc_strength;
> +	int ecc_step_size;
> +	int page_size;
> +	int oob_size;
> +	int usable_page_size;
> +	int eraseblock_size;
> +	int scramble;
> +	int boot0;
> +	off_t offset;
> +	const char *source;
> +	const char *dest;
> +};
> +
> +/**
> + * struct bch_control - BCH control structure
> + * @m:          Galois field order
> + * @n:          maximum codeword size in bits (= 2^m-1)
> + * @t:          error correction capability in bits
> + * @ecc_bits:   ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
> + * @ecc_bytes:  ecc max size (m*t bits) in bytes
> + * @a_pow_tab:  Galois field GF(2^m) exponentiation lookup table
> + * @a_log_tab:  Galois field GF(2^m) log lookup table
> + * @mod8_tab:   remainder generator polynomial lookup tables
> + * @ecc_buf:    ecc parity words buffer
> + * @ecc_buf2:   ecc parity words buffer
> + * @xi_tab:     GF(2^m) base for solving degree 2 polynomial roots
> + * @syn:        syndrome buffer
> + * @cache:      log-based polynomial representation buffer
> + * @elp:        error locator polynomial
> + * @poly_2t:    temporary polynomials of degree 2t
> + */
> +struct bch_control {
> +	unsigned int    m;
> +	unsigned int    n;
> +	unsigned int    t;
> +	unsigned int    ecc_bits;
> +	unsigned int    ecc_bytes;
> +/* private: */
> +	uint16_t       *a_pow_tab;
> +	uint16_t       *a_log_tab;
> +	uint32_t       *mod8_tab;
> +	uint32_t       *ecc_buf;
> +	uint32_t       *ecc_buf2;
> +	unsigned int   *xi_tab;
> +	unsigned int   *syn;
> +	int            *cache;
> +	struct gf_poly *elp;
> +	struct gf_poly *poly_2t[4];
> +};
> +
> +static int fls(int x)
> +{
> +	int r = 32;
> +
> +	if (!x)
> +		return 0;
> +	if (!(x & 0xffff0000u)) {
> +		x <<= 16;
> +		r -= 16;
> +	}
> +	if (!(x & 0xff000000u)) {
> +		x <<= 8;
> +		r -= 8;
> +	}
> +	if (!(x & 0xf0000000u)) {
> +		x <<= 4;
> +		r -= 4;
> +	}
> +	if (!(x & 0xc0000000u)) {
> +		x <<= 2;
> +		r -= 2;
> +	}
> +	if (!(x & 0x80000000u)) {
> +		x <<= 1;
> +		r -= 1;
> +	}
> +	return r;
> +}
> +
> +/*
> + * represent a polynomial over GF(2^m)
> + */
> +struct gf_poly {
> +	unsigned int deg;    /* polynomial degree */
> +	unsigned int c[0];   /* polynomial terms */
> +};
> +
> +/* given its degree, compute a polynomial size in bytes */
> +#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
> +
> +/* polynomial of degree 1 */
> +struct gf_poly_deg1 {
> +	struct gf_poly poly;
> +	unsigned int   c[2];
> +};
> +
> +/*
> + * same as encode_bch(), but process input data one byte at a time
> + */
> +static void encode_bch_unaligned(struct bch_control *bch,
> +				 const unsigned char *data, unsigned int len,
> +				 uint32_t *ecc)
> +{
> +	int i;
> +	const uint32_t *p;
> +	const int l = BCH_ECC_WORDS(bch)-1;
> +
> +	while (len--) {
> +		p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
> +
> +		for (i = 0; i < l; i++)
> +			ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
> +
> +		ecc[l] = (ecc[l] << 8)^(*p);
> +	}
> +}
> +
> +/*
> + * convert ecc bytes to aligned, zero-padded 32-bit ecc words
> + */
> +static void load_ecc8(struct bch_control *bch, uint32_t *dst,
> +		      const uint8_t *src)
> +{
> +	uint8_t pad[4] = {0, 0, 0, 0};
> +	unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
> +
> +	for (i = 0; i < nwords; i++, src += 4)
> +		dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
> +
> +	memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
> +	dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
> +}
> +
> +/*
> + * convert 32-bit ecc words to ecc bytes
> + */
> +static void store_ecc8(struct bch_control *bch, uint8_t *dst,
> +		       const uint32_t *src)
> +{
> +	uint8_t pad[4];
> +	unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
> +
> +	for (i = 0; i < nwords; i++) {
> +		*dst++ = (src[i] >> 24);
> +		*dst++ = (src[i] >> 16) & 0xff;
> +		*dst++ = (src[i] >>  8) & 0xff;
> +		*dst++ = (src[i] >>  0) & 0xff;
> +	}
> +	pad[0] = (src[nwords] >> 24);
> +	pad[1] = (src[nwords] >> 16) & 0xff;
> +	pad[2] = (src[nwords] >>  8) & 0xff;
> +	pad[3] = (src[nwords] >>  0) & 0xff;
> +	memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
> +}
> +
> +/**
> + * encode_bch - calculate BCH ecc parity of data
> + * @bch:   BCH control structure
> + * @data:  data to encode
> + * @len:   data length in bytes
> + * @ecc:   ecc parity data, must be initialized by caller
> + *
> + * The @ecc parity array is used both as input and output parameter, in order to
> + * allow incremental computations. It should be of the size indicated by member
> + * @ecc_bytes of @bch, and should be initialized to 0 before the first call.
> + *
> + * The exact number of computed ecc parity bits is given by member @ecc_bits of
> + * @bch; it may be less than m*t for large values of t.
> + */
> +static void encode_bch(struct bch_control *bch, const uint8_t *data,
> +		unsigned int len, uint8_t *ecc)
> +{
> +	const unsigned int l = BCH_ECC_WORDS(bch)-1;
> +	unsigned int i, mlen;
> +	unsigned long m;
> +	uint32_t w, r[l+1];
> +	const uint32_t * const tab0 = bch->mod8_tab;
> +	const uint32_t * const tab1 = tab0 + 256*(l+1);
> +	const uint32_t * const tab2 = tab1 + 256*(l+1);
> +	const uint32_t * const tab3 = tab2 + 256*(l+1);
> +	const uint32_t *pdata, *p0, *p1, *p2, *p3;
> +
> +	if (ecc) {
> +		/* load ecc parity bytes into internal 32-bit buffer */
> +		load_ecc8(bch, bch->ecc_buf, ecc);
> +	} else {
> +		memset(bch->ecc_buf, 0, sizeof(r));
> +	}
> +
> +	/* process first unaligned data bytes */
> +	m = ((uintptr_t)data) & 3;
> +	if (m) {
> +		mlen = (len < (4-m)) ? len : 4-m;
> +		encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
> +		data += mlen;
> +		len  -= mlen;
> +	}
> +
> +	/* process 32-bit aligned data words */
> +	pdata = (uint32_t *)data;
> +	mlen  = len/4;
> +	data += 4*mlen;
> +	len  -= 4*mlen;
> +	memcpy(r, bch->ecc_buf, sizeof(r));
> +
> +	/*
> +	 * split each 32-bit word into 4 polynomials of weight 8 as follows:
> +	 *
> +	 * 31 ...24  23 ...16  15 ... 8  7 ... 0
> +	 * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt
> +	 *                               tttttttt  mod g = r0 (precomputed)
> +	 *                     zzzzzzzz  00000000  mod g = r1 (precomputed)
> +	 *           yyyyyyyy  00000000  00000000  mod g = r2 (precomputed)
> +	 * xxxxxxxx  00000000  00000000  00000000  mod g = r3 (precomputed)
> +	 * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt  mod g = r0^r1^r2^r3
> +	 */
> +	while (mlen--) {
> +		/* input data is read in big-endian format */
> +		w = r[0]^cpu_to_be32(*pdata++);
> +		p0 = tab0 + (l+1)*((w >>  0) & 0xff);
> +		p1 = tab1 + (l+1)*((w >>  8) & 0xff);
> +		p2 = tab2 + (l+1)*((w >> 16) & 0xff);
> +		p3 = tab3 + (l+1)*((w >> 24) & 0xff);
> +
> +		for (i = 0; i < l; i++)
> +			r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
> +
> +		r[l] = p0[l]^p1[l]^p2[l]^p3[l];
> +	}
> +	memcpy(bch->ecc_buf, r, sizeof(r));
> +
> +	/* process last unaligned bytes */
> +	if (len)
> +		encode_bch_unaligned(bch, data, len, bch->ecc_buf);
> +
> +	/* store ecc parity bytes into original parity buffer */
> +	if (ecc)
> +		store_ecc8(bch, ecc, bch->ecc_buf);
> +}
> +
> +static inline int modulo(struct bch_control *bch, unsigned int v)
> +{
> +	const unsigned int n = GF_N(bch);
> +	while (v >= n) {
> +		v -= n;
> +		v = (v & n) + (v >> GF_M(bch));
> +	}
> +	return v;
> +}
> +
> +/*
> + * shorter and faster modulo function, only works when v < 2N.
> + */
> +static inline int mod_s(struct bch_control *bch, unsigned int v)
> +{
> +	const unsigned int n = GF_N(bch);
> +	return (v < n) ? v : v-n;
> +}
> +
> +static inline int deg(unsigned int poly)
> +{
> +	/* polynomial degree is the most-significant bit index */
> +	return fls(poly)-1;
> +}
> +
> +/* Galois field basic operations: multiply, divide, inverse, etc. */
> +
> +static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
> +				  unsigned int b)
> +{
> +	return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
> +					       bch->a_log_tab[b])] : 0;
> +}
> +
> +static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
> +{
> +	return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
> +}
> +
> +static inline unsigned int a_pow(struct bch_control *bch, int i)
> +{
> +	return bch->a_pow_tab[modulo(bch, i)];
> +}
> +
> +static inline int a_log(struct bch_control *bch, unsigned int x)
> +{
> +	return bch->a_log_tab[x];
> +}
> +
> +/*
> + * generate Galois field lookup tables
> + */
> +static int build_gf_tables(struct bch_control *bch, unsigned int poly)
> +{
> +	unsigned int i, x = 1;
> +	const unsigned int k = 1 << deg(poly);
> +
> +	/* primitive polynomial must be of degree m */
> +	if (k != (1u << GF_M(bch)))
> +		return -1;
> +
> +	for (i = 0; i < GF_N(bch); i++) {
> +		bch->a_pow_tab[i] = x;
> +		bch->a_log_tab[x] = i;
> +		if (i && (x == 1))
> +			/* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
> +			return -1;
> +		x <<= 1;
> +		if (x & k)
> +			x ^= poly;
> +	}
> +	bch->a_pow_tab[GF_N(bch)] = 1;
> +	bch->a_log_tab[0] = 0;
> +
> +	return 0;
> +}
> +
> +/*
> + * compute generator polynomial remainder tables for fast encoding
> + */
> +static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
> +{
> +	int i, j, b, d;
> +	uint32_t data, hi, lo, *tab;
> +	const int l = BCH_ECC_WORDS(bch);
> +	const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
> +	const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
> +
> +	memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
> +
> +	for (i = 0; i < 256; i++) {
> +		/* p(X)=i is a small polynomial of weight <= 8 */
> +		for (b = 0; b < 4; b++) {
> +			/* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */
> +			tab = bch->mod8_tab + (b*256+i)*l;
> +			data = i << (8*b);
> +			while (data) {
> +				d = deg(data);
> +				/* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */
> +				data ^= g[0] >> (31-d);
> +				for (j = 0; j < ecclen; j++) {
> +					hi = (d < 31) ? g[j] << (d+1) : 0;
> +					lo = (j+1 < plen) ?
> +						g[j+1] >> (31-d) : 0;
> +					tab[j] ^= hi|lo;
> +				}
> +			}
> +		}
> +	}
> +}
> +
> +/*
> + * build a base for factoring degree 2 polynomials
> + */
> +static int build_deg2_base(struct bch_control *bch)
> +{
> +	const int m = GF_M(bch);
> +	int i, j, r;
> +	unsigned int sum, x, y, remaining, ak = 0, xi[m];
> +
> +	/* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
> +	for (i = 0; i < m; i++) {
> +		for (j = 0, sum = 0; j < m; j++)
> +			sum ^= a_pow(bch, i*(1 << j));
> +
> +		if (sum) {
> +			ak = bch->a_pow_tab[i];
> +			break;
> +		}
> +	}
> +	/* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */
> +	remaining = m;
> +	memset(xi, 0, sizeof(xi));
> +
> +	for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
> +		y = gf_sqr(bch, x)^x;
> +		for (i = 0; i < 2; i++) {
> +			r = a_log(bch, y);
> +			if (y && (r < m) && !xi[r]) {
> +				bch->xi_tab[r] = x;
> +				xi[r] = 1;
> +				remaining--;
> +				dbg("x%d = %x\n", r, x);
> +				break;
> +			}
> +			y ^= ak;
> +		}
> +	}
> +	/* should not happen but check anyway */
> +	return remaining ? -1 : 0;
> +}
> +
> +static void *bch_alloc(size_t size, int *err)
> +{
> +	void *ptr;
> +
> +	ptr = malloc(size);
> +	if (ptr == NULL)
> +		*err = 1;
> +	return ptr;
> +}
> +
> +/*
> + * compute generator polynomial for given (m,t) parameters.
> + */
> +static uint32_t *compute_generator_polynomial(struct bch_control *bch)
> +{
> +	const unsigned int m = GF_M(bch);
> +	const unsigned int t = GF_T(bch);
> +	int n, err = 0;
> +	unsigned int i, j, nbits, r, word, *roots;
> +	struct gf_poly *g;
> +	uint32_t *genpoly;
> +
> +	g = bch_alloc(GF_POLY_SZ(m*t), &err);
> +	roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
> +	genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
> +
> +	if (err) {
> +		kfree(genpoly);
> +		genpoly = NULL;
> +		goto finish;
> +	}
> +
> +	/* enumerate all roots of g(X) */
> +	memset(roots , 0, (bch->n+1)*sizeof(*roots));
> +	for (i = 0; i < t; i++) {
> +		for (j = 0, r = 2*i+1; j < m; j++) {
> +			roots[r] = 1;
> +			r = mod_s(bch, 2*r);
> +		}
> +	}
> +	/* build generator polynomial g(X) */
> +	g->deg = 0;
> +	g->c[0] = 1;
> +	for (i = 0; i < GF_N(bch); i++) {
> +		if (roots[i]) {
> +			/* multiply g(X) by (X+root) */
> +			r = bch->a_pow_tab[i];
> +			g->c[g->deg+1] = 1;
> +			for (j = g->deg; j > 0; j--)
> +				g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
> +
> +			g->c[0] = gf_mul(bch, g->c[0], r);
> +			g->deg++;
> +		}
> +	}
> +	/* store left-justified binary representation of g(X) */
> +	n = g->deg+1;
> +	i = 0;
> +
> +	while (n > 0) {
> +		nbits = (n > 32) ? 32 : n;
> +		for (j = 0, word = 0; j < nbits; j++) {
> +			if (g->c[n-1-j])
> +				word |= 1u << (31-j);
> +		}
> +		genpoly[i++] = word;
> +		n -= nbits;
> +	}
> +	bch->ecc_bits = g->deg;
> +
> +finish:
> +	kfree(g);
> +	kfree(roots);
> +
> +	return genpoly;
> +}
> +
> +/**
> + *  free_bch - free the BCH control structure
> + *  @bch:    BCH control structure to release
> + */
> +static void free_bch(struct bch_control *bch)
> +{
> +	unsigned int i;
> +
> +	if (bch) {
> +		kfree(bch->a_pow_tab);
> +		kfree(bch->a_log_tab);
> +		kfree(bch->mod8_tab);
> +		kfree(bch->ecc_buf);
> +		kfree(bch->ecc_buf2);
> +		kfree(bch->xi_tab);
> +		kfree(bch->syn);
> +		kfree(bch->cache);
> +		kfree(bch->elp);
> +
> +		for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
> +			kfree(bch->poly_2t[i]);
> +
> +		kfree(bch);
> +	}
> +}
> +
> +/**
> + * init_bch - initialize a BCH encoder/decoder
> + * @m:          Galois field order, should be in the range 5-15
> + * @t:          maximum error correction capability, in bits
> + * @prim_poly:  user-provided primitive polynomial (or 0 to use default)
> + *
> + * Returns:
> + *  a newly allocated BCH control structure if successful, NULL otherwise
> + *
> + * This initialization can take some time, as lookup tables are built for fast
> + * encoding/decoding; make sure not to call this function from a time critical
> + * path. Usually, init_bch() should be called on module/driver init and
> + * free_bch() should be called to release memory on exit.
> + *
> + * You may provide your own primitive polynomial of degree @m in argument
> + * @prim_poly, or let init_bch() use its default polynomial.
> + *
> + * Once init_bch() has successfully returned a pointer to a newly allocated
> + * BCH control structure, ecc length in bytes is given by member @ecc_bytes of
> + * the structure.
> + */
> +static struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
> +{
> +	int err = 0;
> +	unsigned int i, words;
> +	uint32_t *genpoly;
> +	struct bch_control *bch = NULL;
> +
> +	const int min_m = 5;
> +	const int max_m = 15;
> +
> +	/* default primitive polynomials */
> +	static const unsigned int prim_poly_tab[] = {
> +		0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
> +		0x402b, 0x8003,
> +	};
> +
> +#if defined(CONFIG_BCH_CONST_PARAMS)
> +	if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
> +		printk(KERN_ERR "bch encoder/decoder was configured to support "
> +		       "parameters m=%d, t=%d only!\n",
> +		       CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
> +		goto fail;
> +	}
> +#endif
> +	if ((m < min_m) || (m > max_m))
> +		/*
> +		 * values of m greater than 15 are not currently supported;
> +		 * supporting m > 15 would require changing table base type
> +		 * (uint16_t) and a small patch in matrix transposition
> +		 */
> +		goto fail;
> +
> +	/* sanity checks */
> +	if ((t < 1) || (m*t >= ((1 << m)-1)))
> +		/* invalid t value */
> +		goto fail;
> +
> +	/* select a primitive polynomial for generating GF(2^m) */
> +	if (prim_poly == 0)
> +		prim_poly = prim_poly_tab[m-min_m];
> +
> +	bch = malloc(sizeof(*bch));
> +	if (bch == NULL)
> +		goto fail;
> +
> +	memset(bch, 0, sizeof(*bch));
> +
> +	bch->m = m;
> +	bch->t = t;
> +	bch->n = (1 << m)-1;
> +	words  = DIV_ROUND_UP(m*t, 32);
> +	bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
> +	bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
> +	bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
> +	bch->mod8_tab  = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
> +	bch->ecc_buf   = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
> +	bch->ecc_buf2  = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
> +	bch->xi_tab    = bch_alloc(m*sizeof(*bch->xi_tab), &err);
> +	bch->syn       = bch_alloc(2*t*sizeof(*bch->syn), &err);
> +	bch->cache     = bch_alloc(2*t*sizeof(*bch->cache), &err);
> +	bch->elp       = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
> +
> +	for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
> +		bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
> +
> +	if (err)
> +		goto fail;
> +
> +	err = build_gf_tables(bch, prim_poly);
> +	if (err)
> +		goto fail;
> +
> +	/* use generator polynomial for computing encoding tables */
> +	genpoly = compute_generator_polynomial(bch);
> +	if (genpoly == NULL)
> +		goto fail;
> +
> +	build_mod8_tables(bch, genpoly);
> +	kfree(genpoly);
> +
> +	err = build_deg2_base(bch);
> +	if (err)
> +		goto fail;
> +
> +	return bch;
> +
> +fail:
> +	free_bch(bch);
> +	return NULL;
> +}
> +
> +static void swap_bits(uint8_t *buf, int len)
> +{
> +	int i, j;
> +
> +	for (j = 0; j < len; j++) {
> +		uint8_t byte = buf[j];
> +
> +		buf[j] = 0;
> +		for (i = 0; i < 8; i++) {
> +			if (byte & (1 << i))
> +				buf[j] |= (1 << (7 - i));
> +		}
> +	}
> +}
> +
> +static uint16_t lfsr_step(uint16_t state, int count)
> +{
> +	state &= 0x7fff;
> +	while (count--)
> +		state = ((state >> 1) |
> +			 ((((state >> 0) ^ (state >> 1)) & 1) << 14)) & 0x7fff;
> +
> +	return state;
> +}
> +
> +static uint16_t default_scrambler_seeds[] = {
> +	0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
> +	0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
> +	0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
> +	0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
> +	0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
> +	0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
> +	0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
> +	0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
> +	0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
> +	0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
> +	0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
> +	0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
> +	0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
> +	0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
> +	0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
> +	0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
> +};
> +
> +static uint16_t brom_scrambler_seeds[] = { 0x4a80 };
> +
> +static void scramble(const struct image_info *info,
> +		     int page, uint8_t *data, int datalen)
> +{
> +	uint16_t state;
> +	int i;
> +
> +	/* Boot0 is always scrambled no matter the command line option. */
> +	if (info->boot0) {
> +		state = brom_scrambler_seeds[0];
> +	} else {
> +		unsigned seedmod = info->eraseblock_size / info->page_size;
> +
> +		/* Bail out earlier if the user didn't ask for scrambling. */
> +		if (!info->scramble)
> +			return;
> +
> +		if (seedmod > ARRAY_SIZE(default_scrambler_seeds))
> +			seedmod = ARRAY_SIZE(default_scrambler_seeds);
> +
> +		state = default_scrambler_seeds[page % seedmod];
> +	}
> +
> +	/* Prepare the initial state... */
> +	state = lfsr_step(state, 15);
> +
> +	/* and start scrambling data. */
> +	for (i = 0; i < datalen; i++) {
> +		data[i] ^= state;
> +		state = lfsr_step(state, 8);
> +	}
> +}
> +
> +static int write_page(const struct image_info *info, uint8_t *buffer,
> +		      FILE *src, FILE *rnd, FILE *dst,
> +		      struct bch_control *bch, int page)
> +{
> +	int steps = info->usable_page_size / info->ecc_step_size;
> +	int eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
> +	off_t pos = ftell(dst);
> +	size_t pad, cnt;
> +	int i;
> +
> +	if (eccbytes % 2)
> +		eccbytes++;
> +
> +	memset(buffer, 0xff, info->page_size + info->oob_size);
> +	cnt = fread(buffer, 1, info->usable_page_size, src);
> +	if (!cnt) {
> +		if (!feof(src)) {
> +			fprintf(stderr,
> +				"Failed to read data from the source\n");
> +			return -1;
> +		} else {
> +			return 0;
> +		}
> +	}
> +
> +	fwrite(buffer, info->page_size + info->oob_size, 1, dst);
> +
> +	for (i = 0; i < info->usable_page_size; i++) {
> +		if (buffer[i] !=  0xff)
> +			break;
> +	}
> +
> +	/* We leave empty pages at 0xff. */
> +	if (i == info->usable_page_size)
> +		return 0;
> +
> +	/* Restore the source pointer to read it again. */
> +	fseek(src, -cnt, SEEK_CUR);
> +
> +	/* Randomize unused space if scrambling is required. */
> +	if (info->scramble) {
> +		int offs;
> +
> +		if (info->boot0) {
> +			offs = steps * (info->ecc_step_size + eccbytes + 4);
> +			cnt = info->page_size + info->oob_size - offs;
> +			fread(buffer + offs, 1, cnt, rnd);
> +		} else {
> +			offs = info->page_size + (steps * (eccbytes + 4));
> +			cnt = info->page_size + info->oob_size - offs;
> +			memset(buffer + offs, 0xff, cnt);
> +			scramble(info, page, buffer + offs, cnt);
> +		}
> +		fseek(dst, pos + offs, SEEK_SET);
> +		fwrite(buffer + offs, cnt, 1, dst);
> +	}
> +
> +	for (i = 0; i < steps; i++) {
> +		int ecc_offs, data_offs;
> +		uint8_t *ecc;
> +
> +		memset(buffer, 0xff, info->ecc_step_size + eccbytes + 4);
> +		ecc = buffer + info->ecc_step_size + 4;
> +		if (info->boot0) {
> +			data_offs = i * (info->ecc_step_size + eccbytes + 4);
> +			ecc_offs = data_offs + info->ecc_step_size + 4;
> +		} else {
> +			data_offs = i * info->ecc_step_size;
> +			ecc_offs = info->page_size + 4 + (i * (eccbytes + 4));
> +		}
> +
> +		cnt = fread(buffer, 1, info->ecc_step_size, src);
> +		if (!cnt && !feof(src)) {
> +			fprintf(stderr,
> +				"Failed to read data from the source\n");
> +			return -1;
> +		}
> +
> +		pad = info->ecc_step_size - cnt;
> +		if (pad) {
> +			if (info->scramble && info->boot0)
> +				fread(buffer + cnt, 1, pad, rnd);
> +			else
> +				memset(buffer + cnt, 0xff, pad);
> +		}
> +
> +		memset(ecc, 0, eccbytes);
> +		swap_bits(buffer, info->ecc_step_size + 4);
> +		encode_bch(bch, buffer, info->ecc_step_size + 4, ecc);
> +		swap_bits(buffer, info->ecc_step_size + 4);
> +		swap_bits(ecc, eccbytes);
> +		scramble(info, page, buffer, info->ecc_step_size + 4 + eccbytes);
> +
> +		fseek(dst, pos + data_offs, SEEK_SET);
> +		fwrite(buffer, info->ecc_step_size, 1, dst);
> +		fseek(dst, pos + ecc_offs - 4, SEEK_SET);
> +		fwrite(ecc - 4, eccbytes + 4, 1, dst);
> +	}
> +
> +	/* Fix BBM. */
> +	fseek(dst, pos + info->page_size, SEEK_SET);
> +	memset(buffer, 0xff, 2);
> +	fwrite(buffer, 2, 1, dst);
> +
> +	/* Make dst pointer point to the next page. */
> +	fseek(dst, pos + info->page_size + info->oob_size, SEEK_SET);
> +
> +	return 0;
> +}
> +
> +static int create_image(const struct image_info *info)
> +{
> +	off_t page = info->offset / info->page_size;
> +	struct bch_control *bch;
> +	FILE *src, *dst, *rnd;
> +	uint8_t *buffer;
> +
> +	bch = init_bch(14, info->ecc_strength, BCH_PRIMITIVE_POLY);
> +	if (!bch) {
> +		fprintf(stderr, "Failed to init the BCH engine\n");
> +		return -1;
> +	}
> +
> +	buffer = malloc(info->page_size + info->oob_size);
> +	if (!buffer) {
> +		fprintf(stderr, "Failed to allocate the NAND page buffer\n");
> +		return -1;
> +	}
> +
> +	memset(buffer, 0xff, info->page_size + info->oob_size);
> +
> +	src = fopen(info->source, "r");
> +	if (!src) {
> +		fprintf(stderr, "Failed to open source file (%s)\n",
> +			info->source);
> +		return -1;
> +	}
> +
> +	dst = fopen(info->dest, "w");
> +	if (!dst) {
> +		fprintf(stderr, "Failed to open dest file (%s)\n", info->dest);
> +		return -1;
> +	}
> +
> +	rnd = fopen("/dev/urandom", "r");
> +	if (!rnd) {
> +		fprintf(stderr, "Failed to open /dev/urandom\n");
> +		return -1;
> +	}
> +
> +	while (!feof(src)) {
> +		int ret;
> +
> +		ret = write_page(info, buffer, src, rnd, dst, bch, page++);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void display_help(int status)
> +{
> +	fprintf(status == EXIT_SUCCESS ? stdout : stderr,
> +		"sunxi-nand-image-builder %s\n"
> +		"\n"
> +		"Usage: sunxi-nand-image-builder [OPTIONS] source-image output-image\n"
> +		"\n"
> +		"Creates a raw NAND image that can be read by the sunxi NAND controller.\n"
> +		"\n"
> +		"-h               --help               Display this help and exit\n"
> +		"-c <str>/<step>  --ecc=<str>/<step>   ECC config (strength/step-size)\n"
> +		"-p <size>        --page=<size>        Page size\n"
> +		"-o <size>        --oob=<size>         OOB size\n"
> +		"-u <size>        --usable=<size>      Usable page size\n"
> +		"-e <size>        --eraseblock=<size>  Erase block size\n"
> +		"-b               --boot0              Build a boot0 image.\n"
> +		"-s               --scramble           Scramble data\n"
> +		"-a <offset>      --address=<offset>   Where the image will be programmed.\n"
> +		"\n"
> +		"Notes:\n"
> +		"All the information you need to pass to this tool should be part of\n"
> +		"the NAND datasheet.\n"
> +		"\n"
> +		"The NAND controller only supports the following ECC configs\n"
> +		"  Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n"
> +		"  Valid ECC step size: 512 and 1024\n"
> +		"\n"
> +		"If you are building a boot0 image, you'll have specify extra options.\n"
> +		"These options should be chosen based on the layouts described here:\n"
> +		"  http://linux-sunxi.org/NAND#More_information_on_BROM_NAND\n"
> +		"\n"
> +		"  --usable should be assigned the 'Hardware page' value\n"
> +		"  --ecc should be assigned the 'ECC capacity'/'ECC page' values\n"
> +		"  --usable should be smaller than --page\n"
> +		"\n"
> +		"The --address option is only required for non-boot0 images that are \n"
> +		"meant to be programmed at a non eraseblock aligned offset.\n"
> +		"\n"
> +		"Examples:\n"
> +		"  The H27UCG8T2BTR-BC NAND exposes\n"
> +		"  * 16k pages\n"
> +		"  * 1280 OOB bytes per page\n"
> +		"  * 4M eraseblocks\n"
> +		"  * requires data scrambling\n"
> +		"  * expects a minimum ECC of 40bits/1024bytes\n"
> +		"\n"
> +		"  A normal image can be generated with\n"
> +		"    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -c 40/1024\n"
> +		"  A boot0 image can be generated with\n"
> +		"    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -b -u 4096 -c 64/1024\n",
> +		PLAIN_VERSION);
> +	exit(status);
> +}
> +
> +static int check_image_info(struct image_info *info)
> +{
> +	static int valid_ecc_strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
> +	int eccbytes, eccsteps;
> +	unsigned i;
> +
> +	if (!info->page_size) {
> +		fprintf(stderr, "--page is missing\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!info->page_size) {
> +		fprintf(stderr, "--oob is missing\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!info->eraseblock_size) {
> +		fprintf(stderr, "--eraseblock is missing\n");
> +		return -EINVAL;
> +	}
> +
> +	if (info->ecc_step_size != 512 && info->ecc_step_size != 1024) {
> +		fprintf(stderr, "Invalid ECC step argument: %d\n",
> +			info->ecc_step_size);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(valid_ecc_strengths); i++) {
> +		if (valid_ecc_strengths[i] == info->ecc_strength)
> +			break;
> +	}
> +
> +	if (i == ARRAY_SIZE(valid_ecc_strengths)) {
> +		fprintf(stderr, "Invalid ECC strength argument: %d\n",
> +			info->ecc_strength);
> +		return -EINVAL;
> +	}
> +
> +	eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
> +	if (eccbytes % 2)
> +		eccbytes++;
> +	eccbytes += 4;
> +
> +	eccsteps = info->usable_page_size / info->ecc_step_size;
> +
> +	if (info->page_size + info->oob_size <
> +	    info->usable_page_size + (eccsteps * eccbytes)) {
> +		fprintf(stderr,
> +			"ECC bytes do not fit in the NAND page, choose a weaker ECC\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	struct image_info info;
> +
> +	memset(&info, 0, sizeof(info));
> +	/*
> +	 * Process user arguments
> +	 */
> +	for (;;) {
> +		int option_index = 0;
> +		char *endptr = NULL;
> +		static const struct option long_options[] = {
> +			{"help", no_argument, 0, 'h'},
> +			{"ecc", required_argument, 0, 'c'},
> +			{"page", required_argument, 0, 'p'},
> +			{"oob", required_argument, 0, 'o'},
> +			{"usable", required_argument, 0, 'u'},
> +			{"eraseblock", required_argument, 0, 'e'},
> +			{"boot0", no_argument, 0, 'b'},
> +			{"scramble", no_argument, 0, 's'},
> +			{"address", required_argument, 0, 'a'},
> +			{0, 0, 0, 0},
> +		};
> +
> +		int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sh",
> +				long_options, &option_index);
> +		if (c == EOF)
> +			break;
> +
> +		switch (c) {
> +		case 'h':
> +			display_help(0);
> +			break;
> +		case 's':
> +			info.scramble = 1;
> +			break;
> +		case 'c':
> +			info.ecc_strength = strtol(optarg, &endptr, 0);
> +			if (endptr || *endptr == '/')
> +				info.ecc_step_size = strtol(endptr + 1, NULL, 0);
> +			break;
> +		case 'p':
> +			info.page_size = strtol(optarg, NULL, 0);
> +			break;
> +		case 'o':
> +			info.oob_size = strtol(optarg, NULL, 0);
> +			break;
> +		case 'u':
> +			info.usable_page_size = strtol(optarg, NULL, 0);
> +			break;
> +		case 'e':
> +			info.eraseblock_size = strtol(optarg, NULL, 0);
> +			break;
> +		case 'b':
> +			info.boot0 = 1;
> +			break;
> +		case 'a':
> +			info.offset = strtoull(optarg, NULL, 0);
> +			break;
> +		case '?':
> +			display_help(-1);
> +			break;
> +		}
> +	}
> +
> +	if ((argc - optind) != 2)
> +		display_help(-1);
> +
> +	info.source = argv[optind];
> +	info.dest = argv[optind + 1];
> +
> +	if (!info.boot0) {
> +		info.usable_page_size = info.page_size;
> +	} else if (!info.usable_page_size) {
> +		if (info.page_size > 8192)
> +			info.usable_page_size = 8192;
> +		else if (info.page_size > 4096)
> +			info.usable_page_size = 4096;
> +		else
> +			info.usable_page_size = 1024;
> +	}
> +
> +	if (check_image_info(&info))
> +		display_help(-1);
> +
> +	return create_image(&info);
> +}
>

^ permalink raw reply

* [U-Boot] [PATCH 3/7] sunxi: Enable UBI and NAND support
From: Hans de Goede @ 2016-11-14 11:18 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <6c44b7aa93af6ffd76d4d0bee5713f087e082c62.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> From: Hans de Goede <hdegoede@redhat.com>
>
> Enable the NAND and UBI support in the configuration header so that we can
> (finally) use it.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/configs/sunxi-common.h | 26 ++++++++++++++++++++++----
>  1 file changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
> index 8363414828fa..1733767ba53b 100644
> --- a/include/configs/sunxi-common.h
> +++ b/include/configs/sunxi-common.h
> @@ -129,9 +129,23 @@
>  #define CONFIG_SERIAL_TAG
>
>  #ifdef CONFIG_NAND_SUNXI
> +#define CONFIG_SYS_NAND_U_BOOT_OFFS	(8 << 20) /* 8 MiB */

As Boris already said, please put this in Kconfig.

>  #define CONFIG_SYS_NAND_MAX_ECCPOS 1664
>  #define CONFIG_SYS_NAND_ONFI_DETECTION
>  #define CONFIG_SYS_MAX_NAND_DEVICE 8
> +
> +/* Requirements for UBI */
> +#define CONFIG_RBTREE
> +#define CONFIG_LZO
> +#define CONFIG_CMD_MTDPARTS
> +#define CONFIG_CMD_UBI
> +#define CONFIG_CMD_UBIFS
> +#define CONFIG_MTD_DEVICE
> +
> +#define CONFIG_MTD_PARTITIONS
> +
> +#define CONFIG_CMD_NAND
> +#define CONFIG_CMD_NAND_TRIMFFS
>  #endif
>
>  #ifdef CONFIG_SPL_SPI_SUNXI
> @@ -143,7 +157,14 @@
>  #define CONFIG_GENERIC_MMC
>  #define CONFIG_MMC_SUNXI
>  #define CONFIG_MMC_SUNXI_SLOT		0
> -#define CONFIG_ENV_IS_IN_MMC
> +#endif
> +
> +#if defined(CONFIG_ENV_IS_IN_NAND)
> +#define CONFIG_ENV_OFFSET			0xc00000
> +#define CONFIG_ENV_SIZE				0x400000
> +#elif defined(CONFIG_ENV_IS_IN_MMC)
> +#define CONFIG_ENV_OFFSET			(544 << 10) /* (8 + 24 + 512) KiB */
> +#define CONFIG_ENV_SIZE				(128 << 10) /* 128 KiB */
>  #define CONFIG_SYS_MMC_ENV_DEV		0	/* first detected MMC controller */
>  #endif
>

I would greatly prefer putting the env in an UBI partition,
I thought that we had agreed on doing that ?

Regards,

Hans



> @@ -175,9 +196,6 @@
>
>  #define CONFIG_SYS_MONITOR_LEN		(768 << 10)	/* 768 KiB */
>
> -#define CONFIG_ENV_OFFSET		(544 << 10) /* (8 + 24 + 512) KiB */
> -#define CONFIG_ENV_SIZE			(128 << 10)	/* 128 KiB */
> -
>  #define CONFIG_FAT_WRITE	/* enable write access */
>
>  #define CONFIG_SPL_FRAMEWORK
>

^ permalink raw reply

* Re: [PATCH v4 5/8] media: adv7180: implement g_parm
From: Hans Verkuil @ 2016-11-14 11:17 UTC (permalink / raw)
  To: Steve Longerbeam, lars
  Cc: mchehab, linux-media, linux-kernel, Steve Longerbeam
In-Reply-To: <1470247430-11168-6-git-send-email-steve_longerbeam@mentor.com>

On 08/03/2016 08:03 PM, Steve Longerbeam wrote:
> Implement g_parm to return the current standard's frame period.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> Tested-by: Tim Harvey <tharvey@gateworks.com>
> Acked-by: Tim Harvey <tharvey@gateworks.com>
> 
> ---
> v4: no changes
> v3: no changes
> v2: no changes
> ---
>  drivers/media/i2c/adv7180.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index b2df181..9705e24 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -764,6 +764,27 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> +static int adv7180_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
> +{
> +	struct adv7180_state *state = to_state(sd);
> +	struct v4l2_captureparm *cparm = &a->parm.capture;
> +
> +	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		return -EINVAL;
> +
> +	memset(a, 0, sizeof(*a));
> +	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

Don't memset this, it is the responsibility of the caller to do that,
not of the subdev.

The caller may have set other fields in the struct that the memset would
wipe out.

Regards,

	Hans

> +	if (state->curr_norm & V4L2_STD_525_60) {
> +		cparm->timeperframe.numerator = 1001;
> +		cparm->timeperframe.denominator = 30000;
> +	} else {
> +		cparm->timeperframe.numerator = 1;
> +		cparm->timeperframe.denominator = 25;
> +	}
> +
> +	return 0;
> +}
> +
>  static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap)
>  {
>  	struct adv7180_state *state = to_state(sd);
> @@ -822,6 +843,7 @@ static int adv7180_subscribe_event(struct v4l2_subdev *sd,
>  static const struct v4l2_subdev_video_ops adv7180_video_ops = {
>  	.s_std = adv7180_s_std,
>  	.g_std = adv7180_g_std,
> +	.g_parm = adv7180_g_parm,
>  	.querystd = adv7180_querystd,
>  	.g_input_status = adv7180_g_input_status,
>  	.s_routing = adv7180_s_routing,
> 

^ permalink raw reply

* ✓ Fi.CI.BAT: success for Add support for GuC-based SLPC (rev6)
From: Patchwork @ 2016-11-14 11:17 UTC (permalink / raw)
  To: tom.orourke; +Cc: intel-gfx
In-Reply-To: <1479119849-20187-1-git-send-email-sagar.a.kamble@intel.com>

== Series Details ==

Series: Add support for GuC-based SLPC (rev6)
URL   : https://patchwork.freedesktop.org/series/2691/
State : success

== Summary ==

Series 2691v6 Add support for GuC-based SLPC
https://patchwork.freedesktop.org/api/1.0/series/2691/revisions/6/mbox/


fi-bdw-5557u     total:244  pass:229  dwarn:0   dfail:0   fail:0   skip:15 
fi-bsw-n3050     total:244  pass:204  dwarn:0   dfail:0   fail:0   skip:40 
fi-bxt-t5700     total:244  pass:216  dwarn:0   dfail:0   fail:0   skip:28 
fi-byt-j1900     total:244  pass:216  dwarn:0   dfail:0   fail:0   skip:28 
fi-byt-n2820     total:244  pass:212  dwarn:0   dfail:0   fail:0   skip:32 
fi-hsw-4770      total:244  pass:224  dwarn:0   dfail:0   fail:0   skip:20 
fi-hsw-4770r     total:244  pass:224  dwarn:0   dfail:0   fail:0   skip:20 
fi-ilk-650       total:244  pass:191  dwarn:0   dfail:0   fail:0   skip:53 
fi-ivb-3520m     total:244  pass:222  dwarn:0   dfail:0   fail:0   skip:22 
fi-ivb-3770      total:244  pass:222  dwarn:0   dfail:0   fail:0   skip:22 
fi-kbl-7200u     total:244  pass:222  dwarn:0   dfail:0   fail:0   skip:22 
fi-skl-6260u     total:244  pass:230  dwarn:0   dfail:0   fail:0   skip:14 
fi-skl-6700hq    total:244  pass:223  dwarn:0   dfail:0   fail:0   skip:21 
fi-skl-6700k     total:244  pass:222  dwarn:1   dfail:0   fail:0   skip:21 
fi-skl-6770hq    total:244  pass:230  dwarn:0   dfail:0   fail:0   skip:14 
fi-snb-2520m     total:244  pass:212  dwarn:0   dfail:0   fail:0   skip:32 
fi-snb-2600      total:244  pass:211  dwarn:0   dfail:0   fail:0   skip:33 

020e291d72d4aaf3e0f8f5168a60ac05daa43a77 drm-intel-nightly: 2016y-11m-14d-08h-02m-22s UTC integration manifest
5194ffc drm/i915/slpc: Enable SLPC, where supported
270f8db drm/i915/slpc: Add Broxton SLPC support
f732e79 drm/i915/slpc: Add SKL SLPC Support
d80a179 drm/i915/slpc: Preserve min/max frequency softlimits on re-activation
d3628bc drm/i915/slpc: Only enable GTPERF task, Disable other tasks/parameters
8862c5c drm/i915/slpc: Add i915_slpc_info to debugfs
e63a297 drm/i915/slpc: Add enable/disable controls for slpc tasks
603dc73 drm/i915/slpc: Add support for min/max frequency control
9118228 drm/i915/slpc: Add parameter unset/set/get functions
52bf59d drm/i915/slpc: Send shutdown event
248b5e5 drm/i915/slpc: Send reset event and handle SLPC enabling
9b8a6e4 drm/i915/slpc: Add slpc communication interfaces
4358260 drm/i915/slpc: Update debugfs interfaces for frequency parameters
4754736a drm/i915/slpc: Allocate/Release/Initialize SLPC shared data
282dfc6 drm/i915/slpc: If using SLPC, do not set frequency
b88c0d5 drm/i915/slpc: Enable SLPC in GuC if supported
94c1edf drm/i915/slpc: Use intel_slpc_* functions if supported
a975349 drm/i915/slpc: Sanitize GuC version
3696cb6 drm/i915/slpc: Add enable_slpc module parameter
2c544bc drm/i915/slpc: Add has_slpc capability flag
61c000ea drm/i915/slpc: Expose GuC functions for use with SLPC
64cd6cb drm/i915/gen9: Separate RPS and RC6 handling

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_2979/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH v3 09/14] drm/i915: Store the execution priority on the context
From: Tvrtko Ursulin @ 2016-11-14 11:16 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
In-Reply-To: <20161114085703.16540-9-chris@chris-wilson.co.uk>


On 14/11/2016 08:56, Chris Wilson wrote:
> In order to support userspace defining different levels of importance to
> different contexts, and in particular the preferred order of execution,
> store a priority value on each context. By default, the kernel's
> context, which is used for idling and other background tasks, is given
> minimum priority (all user contexts will execute first).
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         | 1 +
>  drivers/gpu/drm/i915/i915_gem_context.c | 1 +
>  drivers/gpu/drm/i915/i915_gem_request.c | 2 +-
>  3 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index ab4ad5522cf5..fb3e850f5d3a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -936,6 +936,7 @@ struct i915_gem_context {
>  	/* Unique identifier for this context, used by the hw for tracking */
>  	unsigned int hw_id;
>  	u32 user_handle;
> +	int priority; /* greater priorities are serviced first */
>
>  	u32 ggtt_alignment;
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 6dd475735f0a..1f94b8d6d83d 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -476,6 +476,7 @@ int i915_gem_context_init(struct drm_device *dev)
>  		return PTR_ERR(ctx);
>  	}
>
> +	ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
>  	dev_priv->kernel_context = ctx;
>
>  	DRM_DEBUG_DRIVER("%s context support initialized\n",
> diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
> index 13574a1e29b1..b9b5253cf3cd 100644
> --- a/drivers/gpu/drm/i915/i915_gem_request.c
> +++ b/drivers/gpu/drm/i915/i915_gem_request.c
> @@ -867,7 +867,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
>  	 * run at the earliest possible convenience.
>  	 */
>  	if (engine->schedule)
> -		engine->schedule(request, 0);
> +		engine->schedule(request, request->ctx->priority);
>
>  	local_bh_disable();
>  	i915_sw_fence_commit(&request->submit);
>

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH 2/3] drm/bridge: Add ti-ftp410 HDMI transmitter driver
From: Tomi Valkeinen @ 2016-11-14 11:16 UTC (permalink / raw)
  To: Laurent Pinchart, Jyri Sarha
  Cc: devicetree, bcousson, khilman, dri-devel, bgolaszewski
In-Reply-To: <1740464.TP0bE1PYbC@avalon>


[-- Attachment #1.1.1: Type: text/plain, Size: 1481 bytes --]

On 14/11/16 13:10, Laurent Pinchart wrote:
> Hi Jyri,
> 
> On Monday 14 Nov 2016 10:49:43 Jyri Sarha wrote:
>> On 11/03/16 19:46, Laurent Pinchart wrote:
>>>> +Required properties:
>>>>> +	- compatible: "ti,tfp410"
>>>
>>> The device is an I2C slave, it should have a reg property. Given that the
>>> chip can be used without being controlled through I2C, the reg property
>>> should be optional. You should document this clearly, and explain how the
>>> DT node can be instantiated as a child of an I2C controller when the I2C
>>> interface is used, or in other parts of the device tree otherwise.
>>
>> Shouldn't I have two different compatible strings if want to make both
>> platform driver probe and i2c client probe to work?
> 
> I don't think so, it's still the same chip.
> 
>> Or can it be done with single compatible string? Would you know of an
>> example of such a driver?
> 
> You will need to register both a i2c_driver and a platform_driver in the 
> tfp410 driver. Both will advertise the same compatible string. As you'll have 
> two probe functions, it should be easy to handle the differences between the 

If you have the same compatible string, won't both probes trigger? If
so, how does, e.g., the platform driver know this is actually i2c case,
and bail out? And if both probes don't trigger, why not? How does the
device probing machinery know that this DT node is actually an i2c node,
not a platform device node?

 Tomi


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH v4 3/3] PCI: qcom: add runtime pm support to pcie_port
From: Srinivas Kandagatla @ 2016-11-14 11:15 UTC (permalink / raw)
  To: svarbanov, linux-pci, bhelgaas
  Cc: robh+dt, linux-arm-msm, srinivas.kandagatla, devicetree
In-Reply-To: <1479122155-13393-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch is required when the pcie controller sits on a bus with
its own power domain and clocks which are controlled via a bus driver
like simple pm bus. As these bus driver have runtime pm enabled, it makes
sense to update the usage counter so that the runtime pm does not suspend
the clks or power domain associated with the bus driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/pci/host/pcie-qcom.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
index 03ba6b1..c2ca848 100644
--- a/drivers/pci/host/pcie-qcom.c
+++ b/drivers/pci/host/pcie-qcom.c
@@ -587,6 +587,8 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
 	int ret;
 
+	pm_runtime_get_sync(pp->dev);
+
 	qcom_ep_reset_assert(pcie);
 
 	ret = pcie->ops->init(pcie);
@@ -617,6 +619,7 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	phy_power_off(pcie->phy);
 err_deinit:
 	pcie->ops->deinit(pcie);
+	pm_runtime_put_sync(pp->dev);
 }
 
 static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
@@ -673,6 +676,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
 	if (!pcie)
 		return -ENOMEM;
 
+	pm_runtime_enable(dev);
 	pp = &pcie->pp;
 	pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
 
-- 
2.10.1


^ permalink raw reply related

* [PATCH v4 2/3] PCI: qcom: add support to msm8996 PCIE controller
From: Srinivas Kandagatla @ 2016-11-14 11:15 UTC (permalink / raw)
  To: svarbanov, linux-pci, bhelgaas
  Cc: robh+dt, linux-arm-msm, srinivas.kandagatla, devicetree
In-Reply-To: <1479122155-13393-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
legacy interrupts and it conforms to PCI Express Base 2.1 specification.

This patch adds post_init callback to qcom_pcie_ops, as this is pcie
pipe clocks are only setup after the phy is powered on.
It also adds ltssm_enable callback as it is very much different to other
supported SOCs in the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 .../devicetree/bindings/pci/qcom,pcie.txt          |  67 +++++++-
 drivers/pci/host/pcie-qcom.c                       | 177 ++++++++++++++++++++-
 2 files changed, 238 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
index 4059a6f..141d8c3 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
@@ -7,6 +7,7 @@
 			- "qcom,pcie-ipq8064" for ipq8064
 			- "qcom,pcie-apq8064" for apq8064
 			- "qcom,pcie-apq8084" for apq8084
+			- "qcom,pcie-msm8996" for msm8996 or apq8096
 
 - reg:
 	Usage: required
@@ -92,6 +93,17 @@
 			- "aux"		Auxiliary (AUX) clock
 			- "bus_master"	Master AXI clock
 			- "bus_slave"	Slave AXI clock
+
+- clock-names:
+	Usage: required for msm8996/apq8096
+	Value type: <stringlist>
+	Definition: Should contain the following entries
+			- "pipe"	Pipe Clock driving internal logic.
+			- "aux"		Auxiliary (AUX) clock.
+			- "cfg"		Configuration clk.
+			- "bus_master"	Master AXI clock.
+			- "bus_slave"	Slave AXI clock.
+
 - resets:
 	Usage: required
 	Value type: <prop-encoded-array>
@@ -115,7 +127,7 @@
 			- "core" Core reset
 
 - power-domains:
-	Usage: required for apq8084
+	Usage: required for apq8084 and msm8996/apq8096
 	Value type: <prop-encoded-array>
 	Definition: A phandle and power domain specifier pair to the
 		    power domain which is responsible for collapsing
@@ -231,3 +243,56 @@
 		pinctrl-0 = <&pcie0_pins_default>;
 		pinctrl-names = "default";
 	};
+
+* Example for apq8096:
+
+	pcie@608000{
+		compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
+		power-domains = <&gcc PCIE1_GDSC>;
+		bus-range = <0x00 0xff>;
+		num-lanes = <1>;
+
+		reg = <0x00608000 0x2000>,
+		      <0x0d000000 0xf1d>,
+		      <0x0d000f20 0xa8>,
+		      <0x0d100000 0x100000>;
+
+		reg-names = "parf", "dbi", "elbi", "config";
+
+		phys = <&pcie_phy 1>;
+		phy-names = "pciephy";
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges = <0x01000000 0x0 0x0d200000 0x0d200000 0x0 0x100000>,
+			<0x02000000 0x0 0x0d300000 0x0d300000 0x0 0xd00000>;
+
+		interrupts = <GIC_SPI 413 IRQ_TYPE_NONE>;
+		interrupt-names = "msi";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &intc 0 272 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+				<0 0 0 2 &intc 0 273 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+				<0 0 0 3 &intc 0 274 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+				<0 0 0 4 &intc 0 275 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&pcie1_clkreq_default &pcie1_perst_default &pcie1_wake_default>;
+		pinctrl-1 = <&pcie1_clkreq_sleep &pcie1_perst_default &pcie1_wake_sleep>;
+
+		vdda-1p8-supply = <&pm8994_l12>;
+		vdda-supply = <&pm8994_l28>;
+		linux,pci-domain = <1>;
+
+		clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
+			<&gcc GCC_PCIE_1_AUX_CLK>,
+			<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+			<&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
+			<&gcc GCC_PCIE_1_SLV_AXI_CLK>;
+
+		clock-names =  "pipe",
+				"aux",
+				"cfg",
+				"bus_master",
+				"bus_slave";
+	};
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
index 3593640..03ba6b1 100644
--- a/drivers/pci/host/pcie-qcom.c
+++ b/drivers/pci/host/pcie-qcom.c
@@ -36,11 +36,19 @@
 
 #include "pcie-designware.h"
 
+#define PCIE20_PARF_DBI_BASE_ADDR	0x168
+
+#define PCIE20_PARF_SYS_CTRL			0x00
 #define PCIE20_PARF_PHY_CTRL			0x40
 #define PCIE20_PARF_PHY_REFCLK			0x4C
 #define PCIE20_PARF_DBI_BASE_ADDR		0x168
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16c
+#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174
 #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
+#define MSM8996_PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT   0x1A8
+#define PCIE20_PARF_LTSSM			0x1B0
+#define PCIE20_PARF_SID_OFFSET			0x234
+#define PCIE20_PARF_BDF_TRANSLATE_CFG		0x24C
 
 #define PCIE20_ELBI_SYS_CTRL			0x04
 #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE		BIT(0)
@@ -72,9 +80,18 @@ struct qcom_pcie_resources_v1 {
 	struct regulator *vdda;
 };
 
+struct qcom_pcie_resources_v2 {
+	struct clk *aux_clk;
+	struct clk *master_clk;
+	struct clk *slave_clk;
+	struct clk *cfg_clk;
+	struct clk *pipe_clk;
+};
+
 union qcom_pcie_resources {
 	struct qcom_pcie_resources_v0 v0;
 	struct qcom_pcie_resources_v1 v1;
+	struct qcom_pcie_resources_v2 v2;
 };
 
 struct qcom_pcie;
@@ -82,7 +99,9 @@ struct qcom_pcie;
 struct qcom_pcie_ops {
 	int (*get_resources)(struct qcom_pcie *pcie);
 	int (*init)(struct qcom_pcie *pcie);
+	int (*post_init)(struct qcom_pcie *pcie);
 	void (*deinit)(struct qcom_pcie *pcie);
+	void (*ltssm_enable)(struct qcom_pcie *pcie);
 };
 
 struct qcom_pcie {
@@ -116,17 +135,33 @@ static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
 	return dw_handle_msi_irq(pp);
 }
 
-static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
+static void qcom_pcie_v0_v1_ltssm_enable(struct qcom_pcie *pcie)
 {
 	u32 val;
-
-	if (dw_pcie_link_up(&pcie->pp))
-		return 0;
-
 	/* enable link training */
 	val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
 	val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
 	writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
+}
+
+static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
+{
+	u32 val;
+	/* enable link training */
+	val = readl(pcie->parf + PCIE20_PARF_LTSSM);
+	val |= BIT(8);
+	writel(val, pcie->parf + PCIE20_PARF_LTSSM);
+}
+
+static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
+{
+
+	if (dw_pcie_link_up(&pcie->pp))
+		return 0;
+
+	/* Enable Link Training state machine */
+	if (pcie->ops->ltssm_enable)
+		pcie->ops->ltssm_enable(pcie);
 
 	return dw_pcie_wait_for_link(&pcie->pp);
 }
@@ -421,6 +456,113 @@ static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
 	return ret;
 }
 
+static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+
+	res->aux_clk = devm_clk_get(dev, "aux");
+	if (IS_ERR(res->aux_clk))
+		return PTR_ERR(res->aux_clk);
+
+	res->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(res->cfg_clk))
+		return PTR_ERR(res->cfg_clk);
+
+	res->master_clk = devm_clk_get(dev, "bus_master");
+	if (IS_ERR(res->master_clk))
+		return PTR_ERR(res->master_clk);
+
+	res->slave_clk = devm_clk_get(dev, "bus_slave");
+	if (IS_ERR(res->slave_clk))
+		return PTR_ERR(res->slave_clk);
+
+	res->pipe_clk = devm_clk_get(dev, "pipe");
+	if (IS_ERR(res->pipe_clk))
+		return PTR_ERR(res->pipe_clk);
+
+	return 0;
+}
+
+static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+	u32 val;
+	int ret;
+
+	ret = clk_prepare_enable(res->aux_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable aux clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(res->cfg_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable cfg clock\n");
+		goto err_cfg_clk;
+	}
+
+	ret = clk_prepare_enable(res->master_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable master clock\n");
+		goto err_master_clk;
+	}
+
+	ret = clk_prepare_enable(res->slave_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable slave clock\n");
+		goto err_slave_clk;
+	}
+
+	/* enable PCIe clocks and resets */
+	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
+	val &= ~BIT(0);
+	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
+
+	/* change DBI base address */
+	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
+
+	/* MAC PHY_POWERDOWN MUX DISABLE  */
+	val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
+	val &= ~BIT(29);
+	writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
+
+	val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+	val |= BIT(4);
+	writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+
+	val = readl(pcie->parf + MSM8996_PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
+	val |= BIT(31);
+	writel(val, pcie->parf + MSM8996_PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
+
+	return 0;
+
+err_slave_clk:
+	clk_disable_unprepare(res->master_clk);
+err_master_clk:
+	clk_disable_unprepare(res->cfg_clk);
+err_cfg_clk:
+	clk_disable_unprepare(res->aux_clk);
+
+	return ret;
+}
+
+static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+	int ret;
+
+	ret = clk_prepare_enable(res->pipe_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable pipe clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int qcom_pcie_link_up(struct pcie_port *pp)
 {
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
@@ -429,6 +571,17 @@ static int qcom_pcie_link_up(struct pcie_port *pp)
 	return !!(val & PCI_EXP_LNKSTA_DLLLA);
 }
 
+static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+
+	clk_disable_unprepare(res->pipe_clk);
+	clk_disable_unprepare(res->slave_clk);
+	clk_disable_unprepare(res->master_clk);
+	clk_disable_unprepare(res->cfg_clk);
+	clk_disable_unprepare(res->aux_clk);
+}
+
 static void qcom_pcie_host_init(struct pcie_port *pp)
 {
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
@@ -444,6 +597,9 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	if (ret)
 		goto err_deinit;
 
+	if (pcie->ops->post_init)
+		pcie->ops->post_init(pcie);
+
 	dw_pcie_setup_rc(pp);
 
 	if (IS_ENABLED(CONFIG_PCI_MSI))
@@ -487,12 +643,22 @@ static const struct qcom_pcie_ops ops_v0 = {
 	.get_resources = qcom_pcie_get_resources_v0,
 	.init = qcom_pcie_init_v0,
 	.deinit = qcom_pcie_deinit_v0,
+	.ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
 };
 
 static const struct qcom_pcie_ops ops_v1 = {
 	.get_resources = qcom_pcie_get_resources_v1,
 	.init = qcom_pcie_init_v1,
 	.deinit = qcom_pcie_deinit_v1,
+	.ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
+};
+
+static const struct qcom_pcie_ops ops_v2 = {
+	.get_resources = qcom_pcie_get_resources_v2,
+	.init = qcom_pcie_init_v2,
+	.post_init = qcom_pcie_post_init_v2,
+	.deinit = qcom_pcie_deinit_v2,
+	.ltssm_enable = qcom_pcie_v2_ltssm_enable,
 };
 
 static int qcom_pcie_probe(struct platform_device *pdev)
@@ -572,6 +738,7 @@ static const struct of_device_id qcom_pcie_match[] = {
 	{ .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
 	{ .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
 	{ .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
+	{ .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
 	{ }
 };
 
-- 
2.10.1

^ permalink raw reply related

* [PATCH v4 0/3] PCI: qcom: Add support to msm8996 pcie controller.
From: Srinivas Kandagatla @ 2016-11-14 11:15 UTC (permalink / raw)
  To: svarbanov, linux-pci, bhelgaas
  Cc: robh+dt, linux-arm-msm, srinivas.kandagatla, devicetree

This patchset adds support to msm8996 pcie controller. I tested this patch on
v4.9-rc2 along with phy driver patch [1] and
"PCI: designware: check for iATU unroll support after initializing host"
fix [2] on DB820c APQ8096 board on port B and port C using sata and
ethernet controller.

Changes since v3:
	- remove unnesessary variable initialization spotted by vivek.
	- moved pipe clk disable before other clocks suggested by vivek.
	- fixed dt example suggested by Rob.
Changes since v2:
	- Removed regulators that belong to phy, spotted by Stephen
	- Removed clocks in to simple pm bus driver, spotted by Stephen
	- renamed msm8996 ops to v2 ops as suggested by Stephen.
	- cleanups as suggested by Stephen.
	- Add runtime pm support to driver.
	- Added pm clk support to simple pm bus driver.

Changes since v1:
	- Fixed dt example as suggested by Rob
	- added smmu bus clk dependency as smmu sits in between
	  system NOC and PCIe.
	- Removed smmu configuration from bindings and driver as
	  the smmu Level2 translation on this SOC is controlled by
	  the secure world, and level 1 translation is disabled,
	  so there is one-to-one mapping of the address space.

Thanks,
srini

[1] https://patchwork.kernel.org/patch/9384711/
[2] https://patchwork.kernel.org/patch/9377557/


Srinivas Kandagatla (3):
  bus: simple-pm: add support to pm clocks
  PCI: qcom: add support to msm8996 PCIE controller
  PCI: qcom: add runtime pm support to pcie_port

 .../devicetree/bindings/pci/qcom,pcie.txt          |  67 +++++++-
 drivers/bus/simple-pm-bus.c                        |  13 +-
 drivers/pci/host/pcie-qcom.c                       | 181 ++++++++++++++++++++-
 3 files changed, 254 insertions(+), 7 deletions(-)

-- 
2.10.1

^ permalink raw reply

* Re: [PATCH v3 08/14] drm/i915/scheduler: Execute requests in order of priorities
From: Tvrtko Ursulin @ 2016-11-14 11:15 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
In-Reply-To: <20161114085703.16540-8-chris@chris-wilson.co.uk>


On 14/11/2016 08:56, Chris Wilson wrote:
> Track the priority of each request and use it to determine the order in
> which we submit requests to the hardware via execlists.
>
> The priority of the request is determined by the user (eventually via
> the context) but may be overridden at any time by the driver. When we set
> the priority of the request, we bump the priority of all of its
> dependencies to match - so that a high priority drawing operation is not
> stuck behind a background task.
>
> When the request is ready to execute (i.e. we have signaled the submit
> fence following completion of all its dependencies, including third
> party fences), we put the request into a priority sorted rbtree to be
> submitted to the hardware. If the request is higher priority than all
> pending requests, it will be submitted on the next context-switch
> interrupt as soon as the hardware has completed the current request. We
> do not currently preempt any current execution to immediately run a very
> high priority request, at least not yet.
>
> One more limitation, is that this is first implementation is for
> execlists only so currently limited to gen8/gen9.
>
> v2: Replace recursive priority inheritance bumping with an iterative
> depth-first search list.
> v3: list_next_entry() for walking lists
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c        |   7 +-
>  drivers/gpu/drm/i915/i915_gem.c            |   3 +-
>  drivers/gpu/drm/i915/i915_gem_request.c    |   5 ++
>  drivers/gpu/drm/i915/i915_gem_request.h    |   8 +-
>  drivers/gpu/drm/i915/i915_guc_submission.c |   1 +
>  drivers/gpu/drm/i915/intel_engine_cs.c     |   3 +-
>  drivers/gpu/drm/i915/intel_lrc.c           | 135 +++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_ringbuffer.h    |   3 +-
>  8 files changed, 149 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 03e3c2afbb06..1cc971cb6cb1 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -631,8 +631,9 @@ static void print_request(struct seq_file *m,
>  			  struct drm_i915_gem_request *rq,
>  			  const char *prefix)
>  {
> -	seq_printf(m, "%s%x [%x:%x] @ %d: %s\n", prefix,
> +	seq_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
>  		   rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
> +		   rq->priotree.priority,
>  		   jiffies_to_msecs(jiffies - rq->emitted_jiffies),
>  		   rq->timeline->common->name);
>  }
> @@ -3216,6 +3217,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
>
>  		if (i915.enable_execlists) {
>  			u32 ptr, read, write;
> +			struct rb_node *rb;
>
>  			seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
>  				   I915_READ(RING_EXECLIST_STATUS_LO(engine)),
> @@ -3255,7 +3257,8 @@ static int i915_engine_info(struct seq_file *m, void *unused)
>  			rcu_read_unlock();
>
>  			spin_lock_irq(&engine->timeline->lock);
> -			list_for_each_entry(rq, &engine->execlist_queue, execlist_link) {
> +			for (rb = engine->execlist_first; rb; rb = rb_next(rb)) {
> +				rq = rb_entry(rb, typeof(*rq), priotree.node);
>  				print_request(m, rq, "\t\tQ ");
>  			}
>  			spin_unlock_irq(&engine->timeline->lock);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index b331e5966fe2..a9d27f3e88d2 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2722,10 +2722,11 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
>
>  		spin_lock_irqsave(&engine->timeline->lock, flags);
>
> -		INIT_LIST_HEAD(&engine->execlist_queue);
>  		i915_gem_request_put(engine->execlist_port[0].request);
>  		i915_gem_request_put(engine->execlist_port[1].request);
>  		memset(engine->execlist_port, 0, sizeof(engine->execlist_port));
> +		engine->execlist_queue = RB_ROOT;
> +		engine->execlist_first = NULL;
>
>  		spin_unlock_irqrestore(&engine->timeline->lock, flags);
>  	}
> diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
> index 78c87d94d205..13574a1e29b1 100644
> --- a/drivers/gpu/drm/i915/i915_gem_request.c
> +++ b/drivers/gpu/drm/i915/i915_gem_request.c
> @@ -132,6 +132,7 @@ __i915_priotree_add_dependency(struct i915_priotree *pt,
>  			       struct i915_dependency *dep,
>  			       unsigned long flags)
>  {
> +	INIT_LIST_HEAD(&dep->dfs_link);
>  	list_add(&dep->wait_link, &signal->waiters_list);
>  	list_add(&dep->signal_link, &pt->signalers_list);
>  	dep->signaler = signal;
> @@ -158,6 +159,8 @@ i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt)
>  {
>  	struct i915_dependency *dep, *next;
>
> +	GEM_BUG_ON(!RB_EMPTY_NODE(&pt->node));
> +
>  	/* Everyone we depended upon (the fences we wait to be signaled)
>  	 * should retire before us and remove themselves from our list.
>  	 * However, retirement is run independently on each timeline and
> @@ -182,6 +185,8 @@ i915_priotree_init(struct i915_priotree *pt)
>  {
>  	INIT_LIST_HEAD(&pt->signalers_list);
>  	INIT_LIST_HEAD(&pt->waiters_list);
> +	RB_CLEAR_NODE(&pt->node);
> +	pt->priority = INT_MIN;
>  }
>
>  void i915_gem_retire_noop(struct i915_gem_active *active,
> diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
> index 943c39d2a62a..e2b077df2da0 100644
> --- a/drivers/gpu/drm/i915/i915_gem_request.h
> +++ b/drivers/gpu/drm/i915/i915_gem_request.h
> @@ -48,6 +48,7 @@ struct i915_dependency {
>  	struct i915_priotree *signaler;
>  	struct list_head signal_link;
>  	struct list_head wait_link;
> +	struct list_head dfs_link;
>  	unsigned long flags;
>  #define I915_DEPENDENCY_ALLOC BIT(0)
>  };
> @@ -64,6 +65,10 @@ struct i915_dependency {
>  struct i915_priotree {
>  	struct list_head signalers_list; /* those before us, we depend upon */
>  	struct list_head waiters_list; /* those after us, they depend upon us */
> +	struct rb_node node;
> +	int priority;
> +#define I915_PRIORITY_MAX 1024
> +#define I915_PRIORITY_MIN (-I915_PRIORITY_MAX)
>  };
>
>  /**
> @@ -194,9 +199,6 @@ struct drm_i915_gem_request {
>  	struct drm_i915_file_private *file_priv;
>  	/** file_priv list entry for this request */
>  	struct list_head client_list;
> -
> -	/** Link in the execlist submission queue, guarded by execlist_lock. */
> -	struct list_head execlist_link;
>  };
>
>  extern const struct dma_fence_ops i915_fence_ops;
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index 942f5000d372..4462112725ef 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -1532,6 +1532,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
>  	/* Take over from manual control of ELSP (execlists) */
>  	for_each_engine(engine, dev_priv, id) {
>  		engine->submit_request = i915_guc_submit;
> +		engine->schedule = NULL;
>
>  		/* Replay the current set of previously submitted requests */
>  		list_for_each_entry(request,
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index c9171a058478..3da4d466e332 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -239,7 +239,8 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine)
>   */
>  void intel_engine_setup_common(struct intel_engine_cs *engine)
>  {
> -	INIT_LIST_HEAD(&engine->execlist_queue);
> +	engine->execlist_queue = RB_ROOT;
> +	engine->execlist_first = NULL;
>
>  	intel_engine_init_timeline(engine);
>  	intel_engine_init_hangcheck(engine);
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index d1aea7462515..d13a335ad83a 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -432,9 +432,10 @@ static bool can_merge_ctx(const struct i915_gem_context *prev,
>
>  static void execlists_dequeue(struct intel_engine_cs *engine)
>  {
> -	struct drm_i915_gem_request *cursor, *last;
> +	struct drm_i915_gem_request *last;
>  	struct execlist_port *port = engine->execlist_port;
>  	unsigned long flags;
> +	struct rb_node *rb;
>  	bool submit = false;
>
>  	last = port->request;
> @@ -471,7 +472,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
>  	 */
>
>  	spin_lock_irqsave(&engine->timeline->lock, flags);
> -	list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) {
> +	rb = engine->execlist_first;
> +	while (rb) {
> +		struct drm_i915_gem_request *cursor =
> +			rb_entry(rb, typeof(*cursor), priotree.node);
> +
>  		/* Can we combine this request with the current port? It has to
>  		 * be the same context/ringbuffer and not have any exceptions
>  		 * (e.g. GVT saying never to combine contexts).
> @@ -503,6 +508,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
>  			port++;
>  		}
>
> +		rb = rb_next(rb);
> +		rb_erase(&cursor->priotree.node, &engine->execlist_queue);
> +		RB_CLEAR_NODE(&cursor->priotree.node);
> +		cursor->priotree.priority = INT_MAX;
> +
>  		/* We keep the previous context alive until we retire the
>  		 * following request. This ensures that any the context object
>  		 * is still pinned for any residual writes the HW makes into it
> @@ -517,11 +527,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
>  		submit = true;
>  	}
>  	if (submit) {
> -		/* Decouple all the requests submitted from the queue */
> -		engine->execlist_queue.next = &cursor->execlist_link;
> -		cursor->execlist_link.prev = &engine->execlist_queue;
> -
>  		i915_gem_request_assign(&port->request, last);
> +		engine->execlist_first = rb;
>  	}
>  	spin_unlock_irqrestore(&engine->timeline->lock, flags);
>
> @@ -626,6 +633,32 @@ static void intel_lrc_irq_handler(unsigned long data)
>  	intel_uncore_forcewake_put(dev_priv, engine->fw_domains);
>  }
>
> +static bool insert_request(struct i915_priotree *pt, struct rb_root *root)
> +{
> +	struct rb_node **p, *rb;
> +	bool first = true;
> +
> +	/* most positive priority is scheduled first, equal priorities fifo */
> +	rb = NULL;
> +	p = &root->rb_node;
> +	while (*p) {
> +		struct i915_priotree *pos;
> +
> +		rb = *p;
> +		pos = rb_entry(rb, typeof(*pos), node);
> +		if (pt->priority > pos->priority) {
> +			p = &rb->rb_left;
> +		} else {
> +			p = &rb->rb_right;
> +			first = false;
> +		}
> +	}
> +	rb_link_node(&pt->node, rb, p);
> +	rb_insert_color(&pt->node, root);
> +
> +	return first;
> +}
> +
>  static void execlists_submit_request(struct drm_i915_gem_request *request)
>  {
>  	struct intel_engine_cs *engine = request->engine;
> @@ -634,13 +667,96 @@ static void execlists_submit_request(struct drm_i915_gem_request *request)
>  	/* Will be called from irq-context when using foreign fences. */
>  	spin_lock_irqsave(&engine->timeline->lock, flags);
>
> -	list_add_tail(&request->execlist_link, &engine->execlist_queue);
> +	if (insert_request(&request->priotree, &engine->execlist_queue))
> +		engine->execlist_first = &request->priotree.node;
>  	if (execlists_elsp_idle(engine))
>  		tasklet_hi_schedule(&engine->irq_tasklet);
>
>  	spin_unlock_irqrestore(&engine->timeline->lock, flags);
>  }
>
> +static struct intel_engine_cs *
> +pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)
> +{
> +	struct intel_engine_cs *engine;
> +
> +	engine = container_of(pt,
> +			      struct drm_i915_gem_request,
> +			      priotree)->engine;
> +	if (engine != locked) {
> +		if (locked)
> +			spin_unlock_irq(&locked->timeline->lock);
> +		spin_lock_irq(&engine->timeline->lock);
> +	}
> +
> +	return engine;
> +}
> +
> +static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
> +{
> +	struct intel_engine_cs *engine = NULL;
> +	struct i915_dependency *dep, *p;
> +	struct i915_dependency stack;
> +	LIST_HEAD(dfs);
> +
> +	if (prio <= READ_ONCE(request->priotree.priority))
> +		return;
> +
> +	/* Need BKL in order to use the temporary link inside i915_dependency */
> +	lockdep_assert_held(&request->i915->drm.struct_mutex);
> +
> +	stack.signaler = &request->priotree;
> +	list_add(&stack.dfs_link, &dfs);
> +
> +	/* Recursively bump all dependent priorities to match the new request */

Missed last time round that the comment needs updating.

> +	list_for_each_entry_safe(dep, p, &dfs, dfs_link) {
> +		struct i915_priotree *pt = dep->signaler;
> +
> +		list_for_each_entry(p, &pt->signalers_list, signal_link)
> +			if (prio > READ_ONCE(p->signaler->priority))
> +				list_move_tail(&p->dfs_link, &dfs);
> +
> +		p = list_next_entry(dep, dfs_link);
> +		if (!RB_EMPTY_NODE(&pt->node))
> +			continue;
> +
> +		engine = pt_lock_engine(pt, engine);
> +
> +		/* If it is not already in the rbtree, we can update the
> +		 * priority inplace and skip over it (and its dependencies)
> +		 * if it is referenced *again* as we descend the dfs.
> +		 */
> +		if (prio > pt->priority && RB_EMPTY_NODE(&pt->node)) {
> +			pt->priority = prio;
> +			list_del_init(&dep->dfs_link);
> +		}
> +	}
> +
> +	/* Fifo and depth-first replacement ensure our deps execute before us */
> +	list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
> +		struct i915_priotree *pt = dep->signaler;
> +
> +		INIT_LIST_HEAD(&dep->dfs_link);
> +
> +		engine = pt_lock_engine(pt, engine);
> +
> +		if (prio <= pt->priority)
> +			continue;
> +
> +		GEM_BUG_ON(RB_EMPTY_NODE(&pt->node));
> +
> +		pt->priority = prio;
> +		rb_erase(&pt->node, &engine->execlist_queue);
> +		if (insert_request(pt, &engine->execlist_queue))
> +			engine->execlist_first = &pt->node;
> +	}
> +
> +	if (engine)
> +		spin_unlock_irq(&engine->timeline->lock);
> +
> +	/* XXX Do we need to preempt to make room for us and our deps? */
> +}
> +
>  int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
>  {
>  	struct intel_engine_cs *engine = request->engine;
> @@ -1677,8 +1793,10 @@ void intel_execlists_enable_submission(struct drm_i915_private *dev_priv)
>  	struct intel_engine_cs *engine;
>  	enum intel_engine_id id;
>
> -	for_each_engine(engine, dev_priv, id)
> +	for_each_engine(engine, dev_priv, id) {
>  		engine->submit_request = execlists_submit_request;
> +		engine->schedule = execlists_schedule;
> +	}
>  }
>
>  static void
> @@ -1691,6 +1809,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine)
>  	engine->emit_breadcrumb = gen8_emit_breadcrumb;
>  	engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_sz;
>  	engine->submit_request = execlists_submit_request;
> +	engine->schedule = execlists_schedule;
>
>  	engine->irq_enable = gen8_logical_ring_enable_irq;
>  	engine->irq_disable = gen8_logical_ring_disable_irq;
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index b9583941eb6b..3466b4e77e7c 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -348,7 +348,8 @@ struct intel_engine_cs {
>  		struct drm_i915_gem_request *request;
>  		unsigned int count;
>  	} execlist_port[2];
> -	struct list_head execlist_queue;
> +	struct rb_root execlist_queue;
> +	struct rb_node *execlist_first;
>  	unsigned int fw_domains;
>  	bool disable_lite_restore_wa;
>  	bool preempt_wa;
>

Just the comment needs to be updated. With that:

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* [PATCH v4 3/3] PCI: qcom: add runtime pm support to pcie_port
From: Srinivas Kandagatla @ 2016-11-14 11:15 UTC (permalink / raw)
  To: svarbanov-NEYub+7Iv8PQT0dZR+AlfA,
	linux-pci-u79uwXL29TY76Z2rM5mHXA, bhelgaas-hpIqsD4AKlfQT0dZR+AlfA
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479122155-13393-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

This patch is required when the pcie controller sits on a bus with
its own power domain and clocks which are controlled via a bus driver
like simple pm bus. As these bus driver have runtime pm enabled, it makes
sense to update the usage counter so that the runtime pm does not suspend
the clks or power domain associated with the bus driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/pci/host/pcie-qcom.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
index 03ba6b1..c2ca848 100644
--- a/drivers/pci/host/pcie-qcom.c
+++ b/drivers/pci/host/pcie-qcom.c
@@ -587,6 +587,8 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
 	int ret;
 
+	pm_runtime_get_sync(pp->dev);
+
 	qcom_ep_reset_assert(pcie);
 
 	ret = pcie->ops->init(pcie);
@@ -617,6 +619,7 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	phy_power_off(pcie->phy);
 err_deinit:
 	pcie->ops->deinit(pcie);
+	pm_runtime_put_sync(pp->dev);
 }
 
 static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
@@ -673,6 +676,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
 	if (!pcie)
 		return -ENOMEM;
 
+	pm_runtime_enable(dev);
 	pp = &pcie->pp;
 	pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
 
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v4 1/3] bus: simple-pm: add support to pm clocks
From: Srinivas Kandagatla @ 2016-11-14 11:15 UTC (permalink / raw)
  To: svarbanov, linux-pci, bhelgaas
  Cc: robh+dt, linux-arm-msm, srinivas.kandagatla, devicetree
In-Reply-To: <1479122155-13393-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds support to pm clocks via device tree, so that the clocks
can be turned on and off during runtime pm. This patch is required for
Qualcomm msm8996 pcie controller which sits on a bus with its own
power-domain and clocks.

Without this patch the clock associated with the bus are never turned on.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/bus/simple-pm-bus.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
index c5eb46c..63b7e8c 100644
--- a/drivers/bus/simple-pm-bus.c
+++ b/drivers/bus/simple-pm-bus.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_clock.h>
 #include <linux/pm_runtime.h>
 
 
@@ -22,17 +23,26 @@ static int simple_pm_bus_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(&pdev->dev);
 
-	if (np)
+	if (np) {
+		of_pm_clk_add_clks(&pdev->dev);
 		of_platform_populate(np, NULL, NULL, &pdev->dev);
+	}
 
 	return 0;
 }
 
+static const struct dev_pm_ops simple_pm_bus_pm_ops = {
+	SET_RUNTIME_PM_OPS(pm_clk_suspend,
+			   pm_clk_resume, NULL)
+};
+
 static int simple_pm_bus_remove(struct platform_device *pdev)
 {
 	dev_dbg(&pdev->dev, "%s\n", __func__);
 
 	pm_runtime_disable(&pdev->dev);
+	pm_clk_destroy(&pdev->dev);
+
 	return 0;
 }
 
@@ -48,6 +58,7 @@ static struct platform_driver simple_pm_bus_driver = {
 	.driver = {
 		.name = "simple-pm-bus",
 		.of_match_table = simple_pm_bus_of_match,
+		.pm = &simple_pm_bus_pm_ops,
 	},
 };
 
-- 
2.10.1

^ permalink raw reply related

* Re: [PATCH v3 5/6] arm64: arch_timer: apci: Introduce a generic aquirk framework for erratum
From: Ding Tianhong @ 2016-11-14 11:15 UTC (permalink / raw)
  To: Hanjun Guo, catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	marc.zyngier-5wv7dgnIgG8, mark.rutland-5wv7dgnIgG8,
	oss-fOR+EgIDQEHk1uMJSBkQmQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linuxarm-hv44wF8Li93QT0dZR+AlfA,
	hanjun.guo-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <582971E0.4070403-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>

OK, will wait more feedback and fix them together in the next version.

Thanks.
Ding

On 2016/11/14 16:12, Hanjun Guo wrote:
> On 2016/11/4 21:06, Ding Tianhong wrote:
>> From: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> Introduce a general quirk framework for each timer erratum in ACPI,
>> which use the oem information in GTDT table for platform specific erratums.
>> The struct gtdt_arch_timer_fixup is introduced to record the oem
>> information to match the quirk and handle the erratum.
>>
>> v3: Introduce a generic aquick framework for erratum in ACPI mode.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> Signed-off-by: Ding Tianhong <dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 37 ++++++++++++++++++++++++++++++++++++
>>  1 file changed, 37 insertions(+)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>> index 3d59af1..9bc93e5 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -1068,6 +1068,40 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
>>  		       arch_timer_mem_init);
>>  
>>  #ifdef CONFIG_ACPI
>> +struct gtdt_arch_timer_fixup {
>> +	char oem_id[ACPI_OEM_ID_SIZE];
>> +	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
>> +	u32 oem_revision;
>> +
>> +	/* quirk handler for arch timer erratum */
>> +	void (*handler)(u32 erratum);
>> +	u32 erratum;
> 
> Hmm, I think we just use
> 
> void *context;
> 
> and we convert it in the platform specific handler, then this struct
> can be reused for other type of quirks.
> 
>> +};
>> +
>> +/* note: this needs to be updated according to the doc of OEM ID
>> + * and TABLE ID for different board.
>> + */
>> +struct gtdt_arch_timer_fixup arch_timer_quirks[] __initdata = {
>> +};
>> +
>> +void __init arch_timer_acpi_quirks_handler(char *oem_id,
>> +						  char *oem_table_id,
>> +						  u32 oem_revision)
>> +{
>> +	struct gtdt_arch_timer_fixup *quirks = arch_timer_quirks;
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(arch_timer_quirks); i++, quirks++) {
>> +		if (!memcmp(quirks->oem_id, oem_id, ACPI_OEM_ID_SIZE) &&
>> +		    !memcmp(quirks->oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
>> +		    quirks->oem_revision == oem_revision) {
>> +			if (quirks->handler && quirks->erratum)
>> +				quirks->handler(quirks->erratum);
>> +			break;
> 
> we can't just break because we have multi quirks for different handlers.
> 
> Thanks
> Hanjun
> 
> 
> .
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v3 5/6] arm64: arch_timer: apci: Introduce a generic aquirk framework for erratum
From: Ding Tianhong @ 2016-11-14 11:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <582971E0.4070403@huawei.com>

OK, will wait more feedback and fix them together in the next version.

Thanks.
Ding

On 2016/11/14 16:12, Hanjun Guo wrote:
> On 2016/11/4 21:06, Ding Tianhong wrote:
>> From: Hanjun Guo <hanjun.guo@linaro.org>
>>
>> Introduce a general quirk framework for each timer erratum in ACPI,
>> which use the oem information in GTDT table for platform specific erratums.
>> The struct gtdt_arch_timer_fixup is introduced to record the oem
>> information to match the quirk and handle the erratum.
>>
>> v3: Introduce a generic aquick framework for erratum in ACPI mode.
>>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 37 ++++++++++++++++++++++++++++++++++++
>>  1 file changed, 37 insertions(+)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>> index 3d59af1..9bc93e5 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -1068,6 +1068,40 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
>>  		       arch_timer_mem_init);
>>  
>>  #ifdef CONFIG_ACPI
>> +struct gtdt_arch_timer_fixup {
>> +	char oem_id[ACPI_OEM_ID_SIZE];
>> +	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
>> +	u32 oem_revision;
>> +
>> +	/* quirk handler for arch timer erratum */
>> +	void (*handler)(u32 erratum);
>> +	u32 erratum;
> 
> Hmm, I think we just use
> 
> void *context;
> 
> and we convert it in the platform specific handler, then this struct
> can be reused for other type of quirks.
> 
>> +};
>> +
>> +/* note: this needs to be updated according to the doc of OEM ID
>> + * and TABLE ID for different board.
>> + */
>> +struct gtdt_arch_timer_fixup arch_timer_quirks[] __initdata = {
>> +};
>> +
>> +void __init arch_timer_acpi_quirks_handler(char *oem_id,
>> +						  char *oem_table_id,
>> +						  u32 oem_revision)
>> +{
>> +	struct gtdt_arch_timer_fixup *quirks = arch_timer_quirks;
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(arch_timer_quirks); i++, quirks++) {
>> +		if (!memcmp(quirks->oem_id, oem_id, ACPI_OEM_ID_SIZE) &&
>> +		    !memcmp(quirks->oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
>> +		    quirks->oem_revision == oem_revision) {
>> +			if (quirks->handler && quirks->erratum)
>> +				quirks->handler(quirks->erratum);
>> +			break;
> 
> we can't just break because we have multi quirks for different handlers.
> 
> Thanks
> Hanjun
> 
> 
> .
> 

^ permalink raw reply

* [bug report] drm/i915: Allow compaction upto SWIOTLB max segment size
From: Dan Carpenter @ 2016-11-14 11:14 UTC (permalink / raw)
  To: chris; +Cc: intel-gfx

Hello Chris Wilson,

The patch 871dfbd67d4e: "drm/i915: Allow compaction upto SWIOTLB max
segment size" from Oct 11, 2016, leads to the following static
checker warning:

	drivers/gpu/drm/i915/i915_gem.c:2357 i915_gem_object_get_pages_gtt()
	error: we previously assumed 'sg' could be null (see line 2341)

drivers/gpu/drm/i915/i915_gem.c
  2339                  /* Check that the i965g/gm workaround works. */
  2340                  WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL));
  2341          }
  2342          if (sg) /* loop terminated early; short sg table */

We added a new check for NULL.

  2343                  sg_mark_end(sg);
  2344  
  2345          /* Trim unused sg entries to avoid wasting memory. */
  2346          i915_sg_trim(st);
  2347  
  2348          ret = i915_gem_gtt_prepare_pages(obj, st);
  2349          if (ret)
  2350                  goto err_pages;

but we hit this goto

  2351  
  2352          if (i915_gem_object_needs_bit17_swizzle(obj))
  2353                  i915_gem_object_do_bit_17_swizzle(obj, st);
  2354  
  2355          return st;
  2356  
  2357  err_pages:
  2358          sg_mark_end(sg);

Then don't check here.  Also do we really need to sg_mark_end() twice?

  2359          for_each_sgt_page(page, sgt_iter, st)
  2360                  put_page(page);
  2361          sg_free_table(st);
  2362          kfree(st);

regards,
dan carpenter
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* [U-Boot] [PATCH 2/7] mtd: nand: add support for the TC58NVG2S0H chip
From: Hans de Goede @ 2016-11-14 11:15 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <b535d6b27a3af2d2a927de1a788a12455c523b3d.1478621974.git-series.maxime.ripard@free-electrons.com>

Hi,

On 08-11-16 17:21, Maxime Ripard wrote:
> From: Boris Brezillon <boris.brezillon@free-electrons.com>
>
> Add the description of the Toshiba TC58NVG2S0H SLC nand to the nand_ids
> table so we can use the NAND ECC infos and the ONFI timings.
>
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Looks good to me:

Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans



> ---
>  drivers/mtd/nand/nand_ids.c | 3 +++
>  1 file changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
> index ce0a14e28abb..d36f9006c99d 100644
> --- a/drivers/mtd/nand/nand_ids.c
> +++ b/drivers/mtd/nand/nand_ids.c
> @@ -46,6 +46,9 @@ struct nand_flash_dev nand_flash_ids[] = {
>  	{"TC58NVG2S0F 4G 3.3V 8-bit",
>  		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
>  		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
> +	{"TC58NVG2S0H 4G 3.3V 8-bit",
> +		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00} },
> +		  SZ_4K, SZ_512, SZ_256K, 0, 8, 256, NAND_ECC_INFO(8, SZ_512) },
>  	{"TC58NVG3S0F 8G 3.3V 8-bit",
>  		{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },
>  		  SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) },
>

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.