All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [v5] ath9k: Switch to using mac80211 intermediate software queues.
From: Kalle Valo @ 2016-11-09  2:22 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen
  Cc: make-wifi-fast, linux-wireless, Toke Høiland-Jørgensen,
	Tim Shepard, Felix Fietkau
In-Reply-To: <20160902140030.11798-1-toke@toke.dk>

Toke Høiland-Jørgensen wrote:
> This switches ath9k over to using the mac80211 intermediate software
> queueing mechanism for data packets. It removes the queueing inside the
> driver, except for the retry queue, and instead pulls from mac80211 when
> a packet is needed. The retry queue is used to store a packet that was
> pulled but can't be sent immediately.
> 
> The old code path in ath_tx_start that would queue packets has been
> removed completely, as has the qlen limit tunables (since there's no
> longer a queue in the driver to limit).
> 
> Based on Tim's original patch set, but reworked quite thoroughly.
> 
> Cc: Tim Shepard <shep@alum.mit.edu>
> Cc: Felix Fietkau <nbd@nbd.name>
> Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>

All dependencies have trickled down to ath.git but unfortunately doesn't apply
anymore, so please rebase. Hopefully the last time :)

While at it, could you also add to the commit log some info how awesome this
patch is from user's point of view and how it helps. For example, before and
and after numbers and other results.

error: patch failed: drivers/net/wireless/ath/ath9k/xmit.c:921
error: drivers/net/wireless/ath/ath9k/xmit.c: patch does not apply
stg import: Diff does not apply cleanly

Patch set to Changes Requested.

-- 
https://patchwork.kernel.org/patch/9311037/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* [PATCH v2] fstests: btrfs: Check false ENOSPC bug caused by incorrect metadata reserve
From: Qu Wenruo @ 2016-11-09  2:21 UTC (permalink / raw)
  To: linux-btrfs, fstests

Due to the fact that btrfs uses different max extent size for
compressed and non-compressed write, it calculates metadata reservation
incorrectly.

This can leads to false ENOSPC alert for compressed write.

This test case will check it by using small fs and large nodesize, and
do parallel compressed write to trigger it.

The fix is not merged and may change in the future, but the function is
good enough:
btrfs: improve inode's outstanding_extents computation
btrfs: fix false enospc for compression

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
v2:
  Use $XFS_IO_PROGS to replace hard coded xfs_io.
  Fix "kill 0" which will also kill the script itself.
  Add missing "Silence is golden" output.
  Add workaround for EBUSY while umount for compression
---
 tests/btrfs/132     | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/btrfs/132.out |  2 ++
 tests/btrfs/group   |  1 +
 3 files changed, 101 insertions(+)
 create mode 100755 tests/btrfs/132
 create mode 100644 tests/btrfs/132.out

diff --git a/tests/btrfs/132 b/tests/btrfs/132
new file mode 100755
index 0000000..530a128
--- /dev/null
+++ b/tests/btrfs/132
@@ -0,0 +1,98 @@
+#! /bin/bash
+# FS QA Test 132
+#
+# Check if false ENOSPC will happen when parallel buffer write happens
+# The problem is caused by incorrect metadata reservation.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2016 Fujitsu.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would 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 the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+	cd /
+	rm -f $tmp.*
+	kill $pids &> /dev/null
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# remove previous $seqres.full before test
+rm -f $seqres.full
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs btrfs
+_supported_os Linux
+_require_scratch
+
+# Use small filesystem with maximum nodesize.
+# Since the false ENOSPC happens due to incorrect metadata reservation,
+# larger nodesize and small fs will make it much easier to reproduce
+_scratch_mkfs -b 512M -n 64K >> $seqres.full 2>&1
+_scratch_mount "-o compress"
+
+sleep_time=$(($TIME_FACTOR * 15))
+loop_writer()
+{
+	offset=$1
+	len=$2
+	file=$3
+
+	while true;
+	do
+		# Only need stderr, and we need to specify small block size
+		# but still large enough trigger compression
+		$XFS_IO_PROG -c "pwrite -b 8K $offset $len" $file 2>&1 \
+			> /dev/null
+	done
+}
+
+touch $SCRATCH_MNT/testfile
+
+# Start 2 writter writting into the same file
+# The file is 142M, which is smaller than 1/2 of the filesystem,
+# so no other cause can lead to ENOSPC.
+loop_writer 0 128M $SCRATCH_MNT/testfile &
+pids=$!
+loop_writer 128M 16M $SCRATCH_MNT/testfile &
+pids="$pids $!"
+
+sleep $sleep_time
+
+kill $pids
+wait
+
+# Sync the fs to avoid EBUSY while umount, which is quite common for btrfs
+# compression
+sync
+
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/132.out b/tests/btrfs/132.out
new file mode 100644
index 0000000..b096312
--- /dev/null
+++ b/tests/btrfs/132.out
@@ -0,0 +1,2 @@
+QA output created by 132
+Silence is golden
diff --git a/tests/btrfs/group b/tests/btrfs/group
index c090604..ec8ad80 100644
--- a/tests/btrfs/group
+++ b/tests/btrfs/group
@@ -134,3 +134,4 @@
 129 auto quick send
 130 auto clone send
 131 auto quick
+132 auto compress
-- 
2.7.4




^ permalink raw reply related

* Re: [PATCH] u-boot: mkimage: Fix build of u-boot-mkimage
From: Gary Thomas @ 2016-11-09  2:22 UTC (permalink / raw)
  To: openembedded-core
In-Reply-To: <CAJTo0Lb-xraoP7zCyWEw-06Q4BwjFjFMG+d5mbkgKRCyfzYbzg@mail.gmail.com>

On 2016-11-09 01:45, Burton, Ross wrote:
>
> On 9 November 2016 at 00:43, Khem Raj <raj.khem@gmail.com <mailto:raj.khem@gmail.com>> wrote:
>
>     > I'm guessing that it is using the host compiler instead of the cross compiler.
>
>     isnt mkimage a host tool ? why are we building it for target ?
>
>
> If there's no chance that it will be ran on the target for in a SDK then patches welcome to force the recipe to native only.
>
> The recipe is using _append without adding whitespace, but fixing that doesn't fix the build.

I routinely build and use it on my targets, so no, it's not host only.

-- 
------------------------------------------------------------
Gary Thomas                 |  Consulting for the
MLB Associates              |    Embedded world
------------------------------------------------------------


^ permalink raw reply

* Re: BUG: Hung task timeouts in for-4.10/dio
From: Damien Le Moal @ 2016-11-09  2:17 UTC (permalink / raw)
  To: Jens Axboe, Christoph Hellwig; +Cc: Logan Gunthorpe, linux-block, Mike Snitzer
In-Reply-To: <03cda65e-3a82-6ccd-861b-67a55888eb19@kernel.dk>


Jens,

On 11/9/16 11:02, Jens Axboe wrote:
> It smells like an accounting error. One thing that I don't like with the
> current scheme is the implicit knowledge that certain flags imply sync
> as well. If we clear any of those flags, then we screw up accounting at
> the end.
> 
> Does this make a difference?
> 
> 
> diff --git a/block/blk-flush.c b/block/blk-flush.c
> index c486b7aa62ee..d70983e28115 100644
> --- a/block/blk-flush.c
> +++ b/block/blk-flush.c
> @@ -395,6 +395,8 @@ void blk_insert_flush(struct request *rq)
>   	if (!(fflags & (1UL << QUEUE_FLAG_FUA)))
>   		rq->cmd_flags &= ~REQ_FUA;
> 
> +	rq->cmd_flags |= REQ_SYNC;
> +
>   	/*
>   	 * An empty flush handed down from a stacking driver may
>   	 * translate into nothing if the underlying device does not

That worked. Still seeing hangs/failures at boot with the latest
for-4.10/block (networkmanager failing, no login shell, etc) but with
the above patch, I get a clean boot and login with network working.
Once booted, simple tests on ext4 and xfs do not show any problem, but
that was only very light testing.

Best regards.

-- 
Damien Le Moal, Ph.D.
Sr. Manager, System Software Research Group,
Western Digital Corporation
Damien.LeMoal@wdc.com
(+81) 0466-98-3593 (ext. 513593)
1 kirihara-cho, Fujisawa,
Kanagawa, 252-0888 Japan
www.wdc.com, www.hgst.com

^ permalink raw reply

* RE: [PATCH v1] ufs: introduce UFSHCD_QUIRK_BROKEN_DWORD_UTRD quirk
From: Kiwoong Kim @ 2016-11-09  2:17 UTC (permalink / raw)
  To: 'Subhash Jadavani'
  Cc: 'James E.J. Bottomley', linux-scsi,
	'Martin K. Petersen', vinholikatti, '???',
	linux-scsi-owner
In-Reply-To: <a0c337c3537b86c8cdeb1780958684d0@codeaurora.org>

> > Some UFS host controllers may think
> > granularitys of PRDT length and offset as bytes, not double words.
> >
> > Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
> > ---
> >  drivers/scsi/ufs/ufshcd.c | 24 +++++++++++++++++++-----
> > drivers/scsi/ufs/ufshcd.h |  2 ++
> >  2 files changed, 21 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index 8e19631..549e3e8 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -1161,8 +1161,13 @@ static int ufshcd_map_sg(struct ufshcd_lrb
> > *lrbp)
> >  		return sg_segments;
> >
> >  	if (sg_segments) {
> > -		lrbp->utr_descriptor_ptr->prd_table_length =
> > -					cpu_to_le16((u16) (sg_segments));
> > +		if (hba->quirks & UFSHCD_QUIRK_BROKEN_DWORD_UTRD)
> 
> This might sound more specific:
> s/UFSHCD_QUIRK_BROKEN_DWORD_UTRD/UFSHCD_QUIRK_PRDT_BYTE_GRAN .

That sounds good. I'll apply what you said.

> 
> > +			lrbp->utr_descriptor_ptr->prd_table_length =
> > +				cpu_to_le16((u16)(sg_segments *
> > +					sizeof(struct ufshcd_sg_entry)));
> > +		else
> > +			lrbp->utr_descriptor_ptr->prd_table_length =
> > +				cpu_to_le16((u16) (sg_segments));
> >
> >  		prd_table = (struct ufshcd_sg_entry *)lrbp->ucd_prdt_ptr;
> >
> > @@ -2385,12 +2390,21 @@ static void
> > ufshcd_host_memory_configure(struct ufs_hba *hba)
> >
> 	cpu_to_le32(upper_32_bits(cmd_desc_element_addr));
> >
> >  		/* Response upiu and prdt offset should be in double words
> */
> > -		utrdlp[i].response_upiu_offset =
> > +		if (hba->quirks & UFSHCD_QUIRK_BROKEN_DWORD_UTRD) {
> > +			utrdlp[i].response_upiu_offset =
> > +				cpu_to_le16(response_offset);
> > +			utrdlp[i].prd_table_offset =
> > +				cpu_to_le16(prdt_offset);
> > +			utrdlp[i].response_upiu_length =
> > +				cpu_to_le16(ALIGNED_UPIU_SIZE);
> > +		} else {
> > +			utrdlp[i].response_upiu_offset =
> >  				cpu_to_le16((response_offset >> 2));
> > -		utrdlp[i].prd_table_offset =
> > +			utrdlp[i].prd_table_offset =
> >  				cpu_to_le16((prdt_offset >> 2));
> > -		utrdlp[i].response_upiu_length =
> > +			utrdlp[i].response_upiu_length =
> >  				cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
> > +		}
> >
> >  		hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
> >  		hba->lrb[i].ucd_req_ptr =
> > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> > index 8cf3991..565f005 100644
> > --- a/drivers/scsi/ufs/ufshcd.h
> > +++ b/drivers/scsi/ufs/ufshcd.h
> > @@ -494,6 +494,8 @@ struct ufs_hba {
> >  	#define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION		UFS_BIT(5)
> >
> >  	#define UFSHCD_QUIRK_GET_VS_RESULT			UFS_BIT(6)
> > +	#define UFSHCD_QUIRK_BROKEN_DWORD_UTRD                  UFS_BIT(7)
> > +
> 
> This extra line space isn't needed.

Okay.

> 
> >
> >  	unsigned int quirks;	/* Deviations from standard UFSHCI spec.
> */
> 
> --
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
> Linux Foundation Collaborative Project
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html



^ permalink raw reply

* Re: [PATCH v2 0/2] arm64: fix the bugs found in the hugetlb test
From: Huang Shijie @ 2016-11-09  1:42 UTC (permalink / raw)
  To: Will Deacon
  Cc: Catalin Marinas, dwoods, steve.capper, linux-kernel, kaly.xin,
	akpm, nd, linux-arm-kernel
In-Reply-To: <20161108163642.GE20591@arm.com>

Hi Will & Catalin,

On Tue, Nov 08, 2016 at 04:36:43PM +0000, Will Deacon wrote:
> On Tue, Nov 08, 2016 at 02:09:09PM +0000, Catalin Marinas wrote:
> > On Tue, Nov 08, 2016 at 01:44:37PM +0800, Huang Shijie wrote:
> > > (3) The test result in the Softiron and Juno-r1 boards:
> > > 
> > >    This detail test result shows below (both the "make func" & "make stress"):
> > > 
> > >     4KB granule:
> > > 
> > >         1.1) PTE + Contiguous bit : 4K x 16 = 64K (per huge page size)
> > >              Test result          : PASS
> > > 
> > >         1.2) PMD                  : 2M x  1 = 2M  (per huge page size)
> > >              Test result          : PASS
> > > 
> > >         1.3) PMD + Contiguous bit : 2M x 16 = 32M (per huge page size)
> > >              Test result          : PASS
> > > 
> > >     64KB granule:
> > > 
> > >         3.1) PTE + Contiguous bit : 64K x 32 = 2M (per huge page size)
> > >              Test result          : PASS
> > > 
> > >         3.2) PMD + Contiguous bit : 512M x 32 = 16G (per huge page size)
> > >              Test result          : no hardware to support this test
> > 
> > Don't we have support for single (non-contiguous) PMD huge page with 64K
> > pages (512M per huge page)? I gave it a try and it seems to work (though
> > without your patches applied ;)).
Yes, it should be okay. This patch set does not affect the the single
PMD huge page.

