print_circular_bug_entry(entry, depth);
 }
 
-static inline bool class_equal(struct lock_list *entry, void *data)
+/*
+ * We are about to add A -> B into the dependency graph, and in __bfs() a
+ * strong dependency path A -> .. -> B is found: hlock_class equals
+ * entry->class.
+ *
+ * If A -> .. -> B can replace A -> B in any __bfs() search (means the former
+ * is _stronger_ than or equal to the latter), we consider A -> B as redundant.
+ * For example if A -> .. -> B is -(EN)-> (i.e. A -(E*)-> .. -(*N)-> B), and A
+ * -> B is -(ER)-> or -(EN)->, then we don't need to add A -> B into the
+ * dependency graph, as any strong path ..-> A -> B ->.. we can get with
+ * having dependency A -> B, we could already get a equivalent path ..-> A ->
+ * .. -> B -> .. with A -> .. -> B. Therefore A -> B is reduntant.
+ *
+ * We need to make sure both the start and the end of A -> .. -> B is not
+ * weaker than A -> B. For the start part, please see the comment in
+ * check_redundant(). For the end part, we need:
+ *
+ * Either
+ *
+ *     a) A -> B is -(*R)-> (everything is not weaker than that)
+ *
+ * or
+ *
+ *     b) A -> .. -> B is -(*N)-> (nothing is stronger than this)
+ *
+ */
+static inline bool hlock_equal(struct lock_list *entry, void *data)
 {
-       return entry->class == data;
+       struct held_lock *hlock = (struct held_lock *)data;
+
+       return hlock_class(hlock) == entry->class && /* Found A -> .. -> B */
+              (hlock->read == 2 ||  /* A -> B is -(*R)-> */
+               !entry->only_xr); /* A -> .. -> B is -(*N)-> */
 }
 
 /*
        struct lock_list src_entry;
 
        bfs_init_root(&src_entry, src);
+       /*
+        * Special setup for check_redundant().
+        *
+        * To report redundant, we need to find a strong dependency path that
+        * is equal to or stronger than <src> -> <target>. So if <src> is E,
+        * we need to let __bfs() only search for a path starting at a -(E*)->,
+        * we achieve this by setting the initial node's ->only_xr to true in
+        * that case. And if <prev> is S, we set initial ->only_xr to false
+        * because both -(S*)-> (equal) and -(E*)-> (stronger) are redundant.
+        */
+       src_entry.only_xr = src->read == 0;
 
        debug_atomic_inc(nr_redundant_checks);
 
-       ret = check_path(target, &src_entry, class_equal, &target_entry);
+       ret = check_path(target, &src_entry, hlock_equal, &target_entry);
 
        if (ret == BFS_RMATCH)
                debug_atomic_inc(nr_redundant);