irqchip/gic-v3-its: Fix misuse of GENMASK macro
[linux-2.6-block.git] / drivers / irqchip / irq-gic-v3-its.c
index cfb9b4e5f91450e18b507e30a1ae6c14010ebfb8..730fbe0e2a9dfa788b3698cbdcb10b682fe22888 100644 (file)
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2013-2017 ARM Limited, All Rights Reserved.
  * Author: Marc Zyngier <marc.zyngier@arm.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/acpi.h>
@@ -196,7 +185,7 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
 
 static struct its_collection *valid_col(struct its_collection *col)
 {
-       if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15)))
+       if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(15, 0)))
                return NULL;
 
        return col;
@@ -744,32 +733,43 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
 }
 
 static int its_wait_for_range_completion(struct its_node *its,
-                                        struct its_cmd_block *from,
+                                        u64    prev_idx,
                                         struct its_cmd_block *to)
 {
-       u64 rd_idx, from_idx, to_idx;
+       u64 rd_idx, to_idx, linear_idx;
        u32 count = 1000000;    /* 1s! */
 
-       from_idx = its_cmd_ptr_to_offset(its, from);
+       /* Linearize to_idx if the command set has wrapped around */
        to_idx = its_cmd_ptr_to_offset(its, to);
+       if (to_idx < prev_idx)
+               to_idx += ITS_CMD_QUEUE_SZ;
+
+       linear_idx = prev_idx;
 
        while (1) {
+               s64 delta;
+
                rd_idx = readl_relaxed(its->base + GITS_CREADR);
 
-               /* Direct case */
-               if (from_idx < to_idx && rd_idx >= to_idx)
-                       break;
+               /*
+                * Compute the read pointer progress, taking the
+                * potential wrap-around into account.
+                */
+               delta = rd_idx - prev_idx;
+               if (rd_idx < prev_idx)
+                       delta += ITS_CMD_QUEUE_SZ;
 
-               /* Wrapped case */
-               if (from_idx >= to_idx && rd_idx >= to_idx && rd_idx < from_idx)
+               linear_idx += delta;
+               if (linear_idx >= to_idx)
                        break;
 
                count--;
                if (!count) {
-                       pr_err_ratelimited("ITS queue timeout (%llu %llu %llu)\n",
-                                          from_idx, to_idx, rd_idx);
+                       pr_err_ratelimited("ITS queue timeout (%llu %llu)\n",
+                                          to_idx, linear_idx);
                        return -1;
                }
+               prev_idx = rd_idx;
                cpu_relax();
                udelay(1);
        }
@@ -786,6 +786,7 @@ void name(struct its_node *its,                                             \
        struct its_cmd_block *cmd, *sync_cmd, *next_cmd;                \
        synctype *sync_obj;                                             \
        unsigned long flags;                                            \
+       u64 rd_idx;                                                     \
                                                                        \
        raw_spin_lock_irqsave(&its->lock, flags);                       \
                                                                        \
@@ -807,10 +808,11 @@ void name(struct its_node *its,                                           \
        }                                                               \
                                                                        \
 post:                                                                  \
+       rd_idx = readl_relaxed(its->base + GITS_CREADR);                \
        next_cmd = its_post_commands(its);                              \
        raw_spin_unlock_irqrestore(&its->lock, flags);                  \
                                                                        \
-       if (its_wait_for_range_completion(its, cmd, next_cmd))          \
+       if (its_wait_for_range_completion(its, rd_idx, next_cmd))       \
                pr_err_ratelimited("ITS cmd %ps failed\n", builder);    \
 }