> > 
> > > Huang Shijie (2):
> > >   arm64: hugetlb: remove the wrong pmd check in find_num_contig()
> > >   arm64: hugetlb: fix the wrong address for several functions
> > 
> > For these patches:
> > 
> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Thanks you, Catalin.

> > 
> > I'm not sure whether Will plans to push them into 4.9. AFAICT, the
> > contiguous huge pages never worked properly, so we may not count it as a
> > regression but a new feature. If Will doesn't take them, I'll queue the
> > patches for 4.10.
> 
> Right, given that it's never worked and the failure only seems to crop up
> in synthetic testing, I think you can queue these for 4.10.
Okay. Thank for queue them for 4.10.

Thanks
Huang Shijie

^ permalink raw reply

* RE: [REGRESSION] 4.9-rc4+ doesn't boot on my test box
From: Kashyap Desai @ 2016-11-09  2:14 UTC (permalink / raw)
  To: Jens Axboe, Martin K. Petersen; +Cc: linux-scsi
In-Reply-To: <7829000d-2e1c-d298-57cb-8d02c4e020d2@kernel.dk>

> -----Original Message-----
> From: Jens Axboe [mailto:axboe@kernel.dk]
> Sent: Wednesday, November 09, 2016 6:50 AM
> To: Kashyap Desai; Martin K. Petersen
> Cc: linux-scsi
> Subject: Re: [REGRESSION] 4.9-rc4+ doesn't boot on my test box
>
> On 11/08/2016 05:20 PM, Kashyap Desai wrote:
> >> -----Original Message-----
> >> From: Martin K. Petersen [mailto:martin.petersen@oracle.com]
> >> Sent: Wednesday, November 09, 2016 4:45 AM
> >> To: Jens Axboe
> >> Cc: linux-scsi; Kashyap Desai; Martin K. Petersen
> >> Subject: Re: [REGRESSION] 4.9-rc4+ doesn't boot on my test box
> >>
> >>>>>>> "Jens" == Jens Axboe <axboe@kernel.dk> writes:
> >>
> >> Jens> I wasted half a day on this, thinking it was something in my
> >> Jens> 4.10 branches. But it turns out it is not, the regression is in
> >> Jens> mainline.
> >
> > Jens -
> >
> > Sorry for trouble.  I did not validated this single patch. I validated
> > complete patch set.
> > Issue is improper MACRO usage MEGASAS_IS_LOGICAL, which gives
> > incorrect check condition in qcmd Path.
> >
> > Below is proposed fix.
> >
> >
> > diff --git a/drivers/scsi/megaraid/megaraid_sas.h
> > b/drivers/scsi/megaraid/megaraid_sas.h
> > index 74c7b44..0d2625b 100644
> > --- a/drivers/scsi/megaraid/megaraid_sas.h
> > +++ b/drivers/scsi/megaraid/megaraid_sas.h
> > @@ -2236,7 +2236,7 @@ struct megasas_instance_template {  };
> >
> >  #define MEGASAS_IS_LOGICAL(scp)
> > \
> > -	(scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
>
> Ugh... So we're completing everything immediately.
>
> > Martin -  I validated whole series.  Apologies for this.
> >
> > Please help me to know how to fix this ? Do I need to send only fix on
> > top of latest commit (as posted above - MACRO definition) for this issue
> > ?
>
> Send a fix on top of current -git asap. The current tree is completely
> broken for
> any megaraid user. -rc4 is no time to send in untested patches, especially
> not
> something that claims to fix a 9 year old bug and is marked for stable as
> well.


I will run some more test (using patch set only marked for stable from last
series) and submit fix ASAP.

>
> --
> Jens Axboe

^ permalink raw reply

* RE: [PATCH v1] ufs: introduce UFSHCD_QUIRK_USE_OF_HCE quirk
From: Kiwoong Kim @ 2016-11-09  2:13 UTC (permalink / raw)
  To: 'Subhash Jadavani'
  Cc: 'James E.J. Bottomley', linux-scsi,
	'Martin K. Petersen', vinholikatti, '???',
	linux-scsi-owner
In-Reply-To: <2c77bb07cb872130fb55c555391f8080@codeaurora.org>



> On 2016-11-07 23:57, Kiwoong Kim wrote:
> > Some host controller might not initialize itself by setting "Host
> > Controller Enable" to 1.
> 
> > They should do this to reset UIC.
> 
> I am not sure if i understood this statment. can you give more details?

UFSHCI spec says as follows:
- When HCE is ‘0’ and software writes ‘1’, the host 
controller hardware shall execute the step 2 described in section 7.1.1
of this standard, including reset of the host UTP and UIC layers.

I found that a specific controller didn't execute reset of UIC layers
Properly for an internal problem.
At that time, DME reset and DME enable could make UIC be reset properly
instead of using "Host Controller Enable".

> 
> > In such cases, 'DME reset' and 'DME enable' are required for normal
> > subsequent operations.
> 
> This means HCE implementation is broken, you should name the quirk as
> UFSHCD_QUIRK_BROKEN_HCE .

Okay.

> 
> >
> > Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
> > ---
> >  drivers/scsi/ufs/ufshcd.c | 44
> > +++++++++++++++++++++++++++++++++++++++++++-
> >  drivers/scsi/ufs/ufshcd.h |  1 +
> >  2 files changed, 44 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index 24d6ea7..c904854 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -2496,6 +2496,37 @@ static inline void
> > ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba)
> >  	usleep_range(min_sleep_time_us, min_sleep_time_us + 50);  }
> >
> > +static int ufshcd_dme_reset(struct ufs_hba *hba) {
> > +	struct uic_command uic_cmd = {0};
> > +	int ret;
> > +
> > +	uic_cmd.command = UIC_CMD_DME_RESET;
> > +	uic_cmd.argument1 = 0x1;
> > +
> > +	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> > +	if (ret)
> > +		dev_err(hba->dev,
> > +			"dme-reset: error code %d\n", ret);
> 
> This error message doesn't say which DME command failed, do you want to
> add that?

I think that the string "dme-reset" is useful when clarifying some problems.
But if you don't agree merging it to mainline, I'll remove it in next
version.

> 
> > +
> > +	return ret;
> > +}
> > +
> > +static int ufshcd_dme_enable(struct ufs_hba *hba) {
> > +	struct uic_command uic_cmd = {0};
> > +	int ret;
> > +
> > +	uic_cmd.command = UIC_CMD_DME_ENABLE;
> > +
> > +	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> > +	if (ret)
> > +		dev_err(hba->dev,
> > +			"dme-enable: error code %d\n", ret);
> 
> This error message doesn't say which DME command failed, do you want to
> add that?

Same with above.

> 
> > +
> > +	return ret;
> > +}
> > +
> >  /**
> >   * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
> >   * @hba: per adapter instance
> > @@ -3101,6 +3132,7 @@ static inline void ufshcd_hba_stop(struct
> > ufs_hba *hba, bool can_sleep)  static int ufshcd_hba_enable(struct
> > ufs_hba *hba)  {
> >  	int retry;
> > +	int ret = 0;
> >
> >  	/*
> >  	 * msleep of 1 and 5 used in this function might result in
> > msleep(20), @@ -3117,6 +3149,9 @@ static int ufshcd_hba_enable(struct
> > ufs_hba *hba)
> >
> >  	ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
> >
> > +	if (hba->quirks & UFSHCD_QUIRK_USE_OF_HCE)
> > +		goto use_dme;
> > +
> >  	/* start controller initialization sequence */
> >  	ufshcd_hba_start(hba);
> >
> > @@ -3145,12 +3180,19 @@ static int ufshcd_hba_enable(struct ufs_hba
> > *hba)
> >  		msleep(5);
> >  	}
> >
> > +use_dme:
> >  	/* enable UIC related interrupts */
> >  	ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
> >
> > +	if (hba->quirks & UFSHCD_QUIRK_USE_OF_HCE) {
> > +		ret = ufshcd_dme_reset(hba);
> > +		if (!ret)
> > +			ret = ufshcd_dme_enable(hba);
> > +	}
> > +
> >  	ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
> >
> > -	return 0;
> > +	return ret;
> >  }
> >
> >  static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) diff
> > --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index
> > c4abd76..6a96f24 100644
> > --- a/drivers/scsi/ufs/ufshcd.h
> > +++ b/drivers/scsi/ufs/ufshcd.h
> > @@ -496,6 +496,7 @@ struct ufs_hba {
> >  	#define UFSHCD_QUIRK_GET_VS_RESULT			UFS_BIT(6)
> >  	#define UFSHCD_QUIRK_BROKEN_DWORD_UTRD                  UFS_BIT(7)
> >  	#define UFSHCD_QUIRK_BROKEN_REQ_LIST_CLR                UFS_BIT(8)
> > +	#define UFSHCD_QUIRK_USE_OF_HCE				UFS_BIT(9)
> >
> >
> >  	unsigned int quirks;	/* Deviations from standard UFSHCI spec.
> */
> 
> --
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
> Linux Foundation Collaborative Project



^ permalink raw reply

* Re: [PATCH] Avoid that SCSI device removal through sysfs triggers a deadlock
From: Eric W. Biederman @ 2016-11-09  2:10 UTC (permalink / raw)
  To: James Bottomley
  Cc: Bart Van Assche, Martin K. Petersen, Greg Kroah-Hartman,
	Hannes Reinecke, Johannes Thumshirn, Sagi Grimberg,
	linux-scsi@vger.kernel.org
In-Reply-To: <1478655815.2368.34.camel@linux.vnet.ibm.com>

James Bottomley <jejb@linux.vnet.ibm.com> writes:

> On Tue, 2016-11-08 at 18:57 -0600, Eric W. Biederman wrote:
>> James Bottomley <jejb@linux.vnet.ibm.com> writes:
>> 
>> > On Tue, 2016-11-08 at 13:13 -0600, Eric W. Biederman wrote:
> [...]
>> > > Is it really the dropping of the lock that is causing this?
>> > > I don't see that when I read those traces.
>> > 
>> > No, it's an ABBA lock inversion that causes this.  The traces are
>> > somewhat dense, but they say it here:
>> > 
>> >  Possible unsafe locking scenario:
>> >        CPU0                    CPU1
>> >        ----                    ----
>> >   lock(s_active#336);
>> >                                lock(&shost->scan_mutex);
>> >                                lock(s_active#336);
>> >   lock(&shost->scan_mutex);
>> > 
>> >  *** DEADLOCK ***
>> > 
>> > The detailed explanation of this is here:
>> > 
>> > http://marc.info/?l=linux-scsi&m=147855187425596
>> > 
>> > The fix is ensuring that the CPU1 thread doesn't get into taking
>> > s_active if CPU0 already has it using the KERNFS_SUICIDED/AL flag 
>> > as an indicator.
>> 
>> So.  The kernfs code does not look safe to have kernfs_remove_self
>> and kernfs_remove_by_name_ns racing against each other I agree.
>> 
>> The kernfs_remove_self path turns KERNFS_SUICIDAL into another 
>> blocking lock by another name, and without lockdep annotations so I 
>> don't know that it is safe.
>
> Yes ... the number of hand rolled locks in that code make it super hard
> to follow.
>
>> The relevant bit from kernfs_remove_self is:
>> 
>> 	if (!(kn->flags & KERNFS_SUICIDAL)) {
>> 		kn->flags |= KERNFS_SUICIDAL;
>> 		__kernfs_remove(kn);
>> 		kn->flags |= KERNFS_SUICIDED;
>> 		ret = true;
>> 	} else {
>> 		wait_queue_head_t *waitq = &kernfs_root(kn)
>> ->deactivate_waitq;
>> 		DEFINE_WAIT(wait);
>> 
>> 		while (true) {
>> 			prepare_to_wait(waitq, &wait,
>> TASK_UNINTERRUPTIBLE);
>> 
>> 			if ((kn->flags & KERNFS_SUICIDED) &&
>> 			    atomic_read(&kn->active) ==
>> KN_DEACTIVATED_BIAS)
>> 				break;
>> 
>> 			mutex_unlock(&kernfs_mutex);
>> 			schedule();
>> 			mutex_lock(&kernfs_mutex);
>> 		}
>> 		finish_wait(waitq, &wait);
>> 		WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb));
>> 		ret = false;
>> 	}
>> 
>> I am pretty certain that if you are going to make kernfs_remove_self 
>> and kernfs_remove_by_name_ns to be safe to race against each other, 
>> not just the KERNFS_SUICIDAL check, but the wait when KERNFS_SUICIDAL 
>> is set needs to be added ot kernfs_remove_by_name_ns.
>
> I don't think you can do that: waiting for SUICIDED would introduce
> another potential lock entanglement.  I'm reasonably happy that the
> deactivation offset coupled with kernfs_drain in the non self remove
> path means that the necessary cleanup is done when the directory itself
> is removed.  That seems to be a common pattern in all non-self
> removes.

But if we don't I am pretty certain there will be asynchrounous behavior
in some cases that could potentially confuse userspace.

Which is partly why I would like to kill kernfs_remove_self.

>> And I suspect if you add the appropriate lockdep annotations to that 
>> mess you will find yourself in a similar but related ABBA deadlock.
>
> I can't prove the negative, but as long as there's no waiting on the
> SUICIDED/AL flags in the non-self remove path, I believe we're safe
> with the current patch.
>
>> Which is why I would like a simpler easier to understand mechanism if
>> we can.
>
> I don't disagree: If you want to clean out the Augean Stables, I can
> lend you the thigh length rubber boots and the gas mask.  However, I
> think that what we're currently proposing: a simple patch to make
> device_remove_file_self() actually work for everyone, along with
> stringent testing is the better approach.
>
> After all, if you look at
>
> commit ac0ece9174aca9aa895ce0accc54f1f8ff12d117
> Author: Tejun Heo <tj@kernel.org>
> Date:   Mon Feb 3 14:03:03 2014 -0500
>
>     scsi: use device_remove_file_self() instead of device_schedule_callback()
>
> You'll see Tejun added all this stuff just to remove the async callback
> we originally had.  Simply restoring the async callback back makes us
> quite considerably worse off because the device_remove_file_self()
> mechanism is in use elsewhere.  We need either to fix it and move on or
> junk it and go back to the original.

I vote we junk it and go back to something that resembles the original.
there are only about 5 other callers so this isn't that bad to do.

Tejun's work clearly added this deadlock 2 and a half years ago, and
it was nasty enough no one noticed until recently.

Using task_work_add(current, ...) as I posted earlier let's us retain
the synchronous property of the current API.

While we debate the details I am happy to look at scsi as a special case
and solve for scsi.  Then when we have the details worked out we can go
fix the other cases.  Given my preliminary patch in my last reply it
looks very straight forward to fix this sanely.

Eric


^ permalink raw reply

* [PATCH linux v2 3/3] devicetree : Add support in Zaius platform for 4 PWM output ports
From: Jaghathiswari Rankappagounder Natarajan @ 2016-11-09  2:11 UTC (permalink / raw)
  To: openbmc, joel; +Cc: Jaghathiswari Rankappagounder Natarajan
In-Reply-To: <1478657505-23109-1-git-send-email-jaghu@google.com>

Zaius has four fans. Add support for four PWM output ports in Zaius.

v2:
- make the pwmX entries children of the pwm_controller entry.

Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
---
 arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts | 43 ++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
index 4c4754b..5ba8fed 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
@@ -58,6 +58,49 @@
 			};
 		};
 	};
