linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Quota fixes and improvements
       [not found] <yes>
@ 2009-01-16 18:08 ` Jan Kara
  2009-01-16 18:08   ` [PATCH 01/11] quota: Improve locking Jan Kara
  2009-05-31 14:49 ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS tom.leiming
                   ` (33 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel

I'm sending for review patches fixing some bugs and implementing new quota
features. First four patches fix possible deadlocks in OCFS2 quotas. I plan
to send them to Linus next week if nobody objects. The remaining patches
are going to linux-next and I plan to merge them in the next merge window.

								Honza

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 01/11] quota: Improve locking
  2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
@ 2009-01-16 18:08   ` Jan Kara
  2009-01-16 18:08     ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
  2009-01-24  7:49     ` [PATCH 01/11] quota: Improve locking Andrew Morton
  0 siblings, 2 replies; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

We implement dqget() and dqput() that need neither dqonoff_mutex nor dqptr_sem.
Then move dqget() and dqput() calls so that they are not called from under
dqptr_sem. This is important because filesystem callbacks aren't called from
under dqptr_sem which used to cause *lots* of problems with lock ranking
(and with OCFS2 they became close to unsolvable).

The patch also removes two functions which were introduced solely because OCFS2
needed them to cope with the old locking scheme. As time showed, they were not
enough for OCFS2 anyway and it would be unnecessary work to adapt them to the
new locking scheme in which they aren't needed.  As a result OCFS2 needs the
following patch to compile properly with quotas.  Sorry to any bisecters which
hit this in advance.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/dquot.c               |  218 ++++++++++++++++++++++++++--------------------
 include/linux/quotaops.h |    2 -
 2 files changed, 122 insertions(+), 98 deletions(-)

diff --git a/fs/dquot.c b/fs/dquot.c
index 48c0571..bca3cac 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -87,14 +87,17 @@
 #define __DQUOT_PARANOIA
 
 /*
- * There are two quota SMP locks. dq_list_lock protects all lists with quotas
- * and quota formats and also dqstats structure containing statistics about the
- * lists. dq_data_lock protects data from dq_dqb and also mem_dqinfo structures
- * and also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
+ * There are three quota SMP locks. dq_list_lock protects all lists with quotas
+ * and quota formats, dqstats structure containing statistics about the lists
+ * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and
+ * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
  * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly
- * in inode_add_bytes() and inode_sub_bytes().
+ * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects
+ * modifications of quota state (on quotaon and quotaoff) and readers who care
+ * about latest values take it as well.
  *
- * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock
+ * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock,
+ *   dq_list_lock > dq_state_lock
  *
  * Note that some things (eg. sb pointer, type, id) doesn't change during
  * the life of the dquot structure and so needn't to be protected by a lock
@@ -103,12 +106,7 @@
  * operation is just reading pointers from inode (or not using them at all) the
  * read lock is enough. If pointers are altered function must hold write lock
  * (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed).  If operation is holding
- * reference to dquot in other way (e.g. quotactl ops) it must be guarded by
- * dqonoff_mutex.
- * This locking assures that:
- *   a) update/access to dquot pointers in inode is serialized
- *   b) everyone is guarded against invalidate_dquots()
+ * for altering the flag i_mutex is also needed).
  *
  * Each dquot has its dq_lock mutex. Locked dquots might not be referenced
  * from inodes (dquot_alloc_space() and such don't check the dq_lock).
@@ -122,10 +120,17 @@
  * Lock ordering (including related VFS locks) is the following:
  *   i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
  *   dqio_mutex
+ * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
+ * dqptr_sem. But filesystem has to count with the fact that functions such as
+ * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
+ * from inside a transaction to keep filesystem consistency after a crash. Also
+ * filesystems usually want to do some IO on dquot from ->mark_dirty which is
+ * called with dqptr_sem held.
  * i_mutex on quota files is special (it's below dqio_mutex)
  */
 
 static DEFINE_SPINLOCK(dq_list_lock);
+static DEFINE_SPINLOCK(dq_state_lock);
 DEFINE_SPINLOCK(dq_data_lock);
 
 static char *quotatypes[] = INITQFNAMES;
@@ -428,7 +433,7 @@ static inline void do_destroy_dquot(struct dquot *dquot)
  * quota is disabled and pointers from inodes removed so there cannot be new
  * quota users. There can still be some users of quotas due to inodes being
  * just deleted or pruned by prune_icache() (those are not attached to any
- * list). We have to wait for such users.
+ * list) or parallel quotactl call. We have to wait for such users.
  */
 static void invalidate_dquots(struct super_block *sb, int type)
 {
@@ -600,7 +605,6 @@ static struct shrinker dqcache_shrinker = {
 /*
  * Put reference to dquot
  * NOTE: If you change this function please check whether dqput_blocks() works right...
- * MUST be called with either dqptr_sem or dqonoff_mutex held
  */
 void dqput(struct dquot *dquot)
 {
@@ -697,36 +701,30 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
 }
 
 /*
- * Check whether dquot is in memory.
- * MUST be called with either dqptr_sem or dqonoff_mutex held
- */
-int dquot_is_cached(struct super_block *sb, unsigned int id, int type)
-{
-	unsigned int hashent = hashfn(sb, id, type);
-	int ret = 0;
-
-        if (!sb_has_quota_active(sb, type))
-		return 0;
-	spin_lock(&dq_list_lock);
-	if (find_dquot(hashent, sb, id, type) != NODQUOT)
-		ret = 1;
-	spin_unlock(&dq_list_lock);
-	return ret;
-}
-
-/*
  * Get reference to dquot
- * MUST be called with either dqptr_sem or dqonoff_mutex held
+ *
+ * Locking is slightly tricky here. We are guarded from parallel quotaoff()
+ * destroying our dquot by:
+ *   a) checking for quota flags under dq_list_lock and
+ *   b) getting a reference to dquot before we release dq_list_lock
  */
 struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
 {
 	unsigned int hashent = hashfn(sb, id, type);
-	struct dquot *dquot, *empty = NODQUOT;
+	struct dquot *dquot = NODQUOT, *empty = NODQUOT;
 
         if (!sb_has_quota_active(sb, type))
 		return NODQUOT;
 we_slept:
 	spin_lock(&dq_list_lock);
+	spin_lock(&dq_state_lock);
+	if (!sb_has_quota_active(sb, type)) {
+		spin_unlock(&dq_state_lock);
+		spin_unlock(&dq_list_lock);
+		goto out;
+	}
+	spin_unlock(&dq_state_lock);
+
 	if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) {
 		if (empty == NODQUOT) {
 			spin_unlock(&dq_list_lock);
@@ -735,6 +733,7 @@ we_slept:
 			goto we_slept;
 		}
 		dquot = empty;
+		empty = NODQUOT;
 		dquot->dq_id = id;
 		/* all dquots go on the inuse_list */
 		put_inuse(dquot);
@@ -749,8 +748,6 @@ we_slept:
 		dqstats.cache_hits++;
 		dqstats.lookups++;
 		spin_unlock(&dq_list_lock);
-		if (empty)
-			do_destroy_dquot(empty);
 	}
 	/* Wait for dq_lock - after this we know that either dquot_release() is already
 	 * finished or it will be canceled due to dq_count > 1 test */
@@ -758,11 +755,15 @@ we_slept:
 	/* Read the dquot and instantiate it (everything done only if needed) */
 	if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) {
 		dqput(dquot);
-		return NODQUOT;
+		dquot = NODQUOT;
+		goto out;
 	}
 #ifdef __DQUOT_PARANOIA
 	BUG_ON(!dquot->dq_sb);	/* Has somebody invalidated entry under us? */
 #endif
+out:
+	if (empty)
+		do_destroy_dquot(empty);
 
 	return dquot;
 }
@@ -1198,63 +1199,76 @@ static int info_bdq_free(struct dquot *dquot, qsize_t space)
 }
 /*
  *	Initialize quota pointers in inode
- *	Transaction must be started at entry
+ *	We do things in a bit complicated way but by that we avoid calling
+ *	dqget() and thus filesystem callbacks under dqptr_sem.
  */
 int dquot_initialize(struct inode *inode, int type)
 {
 	unsigned int id = 0;
 	int cnt, ret = 0;
+	struct dquot *got[MAXQUOTAS] = { NODQUOT, NODQUOT };
+	struct super_block *sb = inode->i_sb;
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
 	if (IS_NOQUOTA(inode))
 		return 0;
-	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
+	/* First get references to structures we might need. */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (type != -1 && cnt != type)
+			continue;
+		switch (cnt) {
+		case USRQUOTA:
+			id = inode->i_uid;
+			break;
+		case GRPQUOTA:
+			id = inode->i_gid;
+			break;
+		}
+		got[cnt] = dqget(sb, id, cnt);
+	}
+
+	down_write(&sb_dqopt(sb)->dqptr_sem);
 	/* Having dqptr_sem we know NOQUOTA flags can't be altered... */
 	if (IS_NOQUOTA(inode))
 		goto out_err;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (type != -1 && cnt != type)
 			continue;
+		/* Avoid races with quotaoff() */
+		if (!sb_has_quota_active(sb, cnt))
+			continue;
 		if (inode->i_dquot[cnt] == NODQUOT) {
-			switch (cnt) {
-				case USRQUOTA:
-					id = inode->i_uid;
-					break;
-				case GRPQUOTA:
-					id = inode->i_gid;
-					break;
-			}
-			inode->i_dquot[cnt] = dqget(inode->i_sb, id, cnt);
+			inode->i_dquot[cnt] = got[cnt];
+			got[cnt] = NODQUOT;
 		}
 	}
 out_err:
-	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	up_write(&sb_dqopt(sb)->dqptr_sem);
+	/* Drop unused references */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		dqput(got[cnt]);
 	return ret;
 }
 
 /*
  * 	Release all quotas referenced by inode
- *	Transaction must be started at an entry
  */
-int dquot_drop_locked(struct inode *inode)
+int dquot_drop(struct inode *inode)
 {
 	int cnt;
+	struct dquot *put[MAXQUOTAS];
 
+	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] != NODQUOT) {
-			dqput(inode->i_dquot[cnt]);
-			inode->i_dquot[cnt] = NODQUOT;
-		}
+		put[cnt] = inode->i_dquot[cnt];
+		inode->i_dquot[cnt] = NODQUOT;
 	}
-	return 0;
-}
-
-int dquot_drop(struct inode *inode)
-{
-	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	dquot_drop_locked(inode);
 	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		dqput(put[cnt]);
 	return 0;
 }
 
@@ -1470,8 +1484,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 	qsize_t space;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
-	int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
-	    chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
+	int cnt, ret = QUOTA_OK;
+	int chuid = iattr->ia_valid & ATTR_UID && inode->i_uid != iattr->ia_uid,
+	    chgid = iattr->ia_valid & ATTR_GID && inode->i_gid != iattr->ia_gid;
 	char warntype_to[MAXQUOTAS];
 	char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
 
@@ -1479,21 +1494,11 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
          * re-enter the quota code and are already holding the mutex */
 	if (IS_NOQUOTA(inode))
 		return QUOTA_OK;
-	/* Clear the arrays */
+	/* Initialize the arrays */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
+		transfer_from[cnt] = NODQUOT;
+		transfer_to[cnt] = NODQUOT;
 		warntype_to[cnt] = QUOTA_NL_NOWARN;
-	}
-	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	/* Now recheck reliably when holding dqptr_sem */
-	if (IS_NOQUOTA(inode)) {	/* File without quota accounting? */
-		up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		return QUOTA_OK;
-	}
-	/* First build the transfer_to list - here we can block on
-	 * reading/instantiating of dquots.  We know that the transaction for
-	 * us was already started so we don't violate lock ranking here */
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		switch (cnt) {
 			case USRQUOTA:
 				if (!chuid)
@@ -1507,6 +1512,13 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 				break;
 		}
 	}
+
+	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	/* Now recheck reliably when holding dqptr_sem */
+	if (IS_NOQUOTA(inode)) {	/* File without quota accounting? */
+		up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+		goto put_all;
+	}
 	spin_lock(&dq_data_lock);
 	space = inode_get_bytes(inode);
 	/* Build the transfer_from list and check the limits */
@@ -1517,7 +1529,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 		if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) ==
 		    NO_QUOTA || check_bdq(transfer_to[cnt], space, 0,
 		    warntype_to + cnt) == NO_QUOTA)
-			goto warn_put_all;
+			goto over_quota;
 	}
 
 	/*
@@ -1545,28 +1557,37 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 
 		inode->i_dquot[cnt] = transfer_to[cnt];
 	}
-	ret = QUOTA_OK;
-warn_put_all:
 	spin_unlock(&dq_data_lock);
+	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
 	/* Dirtify all the dquots - this can block when journalling */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (transfer_from[cnt])
 			mark_dquot_dirty(transfer_from[cnt]);
-		if (transfer_to[cnt])
+		if (transfer_to[cnt]) {
 			mark_dquot_dirty(transfer_to[cnt]);
+			/* The reference we got is transferred to the inode */
+			transfer_to[cnt] = NODQUOT;
+		}
 	}
+warn_put_all:
 	flush_warnings(transfer_to, warntype_to);
 	flush_warnings(transfer_from, warntype_from_inodes);
 	flush_warnings(transfer_from, warntype_from_space);
-	
+put_all:
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT)
-			dqput(transfer_from[cnt]);
-		if (ret == NO_QUOTA && transfer_to[cnt] != NODQUOT)
-			dqput(transfer_to[cnt]);
+		dqput(transfer_from[cnt]);
+		dqput(transfer_to[cnt]);
 	}
-	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return ret;
+over_quota:
+	spin_unlock(&dq_data_lock);
+	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	/* Clear dquot pointers we don't want to dqput() */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		transfer_from[cnt] = NODQUOT;
+	ret = NO_QUOTA;
+	goto warn_put_all;
 }
 
 /* Wrapper for transferring ownership of an inode */
@@ -1651,19 +1672,24 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
 			continue;
 
 		if (flags & DQUOT_SUSPENDED) {
+			spin_lock(&dq_state_lock);
 			dqopt->flags |=
 				dquot_state_flag(DQUOT_SUSPENDED, cnt);
+			spin_unlock(&dq_state_lock);
 		} else {
+			spin_lock(&dq_state_lock);
 			dqopt->flags &= ~dquot_state_flag(flags, cnt);
 			/* Turning off suspended quotas? */
 			if (!sb_has_quota_loaded(sb, cnt) &&
 			    sb_has_quota_suspended(sb, cnt)) {
 				dqopt->flags &=	~dquot_state_flag(
 							DQUOT_SUSPENDED, cnt);
+				spin_unlock(&dq_state_lock);
 				iput(dqopt->files[cnt]);
 				dqopt->files[cnt] = NULL;
 				continue;
 			}
+			spin_unlock(&dq_state_lock);
 		}
 
 		/* We still have to keep quota loaded? */
@@ -1830,7 +1856,9 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
 	}
 	mutex_unlock(&dqopt->dqio_mutex);
 	mutex_unlock(&inode->i_mutex);
+	spin_lock(&dq_state_lock);
 	dqopt->flags |= dquot_state_flag(flags, type);
+	spin_unlock(&dq_state_lock);
 
 	add_dquot_ref(sb, type);
 	mutex_unlock(&dqopt->dqonoff_mutex);
@@ -1872,9 +1900,11 @@ static int vfs_quota_on_remount(struct super_block *sb, int type)
 	}
 	inode = dqopt->files[type];
 	dqopt->files[type] = NULL;
+	spin_lock(&dq_state_lock);
 	flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
 						DQUOT_LIMITS_ENABLED, type);
 	dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, type);
+	spin_unlock(&dq_state_lock);
 	mutex_unlock(&dqopt->dqonoff_mutex);
 
 	flags = dquot_generic_flag(flags, type);
@@ -1952,7 +1982,9 @@ int vfs_quota_enable(struct inode *inode, int type, int format_id,
 			ret = -EBUSY;
 			goto out_lock;
 		}
+		spin_lock(&dq_state_lock);
 		sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
+		spin_unlock(&dq_state_lock);
 out_lock:
 		mutex_unlock(&dqopt->dqonoff_mutex);
 		return ret;
@@ -2039,14 +2071,12 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
 {
 	struct dquot *dquot;
 
-	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-	if (!(dquot = dqget(sb, id, type))) {
-		mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+	dquot = dqget(sb, id, type);
+	if (dquot == NODQUOT)
 		return -ESRCH;
-	}
 	do_get_dqblk(dquot, di);
 	dqput(dquot);
-	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+
 	return 0;
 }
 
@@ -2130,7 +2160,6 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
 	struct dquot *dquot;
 	int rc;
 
-	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
 	dquot = dqget(sb, id, type);
 	if (!dquot) {
 		rc = -ESRCH;
@@ -2139,7 +2168,6 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
 	rc = do_set_dqblk(dquot, di);
 	dqput(dquot);
 out:
-	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
 	return rc;
 }
 
@@ -2370,11 +2398,9 @@ EXPORT_SYMBOL(dquot_release);
 EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 EXPORT_SYMBOL(dquot_initialize);
 EXPORT_SYMBOL(dquot_drop);
-EXPORT_SYMBOL(dquot_drop_locked);
 EXPORT_SYMBOL(vfs_dq_drop);
 EXPORT_SYMBOL(dqget);
 EXPORT_SYMBOL(dqput);
-EXPORT_SYMBOL(dquot_is_cached);
 EXPORT_SYMBOL(dquot_alloc_space);
 EXPORT_SYMBOL(dquot_alloc_inode);
 EXPORT_SYMBOL(dquot_free_space);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 21b781a..0b35b3a 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -24,10 +24,8 @@ void sync_dquots(struct super_block *sb, int type);
 
 int dquot_initialize(struct inode *inode, int type);
 int dquot_drop(struct inode *inode);
-int dquot_drop_locked(struct inode *inode);
 struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
 void dqput(struct dquot *dquot);
-int dquot_is_cached(struct super_block *sb, unsigned int id, int type);
 int dquot_scan_active(struct super_block *sb,
 		      int (*fn)(struct dquot *dquot, unsigned long priv),
 		      unsigned long priv);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop()
  2009-01-16 18:08   ` [PATCH 01/11] quota: Improve locking Jan Kara
@ 2009-01-16 18:08     ` Jan Kara
  2009-01-16 18:08       ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
  2009-01-24  7:49     ` [PATCH 01/11] quota: Improve locking Andrew Morton
  1 sibling, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

Since ->acquire_dquot and ->release_dquot callbacks aren't called under
dqptr_sem anymore, we don't have to start a transaction and obtain locks
so early. So we can just remove all this complicated stuff.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ocfs2/quota_global.c |  169 +----------------------------------------------
 1 files changed, 2 insertions(+), 167 deletions(-)

diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 6aff8f2..f4efa89 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -810,171 +810,6 @@ out:
 	return status;
 }
 
-/* This is difficult. We have to lock quota inode and start transaction
- * in this function but we don't want to take the penalty of exlusive
- * quota file lock when we are just going to use cached structures. So
- * we just take read lock check whether we have dquot cached and if so,
- * we don't have to take the write lock... */
-static int ocfs2_dquot_initialize(struct inode *inode, int type)
-{
-	handle_t *handle = NULL;
-	int status = 0;
-	struct super_block *sb = inode->i_sb;
-	struct ocfs2_mem_dqinfo *oinfo;
-	int exclusive = 0;
-	int cnt;
-	qid_t id;
-
-	mlog_entry_void();
-
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (type != -1 && cnt != type)
-			continue;
-		if (!sb_has_quota_active(sb, cnt))
-			continue;
-		oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
-		status = ocfs2_lock_global_qf(oinfo, 0);
-		if (status < 0)
-			goto out;
-		/* This is just a performance optimization not a reliable test.
-		 * Since we hold an inode lock, noone can actually release
-		 * the structure until we are finished with initialization. */
-		if (inode->i_dquot[cnt] != NODQUOT) {
-			ocfs2_unlock_global_qf(oinfo, 0);
-			continue;
-		}
-		/* When we have inode lock, we know that no dquot_release() can
-		 * run and thus we can safely check whether we need to
-		 * read+modify global file to get quota information or whether
-		 * our node already has it. */
-		if (cnt == USRQUOTA)
-			id = inode->i_uid;
-		else if (cnt == GRPQUOTA)
-			id = inode->i_gid;
-		else
-			BUG();
-		/* Obtain exclusion from quota off... */
-		down_write(&sb_dqopt(sb)->dqptr_sem);
-		exclusive = !dquot_is_cached(sb, id, cnt);
-		up_write(&sb_dqopt(sb)->dqptr_sem);
-		if (exclusive) {
-			status = ocfs2_lock_global_qf(oinfo, 1);
-			if (status < 0) {
-				exclusive = 0;
-				mlog_errno(status);
-				goto out_ilock;
-			}
-			handle = ocfs2_start_trans(OCFS2_SB(sb),
-					ocfs2_calc_qinit_credits(sb, cnt));
-			if (IS_ERR(handle)) {
-				status = PTR_ERR(handle);
-				mlog_errno(status);
-				goto out_ilock;
-			}
-		}
-		dquot_initialize(inode, cnt);
-		if (exclusive) {
-			ocfs2_commit_trans(OCFS2_SB(sb), handle);
-			ocfs2_unlock_global_qf(oinfo, 1);
-		}
-		ocfs2_unlock_global_qf(oinfo, 0);
-	}
-	mlog_exit(0);
-	return 0;
-out_ilock:
-	if (exclusive)
-		ocfs2_unlock_global_qf(oinfo, 1);
-	ocfs2_unlock_global_qf(oinfo, 0);
-out:
-	mlog_exit(status);
-	return status;
-}
-
-static int ocfs2_dquot_drop_slow(struct inode *inode)
-{
-	int status = 0;
-	int cnt;
-	int got_lock[MAXQUOTAS] = {0, 0};
-	handle_t *handle;
-	struct super_block *sb = inode->i_sb;
-	struct ocfs2_mem_dqinfo *oinfo;
-
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (!sb_has_quota_active(sb, cnt))
-			continue;
-		oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
-		status = ocfs2_lock_global_qf(oinfo, 1);
-		if (status < 0)
-			goto out;
-		got_lock[cnt] = 1;
-	}
-	handle = ocfs2_start_trans(OCFS2_SB(sb),
-			ocfs2_calc_qinit_credits(sb, USRQUOTA) +
-			ocfs2_calc_qinit_credits(sb, GRPQUOTA));
-	if (IS_ERR(handle)) {
-		status = PTR_ERR(handle);
-		mlog_errno(status);
-		goto out;
-	}
-	dquot_drop(inode);
-	ocfs2_commit_trans(OCFS2_SB(sb), handle);
-out:
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-		if (got_lock[cnt]) {
-			oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
-			ocfs2_unlock_global_qf(oinfo, 1);
-		}
-	return status;
-}
-
-/* See the comment before ocfs2_dquot_initialize. */
-static int ocfs2_dquot_drop(struct inode *inode)
-{
-	int status = 0;
-	struct super_block *sb = inode->i_sb;
-	struct ocfs2_mem_dqinfo *oinfo;
-	int exclusive = 0;
-	int cnt;
-	int got_lock[MAXQUOTAS] = {0, 0};
-
-	mlog_entry_void();
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (!sb_has_quota_active(sb, cnt))
-			continue;
-		oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
-		status = ocfs2_lock_global_qf(oinfo, 0);
-		if (status < 0)
-			goto out;
-		got_lock[cnt] = 1;
-	}
-	/* Lock against anyone releasing references so that when when we check
-	 * we know we are not going to be last ones to release dquot */
-	down_write(&sb_dqopt(sb)->dqptr_sem);
-	/* Urgh, this is a terrible hack :( */
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] != NODQUOT &&
-		    atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) {
-			exclusive = 1;
-			break;
-		}
-	}
-	if (!exclusive)
-		dquot_drop_locked(inode);
-	up_write(&sb_dqopt(sb)->dqptr_sem);
-out:
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-		if (got_lock[cnt]) {
-			oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
-			ocfs2_unlock_global_qf(oinfo, 0);
-		}
-	/* In case we bailed out because we had to do expensive locking
-	 * do it now... */
-	if (exclusive)
-		status = ocfs2_dquot_drop_slow(inode);
-	mlog_exit(status);
-	return status;
-}
-
 static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
 {
 	struct ocfs2_dquot *dquot =
@@ -991,8 +826,8 @@ static void ocfs2_destroy_dquot(struct dquot *dquot)
 }
 
 struct dquot_operations ocfs2_quota_operations = {
-	.initialize	= ocfs2_dquot_initialize,
-	.drop		= ocfs2_dquot_drop,
+	.initialize	= dquot_initialize,
+	.drop		= dquot_drop,
 	.alloc_space	= dquot_alloc_space,
 	.alloc_inode	= dquot_alloc_inode,
 	.free_space	= dquot_free_space,
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq
  2009-01-16 18:08     ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
@ 2009-01-16 18:08       ` Jan Kara
  2009-01-16 18:08         ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

Dropping of last reference to dentry lock is a complicated operation involving
dropping of reference to inode. This can get complicated and quota code in
particular needs to obtain some quota locks which leads to potential deadlock.
Thus we defer dropping of inode reference to ocfs2_wq.

Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Mark Fasheh <mfasheh@suse.de>
---
 fs/ocfs2/dcache.c |   42 +++++++++++++++++++++++++++++++++++++++---
 fs/ocfs2/dcache.h |    9 ++++++++-
 fs/ocfs2/ocfs2.h  |    6 ++++++
 fs/ocfs2/super.c  |    3 +++
 4 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index b1cc7c3..e9d7c20 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -38,6 +38,7 @@
 #include "dlmglue.h"
 #include "file.h"
 #include "inode.h"
+#include "super.h"
 
 
 static int ocfs2_dentry_revalidate(struct dentry *dentry,
@@ -294,6 +295,34 @@ out_attach:
 	return ret;
 }
 
+static DEFINE_SPINLOCK(dentry_list_lock);
+
+/* We limit the number of dentry locks to drop in one go. We have
+ * this limit so that we don't starve other users of ocfs2_wq. */
+#define DL_INODE_DROP_COUNT 64
+
+/* Drop inode references from dentry locks */
+void ocfs2_drop_dl_inodes(struct work_struct *work)
+{
+	struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
+					       dentry_lock_work);
+	struct ocfs2_dentry_lock *dl;
+	int drop_count = DL_INODE_DROP_COUNT;
+
+	spin_lock(&dentry_list_lock);
+	while (osb->dentry_lock_list && drop_count--) {
+		dl = osb->dentry_lock_list;
+		osb->dentry_lock_list = dl->dl_next;
+		spin_unlock(&dentry_list_lock);
+		iput(dl->dl_inode);
+		kfree(dl);
+		spin_lock(&dentry_list_lock);
+	}
+	if (osb->dentry_lock_list)
+		queue_work(ocfs2_wq, &osb->dentry_lock_work);
+	spin_unlock(&dentry_list_lock);
+}
+
 /*
  * ocfs2_dentry_iput() and friends.
  *
@@ -318,16 +347,23 @@ out_attach:
 static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
 				   struct ocfs2_dentry_lock *dl)
 {
-	iput(dl->dl_inode);
 	ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
 	ocfs2_lock_res_free(&dl->dl_lockres);
-	kfree(dl);
+
+	/* We leave dropping of inode reference to ocfs2_wq as that can
+	 * possibly lead to inode deletion which gets tricky */
+	spin_lock(&dentry_list_lock);
+	if (!osb->dentry_lock_list)
+		queue_work(ocfs2_wq, &osb->dentry_lock_work);
+	dl->dl_next = osb->dentry_lock_list;
+	osb->dentry_lock_list = dl;
+	spin_unlock(&dentry_list_lock);
 }
 
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
 			   struct ocfs2_dentry_lock *dl)
 {
-	int unlock = 0;
+	int unlock;
 
 	BUG_ON(dl->dl_count == 0);
 
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index c091c34..d06e16c 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -29,8 +29,13 @@
 extern struct dentry_operations ocfs2_dentry_ops;
 
 struct ocfs2_dentry_lock {
+	/* Use count of dentry lock */
 	unsigned int		dl_count;
-	u64			dl_parent_blkno;
+	union {
+		/* Linked list of dentry locks to release */
+		struct ocfs2_dentry_lock *dl_next;
+		u64			dl_parent_blkno;
+	};
 
 	/*
 	 * The ocfs2_dentry_lock keeps an inode reference until
@@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
 			   struct ocfs2_dentry_lock *dl);
 
+void ocfs2_drop_dl_inodes(struct work_struct *work);
+
 struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
 				      int skip_unhashed);
 
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index ad5c24a..0773841 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -210,6 +210,7 @@ struct ocfs2_journal;
 struct ocfs2_slot_info;
 struct ocfs2_recovery_map;
 struct ocfs2_quota_recovery;
+struct ocfs2_dentry_lock;
 struct ocfs2_super
 {
 	struct task_struct *commit_task;
@@ -325,6 +326,11 @@ struct ocfs2_super
 	struct list_head blocked_lock_list;
 	unsigned long blocked_lock_count;
 
+	/* List of dentry locks to release. Anyone can add locks to
+	 * the list, ocfs2_wq processes the list  */
+	struct ocfs2_dentry_lock *dentry_lock_list;
+	struct work_struct dentry_lock_work;
+
 	wait_queue_head_t		osb_mount_event;
 
 	/* Truncate log info */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 43ed113..b1cb38f 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
 	journal->j_state = OCFS2_JOURNAL_FREE;
 
+	INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
+	osb->dentry_lock_list = NULL;
+
 	/* get some pseudo constants for clustersize bits */
 	osb->s_clustersize_bits =
 		le32_to_cpu(di->id2.i_super.s_clustersize_bits);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot()
  2009-01-16 18:08       ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
@ 2009-01-16 18:08         ` Jan Kara
  2009-01-16 18:08           ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

It could happen that some limit has been set via quotactl() and in parallel
->mark_dirty() is called from another thread doing e.g. dquot_alloc_space(). In
such case ocfs2_write_dquot() must not try to sync the dquot because that needs
global quota lock but that ranks above transaction start.

Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Mark Fasheh <mfasheh@suse.de>
---
 fs/ocfs2/quota_global.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index f4efa89..1ed0f7c 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
 	if (dquot->dq_flags & mask)
 		sync = 1;
 	spin_unlock(&dq_data_lock);
-	if (!sync) {
+	/* This is a slight hack but we can't afford getting global quota
+	 * lock if we already have a transaction started. */
+	if (!sync || journal_current_handle()) {
 		status = ocfs2_write_dquot(dquot);
 		goto out;
 	}
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 05/11] quota: Add quota reservation support
  2009-01-16 18:08         ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
@ 2009-01-16 18:08           ` Jan Kara
  2009-01-16 18:08             ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara

From: Mingming Cao <cmm@us.ibm.com>

Delayed allocation defers the block allocation at the dirty pages
flush-out time, doing quota charge/check at that time is too late.
But we can't charge the quota blocks until blocks are really allocated,
otherwise users could get overcharged after reboot from system crash.

This patch adds quota reservation for delayed allocation. Quota blocks
are reserved in memory, inode and quota won't gets dirtied until later
block allocation time.

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/dquot.c               |  117 +++++++++++++++++++++++++++++++++------------
 include/linux/quota.h    |    3 +
 include/linux/quotaops.h |   21 ++++++++
 3 files changed, 110 insertions(+), 31 deletions(-)

diff --git a/fs/dquot.c b/fs/dquot.c
index bca3cac..9b1c4d3 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -899,6 +899,11 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
 	dquot->dq_dqb.dqb_curspace += number;
 }
 
+static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
+{
+	dquot->dq_dqb.dqb_rsvspace += number;
+}
+
 static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
 {
 	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1068,7 +1073,11 @@ err_out:
 	kfree_skb(skb);
 }
 #endif
-
+/*
+ * Write warnings to the console and send warning messages over netlink.
+ *
+ * Note that this function can sleep.
+ */
 static inline void flush_warnings(struct dquot * const *dquots, char *warntype)
 {
 	int i;
@@ -1129,13 +1138,18 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
 /* needs dq_data_lock */
 static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
 {
+	qsize_t tspace;
+
 	*warntype = QUOTA_NL_NOWARN;
 	if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
 	    test_bit(DQ_FAKE_B, &dquot->dq_flags))
 		return QUOTA_OK;
 
+	tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace
+		+ space;
+
 	if (dquot->dq_dqb.dqb_bhardlimit &&
-	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
+	    tspace > dquot->dq_dqb.dqb_bhardlimit &&
             !ignore_hardlimit(dquot)) {
 		if (!prealloc)
 			*warntype = QUOTA_NL_BHARDWARN;
@@ -1143,7 +1157,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
 	}
 
 	if (dquot->dq_dqb.dqb_bsoftlimit &&
-	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+	    tspace > dquot->dq_dqb.dqb_bsoftlimit &&
 	    dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
             !ignore_hardlimit(dquot)) {
 		if (!prealloc)
@@ -1152,7 +1166,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
 	}
 
 	if (dquot->dq_dqb.dqb_bsoftlimit &&
-	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+	    tspace > dquot->dq_dqb.dqb_bsoftlimit &&
 	    dquot->dq_dqb.dqb_btime == 0) {
 		if (!prealloc) {
 			*warntype = QUOTA_NL_BSOFTWARN;
@@ -1306,51 +1320,92 @@ void vfs_dq_drop(struct inode *inode)
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+int __dquot_alloc_space(struct inode *inode, qsize_t number,
+			int warn, int reserve)
 {
-	int cnt, ret = NO_QUOTA;
+	int cnt, ret = QUOTA_OK;
 	char warntype[MAXQUOTAS];
 
-	/* First test before acquiring mutex - solves deadlocks when we
-         * re-enter the quota code and are already holding the mutex */
-	if (IS_NOQUOTA(inode)) {
-out_add:
-		inode_add_bytes(inode, number);
-		return QUOTA_OK;
-	}
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = QUOTA_NL_NOWARN;
 
-	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode)) {	/* Now we can do reliable test... */
-		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		goto out_add;
-	}
 	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
-			goto warn_put_all;
+		if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
+		    == NO_QUOTA) {
+			ret = NO_QUOTA;
+			goto out_unlock;
+		}
 	}
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		dquot_incr_space(inode->i_dquot[cnt], number);
+		if (reserve)
+			dquot_resv_space(inode->i_dquot[cnt], number);
+		else
+			dquot_incr_space(inode->i_dquot[cnt], number);
 	}
-	inode_add_bytes(inode, number);
-	ret = QUOTA_OK;
-warn_put_all:
+	if (!reserve)
+		inode_add_bytes(inode, number);
+out_unlock:
 	spin_unlock(&dq_data_lock);
-	if (ret == QUOTA_OK)
-		/* Dirtify all the dquots - this can block when journalling */
-		for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-			if (inode->i_dquot[cnt])
-				mark_dquot_dirty(inode->i_dquot[cnt]);
 	flush_warnings(inode->i_dquot, warntype);
+	return ret;
+}
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+{
+	int cnt, ret = QUOTA_OK;
+
+	/*
+	 * First test before acquiring mutex - solves deadlocks when we
+	 * re-enter the quota code and are already holding the mutex
+	 */
+	if (IS_NOQUOTA(inode)) {
+		inode_add_bytes(inode, number);
+		goto out;
+	}
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode)) {
+		inode_add_bytes(inode, number);
+		goto out_unlock;
+	}
+
+	ret = __dquot_alloc_space(inode, number, warn, 0);
+	if (ret == NO_QUOTA)
+		goto out_unlock;
+
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt])
+			mark_dquot_dirty(inode->i_dquot[cnt]);
+out_unlock:
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+	return ret;
+}
+
+int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
+{
+	int ret = QUOTA_OK;
+
+	if (IS_NOQUOTA(inode))
+		goto out;
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode))
+		goto out_unlock;
+
+	ret = __dquot_alloc_space(inode, number, warn, 1);
+out_unlock:
+	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
 	return ret;
 }
+EXPORT_SYMBOL(dquot_reserve_space);
 
 /*
  * This operation can block, but only after everything is updated
@@ -2057,7 +2112,7 @@ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
 	spin_lock(&dq_data_lock);
 	di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
 	di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
-	di->dqb_curspace = dm->dqb_curspace;
+	di->dqb_curspace = dm->dqb_curspace + dm->dqb_rsvspace;
 	di->dqb_ihardlimit = dm->dqb_ihardlimit;
 	di->dqb_isoftlimit = dm->dqb_isoftlimit;
 	di->dqb_curinodes = dm->dqb_curinodes;
@@ -2097,7 +2152,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
 
 	spin_lock(&dq_data_lock);
 	if (di->dqb_valid & QIF_SPACE) {
-		dm->dqb_curspace = di->dqb_curspace;
+		dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
 		check_blim = 1;
 		__set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
 	}
diff --git a/include/linux/quota.h b/include/linux/quota.h
index d72d5d8..54b837f 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -198,6 +198,7 @@ struct mem_dqblk {
 	qsize_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
 	qsize_t dqb_bsoftlimit;	/* preferred limit on disk blks */
 	qsize_t dqb_curspace;	/* current used space */
+	qsize_t dqb_rsvspace;   /* current reserved space for delalloc*/
 	qsize_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
 	qsize_t dqb_isoftlimit;	/* preferred inode limit */
 	qsize_t dqb_curinodes;	/* current # allocated inodes */
@@ -308,6 +309,8 @@ struct dquot_operations {
 	int (*release_dquot) (struct dquot *);		/* Quota is going to be deleted from disk */
 	int (*mark_dirty) (struct dquot *);		/* Dquot is marked dirty */
 	int (*write_info) (struct super_block *, int);	/* Write of quota "superblock" */
+	/* reserve quota for delayed block allocation */
+	int (*reserve_space) (struct inode *, qsize_t, int);
 };
 
 /* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 0b35b3a..3e3a0d2 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -183,6 +183,16 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
 	return ret;
 }
 
+static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
+{
+	if (sb_any_quota_active(inode->i_sb)) {
+		/* Used space is updated in alloc_space() */
+		if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA)
+			return 1;
+	}
+	return 0;
+}
+
 static inline int vfs_dq_alloc_inode(struct inode *inode)
 {
 	if (sb_any_quota_active(inode->i_sb)) {
@@ -339,6 +349,11 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
 	return 0;
 }
 
+static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
+{
+	return 0;
+}
+
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
 	inode_sub_bytes(inode, nr);
@@ -376,6 +391,12 @@ static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
 			nr << inode->i_sb->s_blocksize_bits);
 }
 
+static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
+{
+	return vfs_dq_reserve_space(inode,
+			nr << inode->i_blkbits);
+}
+
 static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
 {
 	vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 06/11] quota: Add quota reservation claim and released operations
  2009-01-16 18:08           ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
@ 2009-01-16 18:08             ` Jan Kara
  2009-01-16 18:08               ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara

From: Mingming Cao <cmm@us.ibm.com>

Reserved quota will be claimed at the block allocation time. Over-booked
quota could be returned back with the release callback function.

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/dquot.c               |  110 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/quota.h    |    6 +++
 include/linux/quotaops.h |   53 ++++++++++++++++++++++
 3 files changed, 165 insertions(+), 4 deletions(-)

diff --git a/fs/dquot.c b/fs/dquot.c
index 9b1c4d3..2916f91 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -904,6 +904,23 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
 	dquot->dq_dqb.dqb_rsvspace += number;
 }
 
+/*
+ * Claim reserved quota space
+ */
+static void dquot_claim_reserved_space(struct dquot *dquot,
+						qsize_t number)
+{
+	WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
+	dquot->dq_dqb.dqb_curspace += number;
+	dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
+static inline
+void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
+{
+	dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
 static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
 {
 	if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1452,6 +1469,72 @@ warn_put_all:
 	return ret;
 }
 
+int dquot_claim_space(struct inode *inode, qsize_t number)
+{
+	int cnt;
+	int ret = QUOTA_OK;
+
+	if (IS_NOQUOTA(inode)) {
+		inode_add_bytes(inode, number);
+		goto out;
+	}
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode))	{
+		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+		inode_add_bytes(inode, number);
+		goto out;
+	}
+
+	spin_lock(&dq_data_lock);
+	/* Claim reserved quotas to allocated quotas */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt] != NODQUOT)
+			dquot_claim_reserved_space(inode->i_dquot[cnt],
+							number);
+	}
+	/* Update inode bytes */
+	inode_add_bytes(inode, number);
+	spin_unlock(&dq_data_lock);
+	/* Dirtify all the dquots - this can block when journalling */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt])
+			mark_dquot_dirty(inode->i_dquot[cnt]);
+	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+	return ret;
+}
+EXPORT_SYMBOL(dquot_claim_space);
+
+/*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+	int cnt;
+
+	if (IS_NOQUOTA(inode))
+		goto out;
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode))
+		goto out_unlock;
+
+	spin_lock(&dq_data_lock);
+	/* Release reserved dquots */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt] != NODQUOT)
+			dquot_free_reserved_space(inode->i_dquot[cnt], number);
+	}
+	spin_unlock(&dq_data_lock);
+
+out_unlock:
+	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+	return;
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
 /*
  * This operation can block, but only after everything is updated
  */
@@ -1529,6 +1612,19 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
 }
 
 /*
+ * call back function, get reserved quota space from underlying fs
+ */
+qsize_t dquot_get_reserved_space(struct inode *inode)
+{
+	qsize_t reserved_space = 0;
+
+	if (sb_any_quota_active(inode->i_sb) &&
+	    inode->i_sb->dq_op->get_reserved_space)
+		reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
+	return reserved_space;
+}
+
+/*
  * Transfer the number of inode and blocks from one diskquota to an other.
  *
  * This operation can block, but only after everything is updated
@@ -1536,7 +1632,8 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
  */
 int dquot_transfer(struct inode *inode, struct iattr *iattr)
 {
-	qsize_t space;
+	qsize_t space, cur_space;
+	qsize_t rsv_space = 0;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
 	int cnt, ret = QUOTA_OK;
@@ -1575,7 +1672,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 		goto put_all;
 	}
 	spin_lock(&dq_data_lock);
-	space = inode_get_bytes(inode);
+	cur_space = inode_get_bytes(inode);
+	rsv_space = dquot_get_reserved_space(inode);
+	space = cur_space + rsv_space;
 	/* Build the transfer_from list and check the limits */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (transfer_to[cnt] == NODQUOT)
@@ -1604,11 +1703,14 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
 			warntype_from_space[cnt] =
 				info_bdq_free(transfer_from[cnt], space);
 			dquot_decr_inodes(transfer_from[cnt], 1);
-			dquot_decr_space(transfer_from[cnt], space);
+			dquot_decr_space(transfer_from[cnt], cur_space);
+			dquot_free_reserved_space(transfer_from[cnt],
+						  rsv_space);
 		}
 
 		dquot_incr_inodes(transfer_to[cnt], 1);
-		dquot_incr_space(transfer_to[cnt], space);
+		dquot_incr_space(transfer_to[cnt], cur_space);
+		dquot_resv_space(transfer_to[cnt], rsv_space);
 
 		inode->i_dquot[cnt] = transfer_to[cnt];
 	}
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 54b837f..a510d91 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -311,6 +311,12 @@ struct dquot_operations {
 	int (*write_info) (struct super_block *, int);	/* Write of quota "superblock" */
 	/* reserve quota for delayed block allocation */
 	int (*reserve_space) (struct inode *, qsize_t, int);
+	/* claim reserved quota for delayed alloc */
+	int (*claim_space) (struct inode *, qsize_t);
+	/* release rsved quota for delayed alloc */
+	void (*release_rsv) (struct inode *, qsize_t);
+	/* get reserved quota for delayed alloc */
+	qsize_t (*get_reserved_space) (struct inode *);
 };
 
 /* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 3e3a0d2..7369d04 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot);
 int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
 int dquot_alloc_inode(const struct inode *inode, qsize_t number);
 
+int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
+int dquot_claim_space(struct inode *inode, qsize_t number);
+void dquot_release_reserved_space(struct inode *inode, qsize_t number);
+qsize_t dquot_get_reserved_space(struct inode *inode);
+
 int dquot_free_space(struct inode *inode, qsize_t number);
 int dquot_free_inode(const struct inode *inode, qsize_t number);
 
@@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
 	return 0;
 }
 
+/*
+ * Convert in-memory reserved quotas to real consumed quotas
+ */
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+	if (sb_any_quota_active(inode->i_sb)) {
+		if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
+			return 1;
+	} else
+		inode_add_bytes(inode, nr);
+
+	mark_inode_dirty(inode);
+	return 0;
+}
+
+/*
+ * Release reserved (in-memory) quotas
+ */
+static inline
+void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+	if (sb_any_quota_active(inode->i_sb))
+		inode->i_sb->dq_op->release_rsv(inode, nr);
+}
+
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
 	if (sb_any_quota_active(inode->i_sb))
@@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
 	return 0;
 }
 
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+	return vfs_dq_alloc_space(inode, nr);
+}
+
+static inline
+int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+	return 0;
+}
+
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
 	inode_sub_bytes(inode, nr);
@@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
 			nr << inode->i_blkbits);
 }
 
+static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
+{
+	return vfs_dq_claim_space(inode,
+			nr << inode->i_blkbits);
+}
+
+static inline
+void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
+{
+	vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits);
+}
+
 static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
 {
 	vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 07/11] quota: Use inode->i_blkbits to get block bits
  2009-01-16 18:08             ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
@ 2009-01-16 18:08               ` Jan Kara
  2009-01-16 18:08                 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara

From: Mingming Cao <cmm@us.ibm.com>

Andrew has suggested to use inode->i_blkbits to get the block bits info,
rather than use super block's blockbits. That should be faster and emit
less code.

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 include/linux/quotaops.h |   22 ++++++++--------------
 1 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 7369d04..69b502e 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -410,38 +410,32 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
 
 static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_prealloc_space_nodirty(inode,
-			nr << inode->i_sb->s_blocksize_bits);
+	return vfs_dq_prealloc_space_nodirty(inode, nr << inode->i_blkbits);
 }
 
 static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_prealloc_space(inode,
-			nr << inode->i_sb->s_blocksize_bits);
+	return vfs_dq_prealloc_space(inode, nr << inode->i_blkbits);
 }
 
 static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
- 	return vfs_dq_alloc_space_nodirty(inode,
-			nr << inode->i_sb->s_blocksize_bits);
+	return vfs_dq_alloc_space_nodirty(inode, nr << inode->i_blkbits);
 }
 
 static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_alloc_space(inode,
-			nr << inode->i_sb->s_blocksize_bits);
+	return vfs_dq_alloc_space(inode, nr << inode->i_blkbits);
 }
 
 static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_reserve_space(inode,
-			nr << inode->i_blkbits);
+	return vfs_dq_reserve_space(inode, nr << inode->i_blkbits);
 }
 
 static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_claim_space(inode,
-			nr << inode->i_blkbits);
+	return vfs_dq_claim_space(inode, nr << inode->i_blkbits);
 }
 
 static inline
@@ -452,12 +446,12 @@ void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
 
 static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
 {
-	vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
+	vfs_dq_free_space_nodirty(inode, nr << inode->i_blkbits);
 }
 
 static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr)
 {
-	vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits);
+	vfs_dq_free_space(inode, nr << inode->i_blkbits);
 }
 
 /*
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles
  2009-01-16 18:08               ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
@ 2009-01-16 18:08                 ` Jan Kara
  2009-01-16 18:08                   ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
  0 siblings, 1 reply; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara

From: Mingming Cao <cmm@us.ibm.com>

According to checkpatch: EXPORT_SYMBOL(foo); should immediately follow its
 function/variable

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/dquot.c |   69 ++++++++++++++++++++++++++++-------------------------------
 1 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/fs/dquot.c b/fs/dquot.c
index 2916f91..28aa146 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -132,6 +132,7 @@
 static DEFINE_SPINLOCK(dq_list_lock);
 static DEFINE_SPINLOCK(dq_state_lock);
 DEFINE_SPINLOCK(dq_data_lock);
+EXPORT_SYMBOL(dq_data_lock);
 
 static char *quotatypes[] = INITQFNAMES;
 static struct quota_format_type *quota_formats;	/* List of registered formats */
@@ -148,6 +149,7 @@ int register_quota_format(struct quota_format_type *fmt)
 	spin_unlock(&dq_list_lock);
 	return 0;
 }
+EXPORT_SYMBOL(register_quota_format);
 
 void unregister_quota_format(struct quota_format_type *fmt)
 {
@@ -159,6 +161,7 @@ void unregister_quota_format(struct quota_format_type *fmt)
 		*actqf = (*actqf)->qf_next;
 	spin_unlock(&dq_list_lock);
 }
+EXPORT_SYMBOL(unregister_quota_format);
 
 static struct quota_format_type *find_quota_format(int id)
 {
@@ -215,6 +218,7 @@ static unsigned int dq_hash_bits, dq_hash_mask;
 static struct hlist_head *dquot_hash;
 
 struct dqstats dqstats;
+EXPORT_SYMBOL(dqstats);
 
 static inline unsigned int
 hashfn(const struct super_block *sb, unsigned int id, int type)
@@ -309,6 +313,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
 	spin_unlock(&dq_list_lock);
 	return 0;
 }
+EXPORT_SYMBOL(dquot_mark_dquot_dirty);
 
 /* This function needs dq_list_lock */
 static inline int clear_dquot_dirty(struct dquot *dquot)
@@ -360,6 +365,7 @@ out_iolock:
 	mutex_unlock(&dquot->dq_lock);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_acquire);
 
 /*
  *	Write dquot to disk
@@ -389,6 +395,7 @@ out_sem:
 	mutex_unlock(&dqopt->dqio_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_commit);
 
 /*
  *	Release dquot
@@ -417,6 +424,7 @@ out_dqlock:
 	mutex_unlock(&dquot->dq_lock);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_release);
 
 void dquot_destroy(struct dquot *dquot)
 {
@@ -516,6 +524,7 @@ out:
 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_scan_active);
 
 int vfs_quota_sync(struct super_block *sb, int type)
 {
@@ -563,6 +572,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
 
 	return 0;
 }
+EXPORT_SYMBOL(vfs_quota_sync);
 
 /* Free unused dquots from cache */
 static void prune_dqcache(int count)
@@ -672,6 +682,7 @@ we_slept:
 	put_dquot_last(dquot);
 	spin_unlock(&dq_list_lock);
 }
+EXPORT_SYMBOL(dqput);
 
 struct dquot *dquot_alloc(struct super_block *sb, int type)
 {
@@ -767,6 +778,7 @@ out:
 
 	return dquot;
 }
+EXPORT_SYMBOL(dqget);
 
 static int dqinit_needed(struct inode *inode, int type)
 {
@@ -1282,6 +1294,7 @@ out_err:
 		dqput(got[cnt]);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_initialize);
 
 /*
  * 	Release all quotas referenced by inode
@@ -1302,6 +1315,7 @@ int dquot_drop(struct inode *inode)
 		dqput(put[cnt]);
 	return 0;
 }
+EXPORT_SYMBOL(dquot_drop);
 
 /* Wrapper to remove references to quota structures from inode */
 void vfs_dq_drop(struct inode *inode)
@@ -1324,6 +1338,7 @@ void vfs_dq_drop(struct inode *inode)
 			inode->i_sb->dq_op->drop(inode);
 	}
 }
+EXPORT_SYMBOL(vfs_dq_drop);
 
 /*
  * Following four functions update i_blocks+i_bytes fields and
@@ -1404,6 +1419,7 @@ out_unlock:
 out:
 	return ret;
 }
+EXPORT_SYMBOL(dquot_alloc_space);
 
 int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
 {
@@ -1468,6 +1484,7 @@ warn_put_all:
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_alloc_inode);
 
 int dquot_claim_space(struct inode *inode, qsize_t number)
 {
@@ -1574,6 +1591,7 @@ out_sub:
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return QUOTA_OK;
 }
+EXPORT_SYMBOL(dquot_free_space);
 
 /*
  * This operation can block, but only after everything is updated
@@ -1610,6 +1628,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return QUOTA_OK;
 }
+EXPORT_SYMBOL(dquot_free_inode);
 
 /*
  * call back function, get reserved quota space from underlying fs
@@ -1746,6 +1765,7 @@ over_quota:
 	ret = NO_QUOTA;
 	goto warn_put_all;
 }
+EXPORT_SYMBOL(dquot_transfer);
 
 /* Wrapper for transferring ownership of an inode */
 int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
@@ -1757,7 +1777,7 @@ int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
 	}
 	return 0;
 }
-
+EXPORT_SYMBOL(vfs_dq_transfer);
 
 /*
  * Write info of quota file to disk
@@ -1772,6 +1792,7 @@ int dquot_commit_info(struct super_block *sb, int type)
 	mutex_unlock(&dqopt->dqio_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(dquot_commit_info);
 
 /*
  * Definitions of diskquota operations.
@@ -1924,13 +1945,14 @@ put_inodes:
 		}
 	return ret;
 }
+EXPORT_SYMBOL(vfs_quota_disable);
 
 int vfs_quota_off(struct super_block *sb, int type, int remount)
 {
 	return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED :
 				 (DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED));
 }
-
+EXPORT_SYMBOL(vfs_quota_off);
 /*
  *	Turn quotas on on a device
  */
@@ -2087,6 +2109,7 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
 					     DQUOT_LIMITS_ENABLED);
 	return error;
 }
+EXPORT_SYMBOL(vfs_quota_on_path);
 
 int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
 		 int remount)
@@ -2104,6 +2127,7 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
 	}
 	return error;
 }
+EXPORT_SYMBOL(vfs_quota_on);
 
 /*
  * More powerful function for turning on quotas allowing setting
@@ -2150,6 +2174,7 @@ out_lock:
 load_quota:
 	return vfs_load_quota_inode(inode, type, format_id, flags);
 }
+EXPORT_SYMBOL(vfs_quota_enable);
 
 /*
  * This function is used when filesystem needs to initialize quotas
@@ -2179,6 +2204,7 @@ out:
 	dput(dentry);
 	return error;
 }
+EXPORT_SYMBOL(vfs_quota_on_mount);
 
 /* Wrapper to turn on quotas when remounting rw */
 int vfs_dq_quota_on_remount(struct super_block *sb)
@@ -2195,6 +2221,7 @@ int vfs_dq_quota_on_remount(struct super_block *sb)
 	}
 	return ret;
 }
+EXPORT_SYMBOL(vfs_dq_quota_on_remount);
 
 static inline qsize_t qbtos(qsize_t blocks)
 {
@@ -2236,6 +2263,7 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
 
 	return 0;
 }
+EXPORT_SYMBOL(vfs_get_dqblk);
 
 /* Generic routine for setting common part of quota structure */
 static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
@@ -2327,6 +2355,7 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
 out:
 	return rc;
 }
+EXPORT_SYMBOL(vfs_set_dqblk);
 
 /* Generic routine for getting common part of quota file information */
 int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
@@ -2348,6 +2377,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
 	return 0;
 }
+EXPORT_SYMBOL(vfs_get_dqinfo);
 
 /* Generic routine for setting common part of quota file information */
 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
@@ -2376,6 +2406,7 @@ out:
 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
 	return err;
 }
+EXPORT_SYMBOL(vfs_set_dqinfo);
 
 struct quotactl_ops vfs_quotactl_ops = {
 	.quota_on	= vfs_quota_on,
@@ -2531,37 +2562,3 @@ static int __init dquot_init(void)
 	return 0;
 }
 module_init(dquot_init);
-
-EXPORT_SYMBOL(register_quota_format);
-EXPORT_SYMBOL(unregister_quota_format);
-EXPORT_SYMBOL(dqstats);
-EXPORT_SYMBOL(dq_data_lock);
-EXPORT_SYMBOL(vfs_quota_enable);
-EXPORT_SYMBOL(vfs_quota_on);
-EXPORT_SYMBOL(vfs_quota_on_path);
-EXPORT_SYMBOL(vfs_quota_on_mount);
-EXPORT_SYMBOL(vfs_quota_disable);
-EXPORT_SYMBOL(vfs_quota_off);
-EXPORT_SYMBOL(dquot_scan_active);
-EXPORT_SYMBOL(vfs_quota_sync);
-EXPORT_SYMBOL(vfs_get_dqinfo);
-EXPORT_SYMBOL(vfs_set_dqinfo);
-EXPORT_SYMBOL(vfs_get_dqblk);
-EXPORT_SYMBOL(vfs_set_dqblk);
-EXPORT_SYMBOL(dquot_commit);
-EXPORT_SYMBOL(dquot_commit_info);
-EXPORT_SYMBOL(dquot_acquire);
-EXPORT_SYMBOL(dquot_release);
-EXPORT_SYMBOL(dquot_mark_dquot_dirty);
-EXPORT_SYMBOL(dquot_initialize);
-EXPORT_SYMBOL(dquot_drop);
-EXPORT_SYMBOL(vfs_dq_drop);
-EXPORT_SYMBOL(dqget);
-EXPORT_SYMBOL(dqput);
-EXPORT_SYMBOL(dquot_alloc_space);
-EXPORT_SYMBOL(dquot_alloc_inode);
-EXPORT_SYMBOL(dquot_free_space);
-EXPORT_SYMBOL(dquot_free_inode);
-EXPORT_SYMBOL(dquot_transfer);
-EXPORT_SYMBOL(vfs_dq_transfer);
-EXPORT_SYMBOL(vfs_dq_quota_on_remount);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 09/11] ext3: Remove unnecessary quota functions
  2009-01-16 18:08                 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
@ 2009-01-16 18:08                   ` Jan Kara
  2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
  2009-01-20 21:41                     ` [PATCH 09/11] ext3: " Mingming Cao
  0 siblings, 2 replies; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

ext3_dquot_initialize() and ext3_dquot_drop() is no longer
needed because of modified quota locking.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext3/super.c |   44 ++------------------------------------------
 1 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b70d90e..ec410a9 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -707,8 +707,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
 
-static int ext3_dquot_initialize(struct inode *inode, int type);
-static int ext3_dquot_drop(struct inode *inode);
 static int ext3_write_dquot(struct dquot *dquot);
 static int ext3_acquire_dquot(struct dquot *dquot);
 static int ext3_release_dquot(struct dquot *dquot);
@@ -723,8 +721,8 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
 				const char *data, size_t len, loff_t off);
 
 static struct dquot_operations ext3_quota_operations = {
-	.initialize	= ext3_dquot_initialize,
-	.drop		= ext3_dquot_drop,
+	.initialize	= dquot_initialize,
+	.drop		= dquot_drop,
 	.alloc_space	= dquot_alloc_space,
 	.alloc_inode	= dquot_alloc_inode,
 	.free_space	= dquot_free_space,
@@ -2713,44 +2711,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
 	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 }
 
-static int ext3_dquot_initialize(struct inode *inode, int type)
-{
-	handle_t *handle;
-	int ret, err;
-
-	/* We may create quota structure so we need to reserve enough blocks */
-	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle))
-		return PTR_ERR(handle);
-	ret = dquot_initialize(inode, type);
-	err = ext3_journal_stop(handle);
-	if (!ret)
-		ret = err;
-	return ret;
-}
-
-static int ext3_dquot_drop(struct inode *inode)
-{
-	handle_t *handle;
-	int ret, err;
-
-	/* We may delete quota structure so we need to reserve enough blocks */
-	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle)) {
-		/*
-		 * We call dquot_drop() anyway to at least release references
-		 * to quota structures so that umount does not hang.
-		 */
-		dquot_drop(inode);
-		return PTR_ERR(handle);
-	}
-	ret = dquot_drop(inode);
-	err = ext3_journal_stop(handle);
-	if (!ret)
-		ret = err;
-	return ret;
-}
-
 static int ext3_write_dquot(struct dquot *dquot)
 {
 	int ret, err;
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 10/11] ext4: Remove unnecessary quota functions
  2009-01-16 18:08                   ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
@ 2009-01-16 18:08                     ` Jan Kara
  2009-01-16 18:08                       ` [PATCH 11/11] reiserfs: " Jan Kara
  2009-01-20 21:41                       ` [PATCH 10/11] ext4: " Mingming Cao
  2009-01-20 21:41                     ` [PATCH 09/11] ext3: " Mingming Cao
  1 sibling, 2 replies; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

ext4_dquot_initialize() and ext4_dquot_drop() is no longer
needed because of modified quota locking.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext4/super.c |   44 ++------------------------------------------
 1 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e5f06a5..f0785fd 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -926,8 +926,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_
 #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
 #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
 
-static int ext4_dquot_initialize(struct inode *inode, int type);
-static int ext4_dquot_drop(struct inode *inode);
 static int ext4_write_dquot(struct dquot *dquot);
 static int ext4_acquire_dquot(struct dquot *dquot);
 static int ext4_release_dquot(struct dquot *dquot);
@@ -942,8 +940,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
 				const char *data, size_t len, loff_t off);
 
 static struct dquot_operations ext4_quota_operations = {
-	.initialize	= ext4_dquot_initialize,
-	.drop		= ext4_dquot_drop,
+	.initialize	= dquot_initialize,
+	.drop		= dquot_drop,
 	.alloc_space	= dquot_alloc_space,
 	.alloc_inode	= dquot_alloc_inode,
 	.free_space	= dquot_free_space,
@@ -3378,44 +3376,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
 	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 }
 
-static int ext4_dquot_initialize(struct inode *inode, int type)
-{
-	handle_t *handle;
-	int ret, err;
-
-	/* We may create quota structure so we need to reserve enough blocks */
-	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle))
-		return PTR_ERR(handle);
-	ret = dquot_initialize(inode, type);
-	err = ext4_journal_stop(handle);
-	if (!ret)
-		ret = err;
-	return ret;
-}
-
-static int ext4_dquot_drop(struct inode *inode)
-{
-	handle_t *handle;
-	int ret, err;
-
-	/* We may delete quota structure so we need to reserve enough blocks */
-	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle)) {
-		/*
-		 * We call dquot_drop() anyway to at least release references
-		 * to quota structures so that umount does not hang.
-		 */
-		dquot_drop(inode);
-		return PTR_ERR(handle);
-	}
-	ret = dquot_drop(inode);
-	err = ext4_journal_stop(handle);
-	if (!ret)
-		ret = err;
-	return ret;
-}
-
 static int ext4_write_dquot(struct dquot *dquot)
 {
 	int ret, err;
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 11/11] reiserfs: Remove unnecessary quota functions
  2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
@ 2009-01-16 18:08                       ` Jan Kara
  2009-01-20 21:41                       ` [PATCH 10/11] ext4: " Mingming Cao
  1 sibling, 0 replies; 228+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara

reiserfs_dquot_initialize() and reiserfs_dquot_drop() is no longer
needed because of modified quota locking.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/reiserfs/super.c |   58 +-------------------------------------------------
 1 files changed, 2 insertions(+), 56 deletions(-)

diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f3c820b..317c035 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -629,8 +629,6 @@ static const struct super_operations reiserfs_sops = {
 #ifdef CONFIG_QUOTA
 #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
 
-static int reiserfs_dquot_initialize(struct inode *, int);
-static int reiserfs_dquot_drop(struct inode *);
 static int reiserfs_write_dquot(struct dquot *);
 static int reiserfs_acquire_dquot(struct dquot *);
 static int reiserfs_release_dquot(struct dquot *);
@@ -639,8 +637,8 @@ static int reiserfs_write_info(struct super_block *, int);
 static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
 
 static struct dquot_operations reiserfs_quota_operations = {
-	.initialize = reiserfs_dquot_initialize,
-	.drop = reiserfs_dquot_drop,
+	.initialize = dquot_initialize,
+	.drop = dquot_drop,
 	.alloc_space = dquot_alloc_space,
 	.alloc_inode = dquot_alloc_inode,
 	.free_space = dquot_free_space,
@@ -1896,58 +1894,6 @@ static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 }
 
 #ifdef CONFIG_QUOTA
-static int reiserfs_dquot_initialize(struct inode *inode, int type)
-{
-	struct reiserfs_transaction_handle th;
-	int ret, err;
-
-	/* We may create quota structure so we need to reserve enough blocks */
-	reiserfs_write_lock(inode->i_sb);
-	ret =
-	    journal_begin(&th, inode->i_sb,
-			  2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
-	if (ret)
-		goto out;
-	ret = dquot_initialize(inode, type);
-	err =
-	    journal_end(&th, inode->i_sb,
-			2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
-	if (!ret && err)
-		ret = err;
-      out:
-	reiserfs_write_unlock(inode->i_sb);
-	return ret;
-}
-
-static int reiserfs_dquot_drop(struct inode *inode)
-{
-	struct reiserfs_transaction_handle th;
-	int ret, err;
-
-	/* We may delete quota structure so we need to reserve enough blocks */
-	reiserfs_write_lock(inode->i_sb);
-	ret =
-	    journal_begin(&th, inode->i_sb,
-			  2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
-	if (ret) {
-		/*
-		 * We call dquot_drop() anyway to at least release references
-		 * to quota structures so that umount does not hang.
-		 */
-		dquot_drop(inode);
-		goto out;
-	}
-	ret = dquot_drop(inode);
-	err =
-	    journal_end(&th, inode->i_sb,
-			2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
-	if (!ret && err)
-		ret = err;
-      out:
-	reiserfs_write_unlock(inode->i_sb);
-	return ret;
-}
-
 static int reiserfs_write_dquot(struct dquot *dquot)
 {
 	struct reiserfs_transaction_handle th;
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 09/11] ext3: Remove unnecessary quota functions
  2009-01-16 18:08                   ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
  2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
@ 2009-01-20 21:41                     ` Mingming Cao
  1 sibling, 0 replies; 228+ messages in thread
From: Mingming Cao @ 2009-01-20 21:41 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel


在 2009-01-16五的 19:08 +0100,Jan Kara写道:
> ext3_dquot_initialize() and ext3_dquot_drop() is no longer
> needed because of modified quota locking.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Reviewed_by: Mingming Cao <cmm@us.ibm.com>
> ---
>  fs/ext3/super.c |   44 ++------------------------------------------
>  1 files changed, 2 insertions(+), 42 deletions(-)
> 
> diff --git a/fs/ext3/super.c b/fs/ext3/super.c
> index b70d90e..ec410a9 100644
> --- a/fs/ext3/super.c
> +++ b/fs/ext3/super.c
> @@ -707,8 +707,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
>  #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
>  #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
> 
> -static int ext3_dquot_initialize(struct inode *inode, int type);
> -static int ext3_dquot_drop(struct inode *inode);
>  static int ext3_write_dquot(struct dquot *dquot);
>  static int ext3_acquire_dquot(struct dquot *dquot);
>  static int ext3_release_dquot(struct dquot *dquot);
> @@ -723,8 +721,8 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
>  				const char *data, size_t len, loff_t off);
> 
>  static struct dquot_operations ext3_quota_operations = {
> -	.initialize	= ext3_dquot_initialize,
> -	.drop		= ext3_dquot_drop,
> +	.initialize	= dquot_initialize,
> +	.drop		= dquot_drop,
>  	.alloc_space	= dquot_alloc_space,
>  	.alloc_inode	= dquot_alloc_inode,
>  	.free_space	= dquot_free_space,
> @@ -2713,44 +2711,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
>  	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
>  }
> 
> -static int ext3_dquot_initialize(struct inode *inode, int type)
> -{
> -	handle_t *handle;
> -	int ret, err;
> -
> -	/* We may create quota structure so we need to reserve enough blocks */
> -	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
> -	if (IS_ERR(handle))
> -		return PTR_ERR(handle);
> -	ret = dquot_initialize(inode, type);
> -	err = ext3_journal_stop(handle);
> -	if (!ret)
> -		ret = err;
> -	return ret;
> -}
> -
> -static int ext3_dquot_drop(struct inode *inode)
> -{
> -	handle_t *handle;
> -	int ret, err;
> -
> -	/* We may delete quota structure so we need to reserve enough blocks */
> -	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
> -	if (IS_ERR(handle)) {
> -		/*
> -		 * We call dquot_drop() anyway to at least release references
> -		 * to quota structures so that umount does not hang.
> -		 */
> -		dquot_drop(inode);
> -		return PTR_ERR(handle);
> -	}
> -	ret = dquot_drop(inode);
> -	err = ext3_journal_stop(handle);
> -	if (!ret)
> -		ret = err;
> -	return ret;
> -}
> -
>  static int ext3_write_dquot(struct dquot *dquot)
>  {
>  	int ret, err;


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 10/11] ext4: Remove unnecessary quota functions
  2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
  2009-01-16 18:08                       ` [PATCH 11/11] reiserfs: " Jan Kara
@ 2009-01-20 21:41                       ` Mingming Cao
  1 sibling, 0 replies; 228+ messages in thread
From: Mingming Cao @ 2009-01-20 21:41 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel


在 2009-01-16五的 19:08 +0100,Jan Kara写道:
> ext4_dquot_initialize() and ext4_dquot_drop() is no longer
> needed because of modified quota locking.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Reviewed_by: Mingming Cao <cmm@us.ibm.com>
> ---
>  fs/ext4/super.c |   44 ++------------------------------------------
>  1 files changed, 2 insertions(+), 42 deletions(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index e5f06a5..f0785fd 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -926,8 +926,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_
>  #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
>  #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
> 
> -static int ext4_dquot_initialize(struct inode *inode, int type);
> -static int ext4_dquot_drop(struct inode *inode);
>  static int ext4_write_dquot(struct dquot *dquot);
>  static int ext4_acquire_dquot(struct dquot *dquot);
>  static int ext4_release_dquot(struct dquot *dquot);
> @@ -942,8 +940,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
>  				const char *data, size_t len, loff_t off);
> 
>  static struct dquot_operations ext4_quota_operations = {
> -	.initialize	= ext4_dquot_initialize,
> -	.drop		= ext4_dquot_drop,
> +	.initialize	= dquot_initialize,
> +	.drop		= dquot_drop,
>  	.alloc_space	= dquot_alloc_space,
>  	.alloc_inode	= dquot_alloc_inode,
>  	.free_space	= dquot_free_space,
> @@ -3378,44 +3376,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
>  	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
>  }
> 
> -static int ext4_dquot_initialize(struct inode *inode, int type)
> -{
> -	handle_t *handle;
> -	int ret, err;
> -
> -	/* We may create quota structure so we need to reserve enough blocks */
> -	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb));
> -	if (IS_ERR(handle))
> -		return PTR_ERR(handle);
> -	ret = dquot_initialize(inode, type);
> -	err = ext4_journal_stop(handle);
> -	if (!ret)
> -		ret = err;
> -	return ret;
> -}
> -
> -static int ext4_dquot_drop(struct inode *inode)
> -{
> -	handle_t *handle;
> -	int ret, err;
> -
> -	/* We may delete quota structure so we need to reserve enough blocks */
> -	handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
> -	if (IS_ERR(handle)) {
> -		/*
> -		 * We call dquot_drop() anyway to at least release references
> -		 * to quota structures so that umount does not hang.
> -		 */
> -		dquot_drop(inode);
> -		return PTR_ERR(handle);
> -	}
> -	ret = dquot_drop(inode);
> -	err = ext4_journal_stop(handle);
> -	if (!ret)
> -		ret = err;
> -	return ret;
> -}
> -
>  static int ext4_write_dquot(struct dquot *dquot)
>  {
>  	int ret, err;


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 01/11] quota: Improve locking
  2009-01-16 18:08   ` [PATCH 01/11] quota: Improve locking Jan Kara
  2009-01-16 18:08     ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
@ 2009-01-24  7:49     ` Andrew Morton
  2009-01-26 10:04       ` Jan Kara
  1 sibling, 1 reply; 228+ messages in thread
From: Andrew Morton @ 2009-01-24  7:49 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel

On Fri, 16 Jan 2009 19:08:09 +0100 Jan Kara <jack@suse.cz> wrote:

>  static DEFINE_SPINLOCK(dq_list_lock);
> +static DEFINE_SPINLOCK(dq_state_lock);
>  DEFINE_SPINLOCK(dq_data_lock);

The chances are very good that two or even three of these locks will
all get placed into the same cacheline in main memory.  The effects
will be quite bad if different CPUs (or, worse, different nodes) are
taking these locks.

For single, kernel-wide locks like these I think we should almost
always pad out to a cacheline.

With __cacheline_aligned_in_smp, rather than __cacheline_aligned. 
Because spinlocks do take space even in uniprocessor builds.

There are probably lots of existing locks which should be converted.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 01/11] quota: Improve locking
  2009-01-24  7:49     ` [PATCH 01/11] quota: Improve locking Andrew Morton
@ 2009-01-26 10:04       ` Jan Kara
  0 siblings, 0 replies; 228+ messages in thread
From: Jan Kara @ 2009-01-26 10:04 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, linux-ext4, linux-fsdevel

On Fri 23-01-09 23:49:12, Andrew Morton wrote:
> On Fri, 16 Jan 2009 19:08:09 +0100 Jan Kara <jack@suse.cz> wrote:
> 
> >  static DEFINE_SPINLOCK(dq_list_lock);
> > +static DEFINE_SPINLOCK(dq_state_lock);
> >  DEFINE_SPINLOCK(dq_data_lock);
> 
> The chances are very good that two or even three of these locks will
> all get placed into the same cacheline in main memory.  The effects
> will be quite bad if different CPUs (or, worse, different nodes) are
> taking these locks.
>
> For single, kernel-wide locks like these I think we should almost
> always pad out to a cacheline.
  I never thought about this. Thanks for the idea.

> With __cacheline_aligned_in_smp, rather than __cacheline_aligned. 
> Because spinlocks do take space even in uniprocessor builds.
  I've added this to my list of quota cleanups.

								Honza
-- 
Jan Kara <jack@suse.cz>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 0/8] kernel:lockdep:replace DFS with BFS
       [not found] <yes>
  2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
@ 2009-05-31 14:49 ` tom.leiming
  2009-05-31 14:49   ` [PATCH 1/8] kernel:lockdep:improve implementation of BFS tom.leiming
  2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
  2009-10-07 13:49 ` [PATCH 1/1] perf tools: Up the verbose level for some really verbose stuff Arnaldo Carvalho de Melo
                   ` (32 subsequent siblings)
  34 siblings, 2 replies; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra


Hi,
Currently lockdep uses recursion DFS(depth-first search) algorithm to
search target in checking lock circle(check_noncircular()),irq-safe
-> irq-unsafe(check_irq_usage()) and irq inversion when adding a new
lock dependency. This patches replace the current DFS with BFS, based on
the following consideration:

     1,no loss of efficiency, no matter DFS or BFS, the running time
     are O(V+E) (V is vertex count, and E is edge count of one
     graph);

     2,BFS may be easily implemented by circular queue and consumes
     much less kernel stack space than DFS for DFS is implemented by
     recursion.

     3, The shortest path can be obtained by BFS if the target is
     found, but can't be got by DFS. By the shortest path, we can
     shorten the lock dependency chain and help to troubleshoot lock
     problem easier than before.



^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 1/8] kernel:lockdep:improve implementation of BFS
  2009-05-31 14:49 ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS tom.leiming
@ 2009-05-31 14:49   ` tom.leiming
  2009-05-31 14:49     ` [PATCH 2/8] kernel:lockdep: introduce match function to BFS tom.leiming
  2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
  1 sibling, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>

1,replace %MAX_CIRCULAR_QUE_SIZE with &(MAX_CIRCULAR_QUE_SIZE-1)
since we define MAX_CIRCULAR_QUE_SIZE as power of 2;

2,use bitmap to mark if a lock is accessed in BFS in order to
clear it quickly, because we may search a graph many times.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c           |   23 ++++++++++++++++-------
 kernel/lockdep_internals.h |   35 +++++++++++++++++++++++------------
 2 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 93dc70d..5dcca26 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -42,7 +42,7 @@
 #include <linux/hash.h>
 #include <linux/ftrace.h>
 #include <linux/stringify.h>
-
+#include <linux/bitops.h>
 #include <asm/sections.h>
 
 #include "lockdep_internals.h"
@@ -118,7 +118,7 @@ static inline int debug_locks_off_graph_unlock(void)
 static int lockdep_initialized;
 
 unsigned long nr_list_entries;
-static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
+struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
 
 /*
  * All data structures here are protected by the global debug_lock.
@@ -897,30 +897,38 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 	return 1;
 }
 
+unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
 static struct circular_queue  lock_cq;
+
 static int __search_shortest_path(struct lock_list *source_entry,
 				struct lock_class *target,
 				struct lock_list **target_entry,
 				int forward)
 {
 	struct lock_list *entry;
+	struct list_head *head;
 	struct circular_queue *cq = &lock_cq;
 	int ret = 1;
 
-	__cq_init(cq);
-
-	mark_lock_accessed(source_entry, NULL);
 	if (source_entry->class == target) {
 		*target_entry = source_entry;
 		ret = 0;
 		goto exit;
 	}
 
+	if (forward)
+		head = &source_entry->class->locks_after;
+	else
+		head = &source_entry->class->locks_before;
+
+	if (list_empty(head))
+		goto exit;
+
+	__cq_init(cq);
 	__cq_enqueue(cq, (unsigned long)source_entry);
 
 	while (!__cq_empty(cq)) {
 		struct lock_list *lock;
-		struct list_head *head;
 
 		__cq_dequeue(cq, (unsigned long *)&lock);
 
@@ -1040,6 +1048,7 @@ static noinline int print_circular_bug(void)
 		return 0;
 
 	this.class = hlock_class(check_source);
+	this.parent = NULL;
 	if (!save_trace(&this.trace))
 		return 0;
 
@@ -1580,10 +1589,10 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 	 */
 	check_source = next;
 	check_target = prev;
+
 	if (check_noncircular(hlock_class(next), 0) == 2)
 		return print_circular_bug();
 
-
 	if (!check_prev_add_irq(curr, prev, next))
 		return 0;
 
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index 6f48d37..c2f6594 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -137,23 +137,28 @@ extern atomic_t nr_find_usage_backwards_recursions;
 # define debug_atomic_read(ptr)		0
 #endif
 
+
+extern unsigned long nr_list_entries;
+extern struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
+extern unsigned long bfs_accessed[];
+
+/*For good efficiency of modular, we use power of 2*/
+#define  MAX_CIRCULAR_QUE_SIZE	    4096UL
+
 /* The circular_queue and helpers is used to implement the
  * breadth-first search(BFS)algorithem, by which we can build
  * the shortest path from the next lock to be acquired to the
  * previous held lock if there is a circular between them.
  * */
-#define  MAX_CIRCULAR_QUE_SIZE	    4096UL
 struct circular_queue{
 	unsigned long element[MAX_CIRCULAR_QUE_SIZE];
 	unsigned int  front, rear;
 };
 
-#define LOCK_ACCESSED 		1UL
-#define LOCK_ACCESSED_MASK	(~LOCK_ACCESSED)
-
 static inline void __cq_init(struct circular_queue *cq)
 {
 	cq->front = cq->rear = 0;
+	bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
 }
 
 static inline int __cq_empty(struct circular_queue *cq)
@@ -163,7 +168,7 @@ static inline int __cq_empty(struct circular_queue *cq)
 
 static inline int __cq_full(struct circular_queue *cq)
 {
-	return ((cq->rear + 1)%MAX_CIRCULAR_QUE_SIZE)  == cq->front;
+	return ((cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1))  == cq->front;
 }
 
 static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
@@ -172,7 +177,7 @@ static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
 		return -1;
 
 	cq->element[cq->rear] = elem;
-	cq->rear = (cq->rear + 1)%MAX_CIRCULAR_QUE_SIZE;
+	cq->rear = (cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
 	return 0;
 }
 
@@ -182,30 +187,36 @@ static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
 		return -1;
 
 	*elem = cq->element[cq->front];
-	cq->front = (cq->front + 1)%MAX_CIRCULAR_QUE_SIZE;
+	cq->front = (cq->front + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
 	return 0;
 }
 
 static inline int __cq_get_elem_count(struct circular_queue *cq)
 {
-	return (cq->rear - cq->front)%MAX_CIRCULAR_QUE_SIZE;
+	return (cq->rear - cq->front)&(MAX_CIRCULAR_QUE_SIZE-1);
 }
 
 static inline void mark_lock_accessed(struct lock_list *lock,
 					struct lock_list *parent)
 {
-	lock->parent = (void *) parent + LOCK_ACCESSED;
+	unsigned long nr;
+	nr = lock - list_entries;
+	WARN_ON(nr >= nr_list_entries);
+	lock->parent = parent;
+	set_bit(nr, bfs_accessed);
 }
 
 static inline unsigned long lock_accessed(struct lock_list *lock)
 {
-	return (unsigned long)lock->parent & LOCK_ACCESSED;
+	unsigned long nr;
+	nr = lock - list_entries;
+	WARN_ON(nr >= nr_list_entries);
+	return test_bit(nr, bfs_accessed);
 }
 
 static inline struct lock_list *get_lock_parent(struct lock_list *child)
 {
-	return (struct lock_list *)
-		((unsigned long)child->parent & LOCK_ACCESSED_MASK);
+	return child->parent;
 }
 
 static inline unsigned long get_lock_depth(struct lock_list *child)
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 2/8] kernel:lockdep: introduce match function to BFS
  2009-05-31 14:49   ` [PATCH 1/8] kernel:lockdep:improve implementation of BFS tom.leiming
@ 2009-05-31 14:49     ` tom.leiming
  2009-05-31 14:49       ` [PATCH 3/8] kernel:lockdep:implement check_noncircular() by BFS tom.leiming
  0 siblings, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>

1,introduce match() to BFS in order to make it usable to
match different pattern;

2,also rename some functions to make them more suitable.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |   43 ++++++++++++++++++++++++++-----------------
 1 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 5dcca26..ce6d09e 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -900,17 +900,18 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
 static struct circular_queue  lock_cq;
 
-static int __search_shortest_path(struct lock_list *source_entry,
-				struct lock_class *target,
-				struct lock_list **target_entry,
-				int forward)
+static int __bfs(struct lock_list *source_entry,
+			void *data,
+			int (*match)(struct lock_list *entry, void *data),
+			struct lock_list **target_entry,
+			int forward)
 {
 	struct lock_list *entry;
 	struct list_head *head;
 	struct circular_queue *cq = &lock_cq;
 	int ret = 1;
 
-	if (source_entry->class == target) {
+	if (match(source_entry, data)) {
 		*target_entry = source_entry;
 		ret = 0;
 		goto exit;
@@ -945,7 +946,7 @@ static int __search_shortest_path(struct lock_list *source_entry,
 		list_for_each_entry(entry, head, entry) {
 			if (!lock_accessed(entry)) {
 				mark_lock_accessed(entry, lock);
-				if (entry->class == target) {
+				if (match(entry, data)) {
 					*target_entry = entry;
 					ret = 0;
 					goto exit;
@@ -962,19 +963,21 @@ exit:
 	return ret;
 }
 
-static inline int __search_forward_shortest_path(struct lock_list *src_entry,
-				struct lock_class *target,
-				struct lock_list **target_entry)
+static inline int __bfs_forward(struct lock_list *src_entry,
+			void *data,
+			int (*match)(struct lock_list *entry, void *data),
+			struct lock_list **target_entry)
 {
-	return __search_shortest_path(src_entry, target, target_entry, 1);
+	return __bfs(src_entry, data, match, target_entry, 1);
 
 }
 
-static inline int __search_backward_shortest_path(struct lock_list *src_entry,
-				struct lock_class *target,
-				struct lock_list **target_entry)
+static inline int __bfs_backward(struct lock_list *src_entry,
+			void *data,
+			int (*match)(struct lock_list *entry, void *data),
+			struct lock_list **target_entry)
 {
-	return __search_shortest_path(src_entry, target, target_entry, 0);
+	return __bfs(src_entry, data, match, target_entry, 0);
 
 }
 
@@ -1035,6 +1038,11 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth)
 	return 0;
 }
 
+static inline int class_equal(struct lock_list *entry, void *data)
+{
+	return entry->class == data;
+}
+
 static noinline int print_circular_bug(void)
 {
 	struct task_struct *curr = current;
@@ -1052,9 +1060,10 @@ static noinline int print_circular_bug(void)
 	if (!save_trace(&this.trace))
 		return 0;
 
-	result = __search_forward_shortest_path(&this,
-						hlock_class(check_target),
-						&target);
+	result = __bfs_forward(&this,
+			hlock_class(check_target),
+			class_equal,
+			&target);
 	if (result) {
 		printk("\n%s:search shortest path failed:%d\n", __func__,
 			result);
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 3/8] kernel:lockdep:implement check_noncircular() by BFS
  2009-05-31 14:49     ` [PATCH 2/8] kernel:lockdep: introduce match function to BFS tom.leiming
@ 2009-05-31 14:49       ` tom.leiming
  2009-05-31 14:49         ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards " tom.leiming
  0 siblings, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>

This patch uses BFS to implement check_noncircular() and
prints the generated shortest circle if exists.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |   89 ++++++++++++++++++++++-------------------------------
 1 files changed, 37 insertions(+), 52 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index ce6d09e..f740088 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -985,12 +985,7 @@ static inline int __bfs_backward(struct lock_list *src_entry,
  * Recursive, forwards-direction lock-dependency checking, used for
  * both noncyclic checking and for hardirq-unsafe/softirq-unsafe
  * checking.
- *
- * (to keep the stackframe of the recursive functions small we
- *  use these global variables, and we also mark various helper
- *  functions as noinline.)
  */
-static struct held_lock *check_source, *check_target;
 
 /*
  * Print a dependency chain entry (this is only done when a deadlock
@@ -1014,7 +1009,9 @@ print_circular_bug_entry(struct lock_list *target, unsigned int depth)
  * header first:
  */
 static noinline int
-print_circular_bug_header(struct lock_list *entry, unsigned int depth)
+print_circular_bug_header(struct lock_list *entry, unsigned int depth,
+			struct held_lock *check_src,
+			struct held_lock *check_tgt)
 {
 	struct task_struct *curr = current;
 
@@ -1027,9 +1024,9 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth)
 	printk(  "-------------------------------------------------------\n");
 	printk("%s/%d is trying to acquire lock:\n",
 		curr->comm, task_pid_nr(curr));
-	print_lock(check_source);
+	print_lock(check_src);
 	printk("\nbut task is already holding lock:\n");
-	print_lock(check_target);
+	print_lock(check_tgt);
 	printk("\nwhich lock already depends on the new lock.\n\n");
 	printk("\nthe existing dependency chain (in reverse order) is:\n");
 
@@ -1043,36 +1040,24 @@ static inline int class_equal(struct lock_list *entry, void *data)
 	return entry->class == data;
 }
 
-static noinline int print_circular_bug(void)
+static noinline int print_circular_bug(struct lock_list *this,
+				struct lock_list *target,
+				struct held_lock *check_src,
+				struct held_lock *check_tgt)
 {
 	struct task_struct *curr = current;
-	struct lock_list this;
-	struct lock_list *target;
 	struct lock_list *parent;
-	int result;
 	unsigned long depth;
 
 	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
 
-	this.class = hlock_class(check_source);
-	this.parent = NULL;
-	if (!save_trace(&this.trace))
+	if (!save_trace(&this->trace))
 		return 0;
 
-	result = __bfs_forward(&this,
-			hlock_class(check_target),
-			class_equal,
-			&target);
-	if (result) {
-		printk("\n%s:search shortest path failed:%d\n", __func__,
-			result);
-		return 0;
-	}
-
 	depth = get_lock_depth(target);
 
-	print_circular_bug_header(target, depth);
+	print_circular_bug_header(target, depth, check_src, check_tgt);
 
 	parent = get_lock_parent(target);
 
@@ -1090,6 +1075,16 @@ static noinline int print_circular_bug(void)
 	return 0;
 }
 
+static int noinline print_bfs_bug(int ret)
+{
+	if (!debug_locks_off_graph_unlock())
+		return 0;
+
+	WARN(1, "lockdep bfs error:%d\n", ret);
+
+	return 0;
+}
+
 #define RECURSION_LIMIT 40
 
 static int noinline print_infinite_recursion_bug(void)
@@ -1168,31 +1163,17 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class)
  * lead to <target>. Print an error and return 0 if it does.
  */
 static noinline int
-check_noncircular(struct lock_class *source, unsigned int depth)
+check_noncircular(struct lock_list *root, struct lock_class *target,
+		struct lock_list **target_entry)
 {
-	struct lock_list *entry;
+	int result;
 
-	if (lockdep_dependency_visit(source, depth))
-		return 1;
+	debug_atomic_inc(&nr_cyclic_checks);
 
-	debug_atomic_inc(&nr_cyclic_check_recursions);
-	if (depth > max_recursion_depth)
-		max_recursion_depth = depth;
-	if (depth >= RECURSION_LIMIT)
-		return print_infinite_recursion_bug();
-	/*
-	 * Check this lock's dependency list:
-	 */
-	list_for_each_entry(entry, &source->locks_after, entry) {
-		if (entry->class == hlock_class(check_target))
-			return 2;
-		debug_atomic_inc(&nr_cyclic_checks);
-		if (check_noncircular(entry->class, depth+1) == 2)
-			return 2;
-	}
-	return 1;
-}
+	result = __bfs_forward(root, target, class_equal, target_entry);
 
+	return result;
+}
 
 #if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
 /*
@@ -1586,6 +1567,8 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 {
 	struct lock_list *entry;
 	int ret;
+	struct lock_list this;
+	struct lock_list *uninitialized_var(target_entry);
 
 	/*
 	 * Prove that the new <prev> -> <next> dependency would not
@@ -1596,11 +1579,13 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev,
 	 * We are using global variables to control the recursion, to
 	 * keep the stackframe size of the recursive functions low:
 	 */
-	check_source = next;
-	check_target = prev;
-
-	if (check_noncircular(hlock_class(next), 0) == 2)
-		return print_circular_bug();
+	this.class = hlock_class(next);
+	this.parent = NULL;
+	ret = check_noncircular(&this, hlock_class(prev), &target_entry);
+	if (unlikely(!ret))
+		return print_circular_bug(&this, target_entry, next, prev);
+	else if (unlikely(ret < 0))
+		return print_bfs_bug(ret);
 
 	if (!check_prev_add_irq(curr, prev, next))
 		return 0;
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS
  2009-05-31 14:49       ` [PATCH 3/8] kernel:lockdep:implement check_noncircular() by BFS tom.leiming
@ 2009-05-31 14:49         ` tom.leiming
  2009-05-31 14:49           ` [PATCH 5/8] kernel:lockdep:introduce print_shortest_lock_dependencies tom.leiming
  2009-05-31 15:14           ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS Daniel Walker
  0 siblings, 2 replies; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>

This patch uses BFS to implement find_usage_*wards(),which
was originally writen by DFS.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |  180 ++++++++++++++++++++++--------------------------------
 1 files changed, 72 insertions(+), 108 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index f740088..94b2f1f 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -963,7 +963,7 @@ exit:
 	return ret;
 }
 
-static inline int __bfs_forward(struct lock_list *src_entry,
+static inline int __bfs_forwards(struct lock_list *src_entry,
 			void *data,
 			int (*match)(struct lock_list *entry, void *data),
 			struct lock_list **target_entry)
@@ -972,7 +972,7 @@ static inline int __bfs_forward(struct lock_list *src_entry,
 
 }
 
-static inline int __bfs_backward(struct lock_list *src_entry,
+static inline int __bfs_backwards(struct lock_list *src_entry,
 			void *data,
 			int (*match)(struct lock_list *entry, void *data),
 			struct lock_list **target_entry)
@@ -1085,18 +1085,6 @@ static int noinline print_bfs_bug(int ret)
 	return 0;
 }
 
-#define RECURSION_LIMIT 40
-
-static int noinline print_infinite_recursion_bug(void)
-{
-	if (!debug_locks_off_graph_unlock())
-		return 0;
-
-	WARN_ON(1);
-
-	return 0;
-}
-
 unsigned long __lockdep_count_forward_deps(struct lock_class *class,
 					   unsigned int depth)
 {
@@ -1170,7 +1158,7 @@ check_noncircular(struct lock_list *root, struct lock_class *target,
 
 	debug_atomic_inc(&nr_cyclic_checks);
 
-	result = __bfs_forward(root, target, class_equal, target_entry);
+	result = __bfs_forwards(root, target, class_equal, target_entry);
 
 	return result;
 }
@@ -1181,101 +1169,70 @@ check_noncircular(struct lock_list *root, struct lock_class *target,
  * proving that two subgraphs can be connected by a new dependency
  * without creating any illegal irq-safe -> irq-unsafe lock dependency.
  */
-static enum lock_usage_bit find_usage_bit;
 static struct lock_class *forwards_match, *backwards_match;
 
+
+#define   BFS_PROCESS_RET(ret)	do { \
+					if (ret < 0) \
+						return print_bfs_bug(ret); \
+					if (ret == 1) \
+						return 1; \
+				} while (0)
+
+static inline int usage_match(struct lock_list *entry, void *bit)
+{
+	return entry->class->usage_mask & (1 << (enum lock_usage_bit)bit);
+}
+
+
+
 /*
  * Find a node in the forwards-direction dependency sub-graph starting
- * at <source> that matches <find_usage_bit>.
+ * at @root->class that matches @bit.
  *
- * Return 2 if such a node exists in the subgraph, and put that node
- * into <forwards_match>.
+ * Return 0 if such a node exists in the subgraph, and put that node
+ * into *@target_entry.
  *
- * Return 1 otherwise and keep <forwards_match> unchanged.
- * Return 0 on error.
+ * Return 1 otherwise and keep *@target_entry unchanged.
+ * Return <0 on error.
  */
-static noinline int
-find_usage_forwards(struct lock_class *source, unsigned int depth)
+static int
+find_usage_forwards(struct lock_list *root, enum lock_usage_bit bit,
+			struct lock_list **target_entry)
 {
-	struct lock_list *entry;
-	int ret;
-
-	if (lockdep_dependency_visit(source, depth))
-		return 1;
-
-	if (depth > max_recursion_depth)
-		max_recursion_depth = depth;
-	if (depth >= RECURSION_LIMIT)
-		return print_infinite_recursion_bug();
+	int result;
 
 	debug_atomic_inc(&nr_find_usage_forwards_checks);
-	if (source->usage_mask & (1 << find_usage_bit)) {
-		forwards_match = source;
-		return 2;
-	}
 
-	/*
-	 * Check this lock's dependency list:
-	 */
-	list_for_each_entry(entry, &source->locks_after, entry) {
-		debug_atomic_inc(&nr_find_usage_forwards_recursions);
-		ret = find_usage_forwards(entry->class, depth+1);
-		if (ret == 2 || ret == 0)
-			return ret;
-	}
-	return 1;
+	result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
+
+	return result;
 }
 
 /*
  * Find a node in the backwards-direction dependency sub-graph starting
- * at <source> that matches <find_usage_bit>.
+ * at @root->class that matches @bit.
  *
- * Return 2 if such a node exists in the subgraph, and put that node
- * into <backwards_match>.
+ * Return 0 if such a node exists in the subgraph, and put that node
+ * into *@target_entry.
  *
- * Return 1 otherwise and keep <backwards_match> unchanged.
- * Return 0 on error.
+ * Return 1 otherwise and keep *@target_entry unchanged.
+ * Return <0 on error.
  */
-static noinline int
-find_usage_backwards(struct lock_class *source, unsigned int depth)
+static int
+find_usage_backwards(struct lock_list *root, enum lock_usage_bit bit,
+			struct lock_list **target_entry)
 {
-	struct lock_list *entry;
-	int ret;
-
-	if (lockdep_dependency_visit(source, depth))
-		return 1;
-
-	if (!__raw_spin_is_locked(&lockdep_lock))
-		return DEBUG_LOCKS_WARN_ON(1);
-
-	if (depth > max_recursion_depth)
-		max_recursion_depth = depth;
-	if (depth >= RECURSION_LIMIT)
-		return print_infinite_recursion_bug();
+	int result;
 
 	debug_atomic_inc(&nr_find_usage_backwards_checks);
-	if (source->usage_mask & (1 << find_usage_bit)) {
-		backwards_match = source;
-		return 2;
-	}
 
-	if (!source && debug_locks_off_graph_unlock()) {
-		WARN_ON(1);
-		return 0;
-	}
+	result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
 
-	/*
-	 * Check this lock's dependency list:
-	 */
-	list_for_each_entry(entry, &source->locks_before, entry) {
-		debug_atomic_inc(&nr_find_usage_backwards_recursions);
-		ret = find_usage_backwards(entry->class, depth+1);
-		if (ret == 2 || ret == 0)
-			return ret;
-	}
-	return 1;
+	return result;
 }
 
+
 static int
 print_bad_irq_dependency(struct task_struct *curr,
 			 struct held_lock *prev,
@@ -1343,18 +1300,21 @@ check_usage(struct task_struct *curr, struct held_lock *prev,
 	    enum lock_usage_bit bit_forwards, const char *irqclass)
 {
 	int ret;
+	struct lock_list this;
+	struct lock_list *uninitialized_var(target_entry);
+
+	this.parent = NULL;
+
+	this.class = hlock_class(prev);
+	ret = find_usage_backwards(&this, bit_backwards, &target_entry);
+	BFS_PROCESS_RET(ret);
+	backwards_match = target_entry->class;
+
+	this.class = hlock_class(next);
+	ret = find_usage_forwards(&this, bit_forwards, &target_entry);
+	BFS_PROCESS_RET(ret);
+	forwards_match = target_entry->class;
 
-	find_usage_bit = bit_backwards;
-	/* fills in <backwards_match> */
-	ret = find_usage_backwards(hlock_class(prev), 0);
-	if (!ret || ret == 1)
-		return ret;
-
-	find_usage_bit = bit_forwards;
-	ret = find_usage_forwards(hlock_class(next), 0);
-	if (!ret || ret == 1)
-		return ret;
-	/* ret == 2 */
 	return print_bad_irq_dependency(curr, prev, next,
 			bit_backwards, bit_forwards, irqclass);
 }
@@ -2029,14 +1989,16 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this,
 		     enum lock_usage_bit bit, const char *irqclass)
 {
 	int ret;
+	struct lock_list root;
+	struct lock_list *uninitialized_var(target_entry);
 
-	find_usage_bit = bit;
-	/* fills in <forwards_match> */
-	ret = find_usage_forwards(hlock_class(this), 0);
-	if (!ret || ret == 1)
-		return ret;
+	root.parent = NULL;
+	root.class = hlock_class(this);
+	ret = find_usage_forwards(&root, bit, &target_entry);
+	BFS_PROCESS_RET(ret);
 
-	return print_irq_inversion_bug(curr, forwards_match, this, 1, irqclass);
+	return print_irq_inversion_bug(curr, target_entry->class,
+					this, 1, irqclass);
 }
 
 /*
@@ -2048,14 +2010,16 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this,
 		      enum lock_usage_bit bit, const char *irqclass)
 {
 	int ret;
+	struct lock_list root;
+	struct lock_list *uninitialized_var(target_entry);
 
-	find_usage_bit = bit;
-	/* fills in <backwards_match> */
-	ret = find_usage_backwards(hlock_class(this), 0);
-	if (!ret || ret == 1)
-		return ret;
+	root.parent = NULL;
+	root.class = hlock_class(this);
+	ret = find_usage_backwards(&root, bit, &target_entry);
+	BFS_PROCESS_RET(ret);
 
-	return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
+	return print_irq_inversion_bug(curr, target_entry->class,
+					this, 1, irqclass);
 }
 
 void print_irqtrace_events(struct task_struct *curr)
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 5/8] kernel:lockdep:introduce print_shortest_lock_dependencies
  2009-05-31 14:49         ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards " tom.leiming
@ 2009-05-31 14:49           ` tom.leiming
  2009-05-31 14:49             ` [PATCH 6/8] kernel:lockdep: implement lockdep_count_*ward_deps by BFS tom.leiming
  2009-05-31 15:14           ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS Daniel Walker
  1 sibling, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>

Since the shortest lock dependencies' path may be obtained by BFS,
we print the shortest one by print_shortest_lock_dependencies().

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c           |   93 +++++++++++++++++++++++++++++++------------
 kernel/lockdep_internals.h |    4 +-
 2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 94b2f1f..d839994 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -576,6 +576,36 @@ static void print_lock_class_header(struct lock_class *class, int depth)
 }
 
 /*
+ * printk the shortest lock dependencies from @start to @end in reverse order:
+ */
+static void __used
+print_shortest_lock_dependencies(struct lock_list *leaf,
+				struct lock_list *root)
+{
+	struct lock_list *entry = leaf;
+	int depth;
+
+	/*compute depth from generated tree by BFS*/
+	depth = get_lock_depth(leaf);
+
+	do {
+		print_lock_class_header(entry->class, depth);
+		printk("%*s ... acquired at:\n", depth, "");
+		print_stack_trace(&entry->trace, 2);
+		printk("\n");
+
+		if (depth == 0 && (entry != root)) {
+			printk("lockdep:%s bad BFS generated tree\n", __func__);
+			break;
+		}
+
+		entry = get_lock_parent(entry);
+		depth--;
+	} while (entry && (depth >= 0));
+
+	return;
+}
+/*
  * printk all lock dependencies starting at <entry>:
  */
 static void __used
@@ -992,7 +1022,7 @@ static inline int __bfs_backwards(struct lock_list *src_entry,
  * has been detected):
  */
 static noinline int
-print_circular_bug_entry(struct lock_list *target, unsigned int depth)
+print_circular_bug_entry(struct lock_list *target, int depth)
 {
 	if (debug_locks_silent)
 		return 0;
@@ -1047,7 +1077,7 @@ static noinline int print_circular_bug(struct lock_list *this,
 {
 	struct task_struct *curr = current;
 	struct lock_list *parent;
-	unsigned long depth;
+	int depth;
 
 	if (!debug_locks_off_graph_unlock() || debug_locks_silent)
 		return 0;
@@ -1169,7 +1199,6 @@ check_noncircular(struct lock_list *root, struct lock_class *target,
  * proving that two subgraphs can be connected by a new dependency
  * without creating any illegal irq-safe -> irq-unsafe lock dependency.
  */
-static struct lock_class *forwards_match, *backwards_match;
 
 
 #define   BFS_PROCESS_RET(ret)	do { \
@@ -1235,6 +1264,10 @@ find_usage_backwards(struct lock_list *root, enum lock_usage_bit bit,
 
 static int
 print_bad_irq_dependency(struct task_struct *curr,
+			 struct lock_list *prev_root,
+			 struct lock_list *next_root,
+			 struct lock_list *backwards_entry,
+			 struct lock_list *forwards_entry,
 			 struct held_lock *prev,
 			 struct held_lock *next,
 			 enum lock_usage_bit bit1,
@@ -1267,26 +1300,32 @@ print_bad_irq_dependency(struct task_struct *curr,
 
 	printk("\nbut this new dependency connects a %s-irq-safe lock:\n",
 		irqclass);
-	print_lock_name(backwards_match);
+	print_lock_name(backwards_entry->class);
 	printk("\n... which became %s-irq-safe at:\n", irqclass);
 
-	print_stack_trace(backwards_match->usage_traces + bit1, 1);
+	print_stack_trace(backwards_entry->class->usage_traces + bit1, 1);
 
 	printk("\nto a %s-irq-unsafe lock:\n", irqclass);
-	print_lock_name(forwards_match);
+	print_lock_name(forwards_entry->class);
 	printk("\n... which became %s-irq-unsafe at:\n", irqclass);
 	printk("...");
 
-	print_stack_trace(forwards_match->usage_traces + bit2, 1);
+	print_stack_trace(forwards_entry->class->usage_traces + bit2, 1);
 
 	printk("\nother info that might help us debug this:\n\n");
 	lockdep_print_held_locks(curr);
 
-	printk("\nthe %s-irq-safe lock's dependencies:\n", irqclass);
-	print_lock_dependencies(backwards_match, 0);
+	printk("\nthe dependencies between %s-irq-safe lock", irqclass);
+	printk(" and the holding lock:\n");
+	if (!save_trace(&prev_root->trace))
+		return 0;
+	print_shortest_lock_dependencies(backwards_entry, prev_root);
 
-	printk("\nthe %s-irq-unsafe lock's dependencies:\n", irqclass);
-	print_lock_dependencies(forwards_match, 0);
+	printk("\nthe dependencies between the lock to be acquired");
+	printk(" and %s-irq-unsafe lock:\n", irqclass);
+	if (!save_trace(&next_root->trace))
+		return 0;
+	print_shortest_lock_dependencies(forwards_entry, next_root);
 
 	printk("\nstack backtrace:\n");
 	dump_stack();
@@ -1300,22 +1339,24 @@ check_usage(struct task_struct *curr, struct held_lock *prev,
 	    enum lock_usage_bit bit_forwards, const char *irqclass)
 {
 	int ret;
-	struct lock_list this;
+	struct lock_list this, that;
 	struct lock_list *uninitialized_var(target_entry);
+	struct lock_list *uninitialized_var(target_entry1);
 
 	this.parent = NULL;
 
 	this.class = hlock_class(prev);
 	ret = find_usage_backwards(&this, bit_backwards, &target_entry);
 	BFS_PROCESS_RET(ret);
-	backwards_match = target_entry->class;
 
-	this.class = hlock_class(next);
-	ret = find_usage_forwards(&this, bit_forwards, &target_entry);
+	that.parent = NULL;
+	that.class = hlock_class(next);
+	ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
 	BFS_PROCESS_RET(ret);
-	forwards_match = target_entry->class;
 
-	return print_bad_irq_dependency(curr, prev, next,
+	return print_bad_irq_dependency(curr, &this, &that,
+			target_entry, target_entry1,
+			prev, next,
 			bit_backwards, bit_forwards, irqclass);
 }
 
@@ -1944,7 +1985,8 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
  * print irq inversion bug:
  */
 static int
-print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
+print_irq_inversion_bug(struct task_struct *curr,
+			struct lock_list *root, struct lock_list *other,
 			struct held_lock *this, int forwards,
 			const char *irqclass)
 {
@@ -1962,17 +2004,16 @@ print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
 		printk("but this lock took another, %s-unsafe lock in the past:\n", irqclass);
 	else
 		printk("but this lock was taken by another, %s-safe lock in the past:\n", irqclass);
-	print_lock_name(other);
+	print_lock_name(other->class);
 	printk("\n\nand interrupts could create inverse lock ordering between them.\n\n");
 
 	printk("\nother info that might help us debug this:\n");
 	lockdep_print_held_locks(curr);
 
-	printk("\nthe first lock's dependencies:\n");
-	print_lock_dependencies(hlock_class(this), 0);
-
-	printk("\nthe second lock's dependencies:\n");
-	print_lock_dependencies(other, 0);
+	printk("\nthe shortest dependencies between 2nd lock and 1st lock:\n");
+	if (!save_trace(&root->trace))
+		return 0;
+	print_shortest_lock_dependencies(other, root);
 
 	printk("\nstack backtrace:\n");
 	dump_stack();
@@ -1997,7 +2038,7 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this,
 	ret = find_usage_forwards(&root, bit, &target_entry);
 	BFS_PROCESS_RET(ret);
 
-	return print_irq_inversion_bug(curr, target_entry->class,
+	return print_irq_inversion_bug(curr, &root, target_entry,
 					this, 1, irqclass);
 }
 
@@ -2018,7 +2059,7 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this,
 	ret = find_usage_backwards(&root, bit, &target_entry);
 	BFS_PROCESS_RET(ret);
 
-	return print_irq_inversion_bug(curr, target_entry->class,
+	return print_irq_inversion_bug(curr, &root, target_entry,
 					this, 1, irqclass);
 }
 
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index c2f6594..b115aaa 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -219,9 +219,9 @@ static inline struct lock_list *get_lock_parent(struct lock_list *child)
 	return child->parent;
 }
 
-static inline unsigned long get_lock_depth(struct lock_list *child)
+static inline int get_lock_depth(struct lock_list *child)
 {
-	unsigned long depth = 0;
+	int depth = 0;
 	struct lock_list *parent;
 
 	while ((parent = get_lock_parent(child))) {
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 6/8] kernel:lockdep: implement lockdep_count_*ward_deps by BFS
  2009-05-31 14:49           ` [PATCH 5/8] kernel:lockdep:introduce print_shortest_lock_dependencies tom.leiming
@ 2009-05-31 14:49             ` tom.leiming
  2009-05-31 14:49               ` [PATCH 7/8] kernel:lockdep: update memory usage introduced " tom.leiming
  0 siblings, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>


Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |   52 +++++++++++++++++++++++++---------------------------
 1 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index d839994..6e31e4b 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -1115,61 +1115,59 @@ static int noinline print_bfs_bug(int ret)
 	return 0;
 }
 
-unsigned long __lockdep_count_forward_deps(struct lock_class *class,
-					   unsigned int depth)
+static int noop_count(struct lock_list *entry, void *data)
 {
-	struct lock_list *entry;
-	unsigned long ret = 1;
+	(*(unsigned long *)data)++;
+	return 0;
+}
 
-	if (lockdep_dependency_visit(class, depth))
-		return 0;
+unsigned long __lockdep_count_forward_deps(struct lock_list *this)
+{
+	unsigned long  count = 0;
+	struct lock_list *uninitialized_var(target_entry);
 
-	/*
-	 * Recurse this class's dependency list:
-	 */
-	list_for_each_entry(entry, &class->locks_after, entry)
-		ret += __lockdep_count_forward_deps(entry->class, depth + 1);
+	__bfs_forwards(this, (void *)&count, noop_count, &target_entry);
 
-	return ret;
+	return count;
 }
-
 unsigned long lockdep_count_forward_deps(struct lock_class *class)
 {
 	unsigned long ret, flags;
+	struct lock_list this;
+
+	this.parent = NULL;
+	this.class = class;
 
 	local_irq_save(flags);
 	__raw_spin_lock(&lockdep_lock);
-	ret = __lockdep_count_forward_deps(class, 0);
+	ret = __lockdep_count_forward_deps(&this);
 	__raw_spin_unlock(&lockdep_lock);
 	local_irq_restore(flags);
 
 	return ret;
 }
 
-unsigned long __lockdep_count_backward_deps(struct lock_class *class,
-					    unsigned int depth)
+unsigned long __lockdep_count_backward_deps(struct lock_list *this)
 {
-	struct lock_list *entry;
-	unsigned long ret = 1;
+	unsigned long  count = 0;
+	struct lock_list *uninitialized_var(target_entry);
 
-	if (lockdep_dependency_visit(class, depth))
-		return 0;
-	/*
-	 * Recurse this class's dependency list:
-	 */
-	list_for_each_entry(entry, &class->locks_before, entry)
-		ret += __lockdep_count_backward_deps(entry->class, depth + 1);
+	__bfs_backwards(this, (void *)&count, noop_count, &target_entry);
 
-	return ret;
+	return count;
 }
 
 unsigned long lockdep_count_backward_deps(struct lock_class *class)
 {
 	unsigned long ret, flags;
+	struct lock_list this;
+
+	this.parent = NULL;
+	this.class = class;
 
 	local_irq_save(flags);
 	__raw_spin_lock(&lockdep_lock);
-	ret = __lockdep_count_backward_deps(class, 0);
+	ret = __lockdep_count_backward_deps(&this);
 	__raw_spin_unlock(&lockdep_lock);
 	local_irq_restore(flags);
 
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 7/8] kernel:lockdep: update memory usage introduced by BFS
  2009-05-31 14:49             ` [PATCH 6/8] kernel:lockdep: implement lockdep_count_*ward_deps by BFS tom.leiming
@ 2009-05-31 14:49               ` tom.leiming
  2009-05-31 14:49                 ` [PATCH 8/8] kernel:lockdep:add statistics info for max bfs queue depth tom.leiming
  0 siblings, 1 reply; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>


Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 6e31e4b..faa39cb 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -3429,7 +3429,8 @@ void __init lockdep_info(void)
 		sizeof(struct list_head) * CLASSHASH_SIZE +
 		sizeof(struct lock_list) * MAX_LOCKDEP_ENTRIES +
 		sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS +
-		sizeof(struct list_head) * CHAINHASH_SIZE) / 1024);
+		sizeof(struct list_head) * CHAINHASH_SIZE) / 1024 +
+		sizeof(struct circular_queue) + sizeof(bfs_accessed));
 
 	printk(" per task-struct memory footprint: %lu bytes\n",
 		sizeof(struct held_lock) * MAX_LOCK_DEPTH);
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 8/8] kernel:lockdep:add statistics info for max bfs queue depth
  2009-05-31 14:49               ` [PATCH 7/8] kernel:lockdep: update memory usage introduced " tom.leiming
@ 2009-05-31 14:49                 ` tom.leiming
  0 siblings, 0 replies; 228+ messages in thread
From: tom.leiming @ 2009-05-31 14:49 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, akpm, a.p.zijlstra, Ming Lei

From: Ming Lei <tom.leiming@gmail.com>


Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c           |    6 +++++-
 kernel/lockdep_internals.h |    3 ++-
 kernel/lockdep_proc.c      |    2 ++
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index faa39cb..b20f08b 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -929,7 +929,7 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
 
 unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
 static struct circular_queue  lock_cq;
-
+unsigned int max_bfs_queue_depth;
 static int __bfs(struct lock_list *source_entry,
 			void *data,
 			int (*match)(struct lock_list *entry, void *data),
@@ -975,6 +975,7 @@ static int __bfs(struct lock_list *source_entry,
 
 		list_for_each_entry(entry, head, entry) {
 			if (!lock_accessed(entry)) {
+				unsigned int cq_depth;
 				mark_lock_accessed(entry, lock);
 				if (match(entry, data)) {
 					*target_entry = entry;
@@ -986,6 +987,9 @@ static int __bfs(struct lock_list *source_entry,
 					ret = -1;
 					goto exit;
 				}
+				cq_depth = __cq_get_elem_count(cq);
+				if (max_bfs_queue_depth < cq_depth)
+					max_bfs_queue_depth = cq_depth;
 			}
 		}
 	}
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index b115aaa..6baa880 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -138,6 +138,7 @@ extern atomic_t nr_find_usage_backwards_recursions;
 #endif
 
 
+extern unsigned int max_bfs_queue_depth;
 extern unsigned long nr_list_entries;
 extern struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
 extern unsigned long bfs_accessed[];
@@ -191,7 +192,7 @@ static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
 	return 0;
 }
 
-static inline int __cq_get_elem_count(struct circular_queue *cq)
+static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
 {
 	return (cq->rear - cq->front)&(MAX_CIRCULAR_QUE_SIZE-1);
 }
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index d7135aa..9a1bf34 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -411,6 +411,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
 			max_lockdep_depth);
 	seq_printf(m, " max recursion depth:           %11u\n",
 			max_recursion_depth);
+	seq_printf(m, " max bfs queue depth:           %11u\n",
+			max_bfs_queue_depth);
 	lockdep_stats_debug_show(m);
 	seq_printf(m, " debug_locks:                   %11u\n",
 			debug_locks);
-- 
1.6.0.GIT


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS
  2009-05-31 14:49         ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards " tom.leiming
  2009-05-31 14:49           ` [PATCH 5/8] kernel:lockdep:introduce print_shortest_lock_dependencies tom.leiming
@ 2009-05-31 15:14           ` Daniel Walker
  2009-06-01  0:14             ` Ming Lei
  1 sibling, 1 reply; 228+ messages in thread
From: Daniel Walker @ 2009-05-31 15:14 UTC (permalink / raw)
  To: tom.leiming; +Cc: mingo, linux-kernel, akpm, a.p.zijlstra

On Sun, 2009-05-31 at 22:49 +0800, tom.leiming@gmail.com wrote:
> -static inline int __bfs_forward(struct lock_list *src_entry,
> +static inline int __bfs_forwards(struct lock_list *src_entry,

Your patchset seems a bit young still .. For instance, adding an "s" in
the above line, that's just flux that really shouldn't be there.. I was
reviewing your patches but I stopped because it just looks like you need
to organize them better. I wonder for one, if they bisect or if they
pass checkpatch .. Your code also seems to have a lot of other little
cleanup type issues..

Daniel


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS
  2009-05-31 15:14           ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS Daniel Walker
@ 2009-06-01  0:14             ` Ming Lei
  0 siblings, 0 replies; 228+ messages in thread
From: Ming Lei @ 2009-06-01  0:14 UTC (permalink / raw)
  To: Daniel Walker; +Cc: mingo, linux-kernel, akpm, a.p.zijlstra

2009/5/31 Daniel Walker <dwalker@fifo99.com>:
> On Sun, 2009-05-31 at 22:49 +0800, tom.leiming@gmail.com wrote:
>> -static inline int __bfs_forward(struct lock_list *src_entry,
>> +static inline int __bfs_forwards(struct lock_list *src_entry,
>
> Your patchset seems a bit young still .. For instance, adding an "s" in
> the above line, that's just flux that really shouldn't be there.. I was
> reviewing your patches but I stopped because it just looks like you need
> to organize them better. I wonder for one, if they bisect or if they
> pass checkpatch .. Your code also seems to have a lot of other little

Only No 3. patch has a checkpatch error, so we can continue to review them
now,  can't we?

> cleanup type issues..
>
> Daniel
>
>



-- 
Lei Ming

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-05-31 14:49 ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS tom.leiming
  2009-05-31 14:49   ` [PATCH 1/8] kernel:lockdep:improve implementation of BFS tom.leiming
@ 2009-06-08 12:22   ` Peter Zijlstra
  2009-06-08 13:38     ` Ming Lei
                       ` (2 more replies)
  1 sibling, 3 replies; 228+ messages in thread
From: Peter Zijlstra @ 2009-06-08 12:22 UTC (permalink / raw)
  To: tom.leiming; +Cc: mingo, linux-kernel, akpm

On Sun, 2009-05-31 at 22:49 +0800, tom.leiming@gmail.com wrote:
> Hi,
> Currently lockdep uses recursion DFS(depth-first search) algorithm to
> search target in checking lock circle(check_noncircular()),irq-safe
> -> irq-unsafe(check_irq_usage()) and irq inversion when adding a new
> lock dependency. This patches replace the current DFS with BFS, based on
> the following consideration:
> 
>      1,no loss of efficiency, no matter DFS or BFS, the running time
>      are O(V+E) (V is vertex count, and E is edge count of one
>      graph);
> 
>      2,BFS may be easily implemented by circular queue and consumes
>      much less kernel stack space than DFS for DFS is implemented by
>      recursion.
> 
>      3, The shortest path can be obtained by BFS if the target is
>      found, but can't be got by DFS. By the shortest path, we can
>      shorten the lock dependency chain and help to troubleshoot lock
>      problem easier than before.
> 

OK, so I applied the patches and the cleanup below.

mostly little style nits and moving the circular queue into lockdep.c
(nobody else uses it, so why share it?).

One thing though, macros with return statements?! that's seriously bad
style, don't do that.

One thing that worries me a little is that we loose DaveM's
lockdep_dependency_visit() optimization. My brain seems unwilling to
co-operate on determining if BFS would make that redundant, so a little
word on that would be appreciated.

Then I booted it and all hell broke loose, so either I wrecked something
or you did :-), would you terribly mind poking at that a little?

Over all I like that patches, but they need a little more work. Could
you send delta patches from now on?

---

[    0.000999] =================================
[    0.000999] [ BUG: bad contention detected! ]
[    0.000999] ---------------------------------
[    0.000999] swapper/0 is trying to contend lock (old_style_seqlock_init) at:
[    0.000999] [<ffffffff8133a795>] _spin_lock+0x6d/0x75
[    0.000999] but there are no locks held!
[    0.000999]
[    0.000999] other info that might help us debug this:
[    0.000999] 1 lock held by swapper/0:
[    0.000999]  #0:  (xtime_lock){-.....}, at: [<ffffffff8106a360>] tick_periodic+0x1d/0x74
[    0.000999]
[    0.000999] stack backtrace:
[    0.000999] Pid: 0, comm: swapper Not tainted 2.6.30-rc8-tip #1049
[    0.000999] Call Trace:
[    0.000999]  <IRQ>  [<ffffffff81071bd8>] print_lock_contention_bug+0x100/0x110
[    0.000999]  [<ffffffff81071ce0>] lock_acquired+0xf8/0x2b4
[    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
[    0.000999]  [<ffffffff8133a795>] _spin_lock+0x6d/0x75
[    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
[    0.000999]  [<ffffffff81010221>] update_vsyscall+0x2d/0xd0
[    0.000999]  [<ffffffff81067469>] update_wall_time+0x4c1/0x4cc
[    0.000999]  [<ffffffff8105274b>] do_timer+0x15/0x1c
[    0.000999]  [<ffffffff8106a37e>] tick_periodic+0x3b/0x74
[    0.000999]  [<ffffffff8106a3db>] tick_handle_periodic+0x24/0x71
[    0.000999]  [<ffffffff8100ea23>] timer_interrupt+0x1f/0x26
[    0.000999]  [<ffffffff8109348b>] handle_IRQ_event+0x8e/0x19c
[    0.000999]  [<ffffffff8109501e>] handle_level_irq+0x9d/0xf3
[    0.000999]  [<ffffffff8100e24b>] handle_irq+0x24/0x2c
[    0.000999]  [<ffffffff8133f55b>] do_IRQ+0x63/0xc2
[    0.000999]  [<ffffffff8100c713>] ret_from_intr+0x0/0xf
[    0.000999]  <EOI>  [<ffffffff8133a538>] ? _spin_unlock_irqrestore+0x47/0x6d
[    0.000999]  [<ffffffff81093eea>] ? __setup_irq+0x1ea/0x277
[    0.000999]  [<ffffffff81094120>] ? setup_irq+0x25/0x2a
[    0.000999]  [<ffffffff8158e63e>] ? hpet_time_init+0x20/0x22
[    0.000999]  [<ffffffff8158bbcc>] ? start_kernel+0x2ee/0x37a
[    0.000999]  [<ffffffff8158b29a>] ? x86_64_start_reservations+0xaa/0xae
[    0.000999]  [<ffffffff8158b37f>] ? x86_64_start_kernel+0xe1/0xe8

And ended in a stuck boot at:

[   65.411804] rmmod         R  running task        0   616      1 0x00000008
[   65.411804]  ffff8800023c41a0 ffffea0003336ba8 ffff88007e3a3c08 ffffffff8106f71a
[   65.411804]  ffff88007e3a3c48 0000000000000202 ffff88007f821600 0000000000001823
[   65.411804]  ffff88007e109d20 ffff88007f8b5c80 0000000000000000 ffff88007e3a3d18
[   65.411804] Call Trace:
[   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
[   65.411804]  [<ffffffff8113f1b6>] ? release_sysfs_dirent+0x91/0xb1
[   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
[   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
[   65.411804]  [<ffffffff8113eff3>] ? sysfs_addrm_start+0x7d/0xaa
[   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
[   65.411804]  [<ffffffff810113ff>] ? alternatives_smp_module_del+0x37/0xd0
[   65.411804]  [<ffffffff810e61ee>] ? free_percpu+0x38/0xf8
[   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
[   65.411804]  [<ffffffff8133a542>] ? _spin_unlock_irqrestore+0x51/0x6d
[   65.411804]  [<ffffffff810e62a5>] ? free_percpu+0xef/0xf8
[   65.411804]  [<ffffffff8107ade5>] ? free_module+0x104/0x118
[   65.411804]  [<ffffffff8107b0a8>] ? sys_delete_module+0x20c/0x22e
[   65.411804]  [<ffffffff81339f88>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[   65.411804]  [<ffffffff8100bcdb>] ? system_call_fastpath+0x16/0x1b

( I can send you my .config if you cannot reproduce, but I don't think
its anything special )

---

Subject: lockdep: clean up after BFS patches
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
Date: Mon Jun 08 13:32:31 CEST 2009


LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 include/linux/lockdep.h    |    7 -
 kernel/lockdep.c           |  232 +++++++++++++++++++++++++++------------------
 kernel/lockdep_internals.h |   97 ------------------
 3 files changed, 147 insertions(+), 189 deletions(-)
===================================================================
===================================================================
--- linux-2.6.orig/include/linux/lockdep.h
+++ linux-2.6/include/linux/lockdep.h
@@ -58,7 +58,6 @@ struct lock_class {
 
 	struct lockdep_subclass_key	*key;
 	unsigned int			subclass;
-	unsigned int			dep_gen_id;
 
 	/*
 	 * IRQ/softirq usage tracking bits:
@@ -150,9 +149,9 @@ struct lock_list {
 	struct stack_trace		trace;
 	int				distance;
 
-	/*The parent field is used to implement breadth-first search,and
-	 *the bit 0 is reused to indicate if the lock has been accessed
-	 *in BFS.
+	/*
+	 * The parent field is used to implement breadth-first search, and the
+	 * bit 0 is reused to indicate if the lock has been accessed in BFS.
 	 */
 	struct lock_list		*parent;
 };
===================================================================
--- linux-2.6.orig/kernel/lockdep.c
+++ linux-2.6/kernel/lockdep.c
@@ -43,6 +43,7 @@
 #include <linux/ftrace.h>
 #include <linux/stringify.h>
 #include <linux/bitops.h>
+
 #include <asm/sections.h>
 
 #include "lockdep_internals.h"
@@ -118,7 +119,7 @@ static inline int debug_locks_off_graph_
 static int lockdep_initialized;
 
 unsigned long nr_list_entries;
-struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
+static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
 
 /*
  * All data structures here are protected by the global debug_lock.
@@ -390,19 +391,6 @@ unsigned int nr_process_chains;
 unsigned int max_lockdep_depth;
 unsigned int max_recursion_depth;
 
-static unsigned int lockdep_dependency_gen_id;
-
-static bool lockdep_dependency_visit(struct lock_class *source,
-				     unsigned int depth)
-{
-	if (!depth)
-		lockdep_dependency_gen_id++;
-	if (source->dep_gen_id == lockdep_dependency_gen_id)
-		return true;
-	source->dep_gen_id = lockdep_dependency_gen_id;
-	return false;
-}
-
 #ifdef CONFIG_DEBUG_LOCKDEP
 /*
  * We cannot printk in early bootup code. Not even early_printk()
@@ -575,64 +563,6 @@ static void print_lock_class_header(stru
 	print_ip_sym((unsigned long)class->key);
 }
 
-/*
- * printk the shortest lock dependencies from @start to @end in reverse order:
- */
-static void __used
-print_shortest_lock_dependencies(struct lock_list *leaf,
-				struct lock_list *root)
-{
-	struct lock_list *entry = leaf;
-	int depth;
-
-	/*compute depth from generated tree by BFS*/
-	depth = get_lock_depth(leaf);
-
-	do {
-		print_lock_class_header(entry->class, depth);
-		printk("%*s ... acquired at:\n", depth, "");
-		print_stack_trace(&entry->trace, 2);
-		printk("\n");
-
-		if (depth == 0 && (entry != root)) {
-			printk("lockdep:%s bad BFS generated tree\n", __func__);
-			break;
-		}
-
-		entry = get_lock_parent(entry);
-		depth--;
-	} while (entry && (depth >= 0));
-
-	return;
-}
-/*
- * printk all lock dependencies starting at <entry>:
- */
-static void __used
-print_lock_dependencies(struct lock_class *class, int depth)
-{
-	struct lock_list *entry;
-
-	if (lockdep_dependency_visit(class, depth))
-		return;
-
-	if (DEBUG_LOCKS_WARN_ON(depth >= 20))
-		return;
-
-	print_lock_class_header(class, depth);
-
-	list_for_each_entry(entry, &class->locks_after, entry) {
-		if (DEBUG_LOCKS_WARN_ON(!entry->class))
-			return;
-
-		print_lock_dependencies(entry->class, depth + 1);
-
-		printk("%*s ... acquired at:\n",depth,"");
-		print_stack_trace(&entry->trace, 2);
-		printk("\n");
-	}
-}
-
 static void print_kernel_version(void)
 {
 	printk("%s %.*s\n", init_utsname()->release,
@@ -927,14 +857,106 @@ static int add_lock_to_list(struct lock_
 	return 1;
 }
 
-unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
-static struct circular_queue  lock_cq;
+/*For good efficiency of modular, we use power of 2*/
+#define MAX_CIRCULAR_QUEUE_SIZE		4096UL
+#define CQ_MASK				(MAX_CIRCULAR_QUEUE_SIZE-1)
+
+/* The circular_queue and helpers is used to implement the
+ * breadth-first search(BFS)algorithem, by which we can build
+ * the shortest path from the next lock to be acquired to the
+ * previous held lock if there is a circular between them.
+ * */
+struct circular_queue {
+	unsigned long element[MAX_CIRCULAR_QUEUE_SIZE];
+	unsigned int  front, rear;
+};
+
+static struct circular_queue lock_cq;
+static unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
+
 unsigned int max_bfs_queue_depth;
+
+static inline void __cq_init(struct circular_queue *cq)
+{
+	cq->front = cq->rear = 0;
+	bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
+}
+
+static inline int __cq_empty(struct circular_queue *cq)
+{
+	return (cq->front == cq->rear);
+}
+
+static inline int __cq_full(struct circular_queue *cq)
+{
+	return ((cq->rear + 1) & CQ_MASK) == cq->front;
+}
+
+static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
+{
+	if (__cq_full(cq))
+		return -1;
+
+	cq->element[cq->rear] = elem;
+	cq->rear = (cq->rear + 1) & CQ_MASK;
+	return 0;
+}
+
+static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
+{
+	if (__cq_empty(cq))
+		return -1;
+
+	*elem = cq->element[cq->front];
+	cq->front = (cq->front + 1) & CQ_MASK;
+	return 0;
+}
+
+static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
+{
+	return (cq->rear - cq->front) & CQ_MASK;
+}
+
+static inline void mark_lock_accessed(struct lock_list *lock,
+					struct lock_list *parent)
+{
+	unsigned long nr;
+	nr = lock - list_entries;
+	WARN_ON(nr >= nr_list_entries);
+	lock->parent = parent;
+	set_bit(nr, bfs_accessed);
+}
+
+static inline unsigned long lock_accessed(struct lock_list *lock)
+{
+	unsigned long nr;
+	nr = lock - list_entries;
+	WARN_ON(nr >= nr_list_entries);
+	return test_bit(nr, bfs_accessed);
+}
+
+static inline struct lock_list *get_lock_parent(struct lock_list *child)
+{
+	return child->parent;
+}
+
+static inline int get_lock_depth(struct lock_list *child)
+{
+	int depth = 0;
+	struct lock_list *parent;
+
+	while ((parent = get_lock_parent(child))) {
+		child = parent;
+		depth++;
+	}
+	return depth;
+}
+
 static int __bfs(struct lock_list *source_entry,
-			void *data,
-			int (*match)(struct lock_list *entry, void *data),
-			struct lock_list **target_entry,
-			int forward)
+		 void *data,
+		 int (*match)(struct lock_list *entry, void *data),
+		 struct lock_list **target_entry,
+		 int forward)
 {
 	struct lock_list *entry;
 	struct list_head *head;
@@ -1202,14 +1224,6 @@ check_noncircular(struct lock_list *root
  * without creating any illegal irq-safe -> irq-unsafe lock dependency.
  */
 
-
-#define   BFS_PROCESS_RET(ret)	do { \
-					if (ret < 0) \
-						return print_bfs_bug(ret); \
-					if (ret == 1) \
-						return 1; \
-				} while (0)
-
 static inline int usage_match(struct lock_list *entry, void *bit)
 {
 	return entry->class->usage_mask & (1 << (enum lock_usage_bit)bit);
@@ -1236,6 +1250,8 @@ find_usage_forwards(struct lock_list *ro
 	debug_atomic_inc(&nr_find_usage_forwards_checks);
 
 	result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
+	if (result < 0)
+		return print_bfs_bug(result);
 
 	return result;
 }
@@ -1259,10 +1275,42 @@ find_usage_backwards(struct lock_list *r
 	debug_atomic_inc(&nr_find_usage_backwards_checks);
 
 	result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
+	if (result < 0)
+		return print_bfs_bug(result);
 
 	return result;
 }
 
+/*
+ * printk the shortest lock dependencies from @start to @end in reverse order:
+ */
+static void __used
+print_shortest_lock_dependencies(struct lock_list *leaf,
+				struct lock_list *root)
+{
+	struct lock_list *entry = leaf;
+	int depth;
+
+	/*compute depth from generated tree by BFS*/
+	depth = get_lock_depth(leaf);
+
+	do {
+		print_lock_class_header(entry->class, depth);
+		printk("%*s ... acquired at:\n", depth, "");
+		print_stack_trace(&entry->trace, 2);
+		printk("\n");
+
+		if (depth == 0 && (entry != root)) {
+			printk("lockdep:%s bad BFS generated tree\n", __func__);
+			break;
+		}
+
+		entry = get_lock_parent(entry);
+		depth--;
+	} while (entry && (depth >= 0));
+
+	return;
+}
 
 static int
 print_bad_irq_dependency(struct task_struct *curr,
@@ -1349,12 +1397,14 @@ check_usage(struct task_struct *curr, st
 
 	this.class = hlock_class(prev);
 	ret = find_usage_backwards(&this, bit_backwards, &target_entry);
-	BFS_PROCESS_RET(ret);
+	if (!ret || ret == 1)
+		return ret;
 
 	that.parent = NULL;
 	that.class = hlock_class(next);
 	ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
-	BFS_PROCESS_RET(ret);
+	if (!ret || ret == 1)
+		return ret;
 
 	return print_bad_irq_dependency(curr, &this, &that,
 			target_entry, target_entry1,
@@ -2038,7 +2088,8 @@ check_usage_forwards(struct task_struct 
 	root.parent = NULL;
 	root.class = hlock_class(this);
 	ret = find_usage_forwards(&root, bit, &target_entry);
-	BFS_PROCESS_RET(ret);
+	if (!ret || ret == 1)
+		return ret;
 
 	return print_irq_inversion_bug(curr, &root, target_entry,
 					this, 1, irqclass);
@@ -2059,7 +2110,8 @@ check_usage_backwards(struct task_struct
 	root.parent = NULL;
 	root.class = hlock_class(this);
 	ret = find_usage_backwards(&root, bit, &target_entry);
-	BFS_PROCESS_RET(ret);
+	if (!ret || ret == 1)
+		return ret;
 
 	return print_irq_inversion_bug(curr, &root, target_entry,
 					this, 1, irqclass);
===================================================================
--- linux-2.6.orig/kernel/lockdep_internals.h
+++ linux-2.6/kernel/lockdep_internals.h
@@ -91,6 +91,8 @@ extern unsigned int nr_process_chains;
 extern unsigned int max_lockdep_depth;
 extern unsigned int max_recursion_depth;
 
+extern unsigned int max_bfs_queue_depth;
+
 #ifdef CONFIG_PROVE_LOCKING
 extern unsigned long lockdep_count_forward_deps(struct lock_class *);
 extern unsigned long lockdep_count_backward_deps(struct lock_class *);
@@ -136,98 +138,3 @@ extern atomic_t nr_find_usage_backwards_
 # define debug_atomic_dec(ptr)		do { } while (0)
 # define debug_atomic_read(ptr)		0
 #endif
-
-
-extern unsigned int max_bfs_queue_depth;
-extern unsigned long nr_list_entries;
-extern struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
-extern unsigned long bfs_accessed[];
-
-/*For good efficiency of modular, we use power of 2*/
-#define  MAX_CIRCULAR_QUE_SIZE	    4096UL
-
-/* The circular_queue and helpers is used to implement the
- * breadth-first search(BFS)algorithem, by which we can build
- * the shortest path from the next lock to be acquired to the
- * previous held lock if there is a circular between them.
- * */
-struct circular_queue{
-	unsigned long element[MAX_CIRCULAR_QUE_SIZE];
-	unsigned int  front, rear;
-};
-
-static inline void __cq_init(struct circular_queue *cq)
-{
-	cq->front = cq->rear = 0;
-	bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
-}
-
-static inline int __cq_empty(struct circular_queue *cq)
-{
-	return (cq->front == cq->rear);
-}
-
-static inline int __cq_full(struct circular_queue *cq)
-{
-	return ((cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1))  == cq->front;
-}
-
-static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
-{
-	if (__cq_full(cq))
-		return -1;
-
-	cq->element[cq->rear] = elem;
-	cq->rear = (cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
-	return 0;
-}
-
-static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
-{
-	if (__cq_empty(cq))
-		return -1;
-
-	*elem = cq->element[cq->front];
-	cq->front = (cq->front + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
-	return 0;
-}
-
-static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
-{
-	return (cq->rear - cq->front)&(MAX_CIRCULAR_QUE_SIZE-1);
-}
-
-static inline void mark_lock_accessed(struct lock_list *lock,
-					struct lock_list *parent)
-{
-	unsigned long nr;
-	nr = lock - list_entries;
-	WARN_ON(nr >= nr_list_entries);
-	lock->parent = parent;
-	set_bit(nr, bfs_accessed);
-}
-
-static inline unsigned long lock_accessed(struct lock_list *lock)
-{
-	unsigned long nr;
-	nr = lock - list_entries;
-	WARN_ON(nr >= nr_list_entries);
-	return test_bit(nr, bfs_accessed);
-}
-
-static inline struct lock_list *get_lock_parent(struct lock_list *child)
-{
-	return child->parent;
-}
-
-static inline int get_lock_depth(struct lock_list *child)
-{
-	int depth = 0;
-	struct lock_list *parent;
-
-	while ((parent = get_lock_parent(child))) {
-		child = parent;
-		depth++;
-	}
-	return depth;
-}



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
@ 2009-06-08 13:38     ` Ming Lei
  2009-06-08 13:58     ` Ming Lei
  2009-06-08 15:50     ` Ming Lei
  2 siblings, 0 replies; 228+ messages in thread
From: Ming Lei @ 2009-06-08 13:38 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, akpm

2009/6/8 Peter Zijlstra <a.p.zijlstra@chello.nl>:
>
> OK, so I applied the patches and the cleanup below.

Thank you for your review and feedback.

>
> mostly little style nits and moving the circular queue into lockdep.c
> (nobody else uses it, so why share it?).

Yes, I agree.

>
> One thing though, macros with return statements?! that's seriously bad
> style, don't do that.

Yes, I'll fix it.

>
> One thing that worries me a little is that we loose DaveM's
> lockdep_dependency_visit() optimization. My brain seems unwilling to
> co-operate on determining if BFS would make that redundant, so a little
> word on that would be appreciated.
>
> Then I booted it and all hell broke loose, so either I wrecked something
> or you did :-), would you terribly mind poking at that a little?

Oh, let me work out what's wrong with this, maybe I need a little time.

>
> Over all I like that patches, but they need a little more work. Could
> you send delta patches from now on?

Yes, I'd like to do it.

>
> ---
>
> [    0.000999] =================================
> [    0.000999] [ BUG: bad contention detected! ]
> [    0.000999] ---------------------------------
> [    0.000999] swapper/0 is trying to contend lock (old_style_seqlock_init) at:
> [    0.000999] [<ffffffff8133a795>] _spin_lock+0x6d/0x75
> [    0.000999] but there are no locks held!
> [    0.000999]
> [    0.000999] other info that might help us debug this:
> [    0.000999] 1 lock held by swapper/0:
> [    0.000999]  #0:  (xtime_lock){-.....}, at: [<ffffffff8106a360>] tick_periodic+0x1d/0x74
> [    0.000999]
> [    0.000999] stack backtrace:
> [    0.000999] Pid: 0, comm: swapper Not tainted 2.6.30-rc8-tip #1049
> [    0.000999] Call Trace:
> [    0.000999]  <IRQ>  [<ffffffff81071bd8>] print_lock_contention_bug+0x100/0x110
> [    0.000999]  [<ffffffff81071ce0>] lock_acquired+0xf8/0x2b4
> [    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff8133a795>] _spin_lock+0x6d/0x75
> [    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff81010221>] update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff81067469>] update_wall_time+0x4c1/0x4cc
> [    0.000999]  [<ffffffff8105274b>] do_timer+0x15/0x1c
> [    0.000999]  [<ffffffff8106a37e>] tick_periodic+0x3b/0x74
> [    0.000999]  [<ffffffff8106a3db>] tick_handle_periodic+0x24/0x71
> [    0.000999]  [<ffffffff8100ea23>] timer_interrupt+0x1f/0x26
> [    0.000999]  [<ffffffff8109348b>] handle_IRQ_event+0x8e/0x19c
> [    0.000999]  [<ffffffff8109501e>] handle_level_irq+0x9d/0xf3
> [    0.000999]  [<ffffffff8100e24b>] handle_irq+0x24/0x2c
> [    0.000999]  [<ffffffff8133f55b>] do_IRQ+0x63/0xc2
> [    0.000999]  [<ffffffff8100c713>] ret_from_intr+0x0/0xf
> [    0.000999]  <EOI>  [<ffffffff8133a538>] ? _spin_unlock_irqrestore+0x47/0x6d
> [    0.000999]  [<ffffffff81093eea>] ? __setup_irq+0x1ea/0x277
> [    0.000999]  [<ffffffff81094120>] ? setup_irq+0x25/0x2a
> [    0.000999]  [<ffffffff8158e63e>] ? hpet_time_init+0x20/0x22
> [    0.000999]  [<ffffffff8158bbcc>] ? start_kernel+0x2ee/0x37a
> [    0.000999]  [<ffffffff8158b29a>] ? x86_64_start_reservations+0xaa/0xae
> [    0.000999]  [<ffffffff8158b37f>] ? x86_64_start_kernel+0xe1/0xe8
>
> And ended in a stuck boot at:
>
> [   65.411804] rmmod         R  running task        0   616      1 0x00000008
> [   65.411804]  ffff8800023c41a0 ffffea0003336ba8 ffff88007e3a3c08 ffffffff8106f71a
> [   65.411804]  ffff88007e3a3c48 0000000000000202 ffff88007f821600 0000000000001823
> [   65.411804]  ffff88007e109d20 ffff88007f8b5c80 0000000000000000 ffff88007e3a3d18
> [   65.411804] Call Trace:
> [   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
> [   65.411804]  [<ffffffff8113f1b6>] ? release_sysfs_dirent+0x91/0xb1
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff8113eff3>] ? sysfs_addrm_start+0x7d/0xaa
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff810113ff>] ? alternatives_smp_module_del+0x37/0xd0
> [   65.411804]  [<ffffffff810e61ee>] ? free_percpu+0x38/0xf8
> [   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
> [   65.411804]  [<ffffffff8133a542>] ? _spin_unlock_irqrestore+0x51/0x6d
> [   65.411804]  [<ffffffff810e62a5>] ? free_percpu+0xef/0xf8
> [   65.411804]  [<ffffffff8107ade5>] ? free_module+0x104/0x118
> [   65.411804]  [<ffffffff8107b0a8>] ? sys_delete_module+0x20c/0x22e
> [   65.411804]  [<ffffffff81339f88>] ? trace_hardirqs_on_thunk+0x3a/0x3f
> [   65.411804]  [<ffffffff8100bcdb>] ? system_call_fastpath+0x16/0x1b
>
> ( I can send you my .config if you cannot reproduce, but I don't think
> its anything special )
>
> ---
>
> Subject: lockdep: clean up after BFS patches
> From: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Date: Mon Jun 08 13:32:31 CEST 2009
>
>
> LKML-Reference: <new-submission>
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---
>  include/linux/lockdep.h    |    7 -
>  kernel/lockdep.c           |  232 +++++++++++++++++++++++++++------------------
>  kernel/lockdep_internals.h |   97 ------------------
>  3 files changed, 147 insertions(+), 189 deletions(-)
> ===================================================================
> ===================================================================
> --- linux-2.6.orig/include/linux/lockdep.h
> +++ linux-2.6/include/linux/lockdep.h
> @@ -58,7 +58,6 @@ struct lock_class {
>
>        struct lockdep_subclass_key     *key;
>        unsigned int                    subclass;
> -       unsigned int                    dep_gen_id;
>
>        /*
>         * IRQ/softirq usage tracking bits:
> @@ -150,9 +149,9 @@ struct lock_list {
>        struct stack_trace              trace;
>        int                             distance;
>
> -       /*The parent field is used to implement breadth-first search,and
> -        *the bit 0 is reused to indicate if the lock has been accessed
> -        *in BFS.
> +       /*
> +        * The parent field is used to implement breadth-first search, and the
> +        * bit 0 is reused to indicate if the lock has been accessed in BFS.
>         */
>        struct lock_list                *parent;
>  };
> ===================================================================
> --- linux-2.6.orig/kernel/lockdep.c
> +++ linux-2.6/kernel/lockdep.c
> @@ -43,6 +43,7 @@
>  #include <linux/ftrace.h>
>  #include <linux/stringify.h>
>  #include <linux/bitops.h>
> +
>  #include <asm/sections.h>
>
>  #include "lockdep_internals.h"
> @@ -118,7 +119,7 @@ static inline int debug_locks_off_graph_
>  static int lockdep_initialized;
>
>  unsigned long nr_list_entries;
> -struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
> +static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
>
>  /*
>  * All data structures here are protected by the global debug_lock.
> @@ -390,19 +391,6 @@ unsigned int nr_process_chains;
>  unsigned int max_lockdep_depth;
>  unsigned int max_recursion_depth;
>
> -static unsigned int lockdep_dependency_gen_id;
> -
> -static bool lockdep_dependency_visit(struct lock_class *source,
> -                                    unsigned int depth)
> -{
> -       if (!depth)
> -               lockdep_dependency_gen_id++;
> -       if (source->dep_gen_id == lockdep_dependency_gen_id)
> -               return true;
> -       source->dep_gen_id = lockdep_dependency_gen_id;
> -       return false;
> -}
> -
>  #ifdef CONFIG_DEBUG_LOCKDEP
>  /*
>  * We cannot printk in early bootup code. Not even early_printk()
> @@ -575,64 +563,6 @@ static void print_lock_class_header(stru
>        print_ip_sym((unsigned long)class->key);
>  }
>
> -/*
> - * printk the shortest lock dependencies from @start to @end in reverse order:
> - */
> -static void __used
> -print_shortest_lock_dependencies(struct lock_list *leaf,
> -                               struct lock_list *root)
> -{
> -       struct lock_list *entry = leaf;
> -       int depth;
> -
> -       /*compute depth from generated tree by BFS*/
> -       depth = get_lock_depth(leaf);
> -
> -       do {
> -               print_lock_class_header(entry->class, depth);
> -               printk("%*s ... acquired at:\n", depth, "");
> -               print_stack_trace(&entry->trace, 2);
> -               printk("\n");
> -
> -               if (depth == 0 && (entry != root)) {
> -                       printk("lockdep:%s bad BFS generated tree\n", __func__);
> -                       break;
> -               }
> -
> -               entry = get_lock_parent(entry);
> -               depth--;
> -       } while (entry && (depth >= 0));
> -
> -       return;
> -}
> -/*
> - * printk all lock dependencies starting at <entry>:
> - */
> -static void __used
> -print_lock_dependencies(struct lock_class *class, int depth)
> -{
> -       struct lock_list *entry;
> -
> -       if (lockdep_dependency_visit(class, depth))
> -               return;
> -
> -       if (DEBUG_LOCKS_WARN_ON(depth >= 20))
> -               return;
> -
> -       print_lock_class_header(class, depth);
> -
> -       list_for_each_entry(entry, &class->locks_after, entry) {
> -               if (DEBUG_LOCKS_WARN_ON(!entry->class))
> -                       return;
> -
> -               print_lock_dependencies(entry->class, depth + 1);
> -
> -               printk("%*s ... acquired at:\n",depth,"");
> -               print_stack_trace(&entry->trace, 2);
> -               printk("\n");
> -       }
> -}
> -
>  static void print_kernel_version(void)
>  {
>        printk("%s %.*s\n", init_utsname()->release,
> @@ -927,14 +857,106 @@ static int add_lock_to_list(struct lock_
>        return 1;
>  }
>
> -unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
> -static struct circular_queue  lock_cq;
> +/*For good efficiency of modular, we use power of 2*/
> +#define MAX_CIRCULAR_QUEUE_SIZE                4096UL
> +#define CQ_MASK                                (MAX_CIRCULAR_QUEUE_SIZE-1)
> +
> +/* The circular_queue and helpers is used to implement the
> + * breadth-first search(BFS)algorithem, by which we can build
> + * the shortest path from the next lock to be acquired to the
> + * previous held lock if there is a circular between them.
> + * */
> +struct circular_queue {
> +       unsigned long element[MAX_CIRCULAR_QUEUE_SIZE];
> +       unsigned int  front, rear;
> +};
> +
> +static struct circular_queue lock_cq;
> +static unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
> +
>  unsigned int max_bfs_queue_depth;
> +
> +static inline void __cq_init(struct circular_queue *cq)
> +{
> +       cq->front = cq->rear = 0;
> +       bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
> +}
> +
> +static inline int __cq_empty(struct circular_queue *cq)
> +{
> +       return (cq->front == cq->rear);
> +}
> +
> +static inline int __cq_full(struct circular_queue *cq)
> +{
> +       return ((cq->rear + 1) & CQ_MASK) == cq->front;
> +}
> +
> +static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
> +{
> +       if (__cq_full(cq))
> +               return -1;
> +
> +       cq->element[cq->rear] = elem;
> +       cq->rear = (cq->rear + 1) & CQ_MASK;
> +       return 0;
> +}
> +
> +static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
> +{
> +       if (__cq_empty(cq))
> +               return -1;
> +
> +       *elem = cq->element[cq->front];
> +       cq->front = (cq->front + 1) & CQ_MASK;
> +       return 0;
> +}
> +
> +static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
> +{
> +       return (cq->rear - cq->front) & CQ_MASK;
> +}
> +
> +static inline void mark_lock_accessed(struct lock_list *lock,
> +                                       struct lock_list *parent)
> +{
> +       unsigned long nr;
> +       nr = lock - list_entries;
> +       WARN_ON(nr >= nr_list_entries);
> +       lock->parent = parent;
> +       set_bit(nr, bfs_accessed);
> +}
> +
> +static inline unsigned long lock_accessed(struct lock_list *lock)
> +{
> +       unsigned long nr;
> +       nr = lock - list_entries;
> +       WARN_ON(nr >= nr_list_entries);
> +       return test_bit(nr, bfs_accessed);
> +}
> +
> +static inline struct lock_list *get_lock_parent(struct lock_list *child)
> +{
> +       return child->parent;
> +}
> +
> +static inline int get_lock_depth(struct lock_list *child)
> +{
> +       int depth = 0;
> +       struct lock_list *parent;
> +
> +       while ((parent = get_lock_parent(child))) {
> +               child = parent;
> +               depth++;
> +       }
> +       return depth;
> +}
> +
>  static int __bfs(struct lock_list *source_entry,
> -                       void *data,
> -                       int (*match)(struct lock_list *entry, void *data),
> -                       struct lock_list **target_entry,
> -                       int forward)
> +                void *data,
> +                int (*match)(struct lock_list *entry, void *data),
> +                struct lock_list **target_entry,
> +                int forward)
>  {
>        struct lock_list *entry;
>        struct list_head *head;
> @@ -1202,14 +1224,6 @@ check_noncircular(struct lock_list *root
>  * without creating any illegal irq-safe -> irq-unsafe lock dependency.
>  */
>
> -
> -#define   BFS_PROCESS_RET(ret) do { \
> -                                       if (ret < 0) \
> -                                               return print_bfs_bug(ret); \
> -                                       if (ret == 1) \
> -                                               return 1; \
> -                               } while (0)
> -
>  static inline int usage_match(struct lock_list *entry, void *bit)
>  {
>        return entry->class->usage_mask & (1 << (enum lock_usage_bit)bit);
> @@ -1236,6 +1250,8 @@ find_usage_forwards(struct lock_list *ro
>        debug_atomic_inc(&nr_find_usage_forwards_checks);
>
>        result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
> +       if (result < 0)
> +               return print_bfs_bug(result);
>
>        return result;
>  }
> @@ -1259,10 +1275,42 @@ find_usage_backwards(struct lock_list *r
>        debug_atomic_inc(&nr_find_usage_backwards_checks);
>
>        result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
> +       if (result < 0)
> +               return print_bfs_bug(result);
>
>        return result;
>  }
>
> +/*
> + * printk the shortest lock dependencies from @start to @end in reverse order:
> + */
> +static void __used
> +print_shortest_lock_dependencies(struct lock_list *leaf,
> +                               struct lock_list *root)
> +{
> +       struct lock_list *entry = leaf;
> +       int depth;
> +
> +       /*compute depth from generated tree by BFS*/
> +       depth = get_lock_depth(leaf);
> +
> +       do {
> +               print_lock_class_header(entry->class, depth);
> +               printk("%*s ... acquired at:\n", depth, "");
> +               print_stack_trace(&entry->trace, 2);
> +               printk("\n");
> +
> +               if (depth == 0 && (entry != root)) {
> +                       printk("lockdep:%s bad BFS generated tree\n", __func__);
> +                       break;
> +               }
> +
> +               entry = get_lock_parent(entry);
> +               depth--;
> +       } while (entry && (depth >= 0));
> +
> +       return;
> +}
>
>  static int
>  print_bad_irq_dependency(struct task_struct *curr,
> @@ -1349,12 +1397,14 @@ check_usage(struct task_struct *curr, st
>
>        this.class = hlock_class(prev);
>        ret = find_usage_backwards(&this, bit_backwards, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        that.parent = NULL;
>        that.class = hlock_class(next);
>        ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_bad_irq_dependency(curr, &this, &that,
>                        target_entry, target_entry1,
> @@ -2038,7 +2088,8 @@ check_usage_forwards(struct task_struct
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_forwards(&root, bit, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
>                                        this, 1, irqclass);
> @@ -2059,7 +2110,8 @@ check_usage_backwards(struct task_struct
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_backwards(&root, bit, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
>                                        this, 1, irqclass);
> ===================================================================
> --- linux-2.6.orig/kernel/lockdep_internals.h
> +++ linux-2.6/kernel/lockdep_internals.h
> @@ -91,6 +91,8 @@ extern unsigned int nr_process_chains;
>  extern unsigned int max_lockdep_depth;
>  extern unsigned int max_recursion_depth;
>
> +extern unsigned int max_bfs_queue_depth;
> +
>  #ifdef CONFIG_PROVE_LOCKING
>  extern unsigned long lockdep_count_forward_deps(struct lock_class *);
>  extern unsigned long lockdep_count_backward_deps(struct lock_class *);
> @@ -136,98 +138,3 @@ extern atomic_t nr_find_usage_backwards_
>  # define debug_atomic_dec(ptr)         do { } while (0)
>  # define debug_atomic_read(ptr)                0
>  #endif
> -
> -
> -extern unsigned int max_bfs_queue_depth;
> -extern unsigned long nr_list_entries;
> -extern struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
> -extern unsigned long bfs_accessed[];
> -
> -/*For good efficiency of modular, we use power of 2*/
> -#define  MAX_CIRCULAR_QUE_SIZE     4096UL
> -
> -/* The circular_queue and helpers is used to implement the
> - * breadth-first search(BFS)algorithem, by which we can build
> - * the shortest path from the next lock to be acquired to the
> - * previous held lock if there is a circular between them.
> - * */
> -struct circular_queue{
> -       unsigned long element[MAX_CIRCULAR_QUE_SIZE];
> -       unsigned int  front, rear;
> -};
> -
> -static inline void __cq_init(struct circular_queue *cq)
> -{
> -       cq->front = cq->rear = 0;
> -       bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
> -}
> -
> -static inline int __cq_empty(struct circular_queue *cq)
> -{
> -       return (cq->front == cq->rear);
> -}
> -
> -static inline int __cq_full(struct circular_queue *cq)
> -{
> -       return ((cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1))  == cq->front;
> -}
> -
> -static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
> -{
> -       if (__cq_full(cq))
> -               return -1;
> -
> -       cq->element[cq->rear] = elem;
> -       cq->rear = (cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
> -       return 0;
> -}
> -
> -static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
> -{
> -       if (__cq_empty(cq))
> -               return -1;
> -
> -       *elem = cq->element[cq->front];
> -       cq->front = (cq->front + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
> -       return 0;
> -}
> -
> -static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
> -{
> -       return (cq->rear - cq->front)&(MAX_CIRCULAR_QUE_SIZE-1);
> -}
> -
> -static inline void mark_lock_accessed(struct lock_list *lock,
> -                                       struct lock_list *parent)
> -{
> -       unsigned long nr;
> -       nr = lock - list_entries;
> -       WARN_ON(nr >= nr_list_entries);
> -       lock->parent = parent;
> -       set_bit(nr, bfs_accessed);
> -}
> -
> -static inline unsigned long lock_accessed(struct lock_list *lock)
> -{
> -       unsigned long nr;
> -       nr = lock - list_entries;
> -       WARN_ON(nr >= nr_list_entries);
> -       return test_bit(nr, bfs_accessed);
> -}
> -
> -static inline struct lock_list *get_lock_parent(struct lock_list *child)
> -{
> -       return child->parent;
> -}
> -
> -static inline int get_lock_depth(struct lock_list *child)
> -{
> -       int depth = 0;
> -       struct lock_list *parent;
> -
> -       while ((parent = get_lock_parent(child))) {
> -               child = parent;
> -               depth++;
> -       }
> -       return depth;
> -}
>
>
>



-- 
Lei Ming

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
  2009-06-08 13:38     ` Ming Lei
@ 2009-06-08 13:58     ` Ming Lei
  2009-06-08 14:04       ` Peter Zijlstra
  2009-06-08 15:50     ` Ming Lei
  2 siblings, 1 reply; 228+ messages in thread
From: Ming Lei @ 2009-06-08 13:58 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, akpm

2009/6/8 Peter Zijlstra <a.p.zijlstra@chello.nl>:

>
> Then I booted it and all hell broke loose, so either I wrecked something
> or you did :-), would you terribly mind poking at that a little?

I does not reproduce the break on 2.6.30-rc8 + 2009-06-04-next + BFS patches.

I guess you touch it on the latest tip + BFS patches, right?  If so,
I'll try to reproduce it on the current tip tree. If not, would you
mind provide the git
version to me?

Thanks.

>
> Over all I like that patches, but they need a little more work. Could
> you send delta patches from now on?
>
> ---
>
> [    0.000999] =================================
> [    0.000999] [ BUG: bad contention detected! ]
> [    0.000999] ---------------------------------
> [    0.000999] swapper/0 is trying to contend lock (old_style_seqlock_init) at:
> [    0.000999] [<ffffffff8133a795>] _spin_lock+0x6d/0x75
> [    0.000999] but there are no locks held!
> [    0.000999]
> [    0.000999] other info that might help us debug this:
> [    0.000999] 1 lock held by swapper/0:
> [    0.000999]  #0:  (xtime_lock){-.....}, at: [<ffffffff8106a360>] tick_periodic+0x1d/0x74
> [    0.000999]
> [    0.000999] stack backtrace:
> [    0.000999] Pid: 0, comm: swapper Not tainted 2.6.30-rc8-tip #1049
> [    0.000999] Call Trace:
> [    0.000999]  <IRQ>  [<ffffffff81071bd8>] print_lock_contention_bug+0x100/0x110
> [    0.000999]  [<ffffffff81071ce0>] lock_acquired+0xf8/0x2b4
> [    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff8133a795>] _spin_lock+0x6d/0x75
> [    0.000999]  [<ffffffff81010221>] ? update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff81010221>] update_vsyscall+0x2d/0xd0
> [    0.000999]  [<ffffffff81067469>] update_wall_time+0x4c1/0x4cc
> [    0.000999]  [<ffffffff8105274b>] do_timer+0x15/0x1c
> [    0.000999]  [<ffffffff8106a37e>] tick_periodic+0x3b/0x74
> [    0.000999]  [<ffffffff8106a3db>] tick_handle_periodic+0x24/0x71
> [    0.000999]  [<ffffffff8100ea23>] timer_interrupt+0x1f/0x26
> [    0.000999]  [<ffffffff8109348b>] handle_IRQ_event+0x8e/0x19c
> [    0.000999]  [<ffffffff8109501e>] handle_level_irq+0x9d/0xf3
> [    0.000999]  [<ffffffff8100e24b>] handle_irq+0x24/0x2c
> [    0.000999]  [<ffffffff8133f55b>] do_IRQ+0x63/0xc2
> [    0.000999]  [<ffffffff8100c713>] ret_from_intr+0x0/0xf
> [    0.000999]  <EOI>  [<ffffffff8133a538>] ? _spin_unlock_irqrestore+0x47/0x6d
> [    0.000999]  [<ffffffff81093eea>] ? __setup_irq+0x1ea/0x277
> [    0.000999]  [<ffffffff81094120>] ? setup_irq+0x25/0x2a
> [    0.000999]  [<ffffffff8158e63e>] ? hpet_time_init+0x20/0x22
> [    0.000999]  [<ffffffff8158bbcc>] ? start_kernel+0x2ee/0x37a
> [    0.000999]  [<ffffffff8158b29a>] ? x86_64_start_reservations+0xaa/0xae
> [    0.000999]  [<ffffffff8158b37f>] ? x86_64_start_kernel+0xe1/0xe8
>
> And ended in a stuck boot at:
>
> [   65.411804] rmmod         R  running task        0   616      1 0x00000008
> [   65.411804]  ffff8800023c41a0 ffffea0003336ba8 ffff88007e3a3c08 ffffffff8106f71a
> [   65.411804]  ffff88007e3a3c48 0000000000000202 ffff88007f821600 0000000000001823
> [   65.411804]  ffff88007e109d20 ffff88007f8b5c80 0000000000000000 ffff88007e3a3d18
> [   65.411804] Call Trace:
> [   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
> [   65.411804]  [<ffffffff8113f1b6>] ? release_sysfs_dirent+0x91/0xb1
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff8113eff3>] ? sysfs_addrm_start+0x7d/0xaa
> [   65.411804]  [<ffffffff81071af6>] ? print_lock_contention_bug+0x1e/0x110
> [   65.411804]  [<ffffffff810113ff>] ? alternatives_smp_module_del+0x37/0xd0
> [   65.411804]  [<ffffffff810e61ee>] ? free_percpu+0x38/0xf8
> [   65.411804]  [<ffffffff8106f71a>] ? trace_hardirqs_on+0xd/0xf
> [   65.411804]  [<ffffffff8133a542>] ? _spin_unlock_irqrestore+0x51/0x6d
> [   65.411804]  [<ffffffff810e62a5>] ? free_percpu+0xef/0xf8
> [   65.411804]  [<ffffffff8107ade5>] ? free_module+0x104/0x118
> [   65.411804]  [<ffffffff8107b0a8>] ? sys_delete_module+0x20c/0x22e
> [   65.411804]  [<ffffffff81339f88>] ? trace_hardirqs_on_thunk+0x3a/0x3f
> [   65.411804]  [<ffffffff8100bcdb>] ? system_call_fastpath+0x16/0x1b
>
> ( I can send you my .config if you cannot reproduce, but I don't think
> its anything special )
>
> ---
>
> Subject: lockdep: clean up after BFS patches
> From: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Date: Mon Jun 08 13:32:31 CEST 2009
>
>
> LKML-Reference: <new-submission>
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---
>  include/linux/lockdep.h    |    7 -
>  kernel/lockdep.c           |  232 +++++++++++++++++++++++++++------------------
>  kernel/lockdep_internals.h |   97 ------------------
>  3 files changed, 147 insertions(+), 189 deletions(-)
> ===================================================================
> ===================================================================
> --- linux-2.6.orig/include/linux/lockdep.h
> +++ linux-2.6/include/linux/lockdep.h
> @@ -58,7 +58,6 @@ struct lock_class {
>
>        struct lockdep_subclass_key     *key;
>        unsigned int                    subclass;
> -       unsigned int                    dep_gen_id;
>
>        /*
>         * IRQ/softirq usage tracking bits:
> @@ -150,9 +149,9 @@ struct lock_list {
>        struct stack_trace              trace;
>        int                             distance;
>
> -       /*The parent field is used to implement breadth-first search,and
> -        *the bit 0 is reused to indicate if the lock has been accessed
> -        *in BFS.
> +       /*
> +        * The parent field is used to implement breadth-first search, and the
> +        * bit 0 is reused to indicate if the lock has been accessed in BFS.
>         */
>        struct lock_list                *parent;
>  };
> ===================================================================
> --- linux-2.6.orig/kernel/lockdep.c
> +++ linux-2.6/kernel/lockdep.c
> @@ -43,6 +43,7 @@
>  #include <linux/ftrace.h>
>  #include <linux/stringify.h>
>  #include <linux/bitops.h>
> +
>  #include <asm/sections.h>
>
>  #include "lockdep_internals.h"
> @@ -118,7 +119,7 @@ static inline int debug_locks_off_graph_
>  static int lockdep_initialized;
>
>  unsigned long nr_list_entries;
> -struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
> +static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
>
>  /*
>  * All data structures here are protected by the global debug_lock.
> @@ -390,19 +391,6 @@ unsigned int nr_process_chains;
>  unsigned int max_lockdep_depth;
>  unsigned int max_recursion_depth;
>
> -static unsigned int lockdep_dependency_gen_id;
> -
> -static bool lockdep_dependency_visit(struct lock_class *source,
> -                                    unsigned int depth)
> -{
> -       if (!depth)
> -               lockdep_dependency_gen_id++;
> -       if (source->dep_gen_id == lockdep_dependency_gen_id)
> -               return true;
> -       source->dep_gen_id = lockdep_dependency_gen_id;
> -       return false;
> -}
> -
>  #ifdef CONFIG_DEBUG_LOCKDEP
>  /*
>  * We cannot printk in early bootup code. Not even early_printk()
> @@ -575,64 +563,6 @@ static void print_lock_class_header(stru
>        print_ip_sym((unsigned long)class->key);
>  }
>
> -/*
> - * printk the shortest lock dependencies from @start to @end in reverse order:
> - */
> -static void __used
> -print_shortest_lock_dependencies(struct lock_list *leaf,
> -                               struct lock_list *root)
> -{
> -       struct lock_list *entry = leaf;
> -       int depth;
> -
> -       /*compute depth from generated tree by BFS*/
> -       depth = get_lock_depth(leaf);
> -
> -       do {
> -               print_lock_class_header(entry->class, depth);
> -               printk("%*s ... acquired at:\n", depth, "");
> -               print_stack_trace(&entry->trace, 2);
> -               printk("\n");
> -
> -               if (depth == 0 && (entry != root)) {
> -                       printk("lockdep:%s bad BFS generated tree\n", __func__);
> -                       break;
> -               }
> -
> -               entry = get_lock_parent(entry);
> -               depth--;
> -       } while (entry && (depth >= 0));
> -
> -       return;
> -}
> -/*
> - * printk all lock dependencies starting at <entry>:
> - */
> -static void __used
> -print_lock_dependencies(struct lock_class *class, int depth)
> -{
> -       struct lock_list *entry;
> -
> -       if (lockdep_dependency_visit(class, depth))
> -               return;
> -
> -       if (DEBUG_LOCKS_WARN_ON(depth >= 20))
> -               return;
> -
> -       print_lock_class_header(class, depth);
> -
> -       list_for_each_entry(entry, &class->locks_after, entry) {
> -               if (DEBUG_LOCKS_WARN_ON(!entry->class))
> -                       return;
> -
> -               print_lock_dependencies(entry->class, depth + 1);
> -
> -               printk("%*s ... acquired at:\n",depth,"");
> -               print_stack_trace(&entry->trace, 2);
> -               printk("\n");
> -       }
> -}
> -
>  static void print_kernel_version(void)
>  {
>        printk("%s %.*s\n", init_utsname()->release,
> @@ -927,14 +857,106 @@ static int add_lock_to_list(struct lock_
>        return 1;
>  }
>
> -unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
> -static struct circular_queue  lock_cq;
> +/*For good efficiency of modular, we use power of 2*/
> +#define MAX_CIRCULAR_QUEUE_SIZE                4096UL
> +#define CQ_MASK                                (MAX_CIRCULAR_QUEUE_SIZE-1)
> +
> +/* The circular_queue and helpers is used to implement the
> + * breadth-first search(BFS)algorithem, by which we can build
> + * the shortest path from the next lock to be acquired to the
> + * previous held lock if there is a circular between them.
> + * */
> +struct circular_queue {
> +       unsigned long element[MAX_CIRCULAR_QUEUE_SIZE];
> +       unsigned int  front, rear;
> +};
> +
> +static struct circular_queue lock_cq;
> +static unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];
> +
>  unsigned int max_bfs_queue_depth;
> +
> +static inline void __cq_init(struct circular_queue *cq)
> +{
> +       cq->front = cq->rear = 0;
> +       bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
> +}
> +
> +static inline int __cq_empty(struct circular_queue *cq)
> +{
> +       return (cq->front == cq->rear);
> +}
> +
> +static inline int __cq_full(struct circular_queue *cq)
> +{
> +       return ((cq->rear + 1) & CQ_MASK) == cq->front;
> +}
> +
> +static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
> +{
> +       if (__cq_full(cq))
> +               return -1;
> +
> +       cq->element[cq->rear] = elem;
> +       cq->rear = (cq->rear + 1) & CQ_MASK;
> +       return 0;
> +}
> +
> +static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
> +{
> +       if (__cq_empty(cq))
> +               return -1;
> +
> +       *elem = cq->element[cq->front];
> +       cq->front = (cq->front + 1) & CQ_MASK;
> +       return 0;
> +}
> +
> +static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
> +{
> +       return (cq->rear - cq->front) & CQ_MASK;
> +}
> +
> +static inline void mark_lock_accessed(struct lock_list *lock,
> +                                       struct lock_list *parent)
> +{
> +       unsigned long nr;
> +       nr = lock - list_entries;
> +       WARN_ON(nr >= nr_list_entries);
> +       lock->parent = parent;
> +       set_bit(nr, bfs_accessed);
> +}
> +
> +static inline unsigned long lock_accessed(struct lock_list *lock)
> +{
> +       unsigned long nr;
> +       nr = lock - list_entries;
> +       WARN_ON(nr >= nr_list_entries);
> +       return test_bit(nr, bfs_accessed);
> +}
> +
> +static inline struct lock_list *get_lock_parent(struct lock_list *child)
> +{
> +       return child->parent;
> +}
> +
> +static inline int get_lock_depth(struct lock_list *child)
> +{
> +       int depth = 0;
> +       struct lock_list *parent;
> +
> +       while ((parent = get_lock_parent(child))) {
> +               child = parent;
> +               depth++;
> +       }
> +       return depth;
> +}
> +
>  static int __bfs(struct lock_list *source_entry,
> -                       void *data,
> -                       int (*match)(struct lock_list *entry, void *data),
> -                       struct lock_list **target_entry,
> -                       int forward)
> +                void *data,
> +                int (*match)(struct lock_list *entry, void *data),
> +                struct lock_list **target_entry,
> +                int forward)
>  {
>        struct lock_list *entry;
>        struct list_head *head;
> @@ -1202,14 +1224,6 @@ check_noncircular(struct lock_list *root
>  * without creating any illegal irq-safe -> irq-unsafe lock dependency.
>  */
>
> -
> -#define   BFS_PROCESS_RET(ret) do { \
> -                                       if (ret < 0) \
> -                                               return print_bfs_bug(ret); \
> -                                       if (ret == 1) \
> -                                               return 1; \
> -                               } while (0)
> -
>  static inline int usage_match(struct lock_list *entry, void *bit)
>  {
>        return entry->class->usage_mask & (1 << (enum lock_usage_bit)bit);
> @@ -1236,6 +1250,8 @@ find_usage_forwards(struct lock_list *ro
>        debug_atomic_inc(&nr_find_usage_forwards_checks);
>
>        result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
> +       if (result < 0)
> +               return print_bfs_bug(result);
>
>        return result;
>  }
> @@ -1259,10 +1275,42 @@ find_usage_backwards(struct lock_list *r
>        debug_atomic_inc(&nr_find_usage_backwards_checks);
>
>        result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
> +       if (result < 0)
> +               return print_bfs_bug(result);
>
>        return result;
>  }
>
> +/*
> + * printk the shortest lock dependencies from @start to @end in reverse order:
> + */
> +static void __used
> +print_shortest_lock_dependencies(struct lock_list *leaf,
> +                               struct lock_list *root)
> +{
> +       struct lock_list *entry = leaf;
> +       int depth;
> +
> +       /*compute depth from generated tree by BFS*/
> +       depth = get_lock_depth(leaf);
> +
> +       do {
> +               print_lock_class_header(entry->class, depth);
> +               printk("%*s ... acquired at:\n", depth, "");
> +               print_stack_trace(&entry->trace, 2);
> +               printk("\n");
> +
> +               if (depth == 0 && (entry != root)) {
> +                       printk("lockdep:%s bad BFS generated tree\n", __func__);
> +                       break;
> +               }
> +
> +               entry = get_lock_parent(entry);
> +               depth--;
> +       } while (entry && (depth >= 0));
> +
> +       return;
> +}
>
>  static int
>  print_bad_irq_dependency(struct task_struct *curr,
> @@ -1349,12 +1397,14 @@ check_usage(struct task_struct *curr, st
>
>        this.class = hlock_class(prev);
>        ret = find_usage_backwards(&this, bit_backwards, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        that.parent = NULL;
>        that.class = hlock_class(next);
>        ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_bad_irq_dependency(curr, &this, &that,
>                        target_entry, target_entry1,
> @@ -2038,7 +2088,8 @@ check_usage_forwards(struct task_struct
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_forwards(&root, bit, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
>                                        this, 1, irqclass);
> @@ -2059,7 +2110,8 @@ check_usage_backwards(struct task_struct
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_backwards(&root, bit, &target_entry);
> -       BFS_PROCESS_RET(ret);
> +       if (!ret || ret == 1)
> +               return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
>                                        this, 1, irqclass);
> ===================================================================
> --- linux-2.6.orig/kernel/lockdep_internals.h
> +++ linux-2.6/kernel/lockdep_internals.h
> @@ -91,6 +91,8 @@ extern unsigned int nr_process_chains;
>  extern unsigned int max_lockdep_depth;
>  extern unsigned int max_recursion_depth;
>
> +extern unsigned int max_bfs_queue_depth;
> +
>  #ifdef CONFIG_PROVE_LOCKING
>  extern unsigned long lockdep_count_forward_deps(struct lock_class *);
>  extern unsigned long lockdep_count_backward_deps(struct lock_class *);
> @@ -136,98 +138,3 @@ extern atomic_t nr_find_usage_backwards_
>  # define debug_atomic_dec(ptr)         do { } while (0)
>  # define debug_atomic_read(ptr)                0
>  #endif
> -
> -
> -extern unsigned int max_bfs_queue_depth;
> -extern unsigned long nr_list_entries;
> -extern struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
> -extern unsigned long bfs_accessed[];
> -
> -/*For good efficiency of modular, we use power of 2*/
> -#define  MAX_CIRCULAR_QUE_SIZE     4096UL
> -
> -/* The circular_queue and helpers is used to implement the
> - * breadth-first search(BFS)algorithem, by which we can build
> - * the shortest path from the next lock to be acquired to the
> - * previous held lock if there is a circular between them.
> - * */
> -struct circular_queue{
> -       unsigned long element[MAX_CIRCULAR_QUE_SIZE];
> -       unsigned int  front, rear;
> -};
> -
> -static inline void __cq_init(struct circular_queue *cq)
> -{
> -       cq->front = cq->rear = 0;
> -       bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
> -}
> -
> -static inline int __cq_empty(struct circular_queue *cq)
> -{
> -       return (cq->front == cq->rear);
> -}
> -
> -static inline int __cq_full(struct circular_queue *cq)
> -{
> -       return ((cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1))  == cq->front;
> -}
> -
> -static inline int __cq_enqueue(struct circular_queue *cq, unsigned long elem)
> -{
> -       if (__cq_full(cq))
> -               return -1;
> -
> -       cq->element[cq->rear] = elem;
> -       cq->rear = (cq->rear + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
> -       return 0;
> -}
> -
> -static inline int __cq_dequeue(struct circular_queue *cq, unsigned long *elem)
> -{
> -       if (__cq_empty(cq))
> -               return -1;
> -
> -       *elem = cq->element[cq->front];
> -       cq->front = (cq->front + 1)&(MAX_CIRCULAR_QUE_SIZE-1);
> -       return 0;
> -}
> -
> -static inline unsigned int  __cq_get_elem_count(struct circular_queue *cq)
> -{
> -       return (cq->rear - cq->front)&(MAX_CIRCULAR_QUE_SIZE-1);
> -}
> -
> -static inline void mark_lock_accessed(struct lock_list *lock,
> -                                       struct lock_list *parent)
> -{
> -       unsigned long nr;
> -       nr = lock - list_entries;
> -       WARN_ON(nr >= nr_list_entries);
> -       lock->parent = parent;
> -       set_bit(nr, bfs_accessed);
> -}
> -
> -static inline unsigned long lock_accessed(struct lock_list *lock)
> -{
> -       unsigned long nr;
> -       nr = lock - list_entries;
> -       WARN_ON(nr >= nr_list_entries);
> -       return test_bit(nr, bfs_accessed);
> -}
> -
> -static inline struct lock_list *get_lock_parent(struct lock_list *child)
> -{
> -       return child->parent;
> -}
> -
> -static inline int get_lock_depth(struct lock_list *child)
> -{
> -       int depth = 0;
> -       struct lock_list *parent;
> -
> -       while ((parent = get_lock_parent(child))) {
> -               child = parent;
> -               depth++;
> -       }
> -       return depth;
> -}
>
>
>



-- 
Lei Ming

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-06-08 13:58     ` Ming Lei
@ 2009-06-08 14:04       ` Peter Zijlstra
  0 siblings, 0 replies; 228+ messages in thread
From: Peter Zijlstra @ 2009-06-08 14:04 UTC (permalink / raw)
  To: Ming Lei; +Cc: mingo, linux-kernel, akpm

On Mon, 2009-06-08 at 21:58 +0800, Ming Lei wrote:
> >
> > Then I booted it and all hell broke loose, so either I wrecked something
> > or you did :-), would you terribly mind poking at that a little?
> 
> I does not reproduce the break on 2.6.30-rc8 + 2009-06-04-next + BFS patches.
> 
> I guess you touch it on the latest tip + BFS patches, right?  If so,
> I'll try to reproduce it on the current tip tree. If not, would you
> mind provide the git
> version to me?

v2.6.30-rc8-2058-g1615bb0

---
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.30-rc8
# Mon Jun  8 13:40:26 2009
#
CONFIG_64BIT=y
# CONFIG_X86_32 is not set
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_FAST_CMPXCHG_LOCAL=y
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_DEFAULT_IDLE=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_HAVE_DYNAMIC_PER_CPU_AREA=y
CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ZONE_DMA32=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_AUDIT_ARCH=y
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_X86_64_SMP=y
CONFIG_X86_HT=y
CONFIG_X86_TRAMPOLINE=y
# CONFIG_KTIME_SCALAR is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"

#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
# CONFIG_TASK_XACCT is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_AUDIT_TREE=y

#
# RCU Subsystem
#
CONFIG_CLASSIC_RCU=y
# CONFIG_TREE_RCU is not set
# CONFIG_PREEMPT_RCU is not set
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=20
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
# CONFIG_GROUP_SCHED is not set
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
# CONFIG_CGROUP_NS is not set
# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CGROUP_DEVICE is not set
# CONFIG_CPUSETS is not set
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_RESOURCE_COUNTERS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
# CONFIG_NET_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_HAVE_PERF_COUNTERS=y

#
# Performance Counters
#
CONFIG_PERF_COUNTERS=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
CONFIG_MARKERS=y
CONFIG_OPROFILE=m
# CONFIG_OPROFILE_IBS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_BLOCK_COMPAT=y

#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_FREEZER=y

#
# Processor type and features
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SMP=y
# CONFIG_SPARSE_IRQ is not set
CONFIG_X86_MPPARSE=y
CONFIG_X86_EXTENDED_PLATFORM=y
# CONFIG_X86_VSMP is not set
CONFIG_SCHED_OMIT_FRAME_POINTER=y
# CONFIG_PARAVIRT_GUEST is not set
CONFIG_MEMTEST=y
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set
# CONFIG_MCORE2 is not set
CONFIG_GENERIC_CPU=y
CONFIG_X86_CPU=y
CONFIG_X86_L1_CACHE_BYTES=64
CONFIG_X86_INTERNODE_CACHE_BYTES=64
CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_X86_DS=y
CONFIG_X86_PTRACE_BTS=y
CONFIG_HPET_TIMER=y
CONFIG_DMI=y
CONFIG_GART_IOMMU=y
CONFIG_CALGARY_IOMMU=y
CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y
CONFIG_AMD_IOMMU=y
# CONFIG_AMD_IOMMU_STATS is not set
CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y
CONFIG_IOMMU_API=y
# CONFIG_MAXSMP is not set
CONFIG_NR_CPUS=8
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
CONFIG_X86_MCE=y
CONFIG_X86_NEW_MCE=y
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_AMD=y
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set
CONFIG_X86_THERMAL_VECTOR=y
# CONFIG_I8K is not set
CONFIG_MICROCODE=m
CONFIG_MICROCODE_INTEL=y
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
# CONFIG_X86_CPU_DEBUG is not set
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_DIRECT_GBPAGES=y
# CONFIG_NUMA is not set
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
CONFIG_HAVE_MLOCK=y
CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_MMU_NOTIFIER=y
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
CONFIG_X86_RESERVE_LOW_64K=y
CONFIG_MTRR=y
CONFIG_MTRR_SANITIZER=y
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
# CONFIG_X86_PAT is not set
# CONFIG_EFI is not set
# CONFIG_SECCOMP is not set
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x1000000
# CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x1000000
CONFIG_HOTPLUG_CPU=y
CONFIG_COMPAT_VDSO=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y

#
# Power management and ACPI options
#
CONFIG_PM=y
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP_SMP=y
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
# CONFIG_HIBERNATION is not set
CONFIG_ACPI=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_PROCFS=y
CONFIG_ACPI_PROCFS_POWER=y
CONFIG_ACPI_SYSFS_POWER=y
CONFIG_ACPI_PROC_EVENT=y
CONFIG_ACPI_AC=m
CONFIG_ACPI_BATTERY=m
CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_FAN=y
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_CUSTOM_DSDT is not set
CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_PCI_SLOT is not set
CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_CONTAINER=y
CONFIG_ACPI_SBS=m

#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=m
CONFIG_CPU_FREQ_STAT_DETAILS=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=m
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m

#
# CPUFreq processor drivers
#
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_X86_POWERNOW_K8=y
# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
# CONFIG_X86_P4_CLOCKMOD is not set

#
# shared options
#
# CONFIG_X86_SPEEDSTEP_LIB is not set
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y

#
# Memory power savings
#
# CONFIG_I7300_IDLE is not set

#
# Bus options (PCI etc.)
#
CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_DOMAINS=y
# CONFIG_DMAR is not set
# CONFIG_INTR_REMAP is not set
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=m
CONFIG_PCIEAER=y
# CONFIG_PCIEASPM is not set
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
CONFIG_HT_IRQ=y
# CONFIG_PCI_IOV is not set
CONFIG_ISA_DMA_API=y
CONFIG_K8_NB=y
# CONFIG_PCCARD is not set
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_FAKE=m
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_HOTPLUG_PCI_ACPI_IBM=m
# CONFIG_HOTPLUG_PCI_CPCI is not set
CONFIG_HOTPLUG_PCI_SHPC=m

#
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
CONFIG_IA32_EMULATION=y
# CONFIG_IA32_AOUT is not set
CONFIG_COMPAT=y
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BIC=y
CONFIG_TCP_CONG_CUBIC=m
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HSTCP=m
CONFIG_TCP_CONG_HYBLA=m
CONFIG_TCP_CONG_VEGAS=m
CONFIG_TCP_CONG_SCALABLE=m
CONFIG_TCP_CONG_LP=m
CONFIG_TCP_CONG_VENO=m
# CONFIG_TCP_CONG_YEAH is not set
# CONFIG_TCP_CONG_ILLINOIS is not set
CONFIG_DEFAULT_BIC=y
# CONFIG_DEFAULT_CUBIC is not set
# CONFIG_DEFAULT_HTCP is not set
# CONFIG_DEFAULT_VEGAS is not set
# CONFIG_DEFAULT_WESTWOOD is not set
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="bic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_NETLABEL is not set
CONFIG_NETWORK_SECMARK=y
# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set

#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
CONFIG_RFKILL=m
# CONFIG_RFKILL_INPUT is not set
CONFIG_RFKILL_LEDS=y

#
# Device Drivers
#

#
# Generic Driver Options
#
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_PNP=y
CONFIG_PNP_DEBUG_MESSAGES=y

#
# Protocols
#
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_FD=m
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
# CONFIG_BLK_DEV_XIP is not set
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
# CONFIG_ATA_OVER_ETH is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_IBM_ASM is not set
# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_DELL_LAPTOP is not set
# CONFIG_ISL29003 is not set
# CONFIG_C2PORT is not set

#
# EEPROM support
#
# CONFIG_EEPROM_AT24 is not set
# CONFIG_EEPROM_LEGACY is not set
# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set

#
# SCSI device support
#
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
CONFIG_SCSI_TGT=m
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y

#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
CONFIG_BLK_DEV_SR=m
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
CONFIG_CHR_DEV_SCH=m

#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
# CONFIG_SCSI_SCAN_ASYNC is not set
CONFIG_SCSI_WAIT_SCAN=m

#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=m
# CONFIG_SCSI_FC_TGT_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
CONFIG_SCSI_SAS_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
# CONFIG_SCSI_SAS_ATA is not set
CONFIG_SCSI_SAS_HOST_SMP=y
# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
CONFIG_SCSI_SRP_ATTRS=m
# CONFIG_SCSI_SRP_TGT_ATTRS is not set
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_DH is not set
# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_ACPI=y
CONFIG_SATA_PMP=y
CONFIG_SATA_AHCI=y
# CONFIG_SATA_SIL24 is not set
CONFIG_ATA_SFF=y
CONFIG_SATA_SVW=y
CONFIG_ATA_PIIX=y
# CONFIG_SATA_MV is not set
# CONFIG_SATA_NV is not set
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ACPI is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
CONFIG_ATA_GENERIC=y
# CONFIG_PATA_HPT366 is not set
# CONFIG_PATA_HPT37X is not set
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
CONFIG_PATA_MPIIX=y
CONFIG_PATA_OLDPIIX=y
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RZ1000 is not set
# CONFIG_PATA_SC1200 is not set
CONFIG_PATA_SERVERWORKS=y
# CONFIG_PATA_PDC2027X is not set
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set

#
# IEEE 1394 (FireWire) support
#

#
# Enable only one of the two stacks, unless you know what you are doing
#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
CONFIG_I2O=m
# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
CONFIG_I2O_EXT_ADAPTEC=y
CONFIG_I2O_EXT_ADAPTEC_DMA64=y
CONFIG_I2O_BUS=m
CONFIG_I2O_BLOCK=m
CONFIG_I2O_SCSI=m
CONFIG_I2O_PROC=m
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
# CONFIG_VETH is not set
# CONFIG_NET_SB1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_NET_ETHERNET is not set
CONFIG_MII=m
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000E=y
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
# CONFIG_ATL1C is not set
# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set

#
# Wireless LAN
#
# CONFIG_WLAN_PRE80211 is not set
CONFIG_WLAN_80211=y
# CONFIG_LIBERTAS is not set
# CONFIG_AIRO is not set
# CONFIG_ATMEL is not set
# CONFIG_PRISM54 is not set
# CONFIG_USB_ZD1201 is not set
# CONFIG_USB_NET_RNDIS_WLAN is not set
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
# CONFIG_HOSTAP is not set
# CONFIG_HERMES is not set

#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#

#
# USB Network Adapters
#
CONFIG_USB_CATC=m
CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_CDCETHER=m
# CONFIG_USB_NET_CDC_EEM is not set
CONFIG_USB_NET_DM9601=m
# CONFIG_USB_NET_SMSC95XX is not set
CONFIG_USB_NET_GL620A=m
CONFIG_USB_NET_NET1080=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_USB_NET_RNDIS_HOST=m
CONFIG_USB_NET_CDC_SUBSET=m
CONFIG_USB_ALI_M5632=y
CONFIG_USB_AN2720=y
CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
CONFIG_USB_NET_ZAURUS=m
# CONFIG_USB_HSO is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
CONFIG_NETCONSOLE=y
# CONFIG_NETCONSOLE_DYNAMIC is not set
CONFIG_NETPOLL=y
CONFIG_NETPOLL_TRAP=y
CONFIG_NET_POLL_CONTROLLER=y
# CONFIG_ISDN is not set
# CONFIG_PHONE is not set

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_POLLDEV=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=m
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_KEYBOARD_STOWAWAY=m
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_BCM5974 is not set
CONFIG_MOUSE_VSXXXAA=m
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_ANALOG=m
CONFIG_JOYSTICK_A3D=m
CONFIG_JOYSTICK_ADI=m
CONFIG_JOYSTICK_COBRA=m
CONFIG_JOYSTICK_GF2K=m
CONFIG_JOYSTICK_GRIP=m
CONFIG_JOYSTICK_GRIP_MP=m
CONFIG_JOYSTICK_GUILLEMOT=m
CONFIG_JOYSTICK_INTERACT=m
CONFIG_JOYSTICK_SIDEWINDER=m
CONFIG_JOYSTICK_TMDC=m
CONFIG_JOYSTICK_IFORCE=m
CONFIG_JOYSTICK_IFORCE_USB=y
CONFIG_JOYSTICK_IFORCE_232=y
CONFIG_JOYSTICK_WARRIOR=m
CONFIG_JOYSTICK_MAGELLAN=m
CONFIG_JOYSTICK_SPACEORB=m
CONFIG_JOYSTICK_SPACEBALL=m
CONFIG_JOYSTICK_STINGER=m
CONFIG_JOYSTICK_TWIDJOY=m
# CONFIG_JOYSTICK_ZHENHUA is not set
CONFIG_JOYSTICK_JOYDUMP=m
# CONFIG_JOYSTICK_XPAD is not set
# CONFIG_INPUT_TABLET is not set
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
# CONFIG_TOUCHSCREEN_AD7879 is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
CONFIG_TOUCHSCREEN_GUNZE=m
CONFIG_TOUCHSCREEN_ELO=m
# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
CONFIG_TOUCHSCREEN_MTOUCH=m
# CONFIG_TOUCHSCREEN_INEXIO is not set
CONFIG_TOUCHSCREEN_MK712=m
CONFIG_TOUCHSCREEN_PENMOUNT=m
CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
CONFIG_TOUCHSCREEN_TOUCHWIN=m
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_APANEL is not set
CONFIG_INPUT_ATLAS_BTNS=m
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_CM109 is not set
CONFIG_INPUT_UINPUT=m

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m
CONFIG_GAMEPORT=m
CONFIG_GAMEPORT_NS558=m
CONFIG_GAMEPORT_L4=m
CONFIG_GAMEPORT_EMU10K1=m
CONFIG_GAMEPORT_FM801=m

#
# Character devices
#
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_DEVKMEM=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_COMPUTONE is not set
# CONFIG_ROCKETPORT is not set
CONFIG_CYCLADES=m
# CONFIG_CYZ_INTR is not set
# CONFIG_DIGIEPCA is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
CONFIG_SYNCLINK=m
CONFIG_SYNCLINKMP=m
CONFIG_SYNCLINK_GT=m
CONFIG_N_HDLC=m
# CONFIG_RISCOM8 is not set
# CONFIG_SPECIALIX is not set
# CONFIG_SX is not set
# CONFIG_RIO is not set
# CONFIG_STALDRV is not set
# CONFIG_NOZOMI is not set

#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_PNP=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y

#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_CONSOLE_POLL=y
CONFIG_SERIAL_JSM=m
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_IPMI_HANDLER=m
# CONFIG_IPMI_PANIC_EVENT is not set
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_IPMI_WATCHDOG=m
CONFIG_IPMI_POWEROFF=m
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
CONFIG_HW_RANDOM_INTEL=m
CONFIG_HW_RANDOM_AMD=m
CONFIG_NVRAM=y
CONFIG_R3964=m
# CONFIG_APPLICOM is not set
CONFIG_MWAVE=m
CONFIG_PC8736x_GPIO=m
CONFIG_NSC_GPIO=m
# CONFIG_RAW_DRIVER is not set
# CONFIG_HPET is not set
CONFIG_HANGCHECK_TIMER=m
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
# CONFIG_TELCLOCK is not set
CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=m

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
CONFIG_I2C_AMD756=m
CONFIG_I2C_AMD8111=m
CONFIG_I2C_I801=m
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
CONFIG_I2C_NFORCE2=m
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
CONFIG_I2C_SIS96X=m
CONFIG_I2C_VIA=m
CONFIG_I2C_VIAPRO=m

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set

#
# External I2C/SMBus adapter drivers
#
CONFIG_I2C_PARPORT_LIGHT=m
# CONFIG_I2C_TAOS_EVM is not set
# CONFIG_I2C_TINY_USB is not set

#
# Graphics adapter I2C/DDC channel drivers
#
CONFIG_I2C_VOODOO3=m

#
# Other I2C/SMBus bus drivers
#
# CONFIG_I2C_PCA_PLATFORM is not set
CONFIG_I2C_STUB=m

#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
CONFIG_SENSORS_PCF8574=m
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
CONFIG_SENSORS_MAX6875=m
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_BATTERY_BQ27x00 is not set
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set

#
# Watchdog Device Drivers
#
CONFIG_SOFT_WATCHDOG=m
# CONFIG_ACQUIRE_WDT is not set
# CONFIG_ADVANTECH_WDT is not set
# CONFIG_ALIM1535_WDT is not set
# CONFIG_ALIM7101_WDT is not set
# CONFIG_SC520_WDT is not set
# CONFIG_EUROTECH_WDT is not set
# CONFIG_IB700_WDT is not set
# CONFIG_IBMASR is not set
# CONFIG_WAFER_WDT is not set
# CONFIG_I6300ESB_WDT is not set
# CONFIG_ITCO_WDT is not set
# CONFIG_IT8712F_WDT is not set
CONFIG_IT87_WDT=m
# CONFIG_HP_WATCHDOG is not set
# CONFIG_SC1200_WDT is not set
# CONFIG_PC87413_WDT is not set
# CONFIG_60XX_WDT is not set
# CONFIG_SBC8360_WDT is not set
# CONFIG_CPU5_WDT is not set
# CONFIG_SMSC_SCH311X_WDT is not set
# CONFIG_SMSC37B787_WDT is not set
# CONFIG_W83627HF_WDT is not set
# CONFIG_W83697HF_WDT is not set
# CONFIG_W83697UG_WDT is not set
# CONFIG_W83877F_WDT is not set
# CONFIG_W83977F_WDT is not set
# CONFIG_MACHZ_WDT is not set
# CONFIG_SBC_EPX_C3_WATCHDOG is not set

#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set

#
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
CONFIG_SSB_POSSIBLE=y

#
# Sonics Silicon Backplane
#
CONFIG_SSB=m
CONFIG_SSB_SPROM=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
# CONFIG_SSB_B43_PCI_BRIDGE is not set
# CONFIG_SSB_DEBUG is not set
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_DRIVER_PCICORE=y

#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set

#
# Multimedia devices
#

#
# Multimedia core support
#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
# CONFIG_VIDEO_MEDIA is not set

#
# Multimedia drivers
#
# CONFIG_DAB is not set

#
# Graphics support
#
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
CONFIG_AGP_INTEL=y
CONFIG_AGP_SIS=y
CONFIG_AGP_VIA=y
# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_ILI9320 is not set
# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=y
CONFIG_BACKLIGHT_PROGEAR=m
# CONFIG_BACKLIGHT_MBP_NVIDIA is not set
# CONFIG_BACKLIGHT_SAHARA is not set

#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set

#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set

#
# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y

#
# Special HID drivers
#
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
CONFIG_HID_KYE=y
CONFIG_HID_GYRATION=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LOGITECH=y
CONFIG_LOGITECH_FF=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_NTRIG=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
# CONFIG_GREENASIA_FF is not set
CONFIG_HID_TOPSEED=y
CONFIG_THRUSTMASTER_FF=y
CONFIG_ZEROPLUS_FF=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set

#
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
# CONFIG_USB_OTG is not set
CONFIG_USB_MON=y
# CONFIG_USB_WUSB is not set
# CONFIG_USB_WUSB_CBAF is not set

#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_OXU210HP_HCD is not set
CONFIG_USB_ISP116X_HCD=m
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_SL811_HCD=m
# CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_HWA_HCD is not set

#
# USB Device Class drivers
#
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
# CONFIG_USB_WDM is not set
# CONFIG_USB_TMC is not set

#
# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#

#
# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
CONFIG_USB_LIBUSUAL=y

#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set

#
# USB port drivers
#
CONFIG_USB_SERIAL=m
CONFIG_USB_EZUSB=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_AIRCABLE=m
CONFIG_USB_SERIAL_ARK3116=m
CONFIG_USB_SERIAL_BELKIN=m
# CONFIG_USB_SERIAL_CH341 is not set
CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
# CONFIG_USB_SERIAL_CP210X is not set
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_FUNSOFT=m
CONFIG_USB_SERIAL_VISOR=m
CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_EDGEPORT_TI=m
CONFIG_USB_SERIAL_GARMIN=m
CONFIG_USB_SERIAL_IPW=m
# CONFIG_USB_SERIAL_IUU is not set
CONFIG_USB_SERIAL_KEYSPAN_PDA=m
CONFIG_USB_SERIAL_KEYSPAN=m
# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_MOS7720=m
CONFIG_USB_SERIAL_MOS7840=m
# CONFIG_USB_SERIAL_MOTOROLA is not set
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_OTI6858 is not set
# CONFIG_USB_SERIAL_QUALCOMM is not set
# CONFIG_USB_SERIAL_SPCP8X5 is not set
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
# CONFIG_USB_SERIAL_SYMBOL is not set
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
# CONFIG_USB_SERIAL_OPTICON is not set
CONFIG_USB_SERIAL_DEBUG=m

#
# USB Miscellaneous drivers
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set

#
# OTG and related infrastructure
#
# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y

#
# LED drivers
#
# CONFIG_LEDS_ALIX2 is not set
# CONFIG_LEDS_PCA9532 is not set
# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_CLEVO_MAIL is not set
# CONFIG_LEDS_PCA955X is not set
# CONFIG_LEDS_BD2802 is not set

#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set

#
# iptables trigger is under Netfilter config (LED target)
#
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
CONFIG_EDAC=y

#
# Reporting subsystems
#
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_MM_EDAC=m
CONFIG_EDAC_E752X=m
# CONFIG_EDAC_I82975X is not set
# CONFIG_EDAC_I3000 is not set
# CONFIG_EDAC_X38 is not set
# CONFIG_EDAC_I5400 is not set
# CONFIG_EDAC_I5000 is not set
# CONFIG_EDAC_I5100 is not set
CONFIG_RTC_LIB=m
CONFIG_RTC_CLASS=m

#
# RTC interfaces
#
# CONFIG_RTC_INTF_SYSFS is not set
# CONFIG_RTC_INTF_PROC is not set
# CONFIG_RTC_INTF_DEV is not set
# CONFIG_RTC_DRV_TEST is not set

#
# I2C RTC drivers
#
# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8581 is not set

#
# SPI RTC drivers
#

#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set

#
# on-CPU RTC drivers
#
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
CONFIG_X86_PLATFORM_DEVICES=y
# CONFIG_ACER_WMI is not set
# CONFIG_ASUS_LAPTOP is not set
# CONFIG_FUJITSU_LAPTOP is not set
# CONFIG_MSI_LAPTOP is not set
# CONFIG_PANASONIC_LAPTOP is not set
# CONFIG_COMPAL_LAPTOP is not set
# CONFIG_SONY_LAPTOP is not set
# CONFIG_THINKPAD_ACPI is not set
# CONFIG_INTEL_MENLOW is not set
# CONFIG_EEEPC_LAPTOP is not set
# CONFIG_ACPI_WMI is not set
# CONFIG_ACPI_ASUS is not set
# CONFIG_ACPI_TOSHIBA is not set

#
# Firmware Drivers
#
CONFIG_EDD=m
# CONFIG_EDD_OFF is not set
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DELL_RBU=m
CONFIG_DCDBAS=m
CONFIG_DMIID=y
# CONFIG_ISCSI_IBFT_FIND is not set

#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT2_FS_XIP=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4_FS is not set
CONFIG_FS_XIP=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_DEBUG is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
# CONFIG_QUOTA_NETLINK_INTERFACE is not set
CONFIG_PRINT_QUOTA_WARNING=y
CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
CONFIG_GENERIC_ACL=y

#
# Caches
#
# CONFIG_FSCACHE is not set

#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y

#
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
# CONFIG_NTFS_FS is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_CONFIGFS_FS=m
CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
CONFIG_HFS_FS=m
CONFIG_HFSPLUS_FS=m
CONFIG_BEFS_FS=m
# CONFIG_BEFS_DEBUG is not set
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=m
# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
CONFIG_MINIX_FS=m
# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_QNX4FS_FS=m
CONFIG_ROMFS_FS=m
CONFIG_ROMFS_BACKED_BY_BLOCK=y
# CONFIG_ROMFS_BACKED_BY_MTD is not set
# CONFIG_ROMFS_BACKED_BY_BOTH is not set
CONFIG_ROMFS_ON_BLOCK=y
CONFIG_SYSV_FS=m
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
# CONFIG_UFS_DEBUG is not set
# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NFSD=m
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_RPCSEC_GSS_SPKM3=m
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
# CONFIG_ACORN_PARTITION is not set
CONFIG_OSF_PARTITION=y
CONFIG_AMIGA_PARTITION=y
# CONFIG_ATARI_PARTITION is not set
CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
# CONFIG_LDM_PARTITION is not set
CONFIG_SGI_PARTITION=y
# CONFIG_ULTRIX_PARTITION is not set
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_EFI_PARTITION=y
# CONFIG_SYSV68_PARTITION is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=m
CONFIG_NLS_CODEPAGE_775=m
CONFIG_NLS_CODEPAGE_850=m
CONFIG_NLS_CODEPAGE_852=m
CONFIG_NLS_CODEPAGE_855=m
CONFIG_NLS_CODEPAGE_857=m
CONFIG_NLS_CODEPAGE_860=m
CONFIG_NLS_CODEPAGE_861=m
CONFIG_NLS_CODEPAGE_862=m
CONFIG_NLS_CODEPAGE_863=m
CONFIG_NLS_CODEPAGE_864=m
CONFIG_NLS_CODEPAGE_865=m
CONFIG_NLS_CODEPAGE_866=m
CONFIG_NLS_CODEPAGE_869=m
CONFIG_NLS_CODEPAGE_936=m
CONFIG_NLS_CODEPAGE_950=m
CONFIG_NLS_CODEPAGE_932=m
CONFIG_NLS_CODEPAGE_949=m
CONFIG_NLS_CODEPAGE_874=m
CONFIG_NLS_ISO8859_8=m
CONFIG_NLS_CODEPAGE_1250=m
CONFIG_NLS_CODEPAGE_1251=m
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
CONFIG_NLS_ISO8859_4=m
CONFIG_NLS_ISO8859_5=m
CONFIG_NLS_ISO8859_6=m
CONFIG_NLS_ISO8859_7=m
CONFIG_NLS_ISO8859_9=m
CONFIG_NLS_ISO8859_13=m
CONFIG_NLS_ISO8859_14=m
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
# CONFIG_DLM is not set

#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
CONFIG_ALLOW_WARNINGS=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
CONFIG_LOCK_STAT=y
# CONFIG_DEBUG_LOCKDEP is not set
CONFIG_TRACE_IRQFLAGS=y
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_VIRTUAL is not set
# CONFIG_DEBUG_WRITECOUNT is not set
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FTRACE_NMI_ENTER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_HW_BRANCH_TRACER=y
CONFIG_HAVE_FTRACE_SYSCALLS=y
CONFIG_RING_BUFFER=y
CONFIG_FTRACE_NMI_ENTER=y
CONFIG_EVENT_TRACING=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_TRACING=y
CONFIG_GENERIC_TRACER=y
CONFIG_TRACING_SUPPORT=y
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SYSPROF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_FTRACE_SYSCALLS is not set
# CONFIG_BOOT_TRACER is not set
CONFIG_BRANCH_PROFILE_NONE=y
# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
# CONFIG_PROFILE_ALL_BRANCHES is not set
# CONFIG_POWER_TRACER is not set
# CONFIG_KSYM_TRACER is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_HW_BRANCH_TRACER is not set
# CONFIG_KMEMTRACE is not set
# CONFIG_WORKQUEUE_TRACER is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
CONFIG_DYNAMIC_FTRACE=y
# CONFIG_FUNCTION_PROFILER is not set
CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_MMIOTRACE is not set
# CONFIG_RING_BUFFER_BENCHMARK is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
# CONFIG_KGDB_TESTS is not set
CONFIG_HAVE_ARCH_KMEMCHECK=y
# CONFIG_STRICT_DEVMEM is not set
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PER_CPU_MAPS is not set
# CONFIG_X86_PTDUMP is not set
# CONFIG_DEBUG_RODATA is not set
# CONFIG_DEBUG_NX_TEST is not set
# CONFIG_IOMMU_DEBUG is not set
# CONFIG_IOMMU_STRESS is not set
CONFIG_X86_DS_SELFTEST=y
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_DEBUG_BOOT_PARAMS is not set
# CONFIG_CPA_DEBUG is not set
# CONFIG_OPTIMIZE_INLINING is not set

#
# Security options
#
CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_PATH is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
# CONFIG_SECURITY_SELINUX is not set
# CONFIG_SECURITY_TOMOYO is not set
# CONFIG_IMA is not set
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
# CONFIG_CRYPTO_TEST is not set

#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_SEQIV is not set

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_XTS is not set

#
# Hash modes
#
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_XCBC=m

#
# Digest
#
CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CRC32C_INTEL is not set
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_X86_64=m
CONFIG_CRYPTO_AES_NI_INTEL=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SALSA20_X86_64 is not set
# CONFIG_CRYPTO_SEED is not set
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_TWOFISH_X86_64=m

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_ZLIB=m
# CONFIG_CRYPTO_LZO is not set

#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
CONFIG_KVM_AMD=m
# CONFIG_KVM_TRACE is not set
# CONFIG_VIRTIO_PCI is not set
# CONFIG_VIRTIO_BALLOON is not set
CONFIG_BINARY_PRINTF=y

#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_NLATTR=y



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
  2009-06-08 13:38     ` Ming Lei
  2009-06-08 13:58     ` Ming Lei
@ 2009-06-08 15:50     ` Ming Lei
  2009-06-09 12:52       ` Ming Lei
  2 siblings, 1 reply; 228+ messages in thread
From: Ming Lei @ 2009-06-08 15:50 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, akpm

On Mon, 08 Jun 2009 14:22:07 +0200
Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:

> On Sun, 2009-05-31 at 22:49 +0800, tom.leiming@gmail.com wrote:
> > Hi,
> > Currently lockdep uses recursion DFS(depth-first search) algorithm
> > to search target in checking lock
> > circle(check_noncircular()),irq-safe ->
> > irq-unsafe(check_irq_usage()) and irq inversion when adding a new
> > lock dependency. This patches replace the current DFS with BFS,
> > based on the following consideration:
> > 
> >      1,no loss of efficiency, no matter DFS or BFS, the running time
> >      are O(V+E) (V is vertex count, and E is edge count of one
> >      graph);
> > 
> >      2,BFS may be easily implemented by circular queue and consumes
> >      much less kernel stack space than DFS for DFS is implemented by
> >      recursion.
> > 
> >      3, The shortest path can be obtained by BFS if the target is
> >      found, but can't be got by DFS. By the shortest path, we can
> >      shorten the lock dependency chain and help to troubleshoot lock
> >      problem easier than before.
> > 
> 
> OK, so I applied the patches and the cleanup below.
> 
> mostly little style nits and moving the circular queue into lockdep.c
> (nobody else uses it, so why share it?).
> 
> One thing though, macros with return statements?! that's seriously bad
> style, don't do that.
> 
> One thing that worries me a little is that we loose DaveM's
> lockdep_dependency_visit() optimization. My brain seems unwilling to
> co-operate on determining if BFS would make that redundant, so a
> little word on that would be appreciated.
> 
> Then I booted it and all hell broke loose, so either I wrecked
> something or you did :-), would you terribly mind poking at that a
> little?

I have fixed the bug, which is introduced in your patch:
	lockdep: clean up after BFS patches.

Please apply and verify the patch,thanks.

I'll go to bed,:-)

>From e99ce7b2b4985032e9f54b08a7790f3df2783286 Mon Sep 17 00:00:00 2001
From: Ming Lei <tom.leiming@gmail.com>
Date: Mon, 8 Jun 2009 23:38:59 +0800
Subject: [PATCH] kernel:lockdep:fix return value of check_usage*()

Return zero if BFS find the target, so fix return value of callers
of BFS.

The patch fixes the boot failure introduced by the patch:
	lockdep: clean up after BFS patches
.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 kernel/lockdep.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 09a141f..48c3364 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -1250,8 +1250,6 @@ find_usage_forwards(struct lock_list *root, enum lock_usage_bit bit,
 	debug_atomic_inc(&nr_find_usage_forwards_checks);
 
 	result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
-	if (result < 0)
-		return print_bfs_bug(result);
 
 	return result;
 }
@@ -1275,8 +1273,6 @@ find_usage_backwards(struct lock_list *root, enum lock_usage_bit bit,
 	debug_atomic_inc(&nr_find_usage_backwards_checks);
 
 	result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
-	if (result < 0)
-		return print_bfs_bug(result);
 
 	return result;
 }
@@ -1397,13 +1393,17 @@ check_usage(struct task_struct *curr, struct held_lock *prev,
 
 	this.class = hlock_class(prev);
 	ret = find_usage_backwards(&this, bit_backwards, &target_entry);
-	if (!ret || ret == 1)
+	if (ret < 0)
+		return print_bfs_bug(ret);
+	if (ret == 1)
 		return ret;
 
 	that.parent = NULL;
 	that.class = hlock_class(next);
 	ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
-	if (!ret || ret == 1)
+	if (ret < 0)
+		return print_bfs_bug(ret);
+	if (ret == 1)
 		return ret;
 
 	return print_bad_irq_dependency(curr, &this, &that,
@@ -2088,7 +2088,9 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this,
 	root.parent = NULL;
 	root.class = hlock_class(this);
 	ret = find_usage_forwards(&root, bit, &target_entry);
-	if (!ret || ret == 1)
+	if (ret < 0)
+		return print_bfs_bug(ret);
+	if (ret == 1)
 		return ret;
 
 	return print_irq_inversion_bug(curr, &root, target_entry,
@@ -2110,7 +2112,9 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this,
 	root.parent = NULL;
 	root.class = hlock_class(this);
 	ret = find_usage_backwards(&root, bit, &target_entry);
-	if (!ret || ret == 1)
+	if (ret < 0)
+		return print_bfs_bug(ret);
+	if (ret == 1)
 		return ret;
 
 	return print_irq_inversion_bug(curr, &root, target_entry,
-- 
1.6.0.GIT




-- 
Lei Ming

^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 0/8] kernel:lockdep:replace DFS with BFS
  2009-06-08 15:50     ` Ming Lei
@ 2009-06-09 12:52       ` Ming Lei
  0 siblings, 0 replies; 228+ messages in thread
From: Ming Lei @ 2009-06-09 12:52 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, akpm

2009/6/8 Ming Lei <tom.leiming@gmail.com>:
> I have fixed the bug, which is introduced in your patch:
>        lockdep: clean up after BFS patches.
>
> Please apply and verify the patch,thanks.

Hi, Peter

Would you mind verifying the patch which fixes your kernel boot failure?

If it does work,  What do we need to do for this patches being accepted
by tip-tree?

Thanks.

>
> I'll go to bed,:-)
>
> From e99ce7b2b4985032e9f54b08a7790f3df2783286 Mon Sep 17 00:00:00 2001
> From: Ming Lei <tom.leiming@gmail.com>
> Date: Mon, 8 Jun 2009 23:38:59 +0800
> Subject: [PATCH] kernel:lockdep:fix return value of check_usage*()
>
> Return zero if BFS find the target, so fix return value of callers
> of BFS.
>
> The patch fixes the boot failure introduced by the patch:
>        lockdep: clean up after BFS patches
> .
>
> Signed-off-by: Ming Lei <tom.leiming@gmail.com>
> ---
>  kernel/lockdep.c |   20 ++++++++++++--------
>  1 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/lockdep.c b/kernel/lockdep.c
> index 09a141f..48c3364 100644
> --- a/kernel/lockdep.c
> +++ b/kernel/lockdep.c
> @@ -1250,8 +1250,6 @@ find_usage_forwards(struct lock_list *root, enum lock_usage_bit bit,
>        debug_atomic_inc(&nr_find_usage_forwards_checks);
>
>        result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
> -       if (result < 0)
> -               return print_bfs_bug(result);
>
>        return result;
>  }
> @@ -1275,8 +1273,6 @@ find_usage_backwards(struct lock_list *root, enum lock_usage_bit bit,
>        debug_atomic_inc(&nr_find_usage_backwards_checks);
>
>        result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
> -       if (result < 0)
> -               return print_bfs_bug(result);
>
>        return result;
>  }
> @@ -1397,13 +1393,17 @@ check_usage(struct task_struct *curr, struct held_lock *prev,
>
>        this.class = hlock_class(prev);
>        ret = find_usage_backwards(&this, bit_backwards, &target_entry);
> -       if (!ret || ret == 1)
> +       if (ret < 0)
> +               return print_bfs_bug(ret);
> +       if (ret == 1)
>                return ret;
>
>        that.parent = NULL;
>        that.class = hlock_class(next);
>        ret = find_usage_forwards(&that, bit_forwards, &target_entry1);
> -       if (!ret || ret == 1)
> +       if (ret < 0)
> +               return print_bfs_bug(ret);
> +       if (ret == 1)
>                return ret;
>
>        return print_bad_irq_dependency(curr, &this, &that,
> @@ -2088,7 +2088,9 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this,
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_forwards(&root, bit, &target_entry);
> -       if (!ret || ret == 1)
> +       if (ret < 0)
> +               return print_bfs_bug(ret);
> +       if (ret == 1)
>                return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
> @@ -2110,7 +2112,9 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this,
>        root.parent = NULL;
>        root.class = hlock_class(this);
>        ret = find_usage_backwards(&root, bit, &target_entry);
> -       if (!ret || ret == 1)
> +       if (ret < 0)
> +               return print_bfs_bug(ret);
> +       if (ret == 1)
>                return ret;
>
>        return print_irq_inversion_bug(curr, &root, target_entry,
> --
> 1.6.0.GIT
>
>
>
>
> --
> Lei Ming
>



-- 
Lei Ming

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 1/1] perf tools: Up the verbose level for some really verbose stuff
       [not found] <yes>
  2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
  2009-05-31 14:49 ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS tom.leiming
@ 2009-10-07 13:49 ` Arnaldo Carvalho de Melo
  2009-10-08 17:31   ` [tip:perf/core] " tip-bot for Arnaldo Carvalho de Melo
  2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
                   ` (31 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Arnaldo Carvalho de Melo @ 2009-10-07 13:49 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Frederic Weisbecker,
	Peter Zijlstra, Paul Mackerras, Mike Galbraith

Like printing every symbol created.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c |    4 ++--
 tools/perf/builtin-report.c   |    4 ++--
 tools/perf/util/symbol.c      |    4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 35ed97b..8c84320 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -658,10 +658,10 @@ more:
 	if (dump_trace)
 		return 0;
 
-	if (verbose >= 3)
+	if (verbose > 3)
 		threads__fprintf(stdout, &threads);
 
-	if (verbose >= 2)
+	if (verbose > 2)
 		dsos__fprintf(stdout);
 
 	collapse__resort();
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 12f8c86..3f0f1a4 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1021,10 +1021,10 @@ done:
 	if (dump_trace)
 		return 0;
 
-	if (verbose >= 3)
+	if (verbose > 3)
 		threads__fprintf(stdout, &threads);
 
-	if (verbose >= 2)
+	if (verbose > 2)
 		dsos__fprintf(stdout);
 
 	collapse__resort();
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 582ce72..a6887f9 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -74,7 +74,7 @@ static struct symbol *symbol__new(u64 start, u64 len, const char *name,
 	if (!self)
 		return NULL;
 
-	if (v >= 2)
+	if (v > 2)
 		printf("new symbol: %016Lx [%08lx]: %s, hist: %p\n",
 			start, (unsigned long)len, name, self->hist);
 
@@ -685,7 +685,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
 		}
 
 		if (self->adjust_symbols) {
-			if (v >= 2)
+			if (v > 2)
 				printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
 					(u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
 
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [tip:perf/core] perf tools: Up the verbose level for some really verbose stuff
  2009-10-07 13:49 ` [PATCH 1/1] perf tools: Up the verbose level for some really verbose stuff Arnaldo Carvalho de Melo
@ 2009-10-08 17:31   ` tip-bot for Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 228+ messages in thread
From: tip-bot for Arnaldo Carvalho de Melo @ 2009-10-08 17:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, paulus, acme, hpa, mingo, efault, peterz, fweisbec,
	tglx, mingo

Commit-ID:  da21d1b547cbaa2c026cf645753651c25d340923
Gitweb:     http://git.kernel.org/tip/da21d1b547cbaa2c026cf645753651c25d340923
Author:     Arnaldo Carvalho de Melo <acme@redhat.com>
AuthorDate: Wed, 7 Oct 2009 10:49:00 -0300
Committer:  Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 8 Oct 2009 19:27:10 +0200

perf tools: Up the verbose level for some really verbose stuff

Like printing every symbol created.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <1254923340-4870-1-git-send-email-acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 tools/perf/builtin-annotate.c |    4 ++--
 tools/perf/builtin-report.c   |    4 ++--
 tools/perf/util/symbol.c      |    4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 35ed97b..8c84320 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -658,10 +658,10 @@ more:
 	if (dump_trace)
 		return 0;
 
-	if (verbose >= 3)
+	if (verbose > 3)
 		threads__fprintf(stdout, &threads);
 
-	if (verbose >= 2)
+	if (verbose > 2)
 		dsos__fprintf(stdout);
 
 	collapse__resort();
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 87c4582..f57a23b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -880,10 +880,10 @@ static int __cmd_report(void)
 	if (dump_trace)
 		return 0;
 
-	if (verbose >= 3)
+	if (verbose > 3)
 		threads__fprintf(stdout, &threads);
 
-	if (verbose >= 2)
+	if (verbose > 2)
 		dsos__fprintf(stdout);
 
 	collapse__resort();
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 582ce72..a6887f9 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -74,7 +74,7 @@ static struct symbol *symbol__new(u64 start, u64 len, const char *name,
 	if (!self)
 		return NULL;
 
-	if (v >= 2)
+	if (v > 2)
 		printf("new symbol: %016Lx [%08lx]: %s, hist: %p\n",
 			start, (unsigned long)len, name, self->hist);
 
@@ -685,7 +685,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
 		}
 
 		if (self->adjust_symbols) {
-			if (v >= 2)
+			if (v > 2)
 				printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
 					(u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
 

^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 00/10] cifs: local caching support using FS-Cache
       [not found] <yes>
                   ` (2 preceding siblings ...)
  2009-10-07 13:49 ` [PATCH 1/1] perf tools: Up the verbose level for some really verbose stuff Arnaldo Carvalho de Melo
@ 2010-06-22 15:20 ` Suresh Jayaraman
  2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
                   ` (30 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:20 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

This patchset is a first stab at adding persistent, local caching facility for
CIFS using the FS-Cache interface.

The index hierarchy which is mainly used to locate a file object or discard
a certain subset of the files cached, currently has three levels:
	- Server
	- Share 
	- File

The server index object is keyed by hostname of the server. The superblock
index object is keyed by the sharename and the inode object is keyed by the
UniqueId. The cache coherency is ensured by checking the 'LastWriteTime' and
size of file.

To use this, apply this patchset in order, mount the share with rsize=4096 and
try copying a huge file (say few hundred MBs) from mount point to local
filesystem. During the first time, the cache will be initialized. When you copy
the second time, it should read from the local cache.

To reduce the impact of page cache and see the local caching in action
readily, try doing a sync and drop the caches by doing:
	sync; echo 3 > /proc/sys/vm/drop_caches

Known issues
-------------
	- the cache coherency check may not be reliable always as some
	  CIFS servers are known not to update mtime until the filehandle is
	  closed.
	- not all the Servers under all circumstances provide a unique
	  'UniqueId'.

Todo's
-------
	- improvements to avoid potential key collisions
	- address the above known issues

This set is lightly tested and all the bugs seen during my testing have been
fixed. However, this can be considered as an RFC for now.

Any Comments or Suggestions are welcome.

Suresh Jayaraman (10)
  cifs: add kernel config option for CIFS Client caching support
  cifs: guard cifsglob.h against multiple inclusion
  cifs: register CIFS for caching
  cifs: define server-level cache index objects and register them with FS-Cache
  cifs: define superblock-level cache index objects and register them
  cifs: define inode-level cache object and register them
  cifs: FS-Cache page management
  cifs: store pages into local cache
  cifs: read pages from FS-Cache
  cifs: add mount option to enable local caching

 Kconfig      |    9 ++
 Makefile     |    2 
 cache.c      |  251 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cifs_fs_sb.h |    1 
 cifsfs.c     |   15 +++
 cifsglob.h   |   14 +++
 connect.c    |   16 +++
 file.c       |   51 +++++++++++
 fscache.c    |  244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fscache.h    |  135 +++++++++++++++++++++++++++++++
 inode.c      |    4 
 11 files changed, 742 insertions(+)


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support
       [not found] <yes>
                   ` (3 preceding siblings ...)
  2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
@ 2010-06-22 15:22 ` Suresh Jayaraman
  2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:22 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Add a kernel config option to enable local caching for CIFS.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/Kconfig |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 80f3525..5739fd7 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -131,6 +131,15 @@ config CIFS_DFS_UPCALL
 	    IP addresses) which is needed for implicit mounts of DFS junction
 	    points. If unsure, say N.
 
+config CIFS_FSCACHE
+	  bool "Provide CIFS client caching support (EXPERIMENTAL)"
+	  depends on EXPERIMENTAL
+	  depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
+	  help
+	    Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
+	    to be cached locally on disk through the general filesystem cache
+	    manager. If unsure, say N.
+
 config CIFS_EXPERIMENTAL
 	  bool "CIFS Experimental Features (EXPERIMENTAL)"
 	  depends on CIFS && EXPERIMENTAL
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion
       [not found] <yes>
                   ` (4 preceding siblings ...)
  2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
@ 2010-06-22 15:22 ` Suresh Jayaraman
  2010-06-22 21:37   ` Jeff Layton
  2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
                   ` (28 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:22 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Add conditional compile macros to guard the header file against multiple
inclusion.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/cifsglob.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a88479c..6b2c39d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -16,6 +16,9 @@
  *   the GNU Lesser General Public License for more details.
  *
  */
+#ifndef _CIFS_GLOB_H
+#define _CIFS_GLOB_H
+
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/slab.h>
@@ -733,3 +736,5 @@ GLOBAL_EXTERN unsigned int cifs_min_small;  /* min size of small buf pool */
 GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
 
 extern const struct slow_work_ops cifs_oplock_break_ops;
+
+#endif	/* _CIFS_GLOB_H */
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 03/10] cifs: register CIFS for caching
       [not found] <yes>
                   ` (5 preceding siblings ...)
  2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
  2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
                   ` (27 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Define CIFS for FS-Cache and register for caching. Upon registration the
top-level index object cookie will be stuck to the netfs definition by
FS-Cache.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/Makefile  |    2 ++
 fs/cifs/cache.c   |   53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/cifsfs.c  |    8 ++++++++
 fs/cifs/fscache.h |   40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+), 0 deletions(-)
 create mode 100644 fs/cifs/cache.c
 create mode 100644 fs/cifs/fscache.h

diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 9948c00..e2de709 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -11,3 +11,5 @@ cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
 cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
+
+cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
new file mode 100644
index 0000000..1080b96
--- /dev/null
+++ b/fs/cifs/cache.c
@@ -0,0 +1,53 @@
+/*
+ *   fs/cifs/cache.c - CIFS filesystem cache index structure definitions
+ *
+ *   Copyright (c) 2010 Novell, Inc.
+ *   Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include "fscache.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+/*
+ * CIFS filesystem definition for FS-Cache
+ */
+struct fscache_netfs cifs_fscache_netfs = {
+	.name = "cifs",
+	.version = 0,
+};
+
+/*
+ * Register CIFS for caching with FS-Cache
+ */
+int cifs_fscache_register(void)
+{
+	return fscache_register_netfs(&cifs_fscache_netfs);
+}
+
+/*
+ * Unregister CIFS for caching
+ */
+void cifs_fscache_unregister(void)
+{
+	fscache_unregister_netfs(&cifs_fscache_netfs);
+}
+
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 484e52b..c2a7aa9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -47,6 +47,7 @@
 #include <linux/key-type.h>
 #include "dns_resolve.h"
 #include "cifs_spnego.h"
+#include "fscache.h"
 #define CIFS_MAGIC_NUMBER 0xFF534D42	/* the first four bytes of SMB PDUs */
 
 int cifsFYI = 0;
@@ -902,6 +903,10 @@ init_cifs(void)
 		cFYI(1, "cifs_max_pending set to max of 256");
 	}
 
+	rc = cifs_fscache_register();
+	if (rc)
+		goto out;
+
 	rc = cifs_init_inodecache();
 	if (rc)
 		goto out_clean_proc;
@@ -949,8 +954,10 @@ init_cifs(void)
 	cifs_destroy_mids();
  out_destroy_inodecache:
 	cifs_destroy_inodecache();
+	cifs_fscache_unregister();
  out_clean_proc:
 	cifs_proc_clean();
+ out:
 	return rc;
 }
 
@@ -959,6 +966,7 @@ exit_cifs(void)
 {
 	cFYI(DBG2, "exit_cifs");
 	cifs_proc_clean();
+	cifs_fscache_unregister();
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	cifs_dfs_release_automount_timer();
 	unregister_key_type(&key_type_dns_resolver);
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
new file mode 100644
index 0000000..cec9e2b
--- /dev/null
+++ b/fs/cifs/fscache.h
@@ -0,0 +1,40 @@
+/*
+ *   fs/cifs/fscache.h - CIFS filesystem cache interface definitions
+ *
+ *   Copyright (c) 2010 Novell, Inc.
+ *   Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _CIFS_FSCACHE_H
+#define _CIFS_FSCACHE_H
+
+#include <linux/fscache.h>
+#include "cifsglob.h"
+
+#ifdef CONFIG_CIFS_FSCACHE
+
+extern struct fscache_netfs cifs_fscache_netfs;
+
+extern int cifs_fscache_register(void);
+extern void cifs_fscache_unregister(void);
+
+#else /* CONFIG_CIFS_FSCACHE */
+static inline int cifs_fscache_register(void) { return 0; }
+static inline void cifs_fscache_unregister(void) {}
+
+#endif /* CONFIG_CIFS_FSCACHE */
+
+#endif /* _CIFS_FSCACHE_H */
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
       [not found] <yes>
                   ` (6 preceding siblings ...)
  2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
  2010-06-22 21:52   ` Jeff Layton
  2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
                   ` (26 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Define server-level cache index objects (as managed by TCP_ServerInfo structs).
Each server object is created in the CIFS top-level index object and is itself
an index into which superblock-level objects are inserted.

Currently, the server objects are keyed by hostname.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/Makefile   |    2 +-
 fs/cifs/cache.c    |   25 +++++++++++++++++++++++++
 fs/cifs/cifsglob.h |    3 +++
 fs/cifs/connect.c  |    4 ++++
 fs/cifs/fscache.c  |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/fscache.h  |   12 ++++++++++++
 6 files changed, 92 insertions(+), 1 deletion(-)
 create mode 100644 fs/cifs/fscache.c

Index: cifs-2.6/fs/cifs/Makefile
===================================================================
--- cifs-2.6.orig/fs/cifs/Makefile
+++ cifs-2.6/fs/cifs/Makefile
@@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
 
 cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
 
-cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
+cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
 	fscache_unregister_netfs(&cifs_fscache_netfs);
 }
 
+/*
+ * Server object currently keyed by hostname
+ */
+static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
+				   void *buffer, uint16_t maxbuf)
+{
+	const struct TCP_Server_Info *server = cookie_netfs_data;
+	uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
+
+	if (len > maxbuf)
+		return 0;
+
+	memcpy(buffer, server->hostname, len);
+
+	return len;
+}
+
+/*
+ * Server object for FS-Cache
+ */
+const struct fscache_cookie_def cifs_fscache_server_index_def = {
+	.name = "CIFS.server",
+	.type = FSCACHE_COOKIE_TYPE_INDEX,
+	.get_key = cifs_server_get_key,
+};
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -193,6 +193,9 @@ struct TCP_Server_Info {
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
 	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
 	bool	sec_ntlmssp;		/* supports NTLMSSP */
+#ifdef CONFIG_CIFS_FSCACHE
+	struct fscache_cookie   *fscache; /* client index cache cookie */
+#endif
 };
 
 /*
Index: cifs-2.6/fs/cifs/connect.c
===================================================================
--- cifs-2.6.orig/fs/cifs/connect.c
+++ cifs-2.6/fs/cifs/connect.c
@@ -48,6 +48,7 @@
 #include "nterr.h"
 #include "rfc1002pdu.h"
 #include "cn_cifs.h"
+#include "fscache.h"
 
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
@@ -1453,6 +1454,8 @@ cifs_put_tcp_session(struct TCP_Server_I
 		return;
 	}
 
+	cifs_fscache_release_client_cookie(server);
+
 	list_del_init(&server->tcp_ses_list);
 	write_unlock(&cifs_tcp_ses_lock);
 
@@ -1572,6 +1575,7 @@ cifs_get_tcp_session(struct smb_vol *vol
 		goto out_err;
 	}
 
+	cifs_fscache_get_client_cookie(tcp_ses);
 	/* thread spawned, put it on the list */
 	write_lock(&cifs_tcp_ses_lock);
 	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- /dev/null
+++ cifs-2.6/fs/cifs/fscache.c
@@ -0,0 +1,47 @@
+/*
+ *   fs/cifs/fscache.c - CIFS filesystem cache interface
+ *
+ *   Copyright (c) 2010 Novell, Inc.
+ *   Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/in6.h>
+
+#include "fscache.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
+{
+	server->fscache =
+		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
+				&cifs_fscache_server_index_def, server);
+	cFYI(1, "CIFS: get client cookie (0x%p/0x%p)\n",
+				server, server->fscache);
+}
+
+void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
+{
+	cFYI(1, "CIFS: release client cookie (0x%p/0x%p)\n",
+				server, server->fscache);
+	fscache_relinquish_cookie(server->fscache, 0);
+	server->fscache = NULL;
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -27,14 +27,26 @@
 #ifdef CONFIG_CIFS_FSCACHE
 
 extern struct fscache_netfs cifs_fscache_netfs;
+extern const struct fscache_cookie_def cifs_fscache_server_index_def;
 
 extern int cifs_fscache_register(void);
 extern void cifs_fscache_unregister(void);
 
+/*
+ * fscache.c
+ */
+extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
+extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
+
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
 static inline void cifs_fscache_unregister(void) {}
 
+static inline void
+cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
+static inline void
+cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
+
 #endif /* CONFIG_CIFS_FSCACHE */
 
 #endif /* _CIFS_FSCACHE_H */

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
       [not found] <yes>
                   ` (7 preceding siblings ...)
  2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
  2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
                   ` (25 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Define superblock-level cache index objects (managed by cifsTconInfo structs).
Each superblock object is created in a server-level index object and in itself
an index into which inode-level objects are inserted.

Currently, the superblock objects are keyed by sharename.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/cache.c    |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/cifsglob.h |    3 ++
 fs/cifs/connect.c  |    4 +++
 fs/cifs/fscache.c  |   17 ++++++++++++++
 fs/cifs/fscache.h  |    6 +++++
 5 files changed, 92 insertions(+)

Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -76,3 +76,65 @@ const struct fscache_cookie_def cifs_fsc
 	.type = FSCACHE_COOKIE_TYPE_INDEX,
 	.get_key = cifs_server_get_key,
 };
+
+static char *extract_sharename(const char *treename)
+{
+	const char *src;
+	char *delim, *dst;
+	int len;
+
+	/* skip double chars at the beginning */
+	src = treename + 2;
+
+	/* share name is always preceded by '\\' now */
+	delim = strchr(src, '\\');
+	if (!delim)
+		return ERR_PTR(-EINVAL);
+	delim++;
+	len = strlen(delim);
+
+	/* caller has to free the memory */
+	dst = kstrndup(delim, len, GFP_KERNEL);
+	if (!dst)
+		return ERR_PTR(-ENOMEM);
+
+	return dst;
+}
+
+/*
+ * Superblock object currently keyed by share name
+ */
+static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
+				   uint16_t maxbuf)
+{
+	const struct cifsTconInfo *tcon = cookie_netfs_data;
+	char *sharename;
+	uint16_t len;
+
+	sharename = extract_sharename(tcon->treeName);
+	if (IS_ERR(sharename)) {
+		cFYI(1, "CIFS: couldn't extract sharename\n");
+		sharename = NULL;
+		return 0;
+	}
+
+	len = strlen(sharename);
+	if (len > maxbuf)
+		return 0;
+
+	memcpy(buffer, sharename, len);
+
+	kfree(sharename);
+
+	return len;
+}
+
+/*
+ * Superblock object for FS-Cache
+ */
+const struct fscache_cookie_def cifs_fscache_super_index_def = {
+	.name = "CIFS.super",
+	.type = FSCACHE_COOKIE_TYPE_INDEX,
+	.get_key = cifs_super_get_key,
+};
+
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -317,6 +317,9 @@ struct cifsTconInfo {
 	bool local_lease:1; /* check leases (only) on local system not remote */
 	bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
 	bool need_reconnect:1; /* connection reset, tid now invalid */
+#ifdef CONFIG_CIFS_FSCACHE
+	struct fscache_cookie *fscache; /* cookie for share */
+#endif
 	/* BB add field for back pointer to sb struct(s)? */
 };
 
Index: cifs-2.6/fs/cifs/connect.c
===================================================================
--- cifs-2.6.orig/fs/cifs/connect.c
+++ cifs-2.6/fs/cifs/connect.c
@@ -1773,6 +1773,8 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
 	list_del_init(&tcon->tcon_list);
 	write_unlock(&cifs_tcp_ses_lock);
 
+	cifs_fscache_release_super_cookie(tcon);
+
 	xid = GetXid();
 	CIFSSMBTDis(xid, tcon);
 	_FreeXid(xid);
@@ -1843,6 +1845,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, s
 	tcon->nocase = volume_info->nocase;
 	tcon->local_lease = volume_info->local_lease;
 
+	cifs_fscache_get_super_cookie(tcon);
+
 	write_lock(&cifs_tcp_ses_lock);
 	list_add(&tcon->tcon_list, &ses->tcon_list);
 	write_unlock(&cifs_tcp_ses_lock);
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.c
+++ cifs-2.6/fs/cifs/fscache.c
@@ -45,3 +45,20 @@ void cifs_fscache_release_client_cookie(
 	server->fscache = NULL;
 }
 
+void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon)
+{
+	tcon->fscache =
+		fscache_acquire_cookie(tcon->ses->server->fscache,
+				&cifs_fscache_super_index_def, tcon);
+	cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)\n",
+				tcon, tcon->fscache);
+}
+
+void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon)
+{
+	cFYI(1, "CIFS: releasing superblock cookie (0x%p/0x%p)\n",
+			tcon, tcon->fscache);
+	fscache_relinquish_cookie(tcon->fscache, 0);
+	tcon->fscache = NULL;
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -28,6 +28,7 @@
 
 extern struct fscache_netfs cifs_fscache_netfs;
 extern const struct fscache_cookie_def cifs_fscache_server_index_def;
+extern const struct fscache_cookie_def cifs_fscache_super_index_def;
 
 extern int cifs_fscache_register(void);
 extern void cifs_fscache_unregister(void);
@@ -37,6 +38,8 @@ extern void cifs_fscache_unregister(void
  */
 extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
 extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
+extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
+extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
 
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
@@ -46,6 +49,9 @@ static inline void
 cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
 static inline void
 cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
+static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {}
+static inline void
+cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
 
 #endif /* CONFIG_CIFS_FSCACHE */
 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
       [not found] <yes>
                   ` (8 preceding siblings ...)
  2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
  2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
                   ` (24 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Define inode-level data storage objects (managed by cifsInodeInfo structs).
Each inode-level object is created in a super-block level object and is itself
a data storage object in to which pages from the inode are stored.

The inode object is keyed by UniqueId. The coherency data being used is
LastWriteTime and the file size.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/cache.c    |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/cifsfs.c   |    7 ++++
 fs/cifs/cifsglob.h |    3 +
 fs/cifs/file.c     |    6 +++
 fs/cifs/fscache.c  |   68 +++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/fscache.h  |   12 +++++++
 fs/cifs/inode.c    |    4 ++
 7 files changed, 180 insertions(+)

Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -138,3 +138,83 @@ const struct fscache_cookie_def cifs_fsc
 	.get_key = cifs_super_get_key,
 };
 
+/*
+ * Auxiliary data attached to CIFS inode within the cache
+ */
+struct cifs_fscache_inode_auxdata {
+	struct timespec	last_write_time;
+	loff_t		size;
+};
+
+static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
+					   void *buffer, uint16_t maxbuf)
+{
+	const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+	uint16_t keylen;
+
+	/* use the UniqueId as the key */
+	keylen = sizeof(cifsi->uniqueid);
+	if (keylen > maxbuf)
+		keylen = 0;
+	else
+		memcpy(buffer, &cifsi->uniqueid, keylen);
+
+	return keylen;
+}
+
+static void
+cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
+{
+	const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+	*size = cifsi->vfs_inode.i_size;
+}
+
+static uint16_t
+cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
+			   uint16_t maxbuf)
+{
+	struct cifs_fscache_inode_auxdata auxdata;
+	const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+	memset(&auxdata, 0, sizeof(auxdata));
+	auxdata.size = cifsi->vfs_inode.i_size;
+	auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
+
+	if (maxbuf > sizeof(auxdata))
+		maxbuf = sizeof(auxdata);
+
+	memcpy(buffer, &auxdata, maxbuf);
+
+	return maxbuf;
+}
+
+static enum
+fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
+					      const void *data,
+					      uint16_t datalen)
+{
+	struct cifs_fscache_inode_auxdata auxdata;
+	struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+	if (datalen != sizeof(auxdata))
+		return FSCACHE_CHECKAUX_OBSOLETE;
+
+	memset(&auxdata, 0, sizeof(auxdata));
+	auxdata.size = cifsi->vfs_inode.i_size;
+	auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
+
+	if (memcmp(data, &auxdata, datalen) != 0)
+		return FSCACHE_CHECKAUX_OBSOLETE;
+
+	return FSCACHE_CHECKAUX_OKAY;
+}
+
+const struct fscache_cookie_def cifs_fscache_inode_object_def = {
+	.name		= "CIFS.uniqueid",
+	.type		= FSCACHE_COOKIE_TYPE_DATAFILE,
+	.get_key	= cifs_fscache_inode_get_key,
+	.get_attr	= cifs_fscache_inode_get_attr,
+	.get_aux	= cifs_fscache_inode_get_aux,
+	.check_aux	= cifs_fscache_inode_check_aux,
+};
Index: cifs-2.6/fs/cifs/cifsfs.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsfs.c
+++ cifs-2.6/fs/cifs/cifsfs.c
@@ -330,6 +330,12 @@ cifs_destroy_inode(struct inode *inode)
 }
 
 static void
+cifs_clear_inode(struct inode *inode)
+{
+	cifs_fscache_release_inode_cookie(inode);
+}
+
+static void
 cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
 {
 	seq_printf(s, ",addr=");
@@ -490,6 +496,7 @@ static const struct super_operations cif
 	.alloc_inode = cifs_alloc_inode,
 	.destroy_inode = cifs_destroy_inode,
 	.drop_inode	= cifs_drop_inode,
+	.clear_inode	= cifs_clear_inode,
 /*	.delete_inode	= cifs_delete_inode,  */  /* Do not need above
 	function unless later we add lazy close of inodes or unless the
 	kernel forgets to call us with the same number of releases (closes)
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -407,6 +407,9 @@ struct cifsInodeInfo {
 	bool invalid_mapping:1;		/* pagecache is invalid */
 	u64  server_eof;		/* current file size on server */
 	u64  uniqueid;			/* server inode number */
+#ifdef CONFIG_CIFS_FSCACHE
+	struct fscache_cookie *fscache;
+#endif
 	struct inode vfs_inode;
 };
 
Index: cifs-2.6/fs/cifs/file.c
===================================================================
--- cifs-2.6.orig/fs/cifs/file.c
+++ cifs-2.6/fs/cifs/file.c
@@ -40,6 +40,7 @@
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "fscache.h"
 
 static inline int cifs_convert_flags(unsigned int flags)
 {
@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struc
 				CIFSSMBClose(xid, tcon, netfid);
 				rc = -ENOMEM;
 			}
+
+			cifs_fscache_set_inode_cookie(inode, file);
+
 			goto out;
 		} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
 			if (tcon->ses->serverNOS)
@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struc
 		goto out;
 	}
 
+	cifs_fscache_set_inode_cookie(inode, file);
+
 	if (oplock & CIFS_CREATE_ACTION) {
 		/* time to set mode which we can not set earlier due to
 		   problems creating new read-only files */
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.c
+++ cifs-2.6/fs/cifs/fscache.c
@@ -62,3 +62,71 @@ void cifs_fscache_release_super_cookie(s
 	tcon->fscache = NULL;
 }
 
+static void cifs_fscache_enable_inode_cookie(struct inode *inode)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+	if (cifsi->fscache)
+		return;
+
+	cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+				&cifs_fscache_inode_object_def,
+				cifsi);
+	cFYI(1, "CIFS: got FH cookie (0x%p/0x%p/0x%p)\n",
+			cifs_sb->tcon, cifsi, cifsi->fscache);
+}
+
+void cifs_fscache_release_inode_cookie(struct inode *inode)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+	if (cifsi->fscache) {
+		cFYI(1, "CIFS releasing inode cookie (0x%p/0x%p)\n",
+				cifsi, cifsi->fscache);
+		fscache_relinquish_cookie(cifsi->fscache, 0);
+		cifsi->fscache = NULL;
+	}
+}
+
+static void cifs_fscache_disable_inode_cookie(struct inode *inode)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+	if (cifsi->fscache) {
+		cFYI(1, "CIFS disabling inode cookie (0x%p/0x%p)\n",
+				cifsi, cifsi->fscache);
+		fscache_relinquish_cookie(cifsi->fscache, 1);
+		cifsi->fscache = NULL;
+	}
+}
+
+void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
+{
+	/* BB: parallel opens - need locking? */
+	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
+		cifs_fscache_disable_inode_cookie(inode);
+	else {
+		cifs_fscache_enable_inode_cookie(inode);
+		cFYI(1, "CIFS: fscache inode cookie set\n");
+	}
+}
+
+void cifs_fscache_reset_inode_cookie(struct inode *inode)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct fscache_cookie *old = cifsi->fscache;
+
+	if (cifsi->fscache) {
+		/* retire the current fscache cache and get a new one */
+		fscache_relinquish_cookie(cifsi->fscache, 1);
+
+		cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+					&cifs_fscache_inode_object_def,
+					cifsi);
+		cFYI(1, "CIFS: new cookie (0x%p/0x%p) oldcookie 0x%p\n",
+				cifsi, cifsi->fscache, old);
+	}
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -29,6 +29,8 @@
 extern struct fscache_netfs cifs_fscache_netfs;
 extern const struct fscache_cookie_def cifs_fscache_server_index_def;
 extern const struct fscache_cookie_def cifs_fscache_super_index_def;
+extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
+
 
 extern int cifs_fscache_register(void);
 extern void cifs_fscache_unregister(void);
@@ -41,6 +43,10 @@ extern void cifs_fscache_release_client_
 extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
 extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
 
+extern void cifs_fscache_release_inode_cookie(struct inode *);
+extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
+extern void cifs_fscache_reset_inode_cookie(struct inode *);
+
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
 static inline void cifs_fscache_unregister(void) {}
@@ -53,6 +59,12 @@ static inline void cifs_fscache_get_supe
 static inline void
 cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
 
+static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
+			struct file *filp) {}
+static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
+
+
 #endif /* CONFIG_CIFS_FSCACHE */
 
 #endif /* _CIFS_FSCACHE_H */
Index: cifs-2.6/fs/cifs/inode.c
===================================================================
--- cifs-2.6.orig/fs/cifs/inode.c
+++ cifs-2.6/fs/cifs/inode.c
@@ -29,6 +29,7 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "fscache.h"
 
 
 static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
@@ -776,6 +777,8 @@ retry_iget5_locked:
 			inode->i_flags |= S_NOATIME | S_NOCMTIME;
 		if (inode->i_state & I_NEW) {
 			inode->i_ino = hash;
+			/* initialize per-inode cache cookie pointer */
+			CIFS_I(inode)->fscache = NULL;
 			unlock_new_inode(inode);
 		}
 	}
@@ -1568,6 +1571,7 @@ cifs_invalidate_mapping(struct inode *in
 			cifs_i->write_behind_rc = rc;
 	}
 	invalidate_remote_inode(inode);
+	cifs_fscache_reset_inode_cookie(inode);
 }
 
 int cifs_revalidate_file(struct file *filp)

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC][PATCH 07/10] cifs: FS-Cache page management
       [not found] <yes>
                   ` (9 preceding siblings ...)
  2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
  2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Takes care of invalidation and release of FS-Cache marked pages and also
invalidation of the FsCache page flag when the inode is removed.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/cache.c   |   31 +++++++++++++++++++++++++++++++
 fs/cifs/file.c    |   20 ++++++++++++++++++++
 fs/cifs/fscache.c |   26 ++++++++++++++++++++++++++
 fs/cifs/fscache.h |   16 ++++++++++++++++
 4 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index b205424..3a733c1 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -210,6 +210,36 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
 	return FSCACHE_CHECKAUX_OKAY;
 }
 
+static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
+{
+	struct cifsInodeInfo *cifsi = cookie_netfs_data;
+	struct pagevec pvec;
+	pgoff_t first;
+	int loop, nr_pages;
+
+	pagevec_init(&pvec, 0);
+	first = 0;
+
+	cFYI(1, "cifs inode 0x%p now uncached\n", cifsi);
+
+	for (;;) {
+		nr_pages = pagevec_lookup(&pvec,
+					  cifsi->vfs_inode.i_mapping, first,
+					  PAGEVEC_SIZE - pagevec_count(&pvec));
+		if (!nr_pages)
+			break;
+
+		for (loop = 0; loop < nr_pages; loop++)
+			ClearPageFsCache(pvec.pages[loop]);
+
+		first = pvec.pages[nr_pages - 1]->index + 1;
+
+		pvec.nr = nr_pages;
+		pagevec_release(&pvec);
+		cond_resched();
+	}
+}
+
 const struct fscache_cookie_def cifs_fscache_inode_object_def = {
 	.name		= "CIFS.uniqueid",
 	.type		= FSCACHE_COOKIE_TYPE_DATAFILE,
@@ -217,4 +247,5 @@ const struct fscache_cookie_def cifs_fscache_inode_object_def = {
 	.get_attr	= cifs_fscache_inode_get_attr,
 	.get_aux	= cifs_fscache_inode_get_aux,
 	.check_aux	= cifs_fscache_inode_check_aux,
+	.now_uncached	= cifs_fscache_inode_now_uncached,
 };
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 55ecb55..786ec04 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2271,6 +2271,22 @@ out:
 	return rc;
 }
 
+static int cifs_release_page(struct page *page, gfp_t gfp)
+{
+	if (PagePrivate(page))
+		return 0;
+
+	return cifs_fscache_release_page(page, gfp);
+}
+
+static void cifs_invalidate_page(struct page *page, unsigned long offset)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
+
+	if (offset == 0)
+		cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
+}
+
 static void
 cifs_oplock_break(struct slow_work *work)
 {
@@ -2344,6 +2360,8 @@ const struct address_space_operations cifs_addr_ops = {
 	.write_begin = cifs_write_begin,
 	.write_end = cifs_write_end,
 	.set_page_dirty = __set_page_dirty_nobuffers,
+	.releasepage = cifs_release_page,
+	.invalidatepage = cifs_invalidate_page,
 	/* .sync_page = cifs_sync_page, */
 	/* .direct_IO = */
 };
@@ -2360,6 +2378,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
 	.write_begin = cifs_write_begin,
 	.write_end = cifs_write_end,
 	.set_page_dirty = __set_page_dirty_nobuffers,
+	.releasepage = cifs_release_page,
+	.invalidatepage = cifs_invalidate_page,
 	/* .sync_page = cifs_sync_page, */
 	/* .direct_IO = */
 };
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index ddfd355..c09d3b8 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -130,3 +130,29 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
 	}
 }
 
+int cifs_fscache_release_page(struct page *page, gfp_t gfp)
+{
+	if (PageFsCache(page)) {
+		struct inode *inode = page->mapping->host;
+		struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+		cFYI(1, "CIFS: fscache release page (0x%p/0x%p)\n",
+				cifsi->fscache, page);
+		if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
+			return 0;
+	}
+
+	return 1;
+}
+
+void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
+{
+	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+	struct fscache_cookie *cookie = cifsi->fscache;
+
+	cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
+			cookie, page, cifsi);
+	fscache_wait_on_page_write(cookie, page);
+	fscache_uncache_page(cookie, page);
+}
+
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 836bb02..127cb0a 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -47,6 +47,16 @@ extern void cifs_fscache_release_inode_cookie(struct inode *);
 extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
 extern void cifs_fscache_reset_inode_cookie(struct inode *);
 
+extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
+extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
+
+static inline void cifs_fscache_invalidate_page(struct page *page,
+					       struct inode *inode)
+{
+	if (PageFsCache(page))
+		__cifs_fscache_invalidate_page(page, inode);
+}
+
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
 static inline void cifs_fscache_unregister(void) {}
@@ -63,7 +73,13 @@ static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
 static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
 			struct file *filp) {}
 static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
+{
+	return 1; /* May release page */
+}
 
+static inline int cifs_fscache_invalidate_page(struct page *page,
+			struct inode *) {}
 
 #endif /* CONFIG_CIFS_FSCACHE */
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 08/10] cifs: store pages into local cache
       [not found] <yes>
                   ` (10 preceding siblings ...)
  2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
@ 2010-06-22 15:24 ` Suresh Jayaraman
  2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:24 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Store pages from an CIFS inode into the data storage object associated with
that inode.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/file.c    |    6 ++++++
 fs/cifs/fscache.c |   13 +++++++++++++
 fs/cifs/fscache.h |   11 +++++++++++
 3 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 786ec04..39c1ce0 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2060,6 +2060,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 				   we will hit it on next read */
 
 				/* break; */
+				/* send this page to FS-Cache */
+				cifs_readpage_to_fscache(mapping->host, page);
 			}
 		} else {
 			cFYI(1, "No bytes read (%d) at offset %lld . "
@@ -2117,6 +2119,10 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 
 	flush_dcache_page(page);
 	SetPageUptodate(page);
+
+	/* send this page to the cache */
+	cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
+
 	rc = 0;
 
 io_error:
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index c09d3b8..13e47d5 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -145,6 +145,19 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 	return 1;
 }
 
+void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
+{
+	int ret;
+
+	cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p\n",
+			CIFS_I(inode)->fscache, page, inode);
+	ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
+	cFYI(1, "CIFS: fscache_write_page returned %d\n", ret);
+
+	if (ret != 0)
+		fscache_uncache_page(CIFS_I(inode)->fscache, page);
+}
+
 void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
 {
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 127cb0a..e34d8ab 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -50,6 +50,8 @@ extern void cifs_fscache_reset_inode_cookie(struct inode *);
 extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
 extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
 
+extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
+
 static inline void cifs_fscache_invalidate_page(struct page *page,
 					       struct inode *inode)
 {
@@ -57,6 +59,13 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
 		__cifs_fscache_invalidate_page(page, inode);
 }
 
+static inline void cifs_readpage_to_fscache(struct inode *inode,
+					    struct page *page)
+{
+	if (PageFsCache(page))
+		__cifs_readpage_to_fscache(inode, page);
+}
+
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
 static inline void cifs_fscache_unregister(void) {}
@@ -80,6 +89,8 @@ static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
 
 static inline int cifs_fscache_invalidate_page(struct page *page,
 			struct inode *) {}
+static inline void cifs_readpage_to_fscache(struct inode *inode,
+			struct page *page) {}
 
 #endif /* CONFIG_CIFS_FSCACHE */
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 09/10] cifs: read pages from FS-Cache
       [not found] <yes>
                   ` (11 preceding siblings ...)
  2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
@ 2010-06-22 15:24 ` Suresh Jayaraman
  2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
                   ` (21 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:24 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Read pages from a FS-Cache data storage object into a CIFS inode.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/file.c    |   19 ++++++++++++++
 fs/cifs/fscache.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/fscache.h |   40 ++++++++++++++++++++++++++++-
 3 files changed, 131 insertions(+), 1 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 39c1ce0..42d2f25 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1978,6 +1978,16 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 
+	/*
+	 * Reads as many pages as possible from fscache. Returns -ENOBUFS
+	 * immediately if the cookie is negative
+	 */
+	rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
+					 &num_pages);
+	cFYI(1, "CIFS: readpages_from_fscache returned %d\n", rc);
+	if (rc == 0)
+		goto read_complete;
+
 	cFYI(DBG2, "rpages: num pages %d", num_pages);
 	for (i = 0; i < num_pages; ) {
 		unsigned contig_pages;
@@ -2090,6 +2100,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 		smb_read_data = NULL;
 	}
 
+read_complete:
 	FreeXid(xid);
 	return rc;
 }
@@ -2100,6 +2111,12 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 	char *read_data;
 	int rc;
 
+	/* Is the page cached? */
+	rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
+	cFYI(1, "CIFS: cifs_readpage_from_fscache returned %d\n", rc);
+	if (rc == 0)
+		goto read_complete;
+
 	page_cache_get(page);
 	read_data = kmap(page);
 	/* for reads over a certain size could initiate async read ahead */
@@ -2128,6 +2145,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 io_error:
 	kunmap(page);
 	page_cache_release(page);
+
+read_complete:
 	return rc;
 }
 
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 13e47d5..6813737 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -145,6 +145,79 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 	return 1;
 }
 
+static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
+						int error)
+{
+	cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)\n",
+			page, error);
+	if (!error)
+		SetPageUptodate(page);
+	unlock_page(page);
+}
+
+/*
+ * Retrieve a page from FS-Cache
+ */
+int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+	int ret;
+
+	cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p\n",
+			CIFS_I(inode)->fscache, page, inode);
+	ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
+					 cifs_readpage_from_fscache_complete,
+					 NULL,
+					 GFP_KERNEL);
+	switch (ret) {
+
+	case 0: /* page found in fscache, read submitted */
+		cFYI(1, "CIFS: readpage_from_fscache: submitted\n");
+		return ret;
+	case -ENOBUFS:	/* page won't be cached */
+	case -ENODATA:	/* page not in cache */
+		cFYI(1, "CIFS: readpage_from_fscache %d\n", ret);
+		return 1;
+
+	default:
+		cFYI(1, "unknown error ret = %d", ret);
+	}
+	return ret;
+}
+
+/*
+ * Retrieve a set of pages from FS-Cache
+ */
+int __cifs_readpages_from_fscache(struct inode *inode,
+				struct address_space *mapping,
+				struct list_head *pages,
+				unsigned *nr_pages)
+{
+	int ret;
+
+	cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)\n",
+			CIFS_I(inode)->fscache, *nr_pages, inode);
+	ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
+					  pages, nr_pages,
+					  cifs_readpage_from_fscache_complete,
+					  NULL,
+					  mapping_gfp_mask(mapping));
+	switch (ret) {
+	case 0:	/* read submitted to the cache for all pages */
+		cFYI(1, "CIFS: readpages_from_fscache\n");
+		return ret;
+
+	case -ENOBUFS:	/* some pages are not cached and can't be */
+	case -ENODATA:	/* some pages are not cached */
+		cFYI(1, "CIFS: readpages_from_fscache: no page\n");
+		return 1;
+
+	default:
+		cFYI(1, "unknown error ret = %d", ret);
+	}
+
+	return ret;
+}
+
 void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
 {
 	int ret;
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index e34d8ab..03bd3fe 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -31,7 +31,6 @@ extern const struct fscache_cookie_def cifs_fscache_server_index_def;
 extern const struct fscache_cookie_def cifs_fscache_super_index_def;
 extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
 
-
 extern int cifs_fscache_register(void);
 extern void cifs_fscache_unregister(void);
 
@@ -49,6 +48,11 @@ extern void cifs_fscache_reset_inode_cookie(struct inode *);
 
 extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
 extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
+extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
+extern int __cifs_readpages_from_fscache(struct inode *,
+					 struct address_space *,
+					 struct list_head *,
+					 unsigned *);
 
 extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
 
@@ -59,6 +63,26 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
 		__cifs_fscache_invalidate_page(page, inode);
 }
 
+static inline int cifs_readpage_from_fscache(struct inode *inode,
+					     struct page *page)
+{
+	if (CIFS_I(inode)->fscache)
+		return __cifs_readpage_from_fscache(inode, page);
+
+	return -ENOBUFS;
+}
+
+static inline int cifs_readpages_from_fscache(struct inode *inode,
+					      struct address_space *mapping,
+					      struct list_head *pages,
+					      unsigned *nr_pages)
+{
+	if (CIFS_I(inode)->fscache)
+		return __cifs_readpages_from_fscache(inode, mapping, pages,
+						     nr_pages);
+	return -ENOBUFS;
+}
+
 static inline void cifs_readpage_to_fscache(struct inode *inode,
 					    struct page *page)
 {
@@ -89,6 +113,20 @@ static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
 
 static inline int cifs_fscache_invalidate_page(struct page *page,
 			struct inode *) {}
+static inline int
+cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+	return -ENOBUFS;
+}
+
+static inline int cifs_readpages_from_fscache(struct inode *inode,
+					      struct address_space *mapping,
+					      struct list_head *pages,
+					      unsigned *nr_pages)
+{
+	return -ENOBUFS;
+}
+
 static inline void cifs_readpage_to_fscache(struct inode *inode,
 			struct page *page) {}
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [RFC][PATCH 10/10] cifs: add mount option to enable local caching
       [not found] <yes>
                   ` (12 preceding siblings ...)
  2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
@ 2010-06-22 15:25 ` Suresh Jayaraman
  2010-06-23 18:32   ` Scott Lovenberg
  2010-06-23 16:51 ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
                   ` (20 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:25 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells

Add a mount option 'fsc' to enable local caching on CIFS.

As the cifs-utils (userspace) changes are not done yet, this patch enables
'fsc' by default to assist testing.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 fs/cifs/cifs_fs_sb.h |    1 +
 fs/cifs/connect.c    |    8 ++++++++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 246a167..9e77145 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -35,6 +35,7 @@
 #define CIFS_MOUNT_DYNPERM      0x1000 /* allow in-memory only mode setting   */
 #define CIFS_MOUNT_NOPOSIXBRL   0x2000 /* mandatory not posix byte range lock */
 #define CIFS_MOUNT_NOSSYNC      0x4000 /* don't do slow SMBflush on every sync*/
+#define CIFS_MOUNT_FSCACHE	0x8000 /* local caching enabled */
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4844dbd..6c6ff3c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -98,6 +98,7 @@ struct smb_vol {
 	bool noblocksnd:1;
 	bool noautotune:1;
 	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
+	bool fsc:1;	/* enable fscache */
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
@@ -843,6 +844,9 @@ cifs_parse_mount_options(char *options, const char *devname,
 	/* default to using server inode numbers where available */
 	vol->server_ino = 1;
 
+	/* XXX: default to fsc for testing until mount.cifs pieces are done */
+	vol->fsc = 1;
+
 	if (!options)
 		return 1;
 
@@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const char *devname,
 			printk(KERN_WARNING "CIFS: Mount option noac not "
 				"supported. Instead set "
 				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
+		} else if (strnicmp(data, "fsc", 3) == 0) {
+			vol->fsc = true;
 		} else
 			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
 						data);
@@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
 	if (pvolume_info->dynperm)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+	if (pvolume_info->fsc)
+		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
 	if (pvolume_info->direct_io) {
 		cFYI(1, "mounting share using direct i/o");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion
  2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
@ 2010-06-22 21:37   ` Jeff Layton
  0 siblings, 0 replies; 228+ messages in thread
From: Jeff Layton @ 2010-06-22 21:37 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel, David Howells

On Tue, 22 Jun 2010 20:52:50 +0530
Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Add conditional compile macros to guard the header file against multiple
> inclusion.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
> ---
>  fs/cifs/cifsglob.h |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index a88479c..6b2c39d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -16,6 +16,9 @@
>   *   the GNU Lesser General Public License for more details.
>   *
>   */
> +#ifndef _CIFS_GLOB_H
> +#define _CIFS_GLOB_H
> +
>  #include <linux/in.h>
>  #include <linux/in6.h>
>  #include <linux/slab.h>
> @@ -733,3 +736,5 @@ GLOBAL_EXTERN unsigned int cifs_min_small;  /* min size of small buf pool */
>  GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
>  
>  extern const struct slow_work_ops cifs_oplock_break_ops;
> +
> +#endif	/* _CIFS_GLOB_H */

Strong ACK

Acked-by: Jeff Layton <jlayton@samba.org>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
  2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
@ 2010-06-22 21:52   ` Jeff Layton
  2010-06-23  5:34     ` Suresh Jayaraman
  0 siblings, 1 reply; 228+ messages in thread
From: Jeff Layton @ 2010-06-22 21:52 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel, David Howells

On Tue, 22 Jun 2010 20:53:18 +0530
Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Define server-level cache index objects (as managed by TCP_ServerInfo structs).
> Each server object is created in the CIFS top-level index object and is itself
> an index into which superblock-level objects are inserted.
> 
> Currently, the server objects are keyed by hostname.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
> ---
>  fs/cifs/Makefile   |    2 +-
>  fs/cifs/cache.c    |   25 +++++++++++++++++++++++++
>  fs/cifs/cifsglob.h |    3 +++
>  fs/cifs/connect.c  |    4 ++++
>  fs/cifs/fscache.c  |   47 +++++++++++++++++++++++++++++++++++++++++++++++
>  fs/cifs/fscache.h  |   12 ++++++++++++
>  6 files changed, 92 insertions(+), 1 deletion(-)
>  create mode 100644 fs/cifs/fscache.c
> 
> Index: cifs-2.6/fs/cifs/Makefile
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/Makefile
> +++ cifs-2.6/fs/cifs/Makefile
> @@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
>  
>  cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>  
> -cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
> +cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
> Index: cifs-2.6/fs/cifs/cache.c
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/cache.c
> +++ cifs-2.6/fs/cifs/cache.c
> @@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
>  	fscache_unregister_netfs(&cifs_fscache_netfs);
>  }
>  
> +/*
> + * Server object currently keyed by hostname
> + */
> +static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
> +				   void *buffer, uint16_t maxbuf)
> +{
> +	const struct TCP_Server_Info *server = cookie_netfs_data;
> +	uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
> +

Would a tuple of address/family/port be a better choice here? Imagine I
mount "foo" and then later mount "foor.bar.baz". If they are the same
address and only the UNC differs, then you won't get the benefit of
the cache, right?

> +	if (len > maxbuf)
> +		return 0;
> +
> +	memcpy(buffer, server->hostname, len);
> +
> +	return len;
> +}
> +
> +/*
> + * Server object for FS-Cache
> + */
> +const struct fscache_cookie_def cifs_fscache_server_index_def = {
> +	.name = "CIFS.server",
> +	.type = FSCACHE_COOKIE_TYPE_INDEX,
> +	.get_key = cifs_server_get_key,
> +};
> Index: cifs-2.6/fs/cifs/cifsglob.h
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/cifsglob.h
> +++ cifs-2.6/fs/cifs/cifsglob.h
> @@ -193,6 +193,9 @@ struct TCP_Server_Info {
>  	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
>  	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
>  	bool	sec_ntlmssp;		/* supports NTLMSSP */
> +#ifdef CONFIG_CIFS_FSCACHE
> +	struct fscache_cookie   *fscache; /* client index cache cookie */
> +#endif
>  };
>  
>  /*
> Index: cifs-2.6/fs/cifs/connect.c
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/connect.c
> +++ cifs-2.6/fs/cifs/connect.c
> @@ -48,6 +48,7 @@
>  #include "nterr.h"
>  #include "rfc1002pdu.h"
>  #include "cn_cifs.h"
> +#include "fscache.h"
>  
>  #define CIFS_PORT 445
>  #define RFC1001_PORT 139
> @@ -1453,6 +1454,8 @@ cifs_put_tcp_session(struct TCP_Server_I
>  		return;
>  	}
>  
> +	cifs_fscache_release_client_cookie(server);
> +
>  	list_del_init(&server->tcp_ses_list);
>  	write_unlock(&cifs_tcp_ses_lock);
>  
> @@ -1572,6 +1575,7 @@ cifs_get_tcp_session(struct smb_vol *vol
>  		goto out_err;
>  	}
>  
> +	cifs_fscache_get_client_cookie(tcp_ses);
>  	/* thread spawned, put it on the list */
>  	write_lock(&cifs_tcp_ses_lock);
>  	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
> Index: cifs-2.6/fs/cifs/fscache.c
> ===================================================================
> --- /dev/null
> +++ cifs-2.6/fs/cifs/fscache.c
> @@ -0,0 +1,47 @@
> +/*
> + *   fs/cifs/fscache.c - CIFS filesystem cache interface
> + *
> + *   Copyright (c) 2010 Novell, Inc.
> + *   Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
> + *
> + *   This library is free software; you can redistribute it and/or modify
> + *   it under the terms of the GNU Lesser General Public License as published
> + *   by the Free Software Foundation; either version 2.1 of the License, or
> + *   (at your option) any later version.
> + *
> + *   This library 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 Lesser General Public License for more details.
> + *
> + *   You should have received a copy of the GNU Lesser General Public License
> + *   along with this library; if not, write to the Free Software
> + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/mm.h>
> +#include <linux/in6.h>
> +
> +#include "fscache.h"
> +#include "cifsglob.h"
> +#include "cifs_debug.h"
> +
> +void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
> +{
> +	server->fscache =
> +		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
> +				&cifs_fscache_server_index_def, server);
> +	cFYI(1, "CIFS: get client cookie (0x%p/0x%p)\n",
> +				server, server->fscache);
> +}
> +
> +void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
> +{
> +	cFYI(1, "CIFS: release client cookie (0x%p/0x%p)\n",
> +				server, server->fscache);
> +	fscache_relinquish_cookie(server->fscache, 0);
> +	server->fscache = NULL;
> +}
> +
> Index: cifs-2.6/fs/cifs/fscache.h
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/fscache.h
> +++ cifs-2.6/fs/cifs/fscache.h
> @@ -27,14 +27,26 @@
>  #ifdef CONFIG_CIFS_FSCACHE
>  
>  extern struct fscache_netfs cifs_fscache_netfs;
> +extern const struct fscache_cookie_def cifs_fscache_server_index_def;
>  
>  extern int cifs_fscache_register(void);
>  extern void cifs_fscache_unregister(void);
>  
> +/*
> + * fscache.c
> + */
> +extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
> +extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
> +
>  #else /* CONFIG_CIFS_FSCACHE */
>  static inline int cifs_fscache_register(void) { return 0; }
>  static inline void cifs_fscache_unregister(void) {}
>  
> +static inline void
> +cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
> +static inline void
> +cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
> +
>  #endif /* CONFIG_CIFS_FSCACHE */
>  
>  #endif /* _CIFS_FSCACHE_H */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Jeff Layton <jlayton@poochiereds.net>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
  2010-06-22 21:52   ` Jeff Layton
@ 2010-06-23  5:34     ` Suresh Jayaraman
  0 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-23  5:34 UTC (permalink / raw)
  To: Jeff Layton
  Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel, David Howells

On 06/23/2010 03:22 AM, Jeff Layton wrote:
> On Tue, 22 Jun 2010 20:53:18 +0530
> Suresh Jayaraman <sjayaraman@suse.de> wrote:
> 
>> Define server-level cache index objects (as managed by TCP_ServerInfo structs).
>> Each server object is created in the CIFS top-level index object and is itself
>> an index into which superblock-level objects are inserted.
>>
>> Currently, the server objects are keyed by hostname.
>>
>> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
>> ---
>>  fs/cifs/Makefile   |    2 +-
>>  fs/cifs/cache.c    |   25 +++++++++++++++++++++++++
>>  fs/cifs/cifsglob.h |    3 +++
>>  fs/cifs/connect.c  |    4 ++++
>>  fs/cifs/fscache.c  |   47 +++++++++++++++++++++++++++++++++++++++++++++++
>>  fs/cifs/fscache.h  |   12 ++++++++++++
>>  6 files changed, 92 insertions(+), 1 deletion(-)
>>  create mode 100644 fs/cifs/fscache.c
>>
>> Index: cifs-2.6/fs/cifs/Makefile
>> ===================================================================
>> --- cifs-2.6.orig/fs/cifs/Makefile
>> +++ cifs-2.6/fs/cifs/Makefile
>> @@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
>>  
>>  cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>>  
>> -cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
>> +cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
>> Index: cifs-2.6/fs/cifs/cache.c
>> ===================================================================
>> --- cifs-2.6.orig/fs/cifs/cache.c
>> +++ cifs-2.6/fs/cifs/cache.c
>> @@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
>>  	fscache_unregister_netfs(&cifs_fscache_netfs);
>>  }
>>  
>> +/*
>> + * Server object currently keyed by hostname
>> + */
>> +static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
>> +				   void *buffer, uint16_t maxbuf)
>> +{
>> +	const struct TCP_Server_Info *server = cookie_netfs_data;
>> +	uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
>> +
> 
> Would a tuple of address/family/port be a better choice here? Imagine I
> mount "foo" and then later mount "foor.bar.baz". If they are the same
> address and only the UNC differs, then you won't get the benefit of
> the cache, right?
> 

Good point. I'll fix it up when I do a respin.

Thanks,

-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 03/10] cifs: register CIFS for caching
       [not found] <yes>
                   ` (13 preceding siblings ...)
  2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
@ 2010-06-23 16:51 ` David Howells
  2010-06-25 10:56   ` Suresh Jayaraman
  2010-06-23 16:54 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache David Howells
                   ` (19 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: David Howells @ 2010-06-23 16:51 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> +	rc = cifs_fscache_register();
> +	if (rc)
> +		goto out;
> +
>  	rc = cifs_init_inodecache();
>  	if (rc)
>  		goto out_clean_proc;
> @@ -949,8 +954,10 @@ init_cifs(void)
>  	cifs_destroy_mids();
>   out_destroy_inodecache:
>  	cifs_destroy_inodecache();
> +	cifs_fscache_unregister();
>   out_clean_proc:

This is incorrect.  You need to call cifs_fscache_unregister() if
cifs_init_inodecache() fails.

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
       [not found] <yes>
                   ` (14 preceding siblings ...)
  2010-06-23 16:51 ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
@ 2010-06-23 16:54 ` David Howells
  2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 16:54 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Define server-level cache index objects (as managed by TCP_ServerInfo
> structs).  Each server object is created in the CIFS top-level index object
> and is itself an index into which superblock-level objects are inserted.
> 
> Currently, the server objects are keyed by hostname.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Looks reasonable, apart from the index key.  I agree with Jeff that you
probably want {address,port,family} rather than a hostname.

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
       [not found] <yes>
                   ` (15 preceding siblings ...)
  2010-06-23 16:54 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache David Howells
@ 2010-06-23 16:58 ` David Howells
  2010-06-25 12:44   ` Suresh Jayaraman
                     ` (2 more replies)
  2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
                   ` (17 subsequent siblings)
  34 siblings, 3 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 16:58 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Define superblock-level cache index objects (managed by cifsTconInfo
> structs).  Each superblock object is created in a server-level index object
> and in itself an index into which inode-level objects are inserted.
> 
> Currently, the superblock objects are keyed by sharename.

Seems reasonable.  Is there any way you can check that the share you are
looking at on a server is the same as the last time you looked?  Can you
validate the root directory of the share in some way?

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
       [not found] <yes>
                   ` (16 preceding siblings ...)
  2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
@ 2010-06-23 17:02 ` David Howells
  2010-06-25 12:50   ` Suresh Jayaraman
  2010-06-25 12:55   ` David Howells
  2010-06-23 17:05 ` [RFC][PATCH 07/10] cifs: FS-Cache page management David Howells
                   ` (16 subsequent siblings)
  34 siblings, 2 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 17:02 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Define inode-level data storage objects (managed by cifsInodeInfo structs).
> Each inode-level object is created in a super-block level object and is
> itself a data storage object in to which pages from the inode are stored.
> 
> The inode object is keyed by UniqueId. The coherency data being used is
> LastWriteTime and the file size.

Isn't there a file creation time too?

I take it you don't support caching on files that are open for writing at this
time?

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 07/10] cifs: FS-Cache page management
       [not found] <yes>
                   ` (17 preceding siblings ...)
  2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
@ 2010-06-23 17:05 ` David Howells
  2010-06-23 17:06 ` [RFC][PATCH 08/10] cifs: store pages into local cache David Howells
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 17:05 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Takes care of invalidation and release of FS-Cache marked pages and also
> invalidation of the FsCache page flag when the inode is removed.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Acked-by: David Howells <dhowells@redhat.com>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 08/10] cifs: store pages into local cache
       [not found] <yes>
                   ` (18 preceding siblings ...)
  2010-06-23 17:05 ` [RFC][PATCH 07/10] cifs: FS-Cache page management David Howells
@ 2010-06-23 17:06 ` David Howells
  2010-06-23 17:07 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache David Howells
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 17:06 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Store pages from an CIFS inode into the data storage object associated with
> that inode.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Acked-by: David Howells <dhowells@redhat.com>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 09/10] cifs: read pages from FS-Cache
       [not found] <yes>
                   ` (19 preceding siblings ...)
  2010-06-23 17:06 ` [RFC][PATCH 08/10] cifs: store pages into local cache David Howells
@ 2010-06-23 17:07 ` David Howells
  2010-06-23 17:08 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching David Howells
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 17:07 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Read pages from a FS-Cache data storage object into a CIFS inode.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Acked-by: David Howells <dhowells@redhat.com>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
       [not found] <yes>
                   ` (20 preceding siblings ...)
  2010-06-23 17:07 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache David Howells
@ 2010-06-23 17:08 ` David Howells
  2011-06-15  0:46 ` [PATCH] Add ok2440 development board support Wu DaoGuang
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-23 17:08 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Add a mount option 'fsc' to enable local caching on CIFS.
> 
> As the cifs-utils (userspace) changes are not done yet, this patch enables
> 'fsc' by default to assist testing.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Acked-by: David Howells <dhowells@redhat.com>

(Give or take the debugging bit)

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
  2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
@ 2010-06-23 18:32   ` Scott Lovenberg
  2010-06-25 10:48     ` Suresh Jayaraman
  0 siblings, 1 reply; 228+ messages in thread
From: Scott Lovenberg @ 2010-06-23 18:32 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel, David Howells

On 6/22/2010 11:25 AM, Suresh Jayaraman wrote:
> Add a mount option 'fsc' to enable local caching on CIFS.
>
> As the cifs-utils (userspace) changes are not done yet, this patch enables
> 'fsc' by default to assist testing.
>    
[...]
> @@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const char *devname,
>   			printk(KERN_WARNING "CIFS: Mount option noac not "
>   				"supported. Instead set "
>   				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
> +		} else if (strnicmp(data, "fsc", 3) == 0) {
> +			vol->fsc = true;
>   		} else
>   			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
>   						data);
> @@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
>   		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
>   	if (pvolume_info->dynperm)
>   		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
> +	if (pvolume_info->fsc)
> +		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
>   	if (pvolume_info->direct_io) {
>   		cFYI(1, "mounting share using direct i/o");
>   		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
>    
I reworked the CIFS mount option parsing a while back; I'm not sure 
whether that patch was going to be in the 2.6.35 tree or not (the window 
just opened, didn't it?).

Jeff, Steve, can you confirm if that patch is going to be in 2.6.35?

Patch refs: http://patchwork.ozlabs.org/patch/53059/  and 
http://patchwork.ozlabs.org/patch/53674/




^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
  2010-06-23 18:32   ` Scott Lovenberg
@ 2010-06-25 10:48     ` Suresh Jayaraman
  0 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 10:48 UTC (permalink / raw)
  To: Scott Lovenberg
  Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel, David Howells

On 06/24/2010 12:02 AM, Scott Lovenberg wrote:
> On 6/22/2010 11:25 AM, Suresh Jayaraman wrote:
>> Add a mount option 'fsc' to enable local caching on CIFS.
>>
>> As the cifs-utils (userspace) changes are not done yet, this patch
>> enables
>> 'fsc' by default to assist testing.
>>    
> [...]
>> @@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const
>> char *devname,
>>               printk(KERN_WARNING "CIFS: Mount option noac not "
>>                   "supported. Instead set "
>>                   "/proc/fs/cifs/LookupCacheEnabled to 0\n");
>> +        } else if (strnicmp(data, "fsc", 3) == 0) {
>> +            vol->fsc = true;
>>           } else
>>               printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
>>                           data);
>> @@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol
>> *pvolume_info,
>>           cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
>>       if (pvolume_info->dynperm)
>>           cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
>> +    if (pvolume_info->fsc)
>> +        cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
>>       if (pvolume_info->direct_io) {
>>           cFYI(1, "mounting share using direct i/o");
>>           cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
>>    
> I reworked the CIFS mount option parsing a while back; I'm not sure
> whether that patch was going to be in the 2.6.35 tree or not (the window
> just opened, didn't it?).

Not a problem, I could redo this patch alone when the reworked option
parsing patches get in.

> Jeff, Steve, can you confirm if that patch is going to be in 2.6.35?
> 
> Patch refs: http://patchwork.ozlabs.org/patch/53059/  and
> http://patchwork.ozlabs.org/patch/53674/
> 

Thanks,

-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 03/10] cifs: register CIFS for caching
  2010-06-23 16:51 ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
@ 2010-06-25 10:56   ` Suresh Jayaraman
  0 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 10:56 UTC (permalink / raw)
  To: David Howells; +Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel

On 06/23/2010 10:21 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman@suse.de> wrote:
> 
>> +	rc = cifs_fscache_register();
>> +	if (rc)
>> +		goto out;
>> +
>>  	rc = cifs_init_inodecache();
>>  	if (rc)
>>  		goto out_clean_proc;
>> @@ -949,8 +954,10 @@ init_cifs(void)
>>  	cifs_destroy_mids();
>>   out_destroy_inodecache:
>>  	cifs_destroy_inodecache();
>> +	cifs_fscache_unregister();
>>   out_clean_proc:
> 
> This is incorrect.  You need to call cifs_fscache_unregister() if
> cifs_init_inodecache() fails.
> 

Doh! I'll fix it.


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
  2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
@ 2010-06-25 12:44   ` Suresh Jayaraman
  2010-06-25 12:58   ` David Howells
  2010-06-25 13:26   ` David Howells
  2 siblings, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 12:44 UTC (permalink / raw)
  To: David Howells; +Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel

On 06/23/2010 10:28 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman@suse.de> wrote:
> 
>> Define superblock-level cache index objects (managed by cifsTconInfo
>> structs).  Each superblock object is created in a server-level index object
>> and in itself an index into which inode-level objects are inserted.
>>
>> Currently, the superblock objects are keyed by sharename.
> 
> Seems reasonable.  Is there any way you can check that the share you are
> looking at on a server is the same as the last time you looked?  Can you

Good point.

I thought of using TID (Tree identifier; a unique ID for a resource in
use by client) along with sharename. But, Server is free to reuse them
when the tree connection closes and does not guarantee the same Tid for
a particular resource across tree connections.

Also, considering the UNC name of the resource (//server/share) may not
be a good idea too as the cache will not be used when for e.g. IPaddress
is used to mount.

So, if a server does something like this:
   - export a share 'foo' (original server path: /export/vol1/foo)
   - client mounts and uses it
   - server unexports the share 'foo'
   - server exports 'foo' (original sever path: /export/vol2/foo)

we have a bit of problem..

> validate the root directory of the share in some way?
> 

I don't know if there is a way to do this.

Thanks,


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
@ 2010-06-25 12:50   ` Suresh Jayaraman
  2010-06-25 12:55   ` David Howells
  1 sibling, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 12:50 UTC (permalink / raw)
  To: David Howells; +Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel

On 06/23/2010 10:32 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman@suse.de> wrote:
> 
>> Define inode-level data storage objects (managed by cifsInodeInfo structs).
>> Each inode-level object is created in a super-block level object and is
>> itself a data storage object in to which pages from the inode are stored.
>>
>> The inode object is keyed by UniqueId. The coherency data being used is
>> LastWriteTime and the file size.
> 
> Isn't there a file creation time too?

I think the creation time is currently being ignored as we won't be able
to accomodate in POSIX stat struct.

> I take it you don't support caching on files that are open for writing at this
> time?
> 

Yes.


-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
  2010-06-25 12:50   ` Suresh Jayaraman
@ 2010-06-25 12:55   ` David Howells
  2010-06-25 16:53     ` Jeff Layton
  2010-06-25 21:46     ` David Howells
  1 sibling, 2 replies; 228+ messages in thread
From: David Howells @ 2010-06-25 12:55 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> I think the creation time is currently being ignored as we won't be able
> to accomodate in POSIX stat struct.

The FS-Cache interface doesn't use the POSIX stat struct, but it could be
really useful to save it and use it for cache coherency inside the kernel.

Out of interest, what does Samba do when it comes to generating a creation time
for UNIX where one does not exist?

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
  2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
  2010-06-25 12:44   ` Suresh Jayaraman
@ 2010-06-25 12:58   ` David Howells
  2010-06-25 13:26   ` David Howells
  2 siblings, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-25 12:58 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Also, considering the UNC name of the resource (//server/share) may not
> be a good idea too as the cache will not be used when for e.g. IPaddress
> is used to mount.

You could convert the UNC name to an IP address, and just use that as your
key.

> > validate the root directory of the share in some way?
>
> I don't know if there is a way to do this.

Is there an inode number or something?  Even the creation time might do.

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
  2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
  2010-06-25 12:44   ` Suresh Jayaraman
  2010-06-25 12:58   ` David Howells
@ 2010-06-25 13:26   ` David Howells
  2010-06-28 12:53     ` Suresh Jayaraman
  2010-06-28 13:24     ` David Howells
  2 siblings, 2 replies; 228+ messages in thread
From: David Howells @ 2010-06-25 13:26 UTC (permalink / raw)
  Cc: dhowells, Suresh Jayaraman, Steve French, linux-cifs,
	linux-fsdevel, linux-kernel

David Howells <dhowells@redhat.com> wrote:

> > > validate the root directory of the share in some way?
> >
> > I don't know if there is a way to do this.
> 
> Is there an inode number or something?  Even the creation time might do.

Looking in cifspdu.h, there are a number of things that it might be possible
to use.

 (1) FILE_ALL_INFO: CreationTime, IndexNumber, IndexNumber1, FileName
     (assuming this isn't flattened to '\' or something for the root of a
     share.

 (2) FILE_UNIX_BASIC_INFO: DevMajor, DevMinor, UniqueId.

 (3) FILE_INFO_STANDARD: CreationDate, CreationTime.

 (4) FILE_INFO_BASIC: CreationTime.

 (5) FILE_DIRECTORY_INFO: FileIndex, CreationTime, FileName.

 (6) SEARCH_ID_FULL_DIR_INFO: FileIndex, CreationTime, UniqueId, FileName.

 (7) FILE_BOTH_DIRECTORY_INFO: FileIndex, CreationTime, ShortName, FileName.

 (8) OPEN_RSP_EXT: Fid, CreationTime, VolumeGUID, FileId.

You may have to choose different sets of things, depending on what the server
has on offer.  Also, don't forget, if you can't work out whether a share is
coherent or not from the above, you can always use LastWriteTime, ChangeTime
and EndOfFile and just discard the whole subtree if they differ.

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-25 12:55   ` David Howells
@ 2010-06-25 16:53     ` Jeff Layton
  2010-06-25 21:46     ` David Howells
  1 sibling, 0 replies; 228+ messages in thread
From: Jeff Layton @ 2010-06-25 16:53 UTC (permalink / raw)
  To: David Howells
  Cc: Suresh Jayaraman, Steve French, linux-cifs, linux-fsdevel,
	linux-kernel, samba-technical

On Fri, 25 Jun 2010 13:55:49 +0100
David Howells <dhowells@redhat.com> wrote:

> Suresh Jayaraman <sjayaraman@suse.de> wrote:
> 
> > I think the creation time is currently being ignored as we won't be able
> > to accomodate in POSIX stat struct.
> 
> The FS-Cache interface doesn't use the POSIX stat struct, but it could be
> really useful to save it and use it for cache coherency inside the kernel.
> 
> Out of interest, what does Samba do when it comes to generating a creation time
> for UNIX where one does not exist?
> 

(cc'ing samba-technical since we're talking about the create time)

Looks like it mostly uses the ctime. IMO, the mtime would be a better
choice since it changes less frequently, but I don't guess that it
matters very much.

I have a few patches that make the cifs_iget code do more stringent
checks. One of those makes it use the create time like an i_generation
field to guard against matching inodes that have the same number but
that have undergone a delete/create cycle. They need a bit more testing
but I'm planning to post them in time for 2.6.36.

Because of how samba generates this number, it could be somewhat
problematic to do this. What may save us though is that Linux<->Samba
mostly uses unix extensions unless someone has specifically disabled
them on either end. The unix extension calls don't generally send any
sort of create time field, so we can't rely on it in those codepaths
anyway.

-- 
Jeff Layton <jlayton@samba.org>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-25 12:55   ` David Howells
  2010-06-25 16:53     ` Jeff Layton
@ 2010-06-25 21:46     ` David Howells
  2010-06-25 22:26       ` Jeff Layton
  2010-06-25 23:04       ` David Howells
  1 sibling, 2 replies; 228+ messages in thread
From: David Howells @ 2010-06-25 21:46 UTC (permalink / raw)
  To: Jeff Layton
  Cc: dhowells, Suresh Jayaraman, Steve French, linux-cifs,
	linux-fsdevel, linux-kernel, samba-technical

Jeff Layton <jlayton@samba.org> wrote:

> Looks like it mostly uses the ctime. IMO, the mtime would be a better
> choice since it changes less frequently, but I don't guess that it
> matters very much.

I'd've thought mtime changes more frequently since that's altered when data is
written.  ctime is changed when attributes are changed.

Note that Ext4 appears to have a file creation time field in its inode
(struct ext4_inode::i_crtime[_extra]).  Can Samba be made to use that?

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-25 21:46     ` David Howells
@ 2010-06-25 22:26       ` Jeff Layton
  2010-06-25 23:05         ` Steve French
  2010-06-25 23:04       ` David Howells
  1 sibling, 1 reply; 228+ messages in thread
From: Jeff Layton @ 2010-06-25 22:26 UTC (permalink / raw)
  To: David Howells
  Cc: Suresh Jayaraman, Steve French, linux-cifs, linux-fsdevel,
	linux-kernel, samba-technical

On Fri, 25 Jun 2010 22:46:38 +0100
David Howells <dhowells@redhat.com> wrote:

> Jeff Layton <jlayton@samba.org> wrote:
> 
> > Looks like it mostly uses the ctime. IMO, the mtime would be a better
> > choice since it changes less frequently, but I don't guess that it
> > matters very much.
> 
> I'd've thought mtime changes more frequently since that's altered when data is
> written.  ctime is changed when attributes are changed.
> 

IIUC, updating mtime for a write is also an attribute change, and that
affects ctime. According to the stat(2) manpage:

       The field st_ctime is changed by writing or by setting  inode  informa-
       tion (i.e., owner, group, link count, mode, etc.).

> Note that Ext4 appears to have a file creation time field in its inode
> (struct ext4_inode::i_crtime[_extra]).  Can Samba be made to use that?
> 

Is it exposed to userspace in any (standard) way? It would be handy to
have that. While we're wishing...it might also be nice to have a
standard way to get at the i_generation from userspace too.

-- 
Jeff Layton <jlayton@samba.org>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-25 21:46     ` David Howells
  2010-06-25 22:26       ` Jeff Layton
@ 2010-06-25 23:04       ` David Howells
  1 sibling, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-25 23:04 UTC (permalink / raw)
  To: Jeff Layton
  Cc: dhowells, Suresh Jayaraman, Steve French, linux-cifs,
	linux-fsdevel, linux-kernel, samba-technical

Jeff Layton <jlayton@samba.org> wrote:

> IIUC, updating mtime for a write is also an attribute change, and that
> affects ctime. According to the stat(2) manpage:

You're right.  Okay, ctime is the more frequently changed.

> > Note that Ext4 appears to have a file creation time field in its inode
> > (struct ext4_inode::i_crtime[_extra]).  Can Samba be made to use that?
> 
> Is it exposed to userspace in any (standard) way? It would be handy to
> have that. While we're wishing...it might also be nice to have a
> standard way to get at the i_generation from userspace too.

Not at present, but it's something that could be exported by ioctl() or
getxattr().

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and  register them
  2010-06-25 22:26       ` Jeff Layton
@ 2010-06-25 23:05         ` Steve French
       [not found]           ` <OFB55E8EC7.E8DD23D5-ON8725774E.0004921E-8825774E.0004CC31@us.ibm.com>
  0 siblings, 1 reply; 228+ messages in thread
From: Steve French @ 2010-06-25 23:05 UTC (permalink / raw)
  To: Jeff Layton, Aneesh Kumar K.V, Mingming Cao
  Cc: David Howells, Suresh Jayaraman, linux-cifs, linux-fsdevel,
	linux-kernel, samba-technical, Jeff Layton

On Fri, Jun 25, 2010 at 5:26 PM, Jeff Layton <jlayton@samba.org> wrote:
>
> On Fri, 25 Jun 2010 22:46:38 +0100
> David Howells <dhowells@redhat.com> wrote:
>
> > Jeff Layton <jlayton@samba.org> wrote:
> >
> > > Looks like it mostly uses the ctime. IMO, the mtime would be a better
> > > choice since it changes less frequently, but I don't guess that it
> > > matters very much.
> >
> > I'd've thought mtime changes more frequently since that's altered when data is
> > written.  ctime is changed when attributes are changed.
> >
>
> IIUC, updating mtime for a write is also an attribute change, and that
> affects ctime. According to the stat(2) manpage:
>
>       The field st_ctime is changed by writing or by setting  inode  informa-
>       tion (i.e., owner, group, link count, mode, etc.).
>
> > Note that Ext4 appears to have a file creation time field in its inode
> > (struct ext4_inode::i_crtime[_extra]).  Can Samba be made to use that?
> >
>
> Is it exposed to userspace in any (standard) way? It would be handy to
> have that. While we're wishing...it might also be nice to have a
> standard way to get at the i_generation from userspace too.
>

Yes - I have talked with MingMing and Aneesh about those (NFS may
someday be able to use those too).  An obstacle in the past had been
that samba server stores its own fake creation time in an ndr encoded
xattr which complicates things.

MingMing/Annesh -
Xattr or other way to get at birth time?


--
Thanks,

Steve

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
       [not found]           ` <OFB55E8EC7.E8DD23D5-ON8725774E.0004921E-8825774E.0004CC31@us.ibm.com>
@ 2010-06-27 18:17             ` Aneesh Kumar K. V
  2010-06-27 18:22               ` Christoph Hellwig
  0 siblings, 1 reply; 228+ messages in thread
From: Aneesh Kumar K. V @ 2010-06-27 18:17 UTC (permalink / raw)
  To: Mingming Cao, Steve French, DENIEL Philippe
  Cc: David Howells, Jeff Layton, Jeff Layton, linux-cifs,
	linux-fsdevel, linux-kernel, samba-technical, Suresh Jayaraman

On Fri, 25 Jun 2010 17:52:24 -0700, Mingming Cao <mcao@us.ibm.com> wrote:
> 
> 
> Steve French <smfrench@gmail.com> wrote on 06/25/2010 04:05:30 PM:
> 
> > Steve French <smfrench@gmail.com>
> > 06/25/2010 04:05 PM
> >
> > To
> >
> > Jeff Layton <jlayton@samba.org>, "Aneesh Kumar K.V"
> > <aneesh.kumar@linux.vnet.ibm.com>, Mingming Cao/Beaverton/IBM@IBMUS
> >
> > cc
> >
> > David Howells <dhowells@redhat.com>, Suresh Jayaraman
> > <sjayaraman@suse.de>, linux-cifs@vger.kernel.org, linux-
> > fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, samba-
> > technical@lists.samba.org, Jeff Layton <jlayton@redhat.com>
> >
> > Subject
> >
> > Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and
> > register them
> >
> > On Fri, Jun 25, 2010 at 5:26 PM, Jeff Layton <jlayton@samba.org> wrote:
> > >
> > > On Fri, 25 Jun 2010 22:46:38 +0100
> > > David Howells <dhowells@redhat.com> wrote:
> > >
> > > > Jeff Layton <jlayton@samba.org> wrote:
> > > >
> > > > > Looks like it mostly uses the ctime. IMO, the mtime would be a
> better
> > > > > choice since it changes less frequently, but I don't guess that it
> > > > > matters very much.
> > > >
> > > > I'd've thought mtime changes more frequently since that's
> > altered when data is
> > > > written.  ctime is changed when attributes are changed.
> > > >
> > >
> > > IIUC, updating mtime for a write is also an attribute change, and that
> > > affects ctime. According to the stat(2) manpage:
> > >
> > >       The field st_ctime is changed by writing or by setting
> >  inode  informa-
> > >       tion (i.e., owner, group, link count, mode, etc.).
> > >
> > > > Note that Ext4 appears to have a file creation time field in its
> inode
> > > > (struct ext4_inode::i_crtime[_extra]).  Can Samba be made to use
> that?
> > > >
> > >
> > > Is it exposed to userspace in any (standard) way? It would be handy to
> > > have that. While we're wishing...it might also be nice to have a
> > > standard way to get at the i_generation from userspace too.
> > >
> >
> > Yes - I have talked with MingMing and Aneesh about those (NFS may
> > someday be able to use those too).  An obstacle in the past had been
> > that samba server stores its own fake creation time in an ndr encoded
> > xattr which complicates things.
> >
> > MingMing/Annesh -
> > Xattr or other way to get at birth time?
> >
> >
> 
> Not yet,
>  The ext4 file creation time only accesable from the kernel at the moment.
> There were discussion
> to make this information avaliable via xattr before, but was rejected,
> since most people
> agree that making this info avalibele via stat() is more standard. However
> modifying stat() would imply
> big interface change. thus no action has been taken yet.

NFS ganesha pNFS also had a requirement for getting i_generation and
inode number in userspace. So may be we should now look at updating
stat or add a variant syscall that include i_generation and create time
in the return value

-aneesh

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
  2010-06-27 18:17             ` Aneesh Kumar K. V
@ 2010-06-27 18:22               ` Christoph Hellwig
  0 siblings, 0 replies; 228+ messages in thread
From: Christoph Hellwig @ 2010-06-27 18:22 UTC (permalink / raw)
  To: Aneesh Kumar K. V
  Cc: Mingming Cao, Steve French, DENIEL Philippe, David Howells,
	Jeff Layton, Jeff Layton, linux-cifs, linux-fsdevel,
	linux-kernel, samba-technical, Suresh Jayaraman

On Sun, Jun 27, 2010 at 11:47:21PM +0530, Aneesh Kumar K. V wrote:
> NFS ganesha pNFS also had a requirement for getting i_generation and
> inode number in userspace. So may be we should now look at updating
> stat or add a variant syscall that include i_generation and create time
> in the return value

What's missing in knfsd that you feel the sudden urge to move backwards
to a userspace nfsd (one with a horribly crappy codebase, too).


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
  2010-06-25 13:26   ` David Howells
@ 2010-06-28 12:53     ` Suresh Jayaraman
  2010-06-28 13:24     ` David Howells
  1 sibling, 0 replies; 228+ messages in thread
From: Suresh Jayaraman @ 2010-06-28 12:53 UTC (permalink / raw)
  To: David Howells; +Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel

On 06/25/2010 06:56 PM, David Howells wrote:
> David Howells <dhowells@redhat.com> wrote:
> 
>>>> validate the root directory of the share in some way?
>>>
>>> I don't know if there is a way to do this.
>>
>> Is there an inode number or something?  Even the creation time might do.
> 
> Looking in cifspdu.h, there are a number of things that it might be possible
> to use.
> 
>  (1) FILE_ALL_INFO: CreationTime, IndexNumber, IndexNumber1, FileName
>      (assuming this isn't flattened to '\' or something for the root of a
>      share.
> 
>  (2) FILE_UNIX_BASIC_INFO: DevMajor, DevMinor, UniqueId.
> 
>  (3) FILE_INFO_STANDARD: CreationDate, CreationTime.
> 
>  (4) FILE_INFO_BASIC: CreationTime.
> 
>  (5) FILE_DIRECTORY_INFO: FileIndex, CreationTime, FileName.
> 
>  (6) SEARCH_ID_FULL_DIR_INFO: FileIndex, CreationTime, UniqueId, FileName.
> 
>  (7) FILE_BOTH_DIRECTORY_INFO: FileIndex, CreationTime, ShortName, FileName.
> 
>  (8) OPEN_RSP_EXT: Fid, CreationTime, VolumeGUID, FileId.
> 
> You may have to choose different sets of things, depending on what the server
> has on offer.  Also, don't forget, if you can't work out whether a share is

Did you mean we need to validate differently for different servers?

I just did some testing and it looks like we could rely on CreationTime,
IndexNumber for validating with Windows servers (FileName is relative to
the mapped drive) and UniqueId for validating with Samba servers. I did
not test all possibilities (there could be more).

> coherent or not from the above, you can always use LastWriteTime, ChangeTime
> and EndOfFile and just discard the whole subtree if they differ.
> 

Thanks,

-- 
Suresh Jayaraman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
  2010-06-25 13:26   ` David Howells
  2010-06-28 12:53     ` Suresh Jayaraman
@ 2010-06-28 13:24     ` David Howells
  1 sibling, 0 replies; 228+ messages in thread
From: David Howells @ 2010-06-28 13:24 UTC (permalink / raw)
  To: Suresh Jayaraman
  Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel

Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Did you mean we need to validate differently for different servers?

You may need to, yes, as different servers may make different attributes
available.

This isn't too bad.  Each server index record in the cache has freeform
auxiliary data, just as does each file data record.  You could, say, stick a
byte at the front that indicates what you've stored in there.

David

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH] Add ok2440 development board support.
       [not found] <yes>
                   ` (21 preceding siblings ...)
  2010-06-23 17:08 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching David Howells
@ 2011-06-15  0:46 ` Wu DaoGuang
  2011-10-03  0:32 ` [PATCH 1/1] ARM: Make debug UART optional for S3C devices Thiago A. Correa
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: Wu DaoGuang @ 2011-06-15  0:46 UTC (permalink / raw)
  To: linux, ben-linux, wdgvip; +Cc: linux-arm-kernel, linux-kernel

This patch has been modified for the second time .Reduced the size
of the file ok2440_defconfig and updated to the latest APIs.

The ok2440 development board is based on SAMSUNG's S3C2440
microprocessor,which is developed with ARM920T core.

Thanks to Vasily Khoruzhick <anarsoul@gmail.com> for detailed
proposal in this patch.

This patch is against v3.0-rc3.

Signed-off-by: Wu DaoGuang <wdgvip@gmail.com>
---
 arch/arm/configs/ok2440_defconfig   |  384 +++++++++++++++++++++++++++++
 arch/arm/mach-s3c2440/Kconfig       |   10 +
 arch/arm/mach-s3c2440/Makefile      |    1 +
 arch/arm/mach-s3c2440/mach-ok2440.c |  457 +++++++++++++++++++++++++++++++++++
 4 files changed, 852 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/configs/ok2440_defconfig
 create mode 100644 arch/arm/mach-s3c2440/mach-ok2440.c

diff --git a/arch/arm/configs/ok2440_defconfig b/arch/arm/configs/ok2440_defconfig
new file mode 100644
index 0000000..45f2c86
--- /dev/null
+++ b/arch/arm/configs/ok2440_defconfig
@@ -0,0 +1,384 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_RELAY=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_ARCH_S3C2410=y
+CONFIG_S3C_ADC=y
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_OK2440=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_KEXEC=y
+CONFIG_CPU_IDLE=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+CONFIG_PM=y
+CONFIG_APM_EMULATION=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=m
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_NET_PKTGEN=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_REG_DEBUG=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+CONFIG_RFD_FTL=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_S3C2410=y
+CONFIG_MTD_NAND_PLATFORM=y
+CONFIG_MTD_LPDDR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_SG=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_NET_ETHERNET=y
+CONFIG_DM9000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_ZD1211RW_DEBUG=y
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIO_RAW=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_LEGACY_PTY_COUNT=128
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_S3C2410=y
+CONFIG_I2C_SIMTEC=y
+CONFIG_SPI=y
+CONFIG_SPI_S3C24XX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_SENSORS_LM75=y
+CONFIG_THERMAL=m
+CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_S3C2410=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_DISPLAY_SUPPORT=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_HIDRAW=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=m
+CONFIG_USB_WDM=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_S3C2410=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_MMC=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_S3C=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_S3C24XX=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_DMADEVICES=y
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_INOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 50825a3..1214909 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -176,6 +176,16 @@ config MACH_AT2440EVB
 	help
 	  Say Y here if you are using the AT2440EVB development board
 
+config MACH_OK2440
+	bool "OK2440 development board"
+	select CPU_S3C2440
+	select S3C2440_XTAL_12000000
+	select S3C_DEV_NAND
+	select S3C_DEV_USB_HOST
+	help
+	  Say y here to select support for OK2440. Now it is widely used for
+	  many students and Companies.
+
 config MACH_MINI2440
 	bool "MINI2440 development board"
 	select CPU_S3C2440
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index d5440fa..da4ad71 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
 obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
+obj-$(CONFIG_MACH_OK2440)	+= mach-ok2440.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
 obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
 obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
diff --git a/arch/arm/mach-s3c2440/mach-ok2440.c b/arch/arm/mach-s3c2440/mach-ok2440.c
new file mode 100644
index 0000000..43700e8
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-ok2440.c
@@ -0,0 +1,457 @@
+/* linux/arch/arm/mach-s3c2440/mach-ok2440.c
+ *
+ *	Copyright (c) 2011  Feiling Embedded
+ *	Base on mach-smdk2440.c by Ben Dooks <ben@simtec.co.uk>
+ *
+ *	Wu DaoGuang <wdgvip@gmail.com>
+ *
+ * Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/dm9000.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/mmc/host.h>
+#include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
+
+#include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/nand.h>
+#include <plat/iic.h>
+#include <plat/udc.h>
+#include <plat/mci.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/leds-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/regs-lcd.h>
+#include <mach/regs-mem.h>
+#include <mach/irqs.h>
+
+
+#include <mach/idle.h>
+#include <mach/fb.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-cfg.h>
+#include <plat/usb-control.h>
+
+#include <plat/s3c2410.h>
+#include <plat/s3c244x.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+#include <plat/common-smdk.h>
+#include <sound/s3c24xx_uda134x.h>
+
+#define MACH_OK2440_DM9K_BASE (S3C2410_CS4 + 0x300)
+
+static struct map_desc ok2440_iodesc[] __initdata = {
+	/* ISA IO Space map (memory space selected by A24) */
+
+	{
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
+		.pfn		= __phys_to_pfn(S3C2410_CS2),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+		.pfn		= __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+		.length		= SZ_4M,
+		.type		= MT_DEVICE,
+	}
+};
+
+#define UCON	(S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
+#define ULCON	(S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON	(S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg ok2440_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+/* LCD driver info */
+
+static struct s3c2410fb_display ok2440_lcd_cfg __initdata = {
+
+	.lcdcon5	= S3C2410_LCDCON5_FRM565 |
+			  S3C2410_LCDCON5_INVVLINE |
+			  S3C2410_LCDCON5_INVVFRAME |
+			  S3C2410_LCDCON5_PWREN |
+			  S3C2410_LCDCON5_HWSWP,
+
+	.type		= S3C2410_LCDCON1_TFT,
+
+	.width		= 320,
+	.height		= 240,
+
+	.pixclock	= 270000, /* HCLK 60 MHz, divisor 10 */
+	.xres		= 320,
+	.yres		= 240,
+	.bpp		= 16,
+	.left_margin	= 8,
+	.right_margin	= 5,
+	.hsync_len	= 16,
+	.upper_margin	= 8,
+	.lower_margin	= 5,
+	.vsync_len	= 2,
+};
+
+static struct s3c2410fb_mach_info ok2440_fb_info __initdata = {
+	.displays	= &ok2440_lcd_cfg,
+	.num_displays	= 1,
+	.default_display = 0,
+	.lpcsel		= ((0xCE6) & ~7) | 1<<4,
+};
+
+/* Nand flash partitions on ok2440 */
+static struct mtd_partition ok2440_default_nand_part[] = {
+	[0] = {
+		.name	= "u-boot",
+		.size	= SZ_1M,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "App",
+		.size	= SZ_2M,
+		.offset	= MTDPART_OFS_APPEND,
+	},
+	[2] = {
+		.name	= "Kernel",
+		.size	= SZ_1M*4,
+		.offset	= MTDPART_OFS_APPEND,
+	},
+	[3] = {
+		.name	= "Ramdisk",
+		.size	= SZ_16M,
+		.offset	= MTDPART_OFS_APPEND,
+	},
+	[3] = {
+		.name	= "Rootfs",
+		.size	= MTDPART_SIZ_FULL,
+		.offset	= MTDPART_OFS_APPEND,
+	},
+};
+static struct s3c2410_nand_set ok2440_nand_sets[] = {
+	[0] = {
+		.name		= "nand",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(ok2440_default_nand_part),
+		.partitions	= ok2440_default_nand_part,
+		.flash_bbt	= 1, /* We use u-boot to creat a BBT*/
+	}
+};
+
+static struct s3c2410_platform_nand ok2440_nand_info __initdata = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(ok2440_nand_sets),
+	.sets		= ok2440_nand_sets,
+	.ignore_unset_ecc = 1,
+};
+
+
+/* DM9000AEP 10/100 ethernet controller */
+static struct resource ok2440_dm9k_resource[] = {
+	[0] = {
+		.start = MACH_OK2440_DM9K_BASE,
+		.end   = MACH_OK2440_DM9K_BASE + 3,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = MACH_OK2440_DM9K_BASE + 4,
+		.end   = MACH_OK2440_DM9K_BASE + 7,
+		.flags = IORESOURCE_MEM
+	},
+	[2] = {
+		.start = IRQ_EINT7,
+		.end   = IRQ_EINT7,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+/* The DM9000 has no eeprom ,and it's MAC address is set by
+ * the bootloader before starting the kernel.
+ */
+static struct dm9000_plat_data ok2440_dm9k_pdata = {
+	.flags		= (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+};
+static struct platform_device ok2440_device_eth = {
+	.name		= "dm9000",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ok2440_dm9k_resource),
+	.resource	= ok2440_dm9k_resource,
+	.dev		= {
+		.platform_data	= &ok2440_dm9k_pdata,
+	},
+};
+
+/* LEDS sourport */
+static struct gpio_led ok2440_leds_desc[] = {
+	{
+		.name			= "led0",
+		.default_trigger	= "heartbeat",
+		.gpio			= S3C2410_GPF(3),
+	},
+	{
+		.name			= "led1",
+		.default_trigger	= "nand-disk",
+		.gpio			= S3C2410_GPF(4),
+	},
+	{
+		.name			= "led2",
+		.default_trigger	= "mmc",
+		.gpio			= S3C2410_GPF(5),
+	},
+	{
+		.name			= "led3",
+		.default_trigger	= "network",
+		.gpio			= S3C2410_GPF(6),
+	},
+};
+
+static struct gpio_led_platform_data ok2440_leds_pdata = {
+	.num_leds	= ARRAY_SIZE(ok2440_leds_desc),
+	.leds		= ok2440_leds_desc,
+};
+
+static struct platform_device ok2440_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &ok2440_leds_pdata,
+	},
+};
+/* GPIO KEYS */
+static struct gpio_keys_button ok2440_gpio_keys_table[] = {
+	{
+		.code		= KEY_LEFT,
+		.gpio		= S3C2410_GPF(0),
+		.active_low	= 1,
+		.desc		= "Left button",
+	},
+	{
+		.code		= KEY_RIGHT,
+		.gpio		= S3C2410_GPF(2),
+		.active_low	= 1,
+		.desc		= "Right button",
+	},
+	{
+		.code		= KEY_UP,
+		.gpio		= S3C2410_GPB(5),
+		.active_low	= 1,
+		.desc		= "Up button",
+	},
+	{
+		.code		= KEY_DOWN,
+		.gpio		= S3C2410_GPB(6),
+		.active_low	= 1,
+		.desc		= "Down button",
+	},
+	{
+		.code		= KEY_ENTER,
+		.gpio		= S3C2410_GPB(7),
+		.active_low	= 1,
+		.desc		= "Ok button",
+	},
+
+};
+static struct gpio_keys_platform_data ok2440_gpio_keys_pdata = {
+	.buttons	= ok2440_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(ok2440_gpio_keys_table),
+};
+static struct platform_device ok2440_device_gpiokeys = {
+	.name			= "gpio-keys",
+	.dev.platform_data	= &ok2440_gpio_keys_pdata,
+};
+/* AUDIO */
+static struct s3c24xx_uda134x_platform_data ok2440_audio_pins = {
+	.l3_clk = S3C2410_GPB(4),
+	.l3_mode = S3C2410_GPB(2),
+	.l3_data = S3C2410_GPB(3),
+	.model   = UDA134X_UDA1341
+};
+
+static struct platform_device ok2440_audio = {
+	.name		= "s3c24xx_uda134x",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ok2440_audio_pins,
+	}
+};
+
+static struct platform_device uda1340_codec = {
+	.name = "uda134x-codec",
+	.id   = -1,
+};
+
+/*
+ * I2C devices
+ */
+static struct at24_platform_data at24c08 = {
+	.byte_len	= SZ_8K / 8,
+	.page_size	= 16,
+};
+
+static struct i2c_board_info ok2440_i2c_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("24c08", 0x50),
+		.platform_data	= &at24c08,
+	},
+};
+
+/*  USB device UDC support */
+static struct s3c2410_udc_mach_info ok2440_udc_cfg __initdata = {
+	.pullup_pin = S3C2410_GPG(9),
+};
+
+/* USB */
+static struct s3c2410_hcd_info ok2440_usb_info __initdata = {
+	.port[0]	= {
+		.flags	= S3C_HCDFLG_USED,
+	},
+	.port[1]	= {
+		.flags	= 0,
+	},
+};
+
+/* MMC/SD */
+static struct s3c24xx_mci_pdata ok2440_mmc_cfg __initdata = {
+	.gpio_detect	= S3C2410_GPG(10),
+	.gpio_wprotect	= S3C2410_GPH(8),
+	.set_power	= NULL,
+	.ocr_avail	= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+
+struct syscore_ops s3c24xx_irq_syscore_ops = {
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
+};
+
+static struct platform_device *ok2440_devices[] __initdata = {
+	&s3c_device_ohci,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c0,
+	&s3c_device_iis,
+	&s3c_device_sdi,
+	&s3c_device_nand,
+	&s3c_device_rtc,
+	&s3c_device_usbgadget,
+	&ok2440_device_gpiokeys,
+	&uda1340_codec,
+	&ok2440_device_eth,
+	&ok2440_audio,
+	&ok2440_leds,
+	&samsung_asoc_dma,
+
+};
+
+static void __init ok2440_map_io(void)
+{
+	s3c24xx_init_io(ok2440_iodesc, ARRAY_SIZE(ok2440_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(ok2440_uartcfgs, ARRAY_SIZE(ok2440_uartcfgs));
+}
+
+static void __init ok2440_machine_init(void)
+{
+	/*configure the mmc protect to pull high . */
+	WARN_ON(gpio_request(S3C2410_GPG(8), "mmc pull up"));
+	gpio_direction_output(S3C2410_GPG(8), 1);
+	s3c24xx_fb_set_platdata(&ok2440_fb_info);
+	s3c_i2c0_set_platdata(NULL);
+
+	s3c_ohci_set_platdata(&ok2440_usb_info);
+
+	s3c_nand_set_platdata(&ok2440_nand_info);
+	s3c24xx_udc_set_platdata(&ok2440_udc_cfg);
+	s3c24xx_mci_set_platdata(&ok2440_mmc_cfg);
+	i2c_register_board_info(0, ok2440_i2c_devs,
+				ARRAY_SIZE(ok2440_i2c_devs));
+
+	platform_add_devices(ok2440_devices, ARRAY_SIZE(ok2440_devices));
+	s3c_pm_init();
+}
+
+MACHINE_START(S3C2440, "OK2440 development board.")
+	/* Maintainer: Wu DaoGuang <wdgvip@gmail.com> */
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= ok2440_map_io,
+	.init_machine	= ok2440_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 1/1] ARM: Make debug UART optional for S3C devices
       [not found] <yes>
                   ` (22 preceding siblings ...)
  2011-06-15  0:46 ` [PATCH] Add ok2440 development board support Wu DaoGuang
@ 2011-10-03  0:32 ` Thiago A. Correa
  2011-10-10 14:44   ` Thiago A. Corrêa
  2011-12-11 13:10 ` [PATCH] block: Needn't read the size of device or partition again taco
                   ` (10 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Thiago A. Correa @ 2011-10-03  0:32 UTC (permalink / raw)
  To: Russell King, Ben Dooks, linux-arm-kernel, linux-kernel; +Cc: Thiago A. Correa

This patch makes serial debug messages optional on
Samsung SoC s3c devices making all UART ports available
for other uses.

Signed-off-by: Thiago A. Correa <thiago.correa@gmail.com>
---
 arch/arm/boot/compressed/head.S                 |    2 +-
 arch/arm/plat-samsung/Kconfig                   |   11 +++++++++++
 arch/arm/plat-samsung/include/plat/uncompress.h |    9 +++++++++
 3 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 9f5ac11..3afb755 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -58,7 +58,7 @@
 		add	\rb, \rb, #0x00010000	@ Ser1
 #endif
 		.endm
-#elif defined(CONFIG_ARCH_S3C2410)
+#elif defined(CONFIG_ARCH_S3C2410) && CONFIG_ENABLE_DEBUG_S3C_UART
 		.macro loadsp, rb, tmp
 		mov	\rb, #0x50000000
 		add	\rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index b3e1065..c2183f0 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -33,7 +33,17 @@ config S3C_BOOT_ERROR_RESET
 	  Say y here to use the watchdog to reset the system if the
 	  kernel decompressor detects an error during decompression.
 
+
+config ENABLE_DEBUG_S3C_UART
+	bool "Enable S3C Debug UART"
+	help
+	  Say Y here if you want debug print of low level kernel messages
+	  using S3C UARTS.
+
+	  If in doubt, say N.
+
 config S3C_BOOT_UART_FORCE_FIFO
+       depends on ENABLE_DEBUG_S3C_UART
        bool "Force UART FIFO on during boot process"
        default y
        help
@@ -42,6 +52,7 @@ config S3C_BOOT_UART_FORCE_FIFO
 
 
 config S3C_LOWLEVEL_UART_PORT
+	depends on ENABLE_DEBUG_S3C_UART
 	int "S3C UART to use for low-level messages"
 	default 0
 	help
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h
index ee48e12..778c2df 100644
--- a/arch/arm/plat-samsung/include/plat/uncompress.h
+++ b/arch/arm/plat-samsung/include/plat/uncompress.h
@@ -37,6 +37,7 @@ static void arch_detect_cpu(void);
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX	 (14)
 
+#if defined(CONFIG_ENABLE_DEBUG_S3C_UART)
 #define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)
 
 static __inline__ void
@@ -85,11 +86,19 @@ static void putc(int ch)
 	/* write byte to transmission register */
 	uart_wr(S3C2410_UTXH, ch);
 }
+#else
+static inline void putc(int ch)
+{
+}
+
+
+#endif
 
 static inline void flush(void)
 {
 }
 
+
 #define __raw_writel(d, ad)			\
 	do {							\
 		*((volatile unsigned int __force *)(ad)) = (d); \
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/1] ARM: Make debug UART optional for S3C devices
  2011-10-03  0:32 ` [PATCH 1/1] ARM: Make debug UART optional for S3C devices Thiago A. Correa
@ 2011-10-10 14:44   ` Thiago A. Corrêa
  0 siblings, 0 replies; 228+ messages in thread
From: Thiago A. Corrêa @ 2011-10-10 14:44 UTC (permalink / raw)
  To: Russell King, Ben Dooks, linux-arm-kernel, linux-kernel; +Cc: Thiago A. Correa

Hi,

    This was the first patch I have submited, would appreciate an Ack
or comments.

Kind Regards,
   Thiago A. Correa

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH] block: Needn't read the size of device or partition again
       [not found] <yes>
                   ` (23 preceding siblings ...)
  2011-10-03  0:32 ` [PATCH 1/1] ARM: Make debug UART optional for S3C devices Thiago A. Correa
@ 2011-12-11 13:10 ` taco
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 228+ messages in thread
From: taco @ 2011-12-11 13:10 UTC (permalink / raw)
  To: axboe, linux-kernel; +Cc: taco, linux-scsi

It is not necessary to invoke i_size_read to get the size of device or
partition again, due to did it before.i_size_read maybe need to abtain
lock or disable preempt.

Signed-off-by: taco <tacoee@gmail.com>
---
 block/blk-core.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index ea70e6c..3aa3fc3 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1423,7 +1423,7 @@ static inline void blk_partition_remap(struct bio *bio)
 	}
 }
 
-static void handle_bad_sector(struct bio *bio)
+static void handle_bad_sector(struct bio *bio, sector_t maxsector)
 {
 	char b[BDEVNAME_SIZE];
 
@@ -1432,7 +1432,7 @@ static void handle_bad_sector(struct bio *bio)
 			bdevname(bio->bi_bdev, b),
 			bio->bi_rw,
 			(unsigned long long)bio->bi_sector + bio_sectors(bio),
-			(long long)(i_size_read(bio->bi_bdev->bd_inode) >> 9));
+			(long long)maxsector);
 
 	set_bit(BIO_EOF, &bio->bi_flags);
 }
@@ -1493,7 +1493,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
 			 * without checking the size of the device, e.g., when
 			 * mounting a device.
 			 */
-			handle_bad_sector(bio);
+			handle_bad_sector(bio, maxsector);
 			return 1;
 		}
 	}
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 1/4] slub: change declare of get_slab() to inline at all times
       [not found] <yes>
                   ` (24 preceding siblings ...)
  2011-12-11 13:10 ` [PATCH] block: Needn't read the size of device or partition again taco
@ 2012-06-08 17:23 ` Joonsoo Kim
  2012-06-08 17:23   ` [PATCH 2/4] slub: use __cmpxchg_double_slab() at interrupt disabled place Joonsoo Kim
                     ` (3 more replies)
  2012-06-22 18:22 ` [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
                   ` (8 subsequent siblings)
  34 siblings, 4 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-08 17:23 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

__kmalloc and it's variants are invoked much frequently
and these are performance critical functions,
so their callee functions are declared '__always_inline'
But, currently, get_slab() isn't declared '__always_inline'.
In result, __kmalloc and it's variants call get_slab() on x86.
It is not desirable result, so change it to inline at all times.

Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index 71de9b5..30ceb6d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3320,7 +3320,7 @@ static inline int size_index_elem(size_t bytes)
 	return (bytes - 1) / 8;
 }
 
-static struct kmem_cache *get_slab(size_t size, gfp_t flags)
+static __always_inline struct kmem_cache *get_slab(size_t size, gfp_t flags)
 {
 	int index;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 2/4] slub: use __cmpxchg_double_slab() at interrupt disabled place
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
@ 2012-06-08 17:23   ` Joonsoo Kim
  2012-06-08 17:23   ` [PATCH 3/4] slub: refactoring unfreeze_partials() Joonsoo Kim
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-08 17:23 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

get_freelist(), unfreeze_partials() are only called with interrupt disabled,
so __cmpxchg_double_slab() is suitable.

Acked-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index 30ceb6d..686ed90 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1879,7 +1879,11 @@ redo:
 	}
 }
 
-/* Unfreeze all the cpu partial slabs */
+/*
+ * Unfreeze all the cpu partial slabs.
+ *
+ * This function must be called with interrupt disabled.
+ */
 static void unfreeze_partials(struct kmem_cache *s)
 {
 	struct kmem_cache_node *n = NULL;
@@ -1935,7 +1939,7 @@ static void unfreeze_partials(struct kmem_cache *s)
 				l = m;
 			}
 
-		} while (!cmpxchg_double_slab(s, page,
+		} while (!__cmpxchg_double_slab(s, page,
 				old.freelist, old.counters,
 				new.freelist, new.counters,
 				"unfreezing slab"));
@@ -2163,6 +2167,8 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags,
  * The page is still frozen if the return value is not NULL.
  *
  * If this function returns NULL then the page has been unfrozen.
+ *
+ * This function must be called with interrupt disabled.
  */
 static inline void *get_freelist(struct kmem_cache *s, struct page *page)
 {
@@ -2179,7 +2185,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
 		new.inuse = page->objects;
 		new.frozen = freelist != NULL;
 
-	} while (!cmpxchg_double_slab(s, page,
+	} while (!__cmpxchg_double_slab(s, page,
 		freelist, counters,
 		NULL, new.counters,
 		"get_freelist"));
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 3/4] slub: refactoring unfreeze_partials()
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
  2012-06-08 17:23   ` [PATCH 2/4] slub: use __cmpxchg_double_slab() at interrupt disabled place Joonsoo Kim
@ 2012-06-08 17:23   ` Joonsoo Kim
  2012-06-20  7:19     ` Pekka Enberg
  2012-06-08 17:23   ` [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab() Joonsoo Kim
  2012-06-08 19:02   ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Christoph Lameter
  3 siblings, 1 reply; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-08 17:23 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

Current implementation of unfreeze_partials() is so complicated,
but benefit from it is insignificant. In addition many code in
do {} while loop have a bad influence to a fail rate of cmpxchg_double_slab.
Under current implementation which test status of cpu partial slab
and acquire list_lock in do {} while loop,
we don't need to acquire a list_lock and gain a little benefit
when front of the cpu partial slab is to be discarded, but this is a rare case.
In case that add_partial is performed and cmpxchg_double_slab is failed,
remove_partial should be called case by case.

I think that these are disadvantages of current implementation,
so I do refactoring unfreeze_partials().

Minimizing code in do {} while loop introduce a reduced fail rate
of cmpxchg_double_slab. Below is output of 'slabinfo -r kmalloc-256'
when './perf stat -r 33 hackbench 50 process 4000 > /dev/null' is done.

** before **
Cmpxchg_double Looping
------------------------
Locked Cmpxchg Double redos   182685
Unlocked Cmpxchg Double redos 0

** after **
Cmpxchg_double Looping
------------------------
Locked Cmpxchg Double redos   177995
Unlocked Cmpxchg Double redos 1

We can see cmpxchg_double_slab fail rate is improved slightly.

Bolow is output of './perf stat -r 30 hackbench 50 process 4000 > /dev/null'.

** before **
 Performance counter stats for './hackbench 50 process 4000' (30 runs):

     108517.190463 task-clock                #    7.926 CPUs utilized            ( +-  0.24% )
         2,919,550 context-switches          #    0.027 M/sec                    ( +-  3.07% )
           100,774 CPU-migrations            #    0.929 K/sec                    ( +-  4.72% )
           124,201 page-faults               #    0.001 M/sec                    ( +-  0.15% )
   401,500,234,387 cycles                    #    3.700 GHz                      ( +-  0.24% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   250,576,913,354 instructions              #    0.62  insns per cycle          ( +-  0.13% )
    45,934,956,860 branches                  #  423.297 M/sec                    ( +-  0.14% )
       188,219,787 branch-misses             #    0.41% of all branches          ( +-  0.56% )

      13.691837307 seconds time elapsed                                          ( +-  0.24% )

** after **
 Performance counter stats for './hackbench 50 process 4000' (30 runs):

     107784.479767 task-clock                #    7.928 CPUs utilized            ( +-  0.22% )
         2,834,781 context-switches          #    0.026 M/sec                    ( +-  2.33% )
            93,083 CPU-migrations            #    0.864 K/sec                    ( +-  3.45% )
           123,967 page-faults               #    0.001 M/sec                    ( +-  0.15% )
   398,781,421,836 cycles                    #    3.700 GHz                      ( +-  0.22% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   250,189,160,419 instructions              #    0.63  insns per cycle          ( +-  0.09% )
    45,855,370,128 branches                  #  425.436 M/sec                    ( +-  0.10% )
       169,881,248 branch-misses             #    0.37% of all branches          ( +-  0.43% )

      13.596272341 seconds time elapsed                                          ( +-  0.22% )

No regression is found, but rather we can see slightly better result.

Acked-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index 686ed90..b5f2108 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1886,18 +1886,24 @@ redo:
  */
 static void unfreeze_partials(struct kmem_cache *s)
 {
-	struct kmem_cache_node *n = NULL;
+	struct kmem_cache_node *n = NULL, *n2 = NULL;
 	struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab);
 	struct page *page, *discard_page = NULL;
 
 	while ((page = c->partial)) {
-		enum slab_modes { M_PARTIAL, M_FREE };
-		enum slab_modes l, m;
 		struct page new;
 		struct page old;
 
 		c->partial = page->next;
-		l = M_FREE;
+
+		n2 = get_node(s, page_to_nid(page));
+		if (n != n2) {
+			if (n)
+				spin_unlock(&n->list_lock);
+
+			n = n2;
+			spin_lock(&n->list_lock);
+		}
 
 		do {
 
@@ -1910,43 +1916,17 @@ static void unfreeze_partials(struct kmem_cache *s)
 
 			new.frozen = 0;
 
-			if (!new.inuse && (!n || n->nr_partial > s->min_partial))
-				m = M_FREE;
-			else {
-				struct kmem_cache_node *n2 = get_node(s,
-							page_to_nid(page));
-
-				m = M_PARTIAL;
-				if (n != n2) {
-					if (n)
-						spin_unlock(&n->list_lock);
-
-					n = n2;
-					spin_lock(&n->list_lock);
-				}
-			}
-
-			if (l != m) {
-				if (l == M_PARTIAL) {
-					remove_partial(n, page);
-					stat(s, FREE_REMOVE_PARTIAL);
-				} else {
-					add_partial(n, page,
-						DEACTIVATE_TO_TAIL);
-					stat(s, FREE_ADD_PARTIAL);
-				}
-
-				l = m;
-			}
-
 		} while (!__cmpxchg_double_slab(s, page,
 				old.freelist, old.counters,
 				new.freelist, new.counters,
 				"unfreezing slab"));
 
-		if (m == M_FREE) {
+		if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) {
 			page->next = discard_page;
 			discard_page = page;
+		} else {
+			add_partial(n, page, DEACTIVATE_TO_TAIL);
+			stat(s, FREE_ADD_PARTIAL);
 		}
 	}
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab()
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
  2012-06-08 17:23   ` [PATCH 2/4] slub: use __cmpxchg_double_slab() at interrupt disabled place Joonsoo Kim
  2012-06-08 17:23   ` [PATCH 3/4] slub: refactoring unfreeze_partials() Joonsoo Kim
@ 2012-06-08 17:23   ` Joonsoo Kim
  2012-06-08 19:04     ` Christoph Lameter
  2012-06-08 19:02   ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Christoph Lameter
  3 siblings, 1 reply; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-08 17:23 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

Current implementation of deactivate_slab() which deactivate
freelist of kmem_cache_cpu one by one is inefficient.
This patch changes it to deactivate freelist all at once.
But, there is no overall performance benefit,
because deactivate_slab() is invoked infrequently.

Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index b5f2108..7bcb434 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1733,16 +1733,14 @@ void init_kmem_cache_cpus(struct kmem_cache *s)
  */
 static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 {
-	enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE };
 	struct page *page = c->page;
 	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-	int lock = 0;
-	enum slab_modes l = M_NONE, m = M_NONE;
-	void *freelist;
-	void *nextfree;
-	int tail = DEACTIVATE_TO_HEAD;
+	void *freelist, *lastfree = NULL;
+	unsigned int nr_free = 0;
 	struct page new;
-	struct page old;
+	void *prior;
+	unsigned long counters;
+	int lock = 0, tail = DEACTIVATE_TO_HEAD;
 
 	if (page->freelist) {
 		stat(s, DEACTIVATE_REMOTE_FREES);
@@ -1752,127 +1750,54 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 	c->tid = next_tid(c->tid);
 	c->page = NULL;
 	freelist = c->freelist;
-	c->freelist = NULL;
-
-	/*
-	 * Stage one: Free all available per cpu objects back
-	 * to the page freelist while it is still frozen. Leave the
-	 * last one.
-	 *
-	 * There is no need to take the list->lock because the page
-	 * is still frozen.
-	 */
-	while (freelist && (nextfree = get_freepointer(s, freelist))) {
-		void *prior;
-		unsigned long counters;
-
-		do {
-			prior = page->freelist;
-			counters = page->counters;
-			set_freepointer(s, freelist, prior);
-			new.counters = counters;
-			new.inuse--;
-			VM_BUG_ON(!new.frozen);
-
-		} while (!__cmpxchg_double_slab(s, page,
-			prior, counters,
-			freelist, new.counters,
-			"drain percpu freelist"));
-
-		freelist = nextfree;
+	while (freelist) {
+		lastfree = freelist;
+		freelist = get_freepointer(s, freelist);
+		nr_free++;
 	}
 
-	/*
-	 * Stage two: Ensure that the page is unfrozen while the
-	 * list presence reflects the actual number of objects
-	 * during unfreeze.
-	 *
-	 * We setup the list membership and then perform a cmpxchg
-	 * with the count. If there is a mismatch then the page
-	 * is not unfrozen but the page is on the wrong list.
-	 *
-	 * Then we restart the process which may have to remove
-	 * the page from the list that we just put it on again
-	 * because the number of objects in the slab may have
-	 * changed.
-	 */
-redo:
+	freelist = c->freelist;
+	c->freelist = NULL;
 
-	old.freelist = page->freelist;
-	old.counters = page->counters;
-	VM_BUG_ON(!old.frozen);
+	do {
+		if (lock) {
+			lock = 0;
+			spin_unlock(&n->list_lock);
+		}
 
-	/* Determine target state of the slab */
-	new.counters = old.counters;
-	if (freelist) {
-		new.inuse--;
-		set_freepointer(s, freelist, old.freelist);
-		new.freelist = freelist;
-	} else
-		new.freelist = old.freelist;
+		prior = page->freelist;
+		counters = page->counters;
 
-	new.frozen = 0;
+		if (lastfree)
+			set_freepointer(s, lastfree, prior);
+		else
+			freelist = prior;
 
-	if (!new.inuse && n->nr_partial > s->min_partial)
-		m = M_FREE;
-	else if (new.freelist) {
-		m = M_PARTIAL;
-		if (!lock) {
-			lock = 1;
-			/*
-			 * Taking the spinlock removes the possiblity
-			 * that acquire_slab() will see a slab page that
-			 * is frozen
-			 */
-			spin_lock(&n->list_lock);
-		}
-	} else {
-		m = M_FULL;
-		if (kmem_cache_debug(s) && !lock) {
+		new.counters = counters;
+		VM_BUG_ON(!new.frozen);
+		new.inuse -= nr_free;
+		new.frozen = 0;
+
+		if (new.inuse || n->nr_partial <= s->min_partial) {
 			lock = 1;
-			/*
-			 * This also ensures that the scanning of full
-			 * slabs from diagnostic functions will not see
-			 * any frozen slabs.
-			 */
 			spin_lock(&n->list_lock);
 		}
-	}
-
-	if (l != m) {
-
-		if (l == M_PARTIAL)
-
-			remove_partial(n, page);
-
-		else if (l == M_FULL)
-
-			remove_full(s, page);
-
-		if (m == M_PARTIAL) {
 
+	} while (!__cmpxchg_double_slab(s, page,
+				prior, counters,
+				freelist, new.counters,
+				"drain percpu freelist"));
+	if (lock) {
+		if (kmem_cache_debug(s) && !freelist) {
+			add_full(s, n, page);
+			stat(s, DEACTIVATE_FULL);
+		} else {
 			add_partial(n, page, tail);
 			stat(s, tail);
-
-		} else if (m == M_FULL) {
-
-			stat(s, DEACTIVATE_FULL);
-			add_full(s, n, page);
-
 		}
-	}
-
-	l = m;
-	if (!__cmpxchg_double_slab(s, page,
-				old.freelist, old.counters,
-				new.freelist, new.counters,
-				"unfreezing slab"))
-		goto redo;
-
-	if (lock)
 		spin_unlock(&n->list_lock);
-
-	if (m == M_FREE) {
+	} else {
+		VM_BUG_ON(new.inuse);
 		stat(s, DEACTIVATE_EMPTY);
 		discard_slab(s, page);
 		stat(s, FREE_SLAB);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/4] slub: change declare of get_slab() to inline at all times
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
                     ` (2 preceding siblings ...)
  2012-06-08 17:23   ` [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab() Joonsoo Kim
@ 2012-06-08 19:02   ` Christoph Lameter
  2012-06-09 15:57     ` JoonSoo Kim
  3 siblings, 1 reply; 228+ messages in thread
From: Christoph Lameter @ 2012-06-08 19:02 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Sat, 9 Jun 2012, Joonsoo Kim wrote:

> -static struct kmem_cache *get_slab(size_t size, gfp_t flags)
> +static __always_inline struct kmem_cache *get_slab(size_t size, gfp_t flags)

I thought that the compiler felt totally free to inline static functions
at will? This may be a matter of compiler optimization settings. I can
understand the use of always_inline in a header file but why in a .c file?



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab()
  2012-06-08 17:23   ` [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab() Joonsoo Kim
@ 2012-06-08 19:04     ` Christoph Lameter
  2012-06-10 10:27       ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: Christoph Lameter @ 2012-06-08 19:04 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Sat, 9 Jun 2012, Joonsoo Kim wrote:

> Current implementation of deactivate_slab() which deactivate
> freelist of kmem_cache_cpu one by one is inefficient.
> This patch changes it to deactivate freelist all at once.
> But, there is no overall performance benefit,
> because deactivate_slab() is invoked infrequently.

Hmm, deactivate freelist can race with slab_free. Need to look at this in
detail.



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/4] slub: change declare of get_slab() to inline at all times
  2012-06-08 19:02   ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Christoph Lameter
@ 2012-06-09 15:57     ` JoonSoo Kim
  2012-06-11 15:04       ` Christoph Lameter
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-06-09 15:57 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/6/9 Christoph Lameter <cl@linux.com>:
> On Sat, 9 Jun 2012, Joonsoo Kim wrote:
>
>> -static struct kmem_cache *get_slab(size_t size, gfp_t flags)
>> +static __always_inline struct kmem_cache *get_slab(size_t size, gfp_t flags)
>
> I thought that the compiler felt totally free to inline static functions
> at will? This may be a matter of compiler optimization settings. I can
> understand the use of always_inline in a header file but why in a .c file?

Yes, but the compiler with -O2 doesn't inline get_slab() which
declared just 'static'.
I think that inlining get_slab() have a performance benefit, so add
'__always_inline' to declare of get_slab().
Other functions like slab_alloc, slab_free also use 'always_inline' in
.c file (slub.c)

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab()
  2012-06-08 19:04     ` Christoph Lameter
@ 2012-06-10 10:27       ` JoonSoo Kim
  2012-06-22 18:34         ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-06-10 10:27 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/6/9 Christoph Lameter <cl@linux.com>:
> On Sat, 9 Jun 2012, Joonsoo Kim wrote:
>
>> Current implementation of deactivate_slab() which deactivate
>> freelist of kmem_cache_cpu one by one is inefficient.
>> This patch changes it to deactivate freelist all at once.
>> But, there is no overall performance benefit,
>> because deactivate_slab() is invoked infrequently.
>
> Hmm, deactivate freelist can race with slab_free. Need to look at this in
> detail.

Implemented logic is nearly same as previous one.
I just merge first step of previous deactivate_slab() with second one.
In case of failure of cmpxchg_double_slab(), reloading page->freelist,
page->counters and recomputing inuse
ensure that race with slab_free() cannot be possible.
In case that we need a lock, try to get a lock before invoking
cmpxchg_double_slab(),
so race with slab_free cannot be occured too.

Above is my humble opinion, please give me some comments.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/4] slub: change declare of get_slab() to inline at all times
  2012-06-09 15:57     ` JoonSoo Kim
@ 2012-06-11 15:04       ` Christoph Lameter
  0 siblings, 0 replies; 228+ messages in thread
From: Christoph Lameter @ 2012-06-11 15:04 UTC (permalink / raw)
  To: JoonSoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Sun, 10 Jun 2012, JoonSoo Kim wrote:

> 2012/6/9 Christoph Lameter <cl@linux.com>:
> > On Sat, 9 Jun 2012, Joonsoo Kim wrote:
> >
> >> -static struct kmem_cache *get_slab(size_t size, gfp_t flags)
> >> +static __always_inline struct kmem_cache *get_slab(size_t size, gfp_t flags)
> >
> > I thought that the compiler felt totally free to inline static functions
> > at will? This may be a matter of compiler optimization settings. I can
> > understand the use of always_inline in a header file but why in a .c file?
>
> Yes, but the compiler with -O2 doesn't inline get_slab() which
> declared just 'static'.
> I think that inlining get_slab() have a performance benefit, so add
> '__always_inline' to declare of get_slab().
> Other functions like slab_alloc, slab_free also use 'always_inline' in
> .c file (slub.c)

Yea I thought about removing those since I would think that the compiler
should be doing the right thing.

Does gcc inline with higher optimization settings?


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/4] slub: refactoring unfreeze_partials()
  2012-06-08 17:23   ` [PATCH 3/4] slub: refactoring unfreeze_partials() Joonsoo Kim
@ 2012-06-20  7:19     ` Pekka Enberg
  0 siblings, 0 replies; 228+ messages in thread
From: Pekka Enberg @ 2012-06-20  7:19 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Christoph Lameter, linux-kernel, linux-mm, David Rientjes

On Fri, Jun 8, 2012 at 8:23 PM, Joonsoo Kim <js1304@gmail.com> wrote:
> Current implementation of unfreeze_partials() is so complicated,
> but benefit from it is insignificant. In addition many code in
> do {} while loop have a bad influence to a fail rate of cmpxchg_double_slab.
> Under current implementation which test status of cpu partial slab
> and acquire list_lock in do {} while loop,
> we don't need to acquire a list_lock and gain a little benefit
> when front of the cpu partial slab is to be discarded, but this is a rare case.
> In case that add_partial is performed and cmpxchg_double_slab is failed,
> remove_partial should be called case by case.
>
> I think that these are disadvantages of current implementation,
> so I do refactoring unfreeze_partials().
>
> Minimizing code in do {} while loop introduce a reduced fail rate
> of cmpxchg_double_slab. Below is output of 'slabinfo -r kmalloc-256'
> when './perf stat -r 33 hackbench 50 process 4000 > /dev/null' is done.
>
> ** before **
> Cmpxchg_double Looping
> ------------------------
> Locked Cmpxchg Double redos   182685
> Unlocked Cmpxchg Double redos 0
>
> ** after **
> Cmpxchg_double Looping
> ------------------------
> Locked Cmpxchg Double redos   177995
> Unlocked Cmpxchg Double redos 1
>
> We can see cmpxchg_double_slab fail rate is improved slightly.
>
> Bolow is output of './perf stat -r 30 hackbench 50 process 4000 > /dev/null'.
>
> ** before **
>  Performance counter stats for './hackbench 50 process 4000' (30 runs):
>
>     108517.190463 task-clock                #    7.926 CPUs utilized            ( +-  0.24% )
>         2,919,550 context-switches          #    0.027 M/sec                    ( +-  3.07% )
>           100,774 CPU-migrations            #    0.929 K/sec                    ( +-  4.72% )
>           124,201 page-faults               #    0.001 M/sec                    ( +-  0.15% )
>   401,500,234,387 cycles                    #    3.700 GHz                      ( +-  0.24% )
>   <not supported> stalled-cycles-frontend
>   <not supported> stalled-cycles-backend
>   250,576,913,354 instructions              #    0.62  insns per cycle          ( +-  0.13% )
>    45,934,956,860 branches                  #  423.297 M/sec                    ( +-  0.14% )
>       188,219,787 branch-misses             #    0.41% of all branches          ( +-  0.56% )
>
>      13.691837307 seconds time elapsed                                          ( +-  0.24% )
>
> ** after **
>  Performance counter stats for './hackbench 50 process 4000' (30 runs):
>
>     107784.479767 task-clock                #    7.928 CPUs utilized            ( +-  0.22% )
>         2,834,781 context-switches          #    0.026 M/sec                    ( +-  2.33% )
>            93,083 CPU-migrations            #    0.864 K/sec                    ( +-  3.45% )
>           123,967 page-faults               #    0.001 M/sec                    ( +-  0.15% )
>   398,781,421,836 cycles                    #    3.700 GHz                      ( +-  0.22% )
>   <not supported> stalled-cycles-frontend
>   <not supported> stalled-cycles-backend
>   250,189,160,419 instructions              #    0.63  insns per cycle          ( +-  0.09% )
>    45,855,370,128 branches                  #  425.436 M/sec                    ( +-  0.10% )
>       169,881,248 branch-misses             #    0.37% of all branches          ( +-  0.43% )
>
>      13.596272341 seconds time elapsed                                          ( +-  0.22% )
>
> No regression is found, but rather we can see slightly better result.
>
> Acked-by: Christoph Lameter <cl@linux.com>
> Signed-off-by: Joonsoo Kim <js1304@gmail.com>

Applied, thanks!

> diff --git a/mm/slub.c b/mm/slub.c
> index 686ed90..b5f2108 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1886,18 +1886,24 @@ redo:
>  */
>  static void unfreeze_partials(struct kmem_cache *s)
>  {
> -       struct kmem_cache_node *n = NULL;
> +       struct kmem_cache_node *n = NULL, *n2 = NULL;
>        struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab);
>        struct page *page, *discard_page = NULL;
>
>        while ((page = c->partial)) {
> -               enum slab_modes { M_PARTIAL, M_FREE };
> -               enum slab_modes l, m;
>                struct page new;
>                struct page old;
>
>                c->partial = page->next;
> -               l = M_FREE;
> +
> +               n2 = get_node(s, page_to_nid(page));
> +               if (n != n2) {
> +                       if (n)
> +                               spin_unlock(&n->list_lock);
> +
> +                       n = n2;
> +                       spin_lock(&n->list_lock);
> +               }
>
>                do {
>
> @@ -1910,43 +1916,17 @@ static void unfreeze_partials(struct kmem_cache *s)
>
>                        new.frozen = 0;
>
> -                       if (!new.inuse && (!n || n->nr_partial > s->min_partial))
> -                               m = M_FREE;
> -                       else {
> -                               struct kmem_cache_node *n2 = get_node(s,
> -                                                       page_to_nid(page));
> -
> -                               m = M_PARTIAL;
> -                               if (n != n2) {
> -                                       if (n)
> -                                               spin_unlock(&n->list_lock);
> -
> -                                       n = n2;
> -                                       spin_lock(&n->list_lock);
> -                               }
> -                       }
> -
> -                       if (l != m) {
> -                               if (l == M_PARTIAL) {
> -                                       remove_partial(n, page);
> -                                       stat(s, FREE_REMOVE_PARTIAL);
> -                               } else {
> -                                       add_partial(n, page,
> -                                               DEACTIVATE_TO_TAIL);
> -                                       stat(s, FREE_ADD_PARTIAL);
> -                               }
> -
> -                               l = m;
> -                       }
> -
>                } while (!__cmpxchg_double_slab(s, page,
>                                old.freelist, old.counters,
>                                new.freelist, new.counters,
>                                "unfreezing slab"));
>
> -               if (m == M_FREE) {
> +               if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) {
>                        page->next = discard_page;
>                        discard_page = page;
> +               } else {
> +                       add_partial(n, page, DEACTIVATE_TO_TAIL);
> +                       stat(s, FREE_ADD_PARTIAL);
>                }
>        }
>
> --
> 1.7.9.5
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc()
       [not found] <yes>
                   ` (25 preceding siblings ...)
  2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
@ 2012-06-22 18:22 ` Joonsoo Kim
  2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
                     ` (2 more replies)
       [not found] ` <1360258447-27247-1-git-send-email-yes>
                   ` (7 subsequent siblings)
  34 siblings, 3 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-22 18:22 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

Commit 0ad9500e16fe24aa55809a2b00e0d2d0e658fc71 ('slub: prefetch
next freelist pointer in slab_alloc') add prefetch instruction to
fast path of allocation.

Same benefit is also available in slow path of allocation, but it is not
large portion of overall allocation. Nevertheless we could get
some benifit from it, so prefetch next freelist pointer in __slab_alloc.

Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index f96d8bc..92f1c0e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2248,6 +2248,7 @@ load_freelist:
 	VM_BUG_ON(!c->page->frozen);
 	c->freelist = get_freepointer(s, freelist);
 	c->tid = next_tid(c->tid);
+	prefetch_freepointer(s, c->freelist);
 	local_irq_restore(flags);
 	return freelist;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing
  2012-06-22 18:22 ` [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
@ 2012-06-22 18:22   ` Joonsoo Kim
  2012-07-04 13:05     ` Pekka Enberg
  2012-08-16  7:06     ` Pekka Enberg
  2012-06-22 18:22   ` [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free() Joonsoo Kim
  2012-06-22 18:45   ` [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
  2 siblings, 2 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-22 18:22 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

In current implementation, after unfreezing, we doesn't touch oldpage,
so it remain 'NOT NULL'. When we call this_cpu_cmpxchg()
with this old oldpage, this_cpu_cmpxchg() is mostly be failed.

We can change value of oldpage to NULL after unfreezing,
because unfreeze_partial() ensure that all the cpu partial slabs is removed
from cpu partial list. In this time, we could expect that
this_cpu_cmpxchg is mostly succeed.

Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index 92f1c0e..531d8ed 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1968,6 +1968,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 				local_irq_save(flags);
 				unfreeze_partials(s);
 				local_irq_restore(flags);
+				oldpage = NULL;
 				pobjects = 0;
 				pages = 0;
 				stat(s, CPU_PARTIAL_DRAIN);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-06-22 18:22 ` [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
  2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
@ 2012-06-22 18:22   ` Joonsoo Kim
  2012-07-04 13:10     ` Pekka Enberg
  2012-07-05 14:26     ` Christoph Lameter
  2012-06-22 18:45   ` [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
  2 siblings, 2 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-22 18:22 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Joonsoo Kim

In some case of __slab_free(), we need a lock for manipulating partial list.
If freeing object with a lock is failed, a lock doesn't needed anymore
for some reasons.

Case 1. prior is NULL, kmem_cache_debug(s) is true

In this case, another free is occured before our free is succeed.
When slab is full(prior is NULL), only possible operation is slab_free().
So in this case, we guess another free is occured.
It may make a slab frozen, so lock is not needed anymore.

Case 2. inuse is NULL

In this case, acquire_slab() is occured before out free is succeed.
We have a last object for slab, so other operation for this slab is
not possible except acquire_slab().
Acquire_slab() makes a slab frozen, so lock is not needed anymore.

Above two reason explain why we don't need a lock
when freeing object with a lock is failed.

So, when cmpxchg_double_slab() is failed, releasing a lock is more suitable.
This may reduce lock contention.

This also make logic somehow simple that 'was_frozen with a lock' case
is never occured. Remove it.

Signed-off-by: Joonsoo Kim <js1304@gmail.com>

diff --git a/mm/slub.c b/mm/slub.c
index 531d8ed..3e0b9db 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2438,7 +2438,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 	void *prior;
 	void **object = (void *)x;
 	int was_frozen;
-	int inuse;
 	struct page new;
 	unsigned long counters;
 	struct kmem_cache_node *n = NULL;
@@ -2450,13 +2449,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 		return;
 
 	do {
+		if (unlikely(n)) {
+			spin_unlock_irqrestore(&n->list_lock, flags);
+			n = NULL;
+		}
 		prior = page->freelist;
 		counters = page->counters;
 		set_freepointer(s, object, prior);
 		new.counters = counters;
 		was_frozen = new.frozen;
 		new.inuse--;
-		if ((!new.inuse || !prior) && !was_frozen && !n) {
+		if ((!new.inuse || !prior) && !was_frozen) {
 
 			if (!kmem_cache_debug(s) && !prior)
 
@@ -2481,7 +2484,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 
 			}
 		}
-		inuse = new.inuse;
 
 	} while (!cmpxchg_double_slab(s, page,
 		prior, counters,
@@ -2507,25 +2509,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                 return;
         }
 
+	if (unlikely(!new.inuse && n->nr_partial > s->min_partial))
+		goto slab_empty;
+
 	/*
-	 * was_frozen may have been set after we acquired the list_lock in
-	 * an earlier loop. So we need to check it here again.
+	 * Objects left in the slab. If it was not on the partial list before
+	 * then add it.
 	 */
-	if (was_frozen)
-		stat(s, FREE_FROZEN);
-	else {
-		if (unlikely(!inuse && n->nr_partial > s->min_partial))
-                        goto slab_empty;
-
-		/*
-		 * Objects left in the slab. If it was not on the partial list before
-		 * then add it.
-		 */
-		if (unlikely(!prior)) {
-			remove_full(s, page);
-			add_partial(n, page, DEACTIVATE_TO_TAIL);
-			stat(s, FREE_ADD_PARTIAL);
-		}
+	if (kmem_cache_debug(s) && unlikely(!prior)) {
+		remove_full(s, page);
+		add_partial(n, page, DEACTIVATE_TO_TAIL);
+		stat(s, FREE_ADD_PARTIAL);
 	}
 	spin_unlock_irqrestore(&n->list_lock, flags);
 	return;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab()
  2012-06-10 10:27       ` JoonSoo Kim
@ 2012-06-22 18:34         ` JoonSoo Kim
  0 siblings, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-06-22 18:34 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/6/10 JoonSoo Kim <js1304@gmail.com>:
> 2012/6/9 Christoph Lameter <cl@linux.com>:
>> On Sat, 9 Jun 2012, Joonsoo Kim wrote:
>>
>>> Current implementation of deactivate_slab() which deactivate
>>> freelist of kmem_cache_cpu one by one is inefficient.
>>> This patch changes it to deactivate freelist all at once.
>>> But, there is no overall performance benefit,
>>> because deactivate_slab() is invoked infrequently.
>>
>> Hmm, deactivate freelist can race with slab_free. Need to look at this in
>> detail.
>
> Implemented logic is nearly same as previous one.
> I just merge first step of previous deactivate_slab() with second one.
> In case of failure of cmpxchg_double_slab(), reloading page->freelist,
> page->counters and recomputing inuse
> ensure that race with slab_free() cannot be possible.
> In case that we need a lock, try to get a lock before invoking
> cmpxchg_double_slab(),
> so race with slab_free cannot be occured too.
>
> Above is my humble opinion, please give me some comments.

Hi Pekka and Christoph.
Could you give me some comments about this, please?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-06-22 18:22 ` [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
  2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
  2012-06-22 18:22   ` [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free() Joonsoo Kim
@ 2012-06-22 18:45   ` Joonsoo Kim
  2012-07-04 12:58     ` JoonSoo Kim
  2012-07-04 13:00     ` Pekka Enberg
  2 siblings, 2 replies; 228+ messages in thread
From: Joonsoo Kim @ 2012-06-22 18:45 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, Joonsoo Kim

Commit 0ad9500e16fe24aa55809a2b00e0d2d0e658fc71 ('slub: prefetch
next freelist pointer in slab_alloc') add prefetch instruction to
fast path of allocation.

Same benefit is also available in slow path of allocation, but it is not
large portion of overall allocation. Nevertheless we could get
some benifit from it, so prefetch next freelist pointer in __slab_alloc.

Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Joonsoo Kim <js1304@gmail.com>
---
Add 'Cc: Eric Dumazet <eric.dumazet@gmail.com>'

diff --git a/mm/slub.c b/mm/slub.c
index f96d8bc..92f1c0e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2248,6 +2248,7 @@ load_freelist:
 	VM_BUG_ON(!c->page->frozen);
 	c->freelist = get_freepointer(s, freelist);
 	c->tid = next_tid(c->tid);
+	prefetch_freepointer(s, c->freelist);
 	local_irq_restore(flags);
 	return freelist;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-06-22 18:45   ` [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
@ 2012-07-04 12:58     ` JoonSoo Kim
  2012-07-04 13:00     ` Pekka Enberg
  1 sibling, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 12:58 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, Joonsoo Kim

Hi Pekka and Christoph.
Could you give me some comments for these patches?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-06-22 18:45   ` [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
  2012-07-04 12:58     ` JoonSoo Kim
@ 2012-07-04 13:00     ` Pekka Enberg
  2012-07-04 14:30       ` JoonSoo Kim
  1 sibling, 1 reply; 228+ messages in thread
From: Pekka Enberg @ 2012-07-04 13:00 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet

On Fri, Jun 22, 2012 at 9:45 PM, Joonsoo Kim <js1304@gmail.com> wrote:
> Commit 0ad9500e16fe24aa55809a2b00e0d2d0e658fc71 ('slub: prefetch
> next freelist pointer in slab_alloc') add prefetch instruction to
> fast path of allocation.
>
> Same benefit is also available in slow path of allocation, but it is not
> large portion of overall allocation. Nevertheless we could get
> some benifit from it, so prefetch next freelist pointer in __slab_alloc.
>
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Joonsoo Kim <js1304@gmail.com>
> ---
> Add 'Cc: Eric Dumazet <eric.dumazet@gmail.com>'
>
> diff --git a/mm/slub.c b/mm/slub.c
> index f96d8bc..92f1c0e 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2248,6 +2248,7 @@ load_freelist:
>         VM_BUG_ON(!c->page->frozen);
>         c->freelist = get_freepointer(s, freelist);
>         c->tid = next_tid(c->tid);
> +       prefetch_freepointer(s, c->freelist);
>         local_irq_restore(flags);
>         return freelist;

Well, can you show improvement in any benchmark or workload?
Prefetching is not always an obvious win and the reason we merged
Eric's patch was that he was able to show an improvement in hackbench.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing
  2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
@ 2012-07-04 13:05     ` Pekka Enberg
  2012-07-05 14:20       ` Christoph Lameter
  2012-08-16  7:06     ` Pekka Enberg
  1 sibling, 1 reply; 228+ messages in thread
From: Pekka Enberg @ 2012-07-04 13:05 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Christoph Lameter, linux-kernel, linux-mm, David Rientjes

On Fri, Jun 22, 2012 at 9:22 PM, Joonsoo Kim <js1304@gmail.com> wrote:
> In current implementation, after unfreezing, we doesn't touch oldpage,
> so it remain 'NOT NULL'. When we call this_cpu_cmpxchg()
> with this old oldpage, this_cpu_cmpxchg() is mostly be failed.
>
> We can change value of oldpage to NULL after unfreezing,
> because unfreeze_partial() ensure that all the cpu partial slabs is removed
> from cpu partial list. In this time, we could expect that
> this_cpu_cmpxchg is mostly succeed.
>
> Signed-off-by: Joonsoo Kim <js1304@gmail.com>
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 92f1c0e..531d8ed 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1968,6 +1968,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
>                                 local_irq_save(flags);
>                                 unfreeze_partials(s);
>                                 local_irq_restore(flags);
> +                               oldpage = NULL;
>                                 pobjects = 0;
>                                 pages = 0;
>                                 stat(s, CPU_PARTIAL_DRAIN);

Makes sense. Christoph, David?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-06-22 18:22   ` [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free() Joonsoo Kim
@ 2012-07-04 13:10     ` Pekka Enberg
  2012-07-04 14:48       ` JoonSoo Kim
  2012-07-05 14:26     ` Christoph Lameter
  1 sibling, 1 reply; 228+ messages in thread
From: Pekka Enberg @ 2012-07-04 13:10 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Christoph Lameter, linux-kernel, linux-mm, David Rientjes

On Fri, Jun 22, 2012 at 9:22 PM, Joonsoo Kim <js1304@gmail.com> wrote:
> In some case of __slab_free(), we need a lock for manipulating partial list.
> If freeing object with a lock is failed, a lock doesn't needed anymore
> for some reasons.
>
> Case 1. prior is NULL, kmem_cache_debug(s) is true
>
> In this case, another free is occured before our free is succeed.
> When slab is full(prior is NULL), only possible operation is slab_free().
> So in this case, we guess another free is occured.
> It may make a slab frozen, so lock is not needed anymore.
>
> Case 2. inuse is NULL
>
> In this case, acquire_slab() is occured before out free is succeed.
> We have a last object for slab, so other operation for this slab is
> not possible except acquire_slab().
> Acquire_slab() makes a slab frozen, so lock is not needed anymore.
>
> Above two reason explain why we don't need a lock
> when freeing object with a lock is failed.
>
> So, when cmpxchg_double_slab() is failed, releasing a lock is more suitable.
> This may reduce lock contention.
>
> This also make logic somehow simple that 'was_frozen with a lock' case
> is never occured. Remove it.
>
> Signed-off-by: Joonsoo Kim <js1304@gmail.com>
>
> diff --git a/mm/slub.c b/mm/slub.c
> index 531d8ed..3e0b9db 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2438,7 +2438,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>         void *prior;
>         void **object = (void *)x;
>         int was_frozen;
> -       int inuse;
>         struct page new;
>         unsigned long counters;
>         struct kmem_cache_node *n = NULL;
> @@ -2450,13 +2449,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>                 return;
>
>         do {
> +               if (unlikely(n)) {
> +                       spin_unlock_irqrestore(&n->list_lock, flags);
> +                       n = NULL;
> +               }
>                 prior = page->freelist;
>                 counters = page->counters;
>                 set_freepointer(s, object, prior);
>                 new.counters = counters;
>                 was_frozen = new.frozen;
>                 new.inuse--;
> -               if ((!new.inuse || !prior) && !was_frozen && !n) {
> +               if ((!new.inuse || !prior) && !was_frozen) {
>
>                         if (!kmem_cache_debug(s) && !prior)
>
> @@ -2481,7 +2484,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>
>                         }
>                 }
> -               inuse = new.inuse;
>
>         } while (!cmpxchg_double_slab(s, page,
>                 prior, counters,
> @@ -2507,25 +2509,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>                  return;
>          }
>
> +       if (unlikely(!new.inuse && n->nr_partial > s->min_partial))
> +               goto slab_empty;
> +
>         /*
> -        * was_frozen may have been set after we acquired the list_lock in
> -        * an earlier loop. So we need to check it here again.
> +        * Objects left in the slab. If it was not on the partial list before
> +        * then add it.
>          */
> -       if (was_frozen)
> -               stat(s, FREE_FROZEN);
> -       else {
> -               if (unlikely(!inuse && n->nr_partial > s->min_partial))
> -                        goto slab_empty;
> -
> -               /*
> -                * Objects left in the slab. If it was not on the partial list before
> -                * then add it.
> -                */
> -               if (unlikely(!prior)) {
> -                       remove_full(s, page);
> -                       add_partial(n, page, DEACTIVATE_TO_TAIL);
> -                       stat(s, FREE_ADD_PARTIAL);
> -               }
> +       if (kmem_cache_debug(s) && unlikely(!prior)) {
> +               remove_full(s, page);
> +               add_partial(n, page, DEACTIVATE_TO_TAIL);
> +               stat(s, FREE_ADD_PARTIAL);
>         }
>         spin_unlock_irqrestore(&n->list_lock, flags);
>         return;

I'm confused. Does this fix a bug or is it an optimization?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 13:00     ` Pekka Enberg
@ 2012-07-04 14:30       ` JoonSoo Kim
  2012-07-04 15:08         ` Pekka Enberg
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 14:30 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet

2012/7/4 Pekka Enberg <penberg@kernel.org>:
> Well, can you show improvement in any benchmark or workload?
> Prefetching is not always an obvious win and the reason we merged
> Eric's patch was that he was able to show an improvement in hackbench.

I thinks that this patch is perfectly same effect as Eric's patch, so
doesn't include benchmark result.
Eric's patch which add "prefetch instruction" in fastpath works for
second ~ last object of cpu slab.
This patch which add "prefetch instrunction" in slowpath works for
first object of cpu slab.

But, I do test "./perf stat -r 20 ./hackbench 50 process 4000 >
/dev/null" and gain following outputs.

***** vanilla *****

 Performance counter stats for './hackbench 50 process 4000' (20 runs):

     114189.571311 task-clock                #    7.924 CPUs utilized
          ( +-  0.29% )
         2,978,515 context-switches          #    0.026 M/sec
          ( +-  3.45% )
           102,635 CPU-migrations            #    0.899 K/sec
          ( +-  5.63% )
           123,948 page-faults               #    0.001 M/sec
          ( +-  0.16% )
   422,477,120,134 cycles                    #    3.700 GHz
          ( +-  0.29% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   251,943,851,074 instructions              #    0.60  insns per
cycle          ( +-  0.14% )
    46,214,207,979 branches                  #  404.715 M/sec
          ( +-  0.15% )
       215,342,095 branch-misses             #    0.47% of all
branches          ( +-  0.53% )

      14.409990448 seconds time elapsed
          ( +-  0.30% )

 Performance counter stats for './hackbench 50 process 4000' (20 runs):

     114576.053284 task-clock                #    7.921 CPUs utilized
          ( +-  0.35% )
         2,810,138 context-switches          #    0.025 M/sec
          ( +-  3.21% )
            85,641 CPU-migrations            #    0.747 K/sec
          ( +-  5.05% )
           124,299 page-faults               #    0.001 M/sec
          ( +-  0.18% )
   423,906,539,517 cycles                    #    3.700 GHz
          ( +-  0.35% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   251,354,351,283 instructions              #    0.59  insns per
cycle          ( +-  0.13% )
    46,098,601,012 branches                  #  402.341 M/sec
          ( +-  0.13% )
       213,448,657 branch-misses             #    0.46% of all
branches          ( +-  0.50% )

      14.464325969 seconds time elapsed
          ( +-  0.34% )


***** patch applied *****

 Performance counter stats for './hackbench 50 process 4000' (20 runs):

     112935.199731 task-clock                #    7.926 CPUs utilized
          ( +-  0.29% )
         2,810,157 context-switches          #    0.025 M/sec
          ( +-  2.95% )
           104,278 CPU-migrations            #    0.923 K/sec
          ( +-  6.83% )
           123,999 page-faults               #    0.001 M/sec
          ( +-  0.17% )
   417,834,406,420 cycles                    #    3.700 GHz
          ( +-  0.29% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   251,291,523,926 instructions              #    0.60  insns per
cycle          ( +-  0.11% )
    46,083,091,476 branches                  #  408.049 M/sec
          ( +-  0.12% )
       213,714,228 branch-misses             #    0.46% of all
branches          ( +-  0.43% )

      14.248980376 seconds time elapsed
          ( +-  0.29% )

 Performance counter stats for './hackbench 50 process 4000' (20 runs):

     113640.944855 task-clock                #    7.926 CPUs utilized
          ( +-  0.28% )
         2,776,983 context-switches          #    0.024 M/sec
          ( +-  5.66% )
            95,962 CPU-migrations            #    0.844 K/sec
          ( +- 10.69% )
           123,849 page-faults               #    0.001 M/sec
          ( +-  0.15% )
   420,446,572,595 cycles                    #    3.700 GHz
          ( +-  0.28% )
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
   251,174,259,429 instructions              #    0.60  insns per
cycle          ( +-  0.21% )
    46,060,683,039 branches                  #  405.318 M/sec
          ( +-  0.23% )
       213,480,999 branch-misses             #    0.46% of all
branches          ( +-  0.75% )

      14.336843534 seconds time elapsed
          ( +-  0.28% )

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-04 13:10     ` Pekka Enberg
@ 2012-07-04 14:48       ` JoonSoo Kim
  0 siblings, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 14:48 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Christoph Lameter, linux-kernel, linux-mm, David Rientjes

2012/7/4 Pekka Enberg <penberg@kernel.org>:
> On Fri, Jun 22, 2012 at 9:22 PM, Joonsoo Kim <js1304@gmail.com> wrote:
>> In some case of __slab_free(), we need a lock for manipulating partial list.
>> If freeing object with a lock is failed, a lock doesn't needed anymore
>> for some reasons.
>>
>> Case 1. prior is NULL, kmem_cache_debug(s) is true
>>
>> In this case, another free is occured before our free is succeed.
>> When slab is full(prior is NULL), only possible operation is slab_free().
>> So in this case, we guess another free is occured.
>> It may make a slab frozen, so lock is not needed anymore.
>>
>> Case 2. inuse is NULL
>>
>> In this case, acquire_slab() is occured before out free is succeed.
>> We have a last object for slab, so other operation for this slab is
>> not possible except acquire_slab().
>> Acquire_slab() makes a slab frozen, so lock is not needed anymore.
>>
>> Above two reason explain why we don't need a lock
>> when freeing object with a lock is failed.
>>
>> So, when cmpxchg_double_slab() is failed, releasing a lock is more suitable.
>> This may reduce lock contention.
>>
>> This also make logic somehow simple that 'was_frozen with a lock' case
>> is never occured. Remove it.
>>
>> Signed-off-by: Joonsoo Kim <js1304@gmail.com>
>>
>> diff --git a/mm/slub.c b/mm/slub.c
>> index 531d8ed..3e0b9db 100644
>> --- a/mm/slub.c
>> +++ b/mm/slub.c
>> @@ -2438,7 +2438,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>>         void *prior;
>>         void **object = (void *)x;
>>         int was_frozen;
>> -       int inuse;
>>         struct page new;
>>         unsigned long counters;
>>         struct kmem_cache_node *n = NULL;
>> @@ -2450,13 +2449,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>>                 return;
>>
>>         do {
>> +               if (unlikely(n)) {
>> +                       spin_unlock_irqrestore(&n->list_lock, flags);
>> +                       n = NULL;
>> +               }
>>                 prior = page->freelist;
>>                 counters = page->counters;
>>                 set_freepointer(s, object, prior);
>>                 new.counters = counters;
>>                 was_frozen = new.frozen;
>>                 new.inuse--;
>> -               if ((!new.inuse || !prior) && !was_frozen && !n) {
>> +               if ((!new.inuse || !prior) && !was_frozen) {
>>
>>                         if (!kmem_cache_debug(s) && !prior)
>>
>> @@ -2481,7 +2484,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>>
>>                         }
>>                 }
>> -               inuse = new.inuse;
>>
>>         } while (!cmpxchg_double_slab(s, page,
>>                 prior, counters,
>> @@ -2507,25 +2509,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
>>                  return;
>>          }
>>
>> +       if (unlikely(!new.inuse && n->nr_partial > s->min_partial))
>> +               goto slab_empty;
>> +
>>         /*
>> -        * was_frozen may have been set after we acquired the list_lock in
>> -        * an earlier loop. So we need to check it here again.
>> +        * Objects left in the slab. If it was not on the partial list before
>> +        * then add it.
>>          */
>> -       if (was_frozen)
>> -               stat(s, FREE_FROZEN);
>> -       else {
>> -               if (unlikely(!inuse && n->nr_partial > s->min_partial))
>> -                        goto slab_empty;
>> -
>> -               /*
>> -                * Objects left in the slab. If it was not on the partial list before
>> -                * then add it.
>> -                */
>> -               if (unlikely(!prior)) {
>> -                       remove_full(s, page);
>> -                       add_partial(n, page, DEACTIVATE_TO_TAIL);
>> -                       stat(s, FREE_ADD_PARTIAL);
>> -               }
>> +       if (kmem_cache_debug(s) && unlikely(!prior)) {
>> +               remove_full(s, page);
>> +               add_partial(n, page, DEACTIVATE_TO_TAIL);
>> +               stat(s, FREE_ADD_PARTIAL);
>>         }
>>         spin_unlock_irqrestore(&n->list_lock, flags);
>>         return;
>
> I'm confused. Does this fix a bug or is it an optimization?

It is for reducing lock contention and code clean-up.

If we aquire a lock and cmpxchg_double failed, we do releasing a lock.
This result in reducing lock contention.
And this remove "was_frozen and having a lock" case, so logic slightly
simpler than before.

Commit message which confuse u means that this patch do not decrease
performance for two reasons.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 14:30       ` JoonSoo Kim
@ 2012-07-04 15:08         ` Pekka Enberg
  2012-07-04 15:26           ` Eric Dumazet
  2012-07-04 15:45           ` JoonSoo Kim
  0 siblings, 2 replies; 228+ messages in thread
From: Pekka Enberg @ 2012-07-04 15:08 UTC (permalink / raw)
  To: JoonSoo Kim
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, David Rientjes

> 2012/7/4 Pekka Enberg <penberg@kernel.org>:
>> Well, can you show improvement in any benchmark or workload?
>> Prefetching is not always an obvious win and the reason we merged
>> Eric's patch was that he was able to show an improvement in hackbench.

On Wed, Jul 4, 2012 at 5:30 PM, JoonSoo Kim <js1304@gmail.com> wrote:
> I thinks that this patch is perfectly same effect as Eric's patch, so
> doesn't include benchmark result.
> Eric's patch which add "prefetch instruction" in fastpath works for
> second ~ last object of cpu slab.
> This patch which add "prefetch instrunction" in slowpath works for
> first object of cpu slab.

Prefetching can also have negative effect on overall performance:

http://lwn.net/Articles/444336/

> But, I do test "./perf stat -r 20 ./hackbench 50 process 4000 >
> /dev/null" and gain following outputs.
>
> ***** vanilla *****
>
>  Performance counter stats for './hackbench 50 process 4000' (20 runs):
>
>      114189.571311 task-clock                #    7.924 CPUs utilized
>           ( +-  0.29% )
>          2,978,515 context-switches          #    0.026 M/sec
>           ( +-  3.45% )
>            102,635 CPU-migrations            #    0.899 K/sec
>           ( +-  5.63% )
>            123,948 page-faults               #    0.001 M/sec
>           ( +-  0.16% )
>    422,477,120,134 cycles                    #    3.700 GHz
>           ( +-  0.29% )
>    <not supported> stalled-cycles-frontend
>    <not supported> stalled-cycles-backend
>    251,943,851,074 instructions              #    0.60  insns per
> cycle          ( +-  0.14% )
>     46,214,207,979 branches                  #  404.715 M/sec
>           ( +-  0.15% )
>        215,342,095 branch-misses             #    0.47% of all
> branches          ( +-  0.53% )
>
>       14.409990448 seconds time elapsed
>           ( +-  0.30% )
>
>  Performance counter stats for './hackbench 50 process 4000' (20 runs):
>
>      114576.053284 task-clock                #    7.921 CPUs utilized
>           ( +-  0.35% )
>          2,810,138 context-switches          #    0.025 M/sec
>           ( +-  3.21% )
>             85,641 CPU-migrations            #    0.747 K/sec
>           ( +-  5.05% )
>            124,299 page-faults               #    0.001 M/sec
>           ( +-  0.18% )
>    423,906,539,517 cycles                    #    3.700 GHz
>           ( +-  0.35% )
>    <not supported> stalled-cycles-frontend
>    <not supported> stalled-cycles-backend
>    251,354,351,283 instructions              #    0.59  insns per
> cycle          ( +-  0.13% )
>     46,098,601,012 branches                  #  402.341 M/sec
>           ( +-  0.13% )
>        213,448,657 branch-misses             #    0.46% of all
> branches          ( +-  0.50% )
>
>       14.464325969 seconds time elapsed
>           ( +-  0.34% )
>
>
> ***** patch applied *****
>
>  Performance counter stats for './hackbench 50 process 4000' (20 runs):
>
>      112935.199731 task-clock                #    7.926 CPUs utilized
>           ( +-  0.29% )
>          2,810,157 context-switches          #    0.025 M/sec
>           ( +-  2.95% )
>            104,278 CPU-migrations            #    0.923 K/sec
>           ( +-  6.83% )
>            123,999 page-faults               #    0.001 M/sec
>           ( +-  0.17% )
>    417,834,406,420 cycles                    #    3.700 GHz
>           ( +-  0.29% )
>    <not supported> stalled-cycles-frontend
>    <not supported> stalled-cycles-backend
>    251,291,523,926 instructions              #    0.60  insns per
> cycle          ( +-  0.11% )
>     46,083,091,476 branches                  #  408.049 M/sec
>           ( +-  0.12% )
>        213,714,228 branch-misses             #    0.46% of all
> branches          ( +-  0.43% )
>
>       14.248980376 seconds time elapsed
>           ( +-  0.29% )
>
>  Performance counter stats for './hackbench 50 process 4000' (20 runs):
>
>      113640.944855 task-clock                #    7.926 CPUs utilized
>           ( +-  0.28% )
>          2,776,983 context-switches          #    0.024 M/sec
>           ( +-  5.66% )
>             95,962 CPU-migrations            #    0.844 K/sec
>           ( +- 10.69% )
>            123,849 page-faults               #    0.001 M/sec
>           ( +-  0.15% )
>    420,446,572,595 cycles                    #    3.700 GHz
>           ( +-  0.28% )
>    <not supported> stalled-cycles-frontend
>    <not supported> stalled-cycles-backend
>    251,174,259,429 instructions              #    0.60  insns per
> cycle          ( +-  0.21% )
>     46,060,683,039 branches                  #  405.318 M/sec
>           ( +-  0.23% )
>        213,480,999 branch-misses             #    0.46% of all
> branches          ( +-  0.75% )
>
>       14.336843534 seconds time elapsed
>           ( +-  0.28% )

That doesn't seem like that obvious win to me... Eric, Christoph?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:08         ` Pekka Enberg
@ 2012-07-04 15:26           ` Eric Dumazet
  2012-07-04 15:48             ` JoonSoo Kim
  2012-07-04 15:45           ` JoonSoo Kim
  1 sibling, 1 reply; 228+ messages in thread
From: Eric Dumazet @ 2012-07-04 15:26 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: JoonSoo Kim, Christoph Lameter, linux-kernel, linux-mm, David Rientjes

On Wed, 2012-07-04 at 18:08 +0300, Pekka Enberg wrote:

> That doesn't seem like that obvious win to me... Eric, Christoph?

Its the slow path. I am not convinced its useful on real workloads (not
a benchmark)

I mean, if a workload hits badly slow path, some more important work
should be done to avoid this at a higher level.



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:08         ` Pekka Enberg
  2012-07-04 15:26           ` Eric Dumazet
@ 2012-07-04 15:45           ` JoonSoo Kim
  2012-07-04 15:59             ` Pekka Enberg
  1 sibling, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 15:45 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, David Rientjes

2012/7/5 Pekka Enberg <penberg@kernel.org>:
>> 2012/7/4 Pekka Enberg <penberg@kernel.org>:
>>> Well, can you show improvement in any benchmark or workload?
>>> Prefetching is not always an obvious win and the reason we merged
>>> Eric's patch was that he was able to show an improvement in hackbench.
>
> On Wed, Jul 4, 2012 at 5:30 PM, JoonSoo Kim <js1304@gmail.com> wrote:
>> I thinks that this patch is perfectly same effect as Eric's patch, so
>> doesn't include benchmark result.
>> Eric's patch which add "prefetch instruction" in fastpath works for
>> second ~ last object of cpu slab.
>> This patch which add "prefetch instrunction" in slowpath works for
>> first object of cpu slab.
>
> Prefetching can also have negative effect on overall performance:
>
> http://lwn.net/Articles/444336/
>

Thanks for good article which is very helpful to me.

> That doesn't seem like that obvious win to me... Eric, Christoph?

Could you tell me how I test this patch more deeply, plz?
I am a kernel newbie and in the process of learning.
I doesn't know what I can do more for this.
I googling previous patch related to slub, some people use netperf.

Just do below is sufficient?
How is this test related to slub?

for in in `seq 1 32`
do
 netperf -H 192.168.0.8 -v 0 -l -100000 -t TCP_RR > /dev/null &
done
wait

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:26           ` Eric Dumazet
@ 2012-07-04 15:48             ` JoonSoo Kim
  2012-07-04 16:15               ` Eric Dumazet
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 15:48 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Pekka Enberg, Christoph Lameter, linux-kernel, linux-mm, David Rientjes

2012/7/5 Eric Dumazet <eric.dumazet@gmail.com>:
> Its the slow path. I am not convinced its useful on real workloads (not
> a benchmark)
>
> I mean, if a workload hits badly slow path, some more important work
> should be done to avoid this at a higher level.
>

In hackbench test, fast path allocation is about to 93%.
Is it insufficient?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:45           ` JoonSoo Kim
@ 2012-07-04 15:59             ` Pekka Enberg
  2012-07-04 16:04               ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: Pekka Enberg @ 2012-07-04 15:59 UTC (permalink / raw)
  To: JoonSoo Kim
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, David Rientjes

On Wed, Jul 4, 2012 at 6:45 PM, JoonSoo Kim <js1304@gmail.com> wrote:
>> Prefetching can also have negative effect on overall performance:
>>
>> http://lwn.net/Articles/444336/
>
> Thanks for good article which is very helpful to me.
>
>> That doesn't seem like that obvious win to me... Eric, Christoph?
>
> Could you tell me how I test this patch more deeply, plz?
> I am a kernel newbie and in the process of learning.
> I doesn't know what I can do more for this.
> I googling previous patch related to slub, some people use netperf.
>
> Just do below is sufficient?
> How is this test related to slub?
>
> for in in `seq 1 32`
> do
>  netperf -H 192.168.0.8 -v 0 -l -100000 -t TCP_RR > /dev/null &
> done
> wait

The networking subsystem is sensitive to slab allocator performance
which makes netperf an interesting benchmark, that's all.

As for slab benchmarking, you might want to look at what Mel Gorman
has done in the past:

https://lkml.org/lkml/2009/2/16/252

For something like prefetch optimization, you'd really want to see a
noticeable win in some benchmark. The kind of improvement you're
seeing with your patch is likely to be lost in the noise - or even
worse, cause negative performance for real world workloads.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:59             ` Pekka Enberg
@ 2012-07-04 16:04               ` JoonSoo Kim
  0 siblings, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 16:04 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Christoph Lameter, linux-kernel, linux-mm, Eric Dumazet, David Rientjes

2012/7/5 Pekka Enberg <penberg@kernel.org>:
> On Wed, Jul 4, 2012 at 6:45 PM, JoonSoo Kim <js1304@gmail.com> wrote:
>>> Prefetching can also have negative effect on overall performance:
>>>
>>> http://lwn.net/Articles/444336/
>>
>> Thanks for good article which is very helpful to me.
>>
>>> That doesn't seem like that obvious win to me... Eric, Christoph?
>>
>> Could you tell me how I test this patch more deeply, plz?
>> I am a kernel newbie and in the process of learning.
>> I doesn't know what I can do more for this.
>> I googling previous patch related to slub, some people use netperf.
>>
>> Just do below is sufficient?
>> How is this test related to slub?
>>
>> for in in `seq 1 32`
>> do
>>  netperf -H 192.168.0.8 -v 0 -l -100000 -t TCP_RR > /dev/null &
>> done
>> wait
>
> The networking subsystem is sensitive to slab allocator performance
> which makes netperf an interesting benchmark, that's all.
>
> As for slab benchmarking, you might want to look at what Mel Gorman
> has done in the past:
>
> https://lkml.org/lkml/2009/2/16/252
>
> For something like prefetch optimization, you'd really want to see a
> noticeable win in some benchmark. The kind of improvement you're
> seeing with your patch is likely to be lost in the noise - or even
> worse, cause negative performance for real world workloads.

Okay.
Thanks for comments.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 15:48             ` JoonSoo Kim
@ 2012-07-04 16:15               ` Eric Dumazet
  2012-07-04 16:24                 ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: Eric Dumazet @ 2012-07-04 16:15 UTC (permalink / raw)
  To: JoonSoo Kim
  Cc: Pekka Enberg, Christoph Lameter, linux-kernel, linux-mm, David Rientjes

On Thu, 2012-07-05 at 00:48 +0900, JoonSoo Kim wrote:
> 2012/7/5 Eric Dumazet <eric.dumazet@gmail.com>:
> > Its the slow path. I am not convinced its useful on real workloads (not
> > a benchmark)
> >
> > I mean, if a workload hits badly slow path, some more important work
> > should be done to avoid this at a higher level.
> >
> 
> In hackbench test, fast path allocation is about to 93%.
> Is it insufficient?

7% is insufficient I am afraid.

One prefetch() in the fast path serves 93% of the allocations,
so added icache pressure is ok.

One prefetch() in slow path serves 7% of the allocations, do you see the
difference ?

Adding a prefetch() is usually a win when a benchmark uses the path one
million times per second.

But adding prefetches also increases kernel size and it hurts globally.
(Latency of the kernel depends on its size, when cpu caches are cold)




^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc()
  2012-07-04 16:15               ` Eric Dumazet
@ 2012-07-04 16:24                 ` JoonSoo Kim
  0 siblings, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-04 16:24 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Pekka Enberg, Christoph Lameter, linux-kernel, linux-mm, David Rientjes

2012/7/5 Eric Dumazet <eric.dumazet@gmail.com>:
> On Thu, 2012-07-05 at 00:48 +0900, JoonSoo Kim wrote:
>> 2012/7/5 Eric Dumazet <eric.dumazet@gmail.com>:
>> > Its the slow path. I am not convinced its useful on real workloads (not
>> > a benchmark)
>> >
>> > I mean, if a workload hits badly slow path, some more important work
>> > should be done to avoid this at a higher level.
>> >
>>
>> In hackbench test, fast path allocation is about to 93%.
>> Is it insufficient?
>
> 7% is insufficient I am afraid.
>
> One prefetch() in the fast path serves 93% of the allocations,
> so added icache pressure is ok.
>
> One prefetch() in slow path serves 7% of the allocations, do you see the
> difference ?
>
> Adding a prefetch() is usually a win when a benchmark uses the path one
> million times per second.
>
> But adding prefetches also increases kernel size and it hurts globally.
> (Latency of the kernel depends on its size, when cpu caches are cold)
>

Okay.
Thanks for comments which is very helpful to me.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing
  2012-07-04 13:05     ` Pekka Enberg
@ 2012-07-05 14:20       ` Christoph Lameter
  0 siblings, 0 replies; 228+ messages in thread
From: Christoph Lameter @ 2012-07-05 14:20 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: Joonsoo Kim, linux-kernel, linux-mm, David Rientjes

On Wed, 4 Jul 2012, Pekka Enberg wrote:

> On Fri, Jun 22, 2012 at 9:22 PM, Joonsoo Kim <js1304@gmail.com> wrote:
> > In current implementation, after unfreezing, we doesn't touch oldpage,
> > so it remain 'NOT NULL'. When we call this_cpu_cmpxchg()
> > with this old oldpage, this_cpu_cmpxchg() is mostly be failed.
> >
> > We can change value of oldpage to NULL after unfreezing,
> > because unfreeze_partial() ensure that all the cpu partial slabs is removed
> > from cpu partial list. In this time, we could expect that
> > this_cpu_cmpxchg is mostly succeed.
> >
> > Signed-off-by: Joonsoo Kim <js1304@gmail.com>
> >
> > diff --git a/mm/slub.c b/mm/slub.c
> > index 92f1c0e..531d8ed 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -1968,6 +1968,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
> >                                 local_irq_save(flags);
> >                                 unfreeze_partials(s);
> >                                 local_irq_restore(flags);
> > +                               oldpage = NULL;
> >                                 pobjects = 0;
> >                                 pages = 0;
> >                                 stat(s, CPU_PARTIAL_DRAIN);
>
> Makes sense. Christoph, David?

Acked-by: Christoph Lameter <cl@linux.com>


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-06-22 18:22   ` [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free() Joonsoo Kim
  2012-07-04 13:10     ` Pekka Enberg
@ 2012-07-05 14:26     ` Christoph Lameter
  2012-07-06 14:19       ` JoonSoo Kim
  1 sibling, 1 reply; 228+ messages in thread
From: Christoph Lameter @ 2012-07-05 14:26 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Sat, 23 Jun 2012, Joonsoo Kim wrote:

> In some case of __slab_free(), we need a lock for manipulating partial list.
> If freeing object with a lock is failed, a lock doesn't needed anymore
> for some reasons.
>
> Case 1. prior is NULL, kmem_cache_debug(s) is true
>
> In this case, another free is occured before our free is succeed.
> When slab is full(prior is NULL), only possible operation is slab_free().
> So in this case, we guess another free is occured.
> It may make a slab frozen, so lock is not needed anymore.

A free cannot freeze the slab without taking the lock. The taken lock
makes sure that the thread that first enters slab_free() will be able to
hold back the thread that wants to freeze the slab.

> Case 2. inuse is NULL
>
> In this case, acquire_slab() is occured before out free is succeed.
> We have a last object for slab, so other operation for this slab is
> not possible except acquire_slab().
> Acquire_slab() makes a slab frozen, so lock is not needed anymore.

acquire_slab() also requires lock acquisition and would be held of by
slab_free holding the lock.

> This also make logic somehow simple that 'was_frozen with a lock' case
> is never occured. Remove it.

That is actually interesting and would be a good optimization.


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-05 14:26     ` Christoph Lameter
@ 2012-07-06 14:19       ` JoonSoo Kim
  2012-07-06 14:34         ` Christoph Lameter
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-06 14:19 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/7/5 Christoph Lameter <cl@linux.com>:
> On Sat, 23 Jun 2012, Joonsoo Kim wrote:
>
>> In some case of __slab_free(), we need a lock for manipulating partial list.
>> If freeing object with a lock is failed, a lock doesn't needed anymore
>> for some reasons.
>>
>> Case 1. prior is NULL, kmem_cache_debug(s) is true
>>
>> In this case, another free is occured before our free is succeed.
>> When slab is full(prior is NULL), only possible operation is slab_free().
>> So in this case, we guess another free is occured.
>> It may make a slab frozen, so lock is not needed anymore.
>
> A free cannot freeze the slab without taking the lock. The taken lock
> makes sure that the thread that first enters slab_free() will be able to
> hold back the thread that wants to freeze the slab.

I don't mean we can freeze the slab without taking the lock.
We can fail cmpxchg_double_slab with taking the lock.
And in this case, we don't need lock anymore, so let's release lock.

For example,
When we try to free object A at cpu 1, another process try to free
object B at cpu 2 at the same time.
object A, B is in same slab, and this slab is in full list.

CPU 1                           CPU 2
prior = page->freelist;    prior = page->freelist
....                                  ...
new.inuse--;                   new.inuse--;
taking lock                      try to take the lock, but failed, so
spinning...
free success                   spinning...
add_partial
release lock                    taking lock
                                       fail cmpxchg_double_slab
                                       retry
                                       currently, we don't need lock

At CPU2, we don't need lock anymore, because this slab already in partial list.

Case 2 is similar as case 1.
So skip explain.

Case 1, 2 in commit message explain almost retry case with taking lock.
So, below is reasonable.

@@ -2450,13 +2449,17 @@ static void __slab_free(struct kmem_cache *s,
struct page *page,
                return;

        do {
+               if (unlikely(n)) {
+                       spin_unlock_irqrestore(&n->list_lock, flags);
+                       n = NULL;
+               }
                prior = page->freelist;
                counters = page->counters;
                set_freepointer(s, object, prior);


>> Case 2. inuse is NULL
>>
>> In this case, acquire_slab() is occured before out free is succeed.
>> We have a last object for slab, so other operation for this slab is
>> not possible except acquire_slab().
>> Acquire_slab() makes a slab frozen, so lock is not needed anymore.
>
> acquire_slab() also requires lock acquisition and would be held of by
> slab_free holding the lock.

See above explain.

>> This also make logic somehow simple that 'was_frozen with a lock' case
>> is never occured. Remove it.
>
> That is actually interesting and would be a good optimization.
>

So, I think patch is valid.
Thanks for comments.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-06 14:19       ` JoonSoo Kim
@ 2012-07-06 14:34         ` Christoph Lameter
  2012-07-06 14:59           ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: Christoph Lameter @ 2012-07-06 14:34 UTC (permalink / raw)
  To: JoonSoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Fri, 6 Jul 2012, JoonSoo Kim wrote:

> For example,
> When we try to free object A at cpu 1, another process try to free
> object B at cpu 2 at the same time.
> object A, B is in same slab, and this slab is in full list.
>
> CPU 1                           CPU 2
> prior = page->freelist;    prior = page->freelist
> ....                                  ...
> new.inuse--;                   new.inuse--;
> taking lock                      try to take the lock, but failed, so
> spinning...
> free success                   spinning...
> add_partial
> release lock                    taking lock
>                                        fail cmpxchg_double_slab
>                                        retry
>                                        currently, we don't need lock
>
> At CPU2, we don't need lock anymore, because this slab already in partial list.

For that scenario we could also simply do a trylock there and redo
the loop if we fail. But still what guarantees that another process will
not modify the page struct between fetching the data and a successful
trylock?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-06 14:34         ` Christoph Lameter
@ 2012-07-06 14:59           ` JoonSoo Kim
  2012-07-06 15:10             ` Christoph Lameter
  0 siblings, 1 reply; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-06 14:59 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/7/6 Christoph Lameter <cl@linux.com>:
> On Fri, 6 Jul 2012, JoonSoo Kim wrote:
>
>> For example,
>> When we try to free object A at cpu 1, another process try to free
>> object B at cpu 2 at the same time.
>> object A, B is in same slab, and this slab is in full list.
>>
>> CPU 1                           CPU 2
>> prior = page->freelist;    prior = page->freelist
>> ....                                  ...
>> new.inuse--;                   new.inuse--;
>> taking lock                      try to take the lock, but failed, so
>> spinning...
>> free success                   spinning...
>> add_partial
>> release lock                    taking lock
>>                                        fail cmpxchg_double_slab
>>                                        retry
>>                                        currently, we don't need lock
>>
>> At CPU2, we don't need lock anymore, because this slab already in partial list.
>
> For that scenario we could also simply do a trylock there and redo
> the loop if we fail. But still what guarantees that another process will
> not modify the page struct between fetching the data and a successful
> trylock?


I'm not familiar with English, so take my ability to understand into
consideration.

we don't need guarantees that another process will not modify
the page struct between fetching the data and a successful trylock.

As I understand, do u ask below scenario?

CPU A               CPU B
lock
cmpxchg fail
retry
unlock
...                       modify page strcut
...
cmpxchg~~

In this case, cmpxchg will fail and just redo the loop.
If we need the lock again during redo, re-take the lock.
But I think this is not common case.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-06 14:59           ` JoonSoo Kim
@ 2012-07-06 15:10             ` Christoph Lameter
  2012-07-08 16:19               ` JoonSoo Kim
  0 siblings, 1 reply; 228+ messages in thread
From: Christoph Lameter @ 2012-07-06 15:10 UTC (permalink / raw)
  To: JoonSoo Kim; +Cc: Pekka Enberg, linux-kernel, linux-mm

On Fri, 6 Jul 2012, JoonSoo Kim wrote:

> >> At CPU2, we don't need lock anymore, because this slab already in partial list.
> >
> > For that scenario we could also simply do a trylock there and redo
> > the loop if we fail. But still what guarantees that another process will
> > not modify the page struct between fetching the data and a successful
> > trylock?
>
>
> I'm not familiar with English, so take my ability to understand into
> consideration.

I have a hard time understanding what you want to accomplish here.

> we don't need guarantees that another process will not modify
> the page struct between fetching the data and a successful trylock.

No we do not need that since the cmpxchg will then fail.

Maybe it would be useful to split this patch into two?

One where you introduce the dropping of the lock and the other where you
get rid of certain code paths?


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free()
  2012-07-06 15:10             ` Christoph Lameter
@ 2012-07-08 16:19               ` JoonSoo Kim
  0 siblings, 0 replies; 228+ messages in thread
From: JoonSoo Kim @ 2012-07-08 16:19 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Pekka Enberg, linux-kernel, linux-mm

2012/7/7 Christoph Lameter <cl@linux.com>:
> On Fri, 6 Jul 2012, JoonSoo Kim wrote:
>
>> >> At CPU2, we don't need lock anymore, because this slab already in partial list.
>> >
>> > For that scenario we could also simply do a trylock there and redo
>> > the loop if we fail. But still what guarantees that another process will
>> > not modify the page struct between fetching the data and a successful
>> > trylock?
>>
>>
>> I'm not familiar with English, so take my ability to understand into
>> consideration.
>
> I have a hard time understanding what you want to accomplish here.
>
>> we don't need guarantees that another process will not modify
>> the page struct between fetching the data and a successful trylock.
>
> No we do not need that since the cmpxchg will then fail.
>
> Maybe it would be useful to split this patch into two?
>
> One where you introduce the dropping of the lock and the other where you
> get rid of certain code paths?
>

Dropping of the lock is need for getting rid of certain code paths.
So, I can't split this patch into two.

Sorry for confusing all the people.
I think that I don't explain my purpose well.
I will prepare new version in which I explain purpose of patch better.

Thanks for kind review.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing
  2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
  2012-07-04 13:05     ` Pekka Enberg
@ 2012-08-16  7:06     ` Pekka Enberg
  1 sibling, 0 replies; 228+ messages in thread
From: Pekka Enberg @ 2012-08-16  7:06 UTC (permalink / raw)
  To: Joonsoo Kim; +Cc: Christoph Lameter, linux-kernel, linux-mm

On Sat, 23 Jun 2012, Joonsoo Kim wrote:
> In current implementation, after unfreezing, we doesn't touch oldpage,
> so it remain 'NOT NULL'. When we call this_cpu_cmpxchg()
> with this old oldpage, this_cpu_cmpxchg() is mostly be failed.
> 
> We can change value of oldpage to NULL after unfreezing,
> because unfreeze_partial() ensure that all the cpu partial slabs is removed
> from cpu partial list. In this time, we could expect that
> this_cpu_cmpxchg is mostly succeed.
> 
> Signed-off-by: Joonsoo Kim <js1304@gmail.com>
> 
> diff --git a/mm/slub.c b/mm/slub.c
> index 92f1c0e..531d8ed 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1968,6 +1968,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
>  				local_irq_save(flags);
>  				unfreeze_partials(s);
>  				local_irq_restore(flags);
> +				oldpage = NULL;
>  				pobjects = 0;
>  				pages = 0;
>  				stat(s, CPU_PARTIAL_DRAIN);

Applied, thanks!

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
@ 2013-02-07 17:34   ` manjunath.goudar
  2013-02-07 19:41     ` Arnd Bergmann
  2013-02-08 10:38     ` Florian Fainelli
  2013-02-07 17:34   ` [PATCH 05/10] USB: EHCI: make ehci-atmel " manjunath.goudar
                     ` (4 subsequent siblings)
  5 siblings, 2 replies; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, Jason Cooper, Andrew Lunn, Russell King, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the Marvell Orion host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig      |    7 +++
 drivers/usb/host/Makefile     |    1 +
 drivers/usb/host/ehci-hcd.c   |   27 +++++-------
 drivers/usb/host/ehci-orion.c |   98 +++++++++++++++++++++--------------------
 4 files changed, 69 insertions(+), 64 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 4413075..3689b7b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -169,6 +169,13 @@ config USB_EHCI_HCD_SPEAR
         ---help---
           Enables support for the on-chip EHCI controller on
           ST spear chips.
+config USB_EHCI_HCD_ORION
+        tristate  "Support for Marvell Orion on-chip EHCI USB controller"
+        depends on USB_EHCI_HCD && PLAT_ORION
+        default y
+        ---help---
+          Enables support for the on-chip EHCI controller on
+          Morvell Orion chips.
 
 config USB_EHCI_MSM
 	bool "Support for MSM on-chip EHCI USB controller"
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index c97f4ab..23b07dd 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
 obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
 obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
 obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
+obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 68cea63..5a19a57 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
  * before driver shutdown. But it also seems to be caused by bugs in cardbus
  * bridge shutdown:  shutting down the bridge before the devices using it.
  */
-static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
 		      u32 mask, u32 done, int usec)
 {
 	u32	result;
@@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
 	} while (usec > 0);
 	return -ETIMEDOUT;
 }
-
+EXPORT_SYMBOL_GPL(handshake);
 /* check TDI/ARC silicon is in host mode */
-static int tdi_in_host_mode (struct ehci_hcd *ehci)
+static int tdi_in_host_mode(struct ehci_hcd *ehci)
 {
 	u32		tmp;
 
@@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
  * Force HC to halt state from unknown (EHCI spec section 2.3).
  * Must be called with interrupts enabled and the lock not held.
  */
-static int ehci_halt (struct ehci_hcd *ehci)
+int ehci_halt(struct ehci_hcd *ehci)
 {
 	u32	temp;
 
@@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
 	return handshake(ehci, &ehci->regs->status,
 			  STS_HALT, STS_HALT, 16 * 125);
 }
-
+EXPORT_SYMBOL_GPL(ehci_halt);
 /* put TDI/ARC silicon into EHCI mode */
-static void tdi_reset (struct ehci_hcd *ehci)
+void tdi_reset(struct ehci_hcd *ehci)
 {
 	u32		tmp;
 
@@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
 		tmp |= USBMODE_BE;
 	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
 }
-
+EXPORT_SYMBOL_GPL(tdi_reset);
 /*
  * Reset a non-running (STS_HALT == 1) controller.
  * Must be called with interrupts enabled and the lock not held.
  */
-static int ehci_reset (struct ehci_hcd *ehci)
+int ehci_reset(struct ehci_hcd *ehci)
 {
 	int	retval;
 	u32	command = ehci_readl(ehci, &ehci->regs->command);
@@ -272,7 +272,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
 			ehci->resuming_ports = 0;
 	return retval;
 }
-
+EXPORT_SYMBOL_GPL(ehci_reset);
 /*
  * Idle the controller (turn off the schedules).
  * Must be called with interrupts enabled and the lock not held.
@@ -352,7 +352,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
  * This forcibly disables dma and IRQs, helping kexec and other cases
  * where the next system software may expect clean state.
  */
-static void ehci_shutdown(struct usb_hcd *hcd)
+void ehci_shutdown(struct usb_hcd *hcd)
 {
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
 
@@ -366,7 +366,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 
 	hrtimer_cancel(&ehci->hrtimer);
 }
-
+EXPORT_SYMBOL_GPL(ehci_shutdown);
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1267,11 +1267,6 @@ MODULE_LICENSE ("GPL");
 #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver
 #endif
 
-#ifdef CONFIG_PLAT_ORION
-#include "ehci-orion.c"
-#define	PLATFORM_DRIVER		ehci_orion_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 914a3ec..de4dde2 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -8,6 +8,17 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+
+#include <linux/slab.h>
+#include <linux/usb/ulpi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
+
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -17,6 +28,9 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/dma-mapping.h>
+#include "ehci.h"
+
 
 #define rdl(off)	__raw_readl(hcd->regs + (off))
 #define wrl(off, val)	__raw_writel((val), hcd->regs + (off))
@@ -34,6 +48,17 @@
 #define USB_PHY_IVREF_CTRL	0x440
 #define USB_PHY_TST_GRP_CTRL	0x450
 
+#define DRIVER_DESC "EHCI orion driver"
+
+static const char hcd_name[] = "ehci-orion";
+
+static struct hc_driver __read_mostly ehci_orion_hc_driver;
+
+static const struct ehci_driver_overrides orion_overrides __initdata = {
+	.reset = ehci_setup,
+};
+
+
 /*
  * Implement Orion USB controller specification guidelines
  */
@@ -104,51 +129,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
 	wrl(USB_MODE, 0x13);
 }
 
-static const struct hc_driver ehci_orion_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Marvell Orion EHCI",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = ehci_setup,
-	.start = ehci_run,
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-	.relinquish_port = ehci_relinquish_port,
-	.port_handed_over = ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
 static void
 ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
 			     const struct mbus_dram_target_info *dram)
@@ -323,8 +303,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
-MODULE_ALIAS("platform:orion-ehci");
-
 static const struct of_device_id ehci_orion_dt_ids[] = {
 	{ .compatible = "marvell,orion-ehci", },
 	{},
@@ -336,8 +314,32 @@ static struct platform_driver ehci_orion_driver = {
 	.remove		= __exit_p(ehci_orion_drv_remove),
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
-		.name	= "orion-ehci",
+		.name	= hcd_name,
 		.owner  = THIS_MODULE,
 		.of_match_table = of_match_ptr(ehci_orion_dt_ids),
 	},
 };
+
+static int __init ehci_orion_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_orion_hc_driver, &orion_overrides);
+	return platform_driver_register(&ehci_orion_driver);
+}
+module_init(ehci_orion_init);
+
+static void __exit ehci_orion_cleanup(void)
+{
+	platform_driver_unregister(&ehci_orion_driver);
+}
+module_exit(ehci_orion_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:ehci-orion");
+MODULE_AUTHOR("Tzachi Perelstein");
+MODULE_LICENSE("GPL");
+
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 05/10] USB: EHCI: make ehci-atmel a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
  2013-02-07 17:34   ` [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver manjunath.goudar
@ 2013-02-07 17:34   ` manjunath.goudar
  2013-02-08  2:58     ` Bo Shen
  2013-06-12 11:53     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-02-07 17:34   ` [PATCH 07/10] USB: EHCI: make ehci-mv " manjunath.goudar
                     ` (3 subsequent siblings)
  5 siblings, 2 replies; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, Grant Likely, Rob Herring, Andrew Victor, Nicolas Ferre,
	Jean-Christophe Plagniol-Villard, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the Atmel host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Greg KH <greg@kroah.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Andrew Victor <linux@maxim.org.za>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig      |    7 ++++
 drivers/usb/host/Makefile     |    1 +
 drivers/usb/host/ehci-atmel.c |   78 ++++++++++++++++++++++-------------------
 drivers/usb/host/ehci-hcd.c   |    6 +---
 4 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3689b7b..5a13f9d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
         ---help---
           Enables support for the on-chip EHCI controller on
           Morvell Orion chips.
+config USB_EHCI_HCD_AT91
+        tristate  "Support for Atmel on-chip EHCI USB controller"
+        depends on USB_EHCI_HCD && ARCH_AT91
+        default y
+        ---help---
+          Enables support for the on-chip EHCI controller on
+          Atmel chips.
 
 config USB_EHCI_MSM
 	bool "Support for MSM on-chip EHCI USB controller"
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 23b07dd..96b4839 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
 obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
 obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
+obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 27639487..2f06711 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -15,6 +15,19 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI atmel driver"
+
+static const char hcd_name[] = "ehci-atmel";
+static struct hc_driver __read_mostly ehci_atmel_hc_driver;
 
 /* interface and function clocks */
 static struct clk *iclk, *fclk;
@@ -60,41 +73,6 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
 	return ehci_setup(hcd);
 }
 
-static const struct hc_driver ehci_atmel_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Atmel EHCI UHP HS",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/* generic hardware linkage */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/* basic lifecycle operations */
-	.reset			= ehci_atmel_setup,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	/* managing i/o requests and associated device resources */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-
-	/* scheduling support */
-	.get_frame_number	= ehci_get_frame,
-
-	/* root hub support */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
-};
-
 static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
 
 static int ehci_atmel_drv_probe(struct platform_device *pdev)
@@ -210,7 +188,35 @@ static struct platform_driver ehci_atmel_driver = {
 	.remove		= ehci_atmel_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver		= {
-		.name	= "atmel-ehci",
+		.name	= hcd_name,
 		.of_match_table	= of_match_ptr(atmel_ehci_dt_ids),
 	},
 };
+
+static const struct ehci_driver_overrides atmel_overrides __initdata = {
+	.reset = ehci_atmel_setup,
+};
+
+static int __init ehci_atmel_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ehci_init_driver(&ehci_atmel_hc_driver, &atmel_overrides);
+	return platform_driver_register(&ehci_atmel_driver);
+}
+module_init(ehci_atmel_init);
+
+static void __exit ehci_atmel_cleanup(void)
+{
+	platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_ALIAS("platform:ehci-atmel");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5a19a57..628ed139 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1272,11 +1272,6 @@ MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
 #endif
 
-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define	PLATFORM_DRIVER		ehci_atmel_driver
-#endif
-
 #ifdef CONFIG_USB_OCTEON_EHCI
 #include "ehci-octeon.c"
 #define PLATFORM_DRIVER		ehci_octeon_driver
@@ -1334,6 +1329,7 @@ MODULE_LICENSE ("GPL");
 	!defined(PLATFORM_DRIVER) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
 	!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
+	!IS_ENABLED(CONFIG_ARCH_AT91) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
 	!defined(XILINX_OF_PLATFORM_DRIVER)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 07/10] USB: EHCI: make ehci-mv a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
  2013-02-07 17:34   ` [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver manjunath.goudar
  2013-02-07 17:34   ` [PATCH 05/10] USB: EHCI: make ehci-atmel " manjunath.goudar
@ 2013-02-07 17:34   ` manjunath.goudar
  2013-02-07 17:34   ` [PATCH 08/10] USB: EHCI: make ehci-vt8500 " manjunath.goudar
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, Jason Cooper, Andrew Lunn, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the mv(marvell) host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig    |    2 +-
 drivers/usb/host/Makefile   |    1 +
 drivers/usb/host/ehci-hcd.c |    6 +---
 drivers/usb/host/ehci-mv.c  |   81 ++++++++++++++++++++-----------------------
 4 files changed, 40 insertions(+), 50 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f2e0ed3..e7c3ce0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -227,7 +227,7 @@ config USB_EHCI_S5P
 	 Enable support for the S5P SOC's on-chip EHCI controller.
 
 config USB_EHCI_MV
-	bool "EHCI support for Marvell on-chip controller"
+	tristate "EHCI support for Marvell on-chip controller"
 	depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
 	select USB_EHCI_ROOT_HUB_TT
 	---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 5c4f5e1..677f1d3 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
 obj-$(CONFIG_USB_EHCI_S5P)      += ehci-s5p.o
+obj-$(CONFIG_USB_EHCI_MV)       += ehci-mv.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 36557e3..e636719 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1307,11 +1307,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_grlib_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MV
-#include "ehci-mv.c"
-#define        PLATFORM_DRIVER         ehci_mv_driver
-#endif
-
 #ifdef CONFIG_MIPS_SEAD3
 #include "ehci-sead3.c"
 #define	PLATFORM_DRIVER		ehci_hcd_sead3_driver
@@ -1326,6 +1321,7 @@ MODULE_LICENSE ("GPL");
 	!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
 	!IS_ENABLED(CONFIG_ARCH_AT91) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_MV) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
 	!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 6c56297..67de419 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -17,7 +17,18 @@
 #include <linux/usb/otg.h>
 #include <linux/platform_data/mv_usb.h>
 
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI mv driver"
+
 #define CAPLENGTH_MASK         (0xff)
+static const char hcd_name[] = "ehci-mv";
+static struct hc_driver __read_mostly mv_ehci_hc_driver;
 
 struct ehci_hcd_mv {
 	struct usb_hcd *hcd;
@@ -95,48 +106,6 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
 	return retval;
 }
 
-static const struct hc_driver mv_ehci_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Marvell EHCI",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = mv_ehci_reset,
-	.start = ehci_run,
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-};
-
 static int mv_ehci_probe(struct platform_device *pdev)
 {
 	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
@@ -302,7 +271,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
 {
 	struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_mv->hcd;
-	int clk_i;
 
 	if (hcd->rh_registered)
 		usb_remove_hcd(hcd);
@@ -351,8 +319,33 @@ static struct platform_driver ehci_mv_driver = {
 	.remove = mv_ehci_remove,
 	.shutdown = mv_ehci_shutdown,
 	.driver = {
-		   .name = "mv-ehci",
+		   .name = hcd_name,
 		   .bus = &platform_bus_type,
 		   },
 	.id_table = ehci_id_table,
 };
+static const struct ehci_driver_overrides mv_overrides __initdata = {
+	.reset = mv_ehci_reset,
+};
+
+static int __init ehci_mv_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ehci_init_driver(&mv_ehci_hc_driver, &mv_overrides);
+	return platform_driver_register(&ehci_mv_driver);
+}
+module_init(ehci_mv_init);
+
+static void __exit ehci_mv_cleanup(void)
+{
+	platform_driver_unregister(&ehci_mv_driver);
+}
+module_exit(ehci_mv_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:ehci-mv");
+MODULE_AUTHOR("Marvell");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 08/10] USB: EHCI: make ehci-vt8500 a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
                     ` (2 preceding siblings ...)
  2013-02-07 17:34   ` [PATCH 07/10] USB: EHCI: make ehci-mv " manjunath.goudar
@ 2013-02-07 17:34   ` manjunath.goudar
  2013-02-07 18:54     ` Tony Prisk
  2013-02-07 17:34   ` [PATCH 09/10] USB: EHCI: make ehci-msm " manjunath.goudar
  2013-02-07 17:34   ` [PATCH 10/10] USB: EHCI: make ehci-w90X900 " manjunath.goudar
  5 siblings, 1 reply; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, Tony Prisk, Alexey Charkov, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the vt8500 host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Tony Prisk <linux@prisktech.co.nz>
Cc: Alexey Charkov <alchark@gmail.com>
Cc: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig       |    8 +++++
 drivers/usb/host/Makefile      |    1 +
 drivers/usb/host/ehci-hcd.c    |    5 ---
 drivers/usb/host/ehci-vt8500.c |   73 ++++++++++++++++++----------------------
 4 files changed, 42 insertions(+), 45 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index e7c3ce0..d20d22c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -162,6 +162,14 @@ config USB_EHCI_HCD_OMAP
 	  Enables support for the on-chip EHCI controller on
 	  OMAP3 and later chips.
 
+config USB_EHCI_HCD_VT8500
+        tristate "Support for VT8500 on-chip EHCI USB controller"
+        depends on USB_EHCI_HCD && ARCH_VT8500
+        default y
+        ---help---
+          Enables support for the on-chip EHCI controller on
+          VT8500 chips.
+
 config USB_EHCI_HCD_SPEAR
         tristate "Support for ST spear on-chip EHCI USB controller"
         depends on USB_EHCI_HCD && PLAT_SPEAR
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 677f1d3..cf71e5d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
 obj-$(CONFIG_USB_EHCI_S5P)      += ehci-s5p.o
 obj-$(CONFIG_USB_EHCI_MV)       += ehci-mv.o
+obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e636719..952f85e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1277,11 +1277,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define	PLATFORM_DRIVER		vt8500_ehci_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_MSM
 #include "ehci-msm.c"
 #define PLATFORM_DRIVER		ehci_msm_driver
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
index 11695d5..ff4e3ae 100644
--- a/drivers/usb/host/ehci-vt8500.c
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -16,52 +16,25 @@
  *
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
-static const struct hc_driver vt8500_ehci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "VT8500 EHCI",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
+#include "ehci.h"
 
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset			= ehci_setup,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
+#define DRIVER_DESC "vt8500 On-Chip EHCI Host driver"
 
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
+static const char hcd_name[] = "ehci-vt8500";
 
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ehci_get_frame,
+static struct hc_driver __read_mostly vt8500_ehci_hc_driver;
 
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides ehci_vt8500_overrides __initdata = {
+	.reset = ehci_setup,
 };
 
 static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
@@ -140,11 +113,31 @@ static struct platform_driver vt8500_ehci_driver = {
 	.remove		= vt8500_ehci_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
-		.name	= "vt8500-ehci",
+		.name	= hcd_name,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(vt8500_ehci_ids),
 	}
 };
 
+static int __init ehci_vt8500_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ehci_init_driver(&vt8500_ehci_hc_driver, &ehci_vt8500_overrides);
+	return platform_driver_register(&vt8500_ehci_driver);
+}
+module_init(ehci_vt8500_init);
+
+static void __exit ehci_vt8500_cleanup(void)
+{
+	platform_driver_unregister(&vt8500_ehci_driver);
+}
+module_exit(ehci_vt8500_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Alexey Charkov");
+MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:vt8500-ehci");
 MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 09/10] USB: EHCI: make ehci-msm a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
                     ` (3 preceding siblings ...)
  2013-02-07 17:34   ` [PATCH 08/10] USB: EHCI: make ehci-vt8500 " manjunath.goudar
@ 2013-02-07 17:34   ` manjunath.goudar
  2013-02-07 18:48     ` Stephen Warren
  2013-02-07 19:05     ` David Brown
  2013-02-07 17:34   ` [PATCH 10/10] USB: EHCI: make ehci-w90X900 " manjunath.goudar
  5 siblings, 2 replies; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, David Brown, Daniel Walker, Bryan Huntsman,
	Brian Swetland, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the Qualcomm On-Chip host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brown <davidb@codeaurora.org>
Cc: Daniel Walker <dwalker@fifo99.com>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Brian Swetland <swetland@google.com>
Cc: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig    |    5 +--
 drivers/usb/host/Makefile   |    1 +
 drivers/usb/host/ehci-hcd.c |    7 ++--
 drivers/usb/host/ehci-msm.c |   84 +++++++++++++++++++------------------------
 4 files changed, 43 insertions(+), 54 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d20d22c..8d18a6c 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -184,6 +184,7 @@ config USB_EHCI_HCD_ORION
         ---help---
           Enables support for the on-chip EHCI controller on
           Morvell Orion chips.
+
 config USB_EHCI_HCD_AT91
         tristate  "Support for Atmel on-chip EHCI USB controller"
         depends on USB_EHCI_HCD && ARCH_AT91
@@ -193,7 +194,7 @@ config USB_EHCI_HCD_AT91
           Atmel chips.
 
 config USB_EHCI_MSM
-	bool "Support for MSM on-chip EHCI USB controller"
+	tristate "Support for MSM on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && ARCH_MSM
 	select USB_EHCI_ROOT_HUB_TT
 	select USB_MSM_OTG
@@ -209,7 +210,7 @@ config USB_EHCI_TEGRA
        boolean "NVIDIA Tegra HCD support"
        depends on USB_EHCI_HCD && ARCH_TEGRA
        select USB_EHCI_ROOT_HUB_TT
-       help
+      --- help---
          This driver enables support for the internal USB Host Controllers
          found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
 
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cf71e5d..6c1d0e0 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
 obj-$(CONFIG_USB_EHCI_S5P)      += ehci-s5p.o
 obj-$(CONFIG_USB_EHCI_MV)       += ehci-mv.o
 obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
+obj-$(CONFIG_USB_EHCI_MSM)      += ehci-msm.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 952f85e..d44115b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1277,11 +1277,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MSM
-#include "ehci-msm.c"
-#define PLATFORM_DRIVER		ehci_msm_driver
-#endif
-
 #ifdef CONFIG_TILE_USB
 #include "ehci-tilegx.c"
 #define	PLATFORM_DRIVER		ehci_hcd_tilegx_driver
@@ -1317,6 +1312,8 @@ MODULE_LICENSE ("GPL");
 	!IS_ENABLED(CONFIG_ARCH_AT91) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_MV) && \
+	!IS_ENABLED(CONFIG_ARCH_VT8500) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
 	!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 88a49c8..fdf66a9 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -30,8 +30,19 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/msm_hsusb_hw.h>
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include "ehci.h"
+
 #define MSM_USB_BASE (hcd->regs)
 
+#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller"
+
+static const char hcd_name[] = "msm_hsusb_host";
+static struct hc_driver __read_mostly msm_hc_driver;
 static struct usb_phy *phy;
 
 static int ehci_msm_reset(struct usb_hcd *hcd)
@@ -56,52 +67,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	return 0;
 }
 
-static struct hc_driver msm_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Qualcomm On-Chip EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq			= ehci_irq,
-	.flags			= HCD_USB2 | HCD_MEMORY,
-
-	.reset			= ehci_msm_reset,
-	.start			= ehci_run,
-
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	/*
-	 * PM support
-	 */
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-};
-
 static int ehci_msm_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -222,7 +187,32 @@ static struct platform_driver ehci_msm_driver = {
 	.probe	= ehci_msm_probe,
 	.remove	= ehci_msm_remove,
 	.driver = {
-		   .name = "msm_hsusb_host",
+		   .name = hcd_name,
 		   .pm = &ehci_msm_dev_pm_ops,
 	},
 };
+
+static const struct ehci_driver_overrides msm_overrides __initdata = {
+	.reset = ehci_msm_reset,
+};
+
+static int __init ehci_msm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ehci_init_driver(&msm_hc_driver, &msm_overrides);
+	return platform_driver_register(&ehci_msm_driver);
+}
+module_init(ehci_msm_init);
+
+static void __exit ehci_msm_cleanup(void)
+{
+	platform_driver_unregister(&ehci_msm_driver);
+}
+module_exit(ehci_msm_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:omap-msm");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH 10/10] USB: EHCI: make ehci-w90X900 a separate driver
       [not found] ` <1360258447-27247-1-git-send-email-yes>
                     ` (4 preceding siblings ...)
  2013-02-07 17:34   ` [PATCH 09/10] USB: EHCI: make ehci-msm " manjunath.goudar
@ 2013-02-07 17:34   ` manjunath.goudar
  5 siblings, 0 replies; 228+ messages in thread
From: manjunath.goudar @ 2013-02-07 17:34 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-arm-kernel, patches, stern, arnd, gregkh, Manjunath Goudar,
	Greg KH, Wan ZongShun, linux-kernel

From: Manjunath Goudar <manjunath.goudar@linaro.org>

Separate the Nuvoton On-Chip host controller driver from ehci-hcd host code
into its own driver module.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/usb/host/Kconfig        |    2 +-
 drivers/usb/host/Makefile       |    1 +
 drivers/usb/host/ehci-hcd.c     |    6 +--
 drivers/usb/host/ehci-w90x900.c |   90 +++++++++++++++++----------------------
 4 files changed, 43 insertions(+), 56 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 8d18a6c..1b5e30b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -245,7 +245,7 @@ config USB_EHCI_MV
 	  only be EHCI host. OTG is controller that can switch to host mode.
 
 config USB_W90X900_EHCI
-	bool "W90X900(W90P910) EHCI support"
+	 tristate "W90X900(W90P910) EHCI support"
 	depends on USB_EHCI_HCD && ARCH_W90X900
 	---help---
 		Enables support for the W90X900 USB controller
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6c1d0e0..74db4d4 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_USB_EHCI_S5P)      += ehci-s5p.o
 obj-$(CONFIG_USB_EHCI_MV)       += ehci-mv.o
 obj-$(CONFIG_USB_EHCI_HCD_VT8500)+= ehci-vt8500.o
 obj-$(CONFIG_USB_EHCI_MSM)      += ehci-msm.o
+obj-$(CONFIG_USB_W90X900_EHCI)  += ehci-w90x900.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
 obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d44115b..84ed7d7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1267,11 +1267,6 @@ MODULE_LICENSE ("GPL");
 #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver
 #endif
 
-#ifdef CONFIG_USB_W90X900_EHCI
-#include "ehci-w90x900.c"
-#define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
-#endif
-
 #ifdef CONFIG_USB_OCTEON_EHCI
 #include "ehci-octeon.c"
 #define PLATFORM_DRIVER		ehci_octeon_driver
@@ -1314,6 +1309,7 @@ MODULE_LICENSE ("GPL");
 	!IS_ENABLED(CONFIG_USB_EHCI_MV) && \
 	!IS_ENABLED(CONFIG_ARCH_VT8500) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
+	!IS_ENABLED(CONFIG_USB_W90X900_EHCI) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
 	!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index 59e0e24..0b677ec 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -13,11 +13,31 @@
 
 #include <linux/platform_device.h>
 
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include "ehci.h"
+
 /* enable phy0 and phy1 for w90p910 */
 #define	ENPHY		(0x01<<8)
 #define PHY0_CTR	(0xA4)
 #define PHY1_CTR	(0xA8)
 
+#define DRIVER_DESC "Nuvoton w90x900 On-Chip EHCI Host driver"
+
+static const char hcd_name[] = "ehci-w90x900";
+
+static struct hc_driver __read_mostly ehci_w90x900_hc_driver;
+
+static const struct ehci_driver_overrides ehci_w90X900_overrides __initdata = {
+	.reset = ehci_setup,
+};
+
 static int usb_w90x900_probe(const struct hc_driver *driver,
 		      struct platform_device *pdev)
 {
@@ -99,54 +119,6 @@ void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
 	usb_put_hcd(hcd);
 }
 
-static const struct hc_driver ehci_w90x900_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Nuvoton w90x900 EHCI Host Controller",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_USB2|HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = ehci_setup,
-	.start = ehci_run,
-
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-#endif
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
 static int ehci_w90x900_probe(struct platform_device *pdev)
 {
 	if (usb_disabled())
@@ -168,12 +140,30 @@ static struct platform_driver ehci_hcd_w90x900_driver = {
 	.probe  = ehci_w90x900_probe,
 	.remove = ehci_w90x900_remove,
 	.driver = {
-		.name = "w90x900-ehci",
+		.name = hcd_name,
 		.owner = THIS_MODULE,
 	},
 };
 
+static int __init ehci_w90X900_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_w90x900_hc_driver, &ehci_w90X900_overrides);
+	return platform_driver_register(&ehci_hcd_w90x900_driver);
+}
+module_init(ehci_w90X900_init);
+
+static void __exit ehci_w90X900_cleanup(void)
+{
+	platform_driver_unregister(&ehci_hcd_w90x900_driver);
+}
+module_exit(ehci_w90X900_cleanup);
+
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 usb ehci driver!");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:w90p910-ehci");
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH 09/10] USB: EHCI: make ehci-msm a separate driver
  2013-02-07 17:34   ` [PATCH 09/10] USB: EHCI: make ehci-msm " manjunath.goudar
@ 2013-02-07 18:48     ` Stephen Warren
  2013-02-07 19:05     ` David Brown
  1 sibling, 0 replies; 228+ messages in thread
From: Stephen Warren @ 2013-02-07 18:48 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, arnd, gregkh,
	Greg KH, David Brown, Daniel Walker, Bryan Huntsman,
	Brian Swetland, linux-kernel

On 02/07/2013 10:34 AM, manjunath.goudar@linaro.org wrote:
> Separate the Qualcomm On-Chip host controller driver from ehci-hcd host code
> into its own driver module.

> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig

> @@ -209,7 +210,7 @@ config USB_EHCI_TEGRA
>         boolean "NVIDIA Tegra HCD support"
>         depends on USB_EHCI_HCD && ARCH_TEGRA
>         select USB_EHCI_ROOT_HUB_TT
> -       help
> +      --- help---
>           This driver enables support for the internal USB Host Controllers
>           found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.

That seems like an unrelated change. The indentation and space after
first "---" looks wrong too. It looks pretty random which of "help" and
"---help---" is used in this file; if you're going to fix that, I think
fix them all, but in a separate patch.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 08/10] USB: EHCI: make ehci-vt8500 a separate driver
  2013-02-07 17:34   ` [PATCH 08/10] USB: EHCI: make ehci-vt8500 " manjunath.goudar
@ 2013-02-07 18:54     ` Tony Prisk
  0 siblings, 0 replies; 228+ messages in thread
From: Tony Prisk @ 2013-02-07 18:54 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, arnd, gregkh,
	Greg KH, Alexey Charkov, linux-kernel

On Thu, 2013-02-07 at 23:04 +0530, manjunath.goudar@linaro.org wrote:
> From: Manjunath Goudar <manjunath.goudar@linaro.org>
> 
> Separate the vt8500 host controller driver from ehci-hcd host code
> into its own driver module.
> 
> Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
> Cc: Greg KH <greg@kroah.com>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Tony Prisk <linux@prisktech.co.nz>
> Cc: Alexey Charkov <alchark@gmail.com>
> Cc: linux-usb@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  drivers/usb/host/Kconfig       |    8 +++++
>  drivers/usb/host/Makefile      |    1 +
>  drivers/usb/host/ehci-hcd.c    |    5 ---
>  drivers/usb/host/ehci-vt8500.c |   73 ++++++++++++++++++----------------------
>  4 files changed, 42 insertions(+), 45 deletions(-)
> 
...
> diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
> index 11695d5..ff4e3ae 100644
> --- a/drivers/usb/host/ehci-vt8500.c
> +++ b/drivers/usb/host/ehci-vt8500.c
> @@ -16,52 +16,25 @@
...
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_AUTHOR("Alexey Charkov");
> +MODULE_LICENSE("GPL");
Should be "GPL v2" as per the license header.

>  MODULE_ALIAS("platform:vt8500-ehci");
>  MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);

Regards
Tony Prisk


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 09/10] USB: EHCI: make ehci-msm a separate driver
  2013-02-07 17:34   ` [PATCH 09/10] USB: EHCI: make ehci-msm " manjunath.goudar
  2013-02-07 18:48     ` Stephen Warren
@ 2013-02-07 19:05     ` David Brown
  1 sibling, 0 replies; 228+ messages in thread
From: David Brown @ 2013-02-07 19:05 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, arnd, gregkh,
	Greg KH, Daniel Walker, Bryan Huntsman, Brian Swetland,
	linux-kernel

manjunath.goudar@linaro.org writes:

> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_ALIAS("platform:omap-msm");
> +MODULE_LICENSE("GPL");

omap-msm?  I think you mean msm-ehci.

I don't have any hardware to test this on, so hopefully someone can
chime in after testing it.

David

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver
  2013-02-07 17:34   ` [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver manjunath.goudar
@ 2013-02-07 19:41     ` Arnd Bergmann
  2013-02-08 10:38     ` Florian Fainelli
  1 sibling, 0 replies; 228+ messages in thread
From: Arnd Bergmann @ 2013-02-07 19:41 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, gregkh, Greg KH,
	Jason Cooper, Andrew Lunn, Russell King, linux-kernel

On Thursday 07 February 2013, manjunath.goudar@linaro.org wrote:
> @@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
>   * before driver shutdown. But it also seems to be caused by bugs in cardbus
>   * bridge shutdown:  shutting down the bridge before the devices using it.
>   */
> -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
> +int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
>                       u32 mask, u32 done, int usec)
>  {
>         u32     result;

I had not noticed this before, but apparently it belongs into the
tegra patch that you dropped, rather than this patch.

Same thing for all the changes below.

> @@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
>         } while (usec > 0);
>         return -ETIMEDOUT;
>  }
> -
> +EXPORT_SYMBOL_GPL(handshake);
>  /* check TDI/ARC silicon is in host mode */
> -static int tdi_in_host_mode (struct ehci_hcd *ehci)
> +static int tdi_in_host_mode(struct ehci_hcd *ehci)
>  {
>         u32             tmp;
>  
> @@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
>   * Force HC to halt state from unknown (EHCI spec section 2.3).
>   * Must be called with interrupts enabled and the lock not held.
>   */
> -static int ehci_halt (struct ehci_hcd *ehci)
> +int ehci_halt(struct ehci_hcd *ehci)
>  {
>         u32     temp;
>  
> @@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
>         return handshake(ehci, &ehci->regs->status,
>                           STS_HALT, STS_HALT, 16 * 125);
>  }
> -
> +EXPORT_SYMBOL_GPL(ehci_halt);
>  /* put TDI/ARC silicon into EHCI mode */
> -static void tdi_reset (struct ehci_hcd *ehci)
> +void tdi_reset(struct ehci_hcd *ehci)
>  {
>         u32             tmp;
>  
> @@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
>                 tmp |= USBMODE_BE;
>         ehci_writel(ehci, tmp, &ehci->regs->usbmode);
>  }
> -
> +EXPORT_SYMBOL_GPL(tdi_reset);
>  /*
>   * Reset a non-running (STS_HALT == 1) controller.
>   * Must be called with interrupts enabled and the lock not held.
>   */
> -static int ehci_reset (struct ehci_hcd *ehci)
> +int ehci_reset(struct ehci_hcd *ehci)
>  {
>         int     retval;
>         u32     command = ehci_readl(ehci, &ehci->regs->command);
> @@ -272,7 +272,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
>                         ehci->resuming_ports = 0;
>         return retval;
>  }
> -
> +EXPORT_SYMBOL_GPL(ehci_reset);
>  /*
>   * Idle the controller (turn off the schedules).
>   * Must be called with interrupts enabled and the lock not held.
> @@ -352,7 +352,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
>   * This forcibly disables dma and IRQs, helping kexec and other cases
>   * where the next system software may expect clean state.
>   */
> -static void ehci_shutdown(struct usb_hcd *hcd)
> +void ehci_shutdown(struct usb_hcd *hcd)
>  {
>         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>  
> @@ -366,7 +366,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>  
>         hrtimer_cancel(&ehci->hrtimer);
>  }
> -
> +EXPORT_SYMBOL_GPL(ehci_shutdown);

	Arnd

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 05/10] USB: EHCI: make ehci-atmel a separate driver
  2013-02-07 17:34   ` [PATCH 05/10] USB: EHCI: make ehci-atmel " manjunath.goudar
@ 2013-02-08  2:58     ` Bo Shen
  2013-06-12 11:53     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 228+ messages in thread
From: Bo Shen @ 2013-02-08  2:58 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, patches, gregkh, Nicolas Ferre, linux-kernel,
	Rob Herring, Andrew Victor, Grant Likely, stern, Greg KH,
	Jean-Christophe Plagniol-Villard, arnd, linux-arm-kernel

Hi Manjunath Goudar,
   I test this patch based on linux master branch, the commit id is: 
6bacaa9ddacb71c691d32c678d37bc59ffc71fac. (I am not sure this is the 
right place for testing).
   First, it has an compile error as following. After fix it, and 
tested, the EHCI doesn't work.
---<8---
drivers/usb/host/ehci-atmel.c: In function 'ehci_atmel_drv_remove':
drivers/usb/host/ehci-atmel.c:167: error: implicit declaration of 
function 'ehci_shutdown'
--->8---

And a little code style comments as following.

On 2/8/2013 1:34, manjunath.goudar@linaro.org wrote:
> From: Manjunath Goudar <manjunath.goudar@linaro.org>
>
> Separate the Atmel host controller driver from ehci-hcd host code
> into its own driver module.
>
> Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Greg KH <greg@kroah.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Andrew Victor <linux@maxim.org.za>
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: linux-usb@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>   drivers/usb/host/Kconfig      |    7 ++++
>   drivers/usb/host/Makefile     |    1 +
>   drivers/usb/host/ehci-atmel.c |   78 ++++++++++++++++++++++-------------------
>   drivers/usb/host/ehci-hcd.c   |    6 +---
>   4 files changed, 51 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 3689b7b..5a13f9d 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
>           ---help---
>             Enables support for the on-chip EHCI controller on
>             Morvell Orion chips.

Need blank line here.

> +config USB_EHCI_HCD_AT91
> +        tristate  "Support for Atmel on-chip EHCI USB controller"
> +        depends on USB_EHCI_HCD && ARCH_AT91
> +        default y
> +        ---help---
> +          Enables support for the on-chip EHCI controller on
> +          Atmel chips.
>
>   config USB_EHCI_MSM
>   	bool "Support for MSM on-chip EHCI USB controller"

[snip]

> +static void __exit ehci_atmel_cleanup(void)
> +{
> +	platform_driver_unregister(&ehci_atmel_driver);
> +}
> +module_exit(ehci_atmel_cleanup);
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +
> +MODULE_ALIAS("platform:ehci-atmel");
> +MODULE_AUTHOR("Nicolas Ferre");
> +MODULE_LICENSE("GPL");
> +

Remove the blank line here. As to it is the EOF.

Best Regards,
Bo Shen

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver
  2013-02-07 17:34   ` [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver manjunath.goudar
  2013-02-07 19:41     ` Arnd Bergmann
@ 2013-02-08 10:38     ` Florian Fainelli
  1 sibling, 0 replies; 228+ messages in thread
From: Florian Fainelli @ 2013-02-08 10:38 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, arnd, gregkh,
	Greg KH, Jason Cooper, Andrew Lunn, Russell King, linux-kernel

Hello Manjunath,

On 02/07/2013 06:34 PM, manjunath.goudar@linaro.org wrote:
> From: Manjunath Goudar <manjunath.goudar@linaro.org>
>
> Separate the Marvell Orion host controller driver from ehci-hcd host code
> into its own driver module.
>
[snip]

The changes you introduce in ehci-hcd.c would certainly deserve their 
own preliminary patch in this serie and not be squashed into this one imho.

> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
>    * before driver shutdown. But it also seems to be caused by bugs in cardbus
>    * bridge shutdown:  shutting down the bridge before the devices using it.
>    */
> -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
> +int handshake(struct ehci_hcd *ehci, void __iomem *ptr,
>   		      u32 mask, u32 done, int usec)
>   {
>   	u32	result;
> @@ -172,9 +172,9 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
>   	} while (usec > 0);
>   	return -ETIMEDOUT;
>   }
> -
> +EXPORT_SYMBOL_GPL(handshake);

This sounds way too generic as a name to be exported as is, so please 
namespace this with ehci_hcd_ at least.

>   /* check TDI/ARC silicon is in host mode */
> -static int tdi_in_host_mode (struct ehci_hcd *ehci)
> +static int tdi_in_host_mode(struct ehci_hcd *ehci)

Looks unrelated to the goals of your patches.

>   {
>   	u32		tmp;
>
> @@ -186,7 +186,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
>    * Force HC to halt state from unknown (EHCI spec section 2.3).
>    * Must be called with interrupts enabled and the lock not held.
>    */
> -static int ehci_halt (struct ehci_hcd *ehci)
> +int ehci_halt(struct ehci_hcd *ehci)
>   {
>   	u32	temp;
>
> @@ -215,9 +215,9 @@ static int ehci_halt (struct ehci_hcd *ehci)
>   	return handshake(ehci, &ehci->regs->status,
>   			  STS_HALT, STS_HALT, 16 * 125);
>   }
> -
> +EXPORT_SYMBOL_GPL(ehci_halt);

I would rename this to ehci_hcd_halt to express the fact that it takes 
an ehci_hcd structure pointer as parameter, can be addressed later.

>   /* put TDI/ARC silicon into EHCI mode */
> -static void tdi_reset (struct ehci_hcd *ehci)
> +void tdi_reset(struct ehci_hcd *ehci)
>   {
>   	u32		tmp;
>
> @@ -231,12 +231,12 @@ static void tdi_reset (struct ehci_hcd *ehci)
>   		tmp |= USBMODE_BE;
>   	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
>   }
> -
> +EXPORT_SYMBOL_GPL(tdi_reset);

Same here, way too generic to be exported as is as a symbol name.
--
Florian

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support
       [not found] <yes>
                   ` (27 preceding siblings ...)
       [not found] ` <1360258447-27247-1-git-send-email-yes>
@ 2013-06-10  9:17 ` Srinivas KANDAGATLA
  2013-06-10  9:21   ` [PATCH v2 01/11] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
                     ` (10 more replies)
  2014-08-12  6:40 ` [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held() Sanjeev Sharma
                   ` (5 subsequent siblings)
  34 siblings, 11 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

From: Srinivas Kandagatla <srinivas.kandagatla@st.com>

Here is new patch-set incorporating all the review comments.

This patch-set adds basic support for STMicroelectronics STixxxx SOCs
which includes STiH415 and STiH416 with B2000 and B2020 board support.

STiH415 and STiH416 are dual-core ARM Cortex-A9 CPU, designed for use in
Set-top-boxes. The SOC support is available in mach-stixxxx which contains
support code for STiH415, STiH416 SOCs including the generic board support.

Only device drivers included in this patch set are UART and pinctrl, other
drivers will be added in future.

The reason for adding two SOCs at this patch set is to show that no new
C code is required for second SOC(STiH416) support.

Thankyou all for reviewing the first set of RFC patches.
I would appreciate any feedback on these patches.

Changes since RFC:
 - st-asc Serial driver:
	- modified kconfig to remove default y
	- removed all the forward declaration.
	- use dynamic major numbering.
	- merge header-file in to driver.

 - ARM Global timer:
	- moved to drivers/clocksource.
	- added revision check in driver.
	- removed unused header file.
	- moved to u64 from union gt_counter
	- comments added in get_counter
	- removed leftover debug code.
	- moved code to use __raw_readl/writel.
	- used DIV_ROUND_CLOSEST
	- added check in interrupt handler.
	- expanded CE and CS acronyms usage.
	- Fixed minimum clock ticks value.
	- move to use clocksource_register_hz
	- added arch sched_clock support.
	- added ERRATA 740657 workaround.

 - ST-System Configuration Registers:
	- moved from syscon usage to st specific driver.

 - ST Pinctrl support:
	- fixed few typos in the documentation.
	- moved some of the retime offset information to driver.
	
 - STixxxx Support:
	- all the SOC support code is moved to mach-stixxxx
	- seperated DEBUG_LL code to new patch.
	- removed unnecessary #interrupt-cells
	- renamed uart to serial
	- moved to multi_v7_defconfig
	- used menuconfig in mach-stixxx/Kconfig
	- removed of_platform_populate as generic code does it for you.
	- scu address is ioremaped.

Thanks,
srini

Srinivas Kandagatla (10):
  serial:st-asc: Add ST ASC driver.
  regmap: Add regmap_field APIs
  mfd:stixxxx-syscfg: Add ST System Configuration support.
  pinctrl:stixxxx: Add pinctrl and pinconf support.
  ARM:stixxxx: Add STiH415 SOC support
  ARM:stixxxx: Add STiH416 SOC support
  ARM:stixxxx: Add DEBUG_LL console support
  ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  ARM:stih41x: Add B2000 board support
  ARM:stih41x: Add B2020 board support

Stuart Menefy (1):
  clocksource:global_timer: Add ARM global timer support.

 Documentation/arm/stixxxx/overview.txt             |   33 +
 Documentation/arm/stixxxx/stih415-overview.txt     |   12 +
 Documentation/arm/stixxxx/stih416-overview.txt     |   12 +
 .../devicetree/bindings/arm/global_timer.txt       |   21 +
 .../devicetree/bindings/mfd/stixxxx-syscfg.txt     |   18 +
 .../bindings/pinctrl/pinctrl-stixxxx.txt           |  116 ++
 .../devicetree/bindings/tty/serial/st-asc.txt      |   18 +
 MAINTAINERS                                        |   11 +
 arch/arm/Kconfig                                   |    2 +
 arch/arm/Kconfig.debug                             |   38 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/boot/dts/Makefile                         |    4 +
 arch/arm/boot/dts/stih415-b2000.dts                |   15 +
 arch/arm/boot/dts/stih415-b2020.dts                |   15 +
 arch/arm/boot/dts/stih415-clock.dtsi               |   38 +
 arch/arm/boot/dts/stih415-pinctrl.dtsi             |  326 ++++++
 arch/arm/boot/dts/stih415.dtsi                     |  102 ++
 arch/arm/boot/dts/stih416-b2000.dts                |   16 +
 arch/arm/boot/dts/stih416-b2020.dts                |   16 +
 arch/arm/boot/dts/stih416-clock.dtsi               |   41 +
 arch/arm/boot/dts/stih416-pinctrl.dtsi             |  377 ++++++
 arch/arm/boot/dts/stih416.dtsi                     |  111 ++
 arch/arm/boot/dts/stih41x-b2000.dtsi               |   41 +
 arch/arm/boot/dts/stih41x-b2020.dtsi               |   42 +
 arch/arm/boot/dts/stih41x.dtsi                     |   38 +
 arch/arm/boot/dts/stixxxx-pincfg.h                 |   94 ++
 arch/arm/configs/multi_v7_defconfig                |   32 +-
 arch/arm/include/debug/stixxxx.S                   |   61 +
 arch/arm/mach-stixxxx/Kconfig                      |   45 +
 arch/arm/mach-stixxxx/Makefile                     |    2 +
 arch/arm/mach-stixxxx/board-dt.c                   |   50 +
 arch/arm/mach-stixxxx/headsmp.S                    |   44 +
 arch/arm/mach-stixxxx/platsmp.c                    |  117 ++
 arch/arm/mach-stixxxx/smp.h                        |   19 +
 drivers/base/regmap/internal.h                     |    8 +
 drivers/base/regmap/regmap.c                       |  104 ++
 drivers/clocksource/Kconfig                        |   13 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/arm_global_timer.c             |  368 ++++++
 drivers/mfd/Kconfig                                |   10 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/stixxxx-syscfg.c                       |  168 +++
 drivers/pinctrl/Kconfig                            |   11 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-stixxxx.c                  | 1212 ++++++++++++++++++++
 drivers/pinctrl/pinctrl-stixxxx.h                  |  197 ++++
 drivers/tty/serial/Kconfig                         |   16 +
 drivers/tty/serial/Makefile                        |    1 +
 drivers/tty/serial/st-asc.c                        |  911 +++++++++++++++
 include/linux/mfd/stixxxx-syscfg.h                 |   15 +
 include/linux/regmap.h                             |   42 +
 include/uapi/linux/serial_core.h                   |    3 +
 52 files changed, 4993 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/arm/stixxxx/overview.txt
 create mode 100644 Documentation/arm/stixxxx/stih415-overview.txt
 create mode 100644 Documentation/arm/stixxxx/stih416-overview.txt
 create mode 100644 Documentation/devicetree/bindings/arm/global_timer.txt
 create mode 100644 Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
 create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
 create mode 100644 arch/arm/boot/dts/stih415-b2000.dts
 create mode 100644 arch/arm/boot/dts/stih415-b2020.dts
 create mode 100644 arch/arm/boot/dts/stih415-clock.dtsi
 create mode 100644 arch/arm/boot/dts/stih415-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stih415.dtsi
 create mode 100644 arch/arm/boot/dts/stih416-b2000.dts
 create mode 100644 arch/arm/boot/dts/stih416-b2020.dts
 create mode 100644 arch/arm/boot/dts/stih416-clock.dtsi
 create mode 100644 arch/arm/boot/dts/stih416-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stih416.dtsi
 create mode 100644 arch/arm/boot/dts/stih41x-b2000.dtsi
 create mode 100644 arch/arm/boot/dts/stih41x-b2020.dtsi
 create mode 100644 arch/arm/boot/dts/stih41x.dtsi
 create mode 100644 arch/arm/boot/dts/stixxxx-pincfg.h
 create mode 100644 arch/arm/include/debug/stixxxx.S
 create mode 100644 arch/arm/mach-stixxxx/Kconfig
 create mode 100644 arch/arm/mach-stixxxx/Makefile
 create mode 100644 arch/arm/mach-stixxxx/board-dt.c
 create mode 100644 arch/arm/mach-stixxxx/headsmp.S
 create mode 100644 arch/arm/mach-stixxxx/platsmp.c
 create mode 100644 arch/arm/mach-stixxxx/smp.h
 create mode 100644 drivers/clocksource/arm_global_timer.c
 create mode 100644 drivers/mfd/stixxxx-syscfg.c
 create mode 100644 drivers/pinctrl/pinctrl-stixxxx.c
 create mode 100644 drivers/pinctrl/pinctrl-stixxxx.h
 create mode 100644 drivers/tty/serial/st-asc.c
 create mode 100644 include/linux/mfd/stixxxx-syscfg.h

-- 
1.7.6.5


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH v2 01/11] serial:st-asc: Add ST ASC driver.
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
@ 2013-06-10  9:21   ` Srinivas KANDAGATLA
  2013-06-10  9:35     ` Russell King - ARM Linux
  2013-06-10  9:21   ` [PATCH v2 02/11] clocksource:global_timer: Add ARM global timer support Srinivas KANDAGATLA
                     ` (9 subsequent siblings)
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:21 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP is common
across all the ST parts for settop box platforms.

ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 .../devicetree/bindings/tty/serial/st-asc.txt      |   18 +
 drivers/tty/serial/Kconfig                         |   16 +
 drivers/tty/serial/Makefile                        |    1 +
 drivers/tty/serial/st-asc.c                        |  911 ++++++++++++++++++++
 include/uapi/linux/serial_core.h                   |    3 +
 5 files changed, 949 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt
 create mode 100644 drivers/tty/serial/st-asc.c

diff --git a/Documentation/devicetree/bindings/tty/serial/st-asc.txt b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
new file mode 100644
index 0000000..75d877f
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/st-asc.txt
@@ -0,0 +1,18 @@
+*st-asc(Serial Port)
+
+Required properties:
+- compatible : Should be "st,asc".
+- reg, reg-names, interrupts, interrupt-names	: Standard way to define device
+			resources with names. look in
+			Documentation/devicetree/bindings/resource-names.txt
+
+Optional properties:
+- st,hw-flow-ctrl	bool flag to enable hardware flow control.
+- st,force-m1		bool flat to force asc to be in Mode-1 recommeded
+			for high bit rates (above 19.2K)
+Example:
+serial@fe440000{
+    compatible    = "st,asc";
+    reg         = <0xfe440000 0x2c>;
+    interrupts     =  <0 209 0>;
+};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 7e7006f..0c6ddf6 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1484,6 +1484,22 @@ config SERIAL_RP2_NR_UARTS
 	  If multiple cards are present, the default limit of 32 ports may
 	  need to be increased.
 
+config SERIAL_ST_ASC
+	tristate "ST ASC serial port support"
+	select SERIAL_CORE
+	help
+	  This driver is for the on-chip Asychronous Serial Controller on
+	  STMicroelectronics STixxxx SoCs.
+	  ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
+	  It support all industry standard baud rates.
+
+	  If unsure, say N.
+
+config SERIAL_ST_ASC_CONSOLE
+	bool "Support for console on ST ASC"
+	depends on SERIAL_ST_ASC=y
+	select SERIAL_CORE_CONSOLE
+
 endmenu
 
 endif # TTY
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index eedfec4..536ccc7 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
 obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
 obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
new file mode 100644
index 0000000..6592c04
--- /dev/null
+++ b/drivers/tty/serial/st-asc.c
@@ -0,0 +1,911 @@
+/*
+ * st-asc.c: ST Asynchronous serial controller (ASC) driver
+ *
+ * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "st-asc"
+#define ASC_SERIAL_NAME "ttyAS"
+#define ASC_FIFO_SIZE 16
+#define ASC_MAX_PORTS 8
+
+struct asc_port {
+	struct uart_port port;
+	struct clk *clk;
+	unsigned int hw_flow_control:1;
+	unsigned int check_parity:1;
+	unsigned int force_m1:1;
+};
+
+static struct asc_port asc_ports[ASC_MAX_PORTS];
+static struct uart_driver asc_uart_driver;
+
+/*---- UART Register definitions ------------------------------*/
+
+/* Register offsets */
+
+#define ASC_BAUDRATE			0x00
+#define ASC_TXBUF			0x04
+#define ASC_RXBUF			0x08
+#define ASC_CTL				0x0C
+#define ASC_INTEN			0x10
+#define ASC_STA				0x14
+#define ASC_GUARDTIME			0x18
+#define ASC_TIMEOUT			0x1C
+#define ASC_TXRESET			0x20
+#define ASC_RXRESET			0x24
+#define ASC_RETRIES			0x28
+
+/* ASC_RXBUF */
+#define ASC_RXBUF_PE			0x100
+#define ASC_RXBUF_FE			0x200
+
+/* ASC_CTL */
+
+#define ASC_CTL_MODE_MSK		0x0007
+#define  ASC_CTL_MODE_8BIT		0x0001
+#define  ASC_CTL_MODE_7BIT_PAR		0x0003
+#define  ASC_CTL_MODE_9BIT		0x0004
+#define  ASC_CTL_MODE_8BIT_WKUP		0x0005
+#define  ASC_CTL_MODE_8BIT_PAR		0x0007
+#define ASC_CTL_STOP_MSK		0x0018
+#define  ASC_CTL_STOP_HALFBIT		0x0000
+#define  ASC_CTL_STOP_1BIT		0x0008
+#define  ASC_CTL_STOP_1_HALFBIT		0x0010
+#define  ASC_CTL_STOP_2BIT		0x0018
+#define ASC_CTL_PARITYODD		0x0020
+#define ASC_CTL_LOOPBACK		0x0040
+#define ASC_CTL_RUN			0x0080
+#define ASC_CTL_RXENABLE		0x0100
+#define ASC_CTL_SCENABLE		0x0200
+#define ASC_CTL_FIFOENABLE		0x0400
+#define ASC_CTL_CTSENABLE		0x0800
+#define ASC_CTL_BAUDMODE		0x1000
+
+/* ASC_GUARDTIME */
+
+#define ASC_GUARDTIME_MSK		0x00FF
+
+/* ASC_INTEN */
+
+#define ASC_INTEN_RBE			0x0001
+#define ASC_INTEN_TE			0x0002
+#define ASC_INTEN_THE			0x0004
+#define ASC_INTEN_PE			0x0008
+#define ASC_INTEN_FE			0x0010
+#define ASC_INTEN_OE			0x0020
+#define ASC_INTEN_TNE			0x0040
+#define ASC_INTEN_TOI			0x0080
+#define ASC_INTEN_RHF			0x0100
+
+/* ASC_RETRIES */
+
+#define ASC_RETRIES_MSK			0x00FF
+
+/* ASC_RXBUF */
+
+#define ASC_RXBUF_MSK			0x03FF
+
+/* ASC_STA */
+
+#define ASC_STA_RBF			0x0001
+#define ASC_STA_TE			0x0002
+#define ASC_STA_THE			0x0004
+#define ASC_STA_PE			0x0008
+#define ASC_STA_FE			0x0010
+#define ASC_STA_OE			0x0020
+#define ASC_STA_TNE			0x0040
+#define ASC_STA_TOI			0x0080
+#define ASC_STA_RHF			0x0100
+#define ASC_STA_TF			0x0200
+#define ASC_STA_NKD			0x0400
+
+/* ASC_TIMEOUT */
+
+#define ASC_TIMEOUT_MSK			0x00FF
+
+/* ASC_TXBUF */
+
+#define ASC_TXBUF_MSK			0x01FF
+
+/*---- Inline function definitions ---------------------------*/
+
+static inline struct asc_port *to_asc_port(struct uart_port *port)
+{
+	return container_of(port, struct asc_port, port);
+}
+
+static inline u32 asc_in(struct uart_port *port, u32 offset)
+{
+	return readl(port->membase + offset);
+}
+
+static inline void asc_out(struct uart_port *port, u32 offset, u32 value)
+{
+	writel(value, port->membase + offset);
+}
+
+/*
+ * Some simple utility functions to enable and disable interrupts.
+ * Note that these need to be called with interrupts disabled.
+ */
+static inline void asc_disable_tx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE;
+	asc_out(port, ASC_INTEN, intenable);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+}
+
+static inline void asc_enable_tx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE;
+	asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline void asc_disable_rx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE;
+	asc_out(port, ASC_INTEN, intenable);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+}
+
+static inline void asc_enable_rx_interrupts(struct uart_port *port)
+{
+	u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE;
+	asc_out(port, ASC_INTEN, intenable);
+}
+
+static inline u32 asc_txfifo_is_empty(struct uart_port *port)
+{
+	return asc_in(port, ASC_STA) & ASC_STA_TE;
+}
+
+static inline int asc_txfifo_is_full(struct uart_port *port)
+{
+	return asc_in(port, ASC_STA) & ASC_STA_TF;
+}
+
+static inline const char *asc_port_name(struct uart_port *port)
+{
+	return to_platform_device(port->dev)->name;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * This section contains code to support the use of the ASC as a
+ * generic serial port.
+ */
+
+static inline unsigned asc_hw_txroom(struct uart_port *port)
+{
+	u32 status = asc_in(port, ASC_STA);
+
+	if (status & ASC_STA_THE)
+		return port->fifosize / 2;
+	else if (!(status & ASC_STA_TF))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Start transmitting chars.
+ * This is called from both interrupt and task level.
+ * Either way interrupts are disabled.
+ */
+static void asc_transmit_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+	int txroom;
+	unsigned char c;
+
+	txroom = asc_hw_txroom(port);
+
+	if ((txroom != 0) && port->x_char) {
+		c = port->x_char;
+		port->x_char = 0;
+		asc_out(port, ASC_TXBUF, c);
+		port->icount.tx++;
+		txroom = asc_hw_txroom(port);
+	}
+
+	if (uart_tx_stopped(port)) {
+		/*
+		 * We should try and stop the hardware here, but I
+		 * don't think the ASC has any way to do that.
+		 */
+		asc_disable_tx_interrupts(port);
+		return;
+	}
+
+	if (uart_circ_empty(xmit)) {
+		asc_disable_tx_interrupts(port);
+		return;
+	}
+
+	if (txroom == 0)
+		return;
+
+	do {
+		c = xmit->buf[xmit->tail];
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		asc_out(port, ASC_TXBUF, c);
+		port->icount.tx++;
+		txroom--;
+	} while ((txroom > 0) && (!uart_circ_empty(xmit)));
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		asc_disable_tx_interrupts(port);
+}
+
+static void asc_receive_chars(struct uart_port *port)
+{
+	int count;
+	struct asc_port *ascport = to_asc_port(port);
+	struct tty_port *tport = &port->state->port;
+	int copied = 0;
+	unsigned long status;
+	unsigned long c = 0;
+	char flag;
+	int overrun;
+
+	if (port->irq_wake)
+		pm_wakeup_event(tport->tty->dev, 0);
+
+	while (1) {
+		status = asc_in(port, ASC_STA);
+		if (status & ASC_STA_RHF)
+			count = port->fifosize / 2;
+		else if (status & ASC_STA_RBF)
+			count = 1;
+		else
+			break;
+
+		/*
+		 * Check for overrun before reading any data from the
+		 * RX FIFO, as this clears the overflow error condition.
+		 */
+		overrun = status & ASC_STA_OE;
+
+		for (; count != 0; count--) {
+			c = asc_in(port, ASC_RXBUF);
+			flag = TTY_NORMAL;
+			port->icount.rx++;
+
+			if (unlikely(c & ASC_RXBUF_FE)) {
+				if (c == ASC_RXBUF_FE) {
+					port->icount.brk++;
+					if (uart_handle_break(port))
+						continue;
+					flag = TTY_BREAK;
+				} else {
+					port->icount.frame++;
+					flag = TTY_FRAME;
+				}
+			} else if (ascport->check_parity &&
+				   unlikely(c & ASC_RXBUF_PE)) {
+				port->icount.parity++;
+				flag = TTY_PARITY;
+			}
+
+			if (uart_handle_sysrq_char(port, c))
+				continue;
+			tty_insert_flip_char(tport, c & 0xff, flag);
+		}
+		if (overrun) {
+			port->icount.overrun++;
+			tty_insert_flip_char(tport, 0, TTY_OVERRUN);
+		}
+
+		copied = 1;
+	}
+
+	if (copied) {
+		/* Tell the rest of the system the news. New characters! */
+		tty_flip_buffer_push(tport);
+	}
+}
+
+static irqreturn_t asc_interrupt(int irq, void *ptr)
+{
+	struct uart_port *port = ptr;
+	u32 status;
+
+	spin_lock(&port->lock);
+
+	status = asc_in(port, ASC_STA);
+
+	if (status & ASC_STA_RBF) {
+		/* Receive FIFO not empty */
+		asc_receive_chars(port);
+	}
+
+	if ((status & ASC_STA_THE) &&
+	    (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) {
+		/* Transmitter FIFO at least half empty */
+		asc_transmit_chars(port);
+	}
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * UART Functions
+ */
+
+static unsigned int asc_tx_empty(struct uart_port *port)
+{
+	return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0;
+}
+
+static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/*
+	 * This routine is used for seting signals of: DTR, DCD, CTS/RTS
+	 * We use ASC's hardware for CTS/RTS, so don't need any for that.
+	 * Some boards have DTR and DCD implemented using PIO pins,
+	 * code to do this should be hooked in here.
+	 */
+}
+
+static unsigned int asc_get_mctrl(struct uart_port *port)
+{
+	/*
+	 * This routine is used for geting signals of: DTR, DCD, DSR, RI,
+	 * and CTS/RTS
+	 */
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void asc_start_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (!uart_circ_empty(xmit))
+		asc_enable_tx_interrupts(port);
+}
+
+/* Transmit stop */
+static void asc_stop_tx(struct uart_port *port)
+{
+	asc_disable_tx_interrupts(port);
+}
+
+/* Receive stop */
+static void asc_stop_rx(struct uart_port *port)
+{
+	asc_disable_rx_interrupts(port);
+}
+
+/* Force modem status interrupts on */
+static void asc_enable_ms(struct uart_port *port)
+{
+	/* Nothing here yet .. */
+}
+
+/* Handle breaks - ignored by us */
+static void asc_break_ctl(struct uart_port *port, int break_state)
+{
+	/* Nothing here yet .. */
+}
+
+/*
+ * Enable port for reception.
+ */
+static int asc_startup(struct uart_port *port)
+{
+	if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
+			asc_port_name(port), port)) {
+		dev_err(port->dev, "cannot allocate irq.\n");
+		return -ENODEV;
+	}
+
+	asc_transmit_chars(port);
+	asc_enable_rx_interrupts(port);
+
+	return 0;
+}
+
+static void asc_shutdown(struct uart_port *port)
+{
+	asc_disable_tx_interrupts(port);
+	asc_disable_rx_interrupts(port);
+	free_irq(port->irq, port);
+}
+
+static void asc_pm(struct uart_port *port, unsigned int state,
+		unsigned int oldstate)
+{
+	struct asc_port *ascport = to_asc_port(port);
+	unsigned long flags = 0;
+	u32 ctl;
+
+	switch (state) {
+	case UART_PM_STATE_ON:
+		clk_prepare_enable(ascport->clk);
+		break;
+	case UART_PM_STATE_OFF:
+		/*
+		 * Disable the ASC baud rate generator, which is as close as
+		 * we can come to turning it off. Note this is not called with
+		 * the port spinlock held.
+		 */
+		spin_lock_irqsave(&port->lock, flags);
+		ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
+		asc_out(port, ASC_CTL, ctl);
+		spin_unlock_irqrestore(&port->lock, flags);
+		clk_disable_unprepare(ascport->clk);
+		break;
+	}
+}
+
+static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
+			    struct ktermios *old)
+{
+	struct asc_port *ascport = to_asc_port(port);
+	unsigned int baud;
+	u32 ctrl_val;
+	tcflag_t cflag;
+	unsigned long flags;
+
+	port->uartclk = clk_get_rate(ascport->clk);
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	cflag = termios->c_cflag;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* read control register */
+	ctrl_val = asc_in(port, ASC_CTL);
+
+	/* stop serial port and reset value */
+	asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
+	ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
+
+	/* reset fifo rx & tx */
+	asc_out(port, ASC_TXRESET, 1);
+	asc_out(port, ASC_RXRESET, 1);
+
+	/* set character length */
+	if ((cflag & CSIZE) == CS7) {
+		ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
+	} else {
+		ctrl_val |= (cflag & PARENB) ?  ASC_CTL_MODE_8BIT_PAR :
+						ASC_CTL_MODE_8BIT;
+	}
+
+	ascport->check_parity = (cflag & PARENB) ? 1 : 0;
+
+	/* set stop bit */
+	ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
+
+	/* odd parity */
+	if (cflag & PARODD)
+		ctrl_val |= ASC_CTL_PARITYODD;
+
+	/* hardware flow control */
+	if ((cflag & CRTSCTS) && ascport->hw_flow_control)
+		ctrl_val |= ASC_CTL_CTSENABLE;
+
+	if ((baud < 19200) && !ascport->force_m1) {
+		asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
+	} else {
+		/*
+		 * MODE 1: recommended for high bit rates (above 19.2K)
+		 *
+		 *                   baudrate * 16 * 2^16
+		 * ASCBaudRate =   ------------------------
+		 *                          inputclock
+		 *
+		 * However to keep the maths inside 32bits we divide top and
+		 * bottom by 64. The +1 is to avoid a divide by zero if the
+		 * input clock rate is something unexpected.
+		 */
+		u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
+		asc_out(port, ASC_BAUDRATE, counter);
+		ctrl_val |= ASC_CTL_BAUDMODE;
+	}
+
+	uart_update_timeout(port, cflag, baud);
+
+	/* Set the timeout */
+	asc_out(port, ASC_TIMEOUT, 20);
+
+	/* write final value and enable port */
+	asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *asc_type(struct uart_port *port)
+{
+	return (port->type == PORT_ASC) ? DRIVER_NAME : NULL;
+}
+
+static void asc_release_port(struct uart_port *port)
+{
+}
+
+static int asc_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/*
+ * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set
+ * Set type field if successful
+ */
+static void asc_config_port(struct uart_port *port, int flags)
+{
+	if ((flags & UART_CONFIG_TYPE))
+		port->type = PORT_ASC;
+}
+
+static int
+asc_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	/* No user changeable parameters */
+	return -EINVAL;
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context (i.e. kgdb).
+ */
+
+static int asc_get_poll_char(struct uart_port *port)
+{
+	if (!(asc_in(port, ASC_STA) & ASC_STA_RBF))
+		return NO_POLL_CHAR;
+
+	return asc_in(port, ASC_RXBUF);
+}
+
+static void asc_put_poll_char(struct uart_port *port, unsigned char c)
+{
+	while (asc_txfifo_is_full(port))
+		cpu_relax();
+	asc_out(port, ASC_TXBUF, c);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+/*---------------------------------------------------------------------*/
+
+static struct uart_ops asc_uart_ops = {
+	.tx_empty	= asc_tx_empty,
+	.set_mctrl	= asc_set_mctrl,
+	.get_mctrl	= asc_get_mctrl,
+	.start_tx	= asc_start_tx,
+	.stop_tx	= asc_stop_tx,
+	.stop_rx	= asc_stop_rx,
+	.enable_ms	= asc_enable_ms,
+	.break_ctl	= asc_break_ctl,
+	.startup	= asc_startup,
+	.shutdown	= asc_shutdown,
+	.set_termios	= asc_set_termios,
+	.type		= asc_type,
+	.release_port	= asc_release_port,
+	.request_port	= asc_request_port,
+	.config_port	= asc_config_port,
+	.verify_port	= asc_verify_port,
+	.pm		= asc_pm,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = asc_get_poll_char,
+	.poll_put_char = asc_put_poll_char,
+#endif /* CONFIG_CONSOLE_POLL */
+};
+
+static int asc_init_port(struct asc_port *ascport,
+			  struct platform_device *pdev)
+{
+	struct uart_port *port = &ascport->port;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		dev_err(&pdev->dev, "Unable to get io resource\n");
+		return -ENODEV;
+	}
+
+	port->iotype	= UPIO_MEM;
+	port->flags	= UPF_BOOT_AUTOCONF;
+	port->ops	= &asc_uart_ops;
+	port->fifosize	= ASC_FIFO_SIZE;
+	port->dev	= &pdev->dev;
+	port->mapbase	= res->start;
+	port->irq	= platform_get_irq(pdev, 0);
+
+	port->membase = devm_request_and_ioremap(&pdev->dev, res);
+	if (!port->membase) {
+		dev_err(&pdev->dev, "Unable to request io memory\n");
+		return -ENODEV;
+	}
+
+	spin_lock_init(&port->lock);
+
+	ascport->clk = devm_clk_get(&pdev->dev, NULL);
+
+	if (WARN_ON(IS_ERR(ascport->clk)))
+		return -EINVAL;
+	/* ensure that clk rate is correct by enabling the clk */
+	clk_prepare_enable(ascport->clk);
+	ascport->port.uartclk = clk_get_rate(ascport->clk);
+	WARN_ON(ascport->port.uartclk == 0);
+	clk_disable_unprepare(ascport->clk);
+
+	return 0;
+}
+
+static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int id;
+
+	if (!np)
+		return NULL;
+
+	id = of_alias_get_id(np, ASC_SERIAL_NAME);
+	if (WARN_ON(id >= ASC_MAX_PORTS))
+		return NULL;
+
+	asc_ports[id].hw_flow_control = of_property_read_bool(np,
+							"st,hw-flow-control");
+	asc_ports[id].force_m1 =  of_property_read_bool(np, "st,force_m1");
+	asc_ports[id].port.line = id;
+	return &asc_ports[id];
+}
+
+static struct of_device_id asc_match[] = {
+	{ .compatible = "st,asc", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, asc_match);
+
+static int asc_serial_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct asc_port *ascport;
+
+	ascport = asc_of_get_asc_port(pdev);
+	if (!ascport)
+		return -ENODEV;
+
+	ret = asc_init_port(ascport, pdev);
+	if (ret)
+		return ret;
+
+	ret = uart_add_one_port(&asc_uart_driver, &ascport->port);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, &ascport->port);
+
+	return 0;
+}
+
+static int asc_serial_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	return uart_remove_one_port(&asc_uart_driver, port);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int asc_serial_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	return uart_suspend_port(&asc_uart_driver, port);
+}
+
+static int asc_serial_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct uart_port *port = platform_get_drvdata(pdev);
+
+	if (pdev->dev.pins->default_state) {
+		if (pinctrl_select_state(pdev->dev.pins->p,
+					 pdev->dev.pins->default_state) < 0)
+			return -EBUSY;
+	}
+
+	return uart_resume_port(&asc_uart_driver, port);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
+static void asc_console_putchar(struct uart_port *port, int ch)
+{
+	unsigned int timeout = 1000000;
+
+	/* Wait for upto 1 second in case flow control is stopping us. */
+	while (--timeout && asc_txfifo_is_full(port))
+		udelay(1);
+
+	asc_out(port, ASC_TXBUF, ch);
+}
+
+/*
+ *  Print a string to the serial port trying not to disturb
+ *  any possible real use of the port...
+ */
+
+static void asc_console_write(struct console *co, const char *s, unsigned count)
+{
+	struct uart_port *port = &asc_ports[co->index].port;
+	unsigned long flags;
+	unsigned long timeout = 1000000;
+	int locked = 1;
+	u32 intenable;
+
+	local_irq_save(flags);
+	if (port->sysrq)
+		locked = 0; /* asc_interrupt has already claimed the lock */
+	else if (oops_in_progress)
+		locked = spin_trylock(&port->lock);
+	else
+		spin_lock(&port->lock);
+
+	/*
+	 * Disable interrupts so we don't get the IRQ line bouncing
+	 * up and down while interrupts are disabled.
+	 */
+	intenable = asc_in(port, ASC_INTEN);
+	asc_out(port, ASC_INTEN, 0);
+	(void)asc_in(port, ASC_INTEN);	/* Defeat bus write posting */
+
+	uart_console_write(port, s, count, asc_console_putchar);
+
+	while (--timeout && !asc_txfifo_is_empty(port))
+		udelay(1);
+
+	asc_out(port, ASC_INTEN, intenable);
+
+	if (locked)
+		spin_unlock(&port->lock);
+	local_irq_restore(flags);
+}
+
+static int asc_console_setup(struct console *co, char *options)
+{
+	struct asc_port *ascport;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index >= ASC_MAX_PORTS)
+		return -ENODEV;
+
+	ascport = &asc_ports[co->index];
+
+	/*
+	 * This driver does not support early console initialization
+	 * (use ARM early printk support instead), so we only expect
+	 * this to be called during the uart port registration when the
+	 * driver gets probed and the port should be mapped at that point.
+	 */
+	BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&ascport->port, co, baud, parity, bits, flow);
+}
+
+static struct console asc_console = {
+	.name		= ASC_SERIAL_NAME,
+	.device		= uart_console_device,
+	.write		= asc_console_write,
+	.setup		= asc_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &asc_uart_driver,
+};
+
+#define ASC_SERIAL_CONSOLE (&asc_console)
+
+#else
+#define ASC_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */
+
+static struct uart_driver asc_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= DRIVER_NAME,
+	.dev_name	= ASC_SERIAL_NAME,
+	.major		= 0,
+	.minor		= 0,
+	.nr		= ASC_MAX_PORTS,
+	.cons		= ASC_SERIAL_CONSOLE,
+};
+
+static const struct dev_pm_ops asc_serial_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
+};
+
+static struct platform_driver asc_serial_driver = {
+	.probe		= asc_serial_probe,
+	.remove		= asc_serial_remove,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.pm	= &asc_serial_pm_ops,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(asc_match),
+	},
+};
+
+static int __init asc_init(void)
+{
+	int ret;
+	static char banner[] __initdata =
+		KERN_INFO "STMicroelectronics ASC driver initialized\n";
+
+	printk(banner);
+
+	ret = uart_register_driver(&asc_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&asc_serial_driver);
+	if (ret)
+		uart_unregister_driver(&asc_uart_driver);
+
+	return ret;
+}
+
+static void __exit asc_exit(void)
+{
+	platform_driver_unregister(&asc_serial_driver);
+	uart_unregister_driver(&asc_uart_driver);
+}
+
+module_init(asc_init);
+module_exit(asc_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("STMicroelectronics (R&D) Limited");
+MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 74c2bf7..ec80e01 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -226,4 +226,7 @@
 /* Rocketport EXPRESS/INFINITY */
 #define PORT_RP2	102
 
+/* ST ASC type numbers */
+#define PORT_ASC       103
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 02/11] clocksource:global_timer: Add ARM global timer support.
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
  2013-06-10  9:21   ` [PATCH v2 01/11] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
@ 2013-06-10  9:21   ` Srinivas KANDAGATLA
       [not found]     ` <CACRpkdbQCRKBzRF4HzNsXHwXCLJJcFZ9T36GPmmYsnX1OfgGRg@mail.gmail.com>
  2013-06-10  9:21   ` [PATCH v2 03/11] regmap: Add regmap_field APIs Srinivas KANDAGATLA
                     ` (8 subsequent siblings)
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:21 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk,
	Rob Herring, Will Deacon

From: Stuart Menefy <stuart.menefy@st.com>

This is a simple driver for the global timer module found in the Cortex
A9-MP cores from revision r1p0 onwards. This should be able to perform
the functions of the system timer and the local timer in an SMP system.

The global timer has the following features:
    The global timer is a 64-bit incrementing counter with an
auto-incrementing feature. It continues incrementing after sending
interrupts. The global timer is memory mapped in the private memory
region.
    The global timer is accessible to all Cortex-A9 processors in the
cluster. Each Cortex-A9 processor has a private 64-bit comparator that
is used to assert a private interrupt when the global timer has reached
the comparator value. All the Cortex-A9 processors in a design use the
banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt
Controller as a Private Peripheral Interrupt. The global timer is
clocked by PERIPHCLK.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Rob Herring <robherring2@gmail.com>
CC: Linus Walleij <linus.walleij@linaro.org>
CC: Will Deacon <will.deacon@arm.com>
CC: Thomas Gleixner <tglx@linutronix.de>
---
 .../devicetree/bindings/arm/global_timer.txt       |   21 ++
 drivers/clocksource/Kconfig                        |   13 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/arm_global_timer.c             |  368 ++++++++++++++++++++
 4 files changed, 403 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/global_timer.txt
 create mode 100644 drivers/clocksource/arm_global_timer.c

diff --git a/Documentation/devicetree/bindings/arm/global_timer.txt b/Documentation/devicetree/bindings/arm/global_timer.txt
new file mode 100644
index 0000000..b64abac
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/global_timer.txt
@@ -0,0 +1,21 @@
+
+* ARM Global Timer
+	Cortex-A9 are often associated with a per-core Global timer.
+
+** Timer node required properties:
+
+- compatible : Should be "arm,cortex-a9-global-timer"
+		Driver supports versions r2p0 and above.
+
+- interrupts : One interrupt to each core
+
+- reg : Specify the base address and the size of the GT timer
+	register window.
+
+Example:
+
+	timer@2c000600 {
+		compatible = "arm,cortex-a9-global-timer";
+		reg = <0x2c000600 0x20>;
+		interrupts = <1 13 0xf01>;
+	};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f151c6c..b0c4c42 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -67,6 +67,19 @@ config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
 
+config ARM_GLOBAL_TIMER
+	bool
+	select CLKSRC_OF if OF
+	help
+	  This options enables support for the ARM global timer unit
+
+config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+	bool
+	depends on ARM_GLOBAL_TIMER
+	default y
+	help
+	 Use ARM global timer clock source as sched_clock
+
 config CLKSRC_METAG_GENERIC
 	def_bool y if METAG
 	help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8d979c7..b2363cb 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -28,4 +28,5 @@ obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= samsung_pwm_timer.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
+obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
new file mode 100644
index 0000000..e4bc4fe
--- /dev/null
+++ b/drivers/clocksource/arm_global_timer.c
@@ -0,0 +1,368 @@
+/*
+ * drivers/clocksource/arm_global_timer.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/sched_clock.h>
+#include <asm/mach/irq.h>
+#include <asm/cputype.h>
+#include <asm/localtimer.h>
+
+#define GT_COUNTER0	0x00
+#define GT_COUNTER1	0x04
+
+#define GT_CONTROL	0x08
+#define GT_CONTROL_TIMER_ENABLE		BIT(0)  /* this bit is NOT banked */
+#define GT_CONTROL_COMP_ENABLE		BIT(1)	/* banked */
+#define GT_CONTROL_IRQ_ENABLE		BIT(2)	/* banked */
+#define GT_CONTROL_AUTO_INC		BIT(3)	/* banked */
+
+#define GT_INT_STATUS	0x0c
+#define GT_INT_STATUS_EVENT_FLAG	BIT(0)
+
+#define GT_COMP0	0x10
+#define GT_COMP1	0x14
+#define GT_AUTO_INC	0x18
+
+/*
+ * We are expecting to be clocked by the ARM peripheral clock.
+ *
+ * Note: it is assumed we are using a prescaler value of zero, so this is
+ * the units for all operations.
+ */
+static void __iomem *gt_base;
+static unsigned long gt_clk_rate;
+static int gt_ppi;
+static struct clock_event_device __percpu **gt_evt;
+static DEFINE_PER_CPU(bool, percpu_init_called);
+static DEFINE_PER_CPU(struct clock_event_device, gt_clockevent);
+
+/*
+ * To get the value from the Global Timer Counter register proceed as follows:
+ * 1. Read the upper 32-bit timer counter register
+ * 2. Read the lower 32-bit timer counter register
+ * 3. Read the upper 32-bit timer counter register again. If the value is
+ *  different to the 32-bit upper value read previously, go back to step 2.
+ *  Otherwise the 64-bit timer counter value is correct.
+ */
+static u64 gt_counter_read(void)
+{
+	u64 counter;
+	u32 lower;
+	u32 upper, old_upper;
+
+	upper = __raw_readl(gt_base + GT_COUNTER1);
+	do {
+		old_upper = upper;
+		lower = __raw_readl(gt_base + GT_COUNTER0);
+		upper = __raw_readl(gt_base + GT_COUNTER1);
+	} while (upper != old_upper);
+
+	counter = upper;
+	counter <<= 32;
+	counter |= lower;
+	return counter;
+}
+
+/**
+ * To ensure that updates to comparator value register do not set the
+ * Interrupt Status Register proceed as follows:
+ * 1. Clear the Comp Enable bit in the Timer Control Register.
+ * 2. Write the lower 32-bit Comparator Value Register.
+ * 3. Write the upper 32-bit Comparator Value Register.
+ * 4. Set the Comp Enable bit and, if necessary, the IRQ enable bit.
+ */
+static void gt_compare_set(unsigned long delta, int periodic)
+{
+	u64 counter = gt_counter_read();
+	unsigned long ctrl = __raw_readl(gt_base + GT_CONTROL);
+
+	counter += delta;
+	ctrl &=  ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE);
+
+	__raw_writel(ctrl, gt_base + GT_CONTROL);
+	__raw_writel(lower_32_bits(counter), gt_base + GT_COMP0);
+	__raw_writel(upper_32_bits(counter), gt_base + GT_COMP1);
+
+	if (periodic) {
+		__raw_writel(delta, gt_base + GT_AUTO_INC);
+		ctrl |= GT_CONTROL_AUTO_INC;
+	}
+
+	ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
+	__raw_writel(ctrl, gt_base + GT_CONTROL);
+}
+
+static void gt_clockevent_set_mode(enum clock_event_mode mode,
+				   struct clock_event_device *clk)
+{
+	unsigned long ctrl;
+
+	ctrl = __raw_readl(gt_base + GT_CONTROL);
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		ctrl &= ~(GT_CONTROL_AUTO_INC);
+		__raw_writel(ctrl, gt_base + GT_CONTROL);
+		break;
+	/* Can not shut down it as enable bit is not banked */
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl &= ~(GT_CONTROL_COMP_ENABLE |
+				GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC);
+		__raw_writel(ctrl, gt_base + GT_CONTROL);
+		break;
+	default:
+		break;
+	}
+}
+
+static int gt_clockevent_set_next_event(unsigned long evt,
+					struct clock_event_device *unused)
+{
+	gt_compare_set(evt, 0);
+	return 0;
+}
+
+static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+	if (__raw_readl(gt_base + GT_INT_STATUS) & GT_INT_STATUS_EVENT_FLAG) {
+		/**
+		 * ERRATA 740657( Global Timer can send 2 interrupts for
+		 * the same event in single-shot mode)
+		 * Workaround:
+		 *	Either disable single-shot mode.
+		 *	Or
+		 *	Modify the Interrupt Handler to avoid the
+		 *	offending sequence. This is achieved by clearing
+		 *	the Global Timer flag _after_ having incremented
+		 *	the Comparator register	value to a higher value.
+		 */
+		if (!(__raw_readl(gt_base + GT_CONTROL) & GT_CONTROL_AUTO_INC))
+			gt_compare_set(ULONG_MAX, 0);
+
+		__raw_writel(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS);
+
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int __cpuinit gt_clockevents_init(struct clock_event_device *clk)
+{
+	struct clock_event_device **this_cpu_clk;
+	int cpu = smp_processor_id();
+
+	clk->name = "ARM global timer clock event";
+	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	clk->set_mode = gt_clockevent_set_mode;
+	clk->set_next_event = gt_clockevent_set_next_event;
+	this_cpu_clk = __this_cpu_ptr(gt_evt);
+	*this_cpu_clk = clk;
+	clk->cpumask = cpumask_of(cpu);
+	clk->irq = gt_ppi;
+	clockevents_config_and_register(clk, gt_clk_rate,
+					0, 0xffffffff);
+	per_cpu(percpu_init_called, cpu) = true;
+	enable_percpu_irq(clk->irq, IRQ_TYPE_NONE);
+	return 0;
+}
+
+static void gt_clockevents_stop(struct clock_event_device *clk)
+{
+	gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+	disable_percpu_irq(clk->irq);
+}
+
+static int __cpuinit gt_clockevents_setup(struct clock_event_device *clk)
+{
+	/* Use existing clock_event for boot cpu */
+	if (per_cpu(percpu_init_called, smp_processor_id()))
+		return 0;
+
+	/* already enabled in gt_clocksource_init. */
+	return gt_clockevents_init(clk);
+}
+
+static cycle_t gt_clocksource_read(struct clocksource *cs)
+{
+	return gt_counter_read();
+}
+
+static struct clocksource gt_clocksource = {
+	.name	= "ARM global timer clock source",
+	.rating	= 300,
+	.read	= gt_clocksource_read,
+	.mask	= CLOCKSOURCE_MASK(64),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+static u32 gt_sched_clock_read(void)
+{
+	if (!gt_base)
+		return 0;
+
+	return gt_counter_read();
+}
+#endif
+
+static void __init gt_clocksource_init(void)
+{
+	__raw_writel(0, gt_base + GT_CONTROL);
+	__raw_writel(0, gt_base + GT_COUNTER0);
+	__raw_writel(0, gt_base + GT_COUNTER1);
+	/* enables timer on all the cores */
+	__raw_writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+
+#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+	setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate);
+#endif
+	clocksource_register_hz(&gt_clocksource, gt_clk_rate);
+}
+
+static struct clk *gt_get_clock(void)
+{
+	struct clk *clk;
+	int err;
+
+	clk = clk_get_sys("gt", NULL);
+	if (IS_ERR(clk)) {
+		pr_err("global-timer: clock not found: %ld\n", PTR_ERR(clk));
+		return clk;
+	}
+
+	err = clk_prepare_enable(clk);
+	if (err) {
+		pr_err("global-timer: clock prepare+enable failed: %d\n", err);
+		clk_put(clk);
+		return ERR_PTR(err);
+	}
+
+	return clk;
+}
+
+static struct local_timer_ops gt_lt_ops __cpuinitdata = {
+	.setup	= gt_clockevents_setup,
+	.stop	= gt_clockevents_stop,
+};
+
+int __init global_timer_init(void __iomem *base, unsigned int timer_irq)
+{
+	unsigned int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(gt_clockevent, cpu);
+	int err = 0;
+	struct clk *gt_clk;
+
+	if (gt_base) {
+		pr_warn("global-timer: invalid base address\n");
+		return -EINVAL;
+	}
+
+	gt_clk = gt_get_clock();
+	if (IS_ERR(gt_clk)) {
+		pr_warn("global-timer: clk not found\n");
+		return -EINVAL;
+	}
+
+	gt_evt = alloc_percpu(struct clock_event_device *);
+	if (!gt_evt) {
+		pr_warn("global-timer: can't allocate memory\n");
+		return -ENOMEM;
+	}
+
+	err = request_percpu_irq(timer_irq, gt_clockevent_interrupt,
+				 "gt", gt_evt);
+	if (err) {
+		pr_warn("global-timer: can't register interrupt %d (%d)\n",
+			timer_irq, err);
+		goto out_free;
+	}
+
+	gt_base = base;
+	gt_clk_rate = clk_get_rate(gt_clk);
+	gt_ppi = timer_irq;
+	gt_clocksource_init();
+	gt_clockevents_init(evt);
+#ifdef CONFIG_LOCAL_TIMERS
+	err =  local_timer_register(&gt_lt_ops);
+	if (err) {
+		pr_warn("global-timer: unable to register local timer.\n");
+		goto out_irq;
+	}
+#endif
+	return 0;
+
+out_irq:
+	free_percpu_irq(timer_irq, gt_evt);
+out_free:
+	free_percpu(gt_evt);
+	return err;
+}
+
+#ifdef CONFIG_OF
+static void __init global_timer_of_register(struct device_node *np)
+{
+	struct clk *clk;
+	int err = 0;
+	int gt_ppi;
+	static void __iomem *gt_base;
+
+	/*
+	 * In r2p0 the comparators for each processor with the global timer
+	 * fire when the timer value is greater than or equal to. In previous
+	 * revisions the comparators fired when the timer value was equal to.
+	 */
+	if ((read_cpuid_id() & 0xf0000f) < 0x200000)
+		goto out;
+
+	gt_ppi = irq_of_parse_and_map(np, 0);
+	if (!gt_ppi) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	gt_base = of_iomap(np, 0);
+	if (!gt_base) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (!IS_ERR(clk))
+		clk_register_clkdev(clk, NULL, "gt");
+
+	global_timer_init(gt_base, gt_ppi);
+
+out:
+	WARN(err, "Global timer register failed (%d)\n", err);
+}
+
+/* Only tested on r2p2 and r3p0  */
+CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
+			global_timer_of_register);
+#endif
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 03/11] regmap: Add regmap_field APIs
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
  2013-06-10  9:21   ` [PATCH v2 01/11] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
  2013-06-10  9:21   ` [PATCH v2 02/11] clocksource:global_timer: Add ARM global timer support Srinivas KANDAGATLA
@ 2013-06-10  9:21   ` Srinivas KANDAGATLA
  2013-06-11 10:48     ` Mark Brown
  2013-06-10  9:22   ` [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support Srinivas KANDAGATLA
                     ` (7 subsequent siblings)
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:21 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk,
	Alexander Shiyan, Lars-Peter Clausen

It is common to access regmap registers at bit level, using
regmap_update_bits or regmap_read functions, however the end user has to
take care of a mask or shifting. This becomes overhead when such use
cases are high. Having a common function to do this is much convenient
and less error prone.

The idea of regmap_field is simple, regmap_field gives a logical
structure to bits of the regmap register, and the driver can use this
logical entity without the knowledge of the bit postions and masks all
over the code. This way code looks much neat and it need not handle the
masks, shifts every time it access the those entities.

With this new regmap_field_read/write apis the end user can setup a
regmap field using regmap_field_init and use the return regmap_field to
read write the register field without worrying about the masks or
shifts.

Also this apis will be usefull for drivers which are based on regmaps,
like some clocks or pinctrls which can work on the regmap_fields
directly without having to worry about bit positions.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Mark Brown <broonie@kernel.org>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Alexander Shiyan <shc_work@mail.ru>
CC: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/base/regmap/internal.h |    8 +++
 drivers/base/regmap/regmap.c   |  104 ++++++++++++++++++++++++++++++++++++++++
 include/linux/regmap.h         |   42 ++++++++++++++++
 3 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index c130536..c5f6ebd 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -174,6 +174,14 @@ struct regmap_range_node {
 	unsigned int window_len;
 };
 
+struct regmap_field {
+	struct regmap *regmap;
+	unsigned int mask;
+	/* lsb */
+	unsigned int shift;
+	unsigned int reg;
+};
+
 #ifdef CONFIG_DEBUG_FS
 extern void regmap_debugfs_initcall(void);
 extern void regmap_debugfs_init(struct regmap *map, const char *name);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index a941dcf..8d967cc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -801,6 +801,67 @@ struct regmap *devm_regmap_init(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_regmap_init);
 
+static void regmap_field_init(struct regmap_field *rm_field,
+	struct regmap *regmap, struct reg_field reg_field)
+{
+	int field_bits = reg_field.msb - reg_field.lsb + 1;
+	rm_field->regmap = regmap;
+	rm_field->reg = reg_field.reg;
+	rm_field->shift = reg_field.lsb;
+	rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
+}
+
+/**
+ * devm_regmap_field_alloc(): Allocate and initialise a register field
+ * in a register map.
+ *
+ * @dev: Device that will be interacted with
+ * @regmap: regmap bank in which this register field is located.
+ * @reg_field: Register field with in the bank.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap_field. The regmap_field will be automatically freed
+ * by the device management code.
+ */
+struct regmap_field *devm_regmap_field_alloc(struct device *dev,
+		struct regmap *regmap, struct reg_field reg_field)
+{
+	struct regmap_field *rm_field = devm_kzalloc(dev,
+					sizeof(*rm_field), GFP_KERNEL);
+	if (!rm_field)
+		return ERR_PTR(-ENOMEM);
+
+	regmap_field_init(rm_field, regmap, reg_field);
+
+	return rm_field;
+
+}
+EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
+/**
+ * regmap_field_alloc(): Allocate and initialise a register field
+ * in a register map.
+ *
+ * @regmap: regmap bank in which this register field is located.
+ * @reg_field: Register field with in the bank.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap_field. The regmap_field should be freed by the
+ * user once its finished working with it using regmap_field_free().
+ */
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+		struct reg_field reg_field)
+{
+	struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
+
+	if (!rm_field)
+		return ERR_PTR(-ENOMEM);
+
+	regmap_field_init(rm_field, regmap, reg_field);
+
+	return rm_field;
+}
+EXPORT_SYMBOL_GPL(regmap_field_alloc);
+
 /**
  * regmap_reinit_cache(): Reinitialise the current register cache
  *
@@ -1249,6 +1310,23 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(regmap_raw_write);
 
+/**
+ * regmap_field_write(): Write a value to a single register field
+ *
+ * @field: Register field to write to
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int regmap_field_write(struct regmap_field *field, unsigned int val)
+{
+	return regmap_update_bits(field->regmap, field->reg,
+				field->mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_field_write);
+
 /*
  * regmap_bulk_write(): Write multiple registers to the device
  *
@@ -1532,6 +1610,32 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 EXPORT_SYMBOL_GPL(regmap_raw_read);
 
 /**
+ * regmap_field_read(): Read a value to a single register field
+ *
+ * @field: Register field to read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val)
+{
+	int ret;
+	unsigned int reg_val;
+	ret = regmap_read(field->regmap, field->reg, &reg_val);
+	if (ret != 0)
+		return ret;
+
+	reg_val &= field->mask;
+	reg_val >>= field->shift;
+	*val = reg_val;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_field_read);
+
+/**
  * regmap_bulk_read(): Read multiple registers from the device
  *
  * @map: Register map to write to
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 02d84e2..557a54e 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -15,6 +15,8 @@
 
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <linux/device.h>
+#include <linux/slab.h>
 
 struct module;
 struct device;
@@ -23,6 +25,7 @@ struct irq_domain;
 struct spi_device;
 struct regmap;
 struct regmap_range_cfg;
+struct regmap_field;
 
 /* An enum of all the supported cache types */
 enum regcache_type {
@@ -412,6 +415,45 @@ bool regmap_reg_in_ranges(unsigned int reg,
 			  unsigned int nranges);
 
 /**
+ * Description of an register field
+ *
+ * @reg: Offset of the register within the regmap bank
+ * @lsb: lsb of the register field.
+ * @reg: msb of the register field.
+ */
+struct reg_field {
+	unsigned int reg;
+	unsigned int lsb;
+	unsigned int msb;
+};
+
+#define REG_FIELD(_reg, _lsb, _msb) {		\
+				.reg = _reg,	\
+				.lsb = _lsb,	\
+				.msb = _msb,	\
+				}
+
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+		struct reg_field reg_field);
+
+struct regmap_field *devm_regmap_field_alloc(struct device *dev,
+		struct regmap *regmap, struct reg_field reg_field);
+
+static inline void regmap_field_free(struct regmap_field *field)
+{
+	kfree(field);
+}
+
+static inline void devm_regmap_field_free(struct device *dev,
+	struct regmap_field *field)
+{
+	devm_kfree(dev, field);
+}
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val);
+int regmap_field_write(struct regmap_field *field, unsigned int val);
+
+/**
  * Description of an IRQ for the generic regmap irq_chip.
  *
  * @reg_offset: Offset of the status/mask register within the bank
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (2 preceding siblings ...)
  2013-06-10  9:21   ` [PATCH v2 03/11] regmap: Add regmap_field APIs Srinivas KANDAGATLA
@ 2013-06-10  9:22   ` Srinivas KANDAGATLA
       [not found]     ` <CACRpkdaW2ALTWCB7Rd8m=aAGQwh3T_dJVncxJn_eXer4X3J6_g@mail.gmail.com>
  2013-06-10  9:22   ` [PATCH v2 05/11] pinctrl:stixxxx: Add pinctrl and pinconf support Srinivas KANDAGATLA
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

System configuration(aka syscfg) registers are very basic configuration
registers arranged in groups across ST Settop Box parts.

The SOCs are assembled from existing IP blocks, which don't change very
often. However these blocks are assembled in different configurations to
meet the device requirements. So most IP blocks as well as having a bus
interface through which their own registers are accessible, will also
have a number of bristles(wires) which are signals that are going in and
out of the IP for configuration and status. To make these signals
accessible to software they are wired to "System Configuration
Registers".

Drivers target the IP blocks, which don't change much. Where as the
mapping of IP specific bristles(wires) to "System Configuration
Registers" do change per each SOC, and therefore we do not want this
information to be part of the driver.

Having a System Configuration infrastructure gives much flexibility and
abstraction to drivers to configure them. Typically in a SOC there will
be more than hundreds of these registers, which are again divided into
groups. The IP related config registers tend to much regular in latest
ST SOCs, so having a common place for configuring these registers makes
sense and avoid lot of code duplication.

This mfd driver provides higher level inialization routines for various
IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
get to syscfg registers via standard regmap api which is usefull for
drivers like pinctrl.

This patch adds support to ST System Configuration registers, which can
be configured by the drivers.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Linus Walleij <linus.walleij@linaro.org>
CC: Mark Brown <broonie@kernel.org>
---
 .../devicetree/bindings/mfd/stixxxx-syscfg.txt     |   18 ++
 drivers/mfd/Kconfig                                |   10 ++
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/stixxxx-syscfg.c                       |  168 ++++++++++++++++++++
 include/linux/mfd/stixxxx-syscfg.h                 |   15 ++
 5 files changed, 212 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
 create mode 100644 drivers/mfd/stixxxx-syscfg.c
 create mode 100644 include/linux/mfd/stixxxx-syscfg.h

diff --git a/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
new file mode 100644
index 0000000..428c751
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stixxxx-syscfg.txt
@@ -0,0 +1,18 @@
+*STixxxx SYSCFG
+
+- compatible : should be "st,<SOC>-syscfg" like "st,stih415-syscfg"
+			or "st,stih416-syscfg".
+- reg, reg-names, interrupts, interrupt-names	: Standard way to define device
+			resources with names. look in
+			Documentation/devicetree/bindings/resource-names.txt
+- syscfg-range <start size> : Should be syscfg number range for this bank.
+- syscfg-name		    : Should be name of the syscfg, will be used in debugfs.
+
+Example of a SBC_SYSCFG bank node:
+
+syscfg_sbc: syscfg@fe600000{
+	compatible      = "st,stih415-syscfg";
+	reg		= <0xfe600000 0xb4>;
+	syscfg-range	= <0 44>;
+	syscfg-name	= "SYSCFG_SBC";
+};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d54e985..af49b58 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -649,6 +649,16 @@ config MFD_STA2X11
 	select MFD_CORE
 	select REGMAP_MMIO
 
+config MFD_STIXXXX_SYSCFG
+	bool "ST System Configuration Registers(aka syscfg) via regmap"
+	select REGMAP_MMIO
+	help
+	  Select this option to enable accessing STMicroelectronics
+	  System Configuration Registers via standard regmap apis with
+	  lookup helper functions.
+
+	  If unsure, say N.
+
 config MFD_SYSCON
 	bool "System Controller Register R/W Based on Regmap"
 	select REGMAP_MMIO
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 718e94a..c1f6570 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
 obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
 obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
+obj-$(CONFIG_MFD_STIXXXX_SYSCFG)	+= stixxxx-syscfg.o
 obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
 obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
diff --git a/drivers/mfd/stixxxx-syscfg.c b/drivers/mfd/stixxxx-syscfg.c
new file mode 100644
index 0000000..10ea4e4
--- /dev/null
+++ b/drivers/mfd/stixxxx-syscfg.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Syscfg driver is used to configure various devices like Ethernet,
+ * USB, PCIE, SATA and so on.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/stixxxx-syscfg.h>
+
+#define DRIVER_NAME "stixxxx-syscfg"
+
+static struct platform_driver syscfg_driver;
+struct syscfg {
+	void __iomem *base;
+	struct regmap *regmap;
+	int	start, end;
+	const char *name;
+	struct device_node *of_node;
+};
+
+static int syscfg_match_name(struct device *dev, void *data)
+{
+	struct syscfg *syscfg = dev_get_drvdata(dev);
+
+	if (syscfg)
+		if (!strcmp(syscfg->name, (const char *)data))
+			return 1;
+	return 0;
+}
+
+struct regmap *syscfg_regmap_lookup_by_name(const char *name)
+{
+	struct syscfg *syscfg;
+	struct device *dev;
+
+	dev = driver_find_device(&syscfg_driver.driver, NULL, (void *)name,
+				 syscfg_match_name);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	syscfg = dev_get_drvdata(dev);
+
+	return syscfg->regmap;
+}
+
+static int syscfg_match_node(struct device *dev, void *data)
+{
+	struct device_node *dn = data;
+
+	return (dev->of_node == dn) ? 1 : 0;
+}
+
+struct regmap *syscfg_node_to_regmap(struct device_node *np)
+{
+	struct syscfg *syscfg;
+	struct device *dev;
+
+	dev = driver_find_device(&syscfg_driver.driver, NULL, np,
+				 syscfg_match_node);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	syscfg = dev_get_drvdata(dev);
+
+	return syscfg->regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_node_to_regmap);
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+					const char *property)
+{
+	struct device_node *syscfg_np;
+	struct regmap *regmap;
+
+	syscfg_np = of_parse_phandle(np, property, 0);
+	if (!syscfg_np)
+		return ERR_PTR(-ENODEV);
+
+	regmap = syscfg_node_to_regmap(syscfg_np);
+	of_node_put(syscfg_np);
+
+	return regmap;
+}
+EXPORT_SYMBOL_GPL(syscfg_regmap_lookup_by_phandle);
+
+static struct regmap_config syscfg_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int syscfg_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct syscfg *syscfg;
+	struct resource *res;
+	u32 range[2];
+
+	if (!np)
+		return -EINVAL;
+
+	syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
+	if (!syscfg)
+		return -ENOMEM;
+
+	syscfg->of_node = np;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	syscfg->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!syscfg->base) {
+		dev_err(&pdev->dev, "Unable to ioremap registers|\n");
+		return -ENODATA;
+	}
+
+	of_property_read_u32_array(np, "syscfg-range", (u32 *)&range, 2);
+	syscfg->start = range[0];
+	syscfg->end = range[0] + range[1];
+	of_property_read_string(np, "syscfg-name", &syscfg->name);
+
+	syscfg_regmap_config.name = kasprintf(GFP_KERNEL, "%s", syscfg->name);
+	syscfg_regmap_config.max_register = res->end - res->start - 3;
+	syscfg->regmap = devm_regmap_init_mmio(&pdev->dev, syscfg->base,
+					&syscfg_regmap_config);
+	if (IS_ERR(syscfg->regmap)) {
+		dev_err(&pdev->dev, "regmap init failed\n");
+		return PTR_ERR(syscfg->regmap);
+	}
+
+	platform_set_drvdata(pdev, syscfg);
+	dev_info(&pdev->dev,
+		"%s[%d - %d] sucessfully intialized\n",
+		syscfg->name, syscfg->start, syscfg->end);
+	return 0;
+}
+
+static struct of_device_id syscfg_match[] = {
+	{ .compatible = "st,stih415-syscfg", },
+	{ .compatible = "st,stih416-syscfg", },
+	{},
+};
+
+static struct platform_driver syscfg_driver = {
+	.probe		= syscfg_probe,
+	.driver	= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(syscfg_match),
+	},
+};
+
+static int __init syscfg_init(void)
+{
+	return platform_driver_register(&syscfg_driver);
+}
+postcore_initcall(syscfg_init);
diff --git a/include/linux/mfd/stixxxx-syscfg.h b/include/linux/mfd/stixxxx-syscfg.h
new file mode 100644
index 0000000..18ed6da7
--- /dev/null
+++ b/include/linux/mfd/stixxxx-syscfg.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+
+#ifndef __LINUX_MFD_STIXXXX_SYSCFG_H
+#define __LINUX_MFD_STIXXXX_SYSCFG_H
+
+struct regmap *syscfg_regmap_lookup_by_phandle(struct device_node *np,
+					const char *property);
+struct regmap *syscfg_regmap_lookup_by_name(const char *name);
+
+#endif /* __LINUX_MFD_STIXXXX_SYSCFG_H */
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 05/11] pinctrl:stixxxx: Add pinctrl and pinconf support.
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (3 preceding siblings ...)
  2013-06-10  9:22   ` [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support Srinivas KANDAGATLA
@ 2013-06-10  9:22   ` Srinivas KANDAGATLA
  2013-06-10  9:26   ` =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

This patch add pinctrl support to ST SoCs.

About hardware:
ST Set-Top-Box parts have two blocks called PIO and PIO-mux which handle
pin configurations.

Each multi-function pin is controlled, driven and routed through the PIO
multiplexing block. Each pin supports GPIO functionality (ALT0) and
multiple alternate functions(ALT1 - ALTx) that directly connect the pin
to different hardware blocks. When a pin is in GPIO mode, Output Enable
(OE), Open Drain(OD), and Pull Up (PU) are driven by the related PIO
block. Otherwise the PIO multiplexing block configures these parameters
and retiming the signal.

About driver:
This pinctrl driver manages both PIO and PIO-mux block using pinctrl,
pinconf, pinmux, gpio subsystems. All the pinctrl related config
information can only come from device trees.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 .../bindings/pinctrl/pinctrl-stixxxx.txt           |  116 ++
 drivers/pinctrl/Kconfig                            |   11 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-stixxxx.c                  | 1212 ++++++++++++++++++++
 drivers/pinctrl/pinctrl-stixxxx.h                  |  197 ++++
 5 files changed, 1537 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
 create mode 100644 drivers/pinctrl/pinctrl-stixxxx.c
 create mode 100644 drivers/pinctrl/pinctrl-stixxxx.h

diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
new file mode 100644
index 0000000..ac69dca
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stixxxx.txt
@@ -0,0 +1,116 @@
+*ST pin controller.
+
+Each multi-function pin is controlled, driven and routed through the
+PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
+and multiple alternate functions(ALT1 - ALTx) that directly connect
+the pin to different hardware blocks.
+
+When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
+Pull Up (PU) are driven by the related PIO block.
+
+ST pinctrl driver controls PIO multiplexing block and also interacts with
+gpio driver to configure a pin.
+
+Required properties: (PIO multiplexing block)
+- compatible	: should be "st,stixxxx-pinctrl"
+			each subnode should set "st,stixxxx-gpio"
+			as compatible for each gpio-controller bank.
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells	  : Should be one. The first cell is the pin number.
+- st,retime-in-delay	: Should be array of delays in nsecs.
+- st,retime-out-delay	: Should be array of delays in nsecs.
+- st,retime-pin-mask	: Should be mask to specify which pins can be retimed.
+- st,bank-name		: Should be a name string for this bank.
+- st,syscfg		: phandle of the syscfg node.
+- st,syscfg-offsets	: Should be a 5 cell entry which represent offset of altfunc,
+	output-enable, pull-up , open drain and retime registers in the syscfg bank
+
+Example:
+	pin-controller {
+		compatible = "st,stixxxx-pinctrl", "simple-bus";
+		st,retime-in-delay = <0 500 1000 1500>;
+		st,retime-out-delay = <0 1000 2000 3000>;
+		st,syscfg		= <&syscfg_front>;
+		st,syscfg-offsets	= <0 8 10 12 16>;
+		ranges;
+		PIO0: pinctrl@fe610000 {
+			gpio-controller;
+			#gpio-cells = <1>;
+			compatible = "st,stixxxx-gpio";
+			reg = <0xfe610000 0x100>;
+			st,bank-name  = "PIO0";
+		};
+		...
+		pin-functions nodes follow...
+	};
+
+
+Contents of function subnode node:
+----------------------
+Required properties for pin configuration node:
+- st,function	: Should be alternate function number associated
+		with this set of pins. Use same numbers from datasheet.
+
+- st,pins	: Child node with list of pins with configuration.
+
+Below is the format of how each pin conf should look like.
+
+<bank offset mode rt_type rt_delay rt_clk>
+
+Every PIO is represented with 4-7 parameters depending on retime configuration.
+Each parameter is explained as below.
+
+-bank		: Should be bank phandle to which this PIO belongs.
+-offset		: Offset in the PIO bank.
+-mode		:pin configuration is selected from one of the below values.
+		IN
+		IN_PU
+		OUT
+		BIDIR
+		BIDIR_PU
+
+-rt_type	Retiming Configuration for the pin.
+		Possible retime configuration are:
+
+		-------		-------------
+		value		args
+		-------		-------------
+		NICLK		<delay> <clk>
+		ICLK_IO		<delay> <clk>
+		BYPASS		<delay>
+		DE_IO		<delay> <clk>
+		SE_ICLK_IO	<delay> <clk>
+		SE_NICLK_IO	<delay> <clk>
+
+- delay	is retime delay in pico seconds.
+		Possible values are: refer to retime-in/out-delays
+
+- rt_clk	:clk to be use for retime.
+		Possible values are:
+		CLK_A
+		CLK_B
+		CLK_C
+		CLK_D
+
+Example of mmcclk pin which is a bi-direction pull pu with retime config
+as non inverted clock retimed with CLK_B and delay of 0 pico seconds:
+
+pin-controller {
+	...
+	mmc0 {
+		pinctrl_mmc: mmc {
+			st,function = <ALT4>;
+			st,pins {
+				mmcclk = <&PIO13 4 BIDIR_PU NICLK  0  CLK_B>;
+				...
+			};
+		};
+	...
+	};
+};
+
+sdhci0:sdhci@fe810000{
+	...
+	pinctrl-names = "default";
+	pinctrl-0	= <&pinctrl_mmc>;
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f66924..0c040a3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -169,6 +169,17 @@ config PINCTRL_SUNXI
 	select PINMUX
 	select GENERIC_PINCONF
 
+config PINCTRL_STIXXXX
+	bool "ST Microelectronics pin controller driver for STixxxx SoCs"
+	select PINMUX
+	select PINCONF
+	help
+	  Say yes here to support pinctrl interface on STixxxx SOCs.
+	  This driver is used to control both PIO block and PIO-mux
+	  block to configure a pin.
+
+	  If unsure, say N.
+
 config PINCTRL_TEGRA
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 9bdaeb8..0e035bb 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_EXYNOS5440)	+= pinctrl-exynos5440.o
 obj-$(CONFIG_PINCTRL_S3C64XX)	+= pinctrl-s3c64xx.o
 obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_STIXXXX) 	+= pinctrl-stixxxx.o
 
 obj-$(CONFIG_PLAT_ORION)        += mvebu/
 obj-$(CONFIG_ARCH_SHMOBILE)	+= sh-pfc/
diff --git a/drivers/pinctrl/pinctrl-stixxxx.c b/drivers/pinctrl/pinctrl-stixxxx.c
new file mode 100644
index 0000000..da4e3d7
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.c
@@ -0,0 +1,1212 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ *	Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/stixxxx-syscfg.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/platform_device.h>
+#include "core.h"
+#include "pinctrl-stixxxx.h"
+
+struct stixxxx_pinconf {
+	int		pin;
+	const char	*name;
+	unsigned long	config;
+};
+
+struct stixxxx_pmx_func {
+	const char	*name;
+	const char	**groups;
+	unsigned	ngroups;
+};
+
+struct stixxxx_pctl_group {
+	const char		*name;
+	unsigned int		*pins;
+	unsigned		npins;
+	int			altfunc;
+	struct stixxxx_pinconf	*pin_conf;
+};
+
+#define to_stixxxx_gpio_port(chip) \
+		container_of(chip, struct stixxxx_gpio_port, gpio_chip)
+
+struct stixxxx_gpio_port {
+	struct gpio_chip	gpio_chip;
+	struct pinctrl_gpio_range range;
+	void __iomem		*base;
+	struct device_node	*of_node;
+	const char		*bank_name;
+};
+
+static struct stixxxx_gpio_port *gpio_ports[STIXXXX_MAX_GPIO_BANKS];
+
+struct stixxxx_pinctrl {
+	struct device			*dev;
+	struct pinctrl_dev		*pctl;
+	int				nbanks;
+	struct stixxxx_pmx_func		*functions;
+	int				nfunctions;
+	struct stixxxx_pctl_group	*groups;
+	int				ngroups;
+	struct stixxxx_pio_control	*pio_controls;
+	struct pinctrl_gpio_range	**gpio_ranges;
+	struct regmap			*regmap;
+};
+
+/* Low level functions.. */
+static void stixxxx_pinconf_set_direction(struct stixxxx_pio_control *pc,
+				int pin_id, unsigned long config)
+{
+	struct regmap_field *output_enable;
+	struct regmap_field *pull_up;
+	struct regmap_field *open_drain;
+	unsigned int oe_value, pu_value, od_value;
+	unsigned long mask;
+	int pin = stixxxx_gpio_pin(pin_id);
+
+	output_enable = pc->oe;
+	pull_up = pc->pu;
+	open_drain = pc->od;
+
+	mask = BIT(pin);
+
+	regmap_field_read(output_enable, &oe_value);
+	regmap_field_read(pull_up, &pu_value);
+	regmap_field_read(open_drain, &od_value);
+
+	/* Clear old values */
+	oe_value &= ~mask;
+	pu_value &= ~mask;
+	od_value &= ~mask;
+
+	if (config & STIXXXX_PINCONF_OE)
+		oe_value |= mask;
+	if (config & STIXXXX_PINCONF_PU)
+		pu_value |= mask;
+	if (config & STIXXXX_PINCONF_OD)
+		od_value |= mask;
+
+	regmap_field_write(output_enable, oe_value);
+	regmap_field_write(pull_up, pu_value);
+	regmap_field_write(open_drain, od_value);
+}
+
+static void stixxxx_pctl_set_function(struct stixxxx_pio_control *pc,
+				int pin_id, int function)
+{
+	struct regmap_field *selector;
+	int offset;
+	unsigned int val;
+	int pin = stixxxx_gpio_pin(pin_id);
+
+	selector = pc->alt;
+	offset = pin * 4;
+	regmap_field_read(selector, &val);
+	val &= ~(0xf << offset);
+	val |= function << offset;
+	regmap_field_write(selector, val);
+}
+
+static unsigned long stixxxx_pinconf_delay_to_bit(unsigned int delay,
+		const struct stixxxx_retime_params *rt_params,
+		unsigned long config)
+{
+	unsigned int *delay_times;
+	int num_delay_times, i, closest_index = -1;
+	unsigned int closest_divergence = UINT_MAX;
+
+	if (STIXXXX_PINCONF_UNPACK_OE(config)) {
+		delay_times = rt_params->delay_times_out;
+		num_delay_times = rt_params->num_delay_times_out;
+	} else {
+		delay_times = rt_params->delay_times_in;
+		num_delay_times = rt_params->num_delay_times_in;
+	}
+
+	for (i = 0; i < num_delay_times; i++) {
+		unsigned int divergence = abs(delay - delay_times[i]);
+
+		if (divergence == 0)
+			return i;
+
+		if (divergence < closest_divergence) {
+			closest_divergence = divergence;
+			closest_index = i;
+		}
+	}
+
+	pr_warn("Attempt to set delay %d, closest available %d\n",
+	     delay, delay_times[closest_index]);
+
+	return closest_index;
+}
+
+static unsigned long stixxxx_pinconf_bit_to_delay(unsigned int index,
+		const struct stixxxx_retime_params *rt_params,
+		unsigned long output)
+{
+	unsigned int *delay_times;
+	int num_delay_times;
+
+	if (output) {
+		delay_times = rt_params->delay_times_out;
+		num_delay_times = rt_params->num_delay_times_out;
+	} else {
+		delay_times = rt_params->delay_times_in;
+		num_delay_times = rt_params->num_delay_times_in;
+	}
+
+	if (index < num_delay_times) {
+		return delay_times[index];
+	} else {
+		pr_warn("Delay not found in/out delay list\n");
+		return 0;
+	}
+}
+
+static void stixxxx_pinconf_set_retime_packed(
+		struct stixxxx_pio_control *pc,
+		unsigned long config, int pin)
+{
+	const struct stixxxx_retime_params *rt_params = pc->rt_params;
+	const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+	struct regmap_field **regs;
+	unsigned int values[2];
+	unsigned long mask;
+	int i, j;
+	int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+	int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+	int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+	int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+	int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+	unsigned long delay = stixxxx_pinconf_delay_to_bit(
+			STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+			pc->rt_params, config);
+
+	unsigned long rt_cfg =
+		((clk		& 1) << offset->clk1notclk0_offset) |
+		((clknotdata	& 1) << offset->clknotdata_offset) |
+		((delay		& 1) << offset->delay_lsb_offset) |
+		(((delay >> 1)  & 1) << offset->delay_msb_offset) |
+		((double_edge	& 1) << offset->double_edge_offset) |
+		((invertclk	& 1) << offset->invertclk_offset) |
+		((retime	& 1) << offset->retime_offset);
+
+	regs = pc->retiming;
+	regmap_field_read(regs[0], &values[0]);
+	regmap_field_read(regs[1], &values[1]);
+
+	for (i = 0; i < 2; i++) {
+		mask = BIT(pin);
+		for (j = 0; j < 4; j++) {
+			if (rt_cfg & 1)
+				values[i] |= mask;
+			else
+				values[i] &= ~mask;
+			mask <<= 8;
+			rt_cfg >>= 1;
+		}
+	}
+
+	regmap_field_write(regs[0], values[0]);
+	regmap_field_write(regs[1], values[1]);
+}
+
+static void stixxxx_pinconf_set_retime_dedicated(
+	struct stixxxx_pio_control *pc,
+	unsigned long config, int pin)
+{
+	struct regmap_field *reg;
+	int input = STIXXXX_PINCONF_UNPACK_OE(config) ? 0 : 1;
+	int clk = STIXXXX_PINCONF_UNPACK_RT_CLK(config);
+	int clknotdata = STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config);
+	int double_edge = STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config);
+	int invertclk = STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config);
+	int retime = STIXXXX_PINCONF_UNPACK_RT(config);
+	unsigned long delay = stixxxx_pinconf_delay_to_bit(
+			STIXXXX_PINCONF_UNPACK_RT_DELAY(config),
+			pc->rt_params, config);
+
+	unsigned long retime_config =
+		((clk		& 0x3) << 0) |
+		((clknotdata	& 0x1) << 2) |
+		((delay		& 0xf) << 3) |
+		((input		& 0x1) << 7) |
+		((double_edge	& 0x1) << 8) |
+		((invertclk	& 0x1) << 9) |
+		((retime	& 0x1) << 10);
+
+	reg = pc->retiming[pin];
+	regmap_field_write(reg, retime_config);
+}
+
+static void stixxxx_pinconf_get_direction(struct stixxxx_pio_control *pc,
+	int pin_id, unsigned long *config)
+{
+	unsigned int oe_value, pu_value, od_value;
+	int pin = stixxxx_gpio_pin(pin_id);
+
+	regmap_field_read(pc->oe, &oe_value);
+	regmap_field_read(pc->pu, &pu_value);
+	regmap_field_read(pc->od, &od_value);
+
+	oe_value = (oe_value >> pin) & 1;
+	pu_value = (pu_value >> pin) & 1;
+	od_value = (od_value >> pin) & 1;
+
+	STIXXXX_PINCONF_PACK_OE(*config, oe_value);
+	STIXXXX_PINCONF_PACK_PU(*config, pu_value);
+	STIXXXX_PINCONF_PACK_OD(*config, od_value);
+}
+
+static int stixxxx_pinconf_get_retime_packed(
+		struct stixxxx_pio_control *pc,
+		int pin, unsigned long *config)
+{
+	const struct stixxxx_retime_params *rt_params = pc->rt_params;
+	const struct stixxxx_retime_offset *offset = rt_params->retime_offset;
+	unsigned long delay_bits, delay, rt_reduced;
+	unsigned int rt_value[2];
+	int i, j;
+	int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+	regmap_field_read(pc->retiming[0], &rt_value[0]);
+	regmap_field_read(pc->retiming[1], &rt_value[1]);
+
+	rt_reduced = 0;
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < 4; j++) {
+			if (rt_value[i] & (1<<((8*j)+pin)))
+				rt_reduced |= 1 << ((i*4)+j);
+		}
+	}
+
+	STIXXXX_PINCONF_PACK_RT(*config,
+			(rt_reduced >> offset->retime_offset) & 1);
+	STIXXXX_PINCONF_PACK_RT_CLK(*config,
+			(rt_reduced >> offset->clk1notclk0_offset) & 1);
+	STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config,
+			(rt_reduced >> offset->clknotdata_offset) & 1);
+	STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config,
+			(rt_reduced >> offset->double_edge_offset) & 1);
+	STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config,
+			(rt_reduced >> offset->invertclk_offset) & 1);
+
+	delay_bits =  (((rt_reduced >> offset->delay_msb_offset) & 1)<<1) |
+			((rt_reduced >> offset->delay_lsb_offset) & 1);
+	delay =  stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+	STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+	return 0;
+}
+
+static int stixxxx_pinconf_get_retime_dedicated(
+		struct stixxxx_pio_control *pc,
+		int pin, unsigned long *config)
+{
+	unsigned int value;
+	unsigned long delay_bits, delay;
+	const struct stixxxx_retime_params *rt_params = pc->rt_params;
+	int output = STIXXXX_PINCONF_UNPACK_OE(*config);
+
+	regmap_field_read(pc->retiming[pin], &value);
+	STIXXXX_PINCONF_PACK_RT_CLK(*config, ((value >> 0) & 0x3));
+	STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(*config, ((value >> 2) & 0x1));
+	delay_bits = ((value >> 3) & 0xf);
+	delay =  stixxxx_pinconf_bit_to_delay(delay_bits, rt_params, output);
+	STIXXXX_PINCONF_PACK_RT_DELAY(*config, delay);
+	STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(*config, ((value >> 8) & 0x1));
+	STIXXXX_PINCONF_PACK_RT_INVERTCLK(*config, ((value >> 9) & 0x1));
+	STIXXXX_PINCONF_PACK_RT(*config, ((value >> 10) & 0x1));
+
+	return 0;
+}
+
+/* GPIO related functions */
+
+static inline void __stixxxx_gpio_set(struct stixxxx_gpio_port *port,
+	unsigned offset, int value)
+{
+	if (value)
+		writel(BIT(offset), port->base + REG_PIO_SET_POUT);
+	else
+		writel(BIT(offset), port->base + REG_PIO_CLR_POUT);
+}
+
+static void stixxxx_gpio_direction(unsigned int gpio, unsigned int direction)
+{
+	int port_num = stixxxx_gpio_port(gpio);
+	int offset = stixxxx_gpio_pin(gpio);
+	struct stixxxx_gpio_port *port  = gpio_ports[port_num];
+	int i = 0;
+
+	for (i = 0; i <= 2; i++) {
+		if (direction & BIT(i))
+			writel(BIT(offset), port->base + REG_PIO_SET_PC(i));
+		else
+			writel(BIT(offset), port->base + REG_PIO_CLR_PC(i));
+	}
+}
+
+static int stixxxx_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void stixxxx_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static int stixxxx_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+	return (readl(port->base + REG_PIO_PIN) >> offset) & 1;
+}
+
+static void stixxxx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+	__stixxxx_gpio_set(port, offset, value);
+}
+
+static int stixxxx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_gpio_direction_input(chip->base + offset);
+	return 0;
+}
+
+static int stixxxx_gpio_direction_output(struct gpio_chip *chip,
+	unsigned offset, int value)
+{
+	struct stixxxx_gpio_port *port = to_stixxxx_gpio_port(chip);
+
+	__stixxxx_gpio_set(port, offset, value);
+	pinctrl_gpio_direction_output(chip->base + offset);
+
+	return 0;
+}
+
+static int stixxxx_gpio_xlate(struct gpio_chip *gc,
+			const struct of_phandle_args *gpiospec, u32 *flags)
+{
+	if (WARN_ON(gc->of_gpio_n_cells < 1))
+		return -EINVAL;
+
+	if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+		return -EINVAL;
+
+	if (gpiospec->args[0] > gc->ngpio)
+		return -EINVAL;
+
+	return gpiospec->args[0];
+}
+
+/* Pinctrl Groups */
+static int stixxxx_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->ngroups;
+}
+
+static const char *stixxxx_pctl_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->groups[selector].name;
+}
+
+static int stixxxx_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+	unsigned selector, const unsigned **pins, unsigned *npins)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pins;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static const inline struct stixxxx_pctl_group *stixxxx_pctl_find_group_by_name(
+	const struct stixxxx_pinctrl *info, const char *name)
+{
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (!strcmp(info->groups[i].name, name))
+			return &info->groups[i];
+	}
+
+	return NULL;
+}
+
+static int stixxxx_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+	struct device_node *np, struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	const struct stixxxx_pctl_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num, i;
+
+	grp = stixxxx_pctl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	map_num = grp->npins + 1;
+	new_map = devm_kzalloc(pctldev->dev,
+				sizeof(*new_map) * map_num, GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+
+	*map = new_map;
+	*num_maps = map_num;
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map per pin */
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = &grp->pin_conf[i].config;
+		new_map[i].data.configs.num_configs = 1;
+	}
+	dev_info(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, grp->name, map_num);
+
+	return 0;
+}
+
+static void stixxxx_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops stixxxx_pctlops = {
+	.get_groups_count	= stixxxx_pctl_get_groups_count,
+	.get_group_pins		= stixxxx_pctl_get_group_pins,
+	.get_group_name		= stixxxx_pctl_get_group_name,
+	.dt_node_to_map		= stixxxx_pctl_dt_node_to_map,
+	.dt_free_map		= stixxxx_pctl_dt_free_map,
+};
+
+/* Pinmux */
+static int stixxxx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->nfunctions;
+}
+
+const char *stixxxx_pmx_get_fname(struct pinctrl_dev *pctldev,
+	unsigned selector)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+	return info->functions[selector].name;
+}
+
+static int stixxxx_pmx_get_groups(struct pinctrl_dev *pctldev,
+	unsigned selector, const char * const **grps, unsigned * const ngrps)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	*grps = info->functions[selector].groups;
+	*ngrps = info->functions[selector].ngroups;
+
+	return 0;
+}
+
+static struct stixxxx_pio_control *stixxxx_get_pio_control(
+			struct stixxxx_pinctrl *info, int pin_id)
+{
+	int index = stixxxx_gpio_port(pin_id) - info->gpio_ranges[0]->id;
+	return &info->pio_controls[index];
+}
+
+static int stixxxx_pmx_enable(struct pinctrl_dev *pctldev, unsigned fselector,
+		unsigned group)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	struct stixxxx_pinconf *conf = info->groups[group].pin_conf;
+	struct stixxxx_pio_control *pc;
+	int i;
+
+	for (i = 0; i < info->groups[group].npins; i++) {
+		pc = stixxxx_get_pio_control(info, conf[i].pin);
+		stixxxx_pctl_set_function(pc, conf[i].pin,
+					info->groups[group].altfunc);
+	}
+
+	return 0;
+}
+
+static void stixxxx_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+		unsigned group)
+{
+}
+
+static int stixxxx_pmx_set_gpio_direction(struct pinctrl_dev *pctldev,
+			struct pinctrl_gpio_range *range, unsigned gpio,
+			bool input)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	int offset = range->id - info->gpio_ranges[0]->id;
+	struct stixxxx_pio_control *pc = &info->pio_controls[offset];
+	/*
+	 * When a PIO port is used in its primary function mode (altfunc = 0)
+	 * Output Enable (OE), Open Drain(OD), and Pull Up (PU)
+	 * for the primary PIO functions are driven by the related PIO block
+	 */
+	stixxxx_pctl_set_function(pc, gpio, 0);
+	stixxxx_gpio_direction(gpio, input ?
+		STIXXXX_GPIO_DIRECTION_IN : STIXXXX_GPIO_DIRECTION_OUT);
+
+	return 0;
+}
+
+static struct pinmux_ops stixxxx_pmxops = {
+	.get_functions_count	= stixxxx_pmx_get_funcs_count,
+	.get_function_name	= stixxxx_pmx_get_fname,
+	.get_function_groups	= stixxxx_pmx_get_groups,
+	.enable			= stixxxx_pmx_enable,
+	.disable		= stixxxx_pmx_disable,
+	.gpio_set_direction	= stixxxx_pmx_set_gpio_direction,
+};
+
+/* Pinconf  */
+static void stixxxx_pinconf_get_retime(struct stixxxx_pio_control *pc,
+	int pin_id, unsigned long *config)
+{
+	int pin = stixxxx_gpio_pin(pin_id);
+	if (pc->rt_style == stixxxx_retime_style_packed)
+		stixxxx_pinconf_get_retime_packed(pc, pin, config);
+	else if (pc->rt_style == stixxxx_retime_style_dedicated)
+		if ((BIT(pin) & pc->rt_pin_mask))
+			stixxxx_pinconf_get_retime_dedicated(pc, pin, config);
+}
+
+static void stixxxx_pinconf_set_retime(struct stixxxx_pio_control *pc,
+	int pin_id, unsigned long config)
+{
+	int pin = stixxxx_gpio_pin(pin_id);
+
+	if (pc->rt_style == stixxxx_retime_style_packed)
+		stixxxx_pinconf_set_retime_packed(pc, config, pin);
+	else if (pc->rt_style == stixxxx_retime_style_dedicated)
+		if ((BIT(pin) & pc->rt_pin_mask))
+			stixxxx_pinconf_set_retime_dedicated(pc, config, pin);
+}
+
+static int stixxxx_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long config)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+	stixxxx_pinconf_set_direction(pc, pin_id, config);
+	stixxxx_pinconf_set_retime(pc, pin_id, config);
+	return 0;
+}
+
+static int stixxxx_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	struct stixxxx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+	struct stixxxx_pio_control *pc = stixxxx_get_pio_control(info, pin_id);
+
+	*config = 0;
+	stixxxx_pinconf_get_direction(pc, pin_id, config);
+	stixxxx_pinconf_get_retime(pc, pin_id, config);
+
+	return 0;
+}
+
+static void stixxxx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+	unsigned long config;
+	stixxxx_pinconf_get(pctldev, pin_id, &config);
+
+	seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+		"\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
+		"de:%ld,rt-clk:%ld,rt-delay:%ld]",
+		STIXXXX_PINCONF_UNPACK_OE(config),
+		STIXXXX_PINCONF_UNPACK_PU(config),
+		STIXXXX_PINCONF_UNPACK_OD(config),
+		STIXXXX_PINCONF_UNPACK_RT(config),
+		STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(config),
+		STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(config),
+		STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(config),
+		STIXXXX_PINCONF_UNPACK_RT_CLK(config),
+		STIXXXX_PINCONF_UNPACK_RT_DELAY(config));
+}
+
+static struct pinconf_ops stixxxx_confops = {
+	.pin_config_get		= stixxxx_pinconf_get,
+	.pin_config_set		= stixxxx_pinconf_set,
+	.pin_config_dbg_show	= stixxxx_pinconf_dbg_show,
+};
+
+static int stixxxx_pinconf_dt_parse_rt_params(struct stixxxx_pinctrl *info,
+	struct device_node *np,	struct stixxxx_retime_params *params)
+{
+	struct stixxxx_retime_offset *rt_offset;
+	int delay_count = 0;
+	int len;
+	if (of_find_property(np, "st,retime-in-delay", &len))
+		delay_count = len/sizeof(__be32);
+	else
+		dev_err(info->dev, "No delays found\n");
+
+	params->num_delay_times_out = delay_count;
+	params->num_delay_times_in = delay_count;
+	params->delay_times_in = devm_kzalloc(info->dev,
+				sizeof(u32) * delay_count, GFP_KERNEL);
+	params->delay_times_out = devm_kzalloc(info->dev,
+				sizeof(u32) * delay_count, GFP_KERNEL);
+
+	if (!params->delay_times_in || !params->delay_times_out)
+		return -ENOMEM;
+
+	of_property_read_u32_array(np, "st,retime-in-delay",
+				(u32 *)params->delay_times_in, delay_count);
+	of_property_read_u32_array(np, "st,retime-out-delay",
+				(u32 *)params->delay_times_out, delay_count);
+
+	if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+		rt_offset = devm_kzalloc(info->dev,
+			sizeof(*rt_offset), GFP_KERNEL);
+
+		if (!rt_offset)
+			return -ENOMEM;
+
+		rt_offset->clk1notclk0_offset = 0;
+		rt_offset->delay_lsb_offset = 2;
+		rt_offset->delay_msb_offset = 3;
+		rt_offset->invertclk_offset = 4;
+		rt_offset->retime_offset = 5;
+		rt_offset->clknotdata_offset = 6;
+		rt_offset->double_edge_offset = 7;
+		params->retime_offset = rt_offset;
+	}
+
+	return 0;
+}
+
+static const char *gpio_compat = "st,stixxxx-gpio";
+
+static void stixxxx_pctl_dt_child_count(struct stixxxx_pinctrl *info,
+				     struct device_node *np)
+{
+	struct device_node *child;
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->nbanks++;
+		} else {
+			info->nfunctions++;
+			info->ngroups += of_get_child_count(child);
+		}
+	}
+}
+
+static int stixxxx_pctl_dt_get_retime_conf(struct stixxxx_pinctrl *info,
+	struct stixxxx_pio_control *pc, u32 *syscfg)
+{
+	unsigned int j;
+	int rt_syscfg = *syscfg;
+	struct device_node *np = info->dev->of_node;
+
+	if (of_device_is_compatible(np, "st,stih415-pinctrl")) {
+		pc->rt_style = stixxxx_retime_style_packed;
+		for (j = 0; j < 2; j++) {
+			struct reg_field rt_reg =
+					REG_FIELD(4 * rt_syscfg ++, 0, 31);
+			pc->retiming[j] = devm_regmap_field_alloc(info->dev,
+						info->regmap, rt_reg);
+			if (IS_ERR(pc->retiming[j]))
+				return -ENODATA;
+		}
+	} else if (of_device_is_compatible(np, "st,stih416-pinctrl")) {
+		pc->rt_style = stixxxx_retime_style_dedicated;
+		for (j = 0; j < 8; j++) {
+			if ((1<<j) & pc->rt_pin_mask) {
+				struct reg_field rt_reg =
+					REG_FIELD(4 * rt_syscfg ++, 0, 31);
+				pc->retiming[j] = devm_regmap_field_alloc(
+					info->dev, info->regmap, rt_reg);
+				if (IS_ERR(pc->retiming[j]))
+					return -ENODATA;
+			}
+		}
+	} else {
+		pc->rt_style = stixxxx_retime_style_none;
+	}
+
+	*syscfg = rt_syscfg;
+	return 0;
+}
+
+static int stixxxx_pctl_dt_init(struct stixxxx_pinctrl *info,
+			struct device_node *np)
+{
+	struct stixxxx_pio_control *pc;
+	struct stixxxx_retime_params *rt_params;
+	struct device *dev = info->dev;
+	struct regmap *regmap;
+	unsigned int i = 0;
+	struct device_node *child = NULL;
+	u32 alt_syscfg, oe_syscfg, pu_syscfg, od_syscfg, rt_syscfg;
+	u32 syscfg_offsets[5];
+	u32 msb, lsb;
+
+	pc = devm_kzalloc(dev, sizeof(*pc) * info->nbanks, GFP_KERNEL);
+	rt_params = devm_kzalloc(dev, sizeof(*rt_params), GFP_KERNEL);
+
+	if (!pc || !rt_params)
+		return -ENOMEM;
+
+	regmap = syscfg_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (!regmap) {
+		dev_err(dev, "No syscfg phandle specified\n");
+		return -ENOMEM;
+	}
+	info->regmap = regmap;
+	info->pio_controls = pc;
+	if (stixxxx_pinconf_dt_parse_rt_params(info, np, rt_params))
+		return -ENOMEM;
+
+	if (of_property_read_u32_array(np, "st,syscfg-offsets",
+				syscfg_offsets, 5)) {
+		dev_err(dev, "Syscfg offsets not found\n");
+		return -EINVAL;
+	}
+	alt_syscfg = syscfg_offsets[0];
+	oe_syscfg = syscfg_offsets[1];
+	pu_syscfg = syscfg_offsets[2];
+	od_syscfg = syscfg_offsets[3];
+	rt_syscfg = syscfg_offsets[4];
+
+	lsb = 0;
+	msb = 7;
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			struct reg_field alt_reg =
+					REG_FIELD(4 * alt_syscfg++, 0, 31);
+			struct reg_field oe_reg =
+					REG_FIELD(4 * oe_syscfg, lsb, msb);
+			struct reg_field pu_reg =
+					REG_FIELD(4 * pu_syscfg, lsb, msb);
+			struct reg_field od_reg =
+					REG_FIELD(4 * od_syscfg, lsb, msb);
+			pc[i].rt_params = rt_params;
+
+			pc[i].alt = devm_regmap_field_alloc(dev,
+							regmap, alt_reg);
+			pc[i].oe = devm_regmap_field_alloc(dev,
+							regmap, oe_reg);
+			pc[i].pu = devm_regmap_field_alloc(dev,
+							regmap, pu_reg);
+			pc[i].od = devm_regmap_field_alloc(dev,
+							regmap, od_reg);
+
+			if (IS_ERR(pc[i].alt) || IS_ERR(pc[i].oe)
+				|| IS_ERR(pc[i].pu) || IS_ERR(pc[i].od))
+				goto failed;
+
+			of_property_read_u32(child, "st,retime-pin-mask",
+						&pc[i].rt_pin_mask);
+
+			stixxxx_pctl_dt_get_retime_conf(info, &pc[i],
+							&rt_syscfg);
+			i++;
+			if (msb  == 31) {
+				oe_syscfg++;
+				pu_syscfg++;
+				od_syscfg++;
+				lsb = 0;
+				msb = 7;
+			} else {
+				lsb += 8;
+				msb += 8;
+			}
+		}
+	}
+
+	return 0;
+failed:
+	dev_err(dev, "Unable to allocate syscfgs\n");
+	return -ENOMEM;
+}
+
+#define OF_GPIO_ARGS_MIN	(3)
+/*
+ * Each pin is represented in of the below forms.
+ * <bank offset direction func rt_type rt_delay rt_clk>
+ */
+static int stixxxx_pctl_dt_parse_groups(struct device_node *np,
+	struct stixxxx_pctl_group *grp, struct stixxxx_pinctrl *info, int idx)
+{
+	/* bank pad direction val altfunction */
+	const __be32 *list;
+	struct property *pp;
+	struct stixxxx_pinconf *conf;
+	phandle phandle;
+	struct device_node *pins;
+	u32 pin;
+	int i = 0, npins = 0, nr_props;
+
+	pins = of_get_child_by_name(np, "st,pins");
+	if (!pins)
+		return -ENODATA;
+
+	for_each_property_of_node(pins, pp) {
+		/* Skip those we do not want to proceed */
+		if (!strcmp(pp->name, "name"))
+			continue;
+
+		if (pp  && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) {
+			npins++;
+		} else {
+			pr_warn("Invalid st,pins in %s node\n", np->name);
+			return -EINVAL;
+		}
+	}
+
+	grp->npins = npins;
+	grp->name = np->name;
+	grp->pins = devm_kzalloc(info->dev, npins * sizeof(u32), GFP_KERNEL);
+	grp->pin_conf = devm_kzalloc(info->dev,
+					npins * sizeof(*conf), GFP_KERNEL);
+	of_property_read_u32(np, "st,function", &grp->altfunc);
+
+	if (!grp->pins || !grp->pin_conf)
+		return -ENOMEM;
+
+	/* <bank offset direction rt_type rt_delay rt_clk> */
+	for_each_property_of_node(pins, pp) {
+		if (!strcmp(pp->name, "name"))
+			continue;
+		nr_props = pp->length/sizeof(u32);
+		list = pp->value;
+		conf = &grp->pin_conf[i];
+
+		/* bank & offset */
+		phandle = be32_to_cpup(list++);
+		pin = be32_to_cpup(list++);
+		conf->pin = of_get_named_gpio(pins, pp->name, 0);
+		conf->name = pp->name;
+		grp->pins[i] = conf->pin;
+
+		conf->config = 0;
+		/* direction */
+		conf->config |= be32_to_cpup(list++);
+		/* rt_type rt_delay rt_clk */
+		if (nr_props >= OF_GPIO_ARGS_MIN + 2) {
+			/* rt_type */
+			conf->config |= be32_to_cpup(list++);
+			/* rt_delay */
+			conf->config |= be32_to_cpup(list++);
+			/* rt_clk */
+			if (nr_props > OF_GPIO_ARGS_MIN + 2)
+				conf->config |= be32_to_cpup(list++);
+		}
+		i++;
+	}
+	of_node_put(pins);
+
+	return 0;
+}
+
+static int stixxxx_pctl_parse_functions(struct device_node *np,
+			struct stixxxx_pinctrl *info, u32 index, int *grp_index)
+{
+	struct device_node *child;
+	struct stixxxx_pmx_func *func;
+	struct stixxxx_pctl_group *grp;
+	int ret, i;
+
+	func = &info->functions[index];
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+	if (func->ngroups <= 0) {
+		dev_err(info->dev, "No groups defined\n");
+		return -EINVAL;
+	}
+	func->groups = devm_kzalloc(info->dev,
+			func->ngroups * sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	i = 0;
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[*grp_index];
+		*grp_index += 1;
+		ret = stixxxx_pctl_dt_parse_groups(child, grp, info, i++);
+		if (ret)
+			return ret;
+	}
+	dev_info(info->dev, "Function[%d\t name:%s,\tgroups:%d]\n",
+				index, func->name, func->ngroups);
+
+	return 0;
+}
+
+static struct pinctrl_gpio_range *find_gpio_range(struct device_node *np)
+{
+	int i;
+	for (i = 0; i < STIXXXX_MAX_GPIO_BANKS; i++)
+		if (gpio_ports[i]->of_node == np)
+			return &gpio_ports[i]->range;
+
+	return NULL;
+}
+
+static int stixxxx_pctl_probe_dt(struct platform_device *pdev,
+	struct pinctrl_desc *pctl_desc, struct stixxxx_pinctrl *info)
+{
+	int ret = 0;
+	int i = 0, j = 0, k = 0, bank;
+	struct pinctrl_pin_desc *pdesc;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+	int grp_index = 0;
+
+	stixxxx_pctl_dt_child_count(info, np);
+	if (info->nbanks < 1) {
+		dev_err(&pdev->dev, "you need atleast one gpio bank\n");
+		return -EINVAL;
+	}
+
+	ret = stixxxx_pctl_dt_init(info, np);
+	if (ret)
+		return ret;
+
+	dev_info(&pdev->dev, "nbanks = %d\n", info->nbanks);
+	dev_info(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+	dev_info(&pdev->dev, "ngroups = %d\n", info->ngroups);
+	info->functions = devm_kzalloc(&pdev->dev,
+		info->nfunctions * sizeof(*info->functions), GFP_KERNEL);
+
+	info->groups = devm_kzalloc(&pdev->dev,
+		info->ngroups * sizeof(*info->groups) ,	GFP_KERNEL);
+
+	info->gpio_ranges = devm_kzalloc(&pdev->dev,
+		info->nbanks * sizeof(*info->gpio_ranges), GFP_KERNEL);
+
+	if (!info->functions || !info->groups)
+		return -ENOMEM;
+
+	pctl_desc->npins = info->nbanks * STIXXXX_GPIO_PINS_PER_PORT;
+	pdesc =	devm_kzalloc(&pdev->dev,
+			sizeof(*pdesc) * pctl_desc->npins, GFP_KERNEL);
+	if (!pdesc)
+		return -ENOMEM;
+
+	pctl_desc->pins = pdesc;
+
+	bank = 0;
+	for_each_child_of_node(np, child) {
+		if (of_device_is_compatible(child, gpio_compat)) {
+			info->gpio_ranges[bank] = find_gpio_range(child);
+			k = info->gpio_ranges[bank]->pin_base;
+			for (j = 0; j < STIXXXX_GPIO_PINS_PER_PORT; j++, k++) {
+				const char *port_name = NULL;
+				pdesc->number = k;
+				of_property_read_string(child, "st,bank-name",
+							&port_name);
+				pdesc->name = kasprintf(GFP_KERNEL, "%s[%d]",
+							port_name ? : "PIO",
+							port_name ? j : k);
+				pdesc++;
+			}
+			bank++;
+		} else {
+			ret = stixxxx_pctl_parse_functions(child, info,
+							i++, &grp_index);
+			if (ret) {
+				dev_err(&pdev->dev, "No functions found.\n");
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int stixxxx_pctl_probe(struct platform_device *pdev)
+{
+	struct stixxxx_pinctrl *info;
+	struct pinctrl_desc *pctl_desc;
+	int ret, i;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "device node not found.\n");
+		return -EINVAL;
+	}
+
+	pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
+	if (!pctl_desc)
+		return -ENOMEM;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = &pdev->dev;
+	platform_set_drvdata(pdev, info);
+	ret = stixxxx_pctl_probe_dt(pdev, pctl_desc, info);
+	if (ret)
+		return ret;
+
+	pctl_desc->owner	= THIS_MODULE,
+	pctl_desc->pctlops	= &stixxxx_pctlops,
+	pctl_desc->pmxops	= &stixxxx_pmxops,
+	pctl_desc->confops	= &stixxxx_confops,
+	pctl_desc->name		= dev_name(&pdev->dev);
+
+	info->pctl = pinctrl_register(pctl_desc, &pdev->dev, info);
+	if (IS_ERR(info->pctl)) {
+		dev_err(&pdev->dev, "Failed pinctrl registration\n");
+		return PTR_ERR(info->pctl);
+	}
+
+	for (i = 0; i < info->nbanks; i++)
+		pinctrl_add_gpio_range(info->pctl, info->gpio_ranges[i]);
+
+	return 0;
+}
+
+static struct gpio_chip stixxxx_gpio_template = {
+	.request		= stixxxx_gpio_request,
+	.free			= stixxxx_gpio_free,
+	.get			= stixxxx_gpio_get,
+	.set			= stixxxx_gpio_set,
+	.direction_input	= stixxxx_gpio_direction_input,
+	.direction_output	= stixxxx_gpio_direction_output,
+	.ngpio			= STIXXXX_GPIO_PINS_PER_PORT,
+	.of_gpio_n_cells	= 1,
+	.of_xlate		= stixxxx_gpio_xlate,
+};
+
+static int stixxxx_gpio_probe(struct platform_device *pdev)
+{
+	struct stixxxx_gpio_port *port;
+	struct pinctrl_gpio_range *range;
+	struct device_node *np  = pdev->dev.of_node;
+	int port_num = of_alias_get_id(np, "gpio");
+	struct resource *res;
+	int err;
+
+	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	port->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!port->base) {
+		dev_err(&pdev->dev, "Can't get IO memory mapping!\n");
+		return -ENODEV;
+	}
+
+	of_property_read_string(np, "st,bank-name", &port->bank_name);
+	port->of_node = np;
+
+	port->gpio_chip = stixxxx_gpio_template;
+	port->gpio_chip.base = port_num * STIXXXX_GPIO_PINS_PER_PORT;
+	port->gpio_chip.ngpio = STIXXXX_GPIO_PINS_PER_PORT;
+	port->gpio_chip.of_node = np;
+	port->gpio_chip.label = dev_name(&pdev->dev);
+
+	dev_set_drvdata(&pdev->dev, port);
+	range = &port->range;
+	range->name = port->gpio_chip.label;
+	range->id = port_num;
+	range->pin_base = range->base = range->id * STIXXXX_GPIO_PINS_PER_PORT;
+	range->npins = port->gpio_chip.ngpio;
+	range->gc = &port->gpio_chip;
+	gpio_ports[port_num] = port;
+	err  = gpiochip_add(&port->gpio_chip);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to add gpiochip(%d)!\n", port_num);
+		return err;
+	}
+	dev_info(&pdev->dev, "gpioport[%s] Added as bank%d\n",
+				port->bank_name, port_num);
+	return 0;
+}
+
+static struct of_device_id stixxxx_gpio_of_match[] = {
+	{ .compatible = "st,stixxxx-gpio", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_gpio_driver = {
+	.driver = {
+		.name = "st-gpio",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(stixxxx_gpio_of_match),
+	},
+	.probe = stixxxx_gpio_probe,
+};
+
+static struct of_device_id stixxxx_pctl_of_match[] = {
+	{ .compatible = "st,stixxxx-pinctrl",},
+	{ .compatible = "st,stih415-pinctrl",},
+	{ .compatible = "st,stih416-pinctrl",},
+	{ /* sentinel */ }
+};
+
+static struct platform_driver stixxxx_pctl_driver = {
+	.driver = {
+		.name = "st-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(stixxxx_pctl_of_match),
+	},
+	.probe = stixxxx_pctl_probe,
+};
+
+static int __init stixxxx_pctl_init(void)
+{
+	int ret = platform_driver_register(&stixxxx_gpio_driver);
+	if (ret)
+		return ret;
+	return platform_driver_register(&stixxxx_pctl_driver);
+}
+arch_initcall(stixxxx_pctl_init);
diff --git a/drivers/pinctrl/pinctrl-stixxxx.h b/drivers/pinctrl/pinctrl-stixxxx.h
new file mode 100644
index 0000000..e88ab09
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stixxxx.h
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Authors:
+ *	Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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 __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+#define __LINUX_DRIVERS_PINCTRL_STIXXXX_H
+
+enum stixxxx_retime_style {
+	stixxxx_retime_style_none,
+	stixxxx_retime_style_packed,
+	stixxxx_retime_style_dedicated,
+};
+
+/* Byte positions in 2 syscon words, starts from 0 */
+struct stixxxx_retime_offset {
+	int retime_offset;
+	int clk1notclk0_offset;
+	int clknotdata_offset;
+	int double_edge_offset;
+	int invertclk_offset;
+	int delay_lsb_offset;
+	int delay_msb_offset;
+};
+
+struct stixxxx_retime_params {
+	const struct stixxxx_retime_offset *retime_offset;
+	unsigned int *delay_times_in;
+	int num_delay_times_in;
+	unsigned int *delay_times_out;
+	int num_delay_times_out;
+};
+
+struct stixxxx_pio_control {
+	enum stixxxx_retime_style rt_style;
+	u32 rt_pin_mask;
+	const struct stixxxx_retime_params *rt_params;
+	struct regmap_field *alt;
+	struct regmap_field *oe, *pu, *od;
+	struct regmap_field *retiming[8];
+};
+
+/* PIO Block registers */
+/* PIO output */
+#define REG_PIO_POUT			0x00
+/* Set bits of POUT */
+#define REG_PIO_SET_POUT		0x04
+/* Clear bits of POUT */
+#define REG_PIO_CLR_POUT		0x08
+/* PIO input */
+#define REG_PIO_PIN			0x10
+/* PIO configuration */
+#define REG_PIO_PC(n)			(0x20 + (n) * 0x10)
+/* Set bits of PC[2:0] */
+#define REG_PIO_SET_PC(n)		(0x24 + (n) * 0x10)
+/* Clear bits of PC[2:0] */
+#define REG_PIO_CLR_PC(n)		(0x28 + (n) * 0x10)
+/* PIO input comparison */
+#define REG_PIO_PCOMP			0x50
+/* Set bits of PCOMP */
+#define REG_PIO_SET_PCOMP		0x54
+/* Clear bits of PCOMP */
+#define REG_PIO_CLR_PCOMP		0x58
+/* PIO input comparison mask */
+#define REG_PIO_PMASK			0x60
+/* Set bits of PMASK */
+#define REG_PIO_SET_PMASK		0x64
+/* Clear bits of PMASK */
+#define REG_PIO_CLR_PMASK		0x68
+
+#define STIXXXX_MAX_GPIO_BANKS		32
+
+#define STIXXXX_GPIO_DIRECTION_BIDIR	0x1
+#define STIXXXX_GPIO_DIRECTION_OUT	0x2
+#define STIXXXX_GPIO_DIRECTION_IN	0x4
+
+#define STIXXXX_GPIO_PINS_PER_PORT	8
+#define stixxxx_gpio_port(gpio) ((gpio) / STIXXXX_GPIO_PINS_PER_PORT)
+#define stixxxx_gpio_pin(gpio) ((gpio) % STIXXXX_GPIO_PINS_PER_PORT)
+
+/* pinconf */
+/*
+ * Pinconf is represented in an opaque unsigned long variable.
+ * Below is the bit allocation details for each possible configuration.
+ * All the bit fields can be encapsulated into four variables
+ * (direction, retime-type, retime-clk, retime-delay)
+ *
+ *	 +----------------+
+ *[31:28]| reserved-3     |
+ *	 +----------------+-------------
+ *[27]   |	oe	  |		|
+ *	 +----------------+		v
+ *[26]   |	pu	  |	[Direction	]
+ *	 +----------------+		^
+ *[25]   |	od	  |		|
+ *	 +----------------+-------------
+ *[24]   | reserved-2     |
+ *	 +----------------+-------------
+ *[23]   |    retime      |		|
+ *	 +----------------+		|
+ *[22]   | retime-invclk  |		|
+ *	 +----------------+		v
+ *[21]   |retime-clknotdat|	[Retime-type	]
+ *	 +----------------+		^
+ *[20]   | retime-de      |		|
+ *	 +----------------+-------------
+ *[19:18]| retime-clk     |------>[Retime-Clk	]
+ *	 +----------------+
+ *[17:16]|  reserved-1    |
+ *	 +----------------+
+ *[15..0]| retime-delay   |------>[Retime Delay]
+ *	 +----------------+
+ */
+
+#define STIXXXX_PINCONF_UNPACK(conf, param)\
+				((conf >> STIXXXX_PINCONF_ ##param ##_SHIFT) \
+				& STIXXXX_PINCONF_ ##param ##_MASK)
+
+#define STIXXXX_PINCONF_PACK(conf, val, param)	(conf |=\
+				((val & STIXXXX_PINCONF_ ##param ##_MASK) << \
+					STIXXXX_PINCONF_ ##param ##_SHIFT))
+
+/* Output enable */
+#define STIXXXX_PINCONF_OE_MASK		0x1
+#define STIXXXX_PINCONF_OE_SHIFT	27
+#define STIXXXX_PINCONF_OE		BIT(27)
+#define STIXXXX_PINCONF_UNPACK_OE(conf)	STIXXXX_PINCONF_UNPACK(conf, OE)
+#define STIXXXX_PINCONF_PACK_OE(conf, val)  STIXXXX_PINCONF_PACK(conf, val, OE)
+
+/* Pull Up */
+#define STIXXXX_PINCONF_PU_MASK		0x1
+#define STIXXXX_PINCONF_PU_SHIFT	26
+#define STIXXXX_PINCONF_PU		BIT(26)
+#define STIXXXX_PINCONF_UNPACK_PU(conf)	STIXXXX_PINCONF_UNPACK(conf, PU)
+#define STIXXXX_PINCONF_PACK_PU(conf, val) STIXXXX_PINCONF_PACK(conf, val, PU)
+
+/* Open Drain */
+#define STIXXXX_PINCONF_OD_MASK		0x1
+#define STIXXXX_PINCONF_OD_SHIFT	25
+#define STIXXXX_PINCONF_OD		BIT(25)
+#define STIXXXX_PINCONF_UNPACK_OD(conf)	STIXXXX_PINCONF_UNPACK(conf, OD)
+#define STIXXXX_PINCONF_PACK_OD(conf, val) STIXXXX_PINCONF_PACK(conf, val, OD)
+
+#define STIXXXX_PINCONF_RT_MASK		0x1
+#define STIXXXX_PINCONF_RT_SHIFT	23
+#define STIXXXX_PINCONF_RT		BIT(23)
+#define STIXXXX_PINCONF_UNPACK_RT(conf)	STIXXXX_PINCONF_UNPACK(conf, RT)
+#define STIXXXX_PINCONF_PACK_RT(conf, val) STIXXXX_PINCONF_PACK(conf, val, RT)
+
+#define STIXXXX_PINCONF_RT_INVERTCLK_MASK	0x1
+#define STIXXXX_PINCONF_RT_INVERTCLK_SHIFT	22
+#define STIXXXX_PINCONF_RT_INVERTCLK		BIT(22)
+#define STIXXXX_PINCONF_UNPACK_RT_INVERTCLK(conf) \
+			STIXXXX_PINCONF_UNPACK(conf, RT_INVERTCLK)
+#define STIXXXX_PINCONF_PACK_RT_INVERTCLK(conf, val) \
+			STIXXXX_PINCONF_PACK(conf, val, RT_INVERTCLK)
+
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_MASK	0x1
+#define STIXXXX_PINCONF_RT_CLKNOTDATA_SHIFT	21
+#define STIXXXX_PINCONF_RT_CLKNOTDATA		BIT(21)
+#define STIXXXX_PINCONF_UNPACK_RT_CLKNOTDATA(conf)	\
+				STIXXXX_PINCONF_UNPACK(conf, RT_CLKNOTDATA)
+#define STIXXXX_PINCONF_PACK_RT_CLKNOTDATA(conf, val) \
+				STIXXXX_PINCONF_PACK(conf, val, RT_CLKNOTDATA)
+
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_MASK	0x1
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE_SHIFT	20
+#define STIXXXX_PINCONF_RT_DOUBLE_EDGE		BIT(20)
+#define STIXXXX_PINCONF_UNPACK_RT_DOUBLE_EDGE(conf) \
+				STIXXXX_PINCONF_UNPACK(conf, RT_DOUBLE_EDGE)
+#define STIXXXX_PINCONF_PACK_RT_DOUBLE_EDGE(conf, val) \
+				STIXXXX_PINCONF_PACK(conf, val, RT_DOUBLE_EDGE)
+
+#define STIXXXX_PINCONF_RT_CLK_MASK		0x3
+#define STIXXXX_PINCONF_RT_CLK_SHIFT		18
+#define STIXXXX_PINCONF_RT_CLK			BIT(18)
+#define STIXXXX_PINCONF_UNPACK_RT_CLK(conf)	\
+			STIXXXX_PINCONF_UNPACK(conf, RT_CLK)
+#define STIXXXX_PINCONF_PACK_RT_CLK(conf, val) \
+			STIXXXX_PINCONF_PACK(conf, val, RT_CLK)
+
+/* RETIME_DELAY in Pico Secs */
+#define STIXXXX_PINCONF_RT_DELAY_MASK		0xffff
+#define STIXXXX_PINCONF_RT_DELAY_SHIFT		0
+#define STIXXXX_PINCONF_UNPACK_RT_DELAY(conf) \
+				STIXXXX_PINCONF_UNPACK(conf, RT_DELAY)
+#define STIXXXX_PINCONF_PACK_RT_DELAY(conf, val) \
+				STIXXXX_PINCONF_PACK(conf, val, RT_DELAY)
+
+#endif /* __LINUX_DRIVERS_PINCTRL_STIXXXX_H */
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?=
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (4 preceding siblings ...)
  2013-06-10  9:22   ` [PATCH v2 05/11] pinctrl:stixxxx: Add pinctrl and pinconf support Srinivas KANDAGATLA
@ 2013-06-10  9:26   ` Srinivas KANDAGATLA
  2013-06-10  9:55     ` [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support Michal Simek
                       ` (2 more replies)
  2013-06-10  9:27   ` [PATCH v2 07/11] ARM:stixxxx: Add STiH416 " Srinivas KANDAGATLA
                     ` (4 subsequent siblings)
  10 siblings, 3 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:26 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=yes, Size: 28873 bytes --]

The STiH415 is the next generation of HD, AVC set-top box processors for
satellite, cable, terrestrial and IP-STB markets. It is an ARM Cortex-A9
1.0 GHz, dual-core CPU.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 Documentation/arm/stixxxx/overview.txt         |   33 +++
 Documentation/arm/stixxxx/stih415-overview.txt |   12 +
 MAINTAINERS                                    |   11 +
 arch/arm/Kconfig                               |    2 +
 arch/arm/Makefile                              |    1 +
 arch/arm/boot/dts/stih415-clock.dtsi           |   38 +++
 arch/arm/boot/dts/stih415-pinctrl.dtsi         |  326 ++++++++++++++++++++++++
 arch/arm/boot/dts/stih415.dtsi                 |  102 ++++++++
 arch/arm/boot/dts/stih41x.dtsi                 |   38 +++
 arch/arm/boot/dts/stixxxx-pincfg.h             |   94 +++++++
 arch/arm/mach-stixxxx/Kconfig                  |   45 ++++
 arch/arm/mach-stixxxx/Makefile                 |    2 +
 arch/arm/mach-stixxxx/board-dt.c               |   47 ++++
 arch/arm/mach-stixxxx/headsmp.S                |   44 ++++
 arch/arm/mach-stixxxx/platsmp.c                |  117 +++++++++
 arch/arm/mach-stixxxx/smp.h                    |   19 ++
 16 files changed, 931 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/arm/stixxxx/overview.txt
 create mode 100644 Documentation/arm/stixxxx/stih415-overview.txt
 create mode 100644 arch/arm/boot/dts/stih415-clock.dtsi
 create mode 100644 arch/arm/boot/dts/stih415-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stih415.dtsi
 create mode 100644 arch/arm/boot/dts/stih41x.dtsi
 create mode 100644 arch/arm/boot/dts/stixxxx-pincfg.h
 create mode 100644 arch/arm/mach-stixxxx/Kconfig
 create mode 100644 arch/arm/mach-stixxxx/Makefile
 create mode 100644 arch/arm/mach-stixxxx/board-dt.c
 create mode 100644 arch/arm/mach-stixxxx/headsmp.S
 create mode 100644 arch/arm/mach-stixxxx/platsmp.c
 create mode 100644 arch/arm/mach-stixxxx/smp.h

diff --git a/Documentation/arm/stixxxx/overview.txt b/Documentation/arm/stixxxx/overview.txt
new file mode 100644
index 0000000..a2f6390
--- /dev/null
+++ b/Documentation/arm/stixxxx/overview.txt
@@ -0,0 +1,33 @@
+			STixxxx ARM Linux Overview
+			==========================
+
+Introduction
+------------
+
+  The ST Microelectronics Multimedia and Application Processors range of
+  CortexA9 System-on-Chip are supported by the 'STixxxx' platform of
+  ARM Linux. Currently STiH415, STiH416 SOCs are supported with both
+  B2000 and B2020 Reference boards.
+
+
+  configuration
+  -------------
+
+  A generic configuration is provided for both STiH415/416, and can be used as the
+  default by
+	make stih41x_defconfig
+
+  Layout
+  ------
+  All the files for multiple machine families (STiH415, STiH416, and STiG125)
+  are located in the platform code contained in arch/arm/mach-stixxxx
+
+  There is a generic board board-dt.c in the mach folder which support
+  Flattened Device Tree, which means, It works with any compatible board with
+  Device Trees.
+
+
+  Document Author
+  ---------------
+
+  Srinivas Kandagatla <srinivas.kandagatla@st.com>, (c) 2013 ST Microelectronics
diff --git a/Documentation/arm/stixxxx/stih415-overview.txt b/Documentation/arm/stixxxx/stih415-overview.txt
new file mode 100644
index 0000000..1c264b7
--- /dev/null
+++ b/Documentation/arm/stixxxx/stih415-overview.txt
@@ -0,0 +1,12 @@
+			STiH415 Overview
+			================
+
+Introduction
+------------
+
+    The STiH415 is the next generation of HD, AVC set-top box processors
+    for satellite, cable, terrestrial and IP-STB markets.
+
+    Features
+    - ARM Cortex-A9 1.0 GHz, dual-core CPU
+    - SATA2×2,USB 2.0×3, PCIe, Gbit Ethernet MAC×2
diff --git a/MAINTAINERS b/MAINTAINERS
index 250dc97..2aca7d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1201,6 +1201,17 @@ M:	Dinh Nguyen <dinguyen@altera.com>
 S:	Maintained
 F:	drivers/clk/socfpga/
 
+ARM/STIXXXX ARCHITECTURE
+M:	Srinivas Kandagatla <srinivas.kandagatla@st.com>
+M:	Stuart Menefy <stuart.menefy@st.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+W:	http://www.stlinux.com
+S:	Maintained
+F:	arch/arm/mach-stixxxx/
+F:	drivers/pinctrl/pinctrl-stixxxx*
+F:	drivers/mfd/stixxxx-syscfg*
+F:	drivers/clocksource/global_timer.c
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 49d993c..790e321 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -989,6 +989,8 @@ source "arch/arm/mach-socfpga/Kconfig"
 
 source "arch/arm/mach-spear/Kconfig"
 
+source "arch/arm/mach-stixxxx/Kconfig"
+
 source "arch/arm/mach-s3c24xx/Kconfig"
 
 if ARCH_S3C64XX
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1ba358b..c876e0a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_W90X900)		+= w90x900
 machine-$(CONFIG_FOOTBRIDGE)		+= footbridge
 machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
 machine-$(CONFIG_PLAT_SPEAR)		+= spear
+machine-$(CONFIG_ARCH_STIXXXX)		+= stixxxx
 machine-$(CONFIG_ARCH_VIRT)		+= virt
 machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
 machine-$(CONFIG_ARCH_SUNXI)		+= sunxi
diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
new file mode 100644
index 0000000..174c799
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited
+ *
+ * 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.
+ */
+/ {
+	clocks {
+		/*
+		 * Fixed 30MHz oscillator input to SoC
+		 */
+		CLK_SYSIN: CLK_SYSIN {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <30000000>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: arm_periph_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <500000000>;
+		};
+
+		/*
+		 * Bootloader initialized system infrastructure clock for
+		 * serial devices.
+		 */
+		CLKS_ICN_REG_0: CLKS_ICN_REG_0 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <100000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/stih415-pinctrl.dtsi b/arch/arm/boot/dts/stih415-pinctrl.dtsi
new file mode 100644
index 0000000..c510f11
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-pinctrl.dtsi
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stixxxx-pincfg.h"
+/ {
+
+	aliases {
+		gpio0	= &PIO0;
+		gpio1	= &PIO1;
+		gpio2	= &PIO2;
+		gpio3	= &PIO3;
+		gpio4	= &PIO4;
+		gpio5	= &PIO5;
+		gpio6	= &PIO6;
+		gpio7	= &PIO7;
+		gpio8	= &PIO8;
+		gpio9	= &PIO9;
+		gpio10	= &PIO10;
+		gpio11	= &PIO11;
+		gpio12	= &PIO12;
+		gpio13	= &PIO13;
+		gpio14	= &PIO14;
+		gpio15	= &PIO15;
+		gpio16	= &PIO16;
+		gpio17	= &PIO17;
+		gpio18	= &PIO18;
+		gpio19	= &PIO100;
+		gpio20	= &PIO101;
+		gpio21	= &PIO102;
+		gpio22	= &PIO103;
+		gpio23	= &PIO104;
+		gpio24	= &PIO105;
+		gpio25	= &PIO106;
+		gpio26	= &PIO107;
+	};
+
+
+	soc {
+		pin-controller-sbc {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih415-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 500 1000 1500>;
+			st,retime-out-delay	= <0 1000 2000 3000>;
+			st,syscfg		= <&syscfg_sbc>;
+			st,syscfg-offsets	= <0 5 7 9 16>;
+			ranges;
+
+			PIO0: pinctrl@fe610000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe610000 0x100>;
+				st,bank-name	= "PIO0";
+			};
+
+			PIO1: pinctrl@fe611000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe611000 0x100>;
+				st,bank-name	= "PIO1";
+			};
+
+			PIO2: pinctrl@fe612000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe612000 0x100>;
+				st,bank-name	= "PIO2";
+			};
+
+			PIO3: pinctrl@fe613000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe613000 0x100>;
+				st,bank-name	= "PIO3";
+
+			};
+
+			PIO4: pinctrl@fe614000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe614000 0x100>;
+				st,bank-name	= "PIO4";
+			};
+
+			sbc_serial1 {
+				pinctrl_sbc_serial1:sbc_serial1 {
+					st,function = <ALT3>;
+					st,pins {
+						tx	= <&PIO2 6 OUT>;
+						rx	= <&PIO2 7 IN>;
+					};
+				};
+			};
+		};
+
+		pin-controller-front {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih415-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 500 1000 1500>;
+			st,retime-out-delay	= <0 1000 2000 3000>;
+			st,syscfg		= <&syscfg_front>;
+			st,syscfg-offsets	= <0 8 10 12 16>;
+			ranges;
+
+			PIO5: pinctrl@fee00000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee00000 0x100>;
+				st,bank-name	= "PIO5";
+			};
+			PIO6: pinctrl@fee01000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee01000 0x100>;
+				st,bank-name	= "PIO6";
+			};
+
+			PIO7: pinctrl@fee02000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee02000 0x100>;
+				st,bank-name	= "PIO7";
+			};
+			PIO8: pinctrl@fee03000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee03000 0x100>;
+				st,bank-name	= "PIO8";
+			};
+			PIO9: pinctrl@fee04000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee04000 0x100>;
+				st,bank-name	= "PIO9";
+			};
+			PIO10: pinctrl@fee05000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee05000 0x100>;
+				st,bank-name	= "PIO10";
+			};
+			PIO11: pinctrl@fee06000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee06000 0x100>;
+				st,bank-name	= "PIO11";
+			};
+			PIO12: pinctrl@fee07000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfee07000 0x100>;
+				st,bank-name	= "PIO12";
+			};
+		};
+
+		pin-controller-rear {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih415-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 500 1000 1500>;
+			st,retime-out-delay	= <0 1000 2000 3000>;
+			st,syscfg		= <&syscfg_rear>;
+			st,syscfg-offsets	= <0 6 8 10 38>;
+			ranges;
+
+			PIO13: pinctrl@fe820000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe820000 0x100>;
+				st,bank-name	= "PIO13";
+			};
+			PIO14: pinctrl@fe821000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe821000 0x100>;
+				st,bank-name	= "PIO14";
+			};
+			PIO15: pinctrl@fe822000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe822000 0x100>;
+				st,bank-name	= "PIO15";
+			};
+			PIO16: pinctrl@fe823000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe823000 0x100>;
+				st,bank-name	= "PIO16";
+
+			};
+			PIO17: pinctrl@fe824000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe824000 0x100>;
+				st,bank-name	= "PIO17";
+
+			};
+			PIO18: pinctrl@fe825000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfe825000 0x100>;
+				st,bank-name	= "PIO18";
+
+			};
+
+			serial2 {
+				pinctrl_serial2: serial2-0 {
+					st,function = <ALT2>;
+					st,pins {
+						tx	= <&PIO17 4 OUT>;
+						rx	= <&PIO17 5 IN>;
+					};
+				};
+			};
+
+		};
+
+		pin-controller-left {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih415-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 500 1000 1500>;
+			st,retime-out-delay	= <0 1000 2000 3000>;
+			st,syscfg		= <&syscfg_left>;
+			st,syscfg-offsets	= <0 3 4 5 6>;
+			ranges;
+
+			PIO100: pinctrl@fd6b0000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd6b0000 0x100>;
+				st,bank-name	= "PIO100";
+			};
+			PIO101: pinctrl@fd6b1000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd6b1000 0x100>;
+				st,bank-name	= "PIO101";
+
+			};
+			PIO102: pinctrl@fd6b2000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd6b2000 0x100>;
+				st,bank-name	= "PIO102";
+
+			};
+
+		};
+
+		pin-controller-right {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih415-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 500 1000 1500>;
+			st,retime-out-delay	= <0 1000 2000 3000>;
+			st,syscfg		= <&syscfg_right>;
+			st,syscfg-offsets	= <0 5 7 9 11>;
+			ranges;
+
+			PIO103: pinctrl@fd330000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd330000 0x100>;
+				st,bank-name	= "PIO103";
+			};
+			PIO104: pinctrl@fd331000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd331000 0x100>;
+				st,bank-name	= "PIO104";
+			};
+			PIO105: pinctrl@fd332000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd332000 0x100>;
+				st,bank-name	= "PIO105";
+			};
+			PIO106: pinctrl@fd333000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd333000 0x100>;
+				st,bank-name	= "PIO106";
+			};
+			PIO107: pinctrl@fd334000 {
+				gpio-controller;
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				reg	= <0xfd334000 0x100>;
+				st,bank-name	= "PIO107";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
new file mode 100644
index 0000000..6dcf5b4
--- /dev/null
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih41x.dtsi"
+#include "stih415-clock.dtsi"
+#include "stih415-pinctrl.dtsi"
+/ {
+
+	L2: cache-controller {
+		compatible = "arm,pl310-cache";
+		reg = <0xfffe2000 0x1000>;
+		arm,data-latency = <3 2 2>;
+		arm,tag-latency = <1 1 1>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&intc>;
+		ranges;
+		compatible	= "simple-bus";
+
+		syscfg_sbc: syscfg@fe600000{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfe600000 0xb4>;
+			syscfg-range	= <0 44>;
+			syscfg-name	= "SYSCFG_SBC";
+		};
+
+		syscfg_front: syscfg@fee10000{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfee10000 0x194>;
+			syscfg-range	= <100 100>;
+			syscfg-name	= "SYSCFG_FRONT";
+		};
+
+		syscfg_rear: syscfg@fe830000{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfe830000 0x190>;
+			syscfg-range	= <300 99>;
+			syscfg-name	= "SYSCFG_REAR";
+		};
+
+		/* MPE syscfgs */
+		syscfg_left: syscfg@fd690000{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfd690000 0x78>;
+			syscfg-range 	= <400 29>;
+			syscfg-name	= "SYSCFG_LEFT";
+		};
+
+		syscfg_right: syscfg@fd320000{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfd320000 0x180>;
+			syscfg-range	= <500 95>;
+			syscfg-name	= "SYSCFG_RIGHT";
+		};
+
+		syscfg_system: syscfg@fdde0000  {
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfdde0000 0x15c>;
+			syscfg-range	= <600 86>;
+			syscfg-name	= "SYSCFG_SYSTEM";
+		};
+
+		syscfg_lpm: syscfg@fe4b5100{
+			compatible      = "st,stih415-syscfg";
+			reg		= <0xfe4b5100 0x08>;
+			syscfg-range	= <0 10>;
+			syscfg-name	= "LPM_CFG_REGS";
+		};
+
+		serial2: serial@fed32000 {
+			compatible	= "st,asc";
+			status 		= "disabled";
+			reg		= <0xfed32000 0x2c>;
+			interrupts	= <0 197 0>;
+			pinctrl-names 	= "default";
+			pinctrl-0 	= <&pinctrl_serial2>;
+			clocks		= <&CLKS_ICN_REG_0>;
+		};
+
+		/* SBC comms block ASCs in SASG1 */
+		sbc_serial1: serial@fe531000 {
+			compatible	= "st,asc";
+			status 		= "disabled";
+			reg		= <0xfe531000 0x2c>;
+			interrupts	= <0 210 0>;
+			clocks		= <&CLK_SYSIN>;
+			pinctrl-names 	= "default";
+			pinctrl-0	= <&pinctrl_sbc_serial1>;
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/stih41x.dtsi b/arch/arm/boot/dts/stih41x.dtsi
new file mode 100644
index 0000000..7321403
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x.dtsi
@@ -0,0 +1,38 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	intc: interrupt-controller@fffe1000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0xfffe1000 0x1000>,
+		      <0xfffe0100 0x100>;
+	};
+
+	scu@fffe0000 {
+		compatible = "arm,cortex-a9-scu";
+		reg = <0xfffe0000 0x1000>;
+	};
+
+	timer@fffe0200 {
+		interrupt-parent = <&intc>;
+		compatible = "arm,cortex-a9-global-timer";
+		reg = <0xfffe0200 0x100>;
+		interrupts = <1 11 0x04>;
+		clocks = <&arm_periph_clk>;
+	};
+};
diff --git a/arch/arm/boot/dts/stixxxx-pincfg.h b/arch/arm/boot/dts/stixxxx-pincfg.h
new file mode 100644
index 0000000..0dfaba0
--- /dev/null
+++ b/arch/arm/boot/dts/stixxxx-pincfg.h
@@ -0,0 +1,94 @@
+#ifndef _STIXXXX_PINCFG_H_
+#define _STIXXXX_PINCFG_H_
+
+/* Alternate functions */
+#define ALT1	1
+#define ALT2	2
+#define ALT3	3
+#define ALT4	4
+#define ALT5	5
+#define ALT6	6
+#define ALT7	7
+
+/* Output enable */
+#define OE_MASK			0x1
+#define OE_SHIFT		27
+#define OE			(1 << OE_SHIFT)
+
+/* Pull Up */
+#define PU_MASK			0x1
+#define PU_SHIFT		26
+#define PU			(1 << PU_SHIFT)
+
+/* Open Drain */
+#define OD_MASK			0x1
+#define OD_SHIFT		25
+#define OD			(1 << OD_SHIFT)
+
+#define RT_MASK			0x1
+#define RT_SHIFT		23
+#define RT			(1 << RT_SHIFT)
+
+#define INVERTCLK_MASK		0x1
+#define INVERTCLK_SHIFT		22
+#define INVERTCLK		(1 << INVERTCLK_SHIFT)
+
+#define CLKNOTDATA_MASK		0x1
+#define CLKNOTDATA_SHIFT	21
+#define CLKNOTDATA		(1 << CLKNOTDATA_SHIFT)
+
+#define DOUBLE_EDGE_MASK	 0x1
+#define DOUBLE_EDGE_SHIFT	 20
+#define DOUBLE_EDGE		(1 << DOUBLE_EDGE_SHIFT)
+
+#define CLK_MASK		0x3
+#define CLK_SHIFT		18
+#define CLK_A			(0 << CLK_SHIFT)
+#define CLK_B			(1 << CLK_SHIFT)
+#define CLK_C			(2 << CLK_SHIFT)
+#define CLK_D			(3 << CLK_SHIFT)
+
+/* User-frendly defines for Pin Direction */
+		/* oe = 0, pu = 0, od = 0 */
+#define IN			(0)
+		/* oe = 0, pu = 1, od = 0 */
+#define IN_PU			(PU)
+		/* oe = 1, pu = 0, od = 0 */
+#define OUT			(OE)
+		/* oe = 1, pu = 0, od = 1 */
+#define BIDIR			(OE | OD)
+		/* oe = 1, pu = 1, od = 1 */
+#define BIDIR_PU		(OE | PU | OD)
+
+/* RETIME_TYPE */
+/*
+ * B Mode
+ * Bypass retime with optional delay parameter
+ */
+#define BYPASS		(0)
+/*
+ * R0, R1, R0D, R1D modes
+ * single-edge data non inverted clock, retime data with clk
+ */
+#define SE_NICLK_IO	(RT)
+/*
+ * RIV0, RIV1, RIV0D, RIV1D modes
+ * single-edge data inverted clock, retime data with clk
+ */
+#define SE_ICLK_IO	(RT | INVERTCLK)
+/*
+ * R0E, R1E, R0ED, R1ED modes
+ * double-edge data, retime data with clk
+ */
+#define DE_IO		(RT | DOUBLE_EDGE)
+/*
+ * CIV0, CIV1 modes with inverted clock
+ * Retiming the clk pins will park clock & reduce the noise within the core.
+ */
+#define ICLK		(RT | CLKNOTDATA | INVERTCLK)
+/*
+ * CLK0, CLK1 modes with non-inverted clock
+ * Retiming the clk pins will park clock & reduce the noise within the core.
+ */
+#define NICLK		(RT | CLKNOTDATA)
+#endif /* _STIXXXX_PINCFG_H_ */
diff --git a/arch/arm/mach-stixxxx/Kconfig b/arch/arm/mach-stixxxx/Kconfig
new file mode 100644
index 0000000..278d938
--- /dev/null
+++ b/arch/arm/mach-stixxxx/Kconfig
@@ -0,0 +1,45 @@
+menuconfig ARCH_STIXXXX
+	bool "STMicroelectronics Consumer Electronics SOCs with Device Trees" if ARCH_MULTI_V7
+	select GENERIC_CLOCKEVENTS
+	select CLKDEV_LOOKUP
+	select ARM_GIC
+	select ARM_GLOBAL_TIMER
+	select MFD_STIXXXX_SYSCFG
+	select PINCTRL
+	select PINCTRL_STIXXXX
+	select MIGHT_HAVE_CACHE_L2X0
+	select HAVE_SMP
+	select HAVE_ARM_SCU if SMP
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_754322
+	select PL310_ERRATA_753970
+	select PL310_ERRATA_769419
+	help
+	  Include support for STiH41x SOCs like STiH415/416 using the device tree
+	  for discovery
+	  More information at Documentation/arm/STiH41x and
+	  at Documentation/devicetree
+
+
+if ARCH_STIXXXX
+
+config SOC_STIH415
+	bool "STiH415 STMicroelectronics Consumer Electronics family"
+	default y
+	help
+	  This enables support for STMicroelectronics Digital Consumer
+	  Electronics family StiH415 parts, primarily targetted at set-top-box
+	  and other digital audio/video applications using Flattned Device
+	  Trees.
+
+config SOC_STIH416
+	bool "STiH416 STMicroelectronics Consumer Electronics family"
+	default y
+	help
+	  This enables support for STMicroelectronics Digital Consumer
+	  Electronics family StiH416 parts, primarily targetted at set-top-box
+	  and other digital audio/video applications using Flattened Device
+	  Trees.
+
+endif
diff --git a/arch/arm/mach-stixxxx/Makefile b/arch/arm/mach-stixxxx/Makefile
new file mode 100644
index 0000000..50bf128
--- /dev/null
+++ b/arch/arm/mach-stixxxx/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+obj-$(CONFIG_ARCH_STIXXXX) 		+= board-dt.o
diff --git a/arch/arm/mach-stixxxx/board-dt.c b/arch/arm/mach-stixxxx/board-dt.c
new file mode 100644
index 0000000..52ce665
--- /dev/null
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author(s): Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/irq.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+
+#include "smp.h"
+
+void __init stih41x_l2x0_init(void)
+{
+	u32 way_size = 0x4;
+	u32 aux_ctrl;
+
+	aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
+		(0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
+		(0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
+		(way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
+
+	l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
+}
+
+static void __init stih41x_timer_init(void)
+{
+	of_clk_init(NULL);
+	clocksource_of_init();
+	stih41x_l2x0_init();
+}
+
+static const char *stih41x_dt_match[] __initdata = {
+	"st,stih415",
+	NULL
+};
+
+DT_MACHINE_START(STM, "STiH415 SoC with Flattened Device Tree")
+	.init_time	= stih41x_timer_init,
+	.smp		= smp_ops(stixxxx_smp_ops),
+	.dt_compat	= stih41x_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-stixxxx/headsmp.S b/arch/arm/mach-stixxxx/headsmp.S
new file mode 100644
index 0000000..3dd5c04
--- /dev/null
+++ b/arch/arm/mach-stixxxx/headsmp.S
@@ -0,0 +1,44 @@
+/*
+ *  arch/arm/plat-stixxxx/headsmp.S
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *		http://www.st.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * ST specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(stixxxx_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	pen_release
diff --git a/arch/arm/mach-stixxxx/platsmp.c b/arch/arm/mach-stixxxx/platsmp.c
new file mode 100644
index 0000000..ffc40c0
--- /dev/null
+++ b/arch/arm/mach-stixxxx/platsmp.c
@@ -0,0 +1,117 @@
+/*
+ *  arch/arm/plat-stixxxx/platsmp.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *		http://www.st.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+#include "smp.h"
+
+static void __cpuinit write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit stixxxx_secondary_init(unsigned int cpu)
+{
+	trace_hardirqs_off();
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit stixxxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	write_pen_release(cpu_logical_map(cpu));
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * it to jump to the secondary entrypoint.
+	 */
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+void __init stixxxx_smp_prepare_cpus(unsigned int max_cpus)
+{
+	void __iomem *scu_base = NULL;
+	struct device_node *np = of_find_compatible_node(
+					NULL, NULL, "arm,cortex-a9-scu");
+	if (np) {
+		scu_base = of_iomap(np, 0);
+		scu_enable(scu_base);
+		of_node_put(np);
+	}
+}
+
+struct smp_operations __initdata stixxxx_smp_ops = {
+	.smp_prepare_cpus	= stixxxx_smp_prepare_cpus,
+	.smp_secondary_init	= stixxxx_secondary_init,
+	.smp_boot_secondary	= stixxxx_boot_secondary,
+};
diff --git a/arch/arm/mach-stixxxx/smp.h b/arch/arm/mach-stixxxx/smp.h
new file mode 100644
index 0000000..c3e3d40
--- /dev/null
+++ b/arch/arm/mach-stixxxx/smp.h
@@ -0,0 +1,19 @@
+/*
+ *  arch/arm/plat-stixxxx/platsmp.c
+ *
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *		http://www.st.com
+ *
+ * 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 __PLAT_SMP_H
+#define __PLAT_SMP_H
+
+extern struct smp_operations	stixxxx_smp_ops;
+extern void __iomem *stixxxx_scu_base_addr;
+extern void stixxxx_secondary_startup(void);
+
+#endif
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 07/11] ARM:stixxxx: Add STiH416 SOC support
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (5 preceding siblings ...)
  2013-06-10  9:26   ` =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
@ 2013-06-10  9:27   ` Srinivas KANDAGATLA
  2013-06-10 13:52     ` Arnd Bergmann
  2013-06-10  9:27   ` [PATCH v2 08/11] ARM:stixxxx: Add DEBUG_LL console support Srinivas KANDAGATLA
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

The STiH416 is advanced HD AVC processor with 3D graphics acceleration
and 1.2-GHz ARM Cortex-A9 SMP CPU.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Linus Walleij <linus.walleij@linaro.org>
---
 Documentation/arm/stixxxx/stih416-overview.txt |   12 +
 arch/arm/boot/dts/stih416-clock.dtsi           |   41 +++
 arch/arm/boot/dts/stih416-pinctrl.dtsi         |  377 ++++++++++++++++++++++++
 arch/arm/boot/dts/stih416.dtsi                 |  111 +++++++
 arch/arm/mach-stixxxx/board-dt.c               |    3 +-
 5 files changed, 543 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/arm/stixxxx/stih416-overview.txt
 create mode 100644 arch/arm/boot/dts/stih416-clock.dtsi
 create mode 100644 arch/arm/boot/dts/stih416-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stih416.dtsi

diff --git a/Documentation/arm/stixxxx/stih416-overview.txt b/Documentation/arm/stixxxx/stih416-overview.txt
new file mode 100644
index 0000000..e060867
--- /dev/null
+++ b/Documentation/arm/stixxxx/stih416-overview.txt
@@ -0,0 +1,12 @@
+			STiH416 Overview
+			================
+
+Introduction
+------------
+
+    The STiH416 is the next generation of HD, AVC set-top box processors
+    for satellite, cable, terrestrial and IP-STB markets.
+
+    Features
+    - ARM Cortex-A9 1.2 GHz dual core CPU
+    - SATA2×2,USB 2.0×3, PCIe, Gbit Ethernet MAC×2
diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
new file mode 100644
index 0000000..7026bf1
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics R&D Limited
+ * <stlinux-devel@stlinux.com>
+ *
+ * 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.
+ */
+/ {
+	clocks {
+		/*
+		 * Fixed 30MHz oscillator inputs to SoC
+		 */
+		CLK_SYSIN: CLK_SYSIN {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <30000000>;
+			clock-output-names = "CLK_SYSIN";
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: arm_periph_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <600000000>;
+		};
+
+		/*
+		 * Bootloader initialized system infrastructure clock for
+		 * serial devices.
+		 */
+		CLK_S_ICN_REG_0: clockgenA0@4 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <100000000>;
+			clock-output-names = "CLK_S_ICN_REG_0";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/stih416-pinctrl.dtsi b/arch/arm/boot/dts/stih416-pinctrl.dtsi
new file mode 100644
index 0000000..15843a9
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-pinctrl.dtsi
@@ -0,0 +1,377 @@
+
+/*
+ * Copyright (C) 2013 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stixxxx-pincfg.h"
+/ {
+
+	aliases {
+		gpio0	= &PIO0;
+		gpio1	= &PIO1;
+		gpio2	= &PIO2;
+		gpio3	= &PIO3;
+		gpio4	= &PIO4;
+		gpio5	= &PIO40;
+		gpio6	= &PIO5;
+		gpio7	= &PIO6;
+		gpio8	= &PIO7;
+		gpio9	= &PIO8;
+		gpio10	= &PIO9;
+		gpio11	= &PIO10;
+		gpio12	= &PIO11;
+		gpio13	= &PIO12;
+		gpio14	= &PIO30;
+		gpio15	= &PIO31;
+		gpio16	= &PIO13;
+		gpio17	= &PIO14;
+		gpio18	= &PIO15;
+		gpio19	= &PIO16;
+		gpio20	= &PIO17;
+		gpio21	= &PIO18;
+		gpio22	= &PIO100;
+		gpio23	= &PIO101;
+		gpio24	= &PIO102;
+		gpio25	= &PIO103;
+		gpio26	= &PIO104;
+		gpio27	= &PIO105;
+		gpio28	= &PIO106;
+		gpio29	= &PIO107;
+	};
+
+	soc {
+		pin-controller-sbc {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih416-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,syscfg		= <&syscfg_sbc>;
+			st,syscfg-offsets	= <0 40 50 60 100>;
+			ranges;
+			PIO0: pinctrl@fe610000 {
+				#gpio-cells = <1>;
+				compatible = "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe610000 0x100>;
+				st,bank-name  = "PIO0";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO1: pinctrl@fe611000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe611000 0x100>;
+				st,bank-name  = "PIO1";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO2: pinctrl@fe612000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe612000 0x100>;
+				st,bank-name  = "PIO2";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO3: pinctrl@fe613000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe613000 0x100>;
+				st,bank-name  = "PIO3";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO4: pinctrl@fe614000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe614000 0x100>;
+				st,bank-name  = "PIO4";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO40: pinctrl@fe615000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe615000 0x100>;
+				st,bank-name  = "PIO40";
+				st,retime-pin-mask = <0x7f>;
+			};
+
+			sbc_serial1 {
+				pinctrl_sbc_serial1: sbc_serial1 {
+					st,function = <ALT3>;
+					st,pins {
+						tx	= <&PIO2 6 OUT>;
+						rx	= <&PIO2 7 IN>;
+					};
+				};
+			};
+		};
+
+		pin-controller-front {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih416-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,syscfg		= <&syscfg_front>;
+			st,syscfg-offsets	= <0 40 50 60 100>;
+			ranges;
+
+			PIO5: pinctrl@fee00000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee00000 0x100>;
+				st,bank-name  = "PIO5";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO6: pinctrl@fee01000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee01000 0x100>;
+				st,bank-name  = "PIO6";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO7: pinctrl@fee02000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee02000 0x100>;
+				st,bank-name  = "PIO7";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO8: pinctrl@fee03000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee03000 0x100>;
+				st,bank-name  = "PIO8";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO9: pinctrl@fee04000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee04000 0x100>;
+				st,bank-name  = "PIO9";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO10: pinctrl@fee05000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee05000 0x100>;
+				st,bank-name  = "PIO10";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO11: pinctrl@fee06000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee06000 0x100>;
+				st,bank-name  = "PIO11";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO12: pinctrl@fee07000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee07000 0x100>;
+				st,bank-name  = "PIO12";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO30: pinctrl@fee08000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee08000 0x100>;
+				st,bank-name  = "PIO30";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO31: pinctrl@fee09000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfee09000 0x100>;
+				st,bank-name  = "PIO31";
+				st,retime-pin-mask = <0xff>;
+			};
+		};
+
+		pin-controller-rear {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih416-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,syscfg		= <&syscfg_rear>;
+			st,syscfg-offsets	= <0 40 50 60 100>;
+			ranges;
+
+			PIO13: pinctrl@fe820000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe820000 0x100>;
+				st,bank-name  = "PIO13";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO14: pinctrl@fe821000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe821000 0x100>;
+				st,bank-name  = "PIO14";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO15: pinctrl@fe822000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe822000 0x100>;
+				st,bank-name  = "PIO15";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO16: pinctrl@fe823000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe823000 0x100>;
+				st,bank-name  = "PIO16";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO17: pinctrl@fe824000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe824000 0x100>;
+				st,bank-name  = "PIO17";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO18: pinctrl@fe825000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfe825000 0x100>;
+				st,bank-name  = "PIO18";
+				st,retime-pin-mask = <0xf>;
+			};
+
+			serial2 {
+				pinctrl_serial2: serial2-0 {
+					st,function = <ALT2>;
+					st,pins {
+						tx	= <&PIO17 4 OUT>;
+						rx	= <&PIO17 5 IN>;
+						output-enable	= <&PIO11 3 OUT>;
+					};
+				};
+			};
+		};
+
+		pin-controller-fvdp-fe {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih416-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,syscfg		= <&syscfg_fvdp_fe>;
+			st,syscfg-offsets	= <0 40 50 60 100>;
+			ranges;
+
+			PIO100: pinctrl@fd6b0000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd6b0000 0x100>;
+				st,bank-name  = "PIO100";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO101: pinctrl@fd6b1000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd6b1000 0x100>;
+				st,bank-name  = "PIO101";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO102: pinctrl@fd6b2000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd6b2000 0x100>;
+				st,bank-name  = "PIO102";
+				st,retime-pin-mask = <0xff>;
+			};
+		};
+
+		pin-controller-fvdp-lite {
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			compatible	= "st,stih416-pinctrl", "simple-bus";
+			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
+			st,syscfg		= <&syscfg_fvdp_lite>;
+			st,syscfg-offsets	= <0 40 50 60 100>;
+			ranges;
+
+			PIO103: pinctrl@fd330000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd330000 0x100>;
+				st,bank-name  = "PIO103";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO104: pinctrl@fd331000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd331000 0x100>;
+				st,bank-name  = "PIO104";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO105: pinctrl@fd332000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd332000 0x100>;
+				st,bank-name  = "PIO105";
+				st,retime-pin-mask = <0xff>;
+			};
+			PIO106: pinctrl@fd333000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd333000 0x100>;
+				st,bank-name  = "PIO106";
+				st,retime-pin-mask = <0xff>;
+			};
+
+			PIO107: pinctrl@fd334000 {
+				#gpio-cells	= <1>;
+				compatible	= "st,stixxxx-gpio";
+				gpio-controller;
+				reg = <0xfd334000 0x100>;
+				st,bank-name  = "PIO107";
+				st,retime-pin-mask = <0xf>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
new file mode 100644
index 0000000..7dbe450
--- /dev/null
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 STMicroelectronics Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih41x.dtsi"
+#include "stih416-clock.dtsi"
+#include "stih416-pinctrl.dtsi"
+/ {
+	L2: cache-controller {
+		compatible = "arm,pl310-cache";
+		reg = <0xfffe2000 0x1000>;
+		arm,data-latency = <3 3 3>;
+		arm,tag-latency = <2 2 2>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&intc>;
+		ranges;
+		compatible	= "simple-bus";
+
+		syscfg_sbc:syscfg@fe600000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfe600000 0x1000>;
+			syscfg-range	= <0 999>;
+			syscfg-name	= "SYSCFG_SBC";
+		};
+		syscfg_front:syscfg@fee10000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfee10000 0x1000>;
+			syscfg-range	= <1000 999>;
+			syscfg-name	= "SYSCFG_FRONT";
+		};
+		syscfg_rear:syscfg@fe830000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfe830000 0x1000>;
+			syscfg-range	= <2000 999>;
+			syscfg-name	= "SYSCFG_REAR";
+		};
+
+		/* MPE */
+		syscfg_fvdp_fe:syscfg@fddf0000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfddf0000 0x1000>;
+			syscfg-range	= <5000 999>;
+			syscfg-name	= "SYSCFG_FVDP_FE";
+		};
+		syscfg_fvdp_lite:syscfg@fd6a0000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfd6a0000 0x1000>;
+			syscfg-range	= <6000 999>;
+			syscfg-name	= "SYSCFG_FVDP_LITE";
+		};
+
+		syscfg_cpu:syscfg@fdde0000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfdde0000 0x1000>;
+			syscfg-range	= <7000 999>;
+			syscfg-name	= "SYSCFG_CPU";
+		};
+
+		syscfg_compo:syscfg@fd320000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfd320000 0x1000>;
+			syscfg-range	= <8000 999>;
+			syscfg-name	= "SYSCFG_COMPO";
+		};
+
+		syscfg_transport:syscfg@fd690000{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfd690000 0x1000>;
+			syscfg-range	= <9000 999>;
+			syscfg-name	= "SYSCFG_TRANSPORT";
+		};
+
+		syscfg_lpm:syscfg@fe4b5100{
+			compatible	= "st,stih416-syscfg";
+			reg		= <0xfe4b5100 0x8>;
+			syscfg-range	= <0 10>;
+			syscfg-name	= "LPM_CFG_REGS";
+		};
+
+		serial2: serial@fed32000{
+			compatible	= "st,asc";
+			status 		= "disabled";
+			reg		= <0xfed32000 0x2c>;
+			interrupts	= <0 197 0>;
+			clocks          = <&CLK_S_ICN_REG_0>;
+			pinctrl-names 	= "default";
+			pinctrl-0 	= <&pinctrl_serial2>;
+		};
+
+		/* SBC_UART1 */
+		sbc_serial1: serial@fe531000 {
+			compatible	= "st,asc";
+			status 		= "disabled";
+			reg		= <0xfe531000 0x2c>;
+			interrupts	= <0 210 0>;
+			pinctrl-names 	= "default";
+			pinctrl-0 	= <&pinctrl_sbc_serial1>;
+			clocks          = <&CLK_SYSIN>;
+		};
+	};
+};
diff --git a/arch/arm/mach-stixxxx/board-dt.c b/arch/arm/mach-stixxxx/board-dt.c
index 52ce665..2b2552e 100644
--- a/arch/arm/mach-stixxxx/board-dt.c
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -37,10 +37,11 @@ static void __init stih41x_timer_init(void)
 
 static const char *stih41x_dt_match[] __initdata = {
 	"st,stih415",
+	"st,stih416",
 	NULL
 };
 
-DT_MACHINE_START(STM, "STiH415 SoC with Flattened Device Tree")
+DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
 	.init_time	= stih41x_timer_init,
 	.smp		= smp_ops(stixxxx_smp_ops),
 	.dt_compat	= stih41x_dt_match,
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 08/11] ARM:stixxxx: Add DEBUG_LL console support
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (6 preceding siblings ...)
  2013-06-10  9:27   ` [PATCH v2 07/11] ARM:stixxxx: Add STiH416 " Srinivas KANDAGATLA
@ 2013-06-10  9:27   ` Srinivas KANDAGATLA
  2013-06-10  9:27   ` [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig Srinivas KANDAGATLA
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

This patch adds low level debug uart support to stixxxx based SOCs.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/Kconfig.debug           |   38 +++++++++++++++++++++++
 arch/arm/include/debug/stixxxx.S |   61 ++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-stixxxx/board-dt.c |    2 +
 3 files changed, 101 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/debug/stixxxx.S

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 1d41908..cc98ef3 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -483,6 +483,16 @@ choice
 		  This option selects UART0 on VIA/Wondermedia System-on-a-chip
 		  devices, including VT8500, WM8505, WM8650 and WM8850.
 
+	config DEBUG_STIXXXX_UART
+		depends on ARCH_STIXXXX
+		bool "Use StiH415/416 ASC for low-level debug"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on StiH415/416 based platforms like B2000, B2020.
+		  It support UART2 and SBC_UART1.
+
+		  If unsure, say N.
+
 	config DEBUG_LL_UART_NONE
 		bool "No low-level debugging UART"
 		depends on !ARCH_MULTIPLATFORM
@@ -617,6 +627,33 @@ choice
 
 endchoice
 
+choice
+	prompt "Low-level debug console UART"
+	depends on DEBUG_LL && DEBUG_STIXXXX_UART
+
+	config STIH41X_DEBUG_ASC2
+		bool "ASC2 UART"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on STiH415/416 based platforms like b2000, which has
+		  default UART wired up to ASC2.
+
+		  If unsure, say N.
+
+	config STIH41X_DEBUG_SBC_ASC1
+		bool "SBC ASC1 UART"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on STiH415/416 based platforms like b2020. which has
+		  default UART wired up to SBC ASC1.
+
+		  If unsure, say N.
+
+endchoice
+
+
+
+
 config DEBUG_LL_INCLUDE
 	string
 	default "debug/bcm2835.S" if DEBUG_BCM2835
@@ -641,6 +678,7 @@ config DEBUG_LL_INCLUDE
 				 DEBUG_MMP_UART3
 	default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
 	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
+	default "debug/stixxxx.S" if DEBUG_STIXXXX_UART
 	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
 	default "debug/ux500.S" if DEBUG_UX500_UART
diff --git a/arch/arm/include/debug/stixxxx.S b/arch/arm/include/debug/stixxxx.S
new file mode 100644
index 0000000..7bc02a7
--- /dev/null
+++ b/arch/arm/include/debug/stixxxx.S
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/include/debug/stixxxx.S
+ *
+ * Debugging macro include header
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ *
+ * 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.
+ */
+
+#define STIH41X_COMMS_BASE              0xfed00000
+#define STIH41X_ASC2_BASE               (STIH41X_COMMS_BASE+0x32000)
+
+#define STIH41X_SBC_LPM_BASE            0xfe400000
+#define STIH41X_SBC_COMMS_BASE          (STIH41X_SBC_LPM_BASE + 0x100000)
+#define STIH41X_SBC_ASC1_BASE           (STIH41X_SBC_COMMS_BASE + 0x31000)
+
+
+#define VIRT_ADDRESS(x)		(x - 0x1000000)
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_ASC2)
+#define DEBUG_LL_UART_BASE	STIH41X_ASC2_BASE
+#endif
+
+#if IS_ENABLED(CONFIG_STIH41X_DEBUG_SBC_ASC1)
+#define DEBUG_LL_UART_BASE	STIH41X_SBC_ASC1_BASE
+#endif
+
+#ifndef DEBUG_LL_UART_BASE
+#error "DEBUG UART is not Configured"
+#endif
+
+#define ASC_TX_BUF_OFF  0x04
+#define ASC_CTRL_OFF    0x0c
+#define ASC_STA_OFF     0x14
+
+#define ASC_STA_TX_FULL         (1<<9)
+#define ASC_STA_TX_EMPTY        (1<<1)
+
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rp,      =DEBUG_LL_UART_BASE	@ physical base
+		ldr	\rv,      =VIRT_ADDRESS(DEBUG_LL_UART_BASE) @ virt base
+		.endm
+
+                .macro  senduart,rd,rx
+                strb    \rd, [\rx, #ASC_TX_BUF_OFF]
+                .endm
+
+                .macro  waituart,rd,rx
+1001:           ldr     \rd, [\rx, #ASC_STA_OFF]
+                tst     \rd, #ASC_STA_TX_FULL
+                bne     1001b
+                .endm
+
+                .macro  busyuart,rd,rx
+1001:           ldr     \rd, [\rx, #ASC_STA_OFF]
+                tst     \rd, #ASC_STA_TX_EMPTY
+                beq     1001b
+                .endm
diff --git a/arch/arm/mach-stixxxx/board-dt.c b/arch/arm/mach-stixxxx/board-dt.c
index 2b2552e..2482d139 100644
--- a/arch/arm/mach-stixxxx/board-dt.c
+++ b/arch/arm/mach-stixxxx/board-dt.c
@@ -11,6 +11,7 @@
 #include <linux/clocksource.h>
 #include <linux/irq.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
 #include <asm/mach/arch.h>
 
 #include "smp.h"
@@ -42,6 +43,7 @@ static const char *stih41x_dt_match[] __initdata = {
 };
 
 DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
+	.map_io		= debug_ll_io_init,
 	.init_time	= stih41x_timer_init,
 	.smp		= smp_ops(stixxxx_smp_ops),
 	.dt_compat	= stih41x_dt_match,
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (7 preceding siblings ...)
  2013-06-10  9:27   ` [PATCH v2 08/11] ARM:stixxxx: Add DEBUG_LL console support Srinivas KANDAGATLA
@ 2013-06-10  9:27   ` Srinivas KANDAGATLA
  2013-06-10 10:40     ` Mark Rutland
  2013-06-10  9:28   ` [PATCH v2 10/11] ARM:stih41x: Add B2000 board support Srinivas KANDAGATLA
  2013-06-10  9:28   ` [PATCH v2 11/11] ARM:stih41x: Add B2020 " Srinivas KANDAGATLA
  10 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:27 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

This patch adds stih415 and stih416 support to multi_v7_defconfig.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/configs/multi_v7_defconfig |   32 +++++++++++++++-----------------
 1 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2e67a27..8a5cd5c 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1,23 +1,20 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
-CONFIG_ARCH_SIRF=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SUNXI=y
-CONFIG_ARCH_WM8850=y
-# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
-CONFIG_ARCH_ZYNQ=y
-CONFIG_ARM_ERRATA_754322=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
+CONFIG_ARCH_STIXXXX=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SIRF=y
+CONFIG_ARCH_WM8850=y
+CONFIG_ARCH_ZYNQ=y
 CONFIG_SMP=y
-CONFIG_ARM_ARCH_TIMER=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_HIGHPTE=y
@@ -25,27 +22,30 @@ CONFIG_ARM_APPENDED_DTB=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_NET=y
+CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_SATA_HIGHBANK=y
 CONFIG_SATA_MV=y
-CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
+CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_DW=y
-CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_SIRFSOC=y
 CONFIG_SERIAL_SIRFSOC_CONSOLE=y
 CONFIG_SERIAL_VT8500=y
 CONFIG_SERIAL_VT8500_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
 CONFIG_IPMI_HANDLER=y
 CONFIG_IPMI_SI=y
 CONFIG_I2C=y
@@ -54,7 +54,6 @@ CONFIG_I2C_SIRF=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_SIRF=y
-CONFIG_GPIO_PL061=y
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
 CONFIG_FB_WM8505=y
@@ -67,7 +66,6 @@ CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_SPEAR=y
-CONFIG_MMC_WMT=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
@@ -75,9 +73,9 @@ CONFIG_EDAC_HIGHBANK_L2=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_VT8500=y
-CONFIG_PWM=y
-CONFIG_PWM_VT8500=y
 CONFIG_DMADEVICES=y
-CONFIG_PL330_DMA=y
-CONFIG_SIRF_DMA=y
 CONFIG_DW_DMAC=y
+CONFIG_SIRF_DMA=y
+CONFIG_PL330_DMA=y
+CONFIG_PWM=y
+CONFIG_PWM_VT8500=y
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 10/11] ARM:stih41x: Add B2000 board support
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (8 preceding siblings ...)
  2013-06-10  9:27   ` [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig Srinivas KANDAGATLA
@ 2013-06-10  9:28   ` Srinivas KANDAGATLA
  2013-06-10  9:28   ` [PATCH v2 11/11] ARM:stih41x: Add B2020 " Srinivas KANDAGATLA
  10 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

B2000 board is reference board for STIH415/416 SOCs, it has
2 x UART, 4x USB, 2 x Ethernet, 1 x SATA, 1 x PCIe, and 1GB RAM.

This patch add initial support to b2000 with STiH415/416 with UART2 as
console and a heard beat LED.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/Makefile           |    2 +
 arch/arm/boot/dts/stih415-b2000.dts  |   15 ++++++++++++
 arch/arm/boot/dts/stih416-b2000.dts  |   16 +++++++++++++
 arch/arm/boot/dts/stih41x-b2000.dtsi |   41 ++++++++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih415-b2000.dts
 create mode 100644 arch/arm/boot/dts/stih416-b2000.dts
 create mode 100644 arch/arm/boot/dts/stih41x-b2000.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f0895c5..d4615fd 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -177,6 +177,8 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
 	spear320-evb.dtb \
 	spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
+dtb-$(CONFIG_ARCH_STIXXXX)+= stih415-b2000.dtb \
+	stih416-b2000.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += \
 	sun4i-a10-cubieboard.dtb \
 	sun4i-a10-mini-xplus.dtb \
diff --git a/arch/arm/boot/dts/stih415-b2000.dts b/arch/arm/boot/dts/stih415-b2000.dts
new file mode 100644
index 0000000..d4af531
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2000.dts
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2000.dtsi"
+/ {
+	model = "STiH415 B2000 Board";
+	compatible = "st,stih415", "st,stih415-b2000";
+};
diff --git a/arch/arm/boot/dts/stih416-b2000.dts b/arch/arm/boot/dts/stih416-b2000.dts
new file mode 100644
index 0000000..a5eb6ee
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2000.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2000.dtsi"
+
+/ {
+	compatible = "st,stih416", "st,stih416-b2000";
+	model = "STiH416 B2000";
+};
diff --git a/arch/arm/boot/dts/stih41x-b2000.dtsi b/arch/arm/boot/dts/stih41x-b2000.dtsi
new file mode 100644
index 0000000..8e694d2
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2000.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+
+	memory{
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyAS0,115200";
+		linux,stdout-path = &serial2;
+	};
+
+	aliases {
+		ttyAS0 = &serial2;
+	};
+
+	soc {
+		serial2: serial@fed32000 {
+			status = "okay";
+		};
+
+		leds {
+			compatible	= "gpio-leds";
+			fp_led {
+				#gpio-cells = <1>;
+				label	= "Front Panel LED";
+				gpios	= <&PIO105 7>;
+				linux,default-trigger	= "heartbeat";
+			};
+		};
+
+	};
+};
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 11/11] ARM:stih41x: Add B2020 board support
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
                     ` (9 preceding siblings ...)
  2013-06-10  9:28   ` [PATCH v2 10/11] ARM:stih41x: Add B2000 board support Srinivas KANDAGATLA
@ 2013-06-10  9:28   ` Srinivas KANDAGATLA
  10 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10  9:28 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Srinivas Kandagatla,
	Stephen Gallimore, Stuart Menefy, Thomas Gleixner, Tony Prisk

B2020 ADI board is reference board for STIH415/416 SOCs, it has 2 x
UART, 4x USB, 1 x Ethernet, 1 x SATA, 1 x PCIe, and 2GB RAM  with
standard set-top box IPs.

This patch adds initial support to B2020 with STiH415/416 with SBC_UART1
as console and a heard beat LED.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
CC: Stephen Gallimore <stephen.gallimore@st.com>
CC: Stuart Menefy <stuart.menefy@st.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/boot/dts/Makefile           |    4 ++-
 arch/arm/boot/dts/stih415-b2020.dts  |   15 ++++++++++++
 arch/arm/boot/dts/stih416-b2020.dts  |   16 +++++++++++++
 arch/arm/boot/dts/stih41x-b2020.dtsi |   42 ++++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih415-b2020.dts
 create mode 100644 arch/arm/boot/dts/stih416-b2020.dts
 create mode 100644 arch/arm/boot/dts/stih41x-b2020.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d4615fd..0d24c95 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -178,7 +178,9 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
 	spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
 dtb-$(CONFIG_ARCH_STIXXXX)+= stih415-b2000.dtb \
-	stih416-b2000.dtb
+	stih416-b2000.dtb \
+	stih415-b2020.dtb \
+	stih416-b2020.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += \
 	sun4i-a10-cubieboard.dtb \
 	sun4i-a10-mini-xplus.dtb \
diff --git a/arch/arm/boot/dts/stih415-b2020.dts b/arch/arm/boot/dts/stih415-b2020.dts
new file mode 100644
index 0000000..442b019
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-b2020.dts
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih415.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+	model = "STiH415 B2020 Board";
+	compatible = "st,stih415", "st,stih415-b2020";
+};
diff --git a/arch/arm/boot/dts/stih416-b2020.dts b/arch/arm/boot/dts/stih416-b2020.dts
new file mode 100644
index 0000000..276f28d
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-b2020.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/dts-v1/;
+#include "stih416.dtsi"
+#include "stih41x-b2020.dtsi"
+/ {
+	model = "STiH416 B2020";
+	compatible = "st,stih416", "st,stih416-b2020";
+
+};
diff --git a/arch/arm/boot/dts/stih41x-b2020.dtsi b/arch/arm/boot/dts/stih41x-b2020.dtsi
new file mode 100644
index 0000000..133e181
--- /dev/null
+++ b/arch/arm/boot/dts/stih41x-b2020.dtsi
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+ *
+ * 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
+ * publishhed by the Free Software Foundation.
+ */
+/ {
+	memory{
+		device_type = "memory";
+		reg = <0x40000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyAS0,115200";
+		linux,stdout-path = &sbc_serial1;
+	};
+
+	aliases {
+		ttyAS0 = &sbc_serial1;
+	};
+	soc {
+		sbc_serial1: serial@fe531000 {
+			status = "okay";
+		};
+
+		leds {
+			compatible	= "gpio-leds";
+			red {
+				#gpio-cells = <1>;
+				label	= "Front Panel LED";
+				gpios	= <&PIO4 1>;
+				linux,default-trigger	= "heartbeat";
+			};
+			green {
+				gpios	= <&PIO4 7>;
+				default-state = "off";
+			};
+		};
+	};
+};
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 01/11] serial:st-asc: Add ST ASC driver.
  2013-06-10  9:21   ` [PATCH v2 01/11] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
@ 2013-06-10  9:35     ` Russell King - ARM Linux
  2013-06-10 11:53       ` Srinivas KANDAGATLA
  0 siblings, 1 reply; 228+ messages in thread
From: Russell King - ARM Linux @ 2013-06-10  9:35 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On Mon, Jun 10, 2013 at 10:21:00AM +0100, Srinivas KANDAGATLA wrote:
> This patch adds support to ASC (asynchronous serial controller)
> driver, which is basically a standard serial driver. This IP is common
> across all the ST parts for settop box platforms.
> 
> ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
> It support all industry standard baud rates.

Your driver is not POSIX compliant.

> +		for (; count != 0; count--) {
> +			c = asc_in(port, ASC_RXBUF);
> +			flag = TTY_NORMAL;
> +			port->icount.rx++;
> +
> +			if (unlikely(c & ASC_RXBUF_FE)) {
> +				if (c == ASC_RXBUF_FE) {
> +					port->icount.brk++;
> +					if (uart_handle_break(port))
> +						continue;
> +					flag = TTY_BREAK;
> +				} else {
> +					port->icount.frame++;
> +					flag = TTY_FRAME;
> +				}
> +			} else if (ascport->check_parity &&
> +				   unlikely(c & ASC_RXBUF_PE)) {
> +				port->icount.parity++;
> +				flag = TTY_PARITY;
> +			}
> +
> +			if (uart_handle_sysrq_char(port, c))
> +				continue;
> +			tty_insert_flip_char(tport, c & 0xff, flag);
> +		}
> +		if (overrun) {
> +			port->icount.overrun++;
> +			tty_insert_flip_char(tport, 0, TTY_OVERRUN);
> +		}

No support for ignoring error conditions.  No support for ignoring all
input... and:

> +static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
> +			    struct ktermios *old)
> +{
> +	struct asc_port *ascport = to_asc_port(port);
> +	unsigned int baud;
> +	u32 ctrl_val;
> +	tcflag_t cflag;
> +	unsigned long flags;
> +
> +	port->uartclk = clk_get_rate(ascport->clk);
> +
> +	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
> +	cflag = termios->c_cflag;
> +
> +	spin_lock_irqsave(&port->lock, flags);
> +
> +	/* read control register */
> +	ctrl_val = asc_in(port, ASC_CTL);
> +
> +	/* stop serial port and reset value */
> +	asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
> +	ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
> +
> +	/* reset fifo rx & tx */
> +	asc_out(port, ASC_TXRESET, 1);
> +	asc_out(port, ASC_RXRESET, 1);
> +
> +	/* set character length */
> +	if ((cflag & CSIZE) == CS7) {
> +		ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
> +	} else {
> +		ctrl_val |= (cflag & PARENB) ?  ASC_CTL_MODE_8BIT_PAR :
> +						ASC_CTL_MODE_8BIT;
> +	}
> +
> +	ascport->check_parity = (cflag & PARENB) ? 1 : 0;
> +
> +	/* set stop bit */
> +	ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
> +
> +	/* odd parity */
> +	if (cflag & PARODD)
> +		ctrl_val |= ASC_CTL_PARITYODD;
> +
> +	/* hardware flow control */
> +	if ((cflag & CRTSCTS) && ascport->hw_flow_control)
> +		ctrl_val |= ASC_CTL_CTSENABLE;

This doesn't reflect those facts back into the termios structure to
indicate that they aren't supported.

Consider using uart_port's ignore and read status masks to implement
the break, framing, parity and overrun checking in your interrupt
handler using the same methodology as drivers like 8250, amba-pl011
etc.  That will help you get these code sequences correct.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-10  9:26   ` =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
@ 2013-06-10  9:55     ` Michal Simek
  2013-06-10 11:08     ` Michal Simek
       [not found]     ` <CAHTX3d+dk3W_9b7SVUokWq4KYXnj=Z1=WPj5zJ-gUvJqqwE=+Q@mail.gmail.com>
  2 siblings, 0 replies; 228+ messages in thread
From: Michal Simek @ 2013-06-10  9:55 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=yes, Size: 2 bytes --]



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

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-10  9:27   ` [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig Srinivas KANDAGATLA
@ 2013-06-10 10:40     ` Mark Rutland
  2013-06-10 10:58       ` Srinivas KANDAGATLA
  0 siblings, 1 reply; 228+ messages in thread
From: Mark Rutland @ 2013-06-10 10:40 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Mauro Carvalho Chehab, linux-doc, linux,
	Samuel Ortiz, Stephen Gallimore, linux-serial, grant.likely,
	devicetree-discuss, rob.herring, Stuart Menefy, Mark Brown,
	John Stultz, Thomas Gleixner, Greg Kroah-Hartman, linux-kernel,
	Andrew Morton, David S. Miller

On Mon, Jun 10, 2013 at 10:27:57AM +0100, Srinivas KANDAGATLA wrote:
> This patch adds stih415 and stih416 support to multi_v7_defconfig.

This seems to drop a few options also:

CONFIG_ARM_ARCH_TIMER
CONFIG_ARM_ERRATA_754322
CONFIG_EXPERIMENTAL
CONFIG_GPIO_PL061
CONFIG_MMC_WMT

I just applied this to v3.10-rc5, and ran `make ARCH=arm multi_v7_defconfig`.
It seems MMC_WMT and GPIO_PL061 get selected elsewhere, but ARM_ARCH_TIMER and
ARM_ERRATA_754322 are left unselected.

Thanks,
Mark.

> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>  arch/arm/configs/multi_v7_defconfig |   32 +++++++++++++++-----------------
>  1 files changed, 15 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index 2e67a27..8a5cd5c 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -1,23 +1,20 @@
> -CONFIG_EXPERIMENTAL=y
>  CONFIG_NO_HZ=y
>  CONFIG_HIGH_RES_TIMERS=y
>  CONFIG_ARCH_MVEBU=y
>  CONFIG_MACH_ARMADA_370=y
> -CONFIG_ARCH_SIRF=y
>  CONFIG_MACH_ARMADA_XP=y
>  CONFIG_ARCH_HIGHBANK=y
>  CONFIG_ARCH_SOCFPGA=y
> -CONFIG_ARCH_SUNXI=y
> -CONFIG_ARCH_WM8850=y
> -# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
> -CONFIG_ARCH_ZYNQ=y
> -CONFIG_ARM_ERRATA_754322=y
>  CONFIG_PLAT_SPEAR=y
>  CONFIG_ARCH_SPEAR13XX=y
>  CONFIG_MACH_SPEAR1310=y
>  CONFIG_MACH_SPEAR1340=y
> +CONFIG_ARCH_STIXXXX=y
> +CONFIG_ARCH_SUNXI=y
> +CONFIG_ARCH_SIRF=y
> +CONFIG_ARCH_WM8850=y
> +CONFIG_ARCH_ZYNQ=y
>  CONFIG_SMP=y
> -CONFIG_ARM_ARCH_TIMER=y
>  CONFIG_AEABI=y
>  CONFIG_HIGHMEM=y
>  CONFIG_HIGHPTE=y
> @@ -25,27 +22,30 @@ CONFIG_ARM_APPENDED_DTB=y
>  CONFIG_VFP=y
>  CONFIG_NEON=y
>  CONFIG_NET=y
> +CONFIG_DEVTMPFS=y
>  CONFIG_BLK_DEV_SD=y
>  CONFIG_ATA=y
> +CONFIG_SATA_AHCI_PLATFORM=y
>  CONFIG_SATA_HIGHBANK=y
>  CONFIG_SATA_MV=y
> -CONFIG_SATA_AHCI_PLATFORM=y
>  CONFIG_NETDEVICES=y
>  CONFIG_NET_CALXEDA_XGMAC=y
>  CONFIG_SMSC911X=y
>  CONFIG_STMMAC_ETH=y
> +CONFIG_KEYBOARD_SPEAR=y
>  CONFIG_SERIO_AMBAKMI=y
>  CONFIG_SERIAL_8250=y
>  CONFIG_SERIAL_8250_CONSOLE=y
>  CONFIG_SERIAL_8250_DW=y
> -CONFIG_KEYBOARD_SPEAR=y
>  CONFIG_SERIAL_AMBA_PL011=y
>  CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
> -CONFIG_SERIAL_OF_PLATFORM=y
>  CONFIG_SERIAL_SIRFSOC=y
>  CONFIG_SERIAL_SIRFSOC_CONSOLE=y
>  CONFIG_SERIAL_VT8500=y
>  CONFIG_SERIAL_VT8500_CONSOLE=y
> +CONFIG_SERIAL_OF_PLATFORM=y
> +CONFIG_SERIAL_ST_ASC=y
> +CONFIG_SERIAL_ST_ASC_CONSOLE=y
>  CONFIG_IPMI_HANDLER=y
>  CONFIG_IPMI_SI=y
>  CONFIG_I2C=y
> @@ -54,7 +54,6 @@ CONFIG_I2C_SIRF=y
>  CONFIG_SPI=y
>  CONFIG_SPI_PL022=y
>  CONFIG_SPI_SIRF=y
> -CONFIG_GPIO_PL061=y
>  CONFIG_FB=y
>  CONFIG_FB_ARMCLCD=y
>  CONFIG_FB_WM8505=y
> @@ -67,7 +66,6 @@ CONFIG_MMC_ARMMMCI=y
>  CONFIG_MMC_SDHCI=y
>  CONFIG_MMC_SDHCI_PLTFM=y
>  CONFIG_MMC_SDHCI_SPEAR=y
> -CONFIG_MMC_WMT=y
>  CONFIG_EDAC=y
>  CONFIG_EDAC_MM_EDAC=y
>  CONFIG_EDAC_HIGHBANK_MC=y
> @@ -75,9 +73,9 @@ CONFIG_EDAC_HIGHBANK_L2=y
>  CONFIG_RTC_CLASS=y
>  CONFIG_RTC_DRV_PL031=y
>  CONFIG_RTC_DRV_VT8500=y
> -CONFIG_PWM=y
> -CONFIG_PWM_VT8500=y
>  CONFIG_DMADEVICES=y
> -CONFIG_PL330_DMA=y
> -CONFIG_SIRF_DMA=y
>  CONFIG_DW_DMAC=y
> +CONFIG_SIRF_DMA=y
> +CONFIG_PL330_DMA=y
> +CONFIG_PWM=y
> +CONFIG_PWM_VT8500=y
> -- 
> 1.7.6.5
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-10 10:40     ` Mark Rutland
@ 2013-06-10 10:58       ` Srinivas KANDAGATLA
  2013-06-10 13:15         ` Mark Rutland
  0 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 10:58 UTC (permalink / raw)
  To: Mark Rutland
  Cc: David S. Miller, linux, Samuel Ortiz, linux-doc,
	Greg Kroah-Hartman, devicetree-discuss, Stephen Gallimore,
	rob.herring, linux-kernel, Stuart Menefy, Mark Brown,
	John Stultz, linux-serial, grant.likely, Thomas Gleixner,
	Andrew Morton, linux-arm-kernel, Mauro Carvalho Chehab

Thanks for testing...
On 10/06/13 11:40, Mark Rutland wrote:
> On Mon, Jun 10, 2013 at 10:27:57AM +0100, Srinivas KANDAGATLA wrote:
>> > This patch adds stih415 and stih416 support to multi_v7_defconfig.
> This seems to drop a few options also:
> 
> CONFIG_ARM_ARCH_TIMER

Same as last comment 2:
> CONFIG_ARM_ERRATA_754322
ARM_ERRATA_754322 gets selected by the mach level Kconfig of stixxxx, so
it disappears, Should the mach level Kconfig select that?

> CONFIG_EXPERIMENTAL
> CONFIG_GPIO_PL061
> CONFIG_MMC_WMT

Comment 2: Without any modifications to multi_v7_defconfig if I run
savedefconfig CONFIG_ARM_ARCH_TIMER, CONFIG_EXPERIMENTAL,
CONFIG_GPIO_PL061 and CONFIG_MMC_WMT disappears.
Which suggests that these options seems to be selected by another
kconfigs or mach level. And since then the multi_v7_defconfig was not
run with savedefconfig.


Thanks,
srini
> 
> I just applied this to v3.10-rc5, and ran `make ARCH=arm multi_v7_defconfig`.
> It seems MMC_WMT and GPIO_PL061 get selected elsewhere, but ARM_ARCH_TIMER and
> ARM_ERRATA_754322 are left unselected.
> 
> Thanks,
> Mark.
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-10  9:26   ` =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
  2013-06-10  9:55     ` [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support Michal Simek
@ 2013-06-10 11:08     ` Michal Simek
       [not found]     ` <CAHTX3d+dk3W_9b7SVUokWq4KYXnj=Z1=WPj5zJ-gUvJqqwE=+Q@mail.gmail.com>
  2 siblings, 0 replies; 228+ messages in thread
From: Michal Simek @ 2013-06-10 11:08 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=yes, Size: 2 bytes --]



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

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
       [not found]     ` <CAHTX3d+dk3W_9b7SVUokWq4KYXnj=Z1=WPj5zJ-gUvJqqwE=+Q@mail.gmail.com>
@ 2013-06-10 11:46       ` Srinivas KANDAGATLA
  2013-06-10 23:19         ` Russell King - ARM Linux
  0 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 11:46 UTC (permalink / raw)
  To: Michal Simek
  Cc: linux-arm, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, Russell King, linux-doc, LKML,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On 10/06/13 12:15, Michal Simek wrote:

Thankyou for your comments,
> Hi,
> 
> hmm - that's a nice bug that thunderbird is not able to send this email. :-(
> Let's comment it again via gmail.
>     diff --git a/arch/arm/boot/dts/stih415.dtsi
>     b/arch/arm/boot/dts/stih415.dtsi
>     new file mode 100644
>     index 0000000..6dcf5b4
>     --- /dev/null
>     +++ b/arch/arm/boot/dts/stih415.dtsi
...
>     +
>     +       soc {
>     +               #address-cells = <1>;
>     +               #size-cells = <1>;
>     +               interrupt-parent = <&intc>;
>     +               ranges;
>     +               compatible      = "simple-bus";
> 
> 
> 
> Rob and Grant: what's the purpose of SoC node.
> It seems to me odd that SoC is compatible with simple-bus.

All the drivers on this SOC are based on platform bus, so we use
simple-bus, here.

>     diff --git a/arch/arm/boot/dts/stih41x.dtsi
>     b/arch/arm/boot/dts/stih41x.dtsi
>     new file mode 100644
>     index 0000000..7321403
>     --- /dev/null
>     +++ b/arch/arm/boot/dts/stih41x.dtsi
>     @@ -0,0 +1,38 @@
>     +/ {
>     +       #address-cells = <1>;
>     +       #size-cells = <1>;
>     +
>     +       cpus {
>     +               #address-cells = <1>;
>     +               #size-cells = <0>;
>     +               cpu@0 {
>     +                       compatible = "arm,cortex-a9";
>     +                       reg = <0>;
>     +               };
>     +               cpu@1 {
>     +                       compatible = "arm,cortex-a9";
>     +                       reg = <1>;
>     +               };
>     +       };
>     +
> 
> 
> I believe your SoC also has a bus here.

It does but there is no active driver to manage it.

>     --- /dev/null
>     +++ b/arch/arm/mach-stixxxx/board-dt.c
>     @@ -0,0 +1,47 @@

>     +
>     +void __init stih41x_l2x0_init(void)
>     +{
>     +       u32 way_size = 0x4;
>     +       u32 aux_ctrl;
>     +
>     +       aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
>     +               (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
>     +               (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
>     +               (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
> 
> 
> 
> #include <linux/bitops.h>
> Linus Walleij would write use  BIT() here

I will use BIT() macro.

>     diff --git a/arch/arm/mach-stixxxx/headsmp.S
>     b/arch/arm/mach-stixxxx/headsmp.S
>     new file mode 100644
>     index 0000000..3dd5c04
>     --- /dev/null
>     +++ b/arch/arm/mach-stixxxx/headsmp.S
>     @@ -0,0 +1,44 @@
>     +/*
>     + *  arch/arm/plat-stixxxx/headsmp.S
> 

>     +       .long   pen_release
> 
> 
> check that your SoC has no option to start/reset cpus separately.
> If yes, then you shouldn't use pen_release.
> We discussed this with Russel some days ago.
No, stih41x series can't reset the cores separately.
>  
> 
>     diff --git a/arch/arm/mach-stixxxx/platsmp.c
>     b/arch/arm/mach-stixxxx/platsmp.c
>     new file mode 100644
>     index 0000000..ffc40c0
>     --- /dev/null
>     +++ b/arch/arm/mach-stixxxx/platsmp.c
>     @@ -0,0 +1,117 @@
>     +/*
>     + *  arch/arm/plat-stixxxx/platsmp.c
> 
> 
> wrong.

Left over, will clean it up in next version.

>     + *  arch/arm/plat-stixxxx/platsmp.c
> 
> 
> incorrect.
Left over, will clean it up in next version.
>  
>     +extern struct smp_operations   stixxxx_smp_ops;
>     +extern void __iomem *stixxxx_scu_base_addr;
> 
> 
> Unused variable in this patch.
yes, I will remove stixxxx_scu_base_addr.

thanks,
srini



^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 01/11] serial:st-asc: Add ST ASC driver.
  2013-06-10  9:35     ` Russell King - ARM Linux
@ 2013-06-10 11:53       ` Srinivas KANDAGATLA
  0 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 11:53 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

Thankyou for your comment and suggestion,
I will fix the POSIX compliant issue.

On 10/06/13 10:35, Russell King - ARM Linux wrote:
> On Mon, Jun 10, 2013 at 10:21:00AM +0100, Srinivas KANDAGATLA wrote:
>> This patch adds support to ASC (asynchronous serial controller)
>> driver, which is basically a standard serial driver. This IP is common
>> across all the ST parts for settop box platforms.
>>
>> ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
>> It support all industry standard baud rates.
> 
> Your driver is not POSIX compliant.
> 
>> +		for (; count != 0; count--) {
>> +			c = asc_in(port, ASC_RXBUF);
>> +			flag = TTY_NORMAL;
>> +			port->icount.rx++;
>> +
>> +			if (unlikely(c & ASC_RXBUF_FE)) {
>> +				if (c == ASC_RXBUF_FE) {
>> +					port->icount.brk++;
>> +					if (uart_handle_break(port))
>> +						continue;
>> +					flag = TTY_BREAK;
>> +				} else {
>> +					port->icount.frame++;
>> +					flag = TTY_FRAME;
>> +				}
>> +			} else if (ascport->check_parity &&
>> +				   unlikely(c & ASC_RXBUF_PE)) {
>> +				port->icount.parity++;
>> +				flag = TTY_PARITY;
>> +			}
>> +
>> +			if (uart_handle_sysrq_char(port, c))
>> +				continue;
>> +			tty_insert_flip_char(tport, c & 0xff, flag);
>> +		}
>> +		if (overrun) {
>> +			port->icount.overrun++;
>> +			tty_insert_flip_char(tport, 0, TTY_OVERRUN);
>> +		}
> 
> No support for ignoring error conditions.  No support for ignoring all
> input... and:
> 
>> +static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
>> +			    struct ktermios *old)
>> +{
>> +	struct asc_port *ascport = to_asc_port(port);
>> +	unsigned int baud;
>> +	u32 ctrl_val;
>> +	tcflag_t cflag;
>> +	unsigned long flags;
>> +
>> +	port->uartclk = clk_get_rate(ascport->clk);
>> +
>> +	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
>> +	cflag = termios->c_cflag;
>> +
>> +	spin_lock_irqsave(&port->lock, flags);
>> +
>> +	/* read control register */
>> +	ctrl_val = asc_in(port, ASC_CTL);
>> +
>> +	/* stop serial port and reset value */
>> +	asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
>> +	ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
>> +
>> +	/* reset fifo rx & tx */
>> +	asc_out(port, ASC_TXRESET, 1);
>> +	asc_out(port, ASC_RXRESET, 1);
>> +
>> +	/* set character length */
>> +	if ((cflag & CSIZE) == CS7) {
>> +		ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
>> +	} else {
>> +		ctrl_val |= (cflag & PARENB) ?  ASC_CTL_MODE_8BIT_PAR :
>> +						ASC_CTL_MODE_8BIT;
>> +	}
>> +
>> +	ascport->check_parity = (cflag & PARENB) ? 1 : 0;
>> +
>> +	/* set stop bit */
>> +	ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
>> +
>> +	/* odd parity */
>> +	if (cflag & PARODD)
>> +		ctrl_val |= ASC_CTL_PARITYODD;
>> +
>> +	/* hardware flow control */
>> +	if ((cflag & CRTSCTS) && ascport->hw_flow_control)
>> +		ctrl_val |= ASC_CTL_CTSENABLE;
> 
> This doesn't reflect those facts back into the termios structure to
> indicate that they aren't supported.
> 
> Consider using uart_port's ignore and read status masks to implement
> the break, framing, parity and overrun checking in your interrupt
> handler using the same methodology as drivers like 8250, amba-pl011
> etc.  That will help you get these code sequences correct.
> 
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-10 10:58       ` Srinivas KANDAGATLA
@ 2013-06-10 13:15         ` Mark Rutland
  2013-06-13  9:24           ` Srinivas KANDAGATLA
  0 siblings, 1 reply; 228+ messages in thread
From: Mark Rutland @ 2013-06-10 13:15 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: David S. Miller, linux, Samuel Ortiz, linux-doc,
	Greg Kroah-Hartman, devicetree-discuss, Stephen Gallimore,
	rob.herring, linux-kernel, Stuart Menefy, Mark Brown,
	John Stultz, linux-serial, grant.likely, Thomas Gleixner,
	Andrew Morton, linux-arm-kernel, Mauro Carvalho Chehab

On Mon, Jun 10, 2013 at 11:58:38AM +0100, Srinivas KANDAGATLA wrote:
> Thanks for testing...
> On 10/06/13 11:40, Mark Rutland wrote:
> > On Mon, Jun 10, 2013 at 10:27:57AM +0100, Srinivas KANDAGATLA wrote:
> >> > This patch adds stih415 and stih416 support to multi_v7_defconfig.
> > This seems to drop a few options also:
> > 
> > CONFIG_ARM_ARCH_TIMER
> 
> Same as last comment 2:
> > CONFIG_ARM_ERRATA_754322
> ARM_ERRATA_754322 gets selected by the mach level Kconfig of stixxxx, so
> it disappears, Should the mach level Kconfig select that?
> 

I couldn't find the patch adding mach-stixxxx's Kconfig, though I seem to be
missing patch 6 of the series. As long as CONFIG_ARM_ERRATA_754322 appears in
the resulting .config, it should be fine.

> > CONFIG_EXPERIMENTAL
> > CONFIG_GPIO_PL061
> > CONFIG_MMC_WMT
> 
> Comment 2: Without any modifications to multi_v7_defconfig if I run
> savedefconfig CONFIG_ARM_ARCH_TIMER, CONFIG_EXPERIMENTAL,
> CONFIG_GPIO_PL061 and CONFIG_MMC_WMT disappears.
> Which suggests that these options seems to be selected by another
> kconfigs or mach level. And since then the multi_v7_defconfig was not
> run with savedefconfig.

CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
CONFIG_MMC_WMT get selected elsewhere, so that's fine.

It looks like the architected timer deselection is fallout of my own making,
the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
ARM_ARCH_TIMER.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 07/11] ARM:stixxxx: Add STiH416 SOC support
  2013-06-10  9:27   ` [PATCH v2 07/11] ARM:stixxxx: Add STiH416 " Srinivas KANDAGATLA
@ 2013-06-10 13:52     ` Arnd Bergmann
  2013-06-10 16:17       ` Srinivas KANDAGATLA
  2013-06-14  7:12       ` Srinivas KANDAGATLA
  0 siblings, 2 replies; 228+ messages in thread
From: Arnd Bergmann @ 2013-06-10 13:52 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Andrew Morton, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On Monday 10 June 2013 10:27:05 Srinivas KANDAGATLA wrote:

> +	soc {
> +		pin-controller-sbc {
> +			#address-cells	= <1>;
> +			#size-cells	= <1>;
> +			compatible	= "st,stih416-pinctrl", "simple-bus";

Why is this both its own device with a compatible string and a
"simple-bus" at the same time? Wouldn't it be simpler to just
scan the child device nodes from the "st,stih416-pinctrl"
driver instead of having a separate platform_driver for them?

> +			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
> +			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
> +			st,syscfg		= <&syscfg_sbc>;
> +			st,syscfg-offsets	= <0 40 50 60 100>;
> +			ranges;
> +			PIO0: pinctrl@fe610000 {
> +				#gpio-cells = <1>;
> +				compatible = "st,stixxxx-gpio";
> +				gpio-controller;
> +				reg = <0xfe610000 0x100>;
> +				st,bank-name  = "PIO0";
> +				st,retime-pin-mask = <0xff>;
> +			};
> +			PIO1: pinctrl@fe611000 {
> +				#gpio-cells	= <1>;
> +				compatible	= "st,stixxxx-gpio";
> +				gpio-controller;
> +				reg = <0xfe611000 0x100>;
> +				st,bank-name  = "PIO1";
> +				st,retime-pin-mask = <0xff>;
> +			};

What is in the ranges between these registers? It seems you have
256 bytes for each pinctrl node, with 4kb spacing. I wonder if
it would make sense to declare the entire range to belong to a single
pinctrl device. At least since all of the registers are in a single
range, you could add a property like

	ranges = <0 0xfe610000 0x10000>;

and use relative addresses in the sub-nodes.

Please don't use identifiers with 'xxx' in them. Instead use numbers
of actual chips, ideally using the first one that this is compatible
with.

> +		syscfg_sbc:syscfg@fe600000{
> +			compatible	= "st,stih416-syscfg";
> +			reg		= <0xfe600000 0x1000>;
> +			syscfg-range	= <0 999>;
> +			syscfg-name	= "SYSCFG_SBC";
> +		};
> +		syscfg_front:syscfg@fee10000{
> +			compatible	= "st,stih416-syscfg";
> +			reg		= <0xfee10000 0x1000>;
> +			syscfg-range	= <1000 999>;
> +			syscfg-name	= "SYSCFG_FRONT";
> +		};

Did you mean to declare ranges excluding 1000 and 2000 here?
Normally I would expect inclusive ranges like syscfg-range=<0 1000>;

What is the idea of the 'syscfg-name'? If the nodes are all different,
I would expect them to have distinct "compatible" values and not
need them.

	Arnd

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.
       [not found]     ` <CACRpkdaW2ALTWCB7Rd8m=aAGQwh3T_dJVncxJn_eXer4X3J6_g@mail.gmail.com>
@ 2013-06-10 13:52       ` Srinivas KANDAGATLA
  2013-06-10 14:02         ` Arnd Bergmann
  0 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 13:52 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Mauro Carvalho Chehab, linux-doc, Russell King - ARM Linux,
	Samuel Ortiz, Stephen Gallimore, linux-serial, Grant Likely,
	devicetree-discuss, Rob Herring, Stuart Menefy, Mark Brown,
	John Stultz, Thomas Gleixner, linux-arm-kernel,
	Greg Kroah-Hartman, linux-kernel, Andrew Morton, David S. Miller

On 10/06/13 14:16, Linus Walleij wrote:
> On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
> <srinivas.kandagatla@st.com> wrote:
> 
>> This mfd driver provides higher level inialization routines for various
>> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
>> get to syscfg registers via standard regmap api which is usefull for
>> drivers like pinctrl.
>>
>> This patch adds support to ST System Configuration registers, which can
>> be configured by the drivers.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>> CC: Stuart Menefy <stuart.menefy@st.com>
>> CC: Stephen Gallimore <stephen.gallimore@st.com>
>> CC: Linus Walleij <linus.walleij@linaro.org>
>> CC: Mark Brown <broonie@kernel.org>
> 
> What is this driver doing that drivers/mfd/syscon.c is not already
> doing?
As of now, the driver is very much similar to syscon + some additional
functionality, but we are planning to use this file to add higher level
functions to configure different IPs like ethernet, usb, power, reset
and so on which are very much specific to ST System Configuration Registers.

Thanks,
srini
> 
> I just get the feeling that you're reinventing the wheel here.
> 
> Yours,
> Linus Walleij
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.
  2013-06-10 13:52       ` Srinivas KANDAGATLA
@ 2013-06-10 14:02         ` Arnd Bergmann
  2013-06-10 15:51           ` Srinivas KANDAGATLA
  2013-06-11  7:41           ` Srinivas KANDAGATLA
  0 siblings, 2 replies; 228+ messages in thread
From: Arnd Bergmann @ 2013-06-10 14:02 UTC (permalink / raw)
  To: linux-arm-kernel, srinivas.kandagatla
  Cc: Linus Walleij, David S. Miller, Russell King - ARM Linux,
	Samuel Ortiz, linux-doc, Greg Kroah-Hartman, devicetree-discuss,
	Stephen Gallimore, Rob Herring, linux-kernel, Stuart Menefy,
	Mark Brown, John Stultz, linux-serial, Grant Likely,
	Thomas Gleixner, Andrew Morton, Mauro Carvalho Chehab

On Monday 10 June 2013 14:52:38 Srinivas KANDAGATLA wrote:
> On 10/06/13 14:16, Linus Walleij wrote:
> > On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
> > <srinivas.kandagatla@st.com> wrote:
> > 
> >> This mfd driver provides higher level inialization routines for various
> >> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
> >> get to syscfg registers via standard regmap api which is usefull for
> >> drivers like pinctrl.
> >>
> >> This patch adds support to ST System Configuration registers, which can
> >> be configured by the drivers.
> >>
> >> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
> >> CC: Stuart Menefy <stuart.menefy@st.com>
> >> CC: Stephen Gallimore <stephen.gallimore@st.com>
> >> CC: Linus Walleij <linus.walleij@linaro.org>
> >> CC: Mark Brown <broonie@kernel.org>
> > 
> > What is this driver doing that drivers/mfd/syscon.c is not already
> > doing?
>
> As of now, the driver is very much similar to syscon + some additional
> functionality, but we are planning to use this file to add higher level
> functions to configure different IPs like ethernet, usb, power, reset
> and so on which are very much specific to ST System Configuration Registers.

I was expecting that you'd actually interface with the syscon code and
build on top, rather than copy it.

There are multiple ways of doing that, e.g. you could export a function
from syscon.c that you call to register the device node and then import
the regmap from syscon into your high-level driver again.

	Arnd

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.
  2013-06-10 14:02         ` Arnd Bergmann
@ 2013-06-10 15:51           ` Srinivas KANDAGATLA
  2013-06-11  7:41           ` Srinivas KANDAGATLA
  1 sibling, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 15:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Linus Walleij, David S. Miller,
	Russell King - ARM Linux, Samuel Ortiz, linux-doc,
	Greg Kroah-Hartman, devicetree-discuss, Stephen Gallimore,
	Rob Herring, linux-kernel, Stuart Menefy, Mark Brown,
	John Stultz, linux-serial, Grant Likely, Thomas Gleixner,
	Andrew Morton, Mauro Carvalho Chehab

Thanks for the comments.
On 10/06/13 15:02, Arnd Bergmann wrote:
> On Monday 10 June 2013 14:52:38 Srinivas KANDAGATLA wrote:
>> On 10/06/13 14:16, Linus Walleij wrote:
>>> On Mon, Jun 10, 2013 at 11:22 AM, Srinivas KANDAGATLA
>>> <srinivas.kandagatla@st.com> wrote:
>>>
>>>> This mfd driver provides higher level inialization routines for various
>>>> IPs like Ethernet, USB, PCIE, SATA and so on. Also it provides way to
>>>> get to syscfg registers via standard regmap api which is usefull for
>>>> drivers like pinctrl.
>>>>
>>>> This patch adds support to ST System Configuration registers, which can
>>>> be configured by the drivers.
>>>>
>>>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
>>>> CC: Stuart Menefy <stuart.menefy@st.com>
>>>> CC: Stephen Gallimore <stephen.gallimore@st.com>
>>>> CC: Linus Walleij <linus.walleij@linaro.org>
>>>> CC: Mark Brown <broonie@kernel.org>
>>>
>>> What is this driver doing that drivers/mfd/syscon.c is not already
>>> doing?
>>
>> As of now, the driver is very much similar to syscon + some additional
>> functionality, but we are planning to use this file to add higher level
>> functions to configure different IPs like ethernet, usb, power, reset
>> and so on which are very much specific to ST System Configuration Registers.
> 
> I was expecting that you'd actually interface with the syscon code and
> build on top, rather than copy it.
> 
I did not like the copying either, on the other hand I don't want to
pollute the syscon code.

As you said, I will make use of existing syscon and build "System
configuration interface" on top of it and see how it look like. It will
definitely get rid of lot of code duplication.

Thanks,
srini

> There are multiple ways of doing that, e.g. you could export a function
> from syscon.c that you call to register the device node and then import
> the regmap from syscon into your high-level driver again.

> 
> 	Arnd
> 
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 07/11] ARM:stixxxx: Add STiH416 SOC support
  2013-06-10 13:52     ` Arnd Bergmann
@ 2013-06-10 16:17       ` Srinivas KANDAGATLA
  2013-06-14  7:12       ` Srinivas KANDAGATLA
  1 sibling, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-10 16:17 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mauro Carvalho Chehab, linux-doc, linux, Samuel Ortiz,
	Stephen Gallimore, linux-serial, Grant Likely,
	devicetree-discuss, Rob Herring, Stuart Menefy, Mark Brown,
	John Stultz, Thomas Gleixner, linux-arm-kernel,
	Greg Kroah-Hartman, linux-kernel, Andrew Morton, David S. Miller

Thankyou for your comments.
On 10/06/13 14:52, Arnd Bergmann wrote:
> On Monday 10 June 2013 10:27:05 Srinivas KANDAGATLA wrote:
> 
>> +	soc {
>> +		pin-controller-sbc {
>> +			#address-cells	= <1>;
>> +			#size-cells	= <1>;
>> +			compatible	= "st,stih416-pinctrl", "simple-bus";
> 
> Why is this both its own device with a compatible string and a
> "simple-bus" at the same time? Wouldn't it be simpler to just
> scan the child device nodes from the "st,stih416-pinctrl"
> driver instead of having a separate platform_driver for them?
Am happy to get rid of gpio platform_driver, But looking at the existing
pinctrl drivers like at91, they do it exactly like this.

Also having a gpio platform driver ties the resources to driver in a
neat way.

> 
>> +			st,retime-in-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
>> +			st,retime-out-delay	= <0 300 500 750 1000 1250 1500 1750 2000 2250 2500 2750 3000 3250>;
>> +			st,syscfg		= <&syscfg_sbc>;
>> +			st,syscfg-offsets	= <0 40 50 60 100>;
>> +			ranges;
>> +			PIO0: pinctrl@fe610000 {
>> +				#gpio-cells = <1>;
>> +				compatible = "st,stixxxx-gpio";
>> +				gpio-controller;
>> +				reg = <0xfe610000 0x100>;
>> +				st,bank-name  = "PIO0";
>> +				st,retime-pin-mask = <0xff>;
>> +			};
>> +			PIO1: pinctrl@fe611000 {
>> +				#gpio-cells	= <1>;
>> +				compatible	= "st,stixxxx-gpio";
>> +				gpio-controller;
>> +				reg = <0xfe611000 0x100>;
>> +				st,bank-name  = "PIO1";
>> +				st,retime-pin-mask = <0xff>;
>> +			};
> 
> What is in the ranges between these registers? It seems you have
> 256 bytes for each pinctrl node, with 4kb spacing. I wonder if
> it would make sense to declare the entire range to belong to a single
> pinctrl device. At least since all of the registers are in a single
> range, you could add a property like
> 
> 	ranges = <0 0xfe610000 0x10000>;
> 
> and use relative addresses in the sub-nodes.
> 
OK, I will change to use ranges.
> Please don't use identifiers with 'xxx' in them. Instead use numbers
> of actual chips, ideally using the first one that this is compatible
> with.

Ok, I will change st,stixxxx-gpio to st,stih415-gpio.

> 
>> +		syscfg_sbc:syscfg@fe600000{
>> +			compatible	= "st,stih416-syscfg";
>> +			reg		= <0xfe600000 0x1000>;
>> +			syscfg-range	= <0 999>;
>> +			syscfg-name	= "SYSCFG_SBC";
>> +		};
>> +		syscfg_front:syscfg@fee10000{
>> +			compatible	= "st,stih416-syscfg";
>> +			reg		= <0xfee10000 0x1000>;
>> +			syscfg-range	= <1000 999>;
>> +			syscfg-name	= "SYSCFG_FRONT";
>> +		};
> 
> Did you mean to declare ranges excluding 1000 and 2000 here?
> Normally I would expect inclusive ranges like syscfg-range=<0 1000>;
> 
These numbers are from data sheet so I used it as it is.

> What is the idea of the 'syscfg-name'? If the nodes are all different,
The idea of having syscfg-name is to lookup any sysconf bank(regmap)
from code which do not have reference to phandle from device trees.

> I would expect them to have distinct "compatible" values and not
> need them.
Yes, If we have distinct compatible we would not need them, but there
will be 5-10 compatibility list for each SOC.
It looks like its going to be much neater Am going to try this change
and see how it looks like.
> 
> 	Arnd
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-10 11:46       ` Srinivas KANDAGATLA
@ 2013-06-10 23:19         ` Russell King - ARM Linux
  2013-06-11  6:50           ` Srinivas KANDAGATLA
  2013-06-13 12:47           ` Linus Walleij
  0 siblings, 2 replies; 228+ messages in thread
From: Russell King - ARM Linux @ 2013-06-10 23:19 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: Michal Simek, linux-arm, Andrew Morton, Arnd Bergmann,
	David S. Miller, devicetree-discuss, Grant Likely,
	Greg Kroah-Hartman, John Stultz, Linus Walleij, linux-doc, LKML,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On Mon, Jun 10, 2013 at 12:46:59PM +0100, Srinivas KANDAGATLA wrote:
> >     +       aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
> >     +               (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
> >     +               (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
> >     +               (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
> > 
> > 
> > 
> > #include <linux/bitops.h>
> > Linus Walleij would write use  BIT() here
> 
> I will use BIT() macro.

Without checking those fields... BIT() is only appropriate if you're
really talking about single bits.  If you have a field of more than a
single bit which you happen to be setting to '1' then it's not
appropriate to use BIT().

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-10 23:19         ` Russell King - ARM Linux
@ 2013-06-11  6:50           ` Srinivas KANDAGATLA
  2013-06-13 11:56             ` Russell King - ARM Linux
  2013-06-13 12:47           ` Linus Walleij
  1 sibling, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-11  6:50 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Michal Simek, linux-arm, Andrew Morton, Arnd Bergmann,
	David S. Miller, devicetree-discuss, Grant Likely,
	Greg Kroah-Hartman, John Stultz, Linus Walleij, linux-doc, LKML,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On 11/06/13 00:19, Russell King - ARM Linux wrote:
> On Mon, Jun 10, 2013 at 12:46:59PM +0100, Srinivas KANDAGATLA wrote:
>>> > >     +       aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
>>> > >     +               (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
>>> > >     +               (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
>>> > >     +               (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
>>> > > 
>>> > > 
>>> > > 
>>> > > #include <linux/bitops.h>
>>> > > Linus Walleij would write use  BIT() here
>> > 
>> > I will use BIT() macro.
> Without checking those fields... BIT() is only appropriate if you're
> really talking about single bits.  If you have a field of more than a
> single bit which you happen to be setting to '1' then it's not
> appropriate to use BIT().
> 
> 
You are right, It does not make sense to use BIT() macro for field which
has more than 1 bit. I think using mix of both BIT() and the old style
will make code look bit confusing to reader, Also no other mach code in
the kernel use BIT while configuring L2 controller. So am going to drop
the idea of using BIT here and leave the code as it is.

Thanks,
srini

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support.
  2013-06-10 14:02         ` Arnd Bergmann
  2013-06-10 15:51           ` Srinivas KANDAGATLA
@ 2013-06-11  7:41           ` Srinivas KANDAGATLA
  1 sibling, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-11  7:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Linus Walleij, David S. Miller,
	Russell King - ARM Linux, Samuel Ortiz, linux-doc,
	Greg Kroah-Hartman, devicetree-discuss, Stephen Gallimore,
	Rob Herring, linux-kernel, Stuart Menefy, Mark Brown,
	John Stultz, linux-serial, Grant Likely, Thomas Gleixner,
	Andrew Morton, Mauro Carvalho Chehab

On 10/06/13 15:02, Arnd Bergmann wrote:
> There are multiple ways of doing that, e.g. you could export a function
> from syscon.c that you call to register the device node and then import
> the regmap from syscon into your high-level driver again.
> 

Hi Arnd/Linus,

Thankyou for your comments,
I did try using the full sysconf names in compatible and make use of
syscon driver, with this change the nodes look much neater.

The nodes changes to:

syscfg_sbc:syscfg@fe600000{
    compatible      = "st,stih416-sbc-syscfg", "syscon";
    reg             = <0xfe600000 0x1000>;
};

From:
syscfg_sbc:syscfg@fe600000{
         compatible      = "st,stih416-syscfg";
         reg             = <0xfe600000 0x1000>;
         syscfg-range    = <0 999>;
         syscfg-name     = "SYSCFG_SBC";
};


Also I got rid of the drivers/mfd/stixxxx-syscfg.c driver all together
for this basic support patch series, I will add this once there are new
high level functions.
Additional compatible string will allow code to get to regmap via syscon
apis.

I will get rid of this driver in next version for this series.

Thanks,
srini

> 	Arnd
> 
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 03/11] regmap: Add regmap_field APIs
  2013-06-10  9:21   ` [PATCH v2 03/11] regmap: Add regmap_field APIs Srinivas KANDAGATLA
@ 2013-06-11 10:48     ` Mark Brown
  2013-06-11 11:36       ` Srinivas KANDAGATLA
  0 siblings, 1 reply; 228+ messages in thread
From: Mark Brown @ 2013-06-11 10:48 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux-arm-kernel, Andrew Morton, Arnd Bergmann, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mauro Carvalho Chehab, Olof Johansson, Rob Herring,
	Rob Landley, Samuel Ortiz, Stephen Gallimore, Stuart Menefy,
	Thomas Gleixner, Tony Prisk, Alexander Shiyan,
	Lars-Peter Clausen

[-- Attachment #1: Type: text/plain, Size: 1168 bytes --]

On Mon, Jun 10, 2013 at 10:21:58AM +0100, Srinivas KANDAGATLA wrote:
> It is common to access regmap registers at bit level, using
> regmap_update_bits or regmap_read functions, however the end user has to
> take care of a mask or shifting. This becomes overhead when such use
> cases are high. Having a common function to do this is much convenient
> and less error prone.

So this looks basically good.  A couple of smallish nits below, if you
could respin I'll apply this on a branch so it can be pulled in as
dependency for the other things that use it.

> +	regmap_field_init(rm_field, regmap, reg_field);
> +
> +	return rm_field;
> +
> +}
> +EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
> +/**
> + * regmap_field_alloc(): Allocate and initialise a register field

Needs a blank line between the two functions.

> +#include <linux/device.h>
> +#include <linux/slab.h>

> +static inline void regmap_field_free(struct regmap_field *field)
> +{
> +	kfree(field);
> +}

> +static inline void devm_regmap_field_free(struct device *dev,
> +	struct regmap_field *field)
> +{
> +	devm_kfree(dev, field);
> +}

Probably not worth inlining these, just put them in the code.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 03/11] regmap: Add regmap_field APIs
  2013-06-11 10:48     ` Mark Brown
@ 2013-06-11 11:36       ` Srinivas KANDAGATLA
  0 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-11 11:36 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mauro Carvalho Chehab, linux-doc, Lars-Peter Clausen, linux,
	Samuel Ortiz, Alexander Shiyan, Stephen Gallimore, linux-serial,
	Grant Likely, devicetree-discuss, Rob Herring, Stuart Menefy,
	John Stultz, Thomas Gleixner, linux-arm-kernel,
	Greg Kroah-Hartman, linux-kernel, Andrew Morton, David S. Miller

On 11/06/13 11:48, Mark Brown wrote:
> On Mon, Jun 10, 2013 at 10:21:58AM +0100, Srinivas KANDAGATLA wrote:
>> It is common to access regmap registers at bit level, using
>> regmap_update_bits or regmap_read functions, however the end user has to
>> take care of a mask or shifting. This becomes overhead when such use
>> cases are high. Having a common function to do this is much convenient
>> and less error prone.
> 
> So this looks basically good.  A couple of smallish nits below, if you
> could respin I'll apply this on a branch so it can be pulled in as
> dependency for the other things that use it.
> 
Thankyou for the comments,
I will fix it and send a v3 patch.

>> +	regmap_field_init(rm_field, regmap, reg_field);
>> +
>> +	return rm_field;
>> +
>> +}
>> +EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
>> +/**
>> + * regmap_field_alloc(): Allocate and initialise a register field
> 
> Needs a blank line between the two functions.
> 
>> +#include <linux/device.h>
>> +#include <linux/slab.h>
> 
>> +static inline void regmap_field_free(struct regmap_field *field)
>> +{
>> +	kfree(field);
>> +}
> 
>> +static inline void devm_regmap_field_free(struct device *dev,
>> +	struct regmap_field *field)
>> +{
>> +	devm_kfree(dev, field);
>> +}
> 
> Probably not worth inlining these, just put them in the code.
> 
> 
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 02/11] clocksource:global_timer: Add ARM global timer support.
       [not found]           ` <CACRpkdbppRqnMYknbBy8JpAVtujMOEQvyczXTmpvkQuxgikFog@mail.gmail.com>
@ 2013-06-12 10:45             ` Srinivas KANDAGATLA
  0 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-12 10:45 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Mauro Carvalho Chehab, linux-doc, Will Deacon, Mike Turquette,
	Samuel Ortiz, Stephen Gallimore, linux-serial, Grant Likely,
	devicetree-discuss, Rob Herring, Stuart Menefy, Mark Brown,
	John Stultz, Russell King - ARM Linux, Thomas Gleixner,
	linux-arm-kernel, Greg Kroah-Hartman, linux-kernel,
	Andrew Morton, David S. Miller

On 11/06/13 21:13, Linus Walleij wrote:
> On Tue, Jun 11, 2013 at 4:05 PM, Srinivas KANDAGATLA
> <srinivas.kandagatla@st.com> wrote:
> 
>> Doing this is not adding any value to the driver, because
>>  1. Currently the driver only support DT boot paths, in my previous RFC
>> patches, Arnd suggested to get rid of the header as all platforms are DT
>> now.
> 
> In that case why do you have the separate global_timer_init()
> at all? Just move that code into global_timer_of_register() and
> also remove the #ifdef around CONFIG_OF and make the driver
> depend on CONFIG_OF in Kconfig.
> 
> After this you realize that all that business with
> clk_register_clkdev() / clk_get_sys() is just pure surplus
> baggade, you just use of_clk_get() and that's it.

It makes sense to move all the code into global_timer_of_register().
This will also get rid of un-used code. I will do this in the next spin.

Thanks,
srini

> 
> Yours,
> Linus Walleij
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH 05/10] USB: EHCI: make ehci-atmel a separate driver
  2013-02-07 17:34   ` [PATCH 05/10] USB: EHCI: make ehci-atmel " manjunath.goudar
  2013-02-08  2:58     ` Bo Shen
@ 2013-06-12 11:53     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 228+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-06-12 11:53 UTC (permalink / raw)
  To: manjunath.goudar
  Cc: linux-usb, linux-arm-kernel, patches, stern, arnd, gregkh,
	Greg KH, Grant Likely, Rob Herring, Andrew Victor, Nicolas Ferre,
	linux-kernel

On 23:04 Thu 07 Feb     , manjunath.goudar@linaro.org wrote:
> From: Manjunath Goudar <manjunath.goudar@linaro.org>
> 
> Separate the Atmel host controller driver from ehci-hcd host code
> into its own driver module.
> 
> Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Greg KH <greg@kroah.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Andrew Victor <linux@maxim.org.za>
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: linux-usb@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

Best Regards,
J.
> ---
>  drivers/usb/host/Kconfig      |    7 ++++
>  drivers/usb/host/Makefile     |    1 +
>  drivers/usb/host/ehci-atmel.c |   78 ++++++++++++++++++++++-------------------
>  drivers/usb/host/ehci-hcd.c   |    6 +---
>  4 files changed, 51 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 3689b7b..5a13f9d 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -176,6 +176,13 @@ config USB_EHCI_HCD_ORION
>          ---help---
>            Enables support for the on-chip EHCI controller on
>            Morvell Orion chips.
> +config USB_EHCI_HCD_AT91
> +        tristate  "Support for Atmel on-chip EHCI USB controller"
> +        depends on USB_EHCI_HCD && ARCH_AT91
> +        default y
> +        ---help---
> +          Enables support for the on-chip EHCI controller on
> +          Atmel chips.
>  
>  config USB_EHCI_MSM
>  	bool "Support for MSM on-chip EHCI USB controller"
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 23b07dd..96b4839 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -31,6 +31,7 @@ obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o
>  obj-$(CONFIG_USB_EHCI_HCD_SPEAR)+= ehci-spear.o
>  obj-$(CONFIG_USB_EHCI_HCD_ORION)+= ehci-orion.o
>  obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
> +obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
>  obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
>  obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o
>  obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
> diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
> index 27639487..2f06711 100644
> --- a/drivers/usb/host/ehci-atmel.c
> +++ b/drivers/usb/host/ehci-atmel.c
> @@ -15,6 +15,19 @@
>  #include <linux/platform_device.h>
>  #include <linux/of.h>
>  #include <linux/of_platform.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/usb.h>
> +#include <linux/usb/hcd.h>
> +#include <linux/io.h>
> +#include <linux/dma-mapping.h>
> +
> +#include "ehci.h"
> +
> +#define DRIVER_DESC "EHCI atmel driver"
> +
> +static const char hcd_name[] = "ehci-atmel";
> +static struct hc_driver __read_mostly ehci_atmel_hc_driver;
>  
>  /* interface and function clocks */
>  static struct clk *iclk, *fclk;
> @@ -60,41 +73,6 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
>  	return ehci_setup(hcd);
>  }
>  
> -static const struct hc_driver ehci_atmel_hc_driver = {
> -	.description		= hcd_name,
> -	.product_desc		= "Atmel EHCI UHP HS",
> -	.hcd_priv_size		= sizeof(struct ehci_hcd),
> -
> -	/* generic hardware linkage */
> -	.irq			= ehci_irq,
> -	.flags			= HCD_MEMORY | HCD_USB2,
> -
> -	/* basic lifecycle operations */
> -	.reset			= ehci_atmel_setup,
> -	.start			= ehci_run,
> -	.stop			= ehci_stop,
> -	.shutdown		= ehci_shutdown,
> -
> -	/* managing i/o requests and associated device resources */
> -	.urb_enqueue		= ehci_urb_enqueue,
> -	.urb_dequeue		= ehci_urb_dequeue,
> -	.endpoint_disable	= ehci_endpoint_disable,
> -	.endpoint_reset		= ehci_endpoint_reset,
> -
> -	/* scheduling support */
> -	.get_frame_number	= ehci_get_frame,
> -
> -	/* root hub support */
> -	.hub_status_data	= ehci_hub_status_data,
> -	.hub_control		= ehci_hub_control,
> -	.bus_suspend		= ehci_bus_suspend,
> -	.bus_resume		= ehci_bus_resume,
> -	.relinquish_port	= ehci_relinquish_port,
> -	.port_handed_over	= ehci_port_handed_over,
> -
> -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
> -};
> -
>  static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
>  
>  static int ehci_atmel_drv_probe(struct platform_device *pdev)
> @@ -210,7 +188,35 @@ static struct platform_driver ehci_atmel_driver = {
>  	.remove		= ehci_atmel_drv_remove,
>  	.shutdown	= usb_hcd_platform_shutdown,
>  	.driver		= {
> -		.name	= "atmel-ehci",
> +		.name	= hcd_name,
>  		.of_match_table	= of_match_ptr(atmel_ehci_dt_ids),
>  	},
>  };
> +
> +static const struct ehci_driver_overrides atmel_overrides __initdata = {
> +	.reset = ehci_atmel_setup,
> +};
> +
> +static int __init ehci_atmel_init(void)
> +{
> +	if (usb_disabled())
> +		return -ENODEV;
> +
> +	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
> +	ehci_init_driver(&ehci_atmel_hc_driver, &atmel_overrides);
> +	return platform_driver_register(&ehci_atmel_driver);
> +}
> +module_init(ehci_atmel_init);
> +
> +static void __exit ehci_atmel_cleanup(void)
> +{
> +	platform_driver_unregister(&ehci_atmel_driver);
> +}
> +module_exit(ehci_atmel_cleanup);
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +
> +MODULE_ALIAS("platform:ehci-atmel");
> +MODULE_AUTHOR("Nicolas Ferre");
> +MODULE_LICENSE("GPL");
> +
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index 5a19a57..628ed139 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -1272,11 +1272,6 @@ MODULE_LICENSE ("GPL");
>  #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
>  #endif
>  
> -#ifdef CONFIG_ARCH_AT91
> -#include "ehci-atmel.c"
> -#define	PLATFORM_DRIVER		ehci_atmel_driver
> -#endif
> -
>  #ifdef CONFIG_USB_OCTEON_EHCI
>  #include "ehci-octeon.c"
>  #define PLATFORM_DRIVER		ehci_octeon_driver
> @@ -1334,6 +1329,7 @@ MODULE_LICENSE ("GPL");
>  	!defined(PLATFORM_DRIVER) && \
>  	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
>  	!IS_ENABLED(CONFIG_PLAT_SPEAR) && \
> +	!IS_ENABLED(CONFIG_ARCH_AT91) && \
>  	!defined(PS3_SYSTEM_BUS_DRIVER) && \
>  	!defined(OF_PLATFORM_DRIVER) && \
>  	!defined(XILINX_OF_PLATFORM_DRIVER)
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-10 13:15         ` Mark Rutland
@ 2013-06-13  9:24           ` Srinivas KANDAGATLA
  2013-06-17  9:32             ` Mark Rutland
  0 siblings, 1 reply; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-13  9:24 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux, Samuel Ortiz, linux-doc, Greg Kroah-Hartman,
	devicetree-discuss, Stephen Gallimore, rob.herring, linux-kernel,
	Andrew Morton, Stuart Menefy, Mark Brown, John Stultz,
	linux-serial, grant.likely, Thomas Gleixner, David S. Miller,
	linux-arm-kernel, Mauro Carvalho Chehab

On 10/06/13 14:15, Mark Rutland wrote:
> CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
> CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
> CONFIG_MMC_WMT get selected elsewhere, so that's fine.
> 

Am planning to send a patch to clean this up, so that any new platform
addition to the multi_v7_defconfig will not under go this discussion again..

> It looks like the architected timer deselection is fallout of my own making,
> the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
> ARM_ARCH_TIMER.
Why should it even contain HAVE_ARM_ARCH_TIMER/ARM_ARCH_TIMER?
The only reason I see for de-selection is because none of the platforms
in the multi_v7 defconfig selects it.

Looks like there is no platform in mulit_v7 config which requires this
support. If there is one I think it should select it.

Am I correct?

Thanks,
srini


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-11  6:50           ` Srinivas KANDAGATLA
@ 2013-06-13 11:56             ` Russell King - ARM Linux
  2013-06-13 12:41               ` Srinivas KANDAGATLA
  0 siblings, 1 reply; 228+ messages in thread
From: Russell King - ARM Linux @ 2013-06-13 11:56 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: Michal Simek, linux-arm, Andrew Morton, Arnd Bergmann,
	David S. Miller, devicetree-discuss, Grant Likely,
	Greg Kroah-Hartman, John Stultz, Linus Walleij, linux-doc, LKML,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On Tue, Jun 11, 2013 at 07:50:31AM +0100, Srinivas KANDAGATLA wrote:
> You are right, It does not make sense to use BIT() macro for field which
> has more than 1 bit. I think using mix of both BIT() and the old style
> will make code look bit confusing to reader, Also no other mach code in
> the kernel use BIT while configuring L2 controller. So am going to drop
> the idea of using BIT here and leave the code as it is.

I'd suggest putting a comment in the code to that effect.  With the way
"cleanups" get done, I wouldn't be surprised if this attracts a lot of
people wanting to do a trivial "1 << bit" -> "BIT(bit)" conversions.

One of the problems of open source is that you can say "no" to a patch
like that until you're blue in the face, but it will eventually make
its way in via some path.

Just one of the reasons I consider BIT() to be evil and an inappropriate
macro.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-13 11:56             ` Russell King - ARM Linux
@ 2013-06-13 12:41               ` Srinivas KANDAGATLA
  0 siblings, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-13 12:41 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Michal Simek, linux-arm, Andrew Morton, Arnd Bergmann,
	David S. Miller, devicetree-discuss, Grant Likely,
	Greg Kroah-Hartman, John Stultz, Linus Walleij, linux-doc, LKML,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On 13/06/13 12:56, Russell King - ARM Linux wrote:
> On Tue, Jun 11, 2013 at 07:50:31AM +0100, Srinivas KANDAGATLA wrote:
>> You are right, It does not make sense to use BIT() macro for field which
>> has more than 1 bit. I think using mix of both BIT() and the old style
>> will make code look bit confusing to reader, Also no other mach code in
>> the kernel use BIT while configuring L2 controller. So am going to drop
>> the idea of using BIT here and leave the code as it is.
> 
> I'd suggest putting a comment in the code to that effect.  With the way
> "cleanups" get done, I wouldn't be surprised if this attracts a lot of
> people wanting to do a trivial "1 << bit" -> "BIT(bit)" conversions.
Hmm... I can add a comment for them.

> 
> One of the problems of open source is that you can say "no" to a patch
> like that until you're blue in the face, but it will eventually make
> its way in via some path.
> 
> Just one of the reasons I consider BIT() to be evil and an inappropriate
> macro.
> 
> 


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support
  2013-06-10 23:19         ` Russell King - ARM Linux
  2013-06-11  6:50           ` Srinivas KANDAGATLA
@ 2013-06-13 12:47           ` Linus Walleij
  1 sibling, 0 replies; 228+ messages in thread
From: Linus Walleij @ 2013-06-13 12:47 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Srinivas KANDAGATLA, Michal Simek, linux-arm, Andrew Morton,
	Arnd Bergmann, David S. Miller, devicetree-discuss, Grant Likely,
	Greg Kroah-Hartman, John Stultz, linux-doc, LKML, linux-serial,
	Mark Brown, Mauro Carvalho Chehab, Olof Johansson, Rob Herring,
	Rob Landley, Samuel Ortiz, Stephen Gallimore, Stuart Menefy,
	Thomas Gleixner, Tony Prisk

On Tue, Jun 11, 2013 at 1:19 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jun 10, 2013 at 12:46:59PM +0100, Srinivas KANDAGATLA wrote:
>> >     +       aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
>> >     +               (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
>> >     +               (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
>> >     +               (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
>> >
>> >
>> >
>> > #include <linux/bitops.h>
>> > Linus Walleij would write use  BIT() here
>>
>> I will use BIT() macro.
>
> Without checking those fields... BIT() is only appropriate if you're
> really talking about single bits.  If you have a field of more than a
> single bit which you happen to be setting to '1' then it's not
> appropriate to use BIT().

This is true. Luckily I didn't push for it myself this time.

However, on a related key we have this hidden away in MFD
drivers/mfd/dbx500-prcmu-regs.h:

#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))

It's used like so:

#define PRCM_PLL_FREQ_D_MASK    BITS(0, 7)

So you can define an multi-bit mask with a macro like that.

If there is interest in a construct like this I can make a patch to
move this thing to <linux/bitops.h>.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 07/11] ARM:stixxxx: Add STiH416 SOC support
  2013-06-10 13:52     ` Arnd Bergmann
  2013-06-10 16:17       ` Srinivas KANDAGATLA
@ 2013-06-14  7:12       ` Srinivas KANDAGATLA
  1 sibling, 0 replies; 228+ messages in thread
From: Srinivas KANDAGATLA @ 2013-06-14  7:12 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Andrew Morton, David S. Miller,
	devicetree-discuss, Grant Likely, Greg Kroah-Hartman,
	John Stultz, Linus Walleij, linux, linux-doc, linux-kernel,
	linux-serial, Mark Brown, Mauro Carvalho Chehab, Olof Johansson,
	Rob Herring, Rob Landley, Samuel Ortiz, Stephen Gallimore,
	Stuart Menefy, Thomas Gleixner, Tony Prisk

On 10/06/13 14:52, Arnd Bergmann wrote:
> On Monday 10 June 2013 10:27:05 Srinivas KANDAGATLA wrote:
> 
>> > +	soc {
>> > +		pin-controller-sbc {
>> > +			#address-cells	= <1>;
>> > +			#size-cells	= <1>;
>> > +			compatible	= "st,stih416-pinctrl", "simple-bus";
> Why is this both its own device with a compatible string and a
> "simple-bus" at the same time? Wouldn't it be simpler to just
> scan the child device nodes from the "st,stih416-pinctrl"
> driver instead of having a separate platform_driver for them?
> 
I did try this suggestion, and it simplified driver too, I will do this
change in next version.

Thanks,
srini

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig
  2013-06-13  9:24           ` Srinivas KANDAGATLA
@ 2013-06-17  9:32             ` Mark Rutland
  0 siblings, 0 replies; 228+ messages in thread
From: Mark Rutland @ 2013-06-17  9:32 UTC (permalink / raw)
  To: Srinivas KANDAGATLA
  Cc: linux, Samuel Ortiz, linux-doc, Greg Kroah-Hartman,
	devicetree-discuss, Stephen Gallimore, rob.herring, linux-kernel,
	Andrew Morton, Stuart Menefy, Mark Brown, John Stultz,
	linux-serial, grant.likely, Thomas Gleixner, David S. Miller,
	linux-arm-kernel, Mauro Carvalho Chehab

On Thu, Jun 13, 2013 at 10:24:45AM +0100, Srinivas KANDAGATLA wrote:
> On 10/06/13 14:15, Mark Rutland wrote:
> > CONFIG_EXPERIMENTAL's gone as of 3d374d09f1: "final removal of
> > CONFIG_EXPERIMENTAL", so that's fine to go. CONFIG_GPIO_PL061 and
> > CONFIG_MMC_WMT get selected elsewhere, so that's fine.
> > 
> 
> Am planning to send a patch to clean this up, so that any new platform
> addition to the multi_v7_defconfig will not under go this discussion again..
> 
> > It looks like the architected timer deselection is fallout of my own making,
> > the multi_v7_defconfig should now contain HAVE_ARM_ARCH_TIMER rather than
> > ARM_ARCH_TIMER.
> Why should it even contain HAVE_ARM_ARCH_TIMER/ARM_ARCH_TIMER?
> The only reason I see for de-selection is because none of the platforms
> in the multi_v7 defconfig selects it.
> 
> Looks like there is no platform in mulit_v7 config which requires this
> support. If there is one I think it should select it.
> 
> Am I correct?

You're right, I agree that the selection should be moved down into the
platforms requiring it. I'll put together patches to fix up those platforms.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-12  6:40 ` [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held() Sanjeev Sharma
@ 2014-08-12  6:28   ` Hans de Goede
  2014-08-12  6:37     ` Sharma, Sanjeev
  2014-08-19  6:33     ` Sharma, Sanjeev
  0 siblings, 2 replies; 228+ messages in thread
From: Hans de Goede @ 2014-08-12  6:28 UTC (permalink / raw)
  To: Sanjeev Sharma
  Cc: gregkh, kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi

Hi,

On 08/12/2014 08:40 AM, Sanjeev Sharma wrote:
> on some architecture spin_is_locked() always return false in
> uniprocessor configuration and therefore it would be advise
> to replace with lockdep_assert_held().
> 
> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
> ---
> Changes in v3:
>  incorporated review comment suggested by Greg

Thanks, this is still:

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

Regards,

Hans

> 
>  drivers/usb/storage/uas.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
> index 3f42785..05b2d8e 100644
> --- a/drivers/usb/storage/uas.c
> +++ b/drivers/usb/storage/uas.c
> @@ -154,7 +154,7 @@ static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  
>  	uas_log_cmd_state(cmnd, caller);
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
>  	cmdinfo->state |= COMMAND_ABORTED;
>  	cmdinfo->state &= ~IS_IN_WORK_LIST;
> @@ -181,7 +181,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  	struct uas_dev_info *devinfo = cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	cmdinfo->state |= IS_IN_WORK_LIST;
>  	schedule_work(&devinfo->work);
>  }
> @@ -283,7 +283,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
>  	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
>  	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & (COMMAND_INFLIGHT |
>  			      DATA_IN_URB_INFLIGHT |
>  			      DATA_OUT_URB_INFLIGHT |
> @@ -622,7 +622,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
>  	struct urb *urb;
>  	int err;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & SUBMIT_STATUS_URB) {
>  		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
>  		if (!urb)
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* RE: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-12  6:28   ` Hans de Goede
@ 2014-08-12  6:37     ` Sharma, Sanjeev
  2014-08-19  6:33     ` Sharma, Sanjeev
  1 sibling, 0 replies; 228+ messages in thread
From: Sharma, Sanjeev @ 2014-08-12  6:37 UTC (permalink / raw)
  To: Hans de Goede
  Cc: gregkh, kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi

Yes I have incorporated review comment from Greg.

Regards
Sanjeev Sharma

-----Original Message-----
From: Hans de Goede [mailto:hdegoede@redhat.com] 
Sent: Tuesday, August 12, 2014 11:59 AM
To: Sharma, Sanjeev
Cc: gregkh@linuxfoundation.org; kraxel@redhat.com; mdharm-usb@one-eyed-alien.net; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org
Subject: Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()

Hi,

On 08/12/2014 08:40 AM, Sanjeev Sharma wrote:
> on some architecture spin_is_locked() always return false in 
> uniprocessor configuration and therefore it would be advise to replace 
> with lockdep_assert_held().
> 
> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
> ---
> Changes in v3:
>  incorporated review comment suggested by Greg

Thanks, this is still:

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

Regards,

Hans

> 
>  drivers/usb/storage/uas.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c 
> index 3f42785..05b2d8e 100644
> --- a/drivers/usb/storage/uas.c
> +++ b/drivers/usb/storage/uas.c
> @@ -154,7 +154,7 @@ static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  
>  	uas_log_cmd_state(cmnd, caller);
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
>  	cmdinfo->state |= COMMAND_ABORTED;
>  	cmdinfo->state &= ~IS_IN_WORK_LIST;
> @@ -181,7 +181,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  	struct uas_dev_info *devinfo = cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	cmdinfo->state |= IS_IN_WORK_LIST;
>  	schedule_work(&devinfo->work);
>  }
> @@ -283,7 +283,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
>  	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
>  	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & (COMMAND_INFLIGHT |
>  			      DATA_IN_URB_INFLIGHT |
>  			      DATA_OUT_URB_INFLIGHT |
> @@ -622,7 +622,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
>  	struct urb *urb;
>  	int err;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & SUBMIT_STATUS_URB) {
>  		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
>  		if (!urb)
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
       [not found] <yes>
                   ` (28 preceding siblings ...)
  2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
@ 2014-08-12  6:40 ` Sanjeev Sharma
  2014-08-12  6:28   ` Hans de Goede
  2014-09-04 13:50 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c linux.delve
                   ` (4 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: Sanjeev Sharma @ 2014-08-12  6:40 UTC (permalink / raw)
  To: hdegoede
  Cc: gregkh, kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi,
	Sanjeev Sharma, Sanjeev Sharma

on some architecture spin_is_locked() always return false in
uniprocessor configuration and therefore it would be advise
to replace with lockdep_assert_held().

Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
---
Changes in v3:
 incorporated review comment suggested by Greg

 drivers/usb/storage/uas.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 3f42785..05b2d8e 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -154,7 +154,7 @@ static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
 	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
 
 	uas_log_cmd_state(cmnd, caller);
-	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+	lockdep_assert_held(&devinfo->lock);
 	WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
 	cmdinfo->state |= COMMAND_ABORTED;
 	cmdinfo->state &= ~IS_IN_WORK_LIST;
@@ -181,7 +181,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
 	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
 	struct uas_dev_info *devinfo = cmnd->device->hostdata;
 
-	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+	lockdep_assert_held(&devinfo->lock);
 	cmdinfo->state |= IS_IN_WORK_LIST;
 	schedule_work(&devinfo->work);
 }
@@ -283,7 +283,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
 	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
 
-	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+	lockdep_assert_held(&devinfo->lock);
 	if (cmdinfo->state & (COMMAND_INFLIGHT |
 			      DATA_IN_URB_INFLIGHT |
 			      DATA_OUT_URB_INFLIGHT |
@@ -622,7 +622,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 	struct urb *urb;
 	int err;
 
-	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+	lockdep_assert_held(&devinfo->lock);
 	if (cmdinfo->state & SUBMIT_STATUS_URB) {
 		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
 		if (!urb)
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* RE: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-12  6:28   ` Hans de Goede
  2014-08-12  6:37     ` Sharma, Sanjeev
@ 2014-08-19  6:33     ` Sharma, Sanjeev
  2014-08-19  9:30       ` gregkh
  1 sibling, 1 reply; 228+ messages in thread
From: Sharma, Sanjeev @ 2014-08-19  6:33 UTC (permalink / raw)
  To: gregkh
  Cc: gregkh, kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi,
	Hans de Goede

Hi Greg,

Any feedback on this patch ?

Regards
Sanjeev Sharma

-----Original Message-----
From: Sharma, Sanjeev 
Sent: Tuesday, August 12, 2014 12:07 PM
To: 'Hans de Goede'
Cc: gregkh@linuxfoundation.org; kraxel@redhat.com; mdharm-usb@one-eyed-alien.net; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org
Subject: RE: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()

Yes I have incorporated review comment from Greg.

Regards
Sanjeev Sharma

-----Original Message-----
From: Hans de Goede [mailto:hdegoede@redhat.com]
Sent: Tuesday, August 12, 2014 11:59 AM
To: Sharma, Sanjeev
Cc: gregkh@linuxfoundation.org; kraxel@redhat.com; mdharm-usb@one-eyed-alien.net; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org
Subject: Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()

Hi,

On 08/12/2014 08:40 AM, Sanjeev Sharma wrote:
> on some architecture spin_is_locked() always return false in 
> uniprocessor configuration and therefore it would be advise to replace 
> with lockdep_assert_held().
> 
> Signed-off-by: Sanjeev Sharma <Sanjeev_Sharma@mentor.com>
> ---
> Changes in v3:
>  incorporated review comment suggested by Greg

Thanks, this is still:

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

Regards,

Hans

> 
>  drivers/usb/storage/uas.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c 
> index 3f42785..05b2d8e 100644
> --- a/drivers/usb/storage/uas.c
> +++ b/drivers/usb/storage/uas.c
> @@ -154,7 +154,7 @@ static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  
>  	uas_log_cmd_state(cmnd, caller);
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
>  	cmdinfo->state |= COMMAND_ABORTED;
>  	cmdinfo->state &= ~IS_IN_WORK_LIST;
> @@ -181,7 +181,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
>  	struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
>  	struct uas_dev_info *devinfo = cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	cmdinfo->state |= IS_IN_WORK_LIST;
>  	schedule_work(&devinfo->work);
>  }
> @@ -283,7 +283,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
>  	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
>  	struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & (COMMAND_INFLIGHT |
>  			      DATA_IN_URB_INFLIGHT |
>  			      DATA_OUT_URB_INFLIGHT |
> @@ -622,7 +622,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
>  	struct urb *urb;
>  	int err;
>  
> -	WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
> +	lockdep_assert_held(&devinfo->lock);
>  	if (cmdinfo->state & SUBMIT_STATUS_URB) {
>  		urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
>  		if (!urb)
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-19  6:33     ` Sharma, Sanjeev
@ 2014-08-19  9:30       ` gregkh
  2014-08-19  9:38         ` Sharma, Sanjeev
  2014-09-04  7:06         ` Sharma, Sanjeev
  0 siblings, 2 replies; 228+ messages in thread
From: gregkh @ 2014-08-19  9:30 UTC (permalink / raw)
  To: Sharma, Sanjeev
  Cc: kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi, Hans de Goede

On Tue, Aug 19, 2014 at 06:33:04AM +0000, Sharma, Sanjeev wrote:
> Hi Greg,
> 
> Any feedback on this patch ?

The merge window ended 2 days ago, _and_ I'm at the kernel summit this
week, _and_ my queue is currently sitting at:
	$ mdfrm -c ~/mail/todo/
	1317 messages in /home/gregkh/mail/todo/

So please be patient.  I'll get to it in a few weeks.

greg k-h

^ permalink raw reply	[flat|nested] 228+ messages in thread

* RE: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-19  9:30       ` gregkh
@ 2014-08-19  9:38         ` Sharma, Sanjeev
  2014-09-04  7:06         ` Sharma, Sanjeev
  1 sibling, 0 replies; 228+ messages in thread
From: Sharma, Sanjeev @ 2014-08-19  9:38 UTC (permalink / raw)
  To: gregkh
  Cc: kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi, Hans de Goede

Thanks for letting me know.

Sanjeev Sharma

-----Original Message-----
From: gregkh@linuxfoundation.org [mailto:gregkh@linuxfoundation.org] 
Sent: Tuesday, August 19, 2014 3:01 PM
To: Sharma, Sanjeev
Cc: kraxel@redhat.com; mdharm-usb@one-eyed-alien.net; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org; Hans de Goede
Subject: Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()

On Tue, Aug 19, 2014 at 06:33:04AM +0000, Sharma, Sanjeev wrote:
> Hi Greg,
> 
> Any feedback on this patch ?

The merge window ended 2 days ago, _and_ I'm at the kernel summit this week, _and_ my queue is currently sitting at:
	$ mdfrm -c ~/mail/todo/
	1317 messages in /home/gregkh/mail/todo/

So please be patient.  I'll get to it in a few weeks.

greg k-h

^ permalink raw reply	[flat|nested] 228+ messages in thread

* RE: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()
  2014-08-19  9:30       ` gregkh
  2014-08-19  9:38         ` Sharma, Sanjeev
@ 2014-09-04  7:06         ` Sharma, Sanjeev
  1 sibling, 0 replies; 228+ messages in thread
From: Sharma, Sanjeev @ 2014-09-04  7:06 UTC (permalink / raw)
  To: gregkh
  Cc: kraxel, mdharm-usb, linux-usb, linux-kernel, linux-scsi, Hans de Goede

-----Original Message-----
From: gregkh@linuxfoundation.org [mailto:gregkh@linuxfoundation.org] 
Sent: Tuesday, August 19, 2014 3:01 PM
To: Sharma, Sanjeev
Cc: kraxel@redhat.com; mdharm-usb@one-eyed-alien.net; linux-usb@vger.kernel.org; linux-kernel@vger.kernel.org; linux-scsi@vger.kernel.org; Hans de Goede
Subject: Re: [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held()

On Tue, Aug 19, 2014 at 06:33:04AM +0000, Sharma, Sanjeev wrote:
> Hi Greg,
> 
> Any feedback on this patch ?

The merge window ended 2 days ago, _and_ I'm at the kernel summit this week, _and_ my queue is currently sitting at:
	$ mdfrm -c ~/mail/todo/
	1317 messages in /home/gregkh/mail/todo/

So please be patient.  I'll get to it in a few weeks.

Please let me know when this is going to be merged ?

Thanks
Sanjeev

greg k-h

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c
       [not found] <yes>
                   ` (29 preceding siblings ...)
  2014-08-12  6:40 ` [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held() Sanjeev Sharma
@ 2014-09-04 13:50 ` linux.delve
  2014-09-04 13:51   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool linux.delve
  2014-09-04 14:09 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Chaitra Ramaiah
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 228+ messages in thread
From: linux.delve @ 2014-09-04 13:50 UTC (permalink / raw)
  To: gregkh, burzalodowa, anarey, rmfrfs, gdonald, joe
  Cc: devel, linux-kernel, Chaitra Ramaiah

From: Chaitra Ramaiah <linux.delve@gmail.com>

*** BLURB HERE ***

root (1):
  Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c 
       This is a patch to the file r819xU_firmware.c that fixes a brace
    warning found by checkpatch.pl tool

 drivers/staging/rtl8192u/r819xU_firmware.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool
  2014-09-04 13:50 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c linux.delve
@ 2014-09-04 13:51   ` linux.delve
  0 siblings, 0 replies; 228+ messages in thread
From: linux.delve @ 2014-09-04 13:51 UTC (permalink / raw)
  To: gregkh, burzalodowa, anarey, rmfrfs, gdonald, joe
  Cc: devel, linux-kernel, Chaitra Ramaiah

From: root <root@admin1-Lenovo-IdeaPad-Y510P.(none)>

Signed-off-by: Chaitra Ramaiah <linux.delve@gmail.com>
---
 drivers/staging/rtl8192u/r819xU_firmware.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index 671cbe6..40e1ef5 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -153,11 +153,10 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 			break;
 	}while(check_bootOk_time--);
 
-	if (!(CPU_status&CPU_GEN_BOOT_RDY)) {
+	if (!(CPU_status&CPU_GEN_BOOT_RDY))
 		goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
-	} else {
+	else
 		RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
-	}
 
 	return rt_status;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c
       [not found] <yes>
                   ` (30 preceding siblings ...)
  2014-09-04 13:50 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c linux.delve
@ 2014-09-04 14:09 ` Chaitra Ramaiah
  2014-09-04 14:09   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool Chaitra Ramaiah
  2014-09-04 14:27   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Greg KH
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
                   ` (2 subsequent siblings)
  34 siblings, 2 replies; 228+ messages in thread
From: Chaitra Ramaiah @ 2014-09-04 14:09 UTC (permalink / raw)
  To: gregkh, burzalodowa, anarey, rmfrfs, gdonald, joe
  Cc: devel, linux-kernel, Chaitra Ramaiah

*** BLURB HERE ***

root (1):
  Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c 
       This is a patch to the file r819xU_firmware.c that fixes a brace
    warning found by checkpatch.pl tool

 drivers/staging/rtl8192u/r819xU_firmware.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool
  2014-09-04 14:09 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Chaitra Ramaiah
@ 2014-09-04 14:09   ` Chaitra Ramaiah
  2014-09-04 14:28     ` Greg KH
  2014-09-04 14:33     ` Dan Carpenter
  2014-09-04 14:27   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Greg KH
  1 sibling, 2 replies; 228+ messages in thread
From: Chaitra Ramaiah @ 2014-09-04 14:09 UTC (permalink / raw)
  To: gregkh, burzalodowa, anarey, rmfrfs, gdonald, joe
  Cc: devel, linux-kernel, Chaitra Ramaiah

From: root <root@admin1-Lenovo-IdeaPad-Y510P.(none)>

Signed-off-by: Chaitra Ramaiah <linux.delve@gmail.com>
---
 drivers/staging/rtl8192u/r819xU_firmware.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index 671cbe6..40e1ef5 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -153,11 +153,10 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 			break;
 	}while(check_bootOk_time--);
 
-	if (!(CPU_status&CPU_GEN_BOOT_RDY)) {
+	if (!(CPU_status&CPU_GEN_BOOT_RDY))
 		goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
-	} else {
+	else
 		RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
-	}
 
 	return rt_status;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c
  2014-09-04 14:09 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Chaitra Ramaiah
  2014-09-04 14:09   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool Chaitra Ramaiah
@ 2014-09-04 14:27   ` Greg KH
  1 sibling, 0 replies; 228+ messages in thread
From: Greg KH @ 2014-09-04 14:27 UTC (permalink / raw)
  To: Chaitra Ramaiah
  Cc: burzalodowa, anarey, rmfrfs, gdonald, joe, devel, linux-kernel

On Thu, Sep 04, 2014 at 07:39:11PM +0530, Chaitra Ramaiah wrote:
> *** BLURB HERE ***

No blurb???

:)

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool
  2014-09-04 14:09   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool Chaitra Ramaiah
@ 2014-09-04 14:28     ` Greg KH
  2014-09-04 14:33     ` Dan Carpenter
  1 sibling, 0 replies; 228+ messages in thread
From: Greg KH @ 2014-09-04 14:28 UTC (permalink / raw)
  To: Chaitra Ramaiah
  Cc: burzalodowa, anarey, rmfrfs, gdonald, joe, devel, linux-kernel

On Thu, Sep 04, 2014 at 07:39:12PM +0530, Chaitra Ramaiah wrote:
> From: root <root@admin1-Lenovo-IdeaPad-Y510P.(none)>

I don't think that is your email address...

ALso, look at your subject, something went wrong here :(

Care to try again?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool
  2014-09-04 14:09   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool Chaitra Ramaiah
  2014-09-04 14:28     ` Greg KH
@ 2014-09-04 14:33     ` Dan Carpenter
  1 sibling, 0 replies; 228+ messages in thread
From: Dan Carpenter @ 2014-09-04 14:33 UTC (permalink / raw)
  To: Chaitra Ramaiah
  Cc: gregkh, burzalodowa, anarey, rmfrfs, gdonald, joe, devel, linux-kernel

Read the first paragraph of Documentation/email-clients.txt.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH v2 0/4] Enable PCI controller for Keystone SoCs
       [not found] <yes>
                   ` (31 preceding siblings ...)
  2014-09-04 14:09 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Chaitra Ramaiah
@ 2014-10-29 20:28 ` Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 1/4] ARM: keystone: add pcie related options Murali Karicheri
                     ` (4 more replies)
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
  2015-12-31  8:09 ` [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform ling.ma.program
  34 siblings, 5 replies; 228+ messages in thread
From: Murali Karicheri @ 2014-10-29 20:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: Murali Karicheri, Santosh Shilimkar, Greg Kroah-Hartman,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, devicetree

v2: Some more minor edits based on comments
v1: resend with some minor fix up of the commit description and fixing
    the email ID for Santosh.

CC: Santosh Shilimkar <ssantosh@kernel.org>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: devicetree@vger.kernel.org

Murali Karicheri (4):
  ARM: keystone: add pcie related options
  ARM: keystone: defconfig: add options to enable PCI controller
  ARM: dts: keystone: add DT bindings for PCI controller for port 0
  ARM: dts: keystone-k2e: add DT bindings for PCI controller for port 1

 arch/arm/boot/dts/k2e.dtsi          |   45 +++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/keystone.dtsi     |   45 +++++++++++++++++++++++++++++++++++
 arch/arm/configs/keystone_defconfig |    3 +++
 arch/arm/mach-keystone/Kconfig      |    2 ++
 4 files changed, 95 insertions(+)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 228+ messages in thread

* [PATCH v2 1/4] ARM: keystone: add pcie related options
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
@ 2014-10-29 20:28   ` Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 2/4] ARM: keystone: defconfig: add options to enable PCI controller Murali Karicheri
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 228+ messages in thread
From: Murali Karicheri @ 2014-10-29 20:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: Murali Karicheri, Russell King, Santosh Shilimkar

Now that Keystone PCI controller is merged, add pcie related options
by default for keystone architecture so that driver can be enabled in
the build.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
CC: Russell King <linux@arm.linux.org.uk>
CC: Santosh Shilimkar <ssantosh@kernel.org>
---
 - V2 - No change w.r.t v1
 - v1 - No change w.r.t initial version
 arch/arm/mach-keystone/Kconfig |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 98a156a..ea955f6db 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -9,6 +9,8 @@ config ARCH_KEYSTONE
 	select COMMON_CLK_KEYSTONE
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ZONE_DMA if ARM_LPAE
+	select MIGHT_HAVE_PCI
+	select PCI_DOMAINS if PCI
 	help
 	  Support for boards based on the Texas Instruments Keystone family of
 	  SoCs.
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 2/4] ARM: keystone: defconfig: add options to enable PCI controller
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 1/4] ARM: keystone: add pcie related options Murali Karicheri
@ 2014-10-29 20:28   ` Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 3/4] ARM: dts: keystone: add DT bindings for PCI controller for port 0 Murali Karicheri
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 228+ messages in thread
From: Murali Karicheri @ 2014-10-29 20:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: Murali Karicheri, Santosh Shilimkar, Russell King, Greg Kroah-Hartman

This patch enables PCI controller driver for Keystone SoCs by
default.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
CC: Santosh Shilimkar <ssantosh@kernel.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 v2 - Added a description in the commit log per comment
 v1 - fixed email ID for Santosh
 arch/arm/configs/keystone_defconfig |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index 932ae40..40d3e9d 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -20,6 +20,9 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARM_LPAE=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_KEYSTONE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 3/4] ARM: dts: keystone: add DT bindings for PCI controller for port 0
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 1/4] ARM: keystone: add pcie related options Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 2/4] ARM: keystone: defconfig: add options to enable PCI controller Murali Karicheri
@ 2014-10-29 20:28   ` Murali Karicheri
  2014-10-29 20:28   ` [PATCH v2 4/4] ARM: dts: keystone-k2e: add DT bindings for PCI controller for port 1 Murali Karicheri
  2014-10-29 21:10   ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs santosh shilimkar
  4 siblings, 0 replies; 228+ messages in thread
From: Murali Karicheri @ 2014-10-29 20:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: Murali Karicheri, Santosh Shilimkar, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, devicetree

Add common DT bindings to support PCI controller driver for port 0 on all
of the K2 SoCs that has Synopsis Designware based pcie h/w.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
CC: Santosh Shilimkar <ssantosh@kernel.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: devicetree@vger.kernel.org
---
 v2 - Minor editorial update based on comment
 v1 - fixed email ID for Santosh and reworded the commit description a bit to
      be consistent with the subject.
 arch/arm/boot/dts/keystone.dtsi |   45 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index 5d3e83f..c06542b 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -285,5 +285,50 @@
 			#interrupt-cells = <1>;
 			ti,syscon-dev = <&devctrl 0x2a0>;
 		};
+
+		pcie@21800000 {
+			compatible = "ti,keystone-pcie", "snps,dw-pcie";
+			clocks = <&clkpcie>;
+			clock-names = "pcie";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			reg =  <0x21801000 0x2000>, <0x21800000 0x1000>, <0x02620128 4>;
+			ranges = <0x81000000 0 0 0x23250000 0 0x4000
+				0x82000000 0 0x50000000 0x50000000 0 0x10000000>;
+
+			device_type = "pci";
+			num-lanes = <2>;
+
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc0 0>, /* INT A */
+					<0 0 0 2 &pcie_intc0 1>, /* INT B */
+					<0 0 0 3 &pcie_intc0 2>, /* INT C */
+					<0 0 0 4 &pcie_intc0 3>; /* INT D */
+
+			pcie_msi_intc0: msi-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 31 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+			};
+
+			pcie_intc0: legacy-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 27 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 28 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
 	};
 };
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* [PATCH v2 4/4] ARM: dts: keystone-k2e: add DT bindings for PCI controller for port 1
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
                     ` (2 preceding siblings ...)
  2014-10-29 20:28   ` [PATCH v2 3/4] ARM: dts: keystone: add DT bindings for PCI controller for port 0 Murali Karicheri
@ 2014-10-29 20:28   ` Murali Karicheri
  2014-10-29 21:10   ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs santosh shilimkar
  4 siblings, 0 replies; 228+ messages in thread
From: Murali Karicheri @ 2014-10-29 20:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: Murali Karicheri, Santosh Shilimkar, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, devicetree

K2E SoC has a second PCI port based on Synopsis Designware PCIe h/w.
Add DT bindings to support PCI controller for port 1 for this SoC.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
CC: Santosh Shilimkar <ssantosh@kernel.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: Pawel Moll <pawel.moll@arm.com>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Ian Campbell <ijc+devicetree@hellion.org.uk>
CC: Kumar Gala <galak@codeaurora.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: devicetree@vger.kernel.org
---
 v2 - minor ediorial updates based on comments
 v1 - fixed email ID for Santosh and reworded commit description to be
      consistent with the subject.
 arch/arm/boot/dts/k2e.dtsi |   45 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/k2e.dtsi b/arch/arm/boot/dts/k2e.dtsi
index c358b4b..5fc14683 100644
--- a/arch/arm/boot/dts/k2e.dtsi
+++ b/arch/arm/boot/dts/k2e.dtsi
@@ -85,6 +85,51 @@
 			#gpio-cells = <2>;
 			gpio,syscon-dev = <&devctrl 0x240>;
 		};
+
+		pcie@21020000 {
+			compatible = "ti,keystone-pcie","snps,dw-pcie";
+			clocks = <&clkpcie1>;
+			clock-names = "pcie";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			reg =  <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
+			ranges = <0x81000000 0 0 0x23260000 0x4000 0x4000
+				0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
+
+			device_type = "pci";
+			num-lanes = <2>;
+
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>, /* INT A */
+					<0 0 0 2 &pcie_intc1 1>, /* INT B */
+					<0 0 0 3 &pcie_intc1 2>, /* INT C */
+					<0 0 0 4 &pcie_intc1 3>; /* INT D */
+
+			pcie_msi_intc1: msi-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 378 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 379 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 380 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 381 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 382 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 383 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 384 IRQ_TYPE_EDGE_RISING>;
+			};
+
+			pcie_intc1: legacy-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
 	};
 };
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [PATCH v2 0/4] Enable PCI controller for Keystone SoCs
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
                     ` (3 preceding siblings ...)
  2014-10-29 20:28   ` [PATCH v2 4/4] ARM: dts: keystone-k2e: add DT bindings for PCI controller for port 1 Murali Karicheri
@ 2014-10-29 21:10   ` santosh shilimkar
  4 siblings, 0 replies; 228+ messages in thread
From: santosh shilimkar @ 2014-10-29 21:10 UTC (permalink / raw)
  To: Murali Karicheri, linux-arm-kernel, linux-kernel
  Cc: Mark Rutland, devicetree, Russell King, Pawel Moll, Ian Campbell,
	Greg Kroah-Hartman, Kumar Gala, Rob Herring, Santosh Shilimkar

On 10/29/2014 1:28 PM, Murali Karicheri wrote:
> v2: Some more minor edits based on comments

Thanks for quick update. I will queue these up as
mentioned.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
       [not found] <yes>
                   ` (32 preceding siblings ...)
  2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
@ 2015-10-19  2:27 ` ling.ma.program
  2015-10-19  7:58   ` Ingo Molnar
                     ` (3 more replies)
  2015-12-31  8:09 ` [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform ling.ma.program
  34 siblings, 4 replies; 228+ messages in thread
From: ling.ma.program @ 2015-10-19  2:27 UTC (permalink / raw)
  To: peterz; +Cc: mingo, linux-kernel, Ma Ling

From: Ma Ling <ling.ml@alibaba-inc.com>

All load instructions can run speculatively but they have to follow
memory order rule in multiple cores as below:
_x = _y = 0

Processor 0				Processor 1

mov r1, [ _y]  //M1			mov [ _x], 1  //M3
mov r2, [ _x]  //M2			mov [ _y], 1  //M4

If r1 = 1, r2 must be 1

In order to guarantee above rule, although Processor 0 execute
M1 and M2 instruction out of order, they are kept in ROB,
when load buffer for _x in Processor 0 received the update 
message from Processor 1, Processor 0 need to roll back
from M2 instruction, which will flush the whole pipeline,
the latency is over the penalty from branch prediction miss.

In this patch we use lock cmpxchg instruction to force load
instructions to be serialization, the destination operand
receives a write cycle without regard to the result of
the comparison, which can help us to reduce the penalty
from load instruction roll back.

Our experiment indicates the performance can be improved by 10%~15%
for 2 and 3 threads cases, the conflicts from lock cache line
spend them most of the time.

Thanks
Ling

Signed-off-by: Ma Ling <ling.ml@alibaba-inc.com>
---
 kernel/locking/qspinlock.c |   43 ++++++++++++++++++-------------------------
 1 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 87e9ce6..16421f2 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -332,25 +332,14 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
 	if (new == _Q_LOCKED_VAL)
 		return;
 
-	/*
-	 * we're pending, wait for the owner to go away.
-	 *
-	 * *,1,1 -> *,1,0
+	/* we're waiting, and get lock owner
 	 *
-	 * this wait loop must be a load-acquire such that we match the
-	 * store-release that clears the locked bit and create lock
-	 * sequentiality; this is because not all clear_pending_set_locked()
-	 * implementations imply full barriers.
+	 * *,1,* -> *,0,1
 	 */
-	while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_MASK)
+	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending,
+		_Q_PENDING_VAL, _Q_LOCKED_VAL) != _Q_PENDING_VAL)
 		cpu_relax();
-
-	/*
-	 * take ownership and clear the pending bit.
-	 *
-	 * *,1,0 -> *,0,1
-	 */
-	clear_pending_set_locked(lock);
+
 	return;
 
 	/*
@@ -399,17 +388,21 @@ queue:
 	 * we're at the head of the waitqueue, wait for the owner & pending to
 	 * go away.
 	 *
-	 * *,x,y -> *,0,0
-	 *
-	 * this wait loop must use a load-acquire such that we match the
-	 * store-release that clears the locked bit and create lock
-	 * sequentiality; this is because the set_locked() function below
-	 * does not imply a full barrier.
-	 *
+	 * *,x,y -> *,0,1
 	 */
 	pv_wait_head(lock, node);
-	while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_PENDING_MASK)
+	next = READ_ONCE(node->next);
+	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending, 0,
+		_Q_LOCKED_VAL) != 0) {
+		next = READ_ONCE(node->next);
 		cpu_relax();
+	}
+
+	if (next)
+		goto next_node;
+
+	val = smp_load_acquire(&lock->val.counter);
+	tail = tail | _Q_LOCKED_VAL;
 
 	/*
 	 * claim the lock:
@@ -423,7 +416,6 @@ queue:
 	 */
 	for (;;) {
 		if (val != tail) {
-			set_locked(lock);
 			break;
 		}
 		old = atomic_cmpxchg(&lock->val, val, _Q_LOCKED_VAL);
@@ -439,6 +431,7 @@ queue:
 	while (!(next = READ_ONCE(node->next)))
 		cpu_relax();
 
+next_node:
 	arch_mcs_spin_unlock_contended(&next->locked);
 	pv_kick_node(lock, next);
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
@ 2015-10-19  7:58   ` Ingo Molnar
  2015-10-19  9:34     ` Peter Zijlstra
  2015-10-20  2:57     ` Ling Ma
  2015-10-19  9:33   ` Peter Zijlstra
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 228+ messages in thread
From: Ingo Molnar @ 2015-10-19  7:58 UTC (permalink / raw)
  To: ling.ma.program; +Cc: peterz, mingo, linux-kernel, Ma Ling


* ling.ma.program@gmail.com <ling.ma.program@gmail.com> wrote:

> From: Ma Ling <ling.ml@alibaba-inc.com>
> 
> All load instructions can run speculatively but they have to follow
> memory order rule in multiple cores as below:
> _x = _y = 0
> 
> Processor 0				Processor 1
> 
> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
> 
> If r1 = 1, r2 must be 1
> 
> In order to guarantee above rule, although Processor 0 execute
> M1 and M2 instruction out of order, they are kept in ROB,
> when load buffer for _x in Processor 0 received the update 
> message from Processor 1, Processor 0 need to roll back
> from M2 instruction, which will flush the whole pipeline,
> the latency is over the penalty from branch prediction miss.
> 
> In this patch we use lock cmpxchg instruction to force load
> instructions to be serialization, the destination operand
> receives a write cycle without regard to the result of
> the comparison, which can help us to reduce the penalty
> from load instruction roll back.
> 
> Our experiment indicates the performance can be improved by 10%~15%
> for 2 and 3 threads cases, the conflicts from lock cache line
> spend them most of the time.

So it would be nice to create a new user-space spinlock testing facility, via a 
new 'perf bench spinlock' feature or so. That way others can test and validate 
your results on different hardware as well.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
  2015-10-19  7:58   ` Ingo Molnar
@ 2015-10-19  9:33   ` Peter Zijlstra
  2015-10-19 17:20     ` Waiman Long
  2015-10-20  3:00     ` Ling Ma
  2015-10-19  9:46   ` Peter Zijlstra
  2015-10-19 17:18   ` Waiman Long
  3 siblings, 2 replies; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-19  9:33 UTC (permalink / raw)
  To: ling.ma.program; +Cc: mingo, linux-kernel, Ma Ling, waiman.long

On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
> From: Ma Ling <ling.ml@alibaba-inc.com>
> 
> All load instructions can run speculatively but they have to follow
> memory order rule in multiple cores as below:
> _x = _y = 0
> 
> Processor 0				Processor 1
> 
> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
> 
> If r1 = 1, r2 must be 1
> 
> In order to guarantee above rule, although Processor 0 execute
> M1 and M2 instruction out of order, they are kept in ROB,
> when load buffer for _x in Processor 0 received the update 
> message from Processor 1, Processor 0 need to roll back
> from M2 instruction, which will flush the whole pipeline,
> the latency is over the penalty from branch prediction miss.
> 
> In this patch we use lock cmpxchg instruction to force load
> instructions to be serialization, the destination operand
> receives a write cycle without regard to the result of
> the comparison, which can help us to reduce the penalty
> from load instruction roll back.
> 
> Our experiment indicates the performance can be improved by 10%~15%
> for 2 and 3 threads cases, the conflicts from lock cache line
> spend them most of the time.

On what hardware? Also, you forgot to Cc Waiman, who is a prime author
of this code. Excessive quoting for his benefit.

> Signed-off-by: Ma Ling <ling.ml@alibaba-inc.com>
> ---
>  kernel/locking/qspinlock.c |   43 ++++++++++++++++++-------------------------
>  1 files changed, 18 insertions(+), 25 deletions(-)
> 
> diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
> index 87e9ce6..16421f2 100644
> --- a/kernel/locking/qspinlock.c
> +++ b/kernel/locking/qspinlock.c
> @@ -332,25 +332,14 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
>  	if (new == _Q_LOCKED_VAL)
>  		return;
>  
> -	/*
> -	 * we're pending, wait for the owner to go away.
> -	 *
> -	 * *,1,1 -> *,1,0
> +	/* we're waiting, and get lock owner

That's incorrect coding style

>  	 *
> -	 * this wait loop must be a load-acquire such that we match the
> -	 * store-release that clears the locked bit and create lock
> -	 * sequentiality; this is because not all clear_pending_set_locked()
> -	 * implementations imply full barriers.
> +	 * *,1,* -> *,0,1
>  	 */
> -	while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_MASK)
> +	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending,
> +		_Q_PENDING_VAL, _Q_LOCKED_VAL) != _Q_PENDING_VAL)

That's both horrible coding style and painful, we should not spin-wait
with a cmpxchg instruction like that.

>  		cpu_relax();
> -
> -	/*
> -	 * take ownership and clear the pending bit.
> -	 *
> -	 * *,1,0 -> *,0,1
> -	 */
> -	clear_pending_set_locked(lock);
> +
>  	return;
>  
>  	/*
> @@ -399,17 +388,21 @@ queue:
>  	 * we're at the head of the waitqueue, wait for the owner & pending to
>  	 * go away.
>  	 *
> -	 * *,x,y -> *,0,0
> -	 *
> -	 * this wait loop must use a load-acquire such that we match the
> -	 * store-release that clears the locked bit and create lock
> -	 * sequentiality; this is because the set_locked() function below
> -	 * does not imply a full barrier.
> -	 *
> +	 * *,x,y -> *,0,1
>  	 */
>  	pv_wait_head(lock, node);
> -	while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_PENDING_MASK)
> +	next = READ_ONCE(node->next);
> +	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending, 0,
> +		_Q_LOCKED_VAL) != 0) {

idem

> +		next = READ_ONCE(node->next);
>  		cpu_relax();
> +	}
> +
> +	if (next)
> +		goto next_node;
> +
> +	val = smp_load_acquire(&lock->val.counter);
> +	tail = tail | _Q_LOCKED_VAL;
>  
>  	/*
>  	 * claim the lock:
> @@ -423,7 +416,6 @@ queue:
>  	 */
>  	for (;;) {
>  		if (val != tail) {
> -			set_locked(lock);
>  			break;
>  		}
>  		old = atomic_cmpxchg(&lock->val, val, _Q_LOCKED_VAL);
> @@ -439,6 +431,7 @@ queue:
>  	while (!(next = READ_ONCE(node->next)))
>  		cpu_relax();
>  
> +next_node:
>  	arch_mcs_spin_unlock_contended(&next->locked);
>  	pv_kick_node(lock, next);
>  
> -- 
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  7:58   ` Ingo Molnar
@ 2015-10-19  9:34     ` Peter Zijlstra
  2015-10-19 11:24       ` Ingo Molnar
  2015-10-20  2:57     ` Ling Ma
  1 sibling, 1 reply; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-19  9:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: ling.ma.program, mingo, linux-kernel, Ma Ling

On Mon, Oct 19, 2015 at 09:58:23AM +0200, Ingo Molnar wrote:
> 
> * ling.ma.program@gmail.com <ling.ma.program@gmail.com> wrote:
> 
> > From: Ma Ling <ling.ml@alibaba-inc.com>
> > 
> > All load instructions can run speculatively but they have to follow
> > memory order rule in multiple cores as below:
> > _x = _y = 0
> > 
> > Processor 0				Processor 1
> > 
> > mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> > mov r2, [ _x]  //M2			mov [ _y], 1  //M4
> > 
> > If r1 = 1, r2 must be 1
> > 
> > In order to guarantee above rule, although Processor 0 execute
> > M1 and M2 instruction out of order, they are kept in ROB,
> > when load buffer for _x in Processor 0 received the update 
> > message from Processor 1, Processor 0 need to roll back
> > from M2 instruction, which will flush the whole pipeline,
> > the latency is over the penalty from branch prediction miss.
> > 
> > In this patch we use lock cmpxchg instruction to force load
> > instructions to be serialization, the destination operand
> > receives a write cycle without regard to the result of
> > the comparison, which can help us to reduce the penalty
> > from load instruction roll back.
> > 
> > Our experiment indicates the performance can be improved by 10%~15%
> > for 2 and 3 threads cases, the conflicts from lock cache line
> > spend them most of the time.
> 
> So it would be nice to create a new user-space spinlock testing facility, via a 
> new 'perf bench spinlock' feature or so. That way others can test and validate 
> your results on different hardware as well.

So its trivial to lift this code into userspace -- in fact, I have that
somewhere.

The trouble is going to keep them in sync.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
  2015-10-19  7:58   ` Ingo Molnar
  2015-10-19  9:33   ` Peter Zijlstra
@ 2015-10-19  9:46   ` Peter Zijlstra
  2015-10-20  3:03     ` Ling Ma
  2015-10-20  3:24     ` Ling Ma
  2015-10-19 17:18   ` Waiman Long
  3 siblings, 2 replies; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-19  9:46 UTC (permalink / raw)
  To: ling.ma.program; +Cc: mingo, linux-kernel, Ma Ling, Waiman Long

On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
> From: Ma Ling <ling.ml@alibaba-inc.com>
> 
> All load instructions can run speculatively but they have to follow
> memory order rule in multiple cores as below:
> _x = _y = 0
> 
> Processor 0				Processor 1
> 
> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
> 
> If r1 = 1, r2 must be 1
> 
> In order to guarantee above rule, although Processor 0 execute
> M1 and M2 instruction out of order, they are kept in ROB,
> when load buffer for _x in Processor 0 received the update
> message from Processor 1, Processor 0 need to roll back
> from M2 instruction, which will flush the whole pipeline,
> the latency is over the penalty from branch prediction miss.
> 
> In this patch we use lock cmpxchg instruction to force load

"lock cmpxchg" makes me think you're working on x86.

> instructions to be serialization,

smp_rmb() does that, and that's 'free' on x86. Because x86 doesn't do
read reordering.

> the destination operand
> receives a write cycle without regard to the result of
> the comparison, which can help us to reduce the penalty
> from load instruction roll back.

And that makes me think I'm not understanding what you're getting at. If
you need to force memory order, a "fence" (or smp_mb()) would still be
cheaper than endlessly pulling the line into exclusive state for no
reason, right?

> Our experiment indicates the performance can be improved by 10%~15%
> for 2 and 3 threads cases, the conflicts from lock cache line
> spend them most of the time.

That just doesn't parse, what?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  9:34     ` Peter Zijlstra
@ 2015-10-19 11:24       ` Ingo Molnar
  2015-10-19 17:24         ` Waiman Long
  0 siblings, 1 reply; 228+ messages in thread
From: Ingo Molnar @ 2015-10-19 11:24 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: ling.ma.program, mingo, linux-kernel, Ma Ling,
	Arnaldo Carvalho de Melo, Jiri Olsa


* Peter Zijlstra <peterz@infradead.org> wrote:

> On Mon, Oct 19, 2015 at 09:58:23AM +0200, Ingo Molnar wrote:
> > 
> > * ling.ma.program@gmail.com <ling.ma.program@gmail.com> wrote:
> > 
> > > From: Ma Ling <ling.ml@alibaba-inc.com>
> > > 
> > > All load instructions can run speculatively but they have to follow
> > > memory order rule in multiple cores as below:
> > > _x = _y = 0
> > > 
> > > Processor 0				Processor 1
> > > 
> > > mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> > > mov r2, [ _x]  //M2			mov [ _y], 1  //M4
> > > 
> > > If r1 = 1, r2 must be 1
> > > 
> > > In order to guarantee above rule, although Processor 0 execute
> > > M1 and M2 instruction out of order, they are kept in ROB,
> > > when load buffer for _x in Processor 0 received the update 
> > > message from Processor 1, Processor 0 need to roll back
> > > from M2 instruction, which will flush the whole pipeline,
> > > the latency is over the penalty from branch prediction miss.
> > > 
> > > In this patch we use lock cmpxchg instruction to force load
> > > instructions to be serialization, the destination operand
> > > receives a write cycle without regard to the result of
> > > the comparison, which can help us to reduce the penalty
> > > from load instruction roll back.
> > > 
> > > Our experiment indicates the performance can be improved by 10%~15%
> > > for 2 and 3 threads cases, the conflicts from lock cache line
> > > spend them most of the time.
> > 
> > So it would be nice to create a new user-space spinlock testing facility, via a 
> > new 'perf bench spinlock' feature or so. That way others can test and validate 
> > your results on different hardware as well.
> 
> So its trivial to lift this code into userspace -- in fact, I have that
> somewhere.
> 
> The trouble is going to keep them in sync.

So we can just try this optimistically, and if it keeps breaking, we can use the 
technique perf uses to sync up the rbtree implementation: we copy the kernel 
version into tooling, but run diff against the kernel version and warn at tool 
build time that there's divergence.

I.e. a non-build-fatal force that keeps things in sync.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
                     ` (2 preceding siblings ...)
  2015-10-19  9:46   ` Peter Zijlstra
@ 2015-10-19 17:18   ` Waiman Long
  2015-10-20  3:12     ` Ling Ma
  3 siblings, 1 reply; 228+ messages in thread
From: Waiman Long @ 2015-10-19 17:18 UTC (permalink / raw)
  To: ling.ma.program; +Cc: peterz, mingo, linux-kernel, Ma Ling

On 10/18/2015 10:27 PM, ling.ma.program@gmail.com wrote:
> From: Ma Ling<ling.ml@alibaba-inc.com>
>
> All load instructions can run speculatively but they have to follow
> memory order rule in multiple cores as below:
> _x = _y = 0
>
> Processor 0				Processor 1
>
> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
>
> If r1 = 1, r2 must be 1
>
> In order to guarantee above rule, although Processor 0 execute
> M1 and M2 instruction out of order, they are kept in ROB,
> when load buffer for _x in Processor 0 received the update
> message from Processor 1, Processor 0 need to roll back
> from M2 instruction, which will flush the whole pipeline,
> the latency is over the penalty from branch prediction miss.
>
> In this patch we use lock cmpxchg instruction to force load
> instructions to be serialization, the destination operand
> receives a write cycle without regard to the result of
> the comparison, which can help us to reduce the penalty
> from load instruction roll back.
>
> Our experiment indicates the performance can be improved by 10%~15%
> for 2 and 3 threads cases, the conflicts from lock cache line
> spend them most of the time.

What kind of performance test were you running? With the right timing, 
it is possible that you see some performance gain. However, if the lock 
hold time is longer so that a fair number of cmpxchg instructions have 
to be executed before it can get the lock, you may see a performance 
degradation especially if the lock holder needs to access the lock 
cacheline.

In general, we try to avoid this kind of cmpxchg loop unless we are sure 
that at most a few iterations of the loop may happen.

>
> Thanks
> Ling
>
> Signed-off-by: Ma Ling<ling.ml@alibaba-inc.com>
> ---
>   kernel/locking/qspinlock.c |   43 ++++++++++++++++++-------------------------
>   1 files changed, 18 insertions(+), 25 deletions(-)
>
> diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
> index 87e9ce6..16421f2 100644
> --- a/kernel/locking/qspinlock.c
> +++ b/kernel/locking/qspinlock.c
> @@ -332,25 +332,14 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
>   	if (new == _Q_LOCKED_VAL)
>   		return;
>
> -	/*
> -	 * we're pending, wait for the owner to go away.
> -	 *
> -	 * *,1,1 ->  *,1,0
> +	/* we're waiting, and get lock owner
>   	 *
> -	 * this wait loop must be a load-acquire such that we match the
> -	 * store-release that clears the locked bit and create lock
> -	 * sequentiality; this is because not all clear_pending_set_locked()
> -	 * implementations imply full barriers.
> +	 * *,1,* ->  *,0,1
>   	 */
> -	while ((val = smp_load_acquire(&lock->val.counter))&  _Q_LOCKED_MASK)
> +	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending,
> +		_Q_PENDING_VAL, _Q_LOCKED_VAL) != _Q_PENDING_VAL)
>   		cpu_relax();
> -
> -	/*
> -	 * take ownership and clear the pending bit.
> -	 *
> -	 * *,1,0 ->  *,0,1
> -	 */
> -	clear_pending_set_locked(lock);
> +
>   	return;
>
>   	/*
> @@ -399,17 +388,21 @@ queue:
>   	 * we're at the head of the waitqueue, wait for the owner&  pending to
>   	 * go away.
>   	 *
> -	 * *,x,y ->  *,0,0
> -	 *
> -	 * this wait loop must use a load-acquire such that we match the
> -	 * store-release that clears the locked bit and create lock
> -	 * sequentiality; this is because the set_locked() function below
> -	 * does not imply a full barrier.
> -	 *
> +	 * *,x,y ->  *,0,1
>   	 */
>   	pv_wait_head(lock, node);
> -	while ((val = smp_load_acquire(&lock->val.counter))&  _Q_LOCKED_PENDING_MASK)
> +	next = READ_ONCE(node->next);
> +	while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending, 0,

The locked_pending field isn't valid if _Q_PENDING_BITS != 8. So it 
won't work if NR_CPUS is 16k or more.

> +		_Q_LOCKED_VAL) != 0) {
> +		next = READ_ONCE(node->next);
>   		cpu_relax();
> +	}
> +
> +	if (next)
> +		goto next_node;

I did notice a slight performance benefit by reading the next pointer 
early in light load cases myself. However, it is a very minor 
improvement that I haven't actively pursued it.

> +
> +	val = smp_load_acquire(&lock->val.counter);
> +	tail = tail | _Q_LOCKED_VAL;
>
>   	/*
>   	 * claim the lock:
> @@ -423,7 +416,6 @@ queue:
>   	 */
>   	for (;;) {
>   		if (val != tail) {
> -			set_locked(lock);
>   			break;
>   		}
>   		old = atomic_cmpxchg(&lock->val, val, _Q_LOCKED_VAL);
> @@ -439,6 +431,7 @@ queue:
>   	while (!(next = READ_ONCE(node->next)))
>   		cpu_relax();
>
> +next_node:
>   	arch_mcs_spin_unlock_contended(&next->locked);
>   	pv_kick_node(lock, next);
>


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  9:33   ` Peter Zijlstra
@ 2015-10-19 17:20     ` Waiman Long
  2015-10-20  3:00     ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Waiman Long @ 2015-10-19 17:20 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: ling.ma.program, mingo, linux-kernel, Ma Ling

On 10/19/2015 05:33 AM, Peter Zijlstra wrote:
> On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
>> From: Ma Ling<ling.ml@alibaba-inc.com>
>>
>> All load instructions can run speculatively but they have to follow
>> memory order rule in multiple cores as below:
>> _x = _y = 0
>>
>> Processor 0				Processor 1
>>
>> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
>> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
>>
>> If r1 = 1, r2 must be 1
>>
>> In order to guarantee above rule, although Processor 0 execute
>> M1 and M2 instruction out of order, they are kept in ROB,
>> when load buffer for _x in Processor 0 received the update
>> message from Processor 1, Processor 0 need to roll back
>> from M2 instruction, which will flush the whole pipeline,
>> the latency is over the penalty from branch prediction miss.
>>
>> In this patch we use lock cmpxchg instruction to force load
>> instructions to be serialization, the destination operand
>> receives a write cycle without regard to the result of
>> the comparison, which can help us to reduce the penalty
>> from load instruction roll back.
>>
>> Our experiment indicates the performance can be improved by 10%~15%
>> for 2 and 3 threads cases, the conflicts from lock cache line
>> spend them most of the time.
> On what hardware? Also, you forgot to Cc Waiman, who is a prime author
> of this code. Excessive quoting for his benefit.

Thanks for letting me aware of this patch. I had commented on the patch 
in a separate mail.

Cheers,
Longman


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19 11:24       ` Ingo Molnar
@ 2015-10-19 17:24         ` Waiman Long
  0 siblings, 0 replies; 228+ messages in thread
From: Waiman Long @ 2015-10-19 17:24 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, ling.ma.program, mingo, linux-kernel, Ma Ling,
	Arnaldo Carvalho de Melo, Jiri Olsa

On 10/19/2015 07:24 AM, Ingo Molnar wrote:
> * Peter Zijlstra<peterz@infradead.org>  wrote:
>
>> On Mon, Oct 19, 2015 at 09:58:23AM +0200, Ingo Molnar wrote:
>>> * ling.ma.program@gmail.com<ling.ma.program@gmail.com>  wrote:
>>>
>>>> From: Ma Ling<ling.ml@alibaba-inc.com>
>>>>
>>>> All load instructions can run speculatively but they have to follow
>>>> memory order rule in multiple cores as below:
>>>> _x = _y = 0
>>>>
>>>> Processor 0				Processor 1
>>>>
>>>> mov r1, [ _y]  //M1			mov [ _x], 1  //M3
>>>> mov r2, [ _x]  //M2			mov [ _y], 1  //M4
>>>>
>>>> If r1 = 1, r2 must be 1
>>>>
>>>> In order to guarantee above rule, although Processor 0 execute
>>>> M1 and M2 instruction out of order, they are kept in ROB,
>>>> when load buffer for _x in Processor 0 received the update
>>>> message from Processor 1, Processor 0 need to roll back
>>>> from M2 instruction, which will flush the whole pipeline,
>>>> the latency is over the penalty from branch prediction miss.
>>>>
>>>> In this patch we use lock cmpxchg instruction to force load
>>>> instructions to be serialization, the destination operand
>>>> receives a write cycle without regard to the result of
>>>> the comparison, which can help us to reduce the penalty
>>>> from load instruction roll back.
>>>>
>>>> Our experiment indicates the performance can be improved by 10%~15%
>>>> for 2 and 3 threads cases, the conflicts from lock cache line
>>>> spend them most of the time.
>>> So it would be nice to create a new user-space spinlock testing facility, via a
>>> new 'perf bench spinlock' feature or so. That way others can test and validate
>>> your results on different hardware as well.
>> So its trivial to lift this code into userspace -- in fact, I have that
>> somewhere.
>>
>> The trouble is going to keep them in sync.
> So we can just try this optimistically, and if it keeps breaking, we can use the
> technique perf uses to sync up the rbtree implementation: we copy the kernel
> version into tooling, but run diff against the kernel version and warn at tool
> build time that there's divergence.
>
> I.e. a non-build-fatal force that keeps things in sync.
>
> Thanks,
>
> 	Ingo
>

It is on my to-do list. I just want to wrap up my latest PV qspinlock 
patch before embarking on this adventure.

Cheers,
Longman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  7:58   ` Ingo Molnar
  2015-10-19  9:34     ` Peter Zijlstra
@ 2015-10-20  2:57     ` Ling Ma
  2015-10-20  8:48       ` Ingo Molnar
  2015-10-20  9:15       ` Peter Zijlstra
  1 sibling, 2 replies; 228+ messages in thread
From: Ling Ma @ 2015-10-20  2:57 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: peterz, mingo, linux-kernel, Ma Ling, Waiman.Long

[-- Attachment #1: Type: text/plain, Size: 409 bytes --]

>
> So it would be nice to create a new user-space spinlock testing facility, via a
> new 'perf bench spinlock' feature or so. That way others can test and validate
> your results on different hardware as well.
>
Attached the spinlock test module . Queued spinlock will run very
slowly in user space
because process switch context, it is OK for  spinlock-test
implementation with kernel module ?

Thanks
Ling

[-- Attachment #2: spinlock.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 4152 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  9:33   ` Peter Zijlstra
  2015-10-19 17:20     ` Waiman Long
@ 2015-10-20  3:00     ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2015-10-20  3:00 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, Ma Ling, waiman.long

2015-10-19 17:33 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
> On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
>> From: Ma Ling <ling.ml@alibaba-inc.com>
>>
>> All load instructions can run speculatively but they have to follow
>> memory order rule in multiple cores as below:
>> _x = _y = 0
>>
>> Processor 0                           Processor 1
>>
>> mov r1, [ _y]  //M1                   mov [ _x], 1  //M3
>> mov r2, [ _x]  //M2                   mov [ _y], 1  //M4
>>
>> If r1 = 1, r2 must be 1
>>
>> In order to guarantee above rule, although Processor 0 execute
>> M1 and M2 instruction out of order, they are kept in ROB,
>> when load buffer for _x in Processor 0 received the update
>> message from Processor 1, Processor 0 need to roll back
>> from M2 instruction, which will flush the whole pipeline,
>> the latency is over the penalty from branch prediction miss.
>>
>> In this patch we use lock cmpxchg instruction to force load
>> instructions to be serialization, the destination operand
>> receives a write cycle without regard to the result of
>> the comparison, which can help us to reduce the penalty
>> from load instruction roll back.
>>
>> Our experiment indicates the performance can be improved by 10%~15%
>> for 2 and 3 threads cases, the conflicts from lock cache line
>> spend them most of the time.
>
> On what hardware? Also, you forgot to Cc Waiman, who is a prime author
> of this code. Excessive quoting for his benefit.
>
>> Signed-off-by: Ma Ling <ling.ml@alibaba-inc.com>
>> ---
>>  kernel/locking/qspinlock.c |   43 ++++++++++++++++++-------------------------
>>  1 files changed, 18 insertions(+), 25 deletions(-)
>>
>> diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
>> index 87e9ce6..16421f2 100644
>> --- a/kernel/locking/qspinlock.c
>> +++ b/kernel/locking/qspinlock.c
>> @@ -332,25 +332,14 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
>>       if (new == _Q_LOCKED_VAL)
>>               return;
>>
>> -     /*
>> -      * we're pending, wait for the owner to go away.
>> -      *
>> -      * *,1,1 -> *,1,0
>> +     /* we're waiting, and get lock owner
>
> That's incorrect coding style
Ok, I will fix, thx.
>
>>        *
>> -      * this wait loop must be a load-acquire such that we match the
>> -      * store-release that clears the locked bit and create lock
>> -      * sequentiality; this is because not all clear_pending_set_locked()
>> -      * implementations imply full barriers.
>> +      * *,1,* -> *,0,1
>>        */
>> -     while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_MASK)
>> +     while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending,
>> +             _Q_PENDING_VAL, _Q_LOCKED_VAL) != _Q_PENDING_VAL)
>
> That's both horrible coding style and painful, we should not spin-wait
> with a cmpxchg instruction like that.
Ok I will fix
>
>>               cpu_relax();
>> -
>> -     /*
>> -      * take ownership and clear the pending bit.
>> -      *
>> -      * *,1,0 -> *,0,1
>> -      */
>> -     clear_pending_set_locked(lock);
>> +
>>       return;
>>
>>       /*
>> @@ -399,17 +388,21 @@ queue:
>>        * we're at the head of the waitqueue, wait for the owner & pending to
>>        * go away.
>>        *
>> -      * *,x,y -> *,0,0
>> -      *
>> -      * this wait loop must use a load-acquire such that we match the
>> -      * store-release that clears the locked bit and create lock
>> -      * sequentiality; this is because the set_locked() function below
>> -      * does not imply a full barrier.
>> -      *
>> +      * *,x,y -> *,0,1
>>        */
>>       pv_wait_head(lock, node);
>> -     while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_PENDING_MASK)
>> +     next = READ_ONCE(node->next);
>> +     while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending, 0,
>> +             _Q_LOCKED_VAL) != 0) {
>
> idem
>
>> +             next = READ_ONCE(node->next);
>>               cpu_relax();
>> +     }
>> +
>> +     if (next)
>> +             goto next_node;
>> +
>> +     val = smp_load_acquire(&lock->val.counter);
>> +     tail = tail | _Q_LOCKED_VAL;
>>
>>       /*
>>        * claim the lock:
>> @@ -423,7 +416,6 @@ queue:
>>        */
>>       for (;;) {
>>               if (val != tail) {
>> -                     set_locked(lock);
>>                       break;
>>               }
>>               old = atomic_cmpxchg(&lock->val, val, _Q_LOCKED_VAL);
>> @@ -439,6 +431,7 @@ queue:
>>       while (!(next = READ_ONCE(node->next)))
>>               cpu_relax();
>>
>> +next_node:
>>       arch_mcs_spin_unlock_contended(&next->locked);
>>       pv_kick_node(lock, next);
>>
>> --
>> 1.7.1
>>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  9:46   ` Peter Zijlstra
@ 2015-10-20  3:03     ` Ling Ma
  2015-10-20  3:24     ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2015-10-20  3:03 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, Ma Ling, Waiman Long

2015-10-19 17:46 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
> On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
>> From: Ma Ling <ling.ml@alibaba-inc.com>
>>
>> All load instructions can run speculatively but they have to follow
>> memory order rule in multiple cores as below:
>> _x = _y = 0
>>
>> Processor 0                           Processor 1
>>
>> mov r1, [ _y]  //M1                   mov [ _x], 1  //M3
>> mov r2, [ _x]  //M2                   mov [ _y], 1  //M4
>>
>> If r1 = 1, r2 must be 1
>>
>> In order to guarantee above rule, although Processor 0 execute
>> M1 and M2 instruction out of order, they are kept in ROB,
>> when load buffer for _x in Processor 0 received the update
>> message from Processor 1, Processor 0 need to roll back
>> from M2 instruction, which will flush the whole pipeline,
>> the latency is over the penalty from branch prediction miss.
>>
>> In this patch we use lock cmpxchg instruction to force load
>
> "lock cmpxchg" makes me think you're working on x86.
>
>> instructions to be serialization,
>
> smp_rmb() does that, and that's 'free' on x86. Because x86 doesn't do
> read reordering.
>
>> the destination operand
>> receives a write cycle without regard to the result of
>> the comparison, which can help us to reduce the penalty
>> from load instruction roll back.
>
> And that makes me think I'm not understanding what you're getting at. If
> you need to force memory order, a "fence" (or smp_mb()) would still be
> cheaper than endlessly pulling the line into exclusive state for no
> reason, right?
>
>> Our experiment indicates the performance can be improved by 10%~15%
>> for 2 and 3 threads cases, the conflicts from lock cache line
>> spend them most of the time.
>
> That just doesn't parse, what?
When the thread number is 2 or 3, only lock cache line will generate conflicts,
and cost them the most of the time.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19 17:18   ` Waiman Long
@ 2015-10-20  3:12     ` Ling Ma
  2015-10-20 18:55       ` Waiman Long
  0 siblings, 1 reply; 228+ messages in thread
From: Ling Ma @ 2015-10-20  3:12 UTC (permalink / raw)
  To: Waiman Long; +Cc: Peter Zijlstra, mingo, linux-kernel, Ma Ling

2015-10-20 1:18 GMT+08:00 Waiman Long <waiman.long@hpe.com>:
> On 10/18/2015 10:27 PM, ling.ma.program@gmail.com wrote:
>>
>> From: Ma Ling<ling.ml@alibaba-inc.com>
>>
>> All load instructions can run speculatively but they have to follow
>> memory order rule in multiple cores as below:
>> _x = _y = 0
>>
>> Processor 0                             Processor 1
>>
>> mov r1, [ _y]  //M1                     mov [ _x], 1  //M3
>> mov r2, [ _x]  //M2                     mov [ _y], 1  //M4
>>
>> If r1 = 1, r2 must be 1
>>
>> In order to guarantee above rule, although Processor 0 execute
>> M1 and M2 instruction out of order, they are kept in ROB,
>> when load buffer for _x in Processor 0 received the update
>> message from Processor 1, Processor 0 need to roll back
>> from M2 instruction, which will flush the whole pipeline,
>> the latency is over the penalty from branch prediction miss.
>>
>> In this patch we use lock cmpxchg instruction to force load
>> instructions to be serialization, the destination operand
>> receives a write cycle without regard to the result of
>> the comparison, which can help us to reduce the penalty
>> from load instruction roll back.
>>
>> Our experiment indicates the performance can be improved by 10%~15%
>> for 2 and 3 threads cases, the conflicts from lock cache line
>> spend them most of the time.
>
>
> What kind of performance test were you running? With the right timing, it is
> possible that you see some performance gain. However, if the lock hold time
> is longer so that a fair number of cmpxchg instructions have to be executed
> before it can get the lock, you may see a performance degradation especially
> if the lock holder needs to access the lock cacheline.
>
> In general, we try to avoid this kind of cmpxchg loop unless we are sure
> that at most a few iterations of the loop may happen.

Waiman,

The machine is Haswell (2699 V3, COD off, HT on, 2 sockets)
(we have sent test module in separate email)



A.      Data is located with lock in one cache line On 2 threads cases
(only write struct member data_a)

 1.       Load version test 5 times, the cost time is below:


[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 103904620

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 104351876

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 118599784

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 103064024

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 103389696

Totally cost time is 533310000

2.       Lock cmpxchg version test 5 times, the cost time is below:

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 67081220

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 97640708

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 96439612

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 66699296

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 96464800



Totally cost time is 424325636



Above data shows lock cmpxchg is better about average 25% (533310000/424325636)



B.      Data is located with lock in different cache line On 2 threads
cases(only write struct member data_b)



1.       Load version test 5 times, the cost time is below:



[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 174266128

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 205053924

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 160165124

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 173241552

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 205765008

Totally cost time is 918491736



2.       Lock cmpxchg version test 5 times, the cost time is below:

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 113410044

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 116293104

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 116064256

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 189320876

[root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c



 all cost time is 123735352

Totally cost time is 658823632



Above data shows lock cmpxchg is better about average 39%  (918491736/658823632)




>
>>
>> Thanks
>> Ling
>>
>> Signed-off-by: Ma Ling<ling.ml@alibaba-inc.com>
>> ---
>>   kernel/locking/qspinlock.c |   43
>> ++++++++++++++++++-------------------------
>>   1 files changed, 18 insertions(+), 25 deletions(-)
>>
>> diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
>> index 87e9ce6..16421f2 100644
>> --- a/kernel/locking/qspinlock.c
>> +++ b/kernel/locking/qspinlock.c
>> @@ -332,25 +332,14 @@ void queued_spin_lock_slowpath(struct qspinlock
>> *lock, u32 val)
>>         if (new == _Q_LOCKED_VAL)
>>                 return;
>>
>> -       /*
>> -        * we're pending, wait for the owner to go away.
>> -        *
>> -        * *,1,1 ->  *,1,0
>> +       /* we're waiting, and get lock owner
>>          *
>> -        * this wait loop must be a load-acquire such that we match the
>> -        * store-release that clears the locked bit and create lock
>> -        * sequentiality; this is because not all
>> clear_pending_set_locked()
>> -        * implementations imply full barriers.
>> +        * *,1,* ->  *,0,1
>>          */
>> -       while ((val = smp_load_acquire(&lock->val.counter))&
>> _Q_LOCKED_MASK)
>> +       while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending,
>> +               _Q_PENDING_VAL, _Q_LOCKED_VAL) != _Q_PENDING_VAL)
>>                 cpu_relax();
>> -
>> -       /*
>> -        * take ownership and clear the pending bit.
>> -        *
>> -        * *,1,0 ->  *,0,1
>> -        */
>> -       clear_pending_set_locked(lock);
>> +
>>         return;
>>
>>         /*
>> @@ -399,17 +388,21 @@ queue:
>>          * we're at the head of the waitqueue, wait for the owner&
>> pending to
>>          * go away.
>>          *
>> -        * *,x,y ->  *,0,0
>> -        *
>> -        * this wait loop must use a load-acquire such that we match the
>> -        * store-release that clears the locked bit and create lock
>> -        * sequentiality; this is because the set_locked() function below
>> -        * does not imply a full barrier.
>> -        *
>> +        * *,x,y ->  *,0,1
>>          */
>>         pv_wait_head(lock, node);
>> -       while ((val = smp_load_acquire(&lock->val.counter))&
>> _Q_LOCKED_PENDING_MASK)
>> +       next = READ_ONCE(node->next);
>> +       while (cmpxchg(&((struct __qspinlock *)lock)->locked_pending, 0,
>
>
> The locked_pending field isn't valid if _Q_PENDING_BITS != 8. So it won't
> work if NR_CPUS is 16k or more.
>
>> +               _Q_LOCKED_VAL) != 0) {
>> +               next = READ_ONCE(node->next);
>>                 cpu_relax();
>> +       }
>> +
>> +       if (next)
>> +               goto next_node;
>
>
> I did notice a slight performance benefit by reading the next pointer early
> in light load cases myself. However, it is a very minor improvement that I
> haven't actively pursued it.

We use "next" to avoid smp_load_acquire(&lock->val.counter)
instruction rollback.

>
>> +
>> +       val = smp_load_acquire(&lock->val.counter);
>> +       tail = tail | _Q_LOCKED_VAL;
>>
>>         /*
>>          * claim the lock:
>> @@ -423,7 +416,6 @@ queue:
>>          */
>>         for (;;) {
>>                 if (val != tail) {
>> -                       set_locked(lock);
>>                         break;
>>                 }
>>                 old = atomic_cmpxchg(&lock->val, val, _Q_LOCKED_VAL);
>> @@ -439,6 +431,7 @@ queue:
>>         while (!(next = READ_ONCE(node->next)))
>>                 cpu_relax();
>>
>> +next_node:
>>         arch_mcs_spin_unlock_contended(&next->locked);
>>         pv_kick_node(lock, next);
>>
>

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-19  9:46   ` Peter Zijlstra
  2015-10-20  3:03     ` Ling Ma
@ 2015-10-20  3:24     ` Ling Ma
  2015-10-20  9:16       ` Peter Zijlstra
  1 sibling, 1 reply; 228+ messages in thread
From: Ling Ma @ 2015-10-20  3:24 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, Ma Ling, Waiman Long

2015-10-19 17:46 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
> On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
>> From: Ma Ling <ling.ml@alibaba-inc.com>
>>
>> All load instructions can run speculatively but they have to follow
>> memory order rule in multiple cores as below:
>> _x = _y = 0
>>
>> Processor 0                           Processor 1
>>
>> mov r1, [ _y]  //M1                   mov [ _x], 1  //M3
>> mov r2, [ _x]  //M2                   mov [ _y], 1  //M4
>>
>> If r1 = 1, r2 must be 1
>>
>> In order to guarantee above rule, although Processor 0 execute
>> M1 and M2 instruction out of order, they are kept in ROB,
>> when load buffer for _x in Processor 0 received the update
>> message from Processor 1, Processor 0 need to roll back
>> from M2 instruction, which will flush the whole pipeline,
>> the latency is over the penalty from branch prediction miss.
>>
>> In this patch we use lock cmpxchg instruction to force load
>
> "lock cmpxchg" makes me think you're working on x86.
>
>> instructions to be serialization,
>
> smp_rmb() does that, and that's 'free' on x86. Because x86 doesn't do
> read reordering.
>
>> the destination operand
>> receives a write cycle without regard to the result of
>> the comparison, which can help us to reduce the penalty
>> from load instruction roll back.
>
> And that makes me think I'm not understanding what you're getting at. If
> you need to force memory order, a "fence" (or smp_mb()) would still be
> cheaper than endlessly pulling the line into exclusive state for no
> reason, right?

Peter,

we tested instruction lfence, but we hard to see any benefit, lfence
only force load instruction ,
but load instruction still will rollback ,actually cmpxchg behavior is
more like write operation,
so we choose it.

Thanks
Ling
>
>> Our experiment indicates the performance can be improved by 10%~15%
>> for 2 and 3 threads cases, the conflicts from lock cache line
>> spend them most of the time.
>
> That just doesn't parse, what?

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  2:57     ` Ling Ma
@ 2015-10-20  8:48       ` Ingo Molnar
  2015-10-21  5:28         ` Ling Ma
  2015-10-20  9:15       ` Peter Zijlstra
  1 sibling, 1 reply; 228+ messages in thread
From: Ingo Molnar @ 2015-10-20  8:48 UTC (permalink / raw)
  To: Ling Ma; +Cc: peterz, mingo, linux-kernel, Ma Ling, Waiman.Long


* Ling Ma <ling.ma.program@gmail.com> wrote:

> > So it would be nice to create a new user-space spinlock testing facility, via 
> > a new 'perf bench spinlock' feature or so. That way others can test and 
> > validate your results on different hardware as well.
>
> Attached the spinlock test module . Queued spinlock will run very slowly in user 
> space because process switch context, it is OK for spinlock-test implementation 
> with kernel module ?

Not sure what you mean by 'because process switch context': if you pin the test 
tasks to individual CPUs and make sure there's nothing else running it should be 
equivalent to kernel-space execution.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  2:57     ` Ling Ma
  2015-10-20  8:48       ` Ingo Molnar
@ 2015-10-20  9:15       ` Peter Zijlstra
  1 sibling, 0 replies; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-20  9:15 UTC (permalink / raw)
  To: Ling Ma; +Cc: Ingo Molnar, mingo, linux-kernel, Ma Ling, Waiman.Long

On Tue, Oct 20, 2015 at 10:57:53AM +0800, Ling Ma wrote:
> >
> > So it would be nice to create a new user-space spinlock testing facility, via a
> > new 'perf bench spinlock' feature or so. That way others can test and validate
> > your results on different hardware as well.
> >
> Attached the spinlock test module . Queued spinlock will run very
> slowly in user space
> because process switch context, it is OK for  spinlock-test
> implementation with kernel module ?

Works just fine in userspace if you pin each thread to a cpu and ensure
there's nothing else running on the system.


^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  3:24     ` Ling Ma
@ 2015-10-20  9:16       ` Peter Zijlstra
  2015-10-21  5:30         ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-20  9:16 UTC (permalink / raw)
  To: Ling Ma; +Cc: mingo, linux-kernel, Ma Ling, Waiman Long

On Tue, Oct 20, 2015 at 11:24:02AM +0800, Ling Ma wrote:
> 2015-10-19 17:46 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
> > On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
> >> From: Ma Ling <ling.ml@alibaba-inc.com>
> >>
> >> All load instructions can run speculatively but they have to follow
> >> memory order rule in multiple cores as below:
> >> _x = _y = 0
> >>
> >> Processor 0                           Processor 1
> >>
> >> mov r1, [ _y]  //M1                   mov [ _x], 1  //M3
> >> mov r2, [ _x]  //M2                   mov [ _y], 1  //M4
> >>
> >> If r1 = 1, r2 must be 1
> >>
> >> In order to guarantee above rule, although Processor 0 execute
> >> M1 and M2 instruction out of order, they are kept in ROB,
> >> when load buffer for _x in Processor 0 received the update
> >> message from Processor 1, Processor 0 need to roll back
> >> from M2 instruction, which will flush the whole pipeline,
> >> the latency is over the penalty from branch prediction miss.
> >>
> >> In this patch we use lock cmpxchg instruction to force load
> >
> > "lock cmpxchg" makes me think you're working on x86.
> >
> >> instructions to be serialization,
> >
> > smp_rmb() does that, and that's 'free' on x86. Because x86 doesn't do
> > read reordering.
> >
> >> the destination operand
> >> receives a write cycle without regard to the result of
> >> the comparison, which can help us to reduce the penalty
> >> from load instruction roll back.
> >
> > And that makes me think I'm not understanding what you're getting at. If
> > you need to force memory order, a "fence" (or smp_mb()) would still be
> > cheaper than endlessly pulling the line into exclusive state for no
> > reason, right?
> 
> Peter,
> 
> we tested instruction lfence, but we hard to see any benefit, lfence
> only force load instruction ,
> but load instruction still will rollback ,actually cmpxchg behavior is
> more like write operation,
> so we choose it.

But why? I'm just not getting this.

Also LOCK CMPXCHG is 24 cycles when hot, that's almost as bad as
a pipeline flush, and it can be many times worse when it needs to
actually fetch memory from further than L1.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  3:12     ` Ling Ma
@ 2015-10-20 18:55       ` Waiman Long
  2015-10-21  5:43         ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: Waiman Long @ 2015-10-20 18:55 UTC (permalink / raw)
  To: Ling Ma; +Cc: Peter Zijlstra, mingo, linux-kernel, Ma Ling

On 10/19/2015 11:12 PM, Ling Ma wrote:
> 2015-10-20 1:18 GMT+08:00 Waiman Long<waiman.long@hpe.com>:
>> On 10/18/2015 10:27 PM, ling.ma.program@gmail.com wrote:
>>> From: Ma Ling<ling.ml@alibaba-inc.com>
>>>
>>> All load instructions can run speculatively but they have to follow
>>> memory order rule in multiple cores as below:
>>> _x = _y = 0
>>>
>>> Processor 0                             Processor 1
>>>
>>> mov r1, [ _y]  //M1                     mov [ _x], 1  //M3
>>> mov r2, [ _x]  //M2                     mov [ _y], 1  //M4
>>>
>>> If r1 = 1, r2 must be 1
>>>
>>> In order to guarantee above rule, although Processor 0 execute
>>> M1 and M2 instruction out of order, they are kept in ROB,
>>> when load buffer for _x in Processor 0 received the update
>>> message from Processor 1, Processor 0 need to roll back
>>> from M2 instruction, which will flush the whole pipeline,
>>> the latency is over the penalty from branch prediction miss.
>>>
>>> In this patch we use lock cmpxchg instruction to force load
>>> instructions to be serialization, the destination operand
>>> receives a write cycle without regard to the result of
>>> the comparison, which can help us to reduce the penalty
>>> from load instruction roll back.
>>>
>>> Our experiment indicates the performance can be improved by 10%~15%
>>> for 2 and 3 threads cases, the conflicts from lock cache line
>>> spend them most of the time.
>>
>> What kind of performance test were you running? With the right timing, it is
>> possible that you see some performance gain. However, if the lock hold time
>> is longer so that a fair number of cmpxchg instructions have to be executed
>> before it can get the lock, you may see a performance degradation especially
>> if the lock holder needs to access the lock cacheline.
>>
>> In general, we try to avoid this kind of cmpxchg loop unless we are sure
>> that at most a few iterations of the loop may happen.
> Waiman,
>
> The machine is Haswell (2699 V3, COD off, HT on, 2 sockets)
> (we have sent test module in separate email)
>
>
>
> A.      Data is located with lock in one cache line On 2 threads cases
> (only write struct member data_a)
>
>   1.       Load version test 5 times, the cost time is below:
>
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 103904620
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 104351876
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 118599784
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 103064024
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 103389696
>
> Totally cost time is 533310000
>
> 2.       Lock cmpxchg version test 5 times, the cost time is below:
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 67081220
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 97640708
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 96439612
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 66699296
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 96464800
>
>
>
> Totally cost time is 424325636
>
>
>
> Above data shows lock cmpxchg is better about average 25% (533310000/424325636)
>
>
>
> B.      Data is located with lock in different cache line On 2 threads
> cases(only write struct member data_b)
>
>
>
> 1.       Load version test 5 times, the cost time is below:
>
>
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 174266128
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 205053924
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 160165124
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 173241552
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 205765008
>
> Totally cost time is 918491736
>
>
>
> 2.       Lock cmpxchg version test 5 times, the cost time is below:
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 113410044
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 116293104
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 116064256
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 189320876
>
> [root@localhost spinlock]# insmod dummy.ko; rmmod dummy;dmesg -c
>
>
>
>   all cost time is 123735352
>
> Totally cost time is 658823632
>
>
>
> Above data shows lock cmpxchg is better about average 39%  (918491736/658823632)
>
>

I did see some performance improvement when I used your test program on 
a Haswell-EX system. It seems like the use of cmpxchg has forced the 
changed memory values to be visible to other processors earlier. I also 
ran your test on an older machine with Westmere-EX processors. This 
time, I didn't see any performance improvement. In fact, your change 
actually make it a tiny bit slower. So the benefit of your patch can be 
highly processor sensitive.

As other architectures like ARM & AA64 are going to adopt qspinlock in 
the near future, we will also need to make sure that it won't cause a 
regression there. So I don't see your patch has a big chance of being 
merged upstream unless you can provide a real world workload that can 
benefit from your patch. Even then, proving that it won't cause 
regression in other processors or architectures can be tedious.

Cheers,
Longman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  8:48       ` Ingo Molnar
@ 2015-10-21  5:28         ` Ling Ma
  2015-10-21  7:54           ` Peter Zijlstra
  0 siblings, 1 reply; 228+ messages in thread
From: Ling Ma @ 2015-10-21  5:28 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Peter Zijlstra, mingo, linux-kernel, Ma Ling, Waiman Long

Ok, we will put the spinlock test into the perf bench.

Thanks
Ling

2015-10-20 16:48 GMT+08:00 Ingo Molnar <mingo@kernel.org>:
>
> * Ling Ma <ling.ma.program@gmail.com> wrote:
>
>> > So it would be nice to create a new user-space spinlock testing facility, via
>> > a new 'perf bench spinlock' feature or so. That way others can test and
>> > validate your results on different hardware as well.
>>
>> Attached the spinlock test module . Queued spinlock will run very slowly in user
>> space because process switch context, it is OK for spinlock-test implementation
>> with kernel module ?
>
> Not sure what you mean by 'because process switch context': if you pin the test
> tasks to individual CPUs and make sure there's nothing else running it should be
> equivalent to kernel-space execution.
>
> Thanks,
>
>         Ingo

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20  9:16       ` Peter Zijlstra
@ 2015-10-21  5:30         ` Ling Ma
  0 siblings, 0 replies; 228+ messages in thread
From: Ling Ma @ 2015-10-21  5:30 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: mingo, linux-kernel, Ma Ling, Waiman Long

2015-10-20 17:16 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
> On Tue, Oct 20, 2015 at 11:24:02AM +0800, Ling Ma wrote:
>> 2015-10-19 17:46 GMT+08:00 Peter Zijlstra <peterz@infradead.org>:
>> > On Mon, Oct 19, 2015 at 10:27:22AM +0800, ling.ma.program@gmail.com wrote:
>> >> From: Ma Ling <ling.ml@alibaba-inc.com>
>> >>
>> >> All load instructions can run speculatively but they have to follow
>> >> memory order rule in multiple cores as below:
>> >> _x = _y = 0
>> >>
>> >> Processor 0                           Processor 1
>> >>
>> >> mov r1, [ _y]  //M1                   mov [ _x], 1  //M3
>> >> mov r2, [ _x]  //M2                   mov [ _y], 1  //M4
>> >>
>> >> If r1 = 1, r2 must be 1
>> >>
>> >> In order to guarantee above rule, although Processor 0 execute
>> >> M1 and M2 instruction out of order, they are kept in ROB,
>> >> when load buffer for _x in Processor 0 received the update
>> >> message from Processor 1, Processor 0 need to roll back
>> >> from M2 instruction, which will flush the whole pipeline,
>> >> the latency is over the penalty from branch prediction miss.
>> >>
>> >> In this patch we use lock cmpxchg instruction to force load
>> >
>> > "lock cmpxchg" makes me think you're working on x86.
>> >
>> >> instructions to be serialization,
>> >
>> > smp_rmb() does that, and that's 'free' on x86. Because x86 doesn't do
>> > read reordering.
>> >
>> >> the destination operand
>> >> receives a write cycle without regard to the result of
>> >> the comparison, which can help us to reduce the penalty
>> >> from load instruction roll back.
>> >
>> > And that makes me think I'm not understanding what you're getting at. If
>> > you need to force memory order, a "fence" (or smp_mb()) would still be
>> > cheaper than endlessly pulling the line into exclusive state for no
>> > reason, right?
>>
>> Peter,
>>
>> we tested instruction lfence, but we hard to see any benefit, lfence
>> only force load instruction ,
>> but load instruction still will rollback ,actually cmpxchg behavior is
>> more like write operation,
>> so we choose it.
>
> But why? I'm just not getting this.
>
> Also LOCK CMPXCHG is 24 cycles when hot, that's almost as bad as
> a pipeline flush, and it can be many times worse when it needs to
> actually fetch memory from further than L1.

We will clarify the root cause about this question soon.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-20 18:55       ` Waiman Long
@ 2015-10-21  5:43         ` Ling Ma
  0 siblings, 0 replies; 228+ messages in thread
From: Ling Ma @ 2015-10-21  5:43 UTC (permalink / raw)
  To: Waiman Long; +Cc: Peter Zijlstra, mingo, linux-kernel, Ma Ling

>
> I did see some performance improvement when I used your test program on a
> Haswell-EX system. It seems like the use of cmpxchg has forced the changed
> memory values to be visible to other processors earlier. I also ran your
> test on an older machine with Westmere-EX processors. This time, I didn't
> see any performance improvement. In fact, your change actually make it a
> tiny bit slower. So the benefit of your patch can be highly processor
> sensitive.
>
> As other architectures like ARM & AA64 are going to adopt qspinlock in the
> near future, we will also need to make sure that it won't cause a regression
> there. So I don't see your patch has a big chance of being merged upstream
> unless you can provide a real world workload that can benefit from your
> patch. Even then, proving that it won't cause regression in other processors
> or architectures can be tedious.
>

The optimization will be closely related with CPU arch and cache
coherence implementation.
so we will test it for real world workload on Haswell, and send out the result.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback
  2015-10-21  5:28         ` Ling Ma
@ 2015-10-21  7:54           ` Peter Zijlstra
  0 siblings, 0 replies; 228+ messages in thread
From: Peter Zijlstra @ 2015-10-21  7:54 UTC (permalink / raw)
  To: Ling Ma; +Cc: Ingo Molnar, mingo, linux-kernel, Ma Ling, Waiman Long

[-- Attachment #1: Type: text/plain, Size: 293 bytes --]

On Wed, Oct 21, 2015 at 01:28:04PM +0800, Ling Ma wrote:
> Ok, we will put the spinlock test into the perf bench.

The attached is what I used back when we were doing the initial
qspinlock stuff.

I've not looked at it in quite some time, so it might be out of sync
with the kernel sources.



[-- Attachment #2: spinlocks.tar.bz2 --]
[-- Type: application/octet-stream, Size: 30648 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
       [not found] <yes>
                   ` (33 preceding siblings ...)
  2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
@ 2015-12-31  8:09 ` ling.ma.program
  2016-01-05 18:46   ` Waiman Long
  2016-01-05 21:18   ` Peter Zijlstra
  34 siblings, 2 replies; 228+ messages in thread
From: ling.ma.program @ 2015-12-31  8:09 UTC (permalink / raw)
  To: waiman.long; +Cc: peterz, mingo, linux-kernel, akpm, ling.ml

From: Ma Ling <ling.ml@alibaba-inc.com>

Hi ALL,

Wire-latency(RC delay) dominate modern computer performance,
conventional serialized works cause cache line ping-pong seriously,
the process spend lots of time and power to complete.
specially on multi-core platform.

However if the serialized works are sent to one core and executed
when lock contention happens, that can save much time and power,
because all shared data are located in private cache of one core.
We call the mechanism as Acceleration from Lock Integration
(ali spinlock)

Usually when requests are queued, we have to wait work to submit 
one bye one, in order to improve the whole throughput further,
we introduce LOCK_FREE. So when requests are sent to lock owner,
requester may do other works in parallelism, then ali_spin_is_completed 
function could tell us whether the work has been completed.

The new code is based on qspinlock and implement Lock Integration,
improves performance up to 3X on intel platform with 72 cores(18x2HTx2S HSW),
2X on ARM platform with 96 cores too. And additional trival changes on
Makefile/Kconfig are made to enable compiling of this feature on x86 platform.
(We would like to do further experiments according to your requirement)

Happy New Year 2016!
Ling 

Signed-off-by: Ma Ling <ling.ml@alibaba-inc.com> 
---
 arch/x86/Kconfig             |    1 +
 include/linux/alispinlock.h  |   41 ++++++++++++++++++
 kernel/Kconfig.locks         |    7 +++
 kernel/locking/Makefile      |    1 +
 kernel/locking/alispinlock.c |   97 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 147 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/alispinlock.h
 create mode 100644 kernel/locking/alispinlock.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index db3622f..47d9277 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -42,6 +42,7 @@ config X86
 	select ARCH_USE_CMPXCHG_LOCKREF		if X86_64
 	select ARCH_USE_QUEUED_RWLOCKS
 	select ARCH_USE_QUEUED_SPINLOCKS
+	select ARCH_USE_ALI_SPINLOCKS
 	select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if SMP
 	select ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	select ARCH_WANT_FRAME_POINTERS
diff --git a/include/linux/alispinlock.h b/include/linux/alispinlock.h
new file mode 100644
index 0000000..5207c41
--- /dev/null
+++ b/include/linux/alispinlock.h
@@ -0,0 +1,41 @@
+#ifndef ALI_SPINLOCK_H
+#define ALI_SPINLOCK_H
+/*
+ * Acceleration from Lock Integration
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * Copyright (C) 2015 Alibaba Group.
+ *
+ * Authors: Ma Ling <ling.ml@alibaba-inc.com>
+ *
+ */
+typedef struct ali_spinlock {
+	void  *lock_p;
+} ali_spinlock_t;
+
+struct ali_spinlock_info {
+	struct ali_spinlock_info *next;
+	int flags;
+	int locked;
+	void (*fn)(void *);
+	void *para;
+};
+
+static __always_inline int ali_spin_is_completed(struct ali_spinlock_info *ali)
+{
+	return (READ_ONCE(ali->locked) == 0);
+}
+
+void alispinlock(struct ali_spinlock *lock, struct ali_spinlock_info *ali);
+
+#define ALI_LOCK_FREE 1 
+#endif /* ALI_SPINLOCK_H */
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index ebdb004..5130c63 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -235,6 +235,13 @@ config LOCK_SPIN_ON_OWNER
        def_bool y
        depends on MUTEX_SPIN_ON_OWNER || RWSEM_SPIN_ON_OWNER
 
+config ARCH_USE_ALI_SPINLOCKS
+	bool
+
+config ALI_SPINLOCKS
+	def_bool y if ARCH_USE_ALI_SPINLOCKS
+	depends on SMP
+
 config ARCH_USE_QUEUED_SPINLOCKS
 	bool
 
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 8e96f6c..a4241f8 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LOCKDEP) += lockdep.o
 ifeq ($(CONFIG_PROC_FS),y)
 obj-$(CONFIG_LOCKDEP) += lockdep_proc.o
 endif
+obj-$(CONFIG_ALI_SPINLOCKS) += alispinlock.o
 obj-$(CONFIG_SMP) += spinlock.o
 obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o
 obj-$(CONFIG_SMP) += lglock.o
diff --git a/kernel/locking/alispinlock.c b/kernel/locking/alispinlock.c
new file mode 100644
index 0000000..43078b4
--- /dev/null
+++ b/kernel/locking/alispinlock.c
@@ -0,0 +1,97 @@
+/*
+ * Acceleration from Lock Integration
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * Copyright (C) 2015 Alibaba Group.
+ *
+ * Authors: Ma Ling <ling.ml@alibaba-inc.com>
+ *
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/alispinlock.h>
+/*
+ * Wire-latency(RC delay) dominate modern computer performance,
+ * conventional serialized works cause cache line ping-pong seriously,
+ * the process spend lots of time and power to complete.
+ * specially on multi-core platform.
+ * 
+ * However if the serialized works are sent to one core and executed
+ * when lock contention happens, that can save much time and power,
+ * because all shared data are located in private cache of one core.
+ * We call the mechanism as Acceleration from Lock Integration
+ * (ali spinlock)
+ * 
+ * Usually when requests are queued, we have to wait work to submit 
+ * one bye one, in order to improve the whole throughput further,
+ * we introduce LOCK_FREE. So when requests are sent to lock owner,
+ * requester may do other works in parallelism, then ali_spin_is_completed 
+ * function could tell us whether the work is completed.
+ *
+ */
+void alispinlock(struct ali_spinlock *lock, struct ali_spinlock_info *ali)
+{
+	struct ali_spinlock_info *next, *old;
+
+	ali->next = NULL;
+	ali->locked = 1;
+	old = xchg(&lock->lock_p, ali);
+
+	/* If NULL we are the first one */
+	if (old) {
+		WRITE_ONCE(old->next, ali);
+		if(ali->flags & ALI_LOCK_FREE)
+			return;
+		while((READ_ONCE(ali->locked)))
+			cpu_relax_lowlatency();
+		return;
+	}
+	old = READ_ONCE(lock->lock_p);
+
+	/* Handle all pending works */
+repeat:	
+	if(old == ali)
+		goto end;
+
+	while (!(next = READ_ONCE(ali->next)))
+		cpu_relax();
+	
+	ali->fn(ali->para);
+	ali->locked = 0;
+
+	if(old != next) {
+		while (!(ali = READ_ONCE(next->next)))
+			cpu_relax();
+		next->fn(next->para);
+		next->locked = 0;
+		goto repeat;
+		
+	} else
+		ali = next;
+end:
+	ali->fn(ali->para);
+	/* If we are the last one, clear lock and return */
+	old = cmpxchg(&lock->lock_p, old, 0);
+
+	if(old != ali) {
+		/* There are still some works to do */
+		while (!(next = READ_ONCE(ali->next)))
+			cpu_relax();
+		ali->locked = 0;
+		ali = next;
+		goto repeat;
+	}
+
+	ali->locked = 0;
+	return;
+}
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2015-12-31  8:09 ` [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform ling.ma.program
@ 2016-01-05 18:46   ` Waiman Long
  2016-01-08 22:48     ` Ling Ma
  2016-01-05 21:18   ` Peter Zijlstra
  1 sibling, 1 reply; 228+ messages in thread
From: Waiman Long @ 2016-01-05 18:46 UTC (permalink / raw)
  To: ling.ma.program; +Cc: peterz, mingo, linux-kernel, akpm, ling.ml

On 12/31/2015 03:09 AM, ling.ma.program@gmail.com wrote:
> From: Ma Ling<ling.ml@alibaba-inc.com>
>
> Hi ALL,
>
> Wire-latency(RC delay) dominate modern computer performance,
> conventional serialized works cause cache line ping-pong seriously,
> the process spend lots of time and power to complete.
> specially on multi-core platform.
>
> However if the serialized works are sent to one core and executed
> when lock contention happens, that can save much time and power,
> because all shared data are located in private cache of one core.
> We call the mechanism as Acceleration from Lock Integration
> (ali spinlock)
>
> Usually when requests are queued, we have to wait work to submit
> one bye one, in order to improve the whole throughput further,
> we introduce LOCK_FREE. So when requests are sent to lock owner,
> requester may do other works in parallelism, then ali_spin_is_completed
> function could tell us whether the work has been completed.
>
> The new code is based on qspinlock and implement Lock Integration,
> improves performance up to 3X on intel platform with 72 cores(18x2HTx2S HSW),
> 2X on ARM platform with 96 cores too. And additional trival changes on
> Makefile/Kconfig are made to enable compiling of this feature on x86 platform.
> (We would like to do further experiments according to your requirement)
>
> Happy New Year 2016!
> Ling
>
> Signed-off-by: Ma Ling<ling.ml@alibaba-inc.com>
> ---
>   arch/x86/Kconfig             |    1 +
>   include/linux/alispinlock.h  |   41 ++++++++++++++++++
>   kernel/Kconfig.locks         |    7 +++
>   kernel/locking/Makefile      |    1 +
>   kernel/locking/alispinlock.c |   97 ++++++++++++++++++++++++++++++++++++++++++
>   5 files changed, 147 insertions(+), 0 deletions(-)
>   create mode 100644 include/linux/alispinlock.h
>   create mode 100644 kernel/locking/alispinlock.c
>
>

You should include additional patches that illustrate the possible use 
cases and performance improvement before and after the patches. This 
will allow the reviewers to actually try it out and play with it.

Cheers,
Longman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2015-12-31  8:09 ` [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform ling.ma.program
  2016-01-05 18:46   ` Waiman Long
@ 2016-01-05 21:18   ` Peter Zijlstra
  2016-01-05 21:42     ` One Thousand Gnomes
  2016-01-08 22:56     ` Ling Ma
  1 sibling, 2 replies; 228+ messages in thread
From: Peter Zijlstra @ 2016-01-05 21:18 UTC (permalink / raw)
  To: ling.ma.program; +Cc: waiman.long, mingo, linux-kernel, akpm, ling.ml

On Thu, Dec 31, 2015 at 04:09:34PM +0800, ling.ma.program@gmail.com wrote:
> +void alispinlock(struct ali_spinlock *lock, struct ali_spinlock_info *ali)
> +{
> +	struct ali_spinlock_info *next, *old;
> +
> +	ali->next = NULL;
> +	ali->locked = 1;
> +	old = xchg(&lock->lock_p, ali);
> +
> +	/* If NULL we are the first one */
> +	if (old) {
> +		WRITE_ONCE(old->next, ali);
> +		if(ali->flags & ALI_LOCK_FREE)
> +			return;
> +		while((READ_ONCE(ali->locked)))
> +			cpu_relax_lowlatency();
> +		return;
> +	}
> +	old = READ_ONCE(lock->lock_p);
> +
> +	/* Handle all pending works */
> +repeat:	
> +	if(old == ali)
> +		goto end;
> +
> +	while (!(next = READ_ONCE(ali->next)))
> +		cpu_relax();
> +	
> +	ali->fn(ali->para);
> +	ali->locked = 0;
> +
> +	if(old != next) {
> +		while (!(ali = READ_ONCE(next->next)))
> +			cpu_relax();
> +		next->fn(next->para);
> +		next->locked = 0;
> +		goto repeat;
> +		
> +	} else
> +		ali = next;

So I have a whole bunch of problems with this thing.. For one I object
to this being called a lock. Its much more like an async work queue like
thing.

It suffers the typical problems all those constructs do; namely it
wrecks accountability.

But here that is compounded by the fact that you inject other people's
work into 'your' lock region, thereby bloating lock hold times. Worse,
afaict (from a quick reading) there really isn't a bound on the amount
of work you inject.

This will completely wreck scheduling latency. At the very least the
callback loop should have a need_resched() test on, but even that will
not work if this has IRQs disabled.


And while its a cute collapse of an MCS lock and lockless list style
work queue (MCS after all is a lockless list), saving a few cycles from
the naive spinlock+llist implementation of the same thing, I really
do not see enough justification for any of this.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-05 21:18   ` Peter Zijlstra
@ 2016-01-05 21:42     ` One Thousand Gnomes
  2016-01-06  8:16       ` Peter Zijlstra
  2016-01-08 23:01       ` Ling Ma
  2016-01-08 22:56     ` Ling Ma
  1 sibling, 2 replies; 228+ messages in thread
From: One Thousand Gnomes @ 2016-01-05 21:42 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: ling.ma.program, waiman.long, mingo, linux-kernel, akpm, ling.ml

> It suffers the typical problems all those constructs do; namely it
> wrecks accountability.

That's "government thinking" ;-) - for most real users throughput is
more important than accountability. With the right API it ought to also
be compile time switchable.

> But here that is compounded by the fact that you inject other people's
> work into 'your' lock region, thereby bloating lock hold times. Worse,
> afaict (from a quick reading) there really isn't a bound on the amount
> of work you inject.

That should be relatively easy to fix but for this kind of lock you
normally get the big wins from stuff that is only a short amount of
executing code. The fairness your trade in the cases it is useful should
be tiny except under extreme load, where the "accountability first"
behaviour would be to fall over in a heap.

If your "lock" involves a lot of work then it probably should be a work
queue or not using this kind of locking.

> And while its a cute collapse of an MCS lock and lockless list style
> work queue (MCS after all is a lockless list), saving a few cycles from
> the naive spinlock+llist implementation of the same thing, I really
> do not see enough justification for any of this.

I've only personally dealt with such locks in the embedded space but
there it was a lot more than a few cycles because you go from


	take lock
						spins
	pull things into cache
	do stuff
	cache lines go write/exclusive
	unlock

						take lock
						move all the cache
						do stuff
						etc

to

	take lock
						queue work
	pull things into cache
	do work 1
	caches line go write/exclusive
	do work 2
	
	unlock
						done

and for the kind of stuff you apply those locks you got big improvements.
Even on crappy little embedded processors cache bouncing hurts. Even
better work merging locks like this tend to improve throughput more the
higher the contention unlike most other lock types.

The claim in the original post is 3x performance but doesn't explain
performance doing what, or which kernel locks were switched and what
patches were used. I don't find the numbers hard to believe for a big big
box, but I'd like to see the actual use case patches so it can be benched
with other workloads and also for latency and the like.

Alan

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-05 21:42     ` One Thousand Gnomes
@ 2016-01-06  8:16       ` Peter Zijlstra
  2016-01-06  8:21         ` Peter Zijlstra
  2016-01-08 23:01       ` Ling Ma
  1 sibling, 1 reply; 228+ messages in thread
From: Peter Zijlstra @ 2016-01-06  8:16 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: ling.ma.program, waiman.long, mingo, linux-kernel, akpm, ling.ml

On Tue, Jan 05, 2016 at 09:42:27PM +0000, One Thousand Gnomes wrote:
> > It suffers the typical problems all those constructs do; namely it
> > wrecks accountability.
> 
> That's "government thinking" ;-) - for most real users throughput is
> more important than accountability. With the right API it ought to also
> be compile time switchable.

Its to do with having been involved with -rt. RT wants to do
accountability for such things because of PI and sorts.

> > But here that is compounded by the fact that you inject other people's
> > work into 'your' lock region, thereby bloating lock hold times. Worse,
> > afaict (from a quick reading) there really isn't a bound on the amount
> > of work you inject.
> 
> That should be relatively easy to fix but for this kind of lock you
> normally get the big wins from stuff that is only a short amount of
> executing code. The fairness your trade in the cases it is useful should
> be tiny except under extreme load, where the "accountability first"
> behaviour would be to fall over in a heap.
> 
> If your "lock" involves a lot of work then it probably should be a work
> queue or not using this kind of locking.

Sure, but the fact that it was not even mentioned/considered doesn't
give me a warm fuzzy feeling.

> > And while its a cute collapse of an MCS lock and lockless list style
> > work queue (MCS after all is a lockless list), saving a few cycles from
> > the naive spinlock+llist implementation of the same thing, I really
> > do not see enough justification for any of this.
> 
> I've only personally dealt with such locks in the embedded space but
> there it was a lot more than a few cycles because you go from

Nah, what I meant was that you can do the same callback style construct
with a llist and a spinlock.

> The claim in the original post is 3x performance but doesn't explain
> performance doing what, or which kernel locks were switched and what
> patches were used. I don't find the numbers hard to believe for a big big
> box, but I'd like to see the actual use case patches so it can be benched
> with other workloads and also for latency and the like.

Very much agreed, those claims need to be substantiated with actual
patches using this thing and independently verified.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-06  8:16       ` Peter Zijlstra
@ 2016-01-06  8:21         ` Peter Zijlstra
  2016-01-06 11:24           ` One Thousand Gnomes
  0 siblings, 1 reply; 228+ messages in thread
From: Peter Zijlstra @ 2016-01-06  8:21 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: ling.ma.program, waiman.long, mingo, linux-kernel, akpm, ling.ml

On Wed, Jan 06, 2016 at 09:16:43AM +0100, Peter Zijlstra wrote:
> On Tue, Jan 05, 2016 at 09:42:27PM +0000, One Thousand Gnomes wrote:
> > > It suffers the typical problems all those constructs do; namely it
> > > wrecks accountability.
> > 
> > That's "government thinking" ;-) - for most real users throughput is
> > more important than accountability. With the right API it ought to also
> > be compile time switchable.
> 
> Its to do with having been involved with -rt. RT wants to do
> accountability for such things because of PI and sorts.

Also, real people really do care about latency too, very bad worst case
spikes to upset things.

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-06  8:21         ` Peter Zijlstra
@ 2016-01-06 11:24           ` One Thousand Gnomes
  2016-01-08 22:44             ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: One Thousand Gnomes @ 2016-01-06 11:24 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: ling.ma.program, waiman.long, mingo, linux-kernel, akpm, ling.ml

On Wed, 6 Jan 2016 09:21:06 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> On Wed, Jan 06, 2016 at 09:16:43AM +0100, Peter Zijlstra wrote:
> > On Tue, Jan 05, 2016 at 09:42:27PM +0000, One Thousand Gnomes wrote:
> > > > It suffers the typical problems all those constructs do; namely it
> > > > wrecks accountability.
> > > 
> > > That's "government thinking" ;-) - for most real users throughput is
> > > more important than accountability. With the right API it ought to also
> > > be compile time switchable.
> > 
> > Its to do with having been involved with -rt. RT wants to do
> > accountability for such things because of PI and sorts.
> 
> Also, real people really do care about latency too, very bad worst case
> spikes to upset things.

Some yes - I'm familiar with the way some of the big financial number
crunching jobs need this. There are also people who instead care a lot
about throughput. Anything like this needs to end up with an external API
which looks the same whether the work is done via one thread or the other.

Alan

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-06 11:24           ` One Thousand Gnomes
@ 2016-01-08 22:44             ` Ling Ma
  2016-01-12 13:50               ` One Thousand Gnomes
  0 siblings, 1 reply; 228+ messages in thread
From: Ling Ma @ 2016-01-08 22:44 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Peter Zijlstra, Waiman Long, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 1704 bytes --]

The attachment (alispinlock.tar.bz2) includes original spinlock and
alispinlock ,
we compare them on 70 cores based on kernel 4.3, the alispinlock can
improve performance upto 3x.

the link: https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1035940.html
indicates when we introduce the idea for real application(user space
application  caused the bottle neck from  kernel spinlock )
the spinlock performance is improved by 1.9x (perf top -d1 also tell
us the spinlock cost time is reduced from 25% to 15%).

Appreciate your comments
Ling

2016-01-06 19:24 GMT+08:00 One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>:
> On Wed, 6 Jan 2016 09:21:06 +0100
> Peter Zijlstra <peterz@infradead.org> wrote:
>
>> On Wed, Jan 06, 2016 at 09:16:43AM +0100, Peter Zijlstra wrote:
>> > On Tue, Jan 05, 2016 at 09:42:27PM +0000, One Thousand Gnomes wrote:
>> > > > It suffers the typical problems all those constructs do; namely it
>> > > > wrecks accountability.
>> > >
>> > > That's "government thinking" ;-) - for most real users throughput is
>> > > more important than accountability. With the right API it ought to also
>> > > be compile time switchable.
>> >
>> > Its to do with having been involved with -rt. RT wants to do
>> > accountability for such things because of PI and sorts.
>>
>> Also, real people really do care about latency too, very bad worst case
>> spikes to upset things.
>
> Some yes - I'm familiar with the way some of the big financial number
> crunching jobs need this. There are also people who instead care a lot
> about throughput. Anything like this needs to end up with an external API
> which looks the same whether the work is done via one thread or the other.
>
> Alan

[-- Attachment #2: alispinlock.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 4529 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-05 18:46   ` Waiman Long
@ 2016-01-08 22:48     ` Ling Ma
  0 siblings, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-01-08 22:48 UTC (permalink / raw)
  To: Waiman Long; +Cc: Peter Zijlstra, mingo, linux-kernel, akpm, Ling

2016-01-06 2:46 GMT+08:00 Waiman Long <waiman.long@hpe.com>:
>
> On 12/31/2015 03:09 AM, ling.ma.program@gmail.com wrote:
>>
>> From: Ma Ling<ling.ml@alibaba-inc.com>
>>
>> Hi ALL,
>>
>> Wire-latency(RC delay) dominate modern computer performance,
>> conventional serialized works cause cache line ping-pong seriously,
>> the process spend lots of time and power to complete.
>> specially on multi-core platform.
>>
>> However if the serialized works are sent to one core and executed
>> when lock contention happens, that can save much time and power,
>> because all shared data are located in private cache of one core.
>> We call the mechanism as Acceleration from Lock Integration
>> (ali spinlock)
>>

> You should include additional patches that illustrate the possible use cases and performance improvement before and after the patches. This will allow the reviewers to actually try it out and play with it.
>
we have sent out in last email.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-05 21:18   ` Peter Zijlstra
  2016-01-05 21:42     ` One Thousand Gnomes
@ 2016-01-08 22:56     ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-01-08 22:56 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: Waiman Long, mingo, linux-kernel, akpm, Ling

> So I have a whole bunch of problems with this thing.. For one I object
> to this being called a lock. Its much more like an async work queue like
> thing.
Ok, I will fix it.

> It suffers the typical problems all those constructs do; namely it
> wrecks accountability.
Ok, I will fix it.

> But here that is compounded by the fact that you inject other people's
> work into 'your' lock region, thereby bloating lock hold times. Worse,
> afaict (from a quick reading) there really isn't a bound on the amount
> of work you inject.
>
> This will completely wreck scheduling latency. At the very least the
> callback loop should have a need_resched() test on, but even that will
> not work if this has IRQs disabled.
>
>
> And while its a cute collapse of an MCS lock and lockless list style
> work queue (MCS after all is a lockless list), saving a few cycles from
> the naive spinlock+llist implementation of the same thing, I really
> do not see enough justification for any of this.
we can fix it if we really don't need it.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-05 21:42     ` One Thousand Gnomes
  2016-01-06  8:16       ` Peter Zijlstra
@ 2016-01-08 23:01       ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-01-08 23:01 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Peter Zijlstra, Waiman Long, mingo, linux-kernel, akpm, Ling

> The claim in the original post is 3x performance but doesn't explain
> performance doing what, or which kernel locks were switched and what
> patches were used. I don't find the numbers hard to believe for a big big
> box, but I'd like to see the actual use case patches so it can be benched
> with other workloads and also for latency and the like.
>

We have sent out in email, please review and test it.

Thanks
Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-08 22:44             ` Ling Ma
@ 2016-01-12 13:50               ` One Thousand Gnomes
  2016-01-14  8:10                 ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: One Thousand Gnomes @ 2016-01-12 13:50 UTC (permalink / raw)
  To: Ling Ma; +Cc: Peter Zijlstra, Waiman Long, mingo, linux-kernel, akpm, Ling

On Sat, 9 Jan 2016 06:44:15 +0800
Ling Ma <ling.ma.program@gmail.com> wrote:

> The attachment (alispinlock.tar.bz2) includes original spinlock and
> alispinlock ,
> we compare them on 70 cores based on kernel 4.3, the alispinlock can
> improve performance upto 3x.
> 
> the link: https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1035940.html
> indicates when we introduce the idea for real application(user space
> application  caused the bottle neck from  kernel spinlock )
> the spinlock performance is improved by 1.9x (perf top -d1 also tell
> us the spinlock cost time is reduced from 25% to 15%).
> 
> Appreciate your comments

So this has not been applied to actual real kernel locks (ie converted
some of the hot kernel locks to it) and then benchmarked with a real
world workload. This is just for the theoretical locking overhead ?

Alan

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-12 13:50               ` One Thousand Gnomes
@ 2016-01-14  8:10                 ` Ling Ma
  2016-01-19  8:52                   ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: Ling Ma @ 2016-01-14  8:10 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Peter Zijlstra, Waiman Long, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 1662 bytes --]

Alan,

The attachment  (alispinlock.tar.bz2) in last email includes our
sample cases for spinlock.
The attachment (lock_test.tar.bz2) in this email includes the patch on
kernel 4.3v ,
which has been applied to actual real kernel locks:
when we run the user space program (thread.c) on 72cores E5-2699v3,
it cause many hot kernel spinlocks from __kmalloc and kfree  respectively
with original spinlock cpu cost 25% and  92715428576 cycles after
lock/unlock 1000000 times
with ali spinlock cpu cost 15% and  48475891244 cycles after
lock/unlock 1000000 times.
So we say in the real world workload the ali spinlock improve
performance by 1.9x
(92715428576 cycles/48475891244 cycles)

Thanks
Ling

the

2016-01-12 21:50 GMT+08:00 One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>:
> On Sat, 9 Jan 2016 06:44:15 +0800
> Ling Ma <ling.ma.program@gmail.com> wrote:
>
>> The attachment (alispinlock.tar.bz2) includes original spinlock and
>> alispinlock ,
>> we compare them on 70 cores based on kernel 4.3, the alispinlock can
>> improve performance upto 3x.
>>
>> the link: https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1035940.html
>> indicates when we introduce the idea for real application(user space
>> application  caused the bottle neck from  kernel spinlock )
>> the spinlock performance is improved by 1.9x (perf top -d1 also tell
>> us the spinlock cost time is reduced from 25% to 15%).
>>
>> Appreciate your comments
>
> So this has not been applied to actual real kernel locks (ie converted
> some of the hot kernel locks to it) and then benchmarked with a real
> world workload. This is just for the theoretical locking overhead ?
>
> Alan

[-- Attachment #2: lock_test.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 7447 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-14  8:10                 ` Ling Ma
@ 2016-01-19  8:52                   ` Ling Ma
  2016-01-19 15:36                     ` Waiman Long
  0 siblings, 1 reply; 228+ messages in thread
From: Ling Ma @ 2016-01-19  8:52 UTC (permalink / raw)
  To: One Thousand Gnomes
  Cc: Peter Zijlstra, Waiman Long, mingo, linux-kernel, akpm, Ling

Is it acceptable for performance improvement or more comments on this patch?

Thanks
Ling

2016-01-14 16:10 GMT+08:00 Ling Ma <ling.ma.program@gmail.com>:
> Alan,
>
> The attachment  (alispinlock.tar.bz2) in last email includes our
> sample cases for spinlock.
> The attachment (lock_test.tar.bz2) in this email includes the patch on
> kernel 4.3v ,
> which has been applied to actual real kernel locks:
> when we run the user space program (thread.c) on 72cores E5-2699v3,
> it cause many hot kernel spinlocks from __kmalloc and kfree  respectively
> with original spinlock cpu cost 25% and  92715428576 cycles after
> lock/unlock 1000000 times
> with ali spinlock cpu cost 15% and  48475891244 cycles after
> lock/unlock 1000000 times.
> So we say in the real world workload the ali spinlock improve
> performance by 1.9x
> (92715428576 cycles/48475891244 cycles)
>
> Thanks
> Ling
>
> the
>
> 2016-01-12 21:50 GMT+08:00 One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>:
>> On Sat, 9 Jan 2016 06:44:15 +0800
>> Ling Ma <ling.ma.program@gmail.com> wrote:
>>
>>> The attachment (alispinlock.tar.bz2) includes original spinlock and
>>> alispinlock ,
>>> we compare them on 70 cores based on kernel 4.3, the alispinlock can
>>> improve performance upto 3x.
>>>
>>> the link: https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1035940.html
>>> indicates when we introduce the idea for real application(user space
>>> application  caused the bottle neck from  kernel spinlock )
>>> the spinlock performance is improved by 1.9x (perf top -d1 also tell
>>> us the spinlock cost time is reduced from 25% to 15%).
>>>
>>> Appreciate your comments
>>
>> So this has not been applied to actual real kernel locks (ie converted
>> some of the hot kernel locks to it) and then benchmarked with a real
>> world workload. This is just for the theoretical locking overhead ?
>>
>> Alan

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-19  8:52                   ` Ling Ma
@ 2016-01-19 15:36                     ` Waiman Long
  2016-02-03  4:40                       ` Ling Ma
  0 siblings, 1 reply; 228+ messages in thread
From: Waiman Long @ 2016-01-19 15:36 UTC (permalink / raw)
  To: Ling Ma
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

On 01/19/2016 03:52 AM, Ling Ma wrote:
> Is it acceptable for performance improvement or more comments on this patch?
>
> Thanks
> Ling
>
>

Your alispinlock patchset should also include a use case where the lock 
is used by some code within the kernel with test that can show a 
performance improvement so that the reviewers can independently try it 
out and play around with it. The kernel community will not accept any 
patch without a use case in the kernel.

Your lock_test.tar file is not good enough as it is not a performance 
test of the patch that you sent out.

Cheers,
Longman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-01-19 15:36                     ` Waiman Long
@ 2016-02-03  4:40                       ` Ling Ma
  2016-02-03  6:00                         ` Ling Ma
  2016-02-03 21:42                         ` Waiman Long
  0 siblings, 2 replies; 228+ messages in thread
From: Ling Ma @ 2016-02-03  4:40 UTC (permalink / raw)
  To: Waiman Long
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 1329 bytes --]

Longman,

The attachment include user space code(thread.c), and kernel
patch(ali_work_queue.patch) based on 4.3.0-rc4,
we replaced all original spinlock (list_lock) in slab.h/c  with the
new mechanism.

The thread.c in user space caused lots of hot kernel spinlock from
__kmalloc and kfree,
perf top -d1 shows ~25%  before ali_work_queue.patch,after appending
this patch ,
the synchronous operation consumption from __kmalloc and kfree is
reduced from 25% to ~15% on Intel E5-2699V3
(we also observed the output from user space code (thread.c) is
improved clearly)

Peter, we will send the update version according to your comments.

Thanks
Ling


2016-01-19 23:36 GMT+08:00 Waiman Long <waiman.long@hpe.com>:
> On 01/19/2016 03:52 AM, Ling Ma wrote:
>>
>> Is it acceptable for performance improvement or more comments on this
>> patch?
>>
>> Thanks
>> Ling
>>
>>
>
> Your alispinlock patchset should also include a use case where the lock is
> used by some code within the kernel with test that can show a performance
> improvement so that the reviewers can independently try it out and play
> around with it. The kernel community will not accept any patch without a use
> case in the kernel.
>
> Your lock_test.tar file is not good enough as it is not a performance test
> of the patch that you sent out.
>
> Cheers,
> Longman

[-- Attachment #2: ali_work_queue.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 10512 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-02-03  4:40                       ` Ling Ma
@ 2016-02-03  6:00                         ` Ling Ma
  2016-02-03 21:42                         ` Waiman Long
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-02-03  6:00 UTC (permalink / raw)
  To: Waiman Long
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 2208 bytes --]

The attachment(thread.c) can tell us the new mechanism improve output
from  the user space code (thread,c) by 1.14x (1174810406/1026910602,
kernel spinlock consumption is reduced from 25% to 15%) as below:

  ORG         NEW
38186815 43644156
38340186 43121265
38383155 44087753
38567102 43532586
38027878 43622700
38011581 43396376
37861959 43322857
37963215 43375528
38039247 43618315
37989106 43406187
37916912 44163029
39053184 43138581
37928359 43247866
37967417 43390352
37909796 43218250
37727531 43256009
38032818 43460496
38001860 43536100
38019929 44231331
37846621 43550597
37823231 44229887
38108158 43142689
37771900 43228168
37652536 43901042
37649114 43172690
37591314 43380004
38539678 43435592

Total 1026910602 1174810406

Thanks
Ling

2016-02-03 12:40 GMT+08:00 Ling Ma <ling.ma.program@gmail.com>:
> Longman,
>
> The attachment include user space code(thread.c), and kernel
> patch(ali_work_queue.patch) based on 4.3.0-rc4,
> we replaced all original spinlock (list_lock) in slab.h/c  with the
> new mechanism.
>
> The thread.c in user space caused lots of hot kernel spinlock from
> __kmalloc and kfree,
> perf top -d1 shows ~25%  before ali_work_queue.patch,after appending
> this patch ,
> the synchronous operation consumption from __kmalloc and kfree is
> reduced from 25% to ~15% on Intel E5-2699V3
> (we also observed the output from user space code (thread.c) is
> improved clearly)
>
> Peter, we will send the update version according to your comments.
>
> Thanks
> Ling
>
>
> 2016-01-19 23:36 GMT+08:00 Waiman Long <waiman.long@hpe.com>:
>> On 01/19/2016 03:52 AM, Ling Ma wrote:
>>>
>>> Is it acceptable for performance improvement or more comments on this
>>> patch?
>>>
>>> Thanks
>>> Ling
>>>
>>>
>>
>> Your alispinlock patchset should also include a use case where the lock is
>> used by some code within the kernel with test that can show a performance
>> improvement so that the reviewers can independently try it out and play
>> around with it. The kernel community will not accept any patch without a use
>> case in the kernel.
>>
>> Your lock_test.tar file is not good enough as it is not a performance test
>> of the patch that you sent out.
>>
>> Cheers,
>> Longman

[-- Attachment #2: thread.c --]
[-- Type: text/x-csrc, Size: 2226 bytes --]

/**
	Test Case:
		OpenDir, Get status and close it.
*/
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

#define TEST_DIR "/tmp/thread"
#define MAX_TEST_THREAD (80)
#define MAX_TEST_FILE 5000

static unsigned long *result[MAX_TEST_THREAD];
static int stop = 0;

static void* case_function(void *para)
{
	int id = (int)(long)para;
	DIR *pDir;
	struct stat f_stat;
	struct dirent *entry=NULL;
	char path[256];
	char cmd[512];
	
	int filecnt       = 0;
	int dircnt        = 0;
	int filetotalsize = 0;
	unsigned long myresult = 0;
	int f = 0;
	
	result[id] = &myresult;

	/* Goto my path and construct empty file */
	sprintf(path, "%s/%d", TEST_DIR, id);
	printf("Creating temp file at %s....\n", path);

	sprintf(cmd, "mkdir %s", path);
	system(cmd);
	chdir(path);
	for (f = 0; f < MAX_TEST_FILE; f++)
	{
		char name[256];

		sprintf(name, "%s/%d", path, f);
		int t = open(name,  O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
		if (t != -1)
			close(t);
		else
		{
			printf("Errno = %d.\n", errno);
			exit(errno);
		}		
	}

again:
	if ((pDir = opendir(path)) == NULL)
	{
		printf("打开 %s 错误:没有那个文件或目录\n", TEST_DIR);
		goto err;
	}
	
	while ((entry = readdir(pDir)) != NULL)
	{
		struct stat buf;
		if (entry->d_name[0] == '.')
			continue;
		
		//f = open(entry->d_name, 0);
		f = stat(entry->d_name, &buf);
		
		if (f)
			close(f);
		myresult++;
		
		
		//printf("Filename %s, size %10d",entry->d_name, f_stat.st_size);
	}

	closedir(pDir);
	

	/* Need to stop */
	if (!stop)
		goto again;
	return 0;

err:
	;
}

void main()
{
	int i;
	pthread_t thread;

	system("mkdir "TEST_DIR);
		
	for (i = 0; i < MAX_TEST_THREAD; i++)
	{
		pthread_create(&thread, NULL, case_function, (void*)(long)i);
	}

	while (1)
	{
		sleep(1);
		unsigned long times = 0;
		//printf("Statistics:\n");

		for (i = 0; i < MAX_TEST_THREAD; i++)
		{
			//printf("%d\t", *result[i]);
			times =times +  *result[i];
		}
		printf("%ld\t\n", times);
		for (i = 0; i < MAX_TEST_THREAD; i++)
			*result[i] = 0;
	}
}

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-02-03  4:40                       ` Ling Ma
  2016-02-03  6:00                         ` Ling Ma
@ 2016-02-03 21:42                         ` Waiman Long
  2016-02-04  7:07                           ` Ling Ma
  2016-04-05  3:44                           ` Ling Ma
  1 sibling, 2 replies; 228+ messages in thread
From: Waiman Long @ 2016-02-03 21:42 UTC (permalink / raw)
  To: Ling Ma
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

On 02/02/2016 11:40 PM, Ling Ma wrote:
> Longman,
>
> The attachment include user space code(thread.c), and kernel
> patch(ali_work_queue.patch) based on 4.3.0-rc4,
> we replaced all original spinlock (list_lock) in slab.h/c  with the
> new mechanism.
>
> The thread.c in user space caused lots of hot kernel spinlock from
> __kmalloc and kfree,
> perf top -d1 shows ~25%  before ali_work_queue.patch,after appending
> this patch ,
> the synchronous operation consumption from __kmalloc and kfree is
> reduced from 25% to ~15% on Intel E5-2699V3
> (we also observed the output from user space code (thread.c) is
> improved clearly)

I have 2 major comments here. First of all, you should break up your 
patch into smaller ones. Large patch like the one in the tar ball is 
hard to review. Secondly, you are modifying over 1000 lines of code in 
mm/slab.c with some modest increase in performance. That can be hard to 
justify. Maybe you should find other use cases that involve less 
changes, but still have noticeable performance improvement. That will 
make it easier to be accepted.

Cheers,
Longman

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-02-03 21:42                         ` Waiman Long
@ 2016-02-04  7:07                           ` Ling Ma
  2016-04-05  3:44                           ` Ling Ma
  1 sibling, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-02-04  7:07 UTC (permalink / raw)
  To: Waiman Long
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 3516 bytes --]

> I have 2 major comments here. First of all, you should break up your patch
> into smaller ones. Large patch like the one in the tar ball is hard to
> review.

Ok, we will do it.

>Secondly, you are modifying over 1000 lines of code in mm/slab.c
> with some modest increase in performance. That can be hard to justify. Maybe
> you should find other use cases that involve less changes, but still have
> noticeable performance improvement. That will make it easier to be accepted.

In order to be justified the attachment in this letter include 3 files:

1. user space code (thread.c), which  can cause lots of hot kernel spinlock from
__kmalloc and kfree on multi-core platform

2. ali_work_queue.patch , the kernel patch for 4.3.0-rc4,
when we  run user space code (thread.c) based on the patch,
the synchronous operation consumption from __kmalloc and kfree is
about 15% on Intel E5-2699V3

3. org_spin_lock.patch, which is based on above ali_work_queue.patch,
when we  run user space code thread.c based on the patch,
the synchronous operation consumption from __kmalloc and kfree is
about 25% on Intel E5-2699V3


the main difference between ali_work_queue.patch and
org_spin_lock.patch as below:

diff --git a/mm/slab.h b/mm/slab.h
...
-   ali_spinlock_t list_lock;
+   spinlock_t list_lock;
...

diff --git a/mm/slab.c b/mm/slab.c
...
-   alispinlock(lock, &info);
+   spin_lock((spinlock_t *)lock);
+   fn(para);
+   spin_unlock((spinlock_t *)lock);
...

The above operations remove all performance noise from program modification.

We run  user space code thread.c with ali_work_queue.patch, and
org_spin_lock.patch respectively
 the output from thread.c as below:

ORG         NEW
38923684 43380604
38100464 44163011
37769241 43354266
37908638 43554022
37900994 43457066
38495073 43421394
37340217 43146352
38083979 43506951
37713263 43775215
37749871 43487289
37843224 43366055
38173823 43270225
38303612 43214675
37886717 44083950
37736455 43060728
37529307 44607597
38862690 43541484
37992824 44749925
38013454 43572225
37783135 45240502
37745372 44712540
38721413 43584658
38097842 43235392

            ORG            NEW
TOTAL 874675292 1005486126

So the data tell us the new mechanism can improve performance 14% (
1005486126/874675292) ,
and the operation can be justified fairly.

Thanks
Ling

2016-02-04 5:42 GMT+08:00 Waiman Long <waiman.long@hpe.com>:
> On 02/02/2016 11:40 PM, Ling Ma wrote:
>>
>> Longman,
>>
>> The attachment include user space code(thread.c), and kernel
>> patch(ali_work_queue.patch) based on 4.3.0-rc4,
>> we replaced all original spinlock (list_lock) in slab.h/c  with the
>> new mechanism.
>>
>> The thread.c in user space caused lots of hot kernel spinlock from
>> __kmalloc and kfree,
>> perf top -d1 shows ~25%  before ali_work_queue.patch,after appending
>> this patch ,
>> the synchronous operation consumption from __kmalloc and kfree is
>> reduced from 25% to ~15% on Intel E5-2699V3
>> (we also observed the output from user space code (thread.c) is
>> improved clearly)
>
>
> I have 2 major comments here. First of all, you should break up your patch
> into smaller ones. Large patch like the one in the tar ball is hard to
> review. Secondly, you are modifying over 1000 lines of code in mm/slab.c
> with some modest increase in performance. That can be hard to justify. Maybe
> you should find other use cases that involve less changes, but still have
> noticeable performance improvement. That will make it easier to be accepted.
>
> Cheers,
> Longman
>
>

[-- Attachment #2: ali_work_queue.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 10827 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-02-03 21:42                         ` Waiman Long
  2016-02-04  7:07                           ` Ling Ma
@ 2016-04-05  3:44                           ` Ling Ma
  2016-04-11  8:00                             ` Ling Ma
  1 sibling, 1 reply; 228+ messages in thread
From: Ling Ma @ 2016-04-05  3:44 UTC (permalink / raw)
  To: Waiman Long
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

[-- Attachment #1: Type: text/plain, Size: 916 bytes --]

Hi Longman,

> with some modest increase in performance. That can be hard to justify. Maybe
> you should find other use cases that involve less changes, but still have
> noticeable performance improvement. That will make it easier to be accepted.

The attachment is for other use case with the new lock optimization.
It include two files: main.c (user space workload),
fcntl-lock-opt.patch (kernel patch on 4.3.0-rc4 version)
(The hardware platform is on Intel E5 2699 V3, 72 threads (18core *2Socket *2HT)

1. when we run a.out from main.c on original 4.3.0-rc4 version,
the average throughput from a.out is 1887592( 98% cpu cost from perf top -d1)

2. when we run a.out from main.c with the fcntl-lock-opt.patch ,
the average throughput from a.out is 5277281 (91% cpu cost from perf top -d1)

So we say the new mechanism give us about 2.79x (5277281 / 1887592) improvement.

Appreciate your comments.

Thanks
Ling

[-- Attachment #2: test-lock.tar --]
[-- Type: application/x-tar, Size: 30720 bytes --]

^ permalink raw reply	[flat|nested] 228+ messages in thread

* Re: [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform
  2016-04-05  3:44                           ` Ling Ma
@ 2016-04-11  8:00                             ` Ling Ma
  0 siblings, 0 replies; 228+ messages in thread
From: Ling Ma @ 2016-04-11  8:00 UTC (permalink / raw)
  To: Waiman Long
  Cc: One Thousand Gnomes, Peter Zijlstra, mingo, linux-kernel, akpm, Ling

Is it acceptable for performance improvement or more comments on this patch?

Thanks
Ling

2016-04-05 11:44 GMT+08:00 Ling Ma <ling.ma.program@gmail.com>:
> Hi Longman,
>
>> with some modest increase in performance. That can be hard to justify. Maybe
>> you should find other use cases that involve less changes, but still have
>> noticeable performance improvement. That will make it easier to be accepted.
>
> The attachment is for other use case with the new lock optimization.
> It include two files: main.c (user space workload),
> fcntl-lock-opt.patch (kernel patch on 4.3.0-rc4 version)
> (The hardware platform is on Intel E5 2699 V3, 72 threads (18core *2Socket *2HT)
>
> 1. when we run a.out from main.c on original 4.3.0-rc4 version,
> the average throughput from a.out is 1887592( 98% cpu cost from perf top -d1)
>
> 2. when we run a.out from main.c with the fcntl-lock-opt.patch ,
> the average throughput from a.out is 5277281 (91% cpu cost from perf top -d1)
>
> So we say the new mechanism give us about 2.79x (5277281 / 1887592) improvement.
>
> Appreciate your comments.
>
> Thanks
> Ling

^ permalink raw reply	[flat|nested] 228+ messages in thread

end of thread, other threads:[~2016-04-11  8:00 UTC | newest]

Thread overview: 228+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <yes>
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
2009-01-16 18:08   ` [PATCH 01/11] quota: Improve locking Jan Kara
2009-01-16 18:08     ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
2009-01-16 18:08       ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
2009-01-16 18:08         ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
2009-01-16 18:08           ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
2009-01-16 18:08             ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
2009-01-16 18:08               ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
2009-01-16 18:08                 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
2009-01-16 18:08                   ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
2009-01-16 18:08                     ` [PATCH 10/11] ext4: " Jan Kara
2009-01-16 18:08                       ` [PATCH 11/11] reiserfs: " Jan Kara
2009-01-20 21:41                       ` [PATCH 10/11] ext4: " Mingming Cao
2009-01-20 21:41                     ` [PATCH 09/11] ext3: " Mingming Cao
2009-01-24  7:49     ` [PATCH 01/11] quota: Improve locking Andrew Morton
2009-01-26 10:04       ` Jan Kara
2009-05-31 14:49 ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS tom.leiming
2009-05-31 14:49   ` [PATCH 1/8] kernel:lockdep:improve implementation of BFS tom.leiming
2009-05-31 14:49     ` [PATCH 2/8] kernel:lockdep: introduce match function to BFS tom.leiming
2009-05-31 14:49       ` [PATCH 3/8] kernel:lockdep:implement check_noncircular() by BFS tom.leiming
2009-05-31 14:49         ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards " tom.leiming
2009-05-31 14:49           ` [PATCH 5/8] kernel:lockdep:introduce print_shortest_lock_dependencies tom.leiming
2009-05-31 14:49             ` [PATCH 6/8] kernel:lockdep: implement lockdep_count_*ward_deps by BFS tom.leiming
2009-05-31 14:49               ` [PATCH 7/8] kernel:lockdep: update memory usage introduced " tom.leiming
2009-05-31 14:49                 ` [PATCH 8/8] kernel:lockdep:add statistics info for max bfs queue depth tom.leiming
2009-05-31 15:14           ` [PATCH 4/8] kernel:lockdep:implement find_usage_*wards by BFS Daniel Walker
2009-06-01  0:14             ` Ming Lei
2009-06-08 12:22   ` [PATCH 0/8] kernel:lockdep:replace DFS with BFS Peter Zijlstra
2009-06-08 13:38     ` Ming Lei
2009-06-08 13:58     ` Ming Lei
2009-06-08 14:04       ` Peter Zijlstra
2009-06-08 15:50     ` Ming Lei
2009-06-09 12:52       ` Ming Lei
2009-10-07 13:49 ` [PATCH 1/1] perf tools: Up the verbose level for some really verbose stuff Arnaldo Carvalho de Melo
2009-10-08 17:31   ` [tip:perf/core] " tip-bot for Arnaldo Carvalho de Melo
2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
2010-06-22 21:37   ` Jeff Layton
2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
2010-06-22 21:52   ` Jeff Layton
2010-06-23  5:34     ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
2010-06-23 18:32   ` Scott Lovenberg
2010-06-25 10:48     ` Suresh Jayaraman
2010-06-23 16:51 ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
2010-06-25 10:56   ` Suresh Jayaraman
2010-06-23 16:54 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache David Howells
2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
2010-06-25 12:44   ` Suresh Jayaraman
2010-06-25 12:58   ` David Howells
2010-06-25 13:26   ` David Howells
2010-06-28 12:53     ` Suresh Jayaraman
2010-06-28 13:24     ` David Howells
2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
2010-06-25 12:50   ` Suresh Jayaraman
2010-06-25 12:55   ` David Howells
2010-06-25 16:53     ` Jeff Layton
2010-06-25 21:46     ` David Howells
2010-06-25 22:26       ` Jeff Layton
2010-06-25 23:05         ` Steve French
     [not found]           ` <OFB55E8EC7.E8DD23D5-ON8725774E.0004921E-8825774E.0004CC31@us.ibm.com>
2010-06-27 18:17             ` Aneesh Kumar K. V
2010-06-27 18:22               ` Christoph Hellwig
2010-06-25 23:04       ` David Howells
2010-06-23 17:05 ` [RFC][PATCH 07/10] cifs: FS-Cache page management David Howells
2010-06-23 17:06 ` [RFC][PATCH 08/10] cifs: store pages into local cache David Howells
2010-06-23 17:07 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache David Howells
2010-06-23 17:08 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching David Howells
2011-06-15  0:46 ` [PATCH] Add ok2440 development board support Wu DaoGuang
2011-10-03  0:32 ` [PATCH 1/1] ARM: Make debug UART optional for S3C devices Thiago A. Correa
2011-10-10 14:44   ` Thiago A. Corrêa
2011-12-11 13:10 ` [PATCH] block: Needn't read the size of device or partition again taco
2012-06-08 17:23 ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Joonsoo Kim
2012-06-08 17:23   ` [PATCH 2/4] slub: use __cmpxchg_double_slab() at interrupt disabled place Joonsoo Kim
2012-06-08 17:23   ` [PATCH 3/4] slub: refactoring unfreeze_partials() Joonsoo Kim
2012-06-20  7:19     ` Pekka Enberg
2012-06-08 17:23   ` [PATCH 4/4] slub: deactivate freelist of kmem_cache_cpu all at once in deactivate_slab() Joonsoo Kim
2012-06-08 19:04     ` Christoph Lameter
2012-06-10 10:27       ` JoonSoo Kim
2012-06-22 18:34         ` JoonSoo Kim
2012-06-08 19:02   ` [PATCH 1/4] slub: change declare of get_slab() to inline at all times Christoph Lameter
2012-06-09 15:57     ` JoonSoo Kim
2012-06-11 15:04       ` Christoph Lameter
2012-06-22 18:22 ` [PATCH 1/3] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
2012-06-22 18:22   ` [PATCH 2/3] slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing Joonsoo Kim
2012-07-04 13:05     ` Pekka Enberg
2012-07-05 14:20       ` Christoph Lameter
2012-08-16  7:06     ` Pekka Enberg
2012-06-22 18:22   ` [PATCH 3/3] slub: release a lock if freeing object with a lock is failed in __slab_free() Joonsoo Kim
2012-07-04 13:10     ` Pekka Enberg
2012-07-04 14:48       ` JoonSoo Kim
2012-07-05 14:26     ` Christoph Lameter
2012-07-06 14:19       ` JoonSoo Kim
2012-07-06 14:34         ` Christoph Lameter
2012-07-06 14:59           ` JoonSoo Kim
2012-07-06 15:10             ` Christoph Lameter
2012-07-08 16:19               ` JoonSoo Kim
2012-06-22 18:45   ` [PATCH 1/3 v2] slub: prefetch next freelist pointer in __slab_alloc() Joonsoo Kim
2012-07-04 12:58     ` JoonSoo Kim
2012-07-04 13:00     ` Pekka Enberg
2012-07-04 14:30       ` JoonSoo Kim
2012-07-04 15:08         ` Pekka Enberg
2012-07-04 15:26           ` Eric Dumazet
2012-07-04 15:48             ` JoonSoo Kim
2012-07-04 16:15               ` Eric Dumazet
2012-07-04 16:24                 ` JoonSoo Kim
2012-07-04 15:45           ` JoonSoo Kim
2012-07-04 15:59             ` Pekka Enberg
2012-07-04 16:04               ` JoonSoo Kim
     [not found] ` <1360258447-27247-1-git-send-email-yes>
2013-02-07 17:34   ` [PATCH 04/10] USB: EHCI: make ehci-orion a separate driver manjunath.goudar
2013-02-07 19:41     ` Arnd Bergmann
2013-02-08 10:38     ` Florian Fainelli
2013-02-07 17:34   ` [PATCH 05/10] USB: EHCI: make ehci-atmel " manjunath.goudar
2013-02-08  2:58     ` Bo Shen
2013-06-12 11:53     ` Jean-Christophe PLAGNIOL-VILLARD
2013-02-07 17:34   ` [PATCH 07/10] USB: EHCI: make ehci-mv " manjunath.goudar
2013-02-07 17:34   ` [PATCH 08/10] USB: EHCI: make ehci-vt8500 " manjunath.goudar
2013-02-07 18:54     ` Tony Prisk
2013-02-07 17:34   ` [PATCH 09/10] USB: EHCI: make ehci-msm " manjunath.goudar
2013-02-07 18:48     ` Stephen Warren
2013-02-07 19:05     ` David Brown
2013-02-07 17:34   ` [PATCH 10/10] USB: EHCI: make ehci-w90X900 " manjunath.goudar
2013-06-10  9:17 ` [PATCH v2 00/11] ARM:STixxxx: Add STixxxx platform and board support Srinivas KANDAGATLA
2013-06-10  9:21   ` [PATCH v2 01/11] serial:st-asc: Add ST ASC driver Srinivas KANDAGATLA
2013-06-10  9:35     ` Russell King - ARM Linux
2013-06-10 11:53       ` Srinivas KANDAGATLA
2013-06-10  9:21   ` [PATCH v2 02/11] clocksource:global_timer: Add ARM global timer support Srinivas KANDAGATLA
     [not found]     ` <CACRpkdbQCRKBzRF4HzNsXHwXCLJJcFZ9T36GPmmYsnX1OfgGRg@mail.gmail.com>
     [not found]       ` <51B5D7A6.1020101@st.com>
     [not found]         ` <51B72E9A.6070006@st.com>
     [not found]           ` <CACRpkdbppRqnMYknbBy8JpAVtujMOEQvyczXTmpvkQuxgikFog@mail.gmail.com>
2013-06-12 10:45             ` Srinivas KANDAGATLA
2013-06-10  9:21   ` [PATCH v2 03/11] regmap: Add regmap_field APIs Srinivas KANDAGATLA
2013-06-11 10:48     ` Mark Brown
2013-06-11 11:36       ` Srinivas KANDAGATLA
2013-06-10  9:22   ` [PATCH v2 04/11] mfd:stixxxx-syscfg: Add ST System Configuration support Srinivas KANDAGATLA
     [not found]     ` <CACRpkdaW2ALTWCB7Rd8m=aAGQwh3T_dJVncxJn_eXer4X3J6_g@mail.gmail.com>
2013-06-10 13:52       ` Srinivas KANDAGATLA
2013-06-10 14:02         ` Arnd Bergmann
2013-06-10 15:51           ` Srinivas KANDAGATLA
2013-06-11  7:41           ` Srinivas KANDAGATLA
2013-06-10  9:22   ` [PATCH v2 05/11] pinctrl:stixxxx: Add pinctrl and pinconf support Srinivas KANDAGATLA
2013-06-10  9:26   ` =?yes?q?=5BPATCH=20v2=2006/11=5D=20ARM=3Astixxxx=3A=20Add=20STiH415=20SOC=20support?= Srinivas KANDAGATLA
2013-06-10  9:55     ` [PATCH v2 06/11] ARM:stixxxx: Add STiH415 SOC support Michal Simek
2013-06-10 11:08     ` Michal Simek
     [not found]     ` <CAHTX3d+dk3W_9b7SVUokWq4KYXnj=Z1=WPj5zJ-gUvJqqwE=+Q@mail.gmail.com>
2013-06-10 11:46       ` Srinivas KANDAGATLA
2013-06-10 23:19         ` Russell King - ARM Linux
2013-06-11  6:50           ` Srinivas KANDAGATLA
2013-06-13 11:56             ` Russell King - ARM Linux
2013-06-13 12:41               ` Srinivas KANDAGATLA
2013-06-13 12:47           ` Linus Walleij
2013-06-10  9:27   ` [PATCH v2 07/11] ARM:stixxxx: Add STiH416 " Srinivas KANDAGATLA
2013-06-10 13:52     ` Arnd Bergmann
2013-06-10 16:17       ` Srinivas KANDAGATLA
2013-06-14  7:12       ` Srinivas KANDAGATLA
2013-06-10  9:27   ` [PATCH v2 08/11] ARM:stixxxx: Add DEBUG_LL console support Srinivas KANDAGATLA
2013-06-10  9:27   ` [PATCH v2 09/11] ARM:stixxxx: Add stixxxx options to multi_v7_defconfig Srinivas KANDAGATLA
2013-06-10 10:40     ` Mark Rutland
2013-06-10 10:58       ` Srinivas KANDAGATLA
2013-06-10 13:15         ` Mark Rutland
2013-06-13  9:24           ` Srinivas KANDAGATLA
2013-06-17  9:32             ` Mark Rutland
2013-06-10  9:28   ` [PATCH v2 10/11] ARM:stih41x: Add B2000 board support Srinivas KANDAGATLA
2013-06-10  9:28   ` [PATCH v2 11/11] ARM:stih41x: Add B2020 " Srinivas KANDAGATLA
2014-08-12  6:40 ` [PATCH v3] uas: replace WARN_ON_ONCE() with lockdep_assert_held() Sanjeev Sharma
2014-08-12  6:28   ` Hans de Goede
2014-08-12  6:37     ` Sharma, Sanjeev
2014-08-19  6:33     ` Sharma, Sanjeev
2014-08-19  9:30       ` gregkh
2014-08-19  9:38         ` Sharma, Sanjeev
2014-09-04  7:06         ` Sharma, Sanjeev
2014-09-04 13:50 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c linux.delve
2014-09-04 13:51   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool linux.delve
2014-09-04 14:09 ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Chaitra Ramaiah
2014-09-04 14:09   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c This is a patch to the file r819xU_firmware.c that fixes a brace warning found by checkpatch.pl tool Chaitra Ramaiah
2014-09-04 14:28     ` Greg KH
2014-09-04 14:33     ` Dan Carpenter
2014-09-04 14:27   ` [PATCH] Staging: rtl8192u: fix brace style coding issue in r819xU_firmware.c Greg KH
2014-10-29 20:28 ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs Murali Karicheri
2014-10-29 20:28   ` [PATCH v2 1/4] ARM: keystone: add pcie related options Murali Karicheri
2014-10-29 20:28   ` [PATCH v2 2/4] ARM: keystone: defconfig: add options to enable PCI controller Murali Karicheri
2014-10-29 20:28   ` [PATCH v2 3/4] ARM: dts: keystone: add DT bindings for PCI controller for port 0 Murali Karicheri
2014-10-29 20:28   ` [PATCH v2 4/4] ARM: dts: keystone-k2e: add DT bindings for PCI controller for port 1 Murali Karicheri
2014-10-29 21:10   ` [PATCH v2 0/4] Enable PCI controller for Keystone SoCs santosh shilimkar
2015-10-19  2:27 ` [RFC PATCH] qspinlock: Improve performance by reducing load instruction rollback ling.ma.program
2015-10-19  7:58   ` Ingo Molnar
2015-10-19  9:34     ` Peter Zijlstra
2015-10-19 11:24       ` Ingo Molnar
2015-10-19 17:24         ` Waiman Long
2015-10-20  2:57     ` Ling Ma
2015-10-20  8:48       ` Ingo Molnar
2015-10-21  5:28         ` Ling Ma
2015-10-21  7:54           ` Peter Zijlstra
2015-10-20  9:15       ` Peter Zijlstra
2015-10-19  9:33   ` Peter Zijlstra
2015-10-19 17:20     ` Waiman Long
2015-10-20  3:00     ` Ling Ma
2015-10-19  9:46   ` Peter Zijlstra
2015-10-20  3:03     ` Ling Ma
2015-10-20  3:24     ` Ling Ma
2015-10-20  9:16       ` Peter Zijlstra
2015-10-21  5:30         ` Ling Ma
2015-10-19 17:18   ` Waiman Long
2015-10-20  3:12     ` Ling Ma
2015-10-20 18:55       ` Waiman Long
2015-10-21  5:43         ` Ling Ma
2015-12-31  8:09 ` [RFC PATCH] alispinlock: acceleration from lock integration on multi-core platform ling.ma.program
2016-01-05 18:46   ` Waiman Long
2016-01-08 22:48     ` Ling Ma
2016-01-05 21:18   ` Peter Zijlstra
2016-01-05 21:42     ` One Thousand Gnomes
2016-01-06  8:16       ` Peter Zijlstra
2016-01-06  8:21         ` Peter Zijlstra
2016-01-06 11:24           ` One Thousand Gnomes
2016-01-08 22:44             ` Ling Ma
2016-01-12 13:50               ` One Thousand Gnomes
2016-01-14  8:10                 ` Ling Ma
2016-01-19  8:52                   ` Ling Ma
2016-01-19 15:36                     ` Waiman Long
2016-02-03  4:40                       ` Ling Ma
2016-02-03  6:00                         ` Ling Ma
2016-02-03 21:42                         ` Waiman Long
2016-02-04  7:07                           ` Ling Ma
2016-04-05  3:44                           ` Ling Ma
2016-04-11  8:00                             ` Ling Ma
2016-01-08 23:01       ` Ling Ma
2016-01-08 22:56     ` Ling Ma

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).