Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] clocksource: timer-dm: Make unexported functions static
From: Ladislav Michl @ 2018-01-08 15:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153926.GA3916@lenoch>

As dmtimer no longer exports functions, make those previously
exported static.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>

diff --git a/drivers/clocksource/timer-dm.c b/drivers/clocksource/timer-dm.c
index 60db1734ea3b..43531eecbe54 100644
--- a/drivers/clocksource/timer-dm.c
+++ b/drivers/clocksource/timer-dm.c
@@ -163,6 +163,92 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
 	return ret;
 }
 
+static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+{
+	int ret;
+	char *parent_name = NULL;
+	struct clk *parent;
+	struct dmtimer_platform_data *pdata;
+
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	pdata = timer->pdev->dev.platform_data;
+
+	if (source < 0 || source >= 3)
+		return -EINVAL;
+
+	/*
+	 * FIXME: Used for OMAP1 devices only because they do not currently
+	 * use the clock framework to set the parent clock. To be removed
+	 * once OMAP1 migrated to using clock framework for dmtimers
+	 */
+	if (pdata && pdata->set_timer_src)
+		return pdata->set_timer_src(timer->pdev, source);
+
+	if (IS_ERR(timer->fclk))
+		return -EINVAL;
+
+#if defined(CONFIG_COMMON_CLK)
+	/* Check if the clock has configurable parents */
+	if (clk_hw_get_num_parents(__clk_get_hw(timer->fclk)) < 2)
+		return 0;
+#endif
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		parent_name = "timer_sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		parent_name = "timer_32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		parent_name = "timer_ext_ck";
+		break;
+	}
+
+	parent = clk_get(&timer->pdev->dev, parent_name);
+	if (IS_ERR(parent)) {
+		pr_err("%s: %s not found\n", __func__, parent_name);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(timer->fclk, parent);
+	if (ret < 0)
+		pr_err("%s: failed to set %s as parent\n", __func__,
+			parent_name);
+
+	clk_put(parent);
+
+	return ret;
+}
+
+static void omap_dm_timer_enable(struct omap_dm_timer *timer)
+{
+	int c;
+
+	pm_runtime_get_sync(&timer->pdev->dev);
+
+	if (!(timer->capability & OMAP_TIMER_ALWON)) {
+		if (timer->get_context_loss_count) {
+			c = timer->get_context_loss_count(&timer->pdev->dev);
+			if (c != timer->ctx_loss_count) {
+				omap_timer_restore_context(timer);
+				timer->ctx_loss_count = c;
+			}
+		} else {
+			omap_timer_restore_context(timer);
+		}
+	}
+}
+
+static void omap_dm_timer_disable(struct omap_dm_timer *timer)
+{
+	pm_runtime_put_sync(&timer->pdev->dev);
+}
+
 static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
 	int rc;
@@ -298,16 +384,16 @@ static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)
 	return timer;
 }
 
-struct omap_dm_timer *omap_dm_timer_request(void)
+static struct omap_dm_timer *omap_dm_timer_request(void)
 {
 	return _omap_dm_timer_request(REQUEST_ANY, NULL);
 }
 
-struct omap_dm_timer *omap_dm_timer_request_specific(int id)
+static struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
 	/* Requesting timer by ID is not supported when device tree is used */
 	if (of_have_populated_dt()) {
-		pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n",
+		pr_warn("%s: Please use omap_dm_timer_request_by_node()\n",
 			__func__);
 		return NULL;
 	}
@@ -336,7 +422,7 @@ struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
  * Request a timer based upon a device node pointer. Returns pointer to
  * timer handle on success and a NULL pointer on failure.
  */
-struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
+static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
 {
 	if (!np)
 		return NULL;
@@ -344,7 +430,7 @@ struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
 	return _omap_dm_timer_request(REQUEST_BY_NODE, np);
 }
 
-int omap_dm_timer_free(struct omap_dm_timer *timer)
+static int omap_dm_timer_free(struct omap_dm_timer *timer)
 {
 	if (unlikely(!timer))
 		return -EINVAL;
@@ -356,30 +442,6 @@ int omap_dm_timer_free(struct omap_dm_timer *timer)
 	return 0;
 }
 
-void omap_dm_timer_enable(struct omap_dm_timer *timer)
-{
-	int c;
-
-	pm_runtime_get_sync(&timer->pdev->dev);
-
-	if (!(timer->capability & OMAP_TIMER_ALWON)) {
-		if (timer->get_context_loss_count) {
-			c = timer->get_context_loss_count(&timer->pdev->dev);
-			if (c != timer->ctx_loss_count) {
-				omap_timer_restore_context(timer);
-				timer->ctx_loss_count = c;
-			}
-		} else {
-			omap_timer_restore_context(timer);
-		}
-	}
-}
-
-void omap_dm_timer_disable(struct omap_dm_timer *timer)
-{
-	pm_runtime_put_sync(&timer->pdev->dev);
-}
-
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
 	if (timer)
@@ -424,7 +486,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 
 #else
 
-struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
+static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
 	if (timer && !IS_ERR(timer->fclk))
 		return timer->fclk;
@@ -451,7 +513,7 @@ int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 	return 0;
 }
 
-int omap_dm_timer_start(struct omap_dm_timer *timer)
+static int omap_dm_timer_start(struct omap_dm_timer *timer)
 {
 	u32 l;
 
@@ -471,7 +533,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
 	return 0;
 }
 
-int omap_dm_timer_stop(struct omap_dm_timer *timer)
+static int omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
 	unsigned long rate = 0;
 
@@ -494,70 +556,8 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
 	return 0;
 }
 
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
-	int ret;
-	char *parent_name = NULL;
-	struct clk *parent;
-	struct dmtimer_platform_data *pdata;
-
-	if (unlikely(!timer))
-		return -EINVAL;
-
-	pdata = timer->pdev->dev.platform_data;
-
-	if (source < 0 || source >= 3)
-		return -EINVAL;
-
-	/*
-	 * FIXME: Used for OMAP1 devices only because they do not currently
-	 * use the clock framework to set the parent clock. To be removed
-	 * once OMAP1 migrated to using clock framework for dmtimers
-	 */
-	if (pdata && pdata->set_timer_src)
-		return pdata->set_timer_src(timer->pdev, source);
-
-	if (IS_ERR(timer->fclk))
-		return -EINVAL;
-
-#if defined(CONFIG_COMMON_CLK)
-	/* Check if the clock has configurable parents */
-	if (clk_hw_get_num_parents(__clk_get_hw(timer->fclk)) < 2)
-		return 0;
-#endif
-
-	switch (source) {
-	case OMAP_TIMER_SRC_SYS_CLK:
-		parent_name = "timer_sys_ck";
-		break;
-
-	case OMAP_TIMER_SRC_32_KHZ:
-		parent_name = "timer_32k_ck";
-		break;
-
-	case OMAP_TIMER_SRC_EXT_CLK:
-		parent_name = "timer_ext_ck";
-		break;
-	}
-
-	parent = clk_get(&timer->pdev->dev, parent_name);
-	if (IS_ERR(parent)) {
-		pr_err("%s: %s not found\n", __func__, parent_name);
-		return -EINVAL;
-	}
-
-	ret = clk_set_parent(timer->fclk, parent);
-	if (ret < 0)
-		pr_err("%s: failed to set %s as parent\n", __func__,
-			parent_name);
-
-	clk_put(parent);
-
-	return ret;
-}
-
-int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
-			    unsigned int load)
+static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+				  unsigned int load)
 {
 	u32 l;
 
@@ -582,8 +582,8 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 }
 
 /* Optimized set_load which removes costly spin wait in timer_start */
-int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
-                            unsigned int load)
+static int omap_dm_timer_set_load_start(struct omap_dm_timer *timer,
+					int autoreload, unsigned int load)
 {
 	u32 l;
 
@@ -609,9 +609,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	timer->context.tcrr = load;
 	return 0;
 }
-
-int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
-			     unsigned int match)
+static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+				   unsigned int match)
 {
 	u32 l;
 
@@ -634,8 +633,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 	return 0;
 }
 
-int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
-			   int toggle, int trigger)
+static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+				 int toggle, int trigger)
 {
 	u32 l;
 
@@ -659,7 +658,8 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 	return 0;
 }
 
-int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
+					int prescaler)
 {
 	u32 l;
 
@@ -681,8 +681,8 @@ int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 	return 0;
 }
 
-int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
-				  unsigned int value)
+static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+					unsigned int value)
 {
 	if (unlikely(!timer))
 		return -EINVAL;
@@ -704,7 +704,7 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
  *
  * Disables the specified timer interrupts for a timer.
  */
-int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
+static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 {
 	u32 l = mask;
 
@@ -727,7 +727,7 @@ int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 	return 0;
 }
 
-unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
+static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
 	unsigned int l;
 
@@ -741,7 +741,7 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 	return l;
 }
 
-int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
 	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
 		return -EINVAL;
@@ -751,7 +751,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 	return 0;
 }
 
-unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
+static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
 	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 		pr_err("%s: timer not iavailable or enabled.\n", __func__);
@@ -761,7 +761,7 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 	return __omap_dm_timer_read_counter(timer, timer->posted);
 }
 
-int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
 	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 		pr_err("%s: timer not available or enabled.\n", __func__);
diff --git a/include/clocksource/dmtimer.h b/include/clocksource/dmtimer.h
index 862ad62dab9d..ce596172a93a 100644
--- a/include/clocksource/dmtimer.h
+++ b/include/clocksource/dmtimer.h
@@ -125,37 +125,13 @@ struct omap_dm_timer {
 };
 
 int omap_dm_timer_reserve_systimer(int id);
-struct omap_dm_timer *omap_dm_timer_request(void);
-struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
-struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np);
-int omap_dm_timer_free(struct omap_dm_timer *timer);
-void omap_dm_timer_enable(struct omap_dm_timer *timer);
-void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
 
 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
-struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
 
 int omap_dm_timer_trigger(struct omap_dm_timer *timer);
-int omap_dm_timer_start(struct omap_dm_timer *timer);
-int omap_dm_timer_stop(struct omap_dm_timer *timer);
-
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
-
-int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
-int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask);
-
-unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
-unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
 
 int omap_dm_timers_active(void);
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH 2/5] clocksource: timer-dm: Check prescaler value
From: Ladislav Michl @ 2018-01-08 15:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153926.GA3916@lenoch>

Invalid value silently disables use of the prescaler.
Use -1 explicitely for that purpose and error out on
invalid value.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>

diff --git a/drivers/clocksource/timer-dm.c b/drivers/clocksource/timer-dm.c
index 43531eecbe54..bde1014308f9 100644
--- a/drivers/clocksource/timer-dm.c
+++ b/drivers/clocksource/timer-dm.c
@@ -663,13 +663,13 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
 {
 	u32 l;
 
-	if (unlikely(!timer))
+	if (unlikely(!timer) || prescaler < -1 || prescaler > 7)
 		return -EINVAL;
 
 	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
-	if (prescaler >= 0x00 && prescaler <= 0x07) {
+	if (prescaler >= 0) {
 		l |= OMAP_TIMER_CTRL_PRE;
 		l |= prescaler << 2;
 	}
-- 
2.15.1

^ permalink raw reply related

* [PATCH 3/5] pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
From: Ladislav Michl @ 2018-01-08 15:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153926.GA3916@lenoch>

Prescaler setting is currently not taken into account.
Fix that by introducing freq member variable and initialize
it at device probe time. This also avoids frequency
recomputing at each pwm configure time.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>

diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 3b27aff585b7..ee1cd92b1744 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -40,6 +40,7 @@ struct pwm_omap_dmtimer_chip {
 	pwm_omap_dmtimer *dm_timer;
 	struct omap_dm_timer_ops *pdata;
 	struct platform_device *dm_timer_pdev;
+	unsigned long freq;
 };
 
 static inline struct pwm_omap_dmtimer_chip *
@@ -48,9 +49,10 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip *chip)
 	return container_of(chip, struct pwm_omap_dmtimer_chip, chip);
 }
 
-static u32 pwm_omap_dmtimer_get_clock_cycles(unsigned long clk_rate, int ns)
+static inline u32
+pwm_omap_dmtimer_get_clock_cycles(struct pwm_omap_dmtimer_chip *omap, int ns)
 {
-	return DIV_ROUND_CLOSEST_ULL((u64)clk_rate * ns, NSEC_PER_SEC);
+	return DIV_ROUND_CLOSEST_ULL((u64)omap->freq * ns, NSEC_PER_SEC);
 }
 
 static void pwm_omap_dmtimer_start(struct pwm_omap_dmtimer_chip *omap)
@@ -99,8 +101,6 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
 	struct pwm_omap_dmtimer_chip *omap = to_pwm_omap_dmtimer_chip(chip);
 	u32 period_cycles, duty_cycles;
 	u32 load_value, match_value;
-	struct clk *fclk;
-	unsigned long clk_rate;
 	bool timer_active;
 
 	dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n",
@@ -114,19 +114,6 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
 		return 0;
 	}
 
-	fclk = omap->pdata->get_fclk(omap->dm_timer);
-	if (!fclk) {
-		dev_err(chip->dev, "invalid pmtimer fclk\n");
-		goto err_einval;
-	}
-
-	clk_rate = clk_get_rate(fclk);
-	if (!clk_rate) {
-		dev_err(chip->dev, "invalid pmtimer fclk rate\n");
-		goto err_einval;
-	}
-
-	dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate);
 
 	/*
 	 * Calculate the appropriate load and match values based on the
@@ -144,35 +131,35 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
 	 *   OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11
 	 *   AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6
 	 */
-	period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns);
-	duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns);
+	period_cycles = pwm_omap_dmtimer_get_clock_cycles(omap, period_ns);
+	duty_cycles = pwm_omap_dmtimer_get_clock_cycles(omap, duty_ns);
 
 	if (period_cycles < 2) {
 		dev_info(chip->dev,
 			 "period %d ns too short for clock rate %lu Hz\n",
-			 period_ns, clk_rate);
+			 period_ns, omap->freq);
 		goto err_einval;
 	}
 
 	if (duty_cycles < 1) {
 		dev_dbg(chip->dev,
 			"duty cycle %d ns is too short for clock rate %lu Hz\n",
-			duty_ns, clk_rate);
+			duty_ns, omap->freq);
 		dev_dbg(chip->dev, "using minimum of 1 clock cycle\n");
 		duty_cycles = 1;
 	} else if (duty_cycles >= period_cycles) {
 		dev_dbg(chip->dev,
 			"duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n",
-			duty_ns, period_ns, clk_rate);
+			duty_ns, period_ns, omap->freq);
 		dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n");
 		duty_cycles = period_cycles - 1;
 	}
 
 	dev_dbg(chip->dev, "effective duty cycle: %lld ns, period: %lld ns\n",
 		DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * duty_cycles,
-				      clk_rate),
+				      omap->freq),
 		DIV_ROUND_CLOSEST_ULL((u64)NSEC_PER_SEC * period_cycles,
-				      clk_rate));
+				      omap->freq));
 
 	load_value = (DM_TIMER_MAX - period_cycles) + 1;
 	match_value = load_value + duty_cycles - 1;
@@ -248,6 +235,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	struct dmtimer_platform_data *timer_pdata;
 	struct omap_dm_timer_ops *pdata;
 	pwm_omap_dmtimer *dm_timer;
+	struct clk *fclk;
 	u32 v;
 	int status;
 
@@ -311,12 +299,37 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 		omap->pdata->stop(omap->dm_timer);
 
-	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
-		omap->pdata->set_prescaler(omap->dm_timer, v);
-
 	/* setup dmtimer clock source */
-	if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
-		omap->pdata->set_source(omap->dm_timer, v);
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v)) {
+		status = omap->pdata->set_source(omap->dm_timer, v);
+		if (status) {
+			dev_err(&pdev->dev, "invalid clock-source\n");
+			return status;
+		}
+	}
+
+	fclk = omap->pdata->get_fclk(omap->dm_timer);
+	if (!fclk) {
+		dev_err(&pdev->dev, "invalid fclk\n");
+		return -EINVAL;
+	}
+
+	omap->freq = clk_get_rate(fclk);
+	if (!omap->freq) {
+		dev_err(&pdev->dev, "invalid fclk rate\n");
+		return -EINVAL;
+	}
+
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v)) {
+		status = omap->pdata->set_prescaler(omap->dm_timer, v);
+		if (status) {
+			dev_err(&pdev->dev, "invalid prescaler\n");
+			return status;
+		}
+		omap->freq >>= v + 1;
+	}
+
+	dev_dbg(&pdev->dev, "clk rate: %luHz\n", omap->freq);
 
 	omap->chip.dev = &pdev->dev;
 	omap->chip.ops = &pwm_omap_dmtimer_ops;
-- 
2.15.1

^ permalink raw reply related

* [PATCH 4/5] clocksource: timer-dm: Add event capture
From: Ladislav Michl @ 2018-01-08 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153926.GA3916@lenoch>

Implement event capture functions.

Signed-off-by: Ladislav Michl <ladis@linux-mips.org>

diff --git a/drivers/clocksource/timer-dm.c b/drivers/clocksource/timer-dm.c
index bde1014308f9..dbf2b1f6a941 100644
--- a/drivers/clocksource/timer-dm.c
+++ b/drivers/clocksource/timer-dm.c
@@ -633,6 +633,30 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 	return 0;
 }
 
+static int omap_dm_timer_set_capture(struct omap_dm_timer *timer,
+				     int captmode, int edges)
+{
+	u32 l;
+
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+	l &= ~(OMAP_TIMER_CTRL_CAPTMODE | OMAP_TIMER_CTRL_SCPWM |
+	       OMAP_TIMER_CTRL_PT | OMAP_TIMER_CTRL_TCM_BOTHEDGES);
+	l |= OMAP_TIMER_CTRL_GPOCFG;
+	if (captmode)
+		l |= OMAP_TIMER_CTRL_CAPTMODE;
+	l |= edges << 8;
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
+}
+
 static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 				 int toggle, int trigger)
 {
@@ -791,6 +815,22 @@ int omap_dm_timers_active(void)
 	return 0;
 }
 