+
+	pwm: pwm-controller@1e786000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x1E786000 0x78>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+				&pinctrl_pwm2_default &pinctrl_pwm3_default>;
+		compatible = "aspeed,ast2500-pwm";
+		clock_enable = /bits/ 8 <0x01>;
+		clock_source = /bits/ 8 <0x00>;
+		typem_pwm_clock = <1 5 0 95>;
+		typen_pwm_clock = <0 0 0 0>;
+		typeo_pwm_clock = <0 0 0 0>;
+
+		pwm_port0 {
+			pwm_port = /bits/ 8 <0x00>;
+			pwm_enable = /bits/ 8 <0x01>;
+			pwm_type = /bits/ 8 <0x00>;
+			pwm_duty_cycle_percent = /bits/ 8 <0x64>;
+		};
+
+		pwm_port1 {
+			pwm_port = /bits/ 8 <0x01>;
+			pwm_enable = /bits/ 8 <0x01>;
+			pwm_type = /bits/ 8 <0x00>;
+			pwm_duty_cycle_percent = /bits/ 8 <0x64>;
+		};
+
+		pwm_port2 {
+			pwm_port = /bits/ 8 <0x02>;
+			pwm_enable = /bits/ 8 <0x01>;
+			pwm_type = /bits/ 8 <0x00>;
+			pwm_duty_cycle_percent = /bits/ 8 <0x64>;
+		};
+
+		pwm_port3 {
+			pwm_port = /bits/ 8 <0x03>;
+			pwm_enable = /bits/ 8 <0x01>;
+			pwm_type = /bits/ 8 <0x00>;
+			pwm_duty_cycle_percent = /bits/ 8 <0x64>;
+		};
+	};
 };

 &uart5 {
--
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH linux v2 2/3] drivers: hwmon: ASPEED AST2500 PWM driver
From: Jaghathiswari Rankappagounder Natarajan @ 2016-11-09  2:11 UTC (permalink / raw)
  To: openbmc, joel; +Cc: Jaghathiswari Rankappagounder Natarajan
In-Reply-To: <1478657505-23109-1-git-send-email-jaghu@google.com>

The ASPEED AST2500 PWM controller can support upto 8 PWM output ports.
There are three different PWM sources(types M, N and O)
and each PWM output port can be assigned a particular PWM source.
There is a sysfs file through which the user can control
the duty cycle of a particular PWM port. The duty cycle can range from 0 to
100 percent.

v2:
- Merged the drivers for PWM controller and PWM device as one PWM driver.

Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
---
 drivers/hwmon/Kconfig              |   5 +
 drivers/hwmon/Makefile             |   2 +-
 drivers/hwmon/aspeed_ast2500_pwm.c | 662 +++++++++++++++++++++++++++++++++++++
 drivers/hwmon/aspeed_ast2500_pwm.h | 128 +++++++
 4 files changed, 796 insertions(+), 1 deletion(-)
 create mode 100644 drivers/hwmon/aspeed_ast2500_pwm.c
 create mode 100644 drivers/hwmon/aspeed_ast2500_pwm.h

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 3b34ba9..7edd94e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1800,6 +1800,11 @@ config SENSORS_ULTRA45
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.

+config ASPEED_AST2500_PWM
+	tristate "ASPEED AST2500 PWM driver"
+	help
+	  This driver provides support for ASPEED AST2500 PWM output ports.
+
 if ACPI

 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c0f3201..23529c2 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -163,7 +163,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
-
+obj-$(CONFIG_ASPEED_AST2500_PWM)	+= aspeed_ast2500_pwm.o
 obj-$(CONFIG_PMBUS)		+= pmbus/

 ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
diff --git a/drivers/hwmon/aspeed_ast2500_pwm.c b/drivers/hwmon/aspeed_ast2500_pwm.c
new file mode 100644
index 0000000..fda49d7
--- /dev/null
+++ b/drivers/hwmon/aspeed_ast2500_pwm.c
@@ -0,0 +1,662 @@
+/*
+ * Aspeed AST2500 PWM device driver
+ * * Copyright (c) 2016 Google, Inc
+ *
+ * * 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.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/sysfs.h>
+
+#include "aspeed_pwm.h"
+
+struct ast_pwm_port_data {
+	u8 pwm_port;
+	u8 pwm_enable;
+	u8 pwm_type;
+	u8 pwm_duty_cycle;
+	void __iomem *base;
+};
+
+struct ast_pwm_controller_data {
+	void __iomem *base;
+};
+
+static inline void
+ast_pwm_write(void __iomem *base, u32 val, u32 reg)
+{
+	writel(val, base + reg);
+}
+
+static inline u32
+ast_pwm_read(void __iomem *base, u32 reg)
+{
+	u32 val = readl(base + reg);
+	return val;
+}
+
+static void
+ast_set_pwm_clock_enable(struct ast_pwm_controller_data *priv, u8 val)
+{
+	if (val) {
+		ast_pwm_write(priv->base,
+			ast_pwm_read(priv->base, AST_PTCR_CTRL) |
+			AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
+	} else {
+		ast_pwm_write(priv->base,
+			ast_pwm_read(priv->base, AST_PTCR_CTRL) &
+			~AST_PTCR_CTRL_CLK_EN, AST_PTCR_CTRL);
+	}
+}
+
+static void
+ast_set_pwm_clock_source(struct ast_pwm_controller_data *priv, u8 val)
+{
+	if (val) {
+		ast_pwm_write(priv->base,
+			ast_pwm_read(priv->base, AST_PTCR_CTRL) |
+			AST_PTCR_CTRL_CLK_SRC, AST_PTCR_CTRL);
+	} else {
+		ast_pwm_write(priv->base,
+			ast_pwm_read(priv->base, AST_PTCR_CTRL) &
+			~AST_PTCR_CTRL_CLK_SRC, AST_PTCR_CTRL);
+	}
+}
+
+static void
+ast_set_pwm_clock_division_h(struct ast_pwm_controller_data *priv,
+		u8 pwm_type, u8 div_high)
+{
+	switch (pwm_type) {
+	case PWM_TYPE_M:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEM_H_MASK) |
+			(div_high << AST_PTCR_CLK_CTRL_TYPEM_H),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_N:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEN_H_MASK) |
+			(div_high << AST_PTCR_CLK_CTRL_TYPEN_H),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_O:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_EXT_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEO_H_MASK) |
+			(div_high << AST_PTCR_CLK_CTRL_TYPEO_H),
+			AST_PTCR_CLK_EXT_CTRL);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_clock_division_l(struct ast_pwm_controller_data *priv,
+		u8 pwm_type, u8 div_low)
+{
+	switch (pwm_type) {
+	case PWM_TYPE_M:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEM_L_MASK) |
+			(div_low << AST_PTCR_CLK_CTRL_TYPEM_L),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_N:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEN_L_MASK) |
+			(div_low << AST_PTCR_CLK_CTRL_TYPEN_L),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_O:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_EXT_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEO_L_MASK) |
+			(div_low << AST_PTCR_CLK_CTRL_TYPEO_L),
+			AST_PTCR_CLK_EXT_CTRL);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_clock_unit(struct ast_pwm_controller_data *priv, u8 pwm_type,
+		u8 unit)
+{
+	switch (pwm_type) {
+	case PWM_TYPE_M:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK) |
+			(unit << AST_PTCR_CLK_CTRL_TYPEM_UNIT),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_N:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK) |
+			(unit << AST_PTCR_CLK_CTRL_TYPEN_UNIT),
+			AST_PTCR_CLK_CTRL);
+		break;
+	case PWM_TYPE_O:
+		ast_pwm_write(priv->base,
+			(ast_pwm_read(priv->base, AST_PTCR_CLK_EXT_CTRL) &
+			~AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK) |
+			(unit << AST_PTCR_CLK_CTRL_TYPEO_UNIT),
+			AST_PTCR_CLK_EXT_CTRL);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_enable(struct ast_pwm_port_data *priv, u8 enable)
+{
+	u8 pwm_ch = priv->pwm_port;
+
+	switch (pwm_ch) {
+	case PWMA:
+		if (enable)
+			ast_pwm_write(priv->base,
+				ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) |
+				AST_PTCR_CTRL_PWMA_EN,
+				AST_PTCR_CTRL);
+		else
+			ast_pwm_write(priv->base,
+				ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) &
+				~AST_PTCR_CTRL_PWMA_EN,
+				AST_PTCR_CTRL);
+		break;
+	case PWMB:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) |
+				AST_PTCR_CTRL_PWMB_EN),
+				AST_PTCR_CTRL);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) &
+				~AST_PTCR_CTRL_PWMB_EN),
+				AST_PTCR_CTRL);
+		break;
+	case PWMC:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) |
+				AST_PTCR_CTRL_PWMC_EN),
+				AST_PTCR_CTRL);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) &
+				~AST_PTCR_CTRL_PWMC_EN),
+				AST_PTCR_CTRL);
+		break;
+	case PWMD:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) |
+				AST_PTCR_CTRL_PWMD_EN),
+				AST_PTCR_CTRL);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL) &
+				~AST_PTCR_CTRL_PWMD_EN),
+				AST_PTCR_CTRL);
+		break;
+	case PWME:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) |
+				AST_PTCR_CTRL_PWME_EN),
+				AST_PTCR_CTRL_EXT);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) &
+				~AST_PTCR_CTRL_PWME_EN),
+				AST_PTCR_CTRL_EXT);
+		break;
+	case PWMF:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) |
+				AST_PTCR_CTRL_PWMF_EN),
+				AST_PTCR_CTRL_EXT);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) &
+				~AST_PTCR_CTRL_PWMF_EN),
+				AST_PTCR_CTRL_EXT);
+		break;
+	case PWMG:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) |
+				AST_PTCR_CTRL_PWMG_EN),
+				AST_PTCR_CTRL_EXT);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) &
+				~AST_PTCR_CTRL_PWMG_EN),
+				AST_PTCR_CTRL_EXT);
+		break;
+	case PWMH:
+		if (enable)
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) |
+				AST_PTCR_CTRL_PWMH_EN),
+				AST_PTCR_CTRL_EXT);
+		else
+			ast_pwm_write(priv->base,
+				(ast_pwm_read(priv->base,
+				AST_PTCR_CTRL_EXT) &
+				~AST_PTCR_CTRL_PWMH_EN),
+				AST_PTCR_CTRL_EXT);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_type(struct ast_pwm_port_data *priv, u8 type)
+{
+	u32 tmp1, tmp2;
+	u8 pwm_ch = priv->pwm_port;
+
+	tmp1 = ast_pwm_read(priv->base, AST_PTCR_CTRL);
+	tmp2 = ast_pwm_read(priv->base, AST_PTCR_CTRL_EXT);
+
+	switch (pwm_ch) {
+	case PWMA:
+		tmp1 &= ~AST_PTCR_CTRL_SET_PWMA_TYPE_MASK;
+		tmp1 |= AST_PTCR_CTRL_SET_PWMA_TYPE(type);
+		ast_pwm_write(priv->base, tmp1, AST_PTCR_CTRL);
+
+		break;
+	case PWMB:
+		tmp1 &= ~AST_PTCR_CTRL_SET_PWMB_TYPE_MASK;
+		tmp1 |= AST_PTCR_CTRL_SET_PWMB_TYPE(type);
+		ast_pwm_write(priv->base, tmp1, AST_PTCR_CTRL);
+		break;
+	case PWMC:
+		tmp1 &= ~AST_PTCR_CTRL_SET_PWMC_TYPE_MASK;
+		tmp1 |= AST_PTCR_CTRL_SET_PWMC_TYPE(type);
+		ast_pwm_write(priv->base, tmp1, AST_PTCR_CTRL);
+		break;
+	case PWMD:
+		tmp1 &= ~AST_PTCR_CTRL_SET_PWMD_TYPE_MASK;
+		tmp1 |= AST_PTCR_CTRL_SET_PWMD_TYPE(type);
+		ast_pwm_write(priv->base, tmp1, AST_PTCR_CTRL);
+		break;
+	case PWME:
+		tmp2 &= ~AST_PTCR_CTRL_SET_PWME_TYPE_MASK;
+		tmp2 |= AST_PTCR_CTRL_SET_PWME_TYPE(type);
+		ast_pwm_write(priv->base, tmp2, AST_PTCR_CTRL_EXT);
+		break;
+	case PWMF:
+		tmp2 &= ~AST_PTCR_CTRL_SET_PWMF_TYPE_MASK;
+		tmp2 |= AST_PTCR_CTRL_SET_PWMF_TYPE(type);
+		ast_pwm_write(priv->base, tmp2, AST_PTCR_CTRL_EXT);
+		break;
+	case PWMG:
+		tmp2 &= ~AST_PTCR_CTRL_SET_PWMG_TYPE_MASK;
+		tmp2 |= AST_PTCR_CTRL_SET_PWMG_TYPE(type);
+		ast_pwm_write(priv->base, tmp2, AST_PTCR_CTRL_EXT);
+		break;
+	case PWMH:
+		tmp2 &= ~AST_PTCR_CTRL_SET_PWMH_TYPE_MASK;
+		tmp2 |= AST_PTCR_CTRL_SET_PWMH_TYPE(type);
+		ast_pwm_write(priv->base, tmp2, AST_PTCR_CTRL_EXT);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_duty_rising(struct ast_pwm_port_data *priv, u8 rising)
+{
+	u32 tmp = 0;
+	u8 pwm_ch = priv->pwm_port;
+
+	switch (pwm_ch) {
+	case PWMA:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY0_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_RISE_POINT_MASK;
+		tmp |= rising;
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY0_CTRL);
+		break;
+	case PWMB:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY0_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_RISE_POINT_MASK;
+		tmp |= (rising << DUTY_CTRL_PWM2_RISE_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY0_CTRL);
+		break;
+	case PWMC:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY1_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_RISE_POINT_MASK;
+		tmp |= rising;
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY1_CTRL);
+		break;
+	case PWMD:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY1_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_RISE_POINT_MASK;
+		tmp |= (rising << DUTY_CTRL_PWM2_RISE_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY1_CTRL);
+		break;
+	case PWME:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY2_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_RISE_POINT_MASK;
+		tmp |= rising;
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY2_CTRL);
+		break;
+	case PWMF:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY2_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_RISE_POINT_MASK;
+		tmp |= (rising << DUTY_CTRL_PWM2_RISE_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY2_CTRL);
+		break;
+	case PWMG:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY3_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_RISE_POINT_MASK;
+		tmp |= rising;
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY3_CTRL);
+		break;
+	case PWMH:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY3_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_RISE_POINT_MASK;
+		tmp |= (rising << DUTY_CTRL_PWM2_RISE_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY3_CTRL);
+		break;
+	}
+}
+
+static void
+ast_set_pwm_duty_falling(struct ast_pwm_port_data *priv, u8 falling)
+{
+	u32 tmp = 0;
+	u8 pwm_ch = priv->pwm_port;
+
+	switch (pwm_ch) {
+	case PWMA:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY0_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM1_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY0_CTRL);
+		break;
+	case PWMB:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY0_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM2_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY0_CTRL);
+		break;
+	case PWMC:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY1_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM1_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY1_CTRL);
+		break;
+	case PWMD:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY1_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM2_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY1_CTRL);
+		break;
+	case PWME:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY2_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM1_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY2_CTRL);
+		break;
+	case PWMF:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY2_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM2_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY2_CTRL);
+		break;
+	case PWMG:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY3_CTRL);
+		tmp &= ~DUTY_CTRL_PWM1_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM1_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY3_CTRL);
+		break;
+	case PWMH:
+		tmp = ast_pwm_read(priv->base, AST_PTCR_DUTY3_CTRL);
+		tmp &= ~DUTY_CTRL_PWM2_FALL_POINT_MASK;
+		tmp |= (falling << DUTY_CTRL_PWM2_FALL_POINT);
+		ast_pwm_write(priv->base, tmp, AST_PTCR_DUTY3_CTRL);
+		break;
+	}
+}
+
+static u8
+ast_get_pwm_clock_unit(struct ast_pwm_port_data *priv, u8 pwm_type)
+{
+	u8 tmp = 0;
+
+	switch (pwm_type) {
+	case PWM_TYPE_M:
+		tmp = (ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK) >>
+			AST_PTCR_CLK_CTRL_TYPEM_UNIT;
+		break;
+	case PWM_TYPE_N:
+		tmp = (ast_pwm_read(priv->base, AST_PTCR_CLK_CTRL) &
+			AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK) >>
+			AST_PTCR_CLK_CTRL_TYPEN_UNIT;
+		break;
+	case PWM_TYPE_O:
+		tmp = (ast_pwm_read(priv->base, AST_PTCR_CLK_EXT_CTRL) &
+			AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK) >>
+			AST_PTCR_CLK_CTRL_TYPEO_UNIT;
+		break;
+	}
+	return tmp;
+}
+
+static void
+ast_set_pwm_duty_cycle(struct ast_pwm_port_data *priv, u8 duty_cycle)
+{
+	u8 period;
+	u8 dc_time_on;
+
+	period = ast_get_pwm_clock_unit(priv, priv->pwm_type);
+	period += 1;
+
+	dc_time_on = (duty_cycle * period) / 100;
+	if (dc_time_on == 0) {
+		ast_set_pwm_enable(priv, 0);
+	} else {
+		if (dc_time_on == period) {
+			dc_time_on = 0;
+		}
+		ast_set_pwm_duty_rising(priv, 0);
+		ast_set_pwm_duty_falling(priv, dc_time_on);
+		ast_set_pwm_enable(priv, 1);
+	}
+}
+
+static ssize_t
+set_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
+		size_t count)
+{
+	struct ast_pwm_port_data *priv = dev_get_drvdata(dev);
+	u8 duty_cycle;
+	int ret;
+
+	ret = kstrtou8(buf, 10, &duty_cycle);
+	if (ret)
+		return -EINVAL;
+
+	if (duty_cycle < 0 || duty_cycle > 100)
+		return -EINVAL;
+
+	priv->pwm_duty_cycle = duty_cycle;
+	ast_set_pwm_duty_cycle(priv, duty_cycle);
+	return count;
+}
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct ast_pwm_port_data *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", priv->pwm_duty_cycle);
+}
+
+static SENSOR_DEVICE_ATTR(pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+
+static struct attribute *pwm_dev_attrs[] = {
+	&sensor_dev_attr_pwm.dev_attr.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(pwm_dev);
+
+static int
+aspeed_create_pwm_port(struct device *dev, struct device_node *child,
+		void __iomem *base)
+{
+	struct device *hwmon;
+	u8 val;
+	struct ast_pwm_port_data *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	hwmon = devm_hwmon_device_register_with_groups(dev, "pwm_port",
+		priv, pwm_dev_groups);
+	if (IS_ERR(hwmon)) {
+		dev_err(dev, "Failed to register hwmon device\n");
+		return PTR_ERR(hwmon);
+	}
+	priv->base = base;
+
+	of_property_read_u8(child, "pwm_port", &val);
+	priv->pwm_port = val;
+
+	of_property_read_u8(child, "pwm_enable", &val);
+	priv->pwm_enable = val;
+	ast_set_pwm_enable(priv, val);
+
+	of_property_read_u8(child, "pwm_type", &val);
+	priv->pwm_type = val;
+	ast_set_pwm_type(priv, val);
+
+	of_property_read_u8(child, "pwm_duty_cycle_percent", &val);
+	priv->pwm_duty_cycle = val;
+	ast_set_pwm_duty_cycle(priv, val);
+	return 0;
+}
+
+static int
+aspeed_ast2500_pwm_probe(struct platform_device *pdev)
+{
+	u32 buf[4];
+	struct device_node *np, *child;
+	struct resource *res;
+	u8 val;
+	int err;
+	struct ast_pwm_controller_data *priv;
+
+	np = pdev->dev.of_node;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(struct ast_pwm_controller_data),
+			GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		return -ENOENT;
+	}
+
+	priv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	of_property_read_u8(np, "clock_enable", &val);
+	ast_set_pwm_clock_enable(priv, val);
+	of_property_read_u8(np, "clock_source", &val);
+	ast_set_pwm_clock_source(priv, val);
+
+	of_property_read_u32_array(np, "typem_pwm_clock", buf, 4);
+	if (buf[0] == 1) {
+		ast_set_pwm_clock_division_l(priv, PWM_TYPE_M, buf[1]);
+		ast_set_pwm_clock_division_h(priv, PWM_TYPE_M, buf[2]);
+		ast_set_pwm_clock_unit(priv, PWM_TYPE_M, buf[3]);
+	}
+
+	of_property_read_u32_array(np, "typen_pwm_clock", buf, 4);
+	if (buf[0] == 1) {
+		ast_set_pwm_clock_division_l(priv, PWM_TYPE_N, buf[1]);
+		ast_set_pwm_clock_division_h(priv, PWM_TYPE_N, buf[2]);
+		ast_set_pwm_clock_unit(priv, PWM_TYPE_N, buf[3]);
+	}
+
+	of_property_read_u32_array(np, "typeo_pwm_clock", buf, 4);
+	if (buf[0] == 1) {
+		ast_set_pwm_clock_division_l(priv, PWM_TYPE_O, buf[1]);
+		ast_set_pwm_clock_division_h(priv, PWM_TYPE_O, buf[2]);
+		ast_set_pwm_clock_unit(priv, PWM_TYPE_O, buf[3]);
+	}
+
+	for_each_child_of_node(np, child) {
+		aspeed_create_pwm_port(&pdev->dev,
+				child, priv->base);
+		of_node_put(child);
+	}
+	of_node_put(np);
+	return 0;
+}
+
+static int
+aspeed_ast2500_pwm_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id of_pwm_match_table[] = {
+	{ .compatible = "aspeed,ast2500-pwm", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_pwm_match_table);
+
+static struct platform_driver aspeed_ast2500_pwm_driver = {
+	.probe		= aspeed_ast2500_pwm_probe,
+	.remove		= aspeed_ast2500_pwm_remove,
+	.driver		= {
+		.name	= "aspeed_ast2500_pwm",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_pwm_match_table,
+	},
+};
+
+module_platform_driver(aspeed_ast2500_pwm_driver);
+
+MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>");
+MODULE_DESCRIPTION("ASPEED AST2500 PWM device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/aspeed_ast2500_pwm.h b/drivers/hwmon/aspeed_ast2500_pwm.h
new file mode 100644
index 0000000..1986fd2
--- /dev/null
+++ b/drivers/hwmon/aspeed_ast2500_pwm.h
@@ -0,0 +1,128 @@
+/*
+ * ASPEED AST2500 PWM header file
+ * * Copyright (c) 2016 Google, Inc
+ *
+ * * 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.
+ *
+ */
+
+#ifndef __ASPEED_PWM_H
+#define __ASPEED_PWM_H __FILE__
+
+/* AST PWM & FAN Register Definition */
+#define AST_PTCR_CTRL			0x00
+#define AST_PTCR_CLK_CTRL		0x04
+#define AST_PTCR_DUTY0_CTRL		0x08
+#define AST_PTCR_DUTY1_CTRL		0x0c
+#define AST_PTCR_CTRL_EXT		0x40
+#define AST_PTCR_CLK_EXT_CTRL		0x44
+#define AST_PTCR_DUTY2_CTRL		0x48
+#define AST_PTCR_DUTY3_CTRL		0x4c
+
+/* COMMON Definition */
+#define PWM_TYPE_M	0x0
+#define PWM_TYPE_N	0x1
+#define PWM_TYPE_O	0x2
+
+#define PWMA	0x0
+#define PWMB	0x1
+#define PWMC	0x2
+#define PWMD	0x3
+#define PWME	0x4
+#define PWMF	0x5
+#define PWMG	0x6
+#define PWMH	0x7
+
+#define DUTY_CTRL_PWM2_FALL_POINT			(24)
+#define DUTY_CTRL_PWM2_FALL_POINT_MASK			(0xff<<24)
+#define DUTY_CTRL_PWM2_RISE_POINT			(16)
+#define DUTY_CTRL_PWM2_RISE_POINT_MASK			(0xff<<16)
+#define DUTY_CTRL_PWM1_FALL_POINT			(8)
+#define DUTY_CTRL_PWM1_FALL_POINT_MASK			(0xff<<8)
+#define DUTY_CTRL_PWM1_RISE_POINT			(0)
+#define DUTY_CTRL_PWM1_RISE_POINT_MASK			(0xff)
+
+/* AST_PTCR_CTRL : 0x00 - General Control Register */
+#define AST_PTCR_CTRL_SET_PWMD_TYPE(x)		((x & 0x1) << 15 | \
+						(x & 0x2) << 6)
+#define AST_PTCR_CTRL_SET_PWMD_TYPE_MASK	((0x1 << 7) | (0x1 << 15))
+
+#define AST_PTCR_CTRL_SET_PWMC_TYPE(x)		((x & 0x1) << 14 | \
+						(x & 0x2) << 5)
+#define AST_PTCR_CTRL_SET_PWMC_TYPE_MASK	((0x1 << 6) | (0x1 << 14))
+
+#define AST_PTCR_CTRL_SET_PWMB_TYPE(x)		((x & 0x1) << 13 | \
+						(x & 0x2) << 4)
+#define AST_PTCR_CTRL_SET_PWMB_TYPE_MASK	((0x1 << 5) | (0x1 << 13))
+
+#define AST_PTCR_CTRL_SET_PWMA_TYPE(x)		((x & 0x1) << 12 | \
+						(x & 0x2) << 3)
+#define AST_PTCR_CTRL_SET_PWMA_TYPE_MASK	((0x1 << 4) | (0x1 << 12))
+
+#define	AST_PTCR_CTRL_PWMD			(11)
+#define	AST_PTCR_CTRL_PWMD_EN		(0x1 << 11)
+#define	AST_PTCR_CTRL_PWMC			(10)
+#define	AST_PTCR_CTRL_PWMC_EN		(0x1 << 10)
+#define	AST_PTCR_CTRL_PWMB			(9)
+#define	AST_PTCR_CTRL_PWMB_EN		(0x1 << 9)
+#define	AST_PTCR_CTRL_PWMA			(8)
+#define	AST_PTCR_CTRL_PWMA_EN		(0x1 << 8)
+
+/*0:24Mhz, 1:MCLK */
+#define	AST_PTCR_CTRL_CLK_SRC		0x2
+#define	AST_PTCR_CTRL_CLK_EN		0x1
+
+/* AST_PTCR_CLK_CTRL : 0x04 - Clock Control Register */
+/* TYPE N */
+#define AST_PTCR_CLK_CTRL_TYPEN_UNIT			(24)
+#define AST_PTCR_CLK_CTRL_TYPEN_UNIT_MASK		(0xff << 24)
+#define AST_PTCR_CLK_CTRL_TYPEN_H			(20)
+#define AST_PTCR_CLK_CTRL_TYPEN_H_MASK			(0xf << 20)
+#define AST_PTCR_CLK_CTRL_TYPEN_L			(16)
+#define AST_PTCR_CLK_CTRL_TYPEN_L_MASK			(0xf << 16)
+/* TYPE M */
+#define AST_PTCR_CLK_CTRL_TYPEM_UNIT			(8)
+#define AST_PTCR_CLK_CTRL_TYPEM_UNIT_MASK		(0xff << 8)
+#define AST_PTCR_CLK_CTRL_TYPEM_H			(4)
+#define AST_PTCR_CLK_CTRL_TYPEM_H_MASK			(0xf << 4)
+#define AST_PTCR_CLK_CTRL_TYPEM_L			(0)
+#define AST_PTCR_CLK_CTRL_TYPEM_L_MASK			(0xf)
+
+/* AST_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */
+#define AST_PTCR_CTRL_SET_PWMH_TYPE(x)		((x & 0x1) << 15 | \
+						(x & 0x2) << 6)
+#define AST_PTCR_CTRL_SET_PWMH_TYPE_MASK	((0x1 << 7) | (0x1 << 15))
+
+#define AST_PTCR_CTRL_SET_PWMG_TYPE(x)		((x & 0x1) << 14 | \
+						(x & 0x2) << 5)
+#define AST_PTCR_CTRL_SET_PWMG_TYPE_MASK	((0x1 << 6) | (0x1 << 14))
+
+#define AST_PTCR_CTRL_SET_PWMF_TYPE(x)		((x & 0x1) << 13 | \
+						(x & 0x2) << 4)
+#define AST_PTCR_CTRL_SET_PWMF_TYPE_MASK	((0x1 << 5) | (0x1 << 13))
+
+#define AST_PTCR_CTRL_SET_PWME_TYPE(x)		((x & 0x1) << 12 | \
+						(x & 0x2) << 3)
+#define AST_PTCR_CTRL_SET_PWME_TYPE_MASK	((0x1 << 4) | (0x1 << 12))
+
+#define	AST_PTCR_CTRL_PWMH		(11)
+#define	AST_PTCR_CTRL_PWMH_EN		(0x1 << 11)
+#define	AST_PTCR_CTRL_PWMG		(10)
+#define	AST_PTCR_CTRL_PWMG_EN		(0x1 << 10)
+#define	AST_PTCR_CTRL_PWMF		(9)
+#define	AST_PTCR_CTRL_PWMF_EN		(0x1 << 9)
+#define	AST_PTCR_CTRL_PWME		(8)
+#define	AST_PTCR_CTRL_PWME_EN		(0x1 << 8)
+
+/* AST_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */
+/* TYPE O */
+#define AST_PTCR_CLK_CTRL_TYPEO_UNIT		(8)
+#define AST_PTCR_CLK_CTRL_TYPEO_UNIT_MASK	(0xff << 8)
+#define AST_PTCR_CLK_CTRL_TYPEO_H		(4)
+#define AST_PTCR_CLK_CTRL_TYPEO_H_MASK		(0xf << 4)
+#define AST_PTCR_CLK_CTRL_TYPEO_L		(0)
+#define AST_PTCR_CLK_CTRL_TYPEO_L_MASK		(0xf)
+
+#endif /* __ASPEED_PWM_H */
--
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH linux v2 1/3] devicetree: binding documentation update for ASPEED AST2500 PWM driver
From: Jaghathiswari Rankappagounder Natarajan @ 2016-11-09  2:11 UTC (permalink / raw)
  To: openbmc, joel; +Cc: Jaghathiswari Rankappagounder Natarajan