+static int omap_dm_timer_read_capture(struct omap_dm_timer *timer,
+					unsigned int *reg,
+					unsigned int *reg2)
+{
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
+	*reg = omap_dm_timer_read_reg(timer, OMAP_TIMER_CAPTURE_REG);
+	if (reg2)
+		*reg2 = omap_dm_timer_read_reg(timer, OMAP_TIMER_CAPTURE2_REG);
+
+	return 0;
+}
+
 static const struct of_device_id omap_timer_match[];
 
 /**
@@ -939,11 +979,14 @@ static struct omap_dm_timer_ops dmtimer_ops = {
 	.start = omap_dm_timer_start,
 	.stop = omap_dm_timer_stop,
 	.set_load = omap_dm_timer_set_load,
+	.set_load_start = omap_dm_timer_set_load_start,
 	.set_match = omap_dm_timer_set_match,
+	.set_capture = omap_dm_timer_set_capture,
 	.set_pwm = omap_dm_timer_set_pwm,
 	.set_prescaler = omap_dm_timer_set_prescaler,
 	.read_counter = omap_dm_timer_read_counter,
 	.write_counter = omap_dm_timer_write_counter,
+	.read_capture = omap_dm_timer_read_capture,
 	.read_status = omap_dm_timer_read_status,
 	.write_status = omap_dm_timer_write_status,
 };
diff --git a/include/linux/platform_data/dmtimer-omap.h b/include/linux/platform_data/dmtimer-omap.h
index a3e17945a0e9..ad247d45bc08 100644
--- a/include/linux/platform_data/dmtimer-omap.h
+++ b/include/linux/platform_data/dmtimer-omap.h
@@ -43,8 +43,12 @@ struct omap_dm_timer_ops {
 
 	int	(*set_load)(struct omap_dm_timer *timer, int autoreload,
 			    unsigned int value);
+	int	(*set_load_start)(struct omap_dm_timer *timer, int autoreload,
+				  unsigned int value);
 	int	(*set_match)(struct omap_dm_timer *timer, int enable,
 			     unsigned int match);
+	int	(*set_capture)(struct omap_dm_timer *timer, int captmode,
+			       int edges);
 	int	(*set_pwm)(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger);
 	int	(*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
@@ -52,6 +56,10 @@ struct omap_dm_timer_ops {
 	unsigned int (*read_counter)(struct omap_dm_timer *timer);
 	int	(*write_counter)(struct omap_dm_timer *timer,
 				 unsigned int value);
+
+	int	(*read_capture)(struct omap_dm_timer *timer, unsigned int *reg,
+				unsigned int *reg2);
+
 	unsigned int (*read_status)(struct omap_dm_timer *timer);
 	int	(*write_status)(struct omap_dm_timer *timer,
 				unsigned int value);
-- 
2.15.1

^ permalink raw reply related

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Andrew Lunn @ 2018-01-08 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108151453.GB31502@xora-haswell>

w> I am not familiar with MDIO, but if its similar or a specific
> implementation of a serial bus that does sound sane!

It is a two wire serial bus. A good overview can be found here:

https://www.totalphase.com/support/articles/200349206-MDIO-Background

	Andrew

^ permalink raw reply

* [PATCH v4 4/4] ARM: pinctrl: sunxi-pinctrl: fix pin funtion can not be match correctly.
From: Maxime Ripard @ 2018-01-08 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJeuY79_w+8Gv=jRxK4tajiecNSAZkMGYY_d7PJmsjyOZHPkJw@mail.gmail.com>

On Mon, Jan 08, 2018 at 07:08:53PM +0800, Hao Zhang wrote:
> 2017-12-13 23:45 GMT+08:00 Maxime Ripard <maxime.ripard@free-electrons.com>:
> > Hi,
> >
> > Thanks for your patch!
> >
> > On Wed, Dec 13, 2017 at 10:47:48PM +0800, hao_zhang wrote:
> >> Pin function can not be match correctly when SUNXI_PIN describe with
> >> mutiple variant and same function.
> >>
> >> such as:
> >> on pinctrl-sun4i-a10.c
> >>
> >> SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
> >>               SUNXI_FUNCTION(0x0, "gpio_in"),
> >>               SUNXI_FUNCTION(0x1, "gpio_out"),
> >>               SUNXI_FUNCTION_VARIANT(0x2, "pwm",    /* PWM0 */
> >>                       PINCTRL_SUN4I_A10 |
> >>                       PINCTRL_SUN7I_A20),
> >>               SUNXI_FUNCTION_VARIANT(0x3, "pwm",    /* PWM0 */
> >>                       PINCTRL_SUN8I_R40)),
> >>
> >> it would always match to the first variant function
> >> (PINCTRL_SUN4I_A10, PINCTRL_SUN7I_A20)
> >>
> >> so we should add variant compare on it.
> >>
> >> Signed-off-by: hao_zhang <hao5781286@gmail.com>
> >> ---
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++--
> >>  1 file changed, 4 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> index 4b6cb25..f23e74e 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -83,9 +83,11 @@ sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
> >>                       struct sunxi_desc_function *func = pin->functions;
> >>
> >>                       while (func->name) {
> >> -                             if (!strcmp(func->name, func_name))
> >> +                             if (!strcmp(func->name, func_name)) {
> >> +                                     if (!(func->variant) ||
> >> +                                        (func->variant & pctl->variant))
> >
> > I guess it would be better to have:
> >         if (!strcmp(func->name, func_name) &&
> >             (!func->variant || (func->variant & pctl->variant)))
> 
> It would over 80 characters, can i change it by this ?
> if (!strcmp(func->name, func_name) &&
>          (func->variant & pctl->variant ||
>           !func->variant))

It feels more natural to have !func->variant first, but feel free to
have it split that way yes.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180108/a819570d/attachment-0001.sig>

^ permalink raw reply

* [PATCH] imx6: fix pcie enumeration
From: Lorenzo Pieralisi @ 2018-01-08 15:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1684b8c6-1006-948b-f4f9-c9aaf9cf26a8@ncentric.com>

On Mon, Jan 08, 2018 at 12:13:34PM +0100, Koen Vandeputte wrote:
> 
> 
> On 2018-01-08 12:00, Lorenzo Pieralisi wrote:
> >[+cc Joao, Jingoo]
> >
> >On Mon, Jan 08, 2018 at 09:51:37AM +0100, Koen Vandeputte wrote:
> >
> >[...]
> >
> >>[ Node 4 | node-4 ] lspci -v
> >>00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00
> >>[Normal decode])
> >> ??? Flags: bus master, fast devsel, latency 0, IRQ 298
> >> ??? Memory at 01000000 (32-bit, non-prefetchable) [size=1M]
> >> ??? Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
> >                                      ^^^^^^^^^^^^^^
> >
> >So basically, the subordinate number in the root port does not
> >affect config space forwarding from what I see and it has always
> >been like that for dwc.
> >
> >You are forced to update it to 0xff because otherwise the kernel
> >stops enumerating bus numbers > 1
> Indeed, which affects all devices using Designware PCIe init + a
> PCIe bridge downstream
> >but that's a software issue
> >not HW - the subordinate bus number does not seem to affect anything
> >here.
> 
> >Sigh.
> >
> >Another option would consist in forcing the kernel to reassign
> >all bus numbers by setting the PCI_REASSIGN_ALL_BUS flag but
> >that's not a good idea given how inconsistent that flag usage is.
> >
> >I think that updating the subordinate bus numbers in the DWC
> >config register is the correct solution to make sure the kernel
> >won't get confused anymore by what seems to be a fake root port,
> >I need input from DWC maintainers to confirm my understanding.
> >
> >Thanks,
> >Lorenzo
> >
> 
> The patch I'm currently using internally:
> 
> 
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -861,7 +861,7 @@ void dw_pcie_setup_rc(struct pcie_port *
> ???? /* setup bus numbers */
> ???? val = dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS);
> ???? val &= 0xff000000;
> -??? val |= 0x00010100;
> +??? val |= 0x00ff0100;
> ???? dw_pcie_writel_rc(pp, PCI_PRIMARY_BUS, val);
> 
> ???? /* setup command register */
> 
> 
> Above version logically fixes it for all dwc devices using a bridge
> after the RC, not only imx6.
> If this is fine, I would submit the patch above and drop the current one.
It is fine by me but I won't merge it till I get ACKs and tested-by
from the respective maintainers - it can have potential widespread
impact.

> Backporting this to stable kernels (4.9 .. 4.4 .. etc) will fix all
> nasty warnings on these setups during boot without any change in
> functionality.
> These kernels will require a separate patch as this source file got
> moved & renamed.
> Thanks for your time and analysis so far,

Thank you for reporting it and fixing it.

Lorenzo

^ permalink raw reply

* [PATCH v5 3/9] drm: Add Content Protection property
From: Sean Paul @ 2018-01-08 15:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108155029.244552-1-seanpaul@chromium.org>

This patch adds a new optional connector property to allow userspace to enable
protection over the content it is displaying. This will typically be implemented
by the driver using HDCP.

The property is a tri-state with the following values:
- OFF: Self explanatory, no content protection
- DESIRED: Userspace requests that the driver enable protection
- ENABLED: Once the driver has authenticated the link, it sets this value

The driver is responsible for downgrading ENABLED to DESIRED if the link becomes
unprotected. The driver should also maintain the desiredness of protection
across hotplug/dpms/suspend.

If this looks familiar, I posted [1] this 3 years ago. We have been using this
in ChromeOS across exynos, mediatek, and rockchip over that time.

Changes in v2:
 - Pimp kerneldoc for content_protection_property (Daniel)
 - Drop sysfs attribute
Changes in v3:
 - None
Changes in v4:
- Changed kerneldoc to recommend userspace polling (Daniel)
- Changed kerneldoc to briefly describe how to attach the property (Daniel)
Changes in v5:
- checkpatch whitespace noise
- Change DRM_MODE_CONTENT_PROTECTION_OFF to DRM_MODE_CONTENT_PROTECTION_UNDESIRED

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Sean Paul <seanpaul@chromium.org>

[1] https://lists.freedesktop.org/archives/dri-devel/2014-December/073336.html
---
 drivers/gpu/drm/drm_atomic.c    |  8 +++++
 drivers/gpu/drm/drm_connector.c | 78 +++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h     | 16 +++++++++
 include/uapi/drm/drm_mode.h     |  4 +++
 4 files changed, 106 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b76d49218cf1..69ff763a834e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1224,6 +1224,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->picture_aspect_ratio = val;
 	} else if (property == connector->scaling_mode_property) {
 		state->scaling_mode = val;
+	} else if (property == connector->content_protection_property) {
+		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+			return -EINVAL;
+		}
+		state->content_protection = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
@@ -1303,6 +1309,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->picture_aspect_ratio;
 	} else if (property == connector->scaling_mode_property) {
 		*val = state->scaling_mode;
+	} else if (property == connector->content_protection_property) {
+		*val = state->content_protection;
 	} else if (connector->funcs->atomic_get_property) {
 		return connector->funcs->atomic_get_property(connector,
 				state, property, val);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 2559c615d984..b85a7749709d 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -756,6 +756,13 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
+static struct drm_prop_enum_list drm_cp_enum_list[] = {
+	{ DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
+	{ DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
+	{ DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
+};
+DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
+
 /**
  * DOC: standard connector properties
  *
@@ -826,6 +833,41 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
  * 	Indicates the output should be ignored for purposes of displaying a
  * 	standard desktop environment or console. This is most likely because
  * 	the output device is not rectilinear.
+ * Content Protection:
+ *	This property is used by userspace to request the kernel protect future
+ *	content communicated over the link. When requested, kernel will apply
+ *	the appropriate means of protection (most often HDCP), and use the
+ *	property to tell userspace the protection is active.
+ *
+ *	Drivers can set this up by calling
+ *	drm_connector_attach_content_protection_property() on initialization.
+ *
+ *	The value of this property can be one of the following:
+ *
+ *	- DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
+ *		The link is not protected, content is transmitted in the clear.
+ *	- DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
+ *		Userspace has requested content protection, but the link is not
+ *		currently protected. When in this state, kernel should enable
+ *		Content Protection as soon as possible.
+ *	- DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
+ *		Userspace has requested content protection, and the link is
+ *		protected. Only the driver can set the property to this value.
+ *		If userspace attempts to set to ENABLED, kernel will return
+ *		-EINVAL.
+ *
+ *	A few guidelines:
+ *
+ *	- DESIRED state should be preserved until userspace de-asserts it by
+ *	  setting the property to UNDESIRED. This means ENABLED should only
+ *	  transition to UNDESIRED when the user explicitly requests it.
+ *	- If the state is DESIRED, kernel should attempt to re-authenticate the
+ *	  link whenever possible. This includes across disable/enable, dpms,
+ *	  hotplug, downstream device changes, link status failures, etc..
+ *	- Userspace is responsible for polling the property to determine when
+ *	  the value transitions from ENABLED to DESIRED. This signifies the link
+ *	  is no longer protected and userspace should take appropriate action
+ *	  (whatever that might be).
  *
  * Connectors also have one standardized atomic property:
  *
@@ -1126,6 +1168,42 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
 
+/**
+ * drm_connector_attach_content_protection_property - attach content protection
+ * property
+ *
+ * @connector: connector to attach CP property on.
+ *
+ * This is used to add support for content protection on select connectors.
+ * Content Protection is intentionally vague to allow for different underlying
+ * technologies, however it is most implemented by HDCP.
+ *
+ * The content protection will be set to &drm_connector_state.content_protection
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_content_protection_property(
+		struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_property *prop;
+
+	prop = drm_property_create_enum(dev, 0, "Content Protection",
+					drm_cp_enum_list,
+					ARRAY_SIZE(drm_cp_enum_list));
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&connector->base, prop,
+				   DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
+
+	connector->content_protection_property = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
+
 /**
  * drm_mode_create_aspect_ratio_property - create aspect ratio property
  * @dev: DRM device
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ed38df4ac204..758a176e7b57 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -419,6 +419,12 @@ struct drm_connector_state {
 	 * upscaling, mostly used for built-in panels.
 	 */
 	unsigned int scaling_mode;
+
+	/**
+	 * @content_protection: Connector property to request content
+	 * protection. This is most commonly used for HDCP.
+	 */
+	unsigned int content_protection;
 };
 
 /**
@@ -766,6 +772,7 @@ struct drm_cmdline_mode {
  * @tile_h_size: horizontal size of this tile.
  * @tile_v_size: vertical size of this tile.
  * @scaling_mode_property:  Optional atomic property to control the upscaling.
+ * @content_protection_property: Optional property to control content protection
  *
  * Each connector may be connected to one or more CRTCs, or may be clonable by
  * another connector if they can share a CRTC.  Each connector also has a specific
@@ -856,6 +863,12 @@ struct drm_connector {
 
 	struct drm_property *scaling_mode_property;
 
+	/**
+	 * @content_protection_property: DRM ENUM property for content
+	 * protection
+	 */
+	struct drm_property *content_protection_property;
+
 	/**
 	 * @path_blob_ptr:
 	 *
@@ -1065,6 +1078,7 @@ const char *drm_get_dvi_i_subconnector_name(int val);
 const char *drm_get_dvi_i_select_name(int val);
 const char *drm_get_tv_subconnector_name(int val);
 const char *drm_get_tv_select_name(int val);
+const char *drm_get_content_protection_name(int val);
 
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 int drm_mode_create_tv_properties(struct drm_device *dev,
@@ -1073,6 +1087,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
 					       u32 scaling_mode_mask);
+int drm_connector_attach_content_protection_property(
+		struct drm_connector *connector);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
 int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5597a87154e5..d1a69ff24fe8 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -173,6 +173,10 @@ extern "C" {
 		DRM_MODE_REFLECT_X | \
 		DRM_MODE_REFLECT_Y)
 
+/* Content Protection Flags */
+#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED	0
+#define DRM_MODE_CONTENT_PROTECTION_DESIRED     1
+#define DRM_MODE_CONTENT_PROTECTION_ENABLED     2
 
 struct drm_mode_modeinfo {
 	__u32 clock;
-- 
2.16.0.rc0.223.g4a4ac83678-goog

^ permalink raw reply related

* [PATCH v6 13/16] arm64: acpi: Remove __init from acpi_psci_use_hvc() for use by SDEI
From: Lorenzo Pieralisi @ 2018-01-08 15:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153818.22743-14-james.morse@arm.com>

On Mon, Jan 08, 2018 at 03:38:15PM +0000, James Morse wrote:
> SDEI inherits the 'use hvc' bit that is also used by PSCI. PSCI does all
> its initialisation early, SDEI does its late.
> 
> Remove the __init annotation from acpi_psci_use_hvc().
> 
> Signed-off-by: James Morse <james.morse@arm.com>
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
> The function name is unchanged as this bit is named 'PSCI_USE_HVC'
> in table 5-37 of ACPIv6.2.
> 
>  arch/arm64/kernel/acpi.c | 2 +-
>  include/linux/psci.h     | 3 ++-
>  2 files changed, 3 insertions(+), 2 deletions(-)

Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index b3162715ed78..252396a96c78 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -117,7 +117,7 @@ bool __init acpi_psci_present(void)
>  }
>  
>  /* Whether HVC must be used instead of SMC as the PSCI conduit */
> -bool __init acpi_psci_use_hvc(void)
> +bool acpi_psci_use_hvc(void)
>  {
>  	return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
>  }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index 6306ab10af18..f724fd8c78e8 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -47,10 +47,11 @@ static inline int psci_dt_init(void) { return 0; }
>  #if defined(CONFIG_ARM_PSCI_FW) && defined(CONFIG_ACPI)
>  int __init psci_acpi_init(void);
>  bool __init acpi_psci_present(void);
> -bool __init acpi_psci_use_hvc(void);
> +bool acpi_psci_use_hvc(void);
>  #else
>  static inline int psci_acpi_init(void) { return 0; }
>  static inline bool acpi_psci_present(void) { return false; }
> +static inline bool acpi_psci_use_hvc(void) {return false; }
>  #endif
>  
>  #endif /* __LINUX_PSCI_H */
> -- 
> 2.15.0
> 

^ permalink raw reply

* [PATCH v6 08/10] pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops
From: Keerthy @ 2018-01-08 16:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <eb51e181-8203-0469-d013-dfd40f7da95d@microchip.com>



On 1/8/2018 8:17 PM, Claudiu Beznea wrote:
> 
> 
> On 08.01.2018 16:44, Neil Armstrong wrote:
>> On 08/01/2018 15:33, Keerthy wrote:
>>>
>>>
>>> On Monday 08 January 2018 02:14 PM, Claudiu Beznea wrote:
>>>>
>>>>
>>>> On 02.01.2018 12:09, Keerthy wrote:
>>>>> Adapt driver to utilize dmtimer pdata ops instead of pdata-quirks.
>>>>>
>>>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>>>> Tested-by: Ladislav Michl <ladis@linux-mips.org>
>>>>> ---
>>>>>   drivers/pwm/pwm-omap-dmtimer.c | 39 ++++++++++++++++++++++-----------------
>>>>>   1 file changed, 22 insertions(+), 17 deletions(-)
>>>>>
>>>>> diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
>>>>> index 5ad42f3..3b27aff 100644
>>>>> --- a/drivers/pwm/pwm-omap-dmtimer.c
>>>>> +++ b/drivers/pwm/pwm-omap-dmtimer.c
>>>>> @@ -23,6 +23,7 @@
>>>>>   #include <linux/mutex.h>
>>>>>   #include <linux/of.h>
>>>>>   #include <linux/of_platform.h>
>>>>> +#include <linux/platform_data/dmtimer-omap.h>
>>>>>   #include <linux/platform_data/pwm_omap_dmtimer.h>
>>>>>   #include <linux/platform_device.h>
>>>>>   #include <linux/pm_runtime.h>
>>>>> @@ -37,7 +38,7 @@ struct pwm_omap_dmtimer_chip {
>>>>>   	struct pwm_chip chip;
>>>>>   	struct mutex mutex;
>>>>>   	pwm_omap_dmtimer *dm_timer;
>>>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>>>> +	struct omap_dm_timer_ops *pdata;
>>>>>   	struct platform_device *dm_timer_pdev;
>>>>>   };
>>>>>   
>>>>> @@ -242,19 +243,33 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>>>   {
>>>>>   	struct device_node *np = pdev->dev.of_node;
>>>>>   	struct device_node *timer;
>>>>> +	struct platform_device *timer_pdev;
>>>>>   	struct pwm_omap_dmtimer_chip *omap;
>>>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>>>> +	struct dmtimer_platform_data *timer_pdata;
>>>>> +	struct omap_dm_timer_ops *pdata;
>>>>>   	pwm_omap_dmtimer *dm_timer;
>>>>>   	u32 v;
>>>>>   	int status;
>>>>>   
>>>>> -	pdata = dev_get_platdata(&pdev->dev);
>>>>> -	if (!pdata) {
>>>>> -		dev_err(&pdev->dev, "Missing dmtimer platform data\n");
>>>>> +	timer = of_parse_phandle(np, "ti,timers", 0);
>>>> of_node_put() should be called when done with device_node pointer returned
>>>> by of_parse_phandle() (you may want to check the return ERROR cases below
>>>> regarding this statement):
>>>>> +	if (!timer)
>>>>> +		return -ENODEV;
>>>>> +
>>>>> +	timer_pdev = of_find_device_by_node(timer);
>>>>> +	if (!timer_pdev) {
>>>>> +		dev_err(&pdev->dev, "Unable to find Timer pdev\n");
>>>> here
>>>>> +		return -ENODEV;
>>>>> +	}
>>>>> +
>>>>> +	timer_pdata = dev_get_platdata(&timer_pdev->dev);
>>>>> +	if (!timer_pdata) {
>>>>> +		dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
>>>> here
>>>>>   		return -EINVAL;
>>>>>   	}
>>>>>   
>>>>> -	if (!pdata->request_by_node ||
>>>>> +	pdata = timer_pdata->timer_ops;
>>>>> +
>>>>> +	if (!pdata || !pdata->request_by_node ||
>>>>>   	    !pdata->free ||
>>>>>   	    !pdata->enable ||
>>>>>   	    !pdata->disable ||
>>>>> @@ -270,10 +285,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>>>   		return -EINVAL;
>>>>>   	}
>>>>>   
>>>>> -	timer = of_parse_phandle(np, "ti,timers", 0);
>>>>> -	if (!timer)
>>>>> -		return -ENODEV;
>>>>> -
>>>>>   	if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
>>>> here
>>>>>   		dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
>>>>>   		return -ENODEV;
>>>>> @@ -291,13 +302,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>>>   
>>>>>   	omap->pdata = pdata;
>>>>>   	omap->dm_timer = dm_timer;
>>>>> -
>>>>> -	omap->dm_timer_pdev = of_find_device_by_node(timer);
>>>>> -	if (!omap->dm_timer_pdev) {
>>>>> -		dev_err(&pdev->dev, "Unable to find timer pdev\n");
>>>>> -		omap->pdata->free(dm_timer);
>>>>> -		return -EINVAL;
>>>>> -	}
>>>>> +	omap->dm_timer_pdev = timer_pdev;
>>>>>   
>>>>>   	/*
>>>>>   	 * Ensure that the timer is stopped before we allow PWM core to call
>>>>>
>>>> And all the other return instructions from probe function not listed by git diff
>>>
>>> Thanks for reviewing. I will add the of_node_put call for all the error
>>> paths.
> After that you can add: Reviwed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
>>>
>>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>
>> Apart the missing of_node_put() :
>>
>> Acked-by: Neil Armstrong <narmstrong@baylibre.com>

Thanks Neil and Claudiu.

>>

^ permalink raw reply

* [PATCH v5 07/13] KVM: arm/arm64: mask/unmask daif around VHE guests
From: James Morse @ 2018-01-08 16:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171215155101.23505-8-james.morse@arm.com>

Hi,

On 15/12/17 15:50, James Morse wrote:
> Non-VHE systems take an exception to EL2 in order to world-switch into the
> guest. When returning from the guest KVM implicitly restores the DAIF
> flags when it returns to the kernel at EL1.
> 
> With VHE none of this exception-level jumping happens, so KVMs
> world-switch code is exposed to the host kernel's DAIF values, and KVM
> spills the guest-exit DAIF values back into the host kernel.
> On entry to a guest we have Debug and SError exceptions unmasked, KVM
> has switched VBAR but isn't prepared to handle these. On guest exit
> Debug exceptions are left disabled once we return to the host and will
> stay this way until we enter user space.
> 
> Add a helper to mask/unmask DAIF around VHE guests. The unmask can only
> happen after the hosts VBAR value has been synchronised by the isb in
> __vhe_hyp_call (via kvm_call_hyp()). Masking could be as late as
> setting KVMs VBAR value, but is kept here for symmetry.
> 
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> This isn't backportable because of the 'daif' helpers, I will produce a
> backport once its merged.
> 
> Changes since v4:
>  * Added empty declarations for 32bit. (how did I miss that?)

v4 of this patch had a Reviewed-by Christoffer, which I didn't pick up as I then
went on to confuse everyone...

https://patchwork.kernel.org/patch/10017467/

(Sorry Christoffer!)


Thanks,

James

^ permalink raw reply

* [PATCH v5 13/13] KVM: arm64: Emulate RAS error registers and set HCR_EL2's TERR & TEA
From: James Morse @ 2018-01-08 16:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171215155101.23505-14-james.morse@arm.com>

Hi,

On 15/12/17 15:51, James Morse wrote:
> From: Dongjiu Geng <gengdongjiu@huawei.com>
> 
> ARMv8.2 adds a new bit HCR_EL2.TEA which routes synchronous external
> aborts to EL2, and adds a trap control bit HCR_EL2.TERR which traps
> all Non-secure EL1&0 error record accesses to EL2.
> 
> This patch enables the two bits for the guest OS, guaranteeing that
> KVM takes external aborts and traps attempts to access the physical
> error registers.
> 
> ERRIDR_EL1 advertises the number of error records, we return
> zero meaning we can treat all the other registers as RAZ/WI too.
> 
> Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
> [removed specific emulation, use trap_raz_wi() directly for everything,
>  rephrased parts of the commit message]
> Signed-off-by: James Morse <james.morse@arm.com>

v4 of this patch had a Reviewed-by Marc and Christoffer, which I didn't pick up
because I'm an idiot:

https://patchwork.kernel.org/patch/10017537/


Thanks,

James

^ permalink raw reply

* [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks
From: David Lechner @ 2018-01-08 16:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ebd677dc-44a4-5053-2509-e3ee948ccf98@ti.com>

On 01/08/2018 08:00 AM, Sekhar Nori wrote:
> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>> This adds a new binding for the PLL IP blocks in the mach-davinci family
>> of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
>> but in the future additional child nodes could be added for OBSCLK and
>> BPDIV.
>>
>> Note: Although these PLL controllers are very similar to the TI Keystone
>> SoCs, we are not re-using those bindings. The Keystone bindings use a
>> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
> 
> Not sure what is meant by "legacy one-node-per-clock binding"

It's a term I picked up from of_clk_detect_critical()

  * Do not use this function. It exists only for legacy Device Tree
  * bindings, such as the one-clock-per-node style that are outdated.
  * Those bindings typically put all clock data into .dts and the Linux
  * driver has no clock data, thus making it impossible to set this flag
  * correctly from the driver. Only those drivers may call
  * of_clk_detect_critical from their setup functions.

> 
>> have a slightly different PLL register layout and a number of quirks that
>> can't be handled by the existing bindings, so the keystone bindings could
>> not be used as-is anyway.
> 
> Right, I think different register layout between the processors is the
> main reason for a new driver. This should be sufficient reason IMO.
> 
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>>   .../devicetree/bindings/clock/ti/davinci/pll.txt   | 47 ++++++++++++++++++++++
>>   1 file changed, 47 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>> new file mode 100644
>> index 0000000..99bf5da
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>> @@ -0,0 +1,47 @@
>> +Binding for TI DaVinci PLL Controllers
>> +
>> +The PLL provides clocks to most of the components on the SoC. In addition
>> +to the PLL itself, this controller also contains bypasses, gates, dividers,
>> +an multiplexers for various clock signals.
>> +
>> +Required properties:
>> +- compatible: shall be one of:
>> +	- "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
>> +	- "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
> 
> These PLLs are same IP so they should use the same compatible. You can
> initialize both PLLs for DA850 based on the same compatible.
> 

But they are not exactly the same. For example, PLL0 has 7 PLLDIV clocks while
PLL1 only has 3. PLL0 has PREDIV while PLL1 does not. PLL0 has certain SYSCLKs
that are fixed-ratio but PLL1 does not have any of these. There are even more
differences, but these are the ones we are actually using.

So, if we use the same compatible, we either have to come up with device tree
bindings to describe all of this (yuck) or I suppose we can look at the REVID
register to electronically determine exactly what we have. I went with the
simpler option of just creating two different compatible strings.

^ permalink raw reply

* [PATCH] ARM: realview: remove eb-mp clcd IRQ
From: Robin Murphy @ 2018-01-08 16:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdbCWZB1ZkrdGe0s0GfNVWEYY+NThy4ce-+SBtU-s=WNbQ@mail.gmail.com>

Hi Linus,

On 21/12/17 22:08, Linus Walleij wrote:
> On Thu, Dec 21, 2017 at 10:31 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> 
>> We get a dtc warning about the CLCD interrupt being invalid:
>>
>> arch/arm/boot/dts/arm-realview-eb-11mp-ctrevb.dtb: Warning (interrupts_property): interrupts size is (8), expected multiple of 12 in /fpga/charlcd at 10008000
>>
>> According to the datasheet I found and the old board file, this
>> line is not connected, so I'm removing the respective properties here.
>>
>> Link: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0411d/index.html
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> 
> There is some confusion here. There is CLCD "Color LCD"
> which is just a code name for PrimeCell PL111 and there is the actual
> character LCD which is a hardware thin to talk to a character LCD with
> some characters on.
> 
>> diff --git a/arch/arm/boot/dts/arm-realview-eb-mp.dtsi b/arch/arm/boot/dts/arm-realview-eb-mp.dtsi
> 
> So this DTS is for the ARM 11 MP core tile which is described in
> DUI0318F. It doesn't even list an IRQ for the character LCD.
> 
>>   &charlcd {
>> -       interrupt-parent = <&intc>;
>> -       interrupts = <0  IRQ_TYPE_LEVEL_HIGH>;
> 
> This was probably me thinking to go back and fill in the right
> IRQ and forgetting to actually do it. Sorry :(
> 
>> +       /* CLCD is not connected here */
> 
> Call it character LCD instead to avoid confusion please.
> 
>> +       /delete-property/interrupt-parent;
>> +       /delete-property/interrupts;
> 
> I don't understand this delete-property business (first time
> I see it, but the top level
> DTSI (arm-realview-eb.dtsi) does not define any interrupt
> so can't you just delete this whole &charlcd?
> 
> I do think the reference design has a character LCD, and I
> do think it has an interrupt, it's just undocumented so
> someone with this board would have to test it manually
> to figure out which line it is. Whoever uses this design
> will get to it if ever.

FWIW the EB baseboard is *physically* the same regardless of the CPU, 
it's just flashed with a Core-Tile-specific FPGA bitstream. I've just 
tried firing up an 11MPCore one, and indeed the character LCD does light 
up with the kernel version. I can't convince the recalcitrant beast to 
actually get to userspace, though, so I can't confirm what the 
interrupt's deal is.

The baseboard manual (DUI0303E) says it's interrupt 22 on the 
board-level secondary GICs, and since neither the CT11MP nor its 
corresponding FPGA (AN152) mention any alternate routing direct to the 
Core Tile GIC, I'd guess it probably still is. On the other hand, 
though, it also says this:

   "... However this interrupt signal is reserved for future use and you
    must use a polling routine instead of an interrupt service routine."

So maybe it's appropriate to just remove the interrupt everywhere :/

Robin.

^ permalink raw reply

* [PATCH 2/2] arm64: Branch predictor hardening for Cavium ThunderX2
From: Will Deacon @ 2018-01-08 16:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515394416-166994-2-git-send-email-jnair@caviumnetworks.com>

On Sun, Jan 07, 2018 at 10:53:36PM -0800, Jayachandran C wrote:
> Use PSCI based mitigation for speculative execution attacks targeting
> the branch predictor. The approach is similar to the one used for
> Cortex-A CPUs, but in case of ThunderX2 we add another SMC call to
> test if the firmware supports the capability.
> 
> If the secure firmware has been updated with the mitigation code to
> invalidate the branch target buffer, we use the PSCI version call to
> invoke it.
> 
> Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
> ---
>  arch/arm64/kernel/cpu_errata.c | 38 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index cb0fb37..abceb5d 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -124,6 +124,7 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
>  	__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
>  }
>  
> +#include <linux/arm-smccc.h>
>  #include <linux/psci.h>
>  
>  static int enable_psci_bp_hardening(void *data)
> @@ -138,6 +139,33 @@ static int enable_psci_bp_hardening(void *data)
>  
>  	return 0;
>  }
> +
> +#define CAVIUM_TX2_SIP_SMC_CALL		0xC200FF00
> +#define CAVIUM_TX2_BTB_HARDEN_CAP	0xB0A0
> +
> +static int enable_tx2_psci_bp_hardening(void *data)
> +{
> +	const struct arm64_cpu_capabilities *entry = data;
> +	struct arm_smccc_res res;
> +
> +	if (!entry->matches(entry, SCOPE_LOCAL_CPU))
> +		return;
> +
> +	arm_smccc_smc(CAVIUM_TX2_SIP_SMC_CALL, CAVIUM_TX2_BTB_HARDEN_CAP, 0, 0, 0, 0, 0, 0, &res);

One thing to be aware of here is that if somebody configures qemu to emulate
a TX2, this may actually disappear into EL3 and not return. You're better
off sticking with PSCI GET_VERSION in terms of portability, but it's your
call -- I'd expect you to deal with any breakage reports on the list due
to the SMC above. Fair?

> +	if (res.a0 != 0) {
> +		pr_warn("Error: CONFIG_HARDEN_BRANCH_PREDICTOR enabled, but firmware does not support it\n");
> +		return 0;
> +	}

Please don't print this here; see below.

> +	if (res.a1 == 1 && psci_ops.get_version) {
> +		pr_info("CPU%d: Branch predictor hardening enabled\n", smp_processor_id());

If you want to print a message, please put it in the capability structure
.desc field.

Will

^ permalink raw reply

* [PATCH v2 1/5] pinctrl: imx: use struct imx_pinctrl_soc_info as a const
From: Gary Bisson @ 2018-01-08 16:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106142553.15322-2-stefan@agner.ch>

Hi Stefan,

On Sat, Jan 06, 2018 at 03:25:49PM +0100, Stefan Agner wrote:
> For some SoCs the struct imx_pinctrl_soc_info is passed through
> of_device_id.data which is const. Most variables are already const
> or otherwise not written. However, some fields are modified at
> runtime. Move those fields to the dynamically allocated struct
> imx_pinctrl.
> 
> Fixes: b3060044e495 ("pinctrl: freescale: imx7d: make of_device_ids const")
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com>
> Cc: Dong Aisheng <aisheng.dong@nxp.com>
> Cc: Gary Bisson <gary.bisson@boundarydevices.com>
> Signed-off-by: Stefan Agner <stefan@agner.ch>

This is actually more or less a revert of a previous commit:
b28742be4709 pinctrl: imx: remove const qualifier of imx_pinctrl_soc_info

Note that the idea for this commit was to get dt-overlays working and
able to do pinctrl changes using configfs interface to load an overlay
(using Pantelis patch). Not sure where we stand on loading such overlay
from user-space, is it still something that will happen?

Regards,
Gary

^ permalink raw reply

* [PATCH 0/3] ARM branch predictor hardening
From: Tony Lindgren @ 2018-01-08 16:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106120907.26701-1-marc.zyngier@arm.com>

* Marc Zyngier <marc.zyngier@arm.com> [180106 04:14]:
> This small series implements some basic BP hardening by invalidating
> the BTB on CPUs that are known to be susceptible to aliasing attacks.
> 
> These patches are closely modelled against what we do on arm64,
> although simpler as we can rely on an architected instruction to
> perform the invalidation.
> 
> The first patch reuses the Cortex-A8 BTB invalidation in switch_mm and
> generalises it to be used on all affected CPUs. The second perform the
> same invalidation on fatal signal delivery. The last one nukes it on
> guest exit, and results in some major surgery (kudos to Dimitris
> Papastamos who came up with the magic vector decoding sequence).

So if a Cortex-A8 has bootloder set the IBE bit, and kernel has
ARM_ERRATA_430973 enabled, is Cortex-A8 already hardened then?

Regards,

Tony

^ permalink raw reply

* [RFC] ARM: dts: sama5d2: qspi DMA fixes spi DMA
From: Nicolas Ferre @ 2018-01-08 16:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1514317960-27094-1-git-send-email-aford173@gmail.com>

On 26/12/2017 at 20:52, Adam Ford wrote:
> For some reason without this patch, using SPI0 with DMA yields the
> following message:
> 
> atmel_spi f8000000.spi: DMA TX channel not available, SPI unable to use DMA
> 
> With the patch, trying to use SPI0 yields the following:
> 
> atmel_spi f8000000.spi: Using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers

It seems related to SPI interface, handled by drivers/spi/spi-atmel.c
driver. DMA properties are already set for this driver.

> The QSPI driver doesn't appear to me to be using the DMA but the
> datasheet seems indicate the DMA is supported.  I am not sure why patch would
> fix the errors, so I'm posting it as RFC.

QSPI is a totally different IP and so driver:
drivers/mtd/spi-nor/atmel-quadspi.c

Actually what you modify hereunder is the QSPI DT and the DMA is
disabled for it because we miss a way to make sure that the buffer we
are handling are DMA capable (continuous for instance).

The support for a way to handle this is being discussed right now (by
Cyrille in copy). Once settled, we will be able to use DMA with QSPI in
this driver. DT binding is not determined yet BTW.

For now, your patch is not usable.

Thanks, best regards.
  Nicolas

> Signed-off-by: Adam Ford <aford173@gmail.com>
> 
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 61f68e5..fd55e91 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -999,6 +999,13 @@
>  				reg = <0xf0020000 0x100>, <0xd0000000 0x08000000>;
>  				reg-names = "qspi_base", "qspi_mmap";
>  				interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>;
> +				dmas = <&dma0
> +					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
> +					 AT91_XDMAC_DT_PERID(4))>,
> +				       <&dma0
> +					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
> +					 AT91_XDMAC_DT_PERID(5))>;
> +				dma-names = "tx", "rx";
>  				clocks = <&qspi0_clk>;
>  				#address-cells = <1>;
>  				#size-cells = <0>;
> @@ -1010,6 +1017,13 @@
>  				reg = <0xf0024000 0x100>, <0xd8000000 0x08000000>;
>  				reg-names = "qspi_base", "qspi_mmap";
>  				interrupts = <53 IRQ_TYPE_LEVEL_HIGH 7>;
> +				dmas = <&dma1
> +					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
> +					 AT91_XDMAC_DT_PERID(48))>,
> +				       <&dma0
> +					(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
> +					 AT91_XDMAC_DT_PERID(49))>;
> +				dma-names = "tx", "rx";
>  				clocks = <&qspi1_clk>;
>  				#address-cells = <1>;
>  				#size-cells = <0>;
> 


-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH 0/3] ARM branch predictor hardening
From: Marc Zyngier @ 2018-01-08 17:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108165425.GR3875@atomide.com>

Hi Tony,

On 08/01/18 16:54, Tony Lindgren wrote:
> * Marc Zyngier <marc.zyngier@arm.com> [180106 04:14]:
>> This small series implements some basic BP hardening by invalidating
>> the BTB on CPUs that are known to be susceptible to aliasing attacks.
>>
>> These patches are closely modelled against what we do on arm64,
>> although simpler as we can rely on an architected instruction to
>> perform the invalidation.
>>
>> The first patch reuses the Cortex-A8 BTB invalidation in switch_mm and
>> generalises it to be used on all affected CPUs. The second perform the
>> same invalidation on fatal signal delivery. The last one nukes it on
>> guest exit, and results in some major surgery (kudos to Dimitris
>> Papastamos who came up with the magic vector decoding sequence).
> 
> So if a Cortex-A8 has bootloder set the IBE bit, and kernel has
> ARM_ERRATA_430973 enabled, is Cortex-A8 already hardened then?

Almost. See the extra BTB invalidation in fault.c.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [v2,03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Will Deacon @ 2018-01-08 17:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108072253.GA178830@jc-sabre>

On Sun, Jan 07, 2018 at 11:24:02PM -0800, Jayachandran C wrote:
> On Fri, Jan 05, 2018 at 01:12:33PM +0000, Will Deacon wrote:
> > For non-KASLR kernels where the KPTI behaviour has not been overridden
> > on the command line we can use ID_AA64PFR0_EL1.CSV3 to determine whether
> > or not we should unmap the kernel whilst running at EL0.
> > 
> > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> > Signed-off-by: Will Deacon <will.deacon@arm.com>
> > ---
> >  arch/arm64/include/asm/sysreg.h | 1 +
> >  arch/arm64/kernel/cpufeature.c  | 8 +++++++-
> >  2 files changed, 8 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> > index 08cc88574659..ae519bbd3f9e 100644
> > --- a/arch/arm64/include/asm/sysreg.h
> > +++ b/arch/arm64/include/asm/sysreg.h
> > @@ -437,6 +437,7 @@
> >  #define ID_AA64ISAR1_DPB_SHIFT		0
> >  
> >  /* id_aa64pfr0 */
> > +#define ID_AA64PFR0_CSV3_SHIFT		60
> >  #define ID_AA64PFR0_SVE_SHIFT		32
> >  #define ID_AA64PFR0_GIC_SHIFT		24
> >  #define ID_AA64PFR0_ASIMD_SHIFT		20
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index 9f0545dfe497..d723fc071f39 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -145,6 +145,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
> >  };
> >  
> >  static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
> > +	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
> >  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
> >  	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
> >  	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
> > @@ -851,6 +852,8 @@ static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
> >  static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> >  				int __unused)
> >  {
> > +	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
> > +
> >  	/* Forced on command line? */
> >  	if (__kpti_forced) {
> >  		pr_info_once("kernel page table isolation forced %s by command line option\n",
> > @@ -862,7 +865,9 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> >  	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
> >  		return true;
> >  
> > -	return false;
> > +	/* Defer to CPU feature registers */
> > +	return !cpuid_feature_extract_unsigned_field(pfr0,
> > +						     ID_AA64PFR0_CSV3_SHIFT);
> 
> If I read this correctly, this enables KPTI on all processors without the CSV3
> set (which seems to be a future capability).
> 
> Turning on KPTI has a small but significant overhead, so I think we should turn
> it off on processors that are not vulnerable to CVE-2017-5754. Can we add something
> like  this:
> 
> --->8
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 19ed09b..202b037 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -862,6 +862,13 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>                 return __kpti_forced > 0;
>         }
>  
> +       /* Don't force KPTI for CPUs that are not vulnerable */
> +       switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
> +               case MIDR_CAVIUM_THUNDERX2:
> +               case MIDR_BRCM_VULCAN:
> +                       return false;
> +       }
> +

KASLR aside (I agree with Marc on that), I did consider an MIDR whitelist,
but it gets nasty for big.LITTLE systems if maxcpus= is used and we see a
non-whitelisted CPU after we've booted. At this point, we can't actually
bring the thing online.

You could make the argument that if you're passing maxcpus= then you can just
easily pass kpti= as well, but I wasn't sure.

Will

^ permalink raw reply

* [PATCH v2 1/4] dmaengine: xilinx_dma: populate dma caps properly
From: Vinod Koul @ 2018-01-08 17:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CY1PR02MB1692EB7A4E66BA30A8E0DB45DC130@CY1PR02MB1692.namprd02.prod.outlook.com>

On Mon, Jan 08, 2018 at 10:52:01AM +0000, Appana Durga Kedareswara Rao wrote:
> Hi Vinod,
> 
> 	Thanks for the review.... 
> <Snip>
> >> @@ -2398,6 +2398,7 @@ static int xilinx_dma_chan_probe(struct
> >xilinx_dma_device *xdev,
> >>  		chan->direction = DMA_MEM_TO_DEV;
> >>  		chan->id = chan_id;
> >>  		chan->tdest = chan_id;
> >> +		xdev->common.directions = BIT(DMA_MEM_TO_DEV);
> >>
> >>  		chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
> >>  		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) { @@ -
> >2415,6
> >> +2416,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
> >>  		chan->direction = DMA_DEV_TO_MEM;
> >>  		chan->id = chan_id;
> >>  		chan->tdest = chan_id - xdev->nr_channels;
> >> +		xdev->common.directions |= BIT(DMA_DEV_TO_MEM);
> >>
> >>  		chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
> >>  		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) { @@ -
> >2629,6
> >> +2631,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
> >>  		dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
> >>  	}
> >>
> >> +	xdev->common.dst_addr_widths = BIT(addr_width / 8);
> >> +	xdev->common.src_addr_widths = BIT(addr_width / 8);
> >
> >Do you not support trf of 1byte, 2 bytes, or 4 bytes wide transfers? What is value
> >of addr_width here typically? Usually controllers can support different widths and
> >this is a surprise that you support only one value
> 
> Controller supports address width of 32 and 64.

Then this should have both 32 and 64 values here

> addr_width typical values are 32-bit or 64-bit .
> Here addr_width is device-tree parameter...
> my understanding of src_addr_widths/dst_addr_widths is, it is a bit mask of the 
> address with in bytes that DMA supports, please correct if my understanding is wrong.
> 
> Regards,
> Kedar.
> 
> >
> >--
> >~Vinod

-- 
~Vinod

^ permalink raw reply

* [PATCH] arm64: Implement branch predictor hardening for Falkor
From: Will Deacon @ 2018-01-08 17:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515184139-23743-1-git-send-email-shankerd@codeaurora.org>

On Fri, Jan 05, 2018 at 02:28:59PM -0600, Shanker Donthineni wrote:
> Falkor is susceptible to branch predictor aliasing and can
> theoretically be attacked by malicious code. This patch
> implements a mitigation for these attacks, preventing any
> malicious entries from affecting other victim contexts.

Thanks, Shanker. I'll pick this up (fixing the typo pointed out by Drew).
One comment below.

> Signed-off-by: Shanker Donthineni <shankerd@codeaurora.org>
> ---
>  This patch has been verified using tip of
>    https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=kpti
>         and
>    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/arm64?h=v4.15-rc6&id=c622cc013cece073722592cff1ac6643a33b1622
> 
>  arch/arm64/include/asm/cpucaps.h |  3 ++-
>  arch/arm64/include/asm/kvm_asm.h |  2 ++
>  arch/arm64/kernel/bpi.S          |  8 +++++++
>  arch/arm64/kernel/cpu_errata.c   | 49 ++++++++++++++++++++++++++++++++++++++--
>  arch/arm64/kvm/hyp/entry.S       | 12 ++++++++++
>  arch/arm64/kvm/hyp/switch.c      | 10 ++++++++
>  6 files changed, 81 insertions(+), 3 deletions(-)

[...]

> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> index 12ee62d..9c45c6a 100644
> --- a/arch/arm64/kvm/hyp/entry.S
> +++ b/arch/arm64/kvm/hyp/entry.S
> @@ -196,3 +196,15 @@ alternative_endif
>  
>  	eret
>  ENDPROC(__fpsimd_guest_restore)
> +
> +ENTRY(__qcom_hyp_sanitize_btac_predictors)
> +	/**
> +	 * Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700)
> +	 * 0xC2000000-0xC200FFFF: assigned to SiP Service Calls
> +	 * b15-b0: contains SiP functionID
> +	 */
> +	movz    x0, #0x1700
> +	movk    x0, #0xc200, lsl #16
> +	smc     #0
> +	ret

As I mentioned to Jayachandran for the Cavium patches [1], using an
unallocated SMC number like this may cause a problem for some platforms,
such as qemu. Using the PSCI GET_VERSION call avoids this issue, so I'm
relying on you to handle any breakage reports that arise from this change
then.

FWIW: we're currently looking into extending PSCI/SMCCC so that a
standardised mechanism can be implemented without the overhead of the
current register stacking requirements.

Cheers,

Will

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-January/552511.html

^ permalink raw reply

* [PATCH net-next v5 2/2] net: thunderx: add timestamping support
From: Aleksey Makarov @ 2018-01-08 17:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171211233220.d72rys7nci4lqqd5@localhost>



On 12.12.2017 05:32, Richard Cochran wrote:
> On Mon, Dec 11, 2017 at 05:14:31PM +0300, Aleksey Makarov wrote:
>> diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
>> index 4a02e618e318..204b234beb9d 100644
>> --- a/drivers/net/ethernet/cavium/thunder/nic.h
>> +++ b/drivers/net/ethernet/cavium/thunder/nic.h
>> @@ -263,6 +263,8 @@ struct nicvf_drv_stats {
>>  	struct u64_stats_sync   syncp;
>>  };
>>  
>> +struct cavium_ptp;
>> +
>>  struct nicvf {
>>  	struct nicvf		*pnicvf;
>>  	struct net_device	*netdev;
>> @@ -312,6 +314,12 @@ struct nicvf {
>>  	struct tasklet_struct	qs_err_task;
>>  	struct work_struct	reset_task;
>>  
>> +	/* PTP timestamp */
>> +	struct cavium_ptp	*ptp_clock;
>> +	bool			hw_rx_tstamp;
>> +	struct sk_buff		*ptp_skb;
>> +	atomic_t		tx_ptp_skbs;
> 
> It is disturbing that the above two fields are set in different
> places.  Shouldn't they be unified into one logical lock?

No, they should not as they are not quite related.

`tx_ptp_skbs` is set when the hardware is sending a packet that requires
timestamping.  Cavium hardware can not process more than one
such packet at once so this is set each time the driver submits
a packet that requires timestamping to the send queue and clears
each time it receives the entry on the completion queue saying
that such packet was sent.

So `tx_ptp_skbs` prevents driver from submitting more than one
packet that requires timestamping to the hardware for transmitting.

When that packet is sent, hardware inserts two entries to
the completion queue.  First is the regular CQE_TYPE_SEND entry
that signals that the packet was sent.  The second is CQE_TYPE_SEND_PTP
that contains the actual timestamp for that packet.

`ptp_skb` is initialized in the handler for the CQE_TYPE_SEND
entry and is used and zeroed in the handler for the CQE_TYPE_SEND_PTP
entry.

So `ptp_skb` is used to hold the pointer to the packet between
the calls to CQE_TYPE_SEND and CQE_TYPE_SEND_PTP handlers.

I am going to add those comments to the sources, fix other issues and
send v6 in short time.

Thank you
Aleksey Makarov

> Here you clear them together:
> 
>> +static void nicvf_snd_ptp_handler(struct net_device *netdev,
>> +				  struct cqe_send_t *cqe_tx)
>> +{
>> +	struct nicvf *nic = netdev_priv(netdev);
>> +	struct skb_shared_hwtstamps ts;
>> +	u64 ns;
>> +
>> +	nic = nic->pnicvf;
>> +
>> +	/* Sync for 'ptp_skb' */
>> +	smp_rmb();
>> +
>> +	/* New timestamp request can be queued now */
>> +	atomic_set(&nic->tx_ptp_skbs, 0);
>> +
>> +	/* Check for timestamp requested skb */
>> +	if (!nic->ptp_skb)
>> +		return;
>> +
>> +	/* Check if timestamping is timedout, which is set to 10us */
>> +	if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
>> +	    cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
>> +		goto no_tstamp;
>> +
>> +	/* Get the timestamp */
>> +	memset(&ts, 0, sizeof(ts));
>> +	ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
>> +	ts.hwtstamp = ns_to_ktime(ns);
>> +	skb_tstamp_tx(nic->ptp_skb, &ts);
>> +
>> +no_tstamp:
>> +	/* Free the original skb */
>> +	dev_kfree_skb_any(nic->ptp_skb);
>> +	nic->ptp_skb = NULL;
>> +	/* Sync 'ptp_skb' */
>> +	smp_wmb();
>> +}
>> +
> 
> but here you set the one:
> 
>> @@ -657,7 +697,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
>>  		prefetch(skb);
>>  		(*tx_pkts)++;
>>  		*tx_bytes += skb->len;
>> -		napi_consume_skb(skb, budget);
>> +		/* If timestamp is requested for this skb, don't free it */
>> +		if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
>> +		    !nic->pnicvf->ptp_skb)
>> +			nic->pnicvf->ptp_skb = skb;
>> +		else
>> +			napi_consume_skb(skb, budget);
>>  		sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
>>  	} else {
>>  		/* In case of SW TSO on 88xx, only last segment will have
> 
> here you clear one:
> 
>> @@ -1319,12 +1382,28 @@ int nicvf_stop(struct net_device *netdev)
>>  
>>  	nicvf_free_cq_poll(nic);
>>  
>> +	/* Free any pending SKB saved to receive timestamp */
>> +	if (nic->ptp_skb) {
>> +		dev_kfree_skb_any(nic->ptp_skb);
>> +		nic->ptp_skb = NULL;
>> +	}
>> +
>>  	/* Clear multiqset info */
>>  	nic->pnicvf = nic;
>>  
>>  	return 0;
>>  }
> 
> here you clear both:
> 
>> @@ -1394,6 +1473,12 @@ int nicvf_open(struct net_device *netdev)
>>  	if (nic->sqs_mode)
>>  		nicvf_get_primary_vf_struct(nic);
>>  
>> +	/* Configure PTP timestamp */
>> +	if (nic->ptp_clock)
>> +		nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
>> +	atomic_set(&nic->tx_ptp_skbs, 0);
>> +	nic->ptp_skb = NULL;
>> +
>>  	/* Configure receive side scaling and MTU */
>>  	if (!nic->sqs_mode) {
>>  		nicvf_rss_init(nic);
> 
> here you set the other:
> 
>> @@ -1385,6 +1388,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
>>  		hdr->inner_l3_offset = skb_network_offset(skb) - 2;
>>  		this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
>>  	}
>> +
>> +	/* Check if timestamp is requested */
>> +	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
>> +		skb_tx_timestamp(skb);
>> +		return;
>> +	}
>> +
>> +	/* Tx timestamping not supported along with TSO, so ignore request */
>> +	if (skb_shinfo(skb)->gso_size)
>> +		return;
>> +
>> +	/* HW supports only a single outstanding packet to timestamp */
>> +	if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
>> +		return;
>> +
>> +	/* Mark the SKB for later reference */
>> +	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
>> +
>> +	/* Finally enable timestamp generation
>> +	 * Since 'post_cqe' is also set, two CQEs will be posted
>> +	 * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
>> +	 */
>> +	hdr->tstmp = 1;
>>  }
> 
> and so it is completely non-obvious whether this is race free or not.
> 
> Thanks,
> Richard
> 