In-Reply-To: <1478657505-23109-1-git-send-email-jaghu@google.com>

Add binding documentation update for ASPEED AST2500 PWM driver.
The ASPEED AST2500 PWM driver supports 8 PWM output ports.
The parent node indicates a PWM controller and has options to:
provide register set information, provide pinctrl information,
enable PWM and Fan Tach clock, select clock source, provide settings for
three different PWM sources (type M, N and O).

Each sub node indicates a PWM output port and has options to:
enable PWM port, select the PWM source for the PWM port, provide
duty cycle values to be used at startup.

v2:
- Made binding documentation update as a separate patch.
- Included AST2500 in the description.
- Changed format to "aspeed,ast2500-pwm".
- Included explanation for types M ,N and O and calculation example to
  determine L, H, and period bits.

Signed-off-by: Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>
---
 .../bindings/hwmon/aspeed,ast2500-pwm.txt          | 116 +++++++++++++++++++++
 1 file changed, 116 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/aspeed,ast2500-pwm.txt

diff --git a/Documentation/devicetree/bindings/hwmon/aspeed,ast2500-pwm.txt b/Documentation/devicetree/bindings/hwmon/aspeed,ast2500-pwm.txt
new file mode 100644
index 0000000..2c3f2b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/aspeed,ast2500-pwm.txt
@@ -0,0 +1,116 @@
+ASPEED AST2500 PWM device driver
+
+The ASPEED AST2500 PWM controller can support 8 PWM outputs.
+
+Required properties:
+- #address-cells : should be 1.
+- #size-cells : should be 1.
+- reg : address and length of the register set for the device.
+- pinctrl-names : A pinctrl state named "default" must be defined.
+- pinctrl-0 : Phandle referencing pin configuration of the aspeed pwm ports.
+- compatible : should be "aspeed,ast2500-pwm".
+- clock_enable : option to enable PWM and fan tach clock. should be 1.
+  (D[0] in PTCR00).
+- clock_source : option for clock source selection. 0 indicates 24MHz clock
+  and 1 indicates MCLK (D[1] in PTCR00).
+- typem_pwm_clock : PWM types M, N and 0 are three types just to have three
+  independent PWM source. Each could be assigned to the 8 PWM channels
+  with it's own settings
+  This array contains 4 values.
+  The first value indicates if the values for type M PWM are valid.
+  If the first value is 1, then it indicates that the rest of the values
+  are valid. If it is 0, then invalid.
+  The second value indicates the type M PWM clock division L bit (D[3:0]
+  in PTCR04). (value 0 in D[3:0] indicates 1, value 1 in D[3:0] indicates 2,
+  value 2 in D[3:0] indicates 4, value 3 in D[3:0] indicates 6 and so on
+  with increments in multiples of two).
+  The third value indicates type M PWM clock divison H bit (D[7:4] in PTCR04).
+  (value 0 in D[7:4] indicates 1, value 1 in D[7:4] indicates 2,
+  value 2 in D[7:4] indicates 4, value 3 in D[7:4] indicates 8 and
+  so on with increments in powers of two).
+  The fourth value indicates type M PWM period bit (D[15:8] in PTCR04).
+  If type M is chosen and clock source is 24 MHz then:
+  The PWM base clock = 24Mhz / (type M clock division L bit *
+  type M clock division H bit).
+  The PWM frequency = The PWM base clock / (type M PWM period bit + 1)
+  If we plan to output 25Khz PWM frequency then we can use:
+  typem_pwm_clock = <1 5 0 95>
+  The PWM frequency = 24Mhz / (10 * 1  * (95 + 1)) = 25Khz
+- typen_pwm_clock : This array contains 4 values.
+  The first value indicates if the values for type N PWM are valid.
+  If the first value is 1, then it indicates that the rest of the values
+  are valid. If it is 0, then invalid.
+  The second value indicates the type N PWM clock division L bit (D[19:16]
+  in PTCR04).
+  The third value indicates type N PWM clock division H bit
+  (D[23:20] in PTCR04).
+  The fourth value indicates type N PWM period bit (D[31:24] in PTCR04).
+  Calculations similar as for type M.
+- typeo_pwm_clock : This array contains 4 values.
+  The first value indicates indicates if the values for type O PWM are valid.
+  If the first value is 1, then it indicates that the rest of the values
+  are valid. If it is 0, then invalid.
+  The second value indicates if the type O PWM clock division L bit
+  (D[3:0] in PTCR44).
+  The third value indicates type O PWM clock divison H bit (D[7:4] in PTCR44).
+  The fourth value indicates type O PWM period bit (D[15:8] in PTCR44).
+  Calculations similar as for type M.
+
+Each subnode represents a PWM output port.
+
+Subnode Format
+--------------
+Required properties:
+- pwm_port : Indicates the PWM port. Values 0 through 7 indicate PWM ports
+  A through H respectively.
+- pwm_enable : Option to enable the PWM port indicated above. 0 is enable
+  and 1 is disable.
+  D[8] in PTCR00 indicates enabling PWM port A,
+  D[9] in PTCR00 indicates enabling PWM port B,
+  D[10] in PTCR00 indicates enabling PWM port C,
+  D[11] in PTCR00 indicates enabling PWM port D,
+  D[8] in PTCR40 indicates enabling PWM port E,
+  D[9] in PTCR40 indicates enabling PWM port F,
+  D[10] in PTCR40 indicates enabling PWM port G,
+  D[11] in PTCR40 indicates enabling PWM port H.
+- pwm_type : Indicates the clock type for the PWM port. value 0 is type M
+  PWM clock. value 1 is type N PWM clock. value 2 is type O PWM clock.
+  D[12] in PTCR00 indicates type selection bit of PWM A port,
+  D[13] in PTCR00 indicates type selection bit of PWM B port,
+  D[14] in PTCR00 indicates type selection bit of PWM C port,
+  D[15] in PTCR00 indicates type selection bit of PWM D port,
+  D[12] in PTCR40 indicates type selection bit of PWM E port,
+  D[13] in PTCR40 indicates type selection bit of PWM F port,
+  D[14] in PTCR40 indicates type selection bit of PWM G port,
+  D[15] in PTCR40 indicates type selection bit of PWM H port.
+- pwm_duty_cycle_percent : duty cycle value.
+
+Examples:
+
+pwm: pwm-controller@1e786000 {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = <0x1E786000 0x78>;
+	pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+	 		&pinctrl_pwm2_default &pinctrl_pwm3_default>;
+	compatible = "aspeed,ast2500-pwm";
+	clock_enable = /bits/ 8 <0x01>;
+	clock_source = /bits/ 8 <0x00>;
+	typem_pwm_clock = <1 5 0 95>;
+	typen_pwm_clock = <0 0 0 0>;
+	typeo_pwm_clock = <0 0 0 0>;
+	pwm_port0 {
+		pwm_port = /bits/ 8 <0x00>;
+		pwm_enable = /bits/ 8 <0x01>;
+		pwm_type = /bits/ 8 <0x00>;
+		pwm_duty_cycle_percent = /bits/ 8 <0x5A>;
+	};
+	pwm_port1 {
+		pwm_port = /bits/ 8 <0x01>;
+		pwm_enable = /bits/ 8 <0x01>;
+		pwm_type = /bits/ 8 <0x00>;
+		pwm_duty_cycle_percent = /bits/ 8 <0x5A>;
+	};
+};
+
--
2.8.0.rc3.226.g39d4020

^ permalink raw reply related

* [PATCH linux v2 0/3] ASPEED AST2500 PWM support
From: Jaghathiswari Rankappagounder Natarajan @ 2016-11-09  2:11 UTC (permalink / raw)
  To: openbmc, joel; +Cc: Jaghathiswari Rankappagounder Natarajan

Support for ASPEED AST2500 PWM driver.
The AST2500 PWM controller can support 8 PWM output ports.
There can be three different PWM sources (Type M, N and O); each PWM
source can have different settings.
Each PWM output port can have one of the three different PWM sources.
There is a sysfs file through which the user can configure the duty cycle
for the particular PWM output port.
Added devicetree binding documentation for ast2500 pwm support.
Added support in Zaius platform for 4 PWM output ports since it has
four fans.

Tested on Zaius board and observed that when duty cycle is lowered
then the fan speed is lowered and when the duty cycle is increased
then the fan speed increases.

Tested on AST2500 EVB board and observed the PWM output pulses come
correctly based on the given settings using Logic Saleae Analyzer.

Jaghathiswari Rankappagounder Natarajan (3):
  devicetree: binding documentation update for ASPEED AST2500 PWM driver
  drivers: hwmon: ASPEED AST2500 PWM driver
  devicetree : Add support in Zaius platform for 4 PWM output ports

 .../bindings/hwmon/aspeed,ast2500-pwm.txt          | 116 ++++
 arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts         |  43 ++
 drivers/hwmon/Kconfig                              |   5 +
 drivers/hwmon/Makefile                             |   2 +-
 drivers/hwmon/aspeed_ast2500_pwm.c                 | 662 +++++++++++++++++++++
 drivers/hwmon/aspeed_ast2500_pwm.h                 | 128 ++++
 6 files changed, 955 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/aspeed,ast2500-pwm.txt
 create mode 100644 drivers/hwmon/aspeed_ast2500_pwm.c
 create mode 100644 drivers/hwmon/aspeed_ast2500_pwm.h

--
2.8.0.rc3.226.g39d4020

^ permalink raw reply

* Re: BUG: Hung task timeouts in for-4.10/dio
From: Jens Axboe @ 2016-11-09  2:11 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Damien Le Moal, Logan Gunthorpe, linux-block, Mike Snitzer
In-Reply-To: <20161109020517.GA759@lst.de>

On 11/08/2016 07:05 PM, Christoph Hellwig wrote:
> On Tue, Nov 08, 2016 at 07:02:52PM -0700, Jens Axboe wrote:
>> It smells like an accounting error. One thing that I don't like with the
>> current scheme is the implicit knowledge that certain flags imply sync
>> as well. If we clear any of those flags, then we screw up accounting at
>> the end.
>>
>> Does this make a difference?
>
> That looks interesting.  In the meantime I reproduced a similar
> hang, but only half-way through an xfstests run with a non-mq device.
> I'll see how far I can narrow it down and will give your patch a try as
> well.

It'd only trigger on non-mq, and the symptoms (and the bisect) point at
this being an accounting issue. Damien/Logan, would be great you could
try the debug patch I sent.

My non-mq drive on my test box has write through caching, which probably
explains why I haven't seen the issue.

-- 
Jens Axboe

^ permalink raw reply

* [meta-oe][PATCH] breakpad: Upgrade to latest
From: Khem Raj @ 2016-11-09  2:09 UTC (permalink / raw)
  To: openembedded-devel

Switch to using git
Gets aarch64 support

Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 .../breakpad/{breakpad_svn.bb => breakpad_git.bb}      | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
 rename meta-oe/recipes-devtools/breakpad/{breakpad_svn.bb => breakpad_git.bb} (87%)

diff --git a/meta-oe/recipes-devtools/breakpad/breakpad_svn.bb b/meta-oe/recipes-devtools/breakpad/breakpad_git.bb
similarity index 87%
rename from meta-oe/recipes-devtools/breakpad/breakpad_svn.bb
rename to meta-oe/recipes-devtools/breakpad/breakpad_git.bb
index b573ea5..6dc6500 100644
--- a/meta-oe/recipes-devtools/breakpad/breakpad_svn.bb
+++ b/meta-oe/recipes-devtools/breakpad/breakpad_git.bb
@@ -13,9 +13,21 @@ inherit autotools
 
 BBCLASSEXTEND = "native"
 
-SRCREV = "r1435"
-SRC_URI = "svn://google-breakpad.googlecode.com/svn;module=trunk;protocol=http"
-S = "${WORKDIR}/trunk"
+SRCREV_breakpad = "2f6cb866d615d6240a18c7535c994c6bb93b1ba5"
+SRCREV_glog = "d8cb47f77d1c31779f3ff890e1a5748483778d6a"
+SRCREV_gmock = "f7d03d2734759ee12b57d2dbcb695607d89e8e05"
+SRCREV_gtest = "ec44c6c1675c25b9827aacd08c02433cccde7780"
+SRCREV_protobuf = "cb6dd4ef5f82e41e06179dcd57d3b1d9246ad6ac"
+SRCREV_lss = "1549d20f6d3e7d66bb4e687c0ab9da42c2bff2ac"
+
+SRC_URI = "git://github.com/google/breakpad;name=breakpad \
+           git://github.com/google/glog.git;destsuffix=git/src/third_party/glog;name=glog \
+           git://github.com/google/googlemock.git;destsuffix=git/src/testing;name=gmock \
+           git://github.com/google/googletest.git;destsuffix=git/src/testing/gtest;name=gtest \
+           git://github.com/google/protobuf.git;destsuffix=git/src/third_party/protobuf/protobuf;name=protobuf \
+           git://chromium.googlesource.com/linux-syscall-support;protocol=https;destsuffix=git/src/third_party/lss;name=lss \
+"
+S = "${WORKDIR}/git"
 
 COMPATIBLE_MACHINE_powerpc = "(!.*ppc).*"
 
-- 
2.10.2



^ permalink raw reply related

* [PATCH 2/3] mtd: use min_t() to refactor mtd_ooblayout_{get,set}_bytes()
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen
In-Reply-To: <1478657290-9430-1-git-send-email-yamada.masahiro@socionext.com>

I hope this will make the code a little more readable.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/mtdcore.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index cf85f2b..ca6a89a 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1283,7 +1283,7 @@ static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(buf, oobbuf + oobregion.offset, cnt);
 		buf += cnt;
 		nbytes -= cnt;
@@ -1326,7 +1326,7 @@ static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(oobbuf + oobregion.offset, buf, cnt);
 		buf += cnt;
 		nbytes -= cnt;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/3] mtd: remove unneeded initializer in mtd_ooblayout_{get,set}_bytes()
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen
In-Reply-To: <1478657290-9430-1-git-send-email-yamada.masahiro@socionext.com>

There is no need to initialize oobregion and section since they will
be filled by mtd_ooblayout_find_region().

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/mtdcore.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index d46e4ad..cf85f2b 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1274,8 +1274,8 @@ static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
@@ -1317,8 +1317,8 @@ static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/3] mtd: remove unneeded initializer in mtd_ooblayout_count_bytes()
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen
In-Reply-To: <1478657290-9430-1-git-send-email-yamada.masahiro@socionext.com>

There is no need to initialize oobregion since it will be filled by
the iterator.

This function is called with mtd_ooblayout_free or mtd_ooblayout_ecc
for the iterator; both of them calls memset() to clear the oobregion.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/mtdcore.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index ca6a89a..ca661ce 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1354,7 +1354,7 @@ static int mtd_ooblayout_count_bytes(struct mtd_info *mtd,
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
+	struct mtd_oob_region oobregion;
 	int section = 0, ret, nbytes = 0;
 
 	while (1) {
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/3] mtd: remove unneeded initializer in mtd_ooblayout_{get, set}_bytes()
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen
In-Reply-To: <1478657290-9430-1-git-send-email-yamada.masahiro@socionext.com>

There is no need to initialize oobregion and section since they will
be filled by mtd_ooblayout_find_region().

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/mtdcore.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index d46e4ad..cf85f2b 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1274,8 +1274,8 @@ static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
@@ -1317,8 +1317,8 @@ static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
-- 
1.9.1

^ permalink raw reply related

* [PATCH 2/3] mtd: use min_t() to refactor mtd_ooblayout_{get, set}_bytes()
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen
In-Reply-To: <1478657290-9430-1-git-send-email-yamada.masahiro@socionext.com>

I hope this will make the code a little more readable.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/mtdcore.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index cf85f2b..ca6a89a 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1283,7 +1283,7 @@ static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(buf, oobbuf + oobregion.offset, cnt);
 		buf += cnt;
 		nbytes -= cnt;
@@ -1326,7 +1326,7 @@ static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(oobbuf + oobregion.offset, buf, cnt);
 		buf += cnt;
 		nbytes -= cnt;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 0/3] mtd: some minor cleanups for ooblayout APIs
From: Masahiro Yamada @ 2016-11-09  2:08 UTC (permalink / raw)
  To: linux-mtd
  Cc: Masahiro Yamada, linux-kernel, Boris Brezillon, Marek Vasut,
	Brian Norris, Richard Weinberger, David Woodhouse,
	Cyrille Pitchen

 - Remove unnecessary initializers
 - Use min_t() helper

Masahiro Yamada (3):
  mtd: remove unneeded initializer in mtd_ooblayout_{get,set}_bytes()
  mtd: use min_t() to refactor mtd_ooblayout_{get,set}_bytes()
  mtd: remove unneeded initializer in mtd_ooblayout_count_bytes()

 drivers/mtd/mtdcore.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

-- 
1.9.1

^ permalink raw reply

* RE: [PATCH v4] phy: rcar-gen3-usb2: add sysfs for usb role swap
From: Yoshihiro Shimoda @ 2016-11-09  2:06 UTC (permalink / raw)
  To: Peter Chen
  Cc: kishon@ti.com, gregkh@linuxfoundation.org, balbi@kernel.org,
	Peter.Chen@nxp.com, linux-kernel@vger.kernel.org,
	linux-usb@vger.kernel.org, linux-renesas-soc@vger.kernel.org
In-Reply-To: <20161109013924.GB27425@b29397-desktop>

Hi Peter-san,

> From: Peter Chen
> Sent: Wednesday, November 09, 2016 10:39 AM
> 
> On Tue, Nov 08, 2016 at 08:14:58PM +0900, Yoshihiro Shimoda wrote:
> > This patch adds sysfs "role" for usb role swap. This parameter can be
> > read and write. If you use this file as the following, you can swap
> > the usb role.
> >
> > For example:
> >  1) Connect a usb cable using 2 Salvator-x boards
> >  2) On A-Device (ID pin is low), you input the following command:
> >    # echo peripheral > /sys/devices/platform/soc/ee080200.usb-phy/role
> >  3) On B-Device (ID pin is high), you input the following command:
> >    # echo host > /sys/devices/platform/soc/ee080200.usb-phy/role
> >
> > Then, the A-device acts as a peripheral and the B-device acts as a host.
> > Please note that A-Device must input the following command if you
> > want the board to act as a host again. (even if you disconnect the usb
> > cable, since id state may be the same, the A-Device keeps to act as
> > peripheral.)
> >  # echo host > /sys/devices/platform/soc/ee080200.usb-phy/role
> >
> > Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > ---
> >  This patch is based on the latest linux-phy.git / next branch.
> >  (commit id = 7809cd2ce6abd4f431e4b14e6b1276a7cc842ac4)
> >
> >  Since this patch is related to usb, I added email addresses of Greg, Felipe,
> >  Peter and USB ML as CC. (This patch doesn't use USB OTG FSM though.)
> >
> >  Changes from v3:
> >   - Clean up redundant conditions in role_store().
> >
> >  Changes from v2:
> >   - Modify the sysfs file name to "role", and the argument is "host" or
> >     "peripheral". Peter suggested this. Thank you!
> >
> >  Changes from v1:
> >   - rebase the latest next branch.
> >
> >  .../ABI/testing/sysfs-platform-phy-rcar-gen3-usb2  |  15 +++
> >  drivers/phy/phy-rcar-gen3-usb2.c                   | 118 ++++++++++++++++++++-
> >  2 files changed, 132 insertions(+), 1 deletion(-)
> >  create mode 100644 Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
> >
> > diff --git a/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
> b/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
> > new file mode 100644
> > index 0000000..6212697
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
> > @@ -0,0 +1,15 @@
> > +What:		/sys/devices/platform/<phy-name>/role
> > +Date:		October 2016
> > +KernelVersion:	4.10
> > +Contact:	Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > +Description:
> > +		This file can be read and write.
> > +		The file can show/change the phy mode for role swap of usb.
> > +
> > +		Write the following strings to change the mode:
> > +		 "host" - switching mode from peripheral to host.
> > +		 "peripheral" - switching mode from host to peripheral.
> > +
> > +		Read the file, then it shows the following strings:
> > +		 "host" - The mode is host now.
> > +		 "peripheral" - The mode is peripheral now.
> > diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c
> > index 3d97ead..3f712b4 100644
> > --- a/drivers/phy/phy-rcar-gen3-usb2.c
> > +++ b/drivers/phy/phy-rcar-gen3-usb2.c
> > @@ -70,6 +70,7 @@
> >  #define USB2_LINECTRL1_DP_RPD		BIT(18)
> >  #define USB2_LINECTRL1_DMRPD_EN		BIT(17)
> >  #define USB2_LINECTRL1_DM_RPD		BIT(16)
> > +#define USB2_LINECTRL1_OPMODE_NODRV	BIT(6)
> >
> >  /* ADPCTRL */
> >  #define USB2_ADPCTRL_OTGSESSVLD		BIT(20)
> > @@ -161,6 +162,43 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch)
> >  	schedule_work(&ch->work);
> >  }
> >
> > +static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch)
> > +{
> > +	void __iomem *usb2_base = ch->base;
> > +	u32 val;
> > +
> > +	val = readl(usb2_base + USB2_LINECTRL1);
> > +	writel(val | USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
> > +
> > +	rcar_gen3_set_linectrl(ch, 1, 1);
> > +	rcar_gen3_set_host_mode(ch, 1);
> > +	rcar_gen3_enable_vbus_ctrl(ch, 0);
> > +
> > +	val = readl(usb2_base + USB2_LINECTRL1);
> > +	writel(val & ~USB2_LINECTRL1_OPMODE_NODRV, usb2_base + USB2_LINECTRL1);
> > +}
> > +
> > +static void rcar_gen3_init_for_a_peri(struct rcar_gen3_chan *ch)
> > +{
> > +	rcar_gen3_set_linectrl(ch, 0, 1);
> > +	rcar_gen3_set_host_mode(ch, 0);
> > +	rcar_gen3_enable_vbus_ctrl(ch, 1);
> > +}
> > +
> > +static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
> > +{
> > +	void __iomem *usb2_base = ch->base;
> > +	u32 val;
> > +
> > +	val = readl(usb2_base + USB2_OBINTEN);
> > +	writel(val & ~USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
> > +
> > +	rcar_gen3_enable_vbus_ctrl(ch, 0);
> > +	rcar_gen3_init_for_host(ch);
> > +
> > +	writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN);
> > +}
> > +
> >  static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch)
> >  {
> >  	return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG);
> > @@ -174,6 +212,65 @@ static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch)
> >  		rcar_gen3_init_for_peri(ch);
> >  }
> >
> > +static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
> > +{
> > +	return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
> > +}
> > +
> > +static ssize_t role_store(struct device *dev, struct device_attribute *attr,
> > +			  const char *buf, size_t count)
> > +{
> > +	struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
> > +	bool is_b_device, is_host, new_mode_is_host;
> > +
> > +	if (!ch->has_otg || !ch->phy->init_count)
> > +		return -EIO;
> > +
> > +	/*
> > +	 * is_b_device: true is B-Device. false is A-Device.
> > +	 * If {new_mode_}is_host: true is Host mode. false is Peripheral mode.
> > +	 */
> > +	is_b_device = rcar_gen3_check_id(ch);
> > +	is_host = rcar_gen3_is_host(ch);
> > +	if (!strncmp(buf, "host", strlen("host")))
> > +		new_mode_is_host = true;
> > +	else if (!strncmp(buf, "peripheral", strlen("peripheral")))
> > +		new_mode_is_host = false;
> > +	else
> > +		return -EINVAL;
> > +
> > +	/* If current and new mode is the same, this returns the error */
> > +	if (is_host == new_mode_is_host)
> > +		return -EINVAL;
> > +
> > +	if (new_mode_is_host) {		/* And is_host must be false */
> > +		if (!is_b_device)	/* A-Peripheral */
> > +			rcar_gen3_init_from_a_peri_to_a_host(ch);
> > +		if (is_b_device)	/* B-Peripheral */
> > +			rcar_gen3_init_for_b_host(ch);
> 
> Why not use if-else? The same to below.

Oops! Thank you for the comment. I will fix it and submit v5 patch soon.

> After fixing it, you can add my:
> Reviewed-by: Peter Chen <peter.chen@nxp.com>

Thank you very much for your review!

Best regards,
Yoshihiro Shimoda

> Peter
> 
> > +	} else {			/* And is_host must be true */
> > +		if (!is_b_device)	/* A-Host */
> > +			rcar_gen3_init_for_a_peri(ch);
> > +		if (is_b_device)	/* B-Host */
> > +			rcar_gen3_init_for_peri(ch);
> > +	}
> > +
> > +	return count;
> > +}
> > +
> > +static ssize_t role_show(struct device *dev, struct device_attribute *attr,
> > +			 char *buf)
> > +{
> > +	struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
> > +
> > +	if (!ch->has_otg || !ch->phy->init_count)
> > +		return -EIO;
> > +
> > +	return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
> > +							    "peripheral");
> > +}
> > +static DEVICE_ATTR_RW(role);
> > +
> >  static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
> >  {
> >  	void __iomem *usb2_base = ch->base;
> > @@ -351,21 +448,40 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
> >  		channel->vbus = NULL;
> >  	}
> >
> > +	platform_set_drvdata(pdev, channel);
> >  	phy_set_drvdata(channel->phy, channel);
> >
> >  	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > -	if (IS_ERR(provider))
> > +	if (IS_ERR(provider)) {
> >  		dev_err(dev, "Failed to register PHY provider\n");
> > +	} else if (channel->has_otg) {
> > +		int ret;
> > +
> > +		ret = device_create_file(dev, &dev_attr_role);
> > +		if (ret < 0)
> > +			return ret;
> > +	}
> >
> >  	return PTR_ERR_OR_ZERO(provider);
> >  }
> >
> > +static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
> > +{
> > +	struct rcar_gen3_chan *channel = platform_get_drvdata(pdev);
> > +
> > +	if (channel->has_otg)
> > +		device_remove_file(&pdev->dev, &dev_attr_role);
> > +
> > +	return 0;
> > +};
> > +
> >  static struct platform_driver rcar_gen3_phy_usb2_driver = {
> >  	.driver = {
> >  		.name		= "phy_rcar_gen3_usb2",
> >  		.of_match_table	= rcar_gen3_phy_usb2_match_table,
> >  	},
> >  	.probe	= rcar_gen3_phy_usb2_probe,
> > +	.remove = rcar_gen3_phy_usb2_remove,
> >  };
> >  module_platform_driver(rcar_gen3_phy_usb2_driver);
> >
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> 
> Best Regards,
> Peter Chen

^ permalink raw reply

* Re: btrfs support for filesystems >8TB on 32bit architectures
From: Marc MERLIN @ 2016-11-09  2:05 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: David Sterba, Hugo Mills, linux-btrfs
In-Reply-To: <f17792e9-498a-4ff0-2cc5-674ae10a01ad@cn.fujitsu.com>

On Wed, Nov 09, 2016 at 09:50:08AM +0800, Qu Wenruo wrote:
> Yeah, quite possible!
> 
> The truth is, current btrfs check only checks:
> 1) Metadata
>    while --check-data-csum option will check data, but still
>    follow the restriction 3).
> 2) Crossing reference of metadata (contents of metadata)
> 3) The first good mirror/backup
> 
> So quite a lot of problems can't be detected by btrfs check:
> 1) Data corruption (csum mismatch)
> 2) 2nd mirror corruption(DUP/RAID0/10) or parity error(RAID5/6)
> 
> For btrfsck to check all mirror and data, you could try out-of-tree 
> offline scrub patchset:
> https://github.com/adam900710/btrfs-progs/tree/fsck_scrub
> 
> Which implements the kernel scrub equivalent in btrfs-progs.

I see, thanks for the answer.
Note that this is very confusing to the end user.
If check --repair returns success, the filesystem should be clean.
Hopefully that patchset can be included in btrfs-progs

But sure enough, I'm seeing a lot of these:
BTRFS warning (device dm-6): checksum error at logical 269783986176 on dev /dev/mapper/crypt_bcache2, sector 529035384, root 16755, inode 1225897, offset 77824, length 4096, links 5 (path: magic/20150624/home/merlin/public_html/rig3/img/thumb800_302_1-Wire.jpg)

This is bad because I would expect check --repair to find them all and offer
to remove all the corrupted files after giving me a list of what I've lost,
or just recompute the checksum to be correct, know the file is now corrupted
but "clean" and I have the option of keeping them as is (ok-ish for a video
file) or restore them from backup.

The worst part with scrub is that I have to find all these files, and then
find all the snapshots they're in (maybe 10 or 20) and delete them all, and
then some of those snapshots are read only because they are btrfs send
source, so I need to destroy those snapshots and lose my btrfs send
relationship and am forced to recreate it (maybe 2 to 6 days of syncing over
a slow-ish link)

When data is corrupted, no solution is perfect, but hopefully check --repair
will indeed be able to restore the entire filesystem to a clean state, even
if some data must be lost in the process.

Thanks for considering.

Marc

-- 
"A mouse is a device used to point at the xterm you want to type in" - A.S.R.
Microsoft is to operating systems ....
                                      .... what McDonalds is to gourmet cooking
Home page: http://marc.merlins.org/  

^ permalink raw reply

* Re: BUG: Hung task timeouts in for-4.10/dio
From: Christoph Hellwig @ 2016-11-09  2:05 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Damien Le Moal, Christoph Hellwig, Logan Gunthorpe, linux-block,
	Mike Snitzer
In-Reply-To: <03cda65e-3a82-6ccd-861b-67a55888eb19@kernel.dk>

On Tue, Nov 08, 2016 at 07:02:52PM -0700, Jens Axboe wrote:
> It smells like an accounting error. One thing that I don't like with the
> current scheme is the implicit knowledge that certain flags imply sync
> as well. If we clear any of those flags, then we screw up accounting at
> the end.
>
> Does this make a difference?

That looks interesting.  In the meantime I reproduced a similar
hang, but only half-way through an xfstests run with a non-mq device.
I'll see how far I can narrow it down and will give your patch a try as
well.

^ permalink raw reply

* Re: 484611357c19 introduces arbitrary kernel write bug (root-only)
From: Josef Bacik @ 2016-11-09  2:02 UTC (permalink / raw)
  To: Jann Horn, Daniel Borkmann, Alexei Starovoitov, David S. Miller
  Cc: security, netdev
In-Reply-To: <CAG48ez0mP4xwv6vnKRJ+rcdXYyA1wGnCWsbkKUgWGSBbMtgFMw@mail.gmail.com>

On 11/08/2016 07:23 PM, Jann Horn wrote:
> In 484611357c19 (not in any stable kernel yet), functionality is
> introduced that allows root (and afaics nobody else, since nobody else
> is allowed to perform pointer arithmetic) to basically write to (and
> read from) arbitrary kernel memory. There are multiple bugs in the
> validation logic:
>
>  - A bitwise AND of values in the ranges [a,b] and [c,d] is assumed to
> always result in a value
>    >= a&b. However, for the combination of ranges [1,1] and [1,2],
> this calculates a minimum of 1
>    while actually, 1&2 is zero. This is the bug that my crasher
> (below) triggers.

Ugh crap.  I had this logic right before, but changed it to deal with the case 
of -value & -value which would make the min_value -value.  Instead if min and 
max are both positive then the min should be 0.  I'll fix this up and add a 
testcase, nice catch.

>  - a%b is assumed to always be smaller than b-1. However, for b==0,
> this will calculate an upper
>    limit of -1 while the values will actually always be zero.

Yup you're right.

>  - I'm not sure about this, but I think that, when only one end of the
> range is bounded, the logic will
>    incorrectly also treat the other end as a bounded, and because of
> the usage of bound
>    placeholders that are smaller than the actual maximum values, this
> could be used to perform
>    out-of-bounds accesses.

Yeah I think you're right, if we have register A min bounded at say 
REGISTER_MAX_VALUE, and then have register B not min bounded at all so we 
default to the REGISTER_MIN_VALUE we and did a add we could end up thinking the 
minimum was 0, when it could be anything.  I'll fix this as well.

Thanks for looking at all this, I'll get this fixed up in the morning with test 
cases and send it out,

Josef

^ 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.