^ permalink raw reply

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Marcin Wojtas @ 2018-01-08 17:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108154243.GA30962@lunn.ch>

Hi Andrew,



2018-01-08 16:42 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
> w> I am not familiar with MDIO, but if its similar or a specific
>> implementation of a serial bus that does sound sane!
>

Thanks for digging, I will check if and how we can use
GenericSerialBus with MDIO.

Best regards,
Marcin

> It is a two wire serial bus. A good overview can be found here:
>
> https://www.totalphase.com/support/articles/200349206-MDIO-Background
>

^ permalink raw reply

* [PATCH 2/2] arm64: Branch predictor hardening for Cavium ThunderX2
From: Jayachandran C @ 2018-01-08 17:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108164651.GQ25869@arm.com>

On Mon, Jan 08, 2018 at 04:46:52PM +0000, Will Deacon wrote:
> On Sun, Jan 07, 2018 at 10:53:36PM -0800, Jayachandran C wrote:
> > Use PSCI based mitigation for speculative execution attacks targeting
> > the branch predictor. The approach is similar to the one used for
> > Cortex-A CPUs, but in case of ThunderX2 we add another SMC call to
> > test if the firmware supports the capability.
> > 
> > If the secure firmware has been updated with the mitigation code to
> > invalidate the branch target buffer, we use the PSCI version call to
> > invoke it.
> > 
> > Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
> > ---
> >  arch/arm64/kernel/cpu_errata.c | 38 ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 38 insertions(+)
> > 
> > diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> > index cb0fb37..abceb5d 100644
> > --- a/arch/arm64/kernel/cpu_errata.c
> > +++ b/arch/arm64/kernel/cpu_errata.c
> > @@ -124,6 +124,7 @@ static void  install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
> >  	__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
> >  }
> >  
> > +#include <linux/arm-smccc.h>
> >  #include <linux/psci.h>
> >  
> >  static int enable_psci_bp_hardening(void *data)
> > @@ -138,6 +139,33 @@ static int enable_psci_bp_hardening(void *data)
> >  
> >  	return 0;
> >  }
> > +
> > +#define CAVIUM_TX2_SIP_SMC_CALL		0xC200FF00
> > +#define CAVIUM_TX2_BTB_HARDEN_CAP	0xB0A0
> > +
> > +static int enable_tx2_psci_bp_hardening(void *data)
> > +{
> > +	const struct arm64_cpu_capabilities *entry = data;
> > +	struct arm_smccc_res res;
> > +
> > +	if (!entry->matches(entry, SCOPE_LOCAL_CPU))
> > +		return;
> > +
> > +	arm_smccc_smc(CAVIUM_TX2_SIP_SMC_CALL, CAVIUM_TX2_BTB_HARDEN_CAP, 0, 0, 0, 0, 0, 0, &res);
> 
> One thing to be aware of here is that if somebody configures qemu to emulate
> a TX2, this may actually disappear into EL3 and not return. You're better
> off sticking with PSCI GET_VERSION in terms of portability, but it's your
> call -- I'd expect you to deal with any breakage reports on the list due
> to the SMC above. Fair?

I don't like having a custom SMC here either. But Overloading PSCI get version
is the problem as I wrote earlier - there is no way to check if the firmware
implements BTB hardening with overloading. There is a good chance that users
with old firmware will just fail without any warning.

Is there a reason for overloading PSCI get version? Allocating a new standard
SMC number would make checking for existance and usage much simpler.

I did not quite understand the possible issue in qemu, unimplemented SMC calls
are expected to return an error code. What am I missing here?

> 
> > +	if (res.a0 != 0) {
> > +		pr_warn("Error: CONFIG_HARDEN_BRANCH_PREDICTOR enabled, but firmware does not support it\n");
> > +		return 0;
> > +	}
> 
> Please don't print this here; see below.
> 
> > +	if (res.a1 == 1 && psci_ops.get_version) {
> > +		pr_info("CPU%d: Branch predictor hardening enabled\n", smp_processor_id());
> 
> If you want to print a message, please put it in the capability structure
> .desc field.

Thanks, will fix this in the next rev.

JC.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox